在ROS2中导入包内的模块

6
我创建了一个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”之类的工具来为您安装依赖项吗? - Thomas Moulard
1
我所说的外部依赖是指我在另一个包中开发的模块,而不是由其他人开发的模块。这在我的问题中有解释。 - Hector Esteban
3个回答

11

首先,根据模块搜索路径文档,在执行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

有两种方法可以解决这个问题。

  1. import SimpleOneTrailerSystem之前修改sys.path

import sys
sys.path.append("/path/to/install/planner_pkg/lib/python3.6/site-packages/planner_pkg")

import SimpleOneTrailerSystem

这种方法将路径添加到planner_pkg 安装目录中,以便在后续的导入中无需指定它,同时保留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环境变量。


    (Note: This is the translated content with polished language and retained HTML tags, as requested. No further explanation given.)

    0

    我曾经遇到过同样的问题,通过修改setup.py文件解决了它。

    在"data_files"列表中添加:

    ('lib/' + package_name, [package_name+'/SimpleOneTrailerSystem.py']),

    即可。

    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']),
            ('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',
            ],
        },
    )
    

    -1
    对于包含cpp和python代码的CMAKE软件包,您可以在CMakeLists.txt中添加以下行。这将把您的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})
    

    如果您正在使用Dashing或Eloquent,则为"python3.6",对于Foxy或更新版本,则为"python3.8"。

    我认为这并不是很有帮助。OP正在编写一个仅限于Python的软件包。 - Matt

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接