ros学习笔记.4 Path Planning Part 2 (避障)

news2024/11/15 19:54:43
  • 避障是如何工作的
  • 什么是局部规划器?
  • 什么是局部成本图?
  • 路径规划回顾
  • 如何使用动态重新配置和其他 Rviz 工具

局部规划器

一旦全局规划器计算出要遵循的路径,该路径就会发送给局部规划器。然后,局部规划器将执行全局规划的每个部分(让我们将局部规划想象为全局规划的一小部分)。因此,给定要遵循的规划(由全局规划器提供)和地图,局部规划器将提供速度命令以移动机器人。

与全局规划器不同,局部规划器监视里程表和激光数据,并为机器人选择无碰撞的局部规划(让我们将局部规划想象为全局规划的一小部分)。因此,局部规划器可以动态重新计算机器人的路径,以防止机器人撞到物体,但仍允许它到达目的地。

一旦计算出局部规划,它将发布到名为 /local_plan 的主题中。局部规划器还会将其尝试遵循的全局规划部分发布到主题 /global_plan 中。让我们做一个练习,以便你更好地理解这一点。

练习

a) 打开 Rviz 并添加显示,以便能够可视化局部规划器的 /global_plan 和 /local_plan 主题。

b) 向机器人发送目标姿势并可视化两个主题。

和全局规划器一样,还有不同类型的局部规划器。根据您的设置(您使用的机器人、它导航的环境等)和您想要的性能类型,您将使用其中一种或另一种。让我们来看看最重要的几种。

base_local_planner

base_local_planner提供了轨迹展开(Trajectory Rollout)和动态窗口方法(Dynamic Window Approach, DWA)算法的实现,用于计算和执行机器人的全局路径规划。

总结一下,这些算法的基本工作原理如下:

  1. 从机器人的控制空间中离散地采样。
  2. 对于每个采样的速度,从机器人的当前状态开始执行前向模拟,以预测应用该速度后的情况。
  3. 评估每条前向模拟得到的轨迹。
  4. 丢弃不合法的轨迹。
  5. 选择得分最高的轨迹,并将相关的速度发送到移动底盘。
  6. 重复以上步骤。

DWA 轨迹展开的不同之处在于机器人的空间采样方式。轨迹展开从整个前向模拟期间内可实现的速度集合中进行采样,考虑了机器人的加速度限制;而 DWA 则仅在一个模拟步骤中从可实现的速度集合中进行采样,考虑了机器人的加速度限制。

由于 DWA 采样的空间较小,因此它是一种更高效的算法,但对于加速度限制较低的机器人,DWA 可能不如轨迹展开表现得好,因为 DWA 不会对恒定加速度进行前向模拟。在实际应用中,DWA 和轨迹展开的性能类似,因此推荐使用 DWA 以获得效率上的优势。

base_local_planner的 DWA 算法在一个新的局部规划器中得到了改进,这就是我们接下来要介绍的 DWA local planner。

dwa_local_planner

DWA local planner 提供了动态窗口方法(Dynamic Window Approach, DWA)算法的实现。它基本上是对基础局部规划器的 DWA 选项的重写,但代码更简洁、更易于理解,特别是在轨迹模拟方面。

因此,对于使用 DWA 方法进行局部规划的应用,dwa_local_planner 可能是最佳选择。这是最常用的选项。

eband_local_planner

eband_local_planner实现了弹性带(Elastic Band)方法,以计算要跟随的局部路径。

teb_local_planner

teb 局部规划器实现了有时间弹性带(Timed Elastic Band)方法,以计算要跟随的局部路径。

修改Local Planner

move_base 节点使用的局部规划器在 base_local_planner 参数中指定。可以在参数文件中设置,如下例所示:

base_local_planner: "base_local_planner/TrajectoryPlannerROS" # Sets the Trajectory Rollout algorithm from base local                                                                 planner

base_local_planner: "dwa_local_planner/DWAPlannerROS" # Sets the dwa local planner

base_local_planner: "eband_local_planner/EBandPlannerROS" # Sets the eband local planner

base_local_planner: "teb_local_planner/TebLocalPlannerROS" # Sets the teb local planner

或者可以直接在启动文件中设置,就像我们的例子一样:

<arg name="base_local_planner" default="dwa_local_planner/DWAPlannerROS"/>

正如您所期望的,每个局部规划器也有自己的参数。这些参数将根据您使用的局部规划器而有所不同。在本课程中,我们将重点介绍 DWA 局部规划器参数,因为它是最常见的选择。无论如何,如果您想检查其他局部规划器的具体参数,您可以在此处查看:

base_local_planner: base_local_planner - ROS Wiki

eband_local_planner: eband_local_planner - ROS Wiki

teb_local_planner: teb_local_planner - ROS Wiki

DWAPlannerROS 参数

如果您检查包 my_move_base_launcher 中的文件 my_move_base_params.yaml,您将看到 DWAPlannerROS 规划器的参数:

DWAPlannerROS:
  # Robot configuration parameters  
  acc_lim_x: 2.5
  acc_lim_y: 0
  acc_lim_th: 3.2

  max_vel_x: 0.5
  min_vel_x: 0.0
  max_vel_y: 0
  min_vel_y: 0

  max_vel_trans: 0.5
  min_vel_trans: 0.1
  max_vel_theta: 1.0
  min_vel_theta: 0.2

  # Goal Tolerance Parameters
  yaw_goal_tolerance: 0.1
  xy_goal_tolerance: 0.2
  latch_xy_goal_tolerance: false

DWA 局部规划器最重要的参数如下:

机器人配置参数

  • /acc_lim_x(默认值:2.5):机器人在 x 方向上的加速度限制,单位是米/秒²。
  • /acc_lim_th(默认值:3.2):机器人在旋转方向上的加速度限制,单位是弧度/秒²。
  • /max_vel_trans(默认值:0.55):机器人最大平移速度的绝对值,单位是米/秒。
  • /min_vel_trans(默认值:0.1):机器人最小平移速度的绝对值,单位是米/秒。
  • /max_vel_x(默认值:0.55):机器人最大 x 方向速度,单位是米/秒。
  • /min_vel_x(默认值:0.0):机器人最小 x 方向速度,单位是米/秒,负值表示向后运动。
  • /max_vel_theta(默认值:1.0):机器人最大旋转速度的绝对值,单位是弧度/秒。
  • /min_vel_theta(默认值:0.4):机器人最小旋转速度的绝对值,单位是弧度/秒。

目标容差参数

  • /yaw_goal_tolerance(双精度,默认值:0.05):控制器在达到目标时在偏航/旋转方向上的容差,单位是弧度。
  • /xy_goal_tolerance(双精度,默认值:0.10):控制器在达到目标时在 x 和 y 方向上的容差,单位是米。
  • /latch_xy_goal_tolerance(布尔值,默认值:false):如果目标容差被锁定,当机器人达到目标 xy 位置时,它会原地旋转,即使在旋转过程中最终位置超出了目标容差范围。

练习

a) 打开上一章中创建的 my_move_base_params.yaml 文件进行编辑。

b) 修改 DWAPlannerROS 的 xy_goal_tolerance 参数并将其设置为更高的值。

c) 检查是否注意到性能有任何差异。

High XY tolerance:

 Low XY tolerance:

正如您在练习中看到的,您在参数文件中设置的目标容差越高,机器人设定的目标就越不准确。

正如您在参数文件中看到的,还有其他参数被注释(因此规划器采用它们的默认值):

# 前向模拟参数
# sim_time: 2.0  # 模拟时间(秒)
# sim_granularity: 0.02  # 模拟粒度(秒)
# vx_samples: 6  # x方向速度样本数
# vy_samples: 0  # y方向速度样本数
# vtheta_samples: 20  # 旋转速度样本数
# penalize_negative_x: true  # 是否惩罚负x方向速度

# 轨迹评分参数
# path_distance_bias: 32.0  # 控制器保持接近给定路径的权重
# goal_distance_bias: 24.0  # 控制器试图到达局部目标的权重,也控制速度
# occdist_scale: 0.01  # 控制器尝试避免障碍物的权重
# forward_point_distance: 0.325  # 从机器人中心点到额外评分点的距离(米)
# stop_time_buffer: 0.2  # 为了使轨迹被认为有效,机器人在碰撞前必须停止的时间(秒)
# scaling_speed: 0.25  # 机器人足迹开始缩放的速度绝对值(米/秒)
# max_scaling_factor: 0.2  # 机器人足迹的最大缩放因子

# 振荡防止参数
# oscillation_reset_dist: 0.25  # 机器人在振荡标志重置之前必须行驶的距离(米)(默认值: 0.05)

练习:

a) 修改局部规划器参数文件中的 sim_time 参数并将其设置为 4.0。

b) 检查是否注意到局部规划器的性能或可视化方面有任何差异。

Regular sim_time (local plan in blue):

 High sim_time (local plan in blue):

从上面的练习中可以看出,sim_time 参数越高,计算出的局部规划就越长。但是,请记住,这也会增加使用的计算资源。

轨迹评分参数

  • /path_distance_bias(默认值:32.0):控制器应保持接近给定路径的权重
  • /goal_distance_bias(默认值:24.0):控制器应尝试达到其局部目标的权重;还控制速度
  • /occdist_scale(默认值:0.01):控制器应尝试避开障碍物的权重

这里有一个 dwa_local_planner_params.yaml 的示例:

# 轨迹评分参数
# path_distance_bias: 32.0  # 控制器保持接近给定路径的权重
# goal_distance_bias: 24.0  # 控制器试图到达局部目标的权重,也控制速度
# occdist_scale: 0.01  # 控制器尝试避免障碍物的权重
# forward_point_distance: 0.325  # 从机器人中心点到额外评分点的距离(米)
# stop_time_buffer: 0.2  # 机器人在碰撞前必须停止的时间,以使轨迹被认为有效(秒)
# scaling_speed: 0.25  # 机器人足迹开始缩放的速度绝对值(米/秒)
# max_scaling_factor: 0.2  # 机器人足迹的最大缩放因子

尝试自己修改这些参数,看看它们如何影响规划过程。例如,您可以尝试更改局部规划器参数文件中的 path_distance_bias 参数。

path_distance_bias 参数用于控制机器人在轨迹追踪时保持接近给定路径的权重。修改这个参数会对机器人行为产生以下影响:

  1. 增加 path_distance_bias 的值:

    • 机器人会更紧密地跟随路径。 增大的权重使得控制器更加重视保持机器人在给定路径上的位置,导致机器人更努力地纠正偏离路径的情况。
    • 可能导致路径跟随过度。 如果 path_distance_bias 设得过高,机器人可能会变得过于固执,紧紧依赖路径,可能会导致在复杂或狭窄环境中的表现变差,甚至导致在障碍物附近出现困难。
  2. 减少 path_distance_bias 的值:

    • 机器人会更灵活。 较低的权重使得控制器对路径的依赖性降低,机器人可能会有更多的自由度来进行调整和优化其他目标,例如到达目标点或避开障碍物。
    • 可能导致路径偏离。 如果这个权重设置得过低,机器人可能不会很好地遵循给定路径,从而导致偏离预定路径,尤其是在路径弯曲或变化较大的情况下。

在全局规划器部分,我们已经向您介绍了代价地图,重点介绍了全局代价地图。现在是时候谈谈局部代价地图了。

Local Costmap

您需要知道的第一件事是,局部规划器使用局部代价地图来计算局部规划。

与全局代价地图不同,局部代价地图直接根据机器人的传感器读数创建。给定代价地图的宽度和高度(由用户定义),它会在机器人在整个环境中移动时将机器人保持在代价地图的中心,并在机器人移动时从地图中删除障碍物信息。

让我们做一个练习,以便您更好地了解局部代价地图的外观,以及如何区分局部代价地图和全局代价地图。

练习

a) 打开 Rviz 并添加适当的显示,以便可视化全局和局部成本地图。

b) 执行以下命令以在房间中生成障碍物。

检查您的工作区中是否已经有 object.urdf 文件。如果您还没有,您需要执行以下命令将其移动到您的工作区。

cp /home/simulations/public_sim_ws/src/all/turtlebot/turtlebot_navigation_gazebo/urdf/object.urdf /home/user/catkin_ws/src

 创建对象

rosrun gazebo_ros spawn_model -file /home/user/catkin_ws/src/object.urdf -urdf -x 0 -y 0 -z 1 -model my_object

c) 启动键盘操作并靠近生成的物体。

roslaunch husky_launch keyboard_teleop.launch

d) 检查全局和局部Costmaps之间的差异。

Husky 面对生成的障碍物:

 全局成本地图(未出现障碍物):

 局部成本地图(障碍物出现):

因此,正如您在上一个练习中看到的,局部代价地图确实会检测模拟中出现的新对象,而全局代价地图则不会。

您可能已经推断出这种情况,因为全局代价地图是从静态地图文件创建的。这意味着即使环境发生变化,代价地图也不会改变。相反,局部代价地图是根据机器人的传感器读数创建的,因此它将始终使用来自传感器的新读数进行更新。

由于全局代价地图和局部代价地图的行为不同,因此参数文件也必须不同。让我们来看看我们需要为局部代价地图设置的最重要的参数。

Local Costmap 参数

你需要了解的参数如下:

  • global_frame: 成本地图操作的全局坐标系。在局部成本地图中,此参数必须设置为 "/odom"。
  • robot_base_frame: 机器人基座链接的坐标系名称。
  • rolling_window: 是否使用滚动窗口版本的成本地图。如果 static_map 参数设置为 true,则此参数必须设置为 false。在局部成本地图中,此参数必须设置为 true
  • update_frequency(默认值: 5.0): 更新地图的频率,以赫兹(Hz)为单位。
  • width(默认值: 10): 成本地图的宽度。
  • height(默认值: 10): 成本地图的高度。
  • plugins: 插件规范的序列,每个层一个。每个规范是一个包含 nametype 字段的字典。name 用于定义插件的参数命名空间。

正如你所看到的,这些参数与全局成本地图的参数相同。然而,我们增加了一些在处理局部成本地图时很有用的参数:widthheight。我们还增加了 update_frequency,稍后将在本单元中讨论。

现在,让我们做一个简单的练习来测试 widthheight 参数。

练习

a) 将一个名为 my_local_costmap_params.yaml 的文件添加到您在练习my_move_base_launcher中创建的包的 params目录中。

b) 将 husky_navigation 包的 costmap_local.yaml 文件的内容复制到此文件中。

global_frame: odom
rolling_window: true

plugins:
  - {name: obstacles_laser,           type: "costmap_2d::ObstacleLayer"}
  - {name: inflation,                 type: "costmap_2d::InflationLayer"}

c) 修改您在练习my_move_base_launcher中创建的 my_move_base.launch 文件,以便它加载您刚刚创建的局部 costmap 参数文件。

