ROS1 Docker tutorial

This is a walkthrough of the standard ROS1 tutorial using the WSL2 docker image prepared in the previous post.

If you’ve followed the previous tutorial, your docker volume should have a folder structure which looks something like this:

o l u m e b d s u e r i v c l e d l - C M a k e L i s t s . t x t

In a running container, the top level will be mapped to /root/Ros1Test. To create the required new folders and files, you can work from Visual Studio Code or from the command line inside the Docker container. Or mix both. It’s the same file system.

Let’s start by working in the container. Make sure you’ve got it running by using ‘docker compose up’ and then open another terminal window and connect a new session to the same container: docker exec -it r1_limo_n bash. This will run a new shell on the same Docker container. You might want to source \opt\ros\noetic\setup.bash at this point. Now cd /root/Ros1Test/src, and you’re ready to follow the standard tutorial.

cd /root/Ros1Test/src
catkin_create_pkg test_package std_msgs rospy roscpp
cd ..
catkin_make
cd test_package
mkdir scripts

Now you need to create the python script files for talker and listener, and then edit the CMakeLists.txt to encourage catkin to include them in its build. Let’s do this with Visual Studio Code. Using the Docker extension, explore the volume in a dev container (right-click on the volume and select “Explore in a dev container”). In the ‘scripts’ folder you just created, add the new files “listener.py” and “talker.py”:

#!/usr/bin/env python3
# this file is listener.py
import rospy
from std_msgs.msg import String

def callback(data):
    rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
    
def listener():
    rospy.init_node('listener', anonymous=True)
    rospy.Subscriber("chatter", String, callback)
    rospy.spin()

if __name__ == '__main__':
    listener()
#!/usr/bin/env python3
# This file is talker.py
import rospy
from std_msgs.msg import String

def talker():
    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)
    rate = rospy.Rate(10) # 10hz
    while not rospy.is_shutdown():
        hello_str = "hello world %s" % rospy.get_time()
        rospy.loginfo(hello_str)
        pub.publish(hello_str)
        rate.sleep()

if __name__ == '__main__':
    try:
        talker()
    except rospy.ROSInterruptException:
        pass

Then edit the CMakeLists.txt file in the src folder, adding this at the end:

catkin_install_python(PROGRAMS scripts/talker.py scripts/listener.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

Now the package is ready to build. Go back to the command shell in the docker window and make the package:

cd /root/Ros1Test/src/test_package
catkin_make

Assuming all is well, it should now be possible to test the talker and the listener. In the Docker shell you’ve already got open, start the ROS core process by entering roscore. This will tie up that window until you use Ctrl-C to exit, so we’ll open up new windows for the talker and the listener. Start up two new terminal windows, and in each of them issue the command docker exec -it r1_limo_n bash. Now you’ve got two noew shell into the same Docker container. In one, run the talker:

cd /root/test
source devel/setup.bash
rosrun test_package talker.py

And in the other run the listener:

cd /root/test
source devel/setup.bash
rosrun test_package listener.py

That’s it. You now have ROS 1 running in a container on Windows, running nodes you’ve just created.