00001 #ifndef SimTK_SIMBODY_CONTACT_TRACKER_SUBSYSTEM_H_
00002 #define SimTK_SIMBODY_CONTACT_TRACKER_SUBSYSTEM_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "SimTKcommon.h"
00036 #include "simbody/internal/common.h"
00037 #include "simbody/internal/ContactGeometry.h"
00038 #include "simbody/internal/ContactSurface.h"
00039
00040 namespace SimTK {
00041
00042
00043 class MultibodySystem;
00044 class MobilizedBody;
00045 class ContactTracker;
00046 class Contact;
00047 class ContactSnapshot;
00048
00153
00154
00155
00156 class SimTK_SIMBODY_EXPORT ContactTrackerSubsystem : public Subsystem {
00157 public:
00158 ContactTrackerSubsystem();
00159 explicit ContactTrackerSubsystem(MultibodySystem&);
00160
00165 int getNumSurfaces() const;
00167 const MobilizedBody& getMobilizedBody(ContactSurfaceIndex surfIx) const;
00170 const ContactSurface& getContactSurface(ContactSurfaceIndex surfIx) const;
00173 const Transform& getContactSurfaceTransform(ContactSurfaceIndex surfIx) const;
00174
00180 void adoptContactTracker(ContactTracker* tracker);
00181
00185 bool hasContactTracker(ContactGeometryTypeId surface1,
00186 ContactGeometryTypeId surface2) const;
00187
00193 const ContactTracker& getContactTracker(ContactGeometryTypeId surface1,
00194 ContactGeometryTypeId surface2,
00195 bool& reverseOrder) const;
00196
00199 const ContactSnapshot& getPreviousActiveContacts(const State& state) const;
00200
00203 const ContactSnapshot& getPreviousPredictedContacts(const State& state) const;
00204
00216 const ContactSnapshot& getActiveContacts(const State& state) const;
00217
00226 const ContactSnapshot& getPredictedContacts(const State& state) const;
00227
00234 bool realizeActiveContacts(const State& state,
00235 bool lastTry,
00236 Real& stepAdvice) const;
00237
00241 bool realizePredictedContacts(const State& state,
00242 bool lastTry,
00243 Real& stepAdvice) const;
00244
00245 SimTK_PIMPL_DOWNCAST(ContactTrackerSubsystem, Subsystem);
00246
00247
00248 private:
00249 class ContactTrackerSubsystemImpl& updImpl();
00250 const ContactTrackerSubsystemImpl& getImpl() const;
00251 };
00252
00253
00254
00255
00256
00257
00268 class SimTK_SIMBODY_EXPORT ContactSnapshot {
00269
00270 typedef std::map<ContactId,int> ContactMap;
00271
00272
00273 typedef std::map<std::pair<ContactSurfaceIndex,ContactSurfaceIndex>,
00274 ContactId> SurfaceMap;
00275 public:
00277 ContactSnapshot() : m_time(NaN) {}
00278
00280 void clear() {
00281 m_time = NaN;
00282 m_contacts.clear();
00283 m_id2contact.clear();
00284 m_surfPair2id.clear();
00285 }
00286
00288 void setTimestamp(Real time) {m_time=time;}
00290 Real getTimestamp() const {return m_time;}
00291
00297 void adoptContact(Contact& contact) {
00298 const ContactId id = contact.getContactId();
00299 ContactSurfaceIndex surf1(contact.getSurface1());
00300 ContactSurfaceIndex surf2(contact.getSurface2());
00301 assert(id.isValid() && surf1.isValid() && surf2.isValid());
00302
00303
00304 if (surf1 > surf2) std::swap(surf1,surf2);
00305
00306 assert(!hasContact(id));
00307 assert(!hasContact(surf1,surf2));
00308
00309 const int indx = m_contacts.size();
00310 m_contacts.push_back(contact);
00311 m_id2contact[id] = indx;
00312 m_surfPair2id[std::make_pair(surf1,surf2)] = id;
00313 }
00314
00316 bool hasContact(ContactId id) const
00317 { return m_id2contact.find(id) != m_id2contact.end(); }
00320 bool hasContact(ContactSurfaceIndex surf1, ContactSurfaceIndex surf2) const
00321 { if (surf1 > surf2) std::swap(surf1,surf2);
00322 return m_surfPair2id.find(std::make_pair(surf1,surf2))
00323 != m_surfPair2id.end(); }
00324
00326 int getNumContacts() const {return m_contacts.size();}
00331 const Contact& getContact(int n) const {return m_contacts[n];}
00335 const Contact& getContactById(ContactId id) const
00336 { static Contact empty;
00337 ContactMap::const_iterator p = m_id2contact.find(id);
00338 return p==m_id2contact.end() ? empty : m_contacts[p->second]; }
00342 ContactId getContactIdForSurfacePair(ContactSurfaceIndex surf1,
00343 ContactSurfaceIndex surf2) const
00344 { if (surf1 > surf2) std::swap(surf1,surf2);
00345 SurfaceMap::const_iterator p =
00346 m_surfPair2id.find(std::make_pair(surf1,surf2));
00347 return p==m_surfPair2id.end() ? ContactId() : p->second; }
00348
00349
00350 private:
00351
00352
00353
00354
00355 void removeContact(int n) {
00356 assert(0 <= n && n < m_contacts.size());
00357 if (n+1 == m_contacts.size()) {
00358 m_contacts.pop_back();
00359 return;
00360 }
00361
00362 m_contacts[n] = m_contacts.back();
00363 m_contacts.pop_back();
00364 m_id2contact[m_contacts[n].getContactId()] = n;
00365 }
00366
00367
00368 Real m_time;
00369 Array_<Contact,int> m_contacts;
00370 ContactMap m_id2contact;
00371 SurfaceMap m_surfPair2id;
00372 };
00373
00374
00375 inline std::ostream& operator<<(std::ostream& o, const ContactSnapshot& cs) {
00376 o << "Contact snapshot: time=" << cs.getTimestamp()
00377 << " numContacts=" << cs.getNumContacts() << std::endl;
00378 return o;
00379 }
00380
00381
00382
00383
00384
00385
00403 class SimTK_SIMBODY_EXPORT ContactTracker {
00404 public:
00405 class HalfSpaceSphere;
00406 class SphereSphere;
00407 class HalfSpaceTriangleMesh;
00408 class SphereTriangleMesh;
00409 class TriangleMeshTriangleMesh;
00410
00412 ContactTracker(ContactGeometryTypeId typeOfSurface1,
00413 ContactGeometryTypeId typeOfSurface2)
00414 : m_surfaceTypes(typeOfSurface1, typeOfSurface2)
00415 {
00416 }
00417
00420 const std::pair<ContactGeometryTypeId,ContactGeometryTypeId>&
00421 getContactGeometryTypeIds() const {return m_surfaceTypes;}
00422
00423 virtual ~ContactTracker() {}
00424
00430 virtual bool trackContact
00431 (const Contact& priorStatus,
00432 const Transform& X_GS1,
00433 const ContactGeometry& surface1,
00434 const Transform& X_GS2,
00435 const ContactGeometry& surface2,
00436 Real cutoff,
00437 Contact& currentStatus) const = 0;
00438
00445 virtual bool predictContact
00446 (const Contact& priorStatus,
00447 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1,
00448 const ContactGeometry& surface1,
00449 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2,
00450 const ContactGeometry& surface2,
00451 Real cutoff,
00452 Real intervalOfInterest,
00453 Contact& predictedStatus) const = 0;
00454
00460 virtual bool initializeContact
00461 (const Transform& X_GS1, const SpatialVec& V_GS1,
00462 const ContactGeometry& surface1,
00463 const Transform& X_GS2, const SpatialVec& V_GS2,
00464 const ContactGeometry& surface2,
00465 Real cutoff,
00466 Real intervalOfInterest,
00467 Contact& contactStatus) const = 0;
00468
00469
00470 private:
00471
00472
00473 std::pair<ContactGeometryTypeId,ContactGeometryTypeId> m_surfaceTypes;
00474 };
00475
00476
00477
00478
00479
00480
00483 class SimTK_SIMBODY_EXPORT ContactTracker::HalfSpaceSphere
00484 : public ContactTracker {
00485 public:
00486 HalfSpaceSphere()
00487 : ContactTracker(ContactGeometry::HalfSpace::classTypeId(),
00488 ContactGeometry::Sphere::classTypeId()) {}
00489
00490 virtual ~HalfSpaceSphere() {}
00491
00492 virtual bool trackContact
00493 (const Contact& priorStatus,
00494 const Transform& X_GS1,
00495 const ContactGeometry& surface1,
00496 const Transform& X_GS2,
00497 const ContactGeometry& surface2,
00498 Real cutoff,
00499 Contact& currentStatus) const;
00500
00501 virtual bool predictContact
00502 (const Contact& priorStatus,
00503 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1,
00504 const ContactGeometry& surface1,
00505 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2,
00506 const ContactGeometry& surface2,
00507 Real cutoff,
00508 Real intervalOfInterest,
00509 Contact& predictedStatus) const;
00510
00511 virtual bool initializeContact
00512 (const Transform& X_GS1, const SpatialVec& V_GS1,
00513 const ContactGeometry& surface1,
00514 const Transform& X_GS2, const SpatialVec& V_GS2,
00515 const ContactGeometry& surface2,
00516 Real cutoff,
00517 Real intervalOfInterest,
00518 Contact& contactStatus) const;
00519 };
00520
00521
00522
00523
00524
00525
00528 class SimTK_SIMBODY_EXPORT ContactTracker::SphereSphere
00529 : public ContactTracker {
00530 public:
00531 SphereSphere()
00532 : ContactTracker(ContactGeometry::Sphere::classTypeId(),
00533 ContactGeometry::Sphere::classTypeId()) {}
00534
00535 virtual ~SphereSphere() {}
00536
00537 virtual bool trackContact
00538 (const Contact& priorStatus,
00539 const Transform& X_GS1,
00540 const ContactGeometry& surface1,
00541 const Transform& X_GS2,
00542 const ContactGeometry& surface2,
00543 Real cutoff,
00544 Contact& currentStatus) const;
00545
00546 virtual bool predictContact
00547 (const Contact& priorStatus,
00548 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1,
00549 const ContactGeometry& surface1,
00550 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2,
00551 const ContactGeometry& surface2,
00552 Real cutoff,
00553 Real intervalOfInterest,
00554 Contact& predictedStatus) const;
00555
00556 virtual bool initializeContact
00557 (const Transform& X_GS1, const SpatialVec& V_GS1,
00558 const ContactGeometry& surface1,
00559 const Transform& X_GS2, const SpatialVec& V_GS2,
00560 const ContactGeometry& surface2,
00561 Real cutoff,
00562 Real intervalOfInterest,
00563 Contact& contactStatus) const;
00564 };
00565
00566
00567
00568
00569
00570
00573 class SimTK_SIMBODY_EXPORT ContactTracker::HalfSpaceTriangleMesh
00574 : public ContactTracker {
00575 public:
00576 HalfSpaceTriangleMesh()
00577 : ContactTracker(ContactGeometry::HalfSpace::classTypeId(),
00578 ContactGeometry::TriangleMesh::classTypeId()) {}
00579
00580 virtual ~HalfSpaceTriangleMesh() {}
00581
00582 virtual bool trackContact
00583 (const Contact& priorStatus,
00584 const Transform& X_GS1,
00585 const ContactGeometry& surface1,
00586 const Transform& X_GS2,
00587 const ContactGeometry& surface2,
00588 Real cutoff,
00589 Contact& currentStatus) const;
00590
00591 virtual bool predictContact
00592 (const Contact& priorStatus,
00593 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1,
00594 const ContactGeometry& surface1,
00595 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2,
00596 const ContactGeometry& surface2,
00597 Real cutoff,
00598 Real intervalOfInterest,
00599 Contact& predictedStatus) const;
00600
00601 virtual bool initializeContact
00602 (const Transform& X_GS1, const SpatialVec& V_GS1,
00603 const ContactGeometry& surface1,
00604 const Transform& X_GS2, const SpatialVec& V_GS2,
00605 const ContactGeometry& surface2,
00606 Real cutoff,
00607 Real intervalOfInterest,
00608 Contact& contactStatus) const;
00609
00610 private:
00611 void processBox(const ContactGeometry::TriangleMesh& mesh,
00612 const ContactGeometry::TriangleMesh::OBBTreeNode& node,
00613 const Transform& X_HM, const UnitVec3& hsNormal_M,
00614 Real hsFaceHeight_M, std::set<int>& insideFaces) const;
00615 void addAllTriangles(const ContactGeometry::TriangleMesh::OBBTreeNode& node,
00616 std::set<int>& insideFaces) const;
00617 };
00618
00619
00620
00621
00622
00623
00626 class SimTK_SIMBODY_EXPORT ContactTracker::SphereTriangleMesh
00627 : public ContactTracker {
00628 public:
00629 SphereTriangleMesh()
00630 : ContactTracker(ContactGeometry::Sphere::classTypeId(),
00631 ContactGeometry::TriangleMesh::classTypeId()) {}
00632
00633 virtual ~SphereTriangleMesh() {}
00634
00635 virtual bool trackContact
00636 (const Contact& priorStatus,
00637 const Transform& X_GS1,
00638 const ContactGeometry& surface1,
00639 const Transform& X_GS2,
00640 const ContactGeometry& surface2,
00641 Real cutoff,
00642 Contact& currentStatus) const;
00643
00644 virtual bool predictContact
00645 (const Contact& priorStatus,
00646 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1,
00647 const ContactGeometry& surface1,
00648 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2,
00649 const ContactGeometry& surface2,
00650 Real cutoff,
00651 Real intervalOfInterest,
00652 Contact& predictedStatus) const;
00653
00654 virtual bool initializeContact
00655 (const Transform& X_GS1, const SpatialVec& V_GS1,
00656 const ContactGeometry& surface1,
00657 const Transform& X_GS2, const SpatialVec& V_GS2,
00658 const ContactGeometry& surface2,
00659 Real cutoff,
00660 Real intervalOfInterest,
00661 Contact& contactStatus) const;
00662
00663 private:
00664 void processBox
00665 (const ContactGeometry::TriangleMesh& mesh,
00666 const ContactGeometry::TriangleMesh::OBBTreeNode& node,
00667 const Vec3& center_M, Real radius2,
00668 std::set<int>& insideFaces) const ;
00669 };
00670
00671
00672
00673
00674
00675
00678 class SimTK_SIMBODY_EXPORT ContactTracker::TriangleMeshTriangleMesh
00679 : public ContactTracker {
00680 public:
00681 TriangleMeshTriangleMesh()
00682 : ContactTracker(ContactGeometry::TriangleMesh::classTypeId(),
00683 ContactGeometry::TriangleMesh::classTypeId()) {}
00684
00685 virtual ~TriangleMeshTriangleMesh() {}
00686
00687 virtual bool trackContact
00688 (const Contact& priorStatus,
00689 const Transform& X_GS1,
00690 const ContactGeometry& surface1,
00691 const Transform& X_GS2,
00692 const ContactGeometry& surface2,
00693 Real cutoff,
00694 Contact& currentStatus) const;
00695
00696 virtual bool predictContact
00697 (const Contact& priorStatus,
00698 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1,
00699 const ContactGeometry& surface1,
00700 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2,
00701 const ContactGeometry& surface2,
00702 Real cutoff,
00703 Real intervalOfInterest,
00704 Contact& predictedStatus) const;
00705
00706 virtual bool initializeContact
00707 (const Transform& X_GS1, const SpatialVec& V_GS1,
00708 const ContactGeometry& surface1,
00709 const Transform& X_GS2, const SpatialVec& V_GS2,
00710 const ContactGeometry& surface2,
00711 Real cutoff,
00712 Real intervalOfInterest,
00713 Contact& contactStatus) const;
00714
00715 private:
00716 void findIntersectingFaces
00717 (const ContactGeometry::TriangleMesh& mesh1,
00718 const ContactGeometry::TriangleMesh& mesh2,
00719 const ContactGeometry::TriangleMesh::OBBTreeNode& node1,
00720 const ContactGeometry::TriangleMesh::OBBTreeNode& node2,
00721 const OrientedBoundingBox& node2Bounds_M1,
00722 const Transform& X_M1M2,
00723 std::set<int>& insideFaces1,
00724 std::set<int>& insideFaces2) const;
00725 void findBuriedFaces
00726 (const ContactGeometry::TriangleMesh& mesh,
00727 const ContactGeometry::TriangleMesh& otherMesh,
00728 const Transform& X_OM,
00729 std::set<int>& insideFaces) const;
00730 void tagFaces(const ContactGeometry::TriangleMesh& mesh,
00731 Array_<int>& faceType,
00732 std::set<int>& triangles,
00733 int index,
00734 int depth) const;
00735 };
00736
00737 }
00738
00739 #endif // SimTK_SIMBODY_CONTACT_TRACKER_SUBSYSTEM_H_