Skip to content

Commit

Permalink
Upgrade RouteProgress Step Data (#812)
Browse files Browse the repository at this point in the history
* Add current and upcoming step coordinates to RouteProgress

* Update route progress with current and upcoming step points
- Update tests

* Add tunnel distance calculation

* Finish intersection calculations

* Move distance processing to RouteProcessor

* Don't allow processing of first point

* Update next step nullable

* Update tests

* Add current annotation work
- Begin current and upcoming StepIntersections

* Add current and upcoming intersections in RouteStepProgress

* Finish tests and update test fixtures

* Remove tunnel milestone, no longer in scope

* Update CurrentLegAnnotation javadoc
  • Loading branch information
danesfeder authored Apr 18, 2018
1 parent 9e95f4b commit 2387ad5
Show file tree
Hide file tree
Showing 39 changed files with 2,344 additions and 1,445 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@ navigation-fixtures:
# Intersection:
curl "https://api.mapbox.com/directions/v5/mapbox/driving/-101.70939001157072,33.62145406099651;-101.68721910152767,33.6213852194939?geometries=polyline6&steps=true&access_token=$(MAPBOX_ACCESS_TOKEN)" \
-o libandroid-navigation/src/test/resources/single_intersection.json

# Distance Congestion annotation: Mapbox DC to National Mall
curl "https://api.mapbox.com/directions/v5/mapbox/driving-traffic/-77.034042,38.899949;-77.03949,38.888871?geometries=polyline6&overview=full&steps=true&annotations=congestion%2Cdistance&access_token=$(MAPBOX_ACCESS_TOKEN)" \
-o libandroid-navigation/src/test/resources/directions_distance_congestion_annotation.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public DynamicCamera(@NonNull MapboxMap mapboxMap) {
@Override
public Point target(RouteInformation routeInformation) {
if (routeInformation.location() != null) {
Location target = new Location(routeInformation.location());
Location target = routeInformation.location();
return Point.fromLngLat(target.getLongitude(), target.getLatitude());
} else if (routeInformation.route() != null) {
return super.target(routeInformation);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
package com.mapbox.services.android.navigation.ui.v5;

import com.google.gson.JsonParser;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;

import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;

import static junit.framework.Assert.assertEquals;
import static okhttp3.internal.Util.UTF_8;

public class BaseTest {

public static final double DELTA = 1E-10;
public static final double LARGE_DELTA = 0.1;
protected static final double DELTA = 1E-10;

public static final String ACCESS_TOKEN = "pk.XXX";
private TestRouteBuilder routeBuilder;
private TestRouteProgressBuilder routeProgressBuilder;

public void compareJson(String json1, String json2) {
JsonParser parser = new JsonParser();
assertEquals(parser.parse(json1), parser.parse(json2));
public BaseTest() {
routeBuilder = new TestRouteBuilder();
routeProgressBuilder = new TestRouteProgressBuilder();
}

protected String loadJsonFixture(String filename) throws IOException {
ClassLoader classLoader = getClass().getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream(filename);
Scanner scanner = new Scanner(inputStream, UTF_8.name()).useDelimiter("\\A");
return scanner.hasNext() ? scanner.next() : "";
return routeBuilder.loadJsonFixture(filename);
}

protected RouteProgress buildRouteProgress(DirectionsRoute route,
double stepDistanceRemaining,
double legDistanceRemaining,
double distanceRemaining,
int stepIndex,
int legIndex) throws Exception {
return routeProgressBuilder.buildTestRouteProgress(
route, stepDistanceRemaining, legDistanceRemaining, distanceRemaining, stepIndex, legIndex
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.mapbox.services.android.navigation.ui.v5;

import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;

import static okhttp3.internal.Util.UTF_8;

class TestRouteBuilder {

String loadJsonFixture(String filename) throws IOException {
ClassLoader classLoader = getClass().getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream(filename);
Scanner scanner = new Scanner(inputStream, UTF_8.name()).useDelimiter("\\A");
return scanner.hasNext() ? scanner.next() : "";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.mapbox.services.android.navigation.ui.v5;

import android.support.v4.util.Pair;

import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.api.directions.v5.models.LegStep;
import com.mapbox.api.directions.v5.models.StepIntersection;
import com.mapbox.geojson.Point;
import com.mapbox.geojson.utils.PolylineUtils;
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;

import java.util.List;

import static com.mapbox.core.constants.Constants.PRECISION_6;
import static com.mapbox.services.android.navigation.v5.navigation.NavigationHelper.createDistancesToIntersections;
import static com.mapbox.services.android.navigation.v5.navigation.NavigationHelper.createIntersectionsList;
import static com.mapbox.services.android.navigation.v5.navigation.NavigationHelper.findCurrentIntersection;
import static com.mapbox.services.android.navigation.v5.navigation.NavigationHelper.findUpcomingIntersection;

class TestRouteProgressBuilder {

RouteProgress buildTestRouteProgress(DirectionsRoute route,
double stepDistanceRemaining,
double legDistanceRemaining,
double distanceRemaining,
int stepIndex,
int legIndex) throws Exception {
List<LegStep> steps = route.legs().get(legIndex).steps();
LegStep currentStep = steps.get(stepIndex);
String currentStepGeometry = currentStep.geometry();
List<Point> currentStepPoints = buildStepPointsFromGeometry(currentStepGeometry);
int upcomingStepIndex = stepIndex + 1;
List<Point> upcomingStepPoints = null;
LegStep upcomingStep = null;
if (upcomingStepIndex < steps.size()) {
upcomingStep = steps.get(upcomingStepIndex);
String upcomingStepGeometry = upcomingStep.geometry();
upcomingStepPoints = buildStepPointsFromGeometry(upcomingStepGeometry);
}
List<StepIntersection> intersections = createIntersectionsList(currentStep, upcomingStep);
List<Pair<StepIntersection, Double>> intersectionDistances = createDistancesToIntersections(
currentStepPoints, intersections
);

double stepDistanceTraveled = currentStep.distance() - stepDistanceRemaining;
StepIntersection currentIntersection = findCurrentIntersection(intersections,
intersectionDistances, stepDistanceTraveled
);
StepIntersection upcomingIntersection = findUpcomingIntersection(
intersections, upcomingStep, currentIntersection
);

return RouteProgress.builder()
.stepDistanceRemaining(stepDistanceRemaining)
.legDistanceRemaining(legDistanceRemaining)
.distanceRemaining(distanceRemaining)
.directionsRoute(route)
.currentStepPoints(currentStepPoints)
.upcomingStepPoints(upcomingStepPoints)
.intersections(intersections)
.currentIntersection(currentIntersection)
.upcomingIntersection(upcomingIntersection)
.intersectionDistancesAlongStep(intersectionDistances)
.stepIndex(stepIndex)
.legIndex(legIndex)
.build();
}

private List<Point> buildStepPointsFromGeometry(String stepGeometry) {
return PolylineUtils.decode(stepGeometry, PRECISION_6);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,50 +10,39 @@
import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.services.android.navigation.BuildConfig;
import com.mapbox.services.android.navigation.ui.v5.BaseTest;
import com.mapbox.services.android.navigation.v5.navigation.camera.RouteInformation;
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

import java.io.IOException;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, manifest = Config.DEFAULT_MANIFEST_NAME)
public class DynamicCameraTest extends BaseTest {

private static final String DIRECTIONS_PRECISION_6 = "directions_v5_precision_6.json";

@Mock
private MapboxMap mapboxMap;

private DynamicCamera cameraEngine;

@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
cameraEngine = new DynamicCamera(mapboxMap);
}

@Test
public void sanity() throws Exception {
MapboxMap mapboxMap = mock(MapboxMap.class);
DynamicCamera cameraEngine = new DynamicCamera(mapboxMap);

assertNotNull(cameraEngine);
}

@Test
public void onInformationFromRoute_engineCreatesCorrectTarget() throws Exception {
MapboxMap mapboxMap = mock(MapboxMap.class);
DynamicCamera cameraEngine = new DynamicCamera(mapboxMap);
RouteInformation routeInformation = RouteInformation.create(buildDirectionsRoute(), null, null);

Point target = cameraEngine.target(routeInformation);

double lng = target.longitude();
assertEquals(-122.416686, lng);
double lat = target.latitude();
Expand All @@ -62,30 +51,46 @@ public void onInformationFromRoute_engineCreatesCorrectTarget() throws Exception

@Test
public void onInformationFromRoute_engineCreatesCorrectZoom() throws Exception {
MapboxMap mapboxMap = mock(MapboxMap.class);
DynamicCamera cameraEngine = new DynamicCamera(mapboxMap);
RouteInformation routeInformation = RouteInformation.create(buildDirectionsRoute(), null, null);

double zoom = cameraEngine.zoom(routeInformation);

assertEquals(15d, zoom);
}

@Test
public void onInformationFromRoute_engineCreatesCorrectTilt() throws Exception {
MapboxMap mapboxMap = mock(MapboxMap.class);
DynamicCamera cameraEngine = new DynamicCamera(mapboxMap);
RouteInformation routeInformation = RouteInformation.create(buildDirectionsRoute(), null, null);

double tilt = cameraEngine.tilt(routeInformation);

assertEquals(50d, tilt);
}

@Test
public void onInformationFromRoute_engineCreatesCorrectBearing() throws Exception {
MapboxMap mapboxMap = mock(MapboxMap.class);
DynamicCamera cameraEngine = new DynamicCamera(mapboxMap);
RouteInformation routeInformation = RouteInformation.create(buildDirectionsRoute(), null, null);

double bearing = cameraEngine.bearing(routeInformation);

assertEquals(-99, Math.round(bearing));
}

@Test
public void onInformationFromLocationAndProgress_engineCreatesCorrectTarget() throws Exception {
MapboxMap mapboxMap = mock(MapboxMap.class);
DynamicCamera cameraEngine = new DynamicCamera(mapboxMap);
RouteInformation routeInformation = RouteInformation.create(null,
buildDefaultLocationUpdate(-77.0339782574523, 38.89993519985637), buildDefaultRouteProgress(null));

Point target = cameraEngine.target(routeInformation);

double lng = target.longitude();
assertEquals(-77.0339782574523, lng);
double lat = target.latitude();
Expand All @@ -94,33 +99,49 @@ public void onInformationFromLocationAndProgress_engineCreatesCorrectTarget() th

@Test
public void onHighDistanceRemaining_engineCreatesCorrectTilt() throws Exception {
MapboxMap mapboxMap = mock(MapboxMap.class);
DynamicCamera cameraEngine = new DynamicCamera(mapboxMap);
RouteInformation routeInformation = RouteInformation.create(null,
buildDefaultLocationUpdate(-77.0339782574523, 38.89993519985637), buildDefaultRouteProgress(1000d));

double tilt = cameraEngine.tilt(routeInformation);

assertEquals(50d, tilt);
}

@Test
public void onMediumDistanceRemaining_engineCreatesCorrectTilt() throws Exception {
MapboxMap mapboxMap = mock(MapboxMap.class);
DynamicCamera cameraEngine = new DynamicCamera(mapboxMap);
RouteInformation routeInformation = RouteInformation.create(null,
buildDefaultLocationUpdate(-77.0339782574523, 38.89993519985637), buildDefaultRouteProgress(200d));

double tilt = cameraEngine.tilt(routeInformation);

assertEquals(40d, tilt);
}

@Test
public void onLowDistanceRemaining_engineCreatesCorrectTilt() throws Exception {
MapboxMap mapboxMap = mock(MapboxMap.class);
DynamicCamera cameraEngine = new DynamicCamera(mapboxMap);
RouteInformation routeInformation = RouteInformation.create(null,
buildDefaultLocationUpdate(-77.0339782574523, 38.89993519985637), buildDefaultRouteProgress(null));

double tilt = cameraEngine.tilt(routeInformation);

assertEquals(35d, tilt);
}

@Test
public void onInformationFromLocationAndProgress_engineCreatesCorrectBearing() throws Exception {
MapboxMap mapboxMap = mock(MapboxMap.class);
DynamicCamera cameraEngine = new DynamicCamera(mapboxMap);
RouteInformation routeInformation = RouteInformation.create(null,
buildDefaultLocationUpdate(-77.0339782574523, 38.89993519985637), buildDefaultRouteProgress(null));

double bearing = cameraEngine.bearing(routeInformation);

assertEquals(100f, bearing, DELTA);
}

Expand All @@ -129,26 +150,20 @@ private Location buildDefaultLocationUpdate(double lng, double lat) {
}

private Location buildLocationUpdate(double lng, double lat, long time) {
Location location = new Location(DynamicCameraTest.class.getSimpleName());
location.setLongitude(lng);
location.setLatitude(lat);
location.setSpeed(30f);
location.setBearing(100f);
location.setAccuracy(10f);
location.setTime(time);
Location location = mock(Location.class);
when(location.getLongitude()).thenReturn(lng);
when(location.getLatitude()).thenReturn(lat);
when(location.getSpeed()).thenReturn(30f);
when(location.getBearing()).thenReturn(100f);
when(location.getAccuracy()).thenReturn(10f);
when(location.getTime()).thenReturn(time);
return location;
}

private RouteProgress buildDefaultRouteProgress(@Nullable Double stepDistanceRemaining) throws Exception {
DirectionsRoute aRoute = buildDirectionsRoute();
return RouteProgress.builder()
.stepDistanceRemaining(stepDistanceRemaining == null ? 100 : stepDistanceRemaining)
.legDistanceRemaining(100)
.distanceRemaining(100)
.directionsRoute(aRoute)
.stepIndex(0)
.legIndex(0)
.build();
double stepDistanceRemainingFinal = stepDistanceRemaining == null ? 100 : stepDistanceRemaining;
return buildRouteProgress(aRoute, stepDistanceRemainingFinal, 0, 0, 0, 0);
}

private DirectionsRoute buildDirectionsRoute() throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import java.util.List;

import static com.mapbox.services.android.navigation.v5.navigation.NavigationHelper.buildSnappedLocation;
import static com.mapbox.services.android.navigation.v5.navigation.NavigationHelper.checkMilestones;
import static com.mapbox.services.android.navigation.v5.navigation.NavigationHelper.isUserOffRoute;
import static com.mapbox.services.android.navigation.v5.navigation.NavigationHelper.shouldCheckFasterRoute;
Expand Down Expand Up @@ -72,18 +73,18 @@ private void handleRequest(final NewLocationModel newLocationModel) {

routeProcessor.checkIncreaseIndex(mapboxNavigation);

RouteProgress previousRouteProgress = routeProcessor.getPreviousRouteProgress();
RouteProgress previousRouteProgress = routeProcessor.getRouteProgress();
final List<Milestone> milestones = checkMilestones(previousRouteProgress, routeProgress, mapboxNavigation);

final Location location = routeProcessor.buildSnappedLocation(mapboxNavigation, snapToRouteEnabled,
final Location location = buildSnappedLocation(mapboxNavigation, snapToRouteEnabled,
rawLocation, routeProgress, userOffRoute);

boolean fasterRouteEnabled = mapboxNavigation.options().enableFasterRouteDetection();
final boolean checkFasterRoute = fasterRouteEnabled && !userOffRoute
&& shouldCheckFasterRoute(newLocationModel, routeProgress);

final RouteProgress finalRouteProgress = routeProgress;
routeProcessor.setPreviousRouteProgress(finalRouteProgress);
routeProcessor.setRouteProgress(finalRouteProgress);

responseHandler.post(new Runnable() {
@Override
Expand Down
Loading

0 comments on commit 2387ad5

Please sign in to comment.