Simbody
|
00001 #ifndef SimTK_SIMBODY_CONTACT_TRACKER_SUBSYSTEM_H_ 00002 #define SimTK_SIMBODY_CONTACT_TRACKER_SUBSYSTEM_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTK Simbody(tm) * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00011 * * 00012 * Portions copyright (c) 2010 Stanford University and the Authors. * 00013 * Authors: Michael Sherman, Peter Eastman * 00014 * Contributors: * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 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 // CONTACT TRACKER SUBSYSTEM 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 // CONTACT SNAPSHOT 00257 //============================================================================== 00268 class SimTK_SIMBODY_EXPORT ContactSnapshot { 00269 //TODO: replace with fast hash tables 00270 typedef std::map<ContactId,int> ContactMap; 00271 // Note: we always order the key so that the first surface index is less than 00272 // the second (they can't be equal!). 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 // Surface pair must be ordered (low,high) for the map. 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); // shallow copy 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 // Remove a Contact occupying a particular slot in the Contact array. This 00353 // will result in another Contact object being moved to occupy the now-empty 00354 // slot to keep the array compact. 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(); // this was the last one 00359 return; 00360 } 00361 // Move the last one to replace this one and update the map. 00362 m_contacts[n] = m_contacts.back(); // shallow copy 00363 m_contacts.pop_back(); // destruct 00364 m_id2contact[m_contacts[n].getContactId()] = n; 00365 } 00366 00367 00368 Real m_time; // when this snapshot was taken 00369 Array_<Contact,int> m_contacts; // all the contact pairs 00370 ContactMap m_id2contact; // the contact pairs by contactId 00371 SurfaceMap m_surfPair2id; // surfacepair -> contactId map 00372 }; 00373 00374 // for debugging 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 // CONTACT TRACKER 00385 //============================================================================== 00403 class SimTK_SIMBODY_EXPORT ContactTracker { 00404 public: 00405 class HalfSpaceSphere; 00406 class HalfSpaceEllipsoid; 00407 class SphereSphere; 00408 class HalfSpaceTriangleMesh; 00409 class SphereTriangleMesh; 00410 class TriangleMeshTriangleMesh; 00411 00413 ContactTracker(ContactGeometryTypeId typeOfSurface1, 00414 ContactGeometryTypeId typeOfSurface2) 00415 : m_surfaceTypes(typeOfSurface1, typeOfSurface2) 00416 { 00417 } 00418 00421 const std::pair<ContactGeometryTypeId,ContactGeometryTypeId>& 00422 getContactGeometryTypeIds() const {return m_surfaceTypes;} 00423 00424 virtual ~ContactTracker() {} 00425 00431 virtual bool trackContact 00432 (const Contact& priorStatus, 00433 const Transform& X_GS1, 00434 const ContactGeometry& surface1, 00435 const Transform& X_GS2, 00436 const ContactGeometry& surface2, 00437 Real cutoff, 00438 Contact& currentStatus) const = 0; 00439 00446 virtual bool predictContact 00447 (const Contact& priorStatus, 00448 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1, 00449 const ContactGeometry& surface1, 00450 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2, 00451 const ContactGeometry& surface2, 00452 Real cutoff, 00453 Real intervalOfInterest, 00454 Contact& predictedStatus) const = 0; 00455 00461 virtual bool initializeContact 00462 (const Transform& X_GS1, const SpatialVec& V_GS1, 00463 const ContactGeometry& surface1, 00464 const Transform& X_GS2, const SpatialVec& V_GS2, 00465 const ContactGeometry& surface2, 00466 Real cutoff, 00467 Real intervalOfInterest, 00468 Contact& contactStatus) const = 0; 00469 00470 //-------------------------------------------------------------------------- 00471 private: 00472 // This tracker should be called only for surfaces of these two types, 00473 // in this order. 00474 std::pair<ContactGeometryTypeId,ContactGeometryTypeId> m_surfaceTypes; 00475 }; 00476 00477 00478 00479 //============================================================================== 00480 // HALFSPACE-SPHERE CONTACT TRACKER 00481 //============================================================================== 00484 class SimTK_SIMBODY_EXPORT ContactTracker::HalfSpaceSphere 00485 : public ContactTracker { 00486 public: 00487 HalfSpaceSphere() 00488 : ContactTracker(ContactGeometry::HalfSpace::classTypeId(), 00489 ContactGeometry::Sphere::classTypeId()) {} 00490 00491 virtual ~HalfSpaceSphere() {} 00492 00493 virtual bool trackContact 00494 (const Contact& priorStatus, 00495 const Transform& X_GS1, 00496 const ContactGeometry& surface1, 00497 const Transform& X_GS2, 00498 const ContactGeometry& surface2, 00499 Real cutoff, 00500 Contact& currentStatus) const; 00501 00502 virtual bool predictContact 00503 (const Contact& priorStatus, 00504 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1, 00505 const ContactGeometry& surface1, 00506 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2, 00507 const ContactGeometry& surface2, 00508 Real cutoff, 00509 Real intervalOfInterest, 00510 Contact& predictedStatus) const; 00511 00512 virtual bool initializeContact 00513 (const Transform& X_GS1, const SpatialVec& V_GS1, 00514 const ContactGeometry& surface1, 00515 const Transform& X_GS2, const SpatialVec& V_GS2, 00516 const ContactGeometry& surface2, 00517 Real cutoff, 00518 Real intervalOfInterest, 00519 Contact& contactStatus) const; 00520 }; 00521 00522 00523 00524 //============================================================================== 00525 // HALFSPACE-ELLIPSOID CONTACT TRACKER 00526 //============================================================================== 00529 class SimTK_SIMBODY_EXPORT ContactTracker::HalfSpaceEllipsoid 00530 : public ContactTracker { 00531 public: 00532 HalfSpaceEllipsoid() 00533 : ContactTracker(ContactGeometry::HalfSpace::classTypeId(), 00534 ContactGeometry::Ellipsoid::classTypeId()) {} 00535 00536 virtual ~HalfSpaceEllipsoid() {} 00537 00538 virtual bool trackContact 00539 (const Contact& priorStatus, 00540 const Transform& X_GS1, 00541 const ContactGeometry& surface1, 00542 const Transform& X_GS2, 00543 const ContactGeometry& surface2, 00544 Real cutoff, 00545 Contact& currentStatus) const; 00546 00547 virtual bool predictContact 00548 (const Contact& priorStatus, 00549 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1, 00550 const ContactGeometry& surface1, 00551 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2, 00552 const ContactGeometry& surface2, 00553 Real cutoff, 00554 Real intervalOfInterest, 00555 Contact& predictedStatus) const; 00556 00557 virtual bool initializeContact 00558 (const Transform& X_GS1, const SpatialVec& V_GS1, 00559 const ContactGeometry& surface1, 00560 const Transform& X_GS2, const SpatialVec& V_GS2, 00561 const ContactGeometry& surface2, 00562 Real cutoff, 00563 Real intervalOfInterest, 00564 Contact& contactStatus) const; 00565 }; 00566 00567 00568 00569 //============================================================================== 00570 // SPHERE-SPHERE CONTACT TRACKER 00571 //============================================================================== 00574 class SimTK_SIMBODY_EXPORT ContactTracker::SphereSphere 00575 : public ContactTracker { 00576 public: 00577 SphereSphere() 00578 : ContactTracker(ContactGeometry::Sphere::classTypeId(), 00579 ContactGeometry::Sphere::classTypeId()) {} 00580 00581 virtual ~SphereSphere() {} 00582 00583 virtual bool trackContact 00584 (const Contact& priorStatus, 00585 const Transform& X_GS1, 00586 const ContactGeometry& surface1, 00587 const Transform& X_GS2, 00588 const ContactGeometry& surface2, 00589 Real cutoff, 00590 Contact& currentStatus) const; 00591 00592 virtual bool predictContact 00593 (const Contact& priorStatus, 00594 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1, 00595 const ContactGeometry& surface1, 00596 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2, 00597 const ContactGeometry& surface2, 00598 Real cutoff, 00599 Real intervalOfInterest, 00600 Contact& predictedStatus) const; 00601 00602 virtual bool initializeContact 00603 (const Transform& X_GS1, const SpatialVec& V_GS1, 00604 const ContactGeometry& surface1, 00605 const Transform& X_GS2, const SpatialVec& V_GS2, 00606 const ContactGeometry& surface2, 00607 Real cutoff, 00608 Real intervalOfInterest, 00609 Contact& contactStatus) const; 00610 }; 00611 00612 00613 00614 //============================================================================== 00615 // HALFSPACE-TRIANGLE MESH CONTACT TRACKER 00616 //============================================================================== 00619 class SimTK_SIMBODY_EXPORT ContactTracker::HalfSpaceTriangleMesh 00620 : public ContactTracker { 00621 public: 00622 HalfSpaceTriangleMesh() 00623 : ContactTracker(ContactGeometry::HalfSpace::classTypeId(), 00624 ContactGeometry::TriangleMesh::classTypeId()) {} 00625 00626 virtual ~HalfSpaceTriangleMesh() {} 00627 00628 virtual bool trackContact 00629 (const Contact& priorStatus, 00630 const Transform& X_GS1, 00631 const ContactGeometry& surface1, // the half space 00632 const Transform& X_GS2, 00633 const ContactGeometry& surface2, // the mesh 00634 Real cutoff, 00635 Contact& currentStatus) const; 00636 00637 virtual bool predictContact 00638 (const Contact& priorStatus, 00639 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1, 00640 const ContactGeometry& surface1, 00641 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2, 00642 const ContactGeometry& surface2, 00643 Real cutoff, 00644 Real intervalOfInterest, 00645 Contact& predictedStatus) const; 00646 00647 virtual bool initializeContact 00648 (const Transform& X_GS1, const SpatialVec& V_GS1, 00649 const ContactGeometry& surface1, 00650 const Transform& X_GS2, const SpatialVec& V_GS2, 00651 const ContactGeometry& surface2, 00652 Real cutoff, 00653 Real intervalOfInterest, 00654 Contact& contactStatus) const; 00655 00656 private: 00657 void processBox(const ContactGeometry::TriangleMesh& mesh, 00658 const ContactGeometry::TriangleMesh::OBBTreeNode& node, 00659 const Transform& X_HM, const UnitVec3& hsNormal_M, 00660 Real hsFaceHeight_M, std::set<int>& insideFaces) const; 00661 void addAllTriangles(const ContactGeometry::TriangleMesh::OBBTreeNode& node, 00662 std::set<int>& insideFaces) const; 00663 }; 00664 00665 00666 00667 //============================================================================== 00668 // SPHERE - TRIANGLE MESH CONTACT TRACKER 00669 //============================================================================== 00672 class SimTK_SIMBODY_EXPORT ContactTracker::SphereTriangleMesh 00673 : public ContactTracker { 00674 public: 00675 SphereTriangleMesh() 00676 : ContactTracker(ContactGeometry::Sphere::classTypeId(), 00677 ContactGeometry::TriangleMesh::classTypeId()) {} 00678 00679 virtual ~SphereTriangleMesh() {} 00680 00681 virtual bool trackContact 00682 (const Contact& priorStatus, 00683 const Transform& X_GS1, 00684 const ContactGeometry& surface1, // the sphere 00685 const Transform& X_GS2, 00686 const ContactGeometry& surface2, // the mesh 00687 Real cutoff, 00688 Contact& currentStatus) const; 00689 00690 virtual bool predictContact 00691 (const Contact& priorStatus, 00692 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1, 00693 const ContactGeometry& surface1, 00694 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2, 00695 const ContactGeometry& surface2, 00696 Real cutoff, 00697 Real intervalOfInterest, 00698 Contact& predictedStatus) const; 00699 00700 virtual bool initializeContact 00701 (const Transform& X_GS1, const SpatialVec& V_GS1, 00702 const ContactGeometry& surface1, 00703 const Transform& X_GS2, const SpatialVec& V_GS2, 00704 const ContactGeometry& surface2, 00705 Real cutoff, 00706 Real intervalOfInterest, 00707 Contact& contactStatus) const; 00708 00709 private: 00710 void processBox 00711 (const ContactGeometry::TriangleMesh& mesh, 00712 const ContactGeometry::TriangleMesh::OBBTreeNode& node, 00713 const Vec3& center_M, Real radius2, 00714 std::set<int>& insideFaces) const ; 00715 }; 00716 00717 00718 00719 //============================================================================== 00720 // TRIANGLE MESH - TRIANGLE MESH CONTACT TRACKER 00721 //============================================================================== 00724 class SimTK_SIMBODY_EXPORT ContactTracker::TriangleMeshTriangleMesh 00725 : public ContactTracker { 00726 public: 00727 TriangleMeshTriangleMesh() 00728 : ContactTracker(ContactGeometry::TriangleMesh::classTypeId(), 00729 ContactGeometry::TriangleMesh::classTypeId()) {} 00730 00731 virtual ~TriangleMeshTriangleMesh() {} 00732 00733 virtual bool trackContact 00734 (const Contact& priorStatus, 00735 const Transform& X_GS1, 00736 const ContactGeometry& surface1, // mesh1 00737 const Transform& X_GS2, 00738 const ContactGeometry& surface2, // mesh2 00739 Real cutoff, 00740 Contact& currentStatus) const; 00741 00742 virtual bool predictContact 00743 (const Contact& priorStatus, 00744 const Transform& X_GS1, const SpatialVec& V_GS1, const SpatialVec& A_GS1, 00745 const ContactGeometry& surface1, 00746 const Transform& X_GS2, const SpatialVec& V_GS2, const SpatialVec& A_GS2, 00747 const ContactGeometry& surface2, 00748 Real cutoff, 00749 Real intervalOfInterest, 00750 Contact& predictedStatus) const; 00751 00752 virtual bool initializeContact 00753 (const Transform& X_GS1, const SpatialVec& V_GS1, 00754 const ContactGeometry& surface1, 00755 const Transform& X_GS2, const SpatialVec& V_GS2, 00756 const ContactGeometry& surface2, 00757 Real cutoff, 00758 Real intervalOfInterest, 00759 Contact& contactStatus) const; 00760 00761 private: 00762 void findIntersectingFaces 00763 (const ContactGeometry::TriangleMesh& mesh1, 00764 const ContactGeometry::TriangleMesh& mesh2, 00765 const ContactGeometry::TriangleMesh::OBBTreeNode& node1, 00766 const ContactGeometry::TriangleMesh::OBBTreeNode& node2, 00767 const OrientedBoundingBox& node2Bounds_M1, 00768 const Transform& X_M1M2, 00769 std::set<int>& insideFaces1, 00770 std::set<int>& insideFaces2) const; 00771 void findBuriedFaces 00772 (const ContactGeometry::TriangleMesh& mesh, 00773 const ContactGeometry::TriangleMesh& otherMesh, 00774 const Transform& X_OM, 00775 std::set<int>& insideFaces) const; 00776 void tagFaces(const ContactGeometry::TriangleMesh& mesh, 00777 Array_<int>& faceType, 00778 std::set<int>& triangles, 00779 int index, 00780 int depth) const; 00781 }; 00782 00783 } // namespace SimTK 00784 00785 #endif // SimTK_SIMBODY_CONTACT_TRACKER_SUBSYSTEM_H_