Simbody
3.4 (development)
|
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_