00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00034 #include <acado/code_generation/sim_export.hpp>
00035 #include <acado/code_generation/integrators/export_matlab_integrator.hpp>
00036 #include <acado/code_generation/integrators/integrator_generation.hpp>
00037 #include <acado/code_generation/export_common_header.hpp>
00038 #include <acado/code_generation/templates/templates.hpp>
00039 #include <acado/code_generation/integrators/export_auxiliary_sim_functions.hpp>
00040 #include <acado/code_generation/export_algorithm_factory.hpp>
00041
00042 #ifdef WIN32
00043 #include <windows.h>
00044 #endif
00045
00046 using namespace std;
00047
00048 BEGIN_NAMESPACE_ACADO
00049
00050
00051
00052
00053
00054
00055 SIMexport::SIMexport( const uint simIntervals, const double totalTime ) : ExportModule( )
00056 {
00057 setN(simIntervals);
00058 T = totalTime;
00059 integrator = 0;
00060 timingSteps = 100;
00061
00062 _initStates = "initStates.txt";
00063 _controls = "controls.txt";
00064 _results = "results.txt";
00065 _ref = "ref.txt";
00066 referenceProvided = false;
00067 PRINT_DETAILS = true;
00068
00069 timingCalls = 0;
00070
00071 setStatus( BS_NOT_INITIALIZED );
00072 }
00073
00074
00075 SIMexport::SIMexport( const SIMexport& arg
00076 ) : ExportModule( arg )
00077 {
00078 copy( arg );
00079 }
00080
00081
00082 SIMexport::~SIMexport( )
00083 {
00084 clear( );
00085 }
00086
00087
00088 SIMexport& SIMexport::operator=( const SIMexport& arg
00089 )
00090 {
00091 if( this != &arg )
00092 {
00093 clear( );
00094 ExportModule::operator=( arg );
00095 copy( arg );
00096 }
00097
00098 return *this;
00099 }
00100
00101
00102
00103 returnValue SIMexport::exportCode( const std::string& dirName,
00104 const std::string& _realString,
00105 const std::string& _intString,
00106 int _precision
00107 )
00108 {
00109 if (!modelDimensionsSet() && !exportRhs()) return ACADOERROR( RET_UNABLE_TO_EXPORT_CODE );
00110 set( QP_SOLVER, QP_NONE );
00111
00112 string moduleName;
00113 get(CG_MODULE_NAME, moduleName);
00114
00115
00116
00117
00118
00119 set(CG_EXPORT_FOLDER_NAME, dirName);
00120
00121 returnValue dirStatus = acadoCreateFolder( dirName );
00122 if (dirStatus != SUCCESSFUL_RETURN)
00123 return dirStatus;
00124
00125 if ( setup( ) != SUCCESSFUL_RETURN )
00126 return ACADOERROR( RET_UNABLE_TO_EXPORT_CODE );
00127
00128 int printLevel;
00129 get( PRINTLEVEL,printLevel );
00130
00131
00132 if ( exportAcadoHeader( dirName,commonHeaderName,_realString,_intString,_precision ) != SUCCESSFUL_RETURN )
00133 return ACADOERROR( RET_UNABLE_TO_EXPORT_CODE );
00134
00135 if( integrator != 0 )
00136 {
00137 std::string fileName( dirName );
00138 fileName += "/acado_integrator.c";
00139
00140 ExportFile integratorFile( fileName,commonHeaderName,_realString,_intString,_precision );
00141 integrator->getCode( integratorFile );
00142
00143 if ( integratorFile.exportCode( ) != SUCCESSFUL_RETURN )
00144 return ACADOERROR( RET_UNABLE_TO_EXPORT_CODE );
00145
00146 int sensGen;
00147 get( DYNAMIC_SENSITIVITY, sensGen );
00148 int measGrid;
00149 get( MEASUREMENT_GRID, measGrid );
00150 int generateMatlabInterface;
00151 get( GENERATE_MATLAB_INTERFACE, generateMatlabInterface );
00152 int debugMode;
00153 get( INTEGRATOR_DEBUG_MODE, debugMode );
00154 if ( (bool)generateMatlabInterface == true ) {
00155 std::string integrateInterface = dirName;
00156 integrateInterface += "/acado_integrate.c";
00157 ExportMatlabIntegrator exportMexFun( INTEGRATOR_MEX_TEMPLATE, integrateInterface, commonHeaderName,_realString,_intString,_precision );
00158 exportMexFun.configure((ExportSensitivityType)sensGen, (MeasurementGrid)measGrid == ONLINE_GRID, (bool)debugMode, timingCalls, ((RungeKuttaExport*)integrator)->getNumStages());
00159 exportMexFun.exportCode();
00160
00161 integrateInterface = dirName + std::string("/make_acado_integrator.m");
00162 acadoCopyTemplateFile(MAKE_MEX_INTEGRATOR, integrateInterface, "%", true);
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 }
00174 }
00175
00176
00177
00178 if ( (PrintLevel)printLevel >= HIGH )
00179 cout << "--> Exporting remaining files... ";
00180
00181
00182
00183 ExportAuxiliarySimFunctions eaf(
00184 dirName + string("/") + moduleName + "_auxiliary_sim_functions.h",
00185 dirName + string("/") + moduleName + "_auxiliary_sim_functions.c",
00186 moduleName );
00187 eaf.configure();
00188 eaf.exportCode();
00189
00190
00191 int generateMakeFile;
00192 get( GENERATE_MAKE_FILE,generateMakeFile );
00193 if ( (bool)generateMakeFile == true )
00194 if ( exportMakefile( dirName,"Makefile",_realString,_intString,_precision ) != SUCCESSFUL_RETURN )
00195 return ACADOERROR( RET_UNABLE_TO_EXPORT_CODE );
00196
00197
00198 int exportTestFile;
00199 get( GENERATE_TEST_FILE, exportTestFile );
00200 if ( exportTestFile && exportEvaluation( dirName, std::string( "acado_compare.c" ) ) != SUCCESSFUL_RETURN )
00201 return ACADOERROR( RET_UNABLE_TO_EXPORT_CODE );
00202
00203 if ( (PrintLevel)printLevel >= HIGH )
00204 cout << "done.\n";
00205
00206 if ( (PrintLevel)printLevel > NONE )
00207 ACADOINFO( RET_CODE_EXPORT_SUCCESSFUL );
00208
00209 return SUCCESSFUL_RETURN;
00210 }
00211
00212
00213
00214
00215
00216
00217
00218 returnValue SIMexport::copy( const SIMexport& arg
00219 )
00220 {
00221 integrator = arg.integrator;
00222
00223 _initStates = arg._initStates;
00224 _controls = arg._controls;
00225 _results = arg._results;
00226 _ref = arg._ref;
00227 _refOutputFiles = arg._refOutputFiles;
00228 referenceProvided = arg.referenceProvided;
00229 PRINT_DETAILS = arg.PRINT_DETAILS;
00230 timingSteps = arg.timingSteps;
00231
00232 return SUCCESSFUL_RETURN;
00233 }
00234
00235
00236 returnValue SIMexport::clear( )
00237 {
00238 if ( integrator != 0 )
00239 delete integrator;
00240
00241 return SUCCESSFUL_RETURN;
00242 }
00243
00244
00245
00246 returnValue SIMexport::setup( )
00247 {
00248 returnValue returnvalue = checkConsistency( );
00249 if ( returnvalue != SUCCESSFUL_RETURN )
00250 return ACADOERROR( returnvalue );
00251
00252
00253
00254
00255 string moduleName;
00256 get(CG_MODULE_NAME, moduleName);
00257 commonHeaderName = moduleName + "_common.h";
00258
00259 int numSteps;
00260 get( NUM_INTEGRATOR_STEPS, numSteps );
00261
00262 if ( numSteps <= 0 )
00263 return ACADOERROR( RET_INVALID_OPTION );
00264
00265 int integratorType;
00266 get( INTEGRATOR_TYPE, integratorType );
00267
00268 if ( integrator != NULL )
00269 delete integrator;
00270
00271 integrator = IntegratorExportFactory::instance().createAlgorithm(this, commonHeaderName, static_cast<ExportIntegratorType>(integratorType));
00272
00273 if ( integrator == NULL )
00274 return ACADOERROR( RET_INVALID_OPTION );
00275
00276 Grid grid( 0.0, T, modelData.getN()+1 );
00277 modelData.setIntegrationGrid( grid, numSteps );
00278 integrator->setModelData( modelData );
00279
00280 if( modelData.hasOutputs() ) {
00281 uint i;
00282
00283 std::vector<Grid> newGrids_;
00284 if( !referenceProvided ) _refOutputFiles.clear();
00285 _outputFiles.clear();
00286 for( i = 0; i < modelData.getNumOutputs(); i++ ) {
00287 if( !referenceProvided ) _refOutputFiles.push_back( (std::string)"refOutput" + toString(i) + ".txt" );
00288 _outputFiles.push_back( (std::string)"output" + toString(i) + ".txt" );
00289 }
00290 }
00291
00292 if( !integrator->equidistantControlGrid() ) return ACADOERROR( RET_INVALID_OPTION );
00293
00294 setStatus( BS_READY );
00295
00296 return SUCCESSFUL_RETURN;
00297 }
00298
00299
00300 returnValue SIMexport::checkConsistency( ) const
00301 {
00302
00303
00304 DifferentialEquation f;
00305 modelData.getModel(f);
00306 if ( f.isDiscretized( ) == true )
00307 return ACADOERROR( RET_NO_DISCRETE_ODE_FOR_CODE_EXPORT );
00308
00309 if ( ( f.getNUI( ) > 0 ) ||
00310 ( f.getNPI( ) > 0 ) || ( f.getNW( ) > 0 ) )
00311 return ACADOERROR( RET_ONLY_STATES_AND_CONTROLS_FOR_CODE_EXPORT );
00312
00313
00314
00315 return SUCCESSFUL_RETURN;
00316 }
00317
00318
00319
00320 returnValue SIMexport::collectDataDeclarations( ExportStatementBlock& declarations,
00321 ExportStruct dataStruct
00322 ) const
00323 {
00324 if ( integrator->getDataDeclarations( declarations,dataStruct ) != SUCCESSFUL_RETURN )
00325 return RET_UNABLE_TO_EXPORT_CODE;
00326
00327 return SUCCESSFUL_RETURN;
00328 }
00329
00330
00331 returnValue SIMexport::collectFunctionDeclarations( ExportStatementBlock& declarations
00332 ) const
00333 {
00334 if ( integrator->getFunctionDeclarations( declarations ) != SUCCESSFUL_RETURN )
00335 return RET_UNABLE_TO_EXPORT_CODE;
00336
00337 return SUCCESSFUL_RETURN;
00338 }
00339
00340
00341 returnValue SIMexport::exportTest( const std::string& _dirName,
00342 const std::string& _fileName,
00343 const std::string& _resultsFile,
00344 const std::vector<std::string>& outputFiles,
00345 const bool& TIMING,
00346 const uint jumpReference
00347 ) const
00348 {
00349 int i;
00350 int sensGen;
00351 get( DYNAMIC_SENSITIVITY, sensGen );
00352 bool DERIVATIVES = ((ExportSensitivityType) sensGen != NO_SENSITIVITY);
00353
00354 std::vector<Grid> outputGrids;
00355 std::vector<Expression> outputExpressions;
00356 std::vector<std::string> outputNames;
00357 modelData.getOutputGrids(outputGrids);
00358 modelData.getOutputExpressions(outputExpressions);
00359 modelData.getNameOutputs(outputNames);
00360 if( outputFiles.size() != outputGrids.size() || (outputFiles.size() != outputExpressions.size() && outputFiles.size() != outputNames.size()) ) {
00361 return ACADOERROR( RET_INVALID_OPTION );
00362 }
00363
00364 std::string fileName( _dirName );
00365 fileName += "/" + _fileName;
00366
00367 ExportFile main( fileName,commonHeaderName );
00368
00369 main.addStatement( "#include <stdio.h>\n" );
00370 main << "#include \"acado_auxiliary_sim_functions.h\"\n";
00371 main.addLinebreak( 1 );
00372 main.addComment( "SOME CONVENIENT DEFINTIONS:" );
00373 main.addComment( "---------------------------------------------------------------" );
00374 main.addStatement( (std::string)" #define JUMP " + toString(jumpReference) + " /* jump for the output reference */\n" );
00375 main.addStatement( (std::string)" #define h " + toString(T/modelData.getN()) + " /* length of one simulation interval */\n" );
00376 if( TIMING == true ) main.addStatement( (std::string)" #define STEPS_TIMING " + toString(timingSteps) + " /* number of steps for the timing */\n" );
00377 if( TIMING == true ) main.addStatement( (std::string)" #define CALLS_TIMING " + toString(timingCalls) + " /* number of calls for the timing */\n" );
00378 main.addStatement( (std::string)" #define RESULTS_NAME \"" + _resultsFile + "\"\n" );
00379 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00380 main.addStatement( (std::string)" #define OUTPUT" + toString(i) + "_NAME \"" + outputFiles[i] + "\"\n" );
00381 }
00382 main.addStatement( (std::string)" #define CONTROLS_NAME \"" + _controls + "\"\n" );
00383 main.addStatement( (std::string)" #define INIT_NAME \"" + _initStates + "\"\n" );
00384 main.addComment( "---------------------------------------------------------------" );
00385 main.addLinebreak( 2 );
00386 main.addComment( "GLOBAL VARIABLES FOR THE ACADO REAL-TIME ALGORITHM:" );
00387 main.addComment( "---------------------------------------------------" );
00388 main.addStatement( " ACADOworkspace acadoWorkspace;\n" );
00389 main.addStatement( " ACADOvariables acadoVariables;\n" );
00390 main.addLinebreak( );
00391
00392 main.addLinebreak( 2 );
00393 main.addComment( "A TEMPLATE FOR TESTING THE INTEGRATOR:" );
00394 main.addComment( "----------------------------------------------------" );
00395 main.addStatement( "int main(){\n" );
00396 main.addLinebreak( );
00397 main.addComment( 3,"INTRODUCE AUXILIARY VAIRABLES:" );
00398 main.addComment( 3,"------------------------------" );
00399 main.addStatement( " FILE *file, *controls, *initStates;\n" );
00400 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00401 main.addStatement( (std::string)" FILE *output" + toString(i) + ";\n" );
00402 }
00403 main.addStatement( " int i,j,k,nil,reset;\n" );
00404 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00405 if( !DERIVATIVES ) main.addStatement( (std::string)" const int dimOut" + toString(i) + " = ACADO_NOUT[" + toString(i) + "];\n" );
00406 else main.addStatement( (std::string)" const int dimOut" + toString(i) + " = ACADO_NOUT[" + toString(i) + "]*(1+ACADO_NX+ACADO_NU);\n" );
00407 }
00408 if( !DERIVATIVES ) main.addStatement( " real_t x[ACADO_NX+ACADO_NXA+ACADO_NU];\n" );
00409 else main.addStatement( " real_t x[(ACADO_NX+ACADO_NXA)*(1+ACADO_NX+ACADO_NU)+ACADO_NU];\n" );
00410
00411 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00412 main.addStatement( (std::string)" real_t out" + toString(i) + "[ACADO_NMEAS[" + toString(i) + "]*dimOut" + toString(i) + "];\n" );
00413 }
00414 main.addStatement( " real_t u[ACADO_NU];\n" );
00415 if( modelData.getNXA() > 0 ) main.addStatement( " real_t norm;\n" );
00416 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00417 main.addStatement( (std::string)" real_t step" + toString(i) + " = h/ACADO_NMEAS[" + toString(i) + "];\n" );
00418 }
00419 if( TIMING == true ) {
00420 main.addStatement( " struct timeval theclock;\n" );
00421 main.addStatement( " real_t start, end, time;\n" );
00422 if( !DERIVATIVES ) main.addStatement( " real_t xT[ACADO_NX+ACADO_NXA+ACADO_NU];\n" );
00423 else main.addStatement( " real_t xT[(ACADO_NX+ACADO_NXA)*(1+ACADO_NX+ACADO_NU)+ACADO_NU];\n" );
00424 }
00425 main.addStatement( " const ACADOworkspace nullWork2 = {0};\n" );
00426 main.addStatement( " acadoWorkspace = nullWork2;\n" );
00427 main.addLinebreak( 2 );
00428
00429 main.addComment( 3,"INITIALIZATION:" );
00430 main.addComment( 3,"----------------------------------------" );
00431 main.addStatement( " initStates = fopen( INIT_NAME,\"r\" );\n" );
00432 main.addStatement( " for( j = 0; j < ACADO_NX+ACADO_NXA; j++) {\n" );
00433 main.addStatement( " nil = fscanf( initStates, \"%lf\", &x[j] );\n" );
00434 main.addStatement( " }\n" );
00435 main.addStatement( " fclose( initStates );\n" );
00436 main.addLinebreak( 1 );
00437 if( DERIVATIVES ) {
00438 main.addStatement( " for( i = 0; i < (ACADO_NX+ACADO_NXA); i++ ) {\n" );
00439 main.addStatement( " for( j = 0; j < ACADO_NX; j++ ) {\n" );
00440 main.addStatement( " if( i == j ) {\n" );
00441 main.addStatement( " x[ACADO_NX+ACADO_NXA+i*ACADO_NX+j] = 1;\n" );
00442 main.addStatement( " } else {\n" );
00443 main.addStatement( " x[ACADO_NX+ACADO_NXA+i*ACADO_NX+j] = 0;\n" );
00444 main.addStatement( " }\n" );
00445 main.addStatement( " }\n" );
00446 main.addStatement( " }\n" );
00447 main.addStatement( " for( i = 0; i < (ACADO_NX+ACADO_NXA); i++ ) {\n" );
00448 main.addStatement( " for( j = 0; j < ACADO_NU; j++ ) {\n" );
00449 main.addStatement( " x[ACADO_NX+ACADO_NXA+(ACADO_NX+ACADO_NXA)*ACADO_NX+i*ACADO_NU+j] = 0;\n" );
00450 main.addStatement( " }\n" );
00451 main.addStatement( " }\n" );
00452 }
00453 main.addLinebreak( 1 );
00454 main.addStatement( " reset = 1;\n" );
00455 main.addLinebreak( 1 );
00456 main.addComment( 3,"RUN INTEGRATOR:" );
00457 main.addComment( 3,"----------------------------------------" );
00458 main.addStatement( " file = fopen(RESULTS_NAME,\"w\");\n" );
00459 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00460 main.addStatement( (std::string)" output" + toString(i) + " = fopen(OUTPUT" + toString(i) + "_NAME,\"w\");\n" );
00461 }
00462 main.addStatement( " controls = fopen(CONTROLS_NAME,\"r\");\n" );
00463 main.addStatement( " for( i = 0; i < ACADO_N; i++ ) {\n" );
00464 main.addStatement( " fprintf(file, \"%.16f \", i*h);\n" );
00465 if( !DERIVATIVES ) main.addStatement( " for( j = 0; j < ACADO_NX+ACADO_NXA; j++) {\n" );
00466 else main.addStatement( " for( j = 0; j < (ACADO_NX+ACADO_NXA)*(1+ACADO_NX+ACADO_NU); j++) {\n" );
00467 main.addStatement( " fprintf(file, \"%.16f \", x[j]);\n" );
00468 main.addStatement( " }\n" );
00469 main.addStatement( " fprintf(file, \"\\n\");\n" );
00470 main.addLinebreak( );
00471 if( !DERIVATIVES ) main.addStatement( " nil = fscanf( controls, \"%lf\", &x[ACADO_NX+ACADO_NXA] );\n" );
00472 else main.addStatement( " nil = fscanf( controls, \"%lf\", &x[(ACADO_NX+ACADO_NXA)*(1+ACADO_NX+ACADO_NU)] );\n" );
00473 main.addStatement( " for( j = 0; j < ACADO_NU; j++) {\n" );
00474 if( !DERIVATIVES ) main.addStatement( " nil = fscanf( controls, \"%lf\", &x[ACADO_NX+ACADO_NXA+j] );\n" );
00475 else main.addStatement( " nil = fscanf( controls, \"%lf\", &x[(ACADO_NX+ACADO_NXA)*(1+ACADO_NX+ACADO_NU)+j] );\n" );
00476 main.addStatement( " }\n" );
00477 main.addLinebreak( );
00478 if( TIMING == true ) {
00479 main.addStatement( " if( i == 0 ) {\n" );
00480 if( !DERIVATIVES ) main.addStatement( " for( j=0; j < ACADO_NX+ACADO_NXA+ACADO_NU; j++ ) {\n" );
00481 else main.addStatement( " for( j=0; j < (ACADO_NX+ACADO_NXA)*(1+ACADO_NX+ACADO_NU)+ACADO_NU; j++ ) {\n" );
00482 main.addStatement( " xT[j] = x[j];\n" );
00483 main.addStatement( " }\n" );
00484 main.addStatement( " }\n" );
00485 }
00486 main.addLinebreak( );
00487 std::string integrate( " integrate( x" );
00488 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00489 integrate += string(", out") + toString(i);
00490 }
00491 integrate += ", reset";
00492 main.addStatement( integrate + " );\n" );
00493 main.addStatement( " reset = 0;\n" );
00494 main.addLinebreak( );
00495 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00496 main.addStatement( (std::string)" for( j = 0; j < ACADO_NMEAS[" + toString(i) + "]; j=j+JUMP ) {\n" );
00497 main.addStatement( (std::string)" fprintf(output" + toString(i) + ", \"%.16f \", i*h+(j+1)*step" + toString(i) + ");\n" );
00498 main.addStatement( (std::string)" for( k = 0; k < dimOut" + toString(i) + "; k++ ) {\n" );
00499 main.addStatement( (std::string)" fprintf(output" + toString(i) + ", \"%.16f \", out" + toString(i) + "[j*dimOut" + toString(i) + "+k]);\n" );
00500 main.addStatement( " }\n" );
00501 main.addStatement( (std::string)" fprintf(output" + toString(i) + ", \"%s\", \"\\n\");\n" );
00502 main.addStatement( " }\n" );
00503 }
00504 main.addStatement( " }\n" );
00505 main.addStatement( " fprintf(file, \"%.16f \", ACADO_N*h);\n" );
00506 if( !DERIVATIVES ) main.addStatement( " for( j = 0; j < ACADO_NX+ACADO_NXA; j++) {\n" );
00507 else main.addStatement( " for( j = 0; j < (ACADO_NX+ACADO_NXA)*(1+ACADO_NX+ACADO_NU); j++) {\n" );
00508 main.addStatement( " fprintf(file, \"%.16f \", x[j]);\n" );
00509 main.addStatement( " }\n" );
00510 main.addStatement( " fprintf(file, \"\\n\");\n" );
00511 main.addLinebreak( );
00512 main.addStatement( " fclose(file);\n" );
00513 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00514 main.addStatement( (std::string)" fclose(output" + toString(i) + ");\n" );
00515 }
00516 main.addStatement( " fclose(controls);\n" );
00517 if( TIMING == true ) {
00518 main.addStatement( " gettimeofday( &theclock,0 );\n" );
00519 main.addStatement( " start = 1.0*theclock.tv_sec + 1.0e-6*theclock.tv_usec;\n" );
00520 main.addStatement( " reset = 1;\n" );
00521 main.addStatement( " for( i=0; i < CALLS_TIMING; i++ ) {\n" );
00522 main.addStatement( " for( j=0; j < (ACADO_NX+ACADO_NXA); j++ ) {\n" );
00523 main.addStatement( " x[j] = xT[j];\n" );
00524 main.addStatement( " }\n" );
00525 integrate = std::string( " integrate( x" );
00526 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00527 integrate += string(", out") + toString(i);
00528 }
00529 integrate += ", reset";
00530 main.addStatement( integrate + " );\n" );
00531 main.addStatement( " reset = 0;\n" );
00532 main.addStatement( " }\n" );
00533 main.addStatement( " gettimeofday( &theclock,0 );\n" );
00534 main.addStatement( " end = 1.0*theclock.tv_sec + 1.0e-6*theclock.tv_usec;\n" );
00535 main.addStatement( " time = (end-start);\n" );
00536 main.addLinebreak( );
00537 main.addStatement( " printf( \"\\n\\n AVERAGE DURATION OF ONE INTEGRATION STEP: %.3g μs\\n\\n\", 1e6*time/STEPS_TIMING );\n" );
00538 }
00539 main.addLinebreak( );
00540 main.addStatement( " return 0;\n" );
00541 main.addStatement( "}\n" );
00542
00543
00544 return main.exportCode( );
00545 }
00546
00547
00548 returnValue SIMexport::exportEvaluation( const std::string& _dirName,
00549 const std::string& _fileName
00550 ) const
00551 {
00552 int i;
00553 int sensGen;
00554 get( DYNAMIC_SENSITIVITY, sensGen );
00555 bool DERIVATIVES = ((ExportSensitivityType) sensGen != NO_SENSITIVITY);
00556
00557 DVector nMeasV = modelData.getNumMeas();
00558 DVector nOutV = modelData.getDimOutputs();
00559
00560 std::vector<Grid> outputGrids;
00561 modelData.getOutputGrids(outputGrids);
00562
00563 std::string fileName = _dirName;
00564 fileName += string("/") + _fileName;
00565
00566 ExportFile main( fileName,commonHeaderName );
00567
00568 main.addStatement( "#include <stdio.h>\n" );
00569 main.addStatement( "#include \"acado_auxiliary_sim_functions.h\"\n" );
00570 main.addLinebreak( 1 );
00571 main.addComment( "SOME CONVENIENT DEFINTIONS:" );
00572 main.addComment( "---------------------------------------------------------------" );
00573 main.addStatement( (std::string)" #define h " + toString(T/modelData.getN()) + " /* length of one simulation interval */\n" );
00574 main.addStatement( (std::string)" #define RESULTS_NAME \"" + _results + "\"\n" );
00575 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00576 main.addStatement( (std::string)" #define OUTPUT" + toString(i) + "_NAME \"" + _outputFiles[i] + "\"\n" );
00577 main.addStatement( (std::string)" #define REF_OUTPUT" + toString(i) + "_NAME \"" + _refOutputFiles[i] + "\"\n" );
00578 }
00579 main.addStatement( (std::string)" #define REF_NAME \"" + _ref + "\"\n" );
00580 main.addComment( "---------------------------------------------------------------" );
00581 main.addLinebreak( 2 );
00582 main.addComment( "GLOBAL VARIABLES FOR THE ACADO REAL-TIME ALGORITHM:" );
00583 main.addComment( "---------------------------------------------------" );
00584 main.addStatement( " ACADOworkspace acadoWorkspace;\n" );
00585 main.addStatement( " ACADOvariables acadoVariables;\n" );
00586 main.addLinebreak( );
00587
00588 main.addLinebreak( 2 );
00589 main.addComment( "A TEMPLATE FOR TESTING THE INTEGRATOR:" );
00590 main.addComment( "----------------------------------------------------" );
00591 main.addStatement( "int main(){\n" );
00592 main.addLinebreak( );
00593 main.addComment( 3,"INTRODUCE AUXILIARY VAIRABLES:" );
00594 main.addComment( 3,"------------------------------" );
00595 main.addStatement( " FILE *file, *ref;\n" );
00596 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00597 main.addStatement( (std::string)" FILE *output" + toString(i) + ";\n" );
00598 main.addStatement( (std::string)" FILE *refOutput" + toString(i) + ";\n" );
00599 }
00600 main.addStatement( " int i, j, nil;\n" );
00601 main.addStatement( " real_t x[ACADO_NX+ACADO_NXA];\n" );
00602 main.addStatement( " real_t xRef[ACADO_NX+ACADO_NXA];\n" );
00603 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00604 main.addStatement( (std::string)" real_t step" + toString(i) + " = h/ACADO_NMEAS[" + toString(i) + "];\n" );
00605 main.addStatement( (std::string)" real_t out" + toString(i) + "[ACADO_NMEAS[" + toString(i) + "]*ACADO_NOUT[" + toString(i) + "]];\n" );
00606 main.addStatement( (std::string)" real_t refOut" + toString(i) + "[ACADO_NMEAS[" + toString(i) + "]*ACADO_NOUT[" + toString(i) + "]];\n" );
00607 }
00608 main.addStatement( " real_t maxErr, meanErr, maxErrX, meanErrX, maxErrXA, meanErrXA, temp;\n" );
00609 main.addStatement( " const ACADOworkspace nullWork2 = {0};\n" );
00610 main.addStatement( " acadoWorkspace = nullWork2;\n" );
00611 main.addLinebreak( 2 );
00612
00613 main.addComment( 3,"START EVALUATION RESULTS:" );
00614 main.addComment( 3,"----------------------------------------" );
00615 main.addStatement( " meanErrX = 0;\n" );
00616 main.addStatement( " meanErrXA = 0;\n" );
00617 main.addStatement( " file = fopen(RESULTS_NAME,\"r\");\n" );
00618 main.addStatement( " ref = fopen(REF_NAME,\"r\");\n" );
00619 if( DERIVATIVES ) main.addStatement( " for( i = 0; i < (ACADO_NX+ACADO_NXA)*(1+ACADO_NX+ACADO_NU)+1; i++ ) {\n" );
00620 else main.addStatement( " for( i = 0; i < ACADO_NX+ACADO_NXA+1; i++ ) {\n" );
00621 main.addStatement( " nil = fscanf( file, \"%lf\", &temp );\n" );
00622 main.addStatement( " nil = fscanf( ref, \"%lf\", &temp );\n" );
00623 main.addStatement( " }\n" );
00624 main.addStatement( " printf( \" STATES:\\n\" );\n" );
00625 main.addLinebreak( );
00626 main.addStatement( " for( i = 1; i <= ACADO_N; i++ ) {\n" );
00627 main.addStatement( " nil = fscanf( file, \"%lf\", &temp );\n" );
00628 main.addStatement( " nil = fscanf( ref, \"%lf\", &temp );\n" );
00629 main.addLinebreak( );
00630 main.addStatement( " maxErrX = 0;\n" );
00631 main.addStatement( " for( j = 0; j < ACADO_NX; j++ ) {\n" );
00632 main.addStatement( " nil = fscanf( file, \"%lf\", &x[j] );\n" );
00633 main.addStatement( " nil = fscanf( ref, \"%lf\", &xRef[j] );\n" );
00634 main.addStatement( " temp = fabs(x[j] - xRef[j])/fabs(xRef[j]);\n" );
00635 main.addStatement( " if( temp > maxErrX ) maxErrX = temp;\n" );
00636 main.addStatement( " if( isnan(x[j]) ) maxErrX = sqrt(-1);\n" );
00637 main.addStatement( " }\n" );
00638 main.addLinebreak( );
00639 main.addStatement( " maxErrXA = 0;\n" );
00640 main.addStatement( " for( j = 0; j < ACADO_NXA; j++ ) {\n" );
00641 main.addStatement( " nil = fscanf( file, \"%lf\", &x[ACADO_NX+j] );\n" );
00642 main.addStatement( " nil = fscanf( ref, \"%lf\", &xRef[ACADO_NX+j] );\n" );
00643 main.addStatement( " temp = fabs(x[ACADO_NX+j] - xRef[ACADO_NX+j])/fabs(xRef[ACADO_NX+j]);\n" );
00644 main.addStatement( " if( temp > maxErrXA ) maxErrXA = temp;\n" );
00645 main.addStatement( " if( isnan(x[ACADO_NX+j]) ) maxErrXA = sqrt(-1);\n" );
00646 main.addStatement( " }\n" );
00647 main.addLinebreak( );
00648 if( PRINT_DETAILS && modelData.getNXA() > 0 ) {
00649 main.addStatement( " printf( \"MAX ERROR AT %.3f s: %.4e %.4e \\n\", i*h, maxErrX, maxErrXA );\n" );
00650 }
00651 else if( PRINT_DETAILS ) {
00652 main.addStatement( " printf( \"MAX ERROR AT %.3f s: %.4e \\n\", i*h, maxErrX );\n" );
00653 }
00654 main.addStatement( " meanErrX += maxErrX;\n" );
00655 main.addStatement( " meanErrXA += maxErrXA;\n" );
00656 main.addLinebreak( );
00657 if( DERIVATIVES ) {
00658 main.addStatement( " for( j = 0; j < (ACADO_NX+ACADO_NXA)*(ACADO_NX+ACADO_NU); j++ ) {\n" );
00659 main.addStatement( " nil = fscanf( file, \"%lf\", &temp );\n" );
00660 main.addStatement( " nil = fscanf( ref, \"%lf\", &temp );\n" );
00661 main.addStatement( " }\n" );
00662 }
00663 main.addStatement( " }\n" );
00664 main.addStatement( " meanErrX = meanErrX/ACADO_N;\n" );
00665 main.addStatement( " meanErrXA = meanErrXA/ACADO_N;\n" );
00666 if( PRINT_DETAILS ) main.addStatement( " printf( \"\\n\" );\n" );
00667 if( modelData.getNXA() > 0 ) {
00668 main.addStatement( " printf( \"TOTAL MEAN ERROR: %.4e %.4e \\n\", meanErrX, meanErrXA );\n" );
00669 }
00670 else {
00671 main.addStatement( " printf( \"TOTAL MEAN ERROR: %.4e \\n\", meanErrX );\n" );
00672 }
00673 main.addStatement( " printf( \"\\n\\n\" );\n" );
00674 for( i = 0; i < (int)outputGrids.size(); i++ ) {
00675 main.addLinebreak( );
00676 main.addStatement( (std::string)" printf( \" OUTPUT FUNCTION " + toString(i+1) + ":\\n\" );\n" );
00677 main.addStatement( (std::string)" meanErr = 0;\n" );
00678 main.addStatement( (std::string)" output" + toString(i) + " = fopen(OUTPUT" + toString(i) + "_NAME,\"r\");\n" );
00679 main.addStatement( (std::string)" refOutput" + toString(i) + " = fopen(REF_OUTPUT" + toString(i) + "_NAME,\"r\");\n" );
00680 main.addLinebreak( );
00681 main.addStatement( (std::string)" for( i = 1; i <= ACADO_N*ACADO_NMEAS[" + toString(i) + "]; i++ ) {\n" );
00682 main.addStatement( (std::string)" nil = fscanf( output" + toString(i) + ", \"%lf\", &temp );\n" );
00683 main.addStatement( (std::string)" nil = fscanf( refOutput" + toString(i) + ", \"%lf\", &temp );\n" );
00684 main.addLinebreak( );
00685 main.addStatement( " maxErr = 0;\n" );
00686 main.addStatement( (std::string)" for( j = 0; j < ACADO_NOUT[" + toString(i) + "]; j++ ) {\n" );
00687 main.addStatement( (std::string)" nil = fscanf( output" + toString(i) + ", \"%lf\", &out" + toString(i) + "[j] );\n" );
00688 main.addStatement( (std::string)" nil = fscanf( refOutput" + toString(i) + ", \"%lf\", &refOut" + toString(i) + "[j] );\n" );
00689 main.addStatement( (std::string)" temp = fabs(out" + toString(i) + "[j] - refOut" + toString(i) + "[j])/fabs(refOut" + toString(i) + "[j]);\n" );
00690 main.addStatement( " if( temp > maxErr ) maxErr = temp;\n" );
00691 main.addStatement( (std::string)" if( isnan(out" + toString(i) + "[j]) ) maxErr = sqrt(-1);\n" );
00692 main.addStatement( " }\n" );
00693 main.addLinebreak( );
00694 if( PRINT_DETAILS ) main.addStatement( (std::string)" printf( \"MAX ERROR AT %.3f s: %.4e \\n\", (i-1)*step" + toString(i) + ", maxErr );\n" );
00695 main.addStatement( " meanErr += maxErr;\n" );
00696 main.addLinebreak( );
00697 if( DERIVATIVES ) {
00698 main.addStatement( (std::string)" for( j = 0; j < ACADO_NOUT[" + toString(i) + "]*(ACADO_NX+ACADO_NU); j++ ) {\n" );
00699 main.addStatement( (std::string)" nil = fscanf( output" + toString(i) + ", \"%lf\", &temp );\n" );
00700 main.addStatement( (std::string)" nil = fscanf( refOutput" + toString(i) + ", \"%lf\", &temp );\n" );
00701 main.addStatement( " }\n" );
00702 }
00703 main.addStatement( " }\n" );
00704 main.addStatement( (std::string)" meanErr = meanErr/(ACADO_N*ACADO_NMEAS[" + toString(i) + "]);\n" );
00705 if( PRINT_DETAILS ) main.addStatement( " printf( \"\\n\" );\n" );
00706 main.addStatement( " printf( \"TOTAL MEAN ERROR: %.4e \\n\", meanErr );\n" );
00707 main.addStatement( " printf( \"\\n\\n\" );\n" );
00708 }
00709 main.addLinebreak( );
00710 main.addStatement( " return 0;\n" );
00711 main.addStatement( "}\n" );
00712
00713 return main.exportCode( );
00714 }
00715
00716
00717
00718 returnValue SIMexport::exportAndRun( const std::string& dirName,
00719 const std::string& initStates,
00720 const std::string& controls,
00721 const std::string& results,
00722 const std::string& ref
00723 )
00724 {
00725 std::string test( "acado_test.c" );
00726 set( GENERATE_TEST_FILE, 1 );
00727
00728 Grid integrationGrid;
00729 modelData.getIntegrationGrid(integrationGrid);
00730 std::vector<Grid> outputGrids;
00731 modelData.getOutputGrids(outputGrids);
00732
00733 int measGrid;
00734 get( MEASUREMENT_GRID, measGrid );
00735 if( (MeasurementGrid)measGrid == ONLINE_GRID ) return ACADOERROR( RET_INVALID_OPTION );
00736
00737 _initStates = initStates;
00738 _controls = controls;
00739 _results = results;
00740 _ref = ref;
00741
00742 int numSteps;
00743 get( NUM_INTEGRATOR_STEPS, numSteps );
00744 timingCalls = (uint) ceil((double)(timingSteps*modelData.getN())/((double) numSteps) - 10.0*EPS);
00745 timingSteps = (uint) ceil((double)timingCalls*((double) numSteps/((double) modelData.getN())) - 10.0*EPS);
00746
00747 if( !referenceProvided ) {
00748
00749 set( NUM_INTEGRATOR_STEPS, (int)factorRef*numSteps );
00750 exportCode( dirName );
00751 exportTest( dirName, test, _ref, _refOutputFiles, false, 1 );
00752 executeTest( dirName );
00753 }
00754 modelData.clearIntegrationGrid();
00755
00756
00757 set( NUM_INTEGRATOR_STEPS, numSteps );
00758 exportCode( dirName );
00759 if(timingSteps > 0 && timingCalls > 0) exportTest( dirName, test, _results, _outputFiles, true, 1 );
00760 else exportTest( dirName, test, _results, _outputFiles, false, 1 );
00761 executeTest( dirName );
00762
00763
00764 int nil;
00765 nil = system( (dirName + "/./acado_compare").c_str() );
00766 nil = nil+1;
00767
00768 return SUCCESSFUL_RETURN;
00769 }
00770
00771
00772 returnValue SIMexport::exportAcadoHeader( const std::string& _dirName,
00773 const std::string& _fileName,
00774 const std::string& _realString,
00775 const std::string& _intString,
00776 int _precision
00777 ) const
00778 {
00779 string moduleName;
00780 get(CG_MODULE_NAME, moduleName);
00781
00782 int qpSolver;
00783 get(QP_SOLVER, qpSolver);
00784
00785 int useSinglePrecision;
00786 get(USE_SINGLE_PRECISION, useSinglePrecision);
00787
00788 string fileName;
00789 fileName = _dirName + "/" + _fileName;
00790
00791
00792 map<string, pair<string, string> > options;
00793
00794 DVector nMeasV = getNumMeas();
00795 DVector nOutV = getDimOutputs();
00796
00797 options[ "ACADO_N" ] = make_pair(toString( getN() ), "Number of control/estimation intervals.");
00798 options[ "ACADO_NX" ] = make_pair(toString( getNX() ), "Number of differential variables.");
00799 options[ "ACADO_NXD" ] = make_pair(toString( getNDX() ), "Number of differential derivative variables.");
00800 options[ "ACADO_NXA" ] = make_pair(toString( getNXA() ), "Number of algebraic variables.");
00801 options[ "ACADO_NU" ] = make_pair(toString( getNU() ), "Number of control variables.");
00802 options[ "ACADO_NOD" ] = make_pair(toString( getNOD() ), "Number of online data values.");
00803 options[ "ACADO_NUMOUT" ] = make_pair(toString( nOutV.getDim() ), "Number of output functions.");
00804
00805 if( !nMeasV.isEmpty() && !nOutV.isEmpty() ) {
00806 std::ostringstream acado_nout;
00807 ExportVariable( "ACADO_NOUT",nOutV,STATIC_CONST_INT ).exportDataDeclaration(acado_nout);
00808 std::ostringstream acado_nmeas;
00809 ExportVariable( "ACADO_NMEAS",nMeasV,STATIC_CONST_INT ).exportDataDeclaration(acado_nmeas);
00810 options[ "ACADO_OUTPUTS_DEFINED" ] = make_pair("\n" + acado_nout.str() + acado_nmeas.str(), "Dimension and measurements of the output functions per shooting interval.");
00811 }
00812
00813
00814
00815
00816 ExportStatementBlock variablesBlock;
00817 stringstream variables;
00818
00819 if (collectDataDeclarations(variablesBlock, ACADO_VARIABLES) != SUCCESSFUL_RETURN)
00820 return ACADOERROR( RET_UNABLE_TO_EXPORT_CODE );
00821 variablesBlock.exportCode(variables, _realString, _intString, _precision);
00822
00823 ExportStatementBlock workspaceBlock;
00824 stringstream workspace;
00825
00826 if (collectDataDeclarations(workspaceBlock, ACADO_WORKSPACE) != SUCCESSFUL_RETURN)
00827 return ACADOERROR( RET_UNABLE_TO_EXPORT_CODE );
00828 workspaceBlock.exportCode(workspace, _realString, _intString, _precision);
00829
00830 ExportStatementBlock functionsBlock;
00831 stringstream functions;
00832
00833 if (collectFunctionDeclarations( functionsBlock ) != SUCCESSFUL_RETURN)
00834 return ACADOERROR( RET_UNABLE_TO_EXPORT_CODE );
00835 functionsBlock.exportCode(functions, _realString);
00836
00837 ExportCommonHeader ech(fileName, "", _realString, _intString, _precision);
00838 ech.configure( moduleName, useSinglePrecision, (QPSolverName)qpSolver,
00839 options, variables.str(), workspace.str(), functions.str());
00840
00841 return ech.exportCode();
00842 }
00843
00844
00845 returnValue SIMexport::exportMakefile( const std::string& _dirName,
00846 const std::string& _fileName,
00847 const std::string& _realString,
00848 const std::string& _intString,
00849 int _precision
00850 ) const
00851 {
00852 std::string fileName( _dirName );
00853 fileName += "/" + _fileName;
00854
00855 acadoCopyTemplateFile(MAKEFILE_INTEGRATOR, fileName, "#", true);
00856
00857 return SUCCESSFUL_RETURN;
00858 }
00859
00860
00861 returnValue SIMexport::setReference( const std::string& reference, const std::vector<std::string>& outputReference ) {
00862 if( hasOutputs() && outputReference.size() == 0 ) {
00863 referenceProvided = false;
00864 return RET_UNABLE_TO_EXPORT_CODE;
00865 }
00866 referenceProvided = true;
00867 _ref = reference;
00868 if( outputReference.size() > 0 ) _refOutputFiles = outputReference;
00869
00870 return SUCCESSFUL_RETURN;
00871 }
00872
00873
00874 returnValue SIMexport::setTimingSteps( uint _timingSteps ) {
00875 timingSteps = _timingSteps;
00876
00877 return SUCCESSFUL_RETURN;
00878 }
00879
00880
00881 returnValue SIMexport::printDetails( bool details ) {
00882 PRINT_DETAILS = details;
00883
00884 return SUCCESSFUL_RETURN;
00885 }
00886
00887
00888 returnValue SIMexport::executeTest( const std::string& _dirName ) {
00889
00890 int nil;
00891 nil = system((string("make clean -s -C ") + _dirName).c_str());
00892 nil = system((string("make -s -C ") + _dirName).c_str());
00893 nil = system((_dirName + "/./acado_test").c_str());
00894 nil = nil+1;
00895
00896 return SUCCESSFUL_RETURN;
00897 }
00898
00899 returnValue SIMexport::setTimingCalls( uint _timingCalls ) {
00900 timingCalls = _timingCalls;
00901
00902 return SUCCESSFUL_RETURN;
00903 }
00904
00905
00906 CLOSE_NAMESPACE_ACADO
00907
00908