Unified Robot Description Format,简称为URDF(标准化机器人描述格式),是一种用于描述机器人及其部分结构、关节、自由度等的XML格式文件。

一、创建第一个URDF文件

将要创建的URDF文件描述的是一种最常见的移动机器人,它有四个轮子、一个带有抓取器的手臂。

为了打好基础,我们先做一个带有四个轮子的机器人底座。在 chapter7_tutorials/robot1_description/urdf 文件夹创建一个新文件并命名为robot1.urdf,其内容如下:

<?xml version="1.0"?>
<robot name="robot1">
<link name="base_link">
<visual>
<geometry>
<box size="0.2 .3 .1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0.05"/>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
</link> <link name="wheel_1">
<visual>
<geometry>
<cylinder length="0.05" radius="0.05"/>
</geometry>
<origin rpy="0 1.5 0" xyz="0.1 0.1 0"/>
<material name="black">
<color rgba="0 0 0 1"/>
</material>
</visual>
</link> <link name="wheel_2">
<visual>
<geometry>
<cylinder length="0.05" radius="0.05"/>
</geometry>
<origin rpy="0 1.5 0" xyz="-0.1 0.1 0"/>
<material name="black"/>
</visual>
</link> <link name="wheel_3">
<visual>
<geometry>
<cylinder length="0.05" radius="0.05"/>
</geometry>
<origin rpy="0 1.5 0" xyz="0.1 -0.1 0"/>
<material name="black"/>
</visual>
</link> <link name="wheel_4">
<visual>
<geometry>
<cylinder length="0.05" radius="0.05"/>
</geometry>
<origin rpy="0 1.5 0" xyz="-0.1 -0.1 0"/>
<material name="black"/>
</visual>
</link> <joint name="base_to_wheel1" type="fixed">
<parent link="base_link"/>
<child link="wheel_1"/>
<origin xyz="0 0 0"/>
</joint> <joint name="base_to_wheel2" type="fixed">
<parent link="base_link"/>
<child link="wheel_2"/>
<origin xyz="0 0 0"/>
</joint> <joint name="base_to_wheel3" type="fixed">
<parent link="base_link"/>
<child link="wheel_3"/>
<origin xyz="0 0 0"/>
</joint> <joint name="base_to_wheel4" type="fixed">
<parent link="base_link"/>
<child link="wheel_4"/>
<origin xyz="0 0 0"/>
</joint>
</robot>

二、常见标签说明

连接(link)标签

标签 功能
<link> 连接的可视化、碰撞和惯性属性设置
<visual> 设置连接的可视化属性
<collision> 设置连接的碰撞计算属性
<inertial> 设置连接的惯性属性
<geometry> 输入模型的形状。提供box、cylinder、sphere等形态
<origin> 设置相对于连接相对坐标系的移动和旋转
<material> 设置连接的颜色和纹理
<mass> 连接重量(单位:kg)的设置

关节(joint)标签

标签 功能
<joint> 与连接的关系和关节类型的设置
<parent> 关节的父连接
<child> 关节的子连接
<origin> 将父连接坐标系转换为子连接坐标系
<axis> 设置旋转轴
<limit> 设置关节的速度、力和半径(仅当关节是revolute或prismatic时)

transmission标签

<transmission>是与ROS-CONTROL一起运行所必须的标签,它输入关节与舵机之间的命令接口。

标签 功能
<transmission> 设置关节和舵机之间的变量
<type> 设置力的传递方式的形状
<joint> 设置关节信息设置
<hardwareInterface> 设置硬件接口
<actuator> 设置舵机信息
<mechanicalReduction> 设置舵机与关节之间的齿轮比

注:这里的起点位置是相对与父连杆的位置,并不是绝对坐标。另外连接又称连杆。

三、解释文件格式

如你在代码中所见,有两种用于描述机器人几何结构的基本字段:连接(link)和关节(joint)。

第一个连接的名字是base_link(基本连接),这个名字在文件中必须唯一:

<link name="base_link">
<visual>
<geometry>
<box size="0.2 .3 .1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0.05"/>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
</link>
  • link name:定义连接名称为base_link
  • visual:让定义的物体结构可见
  • geometry:定义几何形状(圆柱体、立方体、球体和网格)为box,尺寸为0.2*0.3*0.1
  • origin:rpy-起点位置无位移,xyz-绕z轴旋转
  • material:定义材质(颜色和纹理),这里只定义了颜色为rgba="1 1 1 1"

然后使用以下代码定义关节:

<joint name="base_to_wheel1" type="fixed">
<parent link="base_link"/>
<child link="wheel_1"/>
<origin xyz="0 0 0"/>
</joint>
  • joint name:定义关节名称为base_to_wheel1,类型为固定关节
  • parent link:父连接是base_link
  • child link:子连接是wheel_1
  • origin:起点位置相对父连接无位移

关节类型

  • fiexd:固定关节,不允许运动的特殊关节
  • continuous:转动关节,可以绕单轴无线旋转
  • revolute:旋转关节,类似于continuous,但旋转角度有限
  • prismatic:滑动关节,沿某一轴线移动的关节,带有位置极限
  • floating:浮动关节,允许进行平移、旋转运动
  • planar:平面关节,允许在平面正交方向上平移或者旋转

四、检查URDF语法

ROS为用户提供了一个检查URDF语法的命令:

check_urdf robot1.urdf

如果一切正常,将会有如下显示:

robot name is: Robot1
---------- Successfully Parsed XML ---------------
root Link: base_link has 4 child(ren)
child(1): wheel1
child(2): wheel2
child(3): wheel3
child(4): wheel4

如果你希望以图形的方式来查看它,那么可以使用urdf_to_graphiz命令工具:

$ urdf_to_graphiz robot1.urdf

此命令将生成两个文件:robot1.gv 和 robot1.pdf。可以使用 evince 打开:

evince robot1.pdf

显示如下:

五、在rviz里查看3D模型

新建launch文件

在robot1_description/launch文件夹下新建display.launch文件,代码如下:

<?xml version="1.0"?>
<launch>
<arg name="model" />
<arg name="gui" default="False" />
<param name="robot_description" textfile="$(arg model)" />
<param name="use_gui" value="$(arg gui)"/>
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find urdf_tutorial)/urdf.rviz" />
</launch>

运行launch文件

$ roslaunch robot1_description display.launch model:="`rospack find robot1_description`/urdf/robot1.urdf"

注:把文件直接拖进终端就可以直接显示文件位置信息。

显示如下: 

默认状态下画面中什么都没有,此时需要做出调整。在左下角的add按钮中添加RobotModel,然后将Fixed Frame选为base_link。

六、添加基座臂、连接臂和夹持臂

补充urdf文件

在</robot>前增添以下代码:

<link name="arm_base">
<visual>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0.1"/>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<joint name="base_to_arm_base" type="continuous">
<parent link="base_link"/>
<child link="arm_base"/>
<axis xyz="0 0 1"/>
<origin xyz="0 0 0"/>
</joint>
<link name="arm_1">
<visual>
<geometry>
<box size="0.05 .05 0.5"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0.25"/>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.05 .05 0.5"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<joint name="arm_1_to_arm_base" type="revolute">
<parent link="arm_base"/>
<child link="arm_1"/>
<axis xyz="1 0 0"/>
<origin xyz="0 0 0.15"/>
<limit effort ="1000.0" lower="-1.0" upper="1.0" velocity="0.5"/>
</joint>
<link name="arm_2">
<visual>
<geometry>
<box size="0.05 0.05 0.5"/>
</geometry>
<origin rpy="0 0 0" xyz="0.06 0 0.15"/>
<material name="white">
<color rgba="1 1 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.05 .05 0.5"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<joint name="arm_2_to_arm_1" type="revolute">
<parent link="arm_1"/>
<child link="arm_2"/>
<axis xyz="1 0 0"/>
<origin xyz="0.0 0 0.45"/>
<limit effort ="1000.0" lower="-2.5" upper="2.5" velocity="0.5"/>
</joint>
<joint name="left_gripper_joint" type="revolute">
<axis xyz="0 0 1"/>
<limit effort="1000.0" lower="0.0" upper="0.548" velocity="0.5"/>
<origin rpy="0 -1.57 0" xyz="0.06 0 0.4"/>
<parent link="arm_2"/>
<child link="left_gripper"/>
</joint>
<link name="left_gripper">
<visual>
<origin rpy="0 0 0" xyz="0 0 0"/>
<geometry>
<mesh filename="package://pr2_description/meshes/gripper_v0/l_finger.dae"/>
</geometry>
</visual>
<collision>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</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://pr2_description/meshes/gripper_v0/l_finger_tip.dae"/>
</geometry>
</visual>
<collision>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<joint name="right_gripper_joint" type="revolute">
<axis xyz="0 0 -1"/>
<limit effort="1000.0" lower="0.0" upper="0.548" velocity="0.5"/>
<origin rpy="0 -1.57 0" xyz="0.06 0 0.4"/>
<parent link="arm_2"/>
<child link="right_gripper"/>
</joint>
<link name="right_gripper">
<visual>
<origin rpy="-3.1415 0 0" xyz="0 0 0"/>
<geometry>
<mesh filename="package://pr2_description/meshes/gripper_v0/l_finger.dae"/>
</geometry>
</visual>
<collision>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</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://pr2_description/meshes/gripper_v0/l_finger_tip.dae"/>
</geometry>
</visual>
<collision>
<geometry>
<box size="0.1 .1 .1"/>
</geometry>
</collision>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>

