Commit b691e9f3 authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: Fix getInterseqScale() to use integer corr_inc for BX/AX/BY/AY positions

getInterseqScale() was calling getCorrIncExact() which returns 0.5*corr_offset
for half_step mode instead of the actual integer keyframe step getCorrInc()
(= corr_offset/2 with integer division). For odd corr_offset (e.g. 5) with
half_step=true these differ: getCorrIncExact()=2.5 vs getCorrInc()=2.

This caused getHalfBeforeAfterPixXY() to compute:
  after - before = RSLT_VX * 0.5   (wrong; observed by user)
instead of:
  after - before = RSLT_VX * corr_inc/corr_offset = RSLT_VX * 0.4  (correct)

recalcOmegas() uses the same interseq_scale in the inverse direction, so it
also reconstructed RSLT_VX/VY incorrectly from neighbouring keyframe positions.

Fix: use getCorrInc() (integer) in getInterseqScale() so that BX/AX positions
correspond to actual raw-frame midpoints and the velocity round-trip is exact.

Also adds an unambiguous convention comment near RSLT_VX/RSLT_VY in
CuasMotionLMA.java documenting all required scale conversions.

The omega calculation (getFrameVelocityScale * ifov * fps_raw) is independent
of corr_inc and was already correct.
Co-authored-by: 's avatarClaude <claude@elphel.com>
parent 9196f324
......@@ -320,14 +320,18 @@ public class CuasMotion {
*
* When {@code cuas_half_step} is enabled and {@code cuas_corr_offset} is odd, the
* actual scan index advance returned by {@link #getCorrInc(CLTParameters)} is truncated
* to an integer scene step. For chaining targets between neighboring keyframes we need
* the intended half-offset geometry rather than the truncated array index increment.
* to an integer scene step. This method returns the idealised real-valued half-step.
*
* NOTE: do NOT use this for position calculations (BX/AX/BY/AY) or RSLT_VX/VY back-
* conversion (recalcOmegas). Those must use the actual integer keyframe step
* {@link #getCorrInc(CLTParameters)} so that BX/AX positions fall at real frame
* positions and the velocity round-trip is consistent.
*/
public static double getCorrIncExact(
CLTParameters clt_parameters) {
return clt_parameters.imp.cuas_half_step ? (0.5 * clt_parameters.imp.cuas_corr_offset) : clt_parameters.imp.cuas_corr_offset;
}
public int getCorrInc() { // == frame_step;
return getCorrInc(clt_parameters);
// return clt_parameters.imp.cuas_half_step ? (clt_parameters.imp.cuas_corr_offset/2) : clt_parameters.imp.cuas_corr_offset;
......@@ -335,15 +339,19 @@ public class CuasMotion {
public int getNumCorrSamples() {
return slice_titles.length;
}
public int getFrameCenter(int nseq) {
int frame0 = start_frame + getSeqLength()/2;
int frame_center = frame0 + nseq * getCorrInc();
return frame_center;
}
public double getInterseqScale() { // multiply target velocity to get offset in the middle between the key frames
return 0.5 * getCorrIncExact(clt_parameters) / corr_offset;
// By Claude on 05/30/2026: use integer getCorrInc() (not getCorrIncExact()) so that BX/AX positions
// sit at actual raw-frame positions and recalcOmegas() round-trips correctly.
// With half_step=true and odd corr_offset (e.g. 5): getCorrInc()=2, getCorrIncExact()=2.5.
// Using 2.5 caused after-BX = 0.5*VX instead of the correct 0.4*VX (= VX*corr_inc/corr_offset).
public double getInterseqScale() { // multiply target velocity to get offset to midpoint between adjacent keyframes
return 0.5 * getCorrInc(clt_parameters) / (double) corr_offset;
}
/**
......
......@@ -78,6 +78,14 @@ public class CuasMotionLMA {
public static final int RSLT_CENT_MX= 15;
public static final int RSLT_CENT_F = 16;
// RSLT_VX / RSLT_VY convention (By Claude on 05/30/2026):
// These store the raw correlation peak offset measured over a pair of frames that are
// corr_offset raw frames apart. They are NOT pixels/raw-frame and NOT pixels/keyframe.
// Conversions:
// pixels / raw-frame = RSLT_VX / corr_offset (see getFrameVelocityScale())
// pixels / keyframe = RSLT_VX * getCorrInc() / corr_offset
// angular rate (rad/s) = (RSLT_VX / corr_offset) * ifov * fps_raw
// half-keyframe-interval = RSLT_VX * getInterseqScale() (used for BX/AX/BY/AY)
public static final int RSLT_VX = 17;
public static final int RSLT_VY = 18;
public static final int RSLT_VSTR = 19;
......
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