Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DirectionsRoute.builder() issue #42

Open
moiatto opened this issue Jan 19, 2023 · 6 comments
Open

DirectionsRoute.builder() issue #42

moiatto opened this issue Jan 19, 2023 · 6 comments

Comments

@moiatto
Copy link

moiatto commented Jan 19, 2023

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()));
  1. 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();
  1. Create a List of RouteLeg
List<RouteLeg> routeLegs = new ArrayList<>();
                    for (RoadLeg leg: road.mLegs)
                    {
                        RouteLeg routeLeg = RouteLeg.builder()
                                .distance(leg.mLength)
                                .duration(leg.mDuration)
                                .build();

                        routeLegs.add(routeLeg);
                    }
  1. 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
Copy link
Collaborator

boldtrn commented Jan 19, 2023

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
Copy link
Author

moiatto commented Jan 19, 2023

Sure...if I can make it!

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

@moiatto
Copy link
Author

moiatto commented Feb 22, 2023

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
Copy link
Collaborator

boldtrn commented Feb 27, 2023

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

@moiatto
Copy link
Author

moiatto commented Feb 27, 2023

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
Copy link
Author

moiatto commented Feb 27, 2023

Try and let me know

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants