command_delay_comp_campaign

MPC command-delay compensation on TIAGo Pro — knot / ramp campaign

This campaign is an attempt to reproduce, on a TIAGo Pro arm, the command-delay compensation approach from:

R. Subburaman and O. Stasse, “Delay Robust Model Predictive Control For Whole-Body Torque Control of Humanoids”, IEEE-RAS International Conference on Humanoid Robots (Humanoids), Nancy, France, 2024. https://ieeexplore.ieee.org/document/10769888/

The paper studies the effect of computation delay in a whole-body MPC running underneath a fast torque-tracking loop (validated on the TALOS humanoid), and proposes lightweight compensation policies that shift or interpolate the published MPC solution to account for that delay, instead of trying to make the solve itself faster.

Here we run the same class of policies on a different robot and a different, much simpler task: TIAGo Pro’s right 7-DoF arm, free motion, no locomotion, no contact. The goal of this specific campaign is to check that these policies still behave sensibly on this stack, and to get a first, real (not simulated) read on their delay/tracking/chatter effect.

Control stack and OCP

Two rates in cascade:

The state is the arm’s [q, v] (7+7).

Running-node costs:

Terminal-node costs: the same state-regularization and frame translation/rotation tracking terms (no control cost at the terminal node). No constraint is active in this campaign (collision-avoidance constraints exist in the OCP definition but are all switched off here — this is a free-motion, obstacle-free test).

Command-delay compensation policies under test (the paper’s terminology): publishing the horizon’s knot 0 as-is (“u⁰”, naive), publishing knot 1 instead to pre-empt one MPC period of delay (“u¹”, apply_knot), and interpolating the LFC’s feedback reference toward the next knot instead of holding it between two /control updates (“u²”, reference_interpolation), alone or combined.

Recorded data

Four bags, TIAGo Pro right arm, free motion, no contact.

run policy (paper) apply_knot reference_interpolation recording duration per-bag plots
ramp_knot_baseline u⁰ 0 false 20260907_142848 4.2 s ocp_brush · torque_per_motor
ramp_knot_u0_interp u⁰ + reference smoothing, no knot shift 0 true 20260907_143536 6.6 s ocp_brush · torque_per_motor
ramp_knot_k1 u¹ 1 false 20260909_115010 7.4 s ocp_brush · torque_per_motor
ramp_knot_u2 u² 1 true 20260907_143659 6.5 s ocp_brush · torque_per_motor

ramp_knot_u0_interp isolates the effect of interpolating the feedback reference from the effect of shifting the published knot.

Results

staircase_qact_qdes.html — the 4 runs stacked, one joint at a time: does the real robot track the commanded reference tightly, and does interpolating the reference (u0_interp/u2) visibly smooth out the tracking compared to holding it (baseline/k1)?

torque_uff_ufb.html — one run at a time, all joints: how much of the commanded torque is the OCP’s own plan vs. the LFC’s fast reactive correction? A large, jittery correction term is what we call “chatter” — this is where to see whether a policy makes the motion rougher or smoother.

ocp_brush.html (one per bag) — every OCP solve’s predicted horizon, all overlaid, against what actually happened: do the predictions consistently land close to reality, or drift off in some direction? Generated for every bag for completeness, not the focus of this campaign.

torque_per_motor.html (one per bag) — same question as torque_uff_ufb.html, but as a per-bag sanity check: does the commanded torque reconstructed from /control agree with what /lfc_debug reports?

run x0-age at /control (mean / median) OCP solve time (mean, max) peak \|q_act-q_stair\| RMS \|u_fb\|
baseline (u⁰) 7.16 / 6.56 ms 5.6 ms, 10.2 ms 0.025 rad (j5) 0.63 N·m
u0_interp 7.56 / 7.34 ms 6.2 ms, 11.2 ms 0.033 rad (j5) 1.05 N·m
k1 (u¹) 7.67 / 6.92 ms 6.1 ms, 11.2 ms 0.072 rad (j7) 3.19 N·m
u2 7.58 / 7.24 ms 6.3 ms, 10.9 ms 0.072 rad (j7) 2.89 N·m