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

SenseHandler.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 
00047 #include "SenseHandler.h"
00048 #include "ActHandler.h"  // sigalarmHandler
00049 #include "Parse.h"
00050 
00051 #include <signal.h>   // needed for SIGALARM
00052 #include <string.h>   // needed for strlen
00053 #include <stdio.h>    // needed for printf
00054 #include <iostream>   // needed for cout
00055 
00056 /*****************************************************************************/
00057 /********************* CLASS SENSEHANDLER ************************************/
00058 /*****************************************************************************/
00059 
00065 #ifdef WIN32
00066 DWORD WINAPI sense_callback( LPVOID v )
00067 #else
00068 void* sense_callback( void *v )
00069 #endif
00070 {
00071   Log.log( 1, "Starting to listen for server messages" );
00072   SenseHandler* s = (SenseHandler*)v;
00073   s->handleMessagesFromServer( );
00074   return NULL;
00075 }
00076 
00077 
00084 SenseHandler::SenseHandler( Connection *c, WorldModel *wm, ServerSettings *ss,
00085                             PlayerSettings *ps )
00086 {
00087   connection             = c;
00088   SS                     = ss;
00089   PS                     = ps;
00090   WM                     = wm;
00091   iSimStep               = SS->getSimulatorStep()*1000;
00092   iTimeSignal            = (int)(iSimStep*0.85);
00093 
00094 #ifdef WIN32
00095   TIMECAPS tc;
00096   UINT     resolution = 1;   // timer resolution for the application (ms)
00097   iTimer = NULL;
00098 
00099   // set the minimum timer resolution for an application
00100   if (TIMERR_NOERROR == timeGetDevCaps( &tc, sizeof(TIMECAPS) ))
00101   {
00102     timerRes = min( max( tc.wPeriodMin, resolution ), tc.wPeriodMax );
00103     timeBeginPeriod( timerRes );
00104   }
00105 #else
00106   struct sigaction sigact;
00107 
00108   sigact.sa_flags = SA_RESTART; // do not unblock primitives (like recvfrom)
00109   sigact.sa_handler = (void (*)(int))sigalarmHandler;
00110   sigaction( SIGALRM, &sigact, NULL );
00111 
00112   // set timer signal to indicate when ActHandler should sent commands to the
00113   // server, this structure will later be filled with exact timing values
00114   itv.it_interval.tv_sec  = 0;
00115   itv.it_interval.tv_usec = 0;
00116   itv.it_value.tv_sec     = 0;
00117   itv.it_value.tv_usec    = 0;
00118 #endif
00119 }
00120 
00123 void SenseHandler::handleMessagesFromServer( )
00124 {
00125   char strBuf[MAX_MSG];
00126   int i=0;
00127 
00128   while( 1 )
00129   {
00130     strBuf[0]='\0';
00131     if( i != -1 )                                         // if no error
00132       i = connection->receiveMessage( strBuf, MAX_MSG );  // get message
00133     if( strBuf[0] != '\0' )                               // if not empty
00134       analyzeMessage( strBuf );                           // parse message
00135   }
00136 }
00137 
00138 
00148 void SenseHandler::setTimeSignal( )
00149 {
00150   if( WM->getAgentViewFrequency() == 1.0 ) // VA_NORMAL AND VQ_HIGH (default)
00151   {
00152     if( iTriCounter % 3 == 0 )             // see will arrive first half cycle
00153     {
00154       iTimeSignal = (int)(iSimStep * PS->getFractionWaitSeeBegin() );
00155       iTriCounter = 0;
00156     }
00157     else if( iTriCounter % 3 == 1 )        // see will arrive 2nd half of cycle
00158     {
00159       iTimeSignal = (int)(iSimStep * PS->getFractionWaitSeeEnd() );
00160     }
00161     else                                   // no see will arrive
00162       iTimeSignal = (int)(iSimStep * PS->getFractionWaitNoSee( ) );
00163   }
00164   else if( WM->getAgentViewFrequency() == 2.0 ) // VA_WIDE AND VQ_HIGH
00165   {
00166     if( iTriCounter % 3 == 0 )              // see will arrive
00167     {
00168       iTimeSignal = (int)(iSimStep * PS->getFractionWaitSeeEnd() );
00169       iTriCounter = 0;
00170     }
00171     else                                   // no see will arrive
00172       iTimeSignal = (int)(iSimStep * PS->getFractionWaitNoSee() );
00173   }
00174   else                                     // VA_NARROW AND VQ_HIGH
00175     iTimeSignal = (int)(iSimStep * PS->getFractionWaitSeeEnd() );
00176 
00177   iTriCounter++;
00178 #ifdef WIN32
00179   // kill the previous timer
00180   if (iTimer != NULL) timeKillEvent( iTimer );
00181   // start a new one
00182   iTimer = timeSetEvent( iTimeSignal / 1000, timerRes,
00183                          sigalarmHandler, (DWORD)0, TIME_ONESHOT );
00184 #else
00185   itv.it_value.tv_usec = iTimeSignal;
00186   setitimer( ITIMER_REAL, &itv, NULL );
00187 #endif
00188 }
00189 
00194 bool SenseHandler::analyzeMessage( char *strMsg )
00195 {
00196   Log.log( 1, strMsg );
00197   bool bReturn = false;
00198   
00199   switch( strMsg[1] )
00200   {
00201     case 'c':
00202         if( strMsg[2] == 'h' )
00203           return analyzeChangePlayerTypeMessage( strMsg );      // ( c hange_
00204         else
00205           ;                                                    // (clang
00206         break;
00207     case 'f':
00208           return analyzeFullStateMessage( strMsg );      // ( f ullstate_
00209     case 'o':                                                 // ( o k
00210         if( strlen(strMsg) > 14 && strMsg[4] == 'c' && strMsg[10] == 'b' )
00211           analyzeCheckBall( strMsg );                         // (ok check_ball
00212         return true;
00213     case 's':
00214     {
00215       switch( strMsg[3] )
00216       {
00217       case 'e':
00218         if( strMsg[5] == 'g')
00219           return analyzeSeeGlobalMessage  ( strMsg ); // (se e_g
00220         else if( WM->isFullStateOn( ) == false )
00221           return analyzeSeeMessage        ( strMsg ); // (se e
00222         break;                  
00223       case 'n': 
00224         bReturn = analyzeSenseMessage      ( strMsg ); // (se n se
00225         if( WM->isFullStateOn( ) == true  )
00226           WM->updateAfterSenseMessage( );
00227         return bReturn; 
00228         break;
00229       case 'r': return analyzeServerParamMessage( strMsg ); // (se r ver_param
00230       default : break;
00231       }
00232     }
00233         break;
00234     case 'i':     return analyzeInitMessage       ( strMsg ); // ( i nit
00235     case 'h':     return analyzeHearMessage       ( strMsg ); // ( h ear
00236     case 'p':     return ( strMsg[8] == 't')
00237                   ? analyzePlayerTypeMessage ( strMsg )  // (player_ t ype
00238                   : analyzePlayerParamMessage( strMsg ); // (player_ p aram
00239     case 'e':     printf("(%d,%d) %s\n", WM->getCurrentCycle(),
00240                            WM->getPlayerNumber(),strMsg);// ( error
00241         break;
00242     case 't':     Log.logWithTime( 2, " incoming think message" );
00243                   WM->processRecvThink( true );          // ( think
00244         break;
00245     default:      cerr << "(" << WM->getCurrentTime() << ", " <<
00246                         WM->getPlayerNumber()
00247                         << ") (SenseHandler::analyzeMessage) " <<
00248                      "ignored message: " << strMsg << "\n";
00249                   return false;
00250   }
00251   return false;
00252 }
00253 
00254 
00259 bool SenseHandler::analyzeSeeMessage( char *strMsg )
00260 {
00261   strcpy( WM->strLastSeeMessage, strMsg );
00262 
00263   Log.logWithTime( 2, " %s",strMsg );
00264 
00265   if( WM->getRelativeDistance( OBJECT_BALL ) < SS->getVisibleDistance() )
00266     Log.logWithTime( 560, "%s", WM->strLastSeeMessage );
00267 
00268   Time    time = WM->getTimeLastRecvSenseMessage();
00269   int iTime = Parse::parseFirstInt( &strMsg );         // get the time
00270   if( time.getTime() != iTime )
00271   {
00272     cerr << "(SenseHandler:analyzeSeeMessage) see and different time as sense:"
00273          << time.getTime() << " vs. " << iTime << endl;
00274     return false;
00275   }
00276 
00277   // count number of see message in this cycle
00278   if( WM->getTimeLastSeeMessage() == time )
00279     m_iSeeCounter++;
00280   else
00281     m_iSeeCounter = 1;
00282 
00283   // do nothing with second see, since it adds nothings
00284   if( m_iSeeCounter >= 2 )
00285   {
00286     Log.logWithTime( 4, "second see message in cycle; do nothing " );
00287     return true;
00288   }
00289 
00290   // reset the send pattern when previous cycle(s) no see arrived
00291   if( WM->getAgentViewFrequency() == 1.0 && // VA_NORMAL; previous cycle no see
00292       time.getTimeDifference( WM->getTimeLastSeeMessage() )== 2 )
00293     iTriCounter = 1;                // see will arive in 2nd half in next cycle
00294   else if( WM->getAgentViewFrequency() == 2.0 && // VA_WIDE; two cycles no see
00295            time.getTimeDifference( WM->getTimeLastSeeMessage() ) == 3 )
00296     iTriCounter = 1;                // no see will arrive next two cycles
00297 
00298   WM->setTimeLastSeeMessage( time );   // set time of last see message
00299   return true;
00300 }
00301 
00307 bool SenseHandler::analyzeSeeGlobalMessage( char *strMsg )
00308 {
00309   Log.logWithTime( 2, " incoming see global message" );
00310   strcpy( WM->strLastSeeMessage, strMsg );
00311 
00312   ObjectT o;
00313   bool    isGoalie;
00314   double  dX, dY, dVelX, dVelY;
00315   int     iTime;
00316   AngDeg  angBody, angNeck;
00317   Time    time = WM->getCurrentTime();
00318 
00319   iTime = Parse::parseFirstInt( &strMsg );         // get the time
00320   time.updateTime( iTime );
00321 
00322   while( *strMsg != ')' )                          // " ((objname.." or ")"
00323   {
00324     dVelX = dVelY = UnknownDoubleValue;
00325     angBody = angNeck = UnknownAngleValue;
00326     strMsg += 2;          // go the start of the object name
00327 
00328     // get the object type at the current position in the string
00329     o = SoccerTypes::getObjectFromStr( &strMsg, &isGoalie, WM->getTeamName() );
00330     if( o == OBJECT_ILLEGAL )
00331     {
00332       Log.log( 4, "Illegal object" );
00333       Log.log( 4, "total messages: %s", WM->strLastSeeMessage );
00334       Log.log( 4, "rest of message: %s", strMsg );
00335     }
00336 
00337     dX = Parse::parseFirstDouble( &strMsg );        // parse first value
00338     dY = Parse::parseFirstDouble( &strMsg );        // parse second value
00339     if ( *strMsg != ')' )                           // if it was no flag
00340     {
00341       dVelX = Parse::parseFirstDouble( &strMsg );   // parse delta x
00342       dVelY = Parse::parseFirstDouble( &strMsg );   // parse delta y
00343       if( *strMsg != ')' )                          // stil not finished
00344       {                                             // get body and neck angle
00345         angBody = Parse::parseFirstDouble( &strMsg );
00346         angNeck = Parse::parseFirstDouble( &strMsg );
00347       }
00348     }
00349     // skip ending bracket of object information.
00350     Parse::gotoFirstOccurenceOf( ')', &strMsg );
00351     strMsg++;
00352 
00353     // process the parsed information (unread values are Unknown...)
00354     WM->processSeeGlobalInfo( o, time, VecPosition(dX,dY),
00355                     VecPosition(dVelX,dVelY), angBody, angNeck );
00356     }
00357   WM->setTimeLastSeeGlobalMessage( time );  // set time last see global message
00358   return true;
00359 }
00360 
00364 bool SenseHandler::analyzeFullStateMessage( char *strMsg )  
00365 {
00366   Log.restartTimer( );
00367   Log.logWithTime( 2, " incoming fullstate message" );
00368   Log.log( 4, " fullstate message: %s", strMsg );  
00369   strcpy( WM->strLastSeeMessage, strMsg );
00370 
00371   ObjectT o;
00372   bool    isGoalie;  
00373   double  dX, dY, dVelX, dVelY;
00374   int     iTime;
00375   AngDeg  angBody, angNeck;
00376   Time    time = WM->getCurrentTime();
00377 
00378   iTime = Parse::parseFirstInt( &strMsg );         // get the time
00379   time.updateTime( iTime );
00380   Log.log( 4, "fullstate time: %d", time.getTime() );
00381   
00382   strMsg++;                                      // skip space
00383   Parse::gotoFirstOccurenceOf( ' ', &strMsg );   // skip (pmode
00384   strMsg++;                                      // skip space
00385 
00386   Log.log( 4, "fullstate parse ref: %s", strMsg );
00387   RefereeMessageT rm = SoccerTypes::getRefereeMessageFromStr( strMsg ); 
00388   PlayModeT       pm = SoccerTypes::getPlayModeFromRefereeMessage( rm );
00389   if( pm != PM_ILLEGAL )                                
00390     WM->setPlayMode( pm );                              
00391       
00392   Parse::gotoFirstOccurenceOf( 'e', &strMsg );   // go to end of vmode
00393   strMsg++;                                      // skip 'e'
00394   strMsg++;                                      // skip space
00395 
00396   Log.log( 4, "fullstate parse qua: %s", strMsg );
00397   ViewQualityT vq = SoccerTypes::getViewQualityFromStr( strMsg ); 
00398   Parse::gotoFirstOccurenceOf( ' ', &strMsg );   // go to end of quality
00399   strMsg++;                                      
00400   Log.log( 4, "fullstate parse ang: %s", strMsg );  
00401   ViewAngleT   va = SoccerTypes::getViewAngleFromStr( strMsg );
00402 
00403   Log.log( 4, "fullstate parse count: %s", strMsg );  
00404   WM->setNrOfCommands( CMD_KICK       , Parse::parseFirstInt( &strMsg ) );
00405   WM->setNrOfCommands( CMD_DASH       , Parse::parseFirstInt( &strMsg ) );
00406   WM->setNrOfCommands( CMD_TURN       , Parse::parseFirstInt( &strMsg ) );
00407   WM->setNrOfCommands( CMD_CATCH      , Parse::parseFirstInt( &strMsg ) );
00408   WM->setNrOfCommands( CMD_MOVE       , Parse::parseFirstInt( &strMsg ) );  
00409   WM->setNrOfCommands( CMD_TURNNECK   , Parse::parseFirstInt( &strMsg ) );
00410   WM->setNrOfCommands( CMD_CHANGEVIEW , Parse::parseFirstInt( &strMsg ) );
00411   WM->setNrOfCommands( CMD_SAY        , Parse::parseFirstInt( &strMsg ) );
00412 
00413   int iArmMovable = Parse::parseFirstInt( &strMsg );
00414   int iArmExpires = Parse::parseFirstInt( &strMsg );
00415   Parse::parseFirstDouble( &strMsg ); // skip pointto info, comes later
00416   Parse::parseFirstDouble( &strMsg ); // skip pointto info, comes later
00417   WM->setNrOfCommands( CMD_POINTTO    , Parse::parseFirstInt( &strMsg ) );
00418 
00419   Parse::gotoFirstOccurenceOf( 'b', &strMsg );   // go to ball position  
00420   
00421   Log.log( 4, "fullstate parse ball: %s", strMsg );    
00422   dX    = Parse::parseFirstDouble( &strMsg );    // parse first value
00423   dY    = Parse::parseFirstDouble( &strMsg );    // parse second value  
00424   dVelX = Parse::parseFirstDouble( &strMsg );    // parse third value  
00425   dVelY = Parse::parseFirstDouble( &strMsg );    // parse fourth value  
00426   if( WM->isBeforeKickOff() ) 
00427     dX = dY = dVelX = dVelY = 0.0;
00428   if( WM->getSide() == SIDE_RIGHT )
00429   {
00430     dX    *= -1;
00431     dY    *= -1;    
00432     dVelX *= -1;    
00433     dVelY *= -1;          
00434   }  
00435   WM->processSeeGlobalInfo( OBJECT_BALL, time, VecPosition(dX,dY),
00436                     VecPosition(dVelX,dVelY), -1, -1 );
00437   strMsg++;
00438   Log.log( 4, "fullstate ball: %f %f %f %f", dX, dY, dVelX, dVelY );
00439     
00440   while( *strMsg != ')' )                          // " ((objname.." or ")"
00441   {
00442     dVelX = dVelY = UnknownDoubleValue;
00443     angBody = angNeck = UnknownAngleValue;
00444     strMsg += 2;          // go the start of the object name
00445     Log.log( 4, "fullstate parse object: %s", strMsg );    
00446     // get the object type at the current position in the string
00447     o = SoccerTypes::getObjectFromStr( &strMsg, &isGoalie, 
00448                           (WM->getSide() == SIDE_LEFT ) ? "l" : "r" );
00449 
00450     dX      = Parse::parseFirstDouble( &strMsg );   // parse x position
00451     dY      = Parse::parseFirstDouble( &strMsg );   // parse y position
00452     dVelX   = Parse::parseFirstDouble( &strMsg );   // parse x velocity
00453     dVelY   = Parse::parseFirstDouble( &strMsg );   // parse y velocity
00454     angBody = Parse::parseFirstDouble( &strMsg );   // parse body angle
00455     angNeck = Parse::parseFirstDouble( &strMsg );   // parse neck angle
00456 
00457     if( WM->getSide() == SIDE_RIGHT )
00458     {
00459       dX    *= -1;
00460       dY    *= -1;    
00461       dVelX *= -1;    
00462       dVelY *= -1;          
00463       angBody = VecPosition::normalizeAngle( angBody + 180 );
00464     }    
00465 
00466     double dStamina  = Parse::parseFirstDouble( &strMsg );  // get stamina
00467     double dEffort   = Parse::parseFirstDouble( &strMsg );  // get effort
00468                        Parse::parseFirstDouble( &strMsg );  // skip recovery
00469 
00470     // skip ending bracket of stamina and then of object information.
00471     Parse::gotoFirstOccurenceOf( ')', &strMsg );
00472     Parse::gotoFirstOccurenceOf( ')', &strMsg );
00473     
00474     strMsg++;
00475     strMsg++;    
00476 
00477     Log.log( 1, "fullstate obj %d: %f %f %f %f %f %f", o, dX, dY, dVelX, dVelY,
00478                  angBody, angNeck );
00479     // process the parsed information 
00480     if( o == WM->getAgentObjectType() )
00481       WM->processNewAgentInfo( vq, va, dStamina, dEffort, -1.0, -1.0, -angNeck,
00482                                -1,iArmMovable, iArmExpires, VecPosition(0,0));
00483       
00484     WM->processSeeGlobalInfo( o, time, VecPosition(dX,dY),
00485                               VecPosition(dVelX,dVelY), angBody, angNeck );
00486     
00487   }
00488   WM->setTimeLastSeeGlobalMessage( time );  // set time last see global message
00489   WM->setTimeLastSenseMessage( time );      // set time last see global message
00490 
00491   return true;
00492 }
00493 
00501 bool SenseHandler::analyzeSenseMessage( char *strMsg )
00502 {
00503   Log.log( 999, "%s", strMsg );
00504   // cerr << strMsg << endl; 
00505   // set the synchronization counter, this is a value [0..2] indicating the
00506   // section of the pattern this cycle is in. It gives an indication when new
00507   // visual information will arrive.
00508 
00509   if( SS->getSynchMode() == false )
00510     setTimeSignal();                        // set signal when to send action
00511   strcpy( WM->strLastSenseMessage, strMsg );
00512 
00513   if( WM->getRelativeDistance( OBJECT_BALL ) < SS->getVisibleDistance() )
00514     Log.logWithTime( 560, "%s", WM->strLastSenseMessage );
00515 
00516   int iTime = Parse::parseFirstInt( &strMsg );// get time
00517   Time timeOld = WM->getCurrentTime();
00518   Time timeNew = timeOld;
00519   timeNew.updateTime( iTime );
00520 
00521   if( timeNew.getTimeDifference( timeOld ) > 1 )
00522     Log.log( 1, "Missed a sense!!" );
00523 
00524   Log.logWithTime ( 2, "\n\nSENSE (%d, %d)", timeNew.getTime(),
00525   timeNew.getTimeStopped() );
00526   Log.restartTimer( );
00527   iSimStep               = SS->getSimulatorStep()*1000;
00528   iTimeSignal            = (int)(iSimStep*0.85); 
00529   Log.logWithTime ( 2, " alarm after %d", iTimeSignal );
00530 
00531   WM->setTimeLastSenseMessage( timeNew ); // set the time
00532 
00533 //  Log.logWithTime( 2, " end analyzing sense" );
00534   return true;
00535 }
00536 
00542 bool SenseHandler::analyzeInitMessage( char *strMsg )
00543 {
00544   Log.log( 999, "%s", strMsg );
00545   strMsg += 6;                                            // go to Side
00546   WM->setSide( SoccerTypes::getSideFromStr( strMsg ) );   // get and set Side
00547   int nr = Parse::parseFirstInt( &strMsg );               // get and set number
00548   if( nr == 0 )                                           // coach
00549   {
00550      WM->setPlayerNumber( nr );
00551      cerr << strMsg  << endl;
00552      return true;
00553   }
00554   WM->setAgentObjectType( SoccerTypes::getTeammateObjectFromIndex( nr - 1 ) );
00555   WM->setPlayerNumber( nr );
00556   strMsg++;                                               // skip space to pm
00557   WM->setPlayMode( SoccerTypes::getPlayModeFromStr( strMsg ) ); // get playmode
00558   return true;
00559 }
00560 
00569 bool SenseHandler::analyzeHearMessage( char *strMsg )
00570 {
00571   RefereeMessageT rm;
00572   PlayModeT       pm;
00573   strcpy( WM->strLastHearMessage, strMsg);
00574 
00575   int iTime = Parse::parseFirstInt( &strMsg );              // ignore time
00576   Time time( iTime );
00577 
00578   switch( Parse::gotoFirstNonSpace( &strMsg ) )
00579   {
00580     case 'r':                                               // referee
00581       Log.log( 999, "%s", WM->strLastHearMessage );
00582       WM->setTimeLastRefereeMessage( time );
00583       Parse::gotoFirstOccurenceOf( ' ', &strMsg );          // go to start
00584       Parse::gotoFirstNonSpace   ( &strMsg      );          // and first part
00585       rm = SoccerTypes::getRefereeMessageFromStr( strMsg ); // get the ref msg
00586       Log.logWithTime( 2, " referee message: %s %s",
00587       SoccerTypes::getRefereeMessageStr(rm), WM->strLastHearMessage);
00588       pm = SoccerTypes::getPlayModeFromRefereeMessage( rm );// get play mode
00589       if( pm != PM_ILLEGAL )                                // from ref msg
00590         WM->setPlayMode( pm );                              // if was pm, set 
00591 
00592       switch( rm )
00593       {
00594         case REFC_GOAL_LEFT:                            // goal left
00595           if( WM->getSide() == SIDE_LEFT )
00596             WM->addOneToGoalDiff();
00597           else
00598             WM->subtractOneFromGoalDiff();
00599           WM->processSeeGlobalInfo( OBJECT_BALL, time, VecPosition( 0, 0 ),
00600                VecPosition( 0, 0 ), 0, 0 );
00601           break;
00602         case REFC_GOAL_RIGHT:                      // goal right
00603           if( WM->getSide() == SIDE_RIGHT )
00604             WM->addOneToGoalDiff();
00605           else
00606             WM->subtractOneFromGoalDiff();
00607           WM->processSeeGlobalInfo( OBJECT_BALL, time, VecPosition( 0, 0 ),
00608                VecPosition( 0, 0 ), 0, 0 );
00609           break;
00610         case REFC_GOALIE_CATCH_BALL_LEFT:         // catch ball
00611         case REFC_GOALIE_CATCH_BALL_RIGHT:
00612           WM->processCatchedBall( rm, time );
00613           break;
00614         case REFC_PENALTY_ONFIELD_LEFT:
00615           WM->setSidePenalty( SIDE_LEFT );
00616           break;
00617         case REFC_PENALTY_ONFIELD_RIGHT:
00618           WM->setSidePenalty( SIDE_RIGHT );
00619           break;
00620         case REFC_PENALTY_MISS_LEFT:
00621         case REFC_PENALTY_SCORE_LEFT:
00622           WM->setPlayMode( PM_FROZEN );
00623           break;
00624         case REFC_PENALTY_MISS_RIGHT:
00625         case REFC_PENALTY_SCORE_RIGHT:
00626           WM->setPlayMode( PM_FROZEN );         
00627           break;
00628         case REFC_PENALTY_FOUL_LEFT:
00629         case REFC_PENALTY_FOUL_RIGHT:
00630         default:
00631           break;
00632       }
00633       break;
00634     case 'o':                                               // online_coach_
00635         analyzeCoachMessage( strMsg );
00636         break;
00637     case 's':                                               // self
00638       break;                                                // do nothing
00639     default:                                                // from direction
00640         Log.logWithTime( 600, "incoming hear: %s", WM->strLastHearMessage );
00641         analyzePlayerMessage( iTime, strMsg );    // from player
00642       break;
00643   }
00644 
00645   return true;
00646 }
00647 
00654 bool SenseHandler::analyzePlayerMessage( int iTime, char *strMsg )
00655 {
00656   Parse::gotoFirstNonSpace( &strMsg );            // skip space
00657 
00658   if( WM->getPlayerNumber() == 0 )                // if i am coach
00659     return false;                                 //   skip message
00660   if( strlen( strMsg ) < 2 || strMsg[0] == 'o' )  // skip message since no dir.
00661     return false;                                 // thus no content
00662 
00663   Parse::parseFirstInt( &strMsg );                // skip direction
00664   Parse::gotoFirstNonSpace( &strMsg );            // skip space
00665   if( strlen( strMsg ) < 2 || strMsg[1] == 'p' )  // skip message when from opp
00666     return false;
00667 
00668   int iPlayer = Parse::parseFirstInt( &strMsg );  // get player number
00669   Parse::gotoFirstNonSpace( &strMsg );            // skip space
00670   strMsg++;                                       // skip " (=quote)
00671 
00672   if( strlen( strMsg ) < 4 )              // < 2 + two ending charactres ")
00673   {
00674     Log.log( 600, "communication string too small" );
00675     return false;
00676   }
00677 
00678   // get the cycle number from the encoding
00679   int iModCycle = (int)(strMsg[0] - 'a');
00680 
00681   if( iModCycle < 0 || iModCycle > 9 )
00682   {
00683     Log.log( 600, "communication cycle nr out of bounds: %d", iModCycle );
00684     return false;
00685   }
00686 
00687   // get the time difference between the current time and the send time
00688   int iDiff = (iTime % 10) - iModCycle;
00689   if( iDiff < 0 )
00690     iDiff += 10;
00691 
00692   // if it is too old; skip parsing; otherwise determine actual send time
00693   if( iDiff > 2  )
00694   {
00695     Log.log( 600, "communication string too old time %d mod %d diff %d",
00696                         iTime, iModCycle, iDiff);
00697     return false;
00698   }
00699   iTime -= iDiff;
00700 
00701   Log.log( 600, "process comm msg, diff %d time %d, %s", iDiff, iTime, strMsg);
00702   WM->storePlayerMessage( iPlayer, strMsg, iTime );
00703   return true;
00704 }
00705 
00706 bool SenseHandler::analyzeCoachMessage( char *strMsg )
00707 {
00708   Log.log( 605, "received coach messages: %s" , strMsg );
00709 
00710   return true;
00711 }
00718 bool SenseHandler::analyzeCheckBall( char *strMsg )
00719 {
00720   WM->setTimeCheckBall( Parse::parseFirstInt( &strMsg ) );
00721   strMsg++;
00722   WM->setCheckBallStatus( SoccerTypes::getBallStatusFromStr( strMsg ) );
00723   return true;
00724 }
00725 
00732 bool SenseHandler::analyzeChangePlayerTypeMessage( char *strMsg )
00733 {
00734   Log.log( 999, "%s", strMsg );
00735   int iPlayer = Parse::parseFirstInt( &strMsg );
00736   if( *strMsg != ')' ) // we are dealing with player of own team
00737   {
00738     int      iType = Parse::parseFirstInt( &strMsg );
00739     ObjectT  obj   = SoccerTypes::getTeammateObjectFromIndex( iPlayer - 1 );
00740     Log.log( 605, "change player from message %d -> %d", obj, iType );
00741     WM->setHeteroPlayerType( obj, iType );
00742     Log.log( 605, "changed player from message %d -> %d", obj, 
00743               WM->getHeteroPlayerType( obj ) );
00744     return true;
00745   }
00746   else
00747   {
00748     ObjectT  obj   = SoccerTypes::getOpponentObjectFromIndex( iPlayer - 1 );
00749     return WM->setSubstitutedOpp( obj );
00750   }
00751 
00752 
00753   return false;
00754 }
00755 
00762 bool SenseHandler::analyzeServerParamMessage( char *strMsg )
00763 {
00764 
00765   Log.log( 4, "%s", strMsg );
00766 
00767   readServerParam( "goal_width",               strMsg );
00768   readServerParam( "player_size",              strMsg );
00769   readServerParam( "player_decay",             strMsg );
00770   readServerParam( "player_rand",              strMsg );
00771   readServerParam( "player_weight",            strMsg );
00772   readServerParam( "player_speed_max",         strMsg );
00773   readServerParam( "player_accel_max",         strMsg );
00774   readServerParam( "stamina_max",              strMsg );
00775   readServerParam( "stamina_inc_max",          strMsg );
00776   readServerParam( "recover_dec_thr",          strMsg );
00777   readServerParam( "recover_min",              strMsg );
00778   readServerParam( "recover_dec",              strMsg );
00779   readServerParam( "effort_dec_thr",           strMsg );
00780   readServerParam( "effort_min",               strMsg );
00781   readServerParam( "effort_dec",               strMsg );
00782   readServerParam( "effort_inc_thr",           strMsg );
00783   readServerParam( "effort_inc",               strMsg );
00784   readServerParam( "kick_rand",                strMsg );
00785   readServerParam( "ball_size",                strMsg );
00786   readServerParam( "ball_decay",               strMsg );
00787   readServerParam( "ball_rand",                strMsg );
00788   readServerParam( "ball_weight",              strMsg );
00789   readServerParam( "ball_speed_max",           strMsg );
00790   readServerParam( "ball_accel_max",           strMsg );
00791   readServerParam( "dash_power_rate",          strMsg );
00792   readServerParam( "kick_power_rate",          strMsg );
00793   readServerParam( "kickable_margin",          strMsg );
00794   readServerParam( "catch_probability",        strMsg );
00795   readServerParam( "catchable_area_l",         strMsg );
00796   readServerParam( "catchable_area_w",         strMsg );
00797   readServerParam( "goalie_max_moves",         strMsg );
00798   readServerParam( "maxpower",                 strMsg );
00799   readServerParam( "minpower",                 strMsg );
00800   readServerParam( "maxmoment",                strMsg );
00801   readServerParam( "minmoment",                strMsg );
00802   readServerParam( "maxneckmoment",            strMsg );
00803   readServerParam( "minneckmoment",            strMsg );
00804   readServerParam( "maxneckang",               strMsg );
00805   readServerParam( "minneckang",               strMsg );
00806   readServerParam( "visible_angle",            strMsg );
00807   readServerParam( "visible_distance",         strMsg );
00808   readServerParam( "audio_cut_dist",           strMsg );
00809   readServerParam( "quantize_step",            strMsg );
00810   readServerParam( "quantize_step_l",          strMsg );
00811   readServerParam( "ckick_margin",             strMsg );
00812   readServerParam( "wind_dir",                 strMsg );
00813   readServerParam( "wind_force",               strMsg );
00814   readServerParam( "wind_rand",                strMsg );
00815   readServerParam( "wind_random",              strMsg );
00816   readServerParam( "inertia_moment",           strMsg );
00817   readServerParam( "half_time",                strMsg );
00818   readServerParam( "drop_ball_time",           strMsg );
00819   readServerParam( "port",                     strMsg );
00820   readServerParam( "coach_port",               strMsg );
00821   readServerParam( "olcoach_port",             strMsg );
00822   readServerParam( "say_coach_cnt_max",        strMsg );
00823   readServerParam( "say_coach_msg_size",       strMsg );
00824   readServerParam( "simulator_step",           strMsg );
00825   readServerParam( "send_step",                strMsg );
00826   readServerParam( "recv_step",                strMsg );
00827   readServerParam( "sense_body_step",          strMsg );
00828   readServerParam( "say_msg_size",             strMsg );
00829   readServerParam( "clang_win_size",           strMsg );
00830   readServerParam( "clang_define_win",         strMsg );
00831   readServerParam( "clang_meta_win",           strMsg );
00832   readServerParam( "clang_advice_win",         strMsg );
00833   readServerParam( "clang_info_win",           strMsg );
00834   readServerParam( "clang_mess_delay",         strMsg );
00835   readServerParam( "clang_mess_per_cycle",     strMsg );
00836   readServerParam( "hear_max",                 strMsg );
00837   readServerParam( "hear_inc",                 strMsg );
00838   readServerParam( "hear_decay",               strMsg );
00839   readServerParam( "catch_ban_cycle",          strMsg );
00840   readServerParam( "send_vi_step",             strMsg );
00841   readServerParam( "use_offside",              strMsg );
00842   readServerParam( "offside_active_area_size", strMsg );
00843   readServerParam( "forbid_kick_off_offside",  strMsg );
00844   readServerParam( "verbose",                  strMsg );
00845   readServerParam( "offside_kick_margin",      strMsg );
00846   readServerParam( "slow_down_factor",         strMsg );
00847   readServerParam( "synch_mode",               strMsg );
00848   readServerParam( "fullstate_l",              strMsg );
00849   readServerParam( "fullstate_r",              strMsg );
00850   readServerParam( "pen_dist_x",               strMsg );
00851   readServerParam( "pen_max_goalie_dist_x",    strMsg );
00852   readServerParam( "pen_allow_mult_kicks",     strMsg );
00853   readServerParam( "tackle_dist",              strMsg );
00854   readServerParam( "tackle_back_dist",         strMsg );
00855   readServerParam( "tackle_width",             strMsg );
00856   readServerParam( "tackle_cycles",            strMsg );
00857   readServerParam( "tackle_power_rate",        strMsg );
00858   readServerParam( "tackle_exponent",          strMsg );
00859 
00860   SS->setMaximalKickDist      ( SS->getKickableMargin() +
00861                                 SS->getPlayerSize()     +
00862                                 SS->getBallSize()          );
00863 // SS->show( cerr, ":" );
00864   return true;
00865 }
00866 
00867 bool SenseHandler::readServerParam( char *strParam, char *strMsg )
00868 {
00869   char strFormat[128];
00870   char strValue[128] = "";
00871   sprintf( strValue, "none" );
00872 
00873   sprintf( strFormat, "%s ", strParam );        // add space after parameters
00874   char *str = strstr( strMsg, strFormat );      // and find param definition
00875   sprintf( strFormat, "%s %%[^)]", strParam );  // read till closing bracket
00876 
00877   if( str == NULL )
00878   {
00879     cerr << "(SenseHandler::readServerParam) " << WM->getPlayerNumber() <<
00880             "  error finding " << strParam <<endl;
00881     return false;
00882   }
00883   int ret = sscanf( str, strFormat, strValue ); // read in values
00884 
00885   if( ret == 1 )
00886     SS->setValue( strParam, strValue );
00887   else
00888     cerr << "(SenseHandler::readServerParam) error reading " <<strParam <<endl;
00889   return (ret == 1 ) ? true : false ;
00890 }
00891 
00892 
00899 bool SenseHandler::analyzePlayerTypeMessage ( char *strMsg )
00900 {
00901   Log.log( 999, "%s", strMsg );
00902 // cerr << strMsg << endl;
00903 
00904   // analyze all heterogeneous player information
00905   int    iIndex           = Parse::parseFirstInt( &strMsg );
00906   double dPlayerSpeedMax  = Parse::parseFirstDouble( &strMsg );
00907   double dStaminaIncMax   = Parse::parseFirstDouble( &strMsg );
00908   double dPlayerDecay     = Parse::parseFirstDouble( &strMsg );
00909   double dInertiaMoment   = Parse::parseFirstDouble( &strMsg );
00910   double dDashPowerRate   = Parse::parseFirstDouble( &strMsg );
00911   double dPlayerSize      = Parse::parseFirstDouble( &strMsg );
00912   double dKickableMargin  = Parse::parseFirstDouble( &strMsg );
00913   double dKickRand        = Parse::parseFirstDouble( &strMsg );
00914   double dExtraStamina    = Parse::parseFirstDouble( &strMsg );
00915   double dEffortMax       = Parse::parseFirstDouble( &strMsg );
00916   double dEffortMin       = Parse::parseFirstDouble( &strMsg );
00917 
00918   WM->processNewHeteroPlayer( iIndex, dPlayerSpeedMax, dStaminaIncMax,
00919       dPlayerDecay,    dInertiaMoment, dDashPowerRate, dPlayerSize,
00920       dKickableMargin, dKickRand,      dExtraStamina,  dEffortMax,
00921       dEffortMin );
00922   return true;
00923 }
00924 
00930 bool SenseHandler::analyzePlayerParamMessage( char *strMsg )
00931 {
00932 //  cout << strMsg << endl;
00933   Log.log( 999, "%s", strMsg );
00934   readServerParam( "player_types",                     strMsg );
00935   readServerParam( "subs_max",                         strMsg );
00936   readServerParam( "player_speed_max_delta_min",       strMsg );
00937   readServerParam( "player_speed_max_delta_max",       strMsg );
00938   readServerParam( "stamina_inc_max_delta_factor",     strMsg );
00939   readServerParam( "player_decay_delta_min",           strMsg );
00940   readServerParam( "player_decay_delta_max",           strMsg );
00941   readServerParam( "inertia_moment_delta_factor",      strMsg );
00942   readServerParam( "dash_power_rate_delta_min",        strMsg );
00943   readServerParam( "dash_power_rate_delta_max",        strMsg );
00944   readServerParam( "player_size_delta_factor",         strMsg );
00945   readServerParam( "kickable_margin_delta_min",        strMsg );
00946   readServerParam( "kickable_margin_delta_max",        strMsg );
00947   readServerParam( "kick_rand_delta_factor",           strMsg );
00948   readServerParam( "extra_stamina_delta_min",          strMsg );
00949   readServerParam( "extra_stamina_delta_max",          strMsg );
00950   readServerParam( "effort_max_delta_factor",          strMsg );
00951   readServerParam( "effort_min_delta_factor",          strMsg );
00952   readServerParam( "new_dash_power_rate_delta_min",    strMsg );
00953   readServerParam( "new_dash_power_rate_delta_max",    strMsg );
00954   readServerParam( "new_stamina_inc_max_delta_factor", strMsg );
00955 
00956   return true;
00957 }
00958 
00959 /*****************************************************************************/
00960 /********************* TESTING PURPOSES **************************************/
00961 /*****************************************************************************/
00962 
00963 /*
00964 int main( void )
00965 {
00966   Connection c( "localhost", 6000 );
00967   WorldModel wm;
00968   SenseHandler i( &c,  &wm );
00969   i.analyzeMessage( "(see 0 ((g r) 64.1 13) ((f r t) 65.4 -16) ((f r b) 79 38) ((f p r t) 46.1 -6) ((f p r c) 48.4 18) ((f p r b) 58 37) ((f g r t) 62.8 7) ((f g r b) 66 19) ((f t r 20) 38.5 -38) ((f t r 30) 46.5 -30) ((f t r 40) 55.7 -25) ((f t r 50) 64.7 -21) ((f b r 50) 80.6 41) ((f r t 30) 69.4 -12) ((f r t 20) 67.4 -4) ((f r t 10) 67.4 4) ((f r 0) 69.4 12) ((f r b 10) 72.2 20) ((f r b 20) 75.9 27) ((f r b 30) 81.5 33) ((l r) 62.8 -89))" );
00970    cout << "2" << endl;
00971   i.analyzeMessage( "(see 0 ((g l) 49.9 -24) ((f l t) 50.9 14) ((f p l t) 31.5 1 0 0) ((f p l c) 34.5 -33) ((f g l t) 47.9 -17) ((f g l b) 52.5 -32) ((f t l 50) 50.9 20) ((f t l 40) 42.5 26) ((f t l 30) 34.8 36) ((f l t 30) 54.6 8) ((f l t 20) 53 -2) ((f l t 10) 53 -12) ((f l 0) 54.6 -23) ((f l b 10) 58 -32) ((f l b 20) 62.8 -41) ((p \"l\" 2) 5 -7 0 0 172 172) ((l l) 47.9 82))" );
00972   c.disconnect();
00973   cout << "exit" << endl ;
00974 
00975 }
00976 
00977 */
00978 

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