ORS java - isochrones

Hello,
With my code, I want to generate isochrones in La Réunion : ESPG 2975 I have an issue with my code; it does not generate isochrones when I give it the right order of longitude and latitude. And when I give it an uncorrect order, it gives me isochrones in Guadeloupe. Can you help figure this out ? :

This is my code :

import os
import json
import logging
import pandas as pd
import geopandas as gpd
import geopandas as gpd
import openrouteservice
from shapely.geometry import shape
from tqdm import tqdm

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

############################################################
# 1) Paramètres
############################################################
ORS_BASE_URL = "http://localhost:8082/ors"
profile = "cycling-regular"          # foot-walking, cycling-regular, etc.
geography = "laReunion"
range_val = 900
interval_val = 300

# Chemin vers shapefile en EPSG:2975
path_carreaux = r"D:\ECOLAB\GD4H\lareunion_carreaux_200m_shp\Filosofi2015_carreaux_200m_shp\Filosofi2015_carreaux_200m_reg04.shp"

# Fichier de sortie .jsonl
output_file = f"out/results_{profile}_{geography}_{range_val}_{interval_val}.jsonl"
os.makedirs("out", exist_ok=True)

############################################################
# 2) Lecture du shapefile (EPSG:2975) et reprojection en EPSG:4326
############################################################
logging.info("Lecture du shapefile et reprojection vers EPSG:4326")
carreaus = gpd.read_file(path_carreaux)
# Reprojection -> EPSG:4326
carreaus = carreaus.to_crs(epsg=4326)

# Calcul du centroïde en WGS84
carreaus["centroid"] = carreaus.geometry.centroid
logging.info(f"Carreaux chargés : {len(carreaus)} lignes.")

############################################################
# 3) Initialisation du client ORS et vérification range
############################################################
try:
    range_val = int(range_val)
    interval_val = int(interval_val)
except Exception as exc:
    logging.error(f"Range et interval doivent être numériques. Erreur: {exc}")
    exit(1)

client = openrouteservice.Client(base_url=ORS_BASE_URL)

############################################################
# 4) Boucle : calcul des isochrones et écriture dans JSONL
############################################################
logging.info("Génération des isochrones (lon, lat)")
with open(output_file, "w", encoding="utf-8") as f_out:
    for idx, row in tqdm(carreaus.iterrows(), total=len(carreaus), desc="Isochrones"):
        c = row["centroid"]
        if c.is_empty:
            continue

        # (lon, lat) = (y, x) en EPSG:4326
        lon, lat = round(c.x, 6), round(c.y, 6)
        # Identifiant du carreau
        id_carreau = row.get("Idcar_200m", f"carreau_{idx}")

        try:
            resp = client.isochrones(
                locations=[(lon, lat)],  # OpenRouteService attend (lon, lat) en degrés
                profile=profile,
                range=[range_val],
                interval=interval_val
            )
            resp["Idcar_200m"] = id_carreau
            f_out.write(json.dumps(resp) + "\n")

        except Exception as e:
            logging.error(f"Erreur carreau={id_carreau}, coords=({lon},{lat}): {e}")

logging.info(f"Isochrones terminées, fichier généré : {output_file}")

############################################################
# 5) Lecture du fichier JSONL et construction du GeoDataFrame
############################################################
logging.info("Lecture du fichier .jsonl et construction du GDF (EPSG:4326)")
records = []
with open(output_file, "r", encoding="utf-8") as f_in:
    for line in f_in:
        rec = json.loads(line.strip())
        records.append(rec)

df_iso = pd.DataFrame(records)

all_features = []
for _, r in df_iso.iterrows():
    if "features" in r:
        for feat in r["features"]:
            feat["Idcar_200m"] = r.get("Idcar_200m", None)
            all_features.append(feat)

df_feats = pd.DataFrame(all_features)
df_feats["geometry"] = df_feats["geometry"].apply(lambda g: shape(g))

# Les isochrones d’ORS sont déjà en WGS84
isochrone_gdf = gpd.GeoDataFrame(df_feats, geometry="geometry", crs="EPSG:4326")
isochrone_gdf["profile"] = profile

logging.info(f"Isochrone_gdf construit avec {len(isochrone_gdf)} features !")
print(isochrone_gdf.head())

and here is my ors-config.yml :

ors:
  # 1) Tell ORS which services we want active and which profiles to use
  services:
    routing:
      enabled: true
      profiles:
        active:
          - name: driving-car
            profiles: ["driving-car"]
          - name: foot-walking
            profiles: ["foot-walking"]
          - name: cycling-regular
            profiles: ["cycling-regular"]

  # 2) The engine section: how to build graphs and define each profile
  engine:
    # Default build settings for the routing graphs
    profile_default:
      build:
        source_file: "D:/ECOLAB/reunion-latest.osm.pbf"
        # If you are running inside Docker, consider how volumes are mapped
        # so that ORS can actually see this path.
    # Define each profile’s details (here, just enabling them)
    profiles:
      driving-car:
        enabled: true
      foot-walking:
        enabled: true
      cycling-regular:
        enabled: true

  # Optional: Logging, or other top-level sections
  logging:
    # ... 
    level: INFO
    # ...

here is an example of error I am getting :

2025-03-21 15:37:38 [ERROR] Erreur carreau=carreau_3589, coords=(55.526258,-21.26961): 400 ({'error': {'code': 3012, 'message': "Parameter 'interval' is out of range: Resulting number of 3 isochrones exceeds maximum value of 1."}, 'info': {'engine': {'build_date': '2025-01-29T12:41:18Z', 'graph_version': '1', 'version': '9.1.0'}, 'timestamp': 1742567858933}})

I would appreciate your help,
Salma

Hey,

that is a config issue that should have an easy fix:

The default number of maximum intervals per location is 1.
On version 9, this can be changed with the

ors.endpoints.isochrones.maximum_intervals

parameter, which you’d have to set higher than 1.
See also our backend documentation at:

It also looks like your config is a bit outdated - are you running ors v9 or later?

Best regards

1 Like

Thanks a lot for your reply ! I am running ors “9.1.0”. I corrected that interval issue. But for people reading this, another issue was the fact that ors built graphs from a previous graph done for another location. So be sure to erase your graphs folder when you switch locations

1 Like