Warning: This project is under active development and is not production-ready. It is being built in public as a learning and portfolio project. APIs, data models, and features may change without notice. Do not use for actual voyage planning or navigation.
A maritime route optimization platform for Medium Range (MR) Product Tankers. Minimizes fuel consumption through weather-aware A* routing, physics-based vessel modeling, and real-time sensor fusion.
- Holtrop-Mennen resistance prediction (calm water, wind, waves)
- SFOC curves at variable engine loads
- Hull fouling calibration from operational noon reports
- Laden and ballast condition support
- Configurable vessel specifications (default: 49,000 DWT MR tanker)
- A* grid-based pathfinding with configurable resolution (0.25-2.0 degrees)
- Variable speed optimization (6-18 knots per leg)
- Seakeeping safety constraints (roll, pitch, acceleration limits)
- Land avoidance via vectorized ocean mask (global-land-mask)
- RTZ file import/export (IEC 61174 ECDIS standard)
- NOAA GFS (0.25°) for near-real-time wind fields via NOMADS GRIB filter
- 5-day wind forecast timeline (f000–f120, 3-hourly steps) with Windy-style animation
- Copernicus Marine Service (CMEMS) for wave and ocean current data
- ERA5 reanalysis as secondary wind fallback (~5-day lag)
- Climatology fallback for beyond-forecast-horizon voyages
- Unified provider that blends forecast and climatology with smooth transitions
- Pre-ingested weather database — grids compressed (zlib/float32) in PostgreSQL, served in milliseconds
- Redis shared cache across all API workers (replaces per-worker in-memory dict)
- 6-hourly background ingestion cycle with DB → live → synthetic fallback chain
- Synthetic data generator for testing and demos
- Parametric Monte Carlo with temporally correlated perturbations
- Divides voyage into up to 100 time slices (~1 per 1.2 hours)
- Cholesky decomposition of exponential temporal correlation matrix
- Log-normal perturbation model: wind σ=0.35, wave σ=0.20 (70% correlated with wind), current σ=0.15
- P10/P50/P90 confidence intervals for ETA, fuel consumption, and voyage time
- Pre-fetches multi-timestep wave forecast grids from database (0–120h)
- 100 simulations complete in <500ms
- IMO CII (Carbon Intensity Indicator) calculations with annual tightening
- Emission Control Areas (ECA/SECA) with fuel switching requirements
- High Risk Areas (HRA), Traffic Separation Schemes (TSS)
- Custom zone creation with penalty/exclusion/mandatory interactions
- GeoJSON export for frontend visualization
- SBG Electronics IMU sensor integration (roll, pitch, heave)
- FFT-based wave spectrum estimation from ship motion
- Multi-source sensor fusion engine
- Continuous model recalibration from live data
- Interactive Leaflet maps with weather overlays and route visualization
- Wind particle animation layer (leaflet-velocity)
- Forecast timeline with play/pause, speed control, and 5-day scrubbing
- Voyage calculation with per-leg fuel, speed, and ETA breakdown
- Vessel configuration and calibration panels
- CII compliance tracking and projections
- Dark maritime theme, responsive design
windmar/
├── api/ # FastAPI backend
│ ├── main.py # API endpoints, weather ingestion loop, DB provider chain
│ ├── auth.py # API key authentication (bcrypt)
│ ├── config.py # API configuration (pydantic-settings)
│ ├── middleware.py # Security headers, structured logging, metrics
│ ├── rate_limit.py # Token bucket rate limiter (Redis-backed)
│ ├── database.py # SQLAlchemy ORM setup
│ ├── models.py # Database models
│ ├── health.py # Health check logic
│ ├── state.py # Thread-safe application state
│ ├── cache.py # Weather data caching (Redis shared cache)
│ ├── resilience.py # Circuit breakers
│ ├── cli.py # CLI utilities
│ └── live.py # Live sensor data API router
├── src/
│ ├── optimization/
│ │ ├── vessel_model.py # Holtrop-Mennen fuel consumption model
│ │ ├── route_optimizer.py # A* pathfinding with weather costs
│ │ ├── voyage.py # Per-leg voyage calculator (LegWeather, VoyageResult)
│ │ ├── monte_carlo.py # Temporal MC simulation with Cholesky correlation
│ │ ├── grid_weather_provider.py # Bilinear interpolation from pre-fetched grids
│ │ ├── vessel_calibration.py # Noon report calibration (scipy)
│ │ └── seakeeping.py # Ship motion safety assessment
│ ├── data/
│ │ ├── copernicus.py # GFS, ERA5, CMEMS providers + forecast prefetch
│ │ ├── db_weather_provider.py # DB-backed weather (compressed grids from PostgreSQL)
│ │ ├── weather_ingestion.py # Scheduled weather grid ingestion service
│ │ ├── regulatory_zones.py # Zone management and point-in-polygon
│ │ ├── eca_zones.py # ECA zone definitions
│ │ └── land_mask.py # Ocean/land detection
│ ├── sensors/
│ │ ├── sbg_nmea.py # SBG IMU NMEA parsing
│ │ ├── sbg_ellipse.py # SBG Ellipse sensor driver
│ │ └── wave_estimator.py # FFT wave spectrum from heave data
│ ├── fusion/
│ │ └── fusion_engine.py # Multi-source data fusion
│ ├── compliance/
│ │ └── cii.py # IMO CII rating calculations
│ ├── routes/
│ │ └── rtz_parser.py # RTZ XML route file parser
│ ├── validation.py # Input validation
│ ├── config.py # Application configuration
│ └── metrics.py # Performance metrics collection
├── frontend/ # Next.js 15 + TypeScript
│ ├── app/ # Pages (route planner, fuel analysis, vessel config, CII, live dashboard)
│ ├── components/ # React components (maps, charts, weather layers, forecast timeline)
│ └── lib/ # API client, utilities
├── tests/
│ ├── unit/ # Vessel model, router, validation, ECA zones, Excel parser, CII, calibration, SBG NMEA, metrics
│ ├── integration/ # API endpoints, optimization flow
│ └── test_e2e_*.py # End-to-end sensor integration
├── examples/ # Demo scripts (simple, ARA-MED, calibration)
├── docker/ # init-db.sql, migrations/ (weather tables)
├── data/ # Runtime data (GRIB cache, calibration, climatology)
├── docker-compose.yml # Full stack (API + frontend + PostgreSQL + Redis)
├── Dockerfile # Multi-stage production build
└── pyproject.toml # Poetry project definition
| Layer | Technology |
|---|---|
| Backend | FastAPI, Uvicorn, Python 3.10+ |
| Frontend | Next.js 15, TypeScript, React, Tailwind CSS |
| Maps | React Leaflet |
| Charts | Recharts |
| Database | PostgreSQL 16, SQLAlchemy |
| Cache | Redis 7 |
| Scientific | NumPy, SciPy, Pandas |
| Auth | API keys, bcrypt |
| Containerization | Docker, Docker Compose |
git clone https://github.com/SL-Mar/Windmar.git
cd Windmar
cp .env.example .env # Edit with your settings
docker compose up -d --buildServices start on:
| Service | URL |
|---|---|
| Frontend | http://localhost:3000 |
| API | http://localhost:8000 |
| API Docs (Swagger) | http://localhost:8000/api/docs |
| PostgreSQL | localhost:5432 |
| Redis | localhost:6379 |
# Backend
pip install -r requirements.txt
python api/main.py
# Frontend (separate terminal)
cd frontend
npm install --legacy-peer-deps
npm run devpython examples/demo_simple.py # Synthetic weather demo
python examples/example_ara_med.py # Rotterdam to Augusta optimization
python examples/example_calibration.py # Noon report calibrationCopy .env.example to .env and configure:
| Variable | Description | Default |
|---|---|---|
ENVIRONMENT |
development / staging / production | development |
DATABASE_URL |
PostgreSQL connection string | postgresql://windmar:...@db:5432/windmar |
REDIS_URL |
Redis connection string | redis://:...@redis:6379/0 |
API_SECRET_KEY |
API key hashing secret | (generate with openssl rand -hex 32) |
CORS_ORIGINS |
Allowed frontend origins | http://localhost:3000 |
COPERNICUS_MOCK_MODE |
Use synthetic weather data | true |
AUTH_ENABLED |
Require API key authentication | true |
RATE_LIMIT_PER_MINUTE |
API rate limit | 60 |
Windmar uses a three-tier provider chain that automatically falls back when a source is unavailable:
| Data Type | Primary Source | Fallback | Credentials Required |
|---|---|---|---|
| Wind | NOAA GFS (0.25°, ~3.5h lag) | ERA5 reanalysis → Synthetic | None (GFS is free) |
| Waves | CMEMS global wave model | Synthetic | CMEMS account |
| Currents | CMEMS global physics model | Synthetic | CMEMS account |
| Forecast | GFS f000–f120 (5-day, 3h steps) | — | None |
Wind data works out of the box — GFS is fetched from NOAA NOMADS without authentication. For wave and current data, you need Copernicus Marine credentials.
CMEMS (waves and currents):
- Register at marine.copernicus.eu
- Set in
.env:COPERNICUSMARINE_SERVICE_USERNAME=your_username COPERNICUSMARINE_SERVICE_PASSWORD=your_password
CDS ERA5 (wind fallback):
- Register at cds.climate.copernicus.eu
- Copy your Personal Access Token from your profile page
- Set in
.env:CDSAPI_KEY=your_personal_access_token
Without these credentials, the system falls back to synthetic data automatically for waves and currents. Wind visualization always works via GFS.
See the Weather Data Documentation for full technical details on data acquisition, GRIB processing, and the forecast timeline.
See the Monte Carlo Simulation article for the mathematical framework behind the temporal perturbation model.
GET /api/weather/wind- Wind field grid (U/V components)GET /api/weather/wind/velocity- Wind in leaflet-velocity format (GFS)GET /api/weather/waves- Wave height field (CMEMS)GET /api/weather/currents- Ocean current field (CMEMS)GET /api/weather/currents/velocity- Currents in leaflet-velocity formatGET /api/weather/point- Weather at specific coordinates
GET /api/weather/forecast/status- GFS prefetch progress and run infoPOST /api/weather/forecast/prefetch- Trigger 5-day forecast download (f000–f120)GET /api/weather/forecast/frames- Bulk download all forecast frames
GET /api/weather/forecast/wave/status- Wave forecast prefetch progressPOST /api/weather/forecast/wave/prefetch- Trigger wave forecast downloadGET /api/weather/forecast/wave/frames- Bulk download wave forecast frames
POST /api/routes/parse-rtz- Parse RTZ route filePOST /api/routes/from-waypoints- Create route from coordinates
POST /api/voyage/calculate- Full voyage calculation with weatherGET /api/voyage/weather-along-route- Weather conditions per waypoint
POST /api/voyage/monte-carlo- Parametric MC simulation (P10/P50/P90)
POST /api/optimize/route- A* weather-optimal route findingGET /api/optimize/status- Optimizer configuration and available targets
POST /api/weather/ingest- Trigger immediate weather ingestion cycleGET /api/weather/ingest/status- Latest ingestion run info and grid countsGET /api/weather/freshness- Weather data age indicator
GET /api/vessel/specs- Current vessel specificationsPOST /api/vessel/specs- Update vessel specificationsGET /api/vessel/calibration- Current calibration factorsPOST /api/vessel/calibration/set- Manually set calibration factorsPOST /api/vessel/calibrate- Run calibration from noon reportsPOST /api/vessel/calibration/estimate-fouling- Estimate hull fouling factorGET /api/vessel/noon-reports- List uploaded noon reportsPOST /api/vessel/noon-reports- Add a single noon reportPOST /api/vessel/noon-reports/upload-csv- Upload operational data (CSV)DELETE /api/vessel/noon-reports- Clear all noon reports
GET /api/zones- All regulatory zones (GeoJSON)GET /api/zones/list- Zone summary listGET /api/zones/{zone_id}- Single zone detailsPOST /api/zones- Create custom zoneDELETE /api/zones/{zone_id}- Delete a custom zoneGET /api/zones/at-point- Zones at specific coordinatesGET /api/zones/check-path- Check zone intersections along a route
GET /api/cii/vessel-types- IMO vessel type categoriesGET /api/cii/fuel-types- Fuel types and CO2 emission factorsPOST /api/cii/calculate- Calculate CII ratingPOST /api/cii/project- Multi-year CII projectionPOST /api/cii/reduction- Required fuel reduction for target rating
GET /api/live/status- Sensor connection statusPOST /api/live/connect- Connect to SBG IMU sensorPOST /api/live/disconnect- Disconnect sensorGET /api/live/data- Current fused sensor dataGET /api/live/timeseries/{channel}- Time series for a specific channelGET /api/live/timeseries- All time series dataGET /api/live/motion/statistics- Motion statistics (roll, pitch, heave)GET /api/live/channels- Available data channelsPOST /api/live/export- Export recorded data
GET /api/health- Health checkGET /api/health/live- Liveness probeGET /api/health/ready- Readiness probeGET /api/status- Application status summaryGET /api/metrics- Prometheus metricsGET /api/metrics/json- Metrics in JSON formatGET /api/data-sources- Weather data source configuration
Full interactive documentation at /api/docs when the server is running.
pytest tests/ -v # All tests
pytest tests/unit/ -v # Unit tests only
pytest tests/integration/ -v # Integration tests
pytest tests/unit/test_vessel_model.py -v # Specific test fileThe system ships with a default MR Product Tanker configuration:
| Parameter | Value |
|---|---|
| DWT | 49,000 MT |
| LOA / Beam | 183m / 32m |
| Draft (laden / ballast) | 11.8m / 6.5m |
| Main Engine | 8,840 kW |
| SFOC at MCR | 171 g/kWh |
| Service Speed (laden / ballast) | 14.5 / 15.0 knots |
Pre-ingested weather grids in PostgreSQL, eliminating live download latency during route calculations.
- Weather ingestion service — background task downloads CMEMS wave/current and GFS wind grids every 6 hours, compresses with zlib (float32), stores in PostgreSQL (
weather_forecast_runs+weather_grid_datatables) - DB weather provider —
DbWeatherProviderreads compressed grids, crops to route bounding box, returnsWeatherDataobjects compatible withGridWeatherProvider - Multi-tier fallback chain — Redis shared cache → DB pre-ingested → live CMEMS/GFS → synthetic
- Redis shared cache — replaces per-worker in-memory dict, all 4 Uvicorn workers share weather data
- Frontend freshness indicator — shows weather data age (green/yellow/red) in map overlay controls
- Performance: route optimization from ~90-180s → 2-5s; voyage calculation from minutes → sub-second
Component architecture refactor and Monte Carlo simulation engine.
- Frontend component split — monolithic
page.tsxrefactored into reusable components (MapOverlayControls,VoyagePanel,AnalysisTab, etc.) - Monte Carlo simulation — N=100 parametric simulation engine with P10/P50/P90 confidence intervals for ETA, fuel, and voyage time
- GridWeatherProvider — bilinear interpolation from pre-fetched weather grids (microsecond-level lookups vs. per-leg API calls), enabling 1000x faster A* routing
- Analysis tab — persistent storage of voyage results for comparison across routes
Live connectivity to Copernicus and NOAA weather services.
- CMEMS wave and current data — Copernicus Marine Service API integration with swell/wind-wave decomposition for accurate seakeeping
- GFS 5-day wind forecast timeline — f000–f120 (3-hourly steps) with Windy-style particle animation on the map
- ERA5 wind fallback — Climate Data Store reanalysis as secondary wind source (~5-day lag)
- Data sources documentation — credential setup guide, provider chain documentation
- Weather data page — dedicated documentation for acquisition, GRIB processing, forecast timeline
main- Stable release branchdevelopment- Integration branch for features in progressfeature/*- Feature branches for experimental work
Licensed under the Apache License, Version 2.0.
SL Mar