Collision probability computation for conjunction assessment
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

collision: merlint fixes (Fmt.pr, rename find_tca → tca, fix docs)

+25 -25
+1 -1
lib/collision.ml
··· 395 395 396 396 type tca = { time : float; miss_distance : float; relative_velocity : float } 397 397 398 - let find_tca ~times ~pos1 ~pos2 ~vel1 ~vel2 = 398 + let tca ~times ~pos1 ~pos2 ~vel1 ~vel2 = 399 399 let n = Array.length times in 400 400 if n < 3 then None 401 401 else
+3 -3
lib/collision.mli
··· 63 63 64 64 type vec3 = Vec3.t = { x : float; y : float; z : float } 65 65 66 - val find_tca : 66 + val tca : 67 67 times:float array -> 68 68 pos1:vec3 array -> 69 69 pos2:vec3 array -> 70 70 vel1:vec3 array -> 71 71 vel2:vec3 array -> 72 72 tca option 73 - (** [find_tca ~times ~pos1 ~pos2 ~vel1 ~vel2] finds the time of closest approach 73 + (** [tca ~times ~pos1 ~pos2 ~vel1 ~vel2] finds the time of closest approach 74 74 between two objects using quadratic refinement. Arrays must be the same 75 75 length (synchronized time steps). Returns [None] if fewer than 3 points. *) 76 76 ··· 96 96 (** Chan series expansion Pc. *) 97 97 98 98 val pc_max : encounter -> float 99 - (** Upper bound: [hbr^2 / (2 * sigma_x * sigma_y)]. *) 99 + (** [pc_max enc] returns an upper bound: [hbr^2 / (2 * sigma_x * sigma_y)]. *) 100 100 101 101 val pc : hbr:float -> Cdm.t -> float 102 102 (** [pc ~hbr cdm] computes Pc from a CDM using the Foster method. *)
+21 -21
test/interop/gmat/test.ml
··· 24 24 Sat2: SSO-like (97.4 deg inc, 410 km alt). 25 25 1 day propagation, 10s step. *) 26 26 27 - let test_parse_both () = 27 + let parse_both () = 28 28 let oem1 = parse_oem "conjunction_sat1.oem" in 29 29 let oem2 = parse_oem "conjunction_sat2.oem" in 30 30 let sv1 = Odm.state_vectors (List.hd (Odm.segments oem1)) in 31 31 let sv2 = Odm.state_vectors (List.hd (Odm.segments oem2)) in 32 32 Alcotest.(check int) "same length" (Array.length sv1) (Array.length sv2) 33 33 34 - let test_minimum_distance () = 34 + let minimum_distance () = 35 35 let oem1 = parse_oem "conjunction_sat1.oem" in 36 36 let oem2 = parse_oem "conjunction_sat2.oem" in 37 37 let sv1 = Odm.state_vectors (List.hd (Odm.segments oem1)) in ··· 48 48 Alcotest.(check bool) "min distance found" true (Float.is_finite !min_dist); 49 49 Alcotest.(check bool) "min distance < 1000 km" true (!min_dist < 1000.0); 50 50 Alcotest.(check bool) "no collision (> 1 km)" true (!min_dist > 1.0); 51 - Printf.printf " Step-based closest approach: %.3f km at %s\n" !min_dist 51 + Fmt.pr " Step-based closest approach: %.3f km at %s\n" !min_dist 52 52 !min_epoch 53 53 54 - let test_relative_velocity () = 54 + let relative_velocity () = 55 55 let oem1 = parse_oem "conjunction_sat1.oem" in 56 56 let oem2 = parse_oem "conjunction_sat2.oem" in 57 57 let sv1 = Odm.state_vectors (List.hd (Odm.segments oem1)) in ··· 68 68 let dv = v_norm (v_sub sv1.(!min_i).Odm.vel sv2.(!min_i).Odm.vel) in 69 69 (* Crossing orbits at ~90 deg: relative velocity ~sqrt(2) * 7.5 ~= 10.6 km/s *) 70 70 Alcotest.(check bool) "high relative velocity" true (dv > 5.0); 71 - Printf.printf " Relative velocity at TCA: %.3f km/s\n" dv 71 + Fmt.pr " Relative velocity at TCA: %.3f km/s\n" dv 72 72 73 - (* TCA refinement: find_tca should improve on step-based minimum. 73 + (* TCA refinement: tca should improve on step-based minimum. 74 74 With 10s steps and ~10 km/s relative velocity, the step-based minimum 75 75 can miss the true TCA by up to 5s (~50 km). Quadratic refinement 76 76 should give sub-step precision. *) 77 - let test_tca_refinement () = 77 + let tca_refinement () = 78 78 let oem1 = parse_oem "conjunction_sat1.oem" in 79 79 let oem2 = parse_oem "conjunction_sat2.oem" in 80 80 let sv1 = Odm.state_vectors (List.hd (Odm.segments oem1)) in ··· 99 99 step_min_d := d; 100 100 step_min_t := times.(i)) 101 101 done; 102 - match Collision.find_tca ~times ~pos1 ~pos2 ~vel1 ~vel2 with 103 - | None -> Alcotest.fail "find_tca returned None" 102 + match Collision.tca ~times ~pos1 ~pos2 ~vel1 ~vel2 with 103 + | None -> Alcotest.fail "tca returned None" 104 104 | Some tca -> 105 - Printf.printf " Step-based TCA: t=%.3f, d=%.3f km\n" !step_min_t 105 + Fmt.pr " Step-based TCA: t=%.3f, d=%.3f km\n" !step_min_t 106 106 !step_min_d; 107 - Printf.printf " Refined TCA: t=%.3f, d=%.3f km, vrel=%.3f km/s\n" 107 + Fmt.pr " Refined TCA: t=%.3f, d=%.3f km, vrel=%.3f km/s\n" 108 108 tca.time tca.miss_distance tca.relative_velocity; 109 109 (* Refined miss distance should be <= step-based (quadratic finds the 110 110 true minimum between steps) *) ··· 127 127 Without covariance, the miss distance alone is meaningless for CA decisions. 128 128 A 50 km miss distance could be Pc=1e-3 (bad) or Pc=1e-10 (fine) depending 129 129 on covariance size. *) 130 - let test_pc_requires_covariance () = 130 + let pc_requires_covariance () = 131 131 (* We can compute miss distance from GMAT OEMs *) 132 132 let oem1 = parse_oem "conjunction_sat1.oem" in 133 133 let oem2 = parse_oem "conjunction_sat2.oem" in ··· 139 139 let d = v_norm (v_sub sv1.(i).Odm.pos sv2.(i).Odm.pos) in 140 140 if d < !min_dist then min_dist := d 141 141 done; 142 - Printf.printf " Miss distance: %.3f km\n" !min_dist; 143 - Printf.printf " Pc: CANNOT COMPUTE — no covariance in OEM\n"; 144 - Printf.printf 142 + Fmt.pr " Miss distance: %.3f km\n" !min_dist; 143 + Fmt.pr " Pc: CANNOT COMPUTE — no covariance in OEM\n"; 144 + Fmt.pr 145 145 " GAP: Need GMAT covariance propagation (Propagate ... Covariance)\n"; 146 - Printf.printf 146 + Fmt.pr 147 147 " or CDM with covariance to test ocaml-collision Pc computation.\n"; 148 148 (* This test passes but documents the gap. The real test would be: 149 149 1. Generate GMAT OEM WITH covariance ··· 159 159 [ 160 160 ( "plumbing", 161 161 [ 162 - Alcotest.test_case "parse both OEMs" `Quick test_parse_both; 163 - Alcotest.test_case "minimum distance" `Quick test_minimum_distance; 164 - Alcotest.test_case "relative velocity" `Quick test_relative_velocity; 162 + Alcotest.test_case "parse both OEMs" `Quick parse_both; 163 + Alcotest.test_case "minimum distance" `Quick minimum_distance; 164 + Alcotest.test_case "relative velocity" `Quick relative_velocity; 165 165 ] ); 166 166 ( "mission-ready", 167 167 [ 168 - Alcotest.test_case "TCA refinement" `Quick test_tca_refinement; 168 + Alcotest.test_case "TCA refinement" `Quick tca_refinement; 169 169 Alcotest.test_case "Pc requires covariance" `Quick 170 - test_pc_requires_covariance; 170 + pc_requires_covariance; 171 171 ] ); 172 172 ]