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

  • 避障是如何工作的
  • 什么是局部规划器?
  • 什么是局部成本图?
  • 路径规划回顾
  • 如何使用动态重新配置和其他 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                                                                 plannerbase_local_planner: "dwa_local_planner/DWAPlannerROS" # Sets the dwa local plannerbase_local_planner: "eband_local_planner/EBandPlannerROS" # Sets the eband local plannerbase_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.5acc_lim_y: 0acc_lim_th: 3.2max_vel_x: 0.5min_vel_x: 0.0max_vel_y: 0min_vel_y: 0max_vel_trans: 0.5min_vel_trans: 0.1max_vel_theta: 1.0min_vel_theta: 0.2# Goal Tolerance Parametersyaw_goal_tolerance: 0.1xy_goal_tolerance: 0.2latch_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: trueplugins:- {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 layerobservation_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.rhkb.cn/news/426182.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring中对于servlet API的封装---springWeb

目录 一.springweb概述 二.springweb的特点 三.springweb的运行流程 四.springweb组件 五.springweb的搭建 1.导包 2.配置 DispatcherServlet 3.开启 springweb 注解 4.处理器的搭建 六.springweb注解 七.springweb拦截器 1.拦截器概述 2.拦截器的实现 (1)添加 servelt api 依赖…

详解:冒泡排序

1.是什么 冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单的排序算法。它重复地遍历要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再需要交换&#xff0c;也就是说该数列已经排序完成…

望繁信科技携流程智能解决方案亮相CNDS 2024新能源产业数智峰会

9月13日&#xff0c;CNDS 2024中国新能源产业数智峰会在北京圆满落幕。本次峰会以“走向数字新能源”为主题&#xff0c;汇聚了来自新能源领域的顶尖领袖、专家学者及知名企业代表&#xff0c;共同探讨数字化技术在新能源行业中的创新应用和发展趋势。上海望繁信科技有限公司&a…

C++ List (带你一篇文章搞定C++中的List类)

感谢大佬的光临各位&#xff0c;希望和大家一起进步&#xff0c;望得到你的三连&#xff0c;互三支持&#xff0c;一起进步 数据结构习题_LaNzikinh篮子的博客-CSDN博客 初阶数据结构_LaNzikinh篮子的博客-CSDN博客 收入专栏&#xff1a;C_LaNzikinh篮子的博客-CSDN博客 其他专…

flask项目初始化

1、初始环境 python3.8 2、flask文档地址&#xff1a;https://flask.palletsprojects.com/en/latest/installation/#install-flask 3、初始化项目 $ mkdir myproject $ cd myproject $ python3 -m venv .venv $ . .venv/bin/activate $ pip install Flask4、打开项目mypr…

Pycharm出现Please specify a different SDK name报错,但是看不到重名环境解决方案

这句话的意思是出现了重名的环境 &#xff0c;一般情况下删除重名的环境即可解决问题。做法如下图所示 1&#xff0c;点击右上角齿轮→settings&#xff08;或者File→settings&#xff09;进入Python Interpreter 2.点击这个沙漏按键&#xff0c;你会发现多了几个环境&#x…

VScode相关问题与解决

VScode只是一个文档编辑器&#xff0c;类似于我们使用的记事本。我们在编辑完文档之后呢一定要保存。 文档编辑器加上它可以安装不同的插件&#xff0c;就可以进行程序开发。 1.写c文件时找不到头文件stdio.h 在linux下我们gcc命令来编译c文件时&#xff0c;会遇到找不到头文…

一文讲懂Mac中的环境变量

你是否曾经因为环境变量配置不当而浪费了宝贵的开发时间?你是否好奇为什么有时候在终端输入命令会提示"command not found",而有时候又能正常运行?如果你是一名Mac用户,并且希望真正掌握环境变量的奥秘,那么这篇文章将为你揭开Mac中环境变量的神秘面纱,帮助你成为一…

Java设计模式—面向对象设计原则(二) --------> 里氏代换原则 LSP (完整详解,附有代码+案列)

文章目录 里氏代换原则3.2.1 概述3.2.2 改进上述代码 里氏代换原则 里氏代换原则&#xff1a;Liskov Substitution Principle&#xff0c;LSP 3.2.1 概述 里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则&#xff1a;任何基类可以出现的地方&#xff0c;子类一定…

