Bookmark this to keep an eye on my project updates!
by
This article assumes that you already know what ROS is and the very basics about it. If you don’t know, check it out at http://ros.org
There are already many guides that exist for ROS, explaining how to install and use it, but they’re pretty bad, so I want to try to make a good one that has a better signal-to-noise ratio. Most of the guides are either extremely unclear or stop before explaining any functionality, API, or building projects.
This article is fairly opinionated (at least at the beginning), based on what I think are good and bad design principles. I may also overly boil down concepts to make them more clear, but not entirely correct if you really get into ROS.
I haven’t used ROS much. The only thing I’ve used it for is myHelperBot (source code), which if you go looking, you’ll notice actually has no ROS code. That’s because we had to rip it out since it was bad and wasn’t working well. I’ve heard from several people who took the ME 597 course at UWaterloo that they spent most of their time just trying to get ROS working. I don’t know, because I didn’t take this course, but stumbled onto ROS in a different way.
Part of the reason I’m writing this is because ROS is difficult to start with and get into, and I want to ease the pain for other people. I think despite being a fundamentally good and useful idea, the execution of it is so bad that it is difficult for me to recommend it. For this reason, I strongly recommend not using ROS if there are other potential solutions available to you. For example, for myHelperBot, we threw away all of our code and started from scratch in .NET/C#. It turned out that it ran much better, had far more documentation to get up and running with, and was much easier to set up. With that out of the way, let’s talk about ROS.
* while this sounds great and is indeed useful, I hear of people having to build from source quite often, especially with newer builds
credit in this section goes mostly to the ROS website; I’m largely just copying and pasting
With all that out of the way, let’s get started with actually installing, explaining, and then using ROS.
I highly recommend using Ubuntu 11.10, regardless of the fact that it’s old. I used Ubuntu 12.10 and a lot of stuff was completely broken. They may or may not have fixed it since then, but the only version I can vouch for is 11.10. I’m guessing 11.04 might be fine too, but wouldn’t bet on it. I’m going to write the rest of this assuming that you’re running Ubuntu 11.10, for the sake of clarity. We’re also going to be setting up ROS Electric, which is one of the distros of ROS that I can confirm works well.
Add the ROS code to your source repos:
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu oneiric main" > /etc/apt/sources.list.d/ros-latest.list'
Set up keys to authenticate the source repos with:
wget http://packages.ros.org/ros.key -O - | sudo apt-key add -
Update your repos:
sudo apt-get update
Install ROS:
sudo apt-get install ros-electric-desktop-full
Setup environment:
echo "source /opt/ros/electric/setup.bash" >> ~/.bashrc
. ~/.bashrc
Install the rosinstall package, which lets you manage your workspace.
sudo apt-get install python-rosinstall
You now have everything installed, but you can’t do anything useful with it yet.
To verify that everything is working (or at least a good litmus test), close your current terminal and open a new one, then type:
roscore
I think it’s best to get the installation out of the way so you can start focusing entirely on understanding things. If you haven’t installed it yet, you should go back to the previous step and do that.
There are some important concepts to understand about ROS before getting started.
Of note here is that nodes can run on different hardware. For example, the sensor and motor nodes could run on two different Arduinos, and the logic node could run on a desktop, and ROS will figure this out.
Now that you have everything installed, the next steps will be:
Your workspace will store everything you’re working on. It can be messy (have code you’re not using, etc.) and it really doesn’t matter.
To create:
rosws init ~/workspace /opt/ros/electric
The first path is, of course, wherever you want it to be. Note that it can be basically anywhere, but for the purposes of this article, I’m going to assume that you put it in ~/workspace. The second path tells ROS where to look for libraries and stock code from when dealing with this workspace.
Workspaces are otherwise not very notable. I don’t recommend moving them around.
There’s a concept related to packages called stacks, which doesn’t seem very useful to me. You can read about it on the ROS site but I never needed them. They’re a way of organizing sets of packages.
To create a package, first cd into your workspace, then type:
roscreate-pkg packagename
To make sure it worked, type:
rospack find packagename
If it didn’t work, that probably means that your package is not in the ROS_PACKAGE_PATH. This happened to me. I fixed it by just adding the workspace manually to ROS_PACKAGE_PATH in my .bashrc:
ROS_PACKAGE_PATH=/home/user/workspace:$ROS_PACKAGE_PATH
After adding that, type:
source ~/.bashrc
Then you should be good to go.
We’re not going to put any actual code in here, yet.
The node is where our actual code will go. We’re going to create one in C++ for now, since for almost any project you’re going to need some C++ anyways.
Navigate to ~/workspace/packagename/src/ and create a file called mynode.cpp. Then copy and paste the following into it:
[Embedded GitHub gist omitted: https://gist.github.com/DouglasSherk/ad6fe8587cc7eb7ca437]
This is basically the bare minimum that could possibly be useful in any way, and is a decent place to start for any node. This should be fairly self-explanatory.
Open CMakeLists.txt and add to the very bottom:
rosbuild_add_executable(mynode src/mynode.cpp)
Additional nodes are added the same way. We’ll cover that more in detail in another section.
We’re ready to actually build your package. While in ~/workspace/packagename/, type:
rosmake
When complete, your package will be ready to run.
To run this node, first you must be running the ROS core. I recommend creating two terminal tabs for this (or you could just use screen). Type:
roscore
You should get a welcome message. Next, type:
rosrun packagename mynode
Your code is now running. You can stop here or keep going. While the code is running, this is a pretty useless example, and doesn’t show anything about ROS other than the main loop. In the next sections, we’ll go over useful examples.
A far more useful example than the previous one is a publisher/subscriber model. To do this, we’re going to edit the first node to be a publisher, and the second one to be a subscriber.
First, rename mynode.cpp to publisher.cpp and fix it in CMakeLists.txt.
Next, delete everything in it, and paste this into it instead.
[Embedded GitHub gist omitted: https://gist.github.com/DouglasSherk/1652daa0819b8baef274]
Next, create a file called subscriber.cpp in the same folder, and paste this into it:
[Embedded GitHub gist omitted: https://gist.github.com/DouglasSherk/82c0276432d4f1e332fd]
Add subscriber.cpp to your CMakeLists.txt. At the end, it should now look like:
rosbuild_add_executable(publisher src/publisher.cpp)
rosbuild_add_executable(publisher src/publisher.cpp)
You can find good and more detailed instructions and explanations on the ROS website here.
You can either run these two now, or wait until we build a launcher for them, which makes it easier to run them together. If you want to run them now, type in one terminal:
rosrun packagename publisher
Then type in another:
rosrun packagename subscriber
In the publisher window, you should see something like:
[INFO] [WallTime: 1314931831.774057] hello world 1314931831.77
[INFO] [WallTime: 1314931832.775497] hello world 1314931832.77
[INFO] [WallTime: 1314931833.778937] hello world 1314931833.78
[INFO] [WallTime: 1314931834.782059] hello world 1314931834.78
[INFO] [WallTime: 1314931835.784853] hello world 1314931835.78
[INFO] [WallTime: 1314931836.788106] hello world 1314931836.79
And in the subscriber window, you should see something like:
[INFO] [WallTime: 1314931969.258941] /subscriber_17657_1314931968795I heard hello world 1314931969.26
[INFO] [WallTime: 1314931970.262246] /subscriber_17657_1314931968795I heard hello world 1314931970.26
[INFO] [WallTime: 1314931971.266348] /subscriber_17657_1314931968795I heard hello world 1314931971.26
[INFO] [WallTime: 1314931972.270429] /subscriber_17657_1314931968795I heard hello world 1314931972.27
[INFO] [WallTime: 1314931973.274382] /subscriber_17657_1314931968795I heard hello world 1314931973.27
[INFO] [WallTime: 1314931974.277694] /subscriber_17657_1314931968795I heard hello world 1314931974.28
[INFO] [WallTime: 1314931975.283708] /subscriber_17657_1314931968795I heard hello world 1314931975.28
You’ll notice that the main weakness of this setup so far is that you have to have 3 terminal windows open, one for each of: the core, the subscriber, the publisher. Fortunately, we have an easy way to launch multiple nodes at once, called a launcher. Create a file called packagename.launch inside the ~/workspace/packagename/ folder, and paste this into it:
[Embedded GitHub gist omitted: https://gist.github.com/DouglasSherk/eaa83054d9120e655cb9]
Now to launch both of the nodes, you can type:
roslaunch packagename
Note that you still have to run roscore separately.
One of the most useful things about ROS is its ability to relatively seamlessly interface with Arduino. This implementation even scales well, supporting tons of message passing that as a non-expert at serial communication I have not been able to replicate.
To get started, we have to install the ROS serial package:
sudo apt-get install ros-electric-rosserial
With this installed, we have to copy ros_lib (a set of Arduino libraries and examples) to the Arduino sketchbook folder. The sketchbook folder is the location that Arduino saves to by default. If you’re not sure where it is, you can also find it in the Arduino IDE’s settings. You can also change it there. To copy ros_lib over, type the following:
roscd rosserial_arduino/libraries
mkdir -p sketchbook/libraries
cp -r ros_lib sketchbook/libraries/ros_lib
Now restart Arduino, then go to File>Examples and you should see a ros_lib folder with some examples in it.
Next, we’re going to create a new Arduino sketch and call it publisher.pde. Paste the following code into it:
[Embedded GitHub gist omitted: https://gist.github.com/DouglasSherk/66c99d8bb35c270864aa]
Compile and upload this to your Arduino. Once complete, make sure that roscore is running, and then run the ROS serial helper:
rosrun rosserial_python serial_node.py /dev/ttyUSB0
Note that the port may not be named /dev/ttyUSB0. You can find its name in the Arduino IDE’s “Port” menu.
Also note that this node will segfault whenever you unplug the Arduino. You will have to rerun it when this happens. Also, to upload code to your Arduino, you have to first shut this node down, then upload the code, then rerun the serial node.
Finally, run the subscriber on your main computer (don’t run the launcher):
rosrun packagename subscriber
Your Arduino should now be communicating with your computer. If not, make sure the following are connected and running:
You can find more tutorials and explanations on the ROS website here.
Some useful commands that didn’t make it into any of the instructions:
rostopic echo chatter - echoes published messages, so you can figure out if problems are on the subscriber or publisher side (chatter is the topic to echo).roswtf - displays errors and warnings about anything running attached to ROS.roscd - cd’s into a package directory, whether it’s with the ROS installation or in your workspace.That’s it. I also have some experience getting the Kinect stuff running, but I wouldn’t recommend using it at all. If enough people want me to write a tutorial on that, maybe I will.
tags: