Revision: 7885
http://playerstage.svn.sourceforge.net/playerstage/?rev=7885&view=rev
Author: rtv
Date: 2009-06-23 18:13:51 +0000 (Tue, 23 Jun 2009)
Log Message:
-----------
moved all model-specific types into their class scope - may break Toby's
end-user code
Modified Paths:
--------------
code/stage/trunk/examples/ctrl/fasr.cc
code/stage/trunk/libstage/model_actuator.cc
code/stage/trunk/libstage/model_gripper.cc
code/stage/trunk/libstage/model_laser.cc
code/stage/trunk/libstage/model_position.cc
code/stage/trunk/libstage/model_ranger.cc
code/stage/trunk/libstage/stage.hh
code/stage/trunk/libstage/waypoint.cc
code/stage/trunk/libstageplugin/p_blobfinder.cc
code/stage/trunk/todo.txt
Modified: code/stage/trunk/examples/ctrl/fasr.cc
===================================================================
--- code/stage/trunk/examples/ctrl/fasr.cc 2009-06-23 15:14:12 UTC (rev
7884)
+++ code/stage/trunk/examples/ctrl/fasr.cc 2009-06-23 18:13:51 UTC (rev
7885)
@@ -453,7 +453,7 @@
static int BlobFinderUpdate( ModelBlobfinder* blobmod, Robot* robot )
{
unsigned int blob_count = 0;
- ModelBlobfinder::Blob* blobs = blobmod->GetBlobs( &blob_count );
+ const ModelBlobfinder::Blob* blobs = blobmod->GetBlobs( &blob_count );
if( blobs && (blob_count>0) )
{
Modified: code/stage/trunk/libstage/model_actuator.cc
===================================================================
--- code/stage/trunk/libstage/model_actuator.cc 2009-06-23 15:14:12 UTC (rev
7884)
+++ code/stage/trunk/libstage/model_actuator.cc 2009-06-23 18:13:51 UTC (rev
7885)
@@ -55,32 +55,28 @@
- axis
if a linear actuator the axis that the actuator will move along
*/
+
+static const double STG_ACTUATOR_WATTS_KGMS = 5.0; // cost per kg per meter
per second
+static const double STG_ACTUATOR_WATTS = 2.0; // base cost of position device
-const double STG_ACTUATOR_WATTS_KGMS = 5.0; // cost per kg per meter per second
-const double STG_ACTUATOR_WATTS = 2.0; // base cost of position device
-
-const stg_actuator_control_mode_t ACTUATOR_CONTROL_DEFAULT =
STG_ACTUATOR_CONTROL_VELOCITY;
-const stg_actuator_type_t ACTUATOR_TYPE_DEFAULT = STG_ACTUATOR_TYPE_LINEAR;
-
-
ModelActuator::ModelActuator( World* world,
-
Model* parent )
+
Model* parent )
: Model( world, parent, MODEL_TYPE_ACTUATOR ),
- goal(0), pos(0), max_speed(1), min_position(0), max_position(1),
- control_mode(ACTUATOR_CONTROL_DEFAULT),
- actuator_type(ACTUATOR_TYPE_DEFAULT)
+ goal(0),
+ pos(0),
+ max_speed(1),
+ min_position(0),
+ max_position(1),
+ control_mode( STG_ACTUATOR_CONTROL_VELOCITY ),
+ actuator_type( STG_ACTUATOR_TYPE_LINEAR ),
+ axis(0,0,0)
{
- // no power consumed until we're subscribed
- this->SetWatts( 0 );
-
- // sensible position defaults
- Velocity vel;
- memset( &vel, 0, sizeof(vel));
- this->SetVelocity( vel );
- this->SetBlobReturn( TRUE );
-
- memset(&axis,0,sizeof(axis));
-
+ // no power consumed until we're subscribed
+ this->SetWatts( 0 );
+
+ // sensible position defaults
+ this->SetVelocity( Velocity(0,0,0,0) );
+ this->SetBlobReturn( TRUE );
}
@@ -165,11 +161,11 @@
// update current position
Pose CurrentPose = GetPose();
// just need to get magnitude difference;
- Pose PoseDiff;
- PoseDiff.x = CurrentPose.x - InitialPose.x;
- PoseDiff.y = CurrentPose.y - InitialPose.y;
- PoseDiff.z = CurrentPose.z - InitialPose.z;
- PoseDiff.a = CurrentPose.a - InitialPose.a;
+ Pose PoseDiff( CurrentPose.x - InitialPose.x,
+ CurrentPose.y - InitialPose.y,
+ CurrentPose.z - InitialPose.z,
+ CurrentPose.a - InitialPose.a );
+
switch (actuator_type)
{
case STG_ACTUATOR_TYPE_LINEAR:
@@ -277,8 +273,9 @@
// safety features!
goal = 0;
- bzero( &velocity, sizeof(velocity) );
+ velocity.Zero();
+
this->SetWatts( 0 );
Model::Shutdown();
Modified: code/stage/trunk/libstage/model_gripper.cc
===================================================================
--- code/stage/trunk/libstage/model_gripper.cc 2009-06-23 15:14:12 UTC (rev
7884)
+++ code/stage/trunk/libstage/model_gripper.cc 2009-06-23 18:13:51 UTC (rev
7885)
@@ -95,16 +95,9 @@
// Update() is not reentrant
thread_safe = false;
- // default size
- Geom geom;
- geom.pose.x = 0.0;
- geom.pose.y = 0.0;
- geom.pose.a = 0.0;
- geom.size.x = 0.2;
- geom.size.y = 0.3;
- geom.size.z = 0.2;
- SetGeom( geom );
-
+ // set default size
+ SetGeom( Geom( Pose(0,0,0,0), Size( 0.2, 0.3, 0.2)));
+
PositionPaddles();
RegisterOption( &showData );
Modified: code/stage/trunk/libstage/model_laser.cc
===================================================================
--- code/stage/trunk/libstage/model_laser.cc 2009-06-23 15:14:12 UTC (rev
7884)
+++ code/stage/trunk/libstage/model_laser.cc 2009-06-23 18:13:51 UTC (rev
7885)
@@ -29,7 +29,6 @@
static const unsigned int DEFAULT_RESOLUTION = 1;
static const char* DEFAULT_COLOR = "blue";
-//TODO make instance attempt to register an option (as customvisualizations do)
Option ModelLaser::Vis::showArea( "Laser scans", "show_laser", "", true, NULL
);
Option ModelLaser::Vis::showStrikes( "Laser strikes", "show_laser_strikes",
"", false, NULL );
Option ModelLaser::Vis::showFov( "Laser FOV", "show_laser_fov", "", false,
NULL );
@@ -73,116 +72,6 @@
Only calculate the true range of every nth laser sample. The missing
samples are filled in with a linear interpolation. Generally it would be better
to use fewer samples, but some (poorly implemented!) programs expect a fixed
number of samples. Setting this number > 1 allows you to reduce the amount of
computation required for your fixed-size laser vector.
*/
-// create static vis objects
-
-ModelLaser::Vis::Vis( World* world )
- : Visualizer( "Laser", "laser_vis" )
-{
- world->RegisterOption( &showArea );
- world->RegisterOption( &showStrikes );
- world->RegisterOption( &showFov );
- world->RegisterOption( &showBeams );
-}
-
-void ModelLaser::Vis::Visualize( Model* mod, Camera* cam )
-{
- ModelLaser* laser( dynamic_cast<ModelLaser*>(mod) );
-
- const std::vector<Sample>& samples( laser->GetSamples() );
-
- size_t sample_count( samples.size() );
-
- glPushMatrix();
- glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
-
- glTranslatef( 0,0, laser->GetGeom().size.z/2.0 ); // shoot the laser beam
out at the right height
-
- // pack the laser hit points into a vertex array for fast rendering
- static std::vector<GLfloat> pts;
- pts.resize( 2 * (sample_count+1) );
-
- pts[0] = 0.0;
- pts[1] = 0.0;
-
- laser->PushColor( 1, 0, 0, 0.5 );
- glDepthMask( GL_FALSE );
- glPointSize( 2 );
-
- for( unsigned int s(0); s<sample_count; s++ )
- {
- double ray_angle = (s * (laser->fov / (sample_count-1))) -
laser->fov/2.0;
- pts[2*s+2] = (float)(samples[s].range * cos(ray_angle) );
- pts[2*s+3] = (float)(samples[s].range * sin(ray_angle) );
-
- // if the sample is unusually bright, draw a little blob
- if( samples[s].reflectance > 0 )
- {
- glBegin( GL_POINTS );
- glVertex2f( pts[2*s+2], pts[2*s+3] );
- glEnd();
- }
- }
-
- glVertexPointer( 2, GL_FLOAT, 0, &pts[0] );
-
- laser->PopColor();
-
- if( showArea )
- {
- // draw the filled polygon in transparent blue
- laser->PushColor( 0, 0, 1, 0.1 );
- glDrawArrays( GL_POLYGON, 0, sample_count+1 );
- laser->PopColor();
- //glDepthMask( GL_TRUE );
- }
-
- glDepthMask( GL_TRUE );
-
- if( showStrikes )
- {
- // draw the beam strike points
- laser->PushColor( 0, 0, 1, 0.8 );
- glDrawArrays( GL_POINTS, 0, sample_count+1 );
- laser->PopColor();
- }
-
- if( showFov )
- {
- for( unsigned int s(0); s<sample_count; s++ )
- {
- double ray_angle((s * (laser->fov / (sample_count-1)))
- laser->fov/2.0);
- pts[2*s+2] = (float)(laser->range_max * cos(ray_angle)
);
- pts[2*s+3] = (float)(laser->range_max * sin(ray_angle)
);
- }
-
- glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
- laser->PushColor( 0, 0, 1, 0.5 );
- glDrawArrays( GL_POLYGON, 0, sample_count+1 );
- laser->PopColor();
- // glPolygonMode( GL_FRONT_AND_BACK,
GL_LINE );
- }
-
- if( showBeams )
- {
- laser->PushColor( 0, 0, 1, 0.5 );
- glBegin( GL_LINES );
-
- for( unsigned int s(0); s<sample_count; s++ )
- {
-
- glVertex2f( 0,0 );
- double ray_angle((s * (laser->fov / (sample_count-1)))
- laser->fov/2.0);
- glVertex2f( samples[s].range * cos(ray_angle),
- samples[s].range *
sin(ray_angle) );
-
- }
- glEnd();
- laser->PopColor();
- }
-
- glPopMatrix();
-}
-
ModelLaser::ModelLaser( World* world,
Model* parent )
@@ -190,7 +79,6 @@
vis( world ),
sample_count( DEFAULT_SAMPLES ),
samples(),
- //ray( this, ),
range_max( DEFAULT_MAXRANGE ),
fov( DEFAULT_FOV ),
resolution( DEFAULT_RESOLUTION )
@@ -199,14 +87,10 @@
PRINT_DEBUG2( "Constructing ModelLaser %d (%s)\n",
id, typestr );
-
// Model data members
interval = DEFAULT_INTERVAL_MS * (int)thousand;
- Geom geom;
- memset( &geom, 0, sizeof(geom));
- geom.size = DEFAULT_SIZE;
- SetGeom( geom );
+ SetGeom( Geom( Pose(0,0,0,0), DEFAULT_SIZE) );
// assert that Update() is reentrant for this derived model
thread_safe = true;
@@ -388,3 +272,115 @@
{
return samples;
}
+
+
+// VIS -------------------------------------------------------------------
+
+ModelLaser::Vis::Vis( World* world )
+ : Visualizer( "Laser", "laser_vis" )
+{
+ world->RegisterOption( &showArea );
+ world->RegisterOption( &showStrikes );
+ world->RegisterOption( &showFov );
+ world->RegisterOption( &showBeams );
+}
+
+void ModelLaser::Vis::Visualize( Model* mod, Camera* cam )
+{
+ ModelLaser* laser( dynamic_cast<ModelLaser*>(mod) );
+
+ const std::vector<Sample>& samples( laser->GetSamples() );
+
+ size_t sample_count( samples.size() );
+
+ glPushMatrix();
+ glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+
+ glTranslatef( 0,0, laser->GetGeom().size.z/2.0 ); // shoot the laser beam
out at the right height
+
+ // pack the laser hit points into a vertex array for fast rendering
+ static std::vector<GLfloat> pts;
+ pts.resize( 2 * (sample_count+1) );
+
+ pts[0] = 0.0;
+ pts[1] = 0.0;
+
+ laser->PushColor( 1, 0, 0, 0.5 );
+ glDepthMask( GL_FALSE );
+ glPointSize( 2 );
+
+ for( unsigned int s(0); s<sample_count; s++ )
+ {
+ double ray_angle = (s * (laser->fov / (sample_count-1))) -
laser->fov/2.0;
+ pts[2*s+2] = (float)(samples[s].range * cos(ray_angle) );
+ pts[2*s+3] = (float)(samples[s].range * sin(ray_angle) );
+
+ // if the sample is unusually bright, draw a little blob
+ if( samples[s].reflectance > 0 )
+ {
+ glBegin( GL_POINTS );
+ glVertex2f( pts[2*s+2], pts[2*s+3] );
+ glEnd();
+ }
+ }
+
+ glVertexPointer( 2, GL_FLOAT, 0, &pts[0] );
+
+ laser->PopColor();
+
+ if( showArea )
+ {
+ // draw the filled polygon in transparent blue
+ laser->PushColor( 0, 0, 1, 0.1 );
+ glDrawArrays( GL_POLYGON, 0, sample_count+1 );
+ laser->PopColor();
+ //glDepthMask( GL_TRUE );
+ }
+
+ glDepthMask( GL_TRUE );
+
+ if( showStrikes )
+ {
+ // draw the beam strike points
+ laser->PushColor( 0, 0, 1, 0.8 );
+ glDrawArrays( GL_POINTS, 0, sample_count+1 );
+ laser->PopColor();
+ }
+
+ if( showFov )
+ {
+ for( unsigned int s(0); s<sample_count; s++ )
+ {
+ double ray_angle((s * (laser->fov / (sample_count-1)))
- laser->fov/2.0);
+ pts[2*s+2] = (float)(laser->range_max * cos(ray_angle)
);
+ pts[2*s+3] = (float)(laser->range_max * sin(ray_angle)
);
+ }
+
+ glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+ laser->PushColor( 0, 0, 1, 0.5 );
+ glDrawArrays( GL_POLYGON, 0, sample_count+1 );
+ laser->PopColor();
+ // glPolygonMode( GL_FRONT_AND_BACK,
GL_LINE );
+ }
+
+ if( showBeams )
+ {
+ laser->PushColor( 0, 0, 1, 0.5 );
+ glBegin( GL_LINES );
+
+ for( unsigned int s(0); s<sample_count; s++ )
+ {
+
+ glVertex2f( 0,0 );
+ double ray_angle((s * (laser->fov / (sample_count-1)))
- laser->fov/2.0);
+ glVertex2f( samples[s].range * cos(ray_angle),
+ samples[s].range *
sin(ray_angle) );
+
+ }
+ glEnd();
+ laser->PopColor();
+ }
+
+ glPopMatrix();
+}
+
Modified: code/stage/trunk/libstage/model_position.cc
===================================================================
--- code/stage/trunk/libstage/model_position.cc 2009-06-23 15:14:12 UTC (rev
7884)
+++ code/stage/trunk/libstage/model_position.cc 2009-06-23 18:13:51 UTC (rev
7885)
@@ -68,29 +68,34 @@
-const double STG_POSITION_WATTS_KGMS = 10.0; // current per kg per meter per
second
-const double STG_POSITION_WATTS = 1.0; // base cost of position device
+static const double WATTS_KGMS = 10.0; // current per kg per meter per second
+static const double WATTS = 1.0; // base cost of position device
// simple odometry error model parameters. the error is selected at
// random in the interval -MAX/2 to +MAX/2 at startup
-const double STG_POSITION_INTEGRATION_ERROR_MAX_X = 0.03;
-const double STG_POSITION_INTEGRATION_ERROR_MAX_Y = 0.03;
-const double STG_POSITION_INTEGRATION_ERROR_MAX_A = 0.05;
+static const double INTEGRATION_ERROR_MAX_X = 0.03;
+static const double INTEGRATION_ERROR_MAX_Y = 0.03;
+static const double INTEGRATION_ERROR_MAX_Z = 0.00; // note zero!
+static const double INTEGRATION_ERROR_MAX_A = 0.05;
-const stg_position_control_mode_t POSITION_CONTROL_DEFAULT =
STG_POSITION_CONTROL_VELOCITY;
-const stg_position_localization_mode_t POSITION_LOCALIZATION_DEFAULT =
STG_POSITION_LOCALIZATION_GPS;
-const stg_position_drive_mode_t POSITION_DRIVE_DEFAULT =
STG_POSITION_DRIVE_DIFFERENTIAL;
-
ModelPosition::ModelPosition( World* world,
- Model* parent )
+
Model* parent )
: Model( world, parent, MODEL_TYPE_POSITION ),
+ goal(0,0,0,0),
+ control_mode( STG_POSITION_CONTROL_VELOCITY ),
+ drive_mode( STG_POSITION_DRIVE_DIFFERENTIAL ),
+ localization_mode( STG_POSITION_LOCALIZATION_GPS ),
+ integration_error( drand48() * INTEGRATION_ERROR_MAX_X -
INTEGRATION_ERROR_MAX_X/2.0,
+ drand48() *
INTEGRATION_ERROR_MAX_Y - INTEGRATION_ERROR_MAX_Y/2.0,
+ drand48() *
INTEGRATION_ERROR_MAX_Z - INTEGRATION_ERROR_MAX_Z/2.0,
+ drand48() *
INTEGRATION_ERROR_MAX_A - INTEGRATION_ERROR_MAX_A/2.0 ),
waypoints( NULL ),
waypoint_count( 0 ),
wpvis(),
posevis()
{
PRINT_DEBUG2( "Constructing ModelPosition %d (%s)\n",
- id, typestr );
+ id, typestr );
// assert that Update() is reentrant for this derived model
thread_safe = true;
@@ -98,34 +103,10 @@
// no power consumed until we're subscribed
this->SetWatts( 0 );
- // zero vel
- Velocity v; // initially zero
- this->SetVelocity( v );
+ this->SetVelocity( Velocity(0,0,0,0) );
this->SetBlobReturn( TRUE );
- // configure the position-specific stuff
-
- // control
- memset( &goal, 0, sizeof(goal));
- drive_mode = POSITION_DRIVE_DEFAULT;
- control_mode = POSITION_CONTROL_DEFAULT;
-
- // localization
- localization_mode = POSITION_LOCALIZATION_DEFAULT;
-
- integration_error.x =
- drand48() * STG_POSITION_INTEGRATION_ERROR_MAX_X -
- STG_POSITION_INTEGRATION_ERROR_MAX_X/2.0;
-
- integration_error.y =
- drand48() * STG_POSITION_INTEGRATION_ERROR_MAX_Y -
- STG_POSITION_INTEGRATION_ERROR_MAX_Y/2.0;
-
- integration_error.a =
- drand48() * STG_POSITION_INTEGRATION_ERROR_MAX_A -
- STG_POSITION_INTEGRATION_ERROR_MAX_A/2.0;
-
AddVisualizer( &wpvis, true );
AddVisualizer( &posevis, false );
}
@@ -165,10 +146,10 @@
if( wf->PropertyExists( wf_entity, "odom" ) )
{
PRINT_WARN1( "the odom property is specified for model \"%s\","
- " but this property is no longer available."
- " Use localization_origin instead. See the position"
- " entry in the manual or src/model_position.c for details.",
- this->token );
+ " but this property is no
longer available."
+ " Use localization_origin
instead. See the position"
+ " entry in the manual or
src/model_position.c for details.",
+ this->token );
}
// set the starting pose as my initial odom position. This could be
@@ -176,8 +157,8 @@
// specified
est_origin = this->GetGlobalPose();
- if( wf->PropertyExists( wf_entity, "localization_origin" ) )
- {
+ if( wf->PropertyExists( wf_entity, "localization_origin" ) )
+ {
est_origin.x = wf->ReadTupleLength( wf_entity,
"localization_origin", 0, est_origin.x );
est_origin.y = wf->ReadTupleLength( wf_entity,
"localization_origin", 1, est_origin.y );
est_origin.z = wf->ReadTupleLength( wf_entity,
"localization_origin", 2, est_origin.z );
@@ -202,35 +183,35 @@
if( wf->PropertyExists( wf_entity, "odom_error" ) )
{
integration_error.x =
- wf->ReadTupleLength( wf_entity, "odom_error", 0, integration_error.x );
+ wf->ReadTupleLength( wf_entity, "odom_error", 0,
integration_error.x );
integration_error.y =
- wf->ReadTupleLength( wf_entity, "odom_error", 1, integration_error.y );
+ wf->ReadTupleLength( wf_entity, "odom_error", 1,
integration_error.y );
integration_error.z =
- wf->ReadTupleLength( wf_entity, "odom_error", 2, integration_error.z );
+ wf->ReadTupleLength( wf_entity, "odom_error", 2,
integration_error.z );
integration_error.a
- = wf->ReadTupleAngle( wf_entity, "odom_error", 3, integration_error.a );
+ = wf->ReadTupleAngle( wf_entity, "odom_error", 3,
integration_error.a );
}
// choose a localization model
if( wf->PropertyExists( wf_entity, "localization" ) )
{
const char* loc_str =
- wf->ReadString( wf_entity, "localization", NULL );
+ wf->ReadString( wf_entity, "localization", NULL );
if( loc_str )
- {
- if( strcmp( loc_str, "gps" ) == 0 )
- localization_mode = STG_POSITION_LOCALIZATION_GPS;
- else if( strcmp( loc_str, "odom" ) == 0 )
- localization_mode = STG_POSITION_LOCALIZATION_ODOM;
- else
- PRINT_ERR2( "unrecognized localization mode \"%s\" for model
\"%s\"."
- " Valid choices are \"gps\" and \"odom\".",
- loc_str, this->token );
- }
+ {
+ if( strcmp( loc_str, "gps" ) == 0 )
+ localization_mode =
STG_POSITION_LOCALIZATION_GPS;
+ else if( strcmp( loc_str, "odom" ) == 0 )
+ localization_mode =
STG_POSITION_LOCALIZATION_ODOM;
+ else
+ PRINT_ERR2( "unrecognized localization mode
\"%s\" for model \"%s\"."
+ " Valid choices
are \"gps\" and \"odom\".",
+ loc_str,
this->token );
+ }
else
- PRINT_ERR1( "no localization mode string specified for model \"%s\"",
- this->token );
+ PRINT_ERR1( "no localization mode string specified for model
\"%s\"",
+ this->token );
}
}
@@ -239,145 +220,144 @@
PRINT_DEBUG1( "[%lu] position update", this->world->sim_time );
// stop by default
- Velocity vel;
- memset( &vel, 0, sizeof(Velocity) );
-
+ Velocity vel(0,0,0,0);
+
if( this->subs ) // no driving if noone is subscribed
{
switch( control_mode )
- {
- case STG_POSITION_CONTROL_VELOCITY :
- {
- PRINT_DEBUG( "velocity control mode" );
- PRINT_DEBUG4( "model %s command(%.2f %.2f %.2f)",
- this->token,
- this->goal.x,
- this->goal.y,
- this->goal.a );
+ {
+ case STG_POSITION_CONTROL_VELOCITY :
+ {
+ PRINT_DEBUG( "velocity control mode" );
+ PRINT_DEBUG4( "model %s command(%.2f %.2f
%.2f)",
+ this->token,
+ this->goal.x,
+ this->goal.y,
+ this->goal.a
);
+
+ switch( drive_mode )
+ {
+ case STG_POSITION_DRIVE_DIFFERENTIAL:
+ // differential-steering model, like a
Pioneer
+ vel.x = goal.x;
+ vel.y = 0;
+ vel.a = goal.a;
+ break;
+
+ case STG_POSITION_DRIVE_OMNI:
+ // direct steering model, like an
omnidirectional robot
+ vel.x = goal.x;
+ vel.y = goal.y;
+ vel.a = goal.a;
+ break;
+
+ case STG_POSITION_DRIVE_CAR:
+ // car like steering model based on
speed and turning angle
+ vel.x = goal.x * cos(goal.a);
+ vel.y = 0;
+ vel.a = goal.x * sin(goal.a)/1.0; //
here 1.0 is the wheel base, this should be a config option
+ break;
+
+ default:
+ PRINT_ERR1( "unknown steering mode
%d", drive_mode );
+ }
+ } break;
+
+ case STG_POSITION_CONTROL_POSITION:
+ {
+ PRINT_DEBUG( "position control mode" );
+
+ double x_error = goal.x - est_pose.x;
+ double y_error = goal.y - est_pose.y;
+ double a_error = normalize( goal.a - est_pose.a
);
+
+ PRINT_DEBUG3( "errors: %.2f %.2f %.2f\n",
x_error, y_error, a_error );
+
+ // speed limits for controllers
+ // TODO - have these configurable
+ double max_speed_x = 0.4;
+ double max_speed_y = 0.4;
+ double max_speed_a = 1.0;
+
+ switch( drive_mode )
+ {
+ case STG_POSITION_DRIVE_OMNI:
+ {
+ // this is easy - we just
reduce the errors in each axis
+ // independently with a
proportional controller, speed
+ // limited
+ vel.x = MIN( x_error,
max_speed_x );
+ vel.y = MIN( y_error,
max_speed_y );
+ vel.a = MIN( a_error,
max_speed_a );
+ }
+ break;
- switch( drive_mode )
- {
- case STG_POSITION_DRIVE_DIFFERENTIAL:
- // differential-steering model, like a Pioneer
- vel.x = goal.x;
- vel.y = 0;
- vel.a = goal.a;
- break;
+ case STG_POSITION_DRIVE_DIFFERENTIAL:
+ {
+ // axes can not be controlled
independently. We have to
+ // turn towards the desired x,y
position, drive there,
+ // then turn to face the
desired angle. this is a
+ // simple controller that works
ok. Could easily be
+ // improved if anyone needs it
better. Who really does
+ // position control anyhoo?
- case STG_POSITION_DRIVE_OMNI:
- // direct steering model, like an omnidirectional robot
- vel.x = goal.x;
- vel.y = goal.y;
- vel.a = goal.a;
- break;
+ // start out with no velocity
+ Velocity calc;
+ double close_enough = 0.02; //
fudge factor
- case STG_POSITION_DRIVE_CAR:
- // car like steering model based on speed and turning angle
- vel.x = goal.x * cos(goal.a);
- vel.y = 0;
- vel.a = goal.x * sin(goal.a)/1.0; // here 1.0 is the wheel
base, this should be a config option
- break;
+ // if we're at the right spot
+ if( fabs(x_error) <
close_enough && fabs(y_error) < close_enough )
+ {
+ PRINT_DEBUG( "TURNING
ON THE SPOT" );
+ // turn on the spot to
minimize the error
+ calc.a = MIN( a_error,
max_speed_a );
+ calc.a = MAX( a_error,
-max_speed_a );
+ }
+ else
+ {
+ PRINT_DEBUG( "TURNING
TO FACE THE GOAL POINT" );
+ // turn to face the
goal point
+ double goal_angle =
atan2( y_error, x_error );
+ double goal_distance =
hypot( y_error, x_error );
- default:
- PRINT_ERR1( "unknown steering mode %d", drive_mode );
- }
- } break;
+ a_error = normalize(
goal_angle - est_pose.a );
+ calc.a = MIN( a_error,
max_speed_a );
+ calc.a = MAX( a_error,
-max_speed_a );
- case STG_POSITION_CONTROL_POSITION:
- {
- PRINT_DEBUG( "position control mode" );
+ PRINT_DEBUG2( "steer
errors: %.2f %.2f \n", a_error, goal_distance );
- double x_error = goal.x - est_pose.x;
- double y_error = goal.y - est_pose.y;
- double a_error = normalize( goal.a - est_pose.a );
+ // if we're pointing
about the right direction, move
+ // forward
+ if( fabs(a_error) <
M_PI/16 )
+ {
+ PRINT_DEBUG(
"DRIVING TOWARDS THE GOAL" );
+ calc.x = MIN(
goal_distance, max_speed_x );
+ }
+ }
- PRINT_DEBUG3( "errors: %.2f %.2f %.2f\n", x_error, y_error, a_error
);
+ // now set the underlying
velocities using the normal
+ // diff-steer model
+ vel.x = calc.x;
+ vel.y = 0;
+ vel.a = calc.a;
+ }
+ break;
- // speed limits for controllers
- // TODO - have these configurable
- double max_speed_x = 0.4;
- double max_speed_y = 0.4;
- double max_speed_a = 1.0;
+ default:
+ PRINT_ERR1( "unknown steering mode
%d", (int)drive_mode );
+ }
+ }
+ break;
- switch( drive_mode )
- {
- case STG_POSITION_DRIVE_OMNI:
- {
- // this is easy - we just reduce the errors in each axis
- // independently with a proportional controller, speed
- // limited
- vel.x = MIN( x_error, max_speed_x );
- vel.y = MIN( y_error, max_speed_y );
- vel.a = MIN( a_error, max_speed_a );
- }
- break;
-
- case STG_POSITION_DRIVE_DIFFERENTIAL:
- {
- // axes can not be controlled independently. We have to
- // turn towards the desired x,y position, drive there,
- // then turn to face the desired angle. this is a
- // simple controller that works ok. Could easily be
- // improved if anyone needs it better. Who really does
- // position control anyhoo?
-
- // start out with no velocity
- Velocity calc;
- double close_enough = 0.02; // fudge factor
-
- // if we're at the right spot
- if( fabs(x_error) < close_enough && fabs(y_error) <
close_enough )
- {
- PRINT_DEBUG( "TURNING ON THE SPOT" );
- // turn on the spot to minimize the error
- calc.a = MIN( a_error, max_speed_a );
- calc.a = MAX( a_error, -max_speed_a );
- }
- else
- {
- PRINT_DEBUG( "TURNING TO FACE THE GOAL POINT" );
- // turn to face the goal point
- double goal_angle = atan2( y_error, x_error );
- double goal_distance = hypot( y_error, x_error );
-
- a_error = normalize( goal_angle - est_pose.a );
- calc.a = MIN( a_error, max_speed_a );
- calc.a = MAX( a_error, -max_speed_a );
-
- PRINT_DEBUG2( "steer errors: %.2f %.2f \n", a_error,
goal_distance );
-
- // if we're pointing about the right direction, move
- // forward
- if( fabs(a_error) < M_PI/16 )
- {
- PRINT_DEBUG( "DRIVING TOWARDS THE GOAL" );
- calc.x = MIN( goal_distance, max_speed_x );
- }
- }
-
- // now set the underlying velocities using the normal
- // diff-steer model
- vel.x = calc.x;
- vel.y = 0;
- vel.a = calc.a;
- }
- break;
-
- default:
- PRINT_ERR1( "unknown steering mode %d", (int)drive_mode );
- }
- }
- break;
-
- default:
- PRINT_ERR1( "unrecognized position command mode %d", control_mode );
- }
+ default:
+ PRINT_ERR1( "unrecognized position command mode %d",
control_mode );
+ }
// simple model of power consumption
- watts = STG_POSITION_WATTS +
- fabs(vel.x) * STG_POSITION_WATTS_KGMS * mass +
- fabs(vel.y) * STG_POSITION_WATTS_KGMS * mass +
- fabs(vel.a) * STG_POSITION_WATTS_KGMS * mass;
+ watts = WATTS +
+ fabs(vel.x) * WATTS_KGMS * mass +
+ fabs(vel.y) * WATTS_KGMS * mass +
+ fabs(vel.a) * WATTS_KGMS * mass;
//PRINT_DEBUG4( "model %s velocity (%.2f %.2f %.2f)",
// this->token,
@@ -392,16 +372,16 @@
{
case STG_POSITION_LOCALIZATION_GPS:
{
- // compute our localization pose based on the origin and true pose
- Pose gpose = this->GetGlobalPose();
+ // compute our localization pose based on the origin and true
pose
+ Pose gpose = this->GetGlobalPose();
- est_pose.a = normalize( gpose.a - est_origin.a );
- double cosa = cos(est_origin.a);
- double sina = sin(est_origin.a);
- double dx = gpose.x - est_origin.x;
- double dy = gpose.y - est_origin.y;
- est_pose.x = dx * cosa + dy * sina;
- est_pose.y = dy * cosa - dx * sina;
+ est_pose.a = normalize( gpose.a - est_origin.a );
+ double cosa = cos(est_origin.a);
+ double sina = sin(est_origin.a);
+ double dx = gpose.x - est_origin.x;
+ double dy = gpose.y - est_origin.y;
+ est_pose.x = dx * cosa + dy * sina;
+ est_pose.y = dy * cosa - dx * sina;
}
break;
@@ -425,12 +405,12 @@
default:
PRINT_ERR2( "unknown localization mode %d for model %s\n",
- localization_mode, this->token );
+ localization_mode, this->token
);
break;
}
PRINT_DEBUG3( " READING POSITION: [ %.4f %.4f %.4f ]\n",
- est_pose.x, est_pose.y, est_pose.a );
+ est_pose.x, est_pose.y, est_pose.a );
Model::Update();
}
@@ -441,7 +421,7 @@
PRINT_DEBUG( "position startup" );
- this->SetWatts( STG_POSITION_WATTS );
+ this->SetWatts( WATTS );
}
void ModelPosition::Shutdown( void )
Modified: code/stage/trunk/libstage/model_ranger.cc
===================================================================
--- code/stage/trunk/libstage/model_ranger.cc 2009-06-23 15:14:12 UTC (rev
7884)
+++ code/stage/trunk/libstage/model_ranger.cc 2009-06-23 18:13:51 UTC (rev
7885)
@@ -83,12 +83,8 @@
using namespace Stg;
static const stg_watts_t RANGER_WATTSPERSENSOR = 0.2;
-static const stg_meters_t RANGER_SIZEX = 0.4;
-static const stg_meters_t RANGER_SIZEY = 0.4;
-static const stg_meters_t RANGER_SIZEZ = 0.05;
-static const stg_meters_t RANGER_TRANSDUCER_SIZEX = 0.01;
-static const stg_meters_t RANGER_TRANSDUCER_SIZEY = 0.04;
-static const stg_meters_t RANGER_TRANSDUCER_SIZEZ = 0.04;
+static const Size RANGER_SIZE( 0.4, 0.4, 0.05 );
+static const Size RANGER_TRANSDUCER_SIZE( 0.01, 0.04, 0.04 );
static const stg_meters_t RANGER_RANGEMAX = 5.0;
static const stg_meters_t RANGER_RANGEMIN = 0.0;
static const unsigned int RANGER_RAYCOUNT = 3;
@@ -119,11 +115,7 @@
// remove the polygon: ranger has no body
this->ClearBlocks();
- Geom geom;
- geom.size.x = RANGER_SIZEX;
- geom.size.y = RANGER_SIZEY;
- geom.size.z = RANGER_SIZEZ;
- this->SetGeom( geom );
+ this->SetGeom( Geom( Pose(), RANGER_SIZE ));
// spread the transducers around the ranger's body
double offset = MIN(geom.size.x, geom.size.y) / 2.0;
@@ -138,9 +130,7 @@
sensors[c].pose.y = offset * sin( sensors[c].pose.a );
sensors[c].pose.z = geom.size.z / 2.0; // half way up
- sensors[c].size.x = RANGER_TRANSDUCER_SIZEX;
- sensors[c].size.y = RANGER_TRANSDUCER_SIZEY;
- sensors[c].size.z = RANGER_TRANSDUCER_SIZEZ;
+ sensors[c].size = RANGER_TRANSDUCER_SIZE;
sensors[c].bounds_range.min = RANGER_RANGEMIN;
sensors[c].bounds_range.max = RANGER_RANGEMAX;;
@@ -194,8 +184,8 @@
sensors.resize( sensor_count );
Size common_size;
- common_size.x = wf->ReadTupleLength( wf_entity, "ssize", 0, RANGER_SIZEX
);
- common_size.y = wf->ReadTupleLength( wf_entity, "ssize", 1, RANGER_SIZEY
);
+ common_size.x = wf->ReadTupleLength( wf_entity, "ssize", 0,
RANGER_SIZE.x );
+ common_size.y = wf->ReadTupleLength( wf_entity, "ssize", 1,
RANGER_SIZE.y );
double common_min = wf->ReadTupleLength( wf_entity, "sview", 0,
RANGER_RANGEMIN );
double common_max = wf->ReadTupleLength( wf_entity, "sview", 1,
RANGER_RANGEMAX );
Modified: code/stage/trunk/libstage/stage.hh
===================================================================
--- code/stage/trunk/libstage/stage.hh 2009-06-23 15:14:12 UTC (rev 7884)
+++ code/stage/trunk/libstage/stage.hh 2009-06-23 18:13:51 UTC (rev 7885)
@@ -299,7 +299,10 @@
/* returns true iff all components of the velocity are zero. */
bool IsZero() const { return( !(x || y || z || a )); };
-
+
+ /** Set the pose to zero [0,0,0,0] */
+ void Zero(){ x=y=z=a=0.0; }
+
void Load( Worldfile* wf, int section, const char* keyword );
void Save( Worldfile* wf, int section, const char* keyword );
};
@@ -351,6 +354,12 @@
size.x,
size.y );
}
+
+ /** Default constructor. Members pose and size use their default
constructors. */
+ Geom() : pose(), size() {}
+
+ /** construct from a prior pose and size */
+ Geom( const Pose& p, const Size& s ) : pose(p), size(s) {}
};
/** Specify a point in space. Arrays of Waypoints can be attached to
@@ -359,6 +368,7 @@
{
public:
Waypoint( stg_meters_t x, stg_meters_t y, stg_meters_t z, stg_radians_t a,
stg_color_t color ) ;
+ Waypoint( const Pose& pose, stg_color_t color ) ;
Waypoint();
void Draw();
@@ -419,7 +429,9 @@
{
public:
stg_meters_t x,y,z;
- stg_point3_t( int x, int y ) : x(x), y(y){}
+ stg_point3_t( stg_meters_t x, stg_meters_t y, stg_meters_t z )
+ : x(x), y(y), z(z) {}
+ //stg_point3_t( int x, int y ) : x(x), y(y), z(0.0) {}
stg_point3_t() : x(0.0), y(0.0), z(0.0) {}
};
@@ -1734,7 +1746,6 @@
private:
/** the number of models instatiated - used to assign unique IDs */
static uint32_t count;
- //static GHashTable* modelsbyid;
static std::map<stg_id_t,Model*> modelsbyid;
std::vector<Option*> drawOptions;
const std::vector<Option*>& getOptions() const { return drawOptions; }
@@ -2010,29 +2021,22 @@
/** static wrapper for DrawBlocks() */
- static void DrawBlocks( gpointer dummykey,
- Model*
mod,
- void*
arg );
+// static void DrawBlocks( gpointer dummykey,
+// Model*
mod,
+// void*
arg );
virtual void DrawPicker();
- virtual void DataVisualize( Camera* cam );
-
+ virtual void DataVisualize( Camera* cam );
virtual void DrawSelected(void);
void DrawTrailFootprint();
void DrawTrailBlocks();
void DrawTrailArrows();
void DrawGrid();
-
-
- void DrawBlinkenlights();
-
+ void DrawBlinkenlights();
void DataVisualizeTree( Camera* cam );
-
void DrawFlagList();
-
void DrawPose( Pose pose );
-
void LoadDataBaseEntries( Worldfile* wf, int entity );
public:
@@ -2043,7 +2047,8 @@
virtual void PushColor( double r, double g, double b, double a )
{ world->PushColor( r,g,b,a ); }
- virtual void PopColor(){ world->PopColor(); }
+ virtual void PopColor()
+ { world->PopColor(); }
PowerPack* FindPowerPack() const;
@@ -2053,11 +2058,12 @@
void PlaceInFreeSpace( stg_meters_t xmin, stg_meters_t xmax,
stg_meters_t ymin, stg_meters_t ymax );
- std::string PoseString(){ return pose.String(); }
-
+ /** Return a human-readable string describing the model's pose */
+ std::string PoseString()
+ { return pose.String(); }
+
/** Look up a model pointer by a unique model ID */
static Model* LookupId( uint32_t id )
- //{ return (Model*)g_hash_table_lookup( modelsbyid, (void*)id ); }
{ return modelsbyid[id]; }
/** Constructor */
@@ -2418,8 +2424,6 @@
{
private:
//static Option showArea;
-
-
public:
Vis( World* world );
virtual ~Vis( void ){}
@@ -2432,11 +2436,8 @@
// predicate for ray tracing
static bool BlockMatcher( Block* testblock, Model* finder );
+ //static Option showBlobData;
- static Option showBlobData;
-
- // virtual void DataVisualize( Camera* cam );
-
public:
stg_radians_t fov;
stg_radians_t pan;
@@ -2457,11 +2458,11 @@
virtual void Update();
virtual void Load();
- Blob* GetBlobs( unsigned int* count )
- {
- if( count ) *count = blobs.size();
- return &blobs[0];
- }
+ Blob* GetBlobs( unsigned int* count )
+ {
+ if( count ) *count = blobs.size();
+ return &blobs[0];
+ }
/** Start finding blobs with this color.*/
void AddColor( stg_color_t col );
@@ -2520,8 +2521,6 @@
unsigned int sample_count;
std::vector<Sample> samples;
- //std::vector<Ray> rays;
- //Ray ray;
stg_meters_t range_max;
stg_radians_t fov;
@@ -2545,17 +2544,17 @@
virtual void Load();
virtual void Print( char* prefix );
- /** returns an array of samples */
+ /** returns an array of range & reflectance samples */
Sample* GetSamples( uint32_t* count );
- /** returns a const reference to a vector of samples */
- const std::vector<Sample>& GetSamples();
-
- /** Get the user-tweakable configuration of the laser */
- Config GetConfig( );
-
- /** Set the user-tweakable configuration of the laser */
- void SetConfig( Config& cfg );
+ /** returns a const reference to a vector of range and reflectance
samples */
+ const std::vector<Sample>& GetSamples();
+
+ /** Get the user-tweakable configuration of the laser */
+ Config GetConfig( );
+
+ /** Set the user-tweakable configuration of the laser */
+ void SetConfig( Config& cfg );
};
@@ -2903,36 +2902,36 @@
// POSITION MODEL --------------------------------------------------------
- /** Define a position control method */
- typedef enum
- { STG_POSITION_CONTROL_VELOCITY,
- STG_POSITION_CONTROL_POSITION
- } stg_position_control_mode_t;
-
- /** Define a localization method */
- typedef enum
- { STG_POSITION_LOCALIZATION_GPS,
- STG_POSITION_LOCALIZATION_ODOM
- } stg_position_localization_mode_t;
-
- /** Define a driving method */
- typedef enum
- { STG_POSITION_DRIVE_DIFFERENTIAL,
- STG_POSITION_DRIVE_OMNI,
- STG_POSITION_DRIVE_CAR
- } stg_position_drive_mode_t;
-
-
/// %ModelPosition class
class ModelPosition : public Model
{
friend class Canvas;
+ public:
+ /** Define a position control method */
+ typedef enum
+ { STG_POSITION_CONTROL_VELOCITY,
+ STG_POSITION_CONTROL_POSITION
+ } ControlMode;
+
+ /** Define a localization method */
+ typedef enum
+ { STG_POSITION_LOCALIZATION_GPS,
+ STG_POSITION_LOCALIZATION_ODOM
+ } LocalizationMode;
+
+ /** Define a driving method */
+ typedef enum
+ { STG_POSITION_DRIVE_DIFFERENTIAL,
+ STG_POSITION_DRIVE_OMNI,
+ STG_POSITION_DRIVE_CAR
+ } DriveMode;
+
private:
Pose goal;///< the current velocity or pose to reach, depending on the
value of control_mode
- stg_position_control_mode_t control_mode;
- stg_position_drive_mode_t drive_mode;
- stg_position_localization_mode_t localization_mode; ///< global or
local mode
+ ControlMode control_mode;
+ DriveMode drive_mode;
+ LocalizationMode localization_mode; ///< global or local mode
Velocity integration_error; ///< errors to apply in simple odometry
model
Waypoint* waypoints;
@@ -2977,7 +2976,7 @@
/** Set the current pose estimate.*/
void SetOdom( Pose odom );
- /** Sets the control_mode to STG_POSITION_CONTROL_VELOCITY and sets
+ /** Sets the control_mode to CONTROL_VELOCITY and sets
the goal velocity. */
void SetSpeed( double x, double y, double a );
void SetXSpeed( double x );
@@ -2988,7 +2987,7 @@
/** Set velocity along all axes to to zero. */
void Stop();
- /** Sets the control mode to STG_POSITION_CONTROL_POSITION and sets
+ /** Sets the control mode to CONTROL_POSITION and sets
the goal pose */
void GoTo( double x, double y, double a );
void GoTo( Pose pose );
@@ -3002,63 +3001,63 @@
// ACTUATOR MODEL --------------------------------------------------------
-/** Define a actuator control method */
-typedef enum
-{ STG_ACTUATOR_CONTROL_VELOCITY,
- STG_ACTUATOR_CONTROL_POSITION
-} stg_actuator_control_mode_t;
-
-/** Define an actuator type */
-typedef enum
-{ STG_ACTUATOR_TYPE_LINEAR,
- STG_ACTUATOR_TYPE_ROTATIONAL
-} stg_actuator_type_t;
-
-
/// %ModelActuator class
class ModelActuator : public Model
{
- private:
- double goal; //< the current velocity or pose to reach,
depending on the value of control_mode
- double pos;
- double max_speed;
- double min_position;
- double max_position;
- stg_actuator_control_mode_t control_mode;
- stg_actuator_type_t actuator_type;
- stg_point3_t axis;
-
- Pose InitialPose;
- public:
- static const char* typestr;
-
- // constructor
- ModelActuator( World* world,
- Model* parent );
- // destructor
- ~ModelActuator();
-
- virtual void Startup();
- virtual void Shutdown();
- virtual void Update();
- virtual void Load();
-
- /** Sets the control_mode to STG_ACTUATOR_CONTROL_VELOCITY and
sets
- the goal velocity. */
- void SetSpeed( double speed );
-
- double GetSpeed() const {return goal;}
-
- /** Sets the control mode to STG_ACTUATOR_CONTROL_POSITION and
sets
- the goal pose */
- void GoTo( double pose );
-
- double GetPosition() const {return pos;};
-
- double GetMaxPosition() const {return max_position;};
-
- double GetMinPosition() const {return min_position;};
-
+public:
+ /** Define a actuator control method */
+ typedef enum
+ { STG_ACTUATOR_CONTROL_VELOCITY,
+ STG_ACTUATOR_CONTROL_POSITION
+ } ControlMode;
+
+ /** Define an actuator type */
+ typedef enum
+ { STG_ACTUATOR_TYPE_LINEAR,
+ STG_ACTUATOR_TYPE_ROTATIONAL
+ } ActuatorType;
+
+private:
+ double goal; //< the current velocity or pose to reach, depending on the
value of control_mode
+ double pos;
+ double max_speed;
+ double min_position;
+ double max_position;
+ ControlMode control_mode;
+ ActuatorType actuator_type;
+ stg_point3_t axis;
+
+ Pose InitialPose;
+public:
+ static const char* typestr;
+
+ // constructor
+ ModelActuator( World* world,
+ Model* parent );
+ // destructor
+ ~ModelActuator();
+
+ virtual void Startup();
+ virtual void Shutdown();
+ virtual void Update();
+ virtual void Load();
+
+ /** Sets the control_mode to STG_ACTUATOR_CONTROL_VELOCITY and sets
+ the goal velocity. */
+ void SetSpeed( double speed );
+
+ double GetSpeed() const {return goal;}
+
+ /** Sets the control mode to STG_ACTUATOR_CONTROL_POSITION and sets
+ the goal pose */
+ void GoTo( double pose );
+
+ double GetPosition() const {return pos;};
+
+ double GetMaxPosition() const {return max_position;};
+
+ double GetMinPosition() const {return min_position;};
+
};
Modified: code/stage/trunk/libstage/waypoint.cc
===================================================================
--- code/stage/trunk/libstage/waypoint.cc 2009-06-23 15:14:12 UTC (rev
7884)
+++ code/stage/trunk/libstage/waypoint.cc 2009-06-23 18:13:51 UTC (rev
7885)
@@ -2,15 +2,17 @@
#include "stage.hh"
using namespace Stg;
+Waypoint::Waypoint( const Pose& pose, stg_color_t color )
+ : pose(pose), color(color)
+{
+}
+
Waypoint::Waypoint( stg_meters_t x, stg_meters_t y, stg_meters_t z,
stg_radians_t a, stg_color_t color )
- : color(color)
+ : pose(x,y,z,a), color(color)
{
- pose.x = x;
- pose.y = y;
- pose.z = z;
- pose.a = a;
}
+
Waypoint::Waypoint()
{
pose = Pose( 0,0,0,0 );
Modified: code/stage/trunk/libstageplugin/p_blobfinder.cc
===================================================================
--- code/stage/trunk/libstageplugin/p_blobfinder.cc 2009-06-23 15:14:12 UTC
(rev 7884)
+++ code/stage/trunk/libstageplugin/p_blobfinder.cc 2009-06-23 18:13:51 UTC
(rev 7885)
@@ -54,10 +54,10 @@
bzero( &bfd, sizeof(bfd) );
ModelBlobfinder* blobmod = (ModelBlobfinder*)this->mod;
-
+
uint32_t bcount = 0;
- ModelBlobfinder::Blob* blobs = blobmod->GetBlobs( &bcount );
-
+ const ModelBlobfinder::Blob* blobs = blobmod->GetBlobs( &bcount );
+
if ( bcount > 0 )
{
// and set the image width * height
Modified: code/stage/trunk/todo.txt
===================================================================
--- code/stage/trunk/todo.txt 2009-06-23 15:14:12 UTC (rev 7884)
+++ code/stage/trunk/todo.txt 2009-06-23 18:13:51 UTC (rev 7885)
@@ -9,6 +9,8 @@
** 3.1.0 RELEASE *
+ - blinkenlights vs lightindicator - resolve and fix interfaces
+ - ranger transducer geometry correct?
- feature freeze around July 1
- scan SF for patches
- fix world files
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit