第1章 环境搭建
ROS2__2">(一)ROS2 的安装和配置
ROS2_4">(二)ROS2快速体验
- 构建 C++ 源文件、构建 Python 源文件;
- 5个步骤:创建功能包、编辑源文件、修改配置文件、编译、执行;
(三)集成开发环境搭建
- 利用 VSCode 开发、插件和环境配置;
- 如何在一个功能包下创建多个源文件,只需要修改配置文件;
- 安装终端:Terminator;
ROS2_15">(四)ROS2体系框架
-
创建工作空间:
mkdir -p [工作空间名]/src # 创建文件夹 cd [工作空间名]/ # 进入文件夹 colcon build # 构建工作空间
-
一个工作空间的结构:
-
资源初始化与资源释放:
-
配置文件
C++功能包的构建信息主要包含在
package.xml
与CMakeLists.txt
中;Python功能包的构建信息则主要包含在
package.xml
和setup.py
中。 -
操作命令
ROS2的文件系统核心是功能包,我们可以通过编译指令
colcon
和ROS2内置的工具指令ros2
来实现功能包的创建、编译、查找与执行等相关操作。-
创建功能包
新建功能包语法如下:
ros2 pkg create 包名 --build-type 构建类型 --dependencies 依赖列表 --node-name 可执行程序名称
格式解释:
--build-type
:是指功能包的构建类型,有cmake、ament_cmake、ament_python三种类型可选;不填默认为 ament_cmake;--dependencies
:所依赖的功能包列表;--node-name
:可执行程序的名称,会自动生成对应的源文件并生成配置文件。
-
编译
编译功能包语法如下:colcon build
或
colcon build --packages-select [功能包列表]
前者会构建工作空间下的所有功能包,后者可以构建指定功能包。
-
执行
执行命令语法如下:. install/setup.bash # 刷新setup文件 ros2 run 功能包 可执行程序 参数
-
查找
在ros2 pkg
命令下包含了多个查询功能包相关信息的参数。ros2 pkg executables [包名] # 输出所有功能包或指定功能包下的可执行程序。 ros2 pkg list # 列出所有功能包 ros2 pkg prefix 包名 # 列出功能包路径 ros2 pkg xml # 输出功能包的package.xml内容
-
ROS2_87">(五)ROS2核心模块
-
通信相关
应用场景、功能包的应用(二进制命令安装、源码安装、自实现)、分布式;
-
工具相关
第2章 通信机制的核心
(一)通信机制简介
-
节点
通信对象的构建依赖于节点;系统由多个协同工作的节点组成。
-
话题
Topic是一个纽带,具有相同话题的节点关联到一起,这是节点之间通信的前提。尽管节点是用不同语言实现的,具有相同话题就可以实现数据交互。
-
通信模型
-
接口
接口,即传输的数据的载体。通信时使用的数据载体需要使用接口文件定义。常用的接口文件有三种:msg文件、srv文件与action文件。每种文件都可以按照一定格式定义特定数据类型的“变量”。
- msg文件是用于定义话题通信中数据载体的接口文件;
- srv文件是用于定义服务通信中数据载体的接口文件;
- action文件使用用于定义动作通信中数据载体的接口文件;
- 参数通信的数据无需定义接口文件,参数通信时数据会被封装为参数对象,参数客户端和服务端操作的都是参数对象。
变量类型:不管是何种接口文件,在文件中每行声明的数据都由字段类型和字段名称组成;
(二)话题通信的实现
创建新的工作空间:ws01_plumbging
,在工作空间下创建基础的接口功能包base_interfaces_demo
;
创建话题通信的功能包:py01_topic
;
- 使用话题通信实现原生消息的传输;
第3章 通信机制的补充
第4章 launch与rosbag2
(一)启动文件launch简介
节点是程序的基本构成单元,一个系统的功能模块由多个节点组成,启动某个功能模块需要依次启动这些节点。而launch模块用于实现节点的批量启动。
作用:简化节点的配置与启动,提高程序的启动效率。
(四)录制回放工具rosbag2
在ROS2中实现数据的留存(保存在磁盘中,序列化的过程)及读取,提供了专门的工具:rosbag2。
它是一个用于录制和回放话题的一个工具集,工具的集合。
作用:实现数据的复用,方便调试、测试。
ROS2_170">第5章 ROS2工具之坐标变换
在机器人系统中,会经常性的使用到“相对位置关系”这一概念,比如:
机器人自身不同部件的相对位置关系,机器人与出发点的相对位置关系,传感器与障碍物的相对位置关系,机器人组队中不同机器人之间的相对位置关系等等。
ros2中使用坐标变换使用相对位置。
(一)坐标变换简介
tf(TransForm Frame)是指坐标变换,它允许用户随时间跟踪多个坐标系。
在时间缓冲的树结构中维护坐标帧之间的关系,并让用户在任何所需的时间点在任意两个坐标帧之间变换点、向量等。
作用:在ROS中用于实现不同坐标系之间的点或向量的转换。
ROS2_191">第6章 ROS2工具之可视化
(一)可视化简介
在前面人机交互的过程中,开发者在终端启动程序来下发数据,程序运行过程中通过命令行的工具来获取机器人发布的数据。这种方式不够直观。
ROS2提供了rviz2这个图形化用户接口,通过这个接口调用者可以用“可视化”的方式与机器人交互。
rviz 即 ROS Visualization Tool,ROS2的三维可视化工具。目的是以三维方式显示ROS消息,并将数据进行可视化表达。如显示机器人模型、激光雷达数据、三维点云数据、从相机获取图像值等。
机器人建模由 URDF 实现。
URDF 即 Unified Robot Description Format,统一(标准化)机器人描述格式。能够以XML文件的方式描述机器人的部分结构。
(二)rviz2的基本使用
-
启动
rviz2
-
左侧插件
(三)rviz2集成URDF
准备工作:
- 安装所需功能包;
- 新建功能包;
- 功能包下新建 urdf、rviz、launch、meshes目录以备用,其中 urdf 目录下再新建子目录 urdf 与 xacro。
正式工作:
-
编写 URDF 文件;
- URDF语法;
-
编写 launch 文件:加载urdf文件并在rviz2中显示机器人模型;
核心:
- 启动robot_state_publisher节点,该节点要以参数的方式加载urdf文件内容;
- 启动rviz2节点;
优化:
-
添加 joint_state_publisher 节点(当机器人有非固定关节时,必须包含该节点);
-
设置 rviz2 的默认配置文件;
可以打开之前设置好插件的rviz2;
-
动态传入 urdf 文件,把 urdf 文件封装为参数;
动态传参启动任意 urdf 文件: ros2 launch cpp06_urdf display.launch.py model:=`ros2 pkg prefix --share cpp06_urdf`/urdf/urdf/xxx.urdf
-
编辑配置文件;
- package.xml:在 package.xml 中需要手动添加一些执行时依赖;
- CMakeLists.txt:在功能包下,新建了若干目录,需要为这些目录配置安装路径;
-
编译;
-
执行 launch 文件并在 rviz2 加载机器人模型。
工作空间下: colcon build --packages-select cpp06_urdf . install/setup.bash ros2 launch cpp06_urdf display.launch.py
(四)URDF语法
(1) <robot>
<robot name="mycar"></robot>
属性
- name:主文件必须具有名称属性;被包含文件如果指定名称属性,需要和主文件一致;
子标签
其他标签都是其子级标签。
(2) <link>
属性
- name(必填):为连杆命名。
子标签
<visual>
(可选):用于描述link的可视化属性,可以设置link的形状(立方体、球体、圆柱等)。
name
(可选):指定link名称,此名称会映射为同名坐标系,还可以通过引用该值定位定位link。<geometry>
(必填):用于设置link的形状,比如:立方体、球体或圆柱。<box>
:立方体标签,通过size属性设置立方体的边长,原点为其几何中心。<cylinder>
:圆柱标签,通过radius属性设置圆柱半径,通过length属性设置圆柱高度,原点为其几何中心。<sphere>
:球体标签,通过radius属性设置球体半径,原点为其几何中心。<mesh>
:通过属性filename引用“皮肤”文件,为link设置外观,该文件必须是本地文件。使用package://<packagename>/<path>
为文件名添加前缀。
<origin>
(可选):用于设置link的相对偏移量以及旋转角度,如未指定则使用默认值(无偏移且无旋转)。xyz
:表示x、y、z三个维度上的偏移量(以米为单位),不同数值之间使用空格分隔,如未指定则使用默认值(三个维度无偏移)。rpy
:表示翻滚、俯仰与偏航的角度(以弧度为单位),不同数值之间使用空格分隔,如未指定则使用默认值(三个维度无旋转)。
<material>
(可选):视觉元素的材质。也可以在根标签robot中定义material标签,然后,可以在link中按名称进行引用。name
(必填):为material指定名称,可以通过该值进行引用。<color>
(可选):rgba 材质的颜色,由代表red/green/blue/alpha 的四个数字组成,每个数字的范围为 [0,1]。<texture>
(可选):材质的纹理,可以由属性filename设置。
<collision>
(可选):link的碰撞属性。
可以与link的视觉属性一致,也可以不同,比如:我们会通常使用更简单的碰撞模型来减少计算时间,或者设置的值大于link的视觉属性,以尽量避免碰撞。另外,同一链接可以存在多个<collision>
标签实例,多个几何图形组合表示link的碰撞属性。
name
(可选):为collision设置名称。<geometry>
(必须):请参考visual标签的geometry使用规则。<origin>
(可选):请参考visual标签的origin使用规则。
<inertial>
(可选):用于设置link的质量、质心位置和中心惯性特性。如果未指定,则默认为质量为0、惯性为0。
<origin>
(可选):该位姿(平移、旋转)描述了链接的质心框架 C 相对于链接框架 L 的位置和方向。xyz
:表示从 Lo(链接框架原点)到 Co(链接的质心)的位置向量为 x L̂x + y L̂y + z L̂z,其中 L̂x、L̂y、L̂z 是链接框架 L 的正交单位向量。rpy
:将 C 的单位向量 Ĉx、Ĉy、Ĉz 相对于链接框架 L 的方向表示为以弧度为单位的欧拉旋转序列 (r p y)。注意:Ĉx、Ĉy、Ĉz 不需要与连杆的惯性主轴对齐。
<mass>
(必填):通过其value属性设置link的质量。<inertia>
(必填):对于固定在质心坐标系 C 中的单位向量 Ĉx、Ĉy、Ĉz,该连杆的惯性矩 ixx、iyy、izz 以及关于 Co(连杆的质心)的惯性 ixy、ixz、iyz 的乘积。
实战
生成不同形状的机器人部件;
(3) <joint>
属性
- name(必填):为关节命名,名称需要唯一。
- type(必填):设置关节类型,可用类型如下:
- continuous:旋转关节,可以绕单轴无限旋转。
- revolute:旋转关节,类似于 continues,但是有旋转角度限制。
- prismatic:滑动关节,沿某一轴线移动的关节,有位置极限。
- planer:平面关节,允许在平面正交方向上平移或旋转。
- floating:浮动关节,允许进行平移、旋转运动。
- fixed:固定关节,不允许运动的特殊关节。
子标签
<parent>
(必填):指定父级link。- link(必填):父级link的名字,是这个link在机器人结构树中的名字。
<child>
(必填):指定子级link。- link(必填):子级link的名字,是这个link在机器人结构树中的名字。
<origin>
(可选):这是从父link到子link的转换,关节位于子link的原点(中心)。- xyz:各轴线上的偏移量。
- rpy:各轴线上的偏移弧度。
<axis>
(可选):如不设置,默认值为(1,0,0)。- xyz:用于设置围绕哪个关节轴运动。
<calibration>
(可选):关节的参考位置,用于校准关节的绝对位置。- rising(可选):当关节向正方向移动时,该参考位置将触发上升沿。
- falling(可选):当关节向正方向移动时,该参考位置将触发下降沿。
<dynamics>
(可选):指定接头物理特性的元素。这些值用于指定关节的建模属性,对仿真较为有用。- damping(可选):关节的物理阻尼值,默认为0。
- friction(可选):关节的物理静摩擦值,默认为0。
<limit>
(关节类型是revolute或prismatic时为必须的):- lower(可选):指定关节下限的属性(旋转关节以弧度为单位,棱柱关节以米为单位)。如果关节是连续的,则省略。
- upper(可选):指定关节上限的属性(旋转关节以弧度为单位,棱柱关节以米为单位)。如果关节是连续的,则省略。
- effort(必填):指定关节可受力的最大值。
- velocity(必填):用于设置最大关节速度(旋转关节以弧度每秒 [rad/s] 为单位,棱柱关节以米每秒 [m/s] 为单位)。
<mimic>
(可选):此标签用于指定定义的关节模仿另一个现有关节。该关节的值可以计算为value = multiplier * other_joint_value + offset
。- joint(必填):指定要模拟的关节的名称。
- multiplier(可选):指定上述公式中的乘法因子。
- offset(可选):指定要在上述公式中添加的偏移量,默认为 0(旋转关节的单位是弧度,棱柱关节的单位是米)。
<safety_controller>
(可选):安全控制器。- soft_lower_limit(可选):指定安全控制器开始限制关节位置的下关节边界,此限制需要大于joint下限。
- soft_upper_limit(可选):指定安全控制器开始限制关节位置的关节上边界的属性,此限制需要小于joint上限。
- k_position(可选):指定位置和速度限制之间的关系。
- k_velocity(必填):指定力和速度限制之间的关系。
实战
创建机器人模型,底盘为长方体,在长方体前面添加一个摄像头。摄像头可以沿着Z轴360度旋转;
将半沉入地下的模型移上去;
<!-- 需求:创建机器人模型,底盘为长方体,在长方体前面添加一个摄像头。摄像头可以沿着Z轴360度旋转。实现:0. 设置初始化link:basefootprint1. 创建底盘link2. 创建摄像头link3. 通过joint关联底盘和摄像头
-->
<robot name="myCar">S<!-- 抽取颜色 --><material name="yellow"><color rgba="0.8 0.8 0 0.8"/></material><material name="red"><color rgba="0.9 0 0 0.8"/></material><!-- 0. 设置初始化link:basefootprint --><link name="base_footprint"><visual><geometry><sphere radius="0.01"/><material name="yellow"/></geometry></visual></link><!-- 1. 创建底盘link --><link name="base_link"><visual><geometry><box size="0.5 0.3 0.1"/></geometry><origin xyz="0 0 0.0" rpy="0.0 0.0 0.0"/><material name="yellow"/></visual></link><!-- 初始化link通过关节连接base_link,设置关节的偏移量,让baselink上移 --><joint name="base_link2base_footprint" type="fixed"><parent link="base_footprint"/><child link="base_link"/><origin xyz="0 0 0.05"/></joint><!-- 2. 创建摄像头link --><link name="camera"><visual><geometry><box size="0.02 0.05 0.05"/></geometry><material name="red"/></visual></link><!-- 3. 通过joint关联底盘和摄像头 --><joint name="camera2base_link" type="continuous"><parent link="base_link"/><child link="camera"/><!-- 设置平移量和旋转度:因为关节位于子link的原点(中心),所以这里其实是设置的子link的平移量和旋转度 --><origin xyz="0.2 0.0 0.075" rpy="0.0 0.0 0.0"/><!-- 设置沿何轴旋转 --><axis xyz="0 0 1"/><!-- 新建终端,执行命令 ros2 run joint_state_publisher_gui joint_state_publisher_gui 控制旋转--></joint>
</robot>
(4) urdf练习:四轮机器人模型
<!-- 需求:创建一个四轮机器人模型;参数:长20cm宽12cm高7cm,车轮半径为2.5cm,车轮厚度为2cm,底盘离地间距为 1.5cm。长0.2m,宽0.12米,高0.07米;轮胎半径0.025,宽0.02,离地间距0.015;--><robot name="myCar"><material name="blue"><color rgba="0.0 0.4 0.6 0.6"/></material><material name="black"><color rgba="0 0 0 0.8"/></material> <!-- 1. 设置base_footprint --><link name="base_footprint"><visual><geometry><sphere radius="0.01"/></geometry></visual></link><!-- 2. 设置base_link --><link name="base_link"><visual><geometry><box size="0.2 0.12 0.07"/></geometry><material name="blue"/></visual></link><!-- 3. 使用joint将两者关联 --><joint name="base_link2base_footprint" type="fixed"><parent link="base_footprint"/><child link="base_link"/><origin xyz="0 0 0.05" rpy="0.0 0.0 0.0"/></joint><!-- 4. 添加车轮link --><link name="left_front_wheel" type="revolute"><visual><geometry><cylinder radius="0.025" length="0.02"/></geometry><material name="black"/><!-- 车轮立起来,设置roll为90度 --><origin xyz="0 0.0 0.0" rpy="1.57 0.0 0.0"/></visual></link><!-- 5. 将车轮和base_link连接起来 --><joint name="left_front_wheel2base_link" type="continuous"><parent link="base_link"/><child link="left_front_wheel"/><!-- 车轮偏移到左前方 --><origin xyz="0.07 0.06 -0.025" rpy="0.0 0.0 0.0"/><!-- 车轮绕y轴旋转;注意joint_state_publisher暂停使用 --><axis xyz="0.0 1 0.0"/></joint><!-- 6. 其他车轮实现 --><link name="right_front_wheel" type="revolute"><visual><geometry><cylinder radius="0.025" length="0.02"/></geometry><material name="black"/><origin xyz="0 0.0 0.0" rpy="1.57 0.0 0.0"/></visual></link><joint name="right_front_wheel2base_link" type="continuous"><parent link="base_link"/><child link="right_front_wheel"/><origin xyz="0.07 -0.06 -0.025" rpy="0.0 0.0 0.0"/><axis xyz="0.0 1 0.0"/></joint><link name="left_behind_wheel" type="revolute"><visual><geometry><cylinder radius="0.025" length="0.02"/></geometry><material name="black"/><origin xyz="0 0.0 0.0" rpy="1.57 0.0 0.0"/></visual></link><joint name="left_behind_wheel2base_link" type="continuous"><parent link="base_link"/><child link="left_behind_wheel"/><origin xyz="-0.07 0.06 -0.025" rpy="0.0 0.0 0.0"/><axis xyz="0.0 1 0.0"/></joint><link name="right_behind_wheel" type="revolute"><visual><geometry><cylinder radius="0.025" length="0.02"/></geometry><material name="black"/><origin xyz="0 0.0 0.0" rpy="1.57 0.0 0.0"/></visual></link><joint name="right_behind_wheel2base_link" type="continuous"><parent link="base_link"/><child link="right_behind_wheel"/><origin xyz="-0.07 -0.06 -0.025" rpy="0.0 0.0 0.0"/><axis xyz="0.0 1 0.0"/></joint>
</robot>
(5) urdf工具
-
check_urdf fileName
命令可以检查复杂的 urdf 文件是否存在逻辑语法问题;在直接运行的时候,只会判断是否有直接语法错误,而不会进行深入判断,打开之后会不会生成模型;可以用这个工具来找出逻辑语法出错的地方;
如果没有错误,则会给出link之间的树形关系。
-
urdf_to_graphviz fileName
命令可以查看 urdf 模型结构,显示不同 link 的层级关系。生成gv和pdf文件,pdf文件中生成树形关系的图形化展示,更加直观的给出层级关系。
使用工具之前,先安装命令:sudo apt install liburdfdom-tools
。
建议终端运行在urdf目录下,方便选择文件;
(五) xacro_URDF的优化
xacro 提供了可编程接口,类似于计算机语言,包括变量声明调用、函数声明与调用等语法实现。在使用 xacro 生成 urdf 时,根标签robot
中必须包含命名空间声明:xmlns:xacro="http://wiki.ros.org/xacro"
。
(1) 使用语法
1.变量与算数运算
-
变量定义:
<xacro:property .../>
<xacro:property name="变量名" value="变量值" />
-
变量调用:
${变量名}
<geometry><cylinder radius="${radius}" length="${length}" /> </geometry>
-
变量运算:
${数学表达式}
<origin xyz="0 0 0" rpy="${PI / 2} 0 0" />
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="demo02_propority"><!-- 变量声明 --><!-- 定义两个数值型变量,一个10一个20 --><xacro:property name="num1" value="10"/><xacro:property name="num2" value="20"/><!-- 变量调用 --><car length="${num1}" width="${num2}"/><!-- 解析后:<car length="10" width="20"/> --><!-- 变量运算 --><sum value = "${num1 + num2}"/><sum value = "${num1 * num2}"/><!-- <sum value="30"/><sum value="200"/> -->
</robot>
2.宏
类似于函数实现,提高代码复用率,优化代码结构,提高安全性。
-
宏定义
<xacro:macro name="宏名称" params="参数列表(多参数之间使用空格分隔)">.....参数调用格式: ${参数名} </xacro:macro>
-
宏调用
<xacro:宏名称 参数1=xxx 参数2=xxx/>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="demo03_function"><!-- 宏定义 --><xacro:macro name="get_sum" params="num1 num2"><sum value = "${num1 + num2}"/></xacro:macro><!-- 宏调用 --><xacro:get_sum num1 = "20" num2 = "30"/><xacro:get_sum num1 = "70" num2 = "30"/>
</robot><!-- 解析后 -->
<robot name="demo03_function"><sum value="50"/><sum value="100"/>
</robot>
3.文件包含
机器人由多部件组成,不同部件可能封装为单独的 xacro 文件,最后再将不同的文件集成,组合为完整机器人,可以使用文件包含实现。
语法格式:
<xacro:include filename="其他xacro文件" />
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="demo04_include"><xacro:include filename="demo02_propority.urdf.xacro"/><xacro:include filename="demo03_function.urdf.xacro"/></robot>
<!-- 解析后 -->
<robot name="demo04_include"><car length="10" width="20"/><sum value="30"/><sum value="200"/><sum value="50"/><sum value="100"/>
</robot>
(2) 练习
使用xacro创建一个四轮机器人模型,并且在底盘之上添加了相机与激光雷达。
需求中的机器人模型是由底盘、摄像头和雷达三部分组成的,那么可以将每一部分都封装进一个xacro文件,最后再通过xacro文件包含组织成一个完整的机器人模型。
- car.urdf.xacro:用于包含不同机器人部件对应的xacro文件;
- car_base.urdf.xacro:描述机器人底盘的xacro文件;
- car_camera.urdf.xacro:描述摄像头的xacro文件;
- car_laser.urdf.xacro:描述雷达的xacro文件。
<!-- 主文件 --><robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="myCar"><xacro:include filename = "02.car_base.urdf.xacro"/><xacro:include filename = "03.car_camera.urdf.xacro"/><xacro:include filename = "04.car_laser.urdf.xacro"/>
</robot>
<!-- 车体实现需求:创建一个四轮机器人模型;参数:长20cm宽12cm高7cm,车轮半径为2.5cm,车轮厚度为2cm,底盘离地间距为 1.5cm。
--><robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="myCar"><!-- 1. 声明相关变量 --><xacro:property name = "car_length" value = "0.2"/><xacro:property name = "car_width" value = "0.12"/><xacro:property name = "car_height" value = "0.07"/><xacro:property name = "car_distance" value = "0.015"/><xacro:property name = "wheel_radius" value = "0.025"/><xacro:property name = "wheel_length" value = "0.02"/><xacro:property name = "PI" value = "3.141592654"/><xacro:property name = "wheel_joint_x" value = "0.08"/><xacro:property name = "wheel_joint_y" value = "${car_width / 2}"/><xacro:property name = "wheel_joint_z" value = "${-(car_height / 2 + car_distance - wheel_radius)}"/><material name="blue"><color rgba="0.0 0.4 0.6 0.6"/></material><material name="black"><color rgba="0 0 0 0.8"/></material> <!-- 2. 设置base_footprint --><link name="base_footprint"><visual><geometry><sphere radius="0.01"/></geometry></visual></link><!-- 3. 设置base_link --><link name="base_link"><visual><geometry><box size="${car_length} ${car_width} ${car_height}"/></geometry><material name="blue" /></visual></link><!-- 4. 使用joint将两者关联 --><joint name="base_link2base_footprint" type="fixed"><parent link="base_footprint"/><child link="base_link"/><origin xyz="0.0 0.0 ${car_height / 2 + car_distance}" rpy="0.0 0.0 0.0"/></joint><!-- 5. 定义车轮相关的宏 --><!-- 函数创建原则:封装可复用代码,变化的数据以参数的形式暴露出去--><xacro:macro name = "wheel_func" params = "link_name front_flag left_flag"><link name = "${link_name}"><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="${link_name}2base_link" type="continuous"><parent link="base_link"/><child link="${link_name}"/><origin xyz="${front_flag * wheel_joint_x} ${left_flag * wheel_joint_y} ${wheel_joint_z}" rpy="0.0 0.0 0.0"/><axis xyz="0 1 0"/></joint></xacro:macro><!-- 6. 调用宏生成多个车轮 --><xacro:wheel_func link_name = "front_left" front_flag = "1" left_flag = "1"/><xacro:wheel_func link_name = "front_right" front_flag = "1" left_flag = "-1"/><xacro:wheel_func link_name = "back_left" front_flag = "-1" left_flag = "1"/><xacro:wheel_func link_name = "back_right" front_flag = "-1" left_flag = "-1"/>
</robot>
<!-- 摄像头实现 --><robot xmlns:xacro="http://www.ros.org/wiki/xacro"><!-- 1. 声明参数 --><xacro:property name = "camera_x" value = "0.01" /><xacro:property name = "camera_y" value = "0.06" /><xacro:property name = "camera_z" value = "0.01" /><xacro:property name = "joint_x" value = "${car_length / 2 - 0.01}" /><xacro:property name = "joint_y" value = "0" /><xacro:property name = "joint_z" value = "${car_height / 2 + camera_z / 2}" /><!-- 2. 设置link 和 joint --><link name="camera"><visual><geometry><box size="${camera_x} ${camera_y} ${camera_z}"/></geometry></visual></link><joint name="camera2base_link" type="fixed"><parent link="base_link"/><child link="camera"/><origin xyz="${joint_x} ${joint_y} ${joint_z}" rpy="0.0 0.0 0.0"/></joint>
</robot>
<!-- 雷达实现 --><robot xmlns:xacro="http://www.ros.org/wiki/xacro"><xacro:property name = "laser_radius" value = "0.03" /><xacro:property name = "laser_length" value = "0.02" /><xacro:property name = "joint_x" value = "0" /><xacro:property name = "joint_y" value = "0" /><xacro:property name = "joint_z" value = "${car_height / 2 + laser_length / 2}" /><material name = "yellow"><color rgba="0.8 0.6 0.0 0.8"/></material><link name="laser_link"><visual><geometry><cylinder radius="${laser_radius}" length="${laser_length}"/></geometry><material name="yellow" /></visual></link><joint name="laser_link2base_link" type="fixed"><parent link="base_link"/><child link="laser_link"/><origin xyz="${joint_x} ${joint_y} ${joint_z}" rpy="0.0 0.0 0.0"/></joint>
</robot>
参考:
https://www.bilibili.com/video/BV1VB4y137ys/?vd_source=1dda1a2cde2fbc0cd61488c797e9b78b