系列文章目录
第一章 ROS空间创建、helloworld的实现、开启多个节点
第二章 话题通信
第三章 服务通信
第四章 参数服务器
第五章 常用指令
第六章 通信机制实操
第七章 ROS通信机制进阶(常用API、Python模块的导入)
第八章 元功能包、节点运行管理launch文件(teleop_twist安装方法)
第九章 重名问题、分布式通信
第十章-第一节 TF坐标变换(内含PyKDL 和PyInit__tf2功能缺失等解决)
第十章-第二节 TF坐标变换实操
第十章-第三节 rosbag、rqt工具箱
第十一章-第一节 机器人系统仿真(URDF相关)
第十一章-第二节 机器人系统仿真(Gazebo相关)
第十二章 机器人导航(仿真)
前言
现在大二,之前大一有幸参加了2021的国赛,很壮烈的拿了个江苏赛区的二等奖。但发现无人机这个题,真的是往堆钱上走了。不上ROS不行,现在来记录一下一个纯小白学习ROS的过程和遇到的问题。防止学弟、学妹们再走我走过的弯路。板子用的是学长给的Jetson Nano(4GB),版本是Ubuntu18.04(已配置好基础ROS所需配置)
一、URDF集成Gazebo
URDF 需要集成进 Rviz 或 Gazebo 才能显示可视化的机器人模型,前面已经介绍了URDF 与 Rviz 的集成,本节主要介绍:
- URDF 与 Gazebo 的基本集成流程;
- 如果要在 Gazebo 中显示机器人模型,URDF 需要做的一些额外配置;
- 关于Gazebo仿真环境的搭建。
1.URDF与Gazebo基本集成流程
URDF 与 Gazebo 集成流程与 Rviz 实现类似,主要步骤如下:
- 创建功能包,导入依赖项
- 编写 URDF 或 Xacro 文件
- 启动 Gazebo 并显示机器人模型
-
创建功能包
创建新功能包,导入依赖包: urdf、xacro、gazebo_ros、gazebo_ros_control、gazebo_plugins -
编写URDF文件
<!--
创建一个盒状机器人模型
-->
<robot name="mycar">
<link name="base_link">
<!-- 可视化部分 -->
<visual>
<geometry>
<box size="0.5 0.3 0.1" />
</geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="yellow">
<color rgba="0.5 0.3 0.0 0.5" />
</material>
</visual>
<!-- 1.连杆的碰撞属性 -->
<!-- 如果是标准几何体,直接复制visual 的geometry和origin即可-->
<collision>
<geometry>
<box size="0.5 0.3 0.1" />
</geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
</collision>
<!-- 2.连杆的惯性矩阵 -->
<inertial>
<!-- 设置重心的偏移 -->
<origin xyz="0 0 0" />
<!-- 设置质量 -->
<mass value="6" />
<!-- 在不同维度上的惯性值 -->
<inertia ixx="1" ixy="0" ixz="0" iyy="1" iyz="0" izz="1" />
</inertial>
</link>
<!-- gazebo有自己的颜色标签 -->
<gazebo reference="base_link">
<material>Gazebo/Red</material>
</gazebo>
</robot>
如果中文报错,将代码改成:
<robot name="mycar">
<link name="base_link">
<visual>
<geometry>
<box size="0.5 0.3 0.1" />
</geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="yellow">
<color rgba="0.5 0.3 0.0 0.5" />
</material>
</visual>
<collision>
<geometry>
<box size="0.5 0.3 0.1" />
</geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
</collision>
<inertial>
<origin xyz="0 0 0" />
<mass value="6" />
<inertia ixx="1" ixy="0" ixz="0" iyy="1" iyz="0" izz="1" />
</inertial>
</link>
<gazebo reference="base_link">
<material>Gazebo/Red</material>
</gazebo>
</robot>
- 启动Gazebo并显示模型
launch 文件实现:
<launch>
<!-- 1.需要在参数服务器中加载urdf -->
<param name="robot_description" textfile="$(find urdf02_gazebo)/urdf/demo01_helloworld.urdf" />
<!-- 2.启动 gazebo 仿真环境-->
<include file="$(find gazebo_ros)/launch/empty_world.launch" />
<!-- 3.在 gazebo 中显示机器人模型 -->
<!--
在 Gazebo 中加载一个机器人模型,该功能由 gazebo_ros 下的 spawn_model 提供:
-urdf 加载的是 urdf 文件
-model mycar 模型名称是 mycar
-param robot_description 从参数 robot_description 中载入模型
-x 模型载入的 x 坐标
-y 模型载入的 y 坐标
-z 模型载入的 z 坐标
-->
<node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description" />
</launch>
编译运行
打开一个命令行:
cd workspace
source ./devel/setup.bash
roslaunch urdf02_gazebo demo01_helloworld.launch
2.URDF集成Gazebo相关设置
较之于 rviz,gazebo在集成 URDF 时,需要做些许修改,比如:必须添加 collision 碰撞属性相关参数、必须添加 inertial 惯性矩阵相关参数,另外,如果直接移植 Rviz 中机器人的颜色设置是没有显示的,颜色设置也必须做相应的变更。
-
collision
如果机器人link是标准的几何体形状,和link的 visual 属性设置一致即可。 -
inertial
惯性矩阵的设置需要结合link的质量与外形参数动态生成,标准的球体、圆柱与立方体的惯性矩阵公式如下(已经封装为 xacro 实现):
球体惯性矩阵:质量m,半径r
<!-- Macro for inertia matrix -->
<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>
圆柱惯性矩阵:质量m,半径r,高h
<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>
立方体惯性矩阵:质量m,x方向上长度:l,y方向上w,z方向上高h
<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>
需要注意的是,原则上,除了 base_footprint
外,机器人的每个刚体部分都需要设置惯性矩阵,且惯性矩阵必须经计算得出,如果随意定义刚体部分的惯性矩阵,那么可能会导致机器人在 Gazebo 中出现抖动,移动等现象。
- 颜色设置
在 gazebo 中显示 link 的颜色,必须要使用指定的标签:
<gazebo reference="link节点名称">
<material>Gazebo/Blue</material>
</gazebo>
注意:material 标签中,设置的值区分大小写,颜色可以设置为 Red Blue Green Black …
3.URDF集成Gazebo实操
需求描述:
将之前的机器人模型(xacro版)显示在 gazebo 中
实现流程:
- 需要编写封装惯性矩阵算法的 xacro 文件
- 为机器人模型中的每一个 link 添加 collision 和 inertial 标签,并且重置颜色属性
- 在 launch 文件中启动 gazebo 并添加机器人模型
- 编写封装惯性矩阵算法的 xacro 文件
<robot name="base" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- Macro for inertia matrix -->
<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>
<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>
</robot>
- 复制相关 xacro 文件,并设置 collision inertial 以及 color 等参数
A.底盘 Xacro 文件
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:property name="footprint_radius" value="0.001" />
<!--1.添加 base_footprint-->
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="${footprint_radius}" />
</geometry>
</visual>
</link>
<xacro:property name="base_radius" value="0.1" />
<xacro:property name="base_length" value="0.08" />
<xacro:property name="base_mass" value="2" />
<xacro:property name="base_lidijianju" value="0.015" />
<xacro:property name="base_joint_z" value="${base_length/2+base_lidijianju}" />
<!--2.添加底盘-->
<!--底盘为圆柱状,半径 10cm,高 8cm.底盘离地间距为 1.5cm-->
<!--2-1.link-->
<link name="base_link">
<visual>
<geometry>
<cylinder radius="${base_radius}" length="${base_length}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="baselink_color">
<color rgba="1 0.5 0.2 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="${base_radius}" length="${base_length}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
</collision>
<!-- 调用惯性矩阵函数 -->
<xacro:cylinder_inertial_matrix m="${base_mass}" r="${base_radius}" h="${base_length}" />
</link>
<gazebo reference="base_link">
<material>Gazebo/Yellow</material>
</gazebo>
<!--2-2.joint-->
<joint name="link2footprint" type="fixed" >
<parent link="base_footprint" />
<child link="base_link" />
<!--车高0.08/2+离地间距0.015-->
<origin xyz="0 0 ${base_joint_z}" rpy="0 0 0" />
</joint>
<!-- 本质:相同的参数属性封装,不同的参数进行传参 -->
<xacro:property name="wheel_radius" value="0.0325" />
<xacro:property name="wheel_length" value="0.015" />
<xacro:property name="wheel_mass" value="0.05" />
<xacro:property name="PI" value="3.1415927" />
<xacro:property name="wheel_joint_z" value="${wheel_radius-base_joint_z}" />
<!-- 驱动轮 -->
<xacro:macro name="wheel_func" params="wheel_name flag">
<link name="${wheel_name}_wheel">
<visual>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_length}" />
</geometry>
<origin xyz="0 0 0" rpy="${PI/2} 0 0" />
<material name="${wheel_name}_wheel">
<color rgba="0 0 0 0.3" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_length}" />
</geometry>
<origin xyz="0 0 0" rpy="${PI/2} 0 0" />
</collision>
<xacro:cylinder_inertial_matrix m="${wheel_mass}" r="${wheel_radius}" h="${wheel_length}" />
</link>
<gazebo reference="${wheel_name}_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--3-2.joint-->
<joint name="${wheel_name}2link" type="continuous" >
<parent link="base_link" />
<child link="${wheel_name}_wheel" />
<!--
x 无偏移
y 车体半径
z 车轮半径0.0325-(车高0.08/2+离地间距0.015)
-->
<origin xyz="0 ${flag*0.1} ${wheel_joint_z}" rpy="0 0 0" />
<axis xyz="0 1 0" />
</joint>
</xacro:macro>
<xacro:wheel_func wheel_name="left" flag="1" />
<xacro:wheel_func wheel_name="right" flag="-1" />
<!--4.添加万向轮-->
<!--
形状: 球体
半径: 0.75 cm
颜色: 黑色
-->
<xacro:property name="small_wheel_radius" value="0.0075" />
<xacro:property name="small_wheel_mass" value="0.01" />
<xacro:property name="small_wheel_z" value="${small_wheel_radius-base_joint_z}" />
<xacro:macro name="small_wheel_func" params="small_wheel_name flag" >
<!--4-1.link-->
<link name="${small_wheel_name}_wheel">
<visual>
<geometry>
<sphere radius="${small_wheel_radius}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="${small_wheel_name}_wheel">
<color rgba="0 0 0 0.3" />
</material>
</visual>
<collision>
<geometry>
<sphere radius="${small_wheel_radius}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
</collision>
<xacro:sphere_inertial_matrix m="${small_wheel_mass}" r="${small_wheel_radius}" />
</link>
<gazebo reference="${small_wheel_name}_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--4-2.joint-->
<joint name="${small_wheel_name}2link" type="continuous" >
<parent link="base_link" />
<child link="${small_wheel_name}_wheel" />
<!--
x 万向轮是在车子下面放置的,取值为:(0,半径)
y 0
z 车轮半径0.0075-(车高0.08/2+离地间距0.015)
-->
<origin xyz="${flag*0.08} 0 ${small_wheel_z}" rpy="0 0 0" />
<axis xyz="0 1 0" />
</joint>
</xacro:macro>
<xacro:small_wheel_func small_wheel_name="front" flag="1" />
<xacro:small_wheel_func small_wheel_name="back" flag="-1" />
</robot>
B.摄像头 Xacro 文件
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 摄像头部件 -->
<!-- 1.参数 -->
<!--
参数:
连杆属性:厚度、宽度、高度
关节属性:x y z
-->
<xacro:property name="camera_length" value="0.02" /> <!--houdu x-->
<xacro:property name="camera_width" value="0.05" /> <!--kuandu y-->
<xacro:property name="camera_height" value="0.05" /> <!--height z-->
<xacro:property name="camera_mass" value="0.01" />
<xacro:property name="joint_camera_x" value="0.08" />
<xacro:property name="joint_camera_y" value="0" />
<xacro:property name="joint_camera_z" value="${(camera_height+base_length)/2}" />
<!-- 2.设计连杆和关节 -->
<link name="camera">
<visual>
<geometry>
<box size="${camera_length} ${camera_width} ${camera_height}" />
</geometry>
<material name="black">
<color rgba="0 0 0 0.8" />
</material>
</visual>
<collision>
<geometry>
<box size="${camera_length} ${camera_width} ${camera_height}" />
</geometry>
</collision>
<xacro:Box_inertial_matrix m="${camera_mass}" l="${camera_length}" w="${camera_width}" h="${camera_height}" />
</link>
<gazebo reference="camera">
<material>Gazebo/Blue</material>
</gazebo>
<joint name="camera2base" type="fixed">
<parent link="base_link" />
<child link="camera" />
<origin xyz="${joint_camera_x} ${joint_camera_y} ${joint_camera_z}" rpy="0 0 0" />
</joint>
</robot>
C.雷达 Xacro 文件
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 雷达部件 -->
<!--
参数:
1.支架
支架尺寸:半径0.01 高度0.15
关节偏移量:x y z
2.雷达
尺寸:半径0.03 高度0.05
关节偏移量:x y z
-->
<xacro:property name="support_radius" value="0.01" />
<xacro:property name="support_length" value="0.15" />
<xacro:property name="support_mass" value="0.1" />
<xacro:property name="laser_length" value="0.05" />
<xacro:property name="laser_radius" value="0.03" />
<xacro:property name="laser_mass" value="0.15" />
<xacro:property name="joint_support_x" value="0.0" />
<xacro:property name="joint_support_y" value="0.0" />
<xacro:property name="joint_support_z" value="${base_length / 2 + support_length / 2}" />
<xacro:property name="joint_laser_x" value="0.0" />
<xacro:property name="joint_laser_y" value="0.0" />
<xacro:property name="joint_laser_z" value="${support_length / 2 + laser_length / 2}" />
<!-- 1.支架 -->
<link name="support">
<visual>
<geometry>
<cylinder radius="${support_radius}" length="${support_length}" />
</geometry>
<material name="yellow">
<color rgba="0.8 0.5 0.0 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="${support_radius}" length="${support_length}" />
</geometry>
</collision>
<xacro:cylinder_inertial_matrix m="${support_mass}" r="${support_radius}" h="${support_length}" />
</link>
<gazebo reference="support">
<material>Gazebo/Gray</material>
</gazebo>
<joint name="support2base" type="fixed">
<parent link="base_link" />
<child link="support" />
<origin xyz="${joint_support_x} ${joint_support_y} ${joint_support_z}" rpy="0 0 0" />
</joint>
<!-- 2.雷达 -->
<link name="laser">
<visual>
<geometry>
<cylinder radius="${laser_radius}" length="${laser_length}" />
</geometry>
<material name="black">
<color rgba="0 0 0 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="${laser_radius}" length="${laser_length}" />
</geometry>
</collision>
<xacro:cylinder_inertial_matrix m="${laser_mass}" r="${laser_radius}" h="${laser_length}" />
</link>
<gazebo reference="laser">
<material>Gazebo/Black</material>
</gazebo>
<joint name="laser2support" type="fixed">
<parent link="support" />
<child link="laser" />
<origin xyz="${joint_laser_x} ${joint_laser_y} ${joint_laser_z}" rpy="0 0 0" />
</joint>
</robot>
D.组合底盘、摄像头与雷达的 Xacro 文件
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 包含惯性矩阵文件 -->
<xacro:include filename="head.xacro" />
<!--包含底盘、摄像头、雷达的xacro文件-->
<xacro:include filename="demo05_car_base.urdf.xacro" />
<xacro:include filename="demo06_car_camera.urdf.xacro" />
<xacro:include filename="demo07_car_laser.urdf.xacro" />
</robot>
打开一个命令行:
cd workspace/src/urdf02_gazebo/urdf
rosrun xacro xacro car.urdf.xacro > car.urdf
输出,并将输出文件中的中文去掉:
<?xml version="1.0" encoding="utf-8"?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from car.urdf.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<robot name="mycar">
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="0.001"/>
</geometry>
</visual>
</link>
<!--2-1.link-->
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.08" radius="0.1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="baselink_color">
<color rgba="1 0.5 0.2 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.08" radius="0.1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="2"/>
<inertia ixx="0.00606666666667" ixy="0" ixz="0" iyy="0.00606666666667" iyz="0" izz="0.01"/>
</inertial>
</link>
<gazebo reference="base_link">
<material>Gazebo/Yellow</material>
</gazebo>
<!--2-2.joint-->
<joint name="link2footprint" type="fixed">
<parent link="base_footprint"/>
<child link="base_link"/>
<origin rpy="0 0 0" xyz="0 0 0.055"/>
</joint>
<link name="left_wheel">
<visual>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="left_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.05"/>
<inertia ixx="1.4140625e-05" ixy="0" ixz="0" iyy="1.4140625e-05" iyz="0" izz="2.640625e-05"/>
</inertial>
</link>
<gazebo reference="left_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--3-2.joint-->
<joint name="left2link" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin rpy="0 0 0" xyz="0 0.1 -0.0225"/>
<axis xyz="0 1 0"/>
</joint>
<link name="right_wheel">
<visual>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="right_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.05"/>
<inertia ixx="1.4140625e-05" ixy="0" ixz="0" iyy="1.4140625e-05" iyz="0" izz="2.640625e-05"/>
</inertial>
</link>
<gazebo reference="right_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--3-2.joint-->
<joint name="right2link" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin rpy="0 0 0" xyz="0 -0.1 -0.0225"/>
<axis xyz="0 1 0"/>
</joint>
<!--4-1.link-->
<link name="front_wheel">
<visual>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="front_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.25e-07" ixy="0" ixz="0" iyy="2.25e-07" iyz="0" izz="2.25e-07"/>
</inertial>
</link>
<gazebo reference="front_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--4-2.joint-->
<joint name="front2link" type="continuous">
<parent link="base_link"/>
<child link="front_wheel"/>
<origin rpy="0 0 0" xyz="0.08 0 -0.0475"/>
<axis xyz="0 1 0"/>
</joint>
<!--4-1.link-->
<link name="back_wheel">
<visual>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="back_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.25e-07" ixy="0" ixz="0" iyy="2.25e-07" iyz="0" izz="2.25e-07"/>
</inertial>
</link>
<gazebo reference="back_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--4-2.joint-->
<joint name="back2link" type="continuous">
<parent link="base_link"/>
<child link="back_wheel"/>
<origin rpy="0 0 0" xyz="-0.08 0 -0.0475"/>
<axis xyz="0 1 0"/>
</joint>
<link name="camera">
<visual>
<geometry>
<box size="0.02 0.05 0.05"/>
</geometry>
<material name="black">
<color rgba="0 0 0 0.8"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.02 0.05 0.05"/>
</geometry>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.41666666667e-06" ixy="0" ixz="0" iyy="2.41666666667e-06" iyz="0" izz="4.16666666667e-06"/>
</inertial>
</link>
<gazebo reference="camera">
<material>Gazebo/Blue</material>
</gazebo>
<joint name="camera2base" type="fixed">
<parent link="base_link"/>
<child link="camera"/>
<origin rpy="0 0 0" xyz="0.08 0 0.065"/>
</joint>
<link name="support">
<visual>
<geometry>
<cylinder length="0.15" radius="0.01"/>
</geometry>
<material name="yellow">
<color rgba="0.8 0.5 0.0 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.15" radius="0.01"/>
</geometry>
</collision>
<inertial>
<mass value="0.1"/>
<inertia ixx="0.00019" ixy="0" ixz="0" iyy="0.00019" iyz="0" izz="5e-06"/>
</inertial>
</link>
<gazebo reference="support">
<material>Gazebo/Gray</material>
</gazebo>
<joint name="support2base" type="fixed">
<parent link="base_link"/>
<child link="support"/>
<origin rpy="0 0 0" xyz="0.0 0.0 0.115"/>
</joint>
<link name="laser">
<visual>
<geometry>
<cylinder length="0.05" radius="0.03"/>
</geometry>
<material name="black">
<color rgba="0 0 0 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.05" radius="0.03"/>
</geometry>
</collision>
<inertial>
<mass value="0.15"/>
<inertia ixx="6.5e-05" ixy="0" ixz="0" iyy="6.5e-05" iyz="0" izz="6.75e-05"/>
</inertial>
</link>
<gazebo reference="laser">
<material>Gazebo/Black</material>
</gazebo>
<joint name="laser2support" type="fixed">
<parent link="support"/>
<child link="laser"/>
<origin rpy="0 0 0" xyz="0.0 0.0 0.1"/>
</joint>
</robot>
- 在 gazebo 中执行
launch 文件:
<launch>
<!-- 1.需要在参数服务器中加载urdf -->
<param name="robot_description" textfile="$(find urdf02_gazebo)/urdf/car.urdf" />
<!-- 2.启动 gazebo 仿真环境-->
<include file="$(find gazebo_ros)/launch/empty_world.launch" />
<!-- 3.在 gazebo 中显示机器人模型 -->
<!--
在 Gazebo 中加载一个机器人模型,该功能由 gazebo_ros 下的 spawn_model 提供:
-urdf 加载的是 urdf 文件
-model mycar 模型名称是 mycar
-param robot_description 从参数 robot_description 中载入模型
-x 模型载入的 x 坐标
-y 模型载入的 y 坐标
-z 模型载入的 z 坐标
-->
<node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description" />
</launch>
打开一个命令行:
cd workspace
source ./devel/setup.bash
roslaunch urdf02_gazebo demo02_car.launch
4.Gazebo仿真环境搭建
到目前为止,我们已经可以将机器人模型显示在 Gazebo 之中了,但是当前默认情况下,在 Gazebo 中机器人模型是在 empty world 中,并没有类似于房间、家具、道路、树木… 之类的仿真物,如何在 Gazebo 中创建仿真环境呢?
Gazebo 中创建仿真实现方式有两种:
方式1: 直接添加内置组件创建仿真环境
方式2: 手动绘制仿真环境(更为灵活)
也还可以直接下载使用官方或第三方提高的仿真环境插件。
在功能包下新建worlds文件夹,导入仿真环境
launch文件对于代码:
<launch>
<!-- 1.需要在参数服务器中加载urdf -->
<param name="robot_description" textfile="$(find urdf02_gazebo)/urdf/car.urdf" />
<!-- 2.启动 gazebo 仿真环境-->
<include file="$(find gazebo_ros)/launch/empty_world.launch" >
<arg name="world_name" value="$(find urdf02_gazebo)/worlds/box_house.world" />
</include>
<!-- 3.在 gazebo 中显示机器人模型 -->
<!--
在 Gazebo 中加载一个机器人模型,该功能由 gazebo_ros 下的 spawn_model 提供:
-urdf 加载的是 urdf 文件
-model mycar 模型名称是 mycar
-param robot_description 从参数 robot_description 中载入模型
-x 模型载入的 x 坐标
-y 模型载入的 y 坐标
-z 模型载入的 z 坐标
-->
<node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description" />
</launch>
二、URDF、Gazebo与Rviz综合应用
关于URDF(Xacro)、Rviz 和 Gazebo 三者的关系,前面已有阐述: URDF 用于创建机器人模型、Rviz 可以显示机器人感知到的环境信息,Gazebo 用于仿真,可以模拟外界环境,以及机器人的一些传感器,如何在 Gazebo 中运行这些传感器,并显示这些传感器的数据(机器人的视角)呢?本节主要介绍的重点就是将三者结合:通过 Gazebo 模拟机器人的传感器,然后在 Rviz 中显示这些传感器感知到的数据。主要内容包括:
- 运动控制以及里程计信息显示
- 雷达信息仿真以及显示
- 摄像头信息仿真以及显示
- kinect 信息仿真以及显示
1.机器人运动控制以及里程计信息显示
gazebo 中已经可以正常显示机器人模型了,那么如何像在 rviz (Arbotix)中一样控制机器人运动呢?在此,需要涉及到ros中的组件: ros_control
。
-
ros_control 简介
场景:同一套 ROS 程序,如何部署在不同的机器人系统上,比如:开发阶段为了提高效率是在仿真平台上测试的,部署时又有不同的实体机器人平台,不同平台的实现是有差异的,如何保证 ROS 程序的可移植性?ROS 内置的解决方式是 ros_control。
ros_control:是一组软件包,它包含了控制器接口,控制器管理器,传输和硬件接口。ros_control 是一套机器人控制的中间件,是一套规范,不同的机器人平台只要按照这套规范实现,那么就可以保证 与ROS 程序兼容,通过这套规范,实现了一种可插拔的架构设计,大大提高了程序设计的效率与灵活性。
gazebo 已经实现了 ros_control 的相关接口,如果需要在 gazebo 中控制机器人运动,直接调用相关接口即可 -
运动控制实现流程(Gazebo)
- 已经创建完毕的机器人模型,编写一个单独的 xacro 文件,为机器人模型添加传动装置以及控制器
- 将此文件集成进xacro文件
- 启动 Gazebo 并发布 /cmd_vel 消息控制机器人运动
2.1 为 joint 添加传动装置以及控制器
两轮差速配置
<robot name="my_car_move" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 传动实现:用于连接控制器与关节 -->
<xacro:macro name="joint_trans" params="joint_name">
<!-- Transmission is important to link the joints and the controller -->
<transmission name="${joint_name}_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="${joint_name}">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
</joint>
<actuator name="${joint_name}_motor">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
</xacro:macro>
<!-- 每一个驱动轮都需要配置传动装置 -->
<!-- 只有这里需要改 -->
<xacro:joint_trans joint_name="left2link" />
<xacro:joint_trans joint_name="right2link" />
<!-- 控制器 -->
<gazebo>
<plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
<rosDebugLevel>Debug</rosDebugLevel>
<publishWheelTF>true</publishWheelTF>
<robotNamespace>/</robotNamespace>
<publishTf>1</publishTf>
<publishWheelJointState>true</publishWheelJointState>
<alwaysOn>true</alwaysOn>
<updateRate>100.0</updateRate>
<legacyMode>true</legacyMode>
<leftJoint>left2link</leftJoint> <!-- 左轮 -->
<rightJoint>right2link</rightJoint> <!-- 右轮 -->
<wheelSeparation>${base_radius* 2}</wheelSeparation> <!-- 车轮间距 这里是底盘直径-->
<wheelDiameter>${wheel_radius * 2}</wheelDiameter> <!-- 车轮直径 -->
<broadcastTF>1</broadcastTF>
<wheelTorque>30</wheelTorque>
<wheelAcceleration>1.8</wheelAcceleration>
<commandTopic>cmd_vel</commandTopic> <!-- 运动控制话题 -->
<odometryFrame>odom</odometryFrame>
<odometryTopic>odom</odometryTopic> <!-- 里程计话题 -->
<robotBaseFrame>base_footprint</robotBaseFrame> <!-- 根坐标系 -->
</plugin>
</gazebo>
</robot>
2.2 xacro文件集成
最后还需要将上述 xacro 文件集成进总的机器人模型文件,代码示例如下:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 包含惯性矩阵文件 -->
<xacro:include filename="head.xacro" />
<!--包含底盘、摄像头、雷达的xacro文件-->
<xacro:include filename="demo05_car_base.urdf.xacro" />
<xacro:include filename="demo06_car_camera.urdf.xacro" />
<xacro:include filename="demo07_car_laser.urdf.xacro" />
<!-- 运动控制 -->
<xacro:include filename="gazebo/move.xacro" />
</robot>
打开一个命令行:
cd workspace/src/urdf02_gazebo/urdf
rosrun xacro xacro car.urdf.xacro > car.urdf
输出,并将输出文件中的中文去掉:
<?xml version="1.0" encoding="utf-8"?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from car.urdf.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<robot name="mycar">
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="0.001"/>
</geometry>
</visual>
</link>
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.08" radius="0.1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="baselink_color">
<color rgba="1 0.5 0.2 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.08" radius="0.1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="2"/>
<inertia ixx="0.00606666666667" ixy="0" ixz="0" iyy="0.00606666666667" iyz="0" izz="0.01"/>
</inertial>
</link>
<gazebo reference="base_link">
<material>Gazebo/Yellow</material>
</gazebo>
<!--2-2.joint-->
<joint name="link2footprint" type="fixed">
<parent link="base_footprint"/>
<child link="base_link"/>
<origin rpy="0 0 0" xyz="0 0 0.055"/>
</joint>
<link name="left_wheel">
<visual>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="left_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.05"/>
<inertia ixx="1.4140625e-05" ixy="0" ixz="0" iyy="1.4140625e-05" iyz="0" izz="2.640625e-05"/>
</inertial>
</link>
<gazebo reference="left_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--3-2.joint-->
<joint name="left2link" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin rpy="0 0 0" xyz="0 0.1 -0.0225"/>
<axis xyz="0 1 0"/>
</joint>
<link name="right_wheel">
<visual>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="right_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.05"/>
<inertia ixx="1.4140625e-05" ixy="0" ixz="0" iyy="1.4140625e-05" iyz="0" izz="2.640625e-05"/>
</inertial>
</link>
<gazebo reference="right_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--3-2.joint-->
<joint name="right2link" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin rpy="0 0 0" xyz="0 -0.1 -0.0225"/>
<axis xyz="0 1 0"/>
</joint>
<!--4-1.link-->
<link name="front_wheel">
<visual>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="front_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.25e-07" ixy="0" ixz="0" iyy="2.25e-07" iyz="0" izz="2.25e-07"/>
</inertial>
</link>
<gazebo reference="front_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--4-2.joint-->
<joint name="front2link" type="continuous">
<parent link="base_link"/>
<child link="front_wheel"/>
<origin rpy="0 0 0" xyz="0.08 0 -0.0475"/>
<axis xyz="0 1 0"/>
</joint>
<!--4-1.link-->
<link name="back_wheel">
<visual>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="back_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.25e-07" ixy="0" ixz="0" iyy="2.25e-07" iyz="0" izz="2.25e-07"/>
</inertial>
</link>
<gazebo reference="back_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--4-2.joint-->
<joint name="back2link" type="continuous">
<parent link="base_link"/>
<child link="back_wheel"/>
<origin rpy="0 0 0" xyz="-0.08 0 -0.0475"/>
<axis xyz="0 1 0"/>
</joint>
<link name="camera">
<visual>
<geometry>
<box size="0.02 0.05 0.05"/>
</geometry>
<material name="black">
<color rgba="0 0 0 0.8"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.02 0.05 0.05"/>
</geometry>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.41666666667e-06" ixy="0" ixz="0" iyy="2.41666666667e-06" iyz="0" izz="4.16666666667e-06"/>
</inertial>
</link>
<gazebo reference="camera">
<material>Gazebo/Blue</material>
</gazebo>
<joint name="camera2base" type="fixed">
<parent link="base_link"/>
<child link="camera"/>
<origin rpy="0 0 0" xyz="0.08 0 0.065"/>
</joint>
<link name="support">
<visual>
<geometry>
<cylinder length="0.15" radius="0.01"/>
</geometry>
<material name="yellow">
<color rgba="0.8 0.5 0.0 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.15" radius="0.01"/>
</geometry>
</collision>
<inertial>
<mass value="0.1"/>
<inertia ixx="0.00019" ixy="0" ixz="0" iyy="0.00019" iyz="0" izz="5e-06"/>
</inertial>
</link>
<gazebo reference="support">
<material>Gazebo/Gray</material>
</gazebo>
<joint name="support2base" type="fixed">
<parent link="base_link"/>
<child link="support"/>
<origin rpy="0 0 0" xyz="0.0 0.0 0.115"/>
</joint>
<link name="laser">
<visual>
<geometry>
<cylinder length="0.05" radius="0.03"/>
</geometry>
<material name="black">
<color rgba="0 0 0 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.05" radius="0.03"/>
</geometry>
</collision>
<inertial>
<mass value="0.15"/>
<inertia ixx="6.5e-05" ixy="0" ixz="0" iyy="6.5e-05" iyz="0" izz="6.75e-05"/>
</inertial>
</link>
<gazebo reference="laser">
<material>Gazebo/Black</material>
</gazebo>
<joint name="laser2support" type="fixed">
<parent link="support"/>
<child link="laser"/>
<origin rpy="0 0 0" xyz="0.0 0.0 0.1"/>
</joint>
<!-- Transmission is important to link the joints and the controller -->
<transmission name="left2link_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="left2link">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
</joint>
<actuator name="left2link_motor">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
<!-- Transmission is important to link the joints and the controller -->
<transmission name="right2link_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="right2link">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
</joint>
<actuator name="right2link_motor">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
<gazebo>
<plugin filename="libgazebo_ros_diff_drive.so" name="differential_drive_controller">
<rosDebugLevel>Debug</rosDebugLevel>
<publishWheelTF>true</publishWheelTF>
<robotNamespace>/</robotNamespace>
<publishTf>1</publishTf>
<publishWheelJointState>true</publishWheelJointState>
<alwaysOn>true</alwaysOn>
<updateRate>100.0</updateRate>
<legacyMode>true</legacyMode>
<leftJoint>left2link</leftJoint>
<rightJoint>right2link</rightJoint>
<wheelSeparation>0.2</wheelSeparation>
<wheelDiameter>0.065</wheelDiameter>
<broadcastTF>1</broadcastTF>
<wheelTorque>30</wheelTorque>
<wheelAcceleration>1.8</wheelAcceleration>
<commandTopic>cmd_vel</commandTopic>
<odometryFrame>odom</odometryFrame>
<odometryTopic>odom</odometryTopic>
<robotBaseFrame>base_footprint</robotBaseFrame>
</plugin>
</gazebo>
</robot>
2.3 启动 gazebo并控制机器人运动
launch文件:
<launch>
<!-- 1.需要在参数服务器中加载urdf -->
<param name="robot_description" textfile="$(find urdf02_gazebo)/urdf/car.urdf" />
<!-- 2.启动 gazebo 仿真环境-->
<include file="$(find gazebo_ros)/launch/empty_world.launch" >
<arg name="world_name" value="$(find urdf02_gazebo)/worlds/box_house.world" />
</include>
<!-- 3.在 gazebo 中显示机器人模型 -->
<!--
在 Gazebo 中加载一个机器人模型,该功能由 gazebo_ros 下的 spawn_model 提供:
-urdf 加载的是 urdf 文件
-model mycar 模型名称是 mycar
-param robot_description 从参数 robot_description 中载入模型
-x 模型载入的 x 坐标
-y 模型载入的 y 坐标
-z 模型载入的 z 坐标
-->
<node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description" />
</launch>
打开一个命令行:
cd workspace
source ./devel/setup.bash
roslaunch urdf02_gazebo demo03_env.launch
启动 launch 文件,使用 topic list 查看话题列表,会发现多了 /cmd_vel
然后发布 cmd_vel
消息控制即可
使用命令控制(或者可以编写单独的节点控制)
新打开一个命令行:rosrun teleop_twist_keyboard teleop_twist_keyboard.py
如果发现没安装这个包的话,输入:sudo apt-get install ros-melodic-teleop-twist-keyboard
安装,注意版本。
- Rviz查看里程计信息
在 Gazebo 的仿真环境中,机器人的里程计信息以及运动朝向等信息是无法获取的,可以通过 Rviz 显示机器人的里程计信息以及运动朝向
里程计: 机器人相对出发点坐标系的位姿状态(X 坐标 Y 坐标 Z坐标以及朝向)。
3.1启动 Rviz
launch 文件:
<launch>
<!--2.启动rviz-->
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" />
<!--3.添加关节状态发布节点-->
<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
<!--4.添加机器人状态发布节点-->
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
</launch>
打开一个命令行:
cd workspace
source ./devel/setup.bash
roslaunch urdf02_gazebo demo03_env.launch
打开一个命令行:
cd workspace
source ./devel/setup.bash
roslaunch urdf02_gazebo demo04_sensor.launch
打开一个命令行:rosrun teleop_twist_keyboard teleop_twist_keyboard.py
2.雷达信息仿真以及显示
通过 Gazebo 模拟激光雷达传感器,并在 Rviz 中显示激光数据。
实现流程:
雷达仿真基本流程:
-
已经创建完毕的机器人模型,编写一个单独的 xacro 文件,为机器人模型添加雷达配置;
-
将此文件集成进xacro文件;
-
启动 Gazebo,使用 Rviz 显示雷达信息。
- Gazebo 仿真雷达
1.1 新建 Xacro 文件,配置雷达传感器信息
<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 雷达 -->
<!-- reference为机器人模型里雷达link的名称 -->
<gazebo reference="laser">
<!-- <sensor type="ray"雷达类型 name="rplidar"雷达名字> -->
<sensor type="ray" name="rplidar">
<!-- 偏移量 欧拉角度 -->
<pose>0 0 0 0 0 0</pose>
<!-- 如果设置为true会在gazebo显示雷达射线 -->
<visualize>true</visualize>
<!-- 雷达射线更新的频率,每秒5.5次 -->
<update_rate>5.5</update_rate>
<ray>
<scan>
<horizontal>
<!-- 雷达旋转一周,采样多少个点 ,即发射多少根射线-->
<samples>360</samples>
<!-- 分辨率,一个整数n,每n个射线里有多少1个测距 -->
<resolution>1</resolution>
<!-- 设置雷达的采样范围 左右各3弧度即为采样范围 -->
<!-- 根据自己雷达的采样范围,来设置 -->
<min_angle>-3</min_angle>
<max_angle>3</max_angle>
</horizontal>
</scan>
<!-- 采样距离为0.1m-30m有效 -->
<range>
<min>0.10</min>
<max>30.0</max>
<!-- 精度为0.01m -->
<resolution>0.01</resolution>
</range>
<!-- 高斯噪音 为了仿真 -->
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.01</stddev>
</noise>
</ray>
<plugin name="gazebo_rplidar" filename="libgazebo_ros_laser.so">
<topicName>/scan</topicName>
<frameName>laser</frameName>
</plugin>
</sensor>
</gazebo>
</robot>
1.2 xacro 文件集成
将步骤1的 Xacro 文件集成进总的机器人模型文件,代码示例如下:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 包含惯性矩阵文件 -->
<xacro:include filename="head.xacro" />
<!--包含底盘、摄像头、雷达的xacro文件-->
<xacro:include filename="demo05_car_base.urdf.xacro" />
<xacro:include filename="demo06_car_camera.urdf.xacro" />
<xacro:include filename="demo07_car_laser.urdf.xacro" />
<!-- 运动控制 -->
<xacro:include filename="gazebo/move.xacro" />
<!-- 雷达 -->
<xacro:include filename="gazebo/laser.xacro" />
</robot>
打开一个命令行:
cd workspace/src/urdf02_gazebo/urdf
rosrun xacro xacro car.urdf.xacro > car.urdf
输出,并将输出文件中的中文去掉:
<?xml version="1.0" encoding="utf-8"?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from car.urdf.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<robot name="mycar">
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="0.001"/>
</geometry>
</visual>
</link>
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.08" radius="0.1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="baselink_color">
<color rgba="1 0.5 0.2 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.08" radius="0.1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="2"/>
<inertia ixx="0.00606666666667" ixy="0" ixz="0" iyy="0.00606666666667" iyz="0" izz="0.01"/>
</inertial>
</link>
<gazebo reference="base_link">
<material>Gazebo/Yellow</material>
</gazebo>
<!--2-2.joint-->
<joint name="link2footprint" type="fixed">
<parent link="base_footprint"/>
<child link="base_link"/>
<origin rpy="0 0 0" xyz="0 0 0.055"/>
</joint>
<link name="left_wheel">
<visual>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="left_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.05"/>
<inertia ixx="1.4140625e-05" ixy="0" ixz="0" iyy="1.4140625e-05" iyz="0" izz="2.640625e-05"/>
</inertial>
</link>
<gazebo reference="left_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--3-2.joint-->
<joint name="left2link" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin rpy="0 0 0" xyz="0 0.1 -0.0225"/>
<axis xyz="0 1 0"/>
</joint>
<link name="right_wheel">
<visual>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="right_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.05"/>
<inertia ixx="1.4140625e-05" ixy="0" ixz="0" iyy="1.4140625e-05" iyz="0" izz="2.640625e-05"/>
</inertial>
</link>
<gazebo reference="right_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--3-2.joint-->
<joint name="right2link" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin rpy="0 0 0" xyz="0 -0.1 -0.0225"/>
<axis xyz="0 1 0"/>
</joint>
<!--4-1.link-->
<link name="front_wheel">
<visual>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="front_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.25e-07" ixy="0" ixz="0" iyy="2.25e-07" iyz="0" izz="2.25e-07"/>
</inertial>
</link>
<gazebo reference="front_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--4-2.joint-->
<joint name="front2link" type="continuous">
<parent link="base_link"/>
<child link="front_wheel"/>
<origin rpy="0 0 0" xyz="0.08 0 -0.0475"/>
<axis xyz="0 1 0"/>
</joint>
<!--4-1.link-->
<link name="back_wheel">
<visual>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="back_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.25e-07" ixy="0" ixz="0" iyy="2.25e-07" iyz="0" izz="2.25e-07"/>
</inertial>
</link>
<gazebo reference="back_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--4-2.joint-->
<joint name="back2link" type="continuous">
<parent link="base_link"/>
<child link="back_wheel"/>
<origin rpy="0 0 0" xyz="-0.08 0 -0.0475"/>
<axis xyz="0 1 0"/>
</joint>
<link name="camera">
<visual>
<geometry>
<box size="0.02 0.05 0.05"/>
</geometry>
<material name="black">
<color rgba="0 0 0 0.8"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.02 0.05 0.05"/>
</geometry>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.41666666667e-06" ixy="0" ixz="0" iyy="2.41666666667e-06" iyz="0" izz="4.16666666667e-06"/>
</inertial>
</link>
<gazebo reference="camera">
<material>Gazebo/Blue</material>
</gazebo>
<joint name="camera2base" type="fixed">
<parent link="base_link"/>
<child link="camera"/>
<origin rpy="0 0 0" xyz="0.08 0 0.065"/>
</joint>
<link name="support">
<visual>
<geometry>
<cylinder length="0.15" radius="0.01"/>
</geometry>
<material name="yellow">
<color rgba="0.8 0.5 0.0 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.15" radius="0.01"/>
</geometry>
</collision>
<inertial>
<mass value="0.1"/>
<inertia ixx="0.00019" ixy="0" ixz="0" iyy="0.00019" iyz="0" izz="5e-06"/>
</inertial>
</link>
<gazebo reference="support">
<material>Gazebo/Gray</material>
</gazebo>
<joint name="support2base" type="fixed">
<parent link="base_link"/>
<child link="support"/>
<origin rpy="0 0 0" xyz="0.0 0.0 0.115"/>
</joint>
<link name="laser">
<visual>
<geometry>
<cylinder length="0.05" radius="0.03"/>
</geometry>
<material name="black">
<color rgba="0 0 0 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.05" radius="0.03"/>
</geometry>
</collision>
<inertial>
<mass value="0.15"/>
<inertia ixx="6.5e-05" ixy="0" ixz="0" iyy="6.5e-05" iyz="0" izz="6.75e-05"/>
</inertial>
</link>
<gazebo reference="laser">
<material>Gazebo/Black</material>
</gazebo>
<joint name="laser2support" type="fixed">
<parent link="support"/>
<child link="laser"/>
<origin rpy="0 0 0" xyz="0.0 0.0 0.1"/>
</joint>
<!-- Transmission is important to link the joints and the controller -->
<transmission name="left2link_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="left2link">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
</joint>
<actuator name="left2link_motor">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
<!-- Transmission is important to link the joints and the controller -->
<transmission name="right2link_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="right2link">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
</joint>
<actuator name="right2link_motor">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
<gazebo>
<plugin filename="libgazebo_ros_diff_drive.so" name="differential_drive_controller">
<rosDebugLevel>Debug</rosDebugLevel>
<publishWheelTF>true</publishWheelTF>
<robotNamespace>/</robotNamespace>
<publishTf>1</publishTf>
<publishWheelJointState>true</publishWheelJointState>
<alwaysOn>true</alwaysOn>
<updateRate>100.0</updateRate>
<legacyMode>true</legacyMode>
<leftJoint>left2link</leftJoint>
<rightJoint>right2link</rightJoint>
<wheelSeparation>0.2</wheelSeparation>
<wheelDiameter>0.065</wheelDiameter>
<broadcastTF>1</broadcastTF>
<wheelTorque>30</wheelTorque>
<wheelAcceleration>1.8</wheelAcceleration>
<commandTopic>cmd_vel</commandTopic>
<odometryFrame>odom</odometryFrame>
<odometryTopic>odom</odometryTopic>
<robotBaseFrame>base_footprint</robotBaseFrame>
</plugin>
</gazebo>
<gazebo reference="laser">
<sensor name="rplidar" type="ray">
<pose>0 0 0 0 0 0</pose>
<visualize>true</visualize>
<update_rate>5.5</update_rate>
<ray>
<scan>
<horizontal>
<samples>360</samples>
<resolution>1</resolution>
<min_angle>-3</min_angle>
<max_angle>3</max_angle>
</horizontal>
</scan>
<range>
<min>0.10</min>
<max>30.0</max>
<resolution>0.01</resolution>
</range>
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.01</stddev>
</noise>
</ray>
<plugin filename="libgazebo_ros_laser.so" name="gazebo_rplidar">
<topicName>/scan</topicName>
<frameName>laser</frameName>
</plugin>
</sensor>
</gazebo>
</robot>
打开一个命令行:
cd workspace
source ./devel/setup.bash
roslaunch urdf02_gazebo demo03_env.launch
打开一个命令行:
cd workspace
source ./devel/setup.bash
roslaunch urdf02_gazebo demo04_sensor.launch
3.摄像头信息仿真以及显示
通过 Gazebo 模拟摄像头传感器,并在 Rviz 中显示摄像头数据。
实现流程:
摄像头仿真基本流程:
已经创建完毕的机器人模型,编写一个单独的 xacro 文件,为机器人模型添加摄像头配置;
将此文件集成进xacro文件;
启动 Gazebo,使用 Rviz 显示摄像头信息。
- Gazebo 仿真摄像头
1.1 新建 Xacro 文件,配置摄像头传感器信息
<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 被引用的camera的link -->
<gazebo reference="camera">
<!-- 类型设置为 camara -->
<sensor type="camera" name="camera_node">
<update_rate>30.0</update_rate> <!-- 更新频率 -->
<!-- 摄像头基本信息设置 -->
<camera name="head">
<horizontal_fov>1.3962634</horizontal_fov>
<image>
<width>1280</width>
<height>720</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.02</near>
<far>300</far>
</clip>
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.007</stddev>
</noise>
</camera>
<!-- 核心插件 -->
<plugin name="gazebo_camera" filename="libgazebo_ros_camera.so">
<alwaysOn>true</alwaysOn>
<updateRate>0.0</updateRate>
<!-- 为你的摄像头生成一个工作空间 -->
<cameraName>/camera</cameraName>
<imageTopicName>image_raw</imageTopicName>
<cameraInfoTopicName>camera_info</cameraInfoTopicName>
<!-- 被引用的camera的link -->
<frameName>camera</frameName>
<hackBaseline>0.07</hackBaseline>
<distortionK1>0.0</distortionK1>
<distortionK2>0.0</distortionK2>
<distortionK3>0.0</distortionK3>
<distortionT1>0.0</distortionT1>
<distortionT2>0.0</distortionT2>
</plugin>
</sensor>
</gazebo>
</robot>
1.2 xacro 文件集成
将步骤1的 Xacro 文件集成进总的机器人模型文件,代码示例如下:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 包含惯性矩阵文件 -->
<xacro:include filename="head.xacro" />
<!--包含底盘、摄像头、雷达的xacro文件-->
<xacro:include filename="demo05_car_base.urdf.xacro" />
<xacro:include filename="demo06_car_camera.urdf.xacro" />
<xacro:include filename="demo07_car_laser.urdf.xacro" />
<!-- 运动控制 -->
<xacro:include filename="gazebo/move.xacro" />
<!-- 雷达 -->
<xacro:include filename="gazebo/laser.xacro" />
<!-- 摄像头 -->
<xacro:include filename="gazebo/camera.xacro" />
</robot>
打开一个命令行:
cd workspace/src/urdf02_gazebo/urdf
rosrun xacro xacro car.urdf.xacro > car.urdf
输出,并将输出文件中的中文去掉:
<?xml version="1.0" encoding="utf-8"?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from car.urdf.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<robot name="mycar">
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="0.001"/>
</geometry>
</visual>
</link>
<!--2-1.link-->
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.08" radius="0.1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="baselink_color">
<color rgba="1 0.5 0.2 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.08" radius="0.1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="2"/>
<inertia ixx="0.00606666666667" ixy="0" ixz="0" iyy="0.00606666666667" iyz="0" izz="0.01"/>
</inertial>
</link>
<gazebo reference="base_link">
<material>Gazebo/Yellow</material>
</gazebo>
<!--2-2.joint-->
<joint name="link2footprint" type="fixed">
<parent link="base_footprint"/>
<child link="base_link"/>
<origin rpy="0 0 0" xyz="0 0 0.055"/>
</joint>
<link name="left_wheel">
<visual>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="left_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.05"/>
<inertia ixx="1.4140625e-05" ixy="0" ixz="0" iyy="1.4140625e-05" iyz="0" izz="2.640625e-05"/>
</inertial>
</link>
<gazebo reference="left_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--3-2.joint-->
<joint name="left2link" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin rpy="0 0 0" xyz="0 0.1 -0.0225"/>
<axis xyz="0 1 0"/>
</joint>
<link name="right_wheel">
<visual>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="right_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.05"/>
<inertia ixx="1.4140625e-05" ixy="0" ixz="0" iyy="1.4140625e-05" iyz="0" izz="2.640625e-05"/>
</inertial>
</link>
<gazebo reference="right_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--3-2.joint-->
<joint name="right2link" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin rpy="0 0 0" xyz="0 -0.1 -0.0225"/>
<axis xyz="0 1 0"/>
</joint>
<!--4-1.link-->
<link name="front_wheel">
<visual>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="front_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.25e-07" ixy="0" ixz="0" iyy="2.25e-07" iyz="0" izz="2.25e-07"/>
</inertial>
</link>
<gazebo reference="front_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--4-2.joint-->
<joint name="front2link" type="continuous">
<parent link="base_link"/>
<child link="front_wheel"/>
<origin rpy="0 0 0" xyz="0.08 0 -0.0475"/>
<axis xyz="0 1 0"/>
</joint>
<!--4-1.link-->
<link name="back_wheel">
<visual>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="back_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.25e-07" ixy="0" ixz="0" iyy="2.25e-07" iyz="0" izz="2.25e-07"/>
</inertial>
</link>
<gazebo reference="back_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--4-2.joint-->
<joint name="back2link" type="continuous">
<parent link="base_link"/>
<child link="back_wheel"/>
<origin rpy="0 0 0" xyz="-0.08 0 -0.0475"/>
<axis xyz="0 1 0"/>
</joint>
<link name="camera">
<visual>
<geometry>
<box size="0.02 0.05 0.05"/>
</geometry>
<material name="black">
<color rgba="0 0 0 0.8"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.02 0.05 0.05"/>
</geometry>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.41666666667e-06" ixy="0" ixz="0" iyy="2.41666666667e-06" iyz="0" izz="4.16666666667e-06"/>
</inertial>
</link>
<gazebo reference="camera">
<material>Gazebo/Blue</material>
</gazebo>
<joint name="camera2base" type="fixed">
<parent link="base_link"/>
<child link="camera"/>
<origin rpy="0 0 0" xyz="0.08 0 0.065"/>
</joint>
<link name="support">
<visual>
<geometry>
<cylinder length="0.15" radius="0.01"/>
</geometry>
<material name="yellow">
<color rgba="0.8 0.5 0.0 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.15" radius="0.01"/>
</geometry>
</collision>
<inertial>
<mass value="0.1"/>
<inertia ixx="0.00019" ixy="0" ixz="0" iyy="0.00019" iyz="0" izz="5e-06"/>
</inertial>
</link>
<gazebo reference="support">
<material>Gazebo/Gray</material>
</gazebo>
<joint name="support2base" type="fixed">
<parent link="base_link"/>
<child link="support"/>
<origin rpy="0 0 0" xyz="0.0 0.0 0.115"/>
</joint>
<link name="laser">
<visual>
<geometry>
<cylinder length="0.05" radius="0.03"/>
</geometry>
<material name="black">
<color rgba="0 0 0 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.05" radius="0.03"/>
</geometry>
</collision>
<inertial>
<mass value="0.15"/>
<inertia ixx="6.5e-05" ixy="0" ixz="0" iyy="6.5e-05" iyz="0" izz="6.75e-05"/>
</inertial>
</link>
<gazebo reference="laser">
<material>Gazebo/Black</material>
</gazebo>
<joint name="laser2support" type="fixed">
<parent link="support"/>
<child link="laser"/>
<origin rpy="0 0 0" xyz="0.0 0.0 0.1"/>
</joint>
<!-- Transmission is important to link the joints and the controller -->
<transmission name="left2link_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="left2link">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
</joint>
<actuator name="left2link_motor">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
<!-- Transmission is important to link the joints and the controller -->
<transmission name="right2link_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="right2link">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
</joint>
<actuator name="right2link_motor">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
<gazebo>
<plugin filename="libgazebo_ros_diff_drive.so" name="differential_drive_controller">
<rosDebugLevel>Debug</rosDebugLevel>
<publishWheelTF>true</publishWheelTF>
<robotNamespace>/</robotNamespace>
<publishTf>1</publishTf>
<publishWheelJointState>true</publishWheelJointState>
<alwaysOn>true</alwaysOn>
<updateRate>100.0</updateRate>
<legacyMode>true</legacyMode>
<leftJoint>left2link</leftJoint>
<rightJoint>right2link</rightJoint>
<wheelSeparation>0.2</wheelSeparation>
<wheelDiameter>0.065</wheelDiameter>
<broadcastTF>1</broadcastTF>
<wheelTorque>30</wheelTorque>
<wheelAcceleration>1.8</wheelAcceleration>
<commandTopic>cmd_vel</commandTopic>
<odometryFrame>odom</odometryFrame>
<odometryTopic>odom</odometryTopic>
<robotBaseFrame>base_footprint</robotBaseFrame>
</plugin>
</gazebo>
<gazebo reference="laser">
<sensor name="rplidar" type="ray">
<pose>0 0 0 0 0 0</pose>
<visualize>true</visualize>
<update_rate>5.5</update_rate>
<ray>
<scan>
<horizontal>
<samples>360</samples>
<resolution>1</resolution>
<min_angle>-3</min_angle>
<max_angle>3</max_angle>
</horizontal>
</scan>
<range>
<min>0.10</min>
<max>30.0</max>
<resolution>0.01</resolution>
</range>
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.01</stddev>
</noise>
</ray>
<plugin filename="libgazebo_ros_laser.so" name="gazebo_rplidar">
<topicName>/scan</topicName>
<frameName>laser</frameName>
</plugin>
</sensor>
</gazebo>
<gazebo reference="camera">
<sensor name="camera_node" type="camera">
<update_rate>30.0</update_rate>
<camera name="head">
<horizontal_fov>1.3962634</horizontal_fov>
<image>
<width>1280</width>
<height>720</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.02</near>
<far>300</far>
</clip>
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.007</stddev>
</noise>
</camera>
<plugin filename="libgazebo_ros_camera.so" name="gazebo_camera">
<alwaysOn>true</alwaysOn>
<updateRate>0.0</updateRate>
<cameraName>/camera</cameraName>
<imageTopicName>image_raw</imageTopicName>
<cameraInfoTopicName>camera_info</cameraInfoTopicName>
<frameName>camera</frameName>
<hackBaseline>0.07</hackBaseline>
<distortionK1>0.0</distortionK1>
<distortionK2>0.0</distortionK2>
<distortionK3>0.0</distortionK3>
<distortionT1>0.0</distortionT1>
<distortionT2>0.0</distortionT2>
</plugin>
</sensor>
</gazebo>
</robot>
打开一个命令行:
cd workspace
source ./devel/setup.bash
roslaunch urdf02_gazebo demo03_env.launch
打开一个命令行:
cd workspace
source ./devel/setup.bash
roslaunch urdf02_gazebo demo04_sensor.launch
4.kinect信息仿真以及显示
通过 Gazebo 模拟kinect摄像头,并在 Rviz 中显示kinect摄像头数据。
实现流程:
kinect摄像头仿真基本流程:
- 已经创建完毕的机器人模型,编写一个单独的 xacro 文件,为机器人模型添加kinect摄像头配置;
- 将此文件集成进xacro文件;
- 启动 Gazebo,使用 Rviz 显示kinect摄像头信息。
- Gazebo仿真Kinect
1.1 新建 Xacro 文件,配置 kinetic传感器信息
<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
<gazebo reference="support">
<sensor type="depth" name="camera">
<always_on>true</always_on>
<update_rate>20.0</update_rate>
<camera>
<horizontal_fov>${60.0*PI/180.0}</horizontal_fov>
<image>
<format>R8G8B8</format>
<width>640</width>
<height>480</height>
</image>
<clip>
<near>0.05</near>
<far>8.0</far>
</clip>
</camera>
<plugin name="kinect_camera_controller" filename="libgazebo_ros_openni_kinect.so">
<cameraName>camera</cameraName>
<alwaysOn>true</alwaysOn>
<updateRate>10</updateRate>
<!-- 采集一般图像 -->
<imageTopicName>rgb/image_raw</imageTopicName>
<depthImageTopicName>depth/image_raw</depthImageTopicName>
<pointCloudTopicName>depth/points</pointCloudTopicName>
<cameraInfoTopicName>rgb/camera_info</cameraInfoTopicName>
<depthImageCameraInfoTopicName>depth/camera_info</depthImageCameraInfoTopicName>
<frameName>support</frameName>
<baseline>0.1</baseline>
<distortion_k1>0.0</distortion_k1>
<distortion_k2>0.0</distortion_k2>
<distortion_k3>0.0</distortion_k3>
<distortion_t1>0.0</distortion_t1>
<distortion_t2>0.0</distortion_t2>
<pointCloudCutoff>0.4</pointCloudCutoff>
</plugin>
</sensor>
</gazebo>
</robot>
1.2 xacro 文件集成
将步骤1的 Xacro 文件集成进总的机器人模型文件,代码示例如下:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 包含惯性矩阵文件 -->
<xacro:include filename="head.xacro" />
<!--包含底盘、摄像头、雷达的xacro文件-->
<xacro:include filename="demo05_car_base.urdf.xacro" />
<xacro:include filename="demo06_car_camera.urdf.xacro" />
<xacro:include filename="demo07_car_laser.urdf.xacro" />
<!-- 运动控制 -->
<xacro:include filename="gazebo/move.xacro" />
<!-- 雷达 -->
<xacro:include filename="gazebo/laser.xacro" />
<!-- 摄像头 -->
<xacro:include filename="gazebo/camera.xacro" />
<!-- kinect -->
<xacro:include filename="gazebo/kinect.xacro" />
</robot>
打开一个命令行:
cd workspace/src/urdf02_gazebo/urdf
rosrun xacro xacro car.urdf.xacro > car.urdf
输出,并将输出文件中的中文去掉:
<?xml version="1.0" encoding="utf-8"?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from car.urdf.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<robot name="mycar">
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="0.001"/>
</geometry>
</visual>
</link>
<!--2-1.link-->
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.08" radius="0.1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="baselink_color">
<color rgba="1 0.5 0.2 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.08" radius="0.1"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="2"/>
<inertia ixx="0.00606666666667" ixy="0" ixz="0" iyy="0.00606666666667" iyz="0" izz="0.01"/>
</inertial>
</link>
<gazebo reference="base_link">
<material>Gazebo/Yellow</material>
</gazebo>
<!--2-2.joint-->
<joint name="link2footprint" type="fixed">
<parent link="base_footprint"/>
<child link="base_link"/>
<origin rpy="0 0 0" xyz="0 0 0.055"/>
</joint>
<link name="left_wheel">
<visual>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="left_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.05"/>
<inertia ixx="1.4140625e-05" ixy="0" ixz="0" iyy="1.4140625e-05" iyz="0" izz="2.640625e-05"/>
</inertial>
</link>
<gazebo reference="left_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--3-2.joint-->
<joint name="left2link" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin rpy="0 0 0" xyz="0 0.1 -0.0225"/>
<axis xyz="0 1 0"/>
</joint>
<link name="right_wheel">
<visual>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="right_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.015" radius="0.0325"/>
</geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.05"/>
<inertia ixx="1.4140625e-05" ixy="0" ixz="0" iyy="1.4140625e-05" iyz="0" izz="2.640625e-05"/>
</inertial>
</link>
<gazebo reference="right_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--3-2.joint-->
<joint name="right2link" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin rpy="0 0 0" xyz="0 -0.1 -0.0225"/>
<axis xyz="0 1 0"/>
</joint>
<!--4-1.link-->
<link name="front_wheel">
<visual>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="front_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.25e-07" ixy="0" ixz="0" iyy="2.25e-07" iyz="0" izz="2.25e-07"/>
</inertial>
</link>
<gazebo reference="front_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--4-2.joint-->
<joint name="front2link" type="continuous">
<parent link="base_link"/>
<child link="front_wheel"/>
<origin rpy="0 0 0" xyz="0.08 0 -0.0475"/>
<axis xyz="0 1 0"/>
</joint>
<!--4-1.link-->
<link name="back_wheel">
<visual>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
<material name="back_wheel">
<color rgba="0 0 0 0.3"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.0075"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.25e-07" ixy="0" ixz="0" iyy="2.25e-07" iyz="0" izz="2.25e-07"/>
</inertial>
</link>
<gazebo reference="back_wheel">
<material>Gazebo/Red</material>
</gazebo>
<!--4-2.joint-->
<joint name="back2link" type="continuous">
<parent link="base_link"/>
<child link="back_wheel"/>
<origin rpy="0 0 0" xyz="-0.08 0 -0.0475"/>
<axis xyz="0 1 0"/>
</joint>
<link name="camera">
<visual>
<geometry>
<box size="0.02 0.05 0.05"/>
</geometry>
<material name="black">
<color rgba="0 0 0 0.8"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.02 0.05 0.05"/>
</geometry>
</collision>
<inertial>
<mass value="0.01"/>
<inertia ixx="2.41666666667e-06" ixy="0" ixz="0" iyy="2.41666666667e-06" iyz="0" izz="4.16666666667e-06"/>
</inertial>
</link>
<gazebo reference="camera">
<material>Gazebo/Blue</material>
</gazebo>
<joint name="camera2base" type="fixed">
<parent link="base_link"/>
<child link="camera"/>
<origin rpy="0 0 0" xyz="0.08 0 0.065"/>
</joint>
<link name="support">
<visual>
<geometry>
<cylinder length="0.15" radius="0.01"/>
</geometry>
<material name="yellow">
<color rgba="0.8 0.5 0.0 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.15" radius="0.01"/>
</geometry>
</collision>
<inertial>
<mass value="0.1"/>
<inertia ixx="0.00019" ixy="0" ixz="0" iyy="0.00019" iyz="0" izz="5e-06"/>
</inertial>
</link>
<gazebo reference="support">
<material>Gazebo/Gray</material>
</gazebo>
<joint name="support2base" type="fixed">
<parent link="base_link"/>
<child link="support"/>
<origin rpy="0 0 0" xyz="0.0 0.0 0.115"/>
</joint>
<link name="laser">
<visual>
<geometry>
<cylinder length="0.05" radius="0.03"/>
</geometry>
<material name="black">
<color rgba="0 0 0 0.5"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.05" radius="0.03"/>
</geometry>
</collision>
<inertial>
<mass value="0.15"/>
<inertia ixx="6.5e-05" ixy="0" ixz="0" iyy="6.5e-05" iyz="0" izz="6.75e-05"/>
</inertial>
</link>
<gazebo reference="laser">
<material>Gazebo/Black</material>
</gazebo>
<joint name="laser2support" type="fixed">
<parent link="support"/>
<child link="laser"/>
<origin rpy="0 0 0" xyz="0.0 0.0 0.1"/>
</joint>
<!-- Transmission is important to link the joints and the controller -->
<transmission name="left2link_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="left2link">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
</joint>
<actuator name="left2link_motor">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
<!-- Transmission is important to link the joints and the controller -->
<transmission name="right2link_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="right2link">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
</joint>
<actuator name="right2link_motor">
<hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
<gazebo>
<plugin filename="libgazebo_ros_diff_drive.so" name="differential_drive_controller">
<rosDebugLevel>Debug</rosDebugLevel>
<publishWheelTF>true</publishWheelTF>
<robotNamespace>/</robotNamespace>
<publishTf>1</publishTf>
<publishWheelJointState>true</publishWheelJointState>
<alwaysOn>true</alwaysOn>
<updateRate>100.0</updateRate>
<legacyMode>true</legacyMode>
<leftJoint>left2link</leftJoint>
<rightJoint>right2link</rightJoint>
<wheelSeparation>0.2</wheelSeparation>
<wheelDiameter>0.065</wheelDiameter>
<broadcastTF>1</broadcastTF>
<wheelTorque>30</wheelTorque>
<wheelAcceleration>1.8</wheelAcceleration>
<commandTopic>cmd_vel</commandTopic>
<odometryFrame>odom</odometryFrame>
<odometryTopic>odom</odometryTopic>
<robotBaseFrame>base_footprint</robotBaseFrame>
</plugin>
</gazebo>
<gazebo reference="laser">
<sensor name="rplidar" type="ray">
<pose>0 0 0 0 0 0</pose>
<visualize>true</visualize>
<update_rate>5.5</update_rate>
<ray>
<scan>
<horizontal>
<samples>360</samples>
<resolution>1</resolution>
<min_angle>-3</min_angle>
<max_angle>3</max_angle>
</horizontal>
</scan>
<range>
<min>0.10</min>
<max>30.0</max>
<resolution>0.01</resolution>
</range>
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.01</stddev>
</noise>
</ray>
<plugin filename="libgazebo_ros_laser.so" name="gazebo_rplidar">
<topicName>/scan</topicName>
<frameName>laser</frameName>
</plugin>
</sensor>
</gazebo>
<gazebo reference="camera">
<sensor name="camera_node" type="camera">
<update_rate>30.0</update_rate>
<camera name="head">
<horizontal_fov>1.3962634</horizontal_fov>
<image>
<width>1280</width>
<height>720</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.02</near>
<far>300</far>
</clip>
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.007</stddev>
</noise>
</camera>
<plugin filename="libgazebo_ros_camera.so" name="gazebo_camera">
<alwaysOn>true</alwaysOn>
<updateRate>0.0</updateRate>
<cameraName>/camera</cameraName>
<imageTopicName>image_raw</imageTopicName>
<cameraInfoTopicName>camera_info</cameraInfoTopicName>
<frameName>camera</frameName>
<hackBaseline>0.07</hackBaseline>
<distortionK1>0.0</distortionK1>
<distortionK2>0.0</distortionK2>
<distortionK3>0.0</distortionK3>
<distortionT1>0.0</distortionT1>
<distortionT2>0.0</distortionT2>
</plugin>
</sensor>
</gazebo>
<gazebo reference="support">
<sensor name="camera" type="depth">
<always_on>true</always_on>
<update_rate>20.0</update_rate>
<camera>
<horizontal_fov>1.04719756667</horizontal_fov>
<image>
<format>R8G8B8</format>
<width>640</width>
<height>480</height>
</image>
<clip>
<near>0.05</near>
<far>8.0</far>
</clip>
</camera>
<plugin filename="libgazebo_ros_openni_kinect.so" name="kinect_camera_controller">
<cameraName>camera</cameraName>
<alwaysOn>true</alwaysOn>
<updateRate>10</updateRate>
<imageTopicName>rgb/image_raw</imageTopicName>
<depthImageTopicName>depth/image_raw</depthImageTopicName>
<pointCloudTopicName>depth/points</pointCloudTopicName>
<cameraInfoTopicName>rgb/camera_info</cameraInfoTopicName>
<depthImageCameraInfoTopicName>depth/camera_info</depthImageCameraInfoTopicName>
<frameName>support</frameName>
<baseline>0.1</baseline>
<distortion_k1>0.0</distortion_k1>
<distortion_k2>0.0</distortion_k2>
<distortion_k3>0.0</distortion_k3>
<distortion_t1>0.0</distortion_t1>
<distortion_t2>0.0</distortion_t2>
<pointCloudCutoff>0.4</pointCloudCutoff>
</plugin>
</sensor>
</gazebo>
</robot>
打开一个命令行:
cd workspace
source ./devel/setup.bash
roslaunch urdf02_gazebo demo03_env.launch
打开一个命令行:
cd workspace
source ./devel/setup.bash
roslaunch urdf02_gazebo demo04_sensor.launch
打开一个命令行:
rostopic pub -r 10 /cmd_vel geometry_msgs/Twist "linear:
x: 0.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.5"
补充:kinect 点云数据显示
在kinect中也可以以点云的方式显示感知周围环境,在 rviz 中操作如下:
问题:在rviz中显示时错位。
原因:在kinect中图像数据与点云数据使用了两套坐标系统,且两套坐标系统位姿并不一致。
解决:
1.在插件中为kinect设置坐标系,修改配置文件的<frameName>
标签内容:
<frameName>support_depth</frameName>
2.发布新设置的坐标系到kinect连杆的坐标变换关系,在启动rviz的launch中,添加:
<node pkg="tf2_ros" type="static_transform_publisher" name="static_transform_publisher" args="0 0 0 -1.57 0 -1.57 /support /support_depth" />
三、本章小结
本章主要介绍了ROS中仿真实现涉及的三大知识点:
- URDF(Xacro)
- Rviz
- Gazebo
URDF 是用于描述机器人模型的 xml 文件,可以使用不同的标签具代表不同含义,URDF 编写机器人模型代码冗余,xacro 可以优化 URDF 实现,代码实现更为精简、高效、易读。容易混淆的是Rviz与Gazebo,在此我们着重比较以下二者的区别:
rviz是三维可视化工具,强调把已有的数据可视化显示;
gazebo是三维物理仿真平台,强调的是创建一个虚拟的仿真环境。
rviz需要已有数据。
- rviz提供了很多插件,这些插件可以显示图像、模型、路径等信息,但是前提都是这些数据已经以话题、参数的形式发布,rviz做的事情就是订阅这些数据,并完成可视化的渲染,让开发者更容易理解数据的意义。
- gazebo不是显示工具,强调的是仿真,它不需要数据,而是创造数据。
我们可以在gazebo中免费创建一个机器人世界,不仅可以仿真机器人的运动功能,还可以仿真机器人的传感器数据。而这些数据就可以放到rviz中显示,所以使用gazebo的时候,经常也会和rviz配合使用。当我们手上没有机器人硬件或实验环境难以搭建时,仿真往往是非常有用的利器。
综上,如果你手上已经有机器人硬件平台,并且在上边可以完成需要的功能,用rviz应该就可以满足开发需求。
如果你手上没有机器人硬件,或者想在仿真环境中做一些算法、应用的测试,gazebo+rviz应该是你需要的。
另外,rviz配合其他功能包也可以建立一个简单的仿真环境,比如rviz+ArbotiX。
总结
以上就是今天要讲的内容,本文仅仅简单记录了ROS的机器人系统仿真(Gazebo相关),如果有问题请在博客下留言或者咨询邮箱:layraliu@foxmail.com。