奥特学园ROS笔记--6(227-285)

目录

227节

228-230节 概述

231节 URDF集成Rviz基本流程

232节 上一节优化

------------URDF语法-----------

233节 URDF语法-0 (robot标签)

238-241节 URDF语法-2 joint-1

242节 优化

244-248节 URDF练习

249节 URDF工具

 ------------URDF优化_xacro------------

250节

251节 Xacro快速体验

252节 xacro语法01

253节 xacro语法02 函数

254节 xacro语法03 宏

255节 xacro语法04 文件包含

256节 xacro完整使用流程

257-258节 补齐256节代码

259-263节 xacro实操

------------使用arbotix------------

264节 控制机器人运动

265节 安装

266节 添加 Arbotix 配置文件

267节 集成arbotix节点

------------URDF集成Gazebo------------

270-271节 基本集成流程案例

273节 urdf集成gazebo相关设置

273-275 URDF集成Gazebo实操

276节 gazebo仿真环境载入

277节 gazebo创建仿真环境

------------URDF、GAZEBO、Rviz综合应用------------

279节 roscontrol简介

280节 运动控制实现流程

281节 rviz查看里程计消息

282节 雷达仿真及其显示

283节 摄像头仿真

284节 深度相机仿真

285节 点云数据显示

本章小结


227节

本章会介绍:

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

围绕以上三个软件展开

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

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

228-230节 概述

机器人建模(URDF)、创建仿真环境(Gazebo)以及感知环境(Rviz)

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

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

以“ros- [ROS_DISTRO] -desktop-full”命令安装ROS时,RViz会默认被安装。

运行使用命令rvizrosrun rviz rviz

如果rviz没有安装,请调用如下命令自行安装:

sudo apt install ros-[ROS_DISTRO]-rviz

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

以“ros- [ROS_DISTRO] -desktop-full”命令安装ROS时,gzebo会默认被安装。

运行使用命令gazeborosrun gazebo_ros gazebo

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

以“ros- [ROS_DISTRO] -desktop-full”命令安装ROS时,gzebo会默认被安装。

运行使用命令gazeborosrun gazebo_ros gazebo

另请参考:

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

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

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

素材链接:

复制链接后找到一个文件夹下打开终端输入:

 下载不动可以试试用手机热点

231节 URDF集成Rviz基本流程

URDF 不能单独使用,需要结合 Rviz 或 Gazebo,URDF 只是一个文件,需要在 Rviz 或 Gazebo 中渲染成图形化的机器人模型

实现流程:

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

  2. 核心:编写 urdf 文件

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

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

步骤1:

创建功能包,同时导入下图一中的依赖

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

urdf: 存储 urdf 文件的目录

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

config: 配置文件

launch: 存储 launch 启动文件

 步骤2:

新建一个子级文件夹:urdf(可选),文件夹中添加一个.urdf文件,复制如下内容(创建一个盒子状态的机器人)

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

代码含义部分之后会介绍

步骤3:launch文件编写

<launch>
    <!-- 载入urdf文件 -->
    <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/urdf/demo01_helloworld.urdf"/>
    <!-- 启动rviz -->
    <node pkg="rviz" type="rviz" name="rviz"/>
</launch>

然后c+s+b编译

然后点击左下角add,添加robotmodel

然后左边有报错:

需要修改fixed frame和之前的urdf文件中的link_name一致

 

然后左下角add添加坐标系就可以得到以下效果

232节 上一节优化

为了避免第二次打开rviz之后还需要配置上一节中的哪些步骤,:即第二次打开urdf配置好了

将其保存到onfug文件夹下,第二次使用的时候载入即可:

左上角file,save xx as,输入名字后保存即可。

读入之前配置的rviz文件:

修改上一节的.launch文件,加入args后面这段

<launch>
    <!-- 载入urdf文件 -->
    <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/urdf/demo01_helloworld.urdf"/>
    <!-- 启动rviz -->
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz"/>
</launch>

------------URDF语法-----------

233节 URDF语法-0 (robot标签)

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

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

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

另请参考:

robot

robot标签作为根标签,所有的 link 和 joint 以及其他标签都必须包含在 robot 标签内,在该标签内可以通过 name 属性设置机器人模型的名称

 link 标签用于描述机器人某个部件(也即刚体部分)的外观和物理属性,比如: 机器人底座、轮子、激光雷达、摄像头...

子标签

  • 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 ---> 连杆的惯性矩阵

在此,只演示visual使用。

案例:分别生成长方体、圆柱与球体的机器人部件

launch文件配置

<launch>
    <!-- 载入urdf文件 -->
    <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/urdf/demo02_link.urdf"/>
    <!-- 启动rviz -->
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz"/>
</launch>

1形状

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

<robot name="mycar">
    <link name="base_link">
        <!-- 可视化标签 -->
        <visual>
            <!-- 形状 -->
            <geometry>
                <!-- 立方体 -->
                <!-- <box size="0.3 0.2 0.1"/> -->
                <!-- 圆柱,半径和长度 -->
                <!-- <cylinder radius="0.5" length="0.1" /> -->
                <!-- 球体,半径-->
                <!-- <sphere radius="0.3" /> -->
                <!-- 皮肤 -->
                <mesh filename="package://urdf01_rviz/meshes/autolabor_mini.stl"/>
            </geometry>
            <!-- 偏移量和倾斜 -->
            <!-- 
                xyz用于设置xyz上的偏移量
                rpy用于设置倾斜弧度r(翻滚)p(俯仰)y(偏航)
             -->
            <origin xyz="0 0 0" rpy="1.57 0 0" />

            <!-- 颜色 -->
        </visual>
    </link>


</robot>

<mesh>标签:可以将写好的模型stl文件进行导入

将之前下载的文件夹sim_demo里面的文件复制到下路径,然后编写mesh标签

2偏移量和欧拉角

偏移量即为空间上所处的位置,欧拉角调整的是其的姿态

上面使用mesh标签导入的时候发现小车竖起来了,我们可以调整它的欧拉角,合理需要沿着x(红色)轴顺时针旋转90度(从原点向x轴延伸方向看),即为正方向旋转0度,所以代码改为

<origin xyz="0 0 0" rpy="1.57 0 0" />

即可

3颜色:

238-241节 URDF语法-2 joint-1

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

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

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用于设置围绕哪个关节轴运动。

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

代码中的前两个link在上一节学过

<!-- 
    需求: 设置机器人底盘并添加摄像头
 -->
<robot name="mycar">
    <!-- 底盘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="car_color">
                <color rgba="0.8 0.5 0 0.5" />
            </material>
        </visual>
    </link>

    <!-- 摄像头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="camera_color">
                <color rgba="0 0 1 0.5" />
            </material>
        </visual>
    </link>

    <!-- 关节 -->
    <joint name="camera2base" type="continuous">
        <!-- 父级link和子级link -->
        <parent link="base_link"/>
        <child link="camera" />
        <!-- 需要计算两个 link 的物理中心之间的偏移量 -->
        <origin xyz="0.12 0 0.05" rpy="0 0 0" />
        <!-- 设置旋转参考的坐标轴,这里围绕z轴旋转 -->
        <axis xyz="0 0 1" />
    </joint>

</robot>

这里要注意joint文件不能和之前那样书写,不然就会建模失败。

需要添加两个节点(注意编写玩要编译):

<launch>
    <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/urdf/demo03_joint.urdf" />
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" /> 
    <!-- 如果只有上述两个语句就会出现问题:
        摄像头显示没有达到预期的位置
        因为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" />
    <!-- 可选:用于控制关节运动的节点 -->
    <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" />

</launch>

上图这里第三个节点用于对两个刚体之间的运动(用于测试关节是否运行正常)

运行报错的话这里可以下载:

sudo apt-get install ros-melodic-joint-state-publisher-gui

然后就可以了

注:

这里可能会出现问题:摄像头并没有在车的表面,因为我们的joint相对位置是在相对于两者的几何中心的,我们并没有考虑到摄像头的体积,所以只需要在相对偏移量的基础上添加上摄像头高度的一般即可(改为0.75)。

242节 优化

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

理解:之前的parentlink是baselink即车体是摄像头的parent,现在又将一个很小的物体作为车体的parent,此时只需要将这个小物体抬高,即可将整个车子抬高。以下在上一节的基础上添加了一个小的link和一个joint

<!--
    使用 base_footprint 优化,添加一个极小的link,再去关联初始link与base_link,
    关节高度刚好和baselink下沉的高度一致(半个底盘高度)
-->

<robot name="mycar">

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

    <!-- 底盘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="car_color">
                <color rgba="0.8 0.5 0 0.5" />
            </material>
        </visual>
    </link>

    <!-- 摄像头link -->
    <link name="camera">
        <visual>
            <geometry>
                <box size="0.02 0.05 0.05" />
            </geometry>
            <!-- 先使用默认(后期需要修改) -->
            <origin xyz="0 0 0.025" rpy="0 0 0" />
            <material name="camera_color">
                <color rgba="0 0 1 0.5" />
            </material>
        </visual>
    </link>

    <!-- 关节 -->
    <joint name="camera2base" type="continuous">
        <!-- 父级link和子级link -->
        <parent link="base_link"/>
        <child link="camera" />
        <!-- 需要计算两个 link 的物理中心之间的偏移量 -->
        <origin xyz="0.12 0 0.05" rpy="0 0 0" />
        <!-- 设置旋转参考的坐标轴,这里围绕z轴旋转 -->
        <axis xyz="0 0 1" />
    </joint>

    <!-- 关联base_link和base_footprint -->
    <joint name="link2footprint" type="fixed">
        <!-- 父级link和子级link -->
        <parent link="base_footprint"/>
        <child link="base_link" />
        <!-- 偏移量,这里将其抬高车体的高度 -->
        <origin xyz="0 0 0.05" rpy="0 0 0" />
    </joint>

</robot>

然后编写对应的launch后进行运行:

 注:这里需要把最开始参考的fixed frame改为base_footprint

244-248节 URDF练习

需求描述:

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

首先创建好urdf和launch文件

注:建议优先在joint里面设置偏移量,而不是在link里面设置,这样才可以将坐标Axes区分开来

<robot name="mycar">

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

    <!-- 
        底盘参数
            形状:圆柱 
            半径: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="baselink_color">
                <color rgba="1 0.5 0.2 0.5" />
            </material>
        </visual>
    </link>

    <joint name="link2base_footprint" type="fixed">
        <parent link="base_footprint" />
        <child link="base_link"/>
        <!-- 高度=车体高度/2+离地间距 -->
        <origin xyz="0 0 0.055" />
    </joint>

    <!-- 添加驱动轮 -->
    <!--
        驱动轮是侧翻的圆柱
        参数
            半径: 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.5708 0 0" />
            <material name="wheel_color">
                <color rgba="0.0 0.0 0.0 0.3" />
            </material>
        </visual>

    </link>

    <joint name="left2base_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.5708 0 0" />
            <material name="wheel_color">
                <color rgba="0.0 0.0 0.0 0.3" />
            </material>
        </visual>

    </link>

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

    <!-- 添加万向轮(支撑轮) -->
    <!--
        参数
            形状: 球体
            半径: 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="wheel_color">
                <color rgba="0.0 0.0 0.0 0.3" />
            </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 0.3" />
            </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>

249节 URDF工具

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

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

  • urdf_to_graphiz命令可以查看 urdf 模型结构,显示不同 link 的层级关系

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

在集成终端中打开:

如果存在语法问题就会报出error。

然后是输出关系PDF文件:

 ------------URDF优化_xacro------------

250节

前面 URDF 文件构建机器人模型的过程中,存在若干问题。

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

问题2:URDF 中的部分内容是高度重复的,驱动轮与支撑轮的设计实现,不同轮子只是部分参数不同,形状、颜色、翻转量都是一致的,在实际应用中,构建复杂的机器人模型时,更是易于出现高度重复的设计,按照一般的编程涉及到重复代码应该考虑封装。

......

如果在编程语言中,可以通过变量结合函数直接解决上述问题,在 ROS 中,已经给出了类似编程的优化方案,称之为:Xacro

概念

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

原理

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

251节 Xacro快速体验

需求描述:

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

准备:在之前创建的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>

Xacro是不能直接运行的,我们需要将他转换为urdf文件才行:

这里需要运行ros内置的一个节点

首先roscore以下

然后进入xacro目录中输入以下可以输出一个urdf文件:

rosrun xacro xacro demo01_helloworld.urdf.xacro >demo01_helloworld.urdf

252节 xacro语法01

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>

253节 xacro语法02 函数

案例:

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

输出:

254节 xacro语法03 宏

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

255节 xacro语法04 文件包含

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

输出结果分别为demo02和demo03中的实现结果

256节 xacro完整使用流程

需求描述:

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

编写到一半的时候可以先转成urdf再check一下()

1 编写xacro文件(这里只书写了之前那个小车案例的baselink部分)

<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
    <!-- <xacro:property name="" value=""/> -->
    <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>
                <box size="0.001 0.001 0.001" />
            </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="baselink_color">
                <color rgba="1 0.5 0.2 0.5" />
            </material>
        </visual>
    </link>

    <joint name="link2base_footprint" type="fixed">
        <parent link="base_footprint" />
        <child link="base_link"/>
        <!-- 高度=车体高度/2+离地间距 -->
        <origin xyz="0 0 ${base_joint_z}" />
    </joint>

</robot>

2集成launch文件

方式1:先将 xacro 文件转换出 urdf 文件,然后集成(launch文件和之前一样,只是多一步转urdf文件的操作)

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

核心代码:

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

<launch>
    <!-- 将 urdf 文件内容设置进参数服务器 -->
    <!-- <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.urdf.xacro" />

    <!-- 启动 rivz -->
    <node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" />
    <!-- 启动机器人状态和关节状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
    <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" />

</launch>

注:方式1和2的launch文件的区别只用第一行的区别

257-258节 补齐256节代码

