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

news2024/11/24 3:23:51

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

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

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

AMCL

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

 

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

创建一个地图

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

Exercise 2.1

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

roscd; cd src;
catkin_create_pkg my_sumit_xl_tools

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

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

start_mapping.launch

<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) 现在,您可以继续启动此启动文件。

roslaunch my_sumit_xl_tools start_mapping.launch

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

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

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

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

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

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

roslaunch summit_xl_gazebo keyboard_teleop.launch

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

保存地图

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

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

rosrun map_server map_saver -f name_of_map

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

Exercise 2.2

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

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

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

<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) 现在,您可以继续启动此启动文件。

roslaunch my_sumit_xl_tools start_amcl_localization.launch

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

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

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

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

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

<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

#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 变量。

world_frame: map
map_frame: map

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

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

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

roslaunch my_sumit_xl_tools start_ekf_localization.launch
rostopic list | grep odom

你应该得到如下结果:

/robotnik_base_control/odom
/odometry/filtered

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

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

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

<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。

<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 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

# 机器人足迹定义,定义了机器人的占用空间
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

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

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

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

<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) 执行您的启动文件以启动导航系统。

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

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

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

相关文章

【浅水模型MATLAB】尝试复刻SCI论文中的溃坝流算例

【浅水模型MATLAB】尝试复刻SCI论文中的溃坝流算例 前言问题描述控制方程及数值方法浅水方程及其数值计算方法边界条件的实现 代码框架与关键代码模拟结果 更新于2024年9月17日 前言 这篇博客算是学习浅水方程&#xff0c;并利用MATLAB复刻Liang (2004)1中溃坝流算例的一个记录…

【FreeRL】Rainbow_DQN的实现和测试

文章目录 前言环境1 PER note2 C51 note3 Noisy note4 Rainbow note其他 前言 具体代码实现见&#xff1a;https://github.com/wild-firefox/FreeRL/blob/main/DQN_file/DQN_with_tricks.py 将其中所有的trick都用上即为Rainbow_DQN。 效果如下&#xff1a;&#xff08;学习曲…

word文档的写入(1)

Word文档的写入 我们手动复制Excel信息&#xff0c;再粘贴进Word&#xff0c;进行文件保存的整个操作。属于机械性的重复劳动&#xff0c;并不能带来太大价值。在Excel和Word的操作内&#xff0c;也没有能很好解决此类问题的方法。如果遇到信息一多&#xff0c;几十上百个文件&…

Win11小技巧之调节音量

无意中发现&#xff0c;鼠标悬停在喇叭&#x1f508;处可通过滚轮调节音量&#xff0c;无需每次都点开音量面板&#xff0c;再悬停在音量滚动条处通过滚轮调节&#xff01;&#xff08;设计师……怎么不早告诉我……&#xff09; 不用点开&#xff0c;之前一直都是这么调节音量…

c++—多态【万字】【多态的原理】【重写的深入学习】【各种继承关系下的虚表查看】

目录 C—多态1.多态的概念2.多态的定义及实现2.1多态的构成条件2.2虚函数的重写2.2.1虚函数重写的两个例外&#xff1a;2.2.1.1协变2.2.1.2析构函数的重写 2.3 c11的override和final2.3.1final2.3.2override 2.4 重载、重写、重定义的对比 3.抽象类3.1抽象类的概念3.2接口继承和…

5款录屏软件电脑版,哪一款更适合你?

身边不少做行政的小伙伴&#xff0c;经常需要制作一些培训视频、会议记录或是演示文稿。这就要求他们必须掌握一款好用的录屏软件。作为一个经常搜索各种办公软件的人&#xff0c;今天&#xff0c;我就来分享一下我使用过的五款录屏软件在录制电脑屏幕时的表现。 1、福昕录屏大…

枚举类题目练习心得

两数之和 题目如下&#xff1a; 一点思路&#xff1a;该题目仅限于数据量少的情况使用枚举&#xff0c;从题目分析来看&#xff0c;需求是给定一个数字&#xff0c;要求在给定数组中找到两个数字并使这两个数字和为给定数字且返回目标数字下标。参考题解思路结合本身思路代码…

Leetcode—环形链表||

题目描述 思路 快慢指针 结论 我们需要用到一个重要的结论&#xff1a;让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环运行,两个指针都是每次均走一步,最终肯定会在入口点的位置相遇。 画图解释 1.利用快慢指针找到相遇点 2. 定义两个…

java138-异常处理_java 138错误

//异常 public class test79 { //定义方法声明定义异常&#xff0c;在满足条件时抛出异常对象&#xff0c;程序转向异常处理 public double count(double n,double m)throws Exception { if (m 0) {//如果除数等于0.则抛出异常实例 throw new Ex…

day03 - Java集合和常用类

第一章 Collection集合 1. Collection概述 集合&#xff1a;java中提供的一种容器&#xff0c;可以用来存储多个数据 集合和数组既然都是容器&#xff0c;它们有啥区别呢&#xff1f; 数组的长度是固定的。集合的长度是不固定的。集合可以随时增加元素&#xff0c;其大小也随…

kubeadm方式安装k8s+基础命令的使用

一、安装环境 二、前期准备 1.设置免密登录 [rootk8s-master ~]# ssh-keygen [rootk8s-master ~]# ssh-copy-id root192.168.2.77 [rootk8s-master ~]# ssh-copy-id root192.168.2.88 2.yum源配置 3.清空创建缓存 4.主机映射&#xff08;三台主机都要设置&#xff09; 5.安装…

vivado中选中bd文件后generate output product是什么用,create HDL wrapper是什么用

vivado中选中bd文件后generate output product是什么用 在Vivado中&#xff0c;“Generate Output Products” 是一个重要的步骤&#xff0c;它用于生成IP核的输出产品&#xff0c;这些产品是将IP核集成到设计中所需的文件。这些输出产品包括&#xff1a; 综合文件&#xff…

多线程下的共享变量访问数据竞争的问题

多线程下对共享变量的写存在数据竞问题可导致数据与预期不一致。最近在研究race conditions漏洞&#xff0c;用以下python 代码记录一下&#xff0c;以此论证&#xff0c;如下&#xff1a; from concurrent.futures import ThreadPoolExecutor globalNum 5 def test():global…

微积分-反函数6.1(反函数)

表1提供了一项实验的数据&#xff0c;其中细菌培养物在有限营养基中以100个细菌开始&#xff1b;在定时记录下细菌数量随时间的变化。细菌数量 N N N 是时间 t t t 的函数&#xff1a; N f ( t ) N f(t) Nf(t)。 然而&#xff0c;假设生物学家改变了她的观点&#xff0c;开…

京东App秒级百G日志传输存储架构设计与实战

本文作者&#xff1a;平台业务研发部-武伟峰&#xff0c;数据与智能部-李阳 背景 在日常工作中&#xff0c;我们通常需要存储一些日志&#xff0c;譬如用户请求的出入参、系统运行时打印的一些info、error之类的日志&#xff0c;从而对系统在运行时出现的问题有排查的依据。 …

作为研发部门的负责人,如何助力产品在市场竞争中胜出?浅谈 CTQ

在激烈的市场竞争中&#xff0c;产品研发团队如何帮助企业的产品脱颖而出&#xff1f;成功的产品往往不仅依赖于强大的功能和技术创新&#xff0c;还需要通过高效的研发效能&#xff0c;包括效率、质量和创新&#xff0c;来提升产品的市场竞争力。在本文中&#xff0c;我们将探…

文档内容识别系统源码分享

文档内容识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

一款源码阅读的插件

文章目录 进度汇报功能预览添加高亮标记高亮风格设置笔记颜色设置数据概览高亮数据详情 结尾 进度汇报 之前提到最近有在开发一个源码阅读的IDEA插件&#xff0c;第一版已经开发完上传插件市场了&#xff0c;等官方审批通过就可以尝鲜了。插件名称&#xff1a;Mark source cod…

基于STM32F407ZGT6——看门狗

独立看门狗 独立看门狗的时钟由独立的RC 振荡器LSI 提供&#xff0c;即使主时钟发生故障它仍然有效&#xff0c;非常独立。 LSI 的频率一般在30~60KHZ 之间&#xff0c;根据温度和工作场合会有一定的漂移&#xff0c; 所以独立看门狗的定时时间并不一定非常精确&#xff0c;只适…

格式化u盘选择FAT还是NTFS U盘和硬盘格式化两者选谁

Mac用户在将U盘或硬盘进行格式化时&#xff0c;选择FAT还是NTFS往往是一个让人纠结的问题。很多用户不知道这两个格式之间有什么区别&#xff0c;更不知道在格式化时如何做出选择。本文将为大家介绍Mac选择FAT还是NTFS&#xff0c;并为大家推荐U盘和硬盘格式化两者选谁。 一、…