4

My app shows the tracking history of the vehicle on Google Map. We receive the location from our mobile app every 2 mins and store it do DB. After that we show the route (using JS API, Directions Service) on the map.

{
  origin: 'Chicago, IL',
  destination: 'Los Angeles, CA',
  waypoints: [
    ...
     ],
  provideRouteAlternatives: false,
  travelMode: 'DRIVING',
  unitSystem: google.maps.UnitSystem.IMPERIAL
}

However, sometimes location can be inaccurate for only 3-5 meters. As an example some location can be shown on the line of oncoming trafic. As a result, Google creates the route around couple blocks etc. enter image description here

So the question: is there any possible way to ignore such inaccurate points and just "force" Google to create the route in one direction?

Thanks!

VitalyZ
  • 161
  • 1
  • 6
Stas P.
  • 191
  • 6
  • I believe for asset tracking purposes the [Roads API](https://developers.google.com/maps/documentation/roads/intro) might be more suitable than Directions API. However, the snapping algorithm used in Roads API supposes that GPS points are quite close (less than 400 m). With 2 minute interval I afraid the points will be sparse and interpolation algorithm won't work well. – xomena Jul 22 '17 at 11:15
  • Seems it should help. I'll try. As I understand I can use this API in addition to Directions API. So I can "correct" the points with Roads API and draw the route with Directions API. – Stas P. Jul 25 '17 at 10:10
  • Didn't help :( Seems it works well only for the cases when points are too close for each other. In my case there are possible 2-10 miles between two points. – Stas P. Aug 22 '17 at 09:01

1 Answers1

0

I had an idea. It looks like it works, at least for the waypoints that I picked on a similar situation.

I put the legs (= route segments between waypoints) in a for-loop. For each segment I calculate/read the "distance along the route" and divide that by the flightpath distance. This ratio should be about 1. If it's much more than 1, something's rong. I set the threshold on 2.0, you should probably lower it (guestimate a value between 1 and 2).

When such a factor is found, I remove that waypoint (well, I make a new array "newWaypoints" without this item), and start again, this produces a red route, after a 2 second setTimeout.

The function is recursive, I don't know what happens with multiple points that should be removed. Maybe it might try again more than once.

<style>
  #map {height: 400px;}
</style>
<div id="map"></div>
<div id="log"></div>
<input type="button" value="click" onclick="calc()">
<script>
var directionsDisplay;
var directionsService;
var map;
var maxFactor = 2.0;    // FEEL FREE TO GUESTIMATE ANOTHER VALUE
function initMap() {
  var start = new google.maps.LatLng(50.96622130043278,3.8518730520809185);
  var mapOptions = {
    zoom:7,
    center: start
  }
  map = new google.maps.Map(document.getElementById('map'), mapOptions);
  directionsService = new google.maps.DirectionsService();
}
function calcRoute(start, end, waypoints, color) {
  directionsDisplay = new google.maps.DirectionsRenderer({ map: map, polylineOptions: {strokeColor: color} });
  var request = {
    origin: start,
    destination: end,
    waypoints: waypoints,
    provideRouteAlternatives: false,
    travelMode: 'DRIVING',
    unitSystem: google.maps.UnitSystem.IMPERIAL
  };
  directionsService.route(request, function(result, status) {
    if (status == 'OK') {
      var newWaypoints = [];

      directionsDisplay.setDirections(result);
      var legs = result.routes[0].legs;
      var problemIndex = -1;
      for(var i in legs) {
        var routeSegment = legs[i].distance.value;
        var origin = legs[i].start_location;
        var destination = legs[i].end_location;
        var flightpathDistance = google.maps.geometry.spherical.computeDistanceBetween(origin, destination);
        var factor = (routeSegment / flightpathDistance);
        if(factor > maxFactor && problemIndex == -1) {
          // too long
          problemIndex = i;
          document.getElementById('log').innerHTML += 'factor ' + factor.toFixed(2) + ' - segment looks too long. romove waypoint ' + i + ' (0 based)<br/>'; 
        }
        else if(factor > maxFactor && problemIndex == i -1) {
          if(i<legs.length - 1) {  // skip the destination; this is not a waypoint
            newWaypoints.push(waypoints[i]);
          }
          document.getElementById('log').innerHTML += 'factor ' + factor.toFixed(2) + ' - segment also too long, but the problem is probably the previous segment<br/>'; 
        }
        else {
          if(i<legs.length - 1) {  // skip the destination; this is not a waypoint
            newWaypoints.push(waypoints[i]);
          }
          document.getElementById('log').innerHTML += 'factor ' + factor.toFixed(2) + '<br/>';
        }
      }
      document.getElementById('log').innerHTML += '<hr/>';
      if(problemIndex > -1) {
        setTimeout(function() {
          calcRoute(start, end, newWaypoints, 'red');
        }, 2000);

      }
    }
  });      
}
function calc() {
  calcRoute(
    '50.95487921891042,3.879781222422025', 
    '51.002379049703315,3.757394492495223',
    [
      {location: '50.96622130043278,3.8518730520809185', stopover: true},
      {location: '50.9725522849737,3.8379914402503345', stopover: true},
      {location: '50.97957292616706,3.8236401199901593', stopover: true},  // This is the problem point, on the opposite side of the road
      {location: '50.98570531465853,3.81125807762146', stopover: true},
      {location: '50.98941308813775,3.8019619700935436', stopover: true}
    ],
    "blue"
  );
}
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap&libraries=geometry"></script>
Emmanuel Delay
  • 3,619
  • 1
  • 11
  • 17
  • As I understand, it will help only in the case when the "incorrect" leg makes the "circle". However, what about the case when wrong leg looks like normal according to "factor" but in incorrect direction? – Stas P. Jul 21 '17 at 11:56
  • Have you tried it out? Could you give a set of coordinates that show the problem (not the big loop, but a more subtle error); so I have something to aim for. I'll see if I can think of a better technique – Emmanuel Delay Jul 24 '17 at 09:22
  • I haven't tried it. I worry that it will filter a lot of usefull points. For example: [link](https://drive.google.com/file/d/0B4S1jDDwoSdhdVVQZWJBdWJrOE0/view?usp=sharing) – Stas P. Jul 25 '17 at 10:08