Skip to main content

Achoo! Crash-choo! Episode II

Some humans find it very, very hard to multi-task.  Like drink coffee, eat toast (with baked beans on top), talk and cycle... all at the same time (...and all of this just after waking up, from a bad night's sleep).  But this is where robots should be cleverer than humans.  They can do many things, at the same time (sort of).  Or they do a little bit of each thing so extremely quickly that it seems like they are doing it all simultaneously.  But, regardless, we still like to think we are cleverer than robots.  And we like to be bossy.  So we're going to order them to be better than us... and multi-task.

Let's remind ourselves:  We were able to move Rosie by controlling her remotely.  Separately, we got her to alert us when there was an object in front of her.  But - I hear your say - how do we get her to do both of those things at the same time?  Could she, for example, think through all the steps needed to drink her Starbucks latte, eat beans on toast, describe to us the taste (yummy!), and compete in the Tour de France, all at the same time?  And how does she keep track of how she's progressing with each task, and work out what to do next when things (obviously) start to go wrong?  If she's now drinking beans on coffee, she needs to stop cyclingRight?

Here's the thing.  Everything we've been doing so far has been boringly sequential... we progressed through each line of Rosie's Python code embedded deep in her brain, in order, one line at a time.  That's so boring.  So yesterday.  Today, we want to get Parallel.  As per the words to this famous song from 1981*:
Let's get parallel, parallel
I want to get parallel
Let's get into parallel
Let me hear your Rosie talk
 *Not really.

You will need to have these:

  • Raspberry Pi 3 (with motors / wheels), and Raspbian running on SDHC card
  • Computer from which you are connecting to the Raspberry Pi remotely
  • Ultrasonic range (distance) sensor and 'RGB' LED to plug into Pi's GPIO pins
  • Obstacles... lots of them

You will need to have done these things:

  1. I’ve got Pi(3) brain
  2. Why-Fi-ght the Wi-Fi?
  3. Hurrah-ndom inventions
  4. Don't reinvent the eel
  5. Achoo! Crash-choo! Episode I

You will need to do this:

  • Adapt the Python program to use a thread
  • Try and make Rosie crash!

What do you get after all this?

You may not have noticed it, but we were walking (or in the case of Rosie, crashing) into a big problem.  And that problem wasn't (for once) Tammy, the cat.

We can control Rosie remotely using our keyboard (over SSH).  And our grand plan was just to combine that bit of code with our code for the distance sensor.  Rosie can then be controlled, but also detect obstacles, at the same time.  Easy.  We just copy and paste in the new code somewhere before or after the existing code.  And we can move onto more interesting things, right?

No way, Jose.  Esto no es tan simple.  And this is why.  The code that takes keyboard input halts, and waits (patiently) on a line of code that requires a human - yeah, that's you - to enter an arrow key before carrying on.  So while it's waiting, it won't be able to do any other useful stuff, like check for approaching alien spaceships using the distance sensor.  And, likewise, once the motors have been instructed to move forwards, Rosie's application will continue to remain paused, until instructed to stop or change direction, using another keyboard key.  There's no background monitoring during these pauses.  We don't get our LED colour changes.  We don't get our auto-break.  That's right... Rosie will continue to crash into Tammy.  Booo!  It's called Blocking, and we don't like it.

So we think.  And we think some more...  What we would actually like to do is run two sets of code in parallel; one in the background, constantly checking the distance sensor, and another (the main program) that waits for, and processes, your input.  And crucially, the main program should have access to what the other bit of code is reporting back so that it can use that information to help it make decisions.

There are many different techniques in programming to achieve this; but in Python, the two most common solutions involve the use of Processes or Threads - mechanisms that seemingly allow bits of code to run in parallel.  There are endless discussions on the Internet about the differences between the two, and why you might use one or the other.  But we don't like the sound of processes (we like to make things up as we go along, you know, break the rules) so let's use threads instead.

Confused already?  Of course.  But is it all worth it?

Yes!  Because when it's all working, Rosie appears to be doing a lot more than just accepting our demands.  She is thinking for herself in the background, and constantly trying to stop us from making the wrong decisions.

This is simply too much detail:

Let's see some Blocking in action.  Temporarily create a file called '' (aren't we being imaginative today?) and place the following lines in the file:

...creates '' Python application file and open in nano

print("ROSIE: Where would you like to go now?")
destination = raw_input()
print("ROSIE: Ok, let's go to...")

If you now run this, you'll notice that it is waiting for you to enter something.

...runs the '' Python code

It's only once you enter that something (and hit 'Enter') that the code carries on and completes.  This makes sense in this case, because carrying on without having the destination from you is pointless.  Where would you go?

We can also confirm this by running Python interactively. 

Sometimes we don't want to create an application (the .py file) to test our code.  We just want to run some Python commands in real-time, and see what it does.  There is nothing stopping you from running Python interactively.  To do this, from the Linux shell, simply type:

...launches Python shell

Here, you can run any Python code you like - interactively - to see what happens.  Use the function exit() to leave the shell at any time.  For example:

message = "Welcome to the world of Python shell"

Start up the Python shell again.  Now, let's just type in the following line from the '' file:

destination = raw_input()

There; we have confirmed that the raw_input() function is Blocking, and that it waits until someone enters something.  All very useless, if you have other things that you need your robot to be thinking about and doing in the meantime.

Now, time to meet the latest of your Python friends: Thread.  He's a bit difficult.  He's moody.  He likes to work alone in most cases.  But you'll grow to like him.  After all, he has special powers; he allows one section of your code to magically run independently. Now would be a great time to ask him to do just that.

Create a new Python file called ''.

...creates '' Python application file and open using nano text editor... but you knew this already!

This is the code that hopefully achieves our aims (for now):

Most of the code will look familiar, as it is simply an ugly mash-up of '' and ''.  The main points of interest are listed out below.

First things first.  We need the threading module to use... wait for it... threads.   If you are using Processes instead, the module would be called 'multiprocessing'.  Read up on the differences between threads and processes before choosing which one to use.

from threading import Thread

A new function check_distance() is created.  This essentially contains the bulk of our code from '' which checks distance sensor input, and changes Rosie's alert level.  It's a busy function: it also does the LED colour changing, and the emergency stopping of motors.  We would like the function to be run as a thread, in the background, infinitely, regardless of what we are telling Rosie to do.  It's, after all, critical to her safety.

def check_distance():
    #...code to check distance, change alert level, change LED colour, stop motors...

A variable to track Rosie's alert level (0 = normal, 1 = warning, 2 = danger) is declared as being 'global'.  This is to allow the main program (more on this later) to receive Rosie's alert level from the background thread.

global alert_level

There are other (more sophisticated, and probably correct!) ways to share data between threads, the most common being Queues, but we'll stick to using a global variable for now.  But remember, running threads can cause a lot of havoc if you don't keep track of what they are all doing, and to what, and when.

And the rest of the program, borrowed heavily from '', ends up in the 'main' part of the program.  In Python, this is defined using a bizarre bit of code.  Don't ask.  Just accept that this is how you define the main section of your program which only gets executed when running your program directly.

if __name__ == "__main__":
    #...bunch of code to do what you want the application to do

Oh, yes.  If you want the thread to now start, don't forget to create an instance of it, and map it back to our check_distance() function.

t = Thread(target = check_distance)
t.daemon = True

The rest of the content here is pretty much the same as the original '' file (which in turn is based on the sample '' program from GitHub), with the exception of:

if alert_level != 2:
    rr.forward(0, 0.5)
    print("ROSIE: I'm moving forwards.\r")
    print("ROSIE: For your safety, forward is currently disabled.\r")

Here, Rosie is simply refusing to follow instructions when the 'UP' key is pressed, if the last alert level provided by the thread, running check_distance() loop, was 'danger' (2).   How sensible of her?

And that's it.  With a bit of threading, we have made a dramatic improvement to Rosie's IQ.  Tell us, who is cleverer now - you or Rosie?

Run the program to find out!

Even more reading:

Python's official documentation on threading module:
A reminder that our particular implementation makes use of the following GitHub contributions for lower-level interaction with the hardware that we are using:


  1. Pretty cool! My "Posie" enjoying a Rosie Mind Meld.

    [email protected]:~/RWPi $ python
    New state: STARTUP
    pollBumpers started with 0.100 interval
    UltrasonicDistance: readingsPerSec: 10
    pollUltrasonicDistance started with 0.100s cycle
    UltrasonicDistance: reading thread told to start
    Motors: worker thread readingsPerSec: 20
    Motors: pollMotors thread started with 0.050000 at 2018-02-19 10:32:38.538830
    waiting for threads to start

    ROSIE: I'm starting up...
    Spoken: I'm starting up

    ROSIE: I've started my distance sensor...
    ROSIE: Startup complete. Controls enabled.

    I've started my distance sensor
    Use the arrow keys to move ROSIE
    Press CTRL-c to quit the program
    ROSIE: I'm turning left.
    Spoken: I'm turning left.

    ROSIE: Too close! Too close!
    Spoken: Too close! Too close!

    ROSIE: It's all good.
    Spoken: It's all good.

    ROSIE: I'm turning right.
    Spoken: I'm turning right.

    ROSIE: I'm moving forwards.
    Spoken: I'm moving forward

    ROSIE: I'm going backwards.
    Spoken: I'm going backwards.

    ROSIE: keyp == 3 detected
    RRB3.cancel() called
    Motors.cancel() called
    Waiting for Motors.control Thread to quit
    New state: SHUTDOWN

    ********* RWPi STATUS *****
    2018-02-19 10:33:49 up 55 min, 4 users, load average: 0.02, 0.06, 0.08
    battery.volts(): 7.7
    battery.hoursOfLifeRemaining(): 8 h 25 m
    currentsensor.current_sense(): 481 mA
    Processor Temp: 55.8'C
    Clock Frequency: 600 MHz
    irDistance.inInches: 14.7
    usDistance.inInches: 33.6
    bumpers: NONE

    bumpers.cancel() called
    UltrasonicDistance.cancel() called
    Waiting for UtrasonicDistance.readThread to quit
    do_run went false. Stopping pollUltrasonicDistance thread
    New state: DONE
    myPDALib.PiExit(): PDALib.pi.stop() called
    do_run went false. Stopping pollBumpers thread
    [email protected]:~/RWPi $

    ("Posie" uses the Pi Droid Alpha interface card that provides 16 digital I/O, 8 analog-digital-conversion, and H-Bridge motor control.

    Posie thinks Rosie is a great robot friend to have.


Post a Comment

Popular posts from this blog

Tea minus 30

We're fast approaching Christmas time.  And if robots were to make one simple observation about the human species during the Christmas festivities, it's that they watch a lot of TV.  A LOT.  Often, accompanied by an inappropriate amount of greenhouse gas-producing food.  Stuff you don't normally eat during the remainder of the year - for good reason.

And most so-called shows on TV are boring to robots like Rosie.  After all, why watch a minor subspecies of the human race - celebrities - stumble awkwardly around the dance floor, dressed like a faulty, sparking circuit board?  Such branch of entertainment doesn't require robots to engage any of their proud circuitry.  Their processors remain idle.  Memory under-utilised.

But if robots are to be part of people's homes (and blend in), they need to look at least a little interested in some of this irrational nonsense.  Nobody likes a party pooper.  A killjoy.  And this is where a certain subgenre of TV entertainment co…

Break an egg! You've got to be in it to win it.

What the 'egg? It turns out: parenting is actually quite hard.

Not least because you suddenly find yourself responsible for one, two, or - in our household - three little miniature versions of us that need to be kept well away from the soldering iron. Or the 3D printer. Or that marauding hexapod that you forgot to power off before you left for work in a hurry.  But to compound matters further, you find yourself well and truly ambushed - financially.  You are at all times being pressurised by dark forces beyond your control to make an investment, however dubious the return.

That's right.  Clearly, you will be considered an abject failure as a responsible adult if you don't purchase the latest, trendy parenting gizmo. That feeding bottle sterilising kit clinically proven to kill all known bacteria through the science of nuclear fission. Or that titanium alloy buggy guaranteed not to crumple in the event of a sudden collision with falling Soviet-era space debris.  Evidently,…

Beam me up, Rosie!

How do you get from A to B?

You can't, as As and Bs are just letters in the alphabet. But if A is your house, and B is a meerkat village at your favourite safari park, you'd probably use a device equipped with GPS.  Not to be confused with UPS, who will deliver you your chosen meerkat through the post. And why on Earth would Rosie Patrol need one? Precisely, it's because she is on Earth that she needs one. Because our planet is rather big. Big enough to get lost in. And we don't want to lose our friendly plastic boxes on wheels. And maybe, eventually when she's clever enough, she'll go and defeat baddies on her own. And return home afterwards for a well deserved Earl Grey tea.

Besides, why wouldn't we want to add another three letter acronym to Rosie Patrol's repertoire?
All superheroes need:One Raspberry Pi 3, running Raspbian OSComputer from which you are connecting to the Raspberry Pi Probably the most important bit: a GPS receiver thingmy. …

LoRa-Wan Kenobi

In the regurgitated words of Michael BublĂ©: It's a new dawnIt's a new dayIt's a new Star Wars filmFor meAnd I'm (George Lucas, and I'm) feeling good.  Unfortunately for Canadian Mike, the Grammy that year was won by the novelty disco classic with the famous refrain: We love IoT, even in Planet Tatooine*.

*Not true.

Clearly, the Star Wars producers didn't sincerely mean the lastJedi the previous time around.  Return of the Jedi, released during the decade that spearheaded cultural renaissance 2.0 with the mullet and hair-metal, was less economic with the truth.  Either way, we're going to take inspiration from the impressive longevity of the money-spinning space-opera and reboot our franchise with some Jedi mind tricks.  Except this particular flick doesn't require an ever-growing cast of unrecognisable characters, unless ASCII or UTF counts.  In place of an ensemble gathering of Hollywood stars and starlets, we will be assembling together a…

Raspberry bye, hello

Let us make this very clear from the onset of this exotic excursion.

This is not a case of Raspberry Bye. Our relationship with our favourite single-board computer hasn't at all soured. In fact, we've become wholly inseparable. There's been many months of undeniable fun that's been had with the venerable computer strangely named after an edible fruit. To the extent that our relationship requires a healthy break. And quite frankly, our Pis require a well earned summer holiday to do whatever it is that robots and computers do during their time off. Crash. Burn. Refuel (with questionable toxins). Not at all unlike their human counterparts. And ultimately, it would be nice if they could return to a brand new, adorable pet waiting for them at home, a likeable little companion that they can just get along with.

Well, we visited a pet shop, but couldn't find anything as small and smart as this adorable pup we stumbled up on while searching the Internet for a new, miniat…