html实现好看的多种风格手风琴折叠菜单效果合集(附源码)

文章目录 1.设计来源1.1 风格1 -图文结合手风琴1.2 风格2 - 纯图片手风琴1.3 风格3 - 导航手风琴1.4 风格4 - 双图手风琴1.5 风格5 - 综合手风琴1.6 风格6 - 简描手风琴1.7 风格7 - 功能手风琴1.8 风格8 - 全屏手风琴1.9 风格9 - 全屏灵活手风琴 2.效果和源码2.1 动态效果2.2 源…

FloodFill(洪水灌溉)算法专题——DFS深搜篇

目录 1、图像渲染 1.1 算法原理 1.2 算法代码 2、岛屿数量 2.1 算法原理 2.2 算法代码 3、岛屿的最大面积 3.1 算法原理 3.2 算法代码 4、被围绕的区域 4.1 算法原理 4.2 算法代码 5、太平洋大西洋水流问题 5.1 算法原理 5.2 算法代码 6、扫雷游戏 6.1 算法原理…

React学习day07-ReactRouter-抽象路由模块、路由导航、路由导航传参、嵌套路由、默认二级路由的设置、两种路由模式

14、ReactRouter续 &#xff08;2&#xff09;抽象路由模块 1&#xff09;新建page文件夹&#xff0c;存放组件 组件内容&#xff1a; 2&#xff09;新建router文件夹&#xff0c;在其下创建实例 3&#xff09;实例导入&#xff0c;使用 4&#xff09;效果 &#xff08;3&…

【大数据方案】智慧大数据平台总体建设方案书(word原件)

第1章 总体说明 1.1 建设背景 1.2 建设目标 1.3 项目建设主要内容 1.4 设计原则 第2章 对项目的理解 2.1 现状分析 2.2 业务需求分析 2.3 功能需求分析 第3章 大数据平台建设方案 3.1 大数据平台总体设计 3.2 大数据平台功能设计 3.3 平台应用 第4章 政策标准保障体系 4.1 政策…

Day26_0.1基础学习MATLAB学习小技巧总结(26)——数据插值

利用空闲时间把碎片化的MATLAB知识重新系统的学习一遍&#xff0c;为了在这个过程中加深印象&#xff0c;也为了能够有所足迹&#xff0c;我会把自己的学习总结发在专栏中&#xff0c;以便学习交流。 参考书目&#xff1a; 1、《MATLAB基础教程 (第三版) (薛山)》 2、《MATL…

Java项目——苍穹外卖(二)

Redis 简介 Redis是一个基于内存的key-value结构数据库 基于内存存储&#xff0c;读写性能高适合存储热点数据&#xff08;热点商品、资讯、新闻&#xff09;企业应用广泛 基础操作 启动 在redis安装目录中打开cmd&#xff0c;输入如上图指令即可启动&#xff0c;按下crtl…

【图像匹配】基于SIFT算法的图像匹配,matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于基于SIFT算法的图像匹配&#xff0c;用matlab实现。 一、案例背景和算法介绍 本…

es的封装

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、类和接口介绍0.封装思想1.es的操作分类 二、创建索引1.成员变量2.构造函数2.添加字段3.发送请求4.创建索引总体代码 三.插入数据四.删除数据五.查询数据 前…

Linux下root用户共享conda环境给其他用户

首先可以先用命令查看环境存储位置 conda env list 比如我的root用户的base环境 # conda environments: # base * /usr/local/miniconda3 在root下先给环境添文件夹加普通用户的权限 chmod -R 755 /usr/local/miniconda3 接下来新建一个用户&#xff0…

Python 课程14-TensorFlow

前言 TensorFlow 是由 Google 开发的一个开源深度学习框架&#xff0c;广泛应用于机器学习和人工智能领域。它具有强大的计算能力&#xff0c;能够运行在 CPU、GPU 甚至 TPU 上&#xff0c;适用于从小型模型到大规模生产系统的各种应用场景。通过 TensorFlow&#xff0c;你可以…

Unity+LeapMotion2的使用

开始吧 导入步骤1.到官网下载软件并安装2.安装插件3.场景中添加检测管理器4.场景中添加手部模型 更多细节 导入步骤 1.到官网下载软件并安装 地址 重启电脑后连接设备 可以看到连接成功 2.安装插件 &#xff08;也可以看官方教程&#xff09; Project—>PackageManag…