SMACC2
Loading...
Searching...
No Matches
cl_nav2z::backward_local_planner::BackwardLocalPlanner Class Reference

#include <backward_local_planner.hpp>

Inheritance diagram for cl_nav2z::backward_local_planner::BackwardLocalPlanner:
Inheritance graph
Collaboration diagram for cl_nav2z::backward_local_planner::BackwardLocalPlanner:
Collaboration graph

Public Member Functions

 BackwardLocalPlanner ()
 
virtual ~BackwardLocalPlanner ()
 
void configure (const rclcpp_lifecycle::LifecycleNode::WeakPtr &parent, std::string name, const std::shared_ptr< tf2_ros::Buffer > tf, const std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmap_ros) override
 
void activate () override
 
void deactivate () override
 
void cleanup () override
 
void setPlan (const nav_msgs::msg::Path &path) override
 nav2_core setPlan - Sets the global plan
 
virtual geometry_msgs::msg::TwistStamped computeVelocityCommands (const geometry_msgs::msg::PoseStamped &pose, const geometry_msgs::msg::Twist &velocity, nav2_core::GoalChecker *goal_checker) override
 nav2_core computeVelocityCommands - calculates the best command given the current pose and velocity
 
bool isGoalReached ()
 
virtual void setSpeedLimit (const double &speed_limit, const bool &percentage) override
 

Private Member Functions

void updateParameters ()
 
bool findInitialCarrotGoal (geometry_msgs::msg::PoseStamped &pose)
 
bool updateCarrotGoal (const geometry_msgs::msg::PoseStamped &pose)
 
bool resamplePrecisePlan ()
 
void straightBackwardsAndPureSpinCmd (const geometry_msgs::msg::PoseStamped &pose, double &vetta, double &gamma, double alpha_error, double betta_error, double rho_error)
 
void clearMarkers ()
 
void publishGoalMarker (double x, double y, double phi)
 
void computeCurrentEuclideanAndAngularErrorsToCarrotGoal (const geometry_msgs::msg::PoseStamped &pose, double &dist, double &angular_error)
 
bool checkGoalReached (const geometry_msgs::msg::PoseStamped &pose, double vetta, double gamma, double alpha_error, geometry_msgs::msg::Twist &cmd_vel)
 
bool checkCurrentPoseInGoalRange (const geometry_msgs::msg::PoseStamped &tfpose, const geometry_msgs::msg::Twist &currentTwist, double angle_error, bool &linearGoalReached, nav2_core::GoalChecker *goalChecker)
 
bool resetDivergenceDetection ()
 
bool divergenceDetectionUpdate (const geometry_msgs::msg::PoseStamped &pose)
 
bool checkCarrotHalfPlainConstraint (const geometry_msgs::msg::PoseStamped &pose)
 
void generateTrajectory (const Eigen::Vector3f &pos, const Eigen::Vector3f &vel, float maxdist, float maxangle, float maxtime, float dt, std::vector< Eigen::Vector3f > &outtraj)
 
Eigen::Vector3f computeNewPositions (const Eigen::Vector3f &pos, const Eigen::Vector3f &vel, double dt)
 

Private Attributes

rclcpp_lifecycle::LifecycleNode::SharedPtr nh_
 
std::string name_
 
std::vector< geometry_msgs::msg::PoseStamped > backwardsPlanPath_
 
std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmapRos_
 
std::shared_ptr< tf2_ros::Buffer > tf_
 
std::shared_ptr< rclcpp_lifecycle::LifecyclePublisher< visualization_msgs::msg::MarkerArray > > goalMarkerPublisher_
 
std::shared_ptr< rclcpp_lifecycle::LifecyclePublisher< nav_msgs::msg::Path > > planPub_
 
double k_rho_
 
double k_alpha_
 
double k_betta_
 
double pure_spinning_allowed_betta_error_
 
double linear_mode_rho_error_threshold_
 
const double alpha_offset_ = M_PI
 
const double betta_offset_ = 0
 
double max_linear_x_speed_
 
double max_angular_z_speed_
 
double yaw_goal_tolerance_
 
double xy_goal_tolerance_
 
meter carrot_distance_
 
rad carrot_angular_distance_
 
meter divergenceDetectionLastCarrotLinearDistance_
 
double transform_tolerance_
 
rclcpp::Duration waitingTimeout_
 
rclcpp::Time waitingStamp_
 
bool goalReached_
 
bool initialPureSpinningStage_
 
bool straightBackwardsAndPureSpinningMode_ = false
 
bool enable_obstacle_checking_ = true
 
bool inGoalPureSpinningState_ = false
 
bool waiting_
 
int currentCarrotPoseIndex_
 

Detailed Description

Definition at line 38 of file backward_local_planner.hpp.

Constructor & Destructor Documentation

◆ BackwardLocalPlanner()

cl_nav2z::backward_local_planner::BackwardLocalPlanner::BackwardLocalPlanner ( )

◆ ~BackwardLocalPlanner()

cl_nav2z::backward_local_planner::BackwardLocalPlanner::~BackwardLocalPlanner ( )
virtual

~BackwardLocalPlanner()

Definition at line 53 of file backward_local_planner.cpp.

53{}

Member Function Documentation

◆ activate()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::activate ( )
override

Definition at line 55 of file backward_local_planner.cpp.

56{
57 RCLCPP_INFO_STREAM(nh_->get_logger(), "activating controller BackwardLocalPlanner");
59
60 goalMarkerPublisher_->on_activate();
61 planPub_->on_activate();
62 backwardsPlanPath_.clear();
63}
std::vector< geometry_msgs::msg::PoseStamped > backwardsPlanPath_
std::shared_ptr< rclcpp_lifecycle::LifecyclePublisher< visualization_msgs::msg::MarkerArray > > goalMarkerPublisher_
std::shared_ptr< rclcpp_lifecycle::LifecyclePublisher< nav_msgs::msg::Path > > planPub_

References backwardsPlanPath_, goalMarkerPublisher_, nh_, planPub_, and updateParameters().

Here is the call graph for this function:

◆ checkCarrotHalfPlainConstraint()

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::checkCarrotHalfPlainConstraint ( const geometry_msgs::msg::PoseStamped & pose)
private

Definition at line 384 of file backward_local_planner.cpp.

386{
387 // this function is specially useful when we want to reach the goal with a lot
388 // of precision. We may pass the goal and then the controller enters in some
389 // unstable state. With this, we are able to detect when stop moving.
390
391 // only apply if the carrot is in goal position and also if we are not in a pure spinning behavior v!=0
392
393 auto & carrot_pose = backwardsPlanPath_[currentCarrotPoseIndex_];
394 const geometry_msgs::msg::Point & carrot_point = carrot_pose.pose.position;
395 double yaw = tf2::getYaw(carrot_pose.pose.orientation);
396
397 // direction vector
398 double vx = cos(yaw);
399 double vy = sin(yaw);
400
401 // line implicit equation
402 // ax + by + c = 0
403 double c = -vx * carrot_point.x - vy * carrot_point.y;
404 const double C_OFFSET_METERS = 0.05; // 5 cm
405 double check = vx * tfpose.pose.position.x + vy * tfpose.pose.position.y + c + C_OFFSET_METERS;
406
407 RCLCPP_INFO_STREAM(
408 nh_->get_logger(),
409 "[BackwardLocalPlanner] half plane constraint:" << vx << "*" << carrot_point.x << " + " << vy
410 << "*" << carrot_point.y << " + " << c);
411 RCLCPP_INFO_STREAM(
412 nh_->get_logger(), "[BackwardLocalPlanner] constraint evaluation: "
413 << vx << "*" << tfpose.pose.position.x << " + " << vy << "*"
414 << tfpose.pose.position.y << " + " << c << " = " << check);
415
416 return check < 0;
417}

References backwardsPlanPath_, currentCarrotPoseIndex_, and nh_.

Referenced by computeVelocityCommands().

Here is the caller graph for this function:

◆ checkCurrentPoseInGoalRange()

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::checkCurrentPoseInGoalRange ( const geometry_msgs::msg::PoseStamped & tfpose,
const geometry_msgs::msg::Twist & currentTwist,
double angle_error,
bool & linearGoalReached,
nav2_core::GoalChecker * goalChecker )
private

