mpc_utils.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. // Copyright 2018-2021 The Autoware Foundation
  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 "mpc_lateral_controller/mpc_utils.hpp"
  15. #include "interpolation/linear_interpolation.hpp"
  16. #include "interpolation/spline_interpolation.hpp"
  17. #include "motion_utils/trajectory/trajectory.hpp"
  18. #include "tier4_autoware_utils/geometry/geometry.hpp"
  19. #include "tier4_autoware_utils/math/normalization.hpp"
  20. #include <algorithm>
  21. #include <limits>
  22. #include <string>
  23. #include <vector>
  24. namespace autoware::motion::control::mpc_lateral_controller
  25. {
  26. namespace
  27. {
  28. double calcLongitudinalOffset(
  29. const geometry_msgs::msg::Point & p_front, const geometry_msgs::msg::Point & p_back,
  30. const geometry_msgs::msg::Point & p_target)
  31. {
  32. const Eigen::Vector3d segment_vec{p_back.x - p_front.x, p_back.y - p_front.y, 0};
  33. const Eigen::Vector3d target_vec{p_target.x - p_front.x, p_target.y - p_front.y, 0};
  34. return segment_vec.dot(target_vec) / segment_vec.norm();
  35. }
  36. } // namespace
  37. namespace MPCUtils
  38. {
  39. //using tier4_autoware_utils::calcDistance2d;
  40. //using tier4_autoware_utils::createQuaternionFromYaw;
  41. //using tier4_autoware_utils::normalizeRadian;
  42. double ADCgetYaw(iv::Quaternion_ q)
  43. {
  44. // yaw (z-axis rotation)
  45. double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
  46. double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
  47. double yaw = std::atan2(siny_cosp, cosy_cosp);
  48. return yaw;
  49. }
  50. double calcDistance2d(const MPCTrajectory & trajectory, const size_t idx1, const size_t idx2)
  51. {
  52. const double dx = trajectory.x.at(idx1) - trajectory.x.at(idx2);
  53. const double dy = trajectory.y.at(idx1) - trajectory.y.at(idx2);
  54. return std::hypot(dx, dy);
  55. }
  56. double calcDistance3d(const MPCTrajectory & trajectory, const size_t idx1, const size_t idx2)
  57. {
  58. const double dx = trajectory.x.at(idx1) - trajectory.x.at(idx2);
  59. const double dy = trajectory.y.at(idx1) - trajectory.y.at(idx2);
  60. const double dz = trajectory.z.at(idx1) - trajectory.z.at(idx2);
  61. return std::hypot(dx, dy, dz);
  62. }
  63. void convertEulerAngleToMonotonic(std::vector<double> & angle_vector)
  64. {
  65. for (uint i = 1; i < angle_vector.size(); ++i) {
  66. const double da = angle_vector.at(i) - angle_vector.at(i - 1);
  67. angle_vector.at(i) = angle_vector.at(i - 1) + normalizeRadian(da);
  68. }
  69. }
  70. //double calcLateralError(const Pose & ego_pose, const Pose & ref_pose)
  71. //{
  72. // const double err_x = ego_pose.position.x - ref_pose.position.x;
  73. // const double err_y = ego_pose.position.y - ref_pose.position.y;
  74. // const double ref_yaw = tf2::getYaw(ref_pose.orientation);
  75. // const double lat_err = -std::sin(ref_yaw) * err_x + std::cos(ref_yaw) * err_y;
  76. // return lat_err;
  77. //}
  78. double calcLateralError(const iv::ADCPose & ego_pose, const iv::ADCPose & ref_pose)
  79. {
  80. const double err_x = ego_pose.position.x - ref_pose.position.x;
  81. const double err_y = ego_pose.position.y - ref_pose.position.y;
  82. const double ref_yaw = ADCgetYaw(ref_pose.orientation);
  83. const double lat_err = -std::sin(ref_yaw) * err_x + std::cos(ref_yaw) * err_y;
  84. return lat_err;
  85. }
  86. void calcMPCTrajectoryArcLength(const MPCTrajectory & trajectory, std::vector<double> & arc_length)
  87. {
  88. double dist = 0.0;
  89. arc_length.clear();
  90. arc_length.push_back(dist);
  91. for (uint i = 1; i < trajectory.size(); ++i) {
  92. dist += calcDistance2d(trajectory, i, i - 1);
  93. arc_length.push_back(dist);
  94. }
  95. }
  96. std::pair<bool, MPCTrajectory> resampleMPCTrajectoryByDistance(
  97. const MPCTrajectory & input, const double resample_interval_dist, const size_t nearest_seg_idx,
  98. const double ego_offset_to_segment)
  99. {
  100. MPCTrajectory output;
  101. if (input.empty()) {
  102. return {true, output};
  103. }
  104. std::vector<double> input_arclength;
  105. calcMPCTrajectoryArcLength(input, input_arclength);
  106. if (input_arclength.empty()) {
  107. return {false, output};
  108. }
  109. std::vector<double> output_arclength;
  110. // To accurately sample the ego point, resample separately in the forward direction and the
  111. // backward direction from the current position.
  112. for (double s = std::clamp(
  113. input_arclength.at(nearest_seg_idx) + ego_offset_to_segment, 0.0,
  114. input_arclength.back() - 1e-6);
  115. 0 <= s; s -= resample_interval_dist) {
  116. output_arclength.push_back(s);
  117. }
  118. std::reverse(output_arclength.begin(), output_arclength.end());
  119. for (double s = std::max(input_arclength.at(nearest_seg_idx) + ego_offset_to_segment, 0.0) +
  120. resample_interval_dist;
  121. s < input_arclength.back(); s += resample_interval_dist) {
  122. output_arclength.push_back(s);
  123. }
  124. std::vector<double> input_yaw = input.yaw;
  125. convertEulerAngleToMonotonic(input_yaw);
  126. const auto lerp_arc_length = [&](const auto & input_value) {
  127. return interpolation::lerp(input_arclength, input_value, output_arclength);
  128. };
  129. const auto spline_arc_length = [&](const auto & input_value) {
  130. return interpolation::spline(input_arclength, input_value, output_arclength);
  131. };
  132. output.x = spline_arc_length(input.x);
  133. output.y = spline_arc_length(input.y);
  134. output.z = spline_arc_length(input.z);
  135. output.yaw = spline_arc_length(input.yaw);
  136. output.vx = lerp_arc_length(input.vx); // must be linear
  137. output.k = spline_arc_length(input.k);
  138. output.smooth_k = spline_arc_length(input.smooth_k);
  139. output.relative_time = lerp_arc_length(input.relative_time); // must be linear
  140. return {true, output};
  141. }
  142. bool linearInterpMPCTrajectory(
  143. const std::vector<double> & in_index, const MPCTrajectory & in_traj,
  144. const std::vector<double> & out_index, MPCTrajectory & out_traj)
  145. {
  146. if (in_traj.empty()) {
  147. out_traj = in_traj;
  148. return true;
  149. }
  150. std::vector<double> in_traj_yaw = in_traj.yaw;
  151. convertEulerAngleToMonotonic(in_traj_yaw);
  152. const auto lerp_arc_length = [&](const auto & input_value) {
  153. return interpolation::lerp(in_index, input_value, out_index);
  154. };
  155. try {
  156. out_traj.x = lerp_arc_length(in_traj.x);
  157. out_traj.y = lerp_arc_length(in_traj.y);
  158. out_traj.z = lerp_arc_length(in_traj.z);
  159. out_traj.yaw = lerp_arc_length(in_traj.yaw);
  160. out_traj.vx = lerp_arc_length(in_traj.vx);
  161. out_traj.k = lerp_arc_length(in_traj.k);
  162. out_traj.smooth_k = lerp_arc_length(in_traj.smooth_k);
  163. out_traj.relative_time = lerp_arc_length(in_traj.relative_time);
  164. } catch (const std::exception & e) {
  165. std::cerr << "linearInterpMPCTrajectory error!: " << e.what() << std::endl;
  166. }
  167. if (out_traj.empty()) {
  168. std::cerr << "[mpc util] linear interpolation error" << std::endl;
  169. return false;
  170. }
  171. return true;
  172. }
  173. void calcTrajectoryYawFromXY(MPCTrajectory & traj, const bool is_forward_shift)
  174. {
  175. if (traj.yaw.size() < 3) { // at least 3 points are required to calculate yaw
  176. return;
  177. }
  178. if (traj.yaw.size() != traj.vx.size()) {
  179. RCLCPP_ERROR(rclcpp::get_logger("mpc_utils"), "trajectory size has no consistency.");
  180. return;
  181. }
  182. // interpolate yaw
  183. for (int i = 1; i < static_cast<int>(traj.yaw.size()) - 1; ++i) {
  184. const double dx = traj.x.at(i + 1) - traj.x.at(i - 1);
  185. const double dy = traj.y.at(i + 1) - traj.y.at(i - 1);
  186. traj.yaw.at(i) = is_forward_shift ? std::atan2(dy, dx) : std::atan2(dy, dx) + M_PI;
  187. }
  188. if (traj.yaw.size() > 1) {
  189. traj.yaw.at(0) = traj.yaw.at(1);
  190. traj.yaw.back() = traj.yaw.at(traj.yaw.size() - 2);
  191. }
  192. }
  193. void calcTrajectoryCurvature(
  194. const int curvature_smoothing_num_traj, const int curvature_smoothing_num_ref_steer,
  195. MPCTrajectory & traj)
  196. {
  197. traj.k = calcTrajectoryCurvature(curvature_smoothing_num_traj, traj);
  198. traj.smooth_k = calcTrajectoryCurvature(curvature_smoothing_num_ref_steer, traj);
  199. }
  200. std::vector<double> calcTrajectoryCurvature(
  201. const int curvature_smoothing_num, const MPCTrajectory & traj)
  202. {
  203. std::vector<double> curvature_vec(traj.x.size());
  204. /* calculate curvature by circle fitting from three points */
  205. geometry_msgs::msg::Point p1, p2, p3;
  206. const int max_smoothing_num =
  207. static_cast<int>(std::floor(0.5 * (static_cast<double>(traj.x.size() - 1))));
  208. const size_t L = static_cast<size_t>(std::min(curvature_smoothing_num, max_smoothing_num));
  209. for (size_t i = L; i < traj.x.size() - L; ++i) {
  210. const size_t curr_idx = i;
  211. const size_t prev_idx = curr_idx - L;
  212. const size_t next_idx = curr_idx + L;
  213. p1.x = traj.x.at(prev_idx);
  214. p2.x = traj.x.at(curr_idx);
  215. p3.x = traj.x.at(next_idx);
  216. p1.y = traj.y.at(prev_idx);
  217. p2.y = traj.y.at(curr_idx);
  218. p3.y = traj.y.at(next_idx);
  219. try {
  220. curvature_vec.at(curr_idx) = tier4_autoware_utils::calcCurvature(p1, p2, p3);
  221. } catch (...) {
  222. std::cerr << "[MPC] 2 points are too close to calculate curvature." << std::endl;
  223. curvature_vec.at(curr_idx) = 0.0;
  224. }
  225. }
  226. /* first and last curvature is copied from next value */
  227. for (size_t i = 0; i < std::min(L, traj.x.size()); ++i) {
  228. curvature_vec.at(i) = curvature_vec.at(std::min(L, traj.x.size() - 1));
  229. curvature_vec.at(traj.x.size() - i - 1) =
  230. curvature_vec.at(std::max(traj.x.size() - L - 1, size_t(0)));
  231. }
  232. return curvature_vec;
  233. }
  234. MPCTrajectory convertToMPCTrajectory(const Trajectory & input)
  235. {
  236. MPCTrajectory output;
  237. for (const TrajectoryPoint & p : input.points) {
  238. const double x = p.pose.position.x;
  239. const double y = p.pose.position.y;
  240. const double z = p.pose.position.z;
  241. const double yaw = tf2::getYaw(p.pose.orientation);
  242. const double vx = p.longitudinal_velocity_mps;
  243. const double k = 0.0;
  244. const double t = 0.0;
  245. output.push_back(x, y, z, yaw, vx, k, k, t);
  246. }
  247. calcMPCTrajectoryTime(output);
  248. return output;
  249. }
  250. Trajectory convertToAutowareTrajectory(const MPCTrajectory & input)
  251. {
  252. Trajectory output;
  253. TrajectoryPoint p;
  254. for (size_t i = 0; i < input.size(); ++i) {
  255. p.pose.position.x = input.x.at(i);
  256. p.pose.position.y = input.y.at(i);
  257. p.pose.position.z = input.z.at(i);
  258. p.pose.orientation = tier4_autoware_utils::createQuaternionFromYaw(input.yaw.at(i));
  259. p.longitudinal_velocity_mps =
  260. static_cast<decltype(p.longitudinal_velocity_mps)>(input.vx.at(i));
  261. output.points.push_back(p);
  262. if (output.points.size() == output.points.max_size()) {
  263. break;
  264. }
  265. }
  266. return output;
  267. }
  268. bool calcMPCTrajectoryTime(MPCTrajectory & traj)
  269. {
  270. constexpr auto min_dt = 1.0e-4; // must be positive value to avoid duplication in time
  271. double t = 0.0;
  272. traj.relative_time.clear();
  273. traj.relative_time.push_back(t);
  274. for (size_t i = 0; i < traj.x.size() - 1; ++i) {
  275. const double dist = calcDistance3d(traj, i, i + 1);
  276. const double v = std::max(std::fabs(traj.vx.at(i)), 0.1);
  277. t += std::max(dist / v, min_dt);
  278. traj.relative_time.push_back(t);
  279. }
  280. return true;
  281. }
  282. void dynamicSmoothingVelocity(
  283. const size_t start_seg_idx, const double start_vel, const double acc_lim, const double tau,
  284. MPCTrajectory & traj)
  285. {
  286. double curr_v = start_vel;
  287. // set current velocity in both start and end point of the segment
  288. traj.vx.at(start_seg_idx) = start_vel;
  289. if (1 < traj.vx.size()) {
  290. traj.vx.at(start_seg_idx + 1) = start_vel;
  291. }
  292. for (size_t i = start_seg_idx + 2; i < traj.size(); ++i) {
  293. const double ds = calcDistance2d(traj, i, i - 1);
  294. const double dt = ds / std::max(std::fabs(curr_v), std::numeric_limits<double>::epsilon());
  295. const double a = tau / std::max(tau + dt, std::numeric_limits<double>::epsilon());
  296. const double updated_v = a * curr_v + (1.0 - a) * traj.vx.at(i);
  297. const double dv = std::max(-acc_lim * dt, std::min(acc_lim * dt, updated_v - curr_v));
  298. curr_v = curr_v + dv;
  299. traj.vx.at(i) = curr_v;
  300. }
  301. calcMPCTrajectoryTime(traj);
  302. }
  303. bool calcNearestPoseInterp(
  304. const MPCTrajectory & traj, const Pose & self_pose, Pose * nearest_pose, size_t * nearest_index,
  305. double * nearest_time, const double max_dist, const double max_yaw)
  306. {
  307. if (traj.empty() || !nearest_pose || !nearest_index || !nearest_time) {
  308. return false;
  309. }
  310. const auto autoware_traj = convertToAutowareTrajectory(traj);
  311. if (autoware_traj.points.empty()) {
  312. const auto logger = rclcpp::get_logger("mpc_util");
  313. auto clock = rclcpp::Clock(RCL_ROS_TIME);
  314. RCLCPP_WARN_THROTTLE(logger, clock, 5000, "[calcNearestPoseInterp] input trajectory is empty");
  315. return false;
  316. }
  317. *nearest_index = motion_utils::findFirstNearestIndexWithSoftConstraints(
  318. autoware_traj.points, self_pose, max_dist, max_yaw);
  319. const size_t traj_size = traj.size();
  320. if (traj.size() == 1) {
  321. nearest_pose->position.x = traj.x.at(*nearest_index);
  322. nearest_pose->position.y = traj.y.at(*nearest_index);
  323. nearest_pose->orientation = createQuaternionFromYaw(traj.yaw.at(*nearest_index));
  324. *nearest_time = traj.relative_time.at(*nearest_index);
  325. return true;
  326. }
  327. /* get second nearest index = next to nearest_index */
  328. const auto [prev, next] = [&]() -> std::pair<size_t, size_t> {
  329. if (*nearest_index == 0) {
  330. return std::make_pair(0, 1);
  331. }
  332. if (*nearest_index == traj_size - 1) {
  333. return std::make_pair(traj_size - 2, traj_size - 1);
  334. }
  335. geometry_msgs::msg::Point nearest_traj_point;
  336. nearest_traj_point.x = traj.x.at(*nearest_index);
  337. nearest_traj_point.y = traj.y.at(*nearest_index);
  338. geometry_msgs::msg::Point next_nearest_traj_point;
  339. next_nearest_traj_point.x = traj.x.at(*nearest_index + 1);
  340. next_nearest_traj_point.y = traj.y.at(*nearest_index + 1);
  341. const double signed_length =
  342. calcLongitudinalOffset(nearest_traj_point, next_nearest_traj_point, self_pose.position);
  343. if (signed_length <= 0) {
  344. return std::make_pair(*nearest_index - 1, *nearest_index);
  345. }
  346. return std::make_pair(*nearest_index, *nearest_index + 1);
  347. }();
  348. geometry_msgs::msg::Point next_traj_point;
  349. next_traj_point.x = traj.x.at(next);
  350. next_traj_point.y = traj.y.at(next);
  351. geometry_msgs::msg::Point prev_traj_point;
  352. prev_traj_point.x = traj.x.at(prev);
  353. prev_traj_point.y = traj.y.at(prev);
  354. const double traj_seg_length =
  355. tier4_autoware_utils::calcDistance2d(prev_traj_point, next_traj_point);
  356. /* if distance between two points are too close */
  357. if (traj_seg_length < 1.0E-5) {
  358. nearest_pose->position.x = traj.x.at(*nearest_index);
  359. nearest_pose->position.y = traj.y.at(*nearest_index);
  360. nearest_pose->orientation = createQuaternionFromYaw(traj.yaw.at(*nearest_index));
  361. *nearest_time = traj.relative_time.at(*nearest_index);
  362. return true;
  363. }
  364. /* linear interpolation */
  365. const double ratio = std::clamp(
  366. calcLongitudinalOffset(prev_traj_point, next_traj_point, self_pose.position) / traj_seg_length,
  367. 0.0, 1.0);
  368. nearest_pose->position.x = (1 - ratio) * traj.x.at(prev) + ratio * traj.x.at(next);
  369. nearest_pose->position.y = (1 - ratio) * traj.y.at(prev) + ratio * traj.y.at(next);
  370. const double tmp_yaw_err = normalizeRadian(traj.yaw.at(prev) - traj.yaw.at(next));
  371. const double nearest_yaw = normalizeRadian(traj.yaw.at(next) + (1 - ratio) * tmp_yaw_err);
  372. nearest_pose->orientation = createQuaternionFromYaw(nearest_yaw);
  373. *nearest_time = (1 - ratio) * traj.relative_time.at(prev) + ratio * traj.relative_time.at(next);
  374. return true;
  375. }
  376. double calcStopDistance(const Trajectory & current_trajectory, const int origin)
  377. {
  378. constexpr float zero_velocity = std::numeric_limits<float>::epsilon();
  379. const float origin_velocity =
  380. current_trajectory.points.at(static_cast<size_t>(origin)).longitudinal_velocity_mps;
  381. double stop_dist = 0.0;
  382. // search forward
  383. if (std::fabs(origin_velocity) > zero_velocity) {
  384. for (int i = origin + 1; i < static_cast<int>(current_trajectory.points.size()) - 1; ++i) {
  385. const auto & p0 = current_trajectory.points.at(i);
  386. const auto & p1 = current_trajectory.points.at(i - 1);
  387. stop_dist += calcDistance2d(p0, p1);
  388. if (std::fabs(p0.longitudinal_velocity_mps) < zero_velocity) {
  389. break;
  390. }
  391. }
  392. return stop_dist;
  393. }
  394. // search backward
  395. for (int i = origin - 1; 0 < i; --i) {
  396. const auto & p0 = current_trajectory.points.at(i);
  397. const auto & p1 = current_trajectory.points.at(i + 1);
  398. if (std::fabs(p0.longitudinal_velocity_mps) > zero_velocity) {
  399. break;
  400. }
  401. stop_dist -= calcDistance2d(p0, p1);
  402. }
  403. return stop_dist;
  404. }
  405. void extendTrajectoryInYawDirection(
  406. const double yaw, const double interval, const bool is_forward_shift, MPCTrajectory & traj)
  407. {
  408. // set terminal yaw
  409. traj.yaw.back() = yaw;
  410. // get terminal pose
  411. const auto autoware_traj = MPCUtils::convertToAutowareTrajectory(traj);
  412. auto extended_pose = autoware_traj.points.back().pose;
  413. constexpr double extend_dist = 10.0;
  414. constexpr double extend_vel = 10.0;
  415. const double x_offset = is_forward_shift ? interval : -interval;
  416. const double dt = interval / extend_vel;
  417. const size_t num_extended_point = static_cast<size_t>(extend_dist / interval);
  418. for (size_t i = 0; i < num_extended_point; ++i) {
  419. extended_pose = tier4_autoware_utils::calcOffsetPose(extended_pose, x_offset, 0.0, 0.0);
  420. traj.push_back(
  421. extended_pose.position.x, extended_pose.position.y, extended_pose.position.z, traj.yaw.back(),
  422. extend_vel, traj.k.back(), traj.smooth_k.back(), traj.relative_time.back() + dt);
  423. }
  424. }
  425. } // namespace MPCUtils
  426. } // namespace autoware::motion::control::mpc_lateral_controller