机器人控制系统 ROS2 学习笔记
赵虚左老师 《ROS2 理论与实践》课程笔记,ROS2 基础知识
第1章 环境搭建
(一)ROS2 的安装和配置
(二)ROS2快速体验
- 构建 C++ 源文件、构建 Python 源文件;
- 5个步骤:创建功能包、编辑源文件、修改配置文件、编译、执行;
(三)集成开发环境搭建
- 利用 VSCode 开发、插件和环境配置;
- 如何在一个功能包下创建多个源文件,只需要修改配置文件;
- 安装终端:Terminator;
(四)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核心模块
-
通信相关
应用场景、功能包的应用(二进制命令安装、源码安装、自实现)、分布式;
-
工具相关
-
终端命令与rqt
rqt是一个图形化工具,功能与命令行工具类似;
-
lunch文件
批量地启动多个ROS2节点,是构建大型项目时启动多节点的常用方式;
-
TF坐标变换
实现机器人不同部位(或不同机器人)之间的相对位置的转换;
-
可视化
图形化显示机器人模型;
-
第2章 通信机制的核心

(一)通信机制简介
-
节点
通信对象的构建依赖于节点;系统由多个协同工作的节点组成。
-
话题
Topic是一个纽带,具有相同话题的节点关联到一起,这是节点之间通信的前提。尽管节点是用不同语言实现的,具有相同话题就可以实现数据交互。
-
通信模型

-
接口
接口,即传输的数据的载体。通信时使用的数据载体需要使用接口文件定义。常用的接口文件有三种:msg文件、srv文件与action文件。每种文件都可以按照一定格式定义特定数据类型的“变量”。
- msg文件是用于定义话题通信中数据载体的接口文件;
- srv文件是用于定义服务通信中数据载体的接口文件;
- action文件使用用于定义动作通信中数据载体的接口文件;
- 参数通信的数据无需定义接口文件,参数通信时数据会被封装为参数对象,参数客户端和服务端操作的都是参数对象。
变量类型:不管是何种接口文件,在文件中每行声明的数据都由字段类型和字段名称组成;
(二)话题通信的实现
创建新的工作空间:ws01_plumbging,在工作空间下创建基础的接口功能包base_interfaces_demo;
创建话题通信的功能包:py01_topic;
- 使用话题通信实现原生消息的传输;
第3章 通信机制的补充
第4章 launch与rosbag2

(一)启动文件launch简介
节点是程序的基本构成单元,一个系统的功能模块由多个节点组成,启动某个功能模块需要依次启动这些节点。而launch模块用于实现节点的批量启动。
作用:简化节点的配置与启动,提高程序的启动效率。
(四)录制回放工具rosbag2
在ROS2中实现数据的留存(保存在磁盘中,序列化的过程)及读取,提供了专门的工具:rosbag2。
它是一个用于录制和回放话题的一个工具集,工具的集合。
作用:实现数据的复用,方便调试、测试。
第5章 ROS2工具之坐标变换
在机器人系统中,会经常性的使用到“相对位置关系”这一概念,比如:
机器人自身不同部件的相对位置关系,机器人与出发点的相对位置关系,传感器与障碍物的相对位置关系,机器人组队中不同机器人之间的相对位置关系等等。
ros2中使用坐标变换使用相对位置。

(一)坐标变换简介
tf(TransForm Frame)是指坐标变换,它允许用户随时间跟踪多个坐标系。
在时间缓冲的树结构中维护坐标帧之间的关系,并让用户在任何所需的时间点在任意两个坐标帧之间变换点、向量等。
作用:在ROS中用于实现不同坐标系之间的点或向量的转换。

第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:basefootprint
1. 创建底盘link
2. 创建摄像头link
3. 通过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
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)