1.gazebo 整体的流程框架
2. 创建urdf 机器人描述文件
对于ros或gazebo都是通过urdf 文件来描述机器人模型的,该文件的主要功能就是描述机器人各个部分(link)与关节(joint)的属性。
link 机器人零部件属性
link属性 | 机器人各个部分,例如,车身, 轮子,其包含如下属性 | |
visual | 这表示着我们是否可以在rviz或gazebo图形界面上观察到这个link,没有的话就观察不到,主要包含geometry标签 | |
例如: <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <mesh filename="package://leo/meshes/base_link.STL" /> </geometry> <material name="black"> <color rgba="1 1 1 1" /> </material> | ||
1. origin : 表示相对坐标轴的平移 和旋转关系 2.geometry : 显示机器人零部件的形状大小等(这里直接用结构的STL描述问件), 例如车身是方形的 <geometry> 轮子是圆柱形的 <geometry>
3. material 这个零部件的颜色,name 是指这种颜色名称 黑色: <material name="black"> 蓝色: <material name="blue">
| ||
collision | 这表示着传感器(主要指激光等投射型的传感器)是否可以在物理引擎上检测到这个link,同时标志着是否会与别的link进行碰撞检测,也主要包含geometry标签 | |
<origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <mesh filename="package://leo/meshes/base_link.STL" /> </geometry> | ||
inertial | 这表示着物理引擎是否能够感受到link的存在,主要包含3个标签: origin:link重心的位置 mass:link的重量 inertia:link的旋转惯量 | |
<inertial> <origin xyz="-0.1246 0.0345 0.0" rpy="0 0 0" /> <mass value="11.1322" /> <inertia ixx="0.01" ixy="0.0" ixz="0.0" iyy="0.01" iyz="0.0" izz="0.01" /> </inertial> | ||
惯性计算公式: 假如: m = 2.4 kg; h = 0.09 m; r = 0.175 m
细节参考:http://en.wikipedia.org/wiki/List_of_moment_of_inertia_tensors |
joint 关节属性
joint 属性 | 在ros中,joint_state_publisher这个节点会通过joint来了解到每个link之间的连接关系,从而根据一个link值推算出所有的link的TF状态,在gazebo中,joint指示了两个link之间的连接方式,如果两个连接为非固定的,还需要配合gazebo的标签指示摩擦系数等等 部件与部件连接的关节,如车身与轮子连接就需要关节, | |
<joint name="end_right_jiont" type="continuous"> <origin xyz="-0.2475 -0.0004 0.1125" rpy="3.1416 0 0" /> <parent link="base_link" /> <child link="end_right_link" /> <axis xyz="0 0 -1" /> </joint> | ||
1.name:标签的名称 2.type:指明这个标签的类型,主要有以下的属性 旋转(revolute) - 具有由上限和下限指定的有限范围,例如机械臂上的肘关节。 连续(continuous) - 绕轴旋转,没有上限和下限,例如底盘上的轮子 棱柱形(prismatic) - 滑动接头,沿轴线滑动,并具有由上限和下限指定的有限范围,例如某个关节是丝杆连接 固定(fixed) - 所有自由度都被锁定,比如你把摄像头用3M胶粘在了底盘上,那么这个关节就是固定的 浮动 - 此关节允许所有6个自由度的运动,这个着实不好举例,6个自由度都可以运动的话总感觉这个关节好像只是一个约束一样 平面 - 此关节允许在垂直于轴的平面内运动,用的比较少,暂时想不到用例了
3.parent:这个关节的一端,称为父端 4.child:这个关节的另一端,称为子端 5.origin:父端与子端的初始transform,例如相机的坐标系与底盘的坐标系方向相同,但是在x方向上差了0.1m,那么就在这个标签上填充上相应的值,该标签默认的值是两个质心是完全重合的。 6.axes:旋转轴,type标签里面反复提到的旋转轴就是这个标签,它指示了绕什么轴进行旋转,例如绕父节点的z轴旋转,那么该标签的值就为xyz=“0 0 1” 7.limit:有限值旋转类型必备标签,指示旋转所能到到的上下限 实际上,joint还是有很多标签的,这里列举了最常用的几个,实际上,只有前4个标签是必须的,其他的标签是要随着你的要求进而确定的 |
xarco 宏定义
xacro | 类比C语言中的宏定义,它并不会影响整个代码的完整性,但是它却能帮你大大的提高修改效率与简化代码量 |
//定义宏变量PI 为3.1415926 <xacro:property name="PI" value="3.1415926"/> //定义默认惯性default_inertial 宏变量 <xacro:macro name="default_inertial" params="mass gain"> <inertial> <mass value="${mass*gain}" /> <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="${PI/2}" /> </inertial> </xacro:macro> //使用default_inertial 宏变量,并指定相应参数 <xacro:default_inertial mass="1.0" gain="10.0"/> | |
urdf 文件例子:
<?xml version="1.0"?>
<robot name="rbo" xmlns:xacro="http://www.ros.org/wiki/xacro">
<!-- variable -->
<xacro:property name="PI" value="3.1415926"/>
<xacro:property name="car_width" value="1.0"/>
<xacro:property name="car_length" value="2.0"/>
<xacro:property name="car_height" value="0.3"/>
<xacro:property name="wheel_length" value="0.1"/>
<xacro:property name="wheel_radius" value="0.2"/>
<xacro:property name="wheel_origin_xyz" value="0.0 0.0 0.0"/>
<xacro:property name="wheel_origin_rpy" value="${PI/2} 0.0 0.0"/>
<!-- rviz color -->
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
<material name="black">
<color rgba="0 0 0 1"/>
</material>
<!-- macro -->
<xacro:macro name="default_inertial" params="mass">
<inertial>
<mass value="${mass}" />
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0" />
</inertial>
</xacro:macro>
<xacro:macro name="box_geometry" params="width length height">
<geometry>
<box size="${width} ${length} ${height}"/>
</geometry>
</xacro:macro>
<xacro:macro name="cylinder_geometry" params="length radius">
<geometry>
<cylinder length="${length}" radius="${radius}"/>
</geometry>
</xacro:macro>
<xacro:macro name="default_origin" params="xyz rpyaw">
<origin xyz="${xyz}" rpy="${rpyaw}"/>
</xacro:macro>
<link name="car_link">
<visual>
<xacro:box_geometry width="${car_width}" length="${car_length}" height="${car_height}"/>
<material name="blue"/>
</visual>
<collision>
<xacro:box_geometry width="${car_width}" length="${car_length}" height="${car_height}"/>
</collision>
<xacro:default_inertial mass="3.0"/>
</link>
<!-- gazebo -->
<gazebo reference="car_link">
<material>Gazebo/SkyBlue</material>
<mu1>0.5</mu1>
<mu2>0.5</mu2>
</gazebo>
<!-- front_right_wheel -->
<link name="front_right_wheel">
<visual>
<xacro:cylinder_geometry length="${wheel_length}" radius="${wheel_radius}"/>
<xacro:default_origin xyz="${wheel_origin_xyz}" rpyaw="${wheel_origin_rpy}" />
<material name="black"/>
</visual>
<collision>
<xacro:cylinder_geometry length="${wheel_length}" radius="${wheel_radius}"/>
<xacro:default_origin xyz="${wheel_origin_xyz}" rpyaw="${wheel_origin_rpy}" />
</collision>
<xacro:default_inertial mass="1.0"/>
</link>
<joint name="car_base_front_right_wheel" type="continuous">
<origin xyz="${1.0*(wheel_length+car_width)/2.0} ${1.0*car_length*0.6/2.0} 0.0" rpy="0.0 0.0 1.57"/>
<parent link="car_link"/>
<child link="front_right_wheel"/>
<axis xyz="0.0 1.0 0.0"/>
</joint>
<!-- front_left_wheel -->
<link name="front_left_wheel">
<visual>
<xacro:cylinder_geometry length="${wheel_length}" radius="${wheel_radius}"/>
<xacro:default_origin xyz="${wheel_origin_xyz}" rpyaw="${wheel_origin_rpy}" />
<material name="black"/>
</visual>
<collision>
<xacro:cylinder_geometry length="${wheel_length}" radius="${wheel_radius}"/>
<xacro:default_origin xyz="${wheel_origin_xyz}" rpyaw="${wheel_origin_rpy}" />
</collision>
<xacro:default_inertial mass="1.0"/>
</link>
<joint name="car_base_front_left_wheel" type="continuous">
<origin xyz="${-1.0*(wheel_length+car_width)/2.0} ${1.0*car_length*0.6/2.0} 0.0" rpy="0.0 0.0 1.57"/>
<parent link="car_link"/>
<child link="front_left_wheel"/>
<axis xyz="0.0 1.0 0.0"/>
</joint>
<!-- end_left_wheel -->
<link name="end_left_wheel">
<visual>
<xacro:cylinder_geometry length="${wheel_length}" radius="${wheel_radius}"/>
<xacro:default_origin xyz="${wheel_origin_xyz}" rpyaw="${wheel_origin_rpy}" />
<material name="black"/>
</visual>
<collision>
<xacro:cylinder_geometry length="${wheel_length}" radius="${wheel_radius}"/>
<xacro:default_origin xyz="${wheel_origin_xyz}" rpyaw="${wheel_origin_rpy}" />
</collision>
<xacro:default_inertial mass="1.0"/>
</link>
<joint name="car_base_end_left_wheel" type="continuous">
<origin xyz="${-1.0*(wheel_length+car_width)/2.0} ${-1.0*car_length*0.6/2.0} 0.0" rpy="0.0 0.0 1.57"/>
<parent link="car_link"/>
<child link="end_left_wheel"/>
<axis xyz="0.0 1.0 0.0"/>
</joint>
<!-- end_right_wheel -->
<link name="end_right_wheel">
<visual>
<xacro:cylinder_geometry length="${wheel_length}" radius="${wheel_radius}"/>
<xacro:default_origin xyz="${wheel_origin_xyz}" rpyaw="${wheel_origin_rpy}" />
<material name="black"/>
</visual>
<collision>
<xacro:cylinder_geometry length="${wheel_length}" radius="${wheel_radius}"/>
<xacro:default_origin xyz="${wheel_origin_xyz}" rpyaw="${wheel_origin_rpy}" />
</collision>
<xacro:default_inertial mass="1.0"/>
</link>
<joint name="car_base_end_right_wheel" type="continuous">
<origin xyz="${1.0*(wheel_length+car_width)/2.0} ${-1.0*car_length*0.6/2.0} 0.0" rpy="0.0 0.0 1.57"/>
<parent link="car_link"/>
<child link="end_right_wheel"/>
<axis xyz="0.0 1.0 0.0"/>
</joint>
<link name="base_link"/>
<joint name="base_link_car" type="fixed">
<origin xyz="0.0 0.0 ${wheel_radius}" rpy="0.0 0.0 -1.57"/>
<parent link="base_link"/>
<child link="car_link"/>
</joint>
<gazebo>
<plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
<alwaysOn>true</alwaysOn>
<updateRate>50.0</updateRate>
<leftJoint>car_base_front_left_wheel</leftJoint>
<rightJoint>car_base_front_right_wheel</rightJoint>
<wheelSeparation>1.0</wheelSeparation>
<wheelDiameter>0.5</wheelDiameter>
<torque>1.0</torque>
<commandTopic>cmd_vel</commandTopic>
<odometryTopic>odom</odometryTopic>
<odometryFrame>odom</odometryFrame>
<robotBaseFrame>base_link</robotBaseFrame>
<publishWheelTF>true</publishWheelTF>
<publishWheelJointState>true</publishWheelJointState>
<legecyMode>true</legecyMode>
<wheelAcceleration>1</wheelAcceleration>
<legacyMode>true</legacyMode>
</plugin>
</gazebo>
</robot>
在ros中,机器人节点的驱动靠的是TF,而在gazebo中,机器人节点的驱动主要靠物理引擎!
因此,没有inertial标签的link在gazebo中是完全看不到的
gazebo是依靠物理引擎来进行机器人仿真的,因此所有在gazebo中的物体和联系都要符合物理定律,否则要么gazebo跪给你看(压根儿就不显示给你),要么gazebo浪给你看(例如两个link之间没有摩擦系数,你轻推一下一个link,它就会以无限的加速度前行)
要注意模型的坐标系关系。
遇到的问题
1 | 由于轮子坐标系错误,在控制行走,机器乱滚, 解决: 通过rviz 观察坐标系情况, 设置旋转参数,x 轴必须朝前, y轴一般朝左(因为差速控制只有前后移动,所以y轴不重要) 一般base_link 坐标系在模型中心底部(车身中心底部,注意不是地面),base_footprint 坐标系在模型中心顶部,尽量控制重心在车子中心,否则可能前溜或后溜 |
2 | 由于车子的惯性参数没设置对,在控制车子行走后,无法正常停止, 停止后,重新启动会出现后溜的情况 修改惯性参数如下: <inertia ixx="0.01" ixy="0.0" |
关键英语术语:
inertial 惯性
collision 碰撞
mesh 齿合
mass 质量
cylinder 圆筒
mu 摩擦系数
torque 转距
link 表示小车零部件,如主体box, 每个轮子
join 表示两个link 之间的连接(包括旋转)关系
参考网址: