ros::NodeHandle n; ros::Timer timer; bool wait_for_wake = false; // 先不唤醒线程 boost::unique_lock<boost::recursive_mutex> lock(planner_mutex_); while(n.ok() ) { // check if we should run the planner (the mutex is locked) while(wait_for_wake || !runPlanner_){ //if we should not be running the planner then suspend this thread log.debug("[move_base_plan_thread] %s","Planner thread is suspending"); planner_cond_.wait(lock); wait_for_wake = false; } // 开启线程 ros::Time start_time = ros::Time::now(); //time to plan! get a copy of the goal and unlock the mutex geometry_msgs::PoseStamped temp_goal = planner_goal_; lock.unlock(); ROS_DEBUG_NAMED("move_base_plan_thread", "Planning..."); // run planner planner_plan_->clear(); bool gotPlan = n.ok() && makePlan(temp_goal, *planner_plan_); ...... }
if(gotPlan) { ROS_DEBUG_NAMED("move_base_plan_thread","Got Plan with %zu points!", planner_plan_->size()); //pointer swap the plans under mutex (the controller will pull from latest_plan_) std::vector<geometry_msgs::PoseStamped>* temp_plan = planner_plan_; lock.lock(); // 交换变量,赋值给 latest_plan_ planner_plan_ = latest_plan_; latest_plan_ = temp_plan; last_valid_plan_ = ros::Time::now(); planning_retries_ = 0; new_global_plan_ = true; //make sure we only start the controller if we still haven't reached the goal if(runPlanner_) state_ = CONTROLLING; if(planner_frequency_ <= 0) runPlanner_ = false; lock.unlock(); } // 如果没找到路径,而且还在 PLANNING 状态(机器人不动) elseif(state_==PLANNING) { ros::Time attempt_end = last_valid_plan_ + ros::Duration(planner_patience_); //check if make a plan for over time limit or maximum number of retries lock.lock(); // lock是用于这个非原子操作 planning_retries_++; // 如果参数 max_planning_retries还是默认值 -1,那转为uint32_t就是一个很大的数,就是不考虑重试次数 if(runPlanner_ && (ros::Time::now() > attempt_end || planning_retries_ > uint32_t(max_planning_retries_)) ) { // 进入 CLEARING 状态 state_ = CLEARING; runPlanner_ = false; // proper solution for issue #523 publishZeroVelocity(); // 车不准动 recovery_trigger_ = PLANNING_R; } lock.unlock(); } //if can't get new plan, robot will move with last global plan // 其实跟上面的情况一样 elseif(state_ == CONTROLLING) { movebase_log.warn("Robot in controlling, but can't get new global plan "); publishZeroVelocity(); state_ = CLEARING; recovery_trigger_ = PLANNING_R; } //take the mutex for the next iteration lock.lock(); if(planner_frequency_ > 0) { ros::Duration sleep_time = (start_time + ros::Duration(1.0/planner_frequency_)) - ros::Time::now(); if (sleep_time > ros::Duration(0.0) ) { wait_for_wake = true; // wakePlanner的函数只有一句: planner_cond_.notify_one(); timer = n.createTimer(sleep_time, &MoveBase::wakePlanner, this); } }