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

news2024/11/26 14:31:28

文章目录

  • 前言
  • 一、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进行机器人建模和仿真,可以更快速地识别和解决机器人系统中的问题,从而提高开发效率和机器人的性能和可靠性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring(四)基于xml的自动装配

自动装配&#xff1a;根据指定的策略&#xff0c;在IOC容器中匹配某一个bean,自动为指定的bean中所依赖的类类型或接口类型属性赋值。 首先我们来熟悉三层架构的创建过程&#xff1a; 三层架构为controller层&#xff0c;service层&#xff0c;dao层。 在service层里面创建ser…

ShareX_一款好用的截图工具安装- Window

择心】向大家介绍and安装ShareX ShareX 免费、开源、轻量多区域截图无缝处理截图屏幕录制、文件共享各种实用工具&#xff08;如拾色器&#xff0c;屏幕拾色器&#xff0c;尺子&#xff0c;图像编辑器&#xff0c;图像合并&#xff0c;图像分割器&#xff0c;生成图像缩略图&am…

mysql学+练

从开始到放弃&#xff01; 开始 mysql -uroot -p123456退出命令 exit 或者 quit注释 # show databases; 单行注释 -- show databases; 单行注释 /* 多行注释 show databases; */DDL操作数据库 创建 /* 方式1 直接指定数据库名进行创建 */ CREATE DATABASE db1; /* 方式2 …

TerminalWorks TSPrint/TSScan/TSWebCam Crack

/ 远程桌面打印软件&#xff0c;TerminalWorks TSPrint Server/Client 从远程服务器打印到本地打印机的 简单方法 TSPrint 为您提供了一个简单的远程桌面打印软件&#xff0c;以及使 Windows 终端服务操作更容易的附加工具。有选择地启用或禁用功能&#xff0c;以便您可以完全…

Unity刚体

1、Dynamic&#xff1a;动态类型 受重力和力的影响移动和旋转 Material&#xff1a; 物理材质&#xff0c;在刚体上设置了物理材质&#xff0c;如果子物体有碰撞器但是没有设置材质则会通用刚体的物理材质 如果不设置&#xff0c;将使用在Physics 2D窗口中设置的默认材质(Physi…

python day1 函数

文章目录 前言一、python函数二、定义函数三、函数返回值四、实例五、变量作用域六、参数扩展1、默认值参数2、顺序参数&#xff0c;关键词参数3、可变参数4、可变关键词参数5、解包操作 七、函数类型的参数八、高阶函数九、匿名函数十、递归 前言 看深度学习的代码时&#xff…

SO21434 持续进行的网络安全(五)

目录 一、概要 二、目标 三、网络安全监控 3.1 输入 3.1.1 先决条件 3.1.2 进一步支持信息 3.2 要求和建议 3.3 输出 四、网络安全事件评估 4.1 输入 4.1.1 先决条件 4.1.2 进一步支持信息 4.2 要求和建议 4.3 输出 五、漏洞分析 5.1 输入 5.1.1 先决条件 5.…

Sentinel如何使用滑动窗口进行限流和降级,请看这篇文章分享

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生&#xff0c;在一家满意的公司实习。本篇文章将详细介绍如何Sentinel如何使用滑动窗口进行限流和降级&#xff0c;后续文章将详细介绍其他知识。 如果文章有什么需要改进的地方还请大佬不吝赐教&#x1f44f;…

环境感知算法——3.PSMNet基于Kitti数据集训练

1. 前言 PSMNet的核心思想是通过金字塔结构来捕捉不同尺度的特征信息&#xff0c;从而提高视差估计的精度。其亮点在于&#xff1a;&#xff08;1&#xff09;使用了金字塔形的卷积神经&#xff08;SPP module&#xff09;网络来提取不同尺度的特征信息&#xff1b;&#xff0…

【UR机械臂ros通讯前的示教器网络配置】

1. 前言 欢迎大家阅读2345VOR的博客【D435i深度相机YOLO V5结合实现目标检测】&#x1f973;&#x1f973;&#x1f973;2345VOR鹏鹏主页&#xff1a; 已获得CSDN《嵌入式领域优质创作者》称号&#x1f47b;&#x1f47b;&#x1f47b;&#xff0c;座右铭&#xff1a;脚踏实地&…

《新程序员005:开源深度指南新金融背后的科技力量》

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰来写书评啦&#xff0c;尽管再忙&#xff0c;也不能不读书&#xff0c;下面&#xff0c;就让小雅兰来带你们走进《新程序员005&#xff1a;开源深度指南&新金融背后的科技力量》这本书的世界吧&#xff01;&#…

安科瑞医用隔离电源系统在浙江某医院项目中的应用

【摘要】介绍该三级乙等综合医院采用安科瑞医用隔离电源系统&#xff0c;使用分体配电柜安装方式&#xff0c;从而实现将TN系统转化为IT系统&#xff0c;以及系统绝缘情况监测。 【关键词】医用隔离电源系统&#xff1b;IT系统&#xff1b;绝缘情况监测&#xff1b;三级乙等综合…

华为OD机试真题 Java 实现【最差产品奖】【2023Q1 200分】

一、题目描述 A公司准备对他下面的N个产品评选最差奖,评选的方式是首先对每个产品进行评分,然后根据评分区间计算相邻几个产品中最差的产品。评选的标准是依次找到从当前产品开始前M个产品中最差的产品,请给出最差产品的评分序列。 二、输入描述 第一行,数字M,表示评分…

chatgpt赋能python:用Python编写软件能够带来哪些SEO优势?

用 Python 编写软件能够带来哪些 SEO 优势&#xff1f; Python 是一种高级编程语言&#xff0c;它的简洁性和易学性让 Python 成为现今最受欢迎的编程语言之一&#xff0c;适用于各种类型的编程任务&#xff0c;并且可以轻松地生成各种种类的软件。在构建网站和应用程序时&…

黑马Redis视频教程实战篇(四)

目录 一、秒杀优化 1.1、秒杀优化-异步秒杀思路 1.2、秒杀优化-Redis完成秒杀资格判断 1.3、秒杀优化-基于阻塞队列实现秒杀优化 二、Redis消息队列 2.1、认识消息队列 2.2、基于List实现消息队列 2.3、基于PubSub的消息队列 2.4、基于Stream的消息队列 2.5、基于Str…

【C++初阶】C++STL详解(一)—— string类

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;C初阶 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 CSTL详解&#xff08;一…

6.3 SpringBoot日志进阶实战 Logback配置详解

文章目录 前言一、Logback入门级配置二、动态指定属性三、动态指定日志级别四、指定配置文件五、滚动记录RollingFIleAppender六、异步记录AsyncAppender总结最后 前言 在上一篇文章中&#xff0c;我和你介绍了SpringBoot快速入门Slf4j Logback实战&#xff0c;遗留的问题是如…

数据中心末端配电的数字化方案及设备选型

普通PDU和智能PDU有什么区别&#xff1f; 机架安装配电盘或机架配电单元 (PDU) 是一种配备许多插座的设备&#xff0c;可将电力分配给位于数据中心机架或机柜内的服务器、存储设备和网络设备。领先的分析公司 IHS 将它们分为两大类&#xff1a; 1) 基本 PDU 提供可靠的配电。 2…

【2023 · CANN训练营第一季】TIK C++算子开发入门 第一章——TIK C++算子开发入门

1.TIK C介绍 TIK C是一种使用C/C作为前端语言的算子开发工具&#xff0c;通过四层接口抽象、并行编程范式、孪生调试等技术&#xff0c;极大提高算子开发效率&#xff0c;助力AI开发者低成本完成算子开发和模型调优部署 使用TIK C开发自定义算子的优势&#xff1a; (1)C/C原语…

如何编写代码审查文档

一、前言 代码审查(Code Review)是开发流程中非常重要的一个环节&#xff0c;可以帮助发现并改正代码中的错误&#xff0c;提高代码质量&#xff0c;也是共享知识、熟悉代码的好机会。 最近功能开发完毕需要做代码审查&#xff0c;发现国内很多公司不强制要求编写代码审查文档…