ROS组合导航笔记2:使用外部定位系统

在上一单元中,我们了解了如何合并不同传感器的数据以生成机器人的姿势估计。因此,基本上,我们介绍了图表的以下部分,其中向 robot_localization 节点提供了不同的传感器,以便通过卡尔曼滤波器进行合并。

但是...图表的其他部分怎么样?如果除了传感器数据之外,我们还有另一个外部定位系统作为输入,会发生什么?

好吧,这就是我们将在接下来的章节中发现的!不过,在本章中,我们将重点介绍如何处理外部 SLAM 系统。所以,让我们开始吧!

AMCL

在 ROS 中有多种定位系统存在,但最为知名和广泛使用的无疑是 AMCL。AMCL 是一个用于 2D 环境中移动机器人的概率定位系统。它实现了自适应蒙特卡洛定位(AMCL)方法,使用粒子滤波器来跟踪机器人相对于已知地图的位置。

在本章节中,我们将专注于运行一个 AMCL 节点,以便稍后我们可以将其与 robot_localization 节点结合使用。那么,让我们开始吧!

创建一个地图

要使用 AMCL,您需要做的第一件事就是创建机器人所在环境的地图。为此,您将需要导航堆栈提供的 slam_gmapping 节点。要了解如何执行此操作,请按照下一个练习进行操作:

Exercise 2.1

a) 首先,让我们创建一个新包,将所有与导航相关的文件放在里面。

bash 复制代码
roscd; cd src;
bash 复制代码
catkin_create_pkg my_sumit_xl_tools

b) 在这个新包中,让我们创建 2 个新目录:一个名为 launch,另一个名为 param。

c) 现在,让我们创建一个 launch 文件以启动我们的 slam_gmapping 节点!

start_mapping.launch

XML 复制代码
<launch>
    <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">
      <remap from="scan" to ="/hokuyo_base/scan"/> <!-- 重映射激光扫描数据源到 /hokuyo_base/scan -->

      <param name="base_frame" value="summit_xl_a_base_footprint"/> <!-- 机器人底盘坐标系名称 -->
      <param name="odom_frame" value="summit_xl_a_odom"/> <!-- 里程计坐标系名称 -->
      
      <!-- 处理每多少个扫描数据中的 1 个(设置为更高的数字以跳过更多扫描) -->
      <param name="throttle_scans" value="1"/>

      <param name="map_update_interval" value="5.0"/> <!-- 地图更新间隔时间(秒),默认值:5.0 -->

      <!-- 激光的最大有效范围。一个光束被裁剪到这个值。 -->
      <param name="maxUrange" value="5.0"/>

      <!-- 传感器的最大范围。如果没有障碍物的区域在传感器范围内应被视为地图中的自由空间,请设置 maxUrange < 真实传感器的最大范围 <= maxRange -->
      <param name="maxRange" value="10.0"/>

      <param name="sigma" value="0.05"/> <!-- 高斯滤波器的标准差 -->
      <param name="kernelSize" value="1"/> <!-- 高斯滤波器的内核大小 -->
      <param name="lstep" value="0.05"/> <!-- 激光扫描数据的步长 -->
      <param name="astep" value="0.05"/> <!-- 角度步长 -->
      <param name="iterations" value="5"/> <!-- 最大迭代次数 -->
      <param name="lsigma" value="0.075"/> <!-- 线性分布的标准差 -->
      <param name="ogain" value="3.0"/> <!-- 增益系数 -->
      <param name="lskip" value="0"/> <!-- 跳过的激光扫描数量 -->
      <param name="srr" value="0.1"/> <!-- 运动模型的旋转误差 -->
      <param name="srt" value="0.2"/> <!-- 运动模型的旋转误差 -->
      <param name="str" value="0.1"/> <!-- 运动模型的平移误差 -->
      <param name="stt" value="0.2"/> <!-- 运动模型的平移误差 -->
      <param name="linearUpdate" value="0.2"/> <!-- 线性更新阈值 -->
      <param name="angularUpdate" value="0.1"/> <!-- 角度更新阈值 -->
      <param name="temporalUpdate" value="3.0"/> <!-- 时间更新阈值 -->
      <param name="resampleThreshold" value="0.5"/> <!-- 重采样阈值 -->
      <param name="particles" value="100"/> <!-- 粒子数量 -->
      <param name="xmin" value="-50.0"/> <!-- 地图的最小 x 坐标 -->
      <param name="ymin" value="-50.0"/> <!-- 地图的最小 y 坐标 -->
      <param name="xmax" value="50.0"/> <!-- 地图的最大 x 坐标 -->
      <param name="ymax" value="50.0"/> <!-- 地图的最大 y 坐标 -->
      <param name="delta" value="0.05"/> <!-- 网格分辨率 -->
      <param name="llsamplerange" value="0.01"/> <!-- 线性样本范围 -->
      <param name="llsamplestep" value="0.01"/> <!-- 线性样本步长 -->
      <param name="lasamplerange" value="0.005"/> <!-- 角度样本范围 -->
      <param name="lasamplestep" value="0.005"/> <!-- 角度样本步长 -->
    </node>
