Add live-tunable GPS solver highway weight

This commit is contained in:
2026-06-26 23:33:20 -05:00
parent 3fa723c3cc
commit 92287bd8e1
12 changed files with 363 additions and 43 deletions
+44 -14
View File
@@ -980,32 +980,62 @@ the original symptom: the solver is weighted enough to avoid obviously invalid
surfaces, but it has no strong reason to stay on highway corridors for long
vehicle trips.
The current RED4ext prototype therefore hooks `0x40bb40` and only changes
driving-mode calls (`solver/job + 0xc4 == 2`). It reads flags from
`node+0x88`, leaves vanilla results intact for ordinary roads and unknown
surfaces, and applies this diagnostic multiplier set:
The first RED4ext prototype tried to hook `0x40bb40` as a normal C++ detour.
That found the correct function but crashed during load-time GPS warmup because
the optimized caller expects the tiny vanilla helper not to disturb volatile
register state used immediately afterward.
The stable prototype now patches inline at the road-tail block `0x40bb98`
instead. Reaching that block already means the vanilla function selected one of
the road-style modes `0/2/4`; pedestrian mode `1` uses a different branch. The
patch preserves vanilla `node+0x93` behavior, checks `node+0x88 & 0x4000`, and
applies an extra multiplier only for highway lanes.
The proof multiplier was:
```text
Highway 0.35
GPSOnly 1.10
Pavement 1.25
Other 1.00
```
`0x40bb00` is currently hooked only for signature logging. If the node
multiplier test moves routes but produces weird reverse/turnaround behavior,
the next step is to tune or gate the auxiliary multiplier as well.
Live A/B testing confirmed this is the decisive world-map route-cost lever.
With `0.35`, routes visibly changed and a custom pin around the city-center
roundabout took an obviously bad highway/ramp hairpin. With the inline patch
disabled, the same route returned to the straight vanilla path through the
roundabout.
The current installed build uses a default highway multiplier of `0.80` and
hot-reloads `solver_weights.bin` from the plugin directory. The file is exactly
one little-endian float32. `tools/write_solver_weights.py` writes the installed
file and can generate named presets:
```text
vanilla 1.00
mild 0.90
default 0.80
strong 0.70
proof-highway-cheap 0.35
highway-expensive 3.00
```
The patch intentionally does not hard-gate on `solver+0xc4 == 2`, because
autodrive-like local vehicle navigation may use another road-style mode. Since
the patch lives in the vanilla road-tail branch, it applies to road-style modes
`0/2/4` and still leaves pedestrian mode `1` alone.
`0x40bb00` is not patched yet. If tuned highway weights still produce
reverse/turnaround artifacts, inspect or patch that auxiliary multiplier so
reverse/special progress branches receive a compatible policy.
## Future Improvements
Better versions of this mod could:
- tune the `0x40bb40` solver multiplier after live A/B testing confirms visible
route changes
- tune the `0x40bb98` inline highway multiplier from the current `0.80` default
using live `solver_weights.bin` presets
- inspect and, if needed, patch `0x40bb00` so reverse/special progress branches
receive the same road-class policy as forward expansion
- add a tiny live-tuning file for the solver multipliers, similar to the earlier
`spatial_weights.bin`, once the hook is confirmed stable
- extend `solver_weights.bin` beyond one highway float only if GPSOnly/pavement
tuning becomes necessary
- replace the crashing `0x8d46cc` detour with a narrower inline patch or a
safer caller-side hook
- decode enough of the `VAND` graph to join navigation points to traffic lane