export_gauss_newton_block_cn2.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 
33 
34 using namespace std;
35 
37 
39  const std::string& _commonHeaderName
40  ) : ExportGaussNewtonCN2( _userInteraction,_commonHeaderName )
41 {}
42 
44 {
45  diagonalH = false;
46  diagonalHN = false;
47 
48  LOG( LVL_DEBUG ) << "Condensing block size: " << getBlockSize() << endl;
49  LOG( LVL_DEBUG ) << "Number of blocks : " << getNumberOfBlocks() << endl;
50  LOG( LVL_DEBUG ) << "# of variables each : " << getNumBlockVariables() << endl;
51  LOG( LVL_DEBUG ) << "# of QP variables : " << getNumQPvars() << " / " << N*(NX+NU)+NX << endl;
52 
53  if (N/getBlockSize() != getNumberOfBlocks())
54  return ACADOERRORTEXT(RET_INVALID_ARGUMENTS, "The condensing block size needs to be a divisor of the horizon length.");
55  if (getBlockSize() == 0 || getBlockSize() > N)
56  return ACADOERRORTEXT(RET_INVALID_ARGUMENTS, "The condensing block size needs to be a divisor of the horizon length.");
57  if (getNumComplexConstraints() > 0)
59  if (performsSingleShooting() == true)
61 
62  LOG( LVL_DEBUG ) << "Solver: setup initialization... " << endl;
64  LOG( LVL_DEBUG ) << "done!" << endl;
65 
66  LOG( LVL_DEBUG ) << "Solver: setup variables... " << endl;
68  LOG( LVL_DEBUG ) << "done!" << endl;
69 
70  LOG( LVL_DEBUG ) << "# of state bounds per block: " << getNumStateBoundsPerBlock() << endl;
71 
72  LOG( LVL_DEBUG ) << "Solver: setup multiplication routines... " << endl;
74  LOG( LVL_DEBUG ) << "done!" << endl;
75 
76  LOG( LVL_DEBUG ) << "Solver: setup model simulation... " << endl;
78  LOG( LVL_DEBUG ) << "done!" << endl;
79 
80  LOG( LVL_DEBUG ) << "Solver: setup objective evaluation... " << endl;
82  LOG( LVL_DEBUG ) << "done!" << endl;
83 
84  LOG( LVL_DEBUG ) << "Solver: setup condensing... " << endl;
86  LOG( LVL_DEBUG ) << "done!" << endl;
87 
88  LOG( LVL_DEBUG ) << "Solver: setup constraints... " << endl;
90  LOG( LVL_DEBUG ) << "done!" << endl;
91 
92  LOG( LVL_DEBUG ) << "Solver: setup evaluation... " << endl;
94  LOG( LVL_DEBUG ) << "done!" << endl;
95 
96  LOG( LVL_DEBUG ) << "Solver: setup auxiliary functions... " << endl;
98  LOG( LVL_DEBUG ) << "done!" << endl;
99 
100  return SUCCESSFUL_RETURN;
101 }
102 
104  ExportStruct dataStruct
105  ) const
106 {
107  returnValue status;
108  status = ExportGaussNewtonCN2::getDataDeclarations(declarations, dataStruct);
109  if (status != SUCCESSFUL_RETURN)
110  return status;
111 
112  declarations.addDeclaration(qpgN, dataStruct);
113  declarations.addDeclaration(qpLb0, dataStruct);
114  declarations.addDeclaration(qpUb0, dataStruct);
115  declarations.addDeclaration(qpC, dataStruct);
116  declarations.addDeclaration(qpc, dataStruct);
117  declarations.addDeclaration(qpH, dataStruct);
118 
119  declarations.addDeclaration(qpLambda, dataStruct);
120  declarations.addDeclaration(qpMu, dataStruct);
121 
122  return SUCCESSFUL_RETURN;
123 }
124 
126  ) const
127 {
128  returnValue status;
129  status = ExportGaussNewtonCN2::getFunctionDeclarations(declarations);
130  if (status != SUCCESSFUL_RETURN)
131  return status;
132 
133  declarations.addDeclaration( cleanup );
134  declarations.addDeclaration( shiftQpData );
135 
136  return SUCCESSFUL_RETURN;
137 }
138 
139 
141 {
142 
144 }
145 
146 //
147 // PROTECTED FUNCTIONS:
148 //
149 
150 
152 {
153  ExportVariable tmp("tmp", 1, 1, REAL, ACADO_LOCAL, true);
154 
155  int hardcodeConstraintValues;
156  get(CG_HARDCODE_CONSTRAINT_VALUES, hardcodeConstraintValues);
157 
159  //
160  // Setup the bounds on control variables
161  //
163 
164  if (initialStateFixed() == true)
165  {
166  qpLb0.setup("qpLb0", 1, NX + getBlockSize()*NU, REAL, ACADO_WORKSPACE);
167  qpUb0.setup("qpUb0", 1, NX + getBlockSize()*NU, REAL, ACADO_WORKSPACE);
168  }
169 
170  DVector lbTmp, ubTmp;
171  DVector lbXValues, ubXValues;
173  DVector lbUValues, ubUValues;
174 
175  DVector lbXInf( NX );
176  lbXInf.setAll( -INFTY );
177  DVector ubXInf( NX );
178  ubXInf.setAll( INFTY );
179 
180  //
181  // Stack state bounds
182  //
183  unsigned index = 0;
184  unsigned numStateBounds = 0;
185  if( getNumStateBoundsPerBlock() ) qpConDim.resize(getNumberOfBlocks() + 1, 0);
186  for (unsigned i = 0; i < getNumberOfBlocks(); ++i) {
187  lbTmp = xBounds.getLowerBounds( i*getBlockSize() );
188  if ( !lbTmp.getDim() )
189  lbXValues.append( lbXInf );
190  else
191  lbXValues.append( lbTmp );
192 
193  ubTmp = xBounds.getUpperBounds( i*getBlockSize() );
194  if ( !ubTmp.getDim() )
195  ubXValues.append( ubXInf );
196  else
197  ubXValues.append( ubTmp );
198 
199  while( index < xBoundsIdx.size() && xBoundsIdx[index] < (i*getBlockSize()+1)*NX ) { // SIMPLE BOUNDS
200  index += 1;
201  }
202  for (unsigned j = 1; j < getBlockSize(); ++j) {
203  lbTmp = xBounds.getLowerBounds( i*getBlockSize()+j );
204  ubTmp = xBounds.getUpperBounds( i*getBlockSize()+j );
205  while( index < xBoundsIdx.size() && xBoundsIdx[index] < (i*getBlockSize()+1+j)*NX ) {
206  unsigned offset = (i*getBlockSize()+j)*NX;
207  lbXAValues(numStateBounds) = lbTmp(xBoundsIdx[index]-offset);
208  ubXAValues(numStateBounds) = ubTmp(xBoundsIdx[index]-offset);
209 
210  numStateBounds += 1;
211  index += 1;
212  }
213  }
215  }
216  lbTmp = xBounds.getLowerBounds( N );
217  if ( !lbTmp.getDim() )
218  lbXValues.append( lbXInf );
219  else
220  lbXValues.append( lbTmp );
221 
222  ubTmp = xBounds.getUpperBounds( N );
223  if ( !ubTmp.getDim() )
224  ubXValues.append( ubXInf );
225  else
226  ubXValues.append( ubTmp );
227 
228  ASSERT( numStateBounds == getNumStateBoundsPerBlock()*getNumberOfBlocks() );
229 
230  ExportVariable evLbXAValues("lbXAValues", lbXAValues, STATIC_CONST_REAL);
231  ExportVariable evUbXAValues("ubXAValues", ubXAValues, STATIC_CONST_REAL);
232  if( hardcodeConstraintValues == YES ) {
233  condensePrep.addVariable( evLbXAValues );
234  condensePrep.addVariable( evUbXAValues );
235  }
236  else {
237  lbAValues.setup("lbAValues", 1, lbXAValues.getDim(), REAL, ACADO_VARIABLES);
238  lbAValues.setDoc( "Lower state bounds values." );
239  ubAValues.setup("ubAValues", 1, ubXAValues.getDim(), REAL, ACADO_VARIABLES);
240  ubAValues.setDoc( "Upper state bounds values." );
241 
242  initialize.addStatement(lbAValues == lbXAValues.transpose());
243  initialize.addStatement(ubAValues == ubXAValues.transpose());
244  }
245 
246  // Add the constraint evaluations to the condensePrep function
247  index = 0;
248  numStateBounds = 0;
249  while( index < xBoundsIdx.size() && xBoundsIdx[index] < NX ) {
250  index += 1;
251  }
252  for (unsigned j = 1; j < getBlockSize(); ++j) {
253  while( index < xBoundsIdx.size() && xBoundsIdx[index] < (1+j)*NX ) {
254  if( hardcodeConstraintValues == YES ) {
255  condensePrep.addStatement( lbA.getRow(blockI*getNumStateBoundsPerBlock()+numStateBounds) == evLbXAValues.getRow(blockI*getNumStateBoundsPerBlock()+numStateBounds) - x.getElement( blockI*getBlockSize()+j, xBoundsIdx[index]-j*NX ) );
256  }
257  else {
259  }
261 
262  if( hardcodeConstraintValues == YES ) {
263  condensePrep.addStatement( ubA.getRow(blockI*getNumStateBoundsPerBlock()+numStateBounds) == evUbXAValues.getRow(blockI*getNumStateBoundsPerBlock()+numStateBounds) - x.getElement( blockI*getBlockSize()+j, xBoundsIdx[index]-j*NX ) );
264  }
265  else {
267  }
269 
271 
272  for (unsigned i = 0; i < j; ++i) { // loop over the controls within one block
273  int offset = i * (2 * getBlockSize() - i + 1) / 2;
274  condensePrep.addStatement( A.getSubMatrix(blockI*getNumStateBoundsPerBlock()+numStateBounds,blockI*getNumStateBoundsPerBlock()+numStateBounds+1,NX+i*NU,NX+(i+1)*NU) == E.getRow((offset-i-1)*NX+xBoundsIdx[index]) );
275  }
276  for (unsigned i = j; i < getBlockSize(); ++i) { // loop over the controls within one block
277  condensePrep.addStatement( A.getSubMatrix(blockI*getNumStateBoundsPerBlock()+numStateBounds,blockI*getNumStateBoundsPerBlock()+numStateBounds+1,NX+i*NU,NX+(i+1)*NU) == zeros<double>(1,NU) );
278  }
279 
280  numStateBounds += 1;
281  index += 1;
282  }
283  }
284  ASSERT( numStateBounds == getNumStateBoundsPerBlock() );
285 
286 
287  ExportVariable evLbXValues("lbXValues", lbXValues, STATIC_CONST_REAL);
288  ExportVariable evUbXValues("ubXValues", ubXValues, STATIC_CONST_REAL);
289 
290  DVector lbUInf( NU );
291  lbUInf.setAll( -INFTY );
292  DVector ubUInf( NU );
293  ubUInf.setAll( INFTY );
294 
295  //
296  // Stack control constraints
297  //
298  for (unsigned i = 0; i < N; ++i)
299  {
300  lbTmp = uBounds.getLowerBounds( i );
301  if ( !lbTmp.getDim() )
302  lbUValues.append( lbUInf );
303  else
304  lbUValues.append( lbTmp );
305 
306  ubTmp = uBounds.getUpperBounds( i );
307  if ( !ubTmp.getDim() )
308  ubUValues.append( ubUInf );
309  else
310  ubUValues.append( ubTmp );
311  }
312 
313  ExportVariable evLbUValues("lbUValues", lbUValues, STATIC_CONST_REAL);
314  ExportVariable evUbUValues("ubUValues", ubUValues, STATIC_CONST_REAL);
315 
316  //
317  // Export evaluation of simple box constraints
318  //
319  evaluateConstraints.setup("evaluateConstraints");
320  if( hardcodeConstraintValues == YES ) {
321  evaluateConstraints.addVariable( evLbXValues );
322  evaluateConstraints.addVariable( evUbXValues );
323  evaluateConstraints.addVariable( evLbUValues );
324  evaluateConstraints.addVariable( evUbUValues );
325  }
326  else {
327  lbValues.setup("lbValues", 1, lbXValues.getDim()+lbUValues.getDim(), REAL, ACADO_VARIABLES);
328  lbValues.setDoc( "Lower bounds values." );
329  ubValues.setup("ubValues", 1, ubXValues.getDim()+ubUValues.getDim(), REAL, ACADO_VARIABLES);
330  ubValues.setDoc( "Upper bounds values." );
331 
332  for( uint i = 0; i < getNumberOfBlocks(); i++ ) {
333  for( uint j = 0; j < NX; j++ ) {
334  initialize.addStatement(lbValues.getCol(i * getNumBlockVariables() + j) == lbXValues(i * NX + j));
335  initialize.addStatement(ubValues.getCol(i * getNumBlockVariables() + j) == ubXValues(i * NX + j));
336  }
337  for( uint j = 0; j < getBlockSize()*NU; j++ ) {
338  initialize.addStatement(lbValues.getCol(i * getNumBlockVariables() + NX + j) == lbUValues(i * getBlockSize()*NU + j));
339  initialize.addStatement(ubValues.getCol(i * getNumBlockVariables() + NX + j) == ubUValues(i * getBlockSize()*NU + j));
340  }
341  }
342  for( uint j = 0; j < NX; j++ ) {
343  initialize.addStatement(lbValues.getCol(getNumberOfBlocks()*getNumBlockVariables() + j) == lbXValues(getNumberOfBlocks() * NX + j));
344  initialize.addStatement(ubValues.getCol(getNumberOfBlocks()*getNumBlockVariables() + j) == ubXValues(getNumberOfBlocks() * NX + j));
345  }
346  }
347 
348  if (initialStateFixed() == true)
349  {
350  for (unsigned i = 0; i < getBlockSize(); ++i) {
351  if( hardcodeConstraintValues == YES ) {
352  evaluateConstraints.addStatement( qpLb0.getCols(NX + i*NU, NX + (i+1)*NU) == evLbUValues.getTranspose().getCols(i*NU, (i+1)*NU) - u.getRow( i ) );
353  evaluateConstraints.addStatement( qpUb0.getCols(NX + i*NU, NX + (i+1)*NU) == evUbUValues.getTranspose().getCols(i*NU, (i+1)*NU) - u.getRow( i ) );
354  }
355  else {
356  evaluateConstraints.addStatement( qpLb0.getCols(NX + i*NU, NX + (i+1)*NU) == lbValues.getCols(NX + i*NU, NX + (i+1)*NU) - u.getRow( i ) );
357  evaluateConstraints.addStatement( qpUb0.getCols(NX + i*NU, NX + (i+1)*NU) == ubValues.getCols(NX + i*NU, NX + (i+1)*NU) - u.getRow( i ) );
358  }
359  }
362  }
363  uint firstBlock = (initialStateFixed() == true) ? 1 : 0;
364 
365  ExportIndex iBlock( "iBlock" );
366  ExportIndex uInd( "uInd" ), offset1( "offset1" ), offset2( "offset2" );
367  evaluateConstraints.addIndex( iBlock );
369  evaluateConstraints.addIndex( offset1 );
370  if( hardcodeConstraintValues == YES ) evaluateConstraints.addIndex( offset2 );
371  ExportForLoop blockLoop(iBlock, firstBlock, getNumberOfBlocks());
372  ExportForLoop uLoop(uInd, 0, getBlockSize());
373 
374  if( hardcodeConstraintValues == YES ) {
375  blockLoop.addStatement(
376  lb.getRows(iBlock*getNumBlockVariables(), iBlock*getNumBlockVariables()+NX) ==
377  evLbXValues.getRows(iBlock*NX, (iBlock + 1) * NX) - x.getRow( iBlock*getBlockSize() ).getTranspose()
378  );
379  blockLoop.addStatement(
380  ub.getRows(iBlock*getNumBlockVariables(), iBlock*getNumBlockVariables()+NX) ==
381  evUbXValues.getRows(iBlock*NX, (iBlock + 1) * NX) - x.getRow( iBlock*getBlockSize() ).getTranspose()
382  );
383  }
384  else {
385  blockLoop.addStatement(
386  lb.getRows(iBlock*getNumBlockVariables(), iBlock*getNumBlockVariables()+NX) ==
388  );
389  blockLoop.addStatement(
390  ub.getRows(iBlock*getNumBlockVariables(), iBlock*getNumBlockVariables()+NX) ==
392  );
393  }
394 
395  uLoop.addStatement( offset1 == iBlock*getNumBlockVariables()+uInd*NU+NX );
396 
397  if( hardcodeConstraintValues == YES ) {
398  uLoop.addStatement( offset2 == iBlock*getBlockSize()*NU+uInd*NU );
399  uLoop.addStatement(
400  lb.getRows(offset1, offset1+NU) ==
401  evLbUValues.getRows(offset2, offset2+NU) - u.getRow( iBlock*getBlockSize()+uInd ).getTranspose()
402  );
403  uLoop.addStatement(
404  ub.getRows(offset1, offset1+NU) ==
405  evUbUValues.getRows(offset2, offset2+NU) - u.getRow( iBlock*getBlockSize()+uInd ).getTranspose()
406  );
407  }
408  else {
409  uLoop.addStatement(
410  lb.getRows(offset1, offset1+NU) ==
411  lbValues.getTranspose().getRows(offset1, offset1+NU) - u.getRow( iBlock*getBlockSize()+uInd ).getTranspose()
412  );
413  uLoop.addStatement(
414  ub.getRows(offset1, offset1+NU) ==
415  ubValues.getTranspose().getRows(offset1, offset1+NU) - u.getRow( iBlock*getBlockSize()+uInd ).getTranspose()
416  );
417  }
418 
419  blockLoop.addStatement( uLoop );
420  evaluateConstraints.addStatement( blockLoop );
422 
423  if( hardcodeConstraintValues == YES ) {
426  evLbXValues.getRows(getNumberOfBlocks()*NX, (getNumberOfBlocks() + 1) * NX) - x.getRow( N ).getTranspose()
427  );
430  evUbXValues.getRows(getNumberOfBlocks()*NX, (getNumberOfBlocks() + 1) * NX) - x.getRow( N ).getTranspose()
431  );
432  }
433  else {
437  );
441  );
442  }
444 
446  //
447  // Setup evaluation of path and point constraints
448  //
450 
451  // TODO
452 
453 
454  return SUCCESSFUL_RETURN;
455 }
456 
458 {
459  condensePrep.setup("condensePrep", blockI);
460 
462  //
463  // Setup local memory for preparation phase: T1, T2, W1, W2
464  //
466 
467  // TODO
468 
470  //
471  // Compute Hessian block H00, H10 and C
472  //
474 
475  if (performFullCondensing() == false)
476  {
477  LOG( LVL_DEBUG ) << "Setup condensing: H00, H10 and C" << endl;
478 
479  if( getBlockSize() > 1 ) {
480  T1.setup("T1", NX, NX, REAL, ACADO_WORKSPACE);
481  T2.setup("T2", NX, NX, REAL, ACADO_WORKSPACE);
482  }
483 
485  for (unsigned row = 1; row < getBlockSize(); ++row)
487  multGxGx, evGx.getAddress((blockI*getBlockSize()+row)*NX), C.getAddress((row - 1) * NX), C.getAddress(row * NX));
488 
489 
490  /* Algorithm for computation of H10 and H00
491 
492  T1 = Q_N * C_{N - 1}
493  for i = N - 1: 1
494  H_{i + 1, 0} = B_i^T * T1
495  H_{i + 1, 0} += S_i^T * C_{i - 1}
496 
497  T2 = A_i^T * T1
498  T1 = T2 + Q_i * C_{i - 1}
499 
500  H_{1, 0} = B_0^T * T1
501  H_{1, 0} += S_0^T
502  H_{0, 0} = Q_0 + A_0^T * T1
503 
504  */
505 
506  // H10 Block
507  condensePrep.addStatement( T1 == zeros<double>(NX,NX) ); // Because you never have a "terminal stage cost" for any of the blocks which are condensed!
508 
509  for (unsigned row = getBlockSize() - 1; row > 0; --row)
510  {
512 
513  if ((S1.isGiven() && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
514  {
515  ExportArgument S1Call = S1.isGiven() == false ? S1.getAddress((blockI*getBlockSize()+row)*NX) : S1;
517  }
518 
520 
521  ExportArgument Q1Call = Q1.isGiven() == true ? Q1 : Q1.getAddress((blockI*getBlockSize()+row)*NX);
522  condensePrep.addFunctionCall(macGxTGx, T2, Q1Call, C.getAddress((row - 1) * NX), T1);
523  }
524 
525  if( getBlockSize() > 1 ) {
527  }
528  if ((S1.isGiven() && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
529  {
531  H.getSubMatrix(NX, NX + NU, 0, NX) += S1.getSubMatrix(blockI*getBlockSize()*NX, blockI*getBlockSize()*NX+NX, 0, NU).getTranspose()
532  );
533  }
534 
535  // H00 Block
536  DMatrix mRegH00 = eye<double>( getNX() );
537  mRegH00 *= levenbergMarquardt;
538  ExportVariable Q1Var = Q1.isGiven() == true ? Q1 : Q1.getSubMatrix(blockI*getBlockSize()*NX, blockI*getBlockSize()*NX+NX, 0, NX);
539 
540  if( getBlockSize() > 1 ) {
541  condensePrep.addStatement( H.getSubMatrix(0, NX, 0, NX) == Q1Var + (evGx.getSubMatrix(blockI*getBlockSize()*NX, blockI*getBlockSize()*NX+NX, 0, NX).getTranspose() * T1) );
542  }
543  else {
544  condensePrep.addStatement( H.getSubMatrix(0, NX, 0, NX) == Q1Var );
545  }
546  condensePrep.addStatement( H.getSubMatrix(0, NX, 0, NX) += mRegH00 );
547  }
548 
550  //
551  // Compute Hessian block H11
552  //
554 
555  LOG( LVL_DEBUG ) << "Setup condensing: H11 and E" << endl;
556 
557  /*
558 
559  This one is only for the case where we have input constraints only
560 
561  // Create E and H
562 
563  for i = 0: N - 1
564  {
565  // Storage for E: (N x nx) x nu
566 
567  E_0 = B_i;
568  for k = 1: N - i - 1
569  E_k = A_{i + k} * E_{k - 1};
570 
571  // Two temporary matrices W1, W2 of size nx x nu
572 
573  W1 = Q_N^T * E_{N - i - 1};
574 
575  for k = N - 1: i + 1
576  {
577  H_{k, i} = B_k^T * W1;
578 
579  W2 = A_k^T * W1;
580  W1 = Q_k^T * E_{k - i - 1} + W2;
581  }
582  H_{i, i} = B_i^T * W1 + R_i^T
583  }
584 
585  Else, in general case:
586 
587  for i = 0: N - 1
588  {
589  // Storage for E: (N * (N + 1) / 2 x nx) x nu
590 
591  j = 1 / 2 * i * (2 * N - i + 1);
592 
593  E_j = B_i;
594  for k = 1: N - i - 1
595  E_{j + k} = A_{i + k} * E_{j + k - 1};
596 
597  // Two temporary matrices W1, W2 of size nx x nu
598 
599  W1 = Q_N^T * E_{j + N - i - 1};
600 
601  for k = N - 1: i + 1
602  {
603  H_{k, i} = B_k^T * W1;
604  H_{k, i} += S_k^T * E_{j + k - i - 1};
605 
606  W2 = A_k^T * W1;
607  W1 = Q_k^T * E_{j + k - i - 1} + W2;
608  }
609  H_{i, i} = B_i^T * W1 + R_i^T
610  }
611 
612  */
613 
614  if( getBlockSize() > 1 ) {
615  W1.setup("W1", NX, NU, REAL, ACADO_WORKSPACE);
616  W2.setup("W2", NX, NU, REAL, ACADO_WORKSPACE);
617  }
618 
619  if (getBlockSize() <= 15)
620  {
621  for (unsigned col = 0; col < getBlockSize(); ++col)
622  {
623  int offset = col * (2 * getBlockSize() - col + 1) / 2;
624 
625  condensePrep.addComment( "Column: " + toString( col ) );
627  moveGuE, evGu.getAddress((blockI*getBlockSize()+col) * NX), E.getAddress(offset * NX)
628  );
629  for (unsigned row = 1; row < getBlockSize() - col; ++row)
631  multGxGu,
632  evGx.getAddress((blockI*getBlockSize()+col + row) * NX),
633  E.getAddress((offset + row - 1) * NX), E.getAddress((offset + row) * NX)
634  );
636 
637  condensePrep.addStatement( W1 == zeros<double>(NX,NU) ); // Because you never have a "terminal stage cost" for any of the blocks which are condensed!
638 
639 
640  for (unsigned row = getBlockSize() - 1; col < row; --row)
641  {
643  multBTW1, evGu.getAddress((blockI*getBlockSize()+row) * NX), W1,
644  ExportIndex( row ), ExportIndex( col )
645  );
646 
647  if ((S1.isGiven() && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
648  {
649  ExportArgument S1Call = S1.isGiven() == false ? S1.getAddress((blockI*getBlockSize()+row) * NX) : S1;
650 
652  mac_S1T_E,
653  S1Call, E.getAddress((offset + row - col - 1) * NX),
654  ExportIndex( row ), ExportIndex( col )
655  );
656  }
657 
659  multGxTGu, evGx.getAddress((blockI*getBlockSize()+row) * NX), W1, W2
660  );
661 
662  ExportArgument Q1Call = Q1.isGiven() == true ? Q1 : Q1.getAddress((blockI*getBlockSize()+row) * NX);
664  macQEW2, Q1Call, E.getAddress((offset + row - col - 1) * NX), W2, W1
665  );
666  }
667 
668  if( getBlockSize() > 1 ) {
669  ExportArgument R1Call = R1.isGiven() == true ? R1 : R1.getAddress((blockI*getBlockSize()+col) * NU);
671  macBTW1_R1, R1Call, evGu.getAddress((blockI*getBlockSize()+col) * NX), W1,
672  ExportIndex( col ) );
673  }
674  else {
675  ExportVariable R1Var = R1.isGiven() == true ? R1 : R1.getRows((blockI*getBlockSize()) * NU, (blockI*getBlockSize()+1) * NU);
676  DMatrix mRegH11 = eye<double>( getNU() );
677  mRegH11 *= levenbergMarquardt;
678  condensePrep.addStatement( H.getSubMatrix(NX, NX+NU, NX, NX+NU) == R1Var + mRegH11 );
679  }
680 
681 
683  }
684  }
685  else
686  {
687  // Long horizons
688 
689  ExportIndex row, col, offset;
690  condensePrep.acquire( row ).acquire( col ).acquire( offset );
691 
692  ExportForLoop cLoop(col, 0, getBlockSize());
693  ExportForLoop fwdLoop(row, 1, getBlockSize() - col);
694  ExportForLoop adjLoop(row, getBlockSize() - 1, col, -1);
695 
696  cLoop.addStatement( offset == col * (2 * getBlockSize() + 1 - col) / 2 );
697  cLoop.addFunctionCall(
698  moveGuE, evGu.getAddress((blockI*getBlockSize()+col) * NX), E.getAddress(offset * NX)
699  );
700 
701  fwdLoop.addFunctionCall(
702  multGxGu,
703  evGx.getAddress((blockI*getBlockSize() + col + row) * NX),
704  E.getAddress((offset + row - 1) * NX), E.getAddress((offset + row) * NX)
705  );
706  cLoop.addStatement( fwdLoop );
707  cLoop.addLinebreak();
708 
709  cLoop.addStatement( W1 == zeros<double>(NX,NU) ); // Because you never have a "terminal stage cost" for any of the blocks which are condensed!
710 
711  adjLoop.addFunctionCall(
712  multBTW1, evGu.getAddress((blockI*getBlockSize() + row) * NX), W1,
713  row, col
714  );
715 
716  if ((S1.isGiven() && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
717  {
718  ExportArgument S1Call = S1.isGiven() == false ? S1.getAddress((blockI*getBlockSize() + row) * NX) : S1;
719 
720  adjLoop.addFunctionCall(
721  mac_S1T_E,
722  S1Call, E.getAddress((offset + row - col - 1) * NX),
723  row, col
724  );
725  }
726 
727  adjLoop.addFunctionCall(
728  multGxTGu, evGx.getAddress((blockI*getBlockSize() + row) * NX), W1, W2
729  );
730 
731  ExportArgument Q1Call = Q1.isGiven() == true ? Q1 : Q1.getAddress((blockI*getBlockSize() + row) * NX);
732  adjLoop.addFunctionCall(
733  macQEW2, Q1Call, E.getAddress((offset + row - col - 1) * NX), W2, W1
734  );
735 
736  cLoop.addStatement( adjLoop );
737 
738  ExportArgument R1Call = R1.isGiven() == true ? R1 : R1.getAddress((blockI*getBlockSize() + col) * NU);
739  cLoop.addFunctionCall(
740  macBTW1_R1, R1Call, evGu.getAddress((blockI*getBlockSize() + col) * NX), W1,
741  ExportIndex( col )
742  );
743 
744  condensePrep.addStatement( cLoop );
746 
747  condensePrep.release( row ).release( col ).release( offset );
748  }
749 
751 
752  LOG( LVL_DEBUG ) << "---> Copy H11 lower part" << endl;
753 
754  // Copy to H11 upper lower part to upper triangular part, TODO: do this together with the copy to qpH !!!
755  if (getBlockSize() <= 20)
756  {
757  for (unsigned ii = 0; ii < getBlockSize(); ++ii)
758  for(unsigned jj = 0; jj < ii; ++jj)
760  copyHTH, ExportIndex( jj ), ExportIndex( ii ));
761 
762  // Copy H10 to H01
763  if( performFullCondensing() == false) {
764  for (unsigned ii = 0; ii < getBlockSize(); ++ii)
766  }
767  }
768  else
769  {
770  ExportIndex ii, jj;
771 
772  condensePrep.acquire( ii );
773  condensePrep.acquire( jj );
774 
775  ExportForLoop eLoopI(ii, 0, getBlockSize());
776  ExportForLoop eLoopJ(jj, 0, ii);
777 
778  eLoopJ.addFunctionCall(copyHTH, jj, ii);
779  eLoopI.addStatement( eLoopJ );
780  condensePrep.addStatement( eLoopI );
781 
782  // Copy H10 to H01
783  if( performFullCondensing() == false) {
784  ExportForLoop eLoopK(ii, 0, getBlockSize());
785  eLoopK.addFunctionCall(copyHTH1, ii);
786  condensePrep.addStatement( eLoopK );
787  }
788 
789  condensePrep.release( ii );
790  condensePrep.release( jj );
791  }
793 
794  // Copy to qpH for qpDUNES:
796 
798  //
799  // Compute gradient components g0 and g1
800  //
802 
803  LOG( LVL_DEBUG ) << "Setup condensing: create Dx0, Dy and DyN" << endl;
804 
805  unsigned offset = performFullCondensing() == true ? 0 : NX;
806 
807  int variableObjS;
808  get(CG_USE_VARIABLE_WEIGHTING_MATRIX, variableObjS);
809 
810  // Compute RDy
811  for(unsigned run1 = 0; run1 < getBlockSize(); ++run1)
812  {
813  ExportArgument R2Call = R2.isGiven() == true ? R2 : R2.getAddress((blockI*getBlockSize()+run1) * NU, 0);
814  ExportArgument SluCall =
815  objSlu.isGiven() == true || variableObjS == false ? objSlu : objSlu.getAddress((blockI*getBlockSize()+run1) * NU, 0);
817  multRDy, R2Call, Dy.getAddress((blockI*getBlockSize()+run1) * NY, 0), SluCall, g.getAddress(blockI*getNumBlockVariables() + offset + run1 * NU, 0)
818  );
819  }
821 
822  // Compute QDy
823  for(unsigned run1 = 0; run1 < getBlockSize(); run1++ )
824  {
825  ExportArgument Q2Call = Q2.isGiven() == true ? Q2 : Q2.getAddress((blockI*getBlockSize()+run1) * NX);
826  ExportArgument SlxCall =
827  objSlx.isGiven() == true || variableObjS == false ? objSlx : objSlx.getAddress((blockI*getBlockSize()+run1) * NX, 0);
829  multQDy, Q2Call, Dy.getAddress((blockI*getBlockSize()+run1) * NY), SlxCall, QDy.getAddress(run1 * NX) );
830  }
832 
833  if (performFullCondensing() == false)
835 
836  /*
837  if partial condensing:
838  g0 = q_0
839 
840  for k = 0: N - 1
841  g1_k = r_k
842 
843  if partial condensing:
844  sbar_0 = 0;
845  else:
846  sbar_0 = Dx_0;
847 
848  sbar(1: N) = d;
849 
850  for k = 0: N - 1
851  sbar_{k + 1} += A_k sbar_k;
852 
853  w1 = Q_N^T * sbar_N + q_N;
854  for k = N - 1: 1
855  {
856  g1_k += B_k^T * w1;
857  g1_k += S_k^T * sbar_k;
858  w2 = A_k^T * w1 + q_k;
859  w1 = Q_k^T * sbar_k + w2;
860  }
861 
862  g1_0 += B_0^T * w1;
863  if partial condensing:
864  g_0 += A_0^T * w1
865  else:
866  g1_0 += S^0^T * x0;
867 
868  */
869 
870  if( getBlockSize() > 1 ) {
871  w1.setup("w1", NX, 1, REAL, ACADO_WORKSPACE);
872  w2.setup("w2", NX, 1, REAL, ACADO_WORKSPACE);
873  }
874 
875  sbar.setup("sbar", (getBlockSize()+1)*NX, 1, REAL, ACADO_WORKSPACE);
876 
877 // if( performFullCondensing() == true ) {
878 // condenseFdb.addStatement( sbar.getRows(0, NX) == Dx0 );
879 // }
880 // else {
881  condensePrep.addStatement( sbar.getRows(0, NX) == zeros<double>(NX,1) ); // Dx0 is now a variable as well !!
882 // }
883  condensePrep.addStatement( sbar.getRows(NX, (getBlockSize() + 1) * NX) == d.getRows(blockI*getBlockSize()*NX,(blockI+1)*getBlockSize()*NX) );
884 
885  for (unsigned i = 1; i < getBlockSize(); ++i)
887  macASbar, evGx.getAddress((blockI*getBlockSize()+i) * NX), sbar.getAddress(i * NX), sbar.getAddress((i + 1) * NX)
888  );
890 
891  condensePrep.addStatement( w1 == zeros<double>(NX,1) );
892  for (unsigned i = getBlockSize() - 1; 0 < i; --i)
893  {
895  macBTw1, evGu.getAddress((blockI*getBlockSize()+i) * NX), w1, g.getAddress(blockI*getNumBlockVariables() + offset + i * NU)
896  );
897 
898  if ((S1.isGiven() == true && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
899  {
900  ExportArgument S1Call = S1.isGiven() == false ? S1.getAddress((blockI*getBlockSize()+i) * NX) : S1;
902  }
903 
905  // TODO Check indexing for QDy
906  macATw1QDy, evGx.getAddress((blockI*getBlockSize()+i) * NX), w1, QDy.getAddress(i * NX), w2
907  );
908 
909  ExportArgument Q1Call = Q1.isGiven() == true ? Q1 : Q1.getAddress((blockI*getBlockSize()+i) * NX);
911  macQSbarW2, Q1Call, sbar.getAddress(i * NX), w2, w1);
912  }
913  if( getBlockSize() > 1 ) {
915  macBTw1, evGu.getAddress( blockI*getBlockSize()*NX ), w1, g.getAddress( blockI*getNumBlockVariables() + offset ) );
916 // if( performFullCondensing() == true ) {
917 // if ((S1.isGiven() == true && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
918 // {
919 // condenseFdb.addFunctionCall(macS1TSbar, S1, sbar.getAddress(0), g);
920 // }
921 // }
922 // else {
924 // }
925  }
927 
929  //
930  // Evaluation of the system dynamics equality constraints
931  //
933 
934  //
935  // Set QP C matrix
936  //
937 
939  condensePrep.addStatement( qpC.getSubMatrix(blockI*NX,(blockI+1)*NX,0,NX) == C.getRows( (getBlockSize()-1)*NX, getBlockSize()*NX ) );
940  for( unsigned i = 0; i < getBlockSize(); i++ ) {
941  unsigned offset2 = i * (2 * getBlockSize() - i + 1) / 2;
942  condensePrep.addStatement( qpC.getSubMatrix(blockI*NX,(blockI+1)*NX,NX+i*NU,NX+(i+1)*NU) == E.getRows((offset2 + getBlockSize()-i-1)*NX,(offset2 + getBlockSize()-i)*NX) );
943  }
945 
946 
948  //
949  // Expansion routine
950  //
952 
953  /*
954 
955  // Step expansion, assuming that u_k is already updated
956 
957  Ds_0 = Dx_0;
958  Ds_{1: N} = d;
959 
960  for i = 0: N - 1
961  {
962  Ds_{k + 1} += A_k * Ds_k; // Reuse multABarD
963  Ds_{k + 1} += B_k * Du_k;
964  s_{k + 1} += Ds_{k + 1};
965  }
966 
967  */
968 
969  LOG( LVL_DEBUG ) << "Setup condensing: create expand routine" << endl;
970 
971  expand.setup( "expand", blockI );
972 
973 // if (performFullCondensing() == true)
974 // {
975 // expand.addStatement( u.makeRowVector() += xVars.getTranspose() );
976 // }
977 // else
978 // {
979  for (unsigned i = 0; i < getBlockSize(); ++i ) {
980  expand.addStatement( (u.getRow(blockI*getBlockSize()+i)).getTranspose() += xVars.getRows(blockI*getNumBlockVariables()+NX+i*NU, blockI*getNumBlockVariables()+NX+(i+1)*NU) );
981  }
982 // }
983 
984 // if( performFullCondensing() == true ) {
985 // expand.addStatement( sbar.getRows(0, NX) == Dx0 );
986 // }
987 // else {
989  expand.addStatement( (x.getRow(blockI*getBlockSize())).getTranspose() += sbar.getRows(0, NX) );
990 // }
991  if( getBlockSize() > 1 ) {
992  expand.addStatement( sbar.getRows(NX, getBlockSize()*NX) == d.getRows(blockI*getBlockSize()*NX,(blockI+1)*getBlockSize()*NX-NX) );
993  }
994 
995  for (unsigned row = 0; row < getBlockSize()-1; ++row ) {
997  expansionStep, evGx.getAddress((blockI*getBlockSize()+row) * NX), evGu.getAddress((blockI*getBlockSize()+row) * NX),
999  sbar.getAddress((row + 1) * NX)
1000  );
1001  expand.addStatement( (x.getRow(blockI*getBlockSize()+row+1)).getTranspose() += sbar.getRows((row+1)*NX, (row+2)*NX) );
1002  }
1003 
1004  // !! Calculation of multipliers: !!
1005  int hessianApproximation;
1006  get( HESSIAN_APPROXIMATION, hessianApproximation );
1007  bool secondOrder = ((HessianApproximationMode)hessianApproximation == EXACT_HESSIAN);
1008  if( secondOrder ) {
1010  // mu_N = lambda_N + q_N + Q_N^T * Ds_N --> wrong in Joel's paper !!
1011  // for i = N - 1: 1
1012  // mu_k = Q_k^T * Ds_k + A_k^T * mu_{k + 1} + S_k * Du_k + q_k
1013 
1014  for (uint j = 0; j < NX; j++ ) {
1015  uint item = N*NX+j;
1016  uint IdxF = std::find(xBoundsIdx.begin(), xBoundsIdx.end(), item) - xBoundsIdx.begin();
1017  if( IdxF != xBoundsIdx.size() ) { // INDEX FOUND
1018  expand.addStatement( mu.getSubMatrix(N-1,N,j,j+1) == yVars.getRow(getNumQPvars()+IdxF) );
1019  }
1020  else { // INDEX NOT FOUND
1021  expand.addStatement( mu.getSubMatrix(N-1,N,j,j+1) == 0.0 );
1022  }
1023  }
1024  expand.addStatement( mu.getRow(N-1) += sbar.getRows(N*NX,(N+1)*NX).getTranspose()*QN1 );
1025  expand.addStatement( mu.getRow(N-1) += QDy.getRows(N*NX,(N+1)*NX).getTranspose() );
1026  for (int i = N - 1; i >= 1; i--) {
1027  for (uint j = 0; j < NX; j++ ) {
1028  uint item = i*NX+j;
1029  uint IdxF = std::find(xBoundsIdx.begin(), xBoundsIdx.end(), item) - xBoundsIdx.begin();
1030  if( IdxF != xBoundsIdx.size() ) { // INDEX FOUND
1031  expand.addStatement( mu.getSubMatrix(i-1,i,j,j+1) == yVars.getRow(getNumQPvars()+IdxF) );
1032  }
1033  else { // INDEX NOT FOUND
1034  expand.addStatement( mu.getSubMatrix(i-1,i,j,j+1) == 0.0 );
1035  }
1036  }
1038  expansionStep2, QDy.getAddress(i*NX), Q1.getAddress(i * NX), sbar.getAddress(i*NX),
1039  S1.getAddress(i * NX), xVars.getAddress(offset + i * NU), evGx.getAddress(i * NX),
1040  mu.getAddress(i-1), mu.getAddress(i) );
1041  }
1042  }
1043 
1044  return SUCCESSFUL_RETURN;
1045 }
1046 
1048 {
1050 
1051  blockI = ExportIndex( "blockI" );
1052 
1055 
1056  if (performFullCondensing() == false || getNumComplexConstraints() > 0)
1057  {
1059  }
1060  E.setup("E", getBlockSize() * (getBlockSize() + 1) / 2 * NX, NU, REAL, ACADO_WORKSPACE);
1061 
1062  QDy.setup ("QDy", getBlockSize()*NX, 1, REAL, ACADO_WORKSPACE); // just for one block now
1063 
1066  g.setup("g", getNumQPvars(), 1, REAL, ACADO_WORKSPACE);
1068 
1069  lb.setup("lb", getNumQPvars(), 1, REAL, ACADO_WORKSPACE);
1070  ub.setup("ub", getNumQPvars(), 1, REAL, ACADO_WORKSPACE);
1071 
1074 
1076  yVars.setup("",0,0); // NOT USED
1077  qpLambda.setup("qpLambda", getNumberOfBlocks()*NX, 1, REAL, ACADO_WORKSPACE);
1079 
1080  return SUCCESSFUL_RETURN;
1081 }
1082 
1083 
1085 {
1087 }
1088 
1090 {
1091  int blockSize;
1092  get(CONDENSING_BLOCK_SIZE, blockSize);
1093 
1094  return blockSize;
1095 }
1096 
1098 {
1099  uint blockSize = getBlockSize();
1100  uint numBlocks = acadoRound(((double)N)/((double)blockSize));
1101 
1102  return numBlocks;
1103 }
1104 
1106 {
1107  return getBlockSize()*NU + NX;
1108 }
1109 
1111 {
1112  unsigned numStateBoundsBlock = 0; // NOTE: it is expected here that all blocks have the same state bounds !
1113  unsigned index = 0;
1114 // for (unsigned i = 0; i < getNumberOfBlocks(); ++i) {
1115  while( index < xBoundsIdx.size() && xBoundsIdx[index] < getBlockSize()*NX ) {
1116  if( xBoundsIdx[index] >= NX ) {
1117  numStateBoundsBlock += 1;
1118  }
1119  index += 1;
1120  }
1121 // }
1122  return numStateBoundsBlock;
1123 }
1124 
1125 
virtual returnValue setupMultiplicationRoutines()
#define LOG(level)
Just define a handy macro for getting the logger.
Lowest level, the debug level.
HessianApproximationMode
virtual unsigned getNumStateBoundsPerBlock() const
virtual returnValue setupEvaluation()=0
ExportVariable getRow(const ExportIndex &idx) const
ExportVariable objSlu
const double INFTY
ExportVariable getTranspose() const
virtual returnValue setupObjectiveEvaluation(void)
bool initialStateFixed() const
VariablesGrid xBounds
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.
DVector getUpperBounds(uint pointIdx) const
ExportGaussNewtonBlockCN2(UserInteraction *_userInteraction=0, const std::string &_commonHeaderName="")
returnValue addComment(const std::string &_comment)
BEGIN_NAMESPACE_ACADO typedef unsigned int uint
Definition: acado_types.hpp:42
virtual returnValue getDataDeclarations(ExportStatementBlock &declarations, ExportStruct dataStruct=ACADO_ANY) const
const DMatrix & getGivenMatrix() const
Allows to export code of a for-loop.
string toString(T const &value)
VariablesGrid uBounds
ExportVariable getElement(const ExportIndex &rowIdx, const ExportIndex &colIdx) const
ExportVariable objSlx
#define CLOSE_NAMESPACE_ACADO
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.
virtual returnValue setupConstraintsEvaluation(void)
Defines a matrix-valued variable that can be passed as argument to exported functions.
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)
#define YES
Definition: acado_types.hpp:51
virtual returnValue setDoc(const std::string &_doc)
virtual returnValue setupInitialization()
ExportStruct
ExportVariable getCols(const ExportIndex &idx1, const ExportIndex &idx2) const
unsigned getDim() const
Definition: vector.hpp:172
int acadoRound(double x)
bool performsSingleShooting() const
virtual returnValue setupSimulation(void)
ExportVariable QN1
Encapsulates all user interaction for setting options, logging data and plotting results.
An OCP solver based on the N^2 condensing algorithm.
returnValue addStatement(const ExportStatement &_statement)
returnValue addLinebreak(uint num=1)
#define ASSERT(x)
GenericVector & append(const GenericVector &_arg)
Definition: vector.cpp:42
virtual ExportFunction & acquire(ExportIndex &obj)
RowXpr row(Index i)
Definition: BlockMethods.h:725
ExportFunction & addVariable(const ExportVariable &_var)
void setAll(const T &_value)
Definition: vector.hpp:160
ExportVariable evGu
virtual returnValue getFunctionDeclarations(ExportStatementBlock &declarations) 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)
unsigned getNumComplexConstraints(void)
DVector getLowerBounds(uint pointIdx) const
#define BEGIN_NAMESPACE_ACADO
ColXpr col(Index i)
Definition: BlockMethods.h:708
virtual returnValue setupVariables()
std::vector< unsigned > xBoundsIdx
virtual returnValue getFunctionDeclarations(ExportStatementBlock &declarations) const
uint getNU() const
Allows to export code for a block of statements.
ExportFunction initialize
ExportArgument getAddress(const ExportIndex &_rowIdx, const ExportIndex &_colIdx=emptyConstExportIndex) const
ExportVariable getCol(const ExportIndex &idx) const
ExportFunction & addIndex(const ExportIndex &_index)
#define ACADOERROR(retval)
Defines a matrix-valued variable to be used for exporting code.
virtual returnValue getDataDeclarations(ExportStatementBlock &declarations, ExportStruct dataStruct=ACADO_ANY) const
#define ACADOERRORTEXT(retval, text)
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


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