What we are going to learn:
- How to set up the package architecture to have custom Python modules inside the ROS2 package
- How to configure
setup.py
so that the modules can be imported - How to import modules and use them in a Python node script
If you want to learn ROS 2 Python in a practical, hands-on way, check out the course ROS 2 Basics in 5 Days: https://app.theconstruct.ai/courses/132
In this course, you’ll cover the foundational concepts needed to start working with ROS 2, as well as more advanced topics, all while engaging in hands-on practice.
In order to follow this tutorial, we need to have ROS2 installed in our system, and ideally a ros2_ws (ROS2 Workspace). To make your life easier, we have already prepared a rosject for that: https://app.theconstructsim.com/l/5e6f9418/
Just by copying the rosject (clicking the link above), you will have a setup already prepared for you.
After the rosject has been successfully copied to your own area, you should see a Run button. Just click that button to launch the rosject ( see this example).
After pressing the Run button, you should have the rosject loaded. Now, let’s head to the next section to get some real practice.
In order to interact with ROS2, we need a terminal.
Let’s open a terminal by clicking the Open a new terminal button.
Setup the package architecture
Create a standard ROS2 package using ament_python
With dependencies on rclpy
:
cd ~/ros2_ws/src/
ros2 pkg create py_pkg –build-type ament_python –dependencies rclpy
Run the “tree
.” command to see the folder structure. If you don’t have the command installed, you can install it using:
sudo apt-get update
sudo apt-get install -y tree
You should be able to see this structure which you are already familiar with:
`– py_pkg
|– package.xml
|– py_pkg
| `– __init__.py
|– resource
| `– py_pkg
|– setup.cfg
|– setup.py
`– test
|– test_copyright.py
|– test_flake8.py
`– test_pep257.py
Add custom Python module(s) that you want to import
You will need to add module files under the directory with the same name as the package (in this case py_pkg
):
cd py_pkg/py_pkg
touch module_to_import.py
For this tutorial for simplicity, we can just add this minimal function to the module_to_import.py
file that just prints “hello world
”:
def function_to_import():
print(“hello world”)
Create a ‘scripts
’ directory for your Python node(s)
Specify the directory as a Python package by creating an empty__init__.py
file (essential for the folder to be recognized by Python as a package), then add a Python node:
cd ..
mkdir scripts
touch scripts/__init__.py
touch scripts/py_node.py
py_node.py
) that imports and uses the function from the module we just created:import rclpyfrom rclpy.node import Node# Import a specific function/class from your modulefrom py_pkg.module_to_import import function_to_importclass MyPythonNode(Node):def __init__(self):super().__init__(“my_node_name”)# Run the imported functionfunction_to_import()def main(args=None):# Initiate ROS communicationsrclpy.init(args=args)# Instantiate the nodenode = MyPythonNode()# Make the node spinrclpy.spin(node)# Destroy the node objectnode.destroy_node()# Shutdown ROS communicationsrclpy.shutdown()if __name__ == ‘__main__’:main()
Final package architecture
Run the “tree.
” command to see the folder structure inside py_pkg
:
|– package.xml
|– py_pkg
| |– __init__.py
| `– module_to_import.py
|– resource
| `– py_pkg
|– scripts
| |– __init__.py
| `– py_node.py
|– setup.cfg
|– setup.py
`– test
|– test_copyright.py
|– test_flake8.py
`– test_pep257.py
Configure the package and test
Modify setup.py
- Add ‘
scripts
‘ to the list of Python packages:
packages=[package_name, ‘scripts’],
This is so that later when you build with colcon
, ROS2 knows to put the Python packages here ~/<workspace_name>/install/<package_name>/lib/<python_version>/site-packages/<package_name>
(in our case <workspace_name>
is ros2_ws
, <python_version>
ispython3.10
, and <package_name>
is py_pkg
).
2. State the entry point:
entry_points={
‘console_scripts’: [
‘py_node_executable = scripts.py_node:main’
],
So your setup.py should look like this:
from setuptools import setup
package_name = ‘py_pkg’
setup(
name=package_name,
version=’0.0.0′,
packages=[package_name, ‘scripts’],
data_files=[
(‘share/ament_index/resource_index/packages’,
[‘resource/’ + package_name]),
(‘share/’ + package_name, [‘package.xml’]),
],
install_requires=[‘setuptools’],
zip_safe=True,
maintainer=’user’,
maintainer_email=’user@todo.todo’,
description=’TODO: Package description’,
license=’TODO: License declaration’,
tests_require=[‘pytest’],
entry_points={
‘console_scripts’: [
‘py_node_executable = scripts.py_node:main’
],
},
)
Compile the Package
cd ~/ros2_ws/
colcon build –packages-select py_pkg
There is a good chance that you will get a SetuptoolsDeprecationWarning:
Starting >>> py_pkg
— stderr: py_pkg
/usr/lib/python3/dist-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
warnings.warn(
—
Finished <<< py_pkg [1.88s]Summary: 1 package finished [2.21s]
1 package had stderr output: py_pkg
If there is no warning then that’s great, but don’t worry if you get it as it is just a warning (not an error) and you will still be able to build successfully.
As of the time of writing this tutorial, the developers hope to have it fixed for Jazzy in May 2024, but for now, there are workarounds to remove the warning. The original workaround was to downgrade the version of setuptools
that is currently installed by doing pip install setuptools==58.2.0
in the terminal. However, that is not recommended. Instead you should use the PYTHONWARNINGS environment variable to suppress that particular warning by adding this to the ~/.bashrc
file:
PYTHONWARNINGS=”ignore:setup.py install is deprecated::setuptools.command.install”; export PYTHONWARNINGS
You could do this by entering this into the terminal:
echo “PYTHONWARNINGS=\”ignore:setup.py install is deprecated::setuptools.command.install\”; export PYTHONWARNINGS” >> ~/.bashrc
Don’t forget to source the .bashrc in the terminal before compiling the package to register the changes:
source ~/.bashrc # . ~/.bashrc
You should now be able to compile the package without the warning.
cd ~/ros2_ws/
colcon build –packages-select py_pkg
Run the node
In the terminal, source the ROS2 environment and start the Python node:
source ~/ros2_ws/install/setup.bash
ros2 run py_pkg py_node_executable
If you get the following output, that means it was successful!
hello world
Congratulations. You now know how to import custom Python3 modules in a ROS 2 package.
To learn more about ROS 2, have a look at the course below:
- ROS 2 Basics in 5 Days: https://app.theconstruct.ai/courses/132
We hope this post was really helpful to you.
This tutorial is created by Robotics Ambassador Ernest.
0 Comments