In the last post I moved the left and right ping sensors from their previous position well forward of the drive wheels to a position right over the axis of rotation, thinking that might allow for smoother wall-following. What I found instead was that performance was severely degraded, to the point where Wall-E was more a wall-banging robot than a wall-following one ;-).
So, back to the drawing board. With the sensors themselves restored to their former positions, I decided to take another look at the wheel speed adjustment algorithm. Wheel speed values range from 0 to 255, with 0 being stopped and 255 being full motor speed. Currently, I start both motors at half speed (128) and then adjust the left/right motor speeds in a complementary fashion to achieve wall following. When the current ping distance is less than the previous one, I speed up the inside motor and slow down the outside motor by the same fixed amount – 50 – empirically derived from a number of runs with different values.
This fixed adjustment or ‘tweak’ value of 50 is HUGE, especially when you consider that it is added to one motor speed value and subtracted from the other; this is effectively 50% of the total range available to either motor. This is clearly why Wall-E’s wall-following performance looks so jerky – it works, but it looks like he’s forever in danger of going out of control (which does happen on occasion). However, on the plus side, it means that Wall-E does OK about negotiating corners, as it only takes two adjustment steps to get to an almost stopped wheel on one side and an almost full speed wheel on the other.
So, what I’m after is a more measured (pun intended) approach, where the ‘tweak’ value isn’t constant but rather is some function of the change in distance between one ping and the next.
There are 4 cases to consider: Assume Dn and Dn-1 are the distances returned by two adjacent pings from the left or right sensor.
- Left wall is closer, Dn – Dn-1 < 0
- Left wall is closer, Dn – Dn-1 > 0
- Right wall is closer, Dn – Dn-1 < 0
- Right wall is closer, Dn – Dn-1 > 0
What I want is some sort of algorithm like:
new left motor speed LSPDn = LSPDn-1 – K * (Dn – Dn-1)
new right motor speed RSPDn = RSPDn-1 + K * (Dn – Dn-1).
This works great for left wall following, where (Dn – Dn-1) < 0 indicates an increase in the left and a decrease in the right motor speeds, but the signs in red need to be swapped for right wall following, where (Dn – Dn-1) < 0 indicates a decrease in the left and an increase in the right motor speeds.
So, the above 4 cases can be reduced to 2 – left wall closer, and right wall closer:
- Left wall: LSPDn = LSPDn-1 – K * (Dn – Dn-1); RSPDn = RSPDn-1 + K * (Dn – Dn-1)
- Right wall: LSPDn = LSPDn-1 + K * (Dn – Dn-1); RSPDn = RSPDn-1 – K * (Dn – Dn-1)
So, for a 2 cm smaller distance to the left wall, LSPDn = LSPDn-1 – K * (-2) = LSPDn-1 + 2K,
RSPDn = RSPDn-1 + K * (-2) = RSPDn-1 – 2K, which is correct. For a 2 cm larger distance, the signs in red would swap, which is also correct.
For the right wall we have: LSPDn = LSPDn-1 + K * (-2) = LSPDn-1 – 2K,
RSPDn = RSPDn-1 – K * (-2) = RSPDn-1 + 2K, which is correct. For a 2 cm larger distance, the signs in red would swap, which is also correct.
So, now all I need to do is code this up and give it a whirl. I think I will start with K = 10, and limit the per-instance wheel adjustment to 50 (same as it is now, essentially).