Definition at line 419 of file backward_local_planner.cpp.

423{
424 auto & finalgoal = backwardsPlanPath_.back();
425 double gdx = finalgoal.pose.position.x - tfpose.pose.position.x;
426 double gdy = finalgoal.pose.position.y - tfpose.pose.position.y;
427 double goaldist = sqrt(gdx * gdx + gdy * gdy);
428
429 auto abs_angle_error = fabs(angle_error);
430 RCLCPP_INFO_STREAM(
431 nh_->get_logger(), "[BackwardLocalPlanner] goal check. linear dist: "
432 << goaldist << "(" << this->xy_goal_tolerance_ << ")" << ", angular dist: "
433 << abs_angle_error << "(" << this->yaw_goal_tolerance_ << ")");
434
435 linearGoalReached = goaldist < this->xy_goal_tolerance_;
436
437 return linearGoalReached && abs_angle_error < this->yaw_goal_tolerance_;
438}

References backwardsPlanPath_, nh_, xy_goal_tolerance_, and yaw_goal_tolerance_.

Referenced by computeVelocityCommands().

Here is the caller graph for this function:

◆ checkGoalReached()

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::checkGoalReached ( const geometry_msgs::msg::PoseStamped & pose,
double vetta,
double gamma,
double alpha_error,
geometry_msgs::msg::Twist & cmd_vel )
private

◆ cleanup()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::cleanup ( )
override

Definition at line 73 of file backward_local_planner.cpp.

74{
75 this->clearMarkers();
76 RCLCPP_WARN_STREAM(nh_->get_logger(), "[BackwardLocalPlanner] cleanup");
77 this->backwardsPlanPath_.clear();
79}

References backwardsPlanPath_, clearMarkers(), currentCarrotPoseIndex_, and nh_.

Here is the call graph for this function:

◆ clearMarkers()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::clearMarkers ( )
private

Definition at line 1124 of file backward_local_planner.cpp.

1125{
1126 visualization_msgs::msg::Marker marker;
1127 marker.header.frame_id = this->costmapRos_->getGlobalFrameID();
1128 marker.header.stamp = nh_->now();
1129
1130 marker.ns = "my_namespace2";
1131 marker.id = 0;
1132 marker.type = visualization_msgs::msg::Marker::ARROW;
1133 marker.action = visualization_msgs::msg::Marker::DELETEALL;
1134
1135 visualization_msgs::msg::MarkerArray ma;
1136 ma.markers.push_back(marker);
1137
1138 goalMarkerPublisher_->publish(ma);
1139}
std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmapRos_

References costmapRos_, goalMarkerPublisher_, and nh_.

Referenced by cleanup(), and deactivate().

Here is the caller graph for this function:

◆ computeCurrentEuclideanAndAngularErrorsToCarrotGoal()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::computeCurrentEuclideanAndAngularErrorsToCarrotGoal ( const geometry_msgs::msg::PoseStamped & tfpose,
double & dist,
double & angular_error )
private

auxiliary functions

Definition at line 244 of file backward_local_planner.cpp.

246{
247 double angle = tf2::getYaw(tfpose.pose.orientation);
248 auto & carrot_pose = backwardsPlanPath_[currentCarrotPoseIndex_];
249 const geometry_msgs::msg::Point & carrot_point = carrot_pose.pose.position;
250
251 tf2::Quaternion carrot_orientation;
252 tf2::convert(carrot_pose.pose.orientation, carrot_orientation);
253 geometry_msgs::msg::Pose currentPoseDebugMsg = tfpose.pose;
254
255 // take error from the current position to the path point
256 double dx = carrot_point.x - tfpose.pose.position.x;
257 double dy = carrot_point.y - tfpose.pose.position.y;
258
259 dist = sqrt(dx * dx + dy * dy);
260
261 double pangle = tf2::getYaw(carrot_orientation);
262 angular_error = fabs(angles::shortest_angular_distance(pangle, angle));
263
264 RCLCPP_INFO_STREAM(
265 nh_->get_logger(), "[BackwardLocalPlanner] Compute carrot errors from current pose. (linear "
266 << dist << ")(angular " << angular_error << ")" << std::endl
267 << "Current carrot pose: " << std::endl
268 << carrot_pose << std::endl
269 << "Current actual pose:" << std::endl
270 << currentPoseDebugMsg);
271}

References backwardsPlanPath_, currentCarrotPoseIndex_, and nh_.

Referenced by divergenceDetectionUpdate(), findInitialCarrotGoal(), and updateCarrotGoal().

Here is the caller graph for this function:

◆ computeNewPositions()

Eigen::Vector3f cl_nav2z::backward_local_planner::BackwardLocalPlanner::computeNewPositions ( const Eigen::Vector3f & pos,
const Eigen::Vector3f & vel,
double dt )
private

Definition at line 1110 of file backward_local_planner.cpp.

1112{
1113 Eigen::Vector3f new_pos = Eigen::Vector3f::Zero();
1114 new_pos[0] = pos[0] + (static_cast<double>(vel[0]) * cos(pos[2]) +
1115 static_cast<double>(vel[1]) * cos(M_PI_2 + pos[2])) *
1116 dt;
1117 new_pos[1] = pos[1] + (static_cast<double>(vel[0]) * sin(pos[2]) +
1118 static_cast<double>(vel[1]) * sin(M_PI_2 + pos[2])) *
1119 dt;
1120 new_pos[2] = pos[2] + vel[2] * dt;
1121 return new_pos;
1122}

Referenced by generateTrajectory().

Here is the caller graph for this function:

◆ computeVelocityCommands()

geometry_msgs::msg::TwistStamped cl_nav2z::backward_local_planner::BackwardLocalPlanner::computeVelocityCommands ( const geometry_msgs::msg::PoseStamped & pose,
const geometry_msgs::msg::Twist & velocity,
nav2_core::GoalChecker * goal_checker )
overridevirtual

nav2_core computeVelocityCommands - calculates the best command given the current pose and velocity

It is presumed that the global plan is already set.

This is mostly a wrapper for the protected computeVelocityCommands function which has additional debugging info.

Parameters
poseCurrent robot pose
velocityCurrent robot velocity
Returns
The best command for the robot to drive

computeVelocityCommands()

Definition at line 466 of file backward_local_planner.cpp.

469{
470 RCLCPP_INFO(
471 nh_->get_logger(),
472 "[BackwardLocalPlanner] ------------------- LOCAL PLANNER LOOP -----------------");
473 this->updateParameters();
474
475 // consistency check
476 if (this->backwardsPlanPath_.size() > 0)
477 {
478 RCLCPP_INFO_STREAM(
479 nh_->get_logger(), "[BackwardLocalPlanner] Current pose frame id: "
480 << backwardsPlanPath_.front().header.frame_id
481 << ", path pose frame id: " << pose.header.frame_id);
482
483 if (backwardsPlanPath_.front().header.frame_id != pose.header.frame_id)
484 {
485 RCLCPP_ERROR_STREAM(nh_->get_logger(), "[BackwardLocalPlanner] Inconsistent frames");
486 }
487 }
488
489 // xy_goal_tolerance and yaw_goal_tolerance are just used for logging proposes and clamping the carrot
490 // goal distance (parameter safety)
491 if (xy_goal_tolerance_ == -1 || yaw_goal_tolerance_ == -1)
492 {
493 geometry_msgs::msg::Pose posetol;
494 geometry_msgs::msg::Twist twistol;
495 if (goal_checker->getTolerances(posetol, twistol))
496 {
497 xy_goal_tolerance_ = posetol.position.x;
498 yaw_goal_tolerance_ = tf2::getYaw(posetol.orientation);
499
500 RCLCPP_INFO_STREAM(
501 nh_->get_logger(), "[BackwardLocalPlanner] xy_goal_tolerance_: "
503 << ", yaw_goal_tolerance_: " << yaw_goal_tolerance_);
504 }
505 else
506 {
507 RCLCPP_INFO_STREAM(
508 nh_->get_logger(), "[BackwardLocalPlanner] could not get tolerances from goal checker");
509 }
510 }
511
512 RCLCPP_INFO(
513 nh_->get_logger(),
514 "[BackwardLocalPlanner] ------------------- LOCAL PLANNER LOOP -----------------");
515
516 geometry_msgs::msg::TwistStamped cmd_vel;
517 RCLCPP_INFO(nh_->get_logger(), "[BackwardLocalPlanner] LOCAL PLANNER LOOP");
518 geometry_msgs::msg::PoseStamped paux;
519 geometry_msgs::msg::PoseStamped tfpose;
520
521 if (!costmapRos_->getRobotPose(tfpose))
522 {
523 RCLCPP_ERROR(
524 nh_->get_logger(),
525 "[BackwardLocalPlanner] missing robot pose, canceling compute Velocity Command");
526 } // it is not working in the pure spinning reel example, maybe the hyperplane check is enough
527 bool divergenceDetected = false;
528
529 bool emergency_stop = false;
530 if (divergenceDetected)
531 {
532 RCLCPP_ERROR(
533 nh_->get_logger(), "[BackwardLocalPlanner] Divergence detected. Sending emergency stop.");
534 emergency_stop = true;
535 }
536
537 bool carrotInLinearGoalRange = updateCarrotGoal(tfpose);
538 RCLCPP_INFO_STREAM(nh_->get_logger(), "[BackwardLocalPlanner] carrot goal created");
539
540 if (emergency_stop)
541 {
542 cmd_vel.twist.linear.x = 0;
543 cmd_vel.twist.angular.z = 0;
544 RCLCPP_INFO_STREAM(
545 nh_->get_logger(), "[BackwardLocalPlanner] emergency stop, exit compute commands");
546 return cmd_vel;
547 }
548
549 // ------ Evaluate the current context ----
550 double rho_error, betta_error, alpha_error;
551
552 // getting carrot goal information
553 tf2::Quaternion q;
554 tf2::convert(tfpose.pose.orientation, q);
555
556 RCLCPP_INFO_STREAM(
557 nh_->get_logger(), "[BackwardLocalPlanner] carrot goal: " << currentCarrotPoseIndex_ << "/"
558 << backwardsPlanPath_.size());
559 const geometry_msgs::msg::PoseStamped & carrotgoalpose =
561 RCLCPP_INFO_STREAM(
562 nh_->get_logger(), "[BackwardLocalPlanner] carrot goal pose current index: "
563 << currentCarrotPoseIndex_ << "/" << backwardsPlanPath_.size() << ": "
564 << carrotgoalpose);
565 const geometry_msgs::msg::Point & carrotGoalPosition = carrotgoalpose.pose.position;
566
567 tf2::Quaternion goalQ;
568 tf2::fromMsg(carrotgoalpose.pose.orientation, goalQ);
569 RCLCPP_INFO_STREAM(nh_->get_logger(), "[BackwardLocalPlanner] -- Control Policy --");
570 // goal orientation (global frame)
571 double betta = tf2::getYaw(goalQ);
572 RCLCPP_INFO_STREAM(nh_->get_logger(), "[BackwardLocalPlanner] goal orientation: " << betta);
573 betta = betta + betta_offset_;
574
575 double dx = carrotGoalPosition.x - tfpose.pose.position.x;
576 double dy = carrotGoalPosition.y - tfpose.pose.position.y;
577
578 // distance error to the targetpoint
579 rho_error = sqrt(dx * dx + dy * dy);
580
581 // heading to goal angle
582 double theta = tf2::getYaw(q);
583 double alpha = atan2(dy, dx);
584 alpha = alpha + alpha_offset_;
585
586 alpha_error = angles::shortest_angular_distance(alpha, theta);
587 betta_error = angles::shortest_angular_distance(betta, theta);
588 //------------- END CONTEXT EVAL ----------
589
590 bool linearGoalReached;
591 bool currentPoseInGoal =
592 checkCurrentPoseInGoalRange(tfpose, velocity, betta_error, linearGoalReached, goal_checker);
593
594 // Make sure the robot is very close to the goal and it is really in the the last goal point.
595 bool carrotInFinalGoalIndex = currentCarrotPoseIndex_ == (int)backwardsPlanPath_.size() - 1;
596
597 // checking if we are really in the end goal pose
598 if (currentPoseInGoal && carrotInFinalGoalIndex)
599 {
600 goalReached_ = true;
601 RCLCPP_INFO_STREAM(
602 nh_->get_logger(),
603 "[BackwardLocalPlanner] GOAL REACHED. Send stop command and skipping trajectory collision: "
604 << cmd_vel.twist);
605 cmd_vel.twist.linear.x = 0;
606 cmd_vel.twist.angular.z = 0;
607 return cmd_vel;
608 }
609 else if (
610 carrotInLinearGoalRange &&
611 linearGoalReached) // checking if we are in the end goal point but with incorrect
612 // orientation
613 {
614 // this means that we are not in the final angular distance, and we may even not be in the last carrot index
615 // (several intermediate angular poses until the last goal pose)
617 }
618
619 // --------------------
620 double vetta, gamma;
622 {
623 // decorated control rule for this mode
625 tfpose, vetta, gamma, alpha_error, betta_error, rho_error);
626 }
627 else // default free navigation backward motion mode
628 {
629 // regular control rule
630 vetta = k_rho_ * rho_error;
631 gamma = k_alpha_ * alpha_error + k_betta_ * betta_error;
632
633 // Even if we are in free navigation, we can enter in the pure spinning state.
634 // then, the linear motion is deactivated.
636 {
637 RCLCPP_INFO(
638 nh_->get_logger(),
639 "[BackwardLocalPlanner] we entered in a pure spinning state even in not pure-spining "
640 "configuration, "
641 "carrotDistanceGoalReached: %d",
642 carrotInLinearGoalRange);
643 gamma = k_betta_ * betta_error;
644 vetta = 0;
645 }
646
647 // classical control to reach a goal backwards
648 }
649
650 // Apply command and Clamp to limits
651 cmd_vel.twist.linear.x = vetta;
652 cmd_vel.twist.angular.z = gamma;
653
654 if (cmd_vel.twist.linear.x > max_linear_x_speed_)
655 {
656 cmd_vel.twist.linear.x = max_linear_x_speed_;
657 }
658 else if (cmd_vel.twist.linear.x < -max_linear_x_speed_)
659 {
660 cmd_vel.twist.linear.x = -max_linear_x_speed_;
661 }
662
663 if (cmd_vel.twist.angular.z > max_angular_z_speed_)
664 {
665 cmd_vel.twist.angular.z = max_angular_z_speed_;
666 }
667 else if (cmd_vel.twist.angular.z < -max_angular_z_speed_)
668 {
669 cmd_vel.twist.angular.z = -max_angular_z_speed_;
670 }
671
672 publishGoalMarker(carrotGoalPosition.x, carrotGoalPosition.y, betta);
673
674 RCLCPP_INFO_STREAM(
675 nh_->get_logger(), "[BackwardLocalPlanner] local planner,"
676 << std::endl
677 << " current pose in goal: " << currentPoseInGoal << std::endl
678 << " carrot in final goal index: " << carrotInFinalGoalIndex << std::endl
679 << " carrot in linear goal range: " << carrotInLinearGoalRange << std::endl
680 << " straightAnPureSpiningMode: " << straightBackwardsAndPureSpinningMode_
681 << std::endl
682 << " inGoalPureSpinningState: " << inGoalPureSpinningState_ << std::endl
683 << " theta: " << theta << std::endl
684 << " betta: " << theta << std::endl
685 << " err_x: " << dx << std::endl
686 << " err_y:" << dy << std::endl
687 << " rho_error:" << rho_error << std::endl
688 << " alpha_error:" << alpha_error << std::endl
689 << " betta_error:" << betta_error << std::endl
690 << " vetta:" << vetta << std::endl
691 << " gamma:" << gamma << std::endl
692 << " cmd_vel.lin.x:" << cmd_vel.twist.linear.x << std::endl
693 << " cmd_vel.ang.z:" << cmd_vel.twist.angular.z);
694
696 {
697 bool carrotHalfPlaneConstraintFailure = checkCarrotHalfPlainConstraint(tfpose);
698
699 if (carrotHalfPlaneConstraintFailure)
700 {
701 RCLCPP_ERROR(
702 nh_->get_logger(),
703 "[BackwardLocalPlanner] CarrotHalfPlaneConstraintFailure detected. Sending "
704 "emergency stop and success to the planner.");
705 cmd_vel.twist.linear.x = 0;
706 }
707 }
708
709 // ---------------------- TRAJECTORY PREDICTION AND COLLISION AVOIDANCE ---------------------
710 geometry_msgs::msg::PoseStamped global_pose;
711 costmapRos_->getRobotPose(global_pose);
712
713 auto * costmap2d = costmapRos_->getCostmap();
714 auto yaw = tf2::getYaw(global_pose.pose.orientation);
715
716 auto & pos = global_pose.pose.position;
717
718 Eigen::Vector3f currentpose(pos.x, pos.y, yaw);
719 Eigen::Vector3f currentvel(
720 cmd_vel.twist.linear.x, cmd_vel.twist.linear.y, cmd_vel.twist.angular.z);
721 std::vector<Eigen::Vector3f> trajectory;
722 this->generateTrajectory(
723 currentpose, currentvel, 0.8 /*meters*/, M_PI / 8 /*rads*/, 3.0 /*seconds*/, 0.05 /*seconds*/,
724 trajectory);
725
726 // check plan rejection
727 bool acceptedLocalTrajectoryFreeOfObstacles = true;
728
729 unsigned int mx, my;
730
732 {
733 if (backwardsPlanPath_.size() > 0)
734 {
735 auto & finalgoalpose = backwardsPlanPath_.back();
736
737 int i = 0;
738 // RCLCPP_INFO_STREAM(nh_->get_logger(), "lplanner goal: " << finalgoalpose.pose.position);
739 geometry_msgs::msg::Twist mockzerospeed;
740
741 for (auto & p : trajectory)
742 {
743 float dx = p[0] - finalgoalpose.pose.position.x;
744 float dy = p[1] - finalgoalpose.pose.position.y;
745
746 float dst = sqrt(dx * dx + dy * dy);
747 if (dst < xy_goal_tolerance_)
748 {
749 RCLCPP_INFO(
750 nh_->get_logger(),
751 "[BackwardLocalPlanner] trajectory simulation for collision checking: goal "
752 "reached with no collision");
753 break;
754 }
755
756 costmap2d->worldToMap(p[0], p[1], mx, my);
757
758 if (costmap2d->getCost(mx, my) >= nav2_costmap_2d::INSCRIBED_INFLATED_OBSTACLE)
759 {
760 acceptedLocalTrajectoryFreeOfObstacles = false;
761 RCLCPP_WARN_STREAM(
762 nh_->get_logger(),
763 "[BackwardLocalPlanner] ABORTED LOCAL PLAN BECAUSE OBSTACLE DETEDTED at point "
764 << i << "/" << trajectory.size() << std::endl
765 << p[0] << ", " << p[1]);
766 break;
767 }
768 i++;
769 }
770 }
771 else
772 {
773 RCLCPP_WARN(
774 nh_->get_logger(), "[BackwardLocalPlanner] Abort local - Backwards global plan size: %ld",
775 backwardsPlanPath_.size());
776 cmd_vel.twist.angular.z = 0;
777 cmd_vel.twist.linear.x = 0;
778 }
779 }
780
781 if (acceptedLocalTrajectoryFreeOfObstacles)
782 {
783 waiting_ = false;
784 RCLCPP_INFO(
785 nh_->get_logger(),
786 "[BackwardLocalPlanner] accepted local trajectory free of obstacle. Local planner "
787 "continues.");
788 return cmd_vel;
789 }
790 else // that is not appceted because existence of obstacles
791 {
792 // emergency stop for collision: waiting a while before sending error
793 cmd_vel.twist.linear.x = 0;
794 cmd_vel.twist.angular.z = 0;
795
796 if (waiting_ == false)
797 {
798 waiting_ = true;
799 waitingStamp_ = nh_->now();
800 RCLCPP_WARN(
801 nh_->get_logger(), "[BackwardLocalPlanner][Not accepted local plan] starting countdown");
802 }
803 else
804 {
805 auto waitingduration = nh_->now() - waitingStamp_;
806
807 if (waitingduration > this->waitingTimeout_)
808 {
809 RCLCPP_WARN(
810 nh_->get_logger(), "[BackwardLocalPlanner][Abort local] timeout! duration %lf/%f",
811 waitingduration.seconds(), waitingTimeout_.seconds());
812 cmd_vel.twist.linear.x = 0;
813 cmd_vel.twist.angular.z = 0;
814 return cmd_vel;
815 }
816 }
817
818 return cmd_vel;
819 }
820}
bool updateCarrotGoal(const geometry_msgs::msg::PoseStamped &pose)
bool checkCarrotHalfPlainConstraint(const geometry_msgs::msg::PoseStamped &pose)
void straightBackwardsAndPureSpinCmd(const geometry_msgs::msg::PoseStamped &pose, double &vetta, double &gamma, double alpha_error, double betta_error, double rho_error)
void generateTrajectory(const Eigen::Vector3f &pos, const Eigen::Vector3f &vel, float maxdist, float maxangle, float maxtime, float dt, std::vector< Eigen::Vector3f > &outtraj)
bool checkCurrentPoseInGoalRange(const geometry_msgs::msg::PoseStamped &tfpose, const geometry_msgs::msg::Twist &currentTwist, double angle_error, bool &linearGoalReached, nav2_core::GoalChecker *goalChecker)

References alpha_offset_, backwardsPlanPath_, betta_offset_, checkCarrotHalfPlainConstraint(), checkCurrentPoseInGoalRange(), costmapRos_, currentCarrotPoseIndex_, enable_obstacle_checking_, generateTrajectory(), goalReached_, inGoalPureSpinningState_, k_alpha_, k_betta_, k_rho_, max_angular_z_speed_, max_linear_x_speed_, nh_, publishGoalMarker(), straightBackwardsAndPureSpinCmd(), straightBackwardsAndPureSpinningMode_, updateCarrotGoal(), updateParameters(), waiting_, waitingStamp_, waitingTimeout_, xy_goal_tolerance_, and yaw_goal_tolerance_.

Here is the call graph for this function:

◆ configure()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::configure ( const rclcpp_lifecycle::LifecycleNode::WeakPtr & parent,
std::string name,
const std::shared_ptr< tf2_ros::Buffer > tf,
const std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmap_ros )
override

Definition at line 96 of file backward_local_planner.cpp.

100{
101 this->costmapRos_ = costmap_ros;
102 this->nh_ = parent.lock();
103 this->name_ = name;
104 this->tf_ = tf;
105
106 k_rho_ = -1.0;
107 k_alpha_ = 0.5;
108 k_betta_ = -1.0; // set to zero means that orientation is not important
116 waitingTimeout_ = rclcpp::Duration(10s);
117
118 this->currentCarrotPoseIndex_ = 0;
119
121 nh_, name_ + ".pure_spinning_straight_line_mode", straightBackwardsAndPureSpinningMode_);
122
123 declareOrSet(nh_, name_ + ".k_rho", k_rho_);
124 declareOrSet(nh_, name_ + ".k_alpha", k_alpha_);
125 declareOrSet(nh_, name_ + ".k_betta", k_betta_);
126 declareOrSet(nh_, name_ + ".linear_mode_rho_error_threshold", linear_mode_rho_error_threshold_);
127
128 declareOrSet(nh_, name_ + ".carrot_distance", carrot_distance_);
129 declareOrSet(nh_, name_ + ".carrot_angular_distance", carrot_angular_distance_);
130 declareOrSet(nh_, name_ + ".enable_obstacle_checking", enable_obstacle_checking_);
131
132 declareOrSet(nh_, name_ + ".max_linear_x_speed", max_linear_x_speed_);
133 declareOrSet(nh_, name_ + ".max_angular_z_speed", max_angular_z_speed_);
134
135 // we have to do this, for example for the case we are refining the final orientation.
136 // check at some point if the carrot is reached in "goal linear distance", then we go into
137 // some automatic pure-spinning mode where we only update the orientation
138 // This means that if we reach the carrot with precision we go into pure spinning mode but we cannot
139 // leave that point (maybe this could be improved)
140
142 {
143 RCLCPP_WARN_STREAM(
144 nh_->get_logger(), "[BackwardLocalPlanner] carrot_angular_distance ("
146 << ") cannot be lower than yaw_goal_tolerance (" << yaw_goal_tolerance_
147 << ") setting carrot_angular_distance = " << yaw_goal_tolerance_);
149 }
150
152 {
153 RCLCPP_WARN_STREAM(
154 nh_->get_logger(), "[BackwardLocalPlanner] carrot_linear_distance ("
155 << carrot_distance_ << ") cannot be lower than xy_goal_tolerance_ ("
157 << ") setting carrot_angular_distance = " << xy_goal_tolerance_);
159 }
160
161 goalMarkerPublisher_ = nh_->create_publisher<visualization_msgs::msg::MarkerArray>(
162 "backward_local_planner/goal_marker", rclcpp::QoS(1));
163
164 planPub_ =
165 nh_->create_publisher<nav_msgs::msg::Path>("backward_local_planner/path", rclcpp::QoS(1));
166}
void declareOrSet(rclcpp_lifecycle::LifecycleNode::SharedPtr &node, std::string param, T &value)
Definition common.hpp:34

References carrot_angular_distance_, carrot_distance_, costmapRos_, currentCarrotPoseIndex_, declareOrSet(), enable_obstacle_checking_, goalMarkerPublisher_, k_alpha_, k_betta_, k_rho_, linear_mode_rho_error_threshold_, max_angular_z_speed_, max_linear_x_speed_, name_, nh_, planPub_, straightBackwardsAndPureSpinningMode_, tf_, waitingTimeout_, xy_goal_tolerance_, and yaw_goal_tolerance_.

Here is the call graph for this function:

◆ deactivate()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::deactivate ( )
override

Definition at line 65 of file backward_local_planner.cpp.

66{
67 this->clearMarkers();
68 RCLCPP_WARN_STREAM(nh_->get_logger(), "[BackwardLocalPlanner] deactivated");
69 planPub_->on_deactivate();
70 goalMarkerPublisher_->on_deactivate();
71}

References clearMarkers(), goalMarkerPublisher_, nh_, and planPub_.

Here is the call graph for this function:

◆ divergenceDetectionUpdate()

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::divergenceDetectionUpdate ( const geometry_msgs::msg::PoseStamped & pose)
private

Definition at line 347 of file backward_local_planner.cpp.

348{
349 double disterr = 0, angleerr = 0;
351
352 RCLCPP_INFO_STREAM(
353 nh_->get_logger(), "[BackwardLocalPlanner] Divergence check. carrot goal distance. was: "
355 << ", now it is: " << disterr);
357 {
358 // candidate of divergence, we do not throw the divergence alarm yet
359 // but we neither update the distance since it is worse than the one
360 // we had previously with the same carrot.
361 const double MARGIN_FACTOR = 1.2;
362 if (disterr > MARGIN_FACTOR * divergenceDetectionLastCarrotLinearDistance_)
363 {
364 RCLCPP_ERROR_STREAM(
365 nh_->get_logger(),
366 "[BackwardLocalPlanner] Divergence detected. The same carrot goal distance was previously: "
367 << divergenceDetectionLastCarrotLinearDistance_ << "but now it is: " << disterr);
368 return true;
369 }
370 else
371 {
372 // divergence candidate
373 return false;
374 }
375 }
376 else
377 {
378 // update:
380 return false;
381 }
382}
void computeCurrentEuclideanAndAngularErrorsToCarrotGoal(const geometry_msgs::msg::PoseStamped &pose, double &dist, double &angular_error)

References computeCurrentEuclideanAndAngularErrorsToCarrotGoal(), divergenceDetectionLastCarrotLinearDistance_, and nh_.

Referenced by setPlan().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ findInitialCarrotGoal()

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::findInitialCarrotGoal ( geometry_msgs::msg::PoseStamped & pose)
private

Definition at line 833 of file backward_local_planner.cpp.

834{
835 double lineardisterr, angleerr;
836 bool inCarrotRange = false;
837
838 // initial state check
839 computeCurrentEuclideanAndAngularErrorsToCarrotGoal(tfpose, lineardisterr, angleerr);
840
841 // lets set the carrot-goal in the correct place with this loop
842 while (currentCarrotPoseIndex_ < (int)backwardsPlanPath_.size() && !inCarrotRange)
843 {
844 computeCurrentEuclideanAndAngularErrorsToCarrotGoal(tfpose, lineardisterr, angleerr);
845
846 RCLCPP_INFO(
847 nh_->get_logger(),
848 "[BackwardLocalPlanner] Finding initial carrot goal i=%d - error to carrot, linear = %lf "
849 "(%lf), "
850 "angular : %lf (%lf)",
852
853 // current path point is inside the carrot distance range, goal carrot tries to escape!
854 if (lineardisterr < carrot_distance_ && angleerr < carrot_angular_distance_)
855 {
856 RCLCPP_INFO(
857 nh_->get_logger(),
858 "[BackwardLocalPlanner] Finding initial carrot goal i=%d - in carrot Range",
860 inCarrotRange = true;
861 // we are inside the goal range
862 }
863 else if (
864 inCarrotRange && (lineardisterr > carrot_distance_ || angleerr > carrot_angular_distance_))
865 {
866 // we were inside the carrot range but not anymore, now we are just leaving. we want to continue forward
867 // (currentCarrotPoseIndex_++) unless we go out of the carrot range
868
869 // but we rollback last index increment (to go back inside the carrot goal scope) and start motion with that
870 // carrot goal we found
872 break;
873 }
874 else
875 {
876 RCLCPP_INFO(
877 nh_->get_logger(),
878 "[BackwardLocalPlanner] Finding initial carrot goal i=%d - carrot out of range, searching "
879 "coincidence...",
881 }
882
884 RCLCPP_INFO_STREAM(
885 nh_->get_logger(), "[BackwardLocalPlanner] setPlan: fw" << currentCarrotPoseIndex_);
886 }
887
888 RCLCPP_INFO_STREAM(
889 nh_->get_logger(), "[BackwardLocalPlanner] setPlan: (found first carrot:"
890 << inCarrotRange << ") initial carrot point index: "
891 << currentCarrotPoseIndex_ << "/" << backwardsPlanPath_.size());
892
893 return inCarrotRange;
894}

References backwardsPlanPath_, carrot_angular_distance_, carrot_distance_, computeCurrentEuclideanAndAngularErrorsToCarrotGoal(), currentCarrotPoseIndex_, and nh_.

Referenced by setPlan().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ generateTrajectory()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::generateTrajectory ( const Eigen::Vector3f & pos,
const Eigen::Vector3f & vel,
float maxdist,
float maxangle,
float maxtime,
float dt,
std::vector< Eigen::Vector3f > & outtraj )
private

Definition at line 1055 of file backward_local_planner.cpp.

1058{
1059 // simulate the trajectory and check for collisions, updating costs along the way
1060 bool end = false;
1061 float time = 0;
1062 Eigen::Vector3f currentpos = pos;
1063 int i = 0;
1064 while (!end)
1065 {
1066 auto loop_vel = vel;
1067 // update the position of the robot using the velocities passed in
1068 auto newpos = computeNewPositions(currentpos, loop_vel, dt);
1069
1070 auto dx = newpos[0] - currentpos[0];
1071 auto dy = newpos[1] - currentpos[1];
1072 float dist, angledist;
1073
1074 // RCLCPP_INFO(nh_->get_logger(), "traj point %d", i);
1075 dist = sqrt(dx * dx + dy * dy);
1076 if (dist > maxdist)
1077 {
1078 end = true;
1079 // RCLCPP_INFO(nh_->get_logger(), "dist break: %f", dist);
1080 }
1081 else
1082 {
1083 // ouble from, double to
1084 angledist = angles::shortest_angular_distance(currentpos[2], newpos[2]);
1085 if (angledist > maxanglediff)
1086 {
1087 end = true;
1088 // RCLCPP_INFO(nh_->get_logger(), "angle dist break: %f", angledist);
1089 }
1090 else
1091 {
1092 outtraj.push_back(newpos);
1093
1094 time += dt;
1095 if (time > maxtime)
1096 {
1097 end = true;
1098 // RCLCPP_INFO(nh_->get_logger(), "time break: %f", time);
1099 }
1100
1101 // RCLCPP_INFO(nh_->get_logger(), "dist: %f, angledist: %f, time: %f", dist, angledist, time);
1102 }
1103 }
1104
1105 currentpos = newpos;
1106 i++;
1107 } // end for simulation steps
1108}
Eigen::Vector3f computeNewPositions(const Eigen::Vector3f &pos, const Eigen::Vector3f &vel, double dt)

References computeNewPositions().

Referenced by computeVelocityCommands().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isGoalReached()

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::isGoalReached ( )

isGoalReached()

Definition at line 827 of file backward_local_planner.cpp.

828{
829 RCLCPP_INFO(nh_->get_logger(), "[BackwardLocalPlanner] isGoalReached call");
830 return goalReached_;
831}

References goalReached_, and nh_.

◆ publishGoalMarker()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::publishGoalMarker ( double x,
double y,
double phi )
private

publishGoalMarker()

Definition at line 1146 of file backward_local_planner.cpp.

1147{
1148 visualization_msgs::msg::Marker marker;
1149 marker.header.frame_id = this->costmapRos_->getGlobalFrameID();
1150 marker.header.stamp = nh_->now();
1151
1152 marker.ns = "my_namespace2";
1153 marker.id = 0;
1154 marker.type = visualization_msgs::msg::Marker::ARROW;
1155 marker.action = visualization_msgs::msg::Marker::ADD;
1156 marker.lifetime = rclcpp::Duration(1.0s);
1157
1158 marker.pose.orientation.w = 1;
1159
1160 marker.scale.x = 0.05;
1161 marker.scale.y = 0.15;
1162 marker.scale.z = 0.05;
1163 marker.color.a = 1.0;
1164
1165 // red marker
1166 marker.color.r = 1;
1167 marker.color.g = 0;
1168 marker.color.b = 0;
1169
1170 geometry_msgs::msg::Point start, end;
1171 start.x = x;
1172 start.y = y;
1173
1174 end.x = x + 0.5 * cos(phi);
1175 end.y = y + 0.5 * sin(phi);
1176
1177 marker.points.push_back(start);
1178 marker.points.push_back(end);
1179
1180 visualization_msgs::msg::MarkerArray ma;
1181 ma.markers.push_back(marker);
1182
1183 goalMarkerPublisher_->publish(ma);
1184}

References costmapRos_, goalMarkerPublisher_, and nh_.

Referenced by computeVelocityCommands().

Here is the caller graph for this function:

◆ resamplePrecisePlan()

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::resamplePrecisePlan ( )
private

Definition at line 896 of file backward_local_planner.cpp.

897{
898 // this algorithm is really important to have a precise carrot (linear or angular)
899 // and not being considered as a divergence from the path
900
901 RCLCPP_INFO(nh_->get_logger(), "[BackwardLocalPlanner] resample precise");
902 if (backwardsPlanPath_.size() <= 1)
903 {
904 RCLCPP_INFO_STREAM(
905 nh_->get_logger(),
906 "[BackwardLocalPlanner] resample precise skipping, size: " << backwardsPlanPath_.size());
907 return false;
908 }
909
910 int counter = 0;
911 double maxallowedAngularError = 0.45 * this->carrot_angular_distance_; // nyquist
912 double maxallowedLinearError = 0.45 * this->carrot_distance_; // nyquist
913
914 for (int i = 0; i < (int)backwardsPlanPath_.size() - 1; i++)
915 {
916 RCLCPP_INFO_STREAM(nh_->get_logger(), "[BackwardLocalPlanner] resample precise, check: " << i);
917 auto & currpose = backwardsPlanPath_[i];
918 auto & nextpose = backwardsPlanPath_[i + 1];
919
920 tf2::Quaternion qCurrent, qNext;
921 tf2::convert(currpose.pose.orientation, qCurrent);
922 tf2::convert(nextpose.pose.orientation, qNext);
923
924 double dx = nextpose.pose.position.x - currpose.pose.position.x;
925 double dy = nextpose.pose.position.y - currpose.pose.position.y;
926 double dist = sqrt(dx * dx + dy * dy);
927
928 bool resample = false;
929 if (dist > maxallowedLinearError)
930 {
931 RCLCPP_INFO_STREAM(
932 nh_->get_logger(), "[BackwardLocalPlanner] resampling point, linear distance:"
933 << dist << "(" << maxallowedLinearError << ")" << i);
934 resample = true;
935 }
936 else
937 {
938 double currentAngle = tf2::getYaw(qCurrent);
939 double nextAngle = tf2::getYaw(qNext);
940
941 double angularError = fabs(angles::shortest_angular_distance(currentAngle, nextAngle));
942 if (angularError > maxallowedAngularError)
943 {
944 resample = true;
945 RCLCPP_INFO_STREAM(
946 nh_->get_logger(), "[BackwardLocalPlanner] resampling point, angular distance:"
947 << angularError << "(" << maxallowedAngularError << ")" << i);
948 }
949 }
950
951 if (resample)
952 {
953 geometry_msgs::msg::PoseStamped pintermediate;
954 auto duration = rclcpp::Time(nextpose.header.stamp) - rclcpp::Time(currpose.header.stamp);
955
956 pintermediate.header.frame_id = currpose.header.frame_id;
957 pintermediate.header.stamp = rclcpp::Time(currpose.header.stamp) + duration * 0.5;
958
959 pintermediate.pose.position.x = 0.5 * (currpose.pose.position.x + nextpose.pose.position.x);
960 pintermediate.pose.position.y = 0.5 * (currpose.pose.position.y + nextpose.pose.position.y);
961 pintermediate.pose.position.z = 0.5 * (currpose.pose.position.z + nextpose.pose.position.z);
962 tf2::Quaternion intermediateQuat = tf2::slerp(qCurrent, qNext, 0.5);
963 pintermediate.pose.orientation = tf2::toMsg(intermediateQuat);
964
965 this->backwardsPlanPath_.insert(this->backwardsPlanPath_.begin() + i + 1, pintermediate);
966
967 // retry this point
968 i--;
969 counter++;
970 }
971 }
972
973 RCLCPP_INFO_STREAM(
974 nh_->get_logger(), "[BackwardLocalPlanner] End resampling. resampled:" << counter
975 << " new inserted poses "
976 "during precise "
977 "resmapling.");
978 return true;
979}

References backwardsPlanPath_, carrot_angular_distance_, carrot_distance_, and nh_.

Referenced by setPlan().

Here is the caller graph for this function:

◆ resetDivergenceDetection()

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::resetDivergenceDetection ( )
private

Definition at line 340 of file backward_local_planner.cpp.

341{
342 // this function should be called always the carrot is updated
343 divergenceDetectionLastCarrotLinearDistance_ = std::numeric_limits<double>::max();
344 return true;
345}

References divergenceDetectionLastCarrotLinearDistance_.

Referenced by setPlan(), and updateCarrotGoal().

Here is the caller graph for this function:

◆ setPlan()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::setPlan ( const nav_msgs::msg::Path & path)
override

nav2_core setPlan - Sets the global plan

Parameters
pathThe global plan

setPlan()

Definition at line 986 of file backward_local_planner.cpp.

987{
988 RCLCPP_INFO_STREAM(
989 nh_->get_logger(),
990 "[BackwardLocalPlanner] setPlan: new global plan received ( " << path.poses.size() << ")");
991
992 //------------- TRANSFORM TO LOCAL FRAME PATH ---------------------------
993 nav_msgs::msg::Path transformedPlan;
994 rclcpp::Duration ttol = rclcpp::Duration::from_seconds(transform_tolerance_);
995 // transform global plan to the navigation reference frame
996 for (auto & p : path.poses)
997 {
998 geometry_msgs::msg::PoseStamped transformedPose;
999 nav_2d_utils::transformPose(tf_, costmapRos_->getGlobalFrameID(), p, transformedPose, ttol);
1000 transformedPose.header.frame_id = costmapRos_->getGlobalFrameID();
1001 transformedPlan.poses.push_back(transformedPose);
1002 }
1003
1004 backwardsPlanPath_ = transformedPlan.poses;
1005
1006 // --------- resampling path feature -----------
1007 geometry_msgs::msg::PoseStamped tfpose;
1008 if (!costmapRos_->getRobotPose(tfpose))
1009 {
1010 RCLCPP_ERROR(nh_->get_logger(), "Failure getting pose from Backward local planner");
1011 return;
1012 }
1013
1014 geometry_msgs::msg::PoseStamped posestamped = tfpose;
1015 backwardsPlanPath_.insert(backwardsPlanPath_.begin(), posestamped);
1016 this->resamplePrecisePlan();
1017
1018 nav_msgs::msg::Path planMsg;
1019 planMsg.poses = backwardsPlanPath_;
1020 planMsg.header.frame_id = costmapRos_->getGlobalFrameID();
1021 planMsg.header.stamp = nh_->now();
1022 planPub_->publish(planMsg);
1023
1024 // ------ reset controller state ----------------------
1025 goalReached_ = false;
1029
1030 if (path.poses.size() == 0)
1031 {
1032 RCLCPP_INFO_STREAM(nh_->get_logger(), "[BackwardLocalPlanner] received plan without any pose");
1033 return;
1034 }
1035
1036 // -------- initialize carrot ----------------
1037 bool foundInitialCarrotGoal = this->findInitialCarrotGoal(tfpose);
1038 if (!foundInitialCarrotGoal)
1039 {
1040 RCLCPP_ERROR(
1041 nh_->get_logger(),
1042 "[BackwardLocalPlanner] new plan rejected. The initial point in the global path is "
1043 "too much far away from the current state (according to carrot_distance "
1044 "parameter)");
1045 // return false; // in this case, the new plan broke the current execution
1046 return;
1047 }
1048 else
1049 {
1050 this->divergenceDetectionUpdate(tfpose);
1051 return;
1052 }
1053}
bool findInitialCarrotGoal(geometry_msgs::msg::PoseStamped &pose)
bool divergenceDetectionUpdate(const geometry_msgs::msg::PoseStamped &pose)

References backwardsPlanPath_, costmapRos_, currentCarrotPoseIndex_, divergenceDetectionUpdate(), findInitialCarrotGoal(), goalReached_, inGoalPureSpinningState_, nh_, planPub_, resamplePrecisePlan(), resetDivergenceDetection(), tf_, and transform_tolerance_.

Here is the call graph for this function:

◆ setSpeedLimit()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::setSpeedLimit ( const double & speed_limit,
const bool & percentage )
overridevirtual

Definition at line 231 of file backward_local_planner.cpp.

233{
234 RCLCPP_WARN_STREAM(
235 nh_->get_logger(),
236 "BackwardLocalPlanner::setSpeedLimit invoked. Ignored, functionality not "
237 "implemented.");
238}

References nh_.

◆ straightBackwardsAndPureSpinCmd()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::straightBackwardsAndPureSpinCmd ( const geometry_msgs::msg::PoseStamped & pose,
double & vetta,
double & gamma,
double alpha_error,
double betta_error,
double rho_error )
private

pureSpinningCmd()

Definition at line 445 of file backward_local_planner.cpp.

448{
449 if (rho_error > linear_mode_rho_error_threshold_) // works in straight motion mode
450 {
451 vetta = k_rho_ * rho_error;
452 gamma = k_alpha_ * alpha_error;
453 }
454 else if (fabs(betta_error) >= this->yaw_goal_tolerance_) // works in pure spinning mode
455 {
456 vetta = 0; // disable linear
457 gamma = k_betta_ * betta_error;
458 }
459}

References k_alpha_, k_betta_, k_rho_, linear_mode_rho_error_threshold_, and yaw_goal_tolerance_.

Referenced by computeVelocityCommands().

Here is the caller graph for this function:

◆ updateCarrotGoal()

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::updateCarrotGoal ( const geometry_msgs::msg::PoseStamped & tfpose)
private

updateCarrotGoal()

Definition at line 278 of file backward_local_planner.cpp.

279{
280 RCLCPP_INFO_STREAM(nh_->get_logger(), "[BackwardsLocalPlanner] --- Carrot update ---");
281 double disterr = 0, angleerr = 0;
282 // iterate the point from the current position and backward until reaching a new goal point in the path
283 // this algorithm among other advantages has that skip the looping with an eager global planner
284 // that recalls the same plan (the already performed part of the plan in the current pose is skipped)
285 while (currentCarrotPoseIndex_ < (long)backwardsPlanPath_.size() - 1)
286 {
288
289 RCLCPP_INFO_STREAM(
290 nh_->get_logger(), "[BackwardsLocalPlanner] update carrot goal: Current index: "
291 << currentCarrotPoseIndex_ << "/" << backwardsPlanPath_.size());
292 RCLCPP_INFO(
293 nh_->get_logger(),
294 "[BackwardsLocalPlanner] update carrot goal: linear error %lf, angular error: %lf", disterr,
295 angleerr);
296
297 // target pose found, goal carrot tries to escape!
298 if (disterr < carrot_distance_ && angleerr < carrot_angular_distance_)
299 {
302 RCLCPP_INFO_STREAM(
303 nh_->get_logger(), "[BackwardsLocalPlanner] move carrot fw "
304 << currentCarrotPoseIndex_ << "/" << backwardsPlanPath_.size());
305 }
306 else
307 {
308 // carrot already escaped
309 break;
310 }
311 }
312 // RCLCPP_INFO(nh_->get_logger(),"[BackwardsLocalPlanner] computing angular error");
313 if (
314 currentCarrotPoseIndex_ >= (long)backwardsPlanPath_.size() - 1 && backwardsPlanPath_.size() > 0)
315 {
317 // reupdated errors
319 }
320
321 RCLCPP_INFO(
322 nh_->get_logger(), "[BackwardsLocalPlanner] Current index carrot goal: %d",
324 RCLCPP_INFO(
325 nh_->get_logger(),
326 "[BackwardsLocalPlanner] Update carrot goal: linear error %lf (xytol: %lf), angular error: "
327 "%lf",
328 disterr, xy_goal_tolerance_, angleerr);
329
330 bool carrotInGoalLinearRange = disterr < xy_goal_tolerance_;
331 RCLCPP_INFO(
332 nh_->get_logger(), "[BackwardsLocalPlanner] carrot in goal radius: %d",
333 carrotInGoalLinearRange);
334
335 RCLCPP_INFO(nh_->get_logger(), "[BackwardsLocalPlanner] ---End carrot update---");
336
337 return carrotInGoalLinearRange;
338}

References backwardsPlanPath_, carrot_angular_distance_, carrot_distance_, computeCurrentEuclideanAndAngularErrorsToCarrotGoal(), currentCarrotPoseIndex_, nh_, resetDivergenceDetection(), and xy_goal_tolerance_.

Referenced by computeVelocityCommands().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ updateParameters()

void cl_nav2z::backward_local_planner::BackwardLocalPlanner::updateParameters ( )
private

Definition at line 168 of file backward_local_planner.cpp.

169{
170 RCLCPP_INFO_STREAM(nh_->get_logger(), "--- parameters ---");
171 tryGetOrSet(nh_, name_ + ".k_rho", k_rho_);
172 RCLCPP_INFO_STREAM(nh_->get_logger(), name_ + ".k_rho:" << k_rho_);
173 tryGetOrSet(nh_, name_ + ".k_alpha", k_alpha_);
174 RCLCPP_INFO_STREAM(nh_->get_logger(), name_ + ".k_alpha:" << k_alpha_);
175 tryGetOrSet(nh_, name_ + ".k_betta", k_betta_);
176 RCLCPP_INFO_STREAM(nh_->get_logger(), name_ + ".k_betta:" << k_betta_);
177
178 tryGetOrSet(nh_, name_ + ".enable_obstacle_checking", enable_obstacle_checking_);
179 RCLCPP_INFO_STREAM(
180 nh_->get_logger(), name_ + ".enable_obstacle_checking: " << enable_obstacle_checking_);
181
182 tryGetOrSet(nh_, name_ + ".carrot_distance", carrot_distance_);
183 RCLCPP_INFO_STREAM(nh_->get_logger(), name_ + ".carrot_distance:" << carrot_distance_);
184 tryGetOrSet(nh_, name_ + ".carrot_angular_distance", carrot_angular_distance_);
185 RCLCPP_INFO_STREAM(
186 nh_->get_logger(), name_ + ".carrot_angular_distance: " << carrot_angular_distance_);
187
189 nh_, name_ + ".pure_spinning_straight_line_mode", straightBackwardsAndPureSpinningMode_);
190 RCLCPP_INFO_STREAM(
191 nh_->get_logger(),
192 name_ + ".pure_spinning_straight_line_mode: " << straightBackwardsAndPureSpinningMode_);
193
194 tryGetOrSet(nh_, name_ + ".linear_mode_rho_error_threshold", linear_mode_rho_error_threshold_);
195 RCLCPP_INFO_STREAM(
196 nh_->get_logger(),
197 name_ + ".linear_mode_rho_error_threshold: " << linear_mode_rho_error_threshold_);
198 tryGetOrSet(nh_, name_ + ".max_linear_x_speed", max_linear_x_speed_);
199 RCLCPP_INFO_STREAM(nh_->get_logger(), name_ + ".max_linear_x_speed: " << max_linear_x_speed_);
200 tryGetOrSet(nh_, name_ + ".max_angular_z_speed", max_angular_z_speed_);
201 RCLCPP_INFO_STREAM(nh_->get_logger(), name_ + ".max_angular_z_speed: " << max_angular_z_speed_);
202
204 {
205 RCLCPP_WARN_STREAM(
206 nh_->get_logger(), "[BackwardLocalPlanner] carrot_angular_distance ("
208 << ") cannot be lower than yaw_goal_tolerance (" << yaw_goal_tolerance_
209 << ") setting carrot_angular_distance = " << yaw_goal_tolerance_);
211 nh_->set_parameter(
212 rclcpp::Parameter(name_ + ".carrot_angular_distance", carrot_angular_distance_));
213 }
214 RCLCPP_INFO_STREAM(
215 nh_->get_logger(), name_ + ".carrot_angular_distance: " << carrot_angular_distance_);
216
218 {
219 RCLCPP_WARN_STREAM(
220 nh_->get_logger(), "[BackwardLocalPlanner] carrot_linear_distance ("
221 << carrot_distance_ << ") cannot be lower than xy_goal_tolerance_ ("
223 << ") setting carrot_angular_distance = " << xy_goal_tolerance_);
225 nh_->set_parameter(rclcpp::Parameter(name_ + ".carrot_distance", carrot_distance_));
226 }
227 RCLCPP_INFO_STREAM(nh_->get_logger(), name_ + ".carrot_distance:" << carrot_distance_);
228 RCLCPP_INFO_STREAM(nh_->get_logger(), "--- end params ---");
229}
void tryGetOrSet(rclcpp_lifecycle::LifecycleNode::SharedPtr &node, std::string param, T &value)

References carrot_angular_distance_, carrot_distance_, enable_obstacle_checking_, k_alpha_, k_betta_, k_rho_, linear_mode_rho_error_threshold_, max_angular_z_speed_, max_linear_x_speed_, name_, nh_, straightBackwardsAndPureSpinningMode_, cl_nav2z::backward_local_planner::tryGetOrSet(), xy_goal_tolerance_, and yaw_goal_tolerance_.

Referenced by activate(), and computeVelocityCommands().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ alpha_offset_

const double cl_nav2z::backward_local_planner::BackwardLocalPlanner::alpha_offset_ = M_PI
private

Definition at line 136 of file backward_local_planner.hpp.

Referenced by computeVelocityCommands().

◆ backwardsPlanPath_

std::vector<geometry_msgs::msg::PoseStamped> cl_nav2z::backward_local_planner::BackwardLocalPlanner::backwardsPlanPath_
private

◆ betta_offset_

const double cl_nav2z::backward_local_planner::BackwardLocalPlanner::betta_offset_ = 0
private

Definition at line 137 of file backward_local_planner.hpp.

Referenced by computeVelocityCommands().

◆ carrot_angular_distance_

rad cl_nav2z::backward_local_planner::BackwardLocalPlanner::carrot_angular_distance_
private

◆ carrot_distance_

meter cl_nav2z::backward_local_planner::BackwardLocalPlanner::carrot_distance_
private

◆ costmapRos_

std::shared_ptr<nav2_costmap_2d::Costmap2DROS> cl_nav2z::backward_local_planner::BackwardLocalPlanner::costmapRos_
private

◆ currentCarrotPoseIndex_

int cl_nav2z::backward_local_planner::BackwardLocalPlanner::currentCarrotPoseIndex_
private

◆ divergenceDetectionLastCarrotLinearDistance_

meter cl_nav2z::backward_local_planner::BackwardLocalPlanner::divergenceDetectionLastCarrotLinearDistance_
private

◆ enable_obstacle_checking_

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::enable_obstacle_checking_ = true
private

◆ goalMarkerPublisher_

std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<visualization_msgs::msg::MarkerArray> > cl_nav2z::backward_local_planner::BackwardLocalPlanner::goalMarkerPublisher_
private

◆ goalReached_

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::goalReached_
private

Definition at line 155 of file backward_local_planner.hpp.

Referenced by computeVelocityCommands(), isGoalReached(), and setPlan().

◆ inGoalPureSpinningState_

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::inGoalPureSpinningState_ = false
private

Definition at line 159 of file backward_local_planner.hpp.

Referenced by computeVelocityCommands(), and setPlan().

◆ initialPureSpinningStage_

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::initialPureSpinningStage_
private

Definition at line 156 of file backward_local_planner.hpp.

◆ k_alpha_

double cl_nav2z::backward_local_planner::BackwardLocalPlanner::k_alpha_
private

◆ k_betta_

double cl_nav2z::backward_local_planner::BackwardLocalPlanner::k_betta_
private

◆ k_rho_

double cl_nav2z::backward_local_planner::BackwardLocalPlanner::k_rho_
private

◆ linear_mode_rho_error_threshold_

double cl_nav2z::backward_local_planner::BackwardLocalPlanner::linear_mode_rho_error_threshold_
private

◆ max_angular_z_speed_

double cl_nav2z::backward_local_planner::BackwardLocalPlanner::max_angular_z_speed_
private

◆ max_linear_x_speed_

double cl_nav2z::backward_local_planner::BackwardLocalPlanner::max_linear_x_speed_
private

◆ name_

std::string cl_nav2z::backward_local_planner::BackwardLocalPlanner::name_
private

Definition at line 119 of file backward_local_planner.hpp.

Referenced by configure(), and updateParameters().

◆ nh_

◆ planPub_

std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<nav_msgs::msg::Path> > cl_nav2z::backward_local_planner::BackwardLocalPlanner::planPub_
private

Definition at line 127 of file backward_local_planner.hpp.

Referenced by activate(), configure(), deactivate(), and setPlan().

◆ pure_spinning_allowed_betta_error_

double cl_nav2z::backward_local_planner::BackwardLocalPlanner::pure_spinning_allowed_betta_error_
private

Definition at line 133 of file backward_local_planner.hpp.

◆ straightBackwardsAndPureSpinningMode_

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::straightBackwardsAndPureSpinningMode_ = false
private

◆ tf_

std::shared_ptr<tf2_ros::Buffer> cl_nav2z::backward_local_planner::BackwardLocalPlanner::tf_
private

Definition at line 123 of file backward_local_planner.hpp.

Referenced by configure(), and setPlan().

◆ transform_tolerance_

double cl_nav2z::backward_local_planner::BackwardLocalPlanner::transform_tolerance_
private

Definition at line 149 of file backward_local_planner.hpp.

Referenced by setPlan().

◆ waiting_

bool cl_nav2z::backward_local_planner::BackwardLocalPlanner::waiting_
private

Definition at line 160 of file backward_local_planner.hpp.

Referenced by computeVelocityCommands().

◆ waitingStamp_

rclcpp::Time cl_nav2z::backward_local_planner::BackwardLocalPlanner::waitingStamp_
private

Definition at line 152 of file backward_local_planner.hpp.

Referenced by computeVelocityCommands().

◆ waitingTimeout_

rclcpp::Duration cl_nav2z::backward_local_planner::BackwardLocalPlanner::waitingTimeout_
private

Definition at line 151 of file backward_local_planner.hpp.

Referenced by computeVelocityCommands(), and configure().

◆ xy_goal_tolerance_

double cl_nav2z::backward_local_planner::BackwardLocalPlanner::xy_goal_tolerance_
private

◆ yaw_goal_tolerance_

double cl_nav2z::backward_local_planner::BackwardLocalPlanner::yaw_goal_tolerance_
private

The documentation for this class was generated from the following files: