ros2_control 使用教程

news2024/11/20 6:28:35

系列文章目录


前言

0.1 欢迎阅读 ros2_control 文档!

        ros2_control 是一个使用(ROS 2)对机器人进行(实时)控制的框架。其软件包是对 ROS(机器人操作系统)中使用的 ros_control 软件包的重写。ros2_control 的目标是简化新硬件的集成并克服一些缺点。

        如果您不熟悉控制理论,请先了解一些相关知识(如维基百科),以便熟悉本手册中使用的术语。

0.2 ros2_control 资源库

        ros2_control 框架由以下 Github 仓库组成:

  • ros2_control - 框架的主要接口和组件;
  • ros2_controllers - 广泛使用的控制器,如正向指令控制器、联合轨迹控制器、差分驱动控制器;
  • control_toolbox - 控制器使用的一些广泛使用的控制理论实现(如 PID);
  • realtime_tools - 实时支持的通用工具包,如实时缓冲器和发布器;
  • control_msgs - 常用消息;
  • kinematics_interface - 用于使用 C++ 运动学框架;

        此外,还有以下(未发布的)软件包与启动和项目管理有关:

  • ros2_control_demos - 常见用例的示例实现,以便顺利启动;
  • roadmap - 项目规划和设计文档。

0.3 开发组织和交流

0.3.1 问题

        请使用机器人堆栈交换(Robotics Stack Exchange),并将您的问题标记为 ros2_control。

0.3.2 工作组会议

        每隔一周的周三都会召开工作组会议。要参加会议,请查看 ROS Discourse 上的公告。您可以通过谷歌群组或直接在谷歌会议上参加会议(查看公告)。要提出新的讨论点,或查看以前会议的记录,请查看此文档。

0.3.3 项目

        ros-control 组织下的 GitHub 项目用于跟踪工作。

0.3.4 错误报告和功能请求

        使用相应版本库中的问题跟踪器。提供问题的简短摘要 确保提供一份最基本的步骤列表,以便重现您发现的问题 提供操作系统、ROS 发行版等相关信息。

0.3.5 一般讨论

        请使用 ROS Discourse。


一、开始使用

1.1 安装

1.1.1 二进制包

ros2_control 框架是为 ROS 2 滚动而发布的。要使用它,必须安装 ros-rolling-ros2-control 和 ros-rolling-ros2-controllers 软件包。

1.1.2 从源代码构建

滚动分支与 Humble 和 Iron ROS 发行版兼容。你可以在本页面的 Humble 和 Iron 版本中找到更多关于兼容性的信息。

如果你想从源代码安装框架,例如为框架做贡献,请使用以下命令:

  • 下载所有软件源
    mkdir -p ~/ros2_ws/src
    cd ~/ros2_ws/
    wget https://raw.githubusercontent.com/ros-controls/ros2_control_ci/master/ros_controls.$ROS_DISTRO.repos
    vcs import src < ros_controls.$ROS_DISTRO.repos
  • 安装依赖项:

    rosdep update --rosdistro=$ROS_DISTRO
    sudo apt-get update
    rosdep install --from-paths src --ignore-src -r -y
  • 构建一切,例如:
    . /opt/ros/${ROS_DISTRO}/setup.sh
    colcon build --symlink-install
  • 不要忘记从安装文件夹中获取 setup.bash 源文件!

1.2 架构

ros2_control 框架的源代码可在 ros2_control 和 ros2_controllers GitHub 存储库中找到。下图显示了 ros2_control 框架的架构。 

下面的 UML 类图描述了 ros2_control 框架的内部实现。

 

1.2.1 控制器管理器


控制器管理器(CM)连接着 ros2_control 框架的控制器和硬件抽象。它也是用户通过 ROS 服务的入口点。CM 实现了一个没有执行器的节点,因此可以集成到自定义设置中。不过,通常建议使用 controller_manager 软件包中 ros2_control_node 文件实现的默认节点设置。本手册假定您使用该默认节点设置。

一方面,CM 管理(如加载、激活、停用、卸载)控制器及其所需的接口。另一方面,它可以(通过资源管理器)访问硬件组件,即它们的接口。控制器管理器会匹配所需的接口和提供的接口,在启用时允许控制器访问硬件,如果存在访问冲突,则会报错。

控制环的执行由 CM 的 update() 方法管理。它从硬件组件读取数据,更新所有激活控制器的输出,并将结果写入组件。

1.2.2 资源管理器


资源管理器(RM)为 ros2_control 框架抽象了物理硬件及其驱动程序(称为硬件组件)。RM 使用 pluginlib 库加载组件,管理其生命周期、组件状态和命令接口。RM 提供的抽象功能允许重用已实施的硬件组件,如机器人和抓手,而无需任何实施,并可灵活应用硬件来实现状态和命令接口,如用于电机控制和编码器读取的独立硬件/通信库。

在控制循环执行中,RM 的 read() 和 write() 方法处理与硬件组件的通信。

1.2.3 控制器


ros2_control 框架中的控制器基于控制理论。它们将参考值与测量输出进行比较,并根据这一误差计算系统的输入。控制器是从 ControllerInterface(ros2_control 中的 controller_interface 包)派生出来的对象,并使用 pluginlib-library 作为插件导出。有关控制器的示例,请查看 ros2_controllers 软件库中的 ForwardCommandController 实现。控制器的生命周期基于 LifecycleNode 类,该类实现了节点生命周期设计文档中描述的状态机。

执行控制循环时,会调用 update() 方法。该方法可访问最新的硬件状态,并使控制器能够写入硬件命令接口。

1.2.4 用户接口

