44 #include <boost/algorithm/string.hpp> 47 #include <mbf_msgs/ExePathResult.h> 52 #include "g2o/core/sparse_optimizer.h" 53 #include "g2o/core/block_solver.h" 54 #include "g2o/core/factory.h" 55 #include "g2o/core/optimization_algorithm_gauss_newton.h" 56 #include "g2o/core/optimization_algorithm_levenberg.h" 57 #include "g2o/solvers/csparse/linear_solver_csparse.h" 58 #include "g2o/solvers/cholmod/linear_solver_cholmod.h" 70 costmap_converter_loader_(
"costmap_converter",
"costmap_converter::BaseCostmapToPolygons"),
71 dynamic_recfg_(NULL), custom_via_points_active_(false), goal_reached_(false), no_infeasible_plans_(0),
72 last_preferred_rotdir_(
RotType::
none), initialized_(false)
87 planner_->updateRobotModel(robot_model);
115 ROS_INFO(
"Parallel planning in distinctive topologies enabled.");
120 ROS_INFO(
"Parallel planning in distinctive topologies disabled.");
128 costmap_model_ = boost::make_shared<base_local_planner::CostmapModel>(*costmap_);
142 boost::replace_all(converter_name,
"::",
"/");
152 ROS_WARN(
"The specified costmap converter plugin cannot be loaded. All occupied costmap cells are treaten as point obstacles. Error message: %s", ex.what());
157 ROS_INFO(
"No costmap conversion plugin specified. All occupied costmap cells are treaten as point obstacles.");
168 dynamic_recfg_ = boost::make_shared< dynamic_reconfigure::Server<TebLocalPlannerReconfigureConfig> >(nh);
183 double controller_frequency = 5;
184 nh_move_base.
param(
"controller_frequency", controller_frequency, controller_frequency);
190 ROS_DEBUG(
"teb_local_planner plugin initialized.");
194 ROS_WARN(
"teb_local_planner has already been initialized, doing nothing.");
205 ROS_ERROR(
"teb_local_planner has not been initialized, please call initialize() before using this planner");
225 std::string dummy_message;
226 geometry_msgs::PoseStamped dummy_pose;
227 geometry_msgs::TwistStamped dummy_velocity, cmd_vel_stamped;
229 cmd_vel = cmd_vel_stamped.twist;
230 return outcome == mbf_msgs::ExePathResult::SUCCESS;
234 const geometry_msgs::TwistStamped& velocity,
235 geometry_msgs::TwistStamped &cmd_vel,
236 std::string &message)
241 ROS_ERROR(
"teb_local_planner has not been initialized, please call initialize() before using this planner");
242 message =
"teb_local_planner has not been initialized";
243 return mbf_msgs::ExePathResult::NOT_INITIALIZED;
246 static uint32_t seq = 0;
247 cmd_vel.header.seq = seq++;
250 cmd_vel.twist.linear.x = cmd_vel.twist.linear.y = cmd_vel.twist.angular.z = 0;
254 geometry_msgs::PoseStamped robot_pose;
259 geometry_msgs::PoseStamped robot_vel_tf;
261 robot_vel_.linear.x = robot_vel_tf.pose.position.x;
262 robot_vel_.linear.y = robot_vel_tf.pose.position.y;
269 std::vector<geometry_msgs::PoseStamped> transformed_plan;
271 geometry_msgs::TransformStamped tf_plan_to_global;
273 transformed_plan, &goal_idx, &tf_plan_to_global))
275 ROS_WARN(
"Could not transform the global plan to the frame of the controller");
276 message =
"Could not transform the global plan to the frame of the controller";
277 return mbf_msgs::ExePathResult::INTERNAL_ERROR;
284 nav_msgs::Odometry base_odom;
288 geometry_msgs::PoseStamped global_goal;
290 double dx = global_goal.pose.position.x -
robot_pose_.
x();
291 double dy = global_goal.pose.position.y -
robot_pose_.
y();
300 return mbf_msgs::ExePathResult::SUCCESS;
308 if (transformed_plan.empty())
310 ROS_WARN(
"Transformed plan is empty. Cannot determine a local plan.");
311 message =
"Transformed plan is empty";
312 return mbf_msgs::ExePathResult::INVALID_PATH;
316 robot_goal_.
x() = transformed_plan.back().pose.position.x;
317 robot_goal_.
y() = transformed_plan.back().pose.position.y;
325 tf2::convert(q, transformed_plan.back().pose.orientation);
333 if (transformed_plan.size()==1)
335 transformed_plan.insert(transformed_plan.begin(), geometry_msgs::PoseStamped());
337 transformed_plan.front() = robot_pose;
361 ROS_WARN(
"teb_local_planner was not able to obtain a local plan for the current setting.");
366 message =
"teb_local_planner was not able to obtain a local plan";
367 return mbf_msgs::ExePathResult::NO_VALID_CMD;
373 cmd_vel.twist.linear.x = cmd_vel.twist.linear.y = cmd_vel.twist.angular.z = 0;
377 ROS_WARN_THROTTLE(1.0,
"TebLocalPlannerROS: the trajectory has diverged. Resetting planner...");
382 return mbf_msgs::ExePathResult::NO_VALID_CMD;
396 cmd_vel.twist.linear.x = cmd_vel.twist.linear.y = cmd_vel.twist.angular.z = 0;
400 ROS_WARN(
"TebLocalPlannerROS: trajectory is not feasible. Resetting planner...");
405 message =
"teb_local_planner trajectory is not feasible";
406 return mbf_msgs::ExePathResult::NO_VALID_CMD;
414 ROS_WARN(
"TebLocalPlannerROS: velocity command invalid. Resetting planner...");
418 message =
"teb_local_planner velocity command invalid";
419 return mbf_msgs::ExePathResult::NO_VALID_CMD;
423 saturateVelocity(cmd_vel.twist.linear.x, cmd_vel.twist.linear.y, cmd_vel.twist.angular.z,
434 if (!std::isfinite(cmd_vel.twist.angular.z))
436 cmd_vel.twist.linear.x = cmd_vel.twist.linear.y = cmd_vel.twist.angular.z = 0;
439 ROS_WARN(
"TebLocalPlannerROS: Resulting steering angle is not finite. Resetting planner...");
442 message =
"teb_local_planner steering angle is not finite";
443 return mbf_msgs::ExePathResult::NO_VALID_CMD;
458 return mbf_msgs::ExePathResult::SUCCESS;
513 for (std::size_t i=0; i<obstacles->obstacles.size(); ++i)
515 const costmap_converter::ObstacleMsg* obstacle = &obstacles->obstacles.at(i);
516 const geometry_msgs::Polygon* polygon = &obstacle->polygon;
518 if (polygon->points.size()==1 && obstacle->radius > 0)
522 else if (polygon->points.size()==1)
526 else if (polygon->points.size()==2)
529 polygon->points[1].x, polygon->points[1].y )));
531 else if (polygon->points.size()>2)
534 for (std::size_t j=0; j<polygon->points.size(); ++j)
536 polyobst->
pushBackVertex(polygon->points[j].x, polygon->points[j].y);
544 obstacles_.back()->setCentroidVelocity(obstacles->obstacles[i].velocities, obstacles->obstacles[i].orientation);
557 Eigen::Affine3d obstacle_to_map_eig;
568 obstacle_to_map_eig.setIdentity();
596 (obstacle_to_map_eig *
line_end).head(2) )));
600 ROS_WARN(
"Invalid custom obstacle received. List of polygon vertices is empty. Skipping...");
628 if (min_separation<=0)
631 std::size_t prev_idx = 0;
632 for (std::size_t i=1; i < transformed_plan.size(); ++i)
635 if (
distance_points2d( transformed_plan[prev_idx].pose.position, transformed_plan[i].pose.position ) < min_separation)
639 via_points_.push_back( Eigen::Vector2d( transformed_plan[i].pose.position.x, transformed_plan[i].pose.position.y ) );
656 if (global_plan.empty())
662 geometry_msgs::TransformStamped global_to_plan_transform = tf.
lookupTransform(global_plan.front().header.frame_id, global_pose.header.frame_id,
ros::Time(0));
663 geometry_msgs::PoseStamped robot;
666 double dist_thresh_sq = dist_behind_robot*dist_behind_robot;
669 std::vector<geometry_msgs::PoseStamped>::iterator it = global_plan.begin();
670 std::vector<geometry_msgs::PoseStamped>::iterator erase_end = it;
671 while (it != global_plan.end())
673 double dx = robot.pose.position.x - it->pose.position.x;
674 double dy = robot.pose.position.y - it->pose.position.y;
675 double dist_sq = dx * dx + dy * dy;
676 if (dist_sq < dist_thresh_sq)
683 if (erase_end == global_plan.end())
686 if (erase_end != global_plan.begin())
687 global_plan.erase(global_plan.begin(), erase_end);
691 ROS_DEBUG(
"Cannot prune path since no transform is available: %s\n", ex.what());
699 const geometry_msgs::PoseStamped& global_pose,
const costmap_2d::Costmap2D& costmap,
const std::string& global_frame,
double max_plan_length,
700 std::vector<geometry_msgs::PoseStamped>& transformed_plan,
int* current_goal_idx, geometry_msgs::TransformStamped* tf_plan_to_global)
const 704 const geometry_msgs::PoseStamped& plan_pose = global_plan[0];
706 transformed_plan.clear();
710 if (global_plan.empty())
712 ROS_ERROR(
"Received plan with zero length");
713 *current_goal_idx = 0;
718 geometry_msgs::TransformStamped plan_to_global_transform = tf.
lookupTransform(global_frame,
ros::Time(), plan_pose.header.frame_id, plan_pose.header.stamp,
722 geometry_msgs::PoseStamped robot_pose;
723 tf.
transform(global_pose, robot_pose, plan_pose.header.frame_id);
728 dist_threshold *= 0.85;
733 double sq_dist_threshold = dist_threshold * dist_threshold;
734 double sq_dist = 1e10;
737 bool robot_reached =
false;
738 for(
int j=0; j < (int)global_plan.size(); ++j)
740 double x_diff = robot_pose.pose.position.x - global_plan[j].pose.position.x;
741 double y_diff = robot_pose.pose.position.y - global_plan[j].pose.position.y;
742 double new_sq_dist = x_diff * x_diff + y_diff * y_diff;
744 if (robot_reached && new_sq_dist > sq_dist)
747 if (new_sq_dist < sq_dist)
749 sq_dist = new_sq_dist;
752 robot_reached =
true;
756 geometry_msgs::PoseStamped newer_pose;
758 double plan_length = 0;
761 while(i < (
int)global_plan.size() && sq_dist <= sq_dist_threshold && (max_plan_length<=0 || plan_length <= max_plan_length))
763 const geometry_msgs::PoseStamped& pose = global_plan[i];
766 transformed_plan.push_back(newer_pose);
768 double x_diff = robot_pose.pose.position.x - global_plan[i].pose.position.x;
769 double y_diff = robot_pose.pose.position.y - global_plan[i].pose.position.y;
770 sq_dist = x_diff * x_diff + y_diff * y_diff;
773 if (i>0 && max_plan_length>0)
774 plan_length +=
distance_points2d(global_plan[i-1].pose.position, global_plan[i].pose.position);
781 if (transformed_plan.empty())
785 transformed_plan.push_back(newer_pose);
788 if (current_goal_idx) *current_goal_idx = int(global_plan.size())-1;
793 if (current_goal_idx) *current_goal_idx = i-1;
797 if (tf_plan_to_global) *tf_plan_to_global = plan_to_global_transform;
801 ROS_ERROR(
"No Transform available Error: %s\n", ex.what());
806 ROS_ERROR(
"Connectivity Error: %s\n", ex.what());
811 ROS_ERROR(
"Extrapolation Error: %s\n", ex.what());
812 if (global_plan.size() > 0)
813 ROS_ERROR(
"Global Frame: %s Plan Frame size %d: %s\n", global_frame.c_str(), (
unsigned int)global_plan.size(), global_plan[0].header.frame_id.c_str());
825 int current_goal_idx,
const geometry_msgs::TransformStamped& tf_plan_to_global,
int moving_average_length)
const 827 int n = (int)global_plan.size();
830 if (current_goal_idx > n-moving_average_length-2)
832 if (current_goal_idx >= n-1)
839 tf2::convert(global_plan.back().pose.orientation, global_orientation);
841 tf2::convert(tf_plan_to_global.transform.rotation, rotation);
848 moving_average_length = std::min(moving_average_length, n-current_goal_idx-1 );
850 std::vector<double> candidates;
851 geometry_msgs::PoseStamped tf_pose_k = local_goal;
852 geometry_msgs::PoseStamped tf_pose_kp1;
854 int range_end = current_goal_idx + moving_average_length;
855 for (
int i = current_goal_idx; i < range_end; ++i)
861 candidates.push_back( std::atan2(tf_pose_kp1.pose.position.y - tf_pose_k.pose.position.y,
862 tf_pose_kp1.pose.position.x - tf_pose_k.pose.position.x ) );
865 tf_pose_k = tf_pose_kp1;
872 double max_vel_x_backwards)
const 874 double ratio_x = 1, ratio_omega = 1, ratio_y = 1;
877 ratio_x = max_vel_x / vx;
880 if (vy > max_vel_y || vy < -max_vel_y)
881 ratio_y = std::abs(max_vel_y / vy);
884 if (omega > max_vel_theta || omega < -max_vel_theta)
885 ratio_omega = std::abs(max_vel_theta / omega);
888 if (max_vel_x_backwards<=0)
890 ROS_WARN_ONCE(
"TebLocalPlannerROS(): Do not choose max_vel_x_backwards to be <=0. Disable backwards driving by increasing the optimization weight for penalyzing backwards driving.");
892 else if (vx < -max_vel_x_backwards)
893 ratio_x = - max_vel_x_backwards / vx;
897 double ratio = std::min(std::min(ratio_x, ratio_y), ratio_omega);
906 omega *= ratio_omega;
909 double vel_linear = std::hypot(vx, vy);
910 if (vel_linear > max_vel_trans)
912 double max_vel_trans_ratio = max_vel_trans / vel_linear;
913 vx *= max_vel_trans_ratio;
914 vy *= max_vel_trans_ratio;
921 if (omega==0 || v==0)
924 double radius = v/omega;
926 if (fabs(radius) < min_turning_radius)
927 radius = double(
g2o::sign(radius)) * min_turning_radius;
929 return std::atan(wheelbase / radius);
935 ROS_WARN_COND(opt_inscribed_radius + min_obst_dist < costmap_inscribed_radius,
936 "The inscribed radius of the footprint specified for TEB optimization (%f) + min_obstacle_dist (%f) are smaller " 937 "than the inscribed radius of the robot's footprint in the costmap parameters (%f, including 'footprint_padding'). " 938 "Infeasible optimziation results might occur frequently!", opt_inscribed_radius, min_obst_dist, costmap_inscribed_radius);
949 goal_idx < (
int)transformed_plan.size()-1 &&
957 int horizon_reduction = goal_idx/2;
962 horizon_reduction /= 2;
968 int new_goal_idx_transformed_plan = int(transformed_plan.size()) - horizon_reduction - 1;
969 goal_idx -= horizon_reduction;
970 if (new_goal_idx_transformed_plan>0 && goal_idx >= 0)
971 transformed_plan.erase(transformed_plan.begin()+new_goal_idx_transformed_plan, transformed_plan.end());
973 goal_idx += horizon_reduction;
980 double max_vel_theta;
995 if (!recently_oscillated)
1002 ROS_WARN(
"TebLocalPlannerROS: possible oscillation (of the robot or its local plan) detected. Activating recovery strategy (prefer current turning direction during optimization).");
1011 ROS_INFO(
"TebLocalPlannerROS: oscillation recovery disabled/expired.");
1025 ROS_INFO_ONCE(
"Via-points received. This message is printed once.");
1028 ROS_WARN(
"Via-points are already obtained from the global plan (global_plan_viapoint_sep>0)." 1029 "Ignoring custom via-points.");
1036 for (
const geometry_msgs::PoseStamped& pose : via_points_msg->poses)
1038 via_points_.emplace_back(pose.pose.position.x, pose.pose.position.y);
1045 std::string model_name;
1046 if (!nh.
getParam(
"footprint_model/type", model_name))
1048 ROS_INFO(
"No robot footprint model specified for trajectory optimization. Using point-shaped model.");
1049 return boost::make_shared<PointRobotFootprint>();
1053 if (model_name.compare(
"point") == 0)
1055 ROS_INFO(
"Footprint model 'point' loaded for trajectory optimization.");
1060 if (model_name.compare(
"circular") == 0)
1064 if (!nh.
getParam(
"footprint_model/radius", radius))
1067 <<
"/footprint_model/radius' does not exist. Using point-model instead.");
1068 return boost::make_shared<PointRobotFootprint>();
1070 ROS_INFO_STREAM(
"Footprint model 'circular' (radius: " << radius <<
"m) loaded for trajectory optimization.");
1071 return boost::make_shared<CircularRobotFootprint>(radius);
1075 if (model_name.compare(
"line") == 0)
1078 if (!nh.
hasParam(
"footprint_model/line_start") || !nh.
hasParam(
"footprint_model/line_end"))
1081 <<
"/footprint_model/line_start' and/or '.../line_end' do not exist. Using point-model instead.");
1082 return boost::make_shared<PointRobotFootprint>();
1086 nh.
getParam(
"footprint_model/line_start", line_start);
1087 nh.
getParam(
"footprint_model/line_end", line_end);
1088 if (line_start.size() != 2 || line_end.size() != 2)
1091 <<
"/footprint_model/line_start' and/or '.../line_end' do not contain x and y coordinates (2D). Using point-model instead.");
1092 return boost::make_shared<PointRobotFootprint>();
1095 ROS_INFO_STREAM(
"Footprint model 'line' (line_start: [" << line_start[0] <<
"," << line_start[1] <<
"]m, line_end: [" 1096 << line_end[0] <<
"," << line_end[1] <<
"]m) loaded for trajectory optimization.");
1097 return boost::make_shared<LineRobotFootprint>(Eigen::Map<const Eigen::Vector2d>(line_start.data()), Eigen::Map<const Eigen::Vector2d>(line_end.data()), config.
obstacles.
min_obstacle_dist);
1101 if (model_name.compare(
"two_circles") == 0)
1104 if (!nh.
hasParam(
"footprint_model/front_offset") || !nh.
hasParam(
"footprint_model/front_radius")
1105 || !nh.
hasParam(
"footprint_model/rear_offset") || !nh.
hasParam(
"footprint_model/rear_radius"))
1108 <<
"/footprint_model/front_offset', '.../front_radius', '.../rear_offset' and '.../rear_radius' do not exist. Using point-model instead.");
1109 return boost::make_shared<PointRobotFootprint>();
1111 double front_offset, front_radius, rear_offset, rear_radius;
1112 nh.
getParam(
"footprint_model/front_offset", front_offset);
1113 nh.
getParam(
"footprint_model/front_radius", front_radius);
1114 nh.
getParam(
"footprint_model/rear_offset", rear_offset);
1115 nh.
getParam(
"footprint_model/rear_radius", rear_radius);
1116 ROS_INFO_STREAM(
"Footprint model 'two_circles' (front_offset: " << front_offset <<
"m, front_radius: " << front_radius
1117 <<
"m, rear_offset: " << rear_offset <<
"m, rear_radius: " << rear_radius <<
"m) loaded for trajectory optimization.");
1118 return boost::make_shared<TwoCirclesRobotFootprint>(front_offset, front_radius, rear_offset, rear_radius);
1122 if (model_name.compare(
"polygon") == 0)
1127 if (!nh.
getParam(
"footprint_model/vertices", footprint_xmlrpc) )
1130 <<
"/footprint_model/vertices' does not exist. Using point-model instead.");
1131 return boost::make_shared<PointRobotFootprint>();
1139 ROS_INFO_STREAM(
"Footprint model 'polygon' loaded for trajectory optimization.");
1140 return boost::make_shared<PolygonRobotFootprint>(polygon);
1142 catch(
const std::exception& ex)
1144 ROS_ERROR_STREAM(
"Footprint model 'polygon' cannot be loaded for trajectory optimization: " << ex.what() <<
". Using point-model instead.");
1145 return boost::make_shared<PointRobotFootprint>();
1151 <<
"/footprint_model/vertices' does not define an array of coordinates. Using point-model instead.");
1152 return boost::make_shared<PointRobotFootprint>();
1158 ROS_WARN_STREAM(
"Unknown robot footprint model specified with parameter '" << nh.
getNamespace() <<
"/footprint_model/type'. Using point model instead.");
1159 return boost::make_shared<PointRobotFootprint>();
1169 footprint_xmlrpc.
size() < 3)
1171 ROS_FATAL(
"The footprint must be specified as list of lists on the parameter server, %s was specified as %s",
1172 full_param_name.c_str(), std::string(footprint_xmlrpc).c_str());
1173 throw std::runtime_error(
"The footprint must be specified as list of lists on the parameter server with at least " 1174 "3 points eg: [[x1, y1], [x2, y2], ..., [xn, yn]]");
1180 for (
int i = 0; i < footprint_xmlrpc.
size(); ++i)
1187 ROS_FATAL(
"The footprint (parameter %s) must be specified as list of lists on the parameter server eg: " 1188 "[[x1, y1], [x2, y2], ..., [xn, yn]], but this spec is not of that form.",
1189 full_param_name.c_str());
1190 throw std::runtime_error(
"The footprint must be specified as list of lists on the parameter server eg: " 1191 "[[x1, y1], [x2, y2], ..., [xn, yn]], but this spec is not of that form");
1197 footprint.push_back(pt);
1208 std::string& value_string = value;
1209 ROS_FATAL(
"Values in the footprint specification (param %s) must be numbers. Found value %s.",
1210 full_param_name.c_str(), value_string.c_str());
1211 throw std::runtime_error(
"Values in the footprint specification must be numbers");
bool include_costmap_obstacles
Specify whether the obstacles in the costmap should be taken into account directly.
bool cmd_angle_instead_rotvel
Substitute the rotational velocity in the commanded velocity message by the corresponding steering an...
boost::shared_ptr< PlannerInterface > PlannerInterfacePtr
Abbrev. for shared instances of PlannerInterface or it's subclasses.
Implements a 2D circular obstacle (point obstacle plus radius)
boost::shared_ptr< dynamic_reconfigure::Server< TebLocalPlannerReconfigureConfig > > dynamic_recfg_
Dynamic reconfigure server to allow config modifications at runtime.
bool isGoalReached()
Check if the goal pose has been achieved.
std::string map_frame
Global planning frame.
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
unsigned int getSizeInCellsX() const
TebVisualizationPtr visualization_
Instance of the visualization class (local/global plan, obstacles, ...)
TebLocalPlannerROS()
Default constructor of the teb plugin.
double max_vel_y
Maximum strafing velocity of the robot (should be zero for non-holonomic robots!) ...
T & transform(const T &in, T &out, const std::string &target_frame, ros::Duration timeout=ros::Duration(0.0)) const
void finalizePolygon()
Call finalizePolygon after the polygon is created with the help of pushBackVertex() methods...
boost::mutex via_point_mutex_
Mutex that locks the via_points container (multi-threaded)
costmap_converter::ObstacleArrayMsg custom_obstacle_msg_
Copy of the most recent obstacle message.
PoseSE2 robot_goal_
Store current robot goal.
Eigen::Vector2d orientationUnitVec() const
Return the unit vector of the current orientation.
bool initialized_
Keeps track about the correct initialization of this class.
double min_obstacle_dist
Minimum desired separation from obstacles.
bool shrink_horizon_backup
Allows the planner to shrink the horizon temporary (50%) in case of automatically detected issues...
unsigned int getSizeInCellsY() const
#define ROS_INFO_ONCE(...)
Eigen::Vector2d & position()
Access the 2D position part.
double robot_circumscribed_radius
The radius of the circumscribed circle of the robot.
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void updateViaPointsContainer(const std::vector< geometry_msgs::PoseStamped > &transformed_plan, double min_separation)
Update internal via-point container based on the current reference plan.
Config class for the teb_local_planner and its components.
boost::shared_ptr< T > createInstance(const std::string &lookup_name)
boost::shared_ptr< base_local_planner::CostmapModel > costmap_model_
static double getYaw(const Quaternion &bt_q)
bool custom_via_points_active_
Keep track whether valid via-points have been received from via_points_sub_.
double theta_stopped_vel
Below what maximum rotation velocity we consider the robot to be stopped in rotation.
double xy_goal_tolerance
Allowed final euclidean distance to the goal position.
double global_plan_viapoint_sep
Min. separation between each two consecutive via-points extracted from the global plan (if negative: ...
void customViaPointsCB(const nav_msgs::Path::ConstPtr &via_points_msg)
Callback for custom via-points.
pluginlib::ClassLoader< costmap_converter::BaseCostmapToPolygons > costmap_converter_loader_
Load costmap converter plugins at runtime.
std::string getGlobalFrameID()
void getOdom(nav_msgs::Odometry &base_odom)
struct teb_local_planner::TebConfig::Robot robot
Robot related parameters.
std::vector< geometry_msgs::Point > footprint_spec_
Store the footprint of the robot.
int no_infeasible_plans_
Store how many times in a row the planner failed to find a feasible plan.
Local planner that explores alternative homotopy classes, create a plan for each alternative and fina...
double yaw_goal_tolerance
Allowed final orientation error.
bool isOscillating() const
Check if the robot got stucked.
double min_turning_radius
Minimum turning radius of a carlike robot (diff-drive robot: zero);.
FailureDetector failure_detector_
Detect if the robot got stucked.
bool goal_reached_
store whether the goal is reached or not
double & x()
Access the x-coordinate the pose.
void setBufferLength(int length)
Set buffer length (measurement history)
std::vector< Eigen::Vector2d, Eigen::aligned_allocator< Eigen::Vector2d > > Point2dContainer
Abbrev. for a container storing 2d points.
ros::Time time_last_infeasible_plan_
Store at which time stamp the last infeasible plan was detected.
void doTransform(const T &data_in, T &data_out, const geometry_msgs::TransformStamped &transform)
struct teb_local_planner::TebConfig::Trajectory trajectory
Trajectory related parameters.
void updateObstacleContainerWithCostmapConverter()
Update internal obstacle vector based on polygons provided by a costmap_converter plugin...
ros::Subscriber custom_obst_sub_
Subscriber for custom obstacles received via a ObstacleMsg.
Implements a polygon obstacle with an arbitrary number of vertices.
Implements a 2D line obstacle.
void initialize(std::string name, tf2_ros::Buffer *tf, costmap_2d::Costmap2DROS *costmap_ros)
Initializes the teb plugin.
bool stopped(const nav_msgs::Odometry &base_odom, const double &rot_stopped_velocity, const double &trans_stopped_velocity)
int feasibility_check_no_poses
Specify up to which pose on the predicted plan the feasibility should be checked each sampling interv...
double costmap_obstacles_behind_robot_dist
Limit the occupied local costmap obstacles taken into account for planning behind the robot (specify ...
struct teb_local_planner::TebConfig::GoalTolerance goal_tolerance
Goal tolerance related parameters.
bool computeVelocityCommands(geometry_msgs::Twist &cmd_vel)
Given the current position, orientation, and velocity of the robot, compute velocity commands to send...
boost::mutex custom_obst_mutex_
Mutex that locks the obstacle array (multi-threaded)
boost::shared_ptr< Obstacle > ObstaclePtr
Abbrev. for shared obstacle pointers.
std::vector< geometry_msgs::PoseStamped > global_plan_
Store the current global plan.
void update(const geometry_msgs::Twist &twist, double v_max, double v_backwards_max, double omega_max, double v_eps, double omega_eps)
Add a new twist measurement to the internal buffer and compute a new decision.
void reconfigure(TebLocalPlannerReconfigureConfig &cfg)
Reconfigure parameters from the dynamic_reconfigure config. Change parameters dynamically (e...
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
Type const & getType() const
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
void updateObstacleContainerWithCustomObstacles()
Update internal obstacle vector based on custom messages received via subscriber. ...
RotType
Symbols for left/none/right rotations.
costmap_2d::Costmap2DROS * costmap_ros_
Pointer to the costmap ros wrapper, received from the navigation stack.
#define ROS_WARN_THROTTLE(period,...)
void loadRosParamFromNodeHandle(const ros::NodeHandle &nh)
Load parmeters from the ros param server.
RotType last_preferred_rotdir_
Store recent preferred turning direction.
#define ROS_WARN_ONCE(...)
struct teb_local_planner::TebConfig::HomotopyClasses hcp
bool getParam(const std::string &key, std::string &s) const
std::string odom_topic
Topic name of the odometry message, provided by the robot driver or simulator.
~TebLocalPlannerROS()
Destructor of the plugin.
boost::shared_ptr< TebVisualization > TebVisualizationPtr
Abbrev. for shared instances of the TebVisualization.
Implements a 2D point obstacle.
bool pruneGlobalPlan(const tf2_ros::Buffer &tf, const geometry_msgs::PoseStamped &global_pose, std::vector< geometry_msgs::PoseStamped > &global_plan, double dist_behind_robot=1)
Prune global plan such that already passed poses are cut off.
int control_look_ahead_poses
Min angular resolution used during the costmap collision check. If not respected, intermediate sample...
std::string getBaseFrameID()
double trans_stopped_vel
Below what maximum velocity we consider the robot to be stopped in translation.
TebConfig cfg_
Config class that stores and manages all related parameters.
static Point2dContainer makeFootprintFromXMLRPC(XmlRpc::XmlRpcValue &footprint_xmlrpc, const std::string &full_param_name)
Set the footprint from the given XmlRpcValue.
bool enable_homotopy_class_planning
Activate homotopy class planning (Requires much more resources that simple planning, since multiple trajectories are optimized at once).
bool getRobotPose(geometry_msgs::PoseStamped &global_pose) const
geometry_msgs::Twist last_cmd_
Store the last control command generated in computeVelocityCommands()
bool free_goal_vel
Allow the robot's velocity to be nonzero (usally max_vel) for planning purposes.
void pushBackVertex(const Eigen::Ref< const Eigen::Vector2d > &vertex)
Add a vertex to the polygon (edge-point)
double max_vel_theta
Maximum angular velocity of the robot.
static Eigen::Vector2d tfPoseToEigenVector2dTransRot(const tf::Pose &tf_vel)
Transform a tf::Pose type into a Eigen::Vector2d containing the translational and angular velocities...
double oscillation_v_eps
Threshold for the average normalized linear velocity: if oscillation_v_eps and oscillation_omega_eps ...
static double getNumberFromXMLRPC(XmlRpc::XmlRpcValue &value, const std::string &full_param_name)
Get a number from the given XmlRpcValue.
#define ROS_WARN_STREAM(args)
virtual std::string getName(const std::string &lookup_name)
bool hasParam(const std::string &key) const
double oscillation_filter_duration
Filter length/duration [sec] for the detection of oscillations.
double getYaw(const A &a)
double transform_tolerance
double & y()
Access the y-coordinate the pose.
This class implements a pose in the domain SE2: The pose consist of the position x and y and an orie...
double & theta()
Access the orientation part (yaw angle) of the pose.
void configureBackupModes(std::vector< geometry_msgs::PoseStamped > &transformed_plan, int &goal_idx)
PoseSE2 robot_pose_
Store current robot pose.
bool is_footprint_dynamic
base_local_planner::OdometryHelperRos odom_helper_
Provides an interface to receive the current velocity from the robot.
bool use_proportional_saturation
double shrink_horizon_min_duration
Specify minimum duration for the reduced horizon in case an infeasible trajectory is detected...
costmap_2d::Costmap2D * costmap_
Pointer to the 2d costmap (obtained from the costmap ros wrapper)
Implements both nav_core::BaseLocalPlanner and mbf_costmap_core::CostmapController abstract interface...
bool costmap_converter_spin_thread
If true, the costmap converter invokes its callback queue in a different thread.
#define ROS_INFO_STREAM(args)
void customObstacleCB(const costmap_converter::ObstacleArrayMsg::ConstPtr &obst_msg)
Callback for custom obstacles that are not obtained from the costmap.
static const unsigned char LETHAL_OBSTACLE
const std::string & getNamespace() const
std::string robot_base_frame_
Used as the base frame id of the robot.
double average_angles(const std::vector< double > &angles)
Return the average angle of an arbitrary number of given angles [rad].
std::string costmap_converter_plugin
Define a plugin name of the costmap_converter package (costmap cells are converted to points/lines/po...
void saturateVelocity(double &vx, double &vy, double &omega, double max_vel_x, double max_vel_y, double max_vel_trans, double max_vel_theta, double max_vel_x_backwards) const
Saturate the translational and angular velocity to given limits.
tf2_ros::Buffer * tf_
pointer to tf buffer
double estimateLocalGoalOrientation(const std::vector< geometry_msgs::PoseStamped > &global_plan, const geometry_msgs::PoseStamped &local_goal, int current_goal_idx, const geometry_msgs::TransformStamped &tf_plan_to_global, int moving_average_length=3) const
Estimate the orientation of a pose from the global_plan that is treated as a local goal for the local...
void validateFootprints(double opt_inscribed_radius, double costmap_inscribed_radius, double min_obst_dist)
Validate current parameter values of the footprint for optimization, obstacle distance and the costma...
ros::Subscriber via_points_sub_
Subscriber for custom via-points received via a Path msg.
void updateObstacleContainerWithCostmap()
Update internal obstacle vector based on occupied costmap cells.
static RobotFootprintModelPtr getRobotFootprintFromParamServer(const ros::NodeHandle &nh, const TebConfig &config)
Get the current robot footprint/contour model.
#define ROS_WARN_COND(cond,...)
This class optimizes an internal Timed Elastic Band trajectory using the g2o-framework.
#define ROS_INFO_COND(cond,...)
bool global_plan_overwrite_orientation
Overwrite orientation of local subgoals provided by the global planner.
struct teb_local_planner::TebConfig::Recovery recovery
Parameters related to recovery and backup strategies.
double robot_inscribed_radius_
The radius of the inscribed circle of the robot (collision possible)
void convert(const A &a, B &b)
boost::shared_ptr< costmap_converter::BaseCostmapToPolygons > costmap_converter_
Store the current costmap_converter.
double getResolution() const
int costmap_converter_rate
The rate that defines how often the costmap_converter plugin processes the current costmap (the value...
void setOdomTopic(std::string odom_topic)
double global_plan_prune_distance
Distance between robot and via_points of global plan which is used for pruning.
PlannerInterfacePtr planner_
Instance of the underlying optimal planner class.
double max_vel_x_backwards
Maximum translational velocity of the robot for driving backwards.
double convertTransRotVelToSteeringAngle(double v, double omega, double wheelbase, double min_turning_radius=0) const
Convert translational and rotational velocities to a steering angle of a carlike robot.
std::string global_frame_
The frame in which the controller will run.
double oscillation_recovery_min_duration
Minumum duration [sec] for which the recovery mode is activated after an oscillation is detected...
bool complete_global_plan
ros::Time time_last_oscillation_
Store at which time stamp the last oscillation was detected.
void getRobotVel(geometry_msgs::PoseStamped &robot_vel)
ObstContainer obstacles_
Obstacle vector that should be considered during local trajectory optimization.
#define ROS_ERROR_STREAM(args)
double distance_points2d(const P1 &point1, const P2 &point2)
Calculate Euclidean distance between two 2D point datatypes.
std::vector< geometry_msgs::Point > getRobotFootprint()
bool setPlan(const std::vector< geometry_msgs::PoseStamped > &orig_global_plan)
Set the plan that the teb local planner is following.
ViaPointContainer via_points_
Container of via-points that should be considered during local trajectory optimization.
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
double oscillation_omega_eps
Threshold for the average normalized angular velocity: if oscillation_v_eps and oscillation_omega_eps...
double wheelbase
The distance between the drive shaft and steering axle (only required for a carlike robot with 'cmd_a...
void mapToWorld(unsigned int mx, unsigned int my, double &wx, double &wy) const
double max_global_plan_lookahead_dist
Specify maximum length (cumulative Euclidean distances) of the subset of the global plan taken into a...
bool transformGlobalPlan(const tf2_ros::Buffer &tf, const std::vector< geometry_msgs::PoseStamped > &global_plan, const geometry_msgs::PoseStamped &global_pose, const costmap_2d::Costmap2D &costmap, const std::string &global_frame, double max_plan_length, std::vector< geometry_msgs::PoseStamped > &transformed_plan, int *current_goal_idx=NULL, geometry_msgs::TransformStamped *tf_plan_to_global=NULL) const
Transforms the global plan of the robot from the planner frame to the local frame (modified)...
geometry_msgs::Twist robot_vel_
Store current robot translational and angular velocity (vx, vy, omega)
bool oscillation_recovery
Try to detect and resolve oscillations between multiple solutions in the same equivalence class (robo...
struct teb_local_planner::TebConfig::Obstacles obstacles
Obstacle related parameters.
unsigned char getCost(unsigned int mx, unsigned int my) const
double max_vel_trans
Maximum translational velocity of the robot for omni robots, which is different from max_vel_x...
Eigen::Isometry3d transformToEigen(const geometry_msgs::Transform &t)
boost::mutex & configMutex()
Return the internal config mutex.
double max_vel_x
Maximum translational velocity of the robot.
void reconfigureCB(TebLocalPlannerReconfigureConfig &config, uint32_t level)
Callback for the dynamic_reconfigure node.
void calculateMinAndMaxDistances(const std::vector< geometry_msgs::Point > &footprint, double &min_dist, double &max_dist)
std::string name_
For use with the ros nodehandle.