系列文章目录
提示:所有文章的目录都可以添加到这里。目录需要手动添加 TODO:写完再整理
文章目录
- 系列文章目录
- 前言
- (0)蒙特卡罗方法原理
- (1)amcl定位框架介绍
- (2)amcl定位框架组成
-
- (1)ROS-TF坐标转换树【ROS的工具】
- (2)robot_pose_ekf扩展卡尔曼位置估计算法
- (3)定位amcl蒙特卡洛定位自适应,adaptive monte carlo localizaion**
- (3)amcl定位节点的订阅和发布
- (4)amcl定位功能包用法
-
- (1)编写amcl节点相关的launch(amcl_omni.launch)文件
- (2)配置launch文件参数
- (3)编写测试launch文件
- (4)执行 launch文件
- (5)amcl定位程序源码应用程序只需安装源码
- (6)amcl的定位效果
-
- (1)第一步:算法初始分布
- (2)第二步:算法收敛:
- (3)第三步:稳定定位
- (4)原理Odometry Localization和AMCL Map Localization比较
- (7)amcl解决定位失败的解决方案(工程经验)
-
- 方法1:机器人运行时处理
- 方法二:机器人停止时处理
前言
认知有限,希望大家多包容,希望能和大家多交流,共同成长!本文先对做一个简单的介绍,具体内容后续更多,其他模块可以参考我的其他文章
提示:以下是本文的主要内容
(0)蒙特卡罗方法原理
蒙特卡罗的本质是基于大数定律防盗标志–盒子君hzj】,主要包括三步:
- 样本采集根据输入的概率密度;
- 每个样本通过非线性函数转换;
- 概率密度从转换样本中重新计算 . 。
(1)amcl定位框架介绍
amcl节点利用粒子滤波算法实现机器人的全局定位,为机器人导航提供全局定位信息 由机器人定位框架ROS-TF坐标转换树,机器人扩展卡尔位置融合曼算法robot_pose_ekf和自适应蒙特卡洛定位框架amcl如果这三个部分相互独立,我们可以根据自己项目的实际需要防盗标志–盒子君hzj】与不同的定位算法灵活匹配,完成机器人的定位任务
简单来说,就是放很多pose(x, y, [偏航角] ),然后估计下一个pose基于粒子滤波的数据,从地图上看到的最符合雷达的数据(KLD)提供算法SLAM定位基础可以帮助机器人在已知地图上确定自己的位置,并不断跟踪机器人的定位 MCL(非自适应蒙特卡洛)定位算法采用粒子滤波定位 例子滤波器和浅度解释:一开始,沙子(颗粒)均匀地撒在地图空间,然后通过移动机器人的运动移动颗粒。例如,机器人向前移动1米,所有颗粒也向前移动1米,防盗标志–盒子君hzj】同时,每个粒子的位置将模拟一个传感器(通常是激光雷达),粒子的位置将模拟传感器与真实传感器进行比较,从而赋予每个粒子位置准确性的概率,然后根据这个概率不断产生新的粒子。准确性概率越大,产生粒子的可能性越大。经过多次迭代,所有粒子都会慢慢收敛聚集在一起,估计机器人的确切位置。
:地图、雷达数据、里程计 :小车pose (x, y,? theta)
(2)amcl定位框架组成
(1)ROS-TF坐标转换树【ROS的工具】
具体看看ros教程
在里程计信息定位和车载传感器定位实现中,机器人坐标系一般采用机器人模型中的根坐标系(base_link 或 base_footprint),里程计定位时,父级坐标系一般称为 odom,【防盗标记–盒子君hzj】如果通过传感器定位,父级参考系一般称为 map。两者结合使用时,map 和 odom 都是机器人模型根坐标系的父级,不符合坐标变换"单继承"因此,转换关系一般设置为: map -> doom -> base_link 或 base_footprint
(2)robot_pose_ekf扩展卡尔曼位置估计算法
我再开一个博客写,请转战
(3)定位amcl蒙特卡洛定位自适应,adaptive monte carlo localizaion**
. .
(3)amcl定位节点的订阅和发布
订阅话题
/tf (tf/tfMessage) 订阅各坐标系转换主题,查询各坐标系转换 /initialpose (geometry_msgs/PoseWithCovarianceStamped) 用于(重新)初始化粒子滤波器的平均值和协方差,简单理解就是先估计机器人的初始位置 /amcl/map (nav_msgs/OccupancyGrid) 当在launch文件中设置了use_map_topic为true时,amcl订阅主题获取地图,然后使用激光定位,当然设置use_map_topic为false不订阅这个话题也可以。
发布话题
amcl_pose (geometry_msgs/PoseWithCovarianceStamped
)机器人在地图上带有协方差的位姿估计,这个是话题是整个粒子滤波定位的最终输出结果,该话题输出的位姿信息是根据全局坐标系/map的坐标转换后的位置 particlecloud
(geometry_msgs/PoseArray
) 在粒子滤波器维护下的一组粒子位姿估计,可以直接在rviz中显示,查看粒子的收敛效果 tf
(tf/tfMessage
) 发布从odom坐标系到map坐标系的转换,当然该odom坐标系可以使用odom_frame_id参数来重新映射为自定义的坐标系名称 scan
(sensor_msgs/LaserScan
)
(4)amcl定位功能包用法
(1)编写amcl节点相关的launch(amcl_omni.launch)文件
<launch>
<node pkg="amcl" type="amcl" name="amcl" output="screen">
<!-- Publish scans from best pose at a max of 10 Hz -->
<param name="odom_model_type" value="diff"/><!-- 里程计模式为差分 -->
<param name="odom_alpha5" value="0.1"/>
<param name="transform_tolerance" value="0.2" />
<param name="gui_publish_rate" value="10.0"/>
<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"/>
<param name="kld_z" value="0.99"/>
<param name="odom_alpha1" value="0.2"/>
<param name="odom_alpha2" value="0.2"/>
<!-- translation std dev, m -->
<param name="odom_alpha3" value="0.8"/>
<param name="odom_alpha4" value="0.2"/>
<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_lambda_short" value="0.1"/>
<param name="laser_model_type" value="likelihood_field"/>
<!-- <param name="laser_model_type" value="beam"/> -->
<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="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"/>
<param name="recovery_alpha_fast" value="0.0"/>
</node>
</launch>
(2)配置launch文件参数
<launch>
<!--当设置为true时,AMCL将会订阅map话题,而不是调用服务返回地图。也就是说当设置为true时,有另外一个节点实时的发布map话题,
也就是机器人在实时的进行地图构建,并供给amcl话题使用;当设置为false时,通过map server,也就是调用已经构建完成的地图。-->
<arg name="use_map_topic" default="false"/>
<arg name="scan_topic" default="scan"/> <!--扫描话题-->
<arg name="initial_pose_x" default="0.0"/> <!--初始位姿均值x,用于初始化高斯分布滤波器-->
<arg name="initial_pose_y" default="0.0"/> <!--初始位姿均值y,用于初始化高斯分布滤波器-->
<arg name="initial_pose_a" default="0.0"/> <!--初始位姿均值(yaw),用于初始化高斯分布滤波器-->
<arg name="odom_frame_id" default="odom"/> <!--里程计默认坐标-->
<arg name="base_frame_id" default="base_link"/> <!--机器人基坐标-->
<arg name="global_frame_id" default="map"/> <!--全局坐标-->
<node pkg="amcl" type="amcl" name="amcl">
<param name="use_map_topic" value="$(arg use_map_topic)"/>
<!-- Publish scans from best pose at a max of 10 Hz -->
<param name="odom_model_type" value="diff"/> <!--选择odom模型,diff差速模型,omni全向模型-->
<param name="odom_alpha5" value="0.1"/> <!--移相关的噪声参数(仅用于模型是“omni”的情况,默认0-->
<param name="gui_publish_rate" value="10.0"/> <!--扫描和路径发布到可视化软件的最大频率-->
<param name="laser_max_beams" value="120"/> <!--更新滤波器时,每次扫描中多少个等间距的光束被使用-->
<param name="laser_max_range" value="80.0"/> <!--最大扫描范围,参数设置为-1.0时,将会使用激光上报的最大扫描范围-->
<param name="min_particles" value="500"/> <!--滤波器中的最少粒子数,值越大定位效果越好,但是相应的会增加主控平台的计算资源消耗-->
<param name="max_particles" value="5000"/> <!--滤波器中最多粒子数,是一个上限值-->
<param name="kld_err" value="0.05"/> <!--真实分布与估计分布之间的最大误差-->
<param name="kld_z" value="0.99"/> <!--上标准分位数(1-p),其中p是估计分布上误差小于kld_err的概率-->
<param name="odom_alpha1" value="0.2"/> <!--机器人运动部分的旋转分量估计的里程计旋转的期望噪声-->
<param name="odom_alpha2" value="0.2"/> <!--机器人运动部分的平移分量估计的里程计旋转的期望噪声-->
<!-- translation std dev, m -->
<param name="odom_alpha3" value="0.8"/> <!--机器人运动部分的平移分量估计的里程计平移的期望噪声-->
<param name="odom_alpha4" value="0.2"/> <!--机器人运动部分的旋转分量估计的里程计平移的期望噪声-->
<param name="laser_z_hit" value="0.5"/> <!--模型的z_hit部分的混合权值-->
<param name="laser_z_short" value="0.05"/> <!--模型的z_short部分的混合权值-->
<param name="laser_z_max" value="0.05"/> <!--模型的z_max部分的混合权值-->
<param name="laser_z_rand" value="0.5"/> <!--模型的z_rand部分的混合权值-->
<param name="laser_sigma_hit" value="0.2"/> <!--被用在模型的z_hit部分的高斯模型的标准差-->
<param name="laser_lambda_short" value="0.1"/> <!--模型z_short部分的指数衰减参数-->
<param name="laser_model_type" value="likelihood_field"/> <!--激光模型类型定义,可以是beam, likehood_field, likehood_field_prob-->
<!-- <param name="laser_model_type" value="beam"/> -->
<param name="laser_likelihood_max_dist" value="2.0"/> <!--地图上做障碍物膨胀的最大距离-->
<param name="update_min_d" value="0.2"/> <!--在执行滤波更新前平移运动的距离-->
<param name="update_min_a" value="0.4"/> <!--执行滤波更新前旋转的角度-->
<param name="odom_frame_id" value="$(arg odom_frame_id)"/>
<param name="base_frame_id" value="$(arg base_frame_id)"/>
<param name="global_frame_id" value="$(arg global_frame_id)"/>
<param name="resample_interval" value="0.5"/> <!--在重采样前需要滤波更新的次数-->
<!-- Increase tolerance because the computer can get quite busy -->
<param name="transform_tolerance" value="0.1"/> <!--tf变换发布推迟的时间-->
<param name="recovery_alpha_slow" value="0.0"/> <!--慢速的平均权重滤波的指数衰减频率,用作决定什么时候通过增加随机位姿来recover-->
<param name="recovery_alpha_fast" value="0.0"/> <!--快速的平均权重滤波的指数衰减频率,用作决定什么时候通过增加随机位姿来recover-->
<<param name="initial_pose_x" value="$(arg initial_pose_x)"/>
<param name="initial_pose_y" value="$(arg initial_pose_y)"/>
<param name="initial_pose_a" value="$(arg initial_pose_a)"/>
<remap from="scan" to="$(arg scan_topic)"/>
</node>
</launch>
< ```
(3)编写测试launch文件
<launch>
<!-- 设置地图的配置文件 -->
<arg name="map" default="nav.yaml" />
<!-- 运行地图服务器,并且加载设置的地图-->
<node name="map_server" pkg="map_server" type="map_server" args="$(find mycar_nav)/map/$(arg map)"/>
<!-- 启动AMCL节点 -->
<include file="$(find mycar_nav)/launch/amcl.launch" />
<!-- 运行rviz -->
<node pkg="rviz" type="rviz" name="rviz"/>
</launch>
(4)执行 launch文件
. .
(5)amcl定位程序源码【应用仅仅需要安装源码】
ROS提供了定位(amcl)功能包,【防盗标记–盒子君hzj】来实现二维地图中的机器人定位,在ROS的导航功能包集navigation中提供了 amcl 功能包,用于实现导航中的机器人定位,amcl已经被集成到了navigation包中
mcl功能包源码路径 . . .
(6)amcl的定位效果
(1)第一步:算法初始化分布
(2)第二步:算法收敛
(3)第三步:稳定定位
(4)【原理】Odometry Localization和AMCL Map Localization比较
(7)amcl全局定位失败的解决办法(工程经验)
方法一:在机器人运行时处理
(1)调用global_localization (std_srvs/Empty)服务 通过调用该服务将初始化全局定位,将所有的粒子重新打散随机的分散在地图的空闲地方,可以通过以下命令来调用该服务,当调用后可以发现所有的粒子被重新打散随机分布在地图上,然后使用键盘遥控机器人旋转,这样可以自动重新对机器人进行定位 rosservice call /global_localization “{}”
(2)调用request_nomotion_update (std_srvs/Empty)服务 该服务是手动的来更新粒子并发布新的粒子,【防盗标记–盒子君hzj】可以使用如下命令来调用服务执行更新粒子的操作,该服务一般需要多次调用才能逐渐看到粒子收敛的效果 rosservice call /request_nomotion_update “{}”
(3)清理代价地图 rosservice call / move_base / clear_costmaps“{}”
(4)机器人再进行旋转重定位
方法二:在机器人停止时处理
(1)运行rosparam dump amcl.yaml /amcl/ (2)修改amcl.yaml文件 将参数"initial_pose_x"、“initial_pose_y”、“initia;_pose_a”注释掉。 (3)重新启动机器人 . .