Nav2 Navigation Stack - humble  humble
ROS 2 Navigation Stack
path_align_critic.cpp
1 // Copyright (c) 2023 Open Navigation LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "nav2_mppi_controller/critics/path_align_critic.hpp"
16 
17 #include <xtensor/xfixed.hpp>
18 #include <xtensor/xmath.hpp>
19 
20 namespace mppi::critics
21 {
22 
23 using namespace xt::placeholders; // NOLINT
24 using xt::evaluation_strategy::immediate;
25 
27 {
28  auto getParam = parameters_handler_->getParamGetter(name_);
29  getParam(power_, "cost_power", 1);
30  getParam(weight_, "cost_weight", 10.0);
31 
32  getParam(max_path_occupancy_ratio_, "max_path_occupancy_ratio", 0.07);
33  getParam(offset_from_furthest_, "offset_from_furthest", 20);
34  getParam(trajectory_point_step_, "trajectory_point_step", 4);
35  getParam(
36  threshold_to_consider_,
37  "threshold_to_consider", 0.5);
38  getParam(use_path_orientations_, "use_path_orientations", false);
39 
40  RCLCPP_INFO(
41  logger_,
42  "ReferenceTrajectoryCritic instantiated with %d power and %f weight",
43  power_, weight_);
44 }
45 
47 {
48  // Don't apply close to goal, let the goal critics take over
49  if (!enabled_ || utils::withinPositionGoalTolerance(
50  threshold_to_consider_, data.state.pose.pose, data.goal))
51  {
52  return;
53  }
54 
55  // Don't apply when first getting bearing w.r.t. the path
56  utils::setPathFurthestPointIfNotSet(data);
57  const size_t path_segments_count = *data.furthest_reached_path_point; // up to furthest only
58  if (path_segments_count < offset_from_furthest_) {
59  return;
60  }
61 
62  // Don't apply when dynamic obstacles are blocking significant proportions of the local path
63  utils::setPathCostsIfNotSet(data, costmap_ros_);
64  const size_t closest_initial_path_point = utils::findPathTrajectoryInitialPoint(data);
65  unsigned int invalid_ctr = 0;
66  const float range = *data.furthest_reached_path_point - closest_initial_path_point;
67  for (size_t i = closest_initial_path_point; i < *data.furthest_reached_path_point; i++) {
68  if (!(*data.path_pts_valid)[i]) {invalid_ctr++;}
69  if (static_cast<float>(invalid_ctr) / range > max_path_occupancy_ratio_ && invalid_ctr > 2) {
70  return;
71  }
72  }
73 
74  const auto P_x = xt::view(data.path.x, xt::range(_, -1)); // path points
75  const auto P_y = xt::view(data.path.y, xt::range(_, -1)); // path points
76  const auto P_yaw = xt::view(data.path.yaws, xt::range(_, -1)); // path points
77 
78  const size_t batch_size = data.trajectories.x.shape(0);
79  const size_t time_steps = data.trajectories.x.shape(1);
80  auto && cost = xt::xtensor<float, 1>::from_shape({data.costs.shape(0)});
81 
82  // Find integrated distance in the path
83  std::vector<float> path_integrated_distances(path_segments_count, 0.0f);
84  float dx = 0.0f, dy = 0.0f;
85  for (unsigned int i = 1; i != path_segments_count; i++) {
86  dx = P_x(i) - P_x(i - 1);
87  dy = P_y(i) - P_y(i - 1);
88  float curr_dist = sqrtf(dx * dx + dy * dy);
89  path_integrated_distances[i] = path_integrated_distances[i - 1] + curr_dist;
90  }
91 
92  float traj_integrated_distance = 0.0f;
93  float summed_path_dist = 0.0f, dyaw = 0.0f;
94  float num_samples = 0.0f;
95  float Tx = 0.0f, Ty = 0.0f;
96  size_t path_pt = 0;
97  for (size_t t = 0; t < batch_size; ++t) {
98  traj_integrated_distance = 0.0f;
99  summed_path_dist = 0.0f;
100  num_samples = 0.0f;
101  path_pt = 0u;
102  const auto T_x = xt::view(data.trajectories.x, t, xt::all());
103  const auto T_y = xt::view(data.trajectories.y, t, xt::all());
104  for (size_t p = trajectory_point_step_; p < time_steps; p += trajectory_point_step_) {
105  Tx = T_x(p);
106  Ty = T_y(p);
107  dx = Tx - T_x(p - trajectory_point_step_);
108  dy = Ty - T_y(p - trajectory_point_step_);
109  traj_integrated_distance += sqrtf(dx * dx + dy * dy);
110  path_pt = utils::findClosestPathPt(
111  path_integrated_distances, traj_integrated_distance, path_pt);
112 
113  // The nearest path point to align to needs to be not in collision, else
114  // let the obstacle critic take over in this region due to dynamic obstacles
115  if ((*data.path_pts_valid)[path_pt]) {
116  dx = P_x(path_pt) - Tx;
117  dy = P_y(path_pt) - Ty;
118  num_samples += 1.0f;
119  if (use_path_orientations_) {
120  const auto T_yaw = xt::view(data.trajectories.yaws, t, xt::all());
121  dyaw = angles::shortest_angular_distance(P_yaw(path_pt), T_yaw(p));
122  summed_path_dist += sqrtf(dx * dx + dy * dy + dyaw * dyaw);
123  } else {
124  summed_path_dist += sqrtf(dx * dx + dy * dy);
125  }
126  }
127  }
128  if (num_samples > 0) {
129  cost[t] = summed_path_dist / num_samples;
130  } else {
131  cost[t] = 0.0f;
132  }
133  }
134 
135  data.costs += xt::pow(std::move(cost) * weight_, power_);
136 }
137 
138 } // namespace mppi::critics
139 
140 #include <pluginlib/class_list_macros.hpp>
141 
142 PLUGINLIB_EXPORT_CLASS(
Abstract critic objective function to score trajectories.
void score(CriticData &data) override
Evaluate cost related to trajectories path alignment.
void initialize() override
Initialize critic.
Data to pass to critics for scoring, including state, trajectories, pruned path, global goal,...
Definition: critic_data.hpp:39