It's All About Control
Another absolute whirlwind of a week has gone by, with significant progress on getting the robot to reach its goal.
I've fully implemented a linear Kalman filter – this is the localisation algorithm that performs sensor fusion on the laser distance sensor and the IMU and estimates where the robot is along the track and its current velocity. This is only one half of the problem to solve though, just because the robot now knows where it is, that doesn't mean it knows how to move somewhere else. That's where the control algorithm comes in – I began experimenting with a cascaded P-Controller, one of the most simple control algorithms out there. This would allow me to at least verify that the Kalman filter could be used as an input to a control algorithm successfully.
First though, I had to make sure to properly calibrate the laser distance sensor. Since “forward” in the the robot's coordinate system is towards a laser distance reading of zero, that doesn't match up with the positive value of the IMU meaning forwards acceleration, or the positive values used for forwards thrust. To account for this, I called the end of the track with the laser reflector (which is just just a white 3d-printed panel mounted to the end of the track) a somewhat arbitrary positive value of 40,000 (4m in the laser's 1/10th of a mm readings) and subtract the reported laser value from that, always resulting in a positive value that gets larger the closer to the reflector the robot. I also added a static offset to the measurement to account for the distance between the front of the laser and the alignment arrow in the middle of the robot. I calculated this by averaging about 350 laser readings with the alignment arrow positioned exactly 1m from the reflector.
Aligning the robot's alignment arrow with the 1m track marker
The cascaded P-Controller loop definitely made the robot move, but the effect was a little on the intense side, so much so, the robot actually damaged itself by slamming into the end of the track and I had to re-print and replace the base the fans sit on, which cost me valuable time. I let that be a lesson to myself – there's no such thing as too much health and safety, and I'm just glad it was an easily replaceable part and not any of the expensive electronics which were damaged.
That's not to say the algorithm I used was bad though, after I had debugged it and placed very strict limits on the raw PWM output that controls the fans to avoid any more damage, the robot definitely looked like it was trying to approach its target, but it was oscillating past it over and over, and no amount of tuning seemed to be fixing it. I could have expanded this to a full PID style control algorithm, but that would have been a bit of a distraction. Remember, the purpose of this system is to sort of emulate how a satellite moves in orbit with reaction control system thrusters that fire in short bursts, that kind of movement can't really be emulated with a classic PID style control algorithm, instead I needed to use a the kind of algorithm actually used on those satellites. This algorithm is called Bang-Bang with hysteresis, and treats the fans being on or off as a binary state, rather than a continuous range of power. The ESCs still expect the PWM signals to be smooth though or they will shut off the fans for safety, so this requires a separate control loop running at its own intervals, independent of the main control loop, to control the smooth ramp up and down of the fans.
This definitely looks like it works better (and closer to how I imagined), but it still requires a little tuning before it's completely ready. The robot does approach it's goal but will still often overshoot slightly and then gets stuck trying to correct as static friction inhibits it's ability to move the short distance back to the goal. This is something I believe I can code around early next week.
Let's Talk Telemetry
All this work on the control algorithms required extensive debugging, which obviously needs data from the robot. To aid myself with this process, I added a new characteristic to the bluetooth stack, to enable streaming of telemetry data back from the robot to the control script in real time. Currently the robot reports the following values which are logged by the control script to a CSV: – Laser distance reading – IMU reading – Front thrust value – Rear thrust value – The algorithm's estimated position – The algorithm's estimated velocity
These have been really helpful for debugging and tuning and should hopefully allow me to make some nice graphs for the final report once everything is working as intended!
Other Stuff
As for other features I've implemented this week, I've added an error tone to the speaker class which plays when the robot encounters an error, or in situations like when the controller disconnects unexpectedly. Speaking of, that exact scenario now also results in an emergency stop triggering to stop the robot going out of control. I've also made it dump error traces to a file on the board itself so in case of errors cascading and not being able to report over bluetooth, I should still have a file I can pull off the board to help debug whatever just happened.
I might add a couple of videos to this post in an update or maybe they'll come next week, we'll see.
Gantt Chart Check In
Thankfully there's been an extension to the final report deadline, that's good news because who knows how I was going to get this done before!