Home » Blog » Using ROS with Docker in macOS

Using ROS with Docker in macOS

— Created: Xiaoke, 2017/06/05 13:41 CST
— Last modified: Xiaoke, 2017/06/07 21:00 CST

I am a beginner of both Docker and ROS, thus techinques listed in this article may not be the optimal or even correct ones. Contents will be continuously examined and updated.

ROS Installation in macOS

The latest LTS (long time support) version of ROS Kinetic Kame can be installed on macOS by following the official instructions. Despite a long troubleshooting list, unexpected errors about GUI packages (rqt) and Qt still occurred in my compliation of the recommended Desktop Install. The Bare Bones ROS-Comm installation turned out to be pretty smooth, but I was still obssessed with using graphics in ROS. Docker seemed to be a good choice in this circumstance.

Docker Installation in macOS

Docker for mac can be downloaded and installed from the Docker store.

Start ROS in Docker

Public docker images are managed by the so-called Docker Registry, and ROS images could be found in the OSRF respository on Docker Hub. A simple command

docker pull osrf/ros:kinetic-desktop

can easily download or “pull” the image of the Kinetic Desktop ROS. The download may take some time depending on the network speed. Note that the osrf/ros in the command refers to the name of the repository, and the kinetic-desktop after the colon is the tag or “branch”. A list of tags in the osrf/ros repository can be found here .

After pulling the osrf/ros:kinetic-desktop image, we can run it by

 docker run -it --rm --name roscore osrf/ros:kinetic-desktop  

A terminal will appear because of the '-it' option. This command actually creates a “container” called roscore due to the '–name roscore' option. The other option '–rm' tells docker that this container will be removed after it stops. Otherwise, it will be always there until we explicitly delete it by

docker rm roscore

In order to use ROS, we need to execute the roscore program first to start a master, a parameter server and a logging node. We can achieve this by executing the following code in the above terminal

ip=$(hostname -I)
export ROS_IP=$ip

After running roscore, the terminal won't accept any further commands, we could use docker exec to execute a command (e.g. bash) in the roscore container

docker exec -it roscore bash

The Talker-Listener Tutorial

After starting roscore, we can test a simple talker-listener example. First, start a listener by

 docker run -it --name listener --rm osrf/ros:kinetic-desktop

then within the terminal, execute the following code

ip=$(hostname -I)
export ROS_IP=$ip
echo $ROS_IP
rosrun rospy_tutorials listener.py

A listener program is waiting for incoming messages, but there won't be anything happening at the moment. Next we start a talker by

 docker run -it --name talker --rm osrf/ros:kinetic-desktop

and within the terminal, execute the following code

ip=$(hostname -I)
export ROS_IP=$ip
echo $ROS_IP
rosrun rospy_tutorials talker.py

Then we can see messages are displayed in both the talker and the listener terminals.

Graphics setup

Download and install XQuartz . Then use the following code to start a ros container.

ip=$(ifconfig en0 | grep inet | awk '$1=="inet" {print $2}')
echo $ip
xhost + $ip
docker run -it --rm --name turtlesim  -e DISPLAY=$ip:0 -v /tmp/.X11-unix:/tmp/.X11-unix:rw osrf/ros:kinetic-desktop

We can run the turtlesim tutorial in this terminal by

rosrun turtlesim turtlesim_node

then, open another terminal without the display settings and execute

rosrun turtlesim turtle_teleop_key

Network with Non-Docker Nodes

The ROS nodes within docker has their own network defaultly bridged to the host machine. We can make docker containers to share the same IP address with the host machine by a '–net=host' option, as

docker run -it --net=host --rm --name roscore -v /tmp/.X11-unix:/tmp/.X11-unix:rw osrf/ros:kinetic-desktop 

However, docker in macOS itself runs inside a virtual machine. The above setting merely shares the same address with the virtual machine rather than the actual host. A temperary workaround is to use port mapping as

docker run -it -p 11311:11311 --name roscore  --rm -v /tmp/.X11-unix:/tmp/.X11-unix:rw osrf/ros:kinetic-desktop

Then we can run roscore in this container, and other nodes within the same local network can connect to this ROS master.