Simbody  3.4 (development)
CompliantContactSubsystem.h
Go to the documentation of this file.
00001 #ifndef SimTK_SIMBODY_COMPLIANT_CONTACT_SUBSYSTEM_H_
00002 #define SimTK_SIMBODY_COMPLIANT_CONTACT_SUBSYSTEM_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                               Simbody(tm)                                  *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK 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/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2008-13 Stanford University and the Authors.        *
00013  * Authors: Peter Eastman, Michael Sherman                                    *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00027 #include "SimTKmath.h"
00028 #include "simbody/internal/common.h"
00029 #include "simbody/internal/ForceSubsystem.h"
00030 
00031 #include <cassert>
00032 
00033 namespace SimTK {
00034 
00035 class MultibodySystem;
00036 class SimbodyMatterSubsystem;
00037 class ContactTrackerSubsystem;
00038 class ContactForceGenerator;
00039 class Contact;
00040 class ContactForce;
00041 class ContactPatch;
00042 
00043 
00044 
00045 //==============================================================================
00046 //                        COMPLIANT CONTACT SUBSYSTEM
00047 //==============================================================================
00053 class SimTK_SIMBODY_EXPORT CompliantContactSubsystem : public ForceSubsystem {
00054 public:
00056 CompliantContactSubsystem() {}
00057 
00063 CompliantContactSubsystem(MultibodySystem&, 
00064                           const ContactTrackerSubsystem&);
00065 
00067 Real getTransitionVelocity() const;
00069 void setTransitionVelocity(Real vt);
00071 Real getOOTransitionVelocity() const;
00072 
00081 void setTrackDissipatedEnergy(bool shouldTrack);
00086 bool getTrackDissipatedEnergy() const;
00087 
00092 int getNumContactForces(const State& state) const;
00099 const ContactForce& getContactForce(const State& state, int n) const;
00107 const ContactForce& getContactForceById(const State& state, ContactId id) const;
00108 
00136 bool calcContactPatchDetailsById(const State&   state,
00137                                  ContactId      id,
00138                                  ContactPatch&  patch) const;
00139 
00170 Real getDissipatedEnergy(const State& state) const;
00171 
00192 void setDissipatedEnergy(State& state, Real energy) const;
00193 
00194 
00199 void adoptForceGenerator(ContactForceGenerator* generator);
00200 
00205 void adoptDefaultForceGenerator(ContactForceGenerator* generator);
00206 
00209 bool hasForceGenerator(ContactTypeId contact) const;
00210 
00214 bool hasDefaultForceGenerator() const;
00215 
00219 const ContactForceGenerator& 
00220     getContactForceGenerator(ContactTypeId contact) const; 
00221 
00224 const ContactForceGenerator& getDefaultForceGenerator() const; 
00225 
00230 const ContactTrackerSubsystem& getContactTrackerSubsystem() const;
00231 
00236 const MultibodySystem& getMultibodySystem() const;
00237    // don't show in Doxygen docs
00239 SimTK_PIMPL_DOWNCAST(CompliantContactSubsystem, ForceSubsystem);
00242 //--------------------------------------------------------------------------
00243                                  private:
00244 class CompliantContactSubsystemImpl& updImpl();
00245 const CompliantContactSubsystemImpl& getImpl() const;
00246 };
00247 
00248 
00249 
00250 //==============================================================================
00251 //                               CONTACT FORCE
00252 //==============================================================================
00301 class ContactForce {
00302 public:
00304 ContactForce() {} // invalid
00305 
00310 ContactForce(ContactId id, const Vec3& contactPt,
00311              const SpatialVec& forceOnSurface2,
00312              Real potentialEnergy, Real powerLoss)
00313 :   m_contactId(id), m_contactPt(contactPt), 
00314     m_forceOnSurface2(forceOnSurface2),
00315     m_potentialEnergy(potentialEnergy), m_powerLoss(powerLoss) {}
00316 
00318 ContactId getContactId() const {return m_contactId;}
00322 const Vec3& getContactPoint() const {return m_contactPt;}
00326 const SpatialVec& getForceOnSurface2() const {return m_forceOnSurface2;}
00329 Real getPotentialEnergy() const {return m_potentialEnergy;}
00333 Real getPowerDissipation() const {return m_powerLoss;}
00334 
00340 void setTo(ContactId id, const Vec3& contactPt,
00341            const SpatialVec& forceOnSurface2,
00342            Real potentialEnergy, Real powerLoss)
00343 {   m_contactId         = id; 
00344     m_contactPt         = contactPt;
00345     m_forceOnSurface2   = forceOnSurface2;
00346     m_potentialEnergy   = potentialEnergy;
00347     m_powerLoss         = powerLoss; }
00348 
00350 void setContactId(ContactId id) {m_contactId=id;}
00352 void setContactPoint(const Vec3& contactPt) {m_contactPt=contactPt;}
00355 void setForceOnSurface2(const SpatialVec& forceOnSurface2) 
00356 {   m_forceOnSurface2=forceOnSurface2; }
00358 void setPotentialEnergy(Real potentialEnergy) 
00359 {   m_potentialEnergy=potentialEnergy; }
00361 void setPowerDissipation(Real powerLoss) {m_powerLoss=powerLoss;}
00362 
00365 void clear() {m_contactId.invalidate();}
00367 bool isValid() const {return m_contactId.isValid();}
00368 
00373 void changeFrameInPlace(const Transform& X_BA) {
00374     m_contactPt         = X_BA*m_contactPt;        // shift & reexpress in B
00375     m_forceOnSurface2   = X_BA.R()*m_forceOnSurface2;      // reexpress in B
00376 }
00377 
00378 private:
00379 ContactId       m_contactId;            // Which Contact produced this force?
00380 Vec3            m_contactPt;            // In some frame A
00381 SpatialVec      m_forceOnSurface2;      // at contact pt, in A; neg. for Surf1
00382 Real            m_potentialEnergy;      // > 0 when due to compression
00383 Real            m_powerLoss;            // > 0 means dissipation
00384 };
00385 
00386 // For debugging.
00387 inline std::ostream& operator<<(std::ostream& o, const ContactForce& f) {
00388     o << "ContactForce for ContactId " << f.getContactId() << " (ground frame):\n";
00389     o << "  contact point=" << f.getContactPoint() << "\n";
00390     o << "  force on surf2 =" << f.getForceOnSurface2() << "\n";
00391     o << "  pot. energy=" << f.getPotentialEnergy() 
00392       << "  powerLoss=" << f.getPowerDissipation();
00393     return o << "\n";
00394 }
00395 
00396 //==============================================================================
00397 //                              CONTACT DETAIL
00398 //==============================================================================
00464 class ContactDetail {
00465 public:
00468 const Vec3& getContactPoint() const {return m_contactPt;}
00472 const UnitVec3& getContactNormal() const {return m_patchNormal;}
00476 const Vec3& getSlipVelocity() const {return m_slipVelocity;}
00479 const Vec3& getForceOnSurface2() const {return m_forceOnSurface2;}
00485 Real getDeformation() const {return m_deformation;}
00491 Real getDeformationRate() const {return m_deformationRate;}
00493 Real getPatchArea() const {return m_patchArea;}
00497 Real getPeakPressure() const {return m_peakPressure;}
00500 Real getPotentialEnergy() const {return m_potentialEnergy;}
00504 Real getPowerDissipation() const {return m_powerLoss;}
00505 
00506     
00510 void changeFrameInPlace(const Transform& X_BA) {
00511     const Rotation& R_BA = X_BA.R();
00512     m_contactPt       = X_BA*m_contactPt;       // shift & reexpress in B (18 flops)
00513     m_patchNormal     = R_BA*m_patchNormal;     // reexpress only       (3*15 flops)
00514     m_slipVelocity    = R_BA*m_slipVelocity;    //      "
00515     m_forceOnSurface2 = R_BA*m_forceOnSurface2; //      "
00516 }
00517 
00521 void changeFrameAndSwitchSurfacesInPlace(const Transform& X_BA) {
00522     const Rotation& R_BA = X_BA.R();
00523     m_contactPt       = X_BA*m_contactPt;       // shift & reexpress in B (18 flops)
00524     m_patchNormal     = R_BA*(-m_patchNormal);  // reverse & reexpress  (3*18 flops)
00525     m_slipVelocity    = R_BA*(-m_slipVelocity); //          "
00526     m_forceOnSurface2 = R_BA*(-m_forceOnSurface2); //       "
00527 }
00528 
00529 Vec3            m_contactPt;            // location of contact point C in A
00530 UnitVec3        m_patchNormal;          // points outwards from body 1, exp. in A
00531 Vec3            m_slipVelocity;         // material slip rate, perp. to normal, in A
00532 Vec3            m_forceOnSurface2;      // applied at C, -force to surf1
00533 Real            m_deformation;          // total normal compression (approach)
00534 Real            m_deformationRate;      // d/dt deformation, w.r.t. A frame
00535 Real            m_patchArea;            // >= 0
00536 Real            m_peakPressure;         // > 0 in compression
00537 Real            m_potentialEnergy;      // > 0 when due to compression
00538 Real            m_powerLoss;            // > 0 means dissipation
00539 };
00540 
00541 // For debugging.
00542 inline std::ostream& operator<<(std::ostream& o, const ContactDetail& d) {
00543     o << "ContactDetail (ground frame):\n";
00544     o << "  contact point=" << d.m_contactPt << "\n";
00545     o << "  contact normal=" << d.m_patchNormal << "\n";
00546     o << "  slip velocity=" << d.m_slipVelocity << "\n";
00547     o << "  force on surf2 =" << d.m_forceOnSurface2 << "\n";
00548     o << "  deformation=" << d.m_deformation 
00549       << "  deformation rate=" << d.m_deformationRate << "\n";
00550     o << "  patch area=" << d.m_patchArea 
00551       << "  peak pressure=" << d.m_peakPressure << "\n";
00552     o << "  pot. energy=" << d.m_potentialEnergy << "  powerLoss=" << d.m_powerLoss;
00553     return o << "\n";
00554 }
00555 
00556 
00557 
00558 //==============================================================================
00559 //                               CONTACT PATCH
00560 //==============================================================================
00581 class SimTK_SIMBODY_EXPORT ContactPatch {
00582 public:
00583 void clear() {m_resultant.clear(); m_elements.clear();}
00584 bool isValid() const {return m_resultant.isValid();}
00585 const ContactForce& getContactForce() const {return m_resultant;}
00586 int getNumDetails() const {return (int)m_elements.size();}
00587 const ContactDetail& getContactDetail(int n) const {return m_elements[n];}
00588 
00592 void changeFrameInPlace(const Transform& X_BA) {
00593     m_resultant.changeFrameInPlace(X_BA);
00594     for (unsigned i=0; i<m_elements.size(); ++i)
00595         m_elements[i].changeFrameInPlace(X_BA);
00596 }
00597 
00598 ContactForce            m_resultant;
00599 Array_<ContactDetail>   m_elements;
00600 };
00601 
00602 
00603 
00604 //==============================================================================
00605 //                          CONTACT FORCE GENERATOR
00606 //==============================================================================
00615 class SimTK_SIMBODY_EXPORT ContactForceGenerator {
00616 public:
00617 class ElasticFoundation;        // for TriangleMeshContact
00618 class HertzCircular;            // for PointContact
00619 class HertzElliptical;          // for EllipticalPointContact
00620 
00621 // These are for response to unknown ContactTypeIds.
00622 class DoNothing;     // do nothing if called
00623 class ThrowError;    // throw an error if called
00624 
00626 explicit ContactForceGenerator(ContactTypeId type): m_contactType(type) {}
00627 
00631 ContactTypeId getContactTypeId() const {return m_contactType;}
00632 
00633 const CompliantContactSubsystem& getCompliantContactSubsystem() const
00634 {   assert(m_compliantContactSubsys); return *m_compliantContactSubsys; }
00635 void setCompliantContactSubsystem(const CompliantContactSubsystem* sub)
00636 {   m_compliantContactSubsys = sub; }
00637 
00639 virtual ~ContactForceGenerator() {}
00640 
00651 virtual void calcContactForce
00652    (const State&            state,
00653     const Contact&          overlapping,
00654     const SpatialVec&       V_S1S2,  // relative surface velocity (S2 in S1)
00655     ContactForce&           contactForce) const = 0;
00656 
00663 virtual void calcContactPatch
00664    (const State&            state,
00665     const Contact&          overlapping,
00666     const SpatialVec&       V_S1S2,  // relative surface velocity (S2 in S1)
00667     ContactPatch&           patch) const = 0;
00668 
00669 
00670 //--------------------------------------------------------------------------
00671 private:
00672     // This generator should be called only for Contact objects of the 
00673     // indicated type id.
00674     ContactTypeId                       m_contactType;
00675     // This is a reference to the owning CompliantContactSubsystem if any;
00676     // don't delete on destruction.
00677     const CompliantContactSubsystem*    m_compliantContactSubsys;
00678 };
00679 
00680 
00681 
00682 
00683 //==============================================================================
00684 //                         HERTZ CIRCULAR GENERATOR
00685 //==============================================================================
00686 
00692 class SimTK_SIMBODY_EXPORT ContactForceGenerator::HertzCircular 
00693 :   public ContactForceGenerator {
00694 public:
00695 HertzCircular() 
00696 :   ContactForceGenerator(CircularPointContact::classTypeId()) {}
00697 
00698 virtual ~HertzCircular() {}
00699 virtual void calcContactForce
00700    (const State&            state,
00701     const Contact&          overlapping,
00702     const SpatialVec&       V_S1S2,
00703     ContactForce&           contactForce) const;
00704 
00705 virtual void calcContactPatch
00706    (const State&            state,
00707     const Contact&          overlapping,
00708     const SpatialVec&       V_S1S2,
00709     ContactPatch&           patch) const;
00710 };
00711 
00712 
00713 
00714 //==============================================================================
00715 //                         HERTZ ELLIPTICAL GENERATOR
00716 //==============================================================================
00717 
00723 class SimTK_SIMBODY_EXPORT ContactForceGenerator::HertzElliptical 
00724 :   public ContactForceGenerator {
00725 public:
00726 HertzElliptical() 
00727 :   ContactForceGenerator(EllipticalPointContact::classTypeId()) {}
00728 
00729 virtual ~HertzElliptical() {}
00730 virtual void calcContactForce
00731    (const State&            state,
00732     const Contact&          overlapping,
00733     const SpatialVec&       V_S1S2,
00734     ContactForce&           contactForce) const;
00735 
00736 virtual void calcContactPatch
00737    (const State&            state,
00738     const Contact&          overlapping,
00739     const SpatialVec&       V_S1S2,
00740     ContactPatch&           patch) const;
00741 };
00742 
00743 
00744 
00745 //==============================================================================
00746 //                       ELASTIC FOUNDATION GENERATOR
00747 //==============================================================================
00751 class SimTK_SIMBODY_EXPORT ContactForceGenerator::ElasticFoundation 
00752 :   public ContactForceGenerator {
00753 public:
00754 ElasticFoundation() 
00755 :   ContactForceGenerator(TriangleMeshContact::classTypeId()) {}
00756 virtual ~ElasticFoundation() {}
00757 virtual void calcContactForce
00758    (const State&            state,
00759     const Contact&          overlapping,
00760     const SpatialVec&       V_S1S2,
00761     ContactForce&           contactForce) const;
00762 
00763 virtual void calcContactPatch
00764    (const State&            state,
00765     const Contact&          overlapping,
00766     const SpatialVec&       V_S1S2,
00767     ContactPatch&           patch) const;
00768 
00769 private:
00770 void calcContactForceAndDetails
00771    (const State&            state,
00772     const Contact&          overlapping,
00773     const SpatialVec&       V_S1S2,
00774     ContactForce&           contactForce,
00775     Array_<ContactDetail>*  contactDetails) const;
00776 
00777 void calcWeightedPatchCentroid
00778    (const ContactGeometry::TriangleMesh&    mesh,
00779     const std::set<int>&                    insideFaces,
00780     Vec3&                                   weightedPatchCentroid,
00781     Real&                                   patchArea) const;
00782                        
00783 void processOneMesh
00784    (const State&                            state,
00785     const ContactGeometry::TriangleMesh&    mesh,
00786     const std::set<int>&                    insideFaces,
00787     const Transform&                        X_MO, 
00788     const SpatialVec&                       V_MO,
00789     const ContactGeometry&                  other,
00790     Real                                    meshDeformationFraction, // 0..1
00791     Real                                    areaScaleFactor, // >= 0
00792     Real k, Real c, Real us, Real ud, Real uv,
00793     const Vec3&                 resultantPt_M, // where to apply forces
00794     SpatialVec&                 resultantForceOnOther_M, // at resultant pt
00795     Real&                       potentialEnergy,
00796     Real&                       powerLoss,
00797     Vec3&                       weightedCenterOfPressure_M, // COP
00798     Real&                       sumOfAllPressureMoments,    // COP weight
00799     Array_<ContactDetail>*      contactDetails) const;
00800 };
00801 
00802 
00803 
00804 
00805 //==============================================================================
00806 //                        DO NOTHING FORCE GENERATOR
00807 //==============================================================================
00811 class SimTK_SIMBODY_EXPORT ContactForceGenerator::DoNothing 
00812 :   public ContactForceGenerator {
00813 public:
00814 explicit DoNothing(ContactTypeId type = ContactTypeId(0)) 
00815 :   ContactForceGenerator(type) {}
00816 virtual ~DoNothing() {}
00817 virtual void calcContactForce
00818    (const State&            state,
00819     const Contact&          overlapping,
00820     const SpatialVec&       V_S1S2,
00821     ContactForce&           contactForce) const
00822 {   SimTK_ASSERT_ALWAYS(!"implemented",
00823         "ContactForceGenerator::DoNothing::calcContactForce() not implemented yet."); }
00824 virtual void calcContactPatch
00825    (const State&            state,
00826     const Contact&          overlapping,
00827     const SpatialVec&       V_S1S2,
00828     ContactPatch&           patch) const
00829 {   SimTK_ASSERT_ALWAYS(!"implemented",
00830         "ContactForceGenerator::DoNothing::calcContactPatch() not implemented yet."); }
00831 };
00832 
00833 
00834 
00835 //==============================================================================
00836 //                       THROW ERROR FORCE GENERATOR
00837 //==============================================================================
00842 class SimTK_SIMBODY_EXPORT ContactForceGenerator::ThrowError 
00843 :   public ContactForceGenerator {
00844 public:
00845 explicit ThrowError(ContactTypeId type = ContactTypeId(0)) 
00846 :   ContactForceGenerator(type) {}
00847 virtual ~ThrowError() {}
00848 virtual void calcContactForce
00849    (const State&            state,
00850     const Contact&          overlapping,
00851     const SpatialVec&       V_S1S2,
00852     ContactForce&           contactForce) const
00853 {   SimTK_ASSERT_ALWAYS(!"implemented",
00854         "ContactForceGenerator::ThrowError::calcContactForce() not implemented yet."); }
00855 virtual void calcContactPatch
00856    (const State&            state,
00857     const Contact&          overlapping,
00858     const SpatialVec&       V_S1S2,
00859     ContactPatch&           patch) const
00860 {   SimTK_ASSERT_ALWAYS(!"implemented",
00861         "ContactForceGenerator::ThrowError::calcContactPatch() not implemented yet."); }
00862 };
00863 
00864 } // namespace SimTK
00865 
00866 #endif // SimTK_SIMBODY_COMPLIANT_CONTACT_SUBSYSTEM_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines