Chapter6 机器人系统仿真(Ⅰ)---使用rviz集成urdf、xacro建造机器人模型

目录

一、rviz、urdf、xacro建造机器人的模型

1.1 概述

1.2 URDF集成Rviz基本流程

1.3 URDF语法详解

1.3.1 本节概述 

1.3.2 URDF语法详解01_robot

1.3.4 URDF语法详解03_joint

1.4 base_footprint优化urdf

1.5 URDF练习:建立四轮车模型

1.5.1 需求及基本实现流程

1.5.2 总成实现代码

1.5.3 底盘实现及参数解释

1.5.4 驱动轮实现及参数解释

1.5.5 万向轮实现及参数解释

1.5.6 URDF工具

1.6 URDF优化_xacro

1.6.1 引言

1.6.2  Xacro语法讲解

1.6.3  Xacro完整版使用流程

二、案例:运用rviz、xacro及本章所学知识做一个多功能小车

2.1 需求

2.2 实现分析:

2.3.大体流程

2.4 具体实现步骤

2.4.1 案例框架搭建

2.4.2 小车底盘实现及数据来源分析

2.4.3 小车摄像头实现及数据来源分析

2.4.4 小车雷达实现及数据来源分析


一、rviz、urdf、xacro建造机器人的模型

1.1 概述

1.本章讲什么

对于ROS新手而言,可能会有疑问:学习机器人操作系统,实体机器人是必须的吗?答案是否定的,机器人一般价格不菲,为了降低机器人学习、调试成本,在ROS中提供了系统的机器人仿真实现,通过仿真,可以实现大部分需求,本章主要就是围绕“仿真”展开的,比如,本章会介绍:

  • 如何创建并显示机器人模型;
  • 如何搭建仿真环境;
  • 如何实现机器人模型与仿真环境的交互。

2.本章预期学习目标

本章预期的学习目标如下:

  • 能够独立使用URDF创建机器人模型,并在Rviz和Gazebo中分别显示;
  • 能够使用Gazebo搭建仿真环境;
  • 能够使用机器人模型中的传感器(雷达、摄像头、编码器...)获取仿真环境数据

 3.机器人仿真应用的开发场景

机器人操作系统学习、开发与测试过程中,会遇到诸多问题,比如:

场景1:机器人一般价格不菲,学习ROS要购买一台机器人吗?

场景2:机器人与之交互的外界环境具有多样性,如何实现复杂的环境设计?

场景3:测试时,直接将未经验证的程序部署到实体机器人运行,安全吗?

...

在诸如此类的场景中,ROS中的仿真就显得尤为重要了。

4.机器人系统仿真概念

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

5.机器人系统仿真作用

Ⅰ.仿真优势:

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

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

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

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

Ⅱ.仿真缺陷

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

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

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

 6.机器人系统仿真相关组件

Ⅰ.URDF

URDF是 Unified Robot Description Format 的首字母缩写,直译为统一(标准化)机器人描述格式,可以以一种 XML 的方式描述机器人的部分结构,比如底盘、摄像头、激光雷达、机械臂以及不同关节的自由度.....,该文件可以被 C++ 内置的解释器转换成可视化的机器人模型,是 ROS 中实现机器人仿真的重要组件

Ⅱ.rviz

RViz 是 ROS Visualization Tool 的首字母缩写,直译为ROS的三维可视化工具。它的主要目的是以三维方式显示ROS消息,可以将 数据进行可视化表达。例如:可以显示机器人模型,可以无需编程就能表达激光测距仪(LRF)传感器中的传感 器到障碍物的距离,RealSense、Kinect或Xtion等三维距离传感器的点云数据(PCD, Point Cloud Data),从相机获取的图像值等

Ⅲ.gazebo

Gazebo是一款3D动态模拟器,用于显示机器人模型并创建仿真环境,能够在复杂的室内和室外环境中准确有效地模拟机器人。与游戏引擎提供高保真度的视觉模拟类似,Gazebo提供高保真度的物理模拟,其提供一整套传感器模型,以及对用户和程序非常友好的交互方式。

 7.三者关系

机器人的系统仿真是一种集成实现,主要包含三部分:

  • URDF 用于创建机器人模型

  • Gzebo 用于搭建仿真环境

  • Rviz 图形化的显示机器人各种传感器感知到的环境信息

三者应用中,只是创建 URDF 意义不大,一般需要结合 Gazebo 或 Rviz 使用,在 Gazebo 或 Rviz 中可以将 URDF 文件解析为图形化的机器人模型,一般的使用组合为:

  • 如果非仿真环境,那么使用 URDF 结合 Rviz 直接显示感知的真实环境信息

  • 如果是仿真环境,那么需要使用 URDF 结合 Gazebo 搭建仿真环境,并结合 Rviz 显示感知的虚拟环境信息

后续课程安排:

  • 先介绍 URDF 与 Rviz 集成使用,在 Rviz 中只是显示机器人模型,主要用于学习 URDF 语法

  • 再介绍 URDF 与 Gazebo 集成,主要学习 URDF 仿真相关语法以及仿真环境搭建

  • 最后集成 URDF 与 Gazebo 与 Rviz,实现综合应用

1.2 URDF集成Rviz基本流程

1.引言

前面介绍过,URDF 不能单独使用,需要结合 Rviz 或 Gazebo,URDF 只是一个文件,需要在 Rviz 或 Gazebo 中渲染成图形化的机器人模型,当前,首先演示URDF与Rviz的集成使用,因为URDF与Rviz的集成较之于URDF与Gazebo的集成更为简单,后期,基于Rviz的集成实现,我们再进一步介绍URDF语法。 

