Simbody

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  *                      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) 2008-10 Stanford University and the Authors.        *
00013  * Authors: Peter Eastman, Michael Sherman                                    *
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 "simbody/internal/common.h"
00036 #include "simbody/internal/ForceSubsystem.h"
00037 #include "simbody/internal/Contact.h"
00038 #include "simbody/internal/ContactGeometry.h"
00039 
00040 #include <cassert>
00041 
00042 namespace SimTK {
00043 
00044 class MultibodySystem;
00045 class SimbodyMatterSubsystem;
00046 class ContactTrackerSubsystem;
00047 class ContactForceGenerator;
00048 class Contact;
00049 class ContactForce;
00050 class ContactPatch;
00051 
00052 
00053 
00054 //==============================================================================
00055 //                        COMPLIANT CONTACT SUBSYSTEM
00056 //==============================================================================
00062 class SimTK_SIMBODY_EXPORT CompliantContactSubsystem : public ForceSubsystem {
00063 public:
00065 CompliantContactSubsystem() {}
00066 
00072 CompliantContactSubsystem(MultibodySystem&, 
00073                           const ContactTrackerSubsystem&);
00074 
00076 Real getTransitionVelocity() const;
00078 void setTransitionVelocity(Real vt);
00080 Real getOOTransitionVelocity() const;
00081 
00086 int getNumContactForces(const State& state) const;
00093 const ContactForce& getContactForce(const State& state, int n) const;
00101 const ContactForce& getContactForceById(const State& state, ContactId id) const;
00102 
00130 bool calcContactPatchDetailsById(const State&   state,
00131                                  ContactId      id,
00132                                  ContactPatch&  patch) const;
00133 
00156 Real getDissipatedEnergy(const State& state) const;
00157 
00170 void setDissipatedEnergy(State& state, Real energy) const;
00171 
00172 
00177 void adoptForceGenerator(ContactForceGenerator* generator);
00178 
00183 void adoptDefaultForceGenerator(ContactForceGenerator* generator);
00184 
00187 bool hasForceGenerator(ContactTypeId contact) const;
00188 
00192 bool hasDefaultForceGenerator() const;
00193 
00197 const ContactForceGenerator& 
00198     getContactForceGenerator(ContactTypeId contact) const; 
00199 
00202 const ContactForceGenerator& getDefaultForceGenerator() const; 
00203 
00208 const ContactTrackerSubsystem& getContactTrackerSubsystem() const;
00209 
00214 const MultibodySystem& getMultibodySystem() const;
00215    // don't show in Doxygen docs
00217 SimTK_PIMPL_DOWNCAST(CompliantContactSubsystem, ForceSubsystem);
00220 //--------------------------------------------------------------------------
00221                                  private:
00222 class CompliantContactSubsystemImpl& updImpl();
00223 const CompliantContactSubsystemImpl& getImpl() const;
00224 };
00225 
00226 
00227 
00228 //==============================================================================
00229 //                               CONTACT FORCE
00230 //==============================================================================
00279 class ContactForce {
00280 public:
00282 ContactForce() {} // invalid
00283 
00288 ContactForce(ContactId id, const Vec3& contactPt,
00289              const SpatialVec& forceOnSurface2,
00290              Real potentialEnergy, Real powerLoss)
00291 :   m_contactId(id), m_contactPt(contactPt), 
00292     m_forceOnSurface2(forceOnSurface2),
00293     m_potentialEnergy(potentialEnergy), m_powerLoss(powerLoss) {}
00294 
00296 ContactId getContactId() const {return m_contactId;}
00300 const Vec3& getContactPoint() const {return m_contactPt;}
00304 const SpatialVec& getForceOnSurface2() const {return m_forceOnSurface2;}
00307 Real getPotentialEnergy() const {return m_potentialEnergy;}
00311 Real getPowerDissipation() const {return m_powerLoss;}
00312 
00318 void setTo(ContactId id, const Vec3& contactPt,
00319            const SpatialVec& forceOnSurface2,
00320            Real potentialEnergy, Real powerLoss)
00321 {   m_contactId         = id; 
00322     m_contactPt         = contactPt;
00323     m_forceOnSurface2   = forceOnSurface2;
00324     m_potentialEnergy   = potentialEnergy;
00325     m_powerLoss         = powerLoss; }
00326 
00328 void setContactId(ContactId id) {m_contactId=id;}
00330 void setContactPoint(const Vec3& contactPt) {m_contactPt=contactPt;}
00333 void setForceOnSurface2(const SpatialVec& forceOnSurface2) 
00334 {   m_forceOnSurface2=forceOnSurface2; }
00336 void setPotentialEnergy(Real potentialEnergy) 
00337 {   m_potentialEnergy=potentialEnergy; }
00339 void setPowerDissipation(Real powerLoss) {m_powerLoss=powerLoss;}
00340 
00343 void clear() {m_contactId.invalidate();}
00345 bool isValid() const {return m_contactId.isValid();}
00346 
00351 void changeFrameInPlace(const Transform& X_BA) {
00352     m_contactPt         = X_BA*m_contactPt;        // shift & reexpress in B
00353     m_forceOnSurface2   = X_BA.R()*m_forceOnSurface2;      // reexpress in B
00354 }
00355 
00356 private:
00357 ContactId       m_contactId;            // Which Contact produced this force?
00358 Vec3            m_contactPt;            // In some frame A
00359 SpatialVec      m_forceOnSurface2;      // at contact pt, in A; neg. for Surf1
00360 Real            m_potentialEnergy;      // > 0 when due to compression
00361 Real            m_powerLoss;            // > 0 means dissipation
00362 };
00363 
00364 // For debugging.
00365 inline std::ostream& operator<<(std::ostream& o, const ContactForce& f) {
00366     o << "ContactForce for ContactId " << f.getContactId() << " (ground frame):\n";
00367     o << "  contact point=" << f.getContactPoint() << "\n";
00368     o << "  force on surf2 =" << f.getForceOnSurface2() << "\n";
00369     o << "  pot. energy=" << f.getPotentialEnergy() 
00370       << "  powerLoss=" << f.getPowerDissipation();
00371     return o << "\n";
00372 }
00373 
00374 //==============================================================================
00375 //                              CONTACT DETAIL
00376 //==============================================================================
00442 class ContactDetail {
00443 public:
00446 const Vec3& getContactPoint() const {return m_contactPt;}
00450 const UnitVec3& getContactNormal() const {return m_patchNormal;}
00454 const Vec3& getSlipVelocity() const {return m_slipVelocity;}
00457 const Vec3& getForceOnSurface2() const {return m_forceOnSurface2;}
00463 Real getDeformation() const {return m_deformation;}
00469 Real getDeformationRate() const {return m_deformationRate;}
00471 Real getPatchArea() const {return m_patchArea;}
00475 Real getPeakPressure() const {return m_peakPressure;}
00478 Real getPotentialEnergy() const {return m_potentialEnergy;}
00482 Real getPowerDissipation() const {return m_powerLoss;}
00483 
00484     
00488 void changeFrameInPlace(const Transform& X_BA) {
00489     const Rotation& R_BA = X_BA.R();
00490     m_contactPt       = X_BA*m_contactPt;       // shift & reexpress in B (18 flops)
00491     m_patchNormal     = R_BA*m_patchNormal;     // reexpress only       (3*15 flops)
00492     m_slipVelocity    = R_BA*m_slipVelocity;    //      "
00493     m_forceOnSurface2 = R_BA*m_forceOnSurface2; //      "
00494 }
00495 
00499 void changeFrameAndSwitchSurfacesInPlace(const Transform& X_BA) {
00500     const Rotation& R_BA = X_BA.R();
00501     m_contactPt       = X_BA*m_contactPt;       // shift & reexpress in B (18 flops)
00502     m_patchNormal     = R_BA*(-m_patchNormal);  // reverse & reexpress  (3*18 flops)
00503     m_slipVelocity    = R_BA*(-m_slipVelocity); //          "
00504     m_forceOnSurface2 = R_BA*(-m_forceOnSurface2); //       "
00505 }
00506 
00507 Vec3            m_contactPt;            // location of contact point C in A
00508 UnitVec3        m_patchNormal;          // points outwards from body 1, exp. in A
00509 Vec3            m_slipVelocity;         // material slip rate, perp. to normal, in A
00510 Vec3            m_forceOnSurface2;      // applied at C, -force to surf1
00511 Real            m_deformation;          // total normal compression (approach)
00512 Real            m_deformationRate;      // d/dt deformation, w.r.t. A frame
00513 Real            m_patchArea;            // >= 0
00514 Real            m_peakPressure;         // > 0 in compression
00515 Real            m_potentialEnergy;      // > 0 when due to compression
00516 Real            m_powerLoss;            // > 0 means dissipation
00517 };
00518 
00519 // For debugging.
00520 inline std::ostream& operator<<(std::ostream& o, const ContactDetail& d) {
00521     o << "ContactDetail (ground frame):\n";
00522     o << "  contact point=" << d.m_contactPt << "\n";
00523     o << "  contact normal=" << d.m_patchNormal << "\n";
00524     o << "  slip velocity=" << d.m_slipVelocity << "\n";
00525     o << "  force on surf2 =" << d.m_forceOnSurface2 << "\n";
00526     o << "  deformation=" << d.m_deformation 
00527       << "  deformation rate=" << d.m_deformationRate << "\n";
00528     o << "  patch area=" << d.m_patchArea 
00529       << "  peak pressure=" << d.m_peakPressure << "\n";
00530     o << "  pot. energy=" << d.m_potentialEnergy << "  powerLoss=" << d.m_powerLoss;
00531     return o << "\n";
00532 }
00533 
00534 
00535 
00536 //==============================================================================
00537 //                               CONTACT PATCH
00538 //==============================================================================
00559 class SimTK_SIMBODY_EXPORT ContactPatch {
00560 public:
00561 void clear() {m_resultant.clear(); m_elements.clear();}
00562 bool isValid() const {return m_resultant.isValid();}
00563 const ContactForce& getContactForce() const {return m_resultant;}
00564 int getNumDetails() const {return (int)m_elements.size();}
00565 const ContactDetail& getContactDetail(int n) const {return m_elements[n];}
00566 
00570 void changeFrameInPlace(const Transform& X_BA) {
00571     m_resultant.changeFrameInPlace(X_BA);
00572     for (unsigned i=0; i<m_elements.size(); ++i)
00573         m_elements[i].changeFrameInPlace(X_BA);
00574 }
00575 
00576 ContactForce            m_resultant;
00577 Array_<ContactDetail>   m_elements;
00578 };
00579 
00580 
00581 
00582 //==============================================================================
00583 //                          CONTACT FORCE GENERATOR
00584 //==============================================================================
00593 class SimTK_SIMBODY_EXPORT ContactForceGenerator {
00594 public:
00595 class ElasticFoundation;        // for TriangleMeshContact
00596 class HertzCircular;            // for PointContact
00597 class HertzElliptical;          // for EllipticalPointContact
00598 
00599 // These are for response to unknown ContactTypeIds.
00600 class DoNothing;     // do nothing if called
00601 class ThrowError;    // throw an error if called
00602 
00604 explicit ContactForceGenerator(ContactTypeId type): m_contactType(type) {}
00605 
00609 ContactTypeId getContactTypeId() const {return m_contactType;}
00610 
00611 const CompliantContactSubsystem& getCompliantContactSubsystem() const
00612 {   assert(m_compliantContactSubsys); return *m_compliantContactSubsys; }
00613 void setCompliantContactSubsystem(const CompliantContactSubsystem* sub)
00614 {   m_compliantContactSubsys = sub; }
00615 
00617 virtual ~ContactForceGenerator() {}
00618 
00629 virtual void calcContactForce
00630    (const State&            state,
00631     const Contact&          overlapping,
00632     const SpatialVec&       V_S1S2,  // relative surface velocity (S2 in S1)
00633     ContactForce&           contactForce) const = 0;
00634 
00641 virtual void calcContactPatch
00642    (const State&            state,
00643     const Contact&          overlapping,
00644     const SpatialVec&       V_S1S2,  // relative surface velocity (S2 in S1)
00645     ContactPatch&           patch) const = 0;
00646 
00647 
00648 //--------------------------------------------------------------------------
00649 private:
00650     // This generator should be called only for Contact objects of the 
00651     // indicated type id.
00652     ContactTypeId                       m_contactType;
00653     // This is a reference to the owning CompliantContactSubsystem if any;
00654     // don't delete on destruction.
00655     const CompliantContactSubsystem*    m_compliantContactSubsys;
00656 };
00657 
00658 
00659 
00660 
00661 //==============================================================================
00662 //                         HERTZ CIRCULAR GENERATOR
00663 //==============================================================================
00664 
00670 class SimTK_SIMBODY_EXPORT ContactForceGenerator::HertzCircular 
00671 :   public ContactForceGenerator {
00672 public:
00673 HertzCircular() 
00674 :   ContactForceGenerator(CircularPointContact::classTypeId()) {}
00675 
00676 virtual ~HertzCircular() {}
00677 virtual void calcContactForce
00678    (const State&            state,
00679     const Contact&          overlapping,
00680     const SpatialVec&       V_S1S2,
00681     ContactForce&           contactForce) const;
00682 
00683 virtual void calcContactPatch
00684    (const State&            state,
00685     const Contact&          overlapping,
00686     const SpatialVec&       V_S1S2,
00687     ContactPatch&           patch) const;
00688 };
00689 
00690 
00691 
00692 //==============================================================================
00693 //                         HERTZ ELLIPTICAL GENERATOR
00694 //==============================================================================
00695 
00701 class SimTK_SIMBODY_EXPORT ContactForceGenerator::HertzElliptical 
00702 :   public ContactForceGenerator {
00703 public:
00704 HertzElliptical() 
00705 :   ContactForceGenerator(EllipticalPointContact::classTypeId()) {}
00706 
00707 virtual ~HertzElliptical() {}
00708 virtual void calcContactForce
00709    (const State&            state,
00710     const Contact&          overlapping,
00711     const SpatialVec&       V_S1S2,
00712     ContactForce&           contactForce) const;
00713 
00714 virtual void calcContactPatch
00715    (const State&            state,
00716     const Contact&          overlapping,
00717     const SpatialVec&       V_S1S2,
00718     ContactPatch&           patch) const;
00719 };
00720 
00721 
00722 
00723 //==============================================================================
00724 //                       ELASTIC FOUNDATION GENERATOR
00725 //==============================================================================
00729 class SimTK_SIMBODY_EXPORT ContactForceGenerator::ElasticFoundation 
00730 :   public ContactForceGenerator {
00731 public:
00732 ElasticFoundation() 
00733 :   ContactForceGenerator(TriangleMeshContact::classTypeId()) {}
00734 virtual ~ElasticFoundation() {}
00735 virtual void calcContactForce
00736    (const State&            state,
00737     const Contact&          overlapping,
00738     const SpatialVec&       V_S1S2,
00739     ContactForce&           contactForce) const;
00740 
00741 virtual void calcContactPatch
00742    (const State&            state,
00743     const Contact&          overlapping,
00744     const SpatialVec&       V_S1S2,
00745     ContactPatch&           patch) const;
00746 
00747 private:
00748 void calcContactForceAndDetails
00749    (const State&            state,
00750     const Contact&          overlapping,
00751     const SpatialVec&       V_S1S2,
00752     ContactForce&           contactForce,
00753     Array_<ContactDetail>*  contactDetails) const;
00754 
00755 void calcWeightedPatchCentroid
00756    (const ContactGeometry::TriangleMesh&    mesh,
00757     const std::set<int>&                    insideFaces,
00758     Vec3&                                   weightedPatchCentroid,
00759     Real&                                   patchArea) const;
00760                        
00761 void processOneMesh
00762    (const State&                            state,
00763     const ContactGeometry::TriangleMesh&    mesh,
00764     const std::set<int>&                    insideFaces,
00765     const Transform&                        X_MO, 
00766     const SpatialVec&                       V_MO,
00767     const ContactGeometry&                  other,
00768     Real                                    meshDeformationFraction, // 0..1
00769     Real k, Real c, Real us, Real ud, Real uv,
00770     const Vec3&                 resultantPt_M, // where to apply forces
00771     SpatialVec&                 resultantForceOnOther_M, // at resultant pt
00772     Real&                       potentialEnergy,
00773     Real&                       powerLoss,
00774     Vec3&                       weightedCenterOfPressure_M, // COP
00775     Real&                       sumOfAllPressureMoments,    // COP weight
00776     Array_<ContactDetail>*      contactDetails) const;
00777 };
00778 
00779 
00780 
00781 
00782 //==============================================================================
00783 //                        DO NOTHING FORCE GENERATOR
00784 //==============================================================================
00788 class SimTK_SIMBODY_EXPORT ContactForceGenerator::DoNothing 
00789 :   public ContactForceGenerator {
00790 public:
00791 explicit DoNothing(ContactTypeId type = ContactTypeId(0)) 
00792 :   ContactForceGenerator(type) {}
00793 virtual ~DoNothing() {}
00794 virtual void calcContactForce
00795    (const State&            state,
00796     const Contact&          overlapping,
00797     const SpatialVec&       V_S1S2,
00798     ContactForce&           contactForce) const
00799 {   SimTK_ASSERT_ALWAYS(!"implemented",
00800         "ContactForceGenerator::DoNothing::calcContactForce() not implemented yet."); }
00801 virtual void calcContactPatch
00802    (const State&            state,
00803     const Contact&          overlapping,
00804     const SpatialVec&       V_S1S2,
00805     ContactPatch&           patch) const
00806 {   SimTK_ASSERT_ALWAYS(!"implemented",
00807         "ContactForceGenerator::DoNothing::calcContactPatch() not implemented yet."); }
00808 };
00809 
00810 
00811 
00812 //==============================================================================
00813 //                       THROW ERROR FORCE GENERATOR
00814 //==============================================================================
00819 class SimTK_SIMBODY_EXPORT ContactForceGenerator::ThrowError 
00820 :   public ContactForceGenerator {
00821 public:
00822 explicit ThrowError(ContactTypeId type = ContactTypeId(0)) 
00823 :   ContactForceGenerator(type) {}
00824 virtual ~ThrowError() {}
00825 virtual void calcContactForce
00826    (const State&            state,
00827     const Contact&          overlapping,
00828     const SpatialVec&       V_S1S2,
00829     ContactForce&           contactForce) const
00830 {   SimTK_ASSERT_ALWAYS(!"implemented",
00831         "ContactForceGenerator::ThrowError::calcContactForce() not implemented yet."); }
00832 virtual void calcContactPatch
00833    (const State&            state,
00834     const Contact&          overlapping,
00835     const SpatialVec&       V_S1S2,
00836     ContactPatch&           patch) const
00837 {   SimTK_ASSERT_ALWAYS(!"implemented",
00838         "ContactForceGenerator::ThrowError::calcContactPatch() not implemented yet."); }
00839 };
00840 
00841 } // namespace SimTK
00842 
00843 #endif // SimTK_SIMBODY_COMPLIANT_CONTACT_SUBSYSTEM_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines