Project: precision parking

Round a box and into a bay facing east, on the worst robot in the course.

3.6ControlRobot club25 min

Do this lesson in the simulator

A box in the middle of the mat, a parking bay in the far corner, and the worst robot in the course: it curves and it leaks. Get round the box, into the bay, and finish facing east. Every controller from this module, in one program.

The plan

# start at the bottom left, facing up
# 1. hold the line x = 0 (relative) up the left side of the box, to y = 67
# 2. slide right along the top of the box, holding y = 67 and heading 0, to x = 55
# 3. turn to face 90 and hold it

position() is relative to the start, so x = 0 means "the line I started on", which passes left of the box. Look at the scene before you run anything.

Leg one as a function

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def wrapped(h):
    return (h + 180) % 360 - 180

def hold_line(target_x, until_y):
    while position()[1] < until_y:
        # where am I? (cm from where I started)
        x, y = position()
        # forward, sideways, rotation: -100 to 100 each, until the next command
        drive(70, (target_x - x) * 10, wrapped(0 - heading()) * 4)
        # pause 0.1 s (the robot keeps doing what it was told)
        wait(0.1)
    # all motors off
    stop()

hold_line(0, 67)
print("top of leg one:", position(), "facing", round(heading()))

Run this in the simulator

Leg two: sideways, holding two things

Now the robot slides right. The forward part of drive holds y, the rotation holds the heading, and the sideways part is the speed:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def wrapped(h):
    return (h + 180) % 360 - 180

def hold_line(target_x, until_y):
    while position()[1] < until_y:
        # where am I? (cm from where I started)
        x, y = position()
        # forward, sideways, rotation: -100 to 100 each, until the next command
        drive(70, (target_x - x) * 10, wrapped(0 - heading()) * 4)
        # pause 0.1 s (the robot keeps doing what it was told)
        wait(0.1)
    # all motors off
    stop()

def slide_right(target_y, until_x):
    while position()[0] < until_x:
        # where am I? (cm from where I started)
        x, y = position()
        # forward, sideways, rotation: -100 to 100 each, until the next command
        drive((target_y - y) * 10, 70, wrapped(0 - heading()) * 4)
        # pause 0.1 s (the robot keeps doing what it was told)
        wait(0.1)
    # all motors off
    stop()

hold_line(0, 67)
slide_right(67, 55)
print("end of leg two:", position(), "facing", round(heading()))

Run this in the simulator

Leg three: turn and hold

A heading controller with no driving, the proper version of lesson 3.1:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def wrapped(h):
    return (h + 180) % 360 - 180

def hold_heading(target):
    error = wrapped(target - heading())
    while abs(error) > 2:
        # forward, sideways, rotation: -100 to 100 each, until the next command
        drive(0, 0, max(-60, min(60, error * 3)))
        # pause 0.05 s (the robot keeps doing what it was told)
        wait(0.05)
        error = wrapped(target - heading())
    # all motors off
    stop()

hold_heading(90)
# pause 0.5 s (the robot keeps doing what it was told)
wait(0.5)
print("facing", round(heading(), 1))

Run this in the simulator

Task: precision parking

Reach the bay without touching the box and finish facing 90, within 6 degrees.

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def wrapped(h):
    return (h + 180) % 360 - 180

def hold_line(target_x, until_y):
    while position()[1] < until_y:
        # where am I? (cm from where I started)
        x, y = position()
        # forward, sideways, rotation: -100 to 100 each, until the next command
        drive(70, (target_x - x) * 10, wrapped(0 - heading()) * 4)
        # pause 0.1 s (the robot keeps doing what it was told)
        wait(0.1)
    # all motors off
    stop()

hold_line(0, 67)

Where next

The Precision Park competition is this project against the clock: three bays, each smaller than the last, and points for stopping dead centre and square. Module 4 gives the robot a camera so it can control on what it sees, not just where it thinks it is.

Challenges

  1. Park in under 10 seconds.
  2. Go round the right of the box instead and arrive from below.
  3. Write go_to(x, y) that drives to any point using math.atan2 for the heading and the two-loop line holder, and park with two calls to it.