146 const geometry_msgs::msg::Pose & pose,
double r,
double g,
double b)
148 double phi = tf2::getYaw(pose.orientation);
150 visualization_msgs::msg::Marker marker;
151 marker.header.frame_id = this->
costmap_ros_->getGlobalFrameID();
152 marker.header.stamp =
nh_->now();
153 marker.ns =
"my_namespace2";
155 marker.type = visualization_msgs::msg::Marker::ARROW;
156 marker.action = visualization_msgs::msg::Marker::ADD;
157 marker.scale.x = 0.1;
158 marker.scale.y = 0.3;
159 marker.scale.z = 0.1;
160 marker.color.a = 1.0;
166 marker.lifetime = rclcpp::Duration(0s);
168 geometry_msgs::msg::Point start, end;
169 start.x = pose.position.x;
170 start.y = pose.position.y;
172 end.x = pose.position.x + 0.5 * cos(phi);
173 end.y = pose.position.y + 0.5 * sin(phi);
175 marker.points.push_back(start);
176 marker.points.push_back(end);
178 visualization_msgs::msg::MarkerArray ma;
179 ma.markers.push_back(marker);
189 const geometry_msgs::msg::PoseStamped & start,
const geometry_msgs::msg::PoseStamped & ,
190 std::vector<geometry_msgs::msg::PoseStamped> & plan)
196 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"[UndoPathGlobalPlanner] Transforming forward path");
197 nav_msgs::msg::Path transformedPlan;
201 geometry_msgs::msg::PoseStamped transformedPose;
202 p.header.stamp =
nh_->now();
203 transformedPose.header.stamp =
nh_->now();
204 transformedPose.header.frame_id =
costmap_ros_->getGlobalFrameID();
205 nav_2d_utils::transformPose(
tf_,
costmap_ros_->getGlobalFrameID(), p, transformedPose, ttol);
206 transformedPlan.poses.push_back(transformedPose);
212 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"[UndoPathGlobalPlanner] finding goal closest point");
216 double linear_mindist = std::numeric_limits<double>::max();
217 int mindistindex = -1;
218 double startPoseAngle = tf2::getYaw(start.pose.orientation);
219 geometry_msgs::msg::Pose startPositionProjected;
225 for (
auto & p : transformedPlan.poses )
227 geometry_msgs::msg::PoseStamped pose = p;
228 pose.header.frame_id =
costmap_ros_->getGlobalFrameID();
230 double dx = pose.pose.position.x - start.pose.position.x;
231 double dy = pose.pose.position.y - start.pose.position.y;
233 double dist = sqrt(dx * dx + dy * dy);
234 double angleOrientation = tf2::getYaw(pose.pose.orientation);
235 double angleError = fabs(angles::shortest_angular_distance(angleOrientation, startPoseAngle));
236 if (dist <= linear_mindist)
238 mindistindex = reverseIndex;
239 linear_mindist = dist;
240 startPositionProjected = pose.pose;
243 nh_->get_logger(),
"[UndoPathGlobalPlanner] initial start point search, NEWBEST_LINEAR= "
244 << reverseIndex <<
". error, linear: " << linear_mindist
245 <<
", angular: " << angleError);
250 nh_->get_logger(),
"[UndoPathGlobalPlanner] initial start point search, skipped= "
251 << reverseIndex <<
". best linear error: " << linear_mindist
252 <<
". current error, linear: " << dist <<
" angular: " << angleError);
258 double const ERROR_DISTANCE_PURE_SPINNING_FACTOR = 1.5;
263 RCLCPP_INFO(
nh_->get_logger(),
"[UndoPathGlobalPlanner] second angular pass");
264 double angularMinDist = std::numeric_limits<double>::max();
266 if (mindistindex >= (
int)transformedPlan.poses.size())
268 transformedPlan.poses.size() -
271 if (transformedPlan.poses.size() == 0)
273 RCLCPP_WARN_STREAM(
nh_->get_logger(),
"[UndoPathGlobalPlanner] Warning possible bug");
277 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"[UndoPathGlobalPlanner] second pass loop");
278 for (
int i = mindistindex; i >= 0; i--)
283 nh_->get_logger(),
"[UndoPathGlobalPlanner] " << i <<
"/" << transformedPlan.poses.size());
284 auto index = (int)transformedPlan.poses.size() - i - 1;
285 if (index < 0 || (
size_t)index >= transformedPlan.poses.size())
289 "[UndoPathGlobalPlanner] this should not happen. Check implementation.");
292 geometry_msgs::msg::PoseStamped pose =
293 transformedPlan.poses[transformedPlan.poses.size() - i - 1];
295 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"[UndoPathGlobalPlanner] global frame");
296 pose.header.frame_id =
costmap_ros_->getGlobalFrameID();
298 double dx = pose.pose.position.x - start.pose.position.x;
299 double dy = pose.pose.position.y - start.pose.position.y;
301 double dist = sqrt(dx * dx + dy * dy);
302 if (dist <= linear_mindist * ERROR_DISTANCE_PURE_SPINNING_FACTOR)
304 double angleOrientation = tf2::getYaw(pose.pose.orientation);
306 fabs(angles::shortest_angular_distance(angleOrientation, startPoseAngle));
307 if (angleError < angularMinDist)
309 angularMinDist = angleError;
313 "[UndoPathGlobalPlanner] initial start point search (angular update), NEWBEST_ANGULAR= "
314 << i <<
". error, linear: " << dist <<
"(" << linear_mindist <<
")"
315 <<
", angular: " << angleError <<
"(" << angularMinDist <<
")");
321 "[UndoPathGlobalPlanner] initial start point search (angular update), skipped= "
322 << i <<
". error, linear: " << dist <<
"(" << linear_mindist <<
")"
323 <<
", angular: " << angleError <<
"(" << angularMinDist <<
")");
330 "[UndoPathGlobalPlanner] initial start point search (angular update) not in linear "
332 << i <<
" linear error: " << dist <<
"(" << linear_mindist <<
")");
338 if (mindistindex != -1)
342 "[UndoPathGlobalPlanner] Creating the backwards plan from odom tracker path (, "
343 << transformedPlan.poses.size() <<
") poses");
346 nh_->get_logger(),
"[UndoPathGlobalPlanner] closer point to goal i="
347 << mindistindex <<
" (linear min dist " << linear_mindist <<
")");
361 const double SAME_POSITION_PRUNE_DISTANCE = 0.02;
362 const auto & goalPosition = transformedPlan.poses.front().pose.position;
363 for (
int i = (
int)transformedPlan.poses.size() - 1 - mindistindex; i >= 0; i--)
365 auto & pose = transformedPlan.poses[i];
369 double gdx = pose.pose.position.x - goalPosition.x;
370 double gdy = pose.pose.position.y - goalPosition.y;
371 if (sqrt(gdx * gdx + gdy * gdy) < SAME_POSITION_PRUNE_DISTANCE)
378 rclcpp::Time t(pose.header.stamp);
382 "[UndoPathGlobalPlanner] adding to plan i = " << i <<
" stamp:" << t.seconds());
383 plan.push_back(pose);
386 nh_->get_logger(),
"[UndoPathGlobalPlanner] refined plan has " << plan.size() <<
" points");
391 nh_->get_logger(),
"[UndoPathGlobalPlanner ] undo global plan size: " << plan.size());
401 const geometry_msgs::msg::PoseStamped & start,
const geometry_msgs::msg::PoseStamped & goal,
402 std::function<
bool()> )
406 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"[UndoPathGlobalPlanner] Undo global plan start ");
407 nav_msgs::msg::Path planMsg;
408 std::vector<geometry_msgs::msg::PoseStamped> & plan = planMsg.poses;
412 "[UndoPathGlobalPlanner] last forward path msg size: " <<
lastForwardPathMsg_.poses.size());
418 "[UndoPathGlobalPlanner] no forward path received yet (odom_tracker_path), returning "
424 nh_->get_logger(),
"[UndoPathGlobalPlanner] last forward path frame id: "
427 nh_->get_logger(),
"[UndoPathGlobalPlanner] start pose frame id: " << start.header.frame_id);
429 nh_->get_logger(),
"[UndoPathGlobalPlanner] goal pose frame id: " << goal.header.frame_id);
432 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"[UndoPathGlobalPlanner] Inputs accommodation");
433 geometry_msgs::msg::PoseStamped transformedStart, transformedGoal;
437 geometry_msgs::msg::PoseStamped pstart = start;
438 pstart.header.stamp =
nh_->now();
439 nav_2d_utils::transformPose(
440 tf_,
costmap_ros_->getGlobalFrameID(), pstart, transformedStart, ttol);
441 transformedStart.header.frame_id =
costmap_ros_->getGlobalFrameID();
444 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"[UndoPathGlobalPlanner] Forced goal");
447 forcedGoal.header.stamp =
nh_->now();
448 nav_2d_utils::transformPose(
449 tf_,
costmap_ros_->getGlobalFrameID(), forcedGoal, transformedGoal, ttol);
450 transformedGoal.header.frame_id =
costmap_ros_->getGlobalFrameID();
454 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"[UndoPathGlobalPlanner] Creating undo plan");
456 planMsg.header.frame_id = this->
costmap_ros_->getGlobalFrameID();
458 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"[UndoPathGlobalPlanner] publishing goal markers");
462 bool acceptedGlobalPlan =
true;
463 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"[UndoPathGlobalPlanner] valid plan checking");
466 for (
auto & p : plan)
469 costmap2d->worldToMap(p.pose.position.x, p.pose.position.y, mx, my);
470 auto cost = costmap2d->getCost(mx, my);
472 if (cost >= nav2_costmap_2d::INSCRIBED_INFLATED_OBSTACLE)
474 acceptedGlobalPlan =
false;
481 nh_->get_logger(),
"[UndoPathGlobalPlanner] plan publishing. size: " << plan.size());
483 if (!acceptedGlobalPlan)
487 "[UndoPathGlobalPlanner] not accepted global plan because of possible collision");
491 nh_->get_logger(),
"[UndoPathGlobalPlanner] plan publishing. size: " << planMsg.poses.size());