java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CourseChangeBasedTrackApproximation.java
... ...
@@ -85,13 +85,15 @@ public class CourseChangeBasedTrackApproximation implements Serializable, GPSTra
85 85
* We need to remember the speed / bearing as we saw them when we inserted the fixes into the {@link #window}
86 86
* collection. Based on more fixes getting added to the track, things may change. In particular, fixes that may have
87 87
* had a valid speed when inserted may later have their cached speed/bearing invalidated, and computing it again
88
- * from the track may then yield {@code null}.
88
+ * from the track may then yield {@code null}.<p>
89
+ *
90
+ * TODO bug6209: the above observation regarding changes when later fixes get added is exactly what is causing the bug6209 issues!
89 91
*/
90 92
private final LinkedList<SpeedWithBearing> speedForFixesInWindow;
91 93
92 94
/**
93 95
* one shorter than "window"; {@link #totalCourseChangeFromBeginningOfWindow}{@code [i]} is from
94
- * {@link #window}{@code [i]} to {@link #window}{@code [i+1]}
96
+ * {@link #window}{@code [0]} to {@link #window}{@code [i+1]}
95 97
*/
96 98
private final List<Double> totalCourseChangeFromBeginningOfWindow;
97 99
... ...
@@ -154,8 +156,9 @@ public class CourseChangeBasedTrackApproximation implements Serializable, GPSTra
154 156
GPSFixMoving add(GPSFixMoving next) {
155 157
assert window.isEmpty() || !next.getTimePoint().before(window.peekFirst().getTimePoint());
156 158
final GPSFixMoving result;
157
- final SpeedWithBearing nextSpeed = next.isEstimatedSpeedCached() ? next.getCachedEstimatedSpeed() : track.getEstimatedSpeed(next.getTimePoint());
158
- if (nextSpeed != null) {
159
+ final SpeedWithBearing nextSpeed = /* TODO this was the original code that can depend on fixes newer than next: next.isEstimatedSpeedCached() ? next.getCachedEstimatedSpeed() : track.getEstimatedSpeed(next.getTimePoint()) */
160
+ next.getSpeed(); int TODO; // TODO bug6209: try without dependency on newer fixes and see if it helps produce equal results for early/late initialization
161
+ if (nextSpeed != null) { // TODO bug6209: this gets messy... if we drop a fix because no estimated speed can be determined for it, and later fix additions may change this, where would we get this fix from again?
159 162
numberOfFixesAdded++;
160 163
int insertPosition = window.size();
161 164
GPSFixMoving previous;
... ...
@@ -179,18 +182,20 @@ public class CourseChangeBasedTrackApproximation implements Serializable, GPSTra
179 182
// rather expensive ceil/floor search on the track; resort to track.getEstimatedSpeed if not cached
180 183
assert previousSpeed != null; // we wouldn't have added the fix in the previous run if it hadn't had a valid speed
181 184
final double courseChangeBetweenPreviousAndNextInDegrees = previousSpeed.getBearing().getDifferenceTo(nextSpeed.getBearing()).getDegrees();
182
- windowDuration = windowDuration.plus(previous.getTimePoint().until(next.getTimePoint()));
185
+ if (insertPosition == window.size()-1) { // if not appended to the end, the window duration won't change
186
+ windowDuration = windowDuration.plus(previous.getTimePoint().until(next.getTimePoint()));
187
+ }
183 188
if (totalCourseChangeFromBeginningOfWindow.isEmpty()) {
184 189
totalCourseChangeFromBeginningOfWindow.add(courseChangeBetweenPreviousAndNextInDegrees);
185 190
absoluteMaximumTotalCourseChangeFromBeginningOfWindowInDegrees = Math.abs(courseChangeBetweenPreviousAndNextInDegrees);
186 191
indexOfMaximumTotalCourseChange = 0;
187 192
} else {
188
- final double totalCourseChangeFromBeginningOfWindowForCurrentFix = totalCourseChangeFromBeginningOfWindow.get(totalCourseChangeFromBeginningOfWindow.size()-1)
193
+ final double totalCourseChangeFromBeginningOfWindowForCurrentFix = totalCourseChangeFromBeginningOfWindow.get(insertPosition-2)
189 194
+ courseChangeBetweenPreviousAndNextInDegrees;
190
- totalCourseChangeFromBeginningOfWindow.add(totalCourseChangeFromBeginningOfWindowForCurrentFix);
195
+ totalCourseChangeFromBeginningOfWindow.add(insertPosition-1, totalCourseChangeFromBeginningOfWindowForCurrentFix);
191 196
if (Math.abs(totalCourseChangeFromBeginningOfWindowForCurrentFix) > absoluteMaximumTotalCourseChangeFromBeginningOfWindowInDegrees) {
192 197
absoluteMaximumTotalCourseChangeFromBeginningOfWindowInDegrees = Math.abs(totalCourseChangeFromBeginningOfWindowForCurrentFix);
193
- indexOfMaximumTotalCourseChange = totalCourseChangeFromBeginningOfWindow.size()-1;
198
+ indexOfMaximumTotalCourseChange = insertPosition-1;
194 199
}
195 200
}
196 201
if (windowDuration.compareTo(getMaximumWindowLength()) > 0) {
java/com.sap.sailing.windestimation.test/src/com/sap/sailing/windestimation/integration/IncrementalMstHmmWindEstimationForTrackedRaceTest.java
... ...
@@ -124,19 +124,23 @@ public class IncrementalMstHmmWindEstimationForTrackedRaceTest extends OnlineTra
124 124
new URL("file:///" + new File("resources/event_20110609_KielerWoch-505_Race_2.txt").getCanonicalPath()),
125 125
/* liveUri */ null, /* storedUri */ storedUri,
126 126
new ReceiverType[] { ReceiverType.MARKPASSINGS, ReceiverType.RACECOURSE, ReceiverType.RAWPOSITIONS, ReceiverType.MARKPOSITIONS });
127
- final MillisecondsTimePoint timePointForFixes = new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23, 10, 00).getTime());
127
+ final GregorianCalendar cal = new GregorianCalendar(2011, 05, 23, 13, 40);
128
+ cal.setTimeZone(TimeZone.getTimeZone("UTC"));
129
+ final MillisecondsTimePoint timePointForFixes = new MillisecondsTimePoint(cal.getTime());
128 130
final WindSourceWithAdditionalID testWindSource = new WindSourceWithAdditionalID(WindSourceType.EXPEDITION, "Test");
129 131
getTrackedRace().getOrCreateWindTrack(testWindSource).add(
130 132
new WindImpl(new DegreePosition(54.48448470246412, 10.185846456327479),
131
- timePointForFixes, new KnotSpeedWithBearingImpl(12.5, /* to */ new DegreeBearingImpl(60))));
132
- final MillisecondsTimePoint timePointForFixes2 = new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23, 10, 30).getTime());
133
+ timePointForFixes, new KnotSpeedWithBearingImpl(9, /* to */ new DegreeBearingImpl(51))));
134
+ cal.set(2011, 05, 23, 14, 6);
135
+ final MillisecondsTimePoint timePointForFixes2 = new MillisecondsTimePoint(cal.getTime());
133 136
getTrackedRace().getOrCreateWindTrack(testWindSource).add(
134 137
new WindImpl(new DegreePosition(54.48448470246412, 10.185846456327479),
135
- timePointForFixes2, new KnotSpeedWithBearingImpl(11.5, /* to */ new DegreeBearingImpl(58))));
136
- final MillisecondsTimePoint timePointForFixes3 = new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23, 10, 45).getTime());
138
+ timePointForFixes2, new KnotSpeedWithBearingImpl(11, /* to */ new DegreeBearingImpl(60))));
139
+ cal.set(2011, 05, 23, 14, 35);
140
+ final MillisecondsTimePoint timePointForFixes3 = new MillisecondsTimePoint(cal.getTime());
137 141
getTrackedRace().getOrCreateWindTrack(testWindSource).add(
138 142
new WindImpl(new DegreePosition(54.4844847, 10.1858464),
139
- timePointForFixes3, new KnotSpeedWithBearingImpl(12.1, /* to */ new DegreeBearingImpl(59))));
143
+ timePointForFixes3, new KnotSpeedWithBearingImpl(14, /* to */ new DegreeBearingImpl(58))));
140 144
final PolarDataServiceImpl polarDataService = new PolarDataServiceImpl();
141 145
getTrackedRace().setPolarDataService(polarDataService);
142 146
polarDataService.insertExistingFixes(getTrackedRace());