15 #ifndef NAV2_SMAC_PLANNER__SMAC_PLANNER_LATTICE_IMPL_HPP_
16 #define NAV2_SMAC_PLANNER__SMAC_PLANNER_LATTICE_IMPL_HPP_
26 #include "nav2_ros_common/node_utils.hpp"
27 #include "nav2_smac_planner/smac_planner_lattice.hpp"
28 #include "nav2_ros_common/tf2_factories.hpp"
32 namespace nav2_smac_planner
35 using namespace std::chrono;
36 using rcl_interfaces::msg::ParameterType;
38 template<
typename NodeT>
41 _collision_checker(nullptr, 1, nullptr),
47 template<
typename NodeT>
51 _logger,
"Destroying plugin %s of type SmacPlannerLattice",
55 template<
typename NodeT>
57 const nav2::LifecycleNode::WeakPtr & parent,
58 std::string name, nav2::TransformBuffer::SharedPtr,
59 std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros)
62 auto node = parent.lock();
63 _logger = node->get_logger();
64 _clock = node->get_clock();
65 _costmap = costmap_ros->getCostmap();
66 _costmap_ros = costmap_ros;
68 _global_frame = costmap_ros->getGlobalFrameID();
70 RCLCPP_INFO(_logger,
"Configuring %s of type SmacPlannerLattice", name.c_str());
73 double analytic_expansion_max_length_m;
75 _tolerance =
static_cast<float>(node->declare_or_get_parameter(name +
".tolerance", 0.25));
76 _allow_unknown = node->declare_or_get_parameter(name +
".allow_unknown",
true);
77 _max_iterations = node->declare_or_get_parameter(name +
".max_iterations", 1000000);
78 _max_on_approach_iterations =
79 node->declare_or_get_parameter(name +
".max_on_approach_iterations", 1000);
80 _terminal_checking_interval =
81 node->declare_or_get_parameter(name +
".terminal_checking_interval", 5000);
82 bool smooth_path = node->declare_or_get_parameter(name +
".smooth_path",
true);
85 _search_info.lattice_filepath = node->declare_or_get_parameter(
86 name +
".lattice_filepath",
87 nav2::get_package_share_directory(
"nav2_smac_planner") +
88 "/sample_primitives/5cm_resolution/0.5m_turning_radius/ackermann/output.json");
89 _search_info.cache_obstacle_heuristic =
90 node->declare_or_get_parameter(name +
".cache_obstacle_heuristic",
false);
91 _search_info.reverse_penalty =
92 node->declare_or_get_parameter(name +
".reverse_penalty", 2.0);
93 _search_info.change_penalty =
94 node->declare_or_get_parameter(name +
".change_penalty", 0.05);
95 _search_info.non_straight_penalty =
96 node->declare_or_get_parameter(name +
".non_straight_penalty", 1.05);
97 _search_info.cost_penalty =
98 node->declare_or_get_parameter(name +
".cost_penalty", 2.0);
99 _search_info.retrospective_penalty =
100 node->declare_or_get_parameter(name +
".retrospective_penalty", 0.015);
101 _search_info.rotation_penalty =
102 node->declare_or_get_parameter(name +
".rotation_penalty", 5.0);
103 _search_info.analytic_expansion_ratio =
104 node->declare_or_get_parameter(name +
".analytic_expansion_ratio", 3.5);
105 _search_info.analytic_expansion_max_cost =
106 node->declare_or_get_parameter(name +
".analytic_expansion_max_cost", 200.0);
107 _search_info.analytic_expansion_max_cost_override =
108 node->declare_or_get_parameter(name +
".analytic_expansion_max_cost_override",
false);
109 analytic_expansion_max_length_m =
110 node->declare_or_get_parameter(name +
".analytic_expansion_max_length", 3.0);
111 _search_info.analytic_expansion_max_length =
112 analytic_expansion_max_length_m / _costmap->getResolution();
113 _search_info.use_quadratic_cost_penalty =
114 node->declare_or_get_parameter(name +
".use_quadratic_cost_penalty",
false);
115 _search_info.downsample_obstacle_heuristic =
116 node->declare_or_get_parameter(name +
".downsample_obstacle_heuristic",
true);
118 _max_planning_time = node->declare_or_get_parameter(name +
".max_planning_time", 5.0);
119 _lookup_table_size = node->declare_or_get_parameter(name +
".lookup_table_size", 20.0);
120 _search_info.allow_reverse_expansion =
121 node->declare_or_get_parameter(name +
".allow_reverse_expansion",
false);
122 _debug_visualizations = node->declare_or_get_parameter(name +
".debug_visualizations",
false);
124 std::string goal_heading_type =
125 node->declare_or_get_parameter(name +
".goal_heading_mode", std::string(
"DEFAULT"));
126 _goal_heading_mode = fromStringToGH(goal_heading_type);
128 _coarse_search_resolution =
129 node->declare_or_get_parameter(name +
".coarse_search_resolution", 1);
131 if (_goal_heading_mode == GoalHeadingMode::UNKNOWN) {
132 std::string error_msg =
"Unable to get GoalHeader type. Given '" + goal_heading_type +
"' "
133 "Valid options are DEFAULT, BIDIRECTIONAL, ALL_DIRECTION. ";
138 _search_info.minimum_turning_radius =
139 _metadata.min_turning_radius / (_costmap->getResolution());
140 _motion_model = MotionModel::STATE_LATTICE;
142 if (_metadata.motion_model ==
"omni" && _search_info.allow_reverse_expansion) {
145 "allow_reverse_expansion is not applicable for omnidirectional robots. Disabling.");
146 _search_info.allow_reverse_expansion =
false;
149 if (_max_on_approach_iterations <= 0) {
151 _logger,
"On approach iteration selected as <= 0, "
152 "disabling tolerance and on approach iterations.");
153 _max_on_approach_iterations = std::numeric_limits<int>::max();
156 if (_max_iterations <= 0) {
158 _logger,
"maximum iteration selected as <= 0, "
159 "disabling maximum iterations.");
160 _max_iterations = std::numeric_limits<int>::max();
163 if (_coarse_search_resolution <= 0) {
165 _logger,
"coarse iteration resolution selected as <= 0, "
166 "disabling coarse iteration resolution search for goal heading"
168 _coarse_search_resolution = 1;
171 if (_metadata.number_of_headings % _coarse_search_resolution != 0) {
172 std::string error_msg =
"coarse iteration should be an increment of"
173 " the number of angular bins configured";
177 float lookup_table_dim =
178 static_cast<float>(_lookup_table_size) /
179 static_cast<float>(_costmap->getResolution());
182 lookup_table_dim =
static_cast<float>(
static_cast<int>(lookup_table_dim));
185 if (
static_cast<int>(lookup_table_dim) % 2 == 0) {
188 "Even sized heuristic lookup table size set %f, increasing size by 1 to make odd",
190 lookup_table_dim += 1.0;
201 _collision_checker.setFootprint(
202 costmap_ros->getRobotFootprint(),
203 costmap_ros->getUseRadius(),
204 findCircumscribedCost(costmap_ros));
207 _a_star = std::make_unique<AStarAlgorithm<NodeT>>(_motion_model, _search_info);
211 _max_on_approach_iterations,
212 _terminal_checking_interval,
215 _metadata.number_of_headings);
219 params.
get(node, name);
220 if (_metadata.motion_model ==
"omni") {
221 params.holonomic_ =
true;
224 _smoother = std::make_unique<Smoother>(params);
225 _smoother->initialize(_metadata.min_turning_radius);
228 _raw_plan_publisher = node->create_publisher<nav_msgs::msg::Path>(
"unsmoothed_plan");
230 if (_debug_visualizations) {
231 _expansions_publisher = node->create_publisher<geometry_msgs::msg::PoseArray>(
"expansions");
232 _planned_footprints_publisher = node->create_publisher<visualization_msgs::msg::MarkerArray>(
233 "planned_footprints");
234 _smoothed_footprints_publisher =
235 node->create_publisher<visualization_msgs::msg::MarkerArray>(
236 "smoothed_footprints");
240 _logger,
"Configured plugin %s of type SmacPlannerLattice with "
241 "maximum iterations %i, max on approach iterations %i, "
242 "and %s. Tolerance %.2f. Using motion model: %s. State lattice file: %s.",
243 _name.c_str(), _max_iterations, _max_on_approach_iterations,
244 _allow_unknown ?
"allowing unknown traversal" :
"not allowing unknown traversal",
245 _tolerance, toString(_motion_model).c_str(), _search_info.lattice_filepath.c_str());
248 template<
typename NodeT>
252 _logger,
"Activating plugin %s of type SmacPlannerLattice",
254 _raw_plan_publisher->on_activate();
255 if (_debug_visualizations) {
256 _expansions_publisher->on_activate();
257 _planned_footprints_publisher->on_activate();
258 _smoothed_footprints_publisher->on_activate();
260 auto node = _node.lock();
262 _post_set_params_handler = node->add_post_set_parameters_callback(
265 this, std::placeholders::_1));
266 _on_set_params_handler = node->add_on_set_parameters_callback(
269 this, std::placeholders::_1));
272 template<
typename NodeT>
276 _logger,
"Deactivating plugin %s of type SmacPlannerLattice",
278 _raw_plan_publisher->on_deactivate();
279 if (_debug_visualizations) {
280 _expansions_publisher->on_deactivate();
281 _planned_footprints_publisher->on_deactivate();
282 _smoothed_footprints_publisher->on_deactivate();
285 auto node = _node.lock();
286 if (_post_set_params_handler && node) {
287 node->remove_post_set_parameters_callback(_post_set_params_handler.get());
289 _post_set_params_handler.reset();
290 if (_on_set_params_handler && node) {
291 node->remove_on_set_parameters_callback(_on_set_params_handler.get());
293 _on_set_params_handler.reset();
296 template<
typename NodeT>
300 _logger,
"Cleaning up plugin %s of type SmacPlannerLattice",
304 _raw_plan_publisher.reset();
305 if (_debug_visualizations) {
306 _expansions_publisher.reset();
307 _planned_footprints_publisher.reset();
308 _smoothed_footprints_publisher.reset();
312 template<
typename NodeT>
314 const geometry_msgs::msg::PoseStamped & start,
315 const geometry_msgs::msg::PoseStamped & goal,
316 const std::vector<geometry_msgs::msg::PoseStamped> & viapoints,
317 std::function<
bool()> cancel_checker)
319 if (!viapoints.empty()) {
320 RCLCPP_WARN(_logger,
"Received %zu viapoints, but this planner ignores them",
324 std::lock_guard<std::mutex> lock_reinit(_mutex);
325 steady_clock::time_point a = steady_clock::now();
327 std::unique_lock<nav2_costmap_2d::Costmap2D::mutex_t> lock(*(_costmap->getMutex()));
330 _collision_checker.setFootprint(
331 _costmap_ros->getRobotFootprint(),
332 _costmap_ros->getUseRadius(),
333 findCircumscribedCost(_costmap_ros));
334 _a_star->setCollisionChecker(&_collision_checker);
337 float mx_start, my_start, mx_goal, my_goal;
338 if (!_costmap->worldToMapContinuous(
339 start.pose.position.x,
340 start.pose.position.y,
345 "Start Coordinates of(" + std::to_string(start.pose.position.x) +
", " +
346 std::to_string(start.pose.position.y) +
") was outside bounds");
348 unsigned int start_bin =
349 _a_star->getContext()->motion_table.getClosestAngularBin(tf2::getYaw(start.pose.orientation));
350 _a_star->setStart(mx_start, my_start, start_bin);
353 if (!_costmap->worldToMapContinuous(
354 goal.pose.position.x,
355 goal.pose.position.y,
360 "Goal Coordinates of(" + std::to_string(goal.pose.position.x) +
", " +
361 std::to_string(goal.pose.position.y) +
") was outside bounds");
363 unsigned int goal_bin =
364 _a_star->getContext()->motion_table.getClosestAngularBin(tf2::getYaw(goal.pose.orientation));
366 mx_goal, my_goal, goal_bin,
367 _goal_heading_mode, _coarse_search_resolution);
370 nav_msgs::msg::Path plan;
371 plan.header.stamp = _clock->now();
372 plan.header.frame_id = _global_frame;
373 geometry_msgs::msg::PoseStamped pose;
374 pose.header = plan.header;
375 pose.pose.position.z = 0.0;
376 pose.pose.orientation.x = 0.0;
377 pose.pose.orientation.y = 0.0;
378 pose.pose.orientation.z = 0.0;
379 pose.pose.orientation.w = 1.0;
382 if (std::floor(mx_start) == std::floor(mx_goal) &&
383 std::floor(my_start) == std::floor(my_goal) &&
384 start_bin == goal_bin)
386 pose.pose = start.pose;
387 pose.pose.orientation = goal.pose.orientation;
388 plan.poses.push_back(pose);
391 if (_raw_plan_publisher->get_subscription_count() > 0) {
392 auto msg = std::make_unique<nav_msgs::msg::Path>(plan);
393 _raw_plan_publisher->publish(std::move(msg));
400 typename NodeT::CoordinateVector path;
401 int num_iterations = 0;
403 std::unique_ptr<std::vector<std::tuple<float, float, float>>> expansions =
nullptr;
404 if (_debug_visualizations) {
405 expansions = std::make_unique<std::vector<std::tuple<float, float, float>>>();
409 if (!_a_star->createPath(
410 path, num_iterations,
411 _tolerance /
static_cast<float>(_costmap->getResolution()), cancel_checker, expansions.get()))
413 if (_debug_visualizations) {
414 auto now = _clock->now();
415 auto msg = std::make_unique<geometry_msgs::msg::PoseArray>();
416 geometry_msgs::msg::Pose msg_pose;
417 msg->header.stamp = now;
418 msg->header.frame_id = _global_frame;
419 for (
auto & e : *expansions) {
420 msg_pose.position.x = std::get<0>(e);
421 msg_pose.position.y = std::get<1>(e);
422 msg_pose.orientation = getWorldOrientation(std::get<2>(e));
423 msg->poses.push_back(msg_pose);
425 _expansions_publisher->publish(std::move(msg));
429 if (num_iterations == 1) {
433 if (num_iterations < _a_star->getMaxIterations()) {
441 plan.poses.reserve(path.size());
442 geometry_msgs::msg::PoseStamped last_pose = pose;
443 for (
int i = path.size() - 1; i >= 0; --i) {
444 pose.pose = getWorldCoords(path[i].x, path[i].y, _costmap);
445 pose.pose.orientation = getWorldOrientation(path[i].theta);
446 if (fabs(pose.pose.position.x - last_pose.pose.position.x) < 1e-4 &&
447 fabs(pose.pose.position.y - last_pose.pose.position.y) < 1e-4 &&
448 fabs(tf2::getYaw(pose.pose.orientation) - tf2::getYaw(last_pose.pose.orientation)) < 1e-4)
452 "Removed a path from the path due to replication. "
453 "Make sure your minimum control set does not contain duplicate values!");
457 plan.poses.push_back(pose);
461 if (_raw_plan_publisher->get_subscription_count() > 0) {
462 auto msg = std::make_unique<nav_msgs::msg::Path>(plan);
463 _raw_plan_publisher->publish(std::move(msg));
466 if (_debug_visualizations) {
467 auto now = _clock->now();
469 auto msg = std::make_unique<geometry_msgs::msg::PoseArray>();
470 geometry_msgs::msg::Pose msg_pose;
471 msg->header.stamp = now;
472 msg->header.frame_id = _global_frame;
473 for (
auto & e : *expansions) {
474 msg_pose.position.x = std::get<0>(e);
475 msg_pose.position.y = std::get<1>(e);
476 msg_pose.orientation = getWorldOrientation(std::get<2>(e));
477 msg->poses.push_back(msg_pose);
479 _expansions_publisher->publish(std::move(msg));
481 if (_planned_footprints_publisher->get_subscription_count() > 0) {
483 auto marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
484 visualization_msgs::msg::Marker clear_all_marker;
485 clear_all_marker.action = visualization_msgs::msg::Marker::DELETEALL;
486 marker_array->markers.push_back(clear_all_marker);
487 _planned_footprints_publisher->publish(std::move(marker_array));
490 marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
491 for (
size_t i = 0; i < plan.poses.size(); i++) {
492 const std::vector<geometry_msgs::msg::Point> edge =
493 transformFootprintToEdges(plan.poses[i].pose, _costmap_ros->getRobotFootprint());
494 marker_array->markers.push_back(createMarker(edge, i, _global_frame, now));
496 _planned_footprints_publisher->publish(std::move(marker_array));
501 steady_clock::time_point b = steady_clock::now();
502 duration<double> time_span = duration_cast<duration<double>>(b - a);
503 double time_remaining = _max_planning_time -
static_cast<double>(time_span.count());
505 #ifdef BENCHMARK_TESTING
506 std::cout <<
"It took " << time_span.count() * 1000 <<
507 " milliseconds with " << num_iterations <<
" iterations." << std::endl;
511 if (_smoother && num_iterations > 1) {
516 _costmap_ros->getUseRadius() ? std::vector<geometry_msgs::msg::Point>() :
517 _costmap_ros->getRobotFootprint());
520 #ifdef BENCHMARK_TESTING
521 steady_clock::time_point c = steady_clock::now();
522 duration<double> time_span2 = duration_cast<duration<double>>(c - b);
523 std::cout <<
"It took " << time_span2.count() * 1000 <<
524 " milliseconds to smooth path." << std::endl;
527 if (_debug_visualizations) {
528 if (_smoothed_footprints_publisher->get_subscription_count() > 0) {
530 auto marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
531 visualization_msgs::msg::Marker clear_all_marker;
532 clear_all_marker.action = visualization_msgs::msg::Marker::DELETEALL;
533 marker_array->markers.push_back(clear_all_marker);
534 _smoothed_footprints_publisher->publish(std::move(marker_array));
537 marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
538 auto now = _clock->now();
539 for (
size_t i = 0; i < plan.poses.size(); i++) {
540 const std::vector<geometry_msgs::msg::Point> edge =
541 transformFootprintToEdges(plan.poses[i].pose, _costmap_ros->getRobotFootprint());
542 marker_array->markers.push_back(createMarker(edge, i, _global_frame, now));
544 _smoothed_footprints_publisher->publish(std::move(marker_array));
551 template<
typename NodeT>
552 rcl_interfaces::msg::SetParametersResult
554 const std::vector<rclcpp::Parameter> & parameters)
556 rcl_interfaces::msg::SetParametersResult result;
557 result.successful =
true;
558 for (
const auto & parameter : parameters) {
559 const auto & param_type = parameter.get_type();
560 const auto & param_name = parameter.get_name();
561 if (param_name.find(_name +
".") != 0) {
564 if (param_type == ParameterType::PARAMETER_DOUBLE) {
565 if (parameter.as_double() < 0.0) {
567 _logger,
"The value of parameter '%s' is incorrectly set to %f, "
568 "it should be >=0. Ignoring parameter update.",
569 param_name.c_str(), parameter.as_double());
570 result.successful =
false;
572 }
else if (param_type == ParameterType::PARAMETER_INTEGER) {
573 if (param_name == _name +
".coarse_search_resolution" && _metadata.number_of_headings %
574 parameter.as_int() != 0)
578 "coarse iteration should be an increment of the number"
579 " of angular bins configured. Ignoring parameter update!"
581 result.successful =
false;
582 }
else if (parameter.as_int() <= 0 && (param_name != _name +
".max_iterations" &&
583 param_name != _name +
".max_on_approach_iterations"))
586 _logger,
"The value of parameter '%s' is incorrectly set to %ld, "
587 "it should be >0. Ignoring parameter update.",
588 param_name.c_str(), parameter.as_int());
589 result.successful =
false;
591 }
else if (param_type == ParameterType::PARAMETER_STRING) {
592 if (param_name == _name +
".lattice_filepath") {
595 if (metadata.number_of_headings % _coarse_search_resolution != 0) {
598 "coarse iteration should be an increment of the number "
599 "of angular bins configured. Ignoring parameter update!"
601 result.successful =
false;
603 }
else if (param_name == _name +
".goal_heading_mode") {
604 GoalHeadingMode goal_heading_mode = fromStringToGH(parameter.as_string());
605 if (goal_heading_mode == GoalHeadingMode::UNKNOWN) {
608 "Unable to get GoalHeader type. Given '%s' Valid options are "
609 "DEFAULT, BIDIRECTIONAL, ALL_DIRECTION. Ignoring parameter update!",
610 parameter.as_string().c_str());
611 result.successful =
false;
619 template<
typename NodeT>
622 const std::vector<rclcpp::Parameter> & parameters)
624 std::lock_guard<std::mutex> lock_reinit(_mutex);
626 bool reinit_a_star =
false;
627 bool reinit_lookup_table =
false;
628 bool reinit_smoother =
false;
630 for (
auto parameter : parameters) {
631 const auto & param_type = parameter.get_type();
632 const auto & param_name = parameter.get_name();
633 if (param_name.find(_name +
".") != 0) {
636 if (param_type == ParameterType::PARAMETER_DOUBLE) {
637 if (param_name == _name +
".max_planning_time") {
638 reinit_a_star =
true;
639 _max_planning_time = parameter.as_double();
640 }
else if (param_name == _name +
".tolerance") {
641 _tolerance =
static_cast<float>(parameter.as_double());
642 }
else if (param_name == _name +
".lookup_table_size") {
643 reinit_a_star =
true;
644 reinit_lookup_table =
true;
645 _lookup_table_size = parameter.as_double();
646 }
else if (param_name == _name +
".reverse_penalty") {
647 reinit_a_star =
true;
648 _search_info.reverse_penalty =
static_cast<float>(parameter.as_double());
649 }
else if (param_name == _name +
".change_penalty") {
650 reinit_a_star =
true;
651 _search_info.change_penalty =
static_cast<float>(parameter.as_double());
652 }
else if (param_name == _name +
".non_straight_penalty") {
653 reinit_a_star =
true;
654 _search_info.non_straight_penalty =
static_cast<float>(parameter.as_double());
655 }
else if (param_name == _name +
".cost_penalty") {
656 reinit_a_star =
true;
657 _search_info.cost_penalty =
static_cast<float>(parameter.as_double());
658 }
else if (param_name == _name +
".rotation_penalty") {
659 reinit_a_star =
true;
660 _search_info.rotation_penalty =
static_cast<float>(parameter.as_double());
661 }
else if (param_name == _name +
".analytic_expansion_ratio") {
662 reinit_a_star =
true;
663 _search_info.analytic_expansion_ratio =
static_cast<float>(parameter.as_double());
664 }
else if (param_name == _name +
".analytic_expansion_max_length") {
665 reinit_a_star =
true;
666 _search_info.analytic_expansion_max_length =
667 static_cast<float>(parameter.as_double()) / _costmap->getResolution();
668 }
else if (param_name == _name +
".analytic_expansion_max_cost") {
669 reinit_a_star =
true;
670 _search_info.analytic_expansion_max_cost =
static_cast<float>(parameter.as_double());
672 }
else if (param_type == ParameterType::PARAMETER_BOOL) {
673 if (param_name == _name +
".allow_unknown") {
674 reinit_a_star =
true;
675 _allow_unknown = parameter.as_bool();
676 }
else if (param_name == _name +
".cache_obstacle_heuristic") {
677 reinit_a_star =
true;
678 _search_info.cache_obstacle_heuristic = parameter.as_bool();
679 }
else if (param_name == _name +
".allow_reverse_expansion") {
680 reinit_a_star =
true;
681 reinit_lookup_table =
true;
682 _search_info.allow_reverse_expansion = parameter.as_bool();
683 }
else if (param_name == _name +
".smooth_path") {
684 if (parameter.as_bool()) {
685 reinit_smoother =
true;
689 }
else if (param_name == _name +
".analytic_expansion_max_cost_override") {
690 _search_info.analytic_expansion_max_cost_override = parameter.as_bool();
691 reinit_a_star =
true;
693 }
else if (param_type == ParameterType::PARAMETER_INTEGER) {
694 if (param_name == _name +
".max_iterations") {
695 reinit_a_star =
true;
696 _max_iterations = parameter.as_int();
697 if (_max_iterations <= 0) {
699 _logger,
"maximum iteration selected as <= 0, "
700 "disabling maximum iterations.");
701 _max_iterations = std::numeric_limits<int>::max();
703 }
else if (param_name == _name +
".max_on_approach_iterations") {
704 reinit_a_star =
true;
705 _max_on_approach_iterations = parameter.as_int();
706 if (_max_on_approach_iterations <= 0) {
708 _logger,
"On approach iteration selected as <= 0, "
709 "disabling tolerance and on approach iterations.");
710 _max_on_approach_iterations = std::numeric_limits<int>::max();
712 }
else if (param_name == _name +
".terminal_checking_interval") {
713 reinit_a_star =
true;
714 _terminal_checking_interval = parameter.as_int();
715 }
else if (param_name == _name +
".coarse_search_resolution") {
716 _coarse_search_resolution = parameter.as_int();
718 }
else if (param_type == ParameterType::PARAMETER_STRING) {
719 if (param_name == _name +
".lattice_filepath") {
720 reinit_a_star =
true;
721 reinit_lookup_table =
true;
723 reinit_smoother =
true;
725 _search_info.lattice_filepath = parameter.as_string();
727 _search_info.minimum_turning_radius =
728 _metadata.min_turning_radius / (_costmap->getResolution());
729 }
else if (param_name == _name +
".goal_heading_mode") {
730 std::string goal_heading_type = parameter.as_string();
733 "GoalHeadingMode type set to '%s'.",
734 goal_heading_type.c_str());
735 _goal_heading_mode = fromStringToGH(goal_heading_type);
741 if (reinit_a_star || reinit_smoother) {
743 _search_info.minimum_turning_radius =
744 _metadata.min_turning_radius / (_costmap->getResolution());
745 float lookup_table_dim =
746 static_cast<float>(_lookup_table_size) /
747 static_cast<float>(_costmap->getResolution());
750 lookup_table_dim =
static_cast<float>(
static_cast<int>(lookup_table_dim));
753 if (
static_cast<int>(lookup_table_dim) % 2 == 0) {
756 "Even sized heuristic lookup table size set %f, increasing size by 1 to make odd",
758 lookup_table_dim += 1.0;
762 if (reinit_smoother) {
763 auto node = _node.lock();
765 params.
get(node, _name);
766 if (_metadata.motion_model ==
"omni") {
767 params.holonomic_ =
true;
769 _smoother = std::make_unique<Smoother>(params);
770 _smoother->initialize(_metadata.min_turning_radius);
775 if (_metadata.motion_model ==
"omni" && _search_info.allow_reverse_expansion) {
778 "allow_reverse_expansion is not applicable for omnidirectional robots. Disabling.");
779 _search_info.allow_reverse_expansion =
false;
781 if (reinit_lookup_table) {
782 _a_star = std::make_unique<AStarAlgorithm<NodeT>>(_motion_model, _search_info);
784 _a_star->setSearchInfo(_search_info);
789 _max_on_approach_iterations,
790 _terminal_checking_interval,
793 _metadata.number_of_headings);
A costmap grid collision checker.
A templated state lattice planner that allows custom node types.
void cleanup() override
Cleanup lifecycle node.
SmacPlannerLatticeT()
constructor
void configure(const nav2::LifecycleNode::WeakPtr &parent, std::string name, nav2::TransformBuffer::SharedPtr tf, std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmap_ros) override
Configuring plugin.
void activate() override
Activate lifecycle node.
rcl_interfaces::msg::SetParametersResult validateParameterUpdatesCallback(const std::vector< rclcpp::Parameter > ¶meters)
Validate incoming parameter updates before applying them. This callback is triggered when one or more...
nav_msgs::msg::Path createPlan(const geometry_msgs::msg::PoseStamped &start, const geometry_msgs::msg::PoseStamped &goal, const std::vector< geometry_msgs::msg::PoseStamped > &viapoints, std::function< bool()> cancel_checker) override
Creating a plan from start and goal poses.
void updateParametersCallback(const std::vector< rclcpp::Parameter > ¶meters)
Apply parameter updates after validation This callback is executed when parameters have been successf...
~SmacPlannerLatticeT()
destructor
void deactivate() override
Deactivate lifecycle node.
static LatticeMetadata getLatticeMetadata(const std::string &lattice_filepath)
Get file metadata needed.
Parameters for the smoother cost function.
void get(nav2::LifecycleNode::SharedPtr node, const std::string &name)
Get params from ROS parameter.