Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add viz_expansions parameter for debug #3577

Merged
merged 4 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 2 additions & 23 deletions nav2_smac_planner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ planner_server:
cache_obstacle_heuristic: True # For Hybrid nodes: Cache the obstacle map dynamic programming distance expansion heuristic between subsiquent replannings of the same goal location. Dramatically speeds up replanning performance (40x) if costmap is largely static.
allow_reverse_expansion: False # For Lattice nodes: Whether to expand state lattice graph in forward primitives or reverse as well, will double the branching factor at each step.
smooth_path: True # For Lattice/Hybrid nodes: Whether or not to smooth the path, always true for 2D nodes.
viz_expansions: True # For Hybrid nodes: Whether to publish expansions on the /expansions topic as an array of poses (the orientation has no meaning). WARNING: heavy to compute and to display, for debug only as it degrades the performance.
smoother:
max_iterations: 1000
w_smooth: 0.3
Expand Down Expand Up @@ -206,26 +207,4 @@ As such, it is recommended if you have sparse SLAM maps, gaps or holes in your m

One interesting thing to note from the second figure is that you see a number of expansions in open space. This is due to travel / heuristic values being so similar, tuning values of the penalty weights can have a decent impact there. The defaults are set as a good middle ground between large open spaces and confined aisles (environment specific tuning could be done to reduce the number of expansions for a specific map, speeding up the planner). The planner actually runs substantially faster the more confined the areas of search / environments are -- but still plenty fast for even wide open areas!

Sometimes visualizing the expansions is very useful to debug potential concerns (why does this goal take longer to compute, why can't I find a path, etc), should you on rare occasion run into an issue. The following snippet is what I used to visualize the expansion in the images above which may help you in future endevours.

``` cpp
// In createPath()
static auto node = std::make_shared<rclcpp::Node>("test");
static auto pub = node->create_publisher<geometry_msgs::msg::PoseArray>("expansions", 1);
geometry_msgs::msg::PoseArray msg;
geometry_msgs::msg::Pose msg_pose;
msg.header.stamp = node->now();
msg.header.frame_id = "map";

...

// Each time we expand a new node
msg_pose.position.x = _costmap->getOriginX() + (current_node->pose.x * _costmap->getResolution());
msg_pose.position.y = _costmap->getOriginY() + (current_node->pose.y * _costmap->getResolution());
msg.poses.push_back(msg_pose);

...

// On backtrace or failure
pub->publish(msg);
```
Sometimes visualizing the expansions is very useful to debug potential concerns (why does this goal take longer to compute, why can't I find a path, etc), should you on rare occasion run into an issue. You can enable the publication of the expansions on the `/expansions` topic for SmacHybrid with the parameter `viz_expansions: True`, beware that it should be used only for debug as it increases a lot the CPU usage.
6 changes: 5 additions & 1 deletion nav2_smac_planner/include/nav2_smac_planner/a_star.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <memory>
#include <queue>
#include <utility>
#include <tuple>
doisyg marked this conversation as resolved.
Show resolved Hide resolved
#include "Eigen/Core"

#include "nav2_costmap_2d/costmap_2d.hpp"
Expand Down Expand Up @@ -104,9 +105,12 @@ class AStarAlgorithm
* @param path Reference to a vector of indicies of generated path
* @param num_iterations Reference to number of iterations to create plan
* @param tolerance Reference to tolerance in costmap nodes
* @param expansions_log Optional expansions logged for debug
* @return if plan was successful
*/
bool createPath(CoordinateVector & path, int & num_iterations, const float & tolerance);
bool createPath(
CoordinateVector & path, int & num_iterations, const float & tolerance,
std::vector<std::tuple<float, float>> * expansions_log = nullptr);

/**
* @brief Sets the collision checker to use
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "nav2_costmap_2d/costmap_2d_ros.hpp"
#include "nav2_costmap_2d/costmap_2d.hpp"
#include "geometry_msgs/msg/pose_stamped.hpp"
#include "geometry_msgs/msg/pose_array.hpp"
#include "nav2_util/lifecycle_node.hpp"
#include "nav2_util/node_utils.hpp"
#include "tf2/utils.h"
Expand Down Expand Up @@ -116,9 +117,12 @@ class SmacPlannerHybrid : public nav2_core::GlobalPlanner
double _max_planning_time;
double _lookup_table_size;
double _minimum_turning_radius_global_coords;
bool _viz_expansions;
std::string _motion_model_for_search;
MotionModel _motion_model;
rclcpp_lifecycle::LifecyclePublisher<nav_msgs::msg::Path>::SharedPtr _raw_plan_publisher;
rclcpp_lifecycle::LifecyclePublisher<geometry_msgs::msg::PoseArray>::SharedPtr
_expansions_publisher;
std::mutex _mutex;
rclcpp_lifecycle::LifecycleNode::WeakPtr _node;

Expand Down
14 changes: 13 additions & 1 deletion nav2_smac_planner/src/a_star.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ bool AStarAlgorithm<NodeT>::areInputsValid()
template<typename NodeT>
bool AStarAlgorithm<NodeT>::createPath(
CoordinateVector & path, int & iterations,
const float & tolerance)
const float & tolerance,
std::vector<std::tuple<float, float>> * expansions_log)
{
steady_clock::time_point start_time = steady_clock::now();
_tolerance = tolerance;
Expand Down Expand Up @@ -273,6 +274,17 @@ bool AStarAlgorithm<NodeT>::createPath(
// 1) Pick Nbest from O s.t. min(f(Nbest)), remove from queue
current_node = getNextNode();

// Save current node coordinates for debug
if (expansions_log) {
Coordinates coords = current_node->getCoords(
current_node->getIndex(), getSizeX(), getSizeDim3());
expansions_log->push_back(
std::make_tuple<float, float>(
_costmap->getOriginX() + (coords.x * _costmap->getResolution()),
_costmap->getOriginY() + (coords.y * _costmap->getResolution()))
);
}

// We allow for nodes to be queued multiple times in case
// shorter paths result in it, but we can visit only once
if (current_node->wasVisited()) {
Expand Down
36 changes: 34 additions & 2 deletions nav2_smac_planner/src/smac_planner_hybrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ void SmacPlannerHybrid::configure(
node, name + ".lookup_table_size", rclcpp::ParameterValue(20.0));
node->get_parameter(name + ".lookup_table_size", _lookup_table_size);

nav2_util::declare_parameter_if_not_declared(
node, name + ".viz_expansions", rclcpp::ParameterValue(false));
node->get_parameter(name + ".viz_expansions", _viz_expansions);

nav2_util::declare_parameter_if_not_declared(
node, name + ".motion_model_for_search", rclcpp::ParameterValue(std::string("DUBIN")));
node->get_parameter(name + ".motion_model_for_search", _motion_model_for_search);
Expand Down Expand Up @@ -215,6 +219,9 @@ void SmacPlannerHybrid::configure(
}

_raw_plan_publisher = node->create_publisher<nav_msgs::msg::Path>("unsmoothed_plan", 1);
if (_viz_expansions) {
_expansions_publisher = node->create_publisher<geometry_msgs::msg::PoseArray>("expansions", 1);
}

RCLCPP_INFO(
_logger, "Configured plugin %s of type SmacPlannerHybrid with "
Expand All @@ -231,6 +238,9 @@ void SmacPlannerHybrid::activate()
_logger, "Activating plugin %s of type SmacPlannerHybrid",
_name.c_str());
_raw_plan_publisher->on_activate();
if (_viz_expansions) {
_expansions_publisher->on_activate();
}
if (_costmap_downsampler) {
_costmap_downsampler->on_activate();
}
Expand All @@ -246,6 +256,9 @@ void SmacPlannerHybrid::deactivate()
_logger, "Deactivating plugin %s of type SmacPlannerHybrid",
_name.c_str());
_raw_plan_publisher->on_deactivate();
if (_viz_expansions) {
_expansions_publisher->on_deactivate();
}
if (_costmap_downsampler) {
_costmap_downsampler->on_deactivate();
}
Expand All @@ -264,6 +277,7 @@ void SmacPlannerHybrid::cleanup()
_costmap_downsampler.reset();
}
_raw_plan_publisher.reset();
_expansions_publisher.reset();
}

nav_msgs::msg::Path SmacPlannerHybrid::createPlan(
Expand Down Expand Up @@ -336,16 +350,34 @@ nav_msgs::msg::Path SmacPlannerHybrid::createPlan(
// Compute plan
NodeHybrid::CoordinateVector path;
int num_iterations = 0;

std::string error;
std::unique_ptr<std::vector<std::tuple<float, float>>> expansions = nullptr;
if (_viz_expansions) {
expansions = std::make_unique<std::vector<std::tuple<float, float>>>();
}
// Note: All exceptions thrown are handled by the planner server and returned to the action
if (!_a_star->createPath(path, num_iterations, 0)) {
if (!_a_star->createPath(path, num_iterations, 0, expansions.get())) {
if (num_iterations < _a_star->getMaxIterations()) {
throw nav2_core::NoValidPathCouldBeFound("no valid path found");
} else {
throw nav2_core::PlannerTimedOut("exceeded maximum iterations");
}
}

// Publish expansions for debug
if (_viz_expansions) {
geometry_msgs::msg::PoseArray msg;
geometry_msgs::msg::Pose msg_pose;
msg.header.stamp = _clock->now();
msg.header.frame_id = _global_frame;
for (auto & e : *expansions) {
msg_pose.position.x = std::get<0>(e);
msg_pose.position.y = std::get<1>(e);
msg.poses.push_back(msg_pose);
}
_expansions_publisher->publish(msg);
}

// Convert to world coordinates
plan.poses.reserve(path.size());
for (int i = path.size() - 1; i >= 0; --i) {
Expand Down