iMSTK
Interactive Medical Simulation Toolkit
imstkControllerForceText.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 "imstkControllerForceText.h"
8 #include "imstkGeometry.h"
9 #include "imstkPbdModel.h"
10 #include "imstkPbdObject.h"
11 #include "imstkPbdObjectController.h"
12 #include "imstkRbdConstraint.h"
13 #include "imstkRenderMaterial.h"
14 #include "imstkRigidObject2.h"
15 #include "imstkRigidObjectController.h"
16 #include "imstkSceneObject.h"
17 #include "imstkTextVisualModel.h"
18 #include "imstkVisualModel.h"
19 #include "imstkPbdObjectCollision.h"
20 #include "imstkPbdCollisionHandling.h"
21 #include "imstkPbdModelConfig.h"
22 #include "imstkPbdContactConstraint.h"
23 
24 namespace imstk
25 {
26 ControllerForceText::ControllerForceText(const std::string& name) : SceneBehaviour(name),
27  m_textVisualModel(std::make_shared<TextVisualModel>("ControllerForceText"))
28 {
29  m_textVisualModel->setPosition(TextVisualModel::DisplayPosition::UpperRight);
30  m_textVisualModel->setFontSize(20.0);
31 }
32 
33 void
35 {
36  // Add a visual representation for the object
37  // how to avoid adding it twice?
38  std::shared_ptr<Entity> entity = m_entity.lock();
39  CHECK(entity != nullptr) << "ControllerForceText must have entity to initialize";
40  if (!entity->containsComponent(m_textVisualModel))
41  {
42  m_textVisualModel->setName(entity->getName() + "_ControllerForceText");
43  entity->addComponent(m_textVisualModel);
44  }
45 
46  CHECK(m_pbdController != nullptr || m_rbdController != nullptr)
47  << "ObjectControllerGhost must have a controller";
48 }
49 
50 void
51 ControllerForceText::computePbdContactForceAndTorque(Vec3d& contactForce, Vec3d& contactTorque) const
52 {
53  // \todo We should be able to do this with the PbdModel itself
54  if (m_collision != nullptr)
55  {
56  auto pbdObj = std::dynamic_pointer_cast<PbdObject>(m_pbdController->getControlledObject());
57  std::shared_ptr<PbdModel> pbdModel = pbdObj->getPbdModel();
58  const double dt = pbdModel->getConfig()->m_dt;
59  const PbdParticleId bodyId = { pbdObj->getPbdBody()->bodyHandle, 0 };
60 
61  contactForce = Vec3d::Zero();
62  contactTorque = Vec3d::Zero();
63 
64  auto pbdCH = std::dynamic_pointer_cast<PbdCollisionHandling>(m_collision->getCollisionHandlingAB());
65  const std::vector<PbdConstraint*>& collisionConstraints = pbdCH->getConstraints();
66  for (const auto& constraint : collisionConstraints)
67  {
68  PbdContactConstraint* contactConstraint = dynamic_cast<PbdContactConstraint*>(constraint);
69  if (contactConstraint == nullptr)
70  {
71  continue;
72  }
73 
74  // Find the gradient of the constraint associated with the rigid body
75  Vec3d grad = Vec3d::Zero();
76  Vec3d r = Vec3d::Zero();
77  for (int i = 0; i < constraint->getParticles().size(); i++)
78  {
79  if (constraint->getParticles()[i] == bodyId)
80  {
81  grad = constraint->getGradient(i);
82  r = contactConstraint->getR(i);
83  break;
84  }
85  }
86 
87  // Multiply with gradient for direction
88  const Vec3d force = constraint->getForce(dt) * grad;
89  contactForce += force;
90  contactTorque += force.cross(r);
91  }
92  }
93 }
94 
95 void
97 {
98  // Only update when visible
99  if (m_textVisualModel->getVisibility())
100  {
101  m_t += dt;
102 
103  // Only update every 0.1 sim time
104  if (m_t > 0.1)
105  {
106  std::ostringstream strStream;
107  strStream.precision(2);
108 
109  if (m_pbdController != nullptr)
110  {
111  const Vec3d deviceForce = m_pbdController->getDeviceForce();
112  const Vec3d deviceTorque = m_pbdController->getDeviceTorque();
113  const double forceScaling = m_pbdController->getForceScaling();
114 
115  auto pbdObj = std::dynamic_pointer_cast<PbdObject>(m_pbdController->getControlledObject());
116 
117  // External/body force torque are cleared at the end of the frame so not possible to get here
118  strStream <<
119  "Device Force: " << deviceForce.norm() << "N"
120  "\nDevice Torque: " << deviceTorque.norm() << "Nm";
121  //"Body Force: " << pbdObj->getPbdBody()->externalForce.norm() << "N\n"
122  //"Body Torque: " << pbdObj->getPbdBody()->externalTorque.norm() << "Nm\n";
123 
124  if (m_collision != nullptr)
125  {
126  Vec3d contactForce = Vec3d::Zero();
127  Vec3d contactTorque = Vec3d::Zero();
128  computePbdContactForceAndTorque(contactForce, contactTorque);
129 
130  // Scale to bring in device space
131  const double contactForceMag = contactForce.norm() * forceScaling;
132  const double contactTorqueMag = contactTorque.norm() * forceScaling;
133 
134  strStream << "\nContact Force: " << contactForceMag << "N";
135  strStream << "\nContact Torque: " << contactTorqueMag << "Nm";
136  }
137  }
138  else
139  {
140  const Vec3d deviceForce = m_rbdController->getDeviceForce();
141  const Vec3d deviceTorque = m_rbdController->getDeviceTorque();
142 
143  auto rbdObj = std::dynamic_pointer_cast<RigidObject2>(m_rbdController->getControlledObject());
144  const Vec3d bodyForce = rbdObj->getRigidBody()->getForce();
145  const Vec3d bodyTorque = rbdObj->getRigidBody()->getTorque();
146 
147  strStream <<
148  "Device Force: " << deviceForce.norm() << "N"
149  "\nDevice Torque: " << deviceTorque.norm() << "Nm"
150  "\nBody Force: " << bodyForce.norm() << "N"
151  "\nBody Torque: " << bodyTorque.norm() << "Nm";
152  }
153 
154  m_textVisualModel->setText(strStream.str());
155  m_t = 0.0;
156  }
157  }
158 }
159 } // namespace imstk
Implements PBD based collision handling. Given an input PbdObject and CollisionData it creates & adds...
const std::vector< PbdConstraint * > & getConstraints() const
Return the constraints generated by this handler This list of constraints is ordered in orderCollisio...
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...
void init() override
Initialize the component, called at a later time after all component construction is complete...
std::shared_ptr< PbdModel > getPbdModel()
Compound Geometry.
void visualUpdate(const double &dt)
Update the display of the last frames update times.
Base class for scene objects that move and/or deform under position based dynamics formulation...
std::shared_ptr< RigidBody > getRigidBody() const
Returns body in the model.
const Vec3d & getR(const int i) const
Get the support point r/the difference to the contact point.
Scene objects that are governed by rigid body dynamics under the RigidBodyModel2. ...
A constraint on a rigid body that defines rotationl correction through dx applied at a local position...