00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00013
00065
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 );
00074
00075
00076 static const Color RANGER_CONFIG_COLOR( 0,0,0.5 );
00077
00078
00079
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
00097
00098
00099 thread_safe = true;
00100
00101 this->SetColor( RANGER_CONFIG_COLOR );
00102
00103
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
00134
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
00144
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
00153
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;
00166
00167
00168
00169
00170
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
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
00192
00193 double sample_incr( fov / std::max(sample_count-1, (unsigned int)1) );
00194
00195
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
00204 Ray ray( mod, rayorg, range.max, ranger_match, NULL, true );
00205
00206 World* world = mod->GetWorld();
00207
00208
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
00217 ray.origin.a += sample_incr;
00218
00219
00220
00221
00222
00223
00224
00225
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
00242
00243
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
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;
00268 rgr->PushColor( c );
00269 glPolygonMode( GL_FRONT, GL_FILL );
00270
00271 if( ranges.size() )
00272 {
00273 if( sample_count == 1 )
00274 {
00275
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
00302 glDrawArrays( GL_POLYGON, 0, sample_count );
00303 }
00304
00305 glDepthMask( GL_TRUE );
00306
00307 if( vis->showStrikes )
00308 {
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
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
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
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;
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