GazeboGripper.cpp
Go to the documentation of this file.
00001 #include "r2_gazebo_gripper/GazeboGripper.h"
00002 #include <gazebo/physics/physics.hh>
00003 #include <gazebo/transport/transport.hh>
00004 
00005 using namespace gazebo;
00006 
00007 GazeboGripper::GazeboGripper()
00008     : ModelPlugin()
00009     , attached(false)
00010     , contactDuration(0.)
00011     , nonContactDuration(0.)
00012 {
00013 }
00014 
00015 GazeboGripper::~GazeboGripper()
00016 {
00017 }
00018 
00019 void GazeboGripper::Load(physics::ModelPtr _model, sdf::ElementPtr _sdf)
00020 {
00021     // Store the pointer to the model
00022     modelPtr = _model;
00023 
00024     prevUpdateTime = _model->GetWorld()->GetSimTime();
00025     prevContactUpdateTime = prevUpdateTime;
00026 
00027     if (!_sdf->HasAttribute("name"))
00028     {
00029         ROS_WARN("GazeboGripper: Plugin name missing");
00030         pluginName = "GazeboGripperPlugin";
00031     }
00032     else
00033         pluginName = _sdf->GetAttribute("name")->GetAsString().c_str();
00034     ROS_INFO("Loading GazeboGripper plugin '%s'", pluginName.c_str());
00035 
00036     // get params
00037     if (!_sdf->HasElement("updateRate"))
00038     {
00039         ROS_INFO("%s: plugin missing <updateRate>, default to 1000", pluginName.c_str());
00040         updateTime = 1 / 1000;
00041     }
00042     else
00043     {
00044         updateTime = 1 / (_sdf->GetElement("updateRate")->Get<double>());
00045     }
00046 
00047     if (!_sdf->HasElement("attachWait"))
00048     {
00049         ROS_FATAL("%s: plugin missing <attachWait>, cannot proceed", pluginName.c_str());
00050         return;
00051     }
00052     else
00053     {
00054         attachWait = _sdf->GetElement("attachWait")->Get<double>();
00055     }
00056 
00057     if (!_sdf->HasElement("detachWait"))
00058     {
00059         ROS_FATAL("%s: plugin missing <detachWait>, cannot proceed", pluginName.c_str());
00060         return;
00061     }
00062     else
00063     {
00064         detachWait = _sdf->GetElement("detachWait")->Get<double>();
00065     }
00066 
00067     if (!_sdf->HasElement("maxRelativeMotionRate"))
00068     {
00069         ROS_FATAL("%s: plugin missing <maxRelativeMotionRate>, cannot proceed", pluginName.c_str());
00070         return;
00071     }
00072     else
00073     {
00074         maxRelativeMotionRate = _sdf->GetElement("maxRelativeMotionRate")->Get<double>();
00075     }
00076 
00077     if (!_sdf->HasElement("gripperAttachLink"))
00078     {
00079         ROS_FATAL("%s: plugin missing <gripperAttachLink>, cannot proceed", pluginName.c_str());
00080         return;
00081     }
00082     else
00083     {
00084         gripperAttachLink = _sdf->GetElement("gripperAttachLink")->Get<std::string>();
00085 
00086         if (!modelPtr->GetLink(gripperAttachLink))
00087         {
00088             ROS_FATAL((std::string("%s: plugin couldn't find gripperAttachLink (%s) in model, cannot proceed.\n")
00089                        + "\tLinks connected with static joints may be combined into one by the URDF parser.").c_str(),
00090                       pluginName.c_str(), gripperAttachLink.c_str());
00091             return;
00092         }
00093 
00094         ROS_INFO("%s: gripperAttachLink: %s", pluginName.c_str(), gripperAttachLink.c_str());
00095     }
00096 
00097     if (!_sdf->HasElement("gripperLink"))
00098     {
00099         ROS_FATAL("%s: plugin missing <gripperLink>, cannot proceed", pluginName.c_str());
00100         return;
00101     }
00102 
00103     std::vector<physics::LinkPtr> links;
00104     sdf::ElementPtr linkElem = _sdf->GetElement("gripperLink");
00105 
00106     while (linkElem)
00107     {
00108         physics::LinkPtr link;
00109 
00110         if (link = modelPtr->GetLink(linkElem->Get<std::string>()))
00111         {
00112             links.push_back(link);
00113             ROS_DEBUG("%s: added gripperLink: %s", linkElem->Get<std::string>().c_str(), pluginName.c_str());
00114         }
00115         else
00116         {
00117             ROS_FATAL((std::string("%s: plugin couldn't find gripperLink (%s) in model, cannot proceed.\n")
00118                        + "\tLinks connected with static joints may be combined into one by the URDF parser.").c_str(),
00119                       pluginName.c_str(), linkElem->Get<std::string>().c_str());
00120             return;
00121         }
00122 
00123         linkElem = linkElem->GetNextElement("gripperLink");
00124     }
00125 
00126     if (links.size() < 2)
00127     {
00128         ROS_FATAL("%s: plugin requires at least two gripperLinks, cannot proceed", pluginName.c_str());
00129         return;
00130     }
00131 
00132     fixedJointPtr = modelPtr->GetWorld()->GetPhysicsEngine()->CreateJoint("revolute");
00133     fixedJointPtr->SetName(pluginName + "_joint");
00134 
00135     collisionNames.clear();
00136 
00137     // iterate through links we care about contacts for and setup a filter in the contact manager
00138     for (std::vector<physics::LinkPtr>::iterator linkIt = links.begin(); linkIt != links.end(); ++linkIt)
00139     {
00140         for (unsigned int j = 0; j < (*linkIt)->GetChildCount(); ++j)
00141         {
00142             physics::CollisionPtr collision = (*linkIt)->GetCollision(j);
00143             collisionNames.push_back(collision->GetScopedName());
00144             ROS_DEBUG("%s: Added collision '%s'", pluginName.c_str(), collision->GetScopedName().c_str());
00145         }
00146     }
00147 
00148     if (collisionNames.size())
00149     {
00150         // The contact manager provides an interface between the physics engine and the links in contact
00151         physics::ContactManager *mgr = modelPtr->GetWorld()->GetPhysicsEngine()->GetContactManager();
00152 
00153         // Filter only the contacts we care about
00154         mgr->CreateFilter(pluginName, collisionNames);
00155         std::sort(collisionNames.begin(), collisionNames.end());
00156     }
00157 
00158     // Connect a callback for when the world is updated (very regularly)
00159     worldUpdateEvent = event::Events::ConnectWorldUpdateEnd(boost::bind(&GazeboGripper::onUpdate, this));
00160 
00161     ROS_INFO("%s: plugin loaded", pluginName.c_str());
00162 }
00163 
00164 void GazeboGripper::Init()
00165 {
00166     ROS_INFO("Gazebo Gripper plugin initialized");
00167     ModelPlugin::Init();
00168 }
00169 
00170 void GazeboGripper::onUpdate()
00171 {
00172     physics::ContactManager *mgr = modelPtr->GetWorld()->GetPhysicsEngine()->GetContactManager();
00173 
00174     common::Time currTime = modelPtr->GetWorld()->GetSimTime();
00175     if ((currTime - prevUpdateTime).Double() >= updateTime)  // limit the rate at which we check contacts
00176     {
00177         prevUpdateTime = currTime;
00178 
00179         const std::vector<physics::Contact*>& contacts = mgr->GetContacts();
00180 
00181         std::vector<physics::Contact*> myContacts;
00182         for (size_t i = 0; i < contacts.size(); ++i)
00183         {
00184             // The names of the links in contact
00185             std::string name1 = contacts[i]->collision1->GetScopedName();
00186             std::string name2 = contacts[i]->collision2->GetScopedName();
00187 
00188             if (std::find(collisionNames.begin(), collisionNames.end(), name1) != collisionNames.end() ||
00189                 std::find(collisionNames.begin(), collisionNames.end(), name2) != collisionNames.end())
00190                 myContacts.push_back(contacts[i]);
00191         }
00192 
00193         handleContacts(myContacts);
00194         mgr->Clear();  // clear the contact list.  This does not happen automatically
00195     }
00196 }
00197 
00198 void GazeboGripper::handleContacts(const std::vector<physics::Contact*>& contacts)
00199 {
00200     common::Time currTime = modelPtr->GetWorld()->GetSimTime();
00201     double elapsedTime = (currTime - prevContactUpdateTime).Double();
00202     prevContactUpdateTime = currTime;
00203 
00204     // Due to jitter in the zero-G simulation, we relax the contact requirement to just one of the gripper links
00205     int minContactCount = 1;
00206     if (contacts.size() >= minContactCount)
00207     {
00208         ROS_DEBUG("%s: Contacts: %d, duration: %f, attached? %s", pluginName.c_str(), (int)contacts.size(), contactDuration+elapsedTime, attached ? "YES":"NO");
00209 
00210         nonContactDuration = 0;
00211         contactDuration += elapsedTime;
00212 
00213         // We were not attached previously, but now there are contacts.  Check to make sure there
00214         // is no relative movement for attachWait seconds.
00215         if (!attached)
00216         {
00217             // Constructing a list of world objects in contact and the number of contacts on each object
00218             std::map<std::string, physics::Collision*> cc;
00219             std::map<std::string, int> contactCounts;
00220 
00221             // identify gripper links colliding with the world parts
00222             for (unsigned int i = 0; i < contacts.size(); ++i)
00223             {
00224                 std::string name1 = contacts[i]->collision1->GetScopedName();
00225                 std::string name2 = contacts[i]->collision2->GetScopedName();
00226 
00227                 // If the link is not in collisionNames, it is part of the world
00228                 std::vector<std::string>::iterator citer = std::find(collisionNames.begin(), collisionNames.end(), name1);
00229                 if (citer == collisionNames.end())
00230                 {
00231                     cc[name1] = contacts[i]->collision1;
00232                     contactCounts[name1] += 1;
00233                 }
00234 
00235                 citer = std::find(collisionNames.begin(), collisionNames.end(), name2);
00236                 if (citer == collisionNames.end())
00237                 {
00238                     cc[name2] = contacts[i]->collision2;
00239                     contactCounts[name2] += 1;
00240                 }
00241             }
00242 
00243             // Iterate through the world links in contact.  If there are at least
00244             // minContactCount contacts, attach the gripper to the world link
00245             for(std::map<std::string, int>::iterator iter = contactCounts.begin(); iter != contactCounts.end(); ++iter)
00246             {
00247                 // Insufficient number of contacts on this link
00248                 if (iter->second < minContactCount)
00249                     continue;
00250 
00251                 // Compute the relative motion rate between the gripper and the world link in contact
00252                 double relMotionRate;
00253 
00254                 math::Pose diff = cc[iter->first]->GetLink()->GetWorldPose() - modelPtr->GetLink(gripperAttachLink)->GetWorldPose();
00255                 if (contactDuration <= elapsedTime)  // first contact with the world.  Relative motion is zero
00256                     relMotionRate = 0.0;
00257                 else
00258                     relMotionRate = (diff - prevDiff).pos.GetSquaredLength() / elapsedTime;
00259 
00260                 prevDiff = diff;
00261 
00262                 // Links are moving too fast to attach
00263                 if (relMotionRate > maxRelativeMotionRate)
00264                 {
00265                     ROS_DEBUG("%s: gripper contact relative motion too great (%f).", pluginName.c_str(), relMotionRate);
00266                     contactDuration = 0;
00267                 }
00268                 else if (contactDuration >= attachWait) // small relative motion for a sufficient amount of time
00269                 {
00270                     handleAttach(cc[iter->first]->GetLink());
00271                     break; // only handle one attachment
00272                 }
00273             }
00274         }
00275     }
00276     else  // too few contacts
00277     {
00278         contactDuration = 0;
00279 
00280         if (attached)
00281         {
00282             nonContactDuration += elapsedTime;
00283             if (nonContactDuration >= detachWait)
00284                 handleDetach();
00285         }
00286     }
00287 }
00288 
00289 void GazeboGripper::handleAttach(physics::LinkPtr linkPtr)
00290 {
00291     attached = true;
00292 
00293     fixedJointPtr->Load(modelPtr->GetLink(gripperAttachLink), linkPtr, math::Pose(0, 0, 0, 0, 0, 0));
00294     fixedJointPtr->Init();
00295     fixedJointPtr->SetHighStop(0, 0);
00296     fixedJointPtr->SetLowStop(0, 0);
00297 
00298     ROS_INFO("%s: Gripper attached", pluginName.c_str());
00299 }
00300 
00301 void GazeboGripper::handleDetach()
00302 {
00303     attached = false;
00304     fixedJointPtr->Detach();
00305     ROS_INFO("%s: Gripper detached", pluginName.c_str());
00306 }
00307 
00308 GZ_REGISTER_MODEL_PLUGIN(GazeboGripper)


r2_gazebo_gripper
Author(s):
autogenerated on Sat Jun 8 2019 20:56:17