stest.cc
Go to the documentation of this file.
00001 
00002 // File: stest.c
00003 // Desc: Stage library test program
00004 // Created: 2004.9.15
00005 // Author: Richard Vaughan <vaughan@sfu.ca>
00006 // CVS: $Id: stest.cc,v 1.1 2008-01-15 01:29:10 rtv Exp $
00007 // License: GPL
00009 
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013 
00014 #include <sstream>
00015 #include <iostream>
00016 #include <cmath>
00017 
00018 #include "stage.hh"
00019 
00020 class Robot
00021 {
00022 public:
00023     Stg::ModelPosition* position;
00024     Stg::ModelRanger* ranger;
00025 };
00026 
00027 class Logic
00028 {
00029 public:
00030     static int Callback(Stg::World* world, void* userarg)
00031     {
00032         Logic* lg = reinterpret_cast<Logic*>(userarg);
00033         
00034         lg->Tick(world);
00035         
00036         // never remove this call-back
00037         return 0;
00038     }
00039     
00040     Logic(unsigned int popsize)
00041     : 
00042     population_size(popsize),
00043     robots(new Robot[population_size])
00044     {
00045 
00046     }
00047     
00048     void connect(Stg::World* world)
00049     {
00050         // connect the first population_size robots to this controller
00051         for(unsigned int idx = 0; idx < population_size; idx++)
00052         {
00053             // the robots' models are named r0 .. r1999
00054             std::stringstream name;
00055             name << "r" << idx;
00056             
00057             // get the robot's model and subscribe to it
00058             Stg::ModelPosition* posmod = reinterpret_cast<Stg::ModelPosition*>(
00059                 world->GetModel(name.str())
00060                 );
00061             assert(posmod != 0);
00062             
00063             robots[idx].position = posmod;
00064             robots[idx].position->Subscribe();
00065             
00066             // get the robot's ranger model and subscribe to it
00067             Stg::ModelRanger* rngmod = reinterpret_cast<Stg::ModelRanger*>(
00068                 robots[idx].position->GetChild( "ranger:0" )
00069                 );
00070             assert(rngmod != 0);
00071             
00072             robots[idx].ranger = rngmod;
00073             robots[idx].ranger->Subscribe();
00074         }
00075         
00076         // register with the world
00077         world->AddUpdateCallback(Logic::Callback, reinterpret_cast<void*>(this));    
00078     }
00079     
00080     ~Logic()
00081     {
00082         delete[] robots;
00083     }
00084     
00085 
00086     void Tick(Stg::World*)
00087     {
00088         // the controllers parameters
00089         const double vspeed = 0.4; // meters per second
00090         const double wgain  = 1.0; // turn speed gain
00091         const double safe_dist = 0.1; // meters
00092         const double safe_angle = 0.3; // radians
00093     
00094         // each robot has a group of ir sensors
00095         // each sensor takes one sample
00096         // the forward sensor is the middle sensor
00097         for(unsigned int idx = 0; idx < population_size; idx++)
00098         {
00099             Stg::ModelRanger* rgr = robots[idx].ranger;
00100 
00101             // compute the vector sum of the sonar ranges             
00102             double dx=0, dy=0;
00103 
00104             // the range model has multiple sensors
00105             typedef std::vector<Stg::ModelRanger::Sensor>::const_iterator sensor_iterator;
00106             const std::vector<Stg::ModelRanger::Sensor> sensors = rgr->GetSensors();
00107             
00108             for(sensor_iterator sensor = sensors.begin(); sensor != sensors.end(); sensor++)
00109             {
00110                 // each sensor takes a single sample (as specified in the .world)
00111                 const double srange = (*sensor).ranges[0];
00112                 const double angle  = (*sensor).pose.a;
00113                 
00114                 dx += srange * std::cos(angle);
00115                 dy += srange * std::sin(angle);
00116             } 
00117             
00118             if(dx == 0)
00119                 continue;
00120             
00121             if(dy == 0)
00122                 continue;
00123             
00124             // calculate the angle towards the farthest obstacle
00125             const double resultant_angle = std::atan2( dy, dx );
00126 
00127             // check whether the front is clear
00128             const unsigned int forward_idx = sensors.size() / 2u - 1u;
00129             
00130             const double forwardm_range = sensors[forward_idx - 1].ranges[0];
00131             const double forward_range  = sensors[forward_idx + 0].ranges[0]; 
00132             const double forwardp_range = sensors[forward_idx + 1].ranges[0]; 
00133             
00134             bool front_clear = (
00135                     (forwardm_range > safe_dist / 5.0) &&
00136                     (forward_range > safe_dist) &&
00137                     (forwardp_range > safe_dist / 5.0) &&
00138                     (std::abs(resultant_angle) < safe_angle)
00139                 );
00140             
00141             // turn the sensor input into movement commands
00142 
00143             // move forwards if the front is clear
00144             const double forward_speed = front_clear ? vspeed : 0.0;
00145             // do not strafe
00146             const double side_speed = 0.0;         
00147             
00148             // turn towards the farthest obstacle
00149             const double turn_speed = wgain * resultant_angle;
00150             
00151             // finally, relay the commands to the robot
00152             robots[idx].position->SetSpeed( forward_speed, side_speed, turn_speed );
00153         }
00154     }
00155     
00156 protected:
00157     unsigned int population_size;   
00158     Robot* robots;
00159 };
00160 
00161 int main( int argc, char* argv[] )
00162 { 
00163     // check and handle the argumets
00164     if( argc < 3 )
00165     {
00166         puts( "Usage: stest <worldfile> <number of robots>" );
00167         exit(0);
00168     }
00169     
00170     const int popsize = atoi(argv[2] );
00171 
00172     // initialize libstage
00173     Stg::Init( &argc, &argv );
00174   
00175     // create the world
00176     //Stg::World world;
00177     Stg::WorldGui world(800, 700, "Stage Benchmark Program");
00178     world.Load( argv[1] );
00179   
00180     // create the logic and connect it to the world
00181     Logic logic(popsize);
00182     logic.connect(&world);
00183     
00184     // and then run the simulation
00185     world.Run();
00186     
00187     return 0;
00188 }


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