Commit 6e7b92d8 authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: rung C3 - freeze per-scene conditioning, light prepare cycles 2+

Design 3-A4i rung C3 (native tile_processor_gpu HEAD): the cycle-1 resident
prepare result carries the FROZEN conditioning; later cycles of the same
scene run a light prepare (fresh measured offsets + fx/J at the moving pose;
weights/eigen/selection/pull/reg/pure_weight untouched). Rulings (Andrey
07/17): eigen freezes WITH the weights (same trust-in-tile nature); a
frozen-selected tile with no fresh valid peak abstains (y=fx, zero
residual); reg weights + pure_weight freeze from cycle 1. Semantic gain:
every cycle optimizes the SAME objective - conditioning no longer wobbles
with per-cycle measurement noise. Provider/GpuQuad/GpuQuadJna gain a light
flag; the per-scene instance naturally scopes the freeze.
Gates: mvn package+test PASS; Stage0 36/36; native suite incl. new LIGHT
bit-exact test PASS.
Co-Authored-By: 's avatarClaude Fable 5 <noreply@anthropic.com>
parent 69eaaf30
...@@ -1088,14 +1088,14 @@ public class CuasPoseRT { ...@@ -1088,14 +1088,14 @@ public class CuasPoseRT {
// packed-index slot/shift are CUAS host policy. By Claude on 07/17/2026. // packed-index slot/shift are CUAS host policy. By Claude on 07/17/2026.
intersceneLma.setPoseLmaPrepareProvider((refCam, sceneCam, refXyz, refAtr, intersceneLma.setPoseLmaPrepareProvider((refCam, sceneCam, refXyz, refAtr,
sceneXyz, sceneAtr, centers, numTiles, useEigen, eigMinSqrt, eigMaxSqrt, sceneXyz, sceneAtr, centers, numTiles, useEigen, eigMinSqrt, eigMaxSqrt,
minConfidence, sameWeights, pullTargets, paramRegweights, capture) -> { minConfidence, sameWeights, pullTargets, paramRegweights, light, capture) -> {
final IntersceneLmaFloat.PrepareResidentResult result = final IntersceneLmaFloat.PrepareResidentResult result =
lmaGpu.execPoseLmaPrepareResident( lmaGpu.execPoseLmaPrepareResident(
refCam, sceneCam, refXyz, refAtr, sceneXyz, sceneAtr, centers, refCam, sceneCam, refXyz, refAtr, sceneXyz, sceneAtr, centers,
numTiles, // rung C2: null camera/centers = keep resident // By Claude on 07/17/2026 numTiles, // rung C2: null camera/centers = keep resident; C3: light = frozen conditioning // By Claude on 07/17/2026
0xff, GPUTileProcessor.CORR_NTILE_SHIFT, 0xff, GPUTileProcessor.CORR_NTILE_SHIFT,
useEigen, eigMinSqrt, eigMaxSqrt, minConfidence, sameWeights, useEigen, eigMinSqrt, eigMaxSqrt, minConfidence, sameWeights,
pullTargets, paramRegweights, capture); pullTargets, paramRegweights, light, capture);
if ((result != null) && !pose_prepare_path_reported) { if ((result != null) && !pose_prepare_path_reported) {
pose_prepare_path_reported = true; pose_prepare_path_reported = true;
System.out.println("CuasPoseRT: resident CUDA prepareLMA active "+ System.out.println("CuasPoseRT: resident CUDA prepareLMA active "+
......
...@@ -2979,6 +2979,7 @@ public class GpuQuad{ // quad camera description ...@@ -2979,6 +2979,7 @@ public class GpuQuad{ // quad camera description
boolean same_weights, boolean same_weights,
float [] pull_targets, float [] pull_targets,
float [] param_regweights, float [] param_regweights,
boolean light, // rung C3 // By Claude on 07/17/2026
boolean capture) { boolean capture) {
return null; return null;
} }
......
...@@ -575,11 +575,12 @@ public class GpuQuadJna extends GpuQuad { ...@@ -575,11 +575,12 @@ public class GpuQuadJna extends GpuQuad {
final boolean sameWeights, final boolean sameWeights,
final float[] pullTargets, final float[] pullTargets,
final float[] paramRegweights, final float[] paramRegweights,
final boolean light, // rung C3: frozen conditioning, fresh measured offsets only // By Claude on 07/17/2026
final boolean capture) { final boolean capture) {
if ((numTiles <= 0) || if ((numTiles <= 0) || (light && capture) ||
((centers != null) && (centers.length != 3 * numTiles)) || ((centers != null) && (centers.length != 3 * numTiles)) ||
(pullTargets == null) || (pullTargets.length != IntersceneLmaFloat.NUM_PARAMS) || (!light && ((pullTargets == null) || (pullTargets.length != IntersceneLmaFloat.NUM_PARAMS) ||
(paramRegweights == null) || (paramRegweights.length != IntersceneLmaFloat.NUM_PARAMS)) { (paramRegweights == null) || (paramRegweights.length != IntersceneLmaFloat.NUM_PARAMS)))) {
throw new IllegalArgumentException("GpuQuadJna.execPoseLmaPrepareResident: inconsistent inputs"); throw new IllegalArgumentException("GpuQuadJna.execPoseLmaPrepareResident: inconsistent inputs");
} }
final int numValues = IntersceneLmaFloat.NUM_COMPONENTS * numTiles + final int numValues = IntersceneLmaFloat.NUM_COMPONENTS * numTiles +
...@@ -613,11 +614,17 @@ public class GpuQuadJna extends GpuQuad { ...@@ -613,11 +614,17 @@ public class GpuQuadJna extends GpuQuad {
useEigen ? 1 : 0, eigMinSqrt, eigMaxSqrt, useEigen ? 1 : 0, eigMinSqrt, eigMaxSqrt,
minConfidence, sameWeights ? 1 : 0, minConfidence, sameWeights ? 1 : 0,
pullTargets, paramRegweights, pullTargets, paramRegweights,
light ? 1 : 0,
prepResult, capture ? 1 : 0, outY, outWeights, outEigen); prepResult, capture ? 1 : 0, outY, outWeights, outEigen);
if (rc != 0) { if (rc != 0) {
throw new IllegalStateException("GpuQuadJna.execPoseLmaPrepareResident rc="+rc+": "+ throw new IllegalStateException("GpuQuadJna.execPoseLmaPrepareResident rc="+rc+": "+
lib.tp_last_error()); lib.tp_last_error());
} }
if (light) { // rung C3: conditioning + compact result frozen from cycle 1
return new IntersceneLmaFloat.PrepareResidentResult(
numTiles, true, 0, 0.0f, 0.0f, 0.0f,
new float[IntersceneLmaFloat.NUM_PARAMS], null, null, null);
}
return new IntersceneLmaFloat.PrepareResidentResult( return new IntersceneLmaFloat.PrepareResidentResult(
numTiles, numTiles,
prepResult[0] != 0.0f, prepResult[0] != 0.0f,
......
...@@ -179,6 +179,7 @@ public interface TpJna extends Library { ...@@ -179,6 +179,7 @@ public interface TpJna extends Library {
int useEigen, float eigMinSqrt, float eigMaxSqrt, int useEigen, float eigMinSqrt, float eigMaxSqrt,
float minConfidence, int sameWeights, float minConfidence, int sameWeights,
float[] pullTargets, float[] paramRegweights, float[] pullTargets, float[] paramRegweights,
int light, // rung C3: 1 = frozen conditioning, fresh y only // By Claude on 07/17/2026
float[] prepResult, int capture, float[] prepResult, int capture,
float[] outY, float[] outWeights, float[] outEigen); float[] outY, float[] outWeights, float[] outEigen);
/** Deterministic double normal-equation products for the lean pose LMA. /** Deterministic double normal-equation products for the lean pose LMA.
......
...@@ -494,6 +494,11 @@ public class IntersceneLma { ...@@ -494,6 +494,11 @@ public class IntersceneLma {
// [19,20]. The one-shot oracle cycle (pose_lma_debug>=1, first prepare) runs // [19,20]. The one-shot oracle cycle (pose_lma_debug>=1, first prepare) runs
// the FULL legacy path and compares the captured buffers at the end. // the FULL legacy path and compares the captured buffers at the end.
// By Claude on 07/17/2026. // By Claude on 07/17/2026.
// Rung C3: the cycle-1 result carries the FROZEN conditioning (weights/
// eigen/selection/pull/reg/pure_weight) - later cycles of the same scene
// run a LIGHT prepare (fresh measured offsets + fx only). The instance is
// per-scene, so this naturally resets per scene. By Claude on 07/17/2026.
final IntersceneLmaFloat.PrepareResidentResult frozen_prepare = poseResidentPrepare;
poseResidentPrepare = null; poseResidentPrepare = null;
boolean lean_pose_shape = (num_components == 2) && boolean lean_pose_shape = (num_components == 2) &&
(par_indices.length == IntersceneLmaFloat.NUM_PARAMS); (par_indices.length == IntersceneLmaFloat.NUM_PARAMS);
...@@ -507,7 +512,7 @@ public class IntersceneLma { ...@@ -507,7 +512,7 @@ public class IntersceneLma {
if ((poseLmaPrepareProvider != null) && lean_pose_shape && (vector_XYSDS != null) && if ((poseLmaPrepareProvider != null) && lean_pose_shape && (vector_XYSDS != null) &&
(reliable_ref == null) && !prepare_capture) { (reliable_ref == null) && !prepare_capture) {
if (residentPrepare(eigen, eig_max_sqrt, eig_min_sqrt, min_confidence, if (residentPrepare(eigen, eig_max_sqrt, eig_min_sqrt, min_confidence,
same_weights, param_regweights, false)) { same_weights, param_regweights, frozen_prepare, false)) {
weights = null; // resident-owned; the steps run with no per-step H2D weights = null; // resident-owned; the steps run with no per-step H2D
y_vector = null; y_vector = null;
if (prof_sink != null) prof_sink.add(PROF_PREP_SETUP, System.nanoTime() - prof_t0); if (prof_sink != null) prof_sink.add(PROF_PREP_SETUP, System.nanoTime() - prof_t0);
...@@ -614,7 +619,7 @@ public class IntersceneLma { ...@@ -614,7 +619,7 @@ public class IntersceneLma {
// captured buffers bit-exactly. By Claude on 07/17/2026. // captured buffers bit-exactly. By Claude on 07/17/2026.
if (prepare_capture) { if (prepare_capture) {
if (residentPrepare(eigen, eig_max_sqrt, eig_min_sqrt, min_confidence, if (residentPrepare(eigen, eig_max_sqrt, eig_min_sqrt, min_confidence,
same_weights, param_regweights, true) && same_weights, param_regweights, null, true) &&
(poseResidentPrepare.capturedY != null)) { (poseResidentPrepare.capturedY != null)) {
final float [] pull = new float [IntersceneLmaFloat.NUM_PARAMS]; final float [] pull = new float [IntersceneLmaFloat.NUM_PARAMS];
final float [] regw = new float [IntersceneLmaFloat.NUM_PARAMS]; final float [] regw = new float [IntersceneLmaFloat.NUM_PARAMS];
...@@ -2036,6 +2041,7 @@ public class IntersceneLma { ...@@ -2036,6 +2041,7 @@ public class IntersceneLma {
boolean useEigen, float eigMinSqrt, float eigMaxSqrt, boolean useEigen, float eigMinSqrt, float eigMaxSqrt,
float minConfidence, boolean sameWeights, float minConfidence, boolean sameWeights,
float [] pullTargets, float [] paramRegweights, float [] pullTargets, float [] paramRegweights,
boolean light, // rung C3: frozen conditioning, fresh measured offsets only // By Claude on 07/17/2026
boolean capture); boolean capture);
} }
private PoseLmaPrepareProvider poseLmaPrepareProvider = null; private PoseLmaPrepareProvider poseLmaPrepareProvider = null;
...@@ -2072,8 +2078,10 @@ public class IntersceneLma { ...@@ -2072,8 +2078,10 @@ public class IntersceneLma {
final double min_confidence, final double min_confidence,
final boolean same_weights, final boolean same_weights,
final double [] param_regweights, final double [] param_regweights,
final IntersceneLmaFloat.PrepareResidentResult frozen, // rung C3: non-null = cycle-1 conditioning to reuse (light) // By Claude on 07/17/2026
final boolean capture) { final boolean capture) {
if (poseLmaPrepareProvider == null) return false; if (poseLmaPrepareProvider == null) return false;
final boolean lightPrepare = (frozen != null) && !capture;
final double [] full_vector = getFullVector(parameters_vector); final double [] full_vector = getFullVector(parameters_vector);
final ErsCorrection ers_ref = scenesCLT[0].getErsCorrection(); final ErsCorrection ers_ref = scenesCLT[0].getErsCorrection();
final ErsCorrection ers_scene = scenesCLT[1].getErsCorrection(); final ErsCorrection ers_scene = scenesCLT[1].getErsCorrection();
...@@ -2112,12 +2120,16 @@ public class IntersceneLma { ...@@ -2112,12 +2120,16 @@ public class IntersceneLma {
ers_scene.setupERS(); ers_scene.setupERS();
poseResidentSceneCamera = IntersceneLmaFloat.Camera.capture(ers_scene); poseResidentSceneCamera = IntersceneLmaFloat.Camera.capture(ers_scene);
} }
final float [] pull = new float [IntersceneLmaFloat.NUM_PARAMS]; float [] pull = null;
final float [] regw = new float [IntersceneLmaFloat.NUM_PARAMS]; float [] regw = null;
for (int par = 0; par < IntersceneLmaFloat.NUM_PARAMS; par++) { if (!lightPrepare) { // rung C3: pull/reg are part of the frozen conditioning
pull[par] = (float) ((parameters_pull != null) ? pull = new float [IntersceneLmaFloat.NUM_PARAMS];
parameters_pull[par] : parameters_vector[par]); // no pull = zero residual rows regw = new float [IntersceneLmaFloat.NUM_PARAMS];
regw[par] = (float) param_regweights[par_indices[par]]; for (int par = 0; par < IntersceneLmaFloat.NUM_PARAMS; par++) {
pull[par] = (float) ((parameters_pull != null) ?
parameters_pull[par] : parameters_vector[par]); // no pull = zero residual rows
regw[par] = (float) param_regweights[par_indices[par]];
}
} }
final IntersceneLmaFloat.PrepareResidentResult result = poseLmaPrepareProvider.calculate( final IntersceneLmaFloat.PrepareResidentResult result = poseLmaPrepareProvider.calculate(
newSequence ? poseSeqRefCamera : null, newSequence ? poseSeqRefCamera : null,
...@@ -2127,12 +2139,18 @@ public class IntersceneLma { ...@@ -2127,12 +2139,18 @@ public class IntersceneLma {
newSequence ? poseSeqCenters : null, newSequence ? poseSeqCenters : null,
macrotile_centers.length, (eigen_src != null), macrotile_centers.length, (eigen_src != null),
(float) eig_min_sqrt, (float) eig_max_sqrt, (float) eig_min_sqrt, (float) eig_max_sqrt,
(float) min_confidence, same_weights, pull, regw, capture); (float) min_confidence, same_weights, pull, regw, lightPrepare, capture);
if ((result == null) || !result.valid) return false; if ((result == null) || !result.valid) return false;
poseResidentPrepare = result; if (lightPrepare) {
pure_weight = result.pureWeight; // Rung C3: keep the cycle-1 compact result (pure_weight/num_meas/reg
num_defined = result.numMeas; // stay authoritative for the whole scene). By Claude on 07/17/2026.
sum_weights = result.sumWRaw; poseResidentPrepare = frozen;
} else {
poseResidentPrepare = result;
pure_weight = result.pureWeight;
num_defined = result.numMeas;
sum_weights = result.sumWRaw;
}
return true; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment