A robot is made up of many hardware components each of which requires its own software. Even a small robot arm with a handful of servo motors uses a servo motor library.
Add that arm to a wheeled vehicle and you have more motors. Then attach some ultrasonic sensors for collision avoidance or a camera for vision. By that point, you’ve probably split the software into multiple processes: one for the arm, another for the mobility, one for vision, and one to act as the brains interfacing somehow with all the rest. The vision may be doing object recognition, something which is computationally demanding and so you now have multiple computers.
Break all this complexity into modules and you have a use case for ROS, the Robot Operating System. As this article shows, ROS can help with designing, building, managing, and even evolving your robot.
What Is ROS?
ROS is a framework consisting of a huge number of libraries and tools specifically for developing robots. It’s open source and most code comes under the BSD license. It’s also community supported.
ROS has been primarily tested on Ubuntu and Mac OS X though the community has also gotten it working on other Linux distributions and is working on Windows. I have the Kinetic release of ROS running under Ubuntu 16.04 on my Raspberry Pi 3B.
Simulating Your Robot
Before you even build your robot, you may wish to first simulate it. For that, you can create a Unified Robot Description Format (URDF) file, which is an XML file that describes your robot in detail. There’s even a URDF exporter add-in available for SolidWorks. You then use it with ROS and the Gazebo robot simulator to see and manipulate your robot on the screen before building anything.
Structuring Things In ROS: Packages
It’s difficult to explain what’s available for ROS without also going over how things are structured.
At the top of the hierarchy, your robot application consists of one or more packages. Packages typically contain code, libraries, datasets, and configuration files. Anything that makes sense to go together as a module would go in a package. Perhaps you’ve dedicated an Arduino Nano to be a servo motor controller. You might put all the files for communicating with that Arduino into their own package.
Running the ROS command,
rospack list at the command line lists 229 packages. Here’s a small sample of what came up.
- joy – ROS driver for a generic Linux joystick
- serial – a cross-platform, simple to use library for using serial ports
- tf2 – helps you keep track of multiple coordinate frames over time
- rosout – system-wide logging mechanism for messages sent to the /rosout topic
- raspicam_node – package for getting video from the Raspberry Pi Camera
- eyeball – Pi eyeball package
The raspicam_node package is one I found online and the eyeball package is one I created from scratch.
Packages are contributed by a large community. For example, from hobbyists, there are packages for popular Pololu motor controllers and from the industrial world, there are packages for the KUKA and Baxter robots. Here’s a link to a large list of available packages. Searching online finds more.
Processes Are Nodes
A sufficiently complex robot will require multiple processes, possibly even spread out over different computers. In ROS, each process is a node. A package contains one or more nodes.
For my example, I use raspicam_node which reads from the Pi Camera and produces a compressed stream of video. A node called image_republisher decompresses that video. My eyeball node then processes images from the video. Of course, to do that they need to communicate somehow.
Communicating Between Nodes
ROS provides two mechanisms for nodes to communicate with each other.
One is a publish-subscribe mechanism wherein one node publishes that it will have data available. It publishes under a name called a topic. In the example illustrated here, raspicam_node publishes compressed video to the topic, /raspicam_node/image/compressed. A node which wants that data, image_republisher in our example, then subscribes to that topic. When the publisher has a compressed video image ready, the publisher publishes it and the subscriber will receive it.
The other communication mechanism is called services. A server node provides a service and a client node requests that service. As with publish-subscribe, the server makes its service known via a topic name and the client finds the service via that topic. Unlike with publish-subscribe, it’s the client node which initiates the communication. It does so whenever it wants the service.
Note that with both mechanisms the communication is initiated using the topic and not by directly addressing any particular node. If you’re testing different motor controllers, you could write different nodes which all publish using the same topic. Test one at a time and the subscriber will find whichever one happens to be running since it’s doing the look-up using the topic and not any specific motor controller. This is also useful if you decide to change hardware at a later date or will use a stub when hardware is out for maintenance.
ROS also provides some language independence between communicating nodes. ROS supports Python and C++. The publisher can be written in Python and the subscriber can be written in C++, or vice versa. For example, a Python publisher can gather sensor data while a C++ subscriber does the heavy-duty processing whenever there’s data available.
How are the topics mapped to specific nodes? A Master process takes care of that.
Nodes can communicate with each other across a network of machines. The Master runs on only one machine. Nodes on all other machines find the Master using an environment variable containing the hostname of the machine which has the Master.
When nodes request to publish or subscribe to a topic they give only the topic name. One day the publishing node may be on one machine and the next it might be on a different machine. Subscribers won’t know this. They’ll simply subscribe to the topic name and the Master takes care of finding the publisher.
As an example, imagine a centaur robot with a torso which can be attached to different mobile platforms. Once physically connected, nodes in the torso have to find the nodes in the mobile platform. If the same topic names are used by all platforms then the nodes will be found regardless of which platform is in use. The robot, Momaro, is shown here for illustration purposes only since it has a permanent base with only one CPU. However, it does use ROS.
There are a few useful command line and graphical tools to help with managing and debugging packages, nodes, topics, and communication. A few command line tools are rospack for packages, rosnode, and rostopic.
Rqt_graph gives a graphical display of nodes, topics and how the nodes are communicating with each other. Here we again see that /raspicam_node/image/compressed is the topic to subscribe to for compressed video images from raspicam_node and /raspicam_node/image is for uncompressed images. This display could highlight communication problems.
rqt_console and rqt_logger_level together display messages logged from nodes, whether strictly informational, warnings or errors. They’re useful for debugging and troubleshooting.
Modular Robots Welcome
And that’s a large sample of what’s available from ROS for helping you with modularity in your robots, from design and simulation to debugging and troubleshooting.
Do you have a robot which uses ROS? Perhaps you’d care to enter it into the Robotics Module Challenge of the 2018 Hackaday Prize but hurry. the June 4th deadline is fast approaching. And even if you aren’t entering the contest, we’d still like to hear about your experiences with ROS. Let us know in the comments below.
Meanwhile, we’ll leave you with a video montage showing robots that use ROS.