A drive that goes sideways

Three degrees of freedom on the floor, and what holonomic buys you.

U2.3Kinematics and framesUniversity25 min

Do this lesson in the simulator

A car has three degrees of freedom on the floor (x, y and heading) and two controls, and it cannot use them independently: to move sideways it must drive forwards and backwards several times. That is a non-holonomic vehicle, and parallel parking is the everyday proof.

The BugBot has three controls for three degrees of freedom. It is holonomic: any combination of forwards, sideways and turning, at once, straight away.

A car needs a back-and-forth shuffle to move sideways; the BugBot slides straight acrossa cartwo controls: shufflebackwards ontwo arcs, thenforwards againthe BugBotthree controls: straight across22 cm to the right,still facing within 1°
Moving to the side. To end up one body width across, facing the same way, the car has to back out on two arcs and drive forwards again. The BugBot, in the first run below, slides 22 cm straight across, counting its coast after stop(), and ends less than 1 degree off the way it started.
from bugbot import *
connect()

# straight to the right, still facing the way it started
drive(0, 70, 0)
wait(2)
stop()
print("ended at", position(), "facing", round(heading()))

Run this in the simulator

What that buys you

  • Position and heading come apart. The robot can point the camera at one thing while travelling towards another. A tracked vehicle has to choose.
  • Planning gets simpler. A path is any curve at all, not a curve a car could follow. The whole subject of Dubins paths and Reeds-Shepp curves, which exists because cars cannot go sideways, is unnecessary here.
  • Control gets simpler. The error in x and the error in y can be fixed by separate terms, at the same time, which is why U2.6 fits in one page.

And what it costs: more actuators, worse efficiency, and an odd drive that is harder to model. The sideways axis of this drive is built slower than the forward axis (about 15 cm/s at full scale against 20) and the two do not stay out of each other's way. Holonomic on paper, only roughly so in the world.

The three commands are not the same size

from bugbot import *
connect()

for name, cmd in (("forward", (70, 0, 0)), ("sideways", (0, 70, 0)), ("turning", (0, 0, 70))):
    drive(*cmd)
    wait(1.2)
    bx, by = flow()
    print(name, "flow", (round(bx, 1), round(by, 1)), "turn rate", round(imu()[1]))
    stop()
    wait(0.6)

Run this in the simulator

On this robot forward 70 gives 12.9 cm/s, sideways 70 gives 12.2 cm/s and turning 70 gives 88 degrees a second. The sideways figure is closer to the forward one than the design says, because this robot's sideways motors happen to be strong ones: that is the gain spread from U1.2 again. Command 70 means 70 percent of that axis, and each axis has its own full scale. Any code that treats a command as a velocity will be wrong by the ratio between them, and wrong differently in x and y, which shows up as a robot that drifts to one side of the straight line it was asked for.

Forward 70 and sideways 70 together: the speeds are not equal, so the direction is not 45 degrees45°: what equalcommands suggestforward 70:14 cm/ssideways 70: 10.5 cm/sthe way it goes: 37°
drive(70, 70, 0) with the design full scales, 20 cm/s forward and 15 sideways. The same 70 gives 14 cm/s one way and 10.5 the other, so the robot heads 37 degrees off forward, not 45. This robot's strong sideways motors (12.9 and 12.2) bring it to 43: every robot is off by its own amount.

Task: crab into the zone

The green zone is to the robot's right. Get into it without turning: the robot has to arrive facing the same way it started.

from bugbot import *
connect()

# drive(forward, sideways, rotation)

Challenges

  1. Drive a diagonal by using forward and sideways together. Is the path straight?
  2. Drive in a circle without changing the heading at all, using only the two translation terms.
  3. Measure the sideways top speed and the forward top speed, and work out the ratio. Keep the number.