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

minimum accuracy before showing GeolocateControl dot #9177

Open
Meekohi opened this issue Jan 13, 2020 · 17 comments
Open

minimum accuracy before showing GeolocateControl dot #9177

Meekohi opened this issue Jan 13, 2020 · 17 comments

Comments

@Meekohi
Copy link
Contributor

Meekohi commented Jan 13, 2020

Motivation

The default GeolocateControl shows the viewer's position as reported by navigator.geolocation.watchPosition immediately, but this often has a very high margin of error. The dot is often in the wrong location, which can be confusing or even dangerous depending on the application.

Design Alternatives

An even better design would be to show the dot with the radius of confusion as a circle around it (common design pattern in many driving/aviation applications).

Design

A simpler edit is to allow the user to provide a "minimum accuracy" in meters, and ignore watchPosition calls that do not meet this level of accuracy.

Mock-Up

Will look the same visually, but the geolocation dot will only show once the minimum gps accuracy is met.

Concepts

New concept is a minimum GPS accuracy, should be documented at https://github.com/mapbox/mapbox-gl-js/blob/master/src/ui/control/geolocate_control.js#L77-L81

Implementation

navigator.geolocation.watchPosition already returns an accuracy value (in meters) as position.coords.accuracy (see https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates)

The _onSuccess function of GeolocateControl can easily be updated to ignore position events below a threshold accuracy: https://github.com/mapbox/mapbox-gl-js/blob/master/src/ui/control/geolocate_control.js#L184

A minimum accuracy can be provided as an optional configuration at https://github.com/mapbox/mapbox-gl-js/blob/master/src/ui/control/geolocate_control.js#L14

@Meekohi
Copy link
Contributor Author

Meekohi commented Jan 13, 2020

Also I'm willing to put together the PR if there is support for this generally.

@Meekohi Meekohi changed the title minimum accuracy before showing GeolocationCoordinates dot minimum accuracy before showing GeolocateControl dot Jan 13, 2020
@ryanhamley
Copy link
Contributor

the geolocation dot will only show once the minimum gps accuracy is met

I think we wouldn't want to go this route since not immediately showing anything can create the impression that the functionality isn't working. This came up recently with multiple maps on one page and watchLocation was waiting for the next result before updating additional maps.

An even better design would be to show the dot with the radius of confusion as a circle around it

This could be tricky to convert meters into a circular radius. You'd have to take into account the latitude and longitude of the point as well as the zoom since the length of a meter would change slightly and then you'd have to convert that to pixels since that's the unit for circle-radius.

Overall, I think I'd prefer the "area of confusion" approach to not showing anything until some threshold is met. But I'm curious how big of a problem this can be. What's an average value for position.coords.accuracy?

@Meekohi
Copy link
Contributor Author

Meekohi commented Jan 13, 2020

In my limited experience the accuracy on mobile devices usually starts at about 1km, rapidly drops down to 100m-10m depending on how good your signal is, and then slowly gets more accurate. On Desktop you often can't get better than ~500m accuracy or even worse (e.g. if the browser is just guessing based off IP address). Would be interesting to find some hard data on this, I will look around.

@Meekohi
Copy link
Contributor Author

Meekohi commented Jan 13, 2020

My specific application is for trail wayfinding on http://cvilletrails.com -- the user experience right now is often "oops, should I go left or right", so you pull out your phone and visit the page. The dot that initially appears (and stays put for some time) is often in the general area, so you assume it is accurate, but can lead you to make the wrong decision and close the page unless you wait ~15 seconds for it to sort itself out. Might be compounded by being 'in the trees' or etc where GPS accuracy is lower than normal.

@Meekohi
Copy link
Contributor Author

Meekohi commented Jan 13, 2020

No luck finding definitive data on accuracy over time -- made a little test page if anyone wants to experiment with their own device: https://meekohi.com/geotest.html (just spits out the timestamp and accuracy every update)

@Meekohi
Copy link
Contributor Author

Meekohi commented Jan 13, 2020

(Note: being on wifi seems to significantly increase the initial accuracy vs just using the GPS directly, try with and without)

@ryanhamley
Copy link
Contributor

Thanks for digging into this. I'm curious if any of my teammates have thoughts on this. I think it could be a useful feature, if a bit tricky to implement as I noted above. That being said, I'd probably advocate for it being optional functionality. Like you'd have to pass showAccuracy: true as part of the GeolocationControl's options to turn this on. That would leave default behavior as is while giving the option for a more accurate display on applications which may need fine-grained location data.

@Meekohi
Copy link
Contributor Author

Meekohi commented Jan 13, 2020

👍 I was imagining an option like accuracyThreshold: 100; // meters that defaults to null for no threshold (keep current behavior).

@Meekohi
Copy link
Contributor Author

Meekohi commented Jan 13, 2020

I'd also be interested in hearing from others about how difficult drawing the 'circle of confusion' might be. I don't know that we'd need to go crazy with accuracy: for amounts less than a few kilometers a common linear approximation is that 111,111 meters == 1 degree of latitude (or cos(latitude) degrees of longitude).

function metersToPixels(accuracy, latitude) {
  const pixeslPerDegree = 10; // figure this out based on zoom level... should be simple/fixed
  return (accuracy / 111111) * pixelsPerDegree / Math.cos(latitude * Math.PI / 180)
}

Since everything is Spherical Mercator projection I think a simple function like above should work ok? I doubt we need anything near pixel accuracy, it's just to give the flavor of whether the point is 'pretty accurate' or 'really not accurate'.

@ryanhamley
Copy link
Contributor

I'm not sure if you saw it, but that's basically the same function as this Stack Overflow answer so yeah I think that's correct. I guess that's true that we're dealing with such small distances and high zoom levels that an approximation should work fine. @mourner would you give this a 👍 to proceed on implementation?

@mourner
Copy link
Member

mourner commented Jan 13, 2020

@ryanhamley yes, this sounds good. The only caveat with that answer is that the stops should start with 1.

@ryanhamley
Copy link
Contributor

Awesome. we'd love to see your PR for this @Meekohi here's our contributing docs if you need them

@Meekohi
Copy link
Contributor Author

Meekohi commented Jan 13, 2020

tbh I don't have the faintest idea how one would draw a circle inside geolocate_control.js... (part of why I proposed the simple threshold solution). Is the idea to create a DOM element shaped like a circle with the correct radius and use a Marker to correctly position it, like the userLocationDot? SVG element?

@andrewharvey
Copy link
Collaborator

andrewharvey commented Jan 14, 2020

Hi @Meekohi thanks for opening this ticket.

I'd much prefer an accuracy circle instead of a minimum threshold.

The current behaviour should set the zoom based on the accuracy so that low accuracy has a low zoom and high accuracy has a high zoom, but I agree we should extend this with a circle.

You'd need to update the SVGHTML Marker element to include an accuracy circle and dynamically update this as the accuracy changes. I'm happy to help review your PR as well along with @ryanhamley and @mourner .

This is what I was thinking for the option.

* @param {boolean} [options.showUserLocationAccuracy=false] If `true` a transparent blue circle will be drawn at the user location, with size indicating the accuracy of the location.

Looking forward to seeing your PR.

@andrewharvey
Copy link
Collaborator

PS I'm working on a separate feature for the GeolocateContral at https://github.com/mapbox/mapbox-gl-js/pull/8929/files, but I'm happy to refactor my PR if you manage to get a PR together first.

@challasrivani
Copy link

I agree with Andrew on adding a circle around the marker based on the accuracy(some thing like this
image )
. Also, the width of the circle around the marker should be based on the zoom level and latitude. FYR ... https://wiki.openstreetmap.org/wiki/Zoom_levels

@Meekohi
Copy link
Contributor Author

Meekohi commented Jan 14, 2020

@andrewharvey doesn't look like they should interfere with each other at all -- I had to take the same approach and add a _accuracy: number to the GeolocateControl class so it would be available for map 'move' events.

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

No branches or pull requests

5 participants