model_gripper.cc
Go to the documentation of this file.
1 //
3 // File: model_gripper.cc
4 // Authors: Richard Vaughan <vaughan@sfu.ca>
5 // Doug Blank
6 // Date: 21 April 2005
7 //
8 // CVS info:
9 // $Source: /home/tcollett/stagecvs/playerstage-cvs/code/stage/src/model_gripper.c,v $
10 // $Author: thjc $
11 // $Revision$
12 //
14 
52 #include <sys/time.h>
53 #include "stage.hh"
54 #include "worldfile.hh"
55 using namespace Stg;
56 
57 #include "option.hh"
58 Option ModelGripper::showData( "Gripper data", "show_gripper_data", "", true, NULL );
59 
60 // TODO - simulate energy use when moving grippers
61 
63  Model* parent,
64  const std::string& type ) :
65  Model( world, parent, type ),
66  cfg(), // configured below
67  cmd( CMD_NOOP )
68 {
69  // set up a gripper-specific config structure
70  cfg.paddle_size.x = 0.66; // proportion of body length that is paddles
71  cfg.paddle_size.y = 0.1; // proportion of body width that is paddles
72  cfg.paddle_size.z = 0.4; // proportion of body height that is paddles
73 
75  cfg.lift = LIFT_DOWN;
76  cfg.paddle_position = 0.0;
77  cfg.lift_position = 0.0;
78  cfg.paddles_stalled = false;
79  cfg.autosnatch = false;
80  cfg.gripped = NULL;
81  cfg.beam[0] = 0;
82  cfg.beam[1] = 0;
83  cfg.contact[0] = 0;
84  cfg.contact[1] = 0;
85 
86  // place the break beam sensors at 1/4 and 3/4 the length of the paddle
87  cfg.break_beam_inset[0] = 3.0/4.0 * cfg.paddle_size.x;
88  cfg.break_beam_inset[1] = 1.0/4.0 * cfg.paddle_size.x;
89 
90  cfg.close_limit = 1.0;
91 
92  SetColor( Color(0.3, 0.3, 0.3, 1.0) );
93 
94  FixBlocks();
95 
96  // Update() is not reentrant
97  thread_safe = false;
98 
99  // set default size
100  SetGeom( Geom( Pose(0,0,0,0), Size( 0.2, 0.3, 0.2)));
101 
102  PositionPaddles();
103 
105 }
106 
108 {
109  /* do nothing */
110 }
111 
112 
114 {
115  cfg.autosnatch = wf->ReadInt( wf_entity, "autosnatch", cfg.autosnatch );
116 
117  // cfg.paddle_size.x = wf->ReadTupleFloat( wf_entity, "paddle_size", 0, cfg.paddle_size.x );
118  // cfg.paddle_size.y = wf->ReadTupleFloat( wf_entity, "paddle_size", 1, cfg.paddle_size.y );
119  // cfg.paddle_size.z = wf->ReadTupleFloat( wf_entity, "paddle_size", 2, cfg.paddle_size.z );
120 
121  wf->ReadTuple( wf_entity, "paddle_size", 0, 3, "lll",
122  &cfg.paddle_size.x,
123  &cfg.paddle_size.y,
124  &cfg.paddle_size.z );
125 
126  //const char* paddles = wf->ReadTupleString( wf_entity, "paddle_state", 0, NULL );
127  //const char* lift = wf->ReadTupleString( wf_entity, "paddle_state", 1, NULL );
128 
129  char* paddles = NULL;
130  char* lift = NULL;
131  wf->ReadTuple( wf_entity, "paddle_state", 0, 2, "ss", &paddles, &lift );
132 
133  if( paddles && strcmp( paddles, "closed" ) == 0 )
134  {
135  cfg.paddle_position = 1.0;
137  }
138 
139  if( paddles && strcmp( paddles, "open" ) == 0 )
140  {
141  cfg.paddle_position = 0.0;
143  }
144 
145  if( lift && strcmp( lift, "up" ) == 0 )
146  {
147  cfg.lift_position = 1.0;
148  cfg.lift = LIFT_UP;
149  }
150 
151  if( lift && strcmp( lift, "down" ) == 0 )
152  {
153  cfg.lift_position = 0.0;
154  cfg.lift = LIFT_DOWN;
155  }
156 
157  FixBlocks();
158 
159  // do this at the end to ensure that the blocks are resize correctly
160  Model::Load();
161 }
162 
164 {
165  Model::Save();
166 
167  // wf->WriteTupleFloat( wf_entity, "paddle_size", 0, cfg.paddle_size.x );
168  // wf->WriteTupleFloat( wf_entity, "paddle_size", 1, cfg.paddle_size.y );
169  // wf->WriteTupleFloat( wf_entity, "paddle_size", 2, cfg.paddle_size.z );
170 
171  wf->WriteTuple( wf_entity, "paddle_size", 0, 3, "lll",
172  cfg.paddle_size.x,
173  cfg.paddle_size.y,
174  cfg.paddle_size.z );
175 
176  // wf->WriteTupleString( wf_entity, "paddle_state", 0, (cfg.paddles == PADDLE_CLOSED ) ? "closed" : "open" );
177  // wf->WriteTupleString( wf_entity, "paddle_state", 1, (cfg.lift == LIFT_UP ) ? "up" : "down" );
178 
179  wf->WriteTuple( wf_entity, "paddle_state", 0, 2, "ss",
180  (cfg.paddles == PADDLE_CLOSED ) ? "closed" : "open",
181  (cfg.lift == LIFT_UP ) ? "up" : "down" );
182 
183 }
184 
186 {
187  // get rid of the default cube
188  ClearBlocks();
189 
190  // add three blocks that make the gripper
191  // base
192  AddBlockRect( 0, 0, 1.0-cfg.paddle_size.x, 1.0, 1.0 );
193 
194  // left (top) paddle
196 
197  // right (bottom) paddle
199 
200  PositionPaddles();
201 }
202 
203 // Update the blocks that are the gripper's body
205 {
206  unsigned int layer = world->GetUpdateCount()%2;
207  UnMap(layer);
208 
209  double paddle_center_pos = cfg.paddle_position * (0.5 - cfg.paddle_size.y );
210  paddle_left->SetCenterY( paddle_center_pos + cfg.paddle_size.y/2.0 );
211  paddle_right->SetCenterY( 1.0 - paddle_center_pos - cfg.paddle_size.y/2.0);
212 
213  double paddle_bottom = cfg.lift_position * (1.0 - cfg.paddle_size.z);
214  double paddle_top = paddle_bottom + cfg.paddle_size.z;
215 
216  paddle_left->SetZ( paddle_bottom, paddle_top );
217  paddle_right->SetZ( paddle_bottom, paddle_top );
218 
219  Map(layer);
220  }
221 
222 
224 {
225  float start_paddle_position = cfg.paddle_position;
226  float start_lift_position = cfg.lift_position;
227 
228  switch( cmd )
229  {
230  case CMD_NOOP:
231  break;
232 
233  case CMD_CLOSE:
234  if( cfg.paddles != PADDLE_CLOSED )
235  {
236  //puts( "closing gripper paddles" );
238  }
239  break;
240 
241  case CMD_OPEN:
242  if( cfg.paddles != PADDLE_OPEN )
243  {
244  //puts( "opening gripper paddles" );
246  }
247  break;
248 
249  case CMD_UP:
250  if( cfg.lift != LIFT_UP )
251  {
252  //puts( "raising gripper lift" );
253  cfg.lift = LIFT_UPPING;
254  }
255  break;
256 
257  case CMD_DOWN:
258  if( cfg.lift != LIFT_DOWN )
259  {
260  //puts( "lowering gripper lift" );
262  }
263  break;
264 
265  default:
266  printf( "unknown gripper command %d\n",cmd );
267  }
268 
269  // // move the paddles
270  if( cfg.paddles == PADDLE_OPENING )// && !cfg.paddles_stalled )
271  {
272  cfg.paddle_position -= 0.05;
273 
274  if( cfg.paddle_position < 0.0 ) // if we're fully open
275  {
276  cfg.paddle_position = 0.0;
277  cfg.paddles = PADDLE_OPEN; // change state
278  }
279 
280 
281  // drop the thing we're carrying
282  if( cfg.gripped &&
284  {
285  // move it to the new location
286  cfg.gripped->SetParent( NULL );
287  cfg.gripped->SetPose( this->GetGlobalPose() );
288  cfg.gripped = NULL;
289 
290  cfg.close_limit = 1.0;
291  }
292  }
293 
294  else if( cfg.paddles == PADDLE_CLOSING ) //&& !cfg.paddles_stalled )
295  {
296  cfg.paddle_position += 0.05;
297  //printf( "paddle position %.2f\n", cfg.paddle_position );
298 
299  if( cfg.paddle_position > cfg.close_limit ) // if we're fully closed
300  {
302  cfg.paddles = PADDLE_CLOSED; // change state
303  }
304  }
305 
306  switch( cfg.lift )
307  {
308  case LIFT_DOWNING:
309  cfg.lift_position -= 0.05;
310 
311  if( cfg.lift_position < 0.0 ) // if we're fully down
312  {
313  cfg.lift_position = 0.0;
314  cfg.lift = LIFT_DOWN; // change state
315  }
316  break;
317 
318  case LIFT_UPPING:
319  cfg.lift_position += 0.05;
320 
321  if( cfg.lift_position > 1.0 ) // if we're fully open
322  {
323  cfg.lift_position = 1.0;
324  cfg.lift = LIFT_UP; // change state
325  }
326  break;
327 
328  case LIFT_DOWN: // nothing to do for these cases
329  case LIFT_UP:
330  default:
331  break;
332  }
333 
334  // if the paddles or lift have changed position
335  if( start_paddle_position != cfg.paddle_position ||
336  start_lift_position != cfg.lift_position )
337  // figure out where the paddles should be
338  PositionPaddles();
339 
340 
342  UpdateContacts();
343 
344  Model::Update();
345 }
346 
347 
348 
349 static bool gripper_raytrace_match( Model* hit,
350  Model* finder,
351  const void* dummy )
352 {
353  (void)dummy; // avoid warning about unused var
354 
355  return( (hit != finder) && hit->vis.gripper_return );
356  // can't use the normal relation check, because we may pick things
357  // up and we must still see them.
358 }
359 
361 {
362  for( unsigned int index=0; index < 2; index++ )
363  {
364  Pose pz;
365 
366  // x location of break beam origin
367  double inset = cfg.break_beam_inset[index];
368 
369  pz.x = (geom.size.x - inset * geom.size.x) - geom.size.x/2.0;
370 
371  // y location of break beam origin
372  pz.y = (1.0 - cfg.paddle_position) * ((geom.size.y/2.0)-(geom.size.y*cfg.paddle_size.y));
373 
374  pz.z = 0.0; // TODO
375 
376  // break beam local heading
377  pz.a = -M_PI/2.0;
378 
379  // break beam max range
380  double bbr =
381  (1.0 - cfg.paddle_position) * (geom.size.y - (geom.size.y * cfg.paddle_size.y * 2.0 ));
382 
383  RaytraceResult sample =
384  Raytrace( pz, // ray origin
385  bbr, // range
386  gripper_raytrace_match, // match func
387  NULL, // match arg
388  true ); // ztest
389 
390  cfg.beam[index] = sample.mod;
391  }
392 
393  // autosnatch grabs anything that breaks the inner beam
394  if( cfg.autosnatch )
395  {
396  if( cfg.beam[0] || cfg.beam[1] )
397  cmd = CMD_CLOSE;
398  else
399  cmd = CMD_OPEN;
400  }
401 }
402 
404 {
405  cfg.paddles_stalled = false; // may be changed below
406 
407  Pose lpz, rpz;
408 
409  // x location of contact sensor origin
410  lpz.x = ((1.0 - cfg.paddle_size.x) * geom.size.x) - geom.size.x/2.0 ;
411  rpz.x = ((1.0 - cfg.paddle_size.x) * geom.size.x) - geom.size.x/2.0 ;
412 
413 // //double inset = beam ? cfg->inner_break_beam_inset : cfg->outer_break_beam_inset;
414 // //pz.x = (geom.size.x - inset * geom.size.x) - geom.size.x/2.0;
415 
416  // y location of paddle beam origin
417 
418  lpz.y = (1.0 - cfg.paddle_position) *
419  ((geom.size.y/2.0) - (geom.size.y*cfg.paddle_size.y));
420 
421  rpz.y = (1.0 - cfg.paddle_position) *
422  -((geom.size.y/2.0) - (geom.size.y*cfg.paddle_size.y));
423 
424  lpz.z = 0.0; // todo
425  rpz.z = 0.0;
426 
427  // paddle beam local heading
428  lpz.a = 0.0;
429  rpz.a = 0.0;
430 
431  // paddle beam max range
432  double bbr = cfg.paddle_size.x * geom.size.x;
433 
434  RaytraceResult leftsample =
435  Raytrace( lpz, // ray origin
436  bbr, // range
437  gripper_raytrace_match, // match func
438  NULL, // match arg
439  true ); // ztest
440 
441  cfg.contact[0] = leftsample.mod;
442 
443  RaytraceResult rightsample =
444  Raytrace( rpz, // ray origin
445  bbr, // range
446  gripper_raytrace_match, // match func
447  NULL, // match arg
448  true ); // ztest
449 
450  cfg.contact[1] = rightsample.mod;
451 
452  if( cfg.contact[0] || cfg.contact[1] )
453  {
454  cfg.paddles_stalled = true;;
455 
456  // if( lhit && (lhit == rhit) )
457  // {
458  // //puts( "left and right hit same thing" );
459 
460  if( cfg.paddles == PADDLE_CLOSING )
461  {
462  Model* hit = cfg.contact[0];
463  if( !hit )
464  hit = cfg.contact[1];
465 
466  if( cfg.gripped == NULL ) // if we're not carrying something already
467  {
468  // get the global pose of the gripper for calculations of the gripped object position
469  // and move it to be right between the paddles
470  Geom hitgeom = hit->GetGeom();
471  //Pose hitgpose = hit->GetGlobalPose();
472 
473  // pose_t pose = {0,0,0};
474  // model_local_to_global( lhit, &pose );
475  // model_global_to_local( mod, &pose );
476 
477  // // grab the model we hit - very simple grip model for now
478  hit->SetParent( this );
479  hit->SetPose( Pose(0,0, -1.0 * geom.size.z ,0) );
480 
481  cfg.gripped = hit;
482 
483  // // calculate how far closed we can get the paddles now
484  double puckw = hitgeom.size.y;
485  double gripperw = geom.size.y;
486  cfg.close_limit = std::max( 0.0, 1.0 - puckw/(gripperw - cfg.paddle_size.y/2.0 ));
487  }
488  }
489  }
490 }
491 
492 
494 {
495  (void)cam; // avoid warning about unused var
496 
497  // only draw if someone is using the gripper
498  if( subs < 1 )
499  return;
500 
501  //if( ! showData )
502  //return;
503 
504  // outline the sensor lights in black
505  PushColor( 0,0,0,1.0 ); // black
506  glTranslatef( 0,0, geom.size.z * cfg.paddle_size.z );
507  glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
508 
509  // different x location for each beam
510  double ibbx = (geom.size.x - cfg.break_beam_inset[0] * geom.size.x) - geom.size.x/2.0;
511  double obbx = (geom.size.x - cfg.break_beam_inset[1] * geom.size.x) - geom.size.x/2.0;
512 
513  // common y position
514  double invp = 1.0 - cfg.paddle_position;
515  double bby =
516  invp * ((geom.size.y/2.0)-(geom.size.y*cfg.paddle_size.y));
517 
518  // // size of the paddle indicator lights
519  double led_dx = cfg.paddle_size.y * 0.5 * geom.size.y;
520 
521  // paddle break beams
522  Gl::draw_centered_rect( ibbx, bby+led_dx, led_dx, led_dx );
523  Gl::draw_centered_rect( ibbx, -bby-led_dx, led_dx, led_dx );
524  Gl::draw_centered_rect( obbx, bby+led_dx, led_dx, led_dx );
525  Gl::draw_centered_rect( obbx, -bby-led_dx, led_dx, led_dx );
526 
527  // paddle contacts
528  double cx = ((1.0 - cfg.paddle_size.x/2.0) * geom.size.x) - geom.size.x/2.0;
529  double cy = (geom.size.y/2.0)-(geom.size.y * 0.8 * cfg.paddle_size.y);
530  double plen = cfg.paddle_size.x * geom.size.x;
531  double pwidth = 0.4 * cfg.paddle_size.y * geom.size.y;
532 
533  Gl::draw_centered_rect( cx, invp * +cy, plen, pwidth );
534  Gl::draw_centered_rect( cx, invp * -cy, plen, pwidth );
535 
536  // if the gripper detects anything, fill the lights in with yellow
537  if( cfg.beam[0] || cfg.beam[1] || cfg.contact[0] || cfg.contact[1] )
538  {
539  PushColor( 1,1,0,1.0 ); // yellow
540  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
541 
542  if( cfg.contact[0] )
543  Gl::draw_centered_rect( cx, invp * +cy, plen, pwidth );
544 
545  if( cfg.contact[1] )
546  Gl::draw_centered_rect( cx, invp * -cy, plen, pwidth );
547 
548  if( cfg.beam[0] )
549  {
550  Gl::draw_centered_rect( ibbx, bby+led_dx, led_dx, led_dx );
551  Gl::draw_centered_rect( ibbx, -bby-led_dx, led_dx, led_dx );
552  }
553 
554  if( cfg.beam[1] )
555  {
556  Gl::draw_centered_rect( obbx, bby+led_dx, led_dx, led_dx );
557  Gl::draw_centered_rect( obbx, -bby-led_dx, led_dx, led_dx );
558  }
559 
560  PopColor(); // yellow
561  }
562 
563  PopColor(); // black
564  }
565 
566 
virtual void PushColor(Color col)
Definition: stage.hh:2189
Model class
Definition: stage.hh:1742
bool autosnatch
if true, cycle the gripper through open-close-up-down automatically
Definition: stage.hh:2614
ModelGripper(World *world, Model *parent, const std::string &type)
int subs
the number of subscriptions to this model
Definition: stage.hh:1959
World class
Definition: stage.hh:814
The Stage library uses its own namespace.
Definition: canvas.hh:8
Block * AddBlockRect(meters_t x, meters_t y, meters_t dx, meters_t dy, meters_t dz)
Definition: model.cc:442
void SetPose(const Pose &pose)
Definition: model.cc:1396
static Option showData
Definition: stage.hh:2635
meters_t x
Definition: stage.hh:228
double lift_position
0.0 = full down, 1.0 full up
Definition: stage.hh:2610
virtual void Save()
Geom geom
Definition: stage.hh:1883
Block * paddle_left
Definition: stage.hh:2632
int ReadTuple(const int entity, const char *name, const unsigned int first, const unsigned int num, const char *format,...)
Definition: worldfile.cc:1506
config_t cfg
Definition: stage.hh:2629
Size size
extent
Definition: stage.hh:395
virtual void PopColor()
Definition: stage.hh:2191
RaytraceResult Raytrace(const Pose &pose, const meters_t range, const ray_test_func_t func, const void *arg, const bool ztest=true)
Definition: model.cc:475
bool thread_safe
Definition: stage.hh:1964
meters_t z
location in 3 axes
Definition: stage.hh:251
meters_t y
Definition: stage.hh:251
Worldfile * wf
Definition: stage.hh:2015
void WriteTuple(const int entity, const char *name, const unsigned int first, const unsigned int count, const char *format,...)
Definition: worldfile.cc:1573
int wf_entity
Definition: stage.hh:2016
void RegisterOption(Option *opt)
Definition: model.cc:996
void draw_centered_rect(float x, float y, float dx, float dy)
Definition: gl.cc:121
Size paddle_size
paddle dimensions
Definition: stage.hh:2606
virtual void Update()
Pose GetGlobalPose() const
Definition: model.cc:1379
Model * beam[2]
points to a model detected by the beams
Definition: stage.hh:2616
virtual void DataVisualize(Camera *cam)
void SetCenterY(double y)
Definition: block.cc:111
static bool gripper_raytrace_match(Model *hit, Model *finder, const void *dummy)
virtual void Load()
meters_t y
Definition: stage.hh:228
virtual void Save()
Definition: model.cc:1633
int SetParent(Model *newparent)
Definition: model.cc:1354
void SetZ(double min, double max)
Definition: block.cc:125
meters_t z
Definition: stage.hh:228
Model * contact[2]
pointers to a model detected by the contacts
Definition: stage.hh:2617
double close_limit
How far the gripper can close. If < 1.0, the gripper has its mouth full.
Definition: stage.hh:2613
virtual void Update()
Definition: model.cc:735
void Map()
Definition: stage.hh:2099
virtual void Load()
Definition: model.cc:1422
class Stg::Model::Visibility vis
World * world
Definition: stage.hh:2017
Block * paddle_right
Definition: stage.hh:2633
double break_beam_inset[2]
distance from the end of the paddle
Definition: stage.hh:2615
void UnMap()
Definition: stage.hh:2104
int ReadInt(int entity, const char *name, int value)
Definition: worldfile.cc:1398
void SetGeom(const Geom &src)
Definition: model.cc:1243
paddle_state_t paddles
Definition: stage.hh:2607
radians_t a
rotation about the z axis.
Definition: stage.hh:252
uint64_t GetUpdateCount() const
Definition: stage.hh:1184
double paddle_position
0.0 = full open, 1.0 full closed
Definition: stage.hh:2609
virtual ~ModelGripper()
Model * mod
the model struck by this beam
Definition: stage.hh:746
void SetColor(Color col)
Definition: model.cc:1260
meters_t x
Definition: stage.hh:251
void ClearBlocks()
Definition: model.cc:421
Geom GetGeom() const
Definition: stage.hh:2378


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