Jetson nano之ROS入门 - - 机器人建模与仿真

文章目录

  • 前言
  • 一、URDF建模
    • 1. URDF语法详解
      • a. robot
      • b. link
      • c. joint
    • 2. URDF机器人建模实操
  • 二、Xacro宏优化
    • 1、 Xacro宏语法详解
    • 2、 Xacro建模实操
  • 三、Rviz与Gazebo仿真
    • 1、Gazebo集成URDF建模语法基础
    • 2、Gazebo集成URDF实操
  • 总结


前言

在这里插入图片描述

在ROS中,机器人建模和仿真是非常重要的一部分。通过建模和仿真,开发人员可以在不使用实际机器人的情况下进行开发和测试,从而节省时间和成本。ROS使用URDF (Unified Robot Description Format)作为机器人建模语言,并提供了一些工具来创建和编辑URDF文件,例如RViz和Gazebo等。

URDF文件:URDF文件描述了机器人的物理特性,包括链接和关节,以及传感器和执行器等。开发人员可以使用URDF文件来创建机器人模型,并在仿真环境中运行。

Gazebo仿真器:Gazebo是一款用于机器人仿真的强大工具,可以模拟机器人的物理特性和环境条件。Gazebo支持ROS,并且可以与ROS进行集成,使得开发人员可以使用ROS中的节点和消息来控制机器人模型。

RViz可视化工具:RViz是ROS的一个可视化工具,可以用于可视化机器人模型、传感器数据和控制输出等。开发人员可以使用RViz来调试机器人模型,并进行可视化分析。

ROS控制器:ROS提供了一些控制器,例如关节控制器和力控制器等,可以用于控制机器人模型的关节和执行器等。

通过使用上述工具和技术,开发人员可以轻松地创建和仿真机器人模型,并进行开发和测试。这使得机器人应用开发更加高效、灵活和可靠。


一、URDF建模

URDF是一种用于描述机器人模型的XML文件格式。URDF(Unified Robot Description Format)它是ROS中使用的标准格式之一。URDF包含机器人的几何形状、传感器、关节和链接等信息,可以用于构建机器人模型、仿真和控制。

URDF文件通常由文本编辑器编写,但也可以使用各种URDF编辑器和可视化工具来创建和编辑。URDF的常见编辑器包括Robotics Toolbox for MATLAB、Blender、SolidWorks和OpenRAVE等。

在ROS中,URDF文件可以与其他ROS工具和程序集成,例如ROS控制器和Gazebo仿真器。下面讲讲URDF的语法详解

1. URDF语法详解

a. robot

urdf 中为了保证 xml 语法的完整性,使用了robot标签作为根标签,所有的 link 和 joint 以及其他标签都必须包含在 robot 标签内

<!-- 根标签 -->
<robot name="car_robot">

	<!-- 子级标签 -->
	
</robot>

在根标签内可以通过 name 属性设置机器人模型的名称,其他标签都是子级标签

b. link

在这里插入图片描述
< l i n k > <link> <link> 标签用于描述一个物体或机器人的连接器。每个连接器都有其自己的坐标系,可以用于描述连接的相对位置和方向。每个 < l i n k > <link> <link> 标签都必须拥有一个独特的名称,并且可以包含多个 < v i s u a l > <visual> <visual> < c o l l i s i o n > <collision> <collision> < i n e r t i a l > <inertial> <inertial> < s e n s o r > <sensor> <sensor> < a u d i o > <audio> <audio> 子标签,用于描述连接器的属性和特征。

    <!-- 子标签name- - -> 为连杆命名 -->
    <link name="base_link">  
        <visual>
            <!-- 子标签geometry- - -> 设置连杆的形状 -->
            <geometry>
                <!-- 子标签box- - ->长方体的长宽高 -->
                <!-- <box size="0.5 0.3 0.1" /> -->
                <!-- 子标签cylinder- - ->圆柱的半径和长度 -->
                <!-- <cylinder radius="0.5" length="0.1" /> -->
                <!-- 子标签sphere- - ->球体的半径-->
                <!-- <sphere radius="0.3" /> -->

            </geometry>
            <!-- 子标签origin - - ->  设置偏移量与欧拉角(3.14=180度 1.57=90度) -->
            <origin xyz="0 0 0" rpy="0 0 0" />
            <!-- 子标签 metrial - - -> 设置材料颜色: r=red g=green b=blue a=alpha -->
            <material name="black">
                <color rgba="0.7 0.5 0 0.5" />
            </material>
            <!-- 子标签collision ---> 连杆的碰撞属性 -->
            <!-- 子标签Inertial ---> 连杆的惯性矩阵 -->
        </visual>
    </link>

c. joint

在这里插入图片描述
< j o i n t > <joint> <joint> 标签用于描述机器人模型中连接两个连接器的关节属性,用于描述机器人的运动学和动力学特性。每个 < j o i n t > <joint> <joint> 标签都必须拥有一个独特的名称,并且必须明确指定父连接器和子连接器的名称。在机器人模型中,多个 < l i n k > <link> <link> 标签可以通过 < j o i n t > <joint> <joint> 标签连接在一起,形成一个完整的机器人结构。连接器和关节的组合可以描述机器人的运动学和动力学特性,用于进行机器人模拟和控制。

<!-- 
    需求: 创建机器人模型,底盘为长方体,
         在长方体的前面添加一摄像头,
         摄像头可以沿着 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>

    <!-- 关节 -->
    <!-- 属性name - - -> 为关节命名 -->
    <!-- 属性type - - -> 关节运动形式:continuous旋转关节、revolute旋转关节、prismatic滑动关节、planer平面关节、floating浮动关节、fixed固定关节 -->
    <joint name="camera2baselink" type="continuous">
        <!-- parent link:父级连杆的名字,是这个link在机器人结构树中的名字 -->
        <parent link="base_link"/>
        <!-- child link:子级连杆的名字,是这个link在机器人结构树中的名字 -->
        <child link="camera" />
        <!-- origin:xyz=各轴线上的偏移量 rpy=各轴线上的偏移弧度 -->
        <origin xyz="0.2 0 0.075" rpy="0 0 0" />
        <!-- axis: xyz用于设置围绕哪个关节轴运动 -->
        <axis xyz="0 0 1" />
    </joint>

</robot>

2. URDF机器人建模实操

下面我们来实操一下URDF机器人建模,我们先建立一个简单的机器人底盘,再加上两个驱动轮和一个支撑轮,这样机器人就可以通过运动控制器运动了。首先右键src目录选择Create Catkin Package,添加几个依赖包roscpp,rospy,urdf,xacro,新建urdf文件夹,里面新建urdf文件夹,里面创建一个model.urdf文件

<robot name="mycar">
    <!-- 设置 base_footprint  -->
    <link name="base_footprint">
        <visual>
            <geometry>
                <sphere radius="0.001" />
            </geometry>
        </visual>
    </link>
    <!-- 设置 机器人底盘  -->
     <link name="base_link">
        <visual>
            <geometry>
                <cylinder radius="0.1" length="0.08" />
            </geometry>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <material name="yellow">
                <color rgba="0.8 0.3 0.1 0.5" />
            </material>
        </visual>
    </link>
    <!-- 设置 左驱动轮  -->
    <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>
	<!-- 设置 右驱动轮  -->
    <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>
	<!-- 设置 后支撑轮  -->
	 <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>

    <!-- 设置 base_footprint与机器人底盘的关节  -->
    <joint name="base_link2base_footprint" type="fixed">
        <parent link="base_footprint" />
        <child link="base_link"/>
        <origin xyz="0 0 0.055" />
    </joint>
     <!-- 设置 左驱动轮与机器人底盘的关节  -->
     <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>
     <!-- 设置 右驱动轮与机器人底盘的关节  -->
	 <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>
    <!-- 设置 后支撑轮与机器人底盘的关节  -->
    <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>

接着在功能包下创建launch文件夹,新建xxx.launch文件,然后根据文件路径修改以下代码并复制进去

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

    <!-- 启动 rivz -->
	<node pkg="rviz" type="rviz" name="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>

最后在打开终端,运行下面的命令

roslaunch xxx(功能包) xxx.launch(launch文件)

只要在rviz配置好就能显示机器人模型,rviz里面的配置我们后面会提到

二、Xacro宏优化

xacro是一个基于XML的宏语言,可以用来描述机器人模型的结构和参数。xacro文件可以通过编写简单的XML代码来生成URDF模型文件。在机器人模型复杂的情况下,xacro可以减少代码的重复,提高代码的可读性和可维护性,以提高机器人模型的性能和效率。

1、 Xacro宏语法详解

属性 property 用于封装 URDF 中的一些字段,比如: PAI 值,小车的尺寸,轮子半径,也可以用于算数计算,设置一些坐标偏移量

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

Xacro宏定义类似于函数定义实现,可提高代码复用率,优化代码结构,提高安全性,需要填写宏名称和可用参数列表信息

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

    .....

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

</xacro:macro>

Xacro宏调用类似于函数调用实现,需要填写宏名称和对应参数值

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

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

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

2、 Xacro建模实操

现在我们用xacro宏来优化URDF建模的实操过程,这次我们先建造机器人底盘,摄像头,激光雷达,然后把这几个部件拼起来,首先现在xxx.urdf文件同级目录下新建xxx.urdf.xacro文件,接着编写摄像头和激光雷达的 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  -->

    <!-- 摄像头关节以及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>
    </link>

    <joint name="camera2base_link" type="fixed">
        <parent link="base_link" />
        <child link="camera" />
        <origin xyz="${camera_x} ${camera_y} ${camera_z}" />
    </joint>
</robot>
<!--
    小车底盘添加激光雷达
-->
<robot name="my_laser" xmlns:xacro="http://wiki.ros.org/xacro">

    <!-- 激光雷达支架 -->
    <xacro:property name="support_length" value="0.15" /> <!-- 支架长度 -->
    <xacro:property name="support_radius" value="0.01" /> <!-- 支架半径 -->
    <xacro:property name="support_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  -->

    <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" /> <!-- 激光雷达安装的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  -->

    <!-- 激光雷达关节以及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>
    </link>

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

接着再编写机器人底盘的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>

然后再编写一个my_robot.urdf.xacro文件,把上面的几个机器人部件的xacro文件include一下,,就可以把所以机器人部件拼起来

<!-- 组合小车底盘与摄像头与雷达 -->
<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>

最后在launch文件夹下面新建my_robot.launch文件,该launch文件用于加载机器人模型并启动rviz

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

    <node pkg="rviz" type="rviz" name="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中配置好RobotModel就可以看到机器人模型

roslaunch xxx(功能包) my_robot.launch(launch文件)

在这里插入图片描述

三、Rviz与Gazebo仿真

rviz是ROS中的一个可视化工具,用于显示机器人的状态、传感器数据和运动规划等信息。它可以显示3D模型、点云、激光雷达数据、图像、路径等,可以通过交互界面进行操作,如平移、旋转、缩放等。rviz还可以与其他ROS节点进行通信,例如与机器人控制节点通信,实现机器人运动规划控制。

Gazebo是ROS中的一个强大的模拟器,用于模拟机器人在虚拟环境中的运动和传感器数据。它可以模拟各种类型的机器人,包括移动机器人、人形机器人和无人机等,同时支持多种传感器类型,如摄像头、激光雷达和IMU等。在Gazebo中,用户可以创建一个虚拟环境,包括地形、障碍物和物体等,并将机器人放置在其中。通过控制机器人的运动,用户可以观察机器人在虚拟环境中的行为,并进行算法测试和优化等工作。Gazebo还可以与其他ROS节点进行通信,例如与机器人控制节点通信,实现机器人的运动控制。

1、Gazebo集成URDF建模语法基础

Gazebo仿真环境加载URDF模型文件,要求使用 collision 碰撞标签,因为在仿真环境中必然涉及到碰撞检测,collision 提供碰撞检测的依据;还需要提供使用 inertial 惯性矩阵标签,此标签标注了当前机器人某个刚体部分的惯性矩阵,用于一些力学相关的仿真计算。

碰撞标签collision设置时,如果机器人的连接器是标准的几何体形状,设置与geometry形状属性一致即可

惯性矩阵标签inertial的设置需要结合连接器的质量分布与形状参数动态生成,下面是惯性矩阵的计算公式, J J J是转动惯量, r i r_{i} ri 是质点到转轴的距离
J = ∑ m i r i 2 J = \sum m_{i}r_{i}^{2} J=miri2

<!-- 球体惯性矩阵 -->
<!-- Macro for inertia matrix -->
    <xacro:macro name="sphere_inertial_matrix" params="m r">
        <inertial>
            <mass value="${m}" />
            <inertia ixx="${2*m*r*r/5}" ixy="0" ixz="0"
                iyy="${2*m*r*r/5}" iyz="0" 
                izz="${2*m*r*r/5}" />
        </inertial>
    </xacro:macro>
<!-- 圆柱惯性矩阵 -->
<xacro:macro name="cylinder_inertial_matrix" params="m r h">
        <inertial>
            <mass value="${m}" />
            <inertia ixx="${m*(3*r*r+h*h)/12}" ixy = "0" ixz = "0"
                iyy="${m*(3*r*r+h*h)/12}" iyz = "0"
                izz="${m*r*r/2}" /> 
        </inertial>
    </xacro:macro>
<!-- 立方体惯性矩阵 -->
 <xacro:macro name="Box_inertial_matrix" params="m l w h">
       <inertial>
               <mass value="${m}" />
               <inertia ixx="${m*(h*h + l*l)/12}" ixy = "0" ixz = "0"
                   iyy="${m*(w*w + l*l)/12}" iyz= "0"
                   izz="${m*(w*w + h*h)/12}" />
       </inertial>
   </xacro:macro>

除了 base_footprint 外,机器人的每个刚体部分都需要设置惯性矩阵,惯性矩阵是依据转动定律计算得出,如果随意定义刚体部分的惯性矩阵,那么可能会导致机器人在 Gazebo 中出现抖动,移动等现象,其它地方基本和之前的URDF建模一样

2、Gazebo集成URDF实操

为了在Gazebo里面显示机器人模型,需要在之前xacro宏文件里面加入碰撞标签、惯性矩阵标签、颜色标签,其他操作基本与前面一致,首先编写机器人惯性矩阵算法的 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>

接着编写机器人底盘的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>

接着编写机器人摄像头的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>

接着编写机器人激光雷达的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>

接下来将惯性矩阵算法文件导入,并组合机器人底盘、摄像头和激光雷达

<!-- 组合小车底盘、摄像头与激光雷达 -->
<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" />
</robot>

最后编写好launch文件并打开终端运行launch文件,配置好rviz和gazebo就可以看到机器人模型

<launch>
    <!-- 将 Urdf 文件的内容加载到参数服务器 -->
    <param name="robot_description" command="$(find xacro)/xacro $(find demo02_urdf_gazebo)/urdf/xacro/my_robot.urdf.xacro" />
    <!-- 启动 rviz -->
    <node pkg="rviz" type="rviz" name="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" />
    <!-- 启动 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>

在这里插入图片描述


总结

以上就是ROS机器人建模与仿真学习笔记的内容。通过使用ROS进行机器人建模和仿真,可以更好地理解机器人的行为和性能,并且可以更好地优化机器人的设计。此外,ROS还提供了一系列的仿真工具,如Gazebo和Stage,可以帮助工程师模拟不同环境下的机器人行为,从而更好地理解机器人在不同条件下的表现。

机器人建模和仿真还可以帮助工程师开发和测试机器人的控制算法,以及评估机器人的性能和鲁棒性。此外,通过使用ROS进行机器人建模和仿真,可以更好地理解机器人系统的各个组件之间的交互和通信,从而更好地设计和调试机器人系统的软件架构。

另外,机器人建模和仿真还可以帮助工程师实现快速迭代和开发,因为在虚拟环境中进行测试和验证比在实际机器人上进行测试和验证更加高效和灵活。通过使用ROS进行机器人建模和仿真,可以更快速地识别和解决机器人系统中的问题,从而提高开发效率和机器人的性能和可靠性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android AIDL Callback的使用(配源码)

零、示例说明 本示例&#xff0c;完成的功能是&#xff1a;客户端向服务端注册一个回调&#xff0c;服务端是一个商店shop&#xff0c;当商店里的产品 Product 有变化时&#xff0c;调用回调向通知客户端&#xff0c;什么商品更新了。 一、完整源代码 完整源码链接: https:/…

solr快速上手:配置从mysql同步数据(五)

0. 引言 上一节我们已经配置了新的索引&#xff0c;但是数据还是手动添加的&#xff0c;并没有实现自动从数据库同步&#xff0c;所以这一节&#xff0c;继续来实现从mysql同步数据到solr solr快速上手&#xff1a;solr简介及安装&#xff08;一&#xff09; solr快速上手&a…

[java安全]反射

文章目录 [java安全]反射定义反射的运用1、反射获取类对象1.1、Class.forName()1.2、Object.class1.3、obj.getClass() 2、反射获取成员方法2.1、getMethods()2.2、getDeclaredMethods()2.3、getMethod()2.4、getDeclaredMethod() 3、反射获取构造方法4、反射创建对象4.1、通过…

自动化测试selenium环境搭建

自动化测试工具selenium搭建 1. 自动化和selenium基本概念 1) 什么是自动化?为什么要做自动化&#xff1f; 自动化测试能够代替一部分的手工测试&#xff0c;自动化测试能够提高测试的效率。随着项目功能的增加&#xff0c;版本越来越多&#xff0c;版本的回归测试的压力也…

MySQL架构简介

MySQL是系统架构中最常见的中间件&#xff0c;主要由Server层&#xff08;连接器Connectors、连接池Connection Pool、查询缓存query cache、分析器Parser、优化器Optimizer、执行器、binlog&#xff09;以及存储引擎层组成。 MySQL架构简介 连接器 与客户端建立连接、认证身…

论文笔记:Graph neural networks: A review of methods and applications

1 GNN的设计pipeline 1.1 获取图结构 结构化场景 图结构在应用问题中是已知的 比如分子结构、物理系统非结构化场景 图结构在应用问题中是未知的 需要根据任务人为地建图 1.2 判断图的类型 & 尺寸 图的类型 有向图/无向图//异构图/同构图 图中的点和边类型是不是一样的…

LearnOpenGL-高级OpenGL-8.高级GLSL

本人初学者&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 文章目录 高级GLSLGLSL的内建变量在顶点着色器的内建变量gl_PointSizegl_VertexID 在片段着色器的内建变量gl_FragCoordgl_FrontFacinggl_FragDepth 接口块Uniform缓冲对象Uniform块布局使用Uniform缓冲简…

基于QT的智能家居中控系统的简明设计

文章目录 系统总体说明主板UI设计后续改进与完善 系统总体说明 系统采用 “主从式架构” &#xff0c;即一主多从式&#xff0c;该智能居家控制系统的主要功能包括登录功能、注册功能、音乐播放功能、时间显示、日历显示、温度湿度光照气压海拔数据等环境指标数据显示等。   …

Linux之理解文件系统——文件的管理

文章目录 前言一、磁盘1.磁盘的物理结构2.磁盘的存储结构3.磁盘的逻辑结构 二、文件系统与inode1.文件在磁盘中是如何存储的&#xff1f;2.对文件进行操作 三、软硬链接1.软链接创建软链接&#xff1a;inode删除软链接&#xff1a;软链接的作用&#xff1a; 2.硬链接创建硬链接…

堆(堆排序 模拟堆)

目录 一、堆的数据结构二、堆的操作方法往下调整的示意图往上调整的示意图相关功能的实现思路1.插入一个数2.求最小值3.删除最小值4.删除任意一个元素5.修改任意一个元素 三、堆的实战运用堆排序模拟堆 一、堆的数据结构 堆是一个完全二叉树&#xff1a;除了最后一层结点以外&…

3ds MAX 基本体建模,长方体、圆柱体和球体

3ds MAX基本页面如下&#xff1a; 生成新的几何体在右侧&#xff1a; 选择生成的对象类型即可&#xff0c;以下为例子&#xff1a; 1、长方体建模 选择建立的对象类型为长方形 在 任意一个窗口绘制&#xff0c;鼠标滑动 这里选择左上角的俯视图 松开鼠标后&#xff0c;可以…

第18章 JQuery DataTables初始化渲染显示与排序

1 System.Linq.AsyncIEnumerableExtensions (Data\Extensions\AsyncIEnumerableExtensions.cs) namespace System.Linq { /// <summary> /// 【异步枚举数扩展--类】 /// <remarks> /// 摘要&#xff1a; /// 该类通过对System.Linq.Async中方法的自定义扩展…

C++进阶 —— set

目录 一&#xff0c;set介绍 二&#xff0c;set使用 一&#xff0c;set介绍 set是按照特定次序存储元素的关联式容器&#xff0c;元素不可重复&#xff1b;set中的元素不能在容器中修改(元素总是const)&#xff0c;但是可从容器中插入和删除它们&#xff1b;set中的元素总是按…

【测试报告】个人博客系统自动化测试报告

文章目录 项目背景项目功能测试计划功能测试测试用例执行测试的操作步骤 自动化测试设计的模块、自动化运行的结果、问题定位的结果自动化测试优点 项目背景 对于一个程序员来说&#xff0c;定期整理总结并写博客是不可或缺的步骤&#xff0c;不管是对近期新掌握的技术或者是遇…

代码随想录算法训练营第五十三天 | 力扣 1143.最长公共子序列, 1035.不相交的线, 53. 最大子序和

1143.最长公共子序列 题目 1143. 最长公共子序列 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符…

SpringBoot——原理(自动配置+原理分析-源码跟踪)

源码跟踪 从Springboot的启动类进入&#xff0c;进行分析. 源码跟踪技巧 在以后接触各种框架的时候&#xff0c;如果需要查看源码&#xff0c;需要找到关键点和核心流程&#xff0c;先在宏观对整个原理和流程有一个认识&#xff0c;之后再去了解其中的细节。 按住Ctrl左键进…

怎么实现常用网络接口自动化测试框架应用?

一、RESTful&#xff08;resource representational state transfer)类型接口测试 (一&#xff09;GUI界面测试工具&#xff1a;jmeter 1、添加线程组 2、添加http请求 3、为线程组添加察看结果树 4、写入接口参数并运行 5、在查看结果树窗口查看结果 6、多组数据可增加CSVDat…

基于物理信息的神经网络(Physics-informed Neural Networks;PINNs)Part-1(简单介绍)

【摘要】 基于物理信息的神经网络&#xff08;Physics-informed Neural Networks&#xff0c;简称PINNs&#xff09;&#xff0c;是一类用于解决有监督学习任务的神经网络&#xff0c;它不仅能够像传统神经网络一样学习到训练数据样本的分布规律&#xff0c;而且能够学习到数学…

UFS 2 -UFS架构简介2

UFS 2 -UFS架构简介2 1 UFS架构简介1.1 System Boot and Enumeration1.2 UFS Interconnect (UIC) Layer1.2.1 UFS Physical Layer Signals1.2.2 MIPI UniPro1.2.3 MIPI UniPro Related Attributes 1.3 UFS Transport Protocol (UTP) Layer1.3.1 Architectural Model1.3.1.1 Cli…

图解max{X,Y}和min{X,Y}并求相关概率

图解max{X,Y}和min{X,Y}并求相关概率 对max{X,Y}或min{X,Y}进行分解再求解 P ( m a x { X , Y } ≥ c ) P [ ( X ≥ c ) ∪ ( Y ≥ c ) ] P ( m a x { X , Y } ≤ c ) P [ ( X ≤ c ) ∩ ( Y ≤ c ) ] P ( m i n { X , Y } ≥ c ) P [ ( X ≥ c ) ∩ ( Y ≥ c ) ] P ( m i…