用户使用控制器管理器的服务与 ros2_control 框架交互。有关服务及其定义的列表,请查看 controller_manager_msgs 软件包中的 srv 文件夹。

虽然服务调用可以直接从命令行或通过节点使用,但还有一个与 ros2 cli 集成的用户友好型命令行界面(CLI)。它支持自动完成,并提供一系列常用命令。基本命令是 ros2 control。有关 CLI 功能的说明,请参阅命令行界面 (CLI) 文档。

1.3 硬件组件


硬件组件实现了与物理硬件的通信,并在 ros2_control 框架中代表了物理硬件的抽象。这些组件必须使用 pluginlib-library 作为插件导出。资源管理器动态加载这些插件并管理其生命周期。

组件有三种基本类型:

系统

复杂(多自由度)机器人硬件,如工业机器人。执行器组件的主要区别在于可以使用复杂的传动装置,如人形机器人手部所需的传动装置。该组件具有读写功能。当硬件(如 KUKA-RSI)只有一个逻辑通信通道时,就需要使用该组件。

传感器

机器人硬件用于感知周围环境。传感器组件与关节(如编码器)或链接(如力矩传感器)相关。该组件类型仅具有读取功能。

执行器
简单(1 DOF)的机器人硬件,如电机、阀门等。执行器只与一个关节相关。该组件类型具有读写功能。如果读取功能不可行(例如使用 Arduino 电路板控制直流电机),则读取功能不是必须的。如果硬件可以进行模块化设计,例如可以与每个电机进行独立的 CAN 通信,那么这种类型的执行器也可以用于多自由度机器人。

有关硬件组件的详细说明,请参阅 "通过控制器进行硬件访问 "设计文档。

1.3.1 URDF 中的硬件描述

ros2_control 框架使用机器人 URDF 文件中的 <ros2_control> 标记来描述其组件,即硬件设置。所选结构可将多个 xacro 宏合并为一个宏,而无需进行任何更改。下面的示例展示了一个具有 2-DOF 的位置控制机器人(RRBot)、一个外部 1-DOF 力矩传感器和一个外部控制的 1-DOF 平行抓手作为其末端执行器。更多示例和详细说明,请查阅 ros2_control_demos 网站和 ROS 2 Control Components URDF Examples 设计文档。

<ros2_control name="RRBotSystemPositionOnly" type="system">
 <hardware>
   <plugin>ros2_control_demo_hardware/RRBotSystemPositionOnlyHardware</plugin>
   <param name="example_param_write_for_sec">2</param>
   <param name="example_param_read_for_sec">2</param>
 </hardware>
 <joint name="joint1">
   <command_interface name="position">
     <param name="min">-1</param>
     <param name="max">1</param>
   </command_interface>
   <state_interface name="position"/>
 </joint>
 <joint name="joint2">
   <command_interface name="position">
     <param name="min">-1</param>
     <param name="max">1</param>
   </command_interface>
   <state_interface name="position"/>
 </joint>
</ros2_control>
<ros2_control name="RRBotForceTorqueSensor1D" type="sensor">
 <hardware>
   <plugin>ros2_control_demo_hardware/ForceTorqueSensor1DHardware</plugin>
   <param name="example_param_read_for_sec">0.43</param>
 </hardware>
 <sensor name="tcp_fts_sensor">
   <state_interface name="force"/>
   <param name="frame_id">rrbot_tcp</param>
   <param name="min_force">-100</param>
   <param name="max_force">100</param>
 </sensor>
</ros2_control>
<ros2_control name="RRBotGripper" type="actuator">
 <hardware>
   <plugin>ros2_control_demo_hardware/PositionActuatorHardware</plugin>
   <param name="example_param_write_for_sec">1.23</param>
   <param name="example_param_read_for_sec">3</param>
 </hardware>
 <joint name="gripper_joint ">
   <command_interface name="position">
     <param name="min">0</param>
     <param name="max">50</param>
   </command_interface>
   <state_interface name="position"/>
   <state_interface name="velocity"/>
 </joint>
</ros2_control>

1.3.2 为机器人运行框架

要运行 ros2_control 框架,请执行以下操作。示例文件可在 ros2_control_demos 资源库中找到。

  1. 创建一个 YAML 文件,其中包含控制器管理器和两个控制器的配置。(RRBot 的配置示例)
  2. 用所需的 <ros2_control> 标记扩展机器人的 URDF 描述。建议使用宏文件 (xacro) 代替纯 URDF。(RRBot URDF 示例)
  3. 创建一个启动文件,以便使用控制器管理器启动节点。您可以使用默认的 ros2_control 节点(推荐),也可以在软件栈中集成控制器管理器。(RRBot 的启动文件示例)

注意:您也可以使用我们的维护者提供的脚本来创建 "hardware_interface "软件包的骨架。

二、ros_control

2.1 应用程序接口文档

API 文档由 doxygen 解析,可在此处找到

2.2 概念

2.2.1 控制器管理器

控制器管理器是 ros2_control 框架的主要组件。它管理控制器的生命周期、访问硬件接口,并为 ROS-world 提供服务。

2.2.1.1 确定性

为了在控制硬件时获得最佳性能,我们希望控制器管理器在主控制环路中的抖动越小越好。

控制器管理器的主线程会尝试配置优先级为 50 的 SCHED_FIFO,这与安装的内核无关。默认情况下,用户无权设置如此高的优先级。要赋予用户此类权限,请添加一个名为 realtime 的组,并将控制机器人的用户添加到该组中:

sudo addgroup realtime
sudo usermod -a -G realtime $(whoami)

然后,在 /etc/security/limits.conf 中为实时组添加以下限制:

@realtime soft rtprio 99
@realtime soft priority 99
@realtime soft memlock 102400
@realtime hard rtprio 99
@realtime hard priority 99
@realtime hard memlock 102400

注销并重新登录后,限制将被应用。

普通 Linux 内核针对计算吞吐量进行了优化,因此不太适合硬件控制。标准内核的替代方案包括

  • Ubuntu 22.04 LTS 测试版上的实时内核
  • Debian Bullseye 上的 linux-image-rt-amd64
  • 任何 Ubuntu 上的 lowlatency 内核(sudo apt install linux-lowlatency)。

虽然安装实时内核肯定能获得最佳的低抖动效果,但使用低延迟内核也能改善很多,而且安装非常简单。

2.2.1.2 订阅者

~/robot_description [std_msgs::msg::String] (机器人描述)

带有 URDF xml 的字符串,例如来自 robot_state_publisher。目前还不支持重新加载 URDF。<ros2_control> 标记中定义的所有关节都必须存在于 URDF 中。

2.2.1.3 参数

hardware_components_initial_state (硬件组件初始状态)

用于硬件组件受控生命周期管理的参数图。组件名称定义为机器人描述(robot_description)中 <ros2_control> 标签的属性。在机器人描述中找到的硬件组件,如果没有明确的状态定义,将立即被激活。各参数的详细说明如下。下面的示例给出了地图的完整结构:

hardware_components_initial_state:
  unconfigured:
    - "arm1"
    - "arm2"
  inactive:
    - "base3"

hardware_components_initial_state.unconfigured (可选;list<string>;默认为空)
定义控制器管理器启动时,哪些硬件组件只能立即加载。

hardware_components_initial_state.inactive (可选;list<string>;默认值:空)
定义哪些硬件组件将在控制器管理器启动时立即配置。

update_rate (必选项;整数)
控制器管理器实时更新循环的频率。该循环从硬件读取状态、更新控制器并向硬件写入命令。

<controller_name>.type
使用 pluginlib 导出的控制器插件名称。这是一个类,从中创建名称为 "controller_name "的控制器实例。

2.2.1.3.1 处理多个控制器管理器

在处理多个控制器管理器时,您有两种选择来管理不同的机器人描述:

  1. 使用命名空间: 您可以将 robot_state_publisher 节点和 controller_manager 节点放在同一个命名空间中。
    control_node = Node(
        package="controller_manager",
        executable="ros2_control_node",
        parameters=[robot_controllers],
        output="both",
        namespace="rrbot",
    )
    robot_state_pub_node = Node(
        package="robot_state_publisher",
        executable="robot_state_publisher",
        output="both",
        parameters=[robot_description],
        namespace="rrbot",
    )
  2. 使用重映射: 您可以使用重映射来处理不同的机器人描述。这包括使用重映射标签转发主题,允许您为每个控制器管理器指定自定义主题。
    control_node = Node(
        package="controller_manager",
        executable="ros2_control_node",
        parameters=[robot_controllers],
        output="both",
        remappings=[('robot_description', '/rrbot/robot_description')]
    )
    robot_state_pub_node = Node(
        package="robot_state_publisher",
        executable="robot_state_publisher",
        output="both",
        parameters=[robot_description],
        namespace="rrbot",
    )
2.2.1.4 辅助脚本

有两个脚本可通过启动文件与控制器管理器交互:

  1. spawner - 加载、配置和启动控制器。
  2. unspawner - 停止并卸载控制器。
spawner
$ ros2 run controller_manager spawner -h
usage: spawner [-h] [-c CONTROLLER_MANAGER] [-p PARAM_FILE] [-n NAMESPACE] [--load-only] [--inactive] [-t CONTROLLER_TYPE] [-u]
                  [--controller-manager-timeout CONTROLLER_MANAGER_TIMEOUT]
                  controller_name

positional arguments:
  controller_name       Name of the controller

options:
  -h, --help            show this help message and exit
  -c CONTROLLER_MANAGER, --controller-manager CONTROLLER_MANAGER
                        Name of the controller manager ROS node
  -p PARAM_FILE, --param-file PARAM_FILE
                        Controller param file to be loaded into controller node before configure
  -n NAMESPACE, --namespace NAMESPACE
                        Namespace for the controller
  --load-only           Only load the controller and leave unconfigured.
  --inactive            Load and configure the controller, however do not activate them
  -t CONTROLLER_TYPE, --controller-type CONTROLLER_TYPE
                        If not provided it should exist in the controller manager namespace
  -u, --unload-on-kill  Wait until this application is interrupted and unload controller
  --controller-manager-timeout CONTROLLER_MANAGER_TIMEOUT
                        Time to wait for the controller manager
unspawner
$ ros2 run controller_manager unspawner -h
usage: unspawner [-h] [-c CONTROLLER_MANAGER] controller_name

positional arguments:
  controller_name       Name of the controller

optional arguments:
  -h, --help            show this help message and exit
  -c CONTROLLER_MANAGER, --controller-manager CONTROLLER_MANAGER
                        Name of the controller manager ROS node
2.2.1.5 在进程中使用控制器管理器

ControllerManager 也可以作为一个类在进程中实例化,但这样做时必须小心谨慎。原因是 ControllerManager 类继承自 rclcpp::Node。

如果进程中有多个 Node,全局节点名称重映射规则会强行更改 ControllerManager 的节点名称,从而导致节点名称重复。无论节点是同级节点还是存在于层次结构中,都会出现这种情况。

解决这一问题的办法是在传递给 ControllerManager 节点的 NodeOptions 中指定另一个节点名称重映射规则(使其忽略全局规则),或确保任何重映射规则都针对特定节点。 

auto options = controller_manager::get_cm_node_options();
  options.arguments({
    "--ros-args",
    "--remap", "_target_node_name:__node:=dst_node_name",
    "--log-level", "info"});

  auto cm = std::make_shared<controller_manager::ControllerManager>(
    executor, "_target_node_name", "some_optional_namespace", options);
2.2.1.6 概念
重启所有控制器

重启所有控制器的最简单方法是使用 switch_controllers 服务或 CLI,并将所有控制器添加到启动和停止列表中。请注意,并非所有控制器都必须重启,例如广播器。

重启硬件

如果硬件被重启,则应再次经历其生命周期,以便重新配置和导出接口

硬件和控制器错误

如果硬件在读取或写入方法中返回 return_type::ERROR,控制器管理器将停止使用该硬件命令和状态接口的所有控制器。同样,如果控制器的更新方法返回 return_type::ERROR,控制器管理器将停用相应的控制器。今后,控制器管理器将尝试启动任何可用的后备控制器。

2.2.2 控制器连锁/级联控制

2.2.3 ros2_control 的关节运动学

2.2.4 硬件组件

硬件组件是 ros2_control 框架中物理硬件的抽象。硬件有三种类型:执行器(Actuator)、传感器(Sensor)和系统(System)。有关每种类型的详细信息,请查看硬件组件说明。

指南和最佳实践

  • 硬件接口类型
  • 编写硬件组件
  • 不同的更新速率
2.2.4.1 处理调用 read() 和 write() 时发生的错误

如果硬件接口类的 read() 或 write() 方法返回 hardware_interface::return_type::ERROR,则会调用 on_error(previous_state)方法来处理发生的错误。

错误处理遵循节点生命周期。如果成功,将返回 CallbackReturn::SUCCESS,硬件将再次处于 UNCONFIGURED 状态;如果发生任何 ERROR 或 FAILURE,硬件将结束于 FINALIZED 状态,无法恢复。唯一的选择是重新加载整个插件,但目前控制器管理器中还没有这方面的服务。

2.2.4.2  ros2_control 硬件接口类型

ros2_control 框架提供了一系列硬件接口类型,可用于实现特定机器人或设备的硬件组件。下文将介绍不同的硬件接口类型及其用法。

2.2.4.2.1 Joints(关节)


<joint> 标签将与物理机器人和致动器关节相关的接口分组。它们具有命令和状态接口,用于设置硬件的目标值和读取其当前状态。

控制器管理器收到的 URDF 中必须包含 <ros2_control> 标签中定义的所有关节。

关节的状态接口可以通过 joint_state_broadcaster 作为 ROS 主题发布。

2.2.4.2.2 Sensors(传感器)

<传感器>标签可将多个状态接口(例如硬件的内部状态)组合在一起。

根据传感器类型的不同,ros2_controllers 提供了一些带有广播器的特定语义组件,例如

Imu 传感器广播器

力矩传感器广播器

2.2.4.2.3 GPIOs

<gpio> 标签用于描述机器人设备的输入和输出端口,这些端口不能与任何关节或传感器相关联。<gpio> 标签的解析与具有命令和状态接口的 <joint> 标签的解析类似。该标记必须至少有一个 <command>- 或 <state>- 标记作为子标记。

选择关键字 "gpio "是因为它的通用性。虽然它严格用于数字信号,但也可描述任何电气模拟信号、数字信号或物理值。

<gpio> 标签可作为所有三种硬件组件(即系统、传感器或执行器)的子标签。

由于以 <gpio> 标签实现的端口通常非常针对特定应用,因此在 ros2_control 框架中不存在通用发布器。因此,必须为每个应用程序定制一个 gpio 控制器。作为示例,请参阅演示库中的 GPIO 控制器示例。

2.2.4.2.4 硬件组

硬件组件组是复杂系统中的重要组织机制,有利于错误处理和容错。通过将相关硬件组件(如机械手中的致动器)分组,用户可以建立一个统一的错误检测和响应框架。

硬件组件组在相互连接的硬件组件之间传播错误方面发挥着至关重要的作用。例如,在机械手系统中,将执行器分组可实现错误传播。如果组内的一个执行器发生故障,错误就会传播到其他执行器,从而引发整个系统的潜在问题。默认情况下,致动器的错误会被隔离到各自的硬件组件中,使其他组件不受影响地继续运行。在提供的 ros2_control 配置中,每个 <ros2_control> 块中的 <group> 标记表示硬件组件的分组,从而在系统内启用错误传播机制。

2.2.4.2.5 示例

以下示例展示了如何在 ros2_control URDF 中使用不同的硬件接口类型。它们可以在不同的硬件组件类型(系统、执行器、传感器)中组合在一起(参见详细文档),如下所示

带多个 GPIO 接口的机器人
  • RRBot 系统
  • 数字: 4 个输入和 2 个输出
  • 模拟 2 个输入和 1 个输出
  • 法兰上的真空阀(开/关)
