oswm_codebase

OSWM accessibility-aware routing

This directory contains the static browser router and the policy used to grade pedestrian-network edges for different users. It is intentionally split into a human-editable policy layer and a generic implementation layer.

Status

The distance-only profile is a neutral baseline. The wheelchair, blind/low-vision and elderly profiles are provisional: they recover useful ideas from OSWM’s historical Streamlit experiment but are not a claim that a route is guaranteed accessible. Their values require participatory calibration with users and accessibility specialists.

Files

File Responsibility
profile_rules.py Human-editable profile dictionaries
profile_validation.py Structural and numerical safety checks
grading.py Attribute normalization and grade calculation
elevation.py Elevation-provider hierarchy and slope cache
routing_demo.html Static MapLibre and PathFinder client
../generation/routing_demo_gen.py Offline routing-data generation

Policy changes should normally touch only profile_rules.py. The remaining modules should not contain profile-specific accessibility judgments.

Every profile declares a routing_mode. The distance mode minimizes segment length directly. The accessibility_grade mode consumes directional, precomputed edge grades. Exactly one distance profile is required so every accessibility route has an unambiguous comparison baseline.

Grade terminology

Negative route costs are never allowed.

Composition

Accessibility-profile factors are composed with a weighted harmonic mean:

grade = sum(weights) / sum(weight / factor_grade)

This prevents one excellent characteristic from completely hiding a very poor one. Hard barriers are evaluated first, while grade caps handle serious but not universally impassable conditions.

The generator calculates separate forward and backward grades. Terrain rising in feature-coordinate order is an ascent forward and a descent backward. The distance profile needs no grades, so no redundant distance_grade_* properties are written to every edge.

Route comparison

When an accessibility profile is selected, the browser offers Compare with distance-only. It calculates a second shortest-distance route between the same snapped points, draws it as an offset orange dashed line, and reports its distance plus the selected route’s absolute and percentage difference. The option is hidden when distance-only is already selected.

Slope source hierarchy

  1. Numeric OSM incline=*.
  2. A node-configured high-resolution DTM/COG.
  3. A node-configured regional elevation model.
  4. Copernicus DEM GLO-30 Public from the AWS Open Data Registry.
  5. Copernicus DEM GLO-90 from AWS where a public 30 m tile is unavailable.
  6. Unknown slope.

incline:across=* is independent and is never inferred from a terrain model. Copernicus GLO-30 and GLO-90 are digital surface models: their results are explicitly treated as low-confidence terrain trends, not measured sidewalk slopes. Together they provide a globally valid default for OSWM nodes.

Nodes can override the provider list through ELEVATION_CONFIG in config.py. The current template contains an example local COG entry.

Downloaded raster tiles are kept under ignored .cache/. Compact derived slopes are stored in data/routing/slope_cache.json, keyed by geometry, mapped incline and provider configuration. Unchanged edges therefore do not need to be sampled again.

Generated node files

File Contents
data/routing/demo.geojson Transitional geometry plus compact grades
data/routing/profiles.json Browser-safe labels and cost rules
data/routing/metadata.json Ruleset, provenance and grade audit
data/routing/slope_cache.json Reusable derived slopes

The GeoJSON is transitional. A future version can serialize the same precomputed properties into typed arrays/a compact topology graph without changing the human-editable rules.

Safely changing a profile

  1. Edit only the relevant values in profile_rules.py.
  2. Increment PROFILE_RULESET_VERSION.
  3. Run:

    python -m unittest discover -s tests -p "test_routing_*.py" -v
    
  4. Generate at least one node and inspect data/routing/metadata.json.
  5. Compare grade distributions and sample routes before propagating the codebase update to all nodes.

The generator records both a semantic version and a deterministic hash, making it clear which rules produced each node artifact.