Simbody  3.7
ContactSurface.h
Go to the documentation of this file.
1 #ifndef SimTK_SIMBODY_CONTACT_SURFACE_H_
2 #define SimTK_SIMBODY_CONTACT_SURFACE_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm) *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2008-13 Stanford University and the Authors. *
13  * Authors: Peter Eastman, Michael Sherman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
30 #include "SimTKmath.h"
32 
33 #include <algorithm>
34 #include <atomic>
35 
36 namespace SimTK {
37 
38 class ContactGeometry;
39 
40 SimTK_DEFINE_UNIQUE_INDEX_TYPE(ContactCliqueId);
41 
42 
43 
44 //==============================================================================
45 // CONTACT MATERIAL
46 //==============================================================================
90 public:
94 ContactMaterial() {clear();}
95 
136 ContactMaterial(Real stiffness, Real dissipation,
137  Real staticFriction, Real dynamicFriction,
138  Real viscousFriction = 0) {
139  setStiffness(stiffness);
140  setDissipation(dissipation);
141  setFriction(staticFriction, dynamicFriction, viscousFriction);
142 }
143 
146 bool isValid() const {return m_stiffness > 0;}
147 
150 { SimTK_ERRCHK(isValid(), "ContactMaterial::getStiffness()",
151  "This is an invalid ContactMaterial.");
152  return m_stiffness; }
155 { SimTK_ERRCHK(isValid(), "ContactMaterial::getStiffness23()",
156  "This is an invalid ContactMaterial.");
157  return m_stiffness23; }
160 { SimTK_ERRCHK(isValid(), "ContactMaterial::getDissipation()",
161  "This is an invalid ContactMaterial.");
162  return m_dissipation; }
165 { SimTK_ERRCHK(isValid(), "ContactMaterial::getStaticFriction()",
166  "This is an invalid ContactMaterial.");
167  return m_staticFriction; }
170 { SimTK_ERRCHK(isValid(), "ContactMaterial::getDynamicFriction()",
171  "This is an invalid ContactMaterial.");
172  return m_dynamicFriction; }
175 { SimTK_ERRCHK(isValid(), "ContactMaterial::getViscousFriction()",
176  "This is an invalid ContactMaterial.");
177  return m_viscousFriction; }
178 
183  SimTK_ERRCHK1_ALWAYS(stiffness >= 0, "ContactMaterial::setStiffness()",
184  "Stiffness %g is illegal; must be >= 0.", stiffness);
185  m_stiffness = stiffness;
186  m_stiffness23 = std::pow(m_stiffness, Real(2./3.));
187  return *this;
188 }
189 
194  SimTK_ERRCHK1_ALWAYS(dissipation >= 0, "ContactMaterial::setDissipation()",
195  "Dissipation %g (in 1/speed) is illegal; must be >= 0.", dissipation);
196  m_dissipation = dissipation;
197  return *this;
198 }
199 
202  Real dynamicFriction,
203  Real viscousFriction = 0)
204 {
205  SimTK_ERRCHK1_ALWAYS(0 <= staticFriction, "ContactMaterial::setFriction()",
206  "Illegal static friction coefficient %g.", staticFriction);
207  SimTK_ERRCHK2_ALWAYS(0<=dynamicFriction && dynamicFriction<=staticFriction,
208  "ContactMaterial::setFriction()",
209  "Dynamic coefficient %g illegal; must be between 0 and static"
210  " coefficient %g.", dynamicFriction, staticFriction);
211  SimTK_ERRCHK1_ALWAYS(0 <= viscousFriction, "ContactMaterial::setFriction()",
212  "Illegal viscous friction coefficient %g.", viscousFriction);
213 
214  m_staticFriction = staticFriction;
215  m_dynamicFriction = dynamicFriction;
216  m_viscousFriction = viscousFriction;
217  return *this;
218 }
219 
229 static Real calcPlaneStrainStiffness(Real youngsModulus,
230  Real poissonsRatio)
231 {
232  SimTK_ERRCHK2_ALWAYS(youngsModulus >= 0 &&
233  -1 < poissonsRatio && poissonsRatio <= 0.5,
234  "ContactMaterial::calcStiffnessForSolid()",
235  "Illegal material properties E=%g, v=%g.",
236  youngsModulus, poissonsRatio);
237 
238  return youngsModulus / (1-square(poissonsRatio));
239 }
240 
241 
251  Real poissonsRatio)
252 {
253  SimTK_ERRCHK2_ALWAYS(youngsModulus >= 0 &&
254  -1 < poissonsRatio && poissonsRatio < 0.5,
255  "ContactMaterial::calcStiffnessForSolid()",
256  "Illegal material properties E=%g, v=%g.",
257  youngsModulus, poissonsRatio);
258 
259  return youngsModulus*(1-poissonsRatio)
260  / ((1+poissonsRatio)*(1-2*poissonsRatio));
261 }
262 
274 static Real calcDissipationFromObservedRestitution
275  (Real restitution, Real speed) {
276  if (restitution==1) return 0;
277  SimTK_ERRCHK2_ALWAYS(0<=restitution && restitution<=1 && speed>0,
278  "ContactMaterial::calcDissipationFromRestitution()",
279  "Illegal coefficient of restitution or speed (%g,%g).",
280  restitution, speed);
281  return (1-restitution)/speed;
282 }
283 
287 void clear() {
288  m_stiffness = NaN; // unspecified
289  m_stiffness23 = NaN;
290  m_restitution = NaN; // unspecified
291  m_dissipation = 0; // default; no dissipation
292  // default; no friction
293  m_staticFriction=m_dynamicFriction=m_viscousFriction = 0;
294 }
295 
296 //--------------------------------------------------------------------------
297 private:
298 
299 // For compliant contact models.
300 Real m_stiffness; // k: stress/%strain=(force/area)/%strain
301 Real m_stiffness23; // k^(2/3) in case we need it
302 Real m_dissipation; // c: %normalForce/normalVelocity
303 
304 // For impulsive collisions.
305 Real m_restitution; // e: unitless, e=(1-cv)
306 
307 // Friction.
308 Real m_staticFriction; // us: unitless
309 Real m_dynamicFriction; // ud: unitless
310 Real m_viscousFriction; // uv: %normalForce/slipVelocity
311 };
312 
313 
314 
315 //==============================================================================
316 // CONTACT SURFACE
317 //==============================================================================
343 public:
345 ContactSurface() : m_thickness(0), m_indexOnBody(-1), m_userRef(nullptr) {}
348  const ContactMaterial& material,
349  Real thickness=0)
350 : m_shape(shape), m_material(material), m_thickness(thickness),
351  m_indexOnBody(-1), m_userRef(nullptr) {
352  SimTK_ERRCHK1_ALWAYS(thickness >= 0, "ContactSurface::ctor()",
353  "Illegal thickness %g.", thickness);
354 }
355 
358 { m_shape = shape; return *this; }
359 
363  Real thickness = 0)
364 { m_material = material; setThickness(thickness); return *this; }
365 
371  SimTK_ERRCHK1_ALWAYS(thickness >= 0, "ContactSurface::setThickness()",
372  "Illegal thickness %g.", thickness);
373  m_thickness = thickness;
374  return *this;
375 }
376 
378 const ContactGeometry& getShape() const {return m_shape;}
379 
381 const ContactMaterial& getMaterial() const {return m_material;}
382 
385 Real getThickness() const {return m_thickness;}
386 
388 ContactGeometry& updShape() {return m_shape;}
389 
391 ContactMaterial& updMaterial() {return m_material;}
392 
395 ContactSurface& joinClique(ContactCliqueId clique) {
396  if (!clique.isValid()) return *this;
397  // Although this is a sorted list, we expect it to be very short so
398  // are using linear search to find where this new clique goes.
400  for (p = m_cliques.begin(); p != m_cliques.end(); ++p) {
401  if (*p==clique) return *this; // already a member
402  if (*p>clique) break;
403  }
404  // insert just before p (might be at the end)
405  m_cliques.insert(p, clique);
406  return *this;
407 }
408 
411 void leaveClique(ContactCliqueId clique) {
412  if (!clique.isValid()) return;
413  // We expect this to be a very short list so are using linear search.
415  std::find(m_cliques.begin(), m_cliques.end(), clique);
416  if (p != m_cliques.end()) m_cliques.erase(p);
417 }
418 
422 bool isInSameClique(const ContactSurface& other) const
423 { if (getCliques().empty() || other.getCliques().empty()) return false;//typical
424  return cliquesIntersect(getCliques(), other.getCliques()); }
425 
428 const Array_<ContactCliqueId,short>& getCliques() const {return m_cliques;}
429 
435 {
438  // Quick checks: empty or non-overlapping.
439  if (ap==a.end() || bp==b.end()) return false;
440  if (*ap > b.back() || *bp > a.back())
441  return false; // disjoint
442  // Both lists have elements and the elements overlap numerically.
443  while (true) {
444  if (*ap==*bp) return true;
445  // Increment the list with smaller front element.
446  if (*ap < *bp) {++ap; if (ap==a.end()) break;}
447  else {++bp; if (bp==b.end()) break;}
448  }
449  // One of the lists ran out of elements before we found a match.
450  return false;
451 }
452 
456 static ContactCliqueId createNewContactClique()
457 { static std::atomic<int> nextAvailableContactClique(1);
458  return ContactCliqueId(nextAvailableContactClique++); }
459 
471 ContactSurface& setIndexOnBody(int index) {m_indexOnBody=index; return *this;}
472 
487 ContactSurface& setUserRef(void* userRef) {m_userRef=userRef; return *this;}
488 
493 int getIndexOnBody() const {return m_indexOnBody;}
494 
499 void* getUserRef() const {return m_userRef;}
500 
501 //----------------------------------------------------------------------
502  private:
503 
504 ContactGeometry m_shape;
505 ContactMaterial m_material;
506 Real m_thickness; // default=0; meaning not set
507 Array_<ContactCliqueId,short> m_cliques; // sorted
508 
509 int m_indexOnBody; // default is -1
510 void* m_userRef; // default is nullptr
511 };
512 
513 
514 
515 } // namespace SimTK
516 
517 #endif // SimTK_SIMBODY_CONTACT_SURFACE_H_
#define SimTK_ERRCHK2_ALWAYS(cond, whereChecked, fmt, a1, a2)
Definition: ExceptionMacros.h:289
bool empty() const
Return true if there are no elements currently stored in this array.
Definition: Array.h:2080
SimTK_DEFINE_UNIQUE_INDEX_TYPE(AssemblyConditionIndex)
ContactSurface & setIndexOnBody(int index)
For selection or other purposes, you may want to use this method to store an index that can identify ...
Definition: ContactSurface.h:471
ContactSurface(const ContactGeometry &shape, const ContactMaterial &material, Real thickness=0)
Create a ContactSurface with a given shape and material.
Definition: ContactSurface.h:347
void * getUserRef() const
Return the pointer value that was supplied to the most recent setUserRef() call for this ContactSurfa...
Definition: ContactSurface.h:499
#define SimTK_ERRCHK1_ALWAYS(cond, whereChecked, fmt, a1)
Definition: ExceptionMacros.h:285
const ContactGeometry & getShape() const
Get read-only access to the shape of this contact surface.
Definition: ContactSurface.h:378
ContactSurface & setThickness(Real thickness)
Set the thickness of the layer of elastic material coating this contact surface.
Definition: ContactSurface.h:370
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
Real getStiffness() const
Return the material stiffness k=(force/area)/%strain.
Definition: ContactSurface.h:149
ContactSurface & setUserRef(void *userRef)
Use this method to store an arbitrary reference pointer with this ContactSurface object.
Definition: ContactSurface.h:487
Real getStaticFriction() const
Return the coefficient of static friction mu_s (unitless).
Definition: ContactSurface.h:164
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:2214
Every Simbody header and source file should include this header before any other Simbody header...
const ContactMaterial & getMaterial() const
Get read-only access to the material of this contact surface.
Definition: ContactSurface.h:381
SimTK_Real Real
This is the default compiled-in floating point type for SimTK, either float or double.
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:606
ContactMaterial & setDissipation(Real dissipation)
Supply material dissipation coefficient c, which is the slope of the coefficient of restitution (e) v...
Definition: ContactSurface.h:193
T * erase(T *first, const T *last1)
Erase elements in range [first,last1), packing in any later elements into the newly-available space a...
Definition: Array.h:2510
const Real NaN
This is the IEEE "not a number" constant for this implementation of the default-precision Real type; ...
unsigned char square(unsigned char u)
Definition: Scalar.h:349
ContactGeometry & updShape()
Get writable access to the shape of this contact surface.
Definition: ContactSurface.h:388
Real getStiffness23() const
Return precalculated 2/3 power of material stiffness k (k^(2/3)).
Definition: ContactSurface.h:154
const Array_< ContactCliqueId, short > & getCliques() const
Return a reference to the list of CliqueIds of the cliques in which this contact surface is a member;...
Definition: ContactSurface.h:428
static Real calcConfinedCompressionStiffness(Real youngsModulus, Real poissonsRatio)
Calculate the contact material stiffness k from its linear elastic material properties Young&#39;s modulu...
Definition: ContactSurface.h:250
bool isValid() const
Return false if material properties have not yet been supplied for this contact material.
Definition: ContactSurface.h:146
T * insert(T *p, size_type n, const T &value)
Insert n copies of a given value at a particular location within this array, moving all following ele...
Definition: Array.h:2632
The Array_<T> container class is a plug-compatible replacement for the C++ standard template library ...
Definition: Array.h:53
ContactSurface & joinClique(ContactCliqueId clique)
Join a contact clique if not already a member.
Definition: ContactSurface.h:395
A ContactGeometry object describes the shape of all or part of the boundary of a solid object...
Definition: ContactGeometry.h:110
Real getDynamicFriction() const
Return the coefficient of dynamic friction mu_d (unitless).
Definition: ContactSurface.h:169
ContactMaterial & updMaterial()
Get writable access to the material of this contact surface.
Definition: ContactSurface.h:391
Real getDissipation() const
Return the material dissipation coefficient c, in units of 1/velocity.
Definition: ContactSurface.h:159
ContactSurface & setMaterial(const ContactMaterial &material, Real thickness=0)
Define a new material for this ContactSurface, optionally providing the thickness of this elastic mat...
Definition: ContactSurface.h:362
static Real calcPlaneStrainStiffness(Real youngsModulus, Real poissonsRatio)
Calculate the contact material stiffness k from its linear elastic material properties Young&#39;s modulu...
Definition: ContactSurface.h:229
#define SimTK_ERRCHK(cond, whereChecked, msg)
Definition: ExceptionMacros.h:324
void leaveClique(ContactCliqueId clique)
Remove this surface from a contact clique if it is a member.
Definition: ContactSurface.h:411
ContactMaterial & setFriction(Real staticFriction, Real dynamicFriction, Real viscousFriction=0)
Set the friction coefficients for this material.
Definition: ContactSurface.h:201
Define the physical properties of the material from which a contact surface is made, including properties needed by a variety of contact response techniques that might be applied during contact.
Definition: ContactSurface.h:89
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:2227
Real getThickness() const
Get the thickness of the elastic material layer on this contact surface, with zero indicating that th...
Definition: ContactSurface.h:385
ContactMaterial()
Default constructor creates an invalid contact material; you must specify at least stiffness before u...
Definition: ContactSurface.h:94
Real getViscousFriction() const
Return the coefficient of viscous friction mu_v (1/velocity).
Definition: ContactSurface.h:174
static bool cliquesIntersect(const Array_< ContactCliqueId, short > &a, const Array_< ContactCliqueId, short > &b)
Return true if there are any common cliques on two clique lists which must each be sorted in ascendin...
Definition: ContactSurface.h:433
#define SimTK_SIMBODY_EXPORT
Definition: Simbody/include/simbody/internal/common.h:68
This class combines a piece of ContactGeometry with a ContactMaterial to make an object suitable for ...
Definition: ContactSurface.h:342
ContactMaterial & setStiffness(Real stiffness)
Supply material stiffness k=(force/area)/%strain.
Definition: ContactSurface.h:182
bool isInSameClique(const ContactSurface &other) const
Determine whether this contact surface is a member of any of the same cliques as some other contact s...
Definition: ContactSurface.h:422
int getIndexOnBody() const
Return the index that was supplied to the most recent setIndexOnBody() call for this ContactSurface o...
Definition: ContactSurface.h:493
static ContactCliqueId createNewContactClique()
Create a new contact clique and return its unique integer id (thread safe).
Definition: ContactSurface.h:456
void clear()
Restore this contact material to an invalid state containing no stiffness specification and default v...
Definition: ContactSurface.h:287
const T & back() const
Return a const reference to the last element in this array, which must not be empty.
Definition: Array.h:2337
ContactSurface & setShape(const ContactGeometry &shape)
Define a new shape for this ContactSurface.
Definition: ContactSurface.h:357
ContactMaterial(Real stiffness, Real dissipation, Real staticFriction, Real dynamicFriction, Real viscousFriction=0)
Create a contact material with a complete set of compliant contact material properties.
Definition: ContactSurface.h:136
ContactSurface()
Create an empty ContactSurface.
Definition: ContactSurface.h:345