ROS自学实践(15):ROS2控制仿真车辆

2023-11-03

我们的目标是拥有一个可以在环境中移动的机器人的完全工作、可控的表示,有两种方法可以实现这个目标。 显式公开控制器节点并使用它们 - 本文的重点。 或者使用预定义的 Gazebo 插件来为您完成繁重的工作。

在本文中,我介绍了如何配置 URDF 模型和显式启动控制节点的教程。 这些节点公开命令来控制机器人模型,但要正常工作,它们需要额外的胶水代码,此处不再赘述。 但是,您将了解有关 ROS 内部结构的基本信息,并且当您想要实现在现实世界中移动机器人的代码时也可以使用这些信息。

一、背景

控制器节点提供了一个方便的界面来控制机器人的关节。 当机器人的关节暴露在外时,您可以发送命令,它们会将当前状态转换为所需状态。 控制器节点分为三组:力、速度和位置。 每个控制器都会根据这个类型修改状态。

控制器节点与机器人的硬件接口进行通信。 该硬件接口又是一个中间层,代表模拟机器人,例如机器人。 在gazebo,或一个真正的机器人。 因此,一旦模拟运行起来,理论上只需要提供一个与模拟控制器具有相同接口的硬件控制器即可。 而且,这使您可以在真实环境中移动机器人,并使用 Gazebo 查看实时模拟。

控制器随 ros-control 包一起提供,它提供的功能比这里描述的要多得多。 有关 ros-control 的完整概述,请查看官方文档。

二、概述:在 Gazebo 中公开控制器节点

显式公开控制器节点涉及多个步骤。 大致按照官方文档、ros control demo repository和我自己的经验,这些是:
1.依赖管理
(1)将依赖项添加到包 XML
2.URDF模型更新
(1)为每个关节添加标签
(2)添加ROS2硬件插件
(3)添加 gazebo-ros 插件
3.Controller节点配置及启动
(1)提供控制器配置
(2)为控制器节点定义启动脚本

第1步:依赖管理

将以下依赖项添加到您的 package.xml

  <depend>urdf</depend>
  <depend>angles</depend>
  <depend>gazebo_dev</depend>
  <depend>gazebo_ros</depend>
  <depend>controller_manager</depend>
  <depend>hardware_interface</depend>
  <depend>pluginlib</depend>
  <depend>std_msgs</depend>
  <depend>joint_state_publisher</depend>
  <depend>robot_state_publisher</depend>
  <depend>gazebo_ros_pkgs</depend>
  <depend>ros2launch</depend>

并安装它们:

rosdep install --from-paths ./ -i -y --rosdistro foxy       --ignore-src
#All required rosdeps installed successfully

另外,确保安装了 ros2 控制包。

apt-get install ros-foxy-ros2-control ros-foxy-ros2-controllers

第2步:URDF 模型更新

(1)在您的 URDF 模型中添加传输标签。
控制器节点需要通过作用力、速度或位置接口访问关节。 对于每个关节,决定要公开哪个接口,然后提供额外的传输标签。
下面是一个示例,说明如何向我的机器人的前轮关节添加一个作用力接口。

<ros2_control name="GazeboSystem" type="system">
  <transmission name="base_link_left_wheel_frontside_transmission">
    <type>transmission_interface/SimpleTransmission</type>
    <joint name="base_link_left_wheel_frontside">
      <hardwareInterface>EffortJointInterface</hardwareInterface>
    </joint>
    <actuator name="base_link_left_wheel_frontside_motor">
      <hardwareInterface>EffortJointInterface</hardwareInterface>
      <mechanicalReduction>1</mechanicalReduction>
    </actuator>
  </transmission>
</ros2_control>

为了使这个 - 以及所有其他以下更改 - 更可行,我定义了额外的 XACRO 宏。 该宏提供了一个transmission块接头。 您始终如上所示包含 joint_state_controller,然后以 joint_name + _position_controller 的形式创建一个部分。
(2)添加硬件插件
URDF 模型需要指示 ROS2 系统使用哪个硬件插件可以访问机器人。 出于模拟目的,您使用以下内容。 请注意,您需要将其包含在与上面相同的 <ros2_control> 标记中。

<ros2_control name="GazeboSystem" type="system">
  <hardware>
    <plugin>gazebo_ros2_control/GazeboSystem</plugin>
  </hardware>
</ros2_control>

(3)添加 Gazebo ROS 插件
要在模拟中与机器人进行交互,需要添加专用的gazebo-ros插件,并配置机器人描述的主题名称、机器人的命名空间、机器人描述所在的节点名称, 以及指向机器人配置文件的链接(在下一节中介绍)。

<gazebo>
  <plugin filename="libgazebo_ros2_control.so" name="gazebo_ros2_control">
    <robot_param>robot_description</robot_param>
    <robot_namespace>box_bot</robot_namespace>
    <robot_param_node>robot_state_publisher</robot_param_node>
    <parameters>$(find radu_bot)/config/controller.yaml</parameters>
  </plugin>
</gazebo>

第3步:控制器节点配置和启动

(1)提供控制器配置文件
控制器配置文件定义了您要使用的控制器类型,以及可以通过哪种控制器类型连接哪些关节。 以下 config/controller.yaml 文件声明使用力和速度控制器,并且每个控制器访问所有关节。

controller_manager:
  ros__parameters:
    update_rate: 100 #Hz

    joint_state_broadcaster:
      type: joint_state_broadcaster/JointStateBroadcaster

    joint_state_controller:
      type: joint_state_controller/JointStateController

    effort_controllers:
      type: effort_controllers/JointGroupEffortController

    velocity_controller:
      type: velocity_controllers/JointGroupVelocityController

effort_controllers:
  ros__parameters:
    joints:
      - base_link_right_wheel_frontside
      - base_link_left_wheel_frontside
      - base_link_right_wheel_backside
      - base_link_left_wheel_backside

velocity_controller:
  ros__parameters:
    joints:
      - base_link_right_wheel_frontside
      - base_link_left_wheel_frontside
      - base_link_right_wheel_backside
      - base_link_left_wheel_backside

(2)为控制器节点定义启动脚本
最后一步是创建启动文件。 以下脚本启动三个节点:ros2 控制节点,它将读取控制器配置文件并创建定义的控制器接口服务/主题,以及用于发布关节状态和机器人状态的节点。

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions import IncludeLaunchDescription
from launch.conditions import IfCondition
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node

from time import sleep
import filecmp

package_name = 'radu_bot'
world_file = 'empty.world'

import xacro

def generate_launch_description():

    pkg_gazebo_ros = get_package_share_directory('gazebo_ros')
    pkg_radu_simulation = get_package_share_directory(package_name)

    robot_description_path =  os.path.join(
        pkg_radu_simulation,
        "urdf2",
        "gazebo.xacro",
    )

    robot_description = {"robot_description": xacro.process_file(robot_description_path).toxml()}

    controller_config = os.path.join(
        pkg_radu_simulation,
        "config",
        "controller.yaml",
    )

    print("MODEL %s" % robot_description['robot_description'])
    sleep(3)
    print("Config %s" % open(controller_config, 'r').read())

    control_node = Node(
        package="controller_manager",
        executable="ros2_control_node",
        parameters=[robot_description, controller_config],
        output="both",
    )

    joint_state_publisher_node = Node(
        package='joint_state_publisher',
        executable='joint_state_publisher',
        name='joint_state_publisher'
    )

    robot_state_publisher_node = Node(
        package="robot_state_publisher",
        executable="robot_state_publisher",
        output="both",
        parameters=[robot_description],
    )

    return LaunchDescription([
      control_node,
      joint_state_publisher_node,
      robot_state_publisher_node
    ])

(3)把它们放在一起
顺序很重要——Gazebo、控制器、机器人描述需要以精确的顺序进行交互。 做到这一点非常困难。 因此,我使用 ros2 演示库进行比较。 该项目提供了一个 Docker 容器,其中包括带有 ROS2 foxy 的完整 Ubuntu 运行时、所有必需的插件以及机器人的描述和 Gazebo 模拟配置。 启动此容器后,我会看到以下日志消息。

