Multi-Modal Access & Egress
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.