机器人控制系统 ROS2 学习笔记

news/2024/12/4 21:08:41/

第1章 环境搭建

ROS2__2">(一)ROS2 的安装和配置

ROS2_4">(二)ROS2快速体验

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

(三)集成开发环境搭建

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

ROS2_15">(四)ROS2体系框架

  • 创建工作空间:

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

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

  • 配置文件

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

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

  • 操作命令

    ROS2的文件系统核心是功能包,我们可以通过编译指令colconROS2内置的工具指令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_87">(五)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。

它是一个用于录制和回放话题的一个工具集,工具的集合。

作用:实现数据的复用,方便调试、测试。

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

准备工作:

  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: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.变量与算数运算
  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


http://www.ppmy.cn/news/1552374.html

相关文章

Zookeeper的通知机制是什么?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper的通知机制是什么?】面试题。希望对大家有帮助&#xff1b; Zookeeper的通知机制是什么? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper的通知机制主要通过Watcher实现&#xff0c;它是Zookeeper客…

QT实战-qt各种菜单样式实现

本文主要介绍了qt普通菜单样式、带选中样式、带子菜单样式、超过一屏幕菜单样式、自定义带有滚动条的菜单样式&#xff0c; 先上图如下&#xff1a; 1.普通菜单样式 代码&#xff1a; m_pmenu new QMenu(this);m_pmenu->setObjectName("quoteListMenu"); qss文…

手撸了一个文件传输工具

在日常的开发与运维中&#xff0c;文件传输工具是不可或缺的利器。无论是跨服务器传递配置文件&#xff0c;还是快速从一台机器下载日志文件&#xff0c;一个高效、可靠且简单的文件传输工具能够显著提高工作效率。今天&#xff0c;我想分享我自己手撸一个文件传输工具的全过程…

【C#】书籍信息的添加、修改、查询、删除

文章目录 一、简介二、程序功能2.1 Book类属性&#xff1a;方法&#xff1a; 2.2 Program 类 三、方法&#xff1a;四、用户界面流程&#xff1a;五、程序代码六、运行效果 一、简介 简单的C#控制台应用程序&#xff0c;用于管理书籍信息。这个程序将允许用户添加、编辑、查看…

顶刊算法 | 鱼鹰算法OOA-BiTCN-BiGRU-Attention多输入单输出回归预测(Maltab)

顶刊算法 | 鱼鹰算法OOA-BiTCN-BiGRU-Attention多输入单输出回归预测&#xff08;Maltab&#xff09; 目录 顶刊算法 | 鱼鹰算法OOA-BiTCN-BiGRU-Attention多输入单输出回归预测&#xff08;Maltab&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实…

vue中如何获取public路径

在Vue项目中获取public路径的方法有多种&#xff0c;主要通过以下1、使用相对路径、2、使用环境变量、3、使用webpack配置三种方式来实现。这些方法可以帮助开发者在项目中更灵活地使用静态资源。下面将详细解释每种方法以及如何使用它们。 一、使用相对路径 在Vue项目中&#…

React进阶面试题目(二)

React 组件声明的方法有哪些&#xff1f;各有什么不同&#xff1f; React 组件声明的方法主要有三种&#xff1a; 无状态函数式组件&#xff1a;这种组件只负责根据传入的props来展示&#xff0c;不涉及到state状态的操作。组件不会被实例化&#xff0c;整体渲染性能得到提升…

反向代理模块开发

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…