ROS系列:第六章 机器人建模

news2024/12/24 10:28:09

文章目录

  • 六、机器人系统仿真
    • 1.概述
      • 仿真优势:
      • 仿真缺陷:
    • 2. URDF集成Rviz基本流程
        • 1.创建功能包,导入依赖
        • 2.编写 URDF 文件
        • 3.在 launch 文件中集成 URDF 与 Rviz
        • 4.在 Rviz 中显示机器人模型
        • 5.优化 rviz 启动
    • 3. URDF语法详解
      • 3.1 URDF语法详解01_robot
        • robot
        • 1.属性
        • 2.子标签
      • 3.2 URDF语法详解02_link
        • link
        • 1.属性
        • 2.子标签
      • 3.3 URDF语法详解03_joint
        • joint
        • 1.属性
        • 2.子标签
      • 3.4 URDF练习
        • 1.新建urdf以及launch文件
      • 3.5 URDF工具
        • 1.check_urdf 语法检查
        • 2.urdf_to_graphiz 结构查看
    • 4. URDF优化_xacro
      • 4.1 Xacro_快速体验
        • 1.Xacro文件编写
        • 2.Xacro文件转换成 urdf 文件
      • 4.2 Xacro_语法详解
        • 1.属性与算数运算
        • 2.宏
        • 3.文件包含
      • 4.3 Xacro_完整使用流程示例
        • 1.编写 Xacro 文件
        • 2.集成launch文件
      • 4.4 URDF语法详解01_robot
        • 1.摄像头和雷达 Xacro 文件实现
        • 2.组合底盘摄像头与雷达的 xacro 文件
        • 3.launch 文件
    • 5.Rviz中控制机器人模型运动
        • 1.安装 Arbotix
        • 2.创建新功能包,准备机器人 urdf、xacro
        • 3.添加 arbotix 所需的配置文件
        • 4.launch 文件中配置 arbotix 节点
        • 5.启动 launch 文件并控制机器人模型运动
    • 6.URDF集成Gazebo
      • 6.1URDF与Gazebo基本集成流程
        • 1.创建功能包
        • 2.编写URDF文件
        • 3.启动Gazebo并显示模型
      • 6.2 URDF集成Gazebo相关设置
        • 1.collision
        • 2.inertial
        • 3.颜色设置
      • 6.3 URDF集成Gazebo实操**需求描述:**
        • 1.编写封装惯性矩阵算法的 xacro 文件
        • 2.复制相关 xacro 文件,并设置 collision inertial 以及 color 等参数
          • **A.底盘 Xacro 文件**
          • B.摄像头 Xacro 文件
          • C.雷达 Xacro 文件
          • D.组合底盘、摄像头与雷达的 Xacro 文件
        • 3.在 gazebo 中执行
      • 6.4 Gazebo仿真环境搭建
        • 1.添加内置组件创建仿真环境
          • 1.1启动 Gazebo 并添加组件
          • 1.2保存仿真环境
          • 1.3 启动
        • 2.自定义仿真环境
          • 2.1 启动 gazebo 打开构建面板,绘制仿真环境
          • 2.2 保存构建的环境
          • 2.3 保存为 world 文件
          • 2.4 启动
        • 3.使用官方提供的插件
          • 3.1 下载官方模型库
          • 3.2 将模型库复制进 gazebo
          • 3.3 应用
    • 7 URDF、Gazebo与Rviz综合应用
      • 7.1 机器人运动控制以及里程计信息显示
        • 1.ros_control 简介
        • 2.运动控制实现流程(Gazebo)
          • 2.1 为 joint 添加传动装置以及控制器
          • 2.2 添加xacro文件
          • 2.3 xacro文件集成
          • 2.4 启动 gazebo并控制机器人运动
        • 3.Rviz查看里程计信息
          • 3.1启动 Rviz
          • 3.2 添加组件
    • 8.本章小结

六、机器人系统仿真

1.概述

**机器人系统仿真:**是通过计算机对实体机器人系统进行模拟的技术,在 ROS 中,仿真实现涉及的内容主要有三:对机器人建模(URDF)、创建仿真环境(Gazebo)以及感知环境(Rviz)等系统性实现。

仿真优势:

仿真在机器人系统研发过程中占有举足轻重的地位,在研发与测试中较之于实体机器人实现,仿真有如下几点的显著优势:

1.**低成本:**当前机器人成本居高不下,动辄几十万,仿真可以大大降低成本,减小风险

2.**高效:**搭建的环境更为多样且灵活,可以提高测试效率以及测试覆盖率

3.**高安全性:**仿真环境下,无需考虑耗损问题

仿真缺陷:

机器人在仿真环境与实际环境下的表现差异较大,换言之,仿真并不能完全做到模拟真实的物理世界,存在一些"失真"的情况,原因:

1.仿真器所使用的物理引擎目前还不能够完全精确模拟真实世界的物理情况

2.仿真器构建的是关节驱动器(电机&齿轮箱)、传感器与信号通信的绝对理想情况,目前不支持模拟实际硬件缺陷或者一些临界状态等情形

2. URDF集成Rviz基本流程

需求描述:

在 Rviz 中显示一个盒状机器人

实现流程:

  1. 准备:新建功能包,导入依赖
  2. 核心:编写 urdf 文件
  3. 核心:在 launch 文件集成 URDF 与 Rviz
  4. 在 Rviz 中显示机器人模型

1.创建功能包,导入依赖

创建一个新的功能包,名称自定义,导入依赖包:urdfxacro

在当前功能包下,再新建几个目录:

urdf: 存储 urdf 文件的目录

meshes:机器人模型渲染文件(暂不使用)

config: 配置文件

launch: 存储 launch 启动文件

2.编写 URDF 文件

新建一个子级文件夹:urdf(可选),文件夹中添加一个.urdf文件,复制如下内容:

<robot name="mycar">
    <link name="base_link">
        <visual>
            <geometry>
                <box size="0.5 0.2 0.1" />
            </geometry>
        </visual>
    </link>
</robot>
Copy

3.在 launch 文件中集成 URDF 与 Rviz

launch目录下,新建一个 launch 文件,该 launch 文件需要启动 Rviz,并导入 urdf 文件,Rviz 启动后可以自动载入解析urdf文件,并显示机器人模型,核心问题:如何导入 urdf 文件? 在 ROS 中,可以将 urdf 文件的路径设置到参数服务器,使用的参数名是:robot_description,示例代码如下:

<launch>

    <!-- 设置参数 -->
    <param name="robot_description" textfile="$(find 包名)/urdf/urdf/urdf01_HelloWorld.urdf" />

    <!-- 启动 rviz -->
    <node pkg="rviz" type="rviz" name="rviz" />

</launch>
Copy

4.在 Rviz 中显示机器人模型

rviz 启动后,会发现并没有盒装的机器人模型,这是因为默认情况下没有添加机器人显示组件,需要手动添加,添加方式如下:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2XO1iRYZ-1670239754316)(http://www.autolabor.com.cn/book/ROSTutorials/assets/01_URDF%E6%96%87%E4%BB%B6%E6%89%A7%E8%A1%8Crviz%E9%85%8D%E7%BD%AE01.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8XRxLmmk-1670239754320)(http://www.autolabor.com.cn/book/ROSTutorials/assets/02_URDF%E6%96%87%E4%BB%B6%E6%89%A7%E8%A1%8Crviz%E9%85%8D%E7%BD%AE02.png)]在这里插入图片描述

设置完毕后,可以正常显示了

5.优化 rviz 启动

重复启动launch文件时,Rviz 之前的组件配置信息不会自动保存,需要重复执行步骤4的操作,为了方便使用,可以使用如下方式优化:

首先,将当前配置保存进config目录[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hkr2wM0H-1670239754330)(http://www.autolabor.com.cn/book/ROSTutorials/assets/10_rviz%E9%85%8D%E7%BD%AE%E4%BF%9D%E5%AD%98.png)]
然后,launch文件中 Rviz 的启动配置添加参数:args,值设置为-d 配置文件路径

<launch>
    <param name="robot_description" textfile="$(find 包名)/urdf/urdf/urdf01_HelloWorld.urdf" />
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find 报名)/config/rviz/show_mycar.rviz" />
</launch>
Copy

再启动时,就可以包含之前的组件配置了,使用更方便快捷。

3. URDF语法详解

  • robot 根标签,类似于 launch文件中的launch标签
  • link 连杆标签
  • joint 关节标签
  • gazebo 集成gazebo需要使用的标签

3.1 URDF语法详解01_robot


robot

urdf 中为了保证 xml 语法的完整性,使用了robot标签作为根标签,所有的 link 和 joint 以及其他标签都必须包含在 robot 标签内,在该标签内可以通过 name 属性设置机器人模型的名称

1.属性

name: 指定机器人模型的名称

2.子标签

其他标签都是子级标签

3.2 URDF语法详解02_link


link

urdf 中的 link 标签用于描述机器人某个部件(也即刚体部分)的外观和物理属性,比如: 机器人底座、轮子、激光雷达、摄像头…每一个部件都对应一个 link, 在 link 标签内,可以设计该部件的形状、尺寸、颜色、惯性矩阵、碰撞参数等一系列属性[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sKElfjJs-1670239754331)(http://www.autolabor.com.cn/book/ROSTutorials/assets/%E5%AE%98%E6%96%B901_link.png)]

1.属性

  • name —> 为连杆命名

2.子标签

  • visual —> 描述外观(对应的数据是可视的)
    • geometry 设置连杆的形状
      • 标签1: box(盒状)
        • 属性:size=长(x) 宽(y) 高(z)
      • 标签2: cylinder(圆柱)
        • 属性:radius=半径 length=高度
      • 标签3: sphere(球体)
        • 属性:radius=半径
      • 标签4: mesh(为连杆添加皮肤)
        • 属性: filename=资源路径(格式:package:文件)
    • origin 设置偏移量与倾斜弧度
      • 属性1: xyz=x偏移 y便宜 z偏移
      • 属性2: rpy=x翻滚 y俯仰 z偏航 (单位是弧度)
    • metrial 设置材料属性(颜色)
      • 属性: name
      • 标签: color
        • 属性: rgba=红绿蓝权重值与透明度 (每个权重值以及透明度取值[0,1])
  • collision —> 连杆的碰撞属性
  • Inertial —> 连杆的惯性矩阵

3.3 URDF语法详解03_joint


joint

urdf 中的 joint 标签用于描述机器人关节的运动学和动力学属性,还可以指定关节运动的安全极限,机器人的两个部件(分别称之为 parent link 与 child link)以"关节"的形式相连接,不同的关节有不同的运动形式: 旋转、滑动、固定、旋转速度、旋转角度限制…,比如:安装在底座上的轮子可以360度旋转,而摄像头则可能是完全固定在底座上。

joint标签对应的数据在模型中是不可见的[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-44yTaDfi-1670239754332)(http://www.autolabor.com.cn/book/ROSTutorials/assets/%E5%AE%98%E6%96%B902_link.png)]

1.属性

  • name —> 为关节命名
  • type —> 关节运动形式
    • continuous: 旋转关节,可以绕单轴无限旋转
    • revolute: 旋转关节,类似于 continues,但是有旋转角度限制
    • prismatic: 滑动关节,沿某一轴线移动的关节,有位置极限
    • planer: 平面关节,允许在平面正交方向上平移或旋转
    • floating: 浮动关节,允许进行平移、旋转运动
    • fixed: 固定关节,不允许运动的特殊关节

2.子标签

  • parent(必需的)

    parent link的名字是一个强制的属性:

    • link:父级连杆的名字,是这个link在机器人结构树中的名字。
  • child(必需的)

    child link的名字是一个强制的属性:

    • link:子级连杆的名字,是这个link在机器人结构树中的名字。
  • origin

    • 属性: xyz=各轴线上的偏移量 rpy=各轴线上的偏移弧度。
  • axis

    • 属性: xyz用于设置围绕哪个关节轴运动。

3.4 URDF练习


需求描述:

创建一个四轮圆柱状机器人模型,机器人参数如下,底盘为圆柱状,半径 10cm,高 8cm,四轮由两个驱动轮和两个万向支撑轮组成,两个驱动轮半径为 3.25cm,轮胎宽度1.5cm,两个万向轮为球状,半径 0.75cm,底盘离地间距为 1.5cm(与万向轮直径一致)

预期结果演示:img

1.新建urdf以及launch文件

urdf 文件:基本实现

<robot name="mycar">
    <!-- <优化项> -->
    <link name="base_footprint">
        <!-- <可视化标签> -->
        <visual>
            <!-- <1.形状> -->
            <geometry>
                <sphere radius="0.001"/>
            </geometry>
        </visual>
    </link>
    <!-- <底盘> -->
    <link name="base_link">
        <!-- <可视化标签> -->
        <visual>
            <!-- <1.形状> -->
            <geometry>
                <!-- <1.1立方体 长宽高>  -->
                <!-- <box size="0.5 0.2 0.1"/> -->
                <!-- <1.2圆柱 半径、高度> -->
                <cylinder radius="0.1" length="0.08"/>
                <!-- <1.3球体 半径> -->
                <!-- <sphere radius="2"/> -->
                <!-- <1.4皮肤> -->
                <!-- <mesh filename="package://urdf01_rviz/meshes/autolabor_mini.stl" /> -->
            </geometry>
            <!-- <2.偏移量与倾斜弧度> -->
            <!-- <xyz坐标 rpy旋转角度3.14=180度 1.57=90度翻滚、俯仰、偏航> -->
            <!-- <无特殊情况不要在此处对xyz进行操作,影响后期TF坐标变换,可在下方joint操作 rpy可以操作> -->
            <origin xyz="0.0 0.0 0.0" rpy="0.0  0.0 0.0"/>
            <!-- <3.颜色>red green blue a透明度 取值范围[0,1]-->
            <material name="baselink_color">
                <color rgba="0.7 0.3 0.2 0.8"/>
            </material>
        </visual>
    </link>
    <!-- <joint关节 关联footprint & baselink> -->
    <joint name="baselink2basefootprint" type="fixed">
        <!-- <设置偏移量> -->
        <origin xyz="0.0 0.0 0.055" rpy="0.0 0.0 0.0"/>
        <!-- <父级 link> -->
        <parent link="base_footprint"/>
        <!-- <子级 link> -->
        <!-- <关节z偏移量 = 车体高度/2 + 离地间距 > -->
        <child link="base_link"/>
        <!-- <fixed不需要设置关节旋转参考的坐标轴> -->
        <!-- <axis xyz="0.0 0.0 0.0"/> -->
        <!-- <limit lower="0.0" upper="0.0" effort="0.0" velocity="0.0"/> -->
    </joint>

    <!-- <驱动轮01> -->
    <link name="left_Wheel">
        <!-- <可视化标签> -->
        <visual>
            <!-- <1.形状> -->
            <geometry>
                <!-- <1.1立方体>  -->
                <!-- <box size="0.02 0.05 0.05"/> -->
                <!-- <1.2圆柱> -->
                <cylinder radius="0.0325" length="0.015"/>
                <!-- <1.3球体> -->
                <!-- <sphere radius="0.0075"/> -->
                <!-- <1.4皮肤> -->
                <!-- <mesh filename="package://urdf01_rviz/meshes/autolabor_mini.stl" /> -->
            </geometry>
            <!-- <2.偏移量与倾斜弧度> -->
            <!-- <xyz坐标 rpy旋转角度3.14=180度 1.57=90度翻滚、俯仰、偏航> -->
            <!-- <先使用默认后期要修改 为防止下沉应该上移动一半的高度> -->
            <!-- <无特殊情况不要在此处对xyz进行操作,影响后期TF坐标变换,可在下方joint操作 rpy可以操作> -->
            <origin xyz="0.0 0.0 0.0" rpy="1.5708 0.0 0.0"/>
            <!-- <3.颜色>red green blue a透明度 取值范围[0,1]-->
            <material name="Whell03_color">
                <color rgba="0.0 0.0 0.0 0.8"/>
            </material>
        </visual>
    </link>
    <!-- <joint关节  关联baselink& Wheel_01> -->
    <joint name="LeftWheel2baselink" type="continuous">
        <!-- <设置偏移量> -->
        <!-- <
            x 无偏移
            y 车体半径
            z 车体高度/2 + 离地 - 车轮半径
    
        > -->
        <origin xyz="0.0 0.1 -0.0225" rpy="0.0 0.0 0.0"/>
        <!-- <父级 link> -->
        <parent link="base_link"/>
        <!-- <子级 link> -->
        <child link="left_Wheel"/>
        <!-- <设置关节旋转参考的坐标轴> -->
        <axis xyz="0.0 1.0 0.0"/>
        <!-- <limit lower="0.0" upper="0.0" effort="0.0" velocity="0.0"/> -->
    </joint>

    <!-- <驱动轮02> -->
    <link name="right_Wheel">
        <!-- <可视化标签> -->
        <visual>
            <!-- <1.形状> -->
            <geometry>
                <!-- <1.1立方体>  -->
                <!-- <box size="0.02 0.05 0.05"/> -->
                <!-- <1.2圆柱> -->
                <cylinder radius="0.0325" length="0.015"/>
                <!-- <1.3球体> -->
                <!-- <sphere radius="0.0075"/> -->
                <!-- <1.4皮肤> -->
                <!-- <mesh filename="package://urdf01_rviz/meshes/autolabor_mini.stl" /> -->
            </geometry>
            <!-- <2.偏移量与倾斜弧度> -->
            <!-- <xyz坐标 rpy旋转角度3.14=180度 1.57=90度翻滚、俯仰、偏航> -->
            <!-- <先使用默认后期要修改 为防止下沉应该上移动一半的高度> -->
            <!-- <无特殊情况不要在此处对xyz进行操作,影响后期TF坐标变换,可在下方joint操作 rpy可以操作> -->
            <origin xyz="0.0 0.0 0.0" rpy="1.5708 0.0 0.0"/>
            <!-- <3.颜色>red green blue a透明度 取值范围[0,1]-->
            <material name="Whell03_color">
                <color rgba="0.0 0.0 0.0 0.8"/>
            </material>
        </visual>
    </link>
    <!-- <joint关节  关联baselink& Wheel_02> -->
    <joint name="RightWheel2baselink" type="continuous">
        <!-- <设置偏移量> -->
        <!-- <
            x 无偏移
            y 车体半径
            z 车体高度/2 + 离地 - 车轮半径
    
        > -->
        <origin xyz="0.0 -0.1 -0.0225" rpy="0.0 0.0 0.0"/>
        <!-- <父级 link> -->
        <parent link="base_link"/>
        <!-- <子级 link> -->
        <child link="right_Wheel"/>
        <!-- <设置关节旋转参考的坐标轴> -->
        <axis xyz="0.0 1.0 0.0"/>
        <!-- <limit lower="0.0" upper="0.0" effort="0.0" velocity="0.0"/> -->
    </joint>

    <!-- <万向轮01> -->
    <link name="front_Wheel">
        <!-- <可视化标签> -->
        <visual>
            <!-- <1.形状> -->
            <geometry>
                <!-- <1.1立方体>  -->
                <!-- <box size="0.02 0.05 0.05"/> -->
                <!-- <1.2圆柱> -->
                <!-- <cylinder radius="0.0325" length="0.015"/> -->
                <!-- <1.3球体> -->
                <sphere radius="0.0075"/>
                <!-- <1.4皮肤> -->
                <!-- <mesh filename="package://urdf01_rviz/meshes/autolabor_mini.stl" /> -->
            </geometry>
            <!-- <2.偏移量与倾斜弧度> -->
            <!-- <xyz坐标 rpy旋转角度3.14=180度 1.57=90度翻滚、俯仰、偏航> -->
            <!-- <先使用默认后期要修改 为防止下沉应该上移动一半的高度> -->
            <!-- <无特殊情况不要在此处对xyz进行操作,影响后期TF坐标变换,可在下方joint操作 rpy可以操作> -->
            <origin xyz="0.0 0.0 0.0" rpy="0.0  0.0 0.0"/>
            <!-- <3.颜色>red green blue a透明度 取值范围[0,1]-->
            <material name="Whell01_color">
                <color rgba="0.0 0.0 0.0 0.8"/>
            </material>
        </visual>
    </link>
    <!-- <joint关节  关联baselink& Wheel_Universal_01> -->
    <joint name="FrontWheel2baselink" type="continuous">
        <!-- <设置偏移量> -->
        <!-- <
            x 小于车体半径
            y 无偏移
            z 车体高度/2 + 离地 - 车轮半径
    
        > -->
        <origin xyz="0.08 0.0 -0.0475" rpy="0.0 0.0 0.0"/>
        <!-- <父级 link> -->
        <parent link="base_link"/>
        <!-- <子级 link> -->
        <child link="front_Wheel"/>
        <!-- <设置关节旋转参考的坐标轴> -->
        <axis xyz="1.0 1.0 0.0"/>
        <!-- <limit lower="0.0" upper="0.0" effort="0.0" velocity="0.0"/> -->
    </joint>



    <!-- <万向轮02> -->
    <link name="back_Wheel">
        <!-- <可视化标签> -->
        <visual>
            <!-- <1.形状> -->
            <geometry>
                <!-- <1.1立方体>  -->
                <!-- <box size="0.02 0.05 0.05"/> -->
                <!-- <1.2圆柱> -->
                <!-- <cylinder radius="0.0325" length="0.015"/> -->
                <!-- <1.3球体> -->
                <sphere radius="0.0075"/>
                <!-- <1.4皮肤> -->
                <!-- <mesh filename="package://urdf01_rviz/meshes/autolabor_mini.stl" /> -->
            </geometry>
            <!-- <2.偏移量与倾斜弧度> -->
            <!-- <xyz坐标 rpy旋转角度3.14=180度 1.57=90度翻滚、俯仰、偏航> -->
            <!-- <先使用默认后期要修改 为防止下沉应该上移动一半的高度> -->
            <!-- <无特殊情况不要在此处对xyz进行操作,影响后期TF坐标变换,可在下方joint操作 rpy可以操作> -->
            <origin xyz="0.0 0.0 0.0" rpy="0.0  0.0 0.0"/>
            <!-- <3.颜色>red green blue a透明度 取值范围[0,1]-->
            <material name="Whell02_color">
                <color rgba="0.0 0.0 0.0 0.8"/>
            </material>
        </visual>
    </link>
    <!-- <joint关节  关联baselink& Wheel_Universal_02> -->
    <joint name="BackWheel2baselink" type="continuous">
        <!-- <设置偏移量> -->
        <!-- <设置偏移量> -->
        <!-- <
            x 小于车体半径
            y 无偏移
            z 车体高度/2 + 离地 - 车轮半径
    
        > -->
        <origin xyz="-0.08 0.0 -0.0475" rpy="0.0 0.0 0.0"/>
        <!-- <父级 link> -->
        <parent link="base_link"/>
        <!-- <子级 link> -->
        <child link="back_Wheel"/>
        <!-- <设置关节旋转参考的坐标轴> -->
        <axis xyz="1.0 1.0 0.0"/>
        <!-- <limit lower="0.0" upper="0.0" effort="0.0" velocity="0.0"/> -->
    </joint>


</robot>

launch 文件:

<launch>

    <!-- 设置参数 -->
    <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/urdf/demo05_test.urdf" />

    <!-- 启动 rviz -->
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" />

    <!-- 添加关节状态节点 -->
    <!-- <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" /> -->
    <!-- 添加关节运动控制节点(应该在机器人状态发布节点之上防止抖动) -->
    <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" />
    <!-- 添加机器人状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />

</launch>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PmcZuDCE-1670239754335)(C:\Users\昊天\AppData\Roaming\Typora\typora-user-images\1669983533650.png)]

3.5 URDF工具


在 ROS 中,提供了一些工具来方便 URDF 文件的编写,比如:

  • check_urdf命令可以检查复杂的 urdf 文件是否存在语法问题
  • urdf_to_graphiz命令可以查看 urdf 模型结构,显示不同 link 的层级关系

当然,要使用工具之前,首先需要安装,安装命令:sudo apt install liburdfdom-tools

1.check_urdf 语法检查

进入urdf文件所属目录,调用:check_urdf urdf文件,如果不抛出异常,说明文件合法,否则非法

在这里插入图片描述

实验:

在这里插入图片描述

注意右键进入第一个urdf文件夹里才可以tab补全

2.urdf_to_graphiz 结构查看

进入urdf文件所属目录,调用:urdf_to_graphiz urdf文件,当前目录下会生成 pdf 文件

在这里插入图片描述

4. URDF优化_xacro


概念

Xacro 是 XML Macros 的缩写,Xacro 是一种 XML 宏语言,是可编程的 XML。

原理

Xacro 可以声明变量,可以通过数学运算求解,使用流程控制控制执行顺序,还可以通过类似函数的实现,封装固定的逻辑,将逻辑中需要的可变的数据以参数的方式暴露出去,从而提高代码复用率以及程序的安全性。

作用

较之于纯粹的 URDF 实现,可以编写更安全、精简、易读性更强的机器人模型文件,且可以提高编写效率。

4.1 Xacro_快速体验


需求描述:

使用xacro优化上一节案例中驱动轮实现,需要使用变量封装底盘的半径、高度,使用数学公式动态计算底盘的关节点坐标,使用 Xacro 宏封装轮子重复的代码并调用宏创建两个轮子(注意: 在此,演示 Xacro 的基本使用,不必要生成合法的 URDF )。

准备:

创建功能包,导入 urdf 与 xacro。

1.Xacro文件编写

编写 Xacro 文件,以变量的方式封装属性(常量半径、高度、车轮半径…),以函数的方式封装重复实现(车轮的添加)。

<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- <
    1.代码复用     Xacro 宏定义 (函数调用)
    2.参数设计     Xacro 变量
> -->
    <!-- 属性封装 -->
    <xacro:property name="wheel_radius" value="0.0325" />
    <xacro:property name="wheel_length" value="0.0015" />
    <xacro:property name="PI" value="3.1415927" />
    <xacro:property name="base_link_length" value="0.08" />
    <xacro:property name="lidi_space" value="0.015" />

    <!-- 宏 -->
    <xacro:macro name="wheel_func" params="wheel_name flag" >
        <link name="${wheel_name}_wheel">
            <visual>
                <geometry>
                    <cylinder radius="${wheel_radius}" length="${wheel_length}" />
                </geometry>

                <origin xyz="0 0 0" rpy="${PI / 2} 0 0" />

                <material name="wheel_color">
                    <color rgba="0 0 0 0.3" />
                </material>
            </visual>
        </link>

        <!-- 3-2.joint -->
        <joint name="${wheel_name}2link" type="continuous">
            <parent link="base_link"  />
            <child link="${wheel_name}_wheel" />
            <!-- 
                x 无偏移
                y 车体半径
                z z= 车体高度 / 2 + 离地间距 - 车轮半径

            -->
            <origin xyz="0 ${0.1 * flag} ${(base_link_length / 2 + lidi_space - wheel_radius) * -1}" rpy="0 0 0" />
            <axis xyz="0 1 0" />
        </joint>

    </xacro:macro>
    <!-- <调用> -->
    <xacro:wheel_func wheel_name="left" flag="1" />
    <xacro:wheel_func wheel_name="right" flag="-1" />
</robot>

2.Xacro文件转换成 urdf 文件

命令行进入 xacro文件 所属目录,执行:rosrun xacro xacro xxx.xacro > xxx.urdf, 会将 xacro 文件解析为 urdf 文件。

注意: 该案例编写生成的是非法的 URDF 文件,目的在于演示 Xacro 的极简使用以及优点。

4.2 Xacro_语法详解


xacro 提供了可编程接口,类似于计算机语言,包括变量声明调用、函数声明与调用等语法实现。在使用 xacro 生成 urdf 时,根标签robot中必须包含命名空间声明:xmlns:xacro="http://wiki.ros.org/xacro"

1.属性与算数运算

用于封装 URDF 中的一些字段,比如: PAI 值,小车的尺寸,轮子半径 …

属性定义

<xacro:property name="xxxx" value="yyyy" />

属性调用

${属性名称}

算数运算

${数学表达式}

2.宏

类似于函数实现,提高代码复用率,优化代码结构,提高安全性

宏定义

<xacro:macro name="宏名称" params="参数列表(多参数之间使用空格分隔)">

    .....

    参数调用格式: ${参数名}

</xacro:macro>

宏调用

<xacro:宏名称 参数1=xxx 参数2=xxx/>

3.文件包含

机器人由多部件组成,不同部件可能封装为单独的 xacro 文件,最后再将不同的文件集成,组合为完整机器人,可以使用文件包含实现

文件包含

<robot name="xxx" xmlns:xacro="http://wiki.ros.org/xacro">
      <xacro:include filename="my_base.xacro" />
      <xacro:include filename="my_camera.xacro" />
      <xacro:include filename="my_laser.xacro" />
      ....
</robot>

4.3 Xacro_完整使用流程示例


需求描述:

使用 Xacro 优化 URDF 版的小车底盘模型实现

预期结果演示:

img

1.编写 Xacro 文件

<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="mycar">
   
    <xacro:property name="footprint_radius" value="0.001"/>
    
     <link name="base_footprint">
        <!-- <可视化标签> -->
        <visual>
            <!-- <1.形状> -->
            <geometry>
            <sphere radius="${footprint_radius}"/>
            </geometry>
        </visual>
    </link>
    <xacro:property name="base_radius" value="0.1"/>
    <xacro:property name="base_length" value="0.08"/>
    <xacro:property name="lidi" value="0.015"/>
    <xacro:property name="base_joint_z" value="${base_length / 2 + lidi}"/>
    <!-- <底盘> -->
    <link name="base_link">
        <!-- <可视化标签> -->
        <visual>
            <!-- <1.形状> -->
            <geometry>
                <cylinder radius="${base_radius}" length="${base_length}"/>
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0  0.0 0.0"/>
            <material name="baselink_color">
                <color rgba="0.7 0.3 0.2 0.5"/>
            </material>
        </visual>
    </link>
    <!-- <joint关节 关联footprint & baselink> -->
    <joint name="baselink2basefootprint" type="fixed">
        <!-- <设置偏移量> -->
        <origin xyz="0.0 0.0 ${base_joint_z}" rpy="0.0 0.0 0.0"/>
        <!-- <父级 link> -->
        <parent link="base_footprint"/>
        <!-- <子级 link> -->
        <!-- <关节z偏移量 = 车体高度/2 + 离地间距 > -->
        <child link="base_link"/>
    </joint>

    <xacro:property name="wheel_radius" value="0.0325"/>
    <xacro:property name="wheel_length" value="0.015"/>
    <xacro:property name="PI" value="3.1415927"/>
    <!-- <结果是负数> -->
    <xacro:property name="wheel_joint_z" value="${(base_length / 2 + lidi - wheel_radius) * -1}"/>
   
    <xacro:macro name="wheel_func" params="wheel_name flag">
    <!-- <
        wheel_name : left or right
        flag : 1 or -1 right/left wheel
    > -->
    <!-- <驱动轮01> -->
        <link name="${wheel_name}">
            <!-- <可视化标签> -->
            <visual>
                <!-- <1.形状> -->
                <geometry>
                    <cylinder radius="${wheel_radius}" length="${wheel_length}"/>
                </geometry>
                <origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0"/>
                <material name="whell03_color">
                    <color rgba="0.0 0.0 0.0 0.8"/>
                </material>
            </visual>
        </link>
        <!-- <joint关节  关联baselink& Wheel_01> -->
        <joint name="${wheel_name}2baselink" type="continuous">
            <!-- <设置偏移量> -->
            <!-- <
                x 无偏移
                y 车体半径
                z 车体高度/2 + 离地 - 车轮半径
            > -->
            <origin xyz="0.0 ${flag * 0.1} ${wheel_joint_z}" rpy="0.0 0.0 0.0"/>
            <!-- <父级 link> -->
            <parent link="base_link"/>
            <!-- <子级 link> -->
            <child link="${wheel_name}"/>
            <!-- <设置关节旋转参考的坐标轴> -->
            <axis xyz="0.0 1.0 0.0"/>
            <!-- <limit lower="0.0" upper="0.0" effort="0.0" velocity="0.0"/> -->
        </joint>
    </xacro:macro>
    <xacro:wheel_func wheel_name="base_l_wheel_joint" flag="1"/>
    <xacro:wheel_func wheel_name="base_r_wheel_joint" flag="-1"/>


    <xacro:property name="sup_wheel_radius" value="0.0075"/>
     <xacro:property name="sup_wheel_joint_x" value="${base_radius - sup_wheel_radius }"/>
     <!-- <结果是负数> -->
    <xacro:property name="sup_wheel_joint_z" value="${(base_length / 2 + lidi - sup_wheel_radius ) * -1}"/>


    <xacro:macro name="sup_wheel_func" params="name flag">
        <!-- <万向轮01> -->
        <link name="${name}_wheel">
            <!-- <可视化标签> -->
            <visual>
                <!-- <1.形状> -->
                <geometry>
                    <sphere radius="${sup_wheel_radius}"/>
                </geometry>
                <origin xyz="0.0 0.0 0.0" rpy="0.0  0.0 0.0"/>
                <material name="whell01_color">
                    <color rgba="0.0 0.0 0.0 0.8"/>
                </material>
            </visual>
        </link>
        <!-- <joint关节  关联baselink& Wheel_Universal_01> -->
        <joint name="${name}2baselink" type="continuous">
            <!-- <设置偏移量> -->
                    <!-- <
                x 小于车体半径 自定义  底盘半径-万象轮半径=0.1-0.0075=0.0925
                y 无偏移
                z 车体高度/2 + 离地 - 车轮直径
            > -->
            <origin xyz="${sup_wheel_joint_x * flag } 0.0 ${sup_wheel_joint_z}" rpy="0.0 0.0 0.0"/>
            <!-- <父级 link> -->
            <parent link="base_link"/>
            <!-- <子级 link> -->
            <child link="${name}_wheel"/>
            <!-- <设置关节旋转参考的坐标轴> -->
            <axis xyz="1.0 1.0 1.0"/>
            <!-- <limit lower="0.0" upper="0.0" effort="0.0" velocity="0.0"/> -->
        </joint>
    </xacro:macro>
    <xacro:sup_wheel_func name="front" flag="1"/>
    <xacro:sup_wheel_func name="back" flag="-1"/>

</robot>

2.集成launch文件

**方式1:**先将 xacro 文件转换出 urdf 文件,然后集成

先将 xacro 文件解析成 urdf 文件:rosrun xacro xacro xxx.xacro > xxx.urdf然后再按照之前的集成方式直接整合 launch 文件;

**方式2:**在 launch 文件中直接加载 xacro(建议使用)

launch 内容示例:

<launch>

    <!-- 设置参数 -->
    <!-- <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/xacro/demo05_car_base.urdf" /> -->
     <param name="robot_description" command="$(find xacro)/xacro $(find urdf01_rviz)/urdf/xacro/demo05_car_base.xacro" />
    <!-- 启动 rviz -->
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" />
    <!-- 添加关节状态节点 -->
    <!-- <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" /> -->
    <!-- 添加关节运动控制节点(应该在机器人状态发布节点之上防止抖动) -->
    <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" />
    <!-- 添加机器人状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />

</launch>

核心代码:

 <param name="robot_description" command="$(find xacro)/xacro $(find urdf01_rviz)/urdf/xacro/demo05_car_base.xacro" />

加载robot_description时使用command属性,属性值就是调用 xacro 功能包的 xacro 程序直接解析 xacro 文件。

4.4 URDF语法详解01_robot


需求描述:

在前面小车底盘基础之上,添加摄像头和雷达传感器。

结果演示:

在这里插入图片描述

实现分析:

机器人模型由多部件组成,可以将不同组件设置进单独文件,最终通过文件包含实现组件的拼装。

实现流程:

  1. 首先编写摄像头和雷达的 xacro 文件
  2. 然后再编写一个组合文件,组合底盘、摄像头与雷达
  3. 最后,通过 launch 文件启动 Rviz 并显示模型

1.摄像头和雷达 Xacro 文件实现

摄像头 xacro 文件:

<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="mycar">
    <!-- <摄像头> -->
    <!-- <
        1.连杆属性:厚度(x)宽度(y) 高度(z)
        2.关节属性: x y z
    > -->

    <xacro:property name="camera_length" value="0.02"/>
    <xacro:property name="camera_width" value="0.05"/>
    <xacro:property name="camera_hight" value="0.05"/>

    <xacro:property name="joint_camera_x" value="0.08"/>
    <xacro:property name="joint_camera_y" value="0.0"/>
    <xacro:property name="joint_camera_z" value="${base_length / 2 +  camera_length / 2 + lidi }"/>
    
    <link name="camera">
      
        <visual>
        <geometry>
            <box size="${camera_length} ${camera_width} ${camera_hight}"/>
        </geometry>
        <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
        <material name="camera_black">
            <color rgba="0.0 0.0 0.0 1.0"/>
        </material>
        </visual>

    </link>
    <joint name="camera2base" type="fixed">
        <parent link="base_link"/>
        <child link="camera"/>
        <origin xyz="${joint_camera_x} ${joint_camera_y} ${joint_camera_z}" rpy="0.0 0.0 0.0"/>
    </joint>
    

</robot>

雷达 xacro 文件:

<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="mycar">
    <!-- <雷达> -->
    <!-- <
        1.支撑尺寸:高度 半径
        2.关节属性: x y z

        1.雷达尺寸:高度 半径
        2.关节属性: x y z
    > -->
    <xacro:property name="support_radius" value="0.01"/>
    <xacro:property name="support_length" value="0.15"/>

    <xacro:property name="joint_support_x" value="0"/>
    <xacro:property name="joint_support_y" value="0"/>
    <!-- z=车体高度/2+支撑高度/2  -->
    <xacro:property name="joint_support_z" value="${support_length / 2+ base_length / 2 }"/>

    <xacro:property name="laser_radius" value="0.03"/>
    <xacro:property name="laser_length" value="0.05"/>

    <xacro:property name="joint_laser_x" value="0"/>
    <xacro:property name="joint_laser_y" value="0"/>
    <xacro:property name="joint_laser_z" value="${support_length / 2+ laser_length / 2}"/>
    <!-- 支架 -->
    <link name="support">
        <visual>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
            <geometry>
                <cylinder radius="${support_radius}" length="${support_length}"/>
            </geometry>
            <material name="yellow">
                <color rgba="0.8 0.5 0.0 0.5"/>
            </material>
        </visual>
    </link>

    <joint name="support2baselink" type="fixed">
        <parent link="base_link"/>
        <child link="support"/>
        <origin xyz="${joint_support_x} ${joint_support_y} ${joint_support_z}" rpy="0.0 0.0 0.0"/>
    </joint>
    <!-- 雷达 -->
    <link name="laser">
        <visual>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
            <geometry>
                <cylinder radius="${laser_radius}" length="${laser_length}"/>
            </geometry>
            <material name="laser">
                <color rgba="0.0 0.0 0.0 0.5"/>
            </material>
        </visual>
    </link>
    <joint name="laser2supportlink" type="fixed">
        <parent link="support"/>
        <child link="laser"/>
        <origin xyz="${joint_laser_x} ${joint_laser_y} ${joint_laser_z}" rpy="0 0 0"/>
    </joint>

</robot>


2.组合底盘摄像头与雷达的 xacro 文件

<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="mycar">
    <!-- <文件包含> -->

    <xacro:include filename="demo05_car_base.urdf.xacro"/>
    <xacro:include filename="demo06_car_camera.urdf.xacro"/>
    <xacro:include filename="demo07_car_laser.urdf.xacro"/>

</robot>

3.launch 文件

<launch>

    <!-- 设置参数 -->
    <!-- <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/xacro/demo05_car_base.urdf" /> -->
    <param name="robot_description" command="$(find xacro)/xacro $(find urdf01_rviz)/urdf/xacro/car.urdf.xacro" />
    <!-- 启动 rviz -->
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" />
    <!-- 添加关节状态节点 -->
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
    <!-- 添加机器人状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />

</launch>

在这里插入图片描述

5.Rviz中控制机器人模型运动

**Arbotix:**Arbotix 是一款控制电机、舵机的控制板,并提供相应的 ros 功能包,这个功能包的功能不仅可以驱动真实的 Arbotix 控制板,它还提供一个差速控制器,通过接受速度控制指令更新机器人的 joint 状态,从而帮助我们实现机器人在 rviz 中的运动。

这个差速控制器在 arbotix_python 程序包中,完整的 arbotix 程序包还包括多种控制器,分别对应 dynamixel 电机、多关节机械臂以及不同形状的夹持器。

接下来,通过一个案例演示 arbotix 的使用。

需求描述:

控制机器人模型在 rviz 中做圆周运动

结果演示:

在这里插入图片描述

实现流程:

  1. 安装 Arbotix
  2. 创建新功能包,准备机器人 urdf、xacro 文件
  3. 添加 Arbotix 配置文件
  4. 编写 launch 文件配置 Arbotix
  5. 启动 launch 文件并控制机器人模型运动

1.安装 Arbotix

**方式1:**命令行调用

sudo apt-get install ros-<<VersionName()>>-arbotix

将 <<VsersionName()>> 替换成当前 ROS 版本名称,如果提示功能包无法定位,请采用方式2。

**方式2:**源码安装

先从 github 下载源码,然后调用 catkin_make 编译

git clone https://github.com/vanadiumlabs/arbotix_ros.git

2.创建新功能包,准备机器人 urdf、xacro

urdf 和 xacro 调用上一讲实现即可

3.添加 arbotix 所需的配置文件

添加 arbotix 所需配置文件

# 该文件是控制器配置,一个机器人模型可能有多个控制器,比如: 底盘、机械臂、夹持器(机械手)....
# 因此,根 name 是 controller
controllers: {
   # 单控制器设置
   base_controller: {
          #类型: 差速控制器
       type: diff_controller,
       #参考坐标
       base_frame_id: base_footprint, 
       #两个轮子之间的间距
       base_width: 0.2,
       #控制频率
       ticks_meter: 2000, 
       #PID控制参数,使机器人车轮快速达到预期速度
       Kp: 12, 
       Kd: 12, 
       Ki: 0, 
       Ko: 50, 
       #加速限制
       accel_limit: 1.0 
    }
}

另请参考: http://wiki.ros.org/arbotix_python/diff_controller

4.launch 文件中配置 arbotix 节点

launch 示例代码

<launch>

    <!-- 设置参数 -->
    <!-- <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/xacro/demo05_car_base.urdf" /> -->
    <param name="robot_description" command="$(find xacro)/xacro $(find urdf01_rviz)/urdf/xacro/car.urdf.xacro" />
    <!-- 启动 rviz -->
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" />
    <!-- 添加关节状态节点 -->
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
    <!-- 添加机器人状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
    <!-- 添加集成 arbotix 运动控制节点,并加载参数 -->
    <node pkg="arbotix_python" type="arbotix_driver" name="driver" output="screen">
        <rosparam command="load" file="$(find urdf01_rviz)/config/control.yaml" />
        <param name="sim" value="true"/>
        <!-- 可以控制现实和仿真环境,因此需要设置为仿真 -->


    </node>

</launch>

代码解释:

调用了 arbotix_python 功能包下的 arbotix_driver 节点

arbotix 驱动机器人运行时,需要获取机器人信息,可以通过 file 加载配置文件

在仿真环境下,需要配置 sim 为 true

5.启动 launch 文件并控制机器人模型运动

**启动launch:**roslaunch xxxx …launch

启动报错:

Joint state with name: "base_l_wheel_joint" was received but not found in URDF

原因:与arbotix配置的名字不同

demo05_car_base.urdf将左右轮的joint节点的name改成"base_l_wheel_joint"和"base_r_wheel_joint"

将xacro变换成urdf:rosrun xacro xacro demo05_car_base.urdf.xacro > demo05.urdf

转换成pdf查看: urdf_to_graphiz urdf/demo05.urdf

在这里插入图片描述

配置 rviz:

在这里插入图片描述

控制小车运动:

此时调用 rostopic list 会发现一个熟悉的话题: /cmd_vel

在这里插入图片描述

rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.2, y: 0, z: 0}, angular: {x: 0, y: 0, z: 0.5}}'

