code wiki / (root) / nx_preflight_test.nx

nx_preflight_test.nx source

↩ module page · 101 lines · 4835 B

1// nx_preflight_test.nx -- exercise preflight orchestrator with 2// good + bad inputs across every failure class. 3// 4// Closed-form invariants: 5// (a) Tetrahedron + Qidi X-Max 3 + Generic PLA + sane params -> SAFE. 6// (b) n_checks_run == 4; n_failed == 0 on the safe case. 7// (c) Non-manifold (3-tri mesh, removed one) -> UNSAFE / NOT_MANIFOLD. 8// (d) Mesh 500mm cube (exceeds 325mm Qidi build) -> UNSAFE / MESH_TOO_LARGE. 9// (e) Material with bad temp (mutate PLA to print 260°C) -> UNSAFE / BAD_THERMAL. 10// (f) Slicer max_speed 1000 mm/s (Qidi max 600) at 0.4×0.2 line -> 11// flow = 0.4 × 0.2 × 1000 = 80 mm³/s > machine 35 mm³/s -> UNSAFE / FLOW_EXCEEDED_MACHINE. 12// (g) Slicer max_speed 200 at 0.4×0.2 -> flow 16 mm³/s; material max 15 -> 13// UNSAFE / FLOW_EXCEEDED_MATERIAL. 14// (h) Verdict name lookup non-NULL for every reason. 15// 16// expect_exit: 0 17// license_tier: ORIGINAL 18 19import "nx_syscalls.nx" 20import "nx_mesh.nx" 21import "nx_mesh_print_check.nx" 22import "nx_machine_graph.nx" 23import "nx_material_profile.nx" 24import "nx_preflight.nx" 25 26const Q14: i64 = 16384 27 28func main() -> i64 { 29 let tet: *NxMesh = nx_mesh_make_tetrahedron(Q14, 0) // 1mm = tiny mesh 30 let qidi: *NxMachineGraph = nx_machine_graph_qidi_xmax3() 31 let pla: *NxMaterialProfile = nx_material_profile_generic_pla() 32 33 // line_width 0.4mm = 6554 Q14; layer_height 0.2mm = 3277 Q14; 34 // typical print speed 150 mm/s. 35 let lw: i64 = 6554 36 let lh: i64 = 3277 37 let speed_ok: i64 = 150 38 39 // --- (a)(b) SAFE case --- 40 let r_safe: *NxPreflightResult = nx_preflight_check(tet, qidi, pla, lh, lw, speed_ok) 41 if r_safe.verdict != NX_PREFLIGHT_SAFE { return 10 } 42 if r_safe.first_reason != NX_PFR_OK { return 11 } 43 if r_safe.n_checks_run != 5 { return 12 } // now 5 checks 44 if r_safe.n_failed != 0 { return 13 } 45 46 // --- (c) Non-manifold mesh --- 47 let bad_mesh: *NxMesh = nx_mesh_make_tetrahedron(Q14, 0) 48 bad_mesh.n_tris = 3 // remove one triangle -> open mesh 49 let r_nm: *NxPreflightResult = nx_preflight_check(bad_mesh, qidi, pla, lh, lw, speed_ok) 50 if r_nm.verdict != NX_PREFLIGHT_UNSAFE { return 20 } 51 if r_nm.first_reason != NX_PFR_NOT_MANIFOLD { return 21 } 52 53 // --- (d) Mesh too large: 500mm cube --- 54 // 500mm = 8192000 Q14. Just need bbox extent > build (Qidi 325mm). 55 // Build a tetrahedron with edge 500mm. 56 let huge: *NxMesh = nx_mesh_make_tetrahedron(500 * Q14, 0) 57 let r_big: *NxPreflightResult = nx_preflight_check(huge, qidi, pla, lh, lw, speed_ok) 58 if r_big.verdict != NX_PREFLIGHT_UNSAFE { return 30 } 59 if r_big.first_reason != NX_PFR_MESH_TOO_LARGE { return 31 } 60 61 // --- (e) Bad thermal: mutate PLA to print 260°C --- 62 let pla_bad: *NxMaterialProfile = nx_material_profile_generic_pla() 63 pla_bad.hotend_print_c = 260 // > PLA decomp 250 64 let r_t: *NxPreflightResult = nx_preflight_check(tet, qidi, pla_bad, lh, lw, speed_ok) 65 if r_t.verdict != NX_PREFLIGHT_UNSAFE { return 40 } 66 if r_t.first_reason != NX_PFR_BAD_THERMAL { return 41 } 67 68 // --- (f) Flow exceeds machine: 1000 mm/s at 0.4×0.2 = 80 mm³/s > 35 --- 69 let r_fm: *NxPreflightResult = nx_preflight_check(tet, qidi, pla, lh, lw, 1000) 70 if r_fm.verdict != NX_PREFLIGHT_UNSAFE { return 50 } 71 if r_fm.first_reason != NX_PFR_FLOW_EXCEEDED_MACHINE { return 51 } 72 73 // --- (g) Flow exceeds material: 250 mm/s × 0.4 × 0.2 = 19 mm³/s > material 15 --- 74 // (At 200 mm/s the integer flow = 15 = material max exactly, no breach. 75 // 250 mm/s breaches cleanly.) 76 let r_fmat: *NxPreflightResult = nx_preflight_check(tet, qidi, pla, lh, lw, 250) 77 if r_fmat.verdict != NX_PREFLIGHT_UNSAFE { return 60 } 78 if r_fmat.first_reason != NX_PFR_FLOW_EXCEEDED_MATERIAL { return 61 } 79 80 // --- (h) Layer too thick: 0.35mm layer on 0.4mm nozzle (>0.3 max) --- 81 let lh_thick: i64 = 5734 // 0.35mm in Q14 82 let r_thick: *NxPreflightResult = nx_preflight_check(tet, qidi, pla, lh_thick, lw, 100) 83 if r_thick.verdict != NX_PREFLIGHT_UNSAFE { return 90 } 84 if r_thick.first_reason != NX_PFR_LAYER_TOO_THICK { return 91 } 85 86 // --- (i) Layer too thin: 0.05mm layer on 0.4mm nozzle (<0.1 min) --- 87 let lh_thin: i64 = 820 // 0.05mm in Q14 88 let r_thin: *NxPreflightResult = nx_preflight_check(tet, qidi, pla, lh_thin, lw, 100) 89 if r_thin.verdict != NX_PREFLIGHT_UNSAFE { return 100 } 90 if r_thin.first_reason != NX_PFR_LAYER_TOO_THIN { return 101 } 91 92 // --- (j) Reason name lookup for all verdicts --- 93 var ri: i64 = 0 94 while ri < NX_PFR_N { 95 let nm: *u8 = nx_pfr_name(ri) 96 if (nm as i64) == 0 { return 110 + ri } 97 ri = ri + 1 98 } 99 100 return 0 101}