States#

A state holds the runtime data of a simulation: positions, velocities, forces, and the solver-specific variables that evolve each step. scene.get_state() returns a SimState, an aggregate snapshot of the whole scene that holds one per-solver state for each active solver:

  • RigidSolverState: link poses, joint positions and velocities.

  • MPMSolverState: particle positions, velocities, deformation gradients.

  • FEMSolverState: node positions, velocities.

  • PBDSolverState: particle positions, velocities.

  • SPHSolverState: particle positions, velocities, densities.

Reading state#

Read state through the entity you added, rather than through the aggregate snapshot. After scene.build(), call the getters directly:

import genesis as gs

gs.init()
scene = gs.Scene()
robot = scene.add_entity(gs.morphs.URDF(file="robot.urdf"))
scene.build()

qpos = robot.get_qpos()                 # ([n_envs,] n_dofs)
qvel = robot.get_qvel()                 # ([n_envs,] n_dofs)
ee_pos = robot.get_link("ee").get_pos()  # ([n_envs,] 3)

The returned tensors follow the batched-optional shape convention: the leading environment dimension is present when the scene is built with multiple environments and absent otherwise. Pass envs_idx to read a subset:

scene.build(n_envs=16)
qpos = robot.get_qpos()                  # (16, n_dofs)
qpos = robot.get_qpos(envs_idx=[0, 5, 10])  # (3, n_dofs)

See Conventions for the full shape and dtype conventions.

Saving and restoring#

scene.get_state() returns a SimState snapshot of the whole scene:

state = scene.get_state()

The scene has no set_state. Restore a snapshot by passing it to scene.reset, which resets the scene to that state and registers it as the new initial state:

scene.reset(state=state)   # restore a saved snapshot
scene.reset()              # reset all environments to the initial state
scene.reset(envs_idx=[0, 1, 2])  # reset only the given environments

Individual solvers and entities expose their own set_state for finer-grained restoration, for example scene.sim.rigid_solver.set_state(...).

Gradient tracking#

When the scene is built for differentiable simulation, state tensors track gradients, so a loss computed from them can be backpropagated:

scene = gs.Scene(sim_options=gs.options.SimOptions(requires_grad=True))
# ... build, step ...
loss = compute_loss(robot.get_qpos())
loss.backward()

See also#