<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
    
    <!-- 
        底盘参数
            形状:圆柱 
            半径:10     cm 
            高度:8      cm 
            离地:1.5    cm

    -->
    <!-- <xacro:property name="" value=""/> -->
    <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>
                <box size="0.001 0.001 0.001" />
            </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="baselink_color">
                <color rgba="1 0.5 0.2 0.5" />
            </material>
        </visual>
    </link>

    <joint name="link2base_footprint" type="fixed">
        <parent link="base_footprint" />
        <child link="base_link"/>
        <!-- 高度=车体高度/2+离地间距 -->
        <origin xyz="0 0 ${base_joint_z}" />
    </joint>

    <!-- 添加驱动轮 -->
    <!--
        驱动轮是侧翻的圆柱
        参数
            半径: 3.25 cm
            宽度: 1.5  cm
            颜色: 黑色
        关节设置:
            x = 0
            y = 底盘的半径 + 轮胎宽度 / 2
            z = 离地间距 + 底盘长度 / 2 - 轮胎半径 = 1.5 + 4 - 3.25 = 2.25(cm)
            axis = 0 1 0
    -->
    <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="${-1*(base_length/2+lidi-wheel_radius)}" />
    <!-- 注意结果是负数 -->

    <!-- 将车轮封装成宏
        wheel_name:left/right
        flag:1/-1 表明左轮还是右轮
     -->
    <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 0.0 0.3" />
                </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"/>


    <!-- 添加万向轮(支撑轮) -->
    <!--
        参数
            形状: 球体
            半径: 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
    -->
    <xacro:property name="small_wheel_radius" value="0.0075"/>
    <xacro:property name="small_joint_z" value="${(base_length/2+lidi-small_wheel_radius)*-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="wheel_color">
                    <color rgba="0.0 0.0 0.0 0.3" />
                </material>
            </visual>
        </link>

        <joint name="${small_wheel_name}_wheel2base_link" 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>

259-263节 xacro实操

需求描述:

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

实现流程:

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

  2. 然后再编写一个组合文件,组合底盘、摄像头与雷达

  3. 最后,通过 launch 文件启动 Rviz 并显示模型

首先新创建这三个文件和launch文件

我们要将demo5、6、7、car四者结合到一起

编写car、demo6、demo7和launch代码

<!-- 组合小车底盘与摄像头与雷达,包含底盘、摄像头、雷达-->
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/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>
<!-- demo06摄像头相关的 xacro 文件 -->
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
    <!-- 摄像头属性 -->
    <xacro:property name="camera_length" value="0.02" /> <!-- 摄像头长度(x) -->
    <xacro:property name="camera_width" value="0.05" /> <!-- 摄像头宽度(y) -->
    <xacro:property name="camera_height" value="0.05" /> <!-- 摄像头高度(z) -->
    <xacro:property name="joint_camera_x" value="0.08" /> <!-- 摄像头安装的x坐标 -->
    <xacro:property name="joint_camera_y" value="0.0" /> <!-- 摄像头安装的y坐标 -->
    <xacro:property name="joint_camera_z" value="${base_length / 2 + camera_height / 2}" /> <!-- 摄像头安装的z坐标:底盘高度 / 2 + 摄像头高度 / 2  -->

    <!-- 摄像头关节以及link -->
    <link name="camera">
        <visual>
            <geometry>
                <box size="${camera_length} ${camera_width} ${camera_height}" />
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
            <material name="black" >
                <color rgba="0 0 0 0.8"/>
            </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}" />
    </joint>
</robot>
<!--
    小车底盘添加雷达
-->
<robot name="my_laser" xmlns:xacro="http://wiki.ros.org/xacro">

    <!-- 雷达支架 -->
    <xacro:property name="support_length" value="0.15" /> <!-- 支架长度 -->
    <xacro:property name="support_radius" value="0.01" /> <!-- 支架半径 -->
    <xacro:property name="joint_support_x" value="0.0" /> <!-- 支架安装的x坐标 -->
    <xacro:property name="joint_support_y" value="0.0" /> <!-- 支架安装的y坐标 -->
    <xacro:property name="joint_support_z" value="${base_length / 2 + support_length / 2}" /> <!-- 支架安装的z坐标:底盘高度 / 2 + 支架高度 / 2  -->

    <link name="support">
        <visual>
            <geometry>
                <cylinder radius="${support_radius}" length="${support_length}" />
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
            <material name="red">
                <color rgba="0.8 0.2 0.0 0.5" />
            </material>
        </visual>
    </link>

    <joint name="support2base_link" type="fixed">
        <parent link="base_link" />
        <child link="support" />
        <origin xyz="${joint_support_x} ${joint_support_y} ${joint_support_z}" />
    </joint>


    <!-- 雷达属性 -->
    <xacro:property name="laser_length" value="0.05" /> <!-- 雷达长度 -->
    <xacro:property name="laser_radius" value="0.03" /> <!-- 雷达半径 -->
    <xacro:property name="joint_laser_x" value="0.0" /> <!-- 雷达安装的x坐标 -->
    <xacro:property name="joint_laser_y" value="0.0" /> <!-- 雷达安装的y坐标 -->
    <xacro:property name="joint_laser_z" value="${support_length / 2 + laser_length / 2}" /> <!-- 雷达安装的z坐标:支架高度 / 2 + 雷达高度 / 2  -->

    <!-- 雷达关节以及link -->
    <link name="laser">
        <visual>
            <geometry>
                <cylinder radius="${laser_radius}" length="${laser_length}" />
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
            <material name="black">
                <color rgba="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}" />
    </joint>
</robot>
<launch>
    <!-- 将 urdf 文件内容设置进参数服务器 -->
    <!-- <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" />

    <!-- 启动 rivz -->
    <node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" />
    <!-- 启动机器人状态和关节状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
    <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" />

</launch>

------------使用arbotix------------

264节 控制机器人运动