</launch>

这些文件中最重要的参数是:

maxUrange :此参数设置您的激光将被视为创建地图的距离。更大的范围将更快地创建地图,并且机器人迷路的可能性更小。缺点是它会消耗更多资源。
throttle_scans:对于降低资源消耗非常有用。

d) 现在,您可以继续启动此启动文件。

bash 复制代码
roslaunch my_sumit_xl_tools start_mapping.launch

e) 现在让我们启动 RViz,以便能够可视化映射过程。执行以下操作:

将以下显示添加到 RViz:RobotModel、LaserScan 和 Map。

  • 将 LaserScan 主题设置为 /hokuyo/base/scan
  • 将 Map 主题设置为 /map。

最后,您应该会看到类似以下内容:

f) 现在,您可以开始在环境中移动机器人,以生成环境的完整地图。

您可以使用以下命令移动机器人:

bash 复制代码
roslaunch summit_xl_gazebo keyboard_teleop.launch

太棒了!所以,您已经创建了环境的完整地图。现在该做什么呢?现在是时候保存这张地图了,这样您就可以使用它来定位您的机器人!

保存地图

ROS 导航堆栈中的另一个可用包是 map_server 包。此包提供 map_saver 节点,允许我们从 ROS 服务访问地图数据并将其保存到文件中。

您可以随时使用以下命令保存构建的地图:

bash 复制代码
rosrun map_server map_saver -f name_of_map

该命令将从地图主题中获取地图数据,并将其写入2个文件,name_of_map.pgm和name_of_map.yaml。

Exercise 2.2

a) 将上一个练习中创建的地图保存到文件中。

bash 复制代码
roscd my_summit_xl_tools;
mkdir maps;
cd maps;
rosrun map_server map_saver -f my_map;

End of Exercise 2.2

您最终应该会得到 2 个新文件:my_map.yaml 和 my_map.pgm。

PGM 文件包含地图的占用数据(真正重要的数据),而 YAML 文件包含有关地图的一些元数据,例如地图尺寸和分辨率,或 PGM 文件的路径。

my_map.yaml

TypeScript 复制代码
image: my_map.pgm
resolution: 0.050000
origin: [-10.000000, -10.000000, 0.000000]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196

my_map.pgm

定位机器人

生成地图后,我们需要做的下一件事就是将机器人定位到该地图中。

为此,我们将使用导航堆栈中的 amcl 节点。因此,正如您在映射过程中所做的那样,让我们​​创建一个启动文件以启动此节点。

Exercise 2.3

a) 在您的包中,创建一个新的启动文件以启动定位节点。

start_amcl_localization.launch

