GazeboGraspFix.cpp
Go to the documentation of this file.
1 //
2 // Created by tom on 19/09/16.
3 //
4 
5 #include <boost/bind.hpp>
6 #include <gazebo/gazebo.hh>
7 #include <gazebo/physics/physics.hh>
8 #include <gazebo/physics/ContactManager.hh>
9 #include <gazebo/physics/Contact.hh>
10 #include <gazebo/common/common.hh>
11 #include <stdio.h>
12 
14 
16 
17 
18 #define DEFAULT_FORCES_ANGLE_TOLERANCE 120
19 #define DEFAULT_UPDATE_RATE 5
20 #define DEFAULT_MAX_GRIP_COUNT 10
21 #define DEFAULT_RELEASE_TOLERANCE 0.005
22 #define DEFAULT_DISABLE_COLLISIONS_ON_ATTACH false
23 
24 // Register this plugin with the simulator
25 GZ_REGISTER_MODEL_PLUGIN(GazeboGraspFix)
26 
27 
29  InitValues();
30 }
31 
32 GazeboGraspFix::GazeboGraspFix(physics::ModelPtr _model)
33 {
34  InitValues();
35 }
36 
38 {
39  this->update_connection.reset();
40  if (this->node) this->node->Fini();
41  this->node.reset();
42 }
43 
45 {
46  this->prevUpdateTime = common::Time::GetWallTime();
47 }
48 
50 {
51 #if GAZEBO_MAJOR_VERSION > 2
52  gazebo::common::Console::SetQuiet(false);
53 #endif
54 
55  // float timeDiff=0.25;
56  // this->releaseTolerance=0.005;
57  // this->updateRate = common::Time(0, common::Time::SecToNano(timeDiff));
58  this->prevUpdateTime = common::Time::GetWallTime();
59  //float graspedSecs=2;
60  //this->maxGripCount=floor(graspedSecs/timeDiff);
61  //this->gripCountThreshold=floor(this->maxGripCount/2);
62  this->node = transport::NodePtr(new transport::Node());
63 }
64 
65 
66 void GazeboGraspFix::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
67 {
68  std::cout<<"Loading grasp-fix plugin"<<std::endl;
69 
70  // ++++++++++++ Read parameters and initialize fields +++++++++++++++
71 
72  physics::ModelPtr model = _parent;
73  this->world = model->GetWorld();
74 
75  sdf::ElementPtr disableCollisionsOnAttachElem = _sdf->GetElement("disable_collisions_on_attach");
76  if (!disableCollisionsOnAttachElem){
77  std::cout<<"GazeboGraspFix: Using default "<<DEFAULT_DISABLE_COLLISIONS_ON_ATTACH<<" because no <disable_collisions_on_attach> element specified."<<std::endl;
79  } else {
80  std::string str = disableCollisionsOnAttachElem->Get<std::string>();
81  bool bVal = false;
82  if ((str=="true") || (str=="1")) bVal = true;
83  this->disableCollisionsOnAttach = bVal;
84  std::cout<<"GazeboGraspFix: Using disable_collisions_on_attach "<<this->disableCollisionsOnAttach<<std::endl;
85  }
86 
87  sdf::ElementPtr forcesAngleToleranceElem = _sdf->GetElement("forces_angle_tolerance");
88  if (!forcesAngleToleranceElem){
89  std::cout<<"GazeboGraspFix: Using default tolerance of "<<DEFAULT_FORCES_ANGLE_TOLERANCE<<" because no <forces_angle_tolerance> element specified."<<std::endl;
91  } else {
92  this->forcesAngleTolerance = forcesAngleToleranceElem->Get<float>() * M_PI/180;
93  }
94 
95  sdf::ElementPtr updateRateElem = _sdf->GetElement("update_rate");
96  double _updateSecs;
97  if (!updateRateElem){
98  std::cout<<"GazeboGraspFix: Using "<<DEFAULT_UPDATE_RATE<<" because no <updateRate_tag> element specified."<<std::endl;
99  _updateSecs = 1.0 / DEFAULT_UPDATE_RATE;
100  } else {
101  int _rate = updateRateElem->Get<int>();
102  double _updateRate = _rate;
103  _updateSecs = 1.0/_updateRate;
104  std::cout<<"GazeboGraspFix: Using update rate "<<_rate<<std::endl;
105  }
106  this->updateRate = common::Time(0, common::Time::SecToNano(_updateSecs));
107 
108  sdf::ElementPtr maxGripCountElem = _sdf->GetElement("max_grip_count");
109  if (!maxGripCountElem){
110  std::cout<<"GazeboGraspFix: Using "<<DEFAULT_MAX_GRIP_COUNT<<" because no <max_grip_count> element specified."<<std::endl;
112  } else {
113  this->maxGripCount = maxGripCountElem->Get<int>();
114  std::cout<<"GazeboGraspFix: Using max_grip_count "<<this->maxGripCount<<std::endl;
115  }
116 
117  sdf::ElementPtr gripCountThresholdElem = _sdf->GetElement("grip_count_threshold");
118  if (!gripCountThresholdElem){
119  this->gripCountThreshold=floor(this->maxGripCount/2.0);
120  std::cout<<"GazeboGraspFix: Using "<<this->gripCountThreshold<<" because no <grip_count_threshold> element specified."<<std::endl;
121  } else {
122  this->gripCountThreshold = gripCountThresholdElem->Get<int>();
123  std::cout<<"GazeboGraspFix: Using grip_count_threshold "<<this->gripCountThreshold<<std::endl;
124  }
125 
126  sdf::ElementPtr releaseToleranceElem = _sdf->GetElement("release_tolerance");
127  if (!releaseToleranceElem){
128  std::cout<<"GazeboGraspFix: Using "<<DEFAULT_RELEASE_TOLERANCE<<" because no <release_tolerance> element specified."<<std::endl;
130  } else {
131  this->releaseTolerance = releaseToleranceElem->Get<float>();
132  std::cout<<"GazeboGraspFix: Using release_tolerance "<<this->releaseTolerance<<std::endl;
133  }
134 
135  // will contain all names of collision entities involved from all arms
136  std::vector<std::string> collisionNames;
137 
138  sdf::ElementPtr armElem=_sdf->GetElement("arm");
139  if (!armElem)
140  {
141  gzerr <<"GazeboGraspFix: Cannot load the GazeboGraspFix without any <arm> declarations"<<std::endl;
142  return;
143  }
144  // add all arms:
145  for (; armElem != NULL; armElem = armElem->GetNextElement("arm"))
146  {
147  sdf::ElementPtr armNameElem = armElem->GetElement("arm_name");
148  sdf::ElementPtr handLinkElem = armElem->GetElement("palm_link");
149  sdf::ElementPtr fingerLinkElem = armElem->GetElement("gripper_link");
150 
151  if (!handLinkElem || !fingerLinkElem || !armNameElem) {
152  gzerr << "ERROR: GazeboGraspFix: Cannot use a GazeboGraspFix arm because "
153  << "not all of <arm_name>, <palm_link> and <gripper_link> elements specified in URDF/SDF. Skipping."<<std::endl;
154  continue;
155  }
156 
157  std::string armName = armNameElem->Get<std::string>();
158  std::string palmName = handLinkElem->Get<std::string>();
159 
160  // collect all finger names:
161  std::vector<std::string> fingerLinkNames;
162  for (; fingerLinkElem != NULL; fingerLinkElem = fingerLinkElem->GetNextElement("gripper_link"))
163  {
164  std::string linkName = fingerLinkElem->Get<std::string>();
165  fingerLinkNames.push_back(linkName);
166  }
167 
168  // add new gripper
169  if (grippers.find(armName)!=grippers.end())
170  {
171  gzerr<<"GazeboGraspFix: Arm named "<<armName<<" was already added, cannot add it twice."<<std::endl;
172  }
173  GazeboGraspGripper& gripper = grippers[armName];
174  std::map<std::string, physics::CollisionPtr> _collisions;
175  if (!gripper.Init(_parent, armName, palmName, fingerLinkNames, disableCollisionsOnAttach, _collisions))
176  {
177  gzerr<<"GazeboGraspFix: Could not initialize arm "<<armName<<". Skipping."<<std::endl;
178  grippers.erase(armName);
179  continue;
180  }
181  // add all the grippers's collision elements
182  for (std::map<std::string, physics::CollisionPtr>::iterator collIt = _collisions.begin();
183  collIt != _collisions.end(); ++collIt)
184  {
185  const std::string& collName=collIt->first;
186  //physics::CollisionPtr& coll=collIt->second;
187  std::map<std::string, std::string>::iterator collIter = this->collisions.find(collName);
188  if (collIter != this->collisions.end()) { //this collision was already added before
189  gzwarn <<"GazeboGraspFix: Adding Gazebo collision link element "<<collName<<" multiple times, the grasp plugin may not work properly"<<std::endl;
190  continue;
191  }
192  std::cout<<"GazeboGraspFix: Adding collision scoped name "<<collName<<std::endl;
193  this->collisions[collName] = armName;
194  collisionNames.push_back(collName);
195  }
196  }
197 
198  if (grippers.empty())
199  {
200  gzerr << "ERROR: GazeboGraspFix: Cannot use a GazeboGraspFix because "
201  << "no arms were configured successfully. Plugin will not work."<<std::endl;
202  return;
203  }
204 
205  // ++++++++++++ start up things +++++++++++++++
206 
207  physics::PhysicsEnginePtr physics = this->world->GetPhysicsEngine();
208  this->node->Init(this->world->GetName());
209  physics::ContactManager * contactManager = physics->GetContactManager();
210  contactManager->PublishContacts(); //XXX not sure I need this?
211 
212  std::string topic = contactManager->CreateFilter(model->GetScopedName(), collisionNames);
213  if (!this->contactSub) {
214  std::cout<<"Subscribing contact manager to topic "<<topic<<std::endl;
215  bool latching=false;
216  this->contactSub = this->node->Subscribe(topic,&GazeboGraspFix::OnContact, this, latching);
217  }
218 
219  update_connection=event::Events::ConnectWorldUpdateEnd(boost::bind(&GazeboGraspFix::OnUpdate, this));
220 }
221 
222 
224 {
225 public:
226 
227  // all forces effecting on the object
228  std::vector<gazebo::math::Vector3> appliedForces;
229 
230  // all grippers involved in the process, along with
231  // a number counting the number of contact points with the
232  // object per gripper
233  std::map<std::string, int> grippersInvolved;
234 
235  // maximum number of contacts of *any one* gripper
236  // (any in grippersInvolved)
238 
239  // the gripper for maxGripperContactCnt
240  std::string maxContactGripper;
241 };
242 
243 
244 
245 bool GazeboGraspFix::isGripperLink(const std::string& linkName, std::string& gripperName) const
246 {
247  for (std::map<std::string, GazeboGraspGripper>::const_iterator it=grippers.begin(); it!=grippers.end(); ++it)
248  {
249  if (it->second.hasLink(linkName))
250  {
251  gripperName=it->first;
252  return true;
253  }
254  }
255  return false;
256 }
257 
258 std::map<std::string, std::string> GazeboGraspFix::getAttachedObjects() const
259 {
260  std::map<std::string, std::string> ret;
261  for (std::map<std::string, GazeboGraspGripper>::const_iterator it=grippers.begin(); it!=grippers.end(); ++it)
262  {
263  const std::string& gripperName = it->first;
264  const GazeboGraspGripper& gripper = it->second;
265  if (gripper.isObjectAttached())
266  {
267  ret[gripper.attachedObject()]=gripperName;
268  }
269  }
270  return ret;
271 }
272 
273 
274 
275 
276 
277 bool GazeboGraspFix::objectAttachedToGripper(const ObjectContactInfo& objContInfo, std::string& attachedToGripper) const
278 {
279  for (std::map<std::string, int>::const_iterator gripInvIt=objContInfo.grippersInvolved.begin();
280  gripInvIt != objContInfo.grippersInvolved.end(); ++gripInvIt)
281  {
282  const std::string& gripperName=gripInvIt->first;
283  if (objectAttachedToGripper(gripperName, attachedToGripper))
284  {
285  return true;
286  }
287  }
288  return false;
289 }
290 
291 bool GazeboGraspFix::objectAttachedToGripper(const std::string& gripperName, std::string& attachedToGripper) const
292 {
293  std::map<std::string, GazeboGraspGripper>::const_iterator gIt=grippers.find(gripperName);
294  if (gIt == grippers.end())
295  {
296  gzerr << "GazeboGraspFix: Inconsistency, gripper "<<gripperName<<" not found in GazeboGraspFix grippers"<<std::endl;
297  return false;
298  }
299  const GazeboGraspGripper& gripper = gIt->second;
300  // std::cout<<"Gripper "<<gripperName<<" is involved in the grasp"<<std::endl;
301  if (gripper.isObjectAttached())
302  {
303  attachedToGripper = gripperName;
304  return true;
305  }
306  return false;
307 }
308 
309 
324 public:
325  CollidingPoint(): sum(0) {}
327  gripperName(o.gripperName),
328  collLink(o.collLink),
329  collObj(o.collObj),
330  force(o.force),
331  pos(o.pos),
332  objPos(o.objPos),
333  sum(o.sum){}
334 
335  // Name of the gripper/arm involved in contact point
336  // This is not the specific link, but the name of the
337  // whole gripper
338  std::string gripperName;
339 
340  // the collision
341  physics::CollisionPtr collLink, collObj;
342 
343  // average force vector of the colliding point
344  gazebo::math::Vector3 force;
345 
346  // position (relative to reference frame of gripper
347  // collision surface) where the contact happens on collision surface
348  gazebo::math::Vector3 pos;
349 
350  // position (relative to reference frame of *gripper* collision surface)
351  // where the object center is located during collision.
352  gazebo::math::Vector3 objPos;
353 
354  // sum of force and pose (they are actually summed
355  // up from several contact points).
356  // Divide both \e force and \e pos by this to obtain average
357  int sum;
358 };
359 
360 
361 
363  if ((common::Time::GetWallTime() - this->prevUpdateTime) < this->updateRate)
364  return;
365 
366  // first, copy all contact data into local struct. Don't do the complex grip check (checkGrip)
367  // within the mutex, because that slows down OnContact().
368  this->mutexContacts.lock();
369  std::map<std::string, std::map<std::string, CollidingPoint> > contPoints(this->contacts);
370  this->contacts.clear(); // clear so it can be filled anew by OnContact().
371  this->mutexContacts.unlock();
372 
373  // contPoints now contains CollidingPoint objects for each *object* and *link*.
374 
375 
376  // Iterate through all contact points to gather all summed forces
377  // (and other useful information) for all the objects (so we have all forces on one object).
378  std::map<std::string, std::map<std::string, CollidingPoint> >::iterator objIt;
379  std::map<std::string, ObjectContactInfo> objectContactInfo;
380 
381  for (objIt=contPoints.begin(); objIt!=contPoints.end(); ++objIt)
382  {
383  std::string objName=objIt->first;
384  //std::cout<<"Examining object collisions with "<<objName<<std::endl;
385 
386  // create new entry in accumulated results map and get reference to fill in:
387  ObjectContactInfo& objContInfo = objectContactInfo[objName];
388 
389  // for all links colliding with this object...
390  std::map<std::string, CollidingPoint>::iterator lIt;
391  for (lIt=objIt->second.begin(); lIt!=objIt->second.end(); ++lIt){
392  std::string linkName=lIt->first;
393  CollidingPoint& collP=lIt->second;
394  gazebo::math::Vector3 avgForce=collP.force/collP.sum;
395  // std::cout << "Found collision with "<<linkName<<": "<<avgForce.x<<", "<<avgForce.y<<", "<<avgForce.z<<" (avg over "<<collP.sum<<")"<<std::endl;
396  objContInfo.appliedForces.push_back(avgForce);
397  // insert the gripper (if it doesn't exist yet) and increase contact counter
398  int& gContactCnt = objContInfo.grippersInvolved[collP.gripperName];
399  gContactCnt++;
400  int& _maxGripperContactCnt=objContInfo.maxGripperContactCnt;
401  if (gContactCnt > _maxGripperContactCnt)
402  {
403  _maxGripperContactCnt = gContactCnt;
404  objContInfo.maxContactGripper=collP.gripperName;
405  }
406  }
407  }
408 
409  // ++++++++++++++++++++ Handle Attachment +++++++++++++++++++++++++++++++
410 
411  // collect of all objects which are found to be "gripped" at the current stage.
412  // if they are gripped, increase the grip counter. If the grip count exceeds the
413  // threshold, attach the object to the gripper which has most contact points with the
414  // object.
415  std::set<std::string> grippedObjects;
416  for (std::map<std::string, ObjectContactInfo>::iterator ocIt=objectContactInfo.begin();
417  ocIt!=objectContactInfo.end(); ++ocIt)
418  {
419  const std::string& objName=ocIt->first;
420  const ObjectContactInfo& objContInfo = ocIt->second;
421 
422  // std::cout<<"Number applied forces on "<<objName<<": "<<objContInfo.appliedForces.size()<<std::endl;
423 
424  float minAngleDiff= this->forcesAngleTolerance; //120 * M_PI/180;
425  if (!checkGrip(objContInfo.appliedForces, minAngleDiff, 0.3))
426  continue;
427 
428  // add to "gripped objects"
429  grippedObjects.insert(objName);
430 
431  //std::cout<<"Grasp Held: "<<objName<<" grip count: "<<this->gripCounts[objName]<<std::endl;
432 
433  int& counts = this->gripCounts[objName];
434  if (counts < this->maxGripCount) ++counts;
435 
436  // only need to attach object if the grip count threshold is exceeded
437  if (counts <= this->gripCountThreshold)
438  continue;
439 
440  //std::cout<<"GRIPPING "<<objName<<", grip count "<<counts<<" (threshold "<<this->gripCountThreshold<<")"<<std::endl;
441 
442  // find out if any of the grippers involved in the grasp is already grasping the object.
443  // If there is no such gripper, attach it to the gripper which has most contact points.
444  std::string attachedToGripper;
445  bool isAttachedToGripper=objectAttachedToGripper(objContInfo, attachedToGripper);
446  if (isAttachedToGripper)
447  { // the object is already attached to a gripper, so it does not need to be attached.
448  // std::cout << "GazeboGraspFix has found that object "<<
449  // gripper.attachedObject()<<" is already attached to gripper "<<gripperName;
450  continue;
451  }
452 
453  // attach the object to the gripper with most contact counts
454  const std::string& graspingGripperName = objContInfo.maxContactGripper;
455  std::map<std::string, GazeboGraspGripper>::iterator gIt=grippers.find(graspingGripperName);
456  if (gIt == grippers.end())
457  {
458  gzerr << "GazeboGraspFix: Inconsistency, gripper '"<<graspingGripperName
459  << "' not found in GazeboGraspFix grippers, so cannot do attachment of object " << objName << std::endl;
460  continue;
461  }
462  GazeboGraspGripper& graspingGripper = gIt->second;
463 
464  if (graspingGripper.isObjectAttached())
465  {
466  gzerr<<"GazeboGraspFix has found that object "<<
467  graspingGripper.attachedObject()<<" is already attached to gripper "<<
468  graspingGripperName<<", so can't grasp '"<<objName<<"'!"<<std::endl;
469  continue;
470  }
471 
472  std::cout<<"GazeboGraspFix: Attaching "<<objName<<" to gripper "<<graspingGripperName<<"!!!!!!!"<<std::endl;
473 
474  // Store the array of contact poses which played part in the grip, sorted by colliding link.
475  // Filter out all link names of other grippers, otherwise if the other gripper moves
476  // away, this is going to trigger the release condition.
477  // XXX this does not consider full support for an object being gripped by two grippers (e.g.
478  // one left, one right).
479  // this->attachGripContacts[objName]=contPoints[objName];
480  const std::map<std::string, CollidingPoint>& contPointsTmp = contPoints[objName];
481  std::map<std::string, CollidingPoint>& attGripConts = this->attachGripContacts[objName];
482  attGripConts.clear();
483  std::map<std::string, CollidingPoint>::const_iterator contPointsIt;
484  for (contPointsIt=contPointsTmp.begin(); contPointsIt!=contPointsTmp.end(); ++contPointsIt)
485  {
486  const std::string& collidingLink = contPointsIt->first;
487  const CollidingPoint& collidingPoint = contPointsIt->second;
488  // std::cout<<"Checking initial contact with "<<collidingLink<<" and "<<graspingGripperName<<std::endl;
489  if (graspingGripper.hasCollisionLink(collidingLink))
490  {
491  // std::cout<<"Insert initial contact with "<<collidingLink<<std::endl;
492  attGripConts[collidingLink] = collidingPoint;
493  }
494  }
495 
496  if (!graspingGripper.HandleAttach(objName)){
497  gzerr<<"GazeboGraspFix: Could not attach object "<<objName<<" to gripper "<<graspingGripperName<<std::endl;
498  }
499  this->OnAttach(objName, graspingGripperName);
500  } // for all objects
501 
502 
503 
504  // ++++++++++++++++++++ Handle Detachment +++++++++++++++++++++++++++++++
505  std::map<std::string, std::string> attachedObjects = getAttachedObjects();
506 
507  // now, for all objects that are not currently gripped,
508  // decrease grip counter, and possibly release object.
509  std::map<std::string, int>::iterator gripCntIt;
510  for (gripCntIt = this->gripCounts.begin(); gripCntIt != this->gripCounts.end(); ++gripCntIt){
511 
512  const std::string& objName=gripCntIt->first;
513 
514  if (grippedObjects.find(objName) != grippedObjects.end())
515  { // this object is one we just detected as "gripped", so no need to check for releasing it...
516  // std::cout<<"NOT considering "<<objName<<" for detachment."<<std::endl;
517  continue;
518  }
519 
520  // the object does not satisfy "gripped" criteria, so potentially has to be released.
521 
522  // std::cout<<"NOT-GRIPPING "<<objName<<", grip count "<<gripCntIt->second<<" (threshold "<<this->gripCountThreshold<<")"<<std::endl;
523 
524  if (gripCntIt->second > 0) --(gripCntIt->second);
525 
526  std::map<std::string, std::string>::iterator attIt = attachedObjects.find(objName);
527  bool isAttached = (attIt != attachedObjects.end());
528 
529  // std::cout<<"is attached: "<<isAttached<<std::endl;
530 
531  if (!isAttached || (gripCntIt->second > this->gripCountThreshold)) continue;
532 
533  const std::string& graspingGripperName=attIt->second;
534 
535  // std::cout<<"Considering "<<objName<<" for detachment."<<std::endl;
536 
537  // Object should potentially be detached now.
538  // However, this happens too easily when just considering the count, as the fingers
539  // in gazebo start wobbling as the arm moves around, and although they are still
540  // close to the object, the grip is not detected any more. So to be sure, we will
541  // check that the collision point (the place on the link where the contact originally
542  // was detected) has not moved too far from where it originally was, relative to the object.
543 
544  // get the initial set of CollidingPoints for this object
545  // note that it is enough to use the initial contact points, because the object won't
546  // have "slipped" after being attached, and the location of the original contact point
547  // on the link itself is considered as a fixed point on the link, regardless whether this
548  // point is currently still colliding with the object or not. We only want to know whether
549  // this fixed point on the link has increased in distance from the corresponding fixed
550  // point (where the contact originally happened) on the object.
551  std::map<std::string, std::map<std::string, CollidingPoint> >::iterator initCollIt=this->attachGripContacts.find(objName);
552  if (initCollIt == this->attachGripContacts.end()) {
553  std::cerr<<"ERROR: Consistency: Could not find attachGripContacts for "<<objName<<std::endl;
554  continue;
555  }
556 
557  std::map<std::string, CollidingPoint>& initColls=initCollIt->second;
558  int cntRelease=0;
559 
560  // for all links which have initially been detected to collide:
561  std::map<std::string, CollidingPoint>::iterator pointIt;
562  for (pointIt=initColls.begin(); pointIt!=initColls.end(); ++pointIt)
563  {
564  CollidingPoint& cpInfo=pointIt->second;
565  // initial distance from link to contact point (relative to link)
566  gazebo::math::Vector3 relContactPos=cpInfo.pos/cpInfo.sum;
567  // initial distance from link to object (relative to link)
568  gazebo::math::Vector3 relObjPos=cpInfo.objPos/cpInfo.sum;
569 
570  // get current world pose of object
571  gazebo::math::Pose currObjWorldPose=cpInfo.collObj->GetLink()->GetWorldPose();
572 
573  // get world pose of link
574  gazebo::math::Pose currLinkWorldPose=cpInfo.collLink->GetLink()->GetWorldPose();
575 
576  // Get transform for currLinkWorldPose as matrix
577  gazebo::math::Matrix4 worldToLink=currLinkWorldPose.rot.GetAsMatrix4();
578  worldToLink.SetTranslate(currLinkWorldPose.pos);
579 
580  // Get the transform from collision link to contact point
581  gazebo::math::Matrix4 linkToContact=gazebo::math::Matrix4::IDENTITY;
582  linkToContact.SetTranslate(relContactPos);
583 
584  // the current world position of the contact point right now is:
585  gazebo::math::Matrix4 _currContactWorldPose=worldToLink*linkToContact;
586  gazebo::math::Vector3 currContactWorldPose=_currContactWorldPose.GetTranslation();
587 
588  // the initial contact point location on the link should still correspond
589  // to the initial contact point location on the object.
590 
591  // initial vector from object center to contact point (relative to link,
592  // because relObjPos and relContactPos are from center of link)
593  gazebo::math::Vector3 oldObjDist= relContactPos - relObjPos;
594  // the same vector as \e oldObjDist, but calculated by the current world pose
595  // of object and the current location of the initial contact location on the link.
596  gazebo::math::Vector3 newObjDist= currContactWorldPose - currObjWorldPose.pos; // new distance from contact to object
597 
598  //std::cout<<"Obj Trans "<<cpInfo.collLink->GetName()<<": "<<relObjPos.x<<", "<<relObjPos.y<<", "<<relObjPos.z<<std::endl;
599  //std::cout<<"Cont Trans "<<cpInfo.collLink->GetName()<<": "<<relContactPos.x<<", "<<relContactPos.y<<", "<<relContactPos.z<<std::endl;
600 
601  // the difference between these vectors should not be too large...
602  float diff=fabs(oldObjDist.GetLength() - newObjDist.GetLength());
603  //std::cout<<"Diff for link "<<cpInfo.collLink->GetName()<<": "<<diff<<std::endl;
604 
605  if (diff > releaseTolerance) {
606  ++cntRelease;
607  }
608  }
609 
610  if (cntRelease > 0)
611  { // sufficient links did not meet the criteria to be close enough to the object.
612  // First, get the grasping gripper:
613  std::map<std::string, GazeboGraspGripper>::iterator gggIt = grippers.find(graspingGripperName);
614  if (gggIt == grippers.end())
615  {
616  gzerr << "GazeboGraspFix: Inconsistency: Gazebo gripper '"<<graspingGripperName<<"' not found when checking for detachment" << std::endl;
617  continue;
618  }
619  GazeboGraspGripper& graspingGripper = gggIt->second;
620  // Now, detach the object:
621  std::cout<<"GazeboGraspFix: Detaching "<<objName<<" from gripper "<<graspingGripperName<<"!!!!!!!"<<std::endl;
622  graspingGripper.HandleDetach(objName);
623  this->OnDetach(objName,graspingGripperName);
624  gripCntIt->second=0;
625  this->attachGripContacts.erase(initCollIt);
626  }
627  }
628 
629  this->prevUpdateTime = common::Time::GetWallTime();
630 }
631 
632 double angularDistance(const gazebo::math::Vector3& _v1, const gazebo::math::Vector3& _v2) {
633  gazebo::math::Vector3 v1=_v1;
634  gazebo::math::Vector3 v2=_v2;
635  v1.Normalize();
636  v2.Normalize();
637  return acos(v1.Dot(v2));
638 }
639 
640 bool GazeboGraspFix::checkGrip(const std::vector<gazebo::math::Vector3>& forces, float minAngleDiff, float lengthRatio){
641  if (((lengthRatio > 1) || (lengthRatio < 0)) && (lengthRatio > 1e-04 && (fabs(lengthRatio-1) > 1e-04))) {
642  std::cerr<<"ERROR: checkGrip: always specify a lengthRatio of [0..1]"<<std::endl;
643  return false;
644  }
645  if (minAngleDiff < M_PI_2){
646  std::cerr<<"ERROR: checkGrip: min angle must be at least 90 degrees (PI/2)"<<std::endl;
647  return false;
648  }
649  std::vector<gazebo::math::Vector3>::const_iterator it1, it2;
650  for (it1=forces.begin(); it1!=forces.end(); ++it1){
651  gazebo::math::Vector3 v1=*it1;
652  for (it2=it1+1; it2!=forces.end(); ++it2){
653  gazebo::math::Vector3 v2=*it2;
654  float l1=v1.GetLength();
655  float l2=v2.GetLength();
656  if ((l1<1e-04) || (l2<1e-04)) continue;
657  /*gazebo::math::Vector3 _v1=v1;
658  gazebo::math::Vector3 _v2=v2;
659  _v1/=l1;
660  _v2/=l2;
661  float angle=acos(_v1.Dot(_v2));*/
662  float angle=angularDistance(v1, v2);
663  // std::cout<<"Angular distance between v1.len="<<v1.GetLength()<<" and v2.len="<<v2.GetLength()<<": "<<angle*180/M_PI<<std::endl;
664  if (angle > minAngleDiff) {
665  float ratio;
666  if (l1>l2) ratio=l2/l1;
667  else ratio=l1/l2;
668  // std::cout<<"Got angle "<<angle<<", ratio "<<ratio<<std::endl;
669  if (ratio >= lengthRatio)
670  {
671  // std::cout<<"checkGrip() is true"<<std::endl;
672  return true;
673  }
674  }
675  }
676  }
677  return false;
678 }
679 
680 void GazeboGraspFix::OnContact(const ConstContactsPtr &_msg)
681 {
682  //std::cout<<"CONTACT! "<<std::endl;//<<_contact<<std::endl;
683  // for all contacts...
684  for (int i = 0; i < _msg->contact_size(); ++i) {
685  physics::CollisionPtr collision1 = boost::dynamic_pointer_cast<physics::Collision>(
686  this->world->GetEntity(_msg->contact(i).collision1()));
687  physics::CollisionPtr collision2 = boost::dynamic_pointer_cast<physics::Collision>(
688  this->world->GetEntity(_msg->contact(i).collision2()));
689 
690  if ((collision1 && !collision1->IsStatic()) && (collision2 && !collision2->IsStatic()))
691  {
692  std::string name1 = collision1->GetScopedName();
693  std::string name2 = collision2->GetScopedName();
694 
695  //std::cout<<"OBJ CONTACT! "<<name1<<" / "<<name2<<std::endl;
696  int count = _msg->contact(i).position_size();
697 
698  // Check to see if the contact arrays all have the same size.
699  if ((count != _msg->contact(i).normal_size()) ||
700  (count != _msg->contact(i).wrench_size()) ||
701  (count != _msg->contact(i).depth_size()))
702  {
703  gzerr << "GazeboGraspFix: Contact message has invalid array sizes\n"<<std::endl;
704  continue;
705  }
706 
707  std::string collidingObjName, collidingLink, gripperOfCollidingLink;
708  physics::CollisionPtr linkCollision;
709  physics::CollisionPtr objCollision;
710 
711  physics::Contact contact;
712  contact = _msg->contact(i);
713 
714  if (contact.count<1)
715  {
716  std::cerr<<"ERROR: GazeboGraspFix: Not enough forces given for contact of ."<<name1<<" / "<<name2<<std::endl;
717  continue;
718  }
719 
720  // all force vectors which are part of this contact
721  std::vector<gazebo::math::Vector3> force;
722 
723  // find out which part of the colliding entities is the object, *not* the gripper,
724  // and copy all the forces applied to it into the vector 'force'.
725  std::map<std::string,std::string>::const_iterator gripperCollIt = this->collisions.find(name2);
726  if (gripperCollIt != this->collisions.end())
727  { // collision 1 is the object
728  collidingObjName=name1;
729  collidingLink=name2;
730  linkCollision=collision2;
731  objCollision=collision1;
732  gripperOfCollidingLink=gripperCollIt->second;
733  for (int k=0; k<contact.count; ++k)
734  force.push_back(contact.wrench[k].body1Force);
735  }
736  else if ((gripperCollIt=this->collisions.find(name1)) != this->collisions.end())
737  { // collision 2 is the object
738  collidingObjName=name2;
739  collidingLink=name1;
740  linkCollision=collision1;
741  objCollision=collision2;
742  gripperOfCollidingLink=gripperCollIt->second;
743  for (int k=0; k<contact.count; ++k)
744  force.push_back(contact.wrench[k].body2Force);
745  }
746 
747  gazebo::math::Vector3 avgForce;
748  // compute average/sum of the forces applied on the object
749  for (int k=0; k<force.size(); ++k){
750  avgForce+=force[k];
751  }
752  avgForce/=force.size();
753 
754  gazebo::math::Vector3 avgPos;
755  // compute center point (average pose) of all the origin positions of the forces appied
756  for (int k=0; k<contact.count; ++k) avgPos+=contact.positions[k];
757  avgPos/=contact.count;
758 
759  // now, get average pose relative to the colliding link
760  gazebo::math::Pose linkWorldPose=linkCollision->GetLink()->GetWorldPose();
761 
762  // To find out the collision point relative to the Link's local coordinate system, first get the Poses as 4x4 matrices
763  gazebo::math::Matrix4 worldToLink=linkWorldPose.rot.GetAsMatrix4();
764  worldToLink.SetTranslate(linkWorldPose.pos);
765 
766  gazebo::math::Matrix4 worldToContact=gazebo::math::Matrix4::IDENTITY;
767  //we can assume that the contact has identity rotation because we don't care about its orientation.
768  //We could always set another rotation here too.
769  worldToContact.SetTranslate(avgPos);
770 
771  // now, worldToLink * contactInLocal = worldToContact
772  // hence, contactInLocal = worldToLink.Inv * worldToContact
773  gazebo::math::Matrix4 worldToLinkInv = worldToLink.Inverse();
774  gazebo::math::Matrix4 contactInLocal = worldToLinkInv * worldToContact;
775  gazebo::math::Vector3 contactPosInLocal = contactInLocal.GetTranslation();
776 
777  //std::cout<<"---------"<<std::endl;
778  //std::cout<<"CNT in loc: "<<contactPosInLocal.x<<","<<contactPosInLocal.y<<","<<contactPosInLocal.z<<std::endl;
779 
780  /*gazebo::math::Vector3 sDiff=avgPos-linkWorldPose.pos;
781  std::cout<<"SIMPLE trans: "<<sDiff.x<<","<<sDiff.y<<","<<sDiff.z<<std::endl;
782  std::cout<<"coll world pose: "<<linkWorldPose.pos.x<<", "<<linkWorldPose.pos.y<<", "<<linkWorldPose.pos.z<<std::endl;
783  std::cout<<"contact avg pose: "<<avgPos.x<<", "<<avgPos.y<<", "<<avgPos.z<<std::endl;
784 
785  gazebo::math::Vector3 lX=linkWorldPose.rot.GetXAxis();
786  gazebo::math::Vector3 lY=linkWorldPose.rot.GetYAxis();
787  gazebo::math::Vector3 lZ=linkWorldPose.rot.GetZAxis();
788 
789  std::cout<<"World ori: "<<linkWorldPose.rot.x<<","<<linkWorldPose.rot.y<<","<<linkWorldPose.rot.z<<","<<linkWorldPose.rot.w<<std::endl;
790  std::cout<<"x axis: "<<lX.x<<","<<lX.y<<","<<lX.z<<std::endl;
791  std::cout<<"y axis: "<<lY.x<<","<<lY.y<<","<<lY.z<<std::endl;
792  std::cout<<"z axis: "<<lZ.x<<","<<lZ.y<<","<<lZ.z<<std::endl;*/
793 
794  // now, get the pose of the object and compute it's relative position to the collision surface.
795  gazebo::math::Pose objWorldPose = objCollision->GetLink()->GetWorldPose();
796  gazebo::math::Matrix4 worldToObj = objWorldPose.rot.GetAsMatrix4();
797  worldToObj.SetTranslate(objWorldPose.pos);
798 
799  gazebo::math::Matrix4 objInLocal = worldToLinkInv * worldToObj;
800  gazebo::math::Vector3 objPosInLocal = objInLocal.GetTranslation();
801 
802  {
803  boost::mutex::scoped_lock lock(this->mutexContacts);
804  CollidingPoint& p = this->contacts[collidingObjName][collidingLink]; // inserts new entry if doesn't exist
805  p.gripperName=gripperOfCollidingLink;
806  p.collLink=linkCollision;
807  p.collObj=objCollision;
808  p.force+=avgForce;
809  p.pos+=contactPosInLocal;
810  p.objPos+=objPosInLocal;
811  p.sum++;
812  }
813  //std::cout<<"Average force of contact= "<<avgForce.x<<", "<<avgForce.y<<", "<<avgForce.z<<" out of "<<force.size()<<" vectors."<<std::endl;
814  }
815  }
816 }
817 
818 
#define DEFAULT_RELEASE_TOLERANCE
double angularDistance(const gazebo::math::Vector3 &_v1, const gazebo::math::Vector3 &_v2)
std::map< std::string, int > grippersInvolved
bool isGripperLink(const std::string &linkName, std::string &gripperName) const
std::vector< gazebo::math::Vector3 > appliedForces
std::map< std::string, std::string > collisions
void HandleDetach(const std::string &objName)
std::map< std::string, std::map< std::string, CollidingPoint > > attachGripContacts
#define DEFAULT_DISABLE_COLLISIONS_ON_ATTACH
common::Time prevUpdateTime
transport::NodePtr node
bool checkGrip(const std::vector< math::Vector3 > &forces, float minAngleDiff, float lengthRatio)
virtual void OnDetach(const std::string &objectName, const std::string &armName)
#define M_PI
CollidingPoint(const CollidingPoint &o)
const std::string & attachedObject() const
#define DEFAULT_FORCES_ANGLE_TOLERANCE
#define DEFAULT_MAX_GRIP_COUNT
#define M_PI_2
#define DEFAULT_UPDATE_RATE
physics::WorldPtr world
virtual void OnAttach(const std::string &objectName, const std::string &armName)
std::map< std::string, int > gripCounts
void OnContact(const ConstContactsPtr &ptr)
std::map< std::string, GazeboGraspGripper > grippers
Helper class for GazeboGraspFix which holds information for one arm. Attaches /detaches objects to th...
bool HandleAttach(const std::string &objName)
std::map< std::string, std::map< std::string, CollidingPoint > > contacts
bool Init(physics::ModelPtr &_model, const std::string &_gripperName, const std::string &palmLinkName, const std::vector< std::string > &fingerLinkNames, bool _disableCollisionsOnAttach, std::map< std::string, physics::CollisionPtr > &_collisions)
bool objectAttachedToGripper(const ObjectContactInfo &objContInfo, std::string &attachedToGripper) const
boost::mutex mutexContacts
event::ConnectionPtr update_connection
transport::SubscriberPtr contactSub
bool hasCollisionLink(const std::string &linkName) const
std::map< std::string, std::string > getAttachedObjects() const
virtual void Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
int ALVAR_EXPORT diff(const std::vector< C > &v, std::vector< C > &ret)
double ALVAR_EXPORT angle(CvPoint *A, CvPoint *B, CvPoint *C, CvPoint *D, int isDirectionDependent)


robotican_common
Author(s):
autogenerated on Wed Jan 3 2018 03:48:33