Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use GoogleMap or MapBox Direction API implement my own navigation in my app

I'd like to implement navigation map for drivers in my Android app. I don't want to use URL scheme to open google Maps app to navigate it. I prefer to implement this navigation function inside my app like what Google Map does.

My requirements is pretty simple. Navigate user from PlaceA to PlaceB.

After I read the documents from google and MapBox website. there are directions api for user to get all the information like routes.

1 GoogleMap Direction API: https://developers.google.com/maps/documentation/directions/intro?hl=en

2 MapBox Direction API: https://www.mapbox.com/developers/api/directions/

My question are below: 1 How do I know when is the proper time to prompt user he should turn right/left? 2 How do I know how far away from my current location to next maneuver/Steps? Do I need to recalculate the distance after my location is changed since my location is always changing? 3 How do I know user has made a wrong action? For example, it is supposed to turn right, but user turned left. I need to request your server to recalculate the route.

Any suggestion? Thanks in advance.

like image 655
user3034559 Avatar asked Jan 07 '16 19:01

user3034559


Video Answer


1 Answers

I'll answer your questions below as if you're using the new Android Mapbox Directions API.

1. How do I know when is the proper time to prompt user he should turn right/left?

First, as you may know, you must call .setSteps(true) within your MapboxDirections.Builder(). This will return directions with all the information you will need. Now in order to prompt user the step at a correct location you will need to get the step maneuver coordinates which are given in a list. This is the absolute coordinate in which a step occurs therefore, it will be rare that a user actually maneuvers through the point while traversing the route. Therefore it's best to measure distance from user location to the next steps coordinate and if the user is within a given distance (say 0.0189394 miles which is ~100 feet) you then prompt user the next step. To measure distance I'll give a reliable method below you can use:

private double computeDistance(Waypoint from, Waypoint to) {
    double dLat = Math.toRadians(to.getLatitude() - from.getLatitude());
    double dLon = Math.toRadians(to.getLongitude() - from.getLongitude());
    double lat1 = Math.toRadians(from.getLatitude());
    double lat2 = Math.toRadians(to.getLatitude());

    double a = Math.pow(Math.sin(dLat/2), 2) + Math.pow(Math.sin(dLon/2), 2) * Math.cos(lat1) * Math.cos(lat2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

    double R = 3960;

    double distance = R * c;
    return distance;
}

Using this method you just compare the distance returned (in miles) to your threshold (in our example 0.0189394 miles) and if distance returned is less then threshold we know the users within range of the next step.

2. How do I know how far away from my current location to next maneuver/Steps? Do I need to recalculate the distance after my location is changed since my location is always changing?

The first part of your question's answered in question 1. To answer the second part, You can call mapView.setOnMyLocationChangeListener and make a new MapView.OnMyLocationChangeListener(). Within it is where you'd need to recalculate the distance between user and next steps coordinates like in the example in question 1.

3. How do I know user has made a wrong action? For example, it is supposed to turn right, but user turned left. I need to request your server to recalculate the route.

You can accomplish this by using the isOffRoute() method which will calculate the distance between the provided userLocation and every waypoint in the route, resulting in an off-route status if the distance is always bigger then a threshold (currently 0.1 miles). So in your case, since you want to recalculate a new route if user veers off route i'd create an if statement similar to this example:

if (route.isOffRoute(userLocation)) {
    Toast.makeText(this, "You are off-route.", Toast.LENGTH_SHORT).show();
}

Instead of displaying a message the the user, I'd request a new route. It's important to note that there is currently a bug within the method that will be fixed in version 1.1 and will also allow you to set the threshold yourself. I'll try and update this answer once it gets released and the bug is fixed.

I hope I answered all your questions and feel free to ask questions below and i'll answer them as quick as possible.

like image 185
cammace Avatar answered Sep 20 '22 05:09

cammace