spline_interpolation_points_2d.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Copyright 2021 Tier IV, Inc.
  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. #include "interpolation/spline_interpolation_points_2d.hpp"
  15. #include <vector>
  16. #include <math.h>
  17. #include <algorithm>
  18. #include <cstdint>
  19. #include <iomanip>
  20. #include <random>
  21. namespace
  22. {
  23. std::vector<double> calcEuclidDist(const std::vector<double> & x, const std::vector<double> & y)
  24. {
  25. if (x.size() != y.size()) {
  26. return std::vector<double>{};
  27. }
  28. std::vector<double> dist_v;
  29. dist_v.push_back(0.0);
  30. for (size_t i = 0; i < x.size() - 1; ++i) {
  31. const double dx = x.at(i + 1) - x.at(i);
  32. const double dy = y.at(i + 1) - y.at(i);
  33. dist_v.push_back(dist_v.at(i) + std::hypot(dx, dy));
  34. }
  35. return dist_v;
  36. }
  37. std::array<std::vector<double>, 4> getBaseValues(
  38. const std::vector<iv::ADCPoint> & points)
  39. {
  40. // calculate x, y
  41. std::vector<double> base_x;
  42. std::vector<double> base_y;
  43. std::vector<double> base_z;
  44. for (size_t i = 0; i < points.size(); i++) {
  45. const auto & current_pos = points.at(i);
  46. if (i > 0) {
  47. const auto & prev_pos = points.at(i - 1);
  48. if (
  49. std::fabs(current_pos.x - prev_pos.x) < 1e-6 &&
  50. std::fabs(current_pos.y - prev_pos.y) < 1e-6) {
  51. continue;
  52. }
  53. }
  54. base_x.push_back(current_pos.x);
  55. base_y.push_back(current_pos.y);
  56. base_z.push_back(current_pos.z);
  57. }
  58. // calculate base_keys, base_values
  59. if (base_x.size() < 2 || base_y.size() < 2 || base_z.size() < 2) {
  60. throw std::logic_error("The number of unique points is not enough.");
  61. }
  62. const std::vector<double> base_s = calcEuclidDist(base_x, base_y);
  63. return {base_s, base_x, base_y, base_z};
  64. }
  65. } // namespace
  66. namespace interpolation
  67. {
  68. std::array<std::vector<double>, 3> slerp2dFromXY(
  69. const std::vector<double> & base_keys, const std::vector<double> & base_x_values,
  70. const std::vector<double> & base_y_values, const std::vector<double> & query_keys)
  71. {
  72. // calculate spline coefficients
  73. SplineInterpolation interpolator_x(base_keys, base_x_values);
  74. SplineInterpolation interpolator_y(base_keys, base_y_values);
  75. const auto diff_x = interpolator_x.getSplineInterpolatedDiffValues(query_keys);
  76. const auto diff_y = interpolator_y.getSplineInterpolatedDiffValues(query_keys);
  77. // calculate yaw
  78. std::vector<double> yaw_vec;
  79. for (size_t i = 0; i < diff_x.size(); i++) {
  80. double yaw = std::atan2(diff_y[i], diff_x[i]);
  81. yaw_vec.push_back(yaw);
  82. }
  83. // interpolate base_keys at query_keys
  84. return {
  85. interpolator_x.getSplineInterpolatedValues(query_keys),
  86. interpolator_y.getSplineInterpolatedValues(query_keys), yaw_vec};
  87. }
  88. template <typename T>
  89. std::vector<double> splineYawFromPoints(const std::vector<T> & points)
  90. {
  91. // calculate spline coefficients
  92. SplineInterpolationPoints2d interpolator(points);
  93. // interpolate base_keys at query_keys
  94. std::vector<double> yaw_vec;
  95. for (size_t i = 0; i < points.size(); ++i) {
  96. const double yaw = interpolator.getSplineInterpolatedYaw(i, 0.0);
  97. yaw_vec.push_back(yaw);
  98. }
  99. return yaw_vec;
  100. }
  101. /*template std::vector<double> splineYawFromPoints(
  102. const std::vector<ADCPoint> & points);
  103. */
  104. } // namespace interpolation
  105. iv::ADCQuaternion SplineInterpolationPoints2d::createQuaternionFromYaw(double yaw) const
  106. {
  107. double pitch = 0;
  108. double roll = 0;
  109. double cy = cos(yaw * 0.5);
  110. double sy = sin(yaw * 0.5);
  111. double cp = cos(pitch * 0.5);
  112. double sp = sin(pitch * 0.5);
  113. double cr = cos(roll * 0.5);
  114. double sr = sin(roll * 0.5);
  115. iv::ADCQuaternion q;
  116. q.w = cy * cp * cr + sy * sp * sr;
  117. q.x = cy * cp * sr - sy * sp * cr;
  118. q.y = sy * cp * sr + cy * sp * cr;
  119. q.z = sy * cp * cr - cy * sp * sr;
  120. return q;
  121. }
  122. iv::ADCPose SplineInterpolationPoints2d::getSplineInterpolatedPose(
  123. const size_t idx, const double s) const
  124. {
  125. iv::ADCPose pose;
  126. pose.position = getSplineInterpolatedPoint(idx, s);
  127. pose.orientation =
  128. createQuaternionFromYaw(getSplineInterpolatedYaw(idx, s));
  129. return pose;
  130. }
  131. iv::ADCPoint SplineInterpolationPoints2d::getSplineInterpolatedPoint(
  132. const size_t idx, const double s) const
  133. {
  134. if (base_s_vec_.size() <= idx) {
  135. throw std::out_of_range("idx is out of range.");
  136. }
  137. double whole_s = base_s_vec_.at(idx) + s;
  138. if (whole_s < base_s_vec_.front()) {
  139. whole_s = base_s_vec_.front();
  140. }
  141. if (whole_s > base_s_vec_.back()) {
  142. whole_s = base_s_vec_.back();
  143. }
  144. const double x = spline_x_.getSplineInterpolatedValues({whole_s}).at(0);
  145. const double y = spline_y_.getSplineInterpolatedValues({whole_s}).at(0);
  146. const double z = spline_z_.getSplineInterpolatedValues({whole_s}).at(0);
  147. iv::ADCPoint geom_point;
  148. geom_point.x = x;
  149. geom_point.y = y;
  150. geom_point.z = z;
  151. return geom_point;
  152. }
  153. double SplineInterpolationPoints2d::getSplineInterpolatedYaw(const size_t idx, const double s) const
  154. {
  155. if (base_s_vec_.size() <= idx) {
  156. throw std::out_of_range("idx is out of range.");
  157. }
  158. const double whole_s =
  159. std::clamp(base_s_vec_.at(idx) + s, base_s_vec_.front(), base_s_vec_.back());
  160. const double diff_x = spline_x_.getSplineInterpolatedDiffValues({whole_s}).at(0);
  161. const double diff_y = spline_y_.getSplineInterpolatedDiffValues({whole_s}).at(0);
  162. return std::atan2(diff_y, diff_x);
  163. }
  164. std::vector<double> SplineInterpolationPoints2d::getSplineInterpolatedYaws() const
  165. {
  166. std::vector<double> yaw_vec;
  167. for (size_t i = 0; i < spline_x_.getSize(); ++i) {
  168. const double yaw = getSplineInterpolatedYaw(i, 0.0);
  169. yaw_vec.push_back(yaw);
  170. }
  171. return yaw_vec;
  172. }
  173. double SplineInterpolationPoints2d::getSplineInterpolatedCurvature(
  174. const size_t idx, const double s) const
  175. {
  176. if (base_s_vec_.size() <= idx) {
  177. throw std::out_of_range("idx is out of range.");
  178. }
  179. const double whole_s =
  180. std::clamp(base_s_vec_.at(idx) + s, base_s_vec_.front(), base_s_vec_.back());
  181. const double diff_x = spline_x_.getSplineInterpolatedDiffValues({whole_s}).at(0);
  182. const double diff_y = spline_y_.getSplineInterpolatedDiffValues({whole_s}).at(0);
  183. const double quad_diff_x = spline_x_.getSplineInterpolatedQuadDiffValues({whole_s}).at(0);
  184. const double quad_diff_y = spline_y_.getSplineInterpolatedQuadDiffValues({whole_s}).at(0);
  185. return (diff_x * quad_diff_y - quad_diff_x * diff_y) /
  186. std::pow(std::pow(diff_x, 2) + std::pow(diff_y, 2), 1.5);
  187. }
  188. std::vector<double> SplineInterpolationPoints2d::getSplineInterpolatedCurvatures() const
  189. {
  190. std::vector<double> curvature_vec;
  191. for (size_t i = 0; i < spline_x_.getSize(); ++i) {
  192. const double curvature = getSplineInterpolatedCurvature(i, 0.0);
  193. curvature_vec.push_back(curvature);
  194. }
  195. return curvature_vec;
  196. }
  197. size_t SplineInterpolationPoints2d::getOffsetIndex(const size_t idx, const double offset) const
  198. {
  199. const double whole_s = base_s_vec_.at(idx) + offset;
  200. for (size_t s_idx = 0; s_idx < base_s_vec_.size(); ++s_idx) {
  201. if (whole_s < base_s_vec_.at(s_idx)) {
  202. return s_idx;
  203. }
  204. }
  205. return base_s_vec_.size() - 1;
  206. }
  207. double SplineInterpolationPoints2d::getAccumulatedLength(const size_t idx) const
  208. {
  209. if (base_s_vec_.size() <= idx) {
  210. throw std::out_of_range("idx is out of range.");
  211. }
  212. return base_s_vec_.at(idx);
  213. }
  214. void SplineInterpolationPoints2d::calcSplineCoefficientsInner(
  215. const std::vector<iv::ADCPoint> & points)
  216. {
  217. const auto base = getBaseValues(points);
  218. base_s_vec_ = base.at(0);
  219. const auto & base_x_vec = base.at(1);
  220. const auto & base_y_vec = base.at(2);
  221. const auto & base_z_vec = base.at(3);
  222. // calculate spline coefficients
  223. spline_x_ = SplineInterpolation(base_s_vec_, base_x_vec);
  224. spline_y_ = SplineInterpolation(base_s_vec_, base_y_vec);
  225. spline_z_ = SplineInterpolation(base_s_vec_, base_z_vec);
  226. }