When playing around with various algorithms, the question becomes: what is the output of the algorithm? Of course one option is to output a signal that gets piped directly to the Sabertooth hardware motor controller. The hardware controller simply converts a signal to voltage, so if our main control algorithm is talking directly to the hardware controller, the control algorithm is effectively outputting a voltage. Lets say the hardware motor controller takes a signal ranging from -100 (full reverse) to 100 (full forward). Then the main control algorithm might issue a command to go forward like this:
But thats a bit of a problem, and here is why: lets say the control algorithm is tuned and Beaker is balancing. Maybe the control algorithm is a neural network, or a simple PID controller. Either way, the system is mostly tuned for a condition which could easily change. The surface of the floor might not always be wood, or flat. A gear might get gunked up and have more friction. The point is that by having the main control algorithm talk directly to the hardware controller, the main control algorithm is burdened with compensating for the problems mentioned earlier in this paragraph (tilted floor, gunked gears, etc..), on top of the central issues like, in Beaker’s case, balancing by paying attention to angle and a few other things. So what can we do about this?
What if instead of outputting voltage, the main control algorithm just put out a desired radians per sec? That command would be passed off to a lieutenant, a faithful servant that would make sure the rads/sec was enforced by the wheels. Using the lieutenant analogy, the main control algorithm would be the Commander, issuing rads/sec, and would not care about carpet flooring vs wood (varying frictions), or gunked up gears. The Lieutenant would worry about it, and the Commander would just be concerned with the higher order task of (in Beakers case) keeping balance by taking inputs of angle (and a few other things), and issuing outputs of rads/sec.
This is known as cascading control. A fast inner loop handles the request of a slower outer loop. In Beaker’s case, the fast inner loop is the PID motor control, and the slower outer loop would be the primary balancing algorithm. Loop speeds in Beakers case were 5ms for the inner loop, and 20ms for the outer loop.
The Lieutenant’s Training Wheels
The Lieutenant in Beaker’s case is the Wheels object, which has a PID controller for each wheel. The Wheels object takes a rads/sec command, and uses that as a new set-point. Great! Except now we just have this issue about tuning these PID controllers. How do we do it? There is lots of documentation on this, so my point here is more about Beaker specifically. Beaker is a balancing robot. So if I turned Beaker upside down and tuned the PID controllers, it would not be very realistic, since there would be very little resistance. So I want Beaker upright. Except he’s just going to fall down. So… so…. Beaker needs training wheels 🙂
With Beaker’s training wheels, Beaker has almost all weight on the wheels, but stays balanced. Now I could get to tuning the PID params without having to think about balance.
Tuning the Lieutenant
Using a little Arduino Script, I was able to run trials of Beaker accelerating from stopped to some target rads/sec and graph the results. Here are some examples:
Too much overshoot and WAY too slow:
At higher setpoint more overshoot but not too bad:
As you can see, with the proper settings, I was able to get a decent rise-time, with not too much overshoot. With this in place, Beaker’s lieutenant was ready to take rads/sec commands, and thusly ready for actual balancing algorithms 🙂
To see Beaker balancing, albeit badly, and just with PID, check out this older instagram