ROS - Basic Python Code Setup

Subscribe Send me a message home page


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

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:

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

3.2 Configure CMakeLists.txt

There are three items to be updated in the CMakeLists.txt file:

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:

1
2
3
4
5
6
7
#!/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:

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/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:

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 -----

Send me a message Subscribe to blog updates

Want some fun stuff?

/static/shopping_demo.png


Comments