VacuumGripperPlugin.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2016 Open Source Robotics Foundation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *
00016 */
00017 #ifdef _WIN32
00018   // Ensure that Winsock2.h is included before Windows.h, which can get
00019   // pulled in by anybody (e.g., Boost).
00020   #include <Winsock2.h>
00021 #endif
00022 
00023 #include <memory>
00024 #include <mutex>
00025 #include <ostream>
00026 #include <vector>
00027 #include <string>
00028 #include <gazebo/common/Events.hh>
00029 #include <gazebo/physics/Collision.hh>
00030 #include <gazebo/physics/Contact.hh>
00031 #include <gazebo/physics/ContactManager.hh>
00032 #include <gazebo/physics/Joint.hh>
00033 #include <gazebo/physics/Link.hh>
00034 #include <gazebo/physics/Model.hh>
00035 #include <gazebo/physics/PhysicsEngine.hh>
00036 #include <gazebo/physics/World.hh>
00037 #include <gazebo/transport/Node.hh>
00038 #include <gazebo/transport/Subscriber.hh>
00039 #include "osrf_gear/VacuumGripperPlugin.hh"
00040 #include "osrf_gear/ARIAC.hh"
00041 
00042 namespace gazebo
00043 {
00046   struct VacuumGripperPluginPrivate
00047   {
00049     public: class Object
00050             {
00054               public: bool operator ==(const Object &_obj) const
00055               {
00056                 return this->type == _obj.type;
00057               }
00058 
00063               public: friend std::ostream &operator<<(std::ostream &_out,
00064                                                       const Object &_obj)
00065               {
00066                 _out << _obj.type << std::endl;
00067                 _out << "  Dst: [" << _obj.destination << "]" << std::endl;
00068                 return _out;
00069               }
00070 
00072               public: std::string type;
00073 
00075               public: math::Pose destination;
00076             };
00077 
00079     public: std::vector<Object> drops;
00080 
00082     public: physics::ModelPtr model;
00083 
00085     public: physics::WorldPtr world;
00086 
00088     public: physics::JointPtr fixedJoint;
00089 
00091     public: physics::LinkPtr suctionCupLink;
00092 
00094     public: event::ConnectionPtr connection;
00095 
00097     public: std::map<std::string, physics::CollisionPtr> collisions;
00098 
00100     public: std::vector<msgs::Contact> contacts;
00101 
00103     public: std::mutex mutex;
00104 
00106     public: bool attached = false;
00107 
00109     public: common::Time updateRate;
00110 
00112     public: common::Time prevUpdateTime;
00113 
00116     public: int posCount;
00117 
00120     public: int zeroCount;
00121 
00123     public: unsigned int minContactCount;
00124 
00126     public: int attachSteps;
00127 
00129     public: int detachSteps;
00130 
00132     public: std::string name;
00133 
00135     public: transport::NodePtr node;
00136 
00138     public: transport::SubscriberPtr contactSub;
00139 
00141     public: bool enabled = false;
00142 
00144     public: bool dropPending = false;
00145 
00147     public: physics::ModelPtr dropAttachedModel;
00148 
00151     public: math::Box dropRegion;
00152 
00154     public: Object dropCurrentObject;
00155   };
00156 }
00157 
00158 using namespace gazebo;
00159 using namespace physics;
00160 
00161 GZ_REGISTER_MODEL_PLUGIN(VacuumGripperPlugin)
00162 
00163 
00164 VacuumGripperPlugin::VacuumGripperPlugin()
00165   : dataPtr(new VacuumGripperPluginPrivate)
00166 {
00167   gzmsg << "VacuumGripper plugin loaded" << std::endl;
00168 
00169   this->dataPtr->attached = false;
00170   this->dataPtr->updateRate = common::Time(0, common::Time::SecToNano(0.75));
00171 }
00172 
00174 VacuumGripperPlugin::~VacuumGripperPlugin()
00175 {
00176   if (this->dataPtr->world && this->dataPtr->world->GetRunning())
00177   {
00178     auto mgr = this->dataPtr->world->GetPhysicsEngine()->GetContactManager();
00179     mgr->RemoveFilter(this->Name());
00180   }
00181 }
00182 
00184 void VacuumGripperPlugin::Load(physics::ModelPtr _model, sdf::ElementPtr _sdf)
00185 {
00186   this->dataPtr->model = _model;
00187   this->dataPtr->world = this->dataPtr->model->GetWorld();
00188 
00189   this->dataPtr->node = transport::NodePtr(new transport::Node());
00190   this->dataPtr->node->Init(this->dataPtr->world->GetName());
00191   this->dataPtr->name = _sdf->Get<std::string>("name");
00192 
00193   // Create the joint that will attach the objects to the suction cup
00194   this->dataPtr->fixedJoint =
00195       this->dataPtr->world->GetPhysicsEngine()->CreateJoint(
00196         "fixed", this->dataPtr->model);
00197   this->dataPtr->fixedJoint->SetName(this->dataPtr->model->GetName() +
00198       "__vacuum_gripper_fixed_joint__");
00199 
00200   // Read the SDF parameters
00201   sdf::ElementPtr graspCheck = _sdf->GetElement("grasp_check");
00202   this->dataPtr->minContactCount =
00203       graspCheck->Get<unsigned int>("min_contact_count");
00204   this->dataPtr->attachSteps = graspCheck->Get<int>("attach_steps");
00205   this->dataPtr->detachSteps = graspCheck->Get<int>("detach_steps");
00206   sdf::ElementPtr suctionCupLinkElem = _sdf->GetElement("suction_cup_link");
00207   this->dataPtr->suctionCupLink =
00208     this->dataPtr->model->GetLink(suctionCupLinkElem->Get<std::string>());
00209   if (!this->dataPtr->suctionCupLink)
00210   {
00211     gzerr << "Suction cup link [" << suctionCupLinkElem->Get<std::string>()
00212           << "] not found!\n";
00213     return;
00214   }
00215 
00216   if (_sdf->HasElement("drops"))
00217   {
00218     sdf::ElementPtr dropsElem = _sdf->GetElement("drops");
00219 
00220     if (!dropsElem->HasElement("drop_region"))
00221     {
00222       gzerr << "VacuumGripperPlugin: Unable to find <drop_region> elements in "
00223             << "the <drops> section\n";
00224       return;
00225     }
00226 
00227     sdf::ElementPtr dropRegionElem = dropsElem->GetElement("drop_region");
00228 
00229     if (!dropRegionElem->HasElement("min"))
00230     {
00231       gzerr << "VacuumGripperPlugin: Unable to find <min> elements in "
00232             << "the <drop_region> section\n";
00233       return;
00234     }
00235 
00236     sdf::ElementPtr minElem = dropRegionElem->GetElement("min");
00237     gazebo::math::Vector3 min = dropRegionElem->Get<math::Vector3>("min");
00238 
00239     if (!dropRegionElem->HasElement("max"))
00240     {
00241       gzerr << "VacuumGripperPlugin: Unable to find <max> elements in "
00242             << "the <drop_region> section\n";
00243       return;
00244     }
00245 
00246     sdf::ElementPtr maxElem = dropRegionElem->GetElement("max");
00247     gazebo::math::Vector3 max = dropRegionElem->Get<math::Vector3>("max");
00248 
00249     this->dataPtr->dropRegion.min = min;
00250     this->dataPtr->dropRegion.max = max;
00251 
00252     if (!dropsElem->HasElement("object"))
00253     {
00254       gzerr << "VacuumGripperPlugin: Unable to find <object> elements in the "
00255             << "<drops> section\n";
00256     }
00257     else
00258     {
00259       sdf::ElementPtr objectElem = dropsElem->GetElement("object");
00260       while (objectElem)
00261       {
00262         // Parse the object type.
00263         if (!objectElem->HasElement("type"))
00264         {
00265           gzerr << "VacuumGripperPlugin: Unable to find <type> in object.\n";
00266           objectElem = objectElem->GetNextElement("object");
00267           continue;
00268         }
00269         sdf::ElementPtr typeElement = objectElem->GetElement("type");
00270         std::string type = typeElement->Get<std::string>();
00271 
00272         // Parse the destination.
00273         if (!objectElem->HasElement("destination"))
00274         {
00275           gzerr << "VacuumGripperPlugin: Unable to find <destination> in "
00276                 << "object\n";
00277           objectElem = objectElem->GetNextElement("destination");
00278           continue;
00279         }
00280         sdf::ElementPtr dstElement = objectElem->GetElement("destination");
00281         math::Pose destination = dstElement->Get<math::Pose>();
00282 
00283         // Add the object to the set.
00284         VacuumGripperPluginPrivate::Object obj = {type, destination};
00285         this->dataPtr->drops.push_back(obj);
00286 
00287         objectElem = objectElem->GetNextElement("object");
00288       }
00289     }
00290   }
00291 
00292   // Find out the collision elements of the suction cup
00293   for (auto j = 0u; j < this->dataPtr->suctionCupLink->GetChildCount(); ++j)
00294   {
00295     physics::CollisionPtr collision =
00296        this->dataPtr->suctionCupLink->GetCollision(j);
00297     std::map<std::string, physics::CollisionPtr>::iterator collIter
00298       = this->dataPtr->collisions.find(collision->GetScopedName());
00299     if (collIter != this->dataPtr->collisions.end())
00300       continue;
00301 
00302     this->dataPtr->collisions[collision->GetScopedName()] = collision;
00303   }
00304 
00305   if (!this->dataPtr->collisions.empty())
00306   {
00307     // Create a filter to receive collision information
00308     auto mgr = this->dataPtr->world->GetPhysicsEngine()->GetContactManager();
00309     auto topic = mgr->CreateFilter(this->Name(), this->dataPtr->collisions);
00310     if (!this->dataPtr->contactSub)
00311     {
00312       this->dataPtr->contactSub = this->dataPtr->node->Subscribe(topic,
00313           &VacuumGripperPlugin::OnContacts, this);
00314     }
00315   }
00316 
00317   this->Reset();
00318 
00319   this->dataPtr->connection = event::Events::ConnectWorldUpdateEnd(
00320       boost::bind(&VacuumGripperPlugin::OnUpdate, this));
00321 }
00322 
00324 void VacuumGripperPlugin::Reset()
00325 {
00326   this->dataPtr->prevUpdateTime = common::Time::GetWallTime();
00327   this->dataPtr->zeroCount = 0;
00328   this->dataPtr->posCount = 0;
00329   this->dataPtr->attached = false;
00330   this->dataPtr->enabled = false;
00331 }
00332 
00334 std::string VacuumGripperPlugin::Name() const
00335 {
00336   return this->dataPtr->name;
00337 }
00338 
00340 bool VacuumGripperPlugin::Enabled() const
00341 {
00342   return this->dataPtr->enabled;
00343 }
00344 
00346 bool VacuumGripperPlugin::Attached() const
00347 {
00348   return this->dataPtr->attached;
00349 }
00350 
00352 void VacuumGripperPlugin::Enable()
00353 {
00354   std::lock_guard<std::mutex> lock(this->dataPtr->mutex);
00355   this->dataPtr->enabled = true;
00356 }
00357 
00359 void VacuumGripperPlugin::Disable()
00360 {
00361   {
00362     std::lock_guard<std::mutex> lock(this->dataPtr->mutex);
00363     this->dataPtr->enabled = false;
00364   }
00365   this->HandleDetach();
00366 }
00367 
00369 void VacuumGripperPlugin::OnUpdate()
00370 {
00371   this->Publish();
00372 
00373   std::lock_guard<std::mutex> lock(this->dataPtr->mutex);
00374   if (common::Time::GetWallTime() -
00375       this->dataPtr->prevUpdateTime < this->dataPtr->updateRate ||
00376       !this->dataPtr->enabled)
00377   {
00378     return;
00379   }
00380 
00381   // @todo: should package the decision into a function
00382   if (this->dataPtr->contacts.size() >= this->dataPtr->minContactCount)
00383   {
00384     this->dataPtr->posCount++;
00385     this->dataPtr->zeroCount = 0;
00386   }
00387   else
00388   {
00389     this->dataPtr->zeroCount++;
00390     this->dataPtr->posCount = std::max(0, this->dataPtr->posCount-1);
00391   }
00392 
00393   if (this->dataPtr->posCount > this->dataPtr->attachSteps &&
00394       !this->dataPtr->attached)
00395   {
00396     this->HandleAttach();
00397   }
00398 
00399   if (this->dataPtr->attached && this->dataPtr->dropPending)
00400   {
00401     auto objPose = this->dataPtr->dropAttachedModel->GetWorldPose();
00402     if (this->dataPtr->dropRegion.Contains(objPose.pos))
00403     {
00404       // Drop the object.
00405       this->HandleDetach();
00406 
00407       // Teleport it to the destination.
00408       this->dataPtr->dropAttachedModel->SetWorldPose(
00409         this->dataPtr->dropCurrentObject.destination);
00410 
00411       this->dataPtr->dropPending = false;
00412       gzdbg << "Object dropped and teleported" << std::endl;
00413     }
00414   }
00415 
00416   // else if (this->dataPtr->zeroCount > this->dataPtr->detachSteps &&
00417   //          this->dataPtr->attached)
00418   // {
00419   //   this->HandleDetach();
00420   // }
00421 
00422   this->dataPtr->contacts.clear();
00423   this->dataPtr->prevUpdateTime = common::Time::GetWallTime();
00424 }
00425 
00427 void VacuumGripperPlugin::OnContacts(ConstContactsPtr &_msg)
00428 {
00429   std::lock_guard<std::mutex> lock(this->dataPtr->mutex);
00430   for (int i = 0; i < _msg->contact_size(); ++i)
00431   {
00432     CollisionPtr collision1 = boost::dynamic_pointer_cast<Collision>(
00433         this->dataPtr->world->GetEntity(_msg->contact(i).collision1()));
00434     CollisionPtr collision2 = boost::dynamic_pointer_cast<Collision>(
00435         this->dataPtr->world->GetEntity(_msg->contact(i).collision2()));
00436 
00437     if ((collision1 && !collision1->IsStatic()) &&
00438         (collision2 && !collision2->IsStatic()))
00439     {
00440       this->dataPtr->contacts.push_back(_msg->contact(i));
00441     }
00442   }
00443 }
00444 
00446 void VacuumGripperPlugin::HandleAttach()
00447 {
00448   std::map<std::string, physics::CollisionPtr> cc;
00449   std::map<std::string, int> contactCounts;
00450   std::map<std::string, int>::iterator iter;
00451 
00452   // This function is only called from the OnUpdate function so
00453   // the call to contacts.clear() is not going to happen in
00454   // parallel with the reads in the following code, no mutex needed.
00455   for (unsigned int i = 0; i < this->dataPtr->contacts.size(); ++i)
00456   {
00457     std::string name1 = this->dataPtr->contacts[i].collision1();
00458     std::string name2 = this->dataPtr->contacts[i].collision2();
00459 
00460     if (this->dataPtr->collisions.find(name1) ==
00461         this->dataPtr->collisions.end())
00462     {
00463       cc[name1] = boost::dynamic_pointer_cast<Collision>(
00464           this->dataPtr->world->GetEntity(name1));
00465       contactCounts[name1] += 1;
00466     }
00467 
00468     if (this->dataPtr->collisions.find(name2) ==
00469         this->dataPtr->collisions.end())
00470     {
00471       cc[name2] = boost::dynamic_pointer_cast<Collision>(
00472           this->dataPtr->world->GetEntity(name2));
00473       contactCounts[name2] += 1;
00474     }
00475   }
00476 
00477   iter = contactCounts.begin();
00478   while (iter != contactCounts.end())
00479   {
00480     if (iter->second < 2)
00481       contactCounts.erase(iter++);
00482     else
00483     {
00484       if (!this->dataPtr->attached && cc[iter->first])
00485       {
00486         this->dataPtr->attached = true;
00487 
00488         this->dataPtr->fixedJoint->Load(this->dataPtr->suctionCupLink,
00489             cc[iter->first]->GetLink(), math::Pose());
00490         this->dataPtr->fixedJoint->Init();
00491 
00492         // Check if the object should drop.
00493         auto name = cc[iter->first]->GetLink()->GetModel()->GetName();
00494         auto type = ariac::DetermineModelType(name);
00495         math::Pose dst;
00496         VacuumGripperPluginPrivate::Object attachedObj = {type, dst};
00497         auto found = std::find(std::begin(this->dataPtr->drops),
00498                                std::end(this->dataPtr->drops), attachedObj);
00499         if (found != std::end(this->dataPtr->drops))
00500         {
00501           // Save the object that is scheduled for dropping.
00502           this->dataPtr->dropCurrentObject = *found;
00503 
00504           // Remove obj from drops.
00505           this->dataPtr->drops.erase(found);
00506 
00507           this->dataPtr->dropPending = true;
00508           this->dataPtr->dropAttachedModel =
00509             cc[iter->first]->GetLink()->GetModel();
00510 
00511           gzdbg << "Drop scheduled" << std::endl;
00512         }
00513       }
00514       ++iter;
00515     }
00516   }
00517 }
00518 
00520 void VacuumGripperPlugin::HandleDetach()
00521 {
00522   this->dataPtr->attached = false;
00523   this->dataPtr->fixedJoint->Detach();
00524 }
00525 
00527 void VacuumGripperPlugin::Publish() const
00528 {
00529 }


osrf_gear
Author(s):
autogenerated on Mon Sep 5 2016 03:41:33