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

Trigger readings only upon geolocation change instead of time interval #13

Open
martijnthe opened this issue Feb 6, 2018 · 17 comments
Open

Comments

@martijnthe
Copy link

martijnthe commented Feb 6, 2018

Is it correct that the current design will trigger reading events at a fixed time interval / frequency?
I can see this is useful for use cases that involve continuous visualization of the current location.

However, in our use case, it would be more useful to be able to configure the instance to only trigger when a certain geolocation delta (distance) has been crossed, compared to the last reading. In other words: "only give me reading events for those locations that compared to the previously emitted reading changed by at least X meters".

We could do this filtering logic in the JS code on top of the time frequency based triggering, but this is less desirable from a power consumption point of view.

@martijnthe
Copy link
Author

A question that just arose: is a similar configuration for heading also needed?

I can imagine for certain use cases one isn't interested in heading at all and consequently wouldn't need to receive new readings at all if only the heading has changed.

@martijnthe
Copy link
Author

fyi @anssiko

@anssiko
Copy link
Member

anssiko commented Feb 15, 2018

I believe most geolocation use cases would be served with a one threshold (expressed in meters). When a change exceeding the defined threshold is observed in latitude, longitude, (or altitude?) compared to the previous reading, a new reading is be triggered.

@martijnthe would that satisfy the requirements you have in mind?

I think use cases that involve tracking heading changes would be better served by the Orientation Sensor.

I'd like us to understand the use cases better to make an informed design decision.

@martijnthe
Copy link
Author

I believe most geolocation use cases would be served with a one threshold (expressed in meters).

Right, I agree.

But the frequency option in the base SensorOptions, isn't it?
Not sure if it makes a lot of sense to have frequency for GeolocationSensor, TBH.

When a change exceeding the defined threshold is observed in latitude, longitude, (or altitude?) compared to the previous reading, a new reading is be triggered.

Right. I think the total delta in meters is probably most interesting in our use case. (So not a separate threshold for latitude, longitude, or altitude -- or would you? Perhaps for aviation use cases...?)

@anssiko
Copy link
Member

anssiko commented Feb 19, 2018

Not sure if it makes a lot of sense to have frequency for GeolocationSensor, TBH.

Correct. I was thinking we might want to default to a similar (but not the same) behavior as in the legacy Geolocation API, allow passing threshold (in meters) and latency (in seconds) at construction time. In pseudo:

If no frequency is given at construction, while (true):

  • If threshold is not given, set its value to an implementation specific default.
  • If latency is not given, set its value to an implementation specific default.
  • If previous_reading does not exist:
    • Invoke onreading
  • If any of latest_reading.(latitude|longitude|altitude) values differ from the respective previous_reading.(latitude|longitude|altitude) values by more than threshold:
    • Invoke onreading
  • If latest_reading.timestamp is greater than than previous_reading.timestamp + latency:
    • Invoke onreading

I think the legacy spec's new position differs significantly from the previous position definition has led to not so great interoperability across implementations since it does not explicitly define threshold (only an abstract high accuracy flag).

We want to learn from the earlier API and make improvements both in terms of developer ergonomics and interoperability.

Suggestions welcome!

I think the total delta in meters is probably most interesting in our use case.

Based on the use cases I'm aware of single threshold that applies globally across latitude, longitude, and altitude would be a good tradeoff. Let me know if you have use cases in mind that'd warrant more detailed control over thresholds, or if you have other ideas.

@blairmacintyre
Copy link

We need to take into account accuracy with this. Obviously a lot of this depends on use-case, and if you are doing big-distance geofencing-style applications, this all makes sense (e.g., my threshold is > 100m).

But, if someone wants a threshold of, say, 10m, in many cases the relative error associated with the location estimate (especially inside) will exceed this.

I'm not sure how to express this.

@tomayac
Copy link
Contributor

tomayac commented Sep 26, 2018

I would like to understand from an implementor, e.g., @reillyeon, how navigator.geolocation.watchPosition() is currently implemented on a high level. It certainly polls the location in the background (at an opaque frequency), but what is the logic as to when a new position makes the callback fire?

A common initial pattern is to navigator.geolocation.getCurrentPosition() first with possibly inaccurate data, and then to navigator.geolocation.watchPosition() to get more accurate data after maybe having obtained a GPS signal.

What I am unclear about is then how the watch loop continues, especially if the developer specifies an unreasonably high update frequency (I would expect, for example, that the user agent may decide to autonomously limit the frequency if the battery is low).

Eventually, this seems to mostly touch upon things that would need to be discussed in the context of #22. We might be able to merge this issue into #22.

@reillyeon
Copy link
Member

@tomayac Note that as mentioned in #21 the polling occurs very differently depending on whether we are using a true GPS receiver or Wi-Fi triangulation. The former is a push-based model where the GPS receiver typically produces a new result at a fixed frequency once a lock has been established. The latter is a pull-based model where the device must decide when it believes that it has moved sufficiently to request a new location estimate from a network service based on Wi-Fi beacons it has received.

The true GPS receiver will produce frequent updates after a long initial delay whereas the network service can be queried very quickly after performing a Wi-Fi scan but further requests are rate-limited to avoid exhausting API quota and so updates will be infrequent.

In addition there are hybrid models which will produce a course result very quickly (using cell tower location or Wi-Fi triangulation) that is then refined using GPS once a lock has been established.

@blairmacintyre
Copy link

Adding to this: on AR/VR devices with precision motion tracking (e.g., handhelds running ARKit/ARCore, or HMDs like Hololens or Magic Leap), either sort of geolocation estimation can be combined with the motion tracking to produce high frequency updates relative to a geolocation estimate.

We are doing a simple proof of concept of this; one thing I've wondered, though, is if the estimation (esp wifi, since so much of GPS is done in hardware) could be improved over time if a precise relative local motion was added in to constrain the results.

@tomayac
Copy link
Contributor

tomayac commented Nov 19, 2018

[O]ne thing I've wondered, though, is if the estimation (esp wifi, since so much of GPS is done in hardware) could be improved over time if a precise relative local motion was added in to constrain the results.

@blairmacintyre Some (native) implementations are using motion co-processors ("fitness sensors") for this, see, for example, Flutter background Geolocation for details.

@blairmacintyre
Copy link

The Flutter approach doesn't actually improve geolocation, it just optimizes battery life. Which is a Very Good Thing[tm] but not the same.

@TZAdvantage
Copy link

TZAdvantage commented Jul 19, 2019

We have a tracking website that is used by many different kinds of businesses. From police, ambulances with dedicated GPS equipment to a single driver with a phone.
In ALL cases a position is needed at an interval even when speed = 0. Also on every turn larger then 30 degrees. A position every x meter does not create reliable routes as those meters can be in s straight line or with corners. Proofing where a vehicle/person was is then impossible. A 'watch' function is superfluous as it can be easily created with setTimeout/setInterval. More important is to get a position whenever it is needed by the application. A simple GetPosition that just does what its name says should be sufficient.

@Hecke29
Copy link

Hecke29 commented Jul 19, 2019

We have a tracking website that is used by many different kinds of businesses. From police, ambulances with dedicated GPS equipment to a single driver with a phone.
In ALL cases a position is needed at an interval even when speed = 0. Also on every turn larger then 30 degrees. A position every x meter does not create reliable routes as those meters can be in s straight line or with corners. Proofing where a vehicle/person was is then impossible. A 'watch' function is superfluous as it can be easily created with setTimeout/setInterval. More important is to get a position whenever it is needed by the application. A simple GetPosition that just does what its name says should be sufficient.

Apperently this is the main reason why this will (hopefully) never come like this.

@RickGlimmer
Copy link

RickGlimmer commented Jul 19, 2019

Is it correct that the current design will trigger reading events at a fixed time interval / frequency?
I can see this is useful for use cases that involve continuous visualization of the current location.
However, in our use case, it would be more useful to be able to configure the instance to only trigger when a certain geolocation delta (distance) has been crossed, compared to the last reading. In other words: "only give me reading events for those locations that compared to the previously emitted reading changed by at least X meters".
We could do this filtering logic in the JS code on top of the time frequency based triggering, but this is less desirable from a power consumption point of view.

The power consumption will not be any lower when you do the filtering logic in JS code. The GPS has to be active for this anyway. Does not matter which piece of software does the filtering.
In my opinion filtering should be left to the application.
I have seen this 'over thinking' too many times. It results in products that can be used by only a few and is a horrible experience for all others. Corners, speed, distance etc can all be checked with a few lines of code as a filter for further processing.

@anssiko
Copy link
Member

anssiko commented Sep 3, 2019

Consider merging this issue into #25.

@tomayac
Copy link
Contributor

tomayac commented Sep 3, 2019

The core question here is at what level the filtering "do I have a 'new' position?" should be done. I looked at Chrome data for watchPosition() (~0.05% of all page loads) compared to getCurrentPosition() (~5% of all page loads). Given these low numbers, it seems reasonable to leave the filtering to the app in question so they can implement their own logic based on the desired accuracy and latency, so merging into #25 seems fine. Any objections?

@bytesnz
Copy link

bytesnz commented Sep 12, 2022

I've just been looking at implementing a generic app to workaround that this isn't possible in the browser ATM. I think it would be good to have options like those of @nativescript/geolocation. frequency could be equivalent to updateTime and then have a option for updateDistance, resulting in a logic of a new position is emitted if the position change is more than updateDistance meters (dependent on accuracy), otherwise every frequency ms.

My use cases are position tracking during surveys (eg litter surveys) and position tracking of responders/first-aiders during events.

Having played with watchPosition, this was the logic I implemented in the code. Having the option to pass these options the the sensor constructor would mean the logic could be implemented at a lower level (it must already be implemented[ish] if it is in NativeScript) to save power.

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

10 participants