ROS2 with Python and YAML: A Step-by-Step Guide from Creating a Workspace to Running Multiple Nodes
If you’re diving into the world of robotics with ROS2 (Robot Operating System 2), setting up a solid foundation is crucial. A well-organized workspace and properly structured nodes are the backbone of any successful ROS project. Whether you’re a beginner or a seasoned developer, this guide will walk you through creating and managing a ROS2 workspace, setting up packages, implementing nodes, and leveraging launch files effectively.
Outline:
- Setting Up Your Package in a ROS Workspace
- Implementing Nodes in Python
- Building Your Package
- Running ROS Nodes
Setting Up Your Package in a ROS Workspace
The very first step is to setup a ROS workspace if you don’t already have one. The ROS workspace is a folder where you implement and build your ROS packages. ROS packages includes implementations of nodes and/or resources and scripts.
Creating a Workspace Folder
- Begin by creating a workspace folder, for example,
ros_workspace
, under your root directory. - Add the following line to your shell setup script (e.g.,
.bashrc
,.zshrc
) to define the workspace:
export ROS_WORKSPACE=~/ros_workspace
Creating a Package
- Navigate to your ROS workspace or any sub-folder. The folder depth doesn’t matter.
- Use the following command to create a package:
ros2 pkg create my-pkg
This command creates a folder named my-pkg
, containing the minimum files needed for your package. To specify a build type, use the --build-type
option. Valid options are: cmake
, ament_cmake
(default), and ament_python
. For example, to create a Python package:
ros2 pkg create --build-type ament_python my-pkg
In the remainder of this article, we’ll go with the default (ament_cmake
). We want to create packages that support both python
and C++ nodes.
Implementing Nodes in Python
Writing Python Nodes
- Use the rclpy (ROS Client Library for the Python language) to implement your node scripts. See examples below.
- Ensure your scripts are executable (
chmod +x
) to avoid the ”No executable found” error. - Place node scripts in the
scripts
sub-folder of your package. - Ensure the
package.xml
file includes dependencies likerclpy
and any additional libraries, such as ones provided topics or service types used in your nodes. For example:
depend>rclpy</depend>
<depend>std_msgs</depend> <
- Add installation details to
CMakeLists.txt
for each script:
install(PROGRAMS scripts/my-node-script.py
DESTINATION lib/${PROJECT_NAME})
Example Publisher Node
#!/usr/bin/python3
import rclpy
from rclpy.node import Node
from std_msgs.msg import UInt16
class CounterNode(Node):
def __init__(self):
rclpy.init()super().__init__('counter')
self.publisher = self.create_publisher(UInt16, 'count', 10)
self.timer = self.create_timer(1, self.publishCount)
self.count = 0
self)
rclpy.spin(self.destroy_node()
rclpy.shutdown()
def publishCount(self):
self.count += 1
= UInt16()
msg = self.count
msg.data print(f'Publishing {msg}')
self.publisher.publish(msg)
if __name__ == "__main__":
CounterNode()
Example Subscriber Node
#!/usr/bin/python3
import rclpy
from rclpy.node import Node
from std_msgs.msg import UInt16
class DoubleNode(Node):
def __init__(self):
rclpy.init()super().__init__('double')
self.subscriber = self.create_subscription(UInt16, 'count', self.displayDouble, 10)
self)
rclpy.spin(self.destroy_node()
rclpy.shutdown()
def displayDouble(self, countMsg):
= countMsg.data
count = count * 2
double print(f'Received {count} which double is {double}')
if __name__ == "__main__":
DoubleNode()
Node Parameters Example in Python
A given node can have parameters passed during the execution. The node script has to first declare the parameters before reading them. Here are some examples:
- Declare parameters:
'my_array', rclpy.Parameter.Type.DOUBLE_ARRAY)
node.declare_parameter(
rclpy.Param'my_int', 42) # 42 is the default value node.declare_parameter(
- Read provided parameter values:
'my_int').value
node.get_parameter('my_int', 'my_array']) node.get_parameters([
You can learn more about node parameters in:
Building Your Package
Build Before Running
Whenever you change any file, rebuild the package using this command:
colcon build
The above command checks all packages inside your ROS workspaces and rebuilds all the dirty ones. This sometimes can take too much time. To build specific packages, use:
colcon build --paths my-pkg some/folder/*
Build Once, Modify and Re-Run Several Times
Building with option --symlink-install
allows to modify and re-run nodes implemented in python, without rebuilding. This is true for all python scripts that were referenced in the CMakeList.txt
upon the build.
Update the Environment
We recommand sourcing the setup.bash
file in the install
folder of the ROS workspace. It updates the environment with all built packages, enabling completion when running your nodes. In the workspace folder evaluate the following command:
source ./install/setup.bash
Running ROS Nodes
Once you have built a package, you can run a single node using the following command:
ros2 run my_package my_node
Running a Node with Parameters
If your node has parameters, you can set them using the following command:
ros2 run my_package my_node --ros-args -p my_int:=2 -p my_array:=[1.0,2.0]
Use Launch Files to Run Multiple Nodes at Once
Launch files allow grouping multiple nodes, as well as other executables, and run them all using a single command. Launch files can be written in multiple languages You can find in the ROS2 HowTo Guide the syntax, and various options for supported languages. In the following we provide a the bare minimum you need to get started with launch files in YAML.
- Launch files are stored in the
launch
folder of your package. - Add the following to
CMakeLists.txt
to include launch files during installation:
install(DIRECTORY launch
DESTINATION share/${PROJECT_NAME}/
)
Example Launch File
launch:
# Start a node with parameters
- node:
pkg: "demo"
exec: "counter"
name: "my_counter"
param:
-
name: 'delta'
value: 100
# Start a node with commandline arguments
- node:
pkg: "rviz2"
exec: "rviz2"
name: "rviz2"
args: "-d $(dirname)/../config/minimal.rviz"
# Run another launch file
- include:
file: "$(find-pkg-share other-package)/launch/other-launch-file.yaml"
# Run a random executatble
# Here we start a terminal where we run a command line
# that starts an interactive node. This is a workaround to
# enable sending keyboard events to an interactive node.
- executable:
cmd: gnome-terminal --tab -e 'ros2 run teleop_twist_keyboard teleop_twist_keyboard'
Adding Configuration Files to a CMake-based Package
In the above example, the launch file relies on a configuration file for rviz2
node. In such cases where extra files are required, you need to reference them in your project.
- Put your configuration files into
config
sub-folder - Tell CMake to copy
config
sub-folder to theinstall
folder of the workspace where the
execution takes place. To do so, add toCMakeLists.txt
the following:
install(DIRECTORY config
DESTINATION share/${PROJECT_NAME}/
)
Substitutions
A launch file might need to retrieve files from some folders, or use some local or environment variable. This is where susbstitutions come to play. Substitutions allow to make launch files that adapt to the setup of the system hosting your ROS packae. Two very useful susbtitutions are used in our example:
$(find-pkg-share)
: Substituted by the share directory path of the given package.$(dirname)
: Substituted by the current launch file directory name. Be careful to use$(dirname)
before any$(find-pkg-share)
. Because,$(dirname)
is affected by previous$(find-pkg-share)
.
Running Launch Files
Use the following command to run a launch file:
ros2 launch my_package my_launch_file
If your launch file accepts parameters, you can append them to the command line:
ros2 launch my_package my_launch_file param_name:=param_value
Conclusion
By following this guide, you’ve set up a ROS2 workspace, created and managed packages, implemented Python nodes, and leveraged launch files. Whether you’re building simple robotics projects or complex systems, you’ll need to to go through these foundational steps.
However, this article barely scratches the surface. Each ROS tool has a lot of options to address various cases. There are also alternative supported languages and tools that we didn’t cover. We provide some links, throughtout the document. You’ll find below some more, that we find useful. They’ll help you in your journey creating amazing robotic applications.
- ROS documentation (Official). Covers all the distributions for both ROS2 and ROS1.
- ROS2 Design(Official). Documents the ROS 2 design.
- Software and Architecture for Mobile-Robotics. Tutorials for the Mobile Robotics course at IMT Nord Europe.
Leave a Reply