运行launch文件

$ roslaunch robot1_description display.launch model:="`rospack find robot1_description`/urdf/robot1.urdf"

显示如下:

七、使机器人模型运动

最常用的关节是转动关节。例如,我们在 arm_1_to_arm_base 上使用的就是,其代码如下所示:

<joint name="arm_1_to_arm_base" type="revolute">
<parent link="arm_base"/>
<child link="arm_1"/>
<axis xyz="1 0 0"/>
<origin xyz="0 0 0.15"/>
<limit effort ="1000.0" lower="-1.0" upper="1.0" velocity="0.5"/>
</joint>
  • <axis xyz="1 0 0"/>旋转转动轴来运动。
  • limit 标签用于选择以下属性:effort(关节所承受的最大力),lower(赋值给关节的下限,旋转关节的单位是弧度,移动关节的单位是米),upper(赋值给关节的上限),velocity(强制关节的最大速度)。

要判断关节的轴或转动限值是否合适,有一种好的办法就是使用 joint_state_publisher GUI 运行 rviz(加上了gui:=true):

$ roslaunch robot1_description display.launch model:="`rospack find robot1_description`/urdf/robot1.urdf" gui:=true

joint_state_publisher GUI 运行界面显示如下:

urdf文件中每一个axis对应一个调节器,joint_state_publisher应该是ros中自带的调节joint的功能,所以直接调用就可以。另外界面中的每个滑块都能控制一个关节。

八、物理属性和碰撞属性

如果你想要在 gazebo 或者其他仿真软件上进行机器人仿真,就需要添加物理属性和碰撞属性。这意味着我们需要设定几何尺寸来计算可能的碰撞,例如设定重量我们才能够计算惯性等。

你需要保证模型文件中的所有连接都有这些参数,否则就无法对这些机器人进行仿真。

在下面的代码中,你会看到我们向名为 base_link 的连接添加这两个属性:

<link name="base_link">
...
<collision>
<geometry>
<box size="0.2 .3 0.1"/>
</geometry>
</collision>
<inertial>
<mass value="100"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>

对于其他的连接也要这么做。记住,要为所有连接添加 collision 和 inertial 属性,因为如果你不这样做的话,gazebo 将无法使用这些模型。

你能够在 robot1_description/urdf/robot1_physics.urdf 中查看带有所有参数的完整文件。

参考: 

ROS-URDF仿真

