15 #ifndef NAV2_SMAC_PLANNER__SMAC_PLANNER_LATTICE_IMPL_HPP_
16 #define NAV2_SMAC_PLANNER__SMAC_PLANNER_LATTICE_IMPL_HPP_
27 #include "nav2_ros_common/node_utils.hpp"
28 #include "nav2_smac_planner/smac_planner_lattice.hpp"
29 #include "nav2_ros_common/tf2_factories.hpp"
33 namespace nav2_smac_planner
36 using namespace std::chrono;
37 using rcl_interfaces::msg::ParameterType;
39 template<
typename NodeT>
42 _collision_checker(nullptr, 1, nullptr),
48 template<
typename NodeT>
52 _logger,
"Destroying plugin %s of type SmacPlannerLattice",
56 template<
typename NodeT>
58 const nav2::LifecycleNode::WeakPtr & parent,
59 std::string name, nav2::TransformBuffer::SharedPtr,
60 std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros)
63 auto node = parent.lock();
64 _logger = node->get_logger();
65 _clock = node->get_clock();
66 _costmap = costmap_ros->getCostmap();
67 _costmap_ros = costmap_ros;
69 _global_frame = costmap_ros->getGlobalFrameID();
71 RCLCPP_INFO(_logger,
"Configuring %s of type SmacPlannerLattice", name.c_str());
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.use_quadratic_cost_penalty =
112 node->declare_or_get_parameter(name +
".use_quadratic_cost_penalty",
false);
113 _search_info.downsample_obstacle_heuristic =
114 node->declare_or_get_parameter(name +
".downsample_obstacle_heuristic",
true);
116 _max_planning_time = node->declare_or_get_parameter(name +
".max_planning_time", 5.0);
117 _lookup_table_size = node->declare_or_get_parameter(name +
".lookup_table_size", 20.0);
118 _search_info.allow_reverse_expansion =
119 node->declare_or_get_parameter(name +
".allow_reverse_expansion",
false);
120 _debug_visualizations = node->declare_or_get_parameter(name +
".debug_visualizations",
false);
122 std::string goal_heading_type =
123 node->declare_or_get_parameter(name +
".goal_heading_mode", std::string(
"DEFAULT"));
124 _goal_heading_mode = fromStringToGH(goal_heading_type);
126 _coarse_search_resolution =
127 node->declare_or_get_parameter(name +
".coarse_search_resolution", 1);
129 if (_goal_heading_mode == GoalHeadingMode::UNKNOWN) {
130 std::string error_msg =
"Unable to get GoalHeader type. Given '" + goal_heading_type +
"' "
131 "Valid options are DEFAULT, BIDIRECTIONAL, ALL_DIRECTION. ";
136 _search_info.analytic_expansion_max_length =
137 _analytic_expansion_max_length_m / _metadata.grid_resolution;
138 _search_info.minimum_turning_radius =
139 _metadata.min_turning_radius / (_metadata.grid_resolution);
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>(_metadata.grid_resolution);
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()));
329 if (std::abs(_costmap->getResolution() - _metadata.grid_resolution) > 1e-6) {
331 "Costmap resolution " + std::to_string(_costmap->getResolution()) +
332 " does not match lattice resolution " + std::to_string(_metadata.grid_resolution) +
333 ". Use primitives generated for the actual costmap resolution.");
337 _collision_checker.setFootprint(
338 _costmap_ros->getRobotFootprint(),
339 _costmap_ros->getUseRadius(),
340 findCircumscribedCost(_costmap_ros));
341 _a_star->setCollisionChecker(&_collision_checker);
344 float mx_start, my_start, mx_goal, my_goal;
345 if (!_costmap->worldToMapContinuous(
346 start.pose.position.x,
347 start.pose.position.y,
352 "Start Coordinates of(" + std::to_string(start.pose.position.x) +
", " +
353 std::to_string(start.pose.position.y) +
") was outside bounds");
355 unsigned int start_bin =
356 _a_star->getContext()->motion_table.getClosestAngularBin(tf2::getYaw(start.pose.orientation));
357 _a_star->setStart(mx_start, my_start, start_bin);
360 if (!_costmap->worldToMapContinuous(
361 goal.pose.position.x,
362 goal.pose.position.y,
367 "Goal Coordinates of(" + std::to_string(goal.pose.position.x) +
", " +
368 std::to_string(goal.pose.position.y) +
") was outside bounds");
370 unsigned int goal_bin =
371 _a_star->getContext()->motion_table.getClosestAngularBin(tf2::getYaw(goal.pose.orientation));
373 mx_goal, my_goal, goal_bin,
374 _goal_heading_mode, _coarse_search_resolution);
377 nav_msgs::msg::Path plan;
378 plan.header.stamp = _clock->now();
379 plan.header.frame_id = _global_frame;
380 geometry_msgs::msg::PoseStamped pose;
381 pose.header = plan.header;
382 pose.pose.position.z = 0.0;
383 pose.pose.orientation.x = 0.0;
384 pose.pose.orientation.y = 0.0;
385 pose.pose.orientation.z = 0.0;
386 pose.pose.orientation.w = 1.0;
389 if (std::floor(mx_start) == std::floor(mx_goal) &&
390 std::floor(my_start) == std::floor(my_goal) &&
391 start_bin == goal_bin)
393 pose.pose = start.pose;
394 pose.pose.orientation = goal.pose.orientation;
395 plan.poses.push_back(pose);
398 if (_raw_plan_publisher->get_subscription_count() > 0) {
399 auto msg = std::make_unique<nav_msgs::msg::Path>(plan);
400 _raw_plan_publisher->publish(std::move(msg));
407 typename NodeT::CoordinateVector path;
408 int num_iterations = 0;
410 std::unique_ptr<std::vector<std::tuple<float, float, float>>> expansions =
nullptr;
411 if (_debug_visualizations) {
412 expansions = std::make_unique<std::vector<std::tuple<float, float, float>>>();
416 if (!_a_star->createPath(
417 path, num_iterations,
418 _tolerance /
static_cast<float>(_costmap->getResolution()), cancel_checker, expansions.get()))
420 if (_debug_visualizations) {
421 auto now = _clock->now();
422 auto msg = std::make_unique<geometry_msgs::msg::PoseArray>();
423 geometry_msgs::msg::Pose msg_pose;
424 msg->header.stamp = now;
425 msg->header.frame_id = _global_frame;
426 for (
auto & e : *expansions) {
427 msg_pose.position.x = std::get<0>(e);
428 msg_pose.position.y = std::get<1>(e);
429 msg_pose.orientation = getWorldOrientation(std::get<2>(e));
430 msg->poses.push_back(msg_pose);
432 _expansions_publisher->publish(std::move(msg));
436 if (num_iterations == 1) {
440 if (num_iterations < _a_star->getMaxIterations()) {
448 plan.poses.reserve(path.size());
449 geometry_msgs::msg::PoseStamped last_pose = pose;
450 for (
int i = path.size() - 1; i >= 0; --i) {
451 pose.pose = getWorldCoords(path[i].x, path[i].y, _costmap);
452 pose.pose.orientation = getWorldOrientation(path[i].theta);
453 if (fabs(pose.pose.position.x - last_pose.pose.position.x) < 1e-4 &&
454 fabs(pose.pose.position.y - last_pose.pose.position.y) < 1e-4 &&
455 fabs(tf2::getYaw(pose.pose.orientation) - tf2::getYaw(last_pose.pose.orientation)) < 1e-4)
459 "Removed a path from the path due to replication. "
460 "Make sure your minimum control set does not contain duplicate values!");
464 plan.poses.push_back(pose);
468 if (_raw_plan_publisher->get_subscription_count() > 0) {
469 auto msg = std::make_unique<nav_msgs::msg::Path>(plan);
470 _raw_plan_publisher->publish(std::move(msg));
473 if (_debug_visualizations) {
474 auto now = _clock->now();
476 auto msg = std::make_unique<geometry_msgs::msg::PoseArray>();
477 geometry_msgs::msg::Pose msg_pose;
478 msg->header.stamp = now;
479 msg->header.frame_id = _global_frame;
480 for (
auto & e : *expansions) {
481 msg_pose.position.x = std::get<0>(e);
482 msg_pose.position.y = std::get<1>(e);
483 msg_pose.orientation = getWorldOrientation(std::get<2>(e));
484 msg->poses.push_back(msg_pose);
486 _expansions_publisher->publish(std::move(msg));
488 if (_planned_footprints_publisher->get_subscription_count() > 0) {
490 auto marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
491 visualization_msgs::msg::Marker clear_all_marker;
492 clear_all_marker.action = visualization_msgs::msg::Marker::DELETEALL;
493 marker_array->markers.push_back(clear_all_marker);
494 _planned_footprints_publisher->publish(std::move(marker_array));
497 marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
498 for (
size_t i = 0; i < plan.poses.size(); i++) {
499 const std::vector<geometry_msgs::msg::Point> edge =
500 transformFootprintToEdges(plan.poses[i].pose, _costmap_ros->getRobotFootprint());
501 marker_array->markers.push_back(createMarker(edge, i, _global_frame, now));
503 _planned_footprints_publisher->publish(std::move(marker_array));
508 steady_clock::time_point b = steady_clock::now();
509 duration<double> time_span = duration_cast<duration<double>>(b - a);
510 double time_remaining = _max_planning_time -
static_cast<double>(time_span.count());
512 #ifdef BENCHMARK_TESTING
513 std::cout <<
"It took " << time_span.count() * 1000 <<
514 " milliseconds with " << num_iterations <<
" iterations." << std::endl;
518 if (_smoother && num_iterations > 1) {
523 _costmap_ros->getUseRadius() ? std::vector<geometry_msgs::msg::Point>() :
524 _costmap_ros->getRobotFootprint());
527 #ifdef BENCHMARK_TESTING
528 steady_clock::time_point c = steady_clock::now();
529 duration<double> time_span2 = duration_cast<duration<double>>(c - b);
530 std::cout <<
"It took " << time_span2.count() * 1000 <<
531 " milliseconds to smooth path." << std::endl;
534 if (_debug_visualizations) {
535 if (_smoothed_footprints_publisher->get_subscription_count() > 0) {
537 auto marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
538 visualization_msgs::msg::Marker clear_all_marker;
539 clear_all_marker.action = visualization_msgs::msg::Marker::DELETEALL;
540 marker_array->markers.push_back(clear_all_marker);
541 _smoothed_footprints_publisher->publish(std::move(marker_array));
544 marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
545 auto now = _clock->now();
546 for (
size_t i = 0; i < plan.poses.size(); i++) {
547 const std::vector<geometry_msgs::msg::Point> edge =
548 transformFootprintToEdges(plan.poses[i].pose, _costmap_ros->getRobotFootprint());
549 marker_array->markers.push_back(createMarker(edge, i, _global_frame, now));
551 _smoothed_footprints_publisher->publish(std::move(marker_array));
558 template<
typename NodeT>
559 rcl_interfaces::msg::SetParametersResult
561 const std::vector<rclcpp::Parameter> & parameters)
563 rcl_interfaces::msg::SetParametersResult result;
564 result.successful =
true;
565 for (
const auto & parameter : parameters) {
566 const auto & param_type = parameter.get_type();
567 const auto & param_name = parameter.get_name();
568 if (param_name.find(_name +
".") != 0) {
571 if (param_type == ParameterType::PARAMETER_DOUBLE) {
572 if (parameter.as_double() < 0.0) {
574 _logger,
"The value of parameter '%s' is incorrectly set to %f, "
575 "it should be >=0. Ignoring parameter update.",
576 param_name.c_str(), parameter.as_double());
577 result.successful =
false;
579 }
else if (param_type == ParameterType::PARAMETER_INTEGER) {
580 if (param_name == _name +
".coarse_search_resolution" && _metadata.number_of_headings %
581 parameter.as_int() != 0)
585 "coarse iteration should be an increment of the number"
586 " of angular bins configured. Ignoring parameter update!"
588 result.successful =
false;
589 }
else if (parameter.as_int() <= 0 && (param_name != _name +
".max_iterations" &&
590 param_name != _name +
".max_on_approach_iterations"))
593 _logger,
"The value of parameter '%s' is incorrectly set to %ld, "
594 "it should be >0. Ignoring parameter update.",
595 param_name.c_str(), parameter.as_int());
596 result.successful =
false;
598 }
else if (param_type == ParameterType::PARAMETER_STRING) {
599 if (param_name == _name +
".lattice_filepath") {
602 if (metadata.number_of_headings % _coarse_search_resolution != 0) {
605 "coarse iteration should be an increment of the number "
606 "of angular bins configured. Ignoring parameter update!"
608 result.successful =
false;
610 }
else if (param_name == _name +
".goal_heading_mode") {
611 GoalHeadingMode goal_heading_mode = fromStringToGH(parameter.as_string());
612 if (goal_heading_mode == GoalHeadingMode::UNKNOWN) {
615 "Unable to get GoalHeader type. Given '%s' Valid options are "
616 "DEFAULT, BIDIRECTIONAL, ALL_DIRECTION. Ignoring parameter update!",
617 parameter.as_string().c_str());
618 result.successful =
false;
626 template<
typename NodeT>
629 const std::vector<rclcpp::Parameter> & parameters)
631 std::lock_guard<std::mutex> lock_reinit(_mutex);
633 bool reinit_a_star =
false;
634 bool reinit_lookup_table =
false;
635 bool reinit_smoother =
false;
637 for (
auto parameter : parameters) {
638 const auto & param_type = parameter.get_type();
639 const auto & param_name = parameter.get_name();
640 if (param_name.find(_name +
".") != 0) {
643 if (param_type == ParameterType::PARAMETER_DOUBLE) {
644 if (param_name == _name +
".max_planning_time") {
645 reinit_a_star =
true;
646 _max_planning_time = parameter.as_double();
647 }
else if (param_name == _name +
".tolerance") {
648 _tolerance =
static_cast<float>(parameter.as_double());
649 }
else if (param_name == _name +
".lookup_table_size") {
650 reinit_a_star =
true;
651 reinit_lookup_table =
true;
652 _lookup_table_size = parameter.as_double();
653 }
else if (param_name == _name +
".reverse_penalty") {
654 reinit_a_star =
true;
655 _search_info.reverse_penalty =
static_cast<float>(parameter.as_double());
656 }
else if (param_name == _name +
".change_penalty") {
657 reinit_a_star =
true;
658 _search_info.change_penalty =
static_cast<float>(parameter.as_double());
659 }
else if (param_name == _name +
".non_straight_penalty") {
660 reinit_a_star =
true;
661 _search_info.non_straight_penalty =
static_cast<float>(parameter.as_double());
662 }
else if (param_name == _name +
".cost_penalty") {
663 reinit_a_star =
true;
664 _search_info.cost_penalty =
static_cast<float>(parameter.as_double());
665 }
else if (param_name == _name +
".rotation_penalty") {
666 reinit_a_star =
true;
667 _search_info.rotation_penalty =
static_cast<float>(parameter.as_double());
668 }
else if (param_name == _name +
".analytic_expansion_ratio") {
669 reinit_a_star =
true;
670 _search_info.analytic_expansion_ratio =
static_cast<float>(parameter.as_double());
671 }
else if (param_name == _name +
".analytic_expansion_max_length") {
672 reinit_a_star =
true;
673 _analytic_expansion_max_length_m = parameter.as_double();
674 }
else if (param_name == _name +
".analytic_expansion_max_cost") {
675 reinit_a_star =
true;
676 _search_info.analytic_expansion_max_cost =
static_cast<float>(parameter.as_double());
678 }
else if (param_type == ParameterType::PARAMETER_BOOL) {
679 if (param_name == _name +
".allow_unknown") {
680 reinit_a_star =
true;
681 _allow_unknown = parameter.as_bool();
682 }
else if (param_name == _name +
".cache_obstacle_heuristic") {
683 reinit_a_star =
true;
684 _search_info.cache_obstacle_heuristic = parameter.as_bool();
685 }
else if (param_name == _name +
".allow_reverse_expansion") {
686 reinit_a_star =
true;
687 reinit_lookup_table =
true;
688 _search_info.allow_reverse_expansion = parameter.as_bool();
689 }
else if (param_name == _name +
".smooth_path") {
690 if (parameter.as_bool()) {
691 reinit_smoother =
true;
695 }
else if (param_name == _name +
".analytic_expansion_max_cost_override") {
696 _search_info.analytic_expansion_max_cost_override = parameter.as_bool();
697 reinit_a_star =
true;
699 }
else if (param_type == ParameterType::PARAMETER_INTEGER) {
700 if (param_name == _name +
".max_iterations") {
701 reinit_a_star =
true;
702 _max_iterations = parameter.as_int();
703 if (_max_iterations <= 0) {
705 _logger,
"maximum iteration selected as <= 0, "
706 "disabling maximum iterations.");
707 _max_iterations = std::numeric_limits<int>::max();
709 }
else if (param_name == _name +
".max_on_approach_iterations") {
710 reinit_a_star =
true;
711 _max_on_approach_iterations = parameter.as_int();
712 if (_max_on_approach_iterations <= 0) {
714 _logger,
"On approach iteration selected as <= 0, "
715 "disabling tolerance and on approach iterations.");
716 _max_on_approach_iterations = std::numeric_limits<int>::max();
718 }
else if (param_name == _name +
".terminal_checking_interval") {
719 reinit_a_star =
true;
720 _terminal_checking_interval = parameter.as_int();
721 }
else if (param_name == _name +
".coarse_search_resolution") {
722 _coarse_search_resolution = parameter.as_int();
724 }
else if (param_type == ParameterType::PARAMETER_STRING) {
725 if (param_name == _name +
".lattice_filepath") {
726 reinit_a_star =
true;
727 reinit_lookup_table =
true;
729 reinit_smoother =
true;
731 _search_info.lattice_filepath = parameter.as_string();
733 _search_info.minimum_turning_radius =
734 _metadata.min_turning_radius / (_metadata.grid_resolution);
735 }
else if (param_name == _name +
".goal_heading_mode") {
736 std::string goal_heading_type = parameter.as_string();
739 "GoalHeadingMode type set to '%s'.",
740 goal_heading_type.c_str());
741 _goal_heading_mode = fromStringToGH(goal_heading_type);
747 if (reinit_a_star || reinit_smoother) {
749 _search_info.analytic_expansion_max_length =
750 _analytic_expansion_max_length_m / _metadata.grid_resolution;
751 _search_info.minimum_turning_radius =
752 _metadata.min_turning_radius / (_metadata.grid_resolution);
753 float lookup_table_dim =
754 static_cast<float>(_lookup_table_size) /
755 static_cast<float>(_metadata.grid_resolution);
758 lookup_table_dim =
static_cast<float>(
static_cast<int>(lookup_table_dim));
761 if (
static_cast<int>(lookup_table_dim) % 2 == 0) {
764 "Even sized heuristic lookup table size set %f, increasing size by 1 to make odd",
766 lookup_table_dim += 1.0;
770 if (reinit_smoother) {
771 auto node = _node.lock();
773 params.
get(node, _name);
774 if (_metadata.motion_model ==
"omni") {
775 params.holonomic_ =
true;
777 _smoother = std::make_unique<Smoother>(params);
778 _smoother->initialize(_metadata.min_turning_radius);
783 if (_metadata.motion_model ==
"omni" && _search_info.allow_reverse_expansion) {
786 "allow_reverse_expansion is not applicable for omnidirectional robots. Disabling.");
787 _search_info.allow_reverse_expansion =
false;
789 if (reinit_lookup_table) {
790 _a_star = std::make_unique<AStarAlgorithm<NodeT>>(_motion_model, _search_info);
792 _a_star->setSearchInfo(_search_info);
797 _max_on_approach_iterations,
798 _terminal_checking_interval,
801 _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.