在 ROS2 的包中导入模块
Posted
技术标签:
【中文标题】在 ROS2 的包中导入模块【英文标题】:Import modules in package in ROS2 【发布时间】:2019-08-09 08:59:54 【问题描述】:我为 ROS2 创建了一个包,并添加了一个我下载的 Python 存储库。我遇到的问题是,在原始存储库中,直接导入了来自自己存储库的模块,而在我的存储库中,我必须导入它们,在模块之前添加 ROS2 包名称,即使我从同一个存储库导入模块,例如:
import planner_pkg.SimpleOneTrailerSystem as SimpleOneTrailerSystem
虽然我愿意:
import SimpleOneTrailerSystem
我的ROS2项目结构是这样的:
ros2_ws
src
planner
planner_pkg
__init__.py
SimpleOneTrailerSystem.py
planner_node.py
...
package.xml
setup.py
package.xml
<?xml version="1.0"?>
<package format="2">
<name>planner_pkg</name>
<version>0.0.1</version>
<description>This package contains algorithm for park planner</description>
<maintainer email=""></maintainer>
<license>Apache License 2.0</license>
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<!-- These test dependencies are optional
Their purpose is to make sure that the code passes the linters -->
<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>
setup.py:
from setuptools import setup
package_name = 'planner_pkg'
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']),
],
install_requires=['setuptools'],
zip_safe=True,
author='',
author_email='',
maintainer='',
maintainer_email='',
keywords=['ROS'],
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python',
'Topic :: Software Development',
],
description='Package containing examples of how to use the rclpy API.',
license='Apache License, Version 2.0',
tests_require=['pytest'],
entry_points=
'console_scripts': [
'planner_node = planner_pkg.planner_node:main',
],
,
)
【问题讨论】:
通常不建议在包中放置外部依赖项。你能用pip
之类的工具为你安装依赖吗?
我所说的外部依赖是指我在另一个包中开发的模块,而不是别人开发的模块。我的问题中对此进行了解释
【参考方案1】:
首先,根据Module Search Path 文档,当您执行import something
时,Python 在以下位置查找something
:
sys.path
,这是一个 list
,包含:
输入脚本的目录
PYTHONPATH
,这是一个包含目录列表的环境变量
依赖于安装的默认值
其次,当您构建您的 ROS2 Python 包时(通过调用 colcon build
调用 ament_python
构建类型),您的 Python 代码将被复制到一个 install 文件夹,其树形结构类似于这个:
install
...
├── planner_pkg
│ ├── bin
│ │ └── planner_node
│ ├── lib
│ │ └── python3.6
│ │ └── site-packages
│ │ ├── planner_pkg
│ │ │ ├── __init__.py
│ │ │ ├── planner_node.py
│ │ │ └── SimpleOneTrailerSystem.py
...
现在,当您执行import SimpleOneTrailerSystem
时,Python 将首先从内置模块中搜索它,它肯定不会在那里找到。列表中的下一个来自sys.path
。您可以在 planner_node.py 的顶部添加 print(sys.path)
以查看类似于此列表的内容:
['/path/to/install/planner_pkg/bin',
'/path/to/install/planner_pkg/lib/python3.6/site-packages',
'/opt/ros/eloquent/lib/python3.6/site-packages',
'/usr/lib/python36.zip',
'/usr/lib/python3.6',
...other Python3.6 installation-dependent dirs...
]
sys.path
列表中的第一个是输入脚本的 bin 文件夹。那里只有可执行文件,没有 SimpleOneTrailerSystem.py 文件/模块,所以导入会失败。
列表中的下一个将是 planner_pkg/lib/pythonX.X/site-packages,从上面的树结构中可以看到,有一个 SimpleOneTrailerSystem.py 模块但它位于 planner_pkg 文件夹下。所以像这样直接导入
import SimpleOneTrailerSystem
不会工作。您需要使用包文件夹对其进行限定,如下所示:
import planner_pkg.SimpleOneTrailerSystem
有两种方法可以解决这个问题。
在import
之前修改sys.path
-ing SimpleOneTrailerSystem
import sys
sys.path.append("/path/to/install/planner_pkg/lib/python3.6/site-packages/planner_pkg")
import SimpleOneTrailerSystem
此方法将planner_pkg
install 目录的路径添加到sys.path
列表中,这样您就无需在后续导入中指定它。
在运行 ROS2 节点之前修改 PYTHONPATH
$ colcon build
$ source install/setup.bash
$ export PYTHONPATH=$PYTHONPATH:/path/to/install/planner_pkg/lib/python3.6/site-packages/planner_pkg
$ planner_node
此方法与第一种方法几乎相同,但不涉及代码更改(也不涉及重建),因为您只需要修改PYTHONPATH
环境变量。
【讨论】:
【参考方案2】:对于带有 cpp 和 python 代码的 CMAKE 包,您可以将以下行添加到您的 CMakeLists.txt。 这会将您的 python_pkg 文件夹复制到您的安装环境到“lib/pythonversion/site-packages”,它默认包含在您的 python 路径中。
# for python code
find_package(ament_cmake_python REQUIRED)
find_package(rclpy REQUIRED)
install(DIRECTORY
../path_to_python_pkg
DESTINATION lib/python3.8/site-packages
)
install(PROGRAMS
$PROJECT_NAME/python_node.py
DESTINATION lib/$PROJECT_NAME
)
ament_python_install_package($PROJECT_NAME)
如果您正在使用例如Dashing 或 Eloquent 为“python3.6”,Foxy 或更新版本为“python3.8”
【讨论】:
以上是关于在 ROS2 的包中导入模块的主要内容,如果未能解决你的问题,请参考以下文章