ocp_export.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 
39 
42 
43 #include <acado/code_generation/templates/templates.hpp>
44 
46 
48 #include <acado/ocp/ocp.hpp>
49 
50 using namespace std;
51 
53 
55 {
57 }
58 
59 
61  ) : ExportModule( )
62 {
63  ocp = _ocp;
64 
66 }
67 
68 returnValue OCPexport::exportCode( const std::string& dirName,
69  const std::string& _realString,
70  const std::string& _intString,
71  int _precision
72  )
73 {
74  int qpSolver;
75  get(QP_SOLVER, qpSolver);
76 
77  string moduleName, modulePrefix;
78  get(CG_MODULE_NAME, moduleName);
79  get(CG_MODULE_PREFIX, modulePrefix);
80 
81  ExportDataInternal::fcnPrefix = moduleName;
82  ExportStatement::fcnPrefix = moduleName;
83  ExportStatement::varPrefix = modulePrefix;
84 
85  acadoPrintCopyrightNotice( "Code Generation Tool" );
86 
87  //
88  // Create the export folders
89  //
90 
91  set(CG_EXPORT_FOLDER_NAME, dirName);
92 
93  returnValue dirStatus = acadoCreateFolder( dirName );
94  if (dirStatus != SUCCESSFUL_RETURN)
95  return dirStatus;
96 
97  //
98  // Setup the export structures
99  //
100  returnValue setupStatus = setup( );
101  if ( setupStatus != SUCCESSFUL_RETURN )
102  return setupStatus;
103 
104  //
105  // Export common header
106  //
107  if (exportAcadoHeader(dirName, commonHeaderName, _realString, _intString, _precision)
108  != SUCCESSFUL_RETURN )
110 
111  //
112  // Export integrator
113  //
114  if (integrator != 0)
115  {
116  ExportFile integratorFile(dirName + "/" + moduleName + "_integrator.c",
117  commonHeaderName, _realString, _intString, _precision);
118 
119  integrator->getCode( integratorFile );
120 
121  if (integratorFile.exportCode( ) != SUCCESSFUL_RETURN)
123  }
124  else
126 
127  //
128  // Export solver
129  //
130  if( solver != 0 )
131  {
132  ExportFile solverFile(dirName + "/" + moduleName + "_solver.c",
133  commonHeaderName, _realString, _intString, _precision);
134 
135  solver->getCode( solverFile );
136 
137  if ( solverFile.exportCode( ) != SUCCESSFUL_RETURN )
139  }
140  else
142 
143  LOG( LVL_DEBUG ) << "Export templates" << endl;
144 
145  //
146  // Export auxiliary functions, always
147  //
148  std::string str;
149 
151  dirName + string("/") + moduleName + "_auxiliary_functions.h",
152  dirName + string("/") + moduleName + "_auxiliary_functions.c",
153  moduleName,
154  modulePrefix
155  );
156  eaf.configure();
157  eaf.exportCode();
158 
159  //
160  // Export Makefile
161  //
162  int generateMakeFile;
163  get(GENERATE_MAKE_FILE, generateMakeFile);
164  int hessianApproximation;
165  get( HESSIAN_APPROXIMATION, hessianApproximation );
166  int hessianRegularization;
167  get( HESSIAN_REGULARIZATION, hessianRegularization );
168 
169  if ( (bool)generateMakeFile == true )
170  {
171  ExportTemplatedFile makefile;
172  makefile.dictionary[ "@MODULE_NAME@" ] = moduleName;
173  makefile.dictionary[ "@MODULE_PREFIX@" ] = modulePrefix;
174  str = dirName + "/Makefile";
175 
176  switch ( (QPSolverName)qpSolver )
177  {
178  case QP_QPOASES:
179  if ( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN ) {
180  //acadoCopyTemplateFile(MAKEFILE_EH_QPOASES, str, "#", true);
181  makefile.setup( MAKEFILE_EH_QPOASES,str,"","real_t","int",16,"#" );
182  }
183  else {
184  //acadoCopyTemplateFile(MAKEFILE_QPOASES, str, "#", true);
185  makefile.setup( MAKEFILE_QPOASES,str,"","real_t","int",16,"#" );
186  }
187  makefile.configure();
188  makefile.exportCode();
189  break;
190 
191  case QP_QPOASES3:
192  if ( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN ) {
193  //acadoCopyTemplateFile(MAKEFILE_EH_QPOASES3, str, "#", true);
194  makefile.setup( MAKEFILE_EH_QPOASES3,str,"","real_t","int",16,"#" );
195  }
196  else {
197  //acadoCopyTemplateFile(MAKEFILE_QPOASES3, str, "#", true);
198  makefile.setup( MAKEFILE_QPOASES3,str,"","real_t","int",16,"#" );
199  }
200  makefile.configure();
201  makefile.exportCode();
202  break;
203 
204  case QP_FORCES:
205  //acadoCopyTemplateFile(MAKEFILE_FORCES, str, "#", true);
206  makefile.setup( MAKEFILE_FORCES,str,"","real_t","int",16,"#" );
207  makefile.configure();
208  makefile.exportCode();
209  break;
210 
211  case QP_QPDUNES:
212  if ( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN ) {
213  //acadoCopyTemplateFile(MAKEFILE_EH_QPDUNES, str, "#", true);
214  makefile.setup( MAKEFILE_EH_QPDUNES,str,"","real_t","int",16,"#" );
215  }
216  else {
217  //acadoCopyTemplateFile(MAKEFILE_QPDUNES, str, "#", true);
218  makefile.setup( MAKEFILE_QPDUNES,str,"","real_t","int",16,"#" );
219  }
220  makefile.configure();
221  makefile.exportCode();
222  break;
223 
224  case QP_HPMPC:
225  //acadoCopyTemplateFile(MAKEFILE_HPMPC, str, "#", true);
226  makefile.setup( MAKEFILE_HPMPC,str,"","real_t","int",16,"#" );
227  makefile.configure();
228  makefile.exportCode();
229  break;
230 
231  default:
232  ACADOWARNINGTEXT(RET_NOT_IMPLEMENTED_YET, "Makefile is not yet available.");
233  break;
234  }
235  }
236 
237  //
238  // Export a dummy test file
239  //
240  int generateTestFile;
241  get(GENERATE_TEST_FILE, generateTestFile);
242  string testFileName = dirName + "/test.c";
243  if ((bool) generateTestFile == true)
244  {
245  //acadoCopyTemplateFile(DUMMY_TEST_FILE, testFileName, "", true);
246  ExportTemplatedFile testFile;
247  testFile.dictionary[ "@MODULE_NAME@" ] = moduleName;
248  testFile.dictionary[ "@MODULE_PREFIX@" ] = modulePrefix;
249 
250  testFile.setup( DUMMY_TEST_FILE,testFileName );
251  testFile.configure();
252  testFile.exportCode();
253  }
254 
255  //
256  // Generate MATLAB MEX interface
257  //
258  int qpSolution;
259  get(SPARSE_QP_SOLUTION, qpSolution);
260  int generateMexInterface;
261  get(GENERATE_MATLAB_INTERFACE, generateMexInterface);
262  if ( (bool)generateMexInterface == true )
263  {
264  ExportTemplatedFile mexInterface;
265  mexInterface.dictionary[ "@MODULE_NAME@" ] = moduleName;
266  mexInterface.dictionary[ "@MODULE_PREFIX@" ] = modulePrefix;
267  str = dirName + "/" + moduleName + "_solver_mex.c";
268 
269  if ( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN ) {
270  //acadoCopyTemplateFile(EH_SOLVER_MEX, str, "", true);
271  mexInterface.setup( EH_SOLVER_MEX,str );
272  mexInterface.configure();
273  mexInterface.exportCode();
274  }
275  else {
276  //acadoCopyTemplateFile(SOLVER_MEX, str, "", true);
277  mexInterface.setup( SOLVER_MEX,str );
278  mexInterface.configure();
279  mexInterface.exportCode();
280  }
281 
282  ExportTemplatedFile mexInterfaceMake;
283  mexInterfaceMake.dictionary[ "@MODULE_NAME@" ] = moduleName;
284  mexInterfaceMake.dictionary[ "@MODULE_PREFIX@" ] = modulePrefix;
285  str = dirName + "/make_" + moduleName + "_solver.m";
286 
287  switch ( (QPSolverName)qpSolver )
288  {
289  case QP_QPOASES:
290  if ( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN ) {
291  //acadoCopyTemplateFile(MAKE_MEX_EH_QPOASES, str, "%", true);
292  mexInterfaceMake.setup( MAKE_MEX_EH_QPOASES,str, "","real_t","int",16,"%" );
293  mexInterfaceMake.configure();
294  mexInterfaceMake.exportCode();
295  }
296  else {
297  //acadoCopyTemplateFile(MAKE_MEX_QPOASES, str, "%", true);
298  mexInterfaceMake.setup( MAKE_MEX_QPOASES,str, "","real_t","int",16,"%" );
299  mexInterfaceMake.configure();
300  mexInterfaceMake.exportCode();
301  }
302  break;
303 
304  case QP_QPOASES3:
305  if ( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN ) {
306  //acadoCopyTemplateFile(MAKE_MEX_EH_QPOASES3, str, "%", true);
307  mexInterfaceMake.setup( MAKE_MEX_EH_QPOASES3,str, "","real_t","int",16,"%" );
308  mexInterfaceMake.configure();
309  mexInterfaceMake.exportCode();
310  }
311  else {
312  //acadoCopyTemplateFile(MAKE_MEX_QPOASES3, str, "%", true);
313  mexInterfaceMake.setup( MAKE_MEX_QPOASES3,str, "","real_t","int",16,"%" );
314  mexInterfaceMake.configure();
315  mexInterfaceMake.exportCode();
316  }
317  break;
318 
319  case QP_FORCES:
320  //acadoCopyTemplateFile(MAKE_MEX_FORCES, str, "%", true);
321  mexInterfaceMake.setup( MAKE_MEX_FORCES,str, "","real_t","int",16,"%" );
322  mexInterfaceMake.configure();
323  mexInterfaceMake.exportCode();
324  break;
325 
326  case QP_QPDUNES:
327  if ( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN ) {
328  //acadoCopyTemplateFile(MAKE_MEX_EH_QPDUNES, str, "%", true);
329  mexInterfaceMake.setup( MAKE_MEX_EH_QPDUNES,str, "","real_t","int",16,"%" );
330  mexInterfaceMake.configure();
331  mexInterfaceMake.exportCode();
332  }
333  else if ( (SparseQPsolutionMethods)qpSolution == BLOCK_CONDENSING_N2 ) {
334  acadoCopyTemplateFile(MAKE_MEX_BLOCK_QPDUNES, str, "%", true);
335  }
336  else {
337  //acadoCopyTemplateFile(MAKE_MEX_QPDUNES, str, "%", true);
338  mexInterfaceMake.setup( MAKE_MEX_QPDUNES,str, "","real_t","int",16,"%" );
339  mexInterfaceMake.configure();
340  mexInterfaceMake.exportCode();
341  }
342  break;
343 
344 
345  case QP_HPMPC:
346  if ( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN ) {
347  //acadoCopyTemplateFile(MAKE_MEX_EH_QPDUNES, str, "%", true);
348  ACADOWARNINGTEXT(RET_NOT_IMPLEMENTED_YET, "MEX interface for HMPC with exact Hessians is not yet available.");
349  }
350  else {
351  //acadoCopyTemplateFile(MAKE_MEX_QPDUNES, str, "%", true);
352  mexInterfaceMake.setup( MAKE_MEX_HPMPC,str, "","real_t","int",16,"%" );
353  mexInterfaceMake.configure();
354  mexInterfaceMake.exportCode();
355  }
356  break;
357 
358  case QP_GENERIC:
359  break;
360  default:
361  ACADOWARNINGTEXT(RET_NOT_IMPLEMENTED_YET, "MEX interface is not yet available.");
362  break;
363  }
364  }
365 
366  //
367  // Generate MATLAB Simulink interface
368  //
369  int generateSimulinkInterface;
370  get(GENERATE_SIMULINK_INTERFACE, generateSimulinkInterface);
371  if ((bool) generateSimulinkInterface == true)
372  {
373  if (!((QPSolverName)qpSolver == QP_QPOASES || (QPSolverName)qpSolver == QP_QPOASES3 || (QPSolverName)qpSolver == QP_QPDUNES|| (QPSolverName)qpSolver == QP_HPMPC))
375  "At the moment, Simulink interface is available only with qpOASES, qpOASES3 and qpDUNES based OCP solvers.");
376  else
377  {
378  string makefileName = dirName + "/make_" + moduleName + "_solver_sfunction.m";
379  string wrapperHeaderName = dirName + "/" + moduleName + "_solver_sfunction.h";
380  string wrapperSourceName = dirName + "/" + moduleName + "_solver_sfunction.c";
381  string qpSolverString;
382 
383  if ((QPSolverName)qpSolver == QP_QPOASES)
384  qpSolverString = "QPOASES";
385  else if ((QPSolverName)qpSolver == QP_QPOASES3)
386  qpSolverString = "QPOASES3";
387  else if ((QPSolverName)qpSolver == QP_QPDUNES)
388  qpSolverString = "QPDUNES";
389  else
390  qpSolverString = "HPMPC";
391 
392  // Get options
393  int useSinglePrecision;
394  get(USE_SINGLE_PRECISION, useSinglePrecision);
395 
396  ExportSimulinkInterface esi(makefileName, wrapperHeaderName, wrapperSourceName, moduleName, modulePrefix);
397  if( useSinglePrecision ) {
398  esi = ExportSimulinkInterface(makefileName, wrapperHeaderName, wrapperSourceName, moduleName, modulePrefix, "", "single");
399  }
400 
401  int hardcodeConstraintValues;
402  get(CG_HARDCODE_CONSTRAINT_VALUES, hardcodeConstraintValues);
403  if ((bool)hardcodeConstraintValues == false)
405 
406  int fixInitialState;
407  get(FIX_INITIAL_STATE, fixInitialState);
408  int useAC;
409  get(CG_USE_ARRIVAL_COST, useAC);
410  int covCalc;
411  get(CG_COMPUTE_COVARIANCE_MATRIX, covCalc);
412 
413  // Configure templates
414  esi.configure(
415  ocp.getN(), ocp.getNX(), ocp.getNDX(), ocp.getNXA(), ocp.getNU(), ocp.getNOD(),
416  solver->getNY(), solver->getNYN(),
417  (bool)fixInitialState,
418  (unsigned)solver->weightingMatricesType(),
419  (bool)hardcodeConstraintValues,
420  (bool)useAC,
421  (bool)covCalc,
422  qpSolverString);
423 
424  esi.exportCode();
425  }
426 
427 }
428  //
429  // Generate Symmetric EVD code
430  //
431  if ( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN && (HessianRegularizationMode)hessianRegularization == BLOCK_REG ) {
432 // LOG( LVL_DEBUG ) << "Exporting Hessian regularization code... " << endl;
434  dirName + string("/") + moduleName + "_hessian_regularization.c",
435  moduleName
436  );
437  evd.configure( ocp.getNX()+ocp.getNU(), 1e-12 );
438  if ( evd.exportCode() != SUCCESSFUL_RETURN )
440  }
441  else if( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN && (HessianRegularizationMode)hessianRegularization == CONDENSED_REG ) {
442  // LOG( LVL_DEBUG ) << "Exporting Hessian regularization code... " << endl;
444  dirName + string("/") + moduleName + "_hessian_regularization.c",
445  moduleName
446  );
447  int fixInitialState;
448  get(FIX_INITIAL_STATE, fixInitialState);
449  if( (bool)fixInitialState == 1 ) {
450  evd.configure( ocp.getN()*ocp.getNU(), 1e-12 );
451  }
452  else {
453  evd.configure( ocp.getNX()+ocp.getN()*ocp.getNU(), 1e-12 );
454  }
455  if ( evd.exportCode() != SUCCESSFUL_RETURN )
457  }
458 
459  return SUCCESSFUL_RETURN;
460 }
461 
462 
463 
465 {
466  if (getStatus() != BS_READY)
467  return SUCCESSFUL_RETURN;
468 
469  LOG( LVL_INFO ) << "ACADO Code Generation Tool:" << endl
470  << "\t* Number of QP variables: " << solver->getNumQPvars( ) << endl
471  << "\t* Number of path and point constraints: " << solver->getNumComplexConstraints() << endl;
472 
473  return SUCCESSFUL_RETURN;
474 }
475 
477 {
478  // Nothing to do as object is up-to-date
479  if ( getStatus() == BS_READY )
480  return SUCCESSFUL_RETURN;
481 
482  // Consistency check
483  returnValue returnvalue = checkConsistency( );
484  if ( returnvalue != SUCCESSFUL_RETURN )
485  return returnvalue;
486 
487  //
488  // Set common header name
489  //
490  string moduleName;
491  get(CG_MODULE_NAME, moduleName);
492  commonHeaderName = moduleName + "_common.h";
493 
494  //
495  // Prepare integrator export
496  //
497  int numSteps;
498  get(NUM_INTEGRATOR_STEPS, numSteps);
499 
500  int integratorType;
501  get(INTEGRATOR_TYPE, integratorType);
502 
504  IntegratorExportFactory::instance().createAlgorithm(this, commonHeaderName, static_cast<ExportIntegratorType>(integratorType)));
505  if (integrator == 0)
506  return ACADOERROR( RET_INVALID_OPTION );
507 
508  ocp.setNumberIntegrationSteps( numSteps );
509  // NOTE: This function internally calls setup() function
510  returnvalue = integrator->setModelData( ocp.getModelData() );
511  if ( returnvalue != SUCCESSFUL_RETURN )
512  return returnvalue;
513 
514  //
515  // Prepare solver export
516  //
517 
518  int qpSolver;
519  get(QP_SOLVER, qpSolver);
520  int qpSolution;
521  get(SPARSE_QP_SOLUTION, qpSolution);
522  int hessianApproximation;
523  get( HESSIAN_APPROXIMATION, hessianApproximation );
524 
525  // TODO Extend ExportNLPSolver ctor to accept OCP reference.
526 
527  switch ( (SparseQPsolutionMethods)qpSolution )
528  {
529  case FULL_CONDENSING:
530  case CONDENSING:
531 
532  if ( ((QPSolverName)qpSolver != QP_QPOASES) && ((QPSolverName)qpSolver != QP_QPOASES3) )
534  "For condensed solution only qpOASES and qpOASES3 QP solver are supported");
535 
538 
539  break;
540 
541  case FULL_CONDENSING_N2:
542  case CONDENSING_N2:
543 
544  if ( ((QPSolverName)qpSolver != QP_QPOASES) && ((QPSolverName)qpSolver != QP_QPOASES3) )
546  "For condensed solution only qpOASES and qpOASES3 QP solver are supported");
547 
548  if ( (HessianApproximationMode)hessianApproximation == GAUSS_NEWTON ) {
551  }
552  else if ( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN ) {
555  }
556  else {
557  return ACADOERRORTEXT(RET_INVALID_ARGUMENTS, "Only Gauss-Newton and Exact Hessian methods are currently supported");
558  }
559 
560  break;
561 
562  case BLOCK_CONDENSING_N2:
563 
564  if ((QPSolverName)qpSolver != QP_QPDUNES && (QPSolverName)qpSolver != QP_FORCES)
566  "For block condensed solution only qpDUNES QP solver is currently supported");
567 
568  if ( (HessianApproximationMode)hessianApproximation == GAUSS_NEWTON && (QPSolverName)qpSolver == QP_QPDUNES ) {
571  }
572  else if ( (HessianApproximationMode)hessianApproximation == GAUSS_NEWTON && (QPSolverName)qpSolver == QP_FORCES ) {
575  }
576  else {
577  return ACADOERRORTEXT(RET_INVALID_ARGUMENTS, "Only Gauss-Newton methods are currently supported in combination with block condensing.");
578  }
579 
580  break;
581 
583 
584  if ( ((QPSolverName)qpSolver != QP_QPOASES) && ((QPSolverName)qpSolver != QP_QPOASES3) )
586  "For condensed solution only qpOASES and qpOASES3 QP solver are supported");
587 
590 
591  break;
592 
593  case SPARSE_SOLVER:
594  if ((QPSolverName)qpSolver != QP_FORCES && (QPSolverName)qpSolver != QP_QPDUNES && (QPSolverName)qpSolver != QP_HPMPC && (QPSolverName)qpSolver != QP_GENERIC)
596  "For sparse solution FORCES, qpDUNES and HPMPC QP solvers are supported");
597  if ( (QPSolverName)qpSolver == QP_FORCES)
600  else if ((QPSolverName)qpSolver == QP_QPDUNES) {
601  if ( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN ) {
604  }
605  else {
608  }
609  }
610  else if ((QPSolverName)qpSolver == QP_HPMPC)
613  else if ((QPSolverName)qpSolver == QP_GENERIC)
616  break;
617 
618  default:
619  return ACADOERRORTEXT(RET_INVALID_ARGUMENTS, "QP solver option is invalid");
620  }
621  if (solver == 0)
622  return ACADOERRORTEXT(RET_INVALID_OPTION, "Cannot allocate the solver object");
623 
624  solver->setDimensions(ocp.getNX(), ocp.getNDX(), ocp.getNXA(), ocp.getNU(), ocp.getNP(), ocp.getN(), ocp.getNOD());
625  solver->setIntegratorExport( integrator );
626 
627  Objective objective;
628  ocp.getObjective( objective );
629 
630  returnValue statusObjective;
631  statusObjective = solver->setObjective( objective );
632  if (statusObjective != SUCCESSFUL_RETURN)
633  return ACADOERRORTEXT(status, "Error in retrieving the objective.");
634 
635  solver->setConstraints( ocp );
636 
637  // Get LM multiplier
638  double levenbergMarquardt;
639  get( LEVENBERG_MARQUARDT,levenbergMarquardt );
640 
641  solver->setLevenbergMarquardt( levenbergMarquardt );
642 
643  returnValue statusSetup;
644  statusSetup = solver->setup( );
645  if (statusSetup != SUCCESSFUL_RETURN)
646  return ACADOERRORTEXT(status, "Error in setting up solver.");
647 
648  setStatus( BS_READY );
649 
650  return SUCCESSFUL_RETURN;
651 }
652 
653 
655 {
656  //
657  // Consistency checks:
658  //
659  Objective objective;
660  ocp.getObjective( objective );
661  int hessianApproximation;
662  get( HESSIAN_APPROXIMATION, hessianApproximation );
663 
664  if ( ocp.hasObjective( ) == true && !((HessianApproximationMode)hessianApproximation == EXACT_HESSIAN &&
665  (objective.getNumMayerTerms() == 1 || objective.getNumLagrangeTerms() == 1)) ) { // for Exact Hessian RTI
667  }
668 
669 
670  int sensitivityProp;
671  get(DYNAMIC_SENSITIVITY, sensitivityProp);
672 
673 // if( (HessianApproximationMode)hessianApproximation == EXACT_HESSIAN && (ExportSensitivityType) sensitivityProp != THREE_SWEEPS ) {
674 // return ACADOERROR( RET_INVALID_OPTION );
675 // }
676 
678  ocp.getModel( f );
679 
680 // if ( f.isDiscretized( ) == BT_TRUE )
681 // return ACADOERROR( RET_NO_DISCRETE_ODE_FOR_CODE_EXPORT );
682 
683  if ( f.getNUI( ) > 0 )
685 
686  if ( f.getNP( ) > 0 )
688  "Free parameters are not supported. For the old functionality use OnlineData class.");
689 
690  if ( (HessianApproximationMode)hessianApproximation != GAUSS_NEWTON && (HessianApproximationMode)hessianApproximation != EXACT_HESSIAN )
691  return ACADOERROR( RET_INVALID_OPTION );
692 
693  int discretizationType;
694  get( DISCRETIZATION_TYPE,discretizationType );
695  if ( ( (StateDiscretizationType)discretizationType != SINGLE_SHOOTING ) &&
696  ( (StateDiscretizationType)discretizationType != MULTIPLE_SHOOTING ) )
697  return ACADOERROR( RET_INVALID_OPTION );
698 
699  return SUCCESSFUL_RETURN;
700 }
701 
702 
704  ExportStruct dataStruct
705  ) const
706 {
707  if (integrator->getDataDeclarations(declarations, dataStruct) != SUCCESSFUL_RETURN)
709 
710  if (solver->getDataDeclarations(declarations, dataStruct) != SUCCESSFUL_RETURN)
712 
713  return SUCCESSFUL_RETURN;
714 }
715 
716 
718  ) const
719 {
720  if (integrator->getFunctionDeclarations( declarations ) != SUCCESSFUL_RETURN)
722 
723  if (solver->getFunctionDeclarations( declarations ) != SUCCESSFUL_RETURN)
725 
726  return SUCCESSFUL_RETURN;
727 }
728 
729 returnValue OCPexport::exportAcadoHeader( const std::string& _dirName,
730  const std::string& _fileName,
731  const std::string& _realString,
732  const std::string& _intString,
733  int _precision
734  ) const
735 {
736  string moduleName, modulePrefix;
737  get(CG_MODULE_NAME, moduleName);
738  get(CG_MODULE_PREFIX, modulePrefix);
739 
740  int qpSolver;
741  get(QP_SOLVER, qpSolver);
742 
743  int useSinglePrecision;
744  get(USE_SINGLE_PRECISION, useSinglePrecision);
745 
746  int hardcodeConstraintValues;
747  get(CG_HARDCODE_CONSTRAINT_VALUES, hardcodeConstraintValues);
748 
749  int fixInitialState;
750  get(FIX_INITIAL_STATE, fixInitialState);
751  int useAC;
752  get(CG_USE_ARRIVAL_COST, useAC);
753  int covCalc;
754  get(CG_COMPUTE_COVARIANCE_MATRIX, covCalc);
755 
756  int linSolver;
757  get(LINEAR_ALGEBRA_SOLVER, linSolver);
758  bool useComplexArithmetic = false;
759 
760  if( (LinearAlgebraSolver)linSolver == SIMPLIFIED_IRK_NEWTON ) useComplexArithmetic = true;
761 
762  string fileName;
763  fileName = _dirName + "/" + _fileName;
764 
765  map<string, pair<string, string> > options;
766 
767  options[ modulePrefix + "_N" ] = make_pair(toString( ocp.getN() ), "Number of control/estimation intervals.");
768  options[ modulePrefix + "_NX" ] = make_pair(toString( ocp.getNX() ), "Number of differential variables.");
769  options[ modulePrefix + "_NXD" ] = make_pair(toString( ocp.getNDX() ), "Number of differential derivative variables.");
770  options[ modulePrefix + "_NXA" ] = make_pair(toString( ocp.getNXA() ), "Number of algebraic variables.");
771  options[ modulePrefix + "_NU" ] = make_pair(toString( ocp.getNU() ), "Number of control variables.");
772  options[ modulePrefix + "_NOD" ] = make_pair(toString( ocp.getNOD() ), "Number of online data values.");
773  options[ modulePrefix + "_NY" ] = make_pair(toString( solver->getNY() ), "Number of references/measurements per node on the first N nodes.");
774  options[ modulePrefix + "_NYN" ] = make_pair(toString( solver->getNYN() ), "Number of references/measurements on the last (N + 1)st node.");
775  options[ modulePrefix + "_NPAC" ] = make_pair(toString( solver->getNumPathConstraints() ), "Number of path constraints.");
776 
777  Grid integrationGrid;
778  ocp.getIntegrationGrid(integrationGrid);
779  uint NIS = integrationGrid.getNumIntervals();
780  if( ocp.hasEquidistantControlGrid() ) options[ modulePrefix + "_RK_NIS" ] = make_pair(toString( NIS ), "Number of integration steps per shooting interval.");
781 
782  RungeKuttaExport *rk_integrator = static_cast<RungeKuttaExport *>(integrator.get()); // Note: As long as only Runge-Kutta type methods are exported.
783  options[ modulePrefix + "_RK_NSTAGES" ] = make_pair(toString( rk_integrator->getNumStages() ), "Number of Runge-Kutta stages per integration step.");
784 
785  options[ modulePrefix + "_INITIAL_STATE_FIXED" ] =
786  make_pair(toString( fixInitialState ), "Indicator for fixed initial state.");
787  options[ modulePrefix + "_WEIGHTING_MATRICES_TYPE" ] =
788  make_pair(toString( (unsigned)solver->weightingMatricesType() ), "Indicator for type of fixed weighting matrices.");
789  options[ modulePrefix + "_USE_LINEAR_TERMS" ] =
790  make_pair(toString( (unsigned)solver->usingLinearTerms() ), "Indicator for usage of non-hard-coded linear terms in the objective.");
791  options[ modulePrefix + "_HARDCODED_CONSTRAINT_VALUES" ] =
792  make_pair(toString( hardcodeConstraintValues ), "Flag indicating whether constraint values are hard-coded or not.");
793  options[ modulePrefix + "_USE_ARRIVAL_COST" ] =
794  make_pair(toString( useAC ), "Providing interface for arrival cost.");
795  options[ modulePrefix + "_COMPUTE_COVARIANCE_MATRIX" ] =
796  make_pair(toString( covCalc ), "Compute covariance matrix of the last state estimate.");
797  options[ modulePrefix + "_QP_NV" ] =
798  make_pair(toString( solver->getNumQPvars() ), "Total number of QP optimization variables.");
799 
800  int qpSolution;
801  get(SPARSE_QP_SOLUTION, qpSolution);
802  if( (QPSolverName)qpSolver == QP_FORCES && (SparseQPsolutionMethods)qpSolution != BLOCK_CONDENSING_N2 ) {
803  ExportGaussNewtonForces *blockSolver = static_cast<ExportGaussNewtonForces*>(solver.get());
804  options[ modulePrefix + "_QP_NLB" ] =
805  make_pair(toString( blockSolver->getNumLowerBounds() ), "Total number of QP lower bound values.");
806  options[ modulePrefix + "_QP_NUB" ] =
807  make_pair(toString( blockSolver->getNumUpperBounds() ), "Total number of QP upper bound values.");
808  }
809 
810  // QPDunes block based condensing:
811  if ( (SparseQPsolutionMethods)qpSolution == BLOCK_CONDENSING_N2 ) {
812  ExportGaussNewtonBlockCN2 *blockSolver = static_cast<ExportGaussNewtonBlockCN2*>(solver.get());
813 
814  options[ modulePrefix + "_BLOCK_CONDENSING" ] =
815  make_pair(toString( 1 ), "User defined block based condensing.");
816  options[ modulePrefix + "_QP_NCA" ] =
817  make_pair(toString( blockSolver->getNumStateBoundsPerBlock()*blockSolver->getNumberOfBlocks() ), "Total number of QP affine constraints.");
818  }
819  else {
820  options[ modulePrefix + "_BLOCK_CONDENSING" ] =
821  make_pair(toString( 0 ), "User defined block based condensing.");
822  }
823 
824 
825  //
826  // ACADO variables and workspace
827  //
828  ExportStatementBlock variablesBlock;
829  stringstream variables;
830 
833  variablesBlock.exportCode(variables, _realString, _intString, _precision);
834 
835  ExportStatementBlock workspaceBlock;
836  stringstream workspace;
837 
840  workspaceBlock.exportCode(workspace, _realString, _intString, _precision);
841 
842  ExportStatementBlock functionsBlock;
843  stringstream functions;
844 
845  if (collectFunctionDeclarations( functionsBlock ) != SUCCESSFUL_RETURN)
847  functionsBlock.exportCode(functions, _realString);
848 
849  ExportCommonHeader ech(fileName, "", _realString, _intString, _precision);
850  ech.configure( moduleName, modulePrefix, useSinglePrecision, useComplexArithmetic, (QPSolverName)qpSolver,
851  options, variables.str(), workspace.str(), functions.str());
852 
853  return ech.exportCode();
854 }
855 
#define LOG(level)
Just define a handy macro for getting the logger.
uint getNumLagrangeTerms() const
Definition: objective.cpp:627
StateDiscretizationType
Returned value is a information.
Lowest level, the debug level.
returnValue collectFunctionDeclarations(ExportStatementBlock &declarations) const
Definition: ocp_export.cpp:717
HessianApproximationMode
virtual unsigned getNumStateBoundsPerBlock() const
virtual returnValue setup(const std::string &_templateName, const std::string &_fileName, const std::string &_commonHeaderName="", const std::string &_realString="real_t", const std::string &_intString="int", int _precision=16, const std::string &_commentString=std::string())
uint getN() const
std::map< std::string, std::string > dictionary
returnValue getObjective(Objective &objective_) const
Definition: ocp.cpp:330
std::shared_ptr< IntegratorExport > IntegratorExportPtr
SparseQPsolutionMethods
LinearAlgebraSolver
Allows to export a tailored Runge-Kutta integrator for fast model predictive control.
Definition: rk_export.hpp:54
returnValue setStatus(BlockStatus _status)
A class for generating the glue code and makefile for interfacing generated code and Simulink...
returnValue configure(unsigned N, unsigned NX, unsigned NDX, unsigned NXA, unsigned NU, unsigned NP, unsigned NY, unsigned NYN, bool _initialStateFixed, unsigned _wMatrixType, bool _hardcodedConstraints, bool _useArrivalCost, bool _compCovMatrix, std::string _qpSolver)
returnValue setNumberIntegrationSteps(const uint numSteps)
Definition: ocp.cpp:346
uint getNOD() const
returnValue exportAcadoHeader(const std::string &_dirName, const std::string &_fileName, const std::string &_realString="real_t", const std::string &_intString="int", int _precision=16) const
Definition: ocp_export.cpp:729
Allows to pass back messages to the calling function.
Centralized place to export the common header for a generated module.
returnValue configure(uint DIM, double eps)
int getNUI() const
Definition: function.cpp:227
HessianRegularizationMode
A class for export of an OCP solver using sparse QP solver FORCES.
BEGIN_NAMESPACE_ACADO typedef unsigned int uint
Definition: acado_types.hpp:42
virtual returnValue exportCode(const std::string &dirName, const std::string &_realString="real_t", const std::string &_intString="int", int _precision=16)
Definition: ocp_export.cpp:68
Allows to conveniently handle (one-dimensional) grids consisting of time points.
Definition: grid.hpp:58
uint getNU() const
string toString(T const &value)
uint getNP() const
#define CLOSE_NAMESPACE_ACADO
virtual returnValue exportCode(std::ostream &stream, const std::string &_realString="real_t", const std::string &_intString="int", int _precision=16) const
uint getNXA() const
std::shared_ptr< ExportNLPSolver > ExportNLPSolverPtr
An OCP solver based on the block N^2 condensing algorithm.
Allows to export files containing automatically generated algorithms for fast model predictive contro...
Definition: export_file.hpp:52
std::string commonHeaderName
Allows export of template files.
returnValue getModel(DifferentialEquation &_f) const
User-interface to automatically generate algorithms for fast model predictive control.
BlockStatus getStatus() const
returnValue configure(const std::string &_moduleName, const std::string &_modulePrefix, bool _useSinglePrecision, bool _useComplexArithmetic, QPSolverName _qpSolver, const std::map< std::string, std::pair< std::string, std::string > > &_options, const std::string &_variables, const std::string &_workspace, const std::string &_functions)
ExportStruct
int getNP() const
Definition: function.cpp:233
static std::string fcnPrefix
returnValue acadoCopyTemplateFile(const std::string &source, const std::string &destination, const std::string &commentString, bool printCodegenNotice)
A class for generating code implementing a symmetric EigenValue Decomposition.
uint getNumMayerTerms() const
Definition: objective.cpp:614
BooleanType hasEquidistantControlGrid() const
static std::string fcnPrefix
returnValue acadoPrintCopyrightNotice(const std::string &subpackage)
Data class for defining optimal control problems.
Definition: ocp.hpp:89
returnValue acadoCreateFolder(const std::string &name)
returnValue setup()
Definition: ocp_export.cpp:476
returnValue getIntegrationGrid(Grid &_grid) const
A class for generating some helper functions.
#define ACADOWARNINGTEXT(retval, text)
returnValue checkConsistency() const
Definition: ocp_export.cpp:654
uint getNumIntervals() const
uint getNDX() const
std::shared_ptr< ExportNLPSolver > solver
Definition: ocp_export.hpp:165
returnValue printDimensionsQP()
Definition: ocp_export.cpp:464
#define BEGIN_NAMESPACE_ACADO
BooleanType hasObjective() const
Definition: ocp.cpp:316
static ExportAlgorithmFactory & instance()
QPSolverName
returnValue collectDataDeclarations(ExportStatementBlock &declarations, ExportStruct dataStruct=ACADO_ANY) const
Definition: ocp_export.cpp:703
virtual returnValue configure()
ModelData & getModelData()
Allows to export code for a block of statements.
Stores and evaluates the objective function of optimal control problems.
Definition: objective.hpp:123
std::shared_ptr< IntegratorExport > integrator
Definition: ocp_export.hpp:162
virtual returnValue exportCode() const
Definition: export_file.cpp:82
static std::string varPrefix
#define ACADOERROR(retval)
#define ACADOERRORTEXT(retval, text)
Allows to setup and evaluate differential equations (ODEs and DAEs) based on SymbolicExpressions.
uint getNX() const


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