1. Introduction
In this post, we will follow the official documentation and this post to write some simple python ROS codes. More specifically, we will see
- How to create a new ROS package
- How to build a package with python codes
- How to run the ROS python codes
2. Create new package
Following the instructions in the book A Gentel Introduction to ROS, we can use catkin_create_pkg <package-name>
command to create a package. For example, if we execute catkin_create_pkg agitr
command in my_ros_workspace/src
folder, we will have the following folder strcture:
myros_workspace/src ├── agitr │ ├── CMakeLists.txt │ ├── package.xml
Later we will see how to update these two files so that we can compile the python code.
Note: The package.xml file is called a manifest in ROS and the CMakeLists.txt file is used by the catkin program.
Here is the workspace after we build our python packages. We will talk about these packages in details in the following sections.
my_ros_workspace ├── devel │ ├── cmake.lock │ ├── env.sh │ ├── lib │ │ └── pkgconfig │ │ └── agitr.pc │ ├── local_setup.bash │ ├── local_setup.sh │ ├── local_setup.zsh │ ├── setup.bash │ ├── setup.sh │ ├── _setup_util.py │ ├── setup.zsh │ └── share │ └── agitr │ └── cmake │ ├── agitrConfig.cmake │ └── agitrConfig-version.cmake └── src ├── agitr │ ├── CMakeLists.txt │ ├── hello_world.py │ ├── package.xml │ ├── publisher_example.py │ └── subscriber_example.py └── CMakeLists.txt -> /opt/ros/noetic/share/catkin/cmake/toplevel.cmake
3. Package set up
3.1 Configure package.xml
There are two types of dependency:
- build dependency
- runtime dependnecy
In order to specify the build and runtime dependency of the package, we can add build_depend
tag and exec_depend
tag respectively to the package.xml
file. For example, as we will write some python ROS code, our package will depend on the rospy
package. To introduce this dependency, we need to
- Find the <buildtool_depend>catkin</buildtool_depend> in the package.xml file.
- Add the following two lines below buildtool_depend
- <build_depend>rospy</build_depend>
- <exec_depend>rospy</exec_depend>
3.2 Configure CMakeLists.txt
There are three items to be updated in the CMakeLists.txt
file:
- find_package
- catkin_package
- include_directores
Here are the updated configuration
find_package(catkin REQUIRED COMPONENTS rospy) catkin_package( INCLUDE_DIRS CATKIN_DEPENDS rospy ) include_directories( ${catkin_INCLUDE_DIRS} )
4. Sample Code
4.1 Hello World
Here is our the Hello worfl script:
#!/usr/bin/env python3
import rospy
if __name__ == '__main__':
rospy.init_node("hell_world", anonymous=True)
rospy.loginfo("Hello World!!!")
This script does two things:
- Initilaize a ros node (A running instance/programme is called a node in ROS) and
- Log a Hello World message.
4.2 Publisher
Here is a simple implementatoin of a publisher. As we can see in the code below, the message type is string and the topic is chatter
. This topic will be used in the subscriber code later when the listener wants to access messages published by the talker.
#!/usr/bin/env python3
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
4.2 Subscriber
As mentioned earlier, the listener subscribes to the topic chatter
defined in the publisher.
#!/usr/bin/env python3
import rospy
from std_msgs.msg import String
def callback(data):
rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
def listener():
# In ROS, nodes are uniquely named. If two nodes with the same
# name are launched, the previous one is kicked off. The
# anonymous=True flag means that rospy will choose a unique
# name for our 'listener' node so that multiple listeners can
# run simultaneously.
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("chatter", String, callback)
# spin() simply keeps python from exiting until this node is stopped
rospy.spin()
if __name__ == '__main__':
listener()
5. Build the code
We can build all packages in a workspace at once:
- Go to the root folder of the workspace (In our example, the root folder is my_ros_workspace)
- Execute command
catkin_make
- Execute command
source devel/setup.bash
Note: As we can see here, topics are accessed by different scripts, therefore, using a hard-coded value is not a good solution.
6. Run python scripts
To run the above scripts, we can go to the root folder of the workspace and execute the following commands:
Note: we need to start the master by running roscore
before before starting a ROS node.
rosrun agitr hello_world.py rosrun agitr publisher_example.py rosrun agitr subscriber_example.py
----- END -----
©2019 - 2022 all rights reserved