Do not fail a hand-back on the step the counters round to

The post-run pass compared the kernel position counters exactly, so a
test that put the head back within a hundredth of a millimeter failed
whenever that distance did not round to the same step.

motion.lid-cancel-home found it on the bench reference. The test cancels
a job with the lid twice and the controller returns the head to the job
start each time, landing 0.038 and 0.037 mm out - the same figures as the
run before it, which passed. This time the two returns left four steps on
X, 0.075 mm at 53.333 steps per mm, and the hand-back called it a
leftover. Twenty-three runs of that test, all passing, on returns of the
same accuracy: whether the residue rounds to zero is chance, not a
property of the machine or of the test.

A difference inside POSITION_DEADBAND_MM (0.1 mm, five steps at x8) on X
and Y is now the quantization rather than a leftover. The head is still
put back, so nothing accumulates over a campaign - only the failure goes.
Z stays exact: the return never moves the lens, so a Z difference is
still a leftover and still unrestorable.

Host-proven: four new unit tests on the boundary (four steps and a moved
Z on either side of it, and an unreadable reading), and the forgetest
suite.
This commit is contained in:
ScottW514
2026-09-10 09:53:27 -04:00
parent 1dd6ad608b
commit b2c42f0cc3
2 changed files with 51 additions and 1 deletions
+25
View File
@@ -354,6 +354,31 @@ if __name__ == "__main__":
unittest.main()
class PositionDeadbandTests(unittest.TestCase):
"""The counters count steps and a controller's own return lands within
a few hundredths of a millimeter, not on the step: a difference that
small is quantization, not a leftover. Found on the bench reference,
where motion.lid-cancel-home returned the head twice, each within
0.04 mm, and failed the hand-back on the four steps left over."""
def test_a_few_steps_of_xy_are_the_quantization(self):
self.assertTrue(baseline.position_quantized([0, 0, 0], [4, 0, 0]))
self.assertTrue(baseline.position_quantized([0, 0, 0], [-4, 4, 0]))
self.assertTrue(baseline.position_quantized([10, 20, 30], [10, 20, 30]))
def test_past_the_dead_band_is_a_leftover(self):
over = int(baseline.POSITION_DEADBAND_MM * baseline.XY_STEPS_PER_MM) + 2
self.assertFalse(baseline.position_quantized([0, 0, 0], [over, 0, 0]))
self.assertFalse(baseline.position_quantized([0, 0, 0], [0, over, 0]))
def test_z_is_exact_because_the_return_never_moves_it(self):
self.assertFalse(baseline.position_quantized([0, 0, 0], [0, 0, 1]))
def test_an_unreadable_reading_is_never_quantization(self):
self.assertFalse(baseline.position_quantized(None, [0, 0, 0]))
self.assertFalse(baseline.position_quantized([0, 0, 0], None))
class BaselineModeTests(BaselineTests):
"""The baseline against a fake forgectrl: what the mode in force
owns. Reuses the fake sysfs tree of BaselineTests; only the new