Skip to content

harsh-pandhe/Autonomous-Ropeway-Alignment

Autonomous Ropeway Alignment

CI Python License: MIT Tests Validation

Open-source toolchain that ingests a free DEM and two station coordinates, then emits a permit-grade aerial-ropeway alignment — tower placement, catenary cable, Eurocode safety checks, AutoCAD DXF, LandXML, 3-D digital twin, bill of materials and regional capex estimate — in under fifteen seconds on a laptop.

Validated against textbook catenary identities to 0.00 % on three reference designs, and against twelve real installations covering all six system archetypes on five continents — jig-back (Aiguille du Midi, Zugspitze, Roosevelt Island, Portland OHSU), MGD (Mi Teleférico Línea Roja, Medellín Línea K, Cablebús Línea 2, IFS Cloud London), 3S (Whistler Peak 2 Peak), funitel (Péclet, Val Thorens), BGD (Ngong Ping 360), chairlift (Whistler) — within published-spec tolerances.

No cloud. No GPU. No vendor lock-in. Runs on a consumer PC.


Headline result

Fed only the two station coordinates and a Copernicus GLO-30 DEM tile, the optimizer reproduces the world-record 2 867 m unsupported span of the Téléphérique de l'Aiguille du Midi (Stage 2) at 2 850 m — a 0.6 % delta — with no hand-tuning and no prior knowledge of the as-built design.

See docs/case_studies/aiguille_du_midi.md.


Quickstart

git clone https://github.com/harsh-pandhe/Autonomous-Ropeway-Alignment
cd Autonomous-Ropeway-Alignment

make install      # creates .venv, pip-installs everything
make demo         # 3 km synthetic terrain end-to-end run
make test         # pytest (157 tests, ~26 s)
make ui           # Streamlit UI at http://localhost:8501
ropeway serve     # FastAPI service at :8000  (docs at /docs)
docker compose up --build   # full stack: API + Postgres

To run against real terrain, download a free Copernicus GLO-30 tile:

curl -fL -o data/dem/Copernicus_DSM_N45_E006.tif \
  "https://copernicus-dem-30m.s3.eu-central-1.amazonaws.com/Copernicus_DSM_COG_10_N45_00_E006_00_DEM/Copernicus_DSM_COG_10_N45_00_E006_00_DEM.tif"

ropeway run \
  --dem data/dem/Copernicus_DSM_N45_E006.tif \
  --start 6.870 45.892 --end 6.887 45.916 \
  --system jigback --generations 60

What it does

Category Capability
Terrain ingestion Copernicus GLO-30 / NASADEM / SRTM GeoTIFF → 2-D corridor profile or 3-D terrain swath (auto UTM reprojection)
Catenary mechanics Inclined catenary kernel; sag / tension / break-over; per-span horizontal tension with sheave-loss propagation
Load model Eurocode EN 1991-1-4 wind, ISO 12494 ice, ANSI B77.1 live load (170 lbf/seat, 1.10 dynamic factor)
Safety envelope EN 12929-1 piecewise clearance (open / road / railway / building / water), wind swing buffer, foundation overturning + sliding SF, EN 1993-1-1 tower buckling + bending
Optimizers DEAP single-objective GA · pymoo NSGA-II Pareto front · stable-baselines3 PPO RL agent · scikit-learn RSM surrogate
System catalogue MGD, BGD, 3S, jig-back, chairlift, funitel — system-appropriate defaults via --system flag
Comfort ISO 2631 vertical + lateral acceleration, 4 h reduced-comfort boundary rating
Geometry Straight-line or curved (Bezier / polyline waypoint) corridors. GA + NSGA-II honour no-tower exclusion zones (avalanche / water / property / protected / military) and pinned intermediate passenger stations — towers route around forbidden terrain and the layout always contains the pinned stations
Outputs PNG plots, GeoJSON, CSV tower schedule, AutoCAD DXF, LandXML 1.2, multi-page validation PDF, interactive 3-D HTML twin, Bill of Materials, regional capex estimate
Service layer FastAPI REST API with JWT auth, role-based access, audit log, immutable snapshots, Docker stack (API + Postgres 16)

Roadmap

Phase Status Summary
1 Geospatial + catenary physics core
2 GA optimizer + Streamlit MVP UI
3 NSGA-II Pareto + RSM surrogate + LandXML + PDF report
4 PyVista 3-D digital twin + project SQLite persistence
5 Gymnasium RL env + PPO agent + GA/NSGA-II/RL benchmark
6 Eurocode wind/ice + multi-rope catalogue + comfort + validation harness
7 Curved 3-D routes + obstacle exclusion polygons
8 AutoCAD DXF + Bill of Materials + regional cost estimator
9 FastAPI service + JWT/RBAC + SQLAlchemy + audit log + Docker
9.5 DEM upload endpoint + project optimize + export endpoints + CI
11 Pricing + pitch + whitepaper + landing page
12a Eurocode 3 tower structural check (buckling + bending)
15a Case study: Aiguille du Midi + --system CLI flag
15b Case study: Mi Teleférico Línea Roja (urban gondola)
15c Case study: Whistler Peak 2 Peak (3S — motivated obstacle-zone gap)
7+ No-tower exclusion zones + pinned intermediate stations wired into GA + NSGA-II
12b Coupled elastic-cable solver (per-span elongation + thermal — hot day lowers clearance, cold day raises tension)
12c Joint horizontal + vertical alignment optimization (per-tower lateral offset within a DEM swath)
13 AI assistant (LLM natural-language → optimization) — ropeway ask "..."
14 htmx web client (shareable links) — / + /htmx/run/{rid}
12d ForcedFlyOverZone — bridge / freeway / shipping-channel corridor intervals where the cable must clear a minimum absolute elevation (dual of NoTowerZone)
12f Curved corridor DEM extraction — `extract_profile_along_route(dem, waypoints, kind="polyline"
15b-redux / 15c-redux Re-ran Línea Roja with Cementerio pinned (3-station topology now matches) + Whistler with Fitzsimmons no-tower valley (2 806 m single span, 7 % vs as-built 3 024 m, down from 47 %)
15d Case study: Roosevelt Island Tramway (NYC urban jig-back)
15e Case study: Medellín Metrocable Línea K (MGD, 4-station, 2 pinned waypoints)
15f Case study: Seilbahn Zugspitze (jig-back record span + Phase 12b thermal sweep)
15g/h/i Case studies: Funitel de Péclet, Ngong Ping 360 (BGD), Whistler chairlift — completes all six system archetypes
15j/k/l Case studies: Cablebús Línea 2 (CDMX), IFS Cloud Cable Car (London), Portland OHSU Tram — twelve installations, five continents
16 Outreach prep (videos, LinkedIn list, translations)
17 Industry validation gate (3 engineer trials)
18-23 🔒 Money phases (TÜV, ISO 9001, conferences) — locked behind validation gate

Honest scorecard: docs/SCORECARD.md — where this stands vs RopeCAD / ROPEKON / Cassia by segment.


Case studies

Case System Match Doc
Téléphérique de l'Aiguille du Midi (Stage 2) jig-back aerial tram longest span: 2 850 m vs 2 867 m as-built (0.6 %) aiguille_du_midi.md
Seilbahn Zugspitze (Eibsee) jig-back aerial tram longest span: 3 300 m vs 3 213 m as-built (+2.7 %), elevation gain 1 962 m vs 1 945 m (+0.9 %); + Phase 12b thermal sweep zugspitze_eibsee.md
Roosevelt Island Tramway (NYC) jig-back aerial tram horizontal length: 872 m vs 940 m as-built (−7.2 %); honest gap — DEM has no Queensboro Bridge roosevelt_island.md
Mi Teleférico Línea Roja (La Paz – El Alto) MGD urban gondola elevation gain: 476 m vs 485 m as-built (1.9 %); 3-station topology matches with Cementerio pinned (Phase 7+) mi_teleferico_linea_roja.md
Metrocable Línea K (Medellín) MGD urban gondola 4-station topology matches with 2 pinned waypoints (Phase 7+); elevation gain 354 m vs 405 m medellin_linea_k.md
Whistler Blackcomb Peak 2 Peak 3S tri-cable longest span: 2 806 m vs 3 024 m as-built (−7.2 %, was 47 % gap); single valley-spanning shot with Fitzsimmons no-tower zone (Phase 7+) whistler_peak2peak.md
Funitel de Péclet (Val Thorens) funitel elevation gain: 650 m vs ≈ 650 m as-built (exact); world's first funitel funitel_peclet.md
Ngong Ping 360 (Hong Kong) BGD bi-cable gondola straight-corridor 5 248 m vs 5 700 m route; reproduces the bay-crossing + hill-climb profile ngong_ping_360.md
Whistler Mountain chairlift chairlift archetype match — short spans (mean 187 m), dense towers, low tension (198 kN) whistler_peak_chair.md
Cablebús Línea 2 (CDMX) MGD urban gondola the longest urban gondola at opening (10.6 km, 7 stations); straight corridor 4 749 m baseline — 2.2× Phase 12c routing gap cablebus_linea2.md
IFS Cloud Cable Car (London) MGD urban gondola Thames crossing single span 778 m vs ≈ 800 m as-built (−2.7 %); UK's only urban cable car london_ifs_cloud.md
Portland Aerial Tram (OHSU) jig-back aerial tram elevation gain 137 m vs 152 m (−9.9 %); cabin 80 vs 79 pax (1-pax match); honest gap — DEM has no I-5 deck portland_ohsu.md

Twelve real installations now validated across all six system archetypes (jig-back, MGD, BGD, 3S, funitel, chairlift) on five continents. Phase 7+ closed the original "honest gaps": pinned stations give Línea Roja (3-station) and Medellín Línea K (4-station) like-for-like topology matches; the Fitzsimmons no-tower zone forces Whistler into its single record span. Zugspitze reproduces a world-record 3 213 m span to 2.7 % and adds the Phase 12b hot-day / cold-day thermal sensitivity sweep. London Thames + Roosevelt Island + Portland I-5 all point at the same next constraint: a forced-fly-over obstacle volume (the dual of Phase 7+ NoTowerZone).

Each case study ships with the alignment plot, AutoCAD DXF, LandXML, validation PDF, BOM CSV and regional cost estimate so reviewers can inspect every artifact without re-running.


CLI commands

Command Purpose
ropeway demo Synthetic terrain GA run (no DEM needed)
ropeway run --dem DEM --start LON LAT --end LON LAT Real DEM GA run
ropeway pareto --dem DEM ... NSGA-II Pareto front (cost / break-over / tension)
ropeway view3d --dem DEM ... Export interactive 3-D digital_twin.html
ropeway rl-train --timesteps 200000 --out outputs/rl_policy Train PPO policy
ropeway rl-run --policy outputs/rl_policy.zip Roll out trained policy
ropeway benchmark --seeds 1,2,3 GA vs NSGA-II vs RL comparison harness
ropeway validate Reference-design validation harness (3 cases, 0 % error)
ropeway serve --host 0.0.0.0 --port 8000 FastAPI service (auth / projects / optimize)

All commands accept --system mgd|bgd|3s|jigback|chair|funitel to load system-appropriate defaults from ropeway.multi_rope.

No-tower exclusion zones + pinned intermediate stations (Phase 7+)

Both the GA (ropeway.optimizer.optimize) and NSGA-II (ropeway.multi_optimizer.optimize_pareto) accept two extra parameters that close the gaps surfaced by the Linea Roja and Whistler case studies:

from ropeway.obstacles import NoTowerZone, ZoneKind
from ropeway.optimizer import optimize

result = optimize(
    profile_fn, corridor_length, cfg=cfg, ga=ga,
    no_tower_zones=[
        NoTowerZone(900.0, 1400.0, kind=ZoneKind.PROTECTED, name="Fitzsimmons Cr."),
    ],
    intermediate_stations=[1500.0],        # pinned passenger station
)
  • no_tower_zones — list of forbidden along-corridor intervals. The decoder drops GA towers in zones and snaps max-span fillers past zone edges, so a decoded layout never places a non-station tower in forbidden terrain.
  • intermediate_stations — distances of pinned passenger stations. They always appear in the layout, are flagged is_station=True (break-over-exempt, zone-exempt), and GA towers that would crowd them are dropped.

See examples/demo_no_tower_zone.py for a three-run before/after demo.


REST API

ropeway serve                            # OpenAPI docs at /docs

curl -sX POST localhost:8000/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"email":"eng@example.com","password":"supersecret123","role":"approver"}'
TOK=$(curl -sX POST localhost:8000/auth/login \
  -d 'username=eng@example.com&password=supersecret123' | jq -r .access_token)

curl -sX POST localhost:8000/projects -H "Authorization: Bearer $TOK" \
  -H 'Content-Type: application/json' -d '{"name":"My Gondola"}'

curl -sX POST localhost:8000/optimize/run -H "Authorization: Bearer $TOK" \
  -H 'Content-Type: application/json' \
  -d '{"corridor_length_m":3000,"generations":40,"population":60}'
Method Path Notes
POST /auth/{register,login}, GET /auth/me JWT issuance + bearer auth
GET / POST / PUT /projects[/{id}] CRUD with ownership + RBAC
POST /projects/{id}/{submit,approve,lock} Workflow; lock creates immutable snapshot
GET /projects/{id}/{snapshots,audit} Approval history + audit log
POST /optimize/run GA on synthetic terrain
POST /optimize/dem Multipart GeoTIFF upload + GA on real terrain
POST /projects/{id}/optimize Run GA on stored project, bump version
GET /projects/{id}/export/{fmt} fmtgeojson | csv | landxml | dxf | pdf

Architecture

src/ropeway/
  physics.py              catenary cable mechanics (textbook-validated)
  dem.py                  GeoTIFF loader, 2-D profile + 3-D corridor patch
  safety.py               EN 12929-1 + ANSI B77.1 envelope + foundation SF
  structural.py           EN 1993-1-1 tower buckling + bending
  environmental_loads.py  EN 1991-1-4 wind + ISO 12494 ice accretion
  multi_rope.py           ropeway system catalogue (MGD/BGD/3S/jigback/...)
  comfort.py              ISO 2631 passenger-comfort metrics
  tension_solver.py       per-span horizontal tension with sheave losses
  alignment.py            tower layout -> cable segments -> evaluation
  optimizer.py            DEAP GA driver
  multi_optimizer.py      pymoo NSGA-II Pareto driver
  surrogate.py            scikit-learn RSM surrogate
  rl_env.py               Gymnasium env for sequential tower placement
  rl_agent.py             PPO train + deterministic rollout
  benchmark.py            GA vs NSGA-II vs RL benchmark harness
  validation.py           reference-design diff harness
  routes.py               curved 3-D corridors (Bezier / polyline)
  obstacles.py            polygon exclusion zones
  viz.py / viz3d.py       matplotlib + PyVista visualization
  io.py / landxml.py / dxf_export.py / report.py
  bom.py / cost.py        bill of materials + regional capex estimator
  project.py              SQLite project save/load
  cli.py                  click CLI
  server/                 FastAPI service (config, db, models, schemas,
                          auth, api)
app/streamlit_app.py      desktop / browser UI
examples/                 demo scripts + case-study runners
tests/                    pytest suite (124 tests)
docs/                     case studies, GTM materials, whitepaper, pricing
.github/                  CI workflow + issue/PR templates

Validation

ropeway validate
case                               sag err   len err     T err    pass
----------------------------------------------------------------------
Alpine MGD short span                0.00%     0.00%     0.00%     YES
Bi-cable tram long span              0.00%     0.00%     0.00%     YES
3S level long span                   0.00%     0.00%     0.00%     YES
Overall: PASS

Three textbook closed-form catenary references are exercised every run. External validation (TÜV / Bureau Veritas) is on the roadmap — deferred until real industry users sign on, per Phase 17 gate criteria.


Testing

make test                                # 124 tests, ~20 s
env -u PYTHONPATH .venv/bin/pytest -v    # full verbose suite

CI (.github/workflows/ci.yml) runs pytest + the validation harness on every push / PR, plus a parallel Docker-build + container-health-check job.


DEM sources (all free)

Reprojection to UTM and nodata interpolation are handled internally.

DXF viewer: Linux has no default for image/vnd.dxf so xdg-open will fail. Install LibreCAD (sudo apt install librecad) or upload the file to https://sharecad.org for a quick browser preview.


Phase 5 finding (honest)

The Gymnasium env + PPO agent + benchmark harness all work end-to-end, but on the static single-corridor layout problem the GA / NSGA-II convincingly beat PPO. A representative benchmark (3 km synthetic corridor, 80 k training steps per RL run):

Method Feasible Mean cost Towers Wall-clock
GA 100 % 694 k 6.0 0.6 s
NSGA-II 100 % 675 k 6.0 0.9 s
PPO 0 % n/a n/a 28.6 s

PPO's value is tactical generalization across many similar problems (one trained policy, many corridors), not beating a global optimizer on one fixed corridor. Curriculum-style multi-corridor training is the natural next step; for production design work GA and NSGA-II remain the right default.


Sales / GTM docs


Contributing

PRs welcome. See CONTRIBUTING.md for the workflow (feature branch → PR → CI → squash merge) and the per-phase pattern used for everything currently in main.

Security issues: see SECURITY.md for the responsible-disclosure process. Code of conduct: CODE_OF_CONDUCT.md.


License

MIT — see LICENSE.

Standards referenced (none vendored): EN 12929-1, ANSI B77.1, EN 1991-1-3, EN 1991-1-4, EN 1993-1-1, ISO 12494, ISO 2631, EU 2016/424.

Releases

No releases published

Packages

 
 
 

Contributors

Languages