ROS production: our prototype [2/5]

This is the second blog post in this series about ROS production. In the previous post we discussed why Ubuntu Core was a good fit for production robotics. In this post we'll be on classic Ubuntu, creating the example ROS prototype that we'll use throughout the rest of the series as we work toward using Ubuntu Core.

I mentioned in the previous post that this series was going to use the Turtlebot 2. However, there are a number of possible configurations for the Turtlebot. Some use a Kinect, others use an Astra Pro, still others use a RealSense, etc. I want this prototype to be runnable by everyone who has a Turtlebot 2, so I'm going to cater to the lowest common denominator here: the Kobuki base. We'll keep it very simple and make it randomly wander around, bumping into things and correcting itself, utilizing both the bumper sensors as well as the cliff sensors.

I also mentioned how the ROS community has standardized around the Turtlebot as the introductory platform. That makes this prototype incredibly easy to create, as every package we need has already been written: we just need to put them together. Let's get started! Remember that this is also a video series: feel free to watch the video version of this post:

Prerequisites

This post will assume the following:

  • You’re running on Ubuntu 16.04 (Xenial)
  • You have ROS Kinetic installed (I installed ros-kinetic-ros-base)
  • You have gone through at least the first 8 ROS tutorials (e.g. you should know what a launch file is)

The computer being used doesn't matter so much as this prototype should work on any standard architecture, but for your reference I'm using an Intel NUC (the DE3815TYKE, specifically).

The prototype

Step 1: Install the Kobuki driver

The first Turtlebot-specific package we'll need is the ROS wrapper for the Kobuki driver. It contains the node that's responsible for communicating with the Kobuki itself, receiving sensor data and publishing it on ROS, etc.

$ sudo apt install ros-kinetic-kobuki-node

Step 2: Configure udev rule

By default, the driver will look for the Turtlebot at /dev/kobuki. Getting the Kobuki there takes a udev rule. Thankfully, what we just installed includes a utility for installing this udev rule:

$ rosrun kobuki_ftdi create_udev_rules

It may prompt for your sudo password. After this completes successfully, connect your Turtlebot, turn it on, and you should see the /dev/kobuki symlink show up.

Step 3: Test the Kobuki driver

We can prove that this is working by running the driver's minimal launch file:

$ roslaunch kobuki_node minimal.launch

After the system comes up, you should hear the Turtlebot sing a little tune. If that doesn’t happen, check to make sure that the udev rule is working. If it does happen, leave it running and continue.

Step 4: Install the Kobuki Random Walker

The Kobuki driver is most of what we need. Its minimal launch file brings up enough nodes to obtain data from the wheel drop sensors, cliff sensors, etc., but most importantly exposes the ability to command the robot to move. We just need to make use of it. We want it to randomly walk around, so we'll use the Kobuki Random Walker (note that this may already be installed):

$ sudo apt install ros-kinetic-kobuki-random-walker

Step 5: Test the Kobuki Random Walker

To run it (the minimal.launch file from kobuki_node still needs to be running):

$ roslaunch kobuki_random_walker safe_random_walker_app.launch

When that system finishes launching, the robot will begin randomly wandering around. If it collides with something using its bumper sensors, it'll back up and rotate, trying to get around it. If it notices it's about to drive off a cliff (e.g. your steps) it’ll stop and rotate again.

Go ahead and stop (ctrl+c) both launch files.

Step 6: Put the pieces together

At this point, if you have the appropriate 3d sensors, you could start doing the really fun stuff with the navigation stack, but as I mentioned before, we're going to keep it simple here. These two launch files make up the entirety of the prototype we'll use for this series. However, if we leave it as-is it has a small limitation: the only udev symlink location supported is /dev/kobuki. That works on our current system, but what if another user has it elsewhere? Or what if we couldn't use that exact symlink in a snap (a hint for the next post in this series)? So let's distill those two launch files into a single launch file that represents our prototype, and make it a little more configurable.

First of all, create a new ROS workspace for this prototype (you can of course put this anywhere):

$ mkdir -p ~/workspace/src
$ cd ~/workspace/src
$ catkin_init_workspace

Now create a new package within that workspace to contain our prototype's launch file. It should depend upon the two packages we know we need (kobuki_node and kobuki_random_walker):

$ cd ~/workspace/src
$ catkin_create_pkg prototype kobuki_node kobuki_random_walker

Now we're going to create our launch file:

$ cd ~/workspace/src/prototype
$ mkdir launch
$ touch launch/prototype.launch

Open that launch/prototype.launch file in your favorite editor. In your terminal, open up the minimal.launch file from the Kobuki driver:

$ rosed kobuki_node minimal.launch

We'll copy the contents of that launch file into ours, clean it up into only the bits we need, and add an argument that makes the serial port configurable. Finally, we're also going to include the random walker launch file so that launching this single launch file brings up our entire prototype:

<launch>
<!-- Make the device port configurable. -->
<arg name="device_port" default="/dev/kobuki"/>

<!--
Nodelet manager for the Kobuki driver as well as the safe
walker.
-->
<node pkg="nodelet" type="nodelet"
name="mobile_base_nodelet_manager" args="manager"/>

<!-- The ROS wrapper for the Kobuki driver. -->
<node pkg="nodelet" type="nodelet" name="mobile_base"
args="load kobuki_node/KobukiNodelet mobile_base_nodelet_manager">
<rosparam file="$(find kobuki_node)/param/base.yaml" command="load"/>
<param name="device_port" value="$(arg device_port)"/>
<remap from="mobile_base/odom" to="odom"/>
<remap from="mobile_base/joint_states" to="joint_states"/>
</node>

<!--
The safe random walker launch file that causes the robot
to wander while trying not to destroy itself by
utilizing the bumper sensors as well as the cliff
sensors.
-->
<include file="$(find kobuki_random_walker)/launch/safe_random_walker_app.launch" />
</launch>

Save and exit. We also need to modify ~/workspace/src/prototype/CMakeLists.txt to actually install that launch file:

cmake_minimum_required(VERSION 2.8.3)
project(prototype)

find_package(catkin REQUIRED)

catkin_package()

install(DIRECTORY launch
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
)

Save and exit. Note that the entire ROS project used here is available for reference. Finally, build the workspace:

$ cd ~/workspace
$ catkin_make

Now test out our final prototype:

$ source ~/workspace/devel/setup.sh
$ roslaunch prototype prototype.launch

And the robot should sing its little tune and immediately begin moving randomly again. So now we have our prototype contained in a single launch file, and we can use a different serial port like so:

$ roslaunch prototype prototype.launch device_port:=/dev/my-serial-port

In the next post in this series, we'll discuss the process of packaging this prototype as a snap.

Comments