# Lab 5.1. ROS Topics in Python

Estimated time to complete this lab: 1 hour

Objectives

At the end of this self-learning lab, you should be able to:

• Write a publisher and subscriber node in Python

## Preparations

1. Download the tutorial package lab5 from Github and place it in your ROS workspace

• You should fork the tutorial repository (https://github.com/m2robocon/m2cs_ros_tutorial) to your personal Github acount.
• Clone the forked tutorial repository to your workspace. The path of the repository should look something like ~/catkin_ws/src/m2cs_ros_tutorial.

2. Allow ROS to recognize the new package

• When in your workspace directory (pwd is catkin_ws), run catkin_make

• The meaning of catkin_make will be explained in 05 L3.
• If you run into errors about the C/C++ compiler not being installed, you need to install g++ on your computer.
To install the g++ compiler, run sudo apt-get install g++
• Verify that ROS recognizes the new package: run rospack list | grep lab5

rospack list | grep lab5 lab5 /home/m2/catkin_ws/src/m2cs_ros_tutorial/lab5
• If you do not see the package path listed, then probably you need to source the setup file of your workspace: Run the following command:
$echo "source /home/m2/catkin_ws/devel/setup.bash" >> ~/.bashrc && source ~/.bashrc  ## Section 0. Node • A node is an executable. • Nodes are placed inside packages. For example, lab5 is a package. • In Python, ROS is just a library that can be imported inside Python. The programming concepts that you learnt in other courses can still be used in ROS. • A python script can be modified to become a ROS node by adding the relevant library codes provided by ROS. ### Basic code structure for a ROS node • Look at the content of lab5/src/node_basic.py.   1 2 3 4 5 6 7 8 9 10 #!/usr/bin/env python3 import rospy if __name__ == '__main__': rospy.init_node('node_basic') rate = rospy.Rate(2) while not rospy.is_shutdown(): rospy.loginfo("hello, world!") rate.sleep()  ### Explanations Let's have a look at what the code is doing, line by line: #!/usr/bin/env python3 Make sure your script is executed as a Python script with python3. Note The #!/usr/bin/env python line points to the path that the command python3 is installed. import rospy You need to import rospy if you are writing a ROS Node. rospy.init_node('node_basic') Tells rospy that this executable is a node, with the name node_basic rate = rospy.Rate(2) The Rate object allows us to use its method sleep() to loop at a desired rate. By calling sleep() inside a loop, the program sleeps for a period of time such that the desired looping rate is maintained. while not rospy.is_shutdown(): To create a forever loop in ROS, use while not rospy.is_shutdown(): condition instead of while True: to allow more smooth node killing without SIGINT. rospy.loginfo("hello, world!") loginfo prints the text to screen, which is also logged inside the node's log file. rate.sleep() Sleep for a certain amount of time to maintain the loop rate defined in rate = rospy.Rate(2). ### Running the node • Run roscore. This should be running as long as you are running ROS. Don't kill it! roscore ... logging to /home/m2/.ros/log/4749b7b8-e3b1-11ea-aa8c-1c1b0d98dfee/roslaunch-tux-9534.log Checking log directory for disk usage. This may take awhile. Press Ctrl-C to interrupt Done checking log file disk usage. Usage is <1GB. started roslaunch server http://m2-null:46785/ ros_comm version 1.12.14 SUMMARY PARAMETERS * /rosdistro: kinetic * /rosversion: 1.12.14 NODES auto-starting new master process[master]: started with pid [9544] ROS_MASTER_URI=http://m2-null:11311/ setting /run_id to 4749b7b8-e3b1-11ea-aa8c-1c1b0d98dfee process[rosout-1]: started with pid [9557] started core service [/rosout] Note Recall that rospy.loginfo() prints text to screen and also writes to a log file. The directory of the log file is stated in the roscore output, under ... logging to /home/m2/.ros/log/4749b7b8-e3b1-11ea-aa8c-1c1b0d98dfee/roslaunch-tux-9534.log. • To run a node in the command line, use rosrun [package] [node]. Try to run the basic node on a separate terminal : rosrun lab5 node_basic.py You should see errors about permissions like the following: $ rosrun lab5 node_basic.py
[rosrun] Couldn't find executable named node_basic.py below /home/m2/catkin_ws/src/m2cs_ros_tutorial/lab5
[rosrun] Found the following, but they're either not files,
[rosrun] or not executable:
[rosrun]   /home/m2/catkin_ws/src/m2cs_ros_tutorial/lab5/src/node_basic.py


Bug

• Oops! Seems that node_basic.py is not an executable. Let's fix that by adding the executable permission:
• Change directory to the package: $roscd lab5/src • Add the executable permission: $ chmod +x node_basic.py
• Now that the execution permission has been added, we can run the node again, this time without errors:
rosrun lab5 node_basic.py [INFO] [1562942112.307432]: hello, world! [INFO] [1562942112.807662]: hello, world! [INFO] [1562942113.307636]: hello, world! ... (omitted)
• You should see that the text of loginfo("hello, world!") is printed at a rate of 2 messages per second (also note that the timestamps are 0.5s apart). This rate is from the rospy.Rate(2) object.

• Verify the node is running by listing out currently running nodes with rosnode list:

## Checklist and Assignment

Completion

Congratulations! You have successfully run a publisher and subscriber and make two nodes communicate with each other!

Now, you should have enough knowledge to complete the first two tasks in Assignment 1 (m2_ps4 manual control).

• Creating a node from a regular python script
• Publishing to a topic (declare publisher object, publish() function)
• Subscribing to a topic (declare subscriber, self-defined callback function)
• Command line tools: rosrun, rosnode, rostopic