code wiki / _hdl_build / nx_skill_coach_dance.nx

nx_skill_coach_dance.nx source

↩ module page · 74 lines · 5099 B

1// nx_skill_coach_dance.nx -- SKILL-COACH vision/DANCE vertical, the COACH LOOP (parallel to audio R1). Given pose 2// KEYPOINTS (joint x,y), compute JOINT ANGLES, grade vs a reference pose, diagnose WHICH joint is off (too bent / 3// too straight) -> drill. This is the dance-coach core; the PERCEPTION (camera->keypoints = a sovereign bits-up 4// pose-net) is the RESEARCHER-owned research arc CAP-COACH-POSE -- here keypoints are synthetic (the pose-net is 5// the separate long-pole, exactly as nx_pitch was the separate perception for audio R1). Pure integer (cos via 6// dot/|.|, isqrt; NO floats, NO acos -- compare cosines: larger cos = smaller angle = more bent). license_tier: ORIGINAL 7import "nx_syscalls.nx" 8import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 9const DC_MAGIC_16384: i64 = 16384 10 11const DC_TOL: i64 = 3000 // Q14 cosine-difference tolerance (data-driven; R2 rubric-store could hold it) 12 13func dc_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 14// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 15// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 16// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 17// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 18func dc_putn(v: i64) -> i64 { nxi_out(v); return 0 } 19func dc_isqrt(n: i64) -> i64 { 20 if n <= 0 { return 0 } 21 var x: i64 = n 22 var y: i64 = (x + 1) / 2 23 while y < x { x = y; y = (x + n / x) / 2 } 24 return x 25} 26func dc_jx(p: *i64, j: i64) -> i64 { return p[2 * j] } 27func dc_jy(p: *i64, j: i64) -> i64 { return p[2 * j + 1] } 28// cosine (Q14) of the joint angle at jb, from points ja-jb-jc 29func dc_jcos(p: *i64, ja: i64, jb: i64, jc: i64) -> i64 { 30 let bax: i64 = dc_jx(p, ja) - dc_jx(p, jb) 31 let bay: i64 = dc_jy(p, ja) - dc_jy(p, jb) 32 let bcx: i64 = dc_jx(p, jc) - dc_jx(p, jb) 33 let bcy: i64 = dc_jy(p, jc) - dc_jy(p, jb) 34 let dot: i64 = bax * bcx + bay * bcy 35 let mba: i64 = dc_isqrt(bax * bax + bay * bay) 36 let mbc: i64 = dc_isqrt(bcx * bcx + bcy * bcy) 37 if mba == 0 { return DC_MAGIC_16384 } 38 if mbc == 0 { return DC_MAGIC_16384 } 39 return dot * DC_MAGIC_16384 / (mba * mbc) 40} 41// grade one joint vs the reference pose. verdict: 0 GOOD, 1 TOO-BENT (angle smaller -> cos larger), 2 TOO-STRAIGHT. 42func dc_coach_joint(pose: *i64, ref: *i64, ja: i64, jb: i64, jc: i64, name: *u8) -> i64 { 43 let dcos: i64 = dc_jcos(pose, ja, jb, jc) 44 let rcos: i64 = dc_jcos(ref, ja, jb, jc) 45 let diff: i64 = dcos - rcos 46 dc_puts(" "); dc_puts(name); dc_puts(": cos="); dc_putn(dcos); dc_puts(" vs ref="); dc_putn(rcos); dc_puts(" -> ") 47 if diff > DC_TOL { dc_puts("TOO BENT -> straighten the joint; DRILL: hold the target shape, mirror-check\n" as *u8); return 1 } 48 if diff < (0 - DC_TOL) { dc_puts("TOO STRAIGHT -> bend more to the target; DRILL: slow ramp into the pose\n" as *u8); return 2 } 49 dc_puts("GOOD form -> hold it / advance\n" as *u8); return 0 50} 51func main() -> i64 { 52 dc_puts("SKILL-COACH (dance R1): pose keypoints -> JOINT ANGLES -> grade vs reference -> DIAGNOSE -> DRILL\n" as *u8) 53 // joints: 0 shoulder 1 elbow 2 wrist 3 hip 4 knee 5 ankle. elbow angle=(0,1,2), knee angle=(3,4,5) 54 let ref: *i64 = sys_mmap(8 * 12) as *i64 55 ref[0] = 0; ref[1] = 0; ref[2] = 10; ref[3] = 0; ref[4] = 10; ref[5] = 10 56 ref[6] = 0; ref[7] = 20; ref[8] = 10; ref[9] = 20; ref[10] = 10; ref[11] = 30 57 var pass: i64 = 0 58 // T1: perfect form (= ref) -> elbow GOOD + knee GOOD 59 dc_puts(" [attempt 1: matches the reference pose]\n" as *u8) 60 let p1: *i64 = sys_mmap(8 * 12) as *i64; var i: i64 = 0; while i < 12 { p1[i] = ref[i]; i = i + 1 } 61 if dc_coach_joint(p1, ref, 0, 1, 2, "L-elbow" as *u8) == 0 { if dc_coach_joint(p1, ref, 3, 4, 5, "L-knee" as *u8) == 0 { pass = pass + 1 } } 62 // T2: bent elbow (wrist pulled in toward shoulder) -> elbow TOO BENT, knee GOOD 63 dc_puts(" [attempt 2: elbow over-bent]\n" as *u8) 64 let p2: *i64 = sys_mmap(8 * 12) as *i64; i = 0; while i < 12 { p2[i] = ref[i]; i = i + 1 } p2[4] = 2; p2[5] = 2 65 if dc_coach_joint(p2, ref, 0, 1, 2, "L-elbow" as *u8) == 1 { if dc_coach_joint(p2, ref, 3, 4, 5, "L-knee" as *u8) == 0 { pass = pass + 1 } } 66 // T3: straight knee (leg locked vertical) -> elbow GOOD, knee TOO STRAIGHT 67 dc_puts(" [attempt 3: knee locked straight]\n" as *u8) 68 let p3: *i64 = sys_mmap(8 * 12) as *i64; i = 0; while i < 12 { p3[i] = ref[i]; i = i + 1 } p3[6] = 10; p3[7] = 0; p3[10] = 10; p3[11] = 40 69 if dc_coach_joint(p3, ref, 0, 1, 2, "L-elbow" as *u8) == 0 { if dc_coach_joint(p3, ref, 3, 4, 5, "L-knee" as *u8) == 2 { pass = pass + 1 } } 70 dc_puts(" dance verdicts correct = "); dc_putn(pass); dc_puts("/3\n" as *u8) 71 if pass == 3 { dc_puts("SKILL-COACH-DANCE: GREEN -- pose->joint-angle->diagnose->drill works; the dance-coach loop (perception=the RESEARCHER pose-net arc)\n" as *u8); return 0 } 72 dc_puts("SKILL-COACH-DANCE: RED\n" as *u8) 73 return 1 74}