发布时间:2025-12-10 11:19:32 浏览次数:2
马上开学,目前学校很多实验室都是人工智能这块,大部分都是和机器人相关,然后软件这块就是和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、创建新的工程包,并创建相应的四个目录:
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><!-- 1、在参数服务器中载入urdf文件 --><param name="robot_description" textfile="$(find 07urdf_rviz)/urdf/urdf/demo01_helloworld.urdf" /><!-- 2、启动rviz --><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><!-- 1、在参数服务器中载入urdf文件 --><param name="robot_description" textfile="$(find 07urdf_rviz)/urdf/urdf/demo01_helloworld.urdf" /><!-- 2、启动rviz -d 表示指定rviz文件来进行加载 --><node pkg="rviz" type="rviz" name="rviz" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" /></launch>接着我们再次启动看看:
roslaunch 07urdf_rviz demo01_helloworld.launchURDF官网文档配置
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。
属性:
子标签:
demo02_link.urdf:编写urdf模型
<robot name="mycar"><link name="base_link"><visual><geometry><!-- 形状 --><!-- 1、立方体 size:长宽高 --><!-- <box size="0.5 0.3 0.1" /> --><!-- 2、圆柱:radius半径,length为高度 --><!-- <cylinder radius="0.1" length="2.0" /> --><!-- 3、球体:radius半径 --><!-- <sphere radius="1" /> --><!-- 4、加载自定义模型文件 --><mesh filename="package://07urdf_rviz/meshes/autolabor_mini.stl" /> </geometry><!-- 偏移量xyz表示x轴、y轴、z轴rpy表示翻转、俯仰、偏航--><origin xyz="0 0 0" rpy="1.57 0 1.57" /><!-- 颜色 --><!-- rgba a表示不透明度,范围值为[0,1] --><material name="car_color"><color rgba="0.5 0.2 0.3 0.5" /> </material></visual></link></robot>demo02_link.launch
<launch><!-- 1、在参数服务器中载入urdf文件 --><param name="robot_description" textfile="$(find 07urdf_rviz)/urdf/urdf/demo02_link.urdf" /><!-- 2、启动rviz -d 表示指定rviz文件来进行加载 --><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模型进行调整:
<!-- 核心修改的就是这个偏移量 --><origin xyz="0 0 0" rpy="1.57 0 1.57" />介绍:urdf 中的 joint 标签用于描述机器人关节的运动学和动力学属性,还可以指定关节运动的安全极限,机器人的两个部件(分别称之为 parent link 与 child link)以"关节"的形式相连接,不同的关节有不同的运动形式: 旋转、滑动、固定、旋转速度、旋转角度限制…,比如:安装在底座上的轮子可以360度旋转,而摄像头则可能是完全固定在底座上。
简而言之:joint标签就是将两个link组件来连接到一起的。
属性:目前只关注旋转关节及固定关节即可。
子标签:
demo03_joint.urdf:
demo03_joint.launch:
<launch><!-- 1、在参数服务器中载入urdf文件 --><param name="robot_description" textfile="$(find 07urdf_rviz)/urdf/urdf/demo03_joint.urdf" /><!-- 2、启动rviz -d 表示指定rviz文件来进行加载 --><node pkg="rviz" type="rviz" name="rviz" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" /><!--若是进行关联两个link,仅仅只配置上面两个文件:表现:设置头显示位置与颜色异常提示:No transform from [camera] to [base_link] 缺少camera 到base_link的坐标变换原因:rviz中显示URDF时,必须发布不同部件之间的 坐标系 关系解决:ROS中提供了关于机器人模型显示的坐标发布相关节点(两个)--><!-- 添加关节状态发布节点 --><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将底盘和基准面进行连接,即可实现在水平了。
最终的效果:以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"><!-- 设置base_footprint --><link name="base_footprint"><visual><geometry><sphere radius="0.001" /></geometry></visual></link><!-- 添加底盘半径:0.1m高度:0.08m离地:0.015m--><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
效果:
步骤二:编写驱动轮
<!-- 添加驱动轮 --><!--驱动轮是侧翻的圆柱(90°)参数半径: 0.0325 cm宽度: 0.015 cm颜色: 黑色 关节设置:x = 0y = 底盘的半径 + 轮胎宽度 / 2 = 0.1 + 0.015 / 2 = 0.1+0.0075=0.10075z = 离地间距 + 底盘长度 / 2 - 轮胎半径 = 0.015 + 0.08/2 - 0.0325 = 0.02250.015axis = 0 1 0--><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><!-- 1、将 urdf 文件内容设置进参数服务器 --><param name="robot_description" textfile="$(find 07urdf_rviz)/urdf/urdf/demo04_test.urdf" /><!-- 2、启动 rivz --><node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" /><!-- 3、启动机器人状态和关节状态发布节点 --><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" /><!-- 4、启动图形化的控制关节运动节点 --><node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" /></launch>最后去进行编译运行节点:
source ./devel/setup.bashroslaunch 07urdf_rviz demo04_test.launch在 ROS 中提供了一些工具来方便 URDF 文件的编写:
安装命令:sudo apt install liburdfdom-tools
1、check_urdf:语法检查
# 进入到urdf目录,来执行check检查命令check_urdf demo04_test.urdf2、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><!-- 3-2.joint --><joint name="${wheel_name}2link" type="continuous"><parent link="base_link" /><child link="${wheel_name}_wheel" /><!-- x 无偏移y 车体半径z z= 车体高度 / 2 + 离地间距 - 车轮半径--><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文件(根据相应的公式编译好的):
<?xml version="1.0" encoding="utf-8"?><!-- =================================================================================== --><!-- | This document was autogenerated by xacro from demo01_helloworld.urdf.xacro | --><!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | --><!-- =================================================================================== --><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><!-- 3-2.joint --><joint name="left2link" type="continuous"><parent link="base_link"/><child link="left_wheel"/><!-- x 无偏移y 车体半径z z= 车体高度 / 2 + 离地间距 - 车轮半径--><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><!-- 3-2.joint --><joint name="right2link" type="continuous"><parent link="base_link"/><child link="right_wheel"/><!-- x 无偏移y 车体半径z z= 车体高度 / 2 + 离地间距 - 车轮半径--><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:
<!--使用 xacro 优化 URDF 版的小车底盘实现:实现思路:1.将一些常量、变量封装为 xacro:property比如:PI 值、小车底盘半径、离地间距、车轮半径、宽度 ....2.使用 宏 封装驱动轮以及支撑轮实现,调用相关宏生成驱动轮与支撑轮--><!-- 根标签,必须声明 xmlns: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" /> <!-- base_footprint 半径 --><xacro:property name="base_link_radius" value="0.1" /> <!-- base_link 半径 --><xacro:property name="base_link_length" value="0.08" /> <!-- base_link 长 --><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><!-- 1、将 urdf 文件内容设置进参数服务器 --><!-- 方式一:采用传统urdf文件方式 --><!-- <param name="robot_description" textfile="$(find 07urdf_rviz)/urdf/xacro/demo02_car_base.urdf" /> --><!-- 方式二:采用xacro工具来进行编译xacro文件 --><param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_rviz)/urdf/xacro/demo02_car_base.urdf.xacro" /><!-- 2、启动 rivz --><node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" /><!-- 3、启动机器人状态和关节状态发布节点 --><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" /><!-- 4、启动图形化的控制关节运动节点 --><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.bashroslaunch 07urdf_rviz demo05_car_base.launch在当前案例中,我们对摄像头、雷达来进行单独封装文件,最后统一在car.launch里进行统一封装。
最终引用的是没有中文注释的
demo02_car_camera.urdf-z.xacro:带有中文注释的
<!-- 摄像头相关的 xacro 文件 --><robot name="my_camera" xmlns:xacro="http://wiki.ros.org/xacro"><!-- 摄像头属性 --><xacro:property name="camera_length" value="0.01" /> <!-- 摄像头长度(x) --><xacro:property name="camera_width" value="0.025" /> <!-- 摄像头宽度(y) --><xacro:property name="camera_height" value="0.025" /> <!-- 摄像头高度(z) --><xacro:property name="camera_x" value="0.08" /> <!-- 摄像头安装的x坐标 --><xacro:property name="camera_y" value="0.0" /> <!-- 摄像头安装的y坐标 --><xacro:property name="camera_z" value="${base_link_length / 2 + camera_height / 2}" /> <!-- 摄像头安装的z坐标:底盘高度 / 2 + 摄像头高度 / 2 --><!-- 摄像头关节以及link --><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" /> <!-- 支架安装的x坐标 --><xacro:property name="support_y" value="0.0" /> <!-- 支架安装的y坐标 --><xacro:property name="support_z" value="${base_link_length / 2 + support_length / 2}" /> <!-- 支架安装的z坐标:底盘高度 / 2 + 支架高度 / 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" /> <!-- 雷达安装的x坐标 --><xacro:property name="laser_y" value="0.0" /> <!-- 雷达安装的y坐标 --><xacro:property name="laser_z" value="${support_length / 2 + laser_length / 2}" /> <!-- 雷达安装的z坐标:支架高度 / 2 + 雷达高度 / 2 --><!-- 雷达关节以及link --><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><!-- 1、载入urdf模型(这里是去使用xacro编译得到的) --><param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_rviz)/urdf/xacro/car.urdf.xacro" /><!-- 2、启动 rivz --><node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" /><!-- 3、启动机器人状态和关节状态发布节点 --><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" /><!-- 4、启动图形化的控制关节运动节点 --><node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" /></launch>最终我们来进行编译执行launch文件:
source ./devel/setup.bashroslaunch 07urdf_rviz car.launch使用URDF 结合 rviz 可以创建并显示机器人模型。当前实现的只是静态模型,如何控制模型的运动呢?
介绍:Arbotix 是一款控制电机、舵机的控制板,并提供相应的 ros 功能包,这个功能包的功能不仅可以驱动真实的 Arbotix 控制板,它还提供一个差速控制器,通过接受速度控制指令更新机器人的 joint 状态,从而帮助我们实现机器人在 rviz 中的运动。
安装Arbotix
安装Arbotix:
方式一:命令行安装
# 语法:sudo apt-get install ros-<<VersionName()>>-arbotixsudo apt-get install ros-melodic-arbotix方式二:源码包安装
git clone https://github.com/vanadiumlabs/arbotix_ros.git# 接着放入到当前工程目录下,调用 catkin_make 编译catkin_make步骤一:添加一个Arbotix配置文件
demo06_control.launch:
# 该文件是控制器配置,一个机器人模型可能有多个控制器,比如: 底盘、机械臂、夹持器(机械手)....# 因此,根 name 是 controllercontrollers: {# 单控制器设置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><!-- 1、加载xacro文件 --><param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_rviz)/urdf/xacro/car.urdf.xacro" /><!-- 2、启动 rivz --><node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find 07urdf_rviz)/config/show_mycar.rviz" /><!-- 3、启动机器人状态和关节状态发布节点 --><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" /><!-- 集成arbotix运动控制结点,并加载参数 --><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.bashroslaunch 07urdf_rviz demo06_control.launch在启动节点之后,我们可以使用rostopic list查看到当前有一个/cmd_vel的话题,接着我们要是想要机器人动起来就需要去发布控制话题命令:
rostopic pub -r 10 /cmd_vel geometry_msgs/Twist "linear:x: 1.0y: 0.0z: 0.0angular:x: 0.0y: 0.0z: 1.0"流程:
步骤一:创建功能包
# 进入到工程下的src目录cd /home/workspace/roslearn/src# 创建名为07urdf_gazebo的包 引入urdf、xacro、gazebo_ros、gazebo_ros_control、gazebo_pluginscatkin_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><!-- 1、设置碰撞参数 --><!-- 如果是标准几何体,直接复制 visual 的 geometry 和 origin 即可 --><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><!-- 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>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/Red</material></gazebo></robot>步骤三:编写launch文件
demo01_helloworld.launch:
<launch><!-- 将 Urdf 文件的内容加载到参数服务器 --><param name="robot_description" textfile="$(find 07urdf_gazebo)/urdf/demo01_helloworld.urdf" /><!-- 启动 gazebo(使用的是gazbo提供的空世界) --><include file="$(find gazebo_ros)/launch/empty_world.launch" /><!-- 在 gazebo 中显示机器人模型-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>最后来执行ros的launch命令启动节点:
# 启动节点roslaunch 07urdf_gazebo demo01_helloworld.launchURDF 需要与 Gazebo 集成时,和 Rviz 有明显区别:
1、必须使用 collision 标签,因为既然是仿真环境,那么必然涉及到碰撞检测,collision 提供碰撞检测的依据。
2、必须使用 inertial 标签,此标签标注了当前机器人某个刚体部分的惯性矩阵,用于一些力学相关的仿真计算。
3、颜色设置,也需要重新使用 gazebo 标签使用reference标注,因为之前的颜色设置为了方便调试包含透明度,仿真环境下没有此选项。
collision标签
机器人link是标准的几何体形状,和link的 visual 属性设置一致即可,可直接将geometry、origin复制过来。
inertial标签
惯性矩阵的设置需要结合link的质量与外形参数动态生成,标准的球体、圆柱与立方体的惯性矩阵公式如下(已经封装为 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>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 的颜色,必须要使用指定的标签:
head.xacro:之前在6.2中给出的官方各个形状组件实例进行整体封装入一个文件
<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封装文件(带有注释的)
demo02_car_base.urdf.xacro:底盘、支撑轮、驱动轮
<!--使用 xacro 优化 URDF 版的小车底盘实现:实现思路:1.将一些常量、变量封装为 xacro:property比如:PI 值、小车底盘半径、离地间距、车轮半径、宽度 ....2.使用 宏 封装驱动轮以及支撑轮实现,调用相关宏生成驱动轮与支撑轮--><!-- 根标签,必须声明 xmlns:xacro --><robot name="my_base" xmlns:xacro="http://www.ros.org/wiki/xacro"><!-- 封装变量、常量 --><!-- PI 值设置精度需要高一些,否则后续车轮翻转量计算时,可能会出现肉眼不能察觉的车轮倾斜,从而导致模型抖动 --><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" /> <!-- base_footprint 半径 --><xacro:property name="base_link_radius" value="0.1" /> <!-- base_link 半径 --><xacro:property name="base_link_length" value="0.08" /> <!-- base_link 长 --><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/Yellow</material></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/Red</material></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/Red</material></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:摄像机
<!-- 摄像头相关的 xacro 文件 --><robot name="my_camera" xmlns:xacro="http://wiki.ros.org/xacro"><!-- 摄像头属性 --><xacro:property name="camera_length" value="0.01" /> <!-- 摄像头长度(x) --><xacro:property name="camera_width" value="0.025" /> <!-- 摄像头宽度(y) --><xacro:property name="camera_height" value="0.025" /> <!-- 摄像头高度(z) --><xacro:property name="camera_x" value="0.08" /> <!-- 摄像头安装的x坐标 --><xacro:property name="camera_y" value="0.0" /> <!-- 摄像头安装的y坐标 --><xacro:property name="camera_z" value="${base_link_length / 2 + camera_height / 2}" /> <!-- 摄像头安装的z坐标:底盘高度 / 2 + 摄像头高度 / 2 --><xacro:property name="camera_m" value="0.01" /> <!-- 摄像头质量 --><!-- 摄像头关节以及link --><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/Blue</material></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" /> <!-- 支架安装的x坐标 --><xacro:property name="support_y" value="0.0" /> <!-- 支架安装的y坐标 --><xacro:property name="support_z" value="${base_link_length / 2 + support_length / 2}" /> <!-- 支架安装的z坐标:底盘高度 / 2 + 支架高度 / 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/White</material></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" /> <!-- 雷达安装的x坐标 --><xacro:property name="laser_y" value="0.0" /> <!-- 雷达安装的y坐标 --><xacro:property name="laser_z" value="${support_length / 2 + laser_length / 2}" /> <!-- 雷达安装的z坐标:支架高度 / 2 + 雷达高度 / 2 --><xacro:property name="laser_m" value="0.1" /> <!-- 雷达质量 --><!-- 雷达关节以及link --><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/Black</material></gazebo></robot>demo02_gazebo.launch:
<launch><!-- 将 Urdf 文件的内容加载到参数服务器 --><param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_gazebo)/urdf/xacro/car.urdf.xacro" /><!-- 启动 gazebo --><include file="$(find gazebo_ros)/launch/empty_world.launch" /><!-- 在 gazebo 中显示机器人模型 --><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=utf8import sysreload(sys)sys.setdefaultencoding('utf8')将world资源防止到worlds目录下:
demo03_evn.launch:接着我们编写launch文件,在加载gazebo时添加参数来引入world,如下第7行
<launch><!-- 将 Urdf 文件的内容加载到参数服务器 --><param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_gazebo)/urdf/xacro/car.urdf.xacro" /><!-- 启动 gazebo --><include file="$(find gazebo_ros)/launch/empty_world.launch" ><!-- 额外添加加载模型 --><arg name="world_name" value="$(find 07urdf_gazebo)/worlds/box_house.world" /></include><!-- 在 gazebo 中显示机器人模型 --><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 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="left_wheel2base_link" /><xacro:joint_trans joint_name="right_wheel2base_link" /><!-- 控制器 --><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>left_wheel2base_link</leftJoint> <!-- 左轮 --><rightJoint>right_wheel2base_link</rightJoint> <!-- 右轮 --><wheelSeparation>${base_link_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>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><!-- 将 Urdf 文件的内容加载到参数服务器 --><param name="robot_description" command="$(find xacro)/xacro $(find 07urdf_gazebo)/urdf/xacro/car.urdf.xacro" /><!-- 启动 gazebo --><include file="$(find gazebo_ros)/launch/empty_world.launch" ><!-- 额外添加加载模型 --><arg name="world_name" value="$(find 07urdf_gazebo)/worlds/box_house.world" /></include><!-- 在 gazebo 中显示机器人模型 --><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_velrostopic pub -r 10 /cmd_vel geometry_msgs/Twist "linear:x: 0.2y: 0.0z: 0.0angular:x: 0.0y: 0.0z: 0.2"方式二:通过键盘控制teleop_twist_keyboard
# 安装teleop_twist_keyboardsudo 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><!-- 启动 rviz,这里有指定配置rviz文件,你需要提前先保存一份配置才能够成功启动! --><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以及键盘控制组件
# 启动gazeboroslaunch 07urdf_gazebo demo03_evn.launch# 启动rvizroslaunch 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"><!-- 被引用的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><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>注意点:
步骤二:整合摄像头组件
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>接着老样子,启动三个服务:
# 启动gazeboroslaunch 07urdf_gazebo demo03_evn.launch# 启动rvizroslaunch 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>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>步骤二:整个到之前的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>接着启动三个部分:
# 启动gazeboroslaunch 07urdf_gazebo demo03_evn.launch# 启动rvizroslaunch 07urdf_gazebo demo03_evn_rviz.launch# 启动键盘控制rosrun teleop_twist_keyboard teleop_twist_keyboard.pyrviz使用的是之前的camera,我们来选择不同的主题即可
为了能够让其自转,这里我们去发布一个位姿消息:
# 目标话题/cmd_velrostopic pub -r 10 /cmd_vel geometry_msgs/Twist "linear:x: 0.0y: 0.0z: 0.0angular:x: 0.0y: 0.0z: 0.3"效果展示:
/camera/depth/image_raw:深度
/camera/rgb/image_raw:rgb
在rviz中添加PointCloud2,然后去订阅主题:/camera/depth/points
效果展示:
若是出现点云投像显示错误,解决方案如下
主要原因:在kinect中图像数据与点云数据使用了两套坐标系统,且两套坐标系统位姿并不一致。
1、在插件中为kinect设置坐标系,修改配置文件的<frameName>标签内容:
<frameName>support_depth</frameName>2、在启动rviz的launch文件中发布新设置的坐标系到kinect连杆的坐标变换关系
<!-- 添加点云坐标系到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:……