p_simulation.cc
Go to the documentation of this file.
1 /*
2  * Player - One Hell of a Robot Server
3  * Copyright (C) 2004, 2005 Richard Vaughan
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 /*
23  * Desc: A plugin driver for Player that gives access to Stage devices.
24  * Author: Richard Vaughan
25  * Date: 10 December 2004
26  * CVS: $Id$
27  */
28 
29 // DOCUMENTATION ------------------------------------------------------------
30 
46 // CODE ------------------------------------------------------------
47 
48 //#define DEBUG
49 
50 #include <string.h> // for checking get/set property requests
51 #include <libgen.h> // for dirname(3)
52 #include <libplayercore/globals.h> // for player_argc & player_argv
53 
54 #include "p_driver.h"
55 using namespace Stg;
56 
57 // these are Player globals
58 extern bool player_quiet_startup;
59 extern PlayerTime* GlobalTime;
60 
61 #define DRIVER_ERROR(X) printf( "Stage driver error: %s\n", X )
62 
63 #ifndef PLAYER_CAPABILITIES_REQ
64 #ifdef PLAYER_CAPABILTIES_REQ
65 #define PLAYER_CAPABILITIES_REQ PLAYER_CAPABILTIES_REQ
66 #endif
67 #endif
68 
70 
71 //
72 // SIMULATION INTERFACE
73 //
75  StgDriver* driver,
76  ConfigFile* cf,
77  int section )
78 : Interface( addr, driver, cf, section )
79 {
80  printf( "a Stage world" ); fflush(stdout);
81  //puts( "InterfaceSimulation constructor" );
82 
83  Stg::Init( &player_argc, &player_argv );
84 
85  StgDriver::usegui = cf->ReadBool(section, "usegui", 1 );
86 
87  const char* worldfile_name = cf->ReadString(section, "worldfile", NULL );
88 
89  if( worldfile_name == NULL )
90  {
91  PRINT_ERR1( "device \"%s\" uses the Stage driver but has "
92  "no \"model\" value defined. You must specify a "
93  "model name that matches one of the models in "
94  "the worldfile.",
95  worldfile_name );
96  return; // error
97  }
98 
99  char fullname[MAXPATHLEN];
100 
101  if( worldfile_name[0] == '/' )
102  strcpy( fullname, worldfile_name );
103  else
104  {
105  char *tmp = strdup(cf->filename);
106  snprintf( fullname, MAXPATHLEN,
107  "%s/%s", dirname(tmp), worldfile_name );
108  free(tmp);
109  }
110 
111  // a little sanity testing
112  // XX TODO
113  // if( !g_file_test( fullname, G_FILE_TEST_EXISTS ) )
114  //{
115  // PRINT_ERR1( "worldfile \"%s\" does not exist", worldfile_name );
116  // return;
117  //}
118 
119  // create a passel of Stage models in the local cache based on the
120  // worldfile
121 
122  // if the initial size is to large this crashes on some systems
123  StgDriver::world = ( StgDriver::usegui ? new WorldGui( 400, 300, worldfile_name ) : new World(worldfile_name));
124  assert(StgDriver::world);
125  puts("");
126 
127  StgDriver::world->Load( fullname );
128  //printf( " done.\n" );
129 
130  // poke the P/S name into the window title bar
131  // if( StgDriver::world )
132  // {
133  // char txt[128];
134  // snprintf( txt, 128, "Player/Stage: %s", StgDriver::world->token );
135  // StgDriverworld_set_title(StgDriver::world, txt );
136  // }
137 
138  // steal the global clock - a bit aggressive, but a simple approach
139 
140  delete GlobalTime;
141  GlobalTime = new StTime( driver );
142  assert(GlobalTime);
143  // start the simulation
144  // printf( " Starting world clock... " ); fflush(stdout);
145  //world_resume( world );
146 
148 
149  // this causes Driver::Update() to be called even when the device is
150  // not subscribed
151  driver->alwayson = TRUE;
152 
153  puts( "" ); // end the Stage startup line
154 }
155 
156 int InterfaceSimulation::ProcessMessage(QueuePointer &resp_queue,
157  player_msghdr_t* hdr,
158  void* data)
159 {
160  if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_CAPABILITIES_REQ, addr))
161  {
162  PLAYER_ERROR1("%p\n", data);
163  player_capabilities_req_t & cap_req = * reinterpret_cast<player_capabilities_req_t *> (data);
164  if (cap_req.type == PLAYER_MSGTYPE_REQ && (cap_req.subtype == PLAYER_SIMULATION_REQ_SET_POSE3D || cap_req.subtype == PLAYER_SIMULATION_REQ_GET_POSE3D))
165  {
166  this->driver->Publish(addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_CAPABILITIES_REQ);
167  return 0;
168  }
169  }
170 
171  // Is it a request to get a model's pose in 2D?
172  if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
173  PLAYER_SIMULATION_REQ_GET_POSE2D,
174  this->addr))
175  {
176  player_simulation_pose2d_req_t* req =
177  (player_simulation_pose2d_req_t*)data;
178 
179  PRINT_DEBUG1( "Stage: received request for the 2D position of object \"%s\"\n", req->name );
180 
181  // look up the named model
182  Model* mod = StgDriver::world->GetModel( req->name );
183 
184  if( mod )
185  {
186  Pose pose = mod->GetPose();
187 
188  PRINT_DEBUG3( "Stage: returning location [ %.2f, %.2f, %.2f ]\n",
189  pose.x, pose.y, pose.a );
190 
191  player_simulation_pose2d_req_t reply;
192  memcpy( &reply, req, sizeof(reply));
193  reply.pose.px = pose.x;
194  reply.pose.py = pose.y;
195  reply.pose.pa = pose.a;
196 
197  this->driver->Publish( this->addr, resp_queue,
198  PLAYER_MSGTYPE_RESP_ACK,
199  PLAYER_SIMULATION_REQ_GET_POSE2D,
200  (void*)&reply, sizeof(reply), NULL );
201  return(0);
202  }
203  else
204  {
205  PRINT_WARN1( "Stage: GET_POSE2D request: simulation model \"%s\" not found", req->name );
206  return(-1);
207  }
208  }
209 
210  // Is it a request to set a model's pose in 2D?
211  if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
212  PLAYER_SIMULATION_REQ_SET_POSE2D,
213  this->addr))
214  {
215  player_simulation_pose2d_req_t* req =
216  (player_simulation_pose2d_req_t*)data;
217 
218  // look up the named model
219  Model* mod = StgDriver::world->GetModel( req->name );
220 
221  if( mod )
222  {
223  PRINT_DEBUG4( "Stage: moving \"%s\" to [ %.2f, %.2f, %.2f ]\n",
224  req->name, req->pose.px, req->pose.py, req->pose.pa );
225 
226  Pose pose = mod->GetPose();
227  pose.x = req->pose.px;
228  pose.y = req->pose.py;
229  pose.a = req->pose.pa;
230 
231  mod->SetPose( pose );
232 
233  this->driver->Publish(this->addr, resp_queue,
234  PLAYER_MSGTYPE_RESP_ACK,
235  PLAYER_SIMULATION_REQ_SET_POSE2D);
236  return(0);
237  }
238  else
239  {
240  PRINT_WARN1( "SETPOSE2D request: simulation model \"%s\" not found", req->name );
241  return(-1);
242  }
243  }
244 
245  // Is it a request to get a model's pose in 3D?
246  else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
247  PLAYER_SIMULATION_REQ_GET_POSE3D,
248  this->addr))
249  {
250  player_simulation_pose3d_req_t* req =
251  (player_simulation_pose3d_req_t*)data;
252 
253  PRINT_DEBUG1( "Stage: received request for the 3D position of object \"%s\"\n", req->name );
254 
255  // look up the named model
256  Model* mod = StgDriver::world->GetModel( req->name );
257 
258  if( mod )
259  {
260  Pose pose = mod->GetPose();
261 
262  PRINT_DEBUG4( "Stage: returning location [ %.2f, %.2f, %.2f, %.2f ]\n",
263  pose.x, pose.y, pose.z, pose.a );
264 
265  player_simulation_pose3d_req_t reply;
266  memcpy( &reply, req, sizeof(reply));
267  reply.pose.px = pose.x;
268  reply.pose.py = pose.y;
269  reply.pose.pz = pose.z;
270  reply.pose.proll = 0; // currently unused
271  reply.pose.ppitch = 0; // currently unused
272  reply.pose.pyaw = pose.a;
273  reply.simtime = mod->GetWorld()->SimTimeNow(); // time in microseconds
274 
275  this->driver->Publish( this->addr, resp_queue,
276  PLAYER_MSGTYPE_RESP_ACK,
277  PLAYER_SIMULATION_REQ_GET_POSE3D,
278  (void*)&reply, sizeof(reply), NULL );
279  return(0);
280  }
281  else
282  {
283  PRINT_WARN1( "Stage: GET_POSE3D request: simulation model \"%s\" not found", req->name );
284  return(-1);
285  }
286  }
287 
288  // Is it a request to set a model's pose in 3D?
289  if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
290  PLAYER_SIMULATION_REQ_SET_POSE3D,
291  this->addr))
292  {
293  player_simulation_pose3d_req_t* req =
294  (player_simulation_pose3d_req_t*)data;
295 
296  // look up the named model
297  Model* mod = StgDriver::world->GetModel( req->name );
298 
299  if( mod )
300  {
301  PRINT_DEBUG5( "Stage: moving \"%s\" to [ %.2f, %.2f, %.2f %.2f ]\n",
302  req->name, req->pose.px, req->pose.py, req->pose.pz, req->pose.pyaw );
303 
304  Pose pose = mod->GetPose();
305  pose.x = req->pose.px;
306  pose.y = req->pose.py;
307  pose.z = req->pose.pz;
308  pose.a = req->pose.pyaw;
309  // roll and pitch are unused
310 
311  mod->SetPose( pose );
312 
313  this->driver->Publish(this->addr, resp_queue,
314  PLAYER_MSGTYPE_RESP_ACK,
315  PLAYER_SIMULATION_REQ_SET_POSE3D);
316  return(0);
317  }
318  else
319  {
320  PRINT_WARN1( "SETPOSE2D request: simulation model \"%s\" not found", req->name );
321  return(-1);
322  }
323  }
324 
325  // see line 2661 of player_interfaces.h for header names and stuff
326  // Is it a request to set a model's property?
327  else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
328  PLAYER_SIMULATION_REQ_SET_PROPERTY,
329  this->addr))
330  {
331  player_simulation_property_req_t* req =
332  (player_simulation_property_req_t*)data;
333 
334  /* check they want to set the colour. If they don't
335  * then that's too bad for them. */
336 
337  //strncmp returns 0 if the strings match
338  if( strncmp(req->prop, "color", (size_t)req->prop_count) )
339  {
340  PRINT_WARN1("Property \"%s\" can not be set. Options are \"color\"", req->prop);
341  return(-1);
342  }
343 
344  /* check the value given is an array of four floats */
345  if(req->value_count != sizeof(float)*4)
346  {
347  PRINT_WARN("Value given by SetProperty must be an array of 4 floats\n");
348  return(-1);
349  }
350 
351 
352  // look up the named model
353  Model* mod = StgDriver::world->GetModel( req->name );
354 
355  // if the requested model exists...
356  if( mod )
357  {
358  int ack = 0;
359  float *col = (float *)req->value;
360  Color newColour = Color(col[0], col[1], col[2], col[3]);
361 
362  mod->SetColor(newColour);
363 
364  this->driver->Publish(this->addr, resp_queue,
365  ack==0 ? PLAYER_MSGTYPE_RESP_ACK : PLAYER_MSGTYPE_RESP_NACK,
366  PLAYER_SIMULATION_REQ_SET_PROPERTY);
367  return(0);
368  }
369  else
370  {
371  PRINT_WARN1( "SET_PROPERTY request: simulation model \"%s\" not found", req->name );
372  return(-1);
373  }
374  }
375 
376  // Is it a request to get a model's property?
377  else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
378  PLAYER_SIMULATION_REQ_GET_PROPERTY,
379  this->addr))
380  {
381  player_simulation_property_req_t* req =
382  (player_simulation_property_req_t*)data;
383 
384 
385 
386  // check they want to set the colour.
387 
388  //strncmp returns 0 if the strings match
389  if( !(strncmp(req->prop, "color", (size_t)req->prop_count) ))
390  {
391  // check the value given is an array of four floats
392  if(req->value_count != sizeof(float)*4)
393  {
394  PRINT_WARN("Colour requires an array of 4 floats to store\n");
395  return(-1);
396  }
397 
398  // look up the named model
399  Model* mod = StgDriver::world->GetModel( req->name );
400 
401  if( mod )
402  {
403  Color newColour = mod->GetColor(); //line 2279 of stage.hh
404  // make an array to hold it as floats
405  float col[4];
406  col[0] = newColour.r;
407  col[1] = newColour.g;
408  col[2] = newColour.b;
409  col[3] = newColour.a;
410 
411  //copy array of floats into memory provided in the req structure
412  memcpy(req->value, col, req->value_count);
413 
414  //make a new structure and copy req into it
415 
416  player_simulation_property_req_t reply;
417  memcpy( &reply, req, sizeof(reply));
418 
419  //put col array into reply
420  memcpy(reply.value, col, reply.value_count);
421 
422 
423  this->driver->Publish( this->addr, resp_queue,
424  PLAYER_MSGTYPE_RESP_ACK,
425  PLAYER_SIMULATION_REQ_GET_PROPERTY,
426  (void*)&reply, sizeof(reply), NULL );
427 
428  return(0);
429  }
430  else
431  {
432  PRINT_WARN1( "GET_PROPERTY request: simulation model \"%s\" not found", req->name );
433  return(-1);
434  }
435  }
436  else if( strncmp(req->prop, "time", (size_t)req->prop_count ) == 0 )
437  {
438  // check the value given is a uint64_t
439  if(req->value_count != sizeof(uint64_t))
440  {
441  PRINT_WARN("Simulation time requires a uint64_t to store\n");
442  return(-1);
443  }
444 
445  //return simulation time
446  // look up the named model
447  Model* mod = StgDriver::world->GetModel( req->name );
448 
449  if( mod )
450  {
451  //make a new structure and copy req into it
452  player_simulation_property_req_t reply;
453  memcpy( &reply, req, sizeof(reply));
454 
455  // and copy the time data
456  *(uint64_t*)&reply.value = mod->GetWorld()->SimTimeNow();
457 
458  this->driver->Publish( this->addr, resp_queue,
459  PLAYER_MSGTYPE_RESP_ACK,
460  PLAYER_SIMULATION_REQ_GET_PROPERTY,
461  (void*)&reply, sizeof(reply), NULL );
462 
463  return(0);
464  }
465  else
466  {
467  PRINT_WARN1( "GET_PROPERTY request: simulation model \"%s\" not found", req->name );
468  return(-1);
469  }
470 
471  }
472  else
473  {
474  PRINT_WARN1("Property \"%s\" is not accessible. Options are \"color\", \"_mp_color\", or \"colour\" for changing colour. \"simtime\" or \"sim_time\" for getting the simulation time.", req->prop);
475  return(-1);
476  }
477 
478  }
479 
480  else
481  {
482  // Don't know how to handle this message.
483  PRINT_WARN2( "simulation doesn't support msg with type/subtype %d/%d",
484  hdr->type, hdr->subtype);
485  return(-1);
486  }
487 }
Model class
Definition: stage.hh:1742
virtual void Start()
Definition: stage.hh:923
InterfaceSimulation(player_devaddr_t addr, StgDriver *driver, ConfigFile *cf, int section)
Definition: p_simulation.cc:74
double a
Definition: stage.hh:200
usec_t SimTimeNow(void) const
Definition: stage.hh:1119
World class
Definition: stage.hh:814
The Stage library uses its own namespace.
Definition: canvas.hh:8
void SetPose(const Pose &pose)
Definition: model.cc:1396
#define PRINT_DEBUG5(m, a, b, c, d, e)
Definition: stage.hh:671
void Init(int *argc, char **argv[])
Definition: stage.cc:18
#define PRINT_WARN2(m, a, b)
Definition: stage.hh:635
Color GetColor() const
Definition: stage.hh:2362
static bool usegui
Definition: p_driver.h:42
StgDriver * driver
Definition: p_driver.h:72
World * GetWorld() const
Definition: stage.hh:2302
meters_t z
location in 3 axes
Definition: stage.hh:251
meters_t y
Definition: stage.hh:251
player_devaddr_t addr
Definition: p_driver.h:66
#define PRINT_DEBUG3(m, a, b, c)
Definition: stage.hh:669
char * dirname(char *path)
Definition: dirname.c:31
double r
Definition: stage.hh:200
PlayerTime * GlobalTime
double b
Definition: stage.hh:200
#define PRINT_WARN(m)
Definition: stage.hh:633
double g
Definition: stage.hh:200
virtual int ProcessMessage(QueuePointer &resp_queue, player_msghdr_t *hdr, void *data)
bool player_quiet_startup
#define PRINT_DEBUG1(m, a)
Definition: stage.hh:667
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_DEBUG4(m, a, b, c, d)
Definition: stage.hh:670
#define PRINT_ERR1(m, a)
Definition: stage.hh:626
Pose GetPose() const
Definition: stage.hh:2382
radians_t a
rotation about the z axis.
Definition: stage.hh:252
#define PRINT_WARN1(m, a)
Definition: stage.hh:634
void SetColor(Color col)
Definition: model.cc:1260
meters_t x
Definition: stage.hh:251
virtual void Load(const std::string &worldfile_path)
Definition: world.cc:388


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