mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-08 21:30:57 +00:00
fixed issue with missing minimum confidence for fixes too far apart (1h as in the 650 mini trans-pacific race tracked with YellowBrick)
This commit is contained in:
1 parent
ac4a4853c4
commit
f20258a1fd
6 files changed
+60
-8
No files matched your search
+2
@@ -39,4 +39,6 @@ public interface ConfidenceFactory {
|
||||
Weigher<TimePoint> createExponentialTimeDifferenceWeigher(long halfConfidenceAfterMilliseconds, double minimumConfidence);
|
||||
|
||||
Weigher<TimePoint> createHyperbolicTimeDifferenceWeigher(long halfConfidenceAfterMilliseconds);
|
||||
|
||||
Weigher<TimePoint> createHyperbolicSquaredTimeDifferenceWeigher(long halfConfidenceAfterMilliseconds);
|
||||
}
|
||||
+5
@@ -34,6 +34,11 @@ public class ConfidenceBasedAveragerFactoryImpl implements ConfidenceFactory {
|
||||
return new HyperbolicTimeDifferenceWeigher(halfConfidenceAfterMilliseconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weigher<TimePoint> createHyperbolicSquaredTimeDifferenceWeigher(long halfConfidenceAfterMilliseconds) {
|
||||
return new HyperbolicSquaredTimeDifferenceWeigher(halfConfidenceAfterMilliseconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weigher<TimePoint> createExponentialTimeDifferenceWeigher(long halfConfidenceAfterMilliseconds) {
|
||||
return new ExponentialTimeDifferenceWeigher(halfConfidenceAfterMilliseconds);
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.sap.sailing.domain.confidence.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.confidence.Weigher;
|
||||
|
||||
public class HyperbolicSquaredTimeDifferenceWeigher implements Weigher<TimePoint> {
|
||||
private static final long serialVersionUID = 4378168079868145134L;
|
||||
private final long halfConfidenceAfterMilliseconds;
|
||||
|
||||
public HyperbolicSquaredTimeDifferenceWeigher(long halfConfidenceAfterMilliseconds) {
|
||||
this.halfConfidenceAfterMilliseconds = halfConfidenceAfterMilliseconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Postconditions:
|
||||
* <pre>
|
||||
* |fix-request|=halfConfidenceAfterMilliseconds ==> result==0.5
|
||||
* 0 <= result <= 1
|
||||
* fix=request ==> result==1
|
||||
* With request approaching infinity, the function grows with the reciprocal of request squared
|
||||
* </pre>
|
||||
*
|
||||
* This implies the following formula for result := f(x):
|
||||
*
|
||||
* <pre>
|
||||
* for x := |fix-request| with x>=0:
|
||||
* f(x) := c/(x^2+y)
|
||||
* f(0) = 1 = c/y ==> c = y
|
||||
* f(halfConfidenceAfterMilliseconds) = 0.5 = c/(halfConfidenceAfterMilliseconds+y)
|
||||
* => c/y = 2c/(halfConfidenceAfterMilliseconds+y)
|
||||
* <=> 1/y = 2/(halfConfidenceAfterMilliseconds+y)
|
||||
* <=> halfConfidenceAfterMilliseconds + y = 2y
|
||||
* <=> y = halfConfidenceAfterMilliseconds
|
||||
* => c = halfConfidenceAfterMilliseconds
|
||||
* </pre>
|
||||
*/
|
||||
@Override
|
||||
public double getConfidence(TimePoint fix, TimePoint request) {
|
||||
double x = Math.abs(fix.asMillis() - request.asMillis());
|
||||
double c = halfConfidenceAfterMilliseconds*halfConfidenceAfterMilliseconds;
|
||||
double y = c;
|
||||
return c/(x*x+y);
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -108,6 +108,7 @@ public class DynamicGPSFixMovingTrackImpl<ItemType> extends DynamicTrackImpl<Ite
|
||||
if (e.isValidityCached()) {
|
||||
result = e.isValid();
|
||||
} else {
|
||||
boolean fixHasValidSogAndCog = (e.getSpeed().getMetersPerSecond() != 0.0 && e.getSpeed().getBearing().getDegrees() != 0.0);
|
||||
GPSFixMoving previous = rawFixes.lower(e);
|
||||
GPSFixMoving next = rawFixes.higher(e);
|
||||
Speed speedToPrevious = Speed.NULL;
|
||||
@@ -120,10 +121,10 @@ public class DynamicGPSFixMovingTrackImpl<ItemType> extends DynamicTrackImpl<Ite
|
||||
speedToNext = e.getPosition().getDistance(next.getPosition())
|
||||
.inTime(next.getTimePoint().asMillis() - e.getTimePoint().asMillis());
|
||||
}
|
||||
result = (previous == null || speedToPrevious.getMetersPerSecond() <= MAX_SPEED_FACTOR_COMPARED_TO_MEASURED_SPEED_FOR_FILTERING
|
||||
result = (!fixHasValidSogAndCog || ((previous == null || speedToPrevious.getMetersPerSecond() <= MAX_SPEED_FACTOR_COMPARED_TO_MEASURED_SPEED_FOR_FILTERING
|
||||
* e.getSpeed().getMetersPerSecond())
|
||||
&& (next == null || speedToNext.getMetersPerSecond() <= MAX_SPEED_FACTOR_COMPARED_TO_MEASURED_SPEED_FOR_FILTERING
|
||||
* e.getSpeed().getMetersPerSecond())
|
||||
* e.getSpeed().getMetersPerSecond())))
|
||||
&& (maxSpeedForSmoothing == null
|
||||
|| (previous == null || speedToPrevious.compareTo(maxSpeedForSmoothing) <= 0) || (next == null || speedToNext
|
||||
.compareTo(maxSpeedForSmoothing) <= 0));
|
||||
|
||||
+2
-2
@@ -521,7 +521,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
|
||||
SpeedWithBearingWithConfidence<TimePoint> estimatedSpeed = getEstimatedSpeed(at, getInternalFixes(),
|
||||
ConfidenceFactory.INSTANCE.createExponentialTimeDifferenceWeigher(
|
||||
// use a minimum confidence to avoid the bearing to flip to 270deg in case all is zero
|
||||
getMillisecondsOverWhichToAverageSpeed()/2)); // half confidence if half averaging interval apart
|
||||
getMillisecondsOverWhichToAverageSpeed()/2, /* minimumConfidence */ 0.00000001)); // half confidence if half averaging interval apart
|
||||
return estimatedSpeed == null ? null : estimatedSpeed.getObject();
|
||||
} finally {
|
||||
unlockAfterRead();
|
||||
@@ -535,7 +535,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
|
||||
return getEstimatedSpeed(at, getRawFixes(),
|
||||
ConfidenceFactory.INSTANCE.createExponentialTimeDifferenceWeigher(
|
||||
// use a minimum confidence to avoid the bearing to flip to 270deg in case all is zero
|
||||
getMillisecondsOverWhichToAverageSpeed())).getObject();
|
||||
getMillisecondsOverWhichToAverageSpeed(), /* minimumConfidence */ 0.00000001)).getObject();
|
||||
} finally {
|
||||
unlockAfterRead();
|
||||
}
|
||||
|
||||
+4
-4
@@ -14,8 +14,8 @@ is encoded on which the <em>operations</em> will perform changes to transition f
|
||||
state to the next. Then, design your operations class. The trickiest part comes next. You
|
||||
have to define a transformer that maps a pair of your operations to another pair of
|
||||
operations of the same type. The transformer has to implement the
|
||||
{@link com.sap.runlet.operationaltransformation.Transformer} interface, in particular
|
||||
the {@link com.sap.runlet.operationaltransformation.Transformer#transform} method. The
|
||||
{@link com.sap.sailing.operationaltransformation.Transformer} interface, in particular
|
||||
the {@link com.sap.sailing.operationaltransformation.Transformer#transform} method. The
|
||||
transformation function assumes that both input operations have been applied to the same
|
||||
state, one on a client, the other one on the server. The resulting operation for the client
|
||||
applied on the client must lead to a state equal to the state reached on the server by
|
||||
@@ -29,8 +29,8 @@ on the server, and <em>c</em> as the operation that was executed in state <em>s_
|
||||
client, and <em>s</em> as the operation executed on the server in state <em>s_s</em>, then the
|
||||
following condition must hold:<br>
|
||||
<pre>
|
||||
t.transform(c, s).getClientOp().applyTo(c.applyTo(s_c).equals(
|
||||
t.transform(c, s).getServerOp().applyTo(s.applyTo(s_s))
|
||||
t.transform(c, s).getClientOp().applyTo(c.applyTo(s_c)).equals(
|
||||
t.transform(c, s).getServerOp().applyTo(s.applyTo(s_s)))
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
|
||||
Reference in new issue
Block a user