p_driver.cc
Go to the documentation of this file.
1 /*
2  * Stage plugin driver for Player
3  * Copyright (C) 2004-2005 Richard Vaughan
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  */
20 
21 /*
22  * Desc: A plugin driver for Player that gives access to Stage devices.
23  * Author: Richard Vaughan
24  * Date: 10 December 2004
25  * CVS: $Id$
26  */
27 
28 // DOCUMENTATION ------------------------------------------------------------
29 
141 // TODO - configs I should implement
142 // - PLAYER_BLOBFINDER_SET_COLOR_REQ
143 // - PLAYER_BLOBFINDER_SET_IMAGER_PARAMS_REQ
144 
145 // CODE ------------------------------------------------------------
146 
147 #include <unistd.h>
148 #include <string.h>
149 #include <math.h>
150 #include "config.h"
151 #include "p_driver.h"
152 using namespace Stg;
153 
154 const char* copyright_notice =
155 "\n * Part of the Player Project [http://playerstage.sourceforge.net]\n"
156 " * Copyright 2000-2009 Richard Vaughan, Brian Gerkey and contributors.\n"
157 " * Released under the GNU General Public License v2.\n";
158 
159 #define STG_DEFAULT_WORLDFILE "default.world"
160 #define DRIVER_ERROR(X) printf( "Stage driver error: %s\n", X )
161 
162 // globals from Player
163 extern PlayerTime* GlobalTime;
164 //extern int global_argc;
165 //extern char** global_argv;
166 extern bool player_quiet_startup;
167 extern bool player_quit;
168 
169 // init static vars
170 World* StgDriver::world = NULL;
171 bool StgDriver::usegui = true;
172 
173 //int update_request = 0;
174 
175 /* need the extern to avoid C++ name-mangling */
176 extern "C"
177 {
178  int player_driver_init(DriverTable* table);
179 }
180 
181 // A factory creation function, declared outside of the class so that it
182 // can be invoked without any object context (alternatively, you can
183 // declare it static in the class). In this function, we create and return
184 // (as a generic Driver*) a pointer to a new instance of this driver.
185 Driver* StgDriver_Init(ConfigFile* cf, int section)
186 {
187  // Create and return a new instance of this driver
188  return ((Driver*) (new StgDriver(cf, section)));
189 }
190 
191 // A driver registration function, again declared outside of the class so
192 // that it can be invoked without object context. In this function, we add
193 // the driver into the given driver table, indicating which interface the
194 // driver can support and how to create a driver instance.
195 void StgDriver_Register(DriverTable* table)
196 {
197  printf( "\n ** %s plugin v%s **", PROJECT, VERSION ); // XX TODO
198 
199  if( !player_quiet_startup )
200  {
201  puts( copyright_notice );
202  }
203 
204  table->AddDriver( (char*)"stage", StgDriver_Init);
205 }
206 
207 int player_driver_init(DriverTable* table)
208 {
209  puts(" Stage driver plugin init");
210  StgDriver_Register(table);
211  return(0);
212 }
213 
214 Interface::Interface( player_devaddr_t addr,
215  StgDriver* driver,
216  ConfigFile* cf,
217  int section )
218 {
219  //puts( "Interface constructor" );
220 
221  this->last_publish_time = 0;
222  this->addr = addr;
223  this->driver = driver;
224  this->publish_interval_msec = 100; // todo - do this properly
225 }
226 
227 InterfaceModel::InterfaceModel( player_devaddr_t addr,
228  StgDriver* driver,
229  ConfigFile* cf,
230  int section,
231  const std::string& type )
232  : Interface( addr, driver, cf, section ), mod( NULL ), subscribed( false )
233 {
234  char* model_name = (char*)cf->ReadString(section, "model", NULL );
235 
236  if( model_name == NULL )
237  {
238  PRINT_ERR1( "device \"%s\" uses the Stage driver but has "
239  "no \"model\" value defined. You must specify a "
240  "model name that matches one of the models in "
241  "the worldfile.",
242  model_name );
243  return; // error
244  }
245 
246  // find a model of the right type
247  this->mod = driver->LocateModel( model_name,
248  &addr,
249  type );
250 
251  // Use same update interval as the model
252  this->publish_interval_msec = this->mod->GetUpdateInterval()/1000;
253 
254  if( !this->mod )
255  {
256  printf( " ERROR! no model available for this device."
257  " Check your world and config files.\n" );
258 
259  exit(-1);
260  return;
261  }
262 
263  if( !player_quiet_startup )
264  printf( "\"%s\"\n", this->mod->Token() );
265 }
266 
268 {
269  if( !subscribed && this->mod )
270  {
271  this->mod->Subscribe();
272  subscribed = true;
273  }
274 }
275 
277 {
278  if( subscribed )
279  {
280  this->mod->Unsubscribe();
281  subscribed = false;
282  }
283 }
284 
285 
286 // Constructor. Retrieve options from the configuration file and do any
287 // pre-Setup() setup.
288 
289 // configure the underlying driver to queue incoming commands and use a very long queue.
290 
291 StgDriver::StgDriver(ConfigFile* cf, int section)
292  : Driver(cf, section, false, 4096 ),
293  devices()
294 {
295  // init the array of device ids
296 
297  int device_count = cf->GetTupleCount( section, "provides" );
298 
299  //if( !player_quiet_startup )
300  // {
301  //printf( " Stage driver creating %d %s\n",
302  // device_count,
303  // device_count == 1 ? "device" : "devices" );
304  // }
305 
306  for( int d=0; d<device_count; d++ )
307  {
308  player_devaddr_t player_addr;
309 
310  if (cf->ReadDeviceAddr( &player_addr, section,
311  "provides", 0, d, NULL) != 0)
312  {
313  this->SetError(-1);
314  return;
315  }
316 
317  if( !player_quiet_startup )
318  {
319  printf( " Stage plugin: %d.%s.%d is ",
320  player_addr.robot,
321  interf_to_str(player_addr.interf),
322  player_addr.index );
323  fflush(stdout);
324  }
325 
326 
327  Interface *ifsrc = NULL;
328 
329  switch( player_addr.interf )
330  {
331  case PLAYER_ACTARRAY_CODE:
332  ifsrc = new InterfaceActArray( player_addr, this, cf, section );
333  break;
334 
335  // case PLAYER_AIO_CODE:
336  // ifsrc = new InterfaceAio( player_addr, this, cf, section );
337  // break;
338 
339  case PLAYER_BLOBFINDER_CODE:
340  ifsrc = new InterfaceBlobfinder( player_addr, this, cf, section );
341  break;
342 
343  // case PLAYER_DIO_CODE:
344  // ifsrc = new InterfaceDio(player_addr, this, cf, section);
345  // break;
346 
347  case PLAYER_FIDUCIAL_CODE:
348  ifsrc = new InterfaceFiducial( player_addr, this, cf, section );
349  break;
350 
351  case PLAYER_RANGER_CODE:
352  ifsrc = new InterfaceRanger( player_addr, this, cf, section );
353  break;
354 
355  case PLAYER_POSITION2D_CODE:
356  ifsrc = new InterfacePosition( player_addr, this, cf, section );
357  break;
358 
359  case PLAYER_SIMULATION_CODE:
360  ifsrc = new InterfaceSimulation( player_addr, this, cf, section );
361  break;
362 
363  case PLAYER_SPEECH_CODE:
364  ifsrc = new InterfaceSpeech( player_addr, this, cf, section );
365  break;
366 
367  // case PLAYER_CAMERA_CODE:
368  // ifsrc = new InterfaceCamera( player_addr, this, cf, section );
369  // break;
370 
371  case PLAYER_GRAPHICS2D_CODE:
372  ifsrc = new InterfaceGraphics2d( player_addr, this, cf, section );
373  break;
374 
375  case PLAYER_GRAPHICS3D_CODE:
376  ifsrc = new InterfaceGraphics3d( player_addr, this, cf, section );
377  break;
378 
379 
380 
381 // case PLAYER_LOCALIZE_CODE:
382 // ifsrc = new InterfaceLocalize( player_addr, this, cf, section );
383 // break;
384 
385 // case PLAYER_MAP_CODE:
386 // ifsrc = new InterfaceMap( player_addr, this, cf, section );
387 // break;
388 
389  case PLAYER_GRIPPER_CODE:
390  ifsrc = new InterfaceGripper( player_addr, this, cf, section );
391  break;
392 
393 // case PLAYER_WIFI_CODE:
394 // ifsrc = new InterfaceWifi( player_addr, this, cf, section );
395 // break;
396 
397 // case PLAYER_POWER_CODE:
398 // ifsrc = new InterfacePower( player_addr, this, cf, section );
399 // break;
400 
401 // case PLAYER_PTZ_CODE:
402 // ifsrc = new InterfacePtz( player_addr, this, cf, section );
403 // break;
404 
405 // case PLAYER_BUMPER_CODE:
406 // ifsrc = new InterfaceBumper( player_addr, this, cf, section );
407 // break;
408 
409 
410  default:
411  PRINT_ERR1( "error: stage driver doesn't support interface type %d\n",
412  player_addr.interf );
413  this->SetError(-1);
414  return;
415  }
416 
417  if( ifsrc )
418  {
419  // attempt to add this interface and we're done
420  if( this->AddInterface( ifsrc->addr))
421  {
422  DRIVER_ERROR( "AddInterface() failed" );
423  this->SetError(-2);
424  return;
425  }
426 
427  // store the Interaface in our device list
428  //g_ptr_array_add( this->devices, ifsrc );
429  devices.push_back( ifsrc );
430  }
431  else
432  {
433  PRINT_ERR3( "No Stage source found for interface %d:%d:%d",
434  player_addr.robot,
435  player_addr.interf,
436  player_addr.index );
437 
438  this->SetError(-3);
439  return;
440  }
441  }
442  //puts( " Stage driver loaded successfully." );
443 }
444 
446  player_devaddr_t* addr,
447  const std::string& type )
448 {
449  //printf( "attempting to find a model under model \"%s\" of type [%d]\n",
450  // basename, type );
451 
452  Model* base_model = world->GetModel( basename );
453 
454  if( base_model == NULL )
455  {
456  PRINT_ERR1( " Error! can't find a Stage model named \"%s\"",
457  basename );
458  return NULL;
459  }
460 
461  if( type == "" ) // if we don't care what type the model is
462  return base_model;
463 
464  // printf( "found base model %s\n", base_model->Token() );
465 
466  // we find the first model in the tree that is the right
467  // type (i.e. has the right initialization function) and has not
468  // been used before
469  //return( model_match( base_model, addr, typestr, this->devices ) );
470  return( base_model->GetUnusedModelOfType( type ) );
471 }
472 
474 // Set up the device. Return 0 if things go well, and -1 otherwise.
476 {
477  puts("stage driver setup");
478  world->Start();
479  return(0);
480 }
481 
482 // find the device record with this Player id
483 // todo - faster lookup with a better data structure
484 Interface* StgDriver::LookupDevice( player_devaddr_t addr )
485 {
486  FOR_EACH( it, this->devices )
487  {
488  Interface* candidate = *it;
489 
490  if( candidate->addr.robot == addr.robot &&
491  candidate->addr.interf == addr.interf &&
492  candidate->addr.index == addr.index )
493  return candidate; // found
494  }
495 
496  return NULL; // not found
497 }
498 
499 
500 // subscribe to a device
501 int StgDriver::Subscribe(QueuePointer &queue,player_devaddr_t addr)
502 {
503  if( addr.interf == PLAYER_SIMULATION_CODE )
504  return 0; // ok
505 
506  Interface* device = this->LookupDevice( addr );
507 
508  if( device )
509  {
510  device->Subscribe();
511  device->Subscribe(queue);
512  return Driver::Subscribe(addr);
513  }
514 
515  puts( "failed to find a device" );
516  return 1; // error
517 }
518 
519 
520 // unsubscribe to a device
521 int StgDriver::Unsubscribe(QueuePointer &queue,player_devaddr_t addr)
522 {
523  if( addr.interf == PLAYER_SIMULATION_CODE )
524  return 0; // ok
525 
526  Interface* device = this->LookupDevice( addr );
527 
528  if( device )
529  {
530  device->Unsubscribe();
531  device->Unsubscribe(queue);
532  return Driver::Unsubscribe(addr);
533  }
534  else
535  return 1; // error
536 }
537 
539 {
540  delete world;
541  puts( "Stage driver destroyed" );
542 }
543 
544 
546 // Shutdown the device
548 {
549  //puts("Shutting stage driver down");
550 
551  FOR_EACH( it, this->devices )
552  (*it)->Unsubscribe();
553 
554  puts("Stage driver has been shutdown");
555 
556  return(0);
557 }
558 
559 
560 // All incoming messages get processed here. This method is called by
561 // Driver::ProcessMessages() once for each message.
562 // Driver::ProcessMessages() is called by StgDriver::Update(), which is
563 // called periodically by player.
564 int
565 StgDriver::ProcessMessage(QueuePointer &resp_queue,
566  player_msghdr * hdr,
567  void * data)
568 {
569  // find the right interface to handle this config
570  Interface* in = this->LookupDevice( hdr->addr );
571  if( in )
572  {
573  return(in->ProcessMessage( resp_queue, hdr, data));
574  }
575  else
576  {
577  PRINT_WARN3( "can't find interface for device %d.%d.%d",
578  this->device_addr.robot,
579  this->device_addr.interf,
580  this->device_addr.index );
581  return(-1);
582  }
583 }
584 
586 {
587  Driver::ProcessMessages();
588 
589  FOR_EACH( it, this->devices )
590  {
591  Interface* interface = *it;
592 
593  assert( interface );
594 
595  switch( interface->addr.interf )
596  {
597  case PLAYER_SIMULATION_CODE:
598  // one round of FLTK's update loop.
599  if (StgDriver::usegui)
600  Fl::wait();
601  else
602  StgDriver::world->Update();
603  break;
604 
605  default:
606  {
607  // Has enough time elapsed since the last time we published on this
608  // interface? This really needs some thought, as each model/interface
609  // should have a configurable publishing rate. For now, I'm using the
610  // world's update rate (which appears to be stored as msec). - BPG
611  double currtime;
612  GlobalTime->GetTimeDouble(&currtime);
613  if((currtime - interface->last_publish_time) >=
614  (interface->publish_interval_msec / 1e3))
615  {
616  interface->Publish();
617  interface->last_publish_time = currtime;
618  }
619  }
620  }
621  }
622 }
623 
624 
Model class
Definition: stage.hh:1742
virtual void Start()
Definition: stage.hh:923
virtual int ProcessMessage(QueuePointer &resp_queue, player_msghdr *hdr, void *data)
Definition: p_driver.cc:565
Driver * StgDriver_Init(ConfigFile *cf, int section)
Definition: p_driver.cc:185
Model * GetUnusedModelOfType(const std::string &type)
Definition: model.cc:914
World class
Definition: stage.hh:814
const char * copyright_notice
Definition: p_driver.cc:154
The Stage library uses its own namespace.
Definition: canvas.hh:8
const char * basename(const char *filename)
Definition: basename.c:35
virtual int Shutdown()
Definition: p_driver.cc:547
Stg::Model * LocateModel(char *basename, player_devaddr_t *addr, const std::string &type)
Definition: p_driver.cc:445
#define PRINT_WARN3(m, a, b, c)
Definition: stage.hh:636
double publish_interval_msec
Definition: p_driver.h:70
Interface(player_devaddr_t addr, StgDriver *driver, ConfigFile *cf, int section)
Definition: p_driver.cc:214
static bool usegui
Definition: p_driver.h:42
#define DRIVER_ERROR(X)
Definition: p_driver.cc:160
player_devaddr_t addr
Definition: p_driver.h:66
virtual int Unsubscribe(QueuePointer &queue, player_devaddr_t addr)
Definition: p_driver.cc:521
int player_driver_init(DriverTable *table)
Definition: p_driver.cc:207
void StgDriver_Register(DriverTable *table)
Definition: p_driver.cc:195
bool player_quit
std::vector< Interface * > devices
an array of pointers to Interface objects, defined below
Definition: p_driver.h:54
virtual void Update()
Definition: p_driver.cc:585
usec_t GetUpdateInterval() const
Definition: stage.hh:2062
virtual bool Update(void)
Definition: world.cc:624
InterfaceModel(player_devaddr_t addr, StgDriver *driver, ConfigFile *cf, int section, const std::string &type)
Definition: p_driver.cc:227
StgDriver(ConfigFile *cf, int section)
Definition: p_driver.cc:291
virtual void Unsubscribe(void)
Definition: p_driver.cc:276
virtual void Subscribe(void)
Definition: p_driver.h:79
#define PRINT_ERR3(m, a, b, c)
Definition: stage.hh:628
void Subscribe()
Definition: model.cc:646
virtual void Unsubscribe(void)
Definition: p_driver.h:80
virtual int Subscribe(QueuePointer &queue, player_devaddr_t addr)
Definition: p_driver.cc:501
void Unsubscribe()
Definition: model.cc:659
Stg::Model * mod
Definition: p_driver.h:115
PlayerTime * GlobalTime
static Stg::World * world
all player devices share the same Stage world (for now)
Definition: p_driver.h:41
Model * GetModel(const std::string &name) const
Definition: world.cc:707
#define PRINT_ERR1(m, a)
Definition: stage.hh:626
bool player_quiet_startup
bool subscribed
Definition: p_driver.h:118
#define FOR_EACH(I, C)
Definition: stage.hh:616
virtual void Subscribe(void)
Definition: p_driver.cc:267
Interface * LookupDevice(player_devaddr_t addr)
find the device record with this Player id
Definition: p_driver.cc:484
virtual int Setup()
Definition: p_driver.cc:475
virtual int ProcessMessage(QueuePointer &resp_queue, player_msghdr_t *hdr, void *data)
Definition: p_driver.h:74
~StgDriver(void)
Definition: p_driver.cc:538
const char * Token() const
Definition: stage.hh:715


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