LCRJune 2009
LCRJune 2009
Computing
With
Robots
Edited by
Deepak Kumar
Permission is hereby granted to reproduce facsimiles of this text in any form for distribution
provided an e-mail note is sent to the editor at [email protected] describing the
manner and intended purpose of distribution.
Permission is also granted to modify the content of this text in any manner seemed desirable
by instructors. We recommend that all derivations from this text be distributed through IPRE
in the same manner as this text. To obtain the permission we require the same process as laid
out for distribution above.
We strongly recommend distributing the text and its modifications with a not for profit
motive.
We are making this text available in the manner described above so as to enable the widest
possible accessibility of the content as well as the ideas illustrated in this text. We hope that
users will respect and honor and promote such practices with their own works.
We have taken great care to attribute all images used in this text to their original sources. This
text is intended for educational purposes and such use constitutes fair use. Where feasible, we
have obtained permissions to use copyrighted images. Please contact the editor in case there
are any pending issues in this regard. All images not explicitly attributed in the text are
created by members of the IPRE team.
ISBN-10: 1607028832
ISBN-13: 978-1607028833
Institute for Personal Robots in Education
Fall 2008, Revised June 2009
Contributors
IPRE was created to explore the use of personal robots in education
with primary funding from Microsoft Research, Georgia Institute of
Technology, and Bryn Mawr College. This text would not have been
possible without the hardware, software, and course materials
developed by members of the IPRE team.
i
Learning Computing With Robots
ii
Learning Computing With Robots
Contents
Preface v
Chapter 1
The World of Robots 1
Chapter 2
Personal Robots 21
Chapter 3
Building Robot Brains 43
Chapter 4
Sensing From Within 71
Chapter 5
Sensing The World 97
Chapter 6
Insect‐Like Behaviors 129
Chapter 7
Behavior Control 157
iii
Learning Computing With Robots
Chapter 8
Sights & Sounds 187
Chapter 9
Image Processing & Perception 215
Chapter 10
Artificial Intelligence 245
Chapter 11
Computers & Computation 273
Chapter 12
Fast, Cheap & Out of Control 309
Index 340
iv
Preface
This book will introduce you to the world of computers, robots, and
computing. Computers, as we know them today have been around less than 75
years. To our young audience for whom this book is designed, that may seem
like an eternity. While computers are all around us, the world of computing is
just in its infancy. It is a baby!
In this book, you will learn that computing is no more about computers than
astronomy is about telescopes. In that respect, the roots of computing could be
traced back more than 2000 years to Euclid in 300 BC. Could it be that
computing is actually as old as or even older than some of the other
disciplines? Prior to the development of modern computers, the word
computing mostly implied numerical calculation. Today, computing
encompasses all forms of electronic manipulation of objects: numbers, text,
sound, music, photographs, movies, genes, motors, etc., and even ideas! Every
day we are discovering new things that can be computed.
Robots are not that much older than computers. We will learn that, contrary to
popular belief, a robot is any mechanism that is guided by automated control.
v
Preface
Advances in the past few decades have brought about many changes in the
way we use and live with technology. Computers have become smaller,
cheaper, faster, and more personal. The same is also true for robots. In this
book we have created a confluence of these two technologies to use as a basis
for introducing the world of computing to students.
The word personal is key to this new confluence. Computers and robots are
no longer the realm of large corporate offices and industrial manufacturing
scenarios. They have become personal in many ways: they help you write
your term papers, store and organize your photographs, your music collection,
your recipes, and keep you in touch with your friends and family. Many
people might even dismiss the computer as an appliance: like a toaster oven,
or a car. However, as you will learn in this book, a computer is far more
versatile than most appliances. It can be used as an extension of your mind.
We were not kidding above when we mentioned that computers can be used
to process ideas. It is in this form, that a computer becomes an enormously
powerful device regardless of your field of interest. How personal you can
make a computer or a robot is entirely up to you and your abilities to control
these devices. This is where this book comes in. You will learn the basics of
how a computer and a robot is controlled and how you can use these ideas to
personalize your computers even further, limited only by your imagination.
vi
• This book.
• A robot. This book uses the Scribbler robot.
• A Fluke Lancet dongle.
• A Bluetooth enabled computer. If your computer does not have built-
in Bluetooth, you can purchase a USB Bluetooth dongle to add that
functionality. You can use any of the following operating systems:
MACOS (Version 10.4 or later), Windows (XP or Vista), or Linux.
• Software: Python+Myro. This book is based on version 2.4 of Python.
• Some accessories: A basic gamepad controller, Sharpie permanent
color markers, a flashlight, spare AA batteries, poster or any other
large drawing paper, a carrying case, some craft materials for
decorating the robot, etc.
You can order the robot, the Fluke dongle, the Bluetooth dongle, as well as a
software CD, and the book from Georgia Robotics Inc. (georgiarobotics.com).
For more information on additional sources, documentation (including a copy
of this book), and latest updates visit the IPRE web site at roboteducation.org.
While our approach is tightly integrated with the use of a personal robot we
will also take frequent excursions into other forms of computing: numbers,
text, sounds, music, images, etc. The thing to remember is that all the
concepts of computing introduced in this book can be used to do computing
on all kinds of objects.
To get the most out of this book we would recommend reading each chapter
first and then bringing all the ideas discussed in the chapter to life by actually
creating computer programs and robot behaviors. Before proceeding to the
next chapter, try and do most of the exercises at the end of each chapter and
think about further applications that come to mind. Try out a few of those and
then proceed to the next chapter. We would also like to encourage you to
work in an environment where you can share your work and ideas with others
around you. After all, you are going to be creating several robot behaviors.
Find the opportunity to demonstrate your robot’s newly programmed
capabilities to your friends, classmates, and even the wider world (through
web sites like youtube.com). Make learning from this book a social activity
Preface
and you will find yourself learning more. The bottom-line keyword here is
doing. Computing is an abstract concept, but the only way to grasp it is by
doing it. Like that famous Nike commercial, Just do it!
viii
For instructors, it should be clear that the above set of concepts provide
sufficient coverage of the CS1 topics recommended by the latest ACM/IEEE
Curricular guidelines1 as well as the guidelines developed for liberal arts
degrees in computer science2. In many respects the content of the book goes
well beyond the recommended CS1 guidelines. It does not explicitly mention
recursion or sorting algorithms. We have deliberately chosen to omit these
topics. Sorting of lists and other sequential structures is built-in in Python and
students will use these to do sorting. We often find that students discover
recursion in the course of doing exercises from the text. Rather than provide a
separate chapter or a section on recursion, we have left it as a topic to be
introduced by the instructor if she/he so chooses. We do use recursion is
example programs in Chapter 10. It would also be fairly trivial for instructors
to include class discussions of sorting algorithms if they feel so inclined.
Further, for instructors, the coverage and sequence of topics in this book will
vastly differ from that found in most traditional CS1 texts. We have
deliberately taken a contextual approach to introduce ideas. The nature of the
context, robots and computers, has driven the nature, ordering, and
sequencing of topics. We have found that this is a more engaging, exciting,
and enlightening framework. We hope that you will be able to share this
excitement while you are teaching a course based on this material. Further
details on how to use this book and additional materials is provided in the
Instructor’s manual accompanying this text. Much of this work is an outcome
of research conducted under the banner of IPRE specifically for developing a
fresh new approach to CS1. We invite you to refer to our project web site
(roboteducation.org) and read some of the papers and articles that elaborate
much more on the underlying research and its goals.
To students, we have taken efforts to make the material engaging and exciting
for you. We hope that we have succeeded somewhat in this. This is an open
source development project, so we hope that you will take the time to provide
1
Computing Curricula 2001, ACM Journal on Educational Resources in Computing (JERIC)
Vol. 1 , No. 3, Fall 2001.
2
A Model Curriculum for a Liberal Arts Degree in Computer Science, LACS, ACM JERIC, Vol.
7, No. 2, June 2007.
Preface
valuable feedback, as well as ideas and content for further improving this
book. We do hope that you will exploit all the fun learning opportunities
provided in this book.
x
The World of Robots
I wouldn't ever want them to be brought back to Earth. We built them for
Mars, and Mars is where they should stay. But Spirit and Opportunity have
become more than just machines to me. The rovers are our surrogates, our
robotic precursors to a world that, as humans, we're still not quite ready to
visit.
1
Chapter 1
The picture on the opposite page is among one of thousands sent back by
Spirit and Opportunity from the surface of Mars. It goes without saying that it
will probably be several years, decades or even more, before a human ever
sets foot on Mars. The rovers Spirit and Opportunity landed on Mars in
January 2004 as robot geologists whose mission was to analyze rocks and
soils of the red planet in search for clues to past presence of water on the
planet. The two robots were expected to last about 90 days. Years later, they
were still exploring the planet's surface and sending invaluable geological and
pictorial data from the planet.
Back on Earth, the same month as the rovers landing on Mars, the
Tumbleweed robot rover traveled 40 miles across Antarctica’s polar plateau
transmitting local meteorological data back to its base station via satellite.
Besides surviving adverse conditions on mars and Antarctica, robots are
slowly becoming household consumer items. Take for instance, the Roomba
from iRobot Corporation. Introduced in 2002, several million Roombas have
been sold to vacuum and clean floors.
One commonality among the robots mentioned above is that they are all
designed for very specific tasks: analyze rocks and soils on the surface of
Mars, meteorology on the polar cap, or vacuuming a room. Yet, the core of
robot technology is almost as easy to use as computers. In this course you will
be given a personal robot of your own. Through this personal robot, you will
learn to give it instructions to do a variety of tasks. Like the robots mentioned
above your robot is also a rover. However, unlike the robots above, your
personal robot does not come pre-programmed to do any specific task. It has
certain basic capabilities (that you will learn about) and it can be programmed
to make use of its capabilities to do various tasks. We hope that the process of
learning about the capabilities of your robot and making it do different things
will be exciting and fun for you. In this chapter, we introduce you to the world
of robots and then introduce you to your own personal robot and some of its
capabilities.
2
The World of Robots
What is a robot?
1. a machine that looks like a human being and performs various complex acts
(as walking or talking) of a human being; also a similar but fictional machine
whose lack of capacity for human emotions is often emphasized; and also
an efficient insensitive person who functions automatically
2. a device that automatically performs complicated often repetitive tasks
3. a mechanism guided by automatic controls
In today's world, the first two definitions will probably be considered archaic
(the third interpretation in the first definition notwithstanding). Robots were
originally conceived as human-like entities, real or fictional, devoid of
emotions, that performed tasks that were repetitive or full or drudgery.
Today's robots come in all kinds of shapes and sizes and take on all kinds of
tasks (see below for some examples). While many robots are put to use for
repetitive or dull tasks (including the Roomba; unless you enjoy the
therapeutic side effects of vacuuming :-), robots today are capable of doing a
lot more than implied by the first two definitions above. Even in fictional
robots the lack of emotional capacity seems to have been overcome (see for
instance Steven Spielberg’s movie, Artificial Intelligence).
3
Chapter 1
4
The World of Robots
5
Chapter 1
The relationship between robots and computers is the basis for the use of the
phrase automatic controls in describing a robot. Automatically controlling a
robot almost always implies that there is a computer involved. So, in the
process of learning about and playing with robots you will also uncover the
world of computers. Your robot has a computer embedded in it. You will be
controlling the robot through your computer. Moreover, you will do this over
a wireless communication technology called bluetooth. Initially, for our
purposes, learning to automatically control a robot is going to be synonymous
with learning to control a computer. This will become more obvious as we
proceed through these lessons.
Automating control involves specifying, in advance, the set of tasks the robot
or the computer is to perform. This is called programming. Programming
involves the use of a programming language. Today, there are more
programming languages than human languages! Perhaps you have heard of
some of them: Java, C, Python, etc. In this course, we will do all our robot
programming in the programming language Python. Python, named after the
popular Monty Python TV shows, is a modern language that is very easy to
learn and use.
While we are talking about computers and languages, we should also mention
the Myro (for My robot) software system. Myro was developed by us to
simplify the programming of robots. Myro provides a small set of robot
commands that extend the Python language. This makes it easy, as you will
see, to specify automatic controls for robots.
6
The World of Robots
The first few activities show you We would also recommend trying out
how you to set up the computer and some (or all) of the exercises
the robot and will help you get suggested at the end to gain a better
familiarized with your Scribbler. understanding.
This will involve the following four
activities:
You may need the assistance of your instructor for the first activity to ensure
that you know how to set up and use your robot for the remainder of the text.
7
Chapter 1
8
The World of Robots
physical devices that serve as receivers and transmitters. In the Scribbler kit
you received, there is a pair of these Bluetooth devices: one connects into the
scribbler (Fluke Dongle) and the other into the USB port of your computer. If
your computer has a built-in Bluetooth capability, you may not need the one
that goes into your computer. Go ahead and make sure that these devices are
plugged in, the robot is turned on, and so is your computer. Open up the
Bluetooth configuration facility on your computer to get the port number
being used for communication. On Windows this will be something like
COM12 (the actual number will vary). Detailed instructions for setting up the
Bluetooth connection came with your robot. Make sure you have established
the connection and obtained the port number before proceeding.
1. Start Python
2. Connect to the robot
3. Make the robot beep
4. Give the robot a name
Since this is your very first experience with using robots, we will provide
detailed instructions to accomplish the task outlined above.
1. Start Python: When you installed the software, a file called Start
Python.pyw was created. You should copy this file into a folder where you
plan to store all your robot programs. Once done, navigate to that folder and
open it. In it you will find the Start Python icon. Go ahead and double-click
on it. The following window should appear on your computer screen:
9
Chapter 1
What you see above is the Python interaction window or the Python Shell.
This particular shell is called IDLE (notice that it reports above that you are
using IDLE Version 1.1.4.). You will be entering all Python commands in
this IDLE window. The next step is to use Myro to coonnect to the robot.
2. Connect to the robot: Make sure your robot and the computer have their
Bluetooth dongles inserted and that your robot is turned on. To connect to the
robot enter the following command into the Python shell:
This interaction is shown below (the Myro version number will be different):
10
The World of Robots
That is, you have now informed the Python Shell that you will be using the
Myro library. The import statement/command is something you will use each
time you want to control the robot. After issuing the import, some useful
information is printed about Myro and then the Shell is ready for the next
Python command. Now it is time to connect to the robot by issuing the
following command:
>>> initialize("comX")
11
Chapter 1
3. Make the robot beep: In the Python Shell, enter the command:
The command above directs the robot to make a beeping sound at 880 Hertz
for 1 second. Go ahead and try it. Your robot will beep for 1 second at 880
Hz. Go ahead and try the following variations to hear different beeps:
beep(0.5, 880)
beep(0.5, 500)
etc.
12
The World of Robots
So now, you should realize that you are in control of the robot. By issuing
simple commands like the ones above, you can make the robot perform
different behaviors. Now, we can learn the command to give the robot a new
name.
4. Give the robot a name: Suppose we wanted to name the robot Shrek. To
do this, all you have to do it give it the following command:
>>> setName("Shrek")
Whatever name you decide to give your robot, you can specify it in the
command above replacing the words Shrek. From now on, that will be the
name of the robot. How do we know this for a fact? Go ahead and try asking it
its name:
>>> getName()
It will also report than name each time you connect to it using the initialize
command:
>>> initialize("com5")
Waking robot from sleep...
Hello, I'm Shrek!
>>>
Congratulations! You have now completed the first Exercise and you are well
on your way to more fun and exciting things with your robot. Before we move
on, it would be a good idea to review what you just did. Each session with a
robot begins by starting the Python software (Step 1 above), followed by
importing the Myro library and initializing the robot. From then on, you can
issue any command to the robot.
The Myro library contains dozens of commands that enable various kinds of
robot behaviors. In the next few weeks we will be learning several robot
commands and learning how to use them to program complex robot
behaviors. One thing to remember at this juncture is that all commands are
13
Chapter 1
being issued in the Python language. Thus, as you learn more about your
robot and its behaviors, you will also be learning the Python language.
>>> gamepad()
In response to this command, you will get some help text printed in the IDLE
window showing what would happen if you pressed various game pad
buttons. If you look in the picture of the game pad controller above, you will
14
The World of Robots
notice that it has eight (8) blue buttons (numbered 1 through 8 in the picture),
and an axis controller (the big blue swivel button on the left). The axis
controller can be used to move the robot around. Go ahead and try it. Pressing
each of the numbered buttons will result in different behaviors, some will
make the robot beep, some will make the computer speak or say things.
Button#1 will result in the robot taking a picture of whatever it is currently
seeing through its camera and display it on your computer screen. Button#8
will quit from the game pad control mode.
Spend some time experimenting with the various game pad control features.
See how well you can navigate the robot to go to various places, or follow a
wall, or go round and round something (like yourself!). You may also place
the robot on a big piece of paper, insert a Sharpie pen in its pen port and then
move it around to observe its scribbling. Can you scribble your name (or
initials)? Try a pattern or other shapes.
OK, now you are on your own. Start Python, import Myro, connect to the
robot, and give commands to move forward, backward, turn left and right, and
spin. Use the commands: forward(SPEED), backward(SPEED),
turnLeft(SPEED), turnRight(SPEED), and rotate(SPEED). SPEED can be
any number between -1.0...1.0. These and all other robot commands are
detailed in the Myro Reference Manual. This would be a good time to review
the descriptions of all the commands introduced in this section.
Myro Review
15
Chapter 1
initialize(<PORT NAME>)
init(<PORT NAME>)
This command establishes a wireless communication connection with the
robot. <PORT NAME> is determined at the time you configured your software
during installation. It is typically the word com followed by a number. For
example, "com5". The double quotes (") are essential and required.
beep(<TIME>, <FREQUENCY>)
Makes the robot beep for <TIME> seconds at frequency specified by
<FREQUENCY>.
getName()
Returns the name of the robot.
setName(<NEW NAME>)
Sets the name of the robot to <NEW NAME>. The new name should be enclosed
in double quotes, no spaces, and not more than 16 characters long. For
example: setName("Bender").
gamepad()
Enables manual control of several robot functions and can be used to move
the robot around.
Python Review
Start Python.pyw
This is the icon you double-click on to start a Python Shell (IDLE).
>>>
The Python prompt. This is where you type in a Python command.
Note: All commands you type (including the Myro commands listed above)
are essentially Python commands. Later, in this section we will list those
commands that are a part of the Python language.
16
The World of Robots
Exercises
1. Where does the word robot come from? Explore the etymology of the
words robot and robotics and write a short paper about it.
2. What are Asimov's Laws of robotics? Write a viewpoint essay on
them.
3. Look up the Wikipedia entry on robots, as well as the section in AI
Topics (see links above). Write a short essay on the current state of
robots.
4. Write a short essay on a robot (real or fictional) of your choice. Based
on what you have learned from your readings, evaluate its capabilities.
5. Spirit and Opportunity were not the
first rovers to land on Mars. On July 4,
1997, the Mars Pathfinder landed on
Mars with a payload that included the
Sojourner rover. The United States
Postal Service issued the stamp shown
here to commemorate the landing.
This is perhaps the first ever real robot Facsimile of the Mars
to appear on a postage stamp! Find out Pathfinder Postage Stamp
what you can about the Mars
Pathfinder mission and compare the Sojourner rover with Spirit and
Opportunity.
6. Through the exercises, you have experienced a subset of capabilities
of the Scribbler robot. Reflect/write about the physical capabilities of
the Scribbler and the kinds of tasks you could make it perform.
7. Insert a pen (provided in your kit) in the robot's pen port. Place the
robot on a surface where it is OK to write/draw. Drive the robot
around with the game pad controller. It will scribble on the paper as it
moves. Observe its scribbles by moving it forward and then
backwards. Does it trace its path exactly? Why or why not?
8. Using the game pad operation, make your robot Scribble your name on
the floor. You may find this difficult for several reasons. Try to make
the robot write your initials instead. Also, see if you can guide the
robot to draw a five point star. This task is in some sense not too
17
Chapter 1
Further Reading
18
The World of Robots
19
Opposite page: Mars Rover.
Photo courtesy of NASA/JPLCaltech
Personal Robots
Every Pleo is autonomous. Yes, each one begins life as a newly-hatched baby
Camarasaurus, but that's where predictability ends and individuality begins.
Like any creature, Pleo feels hunger and fatigue - offset by powerful urges to
explore and be nurtured. He'll graze, nap and toddle about on his own -when
he feels like it! Pleo dinosaur can change his mind and his mood, just as you
do.
From: www.pleoworld.com
21
Chapter 2
Most people associate the personal computer (aka the PC) revolution with the
1980’s but the idea of a personal computer has been around almost as long as
computers themselves. Today, on most college campuses, there are more
personal computers than people. The goal of One Laptop Per Child (OLPC)
Project is to “provide children around the world with new opportunities to
explore, experiment, and express themselves” (see www.laptop.org). Personal
robots, similarly, were conceived several decades ago. However, the personal
robot ‘revolution’ is still in its infancy. The picture on the previous page
shows the Pleo robots that are designed to emulate behaviors of an infant
Camarasaurus. The Pleos are marketed mainly as toys or as mechatronic
“pets”. Robots these days are being used in a variety of situations to perform a
diverse range of tasks: like mowing a lawn; vacuuming or scrubbing a floor;
entertainment; as companions for elders; etc. The range of applications for
robots today is limited only by our imagination! As an example, scientists in
Japan have developed a baby seal robot (shown on the opposite page) that is
being used for therapeutic purposes for nursing home patients.
Your Scribbler robot is your personal robot. In this case it is being used as an
educational robot to learn about robots and computing. As you have already
seen, your Scribbler is a rover, a robot that moves around. Such robots have
become more prevalent in the last few years and represent a new dimension of
robot applications. Roaming robots have been used for mail delivery in large
offices and as vacuum cleaners in homes. Robots vary in the ways in which
they move about: they can roll about like small vehicles (like the lawn mower,
Roomba, Scribbler, etc.), or even ambulate on two, three, or more legs (e.g.
Pleo). The Scribbler robot moves on three wheels, two of which are powered.
In this chapter, we will get to know the Scribbler in some more detail and also
learn about how to use its commands to control its behavior.
In the last chapter you were able to use the Scribbler robot through Myro to
carry out simple movements. You were able to start the Myro software,
connect to the robot, and then were able to make it beep, give it a name, and
move it around using a joystick. By inserting a pen in the pen port, the
22
Personal Robots
motors(LEFT, RIGHT)
LEFT and RIGHT can be any value in the range [-1.0...1.0] and these values
control the left and right motors, respectively. Specifying a negative value
moves the motors/wheels backwards and positive values move it forward.
Thus, the command:
motors(1.0, 1.0)
will cause the robot to move forward at full speed, and the command:
motors(0.0, 1.0)
will cause the left motor to stop and the right motor to move forward at full
speed resulting in the robot turning left. Thus by giving a combination of left
and right motor values, you can control the robot's movements. Myro has also
23
Chapter 2
provided a set of often used movement commands that are easier to remember
and use. Some of them are listed below:
forward(SPEED)
backward(SPEED)
turnLeft(SPEED)
turnRight(SPEED)
stop()
forward(SPEED, SECONDS)
backward(SPEED, SECONDS)
turnLeft(SPEED, SECONDS)
turnRight(SPEED, SECONDS)
Providing a number for SECONDS in the commands above specifies how long
that command will be carried out. For example, if you wanted to make your
robot traverse a square path, you could issue the following sequence of
commands:
forward(1, 1)
turnLeft(1, .3)
forward(1, 1)
turnLeft(1, .3)
forward(1, 1)
turnLeft(1, .3)
forward(1, 1)
turnLeft(1, .3)
of course, whether you get a square or not will depend on how much the robot
turns in 0.3 seconds. There is no direct way to ask the robot to turn exactly 90
degrees, or to move a certain specified distance (say, 2 ½ feet). We will return
to this later.
You can also use the following movement commands to translate (i.e. move
forward or backward), or rotate (turn right or left):
24
Personal Robots
translate(SPEED)
rotate(SPEED)
move(TRANSLATE_SPEED, ROTATE_SPEED)
You can probably tell from the above list that there are a number of redundant
commands (i.e. several commands can be specified to result in the same
movement). This is by design. You can pick and choose the set of movement
commands that appear most convenient to you. It would be a good idea at this
point to try out these commands on your robot.
Do This: Start Myro, connect to the robot, and try out the following
movement commands on your Scribbler:
First make sure you have sufficient room in front of the robot (place it on the
floor with a few feet of open space in front of it).
>>> motors(1, 1)
>>> motors(0, 0)
Observe the behavior of robot. Specifically, notice if it does (or doesn't) move
in a straight line after issuing the first command. You can make the robot
carry out the same behavior by issuing the following commands:
Go ahead and try these. The behavior should be exactly the same. Next, try
making the robot go backwards using any of the following commands:
25
Chapter 2
motors(-1, -1)
move(-1, 0)
backward(1)
Again, notice the behavior closely. In rovers precise movement, like moving
in a straight line, is difficult to achieve. This is because two independent
motors control the robot's movements. In order to move the robot forward or
backward in a straight line, the two motors would have to issue the exact same
amount of power to both wheels. While this technically feasible, there are
several other factors than can contribute to a mismatch of wheel rotation. For
example, slight differences in the mounting of the wheels, different resistance
from the floor on either side, etc. This is not necessarily a bad or undesirable
thing in these kinds of robots.
Under similar circumstances even Do humans walk straight?
people are unable to move in a
precise straight line. To illustrate Find a long empty hallway and make
this point, you can try the sure you have a friend with you to help
experiment shown on right. with this. Stand in the center of the
hallway and mark your spot. Looking
For most people, the above straight ahead, walk about 10‐15 paces
experiment will result in a variable without looking at the floor. Stop,
movement. Unless you really
mark your spot and see if you walked
concentrate hard on walking in a
in a straight line.
straight line, you are most likely to
display similar variability as your Next, go back to the original starting
Scribbler. Walking in a straight
spot and do the same exercise with
line requires constant feedback
and adjustment, something your eyes closed. Make sure your
humans are quite adept at doing. friend is there to warn you in case you
This is hard for robots to do. are about to run into an object or a
Luckily, roving does not require wall. Again, note your spot and see if
such precise moments anyway. you walked in a straight line.
Do This: Review all of the other movement commands listed above and try
them out on your Scribbler. Again, note the behavior of the robot from each of
these commands. In doing this activity, you may find yourself repeatedly
26
Personal Robots
The first line defines the name of the new command/function to be yoyo. The
lines that follow are slightly indented and contain the commands that make up
the yoyo behavior. That is, to act like a yoyo, move forward and then
backward and then stop. The indentation is important and is part of the Python
27
Chapter 2
syntax. It ensures that all indented commands are part of the definition of the
new command. We will have more to say about this later.
Once the new command has been defined, you can try it by entering the
command into IDLE as shown below:
>>> yoyo()
Do This: If you have your Scribbler ready, go ahead and try out the new
definition above by first connecting to the robot, and then entering the
definition above. You will notice that as soon as you type the first line, IDLE
automatically indents the next line(s). After entering the last line hit an extra
RETURN to end the definition. This defines the new command in Python.
Observe the robot's behavior when you give it the yoyo() command. You
may need to repeat the command several times. The robot momentarily moves
and then stops. If you look closely, you will notice that it does move forward
and backwards.
In Python, you can define new functions by using the def syntax as shown
above. Note also that defining a new function doesn't mean that the
commands that make up the function get carried out. You have to explicitly
issue the command to do this. This is useful because it gives you the ability to
use the function over and over again (as you did above). Issuing the new
function like this in Python is called, invocation. Upon invocation, all the
commands that make up the function's definition are executed in the sequence
in which they are listed in the definition.
28
Personal Robots
How can we make the robot's yoyo And now for something
behavior more pronounced? That is, completely different
make it move forward for, say 1 second,
and then backwards for 1 second, and
then stop? You can use the SECONDS
option in forward and backward
movement commands as shown below:
wait(SECONDS)
29
Chapter 2
Take a look at the definition of the yoyo function above and you will notice
the use of parentheses, (), both when defining the function as well as when
using it. You have also used other functions earlier with parentheses in them
and probably can guess their purpose. Commands or functions can specify
certain parameters (or values) by placing them within parentheses. For
example, all of the movement commands, with the exception of stop have
one or more numbers that you specify to indicate the speed of the movement.
The number of seconds you want the robot to wait can be specified as a
parameter in the invocation of the wait command. Similarly, you could have
chosen to specify the speed of the forward and backward movement in the
yoyo command, or the amount of time to wait. Below, we show three
definitions of the yoyo command that make use of parameters:
30
Personal Robots
In the first definition, yoyo1, we specify the speed of the forward or backward
movement as a parameter. Using this definition, you can control the speed of
movement with each invocation. For example, if you wanted to move at half
speed, you can issue the command:
>>> yoyo1(0.5)
As you can imagine, while working with different behaviors for the robot, you
are likely to end up with a large collection of new functions. It would make
sense then that you do not have to type in the definitions over and over again.
Python enables you to define new functions and store them in files in a folder
on your computer. Each such file is called a module and can then be easily
used over and over again. Let us illustrate this by defining two behaviors: a
parameterized yoyo behavior and a wiggle behavior that makes the robot
wiggle left and right. The two definitions are given below:
31
Chapter 2
# File: moves.py
# Purpose: Two useful robot commands to try out as a module.
All lines beginning with a '#' sign are called comments. These are simply
annotations that help us understand and document the programs in Python.
You can place these comments anywhere, including right after a command.
The # sign clearly marks the beginning of the comment and anything
following it on that line is not interpreted as a command by the computer.
This is quite useful and we will make liberal use of comments in all our
programs.
Notice that we have added the import and the init commands at the top. The
init command will always prompt you to enter the com-port number.
Do This: To store the yoyo and wiggle behaviors as a module in a file, you
can ask IDLE for a New Window from the File menu. Next enter the text
containing the two definitions and then save them in a file (let’s call it
moves.py) in your Myro folder (same place you have the Start Python
32
Personal Robots
icon). All Python modules end with the filename extension .py and you
should make sure they are always saved in the same folder as the Start
Python.pyw file. This will make it easy for you as well as IDLE to locate
your modules when you use them.
Once you have created the file, there are two ways you can use it. In IDLE,
just enter the command:
and then try out any of the two commands. For example, the following shows
how to use the yoyo function after importing the moves module:
As you can see from above, accessing the commands defined in a module is
similar to accessing the capabilities of the myro module. This is a nice feature
of Python. In Python, you are encouraged to extend the capabilities of any
system by defining your own functions, storing them in modules and then
using them by importing them. Thus importing from the moves module is no
different that importing from the myro module. In general, the Python import
33
Chapter 2
command has two features that it specifies: the module name; and what is
being imported from it. The precise syntax is described below:
where <MODULE NAME> is the name of the module you are importing from, and
<SOMETHING> specifies the commands/capabilities you are importing. By
specifying a * for <SOMETHING> you are importing everything defined in the
module. We will return to this a little later in the course. But at the moment,
realize that by saying:
you are importing everything defined in the myro module. Everything defined
in this module is listed and documented in the Myro Reference Manual. The
nice thing that this facility provides is that you can now define your own set
of commands that extend the basic commands available in Myro to customize
the behavior of your robot. We will be making use of this over and over again
in this course.
Now that you have learned how to define new commands using existing ones,
it is time to discuss a little more Python. The basic syntax for defining a
Python function takes the form:
That is, to define a new function, start by using the word def followed by the
name of the function (<FUCTION NAME>) followed by <PARAMETERS> enclosed
in parenthesis followed by a colon (:). This line is followed by the commands
that make up the function definition (<SOMETHING>...<SOMETHING>). Each
command is to be placed on a separate line, and all lines that make up the
34
Personal Robots
It reports that there is a syntax error and it highlights the error location by
placing the thick red cursor (see the third line of the definition). This is
because Python strictly enforces the indentation rule described above. The
second definition, however, is acceptable. For two reasons: indentation is
consistent; and commands on the same line can be entered separated by a
semi-colon (;). We would recommend that you continue to enter each
command on a separate line and defer from using the semi-colon as a
separator until you are more comfortable with Python. More importantly, you
35
Chapter 2
will notice that IDLE helps you in making your indentations consistent by
automatically indenting the next line, if needed.
Another feature built into IDLE that enables readability of Python programs is
the use of color highlighting. Notice in the above examples (where we use
screen shots from IDLE) that pieces of your program appear in different
colors. For example, the word def in a function definition appears in red, the
name of your function, yoyo appears in blue. Other colors are also used in
different situations, look out for them. IDLE displays all Python words (like
def) in red and all names defined by you (like yoyo) in blue.
>>> dance()
Do This: Go ahead and add the dance function to your moves.py module.
Try the dance command on the robot. Now you have a very simple behavior
that makes the robot do a little shuffle dance.
36
Personal Robots
Summary
In this chapter, you have learned several commands that make a robot move in
different ways. You also learned how to define new commands by defining
new Python functions. Functions serve as basic building blocks in computing
and defining new and more complex robot behaviors. Python has specific
syntax rules for writing definitions. You also learned how to save all your
function definitions in a file and then using them as a module by importing
from it. While you have learned some very simple robot commands, you have
also learned some important concepts in computing that enable the building of
more complex behaviors. While the concepts themselves are simple enough,
they represent a very powerful and fundamental mechanism employed in
almost all software development. In later chapters, we will provide more
details about writing functions and also how to structure parameters that
customize individual function invocations. Make sure you do some or all of
the exercises in this chapter to review these concepts.
37
Chapter 2
Myro Review
backward(SPEED)
Move backwards at SPEED (value in the range -1.0…1.0).
backward(SPEED,SECONDS)
Move backwards at SPEED (value in the range -1.0…1.0) for a time given in
SECONDS, then stop.
forward(SPEED)
Move forward at SPEED (value in the range -1.0..1.0).
forward(SPEED,TIME)
Move forward at SPEED (value in the range -1.0…1.0) for a time given in
seconds, then stop.
motors(LEFT,RIGHT)
Turn the left motor at LEFT speed and right motor at RIGHT speed (value in the
range -1.0…1.0).
move(TRANSLATE, ROTATE)
Move at the TRANSLATE and ROTATE speeds (value in the range -1.0…1.0).
rotate(SPEED)
Rotates at SPEED (value in the range -1.0…1.0). Negative values rotate right
(clockwise) and positive values rotate left (counter-clockwise).
stop()
Stops the robot.
translate(SPEED)
Move in a straight line at SPEED (value in the range -1.0…1.0). Negative
values specify backward movement and positive values specify forward
movement.
turnLeft(SPEED)
Turn left at SPEED (value in the range -1.0…1.0)
38
Personal Robots
turnLeft(SPEED,SECONDS)
Turn left at SPEED (value in the range -1.0..1.0) for a time given in seconds,
then stops.
turnRight(SPEED)
Turn right at SPEED (value in the range -1.0..1.0)
turnRight(SPEED,SECONDS)
Turn right at SPEED (value in the range -1.0..1.0) for a time given in seconds,
then stops.
wait(TIME)
Pause for the given amount of TIME seconds. TIME can be a decimal number.
Python Review
def <FUNCTION NAME>(<PARAMETERS>):
<SOMETHING>
...
<SOMETHING>
Defines a new function named <FUNCTION NAME>. A function name should
always begin with a letter and can be followed by any sequence of letters,
numbers, or underscores (_), and not contain any spaces. Try to choose names
that appropriately describe the function being defined.
Exercises
39
Chapter 2
2. Insert a pen in the scribbler's pen port and then issue it command to go
forward for 1 or more seconds and then backwards for the same amount. Does
the robot travel the same distance? Does it traverse the same trajectory?
Record your observations.
3. Measure the length of the line drawn by the robot in Exercise 2. Write a
function travel(DISTANCE) to make the robot travel the given DISTANCE.
You may use inches or centimeters as your units. Test the function on the
robot a few times to see how accurate the line is.
5. Generalize the wait time obtained in Exercise 3 and write a function called
degreeTurn(DEGREES). Each time it is called, it will make the robot turn the
specified degrees. Use this function to write a set of instructions to draw a
square.
6. Using the functions travel and degreeTurn, write a function to draw the
Bluetooth logo (See Chapter 1, Exercise 9).
7. Choreograph a simple dance routine for your robot and define functions to
carry it out. Make sure you divide the tasks into re-usable moves and as much
40
Personal Robots
8. Record a video of your robot dance and then dub it with a soundtrack of
your choosing. Use whatever video editing software accessible to you. Post
the video online on sites like YouTube to share with friends.
9. Lawn mower robots and even vacuuming robots can use specific
choreographed movements to ensure that they provide full coverage of the
area to be serviced. Assuming that the area to be mowed or cleaned is
rectangular and without any obstructions, can you design a behavior for your
Scribbler to provide full coverage of the area? Describe it in writing. [Hint:
Think about how you would mow/vacuum yourself.]
41
Opposite page: Mars Rover.
Photo courtesy of NASA/JPLCaltech
Building Robot Brains
43
Chapter 3
If you think of your robot as a creature that acts in the world, then by
programming it, you are essentially building the creature's brain. The power
of computers lies in the fact that the same computer or the robot can be
supplied a different program or brain to make it behave like a different
creature. For example, a program like Firefox or Explorer makes your
computer behave like a web browser. But switching to your Media Player, the
computer behaves as a DVD or a CD player. Similarly, your robot will behave
differently depending upon the instructions in the program that you have
requested to run on it. In this chapter we will learn about the structure of
Python programs and how you can organize different robot behaviors as
programs.
The world of robots and computers, as you have seen so far is intricately
connected. You have been using a computer to connect to your robot and then
controlling it by giving it commands. Most of the commands you have used so
far come from the Myro library which is specially written for easily
controlling robots. The programming language we are using to do the robot
programming is Python. Python is a general purpose programming language.
By that we mean that one can use Python to write software to control the
computer or another device like a robot through that computer. Thus, by
learning to write robot programs you are also learning how to program
computers. Our journey into the world of robots is therefore intricately tied up
with the world of computers and computing. We will continue to interweave
concepts related to robots and computers throughout this journey. In this
chapter, we will learn more about robot and computer programs and their
structure.
The basic structure of a Python program (or a robot brain) is shown below:
def main():
<do something>
<do something>
...
44
Building Robot Brains
This is essentially the same as defining a new function. In fact, here, we are
adopting a convention that all our programs that represent robot brains will be
called main. In general, the structure of your robot programs will be as shown
below (we have provided line numbers so we can refer to them):
Line 9: main()
Every robot brain program will begin with the first two lines (Line 1 and
Line 2). These, as you have already seen, import the Myro library and
establish a connection with the robot. In case you are using any other libraries,
you will then import them (this is shown in Line 3). This is followed by the
definitions of functions (Line 4), and then the definition of the function,
main. Finally, the last line (Line 9) is an invocation of the function main.
This is placed so that when you load this program into the Python Shell the
program will start executing. In order to illustrate this, let us write a robot
program that makes it do a short dance using the yoyo and wiggle
movements defined in the last chapter.
# File: dance.py
# Purpose: A simple dance routine
45
Chapter 3
forward(speed, waitTime)
backward(speed, waitTime)
main()
We have used a new Python command in the definition of the main function:
the print command. This command will print out the text enclosed in double
quotes (") when you run the program. This program is not much different
from the dance function defined in the previous chapter except we are using a
spin motion to wiggle. However, instead of naming the function dance we are
calling it main. As we mentioned earlier, this is just a naming convention that
we are adopting that makes it easy to identify the main program in a program
file.
Do This: In order to run this program on the robot, you can start IDLE, create
a new window, enter the program in it, save it as a file (dance.py) and then
select the Run Module feature in the window's Run menu. Alternately, to run
this program, you can enter the following command in the Python Shell:
46
Building Robot Brains
routine specified in the main program. Also notice the two messages printed
in the IDLE window. These are the results of the print command. print is a
very useful command in Python and can be used to output essentially anything
you ask it to. While you are in this session, go ahead and change the print
command to the following:
speak is a Myro command that enables speech output from your computer.
Go ahead and change the other print command also to the speak command
and try your program. Once done, enter some other speak commands on the
IDLE prompt. For example:
The speech facility is built into most computers these days. Later we will see
how you can find out what other voices are available and also how to change
to them.
Speaking Pythonese
We have launched you into the world of computers and robots without really
giving you a formal introduction to the Python language. In this section, we
provide more details about the language. What you know about Python so far
is that it is needed to control the robot. The robot commands you type are
integrated into Python by way of the Myro library. Python comes with several
other useful libraries or modules that we will try and learn in this course. If
you need to access the commands provided by a library, all you have to do is
import them.
The libraries themselves are largely made up of sets of functions (they can
contain other entities but more on that later). Functions provide the basic
building blocks for any program. Typically, a programming language (and
Python is no exception) includes a set of pre-defined functions and a
mechanism for defining additional functions. In the case of Python, it is the
47
Chapter 3
def construct. You have already seen several examples of function definitions
and indeed have written some of your own by now. In the def construct, when
defining a new function, you have to give the new function a name. Names
are a critical component of programming and Python has rules about what
forms a name.
What’s in a name?
A name in Python must begin with either an alphabetic letter (a-z or A-Z) or
the underscore (i.e. _) and can be followed by any sequence of letters, digits,
or underscore letters. For example,
iRobot
myRobot
jitterBug
jitterBug2
my2cents
my_2_cents
are all examples of valid Python names. Additionally, another important part
of the syntax of names is that Python is case sensitive. That is the names
myRobot and MyRobot and myrobot are distinct names as far as Python is
concerned. Once you name something a particular way, you have to
consistently use that exact case and spelling from then on. Well, so much
about the syntax of names, the bigger question you may be asking is what
kinds of things can (or should) be named?'
So far, you have seen that names can be used to represent functions. That is,
what a robot does each time you use a function name (like yoyo) is specified
in the definition of that function. Thus, by giving functions a name you have a
way of defining new functions. Names can also be used to represent other
things in a program. For instance, you may want to represent a quantity, like
speed or time by a name. In fact, you did so in defining the function yoyo
which is also shown below:
48
Building Robot Brains
Functions can take parameters that help customize what they do. In the above
example, you can issue the following two commands:
The first command is asking to perform the yoyo behavior at speed 0.8 for 2.5
seconds where as the second one is specifying 0.3 and 1.5 for speed and time,
respectively. Thus, by parameterizing the function with those two values, you
are able to produce similar but varying outcomes. This idea is similar to the
idea of mathematical functions: sine(x) for example, computes the sine of
whatever value you supply for x. However, there has to be a way of defining
the function in the first place that makes it independent of specific parameter
values. That is where names come in. In the definition of the function yoyo
you have named two parameters (the order you list them is important): speed
and waitTime. Then you have used those names to specify the behavior that
makes up that function. That is the commands forward, and backward use the
names speed and waitTime to specify whatever the speed and wait times are
included in the function invocation. Thus, the names speed and waitTime
represent or designate specific values in this Python program.
Names in Python can represent functions as well as values. What names you
use is entirely up to you. It is a good idea to pick names that are easy to read,
type, and also appropriately designate the entity they represent. What name
you pick to designate a function or value in your program is very important,
for you. For example, it would make sense if you named a function
turnRight so that when invoked, the robot turned right. It would not make
any sense if the robot actually turned left instead, or worse yet, did the
equivalent of the yoyo dance. But maintaining this kind of semantic
consistency is entirely up to you.
49
Chapter 3
Values
In the last section we saw that names can designate functions as well as
values. While the importance of naming functions may be obvious to you by
now, designating values by names is an even more important feature of
programming. By naming values, we can create names that represent specific
values, like the speed of a robot, or the average high temperature in the month
of December on top of the Materhorn in Switzerland, or the current value of
the Dow Jones Stock Index, or the name of your robot, etc. Names that
designate values are also called variables. Python provides a simple
mechanism for designating values with names:
speed = 0.75
aveHighTemp = 37
DowIndex = 12548.30
myFavoriteRobot = "C3PO"
You should read the above statement as: Let the variable named by
<variable name> be assigned the value that is the result of calculating the
expression <expression>. So what is an <expression>? Here are some
examples:
>>> 5
5
>>> 5 + 3
8
>>> 3 * 4
12
>>> 3.2 + 4.7
7.9
>>> 10 / 2
5
50
Building Robot Brains
What you type at the Python prompt (>>>) is actually called an expression.
The simplest expression you can type is a number (as shown above). A
number evaluates to itself. That is, a 5 is a 5, as it should be! And 5 + 3 is 8.
As you can see when you enter an expression, Python evaluates it and then
outputs the result. Also, addition (+), subtraction (-), multiplication (*), and
division (/) can be used on numbers to form expressions that involve
numbers.
You may have also noticed that numbers can be written as whole numbers (3,
5, 10, 1655673, etc) or with decimal points (3.2, 0.5, etc) in them. Python (and
most computer languages) distinguishes between them. Whole numbers are
called integers and those with decimal points in them are called floating point
numbers. While the arithmetic operations are defined on both kinds of
numbers, there are some differences you should be aware of. Look at the
examples below:
>>> 10.0/3.0
3.3333333333333335
>>> 10/3
3
>>> 1/2
0
>>> 1.0/2
0.5
When you divide a floating point number by another floating point number,
you get a floating point result. However, when you divide an integer by
another integer, you get an integer result. Thus, in the examples above, you
get the result 3.3333333333333335 when you divide 10.0 by 3.0, but you get
3 when you divide 10 by 3. Knowing this, the result of dividing 1 by 2 (see
above) is zero (0) should not be surprising. That is, while the division
operation looks the same (/), it treats integers differently than floating point
values. However, if at least one of the numbers in an arithmetic operation is a
floating point number, Python will give you a floating point result (see last
example above). You should keep this in mind. More on numbers later, before
we get back to robots, let us quickly introduce you to strings.
51
Chapter 3
>>> yourSchool+mySchool
'Georgia Institute of TechnologyBryn Mawr College'
Pay special attention to the last two examples. The operation + is defined on
strings and it results in concatenating the two strings. The print command is
followed by zero or more Python expressions, separated by commas. print
evaluates all the expressions and prints out the results on the screen. As you
have also seen before, this is a convenient way to print out results or messages
from your program.
52
Building Robot Brains
A Calculating Program
Ok, set your robot aside for just a few more minutes. You have now also
learned enough Python to write programs that perform simple, yet interesting,
calculations. Here is a simple problem:
>>> 6650000000*1.14/100.0
75810000.0
>>> 75810000.0/365.0
207131.1475409836
That is, in this year there will be an increase of 75.81 million in the world’s
population which implies an average daily increase of over 207 thousand
people). So now you know the answer!
Also, let us try and write a program to do the above calculations. A program
to do the calculation is obviously going to be a bit of overkill. Why do all the
extra work when we already know the answer? Small steps are needed to get
to higher places. So let’s indulge and see how you would write a Python
program to do this. Below, we give you one version:
53
Chapter 3
#File: worldPop.py
# Purpose:
# Estimate the world population growth in a year and
# also per day.
# Given that on January 1, 2008 the world's population was
# estimated at 6,650,000,000 and the estimated growth is
# at the rate of +1.14%
def main():
population = 6650000000
growthRate = 1.14/100.0
main()
The program follows the same structure and conventions we discussed above.
In this program, we are not using any libraries (we do not need any). We have
defined variables with names population, and growthRate to designate the
values given in the problem description. We also defined the variables
grothInOneYear and growthInADay and use them to designate the results
of the calculations. First, in the main program we assign the values given,
followed by performing the calculation. Finally, we use the print commands
to print out the result of the computations.
Do This: Start Python, enter the program, and run it (just as you would run
your robot programs) and observe the results. Voila! You are now well on
your way to also learning the basic techniques in computing! In this simple
program, we did not import anything, nor did we feel the need to define any
functions. But this was a trivial program. However, it should serve to
convince you that writing programs to do computation is essentially the same
as controlling a robot.
54
Building Robot Brains
55
Chapter 3
#File: worldPop.py
# Purpose:
# Estimate the world population growth in a year and
# also per day.
# Given that on Jnauray 1, 2008 the world's population was
# estimated at 6,650,000,000 and the estimated growth is
# at the rate of +1.14%
def main():
# print out the preamble
# output results
print "World population today is", population
print "In one year, it will grow by", growthInOneYear
print "An average daily increase of", growthInADay
main()
Read the program above carefully. Notice that we have added additional
comments as well as print statements. This improves the overall readability as
well as the interaction of this program. Notice the use of the input statements
above. The basic syntax of input is shown below:
That is, the input is a function whose parameter is a string and the value it
returns is the value of the expression that will be entered by the user. When
executed, the computer will print out the prompt and wait for the user to enter
a Python expression. The user can enter whatever expression in response to
56
Building Robot Brains
the prompt and then hit the RETURN or ENTER key. The expression is then
evaluated by Python and the resulting value is returned by the input function.
That value is then assigned to the variable <variable name>. The statement
above uses the same syntax as the assignment statement described above.
Python has made obtaining input from a user easy by defining input as a
function. Now, look at the use of the input function in the program above.
With this modification, we now have a more general program which can be
run again and again. Below, we show two sample runs:
Notice how you can re-run the program by just typing the name of the
main()function. There are other ways of obtaining input in Python. We will
see those a little later.
Robot Brains
One characteristic that will distinguish robot programs from those that just do
computations is in the amount of time it will take to run a program. Typically,
a program that only performs some computation will terminate as soon as the
57
Chapter 3
computation is completed. However, it will be the case that most of the time
your robot program will require the robot to perform some task over and over
again. Here then, is an interesting question to ask:
Question How much time would it take for a vacuuming robot to vacuum a
16ft X 12ft room?
Seemingly trivial question but if you think about it a little more, you may
reveal some deeper issues. If the room does not have any obstacles in it (i.e.
an empty room), the robot may plan to vacuum the room by starting from one
corner and then going along the entire length of the long wall, then turning
around slightly away from the wall, and traveling to the other end. In this
manner, it will ultimately reach the other side of the room in a systematic way
and then it could stop when it reaches the last corner. This is similar to the
way one would mow a flat oblong lawn, or even harvest a field of crop, or re-
ice an ice hockey rink using a Zamboni machine. To answer the question
posed above all you have to do is calculate the total distance travelled and the
average speed of the vacuum robot and use the two to compute the estimated
time it would take. However, what if the room has furniture and other objects
in it?
You might try and modify the approach for vacuuming outlined above but
then there would be no guarantee that the floor would be completely
vacuumed. You might be tempted to redesign the vacuuming strategy to allow
for random movements and then estimate (based on average speed of the
robot) that after some generous amount of time, you can be assured that the
room would be completely cleaned. It is well known (and we will see this
more formally in a later chapter) that random movements over a long period
of time do end up providing uniform and almost complete coverage.
Inherently this also implies that the same spot may very well end up being
vacuumed several times (which is not necessarily a bad thing!). This is similar
to the thinking that a herd of sheep, if left grazing on a hill, will result, after a
period of time, in a nearly uniform grass height (think of the beautiful hills in
Wales).
58
Building Robot Brains
On the more practical side, iRobot's Roomba robot uses a more advanced
strategy (though it is time based) to ensure that it provides complete coverage.
A more interesting (and important) question one could ask would be:
Question: How does a vacuuming robot know that it is done cleaning the
room?
So far, you have programmed very simple robot behaviors. Each behavior
which is defined by a function, when invoked, makes the robot do something
for a fixed amount of time. For example, the yoyo behavior from the last
chapter when invoked as:
>>> yoyo(0.5, 1)
the robot would move for a total of 11 seconds. Similarly, the dance behavior
defined in the previous chapter will last a total of six seconds. Thus, the total
behavior of a robot is directly dependent upon the time it would take to
execute all the commands that make up the behavior. Knowing how long a
behavior will take can help in pre-programming the total amount of time the
overall behavior could last. For example, if you wanted the robot to perform
the dance moves for 60 seconds, you can repeat the dance behavior ten times.
You can do this by simply issuing the dance command 10 times. But that gets
tedious for us to have to repeat the same commands so many times.
Computers are designed to do repetitious tasks. In fact, repetition is one of the
59
Chapter 3
If you wanted to repeat the dance behavior 10 times, all you have to do is:
for i in range(10):
dance()
The loop specification begins with the keyword for which is followed by a
<variable> and then the keyword in and a <sequence> followed by a colon
(:). This line sets up the number of times the repetition will be repeated. What
follows is a set of statements, indented (again, indentation is important), that
are called a block that forms the body of the loop (stuff that is repeated).
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
60
Building Robot Brains
for i in range(10):
dance()
will take on the values 0 through 9 and for each of those values it will execute
the dance() command.
Do This: Let us try this out on the robot. Modify the robot program from the
start of this chapter to include the dance function and then write a main
program to use the loop above.
# File: dance.py
# Purpose: A simple dance routine
def dance():
yoyo(0.5, 0.5)
yoyo(0.5, 0.5)
wiggle(0.5, 1)
wiggle(0.5, 1)
61
Chapter 3
print "...Done"
IDLE Tip
main()
You can stop a program at any time by
Notice that we have used hitting the CTRL‐C keys (pronounced as
danceStep (a more meaningful Control‐see). That is, pressing the
name than i) to represent the CTRL‐key and then at the same time
loop index variable. When you pressing the c‐key.
run this program, the robot
should perform the dance routine In the case of a robot program this will
ten times. Modify the value also stop the robot.
specified in the range command
to try out some more steps. If you end up specifying a really large value,
remember that for each value of danceStep the robot will do something for 6
seconds. Thus, if you specified 100 repetitions, the robot will run for 10
minutes.
while timeRemaining(10):
<do something>
<do something>
...
The above commands will be repeated for 10 seconds. Thus, if you wanted
the computer to say “Doh!” for 5 seconds, you can write:
62
Building Robot Brains
while timeRemaining(5):
speak("Doh!", 0)
In writing robot programs there will also be times when you just want the
robot to keep doing its behaviors forever! While technically by forever we do
mean eternity in reality what is likely to happen is either it runs out of
batteries, or you decide to stop it (by hitting CTRL-C). The Python command
to specify this uses a different loop statement, called a while-loop that can be
written as:
while True:
<do something>
<do something>
...
True is also a value in Python (along with False) about which we will learn
more a little later. For now, it would suffice for us to say that the above loop
is specifying that the body of the loop be executed forever!
That is, repeatedly add the increase in population, based on growth rate, ten
times.
63
Chapter 3
(Google: “world population growth” to get latest numbers). Can you estimate
when the world population will become 9 billion?
Summary
This chapter introduced the basic structure of Python (and robot) programs.
We also learned about names and values in Python. Names can be used to
designate functions and values. The latter are also called variables. Python
provides several different types of values: integers, floating point numbers,
strings, and also boolean values (True and False). Most values have built-in
operations (like addition, subtration, etc.) that perform calculations on them.
Also, one can form sequences of values using lists. Python provides simple
built-in facilities for obtaining input from the user. All of these enable us to
write not only robot programs but also programs that perform any kind of
computation. Repetition is a central and perhaps the most useful concept in
computing. In Python you can specify repetition using either a for-loop or a
while-loop. The latter are useful in writing general robot brain programs. In
later chapters, we will learn how to write more sophisticated robot behaviors.
Myro Review
speak(<something>)
The computer converts the text in <something> to speech and speaks it out.
<something> is also simultaneously printed on the screen. Speech generation
is done synchronously. That is, anything following the speak command is
done only after the entire thing is spoken.
speak(<something>, 0)
The computer converts the text in <something> to speech and speaks it out.
<something> is also simultaneously printed on the screen. Speech generation
is done asynchronously. That is, execution of subsequent commands can be
done prior to the text being spoken.
timeRemaining(<seconds>)
This is used to specify timed repetitions in a while-loop (see below).
64
Building Robot Brains
Python Review
Values
Values in Python can be numbers (integers or floating point numbers) or
strings. Each type of value can be used in an expression by itself or using a
combination of operations defined for that type (for example, +, -, *, /, % for
numbers). Strings are considered sequences of characters (or letters).
Names
A name in Python must begin with either an alphabetic letter (a-z or A-Z) or
the underscore (i.e. _) and can be followed by any sequence of letters, digits,
or underscore letters.
input(<prompt string>)
This function prints out <prompt string> in the IDLE window and waits for
the user to enter a Python expression. The expression is evaluated and its
result is returned as a value of the input function.
main()
This is the basic structure of a robot control program in Python. Without the
first two lines, it is the basic structure of all Python programs.
65
Chapter 3
range(10)
Generates a sequence, a list, of numbers from 0..9. There are other, more
general, versions of this function. These are shown below.
range(n1, n2)
Generates a list of numbers starting from n1…(n2-1). For example,
range(5, 10) will generate the list of numbers [5, 6, 7, 8, 9].
Repetition
while timeRemaining(<seconds>):
<do something>
<do something>
...
while True:
<do something>
<do something>
...
These are different ways of doing repetition in Python. The first version will
assign <variable> successive values in <sequence> and carry out the body
once for each such value. The second version will carry out the body for
<seconds> amount of time. timeRemaining is a Myro function (see above).
The last version specifies an un-ending repetition.
66
Building Robot Brains
Exercises
4. Modify the version of the dance program above that uses a for-loop to use
the following loop:
That is, you can actually use a list itself to specify the repetition (and
successive values the loop variable will take). Try it again with the lists [3,
2, 6], or [3.5, 7.2, 1.45], or [“United”, “States”, “of”,
“America”]. Also try replacing the list above with the string “ABC”.
Remember, strings are also sequences in Python. We will learn more about
lists later.
5. Run the world population program (any version from the chapter) and when
it prompts for input, try entering the following and observe the behavior of the
program. Also, given what you have learned in this chapter, try and explain
the resulting behavior.
67
Chapter 3
6. Use the values 9000000000, and 1.42 as input values as above. Except,
when it asks for various values, enter them in any order. What happens?
7. Using the same values as above, instead of entering the value, say
9000000000, enter 6000000000+3000000000, or 450000000*2, etc. Do you
notice any differences in output?
8. For any of the values to be input, replace them with a string. For instance
enter "Al Gore" when it prompts you for a number. What happens?
9. Rewrite your solution to Exercise 4 from the previous chapter to use the
program structure described above.
10. You were introduced to the rules of naming in Python. You may have
noticed that we have made extensive use of mixed case in naming some
entities. For example, waitTime. There are several naming conventions used
by programmers and that has led to an interesting culture in of itself. Look up
the phrase CamelCase controversy in your favorite search engine to learn
about naming conventions. For an interesting article on this, see The
Semicolon Wars (www.americanscientist.org/issues/pub/the-semicolon-wars).
11. Experiment with the speak function introduced in this chapter. Try giving
it a number to speak (try both integers and floating point numbers). What is
the largest integer value that it can speak? What happens when this limit is
exceeded? Try to give the speak function a list of numbers, or strings, or
both.
12. Write a Python program that sings the ABC song: ABCD…XYZ. Now I
know my ABC’s. Next time won’t you sing with me?
68
Building Robot Brains
69
Opposite page: Mars Rover.
Photo courtesy of NASA/JPLCaltech
Sensing From Within
71
Chapter 4
Cole Sear in Shyamalan's Sixth Sense is not referring to dead bodies lying in
front of him (for those who have not seen the movie). The five senses that
most humans relate to are: touch, vision, balance, hearing, and taste or smell.
In all cases our bodies have special sensory receptors that are placed on
various parts of the body to enable sensing. For example the taste receptors
are concentrated mostly on the tongue; the touch receptors are most sensitive
on hands and the face and least on the back and on limbs although they are
present all over the body, etc. Besides the difference in the physiology of each
kind of receptors there are also different neuronal pathways and thereby
sensing mechanisms built into our bodies. Functionally, we can say that each
type of sensory system starts with the receptors which convert the thing they
sense into electrochemical signals that are transmitted over neurons. Many of
these pathways lead to the cerebral cortex in the brain where they are further
processed (like, "Whoa, that jalapeno is hot!!"). The perceptual system of an
organism refers to the set of sensory receptors, the neuronal pathways, and the
processing of perceptual information
in the brain. The brain is capable of
combining sensory information from Proprioception
different receptors to create richer Sensing from within
experiences than those facilitated by
the individual receptors. Get something really delicious to eat,
like a cookie, or a piece of chocolate,
The perceptual system of any or candy (whatever you fancy!). Hold
organism includes a set of external it in your right hand, and let your
sensors (also called exteroceptors) right arm hang naturally on your
and some internal sensing side. Now close your eyes, real tight,
mechanisms (interoceptors or and try to eat the thing you are
proprioception). Can you touch your holding. Piece of cake! (well,
belly button in the dark? This is whatever you picked to eat :‐)
because of proprioception. Your
body's sensory system also keeps Without fail, you were able to pick it
up and bring it to your mouth, right?
track of the internal state of your
body parts, how they are oriented,
Give yourself a Snickers moment and
etc.
enjoy the treat.
72
Sensing From Within
The Scribbler has three useful internal sensory mechanisms: stall, time, and
battery level. When your program asks the robot to move it doesn’t always
imply that the robot is actually physically moving. It could be stuck against a
wall, for example. The stall sensor in the Scribbler enables you to detect this.
You have already seen how you can use time to control behaviors using the
timeRemaining and wait functions. Also, for most movement commands,
you can specify how long you want that movement to take place (for example
forward(1, 2.5) means full-speed forward for 2.5 seconds). Finally, it is
also possible to detect battery power level so that you can detect when it is
time to change batteries in the robot.
Time
All computers come built-in with an internal clock. In fact, clocks are so
essential to the computers we use today that without them we would not have
73
Chapter 4
computers at all! Your Scribbler robot can use the computer’s clock to sense
time. It is with the help of this clock that we are able to use time in functions
like timeRemaining, wait, and other movement commands. Just with these
facilities it is possible to define interesting automated behaviors.
Do This: Design a robot program for the Scribbler to draw a square (say with
sides of 6 inches). To accomplish this, you will have to experiment with the
movements of the robot and correlate them with time. The two movements
you have to pay attention to are the rate at which the robot moves, when it
moves in a straight line; and the degree of turn with respect to time. You can
write a function for each of these:
def travelStraight(distance):
# Travel in a straight line for distance inches
...
def degreeTurn(angle):
# Spin a total of angle degrees
That is, figure out by experimentation on your own robot (the results will vary
from robot to robot) as to what the correlation is between the distance and the
time for a given type of movement above and then use that to define the two
functions above. For example, if a robot (hypothetical case) seems to travel at
the rate of 25 inches/minute when you issue the command translate(1.0),
then to travel 6 inches you will have to translate for a total of (6*60)/25
seconds. Try moving your robot forward for varying amounts for time at the
same fixed speed. For example try moving the robot forward at speed 0.5 for
3, 4, 5, 6 seconds. Record the distance travelled by the robot for each of those
times. You will notice a lot of variation in the distance even for the same set
of commands. You may want to average those. Given this data, you can
estimate the average amount of time it takes to travel an inch. You can then
define travelStraight as follows:
74
Sensing From Within
def travelStraight(distance):
# set up your robot’s speed
inchesPerSec = <Insert your robot’s value here>
Similarly you can also determine the time required for turning a given number
of degrees. Try turning the robot at the same speed for varying amounts of
time. Experiment how long it takes the robot to turn 360 degrees, 720 degrees,
etc. Again, average the data you collect to get the number of degrees per
second. Once you have figured out the details use them to write the
degreeTurn function. Then use the following main program:
def main():
# Transcribe a square of sides = 6 inches
main()
Run this program several times. It is unlikely that you will get a perfect square
each time. This has to do with the calculations you performed as well with the
variation in the robot's motors. They are not precise. Also, it generally takes
more power to move from a still stop than to keep moving. Since you have no
way of controlling this, at best you can only approximate this type of
behavior. Over time, you will also notice that the error will aggregate. This
will become evident in doing the exercise below.
Do This: Building on the ideas from the previous exercise, we could further
abstract the robot's drawing behavior so that we can ask it to draw any regular
polygon (given the number of sides and length of each side). Write the
function:
75
Chapter 4
def main():
# Given the number of sides and the length of each side,
# draw a regular polygon
main()
To test the program, first try drawing a square of sides 6 inches as in the
previous exercise. Then try a triangle, a pentagon, hexagon, etc. Try a
polygon with 30 sides of length 0.5 inches. What happens when you give 1 as
the number of sides? What happens when you give zero (0) as the number of
sides?
One way you can do interesting things with robot drawings is to inject some
randomness in how long the robot does something. Python, and most
programming languages, typically provide a library for generating random
numbers. Generating random numbers is an interesting process in itself but we
will save that discussion for a later time. Random numbers are very useful in
all kinds of computer applications, especially games and in simulating real life
76
Sensing From Within
There are lots of features available in this library but we will restrict ourselves
with just two functions for now: random and randint. These are described
below:
77
Chapter 4
As you can see, using the random number library is easy enough, and similar
to using the Myro library for robot commands. Given the two functions, it is
entirely up to you how you use them. Look at the program below:
def main():
# generate 10 random polygons
for poly in range(10):
# generate a random polygon and draw it
Print “Place a new color in the pen port and then…”
userInput = input("Enter any number: ")
sides = randint(3, 8)
size = randint(2, 6)
drawPolygon(sides, size)
The first loop in the program draws 10 random polygons of sizes ranging
from 3 to 8 sides and each side in the range 2 to 6 inches. The second loop
carries out a random walk of 20 steps.
Asking Questions?
As you can see from above, it is easy to program various kinds of movements
into the Scribbler. If there is a pen in the pen port, the Scribbler draws a path.
Also in the example above, you can see that we can stop the program
temporarily, pretend that we are taking some input and use that as an
opportunity to change the pen and then go on. Above, we used the Python
input command to accomplish this. There is a better way to do this and it
uses a function provided in the Myro library:
78
Sensing From Within
When you press your mouse on any of the choices (Yes/No), the window
disappears and the function returns the name of the key selected by the user as
a string. That is, if in the above window you pressed the Yes key, the function
will return the value:
While this is definitely more functional than our previous solution, we can
actually do better. For example, what happens when the user presses the No
button in the above interaction? One thing you know for sure is that the
function will return the string 'No'. However, the way we are using this
function, it really does not matter which key the user presses. askQuestion is
designed so it can be customized by you so that you can specify how many
button choices you want to have in the dialog window as well as what the
names of those buttons would be. Here is an illustration of how you would
write a better version of the above command:
79
Chapter 4
Now this is certainly better. Notice that the function askQuestion can be
used with either one parameter or two. If only one parameter is specified, then
the default behavior of the function is to offer two button choices: 'Yes' and
'No'. However, using the second parameter you can specify, in a list, any
number of strings that will become the choice buttons. For example,
This will be a very handy function to use in many different situations. In the
next exercise, try and use this function to become familiar with it.
Do This: Write a Scribbler program of your own that exploits the Scribbler's
movements to make random drawings. Make sure you generate drawings with
at least three or more colors. Because of random movements, your robot is
likely to run into things and get stuck. Help your robot out by picking it up
and placing it elsewhere when this happens.
80
Sensing From Within
Back to time…
Most programming languages also allow you to access the internal clock to
keep track of time, or time elapsed (as in a stop watch), or in any other way
you may want to make use of time (as in the case of the wait) function. The
Myro library provides a simple function that can be used to retrieve the
current time:
>>> currentTime()
1169237231.836
>>> currentTime()
1169237351.5580001
>>> 1169237351.5580001 - 1169237231.836
119.72200012207031
That is, 119.722 seconds had elapsed between the two commands above. This
provides another way for us to write robot behaviors. So far, we have learned
that if you wanted your robot to go forward for 3 seconds, you could either
do:
forward(1.0, 3.0)
or
forward(1.0)
wait(3.0)
stop()
or
81
Chapter 4
while timeRemaining(3.0):
forward(1.0)
stop()
Using the currentTime function, there is yet another way to do the same
thing:
The above solution uses the internal clock. First, it records the start time. Next
it enters the loop which first gets the current time and then checks to see if the
difference between the current time and start time is less than 3.0 seconds. If
so, the forward command is repeated. As soon as the elapsed time gets over
3.0 seconds, the loop terminates. This is another way of using the while-loop
that you learned in the previous chapter. In the last chapter, you learned that
you could write a loop that executed forever as shown below:
while True:
<do something>
That is, you can specify any condition in <some condition is true>. The
condition is tested and if it results in a True value, the step(s) specified in <do
something> is/are performed. The condition is tested again, and so on. In the
example above, we use the expression:
If this condition is true, it implies that the elapsed time since the start is less
than 3.0 seconds. If it is false, it implies that more than 3.0 seconds have
82
Sensing From Within
elapsed and it results in a False value, and the loop stops. Learning about
writing such conditions is essential to writing smarter robot programs.
While it may appear that the solution that specified time in the forward
command itself seemed simple enough (and it is!), you will soon discover that
being able to use the internal clock as shown above provides more versatility
and functionality in designing robot behaviors. This, for example is how one
could program a vacuum cleaning robot to clean a room for 60 minutes:
startTime = currentTime()
while (currentTime() - startTime)/60.0 < 60.0:
cleanRoom()
You have now seen how to write robot programs that have behaviors or
commands that can be repeated a fixed number of times, or forever, or for a
certain duration:
# do something N times
for step in range(N):
do something...
# do something forever
while True:
do something...
83
Chapter 4
Writing Conditions
Let us spend some time here to learn about conditions you can write in while-
loops. The first thing to realize is that all conditions result in either of two
values: True or False (or, alternately a 1 or a 0). These are Python values,
just like numbers. You can use them in many ways. Simple conditions can be
written using comparison (or relational) operations: < (less than), <= (less than
or equal to), > (greater than), >= (greater than or equal to), == (equal to), and
!= (not equal to). These operations can be used to compare all kinds of values.
Here are some examples:
>>> 42 > 23
True
>>> 42 < 23
False
>>> 42 == 23
False
>>> 42 != 23
True
>>> (42 + 23) < 100
True
>>> a, b, c = 10, 20, 10
>>> a == b
False
>>> a == c
True
>>> a == a
True
>>> True == 1
True
>>> False == 1
False
The last two examples above also show how the values True and False are
related to 1 and 0. True is the same as 1 and 0 is the same as False. You can
form many useful conditions using the comparison operations and all
conditions result in either True (or 1) or False (or 0). You can also compare
other values, like strings, using these operations:
84
Sensing From Within
85
Chapter 4
86
Sensing From Within
Now you can see why the following is a way of saying, “do something
forever”:
while True:
<do something>
Since the condition is always True the statements will be repeated forever.
Similarly, in the loop below:
while timeRemaining(duration):
<do something>
Sensing Stall
We mentioned in the beginning of this chapter that the Scribbler also has a
way of sensing that it is stalled when trying to move. This is done by using the
Myro function getStall:
You can use this to detect that the robot has stalled and even use it as a
condition in a loop to control behavior. For example:
87
Chapter 4
That is, keep doing <do something> until the robot has stalled. Thus, you
could write a robot behavior that goes forward until it bumps into something,
say a wall, and then stops.
In the above example, as long as the robot is not stalled, getStall() will
return False and hence the robot will keep going forward (since not False is
True). Once it does bump into something, getStall() will return True and
then the robot will stop and speak.
Do This: Write a complete program for the Scribbler to implement the above
behavior and then observe the behavior. Show this to some friends who are
not in your course. Ask them for their reactions. You will notice that people
will tend to ascribe some form of intelligence to the robot. That is, your robot
is sensing that it is stuck, and when it is, it stops trying to move and even
announces that it is stuck by speaking. We will return to this idea of artificial
intelligence in a later chapter.
88
Sensing From Within
That is, as long as battery power is above 5.0 and the time limit has not
exceeded duration, <do something>.
89
Chapter 4
That is, add population growth in the next year if the population is below 9
billion. Keep repeating this until it exceeds 9 billion.
Do This: Complete the program above and compute the year when the
world’s population will exceed 9 billion. To make your program more useful
make sure you ask the user to input the values of the year, population, growth
rate, etc. In fact, you can even ask the user to enter the population limit so you
make use the program for any kinds of predictions (8 billion? 10 billion?).
How would you change the program so it prints the population projection for
a given year, say 2100?
Summary
90
Sensing From Within
behaviors that use external sensory mechanisms and also enable us to write
more explicit decision-making behaviors. We will learn about these in the
next chapter.
Myro Review
randomNumber()
Returns a random number in the range 0.0 and 1.0. This is an alternative Myro
function that works just like the random function from the Python random
library (see below).
askQuestion(MESSAGE-STRING)
A dialog window with MESSAGE-STRING is displayed with choices: 'Yes' and
'No'. Returns 'Yes' or 'No' depending on what the user selects.
askQuestion(MESSAGE-STRING, LIST-OF-OPTIONS)
A dialog window with MESSAGE-STRING is displayed with choices indicated in
LIST-OF-OPTIONS. Returns option string depending on what the user selects.
currentTime()
The current time, in seconds from an arbitrary starting point in time, many
years ago.
getStall()
Returns True if the robot is stalled when trying to move, False otherwise.
getBattery()
Returns the current battery power level (in volts). It can be a number between
0 and 9 with 0 indication no power and 9 being the highest. There are also
LED power indicators present on the robot. The robot behavior becomes
erratic when batteries run low. It is then time to replace all batteries.
Python Review
True, False
These are Boolean or logical values in Python. Python also defines True as 1
and False as 0 and they can be used interchangeably.
91
Chapter 4
and, or not
These are logical operations. They can be used to combine any expression that
yields Boolean values.
random()
Returns a random number between 0.0 and 1.0. This function is a part of the
random library in Python.
randint(A, B)
Returns a random number in the range A (inclusive) and B (exclusive). This
function is a part of the random library in Python.
Exercises
1. Write a robot program to make your Scribbler draw a five point star. [Hint:
Each vertex in the star has an interior angle of 36 degrees.]
4. If you had an open rectangular lawn (with no trees or obstructions in it) you
could use a Zanboni like strategy to mow the lawn. Start at one end of the
lawn, mow the entire length of it along the longest side, turn around and mow
the entire length again, next to the previously mowed area, etc. until you are
done. Write a program for your Scribbler to implement this strategy (make the
Scribbler draw its path as it goes).
92
Sensing From Within
5. Enhance the random drawing program from this chapter to make use of
speech. Make the robot, as it is carrying out random movements, to speak out
what it is doing. As a result you will have a robot artist that you have created!
6. Rewrite your program from the previous exercise so that the random
behavior using each different pen is carried out for 30 seconds.
randomValue = 1 + int(random()*6)
The function int() takes any number as its parameter, truncates it to a whole
number and returns an integer. Given that random() returns values between
0.0 (inclusive) and 1.0 (exclusive), the above expression will assign a random
value between 1..5 (inclusive) to randomValue. Given this example, write a
new function called myRandRange() that works just like randrange():
def myRandRange(A, B):
9. What kinds of things can your robot talk about? You have already seen how
to make the robot/computer speak a given sentence or phrase. But the robot
can also "talk" about other things, like the time or the weather.
One way to get the current time and date is to import another Python library
called time:
93
Chapter 4
The time module provides a function called localtime that works as follows:
>>> localtime()
(2007, 5, 29, 12, 15, 49, 1, 149, 1)
1. year
2. month
3. day
4. hour
5. minute
6. seconds
7. weekday
8. day of the year
9. whether it is using daylight savings time, or not
In the example above, it is May 29, 2007 at 12:15pm and 49 seconds. It is also
the 1st day of the week, 149 day of the year, and we are using daylight
savings time. You can assign each of the values to named variables as shown
below:
Then, for the example above, the variable year will have the value 2007;
month will have the value 5, etc. Write a Python program that speaks out the
current date and time.
94
Sensing From Within
95
Opposite page: Mars Rover.
Photo courtesy of NASA/JPLCaltech
Sensing The World
97
Chapter 5
In the previous chapter you learned how proprioception: sensing time, stall,
and battery-level can be used in writing simple yet interesting robot behaviors.
All robots also come equipped with a suite of external sensors (or
exteroceptors) that can sense various things in the environment. Sensing
makes the robot aware of its environment and can be used to define more
intelligent behaviors. Sensing is also related to another important concept in
computing: input. Computers act on different kinds of information: numbers,
text, sounds, images, etc. to produce useful applications. Acquiring
information to be processed is generally referred to as input. In this chapter
we will also see how other forms of input can be acquired for a program to
process. First, let us focus on Scribbler’s sensors.
Scribbler Sensors
The Scribbler robot can sense the amount of ambient light, the presence (or
absence) of obstacles around it, and also take pictures from its camera.
Several devices (or sensors) are located on the Scribbler (see picture on the
previous page). Here is a short description of these:
Camera: The camera can take a still picture of whatever the robot is currently
“seeing”.
Light: There are three light sensors present on the robot. These are located in
the three holes present on the front of the robot. These sensors can detect the
levels of brightness (or darkness). These can be used to detect variations in
ambience light in a room. Also, using the information acquired from the
camera, the Scribbler makes available an alternative set of brightness sensors
(left, center, and right).
Proximity: There are two sets of these on the Scribbler: IR Sensors (left and
right) on the front; and Obstacle Sensors (left, center, and right) on the Fluke
dongle. They can be used to detect objects on the front and on its sides.
98
Sensing the World
Sensing using the sensors provided in the Scribbler is easy. Once you are
familiar with the details of sensor behaviors you will be able to use them in
your programs to design interesting creature-like behaviors for your Scribbler.
But first, we must spend some time getting to know these sensors; how to
access the information reported by them; and what this information looks like.
As for the internal sensors, Myro provides several functions that can be used
to acquire data from each sensor device. Where multiple sensors are available,
you also have the option of obtaining data from all the sensors or selectively
from an individual sensor.
Do This: perhaps the best way to get a quick look at the overall behavior of
all the sensors is to use the Myro function
senses:
Scribbler Sensors
>>> senses()
The Camera
99
Chapter 5
will depend on the orientation of the robot (and the dongle). To take pictures
from the camera you can use the takePicture command:
takePicture()
takePicture("color")
takePicture("gray")
>>> p = takePicture()
>>> show(p)
Once you take a picture from the camera, you can do many things with it. For
example, you may want to see if there is a laptop computer present in the
picture. Image processing is a vast subfield of computer science and has
applications in many areas. Understanding an image is quite complex but
something we do quite naturally. For example, in the picture above, we have
no problem locating the laptop, the bookcase in the background, and even a
case for a badminton racket (or, if you prefer racquet). The camera on the
Scribbler is its most complex sensory device that will require a lot of
computational effort and energy to use it in designing behaviors. In the
simplest case, the camera can serve as your remote “eyes” on the robot. We
may not have mentioned this earlier, but the range of the Bluetooth wireless
on the robot is 100 meters. In Chapter 9 we will learn several ways of using
the pictures. For now, if you take a picture from the camera and would like to
save it for later use, you use the Myro command, savePicture, as in:
100
Sensing the World
The file office-scene.jpg will be saved in the same folder as your Start
Python folder. You can also use savePicture to save a series of pictures
from the camera and turn it into an animated “movie” (an animated gif
image). This is illustrated in the example below.
Do This: First try out all the commands for taking and saving pictures. Make
sure that you are comfortable using them. Try taking some grayscale pictures
as well. Suppose your robot has ventured into a place where you cannot see it
but it is still in communication range with your computer. You would like to
be able to look around to see where it is. Perhaps it is in a new room. You can
ask the robot to turn around and take several pictures and show you around.
You can do this using a combination of rotate and takePicture commands
as shown below:
while timeRemaining(30):
show(takePicture())
turnLeft(0.5, 0.2)
That is, take a picture and then turn for 0.2 seconds, repeating the two steps
for 30 seconds. If you watch the picture window that pops up, you will see
successive pictures of the robot’s views. Try this a few times and see if you
can count how many different images you are able to see. Next, change the
takePicture command to take grayscale images. Can you count how many
images it took this time? There is of course an easier way to do this:
N = 0
while timeRemaining(30):
show(takePicture())
turnLeft(0.5, 0.2)
N = N + 1
print N
101
Chapter 5
First we create an empty list called, Pics. Then we append each successive
picture taken by the camera into the list. Once all the images are accumulated,
we use savePicture to store the entire set as an animated GIF. You will be
able to view the animated GIF inside any web browser. Just load the file into a
web browser and it will play all the images as a movie.
There are many more interesting ways that one can use images from the
camera. In Chapter 9 we will explore images in more detail. For now, let us
take a look at Scribbler’s other sensors.
102
Sensing the World
Light Sensing
>>> getLight()
[135, 3716, 75]
>>> getLight('left')
135
>>> getLight(0)
135
>>> getLight('center')
3716
>>> getLight(1)
3716
>>> getLight('right')
75
>>> getLight(2)
75
The values being reported by these sensors can be in the range [0..5000]
where low values imply bright light and high values imply darkness. The
above values were taken in ambient light with one finger completely covering
the center sensor. Thus, the darker it is, the higher the value reported. In a
way, you could even call it a darkness sensor. Later, we will see how we can
easily transform these values in many different ways to affect robot behaviors.
It would be a good idea to use the senses function to play around with the
light sensors and observe their values. Try to move the robot around to see
how the values change. Turn off the lights in the room, or cover the sensors
with your fingers, etc.
103
Chapter 5
When you use the getLight function without any parameters, you get a list of
three sensor values (left, center, and right). You can use assign these to
individual variables in many ways:
>>> L, C, R = getLight()
>>> print L
135
>>> Center = getLight(“center”)
>>> print center
3716
The variables can then be used in many ways to define robot behaviors. We
will see several examples of these in the next chapter.
The camera present on the Fluke dongle can also be used as a kind of
brightness sensor. This is done by averaging the brightness values in different
zones of the camera image. In a way, you can think of it as a virtual sensor.
That is, it doesn’t physically exist but is embedded in the functionality of the
camera. The function getBright is similar to getLight in how it can be used
to obtain brightness values:
>>> getBright()
[2124047, 1819625, 1471890]
>>> getBright('left')
2124047
>>> getBright(0)
2124047
>>> getBright('center')
1819625
>>> getBright(1)
1819625
>>> getBright('right')
104
Sensing the World
1471890
>>> getBright(2)
1471890
The above values are from the camera image of the Firefox poster (see picture
above). The values being reported by these sensors can vary depending on the
view of the camera and the resulting brightness levels of the image. But you
will notice that higher values imply bright segments and lower values imply
darkness. For example, here is another set
of values based on the image shown here
on the right.
>>> getBright()
[1590288, 1736767, 1491282]
105
Chapter 5
v = Ambient
def main():
# Run the robot for 60 seconds
while timeRemaining(60):
L, C, R = getLight()
# motors run proportional to light
motors(normalize(L), normalize(R))
stop()
Run the above program on your Scribbler robot and observe its behavior. You
will need a flashlight to affect better reactions. When the program is running,
try to shine the flashlight on one of the light sensors (left or right). Observe
the behavior. Do you think the robot is behaving like an insect? Which one?
Study the program above carefully. There are some new Python features used
that we will discuss shortly. We will also return to the idea of making robots
behave like insects in the next chapter.
Proximity Sensing
The Scribbler has two sets of proximity detectors. There are two infrared (IR)
sensors on the front of the robot and there are three additional IR obstacle
sensors on the Fluke dongle. The following functions are available to obtain
values of the front IR sensors:
106
Sensing the World
Examples:
>>> getIR()
[1, 0]
>>> getIR('left')
1
>>> getIR(0)
1
>>> getIR('right')
0
>>> getIR(1)
0
Do This: Run the senses function and observe the values of the IR sensors.
Place various objects in front of the robot and look at the values of the IR
proximity sensors. Take your notebook and place it in front of the robot about
two feet away. Slowly move the notebook closer to the robot. Notice how the
value of the IR sensor changes from a 1 to a 0 and then move the notebook
away again. Can you figure out how far (near) the obstacle should be before it
is detected (or cleared)? Try moving the notebook from side to side. Again
notice the values of the IR sensors.
The Fluke dongle has an additional set of obstacle sensors on it. These are
also IR sensors but behave very differently in terms of the kinds of values
they report. The following functions are available to obtain values of the
obstacle IR sensors:
107
Chapter 5
sensor. <POSITION> can either be one of 'left', ‘center’, or 'right' or one of the
numbers 0, 1, or 2. The positions 0, 1, and 2 correspond to the left, center, and
right sensors.
Examples:
>>> getObstacle()
[1703, 1128, 142]
>>> getObstacle('left')
1703
>>> getObstacle(0)
1703
>>> getObstacle('center')
1128
>>> getObstacle(1)
1128
>>> getObstacle('right')
142
>>> getObstacle(2)
142
The values reported by these sensors range from 0 to 7000. A 0 implies there
is nothing in front of the sensor where as a high number implies the presence
of an object. The sensors on the sides can be used to detect the presence (or
absence of walls on the sides).
Do This: Place your Scribbler on the floor, turn it on, start Python, and
connect to it. Also connect the game pad controller and start the manual drive
operation (gamepad()). Next, issue the senses command to get the real time
sensor display. Our objective here is to really "get into the robot's mind" and
drive it around without ever looking at the robot. Also resist the temptation to
take a picture. You can use the information displayed by the sensors to
navigate the robot. Try driving it to a dark spot, or the brightest spot in the
room. Try driving it so it never hits any objects. Can you detect when it hits
something? If it does get stuck, try to maneuver it out of the jam! This
exercise will give you a pretty good idea of what the robot senses, how it can
use its sensors, and to the range of behaviors it may be capable of. You will
find this exercise a little hard to carry out, but it will give you a good idea as
108
Sensing the World
to what should go into the brains of such robots when you actually try to
design them. We will try and revisit this scenario as we build various robot
programs.
Also do this: Try out the program below. It is very similar to the program
above that used the normalized light sensors.
def main():
# Run the robot for 60 seconds
while timeRemaining(60):
L, R = getIR()
# motors run proportional to IR values
motors(R, L)
main()
Since the IR sensors report 0 or 1 values, you do not need to normalize them.
Also notice that we are putting the left sensor value (L) into the right motor
and the right sensor value (R) into the left motor. Run the program and
observe the robot’s behavior. Keep a notebook handy and try to place it in
front of the robot. Also place it slightly on the left or on the right. What
happens? Can you summarize what the robot is doing? What happens when
you switch the R and L values to the motors?
You can see how simple programs like the ones we have seen above can result
in interesting automated control strategies for robots. You can also define
completely automated behaviors or even a combination of manual and
automated behaviors for robots. In the next chapter we will explore several
robot behaviors. First, it is time to learn about lists in Python.
Lists in Python
You have seen above that several sensor functions return lists of values. We
also used lists to accumulate a series of pictures from the camera to generate
an animated GIF. Lists are a very useful way of collecting a bunch of
information and Python provides a whole host of useful operations and
functions that enable manipulation of lists. In Python, a list is a sequence of
109
Chapter 5
objects. The objects could be anything: numbers, letters, strings, images, etc.
The simplest list you can have is an empty list:
>>> []
[]
or
>>> L = []
>>> print L
[]
An empty list does not contain anything. Here are some lists that contain
objects:
As you can see from above, a list could be a collection of any objects. Python
provides several useful functions that enable manipulation of lists. Below, we
will show some examples using the variables defined above:
>>> len(N)
5
>>>len(L)
0
>>> N + FamousNumbers
[7, 14, 17, 20, 27, 3.1415, 2.718, 42]
>>> SwankyZips[0]
90210
>>> SwankyZips[1:3]
[33139, 60611]
>>> 33139 in SwankyZips
True
>>> 19010 in SwankyZips
False
110
Sensing the World
From the above, you can see that the function len takes a list and returns the
length or the number of objects in the list. An empty list has zero objects in it.
You can also access individual elements in a list using the indexing operation
(as in SwankyZips[0]). The first element in a list has index 0 and the last
element in a list of n elements will have an index n-1. You can concatenate
two lists using the ‘+’ operator to produce a new list. You can also specify a
slice in the index operation (as in SwankyZips[1:3] to refer to the sublist
containing elements from index 1 through 2 (one less than 3). You can also
form True/False conditions to check if an object is in a list or not using the
in operator. These operations are summarized in more detail at the end of the
chapter.
Besides the operations above, Python also provides several other useful list
operations. Here are examples of two useful list operations sort and
reverse:
>>> SwankyZips
[90210, 33139, 60611, 10036]
>>> SwankyZips.sort()
>>> SwankyZips
[10036, 33139, 60611, 90210]
>>> SwankyZips.reverse()
>>> SwankyZips
[90210, 60611, 33139, 10036]
>>> SwankyZips.append(19010)
>>> SwankyZips
[90210, 60611, 33139, 10036, 19010]
sort rearranges elements in the list in ascending order. reverse reverses the
order of elements in the list, and append appends an element to the end of the
list. Some other useful list operations are listed at the end of the chapter.
Remember that lists are also sequences and hence they can be used to perform
repetitions. For example:
111
Chapter 5
New York
Dar es Salaam
Moscow
The variable city takes on subsequent values in the list Cities and the
statements inside the loop are executed once for each value of city. Recall,
that we wrote counting loops as follows:
for I in range(5):
<do something>
>>> range(5)
[0, 1, 2, 3, 4]
Thus the variable I takes on values in the list [0, 1, 2, 3, 4] and, as in the
example below, the loop is executed 5 times:
0
1
2
3
4
Also recall that strings are sequences. That is, the string:
ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
is a sequence of 26 letters. You can write a loop that runs through each
individual letter in the string and speaks it out as follows:
>>> for letter in ABC:
speak(letter)
112
Sensing the World
There are also some useful functions that convert strings into lists. Say we
have a string containing a sentence:
You can convert the string above into individual words using the split
operation:
>>> sentence.split()
['Would', 'you', 'have', 'any', 'Grey', 'Poupon']
In light of the list operations presented above review some of the sensing
examples from earlier in the chapter. We will be using lists in many examples
in the remained of the text. For now, let us return to the topic of sensing.
Extrasensory Perception?
You have seen many ways of acquiring sensory information using the robot’s
sensors. In addition to the robot itself, you should be aware that your
computer also has several “sensors” or devices to acquire all kinds of data.
For example, you have already seen how, using the input function, you can
input some values into your Python programs:
Indeed, there are other ways you can acquire information into your Python
programs. For example, you can input some data from a file in your folder. In
Chapter 1 you also saw how you were able to control your robot using the
game pad controller. The game pad was actually plugged into your computer
and was acting as an input device. Additionally, your computer is most likely
connected to the internet using which you can access many web pages. It is
also possible to acquire the content of any web page using the internet.
Traditionally, in computer science people refer to this is a process of input.
Using this view, getting sensory information from the robot is just a form of
113
Chapter 5
input. Given that we have at our disposal all of the input facilities provided by
the computer, we can just as easily acquire input from any of the modalities
and combine them with robot behaviors if we wish. Whether you consider this
as extra sensory perception or not is a matter of opinion. Regardless, being
able to get input from a diverse set of sources can make for some very
interesting and useful computer and robot applications.
The basic game pad has eight buttons (numbered 1 through 8 in the picture)
and an axis controller (see picture on right). The buttons can be pressed or
released (on/off) which are represented by 1 (for on) and 0 (for off). The axis
can be pressed in many different orientations represented by a pair of values
(for the x-axis and y-axis) that range from -1.0 to 1.0 with [0.0, 0.0]
representing no activity on the axis. Two Myro functions are provided to
access the values of the buttons and the axis:
114
Sensing the World
getGamepad(<device>)
getGamepadNow(<device>) Game Pad’s Axis Control
returns the values indicating the status of
the specified <device>. <device> can be
"axis" or "button".
>>> getGamepadNow("axis")
[0.0, 0.0]
>>> getGamepad("axis")
[0.0, -1.0]
>>> getGamepadNow("button")
[0, 0, 0, 0, 1, 1, 0, 0]
Both getGamepad and getGamepadNow return the same set of values: axis
values are returned as a list [x-axis, y-axis] (see picture on right for
orientation) and the button values are returned as a list of 0, and 1’s. The first
value in the list is the status of button#1, followed by 2, 3, and so on. See
picture above for button numbering.
Do This: Connect the game pad controller to your computer, start Python, and
import the Myro module. Try out the game pad commands above and observe
the values. Here is another way to better understand the operation of the game
pad and the game pad functions:
while timeRemaining(30):
print getGamepad("button")
115
Chapter 5
Try out different button combinations. What happens when you press more
than one button? Repeat the above for axis control and observe the values
returned (keep the axes diagram handy for orientation purposes).
The game pad controller can be used for all kinds of interactive purposes,
especially for robot control as well as in writing computer games (see Chapter
X). Let us write a simple game pad based robot controller. Enter the program
below and run it.
def main():
# A simple game pad based robot controller
while timeRemaining(30):
X, Y = getGamePadNow("axis")
motors(X, Y)
The program above will run for 30 seconds. In that time it will repeatedly
sample the values of the axis controller and since those values are in the range
-1.0..1.0, it uses them to drive the motors. When you run the above program
observe how the robot moves in response to pressing various parts of the axis.
Do the motions of the robot correspond to the directions shown in the game
pad picture on previous page? Try changing the command from motors to
move (recall that move takes two values: translate and rotate). How does it
behave with respect to the axes? Try changing the command to move(-X, -
Y). Observe the behavior.
As you can see from the simple example above, it is easy to combine input
from a game pad to control your robot. Can you expand the program above to
behave exactly like the gamepad controller function you used in Chapter 1?
(See Exercise 6).
If your computer is connected to the internet, you can also use Python
facilities to access the content of any web page and use it as input to your
program. Web pages are written using markup languages like HTML and so
when you access the content of a web page you will get the content with the
116
Sensing the World
markups included. In this section we will show you how to access the content
of a simple web page and print it out. Later we will see how you could use the
information contained in it to do further processing.
http://www.fi.edu/weather/data/jan07.txt
This web page is hosted by the Franklin Institute of Philadelphia and contains
recorded daily weather data for Philadelphia for January 2007. You can
navigate from the above address to other pages on the site to look at daily
weather data for other dates (the data goes back to 1872!). Below, we will
show you how, using a Python library called urllib, you can easily access
the content of any web page. The urllib library provides a useful function
called urlopen using which you can access any web page on the internet as
follows:
January 2007
Day Max Min Liquid Snow Depth
1 57 44 1.8 0 0
2 49 40 0 0 0
3 52 35 0 0 0
… … … … … …
31 31 22 0 0 0
#days 31
Sum 1414 1005 4.18 1.80 1.10
117
Chapter 5
The first command uses the function urlopen (which is imported from the
urllib) to establish a connection between your program and the web page.
The second command issues a read to read from that connection. Whatever is
read from that web page is printed out as a result of the print command.
The Myro module provides you with several useful functions (forward,
turnRight, etc.) that enable easy control of your robot's basic behaviors.
Additionally, using the syntax above, you learned to combine these basic
behaviors into more complex behaviors (like wiggle, yoyo, etc.). By using
parameters you can further customize the behavior of functions by providing
different values for the parameters (for example, forward(1.0) will move the
robot faster than forward(0.5)). You should also note a crucial difference
between the movement commands like forward, turnLeft, and commands
that provide sensory data like getLight or getStall, etc. The sensory
commands always return a value whenever they are issued. That is:
>>> getLight('left')
221
>>> getStall()
0
Commands that return a value when they are invoked are called functions
since they actually behave much like mathematical functions. None of the
movement commands return any value, but they are useful in other ways. For
instance, they make the robot do something. In any program you typically
118
Sensing the World
need both kinds of functions: those that do something but do not return
anything as a result; and those that do something and return a value. In Python
all functions actually return a value. You can already see the utility of having
these two kinds of functions from the examples you have seen so far.
Functions are an integral and critical part of any program and part of learning
to be a good programmer is to learn to recognize abstractions that can then be
packaged into individual functions (like drawPolygon, or degreeTurn) which
can be used over and over again.
def triple(x):
# Returns x*3
return x * 3
The function above can be used just like the ones you have been using:
>>> triple(3)
9
>>> triple(5000)
15000
return <expression>
That is, the function in which this statement is encountered will return the
value of the <expression>. Thus, in the example above, the return-
statement returns the value of the expression 3*x, as shown in the example
invocations. By giving different values for the parameter x, the function
simply triples it. This is the idea we used in normalizing light sensor values in
the example earlier where we defined the function normalize to take in light
sensor values and normalize them to the range 0.0..1.0 relative to the observed
ambient light values:
119
Chapter 5
In defining the function above, we are also using a new Python statement: the
if-statement. This statement enables simple decision making inside computer
programs. The simplest form of the if-statement has the following structure:
if <CONDITION>:
<do something>
<do something>
...
Functions, as you have seen, can be used to package useful computations and
can be used over and over again in many situations. Before we conclude this
section, let us give you another example of a function. Recall from Chapter 4
the robot behavior that enables the robot to go forward until it hits a wall. One
of the program fragments we used to specify this behavior is shown below:
120
Sensing the World
In the above example, we are using the value returned by getStall to help us
make the decision to continue going forward or stopping. We were fortunate
here that the value returned is directly usable in our decision making.
Sometimes, you have to do little interpretation of sensor values to figure out
what exactly the robot is sensing. You will see that in the case of light
sensors. Even though the above statements are easy to read, we can make
them even better, by writing a function called stuck() as follows:
def stuck():
# Is the robot stalled?
# Returns True if it is and False otherwise.
return getStall() == 1
As you can see, it reads much better. Programming is a lot like writing in this
sense. As in writing, there are several ways of expressing an idea in words.
Some are better and more readable than others. Some are downright poetic.
Similarly, in programming, expressing something in a program can be done in
many ways, some better and more readable than others. Programming is not
all about functionality, there can be poetry in the way you write a program.
Summary
In this chapter you have learned all about obtaining sensory data from the
robot’s perceptual system to do visual sensing (pictures), light sensing, and
proximity sensing. The Scribbler provides a rich set of sensors that can be
used to design interesting robot behaviors. You also learned that sensing is
equivalent to the basic input operation in a computer. You also learned how to
121
Chapter 5
get input from a game pad, the World Wide Web, and from data files.
Programs can be written to make creative use of the input modalities available
to define robot behaviors, computer games, and even processing data. In the
rest of the book you will learn how to write programs that make use of these
input modalities in many different ways.
Myro Review
getBright()
Returns a list containing the three values of all light sensors.
getBright(<POSITION>)
Returns the current value in the <POSITION> light sensor. <POSITION> can
either be one of 'left', 'center', 'right' or one of the numbers 0, 1, 2.
getGamepad(<device>)
getGamepadNow(<device>)
Returns the values indicating the status of the specified <device>. <device>
can be "axis" or "button". The getGamepad function waits for an event
before returning values. getGamepadNow immediately returns the current
status of the device.
getIR()
Returns a list containing the two values of all IR sesnors.
getIR(<POSITION>)
Returns the current value in the <POSITION> IR sensor. <POSITION> can
either be one of 'left' or 'right' or one of the numbers 0, 1.
getLight()
Returns a list containing the three values of all light sensors.
getLight(<POSITION>)
Returns the current value in the <POSITION> light sensor. <POSITION> can
either be one of 'left', 'center', 'right' or one of the numbers 0, 1, 2. The
positions 0, 1, and 2 correspond to the left, center, and right sensors.
122
Sensing the World
getObstacle()
Returns a list containing the two values of all IR sesnors.
getObstacle(<POSITION>)
Returns the current value in the <POSITION> IR sensor. <POSITION> can
either be one of 'left', ‘center’, or 'right' or one of the numbers 0, 1, or 2.
savePicture(<picture>, <file>)
savePicture([<picture1>, <picture2>, …], <file>)
Saves the picture in the file specified. The extension of the file should be
“.gif” or “.jpg”. If the first parameter is a list of pictures, the file name
should have an extension “.gif” and an animated GIF file is created using
the pictures provided.
senses()
Displays Scribbler’s sensor values in a window. The display is updated every
second.
show(<picture>)
Displays the picture in a window. You can click the left mouse anywhere in
the window to display the (x, y) and (r, g, b) values of the point in the
window’s status bar.
takePicture()
takePicture(“color”)
takePicture(“gray”)
Takes a picture and returns a picture object. When no parameters are
specified, the picture is in color.
Python review
if <CONDITION>:
<statement-1>
...
<statement-N>
If the condition evaluates to True, all the statements are are performed.
Otherwise, all the statements are skipped.
123
Chapter 5
return <expression>
Can be used inside any function to return the result of the function.
<string>.split()
Splits <string> into a list.
urlopen(<URL>)
Establishes a stream connection with the <URL>. This function is to be
imported from the Python module urlopen.
<stream>.read()
Reads the entire contents of the <stream> as a string.
Lists:
[] is an empty list.
<list>[i]
Returns the ith element in the <list>. Indexing starts from 0.
<value> in <list>
Returns True if <value> is in the <list>, False otherwise.
<list1> + <list2>
Concatenates <list1> and <list2>.
len(<list>)
Returns the number of elements in a list.
range(N)
Returns a list of numbers from 0..N
range(N1, N2)
Returns a list of numbers starting from N1..(N2-1)
124
Sensing the World
Exercises
2. Besides text, the speak command can also vocalize numbers. Try
speak(42) and also speak(3.1419). Try some really large whole numbers,
like speak(4537130980). How is it vocalized? Can you find out the limits of
numerical vocalization?
3. The Fluke camera returns pictures that are 256x192 (= 49,152) pixels.
Typical digital cameras are often characterized by the number of pixels they
use for images. For example, 8 megapixels. What is a megapixel? Do some
web search to find out the answer.
4. All images taken and saved using the Fluke camera can also be displayed in
a web page. In your favorite browser, use the Open File option (under the File
menu) and navigate to a saved picture from the Scribbler. Select it and view it
in the browser window. Try it with an animated GIF image file.
L = [5]*10
125
Chapter 5
6. Modify the game pad input program from this chapter to make the axis
controller behave so that when the top of the axis is pressed, the robot goes
forward and when the bottom of the axis is pressed, it goes backward.
126
Sensing the World
127
Opposite page: Mars Rover.
Photo courtesy of NASA/JPLCaltech
Insect-Like Behaviors
129
Chapter 6
Braitenberg Vehicles
130
Insect‐Like Behaviors
Vehicle 1: Alive
Vehicle#1: Alive
The first vehicle Braitenberg
describes has one sensor and one
motor. The value transmitted by the
sensor directly feeds into the motor.
If the value being reported by the
sensor is a varying quantity (say
light), the vehicle will move at a
speed proportional to the amount of
quantity being detected by the sensor.
A schematic of the vehicle is shown above on the left. In order to design this
vehicle using the Scribbler, you can use the center light sensor and connect
what it reports directly to both motors of the robot. This is shown on the right.
That is, the same light reading is directly controlling both the motors by the
same amount. As you have already seen, there are a many different ways to
specify motor movement commands to the Scribbler. Suppose the value
obtained from the center light sensor is C, you can control both motors using
this value by using the command:
motors(C, C)
forward(C)
Now that we know how the internal structure of this vehicle looks, we can
start to write a program that will implement it. But, before we get there, we
need to sort out a small issue of compatibility: light sensors report values in
131
Chapter 6
the range 0..5000 whereas motors and movement commands take values in
the range -1.0 to 1.0. In this example, we are only concerned with movements
that range from a complete stop to full speed forward, so the values range
from 0.0 to 1.0. We have to computationally normalize, or map the light
sensor values in this range. A first attempt at this would be to write a function
called normalize that operates as follows:
def normalize(v):
# normalizes v to range 0.0 to 1.0
Once we have this function, we can write the behavior for the vehicle as
follows:
def main():
# Braitenberg vehicle#1: Alive
while True:
L = getLight("center")
forward(normalize(L))
main()
It is time now to think about the task of the normalize function. Given a
value received from a light sensor, it has to transform it to a proportional
value between 0.0 and 1.0 so that the brighter the light, the higher the value
(i.e. closer to 1.0). Vehicle#1 moves in proportion to the amount of light it
receives. This is a good time to revisit the senses function of Myro to look at
the values reported by the light sensors. Go ahead and do this.
After examining the values returned by the light sensors you may notice that
they report small values (less than 50) for bright light and larger values (as
large as 3000) for darkness. In a way, you can say that the light sensor is
really a darkness sensor; the darker it is the higher the values reported by it.
The light sensors are capable of reporting values between 0 and 5000. Now,
132
Insect‐Like Behaviors
we can certainly calibrate or normalize using these values using the following
definition of normalize:
def normalize(v):
# Normalize v (in the range 0..5000) to 0..1.0, inversely
That is, we divide the value of the light sensor by its maximum value and then
subtract that from 1.0 (for inverse proportionality). Thus a brighter light value,
say a value of 35, will get normalized as:
If 0.9929 is sent to the motors (as in the above program), the robot would
move full speed forward. Let us also compute the speed of the robot when it is
in total darkness. When you place a finger on the center sensor, you will get
values in the 2000-3000 range. For 3000, the normalization will be:
The robot will still be moving, although at nearly half the speed. Most likely,
you will be operating the robot in a room where there is sufficient ambient
light. You will notice that under ambient daylight conditions, the values
reported by the light sensors are in the 150-250 range. Using the above
normalization you will get:
That is almost full speed ahead. In order to experience the true behavior of the
above vehicle, we have to use a normalization scheme that takes into account
the ambient light conditions (they will vary from room to room). Further, let
us assume that in ambient light conditions, we will watch the robot respond to
a light source that we will control. A flashlight will work nicely. So, to make
the robot appropriately sensitive to the flashlight under ambient light
conditions you can write a better version of normalize as follows:
133
Chapter 6
def normalize(v):
if v > Ambient:
v = Ambient
That is, the darkest condition is represented by the ambient light value
(Ambient) and then normalization is done with respect to that value. You can
either set the ambient value by hand, or, a better way is to have the robot
sense its ambient light at the time the program is initiated. This is the same
version of normalize that you saw in the previous chapter. Now you know
how we arrived at it. The complete program for Vehicle#1 is shown below:
Ambient = getLight("center")
def normalize(v):
if v > Ambient:
v = Ambient
def main():
# Braitenberg vehicle#1: Alive
while True:
L = getLight("center")
forward(normalize(L))
Do This: Implement the program above and observe the robot's behavior.
Does it respond as described above?
You may have also noticed by now that the three light sensors are not
necessarily closely matched. That is, they do not report exactly the same
values under the same conditions. When writing robot programs that use
multiple light sensors, it is a good idea to average the values returned by all
the light sensors to represent the ambient value. Modify the program above to
134
Insect‐Like Behaviors
use the average of all three values as the ambient value. There shouldn't be a
noticeable difference in the robot's behavior. However, this is something you
may want to use in later programs.
# Vraitenberg Vehicle#2a
from myro import *
initialize("com"+ask("What port?"))
Ambient = sum(getLight())/3.0
def normalize(v):
if v > Ambient:
v = Ambient
def main():
# Braitenberg vehicle#2a: Coward
while True:
L = getLight("left")
R = getLight("right")
motors(normalize(L), normalize(R))
135
Chapter 6
You will notice that the robots behave the same way when the light is placed
directly ahead of them: they are both attracted to light and hence move
towards the light source. However, Vehicle 2a will move away from the light
if the light source is on a side. Since the nearer sensor will get excited more,
moving the corresponding motor faster, and thereby turning the robot away.
In the case of Vehicle 2b, however, it will always turn towards the light
source and move towards it. Braitenberg calls these behaviors coward (2a)
and aggressive (2b).
136
Insect‐Like Behaviors
orientation and then loading and executing the program. However prior to the
robot's actual behavior, the robot may need to perform some preliminary
observations (for example, sensing ambient light), it becomes necessary to re-
orient the robot properly before starting the execution of the actual behavior.
This can be easily accomplished by including some simple interactive
commands in the robot's program. The resulting program structure is shown
below:
def main():
# Description of the behavior...
Do This: Modify the programs for Vehicles 1, 2a, and 2b to include the
askquestion command above.
We have introduced a few basic programming patterns above that can be used
in many robot programming situations. The thing to remember is that, at any
point in the execution of a robot's program, you can also program appropriate
interjections to perform various experimental or control functions. We will
see several other examples later on.
Other Normalizations
All the normalizations of light sensor values shown above were used to
normalize the values in the range 0.0..1.0 in direct proportion to the amount of
light being sensed. That is, the darker it is, the closer the normalized values
are to 0.0 and the brighter it gets, the closer the normalized values get to 1.0.
This is just one way that one can relate the quantity being sensed to the
amount of speed applied to the robot's motors. You can imagine other
137
Chapter 6
return v/Ambient
138
Insect‐Like Behaviors
A Non‐Monotonic Function
def normalize(v):
mean = Ambient/2.0
stddev = Ambient/6.0
if v >= Ambient:
v = Ambient
return exp(-(v - mean)**2 / 2*(stddev**2))
139
Chapter 6
There are of course several other possibilities that one could try: a step
function; or a threshold; and any other mathematical combinations. The key
idea is that there is a clear mapping of the range of sensor values to motor
values in the range 0.0..1.0.
Robots using these normalizations and other variations are likely to exhibit
very interesting and sometimes unpredictable behaviors. Observers unaware
of the internal mapping mechanisms will have a hard time describing
precisely the robot's behavior and will tend to use anthropomorphic terms
(like, love, hate, instincts, etc.) to describe the behavior of robots. This is what
an uphill analysis means.
Multiple Sensors
Adding several sensors enriches the design space for robot behaviors. As a
designer, you now have a choice of different types of mappings: excitatory,
inhibitory, or more complex; and connections: straight or crossed. Suddenly
the resulting robot behavior will seem complex. On the Scribbler, for instance,
in addition to light sensors, you also have the stall sensor, and the IR sensors.
With the exception of light sensors, all of these other sensors are digital or
threshold sensors that are either ON or OFF (i.e. they report values that are
either 0 or 1 indicating the presence or absence or the thing they are sensing).
In a way you can think that the digital sensors are already normalized, but it is
still possible to invert the relationship if need be. You can design several
interesting behaviors by combining two or more sensors and deciding whether
to connect them straight or crossed.
140
Insect‐Like Behaviors
More Vehicles
Here are descriptions of several vehicles that are in the spirit of Braitenberg's
designs and also exhibit interesting behaviors. Using the concepts and
programming techniques from above, try to implement these on the Scribbler
robot. Once completed, you should invite some friends to observe the
behaviors of these creatures and record their reactions.
Timid
Indecisive
Indecisive is similar to Timid, except, it never stops: its motors are always
running, either in forward direction, or in reverse direction, controlled by the
threshold light sensor. When the light sensor detects light, it moves forward,
otherwise, it moves backwards. When you run this creature, you will notice
that it tends to oscillate back and forth at shadow edges. Thus, Indecisive is a
shadow edge seeker.
Paranoid
141
Chapter 6
if <condition>:
<this>
else:
<that>
if <condition-1>:
<this>
elif <condition-2>:
<that>
elif <condition-3>:
<something else>
...
else:
<other>
Notice the use of the word elif (yes, it is spelled that way!) to designate "else
if". Thus, depending upon whichever condition is true, the corresponding
<this>, <that>, or <something else> will be carried out. If all else fails,
the <other> will be carried out.
142
Insect‐Like Behaviors
Using the three light sensors the robot can detect varying light conditions in
its environment. Let us write a robot program that makes it detect and orient
towards bright light. Recall from Chapter 5 that light sensors report low
values in bright light conditions and high values in low light. To accomplish
this task, we only need to look at the values reported by left and right light
sensors. The following describes the robot's behavior:
Thus, by making use of the if-else statement, we can refine the above into the
following:
while timeRemaining(30):
if left light is brighter that right light:
turnLeft(1.0)
else:
turnRight(1.0)
The only thing remaining in the commands above is to write the condition to
detect the difference between the two light sensors. This can be done using the
expression:
Do This: Write a complete program that implements the above behavior and
test it on your robot.
You may have noticed that even in uniform lighting conditions sensors tend to
report different values. It is generally a good idea to threshold the difference
when making the decision above. Say we set the threshold to a difference of at
least 50. That is, if the left and right sensors differ by at least 50 then turn
143
Chapter 6
towards the brighter sensor. What happens if the difference is less than the
threshold? Let us decide that in that case the robot will stay still. This
behavior can be captured by the following:
thresh = 50
while timeRemaining(30):
# Get sensor values for left and right light sensors
L = getLight('left')
R = getLight('right')
Notice how we have used the variable thresh to represent the threshold
value. This is good programming practice. Since the performance of sensors
varies under different light conditions, this allows you to adjust the threshold
by simply changing that one value. By using the name thresh instead of a
fixed value, say 50, you only have to make such changes in one place of your
program.
In the statements above, there is a pattern that you will find recurring in many
programs that define robot behaviors using simple decisions:
while timeRemaing(<seconds>):
<sense>
<decide and then act>
Such behaviors are called reactive behaviors. That is, a robot is reacting to the
change in its environment by deciding how to act based on its sensor values.
A wide range of robot behaviors can be written using this program structure.
144
Insect‐Like Behaviors
Burglar Alarm Robot: Design a robot that watches your dorm door. As soon
as the door opens, it sounds an alarm (beeps).
Wall Detector: Write a robot program that goes straight and then stops when
it detects a wall in front. You will be using the IR sensors for this task.
Measuring Device: You have calibrated your robot with regards to how far it
travels in a given amount of time. You can use that to design a robot that
145
Chapter 6
measures space. Write a program that enables a robot to measure the width of
a hallway.
Follower: Write a robot program to exhibit the following behavior: The robot
prefers to stay near a wall (in front). If it does not have a wall in front of it, it
moves forward until it finds it. Test your program first by placing the robot in
a play pen. Ensure that your program behaves as described. Next, place it on a
floor and hold a blank piece of paper in front of it (close enough so the robot
can detect it). Now, slowly move the paper away from the robot. What
happens?
Most of the robot behaviors that are implemented using the Braitenberg style
rely on a few simple things: selecting one or more sensors; choosing the kind
of wiring (straight or crossed); and selecting normalization functions for each
sensor. While you can guess the behavior that may result from these designs
the only way to confirm this is by actually watching the robot carry out the
behavior. You also saw how, using if-statements you can design simple, yet
interesting robot. In this section we will design additional reactive behaviors.
Light Following
146
Insect‐Like Behaviors
# Light follower
# program settings...
thresh = 50
fwdSpeed = 0.8
cruiseSpeed = 0.5
turnSpeed = 0.7 # left turn, -0.7 will be right turn
def main():
while True:
# get light sensor values for left, center, and right
L, C, R = getLight()
Notice that, in the program above, we have decided to set values for light
threshold (thresh) as well as movements to specific values. Also, in all cases,
we are using the move command to specify robot movement. This is because
the move command allows us to blend translation and rotation movement.
Additionally, notice that regardless of the sensor values, the robot is always
moving forward some amount even while turning. This is essential since the
robot has to follow the light and not just orient towards it. In the case where
there is no bright light present, the robot is still moving forward (at half the
cruise speed).
147
Chapter 6
In the design of the light following robot above, we used a threshold value for
detecting the presence of bright light. Sometimes it is more interesting to use
differential thresholds for sensor values. That is, is the light sensor's value
different from the ambient light by a certain threshold amount? You can use
the senses function again observe the differences from ambient light and
modify the program above to use the differential instead of the fixed
threshold.
Here is another idea. Get several of your classmates together in a room with
their robots, all running the same program. Make sure the room has plenty of
floor space and a large window with a curtain. Draw close the curtains so the
outside light is temporarily blocked. Place the robots all over the room and
start the program. The robots will scurry around, cruising in the direction of
their initial orientation. Now, slowly draw the curtains open to let in more
light. What happens?
Avoiding Obstacles
Obstacles in the path of a robot can be detected using the IR sensors in front
of the robot. Then, based on the values obtained, the robot can decide to turn
away from an approaching obstacle using the following algorithm:
148
Insect‐Like Behaviors
# Avoiding Obstacles
# program settings...
cruiseSpeed = 0.6
turnSpeed = 0.5 # this is a left turn, -0.5 will be right
turn
def main():
while True:
# get sensor values for left and right IR sensors
L, R = getIR()
L = 1 - L
R = 1 - R
As in the case of the light follower, observe that we begin by setting values
for movements. Additionally, we have flipped the values of the IR sensors so
that the conditions in the if-statements look more natural. Recall that the IR
sensors report a 1 value in the absence of any obstacle and a 0 in the presence
of one. By flipping them (using 1 - value) the value is 1 for an obstacle
149
Chapter 6
present and 0 otherwise. These values make it more natural to write the
conditions in the program above. Remember in Python, a 0 is equivalent to
False and a 1 is equivalent to True. Read the program above carefully and
make sure you understand these subtleties. Other than that, the program
structure is very similar to the light follower program.
Another way to write a similar robot behavior is to use the value of the stall
sensor. Recall that the stall sensor detects if the robots has bumped against
something. Thus, you can write a behavior that doesn't necessarily avoid
obstacles, but navigates itself around by bumping into things. This is very
similar to a person entering a dark room and then trying to feel their way by
touching or bumping slowly into things. In the case of the robot, there is no
way to tell if the bump was on its left or right. Nevertheless, if you use the
program (shown below) you will observe fairly robust behavior from the
robot.
# program settings...
cruiseSpeed = 1.0
turnSpeed = 0.5 # this is a left turn, -0.5 will be right
turn
def main():
while True:
if getStall():
# I am stalled, turn (randomly?)
move(0, turnSpeed)
else:
# I am not stalled, cruise on
move(cruiseSpeed, 0)
main()
150
Insect‐Like Behaviors
At times, you may notice that the robot gets stuck even when trying to turn.
One remedy for this is to stop the robot, back up a little, and then turn.
Do This: Implement the program above, observe the robot behavior. Next,
modify the program as suggested above (when stalled stop, backup, then
turn).
Maze Solver: Create a simple maze for your robot. Place the robot at one end
of the maze and use the obstacle avoidance programs from above (both
versions). Does you robot solve the maze? If not, note if your maze is right
handed or left handed (i.e. every turn is a right turn or left turn in the maze),
or both. Modify the obstacle avoidance programs to solve the right-handed,
left-handed mazes. How would you enable the robot to solve a maze that has
both right and left turns?
Corral Exiting
OK Corral?
Given that a simple obstacle
avoidance program can enable a
robot to solve simple mazes, we
can also design more interesting
behaviors on top of that. Imagine a
corral: an enclosed area with maze
like partitions and an entrance,
with a light source at the entrance
(see picture on right). Given the
robot's position, can we design a
behavior that will enable the robot
to exit the corral?
One can design a solution for the specific corral shown here: follow a wall
(any wall) until it sees bright light then switch to light seeking. Can the
Scribbler be designed to follow a wall? Remember the Fluke dongle has left
and right obstacle sensors that are pointing to its sides. Another approach will
be to combine the obstacle avoidance behavior from above with the light
151
Chapter 6
seeker behavior. That is, in the absence of any bright light, the robot moves
around the corral avoiding obstacles and when it sees a bright light, it heads
towards it. The hard part here will be to detect that it has exited the corral and
needs to stop.
Summary
Braitenberg uses very simple ideas to enable people to think about the way
animal and human brains and bodies are wired. For example, in humans, the
optic nerves (as do some others) have crossed connections inside the brain.
That is, the nerves from the left eye are connected to the right side of the brain
and vice versa. Actually they cross over and some information from either
side is also represented on the same side (that is there are straight as well as
crossed connections). However, it is still a puzzle among scientists as to why
this is the case and what, if any, are the advantages or disadvantages of this
scheme. Similarly, observing the behaviors of Vehicles 2a and 2b one can
easily see in them parallels in the behavior of several animals, like flies
orienting towards light/heat sources. Simple robot behaviors can provide deep
insights into complex behavior: that the observation and analysis of something
is an uphill task if one doesn't know the internal structure. And, by
constructing simple internal structures one can arrive at seemingly complex
behaviors. These seemingly complex behaviors have also been shown to
influence group behavior in insects (see the picture of article on next page).
That is, robots that do not look anything like insects, and not too different in
size than the Scribbler, can be used to influence insect behavior in many
situations.
In this chapter, we have attempted to give you a flavor for the idea of
synthetic psychology. At the same time you have also learned how to program
internal structures in a robot brain and learned several techniques for robot
control.
152
Insect‐Like Behaviors
Background
All the numbered vehicles described here were developed in a set of thought
experiments designed by Valentino Braitenberg in his book, Vehicles:
Experiments in Synthetic Psychology, MIT Press, 1984.
Some of the other vehicles described here were designed by David Hogg,
Fred Martin, and Mitchel Resnick of the MIT Media Laboratory. Hogg et al
153
Chapter 6
used specialized electronic LEGO bricks to build these vehicles. For more
details, see their paper titled, Braitenberg Creatures.
To read more about robots influencing insect behavior see the November 16,
2007 issue of Science magazine. The primary article that is discussed in the
picture above is by Halloy et al, Social Integration of Robots into Groups of
Cockroaches to Control Self-Organized Choices, Science, November 16,
2007. Volume 318, pp 1155-1158.
Myro Review
Python Review
if <condition>:
<this>
if <condition>:
<this>
else:
<that>
if <condition-1>:
<this>
elif <condition-2>:
<that>
elif <condition-3>:
<something else>
...
...
else:
<other>
154
Insect‐Like Behaviors
Exercises
1. An even better way of averaging the ambient light conditions for purposes
of normalization is to have the robot sample ambient light all around it. That
is, turn around a full circle and sample the different light sensor values. The
ambient value can then be set to the average of all the light values. Write a
function called, setAmbient that rotates the robot for a full circle (or you
could use time), samples light sensor values as it rotates, and then returns the
average of all light values. Change the line:
Ambient = sum(getLight())/3.0
to the line:
Ambient = setAmbient()
Try out all of the earlier behaviors described in this chapter to see how this
new mechanism affects the robot's behavior.
2. Design and implement a program that exhibits the corral exiting behavior
described in this chapter.
155
Opposite page: Mars Rover.
Photo courtesy of NASA/JPLCaltech
Behavior Control
Oh, Behave!
Austin Powers (played by Mike Myers) in the movie
Austin Powers: International Man of Mystery,
New Line Cinema, 1997.
157
Chapter 7
Writing programs is all about exercising control. In the case of a robot’s brain
your program directs the operations of a robot. However, it is also important
to realize that the program itself is really controlling the computer. That is,
when you write Python programs you are controlling the computer that is then
communicating with the robot. Your program is directing the computer to
control the robot. If you take Myro out of the picture you are writing
programs to control the computer. This is the sense in which learning with
robots also leads to learning computing. Every program you write is doing
computation. Contrary to popular misconceptions computing is not just about
doing calculations with numbers. Controlling your robot is also computing, as
is predicting the world’s population, or composing an image, etc. This is one
aspect of control.
When writing robot control programs, the structure you use to organize the
program itself is a control strategy. Programming a robot is specifying
automated control. As a programmer or behavior designer you structure your
program to accomplish the goals of the behavior: how the sensors are used to
decide what to do next. This is another aspect of control. So far, you have
seen how to write control programs using Braitenberg style sensor-motor
wiring. You have also seen how to specify reactive control. These are
examples of two robot control paradigms.
In this chapter we delve further into the world of computation and robot
control paradigms. We will learn how to write robot control programs for
more complex and more robust robot tasks. We will also see how, using the
concepts learned so far, we can write useful and interesting computer
applications.
Behaviorbased Control
When writing robot control programs, so far, you have used a very basic
technique in designing control programs:
158
Behavior Control
def main():
# do forever or for some time
# or until a certain condition is satisfied
As you have seen, such a control program works well for many simple tasks.
However, you may have already run into many situations where, once the task
gets a little complex, it becomes difficult to structure a program in terms of a
single stream of control as shown above. For example, the corral exiting
behavior from the last chapter requires you to combine two simple behaviors:
solve a maze (avoid obstacles) and seek light to get out of the corral. As you
have seen before, it is fairly easy to program each of the individual behaviors:
obstacle avoidance; light following. But, when you combine these behaviors
to accomplish the corral exiting behavior two things happen: you are forced to
amalgamate the two control strategies into a single one and it may become
difficult to decide which way to combine them; additionally, the resulting
program is not very pretty and hard to read. In reality, hardly any robot
programs are written that way. In this section, we will look at a different way
of structuring robot programs that makes designing behaviors easy, and yet,
the resulting structure of the overall program is also clean and straightforward.
You can design some very sophisticated behaviors using these ideas.
People in the robotics community call the style of programming shown above
as reactive control or direct control. Also referred to as sensor fusion, the
resulting programs are purely sensor driven and hence appear to be too
bottom-up. That is, the values of the sensors drive the logic of control as
opposed to the goals of the robot tasks themselves. In behavior-based control
you get away from sensors and focus the design of your robot programs based
on the number and kinds of behaviors your robot has to carry out.
159
Chapter 7
In the diagram above, we have shown the three basic behaviors that we are
trying to combine: Cruise, Avoid, SeekLight. Each of these behaviors
outputs a triple: Yes/No, Translate Speed, Rotate Speed. A Yes implies that the
behavior module has a recommendation. No implies that it doesn't. That is, it
allows the possibility of a behavior having no recommendation. For example,
in the corral exiting situation, in the absence of a light source being sensed by
the robot, the SeekLight module will not have any recommendation. It then
becomes the task of the arbitrator (or the decision module) to decide which of
the available recommendations to use to drive the robot. Notice that in the end
to control the robot, all one has to do is decide how much to translate and
rotate. Many different arbitration schemes can be incorporated. We will use a
simple but effective one: Assign a priority to each behavior module. Then the
arbitrator always chooses the highest priority recommendation. This style of
control architecture is also called subsumption architecture. In the figure
above, we have actually drawn the modules in the order of their priority: the
higher the module is in the figure, the higher its priority. The lowest behavior,
cruise does not require any sensors and is always present: it wants the robot to
always go forward.
160
Behavior Control
cruiseSpeed = 0.8
turnSpeed = 0.8
lightThresh = 80
def cruise():
# is always ON, just move forward
return [True, cruiseSpeed, 0]
def avoid():
# see if there are any obstacles
L, R = getIR()
L = 1 - L
R = 1 - R
if L:
return [True, 0, -turnSpeed]
elif R:
return [True, 0, turnSpeed]
else:
return [False, 0, 0]
161
Chapter 7
def seekLight():
L, C, R = getLight()
if L < lightThresh:
return [True, cruiseSpeed/2.0, turnSpeed]
elif R < lightThresh:
return [True, cruiseSpeed/2.0, -turnSpeed]
else:
return [False, 0, 0]
In the above, you can see that each individual behavior is simple and is easy
to read (and write). There are several ways to incorporate these into a
behavior-based program. Here is one:
def main():
while True:
T, R = arbitrate()
move(T, R)
main()
The main program calls the arbitrate function that returns the chosen translate
and rotate commands which are then applied to the robot. The function
arbitrate is simple enough:
162
Behavior Control
Do This: Implement the program above and see how well the robot behaves
in navigating around and exiting the corral. What happens if you change the
priority (ordering in the list) of behaviors? In writing the program above, we
have used two new Python features. We will review these next.
we used the names seekLight, avoid, and cruise to denote the functions
that they represented. We named these functions earlier in the program (using
def). Thus, the list named behaviors is a list of function names each of which
denote the actual function as its value. Next, look at the way we used the
variable behaviors in the function arbitrate:
Since behaviors is a list it can be used in the loop to represent the sequence
of objects (in this case functions). Thus in each iteration of the loop, the
variable behavior takes on successive values from this list: seekLight,
avoid, and cruise. When the value of the variable is seekLight, the function
seekLight is called in the statement:
output, T, R = behavior()
163
Chapter 7
The other new aspect of Python that we have used in the program above is the
fact that a function can return any object as its value. Thus the functions
cruise, avoid, seekLight, and arbitrate all return lists as their values.
ceil(x) Returns the ceiling of x as a float, the smallest integer value greater
than or equal to x.
floor(x) Returns the floor of x as a float, the largest integer value less than
or equal to x.
exp(x) Returns .
164
Behavior Control
log(x[, base]) Returns the logarithm of x to the given base. If the base is
not specified, return the natural logarithm of x (i.e., log ).
pow(x, y) Returns .
Some of the other functions available in the math module are listed at the end
of the chapter. In order to use any of these all you have to do is import the
math module:
import math
>>> math.ceil(5.34)
6.0
>>> math.floor(5.34)
5.0
>>> math.exp(3)
20.085536923187668
>>> math.log10(1000)
3.0
>>> math.log(1024, 2)
10.0
>>> math.pow(2, 10)
1024.0
>>> math.sqrt(7.0)
2.6457513110645907
165
Chapter 7
5.0
>>> exp(3)
20.085536923187668
>>> log10(1000)
3.0
>>> log(1024,2)
10.0
>>> sqrt(7.0)
2.6457513110645907
import <module>
You have to prefix all its commands with the module name (as the case in the
first set of examples above). We have also been using the form
This imports all functions and other objects provided in the module which can
then be used without the prefix. You can also individually import specific
functions from a module using:
Which version you use may depend on the context in which you use the
imported functions. You may run into a situation where two different modules
define functions with the same name but to do different things (or to do things
in a different way). In order to use both functions in the same module you will
have to use the module prefix to make clear which version you are using.
Doing Computations
Lets us weave our way back to traditional style computing for now. You will
see that the concepts you have learned so far will enable you to write lots of
different and more interesting computer applications. It will also give you a
clear sense of the structure of typical computer programs. Later, in Chapter
166
Behavior Control
11, we will also return to the larger issue of the design of general computer
programs.
A Loan Calculator
Your current car, an adorable 1992 SAAB 93 was bought used and, for past
several months, you have had nothing but trouble keeping the car on the road.
Last night the ignition key broke off in the key slot when you were trying to
start it and now the broken piece would not come out (this used to happen a
lot with older SAAB's). The mechanic has to dismantle the entire ignition
assembly to get the broken key out and it could cost you upwards of $500.
The car's engine, which has done over 185,000 miles, has left you stranded on
the road many times. You have decided that this is it; you are going to go out
and get yourself a brand new reliable car. You have been moonlighting at a
restaurant to make extra money and have managed to save $5500.00 for
exactly this situation. You are now wondering what kind of new car you can
buy. Obviously, you will have to take a loan from a bank to finance the rest of
the cost but you are not sure how big a loan, and therefore what kind of car,
you can afford. You can write a small Python program to help you try out
various scenarios.
You can either dream (realistically) of the car you would like to buy, or you
can go to any of the helpful car buying sites on the web (www.edmunds.com
is a good place to start). Let us say that you have spent hours looking at
features and options and have finally narrowed your desires to a couple of
choices. Your first choice is going to cost you $22,000.00 and your second
choice is priced at $18,995.00. Now you have to decide which of these you
can actually afford to purchase.
First, you go talk to a couple of banks and also look at some loan offers on the
web. For example, go to bankrate.com and look for current rates for new car
loans.
Suppose the loan rates quoted to you are: 6.9% for 36 months, 7.25% for 48
months, and 7.15 for 60 months.
167
Chapter 7
You can see that there is a fair bit of variation in the rates. Given all this
information, you are now ready to write a program that can help you figure
out which of the two choices you may be able to make. In order to secure the
loan, you have to ensure that you have enough money to pay the local sales
tax (a 6% sales tax on a $20,000 car will add up to a hefty $1200!). After
paying the sales tax you can use the remainder of the money you have saved
up towards the down payment. The remainder of the money is the amount that
you would borrow. Depending on the type of loan you choose, your monthly
payments and how long you will make those payments will vary. There is a
simple formula that you can use to estimate your monthly payment:
Whoa! That seems complicated. However, given the formula, you can see that
it really requires two mathematical functions: log and , both of which
are available in the Python math module. Suddenly, the problem seems not
that hard.
Let us try and outline the steps needed to write the program: First, note the
cost of the car, the amount of money you have saved, and the sales tax rate
Also, note the financials: the interest rate, and the term of the loan. The
interest rate quoted is generally the annual percentage rate (APR) convert it to
monthly rate (by dividing it by 12). Next, compute the sales tax you will pay.
Use the money left to make a down payment. Then determine the amount you
will borrow. Plug in all of the values in the formula and compute the monthly
payment. Also, compute the total cost of the car. Output all the results. Next,
we can take each of the above steps and start to encode them into a program.
Here is a first order refinement:
def main():
# First, note the cost of the car (Cost),
# the amount of money you have saved (Cash),
# and the sales tax rate (TaxRate)
168
Behavior Control
main()
Above, we have taken the steps and converted them into a skeletal Python
program. All the steps are converted to Python comments and where needed,
we have decided the names of variables that will hold the values that will be
needed for the calculations. This is useful because this also helps determine
how the formula will be encoded and also helps determine what values can be
programmed in and which ones you will have to supply as input. Making the
program require inputs will easily enable you to enter the different parameters
and then based on the outputs you get, you can decide which car to buy. Let
us encode all the inputs first:
def main():
# First, note the cost of the car (Cost),
Cost = input("Enter the cost of the car: $")
169
Chapter 7
APR = input("Enter the APR for the loan (in %): ")
main()
We have refined the program to include the inputs that will be needed for each
run of the program. Notice that we chose not to input the sales tax rate and
instead just assigned it to the variable SalesTaxRate. If you wanted, you
could also have that be entered as input. What you choose to have as input to
your program is your design decision. Sometimes the problem may be framed
so it explicitly specifies the inputs; sometimes you have to figure that out. In
general, whatever you need to make your program more versatile is what you
have to base your decisions on. For instance, fixing the sales tax rate to 6.0
will make the program usable only in places where that rate applies. If, for
example, you wanted your friend in another part of the country to use the
program, you should choose to make that also an input value. Let us go on to
the next steps in the program and encode them in Python. These are mainly
computations. The first few are simple. Perhaps the most complicated
computation to encode is the formula for computing the monthly payment. All
of these are shown in the version below.
def main():
# First, note the cost of the car (Cost),
Cost = input("Enter the cost of the car: $")
170
Behavior Control
171
Chapter 7
main()
Do This: When you enter the above program and run it in Python, you can
enter the data about your car. Here is a sample run:
It appears that at for the $20000.00 car, for a 36 month 6.9% loan you will
end up paying $484.05 (or $484.06 depending upon how your loan company
round pennies!).
When you need to restrict your output values to specific decimal places (two
in the case of dollars and cents, for example), you can use the string
formatting features built into Python. For example, in a string, you can specify
how to include a floating point value as follows:
172
Behavior Control
<string> % <expression>
We deliberately specified that the value be 1 space wide with 4 spaces after
the decimal (i.e. %1.4f). As you can see, the space was expanded to
173
Chapter 7
accommodate the value. What is assured is that the value is always printed
using the exact number of spaces after the decimal. Here is another example:
Thus, the value is printed as 5.000 (i.e. the three places after the decimal are
always considered relevant in a specification like %1.3f). Similarly, for
specifying whole number or integer values you can use the letter-d, and for
strings you can use the letter-s:
Having such control over printed values is important when you are trying to
output tables of aligned values. Let us modify our program from above to use
these formatting features:
def main():
# First, note the cost of the car (Cost),
Cost = input("Enter the cost of the car: $")
174
Behavior Control
main()
175
Chapter 7
When you run it again (say for a slightly different loan term), you get:
You can see that for the same amount if you borrow it for a longer period you
can reduce your monthly payments by over $100 (but you pay about $700
more in the end).
Computers have been extensively used in game playing: for playing games
against people and other computers. The impact of computers on game
playing is so tremendous that these days several manufacturers make game
176
Behavior Control
If we represent the three items in a list, we can have the computer pick one of
them at random by using the random number generation facilities provided in
Python. If the items are represented as:
Then we can select any of the items above as the computer's choice using the
expression:
177
Chapter 7
Now that we know how to the computer and player make their selection, we
need to think about deciding the outcome. Here is an outline:
Rewriting the above using if-statements we get the following first draft:
if myChoice == yourChoice:
print "It is a draw."
if <myChoice beats yourChoice>:
print "I win."
else:
print "You win."
178
Behavior Control
All we need to do is figure out how to write the condition <myChoice beats
yourChoice>. The condition has to capture the rules of the game mentioned
above. We can encode all the rules in a conditional expression as follows:
The conditional expression above captures all of the possibilities that should
be examined in order to make the decision. Another way of writing the above
decision would be to use the following:
That is each condition is examined in turn until one is found that confirms that
the computer wins. If none such condition is true, the else-part of the if-
statement will be reached to indicate that the player won.
if myChoice == yourChoice:
print "It is a draw."
if beats(myChoice, yourChoice):
print "I win."
else:
print "You win."
179
Chapter 7
Let us take a closer look at how we could define the beats function. It needs
to return True if myChoice beats yourChoice. So all we need to do is encode
the rules of the game described above. Here is a draft of the function:
Once again, we have used the if-statements in Python to encode the rules of
the game. Now that we have completely fleshed out all the critical parts of the
program, we can put them all together as shown below:
180
Behavior Control
def main():
# Play a round of Paper, Scissors, Rock!
print "Lets play Paper, Scissors, Rock!"
print "In the window that pops up, make your selection>"
main()
A few more print commands were added to make the interaction more natural.
Do This: Implement the Paper, Scissors, Rock program from above and play
it several times to make sure you understand it completely. Modify the
program above to play several rounds. Also, incorporate a scoring system that
181
Chapter 7
keeps track of the number of times each player won and also the number of
draws.
Summary
Myro Review
Python Review
ceil(x) Returns the ceiling of x as a float, the smallest integer value greater
than or equal to x.
floor(x) Returns the floor of x as a float, the largest integer value less than
or equal to x.
exp(x) Returns .
182
Behavior Control
log(x[, base]) Returns the logarithm of x to the given base. If the base is
not specified, return the natural logarithm of x (i.e., log ).
pow(x, y) Returns .
Trigonometric functions
183
Chapter 7
Exercises
yourChoice = items[randint(0,2)]
yourChoice = choice(items)
6. Implement the HiLo game: the computer picks a random number between 0
and 1000 and the user has to try and guess it. With every guess the computer
informs the user f their guess was high (Hi), low (Lo), or they got it.
7. Reverse the roles in the HiLo game from above. This time, the user guesses
a number between 0 and 1000 and computer program has to guess it. Think
about a good strategy for guessing the number based on high and low clues,
and then implement that strategy.
184
Behavior Control
185
Opposite page: Mars Rover.
Photo courtesy of NASA/JPLCaltech
Sights & Sounds
Don't make music for some vast, unseen audience or market or ratings share
or even for something as tangible as money. Though it's crucial to make a
living, that shouldn't be your inspiration. Do it for yourself.
-Billy Joel
187
Chapter 8
We mentioned earlier that the notion of computation these days extends far
beyond simple numerical calculations. Writing robot control programs is
computation, as is making world population projections. Using devices like
iPods you are able to enjoy music, videos, and radio and television shows.
Manipulating sounds and images is also the realm of computation and in this
chapter we will introduce you to these. You have already seen how, using
your robot, you can take pictures of various scenes. You can also take similar
images from your digital camera. Using basic computational techniques you
have learned so far you will see, in this chapter, how you can do computation
on shapes and sound. You will learn to create images using computation. The
images you create can be used for visualizing data or even for aesthetic
purposes to explore your creative side. We will also present some
fundamentals of sound and music and show you how you can also do similar
forms of computation using music.
Sights: Drawing
If you have used a computer for any amount of time you must have used some
kind of a drawing application. Using a typical drawing application you can
draw various shapes, color them etc. You can also generate drawings using
drawing commands provided in the Myro library module. In order to draw
anything you first need a place to draw it: a canvas or a window. You can
create such a window using the command:
myCanvas = GraphWin()
If you entered the command above in IDLE, you will immediately see a small
gray window pop up (see picture on right). This window will be serving as
our canvas for creating drawings. By default, the window created by the
GraphWin command is 200 pixels high and 200 pixels wide and its name is
“Graphics Window”. Not a very inspiring way to start, but the GraphWin
command has some other variations as well. First, in order to make the
window go away, you can use the command:
188
Sights & Sounds
myCanvas = GraphWin(“My
Masterpiece”, 200, 300)
189
Chapter 8
In a graphics window with width, W and height H (i.e WxH pixels) the pixel
(0, 0) is at the top left corner and the pixel (199, 299) will be at the bottom
right corner. That is, x-coordinates increase as you go right and y-coordinates
increase as you go down.
The simplest object that you can create is a point. This is done as follows:
p = Point(100, 50)
p.draw(myCanvas)
The syntax of the above command may seem a little strange at first. You saw
it briefly when we presented lists in Chapter 5 but we didn’t dwell on it.
Certainly it is different from what you have seen so far. But if you think about
the objects you have seen so far: numbers, strings, etc. Most of them have
standard operations defined on them (like +, *, /, etc.). But when you think
about geometrical objects, there is no standard notation. Programming
languages like Python provide facilities for modeling any kind of object and
the syntax we are using here is standard syntax that can be applied to all kinds
of objects. The general form of commands issued on objects is:
<object>.<function>(<parameters>)
Thus, in the example above, <object> is the name p which was earlier
defined to be a Point object, <function> is draw, and <parameters> is
myCanvas. The draw function requires the graphics window as the parameter.
That is, you are asking the point represented by p to be drawn in the window
specified as its parameter. The Point objects have other functions available:
>>> p.getX()
100
190
Sights & Sounds
>>> p.getY()
50
That is, given a Point object, you can get its x- and y-coordinates. Objects are
created using their constructors like the Point(x, y) constructor above. We
will use lots of constructors in this section for creating the graphics objects. A
line object can be created similar to point objects. A line requires the two end
points to be specified. Thus a line from (0, 0)
to (100, 200) can be created as:
L = Line(Point(0,0), Point(100,200))
L.draw(myCanvas)
Here is a small Python loop that can be used to create and draw several lines:
each value of n a new Line object is created with starting co-ordinates (n,
25) and end point at (100, 100).
Do This: Try out all the commands introduced so far. Then observe the
effects produced by the loop above. Change the increment 5 in the loop above
to different values (1, 3, etc.) and observe the effect. Next, try out the
following loop:
The undraw function does exactly as the name implies. In the loop above, for
each value that n takes, a line is created (as above), drawn, and then, after a
wait of 0.3 seconds, it is erased. Again, modify the value of the increment and
observe the effect. Try also changing the amount of time in the wait
command.
You can also draw several geometrical shapes: circles, rectangles, ovals, and
polygons. To draw a circle, (or any geometrical shape), you first create it and
then draw it:
C = Circle(centerPoint, radius)
c.draw(myCanvas)
Rectangles and ovals are drawn similarly (see details at the end of the
chapter). All geometrical objects have many functions in common. For
192
Sights & Sounds
example, you can get the center point of a circle, a rectangle, or an oval by
using the command:
centerPoint = C.getCenter()
By default, all objects are drawn in black. There are several ways to modify or
specify colors for objects. For each object you can specify a color for its
outline as well as a color to fill it with. For example, to draw a circle centered
at (100, 150), radius 30, and outline color red, and fill color yellow:
By the way, setFill and setOutline have the same effect on Point and
Line objects (since there is no place to fill any color). Also, the line or the
outline drawn is always 1 pixel thick. You can change the thickness by using
the command setWidth(<pixels>):
C.setWidth(5)
The command above changes the width of the circle’s outline to 5 pixels.
Do This: Try out all the commands introduced here. Also, look at the end of
the chapter for details on drawing other shapes.
Earlier, we mentioned that several colors have been assigned names that can
be used to select colors. You can also create colors of your own choosing by
specifying their red, green, and blue values. In Chapter 5 we mentioned that
each color is made up of three values: RGB or red, green and blue color
values. Each of the these values can be in the range 0..255 and is called a 24-
bit color value. In this way of specifying colors, the color with values (255,
255, 255) (that is red = 255, green = 255, and blue = 255) is white; (255, 0, 0)
is pure red, (0, 255, 0), is pure blue, (0, 0, 0) is black, (255, 175, 175) is pink,
etc. You can have as many as 256x256x256 colors (i.e. over 16 million
193
Chapter 8
colors!). Given specific RGB values, you can create a new color by using the
command, color_rgb:
Do This: The program below draws several circles of random sizes with
random colors. Try it out and see its outcome. A sample output screen is show
on the right. Modify the program to input a number for the number of circles
to be drawn. randrange(m,n) returns a random number in range [m..n-1].
def makeColor():
# creates a new color using random RGB values
red = randrange(0, 256)
green = randrange(0, 256)
blue = randrange(0, 256)
return color_rgb(red, green,blue)
def main():
# Create and display a
# graphics window
width = 500
height = 500
myCanvas =
GraphWin(‘Circles’,width,height)
myCanvas.setBackground("white")
194
Sights & Sounds
c.draw(myCanvas)
main()
def makeCircle():
# creates a Circle centered at point (x, y) of radius r
x = randrange(0,width)
y = randrange(0,height)
r = randrange(5, 25)
Python defines the scope of a name in a program textually or lexically. That is,
any name is visible in the text of the program/function after it has been
defined. Note that the notion of after is a textual notion. Moreover, Python
restricts the accessibility of a name to the text of the function in which it is
195
Chapter 8
defined. That is, the names width and height are defined inside the function
main and hence they are not visible anywhere outside of main. Similarly, the
variables red, green, and blue are considered local to the definition of
makeColor and are not accessible outside of the function, makeColor.
So how can makeCircle, if you decided it would generate the x and y values
relative to the window size, get access to the width and height of the window?
There are two solutions to this. First, you can pass them as parameters. In that
case, the definition of makeCircle will be:
Then the way you would use the above function in the main program would
be using the command:
C = makeCircle(width, height)
That is, you pass the values of width and height to makeCircle as
parameters. The other way to define makeCircle would be exactly as shown
in the first instance:
def makeCircle():
# creates a Circle centered at point (x, y) of radius r
x = randrange(0,width)
y = randrange(0,height)
r = randrange(5, 25)
However, you would move the definitions of width and height outside and
before the definitions of all the functions:
196
Sights & Sounds
width = 500
height = 500
def makeCircle():
…
def makeColor():
…
def main():
…
Since the variables are defined outside of any function and before the
definitions of the functions that use them, you can access their values. You
may be wondering at this point, which version is better? Or even, why bother?
The first version was just as good. The answer to these questions is similar in
a way to writing a paragraph in an essay. You can write a paragraph in many
ways. Some versions will be more preferable than others. In programming, the
rule of thumb one uses when it comes to the scope of names is: ensure that
only the parts of the program that are supposed to have access to a name are
allowed access. This is similar to the reason you would not share your
password with anyone, or your bank card code, etc. In our second solution, we
made the names width and height globally visible to the entire program that
follows. This implies that even makeColor can have access to them whether it
makes it needs it or not.
You may want to argue at this point: what difference does it make if you
make those variables visible to makeColor as long as you take care not to use
them in that function? You are correct, it doesn’t. But it puts an extra
responsibility on your part to ensure that you will not do so. But what is the
guarantee that someone who is modifying your program chooses to?
197
Chapter 8
Any object drawn in the graphics window can be moved using the command
move(dx, dy). For example, you move the circle 10 pixels to the right and 5
pixels down you can use the command:
C.move(10, 5)
Do This: Let us write a program that moves a circle about (randomly) in the
graphics window. First, enter this following program and try it out.
def main():
# create and draw the graphics window
w = GraphWin("Moving Circle", 500, 500)
w.setBackground("white")
main()
198
Sights & Sounds
Notice, in the above program, that we are moving the circle around randomly
in the x- and y directions. Try changing the range of movements and observe
the behavior. Try changing the values so that the circle moves only in the
horizontal direction or only in the vertical direction. Also notice that we had
to slow down the animation by inserting the wait command after every move.
Comment the wait command and see what happens. It may appear that
nothing did happen but in fact the 200 moves went so quickly that your eyes
couldn’t even register a single move! Using this as a basis, we can now write
a more interesting program. Look at the program below:
def main():
# create and draw the graphics window
winWidth = winHeight = 500
w = GraphWin("Bouncing Circle", winWidth, winHeight)
w.setBackground("white")
# Animate it
dx = dy = 3
while timeRemaining(15):
# move the circle
c.move(dx, dy)
199
Chapter 8
wait(0.01)
main()
For 15 seconds, you will see a red circle bouncing around the window. Study
the program above to see how we keep the circle inside the window at all
times and how the direction of the ball bounce is being changed. Each time
you change the direction, make the computer beep:
computer.beep(0.005, 440)
If you are excited about the possibility of animating a circle, imagine what
you can do if you have many circles and other shapes animated. Also, plug in
the game pad controller and see if you can control the circle (or any other
object) using the game pad controls. This is very similar to controlling your
robot. Design an interactive computer game that takes advantage of this new
input modality. You can also design multi-user games since you can connect
multiple game pad controllers to your computer. See the Reference
documentation for details on how to get input from several game pad
controllers.
Like shapes, you can also place text in a graphics window. The idea is the
same. You first create the text using the command:
and then draw it. You can specify the type face, size, and style of the text. We
will not detail these here. They are summarized in the reference at the end of
the text. When we get an opportunity, we will use these features below in
other examples.
200
Sights & Sounds
Images in this system are treated just like any other objects. You can create an
image using the Image command:
You have to have an already prepared image in one of the common image
formats (like JPEG, GIF, etc.) and stored in a file (<file name>). Once the
image object is created, it can be drawn, undrawn, or moved just like other
shapes.
What you do with all this new found functionality depends on your creativity.
You can use graphics to visualize some data: plotting the growth of world
population, for example; or create some art, an interactive game, or even an
animated story. You can combine your robot, the game pad controller, or even
sound to enrich the multi-media experience. The exercises at the end of the
chapter present some ideas to explore further. Below, we delve into sounds.
Sound
As we have seen, you can have your robot make beeps by calling the beep()
function, like so:
beep(1, 440)
This command instructs the robot to play a tone at 440 Hz for 1 second. Let us
first try and analyze what is in the 440 Hz tone. First, the letters Hz are an
abbreviation for Hertz. The name itself comes from a German physicist,
Heinrich Rudolph Hertz who did pioneering work in the production of
electromagnetic waves in the late 19th century. Today, we use Hertz (or Hz)
as a unit for specifying frequencies.
201
Chapter 8
The most common use of frequencies these days is in specifying the clock
speeds of computer CPU's. For example, a typical PC today runs at clock
speeds of a few GigaHertz (or GHz).
Sound is a periodic compression and refraction (or return to its original state)
of air (for simplicity, let us assume that the medium is air). One Cycle of a
sound comprises one compression and one refraction. Thus, producing a beep
at 440 Hz represents 440 complete cycles of compression and refraction.
Generally, a human ear is capable for hearing frequencies in the 20 Hz to
20000 Hz (or 20 Kilo Hertz) range. However the capability varies from
person to person. Also, many electronic devices are not capable for producing
frequencies in that entire range. 20-20KHz is considered hi-fidelity for stereo
or home theater audio components. Let us first examine the range of audible
sounds the Scribbler can produce. To make a sound out of the Scribbler, you
have to give a frequency and the duration (in seconds) that the sound should
be played. For example, to play a 440 Hz sound for 0.75 seconds:
beep(0.75, 440)
202
Sights & Sounds
The human ear is capable of distinguishing sounds that differ only by a few
Hertz (as little as 1 Hz) however this ability varies from person to person. Try
the commands:
beep(1, 440)
beep(1, 450)
Can you distinguish between the two tones? Sometimes it is helpful to place
these in a loop so you can repeatedly hear the alternating tones to be able to
distinguish between them. The next exercise can help you determine what
frequencies you are able to distinguish.
Exercise: Using the example above, try to see how close you can get in
distinguishing close frequencies. As suggested, you may want to play the
tones alternating for about 5-10 seconds. Start with 440 Hz. Can you hear the
difference between 440 and 441? 442? Etc. Once you have established your
range, try another frequency, say 800. Is the distance that you can distinguish
the same?
Do This: You can program the Scribbler to create a siren by repeating two
different tones (much like in the example above). You will have to experiment
with different pairs of frequencies (they may be close together or far apart) to
produce a realistic sounding siren. Write your program to play the siren for 15
seconds. The louder the better!
You can also have Myro make a beep directly out of your computer, rather
than the robot, with the command:
computer.beep(1, 440)
Unfortunately, you can't really have the robot and computer play a duet. Why
not? Try these commands:
beep(1, 440)
computer.beep(1, 440)
beep(1, 880)
computer.beep(1, 880)
203
Chapter 8
beep(1, 440)
computer.beep(1, 440)
What happens? Try your solutions to the above exercises by making the
sounds on the computer instead of the Scribbler.
Musical Scales
beep(1, 440)
beep(1, 880)
The second tone is exactly one octave the first. To raise a tone by an octave,
you simply multiply the frequency by 2. Likewise, to make a tone an octave
lower, you divide by 2. Notes indicating an octave can be denoted as follows:
C0 C1 C2 C3 C4 C5 C6 C7 C8
That is, C0 is the note for C in the lowest (or 0) octave. The fifth octave
(numbered 4) is commonly referred to as a middle octave. Thus C4 is the C
note in the middle octave. The frequency corresponding to C4 is 261.63 Hz.
Try playing it on the Scribbler. Also try C5 (523.25) which is twice the
frequency of C4 and C3 (130.815). In common tuning (equal temperament)
204
Sights & Sounds
the 12 notes are equidistant. Thus, if the frequency doubles every octave, each
successive note is 21 / 12 apart. That is, if C4 is 261.63 Hz, C# (or Db) will be:
/
C#4/Db4 = 261.63*2 = 277.18
D4 = 277.18 * 21 / 12 = 293.66
/
D#4/Eb = 293.66*2 = 311.13
etc.
The lowest tone that the Scribbler can play is A0 and the highest tone is C8.
A0 has a frequency of 27.5 Hz, and C8 has a frequency of 4186 Hz. That's
quite a range! Can you hear the entire range?
beep(1, 27.5)
beep(1, 4186)
Making Music
205
Chapter 8
This is the default octave. It is also the 5th octave, which can also be written
as:
The Myro Song Format replicates the keys on the piano, and so goes from A0
to C8. The middle octave on a keyboard is number 4, but we use 5 as the
default octave. See http://en.wikipedia.org/wiki/Piano_key_frequencies for
additional details. Here is a scale:
"C 1; C# 1; D 1; D# 1; E 1; F 1; F# 1; G 1; G# 1; A 1; A# 1; B
1; C 1;"
There are also a few other special note names, including PAUSE, REST, you can
leave the octave number off of the default octave notes if you wish. Use "#"
for sharp, and "b" for flat.
206
Sights & Sounds
Ab2 .125
or
Ab2 1/8
c 1
c .5
c .5
c 1
c .5
c .5
e 1
c .5
c .5
c 2
e 1
e .5
e .5
e 1
e .5
e .5
g 1
e .5
e .5
e 2
You may leave blank lines, and comments should begin with a # sign. Lines
can also be separated with a semicolon.
207
Chapter 8
Using a song
For the following exercises, you will need to have an object to play the song.
You will need to initialize the robot in a slightly different way. Rather than:
initialize()
do:
robot = Scribbler()
Now that you have a song, you probably will want to play it. If your song is in
a file, you can read it:
s = readSong(filename)
robot.playSong(s)
or on the computer:
computer.playSong(s)
s = makeSong("c 1; d 1; e 1; f 1; g 1; a 1; b 1; c7 1;")
If you want to make it play faster or slower, you could change all of the
WHOLENOTE numbers. But, if we just want to change the tempo, there is an
easier way:
robot.playSong(s, .75)
208
Sights & Sounds
Summary
You can use the graphics window as a way of visualizing anything. In the
graphics window you can draw all kinds of shapes: points, line, circles,
rectangles, ovals, polygons, text, and even images. You can also animate these
shapes as you please. What you can do with these basic drawing capabilities is
limited only by your creativity and your programming ability. You can
combine the sights you create with sounds and other interfaces, like the game
pad controller, or even your robot. The multimedia functionalities introduced
in this chapter can be used in all kinds of situations for creating interesting
programs.
Myro Reference
GraphWin()
GraphWin(<title>, <width>, <height>)
Returns a graphics window object. It creates a graphics window with title,
<title> and dimensions <width> x <height>. If no parameters are specified,
the window created is 200x200 pixels.
<window>.close()
Closes the displayed graphics window <window>.
<window>.setBackground(<color>)
Sets the background color of the window to be the specified color. <color>
can be a named color (Google: color names list), or a new color created using
the color_rgb command (see below)
209
Chapter 8
Point(<x>, <y>)
Creates a point object at (<x>, <y>) location in the window.
<point>.getX()
<point>.getY()
Returns the x and y coordinates of the point object <point>.
Rectangle(<point1>, <point2>)
Creates a rectangle object with opposite corners located at <point1> and
<point2>.
Oval(<point1>, <point2>)
Creates an oval object in the bounding box defined by the corner points
<point1> and <point2>.
210
Sights & Sounds
<object>.draw(<window>)
Draws the <object> in the specified graphics window <window>.
<object>.undraw()
Undraws <object>.
<line-object>.getP1()
<line-object>.getP2()
Returns the end points of the <line-object>.
<object>.getCenter()
Returns the center point of the <object>.
<object>.setOutline(<color>)
<object>.setFill(<color>)
Sets the outline and the fill color of the <object> to the specified <color>.
<object>.setWidth(<pixels>)
Sets the thickness of the outline of the <object> to <pixels>.
<object>.move(<dx>, <dy>)
Moves the object <dx>, <dy> from its current position.
beep(<seconds>, <frequency>)
beep(<seconds>, <f1>, <f2>)
Makes robot beep for <seconds> time at frequency specified. You can specify
a single frequency <frequency> or a mix of two: <f1> and <f2>.
211
Chapter 8
robot.playSong(<song>)
Plays the <song> on the robot.
readSong(<filename>)
Reads a song file from <filename>.
song2text(song)
Converts a <song> to text format.
makeSong(<text>)
text2song(<text>)
Converts <text> to a song format.
Python reference
Exercises
212
Sights & Sounds
4. Suppose that each robot from the previous exercise is colored using one of
the colors: red, blue, green, and yellow. Each time a robot is drawn, it uses the
next color in the sequence. Once the sequence is exhausted, it recycles. Write
a program to draw the above pyramid so robots appear in these colors as they
are drawn. You may decide to modify drawRobot to have an additional
parameter: drawRobot(x, y, c, w) or you can write it so that drawRobot
decides which color it chooses. Complete both versions and compare the
resulting programs. Discuss the merits and/or pitfalls of these versions with
friends. [Hint: Use a list of color names.]
5. The beep command can play two tones simultaneously. In this exercise we
will demonstrate an interesting phenomena. First, Try the following
commands:
beep(2, 660)
beep(2, 665)
You may or may not be able to tell the two tones apart. Next, try playing the
two tones together using the command:
You will hear pulsating beats. This phenomenon, called beating, is very
common when you play pure tone together. Explain why this happens.
213
Opposite page: Mars Rover.
Photo courtesy of NASA/JPLCaltech
Image Processing &
Perception
Seeing is believing.
Proverb
215
Chapter 9
Your robot has a small digital camera that can be used to take pictures. A
picture taken by a digital camera is represented as an image. As you have seen
in the previous chapter images can be drawn and moved about in a graphics
window just as if it were any other graphics object (like a line, circle, etc.).
We also saw in Chapter 5 how an image taken from the Scribbler’s camera
can be viewed on your monitor in a separate window. In this chapter we will
learn how to do computing on images. We will learn how images are
represented and how we can create them via computation and also process
them in many different ways. The representation of images we will use is
same as those used by most digital cameras and cell phones and the same
representation can be used to display them in a web page. We will also learn
how an image taken by the robot’s camera can be used to serve as the
camera’s eye into its world using some image understanding techniques.
Image understanding is the first step in visual perception. A robot equipped
with even the most rudimentary visual perception capabilities can be designed
to carry out more interesting behaviors.
What is an Image?
In Myro you can issue a command for the robot to take a picture and display it
on the computer’s monitor using the commands:
pic = takePicture()
show(pic)
The picture on the next page shows an example image taken from the
Scribbler’s camera. An image is made up of several tiny picture elements or
pixels. In a color image, each pixel contains color information which is made
up of the amount of red, green, and blue (also called, RGB) values. Each of
these values can be in the range [0..255] and hence it takes 3 bytes or 24 bits
to store the information contained in a single pixel. A pixel that is colored
pure red will have the RGB values (255, 0, 0). A grayscale image, on the
other hand, only contains the level of gray in a pixel which can be represented
in a single byte (8 bits) as a number ranging from 0..255 where 0 is black and
255 is white. The entire image is just a 2-dimensional array of pixels. For
example, the images obtained from the Scribbler have 256x192 (WxH) or a
216
Image Processing & Perception
217
Chapter 9
After you take a picture with the Scribbler as above you can get some
information about the size of the picture with the getWidth() and
getHeight() functions:
picWidth = getWidth(pic)
picHeight = getHeight(pic)
print "Image WxH is", picWidth, "x", picHeight, “pixels.”
If you wish to save the image for later use, you can use the Myro command:
savePicture(pic, "OfficeScene.jpg")
The file OfficeScene.jpg will be saved in the current folder. The .jpg
extension signals the command to save the image as a JPEG image. If you
wanted to save it as a GIF image, you can use the .gif extension as shown
below:
savePicture(pic, "OfficeScene.gif")
Later, you can load the picture from disk with the makePicture() function:
mySavedPicture = makePicture("OfficeScene.jpg")
show(mySavedPicture)
A nice command combination that allows you to navigate and then select the
image to load is:
mySavedPicture = makePicture(pickAFile())
show(mySavedPicture)
The pickAFile command gives you a navigational dialog box, just like the
one you see when you open and select files in many other computer
applications. You can navigate to any folder and select a file to open as an
image. In fact, you can use the makePicture command to load any JPEG
picture file regardless of whether it was created from your own digital camera
218
Image Processing & Perception
or one you downloaded from the web. Below, we show you how to load a
picture and display it:
lotusTemple = makePicture(pickAFile())
show(lotusTemple, “Lotus Temple”)
A Robot Explorer
If you do not need a full color picture, you can tell Myro to capture a gray-
scale image by giving the takePicture() function the "gray" parameter.
grayPic = takePicture("gray")
show(grayPic)
You will notice that taking the gray-scale picture took less time than taking
the color picture. As we explained earlier, a gray scale picture only uses one
219
Chapter 9
byte per pixel, instead of three. Because gray-scale images can be transferred
from the robot to your computer faster than full color images, they can be
useful if you want the images to update quickly. For example, you can use the
joyStick() function combined with a loop that takes and displays pictures to
turn your robot into a remotely piloted explorer, similar to the mars rovers.
joyStick()
for i in range(25):
pic = takePicture("gray")
show(pic)
The above code will open a joy stick window so that you can control your
robot and then capture and show 25 pictures, one after the other. While the
pictures are being captured and displayed like a movie, you can use the
joystick to drive your robot around, using the pictures to guide it. Of course, if
you removed the "gray" parameter from the takePicture() function call,
you would get color pictures instead of grayscale pictures, but they would
take much longer to transfer from the robot to your computer, and make it
more difficult to control the robot.
pic1 = takePicture()
turnLeft(0.5,0.25)
pic2 = takePicture()
turnLeft(0.5,0.25)
pic3 = takePicture()
turnLeft(0.5,0.25)
pic4 = takePicture()
220
Image Processing & Perception
savePicture(listOfPictures, "turningMovie.gif")
The best way to view an animated GIF file is to use a web browser. In your
favorite browser use the FILE->Open File menu, and then pick the
turningMovie.gif file. The web browser will show all frames in the movie,
but then stop on the last frame. To see the movie again, press the "Reload"
button. You can also use a loop to make a longer movie with more images:
savePicture(pictureList,"rotatingMovie.gif")
The above commands create an animated GIF movie from 15 pictures taken
while the robot was rotating in place. This is a nice way to capture a complete
scene around the robot
Making Pictures
W = H = 100
newPic = makePicture(W, H, black)
show(newPic)
The 100x100 pixel image starts out with all its pixels
colored pure black (i.e. RGB = (0,0,0)). If you’d
rather like all pixels to be a different color, you can
specify its RGB values:
221
Chapter 9
Alternately, if you ever need to, you can also set all the pixels to any color,
say white, using the loop:
for x in range(W)
for y in range(H):
pixel = getPixel(newPic, x, y)
setColor(pixel, white)
repaint(newPic)
myRed = makeColor(255, 0, 0)
To visually select a color and its corresponding RGB values, you can use the
command:
myColor = pickAColor()
A color palette will be displayed from which you can select a color of your
choosing. The palette also shows you the chosen color’s RGB values. After
you select a color and press OK, the value of myColor will be the selected
color.
The repaint command refreshes the displayed image so you can view the
changes you made. In the example loop above, we are using it after all the
pixels are modified. If you want to see the changes as they are being made,
you can include the repaint command inside the loop:
for x in range(W)
for y in range(H):
pixel = getPixel(newPic, x, y)
setColor(pixel, white)
repaint(newPic)
222
Image Processing & Perception
You will be able to view each pixel being changed. However, you will also
notice that repainting this way takes a considerable amount of time even on
the small image we are creating. Thus, it is a good idea to refresh once all the
pixels are modified.
In addition to the setColor command, Myro also has the setRGB command
that can be used to set a pixel’s color. This command uses RGB values
themselves, instead of a color.
r, g, b = getRGB(pixel)
The getRGB command returns the triple (R,G,B) that can be assigned to
individual variables as shown above. Additionally, given a pixel, you get the
individual RGB values using the commands getRed, getGreen, and getBlue.
These are described in more detail at the end of this chapter and are illustrated
in examples below.
Many image creation and processing situations require the processing of every
pixel in the image. In the loops above, we are using the x- and y- variables to
reach every pixel in the image. An alternate way of accomplishing the same
result is to use the following form of the loop:
223
Chapter 9
y- coordinates, while the latter gives you a pixel at a time without worrying
about its x- and y- values.
Shades of Gray
Using the basic image pixel accessing and modifying commands one can
write computations to create interesting and creative images. To introduce you
to basic image creation and processing techniques, we will create some
images entirely in the grayscale spectrum. In a JPEG image, all shades of gray
have equal RGB values. The darkest shade of gray is (0,0,0) or black and the
brightest is (255,255,255) or white. Rather than worrying about the triple of
RGB values, we can think of just a single value in the range 0..255 to
represent the grayscale spectrum. We can write a simple function that will
return the RGB shade of gray as follows:
def gray(v):
# returns an rgb gray color for v
return makeColor(v, v, v)
Let’s create an image that displays the entire range of shades of gray using the
following rule:
That is, a pixel in the image at 0, 0 will get the shade 0+0=0 or black, which
the pixel at 50,50 will get the shade 50+50=100 which will be a midrange
gray. We can accomplish this using the following loop:
def main():
MAX = 255
W = 100
H = 100
224
Image Processing & Perception
We have used the variable MAX above to represent the maximum value of the
grayscale range. In the last line we take the remainder (x+y)%(MAX+1) to
ensure that the gray value will be in the range 0..255. The image generated by
the above commands is shown on the right. It may seem strange at first that
we have used the x- and y- locations of a pixel to compute its grayscale or
brightness value. Since x- and y- are numbers and since the grayscale value
itself is a number it is ok to do this. Recognizing that x- and y- values (and
their sum) might be larger than the range of the grayscale spectrum, we take
the remainder to wrap the values around.
Do This: Write a complete program and try this out. Once you have the
program, try it out on an image of size 123x123 (why?). Then again, try it out
on a much larger image, say 500x500.
MAX = 50
def gray(v):
# returns an rgb gray color for v
brightness = v*255/MAX
return makeColor(brightness, brightness, brightness)
Do This: Rewrite the program to use the above definition of gray and create a
500x500 image. Modify the value of MAX to 25 and create a 100x100 image
(shown above). Note that if you set MAX to 255, it will revert to the earlier
version of the function.
225
Chapter 9
Image Processing
We will use the sample images shown here to learn image transformations.
You can feel free to select one or more images from your own digital camera.
226
Image Processing & Perception
After Shrinking
(150x106, F=2)
Lets us write a program that will take an input image and shrink it by a given
factor, say F. For example, if the original image is 3000x3000 pixels and we
shrink it by a factor of 10, we would end up with an image of size 300x300
227
Chapter 9
pixels. This transformation boils down to selecting the value of each of the
pixel in the new image based on the old image. We can use the following rule
as our transformation:
The program below prompts the user to pick an image, display it, and then ask
the user to specify the shrinking factor (which has to be larger than 1).
def main():
X = getWidth(oldPic)
Y = getHeight(oldPic)
for x in range(newx):
for y in range(newy):
setPixel(newPic, x, y, getPixel(myPic, x*F, y*F))
show(newPic, "After")
Do This: Select one or more images and make sure they are in JPEG format
and are high resolution images (for our purposes, 400x400 pixels or larger).
Run the program on each image and observe the output for different values of
F. Modify the program to use the savePicture command to save the images
into a file for use in examples below.
228
Image Processing & Perception
n1 = getPixel(oldPic, x, y)
n2 = getPixel(oldPic, x, y-1)
n3 = getPixel(oldPic, x-1, y)
n4 = getPixel(oldPic, x+1, y)
n5 = getPixel(oldPic, x, y+1)
Sharpened Image
229
Chapter 9
v = (getRed(n1)+…+getRed(n5))/5
setPixel(newPic, x, y, gray(v))
Notice in the above that n1 is the original pixel. You can use different sizes
and shapes of neighborhoods to create more elaborate blurring effects. The
next page shows the effect of using a larger, still square, neighborhood.
v = 5*getRed(n1) -
(getRed(n2)+…+getRed(n5))
setPixel(newPic, x, y, gray(v))
15‐pixel neighborhood
Do This: Write a complete program that
uses the above neighborhood averaging
formula to blur and sharpen images.
Depending on the size and shape of the
neighborhood you choose, the loop index
ranges will vary. For example, the loop for
the 4-pixel neighborhood will appear as
follows:
for x in range(1,X-1):
for y in range(1,Y-1):
# Average pixel values…
230
Image Processing & Perception
have to subtract from 255 for each of the RGB values. The rule for grayscale
is:
Negative Emboss
Similarly, you can create an embossing or relief effect by subtracting from the
current pixels value, the value (or a fraction thereof) of a pixel two pixels
away:
pixel1 = getPixel(oldPic, x, y)
pixel2 = getPixel(oldPic, x+2, y+2)
v = getRed(pixel1) – getRed(pixel2)
setPixel(newPic, x, y, gray(v))
or
231
Chapter 9
Do This: Implement the two rules shown above. Try creating a negative of a
color image, as well as a grayscale image. Try different fractions for
embossing to see their effect.
Most likely, as you were reading and experimenting with the above
techniques, you were wondering about the kind of image processing done by
some of the popular photo-editing software programs. You may already be
familiar with or might have heard of Adobe Photoshop, Fireworks, GIMP, etc.
Most of these programs use techniques similar to the ones we have described
above and provide many more features and options for image manipulation.
232
Image Processing & Perception
familiar with the basic image processing commands. The same commands
will be used to do image understanding.
The second problem becomes easy once we know how to recognize a ball. We
can write a simple control program like this:
while timeTemaining(T):
# take picture and locate the ball
…
if <ball is on the left of visual field>:
turnLeft(cruiseSpeed)
elif <ball is in the middle of visual field>:
forward(cruiseSpeed)
else:
turnRight(cruiseSpeed)
233
Chapter 9
value is 66. By the way, true pink has RGB values (255,175,175). We can use
this information as a way of identifying the ball. Here is a simple image
transformation loop that turns all pixels in the image into white or black
pixels. If a pixel has a high red value and a lower green value it will be turned
white else it will be turned black.
We are interested in locating the ball in the left, right, or center of the image.
One way to accomplish this is to locate the x- coordinate of the center point
of the ball. One way to do this is to take the average of the x- locations of all
white pixels in the image:
def locateBall(picture):
tot_x = 0
count = 0
234
Image Processing & Perception
Alternately, you could also average the x- locations of all pink pixels without
using the filter. On the image shown, the average x- value returned was 123.
Given that the image is 256 pixels wide, 123 is just about in the center.
Below, we show the locations obtained for each of the images shown:
while timeTemaining(T):
# take picture and locate the ball
pic = takePicture()
ballLocation = locateBall(pic)
235
Chapter 9
different colored objects. Can you use these techniques to recognize any
object? Say an animal? A person? Etc.
Blobs
The kind of threshold filtering used above is commonly called blob filtering.
All pixels satisfying the selected color properties are to be identified and the
rest eliminated. This is such a common operation in image processing that
many cameras and camera hardware integrate blob filtering as a primitive.
The Scribbler also has this capability. Using this, you do not have to worry
about identifying specific color values for the filter threshold. All you have to
do is take a picture and then display it. Then using your mouse, define the
rectangular region that contains your desired blob. To do this, take a picture,
display it, and then click your mouse on the top left corner of the ball in the
image and then drag it to the bottom right corner before releasing it. You have
to make sure that you are connected to the robot because the selected blob
region is transferred back to the robot. Once that is defined, you will be able
to make use of the predefined blob filter by taking pictures using the
command:
pic = takePicture("blob")
236
Image Processing & Perception
As soon as the picture is taken, the camera’s blob detector goes to work and
returns the resulting image (shown above). Now you can use this image as
before to control your robot. You will have to average the locations of all
black pixels.
The function returns three values: the number of ‘on’ pixels (i.e. the pixels in
the image that were in the detected blob), and the average x- and y- location
of the blob pixels. This is a
better and much faster way of
doing blob recognition and you
will notice that your robot tracks
the ball much better.
Further computations on an
image can result in identifying
object boundaries. This is called
edge detection. These can be
further used to do object
recognition: Is there a car in the
picture? A face? Etc. Object
recognition requires the ability
to identify features that are
typical of an object. The domain
of image recognition and
computational vision is rich with techniques and applications like these. On
the right, we show the results of recognizing faces and identifying the
individuals in the picture. As researchers advance these techniques and as
computational capabilities of digital cameras increase, we are starting to see
237
Chapter 9
many of these incorporated into even the most basic digital cameras. Such
techniques can be used to automatically focus on the main subject and also
adjust exposure to get a perfect picture even for amateur photographers.
Summary
In this chapter, you have seen various Myro facilities that can be used for
image creation, processing and understanding. Most image creation,
processing, and understanding techniques involve pixel-level manipulations of
an image. However, many interesting effects as well as applications can be
developed using these simple ideas. Many of these features are increasingly
found in everyday devices like digital cameras, biometric identification
devices, and even automated mail sorting systems. Combined with robot
behaviors these facilities can be used for modeling smarter behaviors.
Myro review
getBlob()
Returns a triple of onPixels, avgX, avgY (the number of pixels that
matched the blob, the average x and y locations of blob pixels).
getHeight(<picture>)
getWidth(<picture>)
Returns the height and width of the <picture> object (in pixels).
getPixel(<picture>, x, y)
Returns the pixel object at x,y in the <picture>.
getPixels(<picture>)
When used in a loop, returns one pixel at a time from <picture>.
getRGB(pixel)
getRed(<pixel>)
getGreen(<pixel>)
238
Image Processing & Perception
getBlue(<pixel>)
Returns the RGB values of the <pixel>.
makeColor(<red>, <green>, <blue>)
Creates a color object with the given <red>, <green>, and <blue> values (all
of which are in the range [0..255]).
makePicture(<file>)
makePicture(<width>, <height>)
makePicture(<width>, <height>, <color>)
Creates a picture object either by reading a picture from a <file>, or of the
given <width> and <height>. If <color> is not specified, the picture created
has a white background.
pickAColor()
Creates an interactive dialog window to select a color visually. Returns the
color object corresponding to the selected color.
pickAFile()
Creates an interactive dialog window that allows user to navigate to a folder
and select a file to open. Note: it cannot be used to create new files.
repaint()
repaint(<picture>)
Refreshes the displayed <picture>.
savePicture(<picture>, <file>)
savePicture(<picture list>, <gif file>)
Saves the <picture> in the specified file (a GIF or JPEG as determined by
the extension of the <file>: .gif or .jpg). <picture list> is saved as an
animated GIF file.
setColor(<pixel>, <color>)
setRed(<pixel>, <value>)
setGreen(<pixel), <value>)
239
Chapter 9
setBlue(<Pixel>, <value>)
Sets the color of <pixel> to specified <color> or <value>.
show(<picture>)
show(<picture>, <name>)
Displays the <picture> on the screen in a window named <name> (string).
takePicture()
takePicture(“gray”)
takePicture(“blob”)
Takes a picture from the Scribbler camera. It is a color picture by default, or
grayscale (“gray”), or a filtered image based on the defined blob (“blob”).
See chapter text for examples.
Python Review
240
Image Processing & Perception
Exercises
Write a function called polar(x, y) that returns the polar coordinates (r, theta)
of the given point. Using this function write a transformation as follows:
for x in range (1, W):
for y in range(1, H):
r, theta = polar(x, y)
setPixel(myPic, x, y,
gray((((r+theta)%16)-8)*MAX/16+MAX/2))
Create a 400x400 picture using the above transformation. Start with a black
picture.
2. Based on the above exercise, try transforming an image (like a portrait). For
example use the rule: new x, y is a copy of original picture’s /2, theta.
241
Chapter 9
4. Write an image transformation that averages two images (same size) into a
single image.
242
Image Processing & Perception
243
Opposite page: Mars Rover.
Photo courtesy of NASA/JPLCaltech
Artificial Intelligence
David: Martin is Mommy and Henry's real son. After I find the Blue Fairy then I can
go home. Mommy will love a real boy. The Blue Fairy will make me into one.
Gigolo Joe: Is Blue Fairy Mecha, Orga, man or woman?
David: Woman.
Gigolo Joe: Woman? I know women! They sometimes ask for me by name. I know
all about women. About as much as there is to know. No two are ever alike, And
after they've met me, no two are ever the same. And I know where most of them can
be found.
David: Where?
Gigolo Joe: Rouge City. Across the Delaware.
Dialog between two Artificial Intelligence entities: Gigolo Joe (played by Jude Law)
and David (played by Haley Joel Osment) in the movie, Artificial Intelligence,
Directed by Steven Speilberg, Warner Bros., 2001.
245
Chapter 10
The quest for the understanding of intelligence probably forms the oldest and
yet to be fully understood human inquiry. With the advent of computers and
robots the question of whether robots and computers can be as intelligent as
humans has driven the scientific pursuits in the field of Artificial Intelligence
(AI). Whether a computer can be intelligent was lucidly discussed by
Professor Alan Turing in 1950. To illustrate the issues underlying machine
intelligence, Turing devised a thought experiment in the form of an imitation
game. It is played with three people, a man, a woman, and an interrogator.
They are all in separate rooms and interact with each other by typing text into
a computer (much like the way people interact with each other over IM or
other instant messaging services). The interrogator's task is to identify which
person is a man (or woman). To make the game interesting, either player can
try and be deceptive in giving their answers. Turing argues that a computer
should be considered intelligent if it could be made to play the role of either
player in the game without giving itself away. This test of intelligence has
come to be called the Turing Test and has generated much activity in the
community of AI researchers (see Exercises). The dialog shown above, from
the movie Artificial Intelligence, depicts an aspect of the test of intelligence
designed by Alan Turing. Based on the exchange between Gigolo Joe and
David, can you conclude that they are both intelligent? Human?
After over five decades of AI research the field has matured and evolved in
many ways. For one, the focus on intelligence is no longer limited to humans:
insects and other forms of animals with varying degrees and kinds of
intelligence have been the subject of study within AI. There has also been a
fruitful exchange of ideas and models between AI scientists, biologists,
psychologists, cognitive scientists, neuroscientists, linguists and philosophers.
You saw examples of such an influence in the models of Braitenberg vehicles
introduced earlier. Given the diversity of researchers involved in AI there has
also been an evolution of what AI itself is really about. We will return to this
later in the chapter. First, we will give you a few examples of models that
could be considered intelligent that are commonly used by many AI scientists.
246
Artificial Intelligence
Language Understanding
You: forward
Scribbler: starts moving forward…
You: right
Scribbler starts turning right…
You: stop
…
Experiment with the behavior of the robot based on these commands and
think about the proper interpretation that may make its behavior more natural.
247
Chapter 10
Decisions like these also give deep insights into our own abilities of
understanding language. You can also see that, as in the case of visual
perception, processing of language (or text) begins at a very primitive level:
words. If the input is speech, the basic units are electrical signals, perhaps
coming from a microphone. Just like processing individual pixels to try and
understand the contents of an image, one has to start at a low level of
representation for beginning to understand language.
Earlier, you have written Python programs that perform similar behaviors.
However, now imagine interacting with the robot in the fashion described.
From a physical perspective, imagine that you are sitting in front of a
248
Artificial Intelligence
computer, and you have a Bluetooth connection to the robot. The first
question then becomes: Are you actually speaking or typing the above
commands? From an AI perspective, both modalities are possible: You could
be sitting in front of the computer and speaking into a microphone; or you
could be typing those commands on the keyboard. In the first instance, you
would need a speech understanding capability. Today, you can obtain
software (commercial as well as freeware) that will enable you to do this.
Some of these systems are capable of distinguishing accents, intonations, male
or female voices etc. Indeed, speech and spoken language understanding is a
fascinating field of study that combines knowledge from linguistics, signal
processing, phonology, etc.
You can imagine that the end result of speaking into a computer is a piece of
text that transcribes what you said. So, the question posed to the Scribbler
above: Do you see a wall? will have to be processed and then transcribed into
text. Once you have the text, that is, a string “Do you see a wall?” it can
be further processed or analyzed to understand the meaning or the content of
the text. The field of computational linguistics provides many ways of
syntactic parsing, analyzing, and extracting meaning from texts. Researchers
in AI itself have developed ways of representing knowledge in a computer
using symbolic notations (e.g. formal logic). In the end, the analysis of the
text will result in a getIR() or getObstacle() command to the Scribbler
robot and will produce the response shown above.
Our goal of bringing up the above scenario here is to illustrate to you various
dimensions of AI research that can involve people from many different
disciplines. These days, it is entirely possible even for you to design and build
computer programs or systems that are capable of interacting with robots
using language.
Game Playing
In the early history of AI, scientists posed several challenging tasks which if
performed by computers could be used as a way of demonstrating the
feasibility of machine intelligence. It was common practice to think of games
249
Chapter 10
in this realm. For example, if a computer could play a game, like chess, or
checkers, at the same level or better than humans we would be convinced into
thinking that it was indeed feasible to think of a computer as a possible
candidate for machine intelligence. Some of the earliest demonstrations of AI
research included attempts at computer models for playing various games.
Checkers and chess seemed to be the most popular choices, but researchers
have indulged themselves into examining computer models of many popular
games: Poker, Bridge, Scrabble, Backgammon, etc.
In many games, it is now possible for computer models to play at the highest
levels of human performance. In Chess, for example, even though the earliest
programs handily beat novices in the 1960's, it wasn't until 1996 when an
IBM computer Chess program, named Deep Blue, beat the world champion
Gary Kasparov at a tournament-level game, though Kasparov did manage to
win the match 4-2. A year later, in New York, Deep Blue beat Kasparov in a 6
game match representing the very first time a computer defeated the best
human player in a classical style game of Chess. While these
accomplishments are worthy of praise it also now clear that the quest for
machine intelligence is not necessarily answered by computer game playing.
This has resulted in much progress in game playing systems and game playing
technology which is now a multi-billion dollar industry.
It turns out that in many Chess-like games the general strategy for a computer
to play the game is very similar. Such games are classified as two-person
zero-sum games: two people/computers play against each other and the result
of the game is either a win for one player and loss for the other, or it is a draw.
250
Artificial Intelligence
In many such games, the basic strategy for making the next move is simple:
look at all the possible moves I have and for each of them all the possible
moves the other player might have and so on until the very end. Then, trace
back from wins (or draws) and make the next move based on those desirable
outcomes. You can see this even in simple games like Tic Tac Toe where it is
easy to mentally look ahead future moves and then make more informed
decisions about what to do next. The best way to understand this is to actually
write a program that plays the game.
Also known as Noughts and Crosses or Hugs and Kisses, Tic Tac Toe is a
popular children’s game (see description on right). We will develop a program
that can be used to play this game against a person. Almost any board game
can be programmed using the basic loop shown below:
def play():
# Initialize board
board = makeBoard()
251
Chapter 10
The function above can be used to play a round of any two-person board
game. The variable player is the player (or piece) whose move is next. We
are already using the Tic Tac Toe piece ‘X’ in the function above. Six basic
functions (shown highlighted above) make up the basic building blocks of the
game. For Tic Tac Toe, they can be defined as:
We will need a few more functions to complete the game but these six form
the basic core. We will write them first.
The game itself consists of nine squares that start out being empty. Players
choose a game piece: an ‘X’ or an ‘O’. We will assume that ‘X’ always goes
first. The first thing to do then is to design a representation of the game board.
We will use the following simple representation:
board = [' ',' ',' ',' ',' ',' ',' ',' ',' ']
252
Artificial Intelligence
This is a list of 9 1-character strings. Note that we are using this linear
representation of the board instead of a 2-dimensional one. However, as you
will see, this representation makes it easier to do many manipulations for the
game. During play, the board can be displayed in its natural format. Below,
we show two functions: one creates a fresh new board each time it is called;
and one displays it:
def makeBoard():
# A 3x3 board is represented as a list of 9 elements.
# We will use the following numbering to locate a square
# 0 | 1 | 2
# ---|---|---
# 3 | 4 | 5
# ---|---|---
# 6 | 7 | 8
return [' ',' ',' ',' ',' ',' ',' ',' ',' ']
def display(board):
for i in range(0, 9, 3):
if i > 0:
print '---|---|---'
print " %c | %c | %c "%(board[i],board[i+1],board[i+2])
print
board = makeBoard()
display(board)
253
Chapter 10
def opponent(player):
if player == "X":
return "O"
else:
return "X"
Next, we have to write the function move. It first determines whose move it is.
If it is the user’s move, it will input the move from the user. Otherwise, it will
determine the best move for the computer. Then it will actually make the
move. As a first design, we will let move make a random choice out of the
possible moves for the computer. Later, we will make a more informed
decision. The choice function is available in the random library module:
We have set the global variables You and Me to specific pieces. This is a
simplification for now. Later you can come back and rewrite them so that for
each game, the user gets to select their piece. In Tic Tac Toe, X always moves
first. So by making the user’s piece X, we have made an assumption that X
always goes first. Again, later we can come back and modify this (See
Exercises). Also notice that we are not doing any error checking in user input
to ensure that a legal move was input (see exercises).
The user inputs their move by entering a number from 1..9 where the square
numbering is as shown below. This is slightly different from our internal
numbering of squares and more natural for people. In the move function
254
Artificial Intelligence
above, we subtract 1 from the input number so it maps to the proper square in
our internal scheme.
1 | 2 | 3
---|---|---
2 | 5 | 6
---|---|---
7 | 8 | 9
Again, we have simplified the interface for now. The exercises suggest how to
improve on this design.
The move function defined above requires two additional functions (shown
highlighted). These are also core functions in any board-based game and are
described below:
In Tic Tac Toe all empty squares are possible places where a player can
move. Below, we write a function that, given a board, returns a list of all the
possible locations where a piece can be placed:
def possibleMoves(board):
return [i for i in range(9) if board[i] == ' ']
We are using list comprehensions (a Python feature) above to create the list of
possible moves. You may be more comfortable writing the following version
instead:
255
Chapter 10
def possibleMoves(board):
moves = []
for i in range(9):
if board[i] == ' ':
moves.append(i)
return moves
To complete the game playing program, we need to write two more functions
defined above. The winner function examines the board and determines who
won. It returns the winning piece (an 'X', 'O') or the string 'Tie'. In case
the game is not yet over, it returns a ' '. Below, we first define all the
winning positions in Tic Tac Toe, based on our board representation. Next,
we define the function itself to examine the board.
def winner(board):
for win in WINS:
posWinner = board[win[0]]
if (posWinner != ' ' and
posWinner == board[win[1]] and
posWinner == board[win[2]]):
return posWinner
256
Artificial Intelligence
Last, the gameOver function can be written either by relying on the fact that
winner retruns a ' ' when the game is not yet over. Alternately, we can
write it using possibleMoves as follows:
def gameOver(board):
return len(possibleMoves(board)) == 0
Now, we have all the ingredients for a program to play a game of Tic Tac
Toe. The version above is simplified in many ways, and yet it captures the
essential elements of playing a round of Tic Tac Toe.
Do This: Implement the program above and play a few rounds of Tic Tac
Toe. When you play against the computer, you are anticipating possible
moves down the road and then playing your own moves with those in mind.
You probably had no problems beating the computer at the game. That is
because the computer is just picking its moves by random from a set of
possible moves:
This is the line in move where we can put some intelligence into the program.
However, the basic question that needs to be asked is: which of the possible
moves is the best one for me? Think about this for yourself a little. In Tic Tac
Toe, you play in two modes: defensively so as not to lose after the next move,
or offensively to try and win. If a win is imminent for you, you will of course
make that move, but if it isn’t (and neither is a loss) how do you select your
move? We will try and generalize this idea next in a way that will also be
applicable to other board games.
257
Chapter 10
If bestMove were to make a random choice (as above) we could write it as:
Imagine that you decided to go watch two players playing a game of Chess (or
Tic Tac Toe). However, you get there in the middle of the game. You walk
into the room, look at the board, and are able to evaluate how each player is
doing without knowing anything about how the board came to be. For
example, take a look at the Tic Tac Toe boards:
X | O | X O | X | X X | O | X X | |
---|---|--- ---|---|--- ---|---|--- ---|---|---
| O | | | O | X | O | |
---|---|--- ---|---|--- ---|---|--- ---|---|---
O | X | X X | | O | X | | |
1 2 3 4
In all the cases above, the computer is playing O and it is O’s turn next.
Examine each board and think about what the best move for O would be.
Think about how we could quantify each of the above board positions with
respect to O’s chances of winning. For each board, count the number of
possible winning positions still remaining for O and compare those for X. For
example, in the first board, O has 5 possible winning positions, and X has 6.
258
Artificial Intelligence
We could say that O is 5 – 6 = -1 has one less possibility than X. If you did
this for the second and the third boards, you will see that both X and O are
even in the number of possible remaining winning positions (5 each).
However, in the fourth case, O has 5 possible winning positions remaining,
and X has only 4. Try and work out the remaining board positions to confirm
the scores shown above. Clearly, you can see that placing O in square 5 is the
best of all the possibilities. Try and elaborate the 5 possible moves for O in
case 2 above. You will find that one of the five leads to a win for O. Similarly,
when you elaborate the two options for O in case 1, you will notice that one
leads to a tie and the other to a loss for O. We can capture all these situations
in a function that takes a look at the board and returns a number representing a
score in favor of O: the higher the value returned, the more desirable the
board.
∞,
∞,
, /
That is, a win for the computer receives a high score, a loss receives a low
score. Otherwise, it is the difference in the number of open wins remaining for
each. We can capture this in Python as follows:
259
Chapter 10
INFINITY = 10
def evaluate(board):
# if board is a win for player, return INFINITY
piece = winner(board)
if piece == Me:
return INFINITY
elif piece == You:
return –INFINITY
else:
return openWins(board,Me) - openWins(board,You)
We define INFINITY as 10, a large enough number relative to the other values
that might be returned by evaluate. openWins looks at each winning triple
on the board and counts the number of openings for the given player.
Do This: Implement the two functions above and then test them. Create
several board positions (use the ones from examples above) and confirm that
the board is being evaluated to the correct values.
return moves[scores.index(max(scores))]
260
Artificial Intelligence
Notice how it takes each possible move, creates a new board with that move,
and then evaluates the score of the resulting board. Finally, it returns the move
with the highest score as the best move. Modify your program from above to
use this version of bestMove and play the game several times. You will notice
that there is a significant improvement in the computer’s playing ability. Can
you measure it in some way? (See Exercises).
The above rewrite of bestMove will make the program play significantly
better but there is still more room for improvement. In most board games
good players are able to mentally picture the game several moves ahead. In
many games, like Chess, certain recognizable situations lead to well
determined outcomes and so a great part of playing a successful game also
relies on the ability to recognize those situations.
When you look ahead a few moves, you take into account that your opponent
is going to try and beat you at every move. Your program, in trying to select
the best move, can look ahead at the opponent’s moves and take that into
consideration when choosing its best move. In fact, it can go further, all the
way to the end. The evaluate function we wrote above can be used
effectively to evaluate future board situations by assuming that when it is the
computer’s move, it will always try to pick the move that promises the highest
score in the future. However, when it examines the opponent’s moves, it has
to assume that the opponent is going to make the move that is worst for the
computer. In other words, when looking ahead, the computer is going to
261
Chapter 10
maximize its possible score while the opponent is going to minimize the
computer’s chances to win. This can be captured in the following:
moves = possibleMoves(board)
if level <= 0 or len(moves)==0: # limit of look ahead
return evaluate(board)
The lookahead function defined above takes the current board, the player
whose turn it is, whether the player is the computer (one trying to maximize
its outcome) or the computer (one trying to minimize the computer’s
outcomes), and the levels still to look ahead, and computes a score based on
examining all the moves going forward to the limit of look ahead. In the
above function when MAX is 1 it represents the computer and 0 represents its
opponent. Thus, depending on the value of MAX, the evaluation is minimized
or maximized accordingly. Each time it looks ahead further, the level is
reduced by 1. The final value returned by lookahead can be used by
bestMove as follows:
LEVEL = 9
def bestMove(board, player, moves):
scores = []
for m in moves:
262
Artificial Intelligence
b = copy(board)
b[m] = player
scores.append(lookahead(b,opponent(player),0,LEVEL-1)
return moves[scores.index(max(scores))]
As before, the move with the highest value is considered the best move. We
have set the value of LEVEL above at 9 (i.e. look 9 moves ahead!) implying
that each time it will look as far as the end of the game before making the
decision. There can only be a maximum of 9 moves in a Tic Tac Toe game.
The quality of the computer’s decision maker can in fact be adjusted by
lowering the value of LEVEL. At LEVEL = 1, it will be equivalent to the
version we wrote earlier that only used the evaluate function.
How many levels ahead one looks in a game like this can depend on the game
itself. Can you guess how many board situations the computer will have to
look at in doing a look ahead at LEVEL = 9 after the user’s first move? It will
be 40,320 different board situations! Why? Additionally, by the time it is the
computer’s second move, it will only need to look at 720 board positions.
This is because, in Tic Tac Toe, as the board gets filled, there are fewer
possible moves remaining. In fact, by the time it is the computer’s third move,
it only needs to look at a total of 24 boards. And, if the computer makes it to
its fourth move, it will only have to look at two possible moves. Thus, an
exhaustive search for all the possible board positions until the end of the game
each time the computer has to make a move it will be examining a total of
41,066 board positions. However, if you consider a typical game of Chess, in
which each player makes an average of 32 moves and the number of feasible
moves available at any time averages around 10, you would soon realize that
the computer would have to examine something of the order of 10 board
positions before making a move! This, even for the fastest computers
available today, will take several gazillion years! More on that later. But, to
play an interesting two-person zero-sum game, it is not essential to look so far
ahead. You can vary the amount of look ahead by adjusting the value of
LEVEL in such programs.
263
Chapter 10
The exercises at the end of the chapter will guide you in transforming the
above program into a more robust and even efficient game playing program
for Tic Tac Toe. However, study the program structure carefully and you will
be able to use the same strategy, including much of the core of the program, to
play many other two-person board games.
In Chapter 7, you saw an example of a program that played the game of Paper
Scissors Rock against a human user. In that version, the program’s choice
strategy for picking an object was completely random. We reproduce that
section of the program here:
…
items = ["Paper", "Scissors", "Rock"]
…
# Computer makes a selection
myChoice = items[randint(0, 2)]
…
In the above program segment, myChoice is the program’s choice. As you can
see, the program uses a random number to select its object. That is, the
likelihood of picking any of the three objects is 0.33 or 33%. The game and
winning strategies for this game have been extensively studied. Some
strategies rely on detecting patterns in human choice behavior. Even though
we may not realize it there are patterns in our seemingly random behavior.
Computer programs can easily track such behavior patterns by keeping long
histories of player’s choices, detect them, and then design strategies to beat
those patterns. This has been shown to work quite effectively. It involves
recording player’s choices and searching through them. Another strategy is to
264
Artificial Intelligence
study human choice statistics in this game. Before we present you with some
data, do the exercise suggested below:
Do This: Play the game against a few people, Play several dozen rounds.
Record the choices made by each player (just write a P/S/R in two columns).
Once done, compute the percentages of each object picked. Now read on.
It turns out that most casual human players are more prone towards picking
Rock than Paper or Scissors. In fact, various analyses suggest that 36% of the
time people tend to pick Rock, 30% Paper, and 34% Scissors. This suggests
that RPS is not merely a game of chance there is room for some strategies at
winning. Believe it or not, there are world championships of RPS held each
year. Even a simple game like this has numerous possibilities. We can use
some of this information, for instance, to make our program smarter or better
adept at playing the game. All we have to do is instead of using a fair 33%
chance of selecting each object we can skew the chances of selection based on
people’s preferences. Thus, if 36% of the time people tend to pick Rock, it
would be better for our program to pick Paper 36% of the time since Paper
beats Rock. Similarly, our program should pick Scissors 30% of the time to
match the chance of beating Paper, and pick Rock 34% of the time to match
the chances of beating Paper. We can bias the random number generator using
these percentages as follows:
265
Chapter 10
def mySelection():
Do This: Modify your RPS program from Chapter 7 to use this strategy. Play
the game several times. Does it perform much better that the previous
version? You will have to test this by collecting data from both versions
against several people (make sure they are novices!).
Another strategy that people use is based upon the following observation:
After many rounds, people tend to make the move that would have beaten
their own previous move.
Say a player picks Paper. Their next pick will be Scissors. A computer
program or a player playing against this player should then pick Rock to beat
Scissors. Note that the relationship between the choices is cyclical. Paper
beats Rock, Rock beats Scissors, and Scissors beat Paper. Therefore, since the
player’s previous move was Paper, your program can pick Rock in
anticipation of the player’s pick of Scissors. Try to think over this carefully
and make sure your head is not spinning by the end of it. If a player can spot
this they can use this as a winning strategy. We will leave the implementation
of this strategy as an exercise. The exercises also suggest another strategy.
The point of the above examples is that using strategies in your programs you
can make your programs smarter or more intelligent. Deliberately, we have
started to use the term intelligence a little more loosely than what Alan Turing
266
Artificial Intelligence
implied in his famous essay. Many people would argue that these programs
are not intelligent in the ultimate sense of the word. We agree. However,
writing smarter programs is a natural activity. If the programs incorporate
strategies or heuristics that people would use when they are doing the same
activity, then the programs have some form of artificial intelligence in them.
Even if the strategy used by the program is nothing like what people would
use, but it would make the program smarter or better, we would call it
artificial intelligence. Many people would disagree with this latter claim. To
some, the quest for figuring out intelligence is limited to the understanding of
intelligence in humans (and other animals). In AI both points of view are quite
prevalent and make for some passionate debates among scholars.
Discussion
267
Chapter 10
Myro Review
Python review
choice(LIST)
Returns a randomly selected element from LIST. This function is to be
imported from the random module.
List Comprehensions
A short and elegant way to construct lists. See Python documentation for
more information.
268
Artificial Intelligence
Exercises
1. Read Alan Turing’s paper Computing Machinery and Intelligence. You can
easily find a copy of it by searching on the web.
3. Rewrite display for Tic Tac Toe game to display the board graphically.
5. Extend the language from Exercise 4 to include queries (e.g. wall?) and
then modify your program to incorporate such queries.
8. In the Tic Tac Toe program designed in this Chapter, we assumed that the
user always plays an X. Modify your program so that it gives the user a choice
at the beginning of the game. Further, at the end of each game, the pieces are
swapped.
9. In the function move defined for Tic Tac Toe, the program accepts whatever
the user inputs for their move. Try the program and instead of entering a valid
move, enter your name instead. What happens? Such an errors might be easily
detected since it will halt the program’s execution. However, next try entering
a number from 1-9 using a spare position that is already occupied in the
board. What happens? Modify the function to accept only correct moves. If
269
Chapter 10
the user enters an incorrect move, the program should point that out and give
the user another chance.
10. The function gameOver can make use of the winner function to make its
decision in the Tic Tac Toe program. Rewrite gameOver to do this.
11. One way to measure how one strategy compares against another is to play
it against another strategy over and over again recording the number of wins,
losses, and draws. Modify your Tic Tac Toe or RPS program to substitute the
second strategy for the user (instead of taking input from the user, it uses a
function that implements the second strategy. Add statements to play the
game many times (say 1000) and record the wins, losses, and draws. You may
also want to suppress all board output since the game is being played
completely inside the program. Do a comparison of all the strategies discussed
in this Chapter and how they compare against each other.
270
Artificial Intelligence
271
Opposite page: Mars Rover.
Photo courtesy of NASA/JPLCaltech
Computers &
Computation
Home computers are being called upon to perform many new functions, including the
consumption of homework formerly eaten by the dog.
Doug Larson
What is the central core of computer science?My answer is simple -it is the art of
programming a computer. It is the art of designing efficient and elegant methods of
getting a computer to solve problems, theoretical or practical, small or large, simple
or complex. It is the art of translating this design into an effective and accurate
computer program.
C.A.R. Hoare
Opposite page: The XO Laptop
Photo courtesy of OLPC Project (www.olpc.org)
273
Chapter 11
Today, there are more computers than people on most college campuses in the
United States. The laptop computer shown on the previous page is the XO
laptop developed by the One Laptop Per Child Project (OLPC). It is a low
cost computer designed for kids. The OLPC project aims to reach out to over
2 billion children all over the world. They aim to get the XO computers in
their hands to help in education. Their mission is to bring about a radical
change in the global education system by way of computers. Of course a
project with such a grandiose mission is not without controversy. It has had a
bumpy ride since its inception. The technological issues were the least of their
problems. They have had to convince governments (i.e. politicians) to buy-in
into the mission. Several countries have agreed to buy-in and then reneged for
all kinds of reasons. The laptops are not available for open purchase within
the United States which has led to other socio-political controversies.
Regardless, in the first year of its release the project aims to have over 1
million XO’s in the hands of children in many developing countries. The
thing about technology that has always been true is that a good idea is
infective. Other players have emerged who are now developing ultra-low cost
computers for kids. It will not be long before other competitive products will
be available to all. The bigger questions are: What kind of change will this
bring about in the world? How will these computers be used in teaching
elementary and middle school children? Etc. You may also be wondering if
your Scribbler robot can be controlled by the XO. It can.
You have been writing programs to control your robot through a computer.
Along the way you have seen many different ways to control a robot and also
ways of organizing your Python programs. Essentially you have been
engaging in the activity commonly understood as computer programming or
computer-based problem solving. We have deliberately refrained from using
those terms because the general perception of these conjures up images of
geeks with pocket-protectors and complex mathematical equations that seem
to be avoidable or out of reach for most people. Hopefully you have
discovered by now that solving problems using a computer can be quite
exciting and engaging. Your robot may have been the real reason that
motivated you into this activity and that was by design. We are confessing to
you that robots were used to attract you to pay some attention to computing.
274
Computers & Computation
You have to agree, if you are reading this, that the ploy worked! But
remember that the reason you are holding a robot of your own in your hand is
also because of computers. Your robot itself is a computer. Whether it was a
ploy or not you have assimilated many key ideas in computing and computer
science. In this chapter, we will make some of these ideas more explicit and
also give you a flavor for what computer science is really all about. As
Dijkstra puts it, computer science is no more about computers than astronomy
is about telescopes.
Say you are hosting an international exchange student in your home. Soon
after her arrival you teach her the virtues of PB&J (Peanut Butter & Jelly)
sandwiches. After keenly listening to you, her mouth starts to water and she
politely asks you if you can share the recipe with her. You write it down on a
piece of paper and hand it to her.
Do This: Go ahead, use your recipe from above to make yourself a PB&J
sandwich. Try to follow the instructions exactly as literally as you can. If you
successfully managed to make a PB&J sandwich, congratulations! Go ahead
and enjoy it. Do you think your friend will be able to follow your recipe and
enjoy PB&J sandwiches?
You have to agree, writing a recipe for PB&J sandwiches seemed trivial at
first, but when you sit down to write it you have no choice but to question
several assumptions: does she know what peanut butter is? Should I
recommend a specific brand? Ditto for jelly? By the way, did you forget to
mention it was grape jelly? What kind of bread to use? Will it be pre-sliced?
If not, you need a knife for slicing the loaf? Did you specify how thick the
275
Chapter 11
slices should be? Should she use the same knife for spreading the peanut
butter and the jelly? Etc. The thing is, at such a level of detail you can go on
and on...does your friend know how to use a knife to spread butter or jelly on
a slice? Suddenly, a seemingly trivial task becomes a daunting exercise. In
reality, in writing down your recipe, you make several assumptions: she
knows what a sandwich is, it involves slices of bread, spreading things on the
slices, and slapping them together. There, you have a sandwich!
Think of the number of recipes that have been published in cookbooks all
over the world. Most good cookbook authors start with a dish, write down a
recipe, try it a number of times and refine it in different ways. Prior to
publication, the recipe is tested by others. After all, the recipe is for others to
follow and recreate a dish. The recipe is revised and adjusted based on
feedback by recipe testers. The assumption that cookbook authors make is that
you will have the competence to follow the recipe and recreate the dish to
your satisfaction. It may never result in the same dish that the author prepared.
But it will give you a base to improvise upon. Wouldn't it be nice if there was
an exact way of following a recipe so that you end up with the exact same
result as the cookbook author every time you made that dish? Would it? That
may depend on your own tastes and preferences. Just for fun, here is a recipe
for some yummy Saffron Chicken Kabobs.
Ingredients
276
Computers & Computation
Preparation
In cooking recipes, like the ones above, you can assume many things: they
will be used by people (like you and me); they will be able to follow them;
perhaps even improvise. For instance, in the recipe above, we do not specify
that one will need a knife to cut the chicken, onions, or the lime; or that you
will need a grill or an oven; etc. Most recipes assume that you will be able to
interpret and follow the recipe as written.
Computer programs are also like recipes, to some extent. Think of the
program you wrote for choreographing a robot dance, for instance. We have
reproduced the version from Chapter 3 here:
# File: dance.py
# Purpose: A simple dance routine
# First import myro and connect to the robot
277
Chapter 11
wait(waitTime)
motors(speed, -speed)
wait(waitTime)
stop()
main()
To do a robot dance
Ingredients
1 function yoyo for the robot to go back and forth at a given speed
1 function wiggle that enables the robot to wiggle at a given speed
Preparation
Further, you could similarly specify the steps involved in doing the yoyo and
wiggle motions as a recipe. This may seem like a trivial example, but it
makes two very important points: a computer program is like a recipe in that it
lays out the list of ingredients and a method or steps for accomplishing the
given task; and, like a recipe, its ingredients and the steps require careful pre-
278
Computers & Computation
Do This: Can you find out how many programming languages there are?
What are the ten most commonly used programming languages?
meaningOfLife = 42
279
Chapter 11
is a command for the computer to associate the value, 42 with the name
meaningOfLife. This way, we can ask the computer to check that it is indeed
42:
if meaningOfLife == 42:
speak("Eureka!")
else:
speak("What do we do now?")
Once again, it would be good to remind you that the choice of the name,
meaningOfLife, doesn't really mean that we are talking about the meaning of
life. We could as well have called it timbuktoo, as in:
timbuktoo = 42
Recipes, however, form a good conceptual basis for starting to think about a
program to solve a problem. Say, you have in mind to make your favorite
Apple Strudel. You know you will need apples. Perhaps it is the apple season
that prompted the thought in the first place. You will also need pastry. But
when you get down to it, you will need that recipe you got from your
grandma.
280
Computers & Computation
identified and named, etc. Once you convince yourself that you have a way of
solving the problem, what you have is an algorithm
281
Chapter 11
"best by" date), a code identifying the specific farm the eggs came from, and a
date on which the eggs were packed in that carton. Most people buy eggs by
looking at the "sell by" date or the "best by" date. However the freshness
information is really encoded in the packed on date. To make things more
confusing, this date is encoded as the day of the year.
For example, take a look at the top carton shown on the previous page. Its
"sell by" date is October 4. "P1107" is the farm code. This carton was packed
on the 248th day of the year. Further, USDA requires that all certified eggs be
packed within 7 days of being laid. Thus, the eggs in the top carton were laid
somewhere between day 241 and day 248 of 2007. What dates correspond to
those dates?
Next, look at the bottom carton. Those eggs have a later "sell by" date
(October 18) but an earlier packed date: 233. That is those eggs were laid
somewhere between day 226 and day 233 of 2007.
Even though the "sell by" date on the second carton is two weeks later, the
first carton contains fresher eggs. In fact, the eggs in the upper carton were
laid at least two weeks later!
Do This: Go to the USDA web site (www.usda.gov) and see if you can find
out which farm the two eggs cartons came from.
For a robot, the problem of buying the freshest eggs becomes that of figuring
out, given a packed on date, what the date was when the eggs were packed?
282
Computers & Computation
283
Chapter 11
Output
Date the eggs were packed
Example:
Input: 248, 2007
Output: The eggs were packed on September 5, 2007
Any ideas as to how you would solve this problem? It always helps to try and
do it yourself, with pencil and paper. Take the example above, and see how
you would arrive at the output date. While you are working it out, try to write
down your problem solving process. Your algorithm or recipe will be very
similar.
Suppose we are trying to decode the input 248, 2007. If you were to do this by
hand, using a pen and paper, the process might go something like this:
284
Computers & Computation
That was obviously too repetitious and tedious. But that is where computers
come in. Take a look at the process above and see if there is a pattern to the
steps performed. Sometimes, it is helpful to try another example.
Do This: Suppose the input day and year are: 56, 2007. What is the date?
When you look at the sample computations you have performed, you will see
many patterns. Identifying these is the key to designing an algorithm.
Sometimes, in order to make this easier, it is helpful to identify or name the
key pieces of information being manipulated. Generally, this begins with the
inputs and outputs identified in the problem specification. For example, in this
problem, the inputs are: day of the year, current year. Begin by assigning
these values to specific variable names. That is, let us assign the name day to
represent the day of the year (248 in this example), and year as the name to
store the current year (2007). Notice that we didn't choose to name any of
these variables timbuktu or meaningOfLife!
Also, notice that you have to repeatedly subtract the number of days in a
month, starting from January. Let us assign a variable named, month to keep
track of the month under consideration.
Next, you can substitute the names day and year in the sample computation:
Input:
day = 248
year = 2007
285
Chapter 11
# next month
month = 2
# next month
month = 3
day (= 189) is larger than 31, the # of days in month = 3.
day = day - 31
# next month
month = 4
day (= 158) is larger than 30, the # of days in month = 4.
day = day - 30
# next month
month = 5
day (= 128) is larger than 31, the # of days in month = 5.
day = day - 31
# next month
month = 6
day (= 97) is larger than 30, the # of days in month = 6.
day = day = 30
# next month
month = 7
day (= 67) is larger than 31, the # of days in month = 7.
day = day - 31
# next month
month = 8
day (= 36) is larger than the # of days in month = 8.
day = day - 31
# next month
month = 9
day (= 5) is smaller than the # of days in month = 9.
286
Computers & Computation
Notice now how repetitious the above process is. The repetition can be
expressed more concisely as shown below:
Input:
day
year
Output: day/month/year
We can refine the algorithm above further: one thing we have left unspecified
above is the computation of the number of days in a month. This information
has to be made explicit for a computer to be able to follow the recipe. So, how
do we compute the number of days in a month? The answer may seem simple.
Many of you may remember the following poem:
287
Chapter 11
Ingredients:
1 function daysInMotnh(m, y): returns the number of days in
month, m in year y.
Input:
day
year
Output: day/month/year
Input
month, M
year, Y
288
Computers & Computation
Output
Number of days in month, M in year, Y
On the surface this seems easy, the poem above specifies that April, June,
September, and November have 30 days, and the rest, with the exception of
February have 31. February has 28 or 29 days depending upon whether it falls
in a leap year or not. Thus, we easily elaborate a recipe or an algorithm for
this as follows:
Input:
m, y
Output:
days
This still leaves out one more detail: how do we tell if y is a leap year?
Again, we can refine the algorithm above by assuming that we have another
ingredient, a function: leapYear, that determines if a given year is a leap year
or not. Then we can write the algorithm above as:
Ingredients:
1 function leapYear(y)
returns True if y is a leap year, false otherwise
289
Chapter 11
Input:
m, y
Output:
days
Most of us have been taught that a leap year is a year that is divisible by 4.
That is the year 2007 is not a leap year, since 2007 is not divisible by 4, but
2008 is a leap year, since it is divisible by 4.
Input
y, a year
Output
True if y is a leap year, false otherwise
290
Computers & Computation
Method
if y is divisible by 4
it is a leap year, or True
else
it is not a leap year, or False
However, this is not the complete story. The western calendar that we follow
is called the Gregorian Calendar which was adopted in 1582 by a Papal Bull
issued by Pope Gregory XIII. The Gregorian Calendar defines a leap year, by
adding an extra day, every fourth year. However, there is a 100-year
correction applied to it that makes the situation a little more complicated:
Century years are not leap years except when they are divisible by 400. That
is the years 1700, 1800, 1900, 2100 are not leap years even though they are
divisible by 4. However, the years 1600, 2000, 2400 are leap years. For more
information on this, see the exercises at the end of the chapter. Our algorithm
for determining if a year is a leap year can be refined as shown below:
Input
y, a year
if y is divisible by 400
it is a leap year, or True
else if y is divisible by 100
it is not a leap year, or False
else if y is divisible by 4
it is a leap year, or True
else
it is not a leap year, or False
291
Chapter 11
1. Algorithms are step-by-step recipes that clearly identify the inputs and
outputs
2. Algorithms name the entities that are manipulated or used: variables,
functions, etc.
3. Steps in the algorithm are followed in the order they are written (from
top to bottom)
4. Some steps can specify decisions (if-then) over the choice of some
steps
5. Some steps can specify repetitions (loops) of steps
6. All of the above can be combined in any fashion.
Programming Languages
292
Computers & Computation
we provide below, the Python program that encodes the leapYear algorithm
shown above:
def leapYear(y):
'''Returns true if y is a leap year, false otherwise.'''
if y %400 == 0:
return True
elif y % 100 == 0:
return False
elif y % 4 == 0:
return True
else:
return False
The same algorithm, when expressed in C++ (or Java) will look like this:
bool leapYear(int y) {
// Returns true if y is a leap year, false otherwise.
if (y % 400 == 0)
return true
else if (y % 100 == 0)
return false
else if (y % 4 == 0)
return true
else
return false
}
As you can see, there are definite syntactic variations among programming
languages. But, at least in the above examples, the coding of the same
algorithm looks very similar. Just to give a different flavor, here is the same
function expressed in the programming language CommonLisp.
293
Chapter 11
Again, this may look weird, but it is still expressing the same algorithm.
What is more interesting is that given an algorithm, there can be many ways
to encode it, even in the same programming language. For example, here is
another way to write the leapYear function in Python:
def leapYear(y):
'''Returns true if y is a leap year, false otherwise.'''
Again, this is the same exact algorithm. However, it combines all the tests into
a single condition: y is divisible by 4 or by 400 but not by 400. The same
condition can be used to write an even more succinct version:
def leapYear(y):
'''Returns true if y is a leap year, false otherwise.'''
That is, return whatever the result is (True/False) of the test for y being a
leap year. In a way, expressing algorithms into a program is much like
expressing a thought or a set of ideas in a paragraph or a narrative. There can
be many ways of encoding an algorithm in a programming language. Some
seem more natural, and some more poetic, or both, and, like in writing, some
can be downright obfuscated. As in good writing, good programming ability
comes from practice and, more importantly, learning from reading well
written programs.
To be able to solve the fresh eggs problem, you have to encode all the
algorithms into Python functions and then put them together as a working
program. Below, we present one version:
294
Computers & Computation
# File: fresheggs.py
def leapYear(y):
'''Returns true if y is a leap year, false otherwise.'''
if (m == 4) or (m == 6) or (m == 9) or (m == 11):
return 30
elif m == 2:
if leapYear(y):
return 29
else:
return 28
else:
return 31
def main():
'''Given a day of the year (e.g. 248, 2007),
convert it to the date (i.e. 9/5/2007)'''
# next month
month = month + 1
main()
295
Chapter 11
If you save this program in a file, fresheggs.py, you will be able to run it
and test it for various dates. Go ahead and do this. Here are some sample
outputs:
>>> main()
Enter the day, year: 12, 2007
The date is: 1/12/2007
>>> main()
Enter the day, year: 248, 2008
The date is: 9/4/2008
>>> main()
Enter the day, year: 365, 2007
The date is: 12/31/2007
>>> main()
Enter the day, year: 31, 2007
The date is: 1/31/2007
All seems to be good. Notice how we tested the program for different input
values to confirm that our program is producing correct results. It is very
important to test your program for a varied set of input, taking care to include
all the boundary conditions: first and last day of the year, month, etc. Testing
programs is a fine art in itself and several books have been written about the
topic. One has to ensure that all possible inputs are tested to ensure that the
behavior of the program is acceptable and correct. You did this with your
robot programs by repeatedly running the program and observing the robot's
behavior. Same applies to computation.
What happens, if the above program receives inputs that are outside the
range? What if the user enters the values backwards (e.g. 2007, 248 instead of
248, 2007)? What if the user enters her name instead (e.g. Paris, Hilton)? Now
296
Computers & Computation
is the time to try all this out. Go ahead and run the program and observe its
behavior on some of these inputs.
Ensuring that a program provides acceptable results for all inputs is critical in
most applications. While there is no way to avoid what happens when a user
enters his name instead of entering a day and a year, you should still be able
to safeguard your programs from such situations. For example:
>>> main()
Enter the day, year: 400, 2007
That corresponds to the date: 14/4/2007
The thing that comes to rescue here is the realization that, it is your program
and the computer will only carry out what you have expressed in the program.
That is, you can include error checking facilities in your program to account
for such conditions. In this case, any input value for day that is outside the
range 1..365 (or 1..366 for leap years) will not be acceptable. Additionally,
you can also ensure that the program only accepts years greater than 1582 for
the second input value. Here is the modified program (we'll only show the
main function):
def main():
'''Given a day of the year (e.g. 248, 2007), convert
it to the date (i.e. 9/5/2007)'''
297
Chapter 11
return
if leapYear(year):
if day > 366:
print "I'm sorry. You must enter a valid day
(1..365/366). Please try again."
return
elif day > 365:
print "I'm sorry. You must enter a valid day
(1..365/366). Please try again."
return
# next month
month = month + 1
main()
Here are the results of some more tests on the above program.
>>> main()
Enter the day, year: 0, 2007
I'm sorry. You must enter a valid day (1..365/366). Please try
again.
>>> main()
Enter the day, year: 366, 2007
I'm sorry. You must enter a valid day (1..365/366). Please try
again.
>>> main()
Enter the day, year: 400, 2007
298
Computers & Computation
I'm sorry. You must enter a valid day (1..365/366). Please try
again.
>>> main()
Enter the day, year: 248, 1492
I'm sorry. You must enter a valid year (one after 1582).
Please try again.
>>> main()
Enter the day, year: 366, 2008
The date is: 12/31/2008
299
Chapter 11
def main():
'''Given a day of the year (e.g. 248, 2007), convert
it to the date (i.e. 9/5/2007)'''
# next month
month = month + 1
main()
300
Computers & Computation
Let us start with another problem: You have to travel from Washington State
to Washington DC in the United States of America. To make things
interesting, lets us add a restriction that you can only travel through states
whose names begin with the letters in the word “woman”. That is, it is OK to
go from Washington to Oregon since both “W” and “O” are in the word
“woman” but it is not OK to go from Washington to California. Is this
feasible? If it is, how many ways are possible? Which one goes through the
least/most number of states? Etc.
If you are thinking about how to solve this, you have to rely on your
geographic knowledge of the United States. Alternately, you can Google a
301
Chapter 11
state map and then figure out a solution. But, in doing so, you have stumbled
upon the two key ingredients of computing: data & algorithm.
Data gives you a representation of the relevant information which, in this case
is a way of knowing which states adjoin which other states. The algorithm
gives you a way of finding a solution: Start in Washington, look at its
neighbors. Pick a neighbor whose name satisfies the constraint, then look at
that state’s neighbors, and so on. Additionally, an algorithm also forces you to
make certain choices: if there is more than one eligible neighbor, which one
do you pick? What if you end up in a dead end, how do you go back to the
choices you left behind to explore alternative paths? Etc. Depending on these
decisions, you are likely to end up with many different algorithms: one that
may suggest exploring all alternatives simultaneously; or one that forces you
to choose, only to return to other choices in case of failure. Each of these will
further impact on the amount of data you will need to store to keep track of
your progress.
302
Computers & Computation
for x in range(W)
for y in range(H):
pixel = getPixel(myPic, x, y)
r, g, b = getRGB(pixel)
setRGB(pixel, (255-r,255-g,255-b))
If the image is 1000x1000 pixels (i.e. W=1000 and H=1000), each of the three
statements in the loop is executed 1 million times. Each of those statements in
turn requires an average of 8-16 low-level computing operations: the actual
303
Chapter 11
Summary
304
Computers & Computation
diverse, and deeply intellectual discipline of study that has implications for all
aspects of our lives. We started this chapter by pointing out that there are now
more computers on a typical college campus in the United States than the
number of people. It probably will not be long before there are more
computers than people on this entire planet. Yet, the idea of an algorithm that
is central to computing is barely understood by most users despite its simple
and intuitive constituents. Many computer scientists believe that we are still
sitting at the dawn of the age of algorithm and that there are much bigger
intellectual and societal benefits yet to be realized, especially if more people
were aware of these ideas.
Myro review
Python Review
The only new Python feature introduced in this chapter was the creation of
modules. Every program you create can be used as a library module from
which you can import useful facilities.
Exercises
if (m == 4) or (m == 6) or (m == 9) or (m == 11):
return 30
elif m == 2:
if leapYear(y):
return 29
else:
return 28
else:
return 31
305
Chapter 11
You can further simplify the writing of the condition in the first if-statement
by using lists:
if m in [4, 6, 9, 11]:
return 30
…
def main():
'''Given a day of the year (e.g. 248, 2007), convert
it to the date (i.e. 9/5/2007)'''
# next month
month = month + 1
main()
306
Computers & Computation
Rewrite the program as shown above to use the new function. Besides
developing a correct algorithm it is also important to write programs in a way
that makes them more readable for you.
3. Find out the how fast your computer is by noting the clock speed of the
CPU. Based on that estimate how many arithmetic operations it will be able to
perform in 1 second. Write a program to see how many operations it actually
performs in one second.
5. What is the fastest computer in use today? Can you find out? How fast is it
compared to the computer you use? 100 times? 1000 time? 100,000 times?
307
Opposite page: Mars Rover.
Photo courtesy of NASA/JPLCaltech
Fast, Cheap &
Out of Control
We suggest that within a few years it will be possible at
modest cost to invade a planet with millions of tiny robots…
With imagination and nerve we can invade the whole solar system.
From a paper titled,
Fast, cheap and out of control: A robot invasion of the solar system,
Rodney Brooks and Anita M. Flynn,
Journal of the British Interplanetary Society, Volume 42, pp 478-485, 1989.
309
Chapter 12
Nearly two decades ago, Brooks and Flynn laid out a radical vision for the
future that, on July 4, 1997, resulted in successful landing of Sojourner rover
on the surface of Mars. A few years later, in 2004, two rovers Spirit and
Opportunity arrived on Mars to explore the planet. In 2002, in his book, Flesh
and Machines, a more reflective Rodney Brooks confesses to his exuberance
in making the comments in his paper with Anita Flynn and describes the
rovers as planetary ambassadors. The vision put forward by Brooks and Flynn
was to replace a single large 1000 kilogram rover by 100 smaller 1 kilogram
rovers to explore planetary surfaces. The smaller robots would move much
faster and could be built much cheaper and mass produced. They will also
offer much needed redundancy in case of occasional robot failure which in the
case of a single larger robot would lead to total mission failure. Moreover,
each individual robot would be autonomous (i.e. out of human control)
operating on its own agenda as defined it its control program.
It is debatable whether Brooks actually coined the phrase, fast, cheap and out
of control. But the credit for using it in the title of their landmark paper
followed by the deployment of three rovers on Mars led to its widespread use
in popular culture. The phrase became the title of a 1997 documentary movie
by Errol Morris in which Brooks himself was featured. In his 2002 book,
Brooks recounts how a scientist at NASA’s Jet Propulsion Laboratory
lambasted the idea of fast, cheap, and autonomous rovers. While the original
dream of 100 small, autonomous robots remains to be realized, today one
would find it hard to argue against the idea. We have used Brooks’ phrase in
the title of this chapter to suggest that less than twenty years from the coining
of the phrase we are in the thick of exploring the full potential of small, cheap,
personal robots. Given that several million personal robots have already been
sold, we could conclude that our planet itself has been invaded by them.
Brooks says that, “the robotics revolution is in its nascent stage, set to burst
over us in the early part of the twenty-first century.” In this chapter we present
several examples of the ways robots are becoming a part of our everyday
lives.
310
Fast, Cheap & Out of Control
We accepted the above definition for robots in the beginning of this text.
Using the Scribbler robot we have also learned much about its mechanisms:
sensors and motors; and how to control them via Python programs. In the
course of this journey we have learned valuable lessons in building different
kinds of robot brains, how to design insect-like behaviors, create sounds,
images, and also ventured briefly into the realm of Artificial Intelligence.
Computing lies at the heart of defining automated control. Any robot, no
matter how small or large, has sensing and motor mechanisms and its
behavior can be programmed to enable it to act autonomously in its
environment. It is important to keep this in mind as we explore the various
dimensions of the robotics spectrum.
The range of applications for robots is nearly as diverse as the world we live
in. In fact, it is limited only by our own imagination. Throughout this text we
have presented examples of robots in several domains: planetary rovers,
vacuum cleaners, explorers in hazardous environments, toys and
entertainment, education, medical surgery, manufacturing, etc. Below, we
present additional interesting examples of the use of robot technology. It will
be important, as we explore some of these examples, to try and use your
understanding from this text to figure out what mechanisms are in use in each
case. Try to think about possible other areas where similar mechanisms could
be out to use.
Toys
311
Chapter 12
Scribbler and a motor that drives or pushes the “skin” of the face from behind.
Art
Robots have been actively used in creating all kinds of art and robots
themselves have been the subject of art. There are several organizations
worldwide that are devoted to creating art with robots and robotic devices. In
this book you have also experimented with the Scribbler drawings. A couple
of nice examples of robots creating artwork are illustrated in the works of
Swiss engineers Jürg Lehni and Uli Franke who created the Hektor graffiti
drawing robot (hector.ch) at the School of Art in Lousanne, and Zefrank
313
Chapter 12
Global positioning systems (GPS) have been in use for many years now. More
recently, small portable GPS devices have become available for use in
consumer cars. A GPS enables you to enter a destination or a point of interest
314
Fast, Cheap & Out of Control
and then it plots a route for you to take. It provides real-time map-based turn-
by-turn guidance. The technology used in these devices uses mechanisms that
involve satellite signals and street maps. These devices also form the core of
autopilot mechanisms in an airplane. An airplane operating in autopilot mode
can be considered a robot by our definition. Over 90% take-offs and landings
of commercial flights these days are done using autopilot systems. You may
have also read about robotic surveillance drones that are used by the army to
spy on enemy territories. Unmanned guided missiles use similar devices. The
technology also exists today to create autopilot systems in cars. That is, it is
possible for your car to drive itself to wherever you’d like it to go. In some of
these applications, the questions of technology
deployment become more social and ethical: Do we
really want these or not? What are the implications?
Besides, soccer playing robots, another area of AI and robotics research that is
gathering momentum is Human-Robot Interaction (HRI). As the name
suggests it is an area of research that is studying models of interaction
315
Chapter 12
between humans and robots. Given that we already have millions of robots
amongst us, it is important to recognize the need for creating friendlier ways
of interacting with robots. While we
are of the opinion that every citizen of
this planet should be well versed in
programming and computation we also
recognize that we are nowhere near
that goal. As we mentioned several
times earlier soon there will be more
computers than people on this planet.
Perhaps robots will also follow?
Nevertheless the need for friendlier
interactions with computers has always
been recognized. With the rapid iCat is a research platform for studying
increase in the number of robot-based human‐robot interaction topics. The
applications it would be even more robot is 38 cm tall and is equipped with
imperative for robots, especially given 13 servos that control different parts of
their physical presence, to have the face, such as the eyebrows, eyes,
socially relevant behavior traits. If not eyelids, mouth and head position. With
for any other reason, it would make it this setup iCat can generate many
easier for people to accept them into different facial expressions ‐ happy,
our society and many levels. surprise, angry, sad ‐ that are needed
to create social human‐robot
Within HRI researchers are studying interaction dialogues.
models of emotion, gesture
recognition, and other social
From: research.philips.com
modalities. Emotive robots have been
studied in many applications that range from toys to medical therapy (we
mentioned the Paro seal robot in Chapter 1). Given the interest and recent
advances in the area of HRI a new field of research has emerged: social
robotics. Social robotics studies models that take into account social norms of
behavior relevant to the environment and/or application of the robot.
Emotions can play an important role in this area of research. Within the
relatively small community of researchers there is much debate about whether
social robotics requires one to have a physical robot. Simulated agents acting
socially are acceptable to some researchers but not to others. Take for
316
Fast, Cheap & Out of Control
Brian Scassellati is
developing a humanoid
robot at Yale University
that is roughly the size
of a 1-year old child.
The robot is being used
to explore more
fundamental
developmental tasks A new experimental robot from the MIT Media Lab can slant its
like hand-eye eyebrows in anger, or raise them in surprise, and show a wide
coordination. It is also assortment of facial expressions to communicate with people
being used to enhance in human‐centric terms. Called Nexi, it is aimed at a range of
applications for personal robots and human‐robot teamwork.
the diagnosis of autism From: David Chandler, MIT News Office, April 2008.
in children. Brian and
317
Chapter 12
his colleagues postulate that the social cues that a robot needs to detect and
learn are the very cues that are deficient in autistics children. They also think
that such robots can be used to create functional models of autistic behavior.
Autonomous robots are already in use delivering daily mail in large offices.
You can easily imagine the same technology being used for building roaming
vending machines. One can already configure an office espresso maker to
make coffee based on each individual’s preferences: the machine senses you
(or devices you wear) which transmit your preferences to the machine and it
gets to work. The possibilities are endless. We conclude here with another
novel application: Here is problem description (from: www.koert.com/work):
In the morning paper, I can read the weather report as well as the stock
quotes. But when I look out of my window I only get a weather update and no
stock exchange info. Could someone please fix this bug in my environmental
system? Thanks!
318
Fast, Cheap & Out of Control
Summary
Robots are getting fast, small, cheap, and autonomous. However, it is only in
the sense of autonomy that makes them desirable to be out of control. We may
not yet have sent hundreds of small robots to another plant but we surely seem
to be surrounded by millions of them here on earth. The picture of orb-like
robots on a landscape comes from the Orb Swarm project (orbswarm.com).
They are exploring using swarms of these robots coordinating and exploring
and interacting with their environment similar to the vision of Brooks and
Flynn. Whether we are successful in sending armies of orb-like robots to
another planet still remains to be seen. Though one thing is for sure: it makes
learning computing a whole lot more fun with a personal robot!
319
Chapter 12
320
Python
Overview
Chapter 1
Start Python.pyw
This is the icon you double-click on to start a Python Shell (IDLE).
>>>
The Python prompt. This is where you type in a Python command.
Note: All commands you type (including the Myro commands listed above)
are essentially Python commands. Later, in this section we will list those
commands that are a part of the Python language.
Chapter 2
321
Python Overview
Chapter 3
Values
Values in Python can be numbers (integers or floating point numbers) or
strings. Each type of value can be used in an expression by itself or using a
combination of operations defined for that type (for example, +, -, *, /, % for
numbers). Strings are considered sequences of characters (or letters).
Names
A name in Python must begin with either an alphabetic letter (a-z or A-Z) or
the underscore (i.e. _) and can be followed by any sequence of letters, digits,
or underscore letters.
input(<prompt string>)
This function prints out <prompt string> in the IDLE window and waits for
the user to enter a Python expression. The expression is evaluated and its
result is returned as a value of the input function.
main()
This is the basic structure of a robot control program in Python. Without the
first two lines, it is the basic structure of all Python programs.
322
Python Overview
range(10)
Generates a sequence, a list, of numbers from 0..9. There are other, more
general, versions of this function. These are shown below.
range(n1, n2)
Generates a list of numbers starting from n1…(n2-1). For example,
range(5, 10) will generate the list of numbers [5, 6, 7, 8, 9].
Repetition
while timeRemaining(<seconds>):
<do something>
<do something>
...
while True:
<do something>
<do something>
...
These are different ways of doing repetition in Python. The first version will
assign <variable> successive values in <sequence> and carry out the body
once for each such value. The second version will carry out the body for
<seconds> amount of time. timeRemaining is a Myro function (see above).
The last version specifies an un-ending repetition.
323
Python Overview
Chapter 4
True, False
These are Boolean or logical values in Python. Python also defines True as 1
and False as 0 and they can be used interchangeably.
and, or not
These are logical operations. They can be used to combine any expression that
yields Boolean values.
random()
Returns a random number between 0.0 and 1.0. This function is a part of the
random library in Python.
randint(A, B)
Returns a random number in the range A (inclusive) and B (exclusive). This
function is a part of the random library in Python.
Chapter 5
if <CONDITION>:
<statement-1>
...
<statement-N>
If the condition evaluates to True, all the statements are performed. Otherwise,
all the statements are skipped.
return <expression>
Can be used inside any function to return the result of the function.
<string>.split()
Splits <string> into a list.
324
Python Overview
urlopen(<URL>)
Establishes a stream connection with the <URL>. This function is to be
imported from the Python module urlopen.
<stream>.read()
Reads the entire contents of the <stream> as a string.
Lists:
[] is an empty list.
<list>[i]
Returns the ith element in the <list>. Indexing starts from 0.
<value> in <list>
Returns True if <value> is in the <list>, False otherwise.
<list1> + <list2>
Concatenates <list1> and <list2>.
len(<list>)
Returns the number of elements in a list.
range(N)
Returns a list of numbers from 0..N
range(N1, N2, N3)
Returns a list of numbers starting from N1 and less than N3 incrementing by
N3.
<list>.sort()
Sorts the <list> in ascending order.
<list>.append(<value>)
Appends the <value> at the end of <list>.
<list>.reverse()
Reverses the elements in the list.
325
Python Overview
Chapter 6
if <condition>:
<this>
if <condition>:
<this>
else:
<that>
if <condition-1>:
<this>
elif <condition-2>:
<that>
elif <condition-3>:
<something else>
...
...
else:
<other>
Chapter 7
ceil(x) Returns the ceiling of x as a float, the smallest integer value greater
than or equal to x.
floor(x) Returns the floor of x as a float, the largest integer value less than
or equal to x.
326
Python Overview
log(x[, base]) Returns the logarithm of x to the given base. If the base is
not specified, return the natural logarithm of x (i.e., the logarithm to base e).
Trigonometric functions
327
Python Overview
Chapter 8
Chapter 9 & 10
Chapter 11
The only new Python feature introduced in this chapter was the creation of
modules. Every program you create can be used as a library module from
which you can import useful facilities.
328
Myro
Overview
Below is a chapter by chapter summary of all the Myro features introduced in
this text. For a more comprehensive listing of all the Myro features you
should consult the Myro Reference Manual.
Chapter 1
initialize(<PORT NAME>)
init(<PORT NAME>)
This command establishes a wireless communication connection with the
robot. <PORT NAME> is determined at the time you configured your software
during installation. It is typically the word com followed by a number. For
example, "com5". The double quotes (") are essential and required.
beep(<TIME>, <FREQUENCY>)
Makes the robot beep for <TIME> seconds at frequency specified by
<FREQUENCY>.
getName()
Returns the name of the robot.
329
Myro Overview
setName(<NEW NAME>)
Sets the name of the robot to <NEW NAME>. The new name should be enclosed
in double quotes, no spaces, and not more than 16 characters long. For
example: setName("Bender").
gamepad()
Enables manual control of several robot functions and can be used to move
the robot around.
Chapter 2
backward(SPEED)
Move backwards at SPEED (value in the range -1.0…1.0).
backward(SPEED,SECONDS)
Move backwards at SPEED (value in the range -1.0…1.0) for a time given in
SECONDS, then stop.
forward(SPEED)
Move forward at SPEED (value in the range -1.0..1.0).
forward(SPEED,TIME)
Move forward at SPEED (value in the range -1.0…1.0) for a time given in
seconds, then stop.
motors(LEFT,RIGHT)
Turn the left motor at LEFT speed and right motor at RIGHT speed (value in the
range -1.0…1.0).
move(TRANSLATE, ROTATE)
Move at the TRANSLATE and ROTATE speeds (value in the range -1.0…1.0).
rotate(SPEED)
Rotates at SPEED (value in the range -1.0…1.0). Negative values rotate right
(clockwise) and positive values rotate left (counter-clockwise).
330
Myro Overview
stop()
Stops the robot.
translate(SPEED)
Move in a straight line at SPEED (value in the range -1.0…1.0). Negative
values specify backward movement and positive values specify forward
movement.
turnLeft(SPEED)
Turn left at SPEED (value in the range -1.0…1.0)
turnLeft(SPEED,SECONDS)
Turn left at SPEED (value in the range -1.0..1.0) for a time given in seconds,
then stops.
turnRight(SPEED)
Turn right at SPEED (value in the range -1.0..1.0)
turnRight(SPEED,SECONDS)
Turn right at SPEED (value in the range -1.0..1.0) for a time given in seconds,
then stops.
wait(TIME)
Pause for the given amount of TIME seconds. TIME can be a decimal number.
Chapter 3
speak(<something>)
The computer converts the text in <something> to speech and speaks it out.
<something> is also simultaneously printed on the screen. Speech generation
is done synchronously. That is, anything following the speak command is
done only after the entire thing is spoken.
speak(<something>, 0)
The computer converts the text in <something> to speech and speaks it out.
<something> is also simultaneously printed on the screen. Speech generation
331
Myro Overview
timeRemaining(<seconds>)
This is used to specify timed repetitions in a while-loop (see below).
Chapter 4
randomNumber()
Returns a random number in the range 0.0 and 1.0. This is an alternative Myro
function that works just like the random function from the Python random library
(see below).
askQuestion(MESSAGE-STRING)
A dialog window with MESSAGE-STRING is displayed with choices: 'Yes' and
'No'. Returns 'Yes' or 'No' depending on what the user selects.
askQuestion(MESSAGE-STRING, LIST-OF-OPTIONS)
A dialog window with MESSAGE-STRING is displayed with choices indicated in
LIST-OF-OPTIONS. Returns option string depending on what the user selects.
currentTime()
The current time, in seconds from an arbitrary starting point in time, many years
ago.
getStall()
Returns True if the robot is stalled when trying to move, False otherwise.
getBattery()
Returns the current battery power level (in volts). It can be a number between 0
and 9 with 0 indication no power and 9 being the highest. There are also LED power
indicators present on the robot. The robot behavior becomes erratic when batteries
run low. It is then time to replace all batteries.
Chapter 5
getBright()
Returns a list containing the three values of all light sensors.
332
Myro Overview
getBright(<POSITION>)
Returns the current value in the <POSITION> light sensor. <POSITION> can
either be one of 'left', 'center', 'right' or one of the numbers 0, 1, 2.
getGamepad(<device>)
getGamepadNow(<device>)
Returns the values indicating the status of the specified <device>. <device>
can be "axis" or "button". The getGamepad function waits for an event
before returning values. getGamepadNow immediately returns the current
status of the device.
getIR()
Returns a list containing the two values of all IR sesnors.
getIR(<POSITION>)
Returns the current value in the <POSITION> IR sensor. <POSITION> can
either be one of 'left' or 'right' or one of the numbers 0, 1.
getLight()
Returns a list containing the three values of all light sensors.
getLight(<POSITION>)
Returns the current value in the <POSITION> light sensor. <POSITION> can
either be one of 'left', 'center', 'right' or one of the numbers 0, 1, 2. The
positions 0, 1, and 2 correspond to the left, center, and right sensors.
getObstacle()
Returns a list containing the two values of all IR sesnors.
getObstacle(<POSITION>)
Returns the current value in the <POSITION> IR sensor. <POSITION> can
either be one of 'left', ‘center’, or 'right' or one of the numbers 0, 1, or 2.
333
Myro Overview
savePicture(<picture>, <file>)
savePicture([<picture1>, <picture2>, …], <file>)
Saves the picture in the file specified. The extension of the file should be
“.gif” or “.jpg”. If the first parameter is a list of pictures, the file name
should have an extension “.gif” and an animated GIF file is created using
the pictures provided.
senses()
Displays Scribbler’s sensor values in a window. The display is updated every
second.
show(<picture>)
Displays the picture in a window. You can click the left mouse anywhere in
the window to display the (x, y) and (r, g, b) values of the point in the
window’s status bar.
takePicture()
takePicture(“color”)
TakePicture(“gray”)
Takes a picture and returns a picture object. When no parameters are
specified, the picture is in color.
Chapter 6 & 7
Chapter 8
GraphWin()
GraphWin(<title>, <width>, <height>)
Returns a graphics window object. It creates a graphics window with title,
<title> and dimensions <width> x <height>. If no parameters are specified,
the window created is 200x200 pixels.
<window>.close()
Closes the displayed graphics window <window>.
334
Myro Overview
<window>.setBackground(<color>)
Sets the background color of the window to be the specified color. <color>
can be a named color (Google: color names list), or a new color created using
the color_rgb command (see below)
Point(<x>, <y>)
Creates a point object at (<x>, <y>) location in the window.
<point>.getX()
<point>.getY()
Returns the x and y coordinates of the point object <point>.
Rectangle(<point1>, <point2>)
Creates a rectangle object with opposite corners located at <point1> and
<point2>.
Oval(<point1>, <point2>)
Creates an oval object in the bounding box defined by the corner points
<point1> and <point2>.
335
Myro Overview
<object>.draw(<window>)
Draws the <object> in the specified graphics window <window>.
<object>.undraw()
Undraws <object>.
<object>.getCenter()
Returns the center point of the <object>.
<object>.setOutline(<color>)
<object>.setFill(<color>)
Sets the outline and the fill color of the <object> to the specified <color>.
<object>.setWidth(<pixels>)
Sets the thickness of the outline of the <object> to <pixels>.
<object>.move(<dx>, <dy>)
Moves the object <dx>, <dy> from its current position.
beep(<seconds>, <frequency>)
beep(<seconds>, <f1>, <f2>)
Makes the robot beep for <seconds> time at frequency specified. You can
either specify a single frequency <frequency> or a mix of two: <f1> and
<f2>.
336
Myro Overview
robot.playSong(<song>)
Plays the <song> on the robot.
readSong(<filename>)
Reads a song file from <filename>.
song2text(song)
Converts a <song> to text format.
makeSong(<text>)
text2song(<text>)
Converts <text> to a song format.
Chapter 9
getHeight(<picture>)
getWidth(<picture>)
Returns the height and width of the <picture> object (in pixels).
getPixel(<picture>, x, y)
Returns the pixel object at x,y in the <picture>.
getPixels(<picture>)
When used in a loop, returns one pixel at a time from <picture>.
getRGB(pixel)
getRed(<pixel>)
getGreen(<pixel>)
getBlue(<pixel>)
Returns the RGB values of the <pixel>.
337
Myro Overview
makePicture(<file>)
makePicture(<width>, <height>)
makePicture(<width>, <height>, <color>)
Creates a picture object either by reading a picture from a <file>, or of the
given <width> and <height>. If <color> is not specified, the picture created
has a white background.
pickAColor()
Creates an interactive dialog window to select a color visually. Returns the
color object corresponding to the selected color.
pickAFile()
Creates an interactive dialog window that allows user to navigate to a folder
and select a file to open. Note: it cannot be used to create new files.
repaint()
repaint(<picture>)
Refreshes the displayed <picture>.
savePicture(<picture>, <file>)
savePicture(<picture list>, <gif file>)
Saves the <picture> in the specified file (a GIF or JPEG as determined by
the extension of the <file>: .gif or .jpg). <picture list> is saved as an
animated GIF file.
setColor(<pixel>, <color>)
setRed(<pixel>, <value>)
setGreen(<pixel), <value>)
setBlue(<Pixel>, <value>)
Sets the color of <pixel> to specified <color> or <value>.
show(<picture>)
show(<picture>, <name>)
Displays the <picture> on the screen in a window named <name> (string).
338
Myro Overview
takePicture()
takePicture(“gray”)
takePicture(“blob”)
Takes a picture from the Scribbler camera. It is a color picture by default, or
grayscale (“gray”), or a filtered image based on the defined blob (“blob”). See
chapter text for examples.
Chapter 10
There were no new Myro features introduced in this chapter. Actually, when
the chapter is complete it will have Myro primitives for neural nets/conx
described here.
Chapter 11 & 12
339
Myro Overview
Index
A Bluetooth 6, 8
AAAI 18 Bluetooth logo 18, 40
ABC song 68 blur image 229
abstraction 36 Boolean 85
acos 183, 326 boundary conditions 296
Aesop 43 Braitenberg, Valentino 130, 153
Aggressive, Vehicle#2 135‐6 Braitenberg Vehicles 130‐
Aibo 4 Breazeal, Cynthia 18, 317
algorithm 281, 292, 302, 305 Brooks, Rodney 309‐10, 317
Al Khwarizmi 283 Burglar Alarm 145
Alive, vehicle#1 131‐5
Anananova 317 C
and 85, 86, 92, 324 C6
Animated GIF 220 C++ 293
AntiqueWhite 189 CamelCase 68
append 111, 125, 325 case sensitive 48
Apple Strudel 280 ceil 164, 182, 326
Artificial Intelligence 4, 88, 245‐271 Celsius 67
movie 3, 245 characters 52
Asimov’s Laws 17 Chazelle, Brian 307
asin 183, 326 Chess 250
askQuestion 78, 79, 91, 137, 332 Chicken Kabobs 276‐7
assignment 50, 66, 323 Chinese Room 270
atan 183, 326 Ching‐Chong‐Cha 177
Avoiding obstacles 148‐151 choice 257, 269
Circle 192, 210, 335
B Clash, The 129
backward 24, 38, 330 close 189, 209, 334
battery disposal 89 Cockroach 153
beep 12, 16, 201‐205, 211, 329, 336 color_rgb 194, 210, 335
Behavior‐based control 158 CommonLisp 293
Blobs 236 comments 32
blob filtering 236 computable 304
340
Myro Overview
341
Myro Overview
342
Myro Overview
K M
Kasparov, Gary 250 main 65, 322
Kismet robot 317 makeColor 222, 224, 239, 338
Kitaoka, Akiyoshi 215 makePicture 219, 221‐, 239, 338
Koch Snowflakes 213 Mandelbrot Sets 213
Konane 250 Mars Rover 1, 2, 4
Martin, Fred 153
L math library 139‐40, 164‐6, 326
Ladybug 129 Maze solver 151
Larson, Doug 273 meaning of life 280
LavenderBlush 189 Measuring Device 145‐6
Law, Jude 245 Media Player 43
Leap Frog 313 Megapixel 217
leap year 291‐5 Mignot, Charles 318
Learning 267 Minimax algorithm 262
LED 89 Minsvoort, Koert van 318
LEGO Mindstorms 3 MIT Media Lab 153, 317
len 110, 124, 325 mixed case 68
Lenhi, Jurg 313 module 31, 33, 34, 299
Light following 146‐8 Monty Python 6, 29
Line 191, 210, 335 Morris, Errol 310
linear time algorithms 302 Moscow 110, 112
List comprehensions 255 motors 23, 38, 330
lists 60, 109‐13, 325 move (robot) 25, 38, 330
Loan calculator 167‐76 move (graphics object) 198, 211, 336
local name 196‐7, 328 musical scale 204
localtime 94 Myers, Mike 157
log 165, 183, 326 Myro 6, 8, 13, 329
log10 165, 183, 326 myro Song Format 206
logarithmic time algorithms 302
logical operations 85 N
loop 60 Names 48, 49, 65, 163, 195‐8, 322
343
Myro Overview
344
Myro Overview
345
Myro Overview
Squyres, Steve 1 U
Start Python 9, 16, 321 UGOBE Inc. 21
strings 50, 52 uncomputable 304
stop 25, 38, 331 undraw 211, 336
Subsumption Architecture 160 Unicode 85
Sullivan, Jon 71 Unimation 4
syntax error 35 unsolvable 304
urlopen 117, 124, 325 urllib 117
USDA 281‐2
V
T Values 50, 65
Tag reading pen 313 variable 50
takePicture 100‐2, 123, 216‐, 240, Victoria Crater, Mars 3
334, 339
Takada 312 W
tan 183, 326 wait 29, 39, 322, 331
Tengu 311‐12 Wales 58
Testing 296‐9 Wall Detector 145
text 200, 210, 336 Washington DC 301
Terra flops 304 Washington state 301
Thingamapoops 313 while 62, 66, 83, 87, 323
Tic Tac Toe 250‐264 WhiteSmoke 189
time 94 Wikipedia 18, 29
Space Complexity 301‐5 Wong, Yingshun 157
timeRemaining 62, 64, 332 world population 53, 64, 89
Timid 141 world wide web 5
TOMY Company 312
Toyota Prius 110 X
Traffic Lights 157 XO Laptop 273‐4
translate 25, 38, 331
True 63, 84, 86, 91, 324 Y
Tumbleweed robot 2 Y2K Problem 307
Turing, Alan 246, 270
Turing Test 246 Z
turnLeft 24, 38‐39, 331 Zamboni 58, 92
turnRight 24, 39, 331 Zefrank 313‐14
346
Myro Overview
347
Myro Overview
348