2.需求描述

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

3.实现流程

  1. 准备:新建功能包,导入依赖

  2. 核心:编写 urdf 文件

  3. 核心:在 launch 文件集成 URDF 与 Rviz

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

 4.具体实现(演示版)

Ⅰ.创建工作空间demo05_ws,完成编译环境、开发环境的配置

Ⅱ.新建功能包 urdf01_rviz ,导入依赖 urdf xacro

Ⅲ.创建四个文件夹

config存储配置信息;launch存储launch文件;meshes存储皮肤;urdf存储urdf文件

Ⅳ.编写urdf文件

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

 这个会创建一个盒状的机器人

 Ⅴ.创建launch文件并运行

<launch>
    <!-- 在参数服务器中载入 urdf 文件 -->
    <param  name = "robot_description" textfile = "$(find urdf_rviz)/urdf/urdf/demo01_hello.urdf"/>
    <!-- 启动rviz-->
    <node pkg = "rviz" type = "rviz" name = "rviz" />
</launch>

Ⅵ.优化

将这个保存到当前工作空间下的config文件夹里面就能实现不用设置 fix_frame ,启动axis与设置繁琐的设置啦! 

再设置launch文件

<launch>
    <!-- 在参数服务器中载入 urdf 文件 -->
    <param  name = "robot_description" textfile = "$(find urdf_rviz)/urdf/urdf/demo01_hello.urdf"/>
    <!-- 启动rviz-->
    <node pkg = "rviz" type = "rviz" name = "rviz"  args = "-d $(find urdf_rviz)/config/showmycar.rviz"/>
</launch>

1.3 URDF语法详解

1.3.1 本节概述 

URDF 文件是一个标准的 XML 文件,在 ROS 中预定义了一系列的标签用于描述机器人模型,机器人模型可能较为复杂,但是 ROS 的 URDF 中机器人的组成却是较为简单,可以主要简化为两部分:连杆(link标签) 与 关节(joint标签),接下来我们就通过案例了解一下 URDF 中的不同标签:

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

关于gazebo标签,后期在使用 gazebo 仿真时,才需要使用到,用于配置仿真环境所需参数,比如: 机器人材料属性、gazebo插件等,但是该标签不是机器人模型必须的,只有在仿真时才需设置

1.3.2 URDF语法详解01_robot

1.用处

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

2.属性

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

3.子标签

 其他标签都是子级标签

1.用处

urdf 中的 link 标签用于描述机器人某个部件(也即刚体部分)的外观和物理属性,比如: 机器人底座、轮子、激光雷达、摄像头...每一个部件都对应一个 link, 在 link 标签内,可以设计该部件的形状、尺寸、颜色惯性矩阵碰撞参数等一系列属性。

2.属性

  • name ---> 为连杆命名

3.子标签

  • visual ---> 描述外观(对应的数据是可视的)

    • geometry 设置连杆的形状

      • 标签1: box(盒状)

        • 属性:size=长(x) 宽(y) 高(z)
      • 标签2: cylinder(圆柱)

        • 属性:radius=半径 length=高度
      • 标签3: sphere(球体)

        • 属性:radius=半径
      • 标签4: mesh(为连杆添加皮肤)

        • 属性: filename=资源路径(格式:package://<packagename>/<path>/文件)
    • origin 设置偏移量与倾斜弧度

      • 属性1: xyz=x偏移 y便宜 z偏移

      • 属性2: rpy=x翻滚 y俯仰 z偏航 (单位是弧度)

    • metrial 设置材料属性(颜色)

      • 属性: name

      • 标签: color

        • 属性: rgba=红绿蓝权重值与透明度 (每个权重值以及透明度取值[0,1])
  • collision ---> 连杆的碰撞属性

  • Inertial ---> 连杆的惯性矩阵

4.案例实现:

Ⅰ.需求:分别生成长方体、圆柱与球体的机器人部件

 Ⅱ.rviz文件及launch文件编程

<!--设置不同形状的机器人部件-->

<robot name = "mycar">
    <link name = "base_link">
        <!--可视化标签-->
        <visual>
            <!--1.形状-->
            <geometry>
                <!--立方体 长宽高-->
                <!--box size = "0.3 0.2 0.1" /-->
                <!--圆柱-->
                <!--cylinder radius="0.1" length="2.0"/-->
                <!--球体-->
                <!--sphere radius="1.0"/-->
                <!--添加皮肤-->
                <mesh filename="package://urdf_rviz/meshes/autolabor_mini.stl" />
            </geometry>
            <!--2.偏移量以及倾斜弧度-->
            <!--3.设置颜色-->

        </visual>
    </link>

</robot>
<launch>
    <!-- 在参数服务器中载入 urdf 文件 -->
    <param  name = "robot_description" textfile = "$(find urdf_rviz)/urdf/urdf/demo02_link.urdf"/>
    <!-- 启动rviz-->
    <node pkg = "rviz" type = "rviz" name = "rviz"  args = "-d $(find urdf_rviz)/config/show_mycar.rviz"/>
</launch>

Ⅲ.补充 当建立                 <box size="0.5 0.2 0.1" />  的长方体时候

 

0.5 红(x) 0.2(y) 绿 0.1 蓝(z)

Ⅰ.需求:旋转机器人,以正方体为例介绍语法,再用于机器人 

Ⅱ.代码

<!--设置不同形状的机器人部件-->

<robot name = "mycar">
    <link name = "base_link">
        <!--可视化标签-->
        <visual>
            <!--1.形状-->
            <geometry>
                <!--立方体 长宽高-->
                <box size = "0.3 0.2 0.1" />
                <!--圆柱-->
                <!--cylinder radius="0.1" length="2.0"/-->
                <!--球体-->
                <!--sphere radius="1.0"/-->
                <!--添加皮肤-->
                <!--mesh filename="package://urdf_rviz/meshes/autolabor_mini.stl" /-->
            </geometry>
            <!--2.偏移量以及倾斜弧度-->
            <!--xyz设置机器人模型在xyz轴的偏移量 rpy主要用于设置倾斜弧度-->
            <origin xyz="3.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
            <!--3.设置颜色-->

        </visual>
    </link>

</robot>

这时x是三米

 Ⅲ.代码②

<!--设置不同形状的机器人部件-->

<robot name = "mycar">
    <link name = "base_link">
        <!--可视化标签-->
        <visual>
            <!--1.形状-->
            <geometry>
                <!--立方体 长宽高-->
                <!--box size = "0.3 0.2 0.1" /-->
                <!--圆柱-->
                <!--cylinder radius="0.1" length="2.0"/-->
                <!--球体-->
                <!--sphere radius="1.0"/-->
                <!--添加皮肤-->
                <mesh filename="package://urdf_rviz/meshes/autolabor_mini.stl" />
            </geometry>
            <!--2.偏移量以及倾斜弧度-->
            <!--xyz设置机器人模型在xyz轴的偏移量 rpy主要用于设置倾斜弧度-->
            <origin xyz="0.0 0.0 0.0" rpy="1.57 1.57 0.0"/>
            <!--3.设置颜色-->

        </visual>
    </link>

</robot>

 纯蓝小车

<!--设置不同形状的机器人部件-->

<robot name = "mycar">
    <link name = "base_link">
        <!--可视化标签-->
        <visual>
            <!--1.形状-->
            <geometry>
                <!--立方体 长宽高-->
                <!--box size = "0.3 0.2 0.1" /-->
                <!--圆柱-->
                <!--cylinder radius="0.1" length="2.0"/-->
                <!--球体-->
                <!--sphere radius="1.0"/-->
                <!--添加皮肤-->
                <mesh filename="package://urdf_rviz/meshes/autolabor_mini.stl" />
            </geometry>
            <!--2.偏移量以及倾斜弧度-->
            <!--xyz设置机器人模型在xyz轴的偏移量 rpy主要用于设置倾斜弧度-->
            <origin xyz="0.0 0.0 0.0" rpy="1.57 0.0 1.57"/>
            <!--3.设置颜色-->
            <material name = "car_color">
                <color rgba="0.0 0.0 1.0 1.0"/>
            </material>
        </visual>
    </link>

</robot>

1.3.4 URDF语法详解03_joint

1.joint是干什么用的

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

joint标签对应的数据在模型中是不可见的

2.属性

  • name ---> 为关节命名

  • type ---> 关节运动形式

    • continuous: 旋转关节,可以绕单轴无限旋转

    • revolute: 旋转关节,类似于 continues,但是有旋转角度限制

    • prismatic: 滑动关节,沿某一轴线移动的关节,有位置极限

    • planer: 平面关节,允许在平面正交方向上平移或旋转

    • floating: 浮动关节,允许进行平移、旋转运动

    • fixed: 固定关节,不允许运动的特殊关节

3. 子集标签

  • parent(必需的)

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

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

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

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

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

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

4.实现

Ⅰ.需求:创建机器人模型,底盘为长方体,在长方体的前面添加一摄像头,摄像头可以沿着 Z 轴 360 度旋转。

Ⅱ. 实现

①摄像头的偏移量计算:

<origin xyz="0.12 0.0 0.05" rpy="0.0 0.0 0.0"/>

小车的三围是 0.3 0.2 0.1 (长宽高),小车的中心为中心坐标点,因为摄像头要在最上面的平面上,因此距离要取0.05,y方向由于要在车体的正中间因此取0,x最多取0.15,这里我们取0.12.

②旋转轴设置:旋转时旋转的坐标轴 x,y均不运动,摄像头仅仅围绕z轴运动

③.code

<robot name="mycar">
    <link name="base_link">
        <visual>
            <geometry>
                <box size="0.3 0.2 0.1" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="blue">
                <color rgba="0 0 1.0 0.5" />
            </material>
        </visual>
    </link>

    <link name="camera">
        <visual>
            <geometry>
                <box size="0.02 0.05 0.05" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="red">
                <color rgba="1 0 0 0.5" />
            </material>
        </visual>
    </link>

    <joint name="camera2baselink" type="continuous">
        <parent link="base_link"/>
        <child link="camera" />
        <origin xyz="0.12 0 0.075" rpy="0 0 0" />
        <axis xyz="0 0 1" />
    </joint>

</robot>

④joint orginal z的计算

两个中心点相距离的位置:应该是两方各自除以2相加

(0.05/2)+(0.1/2)= 0.075

⑤设置launch文件

<launch>
    <!-- 在参数服务器中载入 urdf 文件 -->
    <param  name = "robot_description" textfile = "$(find urdf_rviz)/urdf/urdf/demo03_joint.urdf"/>
    <!-- 启动rviz-->
    <node pkg = "rviz" type = "rviz" name = "rviz"  args = "-d $(find urdf_rviz)/config/show_mycar.rviz"/>
    <!--
        若只有上面两条语句会抛出异常
        表现:摄像头显示位置与颜色异常
        提示:No transform from [camera] to [base_link]
        原因:rviz 中显示 URDF 时,必须发布不同部件之间的坐标系关系
        解决:ROS中提供了关于机器人模型显示的坐标发布相关结点(两个)
    -->
    <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>

⑤怎么让摄像头转起来呢:添加节点控制关节运动节点

⑥最终效果

 

1.4 base_footprint优化urdf

Ⅰ.需求:前面实现的机器人模型是半沉到地下的,因为默认情况下: 底盘的中心点位于地图原点上,所以会导致这种情况产生,可以使用的优化策略,将初始 link 设置为一个尺寸极小的 link(比如半径为 0.001m 的球体,或边长为 0.001m 的立方体),然后再在初始 link 上添加底盘等刚体,这样实现,虽然仍然存在初始link半沉的现象,但是基本可以忽略了。这个初始 link 一般称之为 base_footprint

Ⅱ.代码逻辑:

①创建一个 0.001*0.001*0.001的立方体

②创建一个 0.3*0.2*0.1的底盘

③创建一个 0.02*0.05*0.05的摄像头

④创建约束 basefootprint&baselink 固定约束 z的运算为盒子的一半0.05

⑤创建约束 camera2baselink 旋转约束 z

Ⅲ.code

<robot name="mycar">

    <link name="base_footprint">
        <visual>
            <geometry>
                <box size="0.001 0.001 0.001" />
            </geometry>
        </visual>
    </link>

    <link name="base_link">
        <visual>
            <geometry>
                <box size="0.3 0.2 0.1" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="blue">
                <color rgba="0 0 1.0 0.5" />
            </material>
        </visual>
    </link>

    <link name="camera">
        <visual>
            <geometry>
                <box size="0.02 0.05 0.05" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="red">
                <color rgba="1 0 0 0.5" />
            </material>
        </visual>
    </link>

    <joint name="basefootprint2baselink" type="fixed">
        <parent link="base_footprint"/>
        <child link="base_link" />
        <origin xyz="0 0 0.05" rpy="0 0 0" />
    </joint>

    <joint name="camera2baselink" type="continuous">
        <parent link="base_link"/>
        <child link="camera" />
        <origin xyz="0.12 0 0.075" rpy="0 0 0" />
        <axis xyz="0 0 1" />
    </joint>

</robot>
<launch>

    <param name="robot_description" textfile="$(find urdf_rviz)/urdf/urdf/demo04_basefoot.urdf" />
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf_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>

Ⅳ.数据解释

basefootprint2baselink的 origin xyz:小球半径忽略不计,两者中心点相聚为 child.z - parent.z = 底盘中心点 - 0 = 0.05

camera2baselink的 origin xyz:两者中心点相聚为 child.z - parent.z = 0.075(前面计算过)

1.5 URDF练习:建立四轮车模型

1.5.1 需求及基本实现流程

1.需求:

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

 2.实现流程

创建机器人模型可以分步骤实现

  1. 新建 urdf 文件,并与 launch 文件集成

  2. 搭建底盘

  3. 在底盘上添加两个驱动轮

  4. 在底盘上添加两个万向轮

1.5.2 总成实现代码

Ⅰ.code

<robot name="mycar">
    <link name="base_footprint">
        <visual>
            <geometry>
                <sphere radius="0.001" />
            </geometry>
        </visual>
    </link>


    <link name="base_link">
        <visual>
            <geometry>
                <cylinder radius="0.1" length="0.08" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="yellow">
                <color rgba="0.8 0.3 0.1 0.5" />
            </material>
        </visual>
    </link>

    <joint name="base_link2base_footprint" type="fixed">
        <parent link="base_footprint" />
        <child link="base_link"/>
        <origin xyz="0 0 0.055" />
    </joint>

    <link name="left_wheel">
        <visual>
            <geometry>
                <cylinder radius="0.0325" length="0.015" />
            </geometry>
            <origin xyz="0 0 0" rpy="1.5705 0 0" />
            <material name="black">
                <color rgba="0.0 0.0 0.0 1.0" />
            </material>
        </visual>

    </link>

    <joint name="left_wheel2base_link" type="continuous">
        <parent link="base_link" />
        <child link="left_wheel" />
        <origin xyz="0 0.1 -0.0225" />
        <axis xyz="0 1 0" />
    </joint>


    <link name="right_wheel">
        <visual>
            <geometry>
                <cylinder radius="0.0325" length="0.015" />
            </geometry>
            <origin xyz="0 0 0" rpy="1.5705 0 0" />
            <material name="black">
                <color rgba="0.0 0.0 0.0 1.0" />
            </material>
        </visual>

    </link>

    <joint name="right_wheel2base_link" type="continuous">
        <parent link="base_link" />
        <child link="right_wheel" />
        <origin xyz="0 -0.1 -0.0225" />
        <axis xyz="0 1 0" />
    </joint>


    <link name="front_wheel">
        <visual>
            <geometry>
                <sphere radius="0.0075" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="black">
                <color rgba="0.0 0.0 0.0 1.0" />
            </material>
        </visual>
    </link>

    <joint name="front_wheel2base_link" type="continuous">
        <parent link="base_link" />
        <child link="front_wheel" />
        <origin xyz="0.0925 0 -0.0475" />
        <axis xyz="1 1 1" />
    </joint>

    <link name="back_wheel">
        <visual>
            <geometry>
                <sphere radius="0.0075" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="black">
                <color rgba="0.0 0.0 0.0 1.0" />
            </material>
        </visual>
    </link>

    <joint name="back_wheel2base_link" type="continuous">
        <parent link="base_link" />
        <child link="back_wheel" />
        <origin xyz="-0.0925 0 -0.0475" />
        <axis xyz="1 1 1" />
    </joint>

</robot>
<launch>

    <param name="robot_description" textfile="$(find urdf_rviz)/urdf/urdf/demo05_testu.urdf" />
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf_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>

1.5.3 底盘实现及参数解释

<!-- 
        参数
            形状:圆柱 
            半径:10     cm 
            高度:8      cm 
            离地:1.5    cm

    -->
    <link name="base_link">
        <visual>
            <geometry>
                <cylinder radius="0.1" length="0.08" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="yellow">
                <color rgba="0.8 0.3 0.1 0.5" />
            </material>
        </visual>
    </link>

    <joint name="base_link2base_footprint" type="fixed">
        <parent link="base_footprint" />
        <child link="base_link"/>
        <origin xyz="0 0 0.055" />
    </joint>

joint的xyz的设置:由于底盘的中心在其中心点,距离平面距离为 8cm/2 = 4cm,由于还要设置离地间隙,于是basefootprint相对于baselink的z坐标为 childz-parentz = 0.04 + 0.015 - 0

1.5.4 驱动轮实现及参数解释

<!-- 添加驱动轮 -->
    <!--
        驱动轮是侧翻的圆柱
        参数
            半径: 3.25 cm
            宽度: 1.5  cm
            颜色: 黑色
        关节设置:
            x = 0
            y = 底盘的半径 + 轮胎宽度 / 2
            z = 离地间距 + 底盘长度 / 2 - 轮胎半径 = 1.5 + 4 - 3.25 = 2.25(cm)
            axis = 0 1 0
    -->
    <link name="left_wheel">
        <visual>
            <geometry>
                <cylinder radius="0.0325" length="0.015" />
            </geometry>
            <origin xyz="0 0 0" rpy="1.5705 0 0" />
            <material name="black">
                <color rgba="0.0 0.0 0.0 1.0" />
            </material>
        </visual>

    </link>

    <joint name="left_wheel2base_link" type="continuous">
        <parent link="base_link" />
        <child link="left_wheel" />
        <origin xyz="0 0.1 -0.0225" />
        <axis xyz="0 1 0" />
    </joint>


    <link name="right_wheel">
        <visual>
            <geometry>
                <cylinder radius="0.0325" length="0.015" />
            </geometry>
            <origin xyz="0 0 0" rpy="1.5705 0 0" />
            <material name="black">
                <color rgba="0.0 0.0 0.0 1.0" />
            </material>
        </visual>

    </link>

    <joint name="right_wheel2base_link" type="continuous">
        <parent link="base_link" />
        <child link="right_wheel" />
        <origin xyz="0 -0.1 -0.0225" />
        <axis xyz="0 1 0" />
    </joint>

如下图--驱动轮的rpy:前后滚动,绕x轴旋转,设置rpy x = 1.5705

左驱动轮的joint的origin xyz:x没有偏移 y是(leftwheel.y - baselink.y = 0.01 - 0)

z的偏移是:车轮的中心点到地面的距离刚好是车轮的半径0.0325m

chlid.z - base.z = (0.0325)- (0.04+0.015)

右驱动轮除了y是取相反值之外没有区别!

驱动轮的joint的axis :沿着哪个轴运动,左轮添加到车体左侧,y轴运动,y为1

1.5.5 万向轮实现及参数解释

<!-- 添加万向轮(支撑轮) -->
    <!--
        参数
            形状: 球体
            半径: 0.75 cm
            颜色: 黑色

        关节设置:
            x = 自定义(底盘半径 - 万向轮半径) = 0.1 - 0.0075 = 0.0925(cm)
            y = 0
            z = 底盘长度 / 2 + 离地间距 / 2 = 0.08 / 2 + 0.015 / 2 = 0.0475 
            axis= 1 1 1

    -->
    <link name="front_wheel">
        <visual>
            <geometry>
                <sphere radius="0.0075" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="black">
                <color rgba="0.0 0.0 0.0 1.0" />
            </material>
        </visual>
    </link>

    <joint name="front_wheel2base_link" type="continuous">
        <parent link="base_link" />
        <child link="front_wheel" />
        <origin xyz="0.0925 0 -0.0475" />
        <axis xyz="1 1 1" />
    </joint>

    <link name="back_wheel">
        <visual>
            <geometry>
                <sphere radius="0.0075" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="black">
                <color rgba="0.0 0.0 0.0 1.0" />
            </material>
        </visual>
    </link>

    <joint name="back_wheel2base_link" type="continuous">
        <parent link="base_link" />
        <child link="back_wheel" />
        <origin xyz="-0.0925 0 -0.0475" />
        <axis xyz="1 1 1" />
    </joint>

joint前轮的取值:
origin x:chlid_front.x - base_link.x = (底盘半径 -万向轮半径)-0 = 0.1 - 0.0075

origin y:0

origin z:chlid_front.z - base_link.z = 万向轮半径 - (底盘高/2 +0.015) = 0.0075 - (底盘高/2+0.015) = 0.0075-0.055=0.0475

1.5.6 URDF工具

1.check_urdf 命令可以检查复杂的urdf文件是否存在语法问题

2.urdf_to_graphiz 可以查看urdf模型结构

1.6 URDF优化_xacro

1.6.1 引言

1.为什么需要xacro:

问题1:在设计关节位置时,需要按照一定的公式计算,公式是固定的,但是在URDF中依赖于人工计算,存在不便,容易计算失误,且当某些参数发生改变时,还需要重新计算。

问题2:URDF中部分内容是高度重复的,驱动轮与支撑轮的设计实现,不同轮子只是参数不同,形状颜色翻转量都是一样的,考虑封装。 

2.概念

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

3.原理

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

1.6.2  Xacro语法讲解

1.需求描述

使用xacro优化上节的驱动轮实现,需要使用变量封装底盘的半径、高度、使用动态数学公式动态计算底盘的关节点坐标,使用xacro宏封装轮子重复的代码并调用宏创建两个轮子。 

2.xacro是干什么的:

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

xmlns:xacro="http://wiki.ros.org/xacro"

3.属性与算数运算

Ⅰ.属性定义: 

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

 Ⅱ.属性调用

${属性名称}

Ⅲ.算术运算

${数学表达式}

4.属性与算数运算示例

<robot name = "mycar" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <!--  1. 属性定义  -->
    <xacro:property name = "PI"  value = "3.1415927"/>
    <xacro:property name = "radius" value = "0.03" />
    <!--  2.属性调用  -->
    <myuserpropertyxxx name = "${PI}"/>
    <myuserpropertyxxx name = "${radius}"/>
    <!--  3.算术运算  -->
    <myuserpropertyyy result = "${PI/2}"/>
    <myuserpropertyyy result = "${radius*2}"/>
</robot>

命令行调用

rosrun xacro xacro demo02_field.urdf.xacro

执行结果

liuhongwei@liuhongwei-virtual-machine:~/demo05_ws/src/urdf_rviz/urdf/xacro$ rosrun xacro xacro demo02_field.urdf.xacro 
<?xml version="1.0" encoding="utf-8"?>
<!-- =================================================================================== -->
<!-- |    This document was autogenerated by xacro from demo02_field.urdf.xacro        | -->
<!-- |    EDITING THIS FILE BY HAND IS NOT RECOMMENDED                                 | -->
<!-- =================================================================================== -->
<robot name="mycar">
  <!--  2.属性调用  -->
  <myuserpropertyxxx name="3.1415927"/>
  <myuserpropertyxxx name="0.03"/>
  <!--  3.算术运算  -->
  <myuserpropertyyy result="1.57079635"/>
  <myuserpropertyyy result="0.06"/>
</robot>

5.宏

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

Ⅰ.宏定义

<xacro:macro name = "宏名称" params = "参数1 参数2...">
    参数调用格式:${参数名}
</xacro:macro>

 Ⅱ.宏调用

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

6.宏示例 

<robot name = "mycar" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <!--  1. 宏定义  -->
    <xacro:macro name = "getSum"  params = "num1 num2">
        <result value = "${num1 + num2}" />
    </xacro:macro>
    <!--  2. 宏调用  -->
    <xacro:getSum num1 = "1" num2 = "5"/>
</robot>

命令行调用

rosrun xacro xacro demo03_xacro.urdf.xacro 

执行结果

liuhongwei@liuhongwei-virtual-machine:~/demo05_ws/src/urdf_rviz/urdf/xacro$ rosrun xacro xacro demo03_xacro.urdf.xacro 
<?xml version="1.0" encoding="utf-8"?>
<!-- =================================================================================== -->
<!-- |    This document was autogenerated by xacro from demo03_xacro.urdf.xacro        | -->
<!-- |    EDITING THIS FILE BY HAND IS NOT RECOMMENDED                                 | -->
<!-- =================================================================================== -->
<robot name="mycar">
  <result value="6"/>
</robot>

7.文件包含 

Ⅰ.应用场景:机器人由多组件组成、不同部件可能封装为不同的xacro文件,最后再将不同的文件集成,组合为完整机器人,可以用文件包含实现。

Ⅱ.语法

<robot name = "mycar" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <!--  1. 演示文件包含  -->
    <xacro:include filename = "demo02_field.urdf.xacro"/>
    <xacro:include filename = "demo03_xacro.urdf.xacro"/>
</robot>

Ⅲ.执行效果

liuhongwei@liuhongwei-virtual-machine:~/demo05_ws/src/urdf_rviz/urdf/xacro$ rosrun xacro xacro demo04_sum.urdf.xacro 
<?xml version="1.0" encoding="utf-8"?>
<!-- =================================================================================== -->
<!-- |    This document was autogenerated by xacro from demo04_sum.urdf.xacro          | -->
<!-- |    EDITING THIS FILE BY HAND IS NOT RECOMMENDED                                 | -->
<!-- =================================================================================== -->
<robot name="mycar">
  <!--  2.属性调用  -->
  <myuserpropertyxxx name="3.1415927"/>
  <myuserpropertyxxx name="0.03"/>
  <!--  3.算术运算  -->
  <myuserpropertyyy result="1.57079635"/>
  <myuserpropertyyy result="0.06"/>
  <result value="6"/>
</robot>

1.6.3  Xacro完整版使用流程

1.需求

使用xacro优化urdf版的小车底盘模型实现

2.具体实现

Ⅰ.新建文件 demo05_carbase.urdf.xacro 

Ⅱ.编写一段时间看看,确保没有错误在进行,此时我们完成了底盘的设计和底盘与footprint的接合,demo05_carbase.urdf.xacro 文件如下

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

    <xacro:property name = "footfrintradius" value = "0.001"/>
    <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_footprint">
        <visual>
            <geometry>
                <sphere radius="${footfrintradius}" />
            </geometry>
        </visual>
    </link>

    <link name="base_link">
        <visual>
            <geometry>
                <cylinder radius="0.1" length="0.08" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="yellow">
                <color rgba="0.8 0.3 0.1 0.5" />
            </material>
        </visual>
    </link>
    <joint name="base_link2base_footprint" type="fixed">
        <parent link="base_footprint" />
        <child link="base_link"/>
        <origin xyz="0 0 0.055" />
    </joint>

</robot>

Ⅲ.输入命令

rosrun xacro xacro demo05_carbase.urdf.xacro > demo05_car_base.urdf

Ⅳ.发现生成文件 demo05_car_base.urdf

<?xml version="1.0" encoding="utf-8"?>
<!-- =================================================================================== -->
<!-- |    This document was autogenerated by xacro from demo05_carbase.urdf.xacro      | -->
<!-- |    EDITING THIS FILE BY HAND IS NOT RECOMMENDED                                 | -->
<!-- =================================================================================== -->
<robot name="mycar">
  <link name="base_footprint">
    <visual>
      <geometry>
        <sphere radius="0.001"/>
      </geometry>
    </visual>
  </link>
  <link name="base_link">
    <visual>
      <geometry>
        <cylinder length="0.08" radius="0.1"/>
      </geometry>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <material name="yellow">
        <color rgba="0.8 0.3 0.1 0.5"/>
      </material>
    </visual>
  </link>
  <joint name="base_link2base_footprint" type="fixed">
    <parent link="base_footprint"/>
    <child link="base_link"/>
    <origin xyz="0 0 0.055"/>
  </joint>
</robot>

Ⅴ.实现xacro与rviz的集成

①先将rxiz文件转换出urdf文件,然后集成

<launch>

    <param name="robot_description" textfile="$(find urdf_rviz)/urdf/xacro/demo05_car_base.urdf" />
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf_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>

执行:

 

②直接在launch文件中直接加载xacro

执行:注意command属性咋写的!!!!!!!!!!!!!

<launch>

    <param name="robot_description" command="$(find xacro)/xacro $(find urdf_rviz)/urdf/xacro/demo05_carbase.urdf.xacro" />
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf_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>

执行结果相同

Ⅵ.继续完成驱动轮万向轮的封装

比较两个驱动轮,link比较name的差异,joint比较也有name的差异,还有y方向上偏移量的差异,还有各种参数的设计,计算的逻辑

因此把右轮的数据删掉,尝试用左轮进行复用

wheel_name 可取 left 或 right 

flag 可取 1 或 -1

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

    <xacro:property name = "footfrintradius" value = "0.001"/>
    <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 }" />

    <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)}" />

    <xacro:property name = "small_wheel_radius" value = "0.0075" />
    <xacro:property name = "small_joint_z" value = "${-(base_length/2+lidi-small_wheel_radius)}" />



    <link name="base_footprint">
        <visual>
            <geometry>
                <sphere radius="${footfrintradius}" />
            </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.8 0.3 0.1 0.5" />
            </material>
        </visual>
    </link>
    <joint name="base_link2base_footprint" type="fixed">
        <parent link="base_footprint" />
        <child link="base_link"/>
        <origin xyz="0 0 ${base_joint_z}" />
    </joint>

   
    <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="black">
                <color rgba="0.0 0.0 0.0 1.0" />
            </material>
        </visual>
        </link>
        <joint name="${wheel_name}2link" type="continuous">
            <parent link="base_link" />
            <child link="${wheel_name}_wheel" />
            <origin xyz="0 ${0.1 * flag} ${wheel_joint_z}" />
            <axis xyz="0 1 0" />
        </joint>
    </xacro:macro>

    <xacro:wheel_func wheel_name = "left" flag = "1"/>
    <xacro:wheel_func wheel_name = "right" flag = "-1"/>


    <xacro:macro name = "small_wheel_func" params = "small_wheel_name flag">
        <link name="${small_wheel_name}_wheel">
            <visual>
                <geometry>
                    <sphere radius="${small_wheel_radius}" />
                </geometry>
                <origin xyz="0 0 0" rpy="0 0 0" />
                <material name="black">
                    <color rgba="0.0 0.0 0.0 1.0" />
                </material>
            </visual>
        </link>

        <joint name="${small_wheel_name}2link" type="continuous">
            <parent link="base_link" />
            <child link="${small_wheel_name}_wheel" />
            <origin xyz="${0.08*flag} 0 ${small_joint_z}" />
            <axis xyz="1 1 1" />
        </joint>
    </xacro:macro>
    <xacro:small_wheel_func small_wheel_name = "front" flag = "1"/>
    <xacro:small_wheel_func small_wheel_name = "back" flag = "-1"/>

