Part 5 · How robots are programmed

33Telling a robot what to do: commands, loops, timing

The arm is back with no sliders under it, only a program: eleven lines that lift it, wait, wave three times and report where the shoulder ended up. Read it, run it, change a number, and ask for an angle it cannot reach.

This assumes: Joints: the ones that turn and the ones that slide. About 9 minutes of reading.

The arm from the earlier modules is back, and for the first time there are no sliders under it. Every module so far handed you a knob, a slider or a star, and you moved the robot by hand. A robot at work has nobody at the sliders. Somebody wrote down, in advance, what it should do, and the robot does that, from the top, every time. This module is about that list: what one line of it says, how the robot gets from one line to the next, and how a few lines can become a long job. Nothing about the arm is new. What is new is that you write, and it moves.

A list the robot follows

Under the box is an eleven-line program: a list of commands, written down in advance, that the robot's computer carries out one after another from the top. Here it is, and then what each line means.

say("Starting")
moveJoint("shoulder_lift", -40)
moveJoint("elbow_flex", 20)
say("Arm up")
waitFor(1)
repeat(3, () => {
  moveJoint("shoulder_pan", 40)
  moveJoint("shoulder_pan", -40)
})
moveJoint("shoulder_pan", 0)
say("Done. The shoulder turn is at", readJoint("shoulder_pan"))

Each line is a command: it tells the robot to do one thing. A command starts with the name of the action, and then, in round brackets, what the action applies to. Line 1 says the word Starting: say writes whatever is in its brackets on a list under the box, with the time it was said. The quote marks mean "these exact letters, as written"; a number, like the 1 on line 5, needs none. Line 2 sends the shoulder lift to minus forty degrees: moveJoint takes a joint's name, in quote marks, and an angle in degrees, and moves that joint there. The joints are named under the box, in the program's one-word spelling, shoulder_lift, elbow_flex, shoulder_pan, and the plain labels from the arm, "Elbow" or "Shoulder lift", work too.

The line of angles under the box says where the arm starts: folded, with the shoulder lift at −69° and the elbow bent to 75°. A bigger shoulder-lift number tips the upper arm forward, so line 2 tips it forward to −40°, and line 3 opens the elbow from 75° to 20°, which is what raises the hand. Line 4 says so. Line 5, waitFor(1), does nothing for one second.

Lines 6 to 9 are a wave: swing the shoulder turn forty degrees one way, then forty the other, three times; how that is written is the next section. Line 10 turns the shoulder back to the middle. Line 11 says Done, and after it the angle the shoulder turn is at. That angle comes from readJoint, a command inside another command's brackets: it runs first, hands back a number, and that number takes its place inside say's brackets before say runs. A command can hand something back, and the command around it uses it.

That is the whole language: ten commands, all listed under the box. The brackets, quote marks and commas are the rules of JavaScript, the language the page itself is written in. You do not need to know it to read or change this program; keep the brackets and quote marks where they are, and the box tells you which line to look at if one goes missing.

One at a time, and each one finishes first

The rule that makes a program behave: the robot is on one line at a time, and it does not move to the next line until the line it is on is finished. For say that is instant. For moveJoint it is not. The command sends the joint's motor its new target and then waits, reading the joint, until the joint has got there, within two degrees and nearly still. Only then does the program go on to the next line. So line 3 does not start until the shoulder has finished lifting, and the wave does not start until the elbow has opened and the second's wait is over.

This is why a program's timing is the robot's, not the computer's. A computer could read eleven lines in a millionth of a second; the program takes about five, because most of its lines wait for a motor. The list under the box shows it: every line the program says carries the time it was said, and the gap between Arm up and Done is the time the arm spent moving and waiting. Pause the box and the program pauses with it; Slow slows it, because its clock is the robot's.

waitFor is waiting for its own sake; the wave would work without line 5. A real job is full of moments where the robot must do nothing on purpose, letting a gripper close, a part settle, a person step back, and a program has to be able to say "hold still for one second". That is all line 5 says.

Doing it again

Lines 6 to 9 are a loop: a part of a program that runs the same commands again and again. repeat(3, …) means run the lines between the curly bracket { at the end of line 6 and the } on line 9, three times over. The symbols () => { on line 6 and }) on line 9 are JavaScript's fence around the lines to be repeated; you do not need to know why they look like that, only that everything between them is one wave, out and back, done three times. Change the 3 and you change how many times, and nothing else.

This is how a few lines become a long job: a thousand identical placements is two thousand lines without a loop, and two lines and a number with one. The loop here is counted: three times, then stop. The loop in the first module, sense, think, act, sense again, had no count; it ran until the robot was switched off. The next module writes that one.

The box

You are looking at the arm from behind, over its base, so its right is your right. Above the program are Reset, Pause and Slow, as on every box so far. Under it is the program, with its line numbers down the left, and you can click into it and type. Beside Run is Stop, which ends a program part-way, and once you have changed anything a link appears that puts the original program back. Under the buttons one line says what the program is doing and for how long; then everything it has said, each with its time; then every joint's angle, live; and a folded list of the ten commands, with the joints' names and how far each can go.

Run starts the program from line 1, from wherever the arm happens to be: on a second run the arm is already up, so lines 2 and 3 are over at once. Reset folds the arm back to its starting pose and leaves the program as you wrote it, so the tries below start with Reset to get the same timings each time.

Loading the simulation. The robot runs in your browser, so the first one takes a few seconds to arrive.

This is easier on a larger screen, but it works here too.

What you saw

The first run was the program read aloud by the arm. Each line took its turn, each move finished before the next began, and the second of stillness in the middle was a line like any other. The last line reported the shoulder turn a fraction of a degree short of zero rather than at zero, and that is honest: moveJoint counts a joint as arrived once it is within two degrees and nearly still, and when line 11 read the joint the motor was still closing the last of the gap. It has to count that way: a motor closing on its target slows as it gets near and creeps over the last fraction of a degree, so a command that waited for the exact number would wait a long time, or for ever. Every real program has a "near enough" number like that in it somewhere.

The second try was the loop doing what a loop is for: one character changed, the robot did twice the work, and the time went up by three waves and nothing else. Then a line came out and a second came off the clock, because the wait was never for the arm's sake.

The third try is the one to keep. You asked for a hundred and forty degrees, and the shoulder turn's joint limit, the two pegs from the joints module, is a hundred and ten. The robot did not try and fail, and it did not go as far as it could and carry on. It refused, said which line asked and what the joint can do, and stopped there, holding its pose. A program stops at its first mistake, and everything it did before the mistake stays done: the arm was up, and it stayed up.

When it goes wrong

Nearly every program is wrong the first time it runs, and the box is built to tell you where. Misspell a command, movejoint for moveJoint, and you get "Line 2: There is no command called movejoint. Did you mean moveJoint?" as soon as the program reaches line 2: Starting has been said, and the arm has not moved. Like the angle on line 7, the bad name is found when its line's turn comes, and everything before it has already happened. A missing bracket is found sooner: the program cannot be read at all, nothing runs, and the box says it is written wrong, on that line or just before it, and which bracket. Every one of these is a plain sentence with a line number, and the line is marked red beside the program.

A second kind of loop, with no count, is the next module's, with a rule of its own about waiting.

What it is for

Nearly every robot you have seen in this course runs a list like this one. An arm on a production line is programmed by someone standing beside it with a handheld screen, moving it to a spot, saving that spot as a line, moving it to the next, and wrapping the lines that repeat in a loop: move here, close the gripper, wait half a second, move there, open, and again. The commands have longer names and take more numbers, but a program on a real arm is still moves, waits and loops, read from the top, one line finishing before the next begins. What this program never does is read anything but its own joint, so it does the same thing whether or not something is in the way; the next module gives it the robot's senses.

What the simulation leaves out

The joints here arrive quickly and without fuss, because the simulated motors are strong and the arm carries nothing; on a real arm moveJoint is a message to the motor's own small computer, which decides how fast to get there, and a heavy load makes it late. The language is JavaScript because the page is; most real robots are programmed in Python or C++, with commands of the same shape. And nothing here can be hurt, so an angle past a limit is a sentence in red; on a real arm the refusal is there because a program that got past it would bend something.

Watch

Using ForLoops in Blockly to Perform Pick and Place Operations — John Fuller (8:48 of it, starting at 5:34)

Why this video
A real desktop arm sits in a camera window beside its program the whole time, and a teacher does with it what this page asks you to do with the box: he reads the commands out from the top, move above the cube, suction on, move down, carry it over, suction off, move up, presses Start, and you watch the arm do exactly that list, in that order, and stop. Then he says the job is to stack three cubes, puts the same commands inside a loop, sets it to run three times, and presses Start again, and the arm does the list three times over while he feeds it cubes. It is this page's repeat(3, …) on an arm you could put on a desk, with a suction cup for a hand.
What to watch for
At 5:40 he reads the six commands in order and says what each makes the arm do; at 6:59 he presses Start and the picture cuts to the arm, and you can match each move to its line. At 8:08 comes the loop: at 9:54 "we want to loop it three times because we need to stack three blocks", and at 10:25 the count, zero, one, two. From 11:06 the only thing that changes each time round is how high the cube is set down, 25 millimeters higher per turn, which is why the loop needs its counter. At 13:40 he presses Start once more and the arm runs the same list three times; watch the stack grow, and notice nothing else in the program had to change.

Words introduced

program
A list of commands, written down in advance, that a robot's computer carries out one after another from the top. The robot does what the list says, in the order it says, and nothing the list does not say.
command
One line of a program that tells the robot to do one thing. It names the action, then in brackets what the action applies to, such as which joint and what angle. A command that takes time, like moving a joint, is finished only when the robot has done it, and the next command does not start until then.
loop
A part of a program that runs the same commands again and again. A counted loop runs them a set number of times; a loop with no count runs them until something stops it.

Where next

Suggested next: 34. Writing the sense-think-act loop yourself — The first module called the cycle behind a vacuum meeting a chair leg the sense-think-act loop. This module writes it: thirteen lines that drive the rover and, five times a second, read the front rangefinder and turn if something is under forty centimeters.