Commit 0a8d2415 authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: pose test rebased on the certified CuasRender chain (lean v2: MB + all-defined disparity)

Per Andrey: restore the pose test using the new (certified) data.

- Disparity: ONE source for all of RT - the plain DSI slice through
  CuasRender.conditionDisparityCuas (defined for ALL tiles, sky=infinity,
  negatives clamped). The use_lma_dsi gate removed from the pose test (the
  LMA slice is NaN over the sky and silently shrank the usable set).
- leanMeasure/leanFitScene: MB compensation (lean v2) - the same certified
  machinery as CuasRender: setInterTasksMotionBlur two task sets + the
  erase-first interCorrTDMotionBlur double convert (undefined tiles NaN for
  the consolidation), gated by imp.mb_en, vectors from the existing per-scene
  getMotionBlur block (previously computed but unused by lean).
- pose_stored branch gets the same MB treatment.

Expected in the next lean run (LMA, 150-cluster selection, mb_en ON):
az/tilt wobble (v*tau, 0.5 px rotating) collapses toward the MBEN oracle
(0.029/0.021 mrad), corr RMS toward ~0.08; roll bias = the remaining open
question (FPN-mask lead).

Verified: mvn -DskipTests clean package OK.
Co-Authored-By: 's avatarClaude Fable 5 <noreply@anthropic.com>
parent e4e65e23
......@@ -257,6 +257,11 @@ public class CuasPoseRT {
* @param img_out null or length-1 holder - filled with the imclt render of the
* consolidated composite scene ([width*height], NaN outside task tiles);
* requesting it adds an erased re-convert + an imclt pass (debug only)
* @param mb_vectors null (no motion-blur compensation) or [2][ntiles] blur vectors -
* the certified-chain MB: two task sets, double convert (positive SET +
* negative shifted SUBTRACT), erase-first so undefined tiles stay NaN
* @param mb_tau bolometer time constant, s (imp.mb_tau)
* @param mb_max_gain max MB scale before offset stretching (imp.mb_max_gain_inter)
* @return [3][num_pix][] {centers pXpYD, vector_XYS {dx,dy,strength}, eigen
* {e0x,e0y,l0,l1}} - the coord_motion contract of interCorrPair - or null
*/
......@@ -271,6 +276,9 @@ public class CuasPoseRT {
final double [] scene_xyz,
final double [] scene_atr,
final int margin,
final double [][] mb_vectors, // By Claude on 07/05/2026
final double mb_tau, // By Claude on 07/05/2026
final double mb_max_gain, // By Claude on 07/05/2026
final double [][][] corr_pd_out, // By Claude on 07/04/2026
final float [][] img_out, // By Claude on 07/04/2026
final int debugLevel) {
......@@ -280,44 +288,86 @@ public class CuasPoseRT {
final double [][] scene_pXpYD = OpticalFlow.transformToScenePxPyD(
null, center_disparity, scene_xyz, scene_atr, scene, center_CLT);
final double disparity_corr = clt_parameters.imp.disparity_corr + center_CLT.getDispInfinityRef();
final TpTask [] tp_tasks = GpuQuad.setInterTasks(
scene.getNumSensors(),
scene.getGeometryCorrection().getSensorWH()[0],
false, // GPU calculates port coordinates
scene_pXpYD, // per-tile pX,pY,disparity
selection, // only the calibrated tile selection
scene.getGeometryCorrection(),
disparity_corr,
margin,
null, // valid_tiles (not needed)
ImageDtt.THREADS_MAX);
if ((tp_tasks == null) || (tp_tasks.length == 0)) {
System.out.println("leanMeasure(): no tasks for scene "+scene.getImageName());
return null;
}
// 2. convert only: LPFs + tasks + offsets + convert_direct, NO correlation (mask=0)
image_dtt.interCorrTD(
clt_parameters.img_dtt,
tp_tasks,
null, // fcorr_td - not used with mask=0
clt_parameters.gpu_sigma_r,
clt_parameters.gpu_sigma_b,
clt_parameters.gpu_sigma_g,
clt_parameters.gpu_sigma_m,
scene.isMonochrome() ? 1.0 : clt_parameters.gpu_sigma_rb_corr,
clt_parameters.getGpuCorrSigma(scene.isMonochrome()),
clt_parameters.getGpuCorrLoGSigma(scene.isMonochrome()),
clt_parameters.corr_red,
clt_parameters.corr_blue,
0, // sensor_mask_inter = 0: convert only, return before correlate
ImageDtt.THREADS_MAX,
debugLevel);
// DEBUG (img_out): re-convert with erase_clt=1 so non-task tiles are NaN (interCorrTD
// converts with erase=-1, leaving the PREVIOUS scene's tiles outside the selection -
// harmless for correlation, ghosts in a render). Same LPFs/tasks/offsets - identical
// task-tile content, only the background differs. By Claude on 07/04/2026.
if (img_out != null) {
gpuQuad.execConvertDirect(false, null, 1);
if (mb_vectors != null) {
// Motion-blur compensation (lean v2, the certified CuasRender chain): two task
// sets, double convert (positive SET + negative shifted SUBTRACT), erase-first
// so undefined tiles reach downstream (consolidation, renders) as NaN.
// By Claude on 07/05/2026.
final TpTask [][] tp_tasks2 = GpuQuad.setInterTasksMotionBlur(
scene.getNumSensors(),
scene.getGeometryCorrection().getSensorWH()[0],
false, // GPU calculates port coordinates
scene_pXpYD,
selection, // only the calibrated tile selection
mb_tau,
mb_max_gain,
mb_vectors,
scene.getGeometryCorrection(),
disparity_corr,
margin,
null, // valid_tiles
ImageDtt.THREADS_MAX);
if ((tp_tasks2 == null) || (tp_tasks2[0] == null) || (tp_tasks2[0].length == 0)) {
System.out.println("leanMeasure(): no MB tasks for scene "+scene.getImageName());
return null;
}
image_dtt.interCorrTDMotionBlur(
clt_parameters.img_dtt,
1, // erase_clt_first: NaN outside the task set
tp_tasks2,
null, // fcorr_td - not used with mask=0
clt_parameters.gpu_sigma_r,
clt_parameters.gpu_sigma_b,
clt_parameters.gpu_sigma_g,
clt_parameters.gpu_sigma_m,
scene.isMonochrome() ? 1.0 : clt_parameters.gpu_sigma_rb_corr,
clt_parameters.getGpuCorrSigma(scene.isMonochrome()),
clt_parameters.getGpuCorrLoGSigma(scene.isMonochrome()),
clt_parameters.corr_red,
clt_parameters.corr_blue,
0, // sensor_mask_inter = 0: convert only
ImageDtt.THREADS_MAX,
debugLevel);
} else {
final TpTask [] tp_tasks = GpuQuad.setInterTasks(
scene.getNumSensors(),
scene.getGeometryCorrection().getSensorWH()[0],
false, // GPU calculates port coordinates
scene_pXpYD, // per-tile pX,pY,disparity
selection, // only the calibrated tile selection
scene.getGeometryCorrection(),
disparity_corr,
margin,
null, // valid_tiles (not needed)
ImageDtt.THREADS_MAX);
if ((tp_tasks == null) || (tp_tasks.length == 0)) {
System.out.println("leanMeasure(): no tasks for scene "+scene.getImageName());
return null;
}
// 2. convert only: LPFs + tasks + offsets + convert_direct, NO correlation (mask=0)
image_dtt.interCorrTD(
clt_parameters.img_dtt,
tp_tasks,
null, // fcorr_td - not used with mask=0
clt_parameters.gpu_sigma_r,
clt_parameters.gpu_sigma_b,
clt_parameters.gpu_sigma_g,
clt_parameters.gpu_sigma_m,
scene.isMonochrome() ? 1.0 : clt_parameters.gpu_sigma_rb_corr,
clt_parameters.getGpuCorrSigma(scene.isMonochrome()),
clt_parameters.getGpuCorrLoGSigma(scene.isMonochrome()),
clt_parameters.corr_red,
clt_parameters.corr_blue,
0, // sensor_mask_inter = 0: convert only, return before correlate
ImageDtt.THREADS_MAX,
debugLevel);
// DEBUG (img_out): re-convert with erase_clt=1 so non-task tiles are NaN (interCorrTD
// converts with erase=-1, leaving the PREVIOUS scene's tiles outside the selection -
// harmless for correlation, ghosts in a render). Same LPFs/tasks/offsets - identical
// task-tile content, only the background differs. By Claude on 07/04/2026.
if (img_out != null) {
gpuQuad.execConvertDirect(false, null, 1);
}
}
// 3. the CPU consolidation bridge (future clt_average_sensors kernel).
// The TRUE weighted average is fed to the correlator (NOT scaled to the oracle's
......@@ -413,6 +463,9 @@ public class CuasPoseRT {
final boolean [] param_select,
final double [] reg_weights,
final int margin,
final double [][] mb_vectors, // null - no MB compensation // By Claude on 07/05/2026
final double mb_tau, // By Claude on 07/05/2026
final double mb_max_gain, // By Claude on 07/05/2026
final double [] lma_rms, // out
final double [][][] coord_motion_rslt, // out [3][][]
final double [][][] corr_pd_out, // null or len-1: last-cycle PD correlations // By Claude on 07/04/2026
......@@ -428,7 +481,8 @@ public class CuasPoseRT {
cm = leanMeasure(
clt_parameters, image_dtt, center_CLT, scene,
center_disparity, pXpYD_center, selection,
scene_xyzatr0[0], scene_xyzatr0[1], margin, corr_pd_out, img_out, debugLevel);
scene_xyzatr0[0], scene_xyzatr0[1], margin,
mb_vectors, mb_tau, mb_max_gain, corr_pd_out, img_out, debugLevel);
if (cm == null) return null;
final double [][] eigen_masked = clt_parameters.imp.eig_xy_lma ? null : cm[2];
intersceneLma.prepareLMA(
......@@ -510,7 +564,6 @@ public class CuasPoseRT {
final QuadCLT [] quadCLTs,
final int debugLevel) {
final double min_str = clt_parameters.curt.pose_str; // e.g. 1.0
final boolean use_lma_dsi = clt_parameters.imp.use_lma_dsi;
final int margin = clt_parameters.imp.margin;
final double mb_tau = clt_parameters.imp.mb_tau;
final double mb_max_gain = clt_parameters.imp.mb_max_gain_inter;
......@@ -540,10 +593,13 @@ public class CuasPoseRT {
// ---- Reference prep (ONCE) - the persistent virtual-center TD reference ----
final boolean is_aux = center_CLT.isAux();
final double [][] center_dsi = center_CLT.dsi;
final double [] disparity = center_dsi[is_aux ? TwoQuadCLT.DSI_DISPARITY_AUX : TwoQuadCLT.DSI_DISPARITY_MAIN];
final double [] disparity_lma = center_dsi[is_aux ? TwoQuadCLT.DSI_DISPARITY_AUX_LMA : TwoQuadCLT.DSI_DISPARITY_MAIN_LMA];
final double [] strength = center_dsi[is_aux ? TwoQuadCLT.DSI_STRENGTH_AUX : TwoQuadCLT.DSI_STRENGTH_MAIN];
final double [] center_disparity = (use_lma_dsi && (disparity_lma != null)) ? disparity_lma : disparity;
// ONE disparity source for all of RT (Andrey ruling, certified in the render test):
// the PLAIN slice conditioned to be defined for ALL tiles (sky = infinity/0,
// negatives clamped). NOT gated by use_lma_dsi (the LMA slice is NaN over the sky).
// By Claude on 07/05/2026.
final double [] center_disparity = CuasRender.conditionDisparityCuas(
center_dsi[is_aux ? TwoQuadCLT.DSI_DISPARITY_AUX : TwoQuadCLT.DSI_DISPARITY_MAIN]);
final boolean [] reliable_ref = new boolean [strength.length];
int num_reliable = 0;
for (int i = 0; i < strength.length; i++) {
......@@ -665,9 +721,10 @@ public class CuasPoseRT {
clt_parameters.getScaleStrength(center_CLT.isAux()),
center_CLT.getGPU()) : null;
if (clt_parameters.curt.pose_lean) {
System.out.println("CuasPoseRT.testPoseSequence(): LEAN measurement engine (phase B): "+
"TD-average(16) x virtual-center single conj-multiply. NOTE: no MB compensation "+
"in lean v1 - compare against the NOMB baseline");
System.out.println("CuasPoseRT.testPoseSequence(): LEAN measurement engine (phase B v2, "+
"certified CuasRender chain): TD-average(16) x virtual-center single conj-multiply, "+
"all-defined conditioned disparity, MB compensation "+
(clt_parameters.imp.mb_en ? "ON (compare vs MBEN/stored)" : "OFF (compare vs NOMB)"));
}
if (clt_parameters.curt.pose_stored) { // By Claude on 07/04/2026
System.out.println("CuasPoseRT.testPoseSequence(): pose_stored ON (DEBUG) - STORED poses, "+
......@@ -819,6 +876,7 @@ public class CuasPoseRT {
clt_parameters, image_dtt_lean, center_CLT, quadCLTs[nscene],
center_disparity, pXpYD_center, reliable_ref,
use_pose[0], use_pose[1], margin,
mb_vectors_scene, mb_tau, mb_max_gain, // MB per imp.mb_en // By Claude on 07/05/2026
corr_pd_holder, img_holder, debugLevel - 2);
if (cm != null) {
pose = new double [][] {use_pose[0].clone(), use_pose[1].clone()};
......@@ -851,6 +909,9 @@ public class CuasPoseRT {
param_select, // boolean [] param_select,
reg_weights, // double [] reg_weights,
margin, // int margin,
mb_vectors_scene, // double [][] mb_vectors (MB per imp.mb_en - lean v2) // By Claude on 07/05/2026
mb_tau, // double mb_tau, // By Claude on 07/05/2026
mb_max_gain, // double mb_max_gain, // By Claude on 07/05/2026
lma_rms, // double [] lma_rms (out),
coord_motion_rslt, // double [][][] coord_motion_rslt (out),
corr_pd_holder, // double [][][] corr_pd_out (last-cycle PD correlations) // By Claude on 07/04/2026
......
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