model_fiducial.cc
Go to the documentation of this file.
1 //
3 // File: model_fiducial.c
4 // Author: Richard Vaughan
5 // Date: 10 June 2004
6 //
7 // CVS info:
8 // $Source: /home/tcollett/stagecvs/playerstage-cvs/code/stage/libstage/model_fiducial.cc,v $
9 // $Author: rtv $
10 // $Revision$
11 //
13 
14 #undef DEBUG
15 
16 #include "stage.hh"
17 #include "option.hh"
18 #include "worldfile.hh"
19 using namespace Stg;
20 
21 //TODO make instance attempt to register an option (as customvisualizations do)
22 Option ModelFiducial::showData( "Fiducials", "show_fiducial", "", true, NULL );
23 Option ModelFiducial::showFov( "Fiducial FOV", "show_fiducial_fov", "", false, NULL );
24 
68  Model* parent,
69  const std::string& type ) :
70  Model( world, parent, type ),
71  fiducials(),
72  max_range_anon( 8.0 ),
73  max_range_id( 5.0 ),
74  min_range( 0.0 ),
75  fov( M_PI ),
76  heading( 0 ),
77  key( 0 ),
78  ignore_zloc(false)
79 {
80  //PRINT_DEBUG2( "Constructing ModelFiducial %d (%s)\n",
81  // id, typestr );
82 
83  // assert that Update() is reentrant for this derived model
84  thread_safe = true;
85 
86  // sensible fiducial defaults
87  // interval = 200; // common for a SICK LMS200
88 
89  this->ClearBlocks();
90 
91  Geom geom;
92  geom.Zero();
93  SetGeom( geom );
94 
97 }
98 
100 {
101 }
102 
103 static bool fiducial_raytrace_match( Model* candidate,
104  Model* finder,
105  const void* dummy )
106 {
107  (void)dummy; // avoid warning about unused var
108  return( ! finder->IsRelated( candidate ) );
109 }
110 
111 
113 {
114  //PRINT_DEBUG2( "Fiducial %s is testing model %s", token, him->Token() );
115 
116  // only non-zero IDs should ever be checked
117  assert( him->vis.fiducial_return != 0 );
118 
119  // check to see if this neighbor has the right fiducial key
120  // if keys are used extensively, then perhaps a vector per key would be faster
121  if( vis.fiducial_key != him->vis.fiducial_key )
122  {
123  //PRINT_DEBUG1( " but model %s doesn't match the fiducial key", him->Token());
124  return;
125  }
126 
127  Pose mypose = this->GetGlobalPose();
128 
129  // are we within range?
130  Pose hispose = him->GetGlobalPose();
131  double dx = hispose.x - mypose.x;
132  double dy = hispose.y - mypose.y;
133  double range = hypot( dy, dx );
134 
135  // printf( "range to target %.2f m (
136 
137  if( range >= max_range_anon )
138  {
139  //PRINT_DEBUG3( " but model %s is %.2f m away, outside my range of %.2f m",
140  // him->Token(),
141  // range,
142  // max_range_anon );
143  return;
144  }
145 
146  // is he in my field of view?
147  double bearing = atan2( dy, dx );
148  double dtheta = normalize(bearing - mypose.a);
149 
150  if( fabs(dtheta) > fov/2.0 )
151  {
152  //PRINT_DEBUG1( " but model %s is outside my FOV", him->Token());
153  return;
154  }
155 
156  if( IsRelated( him ) )
157  return;
158 
159  //PRINT_DEBUG1( " %s is a candidate. doing ray trace", him->Token());
160 
161 
162  //printf( "bearing %.2f\n", RTOD(bearing) );
163 
164  //If we've gotten to this point, a few things are true:
165  // 1. The fiducial is in the field of view of the finder.
166  // 2. The fiducial is in range of the finder.
167  //At this point the purpose of the ray trace is to start at the finder and see if there is anything
168  //in between the finder and the fiducial. If we simply trace out to the distance we know the finder
169  //is at, then the resulting ray.mod can be one of three things:
170  // 1. A pointer to the model we're tracing to. In this case the model is at the right Zloc to be
171  // returned by the ray tracer.
172  // 2. A pointer to another model that blocked the ray.
173  // 3. NULL. If it's null, then it means that the ray traced to where the fiducial should be but
174  // it's zloc was such that the ray didn't hit it. However, we DO know its there, so we can
175  // return this as a hit.
176 
177  //printf( "range %.2f\n", range );
178 
179  RaytraceResult ray( Raytrace( dtheta,
180  max_range_anon, // TODOscan only as far as the object
182  NULL,
183  true ) );
184 
185  // TODO
186  if( ignore_zloc && ray.mod == NULL ) // i.e. we didn't hit anything *else*
187  ray.mod = him; // so he was just at the wrong height
188 
189  //printf( "ray hit %s and was seeking LOS to %s\n",
190  // ray.mod ? ray.mod->Token() : "null",
191  // him->Token() );
192 
193  // if it was him, we can see him
194  if( ray.mod != him )
195  return;
196 
197  assert( range >= 0 );
198 
199  // passed all the tests! record the fiducial hit
200 
201  Geom hisgeom( him->GetGeom() );
202 
203  // record where we saw him and what he looked like
204  Fiducial fid;
205  fid.mod = him;
206  fid.range = range;
207  fid.bearing = dtheta;
208  fid.geom.x = hisgeom.size.x;
209  fid.geom.y = hisgeom.size.y;
210  fid.geom.z = hisgeom.size.z;
211  fid.geom.a = normalize( hispose.a - mypose.a);
212 
213  //fid.pose_rel = hispose - this->GetGlobalPose();
214 
215  // store the global pose of the fiducial (mainly for the GUI)
216  fid.pose = hispose;
217 
218  // if he's within ID range, get his fiducial.return value, else
219  // we see value 0
220  fid.id = range < max_range_id ? him->vis.fiducial_return : 0;
221 
222  //PRINT_DEBUG2( "adding %s's value %d to my list of fiducials",
223  // him->Token(), him->vis.fiducial_return );
224 
225  fiducials.push_back( fid );
226 }
227 
228 
230 // Update the beacon data
231 //
233 {
234  //PRINT_DEBUG( "fiducial update" );
235 
236  if( subs < 1 )
237  return;
238 
239  // reset the array of detected fiducials
240  fiducials.clear();
241 
242 #if( 1 )
243  // BEGIN EXPERIMENT
244 
245  // find two sets of fiducial-bearing models, within sensor range on
246  // the two different axes
247 
248  double rng = max_range_anon;
249  Pose gp = GetGlobalPose();
250  Model edge; // dummy model used to find bounds in the sets
251 
252  edge.pose = Pose( gp.x-rng, gp.y, 0, 0 ); // LEFT
253  std::set<Model*,World::ltx>::iterator xmin =
254  world->models_with_fiducials_byx.lower_bound( &edge ); // O(log(n))
255 
256  edge.pose = Pose( gp.x+rng, gp.y, 0, 0 ); // RIGHT
257  const std::set<Model*,World::ltx>::iterator xmax =
258  world->models_with_fiducials_byx.upper_bound( &edge );
259 
260  edge.pose = Pose( gp.x, gp.y-rng, 0, 0 ); // BOTTOM
261  std::set<Model*,World::lty>::iterator ymin =
262  world->models_with_fiducials_byy.lower_bound( &edge );
263 
264  edge.pose = Pose( gp.x, gp.y+rng, 0, 0 ); // TOP
265  const std::set<Model*,World::lty>::iterator ymax =
266  world->models_with_fiducials_byy.upper_bound( &edge );
267 
268  // put these models into sets keyed on model pointer, rather than position
269  std::set<Model*> horiz, vert;
270 
271  for( ; xmin != xmax; ++xmin)
272  horiz.insert( *xmin);
273 
274  for( ; ymin != ymax; ++ymin )
275  vert.insert( *ymin );
276 
277  // the intersection of the sets is all the fiducials close by
278  std::vector<Model*> nearby;
279  std::set_intersection( horiz.begin(), horiz.end(),
280  vert.begin(), vert.end(),
281  std::inserter( nearby, nearby.end() ) );
282 
283  // printf( "cand sz %lu\n", nearby.size() );
284 
285  // create sets sorted by x and y position
286  FOR_EACH( it, nearby )
287  AddModelIfVisible( *it );
288 #else
290  AddModelIfVisible( *it );
291 
292 #endif
293 
294  // find the range of fiducials within range in X
295 
296  Model::Update();
297 }
298 
300 {
301  PRINT_DEBUG( "fiducial load" );
302 
303  Model::Load();
304 
305  // load fiducial-specific properties
306  min_range = wf->ReadLength( wf_entity, "range_min", min_range );
308  max_range_id = wf->ReadLength( wf_entity, "range_max_id", max_range_id );
309  fov = wf->ReadAngle ( wf_entity, "fov", fov );
310  ignore_zloc = wf->ReadInt ( wf_entity, "ignore_zloc", ignore_zloc);
311 }
312 
313 
315 {
316  (void)cam; // avoid warning about unused var
317 
318  if( showFov )
319  {
320  PushColor( 1,0,1,0.2 ); // magenta, with a bit of alpha
321 
322  GLUquadric* quadric = gluNewQuadric();
323 
324  gluQuadricDrawStyle( quadric, GLU_SILHOUETTE );
325 
326  gluPartialDisk( quadric,
327  0,
329  20, // slices
330  1, // loops
331  rtod( M_PI/2.0 + fov/2.0), // start angle
332  rtod(-fov) ); // sweep angle
333 
334  gluDeleteQuadric( quadric );
335 
336  PopColor();
337  }
338 
339  if( showData )
340  {
341  PushColor( 1,0,1,0.4 ); // magenta, with a bit of alpha
342 
343  // draw fuzzy dotted lines
344  glLineWidth( 2.0 );
345  glLineStipple( 1, 0x00FF );
346 
347  // draw lines to the fiducials
348  FOR_EACH( it, fiducials )
349  {
350  Fiducial& fid = *it;
351 
352  double dx = fid.range * cos( fid.bearing);
353  double dy = fid.range * sin( fid.bearing);
354 
355  glEnable(GL_LINE_STIPPLE);
356  glBegin( GL_LINES );
357  glVertex2f( 0,0 );
358  glVertex2f( dx, dy );
359  glEnd();
360  glDisable(GL_LINE_STIPPLE);
361 
362  glPushMatrix();
363  Gl::coord_shift( dx,dy,0,fid.geom.a );
364 
365  glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
366  glRectf( -fid.geom.x/2.0, -fid.geom.y/2.0,
367  fid.geom.x/2.0, fid.geom.y/2.0 );
368 
369  // show the fiducial ID
370  char idstr[32];
371  snprintf(idstr, 31, "%d", fid.id );
372  Gl::draw_string( 0,0,0, idstr );
373 
374  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
375  glPopMatrix();
376  }
377 
378  PopColor();
379  glLineWidth( 1.0 );
380  }
381 }
382 
384 {
385  //PRINT_DEBUG( "fiducial shutdown" );
386  fiducials.clear();
387  Model::Shutdown();
388 }
radians_t fov
field of view
Definition: stage.hh:2727
meters_t range
range to the target
Definition: stage.hh:2694
virtual void PushColor(Color col)
Definition: stage.hh:2189
Model class
Definition: stage.hh:1742
meters_t max_range_anon
maximum detection range
Definition: stage.hh:2724
void coord_shift(double x, double y, double z, double a)
Definition: gl.cc:6
int subs
the number of subscriptions to this model
Definition: stage.hh:1959
World class
Definition: stage.hh:814
The Stage library uses its own namespace.
Definition: canvas.hh:8
static Option showData
Definition: stage.hh:2710
virtual void Load()
bool ignore_zloc
Are we ignoring the Z-loc of the fiducials we detect compared to the fiducial detector?
Definition: stage.hh:2730
meters_t x
Definition: stage.hh:228
virtual void DataVisualize(Camera *cam)
Geom geom
Definition: stage.hh:1883
std::set< Model *, ltx > models_with_fiducials_byx
Definition: stage.hh:864
Size size
extent
Definition: stage.hh:395
void AddModelIfVisible(Model *him)
std::vector< Fiducial > fiducials
Definition: stage.hh:2713
virtual void PopColor()
Definition: stage.hh:2191
RaytraceResult Raytrace(const Pose &pose, const meters_t range, const ray_test_func_t func, const void *arg, const bool ztest=true)
Definition: model.cc:475
static bool fiducial_raytrace_match(Model *candidate, Model *finder, const void *dummy)
bool thread_safe
Definition: stage.hh:1964
meters_t y
Definition: stage.hh:251
Worldfile * wf
Definition: stage.hh:2015
Model * mod
Pointer to the model (real fiducial detectors can&#39;t do this!)
Definition: stage.hh:2699
bool IsRelated(const Model *testmod) const
Definition: model.cc:570
double normalize(double a)
Definition: stage.hh:154
int wf_entity
Definition: stage.hh:2016
void RegisterOption(Option *opt)
Definition: model.cc:996
virtual void Update()
Pose GetGlobalPose() const
Definition: model.cc:1379
double rtod(double r)
Definition: stage.hh:148
radians_t bearing
bearing to the target
Definition: stage.hh:2695
meters_t max_range_id
maximum range at which the ID can be read
Definition: stage.hh:2725
double ReadLength(int entity, const char *name, double value)
Definition: worldfile.hh:107
static Option showFov
Definition: stage.hh:2711
void draw_string(float x, float y, float z, const char *string)
Definition: gl.cc:65
virtual void Update()
Definition: model.cc:735
virtual void Load()
Definition: model.cc:1422
class Stg::Model::Visibility vis
virtual ~ModelFiducial()
void Zero()
Definition: stage.hh:421
Pose pose
Definition: stage.hh:1916
Pose geom
size and relative angle of the target
Definition: stage.hh:2696
World * world
Definition: stage.hh:2017
std::set< Model *, lty > models_with_fiducials_byy
Definition: stage.hh:868
std::vector< Model * > models_with_fiducials
Definition: stage.hh:850
int ReadInt(int entity, const char *name, int value)
Definition: worldfile.cc:1398
void SetGeom(const Geom &src)
Definition: model.cc:1243
virtual void Shutdown()
Definition: model.cc:723
#define FOR_EACH(I, C)
Definition: stage.hh:616
ModelFiducial(World *world, Model *parent, const std::string &type)
radians_t a
rotation about the z axis.
Definition: stage.hh:252
#define PRINT_DEBUG(m)
Definition: stage.hh:666
meters_t min_range
minimum detection range
Definition: stage.hh:2726
double ReadAngle(int entity, const char *name, double value)
Definition: worldfile.hh:116
Model * mod
the model struck by this beam
Definition: stage.hh:746
int id
the fiducial identifier of the target (i.e. its fiducial_return value), or -1 if none can be detected...
Definition: stage.hh:2700
meters_t x
Definition: stage.hh:251
void ClearBlocks()
Definition: model.cc:421
Geom GetGeom() const
Definition: stage.hh:2378


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 Mon Jun 10 2019 15:06:09