- 3.0.2 optimal control module.
HPIPMInterface-impl.hpp
Go to the documentation of this file.
1 /**********************************************************************************************************************
2 This file is part of the Control Toolbox (https://github.com/ethz-adrl/control-toolbox), copyright by ETH Zurich.
3 Licensed under the BSD-2 license (see LICENSE file in main directory)
4 **********************************************************************************************************************/
5 
6 #pragma once
7 
8 #ifdef HPIPM
9 
10 namespace ct {
11 namespace optcon {
12 
13 template <int STATE_DIM, int CONTROL_DIM>
14 HPIPMInterface<STATE_DIM, CONTROL_DIM>::HPIPMInterface() : N_(-1), settings_(NLOptConSettings())
15 {
16  hb0_.setZero();
17  hr0_.setZero();
18 
20 }
21 
22 template <int STATE_DIM, int CONTROL_DIM>
23 HPIPMInterface<STATE_DIM, CONTROL_DIM>::~HPIPMInterface()
24 {
25  // todo is there memory that needs to be freed?
26 }
27 
28 template <int STATE_DIM, int CONTROL_DIM>
29 void HPIPMInterface<STATE_DIM, CONTROL_DIM>::initializeAndAllocate()
30 {
32  {
33  std::cout << "HPIPM allocating memory for QP with time horizon: " << N_ << std::endl;
34  for (int i = 0; i < N_ + 1; i++)
35  {
36  std::cout << "HPIPM stage " << i << ": (nx, nu, nbu, nbx, ng) : (" << nx_[i] << ", " << nu_[i] << ", "
37  << nbu_[i] << ", " << nbx_[i] << ", " << ng_[i] << ")" << std::endl;
38  }
39  }
40 
41  // allocate ocp dimensions
42  dim_size_ = d_ocp_qp_dim_memsize(N_);
43  dim_mem_ = malloc(dim_size_);
44  d_ocp_qp_dim_create(N_, &dim_, dim_mem_);
45  d_ocp_qp_dim_set_all(
46  nx_.data(), nu_.data(), nbx_.data(), nbu_.data(), ng_.data(), nsbx_.data(), nsbu_.data(), nsg_.data(), &dim_);
47 
48  // allocate ocp qp
49  int qp_size = ::d_ocp_qp_memsize(&dim_);
50  qp_mem_ = malloc(qp_size);
51  ::d_ocp_qp_create(&dim_, &qp_, qp_mem_);
52  ::d_ocp_qp_set_all(hA_.data(), hB_.data(), hb_.data(), hQ_.data(), hS_.data(), hR_.data(), hq_.data(), hr_.data(),
53  hidxbx_.data(), hlbx_.data(), hubx_.data(), hidxbu_.data(), hlbu_.data(), hubu_.data(), // box constraints
54  hC_.data(), hD_.data(), hlg_.data(), hug_.data(), // gen constraints
55  hZl_.data(), hZu_.data(), hzl_.data(), hzu_.data(), hidxs_.data(), hlls_.data(), hlus_.data(), &qp_);
56 
57  // allocation for solution
58  int qp_sol_size = ::d_ocp_qp_sol_memsize(&dim_);
59  qp_sol_mem_ = malloc(qp_sol_size);
60  ::d_ocp_qp_sol_create(&dim_, &qp_sol_, qp_sol_mem_);
61 
62  // ipm arg
63  int ipm_arg_size = ::d_ocp_qp_ipm_arg_memsize(&dim_);
64  ipm_arg_mem_ = malloc(ipm_arg_size);
65  ::d_ocp_qp_ipm_arg_create(&dim_, &arg_, ipm_arg_mem_);
66 
67  ::d_ocp_qp_ipm_arg_set_default(mode_, &arg_);
68  ::d_ocp_qp_ipm_arg_set_iter_max(&settings_.lqoc_solver_settings.num_lqoc_iterations, &arg_);
69 
70  // create workspace
71  int ipm_size = ::d_ocp_qp_ipm_ws_memsize(&dim_, &arg_);
72  ipm_mem_ = malloc(ipm_size);
73  ::d_ocp_qp_ipm_ws_create(&dim_, &arg_, &workspace_, ipm_mem_);
74 
75 
77  {
78  std::cout << "HPIPM qp_size: " << qp_size << std::endl;
79  std::cout << "HPIPM qp_sol_size: " << qp_sol_size << std::endl;
80  std::cout << "HPIPM ipm_arg_size: " << ipm_arg_size << std::endl;
81  std::cout << "HPIPM ipm_size: " << ipm_size << std::endl;
82  }
83 }
84 
85 
86 template <int STATE_DIM, int CONTROL_DIM>
87 void HPIPMInterface<STATE_DIM, CONTROL_DIM>::configure(const NLOptConSettings& settings)
88 {
89  settings_ = settings;
90  ::d_ocp_qp_ipm_arg_set_iter_max(&settings_.lqoc_solver_settings.num_lqoc_iterations, &arg_);
91 }
92 
93 
94 template <int STATE_DIM, int CONTROL_DIM>
95 void HPIPMInterface<STATE_DIM, CONTROL_DIM>::solve()
96 {
97 // optional printout
98 #ifdef HPIPM_PRINT_MATRICES
99  for (int i = 0; i < N_ + 1; i++)
100  {
101  std::cout << "HPIPM matrix printout for stage " << i << std::endl;
102  if (i < N_)
103  {
104  printf("\nA\n");
105  d_print_mat(STATE_DIM, STATE_DIM, hA_[i], STATE_DIM);
106  printf("\nB\n");
107  d_print_mat(STATE_DIM, CONTROL_DIM, hB_[i], STATE_DIM);
108  printf("\nb\n");
109  d_print_mat(1, STATE_DIM, hb_[i], 1);
110  }
111 
112  printf("\nQ\n");
113  d_print_mat(STATE_DIM, STATE_DIM, hQ_[i], STATE_DIM);
114  printf("\nq\n");
115  d_print_mat(1, STATE_DIM, hq_[i], 1);
116 
117 
118  if (i < N_)
119  {
120  printf("\nR\n");
121  d_print_mat(CONTROL_DIM, CONTROL_DIM, hR_[i], CONTROL_DIM);
122  printf("\nS\n");
123  d_print_mat(CONTROL_DIM, STATE_DIM, hS_[i], CONTROL_DIM);
124  printf("\nr\n");
125  d_print_mat(1, CONTROL_DIM, hr_[i], 1);
126  }
127 
128  printf("\nnbu\n");
129  std::cout << nbu_[i] << std::endl;
130  printf("\nhlbu_\n");
131  d_print_mat(1, nbu_[i], hlbu_[i], 1);
132  printf("\nhubu_\n");
133  d_print_mat(1, nbu_[i], hubu_[i], 1);
134 
135  printf("\nnbx\n");
136  std::cout << nbx_[i] << std::endl;
137  printf("\nhlbx_\n");
138  d_print_mat(1, nbx_[i], hlbx_[i], 1);
139  printf("\nhubx_\n");
140  d_print_mat(1, nbx_[i], hubx_[i], 1);
141 
142  printf("\nng\n");
143  std::cout << ng_[i] << std::endl;
144  printf("\nC\n");
145  d_print_mat(ng_[i], STATE_DIM, hC_[i], ng_[i]);
146  printf("\nD\n");
147  d_print_mat(ng_[i], CONTROL_DIM, hD_[i], ng_[i]);
148  printf("\nhlg_\n");
149  d_print_mat(1, ng_[i], hlg_[i], 1);
150  printf("\nhug_\n");
151  d_print_mat(1, ng_[i], hug_[i], 1);
152 
153  } // end optional printout
154 #endif // HPIPM_PRINT_MATRICES
155 
156 
157  // solve optimal control problem
158  ::d_ocp_qp_ipm_solve(&qp_, &qp_sol_, &arg_, &workspace_);
159  ::d_ocp_qp_ipm_get_status(&workspace_, &hpipm_status_);
160 
161  isLrInvComputed_ = false;
162 
163  // display iteration summary
165  {
166  printf("\nHPIPM returned with flag %i.\n", hpipm_status_);
167  if (hpipm_status_ == 0)
168  {
169  printf("\n -> QP solved!\n");
170  }
171  else if (hpipm_status_ == 1)
172  {
173  printf("\n -> Solver failed! Maximum number of iterations reached\n");
174  }
175  else if (hpipm_status_ == 2)
176  {
177  printf("\n -> Solver failed! Minimum step length reached\n");
178  }
179  else if (hpipm_status_ == 2)
180  {
181  printf("\n -> Solver failed! NaN in computations\n");
182  }
183  else
184  {
185  printf("\n -> Solver failed! Unknown return flag\n");
186  }
187  printf("\nipm iter = %d\n", workspace_.iter);
188  printf("\nalpha_aff\tmu_aff\t\tsigma\t\talpha\t\tmu\n");
189  d_print_e_tran_mat(5, workspace_.iter, workspace_.stat, 5);
190  }
191 }
192 
193 template <int STATE_DIM, int CONTROL_DIM>
194 void HPIPMInterface<STATE_DIM, CONTROL_DIM>::computeStatesAndControls()
195 {
196  // extract solution for x and u
197  for (int ii = 0; ii < N_; ii++)
198  {
199  Eigen::Matrix<double, CONTROL_DIM, 1> u_sol;
200  ::d_ocp_qp_sol_get_u(ii, &qp_sol_, this->u_sol_[ii].data());
201  }
202  for (int ii = 0; ii <= N_; ii++)
203  {
204  Eigen::Matrix<double, STATE_DIM, 1> x_sol;
205  ::d_ocp_qp_sol_get_x(ii, &qp_sol_, this->x_sol_[ii].data());
206  }
207 
208  // display iteration summary
210  {
211  printSolution();
212  }
213 }
214 
215 template <int STATE_DIM, int CONTROL_DIM>
216 void HPIPMInterface<STATE_DIM, CONTROL_DIM>::computeLrInvArray()
217 {
218  // extract data which is mandatory for computing either feedback or iLQR feedforward
219  Eigen::Matrix<double, control_dim, control_dim> Lr;
220  for (int i = 0; i < N_; i++)
221  {
222  ::d_ocp_qp_ipm_get_ric_Lr(i, &workspace_, Lr.data());
223  Lr_inv_[i] = (Lr.template triangularView<Eigen::Lower>())
224  .solve(Eigen::Matrix<double, control_dim, control_dim>::Identity());
225  }
226  isLrInvComputed_ = true;
227 }
228 
229 template <int STATE_DIM, int CONTROL_DIM>
230 void HPIPMInterface<STATE_DIM, CONTROL_DIM>::computeFeedbackMatrices()
231 {
232  if (isLrInvComputed_ == false)
233  computeLrInvArray(); // update Lr_inv_ first
234 
235  LQOCProblem<STATE_DIM, CONTROL_DIM>& p = *this->lqocProblem_;
236  this->L_.resize(p.getNumberOfStages());
237 
238  // for steps k=1,...,N-1 we can just read Ls, Lr_inv already has been computed
239  Eigen::Matrix<double, state_dim, control_dim> Ls;
240 
241  for (int i = 1; i < this->lqocProblem_->getNumberOfStages(); i++)
242  {
243  ::d_ocp_qp_ipm_get_ric_Ls(i, &workspace_, Ls.data());
244  this->L_[i] = -(Ls * Lr_inv_[i]).transpose();
245  }
246 
247  // for stage k=0, HPIPM does not have meaningful entries for Ls, so we have to manually design the feedback
248  // retrieve Riccati matrix for stage 1 (we call it S, others call it P)
249  Eigen::Matrix<double, state_dim, state_dim> S1;
250  ::d_ocp_qp_ipm_get_ric_P(1, &workspace_, S1.data());
251 
252  // step2: compute G[0]
253  Eigen::Matrix<double, control_dim, state_dim> G;
254  G = p.P_[0];
255  G.noalias() += p.B_[0].transpose() * S1 * p.A_[0];
256 
257  // step3: compute K[0] = H.inverse() * G
258  this->L_[0] = (-Lr_inv_[0].transpose() * Lr_inv_[0] * G);
259 }
260 
261 template <int STATE_DIM, int CONTROL_DIM>
262 void HPIPMInterface<STATE_DIM, CONTROL_DIM>::compute_lv()
263 {
264  if (this->lqocProblem_->isConstrained())
265  throw std::runtime_error(
266  "Retrieving lv is not compatible with constraints in HPIPM. Switch to different algorithm, e.g. GNMS, "
267  "which does not require lv");
268 
269  if (isLrInvComputed_ == false)
270  computeLrInvArray(); // update Lr_inv_ first
271 
272  Eigen::Matrix<double, control_dim, 1> lr;
273  for (int i = 0; i < this->lqocProblem_->getNumberOfStages(); i++)
274  {
275  ::d_ocp_qp_ipm_get_ric_lr(i, &workspace_, lr.data());
276  this->lv_[i] = -Lr_inv_[i].transpose() * lr;
277  }
278 }
279 
280 template <int STATE_DIM, int CONTROL_DIM>
282 {
283 #ifdef HPIPM_PRINT_MATRICES
284  int ii;
285 
286  std::cout << "Solution for u: " << std::endl;
287  for (ii = 0; ii < N_; ii++)
288  {
289  std::cout << this->u_sol_[ii].transpose() << std::endl;
290  }
291 
292  std::cout << "Solution for x: " << std::endl;
293  for (ii = 0; ii <= N_; ii++)
294  {
295  std::cout << this->x_sol_[ii].transpose() << std::endl;
296  }
297 #endif // HPIPM_PRINT_MATRICES
298 
299  int iter;
300  ::d_ocp_qp_ipm_get_iter(&workspace_, &iter);
301  printf("\nalpha_aff\tmu_aff\t\tsigma\t\talpha\t\tmu\n");
302  ::d_print_mat(5, iter, workspace_.stat, 5);
303 }
304 
305 
306 template <int STATE_DIM, int CONTROL_DIM>
307 void HPIPMInterface<STATE_DIM, CONTROL_DIM>::setProblemImpl(
308  std::shared_ptr<LQOCProblem<STATE_DIM, CONTROL_DIM>> lqocProblem)
309 {
310  // check if the number of stages N changed and adapt problem dimensions
311  bool dimsChanged = changeProblemSize(lqocProblem);
312 
313  // WARNING: the allocation should in practice not have to happen during the loop.
314  // If possible, prefer receding horizon MPC problems.
315  // If the number of stages has changed, however, the problem needs to be re-built:
316 
317  // setup unconstrained part of problem
318  setupCostAndDynamics(lqocProblem->A_, lqocProblem->B_, lqocProblem->b_, lqocProblem->P_, lqocProblem->qv_,
319  lqocProblem->Q_, lqocProblem->rv_, lqocProblem->R_);
320 
321  if (dimsChanged)
322  {
324  }
325  else
326  {
327  // we need to call the setters to transform our data into HPIPM interal structures
328  ::d_ocp_qp_set_all(hA_.data(), hB_.data(), hb_.data(), hQ_.data(), hS_.data(), hR_.data(), hq_.data(),
329  hr_.data(), hidxbx_.data(), hlbx_.data(), hubx_.data(), hidxbu_.data(), hlbu_.data(), hubu_.data(),
330  hC_.data(), hD_.data(), hlg_.data(), hug_.data(), hZl_.data(), hZu_.data(), hzl_.data(), hzu_.data(),
331  hidxs_.data(), hlls_.data(), hlus_.data(), &qp_);
332  }
333 }
334 
335 
336 template <int STATE_DIM, int CONTROL_DIM>
337 bool HPIPMInterface<STATE_DIM, CONTROL_DIM>::configureInputBoxConstraints(
338  std::shared_ptr<LQOCProblem<STATE_DIM, CONTROL_DIM>> lqocProblem)
339 {
340  bool configChanged = false;
341 
342  const int N = lqocProblem->getNumberOfStages();
343 
344  if ((int)nbu_.size() != N + 1)
345  {
346  nbu_.resize(N + 1, 0);
347  hidxbu_.resize(N + 1);
348  hlbu_.resize(N + 1);
349  hubu_.resize(N + 1);
350  configChanged = true;
351  }
352 
353  // stages 1 to N
354  for (int i = 0; i < N; i++)
355  {
356  if (nbu_[i] != lqocProblem->nbu_[i])
357  {
358  nbu_[i] = lqocProblem->nbu_[i];
359 
360  // set pointers to box constraint boundaries and sparsity pattern
361  hlbu_[i] = lqocProblem->u_lb_[i].data();
362  hubu_[i] = lqocProblem->u_ub_[i].data();
363  hidxbu_[i] = lqocProblem->u_I_[i].data();
364 
365  configChanged = true;
366  }
367  }
368 
369  return configChanged;
370 }
371 
372 
373 template <int STATE_DIM, int CONTROL_DIM>
374 bool HPIPMInterface<STATE_DIM, CONTROL_DIM>::configureStateBoxConstraints(
375  std::shared_ptr<LQOCProblem<STATE_DIM, CONTROL_DIM>> lqocProblem)
376 {
377  bool configChanged = false;
378 
379  const int N = lqocProblem->getNumberOfStages();
380 
381  if ((int)nbx_.size() != N + 1)
382  {
383  nbx_.resize(N + 1, 0);
384  hidxbx_.resize(N + 1);
385  hlbx_.resize(N + 1);
386  hubx_.resize(N + 1);
387  configChanged = true;
388  }
389 
390  // stages 1 to N + 1
391  for (int i = 0; i < N + 1; i++)
392  {
393  // first stage requires special treatment as state is not a decision variable
394  if (i == 0)
395  {
396  nbx_[i] = 0;
397  continue;
398  }
399 
400  if (nbx_[i] != lqocProblem->nbx_[i])
401  {
402  nbx_[i] = lqocProblem->nbx_[i];
403 
404  // set pointers to box constraint boundaries and sparsity pattern
405  hlbx_[i] = lqocProblem->x_lb_[i].data();
406  hubx_[i] = lqocProblem->x_ub_[i].data();
407  hidxbx_[i] = lqocProblem->x_I_[i].data();
408 
409  configChanged = true;
410  }
411  }
412 
413  return configChanged;
414 }
415 
416 
417 template <int STATE_DIM, int CONTROL_DIM>
418 bool HPIPMInterface<STATE_DIM, CONTROL_DIM>::configureGeneralConstraints(
419  std::shared_ptr<LQOCProblem<STATE_DIM, CONTROL_DIM>> lqocProblem)
420 {
421  bool configChanged = false;
422 
423  const int N = lqocProblem->getNumberOfStages();
424  if ((int)ng_.size() != N + 1)
425  {
426  ng_.resize(N + 1, 0);
427  hlg_.resize(N + 1, 0);
428  hug_.resize(N + 1, 0);
429  hC_.resize(N + 1);
430  hD_.resize(N + 1);
431  configChanged = true;
432  }
433 
434 
435  // HPIPM-specific correction for first-stage general constraint bounds
436  hd_lg_0_Eigen_ = lqocProblem->d_lb_[0]; // - lqocProblem->C_[0] * x0; // uncommented since x0=0
437  hd_ug_0_Eigen_ = lqocProblem->d_ub_[0]; // - lqocProblem->C_[0] * x0; // uncommented since x0=0
438 
439  for (int i = 0; i < N + 1; i++) // (includes the terminal stage)
440  {
441  // get the number of constraints
442  if (ng_[i] != lqocProblem->ng_[i])
443  {
444  ng_[i] = lqocProblem->ng_[i];
445  configChanged = true;
446  }
447 
448  lqocProblem->C_[i].resize(lqocProblem->ng_[i], STATE_DIM);
449  lqocProblem->D_[i].resize(lqocProblem->ng_[i], CONTROL_DIM);
450  lqocProblem->d_lb_[i].resize(lqocProblem->ng_[i], 1);
451  lqocProblem->d_ub_[i].resize(lqocProblem->ng_[i], 1);
452 
453  // set pointers to hpipm-style box constraint boundaries and sparsity pattern
454  if (i == 0)
455  {
456  hlg_[i] = hd_lg_0_Eigen_.data();
457  hug_[i] = hd_ug_0_Eigen_.data();
458  }
459  else
460  {
461  hlg_[i] = lqocProblem->d_lb_[i].data();
462  hug_[i] = lqocProblem->d_ub_[i].data();
463  }
464 
465  hC_[i] = lqocProblem->C_[i].data();
466  hD_[i] = lqocProblem->D_[i].data();
467  }
468 
469  return configChanged;
470 }
471 
472 
473 template <int STATE_DIM, int CONTROL_DIM>
474 void HPIPMInterface<STATE_DIM, CONTROL_DIM>::setupCostAndDynamics(StateMatrixArray& A,
476  StateVectorArray& b,
477  FeedbackArray& P,
478  StateVectorArray& qv,
479  StateMatrixArray& Q,
480  ControlVectorArray& rv,
482 {
483  if (N_ == -1)
484  throw std::runtime_error("Time horizon not set, please set it first");
485 
486  this->x_sol_[0].setZero(); // fixed intitial value problem (increment is zero)
487 
488  // IMPORTANT: for hb_ and hr_, we need a HPIPM-specific correction for the first stage
489  hb0_ = b[0]; // + A[0] * x0; // uncommented since x0 = 0 in diff formulation
490  hr0_ = rv[0]; // + P[0] * x0; // uncommented since x0 = 0 in diff formulation
491 
492  // assign data for LQ problem
493  for (int i = 0; i < N_; i++)
494  {
495  hA_[i] = A[i].data();
496  hB_[i] = B[i].data();
497 
498  if (i > 0)
499  hb_[i] = b[i].data(); // do not mutate pointers for init stage
500  }
501 
502  for (int i = 0; i < N_; i++)
503  {
504  hQ_[i] = Q[i].data();
505  hS_[i] = P[i].data();
506  hR_[i] = R[i].data();
507  hq_[i] = qv[i].data();
508 
509  if (i > 0)
510  hr_[i] = rv[i].data(); // do not mutate pointers for init stage
511  }
512 
513  // terminal stage
514  hQ_[N_] = Q[N_].data();
515  hq_[N_] = qv[N_].data();
516 }
517 
518 
519 template <int STATE_DIM, int CONTROL_DIM>
520 bool HPIPMInterface<STATE_DIM, CONTROL_DIM>::changeProblemSize(std::shared_ptr<LQOCProblem<STATE_DIM, CONTROL_DIM>> p)
521 {
522  const int N = p->getNumberOfStages();
523 
524  // check if the problem horizon changed
525  bool horizonChanged = false;
526  if (N_ != N)
527  {
528  horizonChanged = true;
529  }
530 
531  N_ = N;
532 
533  // check if the constraint configuration changed
534  bool numConstraintsChanged = false;
535 
537  numConstraintsChanged = true;
538 
540  numConstraintsChanged = true;
541 
543  numConstraintsChanged = true;
544 
545 
546  // if neither the problem horizon nor the number of constraints changed, return false
547  if (!horizonChanged && !numConstraintsChanged)
548  {
549  return false;
550  }
551 
552  // resize control input variable counter
553  if (nu_.size() > 0)
554  nu_.back() = CONTROL_DIM; // avoid error in case of increasing horizon
555  nu_.resize(N_ + 1, CONTROL_DIM); // initialize number of control inputs per stage
556  nu_[N_] = 0; // last input is not a decision variable
557 
558  nx_.resize(N_ + 1, STATE_DIM); // initialize number of states per stage
559  nx_[0] = 0; // initial state is not a decision variable but given
560 
561 
562  // resize the containers for the affine system dynamics approximation
563  hA_.resize(N_);
564  hB_.resize(N_);
565  hb_.resize(N_);
566 
567  this->x_sol_.resize(N_ + 1);
568  this->u_sol_.resize(N_);
569  this->lv_.resize(N_);
570  this->L_.resize(N_);
571 
572  // resize the containers for the LQ cost approximation
573  hQ_.resize(N_ + 1);
574  hS_.resize(N_ + 1);
575  hR_.resize(N_ + 1);
576  hq_.resize(N_ + 1);
577  hr_.resize(N_ + 1);
578 
579  // currently ignored stuff (resized anyways)
580  nsbx_.resize(N_ + 1, 0); // no softened state box constraints
581  nsbu_.resize(N_ + 1, 0); // no softened input box constraints
582  nsg_.resize(N_ + 1, 0); // no softened general constraints
583 
584  hZl_.resize(N_ + 1, 0);
585  hZu_.resize(N_ + 1, 0);
586  hzl_.resize(N_ + 1, 0);
587  hzu_.resize(N_ + 1, 0);
588 
589  hidxs_.resize(N_ + 1, 0);
590 
591  hlls_.resize(N_ + 1, 0);
592  hlus_.resize(N_ + 1, 0);
593 
594  Lr_inv_.resize(N_);
595 
596  // assignments that stay constant despite varying problem impl data
597  hb_[0] = hb0_.data();
598  hr_[0] = hr0_.data();
599 
600  hS_[N_] = nullptr;
601  hR_[N_] = nullptr;
602  hr_[N_] = nullptr;
603 
604  return true;
605 }
606 
607 template <int STATE_DIM, int CONTROL_DIM>
608 void HPIPMInterface<STATE_DIM, CONTROL_DIM>::d_print_mat(int m, int n, double* A, int lda)
609 {
610  int i, j;
611  for (i = 0; i < m; i++)
612  {
613  for (j = 0; j < n; j++)
614  {
615  printf("%9.5f ", A[i + lda * j]);
616  }
617  printf("\n");
618  }
619  printf("\n");
620 }
621 
622 
623 template <int STATE_DIM, int CONTROL_DIM>
624 void HPIPMInterface<STATE_DIM, CONTROL_DIM>::d_print_e_tran_mat(int row, int col, double* A, int lda)
625 {
626  int i, j;
627  for (j = 0; j < col; j++)
628  {
629  for (i = 0; i < row; i++)
630  {
631  printf("%e\t", A[i + lda * j]);
632  }
633  printf("\n");
634  }
635  printf("\n");
636 }
637 
638 
639 template <int STATE_DIM, int CONTROL_DIM>
640 const ct::core::ControlVectorArray<CONTROL_DIM>& HPIPMInterface<STATE_DIM, CONTROL_DIM>::get_lv()
641 {
642  if (this->lqocProblem_->isConstrained())
643  throw std::runtime_error(
644  "Retrieving lv is not compatible with constraints in HPIPM. Switch to different algorithm, e.g. GNMS, "
645  "which does not require lv");
646 
647  return this->lv_;
648 }
649 
650 } // namespace optcon
651 } // namespace ct
652 
653 #endif // HPIPM
void printSolution(const ct::core::StateVectorArray< state_dim > &x, const ct::core::ControlVectorArray< control_dim > &u, const ct::core::FeedbackArray< state_dim, control_dim > &K)
Definition: ConstrainedLQOCSolverTest.h:16
virtual bool configureStateBoxConstraints(std::shared_ptr< LQOCProblem< STATE_DIM, CONTROL_DIM >> lqocProblem)
Definition: LQOCSolver.hpp:58
ct::core::FeedbackArray< STATE_DIM, CONTROL_DIM, SCALAR > L_
Definition: LQOCSolver.hpp:111
int num_lqoc_iterations
Definition: NLOptConSettings.hpp:160
#define data
DiscreteArray< StateMatrix< STATE_DIM, SCALAR > > StateMatrixArray
virtual bool configureGeneralConstraints(std::shared_ptr< LQOCProblem< STATE_DIM, CONTROL_DIM >> lqocProblem)
setup and configure the general (in)equality constraints
Definition: LQOCSolver.hpp:65
virtual void configure(const NLOptConSettings &settings) override
Definition: GNRiccatiSolver-impl.hpp:49
std::shared_ptr< LQOCProblem_t > lqocProblem_
Definition: LQOCSolver.hpp:107
DiscreteArray< ControlMatrix< CONTROL_DIM, SCALAR > > ControlMatrixArray
for i
Definition: mpc_unittest_plotting.m:14
core::ControlVectorArray< CONTROL_DIM, SCALAR > u_sol_
Definition: LQOCSolver.hpp:110
ct::core::ControlVectorArray< CONTROL_DIM, SCALAR > lv_
Definition: LQOCSolver.hpp:112
virtual bool configureInputBoxConstraints(std::shared_ptr< LQOCProblem< STATE_DIM, CONTROL_DIM >> lqocProblem)
setup and configure the box constraints
Definition: LQOCSolver.hpp:52
LQOCSolverSettings lqoc_solver_settings
the line search settings
Definition: NLOptConSettings.hpp:276
virtual void initializeAndAllocate() override
a method reserved for memory allocation (e.g. required for HPIPM)
Definition: GNRiccatiSolver-impl.hpp:286
int N_
Definition: GNRiccatiSolver.hpp:93
bool lqoc_debug_print
Definition: NLOptConSettings.hpp:159
DiscreteArray< StateControlMatrix< STATE_DIM, CONTROL_DIM, SCALAR > > StateControlMatrixArray
core::StateVectorArray< STATE_DIM, SCALAR > x_sol_
Definition: LQOCSolver.hpp:109
NLOptConSettings settings_
Definition: GNRiccatiSolver.hpp:80