</robot>

二、案例:运用rviz、xacro及本章所学知识做一个多功能小车

2.1 需求

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

2.2 实现分析:

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

2.3.大体流程

Ⅰ.先编写摄像头和雷达的xacro文件

Ⅱ.编写一个组合文件,组合底盘,摄像头和雷达

Ⅲ.通过launch文件启动rviz并显示模型 

2.4 具体实现步骤

2.4.1 案例框架搭建

Ⅰ.搭建框架

准备两个xacro文件,分别是摄像头和雷达的,再编写一个汇总的xacro文件,最后集成进launch文件

Ⅱ.car.urdf.xacro文件实现

<robot name = "mycar" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <xacro:include filename = "demo05_carbase.urdf.xacro"/>
    <xacro:include filename = "demo06_carcamera.urdf.xacro"/>
    <xacro:include filename = "demo07_carlaser.urdf.xacro"/>
</robot>

Ⅲ.launch文件实现

<launch>
    <param name="robot_description" command="$(find xacro)/xacro $(find urdf_rviz)/urdf/xacro/car.urdf.xacro" />
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf_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>

2.4.2 小车底盘实现及数据来源分析

demo05_carbase.urdf.xacro实现

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

    <xacro:property name = "footfrintradius" value = "0.001"/>
    <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 }" />

    <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 = "${wheel_radius - (base_length/2 +lidi)}" />

    <xacro:property name = "small_wheel_radius" value = "0.0075" />
    <xacro:property name = "small_joint_z" value = "${-(base_length/2+lidi-small_wheel_radius)}" />



    <link name="base_footprint">
        <visual>
            <geometry>
                <sphere radius="${footfrintradius}" />
            </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.8 0.3 0.1 0.5" />
            </material>
        </visual>
    </link>
    <joint name="base_link2base_footprint" type="fixed">
        <parent link="base_footprint" />
        <child link="base_link"/>
        <origin xyz="0 0 ${base_joint_z}" />
    </joint>

   
    <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="black">
                <color rgba="0.0 0.0 0.0 1.0" />
            </material>
        </visual>
        </link>
        <joint name="${wheel_name}2link" type="continuous">
            <parent link="base_link" />
            <child link="${wheel_name}_wheel" />
            <origin xyz="0 ${0.1 * flag} ${wheel_joint_z}" />
            <axis xyz="0 1 0" />
        </joint>
    </xacro:macro>

    <xacro:wheel_func wheel_name = "left" flag = "1"/>
    <xacro:wheel_func wheel_name = "right" flag = "-1"/>


    <xacro:macro name = "small_wheel_func" params = "small_wheel_name flag">
        <link name="${small_wheel_name}_wheel">
            <visual>
                <geometry>
                    <sphere radius="${small_wheel_radius}" />
                </geometry>
                <origin xyz="0 0 0" rpy="0 0 0" />
                <material name="black">
                    <color rgba="0.0 0.0 0.0 1.0" />
                </material>
            </visual>
        </link>

        <joint name="${small_wheel_name}2link" type="continuous">
            <parent link="base_link" />
            <child link="${small_wheel_name}_wheel" />
            <origin xyz="${0.08*flag} 0 ${small_joint_z}" />
            <axis xyz="1 1 1" />
        </joint>
    </xacro:macro>
    <xacro:small_wheel_func small_wheel_name = "front" flag = "1"/>
    <xacro:small_wheel_func small_wheel_name = "back" flag = "-1"/>

</robot>

2.4.3 小车摄像头实现及数据来源分析

demo06_carcamera.urdf.xacro的实现

①分析摄像头有什么属性

参数:摄像头自身属性(长宽高)、关节属性(xyz偏移量)

显然,偏移量x方向有(小车左边),y方向没有(小车的中心),z有

x:自己指定即可

z:小车底盘的一半 + 摄像头高度的一半 

②设计连杆及关节

③code

<robot name = "my_camera" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <xacro:property name = "camera_x" value = "0.02" />
    <xacro:property name = "camera_y" value = "0.05" />
    <xacro:property name = "camera_z" value = "0.05" />
    <xacro:property name = "joint_camera_x" value = "0.08" />
    <xacro:property name = "joint_camera_y" value = "0" />
    <xacro:property name = "base_length" value = "0.08" />
    <xacro:property name = "joint_camera_z" value = "${camera_z /2 +base_length/2 }" />
    
    <link name="camera">
        <visual>
            <geometry>
                <box size="${camera_x} ${camera_y} ${camera_z}"/>
            </geometry>
            <material name = "no" >
                <color rgba = "3 3 3 0.3"/>
            </material>
        </visual>
    </link>


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

④运行结果

2.4.4 小车雷达实现及数据来源分析

 demo07_carlaser.urdf.xacro的实现

①分析雷达有什么属性:雷达支架和雷达自身

雷达支架:圆柱形的(高,半径)、支架的关节偏移量xyz

雷达:圆柱形的(高,半径)、雷达的关节偏移量xyz

②雷达支架的属性设置

雷达直接安装在车体的正中心 x y 都是0 

z上的偏移量是 (baselink_z /2 + laser_z /2)

②雷达的属性设置

雷达直接安装在雷达支架的正中心 x y 都是0 

z上的偏移量是 (laser_support_z /2 + laser_z /2)

③code

<robot name = "mylaser" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <xacro:property name = "support_radius" value = "0.01" />
    <xacro:property name = "support_length" value = "0.15" />
    <xacro:property name = "laser_radius" value = "0.03" />
    <xacro:property name = "laser_length" value = "0.05" />

    <xacro:property name = "joint_support_x" value = "0.00" />
    <xacro:property name = "joint_support_y" value = "0.00" />
    <xacro:property name = "joint_support_z" value = "${base_length / 2 +support_length / 2}" />
    <xacro:property name = "joint_laser_x" value = "0.00" />
    <xacro:property name = "joint_laser_y" value = "0.00" />
    <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="sha">
                <color rgba="0.8 0.5 0.0 0.5"/>
            </material>
        </visual>
    </link>

    <joint name="support2base" type="fixed">
        <parent link = "base_link"/>
        <child link = "support" />
        <origin xyz = "${joint_support_x} ${joint_support_y} ${joint_support_z}" rpy = "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="shav">
                <color rgba="0.0 0.0 0.0 0.5"/>
            </material>
        </visual>
    </link>

    <joint name="laser2support" 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>

④运行

  • 6
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

APS2023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值