Beispiel #1
0
 public boolean identifyUTurnIsNeeded(Location currentLocation, float posTolerance) {
   if (finalLocation == null || currentLocation == null || !route.isCalculated()) {
     this.makeUturnWhenPossible = false;
     return makeUturnWhenPossible;
   }
   boolean makeUturnWhenPossible = false;
   if (currentLocation.hasBearing()) {
     float bearingMotion = currentLocation.getBearing();
     Location nextRoutePosition = route.getNextRouteLocation();
     float bearingToRoute = currentLocation.bearingTo(nextRoutePosition);
     double diff = MapUtils.degreesDiff(bearingMotion, bearingToRoute);
     // 7. Check if you left the route and an unscheduled U-turn would bring you back (also Issue
     // 863)
     // This prompt is an interim advice and does only sound if a new route in forward direction
     // could not be found in x seconds
     if (Math.abs(diff) > 135f) {
       float d = currentLocation.distanceTo(nextRoutePosition);
       // 60m tolerance to allow for GPS inaccuracy
       if (d > posTolerance) {
         // require x sec continuous since first detection
         if (makeUTwpDetected == 0) {
           makeUTwpDetected = System.currentTimeMillis();
         } else if ((System.currentTimeMillis() - makeUTwpDetected > 10000)) {
           makeUturnWhenPossible = true;
           // log.info("bearingMotion is opposite to bearingRoute"); //$NON-NLS-1$
         }
       }
     } else {
       makeUTwpDetected = 0;
     }
   }
   this.makeUturnWhenPossible = makeUturnWhenPossible;
   return makeUturnWhenPossible;
 }
Beispiel #2
0
 public synchronized String getCurrentName() {
   NextDirectionInfo n = getNextRouteDirectionInfo(new NextDirectionInfo(), false);
   Location l = lastFixedLocation;
   float speed = 0;
   if (l != null && l.hasSpeed()) {
     speed = l.getSpeed();
   }
   if (n.distanceTo > 0
       && n.directionInfo != null
       && !n.directionInfo.getTurnType().isSkipToSpeak()
       && voiceRouter.isDistanceLess(speed, n.distanceTo, voiceRouter.PREPARE_DISTANCE * 0.75f)) {
     String nm = n.directionInfo.getStreetName();
     String rf = n.directionInfo.getRef();
     String dn = n.directionInfo.getDestinationName();
     return "\u2566 " + formatStreetName(nm, rf, dn);
   }
   RouteSegmentResult rs = getCurrentSegmentResult();
   if (rs != null) {
     String nm = rs.getObject().getName();
     String rf = rs.getObject().getRef();
     String dn = rs.getObject().getDestinationName();
     return "\u21E7 " + formatStreetName(nm, rf, dn);
   }
   return null;
 }
Beispiel #3
0
  public void announceCurrentDirection(Location currentLocation) {
    NextDirectionInfo nextInfo = router.getNextRouteDirectionInfo(new NextDirectionInfo(), true);
    if (nextInfo == null) {
      playGoAheadToDestination();
      return;
    }
    NextDirectionInfo nextNextInfo =
        router.getNextRouteDirectionInfoAfter(nextInfo, new NextDirectionInfo(), false);
    float speed = DEFAULT_SPEED;
    RouteDirectionInfo next = nextInfo.directionInfo;
    int dist = nextInfo.distanceTo;

    if (currentLocation != null && currentLocation.hasSpeed()) {
      speed = Math.max(currentLocation.getSpeed(), speed);
    }

    switch (currentStatus) {
      case STATUS_UTWP_TOLD:
        playMakeUTwp();
        break;
      case STATUS_UNKNOWN:
        if (nextRouteDirection != null && ((next == null) || (next.distance == 0))) {
          playGoAheadToDestination();
        } else {
          playGoAhead(dist);
        }
        break;
      case STATUS_TOLD:
        if (nextRouteDirection != null) {
          playGoAheadToDestination();
        }
        break;
      case STATUS_TURN:
        if (next.distance < TURN_IN_DISTANCE_END && nextNextInfo != null) {
          playMakeTurn(next, nextNextInfo.directionInfo);
        } else {
          playMakeTurn(next, null);
        }
        break;
      case STATUS_TURN_IN:
        if ((isDistanceLess(speed, next.distance, TURN_DISTANCE)
                || next.distance < TURN_IN_DISTANCE_END)
            && nextNextInfo != null) {
          playMakeTurnIn(next, dist, nextNextInfo.directionInfo);
        } else {
          playMakeTurnIn(next, dist, null);
        }
        break;
      case STATUS_PREPARE:
        playPrepareTurn(next, dist);
        break;
      case STATUS_LONG_PREPARE:
        playPrepareTurn(next, dist);
        break;
      default:
        break;
    }
  }
Beispiel #4
0
 public int calculateImminent(float dist, Location loc) {
   float speed = DEFAULT_SPEED;
   if (loc != null && loc.hasSpeed()) {
     speed = loc.getSpeed();
   }
   if (isDistanceLess(speed, dist, TURN_IN_DISTANCE_END)) {
     return 0;
   } else if (dist <= PREPARE_DISTANCE) {
     return 1;
   } else if (dist <= PREPARE_LONG_DISTANCE) {
     return 2;
   } else {
     return -1;
   }
 }
 private void updateCompassVisibility() {
   View compassView = view.findViewById(R.id.compass_layout);
   Location ll = getMyApplication().getLocationProvider().getLastKnownLocation();
   boolean gpsFixed =
       ll != null && System.currentTimeMillis() - ll.getTime() < 1000 * 60 * 60 * 20;
   if (gpsFixed
       && menu.displayDistanceDirection()
       && menu.getCurrentMenuState() != MenuState.FULL_SCREEN) {
     updateDistanceDirection();
     compassView.setVisibility(View.VISIBLE);
   } else {
     if (!menu.displayDistanceDirection()) {
       compassView.setVisibility(View.GONE);
     } else {
       compassView.setVisibility(View.INVISIBLE);
     }
   }
 }
Beispiel #6
0
 private static AlarmInfo createSpeedAlarm(
     MetricsConstants mc, float mxspeed, Location loc, float delta) {
   AlarmInfo speedAlarm = null;
   if (mxspeed != 0
       && loc != null
       && loc.hasSpeed()
       && mxspeed != RouteDataObject.NONE_MAX_SPEED) {
     if (loc.getSpeed() > mxspeed + delta) {
       int speed;
       if (mc == MetricsConstants.KILOMETERS_AND_METERS) {
         speed = Math.round(mxspeed * 3.6f);
       } else {
         speed = Math.round(mxspeed * 3.6f / 1.6f);
       }
       speedAlarm = AlarmInfo.createSpeedLimit(speed, loc);
     }
   }
   return speedAlarm;
 }
Beispiel #7
0
 public List<Amenity> searchAmenitiesOnThePath(
     List<Location> locations,
     double radius,
     SearchPoiTypeFilter filter,
     ResultMatcher<Amenity> matcher) {
   searchAmenitiesInProgress = true;
   final List<Amenity> amenities = new ArrayList<Amenity>();
   try {
     if (locations != null && locations.size() > 0) {
       List<AmenityIndexRepository> repos = new ArrayList<AmenityIndexRepository>();
       double topLatitude = locations.get(0).getLatitude();
       double bottomLatitude = locations.get(0).getLatitude();
       double leftLongitude = locations.get(0).getLongitude();
       double rightLongitude = locations.get(0).getLongitude();
       for (Location l : locations) {
         topLatitude = Math.max(topLatitude, l.getLatitude());
         bottomLatitude = Math.min(bottomLatitude, l.getLatitude());
         leftLongitude = Math.min(leftLongitude, l.getLongitude());
         rightLongitude = Math.max(rightLongitude, l.getLongitude());
       }
       if (!filter.isEmpty()) {
         for (AmenityIndexRepository index : amenityRepositories.values()) {
           if (index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude)) {
             repos.add(index);
           }
         }
         if (!repos.isEmpty()) {
           for (AmenityIndexRepository r : repos) {
             List<Amenity> res = r.searchAmenitiesOnThePath(locations, radius, filter, matcher);
             if (res != null) {
               amenities.addAll(res);
             }
           }
         }
       }
     }
   } finally {
     searchAmenitiesInProgress = false;
   }
   return amenities;
 }
Beispiel #8
0
 public AlarmInfo calculateMostImportantAlarm(
     RouteDataObject ro, Location loc, MetricsConstants mc, boolean showCameras) {
   boolean direction = true;
   if (loc.hasBearing()) {
     double diff =
         MapUtils.alignAngleDifference(
             ro.directionRoute(0, true) - loc.getBearing() / (2 * Math.PI));
     direction = Math.abs(diff) < Math.PI;
   }
   float mxspeed = ro.getMaximumSpeed(direction);
   float delta = app.getSettings().SPEED_LIMIT_EXCEED.get() / 3.6f;
   AlarmInfo speedAlarm = createSpeedAlarm(mc, mxspeed, loc, delta);
   if (speedAlarm != null) {
     getVoiceRouter().announceSpeedAlarm();
     return speedAlarm;
   }
   for (int i = 0; i < ro.getPointsLength(); i++) {
     int[] pointTypes = ro.getPointTypes(i);
     RouteRegion reg = ro.region;
     if (pointTypes != null) {
       for (int r = 0; r < pointTypes.length; r++) {
         RouteTypeRule typeRule = reg.quickGetEncodingRule(pointTypes[r]);
         AlarmInfo info = AlarmInfo.createAlarmInfo(typeRule, 0, loc);
         if (info != null) {
           if (info.getType() != AlarmInfoType.SPEED_CAMERA || showCameras) {
             long ms = System.currentTimeMillis();
             if (ms - announcedAlarmTime > 50 * 1000) {
               announcedAlarmTime = ms;
               getVoiceRouter().announceAlarm(info.getType());
             }
             return info;
           }
         }
       }
     }
   }
   return null;
 }
