在上一单元中,我们了解了如何合并不同传感器的数据以生成机器人的姿势估计。因此,基本上,我们介绍了图表的以下部分,其中向 robot_localization 节点提供了不同的传感器,以便通过卡尔曼滤波器进行合并。
但是...图表的其他部分怎么样?如果除了传感器数据之外,我们还有另一个外部定位系统作为输入,会发生什么?
好吧,这就是我们将在接下来的章节中发现的!不过,在本章中,我们将重点介绍如何处理外部 SLAM 系统。所以,让我们开始吧!
AMCL
在 ROS 中有多种定位系统存在,但最为知名和广泛使用的无疑是 AMCL。AMCL 是一个用于 2D 环境中移动机器人的概率定位系统。它实现了自适应蒙特卡洛定位(AMCL)方法,使用粒子滤波器来跟踪机器人相对于已知地图的位置。
在本章节中,我们将专注于运行一个 AMCL 节点,以便稍后我们可以将其与 robot_localization 节点结合使用。那么,让我们开始吧!
创建一个地图
要使用 AMCL,您需要做的第一件事就是创建机器人所在环境的地图。为此,您将需要导航堆栈提供的 slam_gmapping 节点。要了解如何执行此操作,请按照下一个练习进行操作:
Exercise 2.1
a) 首先,让我们创建一个新包,将所有与导航相关的文件放在里面。
bashroscd; cd src;
bashcatkin_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) 现在,您可以继续启动此启动文件。
bashroslaunch my_sumit_xl_tools start_mapping.launch
e) 现在让我们启动 RViz,以便能够可视化映射过程。执行以下操作:
将以下显示添加到 RViz:RobotModel、LaserScan 和 Map。
- 将 LaserScan 主题设置为 /hokuyo/base/scan
- 将 Map 主题设置为 /map。
最后,您应该会看到类似以下内容:
f) 现在,您可以开始在环境中移动机器人,以生成环境的完整地图。
您可以使用以下命令移动机器人:
bashroslaunch summit_xl_gazebo keyboard_teleop.launch
太棒了!所以,您已经创建了环境的完整地图。现在该做什么呢?现在是时候保存这张地图了,这样您就可以使用它来定位您的机器人!
保存地图
ROS 导航堆栈中的另一个可用包是 map_server 包。此包提供 map_saver 节点,允许我们从 ROS 服务访问地图数据并将其保存到文件中。
您可以随时使用以下命令保存构建的地图:
bashrosrun map_server map_saver -f name_of_map
该命令将从地图主题中获取地图数据,并将其写入2个文件,name_of_map.pgm和name_of_map.yaml。
Exercise 2.2
a) 将上一个练习中创建的地图保存到文件中。
bashroscd 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
TypeScriptimage: 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) 现在,您可以继续启动此启动文件。
bashroslaunch my_sumit_xl_tools start_amcl_localization.launch
e) 现在让我们启动 RViz,以便能够可视化定位过程。您可以使用与映射过程相同的设置,再添加 1 个显示:位姿数组。
您应该看到类似以下内容:
f) 您可以开始在环境中移动机器人,以便定位机器人。随着机器人的移动,您将在 RViz 中看到粒子如何不断靠近,这意味着机器人的估计姿势越来越接近真实位置。这是对您的定位系统运行情况的测试。
您可以使用以下命令移动机器人:
bashroslaunch 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 变量。
TypeScriptworld_frame: map map_frame: map
正如我们在上一章中已经告诉过您的,此 map_frame 变量用于报告来自知道机器人所在位置的系统的全局位置,在本例中,该系统是我们在上一个练习中创建的 AMCL 系统。
那么这个地图坐标系来自哪里?这个坐标系由 AMCL 节点提供。您可以通过可视化坐标系树来看到这一点,就像您在上一单元中所做的那样。请注意,您需要运行 AMCL 系统才能可视化此地图坐标系。
让我们启动 EKF 定位节点,并验证它是否生成一个名为 odometry/filtered 的新主题。
bashroslaunch my_sumit_xl_tools start_ekf_localization.launch
bashrostopic 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_costmap
和local_costmap
。这意味着它将在全局和局部规划以及两个代价地图的生成中被使用。这只是一种代码重用的方法。costmap_local.yaml
TypeScriptglobal_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
TypeScriptglobal_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
bashcontroller_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) 执行您的启动文件以启动导航系统。
bashroslaunch 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