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