Quote:
Originally Posted by Aaron.Graeve
I have a few questions about the Flywheel Controller used on Barrage.
I am trying to understand the states you used to control the flywheel and have gathered the second element is the velocity, but I am having difficulty understanding what the first element is. Looking back on your 2012 code, the first state seems to be a position that is taking the place of an integral term and I am guessing a similar set up was used in 2013 and 2014. Is this correct?
As I was looking for what the first element of the flywheel state is, I came across a line that was writing part of the desired state matrix.
Code:
r.set(0,0, (velGoal * (1 - A.get(1,1)))/ A.get(1,0));
Could anyone clue me into what is being predicted here?
Lastly, what method do you use to find the gains for the matrices and select the poles that will be used?
Sorry for all the questions.
|
Sorry for taking so long. To support properly answering this question, Tom has released the control loop design code that makes this possible to follow. Thanks Tom! I helped design the controller in 2013 for that shooter based on code from 971, and Tom re-tuned it this year. The only changes (that he told me about) were to re-tune the mass for this year.
https://github.com/Team254/ControlLoops
The controller architecture used is called a Delta U controller. I haven't seen used very often, but it is one of my favorite ways of solving integral control. I learned it in a Model Predictive Control class at Berkeley, taught by Professor Borrelli.
Boiled down, a simple flywheel model would be as follows. (Check the python if my conventions for G, Kt, and Kv aren't what you expect) This model is assuming we only care about velocity, and are measuring the velocity with a velocity sensor. (banner sensor reading the pulse width)
dv/dt = -Kt / Kv / (J * G * G * R) * v + Kt / (J * G * R) * volts
A FSFB controller for that plant would apply a power proportional to the velocity error. If there is a constant disturbance, the controller will have to have an error to compensate, so it will never track perfectly.
Somewhere, we need an integrator in the system to be able to add up power to overcome this force. One classic way is to introduce a new state which is the integral of v, and stabilize that as well. This has classic integral windup problems. If everything is going according to the model, the integrator will still integrate up and cause overshoot. I don't like that tradeoff, and have been searching for a way to solve that for years.
Enter Delta U control. The basic idea is that instead of adding an integrator to the output, lets add an integrator to the input. Our state then becomes
[voltage at the motor,
velocity]
This means that our controller will output changes in power that are proportional to the difference between the goal power and the current power, and the goal velocity and the current velocity.
This wouldn't be special, except that we use the voltage estimated by the observer for the current power, and use a separate summer to add up the changes in power that the controller generates. This separate summer then commands the Talons. This means that any disturbances in the system end up showing up as a voltage difference between the voltage estimated by the observer and the voltage commanded. You can think of this like we are estimating the voltage lost due to disturbances, and adding that back into the commanded output.
The really cool part about this is that if our system is responding as the model predicts, the estimated voltage will be the same as the commanded voltage, and we won't get windup! Way cool.
Your first question was why
Code:
r.set(0,0, (velGoal * (1 - A.get(1,1)))/ A.get(1,0));
. The answer is that we need to feed in the desired state. The desired state includes velocity and power. That computation computes the steady state voltage required to go at the velocity we want. (check my math to see).
The Python is used to set the gains. The model is first tuned by plotting the system response to a step input on top of the simulated response and fitting one of the parameters. The gains are then tuned using direct pole placement, looking at the resulting values, and trying it on the robot. For this flywheel controller, the real challenge was tuning it to be robust to noise. There is a fair amount of noise from the variation in the loop frequency in Java, and more noise in the sensor reading. In 2013, we tuned it so that when the signal was noisy, the flywheel held steady. The solution here is to make the observer is very slow to filter out the noise. The controller is overdamped, which produces a pretty fast rise time, and no overshoot.
I hope this was helpful, and not too overwhelming.