Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
c85c55d
mapbox profile specific voice instructions (#3165)
OlafFlebbeBosch Jul 18, 2025
087bacd
Update maps to c688588a
karussell Jul 18, 2025
a148d51
Trip-Based Public Transit Routing (#3184)
michaz Aug 5, 2025
5b1f142
fix: enable last intersection of last step before a via point (#3176)
OlafFlebbeBosch Aug 7, 2025
0fb184c
test fix (#3176)
karussell Aug 7, 2025
1c00fb1
update dropwizard to 3.0.15 and jts to 1.20.0, fixes #3185
karussell Aug 8, 2025
c43535d
added back 25-ea version, fixes #3166
karussell Aug 12, 2025
0bf3b7e
hike profile: allow more sac_scales but include warning in GH Maps ab…
karussell Aug 20, 2025
11c42b3
Upgrade dropwizard to 4.0.15 (#3188)
karussell Aug 25, 2025
1b5360e
fix profile config name
karussell Aug 25, 2025
584dae7
make navigation mode more customizable (#3193)
karussell Aug 26, 2025
0bcabad
Trunk roads are not generally toll roads in Austria (#3191)
tyrasd Aug 27, 2025
6aea942
Update changelog and contributors #3190
easbar Aug 27, 2025
de222a5
Upgrade dropwizard to 4.0.16
karussell Aug 28, 2025
32f6397
allow private for bike & foot and limit bike speed for destination, f…
karussell Sep 11, 2025
f42f901
fix foot.json, #3186
karussell Sep 11, 2025
ca50310
use jdk25 and jdk26-ea for build
karussell Sep 24, 2025
e06d45b
minor improvement of roundabout instruction, related to #3180
karussell Sep 24, 2025
28f11e6
scriptable turn statements (#3174)
karussell Sep 24, 2025
eff38f7
model: avoid DELIVERY too
karussell Sep 24, 2025
b10cee9
higher penalty for destination-only villages like Heitersberg (mentio…
karussell Sep 24, 2025
84fa528
new change_angle path detail
karussell Sep 29, 2025
57ce89d
rename avoid_private_etc.json to more specific
karussell Sep 29, 2025
89cf274
minor fix for bike_tc.json
karussell Sep 29, 2025
d914084
update GH maps to f171bcf
karussell Sep 29, 2025
844e182
minor fix for bike_avoid_private_etc.json
karussell Sep 30, 2025
f2ccc05
NLD: trunk not always hgv toll, similar to #3191
karussell Oct 2, 2025
79804c2
i18n: pt_BR improvements from @PabloaRuiz
karussell Oct 4, 2025
c84fcf5
foot: only soft avoidance for mtb:scale, #3050
karussell Oct 6, 2025
cd716e9
Get storage from CH graph
easbar Oct 8, 2025
b2652a9
car routing possible on pedestrian ways where allowed (#3203)
karussell Oct 8, 2025
57169b1
i18n: update of pt_BR, @PabloaRuiz
karussell Oct 13, 2025
1d2f414
ramer smoothing: use 2D total distance for averageSlope (#3205)
karussell Oct 14, 2025
bbddd8c
fix wrong mode in navigation steps (#3207)
binora Oct 14, 2025
7312590
larger matrix request can take longer
karussell Oct 14, 2025
69e50f6
release 11.0
karussell Oct 14, 2025
f12734e
changed to 12.0-SNAPSHOT
karussell Oct 14, 2025
78e9397
deployment: change to central plugin
karussell Oct 14, 2025
05168e6
2025
karussell Oct 14, 2025
924e954
Log CH sizes
easbar Oct 15, 2025
5626d06
add 'service' to the private handling for way/457306782
karussell Oct 15, 2025
1eaadfa
getLast
easbar Oct 17, 2025
bfa0f3c
Improve bike speed handling (#3214)
karussell Oct 24, 2025
6fd6490
Allow not loading a profile
easbar Oct 27, 2025
be761ae
Don't adjust bicycle speed for highway=service when highway is design…
ratrun Oct 27, 2025
91c4357
racingbike: increase from 20km/h to 24km/h (#3218)
karussell Oct 27, 2025
04da9a2
Mtb route network fix (#3217)
karussell Oct 27, 2025
ff97d18
Log low- and high-weight CH shortcuts
easbar Oct 28, 2025
acccadb
Log minimum and maximum valid shortcut weights.
easbar Oct 28, 2025
d95ce7f
Merge log lines
easbar Oct 29, 2025
71f4e49
Merge branch 'master' into update
GeoffreyFardeau Oct 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
strategy:
fail-fast: false
matrix:
java-version: [ 24 ]
java-version: [ 25, 26-ea ]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish-maven-central.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ jobs:
mvn -B versions:set -DnewVersion=$GITHUB_REF_NAME -DgenerateBackupPoms=false
mvn deploy -P release -DskipTests=true -Dpgp.secretkey=keyring:id=0E2FBADB -B
env:
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
MAVEN_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
### 11.0 [not yet released]
### 12.0 [not yet released]



### 11.0 [14 Oct 2025]

- country-dependent toll rules are now always enabled. in the absence of explicit tags or special toll rules we use Toll.NO instead of Toll.MISSING #3111
- max_weight_except: changed NONE to MISSING
Expand All @@ -7,6 +11,7 @@
- car.json by default avoids private roads
- maxspeed<5 is ignored, maxspeed=none is ignored with some exceptions, maxspeed parsing and related constants were renamed #3077
- improved performance by sorting graph during import, #3177
- trunk roads in Austria are no longer considered to be toll roads by default

### 10.0 [5 Nov 2024]

Expand Down
4 changes: 4 additions & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Here is an overview:
* jessLryan, max elevation can now be negative
* joe-akeem, improvements like #2158
* JohannesPelzer, improved GPX information and various other things
* karololszacki, introduce `navigation_mode` option for Profiles to easily set which Voice Guidance distances to use
* karussell, one of the core developers
* khuebner, initial turn costs support
* kodonnell, adding support for CH and other algorithms (#60) and penalizing inner-link U-turns (#88)
Expand All @@ -71,6 +72,7 @@ Here is an overview:
* osamaalmaani, added missing config option for graph.encoded_values in the config-example.yml file
* oschlueter, fixes like #1185
* otbutz, added multiple EncodedValues
* PabloaRuiz, pt_BR 1i8n improvements
* pantsleftinwash, speed parsing improvements
* PGWelch, shapefile reader #874
* rafaelstelles, fix deserializer web-api
Expand All @@ -89,8 +91,10 @@ Here is an overview:
* Svantulden, improved documentation and nearest API
* taulinger, hopefully more to come
* thehereward, code cleanups like #620
* tyrasd, improved toll road handling in Austria #3190
* vvikas, ideas for many to many improvements and #616
* zstadler, multiple fixes and car4wd
* binora, fix mode in navigation response converter

## Translations

Expand Down
2 changes: 1 addition & 1 deletion NOTICE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

GraphHopper licensed under the Apache license, Version 2.0

Copyright 2012 - 2024 GraphHopper GmbH
Copyright 2012 - 2025 GraphHopper GmbH

The core module includes the following additional software:

Expand Down
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,18 @@ to get started with contribution.

To get started you can try [GraphHopper Maps](README.md#graphhopper-maps), read through [our documentation](./docs/index.md) and install GraphHopper including the Maps UI locally.

* 10.x: [documentation](https://github.com/graphhopper/graphhopper/blob/10.x/docs/index.md)
, [web service jar](https://repo1.maven.org/maven2/com/graphhopper/graphhopper-web/10.0/graphhopper-web-10.0.jar)
, [announcement](https://www.graphhopper.com/blog/2024/11/05/graphhopper-routing-engine-10-0-released/)
* 11.x: [documentation](https://github.com/graphhopper/graphhopper/blob/11.x/docs/index.md)
, [web service jar](https://repo1.maven.org/maven2/com/graphhopper/graphhopper-web/11.0/graphhopper-web-11.0.jar)
, [announcement](https://www.graphhopper.com/blog/2025/10/14/graphhopper-routing-engine-11-0-released/)
* unstable master: [documentation](https://github.com/graphhopper/graphhopper/blob/master/docs/index.md)

See the [changelog file](./CHANGELOG.md) for Java API Changes.

<details><summary>Click to see older releases</summary>

* 10.x: [documentation](https://github.com/graphhopper/graphhopper/blob/10.x/docs/index.md)
, [web service jar](https://repo1.maven.org/maven2/com/graphhopper/graphhopper-web/10.0/graphhopper-web-10.0.jar)
, [announcement](https://www.graphhopper.com/blog/2024/11/05/graphhopper-routing-engine-10-0-released/)
* 9.x: [documentation](https://github.com/graphhopper/graphhopper/blob/9.x/docs/index.md)
, [web service jar](https://repo1.maven.org/maven2/com/graphhopper/graphhopper-web/9.1/graphhopper-web-9.1.jar)
, [announcement](https://www.graphhopper.com/blog/2024/04/23/graphhopper-routing-engine-9-0-released)
Expand Down Expand Up @@ -103,8 +106,8 @@ See the [changelog file](./CHANGELOG.md) for Java API Changes.
To install the [GraphHopper Maps](https://graphhopper.com/maps/) UI and the web service locally you [need a JVM](https://adoptium.net) (>= Java 17) and do:

```bash
wget https://repo1.maven.org/maven2/com/graphhopper/graphhopper-web/10.0/graphhopper-web-10.0.jar \
https://raw.githubusercontent.com/graphhopper/graphhopper/10.x/config-example.yml \
wget https://repo1.maven.org/maven2/com/graphhopper/graphhopper-web/11.0/graphhopper-web-11.0.jar \
https://raw.githubusercontent.com/graphhopper/graphhopper/11.x/config-example.yml \
http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
java -D"dw.graphhopper.datareader.file=berlin-latest.osm.pbf" -jar graphhopper*.jar server config-example.yml
```
Expand Down
4 changes: 2 additions & 2 deletions client-hc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>directions-api-client-hc</artifactId>
<version>11.0-SNAPSHOT</version>
<version>12.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>GraphHopper Directions API hand-crafted Java Client.</name>

<parent>
<groupId>com.graphhopper</groupId>
<artifactId>graphhopper-parent</artifactId>
<version>11.0-SNAPSHOT</version>
<version>12.0-SNAPSHOT</version>
</parent>

<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public GHMatrixSyncRequester() {
public GHMatrixSyncRequester(String serviceUrl) {
this(serviceUrl, new OkHttpClient.Builder().
connectTimeout(5, TimeUnit.SECONDS).
readTimeout(5, TimeUnit.SECONDS).build(), true);
readTimeout(15, TimeUnit.SECONDS).build(), true);
}

public GHMatrixSyncRequester(String serviceUrl, OkHttpClient client, boolean doRequestGzip) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public void customModel() throws JsonProcessingException {
"{\"id\":\"area_1\",\"type\":\"Feature\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[48.019324184801185,11.28021240234375],[48.019324184801185,11.53564453125],[48.11843396091691,11.53564453125],[48.11843396091691,11.28021240234375],[48.019324184801185,11.28021240234375]]]},\"properties\":{}}," +
"{\"id\":\"area_2\",\"type\":\"Feature\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[48.15509285476017,11.53289794921875],[48.15509285476017,11.8212890625],[48.281365151571755,11.8212890625],[48.281365151571755,11.53289794921875],[48.15509285476017,11.53289794921875]]]},\"properties\":{}}]}," +
"\"priority\":[{\"if\":\"surface == DIRT\",\"multiply_by\":\"0.7\"},{\"if\":\"surface == SAND\",\"multiply_by\":\"0.6\"}]," +
"\"speed\":[{\"if\":\"road_class == MOTORWAY\",\"limit_to\":\"80\"}]}");
"\"speed\":[{\"if\":\"road_class == MOTORWAY\",\"limit_to\":\"80\"}],\"turn_penalty\":[]}");
assertEquals(expected, objectMapper.valueToTree(customModelJson));

CustomModel cm = objectMapper.readValue("{\"distance_influence\":null}", CustomModel.class);
Expand Down
30 changes: 22 additions & 8 deletions config-example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ graphhopper:
# turn_costs:
# vehicle_types: [motorcar, motor_vehicle]
# u_turn_costs: 60
# for more advanced turn costs, see #2957 or bike_tc.yml
# for more advanced turn costs see avoid_turns.json
custom_model_files: [car.json]

# You can use the following in-built profiles. After you start GraphHopper it will print which encoded values you'll have to add to graph.encoded_values in this config file.
Expand All @@ -50,13 +50,26 @@ graphhopper:
# - name: mtb
# custom_model_files: [mtb.json, bike_elevation.json]
#
# - name: custom_profile
# navigation_mode: bike
# turn_costs:
# vehicle_types: [bicycle]
# u_turn_costs: 10
# custom_model_files: [your_custom_model.json]
#
# # See the bus.json for more details.
# - name: bus
# turn_costs:
# vehicle_types: [bus, motor_vehicle]
# u_turn_costs: 60
# turn_costs:
# vehicle_types: [bus, motor_vehicle]
# u_turn_costs: 60
# custom_model_files: [bus.json]
#
# You can configure a profile with turn costs like "3 seconds for left" and "5 seconds for right turns" via:
# 1. add the turn_costs entry to the profile (see e.g. the car profile)
# 2. add orientation to the graph.encoded_values list
# 3. add avoid_turns.json to the custom_model_files
# Edit avoid_turns.json or create your own JSON file and put it into the "custom_models.directory". See also bike_tc.yml.
#
# Other custom models not listed here are: car4wd.json, motorcycle.json, truck.json or cargo-bike.json. You might need to modify and test them before production usage.
# See ./core/src/main/resources/com/graphhopper/custom_models and let us know if you customize them, improve them or create new onces!
# Also there is the curvature.json custom model which might be useful for a motorcyle profile or the opposite for a truck profile.
Expand All @@ -69,7 +82,7 @@ graphhopper:
# more RAM/disk space for holding the prepared graph but also means less memory usage per request. Using the following
# list you can define for which of the above routing profiles such preparation shall be performed. Note that to support
# profiles with `turn_costs` a more elaborate preparation is required (longer preparation time and more memory
# usage) and the routing will also be slower than with `turn_costs: false`.
# usage) and the routing will also be slower than without `turn_costs`.
profiles_ch:
- profile: car

Expand All @@ -92,8 +105,10 @@ graphhopper:
# surface,smoothness,max_width,max_height,max_weight,max_weight_except,hgv,max_axle_load,max_length,
# hazmat,hazmat_tunnel,hazmat_water,lanes,osm_way_id,toll,track_type,mtb_rating,hike_rating,horse_rating,
# country,curvature,average_slope,max_slope,car_temporal_access,bike_temporal_access,foot_temporal_access

graph.encoded_values: car_access, car_average_speed, road_access, barrier


#### Speed, hybrid and flexible mode ####

# To make CH preparation faster for multiple profiles you can increase the default threads if you have enough RAM.
Expand Down Expand Up @@ -131,7 +146,6 @@ graphhopper:
# window size in meter along a way used for averaging a node's elevation
# graph.elevation.edge_smoothing.moving_average.window_size: 150


# To increase elevation profile resolution, use the following two parameters to tune the extra resolution you need
# against the additional storage space used for edge geometries. You should enable bilinear interpolation when using
# these features (see #1953 for details).
Expand Down Expand Up @@ -197,11 +211,11 @@ graphhopper:
#### Storage ####

# Excludes certain types of highways during the OSM import to speed up the process and reduce the size of the graph.
# A typical application is excluding 'footway','cycleway','path' and maybe 'pedestrian' and 'track' highways for
# A typical application is excluding 'footway','cycleway','path' and maybe 'track' highways for
# motorized vehicles. This leads to a smaller and less dense graph, because there are fewer ways (obviously),
# but also because there are fewer crossings between highways (=junctions).
# Another typical example is excluding 'motorway', 'trunk' and maybe 'primary' highways for bicycle or pedestrian routing.
import.osm.ignored_highways: footway,construction,cycleway,path,pedestrian,steps # typically useful for motorized-only routing
import.osm.ignored_highways: footway,construction,cycleway,path,steps # typically useful for motorized-only routing
# import.osm.ignored_highways: motorway,trunk # typically useful for non-motorized routing

# configure the memory access, use RAM_STORE for well equipped servers (default and recommended)
Expand Down
4 changes: 2 additions & 2 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<artifactId>graphhopper-core</artifactId>
<name>GraphHopper Core</name>
<version>11.0-SNAPSHOT</version>
<version>12.0-SNAPSHOT</version>
<packaging>jar</packaging>
<description>
GraphHopper is a fast and memory efficient Java road routing engine
Expand All @@ -14,7 +14,7 @@
<parent>
<groupId>com.graphhopper</groupId>
<artifactId>graphhopper-parent</artifactId>
<version>11.0-SNAPSHOT</version>
<version>12.0-SNAPSHOT</version>
</parent>

<properties>
Expand Down
43 changes: 34 additions & 9 deletions core/src/main/java/com/graphhopper/GraphHopper.java
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,16 @@ public Profile getProfile(String profileName) {
return profilesByName.get(profileName);
}

public TransportationMode getNavigationMode(String profileName) {
Profile profile = profilesByName.get(profileName);
if (profile == null) return TransportationMode.CAR;
try {
return TransportationMode.valueOf(profile.getHints().getString("navigation_mode", profileName).toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException e) {
return TransportationMode.CAR;
}
}

/**
* @return true if storing and fetching elevation data is enabled. Default is false
*/
Expand Down Expand Up @@ -1143,14 +1153,21 @@ public boolean load() {
.build();
checkProfilesConsistency();
baseGraph.loadExisting();
String storedProfiles = properties.get("profiles");
String configuredProfiles = getProfilesString();
if (!storedProfiles.equals(configuredProfiles))
throw new IllegalStateException("Profiles do not match:"
+ "\nGraphhopper config: " + configuredProfiles
+ "\nGraph: " + storedProfiles
+ "\nChange configuration to match the graph or delete " + baseGraph.getDirectory().getLocation());

String storedProfilesString = properties.get("profiles");
Map<String, Integer> storedProfileHashes = Arrays.stream(storedProfilesString.split(",")).map(s -> s.split("\\|", 2)).collect((Collectors.toMap(kv -> kv[0], kv -> Integer.parseInt(kv[1]))));
Map<String, Integer> configuredProfileHashes = getProfileHashes();
configuredProfileHashes.forEach((profile, hash) -> {
Integer storedHash = storedProfileHashes.get(profile);
if (storedHash == null)
throw new IllegalStateException("You cannot add new profiles to the loaded graph. Profile '" + profile + "' is new."
+ "\nExisting profiles: " + String.join(",", storedProfileHashes.keySet())
+ "\nChange your configuration to match the graph or delete " + baseGraph.getDirectory().getLocation());
if (!hash.equals(storedHash))
throw new IllegalStateException("Profile '" + profile + "' does not match."
+ "\nStored: " + storedHash
+ "\nConfigured: " + hash
+ "\nChange this profile to match the stored one or delete " + baseGraph.getDirectory().getLocation());
});
postProcessing(false);
directory.loadMMap();
setFullyLoaded();
Expand All @@ -1166,7 +1183,11 @@ protected int getProfileHash(Profile profile) {
}

private String getProfilesString() {
return profilesByName.values().stream().map(p -> p.getName() + "|" + getProfileHash(p)).collect(Collectors.joining(","));
return getProfileHashes().entrySet().stream().map(e -> e.getKey() + "|" + e.getValue()).collect(Collectors.joining(","));
}

private Map<String, Integer> getProfileHashes() {
return profilesByName.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> getProfileHash(e.getValue())));
}

public void checkProfilesConsistency() {
Expand Down Expand Up @@ -1439,6 +1460,10 @@ else if (prepared.containsKey(profile.getProfile())) {
} else
throw new IllegalStateException("CH graph should be either loaded or prepared: " + profile.getProfile());
}
chGraphs.forEach((name, ch) -> {
CHStorage store = ((RoutingCHGraphImpl) ch).getCHStorage();
logger.info("CH available for profile {}, {}MB, {}, ({}MB)", name, Helper.nf(store.getCapacity() / Helper.MB), store.toDetailsString(), store.getMB());
});
}

protected Map<String, PrepareContractionHierarchies.Result> prepareCH(boolean closeEarly, List<CHConfig> configsToPrepare) {
Expand Down
8 changes: 5 additions & 3 deletions core/src/main/java/com/graphhopper/GraphHopperConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
package com.graphhopper;

import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.Nulls;
import com.graphhopper.config.CHProfile;
import com.graphhopper.config.LMProfile;
import com.graphhopper.config.Profile;
Expand Down Expand Up @@ -67,6 +68,7 @@ public List<Profile> getProfiles() {
return profiles;
}

@JsonSetter(nulls = Nulls.AS_EMPTY)
public GraphHopperConfig setProfiles(List<Profile> profiles) {
this.profiles = profiles;
return this;
Expand All @@ -76,7 +78,7 @@ public List<CHProfile> getCHProfiles() {
return chProfiles;
}

@JsonProperty("profiles_ch")
@JsonSetter(value = "profiles_ch", nulls = Nulls.AS_EMPTY)
public GraphHopperConfig setCHProfiles(List<CHProfile> chProfiles) {
this.chProfiles = chProfiles;
return this;
Expand All @@ -86,7 +88,7 @@ public List<LMProfile> getLMProfiles() {
return lmProfiles;
}

@JsonProperty("profiles_lm")
@JsonSetter(value = "profiles_lm", nulls = Nulls.AS_EMPTY)
public GraphHopperConfig setLMProfiles(List<LMProfile> lmProfiles) {
this.lmProfiles = lmProfiles;
return this;
Expand Down
Loading