From f77b3869af183e7e8487dd21556447a4d31a1b92 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Fri, 15 Jul 2011 01:35:24 +0200 Subject: [PATCH] Fix voice router. Consider speed, be more accurate --- .../osmand/plus/activities/RoutingHelper.java | 2 +- .../plus/activities/SettingsActivity.java | 4 +- .../osmand/plus/activities/VoiceRouter.java | 331 +++++++++++------- 3 files changed, 206 insertions(+), 131 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/activities/RoutingHelper.java b/OsmAnd/src/net/osmand/plus/activities/RoutingHelper.java index d19184c546..bf1226dbd7 100644 --- a/OsmAnd/src/net/osmand/plus/activities/RoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/activities/RoutingHelper.java @@ -321,7 +321,7 @@ public class RoutingHelper { // } } } - voiceRouter.updateStatus(); + voiceRouter.updateStatus(currentLocation); lastFixedLocation = currentLocation; if(calculateRoute){ diff --git a/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java b/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java index 8b8f24b8de..47a639a996 100644 --- a/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java @@ -226,10 +226,10 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference } registerListPreference(osmandSettings.MAX_LEVEL_TO_DOWNLOAD_TILE, screen, entries, intValues); - Float[] floatValues = new Float[] {0.3f, 0.5f, 0.7f, 0.8f, 1.0f, 1.2f, 1.3f, 1.5f, 2.0f, 2.5f}; + Float[] floatValues = new Float[] {0.6f, 0.8f, 1.0f, 1.2f, 1.5f}; entries = new String[floatValues.length]; for (int i = 0; i < floatValues.length; i++) { - entries[i] = floatValues[i] +""; + entries[i] = (int) (floatValues[i] * 100) +" %"; } registerListPreference(osmandSettings.MAP_TEXT_SIZE, screen, entries, floatValues); diff --git a/OsmAnd/src/net/osmand/plus/activities/VoiceRouter.java b/OsmAnd/src/net/osmand/plus/activities/VoiceRouter.java index 9e4cb8c186..e4bb6ac986 100644 --- a/OsmAnd/src/net/osmand/plus/activities/VoiceRouter.java +++ b/OsmAnd/src/net/osmand/plus/activities/VoiceRouter.java @@ -6,6 +6,7 @@ import net.osmand.plus.voice.AbstractPrologCommandPlayer; import net.osmand.plus.voice.CommandBuilder; import net.osmand.plus.voice.CommandPlayer; import android.app.Activity; +import android.location.Location; public class VoiceRouter { @@ -24,6 +25,19 @@ public class VoiceRouter { private int currentDirection = 0; private int currentStatus = STATUS_UNKNOWN; + + // default speed to have comfortable announcements (if actual speed is higher than it would be problem) + // Speed in m/s + protected float DEFAULT_SPEED = 12; + + protected int PREPARE_LONG_DISTANCE_ST = 2500; + protected int PREPARE_LONG_DISTANCE_END = 3200; + + protected int PREPARE_DISTANCE = 0; + protected int PREPARE_DISTANCE_END = 0; + protected int TURN_IN_DISTANCE = 0; + protected int TURN_IN_DISTANCE_END = 0; + protected int TURN_DISTANCE = 0; public VoiceRouter(RoutingHelper router, CommandPlayer player) { @@ -53,42 +67,89 @@ public class VoiceRouter { return player.newCommandBuilder(); } - protected int PREPARE_LONG_DISTANCE_ST = 2500; - protected int PREPARE_LONG_DISTANCE_END = 3000; - protected int PREPARE_DISTANCE = 0; - protected int TURN_IN_DISTANCE = 0; - protected int TURN_DISTANCE = 0; public void updateAppMode(){ + // Else consider default time if(router.getAppMode() == ApplicationMode.PEDESTRIAN){ - PREPARE_DISTANCE = 400; - TURN_IN_DISTANCE = 150; - TURN_DISTANCE = 30; + // prepare distance needed ? + PREPARE_DISTANCE = 320; // 160 second + PREPARE_DISTANCE_END = 200; // 75 second + TURN_IN_DISTANCE = 100; // 50 seconds + TURN_IN_DISTANCE_END = 70; // 35 seconds + TURN_DISTANCE = 25; // 12 seconds + DEFAULT_SPEED = 2f; } else if(router.getAppMode() == ApplicationMode.BICYCLE){ - PREPARE_DISTANCE = 550; - TURN_IN_DISTANCE = 200; - TURN_DISTANCE = 55; + PREPARE_DISTANCE = 530; // 100 seconds + PREPARE_DISTANCE_END = 370; // 70 seconds + TURN_IN_DISTANCE = 230; // 40 seconds + TURN_IN_DISTANCE_END = 90; // 16 seconds + TURN_DISTANCE = 55; // 11 seconds + DEFAULT_SPEED = 5; } else { - PREPARE_DISTANCE = 800; - TURN_IN_DISTANCE = 300; - TURN_DISTANCE = 70; + PREPARE_DISTANCE = 730; // 60 seconds + PREPARE_DISTANCE_END = 530; // 45 seconds + TURN_IN_DISTANCE = 330; // 25 seconds + TURN_IN_DISTANCE_END = 160; // 14 seconds + TURN_DISTANCE = 75; // 6 seconds + DEFAULT_SPEED = 12; } } + private boolean isDistanceLess(float currentSpeed, double dist, double etalon){ + if(dist < etalon || (dist / currentSpeed < etalon / DEFAULT_SPEED)){ + return true; + } + return false; + } - protected void updateStatus(){ + + private void nextStatusAfter(int previousStatus){ +// if(previousStatus == STATUS_TURN){ +// this.currentStatus = STATUS_TOLD; +// } else if(previousStatus == STATUS_200_TURN){ +// this.currentStatus = STATUS_TURN; +// } else if(previousStatus == STATUS_800_PREPARE){ +// this.currentStatus = STATUS_200_TURN; +// } else if(previousStatus == STATUS_3000_PREPARE){ +// this.currentStatus = STATUS_800_PREPARE; +// } else + if(previousStatus != STATUS_TOLD){ + this.currentStatus = previousStatus ++; + } else { + this.currentStatus = previousStatus; + } + } + + private boolean statusNotPassed(int statusToCheck){ + return currentStatus <= statusToCheck; + } + + /** + * Updates status of voice guidance + * @param currentLocation + */ + protected void updateStatus(Location currentLocation){ // directly after turn (go - ahead dist) // < 800m prepare // < 200m turn in // < 50m turn + float speed = DEFAULT_SPEED; + if(currentLocation != null && currentLocation.hasSpeed()){ + speed = Math.max(currentLocation.getSpeed(), speed); + } + RouteDirectionInfo next = router.getNextRouteDirectionInfo(); + int dist = router.getDistanceToNextRouteDirection(); + + // if routing is changed update status to unknown if(currentDirection != router.currentDirectionInfo){ currentDirection = router.currentDirectionInfo; currentStatus = STATUS_UNKNOWN; } - RouteDirectionInfo next = router.getNextRouteDirectionInfo(); - int dist = router.getDistanceToNextRouteDirection(); + + + // the last turn say if(next == null || next.distance == 0) { if(currentStatus == STATUS_UNKNOWN && currentDirection > 0){ CommandBuilder play = getNewCommandPlayerToPlay(); @@ -99,132 +160,146 @@ public class VoiceRouter { } return; } - if(dist == 0){ + if(dist == 0 || currentStatus == STATUS_TOLD){ // nothing said possibly that's wrong case we should say before that - // however it should be checked manually !? + // however it should be checked manually ? return; } - RouteDirectionInfo nextNext = router.getNextNextRouteDirectionInfo(); - if(currentStatus == STATUS_UNKNOWN){ - if(dist > PREPARE_DISTANCE){ - CommandBuilder play = getNewCommandPlayerToPlay(); - if(play != null){ - play.goAhead(dist).play(); + RouteDirectionInfo nextNext = router.getNextNextRouteDirectionInfo(); + if(statusNotPassed(STATUS_TURN) && isDistanceLess(speed, dist, TURN_DISTANCE)){ + if(isDistanceLess(speed, next.distance, TURN_DISTANCE) || next.distance < TURN_IN_DISTANCE_END) { + playMakeTurnRightNow(next, nextNext); + } else { + playMakeTurnRightNow(next, null); + } + nextStatusAfter(STATUS_TURN); + } else if(statusNotPassed(STATUS_200_TURN) && isDistanceLess(speed, dist, TURN_IN_DISTANCE)){ + if (dist >= TURN_IN_DISTANCE_END) { + if(isDistanceLess(speed, next.distance, TURN_DISTANCE) || next.distance < TURN_IN_DISTANCE_END) { + playMakeTurnInShortDistance(next, dist, nextNext); + } else { + playMakeTurnInShortDistance(next, dist, null); } - currentStatus = STATUS_3000_PREPARE; - } else if (dist < TURN_IN_DISTANCE){ - // should already told it - currentStatus = STATUS_TURN; + } + nextStatusAfter(STATUS_200_TURN); + } else if (statusNotPassed(STATUS_800_PREPARE) && isDistanceLess(speed, dist, PREPARE_DISTANCE)) { + if (dist >= PREPARE_DISTANCE_END) { + playPrepareLongDistanceTurn(next, dist); + } + nextStatusAfter(STATUS_800_PREPARE); + } else if(statusNotPassed(STATUS_UNKNOWN)){ + if (dist >= PREPARE_DISTANCE * 1.3f) { + playGoAhead(dist); + } + if (dist >= PREPARE_LONG_DISTANCE_END * 1.5f) { + nextStatusAfter(STATUS_UNKNOWN); + } else { + nextStatusAfter(STATUS_3000_PREPARE); + } + } else if(statusNotPassed(STATUS_3000_PREPARE) && isDistanceLess(speed, dist, PREPARE_LONG_DISTANCE_END)){ + if (dist >= PREPARE_LONG_DISTANCE_ST) { + playPrepareLongDistanceTurn(next, dist); + } + nextStatusAfter(STATUS_3000_PREPARE); + } + } + + private void playGoAhead(int dist) { + CommandBuilder play = getNewCommandPlayerToPlay(); + if(play != null){ + play.goAhead(dist).play(); + } + } + + private void playPrepareLongDistanceTurn(RouteDirectionInfo next, int dist) { + CommandBuilder play = getNewCommandPlayerToPlay(); + if(play != null){ + String tParam = getTurnType(next.turnType); + if(tParam != null){ + play.prepareTurn(tParam, dist).play(); + } else if(next.turnType.isRoundAbout()){ + play.prepareRoundAbout(dist).play(); + } else if(next.turnType.getValue().equals(TurnType.TU)){ + play.prepareMakeUT(dist).play(); + } + } + } + + private void playMakeTurnInShortDistance(RouteDirectionInfo next, int dist, RouteDirectionInfo pronounceNextNext) { + CommandBuilder play = getNewCommandPlayerToPlay(); + if (play != null) { + String tParam = getTurnType(next.turnType); + boolean isPlay = true; + if (tParam != null) { + play.turn(tParam, dist); + } else if (next.turnType.isRoundAbout()) { + play.roundAbout(dist, next.turnType.getTurnAngle(), next.turnType.getExitOut()); + } else if (next.turnType.getValue().equals(TurnType.TU)) { + play.makeUT(dist); + } else { + isPlay = false; + } + // small preparation to next after next + if (pronounceNextNext != null) { + TurnType t = pronounceNextNext.turnType; + isPlay = true; + if (next.turnType.getValue().equals(TurnType.C) && + !TurnType.C.equals(t.getValue())) { + play.goAhead(dist); + } + if (TurnType.TL.equals(t.getValue()) || TurnType.TSHL.equals(t.getValue()) || TurnType.TSLL.equals(t.getValue()) + || TurnType.TU.equals(t.getValue())) { + play.then().bearLeft(); + } else if (TurnType.TR.equals(t.getValue()) || TurnType.TSHR.equals(t.getValue()) || TurnType.TSLR.equals(t.getValue())) { + play.then().bearRight(); + } + } + if(isPlay){ + play.play(); } } - - - if(currentStatus <= STATUS_TURN && dist <= TURN_DISTANCE){ - CommandBuilder play = getNewCommandPlayerToPlay(); - if(play != null){ - String tParam = getTurnType(next.turnType); - boolean isplay = true; - if(tParam != null){ - play.turn(tParam); - } else if(next.turnType.isRoundAbout()){ - play.roundAbout(next.turnType.getTurnAngle(), next.turnType.getExitOut()); - } else if(next.turnType.getValue().equals(TurnType.TU)){ - play.makeUT(); - // do not say it + } + + + + private void playMakeTurnRightNow(RouteDirectionInfo next, RouteDirectionInfo nextNext) { + CommandBuilder play = getNewCommandPlayerToPlay(); + if(play != null){ + String tParam = getTurnType(next.turnType); + boolean isplay = true; + if(tParam != null){ + play.turn(tParam); + } else if(next.turnType.isRoundAbout()){ + play.roundAbout(next.turnType.getTurnAngle(), next.turnType.getExitOut()); + } else if(next.turnType.getValue().equals(TurnType.TU)){ + play.makeUT(); + // do not say it // } else if(next.turnType.getValue().equals(TurnType.C)){ // play.goAhead(); - } else { - isplay = false; - } - - if (nextNext != null && next.distance <= TURN_IN_DISTANCE) { - String t2Param = getTurnType(nextNext.turnType); - if (t2Param != null) { - if(isplay) { play.then(); } - play.turn(t2Param, next.distance); - } else if (nextNext.turnType.isRoundAbout()) { - if(isplay) { play.then(); } - play.roundAbout(next.distance, nextNext.turnType.getTurnAngle(), nextNext.turnType.getExitOut()); - } else if (nextNext.turnType.getValue().equals(TurnType.TU)) { - if(isplay) { play.then(); } - play.makeUT(next.distance); - } - isplay = true; - } - if(isplay){ - play.play(); - } + } else { + isplay = false; } - currentStatus = STATUS_TOLD; - } else if(currentStatus <= STATUS_200_TURN && dist <= TURN_IN_DISTANCE){ - CommandBuilder play = getNewCommandPlayerToPlay(); - if (play != null) { - String tParam = getTurnType(next.turnType); - boolean isPlay = true; - if (tParam != null) { - play.turn(tParam, dist); - } else if (next.turnType.isRoundAbout()) { - play.roundAbout(dist, next.turnType.getTurnAngle(), next.turnType.getExitOut()); - } else if (next.turnType.getValue().equals(TurnType.TU)) { - play.makeUT(dist); - } else { - isPlay = false; - } - - if (nextNext != null && next.distance <= TURN_DISTANCE) { - TurnType t = nextNext.turnType; - isPlay = true; - if (next.turnType.getValue().equals(TurnType.C) && - !TurnType.C.equals(t.getValue())) { - play.goAhead(dist); - } - if (TurnType.TL.equals(t.getValue()) || TurnType.TSHL.equals(t.getValue()) || TurnType.TSLL.equals(t.getValue()) - || TurnType.TU.equals(t.getValue())) { - play.then().bearLeft(); - } else if (TurnType.TR.equals(t.getValue()) || TurnType.TSHR.equals(t.getValue()) || TurnType.TSLR.equals(t.getValue())) { - play.then().bearRight(); - } - } - if(isPlay){ - play.play(); + // add turn after next + if (nextNext != null) { + String t2Param = getTurnType(nextNext.turnType); + if (t2Param != null) { + if(isplay) { play.then(); } + play.turn(t2Param, next.distance); + } else if (nextNext.turnType.isRoundAbout()) { + if(isplay) { play.then(); } + play.roundAbout(next.distance, nextNext.turnType.getTurnAngle(), nextNext.turnType.getExitOut()); + } else if (nextNext.turnType.getValue().equals(TurnType.TU)) { + if(isplay) { play.then(); } + play.makeUT(next.distance); } + isplay = true; } - currentStatus = STATUS_TURN; - } else if(currentStatus <= STATUS_800_PREPARE && dist <= PREPARE_DISTANCE){ - CommandBuilder play = getNewCommandPlayerToPlay(); - if(play != null){ - String tParam = getTurnType(next.turnType); - if(tParam != null){ - play.prepareTurn(tParam, dist).play(); - } else if(next.turnType.isRoundAbout()){ - play.prepareRoundAbout(dist).play(); - } else if(next.turnType.getValue().equals(TurnType.TU)){ - play.prepareMakeUT(dist).play(); - } + if(isplay){ + play.play(); } - currentStatus = STATUS_200_TURN; - } else if((currentStatus <= STATUS_800_PREPARE && dist <= PREPARE_DISTANCE) - || (currentStatus <= STATUS_3000_PREPARE && dist <= PREPARE_LONG_DISTANCE_END && dist >= PREPARE_LONG_DISTANCE_ST)){ - CommandBuilder play = getNewCommandPlayerToPlay(); - if(play != null){ - String tParam = getTurnType(next.turnType); - if(tParam != null){ - play.prepareTurn(tParam, dist).play(); - } else if(next.turnType.isRoundAbout()){ - play.prepareRoundAbout(dist).play(); - } else if(next.turnType.getValue().equals(TurnType.TU)){ - play.prepareMakeUT(dist).play(); - } - } - currentStatus = currentStatus <= STATUS_3000_PREPARE ? STATUS_800_PREPARE : STATUS_200_TURN; } - - - - - } private String getTurnType(TurnType t){