GNU Radio Manual and C++ API Reference 3.10.5.1
The Free & Open Software Radio Ecosystem
control_loop.h
Go to the documentation of this file.
1/* -*- c++ -*- */
2/*
3 * Copyright 2011,2013 Free Software Foundation, Inc.
4 *
5 * This file is part of GNU Radio
6 *
7 * SPDX-License-Identifier: GPL-3.0-or-later
8 *
9 */
10
11#ifndef GR_BLOCKS_CONTROL_LOOP
12#define GR_BLOCKS_CONTROL_LOOP
13
14#include <gnuradio/blocks/api.h>
15#include <gnuradio/math.h>
16
17namespace gr {
18namespace blocks {
19
20/*!
21 * \brief A second-order control loop implementation class.
22 *
23 * \details
24 * This class implements a second order control loop and is
25 * intended to act as a parent class to blocks which need a control
26 * loop (e.g., gr::digital::costas_loop_cc,
27 * gr::analog::pll_refout_cc, etc.). It takes in a loop bandwidth
28 * as well as a max and min frequency and provides the functions
29 * that control the update of the loop.
30 *
31 * The loop works of alpha and beta gains. These gains are
32 * calculated using the input loop bandwidth and a pre-set damping
33 * factor. The damping factor can be changed using the
34 * #set_damping_factor after the block is
35 * constructed. The alpha and beta values can be set using their
36 * respective #set_alpha or #set_beta functions if very precise
37 * control over these is required.
38 *
39 * The class tracks both phase and frequency of a signal based on
40 * an error signal. The error calculation is unique for each
41 * algorithm and is calculated externally and passed to the
42 * advance_loop function, which uses this to update its phase and
43 * frequency estimates.
44 *
45 * This class also provides the functions #phase_wrap and
46 * #frequency_limit to easily keep the phase and frequency
47 * estimates within our set bounds (phase_wrap keeps it within
48 * +/-2pi).
49 */
51{
52protected:
53 float d_phase, d_freq;
54 float d_max_freq, d_min_freq;
55 float d_damping, d_loop_bw;
56 float d_alpha, d_beta;
57
58public:
59 control_loop(void) {}
60 control_loop(float loop_bw, float max_freq, float min_freq);
61 virtual ~control_loop();
62
63 /*! \brief Update the system gains from the loop bandwidth and damping factor.
64 *
65 * \details
66 * This function updates the system gains based on the loop
67 * bandwidth and damping factor of the system. These two
68 * factors can be set separately through their own set
69 * functions.
70 */
72
73 /*! \brief Advance the control loop based on the current gain
74 * settings and the inputted error signal.
75 */
76 void advance_loop(float error)
77 {
78 d_freq = d_freq + d_beta * error;
79 d_phase = d_phase + d_freq + d_alpha * error;
80 }
81
82 /*! \brief Keep the phase between -2pi and 2pi.
83 *
84 * \details
85 * This function keeps the phase between -2pi and 2pi. If the
86 * phase is greater than 2pi by d, it wraps around to be -2pi+d;
87 * similarly if it is less than -2pi by d, it wraps around to
88 * 2pi-d.
89 *
90 * This function should be called after advance_loop to keep the
91 * phase in a good operating region. It is set as a separate
92 * method in case another way is desired as this is fairly
93 * heavy-handed.
94 */
96 {
97 while (d_phase > (2 * GR_M_PI))
98 d_phase -= 2 * GR_M_PI;
99 while (d_phase < (-2 * GR_M_PI))
100 d_phase += 2 * GR_M_PI;
101 }
102
103 /*! \brief Keep the frequency between d_min_freq and d_max_freq.
104 *
105 * \details
106 * This function keeps the frequency between d_min_freq and
107 * d_max_freq. If the frequency is greater than d_max_freq, it
108 * is set to d_max_freq. If the frequency is less than
109 * d_min_freq, it is set to d_min_freq.
110 *
111 * This function should be called after advance_loop to keep the
112 * frequency in the specified region. It is set as a separate
113 * method in case another way is desired as this is fairly
114 * heavy-handed.
115 */
117 {
118 if (d_freq > d_max_freq)
119 d_freq = d_max_freq;
120 else if (d_freq < d_min_freq)
121 d_freq = d_min_freq;
122 }
123
124
125 /*******************************************************************
126 * SET FUNCTIONS
127 *******************************************************************/
128
129 /*!
130 * \brief Set the loop bandwidth.
131 *
132 * \details
133 * Set the loop filter's bandwidth to \p bw. This should be
134 * between 2*pi/200 and 2*pi/100 (in rads/samp). It must also be
135 * a positive number.
136 *
137 * When a new damping factor is set, the gains, alpha and beta,
138 * of the loop are recalculated by a call to update_gains().
139 *
140 * \param bw (float) new bandwidth
141 */
142 virtual void set_loop_bandwidth(float bw);
143
144 /*!
145 * \brief Set the loop damping factor.
146 *
147 * \details
148 * Set the loop filter's damping factor to \p df. The damping
149 * factor should be sqrt(2)/2.0 for critically damped systems.
150 * Set it to anything else only if you know what you are
151 * doing. It must be a number between 0 and 1.
152 *
153 * When a new damping factor is set, the gains, alpha and beta,
154 * of the loop are recalculated by a call to update_gains().
155 *
156 * \param df (float) new damping factor
157 */
158 void set_damping_factor(float df);
159
160 /*!
161 * \brief Set the loop gain alpha.
162 *
163 * \details
164 * Sets the loop filter's alpha gain parameter.
165 *
166 * This value should really only be set by adjusting the loop
167 * bandwidth and damping factor.
168 *
169 * \param alpha (float) new alpha gain
170 */
171 void set_alpha(float alpha);
172
173 /*!
174 * \brief Set the loop gain beta.
175 *
176 * \details
177 * Sets the loop filter's beta gain parameter.
178 *
179 * This value should really only be set by adjusting the loop
180 * bandwidth and damping factor.
181 *
182 * \param beta (float) new beta gain
183 */
184 void set_beta(float beta);
185
186 /*!
187 * \brief Set the control loop's frequency.
188 *
189 * \details
190 * Sets the control loop's frequency. While this is normally
191 * updated by the inner loop of the algorithm, it could be
192 * useful to manually initialize, set, or reset this under
193 * certain circumstances.
194 *
195 * \param freq (float) new frequency
196 */
197 void set_frequency(float freq);
198
199 /*!
200 * \brief Set the control loop's phase.
201 *
202 * \details
203 * Sets the control loop's phase. While this is normally
204 * updated by the inner loop of the algorithm, it could be
205 * useful to manually initialize, set, or reset this under
206 * certain circumstances.
207 *
208 * \param phase (float) new phase
209 */
210 void set_phase(float phase);
211
212 /*!
213 * \brief Set the control loop's maximum frequency.
214 *
215 * \details
216 * Set the maximum frequency the control loop can track.
217 *
218 * \param freq (float) new max frequency
219 */
220 void set_max_freq(float freq);
221
222 /*!
223 * \brief Set the control loop's minimum frequency.
224 *
225 * \details
226 * Set the minimum frequency the control loop can track.
227 *
228 * \param freq (float) new min frequency
229 */
230 void set_min_freq(float freq);
231
232 /*******************************************************************
233 * GET FUNCTIONS
234 *******************************************************************/
235
236 /*!
237 * \brief Returns the loop bandwidth.
238 */
239 float get_loop_bandwidth() const;
240
241 /*!
242 * \brief Returns the loop damping factor.
243 */
244 float get_damping_factor() const;
245
246 /*!
247 * \brief Returns the loop gain alpha.
248 */
249 float get_alpha() const;
250
251 /*!
252 * \brief Returns the loop gain beta.
253 */
254 float get_beta() const;
255
256 /*!
257 * \brief Get the control loop's frequency estimate.
258 */
259 float get_frequency() const;
260
261 /*!
262 * \brief Get the control loop's phase estimate.
263 */
264 float get_phase() const;
265
266 /*!
267 * \brief Get the control loop's maximum frequency.
268 */
269 float get_max_freq() const;
270
271 /*!
272 * \brief Get the control loop's minimum frequency.
273 */
274 float get_min_freq() const;
275};
276
277// This is a table of tanh(x) for x in [-2, 2] used in tanh_lut.
278static float tanh_lut_table[256] = {
279 -0.96402758, -0.96290241, -0.96174273, -0.96054753, -0.95931576, -0.95804636,
280 -0.95673822, -0.95539023, -0.95400122, -0.95257001, -0.95109539, -0.9495761,
281 -0.94801087, -0.94639839, -0.94473732, -0.94302627, -0.94126385, -0.93944862,
282 -0.93757908, -0.93565374, -0.93367104, -0.93162941, -0.92952723, -0.92736284,
283 -0.92513456, -0.92284066, -0.92047938, -0.91804891, -0.91554743, -0.91297305,
284 -0.91032388, -0.90759795, -0.9047933, -0.90190789, -0.89893968, -0.89588656,
285 -0.89274642, -0.88951709, -0.88619637, -0.88278203, -0.87927182, -0.87566342,
286 -0.87195453, -0.86814278, -0.86422579, -0.86020115, -0.85606642, -0.85181914,
287 -0.84745683, -0.84297699, -0.83837709, -0.83365461, -0.82880699, -0.82383167,
288 -0.81872609, -0.81348767, -0.80811385, -0.80260204, -0.7969497, -0.79115425,
289 -0.78521317, -0.77912392, -0.772884, -0.76649093, -0.75994227, -0.75323562,
290 -0.74636859, -0.73933889, -0.73214422, -0.7247824, -0.71725127, -0.70954876,
291 -0.70167287, -0.6936217, -0.68539341, -0.67698629, -0.66839871, -0.65962916,
292 -0.65067625, -0.64153871, -0.6322154, -0.62270534, -0.61300768, -0.60312171,
293 -0.59304692, -0.58278295, -0.57232959, -0.56168685, -0.55085493, -0.53983419,
294 -0.52862523, -0.51722883, -0.50564601, -0.49387799, -0.48192623, -0.46979241,
295 -0.45747844, -0.44498647, -0.4323189, -0.41947836, -0.40646773, -0.39329014,
296 -0.37994896, -0.36644782, -0.35279057, -0.33898135, -0.32502449, -0.31092459,
297 -0.2966865, -0.28231527, -0.26781621, -0.25319481, -0.23845682, -0.22360817,
298 -0.208655, -0.19360362, -0.17846056, -0.16323249, -0.14792623, -0.13254879,
299 -0.11710727, -0.10160892, -0.08606109, -0.07047123, -0.05484686, -0.0391956,
300 -0.02352507, -0.00784298, 0.00784298, 0.02352507, 0.0391956, 0.05484686,
301 0.07047123, 0.08606109, 0.10160892, 0.11710727, 0.13254879, 0.14792623,
302 0.16323249, 0.17846056, 0.19360362, 0.208655, 0.22360817, 0.23845682,
303 0.25319481, 0.26781621, 0.28231527, 0.2966865, 0.31092459, 0.32502449,
304 0.33898135, 0.35279057, 0.36644782, 0.37994896, 0.39329014, 0.40646773,
305 0.41947836, 0.4323189, 0.44498647, 0.45747844, 0.46979241, 0.48192623,
306 0.49387799, 0.50564601, 0.51722883, 0.52862523, 0.53983419, 0.55085493,
307 0.56168685, 0.57232959, 0.58278295, 0.59304692, 0.60312171, 0.61300768,
308 0.62270534, 0.6322154, 0.64153871, 0.65067625, 0.65962916, 0.66839871,
309 0.67698629, 0.68539341, 0.6936217, 0.70167287, 0.70954876, 0.71725127,
310 0.7247824, 0.73214422, 0.73933889, 0.74636859, 0.75323562, 0.75994227,
311 0.76649093, 0.772884, 0.77912392, 0.78521317, 0.79115425, 0.7969497,
312 0.80260204, 0.80811385, 0.81348767, 0.81872609, 0.82383167, 0.82880699,
313 0.83365461, 0.83837709, 0.84297699, 0.84745683, 0.85181914, 0.85606642,
314 0.86020115, 0.86422579, 0.86814278, 0.87195453, 0.87566342, 0.87927182,
315 0.88278203, 0.88619637, 0.88951709, 0.89274642, 0.89588656, 0.89893968,
316 0.90190789, 0.9047933, 0.90759795, 0.91032388, 0.91297305, 0.91554743,
317 0.91804891, 0.92047938, 0.92284066, 0.92513456, 0.92736284, 0.92952723,
318 0.93162941, 0.93367104, 0.93565374, 0.93757908, 0.93944862, 0.94126385,
319 0.94302627, 0.94473732, 0.94639839, 0.94801087, 0.9495761, 0.95109539,
320 0.95257001, 0.95400122, 0.95539023, 0.95673822, 0.95804636, 0.95931576,
321 0.96054753, 0.96174273, 0.96290241, 0.96402758
322};
323
324/*!
325 * A look-up table (LUT) tanh calculation. This function returns an
326 * estimate to tanh(x) based on a 256-point LUT between -2 and
327 * 2. If x < -2, it returns -1; if > 2, it returns 1.
328 *
329 * This LUT form of the tanh is "hidden" in this code because it
330 * is likely too coarse an estimate for any real uses of a
331 * tanh. It is useful, however, in certain control loop
332 * applications where the input is expected to be within these
333 * bounds and the noise will be greater than the quanitzation of
334 * this small LUT. For more accurate forms of tanh, see
335 * volk_32f_tanh_32f.
336 */
337static inline float tanhf_lut(float x)
338{
339 if (x > 2)
340 return 1;
341 else if (x <= -2)
342 return -1;
343 else {
344 int index = 128 + 64 * x;
345 return tanh_lut_table[index];
346 }
347}
348
349} /* namespace blocks */
350} /* namespace gr */
351
352#endif /* GR_BLOCKS_CONTROL_LOOP */
A second-order control loop implementation class.
Definition: control_loop.h:51
float get_damping_factor() const
Returns the loop damping factor.
void set_beta(float beta)
Set the loop gain beta.
void set_min_freq(float freq)
Set the control loop's minimum frequency.
float get_min_freq() const
Get the control loop's minimum frequency.
float get_phase() const
Get the control loop's phase estimate.
void frequency_limit()
Keep the frequency between d_min_freq and d_max_freq.
Definition: control_loop.h:116
float d_damping
Definition: control_loop.h:55
float get_loop_bandwidth() const
Returns the loop bandwidth.
control_loop(float loop_bw, float max_freq, float min_freq)
void phase_wrap()
Keep the phase between -2pi and 2pi.
Definition: control_loop.h:95
float d_freq
Definition: control_loop.h:53
float get_frequency() const
Get the control loop's frequency estimate.
control_loop(void)
Definition: control_loop.h:59
float get_alpha() const
Returns the loop gain alpha.
float d_alpha
Definition: control_loop.h:56
void set_frequency(float freq)
Set the control loop's frequency.
float get_beta() const
Returns the loop gain beta.
void set_alpha(float alpha)
Set the loop gain alpha.
void advance_loop(float error)
Advance the control loop based on the current gain settings and the inputted error signal.
Definition: control_loop.h:76
float d_max_freq
Definition: control_loop.h:54
void set_damping_factor(float df)
Set the loop damping factor.
void update_gains()
Update the system gains from the loop bandwidth and damping factor.
virtual void set_loop_bandwidth(float bw)
Set the loop bandwidth.
void set_phase(float phase)
Set the control loop's phase.
float get_max_freq() const
Get the control loop's maximum frequency.
void set_max_freq(float freq)
Set the control loop's maximum frequency.
#define BLOCKS_API
Definition: gr-blocks/include/gnuradio/blocks/api.h:18
#define GR_M_PI
Definition: math.h:32
static float tanh_lut_table[256]
Definition: control_loop.h:278
static float tanhf_lut(float x)
Definition: control_loop.h:337
GNU Radio logging wrapper.
Definition: basic_block.h:29