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
00034 #include <acado/variables_grid/grid.hpp>
00035 #include <iomanip>
00036
00037 using namespace std;
00038
00039 BEGIN_NAMESPACE_ACADO
00040
00041
00042
00043
00044
00045
00046
00047 Grid::Grid( )
00048 {
00049 nPoints = 0;
00050 times = 0;
00051 }
00052
00053
00054 Grid::Grid( uint nPoints_,
00055 double *times_
00056 )
00057 {
00058 times = 0;
00059 init( nPoints_,times_ );
00060 }
00061
00062
00063 Grid::Grid( const DVector& times_
00064 )
00065 {
00066 times = 0;
00067 init( times_ );
00068 }
00069
00070
00071 Grid::Grid( double _firstTime,
00072 double _lastTime,
00073 uint _nPoints
00074 )
00075 {
00076 times = 0;
00077 init( _firstTime,_lastTime,_nPoints );
00078 }
00079
00080
00081
00082 Grid::Grid( const Grid& rhs )
00083 {
00084 nPoints = rhs.nPoints;
00085
00086 if ( rhs.times != 0 )
00087 {
00088 times = (double*) calloc( nPoints,sizeof(double) );
00089
00090 for( uint i=0; i<nPoints; ++i )
00091 times[i] = rhs.times[i];
00092 }
00093 else
00094 {
00095 times = 0;
00096 }
00097 }
00098
00099
00100 Grid::~Grid( )
00101 {
00102 if ( times != 0 )
00103 free( times );
00104 }
00105
00106
00107 returnValue Grid::init( uint _nPoints,
00108 const double* const _times
00109 )
00110 {
00111 nPoints = _nPoints;
00112
00113 if ( times != 0 )
00114 free( times );
00115
00116 if ( nPoints > 0 )
00117 times = (double*) calloc( nPoints,sizeof(double) );
00118 else
00119 times = 0;
00120
00121 if ( _times != 0 )
00122 {
00123 for( uint i=0; i<nPoints; ++i )
00124 times[i] = _times[i];
00125 }
00126 else
00127 {
00128 for( uint i=0; i<nPoints; ++i )
00129 times[i] = -INFTY;
00130 }
00131
00132 return SUCCESSFUL_RETURN;
00133 }
00134
00135
00136 returnValue Grid::init( const DVector& times_
00137 )
00138 {
00139 nPoints = times_.getDim();
00140
00141 if ( times != 0 )
00142 free( times );
00143
00144 if ( nPoints > 0 )
00145 times = (double*) calloc( nPoints,sizeof(double) );
00146 else
00147 times = 0;
00148
00149 for( uint i=0; i<nPoints; ++i )
00150 times[i] = times_(i);
00151
00152 return SUCCESSFUL_RETURN;
00153 }
00154
00155
00156 returnValue Grid::init( double _firstTime,
00157 double _lastTime,
00158 uint _nPoints
00159 )
00160 {
00161 nPoints = _nPoints;
00162
00163 if ( times != 0 )
00164 free( times );
00165
00166 if ( nPoints > 0 )
00167 times = (double*) calloc( nPoints,sizeof(double) );
00168 else
00169 times = 0;
00170
00171 return setupEquidistant( _firstTime,_lastTime );
00172 }
00173
00174
00175 returnValue Grid::init( const Grid& rhs
00176 )
00177 {
00178 operator=( rhs );
00179
00180 return SUCCESSFUL_RETURN;
00181 }
00182
00183
00184
00185 Grid& Grid::operator=( const Grid& rhs )
00186 {
00187 if ( this != &rhs )
00188 {
00189 if ( times != 0 )
00190 free( times );
00191
00192
00193 nPoints = rhs.nPoints;
00194
00195 if ( rhs.times != 0 )
00196 {
00197 times = (double*) calloc( nPoints,sizeof(double) );
00198
00199 for( uint i=0; i<nPoints; ++i )
00200 times[i] = rhs.times[i];
00201 }
00202 else
00203 {
00204 times = 0;
00205 }
00206 }
00207
00208 return *this;
00209 }
00210
00211
00212 Grid& Grid::operator&( const Grid& arg )
00213 {
00214 merge( arg,MM_KEEP,BT_TRUE );
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 return *this;
00290 }
00291
00292
00293 returnValue Grid::equalizeGrids( Grid& arg
00294 )
00295 {
00296 if ( *this == arg )
00297 return SUCCESSFUL_RETURN;
00298
00299
00300 *this & arg;
00301 arg = *this;
00302
00303 return SUCCESSFUL_RETURN;
00304 }
00305
00306
00307 returnValue Grid::setTime( double _time
00308 )
00309 {
00310 int idx = findNextIndex( );
00311
00312 if ( idx < 0 )
00313 return ACADOERROR( RET_GRIDPOINT_SETUP_FAILED );
00314
00315 if ( idx > 0 )
00316 {
00317 if ( acadoIsStrictlyGreater( times[idx-1] , _time ) == BT_TRUE )
00318 return ACADOERROR( RET_GRIDPOINT_HAS_INVALID_TIME );
00319 }
00320
00321 times[idx] = _time;
00322 return SUCCESSFUL_RETURN;
00323 }
00324
00325
00326 returnValue Grid::setTime( uint pointIdx,
00327 double _time
00328 )
00329 {
00330 if ( pointIdx >= getNumPoints( ) )
00331 return ACADOERROR( RET_INDEX_OUT_OF_BOUNDS );
00332
00333 times[pointIdx] = _time;
00334
00335 return SUCCESSFUL_RETURN;
00336 }
00337
00338
00339 returnValue Grid::addTime( double _time
00340 )
00341 {
00342 if ( ( getNumPoints( ) > 0 ) && ( acadoIsGreater( _time,getLastTime() ) == BT_FALSE ) )
00343 {
00344
00345 return ACADOERROR( RET_INVALID_ARGUMENTS );
00346 }
00347
00348 ++nPoints;
00349
00350 times = (double*) realloc( times,nPoints*sizeof(double) );
00351 times[nPoints-1] = _time;
00352
00353 return SUCCESSFUL_RETURN;
00354 }
00355
00356
00357
00358 returnValue Grid::merge( const Grid& arg,
00359 MergeMethod _mergeMethod,
00360 BooleanType keepOverlap
00361 )
00362 {
00363 if ( ( keepOverlap == BT_FALSE ) && ( _mergeMethod == MM_DUPLICATE ) )
00364 return ACADOERROR( RET_INVALID_ARGUMENTS );
00365
00366
00367 if ( arg.getNumPoints( ) == 0 )
00368 return SUCCESSFUL_RETURN;
00369
00370 if ( getNumPoints( ) == 0 )
00371 {
00372 *this = arg;
00373 return SUCCESSFUL_RETURN;
00374 }
00375
00376
00377
00378 Grid mergedGrid;
00379 uint j = 0;
00380 BooleanType overlapping = BT_FALSE;
00381
00382 for( uint i=0; i<getNumPoints( ); ++i )
00383 {
00384 if ( keepOverlap == BT_FALSE )
00385 overlapping = arg.isInInterval( getTime(i) );
00386
00387
00388
00389 while ( ( j < arg.getNumPoints( ) ) &&
00390 ( acadoIsStrictlySmaller( arg.getTime( j ),getTime( i ) ) == BT_TRUE ) )
00391 {
00392 if ( ( overlapping == BT_FALSE ) ||
00393 ( ( overlapping == BT_TRUE ) && ( _mergeMethod == MM_REPLACE ) ) )
00394 {
00395 mergedGrid.addTime( arg.getTime( j ) );
00396 }
00397
00398 ++j;
00399 }
00400
00401
00402 if ( acadoIsEqual( arg.getTime( j ),getTime( i ) ) == BT_TRUE )
00403 {
00404 switch ( _mergeMethod )
00405 {
00406 case MM_KEEP:
00407 mergedGrid.addTime( getTime( i ) );
00408 break;
00409
00410 case MM_REPLACE:
00411 mergedGrid.addTime( arg.getTime( j ) );
00412 break;
00413
00414 case MM_DUPLICATE:
00415 mergedGrid.addTime( getTime( i ) );
00416 mergedGrid.addTime( arg.getTime( j ) );
00417 break;
00418 }
00419 ++j;
00420 }
00421 else
00422 {
00423
00424 if ( ( overlapping == BT_FALSE ) ||
00425 ( ( overlapping == BT_TRUE ) && ( _mergeMethod == MM_KEEP ) ) )
00426 {
00427 mergedGrid.addTime( getTime( i ) );
00428 }
00429 }
00430 }
00431
00432
00433 while ( j < arg.getNumPoints( ) )
00434 {
00435 if ( acadoIsStrictlyGreater( arg.getTime(j),getLastTime() ) == BT_TRUE )
00436 mergedGrid.addTime( arg.getTime( j ) );
00437
00438 ++j;
00439 }
00440
00441
00442 *this = mergedGrid;
00443
00444 return SUCCESSFUL_RETURN;
00445 }
00446
00447
00448
00449 Grid& Grid::shiftTimes( double timeShift
00450 )
00451 {
00452 for( uint i=0; i<nPoints; ++i )
00453 times[i] += timeShift;
00454
00455 return *this;
00456 }
00457
00458
00459
00460 returnValue Grid::scaleTimes( double scaling
00461 )
00462 {
00463 if ( acadoIsStrictlyGreater( scaling,0.0 ) == BT_FALSE )
00464 {
00465 ACADOWARNING( RET_INVALID_ARGUMENTS );
00466 scaling = 1.0;
00467 }
00468
00469 for( uint i=0; i<nPoints; ++i )
00470 times[i] *= scaling;
00471
00472 return SUCCESSFUL_RETURN;
00473 }
00474
00475
00476
00477 returnValue Grid::refineGrid( uint factor
00478 )
00479 {
00480 if ( factor == 0 )
00481 return ACADOERROR( RET_INVALID_ARGUMENTS );
00482
00483
00484 if ( ( factor == 1 ) || ( getNumIntervals( ) == 0 ) )
00485 return SUCCESSFUL_RETURN;
00486
00487
00488 double* newTimes = (double*) calloc( getNumIntervals( )*factor+1,sizeof(double) );
00489
00490 for( uint i=0; i<getNumIntervals( ); ++i )
00491 for( uint j=0; j<factor; ++j )
00492 newTimes[i*factor + j] = getTime( i ) + ((double) j) / ((double) factor) * getIntervalLength( i );
00493 newTimes[ getNumIntervals( )*factor ] = getLastTime( );
00494
00495
00496 nPoints = getNumIntervals( )*factor + 1;
00497
00498 double* tmp = times;
00499 times = newTimes;
00500 free( tmp );
00501
00502 return SUCCESSFUL_RETURN;
00503 }
00504
00505
00506 returnValue Grid::coarsenGrid( uint factor
00507 )
00508 {
00509 if ( factor == 0 )
00510 return ACADOERROR( RET_INVALID_ARGUMENTS );
00511
00512
00513 if ( ( factor == 1 ) || ( getNumIntervals( ) == 0 ) )
00514 return SUCCESSFUL_RETURN;
00515
00516 return RET_NOT_YET_IMPLEMENTED;
00517 }
00518
00519
00520 BooleanType Grid::hasTime( double _time
00521 ) const
00522 {
00523 if ( findTime( _time ) < 0 )
00524 return BT_FALSE;
00525 else
00526 return BT_TRUE;
00527 }
00528
00529
00530
00531 int Grid::findTime( double _time,
00532 uint startIdx
00533 ) const
00534 {
00535 return findFirstTime( _time,startIdx );
00536 }
00537
00538
00539 int Grid::findFirstTime( double _time,
00540 uint startIdx
00541 ) const
00542 {
00543 if ( times == 0 )
00544 return -1;
00545
00546 for( uint i=startIdx; i<getNumPoints( ); ++i )
00547 {
00548 if ( acadoIsEqual( times[i] ,_time ) == BT_TRUE )
00549 return i;
00550
00551
00552 if ( times[i] > _time )
00553 return -1;
00554 }
00555
00556
00557 return -1;
00558 }
00559
00560
00561 int Grid::findLastTime( double _time,
00562 uint startIdx
00563 ) const
00564 {
00565 if ( times == 0 )
00566 return -1;
00567
00568 for( uint i=startIdx; i<getNumPoints( ); ++i )
00569 {
00570 if ( acadoIsEqual( times[i] ,_time ) == BT_TRUE )
00571 {
00572 uint j = i;
00573
00574 while( ( j<getNumPoints( ) ) && ( acadoIsEqual( times[j] , _time ) == BT_TRUE ) )
00575 {
00576 ++j;
00577 }
00578
00579 return j-1;
00580 }
00581
00582
00583 if ( times[i] > _time )
00584 return -1;
00585 }
00586
00587
00588 return -1;
00589 }
00590
00591
00592
00593 uint Grid::getFloorIndex( double time_
00594 ) const
00595 {
00596 uint lowerIdx = 0;
00597 uint upperIdx = getLastIndex( );
00598 uint idx = 0;
00599
00600
00601 if ( acadoIsGreater( getTime( lowerIdx ) , time_ ) == BT_TRUE )
00602 return lowerIdx;
00603
00604 if ( acadoIsSmaller( getTime( upperIdx ) , time_ ) == BT_TRUE )
00605 return upperIdx;
00606
00607
00608 while ( lowerIdx < upperIdx )
00609 {
00610 idx = (uint)floor( 0.5*( (double)(upperIdx + lowerIdx) ) );
00611
00612 if ( isInUpperHalfOpenInterval( idx,time_ ) == BT_TRUE )
00613 break;
00614
00615 if ( acadoIsStrictlyGreater( getTime( idx ) , time_ ) == BT_TRUE )
00616 upperIdx = idx;
00617 else
00618 lowerIdx = idx;
00619 }
00620
00621 return idx;
00622 }
00623
00624
00625 uint Grid::getCeilIndex ( double time_ ) const
00626 {
00627 uint lowerIdx = 0;
00628 uint upperIdx = getLastIndex( );
00629 uint idx = 0;
00630
00631
00632 if ( acadoIsGreater( getTime( lowerIdx ) , time_ ) == BT_TRUE )
00633 return lowerIdx;
00634
00635 if ( acadoIsSmaller( getTime( upperIdx ) , time_ ) == BT_TRUE )
00636 return upperIdx;
00637
00638
00639 while ( lowerIdx < upperIdx )
00640 {
00641 idx = (uint)ceil(0.5*( (double)( upperIdx + lowerIdx) ) );
00642
00643 if ( isInLowerHalfOpenInterval( idx,time_ ) == BT_TRUE )
00644 break;
00645
00646 if ( acadoIsGreater( getTime( idx ) , time_ ) == BT_TRUE )
00647 upperIdx = idx;
00648 else
00649 lowerIdx = idx;
00650 }
00651 return idx;
00652 }
00653
00654
00655 returnValue Grid::getSubGrid( double tStart,
00656 double tEnd,
00657 Grid& _subGrid
00658 ) const
00659 {
00660 if ( ( isInInterval( tStart ) == BT_FALSE ) ||
00661 ( isInInterval( tEnd ) == BT_FALSE ) )
00662 return ACADOERROR( RET_INVALID_ARGUMENTS );
00663
00664
00665
00666 uint nSubPoints = 0;
00667
00668 if ( hasTime( tStart ) == BT_FALSE )
00669 ++nSubPoints;
00670
00671 for( uint i=0; i<getNumPoints( ); ++i )
00672 {
00673 if ( acadoIsGreater( getTime( i ) , tStart ) == BT_TRUE &&
00674 acadoIsSmaller( getTime( i ) , tEnd ) == BT_TRUE ) ++nSubPoints;
00675 }
00676
00677 if ( hasTime( tEnd ) == BT_FALSE )
00678 ++nSubPoints;
00679
00680
00681 _subGrid.init( nSubPoints );
00682
00683 if ( hasTime( tStart ) == BT_FALSE )
00684 _subGrid.setTime( tStart );
00685
00686 for( uint i=0; i<getNumPoints( ); ++i )
00687 {
00688 if ( acadoIsGreater( getTime( i ) , tStart ) == BT_TRUE &&
00689 acadoIsSmaller( getTime( i ) , tEnd ) == BT_TRUE )
00690 _subGrid.setTime( getTime( i ) );
00691 }
00692
00693 if ( hasTime( tEnd ) == BT_FALSE )
00694 _subGrid.setTime( tEnd );
00695
00696 return SUCCESSFUL_RETURN;
00697 }
00698
00699
00700 returnValue Grid::print( ) const
00701 {
00702 for (unsigned t = 0; t < getNumPoints(); t++)
00703 cout << setprecision( 8 ) << getTime( t ) << " ";
00704 cout << endl;
00705
00706 return SUCCESSFUL_RETURN;
00707 }
00708
00709
00710
00711
00712
00713
00714
00715 returnValue Grid::setupEquidistant( double _firstTime,
00716 double _lastTime
00717 )
00718 {
00719 if ( getNumPoints( ) == 0 )
00720 return SUCCESSFUL_RETURN;
00721
00722 if ( getNumPoints( ) == 1 )
00723 {
00724 times[0] = _firstTime;
00725 return SUCCESSFUL_RETURN;
00726 }
00727
00728 if ( _firstTime > _lastTime )
00729 return ACADOERROR( RET_INVALID_ARGUMENTS );
00730
00731
00732 double horizon = _lastTime - _firstTime;
00733
00734 for( uint i=0; i<nPoints; ++i )
00735 times[i] = _firstTime + ((double) i) / ((double) getNumPoints( )-1) * horizon;
00736
00737 return SUCCESSFUL_RETURN;
00738 }
00739
00740
00741 int Grid::findNextIndex( ) const
00742 {
00743 if ( times == 0 )
00744 return -1;
00745
00746 for( uint i=0; i<getNumPoints( ); ++i )
00747 if ( times[i] < -INFTY+1.0 )
00748 return i;
00749
00750
00751 return -1;
00752 }
00753
00754
00755
00756 CLOSE_NAMESPACE_ACADO
00757
00758
00759
00760
00761