<?xml version="1.0"?>
<launch>

  <!-- Run the map server -->
  <arg name="map_file" default="$(find husky_navigation)/maps/my_map.yaml"/>
  <node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)" />

  <!--- Run AMCL -->
  <include file="$(find husky_navigation)/launch/amcl.launch" />

  <arg name="no_static_map" default="false"/>

  <arg name="base_global_planner" default="navfn/NavfnROS"/>
  <arg name="base_local_planner" default="dwa_local_planner/DWAPlannerROS"/>
  <!-- <arg name="base_local_planner" default="base_local_planner/TrajectoryPlannerROS"/> -->

  <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">

    <param name="base_global_planner" value="$(arg base_global_planner)"/>
    <param name="base_local_planner" value="$(arg base_local_planner)"/>  
    <rosparam file="$(find my_move_base_launcher)/params/my_move_base_params.yaml" command="load"/>

    <!-- observation sources located in costmap_common.yaml -->
    <rosparam file="$(find husky_navigation)/config/costmap_common.yaml" command="load" ns="global_costmap" />
    <rosparam file="$(find husky_navigation)/config/costmap_common.yaml" command="load" ns="local_costmap" />

    <!-- local costmap, needs size -->
    <rosparam file="$(find my_move_base_launcher)/params/my_local_costmap_params.yaml" command="load" ns="local_costmap" />
    <param name="local_costmap/width" value="10.0"/> # Change to 5 for the Exercise
    <param name="local_costmap/height" value="10.0"/> # Change to 5 for the Exercise

    <!-- static global costmap, static map provides size -->
    <rosparam file="$(find my_move_base_launcher)/params/my_global_costmap_params.yaml" command="load" ns="global_costmap" unless="$(arg no_static_map)"/>
    
    <!-- global costmap with laser, for odom_navigation_demo -->
    <rosparam file="$(find husky_navigation)/config/costmap_global_laser.yaml" command="load" ns="global_costmap" if="$(arg no_static_map)"/>
    <param name="global_costmap/width" value="100.0" if="$(arg no_static_map)"/>
    <param name="global_costmap/height" value="100.0" if="$(arg no_static_map)"/>
  </node>

</launch>

d) 启动 Rviz 并再次可视化局部costmap。可视化地图和 costmap 模式。

e) 修改宽度和高度参数并将其设置为 5。再次可视化 costmap。

10x10 costmap (map view):

 10x10 costmap (costmap view):

5x5 costmap (map view):

5x5 costmap (costmap view):

正如您在上一个练习中所看到的,为代价地图设置正确的宽度和高度非常重要。根据您想要导航的环境,您将设置一个或另一个值以正确显示障碍物。

让我们继续使用局部代价地图参数。尽管参数与全局代价地图相同,但它们的设置值并不相同。

例如,对于局部代价地图,rolling_window 参数将设置为 true。这样,我们表明我们不希望代价地图从静态地图初始化(就像我们对全局代价地图所做的那样),而是从机器人的传感器读数构建。

此外,由于我们没有任何静态地图,因此需要将 global_frame 参数设置为 odom。

您可以在上一个练习中创建的 my_local_costmap_params.yaml 文件中看到这一点:

global_frame: odom
rolling_window: true

正如我们在全局成本地图中看到的,局部成本地图也可以添加层。在局部成本地图的情况下,通常会添加以下两层:

  • costmap_2d::ObstacleLayer: 用于避障。
  • costmap_2d::InflationLayer: 用于对障碍物进行膨胀处理。

因此,你最终会得到如下结果:

plugins:
    - {name: obstacle_layer,      type: "costmap_2d::ObstacleLayer"}
    - {name: inflation_layer,     type: "costmap_2d::InflationLayer"}

**障碍层**对**局部代价地图**和**全局代价地图**使用不同的插件。对于局部代价地图,它使用**costmap_2d::ObstacleLayer**,而对于全局代价地图,它使用**costmap_2d::VoxelLayer**。这非常重要,因为在导航中,对障碍层使用错误的插件是一个常见错误。

让我们添加最后一个参数!正如您通过练习已经看到的,局部成本地图会不断更新自身。这些更新周期以 update_frequency 参数指定的速率进行。每个周期的工作方式如下:

  1. 传感器数据进入。
  2. 执行标记和清除操作。
  3. 为每个单元格分配适当的成本值。
  4. 对每个有障碍物的单元格执行障碍物膨胀。这包括将成本值从每个占用的单元格向外传播到指定的膨胀半径。

练习

a) 在 local costmap  参数文件中,将地图的 update_frequency 参数改得更慢。

b) 再次重复上面练习,看看现在会发生什么。

代价地图中的对象的生成稍有延迟。

现在,您可能想知道……上面提到的标记和清除操作是什么?

正如您已经知道的,代价地图会自动订阅传感器主题,并根据从传感器收到的数据进行自我更新。每个传感器都用于标记(将障碍物信息插入代价地图)、清除(从代价地图中删除障碍物信息)或两者兼而有之。

标记操作只是数组中的索引,用于更改单元格的成本。

但是,清除操作包括从传感器原点向外通过网格进行光线追踪,以报告每个观察结果。

标记和清除操作可以在障碍层中定义。

此时,我们几乎可以说您已经知道如何配置全局和本地代价地图。但如果您还记得的话,还有一个我们尚未讨论的参数文件。那就是通用代价地图参数文件。这些参数将影响全局和本地代价地图。

Common Costmap Parameters

基本上,您需要在这个文件中设置的最重要参数如下:

  • footprint: 足迹是移动底盘的轮廓。在 ROS 中,它表示为一个二维数组,例如 [x0, y0], [x1, y1], [x2, y2], ...。这个足迹将用于计算内接圆和外接圆的半径,这些圆用于以适合该机器人的方式膨胀障碍物。通常,为了安全起见,我们希望足迹略大于机器人的实际轮廓。
  • robot_radius: 如果机器人是圆形的,我们将指定此参数而不是足迹。
  • layers parameters: 在这里我们将定义每一层的参数。每一层都有其自己的参数。

障碍层

障碍层负责标记和清除操作。

如您所知,成本地图会自动订阅传感器主题,并根据接收到的数据进行更新。每个传感器用于标记(将障碍物信息插入成本地图)、清除(从成本地图中移除障碍物信息),或两者兼具。

  • 标记操作:只是通过数组索引来改变一个单元格的成本。
  • 清除操作:则是通过从传感器原点向外进行网格射线追踪,处理每个报告的观察数据。

标记和清除操作可以在障碍层中定义。

为了配置障碍层,我们首先需要为层设置名称,然后设置 observation_sources 参数。

  • observation_sourcesdefault: ""):由空格分隔的观察源名称列表。这定义了以下各个 source_name 命名空间。

您可以在 husky_navigation 包中的 costmap_common.yaml 文件中查看其操作方式:

obstacles_laser: # Name of the layer
    observation_sources: laser # We define 1 observation_source named laser

现在我们可以为这个 observation_source 定义具体的参数。observation_sources 中的每个 source_name 定义了一个命名空间,其中可以设置参数:

  • /source_name/topic(默认值: source_name):传感器数据接收的主题。默认为源名称。
  • /source_name/data_type(默认值: "PointCloud"):与主题相关联的数据类型,目前只支持 "PointCloud"、"PointCloud2" 和 "LaserScan"。
  • /source_name/clearing(默认值: false):是否使用该观察源来清除空闲空间。
  • /source_name/marking(默认值: true):是否使用该观察源来标记障碍物。
  • /source_name/inf_is_valid(默认值: false):允许在 "LaserScan" 观察消息中存在 Inf 值。Inf 值将被转换为激光的最大范围。
  • /source_name/max_obstacle_height(默认值: 2.0):要插入到成本地图中的障碍物的最大高度(米)。该参数应设置为比机器人的实际高度稍高。
  • /source_name/obstacle_range(默认值: 2.5):障碍物将在成本地图中插入的默认最大距离(米)。此设置可以按传感器进行覆盖。
  • /source_name/raytrace_range(默认值: 3.0):使用传感器数据从地图中射线追踪障碍物的默认范围(米)。此设置可以按传感器进行覆盖。

您可以在 husky_navigation 包中的 costmap_common.yaml 文件中查看其完成方式:

laser: {data_type: LaserScan, clearing: true, marking: true, topic: scan, inf_is_valid: true, obstacle_range: 5.5}

正如您在示例中看到的,我们仅声明 1 个 observer_source,用于激光。这意味着我们的 Husky 机器人将根据从其激光接收到的数据构建其本地成本地图。

练习:

a) 将名为 my_common_costmap_params.yaml 的文件添加到您在练习my_move_base_launcher中创建的包的 params 目录中。

b) 将 husky_navigation 包的 costmap_common.yaml 文件的内容复制到这个新文件中。

# 机器人足迹定义,表示机器人在代价图上的占用区域
footprint: [[-0.5, -0.33], [-0.5, 0.33], [0.5, 0.33], [0.5, -0.33]]

# 足迹填充值,用于确保代价图上机器人的边缘有一定的缓冲
footprint_padding: 0.01

# 机器人基础坐标系
robot_base_frame: base_link

# 更新代价图的频率(Hz)
update_frequency: 4.0

# 发布代价图的频率(Hz)
publish_frequency: 3.0

# 坐标变换的容忍度(秒),用于处理传感器数据和代价图之间的坐标变换
transform_tolerance: 0.5

# 代价图的分辨率(米/像素),定义每个像素在实际世界中的大小
resolution: 0.05

# 层定义部分
# 静态地图层
static:
    # 静态地图的主题名称
    map_topic: /map
    # 是否订阅地图更新
    subscribe_to_updates: true

# 障碍物激光层
obstacles_laser:
    # 观测源,表示激光数据的来源
    observation_sources: laser
    # 激光数据的配置
    laser: {
        data_type: LaserScan,          # 数据类型
        clearing: true,                # 是否清除已探测到的障碍物
        marking: true,                 # 是否标记障碍物
        topic: scan,                   # 激光数据的主题
        inf_is_valid: true,            # 是否将无穷大距离视为有效
        obstacle_range: 5.5            # 识别障碍物的最大范围(米)
    }

# 膨胀层
inflation:
    # 膨胀半径(米),用于扩展障碍物区域以考虑机器人周围的安全距离
    inflation_radius: 1.0

a) 现在,修改 obstacle_range 参数并将其设置为 1。

b) 将机器人移近障碍物并观察会发生什么。

Inflation Layer

Inflation Layer负责对每个包含障碍物的单元格进行膨胀处理。

  • inflation_radius(默认值: 0.55):用于膨胀障碍物成本值的半径(米)。
  • cost_scaling_factor(默认值: 10.0):在膨胀过程中应用于成本值的缩放因子。

练习

a) 现在,修改 costmap 的 inflation_radius 参数,使其速度更慢。

b) 靠近某个物体,检查差异。

inflation_radius 参数用于控制障碍物周围的膨胀区域的大小,这有助于为机器人提供一个更加保守的避障区域。

Low inflation:

High inflation:

Static Layer

静态层负责向需要它的代价地图(全局代价地图)提供静态地图。

map_topic(string,默认值:“map”):代价地图为静态地图订阅的主题。

Rotate Recovery

基本上,旋转恢复行为是一种简单的恢复行为,通过将机器人旋转 360 度来尝试清理空间。这样,机器人可能能够找到一条没有障碍物的路径继续导航。

它有一些可以自定义的参数,以便改变或改善其行为:

旋转恢复参数
  • /sim_granularity (默认值: 0.017): 在检查是否可以安全地进行原地旋转时,检查障碍物的距离,单位是弧度。默认为 1 度。
  • /frequency (默认值: 20.0): 向移动底盘发送速度命令的频率,单位是赫兹 (HZ)。
其他参数
  • /yaw_goal_tolerance (double, 默认值: 0.05): 控制器在实现目标时在偏航/旋转方向上的容差,单位是弧度。
  • /acc_lim_th (double, 默认值: 3.2): 机器人的旋转加速度限制,单位是弧度/秒²。
  • /max_rotational_vel (double, 默认值: 1.0): 底盘允许的最大旋转速度,单位是弧度/秒。
  • /min_in_place_rotational_vel (double, 默认值: 0.4): 执行原地旋转时底盘允许的最小旋转速度,单位是弧度/秒。

这些参数也可以在 move_base 参数文件中设置。

Clear Costmap

清除成本图恢复是一种简单的恢复行为,通过清除机器人地图中指定区域之外的障碍物来清理空间。基本上,局部成本图会恢复到与全局成本图相同的状态。

让我们来进行一个简短的练习,以测试这些恢复行为。

练习

向无法到达的机器人发送导航目标,并检查是否触发恢复行为。

例如,您可以在模拟世界的厨房内设置一个目标。查看下图:

move base节点的输出:

旋转恢复行为:

move_base 节点还提供了一项服务,用于清除 costmap 中的障碍物。这项服务称为 /move_base/clear_cotmaps。

请记住,通过清除 costmap 中的障碍物,您将使这些障碍物对机器人不可见。因此,调用此服务时要小心,因为它可能会导致机器人开始撞到障碍物。

练习

a) 如果还没有,则将一个未出现在全局代价地图中的对象添加到场景中。

b) 移动机器人,使其在局部代价地图中检测到这个新障碍物。

c) 转动机器人,使其不再看到障碍物(激光束检测不到它)。

d) 通过 WebShell 调用 /clear_costmaps 服务,并检查发生了什么。

rosservice call /move_base/clear_costmaps "{}"

被激光检测到的物体,放置到局部Ccostmap中:

Husky转身,激光不再检测到物体,但它仍然出现在本地代价地图中。

调用/move_base/clear_costmaps服务后,对象从局部代价地图中清除:

Recap

恭喜你!到目前为止,你已经了解了本章涵盖的几乎所有重要内容。由于这是课程的最后一章,这意味着你距离完全掌握 ROS 导航系统已经非常接近了!

不过,你可能会对有关路径规划的大量信息感到不知所措。因此,我认为这是一个总结本章内容的好时机。让我们开始吧!

move_base 节点

move_base 节点基本上是协调所有路径规划系统的节点。它接收目标位姿作为输入,并输出必要的速度指令,以便将机器人从初始位姿移动到指定的目标位姿。为实现这一目标,move_base 节点管理一个完整的内部流程,其中包括以下几个部分:

  • 全局规划器
  • 局部规划器
  • 成本图
  • 恢复行为

全局规划器

move_base 节点收到新的目标时,它会立即将其发送给全局规划器。全局规划器随后将计算出一条安全的路径,供机器人到达指定的目标。全局规划器使用全局成本图数据来计算这条路径。

有不同类型的全局规划器。根据你的设置,你将使用不同的全局规划器。

局部规划器

一旦全局规划器为机器人计算出路径,它会将路径发送给局部规划器。局部规划器将执行这条路径,将其拆分为更小的(局部)部分。因此,给定一个要遵循的计划和地图,局部规划器将提供速度指令以移动机器人。局部规划器在局部成本图上操作。

有不同类型的局部规划器。根据你对性能的需求,你将选择不同的局部规划器。

成本图

成本图基本上是表示地图上哪些点对机器人是安全的,哪些点是不安全的地图。有 2 种类型的成本图:

  • 全局成本图
  • 局部成本图

基本上,它们之间的区别在于,全局成本图是使用先前构建的静态地图数据构建的,而局部成本图则是从机器人的传感器读取数据构建的。

恢复行为

恢复行为提供了在机器人卡住时的处理方法。导航栈提供了 2 种不同的恢复行为:

  • 旋转恢复
  • 清除成本图

配置

由于有许多不同的节点协同工作,因此可配置的参数数量也非常高。我认为总结一下需要设置的路径规划相关参数文件是一个好主意。你需要的参数文件如下:

<launch>
    <!-- Load move_base parameters -->
    <param file="$(find your_package)/config/move_base_params.yaml" command="load" />
    
    <!-- Load global planner parameters -->
    <param file="$(find your_package)/config/global_planner_params.yaml" command="load" />
    
    <!-- Load local planner parameters -->
    <param file="$(find your_package)/config/local_planner_params.yaml" command="load" />
    
    <!-- Load common costmap parameters -->
    <param file="$(find your_package)/config/common_costmap_params.yaml" command="load" />
    
    <!-- Load global costmap parameters -->
    <param file="$(find your_package)/config/global_costmap_params.yaml" command="load" />
    
    <!-- Load local costmap parameters -->
    <param file="$(find your_package)/config/local_costmap_params.yaml" command="load" />

    <!-- Start the move_base node -->
    <node pkg="move_base" type="move_base" name="move_base" />
</launch>

除了上述参数文件外,我们还需要一个启动文件,以便启动整个系统并加载不同的参数。

总结

总体而言,路径规划的流程如下:

在获取机器人的当前位置后,我们可以将目标位置发送到 move_base 节点。该节点将目标位置发送到全局规划器,全局规划器将计划出一条从当前位置到目标位置的路径。这个计划是基于全局成本图的,而全局成本图由地图服务器提供数据。

全局规划器将此路径发送给本地规划器,本地规划器执行全局计划的每个部分。本地规划器获取里程计和激光数据值,并找到一个没有碰撞的局部计划。局部规划器与本地成本图相关联,本地成本图可以监视机器人周围的障碍物。局部规划器生成速度指令并将其发送到底盘控制器。底盘控制器将这些指令转换为实际的机器人运动。

如果机器人卡住了,恢复行为节点(如清除成本图恢复或旋转恢复)将被调用。

现在一切都更有意义了,对吧?

所以,凭借你在本课程中获得的所有知识,你可以再次查看下面的图示,尝试理解其中涉及的所有不同元素。

动态重新配置

到目前为止,我们已经了解了如何通过在参数文件中修改参数来更改参数。但是,猜猜看……这不是更改参数的唯一方法!您还可以使用 rqt_reconfigure 工具更改动态参数。请按照以下步骤操作:

a) 运行下一个命令以打开 rqt_reconfigure 工具。

rosrun rqt_reconfigure rqt_reconfigure
  • 打开 move_base group。
  • 选择 DWAPlannerROS 节点。
  • 稍微调整一下以下 3 个参数:
    • path_distance_bias
    • goal_distance_bias
    • occdist_scale
  • 上述参数用于计算成本函数,用于对每条轨迹进行评分。更详细地说,它们定义了以下内容:
    • path_distance_bias:控制器应保持接近给定路径的权重。
    • goal_distance_bias:控制器应尝试达到其局部目标的权重,也控制速度。
    • occdist_scale:控制器应尝试避开障碍物的权重。
  • 打开 Rviz 并可视化全局和局部计划如何根据设置的值发生变化。

Rviz 中的其他有用可视化

到目前为止,我们已经了解了一些通过 Rviz 可视化 move_base 节点过程不同部分的方法。但是,还有一些可能值得了解:

Robot Footprint

它显示了机器人的足迹。

Current Goal

要显示导航堆栈试图实现的目标姿势,请添加姿势显示并将其主题设置为 /move_base_simple/goal。现在您将能够看到红色箭头所示的目标姿势。它可用于了解机器人的最终位置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2138704.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

唯徳知识产权管理系统 DownloadFileWordTemplate 文件读取漏洞复现

0x01 产品简介 唯徳知识产权管理系统,由深圳市唯德科创信息有限公司精心打造,旨在为企业及代理机构提供全方位、高效、安全的知识产权管理解决方案。该系统集成了专利、商标、版权等知识产权的全面管理功能,并通过云平台实现远程在线办公,提升工作效率。是一款集知识产权申…

【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C 目录 前言 一、取地址运算符重载 1. const修饰成员函数 2. 取地址运算符重载 二、深究构造函数 三、类型转换 四、static修饰成员 1. static修饰成员变…

监控系列之-prometheus部署说明

一、Prometheus介绍 Prometheus是一款开源的监控系统&#xff0c;主要用于收集、存储和查询时间序列数据&#xff0c;以便于对系统进行监控和分析Prometheus的架构由四个主要组件组成&#xff1a; 1、Prometheus Server &#xff1a;Prometheus Server是Prometheus的核心组件&a…

带你0到1之QT编程:十二、视图宝典,点通views的任督二脉

此为QT编程的第十二谈&#xff01;关注我&#xff0c;带你快速学习QT编程的学习路线&#xff01; 每一篇的技术点都是很很重要&#xff01;很重要&#xff01;很重要&#xff01;但不冗余&#xff01; 我们通常采取总-分-总和生活化的讲解方式来阐述一个知识点&#xff01; …

text2sql(NL2Sql)综述《The Dawn of Natural Language to SQL: Are We Fully Ready?》

《The Dawn of Natural Language to SQL: Are We Fully Ready?》(github)出自2024年6月的NL2SQL(Natural language to SQL )综述论文。这篇论文尝试回答如下三个问题&#xff1a; 问题1:NL2SQL的现状是什么&#xff1f;(Q1:Where Are we Now?) 论文图1总结了近20年NL2SQL方法…

【移动端】菜单的自动展开与收回

前言 为了满足手机上菜单栏随用户移动&#xff0c;菜单的自动展示与隐藏&#xff0c;特此记录 基本原理 实现逻辑 window.addEventListener(‘scroll’, debouncedScrollHandler) – 监听文档视图滚动事件 document.querySelector(‘.header’) – 选择器匹配元素 创建show和h…

论文速递!Auto-CNN-LSTM!新的锂离子电池(LIB)剩余寿命预测方法

论文标题&#xff1a;A Data-Driven Auto-CNN-LSTM Prediction Model for Lithium-Ion Battery Remaining Useful Life 期刊信息&#xff1a;IEEE TII (中科院1区, JCR Q1, IF11.7) 引用&#xff1a;Ren L, Dong J, Wang X, et al. A data-driven auto-CNN-LSTM prediction m…

JavaScript web API part3

web API DOM 日期对象 > 得到当前系统的时间 new这个操作就是实例化 语法 const date new Date() or const date new Date(2004-11-3 08:00:00) 可以指定时间 > 可应用于通过系统时间和指定时间实现倒计时的操作 //得到当前时间const date new Date()console.lo…

多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测

多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测 目录 多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于BO-LSSVM贝叶斯优化最小二乘支…

Vue介绍、窗体内操作、窗体间操作学习

系列文章目录 第一章 基础知识、数据类型学习 第二章 万年历项目 第三章 代码逻辑训练习题 第四章 方法、数组学习 第五章 图书管理系统项目 第六章 面向对象编程&#xff1a;封装、继承、多态学习 第七章 封装继承多态习题 第八章 常用类、包装类、异常处理机制学习 第九章 集…

树莓派5上手

1 安装系统 Raspberry Pi OS 是基于 Debian 的免费操作系统&#xff0c;针对 Raspberry Pi 硬件进行了优化。Raspberry Pi OS 支持超过 35,000 个 Debian 软件包。树莓派 5 可以安装各种系统&#xff0c;但是如果对于系统没有特殊的要求&#xff0c;还是安装 Raspberry Pi OS …

【MySQL】MySQL索引与事务的透析——(超详解)

前言 &#x1f31f;&#x1f31f;本期讲解关于MySQL索引事务&#xff0c;希望能帮到屏幕前的你。 &#x1f308;上期博客在这里&#xff1a;【MySQL】MySQL表的增删改查&#xff08;进阶篇&#xff09;——之查询操作&#xff08;超级详解&#xff09;-CSDN博客 &#x1f308;感…

CSP-CCF★★★201903-2二十四点★★★

目录 一、问题描述 二、解答 方法一&#xff1a;穷举法&#xff08;只列举了一部分&#xff09; 方法二&#xff1a;中缀表达式直接求值&#xff0c;两个栈&#xff0c;一个存放数值&#xff0c;一个存放符号 方法三&#xff1a;将中缀表达式转换为后缀来计算注意&#xff…

台风,也称为热带气旋,是一种在热带海洋上形成的强烈风暴系统。台风的形成需要满足以下几个条件:

台风&#xff0c;也称为热带气旋&#xff0c;是一种在热带海洋上形成的强烈风暴系统。台风的形成需要满足以下几个条件&#xff1a; 1. **温暖的海水**&#xff1a;台风通常在海面温度至少达到26.5C&#xff08;79.7F&#xff09;的海域形成&#xff0c;因为温暖的海水能够提供…

八股(8)——Spring,SpringBoot

八股&#xff08;8&#xff09;——Spring&#xff0c;SpringBoot 基础1.Spring 是什么&#xff1f;特性&#xff1f;有哪些模块&#xff1f;Spring 有哪些特性呢&#xff1f; 2.Spring 有哪些模块呢&#xff1f;3.Spring 有哪些常用注解呢&#xff1f;Web 开发方面有哪些注解呢…

利用模糊综合评价法进行数值评分计算——算法过程

1、‌模糊综合评价法概述 ‌模糊综合评价法是一种基于模糊数学的综合评价方法&#xff0c;它通过模糊数学的隶属度理论将定性评价转化为定量评价&#xff0c;适用于解决复杂、难以量化的问题。该方法具有结果清晰、系统性强的特点&#xff0c;能够处理多种因素制约下的综合评价…

热门数据恢复软件大盘点

现在大家的数据都喜欢存放在一些电子设备里保存吧。这样既方便存放&#xff0c;也方便我们查找。但是这些设备可能因为病毒、误删除等原因造成数据的丢失。这篇文章我将介绍几款类似易我数据恢复软件的数据恢复工具&#xff0c;减少为数据丢失给我们造成损失。 1.FOXIT数据恢复…

vue国际化

前言 现在的大公司都走国际化路线&#xff0c;我们应用程序也不例外。今天就在 Vue3 项目中整一个比较简单的国际化 背景 之前搞国际化的时候&#xff0c;也搜索了很多帖子&#xff0c;但是没有一个可以完整的实现。今天有空搞了一版&#xff0c;大家有什么问题欢迎留言探讨…

Java设计模式—面向对象设计原则(五) ----->迪米特法则(DP) (完整详解,附有代码+案例)

文章目录 3.5 迪米特法则(DP)3.5.1 概述3.5.2 案例 3.5 迪米特法则(DP) 迪米特法则&#xff1a;Demeter Principle&#xff0c;简称DP 3.5.1 概述 只和你的直接朋友交谈&#xff0c;不跟“陌生人”说话&#xff08;Talk only to your immediate friends and not to stranger…

【CSS in Depth 2 精译_031】5.3 Grid 网格布局的两种替代语法

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09; 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位&#xff08;已完结&#xff09; 2.1 相对…