7 #include "imstkCamera.h" 8 #include "imstkCapsule.h" 9 #include "imstkDeviceManager.h" 10 #include "imstkDeviceManagerFactory.h" 11 #include "imstkDirectionalLight.h" 12 #include "imstkGeometryUtilities.h" 13 #include "imstkIsometricMap.h" 14 #include "imstkMeshIO.h" 15 #include "imstkOpenVRDeviceClient.h" 16 #include "imstkPbdContactConstraint.h" 17 #include "imstkPbdModel.h" 18 #include "imstkPbdModelConfig.h" 19 #include "imstkPbdObject.h" 20 #include "imstkPbdObjectCollision.h" 21 #include "imstkPbdObjectController.h" 22 #include "imstkPbdObjectGrasping.h" 23 #include "imstkPlane.h" 24 #include "imstkPortHoleInteraction.h" 25 #include "imstkRenderMaterial.h" 26 #include "imstkScene.h" 27 #include "imstkSceneControlText.h" 28 #include "imstkSceneManager.h" 29 #include "imstkSimulationManager.h" 30 #include "imstkSimulationUtils.h" 31 #include "imstkSphere.h" 32 #include "imstkVisualModel.h" 33 #include "imstkVTKOpenVRViewer.h" 34 #include "imstkVTKViewer.h" 35 #include "VRCameraControl.h" 37 using namespace imstk;
42 std::shared_ptr<PbdObject>
43 makeLapToolObj(
const std::string& name,
44 std::shared_ptr<PbdModel> model)
46 auto lapTool = std::make_shared<PbdObject>(name);
48 const double capsuleLength = 0.5;
49 auto toolGeom = std::make_shared<Capsule>(
50 Vec3d(0.0, 0.0, capsuleLength * 0.5 - 0.005),
53 Quatd(Rotd(PI_2, Vec3d(1.0, 0.0, 0.0))));
55 const double lapToolHeadLength = 0.01;
56 auto graspCapsule = std::make_shared<Capsule>(
57 Vec3d(0.0, 0.0, lapToolHeadLength * 0.5),
60 Quatd::FromTwoVectors(Vec3d(0.0, 1.0, 0.0), Vec3d(0.0, 0.0, 1.0)));
62 auto lapToolVisualGeom = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT
"/Surgical Instruments/LapTool/laptool_all_in_one.obj");
64 lapTool->setDynamicalModel(model);
65 lapTool->setPhysicsGeometry(toolGeom);
66 lapTool->setCollidingGeometry(toolGeom);
67 lapTool->setVisualGeometry(lapToolVisualGeom);
68 lapTool->setPhysicsToVisualMap(std::make_shared<IsometricMap>(toolGeom, lapToolVisualGeom));
71 auto graspVisualModel = std::make_shared<VisualModel>();
72 graspVisualModel->setGeometry(graspCapsule);
73 graspVisualModel->getRenderMaterial()->setIsDynamicMesh(
false);
74 graspVisualModel->setIsVisible(
false);
75 lapTool->addVisualModel(graspVisualModel);
77 std::shared_ptr<RenderMaterial> material = lapTool->getVisualModel(0)->getRenderMaterial();
78 material->setIsDynamicMesh(
false);
79 material->setMetalness(1.0);
80 material->setRoughness(0.2);
83 lapTool->getPbdBody()->setRigid(
84 Vec3d(0.0, 0.0, capsuleLength * 0.5) + Vec3d(0.0, 0.1, -1.0),
87 Mat3d::Identity() * 0.08);
91 auto graspCapsuleMap = std::make_shared<IsometricMap>(toolGeom, graspCapsule);
92 auto graspCapsuleUpdate = lapTool->addComponent<
LambdaBehaviour>(
"graspCapsuleUpdate");
93 graspCapsuleUpdate->setUpdate([ = ](
const double&)
95 graspCapsuleMap->update();
104 std::shared_ptr<PbdObject>
105 makeHandObj(
const std::string& name,
106 std::shared_ptr<PbdModel> model)
108 auto handSphereObj = std::make_shared<PbdObject>(name);
110 auto sphere = std::make_shared<Sphere>(Vec3d(0.0, 0.0, 0.0), 0.02);
112 handSphereObj->setDynamicalModel(model);
113 handSphereObj->setPhysicsGeometry(sphere);
114 handSphereObj->setCollidingGeometry(sphere);
115 handSphereObj->setVisualGeometry(sphere);
117 std::shared_ptr<RenderMaterial> material = handSphereObj->getVisualModel(0)->getRenderMaterial();
118 material->setIsDynamicMesh(
false);
119 material->setMetalness(0.0);
120 material->setRoughness(1.0);
121 material->setColor(Color::Green);
124 handSphereObj->getPbdBody()->setRigid(
125 Vec3d(0.0, 0.1, -1.0),
128 Mat3d::Identity() * 0.08);
131 controller->setControlledObject(handSphereObj);
132 controller->setLinearKs(10000.0);
133 controller->setAngularKs(10.0);
134 controller->setForceScaling(0.01);
135 controller->setSmoothingKernelSize(15);
136 controller->setUseForceSmoothening(
true);
138 return handSphereObj;
144 static std::shared_ptr<PbdObject>
146 const std::string& name,
147 const Vec3d& pos,
const Vec3d& dir,
const int numVerts,
148 const double stringLength,
149 std::shared_ptr<PbdObject> needleObj)
151 auto stringObj = std::make_shared<PbdObject>(name);
154 std::shared_ptr<LineMesh> stringMesh =
158 auto material = std::make_shared<RenderMaterial>();
159 material->setBackFaceCulling(
false);
160 material->setColor(Color::Red);
161 material->setLineWidth(2.0);
162 material->setPointSize(6.0);
163 material->setDisplayMode(RenderMaterial::DisplayMode::Wireframe);
166 stringObj->setVisualGeometry(stringMesh);
167 stringObj->getVisualModel(0)->setRenderMaterial(material);
168 stringObj->setPhysicsGeometry(stringMesh);
169 stringObj->setCollidingGeometry(stringMesh);
170 std::shared_ptr<PbdModel> model = needleObj->getPbdModel();
171 stringObj->setDynamicalModel(model);
173 stringObj->getPbdBody()->uniformMassValue = 0.02;
175 const int bodyHandle = stringObj->getPbdBody()->bodyHandle;
176 model->getConfig()->enableConstraint(PbdModelConfig::ConstraintGenType::Distance, 1000.0,
178 model->getConfig()->enableBendConstraint(0.1, 1,
true, bodyHandle);
182 auto needleLineMesh = std::dynamic_pointer_cast<
LineMesh>(needleObj->getPhysicsGeometry());
188 const Vec3d endOfNeedle = (*needleLineMesh->getVertexPositions())[0];
189 auto attachmentConstraint = std::make_shared<PbdBodyToBodyDistanceConstraint>();
190 attachmentConstraint->initConstraint(model->getBodies(),
191 { needleObj->getPbdBody()->bodyHandle, 0 },
193 { stringObj->getPbdBody()->bodyHandle, 0 },
214 auto scene = std::make_shared<Scene>(
"VRLapToolControl");
216 auto model = std::make_shared<PbdModel>();
217 model->getConfig()->m_gravity = Vec3d::Zero();
218 model->getConfig()->m_dt = 0.001;
219 model->getConfig()->m_doPartitioning =
false;
221 auto bodyObject = std::make_shared<CollidingObject>(
"body");
223 auto surfMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT
"/human/full_body/body.obj");
224 auto bodyPlane = std::make_shared<Plane>(Vec3d(0.0, -0.04, -1.0), Vec3d(0.0, 1.0, 0.0));
225 bodyObject->setCollidingGeometry(bodyPlane);
226 bodyObject->setVisualGeometry(surfMesh);
227 bodyObject->getVisualModel(0)->getRenderMaterial()->setShadingModel(
229 std::shared_ptr<RenderMaterial> material =
230 bodyObject->getVisualModel(0)->getRenderMaterial();
231 material->setRoughness(0.8);
232 material->setMetalness(0.1);
233 material->setOpacity(0.5);
235 scene->addSceneObject(bodyObject);
238 std::shared_ptr<PbdObject> leftHandObj = makeHandObj(
"leftHand", model);
239 scene->addSceneObject(leftHandObj);
240 std::shared_ptr<PbdObject> rightHandObj = makeHandObj(
"leftHand", model);
241 scene->addSceneObject(rightHandObj);
244 std::shared_ptr<PbdObject> leftToolObj = makeLapToolObj(
"leftLapTool", model);
245 scene->addSceneObject(leftToolObj);
246 std::shared_ptr<PbdObject> rightToolObj = makeLapToolObj(
"rightLapTool", model);
247 scene->addSceneObject(rightToolObj);
250 auto needleObj = std::make_shared<PbdObject>();
252 auto needleMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT
"/Surgical Instruments/Needles/c6_suture.stl");
253 auto needleLineMesh = MeshIO::read<LineMesh>(iMSTK_DATA_ROOT
"/Surgical Instruments/Needles/c6_suture_hull.vtk");
255 needleMesh->translate(Vec3d(0.0, -0.0047, -0.0087), Geometry::TransformType::ApplyToData);
256 needleLineMesh->translate(Vec3d(0.0, -0.0047, -0.0087), Geometry::TransformType::ApplyToData);
257 needleObj->setVisualGeometry(needleMesh);
258 needleObj->setCollidingGeometry(needleLineMesh);
259 needleObj->setPhysicsGeometry(needleLineMesh);
260 needleObj->setPhysicsToVisualMap(std::make_shared<IsometricMap>(needleLineMesh, needleMesh));
261 needleObj->setDynamicalModel(model);
262 needleObj->getPbdBody()->setRigid(
263 Vec3d(0.02, 0.0, -1.26),
266 Mat3d::Identity() * 0.01);
267 needleObj->getVisualModel(0)->getRenderMaterial()->setColor(Color::Orange);
269 scene->addSceneObject(needleObj);
272 auto sutureThreadObj = makePbdString(
"sutureThread",
273 Vec3d(0.02, 0.0, -1.26), Vec3d(0.0, 0.0, 1.0), 50, 0.2, needleObj);
274 scene->addSceneObject(sutureThreadObj);
277 auto lapToolCollision = std::make_shared<PbdObjectCollision>(leftToolObj, rightToolObj);
278 lapToolCollision->setRigidBodyCompliance(0.00001);
279 scene->addInteraction(lapToolCollision);
282 auto threadCollision0 = std::make_shared<PbdObjectCollision>(leftToolObj, sutureThreadObj);
283 threadCollision0->setRigidBodyCompliance(0.0001);
284 threadCollision0->setUseCorrectVelocity(
false);
286 scene->addInteraction(threadCollision0);
287 auto threadCollision1 = std::make_shared<PbdObjectCollision>(rightToolObj, sutureThreadObj);
288 threadCollision1->setRigidBodyCompliance(0.0001);
289 threadCollision1->setUseCorrectVelocity(
false);
291 scene->addInteraction(threadCollision1);
294 auto leftToolGrasping = std::make_shared<PbdObjectGrasping>(leftToolObj, leftHandObj);
295 leftToolGrasping->setCompliance(0.00001);
296 scene->addInteraction(leftToolGrasping);
297 auto leftNeedleGrasping = std::make_shared<PbdObjectGrasping>(needleObj, leftToolObj);
298 leftNeedleGrasping->setCompliance(0.00001);
299 scene->addInteraction(leftNeedleGrasping);
300 auto leftThreadGrasping = std::make_shared<PbdObjectGrasping>(sutureThreadObj, leftToolObj);
301 leftThreadGrasping->setCompliance(0.00001);
302 scene->addInteraction(leftThreadGrasping);
305 auto rightToolGrasping = std::make_shared<PbdObjectGrasping>(rightToolObj, rightHandObj);
306 rightToolGrasping->setCompliance(0.00001);
307 scene->addInteraction(rightToolGrasping);
308 auto rightNeedleGrasping = std::make_shared<PbdObjectGrasping>(needleObj, rightToolObj);
309 rightNeedleGrasping->setCompliance(0.00001);
310 scene->addInteraction(rightNeedleGrasping);
311 auto rightThreadGrasping = std::make_shared<PbdObjectGrasping>(sutureThreadObj, rightToolObj);
312 rightThreadGrasping->setCompliance(0.00001);
313 scene->addInteraction(rightThreadGrasping);
316 auto threadOnThreadCollision = std::make_shared<PbdObjectCollision>(sutureThreadObj, sutureThreadObj);
317 threadOnThreadCollision->setDeformableStiffnessA(0.05);
318 threadOnThreadCollision->setDeformableStiffnessB(0.05);
319 scene->addInteraction(threadOnThreadCollision);
322 auto light = std::make_shared<DirectionalLight>();
323 light->setIntensity(1.0);
324 scene->addLight(
"light", light);
328 portHoleInteraction->setTool(rightToolObj);
329 portHoleInteraction->setPortHoleLocation(Vec3d(0.015, 0.092, -1.117));
330 auto sphere = std::make_shared<Sphere>(Vec3d(0.015, 0.092, -1.117), 0.01);
331 auto rightPortVisuals = rightToolObj->addComponent<
VisualModel>();
332 rightPortVisuals->setGeometry(sphere);
333 portHoleInteraction->setToolGeometry(rightToolObj->getCollidingGeometry());
334 portHoleInteraction->setCompliance(0.000001);
337 portHoleInteraction2->setTool(leftToolObj);
338 portHoleInteraction2->setPortHoleLocation(Vec3d(-0.065, 0.078, -1.127));
339 auto sphere2 = std::make_shared<Sphere>(Vec3d(-0.065, 0.078, -1.127), 0.01);
340 auto leftPortVisuals = leftToolObj->addComponent<
VisualModel>();
341 leftPortVisuals->setGeometry(sphere2);
342 portHoleInteraction2->setToolGeometry(leftToolObj->getCollidingGeometry());
343 portHoleInteraction2->setCompliance(0.000001);
348 auto viewer = std::make_shared<VTKOpenVRViewer>();
349 viewer->setActiveScene(scene);
350 viewer->setDebugAxesLength(0.1, 0.1, 0.1);
353 auto sceneManager = std::make_shared<SceneManager>();
354 sceneManager->setActiveScene(scene);
356 auto driver = std::make_shared<SimulationManager>();
357 driver->addModule(viewer);
358 driver->addModule(sceneManager);
359 driver->setDesiredDt(0.001);
362 std::shared_ptr<OpenVRDeviceClient> leftDeviceClient = viewer->getVRDeviceClient(OPENVR_LEFT_CONTROLLER);
363 leftController->setDevice(leftDeviceClient);
366 std::shared_ptr<OpenVRDeviceClient> rightDeviceClient = viewer->getVRDeviceClient(OPENVR_RIGHT_CONTROLLER);
367 rightController->setDevice(rightDeviceClient);
369 connect<ButtonEvent>(rightDeviceClient, &DeviceClient::buttonStateChanged,
373 if (e->m_button == 7)
375 if (e->m_buttonState == BUTTON_PRESSED)
377 if (rightToolGrasping->hasConstraints())
379 rightToolGrasping->endGrasp();
383 rightToolGrasping->beginCellGrasp(
384 std::dynamic_pointer_cast<Sphere>(rightHandObj->getCollidingGeometry()));
389 else if (e->m_button == 5)
391 viewer->setRenderingMode(Renderer::Mode::Debug);
392 if (e->m_buttonState == BUTTON_PRESSED)
395 auto graspCapsule = std::dynamic_pointer_cast<
Capsule>(rightToolObj->getVisualModel(1)->getGeometry());
396 rightNeedleGrasping->beginCellGrasp(graspCapsule);
397 rightThreadGrasping->beginCellGrasp(graspCapsule);
399 else if (e->m_buttonState == BUTTON_RELEASED)
401 rightNeedleGrasping->endGrasp();
402 rightThreadGrasping->endGrasp();
406 connect<ButtonEvent>(leftDeviceClient, &DeviceClient::buttonStateChanged,
410 if (e->m_button == 6)
412 if (e->m_buttonState == BUTTON_PRESSED)
414 if (leftToolGrasping->hasConstraints())
416 leftToolGrasping->endGrasp();
420 leftToolGrasping->beginCellGrasp(
421 std::dynamic_pointer_cast<Sphere>(leftHandObj->getCollidingGeometry()));
426 if (e->m_button == 4)
428 if (e->m_buttonState == BUTTON_PRESSED)
431 auto graspCapsule = std::dynamic_pointer_cast<
Capsule>(leftToolObj->getVisualModel(1)->getGeometry());
432 leftNeedleGrasping->beginCellGrasp(graspCapsule);
433 leftThreadGrasping->beginCellGrasp(graspCapsule);
435 else if (e->m_buttonState == BUTTON_RELEASED)
437 leftNeedleGrasping->endGrasp();
438 leftThreadGrasping->endGrasp();
444 auto controls = std::make_shared<Entity>();
446 camControl->setRotateDevice(viewer->getVRDeviceClient(OPENVR_RIGHT_CONTROLLER));
447 camControl->setTranslateDevice(viewer->getVRDeviceClient(OPENVR_LEFT_CONTROLLER));
448 camControl->setTranslateSpeedScale(1.0);
449 camControl->setRotateSpeedScale(1.0);
450 camControl->setCamera(scene->getActiveCamera());
451 scene->addSceneObject(controls);
453 connect<Event>(sceneManager, &SceneManager::preUpdate,
456 model->getConfig()->m_dt = sceneManager->getDt();
Container for pbd constraints.
Base class for events which contain a type, priority, and data priority defaults to 0 and uses a grea...
This class uses the provided device to control the provided rigid object via virtual coupling...
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.
Defines the behaviour to constrain a PbdObject LineMesh or Capsule to a fixed port hole location...
A SceneBehaviour that can update via a lambda function.
virtual void addConstraint(std::shared_ptr< PbdConstraint > constraint)
Adds a constraint to the system, thread safe.
Defines a control scheme to move the camera with joysticks. Relative to world space with Y up...
Physically based rendering.
Capsule geometry, default configuration is centered at origin with length running up and down the y a...
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.
Contains geometric, material, and render information.