iMSTK
Interactive Medical Simulation Toolkit
imstkPbdObjectGrasping.cpp
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 #include "imstkPbdObjectGrasping.h"
8 #include "imstkAnalyticalGeometry.h"
9 #include "imstkCDObjectFactory.h"
10 #include "imstkCellPicker.h"
11 #include "imstkLineMesh.h"
12 #include "imstkPbdBaryPointToPointConstraint.h"
13 #include "imstkPbdContactConstraint.h"
14 #include "imstkPbdModel.h"
15 #include "imstkPbdObject.h"
16 #include "imstkPbdSolver.h"
17 #include "imstkPointPicker.h"
18 #include "imstkPointwiseMap.h"
19 #include "imstkSurfaceMesh.h"
20 #include "imstkTaskGraph.h"
21 #include "imstkTetrahedralMesh.h"
22 #include "imstkVertexPicker.h"
23 #include "imstkPbdAngularConstraint.h"
24 
25 namespace imstk
26 {
34 {
35  // You can grasp a deformable or rigid
36  enum class Type
37  {
38  Deformable,
39  Rigid
40  };
41 
42  GraspedData() = default;
43 
44  PbdObject* pbdObj = nullptr;
45  Type objType = Type::Deformable;
46 
47  VecDataArray<double, 3>* vertices = nullptr;
48  AbstractDataArray* indices = nullptr;
49  PointwiseMap* map = nullptr;
50  int bodyId = -1;
51 };
52 
53 static GraspedData
54 unpackGraspedSide(std::shared_ptr<PbdObject> obj,
55  std::shared_ptr<Geometry> geometry,
56  std::shared_ptr<GeometryMap> geomMap)
57 {
58  GraspedData data;
59  data.pbdObj = obj.get();
60  data.bodyId = obj->getPbdBody()->bodyHandle;
61  if (obj->getPbdBody()->bodyType == PbdBody::Type::RIGID)
62  {
63  data.objType = GraspedData::Type::Rigid;
64  }
65  else
66  {
67  data.objType = GraspedData::Type::Deformable;
68  }
69 
70  if (auto pointSetToPick = std::dynamic_pointer_cast<PointSet>(geometry))
71  {
72  // Always should be the data that is constrained (ie: the physics mesh)
73  data.vertices = std::dynamic_pointer_cast<PointSet>(obj->getPhysicsGeometry())->getVertexPositions().get();
74 
75  // This should stil be the picked geometry
76  std::shared_ptr<AbstractDataArray> indicesPtr = nullptr;
77  if (auto cellMesh = std::dynamic_pointer_cast<AbstractCellMesh>(pointSetToPick))
78  {
79  data.indices = cellMesh->getAbstractCells().get();
80  }
81 
82  // If the user tries to pick
83  if (geomMap != nullptr)
84  {
85  if (auto ptMap = std::dynamic_pointer_cast<PointwiseMap>(geomMap))
86  {
87  data.map = ptMap.get();
88  }
89  }
90  }
91  return data;
92 }
93 
101 {
102  // You can grasp with a geometry or with another pbd object
103  enum class Type
104  {
105  Geometry,
106  Rigid
107  };
108 
109  GrasperData() = default;
110 
111  Type objType = Type::Geometry;
112  PbdObject* pbdObj = nullptr;
113  Geometry* grasperGeometry = nullptr;
114  int bodyId = -1;
115 };
116 
117 static GrasperData
118 unpackGrasperSide(std::shared_ptr<PbdObject> grasperObject,
119  std::shared_ptr<Geometry> grasperGeometry)
120 {
121  GrasperData data;
122  data.objType = GrasperData::Type::Geometry;
123  if (grasperObject != nullptr)
124  {
125  data.bodyId = grasperObject->getPbdBody()->bodyHandle;
126  data.pbdObj = grasperObject.get();
127  data.objType = GrasperData::Type::Rigid;
128  }
129 
130  data.grasperGeometry = grasperGeometry.get();
131  return data;
132 }
133 
134 template<int N>
135 static std::vector<PbdParticleId>
136 getElement(const PickData& pickData, const GraspedData& side)
137 {
138  std::vector<PbdParticleId> results(N);
139  if (pickData.idCount == 1 && pickData.cellType != IMSTK_VERTEX) // If given cell index
140  {
141  const Eigen::Matrix<int, N, 1>& cell = (*dynamic_cast<VecDataArray<int, N>*>(side.indices))[pickData.ids[0]];
142  for (int i = 0; i < N; i++)
143  {
144  int vertexId = cell[i];
145  if (side.map != nullptr)
146  {
147  vertexId = side.map->getParentVertexId(vertexId);
148  }
149  results[i] = { side.bodyId, vertexId };
150  }
151  }
152  else // If given vertex indices
153  {
154  for (int i = 0; i < N; i++)
155  {
156  int vertexId = pickData.ids[i];
157  if (side.map != nullptr)
158  {
159  vertexId = side.map->getParentVertexId(vertexId);
160  }
161  results[i] = { side.bodyId, vertexId };
162  }
163  }
164  return results;
165 }
166 
167 static std::vector<double>
168 getWeights(const PbdState& bodies, const std::vector<PbdParticleId>& particles, const Vec3d& pt)
169 {
170  std::vector<double> weights(particles.size());
171  if (particles.size() == 4)
172  {
173  const Vec4d baryCoord = baryCentric(pt,
174  bodies.getPosition(particles[0]),
175  bodies.getPosition(particles[1]),
176  bodies.getPosition(particles[2]),
177  bodies.getPosition(particles[3]));
178  weights[0] = baryCoord[0];
179  weights[1] = baryCoord[1];
180  weights[2] = baryCoord[2];
181  weights[3] = baryCoord[3];
182  }
183  else if (particles.size() == 3)
184  {
185  const Vec3d baryCoord = baryCentric(pt,
186  bodies.getPosition(particles[0]),
187  bodies.getPosition(particles[1]),
188  bodies.getPosition(particles[2]));
189  weights[0] = baryCoord[0];
190  weights[1] = baryCoord[1];
191  weights[2] = baryCoord[2];
192  }
193  else if (particles.size() == 2)
194  {
195  const Vec2d baryCoord = baryCentric(pt,
196  bodies.getPosition(particles[0]),
197  bodies.getPosition(particles[1]));
198  weights[0] = baryCoord[0];
199  weights[1] = baryCoord[1];
200  }
201  else if (particles.size() == 1)
202  {
203  weights[0] = 1.0;
204  }
205  return weights;
206 }
207 
208 PbdObjectGrasping::PbdObjectGrasping(std::shared_ptr<PbdObject> graspedObject,
209  std::shared_ptr<PbdObject> grasperObject) :
210  m_objectToGrasp(graspedObject),
211  m_grasperObject(grasperObject),
212  m_pickMethod(std::make_shared<CellPicker>())
213 {
214  m_pickingNode = std::make_shared<TaskNode>(std::bind(&PbdObjectGrasping::updatePicking, this),
215  "PbdPickingUpdate", true);
216  m_taskGraph->addNode(m_pickingNode);
217 
218  m_taskGraph->addNode(m_objectToGrasp->getTaskGraph()->getSource());
219  m_taskGraph->addNode(m_objectToGrasp->getTaskGraph()->getSink());
220 
221  m_taskGraph->addNode(m_objectToGrasp->getPbdModel()->getSolveNode());
222  m_taskGraph->addNode(m_objectToGrasp->getPbdModel()->getIntegratePositionNode());
223 
224  if (grasperObject != nullptr)
225  {
226  CHECK(grasperObject->getPbdModel() == m_objectToGrasp->getPbdModel()) <<
227  "Grasper object and object to grasp must shared a PbdModel";
228  m_taskGraph->addNode(grasperObject->getTaskGraph()->getSource());
229  m_taskGraph->addNode(grasperObject->getTaskGraph()->getSink());
230  }
231 }
232 
233 void
234 PbdObjectGrasping::beginVertexGrasp(std::shared_ptr<AnalyticalGeometry> geometry)
235 {
236  auto vertexPicker = std::make_shared<VertexPicker>();
237  vertexPicker->setPickingGeometry(geometry);
238  m_pickMethod = vertexPicker;
239  m_graspMode = GraspMode::Vertex;
240  m_graspGeom = geometry;
241 
242  m_isGrasping = true;
243  // LOG(INFO) << "Begin grasp";
244 }
245 
246 void
247 PbdObjectGrasping::beginCellGrasp(std::shared_ptr<AnalyticalGeometry> geometry, std::string cdType)
248 {
249  auto cellPicker = std::make_shared<CellPicker>();
250  cellPicker->setPickingGeometry(geometry);
251 
252  // If no cd provided try to automatically pick one
253  if (cdType == "")
254  {
255  std::shared_ptr<Geometry> pbdPhysicsGeom = m_objectToGrasp->getPhysicsGeometry();
256 
257  // If a specific geometry wasn't specified to pick, then use the physics geometry
258  std::shared_ptr<Geometry> geomtryToPick = (m_geomToPick == nullptr) ? pbdPhysicsGeom : m_geomToPick;
259  cdType = CDObjectFactory::getCDType(*geometry, *geomtryToPick);
260  }
261  cellPicker->setCollisionDetection(CDObjectFactory::makeCollisionDetection(cdType));
262 
263  m_pickMethod = cellPicker;
264  m_graspMode = GraspMode::Cell;
265  m_graspGeom = geometry;
266 
267  m_isGrasping = true;
268 }
269 
270 void
271 PbdObjectGrasping::beginRayPointGrasp(std::shared_ptr<AnalyticalGeometry> geometry,
272  const Vec3d& rayStart, const Vec3d& rayDir, const double maxDist)
273 {
274  auto pointPicker = std::make_shared<PointPicker>();
275  pointPicker->setPickingRay(rayStart, rayDir, maxDist);
276  m_pickMethod = pointPicker;
277  m_graspMode = GraspMode::RayPoint;
278  m_graspGeom = geometry;
279 
280  m_isGrasping = true;
281 }
282 
283 void
284 PbdObjectGrasping::beginRayCellGrasp(std::shared_ptr<AnalyticalGeometry> geometry,
285  const Vec3d& rayStart, const Vec3d& rayDir, const double maxDist)
286 {
287  auto pointPicker = std::make_shared<PointPicker>();
288  pointPicker->setPickingRay(rayStart, rayDir, maxDist);
289  m_pickMethod = pointPicker;
290  m_graspMode = GraspMode::RayCell;
291  m_graspGeom = geometry;
292 
293  m_isGrasping = true;
294 }
295 
296 void
298 {
299  m_isGrasping = false;
300 }
301 
302 void
304 {
305  m_constraints.clear();
306  m_constraintPts.clear();
307  m_collisionConstraints.clear();
308 }
309 
310 void
312 {
314  std::shared_ptr<PbdModel> model = m_objectToGrasp->getPbdModel();
315  std::shared_ptr<Geometry> pbdPhysicsGeom = m_objectToGrasp->getPhysicsGeometry();
316 
317  // If a specific geometry wasn't specified to pick, then use the physics geometry
318  std::shared_ptr<Geometry> geomtryToPick = (m_geomToPick == nullptr) ? pbdPhysicsGeom : m_geomToPick;
319 
320  GraspedData graspedData = unpackGraspedSide(m_objectToGrasp, geomtryToPick, m_geometryToPickMap);
321  GrasperData grasperData = unpackGrasperSide(m_grasperObject, m_graspGeom);
322 
323  const Vec3d& pickGeomPos = m_graspGeom->getPosition();
324  const Mat3d pickGeomRot = m_graspGeom->getRotation().transpose();
325 
326  // Perform the picking
327  const std::vector<PickData>& pickData = m_pickMethod->pick(geomtryToPick);
328 
329  // Digest the pick data based on grasp mode
330  if (m_graspMode == GraspMode::Vertex)
331  {
332  for (size_t i = 0; i < pickData.size(); i++)
333  {
334  const PickData& data = pickData[i];
335  int vertexId = data.ids[0];
336  if (graspedData.map != nullptr)
337  {
338  vertexId = graspedData.map->getParentVertexId(vertexId);
339  }
340 
341  if (graspedData.objType == GraspedData::Type::Deformable
342  && grasperData.objType == GrasperData::Type::Geometry)
343  {
344  const Vec3d relativePos = pickGeomRot * ((*graspedData.vertices)[vertexId] - pickGeomPos);
345  const PbdParticleId graspPointPid = model->addVirtualParticle((*graspedData.vertices)[vertexId], 0.0);
346  m_constraintPts.push_back({ graspPointPid, relativePos });
347 
349  { { graspedData.bodyId, vertexId } }, { 1.0 },
350  { graspPointPid }, { 1.0 },
351  m_stiffness, 0.0);
352  }
353  else if (graspedData.objType == GraspedData::Type::Deformable
354  && grasperData.objType == GrasperData::Type::Rigid)
355  {
357  { graspedData.bodyId, vertexId },
358  { grasperData.bodyId, 0 },
359  (*graspedData.vertices)[vertexId],
360  m_compliance);
361  }
362  }
363  }
364  else if (m_graspMode == GraspMode::Cell || m_graspMode == GraspMode::RayCell)
365  {
366  for (size_t i = 0; i < pickData.size(); i++)
367  {
368  const PickData& data = pickData[i];
369  const CellTypeId pickedCellType = data.cellType;
370 
371  // If we select something without ids (typically analytic geometry)
372  if (data.idCount == 0)
373  {
374  // Just add one constraint at the pick point
375  if (graspedData.objType == GraspedData::Type::Rigid)
376  {
377  if (grasperData.objType == GrasperData::Type::Geometry)
378  {
379  LOG(FATAL) << "Grasping rigid with static geometry (analytic) not supported";
380  }
381  else if (grasperData.objType == GrasperData::Type::Rigid)
382  {
384  { grasperData.bodyId, 0 },
385  { graspedData.bodyId, 0 },
386  data.pickPoint,
387  m_compliance);
388  }
389  }
390  else
391  {
392  LOG(FATAL) << "Grasping deformable without any ids not supported";
393  }
394  }
395  // If we select something with ids (typically meshes)
396  else
397  {
398  // Get vertices selected (if cells selected, get vertices of those cells)
399  std::vector<PbdParticleId> particles;
400  if (pickedCellType == IMSTK_TETRAHEDRON)
401  {
402  particles = getElement<4>(data, graspedData);
403  }
404  else if (pickedCellType == IMSTK_TRIANGLE)
405  {
406  particles = getElement<3>(data, graspedData);
407  }
408  else if (pickedCellType == IMSTK_EDGE)
409  {
410  particles = getElement<2>(data, graspedData);
411  }
412  else if (pickedCellType == IMSTK_VERTEX)
413  {
414  particles = getElement<1>(data, graspedData);
415  }
416 
417  // Does not resolve duplicate vertices yet, but implicit solve makes that ok
418  for (size_t j = 0; j < particles.size(); j++)
419  {
420  const int vertexId = particles[j].second;
421  const Vec3d& vertexPos = (*graspedData.vertices)[vertexId];
422 
423  // If grasper is rigid
424  if (grasperData.objType == GrasperData::Type::Rigid)
425  {
426  // If grasped is a mesh, at pbd particle poitn to pbd body constraint
427  if (graspedData.objType == GraspedData::Type::Deformable)
428  {
429  // Deformable point to body constraint
430  addPointToBodyConstraint(particles[j],
431  { grasperData.bodyId, 0 },
432  vertexPos,
433  m_compliance);
434  }
435  // If grasped is a rigid (but still has a mesh), add body to body constraint
436  else if (graspedData.objType == GraspedData::Type::Rigid)
437  {
439  { grasperData.bodyId, 0 },
440  { graspedData.bodyId, 0 },
441  vertexPos,
442  m_compliance);
443  }
444  }
445  // If grasper is not rigid, static/unsimulated, then add virtual
446  // points moved around relative to the grasping geometry (in updateConstraints)
447  else
448  {
449  // If grasped is a mesh add virtual points at mesh positions
450  if (graspedData.objType == GraspedData::Type::Deformable)
451  {
452  const Vec3d relativePos = pickGeomRot * (vertexPos - pickGeomPos);
453  const PbdParticleId graspPointPid = model->addVirtualParticle(vertexPos, 0.0);
454  m_constraintPts.push_back({ graspPointPid, relativePos });
455 
457  { particles[j] }, { 1.0 },
458  { graspPointPid }, { 1.0 },
459  m_stiffness, 0.0);
460  }
461  else
462  {
463  LOG(FATAL) << "Grasping rigid with static geometry (mesh) not supported";
464  }
465  }
466  }
467  }
468  }
469  }
470  else if (m_graspMode == GraspMode::RayPoint)
471  {
472  for (size_t i = 0; i < pickData.size(); i++)
473  {
474  const PickData& data = pickData[i];
475  const CellTypeId pickedCellType = data.cellType;
476 
477  std::vector<PbdParticleId> particles;
478  if (pickedCellType == IMSTK_TETRAHEDRON)
479  {
480  particles = getElement<4>(data, graspedData);
481  }
482  else if (pickedCellType == IMSTK_TRIANGLE)
483  {
484  particles = getElement<3>(data, graspedData);
485  }
486  else if (pickedCellType == IMSTK_EDGE)
487  {
488  particles = getElement<2>(data, graspedData);
489  }
490 
491  // The point to constrain the element too
492  const Vec3d pickingPt = data.pickPoint;
493 
494  std::vector<double> weights = getWeights(model->getBodies(), particles, pickingPt);
495 
496  const Vec3d relativePos = pickGeomRot * (pickingPt - pickGeomPos);
497  const PbdParticleId graspPointPid = model->addVirtualParticle(pickingPt, 0.0);
498  m_constraintPts.push_back({ graspPointPid, relativePos });
499 
500  // Cell to single point constraint
502  particles, weights,
503  { graspPointPid }, { 1.0 },
504  m_stiffness, 0.0);
505  }
506  }
507 
508  if (m_constraints.size() == 0)
509  {
510  m_isGrasping = false;
511  }
512 
513  m_collisionConstraints.reserve(m_constraints.size());
514  for (int i = 0; i < m_constraints.size(); i++)
515  {
516  m_collisionConstraints.push_back(m_constraints[i].get());
517  }
518 }
519 
520 void
522  const std::vector<PbdParticleId>& ptsA,
523  const std::vector<double>& weightsA,
524  const std::vector<PbdParticleId>& ptsB,
525  const std::vector<double>& weightsB,
526  const double stiffnessA, const double stiffnessB)
527 {
528  auto constraint = std::make_shared<PbdBaryPointToPointConstraint>();
529  constraint->initConstraint(
530  ptsA, weightsA,
531  ptsB, weightsB,
532  stiffnessA, stiffnessB);
533  m_constraints.push_back(constraint);
534 }
535 
536 void
538  const PbdParticleId& graspedBodyId,
539  const PbdParticleId& grasperBodyId,
540  const Vec3d& supportPt,
541  const double compliance)
542 {
543  std::shared_ptr<PbdModel> model = m_objectToGrasp->getPbdModel();
544 
545  // Rigid on rigid grasping
546  // Constrain supportPt on body0 to supportPt on body1 by a distance of 0
547  auto constraint = std::make_shared<PbdBodyToBodyDistanceConstraint>();
548  constraint->initConstraint(
549  model->getBodies(),
550  graspedBodyId,
551  supportPt,
552  grasperBodyId,
553  supportPt,
554  0.0, compliance);
555  m_constraints.push_back(constraint);
556  auto angularConstraint = std::make_shared<PbdAngularDistanceConstraint>();
557  angularConstraint->initConstraintOffset(model->getBodies(),
558  graspedBodyId, grasperBodyId, 0.0);
559  m_constraints.push_back(angularConstraint);
560 }
561 
562 void
564  const PbdParticleId& graspedParticleId,
565  const PbdParticleId& grasperBodyId,
566  const Vec3d& pointOnBody,
567  const double compliance)
568 {
569  std::shared_ptr<PbdModel> model = m_objectToGrasp->getPbdModel();
570 
571  // Rigid on deformable
572  // Constrain supportPt on body0 to supportPt on body1 by a distance of 0
573  auto constraint = std::make_shared<PbdBodyToBodyDistanceConstraint>();
574  constraint->initConstraint(
575  model->getBodies(),
576  grasperBodyId,
577  pointOnBody,
578  graspedParticleId,
579  0.0, compliance);
580  m_constraints.push_back(constraint);
581 }
582 
583 void
585 {
586  // If started picking
587  if ((!m_isPrevGrasping && m_isGrasping) || m_regrasp)
588  {
589  m_objectToGrasp->updateGeometries();
591  m_regrasp = false;
592  }
593 
594  // If stopped picking
595  if (!m_isGrasping && m_isPrevGrasping)
596  {
597  m_objectToGrasp->updateGeometries();
599  }
600  // Push back the picking state
601  m_isPrevGrasping = m_isGrasping;
602 
603  if (m_isGrasping)
604  {
605  m_objectToGrasp->updateGeometries();
607  }
608 }
609 
610 void
612 {
613  std::shared_ptr<PbdModel> model = m_objectToGrasp->getPbdModel();
614 
615  // Update the grasp points when not doing two-way.
616  // In two-way the points are automatically recomputed in the constraint relative
617  // to the rigid body (via local position saved).
618  // When not doing two-way we need to update the points manually.
619  if (m_grasperObject == nullptr)
620  {
621  const Vec3d& pos = m_graspGeom->getPosition();
622  const Mat3d rot = m_graspGeom->getRotation();
623  for (size_t i = 0; i < m_constraintPts.size(); i++)
624  {
625  std::tuple<PbdParticleId, Vec3d>& cPt = m_constraintPts[i];
626  std::shared_ptr<PbdConstraint> c = m_constraints[i];
627 
628  // Because virtual particles are cleared everytime, re-add, also update the transform
629  const Vec3d relativePos = std::get<1>(cPt);
630  const Vec3d vPos = pos + rot * relativePos;
631  const PbdParticleId vPid = model->addVirtualParticle(vPos, 0.0);
632  // Then update the particle id (by convention the last particle is the virtual grasp point)
633  c->getParticles().back() = vPid;
634  }
635  }
636 
637  if (m_collisionConstraints.size() > 0)
638  {
639  model->getSolver()->addConstraints(&m_collisionConstraints);
640  }
641 }
642 
643 void
644 PbdObjectGrasping::initGraphEdges(std::shared_ptr<TaskNode> source, std::shared_ptr<TaskNode> sink)
645 {
646  std::shared_ptr<PbdModel> pbdModel = m_objectToGrasp->getPbdModel();
647 
648  // Add source and sink connections for a valid graph at all times
649  m_taskGraph->addEdge(source, m_objectToGrasp->getTaskGraph()->getSource());
650  m_taskGraph->addEdge(m_objectToGrasp->getTaskGraph()->getSink(), sink);
651 
652  if (m_grasperObject != nullptr)
653  {
654  m_taskGraph->addEdge(source, m_grasperObject->getTaskGraph()->getSource());
655  m_taskGraph->addEdge(m_grasperObject->getTaskGraph()->getSink(), sink);
656  }
657 
658  // The ideal location is after the internal positional solve, but before collisions are solved
659  m_taskGraph->addEdge(pbdModel->getIntegratePositionNode(), m_pickingNode);
660  m_taskGraph->addEdge(m_pickingNode, pbdModel->getSolveNode());
661 }
662 
663 bool
665 {
666  return !m_constraints.empty();
667 }
668 } // namespace imstk
PbdObjectGrasping(std::shared_ptr< PbdObject > graspedObject, std::shared_ptr< PbdObject > grasperObject=nullptr)
Construct PbdObjectGrasping with a object to grasp and and optionally an object that does the graspin...
Base class for all geometries represented by discrete points and elements The pointsets follow a pipe...
Definition: imstkPointSet.h:25
void endGrasp()
End a grasp (picking will end on next update)
virtual void addPointToBodyConstraint(const PbdParticleId &graspedParticleId, const PbdParticleId &grasperBodyId, const Vec3d &pointOnBody, const double compliance)
Add a 0 distance constraint between a deformable point and a point on a body.
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...
virtual void addPointToPointConstraint(const std::vector< PbdParticleId > &ptsA, const std::vector< double > &weightsA, const std::vector< PbdParticleId > &ptsB, const std::vector< double > &weightsB, const double stiffnessA, const double stiffnessB)
Add constraint between a point on each element given via barycentric coordinates pt position = weight...
Compound Geometry.
bool m_regrasp
Add grasped points to the current grasp.
void beginRayCellGrasp(std::shared_ptr< AnalyticalGeometry > geometry, const Vec3d &rayStart, const Vec3d &rayDir, const double maxDist=-1.0)
Begin a ray point grasp (picking will begin on the next update)
std::vector< std::shared_ptr< PbdConstraint > > m_constraints
List of PBD constraints.
bool hasConstraints() const
Returns if any grasp constraints are present.
This class serves as the base class of DataArray, for typeless use.
int idCount
Indicates number of vertices (if 1 a cell or individual vertex)
int getParentVertexId(const int childVertexId) const
Get the mapped/corresponding parent index, given a child index. returns -1 if no correspondence found...
static std::shared_ptr< CollisionDetectionAlgorithm > makeCollisionDetection(const std::string collisionTypeName)
attempts to create a new CD algorithm
Vec3d pickPoint
Some pickings may produce specific points on an element.
Base class for any geometrical representation.
Definition: imstkGeometry.h:22
PickData provides ids to indicate what was picked These may be optionally used to indicate the select...
Base class for scene objects that move and/or deform under position based dynamics formulation...
void beginCellGrasp(std::shared_ptr< AnalyticalGeometry > geometry, std::string cdType="")
Begin a cell grasp (picking will begin on the next update) Also works for rigid on rigid...
void beginRayPointGrasp(std::shared_ptr< AnalyticalGeometry > geometry, const Vec3d &rayStart, const Vec3d &rayDir, const double maxDist=-1.0)
Begin a ray point grasp (picking will begin on the next update)
static std::string getCDType(const Geometry &obj1, const Geometry &obj2)
Get the CD type from the types of objects colliding.
PointwiseMap can compute & apply a mapping between parent and child PointSet geometries.
void updateConstraints()
Update the constraints used for picking.
void removePickConstraints()
Remove the constraints for picking.
GrasperData is either a ray, a grasping geometry, or another PbdObject (rigid)
void addPickConstraints()
Compute/generate the constraints for picking.
std::shared_ptr< TaskGraph > m_taskGraph
Computational Graph.
Provides interface for accessing particles from a 2d array of PbdBody,Particles.
Definition: imstkPbdBody.h:229
Picks cells of geomToPick via those that that are intersecting pickingGeom.
CellTypeId cellType
Indicates picked cell type.
virtual void addBodyToBodyConstraint(const PbdParticleId &graspedBodyId, const PbdParticleId &grasperBodyId, const Vec3d &pointOnBodies, const double compliance)
Add 0 distance constraint between two points defined on two separate bodies.
Info needed to add a constraint for the grasped object Garunteed to be a PbdObject.
void initGraphEdges()
Initializes the edges of the SceneObject&#39;s computational graph.
virtual void updatePicking()
Update picking state, this should move grasp points.
int ids[4]
Ids of the cell or vertices.
void beginVertexGrasp(std::shared_ptr< AnalyticalGeometry > geometry)
Begin a vertex grasp (picking will begin on the next update)
std::vector< std::tuple< PbdParticleId, Vec3d > > m_constraintPts
Vec of virtual particle grasp point ids, and local positions when grasped.