Beispiel #9
0
 public AlarmInfo getMostImportantAlarm(MetricsConstants mc, boolean showCameras) {
   Location lastProjection = app.getRoutingHelper().getLastProjection();
   float mxspeed = route.getCurrentMaxSpeed();
   float delta = app.getSettings().SPEED_LIMIT_EXCEED.get() / 3.6f;
   AlarmInfo speedAlarm = createSpeedAlarm(mc, mxspeed, lastProjection, delta);
   if (speedAlarm != null) {
     getVoiceRouter().announceSpeedAlarm();
   }
   AlarmInfo mostImportant = speedAlarm;
   int value =
       speedAlarm != null ? speedAlarm.updateDistanceAndGetPriority(0, 0) : Integer.MAX_VALUE;
   if (ALARMS < pointsProgress.size()) {
     int kIterator = pointsProgress.get(ALARMS);
     List<LocationPointWrapper> lp = locationPoints.get(ALARMS);
     while (kIterator < lp.size()) {
       LocationPointWrapper lwp = lp.get(kIterator);
       if (lp.get(kIterator).routeIndex < route.getCurrentRoute()) {
         // skip
       } else {
         int d = route.getDistanceToPoint(lwp.routeIndex);
         if (d > LONG_ANNOUNCE_RADIUS) {
           break;
         }
         AlarmInfo inf = (AlarmInfo) lwp.point;
         float speed =
             lastProjection != null && lastProjection.hasSpeed() ? lastProjection.getSpeed() : 0;
         float time = speed > 0 ? d / speed : Integer.MAX_VALUE;
         int vl = inf.updateDistanceAndGetPriority(time, d);
         if (vl < value && (showCameras || inf.getType() != AlarmInfoType.SPEED_CAMERA)) {
           mostImportant = inf;
           value = vl;
         }
       }
       kIterator++;
     }
   }
   return mostImportant;
 }
 public int getDistance() {
   int d = 0;
   LatLon l = getPointToNavigate();
   if (l != null) {
     Location.distanceBetween(
         view.getLatitude(),
         view.getLongitude(),
         l.getLatitude(),
         l.getLongitude(),
         calculations);
     d = (int) calculations[0];
   }
   return d;
 }
Beispiel #11
0
 private static LatLon getProject(Location loc, Location from, Location to) {
   return MapUtils.getProjection(
       loc.getLatitude(),
       loc.getLongitude(),
       from.getLatitude(),
       from.getLongitude(),
       to.getLatitude(),
       to.getLongitude());
 }
Beispiel #12
0
 private static double getOrthogonalDistance(Location loc, Location from, Location to) {
   return MapUtils.getOrthogonalDistance(
       loc.getLatitude(),
       loc.getLongitude(),
       from.getLatitude(),
       from.getLongitude(),
       to.getLatitude(),
       to.getLongitude());
 }
Beispiel #13
0
 /**
  * Wrong movement direction is considered when between current location bearing (determines by 2
  * last fixed position or provided) and bearing from currentLocation to next (current) point the
  * difference is more than 60 degrees
  */
 public boolean checkWrongMovementDirection(Location currentLocation, Location nextRouteLocation) {
   // measuring without bearing could be really error prone (with last fixed location)
   // this code has an effect on route recalculation which should be detected without mistakes
   if (currentLocation.hasBearing() && nextRouteLocation != null) {
     float bearingMotion = currentLocation.getBearing();
     float bearingToRoute = currentLocation.bearingTo(nextRouteLocation);
     double diff = MapUtils.degreesDiff(bearingMotion, bearingToRoute);
     if (Math.abs(diff) > 60f) {
       // require delay interval since first detection, to avoid false positive
       // but leave out for now, as late detection is worse than false positive (it may reset voice
       // router then cause bogus turn and u-turn prompting)
       // if (wrongMovementDetected == 0) {
       //	wrongMovementDetected = System.currentTimeMillis();
       // } else if ((System.currentTimeMillis() - wrongMovementDetected > 500)) {
       return true;
       // }
     } else {
       // wrongMovementDetected = 0;
       return false;
     }
   }
   // wrongMovementDetected = 0;
   return false;
 }
  @Override
  public void onCreate(Bundle savedInstanceState) {
    app = getMyApplication();
    settings = app.getSettings();
    app.applyTheme(this);
    super.onCreate(savedInstanceState);

    mapActions = new MapActivityActions(this);
    mapLayers = new MapActivityLayers(this);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    // Full screen is not used here
    // getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
    // WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.main);
    startProgressDialog = new ProgressDialog(this);
    startProgressDialog.setCancelable(true);
    app.checkApplicationIsBeingInitialized(this, startProgressDialog);
    parseLaunchIntentLocation();

    mapView = (OsmandMapTileView) findViewById(R.id.MapView);
    mapView.setTrackBallDelegate(
        new OsmandMapTileView.OnTrackBallListener() {
          @Override
          public boolean onTrackBallEvent(MotionEvent e) {
            showAndHideMapPosition();
            return MapActivity.this.onTrackballEvent(e);
          }
        });
    mapView.setAccessibilityActions(new MapAccessibilityActions(this));
    if (mapViewTrackingUtilities == null) {
      mapViewTrackingUtilities = new MapViewTrackingUtilities(app);
    }
    mapViewTrackingUtilities.setMapView(mapView);

    // Do some action on close
    startProgressDialog.setOnDismissListener(
        new DialogInterface.OnDismissListener() {
          @Override
          public void onDismiss(DialogInterface dialog) {
            app.getResourceManager().getRenderer().clearCache();
            mapView.refreshMap(true);
          }
        });

    app.getResourceManager()
        .getMapTileDownloader()
        .addDownloaderCallback(
            new IMapDownloaderCallback() {
              @Override
              public void tileDownloaded(DownloadRequest request) {
                if (request != null && !request.error && request.fileToSave != null) {
                  ResourceManager mgr = app.getResourceManager();
                  mgr.tileDownloaded(request);
                }
                if (request == null || !request.error) {
                  mapView.tileDownloaded(request);
                }
              }
            });
    createProgressBarForRouting();
    // This situtation could be when navigation suddenly crashed and after restarting
    // it tries to continue the last route
    if (settings.FOLLOW_THE_ROUTE.get()
        && !app.getRoutingHelper().isRouteCalculated()
        && !app.getRoutingHelper().isRouteBeingCalculated()) {
      FailSafeFuntions.restoreRoutingMode(this);
    }

    mapLayers.createLayers(mapView);

    if (!settings.isLastKnownMapLocation()) {
      // show first time when application ran
      net.osmand.Location location = app.getLocationProvider().getFirstTimeRunDefaultLocation();
      if (location != null) {
        mapView.setLatLon(location.getLatitude(), location.getLongitude());
        mapView.setZoom(14);
      }
    }
    addDialogProvider(mapActions);
    OsmandPlugin.onMapActivityCreate(this);
    if (lockView != null) {
      ((FrameLayout) mapView.getParent()).addView(lockView);
    }
  }
