7 #include "imstkAxesModel.h" 8 #include "imstkCamera.h" 9 #include "imstkCapsule.h" 10 #include "imstkControllerForceText.h" 11 #include "imstkDeviceManager.h" 12 #include "imstkDeviceManagerFactory.h" 13 #include "imstkDirectionalLight.h" 14 #include "imstkIsometricMap.h" 15 #include "imstkKeyboardDeviceClient.h" 16 #include "imstkMeshIO.h" 17 #include "imstkObjectControllerGhost.h" 18 #include "imstkPbdModel.h" 19 #include "imstkPbdModelConfig.h" 20 #include "imstkPbdObject.h" 21 #include "imstkPbdObjectCollision.h" 22 #include "imstkPbdObjectController.h" 23 #include "imstkPbdRigidObjectGrasping.h" 24 #include "imstkPlane.h" 25 #include "imstkRenderMaterial.h" 26 #include "imstkScene.h" 27 #include "imstkSceneManager.h" 28 #include "imstkSimulationManager.h" 29 #include "imstkSimulationUtils.h" 30 #include "imstkSphere.h" 31 #include "imstkTextVisualModel.h" 32 #include "imstkVTKViewer.h" 36 #ifndef USE_TWO_HAPTIC_DEVICES 37 #include "imstkDummyClient.h" 38 #include "imstkMouseDeviceClient.h" 41 using namespace imstk;
43 static std::shared_ptr<PbdObject>
44 makeCapsuleToolObj(std::shared_ptr<PbdModel> model,
bool isLeft)
46 auto toolGeometry = std::make_shared<Capsule>();
47 toolGeometry->setRadius(0.005);
48 toolGeometry->setLength(0.1);
49 toolGeometry->setPosition(Vec3d(0.0, 0.0, 0.0));
50 toolGeometry->setOrientation(Quatd::FromTwoVectors(Vec3d(0.0, 1.0, 0.0), Vec3d(0.0, 0.0, 1.0)));
52 auto toolObj = std::make_shared<PbdObject>(
"Tool");
55 toolObj->setVisualGeometry(toolGeometry);
56 toolObj->setPhysicsGeometry(toolGeometry);
57 toolObj->setCollidingGeometry(toolGeometry);
58 toolObj->setDynamicalModel(model);
59 toolObj->getPbdBody()->setRigid(
63 Mat3d::Identity() * 1.0);
65 toolObj->getVisualModel(0)->getRenderMaterial()->setOpacity(0.9);
69 controller->setControlledObject(toolObj);
70 controller->setLinearKs(500000.0);
71 controller->setAngularKs(10000.0);
72 controller->setUseCritDamping(
true);
73 controller->setForceScaling(0.002);
74 controller->setSmoothingKernelSize(15);
75 controller->setUseForceSmoothening(
true);
77 auto axesModel = toolObj->addComponent<
AxesModel>();
78 axesModel->setScale(Vec3d(0.05, 0.05, 0.05));
80 auto axesUpdate = toolObj->addComponent<
LambdaBehaviour>(
"AxesModelUpdate");
81 axesUpdate->setUpdate([ = ](
const double& dt)
83 axesModel->setPosition((*toolObj->getPbdBody()->vertices)[0]);
84 axesModel->setOrientation((*toolObj->getPbdBody()->orientations)[0]);
89 controllerGhost->setController(controller);
95 controllerForceTxt->getText()->setPosition(TextVisualModel::DisplayPosition::UpperLeft);
97 controllerForceTxt->setController(controller);
113 auto scene = std::make_shared<Scene>(
"PbdRigidBodyGrasping");
114 scene->getActiveCamera()->setPosition(0.0, 0.5, 0.5);
115 scene->getActiveCamera()->setFocalPoint(0.0, 0.0, 0.0);
116 scene->getActiveCamera()->setViewUp(0.0, 1.0, 0.0);
118 auto pbdModel = std::make_shared<PbdModel>();
119 std::shared_ptr<PbdModelConfig> pbdParams = pbdModel->getConfig();
120 pbdParams->m_gravity = Vec3d(0.0, -9.8, 0.0);
122 pbdParams->m_dt = 0.002;
123 pbdParams->m_iterations = 8;
124 pbdParams->m_linearDampingCoeff = 0.01;
125 pbdParams->m_angularDampingCoeff = 0.01;
128 auto planeObj = std::make_shared<CollidingObject>(
"PlaneObj");
129 auto plane = std::make_shared<Plane>(Vec3d(0.0, 0.0, 0.0), Vec3d(0.0, 1.0, 0.0));
130 plane->setWidth(1.0);
131 planeObj->setCollidingGeometry(plane);
132 planeObj->setVisualGeometry(plane);
133 scene->addSceneObject(planeObj);
136 auto needleObj = std::make_shared<PbdObject>();
138 auto needleMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT
"/Surgical Instruments/Needles/c6_suture.stl");
139 auto needleLineMesh = MeshIO::read<LineMesh>(iMSTK_DATA_ROOT
"/Surgical Instruments/Needles/c6_suture_hull.vtk");
141 needleMesh->translate(Vec3d(0.0, -0.0047, -0.0087), Geometry::TransformType::ApplyToData);
142 needleLineMesh->translate(Vec3d(0.0, -0.0047, -0.0087), Geometry::TransformType::ApplyToData);
143 needleMesh->scale(2.0, Geometry::TransformType::ApplyToData);
144 needleLineMesh->scale(2.0, Geometry::TransformType::ApplyToData);
145 needleObj->setVisualGeometry(needleMesh);
146 needleObj->setCollidingGeometry(needleLineMesh);
147 needleObj->setPhysicsGeometry(needleLineMesh);
148 needleObj->setPhysicsToVisualMap(std::make_shared<IsometricMap>(needleLineMesh, needleMesh));
149 needleObj->setDynamicalModel(pbdModel);
150 needleObj->getPbdBody()->setRigid(
151 Vec3d(-0.1, 0.15, 0.0),
154 Mat3d::Identity() * 0.01);
155 needleObj->getVisualModel(0)->getRenderMaterial()->setColor(Color::Orange);
157 scene->addSceneObject(needleObj);
160 auto sphereObj = std::make_shared<PbdObject>();
162 auto sphereGeom = std::make_shared<Sphere>(Vec3d::Zero(), 0.01);
163 sphereObj->setVisualGeometry(sphereGeom);
164 sphereObj->setCollidingGeometry(sphereGeom);
165 sphereObj->setPhysicsGeometry(sphereGeom);
166 sphereObj->setDynamicalModel(pbdModel);
167 sphereObj->getPbdBody()->setRigid(
168 Vec3d(0.1, 0.15, 0.0),
171 Mat3d::Identity() * 0.01);
172 sphereObj->getVisualModel(0)->getRenderMaterial()->setColor(Color::Blood);
174 scene->addSceneObject(sphereObj);
177 std::shared_ptr<PbdObject> leftToolObj = makeCapsuleToolObj(pbdModel,
true);
178 scene->addSceneObject(leftToolObj);
179 std::shared_ptr<PbdObject> rightToolObj = makeCapsuleToolObj(pbdModel,
false);
180 scene->addSceneObject(rightToolObj);
183 auto planeCollision0 = std::make_shared<PbdObjectCollision>(needleObj, planeObj);
184 planeCollision0->setRigidBodyCompliance(0.00001);
185 scene->addInteraction(planeCollision0);
186 auto planeCollision1 = std::make_shared<PbdObjectCollision>(sphereObj, planeObj);
187 planeCollision1->setRigidBodyCompliance(0.00001);
188 scene->addInteraction(planeCollision1);
191 auto sphereNeedleCollision = std::make_shared<PbdObjectCollision>(sphereObj, needleObj,
"PointSetToSphereCD");
192 sphereNeedleCollision->setRigidBodyCompliance(0.000001);
193 scene->addInteraction(sphereNeedleCollision);
196 auto leftGrasping0 = std::make_shared<PbdObjectGrasping>(needleObj, leftToolObj);
197 leftGrasping0->setCompliance(0.00001);
198 scene->addInteraction(leftGrasping0);
199 auto leftGrasping1 = std::make_shared<PbdObjectGrasping>(sphereObj, leftToolObj);
200 leftGrasping1->setCompliance(0.00001);
201 scene->addInteraction(leftGrasping1);
203 auto rightGrasping0 = std::make_shared<PbdObjectGrasping>(needleObj, rightToolObj);
204 rightGrasping0->setCompliance(0.00001);
205 scene->addInteraction(rightGrasping0);
206 auto rightGrasping1 = std::make_shared<PbdObjectGrasping>(sphereObj, rightToolObj);
207 rightGrasping1->setCompliance(0.00001);
208 scene->addInteraction(rightGrasping1);
211 auto light = std::make_shared<DirectionalLight>();
212 light->setFocalPoint(Vec3d(5.0, -8.0, -5.0));
213 light->setIntensity(1.0);
214 scene->addLight(
"Light", light);
219 auto viewer = std::make_shared<VTKViewer>();
220 viewer->setActiveScene(scene);
221 viewer->setDebugAxesLength(0.05, 0.05, 0.05);
224 auto sceneManager = std::make_shared<SceneManager>();
225 sceneManager->setActiveScene(scene);
226 sceneManager->pause();
231 auto driver = std::make_shared<SimulationManager>();
232 driver->addModule(viewer);
233 driver->addModule(sceneManager);
234 driver->addModule(hapticManager);
235 driver->setDesiredDt(0.002);
239 if (hapticManager->getTypeName() ==
"HaplyDeviceManager")
241 leftController->setTranslationOffset(Vec3d(0.1, 0.0, -0.1));
243 std::shared_ptr<DeviceClient> leftDeviceClient = hapticManager->makeDeviceClient();
244 leftController->setDevice(leftDeviceClient);
246 connect<ButtonEvent>(leftDeviceClient, &DeviceClient::buttonStateChanged,
249 if (e->m_button == 1)
251 if (e->m_buttonState == BUTTON_PRESSED)
254 auto capsule = std::dynamic_pointer_cast<
Capsule>(leftToolObj->getCollidingGeometry());
255 auto dilatedCapsule = std::make_shared<Capsule>(*capsule);
256 dilatedCapsule->setRadius(capsule->getRadius() * 1.1);
257 leftGrasping0->beginCellGrasp(dilatedCapsule);
258 leftGrasping1->beginCellGrasp(dilatedCapsule);
260 else if (e->m_buttonState == BUTTON_RELEASED)
262 leftGrasping0->endGrasp();
263 leftGrasping1->endGrasp();
267 #ifdef USE_TWO_HAPTIC_DEVICES 268 std::shared_ptr<DeviceClient> rightDeviceClient = hapticManager->makeDeviceClient(
"Device2");
270 rightController->setDevice(rightDeviceClient);
272 connect<ButtonEvent>(rightDeviceClient, &DeviceClient::buttonStateChanged,
275 if (e->m_button == 1)
277 if (e->m_buttonState == BUTTON_PRESSED)
280 auto capsule = std::dynamic_pointer_cast<
Capsule>(rightToolObj->getCollidingGeometry());
281 auto dilatedCapsule = std::make_shared<Capsule>(*capsule);
282 dilatedCapsule->setRadius(capsule->getRadius() * 1.1);
283 rightGrasping0->beginCellGrasp(dilatedCapsule);
284 rightGrasping1->beginCellGrasp(dilatedCapsule);
286 else if (e->m_buttonState == BUTTON_RELEASED)
288 rightGrasping0->endGrasp();
289 rightGrasping1->endGrasp();
294 auto rightDeviceClient = std::make_shared<DummyClient>();
296 rightController->setDevice(rightDeviceClient);
298 connect<Event>(sceneManager, &SceneManager::postUpdate,
301 const Vec2d mousePos = viewer->getMouseDevice()->getPos();
302 const Vec3d worldPos = Vec3d(mousePos[0] - 0.5, mousePos[1] - 0.5, 0.0) * 0.1;
304 rightDeviceClient->setPosition(worldPos);
306 connect<MouseEvent>(viewer->getMouseDevice(), &MouseDeviceClient::mouseButtonPress,
310 auto capsule = std::dynamic_pointer_cast<
Capsule>(rightToolObj->getCollidingGeometry());
311 auto dilatedCapsule = std::make_shared<Capsule>(*capsule);
312 dilatedCapsule->setRadius(capsule->getRadius() * 1.1);
313 rightGrasping0->beginCellGrasp(dilatedCapsule);
314 rightGrasping1->beginCellGrasp(dilatedCapsule);
316 connect<MouseEvent>(viewer->getMouseDevice(), &MouseDeviceClient::mouseButtonRelease,
319 rightGrasping0->endGrasp();
320 rightGrasping1->endGrasp();
325 std::shared_ptr<Entity> mouseAndKeyControls =
326 SimulationUtils::createDefaultSceneControl(driver);
327 auto instructText = mouseAndKeyControls->getComponent<
TextVisualModel>();
328 instructText->
setText(instructText->getText() +
329 "\nMouse Click/Press Haptic Device Button to grasp");
330 scene->addSceneObject(mouseAndKeyControls);
332 connect<Event>(sceneManager, &SceneManager::preUpdate, [&](
Event*)
335 pbdModel->getConfig()->m_dt = sceneManager->getDt();
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...
static std::shared_ptr< DeviceManager > makeDeviceManager()
Attempts to create a new DeviceManager by whichever is default If multiple haptic managers are built ...
void setText(const std::string &text)
Text to be plotted.
Defines an axes that should be rendered.
Provides the information of a mouse event, this includes button presses/releases and scrolling...
A SceneBehaviour that can update via a lambda function.
Renders text to the screen.
A behaviour that renders a second copy of the controlled object at a lower opacity in the physical po...
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.
Displays virtual coupling force text in the top right.