This tutorial demonstrates how to create a simple web page that communicates with ROS using rosbridge and roslibjs.
No previous knowledge of ROS is really necessary to try out the code in this tutorial but I will not go into great detail on the concepts of ROS and its commands and utilities.
Configuring your system for the tutorial
This section will step you the installations required to carry out the demo.
1. Install ROS
If you do not have ROS installed on your computer, install it following the instructions here.
I am using the hydro release on my computer. Other releases will probably work but the names and structures of topics and messages might be slightly different. Also, this tutorial will use the turtelsim demo program so you will need that installed. The desktop-full installation of ROS includes this demo. I chose to set my environment as indicated in section 1.6 to add the ROS environment variables to all new terminal windows. Finally, this tutorial will assume you are running ROS on Linux.
2. Install rosbridge
Open up a terminal window and type
sudo apt-get install ros-hydro-rosbridge-suite
Detailed instructions can be found here, but note that they relate to the groovy release, not hydro.
Turtlesim introduction
Before I get into the details of rosbridge, I will use the turtlesim demo to introduce some fundamental ROS concepts and commands. If you encounter problems in this section, your computer is probably not configured correctly. Refer back to the installation links for details on setting everything up.
1. Run roscore
Open up a terminal window and type
roscore
This command runs the ROS master program that runs the services and coordinates communication between publishing and subscribing nodes. More detail on those terms and concepts will follow.
You can minimize this terminal window after you start roscore.
2. Run the turtlesim simulator window
Open up a terminal window and type
rosrun turtlesim turtlesim_node
This command will launch the application that displays the simulated turtle robot. ‘turtlesim’ is the name of the ROS package and ‘turtlesim_node’ is the name of the application within the package that will be executed. The turtle icon in the window is essentially listening for movement message instructions.
You can minimize the terminal window used to launch the simulator.
3. Run the turtlesim control window
Open a terminal window and type
rosrun turtlesim turtle_teleop_key
This command will run the ‘turtle_teleop_key’ application node within the ‘turtlesim’ package. In order to send commands to the ROS master, this terminal will need to have focus as you type the left, right, up and down arrow keys.
4. See the list of ROS topics
Open a terminal window and type
rostopic list
This command will list the currently available topics driven by roscore and the nodes that were launched. Topics are essentially channels that node applications can publish and subscribe to. The concept pub/sub messaging systems is a common model in software systems. I will not go into the ideas in detail but quickly say that the concept is fundamental to ROS and very relevant to a system were sensors, actuators, and so forth may be interdependent and interchanged.
One of the topics that you should see displayed by this command will be of particular interest to us. It’s fully qualified name is:
/turtle1/cmd_vel
5. Find the message type for the relevant topic
In the same terminal window type
rostopic info /turtle1/cmd_vel
This command will display information about the topic including the type of messages that will be published and consumed. Messages are objects in the sense that they can be composed of primitive values and other structures containing primitive values. The message type for the /turtle1/cmd_vel topic is indicated as
geometry_msgs/Twist
6. Investigate the message structure
In the same terminal window type
rosmsg show geometry_msgs/Twist
You will see this output
geometry_msgs/Vector3 linear float64 x float64 y float64 z geometry_msgs/Vector3 angular float64 x float64 y float64 z
This output indicates that the geometry_msgs/Twist message structure is composed of two structures of another ROS-type: geometry_msgs/Vector3. The properties of this type within the geometry_msgs/Twist type are named linear and angular.
If you run this command in the terminal window
rosmsg show geometry_msgs/Vector3
you will see that type is composed of three float64 properties named x, y, and z.
7. Monitor messages sent to the relevant topic
In the same terminal window type
rostopic echo /turtle1/cmd_vel
This command will display information related to the messages published to the named topic, in this case: /turtle1/cmd_vel
The command will run in the terminal window until it is terminated with a Ctrl+C.
8. Run the demo
Finally, time to take the turtle for a ride. The three relevant terminal windows for this step are the simulator display (step 2), the control window (step 3), and the window that will echo messages sent to the relevant topic (step 7). Make sure all three windows are visible on your desktop.
Click in the control window to give it focus. Then use the arrow keys to rotate and move the turtle.
Observer the output in the topic echo window. Note how the values change depending on the keys you press. For example, if you press the up arrow you should see this output:
linear: x: 2.0 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: 0.0
Before we start on the next section that investigates how rosbridge works, I will summarize the important points of this section:
The roscore master was started in order to manage the communication of messages between publishing and subscribing nodes
The simulator window node was launched as a subscriber to the topic relevant to the demo
A terminal window was opened to publish messages to the topic relevant to this demo
Controlling turtlesim from a web page
In this section we will build a minimal html page to control the turtle in the simulator.
The section will use rosbridge which includes a set of tools that provide a JSON API for communication with the ROS server. I should point out that I am fairly new to ROS in general. One of the first things I learned was that node applications were typically written in C++ or Python: two languages that I am not proficient in. So I was interested in the idea of rosbridge that would allow ROS communication using tools like JavaScript over WebSocket. This section will also use the ROS JavaScript library, rosblibjs. Much of what I am writing in this section is based on what I learned in this tutorial.
1. Launch rosbridge
Open a terminal window and type this command
roslaunch rosbridge_server rosbridge_websocket.launch
This command will run rosbridge and open a WebSocket on port 9090 that our web page will use to communicate with ROS.
2. Create an html file control panel
This web page is intended to demonstrate how roslibjs and rosbridge can be used to communicate with ROS. The page will not employ best practices like the use of style sheets or JavaScript libraries like jQuery. I will annotate the web page with comments that will explain the important lines.
<!DOCTYPE html> <html> <head> <!-- Based on demo found here: http://wiki.ros.org/roslibjs/Tutorials/BasicRosFunctionality http://wiki.ros.org/roslibjs/Tutorials/BasicRosFunctionality --> <!-- The next two lines bring in the JavaScript files that support rosbridge integration. --> <script type="text/javascript" src="http://cdn.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script> <script type="text/javascript" src="http://cdn.robotwebtools.org/roslibjs/current/roslib.min.js"></script> <script type="text/javascript" type="text/javascript"> // This function connects to the rosbridge server running on the local computer on port 9090 var rbServer = new ROSLIB.Ros({ url : 'ws://localhost:9090' }); // This function is called upon the rosbridge connection event rbServer.on('connection', function() { // Write appropriate message to #feedback div when successfully connected to rosbridge var fbDiv = document.getElementById('feedback'); fbDiv.innerHTML += "<p>Connected to websocket server.</p>"; }); // This function is called when there is an error attempting to connect to rosbridge rbServer.on('error', function(error) { // Write appropriate message to #feedback div upon error when attempting to connect to rosbridge var fbDiv = document.getElementById('feedback'); fbDiv.innerHTML += "<p>Error connecting to websocket server.</p>"; }); // This function is called when the connection to rosbridge is closed rbServer.on('close', function() { // Write appropriate message to #feedback div upon closing connection to rosbridge var fbDiv = document.getElementById('feedback'); fbDiv.innerHTML += "<p>Connection to websocket server closed.</p>"; }); // These lines create a topic object as defined by roslibjs var cmdVelTopic = new ROSLIB.Topic({ ros : rbServer, name : '/turtle1/cmd_vel', messageType : 'geometry_msgs/Twist' }); // These lines create a message that conforms to the structure of the Twist defined in our ROS installation // It initalizes all properties to zero. They will be set to appropriate values before we publish this message. var twist = new ROSLIB.Message({ linear : { x : 0.0, y : 0.0, z : 0.0 }, angular : { x : 0.0, y : 0.0, z : 0.0 } }); /* This function: - retrieves numeric values from the text boxes - assigns these values to the appropriate values in the twist message - publishes the message to the cmd_vel topic. */ function pubMessage() { /** Set the appropriate values on the twist message object according to values in text boxes It seems that turtlesim only uses the x property of the linear object and the z property of the angular object **/ var linearX = 0.0; var angularZ = 0.0; // get values from text input fields. Note for simplicity we are not validating. linearX = 0 + Number(document.getElementById('linearXText').value); angularZ = 0 + Number(document.getElementById('angularZText').value); // Set the appropriate values on the message object twist.linear.x = linearX; twist.angular.z = angularZ; // Publish the message cmdVelTopic.publish(twist); } </script> </head> <body> <form name="ctrlPanel"> <p>Enter positive or negative numeric decimal values in the boxes below</p> <table> <tr><td>Linear X</td><td><input id="linearXText" name="linearXText" type="text" value="1.5"/></td></tr> <tr><td>Angular Z</td><td><input id="angularZText" name="angularZText" type="text" value="1.5"/></td></tr> </table> <button id="sendMsg" type="button" onclick="pubMessage()">Publish Message</button> </form> <div id="feedback"></div> </body> </html>
What Did We Do?
So what did we accomplish in this tutorial? Something pretty cool in my opinion: we created a new controller for the existing turtlesim node without modifying that code
at all. The decoupled publish/subscribe approach that ROS supports made this accomplishment possible. I could argue that the simple node we created is superior in some ways to the command window that comes with the complete ROS installation:
- It seems that the arrow keys always send a 2 or -2. We can send any values using our web page to make the movements greater or finer grained.
- As much as I tried, I could not send linear and angular values in the same message by pressing the keys simultaneously. We can do that with the web page which allows the turtle to travel in arc paths.
Of course we only published a message in this tutorial. I should point out that there is much more you can do with roslibjs including:
- Subscribing to topics in order to receive messages
- Utilizing services hosted within ROS
- Retrieving a list of current topics within the ROS server
Next Steps
So what’s next? I think I’m going to get myself one of those Baxter robots for $25K, build the appropriate web application and never wash dishes again. Ok, maybe not yet…soon, but not just yet. There are probably a couple of other tracks I can progress on first.
Implementation on Raspberry Pi
I have another long term goal to build a disruptively affordable mobile robot platform and implement the first one as an outdoor rover. I imagine that the robot will be controlled by an SBC like a Raspberry Pi and involve an Arduino board. I have heard that some people have found it challenging to run ROS on the Raspberry Pi but it looks like there have been some successes as well. I imagine I would start by just running the minimal amount of ROS on the Raspberry Pi and use my desktop computer for development and debugging, etc. I imagine I could install Apache or Tomcat on the Raspberry Pi, but it may make sense to build a lightweight http server using libraries like Node.js and socket.io. I also want to try to use Cylon.js for tasks like communicating with the Arduino.
Better UI
Ok, I feel like we’re pretty close friends now so I will tell you this: the web page built in this tutorial is not all that attractive or slick. There are a lot of options for incorporation:
- jQuery UI has a number of great widgets
- jQuery mobile makes it very easy to develop applications for mobile devices
- I know some great developers that are favoring Ember.js in order to create ambitious web applications
Looking forward to seeing what others to with rosbridge and roslibjs. Many thanks to everyone involved in these projects.