系列文章目录
前言
一、轮式移动机器人运动学
本页介绍不同轮式移动机器人的运动学。如需进一步参考,请参阅 Siciliano et.al - Robotics: 建模、规划和控制》和 Kevin M. Lynch and Frank C. Park - Modern Robotics: 机械、规划和控制》。
轮式移动机器人可分为两类:
- 全向机器人
- 可在平面内向任意方向瞬时移动,以及
- 非全向机器人
- 不能在平面内任何方向上瞬时移动。
利用车轮执行器的编码器对运动学模型进行前向积分 —— 被称为测距定位或被动定位或死算。我们只称其为测距(odometry)。
1.1 差速驱动机器人
引用 Siciliano et.al - Robotics: 建模、规划和控制:
严格意义上的独轮车(即装有单轮的车辆)是一种在静态条件下存在严重平衡问题的机器人。然而,有一些车辆在运动学上与独轮车相当,但从机械角度来看更加稳定。差速驱动机器人就是其中之一,它有两个轮子,每个轮子都是独立驱动的。
- 是车轮轨迹(车轮之间的距离)。
1.1.1 前向运动学
差速驱动模型的前进运动学可以通过上述独轮车模型计算得出,计算公式为
1.1.2 逆运动学
通过以下方法可以计算出实现理想车身扭转所需的车轮速度:
1.1.3 里程计(Odometry)
我们可以利用上述正向运动学方程,直接从编码器读数中计算出机器人的运动轨迹。
二、差分驱动控制器
用于差速驱动移动机器人的控制器。
它接收机器人本体的速度指令作为输入,并将其转换为差速驱动底座的车轮指令。
通过硬件反馈计算并发布里程计(Odometry,运动轨迹)。
有关移动机器人运动学的介绍和此处使用的术语,请参阅轮式移动机器人运动学。
2.1 其他特点
- 实时安全实施。
- 运动轨迹发布
- 任务空间速度、加速度和颠簸限制
- 指令超时后自动停止
2.2 控制器接口说明
2.2.1 参考资料
(控制器尚未作为可链式控制器实施)
2.2.2 反馈
作为反馈接口类型,使用关节的位置(hardware_interface::HW_IF_POSITION)或速度(hardware_interface::HW_IF_VELOCITY,如果参数 position_feedback=false)。
2.2.3 输出
使用关节的速度(hardware_interface::HW_IF_VELOCITY)。
2.3 ROS 2 接口
2.3.1 订阅者
~/cmd_vel [geometry_msgs/msg/TwistStamped] 控制器的速度命令。
控制器的速度指令。控制器提取线速度的 x 分量和角速度的 z 分量。其他分量上的速度将被忽略。
2.3.2 Publishers
~/odom [nav_msgs::msg::测距]
这表示对机器人在自由空间中的位置和速度的估计。
/tf [tf2_msgs::msg::TFMessage] TF 树。
TF 树。仅在 enable_odom_tf=true 时发布
~/cmd_vel_out [geometry_msgs/msg/TwistStamped] 控制器的速度命令。
控制器的速度命令,其中应用了限制。仅在 publish_limited_velocity=true 时发布
2.3.3 参数
该控制器使用 generate_parameter_library 来处理参数。位于 src 文件夹中的参数定义文件包含控制器使用的所有参数的说明。
left_wheel_names (字符串数组)
左侧车轮关节的名称默认: {}
限制条件:
参数不为空
right_wheel_names (字符串数组)
右侧车轮关节的名称默认: {}
限制条件: 参数不为空:
参数不为空
wheel_separation (双)
左右车轮之间的最短距离。如果此参数有误,机器人在弯道中将无法正常运行。默认值:0.0
限制条件:
大于 0.0
wheel_radius (车轮半径,双)
轮子的半径,即轮子的大小,用于将线性速度转换为轮子旋转。如果该参数有误,机器人的移动速度会比预期的快或慢。默认值: 0.0
限制条件:
大于 0.0
wheel_separation_multiplier(车轮分离倍增器,双)
车轮分离校正系数(TODO(destogl): 请帮我正确描述)默认值:1.0
left_wheel_radius_multiplier(左车轮半径乘数,double)
左侧车轮半径与 wheel_radius 参数中的标称值不同时的修正系数。默认值:1.0
right_wheel_radius_multiplier(右车轮半径乘数,双)
当右侧车轮半径与 wheel_radius 参数中的标称值不同时的修正系数。默认值:1.0
tf_frame_prefix_enable (bool)
启用或禁用在 tf 帧 id 上附加 tf_prefix。默认值:true
tf_frame_prefix (字符串)
(可选)附加到 tf 框架的前缀,发布前将添加到 odom_id 和 base_frame_id 中。如果参数为空,将使用控制器的命名空间。默认值:""
odom_frame_id (字符串)
用于里程测量的框架名称。控制器发布里程计时,该框架是 base_frame_id 的父框架。默认值:"odom
base_frame_id (字符串)
作为里程测量框架子框架的机器人基本框架的名称。默认值:"base_link
pose_covariance_diagonal(对角线双数组)
机器人编码器输出的姿态的轨迹协方差。这些值应根据机器人的轨迹测量样本数据进行调整,但这些值是一个很好的起点: [0.001, 0.001, 0.001, 0.001, 0.001, 0.01].默认值:{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}。
twist_covariance_diagonal(扭转协方差对角线)(双数组)
机器人速度编码器输出的扭转协方差。这些值应根据机器人的轨迹测量样本数据进行调整,但这些值是一个很好的起点: [0.001, 0.001, 0.001, 0.001, 0.001, 0.01].默认值:{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}
open_loop (bool)
如果设置为 "true",机器人的运动轨迹将根据指令值而非反馈值计算。默认值:假
position_feedback (位置反馈)(bool
是否有来自硬件的位置反馈。默认值: true
enable_odom_tf (bool)
发布 odom_frame_id 和 base_frame_id 之间的转换。默认值:true
cmd_vel_timeout (double)
超时时间(以秒为单位),超时后 cmd_vel 主题上的输入命令将被视为已关闭。默认值:0.5
publish_limited_velocity (bool)
发布限制速度值。默认值:false
velocity_rolling_window_size (int)
用于计算里程测量中使用的平均速度的滚动窗口大小。默认值:10
publish_rate (双)
里程测量和 TF 信息的发布速率(赫兹)。默认值:50.0
linear.x
线性 x 轴的关节限位结构。限制器忽略位置限制。详情请参阅 ros2_control 资源库中的 joint_limits 包。
linear.x.has_velocity_limits (bool)
默认值:false
linear.x.has_acceleration_limits (bool) (线性.x.有加速度限制)
默认值:false
linear.x.has_jerk_limits (bool) (线性.x.有加速度限制)
默认值:false
linear.x.max_velocity (double) 线性.x.最大速度(双倍
默认值: std::numeric_limits<double>::quiet_NaN()
linear.x.min_velocity (双倍)
默认值: std::numeric_limits<double>::quiet_NaN()
linear.x.max_acceleration (双)
默认值: std::numeric_limits<double>::quiet_NaN()
linear.x.min_acceleration (double)
默认值: std::numeric_limits<double>::quiet_NaN()
linear.x.max_jerk (double)
默认值: std::numeric_limits<double>::quiet_NaN()
linear.x.min_jerk (double)
默认值: std::numeric_limits<double>::quiet_NaN()
angular.z
围绕 Z 轴旋转的关节限位结构。限制器忽略位置限制。详情请参阅 ros2_control 软件仓库中的 joint_limits 软件包。
angular.z.has_velocity_limits (bool)
默认:false
angular.z.has_acceleration_limits (bool)
默认值:false
angular.z.has_jerk_limits (bool)
默认值:false
angular.z.max_velocity (double)
默认值: std::numeric_limits<double>::quiet_NaN()
angular.z.min_velocity (double)
默认值: std::numeric_limits<double>::quiet_NaN()
angular.z.max_acceleration (double)
默认值: std::numeric_limits<double>::quiet_NaN()
angular.z.min_acceleration (double)
默认值: std::numeric_limits<double>::quiet_NaN()
angular.z.max_jerk (double)
默认值: std::numeric_limits<double>::quiet_NaN()
angular.z.min_jerk (double)
默认值: std::numeric_limits<double>::quiet_NaN()
该控制器的参数文件示例可在 test 目录中找到:
test_diff_drive_controller:
ros__parameters:
left_wheel_names: ["left_wheels"]
right_wheel_names: ["right_wheels"]
wheel_separation: 0.40
wheel_radius: 0.02
wheel_separation_multiplier: 1.0
left_wheel_radius_multiplier: 1.0
right_wheel_radius_multiplier: 1.0
odom_frame_id: odom
base_frame_id: base_link
pose_covariance_diagonal: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
twist_covariance_diagonal: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
position_feedback: false
open_loop: true
enable_odom_tf: true
cmd_vel_timeout: 0.5 # seconds
publish_limited_velocity: true
velocity_rolling_window_size: 10
linear.x.has_velocity_limits: false
linear.x.has_acceleration_limits: false
linear.x.has_jerk_limits: false
linear.x.max_velocity: 0.0
linear.x.min_velocity: 0.0
linear.x.max_acceleration: 0.0
linear.x.max_jerk: 0.0
linear.x.min_jerk: 0.0
angular.z.has_velocity_limits: false
angular.z.has_acceleration_limits: false
angular.z.has_jerk_limits: false
angular.z.max_velocity: 0.0
angular.z.min_velocity: 0.0
angular.z.max_acceleration: 0.0
angular.z.min_acceleration: 0.0
angular.z.max_jerk: 0.0
angular.z.min_jerk: 0.0
三、DiffBot(差速机器人)
DiffBot 或 "差分移动机器人 "是一种具有差分驱动的简单移动底座。该机器人基本上是一个根据差分驱动运动学原理移动的盒子。
在示例_2 中,硬件接口插件只有一个接口。
- 与机器人控制盒的通信使用专有的应用程序接口。
- 所有关节的数据均一次性交换。
DiffBot URDF 文件可在 description/urdf 文件夹中找到。
注意事项
以下命令既适用于本地安装本软件源及其附属程序,也适用于在 docker 容器中运行它们。有关 docker 使用的更多信息,请参阅使用 Docker。
3.1 教程步骤
- 要检查 DiffBot 说明是否正常工作,请使用以下启动命令
ros2 launch ros2_control_demo_example_2 view_robot.launch.py
警告
在终端中获得以下输出是正常的: 警告: 传给 canTransform 参数 target_frame 的无效帧 ID "odom"--帧不存在。出现这种情况是因为 joint_state_publisher_gui 节点需要一些时间才能启动。
- 要启动 DiffBot 示例,请打开终端,将 ROS2- 工作空间作为源代码,然后用以下命令执行启动文件
ros2 launch ros2_control_demo_example_2 diffbot.launch.py
启动文件加载并启动机器人硬件和控制器,并打开 RViz。在启动终端,您将看到硬件执行器的大量输出,显示其内部状态。过度打印只是为了演示。一般来说,在实现硬件接口时应尽量避免向终端打印。
如果能在 RViz 中看到一个橙色方框,那么一切都已正常启动。不过,为了确保万无一失,在移动 DiffBot 之前,我们还是要先检查一下控制系统。
-
打开另一个终端,执行
ros2 control list_hardware_interfaces
您应该获得
command interfaces left_wheel_joint/velocity [available] [claimed] right_wheel_joint/velocity [available] [claimed] state interfaces left_wheel_joint/position left_wheel_joint/velocity right_wheel_joint/position right_wheel_joint/velocity
命令接口上的[声称]标记意味着控制器可以对 DiffBot 发出命令。
此外,我们还可以看到命令接口的类型是速度,这是差分驱动机器人的典型特征。
-
检查控制器是否运行
ros2 control list_controllers
您应该获得
diffbot_base_controller[diff_drive_controller/DiffDriveController] active joint_state_broadcaster[joint_state_broadcaster/JointStateBroadcaster] active
- 如果一切正常,现在可以使用 ROS 2 CLI 界面向 Diff Drive Controller 发送命令:
ros2 topic pub --rate 30 /diffbot_base_controller/cmd_vel geometry_msgs/msg/TwistStamped " twist: linear: x: 0.7 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: 1.0"
现在你应该能在 RViz 中看到一个橙色方框在盘旋。此外,在启动文件的终端中也会看到状态的变化。
[DiffBotSystemHardware]: Got command 43.33333 for 'left_wheel_joint'! [DiffBotSystemHardware]: Got command 50.00000 for 'right_wheel_joint'!
- 让我们反观一下 ros2_control 硬件组件。调用
ros2 control list_hardware_components
应该给你
Hardware Component 1 name: DiffBot type: system plugin name: ros2_control_demo_example_2/DiffBotSystemHardware state: id=3 label=active command interfaces left_wheel_joint/velocity [available] [claimed] right_wheel_joint/velocity [available] [claimed]
这表明自定义硬件接口插件已加载并运行。如果您使用的是真实机器人,但没有运行模拟器,通常使用 mock_components/GenericSystem 硬件组件比编写自定义组件更快。停止启动文件,然后使用附加参数重新启动
ros2 launch ros2_control_demo_example_2 diffbot.launch.py use_mock_hardware:=True
呼叫
ros2 control list_hardware_components
现在应该给你
Hardware Component 1 name: DiffBot type: system plugin name: mock_components/GenericSystem state: id=3 label=active command interfaces left_wheel_joint/velocity [available] [claimed] right_wheel_joint/velocity [available] [claimed]
你会发现加载了一个不同的插件。在 diffbot.ros2_control.xacro 中,可以找到加载该插件和参数 calculate_dynamics 的说明。
<hardware> <plugin>mock_components/GenericSystem</plugin> <param name="calculate_dynamics">true</param> </hardware>
这样就能将速度指令整合到位置状态界面,并通过 ros2 topic echo /joint_states 进行检查: 如果机器人在移动,位置值会随时间增加。现在,您可以使用上述命令对设置进行测试,其工作原理应与自定义硬件组件插件相同。
有关 mock_components 的更多信息,请参阅 ros2_control 文档。
3.2 本演示使用的文件
- 启动文件: diffbot.launch.py
- 控制器 yaml: diffbot_controllers.yaml
- URDF 文件: diffbot.urdf.xacro
- 描述: diffbot_description.urdf.xacro
- ros2_control 标签: diffbot.ros2_control.xacro
- RViz 配置:diffbot.rviz
- 硬件接口插件: diffbot_system.cpp
3.3 本演示中的控制器
- Joint State Broadcaster (ros2_controllers repository): doc
- Diff Drive Controller (ros2_controllers repository): doc