[INFO] [gzserver-1]: process started with pid [31]
[INFO] [robot_state_publisher-2]: process started with pid [34]
[robot_state_publisher-2] Parsing robot urdf xml string.
[spawn_entity.py-3] [INFO] [1622572355.263095787] [spawn_entity]: Spawn Entity started
[spawn_entity.py-3] [INFO] [1622572358.704011723] [spawn_entity]: Spawn status: SpawnEntity: Successfully spawned entity [cartpole]
[gzserver-1] [INFO] [1622572358.886969317] [gazebo_ros2_control]: Loading gazebo_ros2_control plugin
[gzserver-1] [INFO] [1622572358.896913314] [gazebo_ros2_control]: Starting gazebo_ros2_control plugin in namespace: /
[gzserver-1] [INFO] [1622572358.898607083] [gazebo_ros2_control]: Starting gazebo_ros2_control plugin in ros 2 node: gazebo_ros2_control
[gzserver-1] [INFO] [1622572358.899384425] [gazebo_ros2_control]: Loading parameter file /home/ros2_ws/install/share/gazebo_ros2_control_demos/config/cartpole_controller.yaml
[gzserver-1] [INFO] [1622572360.067497363] [gazebo_ros2_control]: connected to service!! robot_state_publisher
[gzserver-1] [INFO] [1622572360.075006386] [gazebo_ros2_control]: Recieved urdf from param server, parsing...
[gzserver-1] [INFO] [1622572360.207253145] [gazebo_ros2_control]: Loading joint: slider_to_cart
[gzserver-1] [INFO] [1622572360.207419217] [gazebo_ros2_control]:  Command:
[gzserver-1] [INFO] [1622572360.207595559] [gazebo_ros2_control]:    position
[gzserver-1] [INFO] [1622572360.211177069] [gazebo_ros2_control]:  State:
[gzserver-1] [INFO] [1622572360.211314621] [gazebo_ros2_control]:    position
[gzserver-1] [INFO] [1622572360.213291135] [gazebo_ros2_control]:    velocity
[gzserver-1] [INFO] [1622572360.213430680] [gazebo_ros2_control]:    effort
[gzserver-1] [INFO] [1622572360.221339236] [gazebo_ros2_control]: Loading controller_manager
[gzserver-1] [INFO] [1622572360.297823090] [gazebo_ros2_control]: Loaded gazebo_ros2_control.
[gzserver-1] [INFO] [1622572361.105781106] [controller_manager]: Loading controller 'joint_state_controller'
[gzserver-1] [INFO] [1622572361.192078267] [controller_manager]: Configuring controller 'joint_state_controller'
[ros2-4] Successfully loaded and started controller joint_state_controller

我们看到这些阶段:
–模型已生成
–Gazebo 加载控件插件
–Gazebo 连接到机器人状态发布者
–Gazebo 解析 URDF,检测控制器类型以及它们对哪些关节有效
–控制器管理器加载联合状态控制器

我试图在启动我的应用程序时获得完全相同的状态消息顺序,并通过启动 Gazebo、启动控制器节点、然后生成机器人来成功。 然后,以相反的顺序,URDF 模型将用于启动关节的控制器节点,Gazebo 将注册控制插件。

STARTING ALL NODES
[INFO] [ros2_control_node-1]: process started with pid [12284]
[INFO] [joint_state_publisher-2]: process started with pid [12286]
[INFO] [robot_state_publisher-3]: process started with pid [12288]
[INFO] [ros2-4]: process started with pid [12290]
[INFO] [ros2-5]: process started with pid [12292]
[INFO] [ros2-6]: process started with pid [12294]
[robot_state_publisher-3] Parsing robot urdf xml string.
[robot_state_publisher-3] The root link base_link has an inertia specified in the URDF, but KDL does not support a root link with an inertia.  As a workaround, you can add an extra dummy link to your URDF.
[robot_state_publisher-3] Link left_wheel_backside had 0 children
[robot_state_publisher-3] Link left_wheel_frontside had 0 children
[robot_state_publisher-3] Link right_wheel_backside had 0 children
[robot_state_publisher-3] Link right_wheel_frontside had 0 children
[robot_state_publisher-3] [INFO] [1622905120.355071330] [robot_state_publisher]: got segment base_link
[robot_state_publisher-3] [INFO] [1622905120.355477881] [robot_state_publisher]: got segment left_wheel_backside
[robot_state_publisher-3] [INFO] [1622905120.355543125] [robot_state_publisher]: got segment left_wheel_frontside
[robot_state_publisher-3] [INFO] [1622905120.355576706] [robot_state_publisher]: got segment right_wheel_backside
[robot_state_publisher-3] [INFO] [1622905120.355609645] [robot_state_publisher]: got segment right_wheel_frontside
[ros2_control_node-1] [INFO] [1622905120.818789225] [controller_manager]: update rate is 100 Hz Hz
[ros2_control_node-1] [INFO] [1622905125.182432589] [controller_manager]: Loading controller 'velocity_ controller'
[ros2_control_node-1] [INFO] [1622905125.241460316] [controller_manager]: Configuring controller 'velocity_controller'
[ros2_control_node-1] [INFO] [1622905125.243706806] [velocity_controller]: configure successful
[ros2_control_node-1] [INFO] [1622905125.252504529] [controller_manager]: Loading controller 'effort_controllers'
[ros2-6] deprecated warning: Please use 'load_controller --set_state start'
[ros2-6] Successfully loaded and started controller velocity_controller
[ros2_control_node-1] [INFO] [1622905125.342950455] [controller_manager]: Configuring controller 'effort_controllers'
[ros2_control_node-1] [INFO] [1622905125.346626669] [effort_controllers]: configure successful
[ros2-5] deprecated warning: Please use 'load_controller --set_state start'
[ros2-5] Successfully loaded and started controller effort_controllers
[ros2_control_node-1] [INFO] [1622905125.410014821] [controller_manager]: Loading controller 'joint_state_controller'
[ros2_control_node-1] [INFO] [1622905125.528520009] [controller_manager]: Configuring controller 'joint_state_controller'
[ros2-4] deprecated warning: Please use 'load_controller --set_state start'
[ros2-4] Successfully loaded and started controller joint_state_controller
[INFO] [ros2-5]: process has finished cleanly [pid 12292]
[INFO] [ros2-6]: process has finished cleanly [pid 12294]
[INFO] [ros2-4]: process has finished cleanly [pid 12290]
[joint_state_publisher-2] [INFO] [1622905126.082525692] [joint_state_publisher]: Waiting for robot_description to be published on the robot_description topic...

