rotate_mpc.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. //
  2. // Created by gf on 23-7-21.
  3. //
  4. #include "rotate_mpc.h"
  5. #include <chrono>
  6. #include <cppad/cppad.hpp>
  7. #include <cppad/ipopt/solve.hpp>
  8. size_t mpc_rotate_steps = 20; //优化考虑后面多少步
  9. size_t delay = 3; // 发送到执行的延迟,即几个周期的时间
  10. #define N mpc_rotate_steps
  11. class FG_eval_rotate {
  12. public:
  13. Eigen::VectorXd m_statu; //当前状态
  14. Eigen::VectorXd m_condition; //搜索条件参数
  15. FG_eval_rotate(Eigen::VectorXd status, Eigen::VectorXd condition) {
  16. m_statu = status;
  17. m_condition = condition;
  18. }
  19. typedef CPPAD_TESTVECTOR(CppAD::AD<double>) ADvector;
  20. void operator()(ADvector &fg, const ADvector &vars) {
  21. fg[0] = 0;
  22. double dt = m_condition[0];
  23. double target_theta = m_condition[1];
  24. double obs_w = m_condition[2];
  25. double obs_h = m_condition[3];
  26. double angular_velocity = m_statu[0];
  27. // Weights for how "important" each cost is - can be tuned
  28. const double y_cost_weight = 1000;
  29. const double angular_cost_weight = 4000;
  30. const double v_cost_weight = 5000;
  31. const double angular_velocity_cost_weight = 1000;
  32. const double acceleration_cost_weight = 1;
  33. const double angular_acceleration_cost_weight = 10;
  34. const double obs_distance_weight = 5000.0;
  35. // 代价函数计算
  36. for (int t = 0; t < N - 1; ++t) {
  37. /// 角速度,角加速度weight loss
  38. fg[0] += angular_velocity_cost_weight * CppAD::pow(vars[N + t], 2);
  39. fg[0] += angular_acceleration_cost_weight * CppAD::pow(vars[N + t + 1] - vars[N + t], 2);
  40. /// 目标角度 loss
  41. fg[0] += angular_cost_weight * CppAD::pow(target_theta - vars[t], 2);
  42. }
  43. // 约束条件
  44. int n_angular = 1;
  45. int n_angular_acceleration = n_angular + N;
  46. int n_obs = n_angular_acceleration + N;
  47. /// 角度等式约束 1~N
  48. fg[n_angular] = vars[0] - angular_velocity * dt;
  49. for (int t = 1; t < N; ++t) {
  50. // State at time t + 1
  51. CppAD::AD<double> theta1 = vars[t];
  52. // State at time t
  53. CppAD::AD<double> theta0 = vars[t - 1];
  54. CppAD::AD<double> angular_velocity0 = vars[N + t - 1];
  55. // Setting up the rest of the model constraints
  56. fg[n_angular + t] = theta1 - (theta0 + angular_velocity0 * dt);
  57. }
  58. /// 角加速度等式约束 N+1~2N
  59. fg[n_angular_acceleration] = (vars[0 + N] - angular_velocity) / dt;
  60. for (int t = 1; t < N; ++t) {
  61. fg[n_angular_acceleration + t] = (vars[t + N] - vars[t + N - 1]) / dt;
  62. }
  63. /// 障碍物距离等式约束 2N+1~3N
  64. if (m_statu.size() == 1 + 3) {
  65. float obs_x = m_statu[1];
  66. float obs_y = m_statu[2];
  67. float obs_theta = m_statu[3];
  68. Pose2d obs_relative_pose(obs_x, obs_y, obs_theta);
  69. std::vector<Pose2d> obs_vertexes = Pose2d::generate_rectangle_vertexs(obs_relative_pose, obs_w * 2,
  70. obs_h * 2);
  71. for (auto t = 0; t < N; ++t) {
  72. CppAD::AD<double> min_distance = 1e19;
  73. for (auto i = 0; i < 8; ++i) {
  74. CppAD::AD<double> ra = obs_vertexes[i].x() * CppAD::cos(vars[t]) -
  75. obs_vertexes[i].y() * CppAD::sin(vars[t]);
  76. CppAD::AD<double> rb = obs_vertexes[i].x() * CppAD::sin(vars[t]) +
  77. obs_vertexes[i].y() * CppAD::cos(vars[t]);
  78. CppAD::AD<double> distance = CppAD::pow(ra / obs_w, 8) + CppAD::pow(rb / obs_h, 8);
  79. if (distance < min_distance) min_distance = distance;
  80. }
  81. fg[n_obs + t] = min_distance;
  82. }
  83. // std::cout << " fg[n_obs]: " << fg[n_obs] << " | __LINE__:" << __LINE__ << std::endl;
  84. }
  85. }
  86. };
  87. RotateMPC::RotateMPC(const Pose2d &obs, double obs_w, double obs_h, double min_velocity, double max_velocity) {
  88. min_velocity_ = min_velocity;
  89. max_velocity_ = max_velocity;
  90. obs_relative_pose_ = obs;
  91. obs_w_ = obs_w;
  92. obs_h_ = obs_h;
  93. }
  94. RotateMPC::~RotateMPC() {}
  95. MpcError
  96. RotateMPC::solve(Pose2d current_to_target, Eigen::VectorXd statu, MPC_parameter mpc_param, std::vector<double> &out) {
  97. auto start = std::chrono::steady_clock::now();
  98. // State vector holds all current values needed for vars below
  99. Pose2d pose_agv = Pose2d(statu[0], statu[1], statu[2]);
  100. double line_velocity = statu[3];
  101. double angular_velocity = statu[4];
  102. /// 定义最大最小角度,角速度,角加速度(不区分方向)
  103. double max_angular = M_PI;
  104. double max_angular_velocity = 15.0 / 180 * M_PI;
  105. double min_angular_velocity = 0.01 / 180 * M_PI;
  106. double max_angular_acceleration_velocity = 30.0 / 180 * M_PI;//mpc_param.acc_angular; //
  107. /// 调整输入
  108. if (angular_velocity > max_angular_velocity) angular_velocity = max_angular_velocity;
  109. if (angular_velocity < -max_angular_velocity) angular_velocity = -max_angular_velocity;
  110. // 优化
  111. typedef CPPAD_TESTVECTOR(double) Dvector;
  112. /// 步长
  113. double dt = mpc_param.dt;
  114. /// 初始化参数
  115. size_t n_vars = N * 2; // 0-N为角度,N-2N为角速度
  116. Dvector vars(n_vars); // 0-N为角度,N-2N为角速度
  117. for (int i = 0; i < n_vars; i++) vars[i] = 0.0;
  118. // 参数上下限
  119. Dvector vars_lowerbound(n_vars);
  120. Dvector vars_upperbound(n_vars);
  121. for (int i = 0; i < n_vars; ++i) {
  122. vars_lowerbound[i] = -1.0e19;
  123. vars_upperbound[i] = 1.0e19;
  124. }
  125. /// limit of angular velocity
  126. for (auto i = N; i < 2 * N; ++i) {
  127. vars_lowerbound[i] = -max_angular_velocity;
  128. vars_upperbound[i] = max_angular_velocity;
  129. }
  130. // Lower and upper limits for the constraints
  131. /// 障碍物是否进入 碰撞检测范围内
  132. // float distance = Pose2d::distance(obs_relative_pose_, Pose2d(0, 0, 0));
  133. float distance = 1000;//屏蔽障碍物
  134. bool find_obs = distance < 5;
  135. if (find_obs) printf(" find obs ..............................\n");
  136. size_t n_constraints = 2 * N + find_obs * N;// 0~N角度约束,N~2N角加速度约束, 2N~3N障碍物约束
  137. Dvector constraints_lowerbound(n_constraints);
  138. Dvector constraints_upperbound(n_constraints);
  139. for (auto i = 0; i < n_constraints; ++i) {
  140. constraints_lowerbound[i] = 0;
  141. constraints_upperbound[i] = 0;
  142. }
  143. /// limit of angular acceleration
  144. for (auto i = N; i < 2 * N; ++i) {
  145. constraints_lowerbound[i] = -max_angular_acceleration_velocity;
  146. constraints_upperbound[i] = max_angular_acceleration_velocity;
  147. }
  148. /// limit of obs distance
  149. if (find_obs)
  150. for (auto i = 2 * N; i < 3 * N; ++i) {
  151. constraints_lowerbound[i] = 1.0;
  152. constraints_upperbound[i] = 1e19;
  153. }
  154. // fg_eval for IPOPT solver
  155. size_t n_fg_status = 1 + 3 * find_obs;
  156. Eigen::VectorXd fg_status(n_fg_status);
  157. fg_status[0] = angular_velocity;
  158. if (find_obs) {
  159. fg_status[1] = obs_relative_pose_.x();
  160. fg_status[2] = obs_relative_pose_.y();
  161. fg_status[3] = obs_relative_pose_.theta();
  162. }
  163. // std::cout << " size of fg_status: " << fg_status.size() << " | __LINE__: " << __LINE__ << std::endl;
  164. Pose2d targetAngularInAGV = current_to_target;
  165. /// 调整到适合的目标角度
  166. // if (targetAngularInAGV.theta() > 0) {
  167. //// double acc_time = (max_angular_velocity - angular_velocity) / max_angular_acceleration_velocity;
  168. //// double max_angular_once = max_angular_velocity * N * dt - acc_time * (max_angular_velocity - angular_velocity);
  169. // double max_angular_once = 9.0 / 180 * M_PI;
  170. // if (targetAngularInAGV.theta() > max_angular_once ) {
  171. // targetAngularInAGV.set_theta(max_angular_once);
  172. // }
  173. // }
  174. // else if (targetAngularInAGV.theta() < 0) {
  175. //// double acc_time = fabs((-max_angular_velocity - angular_velocity) / -max_angular_acceleration_velocity);
  176. //// double max_angular_once = -max_angular_velocity * N * dt + acc_time * (-max_angular_velocity - angular_velocity);
  177. // double max_angular_once = -9.0 / 180 * M_PI;
  178. // if (targetAngularInAGV.theta() < max_angular_once ) {
  179. // targetAngularInAGV.set_theta(max_angular_once);
  180. // }
  181. // } else{
  182. //
  183. // }
  184. // printf("target: %f\n",targetAngularInAGV.theta()/M_PI*180);
  185. Eigen::VectorXd condition(4);
  186. condition << dt, targetAngularInAGV.theta(), obs_w_, obs_h_;
  187. FG_eval_rotate fg_eval(fg_status, condition);
  188. // options for IPOPT solver
  189. std::string options;
  190. /// Uncomment this if you'd like more print information
  191. options += "Integer print_level 0\n";
  192. options += "Sparse true forward\n";
  193. options += "Sparse true reverse\n";
  194. options += "Numeric max_cpu_time 0.5\n";
  195. // place to return solution
  196. CppAD::ipopt::solve_result<Dvector> solution;
  197. // solve the problem
  198. CppAD::ipopt::solve<Dvector, FG_eval_rotate>(
  199. options, vars, vars_lowerbound, vars_upperbound, constraints_lowerbound,
  200. constraints_upperbound, fg_eval, solution);
  201. auto now = std::chrono::steady_clock::now();
  202. auto duration = std::chrono::duration_cast<std::chrono::microseconds>(now - start);
  203. double time =
  204. double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den;
  205. // invalid_number_detected
  206. if (solution.status != CppAD::ipopt::solve_result<Dvector>::success) {
  207. printf(" mpc failed status : %d input: %.5f max_wmg:%.5f\n", solution.status,
  208. angular_velocity, max_angular_velocity);
  209. if (solution.status == CppAD::ipopt::solve_result<Dvector>::local_infeasibility)
  210. return no_solution;
  211. return failed;
  212. }
  213. // Cost
  214. auto cost = solution.obj_value;
  215. // 输出第一步的角速度
  216. out.clear();
  217. double solve_angular_velocity = solution.x[N];
  218. out.push_back(solve_angular_velocity);
  219. return success;
  220. }