Control API
skelarm.control
Trajectory-tracking control: references, torque controllers, and a fixed-step loop.
This module turns a planned reference into joint torques. A task-space trajectory
is first converted to a joint-space reference (samplewise inverse kinematics or
resolved motion rate), then a torque controller (joint PD, inverse-dynamics
feedforward plus PD, or computed torque) tracks it. :func:simulate_controlled
runs a controller against the dynamics with a fixed time step and returns a
:class:~skelarm.StateLog for replay and analysis.
See docs/reference/07_control.md for the theory.
ComputedTorque
Bases: TrackingController
Computed torque control: τ = H(q)(q̈_r + Kd ė + Kp e) + b(q,q̇).
Source code in src/skelarm/control.py
control(t, skeleton)
Compute the model-cancelling torque for the current state.
Source code in src/skelarm/control.py
Controller
Bases: ABC
Base class for joint-torque controllers.
A controller is callable as f(t, skeleton) -> tau so stateless controllers
work directly as a :func:~skelarm.simulate_robot torque callback. Stateful
controllers use :meth:reset and :meth:update together with
:func:simulate_controlled, and may expose internal signals via
:meth:log_channels.
Source code in src/skelarm/control.py
__call__(t, skeleton)
control(t, skeleton)
abstractmethod
log_channels()
reset(skeleton)
InverseDynamicsFeedforwardPD
Bases: TrackingController
Inverse-dynamics feedforward plus PD: τ = ID(q_r,q̇_r,q̈_r) + Kp e + Kd ė.
Source code in src/skelarm/control.py
__init__(reference, kp, kd)
Store the reference and gains; the feedforward model is built lazily.
control(t, skeleton)
Compute the feedforward-plus-PD torque for the current state.
Source code in src/skelarm/control.py
JointPD
Bases: TrackingController
Direct joint-space PD control: τ = Kp(q_r-q) + Kd(q̇_r-q̇).
Source code in src/skelarm/control.py
control(t, skeleton)
Compute the PD torque for the current state.
Source code in src/skelarm/control.py
JointReference
Bases: Protocol
A joint-space reference that can be sampled for (q_r, dq_r, ddq_r).
Source code in src/skelarm/control.py
sample(t)
SampledJointReference
A joint reference stored as time-sampled arrays, read by linear interpolation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
times
|
ArrayLike
|
Sample times, shape |
required |
q
|
ArrayLike
|
Joint angles, velocities, and accelerations, each shape |
required |
dq
|
ArrayLike
|
Joint angles, velocities, and accelerations, each shape |
required |
ddq
|
ArrayLike
|
Joint angles, velocities, and accelerations, each shape |
required |
Source code in src/skelarm/control.py
__init__(times, q, dq, ddq)
Store the sampled reference arrays.
Source code in src/skelarm/control.py
sample(t)
Linearly interpolate the reference at time t (held at the endpoints).
Source code in src/skelarm/control.py
SampledTaskReference
A task-space reference stored as time-sampled arrays, read by linear interpolation.
Use this when a (typically pre-smoothed) endpoint path p_r(t) is supplied as
samples; it satisfies :class:TaskReference, so :func:ik_joint_reference can turn
it into a joint reference for the tracking controllers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
times
|
ArrayLike
|
Sample times, shape |
required |
p
|
ArrayLike
|
Endpoint position, velocity, and acceleration, each shape |
required |
dp
|
ArrayLike
|
Endpoint position, velocity, and acceleration, each shape |
required |
ddp
|
ArrayLike
|
Endpoint position, velocity, and acceleration, each shape |
required |
Source code in src/skelarm/control.py
__init__(times, p, dp, ddp)
Store the sampled task-space arrays and derive the duration.
Source code in src/skelarm/control.py
sample(t)
Linearly interpolate the endpoint reference at time t (held at the endpoints).
Source code in src/skelarm/control.py
TaskReference
Bases: Protocol
A task-space reference p_r(t) sampled for (p, dp, ddp).
Anything exposing .sample(t) and a .duration is a task reference, so
:class:~skelarm.Trajectory, :class:SampledTaskReference, and the periodic
curves all qualify and can feed :func:ik_joint_reference.
Source code in src/skelarm/control.py
sample(t)
TrackingController
Bases: Controller
A controller that tracks a joint reference, logging q_ref and error.
Source code in src/skelarm/control.py
__init__(reference, kp, kd)
Store the reference and (scalar or per-joint) PD gains.
Source code in src/skelarm/control.py
log_channels()
Record the joint reference and tracking error once tracking has begun.
ik_joint_reference(skeleton, task_trajectory, *, dt, method='lm_sugihara')
Convert a task-space trajectory to a joint reference with samplewise IK.
Each sample is solved with :func:compute_inverse_kinematics, warm-started
from the previous solution for joint continuity. Velocities and accelerations
are estimated by finite differences. The input skeleton is not mutated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
skeleton
|
Skeleton
|
The arm to solve for; its current pose seeds the first IK solve. |
required |
task_trajectory
|
TaskReference
|
The desired endpoint trajectory |
required |
dt
|
float
|
Sampling interval (seconds). |
required |
method
|
str
|
IK method passed to :func: |
'lm_sugihara'
|
Returns:
| Type | Description |
|---|---|
SampledJointReference
|
The joint reference |
Source code in src/skelarm/control.py
resolved_rate_joint_reference(skeleton, task_trajectory, *, dt, damping=0.001, k_task=0.0)
Convert a task-space trajectory to a joint reference by resolved motion rate.
Integrates q̇_r = Jᵀ(JJᵀ+µI)⁻¹(ṗ_r + K_task(p_r - p)) forward in time. The
task-feedback term K_task corrects drift from the desired path. The input
skeleton is not mutated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
skeleton
|
Skeleton
|
The arm to convert for; its current pose is the integration start. |
required |
task_trajectory
|
TaskReference
|
The desired endpoint trajectory. |
required |
dt
|
float
|
Integration step (seconds). |
required |
damping
|
float
|
Damping |
0.001
|
k_task
|
float
|
Task-space position-feedback gain. |
0.0
|
Returns:
| Type | Description |
|---|---|
SampledJointReference
|
The joint reference |
Source code in src/skelarm/control.py
simulate_controlled(skeleton, controller, *, duration, dt=0.001, grav_vec=None, enforce_limits=True, extra=None)
Run a controller against the dynamics with a fixed time step.
Uses semi-implicit (symplectic) Euler, the same integration as the GUI
simulator. A clone of skeleton is simulated, so the caller's skeleton is
not mutated. Each frame records q, dq, the applied tau, and any
channels from controller.log_channels().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
skeleton
|
Skeleton
|
Initial state ( |
required |
controller
|
Controller
|
The torque controller to run. |
required |
duration
|
float
|
Total simulated time (seconds). |
required |
dt
|
float
|
Fixed control/integration step (seconds). |
0.001
|
grav_vec
|
NDArray[float64] | None
|
Gravity vector; defaults to zero (planar motion). |
None
|
enforce_limits
|
bool
|
Apply the joint limits as hard stops in the dynamics (default). When
|
True
|
extra
|
Mapping[str, Any] | None
|
Free-form metadata to embed in the returned log's |
None
|
Returns:
| Type | Description |
|---|---|
StateLog
|
The recorded run ( |