Simbody

ContactSurface.h

Go to the documentation of this file.
00001 #ifndef SimTK_SIMBODY_CONTACT_SURFACE_H_
00002 #define SimTK_SIMBODY_CONTACT_SURFACE_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 Stanford University and the Authors.           *
00013  * Authors: 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 
00038 #include "SimTKcommon.h"
00039 #include "simbody/internal/common.h"
00040 #include "simbody/internal/ContactGeometry.h"
00041 
00042 #include <algorithm>
00043 
00044 namespace SimTK {
00045 
00046 class ContactGeometry;
00047 
00048 SimTK_DEFINE_UNIQUE_INDEX_TYPE(ContactCliqueId);
00049 
00050 
00051 
00052 //==============================================================================
00053 //                               CONTACT MATERIAL
00054 //==============================================================================
00095 class SimTK_SIMBODY_EXPORT ContactMaterial {
00096 public:
00100 ContactMaterial() {clear();}
00101 
00106 ContactMaterial(Real stiffness, Real dissipation, 
00107                 Real staticFriction, Real dynamicFriction,
00108                 Real viscousFriction = 0) {
00109     setStiffness(stiffness);
00110     setDissipation(dissipation);
00111     setFriction(staticFriction, dynamicFriction, viscousFriction);
00112 }
00113 
00116 bool isValid() const {return m_stiffness > 0;}
00117 
00119 Real getStiffness() const 
00120 {   SimTK_ERRCHK(isValid(), "ContactMaterial::getStiffness()",
00121         "This is an invalid ContactMaterial.");
00122     return m_stiffness; }
00124 Real getStiffness23() const 
00125 {   SimTK_ERRCHK(isValid(), "ContactMaterial::getStiffness23()",
00126         "This is an invalid ContactMaterial.");
00127     return m_stiffness23; }
00129 Real getDissipation() const 
00130 {   SimTK_ERRCHK(isValid(), "ContactMaterial::getDissipation()",
00131         "This is an invalid ContactMaterial.");
00132     return m_dissipation; }
00134 Real getStaticFriction() const 
00135 {   SimTK_ERRCHK(isValid(), "ContactMaterial::getStaticFriction()",
00136         "This is an invalid ContactMaterial.");
00137     return m_staticFriction; }
00139 Real getDynamicFriction() const 
00140 {   SimTK_ERRCHK(isValid(), "ContactMaterial::getDynamicFriction()",
00141         "This is an invalid ContactMaterial.");
00142     return m_dynamicFriction; }
00144 //TODO: should this be (force/area)/velocity?
00145 Real getViscousFriction() const 
00146 {   SimTK_ERRCHK(isValid(), "ContactMaterial::getViscousFriction()",
00147         "This is an invalid ContactMaterial.");
00148     return m_viscousFriction; }
00149 
00153 ContactMaterial& setStiffness(Real stiffness) {
00154     SimTK_ERRCHK1_ALWAYS(stiffness >= 0, "ContactMaterial::setStiffness()",
00155         "Stiffness %g is illegal; must be >= 0.", stiffness);
00156     m_stiffness = stiffness;
00157     m_stiffness23 = std::pow(m_stiffness, Real(2./3.));
00158     return *this;
00159 }
00160 
00164 ContactMaterial& setDissipation(Real dissipation) {
00165     SimTK_ERRCHK1_ALWAYS(dissipation >= 0, "ContactMaterial::setDissipation()",
00166         "Dissipation %g (in 1/speed) is illegal; must be >= 0.", dissipation);
00167     m_dissipation = dissipation;
00168     return *this;
00169 }
00170 
00172 ContactMaterial& setFriction(Real staticFriction,
00173                              Real dynamicFriction,
00174                              Real viscousFriction = 0)
00175 {
00176     SimTK_ERRCHK1_ALWAYS(0 <= staticFriction, "ContactMaterial::setFriction()",
00177         "Illegal static friction coefficient %g.", staticFriction);
00178     SimTK_ERRCHK2_ALWAYS(0<=dynamicFriction && dynamicFriction<=staticFriction, 
00179         "ContactMaterial::setFriction()",
00180         "Dynamic coefficient %g illegal; must be between 0 and static"
00181         " coefficient %g.", dynamicFriction, staticFriction);
00182     SimTK_ERRCHK1_ALWAYS(0 <= viscousFriction, "ContactMaterial::setFriction()",
00183         "Illegal viscous friction coefficient %g.", viscousFriction);
00184 
00185     m_staticFriction  = staticFriction;
00186     m_dynamicFriction = dynamicFriction;
00187     m_viscousFriction = viscousFriction;
00188     return *this;
00189 }
00190 
00200 static Real calcPlaneStrainStiffness(Real youngsModulus, 
00201                                      Real poissonsRatio) 
00202 {
00203     SimTK_ERRCHK2_ALWAYS(youngsModulus >= 0 &&
00204                          -1 < poissonsRatio && poissonsRatio < 0.5,
00205                          "ContactMaterial::calcStiffnessForSolid()",
00206         "Illegal material properties E=%g, v=%g.", 
00207         youngsModulus, poissonsRatio);
00208 
00209     return youngsModulus / (1-square(poissonsRatio)); 
00210 }
00211 
00212 
00221 static Real calcConfinedCompressionStiffness(Real youngsModulus, 
00222                                              Real poissonsRatio) 
00223 {
00224     SimTK_ERRCHK2_ALWAYS(youngsModulus >= 0 &&
00225                          -1 < poissonsRatio && poissonsRatio < 0.5,
00226                          "ContactMaterial::calcStiffnessForSolid()",
00227         "Illegal material properties E=%g, v=%g.", 
00228         youngsModulus, poissonsRatio);
00229 
00230     return youngsModulus*(1-poissonsRatio) 
00231         / ((1+poissonsRatio)*(1-2*poissonsRatio)); 
00232 }
00233 
00245 static Real calcDissipationFromObservedRestitution
00246    (Real restitution, Real speed) {
00247     if (restitution==1) return 0;
00248     SimTK_ERRCHK2(0<=restitution && restitution<=1 && speed>0,
00249         "ContactMaterial::calcDissipationFromRestitution()",
00250         "Illegal coefficient of restitution or speed (%g,%g).",
00251         restitution, speed);
00252     return (1-restitution)/speed;
00253 }
00254 
00258 void clear() {
00259     m_stiffness   = NaN; // unspecified
00260     m_stiffness23 = NaN;
00261     m_restitution = NaN; // unspecified
00262     m_dissipation = 0;  // default; no dissipation
00263     // default; no friction
00264     m_staticFriction=m_dynamicFriction=m_viscousFriction = 0;
00265 }
00266 
00267 //--------------------------------------------------------------------------
00268 private:
00269 
00270 // For compliant contact models.
00271 Real    m_stiffness;        // k: stress/%strain=(force/area)/%strain
00272 Real    m_stiffness23;      // k^(2/3) in case we need it
00273 Real    m_dissipation;      // c: %normalForce/normalVelocity
00274 
00275 // For impulsive collisions.
00276 Real    m_restitution;      // e: unitless, e=(1-cv)
00277 
00278 // Friction.
00279 Real    m_staticFriction;   // us: unitless
00280 Real    m_dynamicFriction;  // ud: unitless
00281 Real    m_viscousFriction;  // uv: %normalForce/slipVelocity
00282 };
00283 
00284 
00285 
00286 //==============================================================================
00287 //                               CONTACT SURFACE
00288 //==============================================================================
00302 class SimTK_SIMBODY_EXPORT ContactSurface {
00303 public:
00305 ContactSurface() {}
00307 ContactSurface(const ContactGeometry& shape, const ContactMaterial& material)
00308 :   m_shape(shape), m_material(material) {}
00309 
00311 ContactSurface& setShape(const ContactGeometry& shape) 
00312 {   m_shape = shape; return *this; }
00313 
00316 ContactSurface& setMaterial(const ContactMaterial& material,
00317                             Real thickness = Infinity) 
00318 {   m_material = material; setThickness(thickness); return *this; }
00319 
00324 ContactSurface& setThickness(Real thickness)
00325 {   m_thickness = thickness; return *this; }
00326 
00328 const ContactGeometry& getShape()    const {return m_shape;}
00329 
00331 const ContactMaterial& getMaterial() const {return m_material;}
00332 
00336 Real getThickness() const {return m_thickness;}
00337 
00339 ContactGeometry& updShape()    {return m_shape;}
00340 
00342 ContactMaterial& updMaterial() {return m_material;}
00343 
00345 ContactSurface& joinClique(ContactCliqueId clique) {
00346     // Although this is a sorted list, we expect it to be very short so 
00347     // are using linear search to find where this new clique goes.
00348     Array_<ContactCliqueId,short>::iterator p;
00349     for (p = m_cliques.begin(); p != m_cliques.end(); ++p) {   
00350         if (*p==clique) return *this; // already a member
00351         if (*p>clique) break;
00352     }
00353     // insert just before p (might be at the end)
00354     m_cliques.insert(p, clique);
00355     return *this;
00356 }
00357 
00359 void leaveClique(ContactCliqueId clique) {   
00360     // We expect this to be a very short list so are using linear search.
00361     Array_<ContactCliqueId,short>::iterator p =
00362         std::find(m_cliques.begin(), m_cliques.end(), clique);
00363     if (p != m_cliques.end()) m_cliques.erase(p); 
00364 }
00365 
00369 bool isInSameClique(const ContactSurface& other) const 
00370 {   if (getCliques().empty() || other.getCliques().empty()) return false;//typical
00371     return cliquesIntersect(getCliques(), other.getCliques()); }
00372 
00375 const Array_<ContactCliqueId,short>& getCliques() const {return m_cliques;}
00376 
00380 static bool cliquesIntersect(const Array_<ContactCliqueId,short>& a,
00381                              const Array_<ContactCliqueId,short>& b)
00382 {
00383     Array_<ContactCliqueId,short>::const_iterator ap = a.begin();
00384     Array_<ContactCliqueId,short>::const_iterator bp = b.begin();
00385     // Quick checks: empty or non-overlapping.
00386     if (ap==a.end() || bp==b.end()) return false;
00387     if (*ap > b.back() || *bp > a.back()) 
00388         return false; // disjoint
00389     // Both lists have elements and the elements overlap numerically.
00390     while (true) {
00391         if (*ap==*bp) return true;
00392         // Increment the list with smaller front element.
00393         if (*ap < *bp) {++ap; if (ap==a.end()) break;}
00394         else           {++bp; if (bp==b.end()) break;}
00395     }
00396     // One of the lists ran out of elements before we found a match.
00397     return false;
00398 }
00399 
00403 static ContactCliqueId createNewContactClique()
00404 {   static AtomicInteger nextAvailableContactClique = 1;
00405     return ContactCliqueId(nextAvailableContactClique++); }
00406 
00407 //----------------------------------------------------------------------
00408                                  private:
00409 
00410 ContactGeometry                 m_shape;
00411 ContactMaterial                 m_material;
00412 Real                            m_thickness; // default=Infinity
00413 Array_<ContactCliqueId,short>   m_cliques;   // sorted
00414 };
00415 
00416 
00417 
00418 } // namespace SimTK
00419 
00420 #endif // SimTK_SIMBODY_CONTACT_SURFACE_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines