SMACC2
Loading...
Searching...
No Matches
cb_undo_path_backwards.cpp
Go to the documentation of this file.
1// Copyright 2025 Robosoft Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/*****************************************************************************************************************
16 *
17 * Authors: Pablo Inigo Blasco, Brett Aldrich
18 *
19 ******************************************************************************************************************/
20
22#include <cl_nav2z/common.hpp>
25
26namespace cl_nav2z
27{
28using ::cl_nav2z::odom_tracker::CpOdomTracker;
29using ::cl_nav2z::odom_tracker::WorkingMode;
30
31using namespace std::chrono_literals;
32using namespace smacc2;
33
34CbUndoPathBackwards::CbUndoPathBackwards(std::optional<CbUndoPathBackwardsOptions> options)
35{
36 options_ = options;
37}
38
40{
41 requiresComponent(odomTracker, ComponentRequirement::HARD);
42
44
45 CpPlannerSwitcher * plannerSwitcher;
46 requiresComponent(plannerSwitcher, ComponentRequirement::HARD);
47
48 nav_msgs::msg::Path forwardpath = odomTracker->getPath();
49 // RCLCPP_INFO_STREAM(getLogger(),"[UndoPathBackward] Current path backwards: " << forwardpath);
50
51 odomTracker->setWorkingMode(WorkingMode::CLEAR_PATH);
52
53 nav2_msgs::action::NavigateToPose::Goal goal;
54
55 CpGoalCheckerSwitcher * goalCheckerSwitcher;
56 requiresComponent(goalCheckerSwitcher, ComponentRequirement::HARD);
57
58 if (forwardpath.poses.size() > 0)
59 {
60 goal.pose = forwardpath.poses.front();
61 goal.pose.header.stamp = rclcpp::Time(0);
62
63 if (options_ && options_->undoControllerName_)
64 {
65 plannerSwitcher->setUndoPathBackwardPlanner(false);
66 RCLCPP_INFO_STREAM(
67 getLogger(),
68 "[" << getName() << "] Undoing path with controller: " << *options_->undoControllerName_);
69 plannerSwitcher->setDesiredController(*options_->undoControllerName_);
70 plannerSwitcher->commitPublish();
71 }
72 else
73 {
74 plannerSwitcher->setUndoPathBackwardPlanner();
75 }
76
77 // The remote UndoPathGlobalPlanner receives the recorded trail via the
78 // odom_tracker_path topic. Right after a popPath (chained undo) its cache may
79 // still hold the previous, fully-consumed trail - a few poses under the robot -
80 // which would make the goal checker succeed instantly without moving. The
81 // tracker republishes at odom rate (~20-30 Hz), so a short settle guarantees
82 // the planner sees the restored trail before the goal is accepted.
83 // (This runs in the asynchronous onEntry thread: it does not block the state
84 // machine. TODO: replace with an explicit ready handshake from the planner.)
85 rclcpp::sleep_for(std::chrono::milliseconds(500));
86
87 RCLCPP_INFO_STREAM(getLogger(), "[" << getName() << "] activating undo navigation planner");
88
89 if (options_ && options_->goalCheckerId_)
90 {
91 goalCheckerSwitcher->setGoalCheckerId(*options_->goalCheckerId_);
92 }
93 else
94 {
95 goalCheckerSwitcher->setGoalCheckerId("undo_path_backwards_goal_checker");
96 }
97
98 this->sendGoal(goal);
99 }
100}
101
103{
104 RCLCPP_INFO_STREAM(getLogger(), "[" << getName() << "] Exiting: undo navigation ");
105
106 // NOTE: odomTracker was resolved in onEntry. Do NOT call requiresComponent here:
107 // this method runs in the asynchronous onExit thread while the state machine
108 // thread holds m_mutex_ during state disposal and joins this thread - a
109 // requiresComponent lookup (which locks m_mutex_) deadlocks the state machine.
110 if (this->navigationResult_ == rclcpp_action::ResultCode::SUCCEEDED)
111 {
112 RCLCPP_INFO_STREAM(
113 getLogger(), getName() << " - [CbUndoPathBackwards] Exiting: undo navigation successful, "
114 "popping odom tracker path");
115
118 }
119 else
120 {
121 RCLCPP_INFO_STREAM(
122 getLogger(), getName() << " - [CbUndoPathBackwards] Exiting: undo navigation abort, avoiding "
123 "popping current path");
124
126 // navigation interrupted or aborted. The path may be not totally undone.
127 // We keep the odom tracker in its current state, probably in the middle of the undoing process.
128 // Could you try to repeat the behavior?
129 }
130
131 // Stop consuming the recorded path once the behavior is over: CLEAR_PATH must not
132 // outlive this behavior, otherwise the tracker keeps eating paths recorded by
133 // subsequent behaviors.
134 odomTracker->setWorkingMode(WorkingMode::IDLE);
135}
136
137} // namespace cl_nav2z
std::optional< CbUndoPathBackwardsOptions > options_
CbUndoPathBackwards(std::optional< CbUndoPathBackwardsOptions > options=std::nullopt)
void setGoalCheckerId(std::string goal_checker_id)
void setUndoPathBackwardPlanner(bool commit=true)
void popPath(int pathCount=1, bool keepPreviousPath=false)
void setWorkingMode(WorkingMode workingMode)
virtual rclcpp::Logger getLogger() const
void requiresComponent(SmaccComponentType *&storage, ComponentRequirement requirementType=ComponentRequirement::SOFT)