You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

compute_st.cpp 7.1 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #include "basic/basic.h"
  2. #include "geo/private/math/math.h"
  3. #include "geo/private/math/distance.h"
  4. #include "geo/private/util/angle_util.h"
  5. #include "geo/private/math/compute_st.h"
  6. #include "geo/private/math/ns_geom_math.h"
  7. namespace ns
  8. {
  9. namespace geo
  10. {
  11. // 参考网址: https://github.com/udacity/CarND-Path-Planning-Project/blob/master/src/helpers.h
  12. namespace
  13. {
  14. #if 0
  15. // Calculate closest waypoint to current x, y position
  16. int ClosestWaypoint(double x, double y, const std::vector<double> &maps_x, const std::vector<double> &maps_y)
  17. {
  18. double closestLen = 100000; // large number
  19. int closestWaypoint = 0;
  20. for (int i = 0; i < (int)maps_x.size(); ++i)
  21. {
  22. double map_x = maps_x[i];
  23. double map_y = maps_y[i];
  24. double dist = flat_distance(x, y, map_x, map_y);
  25. if (dist < closestLen)
  26. {
  27. closestLen = dist;
  28. closestWaypoint = i;
  29. }
  30. }
  31. return closestWaypoint;
  32. }
  33. // Returns next waypoint of the closest waypoint
  34. int NextWaypoint(double x, double y, double theta, const std::vector<double> &maps_x, const std::vector<double> &maps_y)
  35. {
  36. int closestWaypoint = ClosestWaypoint(x, y, maps_x, maps_y);
  37. double map_x = maps_x[closestWaypoint];
  38. double map_y = maps_y[closestWaypoint];
  39. double heading = atan2((map_y - y), (map_x - x));
  40. double angle = fabs(theta - heading);
  41. angle = std::min(2 * c_pi() - angle, angle);
  42. if (angle > c_pi_2())
  43. {
  44. ++closestWaypoint;
  45. if (closestWaypoint == (int)maps_x.size())
  46. {
  47. closestWaypoint = 0;
  48. }
  49. }
  50. return closestWaypoint;
  51. }
  52. // Transform from Cartesian x,y coordinates to Frenet s,d coordinates
  53. std::vector<double> getFrenet(double x, double y, double theta, const std::vector<double> &maps_x, const std::vector<double> &maps_y)
  54. {
  55. int next_wp = NextWaypoint(x, y, theta, maps_x, maps_y);
  56. int prev_wp;
  57. prev_wp = next_wp - 1;
  58. if (next_wp == 0)
  59. {
  60. prev_wp = maps_x.size() - 1;
  61. }
  62. double n_x = maps_x[next_wp] - maps_x[prev_wp];
  63. double n_y = maps_y[next_wp] - maps_y[prev_wp];
  64. double x_x = x - maps_x[prev_wp];
  65. double x_y = y - maps_y[prev_wp];
  66. //LOG_DEBUG("x: {:.8f}, y: {:.8f}", x, y);
  67. // find the projection of x onto n
  68. // TODO 这个没有看明白,现象是可能存在
  69. double proj_norm = (x_x * n_x + x_y * n_y) / (n_x * n_x + n_y * n_y);
  70. double proj_x = proj_norm * n_x;
  71. double proj_y = proj_norm * n_y;
  72. //LOG_DEBUG("project point: {:.8f}, {:.8f}", proj_x, proj_y);
  73. double frenet_d = flat_distance(x_x, x_y, proj_x, proj_y);
  74. // // see if d value is positive or negative by comparing it to a center point
  75. // double center_x = 1000 - maps_x[prev_wp];
  76. // double center_y = 2000 - maps_y[prev_wp];
  77. // double centerToPos = flat_distance(center_x, center_y, x_x, x_y);
  78. // double centerToRef = flat_distance(center_x, center_y, proj_x, proj_y);
  79. // if (centerToPos <= centerToRef)
  80. // {
  81. // frenet_d *= -1;
  82. // }
  83. // calculate s value
  84. double frenet_s = 0;
  85. for (int i = 0; i < prev_wp; ++i)
  86. {
  87. frenet_s += flat_distance(maps_x[i], maps_y[i], maps_x[i + 1], maps_y[i + 1]);
  88. }
  89. frenet_s += flat_distance(0, 0, proj_x, proj_y);
  90. return {frenet_s, frenet_d};
  91. }
  92. #endif
  93. #if 1
  94. /**
  95. * @brief 获取指定点到指定polyline上的最近距离以及polyline上对应的点的坐标
  96. *
  97. * @param pts 指定的polyline
  98. * @param pos 指定的坐标点
  99. * @param foot polyline上距离pos最近的点
  100. * @param preIndex
  101. * @param beginIndex 从beginIndex点开始抓路
  102. * polyline上foot之前point的index,若foot和polyline上某一点重合,preIndex也是重合点之前点的下标
  103. * @return double
  104. */
  105. double grabLine(std::vector<PointDST> pts, const PointD& pos, PointD& foot, int32_t& preIndex,
  106. int32_t beginIndex = 0)
  107. {
  108. double dis = basic::DOUBLE_MAX;
  109. if (pts.size() >= 2)
  110. {
  111. for (size_t i = beginIndex; i < pts.size() - 1; ++i)
  112. {
  113. PointD tmp;
  114. double d = pointSegmentDistance(pos, pts[i].p, pts[i + 1].p, tmp);
  115. if (d < dis)
  116. {
  117. dis = d;
  118. foot = tmp;
  119. preIndex = static_cast<int32_t>(i);
  120. }
  121. }
  122. }
  123. return dis;
  124. }
  125. // Transform from Cartesian x,y coordinates to Frenet s,d coordinates
  126. // 输入参考线的点的个数不能小于2,否则结果未知, 目前t应该是DOUBLE_MAX
  127. std::vector<double> getFrenet(const PointD& pos, const std::vector<PointDST>& referLine,
  128. int32_t& preIndex, int32_t beginIndex = 0)
  129. {
  130. PointD foot;
  131. double frenet_d = grabLine(referLine, pos, foot, preIndex, beginIndex);
  132. if (frenet_d < basic::DOUBLE_MAX)
  133. {
  134. int32_t side = JudgeSideness(referLine[preIndex].p, referLine[preIndex + 1].p, pos);
  135. if (side < 0)
  136. {
  137. frenet_d *= -1;
  138. }
  139. double frenet_s = 0;
  140. frenet_s += referLine[preIndex].s;
  141. frenet_s += referLine[preIndex].p.distance(foot);
  142. return {frenet_s, frenet_d};
  143. }
  144. return {};
  145. }
  146. #endif
  147. } // namespace
  148. // 求某一个点的st值
  149. std::vector<double> computePointST(const PointD& p, const std::vector<PointDST>& referLine)
  150. {
  151. if (referLine.size() >= 2)
  152. {
  153. int32_t preIndex;
  154. return getFrenet(p, referLine, preIndex);
  155. }
  156. return std::vector<double>();
  157. }
  158. // 求一条参考线的所有st值
  159. int computePolylineST(std::vector<PointDST>& polyline, const std::vector<PointDST>& referLine,
  160. bool increase)
  161. {
  162. if (polyline.size() < 2)
  163. {
  164. return -1;
  165. }
  166. int32_t preIndex = 0;
  167. for (size_t i = 0; i < polyline.size(); i++)
  168. {
  169. int beginIndex = increase ? preIndex : 0;
  170. std::vector<double> results = getFrenet(polyline.at(i).p, referLine, preIndex, beginIndex);
  171. if (results.empty())
  172. return -1;
  173. polyline.at(i).s = results[0];
  174. polyline.at(i).t = results[1];
  175. }
  176. return 0;
  177. }
  178. // TODO 要考虑越界以及点之间有重合的问题
  179. // Transform from Frenet s,d coordinates to Cartesian x,y
  180. PointD getXY(double s, double d, const std::vector<PointDST>& referLine)
  181. {
  182. int prev_wp = -1;
  183. for (size_t i = 0; i < referLine.size() - 1; i++)
  184. {
  185. if (s >= referLine[i].s)
  186. prev_wp = static_cast<int>(i);
  187. }
  188. int wp2 = (prev_wp + 1); // 上面已经确保不会越界
  189. double heading = atan2((referLine[wp2].p.y - referLine[prev_wp].p.y),
  190. (referLine[wp2].p.x - referLine[prev_wp].p.x));
  191. // the x,y,s along the segment
  192. double seg_s = (s - referLine[prev_wp].s);
  193. double seg_x = referLine[prev_wp].p.x + seg_s * cos(heading);
  194. double seg_y = referLine[prev_wp].p.y + seg_s * sin(heading);
  195. double perp_heading = heading + c_pi_2();
  196. PointD pos;
  197. pos.x = seg_x + d * cos(perp_heading);
  198. pos.y = seg_y + d * sin(perp_heading);
  199. pos.z = referLine[prev_wp].p.z;
  200. return pos;
  201. }
  202. } // namespace geo
  203. } // namespace ns