code wiki / _hdl_build / nx_contactforce_gate.nx
nx_contactforce_gate.nx
buildroot/runtime/_hdl_build/nx_contactforce_gate.nx
about
nx_contactforce_gate.nx -- THE CONTACT READBACK IS REAL: it rises with depth, it tells firm tissue from
soft, and it is silent when nothing is touching. (softbody SB2 / hapticcare HC1, 2026-08-25.)
WHY THESE TEETH AND NOT A NUMBER. The solver carries NO KILOGRAM -- inverse mass is a uniform q12 -- so
an absolute newton is not derivable and st_contact_force does not claim one. That makes a tooth of the
form "force == X" impossible to write honestly. What a haptic loop actually consumes is COMPARISON:
press harder and it must read harder, press firm tissue and it must read harder than soft at the SAME
depth. Both are unit-INDEPENDENT, both are exactly what the absent-unit still supports, and both fail
loudly for a readback that is a constant, a counter, or noise.
THE PROBE RECIPE IS BORROWED, NOT INVENTED. nx_softtissue_gate already measured that teleporting the
probe to full depth puts its centre behind the surface and projects far-side vertices BACKWARDS through
the chest wall, inverting elements -- an artefact of instantaneous insertion, not of the solver. So the
probe approaches from OUTSIDE (z_touch = surface projection + radius) and ramps in over CF_RAMP substeps,
the same way that gate does it. Re-deriving the approach would have re-earned their bug.
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 3 imports · 0 importers
imports: nx_syscalls.nxnx_softtissue.nxnx_gate_verdict.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 21 | const CF_G: i64 = 9800 // gravity magnitude, tissue standing in its normal loaded state |
| 22 | const CF_ITERS: i64 = 8 // constraint iterations per substep |
| 23 | const CF_SETTLE: i64 = 60 // substeps to settle before any probe touches it |
| 24 | const CF_RAMP: i64 = 40 // ramp steps, matching nx_softtissue_gate's proven approach |
| 25 | const CF_PROBE_R: i64 = 2500 // 25 mm probe, as the incumbent gate uses |
| 26 | const CF_DEEP: i64 = 2000 // 20 mm press -- the incumbent's depth |
| 27 | const CF_SHALLOW: i64 = 1000 // half of it; the monotonicity pair is DEEP vs exactly half |
| 28 | const CF_H_MM: i64 = 10 |
functions
| 32 | func cf_press(prof: i64, depth: i64, out: *i64) -> i64 |
| 55 | func main() -> i64 |