[英]Import modules in package in ROS2
I have created a package for ROS2 and I have added a Python repository I downloaded.我为 ROS2 创建了一个 package 并添加了一个我下载的 Python 存储库。 The problem I am having is that in the original repository the modules from the own repo were imported directly while in mine I have to import them adding the ROS2 package name before the module, even though I am importing a module from the same repo, like:我遇到的问题是,在原始存储库中,自己的存储库中的模块是直接导入的,而在我的存储库中,我必须导入它们,在模块前添加 ROS2 package 名称,即使我从同一个存储库导入模块,如:
import planner_pkg.SimpleOneTrailerSystem as SimpleOneTrailerSystem
while I would like:而我想:
import SimpleOneTrailerSystem
My ROS2 project structure is like:我的 ROS2 项目结构如下:
ros2_ws
src
planner
planner_pkg
__init__.py
SimpleOneTrailerSystem.py
planner_node.py
...
package.xml
setup.py
package.xml 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:安装程序.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',
],
},
)
First, according to the Module Search Path docs, when you do import something
, Python looks for that something
in the following places:首先,根据Module Search Path文档,当您import something
,Python something
在以下位置查找该内容:
sys.path
, which is a list
containing: sys.path
,这是一个包含以下内容的list
:
PYTHONPATH
, which is an environment variable containing a list of directories PYTHONPATH
,这是一个包含目录列表的环境变量Second, when you build your ROS2 Python package (by calling colcon build
invoking the ament_python
build type), your Python codes will be copied over to an install folder with a tree structure like this:其次,当您构建 ROS2 Python 包时(通过调用colcon build
调用ament_python
构建类型),您的 Python 代码将被复制到具有如下树结构的安装文件夹:
install
...
├── planner_pkg
│ ├── bin
│ │ └── planner_node
│ ├── lib
│ │ └── python3.6
│ │ └── site-packages
│ │ ├── planner_pkg
│ │ │ ├── __init__.py
│ │ │ ├── planner_node.py
│ │ │ └── SimpleOneTrailerSystem.py
...
Now, when you do import SimpleOneTrailerSystem
, Python will first search for it from the built-in modules, which for sure it won't find there.现在,当您import SimpleOneTrailerSystem
,Python 将首先从内置模块中搜索它,它肯定不会在那里找到。 Next on the list is from sys.path
.列表中的下一个来自sys.path
。 You can add a print(sys.path)
at the top of planner_node.py to see something like this list:您可以在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...
]
First on the sys.path
list is the bin folder of the input script. sys.path
列表中的第一个是输入脚本的bin文件夹。 There are only executables there, no SimpleOneTrailerSystem.py file/module, so that import will fail.那里只有可执行文件,没有SimpleOneTrailerSystem.py文件/模块,因此导入将失败。
The next on the list would be the planner_pkg/lib/pythonX.X/site-packages , and as you can see from the tree structure above, there is a SimpleOneTrailerSystem.py module BUT it is under a planner_pkg folder .列表中的下一个是planner_pkg/lib/pythonX.X/site-packages ,从上面的树结构中可以看出,有一个SimpleOneTrailerSystem.py模块,但它位于planner_pkg文件夹下。 So a direct import like this所以像这样直接导入
import SimpleOneTrailerSystem
will not work.不管用。 You need to qualify it with the package folder like this:您需要使用包文件夹来限定它,如下所示:
import planner_pkg.SimpleOneTrailerSystem
There are 2 ways to get around this.有两种方法可以解决这个问题。
Modify sys.path
before import
-ing 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
This approach adds the path to the planner_pkg
install directory to the sys.path
list so that you don't need to specify it in subsequent imports.此方法将planner_pkg
安装目录的路径添加到sys.path
列表中,以便您无需在后续导入中指定它。
Modify PYTHONPATH
before running your ROS2 node在运行 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
This approach is almost the same as the first one, but there is no code change involved (and no rebuilding involved), as you only need to modify the PYTHONPATH
environment variable.这种方法与第一种方法几乎相同,但不涉及代码更改(也不涉及重建),因为您只需要修改PYTHONPATH
环境变量。
I had the same problem and fixed it by modifying setup.py.我有同样的问题并通过修改 setup.py 修复它。
Add:添加:
('lib/' + package_name, [package_name+'/SimpleOneTrailerSystem.py']), ('lib/' + package_name, [package_name+'/SimpleOneTrailerSystem.py']),
to "data_files" list.到“data_files”列表。
setup.py:安装程序.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']),
('lib/' + package_name, [package_name+'/SimpleOneTrailerSystem.py']),
],
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',
],
},
)
For CMAKE packages with cpp and python code you can add the following lines to your CMakeLists.txt.对于带有 cpp 的 CMAKE 包和 python 代码,您可以将以下行添加到您的 CMakeLists.txt。 This will copy your python_pkg folder into your install environment to "lib/python{version}/site-packages" which is per default included in your python path.这会将您的 python_pkg 文件夹复制到安装环境中的“lib/python{version}/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})
If you are using eg Dashing or Eloquent it is "python3.6", for Foxy or newer it is "python3.8"如果您使用的是 Dashing 或 Eloquent,则它是“python3.6”,对于 Foxy 或更新版本,它是“python3.8”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.