Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef _WIN32
00018
00019
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
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
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
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
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
00284 VacuumGripperPluginPrivate::Object obj = {type, destination};
00285 this->dataPtr->drops.push_back(obj);
00286
00287 objectElem = objectElem->GetNextElement("object");
00288 }
00289 }
00290 }
00291
00292
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
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
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
00405 this->HandleDetach();
00406
00407
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
00417
00418
00419
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
00453
00454
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
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
00502 this->dataPtr->dropCurrentObject = *found;
00503
00504
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 }