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

Wish: GPS#Travelled in P082 #3099

Closed
Wiki591 opened this issue Jun 2, 2020 · 7 comments · Fixed by #3103
Closed

Wish: GPS#Travelled in P082 #3099

Wiki591 opened this issue Jun 2, 2020 · 7 comments · Fixed by #3103
Labels
Category: Plugin Related to supported sensors Type: Enhancement Improve something already present Type: Feature Request Add a completely new feature (e.g. controller/plugin)

Comments

@Wiki591
Copy link
Contributor

Wiki591 commented Jun 2, 2020

I am working on a project to design an onboard "computer" for my caravan. My old one (since about 16 years) wrote every 100m my current position into its flash (beside much more data interesting me) and made the vacation trip trackable and I could make the trip visible using OSM maps to present the journey to whom ever interested (and yes, to whom is not interested, too).

I tried to do this using the GPS plugin by setting the interval of distance travelled to 100m, addind in case of the event 100m to a dummy device.

It is doing this, but very inaccurate. The travel distance recorded using this way looses around 20-30% of the way travelled. The faster you go, the higher the miss. The explanation is the 2 secs interval of the GPS sensor, travelling with a speed of 100km/h means, that in worst case the event is triggered after around 150m of true distance. I can see in the log, that the really travelled distance is sent almost accurate to the log. So it would be nice to get this accurate information somehow from the plugin, triggered by an event.

@TD-er
Copy link
Member

TD-er commented Jun 2, 2020

Hmm, that's a rather strange GPS sensor then.
My (3 euro) GPS sensors all output roughly 8 - 9 messages per second (at 9600 baud) and 2 - 3 of them contain position update sentences.
Maybe you can use some tool to change the output rate of some sentences and store that setting in the GPS module?
The GPS plugin does not support writing settings to the GPS module.

We do not have something like a Kalman filter to predict when we might hit some coordinate, meaning we will always be "late".
And the computed distance is based on the 'last position' that was used to generate an update.
Meaning if you travel in a spiral, you may travel a lot more before it may trigger a new event.

I think adding track of the actual distance traveled is only useful when driving with sufficient speed and low enough HDOP values. (the standard deviation in meters of the horizontal position)
When parked, the GPS position may drift quite a bit over time, so then you need to compare it with the last trigger position. But when driving, it does make sense to track the actual movement on every position update.
So that makes for quite a complex algorithm

For now I think it makes sense if you could increase the message frequency of those NMEA sentences containing positional updates.
Like I said, my cheap uBlox clones (I don't believe they are the real deal for less than 3 euro with 25 mm antenna) output positional updates several times a second, which would make the error already quite a bit smaller.... when driving in a straight line.

@TD-er TD-er added Category: Plugin Related to supported sensors Type: Enhancement Improve something already present Type: Feature Request Add a completely new feature (e.g. controller/plugin) labels Jun 2, 2020
@Wiki591
Copy link
Contributor Author

Wiki591 commented Jun 2, 2020

I followed your instruction in the forum to place a rule triggered by GPS#long to write my 100m distance.

The sensor is a Neo 6M, I am using a similar one successfully in another automotive project. I've seen it as an accurate, fast fixing sensor.

HDOP:
grafik

Seems as if I was wrong concerning the message interval of the sensor. Hitting "F5" several times on the device webpage tells me, that the interval seems to be much shorter.

And yes, the only way to calculated the travelled distance is by drawing a straight line between the coordinates, corners will be cut. So there will be a slight difference between travelled and calculated distance. But a difference of 20-30% for me is not explainable in this way. There has to be another reason - I'm lost in this case. The (4) tests I ran followed some 10km of highway, some 10km country roads, some 2km in our village.

Any other suggestions?

(I don't want to turn this platform into a support forum, I will post in parallel in the corresponding thread in the forum itself for discussion)

@TD-er
Copy link
Member

TD-er commented Jun 3, 2020

Well at least the fix quality is more than good enough for a proper update interval.

Can you test what the average interval is? So take the distance between 10+ samples and see what the average interval is in meters.

What can happen is that the delay between sending the event and actually processing the rules can take long enough so that there has been another position update.
And if you refer to [gps#long] (or any other taskname/var reference), it will take the current value, not the value it was at the time of the event.

So the distance between 2 random samples can have quite some deviation. But that 'jitter' should be close to 0 if you take the average interval over multiple samples (10 or more)
If there is still some difference even when averaging over multiple samples, then there's something else going on.

The distance computation is done by comparing the last event position and computing the distance to the current position.
Only if it is more than the set interval distance, it will fire the event.
So if you see a position update which computes to 99.99 meters, it will only fire the event on the next position update.
At 30 meters/sec (little over 100 km/h) and an update interval of 1 sec, you will have an offset of 30% (interval 100m)
So an improvement can be to take into account the speed, distance increase per position update and average time between position updates to predict whether or not you will be over this threshold before the next update.

I use the distance calculation function provided in the TinyGPS+ library, but I have no reason to believe that one is flawed.
As far as I can remember, it only uses the longitude and latitude and does not correct the earth's radius for the latitude (earth is not perfectly round). But I doubt that will give much of a difference.

You can see in the timing stats page how often the PLUGIN_READ is called of the GPS plugin.
That relates roughly to the number of sentences read. About 1/3rd of them contains positional information. (on my units it is 8.27 calls per second)
It is not an exact relation, since I read as many characters as there are in the serial buffer in the 50/sec call. So a call to PLUGIN_READ may in theory sometimes be called after 2 sentences are read.
Now that I write this down, I do realize one thing that may be considered a "bug".
As soon as there is a sentence read, a new call to PLUGIN_READ is scheduled.
However, if a new one is scheduled before the old one is processed, it may be delayed a bit to the new set time.
It is set to be scheduled at millis() + 10, so it does not become a blocking call.
But there is no guarantee something will be executed at the set time. It is mainly to determine the order of scheduled things to do and if the node is idle, to wait until it has to happen.
So the call to PLUGIN_READ may be called with some delay as it may be rescheduled before it was called.
The distance computation is done in the PLUGIN_READ call, as is when the 'new last position' is stored.
So I could move this calculation to the function where the sentences are read, to make sure there is as little delay as possible for this distance calculation.

@Wiki591
Copy link
Contributor Author

Wiki591 commented Jun 3, 2020

I don't think that you have a 'bug' inside the coding or a timing issue. Your distance calculation seems to be correct. At the moment the event is fired everytime in the log appears an entry something like "Distance travelled" (don't remeber exactly) with a number somewhat>100m. But everytime I am counting only +100m, not knowing the correct value. So it works as designed, the difference is predefined.

My thought, probably easiest way: Would it be possible to append this already existing value (>100m, better >Distance Update Interval), shown in the log, as a second eventvalue if an event is fired from the plugin? So I could take this value, put it into my distance counter and I suppose, the difference will be minimzed.

This kind of distance counting I want to use never will be exact because the calculation draws a straight line instead of following the curves. But doesn't need to be. My old onboard computer meets the travelled distance minus some 1%-3% by writing (somewhat around 100m) the "raw" calculated data into its flash.

@TD-er
Copy link
Member

TD-er commented Jun 3, 2020

Yep, that's a good solution, to report the distance traveled as event variable.

@Wiki591
Copy link
Contributor Author

Wiki591 commented Jun 3, 2020

Just for comparism and curiosity:
In the past I calculated the distance using the following code (its not mine, but I don't remember the source), written in Tiger Basic - and it worked pretty well:


[...]
CALL GetDistance(Dist, OldLat, OldLon, Latitude, Longitude)
[...]
Kilometer = Kilometer + Dist
[...]
SUB GetDistance(VAR REAL Dist; REAL Lat1, Lon1, Lat2, Lon2)
	REAL Hoch
	REAL Rechts
	
	Hoch = ABS(Lat1 - Lat2)
	Rechts = ABS(Lon1 - Lon2)
	Rechts = Rechts * COS(DEG * ((Lat1 + Lat2) / 2))
	Hoch = Hoch * 111.1111111111
	Rechts = Rechts * 111.1111111111
	Dist = SQRT((Hoch * Hoch) + (Rechts * Rechts))
END

@TD-er
Copy link
Member

TD-er commented Jun 3, 2020

This is the used distance calculation:

double TinyGPSPlus::distanceBetween(double lat1, double long1, double lat2, double long2)
{
// returns distance in meters between two positions, both specified
// as signed decimal-degrees latitude and longitude. Uses great-circle
// distance computation for hypothetical sphere of radius 6372795 meters.
// Because Earth is no exact sphere, rounding errors may be up to 0.5%.
// Courtesy of Maarten Lamers
double delta = radians(long1-long2);
double sdlong = sin(delta);
double cdlong = cos(delta);
lat1 = radians(lat1);
lat2 = radians(lat2);
double slat1 = sin(lat1);
double clat1 = cos(lat1);
double slat2 = sin(lat2);
double clat2 = cos(lat2);
delta = (clat1 * slat2) - (slat1 * clat2 * cdlong);
delta = sq(delta);
delta += sq(clat2 * sdlong);
delta = sqrt(delta);
double denom = (slat1 * slat2) + (clat1 * clat2 * cdlong);
delta = atan2(delta, denom);
return delta * 6372795;
}

TD-er added a commit to TD-er/ESPEasy that referenced this issue Jun 6, 2020
TD-er added a commit that referenced this issue Jun 8, 2020
[GPS] Add GPS#travelled=... event  (#3099)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Category: Plugin Related to supported sensors Type: Enhancement Improve something already present Type: Feature Request Add a completely new feature (e.g. controller/plugin)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants