Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
smoother_cost_function.hpp
1 // Copyright (c) 2021 RoboTech Vision
2 // Copyright (c) 2020, Samsung Research America
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License. Reserved.
15 
16 #ifndef NAV2_CONSTRAINED_SMOOTHER__SMOOTHER_COST_FUNCTION_HPP_
17 #define NAV2_CONSTRAINED_SMOOTHER__SMOOTHER_COST_FUNCTION_HPP_
18 
19 #include <cmath>
20 #include <vector>
21 #include <iostream>
22 #include <unordered_map>
23 #include <memory>
24 #include <queue>
25 #include <utility>
26 
27 #include "ceres/ceres.h"
28 #include "ceres/cubic_interpolation.h"
29 #include "Eigen/Core"
30 #include "nav2_costmap_2d/costmap_2d.hpp"
31 #include "nav2_constrained_smoother/options.hpp"
32 #include "nav2_constrained_smoother/utils.hpp"
33 
34 namespace nav2_constrained_smoother
35 {
36 
43 {
44 public:
56  const Eigen::Vector2d & original_pos,
57  double next_to_last_length_ratio,
58  bool reversing,
59  const nav2_costmap_2d::Costmap2D * costmap,
60  const std::shared_ptr<ceres::BiCubicInterpolator<ceres::Grid2D<unsigned char>>> &
61  costmap_interpolator,
62  const SmootherParams & params,
63  double costmap_weight_sqrt)
64  : original_pos_(original_pos),
65  next_to_last_length_ratio_(next_to_last_length_ratio),
66  reversing_(reversing),
67  params_(params),
68  costmap_weight_sqrt_(costmap_weight_sqrt),
69  costmap_origin_(costmap->getOriginX(), costmap->getOriginY()),
70  costmap_resolution_(costmap->getResolution()),
71  costmap_interpolator_(costmap_interpolator)
72  {
73  }
74 
75  ceres::CostFunction * AutoDiff()
76  {
77  return new ceres::AutoDiffCostFunction<SmootherCostFunction, 6, 2, 2, 2>(this);
78  }
79 
80  void setCostmapWeightSqrt(double costmap_weight_sqrt)
81  {
82  costmap_weight_sqrt_ = costmap_weight_sqrt;
83  }
84 
85  double getCostmapWeightSqrt()
86  {
87  return costmap_weight_sqrt_;
88  }
89 
98  template<typename T>
99  bool operator()(
100  const T * const pt, const T * const pt_next, const T * const pt_prev,
101  T * pt_residual) const
102  {
103  Eigen::Map<const Eigen::Matrix<T, 2, 1>> xi(pt);
104  Eigen::Map<const Eigen::Matrix<T, 2, 1>> xi_next(pt_next);
105  Eigen::Map<const Eigen::Matrix<T, 2, 1>> xi_prev(pt_prev);
106  Eigen::Map<Eigen::Matrix<T, 6, 1>> residual(pt_residual);
107  residual.setZero();
108 
109  // compute cost
110  addSmoothingResidual<T>(
111  params_.smooth_weight_sqrt, xi, xi_next, xi_prev, residual[0],
112  residual[1]);
113  addCurvatureResidual<T>(params_.curvature_weight_sqrt, xi, xi_next, xi_prev, residual[2]);
114  addDistanceResidual<T>(
115  params_.distance_weight_sqrt, xi,
116  original_pos_.template cast<T>(), residual[3], residual[4]);
117  addCostResidual<T>(costmap_weight_sqrt_, xi, xi_next, xi_prev, residual[5]);
118 
119  return true;
120  }
121 
122 protected:
131  template<typename T>
132  inline void addSmoothingResidual(
133  const double & weight_sqrt,
134  const Eigen::Matrix<T, 2, 1> & pt,
135  const Eigen::Matrix<T, 2, 1> & pt_next,
136  const Eigen::Matrix<T, 2, 1> & pt_prev,
137  T & r1, T & r2) const
138  {
139  Eigen::Matrix<T, 2, 1> d_next = pt_next - pt;
140  Eigen::Matrix<T, 2, 1> d_prev = pt - pt_prev;
141  Eigen::Matrix<T, 2, 1> d_diff = next_to_last_length_ratio_ * d_next - d_prev;
142  r1 += (T)weight_sqrt * d_diff(0, 0); // objective function value
143  r2 += (T)weight_sqrt * d_diff(1, 0);
144  }
145 
155  template<typename T>
156  inline void addCurvatureResidual(
157  const double & weight_sqrt,
158  const Eigen::Matrix<T, 2, 1> & pt,
159  const Eigen::Matrix<T, 2, 1> & pt_next,
160  const Eigen::Matrix<T, 2, 1> & pt_prev,
161  T & r) const
162  {
163  Eigen::Matrix<T, 2, 1> center = arcCenter(
164  pt_prev, pt, pt_next,
165  next_to_last_length_ratio_ < 0);
166  if (CERES_ISINF(center[0])) {
167  return;
168  }
169  T turning_rad = (pt - center).norm();
170  T ki_minus_kmax = (T)1.0 / turning_rad - params_.max_curvature;
171 
172  if (ki_minus_kmax <= (T)EPSILON) {
173  return;
174  }
175 
176  r += (T)weight_sqrt * ki_minus_kmax; // objective function value
177  }
178 
186  template<typename T>
187  inline void addDistanceResidual(
188  const double & weight_sqrt,
189  const Eigen::Matrix<T, 2, 1> & xi,
190  const Eigen::Matrix<T, 2, 1> & xi_original,
191  T & r1, T & r2) const
192  {
193  Eigen::Matrix<T, 2, 1> diff = xi - xi_original;
194  r1 += (T)weight_sqrt * diff(0, 0);
195  r2 += (T)weight_sqrt * diff(1, 0);
196  }
197 
205  template<typename T>
206  inline void addCostResidual(
207  const double & weight_sqrt,
208  const Eigen::Matrix<T, 2, 1> & pt,
209  const Eigen::Matrix<T, 2, 1> & pt_next,
210  const Eigen::Matrix<T, 2, 1> & pt_prev,
211  T & r) const
212  {
213  if (params_.cost_check_points.empty()) {
214  Eigen::Matrix<T, 2, 1> interp_pos =
215  (pt - costmap_origin_.template cast<T>()) / (T)costmap_resolution_;
216  T value;
217  costmap_interpolator_->Evaluate(interp_pos[1] - (T)0.5, interp_pos[0] - (T)0.5, &value);
218  r += (T)weight_sqrt * value; // objective function value
219  } else {
220  Eigen::Matrix<T, 2, 1> dir = tangentDir(
221  pt_prev, pt, pt_next,
222  next_to_last_length_ratio_ < 0);
223  dir.normalize();
224  if (((pt_next - pt).dot(dir) < (T)0) != reversing_) {
225  dir = -dir;
226  }
227  Eigen::Matrix<T, 3, 3> transform;
228  transform << dir[0], -dir[1], pt[0],
229  dir[1], dir[0], pt[1],
230  (T)0, (T)0, (T)1;
231  for (size_t i = 0; i < params_.cost_check_points.size(); i += 3) {
232  Eigen::Matrix<T, 3, 1> ccpt((T)params_.cost_check_points[i],
233  (T)params_.cost_check_points[i + 1], (T)1);
234  auto ccpt_world = (transform * ccpt).template block<2, 1>(0, 0);
235  Eigen::Matrix<T, 2,
236  1> interp_pos = (ccpt_world - costmap_origin_.template cast<T>()) /
237  (T)costmap_resolution_;
238  T value;
239  costmap_interpolator_->Evaluate(interp_pos[1] - (T)0.5, interp_pos[0] - (T)0.5, &value);
240 
241  r += (T)weight_sqrt * (T)params_.cost_check_points[i + 2] * value;
242  }
243  }
244  }
245 
246  const Eigen::Vector2d original_pos_;
247  double next_to_last_length_ratio_;
248  bool reversing_;
249  SmootherParams params_;
250  double costmap_weight_sqrt_;
251  Eigen::Vector2d costmap_origin_;
252  double costmap_resolution_;
253  std::shared_ptr<ceres::BiCubicInterpolator<ceres::Grid2D<unsigned char>>> costmap_interpolator_;
254 };
255 
256 } // namespace nav2_constrained_smoother
257 
258 #endif // NAV2_CONSTRAINED_SMOOTHER__SMOOTHER_COST_FUNCTION_HPP_
Cost function for path smoothing with multiple terms including curvature, smoothness,...
bool operator()(const T *const pt, const T *const pt_next, const T *const pt_prev, T *pt_residual) const
Smoother cost function evaluation.
void addCostResidual(const double &weight_sqrt, const Eigen::Matrix< T, 2, 1 > &pt, const Eigen::Matrix< T, 2, 1 > &pt_next, const Eigen::Matrix< T, 2, 1 > &pt_prev, T &r) const
Cost function term for steering away from costs.
void addSmoothingResidual(const double &weight_sqrt, const Eigen::Matrix< T, 2, 1 > &pt, const Eigen::Matrix< T, 2, 1 > &pt_next, const Eigen::Matrix< T, 2, 1 > &pt_prev, T &r1, T &r2) const
Cost function term for smooth paths.
void addCurvatureResidual(const double &weight_sqrt, const Eigen::Matrix< T, 2, 1 > &pt, const Eigen::Matrix< T, 2, 1 > &pt_next, const Eigen::Matrix< T, 2, 1 > &pt_prev, T &r) const
Cost function term for maximum curved paths.
SmootherCostFunction(const Eigen::Vector2d &original_pos, double next_to_last_length_ratio, bool reversing, const nav2_costmap_2d::Costmap2D *costmap, const std::shared_ptr< ceres::BiCubicInterpolator< ceres::Grid2D< unsigned char >>> &costmap_interpolator, const SmootherParams &params, double costmap_weight_sqrt)
A constructor for nav2_constrained_smoother::SmootherCostFunction.
void addDistanceResidual(const double &weight_sqrt, const Eigen::Matrix< T, 2, 1 > &xi, const Eigen::Matrix< T, 2, 1 > &xi_original, T &r1, T &r2) const
Cost function derivative term for steering away changes in pose.
A 2D costmap provides a mapping between points in the world and their associated "costs".
Definition: costmap_2d.hpp:69