Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

WorldModelHighLevel.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2000-2003, Jelle Kok, University of Amsterdam
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007 
00008 1. Redistributions of source code must retain the above copyright notice, this
00009 list of conditions and the following disclaimer.
00010 
00011 2. Redistributions in binary form must reproduce the above copyright notice,
00012 this list of conditions and the following disclaimer in the documentation
00013 and/or other materials provided with the distribution.
00014 
00015 3. Neither the name of the University of Amsterdam nor the names of its
00016 contributors may be used to endorse or promote products derived from this
00017 software without specific prior written permission.
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00023 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00024 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00025 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00026 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00028 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 */
00030 
00049 #include<list>            // needed for list<double>
00050 #include<stdio.h>         // needed for printf
00051 #include "WorldModel.h"
00052 
00058 int WorldModel::getNrInSetInCircle( ObjectSetT set, Circle c )
00059 {
00060   double dConfThr = PS->getPlayerConfThr();
00061   int    iNr      = 0;
00062   int    iIndex;
00063 
00064   for( ObjectT o = iterateObjectStart( iIndex, set, dConfThr );
00065        o != OBJECT_ILLEGAL;
00066        o = iterateObjectNext ( iIndex, set, dConfThr ) )
00067   {
00068     if( c.isInside( getGlobalPosition( o ) ) )
00069       iNr++;
00070   }
00071   iterateObjectDone( iIndex );
00072 
00073   return iNr;
00074 }
00075 
00085 int WorldModel::getNrInSetInRectangle( ObjectSetT set, Rect *rect  )
00086 {
00087   double dConfThr = PS->getPlayerConfThr();
00088   int    iNr      = 0;
00089   int    iIndex;
00090 
00091   for( ObjectT o = iterateObjectStart( iIndex, set, dConfThr );
00092        o != OBJECT_ILLEGAL;
00093        o = iterateObjectNext ( iIndex, set, dConfThr ) )
00094   {
00095     if( rect == NULL || rect->isInside( getGlobalPosition( o ) ) )
00096       iNr++;
00097   }
00098   iterateObjectDone( iIndex );
00099   return iNr;
00100 }
00101 
00113 int WorldModel::getNrInSetInCone( ObjectSetT set, double dWidth,
00114                                       VecPosition start , VecPosition end )
00115 {
00116   double      dConfThr   = PS->getPlayerConfThr();
00117   int         iNr        = 0;
00118   int         iIndex;
00119   Line        line       = Line::makeLineFromTwoPoints( start, end );
00120   VecPosition posOnLine;
00121   VecPosition posObj;
00122 
00123   for( ObjectT o = iterateObjectStart( iIndex, set, dConfThr );
00124        o != OBJECT_ILLEGAL;
00125        o = iterateObjectNext ( iIndex, set, dConfThr ) )
00126   {
00127     posObj    = getGlobalPosition( o );
00128     posOnLine = line.getPointOnLineClosestTo( posObj );
00129     // whether posOnLine lies in cone is checked by three constraints
00130     // - does it lie in triangle (to infinity)
00131     // - lies between start and end (and thus not behind me)
00132     // - does it lie in circle
00133     if(posOnLine.getDistanceTo(posObj) < dWidth*posOnLine.getDistanceTo(start)
00134        && line.isInBetween( posOnLine, start, end )
00135        && start.getDistanceTo( posObj ) < start.getDistanceTo( end ) )
00136         iNr++;
00137   }
00138   iterateObjectDone( iIndex );
00139   return iNr;
00140 }
00141 
00142 
00145 bool WorldModel::isEmptySpace( ObjectT obj, AngDeg ang, double dDist )
00146 {
00147   if( obj == OBJECT_ILLEGAL )
00148     return false;
00149 
00150   VecPosition pos = getGlobalPosition( obj );
00151    pos += VecPosition( dDist, ang, POLAR );
00152 
00153   if( getNrInSetInCircle( OBJECT_SET_OPPONENTS, Circle( pos, dDist ) ) == 0 )
00154     return true;
00155 
00156   return false;
00157 }
00158 
00159 
00160 bool WorldModel::coordinateWith( ObjectT obj )
00161 {
00162   VecPosition pos = getGlobalPosition( obj );
00163   if( pos.getDistanceTo( getBallPos() ) < 30.0 &&
00164       pos.getX() > getBallPos().getX() - 5.0 )
00165   {
00166     
00167     if( getFastestInSetTo( OBJECT_SET_TEAMMATES, OBJECT_BALL ) ==
00168         getAgentObjectType() )
00169     {
00170       logCircle( 700, pos, 2.5 );
00171     }
00172     Log.log( 700, "coordinate with %d %f %f (%f %f)", 
00173              obj, pos.getDistanceTo( getBallPos() ),
00174              pos.getX(), getBallPos().getX(), getBallPos().getY() );
00175     return true;
00176   }
00177   
00178   return false;
00179 }
00180 
00196 ObjectT WorldModel::getClosestInSetTo( ObjectSetT set, ObjectT objTarget,
00197                                         double *dDist, double dConfThr )
00198 {
00199   if( dConfThr == -1.0 ) dConfThr      = PS->getPlayerConfThr();
00200   ObjectT     closestObject = OBJECT_ILLEGAL;
00201   double      dMinMag       = 1000.0;
00202   VecPosition v;
00203   int         iIndex;
00204 
00205   for( ObjectT o = iterateObjectStart( iIndex, set, dConfThr );
00206        o != OBJECT_ILLEGAL;
00207        o = iterateObjectNext ( iIndex, set, dConfThr ) )
00208   {
00209     if( o != objTarget )               // do not include target object
00210     {
00211       v = getGlobalPosition( objTarget ) - getGlobalPosition( o );
00212       if( v.getMagnitude() < dMinMag )
00213       {
00214         dMinMag       = v.getMagnitude();
00215         closestObject = o;
00216       }
00217     }
00218   }
00219 
00220   iterateObjectDone( iIndex );
00221   if( dDist != NULL )
00222     *dDist = dMinMag;
00223   return closestObject;
00224 }
00225 
00240 ObjectT WorldModel::getClosestInSetTo( ObjectSetT set, VecPosition pos,
00241                                        double *dDist,  double dConfThr )
00242 {
00243   ObjectT     closestObject   = OBJECT_ILLEGAL;
00244   double      dMinMag         = 1000.0;
00245   VecPosition v;
00246   int         iIndex;
00247 
00248   if( dConfThr == -1.0 ) dConfThr      = PS->getPlayerConfThr();
00249   for( ObjectT o = iterateObjectStart( iIndex, set, dConfThr );
00250        o != OBJECT_ILLEGAL;
00251        o = iterateObjectNext ( iIndex, set, dConfThr ) )
00252   {
00253     v = pos - getGlobalPosition( o );
00254     if( v.getMagnitude() < dMinMag )
00255     {
00256       dMinMag         = v.getMagnitude();
00257       closestObject   = o;
00258     }
00259   }
00260   iterateObjectDone( iIndex );
00261   if( dDist != NULL )
00262     *dDist = dMinMag;
00263   return closestObject;
00264 }
00265 
00281 ObjectT WorldModel::getClosestInSetTo( ObjectSetT set, Line l,
00282                               VecPosition pos1, VecPosition pos2,
00283                               double *dDistObjToLine, double *dDistPos1ToPoint)
00284 {
00285   VecPosition posObj;
00286   VecPosition posOnLine;
00287   double      dConfThr  = PS->getPlayerConfThr();
00288   ObjectT     obj       = OBJECT_ILLEGAL;
00289   double      dDist     ;
00290   double      dMinDist  = 1000.0;
00291   double      dDistPos1 = 1000.0;
00292   int         iIndex;
00293 
00294   for( ObjectT o = iterateObjectStart( iIndex, set, dConfThr );
00295        o != OBJECT_ILLEGAL;
00296        o = iterateObjectNext ( iIndex, set, dConfThr ) )
00297   {
00298     posObj    = getGlobalPosition( o );
00299     posOnLine = l.getPointOnLineClosestTo( posObj );
00300     dDist     = posObj.getDistanceTo( posOnLine );
00301     if( l.isInBetween( posOnLine, pos1, pos2 ) && dDist < dMinDist )
00302     {
00303       dMinDist  = dDist;
00304       obj       = o;
00305       dDistPos1 = pos1.getDistanceTo( posOnLine );
00306     }
00307   }
00308   iterateObjectDone( iIndex );
00309   if( dDistObjToLine != NULL )
00310     *dDistObjToLine = dMinDist;
00311   if( dDistPos1ToPoint != NULL )
00312     *dDistPos1ToPoint = dDistPos1;
00313 
00314   return obj;
00315 }
00316 
00323 ObjectT WorldModel::getClosestRelativeInSet( ObjectSetT set, double *dDist )
00324 {
00325   ObjectT     closestObject = OBJECT_ILLEGAL;
00326   double      dMinMag       = 1000.0;
00327   int         iIndex;
00328 
00329   for( ObjectT o = iterateObjectStart( iIndex, set, 1.0 );
00330        o != OBJECT_ILLEGAL;
00331        o = iterateObjectNext ( iIndex, set, 1.0 ) )
00332   {
00333     if( getRelativeDistance( o ) < dMinMag )
00334     {
00335       dMinMag       = getRelativeDistance( o );
00336       closestObject = o;
00337     }
00338   }
00339 
00340   iterateObjectDone( iIndex );
00341   if( dDist != NULL )
00342     *dDist = dMinMag;
00343   return closestObject;
00344 }
00345 
00356 ObjectT WorldModel::getSecondClosestInSetTo ( ObjectSetT set, ObjectT obj,
00357                                               double *dDist,  double dConfThr )
00358 {
00359   VecPosition v;
00360   ObjectT     closestObject       = OBJECT_ILLEGAL;
00361   ObjectT     secondClosestObject = OBJECT_ILLEGAL;
00362   double      dMinMag             = 1000.0;
00363   double      dSecondMinMag       = 1000.0;
00364   int         iIndex;
00365 
00366   if( dConfThr == -1.0 ) dConfThr = PS->getPlayerConfThr();
00367 
00368   for( ObjectT o = iterateObjectStart( iIndex, set, dConfThr );
00369        o != OBJECT_ILLEGAL;
00370        o = iterateObjectNext ( iIndex, set, dConfThr ) )
00371   {
00372     if( o != obj )
00373     {
00374       v = getGlobalPosition( obj ) - getGlobalPosition( o );
00375       if( v.getMagnitude() < dMinMag )                  // closer then first
00376       {
00377         dSecondMinMag         = dMinMag;                // put first to second
00378         secondClosestObject   = closestObject;
00379         dMinMag               = v.getMagnitude();       // and this to first
00380         closestObject         = o;
00381       }
00382       else if( v.getMagnitude() < dSecondMinMag )       // between 1st and 2nd
00383       {
00384         dSecondMinMag         = v.getMagnitude();       // put this to second
00385         secondClosestObject   = o;
00386       }
00387     }
00388   }
00389   iterateObjectDone( iIndex );
00390   if( dDist != NULL )
00391     *dDist = dSecondMinMag;
00392   return secondClosestObject;
00393 }
00394 
00401 ObjectT WorldModel::getSecondClosestRelativeInSet( ObjectSetT set, 
00402                                                    double *dDist )
00403 {
00404   ObjectT     closestObject       = OBJECT_ILLEGAL;
00405   ObjectT     secondClosestObject = OBJECT_ILLEGAL;
00406   double      dMinMag             = 1000.0;
00407   double      dSecondMinMag       = 1000.0;
00408   double      d;
00409   int         iIndex;
00410 
00411   for( ObjectT o = iterateObjectStart( iIndex, set, 1.0 );
00412        o != OBJECT_ILLEGAL;
00413        o = iterateObjectNext ( iIndex, set, 1.0 ) )
00414   {
00415     d = getRelativeDistance( o );
00416     if( d < dMinMag )                                 // closer then first
00417     {
00418       dSecondMinMag         = dMinMag;                // put first to second
00419       secondClosestObject   = closestObject;
00420       dMinMag               = d;                      // and this to first
00421       closestObject         = o;
00422     }
00423     else if( d < dSecondMinMag )                      // between first and 2nd
00424     {
00425       dSecondMinMag         = d;                      // put this to second
00426       secondClosestObject   = o;
00427     }
00428   }
00429   iterateObjectDone( iIndex );
00430   if( dDist != NULL )
00431     *dDist = dSecondMinMag;
00432   return secondClosestObject;
00433 }
00434 
00435 
00447 ObjectT WorldModel::getFurthestInSetTo( ObjectSetT set, ObjectT objTarget,
00448                                         double *dDist, double dConfThr )
00449 {
00450   if( dConfThr == -1.0 ) dConfThr      = PS->getPlayerConfThr();
00451 
00452   ObjectT     furthestObject = OBJECT_ILLEGAL;
00453   double      dMaxMag       = -1000.0;
00454   VecPosition v;
00455   int         iIndex;
00456 
00457   for( ObjectT o = iterateObjectStart( iIndex, set, dConfThr );
00458        o != OBJECT_ILLEGAL;
00459        o = iterateObjectNext ( iIndex, set, dConfThr ) )
00460   {
00461     if( o != objTarget )
00462     {
00463       v = getGlobalPosition( objTarget ) - getGlobalPosition( o );
00464       if( v.getMagnitude() > dMaxMag )
00465       {
00466         dMaxMag        = v.getMagnitude();
00467         furthestObject = o;
00468       }
00469     }
00470   }
00471   iterateObjectDone( iIndex );
00472   if( dDist != NULL )
00473     *dDist = dMaxMag;
00474   return furthestObject;
00475 }
00476 
00483 ObjectT WorldModel::getFurthestRelativeInSet( ObjectSetT set, double *dDist  )
00484 {
00485   ObjectT     furthestObject = OBJECT_ILLEGAL;
00486   double      dMaxMag       = -1000.0;
00487   int         iIndex;
00488 
00489   for( ObjectT o = iterateObjectStart( iIndex, set, 1.0 );
00490        o != OBJECT_ILLEGAL;
00491        o = iterateObjectNext ( iIndex, set, 1.0 ) )
00492   {
00493     if( getRelativeDistance( o ) > dMaxMag )
00494     {
00495       dMaxMag        = getRelativeDistance( o );
00496       furthestObject = o;
00497     }
00498   }
00499   iterateObjectDone( iIndex );
00500   if( dDist != NULL )
00501     *dDist = dMaxMag;
00502   return furthestObject;
00503 }
00504 
00505 
00506 VecPosition WorldModel::getPosClosestOpponentTo( double *dDist, ObjectT o )
00507 {
00508   if( o == OBJECT_ILLEGAL )
00509     o = getAgentObjectType();
00510   ObjectT objOpp = getClosestInSetTo( OBJECT_SET_OPPONENTS, o, dDist );
00511   if( objOpp == OBJECT_ILLEGAL )
00512     return VecPosition( UnknownDoubleValue, UnknownDoubleValue );
00513     
00514   return getGlobalPosition( objOpp );
00515 }
00516 
00517 double WorldModel::getMaxTraveledDistance( ObjectT o )
00518 {
00519   return (getCurrentTime() - getTimeLastSeen( o ) )*SS->getPlayerSpeedMax();
00520 }
00521 
00522 
00523 void WorldModel::createInterceptFeatures( )
00524 {
00525   static int count = 0;
00526   static Time timeLastCalled(0,0);
00527   
00528   if( timeLastCalled == getTimeLastSenseMessage() )
00529     count++;
00530   else
00531     count = 0;
00532     
00533   if( count > 4 )
00534     cerr << getPlayerNumber() << " called createIntercept too often: " << 
00535        count << endl;
00536   // we check all possible next positions of the ball and see
00537   // whether a player (opponent or teammate) can reach the ball at that point
00538   // if so, we log this as a feature. We finish when all features have been
00539   // found.
00540   ObjectSetT      set = OBJECT_SET_PLAYERS;
00541   int             iCycles       = -1;
00542   int             iMinCyclesTeam    = 100;
00543   int             iMinCyclesOpp     = 100;
00544   bool            bOnlyMe           = false;
00545 
00546   VecPosition     posObj;
00547   int             iIndex;
00548   int             iCyclesToObj  ;
00549 
00550   // no feature available, calculate information
00551   ObjectT         objFastestTeam             = OBJECT_ILLEGAL;
00552   ObjectT         objFastestTeamNoGoalie     = OBJECT_ILLEGAL;
00553   ObjectT         objFastestOpp              = OBJECT_ILLEGAL;
00554   ObjectT         objFastestPlayer           = OBJECT_ILLEGAL;
00555 
00556   int             iCyclesFastestPlayer       = -1;
00557   int             iCyclesFastestTeam         = -1;
00558   int             iCyclesFastestTeamNoGoalie = -1;
00559   int             iCyclesFastestOpp          = -1;
00560   int             iCyclesFastestMe           = -1;
00561 
00562   bool            bFinishedPlayer            = false;
00563   bool            bFinishedTeammates         = false;
00564   bool            bFinishedTeammatesNoGoalie = false;
00565   bool            bFinishedOpponents         = false;
00566   bool            bFinishedMe                = false;
00567   bool            bFinished                  = false;
00568 
00569   ObjectT         objLog                     = OBJECT_ILLEGAL;
00570   int             iCyclesLog                 = -1;
00571   FeatureT        featLog                    = FEATURE_ILLEGAL;
00572 
00573   // for each next position of the ball
00574   while( bFinished == false && iCycles <= PS->getPlayerWhenToIntercept() )
00575   {
00576     iCycles++;
00577     iMinCyclesTeam = 100;
00578     iMinCyclesOpp  = 100;
00579     Log.log( 460, "fastest loop: %d", iCycles );
00580 
00581     // determine its position and traverse all players to check the teammate
00582     // and opponent who can reach it first
00583     posObj     = predictPosAfterNrCycles( OBJECT_BALL, iCycles );
00584     for( ObjectT o = iterateObjectStart( iIndex, set );
00585        o != OBJECT_ILLEGAL;
00586        o = iterateObjectNext ( iIndex, set ) )
00587     {
00588       if( getGlobalPosition(o).getDistanceTo(posObj)/SS->getPlayerSpeedMax()
00589           < iCycles + 1 && (bOnlyMe == false || SoccerTypes::isOpponent( o )
00590           || o == getAgentObjectType() ) )
00591       {
00592         Log.log( 460, "call predictNrCyclesToPoint %d %d %d",
00593                        iCycles, iMinCyclesTeam, iMinCyclesOpp );
00594         iCyclesToObj = predictNrCyclesToPoint( o, posObj );
00595 
00596         if( iCyclesToObj < iMinCyclesOpp && SoccerTypes::isOpponent( o ) )
00597         {
00598           iMinCyclesOpp = iCyclesToObj;
00599           objFastestOpp = o;
00600         }
00601         if( iCyclesToObj < iMinCyclesTeam && SoccerTypes::isTeammate( o ) )
00602         {
00603           iMinCyclesTeam = iCyclesToObj;
00604           objFastestTeam = o;
00605         }
00606       }
00607     }
00608     iterateObjectDone( iIndex );
00609 
00610     bool bContinue = true;
00611     bool bLastCall = ( iCycles == PS->getPlayerWhenToIntercept() );
00612     // log all features that have been solved
00613     while( bContinue )
00614     {
00615       featLog = FEATURE_ILLEGAL;
00616       if( bLastCall )
00617         iCycles = 100;
00618 
00619       // if player not set yet and either team or opp is smaller than iCycles
00620       // set fastest player
00621       if( bFinishedPlayer == false &&
00622           ( min( iMinCyclesTeam, iMinCyclesOpp ) <= iCycles 
00623             ||
00624             bLastCall == true ) )
00625       {
00626         featLog              = FEATURE_FASTEST_PLAYER_TO_BALL;
00627         iCyclesLog           = iCycles;
00628         iCyclesFastestPlayer = iCycles;
00629         objLog               = (iMinCyclesTeam<=iMinCyclesOpp) ?
00630                                     objFastestTeam : objFastestOpp;
00631         objFastestPlayer     = objLog;
00632         bFinishedPlayer      = true;
00633       }
00634       // if teammate not set yet and min cycles team smaller set it
00635       else if( bFinishedTeammates == false &&
00636                (iMinCyclesTeam <= iCycles || bFinishedOpponents == true 
00637                 || bLastCall))
00638       {
00639         if( bFinishedOpponents == true )
00640           objFastestTeam = getFastestInSetTo( OBJECT_SET_TEAMMATES, posObj,
00641                              VecPosition(0,0), 0, &iCycles );
00642         featLog            = FEATURE_FASTEST_TEAMMATE_TO_BALL;
00643         iCyclesLog         = iCycles;
00644         iCyclesFastestTeam = iCycles;
00645         objLog             = objFastestTeam;
00646         bFinishedTeammates = true;
00647       }
00648       else if( bFinishedTeammatesNoGoalie == false &&
00649          ( ( iMinCyclesTeam <= iCycles && objFastestTeam != getOwnGoalieType())
00650            || bFinishedOpponents == true || bLastCall ) )
00651       {
00652         if( bFinishedOpponents == true && objFastestTeam == getOwnGoalieType())
00653           objFastestTeam=getFastestInSetTo( OBJECT_SET_TEAMMATES_NO_GOALIE,
00654                             posObj, VecPosition(0,0), 0, &iCycles );
00655         featLog                   = FEATURE_FASTEST_TEAMMATE_TO_BALL_NO_GOALIE;
00656         iCyclesLog                 = iCycles;
00657         iCyclesFastestTeamNoGoalie = iCycles;
00658         objLog                     = objFastestTeam;
00659         objFastestTeamNoGoalie     = objFastestTeam;
00660         bFinishedTeammatesNoGoalie = true;
00661       }
00662       else if( bFinishedMe == false &&
00663         ((iMinCyclesTeam <= iCycles && objFastestTeam == getAgentObjectType())
00664         || bFinishedOpponents == true || bLastCall ) )
00665       {
00666         if( bFinishedOpponents == true && 
00667       objFastestTeam != getAgentObjectType())
00668           iCycles = predictNrCyclesToPoint( getAgentObjectType(), posObj );
00669         featLog          = FEATURE_INTERCEPT_CYCLES_ME;
00670         iCyclesLog       = iCycles;
00671         iCyclesFastestMe = iCycles;
00672         objLog           = getAgentObjectType();
00673         bFinishedMe      = true;
00674       }
00675       else if( bFinishedOpponents == false &&
00676                ( iMinCyclesOpp <= iCycles  || bLastCall ) )
00677       {
00678         featLog            = FEATURE_FASTEST_OPPONENT_TO_BALL;
00679         iCyclesLog         = iCycles;
00680         iCyclesFastestOpp  = iCycles;
00681         objLog             = objFastestOpp;
00682         bFinishedOpponents = true;
00683 
00684       }
00685       else
00686         bContinue = false;
00687 
00688       if( featLog != FEATURE_ILLEGAL )
00689       {
00690         Log.log( 460, "log feature %d object %d in %d cycles sense %d see %d",
00691           featLog, objLog, iCyclesLog,getTimeLastSenseMessage().getTime(),
00692           getTimeLastSeeMessage().getTime()  );
00693         setFeature( featLog,
00694                     Feature( getTimeLastSeeMessage(),
00695                              getTimeLastSenseMessage(),
00696                              getTimeLastHearMessage(), objLog,
00697                              getTimeLastSeeMessage().getTime() + iCyclesLog));
00698       }
00699     }
00700     bFinished = bFinishedTeammates && bFinishedTeammatesNoGoalie;
00701     if( bFinished == true )
00702       bOnlyMe = true;
00703     bFinished &= bFinishedMe ;
00704     if( bFinished == true )
00705       set = OBJECT_SET_OPPONENTS;
00706     bFinished &= bFinishedOpponents;
00707   }
00708   Log.log( 460, "creatIntercept: team %d me %d opp %d",
00709      iCyclesFastestTeamNoGoalie, iCyclesFastestMe, iCyclesFastestOpp );
00710 }
00711 
00712 
00722 ObjectT WorldModel::getFastestInSetTo( ObjectSetT set, ObjectT obj,
00723                               int *iCyclesToIntercept )
00724 {
00725   ObjectT  objFastestOpp  = OBJECT_ILLEGAL, objFastestTeam  = OBJECT_ILLEGAL;
00726   int      iCyclesFastestOpp = 30; // how much do we try
00727   int     iCyclesFastestTeam;
00728   bool  bSkip = false;
00729 
00730   FeatureT        feature_type = FEATURE_ILLEGAL;
00731   ObjectT         fastestObject = OBJECT_ILLEGAL;
00732   int             iCycles       = -1;
00733 
00734   if( obj == OBJECT_BALL )
00735   {
00736     switch( set )
00737     {
00738       case OBJECT_SET_OPPONENTS:
00739         feature_type = FEATURE_FASTEST_OPPONENT_TO_BALL;
00740         break;
00741       case OBJECT_SET_TEAMMATES:
00742         feature_type = FEATURE_FASTEST_TEAMMATE_TO_BALL;
00743         break;
00744       case OBJECT_SET_TEAMMATES_NO_GOALIE:
00745         feature_type = FEATURE_FASTEST_TEAMMATE_TO_BALL_NO_GOALIE;
00746         break;
00747       case OBJECT_SET_PLAYERS:
00748         objFastestOpp =
00749          getFastestInSetTo( OBJECT_SET_OPPONENTS, obj, &iCyclesFastestOpp);
00750         objFastestTeam =
00751          getFastestInSetTo( OBJECT_SET_TEAMMATES, obj, &iCyclesFastestTeam);
00752         if( iCyclesFastestOpp < iCyclesFastestTeam )
00753         {
00754           fastestObject = objFastestOpp;
00755           iCycles = iCyclesFastestOpp;
00756         }
00757         else
00758         {
00759           fastestObject = objFastestTeam;
00760           iCycles = iCyclesFastestTeam;
00761         }
00762         bSkip = true;
00763         feature_type = FEATURE_FASTEST_PLAYER_TO_BALL;
00764         break;
00765       default:
00766         cerr << "WorldModel::getFastestInSetTo unknown set: " << set << endl;
00767         return OBJECT_ILLEGAL;
00768     }
00769     if( isFeatureRelevant( feature_type ) )
00770     {
00771       int i = max(0,
00772              ((int)getFeature( feature_type ).getInfo() - getCurrentCycle() ));
00773       if( iCyclesToIntercept != NULL )
00774         *iCyclesToIntercept  = i;
00775       return getFeature( feature_type ).getObject();
00776     }
00777 
00778     Log.log( 460, "create intercept features" );
00779     createInterceptFeatures( );
00780     Log.log( 460, "call fastest again" );
00781     return getFastestInSetTo( set, obj, iCyclesToIntercept );
00782     if( set == OBJECT_SET_TEAMMATES || set == OBJECT_SET_TEAMMATES_NO_GOALIE )
00783       objFastestOpp =
00784          getFastestInSetTo( OBJECT_SET_OPPONENTS, obj, &iCyclesFastestOpp);
00785   }
00786 
00787   // no feature available, calculate information
00788   double          dConfThr      = PS->getPlayerConfThr();
00789   int             iCyclesToObj  ;
00790   int             iMinCycles    = 100;
00791   int             iIndex;
00792   VecPosition     posObj;
00793 
00794 
00795   while( bSkip == false &&
00796          iCycles < iMinCycles &&
00797          iCycles <= iCyclesFastestOpp )
00798   {
00799     iCycles++;
00800     iMinCycles = 100;
00801     posObj     = predictPosAfterNrCycles( obj, iCycles );
00802     Log.log( 460, "fastest loop: %d fastest_opp %d", 
00803              iCycles, iCyclesFastestOpp );
00804     for( ObjectT o = iterateObjectStart( iIndex, set, dConfThr );
00805        o != OBJECT_ILLEGAL;
00806        o = iterateObjectNext ( iIndex, set, dConfThr ) )
00807     {
00808       if( getGlobalPosition(o).getDistanceTo(posObj)/SS->getPlayerSpeedMax()
00809               < iMinCycles &&
00810           getGlobalPosition(o).getDistanceTo(posObj)/SS->getPlayerSpeedMax()
00811               < iCycles + 1 )
00812       {
00813         Log.log( 460, "call predictNrCyclesToPoint %d %d", 
00814                  iCycles,iMinCycles );
00815         iCyclesToObj = predictNrCyclesToPoint( o, posObj );
00816         if( iCyclesToObj < iMinCycles )
00817         {
00818           iMinCycles = iCyclesToObj;
00819           fastestObject = o;
00820         }
00821       }
00822     }
00823     iterateObjectDone( iIndex );
00824   }
00825   
00826   // opponent is faster and we haven't calculated who can go to the 
00827   // interception point the fastest
00828   if( fastestObject == OBJECT_ILLEGAL )
00829     fastestObject = getFastestInSetTo(set,posObj,VecPosition(0,0),0, &iCycles);
00830 
00831   if( iCyclesToIntercept != NULL )
00832     *iCyclesToIntercept  = iCycles;
00833 
00834   if( feature_type != FEATURE_ILLEGAL )
00835   {
00836     Log.log( 460, "log feature %d object %d in %d cycles sense %d see %d",
00837              feature_type, fastestObject, iCycles,getTimeLastSenseMessage().
00838              getTime(), getTimeLastSeeMessage().getTime()  );
00839     setFeature( feature_type,
00840                 Feature( getTimeLastSeeMessage(),
00841                          getTimeLastSenseMessage(), 
00842                          getTimeLastHearMessage(), fastestObject,
00843                          getTimeLastSeeMessage().getTime() + iCycles ) );
00844   }
00845 
00846   return fastestObject;
00847 }
00848 
00859 ObjectT WorldModel::getFastestInSetTo( ObjectSetT set, VecPosition pos,
00860                     VecPosition vel, double dDecay, int *iCyclesToIntercept)
00861 {
00862   double  dConfThr      = PS->getPlayerConfThr();
00863   ObjectT fastestObject = OBJECT_ILLEGAL;
00864   int     iCycles       = 0;
00865   int     iCyclesToObj  ;
00866   int     iMinCycles    = 100;
00867   int     iIndex;
00868 
00869   while( iCycles <= iMinCycles && iCycles < 100)
00870   {
00871     iCycles    = iCycles + 1  ;
00872     iMinCycles = 100;
00873     Log.log( 460, "fastest to point: %d", iCycles );
00874     for( ObjectT o = iterateObjectStart( iIndex, set, dConfThr );
00875        o != OBJECT_ILLEGAL;
00876        o = iterateObjectNext ( iIndex, set, dConfThr ) )
00877     {
00878        if( getGlobalPosition(o).getDistanceTo(pos)/SS->getPlayerSpeedMax()
00879            < iMinCycles )
00880        {
00881          iCyclesToObj = predictNrCyclesToPoint( o, pos );
00882          if( iCyclesToObj < iMinCycles )
00883          {
00884            iMinCycles    = iCyclesToObj;
00885            fastestObject = o;
00886          }
00887        }
00888     }
00889     iterateObjectDone( iIndex );
00890     pos += vel;
00891     vel *= dDecay;
00892     if( vel.getMagnitude( ) < EPSILON ) // we can quit
00893     {
00894       iCycles = iMinCycles;
00895       iMinCycles--;
00896     }
00897   }
00898   
00899   if( iCyclesToIntercept != NULL )
00900     *iCyclesToIntercept = iCycles;
00901   return fastestObject;
00902 }
00903 
00918 ObjectT WorldModel::getFirstEmptySpotInSet( ObjectSetT set, int iUnknownPlayer)
00919 {
00920   int     iIndex;
00921 
00922   for( ObjectT o = iterateObjectStart( iIndex, set,  0.0, true );
00923        o != OBJECT_ILLEGAL;
00924        o = iterateObjectNext ( iIndex, set, 0.0, true ) )
00925   {
00926     if( getConfidence( o ) <= PS->getPlayerConfThr() &&
00927         o != getAgentObjectType() )
00928       return o;
00929   }
00930   return OBJECT_ILLEGAL;
00931 }
00932 
00933 
00940 bool WorldModel::isVisible( ObjectT o )
00941 {
00942   Object *object = getObjectPtrFromType( o );
00943 
00944   if( object != NULL &&
00945       object->getTimeLastSeen() == getTimeLastSeeMessage() )
00946     return true;
00947 
00948   return false;
00949 }
00950 
00957 bool WorldModel::isBallKickable()
00958 {
00959   return getRelativeDistance( OBJECT_BALL ) < SS->getMaximalKickDist();
00960 }
00961 
00971 bool WorldModel::isBallCatchable()
00972 {
00973   return getTimeSinceLastCatch()            > SS->getCatchBanCycle()  &&
00974          getRelativeDistance( OBJECT_BALL ) <= SS->getCatchableAreaL() &&
00975          isInOwnPenaltyArea( getBallPos() );
00976 }
00977 
00987 bool WorldModel::isBallHeadingToGoal(  )
00988 {
00989   int iSide = 1;
00990 
00991   if( isPenaltyUs() || isPenaltyThem() )
00992     iSide = ( getSide() == getSidePenalty() ) ? 1 : -1;
00993 
00994   if( !isConfidenceGood( OBJECT_BALL ) ||
00995       fabs( getBallPos().getX() ) <  PENALTY_X - 5.0 )
00996   {
00997     Log.log( 553, "ball not towards goal: confidence too low" );
00998     return false;
00999   }
01000 
01001   // make line from ball heading and goal line
01002   Line l = Line::makeLineFromPositionAndAngle(getBallPos(),getBallDirection());
01003   Line l2= Line::makeLineFromTwoPoints( getPosOwnGoal(), getPosOwnGoal() +
01004                                                          VecPosition( 0, 10 ));
01005 
01006   // if intersection is outside goalwidth, not heading to goal
01007   VecPosition posIntersect = l.getIntersection( l2 );
01008   if( fabs(posIntersect.getY()) > SS->getGoalWidth()/2.0 + 3.0)
01009   {
01010     Log.log( 553, "ball not towards goal: outside goal %f",
01011        posIntersect.getY());
01012     return false;
01013   }
01014 
01015   // check whether ball will be behind goal line within 20 cycles.
01016   VecPosition pos    = getBallPos();
01017   int         iCycle = 1;
01018   while( fabs( pos.getX() ) < PITCH_LENGTH/2.0 && iCycle < 20)
01019   {
01020     pos = predictPosAfterNrCycles( OBJECT_BALL, iCycle );
01021     Log.log( 553, "predicted pos %d cycles: (%f,%f)" ,
01022       iCycle, pos.getX(), pos.getY() );
01023     iCycle ++;
01024   }
01025 
01026   return ( iCycle == 20 ) ? false : true;
01027 }
01028 
01033 bool WorldModel::isBallInOurPossesion( )
01034 {
01035   int     iCyc;
01036   ObjectT o = getFastestInSetTo( OBJECT_SET_PLAYERS, OBJECT_BALL, &iCyc );
01037 
01038   if( o == OBJECT_ILLEGAL )
01039     return false;
01040   if( SoccerTypes::isTeammate( o ) )
01041     return true;
01042   else
01043     return false;
01044 }
01045 
01048 bool WorldModel::isBallInOwnPenaltyArea( )
01049 {
01050   return isInOwnPenaltyArea( getBallPos() );
01051 }
01052 
01057 bool WorldModel::isInOwnPenaltyArea( VecPosition pos )
01058 {
01059   ObjectT     objFlag = ( getSide() == SIDE_LEFT  )
01060                               ?  OBJECT_FLAG_P_L_C
01061                               :  OBJECT_FLAG_P_R_C ;
01062 
01063   if( isPenaltyUs() || isPenaltyThem() )
01064     objFlag = ( getSidePenalty() == SIDE_LEFT ) ? OBJECT_FLAG_P_L_C 
01065                                                 : OBJECT_FLAG_P_R_C ;
01066   VecPosition posFlag =SoccerTypes::getGlobalPositionFlag( objFlag, getSide());
01067   if( fabs(pos.getX())   > fabs(posFlag.getX()) &&
01068       fabs( pos.getY() ) < PENALTY_AREA_WIDTH/2.0 )
01069     return true;
01070 
01071   return false;
01072 }
01073 
01078 bool WorldModel::isInTheirPenaltyArea( VecPosition pos )
01079 {
01080   ObjectT     objFlag = ( getSide() == SIDE_LEFT )
01081                               ?  OBJECT_FLAG_P_R_C
01082                               :  OBJECT_FLAG_P_L_C ;
01083   VecPosition posFlag = SoccerTypes::getGlobalPositionFlag( objFlag,getSide());
01084 
01085   if ( pos.getX() > posFlag.getX() &&
01086        fabs(pos.getY()) < PENALTY_AREA_WIDTH/2.0 )
01087     return true;
01088 
01089   return false;
01090 }
01091 
01100 bool WorldModel::isConfidenceGood( ObjectT o )
01101 {
01102   return getConfidence( o ) > PS->getPlayerConfThr() &&
01103          o != getAgentObjectType();
01104 }
01105 
01114 bool WorldModel::isConfidenceVeryGood( ObjectT o )
01115 {
01116   return getConfidence( o ) > PS->getPlayerHighConfThr() &&
01117          o != getAgentObjectType();
01118 }
01119 
01123 bool WorldModel::isOnside( ObjectT obj )
01124 {
01125   return getGlobalPosition( obj ).getX() < getOffsideX() - 0.5 ;
01126 }
01127 
01135 bool WorldModel::isOpponentAtAngle( AngDeg ang , double dDist )
01136 {
01137   VecPosition posAgent   = getAgentGlobalPosition();
01138   VecPosition posOpp;
01139   AngDeg      angOpp;
01140   int         iIndex;
01141 
01142   for( ObjectT o = iterateObjectStart( iIndex, OBJECT_SET_OPPONENTS );
01143        o != OBJECT_ILLEGAL;
01144        o = iterateObjectNext ( iIndex, OBJECT_SET_OPPONENTS ) )
01145   {
01146     posOpp    = getGlobalPosition( o );
01147     angOpp    = ( posOpp - posAgent ).getDirection() ;
01148     if( fabs( angOpp - ang ) < 60 &&
01149         posAgent.getDistanceTo( posOpp ) < dDist )
01150       return true;
01151     else if( fabs( angOpp - ang ) < 120 &&
01152              posAgent.getDistanceTo( posOpp ) < dDist/2.0 )
01153       return true;
01154   }
01155   iterateObjectDone( iIndex );
01156   return false;
01157 }
01158 
01165 Time WorldModel::getTimeFromConfidence( double dConf )
01166 {
01167   return getCurrentTime()-(int)((1.00-dConf)*100);
01168 }
01169 
01174 ObjectT WorldModel::getLastOpponentDefender( double *dX )
01175 {
01176   double  dHighestX = 0.0;
01177   double  dSecondX  = 0.0, x;
01178 
01179   ObjectT o, oLast = OBJECT_ILLEGAL, oSecondLast = OBJECT_ILLEGAL;
01180   for( int i = 0; i < MAX_OPPONENTS ; i ++ )
01181   {
01182     o = Opponents[i].getType();
01183     if( isConfidenceGood( o ) )
01184     {
01185       x = Opponents[i].getGlobalPosition().getX();
01186       if( x > dHighestX )         // if larger x than highest
01187       {
01188         dSecondX    = dHighestX;  // make second the previous highest
01189         dHighestX   = x;          // and this the new one
01190         oSecondLast = oLast;
01191         oLast       = o;
01192       }
01193       else if( x > dSecondX )     // if smaller than 1st  and larger than 2nd
01194       {
01195         dSecondX    = x;          // make it the second
01196         oSecondLast = o;
01197       }
01198     }
01199   }
01200   
01201   // if highest x is outside pen_area, it cannot be the goalie (unless playing
01202   // Portugal ;-) ), so assume goalie is just not seen
01203   if( dHighestX < PENALTY_X && getOppGoalieType() == OBJECT_ILLEGAL )
01204   {
01205     dSecondX    = dHighestX;
01206     oSecondLast = oLast;
01207   }
01208   if( dX != NULL )
01209     *dX = dSecondX ;
01210   return oSecondLast;
01211 }
01212 
01221 double WorldModel::getOffsideX( bool bIncludeComm )
01222 {
01223   double  x, dAgentX;
01224 
01225   getLastOpponentDefender( &dAgentX );
01226   x = getBallPos().getX();
01227   x = max( x, dAgentX );
01228   if( bIncludeComm == true && getCurrentTime() - m_timeCommOffsideX < 3 )
01229     x = max( x, m_dCommOffsideX );
01230   return x ;
01231 }
01232 
01247 VecPosition WorldModel::getOuterPositionInField( VecPosition pos, AngDeg ang,
01248                                   double dDist, bool bWithPenalty )
01249 {
01250   VecPosition posShoot;
01251 
01252   // make shooting line using position and desired direction
01253   Line lineObj     = Line::makeLineFromPositionAndAngle( pos, ang );
01254 
01255   // get intersection point between the created line and goal line
01256   Line lineLength  = Line::makeLineFromPositionAndAngle(
01257                             VecPosition( PITCH_LENGTH/2.0 - dDist, 0.0 ), 90 );
01258   posShoot         = lineObj.getIntersection( lineLength );
01259 
01260   // check whether it first crosses the penalty line
01261   Line linePenalty = Line::makeLineFromPositionAndAngle(
01262                             VecPosition( PENALTY_X - dDist, 0.0 ), 90.0 );
01263   double dPenaltyY = lineObj.getIntersection(linePenalty).getY();
01264 
01265   if( bWithPenalty && fabs(dPenaltyY) < PENALTY_AREA_WIDTH/2.0 )
01266   {
01267     if( fabs(dPenaltyY) < PENALTY_AREA_WIDTH/2.0 - 5.0 ||   // crosses inside
01268         fabs(posShoot.getY()) <  PENALTY_AREA_WIDTH/2.0 )   // or ends inside
01269       posShoot = lineObj.getIntersection( linePenalty );
01270   }
01271 
01272   // check where it crosses the side line
01273   Line lineSide = ( ang < 0 )
01274      ? Line::makeLineFromPositionAndAngle(
01275                            VecPosition( 0.0, - PITCH_WIDTH/2.0 + dDist ),0.0 )
01276      : Line::makeLineFromPositionAndAngle(
01277                            VecPosition( 0.0, + PITCH_WIDTH/2.0 - dDist ),0.0 );
01278 
01279   if( fabs(posShoot.getY()) > PITCH_WIDTH/2.0 - dDist )
01280     posShoot = lineObj.getIntersection( lineSide );
01281 
01282   return posShoot;
01283 }
01284 
01296 AngDeg WorldModel::getDirectionOfWidestAngle(VecPosition posOrg, AngDeg angMin,
01297                                AngDeg angMax, AngDeg *angLargest, double dDist)
01298 {
01299   list<double> v;
01300   list<double> v2;
01301   double       temp;
01302   int          iIndex;
01303   double       dConf  = PS->getPlayerConfThr();
01304 
01305   // add all angles of all the opponents to the list v
01306   for( ObjectT o = iterateObjectStart( iIndex, OBJECT_SET_OPPONENTS, dConf );
01307        o != OBJECT_ILLEGAL;
01308        o = iterateObjectNext ( iIndex, OBJECT_SET_OPPONENTS, dConf ) )
01309   {
01310     if( getRelativeDistance( o ) < dDist )
01311       v.push_back( (getGlobalPosition(o)-posOrg).getDirection());
01312   }
01313   iterateObjectDone( iIndex );
01314   v.sort();
01315 
01316   // if goalkeeper is spotted and he is located within the range that we want
01317   // to shoot at, make sure the angle with the goalkeeper is large enough, since
01318   // he has better intercepting capabilities than the normal players
01319 
01320   ObjectT     objGoalie = getOppGoalieType();
01321   VecPosition posGoalie = getGlobalPosition( objGoalie );
01322   AngDeg      angGoalie;
01323 
01324   if( objGoalie != OBJECT_ILLEGAL && posOrg.getX() > PITCH_LENGTH/4.0 &&
01325       posOrg.getDistanceTo( posGoalie ) < dDist )
01326   {
01327     angGoalie = ( posGoalie - posOrg ).getDirection();
01328     Log.log( 560, "direction_widest_angle: min %f max %f angGoalie %f",
01329                                                   angMin, angMax, angGoalie );
01330 
01331     if( posOrg.getY() > 0 ) // right side of the field
01332     {
01333       angGoalie = VecPosition::normalizeAngle( angGoalie - 33 );
01334       angMax    = max( angMin, min( angGoalie, angMax ) );
01335     }
01336     else
01337     {
01338       angGoalie = VecPosition::normalizeAngle( angGoalie + 33 );
01339       angMin    = min( angMax, max( angMin, angGoalie ) );
01340     }
01341     Log.log( 560, "direction_widest_angle after: %f %f", angMin, angMax );
01342   }
01343 
01344 
01345   // Create new list with only opponents from interval [angMin..angMax].
01346   // Note that opponents outside angMin and angMax can have an influence
01347   // on the largest angle between the opponents, so they should be accounted
01348   // for. To this end, a projection is defined in both angMin and angMax.
01349   // The opponent with the smallest global angle difference a to angMin
01350   // (either inside or outside the interval [angMin..angMax]) is determined
01351   // and an extra angle angMin - a is added to the list. The situation for
01352   // angMax is analogous.
01353 
01354   double absMin     = 1000;
01355   double absMax     = 1000;
01356   double angProjMin = angMin;
01357   double angProjMax = angMax;
01358   double array[MAX_OPPONENTS+2];
01359 
01360   while( v.size() > 0 )
01361   {
01362     if( fabs( v.front() - angMin ) < absMin )      // opp near angMin
01363     {
01364       absMin     = fabs( v.front() - angMin ) ;    // make angMin wider
01365       angProjMin = angMin - absMin;                // to take him into account
01366     }
01367     if( fabs( v.front() - angMax ) < absMax )      // opp near angMax
01368     {
01369       absMax     = fabs( v.front() - angMax ) ;    // make angMax wider
01370       angProjMax = angMax + absMax;                // to take him into account
01371     }
01372     if( v.front() > angMin && v.front() < angMax ) // opp in range
01373       v2.push_back( v.front() );                   // add him
01374     v.pop_front();
01375   }
01376 
01377   // make all angles relative to angProjMin which has angle 0 and set them in
01378   // the range 0..360, where the range -180..0 is moved to 180..360. Do this by
01379   // adding 360 and then subtracting 360 if value is larger than 360.
01380   v.push_back( 0 );
01381   while( v2.size() > 0 )  // for all the opponents
01382   {
01383     temp = VecPosition::normalizeAngle(v2.front()-angProjMin)+360.0;
01384     if( temp > 360 )
01385       temp -= 360;
01386     v.push_back( temp );
01387     v2.pop_front();
01388   }
01389   // add max projection.
01390   temp = VecPosition::normalizeAngle(angProjMax-angProjMin)+360.0;
01391   if( temp > 360 )
01392     temp -= 360;
01393 
01394   v.push_back( temp );
01395 
01396   // sort the list
01397   v.sort();
01398 
01399   // put all the values in an array
01400   int i = 0;
01401   while( v.size() > 0 )
01402   {
01403     array[i++] = v.front();
01404     v.pop_front();
01405   }
01406 
01407   // find the largest angle and determine the associated midpoint direction
01408   double dLargest = -1000;
01409   double d;
01410   double ang      = UnknownAngleValue;
01411   for( int j = 0; j < i - 1 ; j ++ )
01412   {
01413     d = VecPosition::normalizeAngle(( array[j+1] - array[j] )/2.0);
01414     if( d > dLargest )
01415     {
01416       ang = angProjMin + array[j] + d;
01417       ang = VecPosition::normalizeAngle( ang );
01418       dLargest = d;
01419     }
01420   }
01421 
01422   if( ang == UnknownAngleValue ) // no angle found -> get angle in between
01423   {
01424     ang = getBisectorTwoAngles( angMin, angMax );
01425     if( angLargest != NULL )
01426       *angLargest = 360;
01427   }
01428   else if( angLargest != NULL )
01429     *angLargest = dLargest;
01430 
01431   return ang;
01432 }
01433 
01435 bool WorldModel::isInField( VecPosition pos, double dMargin )
01436 {
01437   return Rect( 
01438              VecPosition( + PITCH_LENGTH/2.0 - dMargin, 
01439                           - PITCH_WIDTH/2.0  + dMargin ),
01440              VecPosition( - PITCH_LENGTH/2.0 + dMargin, 
01441                           + PITCH_WIDTH/2.0  - dMargin ) 
01442              ).isInside( pos );
01443 }
01444 
01446 bool WorldModel::isBeforeGoal( VecPosition pos )
01447 {
01448   return Rect(
01449              VecPosition( + PENALTY_X - 2,    - ( SS->getGoalWidth()/2.0 + 1)),
01450              VecPosition( + PITCH_LENGTH/2.0, + ( SS->getGoalWidth()/2.0 + 1))
01451              ).isInside( pos );
01452 }
01453 
01464 VecPosition WorldModel::getStrategicPosition( ObjectT obj, FormationT ft )
01465 {
01466   return getStrategicPosition( SoccerTypes::getIndex( obj ), ft );
01467 }
01468   
01481 VecPosition WorldModel::getStrategicPosition( int iPlayer, FormationT ft )
01482 {
01483   if( iPlayer > MAX_TEAMMATES )
01484     cerr << "WM:getStrategicPosition with player nr " << iPlayer << endl;
01485 
01486   VecPosition pos, posBall = getBallPos();
01487   bool bOwnBall = isBallInOurPossesion();
01488 
01489   // -1 is default -> get player number in formation
01490   if( iPlayer == -1 )
01491     iPlayer = formations->getPlayerInFormation();
01492 
01493   // get maximal allowed x coordinate, this is offside x coordinate
01494   double dMaxX = max( -0.5, getOffsideX() - 1.5 );
01495 
01496   if( bOwnBall && 
01497       getGlobalPosition(
01498         SoccerTypes::getTeammateObjectFromIndex(iPlayer)).getX() 
01499       < posBall.getX() )
01500     dMaxX = max( dMaxX, posBall.getX()  );
01501 
01502   // after standing offside we are not allowed to move for ball
01503   // with a goal kick of them we are not allowed to move into penalty area
01504 
01505   if( isGoalKickThem() )
01506     dMaxX = min( dMaxX, PENALTY_X - 1.0 );
01507   else if( isBeforeKickOff() )
01508     dMaxX = min( dMaxX, -2.0 );
01509   else if ( isOffsideUs() )
01510     dMaxX = posBall.getX() - 0.5;
01511 
01512   // change the ball position on which strategic position is based
01513   // depending on the different deadball situation and thus the
01514   // expected movement of the ball
01515   if( isBeforeKickOff() )
01516     posBall.setVecPosition( 0, 0 );
01517   else if( isGoalKickUs() ||
01518       getTimeSinceLastCatch(  ) < PS->getCyclesCatchWait() + 5  ||
01519       ( isFreeKickUs() && posBall.getX() < - PENALTY_X ) )
01520     posBall.setX( -PITCH_LENGTH/4 + 5.0 );
01521   else if( getConfidence( OBJECT_BALL ) < PS->getBallConfThr() )
01522     posBall.setVecPosition( 0.0, 0.0 );
01523   else if( isGoalKickThem() ||
01524            ( isFreeKickThem() && posBall.getX() > PENALTY_X ) )
01525     posBall.setX( PENALTY_X - 10.0 );
01526   else if( isFreeKickThem() )
01527     posBall.setX( posBall.getX() - 5.0 );
01528   else if( isBallInOurPossesion() && 
01529            !( isDeadBallUs() || isDeadBallThem() ) )
01530     posBall.setX( posBall.getX() + 5.0 );
01531   else if( posBall.getX() < - PENALTY_X + 5.0 )
01532     posBall = predictPosAfterNrCycles( OBJECT_BALL, 3 );
01533 
01534   // get the strategic position
01535   pos = formations->getStrategicPosition( iPlayer, posBall, dMaxX,
01536                           bOwnBall, PS->getMaxYPercentage(),
01537             ft );
01538   return pos;
01539 }
01540 
01561 VecPosition WorldModel::getMarkingPosition( VecPosition pos, double dDist, 
01562               MarkT mark)
01563 {
01564   VecPosition posBall  = getBallPos();
01565     //edictPosAfterNrCycles( OBJECT_BALL, 3 );
01566   VecPosition posGoal  = getPosOwnGoal( );
01567   if( posBall.getX() < - PITCH_LENGTH/2.0 + 10.0 )
01568     posGoal.setX( posBall.getX() + 1  );
01569   else if( posBall.getX() > -PITCH_LENGTH/3.0 )
01570   {
01571     posGoal.setX( -PITCH_LENGTH/2.0 );
01572     double dY  = posBall.getY();
01573     if( fabs( dY ) > 12 )
01574       dY += ( sign( dY ) > 0   ) -5 ? : 5 ;
01575     posGoal.setY( dY );
01576   }
01577       
01578   VecPosition posAgent = getAgentGlobalPosition();
01579   VecPosition posMark;
01580   AngDeg      ang, angToGoal, angToBall;
01581 
01582   if( mark == MARK_GOAL )                       // position in direction goal
01583   {   
01584     angToGoal = (posGoal-pos).getDirection( );    
01585     Line line = Line::makeLineFromTwoPoints( pos, posGoal );
01586 
01587     // we want to know when distance from ball to point p equals distance
01588     // from opp to point p :
01589     // d1 + d3 = sqrt(d2^2 + d3^2) > (d1+d3)^2 = d2^2 + d3^2 =>
01590     // d1^2 + 2*d1*d3 = d2^2 -> d3 = (d2^2 - d1^2 ) / 2*d1
01591     double dCalcDist;
01592     VecPosition posIntersect = line.getPointOnLineClosestTo( posAgent );
01593     double dDistAgent = posIntersect.getDistanceTo( posAgent );
01594     double dDistOpp = posIntersect.getDistanceTo( pos );
01595     dCalcDist = (dDistAgent*dDistAgent-dDistOpp*dDistOpp)/(2*dDistOpp);
01596     double dExtra = 2.0;
01597     //    if( posBall.getX() <  PENALTY_X + 5 )
01598     if( pos.getDistanceTo(posAgent) < 5 )
01599       dExtra = 0.0;
01600     dCalcDist += dDistOpp + dExtra;
01601     Log.log( 513, "dDistOpp %f dDistAgent %f calc %f min %f",
01602        dDistOpp, dDistAgent, dCalcDist, 0.75*pos.getDistanceTo(posGoal));
01603     dCalcDist = min( dCalcDist, 0.75*pos.getDistanceTo( posGoal ) );
01604     double x = -PITCH_LENGTH/2 + 4;
01605     double y = line.getYGivenX( x);
01606     posMark = pos + VecPosition( dCalcDist, angToGoal, POLAR );
01607     if( posMark.getX() < x )
01608       {
01609   Log.log( 513, "change posmark to (%f,%f)", x, y );
01610   posMark.setVecPosition( x, y );
01611       }
01612     // if interception point iss outside range or very close to marking
01613     // point, but far away from opp (is this possible?) move closer.
01614     if( ! line.isInBetween( posMark, pos, posGoal ) ||
01615   ( posMark.getDistanceTo( posAgent ) < 1.5 &&
01616     posMark.getDistanceTo( pos ) > 2*dDist ) )
01617     {
01618       Log.log( 513, "set marking position at dDist %f", min(dDistAgent,7.0) );
01619       posMark   = pos + VecPosition( min( dDistAgent, 7.0 ), angToGoal, POLAR );
01620     }
01621     Log.log( 513, "marking position calc (%f,%f) pos(%f,%f) calcdist %f", 
01622        posMark.getX(), posMark.getY(), pos.getX(), pos.getY(), 
01623        dCalcDist );
01624   }
01625   else if( mark == MARK_BALL )                  // position in direction ball
01626   {
01627     angToBall = (posBall-pos).getDirection( );
01628     posMark   = pos + VecPosition( dDist, angToBall, POLAR );
01629   }
01630   else if( mark == MARK_BISECTOR )             // pos between ball and goal
01631   {
01632     angToBall = (posBall - pos).getDirection( );
01633     angToGoal = (posGoal - pos).getDirection( );
01634     ang       = getBisectorTwoAngles( angToBall, angToGoal );
01635     posMark   = pos + VecPosition( dDist, ang ,POLAR );
01636   }
01637   if( fabs( posMark.getX() ) > PITCH_LENGTH/2.0 - 2.0 )
01638     posMark.setX( sign(posMark.getX())*(PITCH_LENGTH/2.0 - 2.0) );
01639   return posMark;
01640 
01641 }
01642 
01643 
01655 double WorldModel::getActualKickPowerRate( )
01656 {
01657  // true indicates that relative angle to body should be returned
01658  double dir_diff      = fabs( getRelativeAngle( OBJECT_BALL, true ) );
01659  double dist          = getRelativeDistance( OBJECT_BALL ) -
01660                         SS->getPlayerSize( ) - SS->getBallSize( );
01661  return SS->getKickPowerRate() *
01662           ( 1 - 0.25 * dir_diff/180.0 - 0.25 * dist / SS->getKickableMargin());
01663 }
01664 
01679 double WorldModel::getKickPowerForSpeed( double dDesiredSpeed )
01680 {
01681   // acceleration after kick is calculated by power * eff_kick_power_rate
01682   // so actual kick power is acceleration / eff_kick_power_rate
01683   return dDesiredSpeed / getActualKickPowerRate( );
01684 }
01685 
01686 
01693 double WorldModel::getKickSpeedToTravel( double dDistance, double dEndSpeed )
01694 {
01695   // if endspeed is zero we have an infinite series and return the first term
01696   // that corresponds to the distance that has to be travelled.
01697   if( dEndSpeed < 0.0001  )
01698     return Geometry::getFirstInfGeomSeries(dDistance, SS->getBallDecay() );
01699 
01700   // use geometric series to calculate number of steps and with that the
01701   // velocity to give to the ball, we start at endspeed and therefore use
01702   // the inverse of the ball decay (r).
01703   // s = a + a*r + .. a*r^n since we calculated from endspeed (a) to
01704   // firstspeed, firstspeed equals a*r^n = endspeed*r^nr_steps
01705   double dNrSteps = Geometry::getLengthGeomSeries( dEndSpeed,
01706                                   1.0/SS->getBallDecay( ), dDistance );
01707   return getFirstSpeedFromEndSpeed( dEndSpeed, (int)rint(dNrSteps) ) ;
01708 }
01709 
01710 
01718 double WorldModel::getFirstSpeedFromEndSpeed( double dEndSpeed, double dCycles,
01719                                               double dDecay  )
01720 {
01721   if( dDecay < 0 )
01722     dDecay = SS->getBallDecay();
01723 
01724   // geometric serie: s = a + a*r^1 + .. + a*r^n, now given endspeed = a*r^n ->
01725   // endspeed = firstspeed * ratio ^ length ->
01726   // firstpeed = endspeed * ( 1 / ratio ) ^ length
01727   return dEndSpeed * pow( 1 / dDecay, dCycles );
01728 }
01729 
01738 double WorldModel::getFirstSpeedFromDist( double dDist, double dCycles, double
01739                    dDecay )
01740 {
01741   if( dDecay < 0 )
01742     dDecay = SS->getBallDecay();
01743 
01744   return Geometry::getFirstGeomSeries( dDist, dDecay, dCycles);
01745 }
01746 
01753 double WorldModel::getEndSpeedFromFirstSpeed(double dFirstSpeed,double dCycles)
01754 {
01755   // geometric series: s = a + a*r^1 + .. + a*r^n, with firstspeed = a ->
01756   // endspeed = firstspeed * ratio ^ length ;
01757   return dFirstSpeed * pow( SS->getBallDecay(), dCycles );
01758 }
01759 
01767 AngDeg WorldModel::getAngleForTurn( AngDeg angDesiredAngle, double dSpeed,
01768                                     ObjectT obj )
01769 {
01770   AngDeg a = angDesiredAngle * (1.0 + getInertiaMoment( obj ) * dSpeed );
01771   if( a > SS->getMaxMoment() )
01772     return SS->getMaxMoment() ;
01773   else if ( a < SS->getMinMoment() )
01774     return SS->getMinMoment() ;
01775   else
01776     return a;
01777 }
01778 
01785 AngDeg WorldModel::getActualTurnAngle( AngDeg angTurn,double dSpeed,ObjectT o )
01786 {
01787   return angTurn / (1.0 + getInertiaMoment( o ) * dSpeed );
01788 }
01789 
01801 double WorldModel::getPowerForDash( VecPosition posRelTo, AngDeg angBody,
01802               VecPosition vel, double dEffort, int iCycles )
01803 {
01804   // the distance desired is the x-direction to the relative position we
01805   // we want to move to. If point lies far away, we dash maximal. Furthermore
01806   // we subtract the x contribution of the velocity because it is not necessary
01807   // to dash maximal.
01808   double dDist = posRelTo.rotate(-angBody).getX(); // get distance in direction
01809   if( iCycles <= 0 ) iCycles = 1;
01810   double dAcc  = getFirstSpeedFromDist(dDist,iCycles,SS->getPlayerDecay());
01811                                                    // get speed to travel now
01812   if( dAcc > SS->getPlayerSpeedMax() )             // if too far away
01813     dAcc = SS->getPlayerSpeedMax();                // set maximum speed
01814   dAcc -= vel.rotate(-angBody).getX();             // subtract current velocity
01815 
01816   // acceleration = dash_power * dash_power_rate * effort ->
01817   // dash_power = acceleration / (dash_power_rate * effort )
01818   double dDashPower = dAcc/(SS->getDashPowerRate() * dEffort );
01819   if( dDashPower > SS->getMaxPower() )
01820     return SS->getMaxPower();
01821   else if( dDashPower < SS->getMinPower() )
01822     return SS->getMinPower();
01823   else
01824     return dDashPower;
01825 }
01826 
01827 
01837 int WorldModel::getClosestPlayerInFormationTo( VecPosition pos, 
01838                                                bool bIncludeGoalie,
01839                                                ObjectT objWithout,
01840                                                PlayerSetT ps, 
01841                                                FormationT ft )
01842 {
01843   double      dDist = 1000.0;
01844   VecPosition posStrat;
01845   int         iPlayer = -1;
01846 
01847   for( int i = 0; i < MAX_TEAMMATES; i++ )
01848   {
01849     if( bIncludeGoalie == false && i == 0 )
01850       continue;
01851     else if( objWithout == SoccerTypes::getTeammateObjectFromIndex( i ) )
01852       continue;
01853     else if( !SoccerTypes::isPlayerTypeInSet( 
01854         formations->getPlayerType(i,ft), ps ))
01855       continue;
01856 
01857     posStrat = getStrategicPosition( i, ft );
01858 
01859     if( isDeadBallUs( )&&
01860          getBallPos().getX() < PITCH_LENGTH/3.0 &&
01861          i >= 9 )
01862       ;  // don't use attackers when in dead ball situation and not upfront
01863     else if( posStrat.getDistanceTo( pos ) < dDist )
01864     {
01865       dDist   = posStrat.getDistanceTo( pos );
01866       iPlayer = i;
01867     }
01868   }
01869   return iPlayer;
01870 }

Generated on Fri Nov 7 11:45:41 2003 for UvA Trilearn 2003 Base Code by doxygen1.2.12 written by Dimitri van Heesch, © 1997-2001