/ accuracy

Building blocks for a great tracking experience

A great tracking experience is critical for consumer ordering apps with time-sensitive delivery. Consumers get anxious when waiting for their orders to arrive. Think of the cab to take you home food to quench your hunger or a plumber to fix the leak. Live location tracking is a great way to relieve this anxiety and differentiate your product experience.

Hundreds of apps have built such tracking experiences with HyperTrack. Hundreds of other developers have built it themselves using a range of APIs and open source libraries before HyperTrack existed. We have spoken with these developers who built tracking experiences of popular apps. In this post we share a common implementation resulting issues in real world usage and ways to solve them.

Common implementation

Implementing a live location tracking experience involves the rider app (which is being tracked) the server and the consumer app (which is tracking). The example implementation uses Swift APIs on iOS to illustrate a common implementation.

Rider app

  1. Get location data using the iOS or Android APIs to record location changes. In order to do that minimum distance and desired accuracy are two parameters that need to be specified.
let locationManager = CLLocationManager()
locationManager.filterDistance = 30.0
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startMonitoringSignificantLocationChanges()
  1. Receive location in delegate callbacks every time the user moves more than the minimum displacement. Then send the data to the server via an HTTP request.
func locationManager(_ manager: CLLocationManager
  didUpdateLocations locations: [CLLocation]) {

    // Post locations via HTTP POST request.
    // Our tip: ensure you are using gzip!
    // Request payload has location coordinates and timestamps

}

On the server

  1. Once you get locations on the server save them to your database with timestamps to link them with business context.

  2. Sanitize these locations using snap-to-road APIs from your favorite map provider.

  3. Further use route ETA APIs by the map provider to estimate arrival time under current traffic conditions.

These locations are now ready to be sent to the consumer app to visualize on a map fragment.

Consumer app

  1. The consumer app can now fetch locations from the server when the consumer is ready to track the order.

  2. Now that you are ready to visualize set up a map view using a framework like iOS MapKit.

self.mapView = MKMapView() mapView.mapType = MKMapType.standard
  1. Now annotate the map with markers that show the rider location and order destination.
let marker = MKPointAnnotation() self.mapView.addAnnotation(marker)
  1. Then pass location coordinates to the method to animate over it and update the live marker.
func animateMarker(locations: [CLLocationCoordinate2D]
                currentIndex: Int
                    duration: TimeInterval) {

    UIView.animate(withDuration: duration
                      animations: {marker.coordinate = currentLocation}
                      completion: {
        // Recursive call to parent method with next index
        self.animateMarker(coordinates currentIndex: currentIndex + 1 duration: duration) 
    }
}
  1. In order to beautify this visualization you may automatically pan and zoom the map as the locations are animated.
mapView.setVisibleMapRect(annotationsRect edgePadding: insets animated: true)

Issues in real world usage

A real-time location tracking experience needs multiple platforms to dance to the same beat. We have observed some common issues and outlined our solutions for them.

IssuesOur solution
Rider: High battery drainDecouple collection and transmission frequency
Server: Noisy locationsKinematics signal processing snap-to-road activity detection
Server: Map API costsState management of device health activity use case
Server: Data explosion at scaleAbstractions to store compressed location data with context
Consumer: High latencyServer controlled frequency of collection and transmission
Consumer: Poor visual experienceInterpolator and animation libraries

Some of these issues are inter-related. For example battery drain and latency are inversely related—low latency in the consumer view implies high battery drain. In another example filtering of noisy locations is better with accurate activity detection while also reducing map API costs.

Issue: Rider battery and consumer latency

We discovered a 5-10x difference between the battery consumption of collecting location (lower) and transmitting it. This insight may be used to improve battery efficiency by an order of magnitude if you transmit location data only when you need it viz. when the consumer is actively tracking the order.

Our implementation enables a low latency experience for the consumer with low battery drain for the rider. This is achieved through (a) a two-way communication between device and server (b) de-coupling the collection and transmission frequency (c) tuning the frequency based on business context. Since the consumption of tracking is sparse we are able to achieve real-time tracking with near-zero battery consumption.

Issue: Noisy locations

Location data from the rider is noisy and animating the raw data creates an unpleasant experience for the consumer. For consumers looking to relieve their anxiety with the tracking experience bad accuracy will often do the opposite by creating false alarms.

We use a combination of techniques to improve location accuracy—kinematic equations signal processing filters and snap-to-road on mapping data. Read more about our real-time noise filtering. In addition we use smartphone sensors to determine activity—stop walk cycle drive etc. Filters are applied based on the activity for which location is collected. For example a walk may not be snapped to road and a stop may filter out stray WiFi locations that are received with high accuracy outside the distance threshold.

Issue: Map API costs

Map providers have APIs to get ETA with real-time traffic and snap-to-road to improve accuracy. These are priced per API call and developers often need to call them many times during the course of an order. For example the Google Maps ETAs API call is priced at 50 cents for 1000 calls. Therefore a 60 minute period of tracking the pickup and delivery of an order can cost you 6 cents if the ETA is updated twice a minute. The Roads API is priced similarly and has a limit of 50 requests per second making it unusable at scale.

In order to avoid these developers build their own ETA model to recalibrate and trigger real-time alerts for other workflows. This requires state management of activity data and device health to understand granular changes. For example detecting unexpected stops on the road are handy for ETA estimations. In another example if the user disables location the ETA prediction needs to catch and correct for it.

Issue: Data explosion at scale

Location data explodes an order of magnitude faster than your business. Every order generates thousands of location data rows. To store and retrieve location data is easy but to do so in the context of business events and actions is non-trivial. We have seen success in compressing locations in a custom data format—the time aware polyline. A time aware polyline accompanies each activity segment in the life of the user along with device health events like disabled locations and network unavailable. Additionally an order may be segmented as a pickup followed by a delivery (or multiple pickups interleaved with multiple deliveries) while still being associated with each other through an order ID.

var polylineUtil = require('time-aware-polyline') var points = [ [19.13626 72.92506 '2016-07-21T05:43:09+00:00'] [19.13597 72.92495 '2016-07-21T05:43:15+00:00'] [19.13553 72.92469 '2016-07-21T05:43:21+00:00'] ] polylineUtil.encodeTimeAwarePolyline(points) // Use polylineUtil.decodeTimeAwarePolyline(polyline) to decode

With a compressed format (with >80% compression) the data for an order can be saved in a single row—and the polyline can be decoded to accurately determine distance traveled or show the trip summary at the end of the order. Which means retrieving and storing location data for an order can be done with a fraction of the complexity.

Issue: Poor visual experience

A smooth animation experience is key to delivering an anxiety-free experience to your consumers. Since a typical session duration is small it is important to convey progress and set expectations in a quick glance. As we were developing our tracking experience we found the following UI elements to be useful for consumers in addition to the live marker.

  • Marker orientation or bearing: in order to indicate direction of movement
  • Trailing polyline and trip progress: in order to indicate progress made so far
  • Pulsating dot: in order to indicate connectivity of the rider
  • Rider and order info: in order to reassure the consumer and make it real
  • Remaining time and distance: in order to set clear expectations

These elements require interpolation and animation libraries on the device working in sync with each other to ensure a high-quality experience. For example the LatLngInterpolator on Android is a key element to smoothen animation.

private interface LatLngInterpolator {
    LatLng interpolate(float fraction LatLng a LatLng b);
    
    class LinearFixed implements LatLngInterpolator {
        @Override
        public LatLng interpolate(float fraction LatLng a LatLng b) {
            double lat = (b.latitude - a.latitude) * fraction + a.latitude;
            double lngDelta = b.longitude - a.longitude;
            // Take the shortest path across the 180th meridian.
            if (Math.abs(lngDelta) > 180) {
                lngDelta -= Math.signum(lngDelta) * 360;
            }
            double lng = lngDelta * fraction + a.longitude;
            return new LatLng(lat lng);
        }
    }
}

With these elements in place our tracking experience looks like the one below on iOS. Similar experiences are available for Android and the web.

Try us out

How have you built your tracking experience? We are always looking to improve ours and would love to hear from you. We offer our tracking experience through a quick integration experience to developers. There are customizable SDKs for in-app and web experiences.