17 #include "nav2_mppi_controller/critics/cost_critic.hpp"
18 #include "nav2_core/controller_exceptions.hpp"
20 namespace mppi::critics
25 auto getParentParam = parameters_handler_->
getParamGetter(parent_name_);
26 getParentParam(enforce_path_inversion_,
"enforce_path_inversion",
false);
29 getParam(consider_footprint_,
"consider_footprint",
false);
30 getParam(power_,
"cost_power", 1);
31 getParam(weight_,
"cost_weight", 3.81f);
32 getParam(critical_cost_,
"critical_cost", 300.0f);
33 getParam(near_collision_cost_,
"near_collision_cost", 253);
34 getParam(collision_cost_,
"collision_cost", 1000000.0f);
35 getParam(near_goal_distance_,
"near_goal_distance", 0.5f);
36 getParam(inflation_layer_name_,
"inflation_layer_name", std::string(
""));
37 getParam(trajectory_point_step_,
"trajectory_point_step", 2);
43 auto weightDynamicCb = [&](
44 const rclcpp::Parameter & weight, rcl_interfaces::msg::SetParametersResult & ) {
45 weight_ = weight.as_double() / 254.0f;
47 parameters_handler_->
addParamCallback(name_ +
".cost_weight", weightDynamicCb);
52 if (possible_collision_cost_ < 1.0f) {
55 "Inflation layer either not found or inflation is not set sufficiently for "
56 "optimized non-circular collision checking capabilities. It is HIGHLY recommended to set"
57 " the inflation radius to be at MINIMUM half of the robot's largest cross-section. See "
58 "github.com/ros-planning/navigation2/tree/main/nav2_smac_planner#potential-fields"
59 " for full instructions. This will substantially impact run-time performance.");
62 if (costmap_ros_->getUseRadius() == consider_footprint_) {
65 "Inconsistent configuration in collision checking. Please verify the robot's shape settings "
66 "in both the costmap and the cost critic.");
67 if (costmap_ros_->getUseRadius()) {
69 "Considering footprint in collision checking but no robot footprint provided in the "
74 if(near_collision_cost_ > 253) {
75 RCLCPP_WARN(logger_,
"Near collision cost is set higher than INSCRIBED_INFLATED_OBSTACLE");
80 "InflationCostCritic instantiated with %d power and %f / %f weights. "
81 "Critic will collision check based on %s cost.",
82 power_, critical_cost_, weight_, consider_footprint_ ?
83 "footprint" :
"circular");
87 std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap)
90 const double circum_radius = costmap->getLayeredCostmap()->getCircumscribedRadius();
91 if (
static_cast<float>(circum_radius) == circumscribed_radius_) {
93 return circumscribed_cost_;
97 const auto inflation_layer = nav2_costmap_2d::InflationLayer::getInflationLayer(
99 inflation_layer_name_);
100 if (inflation_layer !=
nullptr) {
101 const double resolution = costmap->getCostmap()->getResolution();
102 double inflation_radius = inflation_layer->getInflationRadius();
103 if (inflation_radius < circum_radius) {
105 rclcpp::get_logger(
"computeCircumscribedCost"),
106 "The inflation radius (%f) is smaller than the circumscribed radius (%f) "
107 "If this is an SE2-collision checking plugin, it cannot use costmap potential "
108 "field to speed up collision checking by only checking the full footprint "
109 "when robot is within possibly-inscribed radius of an obstacle. This may "
110 "significantly slow down planning times!",
111 inflation_radius, circum_radius);
115 result = inflation_layer->computeCost(circum_radius / resolution);
119 "No inflation layer found in costmap configuration. "
120 "If this is an SE2-collision checking plugin, it cannot use costmap potential "
121 "field to speed up collision checking by only checking the full footprint "
122 "when robot is within possibly-inscribed radius of an obstacle. This may "
123 "significantly slow down planning times and not avoid anything but absolute collisions!");
126 circumscribed_radius_ =
static_cast<float>(circum_radius);
127 circumscribed_cost_ =
static_cast<float>(result);
129 return circumscribed_cost_;
138 geometry_msgs::msg::Pose goal = utils::getCriticGoal(data, enforce_path_inversion_);
141 is_tracking_unknown_ = costmap_ros_->getLayeredCostmap()->isTrackingUnknown();
142 auto * costmap = collision_checker_.
getCostmap();
143 origin_x_ =
static_cast<float>(costmap->getOriginX());
144 origin_y_ =
static_cast<float>(costmap->getOriginY());
145 resolution_ =
static_cast<float>(costmap->getResolution());
146 size_x_ = costmap->getSizeInCellsX();
147 size_y_ = costmap->getSizeInCellsY();
149 if (consider_footprint_) {
155 bool near_goal =
false;
156 if (utils::withinPositionGoalTolerance(near_goal_distance_, data.state.pose.pose, goal)) {
160 Eigen::ArrayXf repulsive_cost(data.costs.rows());
161 repulsive_cost.setZero();
162 bool all_trajectories_collide =
true;
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>>(data.trajectories.x.data(), strided_traj_rows, strided_traj_cols,
170 Eigen::Stride<-1, -1>(outer_stride, 1));
171 const auto traj_y = Eigen::Map<
const Eigen::ArrayXXf, 0,
172 Eigen::Stride<-1, -1>>(data.trajectories.y.data(), strided_traj_rows, strided_traj_cols,
173 Eigen::Stride<-1, -1>(outer_stride, 1));
174 const auto traj_yaw = Eigen::Map<
const Eigen::ArrayXXf, 0,
175 Eigen::Stride<-1, -1>>(data.trajectories.yaws.data(), strided_traj_rows, strided_traj_cols,
176 Eigen::Stride<-1, -1>(outer_stride, 1));
178 for (
int i = 0; i < strided_traj_rows; ++i) {
179 bool trajectory_collide =
false;
180 float pose_cost = 0.0f;
181 float & traj_cost = repulsive_cost(i);
183 for (
int j = 0; j < strided_traj_cols; j++) {
184 float Tx = traj_x(i, j);
185 float Ty = traj_y(i, j);
186 unsigned int x_i = 0u, y_i = 0u;
194 pose_cost =
static_cast<float>(costmap->getCost(
getIndex(x_i, y_i)));
195 if (pose_cost < 1.0f) {
200 if (
inCollision(pose_cost, Tx, Ty, traj_yaw(i, j))) {
201 traj_cost = collision_cost_;
202 trajectory_collide =
true;
209 if (pose_cost >=
static_cast<float>(near_collision_cost_)) {
210 traj_cost += critical_cost_;
211 }
else if (!near_goal) {
212 traj_cost += pose_cost;
216 all_trajectories_collide &= trajectory_collide;
220 data.costs += (repulsive_cost *
221 (weight_ /
static_cast<float>(strided_traj_cols))).pow(power_);
223 data.costs += repulsive_cost * (weight_ /
static_cast<float>(strided_traj_cols));
226 data.fail_flag = all_trajectories_collide;
231 #include <pluginlib/class_list_macros.hpp>
233 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.
Data to pass to critics for scoring, including state, trajectories, pruned path, global goal,...