Simbody

ContactTrackerSubsystem.h

Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines