7 #include "imstkCamera.h" 8 #include "imstkControllerForceText.h" 9 #include "imstkDebugGeometryModel.h" 10 #include "imstkDirectionalLight.h" 11 #include "imstkGeometryUtilities.h" 12 #include "imstkIsometricMap.h" 13 #include "imstkKeyboardDeviceClient.h" 14 #include "imstkKeyboardSceneControl.h" 15 #include "imstkMeshIO.h" 16 #include "imstkMouseDeviceClient.h" 17 #include "imstkMouseSceneControl.h" 18 #include "imstkObjectControllerGhost.h" 19 #include "imstkPbdCollisionHandling.h" 20 #include "imstkPbdContactConstraint.h" 21 #include "imstkPbdModel.h" 22 #include "imstkPbdModelConfig.h" 23 #include "imstkPbdObject.h" 24 #include "imstkPbdObjectController.h" 25 #include "imstkPointwiseMap.h" 26 #include "imstkPuncturable.h" 27 #include "imstkRenderMaterial.h" 28 #include "imstkScene.h" 29 #include "imstkSceneManager.h" 30 #include "imstkSimulationManager.h" 31 #include "imstkSimulationUtils.h" 32 #include "imstkStraightNeedle.h" 33 #include "imstkTextVisualModel.h" 34 #include "imstkVTKViewer.h" 35 #include "NeedleEmbedder.h" 36 #include "NeedleInteraction.h" 38 #ifdef iMSTK_USE_HAPTICS 39 #include "imstkDeviceManager.h" 40 #include "imstkDeviceManagerFactory.h" 42 #include "imstkDummyClient.h" 45 using namespace imstk;
51 static std::vector<int>
52 computeFixedPtsViaMap(std::shared_ptr<PointSet> parent,
53 std::shared_ptr<PointSet> child,
54 const double tolerance = 0.00001)
56 std::vector<int> fixedPts;
58 auto map = std::make_shared<PointwiseMap>();
59 map->setParentGeometry(parent);
60 map->setChildGeometry(child);
61 map->setTolerance(tolerance);
63 fixedPts.reserve(child->getNumVertices());
64 for (
int i = 0; i < child->getNumVertices(); i++)
66 fixedPts.push_back(map->getParentVertexId(i));
76 static std::shared_ptr<PbdObject>
77 makeTissueObj(
const std::string& name,
78 std::shared_ptr<PbdModel> model,
79 std::shared_ptr<TetrahedralMesh> tissueMesh)
82 std::shared_ptr<SurfaceMesh> surfMesh = tissueMesh->extractSurfaceMesh();
85 auto material = std::make_shared<RenderMaterial>();
86 material->setDisplayMode(RenderMaterial::DisplayMode::WireframeSurface);
87 material->setBackFaceCulling(
false);
88 material->setOpacity(0.5);
91 auto tissueObj = std::make_shared<PbdObject>(name);
92 tissueObj->setVisualGeometry(surfMesh);
93 tissueObj->getVisualModel(0)->setRenderMaterial(material);
94 tissueObj->setPhysicsGeometry(tissueMesh);
95 tissueObj->setCollidingGeometry(surfMesh);
96 tissueObj->setPhysicsToCollidingMap(std::make_shared<PointwiseMap>(tissueMesh, surfMesh));
97 tissueObj->setDynamicalModel(model);
98 tissueObj->getPbdBody()->uniformMassValue = 0.04;
102 auto functor = std::make_shared<PbdFemTetConstraintFunctor>();
103 functor->setGeometry(tissueMesh);
104 functor->setBodyIndex(tissueObj->getPbdBody()->bodyHandle);
105 const double youngsModulus = 100000.0;
106 const double poissonRatio = 0.48;
107 auto constraintConfig = std::make_shared<PbdFemConstraintConfig>(
108 youngsModulus / 2.0 / (1.0 + poissonRatio),
109 youngsModulus * poissonRatio / ((1.0 + poissonRatio) * (1.0 - 2.0 * poissonRatio)),
112 functor->setFemConfig(constraintConfig);
113 functor->setMaterialType(PbdFemConstraint::MaterialType::StVK);
114 model->getConfig()->addPbdConstraintFunctor(functor);
121 static std::shared_ptr<PbdObject>
122 makeNeedleObj(
const std::string& name,
123 std::shared_ptr<PbdModel> model)
125 auto toolObj = std::make_shared<PbdObject>(name);
127 auto toolGeometry = std::make_shared<LineMesh>();
128 auto verticesPtr = std::make_shared<VecDataArray<double, 3>>(2);
129 (*verticesPtr)[0] = Vec3d(0.0, 0.0, 0.0);
130 (*verticesPtr)[1] = Vec3d(0.0, 0.0, 0.25);
131 auto indicesPtr = std::make_shared<VecDataArray<int, 2>>(1);
132 (*indicesPtr)[0] = Vec2i(0, 1);
133 toolGeometry->initialize(verticesPtr, indicesPtr);
135 auto trocarMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT
"/Surgical Instruments/LapTool/trocar.obj");
137 toolObj->setVisualGeometry(trocarMesh);
138 toolObj->setCollidingGeometry(toolGeometry);
139 toolObj->setPhysicsGeometry(toolGeometry);
140 toolObj->setPhysicsToVisualMap(std::make_shared<IsometricMap>(toolGeometry, trocarMesh));
141 toolObj->getVisualModel(0)->getRenderMaterial()->setColor(
Color(0.9, 0.9, 0.9));
143 toolObj->getVisualModel(0)->getRenderMaterial()->setRoughness(0.5);
144 toolObj->getVisualModel(0)->getRenderMaterial()->setMetalness(1.0);
145 toolObj->getVisualModel(0)->getRenderMaterial()->setIsDynamicMesh(
false);
147 toolObj->setDynamicalModel(model);
148 toolObj->getPbdBody()->setRigid(
149 Vec3d(0.0, 1.0, 0.0),
152 Mat3d::Identity() * 10000.0);
156 needle->setNeedleGeometry(toolGeometry);
160 controller->setControlledObject(toolObj);
161 controller->setLinearKs(20000.0);
162 controller->setAngularKs(8000000.0);
163 controller->setUseCritDamping(
true);
164 controller->setForceScaling(0.05);
165 controller->setSmoothingKernelSize(15);
166 controller->setUseForceSmoothening(
true);
171 controllerGhost->setController(controller);
177 updateDebugGeom(std::shared_ptr<NeedleInteraction> interaction,
178 std::shared_ptr<DebugGeometryModel> debugGeomObj)
180 auto needleEmbedder = std::dynamic_pointer_cast<
NeedleEmbedder>(interaction->getEmbedder());
182 const std::vector<Vec3i>& debugEmbeddingTris = needleEmbedder->m_debugEmbeddedTriangles;
183 debugGeomObj->clear();
184 for (
size_t i = 0; i < debugEmbeddingPts.size(); i++)
186 debugGeomObj->addPoint(debugEmbeddingPts[i]);
188 std::shared_ptr<PbdObject> tissueObj = interaction->getEmbedder()->getTissueObject();
189 auto verticesPtr = std::dynamic_pointer_cast<
TetrahedralMesh>(tissueObj->getPhysicsGeometry())->getVertexPositions();
191 for (
size_t i = 0; i < debugEmbeddingTris.size(); i++)
193 debugGeomObj->addTriangle(
194 vertices[debugEmbeddingTris[i][0]],
195 vertices[debugEmbeddingTris[i][1]],
196 vertices[debugEmbeddingTris[i][2]]);
212 auto scene = std::make_shared<Scene>(
"PbdTissueVolumeNeedleContact");
213 scene->getActiveCamera()->setPosition(0.0, 0.412873, 0.102441);
214 scene->getActiveCamera()->setFocalPoint(0.0, -0.0, -0.0);
215 scene->getActiveCamera()->setViewUp(0.0, 0.242952, -0.969977);
216 scene->getConfig()->debugCamBoundingBox =
false;
217 *scene->getCamera(
"debug") = *scene->getActiveCamera();
220 auto pbdModel = std::make_shared<PbdModel>();
221 pbdModel->getConfig()->m_doPartitioning =
false;
222 pbdModel->getConfig()->m_dt = 0.001;
223 pbdModel->getConfig()->m_iterations = 1;
224 pbdModel->getConfig()->m_gravity = Vec3d(0.0, 0.0, 0.0);
227 const Vec3i dim = Vec3i(6, 3, 6);
229 Vec3d(0.0, 0.0, 0.0),
230 Vec3d(0.2, 0.01, 0.2),
232 std::shared_ptr<PbdObject> tissueObj = makeTissueObj(
"PbdTissue1", pbdModel, tetGridMesh);
234 for (
int z = 0; z < dim[2]; z++)
236 for (
int y = 0; y < dim[1]; y++)
238 for (
int x = 0; x < dim[0]; x++)
240 if (x == 0 || x == dim[0] - 1 )
242 tissueObj->getPbdBody()->fixedNodeIds.push_back(x + dim[0] * (y + dim[1] * z));
247 scene->addSceneObject(tissueObj);
249 auto tetMesh = MeshIO::read<TetrahedralMesh>(iMSTK_DATA_ROOT
"/Organs/Kidney/kidney_vol_low_rez.vtk");
250 tetMesh->translate(Vec3d(0.0, -0.07, -0.05), Geometry::TransformType::ApplyToData);
251 std::shared_ptr<PbdObject> tissueObj2 = makeTissueObj(
"PbdTissue2", pbdModel, tetMesh);
252 auto fixedPtMesh = MeshIO::read<PointSet>(iMSTK_DATA_ROOT
"/Organs/Kidney/kidney_fixedpts_low_rez.obj");
253 fixedPtMesh->translate(Vec3d(0.0, -0.07, -0.05), Geometry::TransformType::ApplyToData);
254 tissueObj2->getPbdBody()->fixedNodeIds = computeFixedPtsViaMap(tetMesh, fixedPtMesh, 0.001);
255 tissueObj2->getVisualModel(0)->getRenderMaterial()->setColor(Color::Blood);
256 scene->addSceneObject(tissueObj2);
259 std::shared_ptr<PbdObject> toolObj = makeNeedleObj(
"PbdNeedle", pbdModel);
261 debugGeom->setLineWidth(0.1);
262 scene->addSceneObject(toolObj);
265 auto interaction = std::make_shared<NeedleInteraction>(tissueObj, toolObj);
266 interaction->setPunctureForceThreshold(3.0);
267 interaction->setNeedleCompliance(0.000001);
268 interaction->setFriction(0.1);
269 scene->addInteraction(interaction);
271 auto interaction2 = std::make_shared<NeedleInteraction>(tissueObj2, toolObj);
272 interaction2->setPunctureForceThreshold(3.0);
273 interaction2->setNeedleCompliance(0.000001);
274 interaction2->setFriction(0.1);
275 scene->addInteraction(interaction2);
278 auto light = std::make_shared<DirectionalLight>();
279 light->setFocalPoint(Vec3d(5.0, -8.0, -5.0));
280 light->setIntensity(1.0);
281 scene->addLight(
"Light", light);
286 auto viewer = std::make_shared<VTKViewer>();
287 viewer->setActiveScene(scene);
288 viewer->setVtkLoggerMode(VTKViewer::VTKLoggerMode::MUTE);
289 viewer->setDebugAxesLength(0.1, 0.1, 0.1);
292 auto sceneManager = std::make_shared<SceneManager>();
293 sceneManager->setActiveScene(scene);
294 sceneManager->pause();
296 auto driver = std::make_shared<SimulationManager>();
297 driver->addModule(viewer);
298 driver->addModule(sceneManager);
299 driver->setDesiredDt(0.001);
302 #ifdef iMSTK_USE_HAPTICS 305 std::shared_ptr<DeviceClient> deviceClient = hapticManager->makeDeviceClient();
306 driver->addModule(hapticManager);
308 if (hapticManager->getTypeName() ==
"HaplyDeviceManager")
310 controller->setTranslationOffset(Vec3d(0.125, -0.07, 0.0));
313 auto deviceClient = std::make_shared<DummyClient>();
315 connect<Event>(sceneManager, &SceneManager::postUpdate,
318 const Vec2d mousePos = viewer->getMouseDevice()->getPos();
319 const Vec3d desiredPos = Vec3d(mousePos[0] - 0.5, mousePos[1] - 0.5, 0.0) * 0.1;
320 const Quatd desiredOrientation = Quatd(Rotd(0.0, Vec3d(1.0, 0.0, 0.0)));
322 deviceClient->setPosition(desiredPos);
323 deviceClient->setOrientation(desiredOrientation);
326 controller->setDevice(deviceClient);
329 connect<Event>(viewer, &VTKViewer::preUpdate,
333 updateDebugGeom(interaction, debugGeom);
335 connect<Event>(sceneManager, &SceneManager::preUpdate,
339 pbdModel->getConfig()->m_dt = sceneManager->getDt();
343 std::shared_ptr<Entity> mouseAndKeyControls =
344 SimulationUtils::createDefaultSceneControl(driver);
348 controllerForceTxt->setCollision(interaction);
349 scene->addSceneObject(mouseAndKeyControls);
Class for quickly rendering and showing various primivites such as line segments, triangles...
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...
Place this on an object to make it puncturable by a needle. This allows puncturables to know they've ...
void setUseForceFade(bool useForceFade)
Get/Set whether to use force fade or not. Force fade sets opacity of ghost geometry according to forc...
std::shared_ptr< TetrahedralMesh > toTetGrid(const Vec3d ¢er, const Vec3d &size, const Vec3i &divisions, const Quatd orientation=Quatd::Identity())
Produces a tetrahedral grid given the OrientedBox with the given divisions.
Definition of straight, single segment needle.
static std::shared_ptr< DeviceManager > makeDeviceManager()
Attempts to create a new DeviceManager by whichever is default If multiple haptic managers are built ...
Implements PBD embedded tissue handling for when the needle is embedded in the tissue.
Represents a set of tetrahedrons & vertices via an array of Vec3d double vertices & Vec4i integer ind...
A behaviour that renders a second copy of the controlled object at a lower opacity in the physical po...
std::vector< Vec3d > m_debugEmbeddingPoints
Used for debug visualization.
Physically based rendering.
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.
void setController(std::shared_ptr< PbdObjectController > controller)
Get/Set the controller to display the device force of.
Displays virtual coupling force text in the top right.