Skip to content

Repository files navigation

Able Logo

Able

Navigation that adapts to you.
Accessible routing, AR guidance, and community-driven obstacle reporting for people with disabilities.

React 19 TypeScript Vite Tailwind Google Maps


About

Over 1.3 billion people worldwide live with some form of disability. When they open a navigation app, they get the same directions as everyone else — maybe with stairs filtered out if they're lucky. No consideration for the person's specific needs, the actual conditions of the path, or the hundreds of small barriers that make a "technically accessible" route practically unusable.

Able is built around a simple idea: navigation should adapt to the person, not the other way around. A blind user with a guide dog navigating downtown has completely different needs than a power wheelchair user crossing a college campus, who has completely different needs than someone with a cognitive disability trying to follow directions in an unfamiliar city. One-size-fits-all accessibility doesn't work.

The app has two parts:

  • Mobile App — A PWA with map navigation, AR camera overlay, search, obstacle reporting, and deep accessibility settings for vision, hearing, mobility, cognitive, and vestibular needs
  • Web Portal — An admin dashboard for drawing accessible routes on a map and syncing them to mobile devices in real time

Features

Navigation & AR

  • Turn-by-turn routing that adapts to the user's specific accessibility profile
  • AR overlay — point your camera and see the route rendered as a glowing line on the ground
  • Google Places search with autocomplete and geocoding fallback
  • Community obstacle reporting with photo uploads

Accessibility Profiles

  • Mobility — wheelchair (manual/power), scooter, walker, crutches, cane
  • Vision — screen reader optimization, high contrast, large text, colorblind modes (protanopia, deuteranopia, tritanopia, achromatopsia)
  • Vestibular — reduced motion, no flashing elements
  • Cognitive — simplified interfaces, clearer step-by-step instructions
  • Hearing — visual alerts, spatial audio support
  • 8 language options

Portal

  • Click-to-draw route creation on Google Maps
  • Save, delete, and push routes to mobile in real time
  • Obstacle placement and geolocation
  • Cross-device sync via a lightweight Node.js server

The Routing Algorithm

This is where Able is fundamentally different from existing navigation.

Google Maps treats accessibility as a filter — remove stairs, done. It has no idea what the path is actually like for someone who uses it. It doesn't know that the curb cut on 5th Street has a 2-inch lip that catches wheelchair casters, that the brick sidewalk downtown vibrates a power chair so badly it's painful, that the crosswalk signal at Main and 3rd doesn't have an audible indicator for blind pedestrians, or that the elevator in the parking garage breaks every other Tuesday.

Able doesn't filter paths. It understands them. Every path segment in the graph carries detailed physical metadata, and the algorithm computes a personalized traversal cost based on the specific user's disability profile. The routing engine has four layers.

Layer 1 — The Accessibility Graph

The physical world is represented as a directed graph where each edge (path segment) carries more than just distance:

  • Surface type — smooth concrete, asphalt, brick, cobblestone, gravel, dirt, grass, metal grate. Each surface affects different disabilities differently — cobblestone is jarring for wheelchair users, but also a tripping hazard for cane users and disorienting for people with vestibular disorders.
  • Running slope — percentage grade. ADA maximum is 5% for accessible routes. Steep slopes are dangerous for wheelchairs, exhausting for walker users, and a fall risk for people with balance disorders.
  • Cross-slope — lateral tilt that causes wheelchairs to drift and creates uneven footing for ambulatory users with stability challenges.
  • Width — scored against the user's minimum clearance. A wheelchair needs more space than a cane. A user with a guide dog needs more space than either.
  • Curb cut quality — flush, gradual, steep, has a lip, or missing. Affects wheelchair users directly and ambulatory disabled users who can't step off curbs.
  • Tactile paving — detectable warning surfaces critical for blind and low-vision users navigating intersections.
  • Lighting — safety factor for users with low vision, cognitive disabilities, or anyone navigating after dark.
  • Audible signals — whether crosswalks and transit stops have audible indicators for blind users.
  • Shelter — weather protection, relevant for users who can't easily manage umbrellas or rain gear while using mobility aids.

Nodes are spatially indexed on a grid (~111m cells) for fast nearest-neighbor lookups, allowing O(1) amortized coordinate-to-node snapping.

Layer 2 — Profile-Aware Cost Function

The cost of traversing an edge depends entirely on who's traversing it. Each user has an accessibility profile that specifies their needs, limitations, and preferences.

The cost function evaluates each edge in two passes:

Hard constraints return cost = ∞ (impassable):

  • Slope exceeds the user's stated maximum
  • Path narrower than minimum clearance
  • Surface type is on the user's avoid list
  • A blocking obstacle exists with >70% confidence
  • Missing tactile paving at a crossing (for users who require it)

Soft penalties scale the base distance cost using cost = distance × (1 + ΣPᵢ):

The slope penalty follows a cubic curve:

$$P_{slope}(g) = w_{slope} \cdot 2\left(\frac{g}{g_{max}}\right)^3$$

This keeps the penalty near zero for comfortable grades but ramps up sharply as you approach the user's limit — matching how difficulty is actually experienced.

Slope penalty curve
Slope penalty across mobility profiles. The cubic curve keeps comfortable grades cheap while making near-limit slopes expensive. The red line marks the ADA maximum (5%).

Each profile type has different default weights reflecting how much each factor matters for that specific disability:

Factor Manual Chair Power Chair Walker Cane Low Vision
Slope 1.0 0.5 0.7 0.5 0.3
Surface 0.7 0.8 0.5 0.6 0.4
Width 0.6 0.8 0.3 0.1 0.3
Distance 0.3 0.2 0.6 0.5 0.4
Curb Cuts 0.9 0.9 0.4 0.2 0.3
Tactile Paving 0.1 0.1 0.1 0.2 1.0
Lighting 0.2 0.2 0.3 0.3 0.9
Obstacles 0.8 0.8 0.5 0.4 0.7

Users can override any weight. A power chair user who's particularly sensitive to surface cracks can crank that weight up. A blind user who always travels with a sighted guide can reduce the tactile paving weight.

Surface penalties are assigned per material type:

Surface penalty comparison
Traversal penalty by surface type. Smooth concrete is baseline. Grass, dirt, and gravel are nearly impassable for most mobility aids and hazardous for ambulatory users with balance challenges.

Layer 3 — Crowdsourced Obstacle Intelligence

Static graph data changes slowly, but the real world is dynamic — construction, broken elevators, fallen trees, flooding, missing audible signals, temporary barriers. Our obstacle engine handles these through community reports with a decay model.

When a user reports an obstacle, it gets spatially mapped to all graph edges within 15 meters, initialized with full confidence, and the affected edges get their scores recalculated.

Time decay. Different obstacles have predictably different lifespans:

$$C(t) = 2^{-t/t_{1/2}}$$

Obstacle Half-Life Reasoning
Stairs 365 days Permanent infrastructure
Missing tactile paving 90 days Slow infrastructure fix
Cracked surface 30 days Slow to repair
No audible signal 14 days May be reported/fixed at city level
Construction 7 days Changes week to week
Broken elevator 5 days Usually repaired within a week
Blocked path 3 days Often temporary
Flooding 2 days Recedes quickly

Obstacle confidence decay curves
Confidence decay over 30 days. Temporary obstacles like floods fade quickly. Infrastructure problems like missing tactile paving persist.

Confirmation and resolution. Other users can confirm (confidence +0.3, partial age reset) or resolve (confidence -0.4) obstacles. This keeps the data accurate through community validation — a broken elevator that multiple people confirm stays flagged indefinitely, while a false report decays and disappears.

Layer 4 — Predictive Pattern Detection

The prediction engine learns from historical reports to anticipate problems before they happen:

  • Temporal patterns — "This elevator breaks on weekday mornings" → preemptive cost penalty on those days/hours
  • Recurrence detection — Obstacles that keep coming back after resolution get increasing probability scores: P = min(0.8, 0.3 + n × 0.15)
  • Spatial clustering — Dense clusters of reports in a small area suggest expanding issues (construction zones, flooding patterns). Nearby edges get preemptive penalties even without individual reports.

Pathfinding

Routes are computed with A* search using haversine distance as the heuristic (admissible — guarantees optimal paths). The pathfinder also:

  • Generates alternative routes by penalizing edges shared with the primary route
  • Attaches per-segment warnings — steep slope, narrow path, no curb cut, no tactile paving, poor lighting
  • Computes a route accessibility score (0-100) with bottleneck detection — a route is only as accessible as its worst segment
  • Estimates a fatigue index from distance, elevation, and surface difficulty

Architecture

The algorithm lives in packages/shared/src/algorithm/ as a standalone engine with no UI dependencies:

algorithm/
├── types.ts              # Graph, profile, cost, and result types
├── graph.ts              # Spatial graph with grid indexing + geo utilities
├── cost-function.ts      # Profile-aware composite cost with hard/soft constraints
├── pathfinder.ts         # A* search with min-heap and alt route generation
├── obstacle-engine.ts    # Crowdsourced reports, time decay, confirmations
├── prediction-engine.ts  # Temporal, recurrence, and spatial pattern detection
├── scoring.ts            # Route scoring, bottleneck analysis, fatigue index
└── index.ts              # Public API exports

Tech Stack

Layer Technology
Framework React 19
Language TypeScript 5.7
Build Tool Vite 6
Styling Tailwind CSS 4
State Zustand
Maps Google Maps JavaScript API
Animations Framer Motion
Icons Lucide React
Backend Firebase (Auth, Firestore)
Sync Custom Node.js sync server

Project Structure

able/
├── apps/
│   ├── mobile/          # Mobile PWA
│   │   ├── src/
│   │   │   ├── components/
│   │   │   │   ├── ar/          # Camera feed, route line, HUD
│   │   │   │   ├── map/         # Google Maps, overlays, markers
│   │   │   │   ├── navigation/  # Search, bottom sheet, step list
│   │   │   │   ├── report/      # Obstacle reporting
│   │   │   │   └── shared/      # Reusable UI components
│   │   │   ├── hooks/           # Geolocation, compass, route progress
│   │   │   ├── screens/         # Home, Navigation, AR, Settings
│   │   │   └── stores/          # Zustand state
│   │   └── public/              # PWA manifest, icons, service worker
│   ├── portal/          # Web Portal
│   │   └── src/
│   │       ├── components/      # Map, sidebar, route tools
│   │       └── stores/          # Portal state
│   └── sync-server.js   # Cross-device route sync
└── packages/
    └── shared/           # Shared types, constants, Firebase mock
        └── algorithm/    # Accessibility pathfinding engine

Getting Started

Prerequisites

  • Node.js 18+
  • npm 9+
  • Google Maps API key (Maps JS API, Places API, Geocoding API enabled)

Setup

git clone https://github.com/ajain189/Able.git
cd Able
npm install

cp .env.example apps/mobile/.env
# Add your Google Maps API key to apps/mobile/.env

Running

# Terminal 1
node apps/sync-server.js

# Terminal 2
npm run dev:mobile

# Terminal 3
npm run dev:portal

Mobile runs on https://localhost:5173, portal on http://localhost:5174.

For testing on a phone, use your machine's local IP (https://192.168.x.x:5173) and accept the self-signed cert.


Accessibility

Able is built to be accessible itself, not just route around inaccessibility:

  • WCAG 2.1 AA color contrast throughout
  • Screen reader optimized with semantic markup and ARIA labels
  • Colorblind modes — protanopia, deuteranopia, tritanopia, achromatopsia
  • Vestibular-safe reduced motion for users with motion sensitivity
  • Cognitive simplification — cleaner interfaces, simpler language, fewer choices
  • Photosensitivity protection — no flashing or strobing elements
  • 8 languages — English, Spanish, French, German, Chinese, Japanese, Korean, Arabic
  • Large text mode
  • Voice control support
  • Spatial audio cues for navigation

License

This project is proprietary. All rights reserved.

About

Wheelchair-accessible navigation PWA

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages