@@ -46,11 +46,14 @@ One must therefore create it and then call the ``createScene()`` function:
4646 createScene(root)
4747
4848 # Once defined, initialization of the scene graph
49- Sofa.Simulation.init (root)
49+ Sofa.Simulation.initRoot (root)
5050
5151 # Run as many simulation steps (here 10 steps are computed)
5252 for iteration in range (10 ):
5353 Sofa.Simulation.animate(root, root.dt.value)
54+ print (" Computing iteration " + str (iteration+ 1 ))
55+
56+ print (" Computation is done." )
5457
5558
5659 # Same createScene function as in the previous case
@@ -72,23 +75,26 @@ In case you want to manage the simulation from the runSofa GUI, you can simply c
7275.. code-block :: python
7376
7477 def main ():
75- # Call the SOFA function to create the root node
76- root = Sofa.Core.Node(" root" )
78+ # Call the SOFA function to create the root node
79+ root = Sofa.Core.Node(" root" )
7780
78- # Call the createScene function, as runSofa does
79- createScene(root)
81+ # Call the createScene function, as runSofa does
82+ createScene(root)
8083
81- # Once defined, initialization of the scene graph
82- Sofa.Simulation.init (root)
84+ # Once defined, initialization of the scene graph
85+ Sofa.Simulation.initRoot (root)
8386
84- # Launch the GUI (qt or qglviewer)
85- Sofa.Gui.GUIManager.Init(" myscene" , " qglviewer" )
86- Sofa.Gui.GUIManager.createGUI(root, __file__ )
87- Sofa.Gui.GUIManager.SetDimension(1080 , 800 )
87+ # Import the GUI package
88+ import Sofa.Gui
8889
89- # Initialization of the scene will be done here
90- Sofa.Gui.GUIManager.MainLoop(root)
91- Sofa.Gui.GUIManager.closeGUI()
90+ # Launch the GUI (qt or qglviewer)
91+ Sofa.Gui.GUIManager.Init(" myscene" , " qglviewer" )
92+ Sofa.Gui.GUIManager.createGUI(root, __file__ )
93+ Sofa.Gui.GUIManager.SetDimension(1080 , 800 )
94+
95+ # Initialization of the scene will be done here
96+ Sofa.Gui.GUIManager.MainLoop(root)
97+ Sofa.Gui.GUIManager.closeGUI()
9298
9399
94100 So far, you can load this python scene, but it doesn't do much. Let's enrich this scene!
@@ -116,29 +122,56 @@ We first propose to add a visual grid, in order to see things more clearly. To d
116122.. code-block :: python
117123
118124 def createScene (rootNode ):
125+ # Make sure to load all necessary libraries
126+ import SofaRuntime
127+ SofaRuntime.importPlugin(" Sofa.Component.Visual" )
128+
129+ # Add an object (here of type VisualGrid, with its data "nbSubdiv" and "size")
119130 rootNode.addObject(" VisualGrid" , nbSubdiv = 10 , size = 1000 )
120131
121132 Now, we create a new child node, in order to add the general configuration of the scene : required plugins (here SofaPython3) and other tools (like a system of axes).
122133
123134.. code-block :: python
124-
125- confignode = rootNode.addChild(" Config" )
126- confignode.addObject(' OglSceneFrame' , style = " Arrows" , alignment = " TopRight" )
135+ def createScene (rootNode ):
136+ import SofaRuntime
137+ # Make sure to load all necessary libraries
138+ SofaRuntime.importPlugin(" Sofa.Component.Visual" )
139+ SofaRuntime.importPlugin(" Sofa.GL.Component.Rendering3D" )
140+
141+ rootNode.addObject(" VisualGrid" , nbSubdiv = 10 , size = 1000 )
142+
143+ confignode = rootNode.addChild(" Config" )
144+ confignode.addObject(' OglSceneFrame' , style = " Arrows" , alignment = " TopRight" )
127145
128146
129147 Finally, we add the sphere itself, which consists of two parts : the mechanical representation and the visual representation of the sphere:
130148
131149.. code-block :: python
150+ def createScene (rootNode ):
151+ import SofaRuntime
152+ # Make sure to load all necessary libraries
153+ SofaRuntime.importPlugin(" Sofa.Component.Visual" )
154+ SofaRuntime.importPlugin(" Sofa.GL.Component.Rendering3D" )
155+ SofaRuntime.importPlugin(" Sofa.Component.StateContainer" )
156+ SofaRuntime.importPlugin(" Sofa.Component.IO.Mesh" )
157+ SofaRuntime.importPlugin(" Sofa.Component.Mapping.NonLinear" )
158+ SofaRuntime.importPlugin(" Sofa.Component.AnimationLoop" )
159+
160+ rootNode.addObject(" VisualGrid" , nbSubdiv = 10 , size = 1000 )
161+ rootNode.addObject(" DefaultAnimationLoop" )
162+
163+ confignode = rootNode.addChild(" Config" )
164+ confignode.addObject(' OglSceneFrame' , style = " Arrows" , alignment = " TopRight" )
132165
133- # Creating the falling sphere object
134- sphere = rootNode.addChild(" sphere" )
135- sphere.addObject(' MechanicalObject' , name = " mstate" , template = " Rigid3" , translation2 = [0 ., 0 ., 0 .], rotation2 = [0 ., 0 ., 0 .], showObjectScale = 50 )
166+ # Creating the falling sphere object
167+ sphere = rootNode.addChild(" sphere" )
168+ sphere.addObject(' MechanicalObject' , name = " mstate" , template = " Rigid3" , translation2 = [0 ., 0 ., 0 .], rotation2 = [0 ., 0 ., 0 .], showObjectScale = 50 )
136169
137- # ### Visualization subnode for the sphere
138- sphereVisu = sphere.addChild(" VisualModel" )
139- sphereVisu.loader = sphereVisu.addObject(' MeshOBJLoader' , name = " loader" , filename = " mesh/ball.obj" )
140- sphereVisu.addObject(' OglModel' , name = " model" , src = " @loader" , scale3d = [50 ]* 3 , color = [0 ., 1 ., 0 .], updateNormals = False )
141- sphereVisu.addObject(' RigidMapping' )
170+ # ### Visualization subnode for the sphere
171+ sphereVisu = sphere.addChild(" VisualModel" )
172+ sphereVisu.loader = sphereVisu.addObject(' MeshOBJLoader' , name = " loader" , filename = " mesh/ball.obj" )
173+ sphereVisu.addObject(' OglModel' , name = " model" , src = " @loader" , scale3d = [50 ]* 3 , color = [0 ., 1 ., 0 .], updateNormals = False )
174+ sphereVisu.addObject(' RigidMapping' )
142175
143176 .. image :: ../images/exampleScene_step1.png
144177 :alt: This is what you should see in Sofa at this stage
@@ -169,8 +202,14 @@ We add a mechanical model, so that all our futur elements will have the same tot
169202
170203 We add properties to the sphere. First, we add a mass, then an object called 'UncoupledConstraintCorrection', in charge of computing the constraint forces of the sphere, then we add two different solvers. One is a time integration scheme that defines the system to be solved at each time step of the simulation (here the implicit Euler Method), the other is a solving method (here the Conjugate Gradient method), that solves the equations governing the model at each time step, and updates the MechanicalObject.
171204
205+
172206.. code-block :: python
173207
208+ SofaRuntime.importPlugin(" Sofa.Component.ODESolver.Backward" )
209+ SofaRuntime.importPlugin(" Sofa.Component.LinearSolver.Iterative" )
210+ SofaRuntime.importPlugin(" Sofa.Component.Mass" )
211+ SofaRuntime.importPlugin(" Sofa.Component.Constraint.Lagrangian.Correction" )
212+
174213 # Creating the falling sphere object
175214 sphere = rootNode.addChild(" sphere" )
176215 sphere.addObject(' EulerImplicitSolver' , name = ' odesolver' )
@@ -187,13 +226,17 @@ We add properties to the sphere. First, we add a mass, then an object called 'Un
187226Now, if you click on the Animate button in SOFA, the sphere will fall.
188227
189228
229+
190230Add a second object
191231^^^^^^^^^^^^^^^^^^^
192232
193233Let's add a second element, a floor, to see how they interact :
194234
195235.. code-block :: python
196236
237+ SofaRuntime.importPlugin(" Sofa.Component.Topology.Container.Constant" )
238+ SofaRuntime.importPlugin(" Sofa.Component.Collision.Geometry" )
239+
197240 # Creating the floor object
198241 floor = rootNode.addChild(" floor" )
199242
@@ -232,7 +275,7 @@ We first add a collision model for the scene in general, that is stating how a c
232275.. code-block :: python
233276
234277 # Collision pipeline
235- rootNode.addObject(' DefaultPipeline ' )
278+ rootNode.addObject(' CollisionPipeline ' )
236279 rootNode.addObject(' FreeMotionAnimationLoop' )
237280 rootNode.addObject(' GenericConstraintSolver' , tolerance = " 1e-6" , maxIterations = " 1000" )
238281 rootNode.addObject(' BruteForceBroadPhase' )
@@ -270,6 +313,17 @@ We do the same for the floor, but we also specify that the floor is a stationnar
270313 floorCollis.addObject(' PointCollisionModel' , moving = False , simulated = False )
271314 floorCollis.addObject(' RigidMapping' )
272315
316+ Note that for this step you might have to load the following modules:
317+
318+ .. code-block :: python
319+
320+ SofaRuntime.importPlugin(" Sofa.Component.Collision.Detection.Intersection" )
321+ SofaRuntime.importPlugin(" Sofa.Component.Collision.Detection.Algorithm" )
322+ SofaRuntime.importPlugin(" Sofa.Component.Collision.Geometry" )
323+ SofaRuntime.importPlugin(" Sofa.Component.Collision.Response" )
324+ SofaRuntime.importPlugin(" Sofa.Component.Constraint.Lagrangian.Solver" )
325+ SofaRuntime.importPlugin(" Sofa.Component.Topology.Container.Constant" )
326+
273327
274328 .. image :: ../images/exampleScene_step4.gif
275329 :alt: This is what you should see in Sofa at this stage
@@ -302,7 +356,7 @@ Here is the entire code of the scene :
302356 createScene(root)
303357
304358 # Once defined, initialization of the scene graph
305- Sofa.Simulation.init (root)
359+ Sofa.Simulation.initRoot (root)
306360
307361 # Launch the GUI (qt or qglviewer)
308362 Sofa.Gui.GUIManager.Init(" myscene" , " qglviewer" )
@@ -316,8 +370,6 @@ Here is the entire code of the scene :
316370
317371 def createScene (rootNode ):
318372
319- rootNode.addObject(" VisualGrid" , nbSubdiv = 10 , size = 1000 )
320-
321373 # Define the root node properties
322374 rootNode.gravity= [0.0 ,- 9.81 ,0.0 ]
323375 rootNode.dt= 0.01
@@ -341,10 +393,11 @@ Here is the entire code of the scene :
341393 confignode.addObject(' RequiredPlugin' , name = " Sofa.Component.Visual" , printLog = False )
342394 confignode.addObject(' RequiredPlugin' , name = " Sofa.GL.Component.Rendering3D" , printLog = False )
343395 confignode.addObject(' OglSceneFrame' , style = " Arrows" , alignment = " TopRight" )
396+ confignode.addObject(" VisualGrid" , nbSubdiv = 10 , size = 1000 )
344397
345398
346399 # Collision pipeline
347- rootNode.addObject(' DefaultPipeline ' )
400+ rootNode.addObject(' CollisionPipeline ' )
348401 rootNode.addObject(' FreeMotionAnimationLoop' )
349402 rootNode.addObject(' GenericConstraintSolver' , tolerance = " 1e-6" , maxIterations = " 1000" )
350403 rootNode.addObject(' BruteForceBroadPhase' )
@@ -466,7 +519,7 @@ In the same way, Data can be modified (write access) using the ``.value`` access
466519 createScene(root)
467520
468521 # Once defined, initialization of the scene graph
469- Sofa.Simulation.init (root)
522+ Sofa.Simulation.initRoot (root)
470523
471524 # Run the simulation for 10 steps
472525 for iteration in range (10 ):
@@ -494,7 +547,7 @@ For more complex Data such as Data related to the degrees of freedom (e.g. Coord
494547.. code-block :: python
495548
496549 with root.sphere.CFF .totalForce.writeableArray() as wa:
497- wa[0 ] += 0.01 # modify the first entry of the Deriv Data "totalForce"
550+ wa[0 ] += 0.01 # modify the first entry of the Deriv Data "totalForce"
498551
499552
500553
0 commit comments