iMSTK
Interactive Medical Simulation Toolkit
imstkPbdContactConstraint.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 "imstkPbdConstraint.h"
10 
11 namespace imstk
12 {
23 {
24 protected:
25  PbdContactConstraint(const int numParticles) :
26  PbdConstraint(numParticles), m_r(numParticles, Vec3d::Zero()), m_weights(numParticles)
27  {
28  }
29 
30 public:
31  ~PbdContactConstraint() override = default;
32 
33  IMSTK_TYPE_NAME(PbdContactConstraint)
34 
35 
36  void projectConstraint(PbdState& bodies,
39  const double dt, const SolverType& type) override;
40 
41  virtual Vec3d computeRelativeVelocity(PbdState& imstkNotUsed(bodies)) { return Vec3d::Zero(); }
42 
46  const Vec3d& getR(const int i) const { return m_r[i]; }
47 
51  void correctVelocity(PbdState& bodies, const double dt) override;
52 
57  Vec3d getVelocityOnRigidBody(PbdState& bodies, const int bodyId, const Vec3d& pt)
58  {
59  const PbdParticleId pid = { bodyId, 0 };
60  const Vec3d& bodyPos = bodies.getPosition(pid);
61  const Vec3d r = pt - bodyPos;
62 
63  const Vec3d& v = bodies.getVelocity(pid);
64  const Vec3d& w = bodies.getAngularVelocity(pid);
65  return v + w.cross(r);
66  }
67 
71  double getTorque(const double dt, const int i)
72  {
73  const Vec3d force = getForce(dt) * m_dcdx[i];
74  return force.cross(m_r[i]).norm();
75  }
76 
77 protected:
78  std::vector<Vec3d> m_r;
79  std::vector<double> m_weights;
80 };
81 
88 {
89 public:
91 
101  void initConstraint(
102  const PbdState& state,
103  const PbdParticleId& bodyId,
104  const Vec3d contactPtOnBody,
105  const PbdParticleId& x0, const PbdParticleId& x1, const PbdParticleId& x2,
106  const double compliance = 0.0);
107 
108  bool computeInterpolantsAndContact(const PbdState& bodies,
109  std::vector<double>& weights, Vec3d& contactNormal, double& depth) const;
110 
111  bool computeValueAndGradient(PbdState& bodies,
112  double& c,
113  std::vector<Vec3d>& n) override;
114 
115  Vec3d computeRelativeVelocity(PbdState& bodies) override;
116 };
117 
124 {
125 public:
127 
135  void initConstraint(
136  const PbdState& state,
137  const PbdParticleId& bodyId,
138  const Vec3d contactPtOnBody,
139  const PbdParticleId& x0,
140  const double compliance = 0.0);
141 
142  bool computeValueAndGradient(PbdState& bodies,
143  double& c,
144  std::vector<Vec3d>& n) override;
145 
146  Vec3d computeRelativeVelocity(PbdState& bodies) override;
147 };
148 
155 {
156 public:
158 
167  void initConstraint(
168  const PbdState& state,
169  const PbdParticleId& bodyId,
170  const Vec3d contactPtOnBody,
171  const PbdParticleId& x0, const PbdParticleId& x1,
172  const double compliance = 0.0);
173 
174  bool computeInterpolantsAndContact(const PbdState& bodies,
175  std::vector<double>& weights, Vec3d& contactNormal, double& depth) const;
176 
177  bool computeValueAndGradient(PbdState& bodies,
178  double& c,
179  std::vector<Vec3d>& n) override;
180 
181  Vec3d computeRelativeVelocity(PbdState& bodies) override;
182 };
183 
190 {
191 public:
193 
199  const PbdState& state,
200  const PbdParticleId& bodyId0,
201  const Vec3d ptOnBody0,
202  const PbdParticleId& bodyId1,
203  const Vec3d ptOnBody1,
204  const double restLength,
205  const double compliance)
206  {
207  m_particles[0] = bodyId0;
208  // Compute local position on body in rest pose
209  m_r[0] = ptOnBody0 - state.getPosition(bodyId0);
210  m_rest_r[0] = state.getOrientation(bodyId0).inverse()._transformVector(m_r[0]);
211 
212  m_particles[1] = bodyId1;
213  // Compute local position on body
214  m_r[1] = ptOnBody1 - state.getPosition(bodyId1);
215  m_rest_r[1] = state.getOrientation(bodyId1).inverse()._transformVector(m_r[1]);
216 
217  m_restLength = restLength;
218 
219  setCompliance(compliance);
220  }
221 
232  const PbdState& state,
233  const PbdParticleId& bodyId0,
234  const Vec3d ptOnBody0,
235  const PbdParticleId& bodyId1, // Non rigid body
236  const double restLength,
237  const double compliance)
238  {
239  m_particles[0] = bodyId0;
240  // Compute local position on body in rest pose
241  m_r[0] = ptOnBody0 - state.getPosition(bodyId0);
242  m_rest_r[0] = state.getOrientation(bodyId0).inverse()._transformVector(m_r[0]);
243 
244  m_particles[1] = bodyId1;
245 
246  m_restLength = restLength;
247 
248  setCompliance(compliance);
249  }
250 
257  const PbdState& state,
258  const PbdParticleId& bodyId0,
259  const Vec3d ptOnBody0,
260  const PbdParticleId& bodyId1,
261  const Vec3d ptOnBody1,
262  const double compliance)
263  {
264  initConstraint(state, bodyId0, ptOnBody0, bodyId1, ptOnBody1,
265  (ptOnBody1 - ptOnBody0).norm(), compliance);
266  }
267 
268  bool computeValueAndGradient(PbdState& bodies,
269  double& c,
270  std::vector<Vec3d>& n) override;
271 
272 protected:
273  std::array<Vec3d, 2> m_rest_r = { Vec3d::Zero(), Vec3d::Zero() }; // In rest pose
274  double m_restLength = 0.0;
275 };
276 
287 {
288 public:
290 
296  const PbdState& state,
297  const PbdParticleId& bodyId0,
298  const Vec3d contactPt0,
299  const PbdParticleId& bodyId1,
300  const Vec3d contactPt1,
301  const Vec3d contactNormal0To1,
302  const double compliance)
303  {
304  m_particles[0] = bodyId0;
305  // Compute local position on body in rest pose
306  m_r[0] = contactPt0 - state.getPosition(bodyId0);
307  m_rest_r[0] = state.getOrientation(bodyId0).inverse()._transformVector(m_r[0]);
308 
309  m_particles[1] = bodyId1;
310  // Compute local position on body
311  m_r[1] = contactPt1 - state.getPosition(bodyId1);
312  m_rest_r[1] = state.getOrientation(bodyId1).inverse()._transformVector(m_r[1]);
313 
314  m_contactNormal = contactNormal0To1;
315 
316  setCompliance(compliance);
317  }
318 
319  bool computeValueAndGradient(PbdState& bodies,
320  double& c,
321  std::vector<Vec3d>& n) override;
322 
323 protected:
324  std::array<Vec3d, 2> m_rest_r = { Vec3d::Zero(), Vec3d::Zero() }; // In rest pose
325  Vec3d m_contactNormal = Vec3d::Zero();
326 };
327 
334 {
335 public:
337 
338  void initConstraint(
339  const PbdState& state,
340  const PbdParticleId& lineBodyId,
341  const Vec3d lineP, // P in global space
342  const Vec3d lineQ, // Q in global space
343  const PbdParticleId& ptId,
344  const double compliance)
345  {
346  m_particles[0] = lineBodyId;
347  // Compute local position on body in rest pose
348  const Vec3d local_p = lineP - state.getPosition(lineBodyId);
349  m_p_rest = state.getOrientation(lineBodyId).inverse()._transformVector(local_p);
350  const Vec3d local_q = lineQ - state.getPosition(lineBodyId);
351  m_q_rest = state.getOrientation(lineBodyId).inverse()._transformVector(local_q);
352 
353  m_particles[1] = ptId;
354 
355  setCompliance(compliance);
356  }
357 
358  bool computeValueAndGradient(PbdState& bodies,
359  double& c, std::vector<Vec3d>& n) override;
360 
361 protected:
362  Vec3d m_p_rest = Vec3d::Zero();
363  Vec3d m_q_rest = Vec3d::Zero();
364 };
365 } // namespace imstk
std::vector< Vec3d > m_dcdx
Normalized constraint gradients (per particle)
void initConstraint(const PbdState &state, const PbdParticleId &bodyId0, const Vec3d ptOnBody0, const PbdParticleId &bodyId1, const Vec3d ptOnBody1, const double restLength, const double compliance)
Initialize the constraint ptOnBody is global position.
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...
std::vector< PbdParticleId > m_particles
body, particle index
Resolves a point on body to a triangle with linear and angular movement.
void projectConstraint(PbdState &bodies, const double dt, const SolverType &type) override
Update positions by projecting constraints.
void initConstraint(const PbdState &state, const PbdParticleId &bodyId0, const Vec3d contactPt0, const PbdParticleId &bodyId1, const Vec3d contactPt1, const Vec3d contactNormal0To1, const double compliance)
Initialize the constraint ptOnBody is global position.
Compound Geometry.
void correctVelocity(PbdState &bodies, const double dt) override
Solve the velocities given to the constraint.
Resolves a point on body to an edge with linear and angular movement.
virtual bool computeValueAndGradient(PbdState &bodies, double &c, std::vector< Vec3d > &dcdx)=0
Compute value and gradient of the constraint.
void initConstraint(const PbdState &state, const PbdParticleId &bodyId0, const Vec3d ptOnBody0, const PbdParticleId &bodyId1, const Vec3d ptOnBody1, const double compliance)
Initialize the constraint ptOnBody is global position restLength is set to the initial distance betwe...
double getForce(const double dt) const
Get the force magnitude, valid after solving lambda Only valid with xpbd.
void initConstraint(const PbdState &state, const PbdParticleId &bodyId0, const Vec3d ptOnBody0, const PbdParticleId &bodyId1, const double restLength, const double compliance)
Initialize the constraint.
const Vec3d & getR(const int i) const
Get the support point r/the difference to the contact point.
Base Constraint class for Position based dynamics constraints.
Constrain two locally defined points on each body by a given distance.
SolverType
Type of solvers.
Vec3d getVelocityOnRigidBody(PbdState &bodies, const int bodyId, const Vec3d &pt)
Returns the velocity at the given point on body Either body in collision could be rigid body...
This class constrains a rigid line to a fixed point.
Provides interface for accessing particles from a 2d array of PbdBody,Particles.
Definition: imstkPbdBody.h:229
double getTorque(const double dt, const int i)
Get torque magnitude after solve.
A constraint on a rigid body that defines rotationl correction through dx applied at a local position...