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
00035 #include <acado/simulation_environment/simulation_environment.hpp>
00036
00037 #ifdef WIN32
00038 #define round( value ) floor( value + 0.5 )
00039 #endif
00040
00041
00042
00043
00044 using namespace std;
00045
00046 BEGIN_NAMESPACE_ACADO
00047
00048
00049 SimulationEnvironment::SimulationEnvironment( ) : SimulationBlock( BN_SIMULATION_ENVIRONMENT )
00050 {
00051 setupOptions( );
00052 setupLogging( );
00053
00054 startTime = 0.0;
00055 endTime = 0.0;
00056
00057 process = 0;
00058 controller = 0;
00059
00060 nSteps = 0;
00061
00062 setStatus( BS_NOT_INITIALIZED );
00063 }
00064
00065
00066 SimulationEnvironment::SimulationEnvironment( double _startTime,
00067 double _endTime,
00068 Process& _process,
00069 Controller& _controller
00070 ) : SimulationBlock( BN_SIMULATION_ENVIRONMENT )
00071 {
00072 setupOptions( );
00073 setupLogging( );
00074
00075 startTime = _startTime;
00076 endTime = _endTime;
00077
00078 if ( _process.isDefined( ) == BT_TRUE )
00079 {
00080 process = &_process;
00081 setStatus( BS_NOT_INITIALIZED );
00082 }
00083 else
00084 process = 0;
00085
00086 if ( _controller.isDefined( ) == BT_TRUE )
00087 controller = &_controller;
00088 else
00089 controller = 0;
00090
00091 nSteps = 0;
00092 }
00093
00094
00095 SimulationEnvironment::SimulationEnvironment( const SimulationEnvironment &rhs ) : SimulationBlock( rhs )
00096 {
00097 startTime = rhs.startTime;
00098 endTime = rhs.endTime;
00099
00100 if ( rhs.process != 0 )
00101 process = rhs.process;
00102 else
00103 process = 0;
00104
00105 if ( rhs.controller != 0 )
00106 controller = rhs.controller;
00107 else
00108 controller = 0;
00109
00110 simulationClock = rhs.simulationClock;
00111
00112 processOutput = rhs.processOutput;
00113 feedbackControl = rhs.feedbackControl;
00114 feedbackParameter = rhs.feedbackParameter;
00115
00116 nSteps = rhs.nSteps;
00117 }
00118
00119
00120 SimulationEnvironment::~SimulationEnvironment( )
00121 {
00122 }
00123
00124
00125 SimulationEnvironment& SimulationEnvironment::operator=( const SimulationEnvironment &rhs )
00126 {
00127 if( this != &rhs )
00128 {
00129 SimulationBlock::operator=( rhs );
00130
00131 startTime = rhs.startTime;
00132 endTime = rhs.endTime;
00133
00134 if ( rhs.process != 0 )
00135 process = rhs.process;
00136 else
00137 process = 0;
00138
00139 if ( rhs.controller != 0 )
00140 controller = rhs.controller;
00141 else
00142 controller = 0;
00143
00144 simulationClock = rhs.simulationClock;
00145
00146 processOutput = rhs.processOutput;
00147 feedbackControl = rhs.feedbackControl;
00148 feedbackParameter = rhs.feedbackParameter;
00149
00150 nSteps = rhs.nSteps;
00151 }
00152
00153 return *this;
00154 }
00155
00156
00157
00158 returnValue SimulationEnvironment::setProcess( Process& _process
00159 )
00160 {
00161 if ( _process.isDefined( ) == BT_TRUE )
00162 {
00163 if ( process == 0 )
00164 process = &_process;
00165 else
00166 *process = _process;
00167 }
00168
00169 if ( _process.isDefined( ) == BT_TRUE )
00170 setStatus( BS_NOT_INITIALIZED );
00171
00172 return SUCCESSFUL_RETURN;
00173 }
00174
00175
00176 returnValue SimulationEnvironment::setController( Controller& _controller
00177 )
00178 {
00179 if ( _controller.isDefined( ) == BT_TRUE )
00180 {
00181 if ( controller == 0 )
00182 controller = &_controller;
00183 else
00184 *controller = _controller;
00185 }
00186
00187 if ( getStatus( ) > BS_NOT_INITIALIZED )
00188 setStatus( BS_NOT_INITIALIZED );
00189
00190 return SUCCESSFUL_RETURN;
00191 }
00192
00193
00194
00195 returnValue SimulationEnvironment::initializeAlgebraicStates( const VariablesGrid& _xa_init )
00196 {
00197 if ( controller != 0 )
00198 controller->initializeAlgebraicStates( _xa_init );
00199
00200 if ( process != 0 )
00201 process->initializeAlgebraicStates( _xa_init.getVector(0) );
00202
00203 return SUCCESSFUL_RETURN;
00204 }
00205
00206
00207 returnValue SimulationEnvironment::initializeAlgebraicStates( const char* fileName )
00208 {
00209 VariablesGrid tmp;
00210 tmp.read( fileName );
00211
00212 if ( tmp.isEmpty( ) == BT_TRUE )
00213 return ACADOERROR( RET_FILE_CAN_NOT_BE_OPENED );
00214
00215 return initializeAlgebraicStates( tmp );
00216 }
00217
00218
00219
00220 returnValue SimulationEnvironment::init( const DVector &x0_,
00221 const DVector &p_
00222 )
00223 {
00224 int printLevel;
00225 get( PRINTLEVEL,printLevel );
00226
00227
00228 DVector uStart, pStart;
00229 VariablesGrid yStart;
00230
00231 if ( controller != 0 )
00232 {
00233 if ( (PrintLevel)printLevel >= HIGH )
00234 cout << "--> Initializing controller ...\n";
00235
00236 if ( controller->init( startTime,x0_,p_ ) != SUCCESSFUL_RETURN )
00237 return ACADOERROR( RET_ENVIRONMENT_INIT_FAILED );
00238
00239 if ( controller->getU( uStart ) != SUCCESSFUL_RETURN )
00240 return ACADOERROR( RET_ENVIRONMENT_INIT_FAILED );
00241
00242 if ( controller->getP( pStart ) != SUCCESSFUL_RETURN )
00243 return ACADOERROR( RET_ENVIRONMENT_INIT_FAILED );
00244
00245 if ( (PrintLevel)printLevel >= HIGH )
00246 cout << "<-- Initializing controller done.\n";
00247 }
00248 else
00249 return ACADOERROR( RET_NO_CONTROLLER_SPECIFIED );
00250
00251
00252 if ( process != 0 )
00253 {
00254 if ( (PrintLevel)printLevel >= HIGH )
00255 cout << "--> Initializing process ...\n";
00256
00257 if ( process->init( startTime,x0_,uStart,pStart ) != SUCCESSFUL_RETURN )
00258 return ACADOERROR( RET_ENVIRONMENT_INIT_FAILED );
00259
00260 if ( process->getY( yStart ) != SUCCESSFUL_RETURN )
00261 return ACADOERROR( RET_ENVIRONMENT_INIT_FAILED );
00262
00263 if ( (PrintLevel)printLevel >= HIGH )
00264 cout << "<-- Initializing process done.\n";
00265 }
00266 else
00267 return ACADOERROR( RET_NO_PROCESS_SPECIFIED );
00268
00269 simulationClock.init( startTime );
00270
00271
00272
00273 if ( ( process != 0 ) && ( controller != 0 ) )
00274 {
00275 if ( process->getNY( ) != controller->getNY( ) )
00276 return ACADOERROR( RET_BLOCK_DIMENSION_MISMATCH );
00277
00278
00279
00280 if ( process->getNU( ) != controller->getNU( ) )
00281 return ACADOERROR( RET_BLOCK_DIMENSION_MISMATCH );
00282
00283 if ( process->getNP( ) > controller->getNP( ) )
00284 return ACADOERROR( RET_BLOCK_DIMENSION_MISMATCH );
00285 }
00286
00287
00288
00289 if ( getNU( ) > 0 )
00290 feedbackControl. add( startTime-10.0*EPS,startTime,uStart );
00291
00292 if ( getNP( ) > 0 )
00293 feedbackParameter.add( startTime-10.0*EPS,startTime,pStart );
00294 if ( getNY( ) > 0 )
00295 processOutput. add( startTime-10.0*EPS,startTime,yStart.getVector(0) );
00296
00297
00298 setStatus( BS_READY );
00299 return SUCCESSFUL_RETURN;
00300 }
00301
00302
00303
00304 returnValue SimulationEnvironment::step( )
00305 {
00306
00307 if ( getStatus( ) != BS_READY )
00308 return ACADOERROR( RET_BLOCK_NOT_READY );
00309
00310
00311 ++nSteps;
00312 printf( "\n*** SIMULATION LOOP NO. %d (starting at time %.3f) ***\n",nSteps,simulationClock.getTime( ) );
00313
00314
00315 DVector u, p;
00316 DVector uPrevious, pPrevious;
00317
00318 if ( getNU( ) > 0 )
00319 feedbackControl.evaluate( simulationClock.getTime( ),uPrevious );
00320
00321 if ( getNP( ) > 0 )
00322 feedbackParameter.evaluate( simulationClock.getTime( ),pPrevious );
00323
00324 VariablesGrid y;
00325 DVector yPrevious;
00326
00327 if ( getNY( ) > 0 )
00328 processOutput.evaluate( simulationClock.getTime( ),yPrevious );
00329
00330
00331
00332
00333
00334 int printLevel;
00335 get( PRINTLEVEL,printLevel );
00336
00337 if ( (PrintLevel)printLevel >= HIGH )
00338 cout << "--> Calling controller ...\n";
00339
00340
00341
00342 if ( controller->step( simulationClock.getTime( ),yPrevious ) != SUCCESSFUL_RETURN )
00343 return ACADOERROR( RET_ENVIRONMENT_STEP_FAILED );
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 if ( (PrintLevel)printLevel >= HIGH )
00354 cout << "<-- Calling controller done.\n";
00355
00356 double compDelay = determineComputationalDelay( controller->getPreviousRealRuntime( ) );
00357 double nextSamplingInstant = controller->getNextSamplingInstant( simulationClock.getTime( ) );
00358 nextSamplingInstant = round( nextSamplingInstant * 1.0e6 ) / 1.0e6;
00359
00360
00361 if ( controller->getU( u ) != SUCCESSFUL_RETURN )
00362 return ACADOERROR( RET_ENVIRONMENT_STEP_FAILED );
00363
00364 #ifdef SIM_DEBUG
00365 uPrevious.print("previous u(0)");
00366 u.print("u(0) from controller");
00367 #endif
00368
00369 if ( controller->getP( p ) != SUCCESSFUL_RETURN )
00370 return ACADOERROR( RET_ENVIRONMENT_STEP_FAILED );
00371
00372 if ( acadoIsEqual( simulationClock.getTime( ),endTime ) == BT_TRUE )
00373 {
00374 simulationClock.init( nextSamplingInstant );
00375 return SUCCESSFUL_RETURN;
00376 }
00377
00378 if ( (PrintLevel)printLevel >= HIGH )
00379 cout << "--> Simulating process ...\n";
00380
00381 if ( fabs( compDelay ) < 100.0*EPS )
00382 {
00383
00384
00385
00386 if ( process->step( simulationClock.getTime( ),nextSamplingInstant,u,p ) != SUCCESSFUL_RETURN )
00387 return ACADOERROR( RET_ENVIRONMENT_STEP_FAILED );
00388
00389
00390 if ( process->getY( y ) != SUCCESSFUL_RETURN )
00391 return ACADOERROR( RET_ENVIRONMENT_STEP_FAILED );
00392
00393
00394
00395
00396
00397
00398
00399
00400 if ( getNU( ) > 0 )
00401 feedbackControl. add( simulationClock.getTime( ),nextSamplingInstant,u );
00402 if ( getNP( ) > 0 )
00403 feedbackParameter.add( simulationClock.getTime( ),nextSamplingInstant,p );
00404 if ( getNY( ) > 0 )
00405 processOutput. add( y,IM_LINEAR );
00406 }
00407 else
00408 {
00409
00410 if ( simulationClock.getTime( )+compDelay > nextSamplingInstant )
00411 return ACADOERROR( RET_COMPUTATIONAL_DELAY_TOO_BIG );
00412
00413 Grid delayGrid( 3 );
00414 delayGrid.setTime( simulationClock.getTime( ) );
00415 delayGrid.setTime( simulationClock.getTime( )+compDelay );
00416 delayGrid.setTime( nextSamplingInstant );
00417
00418 VariablesGrid uDelayed( u.getDim( ),delayGrid,VT_CONTROL );
00419 uDelayed.setVector( 0,uPrevious );
00420 uDelayed.setVector( 1,u );
00421 uDelayed.setVector( 2,u );
00422
00423 VariablesGrid pDelayed( p.getDim( ),delayGrid,VT_PARAMETER );
00424 pDelayed.setVector( 0,pPrevious );
00425 pDelayed.setVector( 1,p );
00426 pDelayed.setVector( 2,p );
00427
00428 if ( process->step( uDelayed,pDelayed ) != SUCCESSFUL_RETURN )
00429 return ACADOERROR( RET_ENVIRONMENT_STEP_FAILED );
00430
00431
00432 if ( process->getY( y ) != SUCCESSFUL_RETURN )
00433 return ACADOERROR( RET_ENVIRONMENT_STEP_FAILED );
00434
00435
00436 if ( getNU( ) > 0 )
00437 feedbackControl. add( uDelayed,IM_CONSTANT );
00438
00439 if ( getNP( ) > 0 )
00440 feedbackParameter.add( pDelayed,IM_CONSTANT );
00441
00442 if ( getNY( ) > 0 )
00443 processOutput. add( y,IM_LINEAR );
00444 }
00445 if ( (PrintLevel)printLevel >= HIGH )
00446 cout << "<-- Simulating process done.\n";
00447
00448
00449 simulationClock.init( nextSamplingInstant );
00450
00451 return SUCCESSFUL_RETURN;
00452 }
00453
00454
00455 returnValue SimulationEnvironment::step( double nextTime
00456 )
00457 {
00458 if ( ( nextTime < startTime ) || ( nextTime > endTime ) )
00459 return ACADOERROR( RET_INVALID_ARGUMENTS );
00460
00461 while ( nextTime >= simulationClock.getTime( ) )
00462 {
00463 returnValue returnvalue = step( );
00464
00465 if ( returnvalue != SUCCESSFUL_RETURN )
00466 return returnvalue;
00467 }
00468
00469
00470
00471
00472
00473 return SUCCESSFUL_RETURN;
00474 }
00475
00476
00477 returnValue SimulationEnvironment::run( )
00478 {
00479 return step( endTime );
00480 }
00481
00482
00483
00484
00485
00486
00487 returnValue SimulationEnvironment::setupOptions( )
00488 {
00489 addOption( SIMULATE_COMPUTATIONAL_DELAY , defaultSimulateComputationalDelay );
00490 addOption( COMPUTATIONAL_DELAY_FACTOR , defaultComputationalDelayFactor );
00491 addOption( COMPUTATIONAL_DELAY_OFFSET , defaultComputationalDelayOffset );
00492 addOption( PRINTLEVEL , defaultPrintlevel );
00493
00494 return SUCCESSFUL_RETURN;
00495 }
00496
00497 returnValue SimulationEnvironment::setupLogging( )
00498 {
00499
00500
00501
00502
00503
00504
00505 return SUCCESSFUL_RETURN;
00506 }
00507
00508
00509 double SimulationEnvironment::determineComputationalDelay( double controllerRuntime
00510 ) const
00511 {
00512 int simulateComputationalDelay;
00513 get( SIMULATE_COMPUTATIONAL_DELAY,simulateComputationalDelay );
00514
00515 if ( (BooleanType)simulateComputationalDelay == BT_TRUE )
00516 {
00517 ACADOWARNING( RET_COMPUTATIONAL_DELAY_NOT_SUPPORTED );
00518 return 0.0;
00519
00520 double computationalDelayFactor, computationalDelayOffset;
00521 get( COMPUTATIONAL_DELAY_FACTOR,computationalDelayFactor );
00522 get( COMPUTATIONAL_DELAY_OFFSET,computationalDelayOffset );
00523
00524 return acadoMax( 0.0, controllerRuntime*computationalDelayFactor + computationalDelayOffset );
00525 }
00526 else
00527 return 0.0;
00528 }
00529
00530
00531
00532
00533 CLOSE_NAMESPACE_ACADO
00534
00535