SMACC2
Loading...
Searching...
No Matches
forward_local_planner.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 ******************************************************************************************************************/
21
22#include <angles/angles.h>
23#include <geometry_msgs/msg/pose_stamped.hpp>
24#include <geometry_msgs/msg/twist.hpp>
25#include <rclcpp/rclcpp.hpp>
26#include <visualization_msgs/msg/marker_array.hpp>
27
28#include <boost/intrusive_ptr.hpp>
29#include <nav_2d_utils/tf_help.hpp>
30#include <pluginlib/class_list_macros.hpp>
31
32using namespace std::chrono_literals;
33namespace cl_nav2z
34{
35namespace forward_local_planner
36{
42ForwardLocalPlanner::ForwardLocalPlanner() : transform_tolerance_(0.1), waitingTimeout_(2s) {}
43
45
47{
48 RCLCPP_DEBUG_STREAM(nh_->get_logger(), "activating controller ForwardLocalPlanner");
49 this->updateParameters();
50 this->goalMarkerPublisher_->on_activate();
51}
52
54{
55 this->cleanMarkers();
56 this->goalMarkerPublisher_->on_deactivate();
57}
58
60{
61 this->cleanMarkers();
62 this->plan_.clear();
63 this->currentPoseIndex_ = 0;
66}
67
69 const rclcpp_lifecycle::LifecycleNode::WeakPtr & node, std::string name,
70 const std::shared_ptr<tf2_ros::Buffer> tf,
71 const std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros)
72{
73 nh_ = node.lock();
74 costmapRos_ = costmap_ros;
75 tf_ = tf;
76 name_ = name;
77 k_rho_ = 1.0;
78 k_alpha_ = -0.4;
79 k_betta_ = -1.0; // set to zero means that orientation is not important
80
81 goalReached_ = false;
82 carrot_distance_ = 0.4;
87
89
90 declareOrSet(nh_, name_ + ".k_rho", k_rho_);
91 declareOrSet(nh_, name_ + ".k_alpha", k_alpha_);
92 declareOrSet(nh_, name_ + ".k_betta", k_betta_);
93 declareOrSet(nh_, name_ + ".carrot_distance", carrot_distance_);
94 declareOrSet(nh_, name_ + ".yaw_goal_tolerance", yaw_goal_tolerance_);
95 declareOrSet(nh_, name_ + ".xy_goal_tolerance", xy_goal_tolerance_);
96 declareOrSet(nh_, name_ + ".max_linear_x_speed", max_linear_x_speed_);
97 declareOrSet(nh_, name_ + ".max_angular_z_speed", max_angular_z_speed_);
98 declareOrSet(nh_, name_ + ".transform_tolerance", transform_tolerance_);
99
100 RCLCPP_DEBUG(
101 nh_->get_logger(),
102 "[ForwardLocalPlanner] max linear speed: %lf, max angular speed: %lf, k_rho: %lf, "
103 "carrot_distance: "
104 "%lf, ",
106 goalMarkerPublisher_ = nh_->create_publisher<visualization_msgs::msg::MarkerArray>(
107 "forward_local_planner/carrot_goal_marker", rclcpp::QoS(1));
108
109 waiting_ = false;
110 waitingTimeout_ = rclcpp::Duration(10s);
111}
112
114{
115 nh_->get_parameter(name_ + ".k_rho", k_rho_);
116 nh_->get_parameter(name_ + ".k_alpha", k_alpha_);
117 nh_->get_parameter(name_ + ".k_betta", k_betta_);
118 nh_->get_parameter(name_ + ".carrot_distance", carrot_distance_);
119 nh_->get_parameter(name_ + ".yaw_goal_tolerance", yaw_goal_tolerance_);
120 nh_->get_parameter(name_ + ".xy_goal_tolerance", xy_goal_tolerance_);
121 nh_->get_parameter(name_ + ".max_linear_x_speed", max_linear_x_speed_);
122 nh_->get_parameter(name_ + ".max_angular_z_speed", max_angular_z_speed_);
123 nh_->get_parameter(name_ + ".transform_tolerance", transform_tolerance_);
124
125 RCLCPP_INFO_STREAM(nh_->get_logger(), "[ForwardLocalPlanner.k_rho: " << k_rho_);
126 RCLCPP_INFO_STREAM(nh_->get_logger(), "[ForwardLocalPlanner.k_alpha: " << k_alpha_);
127 RCLCPP_INFO_STREAM(nh_->get_logger(), "[ForwardLocalPlanner.k_betta: " << k_betta_);
128 RCLCPP_INFO_STREAM(
129 nh_->get_logger(), "[ForwardLocalPlanner.carrot_distance: " << carrot_distance_);
130 RCLCPP_INFO_STREAM(
131 nh_->get_logger(), "[ForwardLocalPlanner.yaw_goal_tolerance:" << yaw_goal_tolerance_);
132 RCLCPP_INFO_STREAM(
133 nh_->get_logger(), "[ForwardLocalPlanner.xy_goal_tolerance: " << xy_goal_tolerance_);
134 RCLCPP_INFO_STREAM(
135 nh_->get_logger(), "[ForwardLocalPlanner.max_linear_x_speed:" << max_linear_x_speed_);
136 RCLCPP_INFO_STREAM(
137 nh_->get_logger(), "[ForwardLocalPlanner.max_angular_z_speed:" << max_angular_z_speed_);
138 RCLCPP_INFO_STREAM(
139 nh_->get_logger(), "[ForwardLocalPlanner.transform_tolerance:" << transform_tolerance_);
140}
141
143 const Eigen::Vector3f & pos, const Eigen::Vector3f & vel, float maxdist, float maxanglediff,
144 float maxtime, float dt, std::vector<Eigen::Vector3f> & outtraj)
145{
146 // simulate the trajectory and check for collisions, updating costs along the way
147 bool end = false;
148 float time = 0;
149 Eigen::Vector3f currentpos = pos;
150 int i = 0;
151 while (!end)
152 {
153 // add the point to the trajectory so we can draw it later if we want
154 // traj.addPoint(pos[0], pos[1], pos[2]);
155
156 auto loop_vel = vel;
157 // update the position of the robot using the velocities passed in
158 auto newpos = computeNewPositions(currentpos, loop_vel, dt);
159
160 auto dx = newpos[0] - currentpos[0];
161 auto dy = newpos[1] - currentpos[1];
162 float dist, angledist;
163
164 // RCLCPP_DEBUG(nh_->get_logger(), "traj point %d", i);
165 dist = sqrt(dx * dx + dy * dy);
166 if (dist > maxdist)
167 {
168 end = true;
169 // RCLCPP_DEBUG(nh_->get_logger(), "dist break: %f", dist);
170 }
171 else
172 {
173 // ouble from, double to
174 angledist = fabs(angles::shortest_angular_distance(currentpos[2], newpos[2]));
175 if (angledist > maxanglediff)
176 {
177 end = true;
178 // RCLCPP_DEBUG(nh_->get_logger(), "angle dist break: %f", angledist);
179 }
180 else
181 {
182 outtraj.push_back(newpos);
183
184 time += dt;
185 if (time > maxtime)
186 {
187 end = true;
188 // RCLCPP_DEBUG(nh_->get_logger(), "time break: %f", time);
189 }
190
191 // RCLCPP_DEBUG(nh_->get_logger(), "dist: %f, angledist: %f, time: %f", dist, angledist, time);
192 }
193 }
194
195 currentpos = newpos;
196 i++;
197 } // end for simulation steps
198}
199
201 const Eigen::Vector3f & pos, const Eigen::Vector3f & vel, double dt)
202{
203 Eigen::Vector3f new_pos = Eigen::Vector3f::Zero();
204 new_pos[0] = pos[0] + (static_cast<double>(vel[0]) * cos(pos[2]) +
205 static_cast<double>(vel[1]) * cos(M_PI_2 + pos[2])) *
206 dt;
207 new_pos[1] = pos[1] + (static_cast<double>(vel[0]) * sin(pos[2]) +
208 static_cast<double>(vel[1]) * sin(M_PI_2 + pos[2])) *
209 dt;
210 new_pos[2] = pos[2] + vel[2] * dt;
211 return new_pos;
212}
213
219void ForwardLocalPlanner::publishGoalMarker(double x, double y, double phi)
220{
221 visualization_msgs::msg::Marker marker;
222
223 marker.header.frame_id = costmapRos_->getGlobalFrameID();
224 marker.header.stamp = nh_->now();
225 marker.ns = "my_namespace2";
226 marker.id = 0;
227 marker.type = visualization_msgs::msg::Marker::ARROW;
228 marker.action = visualization_msgs::msg::Marker::ADD;
229 marker.pose.orientation.w = 1;
230 marker.lifetime = rclcpp::Duration(1.0s);
231
232 marker.scale.x = 0.1;
233 marker.scale.y = 0.3;
234 marker.scale.z = 0.1;
235 marker.color.a = 1.0;
236 marker.color.r = 0;
237 marker.color.g = 0;
238 marker.color.b = 1.0;
239
240 geometry_msgs::msg::Point start, end;
241 start.x = x;
242 start.y = y;
243
244 end.x = x + 0.5 * cos(phi);
245 end.y = y + 0.5 * sin(phi);
246
247 marker.points.push_back(start);
248 marker.points.push_back(end);
249
250 visualization_msgs::msg::MarkerArray ma;
251 ma.markers.push_back(marker);
252
253 goalMarkerPublisher_->publish(ma);
254}
255
257{
258 RCLCPP_INFO_STREAM(nh_->get_logger(), "[ForwardLocalPlanner] cleaning markers.");
259 visualization_msgs::msg::Marker marker;
260
261 marker.header.frame_id = costmapRos_->getGlobalFrameID();
262 marker.header.stamp = nh_->now();
263 marker.ns = "my_namespace2";
264 marker.id = 0;
265 marker.action = visualization_msgs::msg::Marker::DELETEALL;
266
267 visualization_msgs::msg::MarkerArray ma;
268 ma.markers.push_back(marker);
269
270 goalMarkerPublisher_->publish(ma);
271}
272
273void clamp(
274 rclcpp::Node::SharedPtr nh_, geometry_msgs::msg::Twist & cmd_vel, double max_linear_x_speed_,
275 double max_angular_z_speed_)
276{
277 if (max_angular_z_speed_ == 0 || max_linear_x_speed_ == 0) return;
278
279 if (cmd_vel.angular.z == 0)
280 {
281 cmd_vel.linear.x = max_linear_x_speed_;
282 }
283 else
284 {
285 double kurvature = cmd_vel.linear.x / cmd_vel.angular.z;
286
287 double linearAuthority = fabs(cmd_vel.linear.x / max_linear_x_speed_);
288 double angularAuthority = fabs(cmd_vel.angular.z / max_angular_z_speed_);
289 if (linearAuthority < angularAuthority)
290 {
291 // lets go to maximum linear speed
292 cmd_vel.linear.x = max_linear_x_speed_;
293 cmd_vel.angular.z = kurvature / max_linear_x_speed_;
294 RCLCPP_WARN_STREAM(
295 nh_->get_logger(), "k=" << kurvature << "lets go to maximum linear capacity: " << cmd_vel);
296 }
297 else
298 {
299 // lets go with maximum angular speed
300 cmd_vel.angular.x = max_angular_z_speed_;
301 cmd_vel.linear.x = kurvature * max_angular_z_speed_;
302 RCLCPP_WARN_STREAM(nh_->get_logger(), "lets go to maximum angular capacity: " << cmd_vel);
303 }
304 }
305}
306
313geometry_msgs::msg::TwistStamped ForwardLocalPlanner::computeVelocityCommands(
314 const geometry_msgs::msg::PoseStamped & currentPose,
315 const geometry_msgs::msg::Twist & /*velocity*/, nav2_core::GoalChecker * goal_checker)
316{
317 this->updateParameters();
318
319 if (this->plan_.size() > 0)
320 {
321 RCLCPP_INFO_STREAM(
322 nh_->get_logger(), "[ForwardLocalPlanner] Current pose frame id: "
323 << plan_.front().header.frame_id
324 << ", path pose frame id: " << currentPose.header.frame_id);
325
326 if (plan_.front().header.frame_id != currentPose.header.frame_id)
327 {
328 RCLCPP_ERROR_STREAM(nh_->get_logger(), "[ForwardLocalPlanner] Inconsistent frames");
329 }
330 }
331
332 // xy_goal_tolerance and yaw_goal_tolerance are just used for logging proposes and clamping the carrot
333 // goal distance (parameter safety)
334 if (xy_goal_tolerance_ == -1 || yaw_goal_tolerance_ == -1)
335 {
336 geometry_msgs::msg::Pose posetol;
337 geometry_msgs::msg::Twist twistol;
338 if (goal_checker->getTolerances(posetol, twistol))
339 {
340 xy_goal_tolerance_ = posetol.position.x;
341 yaw_goal_tolerance_ = tf2::getYaw(posetol.orientation);
342 //xy_goal_tolerance_ = posetol.position.x * 0.35; // WORKAROUND DIFFERENCE WITH NAV CONTROLLER GOAL CHECKER
343 //yaw_goal_tolerance_ = tf2::getYaw(posetol.orientation) * 0.35;
344 RCLCPP_INFO_STREAM(
345 nh_->get_logger(), "[ForwardLocalPlanner] xy_goal_tolerance_: " << xy_goal_tolerance_
346 << ", yaw_goal_tolerance_: "
348 }
349 else
350 {
351 RCLCPP_INFO_STREAM(
352 nh_->get_logger(), "[ForwardLocalPlanner] could not get tolerances from goal checker");
353 }
354 }
355
356 geometry_msgs::msg::TwistStamped cmd_vel;
357 goalReached_ = false;
358 RCLCPP_DEBUG(
359 nh_->get_logger(), "[ForwardLocalPlanner] ----- COMPUTE VELOCITY COMMAND LOCAL PLANNER ---");
360
361 bool ok = false;
362 while (!ok)
363 {
364 // iterate the point from the current position and ahead until reaching a new goal point in the path
365 while (!ok && currentPoseIndex_ < (int)plan_.size())
366 {
367 auto & pose = plan_[currentPoseIndex_];
368 const geometry_msgs::msg::Point & p = pose.pose.position;
369 tf2::Quaternion q;
370 tf2::fromMsg(pose.pose.orientation, q);
371
372 // take error from the current position to the path point
373 double dx = p.x - currentPose.pose.position.x;
374 double dy = p.y - currentPose.pose.position.y;
375 double dist = sqrt(dx * dx + dy * dy);
376
377 double pangle = tf2::getYaw(q);
378 double angle = tf2::getYaw(currentPose.pose.orientation);
379 double angular_error = angles::shortest_angular_distance(pangle, angle);
380
381 if (dist >= carrot_distance_ || fabs(angular_error) > 0.1)
382 {
383 // the target pose is enough different to be defined as a target
384 ok = true;
385 RCLCPP_DEBUG(
386 nh_->get_logger(),
387 "current index: %d, carrot goal percentaje: %lf, dist: %lf, maxdist: %lf, angle_error: "
388 "%lf",
390 angular_error);
391 }
392 else
393 {
395 }
396 }
397
398 RCLCPP_DEBUG_STREAM(
399 nh_->get_logger(), "[ForwardLocalPlanner] selected carrot pose index "
400 << currentPoseIndex_ << "/" << plan_.size());
401
402 if (currentPoseIndex_ >= (int)plan_.size())
403 {
404 // even the latest point is quite similar, then take the last since it is the final goal
405 cmd_vel.twist.linear.x = 0;
406 cmd_vel.twist.angular.z = 0;
407 // RCLCPP_INFO(nh_->get_logger(), "End Local planner");
408 ok = true;
409 currentPoseIndex_ = (int)plan_.size() - 1;
410 }
411 }
412
413 // RCLCPP_INFO(nh_->get_logger(), "pose control algorithm");
414
415 const geometry_msgs::msg::PoseStamped & finalgoalpose = plan_.back();
416 const geometry_msgs::msg::PoseStamped & carrot_goalpose = plan_[currentPoseIndex_];
417 const geometry_msgs::msg::Point & goalposition = carrot_goalpose.pose.position;
418
419 tf2::Quaternion carrotGoalQ;
420 tf2::fromMsg(carrot_goalpose.pose.orientation, carrotGoalQ);
421 // RCLCPP_INFO_STREAM(nh_->get_logger(), "Plan goal quaternion at "<< carrot_goalpose.pose.orientation);
422
423 // goal orientation (global frame)
424 double betta = tf2::getYaw(carrot_goalpose.pose.orientation) + betta_offset_;
425 double dx = goalposition.x - currentPose.pose.position.x;
426 double dy = goalposition.y - currentPose.pose.position.y;
427
428 // distance error to the targetpoint
429 double rho_error = sqrt(dx * dx + dy * dy);
430
431 tf2::Quaternion currentOrientation;
432 tf2::convert(currentPose.pose.orientation, currentOrientation);
433
434 // current angle
435 double theta = tf2::getYaw(currentOrientation);
436 double alpha = atan2(dy, dx);
437 alpha = alpha + alpha_offset_;
438
439 double alpha_error = angles::shortest_angular_distance(alpha, theta);
440 double betta_error = angles::shortest_angular_distance(betta, theta);
441
442 double vetta = 0; // = k_rho_ * rho_error;
443 double gamma = 0; //= k_alpha_ * alpha_error + k_betta_ * betta_error;
444
445 if (
446 rho_error >
447 xy_goal_tolerance_) // regular control rule, be careful, rho error is with the carrot not with the
448 // final goal (this is something to improve like the backwards planner)
449 {
450 vetta = k_rho_ * rho_error;
451 gamma = k_alpha_ * alpha_error;
452 }
453 else if (fabs(betta_error) >= yaw_goal_tolerance_) // pureSpining
454 {
455 vetta = 0;
456 gamma = k_betta_ * betta_error;
457 }
458 else // goal reached
459 {
460 RCLCPP_DEBUG(nh_->get_logger(), "GOAL REACHED");
461 vetta = 0;
462 gamma = 0;
463 goalReached_ = true;
464 }
465
466 // linear speed clamp
467 if (vetta > max_linear_x_speed_)
468 {
469 vetta = max_linear_x_speed_;
470 }
471 else if (vetta < -max_linear_x_speed_)
472 {
473 vetta = -max_linear_x_speed_;
474 }
475
476 // angular speed clamp
477 if (gamma > max_angular_z_speed_)
478 {
479 gamma = max_angular_z_speed_;
480 }
481 else if (gamma < -max_angular_z_speed_)
482 {
483 gamma = -max_angular_z_speed_;
484 }
485
486 cmd_vel.twist.linear.x = vetta;
487 cmd_vel.twist.angular.z = gamma;
488
489 publishGoalMarker(goalposition.x, goalposition.y, betta);
490
491 RCLCPP_DEBUG_STREAM(
492 nh_->get_logger(), "Forward local planner,"
493 << std::endl
494 << " theta: " << theta << std::endl
495 << " betta: " << betta << std::endl
496 << " err_x: " << dx << std::endl
497 << " err_y:" << dy << std::endl
498 << " rho_error:" << rho_error << std::endl
499 << " alpha_error:" << alpha_error << std::endl
500 << " betta_error:" << betta_error << std::endl
501 << " vetta:" << vetta << std::endl
502 << " gamma:" << gamma << std::endl
503 << " xy_goal_tolerance:" << xy_goal_tolerance_ << std::endl
504 << " yaw_goal_tolerance:" << yaw_goal_tolerance_ << std::endl);
505
506 // integrate trajectory and check collision
507
508 assert(currentPose.header.frame_id == "odom" || currentPose.header.frame_id == "map");
509 auto global_pose = currentPose;
510
511 auto * costmap2d = costmapRos_->getCostmap();
512 auto yaw = tf2::getYaw(global_pose.pose.orientation);
513
514 auto & pos = global_pose.pose.position;
515
516 Eigen::Vector3f currentpose(pos.x, pos.y, yaw);
517 Eigen::Vector3f currentvel(
518 cmd_vel.twist.linear.x, cmd_vel.twist.linear.y, cmd_vel.twist.angular.z);
519
520 std::vector<Eigen::Vector3f> trajectory;
521 this->generateTrajectory(
522 currentpose, currentvel, 0.8 /*meters*/, M_PI / 8 /*rads*/, 3.0 /*seconds*/, 0.05 /*seconds*/,
523 trajectory);
524
525 // check plan rejection
526 bool aceptedplan = true;
527
528 unsigned int mx, my;
529
530 int i = 0;
531 // RCLCPP_INFO_STREAM(nh_->get_logger(), "lplanner goal: " << finalgoalpose.pose.position);
532 for (auto & p : trajectory)
533 {
534 float dx = p[0] - finalgoalpose.pose.position.x;
535 float dy = p[1] - finalgoalpose.pose.position.y;
536
537 float dst = sqrt(dx * dx + dy * dy);
538 if (dst < xy_goal_tolerance_)
539 {
540 // RCLCPP_INFO(nh_->get_logger(), "trajectory checking skipped, goal reached");
541 break;
542 }
543
544 costmap2d->worldToMap(p[0], p[1], mx, my);
545
546 // RCLCPP_INFO(nh_->get_logger(), "checking cost pt %d [%lf, %lf] cell[%d,%d] = %d", i, p[0], p[1], mx, my, cost);
547 // RCLCPP_INFO_STREAM(nh_->get_logger(), "cost: " << cost);
548
549 // static const unsigned char NO_INFORMATION = 255;
550 // static const unsigned char LETHAL_OBSTACLE = 254;
551 // static const unsigned char INSCRIBED_INFLATED_OBSTACLE = 253;
552 // static const unsigned char FREE_SPACE = 0;
553
554 if (costmap2d->getCost(mx, my) >= nav2_costmap_2d::INSCRIBED_INFLATED_OBSTACLE)
555 {
556 aceptedplan = false;
557 // RCLCPP_WARN(nh_->get_logger(), "ABORTED LOCAL PLAN BECAUSE OBSTACLE DETEDTED");
558 break;
559 }
560 i++;
561 }
562
563 bool success = false;
564 if (aceptedplan)
565 {
566 waiting_ = false;
567 success = true;
568 RCLCPP_DEBUG(nh_->get_logger(), "simulated trajectory is accepted.");
569 }
570 else
571 {
572 RCLCPP_DEBUG(nh_->get_logger(), "simulated trajectory is not accepted. Stop command.");
573
574 // stop and wait
575 cmd_vel.twist.linear.x = 0;
576 cmd_vel.twist.angular.z = 0;
577
578 if (!waiting_)
579 {
580 RCLCPP_DEBUG(nh_->get_logger(), "Start waiting obstacle disappear");
581 waiting_ = true;
582 waitingStamp_ = nh_->now();
583 }
584 else
585 {
586 auto waitingduration = nh_->now() - waitingStamp_;
587 RCLCPP_DEBUG(
588 nh_->get_logger(), "waiting obstacle disappear, elapsed: %lf seconds",
589 waitingduration.seconds());
590
591 if (waitingduration > this->waitingTimeout_)
592 {
593 RCLCPP_WARN(
594 nh_->get_logger(), "TIMEOUT waiting obstacle disappear, elapsed: %lf seconds",
595 waitingduration.seconds());
596 success = false;
597 }
598 }
599 }
600
601 if (!success)
602 {
603 RCLCPP_DEBUG(
604 nh_->get_logger(),
605 "[ForwardLocalPlanner] object detected waiting stopped until it disappears.");
606 }
607
608 cmd_vel.header.stamp = nh_->now();
609 return cmd_vel;
610}
611
612void ForwardLocalPlanner::setSpeedLimit(const double & /*speed_limit*/, const bool & /*percentage*/)
613{
614 RCLCPP_WARN_STREAM(
615 nh_->get_logger(),
616 "ForwardLocalPlanner::setSpeedLimit invoked. Ignored, functionality not "
617 "implemented.");
618}
619
626
632void ForwardLocalPlanner::setPlan(const nav_msgs::msg::Path & plan)
633{
634 nav_msgs::msg::Path transformedPlan;
635
636 rclcpp::Duration ttol = rclcpp::Duration::from_seconds(transform_tolerance_);
637 // transform global plan
638 for (auto & p : plan.poses)
639 {
640 geometry_msgs::msg::PoseStamped transformedPose;
641 nav_2d_utils::transformPose(tf_, costmapRos_->getGlobalFrameID(), p, transformedPose, ttol);
642 transformedPose.header.frame_id = costmapRos_->getGlobalFrameID();
643 transformedPlan.poses.push_back(transformedPose);
644 }
645
646 plan_ = transformedPlan.poses;
647 goalReached_ = false;
648}
649} // namespace forward_local_planner
650} // namespace cl_nav2z
651PLUGINLIB_EXPORT_CLASS(cl_nav2z::forward_local_planner::ForwardLocalPlanner, nav2_core::Controller)
std::vector< geometry_msgs::msg::PoseStamped > plan_
std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmapRos_
Eigen::Vector3f computeNewPositions(const Eigen::Vector3f &pos, const Eigen::Vector3f &vel, double dt)
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 generateTrajectory(const Eigen::Vector3f &pos, const Eigen::Vector3f &vel, float maxdist, float maxangle, float maxtime, float dt, std::vector< Eigen::Vector3f > &outtraj)
virtual void setSpeedLimit(const double &speed_limit, const bool &percentage) override
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
void setPlan(const nav_msgs::msg::Path &path) override
nav2_core setPlan - Sets the global plan
rclcpp_lifecycle::LifecyclePublisher< visualization_msgs::msg::MarkerArray >::SharedPtr goalMarkerPublisher_
void declareOrSet(rclcpp_lifecycle::LifecycleNode::SharedPtr &node, std::string param, T &value)
Definition common.hpp:34
void clamp(rclcpp::Node::SharedPtr nh_, geometry_msgs::msg::Twist &cmd_vel, double max_linear_x_speed_, double max_angular_z_speed_)