7 #include "imstkArcNeedle.h" 8 #include "imstkCamera.h" 9 #include "imstkGeometryUtilities.h" 10 #include "imstkIsometricMap.h" 11 #include "imstkKeyboardDeviceClient.h" 12 #include "imstkKeyboardSceneControl.h" 13 #include "imstkMeshIO.h" 14 #include "imstkMouseDeviceClient.h" 15 #include "imstkMouseSceneControl.h" 16 #include "imstkOrientedBox.h" 17 #include "imstkPbdModel.h" 18 #include "imstkPbdModelConfig.h" 19 #include "imstkPbdObject.h" 20 #include "imstkPbdObjectCollision.h" 21 #include "imstkPuncturable.h" 22 #include "imstkRbdConstraint.h" 23 #include "imstkRenderMaterial.h" 24 #include "imstkRigidBodyModel2.h" 25 #include "imstkRigidObject2.h" 26 #include "imstkRigidObjectController.h" 27 #include "imstkScene.h" 28 #include "imstkSceneManager.h" 29 #include "imstkSimulationManager.h" 30 #include "imstkSimulationUtils.h" 31 #include "imstkVisualModel.h" 32 #include "imstkVTKViewer.h" 33 #include "NeedleInteraction.h" 35 #undef iMSTK_USE_HAPTICS 36 #ifdef iMSTK_USE_HAPTICS 37 #include "imstkDeviceManager.h" 38 #include "imstkDeviceManagerFactory.h" 40 #include "imstkDummyClient.h" 43 using namespace imstk;
48 static std::shared_ptr<PbdObject>
50 const std::string& name,
51 const Vec3d& pos,
const Vec3d& dir,
const int numVerts,
52 const double stringLength)
54 auto stringObj = std::make_shared<PbdObject>(name);
57 std::shared_ptr<LineMesh> stringMesh =
61 auto pbdParams = std::make_shared<PbdModelConfig>();
62 pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Distance, 100.0);
63 pbdParams->enableBendConstraint(100000.0, 1);
64 pbdParams->enableBendConstraint(100000.0, 2);
65 pbdParams->m_gravity = Vec3d(0.0, -9.8, 0.0);
66 pbdParams->m_dt = 0.0005;
70 pbdParams->m_iterations = 100;
71 pbdParams->m_linearDampingCoeff = 0.01;
74 auto pbdModel = std::make_shared<PbdModel>();
75 pbdModel->configure(pbdParams);
78 auto material = std::make_shared<RenderMaterial>();
79 material->setBackFaceCulling(
false);
80 material->setColor(Color::Red);
81 material->setLineWidth(2.0);
82 material->setPointSize(6.0);
83 material->setDisplayMode(RenderMaterial::DisplayMode::Wireframe);
86 stringObj->setVisualGeometry(stringMesh);
87 stringObj->getVisualModel(0)->setRenderMaterial(material);
88 stringObj->setPhysicsGeometry(stringMesh);
89 stringObj->setCollidingGeometry(stringMesh);
90 stringObj->setDynamicalModel(pbdModel);
91 stringObj->getPbdBody()->fixedNodeIds = { 0, 1, 19, 20 };
92 stringObj->getPbdBody()->uniformMassValue = 0.002 / numVerts;
100 static std::shared_ptr<CollidingObject>
103 auto tissueObj = std::make_shared<CollidingObject>(
"tissue");
105 auto box1 = std::make_shared<OrientedBox>(Vec3d(0.0, -0.1, -0.1), Vec3d(0.1, 0.025, 0.1));
106 auto box1Model = std::make_shared<VisualModel>();
107 box1Model->setGeometry(box1);
109 box1Model->getRenderMaterial()->setColor(Color::LightSkin);
110 tissueObj->addVisualModel(box1Model);
112 tissueObj->setCollidingGeometry(box1);
114 auto box2 = std::make_shared<OrientedBox>(Vec3d(0.0, -0.105, -0.1), Vec3d(0.1001, 0.025, 0.1001));
115 auto box2Model = std::make_shared<VisualModel>();
116 box2Model->setGeometry(box2);
118 box2Model->getRenderMaterial()->setColor(Color::darken(Color::Yellow, 0.2));
119 tissueObj->addVisualModel(box2Model);
126 static std::shared_ptr<SceneObject>
127 makeToolObj(std::string name)
130 MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT
"/Surgical Instruments/Clamps/Gregory Suture Clamp/gregory_suture_clamp.obj");
132 auto toolObj = std::make_shared<SceneObject>(name);
133 toolObj->setVisualGeometry(surfMesh);
134 auto renderMaterial = std::make_shared<RenderMaterial>();
135 renderMaterial->setColor(Color::LightGray);
137 renderMaterial->setRoughness(0.5);
138 renderMaterial->setMetalness(1.0);
139 toolObj->getVisualModel(0)->setRenderMaterial(renderMaterial);
144 static std::shared_ptr<RigidObject2>
147 auto needleObj = std::make_shared<RigidObject2>();
149 auto sutureMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT
"/Surgical Instruments/Needles/c6_suture.stl");
150 auto sutureLineMesh = MeshIO::read<LineMesh>(iMSTK_DATA_ROOT
"/Surgical Instruments/Needles/c6_suture_hull.vtk");
152 const Mat4d rot = mat4dRotation(Rotd(-PI_2, Vec3d(0.0, 1.0, 0.0))) *
153 mat4dRotation(Rotd(-0.6, Vec3d(1.0, 0.0, 0.0)));
154 sutureMesh->transform(rot, Geometry::TransformType::ApplyToData);
155 sutureLineMesh->transform(rot, Geometry::TransformType::ApplyToData);
157 needleObj->setVisualGeometry(sutureMesh);
158 needleObj->setCollidingGeometry(sutureLineMesh);
159 needleObj->setPhysicsGeometry(sutureLineMesh);
160 needleObj->setPhysicsToVisualMap(std::make_shared<IsometricMap>(sutureLineMesh, sutureMesh));
161 needleObj->getVisualModel(0)->getRenderMaterial()->setColor(
Color(0.9, 0.9, 0.9));
163 needleObj->getVisualModel(0)->getRenderMaterial()->setRoughness(0.5);
164 needleObj->getVisualModel(0)->getRenderMaterial()->setMetalness(1.0);
166 std::shared_ptr<RigidBodyModel2> rbdModel = std::make_shared<RigidBodyModel2>();
167 rbdModel->getConfig()->m_gravity = Vec3d::Zero();
168 rbdModel->getConfig()->m_maxNumIterations = 5;
169 needleObj->setDynamicalModel(rbdModel);
171 needleObj->getRigidBody()->m_mass = 1.0;
172 needleObj->getRigidBody()->m_intertiaTensor = Mat3d::Identity() * 10000.0;
173 needleObj->getRigidBody()->m_initPos = Vec3d(0.0, 0.0, 0.0);
177 Mat3d arcBasis = Mat3d::Identity();
178 arcBasis.col(0) = Vec3d(0.0, 0.0, -1.0);
179 arcBasis.col(1) = Vec3d(1.0, 0.0, 0.0);
180 arcBasis.col(2) = Vec3d(0.0, 1.0, 0.0);
181 arcBasis = rot.block<3, 3>(0, 0) * arcBasis;
182 const Vec3d arcCenter = (rot * Vec4d(0.0, -0.005455, 0.008839, 1.0)).head<3>();
183 const double arcRadius = 0.010705;
186 auto needle = needleObj->addComponent<
ArcNeedle>();
187 needle->setArc(arcCenter, arcBasis, arcRadius, 0.558, 2.583);
191 controller->setControlledObject(needleObj);
192 controller->setLinearKs(1000.0);
193 controller->setAngularKs(10000000.0);
194 controller->setUseCritDamping(
true);
195 controller->setForceScaling(0.2);
196 controller->setSmoothingKernelSize(5);
197 controller->setUseForceSmoothening(
true);
217 auto scene = std::make_shared<Scene>(
"PbdStaticSuture");
220 std::shared_ptr<RigidObject2> needleObj = makeNeedleObj();
221 scene->addSceneObject(needleObj);
224 const double stringLength = 0.2;
225 const int stringVertexCount = 30;
226 std::shared_ptr<PbdObject> sutureThreadObj =
227 makePbdString(
"SutureThread", Vec3d(0.0, 0.0, 0.018), Vec3d(0.0, 0.0, 1.0),
228 stringVertexCount, stringLength);
229 scene->addSceneObject(sutureThreadObj);
232 std::shared_ptr<CollidingObject> tissueObj = makeTissueObj();
233 scene->addSceneObject(tissueObj);
236 std::shared_ptr<SceneObject> clampsObj = makeToolObj(
"Clamps");
237 scene->addSceneObject(clampsObj);
240 std::shared_ptr<SceneObject> ghostClampsObj = makeToolObj(
"GhostClamps");
241 ghostClampsObj->getVisualModel(0)->getRenderMaterial()->setColor(Color::Orange);
242 scene->addSceneObject(ghostClampsObj);
245 auto interaction = std::make_shared<PbdObjectCollision>(sutureThreadObj, tissueObj);
246 interaction->setFriction(0.0);
247 scene->addInteraction(interaction);
250 auto needleInteraction = std::make_shared<NeedleInteraction>(tissueObj, needleObj);
251 scene->addInteraction(needleInteraction);
254 scene->getActiveCamera()->setFocalPoint(0.00138345, -0.0601133, -0.0261938);
255 scene->getActiveCamera()->setPosition(0.00137719, 0.0492882, 0.201508);
256 scene->getActiveCamera()->setViewUp(-0.000780726, 0.901361, -0.433067);
261 auto viewer = std::make_shared<VTKViewer>();
262 viewer->setActiveScene(scene);
263 viewer->setDebugAxesLength(0.01, 0.01, 0.01);
266 auto sceneManager = std::make_shared<SceneManager>();
267 sceneManager->setActiveScene(scene);
268 sceneManager->pause();
271 auto driver = std::make_shared<SimulationManager>();
272 driver->addModule(viewer);
273 driver->addModule(sceneManager);
274 driver->setDesiredDt(0.001);
277 #ifdef iMSTK_USE_HAPTICS 280 std::shared_ptr<DeviceClient> deviceClient = hapticManager->makeDeviceClient();
281 driver->addModule(hapticManager);
283 controller->setTranslationOffset(Vec3d(0.05, -0.05, 0.0));
285 auto deviceClient = std::make_shared<DummyClient>();
286 deviceClient->setOrientation(Quatd(Rotd(1.57, Vec3d(0.0, 1.0, 0.0))));
287 controller->setTranslationScaling(0.13);
288 controller->setTranslationOffset(Vec3d(-0.05, -0.1, -0.005));
290 auto needleMouseMove = needleObj->addComponent<
LambdaBehaviour>(
"NeedleMouseMove");
291 needleMouseMove->setUpdate([&](
const double&)
293 const Vec2d& pos2d = viewer->getMouseDevice()->getPos();
294 deviceClient->setPosition(Vec3d(pos2d[0], pos2d[1], 0.0));
296 connect<MouseEvent>(viewer->getMouseDevice(), &MouseDeviceClient::mouseScroll,
299 const Quatd delta = Quatd(Rotd(e->m_scrollDx * 0.1, Vec3d(0.0, 0.0, 1.0)));
300 deviceClient->setOrientation(deviceClient->getOrientation() * delta);
303 controller->setDevice(deviceClient);
306 connect<Event>(sceneManager, &SceneManager::preUpdate,
309 needleObj->getRigidBodyModel2()->getConfig()->m_dt = sceneManager->getDt();
313 connect<Event>(sceneManager, &SceneManager::postUpdate,
316 auto needleLineMesh = std::dynamic_pointer_cast<
LineMesh>(needleObj->getPhysicsGeometry());
317 auto sutureLineMesh = std::dynamic_pointer_cast<
LineMesh>(sutureThreadObj->getPhysicsGeometry());
318 (*sutureLineMesh->getVertexPositions())[1] = (*needleLineMesh->getVertexPositions())[0];
319 (*sutureLineMesh->getVertexPositions())[0] = (*needleLineMesh->getVertexPositions())[1];
322 const Vec3d clampOffset = Vec3d(-0.009, 0.01, 0.001);
323 connect<Event>(sceneManager, &SceneManager::postUpdate,
326 clampsObj->getVisualGeometry()->setTransform(
327 needleObj->getVisualGeometry()->getTransform() *
328 mat4dTranslate(clampOffset) *
329 mat4dRotation(Rotd(PI, Vec3d(0.0, 1.0, 0.0))));
330 clampsObj->getVisualGeometry()->postModified();
333 connect<Event>(sceneManager, &SceneManager::postUpdate,
336 ghostClampsObj->getVisualGeometry()->setTransform(
337 mat4dTranslate(controller->getPosition()) * mat4dRotation(controller->getOrientation()) *
338 mat4dTranslate(clampOffset) *
339 mat4dRotation(Rotd(PI, Vec3d(0.0, 1.0, 0.0))));
340 ghostClampsObj->getVisualGeometry()->updatePostTransformData();
341 ghostClampsObj->getVisualGeometry()->postModified();
342 ghostClampsObj->getVisualModel(0)->getRenderMaterial()->setOpacity(std::min(1.0, controller->getDeviceForce().norm() / 5.0));
346 std::shared_ptr<Entity> mouseAndKeyControls =
347 SimulationUtils::createDefaultSceneControl(driver);
348 scene->addSceneObject(mouseAndKeyControls);
Base class for events which contain a type, priority, and data priority defaults to 0 and uses a grea...
Place this on an object to make it puncturable by a needle. This allows puncturables to know they've ...
Gouraud shading model (default)
static std::shared_ptr< DeviceManager > makeDeviceManager()
Attempts to create a new DeviceManager by whichever is default If multiple haptic managers are built ...
std::shared_ptr< LineMesh > toLineGrid(const Vec3d &start, const Vec3d &dir, const double length, const int dim)
Creates a set of connected lines.
Base class for all volume mesh types.
This class uses the provided device to control the provided rigid object via virtual coupling...
Provides the information of a mouse event, this includes button presses/releases and scrolling...
A SceneBehaviour that can update via a lambda function.
Physically based rendering.
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.