diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml index 1d23647..57cd7a4 100644 --- a/.github/workflows/gradle-publish.yml +++ b/.github/workflows/gradle-publish.yml @@ -18,10 +18,10 @@ jobs: packages: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 11 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'temurin' diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 39fdb4e..4fd8bde 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -15,9 +15,9 @@ jobs: runs-on: ubuntu-latest environment: BRouter steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 11 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'temurin' @@ -37,7 +37,7 @@ jobs: ORG_GRADLE_PROJECT_RELEASE_STORE_PASSWORD: ${{ secrets.BROUTER_STORE_PASSWORD }} run: ./gradlew build - name: Upload ZIP - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ZIP path: brouter-server/build/distributions/brouter-*.zip diff --git a/brouter-core/src/main/java/btools/router/FormatGpx.java b/brouter-core/src/main/java/btools/router/FormatGpx.java index 0ed6cc5..8a6f761 100644 --- a/brouter-core/src/main/java/btools/router/FormatGpx.java +++ b/brouter-core/src/main/java/btools/router/FormatGpx.java @@ -153,7 +153,9 @@ public class FormatGpx extends Formatter { sb.append(" ") .append(hint.selev == Short.MIN_VALUE ? "" : "" + (hint.selev / 4.) + "") - .append("").append(hint.getMessageString()).append("") + .append("") + .append(hint.getMessageString()) + .append("") .append("").append("" + hint.distanceToNext).append(""); float rteTime = t.getVoiceHintTime(i + 1); if (rteTime != lastRteTime) { // add timing only if available diff --git a/brouter-core/src/main/java/btools/router/OsmTrack.java b/brouter-core/src/main/java/btools/router/OsmTrack.java index 087caf5..ac278d1 100644 --- a/brouter-core/src/main/java/btools/router/OsmTrack.java +++ b/brouter-core/src/main/java/btools/router/OsmTrack.java @@ -501,7 +501,8 @@ public final class OsmTrack { node = node.origin; } - VoiceHintProcessor vproc = new VoiceHintProcessor(rc.turnInstructionCatchingRange, rc.turnInstructionRoundabouts); + int transportMode = voiceHints.transportMode(); + VoiceHintProcessor vproc = new VoiceHintProcessor(rc.turnInstructionCatchingRange, rc.turnInstructionRoundabouts, transportMode); List results = vproc.process(inputs); double minDistance = getMinDistance(); @@ -514,13 +515,12 @@ public final class OsmTrack { int getMinDistance() { if (voiceHints != null) { - switch (voiceHints.getTransportMode()) { - case "car": + switch (voiceHints.transportMode()) { + case VoiceHintList.TRANS_MODE_CAR: return 20; - case "bike": - return 5; - case "foot": + case VoiceHintList.TRANS_MODE_FOOT: return 3; + case VoiceHintList.TRANS_MODE_BIKE: default: return 5; } diff --git a/brouter-core/src/main/java/btools/router/VoiceHint.java b/brouter-core/src/main/java/btools/router/VoiceHint.java index 2f858be..3d0b425 100644 --- a/brouter-core/src/main/java/btools/router/VoiceHint.java +++ b/brouter-core/src/main/java/btools/router/VoiceHint.java @@ -44,6 +44,7 @@ public class VoiceHint { float angle = Float.MAX_VALUE; boolean turnAngleConsumed; boolean needsRealTurn; + int maxBadPrio = -1; int roundaboutExit; diff --git a/brouter-core/src/main/java/btools/router/VoiceHintList.java b/brouter-core/src/main/java/btools/router/VoiceHintList.java index 229f4ab..e377e24 100644 --- a/brouter-core/src/main/java/btools/router/VoiceHintList.java +++ b/brouter-core/src/main/java/btools/router/VoiceHintList.java @@ -10,23 +10,50 @@ import java.util.ArrayList; import java.util.List; public class VoiceHintList { - private String transportMode; + + static final int TRANS_MODE_NONE = 0; + static final int TRANS_MODE_FOOT = 1; + static final int TRANS_MODE_BIKE = 2; + static final int TRANS_MODE_CAR = 3; + + private int transportMode = TRANS_MODE_BIKE; int turnInstructionMode; List list = new ArrayList<>(); public void setTransportMode(boolean isCar, boolean isBike) { - transportMode = isCar ? "car" : (isBike ? "bike" : "foot"); + transportMode = isCar ? TRANS_MODE_CAR : (isBike ? TRANS_MODE_BIKE : TRANS_MODE_FOOT); + } + + public void setTransportMode(int mode) { + transportMode = mode; } public String getTransportMode() { + String ret; + switch (transportMode) { + case TRANS_MODE_FOOT: + ret = "foot"; + break; + case TRANS_MODE_CAR: + ret = "car"; + break; + case TRANS_MODE_BIKE: + default: + ret = "bike"; + break; + } + return ret; + } + + public int transportMode() { return transportMode; } public int getLocusRouteType() { - if ("car".equals(transportMode)) { + if (transportMode == TRANS_MODE_CAR) { return 0; } - if ("bike".equals(transportMode)) { + if (transportMode == TRANS_MODE_BIKE) { return 5; } return 3; // foot diff --git a/brouter-core/src/main/java/btools/router/VoiceHintProcessor.java b/brouter-core/src/main/java/btools/router/VoiceHintProcessor.java index 1a63a0a..cb60390 100644 --- a/brouter-core/src/main/java/btools/router/VoiceHintProcessor.java +++ b/brouter-core/src/main/java/btools/router/VoiceHintProcessor.java @@ -15,10 +15,12 @@ public final class VoiceHintProcessor { // private double catchingRange; // range to catch angles and merge turns private boolean explicitRoundabouts; + private int transportMode; - public VoiceHintProcessor(double catchingRange, boolean explicitRoundabouts) { + public VoiceHintProcessor(double catchingRange, boolean explicitRoundabouts, int transportMode) { // this.catchingRange = catchingRange; this.explicitRoundabouts = explicitRoundabouts; + this.transportMode = transportMode; } private float sumNonConsumedWithinCatchingRange(List inputs, int offset) { @@ -81,10 +83,21 @@ public final class VoiceHintProcessor { if (explicitRoundabouts && input.oldWay.isRoundabout()) { if (roundaboudStartIdx == -1) roundaboudStartIdx = hintIdx; roundAboutTurnAngle += sumNonConsumedWithinCatchingRange(inputs, hintIdx); + if (roundaboudStartIdx == hintIdx) { + if (input.badWays != null) { + // remove goodWay + roundAboutTurnAngle -= input.goodWay.turnangle; + // add a badWay + for (MessageData badWay : input.badWays) { + if (!badWay.isBadOneway()) roundAboutTurnAngle += badWay.turnangle; + } + } + } boolean isExit = roundaboutExit == 0; // exit point is always exit if (input.badWays != null) { for (MessageData badWay : input.badWays) { - if (!badWay.isBadOneway() && badWay.isGoodForCars() && Math.abs(badWay.turnangle) < 120.) { + if (!badWay.isBadOneway() && + badWay.isGoodForCars()) { isExit = true; } } @@ -95,12 +108,35 @@ public final class VoiceHintProcessor { continue; } if (roundaboutExit > 0) { - roundAboutTurnAngle += sumNonConsumedWithinCatchingRange(inputs, hintIdx); - double startTurn = (roundaboudStartIdx != -1 ? inputs.get(roundaboudStartIdx).goodWay.turnangle : turnAngle); + //roundAboutTurnAngle += sumNonConsumedWithinCatchingRange(inputs, hintIdx); + //double startTurn = (roundaboudStartIdx != -1 ? inputs.get(roundaboudStartIdx + 1).goodWay.turnangle : turnAngle); input.angle = roundAboutTurnAngle; + input.goodWay.turnangle = roundAboutTurnAngle; input.distanceToNext = distance; - input.roundaboutExit = startTurn < 0 ? -roundaboutExit : roundaboutExit; + //input.roundaboutExit = startTurn < 0 ? roundaboutExit : -roundaboutExit; + input.roundaboutExit = roundAboutTurnAngle < 0 ? roundaboutExit : -roundaboutExit; + float tmpangle = 0; + VoiceHint tmpRndAbt = new VoiceHint(); + tmpRndAbt.badWays = new ArrayList<>(); + for (int i = hintIdx-1; i > roundaboudStartIdx; i--) { + VoiceHint vh = inputs.get(i); + tmpangle += inputs.get(i).goodWay.turnangle; + if (vh.badWays != null) { + for (MessageData badWay : vh.badWays) { + if (!badWay.isBadOneway()) { + MessageData md = new MessageData(); + md.linkdist = vh.goodWay.linkdist; + md.priorityclassifier = vh.goodWay.priorityclassifier; + md.turnangle = tmpangle; + tmpRndAbt.badWays.add(md); + } + } + } + } distance = 0.; + + input.badWays = tmpRndAbt.badWays; + results.add(input); roundAboutTurnAngle = 0.f; roundaboutExit = 0; @@ -127,10 +163,7 @@ public final class VoiceHintProcessor { if (badPrio > maxPrioAll && !isBadHighway2Link) { maxPrioAll = badPrio; - } - - if (badWay.costfactor < 20.f && Math.abs(badTurn) < minAbsAngeRaw) { - minAbsAngeRaw = Math.abs(badTurn); + input.maxBadPrio = Math.max(input.maxBadPrio, badPrio); } if (badPrio < minPrio) { @@ -145,8 +178,13 @@ public final class VoiceHintProcessor { continue; // ways from the back should not trigger a slight turn } + if (badWay.costfactor < 20.f && Math.abs(badTurn) < minAbsAngeRaw) { + minAbsAngeRaw = Math.abs(badTurn); + } + if (badPrio > maxPrioCandidates) { maxPrioCandidates = badPrio; + input.maxBadPrio = Math.max(input.maxBadPrio, badPrio); } if (badTurn > maxAngle) { maxAngle = badTurn; @@ -157,7 +195,8 @@ public final class VoiceHintProcessor { } } - boolean hasSomethingMoreStraight = (Math.abs(turnAngle) - minAbsAngeRaw) > 20.; + // boolean hasSomethingMoreStraight = (Math.abs(turnAngle) - minAbsAngeRaw) > 20.; + boolean hasSomethingMoreStraight = (Math.abs(turnAngle - minAbsAngeRaw)) > 20. && input.badWays != null; // && !ignoreBadway; // unconditional triggers are all junctions with // - higher detour prios than the minimum route prio (except link->highway junctions) @@ -244,80 +283,132 @@ public final class VoiceHintProcessor { List results = new ArrayList<>(); double distance = 0; VoiceHint inputLast = null; - ArrayList tmpList = new ArrayList<>(); + VoiceHint inputLastSaved = null; for (int hintIdx = 0; hintIdx < inputs.size(); hintIdx++) { VoiceHint input = inputs.get(hintIdx); + VoiceHint nextInput = null; + if (hintIdx + 1 < inputs.size()) { + nextInput = inputs.get(hintIdx + 1); + } - if (input.cmd == VoiceHint.C && !input.goodWay.isLinktType()) { - int badWayPrio = 0; - if (input.badWays != null) { - for (MessageData md : input.badWays) { - badWayPrio = Math.max(badWayPrio, md.getPrio()); + if (nextInput == null) { + if (input.cmd == VoiceHint.C && !input.goodWay.isLinktType()) { + if (input.goodWay.getPrio() < input.maxBadPrio && (inputLastSaved != null && inputLastSaved.distanceToNext > catchingRange)) { + results.add(input); + } else { + if (inputLast != null) { // when drop add distance to last + inputLast.distanceToNext += input.distanceToNext; + } + continue; } - } - if (input.goodWay.getPrio() < badWayPrio) { - results.add(input); } else { - if (inputLast != null) { // when drop add distance to last - inputLast.distanceToNext += input.distanceToNext; - } - continue; + results.add(input); } } else { - if (input.distanceToNext < catchingRange) { + if ((inputLastSaved != null && inputLastSaved.distanceToNext > catchingRange) || input.distanceToNext > catchingRange) { + if (input.cmd == VoiceHint.C && !input.goodWay.isLinktType()) { + if (input.goodWay.getPrio() < input.maxBadPrio + && (inputLastSaved != null && inputLastSaved.distanceToNext > minRange) + && (input.distanceToNext > minRange)) { + // add only on prio + results.add(input); + inputLastSaved = input; + } else { + if (inputLastSaved != null) { // when drop add distance to last + inputLastSaved.distanceToNext += input.distanceToNext; + } + } + } else { + // add all others + // ignore motorway / primary continue + if (((input.goodWay.getPrio() != 28) && + (input.goodWay.getPrio() != 30) && + (input.goodWay.getPrio() != 26)) + || input.isRoundabout() + || Math.abs(input.angle) > 21.f) { + results.add(input); + inputLastSaved = input; + } else { + if (inputLastSaved != null) { // when drop add distance to last + inputLastSaved.distanceToNext += input.distanceToNext; + } + } + } + } else if (input.distanceToNext < catchingRange) { double dist = input.distanceToNext; float angles = input.angle; int i = 1; - boolean save = true; - tmpList.clear(); - while (dist < catchingRange && hintIdx + i < inputs.size()) { - VoiceHint h2 = inputs.get(hintIdx + i); - dist += h2.distanceToNext; - angles += h2.angle; - if (VoiceHint.is180DegAngle(input.angle) || VoiceHint.is180DegAngle(h2.angle)) { // u-turn, 180 degree - save = true; - break; - } else if (Math.abs(angles) > 180 - SIGNIFICANT_ANGLE) { // u-turn, collects e.g. two left turns in range - input.angle = angles; - input.calcCommand(); - input.distanceToNext += h2.distanceToNext; - save = true; - hintIdx++; - break; - } else if (Math.abs(angles) < SIGNIFICANT_ANGLE && input.distanceToNext < minRange) { - input.angle = angles; - input.calcCommand(); - input.distanceToNext += h2.distanceToNext; - save = true; - hintIdx++; - break; - } else if (Math.abs(input.angle) > SIGNIFICANT_ANGLE) { - tmpList.add(h2); - hintIdx++; - } else if (dist > catchingRange) { // distance reached - break; - } else { - if (inputLast != null) { // when drop add distance to last - inputLast.distanceToNext += input.distanceToNext; + boolean save = false; + + dist += nextInput.distanceToNext; + angles += nextInput.angle; + + if (input.cmd == VoiceHint.C && !input.goodWay.isLinktType()) { + if (input.goodWay.getPrio() < input.maxBadPrio) { + if (inputLastSaved != null && inputLastSaved.cmd != VoiceHint.C + && (inputLastSaved != null && inputLastSaved.distanceToNext > minRange) + && transportMode != VoiceHintList.TRANS_MODE_CAR) { + // add when straight and not linktype + // and last vh not straight + save = true; + // remove when next straight and not linktype + if (nextInput != null && + nextInput.cmd == VoiceHint.C && + !nextInput.goodWay.isLinktType()) { + input.distanceToNext += nextInput.distanceToNext; + hintIdx++; + } + } + + } else { + if (inputLastSaved != null) { // when drop add distance to last + inputLastSaved.distanceToNext += input.distanceToNext; } - save = false; } - i++; + } else if (VoiceHint.is180DegAngle(input.angle)) { + // add u-turn, 180 degree + save = true; + } else if (transportMode == VoiceHintList.TRANS_MODE_CAR && Math.abs(angles) > 180 - SIGNIFICANT_ANGLE) { + // add when inc car mode and u-turn, collects e.g. two left turns in range + input.angle = angles; + input.calcCommand(); + input.distanceToNext += nextInput.distanceToNext; + save = true; + hintIdx++; + } else if (Math.abs(angles) < SIGNIFICANT_ANGLE && input.distanceToNext < minRange) { + input.angle = angles; + input.calcCommand(); + input.distanceToNext += nextInput.distanceToNext; + save = true; + hintIdx++; + } else if (Math.abs(input.angle) > SIGNIFICANT_ANGLE) { + // add when angle above 22.5 deg + save = true; + } else if (Math.abs(input.angle) < SIGNIFICANT_ANGLE) { + // add when angle below 22.5 deg ??? + // save = true; + } else { + // otherwise ignore but add distance to next + if (nextInput != null) { // when drop add distance to last + nextInput.distanceToNext += input.distanceToNext; + } + save = false; } + if (save) { results.add(input); // add when last - if (tmpList.size() > 0) { // add when something in stock - results.addAll(tmpList); - hintIdx += tmpList.size() - 1; - } + inputLastSaved = input; } } else { results.add(input); + inputLastSaved = input; } - inputLast = input; } + inputLast = input; } + return results; } + } diff --git a/brouter-server/src/main/java/btools/server/RouteServer.java b/brouter-server/src/main/java/btools/server/RouteServer.java index ba421f9..0685eac 100644 --- a/brouter-server/src/main/java/btools/server/RouteServer.java +++ b/brouter-server/src/main/java/btools/server/RouteServer.java @@ -194,6 +194,10 @@ public class RouteServer extends Thread implements Comparable { if (wplist.size() < 10) { SuspectManager.nearRecentWps.add(wplist); } + if (params.containsKey("profile")) { + // already handled in readRoutingContext + params.remove("profile"); + } int engineMode = 0; if (params.containsKey("engineMode")) { engineMode = Integer.parseInt(params.get("engineMode")); diff --git a/docs/developers/android_service.md b/docs/developers/android_service.md index 0feaddf..5bbc475 100644 --- a/docs/developers/android_service.md +++ b/docs/developers/android_service.md @@ -39,19 +39,52 @@ Please note: when they have a parameter 'weight' the result is not an absolute n This parameters are needed to tell BRouter what to do. +### using profiles + +For calulation BRouter uses a set of rules defined in a profile. See description of profile [rules](https://github.com/abrensch/brouter/blob/master/docs/developers/profile_developers_guide.md). + +Here we talk about how we let BRouter know witch profile to use. +There are three ways: + +1. use the parameter 'v' and 'fast' +``` + "v"-->[motorcar|bicycle|foot] + "fast"-->[0|1] + This enables BRouter to look into the file serviceconfig.dat. + In there BRouter find the profile associated for e.g bicyle_fast trekking + This could be changed by the user calling the BRouter app server-mode. +``` + +2. use the profile parameter +``` + profile=trekking + It needs an available file in the BRouter profile folder e.g. trekking.brf +``` + +3. use a remote profile +``` + remoteProfile=a long string with routing rules + This is saved in BRouter profile folder temporary with the file name 'remote.brf' +``` + + ### profile parameter Profile parameters affect the result of a profile. +The variables inside a profile predefine a value e.g. avoidsteps=1 +A parameter call gives the chance to change this start value without changing the profile e.g. avoidsteps=0 For the app it is a list of params concatenated by '&'. E.g. extraParams=avoidferry=1&avoidsteps=0 The server calls profile params by a prefix 'profile:'. E.g. ...&profile:avoidferry=1&profile:avoidsteps=0 +By using this parameter logic, there is no need to edit a profile before sending. + ### using profile parameter inside an app To be flexible it is possible to send a profile to BRouter - server or app. Another variant is to send parameters for an existing profile that are different from the original profile. -With the version 1.7.1 it is possible to collect parameters from the profile. +With the version 1.7.1 it is possible to collect parameters from the profile. The variable parameters are defined like this ``` assign avoid_path = false # %avoid_path% | Set to true to avoid pathes | boolean @@ -61,9 +94,9 @@ Now you could do that with an calling app. What to do to get it work? -- First copy the [RoutingParam](brouter-routing-app/src/main/java/btools/routingapp/RoutingParam.java) class to your source - use the same name and package name. +- First copy the [RoutingParam](brouter-routing-app/src/main/java/btools/routingapp/RoutingParam.java) class to your source - use the same name and package name. - Second analyze the profile for which you need the parameter. - This [BRouter routine](https://github.com/abrensch/brouter/blob/086503e529da7c044cc0f88f86c394fdb574d6cf/brouter-routing-app/src/main/java/btools/routingapp/RoutingParameterDialog.java#L103) can do that, just copy it to your source to use it in your app. + This [BRouter routine](https://github.com/abrensch/brouter/blob/086503e529da7c044cc0f88f86c394fdb574d6cf/brouter-routing-app/src/main/java/btools/routingapp/RoutingParameterDialog.java#L103) can do that, just copy it to your source to use it in your app. It builds a List you could send to BRouter app. - You find the call of BRouter app in comment at [RoutingParameterDialog](https://github.com/abrensch/brouter/blob/086503e529da7c044cc0f88f86c394fdb574d6cf/brouter-routing-app/src/main/java/btools/routingapp/RoutingParameterDialog.java#L33) @@ -79,7 +112,7 @@ intent.putExtra("runsilent", true); startActivity(intent); ``` -This suppress the first question after installation for the BRouter path, generates the BRouter folders in main space and starts the download dialog. +This suppress the first question after installation for the BRouter path, generates the BRouter folders in main space and starts the download dialog. ### silent app call @@ -92,7 +125,7 @@ intent.putExtra("runsilent", true); startActivity(intent); ``` -This suppress the first question after installation for the BRouter path, generates the BRouter folders in main space and starts the download dialog. +This suppress the first question after installation for the BRouter path, generates the BRouter folders in main space and starts the download dialog. ## other routing engine modes in app diff --git a/docs/developers/docker_guide.md b/docs/developers/docker_guide.md new file mode 100644 index 0000000..990d8e9 --- /dev/null +++ b/docs/developers/docker_guide.md @@ -0,0 +1,125 @@ +--- +parent: Developers +--- + +# Docker help + +In addition to the intro in readme.md about Docker, here are a few commands for daily work with the system. + +Build the Docker with a version based name +``` +$ docker build -t brouter-1.7.2 . +``` + +Start Docker with name additional to the Docker image name. +Please note: +The path for segments are on a Windows system. +Here the port used in server.sh is published. +``` +$ docker run --rm -v "I:/Data/test/segment4":/segments4 --publish 17777:17777 --name brouter-1.7.2 brouter-1.7.2 +``` + +and with a mount for profiles as well +``` +$ docker run --rm -v "I:/Data/test/segment4":/segments4 -v "I:/Data/test/profiles2":/profiles2 --name brouter-1.7.2 brouter-1.7.2 +``` + +Show the running Docker processes +``` +$ docker ps + +output: +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +b23518e8791d brouter-1.7.2 "/bin/sh -c /bin/ser…" 5 minutes ago Up 5 minutes 0.0.0.0:17777->17777/tcp brouter-1.7.2 +``` + +Fire some curl or wget commands to test if is realy useful running. + +Stop a running Docker image - please note, this only works when starts docker image with name, see above +``` +$ docker stop brouter-1.7.2 +``` + +Docker available images + +``` +$ docker images + +output: +REPOSITORY TAG IMAGE ID CREATED SIZE +brouter-1.7.2 latest e39703dec2fa 2 hours ago 410MB +brouter latest 728f122c7388 3 hours ago 410MB +``` + +Control +## Docker with docker-compose + +Use a git clone to build a local folder with last version. +Make a Docker container with version number inside your repository folder. +``` +$ docker build -t brouter:1.7.2 . + +$ docker images + +REPOSITORY TAG IMAGE ID CREATED SIZE +brouter-1.7.2 latest e39703dec2fa 3 hours ago 410MB +brouter 1.7.2 e39703dec2fa 3 hours ago 410MB +``` + +Start a container with composer +This needs a docker config file docker-compose.yml +Something like this: +``` +version: '2' +services: + brouter: + image: brouter:1.7.2 + restart: unless-stopped + ports: + - 17777:17777 + volumes: + - type: bind + source: "I:/Data/test/segment4" + target: /segments4 +# - type: bind +# source: "I:/Data/test/profiles2" +# target: /profiles2 +``` + +Start it +``` +$ docker-compose up -d +``` + +Have a look what is running +``` +$ docker-compose ps +or +$ docker-compose ls +or +$ docker ps +``` + + +Now update your repository (git pull) and build your Docker container with the new version tag +``` +$ docker build -t brouter:1.7.3 . + +$ docker images + +REPOSITORY TAG IMAGE ID CREATED SIZE +brouter 1.7.3 5edc998cb5ae 3 hours ago 410MB +brouter-1.7.2 latest e39703dec2fa 6 hours ago 410MB +``` + +Replace the version in Docker config file docker-compose.yml +``` + image: brouter:1.7.3 +``` + +Stop old running container and start the new one +``` +$ docker-compose down + +$ docker-compose up -d +``` diff --git a/docs/developers/profile_developers_guide.md b/docs/developers/profile_developers_guide.md index f5b69bf..cbc6fc3 100644 --- a/docs/developers/profile_developers_guide.md +++ b/docs/developers/profile_developers_guide.md @@ -176,7 +176,7 @@ All expressions have one of the following basic forms: - `and ` - `xor ` - `multiply ` - - `div ` + - `divide ` - `add ` - `sub ` - `max ` diff --git a/docs/users/osmand.md b/docs/users/osmand.md index db751f7..a1c2f03 100644 --- a/docs/users/osmand.md +++ b/docs/users/osmand.md @@ -67,3 +67,29 @@ application profiles"/> The BRouter app should be launched before OsmAnd for this specific entry to appear in OsmAnd. Therefore, if you cannot find "BRouter (offline)" navigation option, you should force quit OsmAnd and restart it. + + +## OsmAnd version 4.7.1 + +From version 4.7.1 upwards Osmand supports the profile parameter for mapping: +Since Osmand version 3, many profiles can be defined in Osmand and the user can easily switch between these profiles. +This allow now when using the service-interface to address different brouter-profiles in a more flexible and better comprehensive way. + +- If in Osmand a profile has "BRouter" defined as navigation service +- AND the profile-name looks like "Brouter[mysting] + +==> then the profile "mystring" will be used in the Brouter-app! +(this new mapping replaces in that case the basic mapping defined above and based on the file "serviceconfig.dat) + +### Examples: Osmand-profile name Brouter-app +``` +[Brouter[trekking] "trekking" profile will be used (file trekking.brf) +[Brouter[racebike] "racebike" profile will be used (file racebike.brf) +.... +``` +Remark: +Currently Osmand do not check the defined name (case sensitiv) for the Brouter-profile (mystring). +If no profile is found, the routing will fail with "Could not calculate route.."! + +BRouter configuration in OsmAnd
+application profiles diff --git a/docs/users/osmand/brouter-osmand-4.7.1.png b/docs/users/osmand/brouter-osmand-4.7.1.png new file mode 100644 index 0000000..42dfe80 Binary files /dev/null and b/docs/users/osmand/brouter-osmand-4.7.1.png differ