Beispiel #15
0
 public void announceVisibleLocations() {
   Location lastKnownLocation = app.getRoutingHelper().getLastProjection();
   if (lastKnownLocation != null && app.getRoutingHelper().isFollowingMode()) {
     for (int type = 0; type < locationPoints.size(); type++) {
       int currentRoute = route.getCurrentRoute();
       List<LocationPointWrapper> approachPoints = new ArrayList<LocationPointWrapper>();
       List<LocationPointWrapper> announcePoints = new ArrayList<LocationPointWrapper>();
       List<LocationPointWrapper> lp = locationPoints.get(type);
       if (lp != null) {
         int kIterator = pointsProgress.get(type);
         while (kIterator < lp.size() && lp.get(kIterator).routeIndex < currentRoute) {
           kIterator++;
         }
         pointsProgress.set(type, kIterator);
         while (kIterator < lp.size()) {
           LocationPointWrapper lwp = lp.get(kIterator);
           if (route.getDistanceToPoint(lwp.routeIndex) > LONG_ANNOUNCE_RADIUS * 2) {
             break;
           }
           LocationPoint point = lwp.point;
           double d1 =
               Math.max(
                   0.0,
                   MapUtils.getDistance(
                           lastKnownLocation.getLatitude(),
                           lastKnownLocation.getLongitude(),
                           point.getLatitude(),
                           point.getLongitude())
                       - lwp.getDeviationDistance());
           Integer state = locationPointsStates.get(point);
           if (state != null
               && state.intValue() == ANNOUNCED_ONCE
               && getVoiceRouter()
                   .isDistanceLess(lastKnownLocation.getSpeed(), d1, SHORT_ANNOUNCE_RADIUS, 0f)) {
             locationPointsStates.put(point, ANNOUNCED_DONE);
             announcePoints.add(lwp);
           } else if (type != ALARMS
               && (state == null || state == NOT_ANNOUNCED)
               && getVoiceRouter()
                   .isDistanceLess(lastKnownLocation.getSpeed(), d1, LONG_ANNOUNCE_RADIUS, 0f)) {
             locationPointsStates.put(point, ANNOUNCED_ONCE);
             approachPoints.add(lwp);
           } else if (type == ALARMS
               && (state == null || state == NOT_ANNOUNCED)
               && getVoiceRouter()
                   .isDistanceLess(lastKnownLocation.getSpeed(), d1, ALARMS_ANNOUNCE_RADIUS, 0f)) {
             locationPointsStates.put(point, ANNOUNCED_ONCE);
             approachPoints.add(lwp);
           }
           kIterator++;
         }
         if (!announcePoints.isEmpty()) {
           if (announcePoints.size() > ANNOUNCE_POI_LIMIT) {
             announcePoints = announcePoints.subList(0, ANNOUNCE_POI_LIMIT);
           }
           if (type == WAYPOINTS) {
             getVoiceRouter().announceWaypoint(announcePoints);
           } else if (type == POI) {
             getVoiceRouter().announcePoi(announcePoints);
           } else if (type == ALARMS) {
             // nothing to announce
           } else if (type == FAVORITES) {
             getVoiceRouter().announceFavorite(announcePoints);
           }
         }
         if (!approachPoints.isEmpty()) {
           if (approachPoints.size() > APPROACH_POI_LIMIT) {
             approachPoints = approachPoints.subList(0, APPROACH_POI_LIMIT);
           }
           if (type == WAYPOINTS) {
             getVoiceRouter().approachWaypoint(lastKnownLocation, approachPoints);
           } else if (type == POI) {
             getVoiceRouter().approachPoi(lastKnownLocation, approachPoints);
           } else if (type == ALARMS) {
             EnumSet<AlarmInfoType> ait = EnumSet.noneOf(AlarmInfoType.class);
             for (LocationPointWrapper pw : approachPoints) {
               ait.add(((AlarmInfo) pw.point).getType());
             }
             for (AlarmInfoType t : ait) {
               app.getRoutingHelper().getVoiceRouter().announceAlarm(t);
             }
           } else if (type == FAVORITES) {
             getVoiceRouter().approachFavorite(lastKnownLocation, approachPoints);
           }
         }
       }
     }
   }
 }
 public boolean updateInfo(DrawSettings drawSettings) {
   boolean visible = false;
   int locimminent = -1;
   int[] loclanes = null;
   int dist = 0;
   // TurnType primary = null;
   if ((rh == null || !rh.isFollowingMode())
       && trackingUtilities.isMapLinkedToLocation()
       && settings.SHOW_LANES.get()) {
     RouteDataObject ro = locationProvider.getLastKnownRouteSegment();
     Location lp = locationProvider.getLastKnownLocation();
     if (ro != null) {
       float degree = lp == null || !lp.hasBearing() ? 0 : lp.getBearing();
       loclanes = RouteResultPreparation.parseTurnLanes(ro, degree / 180 * Math.PI);
       if (loclanes == null) {
         loclanes = RouteResultPreparation.parseLanes(ro, degree / 180 * Math.PI);
       }
     }
   } else if (rh != null && rh.isRouteCalculated()) {
     if (rh.isFollowingMode() && settings.SHOW_LANES.get()) {
       NextDirectionInfo r = rh.getNextRouteDirectionInfo(new NextDirectionInfo(), false);
       if (r != null && r.directionInfo != null && r.directionInfo.getTurnType() != null) {
         loclanes = r.directionInfo.getTurnType().getLanes();
         // primary = r.directionInfo.getTurnType();
         locimminent = r.imminent;
         // Do not show too far
         if ((r.distanceTo > 800 && r.directionInfo.getTurnType().isSkipToSpeak())
             || r.distanceTo > 1200) {
           loclanes = null;
         }
         dist = r.distanceTo;
       }
     } else {
       int di = MapRouteInfoControl.getDirectionInfo();
       if (di >= 0
           && MapRouteInfoControl.isControlVisible()
           && di < rh.getRouteDirections().size()) {
         RouteDirectionInfo next = rh.getRouteDirections().get(di);
         if (next != null) {
           loclanes = next.getTurnType().getLanes();
           // primary = next.getTurnType();
         }
       }
     }
   }
   visible = loclanes != null && loclanes.length > 0;
   if (visible) {
     if (!Arrays.equals(lanesDrawable.lanes, loclanes)
         || (locimminent == 0) != lanesDrawable.imminent) {
       lanesDrawable.imminent = locimminent == 0;
       lanesDrawable.lanes = loclanes;
       lanesDrawable.updateBounds();
       lanesView.setImageDrawable(null);
       lanesView.setImageDrawable(lanesDrawable);
       lanesView.requestLayout();
       lanesView.invalidate();
     }
     if (distChanged(dist, this.dist)) {
       this.dist = dist;
       if (dist == 0) {
         lanesShadowText.setText("");
         lanesText.setText("");
       } else {
         lanesShadowText.setText(OsmAndFormatter.getFormattedDistance(dist, app));
         lanesText.setText(OsmAndFormatter.getFormattedDistance(dist, app));
       }
       lanesShadowText.invalidate();
       lanesText.invalidate();
     }
   }
   updateVisibility(lanesShadowText, visible && shadowRadius > 0);
   updateVisibility(lanesText, visible);
   updateVisibility(lanesView, visible);
   updateVisibility(centerInfo, visible || progress.getVisibility() == View.VISIBLE);
   return true;
 }
