move_base分析(二)导航过程
  1. 在我的程序里,从Service的客户端(比如网页端)选择一个目标点后,服务端获得目标的位姿,传递给需要的线程.
  1. 初始化一个Action的客户端SimpleActionClient的指针g_ac_ptr:
1
2
3
4
actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction>* g_ac_ptr=NULL;
// 初始化move_base ActionClient
actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> ac("move_base",true); // action名称为move_base
g_ac_ptr = &ac;
  1. 发送目标:
1
2
3
4
5
6
7
move_base_msgs::MoveBaseGoal goal;

goal.target_pose.header.frame_id = "map";
goal.target_pose.header.stamp = ros::Time::now();
goal.target_pose.pose = g_request.pose; // 服务端获得目标的位姿

g_ac_ptr->sendGoal(goal);

sendGoal会将目标点发送到move_base节点进行处理,进而会发布话题move_base/goal,消息类型为move_base_msgs/MoveBaseActionGoal,用于存储导航的目标位置数据

我没有用到/move_base_simple/goal话题,其实平时应该用这个,比如:

1
2
rostopic pub /move_base_simple/goal geometry_msgs/PoseStamped \
'{ header: { frame_id: "base_link" }, pose: { position: { x: 1.0, y: 0, z: 0 }, orientation: { x: 0, y: 0, z: 0, w: 1 } } }'

  1. Action的服务端在MoveBase的构造函数:
1
2
3
4
5
// 回调函数是 MoveBase::executeCb
as_ = new MoveBaseActionServer(ros::NodeHandle(), "move_base", boost::bind(&MoveBase::executeCb, this, _1), false);
......
//we're all set up now so we can start the action server
as_->start();

MoveBase::executeCb函数在move_base693行,过程太复杂,步骤大致如下:

  • 验证目标位姿的欧拉角是否合理
  • 目标位姿转换为全局frame中的位姿
1
2
3
4
5
6
//we have a goal so start the planner
boost::unique_lock<boost::recursive_mutex> lock(planner_mutex_);
planner_goal_ = goal;
runPlanner_ = true;
planner_cond_.notify_one();
lock.unlock();
  • 发布话题move_base/current_goal,与/move_base/goal的target_pose部分只有seq的不同

调用executeCycle
进行local plan,发布cmd_vel的topic,根据小车处于的状态,进行相应的实现(会进行plan,control,clear obstacle)

1
2
3
4
5
6
7
8
9
10
11
12
enum MoveBaseState {
PLANNING,
CONTROLLING,
CLEARING
};

enum RecoveryTrigger
{
PLANNING_R,
CONTROLLING_R,
OSCILLATION_R
};

DWAPlannerROS和TrajectoryPlannerROS都继承了 nav_core::BaseLocalPlanner

1
2
3
4
5
6
DWAPlannerROS::computeVelocityCommands
dwaComputeVelocityCommands(current_pose_, cmd_vel);

DWAPlannerROS::publishGlobalPlan

base_local_planner::publishPlan(path, g_plan_pub_);

MoveBase::executeCycle调用了DWAPlannerROS::computeVelocityCommands