XML 复制代码
<launch>

  <!-- 运行地图服务器 -->
  <arg name="map_file" default="$(find my_sumit_xl_tools)/maps/my_map.yaml"/> <!-- 指定地图文件路径 -->
  <node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)" /> <!-- 启动地图服务器节点 -->
    
  <node pkg="amcl" type="amcl" name="amcl" output="screen">
  
    <remap from="scan" to="/hokuyo_base/scan" /> <!-- 将扫描数据重映射到 /hokuyo_base/scan -->
    <remap from="cmd_vel" to="/summit_xl_control/cmd_vel"/> <!-- 将速度命令重映射到 /summit_xl_control/cmd_vel -->

    <!-- 从最佳姿态发布扫描,最大频率为 10 Hz -->
    <param name="odom_model_type" value="diff"/> <!-- 里程计模型类型为差分 -->
    <param name="odom_alpha5" value="0.1"/> <!-- 里程计模型的 alpha5 参数 -->
    <param name="transform_tolerance" value="0.2" /> <!-- 变换容忍度 -->
    <param name="gui_publish_rate" value="10.0"/> <!-- GUI 发布速率 -->
    <param name="laser_max_beams" value="30"/> <!-- 激光最大光束数 -->
    <param name="min_particles" value="500"/> <!-- 最小粒子数 -->
    <param name="max_particles" value="5000"/> <!-- 最大粒子数 -->
    <param name="kld_err" value="0.05"/> <!-- KLD 错误阈值 -->
    <param name="kld_z" value="0.99"/> <!-- KLD Z 值 -->
    <param name="odom_alpha1" value="0.2"/> <!-- 里程计模型的 alpha1 参数 -->
    <param name="odom_alpha2" value="0.2"/> <!-- 里程计模型的 alpha2 参数 -->
    <param name="odom_alpha3" value="0.8"/> <!-- 里程计模型的 alpha3 参数 -->
    <param name="odom_alpha4" value="0.2"/> <!-- 里程计模型的 alpha4 参数 -->
    <param name="laser_z_hit" value="0.5"/> <!-- 激光测量的命中概率 -->
    <param name="laser_z_short" value="0.05"/> <!-- 激光短距离测量概率 -->
    <param name="laser_z_max" value="0.05"/> <!-- 激光最大距离测量概率 -->
    <param name="laser_z_rand" value="0.5"/> <!-- 激光随机测量概率 -->
    <param name="laser_sigma_hit" value="0.2"/> <!-- 激光命中模型的标准差 -->
    <param name="laser_lambda_short" value="0.1"/> <!-- 激光短距离模型的参数 -->
    <param name="laser_model_type" value="likelihood_field"/> <!-- 激光模型类型为 likelihood field -->
    <param name="laser_likelihood_max_dist" value="2.0"/> <!-- 激光最大可能距离 -->
    <param name="update_min_d" value="0.2"/> <!-- 最小距离更新阈值 -->
    <param name="update_min_a" value="0.5"/> <!-- 最小角度更新阈值 -->
    <param name="odom_frame_id" value="summit_xl_a_odom"/> <!-- 里程计坐标系ID -->
    <param name="base_frame_id" value="summit_xl_a_base_link"/> <!-- 机器人底盘坐标系ID -->
    <param name="global_frame_id" value="map"/> <!-- 全局坐标系ID -->

    <!--
    <param name="odom_frame_id" value="odom"/>
    <param name="base_frame_id" value="base_footprint"/>
    <param name="global_frame_id" value="map"/>
    -->
    
    <param name="resample_interval" value="1"/> <!-- 重采样间隔 -->
    <param name="transform_tolerance" value="0.1"/> <!-- 变换容忍度 -->
    <param name="recovery_alpha_slow" value="0.0"/> <!-- 慢速恢复的 alpha 参数 -->
    <param name="recovery_alpha_fast" value="0.0"/> <!-- 快速恢复的 alpha 参数 -->
    <param name="initial_pose_x" value ="0.0"/> <!-- 初始位置 x 坐标 -->
    <param name="initial_pose_y" value ="0.0"/> <!-- 初始位置 y 坐标 -->
    <param name="initial_pose_a" value ="0.0"/> <!-- 初始姿态角度 -->

  </node>

</launch>

这些文件中最重要的参数是:

min_particles、max_particles:此参数设置过滤器将使用的粒子数量,以便定位机器人。使用的粒子越多,定位就越精确,但消耗的资源也越多。

laser_max_range:激光束的最大范围。

d) 现在,您可以继续启动此启动文件。

bash 复制代码
roslaunch my_sumit_xl_tools start_amcl_localization.launch

e) 现在让我们启动 RViz,以便能够可视化定位过程。您可以使用与映射过程相同的设置,再添加 1 个显示:位姿数组。

您应该看到类似以下内容:

f) 您可以开始在环境中移动机器人,以便定位机器人。随着机器人的移动,您将在 RViz 中看到粒子如何不断靠近,这意味着机器人的估计姿势越来越接近真实位置。这是对您的定位系统运行情况的测试。

您可以使用以下命令移动机器人:

bash 复制代码
roslaunch summit_xl_gazebo keyboard_teleop.launch

End of Exercise 2.3

太棒了!现在,您已经构建了环境地图,并且能够在地图上定位 Summit XL 机器人

合并amcl与robot_localization

所以,既然我们的 AMCL 系统已经运行,让我们将它与 robot_localization 包合并!

Exercise 2.4

在您的包中,创建一个新的启动文件以启动 robot_localization 包。

start_ekf_localization.launch

XML 复制代码
<launch> 

    <!-- Run the EKF Localization node -->
    <node pkg="robot_localization" type="ekf_localization_node" name="ekf_localization">
        <rosparam command="load" file="$(find my_sumit_xl_tools)/config/ekf_localization.yaml"/>
    </node>

</launch>

现在,让我们创建配置文件,就像您在上一单元中所做的那样。

ekf_localization.yaml

TypeScript 复制代码
#Configuation for robot odometry EKF
#
frequency: 50
    
two_d_mode: true
    
publish_tf: false

odom_frame: summit_xl_a_odom
base_link_frame: summit_xl_a_base_link
world_frame: map
map_frame: map

odom0: /robotnik_base_control/odom
odom0_config: [false, false, false,
               false, false, true,
               true, true, false,
               false, false, true,
               false, false, false]
odom0_differential: false

imu0: /imu/data
imu0_config: [false, false, false,
              false, false, true,
              false, false, false,
              false, false, true,
              true, false, false]
imu0_differential: false

process_noise_covariance": [0.05, 0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,
                                              0,    0.05, 0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,
                                              0,    0,    0.06, 0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,
                                              0,    0,    0,    0.03, 0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,
                                              0,    0,    0,    0,    0.03, 0,    0,     0,     0,    0,    0,    0,    0,    0,    0,
                                              0,    0,    0,    0,    0,    0.06, 0,     0,     0,    0,    0,    0,    0,    0,    0,
                                              0,    0,    0,    0,    0,    0,    0.025, 0,     0,    0,    0,    0,    0,    0,    0,
                                              0,    0,    0,    0,    0,    0,    0,     0.025, 0,    0,    0,    0,    0,    0,    0,
                                              0,    0,    0,    0,    0,    0,    0,     0,     0.04, 0,    0,    0,    0,    0,    0,
                                              0,    0,    0,    0,    0,    0,    0,     0,     0,    0.01, 0,    0,    0,    0,    0,
                                              0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0.01, 0,    0,    0,    0,
                                              0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0.02, 0,    0,    0,
                                              0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0.01, 0,    0,
                                              0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0.01, 0,
                                              0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0.015]


initial_estimate_covariance: [1e-9, 0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,
                                                      0,    1e-9, 0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,
                                                      0,    0,    1e-9, 0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,
                                                      0,    0,    0,    1e-9, 0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,
                                                      0,    0,    0,    0,    1e-9, 0,    0,    0,    0,    0,     0,     0,     0,    0,    0,
                                                      0,    0,    0,    0,    0,    1e-9, 0,    0,    0,    0,     0,     0,     0,    0,    0,
                                                      0,    0,    0,    0,    0,    0,    1e-9, 0,    0,    0,     0,     0,     0,    0,    0,
                                                      0,    0,    0,    0,    0,    0,    0,    1e-9, 0,    0,     0,     0,     0,    0,    0,
                                                      0,    0,    0,    0,    0,    0,    0,    0,    1e-9, 0,     0,     0,     0,    0,    0,
                                                      0,    0,    0,    0,    0,    0,    0,    0,    0,    1e-9,  0,     0,     0,    0,    0,
                                                      0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     1e-9,  0,     0,    0,    0,
                                                      0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     1e-9,  0,    0,    0,
                                                      0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     1e-9, 0,    0,
                                                      0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    1e-9, 0,
                                                      0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    1e-9]

如您所见,主要的区别在于,现在我们使用 map_frame 变量。

TypeScript 复制代码
world_frame: map
map_frame: map

正如我们在上一章中已经告诉过您的,此 map_frame 变量用于报告来自知道机器人所在位置的系统的全局位置,在本例中,该系统是我们在上一个练习中创建的 AMCL 系统。

那么这个地图坐标系来自哪里?这个坐标系由 AMCL 节点提供。您可以通过可视化坐标系树来看到这一点,就像您在上一单元中所做的那样。请注意,您需要运行 AMCL 系统才能可视化此地图坐标系。

让我们启动 EKF 定位节点,并验证它是否生成一个名为 odometry/filtered 的新主题。

bash 复制代码
roslaunch my_sumit_xl_tools start_ekf_localization.launch
bash 复制代码
rostopic list | grep odom

你应该得到如下结果:

bash 复制代码
/robotnik_base_control/odom
/odometry/filtered

太棒了!现在我们知道我们的 EKF 定位节点正在工作......什么?好吧,现在我们使用它!

默认情况下,我们在上一个练习中创建的 AMCL 系统使用 /odom 主题来获取里程表数据。但是现在,多亏了我们的 EKF 定位节点,我们拥有了更可靠的里程表数据,这些数据发布在 /odometry/filtered 主题上。那么......如何使用这个新的里程表代替旧的里程表呢?

为此,我们需要做的就是重新映射 start_amcl_localization.launch 文件中的主题。在文件的开头,您将看到一些主题正在重新映射,因此让我们也重新映射里程表主题:

XML 复制代码
<node pkg="amcl" type="amcl" name="amcl" output="screen">

  <remap from="scan" to="/hokuyo_base/scan" />
  <remap from="cmd_vel" to="/summit_xl_control/cmd_vel"/>
  <remap from="odom" to="/odometry/filtered" />

太棒了!现在让我们创建一个结合两种定位的新启动文件。我们将其命名为 global_localization.launch。

XML 复制代码
<launch>

    <!--- Start AMCL Localization -->
    <include file="$(find my_sumit_xl_tools)/launch/start_amcl_localization.launch" />
    
    <!-- Start EKF Localization -->
    <include file="$(find my_sumit_xl_tools)/launch/start_ekf_localization.launch" />

</launch>

启动这个新文件,并使用 PoseArray 显示器在 RViz 中检查现在的定位效果。您应该得到如下结果:

你看到有什么不同吗?如果我们比较添加 EKF 定位节点之前和之后的同一张图像,我们可以看到我们的定位有了很大的改善。

如您所见,在第二张图片中,箭头更加集中,分散性更低,这意味着定位效果更好。

太棒了!现在,为了完成本章,让我们添加一个路径规划系统,以便我们能够使用我们新改进的定位来导航我们的机器人!

让我们导航我们的机器人!

为了进行路径规划,我们将使用导航堆栈中的 move_base 节点,它将为您管理整个路径规划系统。因此,正如您在前面的练习中所做的那样,让我们​​创建启动文件以启动路径规划系统。不过,这一次,您将需要做一些额外的工作,因为您需要设置很多参数。但别担心,您可以按照下一个练习来指导您完成整个过程!

Exercise 2.5

a) 首先,让我们创建一个新的启动文件来启动move_base节点。

move_base_map.launch

XML 复制代码
<?xml version="1.0"?>
<!-- NEW SUMIT XL NAVIGATION -->
<launch>
    
    <arg name="base_global_planner" default="navfn/NavfnROS"/> <!-- 全局规划器,默认使用 NavfnROS -->
    <arg name="base_local_planner" default="dwa_local_planner/DWAPlannerROS"/> <!-- 局部规划器,默认使用 DWAPlannerROS -->
    <!-- <arg name="base_local_planner" default="base_local_planner/TrajectoryPlannerROS"/> --> <!-- 可选的局部规划器,TrajectoryPlannerROS -->

    <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
        
        <remap from="scan" to="/hokuyo_base/scan" /> <!-- 将扫描数据重映射到 /hokuyo_base/scan -->
        <remap from="cmd_vel" to="/summit_xl_control/cmd_vel"/> <!-- 将速度命令重映射到 /summit_xl_control/cmd_vel -->
        <remap from="odom" to="/odometry/filtered" /> <!-- 将里程计数据重映射到 /odometry/filtered -->
        
        <param name="base_global_planner" value="$(arg base_global_planner)"/> <!-- 设置全局规划器 -->
        <param name="base_local_planner" value="$(arg base_local_planner)"/>  <!-- 设置局部规划器 -->
        
        <!-- 加载全局和局部代价地图的通用配置 -->
        <rosparam file="$(find my_sumit_xl_tools)/config/planner.yaml" command="load"/> <!-- 加载规划器相关的参数配置 -->
        
        <!-- 代价地图源配置,位于 costmap_common.yaml -->
        <rosparam file="$(find my_sumit_xl_tools)/config/costmap_common.yaml" command="load" ns="global_costmap" /> <!-- 加载全局代价地图的通用配置 -->
        <rosparam file="$(find my_sumit_xl_tools)/config/costmap_common.yaml" command="load" ns="local_costmap" /> <!-- 加载局部代价地图的通用配置 -->
        
        <!-- 局部代价地图,需要设置尺寸 -->
        <rosparam file="$(find my_sumit_xl_tools)/config/costmap_local.yaml" command="load" ns="local_costmap" /> <!-- 加载局部代价地图的特定配置 -->
        <param name="local_costmap/width" value="5.0"/> <!-- 局部代价地图的宽度 -->
        <param name="local_costmap/height" value="5.0"/> <!-- 局部代价地图的高度 -->
        
        <!-- 静态全局代价地图,静态地图提供尺寸 -->
        <rosparam file="$(find my_sumit_xl_tools)/config/costmap_global_static.yaml" command="load" ns="global_costmap" /> <!-- 加载静态全局代价地图的配置 -->

    </node>

</launch>

如您所见,有许多参数文件正在加载,所以让我们创建它们!您必须将所有这些参数文件放在 my_sumit_xl_tools 包内名为 config 的文件夹中。

costmap_common.yaml

TypeScript 复制代码
# 机器人足迹定义,定义了机器人的占用空间
footprint: [[0.35, -0.3], [0.35, 0.3], [-0.35, 0.3], [-0.35, -0.3]]
footprint_padding: 0.01  # 足迹的额外填充,用于增加安全边距

# 机器人基础坐标系
robot_base_frame: summit_xl_a_base_link
update_frequency: 4.0  # 代价地图的更新频率(Hz)
publish_frequency: 3.0  # 代价地图的发布频率(Hz)
transform_tolerance: 0.5  # 变换容忍度,用于处理坐标变换的延迟

resolution: 0.05  # 地图分辨率,每个栅格的大小为 0.05 米

obstacle_range: 5.5  # 检测障碍物的最大范围(米)
raytrace_range: 6.0  # 激光射线追踪的最大范围(米)

# 图层定义
static:
    map_topic: /map  # 静态地图的话题
    subscribe_to_updates: true  # 是否订阅地图更新

obstacles_laser:
    observation_sources: hokuyo_laser  # 观测源的名称
    hokuyo_laser: 
        sensor_frame: summit_xl_a_front_laser_link  # 激光传感器坐标系
        data_type: LaserScan  # 数据类型
        clearing: true  # 是否用于清除障碍物
        marking: true  # 是否用于标记障碍物
        topic: hokuyo_base/scan  # 激光扫描数据的话题
        inf_is_valid: true  # 是否将无限距离视为有效数据

inflation:
    inflation_radius: 1.0  # 膨胀半径,用于在代价地图中创建障碍物周围的安全区域

评论一下涉及到 Summit XL 的一些元素:

  • footprint 和 footprint_padding:这些参数定义了机器人的简化模型,即一个包围机器人的简单框。如果你希望机器人能够非常接近物体,可以将填充值(padding)设得更小。在这种情况下,值为 0.1,因为这个型号的 Summit 配备普通轮子,在转向时容易产生某些误差,因此其机动性不如其兄弟型号 Summit XL(配备全向轮)。

  • obstacles_laser :这里定义了用于导航的激光数据传感器。在这个例子中,话题是 /hokuyo_base/scan

另外,提到这个文件 costmap_common.yaml 被加载到两个命名空间中:global_costmaplocal_costmap。这意味着它将在全局和局部规划以及两个代价地图的生成中被使用。这只是一种代码重用的方法。

costmap_local.yaml

TypeScript 复制代码
global_frame: summit_xl_a_odom  # 全局坐标系的名称,这里设置为 summit_xl_a_odom
rolling_window: true  # 是否使用滚动窗口模式

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

在此处注释:

  • global_frame:对于 Local Costmaps,通常将其设置为 odom。
  • plugins:此处加载并执行障碍物检测和膨胀的插件。

costmap_global_static.yaml

TypeScript 复制代码
global_frame: map  # 全局坐标系的名称,这里设置为 'map'
rolling_window: false  # 是否使用滚动窗口模式,这里设置为 false,表示不使用滚动窗口模式
track_unknown_space: true  # 是否跟踪未知空间,将未知空间标记为代价地图中的障碍物

plugins:
  - {name: static, type: "costmap_2d::StaticLayer"}  
  - {name: inflation, type: "costmap_2d::InflationLayer"}  

因此,如您所见,它与前一个非常相似。

  • global_frame:对于 Global Costmaps,通常将其设置为 map(使用地图导航时)。
  • plugins:此处加载并执行静态地图和 Inflation 的插件。

planner.yaml

bash 复制代码
controller_frequency: 5.0  # 控制器的频率(Hz),表示控制器每秒更新的次数
recovery_behaviour_enabled: true  # 是否启用恢复行为,用于处理机器人遇到的障碍物或困境

NavfnROS:
  allow_unknown: true  # 是否允许导航规划器生成穿越未知空间的路径
  default_tolerance: 0.1  # 规划器目标点的容忍度

TrajectoryPlannerROS:
  # 机器人配置参数
  acc_lim_x: 2.5  # 机器人在 X 轴方向的加速度限制
  acc_lim_theta: 3.2  # 机器人在旋转方向的加速度限制

  max_vel_x: 1.0  # 机器人在 X 轴方向的最大速度
  min_vel_x: 0.0  # 机器人在 X 轴方向的最小速度

  max_vel_theta: 1.0  # 机器人在旋转方向的最大速度
  min_vel_theta: -1.0  # 机器人在旋转方向的最小速度
  min_in_place_vel_theta: 0.2  # 机器人在原地旋转时的最小速度

  holonomic_robot: false  # 机器人是否为全向的,这里设置为 false 表示不是全向机器人
  escape_vel: -0.1  # 逃逸速度,机器人在遇到障碍物时的反向速度

  # 目标容忍度参数
  yaw_goal_tolerance: 0.1  # 目标方向的容忍度(弧度)
  xy_goal_tolerance: 0.2  # 目标位置的容忍度(米)
  latch_xy_goal_tolerance: false  # 是否锁定目标位置的容忍度,设置为 false 表示不锁定

  # 前向模拟参数
  sim_time: 2.0  # 模拟时间(秒)
  sim_granularity: 0.02  # 模拟粒度,时间步长(秒)
  angular_sim_granularity: 0.02  # 角度模拟粒度(弧度)
  vx_samples: 6  # 前向速度样本数量
  vtheta_samples: 20  # 旋转速度样本数量
  controller_frequency: 20.0  # 控制器的频率(Hz)

  # 轨迹评分参数
  meter_scoring: true  # 是否将距离单位假设为米,而不是默认的栅格单元
  occdist_scale: 0.1  # 避免障碍物的权重
  pdist_scale: 0.75  # 保持靠近路径的权重
  gdist_scale: 1.0  # 尝试达到局部目标的权重,同时控制速度

  heading_lookahead: 0.325  # 在评分不同的旋转轨迹时,前瞻的距离(米)
  heading_scoring: false  # 是否基于机器人朝向路径还是距离路径进行评分
  heading_scoring_timestep: 0.8  # 使用朝向评分时,模拟轨迹的前瞻时间(秒)
  dwa: true  # 是否使用动态窗口方法(DWA),否则使用轨迹展开
  simple_attractor: false  # 是否使用简单的吸引子模型
  publish_cost_grid_pc: true  # 是否发布代价网格点云

  # 振荡防止参数
  oscillation_reset_dist: 0.25  # 机器人必须移动的距离(米),以便重置振荡标志
  escape_reset_dist: 0.1  # 逃逸模式重置距离
  escape_reset_theta: 0.1  # 逃逸模式重置角度(弧度)

