fixed maneuver detection where angle of next-next DP result was used instead of next

This commit is contained in:
Axel Uhl committed 2011-12-05 14:40:43 +01:00
1 parent f3ff85d983
commit d6592c6863
3 files changed
+26 -16

No files matched your search

@@ -21,7 +21,7 @@ public class BoatClassImpl extends NamedImpl implements BoatClass {
public BoatClassImpl(String name) { public BoatClassImpl(String name) {
super(name); super(name);
approximateManeuverDurationInMilliseconds = 10000; approximateManeuverDurationInMilliseconds = 5000; // as discussed with Dennis Gehrlein
} }
@Override @Override
@@ -63,6 +63,9 @@ public class DouglasPeucker<ItemType, FixType extends GPSFix> {
* including the last fix at or before time <code>to</code> that approximates the {@link #track} such that * including the last fix at or before time <code>to</code> that approximates the {@link #track} such that
* the maximum distance of any fix on the {@link #track} to the approximation is less than * the maximum distance of any fix on the {@link #track} to the approximation is less than
* <code>maxDistance</code>. Always returns a non-<code>null</code> list which may, however, be empty. * <code>maxDistance</code>. Always returns a non-<code>null</code> list which may, however, be empty.
* Note, that if the fixes contain bearing information, the bearing is not the bearing leading to the
* next fix of the approximation but the bearing the tracked item had at the point in time of the
* approximation fix.
*/ */
public List<FixType> approximate(Distance maxDistance, TimePoint from, TimePoint to) { public List<FixType> approximate(Distance maxDistance, TimePoint from, TimePoint to) {
List<FixType> resultWithoutFirstFix = approximateWithoutFirst(maxDistance, from, to); List<FixType> resultWithoutFirstFix = approximateWithoutFirst(maxDistance, from, to);
@@ -644,14 +644,18 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
} }
/** /**
* Tries to detect a maneuver on the <code>competitor</code>'s track around a given time point. The time period is * Tries to detect maneuvers on the <code>competitor</code>'s track based on a number of approximating fixes. The
* taken from the {@link BoatClass#getApproximateManeuverDurationInMilliseconds() boat class}. If no maneuver is * fixes contain bearing information, but this is not the bearing leading to the next approximation fix but the
* detected, an empty list is returned. Maneuvers can only be expected to be detected if at least three fixes are * bearing the boat had at the time of the approximating fix which is taken from the original track.
* provided in <code>approximatedFixesToAnalyze</code>. For the inner approximating fixes (all except the first and *
* the last approximating fix), their course changes according to the approximated path (and not the underlying * The time period assumed for a maneuver duration is taken from the
* actual tracked fixes) are computed. Subsequent course changes to the same direction are then grouped. Those in * {@link BoatClass#getApproximateManeuverDurationInMilliseconds() boat class}. If no maneuver is detected, an empty
* closer timely distance than {@link #getApproximateManeuverDurationInMilliseconds()} (including single course * list is returned. Maneuvers can only be expected to be detected if at least three fixes are provided in
* changes that have no surrounding other course changes to group) are grouped into one {@link Maneuver}. * <code>approximatedFixesToAnalyze</code>. For the inner approximating fixes (all except the first and the last
* approximating fix), their course changes according to the approximated path (and not the underlying actual
* tracked fixes) are computed. Subsequent course changes to the same direction are then grouped. Those in closer
* timely distance than {@link #getApproximateManeuverDurationInMilliseconds()} (including single course changes
* that have no surrounding other course changes to group) are grouped into one {@link Maneuver}.
* *
* @return an empty list if no maneuver is detected for <code>competitor</code> between <code>from</code> and * @return an empty list if no maneuver is detected for <code>competitor</code> between <code>from</code> and
* <code>to</code>, or else the list of maneuvers detected. * <code>to</code>, or else the list of maneuvers detected.
@@ -660,15 +664,17 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
List<Maneuver> result = new ArrayList<Maneuver>(); List<Maneuver> result = new ArrayList<Maneuver>();
if (approximatingFixesToAnalyze.size() > 2) { if (approximatingFixesToAnalyze.size() > 2) {
List<Pair<GPSFixMoving, CourseChange>> courseChangeSequenceInSameDirection = new ArrayList<Pair<GPSFixMoving, CourseChange>>(); List<Pair<GPSFixMoving, CourseChange>> courseChangeSequenceInSameDirection = new ArrayList<Pair<GPSFixMoving, CourseChange>>();
Iterator<GPSFixMoving> iter = approximatingFixesToAnalyze.iterator(); Iterator<GPSFixMoving> approximationPointsIter = approximatingFixesToAnalyze.iterator();
GPSFixMoving previous = iter.next(); GPSFixMoving previous = approximationPointsIter.next();
GPSFixMoving current = iter.next(); GPSFixMoving current = approximationPointsIter.next();
// the bearings in these variables are between approximation points
SpeedWithBearing speedWithBearingFromPreviousToCurrent = previous.getSpeedAndBearingRequiredToReach(current); SpeedWithBearing speedWithBearingFromPreviousToCurrent = previous.getSpeedAndBearingRequiredToReach(current);
SpeedWithBearing speedWithBearingAtBeginningOfUnidirectionalCourseChanges = speedWithBearingFromPreviousToCurrent; SpeedWithBearing speedWithBearingAtBeginningOfUnidirectionalCourseChanges = speedWithBearingFromPreviousToCurrent;
SpeedWithBearing speedWithBearingFromCurrentToNext; // will certainly be assigned because iter's collection's size > 2 SpeedWithBearing speedWithBearingFromCurrentToNext; // will certainly be assigned because iter's collection's size > 2
do { do {
GPSFixMoving next = iter.next(); GPSFixMoving next = approximationPointsIter.next();
speedWithBearingFromCurrentToNext = current.getSpeedAndBearingRequiredToReach(next); speedWithBearingFromCurrentToNext = current.getSpeedAndBearingRequiredToReach(next);
// compute course change on "approximation track"
CourseChange courseChange = speedWithBearingFromPreviousToCurrent.getCourseChangeRequiredToReach(speedWithBearingFromCurrentToNext); CourseChange courseChange = speedWithBearingFromPreviousToCurrent.getCourseChangeRequiredToReach(speedWithBearingFromCurrentToNext);
Pair<GPSFixMoving, CourseChange> courseChangeAtFix = new Pair<GPSFixMoving, CourseChange>(current, courseChange); Pair<GPSFixMoving, CourseChange> courseChangeAtFix = new Pair<GPSFixMoving, CourseChange>(current, courseChange);
if (!courseChangeSequenceInSameDirection.isEmpty() && if (!courseChangeSequenceInSameDirection.isEmpty() &&
@@ -685,7 +691,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
previous = current; previous = current;
current = next; current = next;
speedWithBearingFromPreviousToCurrent = speedWithBearingFromCurrentToNext; speedWithBearingFromPreviousToCurrent = speedWithBearingFromCurrentToNext;
} while (iter.hasNext()); } while (approximationPointsIter.hasNext());
if (!courseChangeSequenceInSameDirection.isEmpty()) { if (!courseChangeSequenceInSameDirection.isEmpty()) {
result.addAll(groupChangesInSameDirectionIntoManeuvers(competitor, speedWithBearingAtBeginningOfUnidirectionalCourseChanges, result.addAll(groupChangesInSameDirectionIntoManeuvers(competitor, speedWithBearingAtBeginningOfUnidirectionalCourseChanges,
courseChangeSequenceInSameDirection)); courseChangeSequenceInSameDirection));
@@ -722,10 +728,10 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
Iterator<Pair<GPSFixMoving, CourseChange>> iter = courseChangeSequenceInSameDirection.iterator(); Iterator<Pair<GPSFixMoving, CourseChange>> iter = courseChangeSequenceInSameDirection.iterator();
double totalCourseChangeInDegrees = 0.0; double totalCourseChangeInDegrees = 0.0;
long totalMilliseconds = 0l; long totalMilliseconds = 0l;
SpeedWithBearing afterCurrentCourseChange; // sure to be set because iter's collection is not empty SpeedWithBearing afterCurrentCourseChange = null; // sure to be set because iter's collection is not empty
// and the first use requires group not to be empty which can only happen after the first group.add
do { do {
Pair<GPSFixMoving, CourseChange> currentFixAndCourseChange = iter.next(); Pair<GPSFixMoving, CourseChange> currentFixAndCourseChange = iter.next();
afterCurrentCourseChange = beforeCurrentCourseChange.applyCourseChange(currentFixAndCourseChange.getB());
if (!group.isEmpty() if (!group.isEmpty()
&& currentFixAndCourseChange.getA().getTimePoint().asMillis() - group.get(group.size() - 1).getA().getTimePoint().asMillis() > && currentFixAndCourseChange.getA().getTimePoint().asMillis() - group.get(group.size() - 1).getA().getTimePoint().asMillis() >
getApproximateManeuverDurationInMilliseconds()) { getApproximateManeuverDurationInMilliseconds()) {
@@ -738,6 +744,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
totalMilliseconds = 0l; totalMilliseconds = 0l;
beforeGroup = beforeCurrentCourseChange; beforeGroup = beforeCurrentCourseChange;
} }
afterCurrentCourseChange = beforeCurrentCourseChange.applyCourseChange(currentFixAndCourseChange.getB());
totalMilliseconds += currentFixAndCourseChange.getA().getTimePoint().asMillis(); totalMilliseconds += currentFixAndCourseChange.getA().getTimePoint().asMillis();
totalCourseChangeInDegrees += currentFixAndCourseChange.getB().getCourseChangeInDegrees(); totalCourseChangeInDegrees += currentFixAndCourseChange.getB().getCourseChangeInDegrees();
group.add(currentFixAndCourseChange); group.add(currentFixAndCourseChange);