franky.CartesianImpedanceTracker

class franky.CartesianImpedanceTracker(robot: Robot, *, translational_stiffness: float | None = None, rotational_stiffness: float | None = None, damping: ndarray | None = None, gains: CartesianImpedanceGains | None = None, translational_error_clip: ndarray | None = None, rotational_error_clip: ndarray | None = None, posture_task: PostureTask | None = None, manipulability_task: ManipulabilityTask | None = None, friction: FrictionCompensationParams | None = None, max_delta_tau: float = 1.0, lower_joint_limits: ndarray | None = None, upper_joint_limits: ndarray | None = None, joint_limit_activation_distance: float = 0.1, joint_limit_stiffness: float = 4.0, joint_limit_damping: float = 1.0, joint_limit_max_torque: float = 5.0, gains_time_constant: float = 0.1, period: float | None = None)

Bases: object

Long-lived session for streaming Cartesian impedance tracking commands.

Use as a context manager to stop the controller on exit. Stiffness and damping are orthogonal knobs (see set_gains()); omitting damping means critical damping (2 * sqrt(stiffness)), tracked against the current stiffness each cycle. Pass posture_task/manipulability_task to add nullspace objectives.

Example:

with CartesianImpedanceTracker(robot, translational_stiffness=800.0, period=0.01) as tracker:
    while tracker.tick():
        tracker.set_target(desired_pose)
__init__(robot: Robot, *, translational_stiffness: float | None = None, rotational_stiffness: float | None = None, damping: ndarray | None = None, gains: CartesianImpedanceGains | None = None, translational_error_clip: ndarray | None = None, rotational_error_clip: ndarray | None = None, posture_task: PostureTask | None = None, manipulability_task: ManipulabilityTask | None = None, friction: FrictionCompensationParams | None = None, max_delta_tau: float = 1.0, lower_joint_limits: ndarray | None = None, upper_joint_limits: ndarray | None = None, joint_limit_activation_distance: float = 0.1, joint_limit_stiffness: float = 4.0, joint_limit_damping: float = 1.0, joint_limit_max_torque: float = 5.0, gains_time_constant: float = 0.1, period: float | None = None)
set_gains(*, translational_stiffness: float | None = None, rotational_stiffness: float | None = None, damping: ndarray | None = None, gains: CartesianImpedanceGains | None = None, posture_stiffness: float | ndarray | None = None, nullspace_gains: NullspaceGains | None = None) None

Update impedance gains (smoothed in the RT loop).

translational_stiffness/rotational_stiffness set a stiffness block. damping is all-or-nothing: a full 6-vector [x, y, z, rx, ry, rz] pins it, CRITICAL unpins it. gains total-replaces with a full CartesianImpedanceGains object (for anisotropic stiffness) and is exclusive with the rest. Omitting damping means critical: a stiffness change re-criticals unless damping is passed too.

For the nullspace, posture_stiffness (scalar or 7-vector) nudges just the posture task’s stiffness; nullspace_gains replaces the full NullspaceGains (posture + manipulability). Mutually exclusive; both only retune tasks configured at construction.

set_target(pose: Affine, twist: Twist | None = None, acceleration: TwistAcceleration | None = None) None

Update the Cartesian target pose and optional twist/acceleration feedforward.

stop(stop_motion: TorqueStopMotion | None = None) None

Gracefully stop the tracking controller and wait for the arm to come to rest.

Enqueues a TorqueStopMotion that ramps the last commanded torque into a damping-only law, brings the arm to rest, and finishes cleanly (no preemption exception). Pass stop_motion to override the ramp/damping behaviour; otherwise sensible defaults are used.

If the controller is no longer in control (e.g. it already faulted), this just joins the motion to surface any stored exception.

tick() float | None

Sleep to maintain the requested period and return the measured timestep.

Returns the wall-clock seconds elapsed since the previous tick, or None once the controller is no longer in control, so a loop can pace itself and pick up a timestep to integrate with in one step:

while dt := tracker.tick():
    tracker.set_target(integrate(dt))

The returned timestep is always non-zero positive.

On the first call, returns immediately (no sleep) and reports period: the nominal length of the cycle about to run, since there is no previous tick to measure against and construction or caller setup time is not the loop’s to report. With no period configured, the first call reports a negligible non-zero timestep. On subsequent calls, sleeps the remaining time until the next tick boundary so that loop body time is compensated for; a body that overran its period shows up as a timestep larger than period.

If no period was set, just measures and returns without sleeping.

property current_pose

The current end-effector pose as a RobotPose (shorthand for robot.current_pose).

property dt: float

The timestep most recently returned by tick() (0.0 before the first tick).

property elapsed_time: float

Seconds since the tracker was created.

property is_running: bool

Whether the tracking controller is still active.

property motion: CartesianImpedanceTrackingMotion

The underlying tracking motion instance.

property period: float | None

The configured loop period in seconds, or None if the tracker is unpaced.

property state

The current robot state from this control session.

property tick_count: int

Number of ticks that have run, i.e. returned a timestep rather than None.