<ros2_control name="RRBotSystemMutipleGPIOs" type="system">
  <hardware>
    <plugin>ros2_control_demo_hardware/RRBotSystemPositionOnlyHardware</plugin>
    <param name="example_param_hw_start_duration_sec">2.0</param>
    <param name="example_param_hw_stop_duration_sec">3.0</param>
    <param name="example_param_hw_slowdown">2.0</param>
  </hardware>
  <joint name="joint1">
    <command_interface name="position">
      <param name="min">-1</param>
      <param name="max">1</param>
    </command_interface>
    <state_interface name="position"/>
  </joint>
  <joint name="joint2">
    <command_interface name="position">
      <param name="min">-1</param>
      <param name="max">1</param>
    </command_interface>
    <state_interface name="position"/>
  </joint>
  <gpio name="flange_digital_IOs">
    <command_interface name="digital_output1"/>
    <state_interface name="digital_output1"/>    <!-- Needed to know current state of the output -->
    <command_interface name="digital_output2"/>
    <state_interface name="digital_output2"/>
    <state_interface name="digital_input1"/>
    <state_interface name="digital_input2"/>
  </gpio>
  <gpio name="flange_analog_IOs">
    <command_interface name="analog_output1"/>
    <state_interface name="analog_output1">    <!-- Needed to know current state of the output -->
      <param name="initial_value">3.1</param>  <!-- Optional initial value for mock_hardware -->
    </state_interface>
    <state_interface name="analog_input1"/>
    <state_interface name="analog_input2"/>
  </gpio>
  <gpio name="flange_vacuum">
    <command_interface name="vacuum"/>
    <state_interface name="vacuum"/>    <!-- Needed to know current state of the output -->
  </gpio>
</ros2_control>
可实现电动和吸力抓取的机械手
  • 多模式机械手
  • 1-DoF 平行机械手
  • 吸力开/关
<ros2_control name="MultimodalGripper" type="actuator">
  <hardware>
    <plugin>ros2_control_demo_hardware/MultimodalGripper</plugin>
  </hardware>
  <joint name="parallel_fingers">
    <command_interface name="position">
      <param name="min">0</param>
      <param name="max">100</param>
    </command_interface>
    <state_interface name="position"/>
  </joint>
  <gpio name="suction">
    <command_interface name="suction"/>
    <state_interface name="suction"/>    <!-- Needed to know current state of the output -->
  </gpio>
</ros2_control>

带温度反馈和可调校准功能的力扭矩传感器
  • 2D FTS
  • 以 °C 为单位的温度反馈
  • 在 3 个校准矩阵(即校准范围)之间进行选择
<ros2_control name="RRBotForceTorqueSensor2D" type="sensor">
  <hardware>
    <plugin>ros2_control_demo_hardware/ForceTorqueSensor2DHardware</plugin>
    <param name="example_param_read_for_sec">0.43</param>
  </hardware>
  <sensor name="tcp_fts_sensor">
    <state_interface name="fx"/>
    <state_interface name="tz"/>
    <param name="frame_id">kuka_tcp</param>
    <param name="fx_range">100</param>
    <param name="tz_range">100</param>
  </sensor>
  <sensor name="temp_feedback">
    <state_interface name="temperature"/>
  </sensor>
  <gpio name="calibration">
    <command_interface name="calibration_matrix_nr"/>
    <state_interface name="calibration_matrix_nr"/>
  </gpio>
</ros2_control>
机器人的多个硬件组件属于同一组:Group1
  • RRBot 系统 1 和 2
  • 数字式: 共有 4 个输入和 2 个输出
  • 模拟: 共 2 个输入和 1 个输出
  • 法兰上的真空阀(开/关)
  • 组 组 1
<ros2_control name="RRBotSystem1" type="system">
  <hardware>
    <plugin>ros2_control_demo_hardware/RRBotSystemPositionOnlyHardware</plugin>
    <group>Group1</group>
    <param name="example_param_hw_start_duration_sec">2.0</param>
    <param name="example_param_hw_stop_duration_sec">3.0</param>
    <param name="example_param_hw_slowdown">2.0</param>
  </hardware>
  <joint name="joint1">
    <command_interface name="position">
      <param name="min">-1</param>
      <param name="max">1</param>
    </command_interface>
    <state_interface name="position"/>
  </joint>
  <gpio name="flange_analog_IOs">
    <command_interface name="analog_output1"/>
    <state_interface name="analog_output1">    <!-- Needed to know current state of the output -->
      <param name="initial_value">3.1</param>  <!-- Optional initial value for mock_hardware -->
    </state_interface>
    <state_interface name="analog_input1"/>
    <state_interface name="analog_input2"/>
  </gpio>
  <gpio name="flange_vacuum">
    <command_interface name="vacuum"/>
    <state_interface name="vacuum"/>    <!-- Needed to know current state of the output -->
  </gpio>
</ros2_control>
<ros2_control name="RRBotSystem2" type="system">
  <hardware>
    <plugin>ros2_control_demo_hardware/RRBotSystemPositionOnlyHardware</plugin>
    <group>Group1</group>
    <param name="example_param_hw_start_duration_sec">2.0</param>
    <param name="example_param_hw_stop_duration_sec">3.0</param>
    <param name="example_param_hw_slowdown">2.0</param>
  </hardware>
  <joint name="joint2">
    <command_interface name="position">
      <param name="min">-1</param>
      <param name="max">1</param>
    </command_interface>
    <state_interface name="position"/>
  </joint>
  <gpio name="flange_digital_IOs">
    <command_interface name="digital_output1"/>
    <state_interface name="digital_output1"/>    <!-- Needed to know current state of the output -->
    <command_interface name="digital_output2"/>
    <state_interface name="digital_output2"/>
    <state_interface name="digital_input1"/>
    <state_interface name="digital_input2"/>
  </gpio>
</ros2_control>
2.2.4.3 编写硬件组件

在 ros2_control 中,硬件系统组件是库,由控制器管理器使用 pluginlib 接口动态加载。以下是为新硬件接口创建源文件、基本测试和编译规则的分步指南。

2.2.4.3.1 准备软件包

如果硬件接口的软件包不存在,则首先创建它。软件包的构建类型应为 ament_cmake。最简单的方法是上网搜索最新的手册。支持这一过程的有用命令是 ros2 pkg create。使用 --help 标志可获取更多关于如何使用该命令的信息。还有一个创建库源文件和编译规则的选项,可以帮助你完成下面的步骤。

