【ROS2】初级:客户端-在类中使用参数(Python)

目标:使用 Python 创建并运行一个带有 ROS 参数的类。

 教程级别:初学者

 时间:20 分钟

 目录

  •  背景

  •  先决条件

  •  任务

    • 1. 创建一个包

    • 2. 编写 Python 节点

    • 3. 建立并运行

  •  摘要

  •  下一步

 背景

在创建您自己的节点时,有时需要添加可以从启动文件设置的参数。

本教程将向您展示如何在 Python 类中创建这些参数,以及如何在启动文件中设置它们。

 先决条件

在之前的教程中,您学习了如何创建工作空间和创建软件包。您还了解了参数及其在 ROS 2 系统中的功能。

 任务

1. 创建一个包

打开一个新的终端并且初始化您的 ROS 2 安装,这样 ros2 命令就会生效。

按照这些指示创建一个名为 ros2_ws 的新工作区。

请记住,包应该在 src 目录中创建,而不是在工作区的根目录中。导航到 ros2_ws/src 并创建一个新包:

cxy@ubuntu2404-cxy:~/ros2_ws/src$ ros2 pkg create --build-type ament_python --license Apache-2.0 python_parameters --dependencies rclpy
going to create a new package
package name: python_parameters
destination directory: /home/cxy/ros2_ws/src
package format: 3
version: 0.0.0
description: TODO: Package description
maintainer: ['cxy <cxy@todo.todo>']
licenses: ['Apache-2.0']
build type: ament_python
dependencies: ['rclpy']
creating folder ./python_parameters
creating ./python_parameters/package.xml
creating source folder
creating folder ./python_parameters/python_parameters
creating ./python_parameters/setup.py
creating ./python_parameters/setup.cfg
creating folder ./python_parameters/resource
creating ./python_parameters/resource/python_parameters
creating ./python_parameters/python_parameters/__init__.py
creating folder ./python_parameters/test
creating ./python_parameters/test/test_copyright.py
creating ./python_parameters/test/test_flake8.py
creating ./python_parameters/test/test_pep257.py

您的终端将返回一条消息,确认您的包 python_parameters 及其所有必要的文件和文件夹已创建。

--dependencies `参数将自动向` package.xml `和` CMakeLists.txt `添加必要的依赖行。

 1.1 更新 package.xml 

因为在创建包时您使用了 --dependencies 选项,所以您无需手动添加依赖项到 package.xml 或 CMakeLists.txt 。

一如既往,不过,请确保将描述、维护者电子邮件和姓名以及许可信息添加到 package.xml 。

<description>Python parameter tutorial</description>
<maintainer email="you@email.com">Your Name</maintainer>
<license>Apache-2.0</license>

2. 编写 Python 节点

在 ros2_ws/src/python_parameters/python_parameters 目录中,创建一个名为 python_parameters_node.py 的新文件,并将以下代码粘贴其中:

cxy@ubuntu2404-cxy:~/ros2_ws/src/python_parameters/python_parameters$ gedit python_parameters_node.py
# 导入rclpy模块,这是ROS2中Python客户端库的一部分
import rclpy
# 导入rclpy.node模块,这是ROS2中用于创建节点的模块
import rclpy.node


# 定义一个MinimalParam类,它继承自rclpy.node.Node类
class MinimalParam(rclpy.node.Node):
    # 类的初始化函数
    def __init__(self):
        # 调用父类的初始化函数,并设置节点名称为'minimal_param_node'
        super().__init__('minimal_param_node')


        # 声明一个参数'my_parameter',并设置默认值为'world'
        self.declare_parameter('my_parameter', 'world')


        # 创建一个定时器,每1秒调用一次timer_callback函数
        self.timer = self.create_timer(1, self.timer_callback)


    # 定时器回调函数
    def timer_callback(self):
        # 获取'my_parameter'参数的值
        my_param = self.get_parameter('my_parameter').get_parameter_value().string_value


        # 使用节点的日志功能打印信息
        self.get_logger().info('Hello %s!' % my_param)


        # 创建一个新的Parameter对象,用于更新'my_parameter'参数的值
        my_new_param = rclpy.parameter.Parameter(
            'my_parameter',
            rclpy.Parameter.Type.STRING,
            'world'
        )
        # 将新参数放入列表中
        all_new_parameters = [my_new_param]
        # 设置新的参数值
        self.set_parameters(all_new_parameters)


# main函数定义
def main():
    # 初始化rclpy库
    rclpy.init()
    # 创建MinimalParam类的实例
    node = MinimalParam()
    # 使节点保持运行,直到被外部事件(如Ctrl+C)中断
    rclpy.spin(node)


# Python脚本的入口点,当直接运行此脚本时执行main函数
if __name__ == '__main__':
    main()
2.1 检查代码 

顶部的 import 语句用于导入包依赖项。

下一段代码创建了类和构造函数。构造函数的第 self.declare_parameter('my_parameter', 'world') 行创建了一个名为 my_parameter 的参数,其默认值为 world 。参数类型是根据默认值推断出来的,所以在这种情况下它会被设置为字符串类型。接下来, timer 被初始化为 1,这导致 timer_callback 函数每秒执行一次。

class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')


        self.declare_parameter('my_parameter', 'world')


        self.timer = self.create_timer(1, self.timer_callback)

我们 timer_callback 函数的第一行从节点获取参数 my_parameter ,并将其存储在 my_param 中。接下来, get_logger 函数确保事件被记录。然后 set_parameters 函数将参数 my_parameter 重置为默认字符串值 world 。如果用户在外部更改了参数,这确保它总是被重置回原来的值。

def timer_callback(self):
    my_param = self.get_parameter('my_parameter').get_parameter_value().string_value


    self.get_logger().info('Hello %s!' % my_param)


    my_new_param = rclpy.parameter.Parameter(
        'my_parameter',
        rclpy.Parameter.Type.STRING,
        'world'
    )
    all_new_parameters = [my_new_param]
    self.set_parameters(all_new_parameters)

跟随 timer_callback 是我们的 main 。这里初始化了 ROS 2,构建了 MinimalParam 类的一个实例, rclpy.spin 开始处理来自节点的数据。

def main():
    rclpy.init()
    node = MinimalParam()
    rclpy.spin(node)


if __name__ == '__main__':
    main()
2.1.1(可选)添加参数描述符 

您可以选择为参数设置一个描述符。描述符允许您指定参数及其约束条件的文本描述,例如使其只读,指定范围等。为此, __init__ 代码必须更改为:

# ...


class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')


        from rcl_interfaces.msg import ParameterDescriptor
        my_parameter_descriptor = ParameterDescriptor(description='This parameter is mine!')


        self.declare_parameter('my_parameter', 'world', my_parameter_descriptor)


        self.timer = self.create_timer(1, self.timer_callback)

代码的其余部分保持不变。一旦运行了节点,你就可以运行 ros2 param describe /minimal_param_node my_parameter 来查看类型和描述。

2.2 添加一个入口点 

打开 setup.py 文件。再次,将 maintainer 、 maintainer_email 、 description 和 license 字段与您的 package.xml 匹配:

maintainer='YourName',
maintainer_email='you@email.com',
description='Python parameter tutorial',
license='Apache-2.0',

在 entry_points 字段的 console_scripts 括号内添加以下行:

entry_points={
    'console_scripts': [
        'minimal_param_node = python_parameters.python_parameters_node:main',
    ],
},

别忘了保存。

# 导入setuptools模块,用于配置、打包和安装Python包
from setuptools import find_packages, setup


# 设置包名为'python_parameters'
package_name = 'python_parameters'


# 调用setup函数来配置Python包
setup(
    # 包名
    name=package_name,
    # 版本号
    version='0.0.0',
    # 自动查找并包含所有find_packages()找到的包,排除名为'test'的包
    packages=find_packages(exclude=['test']),
    # 包含的数据文件
    data_files=[
        # 安装时需要复制的文件或文件夹列表
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    # 安装依赖项,这里只需要'setuptools'
    install_requires=['setuptools'],
    # 设置为zip安全,即可以安全地从zip压缩包运行
    zip_safe=True,
    # 维护者的名称
    maintainer='cxy',
    # 维护者的邮箱地址
    maintainer_email='cxy@126.com',
    # 包的简短描述
    description='Python parameter tutorial',
    # 许可证类型
    license='Apache-2.0',
    # 测试依赖项
    tests_require=['pytest'],
    # 入口点,定义了哪些脚本会被安装到系统路径中,以便直接在命令行中运行
    entry_points={
        'console_scripts': [
                # minimal_param_node是一个可执行命令,指向python_parameters.python_parameters_node模块中的main函数
                'minimal_param_node = python_parameters.python_parameters_node:main',
        ],
    },
)

3. 构建并运行

在工作区的根目录运行 rosdep ( ros2_ws )以检查构建前缺失的依赖项是一个好习惯:

rosdep install -i --from-path src --rosdistro jazzy -y

返回到您的工作区根目录, ros2_ws ,然后构建您的新包:

cxy@ubuntu2404-cxy:~/ros2_ws$ colcon build --packages-select python_parameters
Starting >>> python_parameters
Finished <<< python_parameters [2.56s]          


Summary: 1 package finished [2.82s]

打开一个新的终端,导航到 ros2_ws ,并且导入设置文件:

source install/setup.bash

现在运行节点:终端应该每秒返回以下消息:

cxy@ubuntu2404-cxy:~/ros2_ws$ ros2 run python_parameters minimal_param_node
[INFO] [1720325261.370823709] [minimal_param_node]: Hello world!
[INFO] [1720325262.346870169] [minimal_param_node]: Hello world!
[INFO] [1720325263.346835815] [minimal_param_node]: Hello world!

现在您可以看到参数的默认值,但您希望能够自己设置它。有两种方法可以做到这一点。

3.1 通过控制台进行更改 

这部分将使用你从教程中获得的关于参数的知识,并将其应用到你刚刚创建的节点上。

确保节点正在运行:

ros2 run python_parameters minimal_param_node

打开另一个终端,再次从 ros2_ws 内部获取设置文件,并输入以下行:

cxy@ubuntu2404-cxy:~/ros2_ws$ ros2 param list
/minimal_param_node:
  my_parameter
  start_type_description_service
  use_sim_time

在那里,您将看到自定义参数 my_parameter 。要更改它,只需在控制台中运行以下行:

ros2 param set /minimal_param_node my_parameter earth

你知道如果你得到输出 Set parameter successful ,那就进行得很顺利。如果你看看另一个终端,你应该会看到输出变成了 [INFO] [minimal_param_node]: Hello earth!

由于节点后来将参数重新设置为 world ,因此后续输出显示 [INFO] [minimal_param_node]: Hello world!

3.2 通过启动文件进行更改

您也可以在启动文件中设置参数,但首先您需要添加一个启动目录。在 ros2_ws/src/python_parameters/ 目录内,创建一个名为 launch 的新目录。在那里,创建一个名为 python_parameters_launch.py 的新文件。

# 从launch模块导入LaunchDescription类
from launch import LaunchDescription
# 从launch_ros模块的actions子模块导入Node类
from launch_ros.actions import Node


# 定义一个函数generate_launch_description,这个函数将会返回一个LaunchDescription对象
def generate_launch_description():
    # 返回一个LaunchDescription对象,它包含了一个Node列表
    return LaunchDescription([
        # 创建一个Node对象,用于启动一个ROS节点
        Node(
            # 指定节点所属的包名
            package='python_parameters',
            # 指定节点可执行文件的名称
            executable='minimal_param_node',
            # 为节点指定一个名称
            name='custom_minimal_param_node',
            # 设置节点的输出选项,这里是输出到屏幕
            output='screen',
            # 设置emulate_tty为True,以便在屏幕上模拟tty输出,使得输出更易读
            emulate_tty=True,
            # 设置节点的参数,这里定义了一个名为'my_parameter'的参数,其值为'earth'
            parameters=[
                {'my_parameter': 'earth'}
            ]
        )
    ])

在这里您可以看到,当我们启动节点 parameter_node 时,我们将 my_parameter 设置为 earth 。通过添加下面两行代码,我们确保输出打印在控制台上。

output="screen",
emulate_tty=True,

现在打开 setup.py 文件。将 import 语句添加到文件顶部,并将另一个新语句添加到 data_files 参数中,以包含所有启动文件:

import os
from glob import glob
# ...


setup(
  # ...
  data_files=[
      # ...
      (os.path.join('share', package_name), glob('launch/*launch.[pxy][yma]*')),
    ]
  )
# 从setuptools模块导入find_packages和setup函数
from setuptools import find_packages, setup
# 导入os模块,用于操作系统功能,如路径操作
import os
# 从glob模块导入glob函数,用于文件路径的模式匹配
from glob import glob


# 定义包名为'python_parameters'
package_name = 'python_parameters'


# 调用setup函数来配置包的设置
setup(
    # 设置包名
    name=package_name,
    # 设置包版本
    version='0.0.0',
    # 使用find_packages函数查找并包含所有子包,排除名为'test'的子包
    packages=find_packages(exclude=['test']),
    # 设置数据文件,这些文件将会被安装到系统中
    data_files=[
        # 安装ament索引资源到'share/ament_index/resource_index/packages'
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        # 安装package.xml到'share/' + package_name
        ('share/' + package_name, ['package.xml']),
        # 安装launch文件夹下所有的启动文件到'share/' + package_name
        (os.path.join('share', package_name), glob('launch/*launch.[pxy][yma]*')),
    ],
    # 设置包的依赖项,这里只需要'setuptools'
    install_requires=['setuptools'],
    # 设置zip_safe为True,表示可以安全地将此包作为zip文件运行
    zip_safe=True,
    # 设置维护者信息
    maintainer='cxy',
    maintainer_email='cxy@126.com',
    # 设置包描述
    description='Python parameter tutorial',
    # 设置许可证类型
    license='Apache-2.0',
    # 设置测试需要的依赖项
    tests_require=['pytest'],
    # 设置入口点,定义如何启动包中的程序
    entry_points={
        'console_scripts': [
                # 当运行'minimal_param_node'命令时,会调用python_parameters_node模块中的main函数
                'minimal_param_node = python_parameters.python_parameters_node:main',
        ],
    },
)

打开控制台并导航到您的工作区的根目录, ros2_ws ,然后构建您的新包:

cxy@ubuntu2404-cxy:~/ros2_ws$ colcon build --packages-select python_parameters
Starting >>> python_parameters
Finished <<< python_parameters [2.51s]          


Summary: 1 package finished [2.75s]

然后在新终端中导入设置文件:

source install/setup.bash

现在使用我们刚刚创建的启动文件运行节点:

cxy@ubuntu2404-cxy:~/ros2_ws$ source install/setup.bash
cxy@ubuntu2404-cxy:~/ros2_ws$ ros2 launch python_parameters python_parameters_launch.py
[INFO] [launch]: All log files can be found below /home/cxy/.ros/log/2024-07-07-12-15-25-235509-ubuntu2404-cxy-21329
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [minimal_param_node-1]: process started with pid [21332]
[minimal_param_node-1] [INFO] [1720325726.687588853] [custom_minimal_param_node]: Hello earth!
[minimal_param_node-1] [INFO] [1720325727.671121468] [custom_minimal_param_node]: Hello world!

进一步的输出应该每秒显示 [INFO] [minimal_param_node]: Hello world! 。

 摘要

您创建了一个带有自定义参数的节点,该参数可以从启动文件或命令行中设置。您将依赖项、可执行文件和启动文件添加到包配置文件中,以便您可以构建并运行它们,并看到参数在实际中的应用。

 下一步

现在您已经拥有了一些包和自己的 ROS 2 系统,下一个教程 https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Getting-Started-With-Ros2doctor.html 将向您展示如何在遇到问题时检查环境和系统中的问题。

ec338f859a3ceafc7385127f99de6a56.png

下列软件包有未满足的依赖关系: python3-rosdistro-modules : 依赖: python3-catkin-pkg-modules 但是它将不会被安装 python3-rospkg-modules : 依赖: python3-catkin-pkg-modules 但是它将不会被安装 ros-humble-ament-cmake-core : 依赖: python3-catkin-pkg-modules 但是它将不会被安装 ros-humble-qt-gui : 依赖: python3-catkin-pkg-modules 但是它将不会被安装 ros-humble-ros2doctor : 依赖: python3-catkin-pkg-modules 但是它将不会被安装 ros-humble-ros2pkg : 依赖: python3-catkin-pkg-modules 但是它将不会被安装 ros-humble-rqt-gui : 依赖: python3-catkin-pkg-modules 但是它将不会被安装 ros-humble-rqt-msg : 依赖: python3-catkin-pkg-modules 但是它将不会被安装 ros-humble-rqt-plot : 依赖: python3-catkin-pkg-modules 但是它将不会被安装 ros-humble-rqt-publisher : 依赖: python3-catkin-pkg-modules 但是它将不会被安装 ros-humble-rqt-shell : 依赖: python3-catkin-pkg-modules 但是它将不会被安装 ros-rolling-turtlesim : 依赖: ros-rolling-geometry-msgs 但是它将不会被安装 依赖: ros-rolling-rcl-interfaces 但是它将不会被安装 依赖: ros-rolling-rclcpp 但是它将不会被安装 依赖: ros-rolling-rclcpp-action 但是它将不会被安装 依赖: ros-rolling-rosidl-default-runtime 但是它将不会被安装 依赖: ros-rolling-std-msgs 但是它将不会被安装 依赖: ros-rolling-std-srvs 但是它将不会被安装 E: 有未能满足的依赖关系。请尝试不指明软件包的名字来运行“apt --fix-broken install”(也可以指定一个解决办法)
07-05
<think>我们正在解决ROS安装过程中出现的依赖问题。根据引用,问题通常发生在Ubuntu系统上安装ROS时,具体表现为python3-catkin-pkg-modules等依赖包无法安装,导致其他ROS包安装失败。错误信息提示有未满足的依赖关系,并建议运行`apt --fix-broken install`来尝试修复。 根据引用[2]和[3],错误信息中提到了多个依赖包无法安装,例如python-catkin-pkg、python-rosdep-modules等都有依赖问题。引用[4]提供了一个参考链接,但我们可以先尝试通用的解决方法。 解决步骤: 1. **更新软件包列表**:确保软件包列表是最新的,以避免因旧索引导致的依赖问题。 2. **尝试修复损坏的依赖**:运行`sudo apt --fix-broken install`,这是错误信息中建议的命令。 3. **安装缺失的依赖**:如果上一步不能解决问题,尝试单独安装缺失的依赖包。例如,根据错误信息,可能需要安装`python3-catkin-pkg-modules`,但注意版本要求。 4. **检查软件源**:确保已正确设置ROS的软件源(sources.list)和密钥(key)。 5. **清除apt缓存**:有时候损坏的缓存文件会导致安装失败,可以尝试清除缓存。 6. **尝试安装完整的ROS桌面版**:如果单独安装包失败,可以尝试安装整个ROS桌面版(如`ros-melodic-desktop-full`),这可能会自动解决依赖问题。 具体操作: 步骤1:更新软件包列表 ```bash sudo apt update ``` 步骤2:修复损坏的依赖 ```bash sudo apt --fix-broken install ``` 步骤3:如果步骤2没有解决问题,尝试安装特定的依赖包(根据错误信息,可能需要安装`python3-catkin-pkg-modules`,但注意版本) ```bash sudo apt install python3-catkin-pkg-modules ``` 如果上述命令失败,可能是因为版本冲突或者软件源中没有合适的版本。此时,可以考虑添加正确的ROS软件源。 步骤4:检查软件源 确保你的软件源中包含ROS的源。例如,对于Melodic(Ubuntu 18.04),应该有以下行: ```bash sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' ``` 然后导入密钥: ```bash sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 ``` 然后再次更新: ```bash sudo apt update ``` 步骤5:清除apt缓存 ```bash sudo apt clean sudo apt autoclean sudo rm -rf /var/lib/apt/lists/* sudo apt update ``` 步骤6:安装完整的ROS桌面版(如果之前尝试安装的是部分包) ```bash sudo apt install ros-melodic-desktop-full ``` 注意:以上步骤中的`melodic`需要根据你安装的ROS版本替换(如noetic、kinetic等),Ubuntu版本也需要对应。 如果问题仍然存在,可能需要查看具体的错误日志,或者参考引用[4]中的博客链接,但注意该链接是针对Ubuntu 20.04的,如果你的系统版本不同,可能需要寻找对应版本的解决方案。 最后,如果依赖关系非常混乱,可以考虑使用`aptitude`工具,它有时能提供更好的依赖解决方案。 ```bash sudo apt install aptitude sudo aptitude install ros-melodic-desktop-full ``` 在aptitude的界面中,它会提供几个解决方案,你可以选择接受或拒绝。注意,它可能会建议卸载一些冲突的包,请谨慎选择。 请根据你的实际情况调整上述步骤中的ROS版本和Ubuntu版本。 §§相关问题§§ 1. 如何确定我应该安装哪个版本的ROS2. 在安装ROS时,如何正确配置软件源和密钥? 3. 除了`apt --fix-broken install`,还有哪些方法可以解决依赖问题? 4. 如何避免在安装ROS时出现依赖问题?</think>### 解决ROS软件包安装依赖问题的方法 #### 问题分析 根据引用内容[^1][^2][^3],ROS安装过程中出现的依赖问题通常表现为: ```bash 下列软件包有未满足的依赖关系: python3-catkin-pkg-modules : 依赖: ... 但是它将不会被安装 E: 有未能满足的依赖关系 ``` 主要原因是软件包版本冲突、系统源配置不当或安装流程不规范。 --- ### 解决方案(逐步操作) #### 步骤1:修复损坏的依赖 ```bash sudo apt --fix-broken install ``` 此命令会尝试自动修复引用[^2]中提示的依赖链断裂问题。如果提示需要删除某些包,请确认是否与ROS无关。 #### 步骤2:更新软件源 ```bash sudo apt update sudo apt upgrade ``` 确保所有软件包处于最新状态,解决引用[^4]提到的缓存文件冲突问题。 #### 步骤3:强制安装核心依赖 ```bash sudo apt install -f python3-catkin-pkg-modules python3-rospkg-modules ``` `-f`参数会强制解决依赖关系,适用于引用[^3]中"无法修正错误"的情况。 #### 步骤4:清理冲突包 ```bash sudo apt autoremove sudo apt purge $(dpkg -l | grep '^rc' | awk '{print $2}') ``` 移除残留配置文件,解决引用[^2]中多个软件包相互阻塞的问题。 #### 步骤5:完整安装ROS ```bash sudo apt install ros-melodic-desktop-full # 请替换melodic为你的ROS版本 ``` 完整安装会处理所有子依赖,避免部分安装导致的依赖缺失。 --- ### 预防措施 1. **版本匹配**:确保ROS版本与Ubuntu版本兼容(如Melodic→Ubuntu 18.04) 2. **源配置**:正确设置`/etc/apt/sources.list.d/ros-latest.list` 3. **安装顺序**: ```bash sudo apt install python3-rosdep sudo rosdep init rosdep update ``` 再执行主安装 > **注意**:若仍失败,可尝试更换软件源(如阿里云镜像)或参考引用[^4]的缓存清理方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值