Control Loop Gain Values

I have recently been working on updating our digital modulation capabilities in GNU Radio. This has involved making a gr-digital namespace, moving all relevant digital modulation work over, and going through and fixing up a number of the algorithms. One issue in particular that I have been working on is the concept of the loop gains in all of our control loops. You will find in any control loop we have, like in the clock recovery, Costas loop, constellation receiver, FLL and PLL blocks, that the control loop has two gains, alpha and beta. These are used in the following ways:

freq = freq + beta * error

phase = phase  + freq + alpha * error

When creating any of these blocks, we have to specify both alpha and beta. But what should these values be? What relationship do they have to each other, or, indeed, the physical properties of the control loop? Well, that's not easy to understand or explain, and because of this, it's not the right way to build these algorithms.

A better way is to convert these gains into a damping factor and loop bandwidth, which gives us a bit more intuition as to what's going on and makes them easier to set. So I have been switching over to using these concepts instead of alpha and beta. The loop equations are the same, and so we have to derive alpha and beta from these two new concepts. This is done in the following way where damp is the damping factor and bw is the loop bandwidth:

alpha = (4 * damp * bw) / (1 + 2 * damp * bw + bw * bw)

beta = (4 * bw * bw) / (1 + 2 * damp * bw + bw * bw)

So now we just have to know what damping factor and bandwidth we require from our loops. Of course, right now it seems like we've just translated from one set of unknowns to another set of unknowns. But at least we can better explain this new set. In fact, we're going to break it down so that we only specify one of those numbers.

In control systems, the damping factor specifies the oscillation of the loop, whether it's under, over, or critically damped. In a normalized system, a damping factor of 0.707 (or the sqrt(2)/2) is a critically damped system. This is a good approximation for most systems, so we can just set it and forget about it.

So now, we just have to set a loop bandwidth. This is a bit more difficult, but as a rule, this value should be somewhere around (2pi/100) to (2pi/200), so we can work around there. If we're trying to optimize the behavior of our system, it's now a hell of a lot easier to work with a single value instead of two.

Just to be complete about the whole thing, though, as I have been reworking all of these blocks, I have also been adding set and get functions for every value. So while the constructor only needs us to give it the loop bandwidth, we can also change the damping factor if there's a particular need to do so. We can also individually change alpha and beta, still, if really want to.