通过 URDF 结合 rviz 可以创建并显示机器人模型,不过,当前实现的只是静态模型,如何控制模型的运动呢?在此,可以调用 Arbotix 实现此功能。

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

需求描述:

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

实现流程:

  1. 安装 Arbotix

  2. 创建新功能包,准备机器人 urdf、xacro 文件(之前都写了)

  3. 添加 Arbotix 配置文件

  4. 编写 launch 文件配置 Arbotix

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

265节 安装

方式1

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

将 <<VsersionName()>> 替换成当前 ROS 版本名称,

如果提示功能包无法定位(上图),请采用方式2

先从 github 下载源码(网速慢可以使用手机流量进行下载)

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

将下载好的放入第一层src中

然后调用 catkin_make 即c+s+b 编译

266节 添加 Arbotix 配置文件

到config文件下创建.yaml文件

然后粘贴

# 该文件是控制器配置,一个机器人模型可能有多个控制器,比如: 底盘、机械臂、夹持器(机械手)....
# 因此,根 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 
    }
}

这里不多做解释

267节 集成arbotix节点

创建launch文件

<launch>
    <!-- 将 urdf 文件内容设置进参数服务器 -->
    <!-- <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" />

    <!-- 启动 rivz -->
    <node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" />
    <!-- 启动机器人状态和关节状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />

    <!-- 集成arbotix运动控制节点并且加载参数 -->
    <node pkg="arbotix_python" type="arbotix_driver" name="driver" output="screen">
        <rosparam file="$(find urdf01_rviz)/config/control.yaml" command="load" />
        <param name="sim" value="true" />   <!-- 意味着这是一个仿真环境 -->
    </node>

</launch>

注:运行launch文件之前,因为我的python版本是2.7,所以需要在下图中将python3改为2.7才可以。

 然后运行launch文件,将下图这里改为odom

 然后对话题发布数据来控制机器人做圆周运动

add添加这个之后就有指向箭头

------------URDF集成Gazebo------------

270-271节 基本集成流程案例

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

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

  2. 编写 URDF 或 Xacro 文件

  3. 启动 Gazebo 并显示机器人模型

1 创建功能包urdf02_gazebo,依赖于下图2

2编写urdf文件

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

        <!-- 设置碰撞参数 -->
        <!-- 如果是标准几何体,直接复制visual的geometry和origin即可 -->
        <collision>
            <geometry>
                <box size="0.5 0.2 0.1" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0"/>
        </collision>

        <!-- 设置惯性矩阵 -->
        <intertial>
            <origin xyz="0 0 0" rpy="0 0 0"/>
            <mass value="2">
            <inertia ixx="1" ixy="0" ixz="0" iyy="1" iyz="0" izz="1" />
            <!-- 惯性矩阵:通过计算的来,这里不详细解释 -->
        </intertial>

    </link>
    
    <!-- gazebo有自己的颜色设置标签 -->
    <gazebo reference="base_link">
        <material>Gazebo/Red</material>
    </gazebo>
</robot>

3编写launch文件

<launch>
    <!-- 步骤1 需要在参数服务器中载入urdf -->
    <param name="robot_description" textfile="$(find urdf02_gazebo)/urdf/demo01_helloworld.urdf"  />
    <!-- 步骤2 启动gazebo -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch"    />
    <!-- 步骤3 在gazebo中添加之前已经做好的(urdf文件中)机器人模型 -->
    <node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description"  />
</launch>

步骤3代码解释: spawn_model用于模型产卵,args参数中-urdf指的是加载的是urdf数据,-model mycar指的是加载的是名字为mycar的模型,-param robot_description指的是从参数服务器加载数据(和步骤1的param name对应的)

273节 urdf集成gazebo相关设置

1.collision

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

2.inertial

惯性矩阵的设置需要结合link的质量与外形参数动态生成,标准的球体、圆柱与立方体的惯性矩阵公式如下(已经封装为 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>

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

3.颜色设置(注意大小写)

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

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

273-275 URDF集成Gazebo实操

需求描述:

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

实现流程:

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

  2. 为机器人模型中的每一个 link 添加 collision 和 inertial 标签,并且重置颜色属性

  3. 在 launch 文件中启动 gazebo 并添加机器人模型

我们将之前写的urdf01中的部分代码(car、demo5、6、7)复制过来稍作修改即可:

编写launch文件(和之前的区别杂鱼command这里):

<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"    />
    <!-- 在gazebo中添加机器人模型 -->
    <node pkg="gazebo_ros" type="spawn_model" name="spawn_model" args="-urdf -model mycar -param robot_description"  />
</launch>

然后修改demo05,核心多个link中添加下面两段(注:注意惯性函数在collision外面;使用参数的值的时候要加上${};<gazebo reference=中写的是当前robot的name)

        <collision>
            <geometry>
                <cylinder radius="${base_radius}" length="${base_length}" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
        </collision>
        <!-- 调用head中的惯性矩阵函数 -->
        <xacro:cylinder_inertial_matrix m="${base_mass}" r="${base_radius}" h="${base_length}"/>

         <gazebo reference="base_link">
            <material>Gazebo/Red</material>
        </gazebo>

全部demo05、06、07代码:

<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
    
    <!-- 
        底盘参数
            形状:圆柱 
            半径:10     cm 
            高度:8      cm 
            离地:1.5    cm

    -->
    <!-- <xacro:property name="" value=""/> -->
    <xacro:property name="base_radius" value="0.1"/>
    <xacro:property name="base_length" value="0.08"/>
    <xacro:property name="base_mass" value="2"/>
    <xacro:property name="small_wheel_mass" value="0.01"/>
    <xacro:property name="wheel_mass" value="0.05"/>
    <xacro:property name="lidi" value="0.015"/>
    <xacro:property name="base_joint_z" value="${base_length/2+lidi}"/>

  
    <link name="base_footprint">
        <visual>
            <geometry>
                <box size="0.001 0.001 0.001" />
            </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="baselink_color">
                <color rgba="1 0.5 0.2 0.5" />
            </material>
        </visual>

        <collision>
            <geometry>
                <cylinder radius="${base_radius}" length="${base_length}" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
        </collision>
        <!-- 调用head中的惯性矩阵函数 -->
        <xacro:cylinder_inertial_matrix m="${base_mass}" r="${base_radius}" h="${base_length}"/>
    </link>
    <gazebo reference="base_link">
        <material>Gazebo/Yellow</material>
    </gazebo>


    <joint name="link2base_footprint" type="fixed">
        <parent link="base_footprint" />
        <child link="base_link"/>
        <!-- 高度=车体高度/2+离地间距 -->
        <origin xyz="0 0 ${base_joint_z}" />
    </joint>

    <!-- 添加驱动轮 -->
    <!--
        驱动轮是侧翻的圆柱
        参数
            半径: 3.25 cm
            宽度: 1.5  cm
            颜色: 黑色
        关节设置:
            x = 0
            y = 底盘的半径 + 轮胎宽度 / 2
            z = 离地间距 + 底盘长度 / 2 - 轮胎半径 = 1.5 + 4 - 3.25 = 2.25(cm)
            axis = 0 1 0
    -->
    <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="${-1*(base_length/2+lidi-wheel_radius)}" />
    <!-- 注意结果是负数 -->

    <!-- 将车轮封装成宏
        wheel_name:left/right
        flag:1/-1 表明左轮还是右轮
     -->
    <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 0.0 0.3" />
                </material>
            </visual>
            <collision>
                <geometry>
                    <cylinder radius="${wheel_radius}" length="${wheel_length}" />
                </geometry>
                <origin xyz="0 0 0" rpy="${PI/2} 0 0" />
            </collision>
            <xacro:cylinder_inertial_matrix m="${wheel_mass}" r="${wheel_radius}" h="${wheel_length}"/>
        </link>
        <gazebo reference="${wheel_name}_wheel">
            <material>Gazebo/Red</material>
        </gazebo>


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


    <!-- 添加万向轮(支撑轮) -->
    <!--
        参数
            形状: 球体
            半径: 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
    -->
    <xacro:property name="small_wheel_radius" value="0.0075"/>
    <xacro:property name="small_joint_z" value="${(base_length/2+lidi-small_wheel_radius)*-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="wheel_color">
                    <color rgba="0.0 0.0 0.0 0.3" />
                </material>
            </visual>
            <collision>
                <geometry>
                    <sphere radius="${small_wheel_radius}" />
                </geometry>
                <origin xyz="0 0 0" rpy="0 0 0" />
            </collision>
            <xacro:sphere_inertial_matrix m="${small_wheel_mass}" r="${small_wheel_radius}"/>
        </link>
        <gazebo reference="${small_wheel_name}_wheel">
            <material>Gazebo/Red</material>
        </gazebo>

        <joint name="${small_wheel_name}_wheel2base_link" 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>
<!-- 摄像头相关的 xacro 文件 -->
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
    <!-- 摄像头属性 -->
    <xacro:property name="camera_length" value="0.02" /> <!-- 摄像头长度(x) -->
    <xacro:property name="camera_width" value="0.05" /> <!-- 摄像头宽度(y) -->
    <xacro:property name="camera_height" value="0.05" /> <!-- 摄像头高度(z) -->
    <xacro:property name="camera_mass" value="0.01" /> <!-- 摄像头质量 -->
    <xacro:property name="joint_camera_x" value="0.08" /> <!-- 摄像头安装的x坐标 -->
    <xacro:property name="joint_camera_y" value="0.0" /> <!-- 摄像头安装的y坐标 -->
    <xacro:property name="joint_camera_z" value="${base_length / 2 + camera_height / 2}" /> <!-- 摄像头安装的z坐标:底盘高度 / 2 + 摄像头高度 / 2  -->

    <!-- 摄像头关节以及link -->
    <link name="camera">
        <visual>
            <geometry>
                <box size="${camera_length} ${camera_width} ${camera_height}" />
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
            <material name="black" >
                <color rgba="0 0 0 0.8"/>
            </material>
        </visual>
        <collision>
            <geometry>
                <box size="${camera_length} ${camera_width} ${camera_height}" />
            </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_height}" />
    </link>
    <gazebo reference="camera">
        <material>Gazebo/Blue</material>
    </gazebo>    

    <joint name="camera2base" type="fixed">
        <parent link="base_link" />
        <child link="camera" />
        <origin xyz="${joint_camera_x} ${joint_camera_y} ${joint_camera_z}" />
    </joint>
</robot>
<!--
    小车底盘添加雷达
-->
<robot name="my_laser" xmlns:xacro="http://wiki.ros.org/xacro">

    <!-- 雷达支架 -->
    <xacro:property name="support_length" value="0.15" /> <!-- 支架长度 -->
    <xacro:property name="support_radius" value="0.01" /> <!-- 支架半径 -->
    <xacro:property name="support_mass" value="0.1" /> <!-- 支架质量 -->
    <xacro:property name="joint_support_x" value="0.0" /> <!-- 支架安装的x坐标 -->
    <xacro:property name="joint_support_y" value="0.0" /> <!-- 支架安装的y坐标 -->
    <xacro:property name="joint_support_z" value="${base_length / 2 + support_length / 2}" /> <!-- 支架安装的z坐标:底盘高度 / 2 + 支架高度 / 2  -->

    <link name="support">
        <visual>
            <geometry>
                <cylinder radius="${support_radius}" length="${support_length}" />
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
            <material name="red">
                <color rgba="0.8 0.2 0.0 0.5" />
            </material>
            
        </visual>
        <collision>
            <geometry>
                <cylinder radius="${support_radius}" length="${support_length}" />
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
        </collision>
        <xacro:cylinder_inertial_matrix m="${support_mass}" r="${support_radius}" h="${support_length}"/>
    </link>
    <gazebo reference="support">
        <material>Gazebo/Gray</material>
    </gazebo>    

    <joint name="support2base_link" type="fixed">
        <parent link="base_link" />
        <child link="support" />
        <origin xyz="${joint_support_x} ${joint_support_y} ${joint_support_z}" />
    </joint>


    <!-- 雷达属性 -->
    <xacro:property name="laser_length" value="0.05" /> <!-- 雷达长度 -->
    <xacro:property name="laser_radius" value="0.03" /> <!-- 雷达半径 -->
    <xacro:property name="laser_mass" value="0.15" /> <!-- 雷达质量 -->
    <xacro:property name="joint_laser_x" value="0.0" /> <!-- 雷达安装的x坐标 -->
    <xacro:property name="joint_laser_y" value="0.0" /> <!-- 雷达安装的y坐标 -->
    <xacro:property name="joint_laser_z" value="${support_length / 2 + laser_length / 2}" /> <!-- 雷达安装的z坐标:支架高度 / 2 + 雷达高度 / 2  -->

    <!-- 雷达关节以及link -->
    <link name="laser">
        <visual>
            <geometry>
                <cylinder radius="${laser_radius}" length="${laser_length}" />
            </geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
            <material name="black">
                <color rgba="0 0 0 0.5"/>
            </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>
    <gazebo reference="laser">
        <material>Gazebo/Black</material>
    </gazebo>    

    <joint name="laser2support" type="fixed">
        <parent link="support" />
        <child link="laser" />
        <origin xyz="${joint_laser_x} ${joint_laser_y} ${joint_laser_z}" />
    </joint>
</robot>

276节 gazebo仿真环境载入

在一开始下载的sim_demo文件夹下的box_house就是已经搭建好了的模型环境,我们这里就学习如何在gazebo中集成已经搭建好的环境。

首先创建文件夹并且把sim_demo中下载的box_house粘贴到刚刚建好的文件夹下

然后创建launch文件 (核心代码是“启动gazebo”注释下的代码)

<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="spawn_model" args="-urdf -model mycar -param robot_description"  />
</launch>

277节 gazebo创建仿真环境

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

  • 方式1: 直接添加内置组件创建仿真环境

  • 方式2: 手动绘制仿真环境(更为灵活)

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

方式1

启动roscore后输入:

rosrun gazebo_ros gazebo

如果这里一直打不开,可以参考这个网站

然后通过图形界面拖动创建仿真环境

方式2

将模型库复制进 gazebo

------------URDF、GAZEBO、Rviz综合应用------------

官方参考:

Gazebo : Tutorial : Gazebo plugins in ROS

279节 roscontrol简介

之前在rviz使用的机器人控制方法拿到gazebo中并不能使用,这里就需要设计组件roscontrol。

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

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

roscontrol就可以理解成是一套规范/接口,机器人平台和机器人系统这两者之间都需要按照这个规范来实现。

280节 运动控制实现流程

首先创建文件夹和文件:

然后编写代码(这部分代码直接粘贴,稍加修改)

<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>
 
    <!-- 每一个驱动轮都需要配置传动装置 -->
    <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>

 然后编译执行launch文件

  这时我们发现已经存在了cmd_vel文件

 然后使用以下代码启动键盘控制节点对其进行控制

rosrun teleop_twist_keyboard teleop_twist_keyboard.py _speed:=0.1 _turn:=0.3

如果没有这个功能包就使用以下语句进行安装:

sudo apt-get install ros-melodic-teleop-twist-keyboard
这里如果ros版本是noetic就把melodic改为noetic

281节 rviz查看里程计消息

因为gazebo中无法以图形化的方式显示小车运行的里程信息,所以这里要结合rviz来实现

编写launch文件启动rviz

<launch>
    <!-- 启动 rivz -->
    <node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" />
    <!-- 启动机器人状态和关节状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
</launch>

分别启动两者launch文件

 修改rviz中的一些选项:

 这里参考的是上一节代码中里程计参考的话题是odom。

 然后启动键盘控制节点,在gazebo中运动的路径就可以在rviz中显示了。

282节 雷达仿真及其显示

雷达仿真基本流程(和之前move类似):

    已经创建完毕的机器人模型,编写一个单独的 xacro 文件,为机器人模型添加雷达配置;

    将此文件集成进xacro文件;

    启动 Gazebo,使用 Rviz 显示雷达信息。

编写雷达的xacro文件(官网上可复制),主要修改reference和frameName两个标签,这里reference和framName两个的标签改为之前在gazebo中编写的laser的link的名称,可以理解为将laser装到之前的link上

<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
 
  <!-- 雷达 -->
  <gazebo reference="laser">
    <sensor type="ray" name="rplidar"> 
      <pose>0 0 0 0 0 0</pose>
      <visualize>true</visualize>      <!-- 显示雷达射线 -->
      <update_rate>5.5</update_rate>      <!-- 射线更新频率  /s -->
      <ray>
        <scan>
          <horizontal>
            <samples>360</samples>        <!-- 采样个数:雷达旋转一周发射的点 -->
            <resolution>1</resolution>      <!-- 分辨率:每n个射线有一个测距的,便于降低计算压力,精度降低 -->
            <min_angle>-3</min_angle>      <!-- 采样范围:单位是rad,这里代码中表示的是正前方正负3个弧度是我的采样范围 -->
            <max_angle>3</max_angle>
          </horizontal>
        </scan>
        <range>
          <min>0.10</min>      <!-- 采样的距离:最短和最远的采样距离 -->
          <max>30.0</max>
          <resolution>0.01</resolution>      <!-- 精度:精确到xxx米 -->
        </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>
        <frameName>laser</frameName>
      </plugin>
    </sensor>
  </gazebo>
 
</robot>

注:laser代码中的topicname就是雷达发布数据的话题。

在car.urdf.xacro中添加一行集成雷达配置文件的代码

<!-- 组合小车底盘与摄像头与雷达,包含底盘、摄像头、雷达-->
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="head.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" />
</robot>

然后运行:

 在rviz中查看雷达消息

283节 摄像头仿真

摄像头仿真基本流程:

  1. 已经创建完毕的机器人模型,编写一个单独的 xacro 文件,为机器人模型添加摄像头配置;

  2. 将此文件集成进xacro文件;

  3. 启动 Gazebo,使用 Rviz 显示摄像头信息。

这里还是主要修改reference和frameName

<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>

car.urdf.xacro:添加了集成摄像头

<!-- 组合小车底盘与摄像头与雷达,包含底盘、摄像头、雷达-->
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="head.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" />
</robot>

然后运行demo03和demo04:

修改rviz

 注:这里上图中的topic参考的是camera.xacro中的这两行:

284节 深度相机仿真

kinect摄像头仿真基本流程:

  1. 已经创建完毕的机器人模型,编写一个单独的 xacro 文件,为机器人模型添加kinect摄像头配置;

  2. 将此文件集成进xacro文件;

  3. 启动 Gazebo,使用 Rviz 显示kinect摄像头信息。

创建xacro文件并且编写

<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
    <gazebo reference="support">        <!-- 这里将链接摄像头的支架作为深度相机(偷懒) -->
      <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</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>

car.urdf.xacro

<!-- 组合小车底盘与摄像头与雷达,包含底盘、摄像头、雷达-->
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="head.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>

roslaunch demo03和demo04

在rviz中修改fixed name和camera的topic即可呈现不同的仿真效果

285节 点云数据显示

运行之前的demo03和demo04,add进pointcloud2

问题:在rviz中显示时错位。

原因:在kinect中图像数据与点云数据使用了两套坐标系统,且两套坐标系统位姿并不一致。

解决:

首先在插件中为kinect设置坐标系,修改配置文件的<frameName>标签内容:

 然后在launch文件中添加坐标变换

    <node pkg="tf2_ros" type="static_transform_publisher" name="static_transform_publisher" args="0 0 0 -1.57 0 -1.57 /support /support_depth" />

再次运行即可demo03、04即可

本章小结

本章主要介绍了ROS中仿真实现涉及的三大知识点:

  • URDF(Xacro)
  • Rviz
  • Gazebo

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

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

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

rviz需要已有数据

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

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

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

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

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

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

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值