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" 45 Type objType = Type::Deformable;
54 unpackGraspedSide(std::shared_ptr<PbdObject> obj,
55 std::shared_ptr<Geometry> geometry,
56 std::shared_ptr<GeometryMap> geomMap)
59 data.pbdObj = obj.get();
60 data.bodyId = obj->getPbdBody()->bodyHandle;
61 if (obj->getPbdBody()->bodyType == PbdBody::Type::RIGID)
63 data.objType = GraspedData::Type::Rigid;
67 data.objType = GraspedData::Type::Deformable;
70 if (
auto pointSetToPick = std::dynamic_pointer_cast<PointSet>(geometry))
73 data.vertices = std::dynamic_pointer_cast<
PointSet>(obj->getPhysicsGeometry())->getVertexPositions().get();
76 std::shared_ptr<AbstractDataArray> indicesPtr =
nullptr;
77 if (
auto cellMesh = std::dynamic_pointer_cast<AbstractCellMesh>(pointSetToPick))
79 data.indices = cellMesh->getAbstractCells().get();
83 if (geomMap !=
nullptr)
85 if (
auto ptMap = std::dynamic_pointer_cast<PointwiseMap>(geomMap))
87 data.map = ptMap.get();
111 Type objType = Type::Geometry;
113 Geometry* grasperGeometry =
nullptr;
118 unpackGrasperSide(std::shared_ptr<PbdObject> grasperObject,
119 std::shared_ptr<Geometry> grasperGeometry)
122 data.objType = GrasperData::Type::Geometry;
123 if (grasperObject !=
nullptr)
125 data.bodyId = grasperObject->getPbdBody()->bodyHandle;
126 data.pbdObj = grasperObject.get();
127 data.objType = GrasperData::Type::Rigid;
130 data.grasperGeometry = grasperGeometry.get();
135 static std::vector<PbdParticleId>
138 std::vector<PbdParticleId> results(N);
142 for (
int i = 0; i < N; i++)
144 int vertexId = cell[i];
145 if (side.map !=
nullptr)
149 results[i] = { side.bodyId, vertexId };
154 for (
int i = 0; i < N; i++)
156 int vertexId = pickData.
ids[i];
157 if (side.map !=
nullptr)
161 results[i] = { side.bodyId, vertexId };
167 static std::vector<double>
168 getWeights(
const PbdState& bodies,
const std::vector<PbdParticleId>& particles,
const Vec3d& pt)
170 std::vector<double> weights(particles.size());
171 if (particles.size() == 4)
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];
183 else if (particles.size() == 3)
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];
193 else if (particles.size() == 2)
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];
201 else if (particles.size() == 1)
209 std::shared_ptr<PbdObject> grasperObject) :
210 m_objectToGrasp(graspedObject),
211 m_grasperObject(grasperObject),
215 "PbdPickingUpdate",
true);
218 m_taskGraph->addNode(m_objectToGrasp->getTaskGraph()->getSource());
219 m_taskGraph->addNode(m_objectToGrasp->getTaskGraph()->getSink());
221 m_taskGraph->addNode(m_objectToGrasp->getPbdModel()->getSolveNode());
222 m_taskGraph->addNode(m_objectToGrasp->getPbdModel()->getIntegratePositionNode());
224 if (grasperObject !=
nullptr)
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());
236 auto vertexPicker = std::make_shared<VertexPicker>();
237 vertexPicker->setPickingGeometry(geometry);
238 m_pickMethod = vertexPicker;
239 m_graspMode = GraspMode::Vertex;
240 m_graspGeom = geometry;
249 auto cellPicker = std::make_shared<CellPicker>();
250 cellPicker->setPickingGeometry(geometry);
255 std::shared_ptr<Geometry> pbdPhysicsGeom = m_objectToGrasp->getPhysicsGeometry();
258 std::shared_ptr<Geometry> geomtryToPick = (m_geomToPick ==
nullptr) ? pbdPhysicsGeom : m_geomToPick;
263 m_pickMethod = cellPicker;
264 m_graspMode = GraspMode::Cell;
265 m_graspGeom = geometry;
272 const Vec3d& rayStart,
const Vec3d& rayDir,
const double maxDist)
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;
285 const Vec3d& rayStart,
const Vec3d& rayDir,
const double maxDist)
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;
299 m_isGrasping =
false;
307 m_collisionConstraints.clear();
314 std::shared_ptr<PbdModel> model = m_objectToGrasp->getPbdModel();
315 std::shared_ptr<Geometry> pbdPhysicsGeom = m_objectToGrasp->getPhysicsGeometry();
318 std::shared_ptr<Geometry> geomtryToPick = (m_geomToPick ==
nullptr) ? pbdPhysicsGeom : m_geomToPick;
320 GraspedData graspedData = unpackGraspedSide(m_objectToGrasp, geomtryToPick, m_geometryToPickMap);
321 GrasperData grasperData = unpackGrasperSide(m_grasperObject, m_graspGeom);
323 const Vec3d& pickGeomPos = m_graspGeom->getPosition();
324 const Mat3d pickGeomRot = m_graspGeom->getRotation().transpose();
327 const std::vector<PickData>& pickData = m_pickMethod->pick(geomtryToPick);
330 if (m_graspMode == GraspMode::Vertex)
332 for (
size_t i = 0; i < pickData.size(); i++)
335 int vertexId = data.
ids[0];
336 if (graspedData.map !=
nullptr)
341 if (graspedData.objType == GraspedData::Type::Deformable
342 && grasperData.objType == GrasperData::Type::Geometry)
344 const Vec3d relativePos = pickGeomRot * ((*graspedData.vertices)[vertexId] - pickGeomPos);
345 const PbdParticleId graspPointPid = model->addVirtualParticle((*graspedData.vertices)[vertexId], 0.0);
349 { { graspedData.bodyId, vertexId } }, { 1.0 },
350 { graspPointPid }, { 1.0 },
353 else if (graspedData.objType == GraspedData::Type::Deformable
354 && grasperData.objType == GrasperData::Type::Rigid)
357 { graspedData.bodyId, vertexId },
358 { grasperData.bodyId, 0 },
359 (*graspedData.vertices)[vertexId],
364 else if (m_graspMode == GraspMode::Cell || m_graspMode == GraspMode::RayCell)
366 for (
size_t i = 0; i < pickData.size(); i++)
369 const CellTypeId pickedCellType = data.
cellType;
375 if (graspedData.objType == GraspedData::Type::Rigid)
377 if (grasperData.objType == GrasperData::Type::Geometry)
379 LOG(FATAL) <<
"Grasping rigid with static geometry (analytic) not supported";
381 else if (grasperData.objType == GrasperData::Type::Rigid)
384 { grasperData.bodyId, 0 },
385 { graspedData.bodyId, 0 },
392 LOG(FATAL) <<
"Grasping deformable without any ids not supported";
399 std::vector<PbdParticleId> particles;
400 if (pickedCellType == IMSTK_TETRAHEDRON)
402 particles = getElement<4>(data, graspedData);
404 else if (pickedCellType == IMSTK_TRIANGLE)
406 particles = getElement<3>(data, graspedData);
408 else if (pickedCellType == IMSTK_EDGE)
410 particles = getElement<2>(data, graspedData);
412 else if (pickedCellType == IMSTK_VERTEX)
414 particles = getElement<1>(data, graspedData);
418 for (
size_t j = 0; j < particles.size(); j++)
420 const int vertexId = particles[j].second;
421 const Vec3d& vertexPos = (*graspedData.vertices)[vertexId];
424 if (grasperData.objType == GrasperData::Type::Rigid)
427 if (graspedData.objType == GraspedData::Type::Deformable)
431 { grasperData.bodyId, 0 },
436 else if (graspedData.objType == GraspedData::Type::Rigid)
439 { grasperData.bodyId, 0 },
440 { graspedData.bodyId, 0 },
450 if (graspedData.objType == GraspedData::Type::Deformable)
452 const Vec3d relativePos = pickGeomRot * (vertexPos - pickGeomPos);
453 const PbdParticleId graspPointPid = model->addVirtualParticle(vertexPos, 0.0);
457 { particles[j] }, { 1.0 },
458 { graspPointPid }, { 1.0 },
463 LOG(FATAL) <<
"Grasping rigid with static geometry (mesh) not supported";
470 else if (m_graspMode == GraspMode::RayPoint)
472 for (
size_t i = 0; i < pickData.size(); i++)
475 const CellTypeId pickedCellType = data.
cellType;
477 std::vector<PbdParticleId> particles;
478 if (pickedCellType == IMSTK_TETRAHEDRON)
480 particles = getElement<4>(data, graspedData);
482 else if (pickedCellType == IMSTK_TRIANGLE)
484 particles = getElement<3>(data, graspedData);
486 else if (pickedCellType == IMSTK_EDGE)
488 particles = getElement<2>(data, graspedData);
494 std::vector<double> weights = getWeights(model->getBodies(), particles, pickingPt);
496 const Vec3d relativePos = pickGeomRot * (pickingPt - pickGeomPos);
497 const PbdParticleId graspPointPid = model->addVirtualParticle(pickingPt, 0.0);
503 { graspPointPid }, { 1.0 },
510 m_isGrasping =
false;
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)
528 auto constraint = std::make_shared<PbdBaryPointToPointConstraint>();
529 constraint->initConstraint(
532 stiffnessA, stiffnessB);
540 const Vec3d& supportPt,
541 const double compliance)
543 std::shared_ptr<PbdModel> model = m_objectToGrasp->getPbdModel();
547 auto constraint = std::make_shared<PbdBodyToBodyDistanceConstraint>();
548 constraint->initConstraint(
556 auto angularConstraint = std::make_shared<PbdAngularDistanceConstraint>();
557 angularConstraint->initConstraintOffset(model->getBodies(),
558 graspedBodyId, grasperBodyId, 0.0);
566 const Vec3d& pointOnBody,
567 const double compliance)
569 std::shared_ptr<PbdModel> model = m_objectToGrasp->getPbdModel();
573 auto constraint = std::make_shared<PbdBodyToBodyDistanceConstraint>();
574 constraint->initConstraint(
587 if ((!m_isPrevGrasping && m_isGrasping) ||
m_regrasp)
589 m_objectToGrasp->updateGeometries();
595 if (!m_isGrasping && m_isPrevGrasping)
597 m_objectToGrasp->updateGeometries();
601 m_isPrevGrasping = m_isGrasping;
605 m_objectToGrasp->updateGeometries();
613 std::shared_ptr<PbdModel> model = m_objectToGrasp->getPbdModel();
619 if (m_grasperObject ==
nullptr)
621 const Vec3d& pos = m_graspGeom->getPosition();
622 const Mat3d rot = m_graspGeom->getRotation();
629 const Vec3d relativePos = std::get<1>(cPt);
630 const Vec3d vPos = pos + rot * relativePos;
631 const PbdParticleId vPid = model->addVirtualParticle(vPos, 0.0);
633 c->getParticles().back() = vPid;
637 if (m_collisionConstraints.size() > 0)
639 model->getSolver()->addConstraints(&m_collisionConstraints);
646 std::shared_ptr<PbdModel> pbdModel = m_objectToGrasp->getPbdModel();
649 m_taskGraph->addEdge(source, m_objectToGrasp->getTaskGraph()->getSource());
650 m_taskGraph->addEdge(m_objectToGrasp->getTaskGraph()->getSink(), sink);
652 if (m_grasperObject !=
nullptr)
654 m_taskGraph->addEdge(source, m_grasperObject->getTaskGraph()->getSource());
655 m_taskGraph->addEdge(m_grasperObject->getTaskGraph()->getSink(), sink);
659 m_taskGraph->addEdge(pbdModel->getIntegratePositionNode(), m_pickingNode);
660 m_taskGraph->addEdge(m_pickingNode, pbdModel->getSolveNode());
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...
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...
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.
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.
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'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.