Skip to content

Commit

Permalink
Merge pull request #665 from afischerdev/rework-voicehint
Browse files Browse the repository at this point in the history
Rework on voicehints
  • Loading branch information
afischerdev committed Mar 3, 2024
2 parents 86e62e1 + b2009cf commit 531f913
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 72 deletions.
4 changes: 3 additions & 1 deletion brouter-core/src/main/java/btools/router/FormatGpx.java
Expand Up @@ -153,7 +153,9 @@ public String formatAsGpx(BufferedWriter sb, OsmTrack t) throws IOException {
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
.append(formatILat(hint.ilat)).append("\">")
.append(hint.selev == Short.MIN_VALUE ? "" : "<ele>" + (hint.selev / 4.) + "</ele>")
.append("<name>").append(hint.getMessageString()).append("</name>")
.append("<name>")
.append(hint.getMessageString())
.append("</name>")
.append("<extensions><locus:rteDistance>").append("" + hint.distanceToNext).append("</locus:rteDistance>");
float rteTime = t.getVoiceHintTime(i + 1);
if (rteTime != lastRteTime) { // add timing only if available
Expand Down
12 changes: 6 additions & 6 deletions brouter-core/src/main/java/btools/router/OsmTrack.java
Expand Up @@ -500,7 +500,8 @@ public void processVoiceHints(RoutingContext rc) {
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<VoiceHint> results = vproc.process(inputs);

double minDistance = getMinDistance();
Expand All @@ -513,13 +514,12 @@ public void processVoiceHints(RoutingContext rc) {

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;
}
Expand Down
1 change: 1 addition & 0 deletions brouter-core/src/main/java/btools/router/VoiceHint.java
Expand Up @@ -44,6 +44,7 @@ public float getTime() {
float angle = Float.MAX_VALUE;
boolean turnAngleConsumed;
boolean needsRealTurn;
int maxBadPrio = -1;

int roundaboutExit;

Expand Down
35 changes: 31 additions & 4 deletions brouter-core/src/main/java/btools/router/VoiceHintList.java
Expand Up @@ -10,23 +10,50 @@
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<VoiceHint> 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
Expand Down
213 changes: 152 additions & 61 deletions brouter-core/src/main/java/btools/router/VoiceHintProcessor.java
Expand Up @@ -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<VoiceHint> inputs, int offset) {
Expand Down Expand Up @@ -81,10 +83,21 @@ public List<VoiceHint> process(List<VoiceHint> inputs) {
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;
}
}
Expand All @@ -95,12 +108,35 @@ public List<VoiceHint> process(List<VoiceHint> inputs) {
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;
Expand All @@ -127,10 +163,7 @@ public List<VoiceHint> process(List<VoiceHint> inputs) {

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) {
Expand All @@ -145,8 +178,13 @@ public List<VoiceHint> process(List<VoiceHint> inputs) {
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;
Expand All @@ -157,7 +195,8 @@ public List<VoiceHint> process(List<VoiceHint> inputs) {
}
}

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)
Expand Down Expand Up @@ -244,80 +283,132 @@ public List<VoiceHint> postProcess(List<VoiceHint> inputs, double catchingRange,
List<VoiceHint> results = new ArrayList<>();
double distance = 0;
VoiceHint inputLast = null;
ArrayList<VoiceHint> 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;
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 (inputLast != null) { // when drop add distance to last
inputLast.distanceToNext += input.distanceToNext;
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;
}


}

0 comments on commit 531f913

Please sign in to comment.