mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-21 05:05:31 +00:00
Merge branch 'master' of /home/trac/git
This commit is contained in:
+13
-2
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.maneuverdetection.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
@@ -14,12 +15,15 @@ public class ManeuverCurveBoundaryExtension {
|
||||
private final TimePoint extensionTimePoint;
|
||||
private final SpeedWithBearing speedWithBearingAtExtensionTimePoint;
|
||||
private final double courseChangeInDegreesWithinExtensionArea;
|
||||
private final Speed lowestSpeedWithinExtensionArea;
|
||||
|
||||
public ManeuverCurveBoundaryExtension(TimePoint extensionTimePoint, SpeedWithBearing speedWithBearingAtExtensionTimePoint,
|
||||
double totalCourseChangeInDegreesExtension) {
|
||||
public ManeuverCurveBoundaryExtension(TimePoint extensionTimePoint,
|
||||
SpeedWithBearing speedWithBearingAtExtensionTimePoint, double totalCourseChangeInDegreesExtension,
|
||||
Speed lowestSpeedWithinExtensionArea) {
|
||||
this.extensionTimePoint = extensionTimePoint;
|
||||
this.speedWithBearingAtExtensionTimePoint = speedWithBearingAtExtensionTimePoint;
|
||||
this.courseChangeInDegreesWithinExtensionArea = totalCourseChangeInDegreesExtension;
|
||||
this.lowestSpeedWithinExtensionArea = lowestSpeedWithinExtensionArea;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,4 +54,11 @@ public class ManeuverCurveBoundaryExtension {
|
||||
public double getCourseChangeInDegreesWithinExtensionArea() {
|
||||
return courseChangeInDegreesWithinExtensionArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets lowest speed within extension area.
|
||||
*/
|
||||
public Speed getLowestSpeedWithinExtensionArea() {
|
||||
return lowestSpeedWithinExtensionArea;
|
||||
}
|
||||
}
|
||||
+8
-6
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.maneuverdetection.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.tracking.ManeuverCurveBoundaries;
|
||||
import com.sap.sailing.domain.tracking.impl.ManeuverCurveBoundariesImpl;
|
||||
@@ -17,8 +18,9 @@ public class ManeuverCurveDetails extends ManeuverCurveBoundariesImpl {
|
||||
|
||||
public ManeuverCurveDetails(TimePoint timePointBefore, TimePoint timePointAfter, TimePoint timePoint,
|
||||
SpeedWithBearing speedWithBearingBefore, SpeedWithBearing speedWithBearingAfter,
|
||||
double directionChangeInDegrees, double maxAngularVelocityInDegreesPerSecond) {
|
||||
super(timePointBefore, timePointAfter, speedWithBearingBefore, speedWithBearingAfter, directionChangeInDegrees);
|
||||
double directionChangeInDegrees, double maxAngularVelocityInDegreesPerSecond, Speed lowestSpeed) {
|
||||
super(timePointBefore, timePointAfter, speedWithBearingBefore, speedWithBearingAfter, directionChangeInDegrees,
|
||||
lowestSpeed);
|
||||
this.timePoint = timePoint;
|
||||
this.maxAngularVelocityInDegreesPerSecond = maxAngularVelocityInDegreesPerSecond;
|
||||
}
|
||||
@@ -34,7 +36,7 @@ public class ManeuverCurveDetails extends ManeuverCurveBoundariesImpl {
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximal angular velocity recorded within the curve which was recorded at {@link #getTimePoint()}.
|
||||
* Gets the maximal angular velocity recorded within the curve which was recorded at {@link #getTimePoint()}.
|
||||
*
|
||||
* @return The maximal angular velocity in degrees per second
|
||||
*/
|
||||
@@ -42,8 +44,8 @@ public class ManeuverCurveDetails extends ManeuverCurveBoundariesImpl {
|
||||
return maxAngularVelocityInDegreesPerSecond;
|
||||
}
|
||||
|
||||
public ManeuverCurveBoundaries extractEnteringAndExistingDetailsOnly() {
|
||||
return new ManeuverCurveBoundariesImpl(getTimePointBefore(), getTimePointAfter(),
|
||||
getSpeedWithBearingBefore(), getSpeedWithBearingAfter(), getDirectionChangeInDegrees());
|
||||
public ManeuverCurveBoundaries extractCurveBoundariesOnly() {
|
||||
return new ManeuverCurveBoundariesImpl(getTimePointBefore(), getTimePointAfter(), getSpeedWithBearingBefore(),
|
||||
getSpeedWithBearingAfter(), getDirectionChangeInDegrees(), getLowestSpeed());
|
||||
}
|
||||
}
|
||||
+6
-4
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.maneuverdetection.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.tracking.SpeedWithBearingStepsIterable;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
@@ -13,15 +14,16 @@ import com.sap.sse.common.TimePoint;
|
||||
public class ManeuverCurveDetailsWithBearingSteps extends ManeuverCurveDetails {
|
||||
|
||||
private final SpeedWithBearingStepsIterable speedWithBearingSteps;
|
||||
|
||||
|
||||
public ManeuverCurveDetailsWithBearingSteps(TimePoint timePointBefore, TimePoint timePointAfter,
|
||||
TimePoint timePoint, SpeedWithBearing speedWithBearingBefore, SpeedWithBearing speedWithBearingAfter,
|
||||
double directionChangeInDegrees, double maxAngularVelocityInDegreesPerSecond, SpeedWithBearingStepsIterable speedWithBearingSteps) {
|
||||
double directionChangeInDegrees, double maxAngularVelocityInDegreesPerSecond, Speed lowestSpeed,
|
||||
SpeedWithBearingStepsIterable speedWithBearingSteps) {
|
||||
super(timePointBefore, timePointAfter, timePoint, speedWithBearingBefore, speedWithBearingAfter,
|
||||
directionChangeInDegrees, maxAngularVelocityInDegreesPerSecond);
|
||||
directionChangeInDegrees, maxAngularVelocityInDegreesPerSecond, lowestSpeed);
|
||||
this.speedWithBearingSteps = speedWithBearingSteps;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the list of bearing steps which was used for computation of curve details.
|
||||
*
|
||||
|
||||
+88
-42
@@ -19,6 +19,7 @@ import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.NauticalSide;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
@@ -433,8 +434,8 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
sideToWhichWaypointWasPassed = maneuverDirection;
|
||||
// produce an additional mark passing maneuver; continue to analyze to catch jibe sets and kiwi drops
|
||||
maneuvers.add(new MarkPassingManeuverImpl(ManeuverType.MARK_PASSING, tackAfterManeuver, markPassingPosition,
|
||||
maneuverLoss, markPassingTimePoint, maneuverMainCurveDetails.extractEnteringAndExistingDetailsOnly(),
|
||||
maneuverDetails.extractEnteringAndExistingDetailsOnly(),
|
||||
maneuverLoss, markPassingTimePoint, maneuverMainCurveDetails.extractCurveBoundariesOnly(),
|
||||
maneuverDetails.extractCurveBoundariesOnly(),
|
||||
maneuverMainCurveDetails.getMaxAngularVelocityInDegreesPerSecond(), waypointPassed,
|
||||
sideToWhichWaypointWasPassed));
|
||||
} else {
|
||||
@@ -502,14 +503,14 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
refinedPenaltyDetails = computeManeuverDetails(refinedPenaltyMainCurveDetails,
|
||||
maneuverDetails.getTimePointBefore(), firstPenaltyCircleCompletedAt);
|
||||
}
|
||||
maneuverLoss = getManeuverLoss(maneuverDetails.getTimePointBefore(),
|
||||
maneuverDetails.getTimePoint(), firstPenaltyCircleCompletedAt);
|
||||
maneuverLoss = getManeuverLoss(maneuverDetails.getTimePointBefore(), maneuverDetails.getTimePoint(),
|
||||
firstPenaltyCircleCompletedAt);
|
||||
Position penaltyPosition = competitorTrack.getEstimatedPosition(refinedPenaltyDetails.getTimePoint(),
|
||||
/* extrapolate */ false);
|
||||
final Maneuver maneuver = new ManeuverWithStableSpeedAndCourseBoundariesImpl(maneuverType,
|
||||
tackAfterManeuver, penaltyPosition, maneuverLoss, refinedPenaltyDetails.getTimePoint(),
|
||||
refinedPenaltyMainCurveDetails.extractEnteringAndExistingDetailsOnly(),
|
||||
refinedPenaltyDetails.extractEnteringAndExistingDetailsOnly(),
|
||||
refinedPenaltyMainCurveDetails.extractCurveBoundariesOnly(),
|
||||
refinedPenaltyDetails.extractCurveBoundariesOnly(),
|
||||
refinedPenaltyMainCurveDetails.getMaxAngularVelocityInDegreesPerSecond());
|
||||
maneuvers.add(maneuver);
|
||||
// after we've "consumed" one tack and one jibe, recursively find more maneuvers if tacks and/or jibes
|
||||
@@ -523,12 +524,12 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
final Maneuver maneuver;
|
||||
if (numberOfTacks > 0 || numberOfJibes > 0) {
|
||||
maneuverType = numberOfTacks > 0 ? ManeuverType.TACK : ManeuverType.JIBE;
|
||||
maneuverLoss = getManeuverLoss(maneuverDetails.getTimePointBefore(),
|
||||
maneuverDetails.getTimePoint(), maneuverDetails.getTimePointAfter());
|
||||
maneuverLoss = getManeuverLoss(maneuverDetails.getTimePointBefore(), maneuverDetails.getTimePoint(),
|
||||
maneuverDetails.getTimePointAfter());
|
||||
maneuver = new ManeuverWithStableSpeedAndCourseBoundariesImpl(maneuverType, tackAfterManeuver,
|
||||
maneuverPosition, maneuverLoss, maneuverDetails.getTimePoint(),
|
||||
maneuverMainCurveDetails.extractEnteringAndExistingDetailsOnly(),
|
||||
maneuverDetails.extractEnteringAndExistingDetailsOnly(),
|
||||
maneuverMainCurveDetails.extractCurveBoundariesOnly(),
|
||||
maneuverDetails.extractCurveBoundariesOnly(),
|
||||
maneuverMainCurveDetails.getMaxAngularVelocityInDegreesPerSecond());
|
||||
} else if (wind != null) {
|
||||
// heading up or bearing away
|
||||
@@ -543,18 +544,18 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
// either HEAD_UP or BEAR_AWAY
|
||||
maneuver = new ManeuverWithMainCurveBoundariesImpl(maneuverType, tackAfterManeuver,
|
||||
maneuverPosition, maneuverLoss, maneuverDetails.getTimePoint(),
|
||||
maneuverMainCurveDetails.extractEnteringAndExistingDetailsOnly(),
|
||||
maneuverDetails.extractEnteringAndExistingDetailsOnly(),
|
||||
maneuverMainCurveDetails.extractCurveBoundariesOnly(),
|
||||
maneuverDetails.extractCurveBoundariesOnly(),
|
||||
maneuverMainCurveDetails.getMaxAngularVelocityInDegreesPerSecond());
|
||||
} else {
|
||||
// no wind information; marking as UNKNOWN
|
||||
maneuverType = ManeuverType.UNKNOWN;
|
||||
maneuverLoss = getManeuverLoss(maneuverDetails.getTimePointBefore(),
|
||||
maneuverDetails.getTimePoint(), maneuverDetails.getTimePointAfter());
|
||||
maneuver = new ManeuverWithStableSpeedAndCourseBoundariesImpl(maneuverType, tackAfterManeuver, maneuverPosition,
|
||||
maneuverLoss, maneuverDetails.getTimePoint(),
|
||||
maneuverMainCurveDetails.extractEnteringAndExistingDetailsOnly(),
|
||||
maneuverDetails.extractEnteringAndExistingDetailsOnly(),
|
||||
maneuverLoss = getManeuverLoss(maneuverDetails.getTimePointBefore(), maneuverDetails.getTimePoint(),
|
||||
maneuverDetails.getTimePointAfter());
|
||||
maneuver = new ManeuverWithStableSpeedAndCourseBoundariesImpl(maneuverType, tackAfterManeuver,
|
||||
maneuverPosition, maneuverLoss, maneuverDetails.getTimePoint(),
|
||||
maneuverMainCurveDetails.extractCurveBoundariesOnly(),
|
||||
maneuverDetails.extractCurveBoundariesOnly(),
|
||||
maneuverMainCurveDetails.getMaxAngularVelocityInDegreesPerSecond());
|
||||
}
|
||||
maneuvers.add(maneuver);
|
||||
@@ -582,21 +583,29 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
if (speedWhenSpeedStartedToDrop != null) {
|
||||
SpeedWithBearing speedAfterManeuver = track.getEstimatedSpeed(timePointWhenSpeedLevelledOffAfterManeuver);
|
||||
if (speedAfterManeuver != null) {
|
||||
// For upwind/downwind legs, find the mean course between inbound and outbound course and project actual and
|
||||
// For upwind/downwind legs, find the mean course between inbound and outbound course and project actual
|
||||
// and
|
||||
// extrapolated positions onto it:
|
||||
Bearing middleManeuverAngle = speedWhenSpeedStartedToDrop.getBearing().middle(speedAfterManeuver.getBearing());
|
||||
// extrapolate maximum speed before maneuver to time point of maximum speed after maneuver and project resulting position
|
||||
// onto the average maneuver course; compare to the projected position actually reached at the time point of maximum speed after
|
||||
Bearing middleManeuverAngle = speedWhenSpeedStartedToDrop.getBearing()
|
||||
.middle(speedAfterManeuver.getBearing());
|
||||
// extrapolate maximum speed before maneuver to time point of maximum speed after maneuver and project
|
||||
// resulting position
|
||||
// onto the average maneuver course; compare to the projected position actually reached at the time
|
||||
// point of maximum speed after
|
||||
// maneuver:
|
||||
Position positionWhenSpeedStartedToDrop = track.getEstimatedPosition(timePointWhenSpeedStartedToDrop, /* extrapolate */ false);
|
||||
Position extrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver =
|
||||
speedWhenSpeedStartedToDrop.travelTo(positionWhenSpeedStartedToDrop, timePointWhenSpeedStartedToDrop, timePointWhenSpeedLevelledOffAfterManeuver);
|
||||
Position actualPositionAtTimePointOfMaxSpeedAfterManeuver = track.getEstimatedPosition(timePointWhenSpeedLevelledOffAfterManeuver, /* extrapolate */ false);
|
||||
Position projectedExtrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver =
|
||||
extrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver.projectToLineThrough(positionWhenSpeedStartedToDrop, middleManeuverAngle);
|
||||
Position projectedActualPositionAtTimePointOfMaxSpeedAfterManeuver =
|
||||
actualPositionAtTimePointOfMaxSpeedAfterManeuver.projectToLineThrough(positionWhenSpeedStartedToDrop, middleManeuverAngle);
|
||||
result = projectedActualPositionAtTimePointOfMaxSpeedAfterManeuver.getDistance(projectedExtrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver);
|
||||
Position positionWhenSpeedStartedToDrop = track.getEstimatedPosition(timePointWhenSpeedStartedToDrop,
|
||||
/* extrapolate */ false);
|
||||
Position extrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver = speedWhenSpeedStartedToDrop.travelTo(
|
||||
positionWhenSpeedStartedToDrop, timePointWhenSpeedStartedToDrop,
|
||||
timePointWhenSpeedLevelledOffAfterManeuver);
|
||||
Position actualPositionAtTimePointOfMaxSpeedAfterManeuver = track
|
||||
.getEstimatedPosition(timePointWhenSpeedLevelledOffAfterManeuver, /* extrapolate */ false);
|
||||
Position projectedExtrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver = extrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver
|
||||
.projectToLineThrough(positionWhenSpeedStartedToDrop, middleManeuverAngle);
|
||||
Position projectedActualPositionAtTimePointOfMaxSpeedAfterManeuver = actualPositionAtTimePointOfMaxSpeedAfterManeuver
|
||||
.projectToLineThrough(positionWhenSpeedStartedToDrop, middleManeuverAngle);
|
||||
result = projectedActualPositionAtTimePointOfMaxSpeedAfterManeuver
|
||||
.getDistance(projectedExtrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
@@ -706,7 +715,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
maneuverMainCurveDetails.getSpeedWithBearingAfter(),
|
||||
maneuverMainCurveDetails.getDirectionChangeInDegrees(),
|
||||
maneuverMainCurveDetails.getMaxAngularVelocityInDegreesPerSecond(),
|
||||
maneuverMainCurveSpeedWithBearingSteps);
|
||||
maneuverMainCurveDetails.getLowestSpeed(), maneuverMainCurveSpeedWithBearingSteps);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -754,11 +763,20 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
double totalCourseChangeInDegrees = beforeManeuverSectionExtension.getCourseChangeInDegreesWithinExtensionArea()
|
||||
+ maneuverMainCurveDetails.getDirectionChangeInDegrees()
|
||||
+ afterManeuverSectionExtension.getCourseChangeInDegreesWithinExtensionArea();
|
||||
Speed lowestSpeed = maneuverMainCurveDetails.getLowestSpeed();
|
||||
if (lowestSpeed == null || beforeManeuverSectionExtension.getLowestSpeedWithinExtensionArea() != null
|
||||
&& lowestSpeed.compareTo(beforeManeuverSectionExtension.getLowestSpeedWithinExtensionArea()) > 0) {
|
||||
lowestSpeed = beforeManeuverSectionExtension.getLowestSpeedWithinExtensionArea();
|
||||
}
|
||||
if (lowestSpeed == null || afterManeuverSectionExtension.getLowestSpeedWithinExtensionArea() != null
|
||||
&& lowestSpeed.compareTo(afterManeuverSectionExtension.getLowestSpeedWithinExtensionArea()) > 0) {
|
||||
lowestSpeed = afterManeuverSectionExtension.getLowestSpeedWithinExtensionArea();
|
||||
}
|
||||
return new ManeuverCurveDetails(beforeManeuverSectionExtension.getExtensionTimePoint(),
|
||||
afterManeuverSectionExtension.getExtensionTimePoint(), maneuverMainCurveDetails.getTimePoint(),
|
||||
beforeManeuverSectionExtension.getSpeedWithBearingAtExtensionTimePoint(),
|
||||
afterManeuverSectionExtension.getSpeedWithBearingAtExtensionTimePoint(), totalCourseChangeInDegrees,
|
||||
maneuverMainCurveDetails.getMaxAngularVelocityInDegreesPerSecond());
|
||||
maneuverMainCurveDetails.getMaxAngularVelocityInDegreesPerSecond(), lowestSpeed);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -807,6 +825,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
}
|
||||
TimePoint stableBearingAnalysisUntil = maneuverStart == null ? maneuverMainCurveDetails.getTimePointBefore()
|
||||
: maneuverStart.getExtensionTimePoint();
|
||||
Speed lowestSpeed = maneuverStart == null ? null : maneuverStart.getLowestSpeedWithinExtensionArea();
|
||||
double courseChangeSinceManeuverMainCurveInDegrees = maneuverStart == null ? 0
|
||||
: maneuverStart.getCourseChangeInDegreesWithinExtensionArea();
|
||||
stepsToAnalyze = getSpeedWithBearingStepsWithinTimeRange(stepsToAnalyze, earliestTimePointForSpeedTrendAnalysis,
|
||||
@@ -818,14 +837,19 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
maneuverStart = stableBearingExtension;
|
||||
courseChangeSinceManeuverMainCurveInDegrees += stableBearingExtension
|
||||
.getCourseChangeInDegreesWithinExtensionArea();
|
||||
if (lowestSpeed == null
|
||||
|| lowestSpeed.compareTo(stableBearingExtension.getLowestSpeedWithinExtensionArea()) > 0) {
|
||||
lowestSpeed = stableBearingExtension.getLowestSpeedWithinExtensionArea();
|
||||
}
|
||||
}
|
||||
return maneuverStart != null
|
||||
? new ManeuverCurveBoundaryExtension(maneuverStart.getExtensionTimePoint(),
|
||||
maneuverStart.getSpeedWithBearingAtExtensionTimePoint(),
|
||||
courseChangeSinceManeuverMainCurveInDegrees
|
||||
+ maneuverStart.getCourseChangeInDegreesWithinExtensionArea())
|
||||
+ maneuverStart.getCourseChangeInDegreesWithinExtensionArea(),
|
||||
lowestSpeed)
|
||||
: new ManeuverCurveBoundaryExtension(maneuverMainCurveDetails.getTimePointBefore(),
|
||||
maneuverMainCurveDetails.getSpeedWithBearingBefore(), 0);
|
||||
maneuverMainCurveDetails.getSpeedWithBearingBefore(), 0, null);
|
||||
}
|
||||
|
||||
private boolean isCourseChangeLimitExceededForCurveExtension(
|
||||
@@ -887,6 +911,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
}
|
||||
TimePoint stableBearingAnalysisFrom = maneuverEnd == null ? maneuverMainCurveDetails.getTimePointAfter()
|
||||
: maneuverEnd.getExtensionTimePoint();
|
||||
Speed lowestSpeed = maneuverEnd == null ? null : maneuverEnd.getLowestSpeedWithinExtensionArea();
|
||||
double courseChangeSinceManeuverMainCurveInDegrees = maneuverEnd == null ? 0
|
||||
: maneuverEnd.getCourseChangeInDegreesWithinExtensionArea();
|
||||
stepsToAnalyze = getSpeedWithBearingStepsWithinTimeRange(stepsToAnalyze, stableBearingAnalysisFrom,
|
||||
@@ -898,11 +923,17 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
maneuverEnd = stableBearingExtension;
|
||||
courseChangeSinceManeuverMainCurveInDegrees += stableBearingExtension
|
||||
.getCourseChangeInDegreesWithinExtensionArea();
|
||||
if (lowestSpeed == null
|
||||
|| lowestSpeed.compareTo(stableBearingExtension.getLowestSpeedWithinExtensionArea()) > 0) {
|
||||
lowestSpeed = stableBearingExtension.getLowestSpeedWithinExtensionArea();
|
||||
}
|
||||
}
|
||||
return maneuverEnd != null ? new ManeuverCurveBoundaryExtension(maneuverEnd.getExtensionTimePoint(),
|
||||
maneuverEnd.getSpeedWithBearingAtExtensionTimePoint(), courseChangeSinceManeuverMainCurveInDegrees)
|
||||
return maneuverEnd != null
|
||||
? new ManeuverCurveBoundaryExtension(maneuverEnd.getExtensionTimePoint(),
|
||||
maneuverEnd.getSpeedWithBearingAtExtensionTimePoint(),
|
||||
courseChangeSinceManeuverMainCurveInDegrees, lowestSpeed)
|
||||
: new ManeuverCurveBoundaryExtension(maneuverMainCurveDetails.getTimePointAfter(),
|
||||
maneuverMainCurveDetails.getSpeedWithBearingAfter(), 0);
|
||||
maneuverMainCurveDetails.getSpeedWithBearingAfter(), 0, null);
|
||||
}
|
||||
|
||||
protected Duration getMaxDurationForAfterManeuverSectionExtension(Duration approximateManeuverDuration) {
|
||||
@@ -947,6 +978,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
SpeedWithBearingStep stepWithMaxSpeed = null;
|
||||
double courseChangeSinceMainCurveBeforeSpeedMaximumInDegrees = 0;
|
||||
double courseChangeAfterStepWithSpeedMaximum = 0;
|
||||
Speed lowestSpeed = null;
|
||||
|
||||
for (SpeedWithBearingStep speedWithBearingStep : finalStepsToAnalyze) {
|
||||
courseChangeAfterStepWithSpeedMaximum += speedWithBearingStep.getCourseChangeInDegrees();
|
||||
@@ -963,6 +995,9 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
courseChangeSinceMainCurveBeforeSpeedMaximumInDegrees += courseChangeAfterStepWithSpeedMaximum;
|
||||
courseChangeAfterStepWithSpeedMaximum = 0;
|
||||
}
|
||||
if (lowestSpeed == null || lowestSpeed.compareTo(speedWithBearingStep.getSpeedWithBearing()) > 0) {
|
||||
lowestSpeed = speedWithBearingStep.getSpeedWithBearing();
|
||||
}
|
||||
}
|
||||
previousSpeedInKnots = speedInKnots;
|
||||
}
|
||||
@@ -974,7 +1009,8 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
}
|
||||
return stepWithMaxSpeed == null ? null
|
||||
: new ManeuverCurveBoundaryExtension(stepWithMaxSpeed.getTimePoint(),
|
||||
stepWithMaxSpeed.getSpeedWithBearing(), courseChangeSinceMainCurveBeforeSpeedMaximumInDegrees);
|
||||
stepWithMaxSpeed.getSpeedWithBearing(), courseChangeSinceMainCurveBeforeSpeedMaximumInDegrees,
|
||||
lowestSpeed);
|
||||
}
|
||||
|
||||
private Iterable<SpeedWithBearingStep> cloneAndReverseIterable(SpeedWithBearingStepsIterable stepsToAnalyze) {
|
||||
@@ -1014,6 +1050,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
SpeedWithBearingStep previousStep = null;
|
||||
SpeedWithBearingStep stepUntilStableBearing = null;
|
||||
double courseChangeUntilStepWithStableBearingInDegrees = 0;
|
||||
Speed lowestSpeed = null;
|
||||
|
||||
for (SpeedWithBearingStep currentStep : finalStepsToAnalyze) {
|
||||
if (previousStep != null) {
|
||||
@@ -1024,6 +1061,9 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lowestSpeed == null || lowestSpeed.compareTo(currentStep.getSpeedWithBearing()) > 0) {
|
||||
lowestSpeed = currentStep.getSpeedWithBearing();
|
||||
}
|
||||
courseChangeUntilStepWithStableBearingInDegrees += currentStep.getCourseChangeInDegrees();
|
||||
previousStep = currentStep;
|
||||
}
|
||||
@@ -1032,7 +1072,8 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
}
|
||||
return stepUntilStableBearing == null ? null
|
||||
: new ManeuverCurveBoundaryExtension(stepUntilStableBearing.getTimePoint(),
|
||||
stepUntilStableBearing.getSpeedWithBearing(), courseChangeUntilStepWithStableBearingInDegrees);
|
||||
stepUntilStableBearing.getSpeedWithBearing(), courseChangeUntilStepWithStableBearingInDegrees,
|
||||
lowestSpeed);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1058,6 +1099,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
double maxCourseChangeInDegrees = 0;
|
||||
double currentCourseChangeInDegrees = 0;
|
||||
double maxAngularVelocityInDegreesPerSecond = 0;
|
||||
Speed lowestSpeed = null;
|
||||
TimePoint maneuverTimePoint = null;
|
||||
TimePoint previousTimePoint = null;
|
||||
// Refine the time point before and after maneuver by checking whether the total course changed before maneuver
|
||||
@@ -1079,7 +1121,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
refinedTimePointAfterManeuver = timePoint;
|
||||
refinedSpeedWithBearingAfterManeuver = entry.getSpeedWithBearing();
|
||||
}
|
||||
// Check whether the course change is performed in the target direction of maneuver. If yes, check consider
|
||||
// Check whether the course change is performed in the target direction of maneuver. If yes, consider
|
||||
// the step to locate the maneuver time point with the highest angular velocity within main curve.
|
||||
if (0 < currentCourseChangeInDegrees * totalCourseChangeSignum) {
|
||||
if (maxAngularVelocityInDegreesPerSecond < entry.getAngularVelocityInDegreesPerSecond()) {
|
||||
@@ -1088,6 +1130,9 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
maneuverTimePoint = previousTimePoint.plus(durationFromPreviousStep.divide(2.0));
|
||||
}
|
||||
}
|
||||
if (lowestSpeed == null || lowestSpeed.compareTo(entry.getSpeedWithBearing()) > 0) {
|
||||
lowestSpeed = entry.getSpeedWithBearing();
|
||||
}
|
||||
// If the direction sign does not match, or the angular velocity at the beginning of the curve is nearly
|
||||
// zero => cut the bearing step from the left
|
||||
if (0 >= currentCourseChangeInDegrees * totalCourseChangeSignum
|
||||
@@ -1102,6 +1147,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
angularVelocityMinimumReachedAtMainCurveBeginning = false;
|
||||
maneuverTimePoint = null;
|
||||
maxAngularVelocityInDegreesPerSecond = 0;
|
||||
lowestSpeed = entry.getSpeedWithBearing();
|
||||
} else {
|
||||
angularVelocityMinimumReachedAtMainCurveBeginning = true;
|
||||
}
|
||||
@@ -1121,7 +1167,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
|
||||
ManeuverCurveDetails maneuverEnteringAndExitingDetails = new ManeuverCurveDetails(
|
||||
refinedTimePointBeforeManeuver, refinedTimePointAfterManeuver, maneuverTimePoint,
|
||||
refinedSpeedWithBearingBeforeManeuver, refinedSpeedWithBearingAfterManeuver, maxCourseChangeInDegrees,
|
||||
maxAngularVelocityInDegreesPerSecond);
|
||||
maxAngularVelocityInDegreesPerSecond, lowestSpeed);
|
||||
return maneuverEnteringAndExitingDetails;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.tracking;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
@@ -81,7 +82,7 @@ public interface Maneuver extends GPSFix {
|
||||
* Gets time points and speeds with bearings before and after the maneuver, such that the speed and course before
|
||||
* and after the maneuver are considered as stable.
|
||||
*
|
||||
* @return Entering and existing details of maneuver section, with stable speed and bearing before and after that
|
||||
* @return Entering and exiting details of maneuver section, with stable speed and bearing before and after that
|
||||
* section
|
||||
* @see Maneuver
|
||||
*/
|
||||
@@ -93,7 +94,7 @@ public interface Maneuver extends GPSFix {
|
||||
* {@link #getManeuverCurveWithStableSpeedAndCourseBoundaries()}. The former is considered for HEAD_UP and BEAR_AWAY
|
||||
* maneuvers, whereas the latter is considered for the remainder.
|
||||
*
|
||||
* @return Entering and existing details of maneuver
|
||||
* @return Entering and exiting details of maneuver
|
||||
*/
|
||||
ManeuverCurveBoundaries getManeuverBoundaries();
|
||||
|
||||
@@ -135,4 +136,9 @@ public interface Maneuver extends GPSFix {
|
||||
@Statistic(messageKey = "DirectionChange", resultDecimals = 2, ordinal = 2)
|
||||
double getDirectionChangeInDegrees();
|
||||
|
||||
/**
|
||||
* Gets lowest speed recorded within {@link #getManeuverBoundaries()}.
|
||||
*/
|
||||
Speed getLowestSpeed();
|
||||
|
||||
}
|
||||
|
||||
+8
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.tracking;
|
||||
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
@@ -48,4 +49,11 @@ public interface ManeuverCurveBoundaries {
|
||||
*/
|
||||
double getDirectionChangeInDegrees();
|
||||
|
||||
/**
|
||||
* Gets the lowest speed sailed within the maneuver curve.
|
||||
*
|
||||
* @return The lowest speed within maneuver curve
|
||||
*/
|
||||
Speed getLowestSpeed();
|
||||
|
||||
}
|
||||
|
||||
+11
-2
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.tracking.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.tracking.ManeuverCurveBoundaries;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
@@ -14,15 +15,17 @@ public class ManeuverCurveBoundariesImpl implements ManeuverCurveBoundaries {
|
||||
private final SpeedWithBearing speedWithBearingBefore;
|
||||
private final SpeedWithBearing speedWithBearingAfter;
|
||||
private final double directionChangeInDegrees;
|
||||
private final Speed lowestSpeed;
|
||||
|
||||
public ManeuverCurveBoundariesImpl(TimePoint timePointBefore, TimePoint timePointAfter,
|
||||
SpeedWithBearing speedWithBearingBefore, SpeedWithBearing speedWithBearingAfter,
|
||||
double directionChangeInDegrees) {
|
||||
double directionChangeInDegrees, Speed lowestSpeed) {
|
||||
this.timePointBefore = timePointBefore;
|
||||
this.timePointAfter = timePointAfter;
|
||||
this.speedWithBearingBefore = speedWithBearingBefore;
|
||||
this.speedWithBearingAfter = speedWithBearingAfter;
|
||||
this.directionChangeInDegrees = directionChangeInDegrees;
|
||||
this.lowestSpeed = lowestSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,10 +53,16 @@ public class ManeuverCurveBoundariesImpl implements ManeuverCurveBoundaries {
|
||||
return directionChangeInDegrees;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getLowestSpeed() {
|
||||
return lowestSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Starting at time point " + timePointBefore + ", ending at time point " + timePointAfter
|
||||
+ ". Speed before curve " + speedWithBearingBefore + " speed after curve " + speedWithBearingAfter
|
||||
+ ". Course changed by " + directionChangeInDegrees + "deg.";
|
||||
+ ". Lowest speed within curve: " + lowestSpeed + ". Course changed by " + directionChangeInDegrees
|
||||
+ "deg.";
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.tracking.impl;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.common.tracking.impl.AbstractGPSFixImpl;
|
||||
@@ -89,6 +90,11 @@ public abstract class ManeuverImpl extends AbstractGPSFixImpl implements Maneuve
|
||||
return getManeuverBoundaries().getSpeedWithBearingAfter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getLowestSpeed() {
|
||||
return getManeuverBoundaries().getLowestSpeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " " + type + " on new tack " + newTack + " on position " + position
|
||||
|
||||
+2
@@ -20,6 +20,7 @@ public class ManeuverCurveBoundariesJsonSerializer implements JsonSerializer<Man
|
||||
public static final String COG_AFTER_IN_TRUE_DEGREES = "cogAfterInTrueDegrees";
|
||||
public static final String DIRECTION_CHANGE_IN_DEGREES = "directionChangeInDegrees";
|
||||
public static final String DURATION_IN_MILLIS = "durationInMillis";
|
||||
public static final String LOWEST_SPEED_IN_KNOTS = "lowestSpeedInKnots";
|
||||
|
||||
@Override
|
||||
public JSONObject serialize(ManeuverCurveBoundaries curveBoundaries) {
|
||||
@@ -36,6 +37,7 @@ public class ManeuverCurveBoundariesJsonSerializer implements JsonSerializer<Man
|
||||
: curveBoundaries.getSpeedWithBearingAfter().getBearing().getDegrees());
|
||||
result.put(DIRECTION_CHANGE_IN_DEGREES, curveBoundaries.getDirectionChangeInDegrees());
|
||||
result.put(DURATION_IN_MILLIS, curveBoundaries.getTimePointBefore().until(curveBoundaries.getTimePointAfter()).asMillis());
|
||||
result.put(LOWEST_SPEED_IN_KNOTS, curveBoundaries.getLowestSpeed().getKnots());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -16,6 +16,7 @@ public class ManeuverJsonSerializer implements JsonSerializer<Maneuver> {
|
||||
public static final String MANEUVER_LOSS = "maneuverLoss";
|
||||
public static final String POSITION_AND_TIME = "positionAndTime";
|
||||
public static final String MAX_ANGULAR_VELOCITY_IN_DEGREES_PER_SECOND = "maxAngularVelocityInDegreesPerSecond";
|
||||
public static final String LOWEST_SPEED_IN_KNOTS = "lowestSpeedInKnots";
|
||||
|
||||
private final GPSFixJsonSerializer gpsFixSerializer;
|
||||
private final DistanceJsonSerializer distanceSerializer;
|
||||
@@ -44,6 +45,7 @@ public class ManeuverJsonSerializer implements JsonSerializer<Maneuver> {
|
||||
maneuver.getManeuverLoss() == null ? null : distanceSerializer.serialize(maneuver.getManeuverLoss()));
|
||||
result.put(POSITION_AND_TIME, gpsFixSerializer.serialize(maneuver));
|
||||
result.put(MAX_ANGULAR_VELOCITY_IN_DEGREES_PER_SECOND, maneuver.getMaxAngularVelocityInDegreesPerSecond());
|
||||
result.put(LOWEST_SPEED_IN_KNOTS, maneuver.getLowestSpeed().getKnots());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user