Building ROS 2 Packages with Python: Organizing Your Robotic Code
In ROS 2, a package is the fundamental unit for organizing software. It contains source code, build scripts, configuration files, and other resources related to a specific piece of functionality (e.g., a robot driver, a navigation module). For Python-based ROS 2 development, ament_python provides the necessary tools and conventions for creating, building, and installing packages.
Understanding ROS 2 Packages
A ROS 2 package typically consists of:
package.xml: Defines metadata about the package, including its name, version, description, maintainers, license, build dependencies, and runtime dependencies.setup.py: The standard Python build script forament_pythonpackages. It specifies how Python modules and scripts within the package should be installed.resourcefolder: Contains a marker file (e.g.,share/<package_name>/package.xml) that helps ROS 2 find the package.srcfolder: Contains your Python source code.launchfolder: (Optional) Contains Python or XML launch files to start multiple ROS 2 nodes.configfolder: (Optional) Contains YAML configuration files for parameters.
Creating a New Python Package
You can create a new ROS 2 Python package using the ros2 pkg create command:
ros2 pkg create --build-type ament_python my_python_package --dependencies rclpy std_msgs
Explanation:
--build-type ament_python: Specifies that this is a Python package built withament.my_python_package: The name of your new package.--dependencies rclpy std_msgs: Automatically addsrclpy(the Python client library for ROS 2) andstd_msgs(standard message types) as dependencies topackage.xmlandsetup.py.
This command will create the basic directory structure and populate package.xml and setup.py.
The package.xml File
The package.xml is crucial for ROS 2 package management. Key tags include:
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>my_python_package</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="user@example.com">User</maintainer>
<license>TODO: License declaration</license>
<depend>rclpy</depend>
<depend>std_msgs</depend>
<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
The setup.py File
The setup.py script defines how your Python code is structured and what executables should be exposed as ROS 2 nodes.
from setuptools import setup
import os
from glob import glob
package_name = 'my_python_package'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
(os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')), # Example for launch files
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='User',
maintainer_email='user@example.com',
description='TODO: Package description',
license='TODO: License declaration',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'talker = my_python_package.publisher_member_function:main', # Example node executable
'listener = my_python_package.subscriber_member_function:main',
],
},
)
Explanation of entry_points: This section maps a console script name (e.g., talker) to a Python function within your package (e.g., my_python_package.publisher_member_function:main). This allows you to run your ROS 2 nodes directly using ros2 run my_python_package talker.
Building and Installing Your Package
After creating your package, you need to build and install it using colcon:
# From the root of your ROS 2 workspace (e.g., ~/ros2_ws)
colcon build --packages-select my_python_package
Then, source your workspace to make the new package available:
source install/setup.bash # or setup.zsh, setup.ps1
Now you can run your nodes: ros2 run my_python_package talker.
Co-Learning Elements
💡 Theory: The ament Build System
ament (Ament Build System) is the meta-build system used in ROS 2. It orchestrates the building of various package types (including ament_python, ament_cmake) and ensures dependencies are correctly handled across different programming languages and build tools. It's an evolution of ROS 1's catkin build system, designed for greater flexibility and modularity.
🎓 Key Insight: Separation of Concerns
ROS 2 package structure inherently promotes separation of concerns. By encapsulating specific functionalities within packages, developers can create modular, reusable components. This modularity simplifies development, testing, and maintenance, especially in large-scale robotics projects with many interacting parts.
💬 Practice Exercise: Ask your AI
Prompt: "Generate a complete package.xml and setup.py for a new ROS 2 Python package called humanoid_description_publisher. This package should depend on rclpy and sensor_msgs. It should also expose a console script named joint_state_publisher that runs a Python function main from a module joint_state_publisher_node within the package."
Instructions: Use your preferred AI assistant to provide the full package.xml and setup.py file contents. Ensure all necessary metadata and entry points are correctly defined.