• qpoases解MPC控制


     障碍物表示形式

    凸多面体

    凸多面体可以根据问题形式的不同采用不同的定义形式,可以定义为空间中的一个凸集,半空间的交集(H-representation)和一系列点构成的凸包(V-representation)。

    具体MPC控制算法推导建下面链接:

    LQR、MPC以及osqp库_osqp mpc-CSDN博客

    MPC控制算法推导 - 知乎

    一个模型预测控制(MPC)的简单实现 - 知乎

    1. #include <webots/Robot.hpp>
    2. #include <webots/Motor.hpp>
    3. #include <webots/Supervisor.hpp>
    4. #include <iostream>
    5. #include <Eigen/Dense>
    6. // #include "Array.hh" //使用了MIT中的文件 其修改了向量与矩阵的名字 不然会与Eigen冲突
    7. // #include "QuadProg++.hh"
    8. #include <qpOASES.hpp>
    9. #include <fstream>
    10. // All the webots classes are defined in the "webots" namespace
    11. using namespace webots;
    12. using namespace std;
    13. using namespace Eigen;
    14. using namespace qpOASES;
    15. Motor *motor_FR,*motor_FL,*motor_BR,*motor_BL;
    16. Supervisor* robot;
    17. int testQP();
    18. void setV(double _v,float _time_step);
    19. int main(int argc, char **argv) {
    20. //testQP();
    21. //Robot *robot = new Robot();
    22. robot = new Supervisor();
    23. motor_FR = robot->getMotor("motor_FR");
    24. motor_FL = robot->getMotor("motor_FL");
    25. motor_BR = robot->getMotor("motor_BR");
    26. motor_BL = robot->getMotor("motor_BL");
    27. // get the time step of the current world.
    28. int timeStep = (int)robot->getBasicTimeStep();
    29. // double T = timeStep/1000;
    30. double T = 0.05;
    31. int P = 5;//预测长度
    32. MatrixXd Q(P,P); //状态误差权重
    33. for(int i=0;i<P;i++){
    34. Q(i,i) = 5*1;
    35. }
    36. //std::cout << "Q =\n" << Q << std::endl;
    37. MatrixXd W(P,P); //控制输出权重
    38. for(int i=0;i<P;i++){
    39. W(i,i) = 1;
    40. }
    41. MatrixXd Rk(P,1); //参考值序列
    42. for(int i=0;i<P;i++){
    43. Rk(i,0) = 2;
    44. }
    45. double A_ = 1;
    46. double B_ = T;
    47. MatrixXd fei(P,1); //AK
    48. MatrixXd theta(P,P); //BK
    49. MatrixXd E(P,1); //E
    50. MatrixXd H(P,P); //H
    51. MatrixXd f(P,1); //f
    52. MatrixXd g(1,P);
    53. MatrixXd xk(1,1);
    54. MatrixXd lb(P,1);
    55. MatrixXd ub(P,1);
    56. float pos = 0;
    57. float vmax = 1,vmin = -1;
    58. const int num_of_elements = H.rows() * H.cols(); //元素数
    59. double H_matrix[num_of_elements];
    60. const auto k_num_of_rows = f.rows();
    61. double g_matrix[k_num_of_rows]; // NOLINT , 与offset一般大
    62. const int num_of_lb = lb.rows();
    63. double lb_matrix[num_of_lb];
    64. double ub_matrix[num_of_lb];
    65. for(int i=0;i<num_of_lb;i++)
    66. {
    67. lb_matrix[i] = vmin;
    68. ub_matrix[i] = vmax;
    69. }
    70. QProblemB v_pro(P);
    71. Options options;
    72. //options.enableFlippingBounds = BT_FALSE;
    73. options.initialStatusBounds = ST_INACTIVE;
    74. options.numRefinementSteps = 1;
    75. options.enableCholeskyRefactorisation = 1;
    76. v_pro.setOptions( options );
    77. while (robot->step(timeStep) != -1) {
    78. // pos+=0.1;
    79. xk(0,0) = pos;
    80. for(int i=0 ; i<P;i++){
    81. fei(i,0) = pow(A_,i+1);
    82. }
    83. // cout <<"fei "<<fei <<"\n";
    84. for(int i=0; i <P;++i){
    85. for(int j=0; j <=i;++j){
    86. theta(i,j)= pow(A_,i-j)*B_;
    87. }
    88. }
    89. //cout <<"theta"<<theta <<"\n";
    90. E = fei*xk-Rk;
    91. H = 2.0*(theta.transpose()*Q*theta+W); //求矩阵的转置
    92. f = (2.0*E.transpose()*Q*theta).transpose();
    93. g = f.transpose(); //g为f的转置
    94. // cout <<E <<"\n" << H <<"\n" <<f <<"\n";
    95. //转为qpOASES格式
    96. for(int i =0;i<H.rows();i++)
    97. {
    98. for(int j=0;j<H.cols();j++)
    99. {
    100. H_matrix[(i)*H.cols()+j] = H(i,j);
    101. }
    102. g_matrix[i] = g(0,i);
    103. }
    104. int_t nWSR = 10;
    105. v_pro.init(H_matrix, g_matrix, lb_matrix, ub_matrix, nWSR);
    106. real_t xOpt[2];
    107. v_pro.getPrimalSolution( xOpt );
    108. printf( "\nxOpt = [ %e, %e ]; objVal = %e\n\n", xOpt[0],xOpt[1],v_pro.getObjVal() );
    109. setV(xOpt[0],timeStep);
    110. // setV(0.5,timeStep);
    111. //pos = pos + xOpt[0]*T ;
    112. pos = robot->getSelf()->getPosition()[0];
    113. printf("pos:%f\n",pos);
    114. };
    115. // Enter here exit cleanup code.
    116. delete robot;
    117. return 0;
    118. }
    119. int testQP()
    120. {
    121. /* Setup data of first QP. */
    122. real_t H[2 * 2] = { 1.0, 0.0, 0.0, 0.5 };
    123. real_t A[1 * 2] = { 1.0, 1.0 };
    124. real_t g[2] = { 1.5, 1.0 };
    125. real_t lb[2] = { 0.5, -2.0 };
    126. real_t ub[2] = { 5.0, 2.0 };
    127. real_t lbA[1] = { -1.0 };
    128. real_t ubA[1] = { 2.0 };
    129. /* Setup data of second QP. */
    130. real_t g_new[2] = { 1.0, 1.5 };
    131. real_t lb_new[2] = { 0.0, -1.0 };
    132. real_t ub_new[2] = { 5.0, -0.5 };
    133. real_t lbA_new[1] = { -2.0 };
    134. real_t ubA_new[1] = { 1.0 };
    135. /* Setting up QProblem object. */
    136. QProblem example(2, 1);
    137. /* Solve first QP. */
    138. int_t nWSR = 10;
    139. example.init(H, g, A, lb, ub, lbA, ubA, nWSR);
    140. real_t xOpt[2];
    141. real_t yOpt[2+1];
    142. example.getPrimalSolution( xOpt );
    143. example.getDualSolution( yOpt );
    144. printf( "\nxOpt = [ %e, %e ]; yOpt = [ %e, %e, %e ]; objVal = %e\n\n",
    145. xOpt[0],xOpt[1],yOpt[0],yOpt[1],yOpt[2],example.getObjVal() );
    146. /* Solve second QP. */
    147. nWSR = 10;
    148. example.hotstart(g_new, lb_new, ub_new, lbA_new, ubA_new, nWSR);
    149. /* Get and print solution of second QP. */
    150. // real_t xOpt[2];
    151. example.getPrimalSolution(xOpt);
    152. printf("\n xOpt = [ %e, %e ]; objVal = %e\n\n",
    153. xOpt[0], xOpt[1], example.getObjVal());
    154. return 0;
    155. }
    156. float wheel_p=0;
    157. void setV(double _v,float _time_step)
    158. {
    159. double r = 0.05;
    160. _v = -_v;
    161. wheel_p += _time_step/1000*_v/r;
    162. motor_FR->setPosition(wheel_p);
    163. motor_FL->setPosition(wheel_p);
    164. motor_BR->setPosition(wheel_p);
    165. motor_BL->setPosition(wheel_p);
    166. }

    1. #include "MPC.hpp"
    2. #include "math.h"
    3. #include "iostream"
    4. #define PI 3.1415926
    5. #define T 0.03
    6. #define w0 0.5
    7. #define w1 5.0
    8. #define Ku 1
    9. #define Kl 1
    10. using namespace Eigen;
    11. using namespace std;
    12. USING_NAMESPACE_QPOASES
    13. MatrixXd MPC_controller::MPC_Solve_qp(Eigen::Vector3d X_k,std::vector<Eigen::Vector3d >X_r,std::vector<Eigen::Vector2d >U_r,const int N)
    14. {
    15. //cout<<"current w : "<<w_max<<endl;
    16. 根据参考输入计算出的系数矩阵
    17. vector<MatrixXd> A_r(N),B_r(N),A_multiply1(N);
    18. MatrixXd O_r(3*N,1);
    19. MatrixXd A_bar(3*N,3);
    20. MatrixXd X_ref(3*N,1);
    21. MatrixXd A_multiply2;
    22. MatrixXd B_bar = MatrixXd::Zero(3*N,2*N);
    23. MatrixXd C_bar = MatrixXd::Identity(3*N,3*N);
    24. MatrixXd A_r_init = MatrixXd::Zero(3,3);
    25. MatrixXd B_r_init = MatrixXd::Zero(3,2);
    26. MatrixXd eye_3 = MatrixXd::Identity(3,3);
    27. MatrixXd Q = MatrixXd::Identity(3*N,3*N)*w0;
    28. MatrixXd R = MatrixXd::Identity(3*N,3*N)*w1;
    29. // cout<<"Ur 1 : "<<endl<<U_r[0]<<endl;
    30. // cout<<"Xr 1 : "<<endl<<X_r[0]<<endl;
    31. // cout<<"Xk : "<<endl<<X_k<<endl;
    32. for(int k=0;k<N;k++)
    33. {
    34. A_r[k] = A_r_init;
    35. B_r[k] = B_r_init;
    36. A_r[k](0,2) = -U_r[k](0)*sin(X_r[k](2));
    37. A_r[k](1,2) = U_r[k](0)*cos(X_r[k](2));
    38. Vector3d temp_vec = -T*A_r[k]*X_r[k];
    39. O_r.block<3,1>(k*3,0) = temp_vec;
    40. A_r[k] = eye_3+T*A_r[k];
    41. B_r[k](0,0) = cos(X_r[k](2))*T;
    42. B_r[k](1,0) = sin(X_r[k](2))*T;
    43. B_r[k](2,1) = T;
    44. X_ref.block<3,1>(k*3,0) = X_r[k];
    45. // cout<<"B_r "<<k+1<<" : "<<endl<<B_r[k]<<endl;
    46. if(k==0) A_multiply1[k] = A_r[k];
    47. else A_multiply1[k] = A_multiply1[k-1]*A_r[k];
    48. A_bar.block<3,3>(3*k,0) = A_multiply1[k];
    49. }
    50. // cout<<"Ar 1 : "<<endl<<A_r[0]<<endl;
    51. // cout<<"Br 1 : "<<endl<<B_r[0]<<endl;
    52. // cout<<"Or 1 : "<<endl<<O_r.block<3,1>(0,0)<<endl;
    53. // cout<<"O_r : "<<endl<<O_r<<endl;
    54. for(int k=0;k<N;k++)
    55. {
    56. B_bar.block<3,2>(3*k,2*k) = B_r[k];
    57. A_multiply2 = eye_3;
    58. for(int i=0;i<k;i++)
    59. {
    60. A_multiply2 = A_multiply2*A_r[k-i];
    61. C_bar.block<3,3>(3*k,3*(k-1-i)) = A_multiply2;
    62. B_bar.block<3,2>(3*k,2*(k-1-i)) = A_multiply2*B_r[k-1-i];
    63. }
    64. }
    65. //cout<<"C bar : "<<endl<<C_bar<<endl;
    66. MatrixXd E =A_bar*X_k+C_bar*O_r-X_ref;
    67. MatrixXd Hesse = 2*B_bar.transpose()*(Q+R)*B_bar; Hesse矩阵
    68. VectorXd gradient = 2*B_bar.transpose()*Q*E; 一次项系数
    69. real_t H[2*N*2*N],g[2*N],A[2*N],lb[2*N],ub[2*N],lbA[1],ubA[1];
    70. lbA[0] = N*(v_min+w_min)/Ku;
    71. ubA[0] = N*(v_max+w_max)/Kl;
    72. for(int i=0;i<2*N;i++)
    73. {
    74. g[i] = gradient(i);
    75. A[i] = 1;
    76. if(i%2==0)
    77. {
    78. lb[i] = v_min;
    79. ub[i] = v_max;
    80. }
    81. else
    82. {
    83. lb[i] = w_min;
    84. ub[i] = w_max;
    85. }
    86. for(int j=0;j<2*N;j++)
    87. {
    88. H[i*2*N+j] = Hesse(i,j);
    89. }
    90. }
    91. int_t nWSR = 800;
    92. QProblem mpc_qp_solver(2*N,1);
    93. mpc_qp_solver.init(H,g,A,lb,ub,lbA,ubA,nWSR);
    94. real_t x_solution[2*N];
    95. mpc_qp_solver.getPrimalSolution(x_solution);
    96. Vector2d u_k;
    97. MatrixXd U_result = MatrixXd::Zero(2,N);
    98. for(int i=0;i<N;i++)
    99. {
    100. u_k(0) = x_solution[2*i];
    101. u_k(1) = x_solution[2*i+1];
    102. U_result.col(i) = u_k;
    103. // std::cout<<"U "<<i+1<<" : "<<endl<<u_k<<endl;
    104. }
    105. //cout<<"N : "<<N<<endl;
    106. return U_result;
    107. }
    108. void MPC_controller::MPC_init(ros::NodeHandle &nh)
    109. {
    110. nh.getParam("/ego_planner_node/MPC/v_max", v_max);
    111. nh.getParam("/ego_planner_node/MPC/w_max", w_max);
    112. // nh.param("/ego_planner_node/MPC/v_max",v_max,0.7);
    113. // nh.param("/ego_planner_node/MPC/w_max",w_max,0.3);
    114. ROS_INFO("v_max : %f , w_max : %f",v_max,w_max);
    115. w_min = -w_max;
    116. v_min=0;
    117. }

    其中使用osqp与eigen联合求解为(Non-Condensed Format),它不仅仅与输出控制量有关,与状态量也有关系。

  • 相关阅读:
    Windows上安装 RabbitMQ 教程
    Windows 下 Qt 可执行程序添加默认管理员权限启动(QMAKE、MinGW & MSVC)
    使用机器人操作系统 (ROS) 探索 Python 在机器人开发和控制中的功能
    Nginx 模块开发
    zabbix-agent主动模式下自定义监控项和监控指标
    Flutter实践一:package组织
    第四十基础:强制等待&隐士等待&显示等待&元素定位方法
    【数据库】mysql索引
    [思维]Longest Common Subsequence 2022牛客多校第8场 F
    2D割草/吸血鬼游戏 性能优化——GPU Spine动画
  • 原文地址:https://blog.csdn.net/caokaifa/article/details/132747585