Update of /cvsroot/playerstage/code/stage/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2675

Added Files:
      Tag: opengl
        model_fiducial.cc model_ranger.cc 
Log Message:
feshening up

--- NEW FILE: model_ranger.cc ---
///////////////////////////////////////////////////////////////////////////
//
// File: model_ranger.cc
// Author: Richard Vaughan
// Date: 10 June 2004
//
// CVS info:
//  $Source: /cvsroot/playerstage/code/stage/src/Attic/model_ranger.cc,v $
//  $Author: rtv $
//  $Revision: 1.1.2.1 $
//
///////////////////////////////////////////////////////////////////////////

/**
@ingroup model
@defgroup model_ranger Ranger model 
The ranger model simulates an array of sonar or infra-red (IR) range sensors.

<h2>Worldfile properties</h2>

@par Summary and default values

@verbatim
ranger
(
  # ranger properties
  scount 16
  spose[0] [? ? ?]
  spose[1] [? ? ?]
  spose[2] [? ? ?]
  spose[3] [? ? ?]
  spose[4] [? ? ?]
  spose[5] [? ? ?]
  spose[6] [? ? ?]
  spose[7] [? ? ?]
  spose[8] [? ? ?]
  spose[9] [? ? ?]
  spose[10] [? ? ?]
  spose[11] [? ? ?]
  spose[12] [? ? ?]
  spose[13] [? ? ?]
  spose[14] [? ? ?]
  spose[15] [? ? ?]
   
  ssize [0.01 0.03]
  sview [0.0 5.0 5.0]

  # model properties
  watts 2.0
)
@endverbatim

@par Notes

The ranger model allows configuration of the pose, size and view parameters of 
each transducer seperately (using spose[index], ssize[index] and sview[index]). 
However, most users will set a common size and view (using ssize and sview), 
and just specify individual transducer poses.

@par Details
- scount int 
  - the number of range transducers
- spose[\<transducer index\>] [float float float]
  - [x y theta] 
  - pose of the transducer relative to its parent.
- ssize [float float]
  - [x y] 
  - size in meters. Has no effect on the data, but controls how the sensor 
looks in the Stage window.
- ssize[\<transducer index\>] [float float]
  - per-transducer version of the ssize property. Overrides the common setting.
- sview [float float float]
   - [range_min range_max fov] 
   - minimum range and maximum range in meters, field of view angle in degrees. 
Currently fov has no effect on the sensor model, other than being shown in the 
confgiuration graphic for the ranger device.
- sview[\<transducer index\>] [float float float]
  - per-transducer version of the sview property. Overrides the common setting.

*/

#define DEBUG

#include <math.h>
#include "model.hh"
#include "gui.h"
#include <GL/gl.h>

#define STG_RANGER_WATTS 2.0 // ranger power consumption

StgModelRanger::StgModelRanger( stg_world_t* world, 
                                StgModel* parent,
                                stg_id_t id,
                                CWorldFile* wf )
  : StgModel( world, parent, id, wf )
{
  PRINT_DEBUG2( "Constructing StgModelRanger %d (%s)\n", 
                id, wf->GetEntityType( id ) );
  

  
  
  // Set up sensible defaults
  
  stg_color_t col = stg_lookup_color( STG_RANGER_CONFIG_COLOR );
  this->SetColor( col );
  
  // remove the polygon: ranger has no body
  this->ClearBlocks();

  //stg_geom_t geom;
  //memset( &geom, 0, sizeof(geom)); // no size
  //this->SetGeom( &geom );
  
  sensor_count = 16;
  sensors= g_new0( stg_ranger_sensor_t, sensor_count );

  double offset = MIN(geom.size.x, geom.size.y) / 2.0;

  // create default ranger config
  int c;
  for( c=0; c<sensor_count; c++ )
    {
      sensors[c].pose.a = (2.0*M_PI)/sensor_count * c;
      sensors[c].pose.x = offset * cos( sensors[c].pose.a );
      sensors[c].pose.y = offset * sin( sensors[c].pose.a );
      
      sensors[c].size.x = 0.01; // a small device
      sensors[c].size.y = 0.04;
      
      sensors[c].bounds_range.min = 0;
      sensors[c].bounds_range.max = 5.0;
      sensors[c].fov = (2.0*M_PI)/(sensor_count+1);
      sensors[c].ray_count = 3;
    }
}

StgModelRanger::~StgModelRanger()
{
}

void StgModelRanger::Startup( void )
{
  StgModel::Startup();
  
  PRINT_DEBUG( "ranger startup" );
  
  this->SetWatts( STG_RANGER_WATTS );
}


