sofa icon indicating copy to clipboard operation
sofa copied to clipboard

New gravity mechanism and design

Open hugtalbot opened this issue 3 years ago • 2 comments

The PR #2988 opens this discussion.

Today

  • gravity is defined though a data in the Nodes (by default gravity="0 9.81 0")
  • this gravity is propagated down from the root node to the child nodes
  • gravity computation is performed by the mass (if any) in the node
  • nowhere appears the gravity as a ForceField (mechanical load) within the node

Typical scene

<Node name="root" gravity="0 -9.81 0" dt="0.01">
  <DefaultAnimationLoop name="animationLoop" solveVelocityConstraintFirst="true" 

  <Node name="Object1">
        <EulerImplicitSolver name="ODE0" rayleighMass="0.1" rayleighStiffness="0.1" />
        <SparseLDLSolver template="CompressedRowSparseMatrixMat3x3d" name="Linear0"  />
        <TetrahedronSetTopologyContainer name="Torus0Topo" position="@/Mesh/stuffing.outputPoints" tetrahedra="@/Mesh/stuffing.outputTetrahedra"/>
        <MechanicalObject name="Torus0State" template="Vec3d" velocity="@/Mesh/TorusVVel.output_position" rest_position="@/Mesh/stuffing.outputPoints" position="@Torus0VXForm.output_position" />
        <TetrahedronSetGeometryAlgorithms name="Torus0Algo" />
        <MeshMatrixMass name="MMass" massDensity="2.0" />
        <TetrahedronFEMForceField name="FEM" youngModulus="50" poissonRatio="0.45" />
  </Node>

  <Node name="Object2" >
        <EulerImplicitSolver />
        <CGLinearSolver iterations="200" tolerance="1e-09" threshold="1e-09"/>
        <MechanicalObject template="Rigid3d" name="myParticle" position="0 0 0    0 0 0 1" showObject="1" />
        <UniformMass name="UMass" totalMass="1" />
        <ConstantForceField totalForce="1 0 0 0 0 0" />
    </Node>
</Node>

Advantages

  • easy to write a scene with a global gravity
  • light nodes (no additional ForceField appearing)

Drawbacks

  • prone to error for beginners not seeing that a gravity (external force) is acting

Proposal

  • gravity can still be defined though a data in the Nodes (but default value changed gravity="0 0 0")
  • using this data gravity generates a warning (not the default/advised way of designing a scene)
  • if this gravity data is not null, mass components automatically create a GravityForceField in the node
  • GravityForceField have a link towards the mass to avoid recomputing the M matrix
  • gravity contribution is added in the matrix system by a ForceField
  • GravityForceField must be in the node to compute the gravity

Typical scene

old scene works and now you also can write:

<Node name="root"  dt="0.01">
  <DefaultAnimationLoop name="animationLoop" solveVelocityConstraintFirst="true" 

  <Node name="Object1">
        <EulerImplicitSolver name="ODE0" rayleighMass="0.1" rayleighStiffness="0.1" />
        <SparseLDLSolver template="CompressedRowSparseMatrixMat3x3d" name="Linear0"  />
        <TetrahedronSetTopologyContainer name="Torus0Topo" position="@/Mesh/stuffing.outputPoints" tetrahedra="@/Mesh/stuffing.outputTetrahedra"/>
        <MechanicalObject name="Torus0State" template="Vec3d" velocity="@/Mesh/TorusVVel.output_position" rest_position="@/Mesh/stuffing.outputPoints" position="@Torus0VXForm.output_position" />
        <TetrahedronSetGeometryAlgorithms name="Torus0Algo" />
        <MeshMatrixMass name="MMass" massDensity="2.0" />
        <TetrahedronFEMForceField name="FEM" youngModulus="50" poissonRatio="0.45" />
        <GravityForceField name="gravity" gravitationalAcceleration="0 -9.81 0" mass="@MMass" />
  </Node>

  <Node name="Object2" >
        <EulerImplicitSolver />
        <CGLinearSolver iterations="200" tolerance="1e-09" threshold="1e-09"/>
        <MechanicalObject template="Rigid3d" name="myParticle" position="0 0 0    0 0 0 1" showObject="1" />
        <UniformMass name="UMass" totalMass="1" />
        <ConstantForceField totalForce="1 0 0 0 0 0" />
        <GravityForceField name="gravity" gravitationalAcceleration="0 -9.81 0" mass="@UMass" />
    </Node>
</Node>

Advantages

  • easy to write a scene with a global gravity
  • explicit application of the gravity as an external force
  • cleans the API (seperate the mass and FF API)

Drawbacks

  • makes the nodes heavier

Questions

  • What do you think about it @sofa-framework/reviewers ?
  • Should the use of slaves (GravityForceField as a Slave of Mass) be considered ? (I do not think so)

hugtalbot avatar Jul 20 '22 10:07 hugtalbot

In order to work as expected the automatic addition of the GravityForceField by the node need to be implemented for the two following events:

  • react when the "gravity" field is changed to add the GravityForceField not only done at parse/init... and if gravity is set back to zero... should we remove the GravityForceFIeld ?
  • have a hook in the addObject(BaseObject*) so that any addition of a Mass Object trigger on a node that had a gravity set ... the function adding the GravityForceField is called.

The underlying logic is complex and looks very hack to me but needed to provide a consistant behavior between two deeply inter-connected component (mass & gravityforcefield). I may be wrong but using a "slave" for the "automatic" use-case would cut that complexity.

damienmarchal avatar Jul 20 '22 11:07 damienmarchal

@damienmarchal regarding the hook in the addObject(BaseObject*) so that any addition of a Mass Object, should it not simply warn the user that no gravity will be applied if no GravityForceField is added ?

hugtalbot avatar Sep 02 '22 09:09 hugtalbot