prepared track for distinguishing between raw and smoothened fixes

This commit is contained in:
Axel Uhl committed 2011-07-14 17:52:09 +02:00
1 parent cc1a24dae7
commit f22c6fda80
12 files changed
+68 -39

No files matched your search

@@ -219,7 +219,7 @@ public abstract class AbstractTracTracLiveTest implements Listener {
protected void storeTrack(Competitor competitor, DynamicTrack<Competitor, GPSFixMoving> track) throws FileNotFoundException, IOException {
ObjectOutput oo = getOutputStream(competitor);
for (GPSFixMoving fix : track.getFixes()) {
for (GPSFixMoving fix : track.getRawFixes()) {
writeGPSFixMoving(fix, oo);
}
oo.close();
@@ -129,7 +129,7 @@ public class TrackSmootheningTest extends AbstractTracTracLiveTest {
TimePoint lastTimePoint = null;
GPSFixMoving lastFix = null;
GPSFixMoving outlier = null;
for (GPSFixMoving fix : track.getFixes()) {
for (GPSFixMoving fix : track.getRawFixes()) {
if (lastTimePoint != null) {
TimePoint thisTimePoint = fix.getTimePoint();
long intervalInMillis = thisTimePoint.asMillis()-lastTimePoint.asMillis();
@@ -73,7 +73,7 @@ public class TrackTest {
@Test
public void testIterate() {
Iterator<GPSFixMoving> i = track.getFixes().iterator();
Iterator<GPSFixMoving> i = track.getRawFixes().iterator();
int count;
for (count=0; i.hasNext(); count++) {
i.next();
@@ -86,24 +86,24 @@ public class TrackTest {
long lastMillis = 0;
GPSFix lastFix = null;
boolean first = true;
for (Iterator<GPSFixMoving> i = track.getFixes().iterator(); i.hasNext(); first = false) {
for (Iterator<GPSFixMoving> i = track.getRawFixes().iterator(); i.hasNext(); first = false) {
GPSFixMoving fix = i.next();
long millis = fix.getTimePoint().asMillis();
if (!first) {
assertTrue(millis > lastMillis);
TimePoint inBetweenTimePoint = new MillisecondsTimePoint((millis+lastMillis)/2);
assertEquals(lastFix, track.getLastFixBefore(inBetweenTimePoint));
assertEquals(lastFix, track.getLastRawFixBefore(inBetweenTimePoint));
assertEquals(lastFix, track.getLastFixAtOrBefore(inBetweenTimePoint));
assertEquals(fix, track.getFirstFixAfter(inBetweenTimePoint));
assertEquals(fix, track.getFirstFixAtOrAfter(inBetweenTimePoint));
assertEquals(fix, track.getFirstRawFixAtOrAfter(inBetweenTimePoint));
assertEquals(lastFix, track.getLastFixAtOrBefore(lastFix.getTimePoint()));
assertEquals(fix, track.getFirstFixAtOrAfter(fix.getTimePoint()));
assertEquals(fix, track.getFirstRawFixAtOrAfter(fix.getTimePoint()));
assertEquals(lastFix, track.getLastFixBefore(fix.getTimePoint()));
assertEquals(lastFix, track.getLastRawFixBefore(fix.getTimePoint()));
assertEquals(fix, track.getLastFixAtOrBefore(fix.getTimePoint()));
assertEquals(fix, track.getFirstFixAfter(lastFix.getTimePoint()));
assertEquals(lastFix, track.getFirstFixAtOrAfter(lastFix.getTimePoint()));
assertEquals(lastFix, track.getFirstRawFixAtOrAfter(lastFix.getTimePoint()));
}
lastMillis = millis;
lastFix = fix;
@@ -112,7 +112,7 @@ public class TrackTest {
@Test
public void assertEstimatedPositionBeforeStartIsStart() {
GPSFixMoving start = track.getFixes().iterator().next();
GPSFixMoving start = track.getRawFixes().iterator().next();
TimePoint oneNanoBeforeStart = new MillisecondsTimePoint(start.getTimePoint().asMillis()-1);
assertEquals(start.getPosition(), track.getEstimatedPosition(oneNanoBeforeStart, false));
}
@@ -122,7 +122,7 @@ public class TrackTest {
long lastMillis = 0;
GPSFix lastFix = null;
boolean first = true;
for (Iterator<GPSFixMoving> i = track.getFixes().iterator(); i.hasNext(); first = false) {
for (Iterator<GPSFixMoving> i = track.getRawFixes().iterator(); i.hasNext(); first = false) {
GPSFixMoving fix = i.next();
long millis = fix.getTimePoint().asMillis();
if (!first) {
@@ -143,9 +143,9 @@ public class TrackTest {
@Test
public void testSimpleExtrapolation() {
GPSFix fix = track.getLastFix();
GPSFix fix = track.getLastRawFix();
long millis = fix.getTimePoint().asMillis();
GPSFix lastFix = track.getLastFixBefore(fix.getTimePoint());
GPSFix lastFix = track.getLastRawFixBefore(fix.getTimePoint());
long lastMillis = lastFix.getTimePoint().asMillis();
TimePoint afterTimePoint = new MillisecondsTimePoint(millis + (millis-lastMillis));
Position extrapolatedPosition = track.getEstimatedPosition(afterTimePoint, true);
@@ -155,9 +155,9 @@ public class TrackTest {
@Test
public void testExtrapolationDoesntHappenIfSuppressed() {
GPSFix fix = track.getLastFix();
GPSFix fix = track.getLastRawFix();
long millis = fix.getTimePoint().asMillis();
GPSFix lastFix = track.getLastFixBefore(fix.getTimePoint());
GPSFix lastFix = track.getLastRawFixBefore(fix.getTimePoint());
long lastMillis = lastFix.getTimePoint().asMillis();
TimePoint afterTimePoint = new MillisecondsTimePoint(millis + (millis-lastMillis));
Position extrapolatedPosition = track.getEstimatedPosition(afterTimePoint, false);
@@ -170,7 +170,7 @@ public class TrackTest {
List<GPSFixMoving> fixes = new ArrayList<GPSFixMoving>();
boolean first = true;
GPSFixMoving oldFix = null;
for (GPSFixMoving fix : track.getFixes()) {
for (GPSFixMoving fix : track.getRawFixes()) {
fixes.add(fix);
if (first) {
first = false;
@@ -228,7 +228,7 @@ public class TrackTest {
@Test
public void testDistanceTraveledOnInBetweenSectionFromFixToFix() {
// take second and third fix and compute distance between them
Iterator<GPSFixMoving> iter = track.getFixes().iterator();
Iterator<GPSFixMoving> iter = track.getRawFixes().iterator();
iter.next(); // skip first;
GPSFix second = iter.next();
GPSFix third = iter.next();
@@ -138,7 +138,7 @@ public class RaceTrackerImpl implements Listener, RaceTracker {
boolean first = true;
for (Buoy buoy : domainControlPoint.getBuoys()) {
DynamicTrack<Buoy, GPSFix> buoyTrack = trackedRace.getTrack(buoy);
if (buoyTrack.getFirstFix() == null) {
if (buoyTrack.getFirstRawFix() == null) {
buoyTrack.addGPSFix(new GPSFixImpl(new DegreePosition(
first ? controlPoint.getLat1() : controlPoint.getLat2(),
first ? controlPoint.getLon1() : controlPoint.getLon2()), MillisecondsTimePoint.now()));
@@ -17,24 +17,28 @@ public interface Track<FixType extends Timed> {
* applied to the fixes returned by this method.
*/
Iterable<FixType> getFixes();
Iterable<FixType> getRawFixes();
FixType getLastFixAtOrBefore(TimePoint timePoint);
FixType getFirstFixAtOrAfter(TimePoint timePoint);
FixType getFirstRawFixAtOrAfter(TimePoint timePoint);
FixType getLastFixBefore(TimePoint timePoint);
FixType getLastRawFixBefore(TimePoint timePoint);
FixType getFirstFixAfter(TimePoint timePoint);
/**
* The first fix in this track or <code>null</code> if the track is empty
* The first fix in this track or <code>null</code> if the track is empty. The fix returned may
* be an outlier that is not returned by calls operating on the smoothened version of the track.
*/
FixType getFirstFix();
FixType getFirstRawFix();
/**
* The last fix in this track or <code>null</code> if the track is empty
* The last fix in this track or <code>null</code> if the track is empty. The fix returned may
* be an outlier that is not returned by calls operating on the smoothened version of the track.
*/
FixType getLastFix();
FixType getLastRawFix();
/**
* Returns an iterator starting at the first fix after <code>startingAt</code> (or "at or after" in case
@@ -18,7 +18,7 @@ public class DynamicTrackImpl<ItemType, FixType extends GPSFix> extends
@Override
public void addGPSFix(FixType gpsFix) {
getInternalFixes().add(gpsFix);
getInternalRawFixes().add(gpsFix);
for (RaceChangeListener<ItemType> listener : listeners) {
listener.gpsFixReceived(gpsFix, getTrackedItem());
}
@@ -54,7 +54,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
@Override
public Position getEstimatedPosition(TimePoint timePoint, boolean extrapolate) {
FixType lastFixAtOrBefore = getLastFixAtOrBefore(timePoint);
FixType firstFixAtOrAfter = getFirstFixAtOrAfter(timePoint);
FixType firstFixAtOrAfter = getFirstRawFixAtOrAfter(timePoint);
if (lastFixAtOrBefore != null && lastFixAtOrBefore == firstFixAtOrAfter) {
return lastFixAtOrBefore.getPosition(); // exact match; how unlikely is that?
} else {
@@ -109,7 +109,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
return null;
}
} else if (fix2 == null) {
FixType lastBeforeFix1 = getLastFixBefore(fix1.getTimePoint());
FixType lastBeforeFix1 = getLastRawFixBefore(fix1.getTimePoint());
if (lastBeforeFix1 != null) {
fix2 = fix1;
fix1 = lastBeforeFix1; // compute speed based on the last two fixes and assume constant speed
@@ -129,6 +129,10 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
}
/**
* Returns the smoothened fixes (see {@link #getInternalFixes()}), type-cast such that it's a set of {@link GPSFix}
* objects
*/
private NavigableSet<GPSFix> getGPSFixes() {
@SuppressWarnings("unchecked")
NavigableSet<GPSFix> result = (NavigableSet<GPSFix>) super.getInternalFixes();
@@ -32,18 +32,38 @@ public abstract class TrackImpl<FixType extends Timed> implements Track<FixType>
this.fixes = new ConcurrentSkipListSet<Timed>(TimedComparator.INSTANCE);
}
protected NavigableSet<FixType> getInternalRawFixes() {
@SuppressWarnings("unchecked")
NavigableSet<FixType> result = (NavigableSet<FixType>) fixes;
return result;
}
/**
* @return the smoothened fixes
*/
protected NavigableSet<FixType> getInternalFixes() {
// TODO smoothen the track before returning it, or construct a smoothening "view" onto it
@SuppressWarnings("unchecked")
NavigableSet<FixType> result = (NavigableSet<FixType>) fixes;
return result;
}
/**
* Iterates the fixes in the order of their time points
* Iterates the fixes with outliers getting skipped, in the order of their time points
*/
@SuppressWarnings("unchecked")
@Override
public Iterable<FixType> getFixes() {
// TODO skip outliers in iterable returned
return (Iterable<FixType>) Collections.unmodifiableSet(fixes);
}
/**
* Iterates over the raw sequence of fixes, all potential outliers included
*/
@SuppressWarnings("unchecked")
@Override
public Iterable<FixType> getRawFixes() {
return (Iterable<FixType>) Collections.unmodifiableSet(fixes);
}
@@ -55,13 +75,13 @@ public abstract class TrackImpl<FixType extends Timed> implements Track<FixType>
@SuppressWarnings("unchecked")
@Override
public FixType getFirstFixAtOrAfter(TimePoint timePoint) {
public FixType getFirstRawFixAtOrAfter(TimePoint timePoint) {
return (FixType) fixes.ceiling(new DummyTimed(timePoint));
}
@SuppressWarnings("unchecked")
@Override
public FixType getLastFixBefore(TimePoint timePoint) {
public FixType getLastRawFixBefore(TimePoint timePoint) {
return (FixType) fixes.lower(new DummyTimed(timePoint));
}
@@ -73,7 +93,7 @@ public abstract class TrackImpl<FixType extends Timed> implements Track<FixType>
@SuppressWarnings("unchecked")
@Override
public FixType getFirstFix() {
public FixType getFirstRawFix() {
if (fixes.isEmpty()) {
return null;
} else {
@@ -83,7 +103,7 @@ public abstract class TrackImpl<FixType extends Timed> implements Track<FixType>
@SuppressWarnings("unchecked")
@Override
public FixType getLastFix() {
public FixType getLastRawFix() {
if (fixes.isEmpty()) {
return null;
} else {
@@ -107,7 +107,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
timePointToUse = getMarkPassingForLegEnd().getTimePoint();
} else {
// use time point of latest fix
GPSFixMoving lastFix = getTrackedRace().getTrack(getCompetitor()).getLastFix();
GPSFixMoving lastFix = getTrackedRace().getTrack(getCompetitor()).getLastRawFix();
if (lastFix != null) {
timePointToUse = lastFix.getTimePoint();
} else {
@@ -51,7 +51,7 @@ public class WindTrackImpl extends TrackImpl<Wind> implements WindTrack {
@Override
public void add(Wind wind) {
getInternalFixes().add(wind);
getInternalRawFixes().add(wind);
notifyListenersAboutReceive(wind);
}
@@ -165,7 +165,7 @@ public class WindTrackImpl extends TrackImpl<Wind> implements WindTrack {
@Override
public String toString() {
StringBuilder result = new StringBuilder();
for (Wind wind : getFixes()) {
for (Wind wind : getRawFixes()) {
result.append(wind);
result.append(" avg(");
result.append(millisecondsOverWhichToAverage);
@@ -178,7 +178,7 @@ public class WindTrackImpl extends TrackImpl<Wind> implements WindTrack {
public String toCSV() {
StringBuilder result = new StringBuilder();
for (Wind wind : getFixes()) {
for (Wind wind : getRawFixes()) {
append(result, wind);
Wind estimate = getEstimatedWind(wind.getPosition(), wind.getTimePoint());
append(result, estimate);
@@ -245,7 +245,8 @@ public class WindTrackImpl extends TrackImpl<Wind> implements WindTrack {
@Override
public void remove(Wind wind) {
getInternalFixes().remove(wind);
getInternalRawFixes().remove(wind);
notifyListenersAboutRemoval(wind);
}
}
@@ -254,7 +254,7 @@ public class UDPExpeditionReceiverTest {
if (m.getTrueWind() != null) {
Declination declination = declinationService.getDeclination(m.getTimePoint(), lastKnownPosition,
/* timeoutForOnlineFetchInMilliseconds */5000);
for (Wind recordedWind : race.getWindTrack().getFixes()) {
for (Wind recordedWind : race.getWindTrack().getRawFixes()) {
if (Math.abs(m.getTrueWindBearing().getDegrees() + declination.getBearingCorrectedTo(m.getTimePoint()).getDegrees() -
recordedWind.getBearing().getDegrees()) <= 0.0000001) {
matched.add(recordedWind);
@@ -86,7 +86,7 @@ public class TestStoringAndRetrievingWindTracks extends AbstractTracTracLiveTest
WindTrack result = DomainObjectFactory.INSTANCE.loadWindTrack(domainEvent, race, windSource, /* millisecondsOverWhichToAverage */
30000, database);
double myBearingDeg = 123.4;
for (Wind wind : result.getFixes()) {
for (Wind wind : result.getRawFixes()) {
assertEquals(pos, wind.getPosition());
assertEquals(10., wind.getKnots(), 0.000000000001);
assertEquals(myBearingDeg, wind.getBearing().getDegrees(), 0.000000001);