How do I achieve turn by turn navigation on AI?

I'm relatively new to App Inventor and I'm looking for a method to obtain turn by turn pedestrian navigation for a project I'm working on.
For now, I'm content with obtaining the route between two fixed locations. Could anybody suggest a method by which I can achieve this?

1 Like

This is a very simple method @nityabaskar

Use an ActivityStarter and intents to open Google’s Navigator app. This link provides basic information https://groups.google.com/forum/#!msg/mitappinventortest/3d7bFyGM508/pNsqAb9hBQAJ

The link also provides more advanced options to provide route information too. This advice HOW TO use the new Map Control to plot a route on a map and post driving distance and time for that path. is useful too.

Again a different way is OpenStreetMap without the Map Component

And if you are experienced with JSON and willing to get a Google Map API, you can use the Google Directions API.

Is this what you want to do?

Regards,
Steve

Hi SteveJG,

Thanks for your prompt response. I fear I might not have been too clear with my request, my apologies for the same.

I am trying to provide vibrations controlled by a microcontroller when a user approaches an upcoming turn while walking to their destination.
I understand using the Google Maps Directions API will give me exactly what I want. But how might I incorporate this into my app and furthermore, how can I display these directions on my app.

My UI is fairly simple, the user need only to enter their destination and confirm.

Thanks!

What you hope to do is very complex and difficult; even for an expert App Inventor coder.

Here is what you need to do:

1 -Use the Google Directions API.

2- Use of the Directions API is not free, it incurs a charge. Developers get nominal free usage when they:

notFREE

3 - request the directions using a URL that looks like this:
https://maps.googleapis.com/maps/api/directions/json?origin=Disneyland&destination=Universal+Studios+Hollywood&key=YOUR_API_KEY
Sorry, this specific set of directions will not work unless you provide your Google Developer api key. You have to obtain and use your own api key.

If it were to work, you would receive a JSON response that looks like this:
{
"geocoded_waypoints" : [
{
"geocoder_status" : "OK",
"place_id" : "ChIJRVY_etDX3IARGYLVpoq7f68",
"types" : [
"bus_station",
"transit_station",
"point_of_interest",
"establishment"
]
},
{
"geocoder_status" : "OK",
"partial_match" : true,
"place_id" : "ChIJp2Mn4E2-woARQS2FILlxUzk",
"types" : [ "route" ]
}
],
"routes" : [
{
"bounds" : {
"northeast" : {
"lat" : 34.1330949,
"lng" : -117.9143879
},
"southwest" : {
"lat" : 33.8068768,
"lng" : -118.3527671
}
},
"copyrights" : "Map data ©2016 Google",
"legs" : [
{
"distance" : {
"text" : "35.9 mi",
"value" : 57824
},
"duration" : {
"text" : "51 mins",
"value" : 3062
},
"end_address" : "Universal Studios Blvd, Los Angeles, CA 90068, USA",
"end_location" : {
"lat" : 34.1330949,
"lng" : -118.3524442
},
"start_address" : "Disneyland (Harbor Blvd.), S Harbor Blvd, Anaheim, CA 92802, USA",
"start_location" : {
"lat" : 33.8098177,
"lng" : -117.9154353
},

4 - decode the JSON text using the Web component .

When decoded (for a walking route), the JSON script would be decoded to
provide information like this (depending on how you choose to display the directions in YOUR app) (these directions were provided using a browser an typing " directions from Disneyland to Universal Studios ", then clicking on the blue Directions icon, the selecting a route. Why? Because this is what the api would provide.

disneyDirections

That's all you need to do. :cry: Here is a kind of summary that explains how you can customize this information. The link provides a complete JSON script . Use that example to parse a typical JSON response to see what is involved before you get your api key.

You also asked 'But how might I incorporate this into my app'. That is impossible to answer without seeing what you have coded so far 'to provide vibrations controlled by a microcontroller when a user approaches an upcoming turn while walking to their destination'. That might be very difficult establishing the communications between the microcontroller (possibly using bluetooth?) and coordinating it with the user's current geocoordinates (provided by the GPS receiver and the LocationSensor perhaps).

Your 'UI is fairly simple, the user need only to enter their destination and confirm', but the code to make it happen is fairly complex.

Start coding. When you have a specific question, ask again and someone probably will provide specific advice Nity.

Regards,
Steve

Hi SteveJG,

I couldn’t thank you enough for taking the time out to explain this to me. I appreciate the effort!
As per your advice, I shall begin working on the application and see how it all pans out.

Thanks once again!

Hi Steve !

I read multiple topics in which you indicated how to implement navigation on app inventor but there's something I can not figure out.

My question is the following:

We succeeded the implementation of the navigation between origin and destination and we can display directions between those 2 points (turn by turn).

Now we want to compare the current location of the bike and its position on the trajectory so it could send a binary number to our hardware code (resulting on a vibration). Do you know how we could compare the current position of the bike and the position of each turn of a given trajectory ?

I don't know If I made myself clear haha,
Regards,
Notch

@Snotch This discussion might provide some ideas; it shows how determine if you are at or near a particular location (coordinates) Location sensor (ringed fence / circular ringed fence)

The Navigate directions does not provide the coordinates of each turn (or direction advice). Navigation documents what you can access. There is no magic way to determine the position of each turn. That information is known by the ORS but cannot be exposed using the Navigate tool. Edit: see Evan's post, some of the information required to calculate the positions (coordinates of each turn) is awkwardly available.

A way to determine what these points might be could be to plot the route on a Map and manually use the Map.TapAtPoint (latitude, longitude) to pre determine the location where a change and directions occurs per the ORS directions. Save that information to a file and use the advice to determine a circular fence or calculate the distance to that point (when the distance is approaching 0, you are almost there). Yes, awkward. In reality, unless you monitor Accuracy (you can't be certain you are really there or are 50 meters away). Why? Because the GPS hardware can't guarantee the Accuracy is a low number) - the gps doesn't know where you really are; it only knows where you are with a statistical certainty (uncertainty).

That tells you where you are w.r.t. the turning points.

.

See post #4 regarding the Google Directions API. A significantly better option if you require reliable directions.

  • The Directions api exposes the coordinates of the turns (what you have to have). See the post above.

Navigate is a nice toy; its directions reliability is about the same (or worse) as Google's database was several years ago when following directions blindly could end you up in a lake or and empty field rather than your destination. ORS directions (Navigate) saving grace is it is free.

1 Like

Actually, this is not true. I specifically implemented the ResponseContent property that returns the GeoJSON response of the service as a JSON dictionary. ORS returns information about list of steps and each step structure contains the text of the step and the indices of the waypoints that indicate the segment associated with that step. For each step, you could extract the end waypoint index and use that to look up the lat/long in the points list, e.g.:

{
  "type":"FeatureCollection",
  "features":[{
    "bbox":[8.681436,49.41461,8.690123,49.420514],
    "type":"Feature",
    "properties":{
      "segments":[{
        "distance":887.8,
        "duration":189,
        "steps":[{
          "distance":312.6,
          "duration":75,
          "type":11,
          "instruction":"Head north on Wielandtstraße",
          "name":"Wielandtstraße",
          "way_points":[0,10]
        },{
          "distance":251.1,
          "duration":36.2,
          "type":1,
          "instruction":"Turn right onto Mönchhofstraße",
          "name":"Mönchhofstraße",
          "way_points":[10,21]
        },{
          "distance":212.2,
          "duration":50.9,
          "type":2,
          "instruction":"Turn sharp left onto Keplerstraße",
          "name":"Keplerstraße",
          "way_points":[21,24]
        },
        // truncated for example
        {"distance":0,
          "duration":0,
          "type":10,
          "instruction":
          "Arrive at Roonstraße, straight ahead",
          "name":"-",
          "way_points":[42,42]
        }]
      }],
      "summary":{"distance":1369,"duration":292},
      "way_points":[0,28,42]
    },
   "geometry":{
     "coordinates":[[8.681496,49.41461],[8.68149,49.414711],[8.681441,49.415655],[8.681436,49.415747],[8.681455,49.415835],[8.681509,49.416087],[8.681642,49.416498],[8.681671,49.416588],[8.681701,49.416684],[8.681875,49.417287],[8.68189,49.417394],[8.682045,49.41739],[8.682107,49.41739],[8.682461,49.417389],[8.682563,49.417388],[8.682676,49.417387],[8.682782,49.417388],[8.683371,49.417368],[8.683592,49.41736],[8.683763,49.417362],[8.685222,49.417366],[8.685359,49.417364],[8.685342,49.417411],[8.685024,49.419178],[8.68501,49.419258],[8.685156,49.419273],[8.686408,49.419402],[8.68651,49.419413],[8.686506,49.41943],[8.68651,49.419413],[8.686617,49.419425],[8.686983,49.419461],[8.687101,49.419473],[8.687212,49.419486],[8.688301,49.419619],[8.688398,49.41963],[8.690104,49.419828],[8.690123,49.419833],[8.689854,49.420216],[8.689652,49.420514],[8.68963,49.42051],[8.688601,49.420393],[8.687872,49.420318]],
      "type":"LineString"
    }
  }],
  "bbox":[8.681436,49.41461,8.690123,49.420514],
  "metadata":{
    "attribution":"openrouteservice.org | OpenStreetMap contributors",
    "service":"routing",
    "timestamp":1610476952151,
    "query":{
      "coordinates":[[8.681495,49.41461],[8.686507,49.41943],[8.687872,49.420318]],
      "profile":"driving-car",
      "format":"geojson"
    },
    "engine":{
      "version":"6.3.1",
      "build_date":"2020-12-10T15:35:43Z",
      "graph_date":"1970-01-01T00:00:00Z"
    }
  }
}

Note that the waypoint numbers are 0-indexed whereas lists in App Inventor are 1-based, so you will need to add 1 to each waypoint index of interest to get the corresponding point in the coordinates array.

1 Like

Ok nice to know. Not obviously mentioned in documentation (

ResponseContent The raw response from the server. This can be used to access more details beyond what the GotDirections event provides.) and not terribly useful because the ORS directions themselves are insufficient and unreliable in my experience. The process to extract individual coordinates is convoluted and awkward. You may want to include your more detailed explanation in the documentation.

The difference between the Google api and ORS is the difference between a Cadillac and a bicycle.

Hi,

Thank you for your help. I didn't really understand how can I include the ResponseContent to my code. Knowing that I can display the directions of a given route from a point A to a point B using the portion of code in my screenshot below. Where do I put the ResponseContent or do I have to implement a complete different block.

You said that I had to extract the end waypoints to get the latitude/longitude of each turn but how can I extract it ?

Thank you in advance for your answer !

If I can't implement it I'll turn to @SteveJG's solution :slight_smile:

Here's an example project that you could build from. When the location sensor gets a new location it compares it to the end point of the current segment. If the location is within 20 meters it will move to the next step. Things like "rerouting" if someone takes different directions than what is provided by the server are not implemented. Another thing you'd want to consider is handling if the location sensor doesn't give a value for a while, causing a skip of a step.

NavigationTest.aia (5.6 KB)

1 Like

Is there a way to check if the actual position is on the route segment within a range (to take care of the GPS accuracy problem) so that if it is outside is possible to fire the rerouting function?

Read about Accuracy in Using the Location Sensor .

Read about Programming Your App to Make Decisions .

Using an If..then filter will provide you with a methodology to allow the app to decide what to do depending on the Accuracy of the satellite fix and experiment. When you filter the location geocoordinates stream by eliminating high value Accuracy numbers (GPS accuracy problems) you will drop the use of a data point ( that may or may not be an issue with respect to repositioning).

What have you tried? Be the first to try your proposed Project, share the code and let us know. Check if the actual position is on the route segment possibly. You shouldn't really bother because when you use the rerouting function you will get a plot of where the USER is now. You might save coordinates continuously and post the last usable coordinate so you could to show where the USER went 'off the route'.

Have fun with an exciting coding and mental exercise and you can tell the community whether the above logic (or any logic) actually will work.