ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

Using Python3 modules in ROS2 packages

asked 2021-02-04 11:29:48 -0500

NotARobot gravatar image

updated 2021-02-09 05:17:13 -0500

I developed Python3 modules with code independent from ROS. Now I want to use them in a ROS2 package, more specifically I want to import them in a ROS2 node. The node listens to a ROS topic and should use my Python modules to work with the data provided by the topic.

However I couldn't find any information on how to achieve this. At first I tried to plug my modules next to the node, but when I tried to run the node after colcon build it was unable to import the modules, because colcon build runs the script in the install directory. So I modified the data_files in setup.py with

data_files=[ ('share/ament_index/resource_index/packages', ['resource/' + package_name]), ('share/' + package_name, ['package.xml']), (os.path.join('share', package_name, 'dependencies'), glob('dependencies/*')) ],

and put my modules in the dependencies directory. Now I am unable to build the package, due to a colcon error

Starting >>> tst_mapfusion_r2pp

--- stderr: tst_mapfusion_r2pp error: cant't copy 'dependencies/fusion':

doesn't exist or not a regular file

--- Failed <<< tst_mapfusion_r2pp [0.45s, exited with code 1]

Summary: 0 packages finished [0.74s]

1 package failed: tst_mapfusion_r2pp

1 package had stderr output: tst_mapfusion_r2pp

Whereas the dependencies directory contains the sub-directories for my modules, one of them being fusion.

Where do I have to put my own python modules in order to use them inside the ROS2 package? Is it possible without shenanigans like fiddling with $PYTHONPATH?

Edit: The tree is a bit extensive and I'm not allowed to upload files or pictures (new user -.- ). So please be patient with me.

/root/ros2_ws/src/tst_mapfusion_r2pp

-build

---COLCON_IGNORE

---tst_mapfusion_r2pp

----build

-----lib

------tst_mapfusion_r2pp

-------__init__.py

-------map_fusion.py

----colcon_build.rc

----colcon_command_prefix_setup_py.sh

----colcon_command_prefix_setup_py.sh.env

----dependencies

-----fusion -> /root/ros2_ws/src/tst_mapfusion_r2pp/dependencies/fusion

-----importer -> /root/ros2_ws/src/tst_mapfusion_r2pp/dependencies/importer

-----misc -> /root/ros2_ws/src/tst_mapfusion_r2pp/dependencies/misc

-----opencv -> /root/ros2_ws/src/tst_mapfusion_r2pp/dependencies/opencv

----package.xml -> /root/ros2_ws/src/tst_mapfusion_r2pp/package.xml

----resource

-----tst_mapfusion_r2pp -> /root/ros2_ws/src/tst_mapfusion_r2pp/resource/tst_mapfusion_r2pp

----setup.cfg -> /root/ros2_ws/src/tst_mapfusion_r2pp/setup.cfg

----setup.py -> /root/ros2_ws/src/tst_mapfusion_r2pp/setup.py

----tst_mapfusion_r2pp -> /root/ros2_ws/src/tst_mapfusion_r3pp/tst_mapfusion_r2pp

----tst_mapfusion_r2pp.egg-info

-----PKG-INFO

-----SOURCES.txt

-----dependency_links.txt

-----entry_points.txt

-----requires.txt

-----top_level.txt

-----zip-safe

-dependencies

--fusion

---__pycache__

----map_fusion.cpython-38.pyc

---map_fusion.py

--importer

---__init__.py

---__pycache__

----pgmloader.cpython-38.pyc

---pgmloader

--misc

---__pycache__

----mp_misc.cpython-38.py

---mp_misc.py

--opencv

---__pycache__

----ocvfmodule.cpython-38.pyc

---ocvfmodule.py

-install

-log

-package.xml

-resource

-setup.cfg

-setup.py

-test

-tst_mapfusion_r2pp

--__init__.py

--map_fusion.py

-tst_mapfusion_r2pp.egg-info

-venv

edit retag flag offensive close merge delete

Comments

For clarity, could you please run tree ~/location_of_workspace/src/tst_mapfusion_r2pp and update your question with the output? It should print a tree-like structure of all the files and directories.

phillipov gravatar image phillipov  ( 2021-02-05 13:35:46 -0500 )edit

My understanding is that the data_files option is only supposed to be used for extra stuff your code needs, not code itself. I would expect you would be fine just inserting your extra modules alongside the ROS-specific stuff that gets installed by the packages term in setup.py. This doesn't work?

jdlangs gravatar image jdlangs  ( 2021-02-08 09:57:31 -0500 )edit

I suspect, it's for ROS-packages. I've tried to add my dependencies here, but I got: error: package directory 'dependencies' does not exist.

From my limited understanding, when writing a ROS2 node with Python; colcon build will copy the ROS code in the install folder, specified by setup.cfg and, for a lack of a better term, 'register' it for ROS2 to be found as run-able. So isn't it possible to tell colcon to copy my files in the proper directory when building?

NotARobot gravatar image NotARobot  ( 2021-02-08 10:28:39 -0500 )edit
1

colcon build is not doing anything more than invoking setuptools to install everything into the install/ directory, the same way calling python setup.py install would. The stuff listed under the packages keywords are simply the python packages that will be placed under install/, which most likely should include these extra modules you mention.

jdlangs gravatar image jdlangs  ( 2021-02-08 14:16:36 -0500 )edit
1

In case you haven't seen it, you can understand how setup.py and the packageskeyword work here: https://docs.python.org/3/distutils/s... One thing that often trips people up is remembering a python package is only defined when an __init__.py file is present.

jdlangs gravatar image jdlangs  ( 2021-02-08 14:22:53 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
1

answered 2021-02-09 05:17:28 -0500

NotARobot gravatar image

Solved. Thanks to jdlangs and phillipov. With regard to the setup.py documentation I packed my modules in packages parallel to the node like that:

src

-tst_mapfusion_r2pp

--tst_mapfusion_r2pp

---__init__.py

---map_fusion.py

---fusion

----__init__.py

----map_fusion.py

---importer

----__init__.py

----pgmloader.py

etc.

Furthermore, as jdlangs suggested I edited setup.pys packages section: packages[package_name, '{}'.fusion.(package_name), '{}'.importer(package_name)] and so on for all my modules.

Additionally the import statements in my ROS2 node had to be edited from import fusion.map_fusion as fusion to from .fusion import map_fusion as fusion

Unfortunately deeper dependencies like my misc package which is needed by my ocvfmodule require an import a level deeper, like from ..misc import mp_misc.

Thank you very much for answering my question, even if it turns out to be more of a general python question.

edit flag offensive delete link more

Comments

I believe it should also be possible to put your fusion package at the same level as tst_mapfusion_r2pp and have it installed as a separate top-level package. Then your original import statements would work.

jdlangs gravatar image jdlangs  ( 2021-02-09 10:55:25 -0500 )edit

Question Tools

3 followers

Stats

Asked: 2021-02-04 11:29:48 -0500

Seen: 1,467 times

Last updated: Feb 09 '21