EGraphPlayerIF.h

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 //
00003 // $Id$
00004 //
00005 // Copyright 2008, 2009, 2010, 2011, 2012  Antonio Franchi and Paolo Stegagno    
00006 //
00007 // This file is part of MIP.
00008 //
00009 // MIP is free software: you can redistribute it and/or modify
00010 // it under the terms of the GNU General Public License as published by
00011 // the Free Software Foundation, either version 3 of the License, or
00012 // (at your option) any later version.
00013 //
00014 // MIP is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with MIP. If not, see <http://www.gnu.org/licenses/>.
00021 //
00022 // Contact info: antonio.franchi@tuebingen.mpg.de stegagno@diag.uniroma1.it
00023 //
00024 // ----------------------------------------------------------------------------
00025 
00026 
00027 #ifndef EGRAPH_PLAYER_IF_H
00028 #define EGRAPH_PLAYER_IF_H
00029 
00030 #include <libplayerc++/playerc++.h>
00031 #include <vector>
00032 #include <list>
00033 #include <unistd.h>
00034 #include <math.h>
00035 #include <cstdlib>
00036 #include <assert.h>
00037 #include <iostream>
00038 #include <fstream>
00039 
00040 // MIP
00041 #include <R2.h>
00042 #include <Grid.h>
00043 #include <Scan.h>
00044 
00045 #include "args.h"
00046 #include "utils.h"
00047 
00048 using namespace PlayerCc;
00049 using namespace std;
00050 using namespace boost;
00051 using namespace MipBaselib;
00052 
00053 enum BehaviorTypes
00054 {
00055  EXPAND,
00056  GUARD,
00057  FOLLOW,
00058  WANDER,
00059  NO_BEHAVIOR
00060 };
00061 
00062 enum KeepColor
00063 {
00064  KEEP_UNKNOWN,
00065  KEEP_ORANGE,
00066  KEEP_PURPLE
00067 };
00068 
00069 class PursuitAgent;
00070 
00071 typedef uint Identity;
00072 typedef std::vector<Pose > Path;
00073 typedef std::vector<PursuitAgent* > AgentVector;
00074 typedef std::vector<Pose > ViewPoints;
00075 
00076 ofstream gLogFile;
00077 Timer gTotalTimer;
00078 int gIterCount;
00079 Grid *gGlobalGrid;
00080 AgentVector gAgentVector;
00081 
00082 PlayerClient* gPC;
00083 Graphics2dProxy* gGP = NULL;
00084 MapProxy* gMP = NULL;
00085 
00086 int gMapWidth = -1;
00087 int gMapHeight = -1;
00088 double gMapResolution = -1;
00089 
00090 int gMinArcSize = 2;
00091 int gMinMergeArcSize = 1;
00092 int gMinRadialArcSize = 3;
00093 double gSafeRangeFrac = 0.92;
00094 double gSafeAngleFrac = 0.92;
00095 double gCoverDistScalar = 1.0;
00096 double gOverlapFactor = 1.08;
00097 
00098 Pose adjustViewPoint( Pose initialPose ){
00099  // Force viewpoints to be on 5cm x 5cm grid, which forces grids to mostly align.
00100  
00101  //int iX = (int)round( 20*initialPose.pos().x() );
00102  //int iY = (int)round( 20*initialPose.pos().y() );
00103  
00104  //return Pose( iX/20.0, iY/20.0, initialPose.ori() );
00105  
00106  return initialPose;
00107 }
00108 
00109 void drawSquare( player_color_t color, Position pos, double border, bool bFill ){
00110  player_point_2d_t square[4], center;
00111  
00112  center.px = pos.x();
00113  center.py = pos.y();
00114  
00115  square[0].px = center.px - border;
00116  square[0].py = center.py - border;
00117  square[1].px = center.px + border;
00118  square[1].py = center.py - border;
00119  square[2].px = center.px + border;
00120  square[2].py = center.py + border;
00121  square[3].px = center.px - border;
00122  square[3].py = center.py + border;
00123  
00124  gGP->Color( color );
00125  gGP->DrawPolygon( square, 4, bFill, color );
00126 }
00127 
00128 void drawX( player_color_t color, Position pos, double width ){
00129  player_point_2d_t square[4], center;
00130  
00131  center.px = pos.x();
00132  center.py = pos.y();
00133  
00134  square[0].px = center.px - width;
00135  square[0].py = center.py - width;
00136  square[2].px = center.px + width;
00137  square[2].py = center.py - width;
00138  square[1].px = center.px + width;
00139  square[1].py = center.py + width;
00140  square[3].px = center.px - width;
00141  square[3].py = center.py + width;
00142  
00143  gGP->Color( color );
00144  gGP->DrawPolyline( square, 2 );
00145  gGP->DrawPolyline( &(square[2]), 2 );
00146 }
00147 
00148 void drawRedX( Position pos, double width ){
00149  player_color_t color;
00150  
00151  color.alpha = 255;
00152  color.red = 255;
00153  color.green = 0;
00154  color.blue = 0;
00155  
00156  drawX( color, pos, width);
00157 }
00158 
00159 
00160 class PursuitAgent{
00161  
00162 protected :
00163  Identity m_iID;
00164  PlayerClient* m_pClient;
00165  Position2dProxy* m_pPosProxy;
00166  LaserProxy* m_pLaserProxy;
00167  
00168  BehaviorTypes m_eBehavior;
00169  Frontier m_frontier;
00170  Frontier m_freeArcs;
00171  Frontier m_prevFrontier;
00172  Grid m_LSR;
00173  Grid m_prevLSR;
00174  bool m_bFrontierInitialized;
00175  Path m_path;
00176  PursuitAgent* m_pWaitForAgent;
00177  AgentVector m_followers;
00178  
00179  // Agent action functions
00180  void Expand( AgentVector neighbors );
00181  void Guard( AgentVector neighbors );
00182  void processFrontier( AgentVector neighbors );
00183  void Wander( AgentVector neighbors );
00184  
00185  void recordLSR();
00186  //bool isCanExpandAlone();
00187  bool isCellCovered( Pose viewPoint, DubInt iCell, bool bSilent = true );
00188  
00189  //
00190  // These next functions are the two main functions for the algorithm
00191  //
00192  
00193  // Pick a viewpoint on current frontier to expand
00194  Pose pickBestViewPoint(int *iNumViewPoints, bool bDebugDisplay = false);
00195  
00196  // Update frontier after arriving at new viewpoint, involves clearing
00197  // some of neighbors frontier arcs and classifying LSR boundary
00198  void updateFrontier( AgentVector neighbors, bool bDebugDisplay = false );
00199  void getNeighborFrontiers( AgentVector neighbors, Pose &curPose, vector<Frontier > &ourNeighborFrontiers, 
00200    vector<Frontier > &updatedNeighborFrontiers,
00201    vector<DubInt > &neighborObstacleEndpoints,
00202    vector<DubInt > &neighborObstacleBeginpoints );
00203  void classifyOurFrontier( AgentVector neighbors, Pose &curPose, vector<Frontier > &ourNeighborFrontiers, 
00204    vector<DubInt > &neighborObstacleEndpoints,
00205    vector<DubInt > &neighborObstacleBeginpoints,
00206    bool bDebugDisplay );
00207  void updateNeighborFrontiers( AgentVector neighbors, Pose &curPose, vector<Frontier > &updatedNeighborFrontiers );
00208  void postProcessOurFrontier( vector<Frontier > &ourNeighborFrontiers, Pose &curPose, bool bDebugDisplay );
00209  
00210  
00211 public :
00212  PursuitAgent( Identity ID, PlayerClient* client, Position2dProxy* posProxy, LaserProxy* laserProxy );
00213  ~PursuitAgent( );
00214  
00215  void clientRead();
00216  Identity getID(){ return m_iID; }
00217  BehaviorTypes getBehavior(){ return m_eBehavior; }
00218  Grid getLSR(){ return ((m_bFrontierInitialized) ? m_LSR : m_prevLSR); }
00219  LRR getLRR(){ return ((m_bFrontierInitialized) ? m_LSR._lrr : m_prevLSR._lrr); }
00220  Frontier getFrontier(){ return ((m_bFrontierInitialized) ? m_frontier : m_prevFrontier); }
00221  
00222  int getNumFrontierSegments(){ return ((m_bFrontierInitialized) ? m_frontier.size() : m_prevFrontier.size()); }
00223  int getTotalFrontierCells();
00224  void setFrontier(Frontier frontier, bool bForce = false );
00225  Path getPath(){ return m_path; }
00226  Pose getPose(){ clientRead(); return Pose(m_pPosProxy->GetXPos(), m_pPosProxy->GetYPos(), m_pPosProxy->GetYaw()); }
00227  Position getPosition(){ return getPose().pos(); }
00228  Pose getViewpoint();
00229  Scan getScan();
00230  ExplorationParams getExplParams();
00231  
00232  double getSensorRange(){ return m_pLaserProxy->GetMaxRange(); }
00233  double getCoverRange();
00234  double getCoverFieldOfView();
00235  double getWidth(){ return m_pPosProxy->GetSize().sw; }
00236  int getLSRSize(){ return ((m_bFrontierInitialized) ? m_LSR.columns()*m_LSR.rows() : m_prevLSR.columns()*m_prevLSR.rows()); }
00237  vector<Cell* > getRaster( DubInt iCell1, DubInt iCell2 );
00238  double getLSRResolution(){ return ((m_bFrontierInitialized) ? m_LSR.resolution() : m_prevLSR.resolution()); }
00239  Pose getLSRPose();
00240  LSRBound getLSRBound(){ return ((m_bFrontierInitialized) ? m_LSR.lsrBound() : m_prevLSR.lsrBound()); }
00241  Cell* getCell( DubInt indices ){ return ((m_bFrontierInitialized) ? m_LSR.getCell(indices) : m_prevLSR.getCell(indices)); }
00242  Cell* getCell( Position pos ){ return ((m_bFrontierInitialized) ? m_LSR.getCell(pos) : m_prevLSR.getCell(pos)); }
00243  Cell* getCell( int i ){ return ((m_bFrontierInitialized) ? m_LSR.getCell(i) : m_prevLSR.getCell(i)); }
00244  Position getCellPosition( DubInt indices ){ return getCell(indices)->point(); }
00245  int getNumFollowers(){ return m_followers.size(); }
00246  Position getFollowerPosition();
00247  
00248  // State change functions
00249  void setToExpand( Path path, bool bClearPrevFrontier, AgentVector neighbors, bool bDoExpand = true );
00250  void setToGuard( AgentVector neighbors );
00251  void setToFollow( AgentVector neighbors );
00252  void setToWander( AgentVector neighbors );
00253  void setToNoBehavior( );
00254  
00255  void goTo( Pose pose );
00256  void addFollower( PursuitAgent* newFollower, bool bMove = true );
00257  
00258  // This function is called whenever agent is active
00259  void doCurrentBehavior( AgentVector neighbors );
00260  
00261  bool isLeader();
00262  bool isReady();
00263  bool isWaitingForAnyAgent();
00264  bool isWaitingForAgent(int iID);
00265  void clearWaitingForAgent();
00266  bool isTraveling();
00267  
00268  void drawBoundary( Graphics2dProxy &gp );
00269  void drawFrontier( Graphics2dProxy &gp );
00270  void drawLSR( Graphics2dProxy &gp, bool bOnlyLSR );
00271  
00272  bool canDetectTargetPosition( Position targetPos );
00273 };
00274 
00275 // For logging status of algorithm
00276 void logData( ){
00277  double time = gTotalTimer.get().dCast();
00278  int iAreaExposed = 0.0;
00279  
00280  if( gGlobalGrid != NULL )
00281  {
00282   iAreaExposed = gGlobalGrid->_lsr.size();
00283  }
00284  
00285  int iFrontierCount = 0;
00286  int iGuard = 0;
00287  int iExpand = 0;
00288  int iFollow = 0;
00289  int iWander = 0;
00290  for( int i = 0; i < gAgentVector.size(); i++ )
00291  {
00292   switch (gAgentVector[i]->getBehavior()) 
00293   {
00294    case EXPAND:
00295     iExpand++;
00296     iFrontierCount += gAgentVector[i]->getTotalFrontierCells();
00297     break;
00298    case GUARD:
00299     iGuard++;
00300     iFrontierCount += gAgentVector[i]->getTotalFrontierCells();
00301     break;
00302    case FOLLOW:
00303     iFollow++;
00304     break;
00305    case WANDER:
00306     iWander++;
00307     break;
00308    default:
00309     break;
00310   }
00311  }
00312  
00313  gLogFile << gIterCount << ", ";
00314  gLogFile << time << ", ";
00315  gLogFile << iAreaExposed << ", ";
00316  gLogFile << iFrontierCount << ", ";
00317  gLogFile << iExpand << ", ";
00318  gLogFile << iGuard << ", ";
00319  gLogFile << iFollow << ", ";
00320  gLogFile << iWander;
00321  
00322  gLogFile << endl;
00323 }
00324 
00325 PursuitAgent::PursuitAgent( Identity ID, PlayerClient* client, Position2dProxy* posProxy, LaserProxy* laserProxy ){
00326  m_iID = ID;
00327  m_pClient = client;
00328  m_pPosProxy = posProxy;
00329  m_pLaserProxy = laserProxy;
00330  
00331  m_eBehavior = NO_BEHAVIOR;
00332  m_frontier.clear();
00333  m_freeArcs.clear();
00334  m_prevFrontier.clear();
00335  m_LSR = Grid();
00336  m_prevLSR = Grid();
00337  m_bFrontierInitialized = false;
00338  m_path.clear();
00339  m_pWaitForAgent = NULL;
00340  m_followers.clear();
00341  
00342  // Set up position proxy
00343  m_pPosProxy->SetMotorEnable(true);
00344  m_pPosProxy->RequestGeom();
00345  
00346  while( m_pLaserProxy->GetMaxRange() <= 0.0 || m_pLaserProxy->GetCount() <= 0 )
00347  {
00348   //if( gDebug > 9 ) cout<< "  waiting for real data ..." << endl;
00349   clientRead();
00350  }
00351 }
00352 
00353 void PursuitAgent::Expand( AgentVector neighbors ){
00354  if( gDebug > 5 ) cout<< "Agent " << getID() << ":  doing EXPAND to " << m_path.back().print() << endl;
00355  
00356  if( gDebug > 8 ) 
00357  {
00358   cout<< "  " << getID() << " has followers: ";
00359   for( int i = 0; i < m_followers.size(); i++ )
00360   {
00361    cout<< m_followers[i]->getID() << ", ";
00362   }
00363   cout<< endl;
00364  }
00365  
00366  if( isTraveling() )
00367  {
00368   if( gDebug > 5 ) cout<< "  " << getID() << ":  waiting to reach path pose " << m_path.back().print() << endl;
00369   return;
00370  }
00371  
00372  AgentVector::iterator i;
00373  int iCount = 0;
00374  for(i = m_followers.begin(); i != m_followers.end(); i++ )
00375  {
00376   if( getPosition().dist((*i)->getPosition()) > getSensorRange() )
00377   {
00378    if( gDebug > 5 ) cout<< getID() << ": follower " << (*i)->getID() << " still needs to catch up" << endl;
00379    Position followerPosition = getFollowerPosition();
00380    followerPosition *= (Decimal)(iCount+1.0);
00381    (*i)->goTo( Pose(getPosition() - followerPosition, m_path.back().ori()) );
00382   }
00383   iCount++;
00384  }
00385  
00386  //recordLSR();
00387  
00388  setToGuard( neighbors );
00389 }
00390 
00391 void PursuitAgent::Guard( AgentVector neighbors )
00392 {
00393  if( gDebug > 5 ) cout<< "Agent " << getID() << ":  doing GUARD" << endl;
00394  if( gDebug > 8 ) 
00395  {
00396   cout<< "  " << getID() << " has followers: ";
00397   for( int i = 0; i < m_followers.size(); i++ )
00398   {
00399    cout<< m_followers[i]->getID() << ", ";
00400   }
00401   cout<< endl;
00402  }
00403  
00404  // Send excess followers to nearby guards
00405  if( m_bFrontierInitialized && getNumFollowers() > 2 )
00406  {
00407   Position curPos = getLSRPose().pos();
00408   Frontier ourFrontier = m_LSR.frontier();
00409   
00410   vector<PursuitAgent* > nearbyLeaders;
00411   
00412   for( int i = 0; i < neighbors.size(); i++ )
00413   {
00414    if( neighbors[i]->isLeader() && neighbors[i]->getID() != getID() )
00415    {
00416     if( neighbors[i]->getNumFollowers() < getNumFollowers() / 2 )
00417     {
00418      if( curPos.dist( neighbors[i]->getPosition() ) < 2.0 * getSensorRange() )
00419      {
00420       bool bClose = false;
00421     
00422       for( int m = 0; (!bClose && m < ourFrontier.size()); m++ )
00423       {
00424        for( int n = 0; (!bClose && n < ourFrontier[m].size()); n++ )
00425        {
00426         Position cellPos = curPos + m_LSR.getCell(ourFrontier[m][n])->point() - neighbors[i]->getPosition();
00427         Cell* pTheirCell = neighbors[i]->getCell(cellPos);
00428         
00429         if( pTheirCell != NULL && pTheirCell->isLSR() )
00430         {
00431          nearbyLeaders.push_back(neighbors[i]);
00432         }
00433        }
00434       }
00435      }
00436     }
00437    }
00438   }
00439   
00440   if( nearbyLeaders.size() > 0 )
00441   {
00442    int iFollowersToGive = getNumFollowers() / 2;
00443    
00444    while( iFollowersToGive > 0 )
00445    {
00446     for( int i = 0; i < nearbyLeaders.size(); i++ )
00447     {
00448      if( iFollowersToGive > 0 )
00449      {
00450       iFollowersToGive--;
00451       
00452       if( gDebug > 2 ) cout<< "  " << getID() << " giving " << nearbyLeaders[i]->getID() << " follower " << m_followers.back()->getID() << endl;
00453       
00454       nearbyLeaders[i]->addFollower( m_followers.back(), true );
00455       m_followers.pop_back();
00456      }
00457     }
00458    }
00459   }
00460  }
00461  if( m_bFrontierInitialized )
00462  {
00463   Position curPos = getLSRPose().pos();
00464   for( int i = 0; i < m_followers.size(); i++ )
00465   {
00466    Cell* pCell = m_LSR.getCell( m_followers[i]->getPosition() - curPos );
00467    
00468    if( pCell == NULL || !(pCell->isLSR()) )
00469    {
00470     // release follower who is too far away
00471     m_followers[i]->setToWander( neighbors );
00472     m_followers.erase(m_followers.begin() + i);
00473     i--;
00474    }
00475   }
00476  }
00477  
00478  
00479  if( isWaitingForAnyAgent() )
00480  {
00481   if( gDebug > 5 ) cout<< "  " << getID() << ":  is waiting for agent " << m_pWaitForAgent->getID() << endl;
00482   return;
00483  }
00484  
00485  // Update frontier and neighbor's frontiers, only really does anything
00486  // when agent first appears at new viewpoint
00487  updateFrontier( neighbors, (gDebug > 8) );
00488  
00489  // 
00490  processFrontier( neighbors );
00491 }
00492 
00493 void PursuitAgent::processFrontier( AgentVector neighbors )
00494 {
00495  if( getTotalFrontierCells() < gMinArcSize )
00496  {
00497   if( m_pWaitForAgent != NULL )
00498   {
00499    m_pWaitForAgent->setToWander(neighbors);
00500   }
00501   
00502   if( gDebug > 0 ) cout<< getID() << " has only " << getTotalFrontierCells() << " frontier cells, switching to wander" << endl;
00503   
00504   m_frontier.clear();
00505   m_prevFrontier.clear();
00506   
00507   setToWander(neighbors);
00508   return;
00509  }
00510  
00511  int iNumViewPoints;
00512  // Pick single best view point to expand current frontier
00513  Pose bestViewPoint = pickBestViewPoint(&iNumViewPoints, (gDebug > 30));
00514  
00515  if( bestViewPoint == Pose(0,0,(Angle)0) )
00516  {
00517   if( iNumViewPoints == 1 || m_followers.size() > 0 )
00518   {
00519    // Error condition, happens when stage screws up and produces arcs in impossible places.
00520    //cout<< "WARNING:  best viewpoint for " << getID() << " set to current pose!" << endl;
00521    
00522    //cout<< getID() << " switching to WANDER!" << endl;
00523    //if( m_pWaitForAgent != NULL )
00524    //{
00525     //m_pWaitForAgent->setToWander();
00526    //}
00527    
00528    //setToWander();
00529    return;
00530   }
00531  }
00532  
00533  bestViewPoint = Pose( bestViewPoint.pos() + getLSRPose().pos(), bestViewPoint.ori() );
00534  //if( gDebug > 8 ) cout<< "    Best view point (" << bestViewPoint.x() << "," << bestViewPoint.y() << ")" << endl;
00535  bestViewPoint = adjustViewPoint( bestViewPoint );
00536  if( gDebug > 8 ) cout<< "    Best view point (" << bestViewPoint.print() << ")" << endl;
00537  
00538  // Optimal path to new viewpoint is straight line from current VP to new point,
00539  // never a need to avoid obstacles
00540  Path pathToBestViewPoint;
00541  pathToBestViewPoint.push_back( getPose() );
00542  pathToBestViewPoint.push_back( bestViewPoint );
00543  
00544  if( m_pWaitForAgent != NULL )
00545  {
00546   // Re-route agent who is already expanding, desired new view point might have changed after
00547   // part of our frontier was cleared
00548   m_pWaitForAgent->setToExpand( pathToBestViewPoint, true, neighbors );
00549  }
00550  else if( iNumViewPoints == 1 )
00551  {
00552   if( gDebug > 8 ) cout<< "    Expanding alone" << endl;
00553   
00554   // Agent decides it can expand alone.  For experiments, may not want to do this depending on
00555   // how mutual localization is handled.
00556   
00557   // Save frontier, LSR for this point so that we can use it to determine new frontier when
00558   // arriving at new location
00559   if( m_bFrontierInitialized )
00560   {
00561    m_prevFrontier = m_frontier;
00562    m_prevLSR = m_LSR;
00563   }
00564   
00565   setToExpand( pathToBestViewPoint, false, neighbors );
00566   
00567   // TODO: auction off extra followers?
00568  }
00569  else
00570  {
00571   if( m_followers.size() > 0 )
00572   {
00573    if( gDebug > 8 ) cout<< "    Sending follower " << m_followers.back()->getID() << endl;
00574    
00575    // TODO: what to do about far away followers who may not be close to current viewpoint?
00576    
00577    PursuitAgent* pExpander = m_followers.front();
00578    m_pWaitForAgent = pExpander;
00579    pExpander->setToExpand( pathToBestViewPoint, true, neighbors );
00580    m_followers.erase(m_followers.begin());
00581    
00582    int iMaxNumFollowersToGive = std::min( m_followers.size(), (m_followers.size() + 1)/(iNumViewPoints) );
00583    
00584    if( gDebug > 8 ) cout<< "    Giving follower " << iMaxNumFollowersToGive << " followers out of " << m_followers.size() << endl;
00585    for( int i = 0; i < iMaxNumFollowersToGive; i++ )
00586    {
00587     pExpander->addFollower( m_followers.back() );
00588     m_followers.pop_back();
00589    }
00590   }
00591   else
00592   {
00593    // Wait for followers to join us, or for someone else to clear part of our frontier
00594   }
00595   
00596   // This agent will keep doing guard behavior on next iteration
00597  }
00598 }
00599 
00600 void PursuitAgent::Wander( AgentVector neighbors )
00601 {
00602  if( gDebug > 5 ) cout<< "Agent " << getID() << " doing WANDER" << endl;
00603  AgentVector leaders;
00604  vector<Pose > leaderPaths;
00605  AgentVector allLeaders;
00606  AgentVector wanderers;
00607  
00608  recordLSR();
00609  Frontier ourFrontier = m_LSR.frontier();
00610  
00611  Position curPos = getPosition();
00612  
00613  // Create list of nearby agents of different types
00614  for( int i = 0; i < neighbors.size(); i++ )
00615  {
00616   if( neighbors[i]->isLeader() && neighbors[i]->getID() != getID() )
00617   {
00618    allLeaders.push_back(neighbors[i]);
00619 
00620    if( curPos.dist( neighbors[i]->getPosition() ) < 2.0*getSensorRange() )
00621    {
00622     bool bClose = false;
00623     
00624     for( int m = 0; (!bClose && m < ourFrontier.size()); m++ )
00625     {
00626      for( int n = 0; (!bClose && n < ourFrontier[m].size()); n++ )
00627      {
00628       Position cellPos = curPos + m_LSR.getCell(ourFrontier[m][n])->point() - neighbors[i]->getLSRPose().pos();
00629       Cell* pTheirCell = neighbors[i]->getCell(cellPos);
00630       
00631       if( pTheirCell != NULL && pTheirCell->isLSR() )
00632       {
00633        if( gDebug > 8 )
00634        {
00635         drawSquare( gColorBlue, curPos + m_LSR.getCell(ourFrontier[m][n])->point(), 0.05, false );
00636         usleep( 300000 );
00637        }
00638        leaders.push_back(neighbors[i]);
00639        leaderPaths.push_back( Pose(curPos + m_LSR.getCell(ourFrontier[m][n])->point(), Angle(M_PI) + pTheirCell->point().bearing()));
00640        bClose = true;
00641       }
00642      }
00643     }
00644    }
00645   }
00646   else if( neighbors[i]->getBehavior() == WANDER )
00647   {
00648    if( neighbors[i]->getID() != getID() )
00649    {
00650     if( curPos.dist( neighbors[i]->getPosition() ) < getSensorRange() )
00651     {
00652      Cell* pCell = m_LSR.getCell(neighbors[i]->getPosition() - curPos);
00653      if( pCell != NULL && pCell->isLSR() )
00654      {
00655       wanderers.push_back(neighbors[i]);
00656      }
00657     }
00658    }
00659   }
00660  }
00661  
00662  // Look for new leader to follow
00663  if( leaders.size() > 0 )
00664  {
00665   int iNewLeader = -1;
00666   int iMinFollowers = 10;
00667   
00668   for( int i = 0; i < leaders.size(); i++ )
00669   {
00670    int iFollowers = leaders[i]->getNumFollowers() + (leaders[i]->isWaitingForAnyAgent() ? 1 : 0);
00671    
00672    if( (iFollowers < iMinFollowers) ||
00673     ((iNewLeader >= 0) && (iFollowers == iMinFollowers) && (getPosition().dist(leaders[i]->getPosition()) < getPosition().dist(leaders[iNewLeader]->getPosition()))) )
00674    {
00675     iNewLeader = i;
00676     iMinFollowers = iFollowers;
00677    }
00678   }
00679   
00680   if( iNewLeader >= 0 )
00681   {
00682    Cell* pOurCell = m_LSR.getCell( leaders[iNewLeader]->getPosition() - curPos );
00683    Cell* pTheirCell = leaders[iNewLeader]->getCell( curPos - leaders[iNewLeader]->getPosition() );
00684    if( (pOurCell != NULL && pOurCell->isLSR()) || (pTheirCell != NULL && pTheirCell->isLSR()) )
00685    {
00686     for( int j = 0; j < m_followers.size(); j++ )
00687     {
00688      m_followers[j]->setToFollow(neighbors);
00689      leaders[iNewLeader]->addFollower(m_followers[j]);
00690     }
00691     
00692     m_followers.clear();
00693     
00694     setToFollow(neighbors);
00695     leaders[iNewLeader]->addFollower(this);
00696     return;
00697    }
00698    else
00699    {
00700     // follow path towards leader
00701     if( m_path.size() > 0 && curPos.dist(m_path.back().pos()) > getWidth() )
00702     {
00703      Cell* pTheirCell = leaders[iNewLeader]->getCell( m_path.back().pos() - leaders[iNewLeader]->getLSRPose().pos());
00704      if( pTheirCell != NULL && pTheirCell->isLSR() )
00705      {
00706       goTo( m_path.back() );
00707       return;
00708      }
00709     }
00710     
00711     goTo( leaderPaths[iNewLeader] );
00712     return;
00713    }
00714   }
00715  }
00716  
00717  if( gDebug > 5 ) cout<< "    " << getID() << " no leader to follow" << endl;
00718  
00719  /*
00720  // group with nearby wanderers into a wandering blob
00721  if( wanderers.size() > 0 )
00722  {
00723   for( int j = 0; j < m_followers.size(); j++ )
00724   {
00725    m_followers[j]->setToFollow();
00726    wanderers[0]->addFollower(m_followers[j]);
00727   }
00728   
00729   m_followers.clear();
00730   
00731   setToFollow();
00732   wanderers[0]->addFollower(this);
00733   return;
00734  }
00735  */
00736  Frontier frontier = m_LSR.frontier();
00737  
00738  if( m_path.size() > 0 )
00739  {
00740   if( curPos.dist( m_path.back().pos() ) > 1.5*getWidth() )
00741   {
00742    if( pickIndexInRange(0,20) != 0 )
00743    {
00744     // stick to current path ...
00745     return;
00746    }
00747   }
00748  }
00749  
00750  // Random walk to some point on current frontier
00751  if( frontier.size() > 0 )
00752  {
00753   Position bestRandPos = curPos;
00754   double bestRandPosValue = -1000.0;
00755   
00756   int iFrontierCells = 0;
00757   for( int i = 0; i < frontier.size(); i++ )
00758   {
00759    iFrontierCells += frontier[i].size();
00760   }
00761   
00762   for( int i = 0; i < 10; i++ )
00763   {
00764    int iRand = pickIndexInRange( 0, iFrontierCells );
00765    Position randPos = curPos;
00766    
00767    for( int j = 0; j < frontier.size(); j++ )
00768    {
00769     if( iRand < frontier[j].size() )
00770     {
00771      randPos += m_LSR.getCell(frontier[j][iRand])->point();
00772      break;
00773     }
00774     else
00775     {
00776      iRand -= frontier[j].size();
00777     }
00778    }
00779    
00780    double randPosValue = 10.0*(pickIndexInRange(0, 100))/100.0;
00781    
00782    double distDiv = 6.0 * m_pLaserProxy->GetMaxRange();
00783    double closestDistance = distDiv;
00784    for( int j = 0; j < allLeaders.size(); j++ )
00785    {
00786     closestDistance = std::min( closestDistance, randPos.dist( allLeaders[j]->getPosition() ) );
00787    }
00788    
00789    randPosValue += 5.0*(distDiv - closestDistance)/distDiv;
00790    
00791    randPosValue += 5.0*(M_PI - fabs((randPos - curPos).bearing().alDiff(m_pPosProxy->GetYaw())))/(M_PI);
00792    
00793    if( randPosValue > bestRandPosValue )
00794    {
00795     bestRandPos = randPos;
00796     bestRandPosValue = randPosValue;
00797    }
00798   }
00799   
00800   Position bestGoToPos = curPos;
00801   double bestGoToDist = curPos.dist( bestRandPos );
00802   
00803   for( int i = 0; i < m_LSR._lrr.size(); i++ )
00804   {
00805    Position testPos = curPos + m_LSR.getCell(m_LSR._lrr[i])->point();
00806    double dist = bestRandPos.dist( testPos );
00807    if( dist < bestGoToDist )
00808    {
00809     bestGoToDist = dist;
00810     bestGoToPos = testPos;
00811    }
00812   }
00813   
00814   if( gDebug > 8 )
00815   {
00816    drawRedX( bestRandPos, 0.05 );
00817    drawX( gColorGreen, bestGoToPos, 0.05 );
00818    usleep( 100000 );
00819   }
00820   
00821   m_path.clear();
00822   
00823   m_path.push_back( getPose() );
00824   Position relPos = bestGoToPos - curPos;
00825   m_path.push_back( Pose(bestGoToPos, relPos.bearing()) );
00826   
00827   goTo( m_path.back() );
00828  }
00829 }
00830 
00831 void PursuitAgent::clientRead()
00832 {
00833  //while( m_pClient->Peek(0) )
00834  {
00835   m_pClient->ReadIfWaiting();
00836  }
00837 }
00838 
00839 
00840 void PursuitAgent::getNeighborFrontiers( AgentVector neighbors, Pose &curPose, vector<Frontier > &ourNeighborFrontiers, 
00841    vector<Frontier > &updatedNeighborFrontiers,
00842    vector<DubInt > &neighborObstacleEndpoints,
00843    vector<DubInt > &neighborObstacleBeginpoints )
00844 {
00845  player_color_t color;
00846  
00848  // Process our previous frontier as if it is a neighbor frontier
00849  //
00850  // This is to handle situation where robot has self-expanded.
00852  if( m_prevFrontier.size() > 0 )
00853  {
00854   if( gDebug > 7 ) cout<< "    " << getID() << " has " << m_prevFrontier.size() << " prev frontier(s)" << endl;
00855   Pose neighborPose = m_prevLSR.center();
00856   Frontier ourNeighborFrontier;
00857   // Previous frontier for an agent expanding on its own acts like a neighbor's frontier
00858   for( int j = 0; j < m_prevFrontier.size(); j++ )
00859   {
00860    FrontierArc neighborArc = m_prevFrontier[j];
00861    FrontierArc translatedArc;
00862    Cell* pTranslatedCell;
00863    //Cell* pRotTranslatedCell;
00864    Position translatedPos;
00865    
00866    if( m_prevLSR.getCell(neighborArc[0])->isLabelA() )
00867    {
00868     Position arcCellPos = m_prevLSR.getCell(neighborArc[0])->point();
00869     Position globalPos = neighborPose.pos() + arcCellPos;
00870     translatedPos = neighborPose.pos() - curPose.pos() + arcCellPos;
00871     
00872     pTranslatedCell = m_LSR.getCell( translatedPos );
00873     
00874     if( pTranslatedCell != NULL )
00875     {
00876      neighborObstacleBeginpoints.push_back(pTranslatedCell->indexes());
00877     
00878      if( gDebug > 9 ) cout<< "    prev obstacle beginpoint at " << neighborObstacleBeginpoints.back().print() << endl;
00879     }
00880    }
00881    
00882    if( m_prevLSR.getCell(neighborArc[neighborArc.size()-1])->isLabelB() )
00883    {
00884     if( !(m_prevLSR.getCell(neighborArc[neighborArc.size()-1])->isLabelA()) )
00885     {
00886      Position arcCellPos = m_prevLSR.getCell(neighborArc[neighborArc.size()-1])->point();
00887      Position globalPos = neighborPose.pos() + arcCellPos;
00888      translatedPos = neighborPose.pos() - curPose.pos() + arcCellPos;
00889      
00890      pTranslatedCell = m_LSR.getCell( translatedPos );
00891      
00892      if( pTranslatedCell != NULL )
00893      {
00894       neighborObstacleEndpoints.push_back(pTranslatedCell->indexes());
00895       
00896       if( gDebug > 9 ) cout<< "    prev obstacle endpoint at " << neighborObstacleEndpoints.back().print() << endl;
00897      }
00898     }
00899    }
00900    
00901    //if( gDebug > 7 ) cout<< "      " << neighbors[i]->getID() << " had arc of size " << neighborArc.size() << endl;
00902    
00903    for( int k = 0; k < neighborArc.size(); k++ )
00904    {
00905     Position arcCellPos = m_prevLSR.getCell(neighborArc[k])->point();
00906     Position globalPos = neighborPose.pos() + arcCellPos;
00907     translatedPos = neighborPose.pos() - curPose.pos() + arcCellPos;
00908     
00909     pTranslatedCell = m_LSR.getCell( translatedPos );
00910     
00911     //cout<< "Arc cell " << k << " at " << arcCellPos.print() << " relative to " << neighborPos.print() << endl;
00912     //cout<< "  at " << globalPos.print() << " in global frame" << endl;
00913     
00914     //cout<< "  at " << translatedPos.print() << " relative to " << curPos.print() << endl;
00915     
00916     if( pTranslatedCell == NULL )
00917     {
00918      // Means that position is outside of our LSR grid
00919      if( translatedArc.size() >= 0 )
00920      {
00921       // Put relevant fragment into our stored arcs
00922       ourNeighborFrontier.push_back(translatedArc);
00923       translatedArc = FrontierArc();
00924      }
00925      
00926      color.alpha = 0;
00927      color.red = 255;
00928      color.green = 0;
00929      color.blue = 255;
00930     }
00931     else
00932     {
00933      // If cell is outside of our LSR or on our frontier, leave it in updated neighbor's frontier
00934      if( (!(pTranslatedCell->isLSR()) || pTranslatedCell->isFrontier()) && !(pTranslatedCell->isObstacle()) )
00935      {
00936       //updatedNeighborArc.push_back(neighborArc[k]);
00937       color.alpha = 0;
00938       color.red = 0;
00939       color.green = 0;
00940       color.blue = 255;
00941      }
00942      else
00943      {
00944       color.alpha = 0;
00945       color.red = 255;
00946       color.green = 0;
00947       color.blue = 0;
00948      }
00949      
00950      translatedArc.push_back( pTranslatedCell->indexes() );
00951     }
00952     
00953     //if( bDebugDisplay ) drawSquare( color, globalPos, 0.01, true );
00954    }
00955    
00956    if( translatedArc.size() >= 0 )
00957    {
00958     ourNeighborFrontier.push_back(translatedArc);
00959    }
00960   }
00961   
00962   if( ourNeighborFrontier.size() > 0 )
00963   {
00964    ourNeighborFrontiers.push_back(ourNeighborFrontier);
00965   }
00966  }
00967  
00968  
00970  // Get and process arcs from all neighbors
00972  for( int i = 0; i < neighbors.size(); i++ ){
00973   updatedNeighborFrontiers.push_back( Frontier() );
00974   
00975   if( neighbors[i]->isLeader() && (neighbors[i]->getID() != getID()) )
00976   {
00977    Pose neighborPose = neighbors[i]->getLSRPose();
00978    
00979    if( neighborPose.pos().dist(curPose.pos()) > gOverlapFactor*(getSensorRange() + neighbors[i]->getSensorRange()) )
00980    {
00981     if( gDebug > 7 ) cout<< "    " << getID() << " ignoring distant agent " << neighbors[i]->getID() << endl;
00982     continue;
00983    }
00984    
00985    if( gDebug > 7 ) cout<< "    " << getID() << " updating agent " << neighbors[i]->getID() << " frontiers" << endl;
00986    
00987    // In asynchronous implementation, would need to take over control of
00988    // neighbors frontiers, so they don't send it to anyone else
00989    Frontier neighborFrontier = neighbors[i]->getFrontier();
00990    
00991    Frontier updatedNeighborFrontier;
00992    Frontier ourNeighborFrontier;
00993    
00994    for( int j = 0; j < neighborFrontier.size(); j++ )
00995    {
00996     FrontierArc neighborArc = neighborFrontier[j];
00997     FrontierArc updatedNeighborArc;
00998     
00999     // Represent neighbors arc in our grid, requires either grids to
01000     // (mostly) be aligned or to have some smart handling of correspondence.
01001     // In experimental 
01002     FrontierArc translatedArc;
01003     Cell* pTranslatedCell;
01004     //Cell* pRotTranslatedCell;
01005     Position translatedPos;
01006     
01007     if( neighbors[i]->getCell(neighborArc[0])->isLabelA() )
01008     {
01009      Position arcCellPos = neighbors[i]->getCellPosition(neighborArc[0]);
01010      Position globalPos = neighborPose.pos() + arcCellPos;
01011      translatedPos = neighborPose.pos() - curPose.pos() + arcCellPos;
01012      
01013      pTranslatedCell = m_LSR.getCell( translatedPos );
01014      
01015      if( pTranslatedCell != NULL )
01016      {
01017       neighborObstacleBeginpoints.push_back(pTranslatedCell->indexes());
01018      
01019       if( gDebug > 9 ) cout<< "    neighbor obstacle beginpoint at " << neighborObstacleBeginpoints.back().print() << endl;
01020      }
01021     }
01022     
01023     if( neighbors[i]->getCell(neighborArc[neighborArc.size()-1])->isLabelB() )
01024     {
01025      if( !(neighbors[i]->getCell(neighborArc[neighborArc.size()-1])->isLabelA()) )
01026      {
01027       Position arcCellPos = neighbors[i]->getCellPosition(neighborArc[neighborArc.size()-1]);
01028       Position globalPos = neighborPose.pos() + arcCellPos;
01029       translatedPos = neighborPose.pos() - curPose.pos() + arcCellPos;
01030       
01031       pTranslatedCell = m_LSR.getCell( translatedPos );
01032       
01033       if( pTranslatedCell != NULL )
01034       {
01035        neighborObstacleEndpoints.push_back(pTranslatedCell->indexes());
01036        
01037        if( gDebug > 9 ) cout<< "    neighbor obstacle endpoint at " << neighborObstacleEndpoints.back().print() << endl;
01038       }
01039      }
01040     }
01041     
01042     if( gDebug > 7 ) cout<< "      " << neighbors[i]->getID() << " had arc of size " << neighborArc.size() << endl;
01043     
01044     bool bPrevErased = false;
01045     for( int k = 0; k < neighborArc.size(); k++ )
01046     {
01047      Position arcCellPos = neighbors[i]->getCellPosition(neighborArc[k]);
01048      Position globalPos = neighborPose.pos() + arcCellPos;
01049      translatedPos = neighborPose.pos() - curPose.pos() + arcCellPos;
01050      
01051      pTranslatedCell = m_LSR.getCell( translatedPos );
01052      
01053      //cout<< "Arc cell " << k << " at " << arcCellPos.print() << " relative to " << neighborPos.print() << endl;
01054      //cout<< "  at " << globalPos.print() << " in global frame" << endl;
01055      
01056      //cout<< "  at " << translatedPos.print() << " relative to " << curPos.print() << endl;
01057      
01058      if( pTranslatedCell == NULL )
01059      {
01060       // Means that position is outside of our LSR grid
01061       
01062       // Neighbor should keep this cell
01063       updatedNeighborArc.push_back(neighborArc[k]);
01064       
01065       if( translatedArc.size() > 0 )
01066       {
01067        // Put any relevant fragment we were accumulating into our stored arcs
01068        ourNeighborFrontier.push_back(translatedArc);
01069        translatedArc = FrontierArc();
01070       }
01071       
01072       color.alpha = 0;
01073       color.red = 255;
01074       color.green = 0;
01075       color.blue = 255;
01076      }
01077      else
01078      {
01079       bool bErase = false;
01080       
01081       if( pTranslatedCell->isObstacle() )
01082       {
01083        bErase = true;
01084       }
01085       else if( pTranslatedCell->isFrontier() )
01086       {
01087        bErase = true;
01088       }
01089       else if( pTranslatedCell->isLSR() )
01090       {
01091        bErase = true;
01092       }
01093       else
01094       {
01095        // Outside visibility, probably don't erase
01096        
01097        bErase = false;
01098        
01099        vector<Cell* > surroundingCells = pTranslatedCell->neighbours();
01100        
01101        int iObstacle = 0;
01102        for( int l = 0; l < surroundingCells.size(); l++ )
01103        {
01104         if( surroundingCells[l]->isObstacle() )
01105         {
01106          // This catches certain circumstances where one cell of neighbor's arc lies inside
01107          // an obstacle in this agent's view.  Happens more when grids are poorly aligned.
01108          // May not be necessary or best way to catch these conditions
01109          iObstacle++;
01110          
01111          if( iObstacle > 2 )
01112          {
01113           bErase = true;
01114          }
01115         }
01116         else if( surroundingCells[l]->isLSR() )
01117         {
01118          bErase = false;
01119          break;
01120         }
01121        }
01122        
01123        if( iObstacle > 0 ) cout<< iObstacle << " out of " << surroundingCells.size() << endl;
01124       }
01125       
01126       if( bErase && !bPrevErased && k == neighborArc.size()-1 )
01127       {
01128        if( neighbors[i]->getCell(neighborArc[k])->isLabelB() )
01129        {
01130         // Save obstacle end point
01131         bErase = false;
01132        }
01133       }
01134       
01135       // If cell is outside of our LSR, leave it in updated neighbor's frontier
01136       if( !bErase )
01137       {
01138        if( k == 1 && bPrevErased ) 
01139        {
01140         if( neighbors[i]->getCell(neighborArc[0])->isLabelA() )
01141         {
01142          // Save obstacle begin point
01143          updatedNeighborArc.push_back(neighborArc[0]);
01144         }
01145        }
01146        updatedNeighborArc.push_back(neighborArc[k]);
01147        
01148        color.alpha = 0;
01149        color.red = 0;
01150        color.green = 0;
01151        color.blue = 255;
01152       }
01153       else
01154       {
01155        if( updatedNeighborArc.size() > 0 )
01156        {
01157         if( updatedNeighborArc.size() >= gMinMergeArcSize )
01158         {
01159          if( gDebug > 7 ) cout<< "      adding neighbor arc of size " << (updatedNeighborArc.size()) << endl;
01160          updatedNeighborFrontier.push_back(updatedNeighborArc);
01161         }
01162         else
01163         {
01164          if( gDebug > 7 ) cout<< "      clearing temp neighbor arc of size " << (updatedNeighborArc.size()) << endl;
01165          updatedNeighborFrontier.push_back(updatedNeighborArc);
01166         }
01167         
01168         updatedNeighborArc = FrontierArc();
01169        }
01170        
01171        color.alpha = 0;
01172        color.red = 255;
01173        color.green = 0;
01174        color.blue = 0;
01175       }
01176       
01177       // Add cell to our translated arc
01178       translatedArc.push_back( pTranslatedCell->indexes() );
01179       
01180       bPrevErased = bErase;
01181      }
01182      
01183      //if( bDebugDisplay ) drawSquare( color, globalPos, 0.01, true );
01184      
01185     }
01186     
01187     if( updatedNeighborArc.size() >= gMinMergeArcSize )
01188     {
01189      if( gDebug > 7 ) cout<< "      replacing neighbor arc with one of size " << updatedNeighborArc.size() << endl;
01190      updatedNeighborFrontier.push_back(updatedNeighborArc);
01191     }
01192     else
01193     {
01194      if( gDebug > 7 ) cout<< "      clearing temp neighbor arc (end) of size " << (updatedNeighborArc.size()) << endl;
01195     }
01196     
01197     if( translatedArc.size() > 0 )
01198     {
01199      ourNeighborFrontier.push_back(translatedArc);
01200     }
01201    }
01202    
01203    updatedNeighborFrontiers[i] = updatedNeighborFrontier;
01204    
01205    if( ourNeighborFrontier.size() > 0 )
01206    {
01207     ourNeighborFrontiers.push_back(ourNeighborFrontier);
01208    }
01209    
01210   }
01211  }
01212  
01213 }
01214 
01215 
01216 void PursuitAgent::classifyOurFrontier( AgentVector neighbors, Pose &curPose, vector<Frontier > &ourNeighborFrontiers, 
01217    vector<DubInt > &neighborObstacleEndpoints,
01218    vector<DubInt > &neighborObstacleBeginpoints,
01219    bool bDebugDisplay )
01220 {
01221  player_color_t color;
01222  
01224  // Classify our frontier arcs based on intersections with neighbors' arcs
01226  Frontier orangeFrontier;
01227  Frontier purpleFrontier;
01228  FrontierArc tempFrontierArc;
01229  FrontierArc tempFreeArc;
01230  bool bOrange = true;
01231  KeepColor keepColor = KEEP_UNKNOWN;
01232  
01233  LSRBound lsrBound = m_LSR.lsrBound();
01234  
01235  // Need to find where on lsrBound to start classification loop, if there is an obstacle then we'll start there
01236  // so that we don't split a frontier arc.
01237  int iOffset = 0;
01238  for( int l = 0; l < lsrBound.size(); l++ )
01239  {
01240   int iIndex = (l + iOffset)%lsrBound.size();
01241   DubInt iBoundCell = lsrBound[iIndex];
01242   Cell* pBoundCell = m_LSR.getCell(iBoundCell);
01243   
01244   if( pBoundCell->isObstacle() &&  
01245     m_LSR.getCell(lsrBound[(l + 1 + iOffset)%lsrBound.size()])->isObstacle() &&
01246     m_LSR.getCell(lsrBound[(l - 1 + iOffset)%lsrBound.size()])->isObstacle() )
01247   {
01248    iOffset = l;
01249    break;
01250   }
01251  }
01252  
01253  // Loop classifying boundary of our LSR.  At this point, m_frontier has been initialized to
01254  // be all the free arcs of LSR (or what frontier would be if there were no neighbors).  
01255  // After this loop we'll set m_frontier to its proper value after classifing free arcs.
01256  int iCurArc = -1;
01257  for( int l = 0; l < lsrBound.size(); l++ )
01258  {
01259   int iIndex = (l + iOffset)%lsrBound.size();
01260   DubInt iBoundCell = lsrBound[iIndex];
01261   Cell* pBoundCell = m_LSR.getCell(iBoundCell);
01262   Position globalPos = curPose.pos() + pBoundCell->point();
01263   int iThisArc = -1;
01264   
01265   // Is this LSR boundary cell on the free part of boundary?  (ie, it's a potential frontier cell)
01266   bool bFrontierCell = false;
01267   for( int i = 0; (i < m_frontier.size() && !bFrontierCell); i++ )
01268   {
01269    FrontierArc arc = m_frontier[i];
01270    for( int j = 0; (j < arc.size() && !bFrontierCell); j++ )
01271    {
01272     if( iBoundCell == arc[j] )
01273     {
01274      bFrontierCell = true;
01275      iThisArc = i;
01276      break;
01277     }
01278    }
01279   }
01280   
01281   // Controls whether to break arcs into radial/curved segments or connect them
01282   bool bBreakArc = false;
01283   //bool bBreakArc = (iCurArc >= 0);
01284   //bBreakArc &= (iCurArc != iThisArc);
01285   
01286   // Build list of our free arcs (result should be the similar to m_LSR.frontier())
01287   if( !bFrontierCell || (bBreakArc) )
01288   {
01289    if( tempFreeArc.size() > 0 )
01290    {
01291     m_freeArcs.push_back(tempFreeArc);
01292     tempFreeArc = FrontierArc();
01293    }
01294   }
01295   
01296   if( bFrontierCell )
01297   {
01298    if( tempFreeArc.size() > 0 && tempFreeArc[tempFreeArc.size()-1] == iBoundCell )
01299    {
01300     cerr<< "***Warning***:  Free arc: Repeated cell in boundary at " << iBoundCell.print() << ".  Ignoring repeat." << endl;
01301     cerr<< "                Cell num " << iIndex << " out of " << lsrBound.size() << endl;
01302    }
01303    else
01304    {
01305     tempFreeArc.push_back(iBoundCell);
01306    }
01307   }
01308   
01309   if( !bFrontierCell || bBreakArc )
01310   {
01311    if( tempFrontierArc.size() > 0 )
01312    {
01313     if( tempFrontierArc.size() >= gMinMergeArcSize )
01314     {
01315      if( bOrange )
01316      {
01317       if( gDebug > 8 ) cout<< "Pushing temp arc with " << tempFrontierArc.size() << " cells to orange" << endl;
01318       orangeFrontier.push_back(tempFrontierArc);
01319      }
01320      else
01321      {
01322       if( gDebug > 8 ) cout<< "Pushing temp arc with " << tempFrontierArc.size() << " cells to purple" << endl;
01323       purpleFrontier.push_back(tempFrontierArc);
01324      }
01325     }
01326     
01327     if( gDebug > 8 ) cout<< "Clearing temp arc with " << tempFrontierArc.size() << " cells" << endl;
01328     tempFrontierArc = FrontierArc();
01329    }
01330   }
01331   
01332   // Build lists of free arc segments classified by color, one color will be our true frontier
01333   if( bFrontierCell )
01334   {
01335    //if( gDebug > 8 ) cout<< "  Adding cell at " << globalPos.print() << " to temp frontier arc" << endl;
01336    if( tempFrontierArc.size() > 0 && tempFrontierArc[tempFrontierArc.size()-1] == iBoundCell )
01337    {
01338     cerr<< "***Warning***:  Frontier Arc: Repeated cell in boundary at " << iBoundCell.print() << ".  Ignoring repeat." << endl;
01339     cerr<< "                Cell num " << iIndex << " out of " << lsrBound.size() << endl;
01340    }
01341    else
01342    {
01343     //if( gDebug > 9 ) cout<< "      Adding frontier cell " << iBoundCell.print() << endl;
01344     tempFrontierArc.push_back(iBoundCell);
01345    }
01346   }
01347   
01348   if( iThisArc >= 0 )
01349   {
01350    iCurArc = iThisArc;
01351   }
01352   
01353   if( bDebugDisplay )
01354   {
01355    if( bOrange )
01356    {
01357     color.alpha = 0;
01358     color.red = 255;
01359     color.green = 255;
01360     color.blue = 0;
01361     
01362     if( pBoundCell->isFrontier() )
01363     {
01364      color.green = 125;
01365     }
01366    }
01367    else
01368    {
01369     color.alpha = 0;
01370     color.red = 255;
01371     color.green = 0;
01372     color.blue = 255;
01373     
01374     if( pBoundCell->isFrontier() )
01375     {
01376      color.red = 150;
01377     }
01378    }
01379    
01380    drawSquare( color, globalPos, 0.01, true );
01381   }
01382   
01383   //if( gDebug > 8 && pBoundCell->isFrontier() ) cout<< "Checking frontier cell " << iBoundCell.print() << endl;
01384   
01385   // Find any intersections and, if there's an intersection, consider switching colors
01386   for( int i = 0; i < ourNeighborFrontiers.size(); i++ )
01387   {
01388    for( int j = 0; j < ourNeighborFrontiers[i].size(); j++ )
01389    {
01390     FrontierArc ourNeighborArc = ourNeighborFrontiers[i][j];
01391     
01392     for( int k = 0; k < ourNeighborArc.size(); k++ )
01393     {
01394      bool bChangeIntToExt = false;
01395      bool bChangeExtToInt = false;
01396      
01397      bool bObsEndpoint = false;
01398      bool bObsBeginpoint = false;
01399      
01400      if( (k == 0) )
01401      {
01402       for( int l = 0; l < neighborObstacleBeginpoints.size(); l++ )
01403       {
01404        if( ourNeighborArc[k] == neighborObstacleBeginpoints[l] )
01405        {
01406         bObsBeginpoint = true;
01407         break;
01408        }
01409       }
01410      }
01411      
01412      if( (k == (ourNeighborArc.size() - 1)) )
01413      {
01414       for( int l = 0; l < neighborObstacleEndpoints.size(); l++ )
01415       {
01416        if( ourNeighborArc[k] == neighborObstacleEndpoints[l] )
01417        {
01418         bObsEndpoint = true;
01419         break;
01420        }
01421       }
01422      }
01423      
01424      int iPrevLSRFlag = 0;
01425      int iNextLSRFlag = 0;
01426      
01427      bool bObsPoint = (bObsBeginpoint && !bObsEndpoint) || (!bObsBeginpoint && bObsEndpoint);
01428      
01429      if(bObsPoint || iBoundCell == ourNeighborArc[k])
01430      {
01431       // LSRFlag values:
01432       // -1 : outside LSR
01433       //  0 : on boundary
01434       // +1 : inside LSR
01435       
01436       // have to check up to min arc size cells to classify as a crossing
01437       if( k >= 1 )
01438       {
01439        Cell* pPrevArcCell = m_LSR.getCell(ourNeighborArc[k-1]);
01440        if( !(pPrevArcCell->isBoundary()) )
01441        {
01442         if( pPrevArcCell->isLSR() )
01443         {
01444          iPrevLSRFlag = 1;
01445          for( int m = 2; m <= k && m <= gMinMergeArcSize; m++ )
01446          {
01447           pPrevArcCell = m_LSR.getCell(ourNeighborArc[k-m]);
01448           if( (pPrevArcCell->isBoundary()) || !(pPrevArcCell->isLSR()) )
01449           {
01450            iPrevLSRFlag = 0;
01451            break;
01452           }
01453          }
01454         }
01455         else
01456         {
01457          iPrevLSRFlag = -1;
01458          for( int m = 2; m <= k && m <= gMinMergeArcSize; m++ )
01459          {
01460           pPrevArcCell = m_LSR.getCell(ourNeighborArc[k-m]);
01461           if( (pPrevArcCell->isBoundary()) || (pPrevArcCell->isLSR()) )
01462           {
01463            iPrevLSRFlag = 0;
01464            break;
01465           }
01466          }
01467         }
01468        }
01469       }
01470       
01471       if( k <= (ourNeighborArc.size() - 2) )
01472       {
01473        Cell* pNextArcCell = m_LSR.getCell(ourNeighborArc[k+1]);
01474        if( !(pNextArcCell->isBoundary()) )
01475        {
01476         if( pNextArcCell->isLSR() )
01477         {
01478          iNextLSRFlag = 1;
01479          for( int m = 2; m <= (ourNeighborArc.size() - 1 - k) && m <= gMinMergeArcSize; m++ )
01480          {
01481           pNextArcCell = m_LSR.getCell(ourNeighborArc[k+m]);
01482           if( (pNextArcCell->isBoundary()) || !(pNextArcCell->isLSR()) )
01483           {
01484            iNextLSRFlag = 0;
01485            break;
01486           }
01487          }
01488         }
01489         else
01490         {
01491          iNextLSRFlag = -1;
01492          for( int m = 2; m <= (ourNeighborArc.size() - 1 - k) && m <= gMinMergeArcSize; m++ )
01493          {
01494           pNextArcCell = m_LSR.getCell(ourNeighborArc[k+m]);
01495           if( (pNextArcCell->isBoundary()) || (pNextArcCell->isLSR()) )
01496           {
01497            iNextLSRFlag = 0;
01498            break;
01499           }
01500          }
01501         }
01502        }
01503       }
01504      }
01505      
01506      // Cells are the same
01507      if(iBoundCell == ourNeighborArc[k])
01508      {
01509       if( bObsPoint && bObsBeginpoint && iNextLSRFlag != -1)
01510       {
01511        pBoundCell->setIsLabelA();
01512        bChangeIntToExt = true;
01513        if( gDebug > 1 ) cout<< "  Int to Ext, based on match with obs begin point" << endl;
01514       }
01515       else if( bObsPoint && bObsEndpoint && iPrevLSRFlag != -1)
01516       {
01517        pBoundCell->setIsLabelB();
01518        bChangeExtToInt = true;
01519        if( gDebug > 1) cout<< "  Ext to Int, based on match with obst end point" << endl;
01520       }
01521       else if( !bObsPoint )
01522       {
01523        // Intersect-crossing
01524        if( iPrevLSRFlag == -1 && iNextLSRFlag == 1 )
01525        {
01526         bChangeIntToExt = true;
01527         if( gDebug > 1 ) cout<< "  Int to Ext, based on intersect crossing 1" << endl;
01528        }
01529        else if( iPrevLSRFlag == 1 && iNextLSRFlag == -1 )
01530        {
01531         bChangeExtToInt = true;
01532         if( gDebug > 1 ) cout<< "  Ext to Int, based on intersect crossing 2" << endl;
01533        }
01534        // Intersect-tangent
01535        else if( iPrevLSRFlag == 1 && iNextLSRFlag == 1 )
01536        {
01537         // No change
01538        }
01539        else if( iPrevLSRFlag == -1 && iNextLSRFlag == -1 )
01540        {
01541         // No change
01542        }
01543        // Intersect-join
01544        else if( iPrevLSRFlag == 1 && iNextLSRFlag == 0 )
01545        {
01546         // No change
01547        }
01548        else if( iPrevLSRFlag == -1 && iNextLSRFlag == 0 )
01549        {
01550         bChangeIntToExt = true;
01551         if( gDebug > 1 ) cout<< "  Int to Ext, based on intersect join 2" << endl;
01552        }
01553        else if( iPrevLSRFlag == 0 && iNextLSRFlag == 1 )
01554        {
01555         // No change
01556        }
01557        else if( iPrevLSRFlag == 0 && iNextLSRFlag == -1 )
01558        {
01559         bChangeExtToInt = true;
01560         if( gDebug > 1 ) cout<< "  Ext to Int, based on intersect join 4" << endl;
01561        }
01562       }
01563      }
01564      else
01565      {
01566       // Check it neighbor arc dead ends near obstacle boundary
01567       vector<Cell* > cellNeighbors = m_LSR.getCell(iBoundCell)->neighbours();
01568       
01569       for( int n = 0; n < cellNeighbors.size(); n++ )
01570       {
01571        // Adjacent cell
01572        if(cellNeighbors[n]->indexes() == ourNeighborArc[k])
01573        {
01574         if( bObsPoint && bObsBeginpoint && (iNextLSRFlag == 1 || (cellNeighbors[n]->isLSR() && !cellNeighbors[n]->isBoundary())) )
01575         {
01576          bChangeIntToExt = true;
01577          if( gDebug > 1 ) cout<< "  Int to Ext, based on first arc cell next to obstacle" << endl;
01578          break;
01579         }
01580         else if( bObsPoint && bObsEndpoint && (iPrevLSRFlag == 1 || (cellNeighbors[n]->isLSR() && !cellNeighbors[n]->isBoundary())) )
01581         {
01582          bChangeExtToInt = true;
01583          if( gDebug > 1) cout<< "  Ext to Int, based on last arc cell next to obstacle" << endl;
01584          break;
01585         }
01586        }
01587       }
01588       
01589       if( !(bChangeExtToInt || bChangeIntToExt) )
01590       {
01591        // Cross with no intersecting cells
01592        bool bCross = false;
01593        if( k < (ourNeighborArc.size() - 1) )
01594        {
01595         int iNextIndex = (l + iOffset + 1)%lsrBound.size();
01596         DubInt iNextBoundCell = lsrBound[iNextIndex];
01597         
01598         if( iNextBoundCell.i() != iBoundCell.i() && iNextBoundCell.j() != iBoundCell.j() )
01599         {
01600          if( iBoundCell.i() == ourNeighborArc[k].i() && iNextBoundCell.j() == ourNeighborArc[k].j() )
01601          {
01602           if( iBoundCell.j() == ourNeighborArc[k+1].j() && iNextBoundCell.i() == ourNeighborArc[k+1].i() )
01603           {
01604            bChangeExtToInt = true;
01605            if( gDebug > 1 ) cout<< "  Ext to Int, based on crossing" << endl;
01606           }
01607          }
01608          else if( iBoundCell.i() == ourNeighborArc[k+1].i() && iNextBoundCell.j() == ourNeighborArc[k+1].j() )
01609          {
01610           if( iBoundCell.j() == ourNeighborArc[k].j() && iNextBoundCell.i() == ourNeighborArc[k].i() )
01611           {
01612            bChangeIntToExt = true;
01613            if( gDebug > 1 ) cout<< "  Int to Ext, based on crossing" << endl;
01614           }
01615          }
01616         }
01617        }
01618       }
01619      }
01620      
01621      if(bChangeIntToExt || bChangeExtToInt)
01622      {
01623       if( gDebug > 1 ) cout<< "  Transition at cell " << k << " at " << globalPos.print() << endl;
01624       
01625       bool bChange = false;
01626       
01627       if( bChangeIntToExt )
01628       {
01629        // Moving from internal to external
01630        if( keepColor == KEEP_UNKNOWN )
01631        {
01632         keepColor = (bOrange ? KEEP_PURPLE : KEEP_ORANGE);
01633         if( gDebug > 1 ) cout<< "  Setting keep color to " << (bOrange ? "KEEP_PURPLE" : "KEEP_ORANGE") << endl;
01634         bOrange = !bOrange;
01635         
01636         if( gDebug > 1 ) cout<< "  Switched color to " << (bOrange ? "ORANGE" : "PURPLE") << endl;
01637         bChange = true;
01638        }
01639        else
01640        {
01641         // Were we already external?
01642         if( keepColor == (bOrange ? KEEP_ORANGE : KEEP_PURPLE ) )
01643         {
01644          // Do nothing
01645          if( gDebug > 1 ) cout<< "  Maintaining current color" << endl;
01646         }
01647         else
01648         {
01649          bOrange = !bOrange;
01650          if( gDebug > 1 ) cout<< "  Switched color to " << (bOrange ? "ORANGE" : "PURPLE") << endl;
01651          bChange = true;
01652         }
01653        }
01654        
01655       }
01656       else if( bChangeExtToInt )
01657       {
01658        // Moving from external to internal
01659        if( keepColor == KEEP_UNKNOWN )
01660        {
01661         keepColor = (bOrange ? KEEP_ORANGE : KEEP_PURPLE);
01662         
01663         if( gDebug > 1 ) cout<< "  Setting keep color to " << (bOrange ? "KEEP_ORANGE" : "KEEP_PURPLE") << endl;
01664         bOrange = !bOrange;
01665         
01666         if( gDebug > 1 ) cout<< "  Switched color to " << (bOrange ? "ORANGE" : "PURPLE") << endl;
01667         bChange = true;
01668        }
01669        else
01670        {
01671         // Were we already internal?
01672         if( keepColor == (bOrange ? KEEP_PURPLE : KEEP_ORANGE ) )
01673         {
01674          // Do nothing
01675          if( gDebug > 1 ) cout<< "  Maintaining current color" << endl;
01676         }
01677         else
01678         {
01679          bOrange = !bOrange;
01680          if( gDebug > 1 ) cout<< "  Switched color to " << (bOrange ? "ORANGE" : "PURPLE") << endl;
01681          bChange = true;
01682         }
01683        }
01684       }
01685       
01686       if( bChange )
01687       {
01688        if( tempFrontierArc.size() > 0 )
01689        {
01690         if( tempFrontierArc.size() >= gMinMergeArcSize )
01691         {
01692          // Color just switched, push to previous color
01693          if( !(bOrange) )
01694          {
01695           if( gDebug > 8 ) cout<< "Pushing temp arc with " << tempFrontierArc.size() << " cells to orange (color)" << endl;
01696           orangeFrontier.push_back(tempFrontierArc);
01697          }
01698          else
01699          {
01700           if( gDebug > 8 ) cout<< "Pushing temp arc with " << tempFrontierArc.size() << " cells to purple (color)" << endl;
01701           purpleFrontier.push_back(tempFrontierArc);
01702          }
01703         }
01704         
01705         if( gDebug > 8 ) cout<< "Clearing temp arc (color)" << endl;
01706         tempFrontierArc = FrontierArc();
01707         
01708         if( bFrontierCell )
01709         {
01710          tempFrontierArc.push_back(iBoundCell);
01711         }
01712        }
01713       }
01714      }
01715     }
01716    }
01717   }
01718   
01719   
01720   /*
01721   cout<< "Waiting for go ahead..." << endl;
01722   char input[10];
01723   cin>> input;
01724   */
01725  }
01726  
01727  if( tempFreeArc.size() > 0 )
01728  {
01729   if( m_freeArcs.size() > 0 && m_freeArcs[0][0] == lsrBound[iOffset] )
01730   {
01731    m_freeArcs[0].insert( m_freeArcs[0].begin(), tempFreeArc.begin(), tempFreeArc.end() );
01732   }
01733   else
01734   {
01735    m_freeArcs.push_back(tempFreeArc);
01736   }
01737  }
01738  
01739  if( tempFrontierArc.size() >= gMinMergeArcSize )
01740  {
01741   if( bOrange )
01742   {
01743    if( orangeFrontier.size() > 0 && orangeFrontier[0][0] == lsrBound[iOffset] )
01744    {
01745     if( gDebug > 8 ) cout<< "  Merging temp arc with " << tempFrontierArc.size() << " cells to orange" << endl;
01746     orangeFrontier[0].insert( orangeFrontier[0].begin(), tempFrontierArc.begin(), tempFrontierArc.end() );
01747    }
01748    else
01749    {
01750     if( gDebug > 8 ) cout<< "  Pushing temp arc with " << tempFrontierArc.size() << " cells to orange" << endl;
01751     orangeFrontier.push_back(tempFrontierArc);
01752    }
01753   }
01754   else
01755   {
01756    if( purpleFrontier.size() > 0 && purpleFrontier[0][0] == lsrBound[iOffset] )
01757    {
01758     if( gDebug > 8 ) cout<< "  Merging temp arc with " << tempFrontierArc.size() << " cells to purple" << endl;
01759     purpleFrontier[0].insert( purpleFrontier[0].begin(), tempFrontierArc.begin(), tempFrontierArc.end() );
01760    }
01761    else
01762    {
01763     if( gDebug > 8 ) cout<< "  Pushing temp arc with " << tempFrontierArc.size() << " cells to purple" << endl;
01764     purpleFrontier.push_back(tempFrontierArc);
01765    }
01766   }
01767  }
01768  
01769  // Keep one of the two colors as our new frontier
01770  if( keepColor == KEEP_ORANGE || keepColor == KEEP_UNKNOWN )
01771  {
01772   if( gDebug > 1 ) cout<< "Keeping orange frontier, with " << orangeFrontier.size() << " arcs"<< endl;
01773   m_frontier = orangeFrontier;
01774  }
01775  else
01776  {
01777   if( gDebug > 1 ) cout<< "Keeping purple frontier, with " << purpleFrontier.size() << " arcs"<< endl;
01778   m_frontier = purpleFrontier;
01779  }
01780  
01781  if( gDebug > 8 )
01782  {
01783   cout<< "  Updated frontier size:" << endl;
01784   cout<< "    " << m_frontier.size() << " frontier arcs" << endl;
01785   for( int i = 0; i < m_frontier.size(); i++ )
01786   {
01787    cout<< "     Arc " << i << " has " << m_frontier[i].size() << " cells" << endl;
01788   }
01789  }
01790 }
01791 
01792 
01793 void PursuitAgent::updateNeighborFrontiers( AgentVector neighbors, Pose &curPose, vector<Frontier > &updatedNeighborFrontiers )
01794 {
01795  player_color_t color;
01796  
01798  // Finish processing neighbor frontiers and send them back to neighbors
01800  for( int i = 0; i < neighbors.size(); i++ )
01801  {
01802   if( neighbors[i]->isLeader() && (neighbors[i]->getID() != getID()) )
01803   {
01804    Position neighborPos = neighbors[i]->getLSRPose().pos();
01805    
01806    if( neighborPos.dist(curPose.pos()) > gOverlapFactor*(getSensorRange() + neighbors[i]->getSensorRange()) )
01807    {
01808     if( gDebug > 7 ) cout<< "    " << getID() << " ignoring distant agent " << neighbors[i]->getID() << endl;
01809     continue;
01810    }
01811    
01812    if( gDebug > 7 ) cout<< "    " << getID() << " setting agent " << neighbors[i]->getID() << " frontiers" << endl;
01813    
01814    
01815    Frontier newFrontier;
01816    for( int j = 0; j < updatedNeighborFrontiers[i].size(); j++ )
01817    {
01818     
01819     bool bErase = false;
01820     FrontierArc updatedNeighborArc = updatedNeighborFrontiers[i][j];
01821     
01822     if( updatedNeighborArc.size() <= 3 )
01823     {
01824      if( neighbors[i]->getCell(updatedNeighborArc[0])->isLabelA() )
01825      {
01826       if( neighbors[i]->getCell(updatedNeighborArc[updatedNeighborArc.size()-1])->isLabelB() )
01827       {
01828        bErase = true;
01829       }
01830      }
01831     }
01832     /*
01833     if( updatedNeighborArc.size() < gMinArcSize )
01834     {
01835      // Under some circumstances we want to remove small neighbor arcs because
01836      // they're just the result of poor grid alignment.  However, under other circumstances
01837      // they're important to keep, so this is a tough question.
01838      
01839      if( neighbors[i]->getCell(updatedNeighborArc[0])->isLabelA() )
01840      {
01841       continue;
01842      }
01843      
01844      if( neighbors[i]->getCell(updatedNeighborArc[updatedNeighborArc.size()-1])->isLabelB() )
01845      {
01846       continue;
01847      }
01848      
01849      FrontierArc translatedArc;
01850      Cell* pTranslatedCell;
01851      //Cell* pRotTranslatedCell;
01852      Position translatedPos;
01853      
01854      Position arcCellPos = neighbors[i]->getCellPosition(updatedNeighborArc[0]);
01855      Position globalPos = arcCellPos + neighborPos;
01856      translatedPos = arcCellPos + neighborPos - curPose.pos();
01857      
01858      pTranslatedCell = m_LSR.getCell( translatedPos );
01859      
01860      if( pTranslatedCell != NULL )
01861      {
01862       vector<Cell* > nCells = pTranslatedCell->neighbours();
01863       
01864       for( int m = 0; m < nCells.size(); m++ )
01865       {
01866        if( !(nCells[m]->isUnknown()) )
01867        {
01868         bErase = true;
01869         break;
01870        }
01871       }
01872       
01873       for( int k = 0; (bErase && k < m_frontier.size()); k++ )
01874       {
01875        bool bKill = false;
01876        int iLSRCount = 0;
01877        FrontierArc ourArc = m_frontier[k];
01878        
01879        for( int l = 0; (bErase && l < ourArc.size()); l++ )
01880        {
01881         for( int m = 0; m < nCells.size(); m++ )
01882         {
01883          if( nCells[m]->indexes() == ourArc[l] )
01884          {
01885           bErase = false;
01886           break;
01887          }
01888         }
01889        }
01890       }
01891      }
01892     }*/
01893     
01894     // This is to catch errors where we erase a neighbors obstacle end point, but
01895     // because of quantization our arc doesn't quite hit the obstacle theirs did
01896     
01897     Pose neighborPose = neighbors[i]->getLSRPose();
01898     Cell* pCell1 = neighbors[i]->getCell(updatedNeighborArc[0]);
01899     Cell* pCell2 = neighbors[i]->getCell(updatedNeighborArc[updatedNeighborArc.size()-1]);
01900    
01901     if( !pCell1->isLabelA() && pCell1->isFrontier() )
01902     {
01903      // Did we perhaps erase continuation of this arc because of obstacles
01904      // which neighbor might not be able to see?
01905      bool bSet = false;
01906      Position translatedPos = neighborPose.pos() - curPose.pos() + pCell1->point();
01907      Cell* pTranslatedCell = m_LSR.getCell( translatedPos );
01908      
01909      if( pTranslatedCell != NULL )
01910      {
01911       for( int x = -1; x <= 1; x++ )
01912       {
01913        for( int y = -1; y <= 1; y++ )
01914        {
01915         if( x != 0 || y != 0 )
01916         {
01917          DubInt iTheirs = pCell1->indexes() + DubInt(x,y);
01918          Cell* pTheirCell = neighbors[i]->getCell( iTheirs );
01919          DubInt iOurs = pTranslatedCell->indexes() + DubInt(x,y);
01920          Cell* pOurCell = m_LSR.getCell( iOurs );
01921          
01922          if( pTheirCell != NULL && pOurCell != NULL )
01923          {
01924           if( pTheirCell->isFrontier() && pOurCell->isObstacle() )
01925           {
01926            bSet = true;
01927           }
01928          }
01929         }
01930        }
01931       }
01932      
01933       vector<Cell* > nCells = pTranslatedCell->neighbours();
01934      
01935       for( int l = 0; l < nCells.size(); l++ )
01936       {
01937        if( (m_LSR.getCell(nCells[l]->indexes())->isLabelA()) )
01938        {
01939         bSet = false;
01940        }
01941        
01942        for( int a = 0; a < m_frontier.size(); a++ )
01943        {
01944         FrontierArc ourArc = m_frontier[a];
01945         
01946         if( ourArc[0] == nCells[l]->indexes() )
01947         {
01948          bSet = false;
01949         }
01950         
01951         if( ourArc[ourArc.size()-1] == nCells[l]->indexes() )
01952         {
01953          bSet = false;
01954         }
01955        }
01956       }
01957     
01958       if( bSet )
01959       {
01960        if( gDebug > 7 ) cout<< getID() << " setting error correction neighbor obstacle begin point for neighbor's frontier" << endl;
01961        pCell1->setIsLabelA();
01962        if( gDebug >= 9 ) drawSquare( gColorGreen, neighborPose.pos() + pCell1->point(), 0.05, false );
01963       }
01964      }
01965     }
01966     
01967     if( !pCell2->isLabelB() && pCell2->isFrontier() )
01968     {
01969      // Did we perhaps erase continuation of this arc because of obstacles
01970      // which neighbor might not be able to see?
01971      bool bSet = false;
01972      Position translatedPos = neighborPose.pos() - curPose.pos() + pCell2->point();
01973      Cell* pTranslatedCell = m_LSR.getCell( translatedPos );
01974      
01975      if( pTranslatedCell != NULL )
01976      {
01977       for( int x = -1; x <= 1; x++ )
01978       {
01979        for( int y = -1; y <= 1; y++ )
01980        {
01981         if( x != 0 || y != 0 )
01982         {
01983          Cell* pTheirCell = neighbors[i]->getCell( pCell2->indexes() + DubInt(x,y) );
01984          Cell* pOurCell = m_LSR.getCell( pTranslatedCell->indexes() + DubInt(x,y) );
01985          
01986          if( pTheirCell != NULL && pOurCell != NULL )
01987          {
01988           if( pTheirCell->isFrontier() && pOurCell->isObstacle() )
01989           {
01990            bSet = true;
01991           }
01992          }
01993         }
01994        }
01995       }
01996      
01997       vector<Cell* > nCells = pTranslatedCell->neighbours();
01998      
01999       for( int l = 0; l < nCells.size(); l++ )
02000       {
02001        if( (m_LSR.getCell(nCells[l]->indexes())->isLabelB()) )
02002        {
02003         bSet = false;
02004        }
02005        
02006        for( int a = 0; a < m_frontier.size(); a++ )
02007        {
02008         FrontierArc ourArc = m_frontier[a];
02009         
02010         if( ourArc[0] == nCells[l]->indexes() )
02011         {
02012          bSet = false;
02013         }
02014         
02015         if( ourArc[ourArc.size()-1] == nCells[l]->indexes() )
02016         {
02017          bSet = false;
02018         }
02019        }
02020       }
02021      
02022       if( bSet )
02023       {
02024        if( gDebug > 7 ) cout<< getID() << " setting error correction neighbor obstacle end point for neighbor's frontier" << endl;
02025        pCell2->setIsLabelB();
02026        if( gDebug >= 9 ) drawSquare( gColorRed, neighborPose.pos() + pCell2->point(), 0.05, false );
02027       }
02028      }
02029     }
02030     
02031     if( !bErase )
02032     {
02033      newFrontier.push_back(updatedNeighborArc);
02034     }
02035    }
02036    
02037    // Clear waiting status
02038    if( neighbors[i]->isWaitingForAgent(getID()) )
02039    {
02040     neighbors[i]->clearWaitingForAgent();
02041    }
02042    
02043    // Inform neighbors of updated frontiers
02044    neighbors[i]->setFrontier( newFrontier );
02045   }
02046  }
02047 }
02048 
02049 
02050 void PursuitAgent::postProcessOurFrontier( vector<Frontier > &ourNeighborFrontiers, Pose &curPose, bool bDebugDisplay )
02051 {
02053  // Special labels for endpoints of free arcs so that other agents can tell when our arcs actually ends on an obstacle
02055  LSRBound lsrBound = m_LSR.lsrBound();
02056  for( int i = 0; i < m_freeArcs.size(); i++ )
02057  {
02058   if( m_freeArcs[i].size() < lsrBound.size() )
02059   {
02060    m_LSR.getCell(m_freeArcs[i][0])->setIsLabelA();
02061    m_LSR.getCell(m_freeArcs[i][m_freeArcs[i].size()-1])->setIsLabelB();
02062    
02063    if( bDebugDisplay ) drawX( gColorGray, m_LSR.getCell(m_freeArcs[i][0])->point() + curPose.pos(), 0.05 );
02064    if( bDebugDisplay ) drawX( gColorBlue, m_LSR.getCell(m_freeArcs[i][m_freeArcs[i].size()-1])->point() + curPose.pos(), 0.05 );
02065   }
02066  }
02067  
02068  // This is to catch errors where we erase a neighbors obstacle end point, but
02069  // because of quantization our arc doesn't quite hit the obstacle theirs did
02070  for( int i = 0; i < m_frontier.size(); i++ )
02071  {
02072   if( m_frontier[i].size() < lsrBound.size() )
02073   {
02074    Cell* pCell1 = m_LSR.getCell(m_frontier[i][0]);
02075    Cell* pCell2 = m_LSR.getCell(m_frontier[i][m_frontier[i].size()-1]);
02076    
02077    if( gDebug >= 9 )
02078    {
02079     drawSquare( gColorBlue, m_LSR.center().pos() + pCell1->point(), 0.02, false );
02080     drawSquare( gColorGray, m_LSR.center().pos() + pCell2->point(), 0.02, false );
02081    }
02082    
02083    if( !pCell1->isLabelA() )
02084    {
02085     bool bSet = true;
02086     
02087     vector<Cell* > nCells = pCell1->neighbours();
02088     
02089     /*for( int l = 0; l < nCells.size(); l++ )
02090     {
02091      if( m_LSR.getCell(nCells[l]->indexes())->isLabelA() )
02092      {
02093       bSet = false;
02094      }
02095     }*/
02096    
02097     for( int m = 0; (bSet && m < ourNeighborFrontiers.size()); m++ )
02098     {
02099      for( int j = 0; (bSet && j < ourNeighborFrontiers[m].size()); j++ )
02100      {
02101       FrontierArc ourNeighborArc = ourNeighborFrontiers[m][j];
02102       
02103       for( int k = 0; (bSet && k < ourNeighborArc.size()); k++ )
02104       {
02105        for( int l = 0; l < nCells.size(); l++ )
02106        {
02107         if( ourNeighborArc[k] == nCells[l]->indexes() )
02108         {
02109          // Is this cell a part of a neighbor arc (ie, we haven't cleared it)
02110          if( !(m_LSR.getCell(nCells[l]->indexes())->isLSR()) && !(m_LSR.getCell(nCells[l]->indexes())->isObstacle()) )
02111          {
02112           if( gDebug >= 9 ) drawX( gColorGray, m_LSR.center().pos() + m_LSR.getCell(nCells[l]->indexes())->point(), 0.03 );
02113           bSet = false;
02114           break;
02115          }
02116         }
02117        }
02118       }
02119      }
02120     }
02121     
02122     if( bSet )
02123     {
02124      if( gDebug > 7 ) cout<< getID() << " setting error correction obstacle begin point for frontier " << i << " of size " << m_frontier[i].size() << endl;
02125      pCell1->setIsLabelA();
02126      if( gDebug >= 9 ) drawX( gColorGreen, m_LSR.center().pos() + pCell1->point(), 0.05 );
02127     }
02128    }
02129    
02130    if( !pCell2->isLabelB() )
02131    {
02132     bool bSet = true;
02133     
02134     vector<Cell* > nCells = pCell2->neighbours();
02135     
02136     /*for( int l = 0; l < nCells.size(); l++ )
02137     {
02138      if( m_LSR.getCell(nCells[l]->indexes())->isLabelB() )
02139      {
02140       bSet = false;
02141      }
02142     }*/
02143    
02144     for( int m = 0; (bSet && m < ourNeighborFrontiers.size()); m++ )
02145     {
02146      for( int j = 0; (bSet && j < ourNeighborFrontiers[m].size()); j++ )
02147      {
02148       FrontierArc ourNeighborArc = ourNeighborFrontiers[m][j];
02149       
02150       for( int k = 0; (bSet && k < ourNeighborArc.size()); k++ )
02151       {
02152        for( int l = 0; l < nCells.size(); l++ )
02153        {
02154         if( ourNeighborArc[k] == nCells[l]->indexes() )
02155         {
02156          // Is this cell a part of a neighbor arc (ie, we haven't cleared it)
02157          if( !(m_LSR.getCell(nCells[l]->indexes())->isLSR()) && !(m_LSR.getCell(nCells[l]->indexes())->isObstacle()) )
02158          {
02159           if( gDebug >= 9 ) drawX( gColorGray, m_LSR.center().pos() + m_LSR.getCell(nCells[l]->indexes())->point(), 0.03 );
02160           bSet = false;
02161           break;
02162          }
02163         }
02164        }
02165       }
02166      }
02167     }
02168     
02169     if( bSet )
02170     {
02171      if( gDebug > 7 ) cout<< getID() << " setting error correction obstacle begin point for frontier " << i << " of size " << m_frontier[i].size() << endl;
02172      pCell2->setIsLabelB();
02173      if( gDebug >= 9 ) drawX( gColorRed, m_LSR.center().pos() + pCell2->point(), 0.05 );
02174     }
02175    }
02176   }
02177  }
02178  
02180  // Fix stage errors where a ray sneaks into the corner of an obstacle
02182  Frontier newFrontier;
02183  for( int i = 0; i < m_frontier.size(); i++ )
02184  {
02185   bool bKill = false;
02186   int iLSRCount = 0;
02187   FrontierArc arc = m_frontier[i];
02188   
02189   /*
02190   if( arc.size() < gMinArcSize )
02191   {
02192    // Kill pointless single cell arcs
02193    bKill = true;
02194    vector<Cell* > nCells = m_LSR.getCell(arc[0])->neighbours();
02195    
02196    for( int m = 0; (bKill && m < ourNeighborFrontiers.size()); m++ )
02197    {
02198     for( int j = 0; (bKill && j < ourNeighborFrontiers[m].size()); j++ )
02199     {
02200      FrontierArc ourNeighborArc = ourNeighborFrontiers[m][j];
02201      
02202      for( int k = 0; (bKill && k < ourNeighborArc.size()); k++ )
02203      {
02204       for( int l = 0; l < nCells.size(); l++ )
02205       {
02206        if( ourNeighborArc[k] == nCells[l]->indexes() )
02207        {
02208         if( !(m_LSR.getCell(ourNeighborArc[k])->isLSR()) && !(m_LSR.getCell(ourNeighborArc[k])->isObstacle()) )
02209         {
02210          bKill = false;
02211          break;
02212         }
02213        }
02214       }
02215      }
02216     }
02217    }
02218    
02219    nCells = m_LSR.getCell(arc[arc.size()-1])->neighbours();
02220    
02221    for( int m = 0; (bKill && m < ourNeighborFrontiers.size()); m++ )
02222    {
02223     for( int j = 0; (bKill && j < ourNeighborFrontiers[m].size()); j++ )
02224     {
02225      FrontierArc ourNeighborArc = ourNeighborFrontiers[m][j];
02226      
02227      for( int k = 0; (bKill && k < ourNeighborArc.size()); k++ )
02228      {
02229       for( int l = 0; l < nCells.size(); l++ )
02230       {
02231        if( ourNeighborArc[k] == nCells[l]->indexes() )
02232        {
02233         if( !(m_LSR.getCell(ourNeighborArc[k])->isLSR()) && !(m_LSR.getCell(ourNeighborArc[k])->isObstacle()) )
02234         {
02235          bKill = false;
02236          break;
02237         }
02238        }
02239       }
02240      }
02241     }
02242    }
02243   }
02244   */
02245   
02246   if( arc.size() <= 3 )
02247   {
02248    if( m_LSR.getCell(arc[0])->isLabelA() && m_LSR.getCell(arc[arc.size()-1])->isLabelB() )
02249    {
02250     bKill = true;
02251    }
02252   }
02253   
02254   if( !bKill )
02255   {
02256    for( int j = 0; j < arc.size(); j++ )
02257    {
02258     if( !(m_LSR.getCell(arc[j])->isObstacle()) )
02259     {
02260      vector<Cell* > nCells = m_LSR.getCell(arc[j])->neighbours();
02261        
02262      // To handle Stage errors where one or two rays sneak into an obstacle
02263      for( int k = 0; k < nCells.size(); k++ )
02264      {
02265       if( nCells[k]->isLSR() && !(nCells[k]->isBoundary()) )
02266       {
02267        iLSRCount++;
02268        break;
02269       }
02270      }
02271     }
02272    }
02273    
02274    bKill = (iLSRCount <= std::max(0, (arc.size()-2)/2));
02275   }
02276   
02277   if( !bKill )
02278   {
02279    newFrontier.push_back(arc);
02280   }
02281   else
02282   {
02283    if( gDebug > 0 ) cout<< getID() << " erasing erroneous frontier" << endl;
02284   }
02285  }
02286  m_frontier = newFrontier;
02287 }
02288 
02289 
02290 void PursuitAgent::updateFrontier( AgentVector neighbors, bool bDebugDisplay )
02291 {
02292  if( isTraveling() )//|| (getBehavior() == EXPAND && m_frontier.size() == 0) )
02293  {
02294   return;
02295  }
02296  
02297  if( m_bFrontierInitialized )
02298  {
02299   // Only run this function when first processing LSR from new viewpoint
02300   return;
02301  }
02302  
02303  if( gDebug > 7 ) cout<< "    " << getID() << " updating frontier" << endl;
02304  
02305  int bWaitForKeyboard = (gDebug > 9);
02306  
02307  player_color_t color;
02308  
02309  // Only update frontier and do arc coloring on the first update
02310  setFrontier( m_LSR.frontier(), true );
02311  m_bFrontierInitialized = true;
02312  m_freeArcs.clear();
02313  Pose curPose = getLSRPose();
02314 
02315  // Store full neighbor frontier arcs in our grid for use in classifying our LSR boundary
02316  vector<Frontier > ourNeighborFrontiers;
02317  // Store neighbor frontier arcs minus pieces in our LSR to send back to neighbors after we finish setting up our frontier
02318  vector<Frontier > updatedNeighborFrontiers;
02319  
02320  // The beginning/end cells of a frontier arc on an obstacle are very important for boundary classification
02321  // List of cells where a neighbor frontier arc begins on an obstacle
02322  vector<DubInt > neighborObstacleEndpoints;
02323  // List of cells where a neighbor frontier arc ends on an obstacle
02324  vector<DubInt > neighborObstacleBeginpoints;
02325  
02326  
02327  getNeighborFrontiers( neighbors, curPose, ourNeighborFrontiers, updatedNeighborFrontiers, neighborObstacleEndpoints, neighborObstacleBeginpoints );
02328  
02329  m_prevFrontier.clear();
02330  m_prevLSR = Grid();
02331  
02332  // At this point in the function we have translated all of neighbors' arcs into our
02333  // grid, so we are ready to go on to classifying our LSR boundary.  We have also determined
02334  // which pieces of our neighbors' arcs are inside our LSR, but will not transmit this
02335  // update back to our neighbors until our frontier is set up.
02336  
02337  if( bDebugDisplay )
02338  {
02339   if( gDebug > 5 ) cout<< "  " << m_frontier.size() << " our frontier arcs" << endl;
02340   if( gDebug > 5 ) cout<< "  " << ourNeighborFrontiers.size() << " neighbor frontiers" << endl;
02341   for( int i = 0; i < ourNeighborFrontiers.size(); i++ )
02342   {
02343    if( gDebug > 5 ) cout<< "  " << ourNeighborFrontiers[i].size() << " neighbor frontier arcs" << endl;
02344    for( int j = 0; j < ourNeighborFrontiers[i].size(); j++ )
02345    {
02346     FrontierArc ourNeighborArc = ourNeighborFrontiers[i][j];
02347     if( gDebug > 5 ) 
02348     {
02349      cout<< "  " << ourNeighborArc.size() << " neighbor frontier arc cells, from " ;
02350      cout<< ourNeighborArc[0].print() << " to " << ourNeighborArc[ourNeighborArc.size()-1].print() << endl;
02351     }
02352     
02353     for( int k = 0; k < ourNeighborArc.size(); k++ )
02354     {
02355      Position arcCellPos = getCellPosition(ourNeighborArc[k]);
02356      Position globalPos = curPose.pos() + arcCellPos;
02357      
02358      color.alpha = 0;
02359      color.red = 175;
02360      color.green = 175;
02361      color.blue = 175;
02362      
02363      drawSquare( color, globalPos, 0.01, true );
02364     }
02365     
02366     drawRedX( curPose.pos() + getCellPosition(ourNeighborArc[ourNeighborArc.size()-1]), 0.015 );
02367    }
02368   }
02369   
02370   for( int i = 0; i < neighborObstacleBeginpoints.size(); i++ )
02371   {
02372    drawX( gColorGreen, curPose.pos() + getCellPosition(neighborObstacleBeginpoints[i]), 0.05 );
02373   }
02374   
02375   for( int i = 0; i < neighborObstacleEndpoints.size(); i++ )
02376   {
02377    drawRedX( curPose.pos() + getCellPosition(neighborObstacleEndpoints[i]), 0.05 );
02378   }
02379   
02380   for( int i = 0; (i < m_frontier.size()); i++ )
02381   {
02382    FrontierArc arc = m_frontier[i];
02383    for( int j = 0; (j < arc.size()); j++ )
02384    {
02385     Position arcCellPos = getCellPosition(arc[j]);
02386     Position globalPos = curPose.pos() + arcCellPos;
02387     
02388     color.alpha = 0;
02389     color.red = 255;
02390     color.green = 175;
02391     color.blue = 255;
02392     
02393     drawSquare( color, globalPos, 0.01, true );
02394     
02395     if( j == 0 )
02396     {
02397      drawX( gColorGreen, curPose.pos() + getCellPosition(arc[j]), 0.05 );
02398     }
02399     else if( j == arc.size() - 1 )
02400     {
02401      drawRedX( curPose.pos() + getCellPosition(arc[j]), 0.05 );
02402     }
02403    }
02404   }
02405  }
02406  
02407  if( bDebugDisplay )
02408  {
02409   if( bWaitForKeyboard )
02410   {
02411    cout<< "Waiting for go ahead..." << endl;
02412    char input[10];
02413    cin>> input;
02414   }
02415   else
02416   {
02417    TimeUtilities::sleep( Time(1,500000) );
02418   }
02419   
02420   //gGP->Clear();
02421  }
02422 
02423 
02424  classifyOurFrontier( neighbors, curPose, ourNeighborFrontiers, neighborObstacleEndpoints, neighborObstacleBeginpoints, bDebugDisplay );
02425  
02426  
02427  updateNeighborFrontiers( neighbors, curPose, updatedNeighborFrontiers );
02428  
02429  
02430  postProcessOurFrontier( ourNeighborFrontiers, curPose, bDebugDisplay );
02431  
02432  gIterCount++;
02433 
02434  // Logging
02435  if( gLogFile.is_open() )
02436  {
02437   if( gGlobalGrid != NULL )
02438   {
02439    Position lsrPos = getLSRPose().pos();
02440    for( int i = 0; i < getLSRSize(); i++ )
02441    {
02442     if( getCell(i)->isLSR() )
02443     {
02444      Position LSRpoint = lsrPos + getCell(i)->point();
02445      
02446      Cell* pCell = gGlobalGrid->getCell( LSRpoint );
02447      
02448      if( !pCell->isLSR() )
02449      {
02450       pCell->setIsLSR();
02451       gGlobalGrid->_lsr.push_back(pCell->indexes());
02452      }
02453     }
02454    }
02455   }
02456   
02457   logData();
02458  }
02459  
02460  if( bDebugDisplay )
02461  {
02462   /*if( gDebug > 20 )
02463   {
02464    Position curPos = getLSRPosition();
02465    int iCount = 0;
02466    for( int i = 0; i < m_frontier.size(); i++ )
02467    {
02468     for( int j = 0; j < m_frontier[i].size(); j++ )
02469     {
02470      drawSquare( gColorFrontier, getCellPosition(m_frontier[i][j]) + curPos, 0.005, true );
02471      
02472      if( iCount%5 == 4 )
02473      {
02474       cout<< "Waiting for go ahead..." << endl;
02475       char input[10];
02476       cin>> input;
02477      }
02478      
02479      iCount++;
02480     }
02481    }
02482   }
02483   else */if( bWaitForKeyboard )
02484   {
02485    cout<< "Waiting for go ahead..." << endl;
02486    char input[10];
02487    cin>> input;
02488   }
02489   else
02490   {
02491    TimeUtilities::sleep( Time(2,500000) );
02492   }
02493   
02494   gGP->Clear();
02495  }
02496  
02497  /*
02498  if( bDebugDisplay )
02499  {
02500   for( int i = 0; i < m_freeArcs.size(); i++ )
02501   {
02502    for( int j = 0; j < m_freeArcs[i].size(); j++ )
02503    {
02504     color.alpha = 0;
02505     color.red = 255;
02506     color.green = 255;
02507     color.blue = 0;
02508     
02509     Position globalPos = getCell(m_freeArcs[i][j])->point() + curPos;
02510     
02511     drawSquare( color, globalPos, 0.01, true );
02512    }
02513   }
02514   
02515   if( bWaitForKeyboard )
02516   {
02517    cout<< "Waiting for go ahead..." << endl;
02518    char input[10];
02519    cin>> input;
02520   }
02521   else
02522   {
02523    TimeUtilities::sleep( Time(1,500000) );
02524   }
02525   
02526   gGP->Clear();
02527  }*/
02528  
02529 }
02530 
02531 ExplorationParams PursuitAgent::getExplParams( )
02532 {
02533  double maxRange = getSensorRange();
02534  return ExplorationParams( maxRange, (m_pLaserProxy->GetMaxAngle() - m_pLaserProxy->GetMinAngle()), m_pLaserProxy->GetCount(), m_pLaserProxy->GetScanRes());
02535 }
02536 
02537 void PursuitAgent::recordLSR()
02538 {
02539  // TODO: what is good size of final grid?
02540   
02541  m_LSR = Grid( getExplParams(), getScan(), /*Pose(getPosition(), 0)*/ getPose(), 2*getSensorRange(), 2*getSensorRange(), 2*getWidth() );
02542  
02543  m_LSR.defineBoard( gMinArcSize, gMinRadialArcSize, true );
02544  
02545  cout<< "  Cover field of view " << getCoverFieldOfView() << endl;
02546 }
02547 
02548 double PursuitAgent::getCoverRange()
02549 {
02550  return (gCoverDistScalar * (getSensorRange() - getLSRResolution()));
02551 }
02552 
02553 double PursuitAgent::getCoverFieldOfView()
02554 {
02555  return gSafeAngleFrac*(m_pLaserProxy->GetMaxAngle() - m_pLaserProxy->GetMinAngle());
02556 }
02557 
02558 bool PursuitAgent::isCellCovered( Pose viewPoint, DubInt iCell, bool bSilent )
02559 {
02560  Position relPos = getCellPosition(iCell) - viewPoint.pos();
02561  if(!bSilent) cout<< "  relPos : " << relPos.print() << "  bearing  " << relPos.bearing().print() << endl;
02562  if( relPos.norm() > (getCoverRange() + 0.01) )
02563  {
02564   if(!bSilent) cout<< "    Distance fail" << endl;
02565   return false;
02566  }
02567  
02568  if( fabs(viewPoint.ori().alDiff(relPos.bearing())) > (getCoverFieldOfView()/2.0 + 0.01) )
02569  {
02570   if(!bSilent)
02571   {
02572    cout<< "    Angle fail, " << viewPoint.ori().print() << " vs " << relPos.bearing().print() << endl;
02573    cout<< "    " << fabs(viewPoint.ori().alDiff(relPos.bearing())) << "   " << getCoverFieldOfView()/2.0 << endl;
02574   }
02575   
02576   return false;
02577  }
02578  
02579  vector<Cell* > rasterLine = getRaster( getCell(viewPoint.pos())->indexes(), iCell );
02580  
02581  // Last cell on raster is target cell, allow raster to graze obstacle
02582  int iObstacleCount = 0;
02583  for( int i = 0; i < rasterLine.size() - 2; i++ )
02584  {
02585   if( !(rasterLine[i]->isLSR()) )
02586   {
02587    return false;
02588   }
02589   
02590   if( rasterLine[i]->isObstacle() )
02591   {
02592    iObstacleCount++;
02593   }
02594  }
02595  
02596  if( iObstacleCount > 1 )
02597  {
02598   if(!bSilent) cout<< "    Obstacle fail" << endl;
02599   return false;
02600  }
02601  
02602  if(!bSilent) cout<< "   covered" << endl;
02603  return true;
02604 }
02605 
02606 Pose PursuitAgent::pickBestViewPoint( int *iNumViewPoints, bool bDebugDisplay )
02607 {
02608  Frontier frontier = getFrontier();
02609  assert( frontier.size() > 0 );
02610  assert( m_freeArcs.size() > 0 );
02611  
02612  if( gDebug > 2 ) cout<< "Picking best view point" << endl;
02613  
02614  (*iNumViewPoints) = 1;
02615  
02616  Pose viewPoint( 0.0, 0.0, 0.0 );
02617  //FrontierArc arc = frontier[m_followers.size()%frontier.size()];
02618  int iRelevantFreeArcs = 0;
02619  FrontierArc mostRelevantFreeArc;
02620  int iMaxRelevancy = 0;
02621  vector<DubInt > frontierCellsOnMRFA;
02622  
02623  // TODO: special handling so that arc behind robot is always MRFA when it exists
02624  
02625  // Determine most relevant free Arc
02626  for( int i = 0; i < m_freeArcs.size(); i++ )
02627  {
02628   FrontierArc freeArc = m_freeArcs[i];
02629   int iRelevancy = 0;
02630   vector<DubInt > frontierCellsOnFreeArc;
02631   
02632   for( int k = 0; k < frontier.size(); k++ )
02633   {
02634    for( int l = 0; l < frontier[k].size(); l++ )
02635    {
02636     for( int j = 0; j < freeArc.size(); j++ )
02637     {
02638      // TODO: There must be a smarter way to do this ... this scales worst case as (boundary size)^2
02639      if( freeArc[j] == frontier[k][l] )
02640      {
02641       iRelevancy++;
02642       frontierCellsOnFreeArc.push_back( freeArc[j] );
02643      }
02644     }
02645    }
02646   }
02647   
02648   if( gDebug > 5 ) cout << "  Free arc " << i << " has " << frontierCellsOnFreeArc.size() << " frontier cells out of " << freeArc.size() << endl;
02649   
02650   if( iRelevancy > 0 )
02651   {
02652    iRelevantFreeArcs++;
02653    
02654    if( iRelevancy > iMaxRelevancy )
02655    {
02656     mostRelevantFreeArc = m_freeArcs[i];
02657     frontierCellsOnMRFA = frontierCellsOnFreeArc;
02658     iMaxRelevancy = iRelevancy;
02659    }
02660   }
02661  }
02662  
02663  if( mostRelevantFreeArc.size() == 0 || frontierCellsOnMRFA.size() == 0 )
02664  {
02665   cerr<< "*** Error! *** Empty most relevant free arc, skipping agent " << getID() << endl;
02666   return getLSRPose();
02667  }
02668  
02669  if( gDebug > 2 )
02670  {
02671   cout<< "  Most relevant free arc: size " << mostRelevantFreeArc.size() << ", " << frontierCellsOnMRFA.size() << " frontier cells" << endl;
02672  }
02673  
02674  Pose curPose = getLSRPose();
02675  
02676  if( gDebug > 20 )
02677  {
02678   gGP->Clear();
02679   
02680   for( int i = 0; i < frontierCellsOnMRFA.size(); i++ )
02681   {
02682    drawSquare( gColorFrontier, getCellPosition(frontierCellsOnMRFA[i]) + curPose.pos(), 0.01, true );
02683    
02684    if( i%5 == 4 )
02685    {
02686     cout<< "Waiting for go ahead..." << endl;
02687     char input[10];
02688     cin>> input;
02689    }
02690   }
02691   
02692  }
02693  
02694  // Pick best view point on mostRelevantFreeArc
02695  int iMaxFrontierCoverage = 0;
02696  int iViewPoint = -1;
02697  
02698  // Calculate how many view points are necessary
02699  double angWidthOfMRFA = 0.0;
02700  
02701  Position frontierRight = getCellPosition(frontierCellsOnMRFA[0]);
02702  Angle rightAngle = atan2( frontierRight.y(), frontierRight.x() );
02703  Position frontierLeft = getCellPosition(frontierCellsOnMRFA.back());
02704  Angle leftAngle = atan2( frontierLeft.y(), frontierLeft.x() );
02705  
02706  angWidthOfMRFA = angDistCCW( rightAngle.dCastPi(), leftAngle.dCastPi(), (frontierCellsOnMRFA.size() <= (int)(getSensorRange()/(getLSRResolution() + 0.01))) );
02707  //angWidthOfMRFA = rightAngle.ccwDist(leftAngle);
02708  angWidthOfMRFA *= gOverlapFactor;
02709  
02710  // TODO: what's the right formula, given discretization and safety?
02711  double maxVPAngCoverage = 1.70 * acos( limit( gMinLength/(2*getCoverRange() - getWidth() - getLSRResolution()), 0.03, 0.49 ) );
02712  
02713  (*iNumViewPoints) = 1;
02714  
02715  for( int j = 0; j < frontierCellsOnMRFA.size(); j++ )
02716  {
02717   Position pos = getCellPosition(frontierCellsOnMRFA[j]);
02718   Angle angle = atan2( pos.y(), pos.x() );
02719   
02720   if( angDistCCW( rightAngle.dCastPi(), angle.dCastPi(), true )*gOverlapFactor > maxVPAngCoverage )
02721   {
02722    (*iNumViewPoints)++;
02723    rightAngle = angle;
02724   }
02725  }
02726  
02727  if( angWidthOfMRFA >= 2*M_PI - 0.01 )
02728  {
02729   (*iNumViewPoints) = 3;
02730  }
02731  
02732  rightAngle = atan2( frontierRight.y(), frontierRight.x() );
02733  
02734  //int iNumViewPoints = 1 + (angWidthOfMRFA/std::max(maxVPAngCoverage, (2*M_PI)/3));
02735  
02736  if( gDebug > 2 ) cout << "  VPs: " << (*iNumViewPoints) << " needed to cover MRFA with width " << angWidthOfMRFA << endl;
02737  if( gDebug > 5 ) cout << "       " << rightAngle.dCastPi() << " right, " << leftAngle.dCastPi() << " left" << endl;
02738  if( gDebug > 5 ) cout << "       (" << maxVPAngCoverage << " max coverage per VP)" << endl;
02739  
02740  // Loop over all LRR cells, finding point guaranteeing coverage of required fraction of MRFA and furthest away
02741  LRR curLRR = getLSR()._lrr;
02742  double bestDistHeuristic = -1.0;
02743  double bestCoverage = 0.0;
02744  double minVPDist = std::min( std::max(gMinLength, 1.2*getWidth()), getSensorRange() - getWidth() - getLSRResolution());
02745  minVPDist = std::max( minVPDist, (double)2*getLSRResolution());
02746  
02747  if( gDebug > 5 ) cout << "       " << minVPDist << " minimum VP dist" << endl;
02748  
02749  frontierRight = getCellPosition(frontierCellsOnMRFA[0]);
02750  frontierLeft = frontierRight;
02751  
02752  if( gDebug > 10 ) cout<< "      Must cover point " << getCellPosition(frontierCellsOnMRFA[0]).print() << endl;
02753  
02754  for( int i = 0; i < curLRR.size(); i++ )
02755  {
02756   if( getCell(curLRR[i])->isBoundary() )
02757   {
02758    continue;
02759   }
02760   
02761   int iFrontierCoverage = 0;
02762   double distHeuristic = 0.0;
02763   Angle rightAngleCovered = rightAngle;
02764   Angle leftAngleCovered = rightAngle;
02765   frontierLeft = frontierRight;
02766   double angCoverage = 0.0;
02767   Position baseVec = getCellPosition(frontierCellsOnMRFA[0]) - getCellPosition(curLRR[i]);
02768   Position rightVec = frontierRight - getCellPosition(curLRR[i]);
02769   Position leftVec = frontierLeft - getCellPosition(curLRR[i]);
02770   Pose tempViewPoint = Pose( getCellPosition(curLRR[i]), getCellPosition(curLRR[i]).bearing() );
02771   
02772   if( gDebug > 19 )
02773   {
02774    //cout<< "      test VP pose: " << tempViewPoint.print() << endl;
02775    //cout<< "      right vec: " << rightVec.print() << " bearing " << rightVec.bearing().print() << endl;
02776   }
02777   
02778   if( !(isCellCovered( tempViewPoint, frontierCellsOnMRFA[0])) )
02779   {
02780    // must cover right most frontier cell, to avoid splitting frontier
02781    continue;
02782   }
02783   
02784   //cout<< "covered! waiting for continue ..." << endl;
02785   //getchar();
02786   
02787   if( getCell(curLRR[i])->distVP() < minVPDist )
02788   {
02789    // must be further away than min length
02790    continue;
02791   }
02792   
02793   if( (m_followers.size() > 0 || isWaitingForAnyAgent()) )
02794   {
02795    // Guarantee required coverage of MRFA
02796    bool bAllCovered = true;
02797    bool bAngCoverage = false;
02798    //if( gDebug > 12 ) cout<< "     considering cell " << i << endl;
02799    
02800    for( int j = 0; j < frontierCellsOnMRFA.size(); j++ )
02801    {
02802     if( isCellCovered(tempViewPoint, frontierCellsOnMRFA[j]) )
02803     {
02804      Position pos = getCellPosition(frontierCellsOnMRFA[j]);
02805      frontierLeft = pos;
02806      Angle angle = atan2( pos.y(), pos.x() );
02807      leftAngleCovered = angle;
02808      
02809      iFrontierCoverage++;
02810      distHeuristic += getCellPosition(curLRR[i]).dist(pos);
02811      
02812      angCoverage = angDistCCW( rightAngleCovered.dCastPi(), leftAngleCovered.dCastPi(), true );
02813      
02814      if( (*iNumViewPoints) > 1 && (angCoverage) > (angWidthOfMRFA / (*iNumViewPoints)) )
02815      {
02816       break;
02817      }
02818     }
02819     else
02820     {
02821      //if( iFrontierCoverage > 0 && gDebug > 12 ) cout<< "     " << i << " only covers " << iFrontierCoverage << endl;
02822      bAllCovered = false;
02823      break;
02824     }
02825    }
02826    
02827    if( (*iNumViewPoints) == 1 )
02828    {
02829     if( iFrontierCoverage >= iMaxFrontierCoverage )
02830     {
02831      if( (iFrontierCoverage > iMaxFrontierCoverage) || (distHeuristic < bestDistHeuristic) || (bestDistHeuristic < 0.0) )
02832      {
02833       if( gDebug > 9 ) cout<< "     New best VP at cell " << i << ", covers " << iFrontierCoverage << " with dist heur " << distHeuristic << endl;;
02834       iMaxFrontierCoverage = iFrontierCoverage;
02835       iViewPoint = i;
02836       
02837       Position rightVec = frontierRight - getCellPosition(curLRR[i]);
02838       Position leftVec = frontierLeft - getCellPosition(curLRR[i]);
02839 
02840       viewPoint = Pose( getCellPosition(curLRR[i]), rightVec.bearing() + std::min(getCoverFieldOfView()/2.0, (rightVec.bearing().ccwDiff(leftVec.bearing())/2.0)) );
02841       bestDistHeuristic = distHeuristic;
02842      }
02843     }
02844    }
02845    else
02846    {
02847     if( (iFrontierCoverage >= iMaxFrontierCoverage) )
02848     {
02849      if( (iFrontierCoverage > iMaxFrontierCoverage) || (distHeuristic < bestDistHeuristic) || (bestDistHeuristic < 0.0) )
02850      {
02851       if( gDebug > 9 ) cout<< "     New best VP at cell " << i << ", covers " << iFrontierCoverage << " (" << angCoverage << ") with dist heur " << distHeuristic << endl;
02852       iMaxFrontierCoverage = iFrontierCoverage;
02853       bestCoverage = angCoverage;
02854       iViewPoint = i;
02855       
02856       Position rightVec = frontierRight - getCellPosition(curLRR[i]);
02857       Position leftVec = frontierLeft - getCellPosition(curLRR[i]);
02858       
02859       viewPoint = Pose( getCellPosition(curLRR[i]), rightVec.bearing() + std::min(getCoverFieldOfView()/2.0, (rightVec.bearing().ccwDiff(leftVec.bearing())/2.0)) );
02860       bestDistHeuristic = distHeuristic;
02861      }
02862     }
02863    }
02864   }
02865   else
02866   {
02867    
02868    // Cover all of frontier
02869    for( int j = 0; j < frontier.size(); j++ )
02870    {
02871     for( int k = 0; k < frontier[j].size(); k++ )
02872     {
02873      if( isCellCovered( tempViewPoint, frontier[j][k] ) )
02874      {
02875       Position vec = getCellPosition(frontier[j][k]) - getCellPosition(curLRR[i]);
02876       
02877       
02878       iFrontierCoverage++;
02879       distHeuristic += vec.norm();
02880      }
02881     }
02882    }
02883    
02884    if( (iFrontierCoverage > iMaxFrontierCoverage) || 
02885    ((iFrontierCoverage == iMaxFrontierCoverage) && (distHeuristic < bestDistHeuristic)) )
02886    {
02887     iMaxFrontierCoverage = iFrontierCoverage;
02888     iViewPoint = i;
02889     
02890     viewPoint = tempViewPoint;
02891     bestDistHeuristic = distHeuristic;
02892     
02893     if( gDebug > 15 ) cout<< "    new best: " << viewPoint.print() << " covers " << iMaxFrontierCoverage << " with heuristic " << bestDistHeuristic << endl;
02894    }
02895   }
02896  }
02897  
02898  // Does best view point cover all frontier cells?
02899  int iTotalFrontierCells = 0;
02900  for( int i = 0; i < frontier.size(); i++ )
02901  {
02902   iTotalFrontierCells += frontier[i].size();
02903  }
02904  
02905  if( gDebug > 2 ) cout<< "  View point " << viewPoint.print() << " covers " << iMaxFrontierCoverage << " out of " << iTotalFrontierCells << " frontier cells" << endl;
02906  
02907  if( iMaxFrontierCoverage < iTotalFrontierCells )
02908  {
02909   (*iNumViewPoints) = std::max( (*iNumViewPoints), 2 );
02910  }
02911  
02912  if( gDebug > 19 )
02913  {
02914   gGP->Clear();
02915   
02916   for( int j = 0; j < frontier.size(); j++ )
02917   {
02918    for( int k = 0; k < frontier[j].size(); k++ )
02919    {
02920     if( isCellCovered( viewPoint, frontier[j][k] ) )
02921     {
02922      drawSquare( gColorFrontier, getCellPosition(frontier[j][k]) + curPose.pos(), 0.01, true );
02923     }
02924     else
02925     {
02926      drawSquare( gColorGray, getCellPosition(frontier[j][k]) + curPose.pos(), 0.01, true );
02927     }
02928    }
02929   }
02930   
02931   cout<< "Waiting for continue ..." << endl;
02932   char input[10];
02933   cin>> input;
02934  }
02935  
02936  
02937  
02938  //if( bDebugDisplay )
02939  //{
02940   //gGP->Clear();
02941   
02942   //drawLSR( *gGP, false );
02943   
02944   //drawRedX( getLSRPose().pos() + viewPoint.pos(), .1 );
02945   
02946   //if( gDebug > 30 )
02947   //{
02948    //cout<< "Waiting for go ahead..." << endl;
02949    //char input[10];
02950    //cin>> input;
02951   //}
02952   //else
02953   //{
02954    //TimeUtilities::sleep( Time(1,000000) );
02955   //}
02956   
02957   //gGP->Clear();
02958  //}
02959  
02960  return viewPoint;
02961 }
02962 
02963 void PursuitAgent::setFrontier(Frontier frontier, bool bForce )
02964 {
02965  if(bForce)
02966  {
02967   m_frontier = frontier;
02968   return;
02969  }
02970  
02971  int iCells = 0;
02972  for( int i = 0; i < frontier.size(); i++ )
02973  {
02974   iCells += frontier[i].size();
02975  }
02976  
02977  if( !m_bFrontierInitialized )
02978  {
02979   bool bDoUpdate = (iCells < getTotalFrontierCells());
02980   
02981   m_prevFrontier = frontier;
02982   
02983   if( bDoUpdate ) 
02984   {
02985    if( gDebug > 0 ) cout<< "  " << getID() << " doing set prev frontier updated" << endl;
02986    processFrontier( AgentVector() );
02987   }
02988  }
02989  else
02990  {
02991   bool bDoUpdate = (iCells == 0 || iCells < getTotalFrontierCells());
02992   
02993   m_frontier = frontier;
02994   
02995   if( bDoUpdate && isWaitingForAnyAgent() )
02996   {
02997    processFrontier( AgentVector() );
02998   }
02999   // if new frontier is empty, guard logic will switch behavior
03000  }
03001 }
03002 
03003 int PursuitAgent::getTotalFrontierCells()
03004 {
03005  int iCells = 0;
03006  Frontier frontier = getFrontier();
03007  for( int i = 0; i < frontier.size(); i++ )
03008  {
03009   iCells += frontier[i].size();
03010  }
03011  
03012  return iCells;
03013 }
03014 
03015 Pose PursuitAgent::getViewpoint( )
03016 {
03017  if( m_path.size() > 0 )
03018  {
03019   return m_path.back();
03020  }
03021  else
03022  {
03023   return getPose();
03024  }
03025 }
03026 
03027 Scan PursuitAgent::getScan( )
03028 {
03029  clientRead();
03030  
03031  int iCount = m_pLaserProxy->GetCount();
03032  
03033  vector<Ray> rays;
03034  vector<Ray> rays2;
03035  
03036  for( int i = 0; i < iCount; i++ )
03037  {
03038   // TODO: any easy entry for bValid?
03039   rays.push_back( Ray( m_pLaserProxy->GetRange(i), m_pLaserProxy->GetBearing(i), /*bValid*/ true ) );
03040  }
03041  
03042  return Scan( rays, Time() );
03043 }
03044 
03045 vector<Cell* > PursuitAgent::getRaster( DubInt iCell1, DubInt iCell2 )
03046 {
03047  if( m_bFrontierInitialized )
03048  {
03049   return m_LSR.bresenham( getCell(iCell1), getCell(iCell2) );
03050  }
03051  else
03052  {
03053   return m_prevLSR.bresenham( getCell(iCell1), getCell(iCell2) );
03054  }
03055 }
03056 
03057 
03058 Pose PursuitAgent::getLSRPose()
03059 {
03060  if( m_bFrontierInitialized )
03061  {
03062   return m_LSR.center();
03063  }
03064  else
03065  {
03066   return m_prevLSR.center();
03067  }
03068 }
03069 
03070 void PursuitAgent::setToExpand( Path path, bool bClearPrevFrontier, AgentVector neighbors, bool bDoExpand )
03071 {
03072  if( gDebug > 5 ) cout<< "  " << getID() << ":  set to EXPAND" << endl;
03073  
03074  m_eBehavior = EXPAND;
03075  
03076  m_LSR = Grid();
03077  m_frontier.clear();
03078  m_bFrontierInitialized = false;
03079  if( bClearPrevFrontier )
03080  {
03081   m_prevLSR = m_LSR;
03082   m_prevFrontier.clear();
03083  }
03084  //m_freeArcs.clear();
03085  m_path = path;
03086  
03087  if( getPosition().dist(path.back().pos()) > 0.01 || fabs(getPose().ori().alDiff(path.back().ori())) > (2*M_PI)/180)
03088  {
03089   goTo( path.back() );
03090  }
03091  
03092  m_pWaitForAgent = NULL;
03093  
03094  if( bDoExpand ) Expand( neighbors );
03095 }
03096 
03097 void PursuitAgent::setToGuard( AgentVector neighbors )
03098 {
03099  if( gDebug > 5 ) cout<< "  " << getID() << ":  set to GUARD" << endl;
03100  
03101  m_eBehavior = GUARD;
03102  
03103  recordLSR();
03104  
03105  m_frontier.clear();
03106  m_bFrontierInitialized = false;
03107  //m_freeArcs.clear();
03108  //m_path.clear();
03109  
03110  m_pWaitForAgent = NULL;
03111  
03112  // Stop any current motion
03113  //goTo( getPose() );
03114  
03115  // preserve list of followers
03116  
03117  if( neighbors.size() > 0 )
03118  {
03119   Guard( neighbors );
03120  }
03121 }
03122 
03123 void PursuitAgent::setToFollow( AgentVector neighbors )
03124 {
03125  if( gDebug > 5 ) cout<< "  " << getID() << ":  set to FOLLOW" << endl;
03126  
03127  m_eBehavior = FOLLOW;
03128  
03129  m_LSR = Grid();
03130  m_prevLSR = m_LSR;
03131  m_frontier.clear();
03132  m_prevFrontier.clear();
03133  m_bFrontierInitialized = false;
03134  m_freeArcs.clear();
03135  m_path.clear();
03136  
03137  m_pWaitForAgent = NULL;
03138  
03139  // Stop any current motion
03140  //goTo( getPose() );
03141  
03142  while( !m_followers.empty() )
03143  {
03144   // Should never happen ...
03145   m_followers.back()->setToWander(neighbors);
03146   m_followers.pop_back();
03147  }
03148 }
03149 
03150 void PursuitAgent::setToWander( AgentVector neighbors )
03151 {
03152  if( gDebug > 5 ) cout<< "  " << getID() << ":  set to WANDER" << endl;
03153  
03154  m_eBehavior = WANDER;
03155  
03156  m_LSR = Grid();
03157  m_prevLSR = m_LSR;
03158  m_frontier.clear();
03159  m_prevFrontier.clear();
03160  m_bFrontierInitialized = false;
03161  m_freeArcs.clear();
03162  m_path.clear();
03163  
03164  m_pWaitForAgent = NULL;
03165  
03166  while( !m_followers.empty() )
03167  {
03168   m_followers.back()->setToWander( neighbors );
03169   m_followers.pop_back();
03170  }
03171  
03172  for( uint i = 0; i < neighbors.size(); i++ )
03173  {
03174   if( neighbors[i]->getID() != getID() )
03175   {
03176    if( neighbors[i]->isWaitingForAgent(getID()) )
03177    {
03178     neighbors[i]->clearWaitingForAgent();
03179    }
03180   }
03181  }
03182  
03183  // Stop any current motion
03184  //goTo( getPose() );
03185 }
03186 
03187 void PursuitAgent::setToNoBehavior( )
03188 {
03189  if( gDebug > 5 ) cout<< "  " << getID() << ":  set to NO_BEHAVIOR" << endl;
03190  
03191  m_eBehavior = NO_BEHAVIOR;
03192  
03193  m_LSR = Grid();
03194  m_frontier.clear();
03195  m_freeArcs.clear();
03196  m_bFrontierInitialized = false;
03197  m_path.clear();
03198  
03199  m_pWaitForAgent = NULL;
03200  
03201  while( !m_followers.empty() )
03202  {
03203   m_followers.back()->setToNoBehavior();
03204   m_followers.pop_back();
03205  }
03206  
03207  // Stop any current motion
03208  goTo( getPose() );
03209 }
03210 
03211 void PursuitAgent::goTo( Pose pose )
03212 {
03213  m_pPosProxy->GoTo((double)(pose.pos().x()),(double)(pose.pos().y()),(double)(pose.ori().dCast2Pi()));
03214  
03215  for( int i = 0; i < m_followers.size(); i++ )
03216  {
03217   Position followerPos = getFollowerPosition();
03218   followerPos *= (i+1.0);
03219   m_followers[i]->goTo( Pose(pose.pos() - followerPos, pose.ori()) );
03220  }
03221 }
03222 
03223 Position PursuitAgent::getFollowerPosition()
03224 {
03225  Position pos = Position( 0, 0 );
03226  if( m_path.size() > 1 )
03227  {
03228   pos = (m_path.back().pos() - m_path[m_path.size()-2].pos());
03229   
03230   //double multiplier = std::min( 1.0/(m_followers.size() + 1), (1.5*getWidth())/(pos.norm() + 0.1) );
03231   double multiplier = (1.6*getWidth())/std::max(pos.norm(), 0.1);
03232   
03233   pos *= multiplier;
03234  }
03235  
03236  return pos;
03237 }
03238 
03239 void PursuitAgent::addFollower( PursuitAgent* newFollower, bool bMove )
03240 {
03241  if( gDebug > 5 ) cout<< "  " << getID() << " gained follower " << newFollower->getID() << endl;
03242  
03243  if( newFollower->getID() == getID() )
03244  {
03245   assert(false);
03246   return;
03247  }
03248  
03249  m_followers.push_back(newFollower);
03250  
03251  if( bMove )
03252  {
03253   if( getPath().size() > 0 )
03254   {
03255    newFollower->goTo( Pose(getPath().back().pos() - getFollowerPosition()*m_followers.size(), getPath().back().ori()) );
03256   }
03257   else
03258   {
03259    //newFollower->goTo( getPose() );
03260   }
03261  }
03262 }
03263 
03264 void PursuitAgent::doCurrentBehavior( AgentVector neighbors )
03265 {
03266  //if( gDebug > 8 ) cout<< "  " << getID() << ":  doing current behavior" << endl;
03267  AgentVector leaders;
03268  
03269  clientRead();
03270  
03271  switch (m_eBehavior) {
03272   case EXPAND:
03273    Expand( neighbors );
03274    break;
03275   case GUARD:
03276    Guard( neighbors );
03277    break;
03278   case FOLLOW:
03279    if( gDebug > 8 ) cout<< "  " << getID() << ":  following" << endl;
03280    break;
03281   case NO_BEHAVIOR:
03282    break;
03283   case WANDER:
03284    if( gDebug > 8 ) cout<< "  " << getID() << ":  wandering" << endl;
03285    Wander( neighbors );
03286    break;
03287   default:
03288    cerr<< "ERROR: No behavior category" << endl;
03289    assert(false);
03290   }
03291 }
03292 
03293 bool PursuitAgent::isLeader()
03294 {
03295  return ((m_eBehavior == EXPAND) || (m_eBehavior == GUARD));
03296 }
03297 
03298 bool PursuitAgent::isReady()
03299 {
03300  if( m_pPosProxy->GetSize().sw == 0 || m_pLaserProxy->GetCount() == 0 )
03301  {
03302   return false;
03303  }
03304  
03305  if( isTraveling() )
03306  {
03307   return false;
03308  }
03309  
03310  if( isWaitingForAnyAgent() )
03311  {
03312   return false;
03313  }
03314  
03315  return true;
03316 }
03317 
03318 bool PursuitAgent::isWaitingForAnyAgent()
03319 {
03320  if( m_pWaitForAgent != NULL )
03321  {
03322   return true;
03323  }
03324  
03325  return false;
03326 }
03327 
03328 bool PursuitAgent::isWaitingForAgent(int iID)
03329 {
03330  if( !isWaitingForAnyAgent() )
03331  { 
03332   return false;
03333  }
03334  
03335  if( m_pWaitForAgent->getID() == iID )
03336  {
03337   return true;
03338  }
03339  
03340  return false;
03341 }
03342 
03343 void PursuitAgent::clearWaitingForAgent()
03344 {
03345  m_pWaitForAgent = NULL;
03346 }
03347 
03348 bool PursuitAgent::isTraveling()
03349 {
03350  if( m_path.empty() )
03351  {
03352   return false;
03353  }
03354  
03355  clientRead();
03356  
03357  Pose curPose = getPose();
03358  double dist = curPose.pos().dist(m_path.back().pos());
03359  double check = std::max(m_pPosProxy->GetSize().sw/4,m_pPosProxy->GetSize().sl/4);
03360  
03361  check = std::max( check, 0.011 );
03362  
03363  if( dist > check )
03364  {
03365   //if( dist > 4*check || ((m_pPosProxy->GetXSpeed() + m_pPosProxy->GetYSpeed()) > check/10.0 || m_pPosProxy->GetYawSpeed() > 0.05) )
03366   {
03367    if( gDebug > 10 ) cout<< "    " << getID() << " is travelling, at " << curPose.print() << " dist " << dist << " v. check " << check << endl;
03368    return true;
03369   }
03370  }
03371  
03372  if( (m_pLaserProxy->GetMaxAngle() - m_pLaserProxy->GetMinAngle()) < 1.9*M_PI )
03373  {
03374   if( fabs(curPose.ori().alDiff( m_path.back().ori() )) > (2 * M_PI)/180 )
03375   {
03376    if( gDebug > 10 ) cout<< "    " << getID() << " is turning to final pose, at " << curPose.print() << endl;
03377    return true;
03378   }
03379  }
03380  
03381  return false;
03382 }
03383 
03384 bool PursuitAgent::canDetectTargetPosition( Position targetPos )
03385 {
03386  Position curPos = getLSRPose().pos();
03387  
03388  if( m_bFrontierInitialized || m_prevFrontier.size() > 0 )
03389  {
03390   Cell* targetCell = getCell( targetPos - curPos );
03391   
03392   if( targetCell != NULL )
03393   {
03394    if( targetCell->isLSR() || targetCell->isObstacle() )
03395    {
03396     if( gDebug > 0 ) cout<< "Detection!  Agent " << getID() << " at " << curPos.print() << " spots evader at " << targetPos.print() << endl;
03397     return true;
03398    }
03399   }
03400  }
03401  
03402  return false;
03403 }
03404 
03405 void PursuitAgent::drawBoundary( Graphics2dProxy &gp )
03406 {
03407  bool bDoAgentColors = (gDebug > 10);
03408  Position curPos = getLSRPose().pos();
03409 
03410  LSRBound lsrBound = getLSR().lsrBound();
03411  Frontier frontier = getFrontier();
03412  int i, j, l;
03413  Cell* pBoundCell;
03414  bool bIsActualFrontier;
03415  
03416  if( frontier.size() <= 0 )
03417  {
03418   return;
03419  }
03420  
03421  for( l = 0; l < lsrBound.size(); l++ )
03422  {
03423   pBoundCell = getCell(lsrBound[l]);
03424   
03425   bIsActualFrontier = false;
03426   for( i = 0; !bIsActualFrontier && i < frontier.size(); i++ )
03427   {
03428    for( j = 0; !bIsActualFrontier && j < frontier[i].size(); j++ )
03429    {
03430     bIsActualFrontier = (lsrBound[l] == frontier[i][j]);
03431    }
03432   }
03433   
03434   if( bIsActualFrontier )
03435   {
03436    drawSquare( (bDoAgentColors ? gColorVec[getID()] : gColorFrontier), curPos + pBoundCell->point(), 0.013, true );
03437    
03438    if( gDebug > 8 )
03439    {
03440     if( pBoundCell->isLabelA() )
03441     {
03442      drawX( gColorGreen, curPos + pBoundCell->point(), 0.02 );
03443     }
03444     else if( pBoundCell->isLabelB() )
03445     {
03446      drawX( gColorRed, curPos + pBoundCell->point(), 0.02 );
03447     }
03448    }
03449   }
03450   else if( pBoundCell->isFrontier() )
03451   {
03452    drawSquare( gColorFreeArc, curPos + pBoundCell->point(), 0.013, true );
03453   }
03454   else if( pBoundCell->isObstacle() )
03455   {
03456    drawSquare( gColorObstacle, curPos + pBoundCell->point(), 0.013, true );
03457   }
03458  }
03459  
03460  if( m_path.size() > 0 )
03461  {
03462   //drawX( gColorVec[getID()], m_path.back(), 0.05 );
03463  }
03464 }
03465 
03466 void PursuitAgent::drawFrontier( Graphics2dProxy &gp )
03467 {
03468  bool bDoAgentColors = (gDebug > 8);
03469  Position curPos = getLSRPose().pos();
03470  player_point_2d_t point;
03471  
03472  Frontier frontier = getFrontier();
03473  
03474  for( int i = 0; i < frontier.size(); i++ )
03475  {
03476   player_point_2d_t frontierPts[frontier[i].size()];
03477   for( int j = 0; j < frontier[i].size(); j++ )
03478   {
03479    Cell* pCell = getCell(frontier[i][j]);
03480    if( pCell != NULL )
03481    {
03482     frontierPts[j].px = curPos.x() + pCell->point().x();
03483     frontierPts[j].py = curPos.y() + pCell->point().y();
03484     
03485     drawSquare( gColorVec[getID()], curPos + pCell->point(), 0.01, true );
03486    }
03487   }
03488   
03489   if( frontier[i].size() > 1 )
03490   {
03491    gp.Color( gColorVec[getID()] );
03492   
03493    gp.DrawPolyline( frontierPts, frontier[i].size() );
03494   }
03495   
03496   if( bDoAgentColors ) drawRedX( curPos + getCell(frontier[i][frontier[i].size()-1])->point(), .02 );
03497  }
03498  
03499  if( m_path.size() > 0 )
03500  {
03501   if( bDoAgentColors ) drawX( gColorVec[getID()], m_path.back().pos(), 0.05 );
03502  }
03503 }
03504 
03505 void PursuitAgent::drawLSR( Graphics2dProxy &gp, bool bOnlyLSR )
03506 {
03507  Position curPos = getLSRPose().pos();
03508  player_point_2d_t point;
03509  
03510  int LSRsize = getLSRSize();
03511  player_color_t color;
03512  
03513  for( int i = 0; i < LSRsize; i++ )
03514  {
03515   Position LSRpoint = getCell(i)->point();
03516   
03517   if( !bOnlyLSR && getCell(i)->isFrontier() )
03518   {
03519    color.alpha = 0;
03520    color.red = 0;
03521    color.green = 0;
03522    color.blue = 255;
03523 
03524    drawSquare( color, curPos + LSRpoint, 0.01, true );
03525   }
03526   else if( !bOnlyLSR && getCell(i)->isObstacle() )
03527   {
03528    color.alpha = 0;
03529    color.red = 255;
03530    color.green = 0;
03531    color.blue = 0;
03532 
03533    drawSquare( color, curPos + LSRpoint, 0.01, true );
03534   }
03535   else if( !bOnlyLSR && getCell(i)->isLRR() )
03536   {
03537    color.alpha = 0;
03538    color.red = 0;
03539    color.green = 180;
03540    color.blue = 0;
03541 
03542    drawSquare( color, curPos + LSRpoint, 0.01, true );
03543   }
03544   else if( getCell(i)->isLSR() )
03545   {            
03546    color.alpha = 0;
03547    color.red = 0;
03548    color.green = 255;
03549    color.blue = 0;
03550 
03551    drawSquare( color, curPos + LSRpoint, 0.01, true );
03552   }
03553  }
03554  
03555 }
03556 
03557 #endif

Generated on Mon Feb 20 07:01:07 2017 for MIP by  doxygen 1.5.6