# Implemented rules and research boundaries

This is a separate research simulator, not the earlier single-hub dashboard. It represents rule-based truck agents travelling between supplied hub stops on a geographic UK outline. Nodes, distances, journey times, batteries and arrivals in the example are synthetic study inputs. Named cities do not imply an actual charger installation.

## Driver rules verified on 27 October 2026 (re-checked 28 October 2026; GOV.UK page last updated 1 July 2026, no change to the modelled subset)

Primary source: [DVSA: goods vehicles, assimilated and AETR driving-hours guidance](https://www.gov.uk/guidance/drivers-hours-goods-vehicles/1-assimilated-and-aetr-rules-on-drivers-hours). The standard profile represents an in-scope single-driver HGV case with uninterrupted breaks and regular daily rest:

- No more than 270 minutes of driving between qualifying 45-minute breaks. A break can be taken earlier if the next supplied road leg would exceed the allowance.
- Standard daily driving allowance of 540 minutes, without using the permitted extensions.
- Regular daily rest of 660 minutes. With regular rest, the planner starts daily rest by 13 hours after the duty start so that it can finish within the 24-hour period. It can start earlier when the next driving leg would exceed the daily driving or duty allowance.
- Weekly and fortnight driving budgets use the supplied prior history against 56 and 90 hours. Example histories are zero; these are synthetic fresh-history assumptions.
- Queuing does not automatically qualify as a break. A rest opportunity requires parking or a connected charging bay, and its full uninterrupted duration must complete before the driving clock resets.

This implements a specified subset. It does not implement working-time rules, other work, split breaks, reduced/split daily rest, weekly rest scheduling, compensation, multi-manning, exemptions, extensions, emergency derogations, tachograph records or international case selection. History budgets do not reconstruct a full calendar-week duty schedule. It cannot certify compliance with all GB regulations. Conflicts remain visible and block dispatch rather than authorising more driving. Study mode permits custom break assumptions and must not be presented as the standard GB profile.

## Agent decision order

At each stop: check onward energy feasibility; determine driving/daily rest need; request charging only when the next-leg reserve or SOC trigger requires it; otherwise take a parking-only break or continue. Charging/rest decisions overlap where the driver is genuinely resting. At a congested charger queue, an alternate must satisfy both reserve energy and available driving time. An infeasible alternate never forces the truck away from its current hub.

The research dispatch policy sorts by inability to cover the next leg with reserve, then waiting-age protection within the energy-risk class, then lower SOC, then FIFO and stable input order. Pure FIFO and lowest-SOC policies remain selectable. Queue waiting-age and battery age are separate quantities. Charging is non-preemptive. This priority is an explicit research hypothesis, not a statutory or published universal HGV scheduling standard.

Conditional diversion uses a workload heuristic: current charging/queue energy plus committed inbound charging demand, shared hub supply, and zero-power held-bay delay. It adds diversion travel and the candidate's own charging time. Later decisions see earlier transfers. It does not predict unknown future demand or guarantee a charger reservation, and its estimate is not an exact dispatch forecast. The new route must retain a supplied link to the planned onward stop. At most two diversions per journey and no revisiting a prior diversion destination prevent indefinite diversion loops. No road-search API or geographic road routing is performed.

## Driver and bay release

Charge completion and driver-ready departure are distinct. A resting driver cannot move a truck. Moving an energy-complete truck to rest parking therefore requires an explicitly enabled authorised-mover assumption and a free parking space. Otherwise the truck holds its charging bay at zero power until rest finishes. A parking-only break does not use a charger. Full parking retains a visible rest queue; inability to start regular rest by the model deadline becomes a visible conflict.

Final-destination arrival completes the delivery metric. Subsequent end-of-duty rest is not included in journey completion. Scheduled or unfinished vehicles remain in exports, and low completion means should not be interpreted without that backlog.

## Batteries, charging and numerical method

Current usable capacity = nominal usable capacity × supplied capacity SOH. SOC is defined against that current usable capacity, so SOH is applied once. Calendar age is metadata. A separate charge-power factor derates vehicle acceptance. The short operational study does not infer a degradation law from age; longitudinal degradation would require chemistry, temperature and duty-history calibration.

Road energy = distance × supplied consumption + auxiliary power × travel duration. Required reserve is a fraction of current usable capacity. Charging uses the tested capped power-sharing calculation, constrained by vehicle acceptance, charger rating, grid supply and fixed efficiency. The journey engine uses one-minute steps, with charging allocations additionally capped by remaining required energy in that minute. State frames are recorded before that minute's energy update. Road travel times and departures use whole minutes. No taper curve, terrain, payload/weather inference, faults or waiting auxiliary drain is included.

## Evidence and geography

The project's existing literature screening informed the distinctions between charging occupancy and parking/rest, alternative-hub information, vehicle-specific range and non-guaranteed queue thresholds. Relevant supplied material includes BSI Flex 2071, Electric Freightway, HoLa and BETT; none calibrates the synthetic numeric defaults or mandates the research priority. The full local screening remains in literature_review/REVIEW.md in the project workspace; private papers are not published with this site.

Map outline: [Natural Earth](https://www.naturalearthdata.com/about/terms-of-use/), public-domain 1:50m country data. Geographic city-position markers sit on straight schematic corridor lines; these lines are not roads. Example road distances and durations are assumptions. The map is a simulation replay, not live GPS.


## Four-day studies and research comparisons

Study duration can be up to 96 hours. Daily rest resets daily driving allowance only after the entire rest completes; total driving and supplied weekly/fortnight history are retained across days. The study does not automatically reset fixed-week budgets at midnight or infer a calendar-week boundary. The supported rules scope above remains unchanged; a longer horizon is not a claim of full weekly-rest compliance.

The optional four-day demonstration schedules four independent cohorts of the example fleet, with distinct vehicle/driver identifiers and departures offset by 24 hours. These are independent arrivals, not the same physical vehicles being reset to fresh batteries and driving history each day. An individually supplied multi-stop truck continues to carry its own energy and driving history across the full study.

For studies longer than 24 hours, replay snapshots are recorded every five minutes to bound browser memory. The engine still calculates each minute. Per-hub demand/occupancy intervals and all charging-session milestones retain one-minute resolution. The map labels its snapshot interval; the demand graphs and downloads use the exact interval data, not interpolation from map snapshots. Charging power at the selected hub is looked up from those exact intervals.

Manual editors change initial study inputs, clear old results and require recomputation. They never retroactively alter an already computed vehicle state. Hub efficiency is battery energy / grid energy; vehicle charging-power factor is an acceptance cap, not efficiency. Vehicle driving consumption is specified directly in battery kWh/km.

The optional comparison runs the same input fleet under six strategies: current settings, FIFO, lowest SOC, two extra chargers with unchanged grid supply, extra chargers with proportionally expanded supply, and managed rest parking with an explicitly assumed authorised mover. Only the current-settings case drives the main map; selecting another graph case changes the evidence panel. Extra-bay cases cap installed chargers at 100. A zero-bay site's expanded-grid case uses enough supply for its new chargers, avoiding division by zero. No city's demand is ranked in advance: differences follow vehicle routes, arrivals and hub settings.

Charging history includes queued requests and diversions as well as connected sessions. It separates arrival, queue entry, charging start, energy completion, physical bay release and actual hub departure. Unreached milestones remain null. Delivered energy is retained at cutoff; pending/held sessions are marked explicitly. Sum of session battery energy equals the per-vehicle delivered-energy total; interval-integrated grid energy includes each hub's fixed losses.


## Version 1.4 additions (28 October 2026)

### What is new versus already implemented

Already implemented before 1.4 and unchanged: minute-step agents, GB standard subset, SOH-once capacity, three queue policies, bounded diversion, bay holding and authorised mover, 96-hour studies, editors, CSV import, exact power intervals and paired comparisons. 1.4 adds the items below. Everything in "Future extensions" is not implemented.

### Charger compatibility and background load

Each hub's chargers are homogeneous: one DC rating and one connector set (`connectors`, default `CCS|MCS`). Each vehicle has a connector set (default `CCS`). A vehicle may charge only where the sets intersect. If charging is required for the next leg and no compatible charger exists, the truck is blocked with an explicit `connector_blocked` reason; if only the SOC trigger fired and the next leg is still feasible with reserve, it records `charge_skipped` and continues. Diversion candidates without a compatible bay are rejected.

`background_kw` is a constant, explicitly supplied non-charging site load. Charging budget = (grid supply limit − background load) × efficiency. Reported `grid_kw` is charging demand only; "peak incl. background" and "headroom" add the background load. Background load must be below the supply limit.

### Traceable charger allocation

Every `charge_started` event records the policy, the truck's position in the ranked queue, a plain-language explanation of its rank and the next three trucks it was ranked ahead of, with their explanations. For the research policy the explanation states the next-leg energy margin, waiting age versus the ageing threshold and the SOC or queue-entry tie-breaker actually used. Map frames carry each hub's ranked queue order. Explanations are generated from the same ranking tuple used for dispatch.

### Diversion detail

Each diversion records time, truck, original hub, alternative hub, onward hub, road distance, travel time, ETA, estimated arrival SOC, the stay and alternative delay estimates, predicted saving and every candidate considered with its accept/reject reason. When a congested hub has no beneficial feasible alternative, one `diversion_rejected` event per visit lists why each candidate failed. The map draws an arrow from original to alternative hub, a dotted onward line and a short pulse at the decision time; counters distinguish diversions that have occurred by the replay time from the whole-study total.

### Shared charging with cars or other vehicles

Off by default. Car/other-vehicle arrivals are explicit inputs (`cars`: id, hub, arrival minute, energy kWh, max kW, connectors) or come from the seeded generator. With shared charging on, a car may start only if: the hub has `shared_bays` > 0 and fewer cars than that are connected; its connector is compatible; no HGV is waiting at that hub; and after it connects at least `hgv_guard_bays` bays remain free. Cars are attended: they leave on energy completion, or leave unserved after `car_max_wait_min`. Cars are never preempted and never preempt HGVs, so a car connected before an HGV arrives can delay that HGV; this is reported as "HGV wait while a car was connected". With shared charging off, car arrivals are recorded as not admitted, which keeps HGV-only and shared cases comparable on identical inputs. Car power shares the same hub budget.

### Scenario comparison

Comparison cases are now selectable: FIFO, lowest SOC, risk + waiting age, +2 chargers with the same grid, +2 chargers with explicitly scaled grid, managed rest parking with authorised mover, diversion off/on, HGV-only/shared charging, SOH × 0.9 and vehicle DC acceptance × 1.5. Every case uses the identical fleet, routes, departures and driver histories; each states exactly what changed. No case silently adds trucks, resets drivers or changes grid capacity (only the "+ grid" case changes grid supply, and says so). Arrival-level, time-profile and future-year comparisons are made by generating fleets with stated seeds and running them as separate studies.

### Seeded arrivals and 2030/2035 presets

The generator samples departures from a non-homogeneous Poisson process by thinning: rate(t) = base rate × multiplier for the clock hour (study start 08:00). It uses Python `random.Random(seed)`; the same seed and inputs reproduce the same fleet, and the full specification is saved under `generator` in the study JSON. Class, route, initial SOC and SOH are sampled independently per truck; driving history starts at zero. Generation replaces the fleet only when the user presses Generate and the study must then be rerun. Presets for 2025, 2030 and 2035 set vehicle classes and, separately on request, hub charger rating, connectors and efficiency. Their sources and the parts that are illustrative assumptions are listed in the evidence register (EVIDENCE.md). They are scenarios, not predictions.

### Observed (imported or live) vehicles

Observations are a separate layer: they never move simulated trucks or feed the engine. Each observation needs vehicle ID, ISO 8601 timestamp with timezone and latitude/longitude; SOC, next hub and an ETA with its stated source are optional. Observations are classified fresh, stale (older than the chosen age), future-dated (more than 2 minutes ahead of the device clock) or invalid (missing fields, out-of-range SOC, position outside the GB map). Only fresh and stale observations are drawn, with stale ones greyed. No ETA is calculated without a supplied routing-provider value. The optional live connector polls an https JSON endpoint every 30 s while visible, without cookies, refusing credentials, query strings and redirects; a failure disconnects and removes old observations. No API secret is stored in the site.

### Outputs

Network wait mean/p50/p95/max over started sessions, trucks still queued at cutoff, blocked/conflict list with reasons, peak charging and peak including background load, minimum headroom, held-bay minutes, peak rest-parking occupancy, charging-bay versus occupied-bay utilisation, car sessions and energy. Exports add the decision record, diversions, all-hub demand and all-hub sessions CSVs and an inputs-only JSON.

## Agent architecture and future AI

- **Vehicle agents** follow the programmed rules above (energy feasibility, driver hours, charge/rest/continue, diversion). They do not learn or use a language model.
- **Hub/resource management** allocates bays, rest parking and shared power with the selected non-preemptive policy.
- **Scenario/orchestration layer** (this website) validates inputs, runs paired cases and exports results.
- **Future LLM layer (not implemented):** may translate natural-language questions into validated scenario inputs, run approved experiments through the same engine and explain computed results. It must not invent SOC, distances, charger availability or results; all calculations, validation and seeds stay in the deterministic engine.
- **Future power-system link (not implemented):** hub demand CSVs are the intended input to pandapower, OpenDSS or another validated solver for voltage, loading and losses. Not described as operational until connected and tested.

## Future extensions (not implemented)

Charging taper curves, payload/gradient/weather energy models, heterogeneous bays within a hub, booking and no-shows, split breaks and reduced rests, weekly rest scheduling, calibrated DfT arrival profiles, using observations as simulation initial states, multiple random replications with confidence intervals, and power-flow coupling.


## Version 1.5 additions (28 October 2026)

### Charging power versus state of charge

Vehicle-side power limit each minute = DC acceptance × charging-power factor × f(SOC), where f is a piecewise-linear curve evaluated at the SOC at the start of the minute (explicit one-minute step). The delivered power is then the minimum of that limit, the charger rating, the remaining energy to target and the shared hub budget, as before. Study-wide options: `flat` (f = 1, identical to 1.4 and the default, so earlier studies reproduce) and `taper` (1.0 up to 60% SOC, 0.70 at 80%, 0.40 at 90%, 0.15 at 100%). A truck may supply its own curve as `charge_curve` (`0:1|0.8:0.7|1:0.2`), which overrides the study-wide choice; SOC points must rise from 0 to 1 and fractions lie in (0, 1]. The taper shape is an illustrative assumption, not a measured curve. The diversion delay estimate integrates the same curve in 1% SOC steps. Sessions report charging minutes and mean power. "Charging taper" and "Constant charging" are available as paired comparison cases.

### Repeated runs and confidence intervals

For a generated fleet, the uncertainty panel regenerates arrivals with seeds base, base+1, …, base+n−1 (2–100 runs) and simulates Current settings plus the ticked comparison cases on each identical fleet (common random numbers). For each metric it reports the mean with a t-based 95% confidence interval (t quantile for n−1 degrees of freedom, conservative lookup), the 5th–95th percentile of individual runs, n, and paired differences (case − current, same seed). Per-hub peak demand, p95 wait, maximum queue and bay use are summarised the same way. Runs where a metric is undefined (for example, no charging session started) are excluded from that metric. Seeds that fail validation (for example, more than 100 trucks generated) are listed and excluded. Repeated runs capture arrival randomness only; manual edits to individual generated trucks are not carried into them. Statistics are computed in Python (`describe`, `aggregate`) and covered by tests.


## Version 1.6 additions (28 October 2026)

### Range- and driving-time-based route planning

With `route_planning` on, when a truck's next planned leg is beyond its battery range with the arrival reserve (energy for the leg + reserve > current usable capacity), or longer than a fresh driving allowance, it searches the supplied directed links for the path with the fewest travel minutes to that same next stop. Every leg on the path must be drivable from a full battery with the reserve and within a fresh driving allowance. Every intermediate stop must have at least one charger with a compatible connector. If the truck cannot charge where it is, the first leg must already be feasible on its current energy. The path has at most 6 legs, visits no hub twice and keeps the whole route within 30 stops. The intermediate stops are inserted before the original next stop and logged as `route_replanned`, with the path, its distance and time, and the direct leg it replaced. Ordinary charge, rest and queue decisions then apply at each stop. If no such path exists, the truck is blocked with the original reason plus "route planning found no feasible path". With planning on, input routes may contain a leg longer than a fresh driving allowance, because the planner will route around it. The search uses supplied links only: no road-network routing, no traffic, and no estimate of charging time or queues when choosing the path (fastest driving path, not fastest total time). Off is the engine default, so earlier studies reproduce; the built-in example turns it on. "Route planning on/off" are paired comparison cases, and re-plans appear in the map (dotted blue path), the decision record, the vehicle inspector, the summary, the repeated-runs metrics and the diversions & re-routes CSV.

### Origin–destination fleets

The arrival generator's default route mode picks a random ordered pair of hubs per truck and uses the fastest path over supplied links (legs within a fresh driving allowance; ties broken by hub IDs), keeping only pairs whose path is at least the minimum trip distance (default 150 km). This sends generated traffic through every hub on those paths, including newly added nodes. Battery range is not checked at generation time. The previous list mode remains available.
