iMSTK
Interactive Medical Simulation Toolkit
imstkPbdConstraint.h
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #pragma once
8 
9 #include "imstkPbdBody.h"
10 
11 namespace imstk
12 {
17 using PbdParticleId = std::pair<int, int>;
18 
25 {
26 public:
30  enum class SolverType
31  {
32  xPBD = 0,
33  PBD
34  };
35 
36  PbdConstraint() = default;
37  virtual ~PbdConstraint() = default;
38 
39  virtual const std::string getTypeName() const = 0;
40 
47  virtual bool computeValueAndGradient(PbdState& bodies,
48  double& c, std::vector<Vec3d>& dcdx) = 0;
49 
53  std::vector<PbdParticleId>& getParticles() { return m_particles; }
54 
58  double getRestitution() const { return m_restitution; }
59  void setRestitution(const double restitution) { m_restitution = restitution; }
61 
65  double getFriction() const { return m_friction; }
66  void setFriction(const double friction) { m_friction = friction; }
68 
72  double getStiffness() const { return m_stiffness; }
73  void setStiffness(const double stiffness)
74  {
75  m_stiffness = stiffness;
76  CHECK(m_stiffness != 0.0) << "0 stiffness is invalid";
77  // This is a bit ambigiuous
78  m_compliance = 1.0 / stiffness;
79  }
80 
82 
87  double getCompliance() const { return m_compliance; }
88  void setCompliance(const double compliance)
89  {
90  m_compliance = compliance;
91  // 0 compliance implies infinite stiffness, instead set stiffness to 1.0
92  // which is a convienent value for collision/unilateral constraints solved
93  // under PBD
94  m_stiffness = (m_compliance == 0.0) ? 1.0 : 1.0 / m_compliance;
95  }
96 
98 
102  bool getCorrectVelocity() const { return m_correctVelocity; }
103  void setCorrectVelocity(const bool correctVelocity) { m_correctVelocity = correctVelocity; }
104 
108  const Vec3d& getGradient(const int i) const { return m_dcdx[i]; }
109 
114  double getForce(const double dt) const { return m_lambda / (dt * dt); }
115 
119  double getConstraintC() const { return m_C; }
120 
124  double getLambda() const { return m_lambda; }
125 
130  virtual double getRestValue() const { return 0.0; }
131 
136  void zeroOutLambda() { m_lambda = 0.0; }
137 
141  virtual void projectConstraint(PbdState& bodies, const double dt, const SolverType& type);
142 
147  virtual void correctVelocity(PbdState& bodies, const double dt);
148 
155  inline double computeGeneralizedInvMass(const PbdState& bodies, const size_t particleIndex) const
156  {
157  return bodies.getInvMass(m_particles[particleIndex]);
158  }
159 
167  inline double computeGeneralizedInvMass(const PbdState& bodies,
168  const size_t particleIndex, const Vec3d& r) const
169  {
170  const PbdParticleId& pid = m_particles[particleIndex];
171 
172  // Compute generalized inverse mass sum
173  const double invMass = bodies.getInvMass(pid);
174  if (bodies.getBodyType(pid) == PbdBody::Type::RIGID)
175  {
176  const Quatd invOrientation = bodies.getOrientation(pid).inverse();
177  const Mat3d& invInteria = bodies.getInvInertia(pid);
178  const Vec3d l = invOrientation._transformVector(r.cross(m_dcdx[particleIndex]));
179  // Assumes inertia is diagonal, always in unrotated state
180  return l[0] * l[0] * invInteria(0, 0) +
181  l[1] * l[1] * invInteria(1, 1) +
182  l[2] * l[2] * invInteria(2, 2) + invMass;
183  }
184  else
185  {
186  return invMass;
187  }
188  }
189 
190 protected:
191  PbdConstraint(const size_t numParticles)
192  {
193  m_particles.resize(numParticles);
194  m_dcdx.resize(numParticles);
195  }
196 
197  std::vector<PbdParticleId> m_particles;
198  std::vector<Vec3d> m_dcdx;
199 
200  double m_stiffness = 1.0;
201  double m_compliance = 1e-7;
202  double m_lambda = 0.0;
203  double m_C = 0.0;
204  double m_friction = 0.0;
205  double m_restitution = 0.0;
206  bool m_correctVelocity = false;
207 };
208 } // namespace imstk
std::vector< Vec3d > m_dcdx
Normalized constraint gradients (per particle)
std::pair< int, int > PbdParticleId
Index pair that refers to a particle in a PbdState. Index 0 is the body id, Index 1 is the particle i...
double m_lambda
Lagrange multiplier.
std::vector< PbdParticleId > m_particles
body, particle index
double getCompliance() const
Get/Set the compliance This function is also provided in case users need 0 compliance.
double getRestitution() const
Get/Set restitution.
double computeGeneralizedInvMass(const PbdState &bodies, const size_t particleIndex) const
Compute generalized inverse mass of the particle. Note perf sensitive function. It has been intention...
Compound Geometry.
double getConstraintC() const
Get constraint value C (how much the constraint is violated)
double m_compliance
used in xPBD, inverse of Stiffness
const Vec3d & getGradient(const int i) const
Get gradient given the particle index in constraint.
virtual double getRestValue() const
Get reference constraint value. This value will have different context depending on the constraint be...
double computeGeneralizedInvMass(const PbdState &bodies, const size_t particleIndex, const Vec3d &r) const
Compute generalized inverse mass of the particle.
virtual bool computeValueAndGradient(PbdState &bodies, double &c, std::vector< Vec3d > &dcdx)=0
Compute value and gradient of the constraint.
double getForce(const double dt) const
Get the force magnitude, valid after solving lambda Only valid with xpbd.
double getLambda() const
Get constraint value C (how much the constraint is violated)
double m_stiffness
used in PBD, [0, 1]
bool getCorrectVelocity() const
Get/Set whether velocity should be corrected for this constraint.
Base Constraint class for Position based dynamics constraints.
void zeroOutLambda()
Zero&#39;s out the lagrange multplier before integration only used for xpbd, must be called before solvin...
SolverType
Type of solvers.
double m_C
Constraint Value.
std::vector< PbdParticleId > & getParticles()
Get the vertex indices of the constraint.
virtual void projectConstraint(PbdState &bodies, const double dt, const SolverType &type)
Update positions by projecting constraints.
virtual void correctVelocity(PbdState &bodies, const double dt)
Correct velocities according to friction and restitution Corrects according to the gradient direction...
Provides interface for accessing particles from a 2d array of PbdBody,Particles.
Definition: imstkPbdBody.h:229
double getStiffness() const
Get/Set the stiffness.
double getFriction() const
Get/Set friction.