17 #include "nav2_mppi_controller/critics/obstacles_critic.hpp"
18 #include "nav2_costmap_2d/inflation_layer.hpp"
19 #include "nav2_core/controller_exceptions.hpp"
21 namespace mppi::critics
26 auto getParentParam = parameters_handler_->
getParamGetter(parent_name_);
27 getParentParam(enforce_path_inversion_,
"enforce_path_inversion",
false);
30 getParam(consider_footprint_,
"consider_footprint",
false);
31 getParam(power_,
"cost_power", 1);
32 getParam(repulsion_weight_,
"repulsion_weight", 1.5f);
33 getParam(critical_weight_,
"critical_weight", 20.0f);
34 getParam(collision_cost_,
"collision_cost", 100000.0f);
35 getParam(collision_margin_distance_,
"collision_margin_distance", 0.10f);
36 getParam(near_goal_distance_,
"near_goal_distance", 0.5f);
37 getParam(inflation_layer_name_,
"inflation_layer_name", std::string(
""));
42 if (possible_collision_cost_ < 1.0f) {
45 "Inflation layer either not found or inflation is not set sufficiently for "
46 "optimized non-circular collision checking capabilities. It is HIGHLY recommended to set"
47 " the inflation radius to be at MINIMUM half of the robot's largest cross-section. See "
48 "github.com/ros-planning/navigation2/tree/main/nav2_smac_planner#potential-fields"
49 " for full instructions. This will substantially impact run-time performance.");
52 if (costmap_ros_->getUseRadius() == consider_footprint_) {
55 "Inconsistent configuration in collision checking. Please verify the robot's shape settings "
56 "in both the costmap and the obstacle critic.");
57 if (costmap_ros_->getUseRadius()) {
59 "Considering footprint in collision checking but no robot footprint provided in the "
66 "ObstaclesCritic instantiated with %d power and %f / %f weights. "
67 "Critic will collision check based on %s cost.",
68 power_, critical_weight_, repulsion_weight_, consider_footprint_ ?
69 "footprint" :
"circular");
73 std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap)
76 const double circum_radius = costmap->getLayeredCostmap()->getCircumscribedRadius();
77 if (
static_cast<float>(circum_radius) == circumscribed_radius_) {
79 return circumscribed_cost_;
83 const auto inflation_layer = nav2_costmap_2d::InflationLayer::getInflationLayer(
85 inflation_layer_name_);
86 if (inflation_layer !=
nullptr) {
87 const double resolution = costmap->getCostmap()->getResolution();
88 result = inflation_layer->computeCost(circum_radius / resolution);
89 inflation_scale_factor_ =
static_cast<float>(inflation_layer->getCostScalingFactor());
90 inflation_radius_ =
static_cast<float>(inflation_layer->getInflationRadius());
94 "No inflation layer found in costmap configuration. "
95 "If this is an SE2-collision checking plugin, it cannot use costmap potential "
96 "field to speed up collision checking by only checking the full footprint "
97 "when robot is within possibly-inscribed radius of an obstacle. This may "
98 "significantly slow down planning times and not avoid anything but absolute collisions!");
101 circumscribed_radius_ =
static_cast<float>(circum_radius);
102 circumscribed_cost_ =
static_cast<float>(result);
104 return circumscribed_cost_;
109 const float scale_factor = inflation_scale_factor_;
110 const float min_radius = costmap_ros_->getLayeredCostmap()->getInscribedRadius();
111 float dist_to_obj = (scale_factor * min_radius - log(cost.cost) + log(253.0f)) / scale_factor;
115 if (!cost.using_footprint) {
116 dist_to_obj -= min_radius;
128 if (consider_footprint_) {
133 geometry_msgs::msg::Pose goal = utils::getCriticGoal(data, enforce_path_inversion_);
136 bool near_goal =
false;
137 if (utils::withinPositionGoalTolerance(near_goal_distance_, data.state.pose.pose, goal)) {
141 Eigen::ArrayXf raw_cost = Eigen::ArrayXf::Zero(data.costs.size());
142 Eigen::ArrayXf repulsive_cost = Eigen::ArrayXf::Zero(data.costs.size());
144 const unsigned int traj_len = data.trajectories.x.cols();
145 const unsigned int batch_size = data.trajectories.x.rows();
146 bool all_trajectories_collide =
true;
148 for(
unsigned int i = 0; i != batch_size; i++) {
149 bool trajectory_collide =
false;
150 float traj_cost = 0.0f;
151 const auto & traj = data.trajectories;
154 repulsive_cost(i) = 0.0f;
156 for(
unsigned int j = 0; j != traj_len; j++) {
157 pose_cost =
costAtPose(traj.x(i, j), traj.y(i, j), traj.yaws(i, j));
158 if (pose_cost.cost < 1.0f) {
continue;}
161 trajectory_collide =
true;
166 if (inflation_radius_ == 0.0f || inflation_scale_factor_ == 0.0f) {
173 if (dist_to_obj < collision_margin_distance_) {
174 traj_cost += (collision_margin_distance_ - dist_to_obj);
179 repulsive_cost[i] += inflation_radius_ - dist_to_obj;
183 if (!trajectory_collide) {all_trajectories_collide =
false;}
184 raw_cost(i) = trajectory_collide ? collision_cost_ : traj_cost;
189 auto repulsive_cost_normalized = (repulsive_cost - repulsive_cost.minCoeff()) / traj_len;
193 ((critical_weight_ * raw_cost) + (repulsion_weight_ * repulsive_cost_normalized)).pow(power_);
195 data.costs += (critical_weight_ * raw_cost) + (repulsion_weight_ * repulsive_cost_normalized);
198 data.fail_flag = all_trajectories_collide;
208 bool is_tracking_unknown =
209 costmap_ros_->getLayeredCostmap()->isTrackingUnknown();
212 switch (
static_cast<unsigned char>(cost)) {
213 case (LETHAL_OBSTACLE):
215 case (INSCRIBED_INFLATED_OBSTACLE):
216 return consider_footprint_ ? false :
true;
217 case (NO_INFORMATION):
218 return is_tracking_unknown ? false :
true;
227 float & cost = collision_cost.cost;
228 collision_cost.using_footprint =
false;
229 unsigned int x_i, y_i;
230 if (!collision_checker_.
worldToMap(x, y, x_i, y_i)) {
231 cost = nav2_costmap_2d::NO_INFORMATION;
232 return collision_cost;
234 cost = collision_checker_.
pointCost(x_i, y_i);
236 if (consider_footprint_ &&
237 (cost >= possible_collision_cost_ || possible_collision_cost_ < 1.0f))
240 x, y, theta, costmap_ros_->getRobotFootprint()));
241 collision_cost.using_footprint =
true;
244 return collision_cost;
249 #include <pluginlib/class_list_macros.hpp>
251 PLUGINLIB_EXPORT_CLASS(
auto getParamGetter(const std::string &ns)
Get an object to retrieve parameters.
Abstract critic objective function to score trajectories.
bool inCollision(float cost) const
Checks if cost represents a collision.
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...
CollisionCost costAtPose(float x, float y, float theta)
cost at a robot pose
float distanceToObstacle(const CollisionCost &cost)
Distance to obstacle from cost.
void initialize() override
Initialize critic.
void score(CriticData &data) override
Evaluate cost related to obstacle avoidance.
Data to pass to critics for scoring, including state, trajectories, pruned path, global goal,...
Utility for storing cost information.