You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ROS2节点无法导入configs模块问题求助(含项目结构及排查记录)

ROS2 Humble节点导入configs模块失败问题排查与解决

问题背景

开发ROS2 Humble项目时,遇到节点无法导入configs包内模块的问题,以下是详细信息:

项目结构

test_ws/
├── src/
│   └── test_package/
│       ├── configs/
│       │   ├── __init__.py
│       │   └── global_settings.py
│       ├── test_package/
│       │   ├── __init__.py
│       │   ├── gps_path_planning_node.py
│       │   └── scripts/
│       │       ├── __init__.py
│       │       └── utils.py
│       ├── package.xml
│       ├── setup.cfg
│       └── setup.py

报错信息

执行ros2 launch test_package simulation_launch.py启动节点时出现:

[gps_path_planning_node-5] Traceback (most recent call last):
[gps_path_planning_node-5]   File "/home/hiber/Desktop/test_ws/install/test_package/lib/test_package/gps_path_planning_node", line 33, in <module>
[gps_path_planning_node-5]     sys.exit(load_entry_point('test-package==0.0.0', 'console_scripts', 'gps_path_planning_node')())
...
[gps_path_planning_node-5] ModuleNotFoundError: No module named 'configs'

关键代码片段

gps_path_planning_node.py:

from rclpy.node import Node
import rclpy
from configs import global_settings
from test_package.scripts.utils import *

class GPSPathPlanningNode(Node):
    def __init__(self):
        super().__init__('gps_path_planning_node')
        self.max_speed = EGO_VEHICLE_MAX_SPEED
        self._logger.info('Successfully launched!')

def main(args=None):
    rclpy.init(args=args)
    node = GPSPathPlanningNode()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

setup.py:

import os
from setuptools import setup

PACKAGE_NAME = 'test_package'

def generate_data_files(share_path, data_files_path):
    data_files_temp = []

    for path, _, files in os.walk(data_files_path):
        data_file = (
            os.path.dirname(os.path.dirname(share_path)) + '/' + path, [
                os.path.join(path, file) for file in files if not file.startswith('.')
            ]
        )

        data_files_temp.append(data_file)

    return data_files_temp

data_files = []

data_files.append(('share/ament_index/resource_index/packages', ['resource/' + PACKAGE_NAME]))
data_files.append(('share/' + PACKAGE_NAME, ['package.xml']))

data_files += generate_data_files('share/' + PACKAGE_NAME + '/configs/', 'configs/')
data_files += generate_data_files('share/' + PACKAGE_NAME + '/launch/', 'launch/')
data_files += generate_data_files('share/' + PACKAGE_NAME + '/resource/', 'resource/')

setup(
    name=PACKAGE_NAME, 
    version='0.0.0', 
    packages=[PACKAGE_NAME], 
    data_files=data_files, 
    install_requires=['setuptools'], 
    zip_safe=True, 
    maintainer='hiber', 
    maintainer_email='...', 
    description='TODO: Package description', 
    license='TODO: License declaration', 
    tests_require=['pytest'], 
    entry_points={
        'console_scripts': [
            # 'ackermann_keyboard_teleop_node = test_package.ackermann_keyboard_teleop_node:main', 
            'gps_path_planning_node = test_package.gps_path_planning_node:main', 
            'projection_weight_matrices_node = test_package.projection_weight_matrices_node:main', 
            'surround_view_node = test_package.surround_view_node:main', 
        ], 
    }, 
)

环境信息

  • ROS2版本:Humble
  • Python版本:3.10
  • 操作系统:Ubuntu 22.04

已执行排查步骤

  • 将global_settings.py移至gps_path_planning_node.py同目录,修改导入语句为from test_package.global_settings import *,但scripts目录下的utils.py仍无法找到;
  • 检查setup.py,确认已包含test_package及scripts等子包;
  • 执行colcon clean后运行colcon build --symlink-install,并source工作空间;
  • 本地测试python3 -c 'from test_package.global_settings import *; print("Import successful")'无报错;
  • 确认install/test_package/lib/python3.10/site-packages/test_package/路径应包含configs、scripts等模块;
  • 所有目录均包含__init__.py文件;
  • 尝试多种导入方式(相对导入、绝对导入、动态导入)。

问题原因与解决方案

1. 核心原因

当前setup.py中,packages=[PACKAGE_NAME]只声明了根级的test_package包,但**configs和scripts是独立于内部test_package目录的同级目录,未被声明为Python子包**;同时你把configs作为数据文件安装到了share目录,而非Python包路径下,导致ROS2节点运行时无法在Python搜索路径中找到这些模块。另外,代码中的from configs import global_settings是绝对导入,但configs并未注册为Python包,不在Python搜索路径内。

2. 具体修复步骤

步骤1:调整项目结构(推荐)

将configs和scripts目录移动到内部的test_package目录下,使其成为test_package的子包:

test_ws/
├── src/
│   └── test_package/
│       ├── test_package/
│       │   ├── __init__.py
│       │   ├── gps_path_planning_node.py
│       │   ├── configs/
│       │   │   ├── __init__.py
│       │   │   └── global_settings.py
│       │   └── scripts/
│       │       ├── __init__.py
│       │       └── utils.py
│       ├── package.xml
│       ├── setup.cfg
│       └── setup.py

步骤2:修改setup.py,正确声明所有子包

将packages参数改为自动发现所有子包,或显式列出:

# 替换原来的packages=[PACKAGE_NAME]
packages=setuptools.find_packages(),
# 或者显式列出:
# packages=['test_package', 'test_package.configs', 'test_package.scripts'],

同时移除data_files中关于configs的部分,因为它现在是Python包的一部分,无需作为数据文件安装:

# 删除这一行
# data_files += generate_data_files('share/' + PACKAGE_NAME + '/configs/', 'configs/')

步骤3:修改导入语句

调整gps_path_planning_node.py中的导入路径为绝对子包导入:

# 替换原来的from configs import global_settings
from test_package.configs import global_settings
# scripts的导入可保持不变,或改为相对导入:from .scripts.utils import *

步骤4:重新构建并source

colcon clean
colcon build --symlink-install
source install/setup.bash

3. 不调整目录结构的替代方案

若坚持保留原目录结构,需将configs和scripts声明为独立Python包:

  1. 在setup.py的packages中添加这两个包:
packages=[PACKAGE_NAME, 'configs', 'scripts'],
  1. 保持from configs import global_settings导入语句不变,确保configs和scripts目录下的__init__.py存在;
  2. 重新构建并source工作空间。

内容的提问来源于stack exchange,提问作者Gonam Salinsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:25:00