Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Enable reset simulations #23

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions SlicerSofa/SlicerSofa.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ def __init__(self) -> None:
self._rootNode = None
self._simulationRunning = False
self._currentStep = 0
self._totaSteps = 0
self._totalSteps = 0
self._dt = 0
self.initialgrid = []
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now I would leave this to the derived classes. Two reasons:

  • Not all simulations necessarily will deal with unstructured grids (some may use surface meshes as polydata)
  • Some simulations may imply the use and update of more than one model.

self.startup = True

def setupScene(self, parameterNode):
"""Setup the simulation scene."""
Expand All @@ -91,15 +93,17 @@ def stopSimulation(self) -> None:
if self._sceneUp is True:
self._simulationRunning = False

def resetSimulation(self, parameterNode=None) -> None:
pass

Comment on lines +96 to +98
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function has little use as is. I would move here all the lines involving member variables of this class from https://github.com/Quilliams85/Slicer-SOFA/blob/7bbc2cea19222da2e40646b99230668d78d0bfa9/SoftTissueSimulation/SoftTissueSimulation.py#L406-L417

def simulationStep(self, parameterNode=None) -> None:
"""Perform a single simulation step."""

if self._sceneUp is False or self._simulationRunning is False:
slicer.util.errorDisplay("Can't advance the simulation forward. Simulation is not running.")
return

parameterNode.modelNode.GetUnstructuredGrid()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not needed, we should remove it


self.updateSofa(parameterNode)

if self._currentStep < self._totalSteps:
Sofa.Simulation.animate(self._rootNode, self._dt)
self._currentStep += 1
Expand Down
7 changes: 7 additions & 0 deletions SoftTissueSimulation/Resources/UI/SoftTissueSimulation.ui
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="resetSimulationPushButton">
<property name="text">
<string>Reset Simulation</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
Expand Down
38 changes: 34 additions & 4 deletions SoftTissueSimulation/SoftTissueSimulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ def setup(self) -> None:

self.ui.startSimulationPushButton.connect("clicked()", self.startSimulation)
self.ui.stopSimulationPushButton.connect("clicked()", self.stopSimulation)
self.ui.resetSimulationPushButton.connect("clicked()", self.resetSimulation)
self.ui.addBoundaryROIPushButton.connect("clicked()", self.logic.addBoundaryROI)
self.ui.addGravityVectorPushButton.connect("clicked()", self.logic.addGravityVector)
self.ui.addMovingPointPushButton.connect("clicked()", self.logic.addMovingPoint)
Expand Down Expand Up @@ -298,7 +299,7 @@ def updateSimulationGUI(self, caller, event):

def startSimulation(self):
self.logic.dt = self.ui.dtSpinBox.value
self.logic.totalSteps = self.ui.totalStepsSpinBox.value
self.logic._totalSteps = self.ui.totalStepsSpinBox.value
self.logic.currentStep = self.ui.currentStepSpinBox.value
self.logic.startSimulation()
self.timer.start(0) #This timer drives the simulation updates
Expand All @@ -307,8 +308,14 @@ def stopSimulation(self):
self.timer.stop()
self.logic.stopSimulation()

def resetSimulation(self):
self.timer.stop()
self.ui.currentStepSpinBox.value = 0
self.logic.resetSimulation()

def simulationStep(self):
self.logic.simulationStep(self.parameterNode)
self.logic.simulationStep(self.parameterNode)
self.ui.currentStepSpinBox.value +=1

#
# SoftTissueSimulationLogic
Expand All @@ -330,6 +337,7 @@ def __init__(self) -> None:
self.connectionStatus = 0
self.boxROI = None
self.mouseInteractor = None
self.startup = True

def updateSofa(self, parameterNode) -> None:
if parameterNode is not None:
Expand Down Expand Up @@ -363,9 +371,11 @@ def getSimulationController(self):
return self.simulationController

def startSimulation(self) -> None:

sequenceNode = self.getParameterNode().sequenceNode
browserNode = self.getParameterNode().sequenceBrowserNode
modelNode = self.getParameterNode().modelNode

movingPointNode = self.getParameterNode().movingPointNode

# Synchronize and set up the sequence browser node
Expand All @@ -375,6 +385,12 @@ def startSimulation(self) -> None:
browserNode.SetRecording(sequenceNode, True)
browserNode.SetRecordingActive(True)


#if it's the first time running simulation, save the initial mesh points for reset
if self.startup:
self.startup = False
self.initialgrid = self.getParameterNode().getModelPointsArray()

super().startSimulation(self.getParameterNode())
self._simulationRunning = True
self.getParameterNode().Modified()
Expand All @@ -387,6 +403,21 @@ def stopSimulation(self) -> None:
browserNode.SetRecordingActive(False)
self.getParameterNode().Modified()

def resetSimulation(self) -> None:
self.currentStep = 0
self.totalSteps = 0
#reset mesh
points_vtk = numpy_to_vtk(num_array=self.initialgrid, deep=True, array_type=vtk.VTK_FLOAT)
vtk_points = vtk.vtkPoints()
vtk_points.SetData(points_vtk)
self.getParameterNode().modelNode.GetUnstructuredGrid().SetPoints(vtk_points)
Comment on lines +410 to +413
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pieper recommended to not to use this way of updating the mesh as the ownership of the underlying memory by sofa objects and vtk objects can cause this to crash. Instead, you can look at https://github.com/RafaelPalomar/SlicerSOFA/blob/ce4b4131a9ed4a0403641de4cf44efcf455d2c34/MultiMaterialSimulation/MultiMaterialSimulation.py#L289-L298 where I use the approach suggested by @pieper

As mentioned above, moving as much as possible to the base class will help reusing the code

#reset simulation
self.stopSimulation()
self.clean()
self.createScene(self.getParameterNode())



def onModelNodeModified(self, caller, event) -> None:
if self.getParameterNode().modelNode.GetUnstructuredGrid() is not None:
self.getParameterNode().modelNode.GetUnstructuredGrid().SetPoints(caller.GetPolyData().GetPoints())
Expand All @@ -410,7 +441,6 @@ def addBoundaryROI(self) -> None:
size = [abs(bounds[1] - bounds[0])/2.0, abs(bounds[3] - bounds[2])/2.0, abs(bounds[5] - bounds[4])/2.0]
roiNode.SetXYZ(center)
roiNode.SetRadiusXYZ(size[0], size[1], size[2])

self.getParameterNode().boundaryROI = roiNode

def addGravityVector(self) -> None:
Expand Down Expand Up @@ -531,7 +561,6 @@ def createScene(self, parameterNode) -> Sofa.Core.Node:
from stlib3.physics.deformable import ElasticMaterialObject
from stlib3.physics.rigid import Floor
from splib3.numerics import Vec3

rootNode = Sofa.Core.Node()

MainHeader(rootNode, plugins=[
Expand Down Expand Up @@ -586,6 +615,7 @@ def createScene(self, parameterNode) -> Sofa.Core.Node:
femNode.addObject('TetrahedronFEMForceField', name="FEM", youngModulus=1.5, poissonRatio=0.45, method="large")
femNode.addObject('MeshMatrixMass', totalMass=1)


fixedROI = femNode.addChild('FixedROI')
self.BoxROI = fixedROI.addObject('BoxROI', template="Vec3", box=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0], drawBoxes=False,
position="@../mstate.rest_position", name="FixedROI",
Expand Down