urdf_state_space

URDF → linear state-space plant. See the guide for concepts and the YAML schema.

state_space — linearization core

Linearize rigid-body robot dynamics from a URDF into a state-space model.

The manipulator equation

M(q) q_ddot + C(q, q_dot) q_dot + g(q) = S^T u

is linearized about an equilibrium (q_eq, q_dot = 0, u_eq = gravity compensation), giving the LTI system

x_dot = A x + B u_delta, y = C x + D u_delta

with state x = [q - q_eq, q_dot] (tangent space) and input u_delta = u - u_eq. The partial derivatives of the forward dynamics are computed analytically by Pinocchio (computeABADerivatives), not by finite differences.

class urdf_state_space.state_space.StateSpaceModel(A: ~numpy.ndarray, B: ~numpy.ndarray, C: ~numpy.ndarray, D: ~numpy.ndarray, q_eq: ~numpy.ndarray, u_eq: ~numpy.ndarray, joint_names: ~typing.List[str], actuated_joint_names: ~typing.List[str], output_names: ~typing.List[str] = <factory>)[source]

Bases: object

LTI model of a robot linearized about an equilibrium point.

State x = [q - q_eq (tangent), q_dot], input u = tau_actuated - u_eq.

A: ndarray
B: ndarray
C: ndarray
D: ndarray
q_eq: ndarray
u_eq: ndarray
joint_names: List[str]
actuated_joint_names: List[str]
output_names: List[str]
property n_states: int
property n_inputs: int
property n_outputs: int
poles() ndarray[source]
controllability_matrix() ndarray[source]
observability_matrix() ndarray[source]
is_controllable(tol: float | None = None) bool[source]
is_observable(tol: float | None = None) bool[source]
to_control()[source]

Return a python-control StateSpace object (pip install control).

c2d(dt: float) StateSpaceModel[source]

Discretize with zero-order hold (exact, via matrix exponential).

save_npz(path: str) None[source]
save_mat(path: str) None[source]

Save to MATLAB .mat (usable with hinfsyn/mixsyn in MATLAB).

classmethod load_npz(path: str) StateSpaceModel[source]
summary() str[source]
urdf_state_space.state_space.build_state_space(urdf: str, q_eq: Sequence[float] | Mapping[str, float] | None = None, actuated_joints: Sequence[str] | None = None, output_joints: Sequence[str] | None = None, velocity_outputs: bool = False, joint_damping: Sequence[float] | Mapping[str, float] | None = None, floating_base: bool = False, gravity_tol: float = 1e-06) StateSpaceModel[source]

Linearize the robot in urdf about (q_eq, q_dot = 0).

Parameters:
  • urdf – Path to a URDF file, or the URDF XML itself.

  • q_eq – Equilibrium configuration: either a full pinocchio q vector, or a {joint_name: position} mapping (unnamed joints stay neutral). Defaults to the neutral configuration.

  • actuated_joints – Names of actuated joints (columns of B). Default: all movable joints.

  • output_joints – Joints whose positions appear in y. Default: the actuated joints.

  • velocity_outputs – Also include the velocities of output_joints in y.

  • joint_damping – Viscous damping added to the model (URDF <damping> values are NOT read by pinocchio): either a per-DoF sequence of length nv, or a {joint_name: damping} mapping (unnamed joints get 0). N*m*s/rad.

  • floating_base – Model the base as a free-flyer joint instead of fixed to the world.

  • gravity_tol – Warn if unactuated joints need more torque than this to hold q_eq (the point is then not a true equilibrium for the given actuation).

config — YAML config loader

YAML-driven model setup: describe the linearization per joint, by name.

Example config

model:
  urdf: package://my_robot_description/urdf/my_robot.urdf
  floating_base: false

joints:                        # every movable joint may have an entry
  shoulder_joint: {actuated: true, damping: 0.1}
  elbow_joint:    {actuated: true, damping: 0.1, q_eq: 0.3}
  wrist_joint:    {damping: 0.005}

outputs:
  velocities: true             # y includes velocities as well
  # joints: [elbow_joint]      # optional; default: the actuated joints

export:
  npz: model.npz
  mat: model.mat
  # dt: 0.001                  # also produce/export the ZOH-discretized model

If any joint sets actuated, only joints with actuated: true are actuated; if none does, all movable joints are. Joints without a damping or q_eq entry default to 0 / neutral. Relative paths (URDF and export files) are resolved against the YAML file’s directory.

class urdf_state_space.config.ExportSpec(npz: str | None = None, mat: str | None = None, dt: float | None = None)[source]

Bases: object

npz: str | None = None
mat: str | None = None
dt: float | None = None
urdf_state_space.config.resolve_resource(ref: str, base_dir: str = '.') str[source]

Resolve a package:// URI or a (possibly relative) filesystem path.

urdf_state_space.config.build_from_yaml(config_path: str) Tuple[StateSpaceModel, ExportSpec][source]

Build a StateSpaceModel from a YAML config; also return export spec.

cli — the urdf2ss entry point

Command-line tool: linearize a URDF into state-space matrices.

Preferred: describe everything in a YAML config (joint-name keyed, no positional pitfalls) and run

urdf2ss model.yaml

Quick one-offs can still pass a URDF and flags directly:

urdf2ss robot.urdf urdf2ss robot.urdf –q-eq 0 0.5 0 –actuated shoulder_joint elbow_joint urdf2ss robot.xacro -o model.npz –mat model.mat

urdf_state_space.cli.main(argv=None) int[source]