227节
本章介绍:
- 如何创建和显示机器人模型;
- 如何构建模拟环境;
- 如何实现机器人模型与模拟环境的交互。
围绕以上三个软件展开
本章的学习目标如下:
228-230节 概述
机器人建模(URDF)、创建仿真环境(Gazebo)感知环境(Rviz)
是 Unified Robot Description Format 首字母缩写直译为,可以以一种 XML 描述机器人的部分结构,如底盘、摄像头、激光雷达、机械臂和不同关节的自由度...,本文件可被接受 C 内置的解释器转换成可视化的机器人模型,是 ROS 机器人仿真的重要组件
是 ROS Visualization Tool 首字母缩写直译为。其主要目的是三维显示ROS新闻,可以 可视化表达数据。例如,激光测距仪可以显示机器人模型,无需编程即可表达(LRF)传感器中的传感 从障碍物到障碍物的距离,RealSense、Kinect或Xtion点云数据等三维距离传感器(PCD, Point Cloud Data),从相机获得的图像值等
以“ros- [ROS_DISTRO] -desktop-full”命令安装ROS时,RViz默认安装。
操作使用命令rviz
或rosrun rviz rviz
如果rviz未安装,请调用以下命令自行安装:
sudo apt install ros-[ROS_DISTRO]-rviz
是一款3D动态模拟器用于显示机器人模型,创建模拟环境,能够在复杂的室内外环境中准确有效地模拟机器人。类似于游戏引擎提供高保真度的视觉模拟,,以及对用户和程序非常友好的交互方式。
以“ros- [ROS_DISTRO] -desktop-full”命令安装ROS时,gzebo默认安装。
操作使用命令gazebo
或rosrun gazebo_ros gazebo
是一款3D动态模拟器用于显示机器人模型,创建模拟环境,能够在复杂的室内外环境中准确有效地模拟机器人。类似于游戏引擎提供高保真度的视觉模拟,Gazebo为用户和程序提供高保真度的物理模拟,提供一套完整的传感器模型和非常友好的交互方式。
以“ros- [ROS_DISTRO] -desktop-full”命令安装ROS时,gzebo默认安装。
操作使用命令gazebo
或rosrun gazebo_ros gazebo
-
urdf - ROS Wiki
-
rviz - ROS Wiki
-
Gazebo : Tutorial : ROS overview
在三者应用中,只创建 URDF 意义不大,一般需要结合 Gazebo 或 Rviz 使用,在 Gazebo 或 Rviz 中可以将 URDF 文件分析为图形机器人模型,一般使用组合为:
-
如果仿真环境,则使用 URDF 结合 Rviz 直接显示感知的真实环境信息
-
如果是模拟环境,则需要使用 URDF 结合 Gazebo 构建模拟环境,结合 Rviz 虚拟环境信息显示感知
素材链接:
- https://github.com/zx595306686/sim_demo.git
复制链接后,找到文件夹打开终端输入:
下载可以试试手机热点
231节 URDF集成Rviz基本流程
URDF 不能单独使用,需要结合 Rviz 或 Gazebo,URDF 只是一个文件,需要 Rviz 或 Gazebo 渲染成图形的机器人模型
-
准备:新功能包的引入依赖
-
核心:编写 urdf 文件
-
核心:在 launch 文件集成 URDF 与 Rviz
-
在 Rviz 显示机器人模型
步骤1:
创建功能包,同时导入下图1中的依赖
在当前功能包下,再建几个目录:
urdf
: 存储 urdf 文件的目录
meshes
:机器人模型渲染文件(暂不使用)
config
: 配置文件
launch
: 存储 launch 启动文件
步骤2:
新建子级文件夹:urdf
(可选)在文件夹中添加一个.urdf
复制以下内容(创建盒子状态的机器人)
<robot name="mycar"> <link name="base_link"> <visual> <geometry> <box size="0.5 0.2 0.1" /> </geometry> </visual> </link> </robot>
将介绍代码的含义部分
步骤3:launch文件编写
<launch> <!-- 载入urdf文件 --> <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/urdf/demo01_helloworld.urdf"/> <!-- 启动rviz --> <node pkg="rviz" type="rviz" name="rviz"/> </launch>
然后c s b编译
点击左下角add,添加robotmodel
然后左边有错误:
需要修改fixed frame和之前的urdf文件中的link_name一致
然后左下角add添加坐标系就可以得到以下效果
232节 上一节优化
避免第二次打开rviz之后还需要配置上一节的哪些步骤:第二次打开urdf配置好了
将其保存到onfug文件夹下,第二次使用时可载入:
左上角file,save xx as,输入名称后保存。
阅读前的配置rviz文件:
修改上一节.launch文件,加入args后面这段
<launch> <!-- 载入urdf文件 --> <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/urdf/demo01_helloworld.urdf"/> <!-- 启动rviz --> <node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz"/> </launch>
------------URDF语法-----------
233节 URDF语法-0 (robot标签)
URDF 文件是标准 XML 文件,在 ROS 一系列标签被定义为描述机器人模型。机器人模型可能很复杂,但是 ROS 的 URDF 中机器人的组成相对简单,可以简化为两部分:连杆(link标签) 与 关节(joint标签),然后我们将通过案例了解它 URDF 中的:
- link 连杆标签
- joint 关节标签
- gazebo 集成gazebo需要使用的标签
关于gazebo标签,后期在使用 gazebo 仿真时,才需要使用到,用于配置仿真环境所需参数,比如: 机器人材料属性、gazebo插件等,但是该标签不是机器人模型必须的,只有在仿真时才需设置
- urdf/XML - ROS Wiki
robot
,所有的 link 和 joint 以及其他标签都必须包含在 robot 标签内,在该标签内可以通过 name 属性设置机器人模型的名称
232-237节 URDF语法-1 link
link 标签用于描述机器人某个部件(也即刚体部分)的外观和物理属性,比如: 机器人底座、轮子、激光雷达、摄像头...
子标签
-
visual ---> 描述外观(对应的数据是可视的)
-
geometry 设置连杆的形状
-
标签1: box(盒状)
- 属性:size=长(x) 宽(y) 高(z)
-
标签2: cylinder(圆柱)
- 属性:radius=半径 length=高度
-
标签3: sphere(球体)
- 属性:radius=半径
-
标签4: mesh(为连杆添加皮肤)
- 属性: filename=资源路径(格式:)
-
-
origin 设置偏移量与倾斜弧度
-
属性1: xyz=x偏移 y便宜 z偏移
-
属性2: rpy=x翻滚 y俯仰 z偏航 (单位是弧度)
-
-
metrial 设置材料属性(颜色)
-
属性: name
-
标签: color
- 属性: rgba=红绿蓝权重值与透明度 (每个权重值以及透明度取值[0,1])
-
-
-
collision ---> 连杆的碰撞属性
-
Inertial ---> 连杆的惯性矩阵
在此,只演示visual
使用。
案例:分别生成长方体、圆柱与球体的机器人部件
launch文件配置
<launch>
<!-- 载入urdf文件 -->
<param name="robot_description" textfile="$(find urdf01_rviz)/urdf/urdf/demo02_link.urdf"/>
<!-- 启动rviz -->
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz"/>
</launch>
1形状
<!-- 设置不同形状的机器人零部件 -->
<robot name="mycar">
<link name="base_link">
<!-- 可视化标签 -->
<visual>
<!-- 形状 -->
<geometry>
<!-- 立方体 -->
<!-- <box size="0.3 0.2 0.1"/> -->
<!-- 圆柱,半径和长度 -->
<!-- <cylinder radius="0.5" length="0.1" /> -->
<!-- 球体,半径-->
<!-- <sphere radius="0.3" /> -->
<!-- 皮肤 -->
<mesh filename="package://urdf01_rviz/meshes/autolabor_mini.stl"/>
</geometry>
<!-- 偏移量和倾斜 -->
<!--
xyz用于设置xyz上的偏移量
rpy用于设置倾斜弧度r(翻滚)p(俯仰)y(偏航)
-->
<origin xyz="0 0 0" rpy="1.57 0 0" />
<!-- 颜色 -->
</visual>
</link>
</robot>
将之前下载的文件夹sim_demo里面的文件复制到下路径,然后编写mesh标签
2偏移量和欧拉角
偏移量即为空间上所处的位置,欧拉角调整的是其的姿态
上面使用mesh标签导入的时候发现小车竖起来了,我们可以调整它的欧拉角,合理需要沿着x(红色)轴顺时针旋转90度(从原点向x轴延伸方向看),即为正方向旋转0度,所以代码改为
<origin xyz="0 0 0" rpy="1.57 0 0" />
即可
3颜色:
238-241节 URDF语法-2 joint-1
joint 标签,还可以指定关节运动的安全极限,机器人的两个部件(分别称之为 parent link 与 child link)以"关节"的形式相连接,不同的关节有不同的运动形式: 旋转、滑动、固定、旋转速度、旋转角度限制....,比如:安装在底座上的轮子可以360度旋转,而摄像头则可能是完全固定在底座上。
joint标签对应的数据在模型中是不可见的
1.属性
-
name ---> 为关节命名
-
type ---> 关节运动形式(这里只用第一个和最后一个 )
-
continuous: 旋转关节,可以绕单轴无限旋转
-
revolute: 旋转关节,类似于 continues,但是有旋转角度限制
-
prismatic: 滑动关节,沿某一轴线移动的关节,有位置极限
-
planer: 平面关节,允许在平面正交方向上平移或旋转
-
floating: 浮动关节,允许进行平移、旋转运动
-
fixed: 固定关节,不允许运动的特殊关节
-
2.子标签
-
parent(必需的)
parent link的名字是一个强制的属性:
- link:父级连杆的名字,是这个link在机器人结构树中的名字。
-
child(必需的)
child link的名字是一个强制的属性:
- link:子级连杆的名字,是这个link在机器人结构树中的名字。
-
origin
- 属性: xyz=各轴线上的偏移量 rpy=各轴线上的偏移弧度。
-
axis
- 属性: xyz用于设置围绕哪个关节轴运动。
案例:创建机器人模型,底盘为长方体,在长方体的前面添加一摄像头,摄像头可以沿着 Z 轴 360 度旋转。
代码中的前两个link在上一节学过
<!--
需求: 设置机器人底盘并添加摄像头
-->
<robot name="mycar">
<!-- 底盘link -->
<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 -->
<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>
<!-- 关节 -->
<joint name="camera2base" type="continuous">
<!-- 父级link和子级link -->
<parent link="base_link"/>
<child link="camera" />
<!-- 需要计算两个 link 的物理中心之间的偏移量 -->
<origin xyz="0.12 0 0.05" rpy="0 0 0" />
<!-- 设置旋转参考的坐标轴,这里围绕z轴旋转 -->
<axis xyz="0 0 1" />
</joint>
</robot>
这里要注意joint文件不能和之前那样书写,不然就会建模失败。
需要添加两个节点(注意编写玩要编译):
<launch>
<param name="robot_description" textfile="$(find urdf01_rviz)/urdf/urdf/demo03_joint.urdf" />
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find urdf01_rviz)/config/show_mycar.rviz" />
<!-- 如果只有上述两个语句就会出现问题:
摄像头显示没有达到预期的位置
因为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>
上图这里第三个节点用于对两个刚体之间的运动(用于测试关节是否运行正常)
运行报错的话这里可以下载:
sudo apt-get install ros-melodic-joint-state-publisher-gui
然后就可以了
注:
这里可能会出现问题:摄像头并没有在车的表面,因为我们的joint相对位置是在相对于两者的几何中心的,我们并没有考虑到摄像头的体积,所以只需要在相对偏移量的基础上添加上摄像头高度的一般即可(改为0.75)。
242节 优化
前面实现的机器人模型是半沉到地下的,因为默认情况下: 底盘的中心点位于地图原点上,所以会导致这种情况产生,可以使用的优化策略,将初始 link 设置为一个尺寸极小的 link(比如半径为 0.001m 的球体,或边长为 0.001m 的立方体),然后再在初始 link 上添加底盘等刚体,这样实现,虽然仍然存在初始link半沉的现象,但是基本可以忽略了。这个初始 link 一般称之为 base_footprint
理解:之前的parentlink是baselink即车体是摄像头的parent,现在又将一个很小的物体作为车体的parent,此时只需要将这个小物体抬高,即可将整个车子抬高。以下在上一节的基础上添加了一个小的link和一个joint
<!--
使用 base_footprint 优化,添加一个极小的link,再去关联初始link与base_link,
关节高度刚好和baselink下沉的高度一致(半个底盘高度)
-->
<robot name="mycar">
<link name="base_footprint">
<visual>
<geometry>
<box size="0.001 0.001 0.001" />
</geometry>
</visual>
</link>
<!-- 底盘link -->
<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 -->
<link name="camera">
<visual>
<geometry>
<box size="0.02 0.05 0.05" />
</geometry>
<!-- 先使用默认(后期需要修改) -->
<origin xyz="0 0 0.025" rpy="0 0 0" />
<material name="camera_color">
<color rgba="0 0 1 0.5" />
</material>
</visual>
</link>
<!-- 关节 -->
<joint name="camera2base" type="continuous">
<!-- 父级link和子级link -->
<parent link="base_link"/>
<child link="camera" />
<!-- 需要计算两个 link 的物理中心之间的偏移量 -->
<origin xyz="0.12 0 0.05" rpy="0 0 0" />
<!-- 设置旋转参考的坐标轴,这里围绕z轴旋转 -->
<axis xyz="0 0 1" />
</joint>
<!-- 关联base_link和base_footprint -->
<joint name="link2footprint" type="fixed">
<!-- 父级link和子级link -->
<parent link="base_footprint"/>
<child link="base_link" />
<!-- 偏移量,这里将其抬高车体的高度 -->
<origin xyz="0 0 0.05" rpy="0 0 0" />
</joint>
</robot>
然后编写对应的launch后进行运行:
注:这里需要把最开始参考的fixed frame改为base_footprint
244-248节 URDF练习
创建一个四轮圆柱状机器人模型,机器人参数如下,底盘为圆柱状,半径 10cm,高 8cm,四轮由两个驱动轮和两个万向支撑轮组成,两个驱动轮半径为 3.25cm,轮胎宽度1.5cm,两个万向轮为球状,半径 0.75cm,底盘离地间距为 1.5cm(与万向轮直径一致)
首先创建好urdf和launch文件
<robot name="mycar">
<link name="base_footprint">
<visual>
<geometry>
<box size="0.001 0.001 0.001" />
</geometry>
</visual>
</link>
<!--
底盘参数
形状:圆柱
半径:10 cm
高度:8 cm
离地:1.5 cm
-->
<link name="base_link">
<visual>
<geometry>
<cylinder radius="0.1" length="0.08" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="baselink_color">
<color rgba="1 0.5 0.2 0.5" />
</material>
</visual>
</link>
<joint name="link2base_footprint" type="fixed">
<parent link="base_footprint" />
<child link="base_link"/>
<!-- 高度=车体高度/2+离地间距 -->
<origin xyz="0 0 0.055" />
</joint>
<!-- 添加驱动轮 -->
<!--
驱动轮是侧翻的圆柱
参数
半径: 3.25 cm
宽度: 1.5 cm
颜色: 黑色
关节设置:
x = 0
y = 底盘的半径 + 轮胎宽度 / 2
z = 离地间距 + 底盘长度 / 2 - 轮胎半径 = 1.5 + 4 - 3.25 = 2.25(cm)
axis = 0 1 0
-->
<link name="left_wheel">
<visual>
<geometry>
<cylinder radius="0.0325" length="0.015" />
</geometry>
<origin xyz="0 0 0" rpy="1.5708 0 0" />
<material name="wheel_color">
<color rgba="0.0 0.0 0.0 0.3" />
</material>
</visual>
</link>
<joint name="left2base_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.5708 0 0" />
<material name="wheel_color">
<color rgba="0.0 0.0 0.0 0.3" />
</material>
</visual>
</link>
<joint name="right2base_link" type="continuous">
<parent link="base_link" />
<child link="right_wheel" />
<origin xyz="0 -0.1 -0.0225" />
<axis xyz="0 1 0" />
</joint>
<!-- 添加万向轮(支撑轮) -->
<!--
参数
形状: 球体
半径: 0.75 cm
颜色: 黑色
关节设置:
x = 自定义(底盘半径 - 万向轮半径) = 0.1 - 0.0075 = 0.0925(cm)
y = 0
z = 底盘长度 / 2 + 离地间距 / 2 = 0.08 / 2 + 0.015 / 2 = 0.0475
axis= 1 1 1
-->
<link name="front_wheel">
<visual>
<geometry>
<sphere radius="0.0075" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="wheel_color">
<color rgba="0.0 0.0 0.0 0.3" />
</material>
</visual>
</link>
<joint name="front_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="front_wheel" />
<origin xyz="0.0925 0 -0.0475" />
<axis xyz="1 1 1" />
</joint>
<link name="back_wheel">
<visual>
<geometry>
<sphere radius="0.0075" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="black">
<color rgba="0.0 0.0 0.0 0.3" />
</material>
</visual>
</link>
<joint name="back_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="back_wheel" />
<origin xyz="-0.0925 0 -0.0475" />
<axis xyz="1 1 1" />
</joint>
</robot>
249节 URDF工具
在 ROS 中,提供了一些工具来方便 URDF 文件的编写,比如:
-
check_urdf
命令可以检查复杂的 urdf 文件是否存在语法问题 -
urdf_to_graphiz
命令可以查看 urdf 模型结构,显示不同 link 的层级关系
当然,要使用工具之前,首先需要安装,安装命令:sudo apt install liburdfdom-tools
在集成终端中打开:
如果存在语法问题就会报出error。
然后是输出关系PDF文件:
------------URDF优化_xacro------------
250节
前面 URDF 文件构建机器人模型的过程中,存在若干问题。
问题1:在设计关节的位置时,需要按照一定的公式计算,公式是固定的,但是在 URDF 中依赖于人工计算,存在不便,容易计算失误,且当某些参数发生改变时,还需要重新计算。
问题2:URDF 中的部分内容是高度重复的,驱动轮与支撑轮的设计实现,不同轮子只是部分参数不同,形状、颜色、翻转量都是一致的,在实际应用中,构建复杂的机器人模型时,更是易于出现高度重复的设计,按照一般的编程涉及到重复代码应该考虑封装。
......
如果在编程语言中,可以通过变量结合函数直接解决上述问题,在 ROS 中,已经给出了类似编程的优化方案,称之为:
Xacro 是 XML Macros 的缩写,Xacro 是一种 XML 宏语言,是可编程的 XML。
Xacro 可以声明变量,可以通过数学运算求解,使用流程控制控制执行顺序,还可以通过类似函数的实现,封装固定的逻辑,将逻辑中需要的可变的数据以参数的方式暴露出去,从而提高代码复用率以及程序的安全性。
251节 Xacro快速体验
使用xacro优化上一节案例中驱动轮实现,需要使用变量封装底盘的半径、高度,使用数学公式动态计算底盘的关节点坐标,使用 Xacro 宏封装轮子重复的代码并调用宏创建两个轮子(注意: 在此,演示 Xacro 的基本使用,不必要生成合法的 URDF )。
准备:在之前创建的xacro文件夹中创建.xacro文件,然后输入以下代码
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 上一节案例中存在几个不足:
1代码复用:Xacro宏(可以理解为函数)
2参数设计: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是不能直接运行的,我们需要将他转换为urdf文件才行:
这里需要运行ros内置的一个节点
首先roscore以下
然后进入xacro目录中输入以下可以输出一个urdf文件:
rosrun xacro xacro demo01_helloworld.urdf.xacro >demo01_helloworld.urdf
252节 xacro语法01
xacro 提供了可编程接口,类似于计算机语言,包括变量声明调用、函数声明与调用等语法实现。在使用 xacro 生成 urdf 时,根标签robot
中: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/>
机器人由多部件组成,不同部件可能封装为单独的 xacro 文件,最后再将不同的文件集成,组合为完整机器人,可以使用文件包含实现
文件包含
<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>
253节 xacro语法02 函数
案例:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 属性定义 -->
<xacro:property name="PI" value="3.1415927"/>
<xacro:property name="radius" value="0.03" />
<!-- 属性调用 -->
<myUsePropertyxxx name="${PI}"/>
<myUsePropertyxxx name="${radius}"/>
<!-- 算数运算 -->
<myUsePropertyxxx name="${PI/2}"/>
<myUsePropertyxxx name="${radius*2}"/>
</robot>
输出:
254节 xacro语法03 宏
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 宏定义 -->
<xacro:macro name="getsum" params="num1 num2">
<result value="${num1+num2}"/>
</xacro:macro>
<!-- 宏调用 -->
<xacro:getsum num1="1" num2="2"/>
</robot>
255节 xacro语法04 文件包含
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 宏定义 -->
<xacro:macro name="getsum" params="num1 num2">
<result value="${num1+num2}"/>
</xacro:macro>
<!-- 宏调用 -->
<xacro:getsum num1="1" num2="2"/>
</robot>
输出结果分别为demo02和demo03中的实现结果
256节 xacro完整使用流程
使用 Xacro 优化 URDF 版的小车底盘模型实现
编写到一半的时候可以先转成urdf再check一下()
1 编写xacro文件(这里只书写了之前那个小车案例的baselink部分)
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- <xacro:property name="" value=""/> -->
<xacro:property name="base_radius" value="0.1"/>
<xacro:property name="base_length" value="0.08"/>
<xacro:property name="lidi" value="0.015"/>
<xacro:property name="base_joint_z" value="${base_length/2+lidi}"/>
<link name="base_footprint">
<visual>
<geometry>
<box size="0.001 0.001 0.001" />
</geometry>
</visual>
</link>
<link name="base_link">
<visual>
<geometry>
<cylinder radius="${base_radius}" length="${base_length}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="baselink_color">
<color rgba="1 0.5 0.2 0.5" />
</material>
</visual>
</link>
<joint name="link2base_footprint" type="fixed">
<parent link="base_footprint" />
<child link="base_link"/>
<!-- 高度=车体高度/2+离地间距 -->
<origin xyz="0 0 ${base_joint_z}" />
</joint>
</robot>
2集成launch文件
方式1先将 xacro 文件转换出 urdf 文件,然后集成(launch文件和之前一样,只是多一步转urdf文件的操作)
方式2:在 launch 文件中直接加载 xacro()
核心代码:
<param name="robot_description" command="$(find xacro)/xacro $(find demo01_urdf_helloworld)/urdf/xacro/my_base.urdf.xacro" />
<launch>
<!-- 将 urdf 文件内容设置进参数服务器 -->
<!-- <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/xacro/demo05_car_base.urdf" /> -->
<param name="robot_description" command="$(find xacro)/xacro $(find urdf01_rviz)/urdf/xacro/demo05_car_base.urdf.xacro" />
<!-- 启动 rivz -->
<node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find urdf01_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>
注:方式1和2的launch文件的区别只用第一行的区别
257-258节 补齐256节代码
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!--
底盘参数
形状:圆柱
半径:10 cm
高度:8 cm
离地:1.5 cm
-->
<!-- <xacro:property name="" value=""/> -->
<xacro:property name="base_radius" value="0.1"/>
<xacro:property name="base_length" value="0.08"/>
<xacro:property name="lidi" value="0.015"/>
<xacro:property name="base_joint_z" value="${base_length/2+lidi}"/>
<link name="base_footprint">
<visual>
<geometry>
<box size="0.001 0.001 0.001" />
</geometry>
</visual>
</link>
<link name="base_link">
<visual>
<geometry>
<cylinder radius="${base_radius}" length="${base_length}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="baselink_color">
<color rgba="1 0.5 0.2 0.5" />
</material>
</visual>
</link>
<joint name="link2base_footprint" type="fixed">
<parent link="base_footprint" />
<child link="base_link"/>
<!-- 高度=车体高度/2+离地间距 -->
<origin xyz="0 0 ${base_joint_z}" />
</joint>
<!-- 添加驱动轮 -->
<!--
驱动轮是侧翻的圆柱
参数
半径: 3.25 cm
宽度: 1.5 cm
颜色: 黑色
关节设置:
x = 0
y = 底盘的半径 + 轮胎宽度 / 2
z = 离地间距 + 底盘长度 / 2 - 轮胎半径 = 1.5 + 4 - 3.25 = 2.25(cm)
axis = 0 1 0
-->
<xacro:property name="wheel_radius" value="0.0325" />
<xacro:property name="wheel_length" value="0.015" />
<xacro:property name="PI" value="3.1415927" />
<xacro:property name="wheel_joint_z" value="${-1*(base_length/2+lidi-wheel_radius)}" />
<!-- 注意结果是负数 -->
<!-- 将车轮封装成宏
wheel_name:left/right
flag:1/-1 表明左轮还是右轮
-->
<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 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} ${wheel_joint_z}" />
<axis xyz="0 1 0" />
</joint>
</xacro:macro>
<!-- 调用上面的宏 -->
<xacro:wheel_func wheel_name="left" flag="1"/>
<xacro:wheel_func wheel_name="right" flag="-1"/>
<!-- 添加万向轮(支撑轮) -->
<!--
参数
形状: 球体
半径: 0.75 cm
颜色: 黑色
关节设置:
x = 自定义(底盘半径 - 万向轮半径) = 0.1 - 0.0075 = 0.0925(cm)
y = 0
z = 底盘长度 / 2 + 离地间距 / 2 = 0.08 / 2 + 0.015 / 2 = 0.0475
axis= 1 1 1
-->
<xacro:property name="small_wheel_radius" value="0.0075"/>
<xacro:property name="small_joint_z" value="${(base_length/2+lidi-small_wheel_radius)*-1}"/>
<xacro:macro name="small_wheel_func" params="small_wheel_name flag">
<link name="${small_wheel_name}_wheel">
<visual>
<geometry>
<sphere radius="${small_wheel_radius}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="wheel_color">
<color rgba="0.0 0.0 0.0 0.3" />
</material>
</visual>
</link>
<joint name="${small_wheel_name}_wheel2base_link" type="continuous">
<parent link="base_link" />
<child link="${small_wheel_name}_wheel" />
<origin xyz="${0.08*flag} 0 ${small_joint_z}" />
<axis xyz="1 1 1" />
</joint>
</xacro:macro>
<xacro:small_wheel_func small_wheel_name="front" flag="1"/>
<xacro:small_wheel_func small_wheel_name="back" flag="-1"/>
</robot>
259-263节 xacro实操
在前面小车底盘基础之上,添加摄像头和雷达传感器。
-
首先编写摄像头和雷达的 xacro 文件
-
然后再编写一个组合文件,组合底盘、摄像头与雷达
-
最后,通过 launch 文件启动 Rviz 并显示模型
首先新创建这三个文件和launch文件
我们要将demo5、6、7、car四者结合到一起
编写car、demo6、demo7和launch代码
<!-- 组合小车底盘与摄像头与雷达,包含底盘、摄像头、雷达-->
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="demo05_car_base.urdf.xacro" />
<xacro:include filename="demo06_car_camera.urdf.xacro" />
<xacro:include filename="demo07_car_laser.urdf.xacro" />
</robot>
<!-- demo06摄像头相关的 xacro 文件 -->
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 摄像头属性 -->
<xacro:property name="camera_length" value="0.02" /> <!-- 摄像头长度(x) -->
<xacro:property name="camera_width" value="0.05" /> <!-- 摄像头宽度(y) -->
<xacro:property name="camera_height" value="0.05" /> <!-- 摄像头高度(z) -->
<xacro:property name="joint_camera_x" value="0.08" /> <!-- 摄像头安装的x坐标 -->
<xacro:property name="joint_camera_y" value="0.0" /> <!-- 摄像头安装的y坐标 -->
<xacro:property name="joint_camera_z" value="${base_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" >
<color rgba="0 0 0 0.8"/>
</material>
</visual>
</link>
<joint name="camera2base" type="fixed">
<parent link="base_link" />
<child link="camera" />
<origin xyz="${joint_camera_x} ${joint_camera_y} ${joint_camera_z}" />
</joint>
</robot>
<!--
小车底盘添加雷达
-->
<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="joint_support_x" value="0.0" /> <!-- 支架安装的x坐标 -->
<xacro:property name="joint_support_y" value="0.0" /> <!-- 支架安装的y坐标 -->
<xacro:property name="joint_support_z" value="${base_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.5" />
</material>
</visual>
</link>
<joint name="support2base_link" type="fixed">
<parent link="base_link" />
<child link="support" />
<origin xyz="${joint_support_x} ${joint_support_y} ${joint_support_z}" />
</joint>
<!-- 雷达属性 -->
<xacro:property name="laser_length" value="0.05" /> <!-- 雷达长度 -->
<xacro:property name="laser_radius" value="0.03" /> <!-- 雷达半径 -->
<xacro:property name="joint_laser_x" value="0.0" /> <!-- 雷达安装的x坐标 -->
<xacro:property name="joint_laser_y" value="0.0" /> <!-- 雷达安装的y坐标 -->
<xacro:property name="joint_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">
<color rgba="0 0 0 0.5"/>
</material>
</visual>
</link>
<joint name="laser2support" type="fixed">
<parent link="support" />
<child link="laser" />
<origin xyz="${joint_laser_x} ${joint_laser_y} ${joint_laser_z}" />
</joint>
</robot>
<launch>
<!-- 将 urdf 文件内容设置进参数服务器 -->
<!-- <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/xacro/demo05_car_base.urdf" /> -->
<param name="robot_description" command="$(find xacro)/xacro $(find urdf01_rviz)/urdf/xacro/car.urdf.xacro" />
<!-- 启动 rivz -->
<node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find urdf01_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>
------------使用arbotix------------
264节 控制机器人运动
通过 URDF 结合 rviz 可以创建并显示机器人模型,不过,当前实现的只是静态模型,如何控制模型的运动呢?在此,可以调用 Arbotix 实现此功能。
Arbotix 是一款控制电机、舵机的控制板,,这个功能包的功能不仅可以驱动真实的 Arbotix 控制板,它还提供一个差速控制器,通过接受速度控制指令更新机器人的 joint 状态,从而帮助我们实现机器人在 rviz 中的运动。
控制机器人模型在 rviz 中做圆周运动
-
安装 Arbotix
-
创建新功能包,准备机器人 urdf、xacro 文件(之前都写了)
-
添加 Arbotix 配置文件
-
编写 launch 文件配置 Arbotix
-
启动 launch 文件并控制机器人模型运动
265节 安装
方式1
sudo apt-get install ros-<<VersionName()>>-arbotix
eg:sudo apt-get install ros-nortic-arbotix
将 <<VsersionName()>> 替换成当前 ROS 版本名称,
如果提示功能包无法定位(上图),请采用方式2
先从 github 下载源码(网速慢可以使用手机流量进行下载)
下载:git clone https://github.com/vanadiumlabs/arbotix_ros.git
将下载好的放入第一层src中
然后调用 catkin_make 即c+s+b 编译
266节 添加 Arbotix 配置文件
到config文件下创建.yaml文件
然后粘贴
# 该文件是控制器配置,一个机器人模型可能有多个控制器,比如: 底盘、机械臂、夹持器(机械手)....
# 因此,根 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
}
}
这里不多做解释
267节 集成arbotix节点
创建launch文件
<launch>
<!-- 将 urdf 文件内容设置进参数服务器 -->
<!-- <param name="robot_description" textfile="$(find urdf01_rviz)/urdf/xacro/demo05_car_base.urdf" /> -->
<param name="robot_description" command="$(find xacro)/xacro $(find urdf01_rviz)/urdf/xacro/car.urdf.xacro" />
<!-- 启动 rivz -->
<node pkg="rviz" type="rviz" name="rviz_test" args="-d $(find urdf01_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" />
<!-- 集成arbotix运动控制节点并且加载参数 -->
<node pkg="arbotix_python" type="arbotix_driver" name="driver" output="screen">
<rosparam file="$(find urdf01_rviz)/config/control.yaml" command="load" />
<param name="sim" value="true" /> <!-- 意味着这是一个仿真环境 -->
</node>
</launch>
注:运行launch文件之前,因为我的python版本是2.7,所以需要在下图中将python3改为2.7才可以。
然后运行launch文件,将下图这里改为odom
然后对话题发布数据来控制机器人做圆周运动
add添加这个之后就有指向箭头
------------URDF集成Gazebo------------
270-271节 基本集成流程案例
URDF 与 Gazebo 集成流程与 Rviz 实现类似,主要步骤如下:
-
创建功能包,导入依赖项
-
编写 URDF 或 Xacro 文件
-
启动 Gazebo 并显示机器人模型
1 创建功能包urdf02_gazebo,依赖于下图2
2编写urdf文件
<robot name="mycar">
<link name="base_link">
<visual>
<geometry>
<box size="0.5 0.2 0.1" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
<material name="yellow">
<color rgba="0.5 0.3 0 0.5"/>
</material>
</visual>
<!-- 设置碰撞参数 -->
<!-- 如果是标准几何体,直接复制visual的geometry和origin即可 -->
<collision>
<geometry>
<box size="0.5 0.2 0.1" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
</collision>
<!-- 设置惯性矩阵 -->
<intertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
<mass value="2">
<inertia ixx="1" ixy="0" ixz="0" iyy="1" iyz="0" izz="1" />
<!-- 惯性矩阵:通过计算的来,这里不详细解释 -->
</intertial>
</link>
<!-- gazebo有自己的颜色设置标签 -->
<gazebo reference="base_link">
<material>Gazebo/Red</material>
</gazebo>
</robot>
3编写launch文件
<launch>
<!-- 步骤1 需要在参数服务器中载入urdf -->
<param name="robot_description" textfile="$(find urdf02_gazebo)/urdf/demo01_helloworld.urdf" />
<!-- 步骤2 启动gazebo -->
<include file="$(find gazebo_ros)/launch/empty_world.launch" />
<!-- 步骤3 在gazebo中添加之前已经做好的(urdf文件中)机器人模型 -->
<node pkg="gazebo_ros" type="spawn_model" name="model" args="-urdf -model mycar -param robot_description" />
</launch>
步骤3代码解释: spawn_model用于模型产卵,args参数中-urdf指的是加载的是urdf数据,-model mycar指的是加载的是名字为mycar的模型,-param robot_description指的是从参数服务器加载数据(和步骤1的param name对应的)
273节 urdf集成gazebo相关设置
如果机器人link是标准的几何体形状,和link的 visual 属性设置一致即可。
惯性矩阵的设置需要结合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>
圆柱:
<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>
需要注意的是,原则上,除了 base_footprint 外,机器人的每个刚体部分都需要设置惯性矩阵,且惯性矩阵必须经计算得出,如果随意定义刚体部分的惯性矩阵,那么可能会导致机器人在 Gazebo 中出现抖动,移动等现象。
3.颜色设置(注意大小写)
在 gazebo 中显示 link 的颜色,必须要使用指定的标签:
<gazebo reference="link节点名称">
<material>Gazebo/Blue</material>
</gazebo>
273-275 URDF集成Gazebo实操
将之前的机器人模型(xacro版)显示在 gazebo 中
-
需要编写封装惯性矩阵算法的 xacro 文件
-
为机器人模型中的每一个 link 添加 collision 和 inertial 标签,并且重置颜色属性
-
在 launch 文件中启动 gazebo 并添加机器人模型
我们将之前写的urdf01中的部分代码(car、demo5、6、7)复制过来稍作修改即可:
编写launch文件(和之前的区别杂鱼command这里):
<launch>
<!-- 需要在参数服务器中载入urdf -->
<param name="robot_description" command="$(find xacro)/xacro $(find urdf02_gazebo)/urdf/car.urdf.xacro" />
<!-- 启动gazebo -->
<include file="$(find gazebo_ros)/launch/empty_world.launch" />
<!-- 在gazebo中添加机器人模型 -->
<node pkg="gazebo_ros" type="spawn_model" name="spawn_model" args="-urdf -model mycar -param robot_description" />
</launch>
然后修改demo05,核心多个link中添加下面两段(注:注意惯性函数在collision外面;使用参数的值的时候要加上${};<gazebo reference=中写的是当前robot的name)
<collision>
<geometry>
<cylinder radius="${base_radius}" length="${base_length}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
</collision>
<!-- 调用head中的惯性矩阵函数 -->
<xacro:cylinder_inertial_matrix m="${base_mass}" r="${base_radius}" h="${base_length}"/>
<gazebo reference="base_link">
<material>Gazebo/Red</material>
</gazebo>
全部demo05、06、07代码:
<robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro">
<!--
底盘参数
形状:圆柱
半径:10 cm
高度:8 cm
离地:1.5 cm
-->
<!-- <xacro:property name="" value=""/> -->
<xacro:property name="base_radius" value="0.1"/>
<xacro:property name="base_length" value="0.08"/>
<xacro:property name="base_mass" value="2"/>
<xacro:property name="small_wheel_mass" value="0.01"/>
<xacro:property name="wheel_mass" value="0.05"/>
<xacro:property name="lidi" value="0.015"/>
<xacro:property name="base_joint_z" value="${base_length/2+lidi}"/>
<link name="base_footprint">
<visual>
<geometry>
<box size="0.001 0.001 0.001" />
</geometry>
</visual>
</link>
<link name="base_link">
<visual>
<geometry>
<cylinder radius="${base_radius}" length="${base_length}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="baselink_color">
<color rgba="1 0.5 0.2 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="${base_radius}" length="${base_length}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
</collision>
<!-- 调用head中的惯性矩阵函数 -->
<xacro:cylinder_inertial_matrix m="${base_mass}" r="${base_radius}" h="${base_length}"/>
</link>
<gazebo reference="base_link">
<material>Gazebo/Yellow</material>
</gazebo>
<joint name="link2base_footprint" type="fixed">
<parent link="base_footprint" />
<child link="base_link"/>
<!-- 高度=车体高度/2+离地间距 -->
<origin xyz="0 0 ${base_joint_z}" />
</joint>
<!-- 添加驱动轮 -->
<!--
驱动轮是侧翻的圆柱
参数
半径: 3.25 cm
宽度: 1.5 cm
颜色: 黑色
关节设置:
x = 0
y = 底盘的半径 + 轮胎宽度 / 2
z = 离地间距 + 底盘长度 / 2 - 轮胎半径 = 1.5 + 4 - 3.25 = 2.25(cm)
axis = 0 1 0
-->
<xacro:property name="wheel_radius" value="0.0325" />
<xacro:property name="wheel_length" value="0.015" />
<xacro:property name="PI" value="3.1415927" />
<xacro:property name="wheel_joint_z" value="${-1*(base_length/2+lidi-wheel_radius)}" />
<!-- 注意结果是负数 -->
<!-- 将车轮封装成宏
wheel_name:left/right
flag:1/-1 表明左轮还是右轮
-->
<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 0.0 0.3" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="${wheel_radius}" length="${w