DWAPlannerROS:
  # 机器人配置参数
  acc_lim_x: 2.5  # 机器人在 X 轴方向的加速度限制
  acc_lim_y: 0  # 机器人在 Y 轴方向的加速度限制
  acc_lim_th: 3.2  # 机器人在旋转方向的加速度限制

  max_vel_x: 0.5  # 机器人在 X 轴方向的最大速度
  min_vel_x: 0.0  # 机器人在 X 轴方向的最小速度
  max_vel_y: 0  # 机器人在 Y 轴方向的最大速度
  min_vel_y: 0  # 机器人在 Y 轴方向的最小速度

  max_trans_vel: 0.5  # 最大线速度
  min_trans_vel: 0.1  # 最小线速度
  max_rot_vel: 1.0  # 最大旋转速度
  min_rot_vel: 0.2  # 最小旋转速度

  # 目标容忍度参数
  yaw_goal_tolerance: 0.1  # 目标方向的容忍度(弧度)
  xy_goal_tolerance: 0.2  # 目标位置的容忍度(米)
  latch_xy_goal_tolerance: false  # 是否锁定目标位置的容忍度

  # 轨迹评分参数(已注释掉)
  # 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  # 机器人轮廓缩放的速度(m/s)
  # max_scaling_factor: 0.2  # 机器人轮廓的最大缩放因子

  # 振荡防止参数(已注释掉)
  # oscillation_reset_dist: 0.25  # 机器人必须移动的距离(米),以便重置振荡标志

在这里我们可以注释很多参数。只是指出几个真正重要的:

  • yaw_goal_tolerance:这个参数表示你希望机器人在给定姿态下的精度。在这种情况下,指的是 XY 平面上的方向精度。

  • xy_goal_tolerance:这个参数与前一个类似,但指的是 XY 平面上的位置精度。

  • holonomic_robot:这个参数很重要,因为 Summit XL 配备全向轮时可以被视为全向机器人。而你当前使用的 Summit 型号则不是全向的。

DWAPlannerROS 是用于局部规划器的规划器。您也可以使用 TrajectoryPlannerROS。主要区别在于速度的采样方式。但它们在一般情况下的表现或多或少处于同一水平。

b) 现在,让我们创建一个启动文件,它将我们迄今为止所做的一切结合起来:

start_navigation.launch

XML 复制代码
<launch>

    <!--- Start AMCL Localization -->
    <include file="$(find my_sumit_xl_tools)/launch/start_amcl_localization.launch" />
    
    <!-- Start EKF Localization -->
    <include file="$(find my_sumit_xl_tools)/launch/start_ekf_localization.launch" />
    
    <!-- Start Move Base -->
    <include file="$(find my_sumit_xl_tools)/launch/move_base_map.launch" />

</launch>

c) 执行您的启动文件以启动导航系统。

bash 复制代码
roslaunch my_sumit_xl_tools start_navigation.launch

d) 现在让我们启动 RViz,以便能够可视化路径规划过程。您需要添加以下内容:

  • 固定坐标必须是地图。
  • 请注意两个路径显示:一个用于局部,另一个用于全局规划。
  • 还请注意两个地图:一个用于 LocalCostmap,另一个用于 GlobalCostmap。

最后,你应该看到类似这样的内容:

e) 使用 Rviz 中的 2D 位姿估计工具在地图中定位机器人。

f) 使用 Rviz 中的 2D 导航目标工具向机器人发送目标(所需位姿)。

现在您应该看到 Summit XL 机器人在模拟中到达该位置。在 Rviz 中,您还可以可视化它所遵循的规划路径。

End of Exercise 2.5

相关推荐
Komorebi.py30 分钟前
【Linux】-学习笔记05
linux·笔记·学习
亦枫Leonlew39 分钟前
微积分复习笔记 Calculus Volume 1 - 6.5 Physical Applications
笔记·数学·微积分
冰帝海岸6 小时前
01-spring security认证笔记
java·笔记·spring
小二·7 小时前
java基础面试题笔记(基础篇)
java·笔记·python
wusong99910 小时前
mongoDB回顾笔记(一)
数据库·笔记·mongodb
猫爪笔记10 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
Resurgence0310 小时前
【计组笔记】习题
笔记
pq113_610 小时前
ftdi_sio应用学习笔记 3 - GPIO
笔记·学习·ftdi_sio
爱米的前端小笔记11 小时前
前端八股自学笔记分享—页面布局(二)
前端·笔记·学习·面试·求职招聘
寒笙LED13 小时前
C++详细笔记(六)string库
开发语言·c++·笔记