Skip to content

Exact screw gyro clock derivatives

The native screw_linear gyro factor now differentiates time using its piecewise screw rotation directly. Within an interval, R(t) = R_left Exp(alpha(t) w), so body angular velocity is w / dt. Previously, a 1 ms forward rotation difference averaged adjacent intervals near a knot and could not evaluate a domain shorter than that stencil.

This is a derivative-correctness change. It preserves gyro integration, residual predictions, all nonclock Jacobian blocks, measurement weights, stopping rules, public signatures and serialized schemas. It makes no new speed, independent accuracy or general convergence claim.

Boundary convention and tests

Increasing clock offset moves both factor endpoints left in body time. At an internal knot, the clock column therefore uses the left time limit. If a factor starts exactly at the trajectory's first endpoint, only the opposite clock direction can stay in-domain; both endpoints then use their right time limits. Global endpoints use their single inward interval. Representable times immediately beside a knot retain their actual interval; there is no tolerance-based knot snapping.

The 79 new checks cover closed-form piecewise z rotations, nonuniform knots, short domains, exact knots and their representable neighbours, nonzero clock, mounting rotation, nonunit gyro scales, one-sided residual differences and the fitter's actual weighted clock-gradient column. Of these checks, 47 fail against the previous frozen source and all 79 pass after correction. A 405-test targeted run and 402-module Linux/Win32 type checks also pass.

Across nine saved initial/baseline-final/candidate-final states, all 63 gyro factors retain bit equality of residuals and every nonclock block. All 63 clock blocks change. This diagnostic performs no optimizer steps; the full current development cohort below does perform calibration.

Complete development outcomes

Item Value
Baseline content c8001467f88eee880c6f21169ba858c572bdb068
Numerical candidate 3c2998cf84cbd1916a313ead72269c4e62cc5695
Inputs Already-spent synthetic seeds 20261010, 20261011, 20261012
Current execution One complete maintained CLI cohort, one BLAS thread
Comparison Complete problem/options equality; previous stored outcomes reused

The baseline is the stored candidate cohort from the batch execution comparison, originally measured at df4144a4d135dea3b0863847f26bc778b56fc719. Its complete 402-module source capsule matches c8001467 exactly. It was not rerun or treated as a new timing control. The current cohort uses unchanged options and quality gates; every outcome is retained.

Seed Previous status / iterations Current status / iterations Previous → current raw gradient norm Policy / detected controls
20261010 converged / 21 converged / 20 0.003569 → 0.029755 pass / 32 of 32
20261011 converged / 23 max_iterations / 32 0.043092 → 0.042580 pass / 32 of 32
20261012 converged / 29 converged / 19 0.074092 → 0.039789 pass / 32 of 32

The middle case stops after 32 iterations with max_iterations, before the configured budget of 60. In this solver, that status also covers early damping exhaustion: unsuccessful steps increase damping until it exceeds 1e12. The stopping path is inferred from the frozen control flow and returned status; no per-iteration damping trace was captured. Quality-policy passes refer to the declared error, holdout and control checks; they do not assert optimizer stationarity. All final raw gradients exceed the configured 1e-8 threshold, and the existing small accepted-step criterion can still label a fit converged.

Seed Gyro holdout RMSE, previous → current (rad) Maximum translation error, previous → current (m) Maximum rotation error, previous → current (deg)
20261010 0.000488302268 → 0.000488302519 0.005859982705 → 0.005859983082 0.163571973239 → 0.163571969257
20261011 0.000341162463 → 0.000341163323 0.006994565126 → 0.006994564494 0.097251474177 → 0.097251478319
20261012 0.000423084156 → 0.000423084300 0.006343990061 → 0.006343990130 0.126097611874 → 0.126097637626

Gyro holdout RMSE increases slightly in all three cases; other accuracy changes and iteration counts are mixed. Full covariance, all metrics, final normal models and signed controls remain in the complete development evidence.

Status correction and CI

The original archive and summary.json are retained byte-for-byte. Its candidate_iteration_limit_cases key incorrectly described seed 20261011 as exhausting its iteration budget. The schema-validated erratum supersedes that interpretation and binds the saved options, fit, source and initial CI failures. No numerical result, stopping threshold or quality gate was changed for this correction.

The initial full Python 3.11 and 3.12 CI jobs each reported 5295 passes, 104 skips and one failure: a legacy test required converged although the quality policy passed and the actual fit returned max_iterations. The joint recovery tests now check exact propagation of the real fitter status and iteration count, retain all error/holdout/control gates and reject singular fits. Controlled stopping tests distinguish budget exhaustion from early damping exhaustion and require both to remain nonconverged. Platform-dependent termination is disclosed rather than relabelled or rerun for a preferred result.

Reproduce and remaining work

At the numerical candidate, use one BLAS thread and retain all outcomes:

calibrex trajectory recover-lidar-imu-joint --trajectory screw_linear --seed 20261010 --output replay-20261010.json --json
calibrex trajectory recover-lidar-imu-joint --trajectory screw_linear --seed 20261011 --output replay-20261011.json --json
calibrex trajectory recover-lidar-imu-joint --trajectory screw_linear --seed 20261012 --output replay-20261012.json --json

The archive retains both source capsules and original producers. Platform and floating-point differences can affect accepted steps and iteration counts. No recording download is required.

A one-sided factor derivative does not implement a constrained optimizer. Global clock-domain bounds and feasible stepping remain separate work. A factor spanning both domain endpoints admits no nonzero in-domain clock shift; these checks make no clock-identifiability claim for that case. Accelerometer clock finite differences, mixed-unit stopping and prior-packing approximations also remain unchanged. These limits must be addressed before the independent fixed-budget reliability study.