地图保存
首先,启动相应的仿真环境
切换到工作空间下,输入如下命令
roslaunch urdf_gazebo demo04_control.launch
显示如下
gmapping 是ROS开源社区中较为常用且比较成熟的SLAM算法之一,gmapping可以根据移动机器人里程计数据和激光雷达数据来绘制二维的栅格地图,gmapping 功能包中的核心节点是:slam_gmapping,相关内容链接
输入命令进行地图的绘制,可通过键盘控制小车,也可以通过自主导航建图
roslaunch nav_demo nav02_slam.launch
途中相应的配置map,消息类型是/map
通过键盘控制来实现建静态地图,(因场地是固定的不需要考虑突入起来的其他障碍物)
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
通过按相应的键,控制小车,建好完整的静态地图,如下
第二步
对建好的地图进行保存:map_server使用之地图保存节点(map_saver)
再次打开一个终端:
输入命令
roslaunch nav_demo nav02_nav_save.launch
出现complete,代表保存成功,保存的路径在nav02_nav_save.launch里
找到相应的位置,在目录下找到pgm,打开
yaml保存的是地图的元数据信息,用于描述图片,内容格式
自身定位
AMCL(adaptive Monte Carlo Localization) 是用于2D移动机器人的概率定位系统,它实现了自适应(或KLD采样)蒙特卡洛定位方法,可以根据已有地图使用粒子滤波器推算机器人位置
amcl定位: 可以提供 /map_frame 、/odom_frame 与 /base_frame 之间的坐标变换
相关的内容已在amcl已经被集成到了navigation包
我用的是用于差分移动机器人的,内容如下(针对不同的根坐标系,需更改名称)
<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="basefoot"/><!-- 添加机器人基坐标系 -->
<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>
导航实现:
move_base 功能包提供了基于动作(action)的路径规划实现,move_base 可以根据给定的目标点,控制机器人底盘运动至目标位置,并且在运动过程中会连续反馈机器人自身的姿态与目标点的状态信息
机器人导航(尤其是路径规划模块)是依赖于地图的,地图在SLAM时已经有所介绍了,ROS中的地图其实就是一张图片,这张图片有宽度、高度、分辨率等元数据,在图片中使用灰度值来表示障碍物存在的概率。不过SLAM构建的地图在导航中是不可以直接使用的,因为:
- SLAM构建的地图是静态地图,而导航过程中,障碍物信息是可变的,可能障碍物被移走了,也可能添加了新的障碍物,导航中需要时时的获取障碍物信息;
- 在靠近障碍物边缘时,虽然此处是空闲区域,但是机器人在进入该区域后可能由于其他一些因素,比如:惯性、或者不规则形体的机器人转弯时可能会与障碍物产生碰撞,安全起见,最好在地图的障碍物边缘设置警戒区,尽量禁止机器人进入...
所以,静态地图无法直接应用于导航,其基础之上需要添加一些辅助信息的地图,比如时时获取的障碍物数据,基于静态地图添加的膨胀区等数据。
代价地图有两张:global_costmap(全局代价地图) 和 local_costmap(本地代价地图),前者用于全局路径规划,后者用于本地路径规划。
两张代价地图都可以多层叠加,一般有以下层级:
-
Static Map Layer:静态地图层,SLAM构建的静态地图。
-
Obstacle Map Layer:障碍地图层,传感器感知的障碍物信息。
-
Inflation Layer:膨胀层,在以上两层地图上进行膨胀(向外扩张),以避免机器人的外壳会撞上障碍物。
-
Other Layers:自定义costmap。
路径规划算法在move_base功能包的move_base节点中已经封装完毕了,但是还不可以直接调用,因为算法虽然已经封装了,但是该功能包面向的是各种类型支持ROS的机器人,不同类型机器人可能大小尺寸不同,传感器不同,速度不同,应用场景不同....最后可能会导致不同的路径规划结果,那么在调用路径规划节点之前,我们还需要配置机器人参数
在相应的yaml文件中修改参数
结合以上的launch 集成到一个launch文件
第一个是读取地图的数据以/map话题发布
第二个是自身定位
第三个是根据全局代价地图与本地代价地图,全局路径规划与本地路径规划
实操实现
1.先启动 Gazebo 仿真环境;
roslaunch urdf_gazebo demo04_control.launch
2.启动导航相关的 launch 文件;
roslaunch nav_demo nav05_path_amcl.launch
3全局代价地图与本地代价地图组件配置如下:
有关算法:
导航是根据坐标的相对关系转换成速度,发布速度消息给小车,不理解