ROS学习笔记16:机器人系统建模与仿真

2023-11-16

一、概述:

1.机器人系统仿真:

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

(1)仿真优势:低成本、高效、高安全性。

(2)仿真缺陷:仿真器所使用的物理引擎目前还不能够完全精确模拟真实世界的物理情况;仿真器构建的是关节驱动器(电机&齿轮箱)、传感器与信号通信的绝对理想情况,目前不支持模拟实际硬件缺陷或者一些临界状态等情形。

2.机器人系统仿真所需组件:

(1)创建机器人模型:

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

(2)显示各传感器信息:

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

(3)搭建仿真环境:

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

二、URDF语法讲解:

1.将URDF集成进rviz基本流程:

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

(1)创建功能包,并导入依赖:

        在该功能包下创建四个文件夹:

1)urdf:用于存放机器人模型的URDF或xacro文件;

2)meshes:用于放置URDF中引用的模型渲染文件;

3)launch:用于保存相关启动文件;

4)config:用于保存rviz的配置文件。

(2)编写urdf文件:

        在功能包中新建子文件夹:urdf,添加一个.urdf文件,内容如下:

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

(3)在launch文件中集成URDF与rviz:

        在功能包中新建子文件夹:launch,添加一个.launch文件,内容如下:

<launch>
 
    <!-- 设置参数 -->
    <param name="robot_description" textfile="$((find learning_urdf)/urdf/mycar.urdf" />
 
    <!-- 启动 rviz -->
    <node pkg="rviz" type="rviz" name="rviz" />
 
</launch>

(4)通过launch文件启动rviz,并加载机器人模型:

PS:编译过程中有可能出现因缺少xacro的包导致编译失败

 解决方式是输入以下安装指令安装xacro相关包:

sudo apt-get install ros-noetic-xacro

(5)rviz 启动后,会发现并没有机器人模型,这是因为默认情况下没有添加机器人显示组件,需要手动添加,添加方式如下:

 (6)Fixed Frame处要将默认值map改为urdf文件中机器人底座的name(此处设置的是base_link):

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

1)在功能包中新建子文件夹config:

2)将文件另存为一个.rviz文件:

2.urdf语法:

        URDF文件是一个标准的XML文件,在ROS中预定义了一系列的标签用于描述机器人模型机器人模型可能较为复杂,但是ROS的URDF中机器人的组成却是较为简单,URDF中有四类标签:

        <robot>:根标签,类似于 launch文件中的launch标签;

        <link>:连杆标签;

        <joint>:关节标签;

        <gazebo>: 集成gazebo需要使用的标签。

(1)<robot>标签:

        <robot>标签是完整机器人模型最顶层标签,<link>和<joint>标签都必须包含在<robot>标签内。如下图所示,一个完整的机器人模型由一系列<link>和<joint>组成:

         <robot>标签内可以设置机器人的名称,其基本语法如下:

<robot name="<name of the robot>">
  <link>......</link>
  <link>......</link>
  <joint>......</joint>
  <joint>......</joint>
</robot>

(2)<link>标签:

        <link>标签用于描述机器人某个部件的外观和物理属性,如形状、尺寸、颜色、惯性矩阵、碰撞参数等。机器人的link结构一般如下图所示:

        基本的URDF描述语法如下:

<link name="<link name>">
  <inertial>......</inertial>
  <visual>......</visual>
  <collision>......</collision>
</link>

      子标签的描述内容如下:

示例:demo02_link.urdf

<link name="base_link">
  <visual>
    <!--形状-->
    <geometry>
      <!--长方体的长宽高-->
      <!--<box size="0.5 0.3 0.1" />-->
      <!--圆柱,半径和长度-->
      <!--<cylinder radius="0.5" length="0.1" />-->
      <!--球体,半径-->
      <!--<sphere radius="0.3" />-->
      <!--皮肤-->
      <!--<mesh filename="package://learning_urdf/meshes/autolabor_mini.stl" />-->
    </geometry>
    <!--xyz坐标 rpy翻滚、俯仰、偏航(弧度)-->
    <origin xyz="0 0 0" rpy="0 0 0" />
    <!--颜色:r=red g=green b=blue a=alpha-->
    <material name="black" >
      <color rgba="0.7 0.5 0 0.5" />
    </material>
  </visual>
</link>

(3)<joint>标签:

        <joint>标签用于描述机器人关节的运动学和动力学属性,包括关节运动的位置和速度限制。

        根据机器人的关节运动形式,可以将其分为六种类型:

        与人的关节一样,机器人关节(joint)的主要作用是连接两个刚体(link),这两个link分别称为parent linkchild link,如下图所示:

         <joint>标签的描述语法如下:

<joint name="<name of the joint>" type="<type of the joint>">
  <parent link="parent_link" />
  <child link="child_link" />
  <calibration .../>
  <dynamics damping .../>
  <limit effort .../>
  ...
</joint>

        在这些joint的属性中,必须指定joint的parent link和child link,其他属性可选:

1)<parent link>:强制的属性,父级连杆的名字,是这个link在机器人结构树中的名字。

2)<child link>:强制的属性,子级连杆的名字,是这个link在机器人结构树中的名字。

3)<origin>:xyz=各轴线上的偏移量 rpy=各轴线上的偏移弧度。

4)<axis>:xyz用于设置围绕哪个关节轴运动。

5)<calibration>:关节的参考位置,用来校准关节的绝对位置。

