export_gauss_newton_hpmpc.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ACADO Toolkit.
3  *
4  * ACADO Toolkit -- A Toolkit for Automatic Control and Dynamic Optimization.
5  * Copyright (C) 2008-2014 by Boris Houska, Hans Joachim Ferreau,
6  * Milan Vukov, Rien Quirynen, KU Leuven.
7  * Developed within the Optimization in Engineering Center (OPTEC)
8  * under supervision of Moritz Diehl. All rights reserved.
9  *
10  * ACADO Toolkit is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 3 of the License, or (at your option) any later version.
14  *
15  * ACADO Toolkit is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with ACADO Toolkit; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  */
25 
34 
36 
37 using namespace std;
38 
40  const std::string& _commonHeaderName
41  ) : ExportNLPSolver( _userInteraction,_commonHeaderName )
42 {}
43 
45 {
47 
49 
51 
53 
55 
57 
59 
61 
62  return SUCCESSFUL_RETURN;
63 }
64 
66  ExportStruct dataStruct
67  ) const
68 {
69  returnValue status;
70  status = ExportNLPSolver::getDataDeclarations(declarations, dataStruct);
71  if (status != SUCCESSFUL_RETURN)
72  return status;
73 
74  declarations.addDeclaration(x0, dataStruct);
75 
76  if (Q1.isGiven() == true)
77  declarations.addDeclaration(qpQ, dataStruct);
78  if (QN1.isGiven() == true)
79  declarations.addDeclaration(qpQf, dataStruct);
80  if (S1.isGiven() == true)
81  declarations.addDeclaration(qpS, dataStruct);
82  if (R1.isGiven() == true)
83  declarations.addDeclaration(qpR, dataStruct);
84 
85  declarations.addDeclaration(qpq, dataStruct);
86  declarations.addDeclaration(qpqf, dataStruct);
87  declarations.addDeclaration(qpr, dataStruct);
88 
89  declarations.addDeclaration(qpx, dataStruct);
90  declarations.addDeclaration(qpu, dataStruct);
91 
92  declarations.addDeclaration(qpLb, dataStruct);
93  declarations.addDeclaration(qpUb, dataStruct);
94 
95  declarations.addDeclaration(qpLbA, dataStruct);
96  declarations.addDeclaration(qpUbA, dataStruct);
97 
98  declarations.addDeclaration(sigmaN, dataStruct);
99 
100  declarations.addDeclaration(qpLambda, dataStruct);
101  declarations.addDeclaration(qpMu, dataStruct);
102 
103  declarations.addDeclaration(nIt, dataStruct);
104 
105  return SUCCESSFUL_RETURN;
106 }
107 
109  ) const
110 {
111  declarations.addDeclaration( preparation );
112  declarations.addDeclaration( feedback );
113 
114  declarations.addDeclaration( initialize );
115  declarations.addDeclaration( initializeNodes );
116  declarations.addDeclaration( shiftStates );
117  declarations.addDeclaration( shiftControls );
118  declarations.addDeclaration( getKKT );
119  declarations.addDeclaration( getObjective );
120 
121  declarations.addDeclaration( evaluateStageCost );
122  declarations.addDeclaration( evaluateTerminalCost );
123 
124  return SUCCESSFUL_RETURN;
125 }
126 
128  )
129 {
130  qpInterface->exportCode();
131 
132  string moduleName;
133  get(CG_MODULE_NAME, moduleName);
134  // Forward declaration, same as in the template file.
135  code << "#ifdef __cplusplus\n";
136  code << "extern \"C\"{\n";
137  code << "#endif\n";
138  code << "int " << moduleName << "_hpmpc_wrapper(real_t* A, real_t* B, real_t* d, real_t* Q, real_t* Qf, real_t* S, real_t* R, real_t* q, real_t* qf, real_t* r, real_t* lb, real_t* ub, real_t* C, real_t* D, real_t* lbg, real_t* ubg, real_t* CN, real_t* x, real_t* u, real_t* lambda, real_t* mu, int* nIt);\n";
139  code << "#ifdef __cplusplus\n";
140  code << "}\n";
141  code << "#endif\n";
142 
143  if (initialStateFixed() == false)
144  {
145  // MHE case, we use a wrapper directly from the NMPC
146  code << "#define NX " << toString( NX ) << "\n";
147  code << "#define NU " << toString( NU ) << "\n";
148  code << "#define NW " << toString( NU ) << "\n";
149  code << "#define NY " << toString( NY ) << "\n";
150  code << "#define NN " << toString( N ) << "\n";
151 
152  code << "#include <hpmpc/c_interface.h>\n\n";
153  }
154 
155  code.addLinebreak( 2 );
156  code.addStatement( "/******************************************************************************/\n" );
157  code.addStatement( "/* */\n" );
158  code.addStatement( "/* ACADO code generation */\n" );
159  code.addStatement( "/* */\n" );
160  code.addStatement( "/******************************************************************************/\n" );
161  code.addLinebreak( 2 );
162 
163  int useOMP;
164  get(CG_USE_OPENMP, useOMP);
165  if ( useOMP )
166  {
167  code.addDeclaration( state );
168  }
169 
171 
174  code.addFunction( setObjQ1Q2 );
175  code.addFunction( setObjR1R2 );
176  code.addFunction( setObjS1 );
177  code.addFunction( setObjQN1QN2 );
178  code.addFunction( setStagef );
180 
182 
183  for (unsigned i = 0; i < evaluatePointConstraints.size(); ++i)
184  {
185  if (evaluatePointConstraints[ i ] == 0)
186  continue;
188  }
189 
190  code.addFunction( setStagePac );
192 
193  code.addFunction( acc );
194 
195  code.addFunction( preparation );
196  code.addFunction( feedback );
197 
198  code.addFunction( initialize );
200  code.addFunction( shiftStates );
201  code.addFunction( shiftControls );
202  code.addFunction( getKKT );
203  code.addFunction( getObjective );
204 
205  return SUCCESSFUL_RETURN;
206 }
207 
208 
210 {
211  if (initialStateFixed() == true)
212  return N * NX + N * NU;
213 
214  return (N + 1) * NX + N * NU;
215 }
216 
217 //
218 // PROTECTED FUNCTIONS:
219 //
220 
222 {
223  evaluateObjective.setup("evaluateObjective");
224 
225  int variableObjS;
226  get(CG_USE_VARIABLE_WEIGHTING_MATRIX, variableObjS);
227 
228  ExportVariable evLmX = zeros<double>(NX, NX);
229  ExportVariable evLmU = zeros<double>(NU, NU);
230 
231  if (levenbergMarquardt > 0.0)
232  {
233  DMatrix lmX = eye<double>( NX );
234  lmX *= levenbergMarquardt;
235 
236  DMatrix lmU = eye<double>( NU );
237  lmU *= levenbergMarquardt;
238 
239  evLmX = lmX;
240  evLmU = lmU;
241  }
242 
243  //
244  // Main loop that calculates Hessian and gradients
245  //
246 
247  ExportIndex runObj( "runObj" );
248  ExportForLoop loopObjective( runObj, 0, N );
249 
250  evaluateObjective.addIndex( runObj );
251 
252  loopObjective.addStatement( objValueIn.getCols(0, getNX()) == x.getRow( runObj ) );
253  loopObjective.addStatement( objValueIn.getCols(NX, NX + NU) == u.getRow( runObj ) );
254  loopObjective.addStatement( objValueIn.getCols(NX + NU, NX + NU + NOD) == od.getRow( runObj ) );
255  loopObjective.addLinebreak( );
256 
257  // Evaluate the objective function
259 
260  // Stack the measurement function value
261  loopObjective.addStatement(
262  Dy.getRows(runObj * NY, (runObj + 1) * NY) == objValueOut.getTranspose().getRows(0, getNY())
263  );
264  loopObjective.addLinebreak( );
265 
266  // Optionally compute derivatives
267 
268  ExportVariable tmpObjS, tmpFx, tmpFu;
269  ExportVariable tmpFxEnd, tmpObjSEndTerm;
270  tmpObjS.setup("tmpObjS", NY, NY, REAL, ACADO_LOCAL);
271  if (objS.isGiven() == true)
272  tmpObjS = objS;
273  tmpFx.setup("tmpFx", NY, NX, REAL, ACADO_LOCAL);
274  if (objEvFx.isGiven() == true)
275  tmpFx = objEvFx;
276  tmpFu.setup("tmpFu", NY, NU, REAL, ACADO_LOCAL);
277  if (objEvFu.isGiven() == true)
278  tmpFu = objEvFu;
279  tmpFxEnd.setup("tmpFx", NYN, NX, REAL, ACADO_LOCAL);
280  if (objEvFxEnd.isGiven() == true)
281  tmpFxEnd = objEvFxEnd;
282  tmpObjSEndTerm.setup("tmpObjSEndTerm", NYN, NYN, REAL, ACADO_LOCAL);
283  if (objSEndTerm.isGiven() == true)
284  tmpObjSEndTerm = objSEndTerm;
285 
286  unsigned indexX = getNY();
287  ExportArgument tmpFxCall = tmpFx;
288  if (tmpFx.isGiven() == false)
289  {
290  tmpFxCall = objValueOut.getAddress(0, indexX);
291  indexX += objEvFx.getDim();
292  }
293 
294  ExportArgument tmpFuCall = tmpFu;
295  if (tmpFu.isGiven() == false)
296  {
297  tmpFuCall = objValueOut.getAddress(0, indexX);
298  }
299 
300  ExportArgument objSCall = variableObjS == true ? objS.getAddress(runObj * NY, 0) : objS;
301 
302  //
303  // Optional computation of Q1, Q2
304  //
305  if (Q1.isGiven() == false)
306  {
307  ExportVariable tmpQ1, tmpQ2;
308  tmpQ1.setup("tmpQ1", NX, NX, REAL, ACADO_LOCAL);
309  tmpQ2.setup("tmpQ2", NX, NY, REAL, ACADO_LOCAL);
310 
311  setObjQ1Q2.setup("setObjQ1Q2", tmpFx, tmpObjS, tmpQ1, tmpQ2);
312  setObjQ1Q2.addStatement( tmpQ2 == (tmpFx ^ tmpObjS) );
313  setObjQ1Q2.addStatement( tmpQ1 == tmpQ2 * tmpFx );
314  setObjQ1Q2.addStatement( tmpQ1 += evLmX );
315 
316  loopObjective.addFunctionCall(
317  setObjQ1Q2,
318  tmpFxCall, objSCall,
319  Q1.getAddress(runObj * NX, 0), Q2.getAddress(runObj * NX, 0)
320  );
321 
322  loopObjective.addLinebreak( );
323  }
324  else if (levenbergMarquardt > 0.0)
325  Q1 = Q1.getGivenMatrix() + evLmX.getGivenMatrix();
326 
327  if (R1.isGiven() == false)
328  {
329  ExportVariable tmpR1, tmpR2;
330  tmpR1.setup("tmpR1", NU, NU, REAL, ACADO_LOCAL);
331  tmpR2.setup("tmpR2", NU, NY, REAL, ACADO_LOCAL);
332 
333  setObjR1R2.setup("setObjR1R2", tmpFu, tmpObjS, tmpR1, tmpR2);
334  setObjR1R2.addStatement( tmpR2 == (tmpFu ^ tmpObjS) );
335  setObjR1R2.addStatement( tmpR1 == tmpR2 * tmpFu );
336  setObjR1R2.addStatement( tmpR1 += evLmU );
337 
338  loopObjective.addFunctionCall(
339  setObjR1R2,
340  tmpFuCall, objSCall,
341  R1.getAddress(runObj * NU, 0), R2.getAddress(runObj * NU, 0)
342  );
343 
344  loopObjective.addLinebreak( );
345  }
346  else if (levenbergMarquardt > 0.0)
347  R1 = R1.getGivenMatrix() + evLmU.getGivenMatrix();
348 
349  if (S1.isGiven() == false)
350  {
351  ExportVariable tmpS1;
352  ExportVariable tmpS2;
353 
354  tmpS1.setup("tmpS1", NX, NU, REAL, ACADO_LOCAL);
355  tmpS2.setup("tmpS2", NX, NY, REAL, ACADO_LOCAL);
356 
357  setObjS1.setup("setObjS1", tmpFx, tmpFu, tmpObjS, tmpS1);
358  setObjS1.addVariable( tmpS2 );
359  setObjS1.addStatement( tmpS2 == (tmpFx ^ tmpObjS) );
360  setObjS1.addStatement( tmpS1 == tmpS2 * tmpFu );
361 
362  loopObjective.addFunctionCall(
363  setObjS1,
364  tmpFxCall, tmpFuCall, objSCall,
365  S1.getAddress(runObj * NX, 0)
366  );
367  }
368 
369  evaluateObjective.addStatement( loopObjective );
370 
371  //
372  // Evaluate the quadratic Mayer term
373  //
376 
377  // Evaluate the objective function, last node.
380 
383 
384  if (QN1.isGiven() == false)
385  {
386  ExportVariable tmpQN1, tmpQN2;
387  tmpQN1.setup("tmpQN1", NX, NX, REAL, ACADO_LOCAL);
388  tmpQN2.setup("tmpQN2", NX, NYN, REAL, ACADO_LOCAL);
389 
390  setObjQN1QN2.setup("setObjQN1QN2", tmpFxEnd, tmpObjSEndTerm, tmpQN1, tmpQN2);
391  setObjQN1QN2.addStatement( tmpQN2 == (tmpFxEnd ^ tmpObjSEndTerm) );
392  setObjQN1QN2.addStatement( tmpQN1 == tmpQN2 * tmpFxEnd );
393  setObjQN1QN2.addStatement( tmpQN1 += evLmX );
394 
395  indexX = getNYN();
396  ExportArgument tmpFxEndCall = tmpFxEnd.isGiven() == true ? tmpFxEnd : objValueOut.getAddress(0, indexX);
397 
399  setObjQN1QN2,
400  tmpFxEndCall, objSEndTerm,
401  QN1.getAddress(0, 0), QN2.getAddress(0, 0)
402  );
403 
405  }
406  else if (levenbergMarquardt > 0.0)
407  QN1 = QN1.getGivenMatrix() + evLmX.getGivenMatrix();
408 
409  //
410  // Hessian setup
411  //
412 
413  ExportIndex index( "index" );
414 
415  //
416  // Gradient setup
417  //
418  ExportVariable qq, rr;
419  qq.setup("stageq", NX, 1, REAL, ACADO_LOCAL);
420  rr.setup("stager", NU, 1, REAL, ACADO_LOCAL);
421  setStagef.setup("setStagef", qq, rr, index);
422 
423  if (Q2.isGiven() == false)
425  qq == Q2.getSubMatrix(index * NX, (index + 1) * NX, 0, NY) * Dy.getRows(index * NY, (index + 1) * NY)
426  );
427  else
428  {
429  setStagef << "(void)" << index.getFullName() << ";\n";
431  qq == Q2 * Dy.getRows(index * NY, (index + 1) * NY)
432  );
433  }
435 
436  if (R2.isGiven() == false)
438  rr == R2.getSubMatrix(index * NU, (index + 1) * NU, 0, NY) * Dy.getRows(index * NY, (index + 1) * NY)
439  );
440  else
441  {
443  rr == R2 * Dy.getRows(index * NY, (index + 1) * NY)
444  );
445  }
446 
447  //
448  // Setup necessary QP variables
449  //
450 
451  if (Q1.isGiven() == true)
452  {
453  qpQ.setup("qpQ", N * NX, NX, REAL, ACADO_WORKSPACE);
454  for (unsigned blk = 0; blk < N; ++blk)
455  initialize.addStatement( qpQ.getSubMatrix(blk * NX, (blk + 1) * NX, 0, NX) == Q1);
456  }
457  else
458  {
459  qpQ = Q1;
460  }
461 
462  if (R1.isGiven() == true)
463  {
464  qpR.setup("qpR", N * NU, NU, REAL, ACADO_WORKSPACE);
465  for (unsigned blk = 0; blk < N; ++blk)
466  initialize.addStatement( qpR.getSubMatrix(blk * NU, (blk + 1) * NU, 0, NU) == R1);
467  }
468  else
469  {
470  qpR = R1;
471  }
472 
473  if (S1.isGiven() == true)
474  {
475  qpS.setup("qpS", N * NX, NU, REAL, ACADO_WORKSPACE);
476  if (S1.getGivenMatrix().isZero() == true)
477  initialize.addStatement(qpS == zeros<double>(N * NX, NU));
478  else
479  for (unsigned blk = 0; blk < N; ++blk)
480  initialize.addStatement( qpS.getSubMatrix(blk * NX, (blk + 1) * NX, 0, NU) == S1);
481  }
482  else
483  {
484  qpS = S1;
485  }
486 
487  if (QN1.isGiven() == true)
488  {
489  qpQf.setup("qpQf", NX, NX, REAL, ACADO_WORKSPACE);
491  }
492  else
493  {
494  qpQf = QN1;
495  }
496 
497  return SUCCESSFUL_RETURN;
498 }
499 
501 {
503  //
504  // Setup evaluation of box constraints on states and controls
505  //
507 
508 
509 
510 // int hardcodeConstraintValues;
511 // get(CG_HARDCODE_CONSTRAINT_VALUES, hardcodeConstraintValues);
512 
513  evaluateConstraints.setup("evaluateConstraints");
514 
515  DVector lbTmp, ubTmp;
516 
517  DVector lbXInf( NX );
518  lbXInf.setAll( -INFTY );
519 
520  DVector ubXInf( NX );
521  ubXInf.setAll( INFTY );
522 
523  DVector lbUInf( NU );
524  lbUInf.setAll( -INFTY );
525 
526  DVector ubUInf( NU );
527  ubUInf.setAll( INFTY );
528 
529  DVector lbValues, ubValues;
530 
531  //
532  // Stack input bounds
533  //
534  for (unsigned node = 0; node < N; ++node)
535  {
536  lbTmp = uBounds.getLowerBounds( node );
537  if ( !lbTmp.getDim() )
538  lbValues.append( lbUInf );
539  else
540  lbValues.append( lbTmp );
541 
542  ubTmp = uBounds.getUpperBounds( node );
543  if ( !ubTmp.getDim() )
544  ubValues.append( ubUInf );
545  else
546  ubValues.append( ubTmp );
547  }
548 
549  //
550  // Stack state bounds
551  //
552  for (unsigned node = 1; node < N + 1; ++node)
553  {
554  lbTmp = xBounds.getLowerBounds( node );
555  if ( !lbTmp.getDim() )
556  lbValues.append( lbXInf );
557  else
558  lbValues.append( lbTmp );
559 
560  ubTmp = xBounds.getUpperBounds( node );
561  if ( !ubTmp.getDim() )
562  ubValues.append( ubXInf );
563  else
564  ubValues.append( ubTmp );
565  }
566 
567  qpLb.setup("qpLb", N * NU + N * NX, 1, REAL, ACADO_WORKSPACE);
568  qpUb.setup("qpUb", N * NU + N * NX, 1, REAL, ACADO_WORKSPACE);
569 
570  evLbValues.setup("evLbValues", lbValues, STATIC_CONST_REAL, ACADO_LOCAL);
571  evUbValues.setup("evUbValues", ubValues, STATIC_CONST_REAL, ACADO_LOCAL);
572 
575 
578 
579  evaluateConstraints.addStatement( qpLb.getRows(N * NU, N * NU + N * NX) == evLbValues.getRows(N * NU, N * NU + N * NX) - x.makeColVector().getRows(NX, NX * (N + 1)) );
580  evaluateConstraints.addStatement( qpUb.getRows(N * NU, N * NU + N * NX) == evUbValues.getRows(N * NU, N * NU + N * NX) - x.makeColVector().getRows(NX, NX * (N + 1)) );
581 
582 
583 
585  //
586  // Setup evaluation of path and point constraints
587  //
589 
590  qpDimHtot = N * dimPacH;
591  qpDimH = N * dimPacH;
592  qpDimHN = 0;
593 
594  qpConDim.resize(N + 1, 0);
595  for (unsigned i = 0; i < N; ++i)
596  qpConDim[ i ] += dimPacH;
597 
598  for (unsigned i = 0; i < N; ++i)
599  if (evaluatePointConstraints[ i ])
600  {
601  unsigned dim = evaluatePointConstraints[ i ]->getFunctionDim() / (1 + NX + NU);
602 
603  qpDimHtot += dim;
604  qpDimH += dim;
605 
606  qpConDim[ i ] += dim;
607  }
608 
609  if (evaluatePointConstraints[ N ])
610  {
611  unsigned dim = evaluatePointConstraints[ N ]->getFunctionDim() / (1 + NX);
612  qpDimHtot += dim;
613  qpDimHN += dim;
614 
615  qpConDim[ N ] += dim;
616  }
617 
618 
619  if (qpDimHtot) // this is a bit of a hack...
620  // dummy qpUbA and qpLbA are created if there are no polytopic constraints
621  {
622  qpLbA.setup("qpLbA", qpDimHtot, 1, REAL, ACADO_WORKSPACE);
623  qpUbA.setup("qpUbA", qpDimHtot, 1, REAL, ACADO_WORKSPACE);
624  qpMu.setup("qpMu", 2 * N * (NX + NU) + 2*qpDimHtot, 1, REAL, ACADO_WORKSPACE);
625  }
626  else
627  {
628  qpLbA.setup("qpLbA", 1, 1, REAL, ACADO_WORKSPACE);
629  qpUbA.setup("qpUbA", 1, 1, REAL, ACADO_WORKSPACE);
630  qpMu.setup("qpMu", 2 * N * (NX + NU), 1, REAL, ACADO_WORKSPACE);
631  }
632 
633  //
634  // Setup constraint values for the whole horizon.
635  //
636  DVector lbAValues;
637  DVector ubAValues;
638 
639  for (unsigned i = 0; i < N; ++i)
640  {
641  if ( dimPacH )
642  {
643  lbAValues.append( lbPathConValues.block(i * dimPacH, 0, dimPacH, 1) );
644  ubAValues.append( ubPathConValues.block(i * dimPacH, 0, dimPacH, 1) );
645  }
646  lbAValues.append( pocLbStack[ i ] );
647  ubAValues.append( pocUbStack[ i ] );
648  }
649  lbAValues.append( pocLbStack[ N ] );
650  ubAValues.append( pocUbStack[ N ] );
651 
652  ExportVariable evLbAValues("lbAValues", lbAValues, STATIC_CONST_REAL);
653  ExportVariable evUbAValues("ubAValues", ubAValues, STATIC_CONST_REAL);
654 
655  evaluateConstraints.addVariable( evLbAValues );
656  evaluateConstraints.addVariable( evUbAValues );
657 
658  //
659  // Evaluate path constraints
660  //
661 
662  if ( dimPacH )
663  {
664  ExportIndex runPac;
665  evaluateConstraints.acquire( runPac );
666  ExportForLoop loopPac(runPac, 0, N);
667 
668  loopPac.addStatement( conValueIn.getCols(0, NX) == x.getRow( runPac ) );
669  loopPac.addStatement( conValueIn.getCols(NX, NX + NU) == u.getRow( runPac ) );
670  loopPac.addStatement( conValueIn.getCols(NX + NU, NX + NU + NOD) == od.getRow( runPac ) );
672 
673  loopPac.addStatement( pacEvH.getRows( runPac * dimPacH, (runPac + 1) * dimPacH) ==
674  conValueOut.getTranspose().getRows(0, dimPacH) );
675  loopPac.addLinebreak( );
676 
677  unsigned derOffset = dimPacH;
678 
679  // Optionally store derivatives
680  if (pacEvHx.isGiven() == false)
681  {
682  loopPac.addStatement(
683  pacEvHx.makeRowVector().getCols(runPac * dimPacH * NX, (runPac + 1) * dimPacH * NX) ==
684  conValueOut.getCols(derOffset, derOffset + dimPacH * NX )
685  );
686 
687  derOffset = derOffset + dimPacH * NX;
688  }
689  if (pacEvHu.isGiven() == false )
690  {
691  loopPac.addStatement(
692  pacEvHu.makeRowVector().getCols(runPac * dimPacH * NU, (runPac + 1) * dimPacH * NU) ==
693  conValueOut.getCols(derOffset, derOffset + dimPacH * NU )
694  );
695  }
696 
697  // Add loop to the function.
699  evaluateConstraints.release( runPac );
701  }
702 
703  //
704  // Evaluate point constraints
705  //
706 
707  for (unsigned i = 0, intRowOffset = 0, dim = 0; i < N + 1; ++i)
708  {
709  if (evaluatePointConstraints[ i ] == 0)
710  continue;
711 
713  string( "Evaluating constraint on node: #" ) + toString( i )
714  );
715 
717  if (i < N)
718  {
719  evaluateConstraints.addStatement( conValueIn.getCols(NX, NX + NU) == u.getRow( i ) );
720  evaluateConstraints.addStatement( conValueIn.getCols(NX + NU, NX + NU + NOD) == od.getRow( i ) );
721  }
722  else
724 
726  evaluatePointConstraints[ i ]->getName(), conValueIn, conValueOut );
728 
729  if (i < N)
730  dim = evaluatePointConstraints[ i ]->getFunctionDim() / (1 + NX + NU);
731  else
732  dim = evaluatePointConstraints[ i ]->getFunctionDim() / (1 + NX);
733 
734  // Fill pocEvH, pocEvHx, pocEvHu
736  pocEvH.getRows(intRowOffset, intRowOffset + dim) ==
737  conValueOut.getTranspose().getRows(0, dim));
739 
741  pocEvHx.makeRowVector().getCols(intRowOffset * NX, (intRowOffset + dim) * NX)
742  == conValueOut.getCols(dim, dim + dim * NX));
744 
745  if (i < N)
746  {
748  pocEvHu.makeRowVector().getCols(intRowOffset * NU, (intRowOffset + dim) * NU)
749  == conValueOut.getCols(dim + dim * NX, dim + dim * NX + dim * NU));
751  }
752 
753  intRowOffset += dim;
754  }
755 
756  //
757  // Copy data to QP solver structures
758  //
759 
760  ExportVariable tLbAValues, tUbAValues;
761  ExportIndex offsetPac("offset"), indPac( "ind" );
762 
763  tLbAValues.setup("lbAValues", dimPacH, 1, REAL, ACADO_LOCAL);
764  tUbAValues.setup("ubAValues", dimPacH, 1, REAL, ACADO_LOCAL);
765 
766  setStagePac.setup("setStagePac", offsetPac, indPac, tLbAValues, tUbAValues);
767 
769  << (qpLbA.getRows(offsetPac, offsetPac + dimPacH) == tLbAValues - pacEvH.getRows(indPac * dimPacH, indPac * dimPacH + dimPacH))
770  << (qpUbA.getRows(offsetPac, offsetPac + dimPacH) == tUbAValues - pacEvH.getRows(indPac * dimPacH, indPac * dimPacH + dimPacH));
771 
772  ExportVariable tPocA;
773  tPocA.setup("tPocA", conValueOut.getDim(), NX + NU, REAL);
774  if ( dimPocH )
776 
777  unsigned offsetEval = 0;
778  unsigned offsetPoc = 0;
779  for (unsigned i = 0; i < N; ++i)
780  {
781  if ( dimPacH )
782  {
784  setStagePac,
785  ExportIndex( offsetEval ), ExportIndex( i ),
786  evLbAValues.getAddress( offsetEval ), evUbAValues.getAddress( offsetEval )
787  );
788 
789  offsetEval += dimPacH;
790  }
791 
792  if ( evaluatePointConstraints[ i ] )
793  {
794  unsigned dim = evaluatePointConstraints[ i ]->getFunctionDim() / (1 + NX + NU);
795 
797 
799  << (tPocA.getSubMatrix(0, dim, 0, NX) == pocEvHx.getSubMatrix(offsetPoc, offsetPoc + dim, 0, NX))
800  << (tPocA.getSubMatrix(0, dim, NX, NX + NU) == pocEvHu.getSubMatrix(offsetPoc, offsetPoc + dim, 0, NU))
801  << (qpLbA.getRows(offsetEval, offsetEval + dim) ==
802  evLbAValues.getRows(offsetEval, offsetEval + dim) - pocEvH.getRows(offsetPoc, offsetPoc + dim))
803  << (qpUbA.getRows(offsetEval, offsetEval + dim) ==
804  evUbAValues.getRows(offsetEval, offsetEval + dim) - pocEvH.getRows(offsetPoc, offsetPoc + dim));
805 
806  offsetEval += dim;
807  offsetPoc += dim;
808  }
809  }
810 
811  if ( evaluatePointConstraints[ N ] )
812  {
813  unsigned dim = evaluatePointConstraints[ N ]->getFunctionDim() / (1 + NX);
814 
816  << (qpLbA.getRows(offsetEval, offsetEval + dim) ==
817  evLbAValues.getRows(offsetEval, offsetEval + dim) - pocEvH.getRows(offsetPoc, offsetPoc + dim))
818  << (qpUbA.getRows(offsetEval, offsetEval + dim) ==
819  evUbAValues.getRows(offsetEval, offsetEval + dim) - pocEvH.getRows(offsetPoc, offsetPoc + dim));
820  }
821 
822  return SUCCESSFUL_RETURN;
823 }
824 
825 
827 {
828  if (initialStateFixed() == true)
829  {
830  x0.setup("x0", NX, 1, REAL, ACADO_VARIABLES);
831  x0.setDoc( "Current state feedback vector." );
832  }
833  else
834  {
835  xAC.setup("xAC", NX, 1, REAL, ACADO_VARIABLES);
836  DxAC.setup("DxAC", NX, 1, REAL, ACADO_WORKSPACE);
837  SAC.setup("SAC", NX, NX, REAL, ACADO_VARIABLES);
838  sigmaN.setup("sigmaN", NX, NX, REAL, ACADO_VARIABLES);
839  }
840 
841  return SUCCESSFUL_RETURN;
842 }
843 
845 {
846  return SUCCESSFUL_RETURN;
847 }
848 
850 {
852  //
853  // Setup preparation phase
854  //
856  preparation.setup("preparationStep");
857  preparation.doc( "Preparation step of the RTI scheme." );
858 
859  ExportVariable retSim("ret", 1, 1, INT, ACADO_LOCAL, true);
860  retSim.setDoc("Status of the integration module. =0: OK, otherwise the error code.");
861  preparation.setReturnValue(retSim, false);
862 
863  preparation << retSim.getFullName() << " = " << modelSimulation.getName() << "();\n";
864 
867 
869  //
870  // Setup feedback phase
871  //
873  ExportVariable stateFeedback("stateFeedback", NX, 1, REAL, ACADO_LOCAL);
874  ExportVariable returnValueFeedbackPhase("retVal", 1, 1, INT, ACADO_LOCAL, true);
875  returnValueFeedbackPhase.setDoc( "Status code of the HPMPC QP solver." );
876  feedback.setup("feedbackStep" );
877  feedback.doc( "Feedback/estimation step of the RTI scheme." );
878  feedback.setReturnValue( returnValueFeedbackPhase );
879 
880  qpx.setup("qpx", NX * (N + 1), 1, REAL, ACADO_WORKSPACE);
881  qpu.setup("qpu", NU * N, 1, REAL, ACADO_WORKSPACE);
882 
883  qpq.setup("qpq", NX * N, 1, REAL, ACADO_WORKSPACE);
884  qpqf.setup("qpqf", NX, 1, REAL, ACADO_WORKSPACE);
885  qpr.setup("qpr", NU * N, 1, REAL, ACADO_WORKSPACE);
886 
887  qpLambda.setup("qpLambda", N * NX, 1, REAL, ACADO_WORKSPACE);
888 
889  nIt.setup("nIt", 1, 1, INT, ACADO_WORKSPACE);
890 
891 
892  if (initialStateFixed() == false)
893  {
894  // Temporary hack for the workspace
895  feedback << "static real_t qpWork[ HPMPC_RIC_MHE_IF_DP_WORK_SPACE ];\n";
896  }
897  else
898  {
899  // State feedback
900  feedback.addStatement( qpx.getRows(0, NX) == x0 - x.getRow( 0 ).getTranspose() );
901  }
902 
903  //
904  // Calculate objective residuals
905  //
906  feedback.addStatement( Dy -= y );
908  feedback.addStatement( DyN -= yN );
910 
911  for (unsigned i = 0; i < N; ++i)
914  feedback.addStatement( qpqf == QN2 * DyN );
916 
917  //
918  // Arrival cost in the MHE case
919  //
920  if (initialStateFixed() == false)
921  {
922  // It is assumed this is the shifted version from the previous time step!
924  }
925 
926  //
927  // Here we have to add the differences....
928  //
929 
930  string moduleName;
931  get(CG_MODULE_NAME, moduleName);
932 
933  // Call the solver
934  if (initialStateFixed() == true) {
935  feedback
936  << returnValueFeedbackPhase.getFullName() << " = " << moduleName << "_hpmpc_wrapper("
937 
938  << evGx.getAddressString( true ) << ", "
939  << evGu.getAddressString( true ) << ", "
940  << d.getAddressString( true ) << ", "
941 
942  << qpQ.getAddressString( true ) << ", "
943  << qpQf.getAddressString( true ) << ", "
944  << qpS.getAddressString( true ) << ", "
945  << qpR.getAddressString( true ) << ", "
946 
947  << qpq.getAddressString( true ) << ", "
948  << qpqf.getAddressString( true ) << ", "
949  << qpr.getAddressString( true ) << ", "
950 
951  << qpLb.getAddressString( true ) << ", "
952  << qpUb.getAddressString( true ) << ", ";
953 
954  if (qpDimH) {
955  feedback << pacEvHx.getAddressString( true ) << ", "
956  << pacEvHu.getAddressString( true ) << ", ";
957  } else {
958  feedback << "0, 0, ";
959  }
960 
961  feedback << qpLbA.getAddressString( true ) << ", "
962  << qpUbA.getAddressString( true ) << ", ";
963 
964  if (qpDimHN) {
965  feedback << pocEvHx.getAddressString( true ) << ", ";
966  } else {
967  feedback << "0, ";
968  }
969 
970  feedback << qpx.getAddressString( true ) << ", "
971  << qpu.getAddressString( true ) << ", "
972 
973  << qpLambda.getAddressString( true ) << ", "
974  << qpMu.getAddressString( true ) << ", "
975 
976  << nIt.getAddressString( true )
977  << ");\n";
978  }
979  else
980  feedback
981  << returnValueFeedbackPhase.getFullName() << " = " << "c_order_riccati_mhe_if('d', 2, "
982  << toString( NX ) << ", "
983  << toString( NU ) << ", "
984  << toString( NY ) << ", "
985  << toString( N ) << ", "
986 
987  << evGx.getAddressString( true ) << ", "
988  << evGu.getAddressString( true ) << ", "
989  << "0, " // C
990  << d.getAddressString( true ) << ", "
991 
992  << qpR.getAddressString( true ) << ", "
993  << qpQ.getAddressString( true ) << ", "
994  << qpQf.getAddressString( true ) << ", "
995 // << qpS.getAddressString( true ) << ", "
996 
997  << qpr.getAddressString( true ) << ", "
998  << qpq.getAddressString( true ) << ", "
999  << qpqf.getAddressString( true ) << ", "
1000  << "0, " // y
1001 
1002  << DxAC.getAddressString( true ) << ", "
1003  << SAC.getAddressString( true ) << ", "
1004 
1005  << qpx.getAddressString( true ) << ", "
1006  << sigmaN.getAddressString( true ) << ", "
1007  << qpu.getAddressString( true ) << ", "
1008 
1009  << qpLambda.getAddressString( true ) << ", "
1010 
1011  << "qpWork);\n";
1012 
1013  /*
1014  int c_order_riccati_mhe_if( char prec, int alg,
1015  int nx, int nw, int ny, int N,
1016  double *A, double *G, double *C, double *f,
1017  double *R, double *Q, double *Qf,
1018  double *r, double *q, double *qf, double *y,
1019  double *x0, double *L0,
1020  double *xe, double *Le, double *w,
1021  double *lam, double *work0 );
1022  */
1023 
1024  // XXX Not 100% sure about this one
1025 
1026  // Accumulate the solution, i.e. perform full Newton step
1029 
1030  if (initialStateFixed() == false)
1031  {
1032  // This is the arrival cost for the next time step!
1034  }
1035 
1037  //
1038  // Setup evaluation of the KKT tolerance
1039  //
1041 
1042  ExportVariable kkt("kkt", 1, 1, REAL, ACADO_LOCAL, true);
1043  ExportVariable tmp("tmp", 1, 1, REAL, ACADO_LOCAL, true);
1044  ExportIndex index( "index" );
1045 
1046  getKKT.setup( "getKKT" );
1047  getKKT.doc( "Get the KKT tolerance of the current iterate." );
1048  kkt.setDoc( "The KKT tolerance value." );
1049  getKKT.setReturnValue( kkt );
1050  getKKT.addVariable( tmp );
1051  getKKT.addIndex( index );
1052 
1053  getKKT.addStatement( kkt == 0.0 );
1054 
1055  // XXX This is still probably relevant for the NMPC case
1056 
1057  getKKT.addStatement( tmp == (qpq ^ qpx.getRows(0, N * NX)) );
1058  getKKT << kkt.getFullName() << " += fabs( " << tmp.getFullName() << " );\n";
1059  getKKT.addStatement( tmp == (qpqf ^ qpx.getRows(N * NX, (N + 1) * NX)) );
1060  getKKT << kkt.getFullName() << " += fabs( " << tmp.getFullName() << " );\n";
1061  getKKT.addStatement( tmp == (qpr ^ qpu) );
1062  getKKT << kkt.getFullName() << " += fabs( " << tmp.getFullName() << " );\n";
1063 
1064  ExportForLoop lamLoop(index, 0, N * NX);
1065  lamLoop << kkt.getFullName() << "+= fabs( " << d.get(index, 0) << " * " << qpLambda.get(index, 0) << ");\n";
1066  getKKT.addStatement( lamLoop );
1067 
1068  if (initialStateFixed() == true)
1069  {
1070  // XXX This is because the MHE does not support inequality constraints at the moment
1071 
1072  ExportForLoop lbLoop(index, 0, N * NU + N * NX);
1073  lbLoop << kkt.getFullName() << "+= fabs( " << qpLb.get(index, 0) << " * " << qpMu.get(index, 0) << ");\n";
1074  ExportForLoop ubLoop(index, 0, N * NU + N * NX);
1075  ubLoop << kkt.getFullName() << "+= fabs( " << qpUb.get(index, 0) << " * " << qpMu.get(index + N * NU + N * NX, 0) << ");\n";
1076  ExportForLoop lgLoop(index, 0, qpDimHtot);
1077  lgLoop << kkt.getFullName() << "+= fabs( " << qpLbA.get(index, 0) << " * " << qpMu.get(index + 2*N*(NU+NX), 0) << ");\n";
1078  ExportForLoop ugLoop(index, 0, qpDimHtot);
1079  ugLoop << kkt.getFullName() << "+= fabs( " << qpUbA.get(index, 0) << " * " << qpMu.get(index + 2*N*(NU+NX) + qpDimHtot, 0) << ");\n";
1080 
1081  getKKT.addStatement( lbLoop );
1082  getKKT.addStatement( ubLoop );
1083  getKKT.addStatement( lgLoop );
1084  getKKT.addStatement( ugLoop );
1085  }
1086 
1087  return SUCCESSFUL_RETURN;
1088 }
1089 
1091 {
1092  //
1093  // Configure and export QP interface
1094  //
1095 
1096  string folderName;
1097  get(CG_EXPORT_FOLDER_NAME, folderName);
1098 
1099  string moduleName;
1100  get(CG_MODULE_NAME, moduleName);
1101 
1102  string outFile = folderName + "/" + moduleName + "_hpmpc_interface.c";
1103 
1104  qpInterface = std::shared_ptr< ExportHpmpcInterface >(new ExportHpmpcInterface(outFile, commonHeaderName));
1105 
1106  int maxNumQPiterations;
1107  get(MAX_NUM_QP_ITERATIONS, maxNumQPiterations);
1108 
1109  // XXX If not specified, use default value
1110  if ( maxNumQPiterations <= 0 )
1111  maxNumQPiterations = getNumQPvars();
1112 
1113  int printLevel;
1114  get(PRINTLEVEL, printLevel);
1115 
1116  if ( (PrintLevel)printLevel >= HIGH )
1117  printLevel = 2;
1118  else
1119  printLevel = 0;
1120 
1121  int useSinglePrecision;
1122  get(USE_SINGLE_PRECISION, useSinglePrecision);
1123 
1124  int hotstartQP;
1125  get(HOTSTART_QP, hotstartQP);
1126 
1127  qpInterface->configure(
1128  maxNumQPiterations,
1129  printLevel,
1130  useSinglePrecision,
1131  hotstartQP,
1132  pacEvHx.getFullName(),
1133  pacEvHu.getFullName(),
1134  qpLbA.getFullName(),
1135  qpUbA.getFullName(),
1136  qpDimHtot,
1137  qpConDim,
1138  N, NX, NU
1139 
1140  );
1141 
1142  return SUCCESSFUL_RETURN;
1143 }
1144 
ExportVariable objEvFx
ExportVariable conValueOut
ExportVariable getRow(const ExportIndex &idx) const
ExportVariable objS
virtual returnValue getDataDeclarations(ExportStatementBlock &declarations, ExportStruct dataStruct=ACADO_ANY) const
ExportVariable DxAC
ExportFunction shiftStates
ExportVariable pacEvHx
const double INFTY
ExportVariable getTranspose() const
ExportVariable pocEvH
bool initialStateFixed() const
VariablesGrid xBounds
ExportVariable pocEvHx
ExportVariable & setup(const std::string &_name, uint _nRows=1, uint _nCols=1, ExportType _type=REAL, ExportStruct _dataStruct=ACADO_LOCAL, bool _callItByValue=false, const std::string &_prefix=std::string())
bool isGiven(const ExportIndex &rowIdx, const ExportIndex &colIdx) const
uint getNX() const
Allows to pass back messages to the calling function.
ExportVariable conValueIn
DVector getUpperBounds(uint pointIdx) const
ExportVariable pacEvHu
std::vector< DVector > pocLbStack
returnValue addComment(const std::string &_comment)
ExportVariable objEvFxEnd
const DMatrix & getGivenMatrix() const
Allows to export code of a for-loop.
ExportVariable xAC
string toString(T const &value)
VariablesGrid uBounds
virtual returnValue getFunctionDeclarations(ExportStatementBlock &declarations) const
#define CLOSE_NAMESPACE_ACADO
ExportVariable DyN
ExportVariable state
ExportVariable getSubMatrix(const ExportIndex &rowIdx1, const ExportIndex &rowIdx2, const ExportIndex &colIdx1, const ExportIndex &colIdx2) const
ExportVariable evGx
Defines a scalar-valued index variable to be used for exporting code.
Base class for export of NLP/OCP solvers.
ExportAcadoFunction evaluateStageCost
Defines a matrix-valued variable that can be passed as argument to exported functions.
ExportAcadoFunction evaluateTerminalCost
ExportFunction & setup(const std::string &_name="defaultFunctionName", const ExportArgument &_argument1=emptyConstExportArgument, const ExportArgument &_argument2=emptyConstExportArgument, const ExportArgument &_argument3=emptyConstExportArgument, const ExportArgument &_argument4=emptyConstExportArgument, const ExportArgument &_argument5=emptyConstExportArgument, const ExportArgument &_argument6=emptyConstExportArgument, const ExportArgument &_argument7=emptyConstExportArgument, const ExportArgument &_argument8=emptyConstExportArgument, const ExportArgument &_argument9=emptyConstExportArgument)
virtual returnValue setDoc(const std::string &_doc)
virtual returnValue setupInitialization()
std::string commonHeaderName
ExportStruct
virtual returnValue setupQPInterface()
Interface generator for the HPMPC QP solver.
ExportFunction modelSimulation
virtual ExportFunction & doc(const std::string &_doc)
uint getNY() const
ExportVariable getCols(const ExportIndex &idx1, const ExportIndex &idx2) const
ExportFunction getObjective
printLevel
Definition: example1.py:55
unsigned getDim() const
Definition: vector.hpp:172
ExportVariable makeRowVector() const
virtual returnValue setupObjectiveEvaluation(void)
ExportVariable objValueIn
ExportFunction initializeNodes
const std::string get(const ExportIndex &rowIdx, const ExportIndex &colIdx) const
ExportVariable QN2
virtual returnValue setupEvaluation()
virtual returnValue setupSimulation(void)
std::vector< unsigned > qpConDim
ExportVariable QN1
std::vector< std::shared_ptr< ExportAcadoFunction > > evaluatePointConstraints
Encapsulates all user interaction for setting options, logging data and plotting results.
virtual uint getDim() const
ExportFunction shiftControls
returnValue addStatement(const ExportStatement &_statement)
virtual bool isGiven() const
PrintLevel
ExportVariable SAC
std::string getFullName() const
returnValue addLinebreak(uint num=1)
virtual returnValue setupConstraintsEvaluation(void)
ExportAcadoFunction evaluatePathConstraints
ExportGaussNewtonHpmpc(UserInteraction *_userInteraction=0, const std::string &_commonHeaderName="")
uint getNYN() const
GenericVector & append(const GenericVector &_arg)
Definition: vector.cpp:42
virtual returnValue setupVariables()
ExportFunction & setReturnValue(const ExportVariable &_functionReturnValue, bool _returnAsPointer=false)
virtual ExportFunction & acquire(ExportIndex &obj)
ExportFunction & addVariable(const ExportVariable &_var)
void setAll(const T &_value)
Definition: vector.hpp:160
ExportVariable evGu
ExportVariable objSEndTerm
std::string getName() const
ExportVariable getRows(const ExportIndex &idx1, const ExportIndex &idx2) const
returnValue addDeclaration(const ExportVariable &_data, ExportStruct _dataStruct=ACADO_ANY)
returnValue setupAuxiliaryFunctions()
virtual ExportFunction & release(const ExportIndex &obj)
DVector getLowerBounds(uint pointIdx) const
#define BEGIN_NAMESPACE_ACADO
returnValue addFunction(const ExportFunction &_function)
std::vector< DVector > pocUbStack
ExportVariable objEvFu
ExportVariable pacEvH
ExportVariable pocEvHu
std::shared_ptr< ExportHpmpcInterface > qpInterface
Allows to export code for a block of statements.
virtual returnValue getDataDeclarations(ExportStatementBlock &declarations, ExportStruct dataStruct=ACADO_ANY) const
ExportFunction initialize
ExportArgument getAddress(const ExportIndex &_rowIdx, const ExportIndex &_colIdx=emptyConstExportIndex) const
ExportVariable objValueOut
virtual returnValue setupMultiplicationRoutines()
ExportFunction & addIndex(const ExportIndex &_index)
virtual returnValue getCode(ExportStatementBlock &code)
Defines a matrix-valued variable to be used for exporting code.
returnValue addFunctionCall(const std::string &_fName, const ExportArgument &_argument1=emptyConstExportArgument, const ExportArgument &_argument2=emptyConstExportArgument, const ExportArgument &_argument3=emptyConstExportArgument, const ExportArgument &_argument4=emptyConstExportArgument, const ExportArgument &_argument5=emptyConstExportArgument, const ExportArgument &_argument6=emptyConstExportArgument, const ExportArgument &_argument7=emptyConstExportArgument, const ExportArgument &_argument8=emptyConstExportArgument, const ExportArgument &_argument9=emptyConstExportArgument)
ExportVariable makeColVector() const
const std::string getAddressString(bool withDataStruct=true) const


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Mon Jun 10 2019 12:34:34