iMSTK
Interactive Medical Simulation Toolkit
imstkPbdRigidObjectCollision.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 "imstkPbdRigidObjectCollision.h"
8 #include "imstkCDObjectFactory.h"
9 #include "imstkCollisionData.h"
10 #include "imstkCollisionDetectionAlgorithm.h"
11 #include "imstkPbdCollisionHandling.h"
12 #include "imstkPbdModel.h"
13 #include "imstkPbdObject.h"
14 #include "imstkPbdSolver.h"
15 #include "imstkRigidBodyCH.h"
16 #include "imstkRigidBodyModel2.h"
17 #include "imstkRigidObject2.h"
18 #include "imstkTaskGraph.h"
19 
20 namespace imstk
21 {
22 PbdRigidObjectCollision::PbdRigidObjectCollision(std::shared_ptr<PbdObject> obj1, std::shared_ptr<RigidObject2> obj2,
23  std::string cdType) :
24  CollisionInteraction("PbdRigidObjectCollision" + obj1->getName() + "_vs_" + obj2->getName(), obj1, obj2, cdType)
25 {
26  std::shared_ptr<PbdModel> pbdModel1 = obj1->getPbdModel();
27 
28  // Setup the handler to resolve obj1
29  auto pbdCH = std::make_shared<PbdCollisionHandling>();
30  pbdCH->setInputObjectA(obj1);
31  pbdCH->setInputObjectB(obj2);
32  pbdCH->setInputCollisionData(m_colDetect->getCollisionData());
33  setCollisionHandlingA(pbdCH);
34 
35  auto rbdCH = std::make_shared<RigidBodyCH>();
36  rbdCH->setInputRigidObjectA(obj2);
37  rbdCH->setInputCollidingObjectB(obj1);
38  rbdCH->setInputCollisionData(m_colDetect->getCollisionData());
39  rbdCH->setBaumgarteStabilization(0.1);
40  setCollisionHandlingB(rbdCH);
41 
42  // Nodes from objectA
43  auto pbdObj = std::dynamic_pointer_cast<PbdObject>(m_objA);
44  m_taskGraph->addNode(pbdObj->getTaskGraph()->getSource());
45  m_taskGraph->addNode(pbdObj->getPbdModel()->getIntegratePositionNode());
46  m_taskGraph->addNode(pbdObj->getPbdModel()->getSolveNode());
47  m_taskGraph->addNode(pbdObj->getTaskGraph()->getSink());
48 
49  // Nodes from objectB
50  auto rbdObj = std::dynamic_pointer_cast<RigidObject2>(m_objB);
51  m_taskGraph->addNode(rbdObj->getTaskGraph()->getSource());
52  m_taskGraph->addNode(rbdObj->getRigidBodyModel2()->getComputeTentativeVelocitiesNode());
53  m_taskGraph->addNode(rbdObj->getRigidBodyModel2()->getSolveNode());
54  m_taskGraph->addNode(rbdObj->getRigidBodyModel2()->getIntegrateNode());
55  m_taskGraph->addNode(rbdObj->getTaskGraph()->getSink());
56 }
57 
58 void
59 PbdRigidObjectCollision::setRestitution(const double restitution)
60 {
61  std::dynamic_pointer_cast<PbdCollisionHandling>(getCollisionHandlingA())->setRestitution(restitution);
62 }
63 
64 const double
65 PbdRigidObjectCollision::getRestitution() const
66 {
67  return std::dynamic_pointer_cast<PbdCollisionHandling>(getCollisionHandlingA())->getRestitution();
68 }
69 
70 void
71 PbdRigidObjectCollision::setFriction(const double friction)
72 {
73  std::dynamic_pointer_cast<PbdCollisionHandling>(getCollisionHandlingA())->setFriction(friction);
74 }
75 
76 const double
77 PbdRigidObjectCollision::getFriction() const
78 {
79  return std::dynamic_pointer_cast<PbdCollisionHandling>(getCollisionHandlingA())->getFriction();
80 }
81 
82 void
83 PbdRigidObjectCollision::initGraphEdges(std::shared_ptr<TaskNode> source, std::shared_ptr<TaskNode> sink)
84 {
85  // Add the collision solve step (which happens after internal constraint solve)
86  std::shared_ptr<TaskNode> pbdHandlerNode = m_collisionHandleANode;
87  std::shared_ptr<TaskNode> rbdHandlerNode = m_collisionHandleBNode;
88 
89  // Because pbd solves directly on positions it would cause a race condition
90  // if we were to solve rbd and pbd at the same time. Pbd won't write to the
91  // rigid body positions, but it will read them.
92  // We solve rigid body before pbd, this way pbd has the most up to date positions
93  // semi-implicit
94 
95  auto pbdObj = std::dynamic_pointer_cast<PbdObject>(m_objA);
96  auto rbdObj = std::dynamic_pointer_cast<RigidObject2>(m_objB);
97 
98  // Ensure a complete graph
99  m_taskGraph->addEdge(source, pbdObj->getTaskGraph()->getSource());
100  m_taskGraph->addEdge(source, rbdObj->getTaskGraph()->getSource());
101  m_taskGraph->addEdge(pbdObj->getTaskGraph()->getSink(), sink);
102  m_taskGraph->addEdge(rbdObj->getTaskGraph()->getSink(), sink);
103 
104  std::shared_ptr<CollisionHandling> pbdCH = m_colHandlingA;
105  {
106  // InternalConstraint Solve -> Update Collision Geometry ->
107  // Collision Detect -> Collision Handle -> Solve Collision ->
108  // Update Pbd Velocity -> Correct Velocity -> PbdModelSink
109  m_taskGraph->addEdge(pbdObj->getPbdModel()->getIntegratePositionNode(), m_collisionGeometryUpdateNode);
110  m_taskGraph->addEdge(m_collisionGeometryUpdateNode, m_collisionDetectionNode);
111  m_taskGraph->addEdge(m_collisionDetectionNode, pbdHandlerNode);
112  m_taskGraph->addEdge(pbdHandlerNode, pbdObj->getPbdModel()->getSolveNode());
113  }
114 
115  std::shared_ptr<CollisionHandling> rbdCH = m_colHandlingB;
116  {
117  // Compute Tentative Velocities -> Collision Detect ->
118  // Collision Handle -> Constraint Solve
119  m_taskGraph->addEdge(rbdObj->getRigidBodyModel2()->getComputeTentativeVelocitiesNode(), m_collisionGeometryUpdateNode);
120  m_taskGraph->addEdge(m_collisionGeometryUpdateNode, m_collisionDetectionNode);
121  m_taskGraph->addEdge(m_collisionDetectionNode, rbdHandlerNode);
122  m_taskGraph->addEdge(m_collisionDetectionNode, pbdHandlerNode);
123  m_taskGraph->addEdge(pbdHandlerNode, rbdObj->getRigidBodyModel2()->getSolveNode()); // Ensure we aren't handling PBD whilst solving RBD
124  m_taskGraph->addEdge(rbdHandlerNode, rbdObj->getRigidBodyModel2()->getSolveNode());
125  m_taskGraph->addEdge(rbdObj->getRigidBodyModel2()->getSolveNode(), pbdObj->getPbdModel()->getSolveNode());
126  m_taskGraph->addEdge(pbdObj->getPbdModel()->getSolveNode(), rbdObj->getRigidBodyModel2()->getIntegrateNode());
127  }
128 }
129 } // namespace imstk
Implements PBD based collision handling. Given an input PbdObject and CollisionData it creates & adds...
void setCollisionHandlingB(std::shared_ptr< CollisionHandling > colHandlingB)
Set the Collision Handling for object B.
Compound Geometry.
PbdRigidObjectCollision(std::shared_ptr< PbdObject > obj1, std::shared_ptr< RigidObject2 > obj2, std::string cdType="")
Constructor for PbdObject-PbdObject or PbdObject-CollidingObject collisions.
std::shared_ptr< CollisionDetectionAlgorithm > m_colDetect
Collision detection algorithm.
Base class for scene objects that move and/or deform under position based dynamics formulation...
Abstract class for defining collision interactions between objects.
void setCollisionHandlingA(std::shared_ptr< CollisionHandling > colHandlingA)
Set the Collision Handling for object A.
std::shared_ptr< TaskGraph > m_taskGraph
Computational Graph.
Scene objects that are governed by rigid body dynamics under the RigidBodyModel2. ...
void initGraphEdges()
Initializes the edges of the SceneObject&#39;s computational graph.