FreeMotionAnimationLoop
This component belongs to the category of AnimationLoop.
The FreeMotionAnimationLoop is the component that rules the simulation in two main steps: a free motion, then a correction step. First, the free motion computes the projective constraints, the physics, solving the resulting free linear system. Second, the correction step solves the constraints based on the Lagrange multipliers. More information on the constraint resolution can be found here.
Usage
The FreeMotionAnimationLoop must be used specifically for constraint resolution based on the Lagrange multiplier. It therefore requires:
- a ConstraintSolver. If no constraint solver can be found, a LCPConstraintSolver is automatically created by default.
Note that one or multiple ConstraintCorrection may be required by the ConstraintSolver.
The animation loop to use with constraints. You must add this loop at the beginning of the scene if you are using constraints."
Target: Sofa.Component.AnimationLoop
namespace: sofa::component::animationloop
parents:
- BaseAnimationLoop
Data
Name | Description | Default value |
---|---|---|
name | object name | unnamed |
printLog | if true, emits extra messages at runtime. | 0 |
tags | list of the subsets the object belongs to | |
bbox | this object bounding box | |
componentState | The state of the component among (Dirty, Valid, Undefined, Loading, Invalid). | Undefined |
listening | if true, handle the events, otherwise ignore the events | 0 |
computeBoundingBox | If true, compute the global bounding box of the scene at each time step. Used mostly for rendering. | 1 |
solveVelocityConstraintFirst | solve separately velocity constraint violations before position constraint violations | 0 |
threadSafeVisitor | If true, do not use realloc and free visitors in fwdInteractionForceField. | 0 |
Multithreading | ||
parallelCollisionDetectionAndFreeMotion | If true, executes free motion step and collision detection step in parallel. | 0 |
parallelODESolving | If true, solves all the ODEs in parallel during the free motion step. | 0 |
Links
Name | Description | Destination type name |
---|---|---|
context | Graph Node containing this object (or BaseContext::getDefault() if no graph is used) | BaseContext |
slaves | Sub-objects used internally by this object | BaseObject |
master | nullptr for regular objects, or master object for which this object is one sub-objects | BaseObject |
targetNode | Link to the scene's node that will be processed by the loop | BaseNode |
constraintSolver | The ConstraintSolver used in this animation loop (required) | ConstraintSolver |
Examples
FreeMotionAnimationLoop.scn
<?xml version="1.0" ?>
<!--
WARNING: this scene uses a PrecomputedConstraintCorrection which has a heavy initialization step. It may take some time
to load the scene. To cache the result, set the recompute Data of PrecomputedConstraintCorrection to false.
To speed up the collision detection, replace BVHNarrowPhase by ParallelBVHNarrowPhase located in the MultiThreading plugin.
-->
<Node name="root" dt="0.01" gravity="0 981 0">
<RequiredPlugin name="Sofa.Component.AnimationLoop"/> <!-- Needed to use components [FreeMotionAnimationLoop] -->
<RequiredPlugin name="Sofa.Component.Collision.Detection.Algorithm"/> <!-- Needed to use components [BVHNarrowPhase BruteForceBroadPhase CollisionPipeline] -->
<RequiredPlugin name="Sofa.Component.Collision.Detection.Intersection"/> <!-- Needed to use components [LocalMinDistance] -->
<RequiredPlugin name="Sofa.Component.Collision.Geometry"/> <!-- Needed to use components [LineCollisionModel PointCollisionModel TriangleCollisionModel] -->
<RequiredPlugin name="Sofa.Component.Collision.Response.Contact"/> <!-- Needed to use components [CollisionResponse] -->
<RequiredPlugin name="Sofa.Component.Constraint.Lagrangian.Correction"/> <!-- Needed to use components [PrecomputedConstraintCorrection UncoupledConstraintCorrection] -->
<RequiredPlugin name="Sofa.Component.Constraint.Lagrangian.Solver"/> <!-- Needed to use components [LCPConstraintSolver] -->
<RequiredPlugin name="Sofa.Component.IO.Mesh"/> <!-- Needed to use components [MeshGmshLoader MeshOBJLoader] -->
<RequiredPlugin name="Sofa.Component.LinearSolver.Iterative"/> <!-- Needed to use components [CGLinearSolver] -->
<RequiredPlugin name="Sofa.Component.Mapping.Linear"/> <!-- Needed to use components [BarycentricMapping] -->
<RequiredPlugin name="Sofa.Component.Mapping.NonLinear"/> <!-- Needed to use components [RigidMapping] -->
<RequiredPlugin name="Sofa.Component.Mass"/> <!-- Needed to use components [UniformMass] -->
<RequiredPlugin name="Sofa.Component.ODESolver.Backward"/> <!-- Needed to use components [EulerImplicitSolver] -->
<RequiredPlugin name="Sofa.Component.SolidMechanics.FEM.Elastic"/> <!-- Needed to use components [TetrahedronFEMForceField] -->
<RequiredPlugin name="Sofa.Component.StateContainer"/> <!-- Needed to use components [MechanicalObject] -->
<RequiredPlugin name="Sofa.Component.Topology.Container.Constant"/> <!-- Needed to use components [MeshTopology] -->
<RequiredPlugin name="Sofa.Component.Visual"/> <!-- Needed to use components [VisualStyle] -->
<RequiredPlugin name="Sofa.GL.Component.Rendering3D"/> <!-- Needed to use components [OglModel] -->
<VisualStyle displayFlags="showBehaviorModels"/>
<FreeMotionAnimationLoop parallelCollisionDetectionAndFreeMotion="true"/>
<LCPConstraintSolver tolerance="1e-3" maxIt="1000"/>
<CollisionPipeline depth="6" verbose="0" draw="0"/>
<BruteForceBroadPhase/>
<BVHNarrowPhase/>
<LocalMinDistance name="Proximity" alarmDistance="2.5" contactDistance="1.0" angleCone="0.0"/>
<CollisionResponse name="Response" response="FrictionContactConstraint"/>
<Node name="Torus1">
<MeshOBJLoader filename="mesh/torus2_for_collision.obj" name="loader"/>
<MeshTopology src="@loader"/>
<MechanicalObject src="@loader" scale="5.0"/>
<TriangleCollisionModel simulated="0" moving="0"/>
<LineCollisionModel simulated="0" moving="0"/>
<PointCollisionModel simulated="0" moving="0"/>
<MeshOBJLoader name="meshLoader_0" filename="mesh/torus2.obj" scale="5.0" handleSeams="1" />
<OglModel name="Visual" src="@meshLoader_0" color="0.5 0.5 0.5 1.0"/>
</Node>
<Node name="TorusFEM">
<EulerImplicitSolver rayleighMass="0.01" rayleighStiffness="0.001"/>
<CGLinearSolver iterations="15" threshold="1.0e-15" tolerance="1.0e-9"/>
<!--<SparseLDLSolver />-->
<MeshGmshLoader name="loader" filename="mesh/torus_low_res.msh"/>
<MeshTopology src="@loader"/>
<MechanicalObject src="@loader" dx="-12" dy="0" dz="0" rx="0" ry="0" rz="0" scale="5.0"/>
<UniformMass totalMass="0.2"/>
<TetrahedronFEMForceField name="FEM" youngModulus="60000" poissonRatio="0.48" computeGlobalMatrix="false" method="polar"/>
<!--<LinearSolverConstraintCorrection />-->
<PrecomputedConstraintCorrection rotations="true" recompute="true"/>
<Node name="Visu">
<MeshOBJLoader name="meshLoader_2" filename="mesh/torus.obj" scale="5.0" handleSeams="1" />
<OglModel name="Visual" src="@meshLoader_2" color="red" dx="-12" dy="0" dz="0" rx="0" ry="0" rz="0"/>
<BarycentricMapping input="@.." output="@Visual"/>
</Node>
<Node name="Surf2">
<MeshOBJLoader name="loader" filename="mesh/torus_for_collision.obj"/>
<MeshTopology src="@loader"/>
<MechanicalObject src="@loader" dx="-12" dy="0" dz="0" rx="0" ry="0" rz="0" scale="5.0"/>
<TriangleCollisionModel contactStiffness="0.1"/>
<LineCollisionModel/>
<PointCollisionModel/>
<BarycentricMapping/>
</Node>
</Node>
<Node name="Torus3">
<EulerImplicitSolver/>
<CGLinearSolver iterations="25" tolerance="1e-5" threshold="1e-5"/>
<MechanicalObject template="Rigid3" scale="5.0" dx="-25" dy="0"/>
<UniformMass filename="BehaviorModels/torus2.rigid" totalMass="0.02"/>
<UncoupledConstraintCorrection/>
<Node name="Visu">
<MeshOBJLoader name="meshLoader_1" filename="mesh/torus2.obj" scale="5.0" handleSeams="1" />
<OglModel name="Visual" src="@meshLoader_1" color="1.0 0.5 0.25 1.0"/>
<RigidMapping input="@.." output="@Visual"/>
</Node>
<Node name="Surf2">
<MeshOBJLoader filename="mesh/torus2_for_collision.obj" name="loader"/>
<MeshTopology src="@loader"/>
<MechanicalObject src="@loader" scale="5.0"/>
<TriangleCollisionModel/>
<LineCollisionModel/>
<PointCollisionModel/>
<RigidMapping/>
</Node>
</Node>
</Node>
def createScene(root_node):
root = root_node.addChild('root', dt="0.01", gravity="0 981 0")
root.addObject('RequiredPlugin', name="Sofa.Component.AnimationLoop")
root.addObject('RequiredPlugin', name="Sofa.Component.Collision.Detection.Algorithm")
root.addObject('RequiredPlugin', name="Sofa.Component.Collision.Detection.Intersection")
root.addObject('RequiredPlugin', name="Sofa.Component.Collision.Geometry")
root.addObject('RequiredPlugin', name="Sofa.Component.Collision.Response.Contact")
root.addObject('RequiredPlugin', name="Sofa.Component.Constraint.Lagrangian.Correction")
root.addObject('RequiredPlugin', name="Sofa.Component.Constraint.Lagrangian.Solver")
root.addObject('RequiredPlugin', name="Sofa.Component.IO.Mesh")
root.addObject('RequiredPlugin', name="Sofa.Component.LinearSolver.Iterative")
root.addObject('RequiredPlugin', name="Sofa.Component.Mapping.Linear")
root.addObject('RequiredPlugin', name="Sofa.Component.Mapping.NonLinear")
root.addObject('RequiredPlugin', name="Sofa.Component.Mass")
root.addObject('RequiredPlugin', name="Sofa.Component.ODESolver.Backward")
root.addObject('RequiredPlugin', name="Sofa.Component.SolidMechanics.FEM.Elastic")
root.addObject('RequiredPlugin', name="Sofa.Component.StateContainer")
root.addObject('RequiredPlugin', name="Sofa.Component.Topology.Container.Constant")
root.addObject('RequiredPlugin', name="Sofa.Component.Visual")
root.addObject('RequiredPlugin', name="Sofa.GL.Component.Rendering3D")
root.addObject('VisualStyle', displayFlags="showBehaviorModels")
root.addObject('FreeMotionAnimationLoop', parallelCollisionDetectionAndFreeMotion="true")
root.addObject('LCPConstraintSolver', tolerance="1e-3", maxIt="1000")
root.addObject('CollisionPipeline', depth="6", verbose="0", draw="0")
root.addObject('BruteForceBroadPhase', )
root.addObject('BVHNarrowPhase', )
root.addObject('LocalMinDistance', name="Proximity", alarmDistance="2.5", contactDistance="1.0", angleCone="0.0")
root.addObject('CollisionResponse', name="Response", response="FrictionContactConstraint")
torus1 = root.addChild('Torus1')
torus1.addObject('MeshOBJLoader', filename="mesh/torus2_for_collision.obj", name="loader")
torus1.addObject('MeshTopology', src="@loader")
torus1.addObject('MechanicalObject', src="@loader", scale="5.0")
torus1.addObject('TriangleCollisionModel', simulated="0", moving="0")
torus1.addObject('LineCollisionModel', simulated="0", moving="0")
torus1.addObject('PointCollisionModel', simulated="0", moving="0")
torus1.addObject('MeshOBJLoader', name="meshLoader_0", filename="mesh/torus2.obj", scale="5.0", handleSeams="1")
torus1.addObject('OglModel', name="Visual", src="@meshLoader_0", color="0.5 0.5 0.5 1.0")
torus_fem = root.addChild('TorusFEM')
torus_fem.addObject('EulerImplicitSolver', rayleighMass="0.01", rayleighStiffness="0.001")
torus_fem.addObject('CGLinearSolver', iterations="15", threshold="1.0e-15", tolerance="1.0e-9")
torus_fem.addObject('MeshGmshLoader', name="loader", filename="mesh/torus_low_res.msh")
torus_fem.addObject('MeshTopology', src="@loader")
torus_fem.addObject('MechanicalObject', src="@loader", dx="-12", dy="0", dz="0", rx="0", ry="0", rz="0", scale="5.0")
torus_fem.addObject('UniformMass', totalMass="0.2")
torus_fem.addObject('TetrahedronFEMForceField', name="FEM", youngModulus="60000", poissonRatio="0.48", computeGlobalMatrix="false", method="polar")
torus_fem.addObject('PrecomputedConstraintCorrection', rotations="true", recompute="true")
visu = TorusFEM.addChild('Visu')
visu.addObject('MeshOBJLoader', name="meshLoader_2", filename="mesh/torus.obj", scale="5.0", handleSeams="1")
visu.addObject('OglModel', name="Visual", src="@meshLoader_2", color="red", dx="-12", dy="0", dz="0", rx="0", ry="0", rz="0")
visu.addObject('BarycentricMapping', input="@..", output="@Visual")
surf2 = TorusFEM.addChild('Surf2')
surf2.addObject('MeshOBJLoader', name="loader", filename="mesh/torus_for_collision.obj")
surf2.addObject('MeshTopology', src="@loader")
surf2.addObject('MechanicalObject', src="@loader", dx="-12", dy="0", dz="0", rx="0", ry="0", rz="0", scale="5.0")
surf2.addObject('TriangleCollisionModel', contactStiffness="0.1")
surf2.addObject('LineCollisionModel', )
surf2.addObject('PointCollisionModel', )
surf2.addObject('BarycentricMapping', )
torus3 = root.addChild('Torus3')
torus3.addObject('EulerImplicitSolver', )
torus3.addObject('CGLinearSolver', iterations="25", tolerance="1e-5", threshold="1e-5")
torus3.addObject('MechanicalObject', template="Rigid3", scale="5.0", dx="-25", dy="0")
torus3.addObject('UniformMass', filename="BehaviorModels/torus2.rigid", totalMass="0.02")
torus3.addObject('UncoupledConstraintCorrection', )
visu = Torus3.addChild('Visu')
visu.addObject('MeshOBJLoader', name="meshLoader_1", filename="mesh/torus2.obj", scale="5.0", handleSeams="1")
visu.addObject('OglModel', name="Visual", src="@meshLoader_1", color="1.0 0.5 0.25 1.0")
visu.addObject('RigidMapping', input="@..", output="@Visual")
surf2 = Torus3.addChild('Surf2')
surf2.addObject('MeshOBJLoader', filename="mesh/torus2_for_collision.obj", name="loader")
surf2.addObject('MeshTopology', src="@loader")
surf2.addObject('MechanicalObject', src="@loader", scale="5.0")
surf2.addObject('TriangleCollisionModel', )
surf2.addObject('LineCollisionModel', )
surf2.addObject('PointCollisionModel', )
surf2.addObject('RigidMapping', )