Simbody
|
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_