ROS2 Python节点读取CSV文件路径异常解决方案:无需绝对路径运行及colcon构建后节点位置与ROS2内部变量说明
我来帮你搞定这个问题,其实核心原因很简单——开发时和构建后的工作目录不一样,导致相对路径失效。咱们一步步拆解解决:
一、为什么相对路径在colcon build后失效?
当你在开发目录直接运行python3 <node_name>.py时,终端的当前工作目录就是你放节点文件和CSV的目录,所以"turtle_commands.csv"这个相对路径能直接找到文件。
但用ros2 run <pkg_name> <node_name>运行时,终端的当前工作目录是你执行这条命令的位置(比如你的home目录),而不是节点安装后的路径,自然就找不到CSV文件了。
二、不用绝对路径的解决方法:利用ROS2的包共享目录
ROS2有一套资源管理机制,你可以把CSV文件标记为包的资源,构建后它会被复制到包的共享目录里,然后用ROS2提供的工具函数来获取这个路径,这样不管在哪运行都能找到文件。
步骤1:配置资源文件的安装路径
首先得告诉colcon build要把你的CSV文件复制到安装目录里,这需要修改setup.py(Python包的配置文件):
找到setup函数里的data_files参数,添加CSV文件的路径配置:
from setuptools import setup import os from glob import glob package_name = 'iti_lab_9' 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']), # 这一行是新增的,把CSV文件安装到包的共享目录 (os.path.join('share', package_name), glob('turtle_commands.csv')), ], install_requires=['setuptools'], zip_safe=True, maintainer='your_name', maintainer_email='your_email@example.com', description='TODO: Package description', license='TODO: License declaration', tests_require=['pytest'], entry_points={ 'console_scripts': [ '<node_name> = iti_lab_9.<node_name>:main', ], }, )
步骤2:修改代码获取正确路径
在你的节点代码里,用ROS2提供的ament_index_python工具包来获取包的共享目录路径,然后拼接CSV文件的名字:
import csv from ament_index_python.packages import get_package_share_path import os # 其他必要的ROS2导入... class YourNode(Node): def __init__(self): super().__init__('your_node_name') self.linear_x = [] self.angular_z = [] # 获取包的共享目录路径 pkg_path = get_package_share_path('iti_lab_9') # 拼接CSV文件的完整路径 csv_file_path = os.path.join(pkg_path, 'turtle_commands.csv') # 现在用这个路径打开文件 with open(csv_file_path, 'r', newline='') as csvfile: csvread = csv.reader(csvfile, delimiter=',') next(csvread) for row in csvread: self.linear_x.append(float(row[0])) self.angular_z.append(float(row[1])) self.index = 0
这样修改后,不管你在哪用ros2 run启动节点,都能正确找到CSV文件了。
三、colcon build后节点被复制到哪里?
构建完成后,你的节点会被安装到install/<pkg_name>/lib/<pkg_name>/目录下:
- 如果你用
entry_points配置了控制台脚本(像上面setup.py里的console_scripts部分),会生成一个可执行脚本在这个目录,ros2 run就是调用这个脚本。 - 你的Python节点源文件(
.py)会被复制到install/<pkg_name>/lib/pythonX.Y/site-packages/<pkg_name>/目录下(X.Y是你的Python版本)。
而你配置的CSV文件,会被复制到install/<pkg_name>/share/<pkg_name>/目录下,这就是我们用get_package_share_path获取的路径。
四、ROS2专属的内部变量/工具
这里最常用的就是ament_index_python包中的工具函数:
get_package_share_path(package_name):返回包的共享目录的路径对象(Python 3.6+支持路径操作)get_package_share_directory(package_name):返回包的共享目录的字符串路径,和上面功能类似,适合老版本Python
另外,你也可以用命令行查看包的安装路径:
ros2 pkg prefix <pkg_name>
这个命令会输出install/<pkg_name>的绝对路径,不过代码里还是用上面的Python函数更灵活。
内容的提问来源于stack exchange,提问作者Ali Hamdy

