Unified Robot Description Format,统一机器人描述格式,简称为URDF。ROS中的urdf功能包包含一个URDF的C++解析器,URDF文件使用XML格式描述机器人模型。
该软件包包含许多机器人模型,传感器,场景等的XML规范。每个XML规范都有一种或多种语言的相应解析器:urdf语法规范。基础部分可以参考官方教程:tutorials-wiki
如何写一个基础的urdf模型不在这里展开。
如示例link1,一个最简单的link需要什么,name,如果还希望显示,就加入
,在仿真中为了模拟真实碰撞,加入
,最后是
惯量,通过质量、质心、惯性矩阵模拟真实物体的运动状况。其中需要注意的,惯量标签是必不可少的,
标签都是相对于标签基坐标本身。
<link name="link1">
<collision>
<origin xyz="0 0 ${height1/2}" rpy="0 0 0"/>
<geometry>
<box size="${width} ${width} ${height1}"/>
geometry>
collision>
<visual>
<origin xyz="0 0 ${height1/2}" rpy="0 0 0"/>
<geometry>
<box size="${width} ${width} ${height1}"/>
geometry>
<material name="orange"/>
visual>
<inertial>
<origin xyz="0 0 1" rpy="0 0 0"/>
<mass value="1"/>
<inertia
ixx="1.0" ixy="0.0" ixz="0.0"
iyy="1.0" iyz="0.0"
izz="1.0"/>
inertial>
link>
示例中使用
,也可以使用其他现有基础形状,对于复杂模型可以使用现有模型加载,如stl、dae等类型的3D模型文件,不同类型的有不同使用属性,在碰撞模型中需要考虑模型复杂程度,避免模型过于复杂,物理引擎计算困难,解决方法可以使用模型处理软件简化模型。惯性参数可以在SolidWorks等软件中获取。
<geometry>
<mesh filename="package://caster_description/mesh/caster_body_part_v2.stl" />
geometry>
对于joint需要添加的属性很少,一般会设置阻尼和摩擦。damping旋转阻尼,friction静摩擦,例如万向轮中垂直摩擦设置damping,limit标签也是经常使用的标签,关节位置,力,速度都可以控制。
<joint name="support_wheel_body_joint" type="continuous">
<origin xyz="0 0 ${height1/2}" rpy="0 0 0"/>
<parent link="base_link" />
<child link="link1" />
<axis xyz="0 0 1" />
<dynamics damping="0.01" friction="0.0"/>
<limit effort="10" velocity="10.0" />
joint>
根据自己的仿真需求创建适合的世界地图,执行命令打开gazebo并加载空地图,在菜单栏Edit的选项中编辑建筑与模型,这里可以使用标准的模块,也可以使用加载模型文件到世界里。构建完成后save as保存成world文件。
执行以下命令打开gazebo并加载相应的世界地图。在这里只是检验地图,之后一般会在launch启动时同时加载。
rosrun gazebo gazebo -r
`rospack find gazebo_worlds`/worlds/empty.world
在实际的开发中,我们是要把所有地图模型都加入功能包中的,如果想要在功能包里加入自己的模型,并且随时都可以插入,这里有一些规则需要遵守.
之前已经创建好了模型,现在放到我们的功能包中,在这里贴出我司caster移动机器人的物理仿真文件结构.
worlds文件夹:存放创建的世界地图.
launch文件:
<launch>
//参数表
<arg name="world_name" value="$(find caster_gazebo)/worlds/caster_home.world"/> 加载地图
<arg name="paused" default="false"/> //以暂停状态启动,默认false
<arg name="use_sim_time" default="true"/> //告诉ROS节点要求时间获取Gazebo发布的模拟时间,通过ROS主题/时钟发布(默认为true)
<arg name="gui" default="true"/> //启动gazebo的用户界面,默认true
<arg name="headless" default="false"/> //状态日志记录
<arg name="debug" default="false"/> //使用gdb以调试模式启动gzserver(默认为false)
//启动gazebo并加载地图
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="world_name" value="$(arg world_name)"/>
<arg name="debug" value="$(arg debug)"/>
<arg name="gui" value="$(arg gui)"/>
<arg name="paused" value="$(arg paused)"/>
<arg name="use_sim_time" value="$(arg use_sim_time)"/>
<arg name="headless" value="$(arg headless)"/>
include>
//urdf的参数
<param name="robot_description" command="$(find xacro)/xacro --inorder $(find caster_description)/urdf/caster_xacro.xacro" />
//两个状态观测器
<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">
<param name="publish_frequency" type="double" value="50.0"/>
node>
//启动rviz,这里使用了包中的rviz文件,会自动加载显示一些选项,可以选择不加载参数
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find caster_viz)/viz/model.rviz" />
//加载机器人模型,如果后边的urdf没有设置好是不能显示的
<node name="spawn_table" pkg="gazebo_ros" type="spawn_model" args="-urdf -param robot_description -model caster" respawn="false" output="screen" />
launch>
在这里给定xyz可以设置初始位置.
启动程序中一般需要修改的是world文件与urdf的文件,其他命名和参数等都可以根据自己的需求进行更改.
最重要的models文件夹,这里存放机器人模型,可以看到model.config文件,这是之前创建的模型文件,其实在这一级还有model.sdf文件(参数都是在这个文件进行修改的),只是在sublime里没有显示. meshes文件夹存放stl,相同于urdf,都是来存放模型文件,可以时一般使用较多的时stl与dae格式文件,但是想要让模型文件加载stl,还需要修改model.sdf文件.
<visual name='visual'>
<geometry>
<mesh>
<uri>model://caster_docker/meshes/docker.STLuri>
mesh>
geometry>
<collision name='collision'>
<geometry>
<mesh>
<uri>model://caster_docker/meshes/docker.STLuri>
mesh>
geometry>
修改两处的uri保证可以找到文件,但是这个文件路径怎么只有一半啊,能找到吗,答案是找不到确实..这时修改package.xml,导入路径,就可以补全相对路径caster_docker了.这时在打开gazebo会发现加载的模型
<export>
<gazebo_ros gazebo_media_path="${prefix}" gazebo_model_path="${prefix}/models:${prefix}/models/caster_docker"/>
export>
现在在gazebo中可以直接插入模型了,接下来就是设置外观颜色等,主要时使用material标签进行设置,在sdf文件中.
<visual name='visual'>
<material>
<script>
<uri>model://caster_docker/materials/scripts</uri>
<uri>model://caster_docker/materials/textures</uri>
<name>docker</name>
script>
material>
visual>
这里主要是添加了两个相对路径,scripts存放.material文件,textures存放贴图文件,用来装饰模型,此处我使用贴图的方式,还有很多其的material可以进行装饰,material的类型写法都可以在开源面向对象的3D引擎可以找到,纯色,纹理色,贴图各种都是可以使用的,但是在我的尝试过程,自定义的模型是不能使用纹理色进行渲染的,还有一点需要提一下,在urdf中和gazebo中使用纯色是基本看不到模型形状的.
颜色库wiki是预设的materials,需要时可以在这里查找适合的进行渲染.
更多的material可以在这里找到material scripts.在gazebo的库中有很多的material可以参考,同时模型库,world等都可以在库里找到参考gazebo库.
那这些文件中的标签都是干什么用的,我还有哪些标签可以使用,这里都有,World Physics Model等等齐全.
现在单独的模型已经可以加载显示了.但是.world文件是之前已经生成好的,我们同样需要修改caster_home.world文件.
找到你自定义模型的部分,按照之前的同样的操作修改三处uri,之后你会发现之前的world也可以直接加载包中模型了.
这是官方框架图,最开始看很是困惑,当把流程全部跑通一遍,会发现一定是清晰明了的.图中加入了controller,但是还有更简单的一种模式,直接加入相应插件plugin,是可以使用controller的,这种方法相对简单易用,但是使用controller的部分却会全部不能使用,不过一些相对简单的插件IMU,Laser等则可以使用,而驱动则最好是使用controller的模式.
我们需要给每一个link添加reference,并添加相应属性,一般只添加material,轮子之类的还需要添加其他的参数摩擦力弹性系数等,可以根据自己的需求进行添加.
<gazebo reference="wheel_left_link">
<mu1>0.1mu1>
<mu2>0.1mu2>
<kp>500000.0kp>
<kd>10.0kd>
<minDepth>0.001minDepth>
<maxVel>0.1maxVel>
<fdir1>1 0 0fdir1>
<material>Gazebo/FlatBlackmaterial>
gazebo>
同样joint也可以添加物理参数设置,但是不同的是在urdf的joint中添加
<joint name="joint2" type="continuous">
<parent link="link2"/>
<child link="link3"/>
<origin xyz="0 ${width} ${height2 - axel_offset*2}" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
<dynamics damping="0.7"/>
joint>
<gazebo>
<plugin name="caster_controller" filename="libgazebo_ros_diff_drive.so">
<alwaysOn>truealwaysOn>
<commandTopic>cmd_velcommandTopic>
<odometryTopic>odomodometryTopic>
<odometryFrame>odomodometryFrame>
<odometrySource>worldodometrySource>
<publishOdomTF>truepublishOdomTF>
<robotBaseFrame>base_footprintrobotBaseFrame>
<publishWheelTF>falsepublishWheelTF>
<publishTf>truepublishTf>
<publishWheelJointState>truepublishWheelJointState>
<legacyMode>falselegacyMode>
<updateRate>50updateRate>
<leftJoint>drive_wheel_left_jointleftJoint>
<rightJoint>drive_wheel_right_jointrightJoint>
<wheelSeparation>0.4174wheelSeparation>
<wheelDiameter>0.15wheelDiameter>
<wheelAcceleration>1wheelAcceleration>
<wheelTorque>6.5wheelTorque>
<rosDebugLevel>narosDebugLevel>
plugin>
gazebo>
我司caster的驱动插件示例,caster使用的是差动轮,所以这里使用的是libgazebo_ros_diff_drive.so插件,这里只是为了示例真实项目中我还是会使用自定义controller的方式,为了控制篇幅这里不再放其他插件示例,底盘源码可以在github下载来参考,相关内容可以直接将在wiki page查看.其他各常用插件的示例及使用方法看这里,找到合适的插件并添加,调整相关参数.
随记一句话:大部分技术文档都是可以从官方找到,并且会是最准确的.
模型有了,现在需要添加执行器,方法为给joint添加transmission标签.同时使用特定的gazebo_ros_control插件进行控制。
注意:自带的仿真控制器是不能与gazebo_ros_control同时使用的
该插件可以解析传输标签并加载适当的硬件接口和控制器管理器。
默认情况下,gazebo_ros_control插件非常简单,但它也可以通过附加的插件架构进行扩展,允许超级用户在ros_control和gazebo之间创建自己的自定义机器人硬件接口。
<gazebo>
<plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
<robotNamespace>/MYROBOTrobotNamespace>
plugin>
gazebo>
:用于插件实例的ROS名称空间,在URDF/SDF中默认为robot名称
:控制器更新周期(秒),默认为露台的周期
:robot描述(URDF)在参数服务器上的位置,默认为“/robot描述”
:要使用的自定义robot sim接口的pluginlib名称(有关详细信息,请参见下文),默认为“DefaultRobotHWSim”在urdf文件中添加transmission:
<transmission name="tran1">
<type>transmission_interface/SimpleTransmissiontype>
<joint name="joint1">
<hardwareInterface>EffortJointInterfacehardwareInterface>
joint>
<actuator name="motor1">
<hardwareInterface>EffortJointInterfacehardwareInterface>
<mechanicalReduction>1mechanicalReduction>
actuator>
transmission>
<transmission name="tran2">
<type>transmission_interface/SimpleTransmissiontype>
<joint name="joint2">
<hardwareInterface>EffortJointInterfacehardwareInterface>
joint>
<actuator name="motor2">
<hardwareInterface>EffortJointInterfacehardwareInterface>
<mechanicalReduction>1mechanicalReduction>
actuator>
transmission>
wiki教程gazebo:http://wiki.ros.org/simulator_gazebo/Tutorials
gazebo与ROS的官方教程:http://gazebosim.org/tutorials?cat=connect_ros
官方网站可找到官方教程,文件库(功能模型等)
开源物理引擎是对引擎的详细说明介绍.