Simbody  3.5
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 
35 namespace SimTK {
36 
37 class ContactGeometry;
38 
39 SimTK_DEFINE_UNIQUE_INDEX_TYPE(ContactCliqueId);
40 
41 
42 
43 //==============================================================================
44 // CONTACT MATERIAL
45 //==============================================================================
89 public:
93 ContactMaterial() {clear();}
94 
135 ContactMaterial(Real stiffness, Real dissipation,
136  Real staticFriction, Real dynamicFriction,
137  Real viscousFriction = 0) {
138  setStiffness(stiffness);
139  setDissipation(dissipation);
140  setFriction(staticFriction, dynamicFriction, viscousFriction);
141 }
142 
145 bool isValid() const {return m_stiffness > 0;}
146 
149 { SimTK_ERRCHK(isValid(), "ContactMaterial::getStiffness()",
150  "This is an invalid ContactMaterial.");
151  return m_stiffness; }
154 { SimTK_ERRCHK(isValid(), "ContactMaterial::getStiffness23()",
155  "This is an invalid ContactMaterial.");
156  return m_stiffness23; }
159 { SimTK_ERRCHK(isValid(), "ContactMaterial::getDissipation()",
160  "This is an invalid ContactMaterial.");
161  return m_dissipation; }
164 { SimTK_ERRCHK(isValid(), "ContactMaterial::getStaticFriction()",
165  "This is an invalid ContactMaterial.");
166  return m_staticFriction; }
169 { SimTK_ERRCHK(isValid(), "ContactMaterial::getDynamicFriction()",
170  "This is an invalid ContactMaterial.");
171  return m_dynamicFriction; }
174 { SimTK_ERRCHK(isValid(), "ContactMaterial::getViscousFriction()",
175  "This is an invalid ContactMaterial.");
176  return m_viscousFriction; }
177 
182  SimTK_ERRCHK1_ALWAYS(stiffness >= 0, "ContactMaterial::setStiffness()",
183  "Stiffness %g is illegal; must be >= 0.", stiffness);
184  m_stiffness = stiffness;
185  m_stiffness23 = std::pow(m_stiffness, Real(2./3.));
186  return *this;
187 }
188 
193  SimTK_ERRCHK1_ALWAYS(dissipation >= 0, "ContactMaterial::setDissipation()",
194  "Dissipation %g (in 1/speed) is illegal; must be >= 0.", dissipation);
195  m_dissipation = dissipation;
196  return *this;
197 }
198 
201  Real dynamicFriction,
202  Real viscousFriction = 0)
203 {
204  SimTK_ERRCHK1_ALWAYS(0 <= staticFriction, "ContactMaterial::setFriction()",
205  "Illegal static friction coefficient %g.", staticFriction);
206  SimTK_ERRCHK2_ALWAYS(0<=dynamicFriction && dynamicFriction<=staticFriction,
207  "ContactMaterial::setFriction()",
208  "Dynamic coefficient %g illegal; must be between 0 and static"
209  " coefficient %g.", dynamicFriction, staticFriction);
210  SimTK_ERRCHK1_ALWAYS(0 <= viscousFriction, "ContactMaterial::setFriction()",
211  "Illegal viscous friction coefficient %g.", viscousFriction);
212 
213  m_staticFriction = staticFriction;
214  m_dynamicFriction = dynamicFriction;
215  m_viscousFriction = viscousFriction;
216  return *this;
217 }
218 
228 static Real calcPlaneStrainStiffness(Real youngsModulus,
229  Real poissonsRatio)
230 {
231  SimTK_ERRCHK2_ALWAYS(youngsModulus >= 0 &&
232  -1 < poissonsRatio && poissonsRatio <= 0.5,
233  "ContactMaterial::calcStiffnessForSolid()",
234  "Illegal material properties E=%g, v=%g.",
235  youngsModulus, poissonsRatio);
236 
237  return youngsModulus / (1-square(poissonsRatio));
238 }
239 
240 
250  Real poissonsRatio)
251 {
252  SimTK_ERRCHK2_ALWAYS(youngsModulus >= 0 &&
253  -1 < poissonsRatio && poissonsRatio < 0.5,
254  "ContactMaterial::calcStiffnessForSolid()",
255  "Illegal material properties E=%g, v=%g.",
256  youngsModulus, poissonsRatio);
257 
258  return youngsModulus*(1-poissonsRatio)
259  / ((1+poissonsRatio)*(1-2*poissonsRatio));
260 }
261 
273 static Real calcDissipationFromObservedRestitution
274  (Real restitution, Real speed) {
275  if (restitution==1) return 0;
276  SimTK_ERRCHK2_ALWAYS(0<=restitution && restitution<=1 && speed>0,
277  "ContactMaterial::calcDissipationFromRestitution()",
278  "Illegal coefficient of restitution or speed (%g,%g).",
279  restitution, speed);
280  return (1-restitution)/speed;
281 }
282 
286 void clear() {
287  m_stiffness = NaN; // unspecified
288  m_stiffness23 = NaN;
289  m_restitution = NaN; // unspecified
290  m_dissipation = 0; // default; no dissipation
291  // default; no friction
292  m_staticFriction=m_dynamicFriction=m_viscousFriction = 0;
293 }
294 
295 //--------------------------------------------------------------------------
296 private:
297 
298 // For compliant contact models.
299 Real m_stiffness; // k: stress/%strain=(force/area)/%strain
300 Real m_stiffness23; // k^(2/3) in case we need it
301 Real m_dissipation; // c: %normalForce/normalVelocity
302 
303 // For impulsive collisions.
304 Real m_restitution; // e: unitless, e=(1-cv)
305 
306 // Friction.
307 Real m_staticFriction; // us: unitless
308 Real m_dynamicFriction; // ud: unitless
309 Real m_viscousFriction; // uv: %normalForce/slipVelocity
310 };
311 
312 
313 
314 //==============================================================================
315 // CONTACT SURFACE
316 //==============================================================================
333 public:
338  const ContactMaterial& material,
339  Real thickness=0)
340 : m_shape(shape), m_material(material), m_thickness(thickness) {
341  SimTK_ERRCHK1_ALWAYS(thickness >= 0, "ContactSurface::ctor()",
342  "Illegal thickness %g.", thickness);
343 }
344 
347 { m_shape = shape; return *this; }
348 
352  Real thickness = 0)
353 { m_material = material; setThickness(thickness); return *this; }
354 
360  SimTK_ERRCHK1_ALWAYS(thickness >= 0, "ContactSurface::setThickness()",
361  "Illegal thickness %g.", thickness);
362  m_thickness = thickness;
363  return *this;
364 }
365 
367 const ContactGeometry& getShape() const {return m_shape;}
368 
370 const ContactMaterial& getMaterial() const {return m_material;}
371 
374 Real getThickness() const {return m_thickness;}
375 
377 ContactGeometry& updShape() {return m_shape;}
378 
380 ContactMaterial& updMaterial() {return m_material;}
381 
384 ContactSurface& joinClique(ContactCliqueId clique) {
385  if (!clique.isValid()) return *this;
386  // Although this is a sorted list, we expect it to be very short so
387  // are using linear search to find where this new clique goes.
389  for (p = m_cliques.begin(); p != m_cliques.end(); ++p) {
390  if (*p==clique) return *this; // already a member
391  if (*p>clique) break;
392  }
393  // insert just before p (might be at the end)
394  m_cliques.insert(p, clique);
395  return *this;
396 }
397 
400 void leaveClique(ContactCliqueId clique) {
401  if (!clique.isValid()) return;
402  // We expect this to be a very short list so are using linear search.
404  std::find(m_cliques.begin(), m_cliques.end(), clique);
405  if (p != m_cliques.end()) m_cliques.erase(p);
406 }
407 
411 bool isInSameClique(const ContactSurface& other) const
412 { if (getCliques().empty() || other.getCliques().empty()) return false;//typical
413  return cliquesIntersect(getCliques(), other.getCliques()); }
414 
417 const Array_<ContactCliqueId,short>& getCliques() const {return m_cliques;}
418 
424 {
427  // Quick checks: empty or non-overlapping.
428  if (ap==a.end() || bp==b.end()) return false;
429  if (*ap > b.back() || *bp > a.back())
430  return false; // disjoint
431  // Both lists have elements and the elements overlap numerically.
432  while (true) {
433  if (*ap==*bp) return true;
434  // Increment the list with smaller front element.
435  if (*ap < *bp) {++ap; if (ap==a.end()) break;}
436  else {++bp; if (bp==b.end()) break;}
437  }
438  // One of the lists ran out of elements before we found a match.
439  return false;
440 }
441 
445 static ContactCliqueId createNewContactClique()
446 { static AtomicInteger nextAvailableContactClique = 1;
447  return ContactCliqueId(nextAvailableContactClique++); }
448 
449 //----------------------------------------------------------------------
450  private:
451 
452 ContactGeometry m_shape;
453 ContactMaterial m_material;
454 Real m_thickness; // default=Infinity
455 Array_<ContactCliqueId,short> m_cliques; // sorted
456 };
457 
458 
459 
460 } // namespace SimTK
461 
462 #endif // SimTK_SIMBODY_CONTACT_SURFACE_H_
const T & back() const
Return a const reference to the last element in this array, which must not be empty.
Definition: Array.h:2297
SimTK_DEFINE_UNIQUE_INDEX_TYPE(AssemblyConditionIndex)
ContactSurface(const ContactGeometry &shape, const ContactMaterial &material, Real thickness=0)
Create a ContactSurface with a given shape and material.
Definition: ContactSurface.h:337
Real getViscousFriction() const
Return the coefficient of viscous friction mu_v (1/velocity).
Definition: ContactSurface.h:173
Real getStiffness() const
Return the material stiffness k=(force/area)/%strain.
Definition: ContactSurface.h:148
ContactSurface & setThickness(Real thickness)
Set the thickness of the layer of elastic material coating this contact surface.
Definition: ContactSurface.h:359
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
Real getDynamicFriction() const
Return the coefficient of dynamic friction mu_d (unitless).
Definition: ContactSurface.h:168
#define SimTK_ERRCHK2_ALWAYS(cond, whereChecked, fmt, a1, a2)
Definition: ExceptionMacros.h:289
const ContactMaterial & getMaterial() const
Get read-only access to the material of this contact surface.
Definition: ContactSurface.h:370
Every Simbody header and source file should include this header before any other Simbody header...
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:593
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:411
ContactMaterial & setDissipation(Real dissipation)
Supply material dissipation coefficient c, which is the slope of the coefficient of restitution (e) v...
Definition: ContactSurface.h:192
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:2187
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:2434
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:417
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:351
This class functions exactly like an int, except that the following operators are atomic: ++...
Definition: AtomicInteger.h:44
ContactGeometry & updShape()
Get writable access to the shape of this contact surface.
Definition: ContactSurface.h:377
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:2174
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:249
#define SimTK_ERRCHK1_ALWAYS(cond, whereChecked, fmt, a1)
Definition: ExceptionMacros.h:285
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:2556
The SimTK::Array_<T> container class is a plug-compatible replacement for the C++ standard template l...
Definition: Array.h:50
ContactSurface & joinClique(ContactCliqueId clique)
Join a contact clique if not already a member.
Definition: ContactSurface.h:384
A ContactGeometry object describes the shape of all or part of the boundary of a solid object...
Definition: ContactGeometry.h:110
Real getStiffness23() const
Return precalculated 2/3 power of material stiffness k (k^(2/3)).
Definition: ContactSurface.h:153
const ContactGeometry & getShape() const
Get read-only access to the shape of this contact surface.
Definition: ContactSurface.h:367
ContactMaterial & updMaterial()
Get writable access to the material of this contact surface.
Definition: ContactSurface.h:380
#define SimTK_ERRCHK(cond, whereChecked, msg)
Definition: ExceptionMacros.h:324
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:351
Real getThickness() const
Get the thickness of the elastic material layer on this contact surface, with zero indicating that th...
Definition: ContactSurface.h:374
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:228
bool isValid() const
Return false if material properties have not yet been supplied for this contact material.
Definition: ContactSurface.h:145
void leaveClique(ContactCliqueId clique)
Remove this surface from a contact clique if it is a member.
Definition: ContactSurface.h:400
ContactMaterial & setFriction(Real staticFriction, Real dynamicFriction, Real viscousFriction=0)
Set the friction coefficients for this material.
Definition: ContactSurface.h:200
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:88
ContactMaterial()
Default constructor creates an invalid contact material; you must specify at least stiffness before u...
Definition: ContactSurface.h:93
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:422
#define SimTK_SIMBODY_EXPORT
Definition: Simbody/include/simbody/internal/common.h:72
Real getStaticFriction() const
Return the coefficient of static friction mu_s (unitless).
Definition: ContactSurface.h:163
This class combines a piece of ContactGeometry with a ContactMaterial to make an object suitable for ...
Definition: ContactSurface.h:332
ContactMaterial & setStiffness(Real stiffness)
Supply material stiffness k=(force/area)/%strain.
Definition: ContactSurface.h:181
static ContactCliqueId createNewContactClique()
Create a new contact clique and return its unique integer id (thread safe).
Definition: ContactSurface.h:445
void clear()
Restore this contact material to an invalid state containing no stiffness specification and default v...
Definition: ContactSurface.h:286
bool empty() const
Return true if there are no elements currently stored in this array.
Definition: Array.h:2042
ContactSurface & setShape(const ContactGeometry &shape)
Define a new shape for this ContactSurface.
Definition: ContactSurface.h:346
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:135
Real getDissipation() const
Return the material dissipation coefficient c, in units of 1/velocity.
Definition: ContactSurface.h:158
ContactSurface()
Create an empty ContactSurface.
Definition: ContactSurface.h:335