I finally found time to play with my Rapiro - Programmable DIY Robot Kit robot (thanks again Element14 for accepting me for this RoadTest!).
You can have a look at the review I wrote, but in a nutshell, after having figured out a few hardware issues, I was essentially ready to start hacking and code what I had in mind: I wanted my Rapiro to become an IoT (Internet of Things) device, that I could control for virtually anywhere in the world!
The project
Meet Rapiro. Rapiro is a nice little toy, that comes in a kit. It is, as you've guessed, a robot!
- The robot itself consists of 12 servos (3 in each arm, 2 in each leg, 1 for the head and 1 for the waist), enabling a wide range of movements. Not-so-wide movements actually, the robots' limb are very short!
- A Raspberry Pi, in the head of the robot, allows
- A PiCam, a 5Mpix camera extension to the Raspberry Pi, allows to take pictures, records videos, ...
- A USB WiFi dongle allows to control the robot completely wirelessly
I won't detail how to assemble the Rapiro, neither will I explain how to get your Raspberry Pi setup with a Linux distro since there are plenty of resources on the Internet. The fun part actually starts after you have finished assembling the Rapiro, and when the Raspberry Pi is properly running, allowing you to open a remote SSH connection to start hacking the beast!
The goal is very simple: my Rapiro is able to get Internet connectivity, thanks to its Raspberry Pi and WiFi dongle, so I want to make it controllable remotely. To that effect, I am going to use MQTT, a very lightweight protocol well-suited for Internet of Things communications, to send commands to the robot. Thanks to the PiCam, the robot should also, when asked to do so, take a picture and transmit it. I want to be able to open a browser from wherever in the world, and start controlling my Rapiro (because why not, eh? ), so I will develop a simple web UI to send the actual MQTT commands.
Steps
Install Eclipse Orion
Eclipse Orion is an IDE that you can run from your favorite web browser. Once you have Orion running on a device (here it's going to be on the Raspberry Pi attached to my Rapiro, obviously), all you really need is a browser for writing.
We are going to run Orion on top of Node.js so we are going to need Node.js first.
cd wget http://nodejs.org/dist/v0.10.26/node-v0.10.26-linux-arm-pi.tar.gz tar -xvzf node-v0.10.26-linux-arm-pi.tar.gz sudo mv node-v0.10.26-linux-arm-pi /opt/node/
In order to have the node and npm executables in your PATH, you can edit the /etc/profile file and add the following lines:
NODE_JS_HOME=/opt/node" PATH="$PATH:$NODE_JS_HOME/bin" export PATH
Great! Node is now correctly installed, and we can use the standard package manager (npm) to install and start Orion.
npm install orion npm start orion
You should see an output similar to this:
> orion@0.0.30 start /home/pi/node_modules/orion > node server.js Using workspace: /home/pi/node_modules/orion/.workspace Listening on port 8081...
And if you open your favorite web browser (http://ip-address-of-your-raspberrypi:8081), you'll see that Orion is actually running – congrats!
So what's next? Orion is going to help us develop a very simple application that will expose Rapiro's Arduino-based controller, to the Internet.
Allow the Rapiro to be controlled from anywhere with MQTT
Rapiro built-in serial commands
By default, the Rapiro is meant to be controlled over a serial connection. Basically, the servo-motors are all attached to an Arduino board, onto which runs a program that listens to commands on the serial interface. These commands can be either built-in, like #M1 to start walking or #M5 to wave hands, or more complex sequences, like #PR000G255B000T010 to set the eyes LEDs to Green (R=0, G=255, B=0), in 10 units of time (T=10).
The Rapiro's head is home for its second brain, in addition to the Arduino controller: a RaspberryPi. It is powered by the same battery pack than the robot, and connected to the Arduino's serial line meaning that I can actually send serial commands from virtually any program that I'd run on the Raspberry Pi. As a very first test, you can ask the Rapiro to start walking from the command line of your Raspberry Pi:
echo "#M1" | sudo minicom -b 57600 -o -D /dev/ttyAMA0
So now the goal is to use Orion to write a simple app that will use MQTT to listen to commands that a web UI is going to send, and forward these commands to the Arduino controller over the serial port.
In Orion, we're going to create a new project (File > New > Project > Basic).
And in this project is going to be our main application, so let's create a file called e.g. main.js.
/******************************************************************************* * Copyright (c) 2013, 2014 Benjamin Cabé and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Benjamin Cabé - initial API and implementation *******************************************************************************/ /** Serial port configuration **/ var serialport = require("serialport"); var SerialPort = serialport.SerialPort; // localize object constructor var sp = new SerialPort("/dev/ttyAMA0", { baudrate: 57600, parser: serialport.parsers.readline("\n") }); /** MQTT client configuration **/ var mqtt = require('mqtt'); var mqttClient = mqtt.createClient(1883, 'iot.eclipse.org'); mqttClient.subscribe('benjamin/rapiro/command'); sp.on("open", function() { console.log('serial port opened'); }); function publishPicture(error, stdout, stderr) { console.log("... sending the picture") mqttClient.publish('benjamin/rapiro/pic', stdout); console.log("... picture sent!") } var sys = require('sys') var exec = require('child_process').exec; var cmd = function(topic, message) { if(message === "TAKE_PICTURE") { console.log("Taking a picture!") exec("raspistill -w 320 -h 240 -hf -vf -t 1 -o - | base64", publishPicture); } else { console.log("Asking Rapiro to execute command: " + message) sp.write(message + '\n'); } }; mqttClient.on('message', cmd);
Yes, it's that simple! Not even 50 lines of Javascript code, cool eh?
Basically, we're using two NodeJS modules: serialport for manipulating the serial port of the Raspberry Pi to which the Arduino controller is attached, and mqtt for doing... MQTT communications!
The code is pretty straight forward:
- lines 14-19: we setup the serialport module, indicating the name of the serial port, its baudrate, ...
- lines 22-25: we setup the MQTT client: we want to communicate with the MQTT broker available at iot.eclipse.org, and we subscribe to the topic where we are accepting to receive commands targeted at the controller
- lines 40-50: on line 50 we indicate the Javascript callback for when a new MQTT message is receive.
In the callback, if the message we received has a "TAKE_PICTURE" payload, we're using raspistill to take a picture and output the binary JPEG encoded in base64 on stdout. publishPicture callback then takes this output, and publishes it in an MQTT message (see Lines 31-35).
If the payload is something else than "TAKE_PICTURE", we just use the serialport module to write this on the serial port, assuming it's a serial command – hopefuly it's something Rapiro can understand!
Use Orion shell to run the app
Now that we have written our MQTT-to-serial bridging application, it's time to use the Orion shell to actually launch it.
Web UI
Here the idea is pretty straightforward. I want a dead simple web UI that will allow me to publish MQTT messages, and receive base64-encoded images that I can display in my page.
In order to perform MQTT communications from a web page, there in Eclipse Paho, a Javascript client that allows to do MQTT over WebSockets.
Without further ado, here is the actual web UI for my page:
<div class="container"> <div class="row"> <div class="col-xs-12 col-md-3"> <p><a class="btn btn-default btn-lg btn-block" href="#" role="button" onclick='message = new Messaging.Message("#M0"); message.destinationName = "benjamin/rapiro/command"; client.send(message); '>STOP!</a></p> </div> <div class="col-xs-12 col-md-3"> <p><a class="btn btn-default btn-lg btn-block" href="#" role="button" onclick='message = new Messaging.Message("#M5"); message.destinationName = "benjamin/rapiro/command"; client.send(message); '>Wave hands</a></p> </div> <div class="col-xs-12 col-md-3"> <p><a class="btn btn-default btn-lg btn-block" href="#" role="button" onclick='message = new Messaging.Message("#M1"); message.destinationName = "benjamin/rapiro/command"; client.send(message); '>Walk</a></p> </div> <div class="col-xs-12 col-md-3"> <p><a class="btn btn-default btn-lg btn-block" href="#" role="button" onclick='message = new Messaging.Message("TAKE_PICTURE"); message.destinationName = "benjamin/rapiro/command"; client.send(message); '>Picture</a></p> </div> <div class="col-xs-12 col-md-12"> <img class="img-responsive" id="cam" src=""/> </div> </div> </div>
It's very simple: when a button is clicked, an MQTT message is published on the topic benjamin/rapiro/command (remember that this is what my Rapiro's Raspberry Pi is subscribed to, right?), with a payload that is what action I want the Rapiro to perform
And below is the few lines of Javascript that will initialize my MQTT client, and listen to the topic on which a base64 image may show up.
<script type="text/javascript" src="http://iot.eclipse.org/demo/js/mqttws31.js"></script> <script> client = new Messaging.Client("ws://iot.eclipse.org/ws", "rapiroweb" + new Date().getTime()); client.onConnectionLost = onConnectionLost; client.onMessageArrived = onMessageArrived; client.connect({ onSuccess: onConnect }); function onConnect() { // Once a connection has been made, make a subscription and send a message. console.log("onConnect"); client.subscribe("benjamin/rapiro/pic"); }; function onConnectionLost(responseObject) { if (responseObject.errorCode !== 0) { console.log("onConnectionLost:" + responseObject.errorMessage); // TODO reconnect?? } }; function onMessageArrived(message) { console.log('Receiving an image') var img = $("#cam"); img.attr('src', 'data:image/jpeg;base64,' + message.payloadString); }; </script>
When actually using the Web UI, granted that the NodeJS app is still running on the Raspberry Pi, the Rapiro will start doing what you're asking it too, and obviously you can use the Orion shell output to troubleshoot what's happening.
See it live!
So this is it! Check out the video below to see all of this in action!
More...
Possible improvements
It took me a couple hours to put together this project (and actually more than a couple hours to write this blog post!), so there is definitely room for improvement.
- Sending raw instructions (e.g. #M0) over MQTT is pretty convenient and very versatile, but the Node.js MQTT-to-serial bridge could be smarter, and instead of naively "forwarding" instructions received via MQTT to the Rapiro over serial, it could understand more advanced commands that would be transmitted as part of the MQTT topic. That way, an MQTT message received on the topic benjamin/rapiro/command/walk would be translated into an #M1 command being written on the serial link.
- Sending webcam images over MQTT works great, but it might be more appropriate to actually expose a live MJPEG stream to the Internet
Source code
The source code for the Web UI is on Github https://github.com/kartben/rapiro-web-ui – it's very simple, but eh, feel free to improve it!
Upcoming webinar
If you would like to ask me questions about that particular project, or if you'd like to learn more about some other cool IoT projects that are part of the Eclipse IoT initiative, please join my webinar next week, on May 7 – From Arduinos to Raspberry Pis, IoT-ize Your Embedded Projects with Open IoT software!
Top Comments