Fix voice router. Consider speed, be more accurate

This commit is contained in:
Victor Shcherb 2011-07-15 01:35:24 +02:00
parent f07e297cdf
commit f77b3869af
3 changed files with 206 additions and 131 deletions

View file

@ -321,7 +321,7 @@ public class RoutingHelper {
// } // }
} }
} }
voiceRouter.updateStatus(); voiceRouter.updateStatus(currentLocation);
lastFixedLocation = currentLocation; lastFixedLocation = currentLocation;
if(calculateRoute){ if(calculateRoute){

View file

@ -226,10 +226,10 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
} }
registerListPreference(osmandSettings.MAX_LEVEL_TO_DOWNLOAD_TILE, screen, entries, intValues); 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]; entries = new String[floatValues.length];
for (int i = 0; i < floatValues.length; i++) { 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); registerListPreference(osmandSettings.MAP_TEXT_SIZE, screen, entries, floatValues);

View file

@ -6,6 +6,7 @@ import net.osmand.plus.voice.AbstractPrologCommandPlayer;
import net.osmand.plus.voice.CommandBuilder; import net.osmand.plus.voice.CommandBuilder;
import net.osmand.plus.voice.CommandPlayer; import net.osmand.plus.voice.CommandPlayer;
import android.app.Activity; import android.app.Activity;
import android.location.Location;
public class VoiceRouter { public class VoiceRouter {
@ -25,6 +26,19 @@ public class VoiceRouter {
private int currentStatus = STATUS_UNKNOWN; 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) { public VoiceRouter(RoutingHelper router, CommandPlayer player) {
this.router = router; this.router = router;
@ -53,42 +67,89 @@ public class VoiceRouter {
return player.newCommandBuilder(); 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(){ public void updateAppMode(){
// Else consider default time
if(router.getAppMode() == ApplicationMode.PEDESTRIAN){ if(router.getAppMode() == ApplicationMode.PEDESTRIAN){
PREPARE_DISTANCE = 400; // prepare distance needed ?
TURN_IN_DISTANCE = 150; PREPARE_DISTANCE = 320; // 160 second
TURN_DISTANCE = 30; 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){ } else if(router.getAppMode() == ApplicationMode.BICYCLE){
PREPARE_DISTANCE = 550; PREPARE_DISTANCE = 530; // 100 seconds
TURN_IN_DISTANCE = 200; PREPARE_DISTANCE_END = 370; // 70 seconds
TURN_DISTANCE = 55; TURN_IN_DISTANCE = 230; // 40 seconds
TURN_IN_DISTANCE_END = 90; // 16 seconds
TURN_DISTANCE = 55; // 11 seconds
DEFAULT_SPEED = 5;
} else { } else {
PREPARE_DISTANCE = 800; PREPARE_DISTANCE = 730; // 60 seconds
TURN_IN_DISTANCE = 300; PREPARE_DISTANCE_END = 530; // 45 seconds
TURN_DISTANCE = 70; 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) // directly after turn (go - ahead dist)
// < 800m prepare // < 800m prepare
// < 200m turn in // < 200m turn in
// < 50m turn // < 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){ if(currentDirection != router.currentDirectionInfo){
currentDirection = router.currentDirectionInfo; currentDirection = router.currentDirectionInfo;
currentStatus = STATUS_UNKNOWN; currentStatus = STATUS_UNKNOWN;
} }
RouteDirectionInfo next = router.getNextRouteDirectionInfo();
int dist = router.getDistanceToNextRouteDirection();
// the last turn say
if(next == null || next.distance == 0) { if(next == null || next.distance == 0) {
if(currentStatus == STATUS_UNKNOWN && currentDirection > 0){ if(currentStatus == STATUS_UNKNOWN && currentDirection > 0){
CommandBuilder play = getNewCommandPlayerToPlay(); CommandBuilder play = getNewCommandPlayerToPlay();
@ -99,29 +160,111 @@ public class VoiceRouter {
} }
return; return;
} }
if(dist == 0){ if(dist == 0 || currentStatus == STATUS_TOLD){
// nothing said possibly that's wrong case we should say before that // 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; return;
} }
RouteDirectionInfo nextNext = router.getNextNextRouteDirectionInfo();
if(currentStatus == STATUS_UNKNOWN){ RouteDirectionInfo nextNext = router.getNextNextRouteDirectionInfo();
if(dist > PREPARE_DISTANCE){ 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);
}
}
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(); CommandBuilder play = getNewCommandPlayerToPlay();
if(play != null){ if(play != null){
play.goAhead(dist).play(); play.goAhead(dist).play();
} }
currentStatus = STATUS_3000_PREPARE; }
} else if (dist < TURN_IN_DISTANCE){
// should already told it private void playPrepareLongDistanceTurn(RouteDirectionInfo next, int dist) {
currentStatus = STATUS_TURN; 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){
private void playMakeTurnRightNow(RouteDirectionInfo next, RouteDirectionInfo nextNext) {
CommandBuilder play = getNewCommandPlayerToPlay(); CommandBuilder play = getNewCommandPlayerToPlay();
if(play != null){ if(play != null){
String tParam = getTurnType(next.turnType); String tParam = getTurnType(next.turnType);
@ -138,8 +281,8 @@ public class VoiceRouter {
} else { } else {
isplay = false; isplay = false;
} }
// add turn after next
if (nextNext != null && next.distance <= TURN_IN_DISTANCE) { if (nextNext != null) {
String t2Param = getTurnType(nextNext.turnType); String t2Param = getTurnType(nextNext.turnType);
if (t2Param != null) { if (t2Param != null) {
if(isplay) { play.then(); } if(isplay) { play.then(); }
@ -157,74 +300,6 @@ public class VoiceRouter {
play.play(); play.play();
} }
} }
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();
}
}
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();
}
}
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){ private String getTurnType(TurnType t){