Skip to content

McKibben UMArm

The McKibbenActuatedUMArm system models the UMArm as a spatial articulated chain composed with a direct-pressure ArticulatedMcKibbenActuator. Body dynamics and actuator geometry have independent immutable parameter objects. Cached robot parameters are kept outside the Python wheel under assets/robot_parameters/ in the source repository; the convenience factory splits the existing cache format internally.

ArticulatedMcKibbenActuator is specifically a spatial articulated transmission: its grouped fixed/moving attachments span two-axis joint pairs and depend on the host's kinematic frames. It is not installed on PCS or GVS rods. Continuum models can use threadlike muscle or equivalent pressure-chamber coordinates; generalizing the full McKibben attachment geometry would require a separate continuum transmission contract.

The cached MuJoCo scene placement is normalized to the SoRoMoX base convention: the root is placed at the origin and the proximal physical segment points along positive x.

Usage

from pathlib import Path

import jax.numpy as jnp

from soromox.systems import McKibbenActuatedUMArm

params_path = Path("assets/robot_parameters/mckibben_umarm/reference_parameters.npz")
robot = McKibbenActuatedUMArm.from_cached_parameters(params_path)

q = jnp.zeros(robot.num_dofs)
p = jnp.zeros(robot.num_actuators)

actuator = robot.actuators[0]
lengths = actuator.effective_lengths(q)
segments = actuator.segments(robot, q)
forces = actuator.axial_forces(q, p)
tau = robot.actuation_force(q, p)

Manual construction keeps body and actuator parameters explicit:

from soromox.actuation import ArticulatedMcKibbenActuator
from soromox.systems import McKibbenActuatedUMArmParams

body_params = McKibbenActuatedUMArmParams.from_cached_npz(params_path)
actuator = ArticulatedMcKibbenActuator.from_cached_npz(params_path)
robot = McKibbenActuatedUMArm(body_params, actuator=actuator)

McKibben actuator coordinates are pressure-normalized volume coordinates,

\[ y_{\mathrm{a},i} = \frac{(B_i^2-\ell_i^2)\ell_i}{4\pi N_i^2}, \]

so pressure is the direct work-conjugate effort. The analytic moment matrix is the transpose of the coordinate Jacobian and retains the cache's group and channel ordering.

For actuator-aware visualization, use UMArmViserRenderer:

UMArm articulated robot and McKibben actuators rendered in Viser

The UMArm renderer displays the articulated mechanism together with actuator-aware McKibben geometry.
from soromox.rendering import UMArmViserRenderer

renderer = UMArmViserRenderer(robot, actuator_color_mode="pressure")
renderer.show(q, actuator_inputs=p)

API Reference

soromox.systems.articulated.mckibben_actuated_umarm

McKibben-actuated UMArm articulated system.

This module implements the UMArm body as a SoRoMoX articulated system composed with :class:soromox.actuation.ArticulatedMcKibbenActuator. The UMArm is a pneumatically driven rigid-soft hybrid arm introduced by Zuo, Han, Li, Jamal, and Bruder in "UMArm: Untethered, Modular, Portable, Soft Pneumatic Arm", arXiv:2505.11476, https://doi.org/10.48550/arXiv.2505.11476.

The body specialization retains UMArm-specific rotor armature and cached-model construction. McKibben geometry, actuator coordinates, moment matrices, axial forces, and rendering geometry live on the installed actuator.

McKibbenActuatedUMArm

McKibbenActuatedUMArm(params: McKibbenActuatedUMArmParams, *, actuator: ArticulatedMcKibbenActuator, passive_elements: PassiveElement | tuple[PassiveElement, ...] | None = (), **kwargs: Any)

Bases: ArticulatedSoftRobot


              flowchart TD
              soromox.systems.articulated.mckibben_actuated_umarm.McKibbenActuatedUMArm[McKibbenActuatedUMArm]
              soromox.systems.articulated.articulated_soft_robot.ArticulatedSoftRobot[ArticulatedSoftRobot]
              soromox.systems.soft_robot.SoftRobot[SoftRobot]
              soromox.systems.dynamical_system.DynamicalSystem[DynamicalSystem]

                              soromox.systems.articulated.articulated_soft_robot.ArticulatedSoftRobot --> soromox.systems.articulated.mckibben_actuated_umarm.McKibbenActuatedUMArm
                                soromox.systems.soft_robot.SoftRobot --> soromox.systems.articulated.articulated_soft_robot.ArticulatedSoftRobot
                                soromox.systems.dynamical_system.DynamicalSystem --> soromox.systems.soft_robot.SoftRobot
                




              click soromox.systems.articulated.mckibben_actuated_umarm.McKibbenActuatedUMArm href "" "soromox.systems.articulated.mckibben_actuated_umarm.McKibbenActuatedUMArm"
              click soromox.systems.articulated.articulated_soft_robot.ArticulatedSoftRobot href "" "soromox.systems.articulated.articulated_soft_robot.ArticulatedSoftRobot"
              click soromox.systems.soft_robot.SoftRobot href "" "soromox.systems.soft_robot.SoftRobot"
              click soromox.systems.dynamical_system.DynamicalSystem href "" "soromox.systems.dynamical_system.DynamicalSystem"
            

Spatial UMArm with rigid links and composable McKibben actuation.

The arm is represented as a 12-DOF serial articulated chain, where each universal joint contributes two one-DOF revolute joints. The required :class:~soromox.actuation.ArticulatedMcKibbenActuator maps pressure inputs to generalized joint torques through work-conjugate volume coordinates. This keeps the UMArm body dynamics separate from the pneumatic transmission while preserving the original analytic model and channel ordering.

References

Zuo, R., Han, D. H., Li, R., Jamal, S., & Bruder, D. (2025). UMArm: Untethered, Modular, Portable, Soft Pneumatic Arm. arXiv:2505.11476. https://doi.org/10.48550/arXiv.2505.11476

Attributes:

Name Type Description
params McKibbenActuatedUMArmParams

Typed articulated-body and armature parameters.

joint_armature Array

Per-joint rotor armature added to dense inertia and the articulated-body recursion, shape (num_dofs,).

actuators tuple[Actuator, ...]

One-element tuple containing the installed McKibben actuator. Its parameters own moving/fixed attachment points, effective-length offsets, thread lengths, fiber turns, and joint-pair indices.

num_segments int

Number of physical UMArm segments.

num_mckibben_groups int

Number of universal-joint actuator groups.

Initialize a UMArm body with one McKibben actuator.

Parameters:

Name Type Description Default
params McKibbenActuatedUMArmParams

UMArm body dynamics and joint-armature parameters.

required
actuator ArticulatedMcKibbenActuator

McKibben pressure actuator installed on the body.

required
passive_elements PassiveElement | tuple[PassiveElement, ...] | None

Optional independent passive mechanics.

()
**kwargs Any

Additional arguments forwarded to :class:ArticulatedSoftRobot.

{}

Raises:

Type Description
TypeError

If the body or actuator parameter types are invalid.

tangent_eps property
tangent_eps: Array

Epsilon value for Lie algebra tangent computations.

Returns:

Name Type Description
Array Array

Epsilon value for Lie algebra tangent computations.

actuator_input_metadata property
actuator_input_metadata: tuple[ActuatorMetadata, ...]

Metadata groups in the same order used to concatenate controls.

length property
length: Array

Total backbone length of the robot (scalar).

segment_length property
segment_length: Array

Per-link centerline lengths.

is_planar property
is_planar: bool

Return False because this is a spatial SE(3) system.

supports_articulated_tendon_routing property
supports_articulated_tendon_routing: bool

The generalized coordinates form a serial articulated joint chain.

base_transform property
base_transform: Array

Return the homogeneous transform represented by base_pose.

Planar robots consume [theta, x, y] and return an SE(2) matrix with shape (3, 3). Spatial robots consume [qw, qx, qy, qz, x, y, z] and return an SE(3) matrix with shape (4, 4). Spatial quaternions are scalar-first Hamilton quaternions.

L_cum property
L_cum: Array

Cumulative link lengths [0, L_0, ..., sum_i L_i].

total_length property
total_length: Array

Alias for length used by other articulated systems.

from_cached_parameters classmethod
from_cached_parameters(path: str | Path, **kwargs: Any) -> McKibbenActuatedUMArm

Build the complete UMArm from an existing cached parameter file.

The cache schema remains unchanged. Body and actuator fields are split into their respective immutable parameter objects during construction.

Parameters:

Name Type Description Default
path str | Path

Path to a UMArm .npz parameter file.

required
**kwargs Any

Additional arguments forwarded to the constructor.

{}

Returns:

Type Description
McKibbenActuatedUMArm

A UMArm with the cached body and McKibben actuator installed.

inertia_matrix
inertia_matrix(q: Array) -> Array

Return dense generalized inertia including rotor armature.

Parameters:

Name Type Description Default
q Array

Joint coordinates with shape (num_dofs,).

required

Returns:

Type Description
Array

Symmetric inertia matrix with shape (num_dofs, num_dofs).

with_params

Replace body and armature parameters while preserving the actuator.

forward_dynamics
forward_dynamics(t: Array, y: Array, actuation_args: tuple | None = None) -> Array

Compute state-space forward dynamics.

Parameters:

Name Type Description Default
t Array

Current time, shape (). The model is autonomous, so this value is unused.

required
y Array

State vector [q, qd], shape (2 * num_links,).

required
actuation_args tuple | None

Optional actuation tuple: - None: zero actuation and zero external force. - (u,): joint inputs only. - (u, tau_ext): joint inputs and external generalized forces.

None

Returns:

Type Description
Array

State derivative [qd, qdd], shape (2 * num_links,).

Raises:

Type Description
ValueError

If actuation_args has an unsupported length.

rollout_to
rollout_to(initial_state: SystemState, u: Array | None = None, tau_ext: Array | None = None, environment_model: Callable[[SystemState], tuple[Array | None, Any | None]] | None = None, t1: float | Array = 10.0, solver_dt: float | Array = 0.0001, save_dt: float | Array | None = 0.01, save_ts: Array | None = None, solver: AbstractSolver | None = None, stepsize_controller: AbstractStepSizeController | None = ConstantStepSize(), max_steps: int | None = None) -> SystemState

Roll out the system dynamics in open loop using Diffrax.

Parameters:

Name Type Description Default
initial_state SystemState

Dataclass holding the initial time, system state vector (y), optional actuation (u), and optional control state.

required
u Array | None

Constant actuation to apply throughout the rollout. If not provided, falls back to initial_state.u, then zeros.

None
tau_ext Array | None

External forces/torques applied to the system (broadcast as constant).

None
environment_model Callable[[SystemState], tuple[Array | None, Any | None]] | None

Optional callable that accepts a SystemState and returns (tau_environment, environment_state_dot). The returned generalized torques are added to tau_ext during integration.

None
t1 float | Array

Final time of the simulation, included in the saved trajectory.

10.0
solver_dt float | Array

Time step for the solver.

0.0001
save_dt float | Array | None

Time interval at which to save the solution when save_ts is not provided.

0.01
save_ts Array | None

Explicit time points to be saved in the output. Must be within [initial_state.t, t1]. Falls back to save_dt if None.

None
solver AbstractSolver | None

Solver to use for the ODE integration.

None
stepsize_controller AbstractStepSizeController | None

Stepsize controller for the solver.

ConstantStepSize()
max_steps int | None

Maximum number of steps for the solver.

None

Returns:

Type Description
SystemState

SystemState PyTree containing time samples, system state trajectory,

SystemState

actuation at each saved step, (optionally) the control state

SystemState

trajectory, and (optionally) the environment state trajectory if

SystemState

initial_state.environment_state was provided. Each leaf has a

SystemState

leading time dimension aligned with save_ts.

rollout_closed_loop_to
rollout_closed_loop_to(initial_state: SystemState, controller: Callable[[SystemState], tuple[Array, Any | None]], tau_ext: Array | None = None, environment_model: Callable[[SystemState], tuple[Array | None, Any | None]] | None = None, t1: float | Array = 10.0, solver_dt: float | Array = 0.0001, save_dt: float | Array = 0.01, save_ts: Array | None = None, solver: AbstractSolver | None = None, stepsize_controller: AbstractStepSizeController | None = ConstantStepSize(), max_steps: int | None = None) -> SystemState

Roll out the system dynamics in closed loop using Diffrax.

The provided controller is queried at every integration step with the current system state (and optional control_state). Its actuation output is added to any feed-forward actuation contained in initial_state.u.

Parameters:

Name Type Description Default
initial_state SystemState

Dataclass holding the initial time, system state vector (y), optional actuation (u), and optional control state.

required
controller Callable[[SystemState], tuple[Array, Any | None]]

Callable that accepts a SystemState and returns a tuple (u_control, control_state_dot). u_control is added to the base actuation from the initial state.

required
tau_ext Array | None

External forces/torques applied to the system (broadcast as constant).

None
environment_model Callable[[SystemState], tuple[Array | None, Any | None]] | None

Optional callable that accepts a SystemState and returns (tau_environment, environment_state_dot). The returned generalized torques are added to tau_ext during integration.

None
t1 float | Array

Final time of the simulation, included in the saved trajectory.

10.0
solver_dt float | Array

Time step for the solver.

0.0001
save_dt float | Array

Time interval at which to save the solution when save_ts is not provided.

0.01
save_ts Array | None

Explicit time points to be saved in the output. Must be within [initial_state.t, t1]. Falls back to save_dt if None.

None
solver AbstractSolver | None

Solver to use for the ODE integration.

None
stepsize_controller AbstractStepSizeController | None

Stepsize controller for the solver.

ConstantStepSize()
max_steps int | None

Maximum number of steps for the solver.

None

Returns:

Type Description
SystemState

SystemState PyTree containing time samples, system state trajectory,

SystemState

actuation at each saved step, controller state trajectory, and

SystemState

(optionally) the environment state trajectory if

SystemState

initial_state.environment_state was provided. Each leaf has a

SystemState

leading time dimension aligned with save_ts.

rollout_discrete_closed_loop_to
rollout_discrete_closed_loop_to(initial_state: SystemState, controller: Callable[[SystemState], tuple[Array, Any | None]], tau_ext: Array | None = None, environment_model: Callable[[SystemState], tuple[Array | None, Any | None]] | None = None, duration: float = 10.0, solver_dt: float | Array = 0.0001, control_dt: float = 0.01, save_dt: float = 0.01, solver: AbstractSolver | None = None, stepsize_controller: AbstractStepSizeController | None = ConstantStepSize(), max_steps: int | None = None) -> SystemState

Roll out the system in discrete-time closed loop.

The controller is evaluated every control_dt seconds. Between control evaluations the actuation is held constant and the system is integrated with Diffrax (equivalent to repeatedly calling rollout_to over each control interval).

The controller signature mirrors rollout_closed_loop_to. If it returns a control_state_dot and initial_state.control_state is provided, the control state is advanced with a forward-Euler step over the control period; otherwise the control state is held constant between controller calls.

The rollout uses a regular time grid. For static tracing/compilation the following constraints are enforced: - duration is an integer multiple of control_dt. - control_dt is an integer multiple of save_dt.

Parameters:

Name Type Description Default
initial_state SystemState

initial time/state (and optional feedforward actuation/control state).

required
controller Callable[[SystemState], tuple[Array, Any | None]]

callable returning (u_control, control_state_dot).

required
tau_ext Array | None

constant external wrench/force applied during the rollout.

None
environment_model Callable[[SystemState], tuple[Array | None, Any | None]] | None

Optional callable returning (tau_environment, environment_state_dot). The returned generalized torques are added to tau_ext during integration.

None
duration float

simulation duration in seconds.

10.0
solver_dt float | Array

initial step size for the solver.

0.0001
control_dt float

sampling period for the controller. Must be positive.

0.01
save_dt float

save interval. Must be positive and evenly divide control_dt.

0.01
solver AbstractSolver | None

Diffrax solver.

None
stepsize_controller AbstractStepSizeController | None

Diffrax stepsize controller.

ConstantStepSize()
max_steps int | None

maximum solver steps.

None

Returns:

Type Description
SystemState

SystemState PyTree containing time samples, system state trajectory,

SystemState

actuation at each saved step, controller state trajectory, and

SystemState

(optionally) the environment state trajectory if

SystemState

initial_state.environment_state was provided. Each leaf has a

SystemState

leading time dimension aligned with the regular save grid.

precompute
precompute() -> None

Optional hook for refreshing state-independent cached quantities.

Subclasses with cached mass, stiffness, damping, basis, or quadrature data can override this method and call it during initialization. Models without such caches can inherit this no-op implementation.

with_actuator_params
with_actuator_params(index: int, params) -> SoftRobot

Return a robot with one actuator's complete parameter object replaced.

update_actuator_params
update_actuator_params(index: int, **updates) -> SoftRobot

Return a robot with selected fields of one actuator's params replaced.

with_passive_element_params
with_passive_element_params(index: int, params) -> SoftRobot

Return a robot with one passive element's complete params replaced.

update_passive_element_params
update_passive_element_params(index: int, **updates) -> SoftRobot

Return a robot with selected passive-element parameter fields replaced.

cross_section_geometry
cross_section_geometry(q: Array, s: Array) -> tuple[Array, Array]

Return circular cross-section metadata for visualization.

forward_kinematics
forward_kinematics(q: Array, s: Array) -> Array

Compute the forward kinematics at a point s along the robot.

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required
s Array

Position parameter along the robot structure. The meaning depends on the specific robot type: - For continuum robots (PCS, PlanarPCS): arc-length in [0, L_total] - For articulated robots (Pendulum): can be link index or fraction

required

Returns:

Name Type Description
chi Array

Pose at point s. The shape and meaning depend on the robot type: - For 3D robots (PCS): SE(3) transformation matrix, shape (4, 4) - For planar robots (PlanarPCS, Pendulum): [theta, x, y], shape (3,)

forward_kinematics_tips
forward_kinematics_tips(q: Array) -> Array

Compute SE(3) frames at all link tips.

Parameters:

Name Type Description Default
q Array

Joint coordinates, shape (num_links,).

required

Returns:

Type Description
Array

Tip frames, shape (num_links, 4, 4).

forward_kinematics_batched
forward_kinematics_batched(q: Array, s_ps: Array) -> Array

Compute the forward kinematics at multiple points along the robot.

Default implementation uses vmap over forward_kinematics. Subclasses may override this for more efficient batch computation.

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required
s_ps Array

Array of position parameters, shape (N,).

required

Returns:

Name Type Description
chi_ps Array

Poses at all points, shape depends on robot type.

forward_kinematics_arc_length_derivative
forward_kinematics_arc_length_derivative(q: Array, s: Array) -> Array

Compute the arc-length derivative of the forward kinematics at s.

The returned tangent has the same shape and representation as forward_kinematics(q, s).

forward_kinematics_and_arc_length_derivative
forward_kinematics_and_arc_length_derivative(q: Array, s: Array) -> tuple[Array, Array]

Compute forward kinematics and its arc-length derivative at s.

Subclasses can override the protected hook to share intermediate kinematic quantities between the primal pose and d pose / ds.

jacobian
jacobian(q: Array, s: Array) -> Array

Compute the Jacobian of the forward kinematics at a point s along the robot.

The Jacobian maps configuration space velocities to operational space (Cartesian/task space) velocities at point s.

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required
s Array

Position parameter along the robot structure.

required

Returns:

Name Type Description
J Array

Jacobian matrix of shape (n_pose_dim, num_dofs), where n_pose_dim depends on the robot type: - For 3D robots (PCS): 6 (angular velocity + linear velocity) - For planar robots (PlanarPCS, Pendulum): 3 (omega_z, v_x, v_y)

jacobian_tips
jacobian_tips(q: Array) -> Array

Compute spatial Jacobians at all link tips.

Parameters:

Name Type Description Default
q Array

Joint coordinates, shape (num_links,).

required

Returns:

Type Description
Array

Tip Jacobians, shape (num_links, 6, num_links).

jacobian_batched
jacobian_batched(q: Array, s_ps: Array) -> Array

Compute the Jacobian at multiple points along the robot.

Default implementation uses vmap over jacobian. Subclasses may override this for more efficient batch computation.

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required
s_ps Array

Array of position parameters, shape (N,).

required

Returns:

Name Type Description
J_ps Array

Jacobians at all points, shape (N, n_pose_dim, num_dofs).

jacobian_arc_length_derivative
jacobian_arc_length_derivative(q: Array, s: Array) -> Array

Compute the arc-length derivative of the Jacobian at s.

The returned derivative has the same shape and frame convention as jacobian(q, s).

jacobian_and_arc_length_derivative
jacobian_and_arc_length_derivative(q: Array, s: Array) -> tuple[Array, Array]

Compute the Jacobian and its arc-length derivative at s.

Returns:

Name Type Description
J Array

Jacobian matrix of shape (n_pose_dim, num_dofs).

Js Array

Arc-length derivative of the Jacobian with the same shape as J.

jacobian_and_time_derivative
jacobian_and_time_derivative(q: Array, qd: Array, s: Array) -> tuple[Array, Array]

Compute the Jacobian and its time derivative at a point s along the robot.

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required
qd Array

Generalized velocities of shape (num_dofs,).

required
s Array

Position parameter along the robot structure.

required

Returns:

Name Type Description
J Array

Jacobian matrix of shape (n_pose_dim, num_dofs).

Jd Array

Time derivative of the Jacobian, shape (n_pose_dim, num_dofs).

jacobian_and_time_derivative_batched
jacobian_and_time_derivative_batched(q: Array, qd: Array, s_ps: Array) -> tuple[Array, Array]

