URDF+Gazebo+Rviz仿真

一、URDF集成Rviz流程

我们需要在配置文件中添加两个依赖urdf与xacro,再在功能包目录下添加几个文件夹

urdf:    存储 urdf 文件的目录
meshes:  机器人模型渲染文件(暂不使用)
config:  配置文件
launch:  存储 launch 启动文件

我们在urdf文件下编写一个模型文件test.urdf

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

在launch文件夹下编写launch文件test1.launch

<launch>
    
    <param name="robot_description" textfile="$(find urdf_rviz_gazebo)/urdf/test.urdf" />
    
    <node pkg="rviz" type="rviz" name="rviz" />
launch>

我们启动launch文件,rviz 启动后,会发现并没有盒装的机器人模型,这是因为默认情况下没有添加机器人显示组件,需要手动添加,添加方式如下:

URDF+Gazebo+Rviz仿真_第1张图片

URDF+Gazebo+Rviz仿真_第2张图片

此时我们可以看到这个红色的盒子了,但是我们应该意识到,rviz不会保存每次的设置,所以我们每次重新打开rviz都需要再重新进行配置,其实我们保存配置文件,如图所示

URDF+Gazebo+Rviz仿真_第3张图片

这样我们在launch文件的调用时将这个文件作为参数传入就可以直接配置

<launch>
    
    <param name="robot_description" textfile="$(find urdf_rviz_gazebo)/urdf/test.urdf" />
    
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf_rviz_gazebo)/config/save1.rviz" />
launch>

二、URDF语法

2.1、robot

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

属性

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

子标签:

所有的标签

2.2、link

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

属性:

name ---> 为连杆命名

子标签:

visual ---> 描述外观(对应的数据是可视的)
    geometry 设置连杆的形状
        标签1: box(盒状)
            属性:size=长(x) 宽(y) 高(z)
        标签2: cylinder(圆柱)
            属性:radius=半径 length=高度
        标签3: sphere(球体)
            属性:radius=半径
        标签4: mesh(为连杆添加皮肤)
            属性: filename=资源路径(格式:package:////文件)

    origin 设置偏移量与倾斜弧度
        属性1: xyz=x偏移 y便宜 z偏移
        属性2: rpy=x翻滚 y俯仰 z偏航 (单位是弧度)

    metrial 设置材料属性(颜色)
        属性: name
        标签: color
            属性: rgba=红绿蓝权重值与透明度 (每个权重值以及透明度取值[0,1])

collision ---> 连杆的碰撞属性

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

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

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

2.3、joint

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

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

属性:

name ---> 为关节命名

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

子标签:

parent(必需的)
    parent link的名字是一个强制的属性:
    link:父级连杆的名字,是这个link在机器人结构树中的名字。
    
child(必需的)
	child link的名字是一个强制的属性:
	link:子级连杆的名字,是这个link在机器人结构树中的名字。

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

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

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


<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="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.2 0 0.075" rpy="0 0 0" />
        <axis xyz="0 0 1" />
    joint>

robot>

启动的launch文件

<launch>
    <param name="robot_description" textfile="$(find urdf_rviz_demo)/urdf/urdf/urdf03_joint.urdf" />
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf_rviz_demo)/config/helloworld.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" />
    
    <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" />
launch>

2.4、base_footprint优化urdf

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


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

    
    <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="blue">
                <color rgba="0 0 1.0 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.05" />
    joint>

    
    <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.2 0 0.075" rpy="0 0 0" />
        <axis xyz="0 0 1" />
    joint>

robot>

2.5、error

UnicodeEncodeError: 'ascii' codec can't encode characters in position 463-464: ordinal not in range(128)
[joint_state_publisher-3] process has died [pid 4443, exit code 1, cmd /opt/ros/melodic/lib/joint_state_publisher/joint_state_publisher __name:=joint_state_publisher __log:=/home/rosmelodic/.ros/log/b38967c0-0acb-11eb-aee3-0800278ee10c/joint_state_publisher-3.log].
log file: /home/rosmelodic/.ros/log/b38967c0-0acb-11eb-aee3-0800278ee10c/joint_state_publisher-3*.log

编码问题导致的,需要去掉urdf文件中的注释

三、URDF练习

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

3.1、新建urdf以及launch文件

urdf 文件:基本实现

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

    


    


    

robot>

launch 文件:

<launch>
    
    <param name="robot_description" textfile="$(find demo01_urdf_helloworld)/urdf/urdf/test.urdf" />

    
    <node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find demo01_urdf_helloworld)/config/helloworld.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>

3.2、底盘搭建


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

3.3、添加驱动轮


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

3.4、添加万向轮


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

四、xacro语法

4.1、xacro体验

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

<robot name="mycar" xmlns:xacro="http://wiki.ros.org/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>

        
        <joint name="${wheel_name}2link" type="continuous">
            <parent link="base_link"  />
            <child link="${wheel_name}_wheel" />
            
            <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文件 所属目录,执行:rosrun xacro xacro xxx.xacro > xxx.urdf, 会将 xacro 文件解析为 urdf 文件,内容如下:






<robot name="mycar">
  <link name="left_wheel">
    <visual>
      <geometry>
        <cylinder length="0.0015" radius="0.0325"/>
      geometry>
      <origin rpy="1.57079635 0 0" xyz="0 0 0"/>
      <material name="wheel_color">
        <color rgba="0 0 0 0.3"/>
      material>
    visual>
  link>
  
  <joint name="left2link" type="continuous">
    <parent link="base_link"/>
    <child link="left_wheel"/>
    
    <origin rpy="0 0 0" xyz="0 0.1 -0.0225"/>
    <axis xyz="0 1 0"/>
  joint>
  <link name="right_wheel">
    <visual>
      <geometry>
        <cylinder length="0.0015" radius="0.0325"/>
      geometry>
      <origin rpy="1.57079635 0 0" xyz="0 0 0"/>
      <material name="wheel_color">
        <color rgba="0 0 0 0.3"/>
      material>
    visual>
  link>
  
  <joint name="right2link" type="continuous">
    <parent link="base_link"/>
    <child link="right_wheel"/>
    
    <origin rpy="0 0 0" xyz="0 -0.1 -0.0225"/>
    <axis xyz="0 1 0"/>
  joint>
robot>

4.2、xacro语法

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

4.2.1、属性与算数运算

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

属性定义

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

属性调用

${属性名称}

算数运算

${数学表达式}
4.2.2、宏

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

宏定义

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

宏调用

<xacro:宏名称 参数1=xxx 参数2=xxx/>
4.2.3、文件包含

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

文件包含

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

4.3、xacro优化底盘

编写xacro文件



<robot name="my_base" xmlns:xacro="http://www.ros.org/wiki/xacro">
    
    <xacro:property name="PI" value="3.141"/>
    
    <material name="black">
        <color rgba="0.0 0.0 0.0 1.0" />
    material>
    
    <xacro:property name="base_footprint_radius" value="0.001" /> 
    <xacro:property name="base_link_radius" value="0.1" /> 
    <xacro:property name="base_link_length" value="0.08" /> 
    <xacro:property name="earth_space" value="0.015" /> 

    
    <link name="base_footprint">
      <visual>
        <geometry>
          <sphere radius="${base_footprint_radius}" />
        geometry>
      visual>
    link>

    <link name="base_link">
      <visual>
        <geometry>
          <cylinder radius="${base_link_radius}" length="${base_link_length}" />
        geometry>
        <origin xyz="0 0 0" rpy="0 0 0" />
        <material name="yellow">
          <color rgba="0.5 0.3 0.0 0.5" />
        material>
      visual>
    link>

    <joint name="base_link2base_footprint" type="fixed">
      <parent link="base_footprint" />
      <child link="base_link" />
      <origin xyz="0 0 ${earth_space + base_link_length / 2 }" />
    joint>

    
    
    <xacro:property name="wheel_radius" value="0.0325" />
    <xacro:property name="wheel_length" value="0.015" />
    
    <xacro:macro name="add_wheels" params="name flag">
      <link name="${name}_wheel">
        <visual>
          <geometry>
            <cylinder radius="${wheel_radius}" length="${wheel_length}" />
          geometry>
          <origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0" />
          <material name="black" />
        visual>
      link>

      <joint name="${name}_wheel2base_link" type="continuous">
        <parent link="base_link" />
        <child link="${name}_wheel" />
        <origin xyz="0 ${flag * base_link_radius} ${-(earth_space + base_link_length / 2 - wheel_radius) }" />
        <axis xyz="0 1 0" />
      joint>
    xacro:macro>
    <xacro:add_wheels name="left" flag="1" />
    <xacro:add_wheels name="right" flag="-1" />
    
    
    <xacro:property name="support_wheel_radius" value="0.0075" /> 

    
    <xacro:macro name="add_support_wheel" params="name flag" >
      <link name="${name}_wheel">
        <visual>
            <geometry>
                <sphere radius="${support_wheel_radius}" />
            geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="black" />
        visual>
      link>

      <joint name="${name}_wheel2base_link" type="continuous">
          <parent link="base_link" />
          <child link="${name}_wheel" />
          <origin xyz="${flag * (base_link_radius - support_wheel_radius)} 0 ${-(base_link_length / 2 + earth_space / 2)}" />
          <axis xyz="1 1 1" />
      joint>
    xacro:macro>

    <xacro:add_support_wheel name="front" flag="1" />
    <xacro:add_support_wheel name="back" flag="-1" />
robot>

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

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

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

    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find demo01_urdf_helloworld)/config/helloworld.rviz" />
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" output="screen" />
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" output="screen" />
    <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" output="screen" />
launch>

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

launch 内容示例:

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

    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find demo01_urdf_helloworld)/config/helloworld.rviz" />
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" output="screen" />
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" output="screen" />
    <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" output="screen" />

launch>

核心代码:

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

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

4.4、xacro实操

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

摄像头 xacro 文件:


<robot name="my_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    
    <xacro:property name="camera_length" value="0.01" /> 
    <xacro:property name="camera_width" value="0.025" /> 
    <xacro:property name="camera_height" value="0.025" /> 
    <xacro:property name="camera_x" value="0.08" /> 
    <xacro:property name="camera_y" value="0.0" /> 
    <xacro:property name="camera_z" value="${base_link_length / 2 + camera_height / 2}" /> 

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

    <joint name="camera2base_link" type="fixed">
        <parent link="base_link" />
        <child link="camera" />
        <origin xyz="${camera_x} ${camera_y} ${camera_z}" />
    joint>
robot>
Copy

雷达 xacro 文件:


<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_x" value="0.0" /> 
    <xacro:property name="support_y" value="0.0" /> 
    <xacro:property name="support_z" value="${base_link_length / 2 + support_length / 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.8" />
            material>
        visual>
    link>

    <joint name="support2base_link" type="fixed">
        <parent link="base_link" />
        <child link="support" />
        <origin xyz="${support_x} ${support_y} ${support_z}" />
    joint>


    
    <xacro:property name="laser_length" value="0.05" /> 
    <xacro:property name="laser_radius" value="0.03" /> 
    <xacro:property name="laser_x" value="0.0" /> 
    <xacro:property name="laser_y" value="0.0" /> 
    <xacro:property name="laser_z" value="${support_length / 2 + laser_length / 2}" /> 

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

    <joint name="laser2support" type="fixed">
        <parent link="support" />
        <child link="laser" />
        <origin xyz="${laser_x} ${laser_y} ${laser_z}" />
    joint>
robot>
Copy

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


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

launch 文件

<launch>
    <param name="robot_description" command="$(find xacro)/xacro $(find urdf_test)/urdf/xacro/my_base_camera_laser.urdf.xacro" />

    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find demo01_urdf_helloworld)/config/helloworld.rviz" />
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" output="screen" />
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" output="screen" />
    <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" output="screen" />

launch>

五、Rviz中控制模型运动

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

5.1、安装

sudo apt-get install ros-noetic-arbotix

如果安装不上可以下载源码编译安装

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

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

5.2、添加 arbotix 所需配置文件

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

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

5.3、launch 文件中配置 arbotix 节点

launch 示例代码

<node name="arbotix" pkg="arbotix_python" type="arbotix_driver" output="screen">
     <rosparam file="$(find my_urdf05_rviz)/config/hello.yaml" command="load" />
     <param name="sim" value="true" />
node>
Copy

代码解释:

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

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

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

5.4、启动 launch 文件并控制机器人模型运动

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

配置 rviz:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LCJdOTF4-1661782081586)(/home/lovess/biji/ROS/picture/13-4.png)]

控制小车运动:

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W7EVa3Fh-1661782081586)(/home/lovess/biji/ROS/picture/13-5.png)]

也就说我们可以发布 cmd_vel 话题消息控制小陈运动了,该实现策略有多种,可以另行编写节点,或者更简单些可以直接通过如下命令发布消息:

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

现在,小车就可以运动起来了。

六、URDF集成Gazebo

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

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

6.1、基本流程

导入功能包

roscpp rospy std_msgs urdf xacro gazebo_ros gazebo_ros_control gazebo_plugins

创建模型文件



<robot name="mycar">
    <link name="base_link">
        <visual>
            <geometry>
                <box size="0.5 0.2 0.1" />
            geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
            <material name="yellow">
                <color rgba="0.5 0.3 0.0 1" />
            material>
        visual>
        <collision>
            <geometry>
                <box size="0.5 0.2 0.1" />
            geometry>
            <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
        collision>
        <inertial>
            <origin xyz="0 0 0" />
            <mass value="6" />
            <inertia ixx="1" ixy="0" ixz="0" iyy="1" iyz="0" izz="1" />
        inertial>
    link>
    <gazebo reference="base_link">
        <material>Gazebo/Blackmaterial>
    gazebo>

robot>

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

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

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

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

launch 文件实现:

<launch>

    
    <param name="robot_description" textfile="$(find demo02_urdf_gazebo)/urdf/urdf01_helloworld.urdf" />

    
    <include file="$(find gazebo_ros)/launch/empty_world.launch" />

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

代码解释:

<include file="$(find gazebo_ros)/launch/empty_world.launch" />


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


6.2、相关设置

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

6.2.1、collision

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

6.2.2、inertial

惯性矩阵的设置需要结合link的质量与外形参数动态生成,标准的球体、圆柱与立方体的惯性矩阵公式如下(已经封装为 xacro 实现):

球体惯性矩阵


    <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 中出现抖动,移动等现象。

6.2.3、颜色设置

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

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

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

6.3、实操

将之前的urdf文件显示在Gazebo中

实现流程:

  1. 需要编写封装惯性矩阵算法的 xacro 文件
  2. 为机器人模型中的每一个 link 添加 collision 和 inertial 标签,并且重置颜色属性
  3. 在 launch 文件中启动 gazebo 并添加机器人模型
<robot name="base" xmlns:xacro="http://wiki.ros.org/xacro">
    
    <xacro:macro name="sphere_inertial_matrix" params="m r">
        <inertial>
            <mass value="${m}" />
            <inertia ixx="${2*m*r*r/5}" ixy="0" ixz="0"
                iyy="${2*m*r*r/5}" iyz="0" 
                izz="${2*m*r*r/5}" />
        inertial>
    xacro:macro>

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

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

A.底盘 Xacro 文件



<robot name="my_base" xmlns:xacro="http://www.ros.org/wiki/xacro">
    
    
    <xacro:property name="PI" value="3.1415926"/>
    
    <material name="black">
        <color rgba="0.0 0.0 0.0 1.0" />
    material>
    
    <xacro:property name="base_footprint_radius" value="0.001" /> 
    <xacro:property name="base_link_radius" value="0.1" /> 
    <xacro:property name="base_link_length" value="0.08" /> 
    <xacro:property name="earth_space" value="0.015" /> 
    <xacro:property name="base_link_m" value="0.5" /> 

    
    <link name="base_footprint">
      <visual>
        <geometry>
          <sphere radius="${base_footprint_radius}" />
        geometry>
      visual>
    link>

    <link name="base_link">
      <visual>
        <geometry>
          <cylinder radius="${base_link_radius}" length="${base_link_length}" />
        geometry>
        <origin xyz="0 0 0" rpy="0 0 0" />
        <material name="yellow">
          <color rgba="0.5 0.3 0.0 0.5" />
        material>
      visual>
      <collision>
        <geometry>
          <cylinder radius="${base_link_radius}" length="${base_link_length}" />
        geometry>
        <origin xyz="0 0 0" rpy="0 0 0" />
      collision>
      <xacro:cylinder_inertial_matrix m="${base_link_m}" r="${base_link_radius}" h="${base_link_length}" />

    link>


    <joint name="base_link2base_footprint" type="fixed">
      <parent link="base_footprint" />
      <child link="base_link" />
      <origin xyz="0 0 ${earth_space + base_link_length / 2 }" />
    joint>
    <gazebo reference="base_link">
        <material>Gazebo/Yellowmaterial>
    gazebo>

    
    
    <xacro:property name="wheel_radius" value="0.0325" />
    <xacro:property name="wheel_length" value="0.015" />
    <xacro:property name="wheel_m" value="0.05" /> 

    
    <xacro:macro name="add_wheels" params="name flag">
      <link name="${name}_wheel">
        <visual>
          <geometry>
            <cylinder radius="${wheel_radius}" length="${wheel_length}" />
          geometry>
          <origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0" />
          <material name="black" />
        visual>
        <collision>
          <geometry>
            <cylinder radius="${wheel_radius}" length="${wheel_length}" />
          geometry>
          <origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0" />
        collision>
        <xacro:cylinder_inertial_matrix m="${wheel_m}" r="${wheel_radius}" h="${wheel_length}" />

      link>

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

      <gazebo reference="${name}_wheel">
        <material>Gazebo/Redmaterial>
      gazebo>

    xacro:macro>
    <xacro:add_wheels name="left" flag="1" />
    <xacro:add_wheels name="right" flag="-1" />
    
    
    <xacro:property name="support_wheel_radius" value="0.0075" /> 
    <xacro:property name="support_wheel_m" value="0.03" /> 

    
    <xacro:macro name="add_support_wheel" params="name flag" >
      <link name="${name}_wheel">
        <visual>
            <geometry>
                <sphere radius="${support_wheel_radius}" />
            geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="black" />
        visual>
        <collision>
            <geometry>
                <sphere radius="${support_wheel_radius}" />
            geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
        collision>
        <xacro:sphere_inertial_matrix m="${support_wheel_m}" r="${support_wheel_radius}" />
      link>

      <joint name="${name}_wheel2base_link" type="continuous">
          <parent link="base_link" />
          <child link="${name}_wheel" />
          <origin xyz="${flag * (base_link_radius - support_wheel_radius)} 0 ${-(base_link_length / 2 + earth_space / 2)}" />
          <axis xyz="1 1 1" />
      joint>
      <gazebo reference="${name}_wheel">
        <material>Gazebo/Redmaterial>
      gazebo>
    xacro:macro>

    <xacro:add_support_wheel name="front" flag="1" />
    <xacro:add_support_wheel name="back" flag="-1" />


robot>

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

  1. 惯性矩阵是否设置了,且设置是否正确合理
  2. 车轮翻转需要依赖于 PI 值,如果 PI 值精度偏低,也可能导致上述情况产生

B.摄像头 Xacro 文件


<robot name="my_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    
    <xacro:property name="camera_length" value="0.01" /> 
    <xacro:property name="camera_width" value="0.025" /> 
    <xacro:property name="camera_height" value="0.025" /> 
    <xacro:property name="camera_x" value="0.08" /> 
    <xacro:property name="camera_y" value="0.0" /> 
    <xacro:property name="camera_z" value="${base_link_length / 2 + camera_height / 2}" /> 

    <xacro:property name="camera_m" value="0.01" /> 

    
    <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" />
        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_m}" l="${camera_length}" w="${camera_width}" h="${camera_height}" />
    link>

    <joint name="camera2base_link" type="fixed">
        <parent link="base_link" />
        <child link="camera" />
        <origin xyz="${camera_x} ${camera_y} ${camera_z}" />
    joint>
    <gazebo reference="camera">
        <material>Gazebo/Bluematerial>
    gazebo>
robot>

C.雷达 Xacro 文件


<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_x" value="0.0" /> 
    <xacro:property name="support_y" value="0.0" /> 
    <xacro:property name="support_z" value="${base_link_length / 2 + support_length / 2}" /> 

    <xacro:property name="support_m" value="0.02" /> 

    <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.8" />
            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_m}" r="${support_radius}" h="${support_length}" />

    link>

    <joint name="support2base_link" type="fixed">
        <parent link="base_link" />
        <child link="support" />
        <origin xyz="${support_x} ${support_y} ${support_z}" />
    joint>

    <gazebo reference="support">
        <material>Gazebo/Whitematerial>
    gazebo>

    
    <xacro:property name="laser_length" value="0.05" /> 
    <xacro:property name="laser_radius" value="0.03" /> 
    <xacro:property name="laser_x" value="0.0" /> 
    <xacro:property name="laser_y" value="0.0" /> 
    <xacro:property name="laser_z" value="${support_length / 2 + laser_length / 2}" /> 

    <xacro:property name="laser_m" value="0.1" /> 

    
    <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" />
        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_m}" r="${laser_radius}" h="${laser_length}" />
    link>

    <joint name="laser2support" type="fixed">
        <parent link="support" />
        <child link="laser" />
        <origin xyz="${laser_x} ${laser_y} ${laser_z}" />
    joint>
    <gazebo reference="laser">
        <material>Gazebo/Blackmaterial>
    gazebo>
robot>

D.组合底盘、摄像头与雷达的 Xacro 文件


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

launch 文件:

<launch>
    
    <param name="robot_description" command="$(find xacro)/xacro $(find urdf_gazebo)/xacro/all.xacro" />
    
    <include file="$(find gazebo_ros)/launch/empty_world.launch" />

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

6.4、仿真环境搭建

到目前为止,我们已经可以将机器人模型显示在 Gazebo 之中了,但是当前默认情况下,在 Gazebo 中机器人模型是在 empty world 中,并没有类似于房间、家具、道路、树木… 之类的仿真物,如何在 Gazebo 中创建仿真环境呢?

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

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

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

6.4.1、添加内置组件创建仿真环境

URDF+Gazebo+Rviz仿真_第4张图片

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

URDF+Gazebo+Rviz仿真_第5张图片

<launch>

    
    <param name="robot_description" command="$(find xacro)/xacro $(find demo02_urdf_gazebo)/urdf/xacro/my_base_camera_laser.urdf.xacro" />
    
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(find demo02_urdf_gazebo)/worlds/hello.world" />
    include>

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

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

<include file="$(find gazebo_ros)/launch/empty_world.launch">
    <arg name="world_name" value="$(find demo02_urdf_gazebo)/worlds/hello.world" />
include>
Copy
6.4.2、自定义仿真环境

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

URDF+Gazebo+Rviz仿真_第6张图片
URDF+Gazebo+Rviz仿真_第7张图片

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

然后 file —> Exit Building Editor

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

URDF+Gazebo+Rviz仿真_第8张图片

6.4.3、使用官方提供的插件

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

下载官方模型库

git clone https://github.com/osrf/gazebo_models

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

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

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

七、URDF、Gazebo、Rviz综合

关于URDF(Xacro)、Rviz 和 Gazebo 三者的关系,前面已有阐述: URDF 用于创建机器人模型、Rviz 可以显示机器人感知到的环境信息,Gazebo 用于仿真

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

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

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

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

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

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

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

两轮差速配置

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

    
    <xacro:macro name="joint_trans" params="joint_name">
        
        <transmission name="${joint_name}_trans">
            <type>transmission_interface/SimpleTransmissiontype>
            <joint name="${joint_name}">
                <hardwareInterface>hardware_interface/VelocityJointInterfacehardwareInterface>
            joint>
            <actuator name="${joint_name}_motor">
                <hardwareInterface>hardware_interface/VelocityJointInterfacehardwareInterface>
                <mechanicalReduction>1mechanicalReduction>
            actuator>
        transmission>
    xacro:macro>

    
    <xacro:joint_trans joint_name="left_wheel2base_link" />
    <xacro:joint_trans joint_name="right_wheel2base_link" />

    
    <gazebo>
        <plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
            <rosDebugLevel>DebugrosDebugLevel>
            <publishWheelTF>truepublishWheelTF>
            <robotNamespace>/robotNamespace>
            <publishTf>1publishTf>
            <publishWheelJointState>truepublishWheelJointState>
            <alwaysOn>truealwaysOn>
            <updateRate>100.0updateRate>
            <legacyMode>truelegacyMode>
            <leftJoint>left_wheel2base_linkleftJoint> 
            <rightJoint>right_wheel2base_linkrightJoint> 
            <wheelSeparation>${base_link_radius * 2}wheelSeparation> 
            <wheelDiameter>${wheel_radius * 2}wheelDiameter> 
            <broadcastTF>1broadcastTF>
            <wheelTorque>30wheelTorque>
            <wheelAcceleration>1.8wheelAcceleration>
            <commandTopic>cmd_velcommandTopic> 
            <odometryFrame>odomodometryFrame> 
            <odometryTopic>odomodometryTopic> 
            <robotBaseFrame>base_footprintrobotBaseFrame> 
        plugin>
    gazebo>
robot>

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


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

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

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

launch文件:

<launch>

    
    <param name="robot_description" command="$(find xacro)/xacro $(find demo02_urdf_gazebo)/urdf/xacro/my_base_camera_laser.urdf.xacro" />
    
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(find demo02_urdf_gazebo)/worlds/hello.world" />
    include>

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

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

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

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

接下来我们会发现: 小车在 Gazebo 中已经正常运行起来了

7.2、雷达信息仿真及其显示

雷达仿真基本流程:

  1. 已经创建完毕的机器人模型,编写一个单独的 xacro 文件,为机器人模型添加雷达配置;
  2. 将此文件集成进xacro文件;
  3. 启动 Gazebo,使用 Rviz 显示雷达信息。
7.2.1、Gazebo 仿真雷达

新建 Xacro 文件,配置雷达传感器信息

<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 0pose>
      <visualize>truevisualize>
      <update_rate>5.5update_rate>
      <ray>
        <scan>
          <horizontal>
            <samples>360samples>
            <resolution>1resolution>
            <min_angle>-3min_angle>
            <max_angle>3max_angle>
          horizontal>
        scan>
        <range>
          <min>0.10min>
          <max>30.0max>
          <resolution>0.01resolution>
        range>
        <noise>
          <type>gaussiantype>
          <mean>0.0mean>
          <stddev>0.01stddev>
        noise>
      ray>
      <plugin name="gazebo_rplidar" filename="libgazebo_ros_laser.so">
        <topicName>/scantopicName>
        <frameName>laserframeName>
      plugin>
    sensor>
  gazebo>
robot>

xacro 文件集成

将步骤1的 Xacro 文件集成进总的机器人模型文件,代码示例如下:


<robot name="my_car_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="my_head.urdf.xacro" />
    <xacro:include filename="my_base.urdf.xacro" />
    <xacro:include filename="my_camera.urdf.xacro" />
    <xacro:include filename="my_laser.urdf.xacro" />
    <xacro:include filename="move.urdf.xacro" />
    
    <xacro:include filename="my_sensors_laser.urdf.xacro" />
robot>

启动仿真环境

编写launch文件,启动gazebo,此处略…

7.2.2、Rviz 显示雷达数据

先启动 rviz,添加雷达信息显示插件

URDF+Gazebo+Rviz仿真_第9张图片

7.3、摄像头信息仿真及其显示

通过 Gazebo 模拟摄像头传感器,并在 Rviz 中显示摄像头数据。

实现流程:

摄像头仿真基本流程:

  1. 已经创建完毕的机器人模型,编写一个单独的 xacro 文件,为机器人模型添加摄像头配置;
  2. 将此文件集成进xacro文件;
  3. 启动 Gazebo,使用 Rviz 显示摄像头信息。
7.3.1、Gazebo 仿真摄像头

新建 Xacro 文件,配置摄像头传感器信息

<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
  
  <gazebo reference="camera">
    
    <sensor type="camera" name="camera_node">
      <update_rate>30.0update_rate> 
      
      <camera name="head">
        <horizontal_fov>1.3962634horizontal_fov>
        <image>
          <width>1280width>
          <height>720height>
          <format>R8G8B8format>
        image>
        <clip>
          <near>0.02near>
          <far>300far>
        clip>
        <noise>
          <type>gaussiantype>
          <mean>0.0mean>
          <stddev>0.007stddev>
        noise>
      camera>
      
      <plugin name="gazebo_camera" filename="libgazebo_ros_camera.so">
        <alwaysOn>truealwaysOn>
        <updateRate>0.0updateRate>
        <cameraName>/cameracameraName>
        <imageTopicName>image_rawimageTopicName>
        <cameraInfoTopicName>camera_infocameraInfoTopicName>
        <frameName>cameraframeName>
        <hackBaseline>0.07hackBaseline>
        <distortionK1>0.0distortionK1>
        <distortionK2>0.0distortionK2>
        <distortionK3>0.0distortionK3>
        <distortionT1>0.0distortionT1>
        <distortionT2>0.0distortionT2>
      plugin>
    sensor>
  gazebo>
robot>

xacro 文件集成

将步骤1的 Xacro 文件集成进总的机器人模型文件,代码示例如下:


<robot name="my_car_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="my_head.urdf.xacro" />
    <xacro:include filename="my_base.urdf.xacro" />
    <xacro:include filename="my_camera.urdf.xacro" />
    <xacro:include filename="my_laser.urdf.xacro" />
    <xacro:include filename="move.urdf.xacro" />
    
    <xacro:include filename="my_sensors_camara.urdf.xacro" />
robot>

启动仿真环境

编写launch文件,启动gazebo,此处略…

7.3.2、Rviz 显示摄像头数据

执行 gazebo 并启动 Rviz,在 Rviz 中添加摄像头组件。

URDF+Gazebo+Rviz仿真_第10张图片

URDF+Gazebo+Rviz仿真_第11张图片

7.4、kinect信息仿真以及显示

实现流程:

kinect摄像头仿真基本流程:

  1. 已经创建完毕的机器人模型,编写一个单独的 xacro 文件,为机器人模型添加kinect摄像头配置;
  2. 将此文件集成进xacro文件;
  3. 启动 Gazebo,使用 Rviz 显示kinect摄像头信息。
7.4.1、Gazebo仿真Kinect

新建 Xacro 文件,配置 kinetic传感器信息

<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
    <gazebo reference="kinect link名称">  
      <sensor type="depth" name="camera">
        <always_on>truealways_on>
        <update_rate>20.0update_rate>
        <camera>
          <horizontal_fov>${60.0*PI/180.0}horizontal_fov>
          <image>
            <format>R8G8B8format>
            <width>640width>
            <height>480height>
          image>
          <clip>
            <near>0.05near>
            <far>8.0far>
          clip>
        camera>
        <plugin name="kinect_camera_controller" filename="libgazebo_ros_openni_kinect.so">
          <cameraName>cameracameraName>
          <alwaysOn>truealwaysOn>
          <updateRate>10updateRate>
          <imageTopicName>rgb/image_rawimageTopicName>
          <depthImageTopicName>depth/image_rawdepthImageTopicName>
          <pointCloudTopicName>depth/pointspointCloudTopicName>
          <cameraInfoTopicName>rgb/camera_infocameraInfoTopicName>
          <depthImageCameraInfoTopicName>depth/camera_infodepthImageCameraInfoTopicName>
          <frameName>kinect link名称frameName>
          <baseline>0.1baseline>
          <distortion_k1>0.0distortion_k1>
          <distortion_k2>0.0distortion_k2>
          <distortion_k3>0.0distortion_k3>
          <distortion_t1>0.0distortion_t1>
          <distortion_t2>0.0distortion_t2>
          <pointCloudCutoff>0.4pointCloudCutoff>
        plugin>
      sensor>
    gazebo>

robot>

xacro 文件集成

将步骤1的 Xacro 文件集成进总的机器人模型文件,代码示例如下:


<robot name="my_car_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="my_head.urdf.xacro" />
    <xacro:include filename="my_base.urdf.xacro" />
    <xacro:include filename="my_camera.urdf.xacro" />
    <xacro:include filename="my_laser.urdf.xacro" />
    <xacro:include filename="move.urdf.xacro" />
    
    <xacro:include filename="my_sensors_kinect.urdf.xacro" />
robot>
7.4.2、Rviz 显示 Kinect 数据

启动 rviz,添加摄像头组件查看数据

URDF+Gazebo+Rviz仿真_第12张图片

URDF+Gazebo+Rviz仿真_第13张图片


7.4.3、补充:kinect 点云数据显示

在kinect中也可以以点云的方式显示感知周围环境,在 rviz 中操作如下:

URDF+Gazebo+Rviz仿真_第14张图片

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

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

解决:

1.在插件中为kinect设置坐标系,修改配置文件的标签内容:

<frameName>support_depthframeName>

2.发布新设置的坐标系到kinect连杆的坐标变换关系,在启动rviz的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" />

3.启动rviz,重新显示。

URDF+Gazebo+Rviz仿真_第15张图片

你可能感兴趣的:(ROS,ROS,CPP,launch)