← Back to portfolio

Case study · Accessible transit routing

Connected is not the same as passable

A planner can hand you three itineraries that all look fine: connected, sorted by time, no warnings. Any of them can be impossible in a wheelchair, because the lift needs a member of staff, the corridor between platforms is a flight of stairs, or nobody knows whether the bus that pulls in can take a chair. I wanted that information inside the route calculation, where it changes the answer, instead of in a footnote under it.

Role
Co-developer and project lead: requirement research and analysis, mathematical modeling, algorithm optimization, front-end implementation and back-end optimization, interface and accessibility adaptation, project coordination
Team
Joint development with Yiyang Fang: requirement research, mathematical modeling, algorithm design, front-end and back-end architecture and development, data and deployment. Copyright co-owned by both developers.
Status
Live public deployment since July 2026
Paper
First author and co-corresponding author, IEEE ITSC 2026 late-breaking poster (co-corresponding: Yuan Sui)
Built with
Python / Flask · SQLite · vanilla JS · AMap Web SDK · A* · 0‑1 BFS · TOPSIS
Evidence
Two field cases + a 508-station scored graph; live system about 8,550 lines

01The problem

Transit routing has spent decades optimizing time, distance and transfer count. All three can be satisfied by a trip that cannot be finished. When I started, the Shanghai network had 508 metro stations, 1,589 bus routes and 16,956 vehicles in service, and 127 bus routes had been publicized as low-floor and accessible. None of that answers the question a wheelchair user actually has: can I get on the 8:15 at this stop.

The failures repeat in the same places. A station has a lift and the lift needs staff; a self-service lift, a staff-operated one and an assisted stair-lift are three different facts with three different outcomes, while a facility list usually records just the first. A transfer is connected, but the corridor is long and goes upstairs. A bus line exists, and there is no evidence about boarding at the stop. Timetables show all of these as normal. Route output shows none of them.

Time-only route card

In-vehicle time only
1 transfer connected
Bus link no boarding evidence

Accessibility-aware card

In-vehicle time only
1 transfer staff-assisted lift
Bus link vehicle not confirmed
Schematic, not a screenshot. Both cards describe the same trip. The left one is close to what most planners print, and every line on it is true. The right one adds what the traveller would otherwise find out standing in front of the lift.

So the question I ended up on was narrower than pathfinding: what belongs on the route card, at which level (station, transfer, stop, vehicle), and who keeps it current.

02What I deliberately did not do

  • I did not write a new shortest-path algorithm. A* runs as published in 1968, and if that were the contribution, the paper would be a restatement of a sixty-year-old result. Whatever is new sits in the cost terms.
  • I did not filter routes. Most map apps hide options once the accessibility switch is on. Hiding is a decision taken quietly on the traveller’s behalf, and it deletes the case where someone takes a difficult route with help. This system keeps every candidate and writes the burden on the card, so the choice stays with the person who has to make the trip.
  • Nothing is trained. Every ranking is deterministic: same input, same output, and when a route comes out on top I can point at why (transfer count, walking distance, six dimension scores). No model has to be explained after the fact, because nothing was fitted in the first place.
  • I did not build user profiles. The scoring never asks which category of disability a traveller belongs to. That would be a guess about a person; the burden of a route is a fact about a station.

03How it works

  1. A graph whose nodes carry evidence

    Metro stations and bus stops become nodes of a directed graph, each with a score between 0 and 1 built from wheelchair-relevant facility evidence: lifts, platforms, ramps, self-service equipment. Field observation split three access categories instead of one accessible label, because a self-service lift, a staff-operated lift and an assisted stair-lift produce different trips even when all three are called accessible.

  2. One cost function, four burdens

    The edge cost adds in-vehicle time, waiting time and transfer effort, then charges two penalties: barriers at the station, and the mismatch between a bus that appears in the timetable and the absence of boarding evidence. The coefficient on the penalties is the traveller’s own preference for time over robustness, not a constant someone hid in the code.

    # accessibility-aware edge cost
    w(e) = Ttrav + Twait + Ttrans + λ(Pbarrier + Pmismatch)
  3. Search is the easy part

    A* runs on that cost and returns a route, along with the reasons behind the number: which transfer needed staff, which station carried the barrier, which bus link had no evidence. The algorithm is deliberately dull. The judgement sits upstream, in deciding what a node score is allowed to mean.

  4. The live site runs a different pipeline

    The public site has no operator timetable feed, so it cannot re-plan a network. It takes the candidate itineraries AMap returns and re-ranks them: transfer count first, because every transfer is another set of stairs or another long corridor; then walking distance; then duration. Station comfort comes from six reported dimensions (entrance, vertical access, transfer, signage, crowding, overall) aggregated with TOPSIS weights of 0.2, 0.2, 0.15, 0.15, 0.15, 0.15. Cards put the burden in words before departure: needs stairs, twelve steps; walk 800 m; long transfer.

04The two cases

22.22 / ~24 Minutes: prototype estimate vs field observation, Beiqiao to Lianhua Road
704B The only wheelchair-feasible bus link in a 3.6 km corridor with two direct lines
508 + 52 Scored nodes: metro stations, and sampled bus stops
1,589 / 127 Bus routes in the network, of which 127 are publicized as low-floor

Case one is a connected metro trip whose transfer burden normally disappears into a generic travel-time estimate. Case two is a short corridor where a direct bus line has existed all along and accessibility still turns on the vehicle and the stop.

The first case changed how I think about the whole project. The prototype put the trip at 22.22 minutes; the field observation came to about 24. Being inside 10% is partly luck, and I would not defend the exact figure on a different corridor. What mattered is that the transfer burden showed up in the estimate at all. A planner that says 24 minutes is not lying. It is averaging the people who take the stairs with the people who cannot, and that average is a route nobody can walk.

The second case is the sharper one. Two direct bus lines cross a corridor of about 3.6 km, so on the map the connection looks solved. Route 704B turned out to be the one link with usable access. Everything that decided the trip stays invisible in a route list: which vehicle is coming, whether the ramp works, whether the driver will deploy it, whether the kerb is low enough to clear. The routing problem sits downstream of a data problem.

05What this does not prove

  • Two trips are not a sample. There is no statistical claim here and no deployment-scale validation; the paper lists that as future work.
  • The 24 minutes is one approximate observation. Landing within 10% means the cost terms point in a sensible direction. It is not an accuracy result, and I would not quote it as one.
  • Fifty-two bus stops against 16,956 vehicles is a sample, not coverage. Bus evidence is the thinnest layer of the graph, and the largest error will come from there.
  • The prototype and the live site are different systems. The two case numbers come from the prototype, which searches an accessibility-aware graph; the public site re-ranks AMap candidates and scores stations with TOPSIS. The cases support the modelling argument. They do not describe what the site outputs.
  • Node scores come from facility lists and user reviews, and a lift that broke last month is in neither. A stale score is worse than a missing one, because it reads as knowledge.

06What comes next

The next step is maintenance rather than search. Stop-level and vehicle-level evidence has to stay alive as route-planning data: the 127 low-floor routes are published at route level, while boarding is settled at vehicle level. That gap is also why we sent proposal letters to AMap and worked with the Minhang District public-interest prosecutors on opening accessibility data. The bottleneck is keeping data current, and no amount of modelling fixes that.

Inside the system, the questionnaire already collects the same six dimensions from riders. The comparison worth running is reported dimensions against published facility lists, ranked by how far apart they are. Those stations are where a dataset is actively steering people wrong, and fixing them costs less than any algorithm.

07What I took from it

A route card is an argument about whether you can get there. If the assumptions behind it stay hidden, the person debugging them is the traveller, at the lift, with a queue behind them.

Settling what counts as evidence took longer than the code. A lift that exists, a lift a wheelchair user can operate alone, and a lift that someone will come and operate are three different facts about the same station; only the second and third let a trip happen, and datasets usually record the first. Most of the design decisions on this project came out of that one distinction.