When I was trying to improve my maze performance, I noticed that my speed was being limited by the intersections. If I was moving too quickly when I hit them, I would invariably screw up somewhere. Going slowly enough to survive the intersections led to annoyingly slow driving on long straight segments, however. My solution was to time then length of every segment I encountered during the learning phase. I would reset the timer at an intersection and then stop it when I hit the following intersection. As I stored an array of visited intersections, I would store the times in a parallel array, so I would end up with something like:
{ L, S, S, R, L, … }
{ 3, 3, 6, 5, 8, … }
The top array gives the action performed at each visited intersection (L = turned left, S = went straight, R = turned right) and the bottom array gives the amount of time spent driving along the segment that directly led to that intersection (in some units that provide reasonably small numbers that can allow me to meaningfully differentiate between longer and shorter segments while still fitting within a single byte for all segments).
Once I’ve learned the maze, my maze-driving algorigthm is something like:
- If I am going straight at the next intersection, drive the current segment at high speed (don’t even worry about slowing down until we know we have an intersection coming up that will require a turn), else
- drive the current segment at high speed until time T has elapsed, at which point slow back down to normal speed until the next intersection is reached
T is computed from a function that uses the previously measured segment “length”. For short segments, T will be negative and I will just drive the entire segment at normal speed. For longer segments, T will be positive and cause me to drive most of the segment at high speed before slowing down just in time to handle the intersection safely. I came up with a function for T on paper, and then I ran a series of tests to get the various constants right. This approach requires just one successful learning run.
Typically, one would use encoders to measure the lengths of the segments. I was able to just use timing on the 3pi, however, because of the 3pi’s power system, which uses a regulated voltage for the motors and produces highly repeatable results. With a more traditional power system, motor speed would decrease as the batteries discharge, and a timing approach like this would potentially produce unreliable results. For example, the function you come up with for T when the batteries are freshly charged might stop working when they are nearly drained.
- Ben