Project: a shape in the world

Drive a square in world coordinates while the robot spins, which only a holonomic drive can do.

U2.7Kinematics and framesUniversity40 min

Do this lesson in the simulator

A square is easy when the robot faces the way it is going. Drive, turn, drive, turn. Now do it while the robot spins the whole time.

This is the exercise that separates the two frames for good. The path is in the world. The commands are in the body. The heading is changing continuously, so the relationship between them changes every tick, and any line of code that assumed forward means north will show it immediately.

The structure

for each corner of the square:
    until close to that corner:
        vector to the corner, in the world
        speed proportional to the gap, capped
        inverse kinematics with the heading you have NOW
        plus a rotation term, all the way

The rotation term never stops. The robot turns continuously; the translation is computed afresh each tick against the new heading. That is the whole trick, and it is why the heading has to be read inside the loop rather than once at the top.

from bugbot import *
import math
connect()

V_MAX, V_LAT = 20.0, 15.0

def world_drive(wx, wy, spin=0.0):
    a = math.radians(heading())
    vx = wx * math.cos(a) - wy * math.sin(a)
    vy = wx * math.sin(a) + wy * math.cos(a)
    drive(100 * vy / V_MAX, 100 * vx / V_LAT, spin)

for tick in range(40):
    world_drive(10, 0, 25)      # due east, spinning
    wait(0.1)
stop()
print("ended", position(), "facing", round(heading()))

Run this in the simulator

Run it and watch: the robot spins, and travels in a straight line east while it does. If the line bends, the heading is being read in the wrong place.

Task: a square while spinning

Visit the four corner zones in order, east then north then west then home, with a rotation term running all the way round.

from bugbot import *
import math
connect()

V_MAX, V_LAT = 20.0, 15.0
# the corners, in cm from where the robot started
CORNERS = [(40, 0), (40, 60), (-20, 60), (-20, 0)]

Challenges

  1. Plot the world path by printing x and y each tick, and check the corners are square.
  2. Make the robot face the corner it is heading for, instead of spinning. Which is easier to write, and which is easier to watch?
  3. Do the whole square with odometry() instead of position(). How square is it by the fourth corner?

What comes next

U3 takes that last challenge seriously. Dead reckoning is the only thing a robot has when nothing is watching it, and the module is about how it fails, how fast, and what it costs.