Compute the Jacobian and its derivative at multiple points along the robot.

Default implementation uses vmap over jacobian_and_time_derivative. Subclasses may override this for more efficient batch computation.

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required
qd Array

Generalized velocities of shape (num_dofs,).

required
s_ps Array

Array of position parameters, shape (N,).

required

Returns:

Name Type Description
J_ps Array

Jacobians at all points, shape (N, n_pose_dim, num_dofs).

Jd_ps Array

Jacobian time derivatives at all points, shape (N, n_pose_dim, num_dofs).

jacobian_bodyframe
jacobian_bodyframe(q: Array, s: Array) -> Array

Compute the body-frame Jacobian at a point s along the robot.

The default implementation converts the public inertial-frame Jacobian to the local pose frame using the rotation-only convention used by the dynamics integrands.

jacobian_bodyframe_batched
jacobian_bodyframe_batched(q: Array, s_ps: Array) -> Array

Compute body-frame Jacobians at multiple points along the robot.

jacobian_and_time_derivative_bodyframe
jacobian_and_time_derivative_bodyframe(q: Array, qd: Array, s: Array) -> tuple[Array, Array]

Compute a body-frame Jacobian and its time derivative at s.

The default differentiates jacobian_bodyframe with respect to the generalized coordinates.

jacobian_and_time_derivative_bodyframe_batched
jacobian_and_time_derivative_bodyframe_batched(q: Array, qd: Array, s_ps: Array) -> tuple[Array, Array]

Compute body-frame Jacobians and time derivatives at many points.

integration_kinematics
integration_kinematics(q: Array, qd: Array) -> tuple[Array, Array, Array]

Evaluate poses, body-frame Jacobians, and Jacobian derivatives at interior integration nodes.

The default implementation is intentionally unfused. It samples integration_points[..., 1:-1] for every segment, maps normalized nodes to arclength, and calls the public kinematics/Jacobian APIs. Subclasses can override this method with a fused implementation.

Returns:

Type Description
Array

Tuple (g_ps, J_ps, Jd_ps) with leading axes

Array

(num_segments, num_inner_points).

coriolis_matrix
coriolis_matrix(q: Array, qd: Array) -> Array

Compute a Christoffel-consistent dense Coriolis matrix.

Parameters:

Name Type Description Default
q Array

Joint coordinates, shape (num_links,).

required
qd Array

Joint velocities, shape (num_links,).

required

Returns:

Type Description
Array

Coriolis matrix, shape (num_links, num_links).

damping_matrix
damping_matrix(q: Array) -> Array

Return the viscous joint damping matrix.

Parameters:

Name Type Description Default
q Array

Joint coordinates, shape (num_links,).

required

Returns:

Type Description
Array

Damping matrix, shape (num_links, num_links).

stiffness_matrix
stiffness_matrix() -> Array

Return the linear joint stiffness matrix.

Returns:

Type Description
Array

Stiffness matrix, shape (num_links, num_links).

elastic_force
elastic_force(q: Array) -> Array

Compute generalized elastic joint forces.

Parameters:

Name Type Description Default
q Array

Joint coordinates, shape (num_links,).

required

Returns:

Type Description
Array

Elastic force vector, shape (num_links,).

gravitational_force
gravitational_force(q: Array) -> Array

Compute the gravitational force.

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required

Returns:

Name Type Description
G Array

Gravitational force of shape (num_dofs,).

potential_force
potential_force(q: Array) -> Array

Compute the total conservative generalized force.

This is the sum of gravitational and elastic forces.

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required

Returns:

Name Type Description
tau_pot Array

Potential force of shape (num_dofs,).

actuator_coordinates
actuator_coordinates(q: Array) -> Array

Return all work-conjugate actuator coordinates in control order.

actuator_velocities
actuator_velocities(q: Array, qd: Array) -> Array

Return all actuator-coordinate velocities in control order.

actuation_matrix
actuation_matrix(q: Array) -> Array

Return the concatenated transmission moment matrix.

actuator_efforts
actuator_efforts(q: Array, u: Array, qd: Array | None = None) -> Array

Map ordered user controls to ordered work-conjugate efforts.

actuation_force
actuation_force(q: Array, u: Array, qd: Array | None = None) -> Array

Return generalized actuation force A(q) @ effort.

passive_elastic_force
passive_elastic_force(q: Array) -> Array

Return the sum of installed passive conservative forces.

passive_damping_matrix
passive_damping_matrix(q: Array) -> Array

Return the sum of installed passive damping matrices.

passive_elastic_energy
passive_elastic_energy(q: Array) -> Array

Return the sum of installed passive elastic energies.

actuator_visual_layers
actuator_visual_layers(q: Array, s_points: Array, *, actuator_inputs: Array | None = None)

Return semantic active and passive actuator geometry for renderers.

kinetic_energy
kinetic_energy(q: Array, qd: Array) -> Array

Compute the kinetic energy of the system.

Default implementation: T = 0.5 * qd^T * M(q) * qd

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required
qd Array

Generalized velocities of shape (num_dofs,).

required

Returns:

Name Type Description
T Array

Kinetic energy (scalar).

gravitational_energy
gravitational_energy(q: Array) -> Array

Compute the gravitational potential energy of the system.

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required

Returns:

Name Type Description
U_g Array

Gravitational potential energy (scalar).

elastic_energy
elastic_energy(q: Array) -> Array

Compute the elastic potential energy stored in the system.

Default implementation: U_el = 0.5 * q^T * K * q

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required

Returns:

Name Type Description
U_el Array

Elastic potential energy (scalar).

potential_energy
potential_energy(q: Array) -> Array

Compute the total potential energy of the system.

This is the sum of gravitational and elastic energy.

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required

Returns:

Name Type Description
U Array

Total potential energy (scalar).

total_energy
total_energy(q: Array, qd: Array) -> Array

Compute the total energy of the system.

This is the sum of kinetic and potential energy.

Parameters:

Name Type Description Default
q Array

Generalized coordinates of shape (num_dofs,).

required
qd Array

Generalized velocities of shape (num_dofs,).

required

Returns:

Name Type Description
E Array

Total energy (scalar).

dynamics_terms
dynamics_terms(q: Array, qd: Array) -> tuple[Array, Array, Array]

Return forward-dynamics terms (M, Cqd, G).

Cqd is the convective force vector C(q, qd) @ qd. The default implementation is intentionally unfused and calls the public matrix and force APIs separately. Overrides must keep M and Cqd energy-consistent with inertia_matrix and coriolis_matrix.

classify_segment
classify_segment(s: Array) -> tuple[Array, Array]

Determine which link contains an arc-length position.

Parameters:

Name Type Description Default
s Array

Arc-length position along the serial chain.

required

Returns:

Type Description
Array

Tuple (link_idx, s_local) with the zero-based link index and local

Array

arc length within that link.

forward_kinematics_joints
forward_kinematics_joints(q: Array) -> Array

Compute SE(3) frames at all joint origins.

Parameters:

Name Type Description Default
q Array

Joint coordinates, shape (num_links,).

required

Returns:

Type Description
Array

Joint frames, shape (num_links, 4, 4).

forward_kinematics_coms
forward_kinematics_coms(q: Array) -> Array

Compute SE(3) frames at all link centers of mass.

Parameters:

Name Type Description Default
q Array

Joint coordinates, shape (num_links,).

required

Returns:

Type Description
Array

COM frames, shape (num_links, 4, 4).

jacobian_coms
jacobian_coms(q: Array) -> Array

Compute spatial Jacobians at all link COMs.

Parameters:

Name Type Description Default
q Array

Joint coordinates, shape (num_links,).

required

Returns:

Type Description
Array

COM Jacobians, shape (num_links, 6, num_links).

jacobian_joints
jacobian_joints(q: Array) -> Array

Compute spatial Jacobians at all joint origins.

Parameters:

Name Type Description Default
q Array

Joint coordinates, shape (num_links,).

required

Returns:

Type Description
Array

Joint-origin Jacobians, shape (num_links, 6, num_links).

jacobian_and_time_derivatives_tips
jacobian_and_time_derivatives_tips(q: Array, qd: Array) -> tuple[Array, Array]

Compute tip Jacobians and their time derivatives.

Parameters:

Name Type Description Default
q Array

Joint coordinates, shape (num_links,).

required
qd Array

Joint velocities, shape (num_links,).

required

Returns:

Type Description
tuple[Array, Array]

Tuple (J, Jd), both with shape (num_links, 6, num_links).

update_params
update_params(**updates: Array) -> ArticulatedSoftRobot

Return an updated copy with selected typed parameter fields replaced.

soromox.rendering.umarm.viser_renderer

Viser renderer specialized for the McKibben-actuated UMArm.

UMArmViserRenderer

UMArmViserRenderer(*args, actuator_color_mode: Literal['uniform', 'pressure', 'force'] = 'uniform', actuator_line_width: float | None = None, actuator_radius: float = 0.003, rod_core_radius_scale: float = 0.45, linkage_radius: float = 0.007, end_effector_radius: float = 0.01, end_effector_sphere_radius: float = 0.019, ujoint_disk_thickness: float = 0.01, actuator_disk_thickness: float = 0.01, **kwargs)

Bases: ViserRenderer


              flowchart TD
              soromox.rendering.umarm.viser_renderer.UMArmViserRenderer[UMArmViserRenderer]
              soromox.rendering.viser_renderer.ViserRenderer[ViserRenderer]
              soromox.rendering.base.BaseSoftRobotRenderer[BaseSoftRobotRenderer]

                              soromox.rendering.viser_renderer.ViserRenderer --> soromox.rendering.umarm.viser_renderer.UMArmViserRenderer
                                soromox.rendering.base.BaseSoftRobotRenderer --> soromox.rendering.viser_renderer.ViserRenderer
                



              click soromox.rendering.umarm.viser_renderer.UMArmViserRenderer href "" "soromox.rendering.umarm.viser_renderer.UMArmViserRenderer"
              click soromox.rendering.viser_renderer.ViserRenderer href "" "soromox.rendering.viser_renderer.ViserRenderer"
              click soromox.rendering.base.BaseSoftRobotRenderer href "" "soromox.rendering.base.BaseSoftRobotRenderer"
            

Viser renderer that adds McKibben actuator segments to the UMArm backbone.

is_planar property
is_planar: bool

Return True for planar (SE(2)) robots.

is_3d property
is_3d: bool

Always True for Viser (3D only).

server property
server: ViserServer

Access underlying Viser server.

url property
url: str

URL to access the visualization.

show
show(q: Array, *, pressures: Array | None = None, **kwargs) -> None

Display a UMArm frame, optionally coloring actuators by pressure or force.

render_sequence
render_sequence(ts: Array, q_ts: Array, *, pressures: Array | None = None, actuator_color_mode: Literal['uniform', 'pressure', 'force'] | None = None, **kwargs) -> None

Render a UMArm trajectory, including McKibben actuator segments.

start_live_mode
start_live_mode(callback: Callable[[float], ndarray] | None = None, dt: float = 0.033, pressure_callback: Callable[[float], ndarray] | None = None) -> UMArmLiveModeController

Start live visualization mode with UMArm-specific rigid geometry.

Parameters:

Name Type Description Default
callback Callable[[float], ndarray] | None

Optional state provider function time -> q. The callback may also return (q, pressures) to update actuator colors together with the configuration.

None
dt float

Callback-mode update period in seconds.

0.033
pressure_callback Callable[[float], ndarray] | None

Optional pressure provider time -> pressures. Ignored when callback returns (q, pressures).

None

Returns:

Type Description
UMArmLiveModeController

Controller for streaming UMArm states into the Viser scene.

compute_backbone_curve
compute_backbone_curve(q: Array) -> Array

Compute backbone points from configuration.

Parameters:

Name Type Description Default
q Array

Robot configuration array

required

Returns:

Type Description
Array

Array of shape (num_points, 3) for 3D or (num_points, 2) for 2D

compute_backbone_poses
compute_backbone_poses(q: Array) -> Array

Compute full FK poses at the configured backbone sample points.

compute_actuator_visual_layers
compute_actuator_visual_layers(q: Array, *, actuator_inputs: Array | None = None) -> tuple[ActuatorVisualLayer, ...]

Compute renderer-facing actuator visual layers for one robot.

compute_actuator_visual_layers_batched
compute_actuator_visual_layers_batched(q_batch: Array, base_offsets: Array, *, actuator_inputs: Array | ndarray | None = None) -> tuple[BatchedActuatorVisualLayer, ...]

Compute actuator visual layers for multiple robots with base offsets.

compute_actuator_visual_layers_trajectory
compute_actuator_visual_layers_trajectory(q_ts: Array, base_offsets: Array, *, actuator_inputs: Array | ndarray | None = None) -> tuple[TrajectoryActuatorVisualLayer, ...]

Compute actuator visual layers for (N, T, DOF) trajectories.

render_frame
render_frame(q: Array, *, base_offsets: Array | None = None, color_config: RendererColorConfig | None = None, camera_config: CameraConfig | None = None, render_actuators: bool = True, actuator_inputs: Array | None = None, static_spheres_positions: Array | None = None, static_spheres_radii: Array | None = None, static_spheres_colors: Array | None = None, capture_client_idx: int = 0) -> ndarray

Render single configuration and capture as image.

Note: Requires at least one connected client to capture.

Parameters:

Name Type Description Default
q Array

Robot configuration (DOF,) or batched (N, DOF)

required
base_offsets Array | None

Base position offsets (N, 3)

None
color_config RendererColorConfig | None

Shared renderer color configuration

None
camera_config CameraConfig | None

Camera configuration (fov, position, look_at, etc.)

None
render_actuators bool

If True, render actuator visual layers.

True
actuator_inputs Array | None

Optional actuator inputs for scalar-colored layers.

None
static_spheres_positions Array | None

Static sphere positions (M, 3)

None
static_spheres_radii Array | None

Static sphere radii (M,)

None
static_spheres_colors Array | None

Static sphere colors (M, 3)

None
capture_client_idx int

Index of client to capture from

0

Returns:

Type Description
ndarray

RGB image as numpy array (height, width, 3), dtype uint8

resolve_backbone_colors
resolve_backbone_colors(num_robots: int, *, color_config: RendererColorConfig | None = None, cache: bool = True) -> ResolvedBackboneColors

Resolve backbone colors using the shared config hierarchy.

get_color_legend
get_color_legend(*, num_robots: int = 1, color_config: RendererColorConfig | None = None) -> ColorLegend

Return a lightweight color legend for the current configuration.

clear_color_cache
clear_color_cache() -> None

Clear cached color resolutions.

compute_backbone_curves_batched
compute_backbone_curves_batched(q_batch: Array, base_offsets: Array) -> Array

Compute backbone curves for multiple robots with base offsets.

Uses forward_kinematics_batched if available (optimized), otherwise falls back to jax.vmap over compute_backbone_curve.

Parameters:

Name Type Description Default
q_batch Array

Configurations of shape (N, DOF) - batch-first

required
base_offsets Array

Base position offsets of shape (N, 2) or (N, 3)

required

Returns:

Type Description
Array

Array of shape (N, num_points, dim) - batch-first

compute_backbone_curves_and_frames_batched
compute_backbone_curves_and_frames_batched(q_batch: Array, base_offsets: Array) -> tuple[Array, Array]

Compute 3D backbone positions and material frames for multiple robots.

The frame columns are the local material-frame axes in world coordinates. Positional base offsets translate the curves without rotating the frames.

start
start() -> None

Start the Viser server.

stop
stop() -> None

Stop the Viser server.

add_gui_plotly
add_gui_plotly(name: str, figure: Figure, aspect: float = 1.0) -> Any

Add a plotly figure to the GUI.

Parameters:

Name Type Description Default
name str

Unique name for the plot

required
figure Figure

Plotly figure object

required
aspect float

Aspect ratio (width/height)

1.0

Returns:

Type Description
Any

Viser plotly handle

create_configuration_plot
create_configuration_plot(ts: Array | ndarray, q_ts: Array | ndarray, robot_name: str = 'Robot') -> Figure

Create a plotly figure showing configurations over time.

Parameters:

Name Type Description Default
ts Array | ndarray

Time array (T,)

required
q_ts Array | ndarray

Configuration array (T, DOF)

required
robot_name str

Name for the plot title

'Robot'

Returns:

Type Description
Figure

Plotly figure

create_actuator_position_plot
create_actuator_position_plot(ts: Array | ndarray, q_ts: Array | ndarray, robot: SoftRobot, robot_name: str = 'Robot') -> Figure

Create a plotly figure showing actuator coordinates over time.

Parameters:

Name Type Description Default
ts Array | ndarray

Time array (T,)

required
q_ts Array | ndarray

Configuration array (T, DOF)

required
robot SoftRobot

Robot instance with an actuator_coordinates method

required
robot_name str

Name for the plot title

'Robot'

Returns:

Type Description
Figure

Plotly figure

add_dynamic_sphere
add_dynamic_sphere(name: str, position: ndarray, radius: float, color: tuple[float, float, float] = (0.2, 0.2, 0.8), opacity: float = 1.0) -> Any

Add a dynamic sphere to the scene.

Parameters:

Name Type Description Default
name str

Unique identifier for the sphere

required
position ndarray

Initial position (3,)

required
radius float

Sphere radius

required
color tuple[float, float, float]

RGB color (0-1)

(0.2, 0.2, 0.8)
opacity float

Opacity (0-1)

1.0

Returns:

Type Description
Any

Viser sphere handle

update_dynamic_sphere
update_dynamic_sphere(name: str, position: ndarray | None = None, radius: float | None = None, color: tuple[float, float, float] | None = None) -> None

Update properties of a dynamic sphere.

Parameters:

Name Type Description Default
name str

Sphere identifier

required
position ndarray | None

New position (3,)

None
radius float | None

New radius

None
color tuple[float, float, float] | None

New RGB color

None
remove_dynamic_sphere
remove_dynamic_sphere(name: str) -> None

Remove a dynamic sphere from the scene.

Parameters:

Name Type Description Default
name str

Sphere identifier

required
add_custom_primitive
add_custom_primitive(name: str, primitive_type: Literal['sphere', 'box', 'cylinder', 'mesh'], **kwargs: Any) -> Any

Add a custom primitive to the scene for extensibility.

Parameters:

Name Type Description Default
name str

Unique identifier

required
primitive_type Literal['sphere', 'box', 'cylinder', 'mesh']

Type of primitive

required
**kwargs Any

Primitive-specific parameters

{}

Returns:

Type Description
Any

Viser scene handle

render_to_video
render_to_video(ts: Array, q_ts: Array, output_path: str, *, width: int | None = None, height: int | None = None, fps: float | None = None, video_config: VideoEncodingConfig | None = None, camera_position: tuple[float, float, float] | None = None, camera_target: tuple[float, float, float] | None = None, **render_kwargs: Any) -> None

Render sequence directly to video file.

This method renders each frame and writes to video using FFmpeg. Requires at least one connected client for capture.

Parameters:

Name Type Description Default
ts Array

Time stamps

required
q_ts Array

Configurations

required
output_path str

Output video path (.mp4, .mov)

required
width int | None

Frame width (default: self.width)

None
height int | None

Frame height (default: self.height)

None
fps float | None

Output FPS (if None, derived from ts)

None
video_config VideoEncodingConfig | None

FFmpeg settings

None
camera_position tuple[float, float, float] | None

Fixed camera position

None
camera_target tuple[float, float, float] | None

Camera look-at target

None
**render_kwargs Any

Additional render_sequence arguments

{}

UMArmLiveModeController

UMArmLiveModeController(renderer: UMArmViserRenderer, callback: Callable[[float], ndarray] | None = None, dt: float = 0.033, pressure_callback: Callable[[float], ndarray] | None = None)

Bases: LiveModeController


              flowchart TD
              soromox.rendering.umarm.viser_renderer.UMArmLiveModeController[UMArmLiveModeController]
              soromox.rendering.viser_renderer.LiveModeController[LiveModeController]

                              soromox.rendering.viser_renderer.LiveModeController --> soromox.rendering.umarm.viser_renderer.UMArmLiveModeController
                


              click soromox.rendering.umarm.viser_renderer.UMArmLiveModeController href "" "soromox.rendering.umarm.viser_renderer.UMArmLiveModeController"
              click soromox.rendering.viser_renderer.LiveModeController href "" "soromox.rendering.viser_renderer.LiveModeController"
            

Live-mode controller that updates UMArm rigid geometry from q.

push_state_with_pressures
push_state_with_pressures(q: ndarray, pressures: ndarray) -> None

Push a live UMArm state and actuator pressures.

start
start() -> None

Start the live mode.

stop
stop() -> None

Stop the live mode.

push_state
push_state(q: ndarray) -> None

Push a new configuration to the renderer.

Parameters:

Name Type Description Default
q ndarray

Configuration array (DOF,) or batched (N, DOF)

required
push_state_with_extras
push_state_with_extras(q: ndarray, dynamic_spheres: dict[str, ndarray] | None = None) -> None

Push state with auxiliary geometry updates.

Parameters:

Name Type Description Default
q ndarray

Configuration array

required
dynamic_spheres dict[str, ndarray] | None

Dict mapping sphere names to positions

None
from_generator
from_generator(state_generator: Generator[ndarray, None, None], fps: float = 30.0) -> None

Consume states from a generator at specified FPS.

Parameters:

Name Type Description Default
state_generator Generator[ndarray, None, None]

Generator yielding configurations

required
fps float

Target frame rate

30.0

References

The UMArm platform was introduced in: