【URDF】1.从头开始使用 URDF 构建视觉机器人模型

安装 urdf_tutorial

首先我们需要安装 urdf_tutorial 这个教程包

vim catkin_ws/src & cd catkin_ws/src
git clone https://github.com/ros/urdf_tutorial.git urdf_tutorial
cd ..
catkin_make

根据教程操作,在第2步我们可以得到所有我们需要的文件

(base) zwhy2022@Zwhy:~/work/catkin_ws/src/urdf_tutorial$ ls
CHANGELOG.rst  CMakeLists.txt  images  launch  meshes  package.xml  README.md  rviz  urdf

但是为什么需要catkin_make呢?其实是需要配置环境变量,笔者现在也不是很了解ros这个中间件到底做了那些事情,因为很多很多,暂时只能做一点补一点.

在我们catkin_make之后执行下面这条指令后,本次终端就能识别到你的ros工作空间了.

source devel/setup.bash

使用ros自带的 urdf_tutorial

zwhy2022@Zwhy:~$ echo $(rospack find urdf_tutorial)
/opt/ros/kinetic/share/urdf_tutorial

这就是为什么之前我说,鱼香ros的一件安装像黑盒,我也不知道ros中就自带了这个pkg(像是小海归一样)

roslaunch urdf_tutorial display.launch model:='$(find urdf_tutorial)/urdf/01-myfirst.urdf'

因为我在终端的启动脚本中source过ros 环境所以其实我的ros 是能识别到urdf_tutorial这个pkg的,但是由于自带的这个urdf_tutorial是没有默认model的,所以你需要手动导入urdf模型文件的路径.你当然可以使用全局变量,但是我们可以使用ros给我提供的工具.

一种形状

下面的代码片段中,我们可以看到第一行是我没有按回车键,而是按下tab补全之后,出来的参数列表.这几个刚好对应了 display.launch文件中三个arg name! 太神奇啦!这也是ros帮我们做的事情,随后执行这句指令.

(base) zwhy2022@Zwhy:~/work/catkin_ws$ roslaunch urdf_tutorial display.launch
gui         model       rvizconfig
(base) zwhy2022@Zwhy:~/work/catkin_ws$ roslaunch urdf_tutorial display.launch

这样你的终端将会唤醒,rviz然后给展现一个圆柱体.是不是很神奇?

image

这是因为 display.launch这个launch文件会有一个默认参数,就如下面的代码片段一般.

(base) zwhy2022@Zwhy:~/work/catkin_ws$ cat src/urdf_tutorial/launch/display.launch
<launch>
  <arg name="model" default="$(find urdf_tutorial)/urdf/01-myfirst.urdf"/>
  <arg name="gui" default="true" />
  <arg name="rvizconfig" default="$(find urdf_tutorial)/rviz/urdf.rviz" />

  <param name="robot_description" command="$(find xacro)/xacro $(arg model)" />

  <node if="$(arg gui)" name="joint_state_publisher" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" />
  <node unless="$(arg gui)" name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
  <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
  <node name="rviz" pkg="rviz" type="rviz" args="-d $(arg rvizconfig)" required="true" />

</launch>

display.launch 做了三件事。

  1. 将指定模型加载到参数服务器中

  2. 运行节点来发布sensor_msgs/JointState并进行转换(稍后将详细介绍)

  3. 使用配置文件启动 Rviz

多种形状

  roslaunch urdf_tutorial display.launch model:=urdf/02-multipleshapes.urdf

好的代码本身就是注释是这么用的,但是并不是说没有注释的代码就是好代码,下面结构很清晰了.

zwhy2022@Zwhy:/opt/ros/kinetic/share/urdf_tutorial$ cat urdf/02-multipleshapes.urdf
<?xml version="1.0"?>
<robot name="multipleshapes">
  <link name="base_link">
    <visual>
      <geometry>
        <cylinder length="0.6" radius="0.2"/>
      </geometry>
    </visual>
  </link>

  <link name="right_leg">
    <visual>
      <geometry>
        <box size="0.6 0.1 0.2"/>
      </geometry>
    </visual>
  </link>

  <joint name="base_to_right_leg" type="fixed">
    <parent link="base_link"/>
    <child link="right_leg"/>
  </joint>

</robot>

你可以发现我们主要是有两种概念,关节和形状(连接).上述我们就通过一个关节吧两个形状连接到一起,然后其实有parent,child的区分.其实这里涉及到 标准DH(SDH)和改进DH(MDH)的概念,笔者放到文末,可以自行学习.

origin

原谅我真的不知道怎么做翻译…

在多种形状的udrf中,我们只是静态的导入形状,现在我们要做一点点变换.

roslaunch urdf_tutorial display.launch model:=urdf/03-origins.urdf

我们可以看到相较之前,我们多了

zwhy2022@Zwhy:~/work/catkin_ws/src/urdf_tutorial$ cat urdf/03-origins.urdf
<?xml version="1.0"?>
<robot name="origins">
  <link name="base_link">
    <visual>
      <geometry>
        <cylinder length="0.6" radius="0.2"/>
      </geometry>
    </visual>
  </link>

  <link name="right_leg">
    <visual>
      <geometry>
        <box size="0.6 0.1 0.2"/>
      </geometry>
      <origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
    </visual>
  </link>

  <joint name="base_to_right_leg" type="fixed">
    <parent link="base_link"/>
    <child link="right_leg"/>
    <origin xyz="0 -0.22 0.25"/>
  </joint>

</robot>

在URDF (Unified Robot Description Format) 中,origin 元素用于定义一个局部坐标系相对于其父坐标系的位置和方向。origin 元素通常在定义连接件 (joint) 和视觉/碰撞几何 (visual/collision) 时使用。

origin 元素可以包含以下两个属性:

  1. xyz: 表示平移,它定义了相对于父坐标系的位置。这是一个由三个浮点数组成的向量,表示在x、y、z方向上的平移距离。

  2. rpy: 表示旋转,它定义了固定角Roll-Pitch-Yaw旋转。这是一个由三个浮点数组成的向量,分别表示绕x、y、z轴的旋转角度。

这里表示right_leg相对于base_link 绕着y轴旋转90°(弧度制),并且在z的负方向平移了-0.3个单位,看上去单位表示的是m.当然urdf_tutorial中,的所有代码你都可以随意修改看看效果,这样反馈很大.

注意: 坐标系的颜色 红-x 绿-y 蓝-z

同样对于关节的变换也是如此,我们可以相互对于父坐标系,做一些平移或者旋转,得到子坐标系.子子孙孙,子承父业,这也是合情合理.所以我们向z平移0.25以及向y平移-0.22后得到了子坐标系的原点.

材质

roslaunch urdf_tutorial display.launch model:=urdf/04-materials.urdf

继续循序渐进,我们只是一葫芦画瓢建立了另一条腿,然后我们给腿和身体上色.

zwhy2022@Zwhy:~/work/catkin_ws/src/urdf_tutorial$ cat urdf/04-materials.urdf
<?xml version="1.0"?>
<robot name="materials">

  <material name="blue">
    <color rgba="0 0 0.8 1"/>
  </material>

  <material name="white">
    <color rgba="1 1 1 1"/>
  </material>


  <link name="base_link">
    <visual>
      <geometry>
        <cylinder length="0.6" radius="0.2"/>
      </geometry>
      <material name="blue"/>
    </visual>
  </link>

  <link name="right_leg">
    <visual>
      <geometry>
        <box size="0.6 0.1 0.2"/>
      </geometry>
      <origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
      <material name="white"/>
    </visual>
  </link>

  <joint name="base_to_right_leg" type="fixed">
    <parent link="base_link"/>
    <child link="right_leg"/>
    <origin xyz="0 -0.22 0.25"/>
  </joint>

  <link name="left_leg">
    <visual>
      <geometry>
        <box size="0.6 0.1 0.2"/>
      </geometry>
      <origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
      <material name="white"/>
    </visual>
  </link>

  <joint name="base_to_left_leg" type="fixed">
    <parent link="base_link"/>
    <child link="left_leg"/>
    <origin xyz="0 0.22 0.25"/>
  </joint>

</robot>

其中红色、绿色、蓝色和 alpha 通道分别定义为 0、0、0.8 和 1。所有值都可以在 [0,1] 范围内.然后红绿蓝是我们常见的rgb,但是归一化到了[0,1]而已,然后alpha表示透明度.0表示完全透明,1表示完全不透明.

完成模型

roslaunch urdf_tutorial display.launch model:=urdf/05-visual.urdf

zwhy2022@Zwhy:~/work/catkin_ws/src/urdf_tutorial$ cat urdf/05-visual.urdf
<?xml version="1.0"?>
<robot name="visual">

<material name="blue">
    <color rgba="0 0 0.8 1"/>
  </material>
  <material name="black">
    <color rgba="0 0 0 1"/>
  </material>
  <material name="white">
    <color rgba="1 1 1 1"/>
  </material>

  <link name="base_link">
    <visual>
      <geometry>
        <cylinder length="0.6" radius="0.2"/>
      </geometry>
      <material name="blue"/>
    </visual>
  </link>

  <link name="right_leg">
    <visual>
      <geometry>
        <box size="0.6 0.1 0.2"/>
      </geometry>
      <origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
      <material name="white"/>
    </visual>
  </link>

  <joint name="base_to_right_leg" type="fixed">
    <parent link="base_link"/>
    <child link="right_leg"/>
    <origin xyz="0 -0.22 0.25"/>
  </joint>

  <link name="right_base">
    <visual>
      <geometry>
        <box size="0.4 0.1 0.1"/>
      </geometry>
      <material name="white"/>
    </visual>
  </link>

  <joint name="right_base_joint" type="fixed">
    <parent link="right_leg"/>
    <child link="right_base"/>
    <origin xyz="0 0 -0.6"/>
  </joint>

  <link name="right_front_wheel">
    <visual>
      <origin rpy="1.57075 0 0" xyz="0 0 0"/>
      <geometry>
        <cylinder length="0.1" radius="0.035"/>
      </geometry>
      <material name="black"/>
    </visual>
  </link>
  <joint name="right_front_wheel_joint" type="fixed">
    <parent link="right_base"/>
    <child link="right_front_wheel"/>
    <origin rpy="0 0 0" xyz="0.133333333333 0 -0.085"/>
  </joint>

  <link name="right_back_wheel">
    <visual>
      <origin rpy="1.57075 0 0" xyz="0 0 0"/>
      <geometry>
        <cylinder length="0.1" radius="0.035"/>
      </geometry>
      <material name="black"/>
    </visual>
  </link>
  <joint name="right_back_wheel_joint" type="fixed">
    <parent link="right_base"/>
    <child link="right_back_wheel"/>
    <origin rpy="0 0 0" xyz="-0.133333333333 0 -0.085"/>
  </joint>

  <link name="left_leg">
    <visual>
      <geometry>
        <box size="0.6 0.1 0.2"/>
      </geometry>
      <origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
      <material name="white"/>
    </visual>
  </link>

  <joint name="base_to_left_leg" type="fixed">
    <parent link="base_link"/>
    <child link="left_leg"/>
    <origin xyz="0 0.22 0.25"/>
  </joint>

  <link name="left_base">
    <visual>
      <geometry>
        <box size="0.4 0.1 0.1"/>
      </geometry>
      <material name="white"/>
    </visual>
  </link>

  <joint name="left_base_joint" type="fixed">
    <parent link="left_leg"/>
    <child link="left_base"/>
    <origin xyz="0 0 -0.6"/>
  </joint>

  <link name="left_front_wheel">
    <visual>
      <origin rpy="1.57075 0 0" xyz="0 0 0"/>
      <geometry>
        <cylinder length="0.1" radius="0.035"/>
      </geometry>
      <material name="black"/>
    </visual>
  </link>
  <joint name="left_front_wheel_joint" type="fixed">
    <parent link="left_base"/>
    <child link="left_front_wheel"/>
    <origin rpy="0 0 0" xyz="0.133333333333 0 -0.085"/>
  </joint>

  <link name="left_back_wheel">
    <visual>
      <origin rpy="1.57075 0 0" xyz="0 0 0"/>
      <geometry>
        <cylinder length="0.1" radius="0.035"/>
      </geometry>
      <material name="black"/>
    </visual>
  </link>
  <joint name="left_back_wheel_joint" type="fixed">
    <parent link="left_base"/>
    <child link="left_back_wheel"/>
    <origin rpy="0 0 0" xyz="-0.133333333333 0 -0.085"/>
  </joint>

  <joint name="gripper_extension" type="fixed">
    <parent link="base_link"/>
    <child link="gripper_pole"/>
    <origin rpy="0 0 0" xyz="0.19 0 0.2"/>
  </joint>

  <link name="gripper_pole">
    <visual>
      <geometry>
        <cylinder length="0.2" radius="0.01"/>
      </geometry>
      <origin rpy="0 1.57075 0 " xyz="0.1 0 0"/>
    </visual>
  </link>

  <joint name="left_gripper_joint" type="fixed">
    <origin rpy="0 0 0" xyz="0.2 0.01 0"/>
    <parent link="gripper_pole"/>
    <child link="left_gripper"/>
  </joint>

  <link name="left_gripper">
    <visual>
      <origin rpy="0.0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://urdf_tutorial/meshes/l_finger.dae"/>
      </geometry>
    </visual>
  </link>

  <joint name="left_tip_joint" type="fixed">
    <parent link="left_gripper"/>
    <child link="left_tip"/>
  </joint>

  <link name="left_tip">
    <visual>
      <origin rpy="0.0 0 0" xyz="0.09137 0.00495 0"/>
      <geometry>
        <mesh filename="package://urdf_tutorial/meshes/l_finger_tip.dae"/>
      </geometry>
    </visual>
  </link>
  <joint name="right_gripper_joint" type="fixed">
    <origin rpy="0 0 0" xyz="0.2 -0.01 0"/>
    <parent link="gripper_pole"/>
    <child link="right_gripper"/>
  </joint>

  <link name="right_gripper">
    <visual>
      <origin rpy="-3.1415 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="package://urdf_tutorial/meshes/l_finger.dae"/>
      </geometry>
    </visual>
  </link>

  <joint name="right_tip_joint" type="fixed">
    <parent link="right_gripper"/>
    <child link="right_tip"/>
  </joint>

  <link name="right_tip">
    <visual>
      <origin rpy="-3.1415 0 0" xyz="0.09137 0.00495 0"/>
      <geometry>
        <mesh filename="package://urdf_tutorial/meshes/l_finger_tip.dae"/>
      </geometry>
    </visual>
  </link>

  <link name="head">
    <visual>
      <geometry>
        <sphere radius="0.2"/>
      </geometry>
      <material name="white"/>
    </visual>
  </link>
  <joint name="head_swivel" type="fixed">
    <parent link="base_link"/>
    <child link="head"/>
    <origin xyz="0 0 0.3"/>
  </joint>

  <link name="box">
    <visual>
      <geometry>
        <box size="0.08 0.08 0.08"/>
      </geometry>
      <material name="blue"/>
    </visual>
  </link>

  <joint name="tobox" type="fixed">
    <parent link="head"/>
    <child link="box"/>
    <origin xyz="0.1814 0 0.1414"/>
  </joint>
</robot>

这里添加了机器人的更多细节,轮子啊,手柄等.最重要的是可以到导入STL,dae 等网格文件.这样会极大的方便我们模型的精细度以及制作的便捷性.

题外话

你可能还是需要一些关于旋转矩阵,坐标系的一些相关知识,当然能看到urdf相关教程,那你肯定是对于TF等一些相关知识有所了解.不求甚解以及零碎知识的学习是一个好习惯,与笔者共勉.

文档中,本章结尾的youture视频还介绍了其他有用的技巧,比如vscode的urdf可视化插件等.相关连接中可以找到

相关链接

  1. 浅谈标准DH(SDH)和改进DH(MDH) - 知乎 (zhihu.com)

  2. urdf/Tutorials/Building a Visual Robot Model with URDF from Scratch - ROS Wiki — urdf/教程/从头开始使用 URDF 构建视觉机器人模型 - ROS Wiki

  3. ROS mobile robot URDF Part # 1 - YouTube

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值