[ROS 系列学习教程] 建模与仿真 - URDF 建模实践

admin2024-05-15  0

[ROS 系列学习教程] 建模与仿真 - URDF 建模实践,在这里插入图片描述,第1张

ROS 系列学习教程(总目录)

本文目录

  • 一、机器人结构组成
  • 二、新建功能包
  • 三、编写launch文件
  • 四、创建底盘
  • 五、添加轮子
  • 六、添加其他部件
  • 七、解决部分实体位于地面以下的问题

前文介绍了URDF建模与URDF语法,接下来介绍怎么使用URDF从零构建一个机器人模型并在rviz中显示。

一、机器人结构组成

最终效果如下图:

[ROS 系列学习教程] 建模与仿真 - URDF 建模实践,在这里插入图片描述,第2张

机器人由如下部分组成:

  • 底盘 * 1
  • 主动轮 * 2
  • 从动轮(脚轮)* 2
  • 激光雷达 * 1
  • RGB相机 * 1

二、新建功能包

为面向零基础的同学,使教学清晰,新建一个功能包用于学习该章节,新建功能包方法见前文,功能包结构如下:

[ROS 系列学习教程] 建模与仿真 - URDF 建模实践,在这里插入图片描述,第3张

其中,

  • config :存放rviz配置文件
  • launch :存放launch文件
  • meshes :存放模型渲染文件
  • models :存放模型文件
  • src与include :存放源文件和头文件

关于ROS工作空间与功能包的创建,详见 ROS Hello World

三、编写launch文件

如前文所述,rviz显示urdf模型需要先把模型参数注册到参数服务器,然后打开rviz,在rviz中配置好后才能正常显示模型。这些步骤可以手动一步一步完成,也可以编写launch文件快速执行。

另外,对于包含多个link的模型,需要发布link间的jointtf关系,以使rviz可以确定link间的空间位置。ROS提供了 joint_state_publisherrobot_state_publisher 两个功能包来实现linkjointtf关系的发布,如没有安装这两个功能包,可以使用如下命令安装(以noetic为例):

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

launch文件内容如下:

<launch>
    <param name="robot_description" textfile="$(find simulation_learning)/models/urdf/mbot_base.urdf" />

    <!-- 设置GUI参数,显示关节控制插件 -->
    <param name="use_gui" value="true" />

    <!-- 运行joint_state_publisher节点,发布机器人的关节状态  -->
    <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />

    <!-- 运行robot_state_publisher节点,发布tf  -->
    <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />

    <!-- 运行rviz可视化界面,并加载配置 -->
    <node name="rviz" pkg="rviz" type="rviz" args="-d $(find simulation_learning)/config/mbot_urdf.rviz" required="true" />
</launch>

关于launch文件的具体描述,见[4.1 launch文件](#4.1 launch文件)

四、创建底盘

models/urdf中创建mbot_base.urdf文件,用于编写urdf模型。

底盘是一个圆柱体,半径为 0.2m,高为0.16m,urdf代码如下:

<?xml version="1.0"?>
<robot name="mbot">
    <link name="base_link">
        <visual>
            <origin xyz=" 0 0 0" rpy="0 0 0" />
            <geometry>
                <cylinder length="0.16" radius="0.20" />
            </geometry>
            <material name="yellow">
                <color rgba="1 0.4 0 1" />
            </material>
        </visual>
    </link>
</robot>

运行 launch 文件,结果如下:

[ROS 系列学习教程] 建模与仿真 - URDF 建模实践,在这里插入图片描述,第4张

这里注意base_link的原点位于圆柱体的几何中心,即有一半圆柱体是位于地面以下的,这一点到最后会解决,目前先把机器人模型搭建起来。

五、添加轮子

轮子是小一点的圆柱体,半径为 0.06m,高为0.025m

现在有了两个实体,底盘和一个轮子,需要使用joint说明他们之间的几何与运动关系,否则rviz解析urdf时会报错。

urdf代码如下:

<!-- 底盘实体描述 -->
<link name="base_link">
    <visual>
        <origin xyz=" 0 0 0" rpy="0 0 0" />
        <geometry>
            <cylinder length="0.16" radius="0.20" />
        </geometry>
        <material name="yellow">
            <color rgba="1 0.4 0 1" />
        </material>
    </visual>
</link>

<!-- 左轮与底盘的关节描述 -->
<joint name="left_wheel_joint" type="continuous">
    <origin xyz="0 0.19 -0.05" rpy="0 0 0" />
    <parent link="base_link" />
    <child link="left_wheel_link" />
    <axis xyz="0 1 0" />
</joint>

<!-- 左轮实体描述 -->
<link name="left_wheel_link">
    <visual>
        <origin xyz="0 0 0" rpy="1.5707 0 0" />
        <geometry>
            <cylinder radius="0.06" length="0.025" />
        </geometry>
        <material name="white">
            <color rgba="1 1 1 0.9" />
        </material>
    </visual>
</link>

其中,joint中的type描述了关节类型(机械中的运动副),该类型为旋转类型(机械中的旋转副),origin表示左轮原点相对于底盘原点的空间位姿偏移,parentchild分别表示该关节的父实体和子实体,由于该关节为旋转关节,使用axis定义旋转轴。关于joint的具体描述见 建模与仿真 - URDF 语法介绍。

运行 launch 文件,结果如下:

[ROS 系列学习教程] 建模与仿真 - URDF 建模实践,在这里插入图片描述,第5张

六、添加其他部件

其他部件同理,添加实体与相应的关节描述。

完整的urdf代码如下:

<?xml version="1.0"?>
<robot name="mbot">

    <!-- 底盘实体描述 -->
    <link name="base_link">
        <visual>
            <origin xyz=" 0 0 0" rpy="0 0 0" />
            <geometry>
                <cylinder length="0.16" radius="0.20" />
            </geometry>
            <material name="yellow">
                <color rgba="1 0.4 0 1" />
            </material>
        </visual>
    </link>

    <!-- 左轮与底盘的关节描述 -->
    <joint name="left_wheel_joint" type="continuous">
        <origin xyz="0 0.19 -0.05" rpy="0 0 0" />
        <parent link="base_link" />
        <child link="left_wheel_link" />
        <axis xyz="0 1 0" />
    </joint>

    <!-- 左轮实体描述 -->
    <link name="left_wheel_link">
        <visual>
            <origin xyz="0 0 0" rpy="1.5707 0 0" />
            <geometry>
                <cylinder radius="0.06" length="0.025" />
            </geometry>
            <material name="white">
                <color rgba="1 1 1 0.9" />
            </material>
        </visual>
    </link>

    <!-- 右轮与底盘的关节描述 -->
    <joint name="right_wheel_joint" type="continuous">
        <origin xyz="0 -0.19 -0.05" rpy="0 0 0" />
        <parent link="base_link" />
        <child link="right_wheel_link" />
        <axis xyz="0 1 0" />
    </joint>

    <!-- 右轮实体描述 -->
    <link name="right_wheel_link">
        <visual>
            <origin xyz="0 0 0" rpy="1.5707 0 0" />
            <geometry>
                <cylinder radius="0.06" length="0.025" />
            </geometry>
            <material name="white">
                <color rgba="1 1 1 0.9" />
            </material>
        </visual>
    </link>

    <!-- 前脚轮实体描述 -->
    <joint name="front_caster_joint" type="continuous">
        <origin xyz="0.18 0 -0.095" rpy="0 0 0" />
        <parent link="base_link" />
        <child link="front_caster_link" />
        <axis xyz="0 1 0" />
    </joint>

    <!-- 前脚轮和底盘的关节描述 -->
    <link name="front_caster_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <geometry>
                <sphere radius="0.015" />
            </geometry>
            <material name="black">
                <color rgba="0 0 0 0.95" />
            </material>
        </visual>
    </link>

    <!-- 后脚轮实体描述 -->
    <joint name="back_caster_joint" type="continuous">
        <origin xyz="-0.18 0 -0.095" rpy="0 0 0" />
        <parent link="base_link" />
        <child link="back_caster_link" />
        <axis xyz="0 1 0" />
    </joint>

    <!-- 后脚轮和底盘的关节描述 -->
    <link name="back_caster_link">
        <visual>
            <origin xyz="0 0 0" rpy="0 0 0" />
            <geometry>
                <sphere radius="0.015" />
            </geometry>
            <material name="black">
                <color rgba="0 0 0 0.95" />
            </material>
        </visual>
    </link>

    <!-- 激光雷达实体描述 -->
    <link name="laser_link">
        <visual>
            <origin xyz=" 0 0 0 " rpy="0 0 0" />
            <geometry>
                <cylinder length="0.05" radius="0.05" />
            </geometry>
            <material name="gray">
                <color rgba="0.25 0.25 0.25 0.95" />
            </material>
        </visual>
    </link>

    <!-- 激光雷达和底盘的关节描述 -->
    <joint name="laser_joint" type="fixed">
        <origin xyz="0 0 0.105" rpy="0 0 0" />
        <parent link="base_link" />
        <child link="laser_link" />
    </joint>

    <!-- 相机实体描述 -->
    <link name="camera_link">
        <visual>
            <origin xyz=" 0 0 0 " rpy="0 1.57 0" />
            <geometry>
                <cylinder radius="0.02" length = "0.05"/>
            </geometry>
            <material name="gray">
                <color rgba="0.25 0.25 0.25 0.95"/>
            </material>
        </visual>
    </link>

    <!-- 相机和底盘的关节描述 -->
    <joint name="camera_joint" type="fixed">
        <origin xyz="0.18 0 0.055" rpy="0 0 0"/>
        <parent link="base_link"/>
        <child link="camera_link"/>
    </joint>

</robot>

运行 launch 文件,结果如下:

[ROS 系列学习教程] 建模与仿真 - URDF 建模实践,在这里插入图片描述,第6张

七、解决部分实体位于地面以下的问题

首先明确我们的 Fixed Framebase_linkFixed Frame 可以理解为世界坐标系,对于我们的设置就是base_link即当前的世界,rviz默认一切都是从世界中心诞生。

实体位于地面以下,是由于我们设置的其他实体都是以世界中心为参考而又认为地面在轮子下方,但rviz认为地面原点在世界中心,所以看起来和我们的认知有些冲突。

解决办法有多种,但基本都是改变base_link或其他实体与世界中心的关系。

方法一:

比较常见的一种:新增floor_link作为 Fixed Frame 世界坐标系,base_link作为他的子级。这种方法对现有已经完成的模型修改最少。

在urdf文件中新增如下内容即可:

<!-- 地面实体描述 -->
<link name="floor_link">
    <visual>
        <origin xyz="0 0 0" rpy="0 0 0" />
        <geometry>
            <!-- 圆柱体高度尽量小,已达到可忽略的精度 -->
            <cylinder length="0.000001" radius="0.20" />
        </geometry>
        <material name="floor">
            <color rgba="1 0.4 0 0" />
        </material>
    </visual>
</link>

<!-- 底盘与地面的关节关系描述 -->
<joint name="base_joint" type="continuous">
    <origin xyz="0 0 0.11" rpy="0 0 0" />
    <parent link="floor_link" />
    <child link="base_link" />
    <axis xyz="0 1 0" />
</joint>

结果如下:

[ROS 系列学习教程] 建模与仿真 - URDF 建模实践,在这里插入图片描述,第7张

使用rviz查看TF关系如下:

[ROS 系列学习教程] 建模与仿真 - URDF 建模实践,在这里插入图片描述,第8张

新增的floor_link如图中框选,但这种方法在工程上很难测量base_link的实际位置,所以就有了方法二。

方法二:

floor_link直接命名为base_link,其他实体都以它为基准,但位置描述都要作相应的修改,这种方法对于现有已经完成的模型修改较多,对新工程比较友好,各实体的实际位置也很容易通过测量得到。

修改后的TF树如下,此时base_link位于世界原点,也是机器人底盘原点在地面的投影点。

[ROS 系列学习教程] 建模与仿真 - URDF 建模实践,在这里插入图片描述,第9张

机器人的外观显示和方法一一样:

[ROS 系列学习教程] 建模与仿真 - URDF 建模实践,在这里插入图片描述,第10张

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!