SMACC2
Loading...
Searching...
No Matches
cb_absolute_rotate.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
21#include <cl_nav2z/cl_nav2z.hpp>
23#include <cl_nav2z/common.hpp>
27
28#include <rclcpp/parameter_client.hpp>
29
30namespace cl_nav2z
31{
32using namespace smacc2;
33
35CbAbsoluteRotate::CbAbsoluteRotate(float absoluteGoalAngleDegree, float yaw_goal_tolerance)
36{
37 this->absoluteGoalAngleDegree = absoluteGoalAngleDegree;
38
39 if (yaw_goal_tolerance >= 0)
40 {
41 this->yawGoalTolerance = yaw_goal_tolerance;
42 }
43}
44
46{
47 listener = std::make_shared<tf2_ros::Buffer>(getNode()->get_clock());
48 double goal_angle = this->absoluteGoalAngleDegree;
49
50 RCLCPP_INFO_STREAM(getLogger(), "[CbAbsoluteRotate] Absolute yaw Angle:" << goal_angle);
51
52 CpPlannerSwitcher * plannerSwitcher;
53 this->requiresComponent(plannerSwitcher, ComponentRequirement::SOFT);
54
56 {
57 plannerSwitcher->setPureSpinningPlanner();
58 }
59 else
60 {
61 plannerSwitcher->setDefaultPlanners();
62 }
63
65
67 this->requiresComponent(p, ComponentRequirement::HARD);
68
69 auto referenceFrame = p->getReferenceFrame();
70 auto currentPoseMsg = p->toPoseMsg();
71
72 nav2_msgs::action::NavigateToPose::Goal goal;
73 goal.pose.header.frame_id = referenceFrame;
74
75 auto targetAngle = goal_angle * M_PI / 180.0;
76 goal.pose.pose.position = currentPoseMsg.position;
77 tf2::Quaternion q;
78 q.setRPY(0, 0, targetAngle);
79 goal.pose.pose.orientation = tf2::toMsg(q);
80
82 this->requiresComponent(odomTracker_, ComponentRequirement::SOFT);
83
84 if (odomTracker_ != nullptr)
85 {
86 auto pathname = this->getCurrentState()->getName() + " - " + getName();
87 odomTracker_->pushPath(pathname);
88 odomTracker_->setStartPoint(p->toPoseStampedMsg());
89 odomTracker_->setCurrentMotionGoal(goal.pose);
91 }
92
93 CpGoalCheckerSwitcher * goalCheckerSwitcher;
94 this->requiresComponent(goalCheckerSwitcher, ComponentRequirement::HARD);
95
96 goalCheckerSwitcher->setGoalCheckerId("absolute_rotate_goal_checker");
97
98 RCLCPP_INFO_STREAM(
99 getLogger(),
100 "[" << getName() << "] current pose yaw: " << tf2::getYaw(currentPoseMsg.orientation));
101 RCLCPP_INFO_STREAM(
102 getLogger(),
103 "[" << getName() << "] goal pose yaw: " << tf2::getYaw(goal.pose.pose.orientation));
104 this->sendGoal(goal);
105}
106
108{
109 auto log = this->getLogger();
110
111 std::string nodename = "/controller_server";
112
113 auto parameters_client =
114 std::make_shared<rclcpp::AsyncParametersClient>(this->getNode(), nodename);
115
116 RCLCPP_INFO_STREAM(
117 log, "[" << getName() << "] using a parameter client to update some controller parameters: "
118 << nodename << ". Waiting service.");
119 parameters_client->wait_for_service();
120
121 RCLCPP_INFO_STREAM(log, "[" << getName() << "] Service found: " << nodename << ".");
122
123 std::string localPlannerName;
124 std::vector<rclcpp::Parameter> parameters;
125
126 rclcpp::Parameter yaw_goal_tolerance("goal_checker.yaw_goal_tolerance");
127
128 rclcpp::Parameter max_vel_theta, min_vel_theta;
129
130 bool isRosBasePlanner = !spinningPlanner || *spinningPlanner == SpinningPlanner::Default;
131 bool isPureSpinningPlanner = spinningPlanner && *spinningPlanner == SpinningPlanner::PureSpinning;
132
133 // SELECTING CONTROLLER AND PARAMETERS NAME
134 if (isPureSpinningPlanner)
135 {
136 localPlannerName = "PureSpinningLocalPlanner";
137 max_vel_theta = rclcpp::Parameter(localPlannerName + ".max_angular_z_speed");
138 min_vel_theta = rclcpp::Parameter(localPlannerName + ".min_vel_theta");
139 }
140 else if (isRosBasePlanner)
141 {
142 localPlannerName = "FollowPath";
143 max_vel_theta = rclcpp::Parameter(localPlannerName + ".max_vel_theta");
144 min_vel_theta = rclcpp::Parameter(localPlannerName + ".min_vel_theta");
145 }
146
147 if (!undo)
148 {
150 {
151 // save old yaw tolerance
152 auto fut = parameters_client->get_parameters(
153 {localPlannerName + ".yaw_goal_tolerance"},
154 [&](auto futureParameters)
155 {
156 auto params = futureParameters.get();
157 oldYawTolerance = params[0].as_double();
158 });
159
160 // make synchronous
161 fut.get();
162
163 yaw_goal_tolerance = rclcpp::Parameter("goal_checker.yaw_goal_tolerance", *yawGoalTolerance);
164 parameters.push_back(yaw_goal_tolerance);
165 RCLCPP_INFO_STREAM(
166 getLogger(), "[" << getName()
167 << "] updating yaw tolerance local planner to: " << *yawGoalTolerance
168 << ", from previous value: " << this->oldYawTolerance);
169 }
170
171 if (maxVelTheta)
172 {
173 if (isRosBasePlanner)
174 {
175 // save old yaw tolerance
176 auto fut = parameters_client->get_parameters(
177 {localPlannerName + ".max_vel_theta"},
178 [&](auto futureParameters)
179 {
180 auto params = futureParameters.get();
181 oldMaxVelTheta = params[0].as_double();
182 });
183
184 // make synchronous
185 fut.get();
186 }
187
188 max_vel_theta = rclcpp::Parameter(localPlannerName + ".max_vel_theta", *maxVelTheta);
189 min_vel_theta = rclcpp::Parameter(localPlannerName + ".min_vel_theta", -*maxVelTheta);
190 parameters.push_back(max_vel_theta);
191 parameters.push_back(min_vel_theta);
192
193 RCLCPP_INFO_STREAM(
194 log, "[" << getName() << "] updating max vel theta local planner to: " << *maxVelTheta
195 << ", from previous value: " << this->oldMaxVelTheta);
196 RCLCPP_INFO_STREAM(
197 log, "[" << getName() << "] updating min vel theta local planner to: " << -*maxVelTheta
198 << ", from previous value: " << this->oldMinVelTheta);
199 }
200 }
201 else
202 {
204 {
205 yaw_goal_tolerance = rclcpp::Parameter("goal_checker.yaw_goal_tolerance", oldYawTolerance);
206 RCLCPP_INFO_STREAM(
207 log, "[" << getName() << "] restoring yaw tolerance local planner from: "
208 << *yawGoalTolerance << " , to previous value: " << this->oldYawTolerance);
209 }
210
211 if (maxVelTheta)
212 {
213 if (isRosBasePlanner)
214 {
215 max_vel_theta = rclcpp::Parameter(localPlannerName + ".max_vel_theta", oldMaxVelTheta);
216 min_vel_theta = rclcpp::Parameter(localPlannerName + ".max_vel_theta", oldMinVelTheta);
217 }
218
219 parameters.push_back(max_vel_theta);
220 parameters.push_back(min_vel_theta);
221 RCLCPP_INFO_STREAM(
222 log, "[" << getName() << "] restoring max vel theta local planner from: " << *maxVelTheta
223 << ", to previous value: " << this->oldMaxVelTheta);
224 RCLCPP_INFO_STREAM(
225 log, "[" << getName() << "] restoring min vel theta local planner from: " << -(*maxVelTheta)
226 << ", to previous value: " << this->oldMinVelTheta);
227 }
228 }
229
230 if (parameters.size())
231 {
232 std::stringstream ss;
233 ss << "Executing asynchronous request. Parameters to update: " << std::endl;
234 for (auto & p : parameters)
235 {
236 ss << p.get_name() << " - " << p.value_to_string() << std::endl;
237 }
238
239 RCLCPP_INFO_STREAM(getLogger(), "[CbAbsoluteRotate] " << ss.str());
240
241 auto futureResults = parameters_client->set_parameters(parameters);
242
243 int i = 0;
244 for (auto & res : futureResults.get())
245 {
246 RCLCPP_INFO_STREAM(
247 getLogger(), "[" << getName() << "] parameter result: " << parameters[i].get_name() << "="
248 << parameters[i].as_string() << ". Result: " << res.successful);
249 i++;
250 }
251
252 RCLCPP_INFO_STREAM(log, "[" << getName() << "] parameters updated");
253 }
254 else
255 {
256 RCLCPP_INFO_STREAM(log, "[" << getName() << "] skipping parameters update");
257 }
258}
259
261{
263 {
264 }
265 else
266 {
267 }
268
270}
271
272} // namespace cl_nav2z
std::optional< float > maxVelTheta
std::optional< SpinningPlanner > spinningPlanner
void updateTemporalBehaviorParameters(bool undo)
std::shared_ptr< tf2_ros::Buffer > listener
std::optional< float > yawGoalTolerance
void sendGoal(nav2_msgs::action::NavigateToPose::Goal &goal)
void setGoalCheckerId(std::string goal_checker_id)
void setPureSpinningPlanner(bool commit=true)
void setDefaultPlanners(bool commit=true)
geometry_msgs::msg::Pose toPoseMsg()
Definition cp_pose.hpp:57
geometry_msgs::msg::PoseStamped toPoseStampedMsg()
Definition cp_pose.hpp:63
const std::string & getReferenceFrame() const
Definition cp_pose.hpp:79
void setCurrentMotionGoal(const geometry_msgs::msg::PoseStamped &pose)
void setWorkingMode(WorkingMode workingMode)
void setStartPoint(const geometry_msgs::msg::PoseStamped &pose)
virtual rclcpp::Logger getLogger() const
virtual rclcpp::Node::SharedPtr getNode() const
void requiresComponent(SmaccComponentType *&storage, ComponentRequirement requirementType=ComponentRequirement::SOFT)
virtual std::string getName()=0