自主导航系列7-DWA
在Movebase主体中,各层地图的更新被启动,Action的回调函数触发全局规划线程,若成功,则将全局规划结果传入局部规划器,循环进行局部规划,得到速度指令,控制机器人前进,直到到达目标。其间,需要判断机器人是否到达终点(若是则规划停止)、机器人是否状态异常如发生震荡行为(若是则进入恢复行为)、机器人是否超时(若是则停止规划发布零速,否则重新规划)等等。
1,costmap
2,move_base的动作服务器
move_base类利用actionlib::SimpleActionServer<move_base_msgs::MoveBaseAction>
给出的接口来实现:给定一个目标,然后控制移动机器人走到目标点的功能。
源码中将其typedef
为MoveBaseActionServer
typedef actionlib::SimpleActionServer<move_base_msgs::MoveBaseAction> MoveBaseActionServer;
as_作为服务器回调executeCb
函数
as_ = new MoveBaseActionServer(ros::NodeHandle(), "move_base", boost::bind(&MoveBase::executeCb, this, _1), false);
3,构造函数MoveBase::MoveBase(tf2_ros::Buffer& tf)
move_base_node
中就只调用了这个构造函数,除了设置as_以外
-
从参数服务器获取一些参数,包括两个规划器名称、代价地图坐标系、规划频率、控制周期等
-
新建planner线程,入口为
MoveBase::planThread
-
订阅
geometry_msgs::PoseStamped
类型的goal
话题,cb为MoveBase::goalCB
,你在rviz中输入的目标点就是通过这个函数来响应的 -
订阅
geometry_msgs::PoseStamped
类型的goal
话题,cb为MoveBase::goalCB
,你在rviz中输入的目标点就是通过这个函数来响应的
4, void executeCb()
这个是movebase这个actionlib服务的回调函数。我们什么时候会用到这个回调呢?当Action Server在move_base_msgs::MoveBaseActionGoal类型的goal话题上收到一个消息,然后将其放到Sample Action Server的待定槽时。
第一次接收到goal时会进入该函数,但如果没有完成任务,尚未退出时,再有接收到goal并不会再新建线程进入一次,而是通过抢断信号的形式通知该函数,所以在处理goal的时候需要经常查看isPreemptRequested函数的返回,看是否有抢占。
该函数流程是
第一次进入后接收goal,判断有效性等,然后开启规划线程得到路径。
然后在while(n.ok())循环中调用executeCycle(goal, global_plan);来控制机器人进行相应跟随。
期间会不断检测是否有新的goal抢占,或者坐标系变换等,如果有则在while循环中重复步骤1的初始化再跟随。
如果有被空抢占(如cancel等)则清除退出如果跟随完成则退出会进行控制周期约束。
参考:撸move_base源码