6)<dynamics>:用于描述关节的物理属性,例如阻尼值、物理静摩擦力等,经常在动力学仿真中用到。

7)<limit>:用于描述运动的一些极限值,包括关节运动的上下限位置、速度限制、力矩限制等。

8)<mimic>:用于描述该关节与已有关节的关系。

9)<safety_controller>:用于描述安全控制器参数。

(4)<gazebo>标签:

        <gazebo>标签用于描述机器人在Gazebo模型中仿真所需要的参数,包括机器人材料的属性、Gazebo插件等。该标签不是机器人模型必须的部分,只有在Gazebo仿真时才需要加入。

        基本语法如下:

<gazebo reference="link_1">
  <material>Gazebo/Black</material>
</gazebo>

3.(练习)创建机器人模型,底盘为长方体,在长方体的上方安装一摄像头,摄像头可以沿着z轴360度旋转:

(1)编写demo03_joint.urdf文件:

<!--设置机器人底盘,并添加摄像头-->
<robot name="mycar" >
  <!--1.底盘 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>
  <!--2.摄像头 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>
  <!--3.关节 joint-->
  <joint name="camera2base" type="continuous">
    <parent link="base_link" />
    <child link="camera" />
    <!--设置偏移量-->
    <origin xyz="0.13 0 0.05" rpy="0 0 0" />
    <!--设置关节旋转参考坐标轴-->
    <axis xyz="0 0 1" />
  </joint>
</robot>

(2)编写launch文件:

        joint_state_publisher节点:可以发布每个joint的状态。

        robot_state_publisher节点:将机器人各个link、joint之间的关系,通过TF的形式整理成三维姿态信息发布出去。

<launch>
  <!--1.在参数服务器载入urdf文件-->
  <param name="robot_description" textfile="$(find learning_urdf)/urdf/demo03_joint.urdf" />
  <!--2.启动rviz-->
  <node pkg="rviz" type="rviz" name="rviz" args="-d $(find learning_urdf)/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>

(3)运行:

 

PS:使用launch文件启动rviz时,可能出现如下报错

解决方案 :缺少依赖包,按指令安装以下依赖包即可

sudo apt-get install ros-noetic-robot-state-publisher
sudo apt-get install ros-noetic-joint-state-publisher
sudo apt-get install ros-noetic-joint-state-publisher-gui

        补充完以上依赖包后,通过launch文件打开rviz,发现之前存在的status错误全部解决了。

4.base_footprint优化urdf:

        之前实现的机器人模型是半沉到地下的,因为默认情况下: 底盘的中心点位于地图原点上,所以会导致这种情况产生。

        优化策略:将初始link设置为一个尺寸极小的link(比如半径为0.001m的球体,或边长0.001m的立方体),然后再在初始 link上添加底盘等刚体,这个初始link一般称之为 base_footprint。

<!--base_footprint-->
<link name="base_footprint">
  <visual>
    <geometry>
      <box size="0.001 0.001 0.001" />
    </geometry>
  </visual>
</link>
<!--关联baes_link与base_footprint-->
  <joint name="link2footprint" type="fixed">
    <parent link="base_footprint" />
    <child_link="base_link" />
    <!--设置偏移量-->
    <origin xyz="0 0 0.05" rpy="0 0 0" />
</joint>

base_footprint的相关链接:

DAY5-URDF优化 简单小练习 工具_Zima Blue?的博客-CSDN博客

【ROS_URDF】小车+摄像头+优化footprint的urdf文件,带中文注释_Baily24的博客-CSDN博客

5.(课后作业)urdf文件编写练习:

要求:

(1)新建文件,demo05_test.urdf,并与launch文件集成;

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

作业过程:

(1)创建urdf文件:

<robot name="mycar">
    <!-- 设置 base_footprint  -->
	    <link name="base_footprint">
	        <visual>
	            <geometry>
	                <sphere radius="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="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.25 cm
	            宽度: 1.5  cm
	            颜色: 黑色
	        关节设置:
	            x = 0
	            y = 底盘的半径 + 轮胎宽度 / 2
	            z = 离地间距 + 底盘长度 / 2 - 轮胎半径 = 1.5 + 4 - 3.25 = 2.25(cm)
	            axis = 0 1 0
	    -->
	    <link name="left_wheel">
	        <visual>
	            <geometry>
	                <cylinder radius="0.0325" length="0.015" />
	            </geometry>
	            <origin xyz="0 0 0" rpy="1.5705 0 0" />
	            <material name="black">
	                <color rgba="0.0 0.0 0.0 1.0" />
	            </material>
	        </visual>
	
	    </link>
	
	    <joint name="left_wheel2base_link" type="continuous">
	        <parent link="base_link" />
	        <child link="left_wheel" />
	        <origin xyz="0 0.1 -0.0225" />
	        <axis xyz="0 1 0" />
	    </joint>
	
	
	    <link name="right_wheel">
	        <visual>
	            <geometry>
	                <cylinder radius="0.0325" length="0.015" />
	            </geometry>
	            <origin xyz="0 0 0" rpy="1.5705 0 0" />
	            <material name="black">
	                <color rgba="0.0 0.0 0.0 1.0" />
	            </material>
	        </visual>
	
	    </link>
	
	    <joint name="right_wheel2base_link" type="continuous">
	        <parent link="base_link" />
	        <child link="right_wheel" />
	        <origin xyz="0 -0.1 -0.0225" />
	        <axis xyz="0 1 0" />
	    </joint>


    <!-- 添加万向轮(支撑轮) -->
	    <!--
	        参数
	            形状: 球体
	            半径: 0.75 cm
	            颜色: 黑色
	
	        关节设置:
	            x = 自定义(底盘半径 - 万向轮半径) = 0.1 - 0.0075 = 0.0925(cm)
	            y = 0
	            z = 底盘长度 / 2 + 离地间距 / 2 = 0.08 / 2 + 0.015 / 2 = 0.0475 
	            axis= 1 1 1
	
	    -->
	    <link name="front_wheel">
	        <visual>
	            <geometry>
	                <sphere radius="0.0075" />
	            </geometry>
	            <origin xyz="0 0 0" rpy="0 0 0" />
	            <material name="black">
	                <color rgba="0.0 0.0 0.0 1.0" />
	            </material>
	        </visual>
	    </link>
	
	    <joint name="front_wheel2base_link" type="continuous">
	        <parent link="base_link" />
	        <child link="front_wheel" />
	        <origin xyz="0.0925 0 -0.0475" />
	        <axis xyz="1 1 1" />
	    </joint>
	
	    <link name="back_wheel">
	        <visual>
	            <geometry>
	                <sphere radius="0.0075" />
	            </geometry>
	            <origin xyz="0 0 0" rpy="0 0 0" />
	            <material name="black">
	                <color rgba="0.0 0.0 0.0 1.0" />
	            </material>
	        </visual>
	    </link>
	
	    <joint name="back_wheel2base_link" type="continuous">
	        <parent link="base_link" />
	        <child link="back_wheel" />
	        <origin xyz="-0.0925 0 -0.0475" />
	        <axis xyz="1 1 1" />
	    </joint>
</robot>

(2) 在launch文件中集成URDF与rviz:

<launch>
    <!-- 将 urdf 文件内容设置进参数服务器 -->
    <param name="robot_description" textfile="$(find demo01_urdf_helloworld)/urdf/urdf/test.urdf" />

    <!-- 启动 rivz -->
    <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)编译,通过launch文件启动rviz,并加载机器人模型:

相关链接:

【基于ROS的URDF练习实例】四轮机器人与摄像头的使用_生如昭诩的博客-CSDN博客

6.urdf工具:

        URDF提供了一些命令行工具,可以帮助我们检查、梳理模型文件,需要在终端中独立安装:

sudo apt-get install liburdfdom-tools

(1)check_urdf语法检查:

check_urdf <名称>.urdf

        check_urdf会解析urdf文件,并且显示解析过程中发现的错误。如果一切正常,在终端中会输出以下信息:

(2)urdf_to_graphiz结构查看:

urdf_to_graphiz <名称>.urdf

        urdf_to_graphiz命令可以查看urdf模型的整体结构。

三、URDF优化—xacro:

1.xacro简介:

        urdf构建的机器人模型存在以下问题:

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

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

        在 ROS 中,为解决这样的问题,针对urdf模型产生了另一种精简化、可复用、模块化的描述形式——xacro,它具备如下优势:

(1)精简模型代码:在xacro文件中,可以通过创建宏定义的方式定义常量或复用代码,不仅可以减少代码量,而且可以让模型代码更加模块化、更具可读性;

(2)提供可编程接口:xacro的语法支持一些可编程接口,如常量、变量、数学公式、条件语句等,可以让建模过程更加智能有效。

2.xacro语法讲解:

(1)属性与算术运算:

1)属性定义:

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

2)属性调用:

${属性名称}

3)算术运算:

${数学表达式}

(2)宏:

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

1)宏定义:

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

2)宏调用:

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

(3)文件包含:

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

3.xacro文件编写:

demo01.urdf.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>

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

4.xacro文件转换成urdf文件:

        命令行进入 xacro文件 所属目录,执行:

rosrun xacro xacro <文件名>.xacro > <文件名>.urdf

        这样就将 xacro 文件解析为 urdf 文件,并储存在当前路径。

 解析前:

 解析后:

5.xacro文件集成launch文件:

<launch>
  <!--1.在参数服务器载入urdf文件-->
  <param name="robot_description" command="$(find xacro)/xacro $(find learning_urdf)/urdf/demo01.urdf.xacro" />
  <!--2.启动rviz-->
  <node pkg="rviz" type="rviz" name="rviz" args="-d $(find learning_urdf)/config/show_mycar.rviz" />
  <!--3.关节状态发布节点-->
  <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
  <!--4.机器人状态发布节点-->
  <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
</launch>

6.通过launch启动rviz:

(这里笔者做出来的结果总是报错,错误原因应该是demo01.urdf.xacro代码有错误,但笔者尚未找到错误,也尚未在网上找到可用代码)

相关链接:

ROS ERROR_printeger的博客-CSDN博客

使用xacro优化URDF的问题解决_m0_56588389的博客-CSDN博客

四.xacro练习:

1.要求:

(1)将demo05_test.urdf所搭建的机器人,改写为.xacro文件,驱动轮和支撑轮通过宏实现;

(2)将所提供的摄像头与雷达的.xacro文件与机器人底盘组合,用<xacro:include filename=“xxx.xacro” />调用各文件 ;

(3)通过launch文件启动rviz并显示模型。

2.编写xacro文件:

(1)小车底盘的xacro文件:

<!--
    使用 xacro 优化 URDF 版的小车底盘实现:

    实现思路:
    1.将一些常量、变量封装为 xacro:property
      比如:PI 值、小车底盘半径、离地间距、车轮半径、宽度 ....
    2.使用 宏 封装驱动轮以及支撑轮实现,调用相关宏生成驱动轮与支撑轮

-->
<!-- 根标签,必须声明 xmlns: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" /> <!-- base_footprint 半径  -->
    <xacro:property name="base_link_radius" value="0.1" /> <!-- base_link 半径 -->
    <xacro:property name="base_link_length" value="0.08" /> <!-- base_link 长 -->
    <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>

(2)摄像头的xacro文件:

<!-- 根标签,必须声明 xmlns:xacro -->
<robot name="my_base" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <!--摄像头组件-->
    <!--参数:自身长宽高,关节属性:xyz偏移量-->
    <xacro:property name="camera_length" value="0.02" /> <!-- 厚度x -->
    <xacro:property name="camera_width" value="0.025" /> <!-- 宽度y -->
    <xacro:property name="camera_height" value="0.04" /> <!-- 高度z -->
    <xacro:property name="joint_camera_x" value="0.08" /> <!--  -->
    <xacro:property name="joint_camera_y" value="0" /> <!--  -->
    <xacro:property name="joint_camera_z" value="${base_link_length / 2 + camera_height / 2}" /> <!--  -->
    
    <!--设计连杆和关节-->
    <link name="camera">
    	<visual>
    		<geometry>
    			<box size="${camera_length} ${camera_width} ${camera_height}" />
    		</geometry>
    		<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}" rpy="0 0 0" />	
    </joint>
</robot>

(3)雷达的xacro文件:

<!-- 根标签,必须声明 xmlns:xacro -->
<robot name="my_base" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <!--雷达组件-->
    <!--支架 参数:半径、高度,关节偏移量xyz-->
    <xacro:property name="support_radius" value="0.01" /> <!--  -->
    <xacro:property name="support_length" value="0.15" />
    <xacro:property name="joint_support_x" value="0" />
    <xacro:property name="joint_support_y" value="0" />
    <xacro:property name="joint_support_z" value="${base_link_length / 2 + support_length / 2}" />
    
    <!--雷达 参数:半径、高度,关节偏移量xyz-->
    <xacro:property name="laser_radius" value="0.03" /> <!--  -->
    <xacro:property name="laser_length" value="0.05" />
    <xacro:property name="joint_laser_x" value="0" />
    <xacro:property name="joint_laser_y" value="0" />
    <xacro:property name="joint_laser_z" value="${support_length / 2 + laser_length / 2}" />
    
    <!--支架-->
    <link name="support">
    	<visual>
    		<geometry>
    			<cylinder radius="${support_radius}" length="${support_length}" />
    		</geometry>
    		<material name="yellow">
    			<color rgba="0.8 0.1 0.2 0.5" />
    		</material>
    	</visual>
    </link>
    
    <joint name="support2base" type="fixed">
    	<parent link="base_link" />
    	<child link="support" />
    	<origin xyz="${joint_support_x} ${joint_support_y} ${joint_support_z}" rpy="0 0 0" />
    </joint>
    
    <!--雷达-->
    <link name="laser">
    	<visual>
    		<geometry>
    			<cylinder radius="${laser_radius}" length="${laser_length}" />
    		</geometry>
    		<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}" rpy="0 0 0" />
    </joint>
</robot>

3.组合小车模型文件:

<!-- 组合小车底盘与摄像头与雷达 -->
<robot name="my_car_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="demo06_car_base.urdf.xacro" />
    <xacro:include filename="demo06_car_camera.urdf.xacro" />
    <xacro:include filename="demo06_car_laser.urdf.xacro" />
</robot>

4.编写launch文件:

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

5.通过launch文件启动rviz:

 相关链接:

【ROS进阶篇】第八讲(下) URDF的编程优化Xacro使用_生如昭诩的博客-CSDN博客

五、基于ArbotiX和rviz的仿真器(rviz中控制机器人运动):

1.ArbotiX介绍:

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

2.安装ArbotiX:

安装方式一:命令行调用

sudo apt-get install ros-noetic-arbotix

        如果命令行安装失败,尝试方式二。

安装方式二:源码安装

git clone https://github.com/vanadiumlabs/arbotix_ros.git
先从 github 下载源码,移至当前工作空间/src下,然后调用catkin_make编译。

3.添加ArbotiX所需的配置文件:

        在config文件夹下新建control.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 
    }
}

