Tuesday, June 24, 2014

Accounting for Zero Order Hold

In our work, we've overlooked an important aspect of digital control systems, which gains importance as we try to control systems with greater time steps in between controller updates. Specifically, we have not taken into account the impact of the zero order hold. Here is a quote from Franklin, Powell, and Workman in the book Digital Control of Dynamic Systems:

"It is worthy to note that the single most important impact of implementing a control system digitally is the delay associated with the D/A converter. Each value of u(kT) is typically held constant until the next value is available from the computer. Thus, the continuous value of u(t) consists of steps that, on the average, lag u(kT) by T/2. If one simply incorporates this T/2 delay in a continuous analysis of a digital system, excellent agreement results for many reasonable sample rates."

These effects become less significant as the control update time step becomes smaller, but we want flexibility in the time step. This is shown by another quote:

"Many systems are originally conceived with fast sample rates, and the computer is specified and frozen early in the design cycle; however, as the designs evolve, more demands are placed on the system, and the only way to accommodate the increased computer load is to slow down the sample rate. Furthermore, for cost-sensitive digital systems, the best design is the one with the lowest cost computer that will do the required job."

With our system, updating the control input at intervals longer than 10 ms causes the system to crash. At 10 ms intervals, I would suspect that the controller will perform poorly and will be more susceptible to failure (especially if a packet is dropped). By accounting for the zero-order hold, I think that the controller can potentially run at a slower rates and still maintain good system performance. Also, perhaps we can use similar techniques to account for time delay caused by network circumstances.

Thursday, June 12, 2014

Successful Lead Compensation

I just got the lead compensator to work. It turns out that I was not tuning the compensator correctly. First of all, I was not using my root locus tools to help me. That will get you in trouble.

I decided to install Matlab to my computer to do some root locus analysis. I set my two poles of my lead compensator and then varied the gains, and the root locus quickly showed me the gain required for a desirable response (zero overshoot, low time constant). I quickly tested this set of parameters, and found that my system was stable, and that my theta response plot was much smoother than it was previously. 

I think that with this new controller, my system will be less sensitive to perturbations and to poor network conditions. Overall, it should be more robust to disturbances, and will be less likely to crash since the controller won't amplify noisy signals like my PD controller. To further tune the controller, I will probably use some genetic programming techniques, which Dr. Remy introduced me to this past year. These techniques essentially evolve gains, discard the ones that perform poorly, and mutate the ones that do well until the best performance is obtained.

Another thing I did, just for the heck of it, was implement a more accurate numerical integration technique to propagate my Model. Before, I was using Euler integration, which is about the most simple method you can possibly imagine. With Euler integration, the accuracy increases linearly was you reduce the time step. I decided to implement Heun's method, also known as the modified Euler method, which can be thought of as a two-state Runge Kutta method. This method requires about twice the computation, since you must compute one more derivative per iteration. However, this allows you to get some sense of the concavity of the solution, and compensate based on that. With Heun's method, the accuracy increases quadratically with reducing time step.

Thankfully, after implementing Heun's method, nothing really changed. This is probably because I am using such a small time step (1 millisecond) for state propagation that the accuracy is already very good. However, with Heun's method implemented, I will probably be able to reduce this time step and get better results than I would with the Euler method. In the future, I could probably look into more complex methods, but I think this will do for now.

Tuesday, June 10, 2014

Attempted Lead Compensation

I tried to implement a low pass filter with my PD controller today, but that drastically failed. I looked at a work that talked about practical implementation of PD control, and it talked about preceding the controller with a low pass filter to reduce the noise in the error signal. Using Routh's stability criteria, I determined that my new controller would be stable if the pole of my filter was greater than the ratio of my proportional and derivative gains.

Unfortunately, the system wasn't stable. The pitch angle just oscillated wildly with increasing amplitude until the plant blew up. The pitch angle response plot was "smooth", however, unlike the response for the system without a filter.

The weirdest thing was, the pitch angle oscillated with increasing magnitude and blew up when I had a step reference for my x-position. I don't know why that is happening.

The only thing I can think of doing is to actually simulate my control system in Simulink and see if I am getting the same response. I am thinking I have done something wrong at this point.

Friday, June 6, 2014

Lead Compensation

Using derivative control with a noisy reference signal is not a good idea. I keep forgetting that.

I originally chose to use a PD controller to control the quadrotor because nearly all of the equations of motion (for the linearized dynamics at least) are double integrators, and PD controllers look really nice on paper for those systems. As long as my two gains are positive, the system is theoretically supposed to be stable.

The problem is, derivative control action doesn't handle high frequency error signals well. My system's response plots show that high frequencies are indeed present in the system, and I have a suspicion that my controller is just amplifying the noise.

I gave my initial approach to this problem in my "Improved Controller Performance" blog. It turns out that my method to handle the high frequency components is very rough, and is probably not the best method. Firstly, it is difficult to determine the error rate threshold I should set to ignore the derivative term. It's kind of like tuning a PID controller by hand (not recommended). Secondly, there is a much better, more promising method that actually has validity: lead compensation.

The way I understand lead compensation, it is the combination of a PD controller with a low pass filter. the error signal is sent through a low pass filter before it is fed into the PD controller. The low pass filter attenuates the high frequency signal components I mentioned earlier. Hence, the derivative action has less high frequency noise to amplify.

With that being said, the lead compensator adds complexity to the system. It will be a bit more challenging to determine the pole and the zeros that give me a desired response. But that doesn't mean it's not worth the bit of extra effort. 

The Need for Efficiency

Dr. Remy and I had a long meeting during which we tried to troubleshoot my code and see what the problem was. At one point, I attempted to print a lot of things to the screen every iteration, and the program crashed--literally. Not the model, the program. I got an error, and apparently I was overworking the system.

When I just tried to print a few things to the screen, the program didn't crash, but the model usually did. But when I printed nothing to the screen, the model crashed a lot less frequently. I started thinking that perhaps this was an efficiency issue. If my code doesn't even have enough time to print to the screen, maybe there were some things I could think of to make it run faster.

I tried some of the tips shown at this web page: https://wiki.python.org/moin/PythonSpeed/PerformanceTips. Some of the info may be outdated, but some of the tips could work. I need to profile the code later to see if it really makes a difference.

1) Instead of using Numpy functions, I used the default math functions. I learned that Numpy functions are much slower than math functions.

2) Apparently the fewer times you use the dot operator, the better. It is best to save a function handle in a variable and use that variable later.

3) I only logged the variables I needed to. When certain flags are set to False, variables that are not needed are not logged. 

4) I had defined many things as global variables that did not need to be global variables. Thus, I shortened this list.

Whereas before I could not get the code to run for 60 seconds without the model crashing, I can now run it for four minutes without it crashing. Here are the results for my four-minute test. The roll and yaw references are zero, the x reference is a sinusoidal input with an amplitude of 1 meter and a period of 5 seconds, and the z reference is a sinusoid with an amplitude of 1 meter and a period of 10 seconds.

(Left) z-position and (right) x-position for sinusoidal z and x inputs

(Left) pitch angle and (right) roll angle for sinusoidal z and x inputs


Yaw angle for sinusoidal z and x inputs