Two layers. The corpus (/home/geo1/maps/toll/corpus/VA) carries the rates printed on VDOT's "Toll Roads in Virginia" pages; va_state.py starts from it and adds positions, the operator-sourced amounts below, and the express-lane schedule rows.
erc_toll_rates_api, erc_toll_chart_2026) and the Jordan Bridge (snjb_tolling, snjb_toll_rates_2026) publish the new year's rates. The file names carry the year: put the new URLs in urls.txt.dullesgreenway_tolls_json, now tolls-2025-08-01.json) changes name when rates change. Check dullesgreenway_calculator for the file it loads.python3 /home/geo1/maps/toll/bin/tollup.py VA update then TOLL_WEB=/home/geo1/maps/toll/corpus python3 /home/geo1/maps/toll/bin/publish.py VA.tollroadsinvirginia_facilities (new or ended facilities: Coleman Bridge ended 2025-08-08).expresslanes_learn_the_lanes). The rows hold the rest-of-year schedule (weekday reversal 11 a.m.-12 p.m.). From late May to early September Transurban reverses at 10 a.m.; holidays change it too. Rows: W95 in va_state.py.vdot_hrel_norfolk_reversible); rows W64. Chesapeake segment: 24 hours (vdot_hrel_chesapeake_segment).vdot_66express_about): eastbound Mon-Fri 5:30-9:30 a.m., westbound 3-7 p.m., free otherwise ($0.00 rows). Federal holidays are not modeled.TU, REV, I6, O6, X64, NOR, CHE.python3 /home/geo1/system/handbuilt/fetch_list.py VA [names] (all VA sources are in urls.txt).erc_toll_chart_2026 (PNG) and snjb_toll_rates_2026 (JPG) are read by eye and typed into va_state.py (ERT: erc_toll_rates_api JSON is the machine source; SNJB: the image only). A new image means re-reading it.python3 va_state.py. New or moved points: the full chain. OSM box for VA/MD/DE: -83.7,36.5,-75.0,39.75 (vamdde).No operator publishes an amount or a minimum (regulation 24VAC30-620-30 B: rates "vary as necessary to manage the demand"). Each express-lane point carries rows with an empty amount: live (toll in effect, with hours and direction) or closed (reversible lanes not running that way). The engine turns them into notices in passed[] with express_lanes; they never enter a total. The router never drives reversible lanes (OSM oneway=reversible), so the 95, 395 and 64 Norfolk lanes are told through the beside: points on the general lanes next to them.
beside: points. Re-check them after an OSM refresh.PT is keyed by (payment, alternative).transurban_live_prices) is archived but not used.Hosts: geo1 (192.168.50.220) holds the sources, builders, drafts, map and API; b100 (192.168.50.14) is the test client. All times are Eastern.
| what | where (geo1 unless said) |
|---|---|
| sources list | /home/geo1/maps/toll/VA/urls.txt (name <tab> URL) |
| archived sources | /home/geo1/maps/toll/VA/sources/<name>/<YYYY-MM-DD>/ (file + meta.json: url, fetched, sha256) |
| builder | /home/geo1/system/handbuilt/va_state.py; shared code toll_common.py |
| OpenStreetMap inputs | /home/geo1/system/handbuilt/osm/va_* (cut from /home/geo1/maps/osm/us-latest.osm.pbf) |
| output | draft /srv/toll/draft/VA/ (the builders write here); published /srv/toll/VA/ (copied from the draft by promote.py publish). The map and the API read the published page, or the draft while it is listed for review |
| toll engine | source /home/geo1/maps/web/tolls.js, served copy /srv/maps/tolls.js (the API runs the served copy) |
| API | /home/geo1/maps/api/server.mjs on 127.0.0.1:8090 behind nginx /api/; pid in logs/test.pid |
| regression trips | b100: ~/apitest/site/cases.json, runner ~/apitest/run.py, browser check ~/apitest/browser.mjs |
python3 /home/geo1/system/handbuilt/fetch_list.py VA [name ...] (no names = every line of urls.txt). A new source: add a line to urls.txt first, then fetch it by name.node ~/apitest/fetch_b100.mjs <out> <name>=<url> ..., then rsync -a <out>/ geo1@192.168.50.220:/home/geo1/maps/toll/VA/sources/. Its meta.json records that it came from b100.diff, pdftotext -layout for PDFs). Same content: nothing to do. Changed amounts or a new effective date: rebuild (step 2) and update the expected amounts of the affected regression trips from the operator's own figures.python3 /home/geo1/maps/toll/bin/tollup.py VA update fetches the adapter's sources (bin/adapters/va.py), stores a document only when its content changes, writes one rate file per version under /home/geo1/maps/toll/VA/rates/ and appends every price change to history.csv (every run to runs.log). TOLL_WEB=/home/geo1/maps/toll/corpus python3 /home/geo1/maps/toll/bin/publish.py VA writes the corpus /home/geo1/maps/toll/corpus/VA from it (DE: plain publish.py DE writes /srv/toll/DE). Never hand-edit either. Then rebuild the draft (step 2) so it picks up the new rates.
cd /home/geo1/system/handbuilt && python3 va_state.pybash /home/geo1/system/handbuilt/chain.sh VA (logs in /tmp/va1.log ... va6.log; it prints the points, any point on no road and the untied count). The builders written since October 2026 share state_kit.py (sources, booths, terms, rows, write) and own_state.py (keeps a state's untied list to toll nodes inside the state, by the local geocoder; cache osm/node_state.json).cd /home/geo1/system/handbuilt; H=$(ls osm/va_highways_*.geojsonseq); J=$(ls osm/va_junctions_*.geojsonseq)
python3 va_state.py && python3 osm_streets.py VA $H $J && python3 va_state.py && python3 osm_snap.py VA && python3 toll_ways.py VA && python3 va_state.pytoll_ways.py's output: nodes claimed by two points: {} and points on no road: [] must both be empty.OSM way <id>) needs that way in osm/va_lane_ways.json (the builder writes it). A point on a road priced entry to exit needs gantry in its location name, or toll_ways.py treats it as a position-only exit marker.osm/ny_not_toll_nodes.json (congestion-zone gantries that are not tolls); every state's untied list leaves those out, so rebuild NJ and PA after NY.tolls.js when it starts. Restart it: cd /home/geo1/maps/api && kill $(cat logs/test.pid); (nohup /home/geo1/maps/node/bin/node server.mjs > logs/server.log 2>&1 & echo $! > logs/test.pid) (it is started by hand, not a service).python3 ~/apitest/run.py ~/apitest/site/cases.json. Every trip must be OK. Add a trip for every rate or rule you change, with the amount taken from the operator's own source.tolls.js): edit /home/geo1/maps/web/tolls.js, check with /home/geo1/maps/node/bin/node --check, copy to /srv/maps/tolls.js with sudo install -o www-data -g www-data -m 644, restart the API, run the trips.The builders match toll points to the OSM way ids the router drives, so the extracts here must come from the same us-latest.osm.pbf the router (Valhalla, /home/geo1/maps/valhalla_data) was built from (now 2026-09-27). New OSM data means: rebuild the router tiles, then for each state cut the box, rebuild its OSM inputs and run the full chain, then compare untied_toll_nodes.csv and the estimated positions below. The box for VA and the cutting commands are in the state's procedure above; the toll-node and way index comes from python3 tollnode_ways.py VA.
A rebuild writes the draft (/srv/toll/draft/VA); the published page (/srv/toll/VA) does not change. python3 /home/geo1/maps/toll/bin/promote.py review VA lists the draft for review: the map and the API then read it instead of the published page. Run the regression trips from b100. After approval, python3 /home/geo1/maps/toll/bin/promote.py publish VA copies the draft to /srv/toll/VA (the previous page is kept under /home/geo1/maps/toll/VA/published/<time>/) and takes it off the review list. After a change, update the coverage line for VA in the API page (/api.html, generator /home/geo1/maps/api/doc/api_page.py) and rebuild this page: python3 /home/geo1/system/handbuilt/maintain_pages.py VA.
Each fetch is kept in its own dated folder under /home/geo1/maps/toll/VA/sources/<name>/; the builder always reads the newest one, so a new fetch takes effect at the next rebuild and the old one stays for comparison.
| id | facility | operator | points | rate / trip rows | effective dates in the rows | source |
|---|---|---|---|---|---|---|
VA-TU-495 | 495 Express Lanes | Transurban (USA) Operations Inc | 8 | 8 | (none printed) | tollroadsinvirginia_facilities |
VA-VDOT-66I | 66 Express Lanes - Inside the Beltway | VDOT | 4 | 16 | (none printed) | tollroadsinvirginia_facilities |
VA-I66EMP-66O | 66 Express Lanes - Outside the Beltway | I-66 Express Mobility Partners | 7 | 7 | (none printed) | tollroadsinvirginia_facilities |
VA-TU-95 | 95 Express Lanes | Transurban (USA) Operations Inc | 11 | 44 | (none printed) | tollroadsinvirginia_facilities |
VA-TU-395 | 395 Express Lanes | Transurban (USA) Operations Inc | 5 | 20 | (none printed) | tollroadsinvirginia_facilities |
VA-TDG | Dulles Greenway | Toll Road Investors Partnership II (Dulles Greenway) | 7 | 280 | 2025-08-01 | tollroadsinvirginia_facilities |
VA-MWAA-DTR | Dulles Toll Road | Metropolitan Washington Airports Authority | 12 | 60 | 2023-01-01 | tollroadsinvirginia_facilities |
VA-POCA | Pocahontas Parkway | Globalvia | 3 | 15 | 2026-04-01 | tollroadsinvirginia_facilities |
VA-VDOT-PPE | Powhite Parkway Extension | VDOT | 4 | 20 | 2025-12-17 | tollroadsinvirginia_facilities |
VA-RMTA-BB | Boulevard Bridge | Richmond Metropolitan Transportation Authority (RMTA) | 1 | 3 | 2026-10-03_observed | tollroadsinvirginia_facilities |
VA-RMTA-DE | Downtown Expressway | Richmond Metropolitan Transportation Authority (RMTA) | 3 | 36 | 2026-10-03_observed | tollroadsinvirginia_facilities |
VA-RMTA-PP | Powhite Parkway | Richmond Metropolitan Transportation Authority (RMTA) | 2 | 24 | 2026-10-03_observed | tollroadsinvirginia_facilities |
VA-VDOT-64X | 64 Express Lanes (Hampton Roads Express Lanes) | VDOT | 4 | 13 | (none printed) | tollroadsinvirginia_facilities |
VA-CBBT | Chesapeake Bay Bridge-Tunnel | Chesapeake Bay Bridge and Tunnel Commission | 1 | 16 | 2024-01-01 | tollroadsinvirginia_facilities |
VA-CHES-X | Chesapeake Expressway | City of Chesapeake | 1 | 12 | 2026-05-01 | tollroadsinvirginia_facilities |
VA-CHES-DBVB | Dominion Boulevard Veterans Bridge | City of Chesapeake | 1 | 6 | 2026-07-01 | tollroadsinvirginia_facilities |
VA-ERT-DT | Elizabeth River Tunnels - Downtown Tunnel | Elizabeth River Crossings (ERC) | 1 | 8 | 2026-01-01 | tollroadsinvirginia_facilities |
VA-ERT-MT | Elizabeth River Tunnels - Midtown Tunnel | Elizabeth River Crossings (ERC) | 1 | 8 | 2026-01-01 | tollroadsinvirginia_facilities |
VA-SNJB | South Norfolk Jordan Bridge | United Bridge Partners | 1 | 8 | 2026-01-01 | tollroadsinvirginia_facilities |
| point | facility | location | placed on | why |
|---|---|---|---|---|
VA-TU-395-03 | 395 Express Lanes | express lanes north of Shirlington | express-lane way (no OSM gantry) | R3 estimate: OSM maps the I-395 express lanes to the D.C. line but no toll gantry north of Seminary Road; a booth on the express-lane way at 38.852 N so a trip on that stretch is located (Transurban does not publish gantry positions) |
VA-I66EMP-66O-01 | 66 Express Lanes - Outside the Beltway | eastbound EB Segment 1 (10 miles): Gainesville (US 29) to Stringfellow Road | operator corridor map + express-lane way | R3 estimate: the 66 Express corridor map (I-66 Express Mobility Partners) draws EB Segment 1 (10 miles) from Gainesville (US 29) to Stringfellow Road; the map is not to scale, so the segment's limits are taken at the interchanges' longitudes on OSM (-77.597, -77.399) and its booth is on the eastbound express-lane way midway; the OSM toll gantry 9091703233 on this segment |
VA-I66EMP-66O-02 | 66 Express Lanes - Outside the Beltway | eastbound EB Segment 2 (5 miles): Stringfellow Road to Chain Bridge Road (VA 123) | operator corridor map + express-lane way | R3 estimate: the 66 Express corridor map (I-66 Express Mobility Partners) draws EB Segment 2 (5 miles) from Stringfellow Road to Chain Bridge Road (VA 123); the map is not to scale, so the segment's limits are taken at the interchanges' longitudes on OSM (-77.399, -77.308) and its booth is on the eastbound express-lane way midway |
VA-I66EMP-66O-03 | 66 Express Lanes - Outside the Beltway | eastbound EB Segment 3 (7 miles): Chain Bridge Road (VA 123) to I-495 | operator corridor map + express-lane way | R3 estimate: the 66 Express corridor map (I-66 Express Mobility Partners) draws EB Segment 3 (7 miles) from Chain Bridge Road (VA 123) to I-495; the map is not to scale, so the segment's limits are taken at the interchanges' longitudes on OSM (-77.308, -77.222) and its booth is on the eastbound express-lane way midway |
VA-I66EMP-66O-04 | 66 Express Lanes - Outside the Beltway | westbound WB Segment 3 (5 miles): I-495 to Chain Bridge Road (VA 123) | operator corridor map + express-lane way | R3 estimate: the 66 Express corridor map (I-66 Express Mobility Partners) draws WB Segment 3 (5 miles) from I-495 to Chain Bridge Road (VA 123); the map is not to scale, so the segment's limits are taken at the interchanges' longitudes on OSM (-77.222, -77.308) and its booth is on the westbound express-lane way midway |
VA-I66EMP-66O-05 | 66 Express Lanes - Outside the Beltway | westbound WB Segment 2 (5 miles): Chain Bridge Road (VA 123) to Sully Road (VA 28) | operator corridor map + express-lane way | R3 estimate: the 66 Express corridor map (I-66 Express Mobility Partners) draws WB Segment 2 (5 miles) from Chain Bridge Road (VA 123) to Sully Road (VA 28); the map is not to scale, so the segment's limits are taken at the interchanges' longitudes on OSM (-77.308, -77.445) and its booth is on the westbound express-lane way midway |
VA-I66EMP-66O-06 | 66 Express Lanes - Outside the Beltway | westbound WB Segment 1B (3 miles): Sully Road (VA 28) to Sudley Road (VA 234 Business) | operator corridor map + express-lane way | R3 estimate: the 66 Express corridor map (I-66 Express Mobility Partners) draws WB Segment 1B (3 miles) from Sully Road (VA 28) to Sudley Road (VA 234 Business); the map is not to scale, so the segment's limits are taken at the interchanges' longitudes on OSM (-77.445, -77.497) and its booth is on the westbound express-lane way midway |
VA-I66EMP-66O-07 | 66 Express Lanes - Outside the Beltway | westbound WB Segment 1A (7 miles): Sudley Road (VA 234 Business) to Gainesville (US 29) | operator corridor map + express-lane way | R3 estimate: the 66 Express corridor map (I-66 Express Mobility Partners) draws WB Segment 1A (7 miles) from Sudley Road (VA 234 Business) to Gainesville (US 29); the map is not to scale, so the segment's limits are taken at the interchanges' longitudes on OSM (-77.497, -77.597) and its booth is on the westbound express-lane way midway |
VA-TU-95-08 | 95 Express Lanes | express lanes between Dumfries and Garrisonville Road | express-lane way (no OSM gantry) | R3 estimate: OSM maps the 95 Express Lanes here but no toll gantry; a booth on the express-lane way at 38.505 N so a trip on this stretch is located (Transurban does not publish gantry positions) |
VA-TU-95-09 | 95 Express Lanes | Fredericksburg extension, Garrisonville Road to US 17 | express-lane way (no OSM gantry) | R3 estimate: OSM maps the 95 Express Lanes here but no toll gantry; a booth on the express-lane way at 38.41 N so a trip on this stretch is located (Transurban does not publish gantry positions) |
VA-TU-495-07 | 495 Express Lanes | northbound express lanes north of Balls Hill (495 NEXT, to the George Washington Memorial Parkway) | express-lane way (no OSM gantry) | R3 estimate: the 495 Express Lanes extension north of the Dulles Toll Road (495 NEXT, open since late November 2025) is mapped in OSM (toll=yes) with no toll gantry; a booth on the express-lane way at 38.952 N |
VA-TU-495-08 | 495 Express Lanes | southbound express lanes north of Balls Hill (495 NEXT, to the George Washington Memorial Parkway) | express-lane way (no OSM gantry) | R3 estimate: the 495 Express Lanes extension north of the Dulles Toll Road (495 NEXT, open since late November 2025) is mapped in OSM (toll=yes) with no toll gantry; a booth on the express-lane way at 38.952 N |
VA-VDOT-64X-01 | 64 Express Lanes (Hampton Roads Express Lanes) | Norfolk reversible express lanes (I-264 to I-564) | express-lane way (no OSM gantry) | R3 estimate: VDOT: 'Norfolk Reversible Express Lanes from I-264 to I-564' tolled; OSM maps them as 'I 64 Express Lanes' with no toll gantry: a booth midway on that way |
VA-VDOT-64X-02 | 64 Express Lanes (Hampton Roads Express Lanes) | Chesapeake express lanes (Bowers Hill to I-264), at the High Rise Bridge | the express-lane ways (OSM: one-lane motorways, toll=yes, hov=yes) | R3 estimate: VDOT: the Chesapeake segment adds 'one Express Lane alongside the two general purpose lanes in each direction'; OSM maps each as its own one-lane way (eastbound 1309089898, westbound 1467051228): a booth on each near the High Rise Bridge |
VA-TU-95-10 | 95 Express Lanes | beside: northbound general lanes of I-95 at Lorton | general-lane carriageway beside reversible express lanes | R3 estimate: the router does not drive reversible lanes (OSM oneway=reversible); a point on the northbound general lanes of I 95 beside them, so a route there is told whether the express lanes run its way and where their price is posted (not a toll) |
VA-TU-95-11 | 95 Express Lanes | beside: southbound general lanes of I-95 at Lorton | general-lane carriageway beside reversible express lanes | R3 estimate: the router does not drive reversible lanes (OSM oneway=reversible); a point on the southbound general lanes of I 95 beside them, so a route there is told whether the express lanes run its way and where their price is posted (not a toll) |
VA-TU-395-04 | 395 Express Lanes | beside: northbound general lanes of I-395 at Shirlington | general-lane carriageway beside reversible express lanes | R3 estimate: the router does not drive reversible lanes (OSM oneway=reversible); a point on the northbound general lanes of I 395 beside them, so a route there is told whether the express lanes run its way and where their price is posted (not a toll) |
VA-TU-395-05 | 395 Express Lanes | beside: southbound general lanes of I-395 at Shirlington | general-lane carriageway beside reversible express lanes | R3 estimate: the router does not drive reversible lanes (OSM oneway=reversible); a point on the southbound general lanes of I 395 beside them, so a route there is told whether the express lanes run its way and where their price is posted (not a toll) |
VA-VDOT-64X-03 | 64 Express Lanes (Hampton Roads Express Lanes) | beside: eastbound general lanes of I-64 in Norfolk, Norfolk reversible lanes | general-lane carriageway beside reversible express lanes | R3 estimate: the router does not drive reversible lanes (OSM oneway=reversible); a point on the eastbound general lanes of I 64 beside them, so a route there is told whether the express lanes run its way and where their price is posted (not a toll) |
VA-VDOT-64X-04 | 64 Express Lanes (Hampton Roads Express Lanes) | beside: westbound general lanes of I-64 in Norfolk, Norfolk reversible lanes | general-lane carriageway beside reversible express lanes | R3 estimate: the router does not drive reversible lanes (OSM oneway=reversible); a point on the westbound general lanes of I 64 beside them, so a route there is told whether the express lanes run its way and where their price is posted (not a toll) |
R2a: 7, R2b: 57, R3: 20, direction: 3, not: 40, priced: 6 (all in decisions.csv).
None.
Toll booths / gantries mapped in OpenStreetMap on or near this state's roads that no toll point claims; a route through one lists it under unpriced. After an OSM refresh, look at new ones here (untied_toll_nodes.csv): a new gantry on a priced road means a point is missing.
Run from b100 (never on geo1): python3 ~/apitest/run.py ~/apitest/site/cases.json. Every trip must come back OK; a changed amount is either a rate change (update the expected amount from the operator's own source) or a fault.
| trip | expected |
|---|---|
| VA Greenway Leesburg->Dulles eastbound 07:30 Wed, E-ZPass (Main Plaza rush $5.80) | $5.80 |
| VA Greenway Leesburg->Dulles eastbound 12:00 Wed, E-ZPass (Main Plaza $5.25) | $5.25 |
| VA Greenway Dulles Airport->Leesburg westbound 17:00 Wed, E-ZPass (DTR Sully Road ramp $2.00 + Greenway Main Plaza rush $5.80, as the Greenway page notes) | $7.80 |
| VA Downtown Tunnel Norfolk->Portsmouth 08:00 Wed, E-ZPass (peak $3.40) | $3.40 |
| VA Downtown Tunnel Portsmouth->Norfolk 12:00 Wed, Pay by Plate (off-peak $7.25) | $7.25 |
| VA Downtown Tunnel Norfolk->Portsmouth 08:00 Sat, E-ZPass (weekend off-peak $2.42) | $2.42 |
| VA Midtown Tunnel Norfolk->Portsmouth 12:00 Wed, E-ZPass (off-peak $2.42) | $2.42 |
| VA Jordan Bridge 12:00 Wed, E-ZPass ($3.70) | $3.70 |
| VA Jordan Bridge 12:00 Wed, pay-by-mail ($3.70 + $5.50) | $9.20 |
| VA 66 Inside eastbound Sat 08:00: toll-free hours (VDOT), $0.00 | $0.00 |
| VA 66 Inside eastbound Wed 11:00: toll-free hours (VDOT), $0.00 | $0.00 |
| VA 66 Inside westbound Wed 08:00: toll-free hours (VDOT), $0.00 | $0.00 |
| VA 495 Express Tysons -> Springfield: optional express lanes, a notice only, never in the total ($0.00) | $0.00 |
| VA 66 Inside eastbound Wed 08:00 (toll hours): notice only ($0.00) | $0.00 |
| VA 66 Outside Gainesville -> Vienna: notice only ($0.00) | $0.00 |
| VA 64 Chesapeake express lane Bowers Hill -> Battlefield Blvd: notice only ($0.00) | $0.00 |