(详细内容参考:http://wiki.ros.org/arbotix_python/diff_controller)

4.launch文件中配置ArbotiX节点:

<launch>
  <!--1.在参数服务器载入urdf文件-->
  <param name="robot_description" command="$(find xacro)/xacro $(find learning_urdf)/urdf/demo06.urdf.xacro" />
  <!--2.启动rviz-->
  <node pkg="rviz" type="rviz" name="rviz" args="-d $(find learning_urdf)/config/show_mycar.rviz" />
  <!--3.关节状态发布节点-->
  <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
  <!--4.机器人状态发布节点-->
  <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
  <!--5.arbotix节点配置-->
  <node name="arbotix" pkg="arbotix_python" type="arbotix_driver" output="screen">
    <rosparam file="$(find learning_urdf)/config/control.yaml" command="load" />
    <param name="sim" value="true" />
  </node>
</launch>

(1)<node>调用了arbotix_python功能包下的arbotix_driver节点

(2)<rosparam>arbotix驱动机器人运行时,需要获取机器人信息,可以通过file家在配置文件

(3)<param>在仿真环境下,需要配置sim为true

5.启动launch文件并配置rviz:

6.控制机器人模型运动:

相关链接:

Rviz中控制机器人模型运动(arbotix)_most delay的博客-CSDN博客_rviz控制机器人运动

六、URDF集成Gazebo:

1.urdf与Gazebo集成的基本流程:

(1)创建功能包并导入依赖:

(2)修改urdf文件(这里以盒状的demo01.urdf的基础修改):

<!-- 
    创建一个机器人模型(盒状即可),显示在 Gazebo 中 
-->

<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/Black</material>
    </gazebo>

</robot>

注意, URDF 与 Gazebo 集成时,和 Rviz 有明显区别:
1)必须使用 <collision> 标签,在仿真环境中,必然涉及到碰撞检测,collision 提供碰撞检测的依据,简单的模型,可采用和<visual>标签中一样的内容;
2)必须使用 <inertial> 标签,包含了机器人的质量和惯性矩阵;
3)颜色设置,需要重新使用 <gazebo> 标签标注,<visual>中的颜色设置只能在 rviz 中显示。

(3)launch文件启动Gazebo并显示模型:

1)launch文件:

<launch>

    <!-- 将 Urdf 文件的内容加载到参数服务器 -->
    <param name="robot_description" textfile="$(find learning_gazebo_urdf)/urdf/demo01.urdf" />

    <!-- 启动 gazebo -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch" />

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

最后一句话意思是在Gazebo中加载一个机器人模型,该功能由gazebo_ros下的spawn_model提供:
-urdf 加载的是 urdf 文件
-model car 模型名称是 car
-param robot_description 从参数 robot_description 中载入模型

2)显示模型:

2.urdf集成Gazebo示例:

(1)编写封装惯性矩阵算法的xacro文件:

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

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

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

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

1)底盘文件(demo05_car_base.urdf.xacro):

<!--
    使用 xacro 优化 URDF 版的小车底盘实现:

    实现思路:
    1.将一些常量、变量封装为 xacro:property
      比如:PI 值、小车底盘半径、离地间距、车轮半径、宽度 ....
    2.使用 宏 封装驱动轮以及支撑轮实现,调用相关宏生成驱动轮与支撑轮

-->
<!-- 根标签,必须声明 xmlns:xacro -->
<robot name="my_base" xmlns:xacro="http://www.ros.org/wiki/xacro">
    <!-- 封装变量、常量 -->
    <!-- PI 值设置精度需要高一些,否则后续车轮翻转量计算时,可能会出现肉眼不能察觉的车轮倾斜,从而导致模型抖动 -->
    <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" /> <!-- base_footprint 半径  -->
    <xacro:property name="base_link_radius" value="0.1" /> <!-- base_link 半径 -->
    <xacro:property name="base_link_length" value="0.08" /> <!-- base_link 长 -->
    <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/Yellow</material>
    </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/Red</material>
      </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/Red</material>
      </gazebo>
    </xacro:macro>

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


</robot>

2)相机文件(demo05_car_camera.urdf.xacro):

<!-- 摄像头相关的 xacro 文件 -->
<robot name="my_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    <!-- 摄像头属性 -->
    <xacro:property name="camera_length" value="0.01" /> <!-- 摄像头长度(x) -->
    <xacro:property name="camera_width" value="0.025" /> <!-- 摄像头宽度(y) -->
    <xacro:property name="camera_height" value="0.025" /> <!-- 摄像头高度(z) -->
    <xacro:property name="camera_x" value="0.08" /> <!-- 摄像头安装的x坐标 -->
    <xacro:property name="camera_y" value="0.0" /> <!-- 摄像头安装的y坐标 -->
    <xacro:property name="camera_z" value="${base_link_length / 2 + camera_height / 2}" /> <!-- 摄像头安装的z坐标:底盘高度 / 2 + 摄像头高度 / 2  -->

    <xacro:property name="camera_m" value="0.01" /> <!-- 摄像头质量 -->

    <!-- 摄像头关节以及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" />
        </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/Blue</material>
    </gazebo>
</robot>

3)雷达文件(demo05_car_laser.urdf.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" /> <!-- 支架安装的x坐标 -->
    <xacro:property name="support_y" value="0.0" /> <!-- 支架安装的y坐标 -->
    <xacro:property name="support_z" value="${base_link_length / 2 + support_length / 2}" /> <!-- 支架安装的z坐标:底盘高度 / 2 + 支架高度 / 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/White</material>
    </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" /> <!-- 雷达安装的x坐标 -->
    <xacro:property name="laser_y" value="0.0" /> <!-- 雷达安装的y坐标 -->
    <xacro:property name="laser_z" value="${support_length / 2 + laser_length / 2}" /> <!-- 雷达安装的z坐标:支架高度 / 2 + 雷达高度 / 2  -->

    <xacro:property name="laser_m" value="0.1" /> <!-- 雷达质量 -->

    <!-- 雷达关节以及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" />
        </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/Black</material>
    </gazebo>
</robot>

4)组合底盘、摄像头与雷达的 Xacro 文件(demo05.urdf.xacro):

<!-- 组合小车底盘与摄像头与雷达 -->
<robot name="my_car_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="demo05_test.urdf.xacro" />
    <xacro:include filename="demo05_car_base.urdf.xacro" />
    <xacro:include filename="demo05_car_camera.urdf.xacro" />
    <xacro:include filename="demo05_car_laser.urdf.xacro" />
</robot>

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

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

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

3.Gazebo仿真环境搭建:

七、URDF、rviz、Gazebo综合应用:

1.ros_control:

        rviz+Arbotix构建的仿真器使用了Arbotix差速控制器实现对机器人模型的控制,但是这款控制器有很大的局限性,无法在ROS丰富的机器人应用中通用。

        ros_control是ROS为开发者提供的机器人控制中间件,包含一系列控制器接口、传动装置接口、硬件接口、控制器工具等,可以帮助机器人应用功能包快速落地,提高开发效率。

2.运动控制实现流程:

(1)为已经创建完毕的机器人模型,编写一个单独的xacro文件,添加传动装置以及控制器:

<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="left_wheel2base_link" />
    <xacro:joint_trans joint_name="right_wheel2base_link" />

    <!-- 控制器 -->
    <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>left_wheel2base_link</leftJoint> <!-- 左轮 -->
            <rightJoint>right_wheel2base_link</rightJoint> <!-- 右轮 -->
            <wheelSeparation>${base_link_radius * 2}</wheelSeparation> <!-- 车轮间距 -->
            <wheelDiameter>${wheel_radius * 2}</wheelDiameter> <!-- 车轮直径 -->
            <broadcastTF>1</broadcastTF>
            <wheelTorque>30</wheelTorque>
            <wheelAcceleration>1.8</wheelAcceleration>
            <commandTopic>cmd_vel</commandTopic> <!-- 运动控制话题 -->
            <odometryFrame>odom</odometryFrame> 
            <odometryTopic>odom</odometryTopic> <!-- 里程计话题 -->
            <robotBaseFrame>base_footprint</robotBaseFrame> <!-- 根坐标系 -->
        </plugin>
    </gazebo>

</robot>

(2)将move.xacro文件集成进总的机器人模型文件(以demo05.xacro为载体):

<!-- 组合小车底盘与摄像头与雷达 -->
<robot name="my_car_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="demo05_test.urdf.xacro" />
    <xacro:include filename="demo05_car_base.urdf.xacro" />
    <xacro:include filename="demo05_car_camera.urdf.xacro" />
    <xacro:include filename="demo05_car_laser.urdf.xacro" />
    <xacro:include filename="move.urdf.xacro" />
</robot>

(3)launch文件启动gazebo,加载课程所提供的仿真环境,控制小车运动:

解决方案:

sudo apt-get ros-noetic-teleop-twist-keyboard

 结果展示:

 

3.rviz查看里程计信息:

(1)launch文件启动rviz:

        创建demo06_odom.launch文件:

<launch>
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find learning_urdf)/config/demo05_test.rviz" />
        
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state" />
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state" />         
</launch>

(2)在rviz中添加组件:

1)启动demo06_car.launch文件:

2)启动demo06_odom.launch文件:

相关链接:

6.7.1 机器人系统仿真/URDF、Gazebo与Rviz综合运用/机器人运动控制以及里程计信息显示_janedipan的博客-CSDN博客

4.雷达信息仿真及显示:

(1)为机器人添加雷达配置:

<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
 
  <!-- 雷达 -->
  <gazebo reference="laser">    //reference要和laser连杆名称一致
    <sensor type="ray" name="rplidar">        //type雷达类型 name起名字
      <pose>0 0 0 0 0 0</pose>        //6D位姿
      <visualize>true</visualize>        //雷达射线true可视,false不可视
      <update_rate>5.5</update_rate>        //雷达射线更新频率  次/s
      <ray>
        <scan>
          <horizontal>
            <samples>360</samples>        //采样个数,雷达旋转一周采样数
            <resolution>1</resolution>        //分辨率,每N个射线测距一次,设置大一点设备计算压力小,但是损失精度
            <min_angle>-3</min_angle>        //采样范围,单位是弧度,以机器人朝向为中心
            <max_angle>3</max_angle>        //逆时针为正,顺时针为负(看下面演示)
          </horizontal>
        </scan>
        <range>
          <min>0.10</min>        //采样范围   单位  米
          <max>30.0</max>
          <resolution>0.01</resolution>         //采样精度
        </range>
        <noise>        //高斯噪声,数据采集不可能每次都准确
          <type>gaussian</type>
          <mean>0.0</mean>
          <stddev>0.01</stddev>
        </noise>
      </ray>
      <plugin name="gazebo_rplidar" filename="libgazebo_ros_laser.so">
        <topicName>/scan</topicName>        //雷达发布的话题!!!
        <frameName>laser</frameName>
      </plugin>
    </sensor>
  </gazebo>
 
</robot>

(2)将laser.xacro文件集成进总的机器人模型文件:

<!-- 组合小车底盘与摄像头与雷达 -->
<robot name="my_car_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="demo05_test.urdf.xacro" />
    <xacro:include filename="demo05_car_base.urdf.xacro" />
    <xacro:include filename="demo05_car_camera.urdf.xacro" />
    <xacro:include filename="demo05_car_laser.urdf.xacro" />
    <xacro:include filename="move.urdf.xacro" />
    <xacro:include filename="my_sensors_laser.urdf.xacro" />
</robot>

(3)launch文件启动gazebo和rviz并显示雷达数据:

相关链接:

ros学习笔记之雷达信息仿真及显示_要好好养胃的博客-CSDN博客

5.摄像头信息仿真及显示:

(1)为机器人添加摄像头配置:

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

(2)将laser.xacro文件集成进总的机器人模型文件:

<!-- 组合小车底盘与摄像头与雷达 -->
<robot name="my_car_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="demo05_test.urdf.xacro" />
    <xacro:include filename="demo05_car_base.urdf.xacro" />
    <xacro:include filename="demo05_car_camera.urdf.xacro" />
    <xacro:include filename="demo05_car_laser.urdf.xacro" />
    <xacro:include filename="move.urdf.xacro" />
    <xacro:include filename="my_sensors_camera.urdf.xacro" />
</robot>

(3)launch文件启动gazebo和rviz并显示摄像头数据:

1)启动gazebo:

2)打开rviz,添加摄像头:

相关链接:

6.7.3 摄像头信息仿真以及显示_赵虚左的博客-CSDN博客

6.kinect信息仿真及显示:

(1)为机器人添加kinect配置:

<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
    <gazebo reference="kinect link名称">  
      <sensor type="depth" name="camera">
        <always_on>true</always_on>
        <update_rate>20.0</update_rate>
        <camera>
          <horizontal_fov>${60.0*PI/180.0}</horizontal_fov>
          <image>
            <format>R8G8B8</format>
            <width>640</width>
            <height>480</height>
          </image>
          <clip>
            <near>0.05</near>
            <far>8.0</far>
          </clip>
        </camera>
        <plugin name="kinect_camera_controller" filename="libgazebo_ros_openni_kinect.so">
          <cameraName>camera</cameraName>
          <alwaysOn>true</alwaysOn>
          <updateRate>10</updateRate>
          <imageTopicName>rgb/image_raw</imageTopicName>
          <depthImageTopicName>depth/image_raw</depthImageTopicName>
          <pointCloudTopicName>depth/points</pointCloudTopicName>
          <cameraInfoTopicName>rgb/camera_info</cameraInfoTopicName>
          <depthImageCameraInfoTopicName>depth/camera_info</depthImageCameraInfoTopicName>
          <frameName>kinect link名称</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>

(2)将laser.xacro文件集成进总的机器人模型文件:

<!-- 组合小车底盘与摄像头与雷达 -->
<robot name="my_car_camera" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="demo05_test.urdf.xacro" />
    <xacro:include filename="demo05_car_base.urdf.xacro" />
    <xacro:include filename="demo05_car_camera.urdf.xacro" />
    <xacro:include filename="demo05_car_laser.urdf.xacro" />
    <xacro:include filename="move.urdf.xacro" />
    <xacro:include filename="my_sensors_laser.urdf.xacro" />
    <xacro:include filename="my_sensors_camera.urdf.xacro" />
    <xacro:include filename="kinect.xacro" />
</robot>

相关链接:

机器人系统仿真(十六)——摄像头和kinect信息仿真以及显示_蔡军帅的博客-CSDN博客

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

ROS学习笔记16:机器人系统建模与仿真 的相关文章

  • coreldraw软件完整最新版2022矢量图形设计软件

    CorelDRAW2022是一款矢量图平面设计软件 发展历史也很长 是平面设计师必学软件 和 illustrator 比起来操作性相对差一点 但在排版上比 AI 好用 还有一个很明显的优点就是在设计大型文件的时候不会很卡 矢量图形设计软件C
  • 设计模式C++学习笔记之二(Proxy代理模式)

    http www cnblogs com wanggary archive 2011 04 08 2009965 html 代理 一看名字就知道这只是个中介而已 真实的执行者在代理的后面呢 cbf4life在他的书里提的例子也很有趣 更详细
  • 基于Three.js的WebXR渲染入门

    1 Three js 渲染管线快速概览 我不会花太多时间讨论 Three JS 渲染管道的工作原理 因为它在互联网上有详细记录 例如 此链接 我将在下图中列出基础知识 以便更容易理解各个部分的去向 2 WebXR 设备 API 入门 在我们
  • AI绘画网站都有哪些比较好用?

    人工智能绘画网站是一种利用人工智能技术进行图像处理和创作的网站 这些绘画网站通常可以帮助艺术家以人工智能绘画的形式快速生成有趣 美丽和独特的绘画作品 无论你是专业的艺术家还是对人工智能绘画感兴趣的普通人 人工智能绘画网站都可以为你提供新的创
  • 【图像去噪】【TGV 正则器的快速计算方法】通过FFT的总(广义)变化进行图像去噪(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 图像去噪 TGV 正则化器的快速计算方法

随机推荐

  • tomcat部署war包出错解决方案

    tomcat部署war包出错解决方案 最最简单直接明了的方法 卸载重新再装一遍 笔者重装了5 6遍 算是整好了 写篇博客 希望你萌 少走弯路 这是我走的弯路 https 下载 安装 配置及部署war包出错解决方案 1 jdk的安装及配置 2
  • git、gitee创建第一个项目、导入项目到线上仓库

    1 新建一个空文件夹 2 在文件夹中运行git bash 3 克隆线上的空仓库到文件夹中 git clone 线上仓库的地址 eg git clone aaa git 4 将项目中的代码复制到文件夹中 5 提交项目代码 运行命令 1 git
  • Shell脚本相关命令

    文章目录 1 编写简单的hello world脚本 查看脚本内容 并运行 2 练习加减乘除 比较等基本的算术运算 3 使用test命令对两个数值比较 等于 小于 大于等于 注释说明含义 4 使用test命令对两个字符串比较 等于 非空 小于
  • 大数据学习线路图

    大数据学习线路图 Java教程 Java 教程 Java 简介 Java 开发环境配置 Java 基础语法 Java 对象和类 Java 基本数据类型 Java变量类型 Java修饰符 Java运算符 Java循环结构 Java分支结构 J
  • C++循环经典练习题

    目录 前言 一 方阵 二 乘法口诀表 1 正向打印 2 反向打印 三 打印三角形 1 正三角 2 倒三角 四 杨辉三角 五 水仙花数 六 斐波那契数列 七 进制转换 1 十进制转二进制 2 二进制转十进制 总结 前言 在C 的海洋中 循环是
  • Qt-4.7.2在dm365下的移植

    此篇为我的上一篇博客 Qt 4 7 2及QtEmbedded 4 7 2在ubuntu11 10下的安装 后续 主要参考 博客http blog chinaunix net uid 25652733 id 291521 html 同样 参照
  • 如何成为一个牛逼的程序员

    一个快乐的人 不是因为他拥有的多 而是因为他计较的少 心态比勤劳更重要 用心做好事 作为程序员 身边总是有牛逼的前辈 后辈或者同辈 牛逼的人总是让人羡慕 比如自己苦搞一天的 BUG 头发快抓掉完了 人家扫上两眼 改一行代码 问题就解决了 比
  • Building Mongodb with Visual Studio 2008

    Building Mongodb with Visual Studio 2008 标签 mongodbpythonjavascriptbuild数据库c 2011 08 27 14 43 938人阅读 评论 0 收藏 举报 分类 VS200
  • C++基础二:模板

    模板 模板的概念 模板就是建立通用的模具 大大提高复用性 例如生活中的模板 模板的特点 模板不可以直接使用 它只是一个框架 模板的通用并不是万能的 函数模板 C 另一种编程思想称为 泛型编程 主要利用的技术就是模板 C 提供两种模板机制 函
  • base64的原理及优缺点

    优点可以加密 减少了HTTTP请求 缺点是需要消耗CPU进行编解码
  • 机器学习总结(一)

    机器学习总结 一 一 基本概念 1 有监督学习 输入数据是带有标签的 称为有监督学习 2 无监督学习 输入数据是不带标签的 称为无监督学习 3 局部最优 函数值空间的一个有限区域内寻找最小值 这个最小值 是小于或等于附近点的函数值 但是有可
  • tinycore的探索

    tinycore的探索 缘起 tinycore的安装 tinycore的持久化 tinycore的初始设置 结语 参考博文 这篇文章会写一些我在学习tinycore的过程中的体会 感兴趣的同学可以了解一下 由于我也是刚开始学习 所以可能会不
  • 【Android】Android工具函数整理

    import android app Activity import android app ActivityManager import android app KeyguardManager import android content
  • TensorRT详细入门指南

    前言 大名鼎鼎的TensorRT有多牛逼就不多说了 因为确实很好用 作为在英伟达自家GPU上的推理库 这些年来一直被大力推广 更新也非常频繁 issue反馈也挺及时 社区的负责人员也很积极 简直不要太NICE 只是TensorRT的入门门槛
  • 比较器参数之Offset voltage(Vos)

    offset voltage 最关键的直流规格参数是输入失调电压 Vos 由于比较器的 Vos产生一个额外的直流电压与串联同相输入 它对比较器的输出阈值改变状态 让我们分析一个非反相具有三个不同 Vos 值的比较器电路更好地理解效果 请记住
  • paddle window10环境下使用conda安装

    话 一开始也是根据别人的文章 疯狂报错 我的建议是自己先根据文档进行搭建 pip 和 conda两种方式都进行了尝试 个人更推荐conda 使用pip好像会出现版本不兼容的问题 其次是会出现要大量手动pip install 的情况 cond
  • 使用coloc 进行 QTL 共定位Colocalization

    GWAS找到显著信号位点后 需要解释显著信号位点如何影响表型 常见的一个解释方法是共定位分析 主流的共定位分析包括 1 GWAS和eQTL共定位 2 GWAS和sQTL共定位 3 GWAS和meQTL共定位 4 GWAS和pQTL共定位 其
  • win7 系统安装图解教程

    链接 http www 360doc com content 10 0720 11 1495415 40258931 shtml
  • 【经典】SpringBoot thymeleaf模板引擎——WEB开发模板引擎

    模板引擎 可以使业务数据和用户界面分离 通过模板引擎自动生成一个HTML文档 简单的说可以理解为 分离数据和界面 简化网页开发 现在主流的模板引擎有Jsp Velocity Beetl Rocker Freemarker thymeleaf
  • ROS学习笔记16:机器人系统建模与仿真

    一 概述 1 机器人系统仿真 是通过计算机对实体机器人系统进行模拟的技术 在 ROS 中 仿真实现涉及的内容主要有三 对机器人建模 URDF 创建仿真环境 Gazebo 以及感知环境 Rviz 等系统性实现 1 仿真优势 低成本 高效 高安