另请参考:

  • http://wiki.ros.org/arbotix

6.URDF集成Gazebo

URDF 需要集成进 Rviz 或 Gazebo 才能显示可视化的机器人模型

6.1URDF与Gazebo基本集成流程

URDF 与 Gazebo 集成流程与 Rviz 实现类似,主要步骤如下:

  1. 创建功能包,导入依赖项
  2. 编写 URDF 或 Xacro 文件
  3. 启动 Gazebo 并显示机器人模型

1.创建功能包

创建新功能包,导入依赖包: urdf、xacro、gazebo_ros、gazebo_ros_control、gazebo_plugins

2.编写URDF文件

注意, 当 URDF 需要与 Gazebo 集成时,和 Rviz 有明显区别:

1.必须使用 collision 标签,因为既然是仿真环境,那么必然涉及到碰撞检测,collision 提供碰撞检测的依据。

2.必须使用 inertial 标签,此标签标注了当前机器人某个刚体部分的惯性矩阵,用于一些力学相关的仿真计算。

3.颜色设置,也需要重新使用 gazebo 标签标注,因为之前的颜色设置为了方便调试包含透明度,仿真环境下没有此选项

3.启动Gazebo并显示模型

代码解释:

<include file="$(find gazebo_ros)/launch/empty_world.launch" />
<!-- 启动 Gazebo 的仿真环境,当前环境为空环境 -->

<node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description"  />

<!-- 
    在 Gazebo 中加载一个机器人模型,该功能由 gazebo_ros 下的 spawn_model 提供:
    -urdf 加载的是 urdf 文件
    -model mycar 模型名称是 mycar
    -param robot_description 从参数 robot_description 中载入模型
    -x 模型载入的 x 坐标
    -y 模型载入的 y 坐标
    -z 模型载入的 z 坐标
-->

6.2 URDF集成Gazebo相关设置

较之于 rviz,gazebo在集成 URDF 时,需要做些许修改,比如:必须添加 collision 碰撞属性相关参数、必须添加 inertial 惯性矩阵相关参数,另外,如果直接移植 Rviz 中机器人的颜色设置是没有显示的,颜色设置也必须做相应的变更。

1.collision

如果机器人link是标准的几何体形状,和link的 visual 属性设置一致即可。

2.inertial

惯性矩阵的设置需要结合link的质量与外形参数动态生成, 原则上,除了 base_footprint 外,机器人的每个刚体部分都需要设置惯性矩阵,且惯性矩阵必须经计算得出,如果随意定义刚体部分的惯性矩阵,那么可能会导致机器人在 Gazebo 中出现抖动,移动等现象。

3.颜色设置

在 gazebo 中显示 link 的颜色,必须要使用指定的标签:

<gazebo reference="link节点名称">
     <material>Gazebo/Blue</material>
</gazebo>

**PS:**material 标签中,设置的值区分大小写,颜色可以设置为 Red Blue Green Black …

6.3 URDF集成Gazebo实操需求描述:

将之前的机器人模型(xacro版)显示在 gazebo 中

结果演示:
在这里插入图片描述

实现流程:

  1. 需要编写封装惯性矩阵算法的 xacro 文件
  2. 为机器人模型中的每一个 link 添加 collision 和 inertial 标签,并且重置颜色属性
  3. 在 launch 文件中启动 gazebo 并添加机器人模型

1.编写封装惯性矩阵算法的 xacro 文件

<robot name="base" xmlns:xacro="http://wiki.ros.org/xacro">
    <!-- Macro for inertia matrix -->
    <xacro:macro name="sphere_inertial_matrix" params="m r">
        <inertial>
            <mass value="${m}" />
            <inertia ixx="${2*m*r*r/5}" ixy="0" ixz="0"
                iyy="${2*m*r*r/5}" iyz="0" 
                izz="${2*m*r*r/5}" />
        </inertial>
    </xacro:macro>

    <xacro:macro name="cylinder_inertial_matrix" params="m r h">
        <inertial>
            <mass value="${m}" />
            <inertia ixx="${m*(3*r*r+h*h)/12}" ixy = "0" ixz = "0"
                iyy="${m*(3*r*r+h*h)/12}" iyz = "0"
                izz="${m*r*r/2}" /> 
        </inertial>
    </xacro:macro>

    <xacro:macro name="Box_inertial_matrix" params="m l w h">
       <inertial>
               <mass value="${m}" />
               <inertia ixx="${m*(h*h + l*l)/12}" ixy = "0" ixz = "0"
                   iyy="${m*(w*w + l*l)/12}" iyz= "0"
                   izz="${m*(w*w + h*h)/12}" />
       </inertial>
   </xacro:macro>
</robot>

2.复制相关 xacro 文件,并设置 collision inertial 以及 color 等参数

A.底盘 Xacro 文件
<robot name="my_base"
    xmlns:xacro="http://www.ros.org/wiki/xacro">
    <!-- 封装变量、常量 -->
    <!-- PI 值设置精度需要高一些,否则后续车轮翻转量计算时,可能会出现肉眼不能察觉的车轮倾斜,从而导致模型抖动 -->

    <!-- 宏:黑色设置 -->
    <material name="black">
        <color rgba="0.0 0.0 0.0 1.0" />
    </material>

    <!-- 底盘属性 -->
    <xacro:property name="footprint_radius" value="0.001" />
    <xacro:property name="PI" value="3.1415926"/>
    <!-- base_footprint 半径  -->
    <xacro:property name="base_radius" value="0.1" />
    <!-- base_link 半径 -->
    <xacro:property name="base_length" value="0.08" />
    <!-- base_link 长 -->
    <xacro:property name="lidi" value="0.015" />
    <!-- 离地间距 -->
    <xacro:property name="base_mass" value="0.5" />
    <!-- 质量  -->
    <!-- 驱动轮属性 -->
    <xacro:property name="wheel_radius" value="0.0325" />
    <!-- 半径 -->
    <xacro:property name="wheel_length" value="0.015" />
    <!-- 宽度 -->
    <xacro:property name="wheel_mass" value="0.05" />
    <!-- 质量  -->
    <!-- 支撑轮属性 -->
    <xacro:property name="sup_wheel_radius" value="0.0075" />
    <!-- 支撑轮半径 -->
    <xacro:property name="sup_wheel_mass" value="0.03" />
    <!-- 质量  -->
    <!-- 底盘 -->
    <link name="base_footprint">
        <visual>
            <geometry>
                <sphere radius="${footprint_radius}" />
            </geometry>
        </visual>
    </link>
    <link name="base_link">
        <visual>
            <geometry>
                <cylinder radius="${base_radius}" length="${base_length}" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="yellow">
                <color rgba="0.5 0.3 0.0 0.5" />
            </material>
        </visual>
        <collision>
            <geometry>
                <cylinder radius="${base_radius}" length="${base_length}" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
        </collision>
        <xacro:cylinder_inertial_matrix m="${base_mass}" r="${base_radius}" h="${base_length}" />
    </link>
    <joint name="base_link2base_footprint" type="fixed">
        <parent link="base_footprint" />
        <child link="base_link" />
        <origin xyz="0 0 ${lidi + base_length / 2 }" />
    </joint>
    <gazebo reference="base_link">
        <material>Gazebo/Yellow</material>
    </gazebo>
    <!-- 驱动轮 -->
    <!-- 驱动轮宏实现 -->
    <xacro:macro name="wheel_func" params="name flag">
        <link name="${name}_wheel">
            <visual>
                <geometry>
                    <cylinder radius="${wheel_radius}" length="${wheel_length}" />
                </geometry>
                <origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0" />
                <material name="black" />
            </visual>
            <collision>
                <geometry>
                    <cylinder radius="${wheel_radius}" length="${wheel_length}" />
                </geometry>
                <origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0" />
            </collision>
            <xacro:cylinder_inertial_matrix m="${wheel_mass}" r="${wheel_radius}" h="${wheel_length}" />

        </link>
        <joint name="${name}_wheel2base_link" type="continuous">
            <parent link="base_link" />
            <child link="${name}_wheel" />
            <origin xyz="0 ${flag * base_radius} ${-(lidi + base_length / 2 - wheel_radius) }" />
            <axis xyz="0 1 0" />
        </joint>

        <gazebo reference="${name}_wheel">
            <material>Gazebo/Red</material>
        </gazebo>
    </xacro:macro>
    <xacro:wheel_func name="left" flag="1" />
    <xacro:wheel_func name="right" flag="-1" />
    <!-- 支撑轮 -->
    <!-- 支撑轮宏 -->
    <xacro:macro name="sup_wheel_func" params="name flag">
        <link name="${name}_wheel">
            <visual>
                <geometry>
                    <sphere radius="${sup_wheel_radius}" />
                </geometry>
                <origin xyz="0 0 0" rpy="0 0 0" />
                <material name="black" />
            </visual>
            <collision>
                <geometry>
                    <sphere radius="${sup_wheel_radius}" />
                </geometry>
                <origin xyz="0 0 0" rpy="0 0 0" />
            </collision>
            <xacro:sphere_inertial_matrix m="${sup_wheel_mass}" r="${sup_wheel_radius}" />
        </link>

        <joint name="${name}_wheel2base_link" type="continuous">
            <parent link="base_link" />
            <child link="${name}_wheel" />
            <origin xyz="${flag * (base_radius - sup_wheel_radius)} 0 ${-(base_length / 2 + lidi / 2)}" />
            <axis xyz="1 1 1" />
        </joint>
        <gazebo reference="${name}_wheel">
            <material>Gazebo/Red</material>
        </gazebo>
    </xacro:macro>
    <xacro:sup_wheel_func name="front" flag="1" />
    <xacro:sup_wheel_func name="back" flag="-1" />
</robot>

注意: 如果机器人模型在 Gazebo 中产生了抖动,滑动,缓慢位移 … 诸如此类情况,请查看

  1. 惯性矩阵是否设置了,且设置是否正确合理
  2. 车轮翻转需要依赖于 PI 值,如果 PI 值精度偏低,也可能导致上述情况产生
B.摄像头 Xacro 文件
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="mycar">
    <!-- <摄像头> -->
    <!-- <
        1.连杆属性:厚度(x)宽度(y) 高度(z)
        2.关节属性: x y z
    > -->

    <xacro:property name="camera_length" value="0.02"/>
    <xacro:property name="camera_width" value="0.05"/>
    <xacro:property name="camera_hight" value="0.05"/>
    <xacro:property name="camera_mass" value="0.01"/>

    <xacro:property name="joint_camera_x" value="0.08"/>
    <xacro:property name="joint_camera_y" value="0.0"/>
    <xacro:property name="joint_camera_z" value="${base_length / 2 +  camera_length / 2 + lidi }"/>

    <link name="camera">
        <visual>
            <geometry>
                <box size="${camera_length} ${camera_width} ${camera_hight}"/>
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
            <material name="camera_black">
                <color rgba="0.0 0.0 0.0 1.0"/>
            </material>
        </visual>
        <collision>
            <geometry>
                <box size="${camera_length} ${camera_width} ${camera_hight}"/>
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
        </collision>
        <xacro:Box_inertial_matrix m="${camera_mass}" l="${camera_length}" w="${camera_width}" h="${camera_hight}" />
    </link>

    <joint name="camera2base" type="fixed">
        <parent link="base_link"/>
        <child link="camera"/>
        <origin xyz="${joint_camera_x} ${joint_camera_y} ${joint_camera_z}" rpy="0.0 0.0 0.0"/>
    </joint>
    <gazebo reference="camera">
        <material>
            Gazebo/Blue 
        </material>
    </gazebo>

</robot>
C.雷达 Xacro 文件
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="mycar">
    <!-- <雷达> -->
    <!-- <
        1.支撑尺寸:高度 半径
        2.关节属性: x y z


        1.雷达尺寸:高度 半径
        2.关节属性: x y z
    > -->
    <xacro:property name="suport_radius" value="0.01"/>
    <xacro:property name="suport_length" value="0.15"/>
    <xacro:property name="suport_mass" value="0.10"/>

    <xacro:property name="joint_suport_x" value="0"/>
    <xacro:property name="joint_suport_y" value="0"/>
    <xacro:property name="joint_suport_z" value="${suport_length / 2+ base_length / 2 }"/>

    <xacro:property name="laser_radius" value="0.03"/>
    <xacro:property name="laser_length" value="0.05"/>
    <xacro:property name="laser_mass" value="0.15"/>

    <xacro:property name="joint_laser_x" value="0"/>
    <xacro:property name="joint_laser_y" value="0"/>
    <xacro:property name="joint_laser_z" value="${suport_length / 2+ laser_length / 2}"/>

    <link name="suport_link">
        <visual>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
            <geometry>
                <cylinder radius="${suport_radius}" length="${suport_length}"/>
            </geometry>
            <material name="suport_link">
                <color rgba="1.0 0.0 1.0 0.6"/>
            </material>
        </visual>
        <collision>
            <geometry>
                <cylinder radius="${suport_radius}" length="${suport_length}"/>
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
        </collision>
        <xacro:cylinder_inertial_matrix m="${suport_mass}" r="${suport_radius}" h="${suport_length}"/>
    </link>

    <joint name="suport2baselink" type="fixed">
        <parent link="base_link"/>
        <child link="suport_link"/>
        <origin xyz="${joint_suport_x} ${joint_suport_y} ${joint_suport_z}" rpy="0.0 0.0 0.0"/>
    </joint>
    <gazebo reference="suport_link">
        <material>
                Gazebo/Grey 
        </material>
    </gazebo>


    <link name="laser">
        <visual>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
            <geometry>
                <cylinder radius="${laser_radius}" length="${laser_length}"/>
            </geometry>
            <material name="laser">
                <color rgba="0.5 0.7 1.0 0.8"/>
            </material>
        </visual>
        <collision>
            <geometry>
                <cylinder radius="${laser_radius}" length="${laser_length}"/>
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
        </collision>
        <xacro:cylinder_inertial_matrix m="${laser_mass}" r="${laser_radius}" h="${laser_length}"/>
    </link>

    <joint name="laser2suportlink" type="fixed">
        <parent link="suport_link"/>
        <child link="laser"/>
        <origin xyz="${joint_laser_x} ${joint_laser_y} ${joint_laser_z}" rpy="0 0 0"/>
    </joint>
    <gazebo reference="laser">
        <material>
                Gazebo/Black 
        </material>
    </gazebo>


</robot>
D.组合底盘、摄像头与雷达的 Xacro 文件
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="mycar">
    <xacro:include filename="inertia.xacro"/>

    <!-- <文件包含> -->

    <xacro:include filename="demo05_car_base.urdf.xacro"/>
    <xacro:include filename="demo06_car_camera.urdf.xacro"/>
    <xacro:include filename="demo07_car_laser.urdf.xacro"/>

</robot>

3.在 gazebo 中执行

launch 文件:

<launch>
    <!-- <需要在参数服务器中载入urdf> -->
    <param name="robot_description" command="$(find xacro)/xacro $(find urdf02_gazebo)/urdf/car.urdf.xacro" />
    <!-- <启动Gazebo仿真环境> -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(find urdf02_gazebo)/worlds/box_house.world" />
    </include>
    <!-- <在Gazebo中添加机器人模型> -->
    <node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description" />
</launch>

在这里插入图片描述

6.4 Gazebo仿真环境搭建

Gazebo 中创建仿真实现方式有两种:

  • 方式1: 直接添加内置组件创建仿真环境
  • 方式2: 手动绘制仿真环境(更为灵活)

也还可以直接下载使用官方或第三方提高的仿真环境插件。

1.添加内置组件创建仿真环境

1.1启动 Gazebo 并添加组件

在这里插入图片描述

1.2保存仿真环境

在这里插入图片描述

添加完毕后,选择 file —> Save World as 选择保存路径(功能包下: worlds 目录),文件名自定义,后缀名设置为 .world

1.3 启动
<launch>

    <!-- 将 Urdf 文件的内容加载到参数服务器 -->
    <param name="robot_description" command="$(find xacro)/xacro $(find demo02_urdf_gazebo)/urdf/xacro/my_base_camera_laser.urdf.xacro" />
    <!-- 启动 gazebo -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(find demo02_urdf_gazebo)/worlds/hello.world" />
    </include>

    <!-- 在 gazebo 中显示机器人模型 -->
    <node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description"  />
</launch>
Copy

核心代码: 启动 empty_world 后,再根据arg加载自定义的仿真环境

<include file="$(find gazebo_ros)/launch/empty_world.launch">
    <arg name="world_name" value="$(find demo02_urdf_gazebo)/worlds/hello.world" />
</include>
Copy

2.自定义仿真环境

2.1 启动 gazebo 打开构建面板,绘制仿真环境

在这里插入图片描述

2.2 保存构建的环境

点击: 左上角 file —> Save (保存路径功能包下的: models)

然后 file —> Exit Building Editor

2.3 保存为 world 文件

可以像方式1一样再添加一些插件,然后保存为 world 文件(保存路径功能包下的: worlds)

在这里插入图片描述

2.4 启动

同方式1

3.使用官方提供的插件

当前 Gazebo 提供的仿真道具有限,还可以下载官方支持,可以提供更为丰富的仿真实现,具体实现如下:

3.1 下载官方模型库
git clone https://github.com/osrf/gazebo_models

之前是:hg clone https://bitbucket.org/osrf/gazebo_models但是已经不可用

注意: 此过程可能比较耗时

3.2 将模型库复制进 gazebo

将得到的gazebo_models文件夹内容复制到 /usr/share/gazebo-*/models

3.3 应用

重启 Gazebo,选择左侧菜单栏的 insert 可以选择并插入相关道具了

7 URDF、Gazebo与Rviz综合应用

通过 Gazebo 模拟机器人的传感器,然后在 Rviz 中显示这些传感器感知到的数据。主要内容包括:

  • 运动控制以及里程计信息显示
  • 雷达信息仿真以及显示
  • 摄像头信息仿真以及显示
  • kinect 信息仿真以及显示

7.1 机器人运动控制以及里程计信息显示

gazebo 中已经可以正常显示机器人模型了,那么如何像在 rviz 中一样控制机器人运动呢?在此,需要涉及到ros中的组件: ros_control。

1.ros_control 简介

**场景:**同一套 ROS 程序,如何部署在不同的机器人系统上,比如:开发阶段为了提高效率是在仿真平台上测试的,部署时又有不同的实体机器人平台,不同平台的实现是有差异的,如何保证 ROS 程序的可移植性?ROS 内置的解决方式是 ros_control。

**ros_control:**是一组软件包,它包含了控制器接口,控制器管理器,传输和硬件接口。ros_control 是一套机器人控制的中间件,是一套规范,不同的机器人平台只要按照这套规范实现,那么就可以保证 与ROS 程序兼容,通过这套规范 ,实现了一种可插拔的架构设计,大大提高了程序设计的效率与灵活性。

gazebo 已经实现了 ros_control 的相关接口,如果需要在 gazebo 中控制机器人运动,直接调用相关接口即可

2.运动控制实现流程(Gazebo)

承上,运动控制基本流程:

  1. 已经创建完毕的机器人模型,编写一个单独的 xacro 文件,为机器人模型添加传动装置以及控制器
  2. 将此文件集成进xacro文件
  3. 启动 Gazebo 并发布 /cmd_vel 消息控制机器人运动
2.1 为 joint 添加传动装置以及控制器

两轮差速配置

<robot name="my_car_move"
    xmlns:xacro="http://wiki.ros.org/xacro">

    <!-- 传动实现:用于连接控制器与关节 -->
    <xacro:macro name="joint_trans" params="joint_name">
        <!-- Transmission is important to link the joints and the controller -->
        <transmission name="${joint_name}_trans">
            <type>transmission_interface/SimpleTransmission</type>
            <joint name="${joint_name}">
                <hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
            </joint>
            <actuator name="${joint_name}_motor">
                <hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
                <mechanicalReduction>1</mechanicalReduction>
            </actuator>
        </transmission>
    </xacro:macro>

    <!-- 每一个驱动轮都需要配置传动装置 参考demo05 joint name ${name}2link    名字一定要打对,否则后续启动gazebo不会出现cmd_vel-->
    <xacro:joint_trans joint_name="left2link" />
    <xacro:joint_trans joint_name="right2link" />

    <!-- 控制器 -->
    <gazebo>
        <plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
            <rosDebugLevel>Debug</rosDebugLevel>
            <publishWheelTF>true</publishWheelTF>
            <robotNamespace>/</robotNamespace>
            <publishTf>1</publishTf>
            <publishWheelJointState>true</publishWheelJointState>
            <alwaysOn>true</alwaysOn>
            <updateRate>100.0</updateRate>
            <legacyMode>true</legacyMode>
            <leftJoint>left2link</leftJoint>            <!-- 左轮 -->
            <rightJoint>right2link</rightJoint>            <!-- 右轮 -->
            <wheelSeparation>${base_radius * 2}</wheelSeparation>            <!-- 车轮间距 -->
            <wheelDiameter>${wheel_radius * 2}</wheelDiameter>            <!-- 车轮直径 -->
            <broadcastTF>1</broadcastTF>
            <wheelTorque>30</wheelTorque>
            <wheelAcceleration>1.8</wheelAcceleration>
            <commandTopic>cmd_vel</commandTopic>            <!-- 运动控制话题 -->
            <odometryFrame>odom</odometryFrame>
            <odometryTopic>odom</odometryTopic>            <!-- 里程计话题 -->
            <robotBaseFrame>base_footprint</robotBaseFrame>            <!-- 根坐标系 -->
        </plugin>
    </gazebo>

</robot>

2.2 添加xacro文件
<!-- 摄像头 -->
<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
  <!-- 被引用的link -->
  <gazebo reference="camera">
    <!-- 类型设置为 camara -->
    <sensor type="camera" name="camera_node">
      <update_rate>30.0</update_rate> <!-- 更新频率 -->
      <!-- 摄像头基本信息设置 -->
      <camera name="head">
        <horizontal_fov>1.3962634</horizontal_fov>
        <image>
          <width>1280</width>
          <height>720</height>
          <format>R8G8B8</format>
        </image>
        <clip>
          <near>0.02</near>
          <far>300</far>
        </clip>
        <noise>
          <type>gaussian</type>
          <mean>0.0</mean>
          <stddev>0.007</stddev>
        </noise>
      </camera>
      <!-- 核心插件 -->
      <plugin name="gazebo_camera" filename="libgazebo_ros_camera.so">
        <alwaysOn>true</alwaysOn>
        <updateRate>0.0</updateRate>
        <cameraName>/camera</cameraName>
        <imageTopicName>image_raw</imageTopicName>
        <cameraInfoTopicName>camera_info</cameraInfoTopicName>
        <frameName>camera</frameName>
        <hackBaseline>0.07</hackBaseline>
        <distortionK1>0.0</distortionK1>
        <distortionK2>0.0</distortionK2>
        <distortionK3>0.0</distortionK3>
        <distortionT1>0.0</distortionT1>
        <distortionT2>0.0</distortionT2>
      </plugin>
    </sensor>
  </gazebo>
</robot>

<!-- kinetic -->
<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
    <gazebo reference="suport_link">  
      <sensor type="depth" name="camera">
        <always_on>true</always_on>
        <update_rate>20.0</update_rate>
        <camera>
          <horizontal_fov>${60.0*PI/180.0}</horizontal_fov>
          <image>
            <format>R8G8B8</format>
            <width>640</width>
            <height>480</height>
          </image>
          <clip>
            <near>0.05</near>
            <far>8.0</far>
          </clip>
        </camera>
        <plugin name="kinect_camera_controller" filename="libgazebo_ros_openni_kinect.so">
          <cameraName>camera</cameraName>
          <alwaysOn>true</alwaysOn>
          <updateRate>10</updateRate>
          <imageTopicName>rgb/image_raw</imageTopicName>
          <depthImageTopicName>depth/image_raw</depthImageTopicName>
          <pointCloudTopicName>depth/points</pointCloudTopicName>
          <cameraInfoTopicName>rgb/camera_info</cameraInfoTopicName>
          <depthImageCameraInfoTopicName>depth/camera_info</depthImageCameraInfoTopicName>
          <frameName>support_depth</frameName>
          <baseline>0.1</baseline>
          <distortion_k1>0.0</distortion_k1>
          <distortion_k2>0.0</distortion_k2>
          <distortion_k3>0.0</distortion_k3>
          <distortion_t1>0.0</distortion_t1>
          <distortion_t2>0.0</distortion_t2>
          <pointCloudCutoff>0.4</pointCloudCutoff>
        </plugin>
      </sensor>
    </gazebo>

</robot>


<!-- laser-->
<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">

  <!-- 雷达 -->
  <gazebo reference="laser"><!-- mingzi -->
    <sensor type="ray" name="rplidar">
      <pose>0 0 0 0 0 0</pose>
      <visualize>true</visualize>
      <update_rate>5.5</update_rate>
      <ray>
        <scan>
          <horizontal>
            <samples>360</samples>
            <resolution>1</resolution>
            <min_angle>-3</min_angle>
            <max_angle>3</max_angle>
          </horizontal>
        </scan>
        <range>
          <min>0.10</min>
          <max>30.0</max>
          <resolution>0.01</resolution>
        </range>
        <noise>
          <type>gaussian</type>
          <mean>0.0</mean>
          <stddev>0.01</stddev>
        </noise>
      </ray>
      <plugin name="gazebo_rplidar" filename="libgazebo_ros_laser.so">
        <topicName>/scan</topicName><!-- hua ti -->
        <frameName>laser</frameName><!-- leidazuobiaoxi -->
      </plugin>
    </sensor>
  </gazebo>
</robot>


2.3 xacro文件集成

最后还需要将上述 xacro 文件集成进总的机器人模型文件,代码示例如下:

<!-- 组合小车底盘与摄像头 -->
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="mycar">
    <xacro:include filename="inertia.xacro"/>

    <!-- <文件包含> -->


    <xacro:include filename="demo05_car_base.urdf.xacro"/>
    <xacro:include filename="demo06_car_camera.urdf.xacro"/>
    <xacro:include filename="demo07_car_laser.urdf.xacro"/>

    <xacro:include filename="gazebo/move.xacro"/>

    <xacro:include filename="gazebo/laser.xacro"/>
    <xacro:include filename="gazebo/camera.xacro"/>
    <xacro:include filename="gazebo/kinect.xacro"/>



</robot>

当前核心: 包含 控制器以及传动配置的 xacro 文件

<xacro:include filename="move.xacro" />
2.4 启动 gazebo并控制机器人运动

launch文件:

<launch>
    <!-- <需要在参数服务器中载入urdf> -->
    <param name="robot_description" command="$(find xacro)/xacro $(find urdf02_gazebo)/urdf/car.urdf.xacro" />
    <!-- <启动Gazebo仿真环境> -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(find urdf02_gazebo)/worlds/box_house.world" />
    </include>
    <!-- <在Gazebo中添加机器人模型> -->
    <node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description" />
</launch>

启动 launch 文件,使用 topic list 查看话题列表,会发现多了 /cmd_vel 然后发布 vmd_vel 消息控制即可

使用命令控制(或者可以编写单独的节点控制)

rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.2, y: 0, z: 0}, angular: {x: 0, y: 0, z: 0.5}}'

小车在 Gazebo 中已经正常运行起来了

3.Rviz查看里程计信息

在 Gazebo 的仿真环境中,机器人的里程计信息以及运动朝向等信息是无法获取的,可以通过 Rviz 显示机器人的里程计信息以及运动朝向

里程计: 机器人相对出发点坐标系的位姿状态(X 坐标 Y 坐标 Z坐标以及朝向)。

3.1启动 Rviz

launch 文件

<launch>

    <!-- 设置点云图tf变换参数 -->
    <node pkg="tf2_ros" type="static_transform_publisher" name="static_transform_publisher" args="0 0 0 -1.57 0 -1.57 /suport_link /support_depth" />

    <!-- 启动 rviz -->
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" />
    <!-- 添加关节状态节点 -->
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />

    <!-- 添加机器人状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />

</launch>
3.2 添加组件

执行 launch 文件后,在 Rviz 中添加图示组件:

在这里插入图片描述

运行:

roslaunch urdf02_gazebo demo03_env.launch 
roslaunch urdf02_gazebo demo04_sensor.launch 
rosrun teleop_twist_keyboard teleop_twist_keyboard.py _speed:=0.3 _turn:=0.5
rostopic pub -r 10 /cmd_vel geometry_msgs/Twist "linear:
  x: 0.0
  y: 0.0
  z: 0.0
angular:
  x: 0.0
  y: 0.0
  z: 0.3" 

注意:名字一定要打对,否则后续启动gazebo不会出现cmd_vel

8.本章小结

URDF 是用于描述机器人模型的 xml 文件,可以使用不同的标签具代表不同含义,URDF 编写机器人模型代码冗余,xacro 可以优化 URDF 实现,代码实现更为精简、高效、易读。容易混淆的是Rviz与Gazebo,在此我们着重比较以下二者的区别:

rviz是三维可视化工具,强调把已有的数据可视化显示;

gazebo是三维物理仿真平台,强调的是创建一个虚拟的仿真环境。

rviz需要已有数据

rviz提供了很多插件,这些插件可以显示图像、模型、路径等信息,但是前提都是这些数据已经以话题、参数的形式发布,rviz做的事情就是订阅这些数据,并完成可视化的渲染,让开发者更容易理解数据的意义。

gazebo不是显示工具,强调的是仿真,它不需要数据,而是创造数据

我们可以在gazebo中免费创建一个机器人世界,不仅可以仿真机器人的运动功能,还可以仿真机器人的传感器数据。而这些数据就可以放到rviz中显示,所以使用gazebo的时候,经常也会和rviz配合使用。当我们手上没有机器人硬件或实验环境难以搭建时,仿真往往是非常有用的利器。

综上,如果你手上已经有机器人硬件平台,并且在上边可以完成需要的功能,用rviz应该就可以满足开发需求。

如果你手上没有机器人硬件,或者想在仿真环境中做一些算法、应用的测试,gazebo+rviz应该是你需要的。

另外,rviz配合其他功能包也可以建立一个简单的仿真环境,比如rviz+ArbotiX。

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

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

相关文章

Promethus实操部署ARM架构 麒麟系统

由于有个地市局的等保测评要求安装监控软件&#xff0c;实操安装普罗米修斯和Zabbix&#xff0c;原本想安装Zabbix在本地安装非常顺利&#xff0c;但是服务器是华为鹏鲲的、ARM架构&#xff0c;Zabbix的有些东西找不到ARM的&#xff0c;所以两个都尝试了下。本篇讲解下Promethu…

协同过滤推荐算法

协同过滤&#xff1a;利用集体智慧&#xff0c;借鉴相关人群的观点进行推荐。 过去兴趣相似的用户在未来的兴趣也会相似&#xff1b;相似的用户会产生相似的历史行为数据。 根据历史行为&#xff0c;产生相似用户&#xff0c;分析出推荐结果。 用一句大白话说&#xff0c;其实也…

Android请求应用权限

文章目录前言参考一、请求应用权限基本原则二、请求权限的流程&#xff08;官网摘抄&#xff09;三、请求权限编码1.允许系统管理权限请求代码2.自行管理权限请求代码总结前言 学习Android为什么需要动态申请危险权限 学会Android应用危险权限申请的方式 参考 Android官方文档…

8 种 Python 定时任务的解决方案

在日常工作中&#xff0c;我们常常会用到需要周期性执行的任务&#xff0c;一种方式是采用 Linux 系统自带的 crond 结合命令行实现&#xff0c;另外一种方式是直接使用Python。 最近我整理了一下 Python 定时任务的实现方式&#xff0c;内容较长&#xff0c;建议收藏后学习&a…

uni-app云开发(我直接访问后端)

uniCloud 是 DCloud 联合阿里云、腾讯云&#xff0c;为开发者提供的基于 serverless 模式和 js 编程的云开发平台。 熟悉的js的程序员&#xff0c;轻松搞定前后台整体业务。实现了前端完成前后端工作的可能 用法&#xff1a; 第一步新建uniCloud项目 点击文件 ——>新建—…

Hue编译安装使用

简介 由于大数据框架很多&#xff0c;为了解决某个问题&#xff0c;一般来说会用到多个框架&#xff0c;但是每个框架又都有自己的web UI监控界面&#xff0c;对应着不同的端口号。比如HDFS(9870)、YARN(8088)、MapReduce(19888)等。这个时候有一个统一的web UI界面去管理各个大…

高斯混合模型下的变分推断

大概从下面几个部分学习&#xff1a; 1.EM算法 人人都懂EM算法 - 知乎 (zhihu.com) 18分钟理解EM算法 - 知乎 (zhihu.com) 变分贝叶斯深度学习综述 - 知乎 (zhihu.com) 【未看完】 EM算法存在的意义是什么&#xff1f; - 知乎 (zhihu.com)【八种境界】 EM 算法具备收敛性…

java计算机毕业设计ssm体育赛事管理系统App2qrcr(附源码、数据库)

java计算机毕业设计ssm体育赛事管理系统App2qrcr&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#x…

[附源码]Python计算机毕业设计Django酒店物联网平台系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;我…

小目标检测文章阅读

无人机上目标检测的特点&#xff1a; 1、图像特点 在多数情况下&#xff0c;无人机的拍摄视野很大&#xff0c;包含丰富的视觉内容&#xff0c;虽然它提供了更全面的场景信息。 缺点&#xff1a; 1&#xff09;但是待检测的目标对象通常在图像中占比较小&#xff0c;且没有足…

法国巴黎索邦大学博士后—实验物理学

【国外博士后招聘-法国博士后】法国巴黎索邦大学博士后—实验物理学 索邦大学&#xff08;法文&#xff1a;Sorbonne Universit&#xff1b;英文&#xff1a;Sorbonne University&#xff09;简称“索邦”&#xff08;Sorbonne&#xff09;&#xff0c;是一所位于法国巴黎拉丁区…

多线程环境下的单例模式

✨✨hello&#xff0c;愿意点进来的小伙伴们&#xff0c;你们好呐&#xff01; &#x1f43b;&#x1f43b;系列专栏&#xff1a;【JavaEE初阶】 &#x1f432;&#x1f432;本篇内容&#xff1a;基于多线程的单例模式 &#x1f42f;&#x1f42f;作者简介:一名现大二的三非编程…

Linux虚拟化网络之路由配置

一、Linux路由配置 如果要在不同网段直接通讯&#xff0c;需要添加路由&#xff0c;Linux添加路由命令如下&#xff1a; route [add|del] [-net|-host] target [netmask Nm] [gw Gw] [[dev] If] add : 添加一条路由规则&#xff1b;del : 删除一条路由规则&#xff1b;-net …

Win11如何开启移动中心页面的操作方法教学

Win11如何开启移动中心页面的操作方法教学分享。有用户不知道怎么去打开移动中心&#xff0c;开启这个页面我们可以去进行屏幕亮度调整、声音调整、笔记本电池状态、外接显示器/投影仪、以及幻灯片显示模式等功能集中到一个面板上进行管理设置。如何开启这个页面&#xff0c;来…

【教程】超详细通过Shizuku转生支付宝集成XQ_Crystal来自动收能量

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.blog.csdn.net] 通过Shizuku是比应用转生更好更稳定的方法&#xff01; 可以先看这篇&#xff1a;免Root使用Xposed插件并开启蚂蚁森林自动偷能量,比应用转生好 还不会的&#xff0c;继续往下。看完还不会&#xff…

手机银行APP评测系列:天津银行持续优化手机银行用户体验,但仍需加强细节提升

易观分析&#xff1a;作为银行金融服务线上场景渗透的有效抓手&#xff0c;当前手机银行APP已经成为其触达用户的重要渠道。随着银行发力场景服务平台成为发展趋势&#xff0c;5G技术问世对金融服务场景端提出新要求&#xff0c;用户体验反馈成为银行线上场景化运营的重要一环。…

JavaScript—分支结构和循环结构整理

目录 一、流程控制 二、分支结构 1. if语句 2. if…else语句 3. if…else if语句 4. switch语句 5. 条件表达式构成的选择结构 三、循环结构 1.while循环 2. do-while循环 3. for循环 3.1 for循环转换为while循环 3.2 断点调试 4. 循环嵌套 JavaScript 是一种解释…

微服务框架 SpringCloud微服务架构 16 SpringAMQP 16.6 FanoutExchange

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构16 SpringAMQP16.6 FanoutExchange16.6.1 发布订阅 - Fanout Exchange16.6…

火山引擎DataTester:一个爆款游戏产品,是如何用A/B测试打磨出来的?

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 随着国内游戏用户数量趋于饱和&#xff0c;中国游戏产业也从高速成长期逐渐转型&#xff0c;市场成熟度提升&#xff0c;竞争趋于精细化。 随着游戏出海以及私域流…

Java开发学习(二十六)----SpringMVC返回响应结果

SpringMVC接收到请求和数据后&#xff0c;进行了一些处理&#xff0c;当然这个处理可以是转发给Service&#xff0c;Service层再调用Dao层完成的&#xff0c;不管怎样&#xff0c;处理完以后&#xff0c;都需要将结果告知给用户。 比如:根据用户ID查询用户信息、查询用户列表、…