-
Notifications
You must be signed in to change notification settings - Fork 3
AI Driver and Recovery
TaxiDriver AI Driver is an adapter around BeamNG's built-in vehicle AI. TaxiDriver selects and validates the route, starts ai.driveUsingPath, observes traffic, controls the pickup hand-off, and verifies that the gameplay target was actually reached. BeamNG remains responsible for steering, lane following, ordinary obstacle avoidance, traffic-light behavior, throttle, braking and gearbox operation.
The 4.0.0 RC architecture, guarded overtaking/evasion, performance budget, and BeamNG 0.39 integration are documented separately in AI Driver Engine 0.39.
AI Driver is experimental. Its behavior still depends on the active map graph, BeamNG traffic AI, vehicle controllers and community content. It is intended for assisted gameplay and testing, not as a guarantee of human-level autonomous driving.
AI Driver is disabled by default. Open Settings → AI Driver and use the master switch. The first enable attempt opens an explicit experimental-feature warning; accepting it reveals the profiles and adds the AI Driver button to active route maps.
While the switch is off, the button is not rendered and the Lua API rejects activation. Turning the master switch off, or pressing the active route button to take control back, immediately disables native AI, releases temporary brake/parking inputs, and restores the player's gearbox behavior. It does not force Park while the vehicle is still moving. Verified route completion, cancellation, no-show, and other route-ending gameplay transitions continue to use the stationary Park/Neutral plus parking-brake hand-off.
The page name retains “Recovery” for compatibility with existing Wiki links. In the current implementation recovery means bounded native-route replanning. The previous local free-space planner, custom bypass controller, reverse-ray recovery and world decision visualizer are no longer part of the active AI runtime.
flowchart LR
Trip["TaxiDriver trip target"] --> Supervisor["autopilot.lua"]
GPS["BeamNG ground-marker route"] --> Supervisor
Graph["BeamNG road graph"] --> Supervisor
Supervisor --> Native["Vehicle ai.driveUsingPath"]
Native --> Vehicle["Player vehicle"]
Traffic["Tracked traffic vehicles"] --> Guard["taxiDriverStockAiObserver"]
Vehicle --> Guard
Guard --> Speed["Smooth temporary speed limit"]
Speed --> Native
Native --> Done["Native Route Done"]
Done --> Supervisor
Supervisor --> Check{"Inside physical target?"}
Check -->|yes| Gameplay["Board / load / complete leg"]
Check -->|no| Replan["Rebuild from current road segment"]
Replan --> Native
| Component | Responsibility |
|---|---|
autopilot.lua |
Player identity, route selection, native-AI lifecycle, physical arrival verification and bounded replanning |
taxiDriverStockAiObserver.lua |
Following gap, steering-arc traffic prediction, target-aligned final braking and protected Route Done observation |
physicalPickup.lua |
Optional delivery cargo prop and cargo pickup completion |
taxiDriverTelemetry.lua |
Vehicle telemetry, forced-stop inputs and observer diagnostics |
fleetWorker.lua |
Reduced-cost native routing and bounded job recovery for one hired vehicle |
aiLogger.lua |
Optional streaming JSONL records for route, traffic, drivetrain, damage and lifecycle events |
Only the current primary player vehicle may receive the player AI route. The supervisor compares the requested object with be:getPlayerVehicleID(0) before every native route command.
This boundary prevents three earlier failure modes:
- a stale callback cannot command a destroyed vehicle VM;
- a Fleet or traffic vehicle ID cannot replace the player's active AI target;
- the player vehicle cannot be processed through NPC traffic lifecycle logic.
ai.setRecoverOnCrash(false) is enforced for the player. BeamNG normally permits traffic AI to use safe teleport when an NPC is stuck. That behavior is unsuitable for the player because a deliberate stop for boarding may look like a stuck traffic vehicle and can relocate or reset the active trip.
AI Driver has two route-selection modes. The mode is independent from the aggression preset.
This is the default.
- TaxiDriver resolves the road edge that contains the pickup, stop, destination or fuel target.
- The target direction determines the legal approach node and departure node.
- The current vehicle heading determines the directed road edge on which the search begins.
- A shortest-path search runs in directed-edge state
(previousNode, currentNode). - Immediate reversal to
previousNodeis forbidden. - One-way metadata is respected.
- The target departure node is appended so native AI crosses the target edge in the intended direction.
The directed-edge state is important. A node-only path can reach the correct junction from the wrong side and ask native AI to make an immediate U-turn across opposing traffic.
For a candidate transition from state (p, v) to (v, u), the accumulated cost is:
C(v, u) = C(p, v) + max(0.1, edgeLength(v, u))
The transition is rejected when u = p or when BeamNG marks (v, u) as the forbidden direction of a one-way edge.
When Strict GPS route is enabled, TaxiDriver reads the ordered road-node sequence from core_groundMarkers.routePlanner.path and sends that exact sequence to native AI.
Coordinate-only start/end entries are discarded. Only entries containing a valid waypoint ID are serialized. This prevents invalid strings such as table: 0x... from reaching BeamNG's ai.lua.
flowchart TD
Toggle{"Strict GPS enabled?"} -->|no| Legal["Directed legal route"]
Toggle -->|yes| Read["Read displayed ground-marker path"]
Read --> Valid{"At least two waypoint IDs?"}
Valid -->|yes| Exact["Send exact GPS node order"]
Valid -->|no| Legal
Reroute["BeamNG recalculates GPS"] --> Dirty["Mark AI route dirty"]
Dirty --> Read
Strict GPS affects path choice, not steering. BeamNG AI may still move within the road geometry to avoid traffic or complete a turn. If the displayed route cannot be read during a transient recalculation, TaxiDriver falls back to the legal autonomous route rather than disabling AI.
Before starting a route, TaxiDriver:
- unloads any legacy custom recovery controller;
- loads
taxiDriverStockAiObserver; - enables native obstacle avoidance;
- enables lane following where required;
- applies the selected aggression, traffic-wait and legal-speed settings;
- disables player safe-teleport recovery;
- starts
ai.driveUsingPathwith the selected node list.
The native route remains authoritative for steering. The traffic guard never writes steering input.
BeamNG Route Done means that native AI considers its graph path complete. It does not prove that the TaxiDriver trigger was reached.
TaxiDriver therefore measures physical distance to the current target:
d = length(vehiclePosition - targetPosition)
If d exceeds the gameplay arrival radius, the completion is classified as premature. The route is immediately rebuilt from the current road segment. A maximum of three premature-completion retries prevents an infinite loop on an unreachable target.
Version 4.0.2 also bounds a native asynchronous route request to 12 seconds. If BeamNG's planner job never returns, TaxiDriver classifies the request as failed and enters the existing retry or parking recovery path instead of leaving AI Driver indefinitely unavailable.
At the final passenger or cargo destination, a verified native completion
hands the vehicle to BeamNG's stop mode. BeamNG finishes braking, applies the
parking brake below its stationary threshold, restores the normal gearbox mode,
and disables AI. Entering dispatcher search after a cancellation, no-show, or
other route-ending event performs the same parked handoff, so an empty order
pool cannot leave the previous free-driving command active.
stateDiagram-v2
[*] --> Planning
Planning --> Driving: Native route issued
Driving --> Planning: GPS recalculated
Driving --> RouteDone: BeamNG reports Route Done
RouteDone --> Planning: Outside target and retries remain
RouteDone --> Waiting: Outside target and retry limit reached
RouteDone --> Arrived: Physical target reached
Driving --> Paused: UI / Vehicle Config suspension
Paused --> Planning: Resume
Driving --> Off: Player takes control
Arrived --> Off: Gameplay leg changes
Final-target speed limiting is enabled only when the vehicle heading agrees with the target-side road direction. The car is not asked to stop early on the opposite side of the road merely because its Euclidean distance to the target is small.
AI Driver captures the player's original Arcade/Realistic gearbox behavior when the AI session begins. The value is restored whenever control is returned. Parking commands are scoped by AI session ID; they no longer reject a valid same-session command merely because a failed route attempt incremented the GE-side route revision before Vehicle Lua received a replacement route.
Every parking failure path clears its pending parking transaction. A missing vehicle, rejected command, lost vehicle during parking, or explicit player hand-back therefore cannot leave the AI toggle permanently trapped in a disabled-but-parking state. These fixes originate from the investigation by JamDaBam in issue #5.
Native BeamNG AI handles ordinary avoidance, but it can follow too closely or miss a vehicle that enters the swept path during a turn. taxiDriverStockAiObserver adds a speed-only safety layer.
Nearby tracked vehicles are projected into the ego vehicle's forward and lateral axes. A vehicle becomes a lead candidate only when it is ahead and overlaps the current body-width corridor.
Let:
-
vbe ego speed; -
v_lbe lead speed; -
deltaV = max(0, v - v_l)be closing speed; -
Tbe configured following time; -
g_minbe configured minimum bumper gap; -
a_cbe comfortable deceleration.
The desired gap is:
g_desired = g_min + v * T + deltaV^2 / (2 * a_c)
The observer starts limiting speed when the measured gap is below g_desired or the time to collision becomes short:
TTC = gap / deltaV
The requested deceleration rises with the gap deficit, but its rate of change is limited. The active speed cap is integrated using a jerk limit of 2.5 m/s^3:
a_next = approach(a_current, a_requested, jerkLimit * dt)
v_limit_next = max(v_desired, v_limit - a_next * dt)
When the path clears, the temporary limit is released progressively. Full immediate braking is used only when TTC < 0.55 s or the required physical deceleration reaches 8.5 m/s^2.
This distinction prevents ordinary distant traffic from producing repeated full-brake pulses.
A straight corridor does not cover the outside corner of a turning vehicle. When steering magnitude is significant, the observer predicts the ego centre along the current turn radius and compares it with short-term motion of nearby vehicles.
The player observer samples twelve points at 100 ms intervals. For sample time t, the approximate ego position in vehicle coordinates is:
yaw(t) = min(1.45, v * t / turnRadius)
forward(t) = sin(yaw(t)) * turnRadius
lateral(t) = turnSide * (1 - cos(yaw(t))) * turnRadius
The closest predicted separation is reduced by the bounding radii of both vehicles. A small remaining clearance becomes a curved-path lead candidate and uses the same smooth braking model.
Passenger pickup is logical in 4.0.0 RC. It no longer spawns a walking unicycle dummy and does not require a horn sequence.
AI pickup requires all of the following:
- the vehicle is within the dedicated 10-metre passenger trigger;
- target-side direction alignment is valid;
- wheel speed is at or below the 0.5 km/h sensor tolerance;
- the AI parking hand-off has brought the vehicle to a stable stop.
Cargo can still use BeamNG's small cardboard-box vehicle. Reaching its loading radius removes the prop and continues into the existing cargo-mass system. If the prop cannot be spawned, the order falls back to the logical loading sequence.
| Setting | Balanced default | Runtime effect |
|---|---|---|
| Aggression | 40% | Native BeamNG AI aggression |
| Following time | 2.3 s | Time component of the desired traffic gap |
| Minimum distance | 4 m | Minimum bumper gap |
| Comfortable braking | 3.5 m/s² | Progressive following and arrival deceleration |
| Traffic wait | 3 s | Native AI traffic-wait parameter |
| Obey speed limits | On | Uses BeamNG legal route-speed mode |
| Lane discipline | On | Requests native lane following |
| Strict GPS route | Off | Uses displayed GPS nodes instead of autonomous legal routing |
| AI trip debug log | Off | Writes a streaming per-session JSONL journal |
The complete presets are:
| Preset | Aggression | Following time | Minimum gap | Braking | Traffic wait | Legal speed | Lane discipline |
|---|---|---|---|---|---|---|---|
| Modest Novice | 30% | 3.4 s | 7 m | 2.5 m/s² | 6 s | Yes | Yes |
| Cautious Driver | 35% | 2.8 s | 5.5 m | 3.0 m/s² | 4 s | Yes | Yes |
| Balanced | 40% | 2.3 s | 4 m | 3.5 m/s² | 3 s | Yes | Yes |
| Assertive | 50% | 1.9 s | 3.2 m | 4.2 m/s² | 2 s | Yes | Yes |
| Mad Racer | 85% | 1.3 s | 2 m | 6.0 m/s² | 1 s | No | No |
Strict GPS is deliberately independent from these presets and is preserved when the player changes temperament.
Every hired Fleet vehicle owns a separate native worker and a separate Vehicle Lua observer. It does not share target, route progress or traffic state with the player.
| Capability | Player AI Driver | Fleet worker |
|---|---|---|
| Route source | Legal directed route or strict GPS | Worker assignment route |
| Traffic observer | 100 ms | 200 ms |
| Curved trajectory samples | 12 | 6 |
| Target-aligned final braking | Yes | No player-specific target hand-off |
| Premature Route Done handling | Up to 3 immediate retries | Current-segment replan after 1 s |
| Stuck recovery | Native route reissue | Minimum 45 s, bounded replans |
| Native safe teleport | Disabled | Enabled for non-player NPC recovery |
Fleet route progress is checked every 250 ms and staggered across workers. Passed route nodes are removed before a replan. This keeps hired taxis persistent and traffic-aware without running the full player update cost for every vehicle.
AI never creates a fuel detour automatically. The player must:
- press Refuel;
- let TaxiDriver create a real or Magic Fuel route;
- enable AI from the refueling map if automatic travel is desired.
The accepted passenger or cargo order remains intact. AI stops when the station route is complete and the player chooses the amount to refuel.
Enable AI trip debug log to create:
taxidriver_ailog_<session-start-timestamp>.jsonl
The file is opened when AI control starts and is closed when the player disables AI or the game session ends. Records are flushed continuously so data before a crash remains readable.
Important records include:
- selected route source and node preview;
- target and physical distance;
- premature native completion and retry count;
- following gap, closing speed and time to collision;
- curved-path risk;
- temporary speed limit and applied deceleration;
- pickup horn stages;
- gearbox, ignition, pedals and vehicle damage;
- route stop reason.
General runtime messages remain available in beamng.log with the [TaxiDriver] prefix when general debug logging is enabled.
- Native AI may still make poor lane choices or hesitate on incomplete community-map graphs.
- Strict GPS can guarantee the requested node order, not human-like steering within every junction.
- Parked objects that BeamNG does not expose as tracked vehicles may be handled only by native obstacle avoidance or the bounded static-ray scan.
- The traffic guard controls speed only; it intentionally does not replace native steering.
- Fleet protection is lower frequency by design and prioritizes bounded CPU cost over player-level responsiveness.
- The player should take control whenever native AI cannot resolve a map, traffic or vehicle-controller edge case safely.
The stock-AI observer captures the driver's Arcade/Realistic behavior before ai.driveUsingPath changes it. A passenger forced stop temporarily holds Realistic behavior while braking, preventing Arcade's brake-to-reverse conversion. When the stop ends, telemetry restores the driver's captured behavior even if AI parking overlapped the stop. This change does not address the separate shift-recovery/flying-vehicle report.
TaxiDriver Reloaded documentation · Version 4.0.3 · BeamNG.drive 0.39
- Installation and Quick Start
- Gameplay and Ride Lifecycle
- Order Generation and Routing
- Passengers, Fares and Ratings
- Cargo Deliveries
- Realistic Refueling
- Driver Profile and Persistence
- Settings, Localization and Audio
- Navigation and Map Controls
- External Web UI
- Driver UI Design
- AI Driver Engine 0.39
- AI Driver and Recovery
- Fleet Operations
- Troubleshooting and Compatibility