Skip to content

Commit 8cf4692

Browse files
authored
[doc] Fix examples given in the First Steps (#494)
1 parent 441731d commit 8cf4692

File tree

1 file changed

+85
-32
lines changed

1 file changed

+85
-32
lines changed

docs/sphinx/source/content/FirstSteps.rst

Lines changed: 85 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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
187226
Now, if you click on the Animate button in SOFA, the sphere will fall.
188227

189228

229+
190230
Add a second object
191231
^^^^^^^^^^^^^^^^^^^
192232

193233
Let'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

Comments
 (0)