Skip to content

Repository files navigation

🚗 Drivelink Software

Machine-learning decision-making for autonomous traffic agents. Drivelink trains lightweight RandomForest models that decide when a car should change lanes, take an exit, or negotiate a merge, and serves those decisions in real time over WebSocket to a Godot driving simulation.

The repo has two halves:

  1. Real-time ML backend (repo root) — trains the models, loads them, and exposes them to the Godot game client over a simple WebSocket protocol. This is what runs during gameplay.
  2. Research simulation (sim/) — runs the same models as a vehicle policy inside SUMO (validated IDM + LC2013 dynamics) and measures how realistic the resulting traffic is against real-world trajectory data. This is the "defensible realism" path for research/product claims.

Architecture

            ┌──────────────────────────── REAL-TIME PATH (gameplay) ───────────────────────────┐

   train_models.py  ──►  models/*.pkl  ──►  model_manager.py  ──►  ml_server.py  ──►  Godot client
   (generate data,       (persisted        (load models,         (WebSocket         (Car.gd / MLClient.gd
    fit & save once)      RandomForests)     validate input,       server on          send car_state, act on
                                             predict)              ws://:8765)         MERGE / WAIT decisions)

            └──────────────────────────────────────────────────────────────────────────────────┘

            ┌──────────────────────────── RESEARCH PATH (validation) ──────────────────────────┐

   SUMO (IDM + LC2013)  ──►  sim/state_mapping  ──►  sim/policy (reuses ModelManager)  ──►  sim/runner
        realistic dynamics      SUMO vehicle →           car_state → MERGE / WAIT             steps sim,
                                Drivelink car_state                                            records trajectories
                                                                                                     │
                                              sim/metrics + sim/validate  ◄───────────────────────────┘
                                              realism metrics vs real data (HighD / NGSIM)

            └──────────────────────────────────────────────────────────────────────────────────┘

The ML models, model_manager.py, and the WebSocket server are shared unchanged between both paths — the research harness imports ModelManager directly rather than reimplementing inference.


The models

All three models are RandomForestClassifiers that take the same 5 features and output a binary act / don't-act decision plus a calibrated confidence.

Model File Decision Trained on
Lane change models/model_lane_change.pkl MERGE / WAIT general lane-changing in a multi-lane flow
Turning (exit) models/model_turning.pkl MERGE / WAIT reaching an exit lane before the exit
V2V chat models/model_v2v_chat.pkl NEGOTIATE_MERGE / HOLD_POSITION cooperative merge where the neighbour yields a slightly smaller gap

How the training data is generated

Rather than learning from hidden ground truth, the models are trained on what a car actually perceives — a coherent perception-based agent. Each model is fit on a small micro-simulation (train_models.py) where vehicles decide using the rule:

Move toward the target lane when the move is needed (rel_target ≠ 0), the perceived gap is large enough for this driver's aggressiveness, and there is enough urgency (or the driver is very aggressive).

perceived_gap is a continuous distance in metres matching exactly what the Godot client (Car.gd) sends at runtime, with a small Gaussian perception jitter so the returned confidence stays smooth and well-calibrated. This removes the artificial noise ceiling of the old random-data approach and yields a clean decision boundary (~0.99 held-out accuracy).

Feature definitions

Feature Type Range Description
speed float 0–25 m/s Current velocity
urgency float 0–1 How critical the maneuver is (0 = relaxed, 1 = critical)
aggressiveness float 0–1 Driver personality (0 = cautious, 1 = aggressive)
rel_target int −2…+2 Lanes to target relative to current (−1 = left, +1 = right)
perceived_gap float 0–40 m Distance to nearest car in the target lane. ~5 m = tight, >10 m = comfortable, 40 = clear road. Larger ⇒ more likely to merge.

Missing features are filled with safe defaults and coerced to numeric, so partial or loosely-typed payloads from the game client never crash the server.


Quick start

# 1. Install backend dependencies
pip install -r requirements.txt

# 2. Train and persist all three models (one-time; writes models/*.pkl)
python train_models.py

# 3. Start the WebSocket server for Godot
python ml_server.py
#    → Drivelink ML WebSocket Server started on ws://0.0.0.0:8765

# 4. (optional) Verify it works from another terminal
python test_client.py

Server configuration (environment variables)

Variable Default Purpose
DRIVELINK_HOST 0.0.0.0 Interface to bind
DRIVELINK_PORT 8765 Port to listen on
DRIVELINK_PORT=9999 python ml_server.py

The server logs structured messages, handles each message in isolation (one bad request never kills the connection), and shuts down cleanly on Ctrl+C / SIGTERM.


WebSocket API

Connect to ws://<host>:<port> and exchange JSON messages. The wire protocol is stable so the existing Godot MLClient keeps working.

Single prediction

Request

{
  "type": "predict_lane_change",
  "car_state": {
    "speed": 15.5,
    "urgency": 0.75,
    "aggressiveness": 0.85,
    "rel_target": 1,
    "perceived_gap": 15
  }
}

type may be predict_lane_change, predict_turning, or predict_v2v.

Response

{
  "type": "prediction",
  "scenario": "lane_change",
  "result": {
    "decision": "MERGE",
    "confidence": 0.92,
    "model": "lane_change",
    "raw_prediction": 1,
    "target_lane": 3
  }
}

Batch prediction

{
  "type": "batch_predict",
  "scenario": "lane_change",
  "car_states": [
    {"speed": 12, "urgency": 0.3, "aggressiveness": 0.7, "rel_target": 1,  "perceived_gap": 18},
    {"speed": 18, "urgency": 0.8, "aggressiveness": 0.9, "rel_target": -1, "perceived_gap": 3}
  ]
}

Utility messages

Request Response Purpose
{"type": "get_models"} {"type": "models_info", "models": {...}} Metadata about loaded models
{"type": "ping"} {"type": "pong", "status": "alive"} Health check

Any unknown or malformed request returns {"error": "..."} instead of dropping the connection.

For full GDScript integration examples, see GODOT_INTEGRATION.md.


Research simulation (sim/)

Runs the Drivelink models as a decision policy on top of validated SUMO dynamics and validates the result against real trajectory data. See sim/README.md for full details.

pip install -r sim/requirements.txt          # SUMO ships in the eclipse-sumo wheel

# Highway forced-merge with the ML policy, validated against the SUMO baseline
python -m sim.run --scenario highway --mode ml --validate

# Urban signalised grid, ML turning policy
python -m sim.run --scenario urban --mode ml --validate

# Watch it live
python -m sim.run --scenario urban --mode ml --gui
Scenario Network Models exercised
highway 3-lane freeway dropping to 2 lanes (forced merging) lane-change
urban signalised 3×3 grid with turning demand turning

Outputs land in sim/runs/: trajectory CSVs, a JSON realism report, and a figure overlaying simulated vs reference distributions. Realism is scored with KS statistic and Wasserstein distance across speed, time headway, time-to-collision, gap acceptance, and the fundamental diagram. To validate against real data (HighD / NGSIM), pass --reference highd --reference-path /path/to/tracks.csv.


Repository layout

.
├── train_models.py        # Generate data, train & persist all 3 models
├── model_manager.py       # Load models, validate input, run inference
├── ml_server.py           # WebSocket server (env-configurable host/port)
├── test_client.py         # Python client exercising every request type
├── requirements.txt       # Backend dependencies
├── models/                # Persisted RandomForests + feature lists (*.pkl)
├── GODOT_INTEGRATION.md   # GDScript usage, feature reference, troubleshooting
│
├── sim/                   # SUMO research simulation + real-data validation
│   ├── run.py             #   CLI entry point  (python -m sim.run ...)
│   ├── runner.py          #   steps SUMO, applies decisions, records trajectories
│   ├── policy.py          #   reuses ModelManager as the lane-change policy
│   ├── state_mapping.py   #   SUMO vehicle → Drivelink car_state
│   ├── metrics.py         #   realism metrics (KS / Wasserstein)
│   ├── validate.py        #   compares simulated vs reference trajectories
│   ├── datasets.py        #   HighD / NGSIM column mappings
│   ├── scenarios/         #   highway + urban SUMO networks (+ builder)
│   └── requirements.txt   #   SUMO + scipy + matplotlib (+ core ML deps)
│
├── Scripts/, Scripts_All/ # Godot-side GDScript (Car.gd, MLClient.gd, HUD.gd, …)
└── traffic_*.py, dataset_lane.py   # Legacy standalone experiments (superseded
                                    # by train_models.py; kept for reference)

Requirements

  • Python 3.9+
  • Backend: numpy, pandas, scikit-learn, joblib, websockets (see requirements.txt)
  • Research sim (optional): eclipse-sumo, libsumo, traci, sumolib, scipy, matplotlib (see sim/requirements.txt) — SUMO ships inside the eclipse-sumo wheel, so no system install is needed.

Troubleshooting

Symptom Fix
No models loaded on startup Run python train_models.py first; confirm models/*.pkl exist
Port already in use Start with a different port: DRIVELINK_PORT=9999 python ml_server.py
Godot can't connect Ensure the server is running and the URL matches; use the host IP instead of localhost if the game runs on another machine
sklearn feature-name warnings Already fixed — models are trained and served on named DataFrame columns

Note on line endings: the tracked Python files use CRLF. When applying patches to this repo, prefer git apply with the original (CRLF) patch — git am strips the carriage returns during mail parsing and the patch will fail to apply.

About

DriveLink — V2V communication ML/software layer: RandomForest intent prediction + SUMO validation for the DriveLink protocol

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages