maplibre / maplibre-navigation-android

Maplibre Navigation SDK for Android
MIT License
96 stars 53 forks source link

DirectionsRoute.builder() issue #42

Open moiatto opened 1 year ago

moiatto commented 1 year ago

I'm using OSMDroid server to get routes.

Then, I convert the obtained OSMDroid route class in DirectionRoute class with the DirectionsRoute.builder():

Road road; // Route obtained from OSMDroid server

  1. Covert the list of OSMDroid points in List:
    
    List<Point> pointsFromResponse = new ArrayList<>();
    ArrayList<org.osmdroid.util.GeoPoint> points;

points = road.mRouteHigh; for (org.osmdroid.util.GeoPoint point : points) pointsFromResponse.add(Point.fromLngLat(point.getLongitude(), point.getLatitude()));


2. Create a RouteOptions class with the builder():

RouteOptions routeOptions = RouteOptions.builder() .geometries(DirectionsCriteria.GEOMETRY_POLYLINE6) .profile(DirectionsCriteria.PROFILE_DRIVING) .accessToken(accessToken) .user(userAgent) .requestUuid("c945b0b4-9764-11ed-a8fc-0242ac120002") // fake UUID ver.1 .baseUrl("www.fakeurl.com") // fake url .coordinates(pointsFromResponse) .voiceInstructions(true) .bannerInstructions(true) .build();


3. Create a List of RouteLeg

List routeLegs = new ArrayList<>(); for (RoadLeg leg: road.mLegs) { RouteLeg routeLeg = RouteLeg.builder() .distance(leg.mLength) .duration(leg.mDuration) .build();

                    routeLegs.add(routeLeg);
                }

4. Finally, create the DirectionRoute:

route = DirectionsRoute.builder() .legs(routeLegs) .geometry(PolylineEncoder.encode(roads.mRouteHigh, 1)). // from OSMDroid class .weightName("auto") .weight(1.0) // I didn't understand what it is, so I assign this value. Can you help me? .distance(roads[0].mLength * 1000) .duration(roads[0].mDuration) .routeOptions(routeOptions) .build();


The issue came when I call:
`navigation.startNavigation(route);`

There is an issue in **NavigationRouteProcessor.java**  class, because I obtain this error **but the List of RouteLeg is never null and size is 1 (minimum).**

FATAL EXCEPTION: mapbox_navigation_thread Process: com.speedox.myride, PID: 2528 java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference at com.mapbox.services.android.navigation.v5.navigation.NavigationRouteProcessor.processNewIndex(NavigationRouteProcessor.java:198) at com.mapbox.services.android.navigation.v5.navigation.NavigationRouteProcessor.createFirstIndices(NavigationRouteProcessor.java:182) at com.mapbox.services.android.navigation.v5.navigation.NavigationRouteProcessor.checkNewRoute(NavigationRouteProcessor.java:125) at com.mapbox.services.android.navigation.v5.navigation.NavigationRouteProcessor.buildNewRouteProgress(NavigationRouteProcessor.java:87) at com.mapbox.services.android.navigation.v5.navigation.RouteProcessorHandlerCallback.handleRequest(RouteProcessorHandlerCallback.java:49) at com.mapbox.services.android.navigation.v5.navigation.RouteProcessorHandlerCallback.handleMessage(RouteProcessorHandlerCallback.java:33) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:246) at android.os.HandlerThread.run(HandlerThread.java:67)

boldtrn commented 1 year ago

Your code does not look correct. You will need a lot more data in the RouteLeg, you need to build Steps, Maneuvers, Instructions, etc.

I would recommend to check the content that Mapbox or OSRM provide and go from there.

If you have a working solution for OSMDroid, a PR would be welcome so we can add support for different routing providers (it needs to integrate well with the current code though :)).

moiatto commented 1 year ago

Sure...if I can make it!

I need to understand the minimum data needed to make navigation work and then add the extras.

moiatto commented 1 year ago

Your code does not look correct. You will need a lot more data in the RouteLeg, you need to build Steps, Maneuvers, Instructions, etc.

I would recommend to check the content that Mapbox or OSRM provide and go from there.

If you have a working solution for OSMDroid, a PR would be welcome so we can add support for different routing providers (it needs to integrate well with the current code though :)).

the information received by OSMDroid is much less than that received by MapBox. I managed to get it to work, but a lot of information is missing

boldtrn commented 1 year ago

If this is something you would like to contribute, I think a PR would be welcome 👍

moiatto commented 1 year ago

Add these dependencies in build.gradle:

// OSMdroid (for Geocoding & Routing features)
implementation 'org.osmdroid:osmdroid-android:6.1.14'  // OSMdroid https://github.com/osmdroid/osmdroid
implementation 'com.github.MKergall:osmbonuspack:6.9.0'  // OSMBonusPack https://github.com/MKergall/osmbonuspack

declare as global:

private DirectionsRoute route;   // MapLibre
private Road[] roads = null;       // OSMBonusPack 

then:

org.osmdroid.util.GeoPoint sPoint;
org.osmdroid.util.GeoPoint ePoint;
ArrayList<org.osmdroid.util.GeoPoint> vPoints = new ArrayList<>();
ArrayList<org.osmdroid.util.GeoPoint> wayPoints = new ArrayList<>();

sPoint = new org.osmdroid.util.GeoPoint(locationGps.getLatitude(), locationGps.getLongitude());
ePoint = new org.osmdroid.util.GeoPoint(destinationPoint.getLatitude(), destinationPoint.getLongitude());

// ....fill array vPoints with ViaPoints (if there are)

wayPoints.add(sPoint);
//add intermediate via points:
wayPoints.addAll(vPoints);
//add destination point:
wayPoints.add(ePoint);

ExecutorService executor = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());

executor.execute(() -> {
    //Background work here

    // OSMR route provider
    RoadManager roadManager = new OSRMRoadManager(requireContext(), userAgent);
    roads = roadManager.getRoads(wayPoints);

    if (roads[0].mStatus == STATUS_OK) route = convertOsrmRoadToMapLibreRoute(roads[0]);

    handler.post(() -> {
        //UI Thread work here

        if (roads[0].mStatus == STATUS_OK)
        {
            startNavigation(route);
        }
        // STATUS_INVALID
        // STATUS_TECHNICAL_ISSUE
        else {
            // MANAGE EXCEPTIONS
        }
    });
});
private DirectionsRoute convertOsrmRoadToMapLibreRoute(Road road)
{
    List<Point> routePoints = new ArrayList<>();
    ArrayList<org.osmdroid.util.GeoPoint> OsrmPoints;

    // Convert list of Points
    OsrmPoints = road.mRouteHigh;
    for (org.osmdroid.util.GeoPoint point : OsrmPoints) {
        routePoints.add(Point.fromLngLat(point.getLongitude(), point.getLatitude()));
    }

    // BUILD RouteOptions
    RouteOptions routeOptions = RouteOptions.builder()
            .geometries(DirectionsCriteria.GEOMETRY_POLYLINE6)
            .profile(DirectionsCriteria.PROFILE_DRIVING)
            .accessToken("pk.0")                                    // fake AccessToken
            .user(userAgent)
            .requestUuid("c945b0b4-9764-11ed-a8fc-0242ac120002")    // fake UUID ver.1
            .baseUrl("www.fakeUrl.com")                             // fake url
            .coordinates(routePoints)
            .voiceInstructions(true)
            .bannerInstructions(true)
            .build();

    // BUILD RouteLegs
    List<RouteLeg> routeLegs = new ArrayList<>();
    for (RoadLeg leg: road.mLegs)
    {
        // BUILD LegSteps
        int indexEndNode;
        List<org.osmdroid.util.GeoPoint> roadPoints = new ArrayList<>(road.mRouteHigh);
        List<LegStep> legSteps = new ArrayList<>();
        for (RoadNode roadNode: road.mNodes)
        {
            // GEOMETRY of LegStep
            indexEndNode = 0;
            for (int i = 0; i < roadPoints.size(); i++) {
                if (CompareIfTwoGeoPointsAreEquals(roadPoints.get(i), roadNode.mLocation)) {
                    indexEndNode = I;
                    break;
                }
            }
            ArrayList<org.osmdroid.util.GeoPoint> legPoints = new ArrayList<>();
            for (int i = 0; i <= indexEndNode ; I++)
                legPoints.add(roadPoints.get(i));
            roadPoints.subList(0, indexEndNode + 1).clear();
            // End GEOMETRY of LegStep

            double[] rawLocation = {roadNode.mLocation.getLongitude(), roadNode.mLocation.getLatitude()};

            List<StepIntersection> stepIntersections = new ArrayList<>();
            StepIntersection stepIntersection = StepIntersection.builder()      // No other OSM data for this
                                                .rawLocation(rawLocation)
                                                .build();
            stepIntersections.add(stepIntersection);

            LegStep legStep = LegStep.builder()
                    .distance(roadNode.mLength * 1000)
                    .duration(roadNode.mDuration)
                    .weight(1.0)
                    .mode("auto")
                    .intersections(stepIntersections)
                    .geometry(PolylineEncoder.encode(legPoints,1))
                    .maneuver(StepManeuver.builder()                    // No all OSM data for this
                                            .instruction(roadNode.mInstructions)
                                            .rawLocation(rawLocation)
                                            .bearingBefore(0.0)         // No OSM data for this
                                            .bearingAfter(0.0)          // No OSM data for this
                                            .build())
                    .build();

            legSteps.add(legStep);
        }

        RouteLeg routeLeg = RouteLeg.builder()
            .distance(leg.mLength)
            .duration(leg.mDuration)
            .steps(legSteps)
            .build();

        routeLegs.add(routeLeg);
    }

    // Build DirectionsRoute
    return DirectionsRoute.builder()
            .legs(routeLegs)
            .geometry(PolylineEncoder.encode(road.mRouteHigh,1))
            .weightName("auto")
            .weight(1.0)
            .distance(road.mLength * 1000)
            .duration(road.mDuration)
            .routeOptions(routeOptions)
            .build();
}
moiatto commented 1 year ago

Try and let me know