Beispiel #17
0
  /**
   * Updates status of voice guidance
   *
   * @param currentLocation
   */
  protected void updateStatus(Location currentLocation) {
    // Directly after turn: goAhead (dist), unless:
    // < PREPARE_LONG_DISTANCE (3000m): playPrepareTurn
    // < PREPARE_DISTANCE (1500m): playPrepareTurn
    // < TURN_IN_DISTANCE (300m or 25sec): playMakeTurnIn
    // < TURN_DISTANCE (60m or 5sec): playMakeTurn
    float speed = DEFAULT_SPEED;
    if (currentLocation != null && currentLocation.hasSpeed()) {
      speed = Math.max(currentLocation.getSpeed(), speed);
    }

    NextDirectionInfo nextInfo = router.getNextRouteDirectionInfo(new NextDirectionInfo(), true);
    // after last turn say:
    if (nextInfo == null
        || nextInfo.directionInfo == null
        || nextInfo.directionInfo.distance == 0) {
      // if(currentStatus <= STATUS_UNKNOWN && currentDirection > 0){ This caused this prompt to be
      // suppressed when coming back from a
      if (currentStatus <= STATUS_UNKNOWN) {
        if (playGoAheadToDestination()) {
          currentStatus = STATUS_TOLD;
          playGoAheadDist = 0;
        }
      }
      return;
    }
    if (nextInfo.intermediatePoint) {
      if (currentStatus <= STATUS_UNKNOWN) {
        if (playGoAheadToIntermediate()) {
          currentStatus = STATUS_TOLD;
          playGoAheadDist = 0;
        }
      }
      return;
    }
    int dist = nextInfo.distanceTo;
    RouteDirectionInfo next = nextInfo.directionInfo;

    // if routing is changed update status to unknown
    if (next != nextRouteDirection) {
      nextRouteDirection = next;
      currentStatus = STATUS_UNKNOWN;
      playGoAheadDist = 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 ?
      return;
    }
    // say how much to go if there is next turn is a bit far
    if (currentStatus == STATUS_UNKNOWN) {
      if (!isDistanceLess(speed, dist, TURN_IN_DISTANCE * 1.3)) {
        playGoAheadDist = dist - 80;
      }
      // say long distance message only for long distances > 10 km
      // if (dist >= PREPARE_LONG_DISTANCE && !isDistanceLess(speed, dist, PREPARE_LONG_DISTANCE)) {
      if (dist > PREPARE_LONG_DISTANCE + 300) {
        nextStatusAfter(STATUS_UNKNOWN);
      } else if (dist > PREPARE_DISTANCE + 300) {
        // say prepare message if it is far enough and don't say preare long distance
        nextStatusAfter(STATUS_LONG_PREPARE);
      } else {
        // don't say even prepare message
        nextStatusAfter(STATUS_PREPARE);
      }
    }

    NextDirectionInfo nextNextInfo =
        router.getNextRouteDirectionInfoAfter(nextInfo, new NextDirectionInfo(), true);
    if (statusNotPassed(STATUS_TURN)
        && isDistanceLess(speed, dist, TURN_DISTANCE, TURN_DEFAULT_SPEED)) {
      if (next.distance < TURN_IN_DISTANCE_END && nextNextInfo != null) {
        playMakeTurn(next, nextNextInfo.directionInfo);
      } else {
        playMakeTurn(next, null);
      }
      nextStatusAfter(STATUS_TURN);
    } else if (statusNotPassed(STATUS_TURN_IN) && 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)
            && nextNextInfo != null) {
          playMakeTurnIn(next, dist, nextNextInfo.directionInfo);
        } else {
          playMakeTurnIn(next, dist, null);
        }
      }
      nextStatusAfter(STATUS_TURN_IN);
      // } else if (statusNotPassed(STATUS_PREPARE) && isDistanceLess(speed, dist,
      // PREPARE_DISTANCE)) {
    } else if (statusNotPassed(STATUS_PREPARE) && (dist <= PREPARE_DISTANCE)) {
      if (dist >= PREPARE_DISTANCE_END) {
        if (next.getTurnType().keepLeft() || next.getTurnType().keepRight()) {
          // do not play prepare for keep left/right
        } else {
          playPrepareTurn(next, dist);
        }
      }
      nextStatusAfter(STATUS_PREPARE);
      // } else if (statusNotPassed(STATUS_LONG_PREPARE) && isDistanceLess(speed, dist,
      // PREPARE_LONG_DISTANCE)){
    } else if (statusNotPassed(STATUS_LONG_PREPARE) && (dist <= PREPARE_LONG_DISTANCE)) {
      if (dist >= PREPARE_LONG_DISTANCE_END) {
        playPrepareTurn(next, dist);
      }
      nextStatusAfter(STATUS_LONG_PREPARE);
    } else if (statusNotPassed(STATUS_UNKNOWN)) {
      // strange how we get here but
      nextStatusAfter(STATUS_UNKNOWN);
    } else if (statusNotPassed(STATUS_TURN_IN) && dist < playGoAheadDist) {
      playGoAheadDist = 0;
      playGoAhead(dist);
    }
  }
Beispiel #18
0
  private Location setCurrentLocation(
      Location currentLocation,
      boolean returnUpdatedLocation,
      RouteCalculationResult previousRoute) {
    Location locationProjection = currentLocation;
    if (finalLocation == null || currentLocation == null) {
      makeUturnWhenPossible = false;
      return locationProjection;
    }
    float posTolerance = POSITION_TOLERANCE;
    if (currentLocation.hasAccuracy()) {
      posTolerance = POSITION_TOLERANCE / 2 + currentLocation.getAccuracy();
    }
    boolean calculateRoute = false;
    synchronized (this) {
      // 0. Route empty or needs to be extended? Then re-calculate route.
      if (route.isEmpty()) {
        calculateRoute = true;
      } else {
        // 1. Update current route position status according to latest received location
        boolean finished = updateCurrentRouteStatus(currentLocation, posTolerance);
        if (finished) {
          return null;
        }
        List<Location> routeNodes = route.getImmutableAllLocations();
        int currentRoute = route.currentRoute;

        // 2. Analyze if we need to recalculate route
        // >100m off current route (sideways)
        if (currentRoute > 0) {
          double dist =
              getOrthogonalDistance(
                  currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute));
          if (dist > 1.7 * posTolerance) {
            log.info("Recalculate route, because correlation  : " + dist); // $NON-NLS-1$
            calculateRoute = true;
          }
          if (dist > 350) {
            voiceRouter.announceOffRoute(dist);
          }
        }
        // 3. Identify wrong movement direction
        Location next = route.getNextRouteLocation();
        boolean wrongMovementDirection = checkWrongMovementDirection(currentLocation, next);
        if (wrongMovementDirection
            && currentLocation.distanceTo(routeNodes.get(currentRoute)) > 2 * posTolerance) {
          log.info(
              "Recalculate route, because wrong movement direction: "
                  + currentLocation.distanceTo(routeNodes.get(currentRoute))); // $NON-NLS-1$
          calculateRoute = true;
        }
        // 4. Identify if UTurn is needed
        boolean uTurnIsNeeded = identifyUTurnIsNeeded(currentLocation, posTolerance);
        // 5. Update Voice router
        if (isFollowingMode) {
          // don't update in route planing mode
          announceGpxWaypoints(currentLocation);
          boolean inRecalc = calculateRoute || isRouteBeingCalculated();
          if (!inRecalc && !uTurnIsNeeded && !wrongMovementDirection) {
            voiceRouter.updateStatus(currentLocation, false);
          } else if (uTurnIsNeeded) {
            voiceRouter.makeUTStatus();
          }
        }

        // calculate projection of current location
        if (currentRoute > 0) {
          locationProjection = new Location(currentLocation);
          Location nextLocation = routeNodes.get(currentRoute);
          LatLon project =
              getProject(
                  currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute));

          locationProjection.setLatitude(project.getLatitude());
          locationProjection.setLongitude(project.getLongitude());
          // we need to update bearing too
          float bearingTo = locationProjection.bearingTo(nextLocation);
          locationProjection.setBearing(bearingTo);
        }
      }
      lastFixedLocation = currentLocation;
      lastProjection = locationProjection;
    }

    if (calculateRoute) {
      recalculateRouteInBackground(
          false,
          currentLocation,
          finalLocation,
          intermediatePoints,
          currentGPXRoute,
          previousRoute.isCalculated() ? previousRoute : null);
    } else if (currentRunningJob != null && currentRunningJob instanceof RouteRecalculationThread) {
      RouteRecalculationThread thread = (RouteRecalculationThread) currentRunningJob;
      thread.stopCalculation();
    }

    double projectDist = mode != null && mode.hasFastSpeed() ? posTolerance : posTolerance / 2;
    if (returnUpdatedLocation
        && locationProjection != null
        && currentLocation.distanceTo(locationProjection) < projectDist) {
      return locationProjection;
    } else {
      return currentLocation;
    }
  }
Beispiel #19
0
  private boolean updateCurrentRouteStatus(Location currentLocation, float posTolerance) {
    List<Location> routeNodes = route.getImmutableAllLocations();
    int currentRoute = route.currentRoute;
    // 1. Try to proceed to next point using orthogonal distance (finding minimum orthogonal dist)
    while (currentRoute + 1 < routeNodes.size()) {
      double dist = currentLocation.distanceTo(routeNodes.get(currentRoute));
      if (currentRoute > 0) {
        dist =
            getOrthogonalDistance(
                currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute));
      }
      boolean processed = false;
      // if we are still too far try to proceed many points
      // if not then look ahead only 3 in order to catch sharp turns
      boolean longDistance = dist >= 250;
      int newCurrentRoute =
          lookAheadFindMinOrthogonalDistance(
              currentLocation, routeNodes, currentRoute, longDistance ? 15 : 8);
      double newDist =
          getOrthogonalDistance(
              currentLocation,
              routeNodes.get(newCurrentRoute),
              routeNodes.get(newCurrentRoute + 1));
      if (longDistance) {
        if (newDist < dist) {
          if (log.isDebugEnabled()) {
            log.debug(
                "Processed by distance : (new) "
                    + newDist
                    + " (old) "
                    + dist); //$NON-NLS-1$//$NON-NLS-2$
          }
          processed = true;
        }
      } else if (newDist < dist || newDist < 10) {
        // newDist < 10 (avoid distance 0 till next turn)
        if (dist > posTolerance) {
          processed = true;
          if (log.isDebugEnabled()) {
            log.debug(
                "Processed by distance : " + newDist + " " + dist); // $NON-NLS-1$//$NON-NLS-2$
          }
        } else {
          // case if you are getting close to the next point after turn
          // but you have not yet turned (could be checked bearing)
          if (currentLocation.hasBearing() || lastFixedLocation != null) {
            float bearingToRoute = currentLocation.bearingTo(routeNodes.get(currentRoute));
            float bearingRouteNext =
                routeNodes.get(newCurrentRoute).bearingTo(routeNodes.get(newCurrentRoute + 1));
            float bearingMotion =
                currentLocation.hasBearing()
                    ? currentLocation.getBearing()
                    : lastFixedLocation.bearingTo(currentLocation);
            double diff = Math.abs(MapUtils.degreesDiff(bearingMotion, bearingToRoute));
            double diffToNext = Math.abs(MapUtils.degreesDiff(bearingMotion, bearingRouteNext));
            if (diff > diffToNext) {
              if (log.isDebugEnabled()) {
                log.debug("Processed point bearing deltas : " + diff + " " + diffToNext);
              }
              processed = true;
            }
          }
        }
      }
      if (processed) {
        // that node already passed
        route.updateCurrentRoute(newCurrentRoute + 1);
        currentRoute = newCurrentRoute + 1;
      } else {
        break;
      }
    }

    // 2. check if intermediate found
    if (route.getIntermediatePointsToPass() > 0
        && route.getDistanceToNextIntermediate(lastFixedLocation) < POSITION_TOLERANCE * 2) {
      showMessage(app.getString(R.string.arrived_at_intermediate_point));
      route.passIntermediatePoint();

      TargetPointsHelper targets = app.getTargetPointsHelper();
      List<String> ns = targets.getIntermediatePointNames();
      int toDel = targets.getIntermediatePoints().size() - route.getIntermediatePointsToPass();
      int currentIndex = toDel - 1;
      String name =
          currentIndex < 0 || currentIndex >= ns.size() || ns.get(currentIndex) == null
              ? ""
              : ns.get(currentIndex);
      if (isFollowingMode) {
        voiceRouter.arrivedIntermediatePoint(name);
      }
      while (toDel > 0) {
        targets.removeWayPoint(false, 0);
        toDel--;
      }

      while (intermediatePoints != null
          && route.getIntermediatePointsToPass() < intermediatePoints.size()) {
        intermediatePoints.remove(0);
      }
    }

    // 3. check if destination found
    Location lastPoint = routeNodes.get(routeNodes.size() - 1);
    if (currentRoute > routeNodes.size() - 3
        && currentLocation.distanceTo(lastPoint)
            < (((float) settings.getApplicationMode().getArrivalDistance())
                * settings.ARRIVAL_DISTANCE_FACTOR.get())) {
      showMessage(app.getString(R.string.arrived_at_destination));
      TargetPointsHelper targets = app.getTargetPointsHelper();
      String description = targets.getPointNavigateDescription();
      if (isFollowingMode) {
        voiceRouter.arrivedDestinationPoint(description);
      }
      if (OsmandPlugin.onDestinationReached()) {
        clearCurrentRoute(null, null);
        setRoutePlanningMode(false);
        app.runInUIThread(
            new Runnable() {
              @Override
              public void run() {
                settings.APPLICATION_MODE.set(settings.DEFAULT_APPLICATION_MODE.get());
              }
            });
        // targets.clearPointToNavigate(false);
        return true;
      }
    }
    return false;
  }