Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
utils.hpp
1 // Copyright (c) 2021 RoboTech Vision
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 #ifndef NAV2_CONSTRAINED_SMOOTHER__UTILS_HPP_
16 #define NAV2_CONSTRAINED_SMOOTHER__UTILS_HPP_
17 
18 #include <limits>
19 #include "Eigen/Core"
20 
21 #define EPSILON 0.0001
22 
27 #if defined(USE_OLD_CERES_API)
28  #define CERES_ISINF(x) ceres::IsInfinite(x)
29 #else
30  #define CERES_ISINF(x) ceres::isinf(x)
31 #endif
32 
33 namespace nav2_constrained_smoother
34 {
35 
44 template<typename T>
45 inline Eigen::Matrix<T, 2, 1> arcCenter(
46  Eigen::Matrix<T, 2, 1> pt_prev,
47  Eigen::Matrix<T, 2, 1> pt,
48  Eigen::Matrix<T, 2, 1> pt_next,
49  bool is_cusp)
50 {
51  Eigen::Matrix<T, 2, 1> d1 = pt - pt_prev;
52  Eigen::Matrix<T, 2, 1> d2 = pt_next - pt;
53 
54  if (is_cusp) {
55  d2 = -d2;
56  pt_next = pt + d2;
57  }
58 
59  T det = d1[0] * d2[1] - d1[1] * d2[0];
60  if (ceres::abs(det) < (T)1e-4) { // straight line
61  return Eigen::Matrix<T, 2, 1>(
62  (T)std::numeric_limits<double>::infinity(), (T)std::numeric_limits<double>::infinity());
63  }
64 
65  // circle center is at the intersection of mirror axes of the segments:
66  // http://paulbourke.net/geometry/circlesphere/
67  // line intersection:
68  // https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Intersection%20of%20two%20lines
69  Eigen::Matrix<T, 2, 1> mid1 = (pt_prev + pt) / (T)2;
70  Eigen::Matrix<T, 2, 1> mid2 = (pt + pt_next) / (T)2;
71  Eigen::Matrix<T, 2, 1> n1(-d1[1], d1[0]);
72  Eigen::Matrix<T, 2, 1> n2(-d2[1], d2[0]);
73  T det1 = (mid1[0] + n1[0]) * mid1[1] - (mid1[1] + n1[1]) * mid1[0];
74  T det2 = (mid2[0] + n2[0]) * mid2[1] - (mid2[1] + n2[1]) * mid2[0];
75  Eigen::Matrix<T, 2, 1> center((det1 * n2[0] - det2 * n1[0]) / det,
76  (det1 * n2[1] - det2 * n1[1]) / det);
77  return center;
78 }
79 
91 template<typename T>
92 inline Eigen::Matrix<T, 2, 1> tangentDir(
93  Eigen::Matrix<T, 2, 1> pt_prev,
94  Eigen::Matrix<T, 2, 1> pt,
95  Eigen::Matrix<T, 2, 1> pt_next,
96  bool is_cusp)
97 {
98  Eigen::Matrix<T, 2, 1> center = arcCenter(pt_prev, pt, pt_next, is_cusp);
99  if (CERES_ISINF(center[0])) { // straight line
100  Eigen::Matrix<T, 2, 1> d1 = pt - pt_prev;
101  Eigen::Matrix<T, 2, 1> d2 = pt_next - pt;
102 
103  if (is_cusp) {
104  d2 = -d2;
105  pt_next = pt + d2;
106  }
107 
108  Eigen::Matrix<T, 2, 1> result(pt_next[0] - pt_prev[0], pt_next[1] - pt_prev[1]);
109  if (result[0] == 0.0 && result[1] == 0.0) { // a very rare edge situation
110  return Eigen::Matrix<T, 2, 1>(d1[1], -d1[0]);
111  }
112  return result;
113  }
114 
115  // tangent is perpendicular to (pt - center)
116  // Note: not determining + or - direction here, this should be handled at the caller side
117  return Eigen::Matrix<T, 2, 1>(center[1] - pt[1], pt[0] - center[0]);
118 }
119 
120 } // namespace nav2_constrained_smoother
121 
122 #endif // NAV2_CONSTRAINED_SMOOTHER__UTILS_HPP_