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.
Tuesday, June 24, 2014
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.
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.
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.
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.
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 |
Subscribe to:
Posts (Atom)