iMSTK
Interactive Medical Simulation Toolkit
VirtualCouplingExample.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 "imstkCamera.h"
8 #include "imstkDeviceManager.h"
9 #include "imstkDeviceManagerFactory.h"
10 #include "imstkDirectionalLight.h"
11 #include "imstkKeyboardDeviceClient.h"
12 #include "imstkMeshIO.h"
13 #include "imstkMouseDeviceClient.h"
14 #include "imstkMouseSceneControl.h"
15 #include "imstkObjectControllerGhost.h"
16 #include "imstkOrientedBox.h"
17 #include "imstkPbdModel.h"
18 #include "imstkPbdModelConfig.h"
19 #include "imstkPbdObject.h"
20 #include "imstkPbdObjectCollision.h"
21 #include "imstkPbdObjectController.h"
22 #include "imstkPlane.h"
23 #include "imstkRenderMaterial.h"
24 #include "imstkScene.h"
25 #include "imstkSceneManager.h"
26 #include "imstkSimulationManager.h"
27 #include "imstkVisualModel.h"
28 
29 #ifdef iMSTK_USE_RENDERING_VTK
30 #include "imstkKeyboardSceneControl.h"
31 #include "imstkSimulationUtils.h"
32 #include "imstkVTKViewer.h"
33 #include "imstkVTKRenderer.h"
34 #endif
35 
36 using namespace imstk;
37 
43 int
44 main()
45 {
46  // Setup logger (write to file and stdout)
48 
49  // Setup default haptics manager
50  std::shared_ptr<DeviceManager> hapticManager = DeviceManagerFactory::makeDeviceManager();
51  std::shared_ptr<DeviceClient> deviceClient = hapticManager->makeDeviceClient();
52 
53  // Scene
54  auto scene = std::make_shared<Scene>("VirtualCoupling");
55  scene->getActiveCamera()->setPosition(Vec3d(0.0, 0.2, 0.35));
56  scene->getActiveCamera()->setFocalPoint(Vec3d(0.0, 0.0, 0.0));
57  scene->getActiveCamera()->setViewUp(Vec3d(0.0, 1.0, 0.0));
58 
59  std::shared_ptr<CollidingObject> obstacleObjs[] =
60  {
61  std::make_shared<CollidingObject>("Plane"),
62  std::make_shared<CollidingObject>("Cube")
63  };
64 
65  // Create a plane and cube for collision with scissors
66  auto plane = std::make_shared<Plane>();
67  plane->setWidth(0.4);
68  obstacleObjs[0]->setVisualGeometry(plane);
69  obstacleObjs[0]->setCollidingGeometry(plane);
70 
71  // 0.1m size cube, slight rotation
72  auto cube = std::make_shared<OrientedBox>(Vec3d(0.0, 0.0, 0.0),
73  Vec3d(0.05, 0.05, 0.05), Quatd(Rotd(1.0, Vec3d(0.0, 1.0, 0.0))));
74  obstacleObjs[1]->setVisualGeometry(cube);
75  obstacleObjs[1]->setCollidingGeometry(cube);
76 
77  for (int i = 0; i < 2; i++)
78  {
79  obstacleObjs[i]->getVisualModel(0)->getRenderMaterial()->setIsDynamicMesh(false);
80  scene->addSceneObject(obstacleObjs[i]);
81  }
82 
83  // The visual geometry is the scissor mesh read in from file
84  auto rbdObj = std::make_shared<PbdObject>();
85  {
86  auto model = std::make_shared<PbdModel>();
87  model->getConfig()->m_dt = 0.001;
88  model->getConfig()->m_gravity = Vec3d::Zero();
89  rbdObj->setDynamicalModel(model);
90  rbdObj->getPbdBody()->setRigid(
91  Vec3d(0.0, 0.05, 0.0), // Position
92  7.0, // Mass
93  Quatd::Identity(), // Orientation
94  Mat3d::Identity() * 100000000.0); // Inertia
95 
96  auto surfMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT "/Surgical Instruments/Scissors/Metzenbaum Scissors/Metz_Scissors.stl");
97  rbdObj->setCollidingGeometry(surfMesh);
98  rbdObj->setVisualGeometry(surfMesh);
99  rbdObj->setPhysicsGeometry(surfMesh);
100 
101  std::shared_ptr<RenderMaterial> mat = rbdObj->getVisualModel(0)->getRenderMaterial();
102  mat->setShadingModel(RenderMaterial::ShadingModel::PBR);
103  mat->setRoughness(0.5);
104  mat->setMetalness(1.0);
105  mat->setIsDynamicMesh(false);
106 
107  // Add a component for controlling via another device
108  auto controller = rbdObj->addComponent<PbdObjectController>();
109  controller->setControlledObject(rbdObj);
110  controller->setDevice(deviceClient);
111  controller->setTranslationOffset(Vec3d(0.0, 0.05, 0.0));
112  controller->setLinearKs(50000.0);
113  controller->setAngularKs(1000000000000.0);
114  controller->setTranslationScaling(1.0);
115  controller->setForceScaling(0.005);
116  controller->setSmoothingKernelSize(10);
117  controller->setUseForceSmoothening(true);
118  controller->setUseCritDamping(true);
119 
120  // Add extra component to tool for the ghost
121  auto controllerGhost = rbdObj->addComponent<ObjectControllerGhost>();
122  controllerGhost->setController(controller);
123  }
124  scene->addSceneObject(rbdObj);
125 
126  // Add interaction between the rigid object sphere and static plane
127  scene->addInteraction(
128  std::make_shared<PbdObjectCollision>(rbdObj, obstacleObjs[0]));
129  scene->addInteraction(
130  std::make_shared<PbdObjectCollision>(rbdObj, obstacleObjs[1]));
131 
132  // Light
133  auto light = std::make_shared<DirectionalLight>();
134  light->setFocalPoint(Vec3d(5.0, -8.0, -5.0));
135  light->setIntensity(1.0);
136  scene->addLight("light0", light);
137 
138  // Run the simulation
139  {
140  // Setup a scene manager to advance the scene
141  auto sceneManager = std::make_shared<SceneManager>();
142  sceneManager->setActiveScene(scene);
143  sceneManager->setPaused(true); // Start paused
144 
145  auto driver = std::make_shared<SimulationManager>();
146  driver->addModule(hapticManager);
147 #ifdef iMSTK_USE_RENDERING_VTK
148  // Setup a viewer to render
149  auto viewer = std::make_shared<VTKViewer>();
150  viewer->setActiveScene(scene);
151  driver->addModule(viewer);
152 #endif
153  driver->addModule(sceneManager);
154  driver->setDesiredDt(0.001);
155 
156  connect<Event>(sceneManager, &SceneManager::preUpdate, [&](Event*)
157  {
158  // Run the rbd model in real time
159  rbdObj->getPbdModel()->getConfig()->m_dt = driver->getDt();
160  });
161 
162  // Add mouse and keyboard controls to the viewer
163 #ifdef iMSTK_USE_RENDERING_VTK
164  // Add default mouse and keyboard controls to the viewer
165  std::shared_ptr<Entity> mouseAndKeyControls =
166  SimulationUtils::createDefaultSceneControl(driver);
167  scene->addSceneObject(mouseAndKeyControls);
168 #endif
169 
170  driver->start();
171  }
172 
173  return 0;
174 }
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...
Compound Geometry.
static std::shared_ptr< DeviceManager > makeDeviceManager()
Attempts to create a new DeviceManager by whichever is default If multiple haptic managers are built ...
A behaviour that renders a second copy of the controlled object at a lower opacity in the physical po...
Physically based rendering.
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.