Repository navigation
0.16 ft/ft drift, added per feature, makes any spot more than a few feet from the meter unresolvable #79
Description
The server grows every AR position's error by 0.16 ft per foot from the meter, then adds the object's error to the wall's. So no clearance check a few feet from the meter can pass, and every scan without a spot beside the meter ends in manual_review.
Seen in. Device field test of TestFlight build 4.1 (beta at 45017ba), iPhone 14 without LiDAR, iOS 26.6.2, 2026-09-26. Both runs on the indoor mock wall; the server re-run at 45017ba on each exported scene matches the phone's result exactly.
- Run 1: result at 6:06 in the recording. Report ID A41-1-09 in run1-2000.md.
- Run 2: result at 4:34, checks scrolled at 4:56–5:00. Report ID A41-2015-08 in run2-2015.md.
What happens.
Run 1, spot 10 ft 11 in → 13 ft 6 in right of the meter:
- AC: 3 ft 2 in ± 5 ft 7 in, against a 3 ft rule.
- Doors and windows: 3 ft 0 in ± 4 ft 0 in.
- Cable run: 12 ft 7 in ± 6 ft 5 in, against the 15 ft reach.
- 825 candidates: 0 pass, 719 unsure, 106 fail.
Run 2, spot 17 ft 1 in → 19 ft 8 in right:
- AC: 3 ft 0 in ± 6 ft 0 in.
- Doors and windows: 9 ft 9 in ± 4 ft 11 in.
- Cable run: 17 ft 1 in ± 4 ft 3 in, against 15 ft confident and 20 ft maximum.
- Meter working space passes, but at 15 ft 10 in ± 4 ft 3 in.
- 784 candidates: 0 pass, 654 unsure, 130 fail.
A second symptom, from run 2's sweep: starts at 5.1–6.9 ft, which put the battery directly under the window, come out unsure for opening_clearance, not fail. The summed errors swamp a sub-foot distance. Ranking still avoids those starts through estimate_fails, but the check's outcome is wrong.
Worked example, run 2's AC: the one-tap AC mark ends at 14.1 ft, so its error is 0.3 + 0.16 × 14.1 = 2.56 ft. The wall at the spot's far edge (19.68 ft) is 0.3 + 0.16 × 19.68 = 3.45 ft. Summed, that is ± 6.0 ft for two things measured on the same walk, about 5 ft apart.
Cause.
errors.drift_per_ftis 0.16 ft/ft (rules.yaml#L38-L41). Its source is ADVIO walks on a 2018 iPhone 6s with ARKit 1.0, and it says current phones are untested.- Objects get the tap error plus drift × the farthest |s| of their span (
scene.py#L809-L813). Ground patches get the same treatment (scene.py#L818-L822), and so do walls throughPiece.error_at(scene.py#L72-L78). - Each check takes the wall's error at the battery's far edge (
solver.py#L886-L890) and adds the object's error to it (solver.py#L464-L466). Both errors come from the same walk and are strongly correlated, so the sum overstates the error of the distance between them. - The app's stand-off distance is derived from the same 0.3 ft + 0.16 ft/ft (
GuidancePlanner.swift#L42-L50), so a change here should update that comment and value too.
Fix direction.
- Re-estimate drift on current phones: use the field tape test, or compare the packet's trajectory with the tape.
- Treat the errors of features measured on the same walk as relative. For example, the tap errors plus drift × the distance between the two features along the wall, not the sum of each one's absolute error from the meter.
- Consider measuring clearances between two features locally, from the photos that see both.
- A battery directly under a window (a sub-foot distance) should come out
fail. Once the error model changes, add that case as a test.
Related.
- Solver picks a spot inside the meter's working space when the meter's error is large #44: the solver picks a spot inside the meter's working space when the meter's error is large (the same error model, the other way round).
- "N checks depend on areas the scan did not see" counts checks that are unsure for other reasons #45.
- Report IDs A41-1-09 and A41-2015-08.
Activity
AidenJohnston commentedon Sep 27, 2026
Proposal: the drift error model needs data before anything changes
This comment lists the options and the data each one needs. It does not pick a model. I checked the code against
origin/t3/server, where the solver lives now.How it works today
plus_minus_ftgets an absolute error: tap error +drift_per_ft(0.16) × its farthest |s| from the meter. This covers tap and VLM objects inparse_scene, ground patches, and walls throughPiece.error_at. Tape items and the meter itself get no drift.Solver.evaluategives the battery the wall's error at its far edge.check_clearanceandcheck_along_wallthen add the object's absolute error to it (e = err + piece.plus_minus). Two features taken on the same walk a few feet apart have strongly correlated errors, so this sum overstates the error of the distance between them. That is how run 2's AC comes out at ± 6 ft, and why a battery directly under a window getsunsureand notfail.starts,_clearance_edgesand_settle_onplace the sweep's boundaries using the same battery error. Whatever the checks use, these three have to use too, or the sweep will miss the starts where an outcome changes.GuidanceConfig.standOffcomment derives the 2 m stand-off from 0.3 ft + 0.16 ft/ft. It must change with the model.Options (not ranked)
rules.yamlplus the drift test expectations. It needs a measured rate for current phones. Even a lower rate still sums two correlated errors, so the under-window case may still come outunsureat larger |s|.starts,_clearance_edges,_settle_on) has to use the same per-pair error. It still needs some number for how error grows with the distance between two features.Data that would settle it
Decisions still needed
Once decided, a server PR on
t3/serverwould do the following:rules.yaml(value and citation) andtest_drift.py;opening_clearancefail;standOffcomment and value in the app.🤖 Generated with Claude Code
AidenJohnston commentedon Sep 27, 2026
Team decision (2026-09-27): defer; keep 0.16 ft/ft until tape-walk data exists.
🤖 Generated with Claude Code
Publish files over 5 MB and skip paths outside the work dir. (#79)