model_fiducial.cc
Go to the documentation of this file.
00001 
00002 //
00003 // File: model_fiducial.c
00004 // Author: Richard Vaughan
00005 // Date: 10 June 2004
00006 //
00007 // CVS info:
00008 //  $Source: /home/tcollett/stagecvs/playerstage-cvs/code/stage/libstage/model_fiducial.cc,v $
00009 //  $Author: rtv $
00010 //  $Revision$
00011 //
00013 
00014 #undef DEBUG 
00015 
00016 #include "stage.hh"
00017 #include "option.hh"
00018 #include "worldfile.hh"
00019 using namespace Stg;
00020 
00021 //TODO make instance attempt to register an option (as customvisualizations do)
00022 Option ModelFiducial::showData( "Fiducials", "show_fiducial", "", true, NULL );
00023 Option ModelFiducial::showFov( "Fiducial FOV", "show_fiducial_fov", "", false, NULL );
00024 
00067   ModelFiducial::ModelFiducial( World* world, 
00068                                                                                   Model* parent,
00069                                                                                   const std::string& type ) : 
00070   Model( world, parent, type ),
00071   fiducials(),
00072   max_range_anon( 8.0 ),
00073   max_range_id( 5.0 ),
00074   min_range( 0.0 ),
00075   fov( M_PI ),
00076   heading( 0 ),
00077   key( 0 ),
00078   ignore_zloc(false)
00079 {
00080   //PRINT_DEBUG2( "Constructing ModelFiducial %d (%s)\n", 
00081   //            id, typestr );
00082   
00083   // assert that Update() is reentrant for this derived model
00084   thread_safe = true;
00085   
00086   // sensible fiducial defaults 
00087   //  interval = 200; // common for a SICK LMS200
00088   
00089   this->ClearBlocks();
00090   
00091   Geom geom;
00092   geom.Zero();
00093   SetGeom( geom );
00094   
00095   RegisterOption( &showData );
00096   RegisterOption( &showFov );
00097 }
00098 
00099 ModelFiducial::~ModelFiducial( void )
00100 {
00101 }
00102 
00103 static bool fiducial_raytrace_match( Model* candidate, 
00104                                                                                                  Model* finder, 
00105                                                                                                  const void* dummy )
00106 {
00107   (void)dummy; // avoid warning about unused var
00108   return( ! finder->IsRelated( candidate ) );
00109 }       
00110 
00111 
00112 void ModelFiducial::AddModelIfVisible( Model* him )  
00113 {
00114         //PRINT_DEBUG2( "Fiducial %s is testing model %s", token, him->Token() );
00115 
00116         // only non-zero IDs should ever be checked
00117         assert( him->vis.fiducial_return != 0 );
00118         
00119         // check to see if this neighbor has the right fiducial key
00120         // if keys are used extensively, then perhaps a vector per key would be faster
00121         if( vis.fiducial_key != him->vis.fiducial_key )
00122         {
00123                 //PRINT_DEBUG1( "  but model %s doesn't match the fiducial key", him->Token());
00124                 return;
00125         }
00126 
00127         Pose mypose = this->GetGlobalPose();
00128 
00129         // are we within range?
00130         Pose hispose = him->GetGlobalPose();
00131         double dx = hispose.x - mypose.x;
00132         double dy = hispose.y - mypose.y;
00133         double range = hypot( dy, dx );
00134 
00135         //  printf( "range to target %.2f m (
00136 
00137         if( range >= max_range_anon )
00138         {
00139                 //PRINT_DEBUG3( "  but model %s is %.2f m away, outside my range of %.2f m", 
00140                 //          him->Token(),
00141                 //          range,
00142                 //          max_range_anon );
00143                 return;
00144         }
00145 
00146         // is he in my field of view?
00147         double bearing = atan2( dy, dx );
00148         double dtheta = normalize(bearing - mypose.a);
00149 
00150         if( fabs(dtheta) > fov/2.0 )
00151         {
00152                 //PRINT_DEBUG1( "  but model %s is outside my FOV", him->Token());
00153                 return;
00154         }
00155 
00156         if( IsRelated( him ) )
00157                 return;
00158 
00159         //PRINT_DEBUG1( "  %s is a candidate. doing ray trace", him->Token());
00160 
00161 
00162         //printf( "bearing %.2f\n", RTOD(bearing) );
00163 
00164         //If we've gotten to this point, a few things are true:
00165         // 1. The fiducial is in the field of view of the finder.
00166         // 2. The fiducial is in range of the finder.
00167         //At this point the purpose of the ray trace is to start at the finder and see if there is anything
00168         //in between the finder and the fiducial.  If we simply trace out to the distance we know the finder
00169         //is at, then the resulting ray.mod can be one of three things:
00170         // 1. A pointer to the model we're tracing to.  In this case the model is at the right Zloc to be 
00171         //    returned by the ray tracer.
00172         // 2. A pointer to another model that blocked the ray.
00173         // 3. NULL.  If it's null, then it means that the ray traced to where the fiducial should be but
00174         //    it's zloc was such that the ray didn't hit it.  However, we DO know its there, so we can 
00175         //    return this as a hit.
00176 
00177         //printf( "range %.2f\n", range );
00178         
00179         RaytraceResult ray( Raytrace( dtheta,
00180                                                                                                                                 max_range_anon, // TODOscan only as far as the object
00181                                                                                                                                 fiducial_raytrace_match,
00182                                                                                                                                 NULL,
00183                                                                                                                                 true ) );
00184         
00185         // TODO
00186         if( ignore_zloc && ray.mod == NULL ) // i.e. we didn't hit anything *else*
00187                 ray.mod = him; // so he was just at the wrong height
00188         
00189         //printf( "ray hit %s and was seeking LOS to %s\n",
00190         //                      ray.mod ? ray.mod->Token() : "null",
00191         //                      him->Token() );
00192         
00193         // if it was him, we can see him
00194         if( ray.mod != him )
00195                 return;
00196         
00197         assert( range >= 0 );
00198         
00199         // passed all the tests! record the fiducial hit
00200         
00201         Geom hisgeom( him->GetGeom() );
00202         
00203         // record where we saw him and what he looked like
00204         Fiducial fid;
00205         fid.mod = him;
00206         fid.range = range;
00207         fid.bearing = dtheta;
00208         fid.geom.x = hisgeom.size.x;
00209         fid.geom.y = hisgeom.size.y;
00210         fid.geom.z = hisgeom.size.z;
00211         fid.geom.a = normalize( hispose.a - mypose.a);
00212         
00213         //fid.pose_rel = hispose - this->GetGlobalPose();
00214 
00215         // store the global pose of the fiducial (mainly for the GUI)
00216         fid.pose = hispose;
00217         
00218         // if he's within ID range, get his fiducial.return value, else
00219         // we see value 0
00220         fid.id = range < max_range_id ? him->vis.fiducial_return : 0;
00221         
00222         //PRINT_DEBUG2( "adding %s's value %d to my list of fiducials",
00223         //                        him->Token(), him->vis.fiducial_return );
00224         
00225         fiducials.push_back( fid );
00226 }       
00227 
00228 
00230 // Update the beacon data
00231 //
00232 void ModelFiducial::Update( void )
00233 {
00234   //PRINT_DEBUG( "fiducial update" );
00235 
00236         if( subs < 1 )
00237                 return;
00238 
00239         // reset the array of detected fiducials
00240         fiducials.clear();
00241 
00242 #if( 1 )        
00243         // BEGIN EXPERIMENT
00244         
00245         // find two sets of fiducial-bearing models, within sensor range on
00246         // the two different axes
00247         
00248         double rng = max_range_anon;
00249         Pose gp = GetGlobalPose();      
00250         Model edge;     // dummy model used to find bounds in the sets
00251         
00252         edge.pose = Pose( gp.x-rng, gp.y, 0, 0 ); // LEFT
00253         std::set<Model*,World::ltx>::iterator xmin = 
00254                 world->models_with_fiducials_byx.lower_bound( &edge ); // O(log(n))
00255         
00256         edge.pose = Pose( gp.x+rng, gp.y, 0, 0 ); // RIGHT
00257         const std::set<Model*,World::ltx>::iterator xmax = 
00258                 world->models_with_fiducials_byx.upper_bound( &edge );
00259         
00260         edge.pose = Pose( gp.x, gp.y-rng, 0, 0 ); // BOTTOM
00261         std::set<Model*,World::lty>::iterator ymin = 
00262                 world->models_with_fiducials_byy.lower_bound( &edge );
00263         
00264         edge.pose = Pose( gp.x, gp.y+rng, 0, 0 ); // TOP
00265         const std::set<Model*,World::lty>::iterator ymax = 
00266                 world->models_with_fiducials_byy.upper_bound( &edge );
00267                 
00268         // put these models into sets keyed on model pointer, rather than position
00269         std::set<Model*> horiz, vert;
00270         
00271         for( ; xmin != xmax;  ++xmin)
00272                 horiz.insert( *xmin);
00273         
00274         for( ; ymin != ymax; ++ymin )
00275                 vert.insert( *ymin );
00276         
00277         // the intersection of the sets is all the fiducials close by
00278         std::vector<Model*> nearby;
00279         std::set_intersection( horiz.begin(), horiz.end(),
00280                                                                                                  vert.begin(), vert.end(),
00281                                                                                                  std::inserter( nearby, nearby.end() ) ); 
00282         
00283         //      printf( "cand sz %lu\n", nearby.size() );
00284                         
00285         // create sets sorted by x and y position
00286         FOR_EACH( it, nearby ) 
00287                         AddModelIfVisible( *it );       
00288 #else
00289         FOR_EACH( it, world->models_with_fiducials )
00290                         AddModelIfVisible( *it );       
00291 
00292 #endif
00293 
00294         // find the range of fiducials within range in X
00295 
00296         Model::Update();
00297 }
00298 
00299 void ModelFiducial::Load( void )
00300 {  
00301         PRINT_DEBUG( "fiducial load" );
00302 
00303         Model::Load();
00304 
00305         // load fiducial-specific properties
00306         min_range             = wf->ReadLength( wf_entity, "range_min",    min_range );
00307         max_range_anon        = wf->ReadLength( wf_entity, "range_max",    max_range_anon );
00308         max_range_id          = wf->ReadLength( wf_entity, "range_max_id", max_range_id );
00309         fov                   = wf->ReadAngle ( wf_entity, "fov",          fov );
00310   ignore_zloc            = wf->ReadInt  ( wf_entity, "ignore_zloc",  ignore_zloc);
00311 }  
00312 
00313 
00314 void ModelFiducial::DataVisualize( Camera* cam )
00315 {
00316   (void)cam; // avoid warning about unused var
00317 
00318         if( showFov )
00319           {
00320                  PushColor( 1,0,1,0.2  ); // magenta, with a bit of alpha
00321 
00322                  GLUquadric* quadric = gluNewQuadric();
00323                  
00324                  gluQuadricDrawStyle( quadric, GLU_SILHOUETTE );
00325                  
00326                  gluPartialDisk( quadric,
00327                                                           0, 
00328                                                           max_range_anon,
00329                                                           20, // slices 
00330                                                           1, // loops
00331                                                           rtod( M_PI/2.0 + fov/2.0), // start angle
00332                                                           rtod(-fov) ); // sweep angle
00333                  
00334                  gluDeleteQuadric( quadric );
00335 
00336                  PopColor();
00337           }
00338         
00339         if( showData )
00340           {
00341                  PushColor( 1,0,1,0.4  ); // magenta, with a bit of alpha
00342                  
00343                  // draw fuzzy dotted lines     
00344                  glLineWidth( 2.0 );
00345                  glLineStipple( 1, 0x00FF );
00346                  
00347                  // draw lines to the fiducials
00348                  FOR_EACH( it, fiducials )
00349                         {
00350                           Fiducial& fid = *it;
00351                           
00352                           double dx = fid.range * cos( fid.bearing);
00353                           double dy = fid.range * sin( fid.bearing);
00354                           
00355                           glEnable(GL_LINE_STIPPLE);
00356                           glBegin( GL_LINES );
00357                           glVertex2f( 0,0 );
00358                           glVertex2f( dx, dy );
00359                           glEnd();
00360                           glDisable(GL_LINE_STIPPLE);
00361                                                   
00362                           glPushMatrix();
00363                           Gl::coord_shift( dx,dy,0,fid.geom.a );
00364                           
00365                           glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
00366                           glRectf( -fid.geom.x/2.0, -fid.geom.y/2.0,
00367                                                   fid.geom.x/2.0, fid.geom.y/2.0 );
00368                           
00369                           // show the fiducial ID
00370                           char idstr[32];
00371                           snprintf(idstr, 31, "%d", fid.id );
00372                           Gl::draw_string( 0,0,0, idstr );
00373                           
00374                           glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00375                           glPopMatrix();                        
00376                         }
00377                  
00378                  PopColor();                     
00379                  glLineWidth( 1.0 );            
00380           }      
00381 }
00382         
00383 void ModelFiducial::Shutdown( void )
00384 { 
00385   //PRINT_DEBUG( "fiducial shutdown" );
00386         fiducials.clear();      
00387         Model::Shutdown();
00388 }


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