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

相关推荐
铁匠匠匠39 分钟前
从零开始学数据结构系列之第六章《排序简介》
c语言·数据结构·经验分享·笔记·学习·开源·课程设计
Moliay2 小时前
【资料分析】刷题日记2
笔记·公考·行测·常识·资料分析
小齿轮lsl2 小时前
PFC理论基础与Matlab仿真模型学习笔记(1)--PFC电路概述
笔记·学习·matlab
天玑y3 小时前
算法设计与分析(背包问题
c++·经验分享·笔记·学习·算法·leetcode·蓝桥杯
web_learning_3214 小时前
source insight学习笔记
笔记·学习
无妄啊______5 小时前
mysql笔记9(子查询)
数据库·笔记·mysql
z2014z5 小时前
系统架构设计师教程 第5章 5.3 系统分析与设计 笔记
笔记·系统架构
青石横刀策马6 小时前
泛读笔记:从Word2Vec到BERT
笔记·bert·word2vec
Magnetic_h7 小时前
【iOS】单例模式
笔记·学习·ui·ios·单例模式·objective-c
重生之我在20年代敲代码8 小时前
HTML讲解(二)head部分
前端·笔记·html·web app