⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.cc

📁 一个机器人平台
💻 CC
📖 第 1 页 / 共 2 页
字号:
  {    PRINT_ERR("Player startup failed");    quit = true;    return false;  }    if( m_real_timestep > 0.0 ) // if we're in real-time mode    this->StartTimer( m_real_timestep ); // start the real-time interrupts going  if( !start_disabled )    m_enable = true;      return true;}///////////////////////////////////////////////////////////////////////////// Start the single instance of playerbool CStageServer::StartupPlayer( void ){  PRINT_DEBUG( "** STARTUP PLAYER **" );  // ----------------------------------------------------------------------  // fork off a player process to handle robot I/O  if( (this->player_pid = fork()) < 0 )  {    PRINT_ERR1("error forking for player: [%s]", strerror(errno));    return false;  }  // If we are the nmew child process...  if (this->player_pid == 0)  {    // release controlling tty so Player doesn't get signals    setpgid(0,0);    // call player like this:    // player -stage <device directory>    // player will open every file in the device directory    // and attempt to memory map it as a device.     // Player must be in the current path    if( execlp( "player", "player",                "-s", DeviceDirectory(),                 (strlen(m_auth_key)) ? "-k" : NULL,                (strlen(m_auth_key)) ? m_auth_key : NULL,                NULL) < 0 )    {      PRINT_ERR1("error executing player: [%s]\n"                 "Make sure player is in your path.", strerror(errno));      if(!kill(getppid(),SIGINT))      {        PRINT_ERR1("error killing player: [%s]", strerror(errno));        exit(-1);      }    }  }    //PRINT_DEBUG( "** STARTUP PLAYER DONE **" );  return true;}///////////////////////////////////////////////////////////////////////////// Stop player instancevoid CStageServer::ShutdownPlayer(){  int wait_retval;  if(this->player_pid)  {    if(kill(this->player_pid,SIGTERM))      PRINT_ERR1("error killing player: [%s]", strerror(errno));    if((wait_retval = waitpid(this->player_pid,NULL,0)) == -1)      PRINT_ERR1("waitpid failed: [%s]", strerror(errno));    this->player_pid = 0;  }}///////////////////////////////////////////////////////////////////////////// Update the worldvoid CStageServer::Update(void){  //PRINT_DEBUG( "** Server Update **" );  //assert( arg == 0 );    //while( !quit )  //printf( "update: enable: %d g_timer_events: %d m_real_timestep: %.3f\n",  //  m_enable, g_timer_events, m_real_timestep );  // get and handle any commands and updates from clients  this->Read();  // if the sim isn't running, we pause briefly and return  //if( !m_enable )  //{  //  usleep( 100000 );  //  return;  // }  // is it time to stop?  if(m_stoptime && m_sim_time >= m_stoptime)    {         quit = true;      return;    }        // let the entities do anything they want to do between clock increments  root->Sync();         // if the timer has gone off recently or we're in fast mode  // we increment the clock and do the time-based updates  if( g_timer_events > 0 || m_real_timestep == 0 )    {                CWorld::Update();            if( g_timer_events > 0 )	g_timer_events--; // we've handled this timer event            Write(); // write any changes back out to clients      Output(); // perform console and log output    }      // if there's nothing pending and we're not in fast mode, we let go  // of the processor (on linux gives us around a 10ms cycle time)  if( g_timer_events < 1 && m_real_timestep > 0.0 )     usleep( 0 );  // dump the contents of the matrix to a file for debugging  //world->matrix->dump();  //getchar();	}// read stuff until we get a continue message on each channelint CStageServer::Read( void ){  //PRINT_DEBUG( "Server::Read()" );  // look for new connections   ListenForConnections();    return CStageIO::Read();  }   void CStageServer::ListenForConnections( void ){  int readable = 0;    // poll for connection requests with a very fast timeout  if((readable = poll( &m_pose_listen, 1, 0 )) == -1)  {    if( errno != EINTR ) // timer interrupts are OK    {       perror( "Stage warning: poll error (not EINTR)");      return;    }  }    bool success = true;  // if the socket had a request  if( readable && (m_pose_listen.revents & POLLIN ) )   {    // set up a socket for this connection    struct sockaddr_in cliaddr;      bzero(&cliaddr, sizeof(cliaddr));#if PLAYER_SOLARIS    int clilen;#else    socklen_t clilen;#endif    clilen  = sizeof(cliaddr);    int connfd = 0;          connfd = accept( m_pose_listen.fd, (SA *) &cliaddr, &clilen);          // set the dirty flag for all entities on this connection    DirtyEntities( m_pose_connection_count );    // determine the type of connection, sync or async, by reading    // the first byte    char b = 0;    int r = 0;    if( (r = read( connfd, &b, 1 )) < 1 )     {      puts( "failed to read sync type byte. Quitting\n" );      if( r < 0 ) perror( "read error" );      exit( -1 );    }          // record the total bytes input    g_bytes_input += r;     // if this is a syncronized connection, increase the sync counter     switch( b )    {      case STAGE_SYNC:         m_sync_counter++; #ifdef VERBOSE              printf( "\nStage: SYNC pose connection accepted (id: %d fd: %d)\n",                 m_pose_connection_count, connfd );        fflush( stdout );#endif                    if( m_external_sync_required ) m_enable = true;        success = true;        break;      case STAGE_ASYNC:        //default:#ifdef VERBOSE              printf( "\nStage: ASYNC pose connection accepted (id: %d fd: %d)\n",                 m_pose_connection_count, connfd );        fflush( stdout );#endif                    success = true;        break;	        default: printf( "Stage: unknown sync on %d. Closing connection\n",                       connfd  );        close( connfd );        success = false;        break;    }       if( success )    {      // add the new connection to the arrays      // store the connection type to help us destroy it later      m_conn_type[ m_pose_connection_count ] = b;      // record the pollfd data      m_pose_connections[ m_pose_connection_count ].fd = connfd;      m_pose_connections[ m_pose_connection_count ].events = POLLIN;      m_pose_connection_count++;    }  }}bool CStageServer::Shutdown(){  int res = CWorld::Shutdown();  PRINT_DEBUG( "server shutting down" );  ShutdownPlayer();  // zap the clock device and lock file   unlink( clockName );  unlink( m_locks_name );  // delete the device directory  if( rmdir( m_device_dir ) != 0 )    PRINT_WARN2("failed to delete device directory \"%s\" [%s]",                m_device_dir,                strerror(errno));  return res;}//////////////////////////////////////////////////////////////////////////// Set up a file for record locking, 1 byte per entity// the contents aren't used - we just use fcntl() to lock bytesbool CStageServer::CreateLockFile( void ){  // store the filename  sprintf( m_locks_name, "%s/%s", m_device_dir, STAGE_LOCK_NAME );  m_locks_fd = -1;  if( (m_locks_fd = open( m_locks_name, O_RDWR | O_CREAT | O_TRUNC,                           S_IRUSR | S_IWUSR )) < 0 )  {    perror("Failed to create lock device" );    return false;  }     // set the file size - 1 byte per entity + 1 for the clock  off_t sz = GetEntityCount() + 1;    if( ftruncate( m_locks_fd, sz ) < 0 )  {    perror( "Failed to set lock file size" );    return false;  }  PRINT_DEBUG3( "Created lock file %s of %d bytes (fd %d)\n", 		m_locks_name, GetEntityCount(), m_locks_fd );    return true;}///////////////////////////////////////////////////////////////////////////// lock the shared mem//bool CStageServer::LockByte( int offset ){  assert( this->m_locks_fd > 0 );  // must have a lock file open  // POSIX RECORD LOCKING METHOD  struct flock cmd;    cmd.l_type = F_WRLCK; // request write lock  cmd.l_whence = SEEK_SET; // count bytes from start of file  cmd.l_start = offset; // lock my unique byte  cmd.l_len = 1; // lock 1 byte    fcntl( this->m_locks_fd, F_SETLKW, &cmd );  #ifdef DEBUG  // DEBUG: write into the file to show which byte is locked  // X = locked, '_' = unlocked  lseek( this->m_locks_fd, offset, SEEK_SET );  write(  this->m_locks_fd, "X", 1 );  //printf( "locking byte %d\n", offset );#endif  return true;}///////////////////////////////////////////////////////////////////////////// unlock the shared mem//bool CStageServer::UnlockByte( int offset ){  assert( this->m_locks_fd > 0 ); // if the world must have a locking file open  // POSIX RECORD LOCKING METHOD  struct flock cmd;    cmd.l_type = F_UNLCK; // request unlock  cmd.l_whence = SEEK_SET; // count bytes from start of file  cmd.l_start = offset; // unlock my unique byte  cmd.l_len = 1; // unlock 1 byte    fcntl( this->m_locks_fd, F_SETLKW, &cmd );  #ifdef DEBUG  // DEBUG: write into the file to show which byte is locked  // X = locked, '_' = unlocked  lseek( this->m_locks_fd, offset, SEEK_SET );  write(  this->m_locks_fd, "_", 1 );  //printf( "unlocking byte %d\n", offset );#endif    return true;}double CStageServer::SetClock( double interval, uint32_t step_num ){  // set the current time internally   double retval = CWorld::SetClock( interval, step_num );  // set the current time in shared mem  this->LockByte( clock_lock_byte );  m_clock->time.tv_sec = m_sim_timeval.tv_sec;  m_clock->time.tv_usec = m_sim_timeval.tv_usec;  this->UnlockByte( clock_lock_byte );  return retval;}void CStageServer::Write( void ){  //PRINT_DEBUG( "SERVER WRITE" );    // if player has changed the subscription count, we make the property dirty    // fix this - it limits the number of entities  // just move the memory into the entity  static int subscribed_last_time[ 10000 ];   static bool init = true;    // is this necessary? can't hurt i guess.  // first time round, we zero the static buffer  if( init )   {    memset( subscribed_last_time, false, 10000 );    init = false;  }        // TODO - FIX THIS  /*    // manage subscriptions only for CPlayerEntity    if( RTTI_ISTYPE( CPlayerEntity*, ent ) )     {    CPlayerEntity* pent = (CPlayerEntity*)ent;        //PRINT_DEBUG1( "checking subscription for entity %d", i );        int currently_subscribed =  pent->Subscribed();          //PRINT_DEBUG3( "Entity %d subscriptions: %d last time: %d\n",       //	    i, currently_subscribed, subscribed_last_time[i] );            // if the current subscription state is different from the last time      if( currently_subscribed != ent->subscribed_last_time[i] )	    {	      	      PRINT_DEBUG2( "Entity %d subscription change (%d subs)\n", 			    i, pent->Subscribed() );	      	      // remember this state for next time	      subscribed_last_time[i] = currently_subscribed;	      	      // mark the subscription property as dirty so we pick it up	      // below	      pent->SetDirty( PropPlayerSubscriptions , 1);	    }	  	}    }  */    CStageIO::Write();}/////////////////////////////////////////////////////////////////////////// Clock device -- create the memory map for IPC with Player bool CStageServer::CreateClockDevice( void ){     size_t clocksize = sizeof( stage_clock_t );    sprintf( clockName, "%s/clock", m_device_dir );    int tfd=-1;  if( (tfd = open( clockName, O_RDWR | O_CREAT | O_TRUNC,                    S_IRUSR | S_IWUSR )) < 0 )  {    PRINT_ERR1("Failed to open clock device file:%s", strerror(errno) );    return false;  }     // make the file the right size  off_t sz = clocksize;  if( ftruncate( tfd, sz ) < 0 )  {    PRINT_ERR1( "Failed to set clock file size:%s", strerror(errno) );    return false;  }    if( write( tfd, &m_sim_timeval, sizeof(m_sim_timeval)) < 0 )  {    PRINT_ERR1( "Failed to write time into clock device:%s", strerror(errno) );    return false;  }  void *map = mmap( NULL, clocksize,                     PROT_READ | PROT_WRITE, MAP_SHARED,                    tfd, (off_t) 0);    if (map == MAP_FAILED )  {    PRINT_ERR1( "Failed to map clock device memory:%s", strerror(errno) );    return false;  }    // Initialise space  //  memset( map, 0, clocksize );  // store the pointer to the clock  m_clock = (stage_clock_t*)map;    this->clock_lock_byte = this->GetEntityCount()+1;  PRINT_DEBUG1( "Clock lock byte: %d\n", this->clock_lock_byte ) ;  close( tfd ); // can close fd once mapped    PRINT_DEBUG( "Successfully mapped clock device." );    return true;}// sleep until a signal goes off// return the time in seconds we spent asleepdouble CStageServer::Pause(){  // we're too busy to sleep!  if( m_real_timestep == 0 || --g_timer_events > 0  )    return 0;    // otherwise  double sleep_start = GetRealTime();  pause(); // wait for the signal  return( GetRealTime() - sleep_start );}void CStageServer::StartTimer( double interval ){  // set up the interval timer  //  // set a timer to go off every few ms. in realtime mode we'll sleep  // in between if there's nothing else to do.   //install signal handler for timing  if( signal( SIGALRM, &TimerHandler ) == SIG_ERR )    {      PRINT_ERR("failed to install signal handler");      exit( -1 );    }  //printf( "interval: %f\n", interval );  //start timer with chosen interval (specified in milliseconds)  struct itimerval tick;  // seconds  tick.it_value.tv_sec = tick.it_interval.tv_sec = (long)floor(interval);  // microseconds  tick.it_value.tv_usec = tick.it_interval.tv_usec =     (long)fmod( interval * MILLION, MILLION);     if( setitimer( ITIMER_REAL, &tick, 0 ) == -1 )    {      PRINT_ERR("failed to set timer");      exit( -1 );    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -