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 {
// packed-index slot/shift are CUAS host policy. By Claude on 07/17/2026.
intersceneLma.setPoseLmaPrepareProvider((refCam, sceneCam, refXyz, refAtr,
sceneXyz, sceneAtr, centers, numTiles, useEigen, eigMinSqrt, eigMaxSqrt,
minConfidence, sameWeights, pullTargets, paramRegweights, capture) -> {
minConfidence, sameWeights, pullTargets, paramRegweights, light, capture) -> {
final IntersceneLmaFloat.PrepareResidentResult result =
lmaGpu.execPoseLmaPrepareResident(
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,
useEigen, eigMinSqrt, eigMaxSqrt, minConfidence, sameWeights,
pullTargets, paramRegweights, capture);
pullTargets, paramRegweights, light, capture);
if ((result != null) && !pose_prepare_path_reported) {
pose_prepare_path_reported = true;
System.out.println("CuasPoseRT: resident CUDA prepareLMA active "+
......
......@@ -2979,6 +2979,7 @@ public class GpuQuad{ // quad camera description
boolean same_weights,
float [] pull_targets,
float [] param_regweights,
boolean light, // rung C3 // By Claude on 07/17/2026
boolean capture) {
return null;
}
......
......@@ -575,11 +575,12 @@ public class GpuQuadJna extends GpuQuad {
final boolean sameWeights,
final float[] pullTargets,
final float[] paramRegweights,
final boolean light, // rung C3: frozen conditioning, fresh measured offsets only // By Claude on 07/17/2026
final boolean capture) {
if ((numTiles <= 0) ||
if ((numTiles <= 0) || (light && capture) ||
((centers != null) && (centers.length != 3 * numTiles)) ||
(pullTargets == null) || (pullTargets.length != IntersceneLmaFloat.NUM_PARAMS) ||
(paramRegweights == null) || (paramRegweights.length != IntersceneLmaFloat.NUM_PARAMS)) {
(!light && ((pullTargets == null) || (pullTargets.length != IntersceneLmaFloat.NUM_PARAMS) ||
(paramRegweights == null) || (paramRegweights.length != IntersceneLmaFloat.NUM_PARAMS)))) {
throw new IllegalArgumentException("GpuQuadJna.execPoseLmaPrepareResident: inconsistent inputs");
}
final int numValues = IntersceneLmaFloat.NUM_COMPONENTS * numTiles +
......@@ -613,11 +614,17 @@ public class GpuQuadJna extends GpuQuad {
useEigen ? 1 : 0, eigMinSqrt, eigMaxSqrt,
minConfidence, sameWeights ? 1 : 0,
pullTargets, paramRegweights,
light ? 1 : 0,
prepResult, capture ? 1 : 0, outY, outWeights, outEigen);
if (rc != 0) {
throw new IllegalStateException("GpuQuadJna.execPoseLmaPrepareResident rc="+rc+": "+
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(
numTiles,
prepResult[0] != 0.0f,
......
......@@ -179,6 +179,7 @@ public interface TpJna extends Library {
int useEigen, float eigMinSqrt, float eigMaxSqrt,
float minConfidence, int sameWeights,
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[] outY, float[] outWeights, float[] outEigen);
/** Deterministic double normal-equation products for the lean pose LMA.
......
......@@ -494,6 +494,11 @@ public class IntersceneLma {
// [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.
// 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;
boolean lean_pose_shape = (num_components == 2) &&
(par_indices.length == IntersceneLmaFloat.NUM_PARAMS);
......@@ -507,7 +512,7 @@ public class IntersceneLma {
if ((poseLmaPrepareProvider != null) && lean_pose_shape && (vector_XYSDS != null) &&
(reliable_ref == null) && !prepare_capture) {
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
y_vector = null;
if (prof_sink != null) prof_sink.add(PROF_PREP_SETUP, System.nanoTime() - prof_t0);
......@@ -614,7 +619,7 @@ public class IntersceneLma {
// captured buffers bit-exactly. By Claude on 07/17/2026.
if (prepare_capture) {
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)) {
final float [] pull = new float [IntersceneLmaFloat.NUM_PARAMS];
final float [] regw = new float [IntersceneLmaFloat.NUM_PARAMS];
......@@ -2036,6 +2041,7 @@ public class IntersceneLma {
boolean useEigen, float eigMinSqrt, float eigMaxSqrt,
float minConfidence, boolean sameWeights,
float [] pullTargets, float [] paramRegweights,
boolean light, // rung C3: frozen conditioning, fresh measured offsets only // By Claude on 07/17/2026
boolean capture);
}
private PoseLmaPrepareProvider poseLmaPrepareProvider = null;
......@@ -2072,8 +2078,10 @@ public class IntersceneLma {
final double min_confidence,
final boolean same_weights,
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) {
if (poseLmaPrepareProvider == null) return false;
final boolean lightPrepare = (frozen != null) && !capture;
final double [] full_vector = getFullVector(parameters_vector);
final ErsCorrection ers_ref = scenesCLT[0].getErsCorrection();
final ErsCorrection ers_scene = scenesCLT[1].getErsCorrection();
......@@ -2112,12 +2120,16 @@ public class IntersceneLma {
ers_scene.setupERS();
poseResidentSceneCamera = IntersceneLmaFloat.Camera.capture(ers_scene);
}
final float [] pull = new float [IntersceneLmaFloat.NUM_PARAMS];
final float [] regw = new float [IntersceneLmaFloat.NUM_PARAMS];
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]];
float [] pull = null;
float [] regw = null;
if (!lightPrepare) { // rung C3: pull/reg are part of the frozen conditioning
pull = new float [IntersceneLmaFloat.NUM_PARAMS];
regw = new float [IntersceneLmaFloat.NUM_PARAMS];
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(
newSequence ? poseSeqRefCamera : null,
......@@ -2127,12 +2139,18 @@ public class IntersceneLma {
newSequence ? poseSeqCenters : null,
macrotile_centers.length, (eigen_src != null),
(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;
poseResidentPrepare = result;
pure_weight = result.pureWeight;
num_defined = result.numMeas;
sum_weights = result.sumWRaw;
if (lightPrepare) {
// Rung C3: keep the cycle-1 compact result (pure_weight/num_meas/reg
// stay authoritative for the whole scene). By Claude on 07/17/2026.
poseResidentPrepare = frozen;
} else {
poseResidentPrepare = result;
pure_weight = result.pureWeight;
num_defined = result.numMeas;
sum_weights = result.sumWRaw;
}
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