17 #include "nav2_mppi_controller/critics/cost_critic.hpp"
18 #include "nav2_core/exceptions.hpp"
20 namespace mppi::critics
26 getParam(consider_footprint_,
"consider_footprint",
false);
27 getParam(power_,
"cost_power", 1);
28 getParam(weight_,
"cost_weight", 3.81);
29 getParam(critical_cost_,
"critical_cost", 300.0);
30 getParam(collision_cost_,
"collision_cost", 1000000.0);
31 getParam(near_goal_distance_,
"near_goal_distance", 0.5);
32 getParam(inflation_layer_name_,
"inflation_layer_name", std::string(
""));
38 auto weightDynamicCb = [&](
const rclcpp::Parameter & weight) {
39 weight_ = weight.as_double() / 254.0f;
46 if (possibly_inscribed_cost_ < 1.0f) {
49 "Inflation layer either not found or inflation is not set sufficiently for "
50 "optimized non-circular collision checking capabilities. It is HIGHLY recommended to set"
51 " the inflation radius to be at MINIMUM half of the robot's largest cross-section. See "
52 "github.com/ros-planning/navigation2/tree/main/nav2_smac_planner#potential-fields"
53 " for full instructions. This will substantially impact run-time performance.");
56 if (costmap_ros_->getUseRadius() == consider_footprint_) {
59 "Inconsistent configuration in collision checking. Please verify the robot's shape settings "
60 "in both the costmap and the cost critic.");
61 if (costmap_ros_->getUseRadius()) {
63 "Considering footprint in collision checking but no robot footprint provided in the "
70 "InflationCostCritic instantiated with %d power and %f / %f weights. "
71 "Critic will collision check based on %s cost.",
72 power_, critical_cost_, weight_, consider_footprint_ ?
73 "footprint" :
"circular");
77 std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap)
79 bool inflation_layer_found =
false;
81 const double circum_radius = costmap->getLayeredCostmap()->getCircumscribedRadius();
82 if (
static_cast<float>(circum_radius) == circumscribed_radius_) {
84 return circumscribed_cost_;
88 for (
auto layer = costmap->getLayeredCostmap()->getPlugins()->begin();
89 layer != costmap->getLayeredCostmap()->getPlugins()->end();
92 auto inflation_layer = std::dynamic_pointer_cast<nav2_costmap_2d::InflationLayer>(*layer);
93 if (!inflation_layer ||
94 (!inflation_layer_name_.empty() &&
95 inflation_layer->getName() != inflation_layer_name_))
100 inflation_layer_found =
true;
101 const double resolution = costmap->getCostmap()->getResolution();
102 result = inflation_layer->computeCost(circum_radius / resolution);
105 if (!inflation_layer_found) {
108 "No inflation layer found in costmap configuration. "
109 "If this is an SE2-collision checking plugin, it cannot use costmap potential "
110 "field to speed up collision checking by only checking the full footprint "
111 "when robot is within possibly-inscribed radius of an obstacle. This may "
112 "significantly slow down planning times and not avoid anything but absolute collisions!");
115 circumscribed_radius_ =
static_cast<float>(circum_radius);
116 circumscribed_cost_ =
static_cast<float>(result);
118 return circumscribed_cost_;
123 using xt::evaluation_strategy::immediate;
128 if (consider_footprint_) {
134 bool near_goal =
false;
135 if (utils::withinPositionGoalTolerance(near_goal_distance_, data.state.pose.pose, data.goal)) {
139 auto && repulsive_cost = xt::xtensor<float, 1>::from_shape({data.costs.shape(0)});
140 repulsive_cost.fill(0.0);
142 const size_t traj_len = data.trajectories.x.shape(1);
143 bool all_trajectories_collide =
true;
144 for (
size_t i = 0; i < data.trajectories.x.shape(0); ++i) {
145 bool trajectory_collide =
false;
146 const auto & traj = data.trajectories;
149 for (
size_t j = 0; j < traj_len; j++) {
153 pose_cost =
costAtPose(traj.x(i, j), traj.y(i, j));
154 if (pose_cost < 1.0f) {
continue;}
156 if (
inCollision(pose_cost, traj.x(i, j), traj.y(i, j), traj.yaws(i, j))) {
157 trajectory_collide =
true;
165 if (pose_cost >= INSCRIBED_INFLATED_OBSTACLE) {
166 repulsive_cost[i] += critical_cost_;
167 }
else if (!near_goal) {
168 repulsive_cost[i] += pose_cost;
172 if (!trajectory_collide) {
173 all_trajectories_collide =
false;
175 repulsive_cost[i] = collision_cost_;
179 data.costs += xt::pow((weight_ * repulsive_cost / traj_len), power_);
180 data.fail_flag = all_trajectories_collide;
190 bool is_tracking_unknown =
191 costmap_ros_->getLayeredCostmap()->isTrackingUnknown();
194 if (consider_footprint_ &&
195 (cost >= possibly_inscribed_cost_ || possibly_inscribed_cost_ < 1.0f))
198 x, y, theta, costmap_ros_->getRobotFootprint()));
201 switch (
static_cast<unsigned char>(cost)) {
203 case (LETHAL_OBSTACLE):
205 case (INSCRIBED_INFLATED_OBSTACLE):
206 return consider_footprint_ ? false :
true;
207 case (NO_INFORMATION):
208 return is_tracking_unknown ? false :
true;
217 unsigned int x_i, y_i;
218 if (!collision_checker_.worldToMap(x, y, x_i, y_i)) {
219 return nav2_costmap_2d::NO_INFORMATION;
222 return collision_checker_.pointCost(x_i, y_i);
227 #include <pluginlib/class_list_macros.hpp>
229 PLUGINLIB_EXPORT_CLASS(
void addDynamicParamCallback(const std::string &name, T &&callback)
Set a parameter to a dynamic parameter callback.
auto getParamGetter(const std::string &ns)
Get an object to retreive parameters.
Critic objective function for avoiding obstacles using costmap's inflated cost.
bool inCollision(float cost, float x, float y, float theta)
Checks if cost represents a collision.
float costAtPose(float x, float y)
cost at a robot pose
float findCircumscribedCost(std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmap)
Find the min cost of the inflation decay function for which the robot MAY be in collision in any orie...
void initialize() override
Initialize critic.
void score(CriticData &data) override
Evaluate cost related to obstacle avoidance.
Abstract critic objective function to score trajectories.
Data to pass to critics for scoring, including state, trajectories, pruned path, global goal,...