← gpu-pilot · json · source: MULTIMODAL.md

Multi-Modal Access & Egress

Kiss&Ride, Uber, Citi Bike, Park&Ride — first/last-mile legs + a cost model around the unchanged kernel. · updated 2026-06-11 20:48

TL;DR

  • Access/egress are a LEG LAYER; the kernel is unchanged — a drive leg is one more (origin, stop, seconds) Round-0 seed, egress is computed post-kernel.
  • Egress changes the answer: a Citi Bike makes the Edison→99 Wall St PATH option joint-fastest (74 min, ~$16), erasing its 1.1 km WTC walk.
  • Validates ground truth: 08854→10001 lands at 77 min (in the 67-78 band) via K&R/Uber Edison + every Metropark option, one kernel pass (multi-source).
  • P&R Edison shows 98 min — correctly, not a bug: parking overhead misses the train K&R catches (exact-schedule fidelity; a range query smooths it).
  • Cost = out-of-pocket + value-of-time($18/hr) × effective minutes; drive-all-the-way is faster but ~4× the cost. Fares are ESTIMATES pending Fares v2.
  • Live data: OSRM drive at 172.26.1.151:5002 (geo2 by IP), Citi Bike GBFS 2,411 docks as the availability gate.

Multi-Modal Access & Egress — Kiss&Ride, Uber, Bikes, Park&Ride

Phase E, pulled forward. RAPTOR computes transit (stop → stop). How you reach the first stop (access) and leave the last (egress) is a separate leg layer — and the new axis is cost, so options rank by time, by money, or by a generalized (time+money) cost the way OTP filters itineraries. The kernel did not change.

Files: multimodal.py (leg + fare + cost library) · run_multimodal_options.py (the two scenarios below). Run: venv/bin/python raptor-design/run_multimodal_options.py 7


The one idea

A drive-access leg is just one more (origin, stop, seconds) entry in the Round-0 walk CSR the kernel already reads; egress is computed after the kernel from travel[:, origin]. So every mode below is a leg generator feeding an unchanged RAPTOR core — exactly how OTP models WALK+TRANSIT, CAR_PARK+TRANSIT, BIKE_RENT, etc.

Mode Leg routing Availability gate Cost (estimate)
Walk crow-fly × 1.35 / 1.33 m·s⁻¹ ≤ 1.2 km $0
Park & Ride OSRM drive → station with a lot station has parking parking/day + mileage
Kiss & Ride OSRM drive → station ~any station mileage only (rider pays $0)
Uber / Lyft OSRM drive anywhere base + $/mi + $/min + booking
Citi Bike / scooter bike speed 4.5 m·s⁻¹ dock within 300 m of both ends (live GBFS) unlock $4.79
Drive all-the-way OSRM origin→dest always mileage + parking + tolls

Data sources (live): OSRM drive http://172.26.1.151:5002 (geo2 by IP — the hostname doesn't resolve from geocoder); Citi Bike GBFS (2,411 docks loaded as a KD-tree availability gate).


Scenario A — EGRESS: Edison → 99 Wall St (the two options, real last mile)

Departing the Edison platform at 07:00; transit times kernel-computed, last mile by mode:

Option 1 — NJT NEC → NY Penn → subway → Wall St (71 min transit)

egress door-to-door fare gen-cost note
walk 74 min $16.65 40.38 218 m — FASTEST + CHEAPEST + BEST
Citi Bike 74 min $21.44 45.21 202 m, docks both ends
Uber 77 min $25.65 50.04 0.3 mi ride

Option 2 — NJT NEC → Newark → PATH → WTC (68 min transit)

egress door-to-door fare gen-cost note
walk 83 min $11.25 39.38 1159 m — CHEAPEST + BEST
Citi Bike 74 min $16.04 39.88 1073 m, docks both ends — FASTEST
Uber 79 min $20.69 45.45 1.3 mi ride

The egress mode changes the answer. Option 2's only weakness was its ~1.1 km WTC→destination walk. A Citi Bike makes Option 2 the joint-fastest (74 min) at ~$16 — matching Option 1 on time at a similar price — while Option 2 + walk stays the cheapest trip overall ($11.25) if you'll do the 15-minute walk.


Scenario B — ACCESS: 08854 Piscataway → 10001 NY Penn (ground-truth pair)

All first-mile options run in one kernel pass as synthetic multi-source origins (lane = access option). Ground truth (CLAUDE.md): 67–78 min via P&R Edison.

access door-to-door fare gen-cost band note
P&R Edison 98 min $23.75 54.58 ⚠ out parking overhead misses the train K&R catches
K&R Edison 77 min $16.74 40.82 ✅ in dropped off after 12 min drive — FASTEST+CHEAPEST+BEST
Uber Edison 77 min $33.76 57.84 ✅ in 5 min wait + 12 min ride (6.0 mi)
P&R Metropark 77 min $25.67 50.20 ✅ in drive 17 min + park (express stop)
K&R Metropark 77 min $18.58 42.66 ✅ in dropped off after 17 min drive
Uber Metropark 77 min $41.86 65.94 ✅ in 17 min ride (9.7 mi)
DRIVE all-the-way 58 min $60.63 77.93 39 mi + $35 parking + $16 tolls

Validates the ground truth: K&R/Uber Edison and every Metropark option land at 77 min — inside the 67–78 band. The kernel + drive-access legs reproduce the documented number.

Why P&R Edison shows 98, not ~77 — and why that's correct, not a bug: from a fixed 07:00 origin departure, the extra ~6 min of parking overhead pushes arrival at Edison from ~07:14 to ~07:20, missing the train K&R/Uber catch, so it waits for the next one (+21 min total). That's exact-schedule fidelity — OTP shows the same. A depart-window range query would shift P&R's start earlier and close the gap; single-departure snapshots are departure-time-sensitive.

Drive-the-whole-way is faster (58 min) but ~4× the cost ($60 vs $16) — the time-vs-money tradeoff that is the commutingcost.com product, now computed.


Cost model (all ESTIMATES — Phase E / GTFS Fares v2 replaces the constants)

  • Generalized cost ($) = out-of-pocket + value-of-time($18/hr) × effective minutes, where walking is weighted 1.5× and each transfer adds +4 min.
  • Transit fares: agency tariffs hardcoded (NJT $13.75, subway $2.90, PATH $2.75…).
  • Uber: base $2.55 + $0.35/min + $1.75/mi + $2.75 booking, min $9, optional surge.
  • Citi Bike: $4.79 unlock (classic, <30 min); e-bike $0.30/min.
  • Mileage: $0.25/mi fuel+wear (K&R counts the driver's round trip).

Real per-leg fares (distance-banded transit, true surge, parking tariffs) are the remaining Phase E work; the kernel still emits arrival-time only, so fares are attributed by named leg, not reconstructed from a path.

Caveats / next

  • Walk + bike legs are crow-fly × detour (NJ first-mile, FiDi last-mile); the Phase-C network walk matrix is NYC-only — extend to NJ/CT.
  • No journey reconstruction yet → fares attributed per named option, not derived from board/alight points. That (parent-pointer trace) + Fares-v2 is Phase E.
  • Add depart-window range queries so P&R-style departure sensitivity is smoothed.

Comments