Chris773 commited on
Commit
7cc3e28
·
verified ·
1 Parent(s): 2508e40

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -20
app.py CHANGED
@@ -4,7 +4,7 @@
4
  # Guided scenarios (ACTIVE):
5
  # A) Straight heading
6
  # B) Variable heading & speed (beam search, BTO-first)
7
- # C) Variable heading & speed (SE bias after 22:40) (beam search, BTO-first + tiny east bias only after 22:40)
8
  #
9
  # Key behavior:
10
  # - Last radar spot FIXED: 18:22:00Z @ 6.578N, 96.341E
@@ -22,9 +22,9 @@
22
  # PERFORMANCE:
23
  # - Straight heading mode keeps Top-K polish.
24
  # - Variable heading & speed uses beam search and skips polish by default (much faster).
25
- # - SE mode reuses the same beam search, but only AFTER 22:40 adds a tiny penalty
26
- # for "westward" heading increases, nudging the solution slightly toward the east
27
- # while keeping BTO as the primary objective.
28
 
29
  import os
30
  import re
@@ -142,13 +142,18 @@ VAR_HEADING_DELTA_SET = [-6, -3, 0, 3, 6] # candidate changes per segment (deg)
142
  VAR_BEAM_WIDTH = 12 # keep top-N partial paths each segment
143
  VAR_SMOOTH_PENALTY_US_PER_DEG = 1.5 # small penalty to avoid wiggles (still BTO-first)
144
 
145
- # ===== SE-bias-after-22:40 (new mode) =====
146
  # Only applied to the last two segments (22:40→00:10, 00:10→00:20).
147
- # Penalty is applied ONLY when heading increases (more west-of-south),
148
- # nudging solutions to be slightly more east while keeping BTO primary.
149
- SE_EAST_DIVERGE_START_SEG_INDEX = 4 # segment indices: 0..5 ; seg 3 ends at 22:40, seg 4 starts after 22:40
150
- SE_VAR_EAST_DELTA_SET = [-8, -4, -2, 0, 2] # prefer small decreases (eastward) after 22:40
151
- SE_EAST_BIAS_PENALTY_US_PER_DEG = 0.8 # small; BTO still dominates
 
 
 
 
 
152
 
153
  # Search area colors (optional)
154
  SEARCH_AREA_COLORS = {
@@ -1650,9 +1655,15 @@ def _solve_guided_variable_core(method, alt_ft, vs_fpm, descent_start_choice, se
1650
 
1651
  # choose heading deltas:
1652
  # - normal: VAR_HEADING_DELTA_SET for all segments
1653
- # - SE mode: after 22:40 (segments 4 and 5), use SE_VAR_EAST_DELTA_SET
1654
  use_se_bias = bool(se_bias_after_2240 and seg_i >= SE_EAST_DIVERGE_START_SEG_INDEX)
1655
- delta_set = SE_VAR_EAST_DELTA_SET if use_se_bias else VAR_HEADING_DELTA_SET
 
 
 
 
 
 
1656
 
1657
  for st in beam:
1658
  h_prev = float(st["h_prev"])
@@ -1660,8 +1671,14 @@ def _solve_guided_variable_core(method, alt_ft, vs_fpm, descent_start_choice, se
1660
  cand_h = []
1661
  for d in delta_set:
1662
  h_try = h_prev + float(d)
1663
- h_try = _clamp(h_try, VAR_HEADING_MIN, VAR_HEADING_MAX)
1664
  cand_h.append(h_try)
 
 
 
 
 
 
1665
  cand_h = sorted(list({round(x, 6): x for x in cand_h}.values()))
1666
 
1667
  for h_try in cand_h:
@@ -1684,7 +1701,7 @@ def _solve_guided_variable_core(method, alt_ft, vs_fpm, descent_start_choice, se
1684
  abs_err = 0.0 if meas is None or (err_seg != err_seg) else abs(float(err_seg))
1685
  smooth_pen = abs(float(h_try) - float(h_prev)) * VAR_SMOOTH_PENALTY_US_PER_DEG
1686
 
1687
- # SE bias only AFTER 22:40: penalize heading increases (more west-of-south)
1688
  east_bias_pen = 0.0
1689
  if use_se_bias:
1690
  dh = float(h_try) - float(h_prev)
@@ -1782,13 +1799,14 @@ def _solve_guided_variable_core(method, alt_ft, vs_fpm, descent_start_choice, se
1782
  ]
1783
  else:
1784
  report_lines = [
1785
- "**Guided mode: Variable heading & speed (SE bias after 22:40) + computed turn (18:22→18:40), clipped to 00:20**",
1786
- "- Solver mode: **BTO-first ring-fit (beam search) + tiny east bias after 22:40**",
1787
  f"- Turn speed: **{best_global_info['v_turn']:.2f} kt** (range {TURN_SPEED_MIN_KT:.0f}–{TURN_SPEED_MAX_KT:.0f})",
1788
  f"- Beam width: **{VAR_BEAM_WIDTH}**",
1789
  f"- Normal heading deltas (pre-22:40): **{VAR_HEADING_DELTA_SET}°**",
1790
- f"- SE heading deltas (post-22:40): **{SE_VAR_EAST_DELTA_SET}°**",
1791
- f"- Smooth penalty: **{VAR_SMOOTH_PENALTY_US_PER_DEG:.2f} µs/deg** | East-bias penalty: **{SE_EAST_BIAS_PENALTY_US_PER_DEG:.2f} µs/deg** (only if heading increases after 22:40)",
 
1792
  "",
1793
  "**Per-segment heading & speed:**",
1794
  f"- 18:40→19:40: **{hs[0]:.2f}°**, **{vs[0]:.2f} kt** (end err {es[0]:+.2f} µs)",
@@ -1803,7 +1821,7 @@ def _solve_guided_variable_core(method, alt_ft, vs_fpm, descent_start_choice, se
1803
  f"- RMSE_BTO at enforced times: **{best_global_info['rmse_bto_us']:.2f} µs**",
1804
  "",
1805
  "*If 18:40 has no measured BTO in your satLoc, it is automatically not enforced.*",
1806
- "*This mode preserves the same BTO-first behavior and only nudges the final two legs slightly east when it can do so without breaking the ring-fit.*",
1807
  ]
1808
 
1809
  return best_global_legs, "\n".join(report_lines), start_dt
@@ -1911,7 +1929,7 @@ with gr.Blocks() as demo:
1911
  f"**Southern speed bounds:** {SOUTH_SPEED_MIN_KT:.0f}–{SOUTH_SPEED_MAX_KT:.0f} kt\n"
1912
  f"**Straight mode:** Top-K polish (top-{TOPK_POLISH})\n"
1913
  f"**Variable mode:** beam search (width {VAR_BEAM_WIDTH})\n"
1914
- f"**SE mode:** same beam search, but adds a tiny east bias only after 22:40"
1915
  )
1916
 
1917
  guided_mode = gr.Dropdown(
 
4
  # Guided scenarios (ACTIVE):
5
  # A) Straight heading
6
  # B) Variable heading & speed (beam search, BTO-first)
7
+ # C) Variable heading & speed (SE after 22:40) (beam search, BTO-first + HARD heading band 175–180 after 22:40)
8
  #
9
  # Key behavior:
10
  # - Last radar spot FIXED: 18:22:00Z @ 6.578N, 96.341E
 
22
  # PERFORMANCE:
23
  # - Straight heading mode keeps Top-K polish.
24
  # - Variable heading & speed uses beam search and skips polish by default (much faster).
25
+ # - SE mode reuses the same beam search, but from 22:40 onward it HARD-CONSTRAINS
26
+ # the last two leg headings into 175–180° (more southeast), with an optional tiny
27
+ # penalty for heading increases within that band.
28
 
29
  import os
30
  import re
 
142
  VAR_BEAM_WIDTH = 12 # keep top-N partial paths each segment
143
  VAR_SMOOTH_PENALTY_US_PER_DEG = 1.5 # small penalty to avoid wiggles (still BTO-first)
144
 
145
+ # ===== SE-after-22:40 (HARD CONSTRAINT mode) =====
146
  # Only applied to the last two segments (22:40→00:10, 00:10→00:20).
147
+ # We constrain headings into a SE band so the path *must* go more east after 22:40.
148
+ SE_EAST_DIVERGE_START_SEG_INDEX = 4 # seg indices: 0..5 ; seg 4 starts after 22:40
149
+ SE_POST2240_HDG_MIN = 175.0
150
+ SE_POST2240_HDG_MAX = 180.0
151
+
152
+ # Candidate deltas for post-22:40 segments: allow stronger "eastward" moves (lower heading)
153
+ SE_VAR_EAST_DELTA_SET = [-16, -12, -8, -6, -4, -2, 0, 2]
154
+
155
+ # Optional tiny penalty if heading increases after 22:40 (nudges toward the lower end of the band)
156
+ SE_EAST_BIAS_PENALTY_US_PER_DEG = 0.8
157
 
158
  # Search area colors (optional)
159
  SEARCH_AREA_COLORS = {
 
1655
 
1656
  # choose heading deltas:
1657
  # - normal: VAR_HEADING_DELTA_SET for all segments
1658
+ # - SE mode: after 22:40 (segments 4 and 5), HARD clamp heading into [175, 180]
1659
  use_se_bias = bool(se_bias_after_2240 and seg_i >= SE_EAST_DIVERGE_START_SEG_INDEX)
1660
+
1661
+ if use_se_bias:
1662
+ delta_set = SE_VAR_EAST_DELTA_SET
1663
+ lo_h, hi_h = float(SE_POST2240_HDG_MIN), float(SE_POST2240_HDG_MAX)
1664
+ else:
1665
+ delta_set = VAR_HEADING_DELTA_SET
1666
+ lo_h, hi_h = float(VAR_HEADING_MIN), float(VAR_HEADING_MAX)
1667
 
1668
  for st in beam:
1669
  h_prev = float(st["h_prev"])
 
1671
  cand_h = []
1672
  for d in delta_set:
1673
  h_try = h_prev + float(d)
1674
+ h_try = _clamp(h_try, lo_h, hi_h)
1675
  cand_h.append(h_try)
1676
+
1677
+ # ensure band edges are always possible candidates in SE mode
1678
+ if use_se_bias:
1679
+ cand_h.append(lo_h)
1680
+ cand_h.append(hi_h)
1681
+
1682
  cand_h = sorted(list({round(x, 6): x for x in cand_h}.values()))
1683
 
1684
  for h_try in cand_h:
 
1701
  abs_err = 0.0 if meas is None or (err_seg != err_seg) else abs(float(err_seg))
1702
  smooth_pen = abs(float(h_try) - float(h_prev)) * VAR_SMOOTH_PENALTY_US_PER_DEG
1703
 
1704
+ # Optional tiny penalty in SE band: penalize heading increases (less SE)
1705
  east_bias_pen = 0.0
1706
  if use_se_bias:
1707
  dh = float(h_try) - float(h_prev)
 
1799
  ]
1800
  else:
1801
  report_lines = [
1802
+ "**Guided mode: Variable heading & speed (SE after 22:40) + computed turn (18:22→18:40), clipped to 00:20**",
1803
+ "- Solver mode: **BTO-first ring-fit (beam search) + HARD SE heading band after 22:40**",
1804
  f"- Turn speed: **{best_global_info['v_turn']:.2f} kt** (range {TURN_SPEED_MIN_KT:.0f}–{TURN_SPEED_MAX_KT:.0f})",
1805
  f"- Beam width: **{VAR_BEAM_WIDTH}**",
1806
  f"- Normal heading deltas (pre-22:40): **{VAR_HEADING_DELTA_SET}°**",
1807
+ f"- Post-22:40 heading band: **[{SE_POST2240_HDG_MIN:.1f}°, {SE_POST2240_HDG_MAX:.1f}°]**",
1808
+ f"- Post-22:40 deltas (inside band): **{SE_VAR_EAST_DELTA_SET}°**",
1809
+ f"- Smooth penalty: **{VAR_SMOOTH_PENALTY_US_PER_DEG:.2f} µs/deg** | Optional increase-penalty: **{SE_EAST_BIAS_PENALTY_US_PER_DEG:.2f} µs/deg**",
1810
  "",
1811
  "**Per-segment heading & speed:**",
1812
  f"- 18:40→19:40: **{hs[0]:.2f}°**, **{vs[0]:.2f} kt** (end err {es[0]:+.2f} µs)",
 
1821
  f"- RMSE_BTO at enforced times: **{best_global_info['rmse_bto_us']:.2f} µs**",
1822
  "",
1823
  "*If 18:40 has no measured BTO in your satLoc, it is automatically not enforced.*",
1824
+ "*SE mode guarantees 175–180° from 22:40 onwards (more southeast). If this makes BTO worse, widen the band slightly.*",
1825
  ]
1826
 
1827
  return best_global_legs, "\n".join(report_lines), start_dt
 
1929
  f"**Southern speed bounds:** {SOUTH_SPEED_MIN_KT:.0f}–{SOUTH_SPEED_MAX_KT:.0f} kt\n"
1930
  f"**Straight mode:** Top-K polish (top-{TOPK_POLISH})\n"
1931
  f"**Variable mode:** beam search (width {VAR_BEAM_WIDTH})\n"
1932
+ f"**SE mode:** beam search + HARD heading band **{SE_POST2240_HDG_MIN:.0f}–{SE_POST2240_HDG_MAX:.0f}°** from 22:40 onwards"
1933
  )
1934
 
1935
  guided_mode = gr.Dropdown(