void StgModelRanger::Shutdown( void )
{
  PRINT_DEBUG( "ranger shutdown" );

  this->SetWatts( 0 );
  //this->SetData( NULL, 0 ); // this will unrender data too.

  StgModel::Shutdown();
}

void StgModelRanger::Load( void )
{
  StgModel::Load();
  
  if( wf->PropertyExists(id, "scount" ) )
    {
      PRINT_DEBUG( "Loading ranger array" );
      puts( "Loading ranger array" );

      // Load the geometry of a ranger array
      sensor_count = wf->ReadInt( id, "scount", 0);
      assert( sensor_count > 0 );
      
      char key[256];
      sensors = g_renew( stg_ranger_sensor_t, sensors, sensor_count );
      
      stg_size_t common_size;
      common_size.x = wf->ReadTupleLength( id, "ssize", 0, sensors[0].size.x );
      common_size.y = wf->ReadTupleLength( id, "ssize", 1, sensors[0].size.y );
      
      double common_min = wf->ReadTupleLength( id, "sview", 0, 
sensors[0].bounds_range.min );
      double common_max = wf->ReadTupleLength( id, "sview", 1, 
sensors[0].bounds_range.max );
      double common_fov = wf->ReadTupleAngle( id, "sview", 2, sensors[0].fov );

      int common_ray_count = wf->ReadInt( id, "sraycount", sensors[0].ray_count 
);

      // set all transducers with the common settings
      int i;
      for(i = 0; i < sensor_count; i++)
        {
          sensors[i].size.x = common_size.x;
          sensors[i].size.y = common_size.y;
          sensors[i].bounds_range.min = common_min;
          sensors[i].bounds_range.max = common_max;
          sensors[i].fov = common_fov;
          sensors[i].ray_count = common_ray_count;        
        }

      // TODO - do this properly, without the hard-coded defaults
      // allow individual configuration of transducers
      for(i = 0; i < sensor_count; i++)
        {
          snprintf(key, sizeof(key), "spose[%d]", i);
          sensors[i].pose.x = wf->ReadTupleLength( id, key, 0, 0);
          sensors[i].pose.y = wf->ReadTupleLength( id, key, 1, 0);
          sensors[i].pose.a = wf->ReadTupleAngle( id, key, 2, 0);
          
/*        snprintf(key, sizeof(key), "ssize[%d]", i); */
/*        sensors[i].size.x = wf->ReadTuplelength(mod->id, key, 0, 0.01); */
/*        sensors[i].size.y = wf->ReadTuplelength(mod->id, key, 1, 0.05); */
          
/*        snprintf(key, sizeof(key), "sview[%d]", i); */
/*        sensors[i].bounds_range.min = */
/*          wf->ReadTuplelength(mod->id, key, 0, 0); */
/*        sensors[i].bounds_range.max =   // set up sensible defaults */

/*          wf->ReadTuplelength(mod->id, key, 1, 5.0); */
/*        sensors[i].fov */
/*          = DTOR(wf->ReadTupleangle(mod->id, key, 2, 5.0 )); */


/*        sensors[i].ray_count = common_ray_count; */

        }
      
      PRINT_DEBUG1( "loaded %d ranger configs", sensor_count );   
    }
}

int ranger_raytrace_match( StgModel* mod, StgModel* hitmod )
{
  // Ignore myself, my children, and my ancestors.
  return( hitmod->RangerReturn() );//&& !stg_model_is_related(mod,hitmod) );
}       

void StgModelRanger::Update( void )
{     
  StgModel::Update();
  
  if( this->subs < 1 )
    return;
  
  if( (sensors == NULL) || (sensor_count < 1 ))
    return;

  PRINT_DEBUG2( "[%d] updating ranger %s", (int)world->sim_time_ms, token );
  
  // raytrace new range data for all sensors
  for( unsigned int t=0; t<sensor_count; t++ )
    {
      // get the sensor's pose in global coords
      stg_pose_t pz;
      memcpy( &pz, &sensors[t].pose, sizeof(pz) ); 
      this->LocalToGlobal( &pz );
      
      double range = sensors[t].bounds_range.max;
      
      int r;
      for( r=0; r<sensors[t].ray_count; r++ )
        {         
          double angle_per_ray = sensors[t].fov / sensors[t].ray_count;
          double ray_angle = -sensors[t].fov/2.0 + angle_per_ray * r + 
angle_per_ray/2.0;
          
          stg_meters_t hitrange, hitx, hity;
          
          // if the ray hits anything, 'range' will be changed
          if( stg_first_model_on_ray( pz.x, pz.y, pz.z + 0.01, // TODO: UNHACK 
                                      pz.a + ray_angle, 
                                      sensors[t].bounds_range.max, 
                                      world->matrix, 
                                      PointToBearingRange, 
                                      ranger_raytrace_match,
                                      this,
                                      &hitrange, &hitx, &hity ) )
            {
              if( hitrange < range )
                range = hitrange;
            } 
        }
      // low-threshold the range
      if( range < sensors[t].bounds_range.min )
        range = sensors[t].bounds_range.min;    
      
      sensors[t].range = range;
      //sensors[t].error = TODO;
    }   
  
  // data graphics will be updated before being drawn onscreen again
  data_dirty = true;
}

/*
int ranger_noise_test( stg_ranger_sample_t* data, size_t count,  )
{
  int s;
  for( s=0; s<count; s++ )
    {
      // add 10mm random error
      ranges[s].range *= 0.1 * drand48();
    }
}
*/

void StgModelRanger::Print( char* prefix )
{
  StgModel::Print( prefix );
    
  printf( "\tRanges[ " );
  
  for( unsigned int i=0; i<sensor_count; i++ )
    printf( "%.2f ", sensors[i].range );
  puts( " ]" );
}


void StgModelRanger::DListData( void )
{
  // recreate the display list for this data
  glNewList( this->dl_data, GL_COMPILE );
  
  if( sensors && sensor_count ) 
    {
      // now get on with rendering the ranger data 
      glPolygonMode( GL_FRONT_AND_BACK, 
                     world->win->show_alpha ? GL_FILL : GL_LINES );
      push_color_rgba( 1, 0, 0, 0.1 ); // transparent pale red 
      glDepthMask( GL_FALSE ); 
      
      // draw the range  beams 
      for( unsigned int s=0; s<sensor_count; s++ ) 
        { 
          if( sensors[s].range > 0.0 ) 
            { 
              stg_ranger_sensor_t* rngr = &sensors[s]; 
              
              // sensor FOV 
              double sidelen = sensors[s].range; 
              double da = rngr->fov/2.0; 
              
              double x1= rngr->pose.x + sidelen*cos(rngr->pose.a - da ); 
              double y1= rngr->pose.y + sidelen*sin(rngr->pose.a - da ); 
              double x2= rngr->pose.x + sidelen*cos(rngr->pose.a + da ); 
              double y2= rngr->pose.y + sidelen*sin(rngr->pose.a + da ); 
              
              glBegin( GL_POLYGON);             
                glVertex3f( rngr->pose.x, rngr->pose.y, 0 ); 
                glVertex3f( x1, y1, 0 ); 
                glVertex3f( x2, y2, 0 ); 
              glEnd();                
            } 
        } 

      // draw the hitpoints
//       push_color_rgba( 1, 0, 0, 1.0 );
//       glPointSize( 3.0 );
//       glBegin(GL_POINTS);            
      
//       for( unsigned int s=0; s<sensor_count; s++ ) 
//      { 
//        if( sensors[s].range > 0.0 ) 
//          { 
//            stg_ranger_sensor_t* rngr = &sensors[s]; 
//            double sidelen = sensors[s].range; 
//            double x1= rngr->pose.x + sidelen*cos( rngr->pose.a ); 
//            double y1= rngr->pose.y + sidelen*sin( rngr->pose.a ); 
              
//            glVertex3f( x1, y1, 0 );          
//          } 
//      } 

//       glEnd();          
//       pop_color();
      
      
      // restore state 
      glDepthMask( GL_TRUE ); 
      pop_color(); 
    }
  
  glEndList();
}
   
   

--- NEW FILE: model_fiducial.cc ---
///////////////////////////////////////////////////////////////////////////
//
// File: model_fiducial.c
// Author: Richard Vaughan
// Date: 10 June 2004
//
// CVS info:
//  $Source: /cvsroot/playerstage/code/stage/src/Attic/model_fiducial.cc,v $
//  $Author: rtv $
//  $Revision: 1.2.2.1 $
//
///////////////////////////////////////////////////////////////////////////

//#define DEBUG 

#include <assert.h>
#include <math.h>
#include "stage_internal.h"
#include "gui.h"

#define STG_FIDUCIALS_MAX 64
#define STG_DEFAULT_FIDUCIAL_RANGEMIN 0
#define STG_DEFAULT_FIDUCIAL_RANGEMAXID 5
#define STG_DEFAULT_FIDUCIAL_RANGEMAXANON 8
#define STG_DEFAULT_FIDUCIAL_FOV DTOR(180)

const double STG_FIDUCIAL_WATTS = 10.0;

/** 
@ingroup model
@defgroup model_fiducial Fiducial detector model

The fiducial model simulates a fiducial-detecting device.

<h2>Worldfile properties</h2>

@par Summary and default values

@verbatim
fiducialfinder
(
  # fiducialfinder properties
  range_min 0.0
  range_max 8.0
  range_max_id 5.0
  fov 180.0

  # model properties
  size [0 0]
)
@endverbatim

@par Details
- range_min float
  - the minimum range reported by the sensor, in meters. The sensor will detect 
objects closer than this, but report their range as the minimum.
- range_max float
  - the maximum range at which the sensor can detect a fiducial, in meters. The 
sensor may not be able to uinquely identify the fiducial, depending on the 
value of range_max_id.
- range_max_id float
  - the maximum range at which the sensor can detect the ID of a fiducial, in 
meters.
- fov float
  - the angular field of view of the scanner, in degrees. 

*/

StgModelFiducial::StgModelFiducial( stg_world_t* world, 
                              StgModel* parent,
                              stg_id_t id,
                              CWorldFile* wf )
  : StgModel( world, parent, id, wf )
{
  PRINT_DEBUG2( "Constructing StgModelFiducial %d (%s)\n", 
                id, wf->GetEntityType( id ) );
  
  // sensible fiducial defaults 
  this->update_interval_ms = 200; // common for a SICK LMS200

  stg_geom_t geom; 
  memset( &geom, 0, sizeof(geom));
  geom.size.x = STG_DEFAULT_FIDUCIAL_SIZEX;
  geom.size.y = STG_DEFAULT_FIDUCIAL_SIZEY;
  geom.size.z = STG_DEFAULT_FIDUCIAL_SIZEZ;
  this->SetGeom( &geom );

  // set default color
  this->SetColor( stg_lookup_color(STG_FIDUCIAL_GEOM_COLOR));

  // set up a fiducial-specific config structure
  stg_fiducial_config_t lconf;
  memset(&lconf,0,sizeof(lconf));  
  lconf.range_min   = STG_DEFAULT_FIDUCIAL_MINRANGE;
  lconf.range_max   = STG_DEFAULT_FIDUCIAL_MAXRANGE;
  lconf.fov         = STG_DEFAULT_FIDUCIAL_FOV;
  lconf.samples     = STG_DEFAULT_FIDUCIAL_SAMPLES;  
  lconf.resolution = 1;
  this->SetCfg( &lconf, sizeof(lconf) );

  this->SetData( NULL, 0 );
}

  // no body
  stg_geom_t geom;
  memset( &geom, 0, sizeof(geom));
  stg_model_set_geom( mod, &geom );    
  stg_model_set_polygons( mod, NULL, 0 );

  // start with no data
  stg_model_set_data( mod, NULL, 0 );

  // default parameters
  stg_fiducial_config_t cfg; 
  cfg.min_range = STG_DEFAULT_FIDUCIAL_RANGEMIN;
  cfg.max_range_anon = STG_DEFAULT_FIDUCIAL_RANGEMAXANON;
  cfg.max_range_id = STG_DEFAULT_FIDUCIAL_RANGEMAXID;
  cfg.fov = STG_DEFAULT_FIDUCIAL_FOV;  
  stg_model_set_cfg( mod, &cfg, sizeof(cfg) );
  
  gui_fiducial_init( mod );
 
  return 0;
}

typedef struct 
{
  stg_model_t* mod;
  stg_pose_t pose;
  stg_fiducial_config_t cfg;
  GArray* fiducials;
} model_fiducial_buffer_t;


int fiducial_raytrace_match( stg_model_t* mod, stg_model_t* hitmod )
{
  // Ignore myself, my children, and my ancestors.
  return( !stg_model_is_related(mod,hitmod) );
}       


void model_fiducial_check_neighbor( gpointer key, 
                                    stg_model_t* him,  
                                    model_fiducial_buffer_t* mfb )
{
  PRINT_DEBUG2( "Model %s inspected model %s", 
                mfb->mod->token, him->token );
  
  // dont' compare a model with itself
  if( him == mfb->mod )
    {
      PRINT_DEBUG1( "  but model %s is itself", him->token);
      return;
    }

  // and don't consider models with invalid returns  
  if( him->fiducial_return == 0 )
    {
      PRINT_DEBUG1( "  but model %s has a zero fiducial ID", him->token);
      return;
    }

  // check to see if this neighbor has the right fiducial key
  if( him->fiducial_key != mfb->mod->fiducial_key )
    {
      PRINT_DEBUG1( "  but model %s doesn't match the fiducial key", 
him->token);
      return;
    }

  // are we within range?
  stg_pose_t hispose;
  stg_model_get_global_pose( him, &hispose );  
  double dx = hispose.x - mfb->pose.x;
  double dy = hispose.y - mfb->pose.y;  
  double range = hypot( dy, dx );
  if( range > mfb->cfg.max_range_anon )
    {
      PRINT_DEBUG1( "  but model %s is outside my range", him->token);
      return;
    }
  
  // is he in my field of view?
  double hisbearing = atan2( dy, dx );
  double dif = mfb->pose.a - hisbearing;

  if( fabs(NORMALIZE(dif)) > mfb->cfg.fov/2.0 )
    {
      PRINT_DEBUG1( "  but model %s is outside my FOV", him->token);
      return;
    }
   
  // now check if we have line-of-sight
  itl_t *itl = itl_create( mfb->pose.x, mfb->pose.y,
                           hispose.x, hispose.y, 
                           him->world->matrix, PointToPoint );
  
  stg_model_t* hitmod = 
    itl_first_matching( itl, fiducial_raytrace_match, mfb->mod );
  
  itl_destroy( itl );

  if( hitmod )
    PRINT_DEBUG2( "I saw %s with fid %d",
                  hitmod->token, hitmod->fiducial_return );
  
  // if it was him, we can see him
  if( hitmod == him )
    {
      stg_geom_t hisgeom;
      stg_model_get_geom(him,&hisgeom);

      // record where we saw him and what he looked like
      stg_fiducial_t fid;      
      fid.range = range;
      fid.bearing = NORMALIZE( hisbearing - mfb->pose.a);
      fid.geom.x = hisgeom.size.x;
      fid.geom.y = hisgeom.size.y;
      fid.geom.a = NORMALIZE( hispose.a - mfb->pose.a);

      // store the global pose of the fiducial (mainly for the GUI)
      memcpy( &fid.pose, &hispose, sizeof(fid.pose));
      
      // if he's within ID range, get his fiducial.return value, else
      // we see value 0
      fid.id = range < mfb->cfg.max_range_id ? hitmod->fiducial_return : 0;

      PRINT_DEBUG2( "adding %s's value %d to my list of fiducials",
            him->token, him->fiducial_return );

      g_array_append_val( mfb->fiducials, fid );
    }
}


///////////////////////////////////////////////////////////////////////////
// Update the beacon data
//
int fiducial_update( stg_model_t* mod, void* unused )
{
  PRINT_DEBUG( "fiducial update" );

  if( mod->subs < 1 )
    return 0;

  model_fiducial_buffer_t mfb;
  memset( &mfb, 0, sizeof(mfb) );
  
  mfb.mod = mod;

  stg_fiducial_config_t* cfg = (stg_fiducial_config_t*)mod->cfg;
  assert(cfg);

  memcpy( &mfb.cfg, cfg, sizeof(mfb.cfg));
  
  mfb.fiducials = g_array_new( FALSE, TRUE, sizeof(stg_fiducial_t) );
  stg_model_get_global_pose( mod, &mfb.pose );
  
  // for all the objects in the world
  g_hash_table_foreach( mod->world->models, 
                        (GHFunc)(model_fiducial_check_neighbor), &mfb );

  PRINT_DEBUG2( "model %s saw %d fiducials", mod->token, mfb.fiducials->len );
  
  stg_model_set_data( mod, mfb.fiducials->data, 
                      mfb.fiducials->len * sizeof(stg_fiducial_t) );
  
  g_array_free( mfb.fiducials, TRUE );

  return 0;
}

void StgModelFiducial::Load( void )
{  
  if( wf->PropertyExists( mod->id, "range_min" ) ||
      wf_property_exists( mod->id, "range_max" ) ||
      wf_property_exists( mod->id, "range_max_id") ||
      wf_property_exists( mod->id, "fov" ) )
    {
      stg_fiducial_config_t* now = (stg_fiducial_config_t*)mod->cfg; 
      
      stg_fiducial_config_t cfg;
      memset( &cfg, 0, sizeof(cfg) );
      
      cfg.fov = 
        wf_read_angle(mod->id, "fov", now->fov );
      
      cfg.min_range = 
        wf_read_length(mod->id, "range_min", now->min_range );
      
      cfg.max_range_anon = 
        wf_read_length(mod->id, "range_max", now->max_range_anon );
      
      cfg.max_range_id = 
        wf_read_length(mod->id, "range_max_id", now->max_range_id );

      stg_model_set_cfg( mod, &cfg, sizeof(cfg));
    }
  return 0;
}  


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to