马上开学,目前学校很多实验室都是人工智能这块,大部分都是和机器人相关,然后软件这块就是和cv、ros相关,就打算开始学习一下。
本章节是虚拟机安装Ubuntu18.04以及安装ROS的环境。
学习教程:【Autolabor初级教程】ROS机器人入门,博客中一些知识点是来源于赵老师的笔记在线笔记,本博客主要是做归纳总结,如有侵权请联系删除。
视频中的案例都基本敲了遍,这里给出我自己的源代码文件:
链接:https://pan.baidu.com/s/13CAzXk0vAWuBsc4oABC-_g
提取码:0hws
所有博客文件目录索引:博客目录索引(持续更新)
**机器人系统仿真:**是通过计算机对实体机器人系统进行模拟的技术,在 ROS 中,仿真实现涉及的内容主要有三:对机器人建模(URDF)、创建仿真环境(Gazebo)以及感知环境(Rviz)等系统性实现。
仿真相关组件:
简而言之:URDF 用于创建机器人模型,Gzebo 用于搭建仿真环境,Rviz 图形化的显示机器人各种传感器感知到的环境信息。
实际应用:三者应用中,只是创建 URDF 意义不大,一般需要结合 Gazebo 或 Rviz 使用,在 Gazebo 或 Rviz 中可以将 URDF 文件解析为图形化的机器人模型,一般的使用组合为
1、创建新的工程包,并创建相应的四个目录:
# 进入到工程下的src目录
cd /home/workspace/roslearn/src
# 创建名为07urdf_rviz的包
catkin_create_pkg --rosdistro melodic 07urdf_rviz urdf xacro
2、编写指定的urdf文件
demo01_helloworld.urdf
<robot name="mycar">
<link name="base_link">
<visual>
<geometry>
<box size="0.5 0.2 0.1" />
geometry>
visual>
link>
robot>
3、编写launch文件,集成URDF与Rviz节点
demo01_helloworld.launch:
<launch>
<param name="robot_description" textfile="$(find 07urdf_rviz)/urdf/urdf/demo01_helloworld.urdf" />
<node pkg="rviz" type="rviz" name="rviz" />
launch>
接着我们来运行下该launch启动文件:
roslaunch 07urdf_rviz demo01_helloworld.launch
最终效果:
问题描述:在上面初始去启动rviz时,我们还需要去手动的添加机器人组件以及frame_id,若是每一次启动都需要这么修改,那就会很繁琐,能不能够通过一种方式我们重复打开时直接就已经配置好了呢?
解决方案:存储rviz文件,接着修改launch配置文件表示去进行读取,此时再去重新启动即可加载模型到rviz中,此时就能够简化机器人模型的显示。
接着我们来优化一下launch配置文件,添加一个args参数表示在启动rviz节点时加载对应的rviz配置:
<launch>
<param name="robot_description" textfile="$(find 07urdf_rviz)/urdf/urdf/demo01_helloworld.urdf" />
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" />
launch>
接着我们再次启动看看:
roslaunch 07urdf_rviz demo01_helloworld.launch
URDF官网文档配置
URDF 文件是一个标准的 XML 文件,在 ROS 中预定义了一系列的标签用于描述机器人模型,机器人模型可能较为复杂,但是 ROS 的 URDF 中机器人的组成却是较为简单,主要分为连杆(link标签) 与 关节(joint标签)。
标签如下:
针对于gazebo标签,后期在使用 gazebo 仿真时,才需要使用到,用于配置仿真环境所需参数,比如: 机器人材料属性、gazebo插件等,但是该标签不是机器人模型必须的,只有在仿真时才需设置。
URDF语法详解:一个关节就是一个link,一个joint点去连接指定的两个关节并且进行指定。
介绍:robot
标签作为根标签,所有的 link 和 joint 以及其他标签都必须包含在 robot 标签内,在该标签内可以通过 name 属性设置机器人模型的名称。
属性:name: 指定机器人模型的名称。
子标签:其他标签如link、joint、gazebo。
介绍:urdf 中的 link 标签用于描述机器人某个部件(也即刚体部分)的外观和物理属性,比如: 机器人底座、轮子、激光雷达、摄像头…每一个部件都对应一个 link, 在 link 标签内,可以设计该部件的形状、尺寸、颜色、惯性矩阵、碰撞参数等一系列属性。
简而言之就是一个部件就可以是一个link。
属性:
子标签:
package:////文件
)demo02_link.urdf:编写urdf模型
<robot name="mycar">
<link name="base_link">
<visual>
<geometry>
<mesh filename="package://07urdf_rviz/meshes/autolabor_mini.stl" />
geometry>
<origin xyz="0 0 0" rpy="1.57 0 1.57" />
<material name="car_color">
<color rgba="0.5 0.2 0.3 0.5" />
material>
visual>
link>
robot>
demo02_link.launch
<launch>
<param name="robot_description" textfile="$(find 07urdf_rviz)/urdf/urdf/demo02_link.urdf" />
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" />
launch>
启动launch节点:
roslaunch 07urdf_rviz demo02_link.launch
其他几个案例展示:
额外
其中一个偏移量的实战案例就是将autolabor_mini.stl模型进行调整:
介绍:urdf 中的 joint 标签用于描述机器人关节的运动学和动力学属性,还可以指定关节运动的安全极限,机器人的两个部件(分别称之为 parent link 与 child link)以"关节"的形式相连接,不同的关节有不同的运动形式: 旋转、滑动、固定、旋转速度、旋转角度限制…,比如:安装在底座上的轮子可以360度旋转,而摄像头则可能是完全固定在底座上。
简而言之:joint标签就是将两个link组件来连接到一起的。
属性:目前只关注旋转关节及固定关节即可。
子标签:
demo03_joint.urdf:
<robot name="mycar">
<link name="base_link">
<visual>
<geometry>
<box size="0.3 0.2 0.1" />
geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="car_color">
<color rgba="0.8 0.5 0 1" />
material>
visual>
link>
<link name="camera">
<visual>
<geometry>
<box size="0.02 0.05 0.05" />
geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="camera_color">
<color rgba="0 0 1 1" />
material>
visual>
link>
<joint name="camera2baselink" type="continous">
<parent link="base_link" />
<child link="camera" />
<origin xyz="0.2 0 0.075" rpy="0 0 0" />
<axis xyz="0 0 1" />
joint>
robot>
demo03_joint.launch:
<launch>
<param name="robot_description" textfile="$(find 07urdf_rviz)/urdf/urdf/demo03_joint.urdf" />
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" />
<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
<node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" />
launch>
运行launch文件:
roslaunch 07urdf_rviz demo03_joint.launch
指定Fixed Frame为base_link,右边的是控制旋转节点(与launch文件中的joint_state_publisher_gui相关,需要手动安装下可见报错方案总结)
针对于现存的一个问题就是当前的长方体并不是水平在平面里的,而是如下图所示并没有完全水平:
解决方案:在对应的urdf文件中新增一个link底盘,并且使用joint将底盘和基准面进行连接,即可实现在水平了。
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="0.001" />
geometry>
visual>
link>
<joint name="base_link2base_footprint" type="fixed">
<parent link="base_footprint" />
<child link="base_link" />
<origin xyz="0 0 0.05" />
joint>
最终的效果:以base_footprint作为Fixed Frame
这里并没有中文注释,以免在launch文件时运行报错!
<robot name="mycar">
<link name="base_link">
<visual>
<geometry>
<box size="0.3 0.2 0.1" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="car_color">
<color rgba="0.8 0.5 0 0.5" />
</material>
</visual>
</link>
<link name="camera">
<visual>
<geometry>
<box size="0.02 0.05 0.05" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="camera_color">
<color rgba="0 0 1 0.5" />
</material>
</visual>
</link>
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="0.001" />
</geometry>
</visual>
</link>
<joint name="camera2baselink" type="continuous">
<parent link="base_link" />
<child link="camera" />
<origin xyz="0.12 0 0.07" rpy="0 0 0" />
<axis xyz="0 0 1" />
</joint>
<joint name="base_link2base_footprint" type="fixed">
<parent link="base_footprint" />
<child link="base_link" />
<origin xyz="0 0 0.05" />
</joint>
</robot>
报错1:若是命令行出现报错’ascii’ codec can’t encode characters in position 463-464
UnicodeEncodeError: 'ascii' codec can't encode characters in position 463-464: ordinal not in range(128)
[joint_state_publisher-3] process has died [pid 4443, exit code 1, cmd /opt/ros/melodic/lib/joint_state_publisher/joint_state_publisher __name:=joint_state_publisher __log:=/home/rosmelodic/.ros/log/b38967c0-0acb-11eb-aee3-0800278ee10c/joint_state_publisher-3.log].
log file: /home/rosmelodic/.ros/log/b38967c0-0acb-11eb-aee3-0800278ee10c/joint_state_publisher-3*.log
解决方案:URDF文件中不要有中文注释。
报错2:缺少joint_state_publisher_gui依赖(在launch节点中运行时出现)
解决方案:安装对应的publisher-gui包即可
sudo apt-get install ros-melodic-joint-state-publisher-gui
报错3:rviz中报错描述:No transform from [camera] to [base_link]。
解决方案:在launch文件中添加关节状态、机器人发布状态节点
<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
创建一个四轮圆柱状机器人模型,机器人参数如下:
实现流程:
步骤一:底盘搭建
<robot name="mycar">
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="0.001" />
geometry>
visual>
link>
<link name="base_link">
<visual>
<geometry>
<cylinder radius="0.1" length="0.08" />
geometry>
visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="yellow">
<color rgba="0.8 0.3 0.1 0.5" />
material>
link>
<joint name="base_link2base_footprint" type="fixed">
<parent link="base_footprint" />
<child link="base_link" />
<origin xyz="0 0 0.055" />
joint>
robot>
底盘搭建的细节及搭建效果如下所示:
对应origin的关节部分就是0.04+0.015=0.055
效果:
步骤二:编写驱动轮
<link name="left_wheel">
<visual>
<geometry>
<cylinder radius="0.0325" length="0.015" />
geometry>
<origin xyz="0 0 0" rpy="1.5705 0 0" />
<material name="black">
<color rgba="0.0 0.0 0.0 1.0" />
material>
visual>
link>
<joint name="left_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="left_wheel" />
<origin xyz="0 0.1 -0.0225" />
<axis xyz="0 1 0" />
joint>
<link name="right_wheel">
<visual>
<geometry>
<cylinder radius="0.0325" length="0.015" />
geometry>
<origin xyz="0 0 0" rpy="1.5705 0 0" />
<material name="black">
<color rgba="0.0 0.0 0.0 1.0" />
material>
visual>
link>
<joint name="right_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="right_wheel" />
<origin xyz="0 -0.1 -0.0225" />
<axis xyz="0 1 0" />
joint>
注意点说明:对于离地的偏移量最好是设置在joint关节上,而不是在本身物体上,如下图所示,若是我们设置在joint关节上,在rviz中添加TF坐标就能够很明显的查看之间的效果:
驱动轮我们是以绿色的y轴作为轮子的位置
对于r为0.0225的说明:
关于axis中y=1的说明:
效果:
定位依旧改成base_footprint,并且添加tf坐标和控制运动
步骤三:编写万向轮
添加万向轮:
效果:
demo04_test.launch:
<launch>
<param name="robot_description" textfile="$(find 07urdf_rviz)/urdf/urdf/demo04_test.urdf" />
<node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" />
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
<node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" />
launch>
最后去进行编译运行节点:
source ./devel/setup.bash
roslaunch 07urdf_rviz demo04_test.launch
在 ROS 中提供了一些工具来方便 URDF 文件的编写:
check_urdf
命令可以检查复杂的 urdf 文件是否存在语法问题urdf_to_graphiz
命令可以查看 urdf 模型结构,显示不同 link 的层级关系安装命令:sudo apt install liburdfdom-tools
1、check_urdf:语法检查
# 进入到urdf目录,来执行check检查命令
check_urdf demo04_test.urdf
2、urdf_to_graphiz:结构查看
# 进入到urdf目录
urdf_to_graphiz demo04_test.urdf
此时就会在该目录下生成pdf文件:
纯使用urdf存在的问题如下:
1、在设计关节的位置时,一些位置数据都是算好之后填上去的,那么如果部件的一些属性修改了,那么就需要重新来去计算。
2、在urdf中若是有一些重复的组件,我们需要反复的重复声明,不能够很好的进行复用。
在ros中给出了类似编程的优化方案,称之为:Xacro。
介绍:Xacro 是 XML Macros 的缩写,Xacro 是一种 XML 宏语言,是可编程的 XML。
原理:Xacro 可以声明变量,可以通过数学运算求解,使用流程控制控制执行顺序,还可以通过类似函数的实现,封装固定的逻辑,将逻辑中需要的可变的数据以参数的方式暴露出去,从而提高代码复用率以及程序的安全性。
作用:较之于纯粹的 URDF 实现,可以编写更安全、精简、易读性更强的机器人模型文件,且可以提高编写效率。
在当前的urdf目录下创建xacro文件:
demo01_helloworld.urdf.xacro:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:property name="wheel_radius" value="0.0325" />
<xacro:property name="wheel_length" value="0.0015" />
<xacro:property name="PI" value="3.1415927" />
<xacro:property name="base_link_length" value="0.08" />
<xacro:property name="lidi_space" value="0.015" />
<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_color">
<color rgba="0 0 0 0.3" />
material>
visual>
link>
<joint name="${wheel_name}2link" type="continuous">
<parent link="base_link" />
<child link="${wheel_name}_wheel" />
<origin xyz="0 ${0.1 * flag} ${(base_link_length / 2 + lidi_space - wheel_radius) * -1}" 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" />
robot>
接着进入到xacro目录下执行编译命令:
# 打印Xacro解析内容到屏幕
rosrun xacro xacro demo01_helloworld.urdf.xacro
# 将Xacro解析内容到文件
rosrun xacro xacro demo01_helloworld.urdf.xacro > demo01_helloworld.urdf
此时就可以快速拿到urdf文件(根据相应的公式编译好的):
<robot name="mycar">
<link name="left_wheel">
<visual>
<geometry>
<cylinder length="0.0015" radius="0.0325"/>
geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="wheel_color">
<color rgba="0 0 0 0.3"/>
material>
visual>
link>
<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.0015" radius="0.0325"/>
geometry>
<origin rpy="1.57079635 0 0" xyz="0 0 0"/>
<material name="wheel_color">
<color rgba="0 0 0 0.3"/>
material>
visual>
link>
<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>
robot>
在编写xacro文件时,在robot标签上一定要添加空间声明:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
语法一:属性与算数运算
用途:用于封装 URDF 中的一些字段,比如: PAI 值,小车的尺寸,轮子半径 …
# 属性定义
<xacro:property name="xxxx" value="yyyy" />
# 属性调用
${属性名称}
# 算数运算
${数学表达式}
语法二:宏
# 宏定义
<xacro:macro name="宏名称" params="参数列表(多参数之间使用空格分隔)">
.....
参数调用格式: ${参数名}
</xacro:macro>
# 宏调用
<xacro:宏名称 参数1=xxx 参数2=xxx/>
语法三:文件包含
# 不同部件单独封装为宏,接着来统一集成组合出机器人(不同组件之间可以互相进行属性调用)
<robot name="xxx" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="my_base.xacro" />
<xacro:include filename="my_camera.xacro" />
<xacro:include filename="my_laser.xacro" />
....
</robot>
实际举例:
demo02_car_base.urdf-z.xacro
:
<robot name="my_base" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:property name="PI" value="3.141"/>
<material name="black">
<color rgba="0.0 0.0 0.0 1.0" />
material>
<xacro:property name="base_footprint_radius" value="0.001" />
<xacro:property name="base_link_radius" value="0.1" />
<xacro:property name="base_link_length" value="0.08" />
<xacro:property name="earth_space" value="0.015" />
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="${base_footprint_radius}" />
geometry>
visual>
link>
<link name="base_link">
<visual>
<geometry>
<cylinder radius="${base_link_radius}" length="${base_link_length}" />
geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="yellow">
<color rgba="0.5 0.3 0.0 0.5" />
material>
visual>
link>
<joint name="base_link2base_footprint" type="fixed">
<parent link="base_footprint" />
<child link="base_link" />
<origin xyz="0 0 ${earth_space + base_link_length / 2 }" />
joint>
<xacro:property name="wheel_radius" value="0.0325" />
<xacro:property name="wheel_length" value="0.015" />
<xacro:macro name="add_wheels" params="name flag">
<link name="${name}_wheel">
<visual>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0" />
<material name="black" />
visual>
link>
<joint name="${name}_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="${name}_wheel" />
<origin xyz="0 ${flag * base_link_radius} ${-(earth_space + base_link_length / 2 - wheel_radius) }" />
<axis xyz="0 1 0" />
joint>
xacro:macro>
<xacro:add_wheels name="left" flag="1" />
<xacro:add_wheels name="right" flag="-1" />
<xacro:property name="support_wheel_radius" value="0.0075" />
<xacro:macro name="add_support_wheel" params="name flag" >
<link name="${name}_wheel">
<visual>
<geometry>
<sphere radius="${support_wheel_radius}" />
geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="black" />
visual>
link>
<joint name="${name}_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="${name}_wheel" />
<origin xyz="${flag * (base_link_radius - support_wheel_radius)} 0 ${-(base_link_length / 2 + earth_space / 2)}" />
<axis xyz="1 1 1" />
joint>
xacro:macro>
<xacro:add_support_wheel name="front" flag="1" />
<xacro:add_support_wheel name="back" flag="-1" />
robot>
demo02_car_base.urdf.xacro
:不带注释的(对于python2.7版本我们在运行launch文件时想要使用xacro编译的能用就需要使用这个文件)
<robot name="my_base" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:property name="PI" value="3.141"/>
<material name="black">
<color rgba="0.0 0.0 0.0 1.0" />
material>
<xacro:property name="base_footprint_radius" value="0.001" />
<xacro:property name="base_link_radius" value="0.1" />
<xacro:property name="base_link_length" value="0.08" />
<xacro:property name="earth_space" value="0.015" />
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="${base_footprint_radius}" />
geometry>
visual>
link>
<link name="base_link">
<visual>
<geometry>
<cylinder radius="${base_link_radius}" length="${base_link_length}" />
geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="yellow">
<color rgba="0.5 0.3 0.0 0.5" />
material>
visual>
link>
<joint name="base_link2base_footprint" type="fixed">
<parent link="base_footprint" />
<child link="base_link" />
<origin xyz="0 0 ${earth_space + base_link_length / 2 }" />
joint>
<xacro:property name="wheel_radius" value="0.0325" />
<xacro:property name="wheel_length" value="0.015" />
<xacro:macro name="add_wheels" params="name flag">
<link name="${name}_wheel">
<visual>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0" />
<material name="black" />
visual>
link>
<joint name="${name}_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="${name}_wheel" />
<origin xyz="0 ${flag * base_link_radius} ${-(earth_space + base_link_length / 2 - wheel_radius) }" />
<axis xyz="0 1 0" />
joint>
xacro:macro>
<xacro:add_wheels name="left" flag="1" />
<xacro:add_wheels name="right" flag="-1" />
<xacro:property name="support_wheel_radius" value="0.0075" />
<xacro:macro name="add_support_wheel" params="name flag" >
<link name="${name}_wheel">
<visual>
<geometry>
<sphere radius="${support_wheel_radius}" />
geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="black" />
visual>
link>
<joint name="${name}_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="${name}_wheel" />
<origin xyz="${flag * (base_link_radius - support_wheel_radius)} 0 ${-(base_link_length / 2 + earth_space / 2)}" />
<axis xyz="1 1 1" />
joint>
xacro:macro>
<xacro:add_support_wheel name="front" flag="1" />
<xacro:add_support_wheel name="back" flag="-1" />
robot>
接着我们来去编写来launch配置文件,两种方式来进行运行urdf文件:
demo05_car_base.launch
:两种方式如下图注释即可
<launch>
<param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_rviz)/urdf/xacro/demo02_car_base.urdf.xacro" />
<node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" />
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
<node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" />
launch>
编译命令:
rosrun xacro xacro demo02_car_base.urdf-z.xacro > demo02_car_base.urdf
# 将Xacro解析内容到文件
rosrun xacro xacro demo02_car_base.urdf.xacro > demo02_car_base.urdf
运行launch节点命令:
source ./devel/setup.bash
roslaunch 07urdf_rviz demo05_car_base.launch
在当前案例中,我们对摄像头、雷达来进行单独封装文件,最后统一在car.launch里进行统一封装。
最终引用的是没有中文注释的
demo02_car_camera.urdf-z.xacro
:带有中文注释的
<robot name="my_camera" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:property name="camera_length" value="0.01" />
<xacro:property name="camera_width" value="0.025" />
<xacro:property name="camera_height" value="0.025" />
<xacro:property name="camera_x" value="0.08" />
<xacro:property name="camera_y" value="0.0" />
<xacro:property name="camera_z" value="${base_link_length / 2 + camera_height / 2}" />
<link name="camera">
<visual>
<geometry>
<box size="${camera_length} ${camera_width} ${camera_height}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="black" />
visual>
link>
<joint name="camera2base_link" type="fixed">
<parent link="base_link" />
<child link="camera" />
<origin xyz="${camera_x} ${camera_y} ${camera_z}" />
joint>
robot>
demo02_car_camera.urdf.xacro:实际引入的组件,无中文注释
<robot name="my_camera" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:property name="camera_length" value="0.01" />
<xacro:property name="camera_width" value="0.025" />
<xacro:property name="camera_height" value="0.025" />
<xacro:property name="camera_x" value="0.08" />
<xacro:property name="camera_y" value="0.0" />
<xacro:property name="camera_z" value="${base_link_length / 2 + camera_height / 2}" />
<link name="camera">
<visual>
<geometry>
<box size="${camera_length} ${camera_width} ${camera_height}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="black" />
visual>
link>
<joint name="camera2base_link" type="fixed">
<parent link="base_link" />
<child link="camera" />
<origin xyz="${camera_x} ${camera_y} ${camera_z}" />
joint>
robot>
最终引入的是无中文注释的
demo02_car_laser.urdf-z.xacro
:
<robot name="my_laser" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:property name="support_length" value="0.15" />
<xacro:property name="support_radius" value="0.01" />
<xacro:property name="support_x" value="0.0" />
<xacro:property name="support_y" value="0.0" />
<xacro:property name="support_z" value="${base_link_length / 2 + support_length / 2}" />
<link name="support">
<visual>
<geometry>
<cylinder radius="${support_radius}" length="${support_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="red">
<color rgba="0.8 0.2 0.0 0.8" />
material>
visual>
link>
<joint name="support2base_link" type="fixed">
<parent link="base_link" />
<child link="support" />
<origin xyz="${support_x} ${support_y} ${support_z}" />
joint>
<xacro:property name="laser_length" value="0.05" />
<xacro:property name="laser_radius" value="0.03" />
<xacro:property name="laser_x" value="0.0" />
<xacro:property name="laser_y" value="0.0" />
<xacro:property name="laser_z" value="${support_length / 2 + laser_length / 2}" />
<link name="laser">
<visual>
<geometry>
<cylinder radius="${laser_radius}" length="${laser_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="black" />
visual>
link>
<joint name="laser2support" type="fixed">
<parent link="support" />
<child link="laser" />
<origin xyz="${laser_x} ${laser_y} ${laser_z}" />
joint>
robot>
demo02_car_laser.urdf.xacro
:
<robot name="my_laser" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:property name="support_length" value="0.15" />
<xacro:property name="support_radius" value="0.01" />
<xacro:property name="support_x" value="0.0" />
<xacro:property name="support_y" value="0.0" />
<xacro:property name="support_z" value="${base_link_length / 2 + support_length / 2}" />
<link name="support">
<visual>
<geometry>
<cylinder radius="${support_radius}" length="${support_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="red">
<color rgba="0.8 0.2 0.0 0.8" />
material>
visual>
link>
<joint name="support2base_link" type="fixed">
<parent link="base_link" />
<child link="support" />
<origin xyz="${support_x} ${support_y} ${support_z}" />
joint>
<xacro:property name="laser_length" value="0.05" />
<xacro:property name="laser_radius" value="0.03" />
<xacro:property name="laser_x" value="0.0" />
<xacro:property name="laser_y" value="0.0" />
<xacro:property name="laser_z" value="${support_length / 2 + laser_length / 2}" />
<link name="laser">
<visual>
<geometry>
<cylinder radius="${laser_radius}" length="${laser_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="black" />
visual>
link>
<joint name="laser2support" type="fixed">
<parent link="support" />
<child link="laser" />
<origin xyz="${laser_x} ${laser_y} ${laser_z}" />
joint>
robot>
car.launch:
<launch>
<param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_rviz)/urdf/xacro/car.urdf.xacro" />
<node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" />
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
<node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" />
launch>
最终我们来进行编译执行launch文件:
source ./devel/setup.bash
roslaunch 07urdf_rviz car.launch
使用URDF 结合 rviz 可以创建并显示机器人模型。当前实现的只是静态模型,如何控制模型的运动呢?
介绍:Arbotix 是一款控制电机、舵机的控制板,并提供相应的 ros 功能包,这个功能包的功能不仅可以驱动真实的 Arbotix 控制板,它还提供一个差速控制器,通过接受速度控制指令更新机器人的 joint 状态,从而帮助我们实现机器人在 rviz 中的运动。
安装Arbotix
安装Arbotix:
方式一:命令行安装
# 语法:sudo apt-get install ros-<>-arbotix
sudo apt-get install ros-melodic-arbotix
方式二:源码包安装
git clone https://github.com/vanadiumlabs/arbotix_ros.git
# 接着放入到当前工程目录下,调用 catkin_make 编译
catkin_make
步骤一:添加一个Arbotix配置文件
demo06_control.launch
:
# 该文件是控制器配置,一个机器人模型可能有多个控制器,比如: 底盘、机械臂、夹持器(机械手)....
# 因此,根 name 是 controller
controllers: {
# 单控制器设置
base_controller: {
#类型: 差速控制器(依据速度差异控制)
type: diff_controller,
#参考坐标
base_frame_id: base_footprint,
#两个轮子之间的间距
base_width: 0.2,
#控制频率
ticks_meter: 2000,
#PID控制参数,使机器人车轮快速达到预期速度
Kp: 12,
Kd: 12,
Ki: 0,
Ko: 50,
#加速限制
accel_limit: 1.0
}
}
步骤二:编写launch文件,并引入arbotix节点服务
demo06_control.launch:
<launch>
<param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_rviz)/urdf/xacro/car.urdf.xacro" />
<node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" />
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
<node name="arbotix" pkg="arbotix_python" type="arbotix_driver" output="screen">
<rosparam file="$(find 07urdf_rviz)/config/control.yaml" command="load" />
<param name="sim" value="true" />
node>
launch>
ok,接着我们来尝试运行launch文件:
source ./devel/setup.bash
roslaunch 07urdf_rviz demo06_control.launch
在启动节点之后,我们可以使用rostopic list查看到当前有一个/cmd_vel的话题,接着我们要是想要机器人动起来就需要去发布控制话题命令:
rostopic pub -r 10 /cmd_vel geometry_msgs/Twist "linear:
x: 1.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 1.0"
流程:
步骤一:创建功能包
# 进入到工程下的src目录
cd /home/workspace/roslearn/src
# 创建名为07urdf_gazebo的包 引入urdf、xacro、gazebo_ros、gazebo_ros_control、gazebo_plugins
catkin_create_pkg --rosdistro melodic 07urdf_gazebo urdf xacro urdf xacro gazebo_ros gazebo_ros_control gazebo_plugins
步骤二:编写urdf文件(带z的是有注释的)
demo01_helloworld-z.urdf
:
<robot name="mycar">
<link name="base_link">
<visual>
<geometry>
<box size="0.5 0.2 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 1" />
material>
visual>
<collision>
<geometry>
<box size="0.5 0.2 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/Redmaterial>
gazebo>
robot>
demo01_helloworld.urdf
:
<robot name="mycar">
<link name="base_link">
<visual>
<geometry>
<box size="0.5 0.2 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 1" />
material>
visual>
<collision>
<geometry>
<box size="0.5 0.2 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/Redmaterial>
gazebo>
robot>
步骤三:编写launch文件
demo01_helloworld.launch:
<launch>
<param name="robot_description" textfile="$(find 07urdf_gazebo)/urdf/demo01_helloworld.urdf" />
<include file="$(find gazebo_ros)/launch/empty_world.launch" />
<node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description" />
launch>
最后来执行ros的launch命令启动节点:
# 启动节点
roslaunch 07urdf_gazebo demo01_helloworld.launch
URDF 需要与 Gazebo 集成时,和 Rviz 有明显区别:
1、必须使用 collision 标签,因为既然是仿真环境,那么必然涉及到碰撞检测,collision 提供碰撞检测的依据。
2、必须使用 inertial 标签,此标签标注了当前机器人某个刚体部分的惯性矩阵,用于一些力学相关的仿真计算。
3、颜色设置,也需要重新使用 gazebo 标签使用reference标注,因为之前的颜色设置为了方便调试包含透明度,仿真环境下没有此选项。
collision标签
机器人link是标准的几何体形状,和link的 visual 属性设置一致即可,可直接将geometry、origin复制过来。
inertial标签
惯性矩阵的设置需要结合link的质量与外形参数动态生成,标准的球体、圆柱与立方体的惯性矩阵公式如下(已经封装为 xacro 实现):
球体惯性矩阵
<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>
Copy
圆柱惯性矩阵
<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>
Copy
立方体惯性矩阵
<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/Bluematerial>
gazebo>
head.xacro
:之前在6.2中给出的官方各个形状组件实例进行整体封装入一个文件
<robot name="base" xmlns:xacro="http://wiki.ros.org/xacro">
<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封装文件(带有注释的)
demo02_car_base.urdf.xacro
:底盘、支撑轮、驱动轮
<robot name="my_base" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:property name="PI" value="3.1415926"/>
<material name="black">
<color rgba="0.0 0.0 0.0 1.0" />
material>
<xacro:property name="base_footprint_radius" value="0.001" />
<xacro:property name="base_link_radius" value="0.1" />
<xacro:property name="base_link_length" value="0.08" />
<xacro:property name="earth_space" value="0.015" />
<xacro:property name="base_link_m" value="0.5" />
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="${base_footprint_radius}" />
geometry>
visual>
link>
<link name="base_link">
<visual>
<geometry>
<cylinder radius="${base_link_radius}" length="${base_link_length}" />
geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="yellow">
<color rgba="0.5 0.3 0.0 0.5" />
material>
visual>
<collision>
<geometry>
<cylinder radius="${base_link_radius}" length="${base_link_length}" />
geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
collision>
<xacro:cylinder_inertial_matrix m="${base_link_m}" r="${base_link_radius}" h="${base_link_length}" />
link>
<joint name="base_link2base_footprint" type="fixed">
<parent link="base_footprint" />
<child link="base_link" />
<origin xyz="0 0 ${earth_space + base_link_length / 2 }" />
joint>
<gazebo reference="base_link">
<material>Gazebo/Yellowmaterial>
gazebo>
<xacro:property name="wheel_radius" value="0.0325" />
<xacro:property name="wheel_length" value="0.015" />
<xacro:property name="wheel_m" value="0.05" />
<xacro:macro name="add_wheels" params="name flag">
<link name="${name}_wheel">
<visual>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0" />
<material name="black" />
visual>
<collision>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="${PI / 2} 0.0 0.0" />
collision>
<xacro:cylinder_inertial_matrix m="${wheel_m}" r="${wheel_radius}" h="${wheel_length}" />
link>
<joint name="${name}_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="${name}_wheel" />
<origin xyz="0 ${flag * base_link_radius} ${-(earth_space + base_link_length / 2 - wheel_radius) }" />
<axis xyz="0 1 0" />
joint>
<gazebo reference="${name}_wheel">
<material>Gazebo/Redmaterial>
gazebo>
xacro:macro>
<xacro:add_wheels name="left" flag="1" />
<xacro:add_wheels name="right" flag="-1" />
<xacro:property name="support_wheel_radius" value="0.0075" />
<xacro:property name="support_wheel_m" value="0.03" />
<xacro:macro name="add_support_wheel" params="name flag" >
<link name="${name}_wheel">
<visual>
<geometry>
<sphere radius="${support_wheel_radius}" />
geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="black" />
visual>
<collision>
<geometry>
<sphere radius="${support_wheel_radius}" />
geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
collision>
<xacro:sphere_inertial_matrix m="${support_wheel_m}" r="${support_wheel_radius}" />
link>
<joint name="${name}_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="${name}_wheel" />
<origin xyz="${flag * (base_link_radius - support_wheel_radius)} 0 ${-(base_link_length / 2 + earth_space / 2)}" />
<axis xyz="1 1 1" />
joint>
<gazebo reference="${name}_wheel">
<material>Gazebo/Redmaterial>
gazebo>
xacro:macro>
<xacro:add_support_wheel name="front" flag="1" />
<xacro:add_support_wheel name="back" flag="-1" />
robot>
demo02_car_camera.urdf.xacro
:摄像机
<robot name="my_camera" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:property name="camera_length" value="0.01" />
<xacro:property name="camera_width" value="0.025" />
<xacro:property name="camera_height" value="0.025" />
<xacro:property name="camera_x" value="0.08" />
<xacro:property name="camera_y" value="0.0" />
<xacro:property name="camera_z" value="${base_link_length / 2 + camera_height / 2}" />
<xacro:property name="camera_m" value="0.01" />
<link name="camera">
<visual>
<geometry>
<box size="${camera_length} ${camera_width} ${camera_height}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="black" />
visual>
<collision>
<geometry>
<box size="${camera_length} ${camera_width} ${camera_height}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
collision>
<xacro:Box_inertial_matrix m="${camera_m}" l="${camera_length}" w="${camera_width}" h="${camera_height}" />
link>
<joint name="camera2base_link" type="fixed">
<parent link="base_link" />
<child link="camera" />
<origin xyz="${camera_x} ${camera_y} ${camera_z}" />
joint>
<gazebo reference="camera">
<material>Gazebo/Bluematerial>
gazebo>
robot>
demo02_car_laser.urdf.xacro
:雷达
<robot name="my_laser" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:property name="support_length" value="0.15" />
<xacro:property name="support_radius" value="0.01" />
<xacro:property name="support_x" value="0.0" />
<xacro:property name="support_y" value="0.0" />
<xacro:property name="support_z" value="${base_link_length / 2 + support_length / 2}" />
<xacro:property name="support_m" value="0.02" />
<link name="support">
<visual>
<geometry>
<cylinder radius="${support_radius}" length="${support_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="red">
<color rgba="0.8 0.2 0.0 0.8" />
material>
visual>
<collision>
<geometry>
<cylinder radius="${support_radius}" length="${support_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
collision>
<xacro:cylinder_inertial_matrix m="${support_m}" r="${support_radius}" h="${support_length}" />
link>
<joint name="support2base_link" type="fixed">
<parent link="base_link" />
<child link="support" />
<origin xyz="${support_x} ${support_y} ${support_z}" />
joint>
<gazebo reference="support">
<material>Gazebo/Whitematerial>
gazebo>
<xacro:property name="laser_length" value="0.05" />
<xacro:property name="laser_radius" value="0.03" />
<xacro:property name="laser_x" value="0.0" />
<xacro:property name="laser_y" value="0.0" />
<xacro:property name="laser_z" value="${support_length / 2 + laser_length / 2}" />
<xacro:property name="laser_m" value="0.1" />
<link name="laser">
<visual>
<geometry>
<cylinder radius="${laser_radius}" length="${laser_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="black" />
visual>
<collision>
<geometry>
<cylinder radius="${laser_radius}" length="${laser_length}" />
geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
collision>
<xacro:cylinder_inertial_matrix m="${laser_m}" r="${laser_radius}" h="${laser_length}" />
link>
<joint name="laser2support" type="fixed">
<parent link="support" />
<child link="laser" />
<origin xyz="${laser_x} ${laser_y} ${laser_z}" />
joint>
<gazebo reference="laser">
<material>Gazebo/Blackmaterial>
gazebo>
robot>
demo02_gazebo.launch
:
<launch>
<param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_gazebo)/urdf/xacro/car.urdf.xacro" />
<include file="$(find gazebo_ros)/launch/empty_world.launch" />
<node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description" />
launch>
启动launch文件:
# 启动节点
roslaunch 07urdf_gazebo demo02_gazebo.launch
效果:
报错描述:UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 454-463: ordinal not in range(128)
问题描述:python2.7的原因。
解决方案:
进入到ros安装目录下的python2.7包中(/opt/ros/melodic/lib/python2.7/dist-packages),创建文件:sitecustomize.py
#coding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
将world资源防止到worlds目录下:
demo03_evn.launch
:接着我们编写launch文件,在加载gazebo时添加参数来引入world,如下第7行
<launch>
<param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_gazebo)/urdf/xacro/car.urdf.xacro" />
<include file="$(find gazebo_ros)/launch/empty_world.launch" >
<arg name="world_name" value="$(find 07urdf_gazebo)/worlds/box_house.world" />
include>
<node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description" />
launch>
启动launch文件:
# 启动节点
roslaunch 07urdf_gazebo demo03_evn.launch
效果:
运行gazebo:
gazebo
保存的内容有两个如下:
1、保存绘制的环境
点击: 左上角 file —> Save (保存路径功能包下的: models)
然后 file —> Exit Building Editor,保存的文件内容如下:
2、保存word世界文件
三者关系:URDF 用于创建机器人模型、Rviz 可以显示机器人感知到的环境信息,Gazebo 用于仿真,可以模拟外界环境,以及机器人的一些传感器。
如何在 Gazebo 中运行这些传感器,并显示这些传感器的数据(机器人的视角)呢?
通过Gazebo 模拟机器人的传感器,然后在 Rviz 中显示这些传感器感知到的数据。
基本流程介绍
运动控制基本流程:
添加的运动控制部件:左右轮胎
快速集成6.3案例中的demo(实现运动控制)
步骤一:添加两轮差速配置
move-z.xacro
:这里贴出有中文注释的配置
<robot name="my_car_move" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:macro name="joint_trans" params="joint_name">
<transmission name="${joint_name}_trans">
<type>transmission_interface/SimpleTransmissiontype>
<joint name="${joint_name}">
<hardwareInterface>hardware_interface/VelocityJointInterfacehardwareInterface>
joint>
<actuator name="${joint_name}_motor">
<hardwareInterface>hardware_interface/VelocityJointInterfacehardwareInterface>
<mechanicalReduction>1mechanicalReduction>
actuator>
transmission>
xacro:macro>
<xacro:joint_trans joint_name="left_wheel2base_link" />
<xacro:joint_trans joint_name="right_wheel2base_link" />
<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_wheel2base_linkleftJoint>
<rightJoint>right_wheel2base_linkrightJoint>
<wheelSeparation>${base_link_radius * 2}wheelSeparation>
<wheelDiameter>${wheel_radius * 2}wheelDiameter>
<broadcastTF>1broadcastTF>
<wheelTorque>30wheelTorque>
<wheelAcceleration>1.8wheelAcceleration>
<commandTopic>cmd_velcommandTopic>
<odometryFrame>odomodometryFrame>
<odometryTopic>odomodometryTopic>
<robotBaseFrame>base_footprintrobotBaseFrame>
plugin>
gazebo>
robot>
tips:在move.xacro中需要绑定好对应的左轮、右轮以及对应的左右关节,与之前的xacro中配置的对应上
步骤二:修改car.urdf.xacro配置
include标签添加gazebo目录下的``car.urdf.xacro`:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="head.xacro" />
<xacro:include filename="demo02_car_base.urdf.xacro" />
<xacro:include filename="demo02_car_camera.urdf.xacro" />
<xacro:include filename="demo02_car_laser.urdf.xacro" />
<xacro:include filename="../gazebo/move.xacro" />
robot>
步骤三:运行6.4案例中编写的launch文件
<launch>
<param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_gazebo)/urdf/xacro/car.urdf.xacro" />
<include file="$(find gazebo_ros)/launch/empty_world.launch" >
<arg name="world_name" value="$(find 07urdf_gazebo)/worlds/box_house.world" />
include>
<node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description" />
launch>
最后运行launch节点:
# 启动节点
roslaunch 07urdf_gazebo demo03_evn.launch
如何控制小车运动呢?
方式一:通过向话题发送消息
# 目标话题/cmd_vel
rostopic pub -r 10 /cmd_vel geometry_msgs/Twist "linear:
x: 0.2
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.2"
方式二:通过键盘控制teleop_twist_keyboard
# 安装teleop_twist_keyboard
sudo apt-get install ros-melodic-teleop-twist-keyboard
# 运行键盘控制
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
控制效果如下图所示:
介绍
在 Gazebo 的仿真环境中,机器人的里程计信息以及运动朝向等信息是无法获取的,可以通过 Rviz 显示机器人的里程计信息以及运动朝向
里程计:机器人相对出发点坐标系的位姿状态(X 坐标 Y 坐标 Z坐标以及朝向)。
使用
当小车运动起来之后,我们可以使用rviz来进行查看相应的里程信息。
demo03_evn_rviz.launch
:
<launch>
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find 07urdf_gazebo)/config/show_mycar.rviz"/>
<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" />
launch>
接着我们来进行启动节点:
# 启动节点
roslaunch 07urdf_gazebo demo03_evn_rviz.launch
最后我们来看一下里程信息的动图效果:
目的
通过 Gazebo 模拟激光雷达传感器,并在 Rviz 中显示激光数据。
雷达仿真基本流程:
添加的雷达部件位置:
实操
步骤一:编写雷达组件
car.urdf.xacro
:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="head.xacro" />
<xacro:include filename="demo02_car_base.urdf.xacro" />
<xacro:include filename="demo02_car_camera.urdf.xacro" />
<xacro:include filename="demo02_car_laser.urdf.xacro" />
<xacro:include filename="../gazebo/move.xacro" />
<xacro:include filename="../gazebo/laser.xacro" />
robot>
注意事项如下:
步骤二:在总配置中引入雷达组件
car.urdf.xacro
:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="head.xacro" />
<xacro:include filename="demo02_car_base.urdf.xacro" />
<xacro:include filename="demo02_car_camera.urdf.xacro" />
<xacro:include filename="demo02_car_laser.urdf.xacro" />
<xacro:include filename="../gazebo/move.xacro" />
<xacro:include filename="../gazebo/laser.xacro" />
robot>
最后我们就来一一运行三个组件分别是:gazebo、rviz以及键盘控制组件
# 启动gazebo
roslaunch 07urdf_gazebo demo03_evn.launch
# 启动rviz
roslaunch 07urdf_gazebo demo03_evn_rviz.launch
# 启动键盘控制
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
启动rviz之后,我们需要额外添加一个新的组件Laser Scan:添加要做的关键事情就是指定/scan主题
接着来看效果:
介绍
目的:通过 Gazebo 模拟摄像头传感器,并在 Rviz 中显示摄像头数据。
基本流程:
添加的摄像头组件位置:
实操
步骤一:编写摄像头组件
camera-z.xacro:
<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
<gazebo reference="camera">
<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>cameraframeName>
<hackBaseline>0.07hackBaseline>
<distortionK1>0.0distortionK1>
<distortionK2>0.0distortionK2>
<distortionK3>0.0distortionK3>
<distortionT1>0.0distortionT1>
<distortionT2>0.0distortionT2>
plugin>
sensor>
gazebo>
robot>
注意点:
步骤二:整合摄像头组件
car.urdf.xacro
·:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="head.xacro" />
<xacro:include filename="demo02_car_base.urdf.xacro" />
<xacro:include filename="demo02_car_camera.urdf.xacro" />
<xacro:include filename="demo02_car_laser.urdf.xacro" />
<xacro:include filename="../gazebo/move.xacro" />
<xacro:include filename="../gazebo/laser.xacro" />
<xacro:include filename="../gazebo/camera.xacro" />
robot>
接着老样子,启动三个服务:
# 启动gazebo
roslaunch 07urdf_gazebo demo03_evn.launch
# 启动rviz
roslaunch 07urdf_gazebo demo03_evn_rviz.launch
# 启动键盘控制
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
在rviz中添加camera组件,并且订阅主题:/camera/image_raw
效果展示:
介绍
目的:通过 Gazebo 模拟kinect摄像头,并在 Rviz 中显示kinect摄像头数据。
kinect摄像头仿真基本流程:
添加的摄像头组件位置:其实也可以直接替换之前的camera位置
实操
步骤一:编写深度相机配置
kinect.xacro
:
<robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
<gazebo reference="support">
<sensor type="depth" name="camera">
<always_on>truealways_on>
<update_rate>20.0update_rate>
<camera>
<horizontal_fov>${60.0*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_camera_controller" filename="libgazebo_ros_openni_kinect.so">
<cameraName>cameracameraName>
<alwaysOn>truealwaysOn>
<updateRate>10updateRate>
<imageTopicName>rgb/image_rawimageTopicName>
<depthImageTopicName>depth/image_rawdepthImageTopicName>
<pointCloudTopicName>depth/pointspointCloudTopicName>
<cameraInfoTopicName>rgb/camera_infocameraInfoTopicName>
<depthImageCameraInfoTopicName>depth/camera_infodepthImageCameraInfoTopicName>
<frameName>supportframeName>
<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>
robot>
步骤二:整个到之前的include配置文件
car.urdf.xacro
:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="head.xacro" />
<xacro:include filename="demo02_car_base.urdf.xacro" />
<xacro:include filename="demo02_car_camera.urdf.xacro" />
<xacro:include filename="demo02_car_laser.urdf.xacro" />
<xacro:include filename="../gazebo/move.xacro" />
<xacro:include filename="../gazebo/laser.xacro" />
<xacro:include filename="../gazebo/camera.xacro" />
<xacro:include filename="../gazebo/kinect.xacro" />
robot>
接着启动三个部分:
# 启动gazebo
roslaunch 07urdf_gazebo demo03_evn.launch
# 启动rviz
roslaunch 07urdf_gazebo demo03_evn_rviz.launch
# 启动键盘控制
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
rviz使用的是之前的camera,我们来选择不同的主题即可
为了能够让其自转,这里我们去发布一个位姿消息:
# 目标话题/cmd_vel
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.3"
效果展示:
/camera/depth/image_raw:深度
/camera/rgb/image_raw:rgb
在rviz中添加PointCloud2,然后去订阅主题:/camera/depth/points
效果展示:
若是出现点云投像显示错误,解决方案如下
主要原因:在kinect中图像数据与点云数据使用了两套坐标系统,且两套坐标系统位姿并不一致。
1、在插件中为kinect设置坐标系,修改配置文件的
标签内容:
<frameName>support_depthframeName>
2、在启动rviz的launch文件中发布新设置的坐标系到kinect连杆的坐标变换关系
<node pkg="tf2_ros" type="static_transform_publisher" name="static_transform_publisher" args="0 0 0 -1.57 0 -1.57 /support /support_depth" />
最终重启各个服务,即可解决!
[1]. ERROR: cannot launch node of type [joint_state_publisher_gui/joint_state_publisher_gui]: joint_state
[2]. ROS启动gazebo出现UnicodeEncodeError: ‘ascii‘ codec can‘t encode character u‘\u5b8f‘ in position 492:……