Back

DefaultAnimationLoop

This component is responsible for driving the animation loop in Sofa simulations by triggering several critical steps to compute collision detection, solve physics equations, update simulation context, mappings and bounding boxes.

abstract
The DefaultAnimationLoop drives the simulation loop in SOFA by orchestrating collision detection, physics solving, and context updating steps. It supports parallel ODE solving through a configurable parameter.
sheet
# DefaultAnimationLoop ## Overview DefaultAnimationLoop is responsible for driving the simulation loop in SOFA simulations. It handles critical steps such as collision detection, solving physics equations, and updating the simulation context. This component inherits from `BaseAnimationLoop`. ## Parameters and Data - **d_parallelODESolving**: A boolean parameter that controls whether ODEs are solved in parallel (`true`) or sequentially (`false`).
name
DefaultAnimationLoop
description
This component is responsible for driving the animation loop in Sofa simulations by triggering several critical steps to compute collision detection, solve physics equations, update simulation context, mappings and bounding boxes.
parameters
  • {'name': 'parallelODESolving', 'type': 'bool', 'default_value': 'false', 'description': 'If set to true, the component will enable parallel solving for all Ordinary Differential Equations (ODEs) in the system.'}
  • {'name': 'computeBoundingBox', 'type': 'bool', 'default_value': 'true', 'description': 'Determines whether or not the bounding box computation is executed. When enabled, it calculates a volume that covers all objects within the simulation scene.'}
methods
  • {'name': 'init()', 'description': 'Initializes the component and validates its state based on the presence of an associated node.'}
  • {'name': 'setNode(Node* n)', 'description': 'Sets the simulation node to which this animation loop is attached, allowing it to manipulate objects within that scene.'}
functionality
  • It manages the entire sequence of operations for each frame in a Sofa simulation.
  • First, it updates object behavior and internal data according to elapsed time.
  • Then it performs collision detection by detecting any intersecting objects within the scene.
  • Following this, the component solves all physics equations which include applying forces and constraints to determine new positions and velocities of objects.
  • After resolving the physics, it projects updated positions and velocities into the next simulation step.
  • The animation loop then updates the simulation context, advancing time for the next frame.
  • Finally, it recalculates mappings (which can involve transforming data between different representations such as mechanical and visual) and re-evaluates bounding boxes to encompass all objects in their new positions.
usage
This component is a crucial part of any Sofa scene that requires dynamic simulation. It should be included if you want your scene to animate over time, solving physics equations at each frame while handling collision detection and other essential tasks.
dependencies
  • {'name': 'Node', 'description': 'The node must exist in the scene for this component to function as it provides a context (time, objects) for animation.'}
  • {'name': 'TaskScheduler', 'optional': True, 'description': 'If parallelODESolving is enabled, the TaskScheduler will be initialized to perform parallel computation on ODEs.'}
output
  • The main output of this component is a dynamically updated simulation where objects move according to physical laws and collision responses.
  • It also updates internal states within Sofa for other components to use (like new positions, velocities, and bounding boxes).
maths
The DefaultAnimationLoop component in Sofa is responsible for orchestrating the numerical integration steps required to simulate physical systems over time. The primary goal of the animation loop is to advance the simulation by one or multiple timesteps, updating the state of all entities (e.g., objects, particles) involved in the simulation according to their physics models and constraints. ### Key Steps and Mathematical Formulation: 1. **BehaviorUpdatePosition**: - This step involves updating the position of physical entities based on their behavior models. For a general dynamical system with positions $\mathbf{q}$, velocities $\dot{\mathbf{q}}$, and accelerations $\ddot{\mathbf{q}}$ driven by forces $\mathbf{F}(t)$, the equations of motion can be expressed as: \[ M(\mathbf{q})\ddot{\mathbf{q}} = \mathbf{F}_{ext} - C(\dot{\mathbf{q}}, \mathbf{q}) - G(\mathbf{q}), \] where $M$ is the mass matrix, $C$ includes constraints and dampings, and $G$ is the gravitational force. 2. **Collision Detection**: - This step involves detecting any collisions between objects in the scene. The collision detection algorithm can be formulated as checking for intersections of geometric primitives (e.g., spheres, boxes) defined by their positions and orientations. For two objects with position vectors $\mathbf{p}_1$ and $\mathbf{p}_2$, and radii $r_1$ and $r_2$, the collision condition is: \[ |\mathbf{p}_1 - \mathbf{p}_2| < r_1 + r_2. \] 3. **Integration** (beginIntegration, endIntegration): - This step involves advancing the system's state through numerical integration methods. Common methods include Euler's method, Runge-Kutta schemes, or implicit solvers. - For example, using an explicit Euler method for a single step: \[ \dot{\mathbf{q}}(t + \Delta t) = \dot{\mathbf{q}}(t) + \ddot{\mathbf{q}}(t) \cdot \Delta t, \] \[ \mathbf{q}(t + \Delta t) = \mathbf{q}(t) + \dot{\mathbf{q}}(t) \cdot \Delta t. \] 4. **UpdateSimulationContext**: - This step updates the global simulation context, such as advancing the simulation time $t$ by a timestep $\Delta t$. \[ t_{new} = t + \Delta t. \] 5. **UpdateMapping and Bounding Box Computation**: - Update mappings are used to apply transformations between different representations of objects (e.g., from mechanical to visual representation). - The bounding box computation involves determining the minimum and maximum coordinates that cover all points in a set of geometric entities. \[ \text{BoundingBox} = \left(\min_x, \max_x; \min_y, \max_y; \min_z, \max_z\right). \] ### Parallel Processing: - The DefaultAnimationLoop can also enable parallel processing for solving Ordinary Differential Equations (ODEs) through the TaskScheduler. Parallelization is achieved by dividing the computational load across multiple threads or processes, potentially reducing the time required to perform numerical integration. The animation loop ensures that all these steps are executed in a coordinated manner, advancing the simulation state accurately and efficiently.
{
  "name": "DefaultAnimationLoop",
  "main": {
    "name": "DefaultAnimationLoop",
    "namespace": "sofa::simulation",
    "module": "Sofa.framework.Simulation.Core",
    "include": "sofa/simulation/DefaultAnimationLoop.h",
    "doc": "Simulation loop, created by default when the user does not define one in the scene. This loop first computes the collision detection and then solves the physics.\n\nDefault Animation Loop to be created when no AnimationLoop found on simulation::node.",
    "inherits": [
      "BaseAnimationLoop"
    ],
    "templates": [],
    "data_fields": [
      {
        "name": "d_parallelODESolving",
        "type": "bool",
        "xmlname": "parallelODESolving",
        "help": "If true, solves all the ODEs in parallel"
      }
    ],
    "links": [],
    "methods": [
      {
        "name": "init",
        "return_type": "void",
        "params": [],
        "is_virtual": true,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "public"
      },
      {
        "name": "setNode",
        "return_type": "void",
        "params": [
          {
            "name": "",
            "type": "simulation::Node *"
          }
        ],
        "is_virtual": true,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "public"
      },
      {
        "name": "step",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          },
          {
            "name": "dt",
            "type": "SReal"
          }
        ],
        "is_virtual": true,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "public"
      },
      {
        "name": "behaviorUpdatePosition",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          },
          {
            "name": "dt",
            "type": "SReal"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "updateInternalData",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "beginIntegration",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          },
          {
            "name": "dt",
            "type": "SReal"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "propagateIntegrateBeginEvent",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "accumulateMatrixDeriv",
        "return_type": "void",
        "params": [
          {
            "name": "cparams",
            "type": "sofa::core::ConstraintParams"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "solve",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          },
          {
            "name": "dt",
            "type": "SReal"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "propagateIntegrateEndEvent",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "endIntegration",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          },
          {
            "name": "dt",
            "type": "SReal"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "projectPositionAndVelocity",
        "return_type": "void",
        "params": [
          {
            "name": "nextTime",
            "type": "SReal"
          },
          {
            "name": "mparams",
            "type": "const sofa::core::MechanicalParams &"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "propagateOnlyPositionAndVelocity",
        "return_type": "void",
        "params": [
          {
            "name": "nextTime",
            "type": "SReal"
          },
          {
            "name": "mparams",
            "type": "const sofa::core::MechanicalParams &"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "propagateCollisionBeginEvent",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "propagateCollisionEndEvent",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "collisionDetection",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "animate",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          },
          {
            "name": "dt",
            "type": "SReal"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "updateSimulationContext",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          },
          {
            "name": "dt",
            "type": "SReal"
          },
          {
            "name": "startTime",
            "type": "SReal"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "propagateAnimateEndEvent",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          },
          {
            "name": "dt",
            "type": "SReal"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "updateMapping",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          },
          {
            "name": "dt",
            "type": "SReal"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "computeBoundingBox",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      },
      {
        "name": "propagateAnimateBeginEvent",
        "return_type": "void",
        "params": [
          {
            "name": "params",
            "type": "const sofa::core::ExecParams *"
          },
          {
            "name": "dt",
            "type": "SReal"
          }
        ],
        "is_virtual": false,
        "is_pure_virtual": false,
        "is_static": false,
        "access": "protected"
      }
    ]
  },
  "desc": {
    "name": "DefaultAnimationLoop",
    "description": "This component is responsible for driving the animation loop in Sofa simulations by triggering several critical steps to compute collision detection, solve physics equations, update simulation context, mappings and bounding boxes.",
    "parameters": [
      {
        "name": "parallelODESolving",
        "type": "bool",
        "default_value": "false",
        "description": "If set to true, the component will enable parallel solving for all Ordinary Differential Equations (ODEs) in the system."
      },
      {
        "name": "computeBoundingBox",
        "type": "bool",
        "default_value": "true",
        "description": "Determines whether or not the bounding box computation is executed. When enabled, it calculates a volume that covers all objects within the simulation scene."
      }
    ],
    "methods": [
      {
        "name": "init()",
        "description": "Initializes the component and validates its state based on the presence of an associated node."
      },
      {
        "name": "setNode(Node* n)",
        "description": "Sets the simulation node to which this animation loop is attached, allowing it to manipulate objects within that scene."
      }
    ],
    "functionality": [
      "It manages the entire sequence of operations for each frame in a Sofa simulation.",
      "First, it updates object behavior and internal data according to elapsed time.",
      "Then it performs collision detection by detecting any intersecting objects within the scene.",
      "Following this, the component solves all physics equations which include applying forces and constraints to determine new positions and velocities of objects.",
      "After resolving the physics, it projects updated positions and velocities into the next simulation step.",
      "The animation loop then updates the simulation context, advancing time for the next frame.",
      "Finally, it recalculates mappings (which can involve transforming data between different representations such as mechanical and visual) and re-evaluates bounding boxes to encompass all objects in their new positions."
    ],
    "usage": "This component is a crucial part of any Sofa scene that requires dynamic simulation. It should be included if you want your scene to animate over time, solving physics equations at each frame while handling collision detection and other essential tasks.",
    "dependencies": [
      {
        "name": "Node",
        "description": "The node must exist in the scene for this component to function as it provides a context (time, objects) for animation."
      },
      {
        "name": "TaskScheduler",
        "optional": true,
        "description": "If parallelODESolving is enabled, the TaskScheduler will be initialized to perform parallel computation on ODEs."
      }
    ],
    "output": [
      "The main output of this component is a dynamically updated simulation where objects move according to physical laws and collision responses.",
      "It also updates internal states within Sofa for other components to use (like new positions, velocities, and bounding boxes)."
    ]
  },
  "maths": {
    "maths": "The DefaultAnimationLoop component in Sofa is responsible for orchestrating the numerical integration steps required to simulate physical systems over time. The primary goal of the animation loop is to advance the simulation by one or multiple timesteps, updating the state of all entities (e.g., objects, particles) involved in the simulation according to their physics models and constraints.\n\n### Key Steps and Mathematical Formulation:\n1. **BehaviorUpdatePosition**:\n   - This step involves updating the position of physical entities based on their behavior models. For a general dynamical system with positions $\\mathbf{q}$, velocities $\\dot{\\mathbf{q}}$, and accelerations $\\ddot{\\mathbf{q}}$ driven by forces $\\mathbf{F}(t)$, the equations of motion can be expressed as:\n     \\[ M(\\mathbf{q})\\ddot{\\mathbf{q}} = \\mathbf{F}_{ext} - C(\\dot{\\mathbf{q}}, \\mathbf{q}) - G(\\mathbf{q}), \\]\n   where $M$ is the mass matrix, $C$ includes constraints and dampings, and $G$ is the gravitational force.\n\n2. **Collision Detection**:\n   - This step involves detecting any collisions between objects in the scene. The collision detection algorithm can be formulated as checking for intersections of geometric primitives (e.g., spheres, boxes) defined by their positions and orientations. For two objects with position vectors $\\mathbf{p}_1$ and $\\mathbf{p}_2$, and radii $r_1$ and $r_2$, the collision condition is:\n     \\[ |\\mathbf{p}_1 - \\mathbf{p}_2| < r_1 + r_2. \\]\n\n3. **Integration** (beginIntegration, endIntegration):\n   - This step involves advancing the system's state through numerical integration methods. Common methods include Euler's method, Runge-Kutta schemes, or implicit solvers.\n   - For example, using an explicit Euler method for a single step:\n     \\[ \\dot{\\mathbf{q}}(t + \\Delta t) = \\dot{\\mathbf{q}}(t) + \\ddot{\\mathbf{q}}(t) \\cdot \\Delta t, \\]\n     \\[ \\mathbf{q}(t + \\Delta t) = \\mathbf{q}(t) + \\dot{\\mathbf{q}}(t) \\cdot \\Delta t. \\]\n\n4. **UpdateSimulationContext**:\n   - This step updates the global simulation context, such as advancing the simulation time $t$ by a timestep $\\Delta t$.\n     \\[ t_{new} = t + \\Delta t. \\]\n\n5. **UpdateMapping and Bounding Box Computation**:\n   - Update mappings are used to apply transformations between different representations of objects (e.g., from mechanical to visual representation).\n   - The bounding box computation involves determining the minimum and maximum coordinates that cover all points in a set of geometric entities.\n     \\[ \\text{BoundingBox} = \\left(\\min_x, \\max_x; \\min_y, \\max_y; \\min_z, \\max_z\\right). \\]\n\n### Parallel Processing:\n   - The DefaultAnimationLoop can also enable parallel processing for solving Ordinary Differential Equations (ODEs) through the TaskScheduler. Parallelization is achieved by dividing the computational load across multiple threads or processes, potentially reducing the time required to perform numerical integration.\n\nThe animation loop ensures that all these steps are executed in a coordinated manner, advancing the simulation state accurately and efficiently."
  },
  "summary": {
    "abstract": "The DefaultAnimationLoop drives the simulation loop in SOFA by orchestrating collision detection, physics solving, and context updating steps. It supports parallel ODE solving through a configurable parameter.",
    "sheet": "\n# DefaultAnimationLoop\n\n## Overview\n\nDefaultAnimationLoop is responsible for driving the simulation loop in SOFA simulations. It handles critical steps such as collision detection, solving physics equations, and updating the simulation context. This component inherits from `BaseAnimationLoop`.\n\n## Parameters and Data\n\n- **d_parallelODESolving**: A boolean parameter that controls whether ODEs are solved in parallel (`true`) or sequentially (`false`).\n"
  }
}