2.2.4.3.2 准备源文件

创建软件包后,至少要有 CMakeLists.txt 和 package.xml 文件。如果 include/<PACKAGE_NAME>/ 和 src 文件夹还不存在,也请创建它们。在 include/<PACKAGE_NAME>/ 文件夹中添加 <robot_hardware_interface_name>.hpp 和 <robot_hardware_interface_name>.cpp 文件。可选择添加 visibility_control.h,其中包含 Windows 导出规则的定义。您可以从现有控制器软件包中复制该文件,并将名称前缀改为 <PACKAGE_NAME>。

2.2.4.3.3 在头文件(.hpp)中添加声明
  1. 注意使用头文件保护。ROS2 风格使用 #ifndef 和 #define 预处理器指令。(如需了解更多相关信息,请使用搜索引擎:)。
  2. 如果正在使用 "hardware_interface/$interface_type$_interface.hpp "和 visibility_control.h,请将其包括在内。根据使用的硬件类型,$interface_type$ 可以是执行器(Actuator)、传感器(Sensor)或系统(System),有关每种类型的详细信息,请查看硬件组件说明。
  3. 为硬件接口定义一个唯一的命名空间。这通常是以 snake_case 书写的软件包名称。
  4. 定义硬件接口的类,扩展 $InterfaceType$Interface,例如... 代码:: c++ class HardwareInterfaceName : public hardware_interface::$InterfaceType$Interface 5.
  5. 添加一个不带参数的构造函数和以下实现 LifecycleNodeInterface 的公共方法:on_configure、on_cleanup、on_shutdown、on_activate、on_deactivate、on_error;覆盖 $InterfaceType$Interface 定义:on_init、export_state_interfaces、export_command_interfaces、prepare_command_mode_switch(可选)、perform_command_mode_switch(可选)、read、write。有关硬件生命周期的更多解释,请查看拉取请求,有关方法的确切定义,请查看 "hardware_interface/$interface_type$_interface.hpp "头文件或 Actuator、Sensor 或 System 的 doxygen 文档。
2.2.4.3.4 在源文件(.cpp)中添加定义
  1. 包含硬件接口的头文件并添加命名空间定义,以简化进一步开发。
  2. 实现 on_init 方法。在此,应初始化所有成员变量并处理 info 参数中的参数。在第一行中,通常会调用父代 on_init 来处理标准值,如 name。具体方法是:hardware_interface::(Actuator|Sensor|System)Interface::on_init(info)。如果所有必要参数都已设置且有效,并且一切运行正常,则返回 CallbackReturn::SUCCESS 或返回 CallbackReturn::ERROR 否则返回 CallbackReturn::ERROR。
  3. 编写 on_configure 方法,通常在该方法中设置与硬件的通信,并设置好一切以便激活硬件。
  4. 实现与 on_configure 相反的 on_cleanup 方法。
  5. 执行 export_state_interfaces 和 export_command_interfaces 方法,定义硬件提供的接口。传感器类型硬件接口没有 export_command_interfaces 方法。需要提醒的是,完整的接口名称结构为 <joint_name>/<interface_type> 。
  6. (可选)对于执行器和系统类型的硬件接口,如果您的硬件接受多种控制模式,请执行 prepare_command_mode_switch 和 perform_command_mode_switch。
  7. 在启用硬件 "电源 "时,执行 on_activate 方法。
  8. 执行与 on_activate 相反的 on_deactivate 方法。
  9. 实现 on_shutdown 方法,优雅地关闭硬件。
  10. 实现 on_error 方法,处理所有状态下的不同错误。
  11. 实现 read 方法,从硬件获取状态并将其存储到 export_state_interfaces 中定义的内部变量。
  12. 实现写方法,根据存储在 export_command_interfaces 中定义的内部变量中的值对硬件发出指令。
  13. 重要:在命名空间关闭后的文件末尾,添加 PLUGINLIB_EXPORT_CLASS 宏。
  14. 为此,您需要包含 "pluginlib/class_list_macros.hpp "头文件。第一个参数应提供准确的硬件接口类,例如 <my_hardware_interface_package>::<RobotHardwareInterfaceName>, 第二个参数应提供基类,即 hardware_interface::(Actuator|Sensor|System)Interface。
2.2.4.3.5 为插件库编写导出定义
  1. 在软件包中创建 <my_hardware_interface_package>.xml 文件,并添加必须对 pluginlib 可见的库和硬件接口类的定义。最简单的方法是检查 hardware_interface mock_components 部分的模拟组件定义。
  2. 通常,插件名称是由软件包(命名空间)和类名定义的,例如,<my_hardware_interface_package>/<RobotHardwareInterfaceName>。当资源管理器搜索硬件接口时,该名称定义了硬件接口的类型。其他两个参数必须与 <robot_hardware_interface_name>.cpp 文件底部宏中的定义一致。
2.2.4.3.6 编写一个简单的测试来检查是否能找到并加载控制器
  1. 在软件包中创建 test 文件夹(如果还不存在),并添加名为 test_load_<robot_hardware_interface_name>.cpp 的文件。
  2. 您可以复制 test_generic_system.cpp 软件包中定义的 load_generic_system_2dof 内容。
  3. 更改复制的测试名称,并在最后一行指定硬件接口类型的地方加上 <my_hardware_interface_package>.xml 文件中定义的名称,例如 <my_hardware_interface_package>/<RobotHardwareInterfaceName>。
2.2.4.3.7 在``CMakeLists.txt``文件中添加编译指令
  1. 在 find_package(ament_cmake REQUIRED) 一行下添加更多依赖项。这些依赖至少包括:hardware_interface、pluginlib、rclcpp 和 rclcpp_lifecycle。
  2. 为共享库添加编译指令,提供 <robot_hardware_interface_name>.cpp 文件作为源代码。
  3. 为库添加目标 include 目录。通常只有 include 目录。
  4. 添加库所需的其他依赖项。至少应添加 1 中列出的依赖项。
  5. 使用以下命令导出 pluginlib 说明文件: ... 代码::: cmake
  6. pluginlib_export_plugin_description_file(hardware_interface <my_hardware_interface_package>.xml)
  7. 为目标和 include 目录添加安装指令。
  8. 在测试部分添加以下依赖项:amment_cmake_gmock、hardware_interface。
  9. 使用 ament_add_gmock 指令为测试添加编译定义。详情请参阅 ros2_control 软件包中的模拟硬件编译方法。
  10. (可选)在 ament_package() 之前将硬件接口库添加到 ament_export_libraries。
2.2.4.3.8 在 ``package.xml`` 文件中添加依赖包
  1. 在 <depend> 标记中至少添加以下软件包:hardware_interface、pluginlib、rclcpp 和 rclcpp_lifecycle。
  2. 在 <test_depend> 标记中至少添加以下软件包:ament_add_gmock 和 hardware_interface。
2.2.4.3.9 编译和测试硬件组件
  1. 现在一切准备就绪,可以使用 colcon build <my_hardware_interface_package> 命令编译硬件组件了。记住,执行该命令前要进入工作区的根目录。
  2. 如果编译成功,则从安装文件夹中获取 setup.bash 文件,然后执行 colcon test <my_hardware_interface_package> 检查新控制器是否能通过 pluginlib 库找到并被控制器管理器加载。

就是这样!尽情编写出色的控制器吧

2.2.4.3.10 有用的外部参考资料

用于生成控制器 shell 的模板和脚本

注意事项

该脚本目前仅推荐用于 Foxy,与 Galactic 及以后的 API 不兼容。

三、ros2_controllers

用于 ros2_control 框架的常用通用控制器,可与许多机器人、MoveIt2 和 Nav2 一起使用。

指南与最佳实践

  • 轮式移动机器人运动学
  • 编写新控制器

轮式移动机器人控制器

  • 差分驱动控制器
  • 转向控制器库
  • 三轮车控制器

机械手和其他机器人控制器
控制器使用通用硬件接口定义,可根据以下命令接口类型使用命名空间:

  • 位置控制器:hardware_interface::HW_IF_POSITION
  • 速度控制器:hardware_interface::HW_IF_VELOCITY
  • 力矩控制器: hardware_interface::HW_IF_ACCELERATION
  • 力矩控制器: hardware_interface::HW_IF_EFFORT

  • 导纳控制器
  • 力矩控制器
  • 前进指令控制器
  • 夹爪控制器
  • 关节轨迹控制器
    • 轨迹表示
    • 轨迹替换
    • 关节轨迹控制器参数
    • rqt_joint_trajectory_controller
  • PID 控制器
  • 位置控制器
  • 速度控制器

广播器
广播器用于从硬件组件向 ROS 主题发布传感器数据。从 ros2_control 的意义上讲,广播器仍然是控制器,使用与上述其他控制器相同的控制器接口。

  • 力矩传感器广播器
  • IMU 传感器广播器
  • 关节状态广播器
  • 范围传感器广播器

常见控制器参数
每个控制器和广播器都有一些通用参数。这些参数是可选的,但如果需要,必须在 onConfigure 过渡到非活动状态前设置,请参阅生命周期文档。一旦控制器已加载,则可使用控制器管理器的 configure_controller 服务完成此转换。

  • update_rate(更新率): 一个无符号整数参数,代表每个控制器/广播器运行更新周期的速率。未指定时,它们将以与控制器管理器相同的频率运行。
  • is_async: 一个布尔参数,用于指定控制器更新是否需要异步运行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1863456.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NetSuite CSV导入类型与记录类型梳理

最近有用户问到我们的一个问题是&#xff0c;哪些数据可以使用CSV导入&#xff0c;哪些数据不能使用CSV导入&#xff0c;干脆咱们就整理出来可使用CSV导入功能的类型和记录类型&#xff0c;供大家直接参考&#xff5e; 但是有一些内容或多或少由于每个企业的环境不一样而有所不…

jenkins环境搭建--关于jenkins在Ubuntu下的安装篇(一)

在ubuntu下使用命令进行下载安装包&#xff1a; 关于jenkins的安装有多种&#xff0c;可以借助docker容器进行安装&#xff0c;也可以通过传统方法手动一步步的进行安装&#xff0c;以下介绍手动一步步的安装方法&#xff0c;后续我们将解释关于jenkins的相关配置以及实战使用…

mongodb 查询语句学习笔记

基础查询 正则查询 {status: A,$or: [{ qty: { $lt: 30 } }, { item: { $regex: ^p } }] }AND 查询 { "size.h": { $lt: 15 }, "size.uom": "in", status: "D" }OR 查询 { $or: [ { status: "A" }, { qty: { $lt: 30 } …

万界星空科技自动化运维管理---设备管理

在信息化管理体系建设中&#xff0c;设备管理系统被看作是重中之重。因为设备是工厂生产中的主体、生命线&#xff0c;随着科学技术的不断发展、智能制造的产业升级&#xff0c;生产设备日益智能化、自动化&#xff0c;设备在现代工业生产中的作用和影响也随之增大&#xff0c;…

智能体——父亲兴趣爱好助手

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大二学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…

Sectigo或RapidSSL DV通配符SSL证书哪个性价比更高?

在当前的网络安全领域&#xff0c;选择一款合适的SSL证书对于保护网站和用户数据至关重要。Sectigo和RapidSSL作为市场上知名的SSL证书提供商&#xff0c;以其高性价比和快速的服务响应而受到市场的青睐。本文将对Sectigo和RapidSSL DV通配符证书进行深入对比&#xff0c;帮助用…

java设计模式(四)原型模式(Prototype Pattern)

1、模式介绍&#xff1a; 原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;它允许对象在创建新实例时通过复制现有实例而不是通过实例化新对象来完成。这样做可以避免耗费大量的资源和时间来初始化对象。原型模式涉及一个被复制的原型对象…

【机器学习】在【R语言】中的应用:结合【PostgreSQL数据库】的【金融行业信用评分模型】构建

目录 1.数据库和数据集的选择 1.准备工作 2.PostgreSQL安装与配置 3.R和RStudio安装与配置 2.数据导入和预处理 1.连接数据库并导入数据 1.连接数据库 2.数据检查和清洗 1.数据标准化 2.拆分训练集和测试集 3.特征工程 1.生成新特征 2.特征选择 4.模型训练和评估…

【浦语开源】深入探索:大模型全链路开源组件 InternLM Lagent,打造灵笔Demo实战指南

一、准备工作&#xff1a; 1、环境配置&#xff1a; pip、conda换源&#xff1a; pip临时换源&#xff1a; pip install -i https://mirrors.cernet.edu.cn/pypi/web/simple some-package# 这里的“https://mirrors.cernet.edu.cn/pypi/web/simple”是所换的源&#xff0c;…

2024广东省职业技能大赛云计算赛项实战——构建CICD

构建CI/CD 前言 题目如下&#xff1a; 构建CI/CD 编写流水线脚本.gitlab-ci.yml触发自动构建&#xff0c;具体要求如下&#xff1a; &#xff08;1&#xff09;基于镜像maven:3.6-jdk-8构建项目的drone分支&#xff1b; &#xff08;2&#xff09;构建镜像的名称&#xff1a…

【threejs】火焰特效制作

2024-06-26 08-57-16火焰 shader 来源 //shadertory&#xff1a;https://www.shadertoy.com/view/ctVGD1//shadertory&#xff1a;https://www.shadertoy.com/view/ml3GWs 代码 import { DoubleSide, ShaderChunk, ShaderMaterial } from "three";export default fu…

嵌入式EMC之TVS管

整理一些网上摘抄的笔记&#xff1a; TVS管认识&#xff1a; TVS的Vc要比&#xff0c;DCDC的最大承受电压要小

mysql workbench使用schema视图导出表和列结构到excel

目的&#xff1a;导出所有表和列的名字和注释 很多时候没有正规的数据库文档&#xff0c;为了快速交流啊&#xff0c;需要一个快捷的基础。数据库建表的时候可能有注释&#xff0c;也可能没有注释。有当然好&#xff0c;查看注释就能清楚很多&#xff0c;没有的话最好一个一个补…

高效文件分类管理:快速将不同类型文件素材归类到专属文件夹,告别混乱,让工作更高效!

在数字化时代&#xff0c;我们每天都会产生大量的文件素材&#xff0c;从图片、文档到音频、视频&#xff0c;种类繁多&#xff0c;数量庞大。如果这些文件没有得到有效的管理和归类&#xff0c;不仅会让我们的工作变得混乱无序&#xff0c;还会影响我们的工作效率。那么&#…

文华WH7主图多空预警系统指标公式源码

RSV:(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100;//收盘价与N周期最低值做差&#xff0c;N周期最高值与N周期最低值做差&#xff0c;两差之间做比值定义为RSV K:SMA(RSV,3,1);//RSV的移动平均 D:SMA(K,3,1);//K值的移动平均 DIFF : EMA(CLOSE,12) - EMA(CLOSE,26); D…

python-17-零基础自学python-

学习内容&#xff1a;《python编程&#xff1a;从入门到实践》第二版 知识点&#xff1a; 类、子类、继承、调用函数 练习内容&#xff1a; 练习9-6&#xff1a;冰激凌小店 冰激凌小店是一种特殊的餐馆。编写一个名为IceCreamStand的类&#xff0c;让它继承为完成练习9-1或…

spring原理篇

第三方bean默认为方法名 自动配置 自动配置的原理 springboot的自动配置原理 首先是从 SpringBootApplication这个注解出发 有一个ComponentScan()默认扫描同级包及其子包 第二个注解是springbootconfiguration 声明当前类是一个配置类 第三个是核心 enableAutoConfigurati…

HRSC2016 :推动光学遥感图像细粒度船舶检测的创新引擎(目标检测)

亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 摘要&a…

华为OD机试【高矮个子排队】(java)(100分)

1、题目描述 现在有一队小朋友&#xff0c;他们高矮不同&#xff0c;我们以正整数数组表示这一队小朋友的身高&#xff0c;如数组{5,3,1,2,3}。 我们现在希望小朋友排队&#xff0c;以“高”“矮”“高”“矮”顺序排列&#xff0c;每一个“高”位置的小朋友要比相邻的位置高或…

pp 学习一 生产模块主数据

生产成本&#xff1a;原材料是什么&#xff0c;价格多少&#xff0c;人工耗费时间&#xff0c;以及其他的费用 离散制造&#xff1a;有生产订单。工序是分开的&#xff08;可以停&#xff09; 重复制造&#xff1a;没有生产订单&#xff08;可能有客户下达的任务单或者计划订…