Table of Contents
Back to main Docker page
Controlling Niryo Robotic Arm with ROS
Create a ROS Melodic container
Creates a Dockerfile called Dockerfile-ros-melodic :
# # this dockerfile roughly follows the 'Ubuntu install of ROS Melodic' from: # http://wiki.ros.org/melodic/Installation/Ubuntu # and Niryo ROS installation : # https://docs.niryo.com/dev/ros/v3.2.0/en/source/simulation.html # # start from base image Ubuntu 18.04 ARG BASE_IMAGE=ubuntu:18.04 FROM ${BASE_IMAGE} # label this new image LABEL maintainer="benblop@gmail.com" LABEL version="0.1" LABEL description="basic ROS melodic Docker image for teaching" ENV ROS_DISTRO=melodic ENV ROS_ROOT=/opt/ros/${ROS_DISTRO} # disable prompt during package installation ENV DEBIAN_FRONTEND=noninteractive # # add the ROS deb repo to the apt sources list # RUN apt-get update && \ apt-get install -y --no-install-recommends \ git \ cmake \ build-essential \ curl \ wget \ gnupg2 \ lsb-release \ ca-certificates \ && rm -rf /var/lib/apt/lists/* RUN sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' RUN curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add - # # install ROS packages # RUN apt-get update && \ apt-get install -y --no-install-recommends \ ros-${ROS_DISTRO}-desktop-full \ python-rosdep \ && rm -rf /var/lib/apt/lists/* # # init/update rosdep # RUN apt-get update && \ cd ${ROS_ROOT} && \ rosdep init && \ rosdep update && \ rm -rf /var/lib/apt/lists/* # # always initialize ROS by default RUN echo "# init ROS" >> /etc/bash.bashrc RUN echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> /etc/bash.bashrc # define a user ENV newuser=rosuser RUN useradd -ms /bin/bash ${newuser} USER ${newuser} WORKDIR /home/${newuser}
Create the image :
docker build -f Dockerfile-ros-melodic -t ros-melodic .
run the image interactively, try running roscore at prompt, then stop roscore with CTRL-C and leave the container with CTRL-D :
docker run -it ros-melodic:latest /bin/bash roscore CTRL-C CTRL-D
In this container, a standard user (called rosuser) has been created. To run the conatiner as root user, add -u root in the command line :
docker run -u root -it ros-melodic:latest /bin/bash
To get the image name (ros-melodic:latest) , just type :
docker images
Save the container so it can be moved and restored on another host (from this link)
docker export container-name | gzip > container-name.gz zcat container-name.gz | docker import - container-name
Test the ROS Melodic container
Open a terminal, start the container and execute roscore
docker run --rm --name ROS-Melodic-Test -it ros-melodic:latest /bin/bash roscore
In a second terminal, verify that ROS is running, first we need to get the ID (and the name) of the container. Here the name is ROS-Melodic-Test and the ID is c012f4611c54. Then using the ID (or the name) of the container we can get its IP address by processing the docker inspect command output :
docker container ls docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ROS-Melodic-Test
Here the IP address is 172.14.0.1. We can now setup the host so it can use ROS running in the ROS-Melodic-Test container :
export ROS_MASTER_URI=http://172.14.0.1:11311 rostopic list
Automatically starts roscore
This container aims at starting roscore without starting an interactive session and typing roscore. The dockerfile starts from the previous image and looks like this :
# start from base image ros-melodic:latest ARG BASE_IMAGE=ros-melodic:latest FROM ${BASE_IMAGE} SHELL ["/bin/bash", "-c"] COPY ./ros_init.bash . ENTRYPOINT ["/bin/bash","/home/rosuser/ros_init.bash"] CMD /opt/ros/melodic/bin/roscore
The command (CMD) is roscore and the entry point (ENTRYPOINT) is used to to initialize ROS with the following script (ros_init.bash) :
#!/bin/bash set -e #setup ros environment source "/opt/ros/$ROS_DISTRO/setup.bash" #setup workspace if it exists if [ -n "$WORKSPACE_NAME" ]; then if [ ! -e "/root/$WORKSPACE_NAME/devel/setup.sh" ]; then previousDirectory=$(pwd) cd /root/$WORKSPACE_NAME catkin_make cd $previousDirectory fi source "/root/$WORKSPACE_NAME/devel/setup.sh" fi exec "$@"
ROS container tests
In a first terminal, roscore is started
docker run --rm --name "ROS-Melodic-roscore" ros-melodic-roscore:latest
In a second terminal we get the IP address of the container (here 170.14.0.1) and we try to get the default topics from roscore :
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ROS-Melodic-roscore export ROS_MASTER_URI=http://172.14.0.1:11311 rostopic list
We should see the default /rosout and /rosout_agg topics. Now we will wait for a /counter topic to be published :
rostopic echo /counter
The publication of this /counter topic we be done in a container. We start an interactive session on ROS-Melodic-Test container. In a third terminal, using docker inspect, we can get the IP address of this container (here 170.14.0.2) so we can connect both containers on the same **roscore*.
docker run --rm --name "ROS-Melodic-Test" -it ros-melodic:latest /bin/bash export ROS_MASTER_URI=http://172.14.0.1:11311 export ROS_IP=172.14.0.2 rostopic pub -r 1 /counter std_msgs/Int32 "data: 8"
In the last line we are sending an integer value (8) in the topic /counter every second. Going back in second terminal, the value 8 should be echoed every second. Other terminals can be connected to the ROS-Melodic-Test container. For example, a new session can be started in a fourth terminal as follows :
docker exec -it ROS-Melodic-Test /bin/bash export ROS_MASTER_URI=http://172.14.0.1:11311 export ROS_IP=172.14.0.2 rostopic pub -r 4 /counter std_msgs/Int32 "data: 1"
In the last line we are sending an integer value (1) in the topic /counter at 4 Hz (every 250 ms). Going back in second terminal, the values 1 and 8 should be echoed with corresponding rates , 1Hz and 4Hz.