学校的这学期课程是ros机器人开发实战,我们学习小组也要搞一个自己的机器人模型,我们组又叫葫芦组,所以我就做了个葫芦形状的机器人,虽说有点丑,本来想用maya建模再导入的,奈何不太懂maya,于是乎就用基础三形状构建了这个机器人模型。
接下来我将会将urdf建模与gazebo仿真过程详细写出,共大家参考与互相学习,如有疏漏,敬请指正。
源码:hulu机器人源码-百度网盘 提取码:hctm
不过这个葫芦机器人走路实在是不稳定,所以又写了另外的俩个机器人,源码和演示视频在文末。
首先我们得把要构建的机器人画出来,把每个肢节的长宽高和半径都标注好,听说可以用CAD/SW/UG等软件画,我当时懒得画,画了个躯体就没画了,纯粹靠手调调节相对位置,耗费了不少时间,如果你会CAD可以减少很多调整时间,效果图大概是这样子的,找了个E100的图作为参考
virtual-machine:~$ catkin_crate_pkg hulu_gazebo urdf xacro
依赖urdf、xacro功能包
find_package(catkin REQUIRED COMPONENTS
urdf
xacro
gazebo_plugins
gazebo_ros
gazebo_ros_control
geometry_msgs
roscpp
rospy
)
<buildtool_depend>catkinbuildtool_depend>
<build_depend>urdfbuild_depend>
<build_depend>xacrobuild_depend>
<build_depend>gazebo_pluginsbuild_depend>
<build_depend>gazebo_rosbuild_depend>
<build_depend>gazebo_ros_controlbuild_depend>
<build_depend>geometry_msgsbuild_depend>
<build_depend>roscppbuild_depend>
<build_depend>rospybuild_depend>
<build_export_depend>urdfbuild_export_depend>
<build_export_depend>xacrobuild_export_depend>
<build_export_depend>gazebo_pluginsbuild_export_depend>
<build_export_depend>gazebo_rosbuild_export_depend>
<build_export_depend>gazebo_ros_controlbuild_export_depend>
<build_export_depend>geometry_msgsbuild_export_depend>
<build_export_depend>roscppbuild_export_depend>
<build_export_depend>rospybuild_export_depend>
<exec_depend>urdfexec_depend>
<exec_depend>xacroexec_depend>
<exec_depend>gazebo_pluginsexec_depend>
<exec_depend>gazebo_rosexec_depend>
<exec_depend>gazebo_ros_controlexec_depend>
<exec_depend>geometry_msgsexec_depend>
<exec_depend>roscppexec_depend>
<exec_depend>rospyexec_depend>
关于CMakeLists.txt可以参考我的这篇文章【ros学习】9.ros话题通讯之publisher与subscribe的c++实现详解
$ git clone http://github.com/vanadiumlabs/arbotis_ros.git
$ catkin_make
什么是Xacro? 我们可以把它理解成为针对URDF的扩展性和配置性而设计的宏语言(macro language)。有了Xacro,我们就可以像编程一样来写URDF文件。XACRO格式提供了一些更高级的方式来组织编辑机器人描述. 主要提供了三种方式来使得整个描述文件变得简单。
(1)Constants
<xacro:property name="WIDTH" value="2.0"/>
类似于C语言中的宏定义, 在头部定义后就可以${body_width}进行引用其数值,有了这个,至少我们可以把需要配置的变量进行统一管理和使用。
(2)Macros
<xacro:macro name="default_origin">
<origin xyz="0 0 0" rpy="0 0 0"/>
xacro:macro>
<xacro:default_origin />
Macros是xacro文件中最重要的部分. 就像宏函数一样, 完成一些最小模块的定义, 方便重用, 以及可以使用参数来标识不同的部分.
(3)Include
很多模型都是已宏的形式进行定义, 并以最小集团分成很多个文件. 而最终的机器人描述就变得非常简单了. 下面摘录一个ur5的描述文件. 从中可以看出来xacro的强大优势. 在最后的示例中我们还能够看到, urdf文件也是能够直接导入进来的.
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="ur5" >
<xacro:include filename="$(find ur_description)/urdf/ur5/common.gazebo.xacro" />
<xacro:include filename="$(find ur_description)/urdf/ur5/ur5.urdf.xacro" />
<xacro:ur5_robot prefix="" joint_limited="false"/>
<link name="world" />
<joint name="world_joint" type="fixed">
<parent link="world" />
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
joint>
robot>
类似于C语言中的include, 先将该文件扩展到包含的位置. 但包含进来的文件很有可能只是一个参数宏的定义. 并没有被调用.\quad
举例说明打开新的终端,输入roslaunch urdf_demo display_xacro.launch,回车之后,发现所有的link和joint已经有在固定的位置上了,并且小车颜色和形状已经固定完成。
(4)数学运算
主体是俩个标签,joint和link标签,joint代表关节,link代表肢节。transmission代表变速器,他控制关节的转动,gazebo设置gazebo相关参数。官方文档:XML Specifications
<geometry>
<box> 盒子,长方体、正方体、立方体
<box size="${x} ${y} ${z}"/>
size属性包含盒子的三个边长。盒子的原点在中间。
<cylinder> 气缸,其实就是个圆柱体
<cylinder radius="0.02" length="0.3"/>
指定半径和长度。圆柱体的原点位于其中心。
<sphere> 球体
<sphere radius="0.05" />
指定半径。球体的原点位于其中心。
<mesh> 网格,导入通过其他建模软件建的dae文件
<mesh filename="package://hulu_gazebo/meshes/kinect.dae" />
由filename指定的trimesh元素,以及用于缩放网格的axis-aligned-bounding-box的可选比例。任何几何格式都是可以接受的,
但是特定的应用程序兼容性取决于实现。最佳的纹理和颜色支持的推荐格式是Collada .dae文件。不能在引用相同模型的机器之间传输网格文件。
它必须是本地文件。
geometry>
<material>
<color> (可选)
<color rgba="1 0.27 0 1"/>
rgba由一组代表红色/绿色/蓝色/ alpha的四个数字指定的材料的颜色,
每个数字的范围为[0,1]。
最后的那个参数是透明度,0全透明,1不透明
rgb(207 166 87 1) -> rgba(207/255 166/255 87/255 1)
<texture> (可选)
材质的纹理由文件名指定
material>
元素中的
元素,urdf模型才能在gazebo中正常工作,因为gazebo里使用的文件格式并不是urdf格式,而是将urdf转换为它自己独有的的SDF格式再进行仿真。尽管URDF在ROS中是一种有用且标准化的格式,但它们缺少许多功能,并且尚未进行更新以应对机器人技术的不断发展的需求。URDF只能单独指定单个机器人的运动学和动力学特性。URDF无法指定世界中机器人本身的姿势。它也不是通用的描述格式,因为它不能指定关节环(平行连接),并且缺乏摩擦和其他特性。此外,它不能指定不是机器人的东西,例如灯光,高度图等。
在实现方面,URDF语法大量使用XML属性破坏了正确的格式设置,这反过来又使URDF更加不灵活。也没有向后兼容的机制。
为了解决此问题,创建了一种称为仿真描述格式(SDF)的新格式
,供凉亭使用,以解决URDF的缺点。SDF是从世界级到机器人级的所有内容的完整描述。它具有可伸缩性,并易于添加和修改元素。SDF格式本身使用XML进行描述,这有助于使用简单的升级工具将旧版本迁移到新版本。它也是自我描述的。
作者的意图是使URDF尽可能完整地记录在凉亭中,并在凉亭中提供支持,但与读者相关的是要了解为什么存在两种格式以及两者都有缺点。如果在URDF中进行更多工作以将其更新为当前的机器人技术,那将是很好的。
- origin 这是惯性参考系相对于肢节参考系的姿势。
- 惯性参考系的原点必须位于重心。惯性基准帧的轴线做不需要与惯性的主轴对齐。
inertial>
<mass value="${m}" />
肢节的质量由此元素的value属性表示
<inertia ixx="${2*m*r*r/5}" ixy="0" ixz="0"
iyy="${2*m*r*r/5}" iyz="0"
izz="${2*m*r*r/5}" />
惯性矩阵
inertial>
<!-- Macro for inertia matrix -->
<!-- 立方体惯性矩阵 -->
<xacro:macro name="box_inertial_matrix" params="m l w h">
<inertial>
<mass value="${m}" />
<inertia ixx="${m*(h*h + l*l)/12}" ixy = "0" ixz = "0"
iyy="${m*(w*w + l*l)/12}" iyz= "0"
izz="${m*(w*w + h*h)/12}" />
</inertial>
</xacro:macro>
<!-- 球体惯性矩阵 -->
<xacro:macro name="sphere_inertial_matrix" params="m r">
<inertial>
<mass value="${m}" />
<inertia ixx="${2*m*r*r/5}" ixy="0" ixz="0"
iyy="${2*m*r*r/5}" iyz="0"
izz="${2*m*r*r/5}" />
</inertial>
</xacro:macro>
<!-- 圆柱体惯性矩阵 -->
<xacro:macro name="cylinder_inertial_matrix" params="m r h">
<inertial>
<mass value="${m}" />
<inertia ixx="${m*(3*r*r+h*h)/12}" ixy = "0" ixz = "0"
iyy="${m*(3*r*r+h*h)/12}" iyz = "0"
izz="${m*r*r/2}" />
</inertial>
</xacro:macro>
矩阵原理及计算方法:机器人的惯性、视觉、碰撞特征计算与表示
<collision>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<box size="0.1 0.1 0.01"/>
geometry>
collision>
这个元素是表明机器人的虚拟预留碰撞范围的,视觉上是绿色的范围是模型,但实际给肢节的碰撞范围比视觉效果大,碰撞范围是红框框,以避免机器人真的撞墙,不过经常为了简便,就直接复制一遍visual的origin、geometry就行了
这个我也不是很懂,大意就是为你的轮子的关节选择一种gazebo提供的电机进行驱动,然后电机会订阅cmd_vel话题去接收速度控制指令然后控制你绑定的关节按axis旋转轴转动。
1个
2 <type> transmission_interface / SimpleTransmission type>
3
4 <hardwareInterface> EffortJointInterface hardwareInterface>
5 joint>
6
7 <mechanicalReduction> 50 mechanicalReduction>
8 <hardwareInterface> EffortJointInterface hardwareInterface>
9 actuator>
10 transmission>
<transmission>
<type> (one occurrence)
指定传输类型。
<joint> (one or more occurrences)
变速箱所连接的关节。
<hardwareInterface> (one or more occurrences)
指定支持的联合空间硬件接口。
<actuator> (one or more occurrences)
变速器连接到的执行器。(电机)
<mechanicalReduction> (optional)
指定关节/执行器传动机构的机械减速。
<hardwareInterface> (optional) (one or more occurrences)
指定支持的联合空间硬件接口。
actuator>
transmission>
元素是URDF的扩展,用于指定在gazebo中进行仿真所需的其他属性。1.可选择的
标签添加方式
· 为<link>元素添加一个<gazebo>元素
1.将视觉颜色转换为凉亭格式
2.将Stl文件转换为dae文件以获得更好的纹理
3.添加传感器插件
· 为<joint>元素添加一个<gazebo>元素
1.设置适当的阻尼动力学
2.添加执行器控制插件
· 为<robot>元素添加一个<gazebo>元素
· 如果应该将机器人牢固地附加到world / base_link,请添加链接<link name="world"/>
差动驱动
说明:模型插件,为凉亭中的差动驱动机器人提供基本控制器。您需要一个定义明确的差动驱动器机器人才能使用此插件。
<gazebo>
<plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
<updateRate>${update_rate}updateRate>
<leftJoint>base_link_left_wheel_jointleftJoint>
<rightJoint>base_link_right_wheel_jointrightJoint>
<wheelSeparation>0.5380wheelSeparation>
<wheelDiameter>0.2410wheelDiameter>
<wheelAcceleration>1.0wheelAcceleration>
<wheelTorque>20wheelTorque>
<commandTopic>cmd_velcommandTopic>
<odometryTopic>odomodometryTopic>
<odometryFrame>odomodometryFrame>
<robotBaseFrame>base_footprintrobotBaseFrame>
<odometrySource>1odometrySource>
<publishWheelTF>truepublishWheelTF>
<publishOdom>truepublishOdom>
<publishWheelJointState>truepublishWheelJointState>
<legacyMode>falselegacyMode>
plugin>
gazebo>
插件使用具体教程:Tutorial: Using Gazebo plugins with ROS
<robot name="mbot" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:property name="M_PI" value="3.14159265354"/>
<xacro:property name="body_mass" value="20" />
<xacro:property name="body_radius" value="0.20"/>
<xacro:property name="body_length" value="0.16"/>
<xacro:property name="head_mass" value="5" />
<xacro:property name="head_radius" value="0.1"/>
<xacro:property name="wheel_mass" value="2" />
<xacro:property name="wheel_radius" value="0.06"/>
<xacro:property name="wheel_length" value="0.025"/>
<xacro:property name="wheel_joint_x" value="0.15"/>
<xacro:property name="wheel_joint_y" value="0.15"/>
<xacro:property name="wheel_joint_z" value="0.16"/>
<xacro:property name="caster_mass" value="0.5" />
<xacro:property name="caster_radius" value="0.06"/>
<xacro:property name="caster_joint_x" value="0.1"/>
<xacro:property name="caster_joint_y" value="0.1"/>
<xacro:property name="caster_joint_z" value="0.16"/>
<xacro:property name="ears_mass" value="0.02" />
<xacro:property name="ears_x" value="0.008" />
<xacro:property name="ears_y" value="0.008" />
<xacro:property name="ears_z" value="0.04" />
<xacro:property name="ears_joint_y" value="0.099"/>
<xacro:property name="ears_joint_z" value="0.02"/>
<xacro:property name="eye_mass" value="0.02" />
<xacro:property name="eye_radius" value="0.01" />
<xacro:property name="eye_joint_x" value="0.085"/>
<xacro:property name="eye_joint_y" value="0.05"/>
<xacro:property name="eye_joint_z" value="0.02"/>
<xacro:property name="eyeball_mass" value="0.02" />
<xacro:property name="eyeball_radius" value="0.0025" />
<xacro:property name="eyeball_joint_x" value="0.0095"/>
<material name="yellow">
<color rgba="1 0.4 0 1"/>
material>
<material name="black">
<color rgba="0 0 0 0.95"/>
material>
<material name="gray">
<color rgba="0.75 0.75 0.75 1"/>
material>
<material name="white">
<color rgba="1 1 1 1"/>
material>
<material name="orange">
<color rgba="1 0.27 0 1"/>
material>
<xacro:macro name="box_inertial_matrix" params="m l w h">
<inertial>
<mass value="${m}" />
inertial>
xacro:macro>
<xacro:macro name="sphere_inertial_matrix" params="m r">
<inertial>
<mass value="${m}" />
<inertia ixx="${2*m*r*r/5}" ixy="0" ixz="0"
iyy="${2*m*r*r/5}" iyz="0"
izz="${2*m*r*r/5}" />
inertial>
xacro:macro>
<xacro:macro name="cylinder_inertial_matrix" params="m r h">
<inertial>
<mass value="${m}" />
inertial>
xacro:macro>
<xacro:macro name="wheel" params="prefix reflect">
<joint name="${prefix}_wheel_joint" type="continuous">
<origin xyz="0 ${reflect*wheel_joint_y} ${-wheel_joint_z}" rpy="0 0 0"/>
<parent link="body_link"/>
<child link="${prefix}_wheel_link"/>
<axis xyz="0 1 0"/>
joint>
<link name="${prefix}_wheel_link">
<visual>
<origin xyz="0 0 0" rpy="${M_PI/2} 0 0" />
<geometry>
geometry>
<material name="gray" />
visual>
<collision>
<origin xyz="0 0 0" rpy="${M_PI/2} 0 0" />
<geometry>
geometry>
collision>
<cylinder_inertial_matrix m="${wheel_mass}" r="${wheel_radius}" h="${wheel_length}" />
link>
<gazebo reference="${prefix}_wheel_link">
<material>Gazebo/DarkGreymaterial>
gazebo>
<transmission name="${prefix}_wheel_joint_trans">
<type>transmission_interface/SimpleTransmissiontype>
<joint name="${prefix}_wheel_joint" >
<hardwareInterface>hardware_interface/VelocityJointInterfacehardwareInterface>
joint>
<actuator name="${prefix}_wheel_joint_motor">
<hardwareInterface>hardware_interface/VelocityJointInterfacehardwareInterface>
<mechanicalReduction>1mechanicalReduction>
actuator>
transmission>
xacro:macro>
<xacro:macro name="caster" params="prefix reflect">
<joint name="${prefix}_caster_joint" type="continuous">
<origin xyz="${reflect*caster_joint_x} 0 ${-caster_joint_z}" rpy="0 0 0"/>
<parent link="body_link"/>
<child link="${prefix}_caster_link"/>
<axis xyz="0 1 0"/>
joint>
<link name="${prefix}_caster_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<sphere radius="${caster_radius}" />
geometry>
<material name="black" />
visual>
<collision>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<sphere radius="${caster_radius}" />
geometry>
collision>
<sphere_inertial_matrix m="${caster_mass}" r="${caster_radius}" />
link>
<gazebo reference="${prefix}_caster_link">
<material>Gazebo/GreyTransparentmaterial>
gazebo>
xacro:macro>
<xacro:macro name="ears" params="prefix reflect" >
<joint name="${prefix}_ears_joint" type="fixed">
<origin xyz="0 ${reflect*ears_joint_y} ${ears_joint_z}" rpy="0 0 0" />
<parent link="head_link"/>
<child link="${prefix}_ears_link" />
joint>
<link name="${prefix}_ears_link">
<visual>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<box size="${ears_x} ${ears_y} ${ears_z}"/>
geometry>
<material name="yellow" />
visual>
<collision>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<box size="${ears_x} ${ears_y} ${ears_z}"/>
geometry>
collision>
<box_inertial_matrix m="${ears_mass}" l="${ears_x}" w="${ears_y}" h="${ears_z}" />
link>
<gazebo reference="${prefix}_ears_link">
<material>Gazebo/Orangematerial>
gazebo>
xacro:macro>
<xacro:macro name="eye" params="prefix reflect">
<joint name="${prefix}_eye_joint" type="fixed">
<origin xyz="${eye_joint_x} ${reflect*eye_joint_y} ${eye_joint_z}" rpy="0 0 0" />
<parent link="head_link"/>
<child link="${prefix}_eye_link" />
joint>
<link name="${prefix}_eye_link">
<visual>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<sphere radius="${eye_radius}" />
geometry>
<material name="white" />
visual>
<collision>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<sphere radius="${eye_radius}" />
geometry>
collision>
<sphere_inertial_matrix m="${eye_mass}" r="${eye_radius}" />
link>
<gazebo reference="${prefix}_eye_link">
<material>Gazebo/Whitematerial>
gazebo>
xacro:macro>
<xacro:macro name="eyeball" params="prefix">
<joint name="${prefix}_eyeball_link_joint" type="fixed">
<origin xyz="${eyeball_joint_x} 0 0" rpy="0 0 0" />
<parent link="${prefix}_eye_link"/>
<child link="${prefix}_eyeball_link" />
joint>
<link name="${prefix}_eyeball_link">
<visual>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<sphere radius="${eyeball_radius}"/>
geometry>
<material name="black" />
visual>
<collision>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<sphere radius="${eyeball_radius}"/>
geometry>
collision>
<sphere_inertial_matrix m="${0.02}" r="${eyeball_radius}" />
link>
<gazebo reference="${prefix}_eyeball_link">
<material>Gazebo/Blackmaterial>
gazebo>
xacro:macro>
<xacro:macro name="hulu_body_gazebo">
<link name="body_footprint">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<box size="0.001 0.001 0.001" />
geometry>
visual>
link>
<gazebo reference="body_footprint">
<turnGravityOff>falseturnGravityOff>
gazebo>
<joint name="body_footprint_joint" type="fixed">
<origin xyz="0 0 ${body_length/2 + caster_radius*2}" rpy="0 0 0" />
<parent link="body_footprint"/>
<child link="body_link" />
joint>
<link name="body_link">
<visual>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<sphere radius="${body_radius}"/>
geometry>
<material name="orange" />
visual>
<collision>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<sphere radius="${body_radius}"/>
geometry>
collision>
<sphere_inertial_matrix m="${body_mass}" r="${body_radius}" />
link>
<gazebo reference="body_link">
<material>Gazebo/RedBrightmaterial>
gazebo>
<joint name="body_link_joint" type="fixed">
<origin xyz="0 0 0.28" rpy="0 0 0" />
<parent link="body_link"/>
<child link="head_link" />
joint>
<link name="head_link">
<visual>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<sphere radius="${head_radius}"/>
geometry>
<material name="orange" />
visual>
<collision>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<sphere radius="${head_radius}"/>
geometry>
collision>
<sphere_inertial_matrix m="${head_mass}" r="${head_radius}" />
link>
<gazebo reference="head_link">
<material>Gazebo/RedBrightmaterial>
gazebo>
<joint name="hand_link_joint" type="fixed">
<origin xyz="0 -0.19 0.1" rpy="0 1.4 -1.5705" />
<parent link="body_link"/>
<child link="hand_link" />
joint>
<link name="hand_link">
<visual>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<cylinder radius="0.02" length="0.3"/>
geometry>
<material name="yellow" />
visual>
<collision>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<cylinder radius="0.02" length="0.3"/>
geometry>
collision>
<cylinder_inertial_matrix m="0.05" r="0.02" h="0.3"/>
link>
<gazebo reference="hand_link">
<material>Gazebo/RedBrightmaterial>
gazebo>
<joint name="palm_link_joint" type="fixed">
<origin xyz="0 0 0.2" rpy="1.75 0 1.5705" />
<parent link="hand_link"/>
<child link="palm_link" />
joint>
<link name="palm_link">
<visual>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<box size="0.1 0.1 0.01"/>
geometry>
<material name="yellow" />
visual>
<collision>
<origin xyz=" 0 0 0" rpy="0 0 0" />
<geometry>
<box size="0.1 0.1 0.01"/>
geometry>
collision>
<box_inertial_matrix m="0.1" l="0.1" w="0.1" h="0.01" />
link>
<gazebo reference="palm_link">
<material>Gazebo/RedBrightmaterial>
gazebo>
<wheel prefix="left" reflect="-1"/>
<wheel prefix="right" reflect="1"/>
<caster prefix="front" reflect="-1"/>
<caster prefix="back" reflect="1"/>
<eye prefix="left" reflect="-1" />
<eye prefix="right" reflect="1" />
<ears prefix="left" reflect="-1" />
<ears prefix="right" reflect="1" />
<eyeball prefix="left"/>
<eyeball prefix="right"/>
<gazebo>
<plugin name="differential_drive_controller"
filename="libgazebo_ros_diff_drive.so">
<rosDebugLevel>DebugrosDebugLevel>
<publishWheelTF>truepublishWheelTF>
<robotNamespace>/robotNamespace>
<publishTf>1publishTf>
<publishWheelJointState>truepublishWheelJointState>
<alwaysOn>truealwaysOn>
<updateRate>100.0updateRate>
<legacyMode>truelegacyMode>
<leftJoint>left_wheel_jointleftJoint>
<rightJoint>right_wheel_jointrightJoint>
<wheelSeparation>${wheel_joint_y*2}wheelSeparation>
<wheelDiameter>${2*wheel_radius}wheelDiameter>
<broadcastTF>1broadcastTF>
<wheelTorque>30wheelTorque>
<wheelAcceleration>1.8wheelAcceleration>
<commandTopic>cmd_velcommandTopic>
<odometryFrame>odomodometryFrame>
<odometryTopic>odomodometryTopic>
<robotBaseFrame>body_footprintrobotBaseFrame>
plugin>
gazebo>
xacro:macro>
robot>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="camera">
<xacro:macro name="usb_camera" params="prefix:=camera">
<link name="${prefix}_link">
<inertial>
<mass value="0.1" />
<origin xyz="0 0 0" />
<inertia ixx="0.01" ixy="0.0" ixz="0.0"
iyy="0.01" iyz="0.0"
izz="0.01" />
inertial>
<visual>
<origin xyz=" 0 0 0 " rpy="0 0 0" />
<geometry>
<box size="0.01 0.02 0.02" />
geometry>
<material name="black"/>
visual>
<collision>
<origin xyz="0.0 0.0 0.0" rpy="0 0 0" />
<geometry>
<box size="0.01 0.02 0.02" />
geometry>
collision>
link>
<gazebo reference="${prefix}_link">
<material>Gazebo/Blackmaterial>
gazebo>
<gazebo reference="${prefix}_link">
<sensor type="camera" name="camera_node">
<update_rate>30.0update_rate>
<camera name="head">
<horizontal_fov>1.3962634horizontal_fov>
<image>
<width>1280width>
<height>720height>
<format>R8G8B8format>
image>
<clip>
<near>0.02near>
<far>300far>
clip>
<noise>
<type>gaussiantype>
<mean>0.0mean>
<stddev>0.007stddev>
noise>
camera>
<plugin name="gazebo_camera" filename="libgazebo_ros_camera.so">
<alwaysOn>truealwaysOn>
<updateRate>0.0updateRate>
<cameraName>/cameracameraName>
<imageTopicName>image_rawimageTopicName>
<cameraInfoTopicName>camera_infocameraInfoTopicName>
<frameName>camera_linkframeName>
<hackBaseline>0.07hackBaseline>
<distortionK1>0.0distortionK1>
<distortionK2>0.0distortionK2>
<distortionK3>0.0distortionK3>
<distortionT1>0.0distortionT1>
<distortionT2>0.0distortionT2>
plugin>
sensor>
gazebo>
xacro:macro>
robot>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="kinect_camera">
<xacro:macro name="kinect_camera" params="prefix:=camera">
<link name="${prefix}_link">
<origin xyz="0 0 0" rpy="0 0 0"/>
<visual>
<origin xyz="0 0 0" rpy="0 0 ${M_PI/2}"/>
<geometry>
<mesh filename="package://hulu_gazebo/meshes/kinect.dae" />
geometry>
visual>
<collision>
<geometry>
<box size="0.07 0.3 0.09"/>
geometry>
collision>
link>
<joint name="${prefix}_optical_joint" type="fixed">
<origin xyz="0 0 0" rpy="-1.5708 0 -1.5708"/>
<parent link="${prefix}_link"/>
<child link="${prefix}_frame_optical"/>
joint>
<link name="${prefix}_frame_optical"/>
<gazebo reference="${prefix}_link">
<sensor type="depth" name="${prefix}">
<always_on>truealways_on>
<update_rate>20.0update_rate>
<camera>
<horizontal_fov>${60.0*M_PI/180.0}horizontal_fov>
<image>
<format>R8G8B8format>
<width>640width>
<height>480height>
image>
<clip>
<near>0.05near>
<far>8.0far>
clip>
camera>
<plugin name="kinect_${prefix}_controller" filename="libgazebo_ros_openni_kinect.so">
<cameraName>${prefix}cameraName>
<alwaysOn>truealwaysOn>
<updateRate>10updateRate>
<imageTopicName>rgb/image_rawimageTopicName>
<depthImageTopicName>depth/image_rawdepthImageTopicName>
<pointCloudTopicName>depth/pointspointCloudTopicName>
<cameraInfoTopicName>rgb/camera_infocameraInfoTopicName>
<depthImageCameraInfoTopicName>depth/camera_infodepthImageCameraInfoTopicName>
<frameName>${prefix}_frame_opticalframeName>
<baseline>0.1baseline>
<distortion_k1>0.0distortion_k1>
<distortion_k2>0.0distortion_k2>
<distortion_k3>0.0distortion_k3>
<distortion_t1>0.0distortion_t1>
<distortion_t2>0.0distortion_t2>
<pointCloudCutoff>0.4pointCloudCutoff>
plugin>
sensor>
gazebo>
xacro:macro>
robot>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="laser">
<xacro:macro name="rplidar" params="prefix:=laser">
<link name="${prefix}_link">
<inertial>
<mass value="0.1" />
<origin xyz="0 0 0" />
<inertia ixx="0.01" ixy="0.0" ixz="0.0"
iyy="0.01" iyz="0.0"
izz="0.01" />
inertial>
<visual>
<origin xyz=" 0 0 0 " rpy="0 0 0" />
<geometry>
<cylinder length="0.05" radius="0.005"/>
geometry>
<material name="black"/>
visual>
<collision>
<origin xyz="0.0 0.0 0.0" rpy="0 0 0" />
<geometry>
<cylinder length="0.06" radius="0.05"/>
geometry>
collision>
link>
<gazebo reference="${prefix}_link">
<material>Gazebo/Blackmaterial>
gazebo>
<gazebo reference="${prefix}_link">
<sensor type="ray" name="rplidar">
<pose>0 0 0 0 0 0pose>
<visualize>falsevisualize>
<update_rate>5.5update_rate>
<ray>
<scan>
<horizontal>
<samples>360samples>
<resolution>1resolution>
<min_angle>-3min_angle>
<max_angle>3max_angle>
horizontal>
scan>
<range>
<min>0.10min>
<max>6.0max>
<resolution>0.01resolution>
range>
<noise>
<type>gaussiantype>
<mean>0.0mean>
<stddev>0.01stddev>
noise>
ray>
<plugin name="gazebo_rplidar" filename="libgazebo_ros_laser.so">
<topicName>/scantopicName>
<frameName>laser_linkframeName>
plugin>
sensor>
gazebo>
xacro:macro>
robot>
<robot name="arm" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:include filename="$(find hulu_gazebo)/urdf/xacro/gazebo/hulu_base_description.xacro" />
<xacro:include filename="$(find hulu_gazebo)/urdf/xacro/sensors/camera_gazebo.xacro" />
<xacro:include filename="$(find hulu_gazebo)/urdf/xacro/sensors/lidar_gazebo.xacro" />
<xacro:include filename="$(find hulu_gazebo)/urdf/xacro/sensors/kinect_gazebo.xacro" />
<xacro:property name="camera_offset_x" value="0.082" />
<xacro:property name="camera_offset_y" value="0" />
<xacro:property name="camera_offset_z" value="0.06" />
<xacro:property name="lidar_offset_x" value="0" />
<xacro:property name="lidar_offset_y" value="0" />
<xacro:property name="lidar_offset_z" value="0.125" />
<xacro:property name="kinect_offset_x" value="0" />
<xacro:property name="kinect_offset_y" value="0" />
<xacro:property name="kinect_offset_z" value="-0.03" />
<joint name="camera_joint" type="fixed">
<origin xyz="${camera_offset_x} ${camera_offset_y} ${-camera_offset_z}" rpy="0 0.27483 0" />
<parent link="head_link"/>
<child link="camera_link"/>
joint>
<xacro:usb_camera prefix="camera"/>
<joint name="lidar_joint" type="fixed">
<origin xyz="${lidar_offset_x} ${lidar_offset_y} ${lidar_offset_z}" rpy="0 0 0" />
<parent link="head_link"/>
<child link="laser_link"/>
joint>
<xacro:rplidar prefix="laser"/>
<joint name="kinect_joint" type="fixed">
<origin xyz="${kinect_offset_x} ${kinect_offset_y} ${kinect_offset_z}" rpy="-3.14159 0 0" />
<parent link="palm_link"/>
<child link="kinect_link"/>
joint>
<xacro:kinect_camera prefix="kinect"/>
<hulu_body_gazebo/>
robot>
controllers: {
base_controller: {
type: diff_controller,
base_frame_id: body_footprint,
base_width: 0.26,
ticks_meter: 4100,
Kp: 12,
Kd: 12,
Ki: 0,
Ko: 50,
accel_limit: 1.0
}
}
Panels:
- Class: rviz/Displays
Help Height: 78
Name: Displays
Property Tree Widget:
Expanded:
- /Global Options1
- /Status1
- /Odometry1/Shape1
Splitter Ratio: 0.5
Tree Height: 631
- Class: rviz/Selection
Name: Selection
- Class: rviz/Tool Properties
Expanded:
- /2D Pose Estimate1
- /2D Nav Goal1
- /Publish Point1
Name: Tool Properties
Splitter Ratio: 0.588679016
- Class: rviz/Views
Expanded:
- /Current View1
Name: Views
Splitter Ratio: 0.5
- Class: rviz/Time
Experimental: false
Name: Time
SyncMode: 0
SyncSource: ""
Visualization Manager:
Class: ""
Displays:
- Alpha: 0.5
Cell Size: 1
Class: rviz/Grid
Color: 160; 160; 164
Enabled: true
省略以下没有营养的内容
<launch>
<arg name="model" default="$(find xacro)/xacro --inorder '$(find hulu_gazebo)/urdf/xacro/gazebo/hulu_with_sensors.xacro'" />
<arg name="gui" default="false" />
<param name="robot_description" command="$(arg model)" />
<param name="use_gui" value="$(arg gui)"/>
<node name="arbotix" pkg="arbotix_python" type="arbotix_driver" output="screen">
<rosparam file="$(find hulu_gazebo)/config/fake_hulu_arbotix.yaml" command="load" />
<param name="sim" value="true"/>
node>
<node 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 $(find hulu_gazebo)/config/hulu_arbotix.rviz" required="true" />
launch>
<launch>
<arg name="world_name" value="$(find hulu_gazebo)/worlds/maze.world"/>
<arg name="paused" default="false"/>
<arg name="use_sim_time" default="true"/>
<arg name="gui" default="true"/>
<arg name="headless" default="false"/>
<arg name="debug" default="false"/>
<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>
<param name="robot_description" command="$(find xacro)/xacro --inorder '$(find hulu_gazebo)/urdf/xacro/gazebo/hulu_with_sensors.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="robot_state_publisher" output="screen" >
<param name="publish_frequency" type="double" value="50.0" />
node>
<node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen"
args="-urdf -model hulu -param robot_description"/>
launch>
<launch>
<node name="hulu_teleop" pkg="hulu_gazebo" type="hulu_teleop.py" output="screen">
<param name="scale_linear" value="0.1" type="double"/>
<param name="scale_angular" value="0.4" type="double"/>
node>
launch>
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
from geometry_msgs.msg import Twist
import sys, select, termios, tty
msg = """
Control hulu!
---------------------------
Moving around:
u i o
j k l
m , .
q/z : increase/decrease max speeds by 10%
w/x : increase/decrease only linear speed by 10%
e/c : increase/decrease only angular speed by 10%
space key, k : force stop
anything else : stop smoothly
CTRL-C to quit
"""
moveBindings = {
'i':(1,0),
'o':(1,-1),
'j':(0,1),
'l':(0,-1),
'u':(1,1),
',':(-1,0),
'.':(-1,1),
'm':(-1,-1),
}
speedBindings={
'q':(1.1,1.1),
'z':(.9,.9),
'w':(1.1,1),
'x':(.9,1),
'e':(1,1.1),
'c':(1,.9),
}
def getKey():
tty.setraw(sys.stdin.fileno())
rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
if rlist:
key = sys.stdin.read(1)
else:
key = ''
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
return key
speed = .2
turn = 1
def vels(speed,turn):
return "currently:\tspeed %s\tturn %s " % (speed,turn)
if __name__=="__main__":
settings = termios.tcgetattr(sys.stdin)
rospy.init_node('hulu_teleop')
pub = rospy.Publisher('/cmd_vel', Twist, queue_size=5)
x = 0
th = 0
status = 0
count = 0
acc = 0.1
target_speed = 0
target_turn = 0
control_speed = 0
control_turn = 0
try:
print msg
print vels(speed,turn)
while(1):
key = getKey()
# 运动控制方向键(1:正方向,-1负方向)
if key in moveBindings.keys():
x = moveBindings[key][0]
th = moveBindings[key][1]
count = 0
# 速度修改键
elif key in speedBindings.keys():
speed = speed * speedBindings[key][0] # 线速度增加0.1倍
turn = turn * speedBindings[key][1] # 角速度增加0.1倍
count = 0
print vels(speed,turn)
if (status == 14):
print msg
status = (status + 1) % 15
# 停止键
elif key == ' ' or key == 'k' :
x = 0
th = 0
control_speed = 0
control_turn = 0
else:
count = count + 1
if count > 4:
x = 0
th = 0
if (key == '\x03'):
break
# 目标速度=速度值*方向值
target_speed = speed * x
target_turn = turn * th
# 速度限位,防止速度增减过快
if target_speed > control_speed:
control_speed = min( target_speed, control_speed + 0.02 )
elif target_speed < control_speed:
control_speed = max( target_speed, control_speed - 0.02 )
else:
control_speed = target_speed
if target_turn > control_turn:
control_turn = min( target_turn, control_turn + 0.1 )
elif target_turn < control_turn:
control_turn = max( target_turn, control_turn - 0.1 )
else:
control_turn = target_turn
# 创建并发布twist消息
twist = Twist()
twist.linear.x = control_speed;
twist.linear.y = 0;
twist.linear.z = 0
twist.angular.x = 0;
twist.angular.y = 0;
twist.angular.z = control_turn
pub.publish(twist)
except:
print e
finally:
twist = Twist()
twist.linear.x = 0; twist.linear.y = 0; twist.linear.z = 0
twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = 0
pub.publish(twist)
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
(1)直接启动
$ roslaunch hulu_gazebo arbotix_hulu_with_rviz.launch
(2)启动键盘控制节点
$ roslaunch hulu_gazebo hulu_teleop.launch
(1) 摄像头仿真
启动gazebo环境
$ roslaunch hulu_gazebo view_hulu_with_gazebo.launch
查看当前ROS计算图
$ rqt_graph
查看当前发布的话题
$ rostopic list
打开摄像头
$ rqt_image_view
打开键盘操控节点
$ roslaunch hulu_gazebo hulu_teleop.launch
(2) 激光雷达仿真
打开rviz
$ rosrun rviz rviz
固定坐标系选择laser_link肢节
添加一个LaserScan模块,订阅/scan话题
将激光点尺寸改大点方便看
键盘控制移动
由于我的激光雷达装在葫芦娃的头顶,所以比它头矮的物品他都扫描不到,这就很尴尬
(3) kinect仿真
把rviz关掉再重进比较快
固定坐标系选择kinect_link肢节
添加一个piontcloud2模块,订阅/kinect/depth/points话题
添加一个image模块,订阅/kinect/rgb/image_raw话题
键盘控制移动
查看当前ROS计算图
$ rqt_graph
测试发现这个葫芦机器人走路很不稳定,基本有坎或者撞墙就翻车,而且它的激光雷达扫描不到比自己矮的物体,调整激光雷达的扫描角度也扫不到,可能是被偷挡住了。所以又写了俩个机器人,一个叫阶梯机器人,一个叫雷达机器人,把他们的传感器都放在了低位置,这次就还行了。
stairs_sensor_lidar.xacro
这样摆放老是让激光雷达把后面俩个方块当成障碍物,所以还是把后面俩个东西去掉了好扫描一点
stairs_sensors.xacro
两个模型的名字取反了,别弄混
新的代码和演示视频:百度网盘
提取码:t9nn