Skip to main content

phyz_model/
state.rs

1//! Simulation state — mutable per-timestep data.
2
3use phyz_math::{DVec, SpatialTransform};
4
5/// Mutable simulation state.
6#[derive(Debug, Clone)]
7pub struct State {
8    /// Generalized positions (joint angles/displacements).
9    pub q: DVec,
10    /// Generalized velocities.
11    pub v: DVec,
12    /// Control inputs / applied torques.
13    pub ctrl: DVec,
14    /// Simulation time.
15    pub time: f64,
16
17    // Cached quantities (filled by forward kinematics / dynamics)
18    /// Body-to-world transforms for each body.
19    pub body_xform: Vec<SpatialTransform>,
20    /// External generalized forces (e.g., from contacts).
21    pub qfrc_external: DVec,
22}
23
24impl State {
25    /// Create a zero-initialized state for `nq` position DOFs and `nv` velocity DOFs.
26    pub fn new(nq: usize, nv: usize, nbodies: usize) -> Self {
27        Self {
28            q: DVec::zeros(nq),
29            v: DVec::zeros(nv),
30            ctrl: DVec::zeros(nv),
31            time: 0.0,
32            body_xform: vec![SpatialTransform::identity(); nbodies],
33            qfrc_external: DVec::zeros(nv),
34        }
35    }
36
37    /// Compute total kinetic energy given mass matrix.
38    /// KE = 0.5 * v^T * M * v
39    pub fn kinetic_energy(&self, mass_matrix: &phyz_math::DMat) -> f64 {
40        0.5 * self.v.dot(&(mass_matrix * &self.v))
41    }
42}