Accessing and mofiying array values with Context Managers in SofaPython3 #4380
Replies: 4 comments 2 replies
-
Hey @nicklj import sys
import Sofa
class ManageParticles(Sofa.Core.Controller):
def __init__(self, *args, **kwargs):
# These are needed (and the normal way to override from a python class)
Sofa.Core.Controller.__init__(self, *args, **kwargs)
self.CFF = kwargs.get("ForceField")
self.rootNode = kwargs.get("rootNode")
self.iteration = 1
def onKeypressedEvent(self, event):
key = event['key']
if key=="+" :
with self.CFF.totalForce.writeableArray() as wa:
wa[0] += 0.002
if key=="-" :
with self.CFF.totalForce.writeableArray() as wa:
wa[0] -= 0.002
if key=="A" :
self.addParticle()
if key=="M" :
self.removeParticle()
return 0;
def addParticle(self):
iteration_loc = self.iteration
name = 'Particle'+str(iteration_loc)
myParticleNode = self.rootNode.addChild(str(name))
myParticleNode.addObject('EulerImplicitSolver')
myParticleNode.addObject('CGLinearSolver', threshold='1e-09', tolerance='1e-09', iterations='200')
myParticleNode.addObject('MechanicalObject', showObject='1', position='0 0 '+str(iteration_loc)+' 0 0 0 1', name='myParticle-'+str(iteration_loc), template='Rigid3d')
myNewMass = myParticleNode.addObject('UniformMass', totalMass='1')
myNewCFF = myParticleNode.addObject('ConstantForceField', name="CFF", totalForce="0.05 0 0 0 0 0" )
myNewMass.init()
myNewCFF.init()
self.iteration = iteration_loc +1
return 0;
def removeParticle(self):
iteration_loc = self.iteration - 1
if iteration_loc >= 0:
name = 'Particle'+str(iteration_loc)
nodeToDelete = self.rootNode.getChild(str(name))
for obj in nodeToDelete.objects:
nodeToDelete.removeObject(obj)
myParticleNode = self.rootNode.removeChild(str(name))
self.iteration = iteration_loc
return 0;
def createScene(root):
root.dt = 0.01
root.gravity = [0,0,0]
root.addObject('RequiredPlugin', name="SIOS-load", pluginName="SofaImplicitOdeSolver")
root.addObject('RequiredPlugin', name="SBC-load", pluginName="SofaBoundaryCondition")
root.addObject('DefaultVisualManagerLoop')
root.addObject('DefaultAnimationLoop')
Particle = root.addChild('Particle0')
Particle.addObject('EulerImplicitSolver')
Particle.addObject('CGLinearSolver', threshold='1e-09', tolerance='1e-09', iterations='200')
Particle.addObject('MechanicalObject', showObject='1', position='0 0 0 0 0 0 1', name='Particle-0', template='Rigid3d')
Particle.addObject('UniformMass', totalMass='1')
Particle.addObject('ConstantForceField', name="CFF", totalForce="0 0 0 0 0 0" )
root.addObject( ManageParticles(name="MyParticlesController", ForceField=Particle.CFF, rootNode=root) )
return 0;
def main():
import SofaRuntime
import Sofa.Gui
# Make sure to load all SOFA libraries
SofaRuntime.importPlugin("SofaBaseMechanics")
SofaRuntime.importPlugin("SofaOpenglVisual")
SofaRuntime.importPlugin("CImgPlugin")
#Create the root node
root = Sofa.Core.Node("root")
# Call the below 'createScene' function to create the scene graph
createScene(root)
Sofa.Simulation.init(root)
# Launch the GUI (qt or qglviewer)
Sofa.Gui.GUIManager.Init("myscene", "qglviewer")
Sofa.Gui.GUIManager.createGUI(root, __file__)
Sofa.Gui.GUIManager.SetDimension(1080, 600)
# Initialization of the scene will be done here
Sofa.Gui.GUIManager.MainLoop(root)
Sofa.Gui.GUIManager.closeGUI()
print("Simulation is done.")
# Function used only if this script is called from a python environment
if __name__ == '__main__':
main() or an example on forcefield is given in the plugin examples |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
This question was previously asked in the SOFA forum as:
https://www.sofa-framework.org/community/forum/topic/accessing-and-mofiying-array-values-with-context-managers-in-sofapython3/
However, as there was no response, and I believe this is really a very important issue, so I post the problem here again for discussion.
The issue occurs when accessing numpy list values with context managers in SofaPython3. I think the nature of the problem is very similar to the question as in the thread as (Issue when changing object position via python scene.), but I’ll try to explain it more clearly.
The motivation is I’d like to move object with modifying the rest_position in the mechanicalObject and with the help of RestShapeSpringsForceField. This is very stratiforward in the previous SofaPython2 version. However, in the SofaPython3, it seems cannot directly modify the value. I’ve tried
self.rootNode.finger1.mechObj.rest_position.value = ****
But clearly it doens not work. I’ve checked many related topics in the forum, and one very clear explanation is as:
Data.value vs Data.writeable() with SP3
However, although I understand the motivation and common practice in modifying the values, I cannot successfully achieve it. The big issue is, the accessed numpy array is not the correct one after 2-3 time steps, and obviously it does not point to the correct memory address, which will yield segmentation fault if I modify it. Here I attached the sample scene file for your reference. The example is with rigid body, but the same problem occurs for deformable body.
https://www.dropbox.com/s/2exibu9m2vahlhs/simplegripper.zip?dl=0
Environment: Ubuntu 20.04 + compiled latest SOFA commit at github
Not sure whether this is because of my wrong usage, or some bugs in the program. Much appreciate if anyone may help to address this issue.
Beta Was this translation helpful? Give feedback.
All reactions