这看起来不错——所有节点都已启动,没有错误消息。 我们将看到几个新主题——/velocity_controller、/effort_controller 和 /controller_manager。

让我们向控制器发布一个速度和一个努力命令:

ros2topic pub /velocity_controller/commands  std_msgs/msg/Float64MultiArray "data:
- 0.5
- 0.5
- 0.0
- 0.0"

ros2topic pub /effort_controllers/commands  std_msgs/msg/Float64MultiArray "data:
- 0.5
- 0.5
- 0.0
- 0.0"

命令已正确处理。 但是正如介绍中所述,机器人不会自行在模拟中移动,您需要另一个节点来解释这些命令并与 Gazebo 模拟交互以移动机器人。 我们可以自己写这个,例如 作为 Python 脚本。 这就是插件的作用,ros-control自带了一套执行器和传感器的插件。 这将在下一篇文章中探讨。

结论

要在节点中控制机器人,您可以明确定义类型为力、速度和位置的控制器。 这些控制器接受命令并访问通用硬件接口来指示机器人。 理论上,这些控制节点可以访问 Gazebo 模拟中的机器人 - 通过使用 ros-control 插件 - 或者在您提供接口代码时访问真实的机器人。 本文展示了如何定义和发布显式控制器节点。 您需要修改机器人的 URDF 模型,添加特殊的 、硬件和 Gazebo 插件。 其次,您需要提供控制器配置文件和启动文件。 第三,您需要按特定顺序启动节点。 但是,要在模拟中实际移动机器人,您需要自定义脚本来将命令从命令节点转换为您的机器人。 大多数 ROS 模拟明确为此目的使用插件,我们将在下一篇文章中探讨插件。

参考文献:

[1] https://admantium.com/blog/ros08_control_nodes_in_ros/
注:根据参考文献翻译而来,仅供个人学习参考使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS自学实践(15):ROS2控制仿真车辆 的相关文章

随机推荐

  • 静态代码检查-Sonar-环境安装(一)

    1 前提 1 安装mysql数据库 5 6以上版本 本人数据库版本5 7 2 安装jdk1 8 本人jdk版本1 8 2 官网下载 https www sonarqube org downloads 最新版本6 7稳定版 选择 Show a
  • 密码学 / 哈希算法

    一 诞生原因 在日常生活中 每个人去银行 坐火车都需要身份证证明自己的身份 身份证存在的目的就是要证明我真的是我 同样在网络中 一个文件是否被改过 更改之后就是新的文件 需要一个 身份证 证明 这里就需要了 hash 算法了 二 特点 为了
  • 黑马并发笔记

    参考这个就好 https www yuque com gaohanghang sgrbwh wng754 这个也不错 https blog csdn net weixin 50280576 article details 113033975
  • 开放加速规范AI服务器设计指南

    近日 在2023年开放计算社区中国峰会 OCP China Day 2023 上 开放加速规范AI服务器设计指南 以下简称 指南 发布 指南 面向生成式AI应用场景 进一步发展和完善了开放加速规范AI服务器的设计理论和设计方法 将助力社区成
  • Linux内存管理:ARM Memory Layout以及mmu配置

    http blog csdn net hongzg1982 article details 47341881 在内核进行page初始化以及mmu配置之前 首先需要知道整个memory map 1 ARM Memory Layout PAGE
  • Adobe Photoshop 2022版 功能介绍及使用技巧

    目录 版本介绍 使用技巧 截图展示 分享 版本介绍 Adobe Photoshop 2022是Adobe公司的一款专业的图像处理软件 它提供了强大的图像处理功能 从色彩调整 图层处理到高级合成等功能 新版本带来的一些更新包括 1 人工智能辅
  • Angular的自动化测试

    当Angular项目的规模到达一定的程度 就需要进行测试工作了 本文着重介绍关于ng的测试部分 主要包括以下三个方面 框架的选择 Karma Jasmine 测试的分类和选择 单元测试 端到端测试 在ng中各个模块如何编写测试用例 下面各部
  • Unity的C#编程教程_36_while循环语句

    do while 循环 首先执行用于循环的程序块 再进行条件判断 判断为真则再次运行程序块 直到判定为假 跳出循环 比如数数程序 using System Collections using System Collections Gener
  • Shell文本处理三剑客之awk

    本章大纲 8 3 awk awk是一个处理文本的编程语言工具 能用简短的程序处理标准输入或文件 数据排序 计算以及生成报表等等 在Linux系统下默认awk是gawk 它是awk的GNU版本 可以通过命令查看应用的版本 ls l bin a
  • 开放封闭原则(Open Closed Principle)

    在面向对象的设计中有很多流行的思想 比如说 所有的成员变量都应该设置为私有 Private 要避免使用全局变量 Global Variables 使用运行时类型识别 RTTI Run Time Type Identification 例如
  • 阿里测试

    今天我们看到的阿里巴巴提供的任何一项服务后边都有着无数子系统和组件的支撑 子系统之间也互相依赖关联 其中任意一个环节出现问题都可能对上游链路产生影响 小明做为新人接收到的第一个任务就是去梳理所有的依赖关系 小明和每个系统的负责人确认了依赖关
  • pycharm tips、快捷键及一些常用设置

    转自 http blog csdn net pipisorry article details 39909057 pycharm Learning tips pythoncharm help tip of the day A special
  • 如何快速入门一个陌生领域?

    嗨 大家好 我是痴海 过去的一个月我从零制作了人生第一个长视频 并且在前天发布了 这个视频制作的过程非常不易 但最终呈现的效果还是不错的 视频有不错的质感 并且整体的节奏也不错 大家可以通过下面的链接进行查看 10 分钟看懂计算机是如何运行
  • 东北大学c++实验最后一次

    问题描述 建立两个磁盘文件f1 txt和f2 txt 编写程序实现以下工作 1 从文件in txt输入20个整数 分别存放在两个磁盘文件f1 txt和f2 txt中 每个文件中放10个整数 2 从f1 txt读入10个数 然后存放到f2 t
  • 将写好的java代码打包成jar包并且运行

    一 前言 今天那记录一下jar包的打包以及运行的过程 还是老样子大佬勿喷有问题求告知 谢谢啦 二 直奔主题 1 首先通过idea写一段简单的Java代码如下图所示 2 写好后我们找到如下图的图标 点击进去 这个图标主要是进行项目结构设计 3
  • android 给ListView的divider设置左右padding

    android 给ListView的divider设置左右padding 解决方案 1 利用inset xml标签 在res drawable文件夹下新建listview divider xml文件
  • vue2.x+ts项目,在props type导入自定义接口类型报‘xxx‘ only refers to a type, but is being used as a value here处理办法

    一 报错 xxx only refers to a type but is being used as a value here 在Props中使用自定义类型约束时 报上面的错误 然后 我在网上查找教程 找到一个说在ts中导出class 接
  • Python必会的单元测试框架 —— unittest

    用Python搭建自动化测试框架 我们需要组织用例以及测试执行 这里博主推荐Python的标准库 unittest unittest是xUnit系列框架中的一员 如果你了解xUnit的其他成员 那你用unittest来应该是很轻松的 它们的
  • 【Linux】PXE安装指导

    1 引言 1 1 简介 PXE 的全称是 preboot execute environment 也被称为预执行环境 提供了一种使用网络接口 NetworkInterface 启动计算机的机制 这种机制让计算机的启动可以不依赖本地数据存储设
  • ROS自学实践(15):ROS2控制仿真车辆

    我们的目标是拥有一个可以在环境中移动的机器人的完全工作 可控的表示 有两种方法可以实现这个目标 显式公开控制器节点并使用它们 本文的重点 或者使用预定义的 Gazebo 插件来为您完成繁重的工作 在本文中 我介绍了如何配置 URDF 模型和