17 #include "nav2_mppi_controller/critics/cost_critic.hpp"
18 #include "nav2_costmap_2d/inflation_layer_interface.hpp"
19 #include "nav2_core/controller_exceptions.hpp"
21 namespace mppi::critics
26 auto getParentParam = parameters_handler_->
getParamGetter(parent_name_);
28 getParam(consider_footprint_,
"consider_footprint",
false);
29 getParam(power_,
"cost_power", 1);
30 getParam(weight_,
"cost_weight", 3.81f);
31 getParam(critical_cost_,
"critical_cost", 300.0f);
32 getParam(near_collision_cost_,
"near_collision_cost", 253);
33 getParam(collision_cost_,
"collision_cost", 1000000.0f);
34 getParam(near_goal_distance_,
"near_goal_distance", 0.5f);
35 getParam(inflation_layer_name_,
"inflation_layer_name", std::string(
""));
36 getParam(trajectory_point_step_,
"trajectory_point_step", 2);
42 auto weightDynamicCb = [&](
43 const rclcpp::Parameter & weight) {
44 weight_ = weight.as_double() / 254.0f;
46 parameters_handler_->
addParamCallback(name_ +
".cost_weight", weightDynamicCb);
51 if (possible_collision_cost_ < 1.0f) {
54 "Inflation layer either not found or inflation is not set sufficiently for "
55 "optimized non-circular collision checking capabilities. It is HIGHLY recommended to set"
56 " the inflation radius to be at MINIMUM half of the robot's largest cross-section. See "
57 "github.com/ros-planning/navigation2/tree/main/nav2_smac_planner#potential-fields"
58 " for full instructions. This will substantially impact run-time performance.");
61 if (costmap_ros_->getUseRadius() == consider_footprint_) {
64 "Inconsistent configuration in collision checking. Please verify the robot's shape settings "
65 "in both the costmap and the cost critic.");
66 if (costmap_ros_->getUseRadius()) {
68 "Considering footprint in CostCritic but no robot footprint provided in the "
69 "costmap (robot radius used instead). Disable considering footprint.");
73 if (near_collision_cost_ > 253) {
74 RCLCPP_WARN(logger_,
"Near collision cost is set higher than INSCRIBED_INFLATED_OBSTACLE");
79 "InflationCostCritic instantiated with %d power and %f / %f weights. "
80 "Critic will collision check based on %s cost.",
81 power_, critical_cost_, weight_, consider_footprint_ ?
82 "footprint" :
"circular");
86 std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap)
89 const double circum_radius = costmap->getLayeredCostmap()->getCircumscribedRadius();
90 if (
static_cast<float>(circum_radius) == circumscribed_radius_) {
92 return circumscribed_cost_;
98 inflation_layer_name_);
99 if (inflation_layer !=
nullptr) {
100 const double resolution = costmap->getCostmap()->getResolution();
101 double inflation_radius = inflation_layer->getInflationRadius();
102 if (inflation_radius < circum_radius) {
104 rclcpp::get_logger(
"computeCircumscribedCost"),
105 "The inflation radius (%f) is smaller than the circumscribed radius (%f) "
106 "If this is an SE2-collision checking plugin, it cannot use costmap potential "
107 "field to speed up collision checking by only checking the full footprint "
108 "when robot is within possibly-inscribed radius of an obstacle. This may "
109 "significantly slow down planning times!",
110 inflation_radius, circum_radius);
114 result = inflation_layer->computeCost(circum_radius / resolution);
118 "No inflation layer found in costmap configuration. "
119 "If this is an SE2-collision checking plugin, it cannot use costmap potential "
120 "field to speed up collision checking by only checking the full footprint "
121 "when robot is within possibly-inscribed radius of an obstacle. This may "
122 "significantly slow down planning times and not avoid anything but absolute collisions!");
125 circumscribed_radius_ =
static_cast<float>(circum_radius);
126 circumscribed_cost_ =
static_cast<float>(result);
128 return circumscribed_cost_;
138 is_tracking_unknown_ = costmap_ros_->getLayeredCostmap()->isTrackingUnknown();
139 auto * costmap = collision_checker_.
getCostmap();
140 origin_x_ =
static_cast<float>(costmap->getOriginX());
141 origin_y_ =
static_cast<float>(costmap->getOriginY());
142 resolution_ =
static_cast<float>(costmap->getResolution());
143 size_x_ = costmap->getSizeInCellsX();
144 size_y_ = costmap->getSizeInCellsY();
146 if (consider_footprint_) {
152 bool near_goal =
false;
153 if (data.state.local_path_length < near_goal_distance_) {
157 Eigen::ArrayXf repulsive_cost(data.costs.rows());
158 repulsive_cost.setZero();
159 bool all_trajectories_collide =
true;
161 auto & collisions = data.trajectories_in_collision;
162 const bool track_collisions = !collisions.empty();
164 int strided_traj_cols = floor((data.trajectories.x.cols() - 1) / trajectory_point_step_) + 1;
165 int strided_traj_rows = data.trajectories.x.rows();
166 int outer_stride = strided_traj_rows * trajectory_point_step_;
168 const auto traj_x = Eigen::Map<
const Eigen::ArrayXXf, 0,
169 Eigen::Stride<-1, -1>>(
170 data.trajectories.x.data(), strided_traj_rows, strided_traj_cols,
171 Eigen::Stride<-1, -1>(outer_stride, 1));
172 const auto traj_y = Eigen::Map<
const Eigen::ArrayXXf, 0,
173 Eigen::Stride<-1, -1>>(
174 data.trajectories.y.data(), strided_traj_rows, strided_traj_cols,
175 Eigen::Stride<-1, -1>(outer_stride, 1));
176 const auto traj_yaw = Eigen::Map<
const Eigen::ArrayXXf, 0,
177 Eigen::Stride<-1, -1>>(
178 data.trajectories.yaws.data(), strided_traj_rows, strided_traj_cols,
179 Eigen::Stride<-1, -1>(outer_stride, 1));
181 for (
int i = 0; i < strided_traj_rows; ++i) {
182 bool trajectory_collide =
false;
183 float pose_cost = 0.0f;
184 float & traj_cost = repulsive_cost(i);
186 for (
int j = 0; j < strided_traj_cols; j++) {
187 float Tx = traj_x(i, j);
188 float Ty = traj_y(i, j);
189 unsigned int x_i = 0u, y_i = 0u;
197 pose_cost =
static_cast<float>(costmap->getCost(
getIndex(x_i, y_i)));
198 if (pose_cost < 1.0f) {
203 if (
inCollision(pose_cost, Tx, Ty, traj_yaw(i, j))) {
204 traj_cost = collision_cost_;
205 trajectory_collide =
true;
206 if (track_collisions) {collisions[i] =
true;}
213 if (pose_cost >=
static_cast<float>(near_collision_cost_)) {
214 traj_cost += critical_cost_;
215 }
else if (!near_goal) {
216 traj_cost += pose_cost;
220 all_trajectories_collide &= trajectory_collide;
224 data.costs += (repulsive_cost *
225 (weight_ /
static_cast<float>(strided_traj_cols))).pow(power_);
227 data.costs += repulsive_cost * (weight_ /
static_cast<float>(strided_traj_cols));
230 data.fail_flag = all_trajectories_collide;
235 #include <pluginlib/class_list_macros.hpp>
237 PLUGINLIB_EXPORT_CLASS(
auto getParamGetter(const std::string &ns)
Get an object to retrieve parameters.
void addParamCallback(const std::string &name, T &&callback)
register a function to be called when setting a parameter
Critic objective function for avoiding obstacles using costmap's inflated cost.
bool worldToMapFloat(float wx, float wy, unsigned int &mx, unsigned int &my) const
An implementation of worldToMap fully using floats.
unsigned int getIndex(unsigned int mx, unsigned int my) const
A local implementation of getIndex.
bool inCollision(float cost, float x, float y, float theta)
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...
void initialize() override
Initialize critic.
void score(CriticData &data) override
Evaluate cost related to obstacle avoidance.
Abstract critic objective function to score trajectories.
static std::shared_ptr< InflationLayerInterface > getInflationLayer(std::shared_ptr< nav2_costmap_2d::Costmap2DROS > &costmap_ros, const std::string layer_name="")
Get the inflation layer from a costmap, checking for both InflationLayer and LegacyInflationLayer imp...
Data to pass to critics for scoring, including state, trajectories, pruned path, global goal,...