ROS学习笔记十一:创建URDF 文件并在RVIZ中查看模型的更多相关文章

  1. ROS学习笔记十:URDF详解

    Unified Robot Description Format,简称为URDF(标准化机器人描述格式),是一种用于描述机器人及其部分结构.关节.自由度等的XML格式文件. 一.URDF语法规范 参见 ...

  2. [转]ROS学习笔记十一:ROS中数据的记录与重放

    本节主要介绍如何记录一个正在运行的ROS系统中的数据,然后在一个运行的系统中根据记录文件重新产生和记录时类似的运动情况.本例子还是以小海龟例程为例. 记录数据(创建一个bag文件) 首先运行小海龟例程 ...

  3. Robot Operating System (ROS)学习笔记---创建简单的机器人模型smartcar

    搭建环境:XMWare  Ubuntu14.04  ROS(indigo) 转载自古月居  转载连接:http://www.guyuehome.com/243 一.创建硬件描述包 已创建catkin_ ...

  4. ROS学习笔记七:在ROS中使用USB摄像头

    下面是一些USB摄像头的驱动(大多数摄像头都支持uvc标准): 1 使用软件库里的uvc-camera功能包 1.1 检查摄像头 lsusb ----------------------------- ...

  5. springmvc学习笔记---idea创建springmvc项目

    前言: 真的是很久没搞java的web服务开发了, 最近一次搞还是读研的时候, 想来感慨万千. 英雄没落, Eclipse的盟主地位隐隐然有被IntelliJ IDEA超越的趋势. Spring从2. ...

  6. java 学习笔记之 流、文件的操作

    ava 学习笔记之 流.文件的操作 对于一些基础的知识,这里不再过多的解释, 简单的文件查询过滤操作 package com.wfu.ch08; import java.io.File; import ...

  7. python3.4学习笔记(十一) 列表、数组实例

    python3.4学习笔记(十一) 列表.数组实例 #python列表,数组类型要相同,python不需要指定数据类型,可以把各种类型打包进去#python列表可以包含整数,浮点数,字符串,对象#创建 ...

  8. Go语言学习笔记十一: 切片(slice)

    Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...

  9. Django:学习笔记(2)——创建第一个应用

    Django:学习笔记(2)——创建第一个应用 创建应用 在 Django 中,每一个应用都是一个 Python 包,并且遵循着相同的约定.Django 自带一个工具,可以帮你生成应用的基础目录结构, ...

随机推荐

  1. SpringMVC get请求中文乱码

    针对GET请求的编码问题,则需要改tomcat的server.xml配置文件,如下: 原 <Connector connectionTimeout="20000" port= ...

  2. [开源]OSharpNS - .net core 快速开发框架 - 简介

    什么是OSharp OSharpNS全称OSharp Framework with .NetStandard2.0,是一个基于.NetStandard2.0开发的一个.NetCore快速开发框架.这个 ...

  3. Scala入门到精通——第十六节 泛型与注解

    本节主要内容 泛型(Generic Type)简单介绍 注解(Annotation)简单介绍 注解经常使用场景 1. 泛型(Generic Type)简单介绍 泛型用于指定方法或类能够接受随意类型參数 ...

  4. SQL 主机

    SQL 主机 SQL 主机 如果您想要您的网站存储数据在数据库并从数据库显示数据,您的 Web 服务器必须能使用 SQL 语言访问数据库系统. 如果您的 Web 服务器托管在互联网服务提供商(ISP, ...

  5. AngularJS自己定义标签加入回调函数eval()

    function helloworld(name){ console.log("hello!!!!!"+name) } var name="zhangsan"; ...

  6. MaterialImageView

    https://github.com/zhaozhentao/MaterialImageView

  7. Android Material Design-Maintaining Compatibility(保持兼容性)-(七)

    转载请注明出处:http://blog.csdn.net/bbld_/article/details/40634829 翻译自: http://developer.android.com/traini ...

  8. jQuery的AJax异步訪问

    用一个样例用以说明:点击button,将input内用户输入的数据发送给服务端.并将结果返回给页面. 首先是html承载内容: <!DOCTYPE html> <html> & ...

  9. Fluently NHibernate 插入CLOB字段

    ORA-01461: can bind a LONG value only for insert into a LONG column 插入oracle某表时报的错. 查来查去,是插入的某个字段值超长 ...

  10. python iterable 和list、dictionary的区别和联系

    1 为什么一些函数的参数指定要iterable object的,但是也可以传入list为参数? 因为list.dictionary都是iterable object. 在iterable object ...