iosqp.hpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #pragma once
  2. #include <osqp/osqp.h>
  3. #include <Eigen/Sparse>
  4. #include <memory>
  5. /**
  6. * osqp interface:
  7. * minimize 0.5 x' P x + q' x
  8. * subject to l <= A x <= u
  9. **/
  10. namespace osqp {
  11. class IOSQP {
  12. public:
  13. IOSQP() : UNBOUNDED_VAL(OSQP_INFTY),
  14. pWork(nullptr),
  15. pSettings(nullptr),
  16. pData(nullptr) {
  17. pSettings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings));
  18. pData = (OSQPData *)c_malloc(sizeof(OSQPData));
  19. if (pSettings)
  20. osqp_set_default_settings(pSettings);
  21. }
  22. ~IOSQP() {
  23. if (pWork)
  24. osqp_cleanup(pWork);
  25. if (pSettings)
  26. c_free(pSettings);
  27. if (pData)
  28. c_free(pData);
  29. }
  30. const double UNBOUNDED_VAL;
  31. inline c_int setMats(Eigen::SparseMatrix<double> &P,
  32. Eigen::VectorXd &q,
  33. Eigen::SparseMatrix<double> &A,
  34. Eigen::VectorXd &l,
  35. Eigen::VectorXd &u,
  36. const double &eps_abs = 1e-3,
  37. const double &eps_rel = 1e-3) {
  38. if (pWork)
  39. osqp_cleanup(pWork);
  40. P = P.triangularView<Eigen::Upper>();
  41. P.makeCompressed();
  42. A.makeCompressed();
  43. pData->n = P.rows();
  44. pData->m = A.rows();
  45. Eigen::Map<const Eigen::VectorXi> iIdxP(P.innerIndexPtr(), P.nonZeros());
  46. Eigen::Map<const Eigen::VectorXi> oIdxP(P.outerIndexPtr(), P.cols() + 1);
  47. Eigen::Matrix<c_int, -1, 1> innerIdxP = iIdxP.cast<c_int>();
  48. Eigen::Matrix<c_int, -1, 1> outerIdxP = oIdxP.cast<c_int>();
  49. pData->P = csc_matrix(pData->n,
  50. pData->n,
  51. P.nonZeros(),
  52. P.valuePtr(),
  53. innerIdxP.data(),
  54. outerIdxP.data());
  55. Eigen::Map<const Eigen::VectorXi> iIdxA(A.innerIndexPtr(), A.nonZeros());
  56. Eigen::Map<const Eigen::VectorXi> oIdxA(A.outerIndexPtr(), A.cols() + 1);
  57. Eigen::Matrix<c_int, -1, 1> innerIdxA = iIdxA.cast<c_int>();
  58. Eigen::Matrix<c_int, -1, 1> outerIdxA = oIdxA.cast<c_int>();
  59. pData->A = csc_matrix(pData->m,
  60. pData->n,
  61. A.nonZeros(),
  62. A.valuePtr(),
  63. innerIdxA.data(),
  64. outerIdxA.data());
  65. Eigen::Matrix<c_float, -1, 1> pDqVec = q.cast<c_float>();
  66. pData->q = pDqVec.data();
  67. Eigen::Matrix<c_float, -1, 1> pDlVec = l.cast<c_float>();
  68. pData->l = pDlVec.data();
  69. Eigen::Matrix<c_float, -1, 1> pDuVec = u.cast<c_float>();
  70. pData->u = pDuVec.data();
  71. pSettings->eps_abs = eps_abs;
  72. pSettings->eps_rel = eps_rel;
  73. c_int exitflag = osqp_setup(&pWork, pData, pSettings);
  74. if (pData->A)
  75. c_free(pData->A);
  76. if (pData->P)
  77. c_free(pData->P);
  78. return exitflag;
  79. }
  80. inline c_int solve() const {
  81. return osqp_solve(pWork);
  82. }
  83. inline c_int getStatus() const {
  84. return pWork->info->status_val;
  85. }
  86. inline Eigen::VectorXd getPrimalSol() const {
  87. return Eigen::Map<const Eigen::VectorXd>(pWork->solution->x,
  88. pWork->data->n);
  89. }
  90. private:
  91. OSQPWorkspace *pWork;
  92. OSQPSettings *pSettings;
  93. OSQPData *pData;
  94. };
  95. } // namespace osqp