Protocols

Agreeing what a message looks like; splitting it into words and numbers.

9.3Talking to each otherRobot club20 min

Do this lesson in the simulator

Two robots can only understand each other if they agree in advance what messages look like. That agreement is a protocol. It can be as small as "one word, then a number", and on this mat it is: the Guide answers next with an instruction like forward 30, right 25 or done.

Asking and waiting

A question is a message you send and then wait for the answer to. ask does both: it sends, then polls for up to a second, and returns the first reply, or None if nothing came. Radios miss things; a program that waits forever for a reply that never comes is stuck, so the timeout is part of the protocol too.

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

def ask(question, seconds=1.0):
    # send a question and return the first reply that arrives within `seconds`, or None
    send(question)
    for tick in range(int(seconds * 10)):
        # pause 0.1 s (the robot keeps doing what it was told)
        wait(0.1)
        for sender, text in messages():
            return text
    return None

def numbers_in(text):
    # every number in a message, as floats: "at 25,55" -> [25.0, 55.0]
    out = []
    for word in text.replace(",", " ").split():
        try:
            out.append(float(word))
        except ValueError:
            pass
    return out

reply = ask("next")
print("the guide says:", reply)

Run this in the simulator

Taking a message apart

split() breaks a string into words at the spaces. The first word says what to do, the second how much:

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

def ask(question, seconds=1.0):
    # send a question and return the first reply that arrives within `seconds`, or None
    send(question)
    for tick in range(int(seconds * 10)):
        # pause 0.1 s (the robot keeps doing what it was told)
        wait(0.1)
        for sender, text in messages():
            return text
    return None

def numbers_in(text):
    # every number in a message, as floats: "at 25,55" -> [25.0, 55.0]
    out = []
    for word in text.replace(",", " ").split():
        try:
            out.append(float(word))
        except ValueError:
            pass
    return out

reply = ask("next")
words = reply.split()
print("words:", words)
command, amount = words[0], float(words[1])
if command == "forward":
    forward(50, distance=amount)
elif command == "right":
    right(50, distance=amount)
print("did", command, amount, "now at", position())

Run this in the simulator

float(words[1]) turns the text 30 into the number 30.0. The text is what travelled; the number is what you can drive with.

Strict out, forgiving in

Two habits that keep robots talking. Be strict about what you send: always the same words, the same order, the same units. Be forgiving about what you receive: text.lower().strip() before you look at it, and if you do not understand a message, ignore it rather than crash. A robot that stops because someone sent Forward 30 instead of forward 30 is not much of a team mate.

Task: follow instructions

Ask the Guide for instructions one at a time, do each one, and stop at done. You will end up in the green zone.

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
def ask(question, seconds=1.0):
    # send a question and return the first reply that arrives within `seconds`, or None
    send(question)
    for tick in range(int(seconds * 10)):
        # pause 0.1 s (the robot keeps doing what it was told)
        wait(0.1)
        for sender, text in messages():
            return text
    return None

def numbers_in(text):
    # every number in a message, as floats: "at 25,55" -> [25.0, 55.0]
    out = []
    for word in text.replace(",", " ").split():
        try:
            out.append(float(word))
        except ValueError:
            pass
    return out
reply = ask('next')
print('guide says:', reply)

Challenges

  1. Handle left <cm> and backward <cm> too, even though this Guide never sends them.
  2. Handle turn <degrees>.
  3. If ask returns None, try again, up to three times, then give up and print why.