failure_detector_.update(last_cmd_, cfg_.robot.max_vel_x, cfg_.robot.max_vel_x_backwards, max_vel_theta, cfg_.recovery.oscillation_v_eps, cfg_.recovery.oscillation_omega_eps); bool oscillating = failure_detector_.isOscillating(); // 距离上次振荡过了多久,若小于配置值(10秒),说明最近也振荡了 bool recently_oscillated = (ros::Time::now()-time_last_oscillation_).toSec() < cfg_.recovery.oscillation_recovery_min_duration; // 如果现在是振荡状态 if (oscillating) { if (!recently_oscillated) // 最近的状态不是振荡 { // save current turning direction // 以下其实都是对 last_preferred_rotdir_ 赋值 if (robot_vel_.angular.z > 0) last_preferred_rotdir_ = RotType::left; else last_preferred_rotdir_ = RotType::right; ROS_WARN("TebLocalPlannerROS: possible oscillation (of the robot or its local plan) detected. Activating recovery strategy (prefer current turning direction during optimization) "); } time_last_oscillation_ = ros::Time::now(); // 对 prefer_rotdir_ 赋值,最终影响 AddEdgesPreferRotDir planner_->setPreferredTurningDir(last_preferred_rotdir_); } // 现在和最近都没有振荡 clear recovery behavior elseif (!recently_oscillated && last_preferred_rotdir_ != RotType::none) { last_preferred_rotdir_ = RotType::none; planner_->setPreferredTurningDir(last_preferred_rotdir_); ROS_INFO("TebLocalPlannerROS: oscillation recovery disabled/expired."); } }
但是如果机器人确实stucked,最终会在move_base里Abort
setPreferredTurningDir
设置期望的初始转弯方向 (也就是惩罚相反的方向)。A desired (initial) turning direction might be specified in case the planned trajectory oscillates between two solutions (in the same equivalence class!) with similar cost. 配置参数以调整惩罚的权重,Initial 说明惩罚只适用于trajectory的前几个位姿
voidHomotopyClassPlanner::setPreferredTurningDir(RotType dir) { // set preferred turning dir for all TEBs for (TebOptPlannerContainer::const_iterator it_teb = tebs_.begin(); it_teb != tebs_.end(); ++it_teb) { (*it_teb)->setPreferredTurningDir(dir); } }
voidTebOptimalPlanner::AddEdgesPreferRotDir() { /* roesmann 注释: these edges can result in odd predictions, in particular we can observe a substantional mismatch between open- and closed-loop planning leading to a poor control performance. 目前这个功能只用于振荡恢复,短期使用这个约束不会有重大影响 可能让机器人脱离振荡 */ if (prefer_rotdir_ == RotType::none || cfg_->optim.weight_prefer_rotdir == 0) return; // 必须定义好转向 if (prefer_rotdir_ != RotType::right && prefer_rotdir_ != RotType::left) { ROS_WARN("TebOptimalPlanner::AddEdgesPreferRotDir(): unsupported RotType selected. Skipping edge creation."); return; } // create edge for satisfiying kinematic constraints Eigen::Matrix<double,1,1> information_rotdir; information_rotdir.fill(cfg_->optim.weight_prefer_rotdir); // 目前只使用前三个旋转 for (int i=0; i < teb_.sizePoses()-1 && i < 3; ++i) { EdgePreferRotDir* rotdir_edge = new EdgePreferRotDir; rotdir_edge->setVertex(0, teb_.PoseVertex(i)); rotdir_edge->setVertex(1, teb_.PoseVertex(i+1)); rotdir_edge->setInformation(information_rotdir); if (prefer_rotdir_ == RotType::left) rotdir_edge->preferLeft(); elseif (prefer_rotdir_ == RotType::right) rotdir_edge->preferRight(); optimizer_->addEdge(rotdir_edge); } }
// Set buffer length (measurement history) // length: number of measurements to be kept voidsetBufferLength(int length){ buffer_.set_capacity(length); }