model_ranger.cc
Go to the documentation of this file.
00001 
00002 //
00003 // File: model_ranger.cc
00004 // Author: Richard Vaughan
00005 // Date: 10 June 2004
00006 //
00007 // CVS info:
00008 //  $Source: /home/tcollett/stagecvs/playerstage-cvs/code/stage/libstage/model_ranger.cc,v $
00009 //  $Author: rtv $
00010 //  $Revision$
00011 //
00013 
00065 //#define DEBUG 1
00066 
00067 #include "stage.hh"
00068 #include "worldfile.hh"
00069 #include "option.hh"
00070 using namespace Stg;
00071 
00072 static const watts_t RANGER_WATTSPERSENSOR = 0.2;
00073 static const Stg::Size RANGER_SIZE( 0.15, 0.15, 0.2 ); // SICK LMS size
00074 
00075 //static const Color RANGER_COLOR( 0,0,1 );
00076 static const Color RANGER_CONFIG_COLOR( 0,0,0.5 );
00077 //static const Color RANGER_GEOM_COLOR( 1,0,1 );
00078 
00079 // static members
00080 Option ModelRanger::Vis::showTransducers( "Ranger transducers", "show_ranger_transducers", "", false, NULL );
00081 Option ModelRanger::Vis::showArea( "Ranger area", "show_ranger_ranges", "", true, NULL );
00082 Option ModelRanger::Vis::showStrikes( "Ranger strikes", "show_ranger_strikes", "", false, NULL );
00083 Option ModelRanger::Vis::showFov( "Ranger FOV", "show_ranger_fov", "", false, NULL );
00084 Option ModelRanger::Vis::showBeams( "Ranger beams", "show_ranger_beams", "", false, NULL );
00085 
00086 
00087 ModelRanger::ModelRanger( World* world, 
00088                           Model* parent,
00089                           const std::string& type ) 
00090   : Model( world, parent, type ),
00091     vis( world ) 
00092 {
00093   PRINT_DEBUG2( "Constructing ModelRanger %d (%s)\n", 
00094                 id, type );
00095   
00096   // Set up sensible defaults
00097   
00098   // assert that Update() is reentrant for this derived model
00099   thread_safe = true;
00100   
00101   this->SetColor( RANGER_CONFIG_COLOR );
00102   
00103   // remove the polygon: ranger has no body
00104   this->ClearBlocks();
00105   
00106   this->SetGeom( Geom( Pose(), RANGER_SIZE ));  
00107         
00108   AddVisualizer( &vis, true );  
00109 }
00110 
00111 ModelRanger::~ModelRanger()
00112 {
00113 }
00114 
00115 void ModelRanger::Startup( void )
00116 {
00117   Model::Startup();
00118   this->SetWatts( RANGER_WATTSPERSENSOR * sensors.size() );
00119 }
00120 
00121 
00122 void ModelRanger::Shutdown( void )
00123 {
00124   PRINT_DEBUG( "ranger shutdown" );
00125 
00126   this->SetWatts( 0 );
00127 
00128   Model::Shutdown();
00129 }
00130 
00131 void ModelRanger::LoadSensor( Worldfile* wf, int entity )
00132 {
00133   //static int c=0;
00134   // printf( "ranger %s loading sensor %d\n", token.c_str(), c++ );
00135   Sensor s;
00136   s.Load( wf, entity );
00137   sensors.push_back(s);
00138 }
00139 
00140 
00141 void ModelRanger::Sensor::Load( Worldfile* wf, int entity )
00142 {
00143   //static int c=0;
00144   // printf( "ranger %s loading sensor %d\n", token.c_str(), c++ );
00145         
00146   pose.Load( wf, entity, "pose" );
00147   size.Load( wf, entity, "size" );
00148   range.Load( wf, entity, "range" );
00149   col.Load( wf, entity );               
00150   fov = wf->ReadAngle( entity, "fov", fov );
00151   sample_count = wf->ReadInt( entity, "samples", sample_count );        
00152   //ranges.resize(sample_count);
00153   //intensities.resize(sample_count);
00154 }
00155 
00156 void ModelRanger::Load( void )
00157 {
00158   Model::Load();
00159 }
00160 
00161 static bool ranger_match( Model* hit, 
00162                           Model* finder,
00163                           const void* dummy )
00164 {
00165   (void)dummy; // avoid warning about unused var
00166   
00167   // Ignore the model that's looking and things that are invisible to
00168   // rangers 
00169   
00170   // small optimization to avoid recursive Model::IsRelated call in common cases
00171   if( (hit == finder->Parent()) || (hit == finder) ) return false;
00172   
00173   return( (!hit->IsRelated( finder )) && (sgn(hit->vis.ranger_return) != -1 ) );
00174 }       
00175 
00176 void ModelRanger::Update( void )
00177 {     
00178   // raytrace new range data for all sensors
00179   FOR_EACH( it, sensors )
00180     it->Update( this );
00181   
00182   Model::Update();
00183 }
00184 
00185 void ModelRanger::Sensor::Update( ModelRanger* mod )
00186 {
00187   ranges.resize( sample_count );
00188   intensities.resize( sample_count );
00189   bearings.resize( sample_count );
00190 
00191   //printf( "update sensor, has ranges size %u\n", (unsigned int)ranges.size() );
00192   // make the first and last rays exactly at the extremes of the FOV
00193   double sample_incr( fov / std::max(sample_count-1, (unsigned int)1) );
00194   
00195   // find the global origin of our first emmitted ray
00196   double start_angle = (sample_count > 1 ? -fov/2.0 : 0.0);
00197 
00198   Pose rayorg(pose);
00199   rayorg.a += start_angle;
00200   rayorg.z += size.z/2.0;
00201   rayorg = mod->LocalToGlobal(rayorg);
00202   
00203   // set up a ray to trace
00204   Ray ray( mod, rayorg, range.max, ranger_match, NULL, true );
00205   
00206   World* world = mod->GetWorld();
00207 
00208   // trace the ray, incrementing its heading for each sample
00209   for( size_t t(0); t<sample_count; t++ )
00210     {
00211       const RaytraceResult& r ( world->Raytrace( ray ) );
00212       ranges[t] = r.range;
00213       intensities[t] = r.mod ? r.mod->vis.ranger_return : 0.0;
00214       bearings[t] = start_angle + ((double)t) * sample_incr;
00215                 
00216       // point the ray to the next angle
00217       ray.origin.a += sample_incr;                      
00218 
00219       //printf( "ranger %s sensor %p pose %s sample %d range %.2f ref %.2f\n",
00220       //                        mod->Token(), 
00221       //                        this, 
00222       //                        pose.String().c_str(),
00223       //                        t, 
00224       //                        ranges[t].range, 
00225       //                        ranges[t].reflectance );
00226     }
00227 }
00228 
00229 std::string ModelRanger::Sensor::String() const
00230 {
00231   char buf[256];
00232   snprintf( buf, 256, "[ samples %u, range [%.2f %.2f] ]", 
00233             sample_count, range.min, range.max );
00234   return( std::string( buf ) );
00235 }
00236 
00237 void ModelRanger::Sensor::Visualize( ModelRanger::Vis* vis, ModelRanger* rgr ) const
00238 {
00239   size_t sample_count( this->sample_count );
00240         
00241   //glTranslatef( 0,0, ranger->GetGeom().size.z/2.0 ); // shoot the ranger beam out at the right height
00242                         
00243   // pack the ranger hit points into a vertex array for fast rendering
00244   GLfloat pts[2*(sample_count+1)];
00245   glVertexPointer( 2, GL_FLOAT, 0, &pts[0] );       
00246         
00247   pts[0] = 0.0;
00248   pts[1] = 0.0;
00249         
00250   glDepthMask( GL_FALSE );
00251   glPointSize( 2 );
00252         
00253   glPushMatrix();
00254 
00255   Gl::pose_shift( pose );
00256 
00257   if( vis->showTransducers )
00258     {
00259       // draw the sensor body as a rectangle
00260       rgr->PushColor( col );
00261       glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );                      
00262       glRectf( -size.x/2.0, -size.y/2.0, size.x/2.0, size.y/2.0 );
00263       rgr->PopColor();
00264     }
00265 
00266   Color c( col );
00267   c.a = 0.15; // transparent version of sensor color
00268   rgr->PushColor( c );
00269   glPolygonMode( GL_FRONT, GL_FILL );                   
00270         
00271   if( ranges.size()  ) // if we have some data
00272     {
00273       if( sample_count == 1 )
00274         {
00275           // only one sample, so we fake up some beam width for beauty
00276           const double sidelen = ranges[0];
00277           const double da = fov/2.0;
00278                                         
00279           sample_count = 3;
00280                                         
00281           pts[2] = sidelen*cos(-da );
00282           pts[3] = sidelen*sin(-da );
00283                                         
00284           pts[4] = sidelen*cos(+da );
00285           pts[5] = sidelen*sin(+da );
00286         }       
00287       else
00288         {
00289           for( size_t s(0); s<sample_count+1; s++ )
00290             {
00291               double ray_angle = (s * (fov / (sample_count-1))) - fov/2.0;
00292               pts[2*s+2] = (float)(ranges[s] * cos(ray_angle) );
00293               pts[2*s+3] = (float)(ranges[s] * sin(ray_angle) );
00294             }
00295         }
00296     }
00297                         
00298   if( vis->showArea )
00299     {
00300       if( sample_count > 1 )
00301         // draw the filled polygon in transparent blue
00302         glDrawArrays( GL_POLYGON, 0, sample_count );
00303     }
00304         
00305   glDepthMask( GL_TRUE );
00306         
00307   if( vis->showStrikes )
00308     {
00309       // TODO - paint the stike point in a color based on intensity
00310       //                        // if the sample is unusually bright, draw a little blob
00311       //                        if( intensities[s] > 0.0 )
00312       //                                {
00313       //                                        // this happens rarely so we can do it in immediate mode
00314       //                                        glBegin( GL_POINTS );
00315       //                                        glVertex2f( pts[2*s+2], pts[2*s+3] );
00316       //                                        glEnd();
00317       //                                }                        
00318                         
00319       // draw the beam strike points
00320       c.a = 0.8;
00321       rgr->PushColor( c );
00322       glDrawArrays( GL_POINTS, 0, sample_count+1 );
00323       rgr->PopColor();
00324     }
00325         
00326   if( vis->showFov )
00327     {
00328       for( size_t s(0); s<sample_count; s++ )
00329         {
00330           double ray_angle((s * (fov / (sample_count-1))) - fov/2.0);
00331           pts[2*s+2] = (float)(range.max * cos(ray_angle) );
00332           pts[2*s+3] = (float)(range.max * sin(ray_angle) );                     
00333         }
00334                         
00335       glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
00336       c.a = 0.5;
00337       rgr->PushColor( c );              
00338       glDrawArrays( GL_POLYGON, 0, sample_count+1 );
00339       rgr->PopColor();
00340     }                    
00341         
00342   if( vis->showBeams )
00343     {
00344       // darker version of the same color
00345       c.r /= 2.0;
00346       c.g /= 2.0;
00347       c.b /= 2.0;
00348       c.a = 1.0;
00349 
00350       rgr->PushColor( c );              
00351       glBegin( GL_LINES );
00352                         
00353       for( size_t s(0); s<sample_count; s++ )
00354         {
00355                                         
00356           glVertex2f( 0,0 );
00357           double ray_angle( sample_count == 1 ? 0 : (s * (fov / (sample_count-1))) - fov/2.0 );
00358           glVertex2f( ranges[s] * cos(ray_angle), 
00359                       ranges[s] * sin(ray_angle) );
00360                                         
00361         }
00362       glEnd();
00363       rgr->PopColor();
00364     }   
00365         
00366   rgr->PopColor();
00367 
00368   glPopMatrix();
00369 }
00370         
00371 void ModelRanger::Print( char* prefix ) const
00372 {
00373   Model::Print( prefix );
00374         
00375   printf( "\tRanges " );
00376   for( size_t i(0); i<sensors.size(); i++ )
00377     {
00378       printf( "[ " );
00379       for( size_t j(0); j<sensors[i].ranges.size(); j++ )
00380         printf( "%.2f ", sensors[i].ranges[j] );
00381                         
00382       printf( " ]" );
00383     }
00384         
00385   printf( "\n\tIntensities " );
00386   for( size_t i(0); i<sensors.size(); i++ )
00387     {
00388       printf( "[ " );
00389       for( size_t j(0); j<sensors[i].intensities.size(); j++ )
00390         printf( "%.2f ", sensors[i].intensities[j] );
00391                         
00392       printf( " ]" );
00393     }
00394   puts("");
00395 }
00396 
00397 
00398 
00399 // VIS -------------------------------------------------------------------
00400 
00401 ModelRanger::Vis::Vis( World* world ) 
00402   : Visualizer( "Ranger", "ranger_vis" )
00403 {
00404   world->RegisterOption( &showArea );
00405   world->RegisterOption( &showStrikes );
00406   world->RegisterOption( &showFov );
00407   world->RegisterOption( &showBeams );            
00408   world->RegisterOption( &showTransducers );
00409 }
00410 
00411 void ModelRanger::Vis::Visualize( Model* mod, Camera* cam ) 
00412 {
00413   (void)cam; // avoid warning about unused var
00414 
00415   ModelRanger* ranger( dynamic_cast<ModelRanger*>(mod) );
00416 
00417   const std::vector<Sensor>& sensors( ranger->GetSensors() );    
00418         
00419   FOR_EACH( it, sensors )
00420     it->Visualize( this, ranger );
00421         
00422   const size_t sensor_count = sensors.size();
00423 
00424   if( showTransducers )
00425     {
00426       glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00427       ranger->PushColor( 0,0,0,1 );
00428                         
00429       for( size_t s(0); s<sensor_count; s++ ) 
00430         { 
00431           const Sensor& rngr(sensors[s]);
00432                                         
00433           glPointSize( 4 );
00434           glBegin( GL_POINTS );
00435           glVertex3f( rngr.pose.x, rngr.pose.y, rngr.pose.z );
00436           glEnd();
00437                                         
00438           char buf[8];
00439           snprintf( buf, 8, "%d", (int)s );
00440           Gl::draw_string( rngr.pose.x, rngr.pose.y, rngr.pose.z, buf );
00441                                         
00442         }
00443       ranger->PopColor();
00444     }
00445 
00446 }
00447 


stage
Author(s): Richard Vaughan , Brian Gerkey , Reed Hedges , Andrew Howard , Toby Collett , Pooya Karimian , Jeremy Asher , Alex Couture-Beil , Geoff Biggs , Rich Mattes , Abbas Sadat
autogenerated on Thu Aug 27 2015 15:20:57