第1章 环境搭建

(一)ROS2 的安装和配置

(二)ROS2快速体验

  • 构建 C++ 源文件、构建 Python 源文件;
  • 5个步骤:创建功能包、编辑源文件、修改配置文件、编译、执行;

(三)集成开发环境搭建

  • 利用 VSCode 开发、插件和环境配置;
  • 如何在一个功能包下创建多个源文件,只需要修改配置文件;
  • 安装终端:Terminator;

(四)ROS2体系框架

  • 创建工作空间:

    mkdir -p [工作空间名]/src	# 创建文件夹
    cd [工作空间名]/		# 进入文件夹
    colcon build 	# 构建工作空间
    
  • 一个工作空间的结构:
    在这里插入图片描述

  • 资源初始化与资源释放:
    在这里插入图片描述

  • 配置文件

    C++功能包的构建信息主要包含在 package.xmlCMakeLists.txt 中;

    Python功能包的构建信息则主要包含在 package.xmlsetup.py 中。

  • 操作命令

    ROS2的文件系统核心是功能包,我们可以通过编译指令colcon和ROS2内置的工具指令ros2来实现功能包的创建、编译、查找与执行等相关操作。

    1. 创建功能包

      新建功能包语法如下:

      ros2 pkg create 包名 --build-type 构建类型 --dependencies 依赖列表 --node-name 可执行程序名称
      

      格式解释:

      • --build-type:是指功能包的构建类型,有cmake、ament_cmake、ament_python三种类型可选;不填默认为 ament_cmake;
      • --dependencies:所依赖的功能包列表;
      • --node-name:可执行程序的名称,会自动生成对应的源文件并生成配置文件。
    2. 编译
      编译功能包语法如下:

      colcon build
      

      colcon build --packages-select [功能包列表]
      

      前者会构建工作空间下的所有功能包,后者可以构建指定功能包。

    3. 执行
      执行命令语法如下:

      . install/setup.bash	# 刷新setup文件
      ros2 run 功能包 可执行程序 参数
      
    4. 查找
      ros2 pkg命令下包含了多个查询功能包相关信息的参数。

      ros2 pkg executables [包名]	# 输出所有功能包或指定功能包下的可执行程序。
      ros2 pkg list	# 列出所有功能包
      ros2 pkg prefix 包名	# 列出功能包路径
      ros2 pkg xml	# 输出功能包的package.xml内容
      

(五)ROS2核心模块

  • 通信相关

    应用场景、功能包的应用(二进制命令安装、源码安装、自实现)、分布式;

  • 工具相关

    • 终端命令与rqt

      rqt是一个图形化工具,功能与命令行工具类似;

    • lunch文件

      批量地启动多个ROS2节点,是构建大型项目时启动多节点的常用方式;

    • TF坐标变换

      实现机器人不同部位(或不同机器人)之间的相对位置的转换;

    • 可视化

      图形化显示机器人模型;

第2章 通信机制的核心

在这里插入图片描述

(一)通信机制简介

  1. 节点

    通信对象的构建依赖于节点;系统由多个协同工作的节点组成。

  2. 话题

    Topic是一个纽带,具有相同话题的节点关联到一起,这是节点之间通信的前提。尽管节点是用不同语言实现的,具有相同话题就可以实现数据交互。

  3. 通信模型

    在这里插入图片描述

  4. 接口

    接口,即传输的数据的载体。通信时使用的数据载体需要使用接口文件定义。常用的接口文件有三种: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

准备工作:

  1. 安装所需功能包;
  2. 新建功能包;
  3. 功能包下新建 urdf、rviz、launch、meshes目录以备用,其中 urdf 目录下再新建子目录 urdf 与 xacro。

正式工作:

  1. 编写 URDF 文件;

    • URDF语法;
  2. 编写 launch 文件:加载urdf文件并在rviz2中显示机器人模型;

    核心:

    1. 启动robot_state_publisher节点,该节点要以参数的方式加载urdf文件内容;
    2. 启动rviz2节点;

    优化:

    1. 添加 joint_state_publisher 节点(当机器人有非固定关节时,必须包含该节点);

    2. 设置 rviz2 的默认配置文件;

      可以打开之前设置好插件的rviz2;

    3. 动态传入 urdf 文件,把 urdf 文件封装为参数;

      动态传参启动任意 urdf 文件:
      ros2 launch cpp06_urdf display.launch.py model:=`ros2 pkg prefix --share cpp06_urdf`/urdf/urdf/xxx.urdf
      
  3. 编辑配置文件;

    • package.xml:在 package.xml 中需要手动添加一些执行时依赖;
    • CMakeLists.txt:在功能包下,新建了若干目录,需要为这些目录配置安装路径;
  4. 编译;

  5. 执行 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(必填):为连杆命名。

子标签

  1. <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设置。
  1. <collision>(可选):link的碰撞属性。

可以与link的视觉属性一致,也可以不同,比如:我们会通常使用更简单的碰撞模型来减少计算时间,或者设置的值大于link的视觉属性,以尽量避免碰撞。另外,同一链接可以存在多个<collision>标签实例,多个几何图形组合表示link的碰撞属性。

  • name(可选):为collision设置名称。
  • <geometry>(必须):请参考visual标签的geometry使用规则。
  • <origin>(可选):请参考visual标签的origin使用规则。
  1. <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.变量与算数运算
  1. 变量定义:<xacro:property .../>

    <xacro:property name="变量名" value="变量值" />
    
  2. 变量调用:${变量名}

    <geometry>
        <cylinder radius="${radius}" length="${length}" />
    </geometry>
    
  3. 变量运算:${数学表达式}

    <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.宏

类似于函数实现,提高代码复用率,优化代码结构,提高安全性。

  1. 宏定义

    <xacro:macro name="宏名称" params="参数列表(多参数之间使用空格分隔)">
        
        .....
        
        参数调用格式: ${参数名}
    </xacro:macro>
    
  2. 宏调用

    <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

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