Merge both tacks in polar service

This commit is contained in:
Frederik Petersen committed 2015-05-28 14:24:32 +02:00
1 parent 2ea762b756
commit 18ec962a05
13 files changed
+89 -109

No files matched your search

@@ -173,12 +173,11 @@ public interface PolarDataService {
*
* @param boatClass
* @param legType
* @param tack
* @return The estimating function for the tack and legtype combination estimating boatspeed over windspeed for the
* given boat class. All values in kn.
* @throws NotEnoughDataHasBeenAddedException
*/
PolynomialFunction getSpeedRegressionFunction(BoatClass boatClass, LegType legType, Tack tack) throws NotEnoughDataHasBeenAddedException;
PolynomialFunction getSpeedRegressionFunction(BoatClass boatClass, LegType legType) throws NotEnoughDataHasBeenAddedException;
/**
* This method is not intended to be used directly apart from debugging purposes. If you intend to use the polar service please
@@ -186,12 +185,11 @@ public interface PolarDataService {
*
* @param boatClass
* @param legType
* @param tack
* @return The estimating function for the tack and legtype combination estimating true wind angle over windspeed for the
* given boat class. TWA in degrees and windspeeds in knots.
* @throws NotEnoughDataHasBeenAddedException
*/
PolynomialFunction getAngleRegressionFunction(BoatClass boatClass, LegType legType, Tack tack) throws NotEnoughDataHasBeenAddedException;
PolynomialFunction getAngleRegressionFunction(BoatClass boatClass, LegType legType) throws NotEnoughDataHasBeenAddedException;
/**
* This method is not intended to be used directly apart from debugging purposes. If you intend to use the polar service please
@@ -10,6 +10,7 @@ import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence;
import com.sap.sailing.domain.base.SpeedWithConfidence;
import com.sap.sailing.domain.base.impl.SpeedWithBearingWithConfidenceImpl;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.ManeuverType;
@@ -20,6 +21,7 @@ import com.sap.sailing.domain.common.Tack;
import com.sap.sailing.domain.common.confidence.BearingWithConfidence;
import com.sap.sailing.domain.common.confidence.impl.BearingWithConfidenceImpl;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
import com.sap.sailing.domain.polars.PolarDataService;
@@ -60,9 +62,19 @@ public class PolarDataServiceImpl implements PolarDataService {
}
@Override
public SpeedWithBearingWithConfidence<Void> getAverageSpeedWithBearing(BoatClass boatClass,
Speed windSpeed, LegType legType, Tack tack, boolean useRegressionForSpeed) throws NotEnoughDataHasBeenAddedException {
return polarDataMiner.getAverageSpeedAndCourseOverGround(boatClass, windSpeed, legType, tack, useRegressionForSpeed);
public SpeedWithBearingWithConfidence<Void> getAverageSpeedWithBearing(BoatClass boatClass, Speed windSpeed,
LegType legType, Tack tack, boolean useRegressionForSpeed) throws NotEnoughDataHasBeenAddedException {
SpeedWithBearingWithConfidence<Void> averageSpeedAndCourseOverGround = polarDataMiner
.getAverageSpeedAndCourseOverGround(boatClass, windSpeed, legType, useRegressionForSpeed);
if ((tack == Tack.PORT && legType == LegType.UPWIND) || (tack == Tack.STARBOARD && legType == LegType.DOWNWIND)) {
DegreeBearingImpl bearing = new DegreeBearingImpl(-averageSpeedAndCourseOverGround.getObject().getBearing()
.getDegrees());
KnotSpeedWithBearingImpl speed = new KnotSpeedWithBearingImpl(averageSpeedAndCourseOverGround.getObject()
.getKnots(), bearing);
averageSpeedAndCourseOverGround = new SpeedWithBearingWithConfidenceImpl<Void>(speed,
averageSpeedAndCourseOverGround.getConfidence(), null);
}
return averageSpeedAndCourseOverGround;
}
@@ -139,15 +151,15 @@ public class PolarDataServiceImpl implements PolarDataService {
}
@Override
public PolynomialFunction getSpeedRegressionFunction(BoatClass boatClass, LegType legType, Tack tack)
public PolynomialFunction getSpeedRegressionFunction(BoatClass boatClass, LegType legType)
throws NotEnoughDataHasBeenAddedException {
return polarDataMiner.getSpeedRegressionFunction(boatClass, legType, tack);
return polarDataMiner.getSpeedRegressionFunction(boatClass, legType);
}
@Override
public PolynomialFunction getAngleRegressionFunction(BoatClass boatClass, LegType legType, Tack tack)
public PolynomialFunction getAngleRegressionFunction(BoatClass boatClass, LegType legType)
throws NotEnoughDataHasBeenAddedException {
return polarDataMiner.getAngleRegressionFunction(boatClass, legType, tack);
return polarDataMiner.getAngleRegressionFunction(boatClass, legType);
}
@Override
@@ -171,14 +183,9 @@ public class PolarDataServiceImpl implements PolarDataService {
if (boatClass == null || windSpeed == null) {
throw new IllegalArgumentException("Boatclass and windspeed cannot be null.");
}
SpeedWithBearingWithConfidence<Void> port = getAverageSpeedWithBearing(boatClass, windSpeed, legType, Tack.PORT);
SpeedWithBearingWithConfidence<Void> starboard = getAverageSpeedWithBearing(boatClass, windSpeed, legType,
Tack.STARBOARD);
double angleSumInDeg = Math.abs(port.getObject().getBearing().getDegrees())
+ Math.abs(starboard.getObject().getBearing().getDegrees());
Bearing bearing = new DegreeBearingImpl(angleSumInDeg);
double confidence = (port.getConfidence() + starboard.getConfidence()) / 2;
BearingWithConfidence<Void> bearingWithConfidence = new BearingWithConfidenceImpl<Void>(bearing, confidence,
SpeedWithBearingWithConfidence<Void> speed = polarDataMiner.getAverageSpeedAndCourseOverGround(boatClass, windSpeed, legType, true);
Bearing bearing = new DegreeBearingImpl(speed.getObject().getBearing().getDegrees() * 2);
BearingWithConfidence<Void> bearingWithConfidence = new BearingWithConfidenceImpl<Void>(bearing, speed.getConfidence(),
null);
return bearingWithConfidence;
}
@@ -8,9 +8,11 @@ import org.apache.commons.math.analysis.polynomials.PolynomialFunction;
import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence;
import com.sap.sailing.domain.base.impl.SpeedWithBearingWithConfidenceImpl;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.LegType;
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.confidence.BearingWithConfidence;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
@@ -30,7 +32,7 @@ public class AngleAndSpeedRegression {
private double maxWindSpeedInKnots = -1;
public void addData(WindWithConfidence<Pair<Position, TimePoint>> windSpeed,
BearingWithConfidence<Integer> angleToTheWind, SpeedWithBearingWithConfidence<TimePoint> boatSpeed) {
BearingWithConfidence<Void> angleToTheWind, SpeedWithBearingWithConfidence<TimePoint> boatSpeed) {
double windSpeedInKnots = windSpeed.getObject().getKnots();
if (windSpeedInKnots > maxWindSpeedInKnots) {
maxWindSpeedInKnots = windSpeedInKnots;
@@ -51,7 +53,7 @@ public class AngleAndSpeedRegression {
return new SpeedWithBearingWithConfidenceImpl<Void>(speedWithBearing, Math.min(1, speedRegression.getNumberOfAddedPoints() / 100.0), null);
}
public Set<SpeedWithBearingWithConfidence<Void>> estimateTrueWindSpeedAndAngleCandidates(Speed speedOverGround) throws NotEnoughDataHasBeenAddedException {
public Set<SpeedWithBearingWithConfidence<Void>> estimateTrueWindSpeedAndAngleCandidates(Speed speedOverGround, LegType legType, Tack tack) throws NotEnoughDataHasBeenAddedException {
double[] coefficiants = speedRegression.getOrCreatePolynomialFunction().getCoefficients();
CubicEquation equation = new CubicEquation(coefficiants[2], coefficiants[1], coefficiants[0], -speedOverGround.getKnots());
@@ -64,6 +66,9 @@ public class AngleAndSpeedRegression {
boolean angleFound;
try {
angle = angleRegression.getOrCreatePolynomialFunction().value(windSpeedCandidateInKnots);
if ((tack == Tack.PORT && legType == LegType.UPWIND) || (tack == Tack.STARBOARD && legType == LegType.DOWNWIND)) {
angle = -angle;
}
angleFound = true;
} catch(NotEnoughDataHasBeenAddedException e) {
angleFound = false;
@@ -45,12 +45,13 @@ public class CubicRegressionPerCourseProcessor implements Processor<GroupedDataE
regressions.put(key, regression);
}
}
regression.addData(fix.getWind(), fix.getAngleToTheWind(), fix.getBoatSpeed());
regression.addData(fix.getWind(), fix.getAbsoluteAngleToTheWind(), fix.getBoatSpeed());
}
}
public SpeedWithBearingWithConfidence<Void> getAverageSpeedAndCourseOverGround(BoatClass boatClass, Speed windSpeed, LegType legType, Tack tack) throws NotEnoughDataHasBeenAddedException {
GroupKey key = createGroupKey(boatClass, legType, tack);
public SpeedWithBearingWithConfidence<Void> getAverageSpeedAndCourseOverGround(BoatClass boatClass,
Speed windSpeed, LegType legType) throws NotEnoughDataHasBeenAddedException {
GroupKey key = createGroupKey(boatClass, legType);
SpeedWithBearingWithConfidence<Void> estimatedSpeedAndAngle = null;
if (regressions.containsKey(key)) {
estimatedSpeedAndAngle = regressions.get(key).estimateSpeedAndAngle(windSpeed);
@@ -62,11 +63,11 @@ public class CubicRegressionPerCourseProcessor implements Processor<GroupedDataE
public Set<SpeedWithBearingWithConfidence<Void>> estimateTrueWindSpeedAndAngleCandidates(BoatClass boatClass,
Speed speedOverGround, LegType legType, Tack tack) {
GroupKey key = createGroupKey(boatClass, legType, tack);
GroupKey key = createGroupKey(boatClass, legType);
Set<SpeedWithBearingWithConfidence<Void>> result = new HashSet<>();
if (regressions.containsKey(key)) {
try {
result = regressions.get(key).estimateTrueWindSpeedAndAngleCandidates(speedOverGround);
result = regressions.get(key).estimateTrueWindSpeedAndAngleCandidates(speedOverGround, legType, tack);
} catch (NotEnoughDataHasBeenAddedException e) {
// Return empty result
}
@@ -76,20 +77,14 @@ public class CubicRegressionPerCourseProcessor implements Processor<GroupedDataE
return result;
}
private GroupKey createGroupKey(final BoatClass boatClass, final LegType legType,
final Tack tack) {
TackAndLegTypePolarClusterKey key = new TackAndLegTypePolarClusterKey() {
private GroupKey createGroupKey(final BoatClass boatClass, final LegType legType) {
LegTypePolarClusterKey key = new LegTypePolarClusterKey() {
@Override
public BoatClass getBoatClass() {
return boatClass;
}
@Override
public Tack getTack() {
return tack;
}
@Override
public LegType getLegType() {
return legType;
@@ -106,9 +101,9 @@ public class CubicRegressionPerCourseProcessor implements Processor<GroupedDataE
return compoundKey;
}
public PolynomialFunction getSpeedRegressionFunction(BoatClass boatClass, LegType legType, Tack tack)
public PolynomialFunction getSpeedRegressionFunction(BoatClass boatClass, LegType legType)
throws NotEnoughDataHasBeenAddedException {
GroupKey key = createGroupKey(boatClass, legType, tack);
GroupKey key = createGroupKey(boatClass, legType);
PolynomialFunction polynomialFunction;
if (regressions.containsKey(key)) {
polynomialFunction = regressions.get(key).getSpeedRegressionFunction();
@@ -118,9 +113,9 @@ public class CubicRegressionPerCourseProcessor implements Processor<GroupedDataE
return polynomialFunction;
}
public PolynomialFunction getAngleRegressionFunction(BoatClass boatClass, LegType legType, Tack tack)
public PolynomialFunction getAngleRegressionFunction(BoatClass boatClass, LegType legType)
throws NotEnoughDataHasBeenAddedException {
GroupKey key = createGroupKey(boatClass, legType, tack);
GroupKey key = createGroupKey(boatClass, legType);
PolynomialFunction polynomialFunction;
if (regressions.containsKey(key)) {
polynomialFunction = regressions.get(key).getAngleRegressionFunction();
@@ -11,13 +11,12 @@ import com.sap.sailing.domain.common.LegType;
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.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.confidence.BearingWithConfidence;
import com.sap.sailing.domain.common.confidence.ConfidenceFactory;
import com.sap.sailing.domain.common.confidence.impl.BearingWithConfidenceImpl;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.TrackedLeg;
@@ -37,7 +36,7 @@ public class GPSFixMovingWithPolarContext implements MovingAveragePolarClusterKe
private final ClusterGroup<Speed> windSpeedClusterGroup;
private final Set<WindSource> windSourcesToExcludeForSpeed;
private final ClusterGroup<Bearing> angleClusterGroup;
private final BearingWithConfidence<Integer> trueWindAngle;
private final BearingWithConfidence<Void> absTrueWindAngle;
private final WindWithConfidence<Pair<Position, TimePoint>> wind;
private final SpeedWithBearingWithConfidence<TimePoint> boatSpeed;
private LegType legType;
@@ -50,7 +49,7 @@ public class GPSFixMovingWithPolarContext implements MovingAveragePolarClusterKe
this.windSpeedClusterGroup = windSpeedClusterGroup;
this.angleClusterGroup = angleClusterGroup;
this.windSourcesToExcludeForSpeed = collectWindSourcesToIgnoreForSpeed();
this.trueWindAngle = computeTrueWindAngle();
this.absTrueWindAngle = computeTrueWindAngleAbsolute();
this.wind = race.getWindWithConfidence(fix.getPosition(), fix.getTimePoint(), windSourcesToExcludeForSpeed);
this.boatSpeed = computeBoatSpeed();
}
@@ -67,19 +66,22 @@ public class GPSFixMovingWithPolarContext implements MovingAveragePolarClusterKe
return competitor;
}
public BearingWithConfidence<Integer> getAngleToTheWind() {
return trueWindAngle;
public BearingWithConfidence<Void> getAbsoluteAngleToTheWind() {
return absTrueWindAngle;
}
private BearingWithConfidence<Integer> computeTrueWindAngle() {
SpeedWithBearing boatSpeed = race.getTrack(competitor).getEstimatedSpeed(fix.getTimePoint());
private BearingWithConfidence<Void> computeTrueWindAngleAbsolute() {
BearingWithConfidenceImpl<Void> result = null;
Bearing bearing;
try {
Bearing realBearing = race.getCurrentLeg(competitor, fix.getTimePoint()).getBeatAngle(fix.getTimePoint());
bearing = new DegreeBearingImpl(Math.abs(realBearing.getDegrees()));
} catch (NoWindException e) {
bearing = null;
}
WindWithConfidence<Pair<Position, TimePoint>> wind = race.getWindWithConfidence(fix.getPosition(), fix.getTimePoint());
BearingWithConfidenceImpl<Integer> result = null;
if (wind != null && boatSpeed != null) {
Bearing bearing = boatSpeed.getBearing();
Bearing difference = wind.getObject().getFrom().getDifferenceTo(bearing);
result = new BearingWithConfidenceImpl<Integer>(difference, wind.getConfidence(), 0);
if (bearing != null && wind != null) {
result = new BearingWithConfidenceImpl<Void>(bearing, wind.getConfidence(), null);
}
return result;
}
@@ -135,15 +137,6 @@ public class GPSFixMovingWithPolarContext implements MovingAveragePolarClusterKe
return race.getRace().getBoatClass();
}
@Override
public Tack getTack() {
return getTack(getAngleToTheWind().getObject());
}
public static Tack getTack(Bearing angleDifferenceWindToBoat) {
return angleDifferenceWindToBoat.getDegrees() <= 0 ? Tack.PORT : Tack.STARBOARD;
}
@Override
public LegType getLegType() {
LegType result = null;
@@ -167,7 +160,7 @@ public class GPSFixMovingWithPolarContext implements MovingAveragePolarClusterKe
@Override
public Cluster<Bearing> getAngleCluster() {
return angleClusterGroup.getClusterFor(getAngleToTheWind().getObject());
return angleClusterGroup.getClusterFor(getAbsoluteAngleToTheWind().getObject());
}
}
@@ -1,13 +1,9 @@
package com.sap.sailing.polars.mining;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.Tack;
import com.sap.sse.datamining.shared.annotations.Dimension;
public interface TackAndLegTypePolarClusterKey extends BasePolarClusterKey {
@Dimension(messageKey = "tack")
Tack getTack();
public interface LegTypePolarClusterKey extends BasePolarClusterKey {
@Dimension(messageKey = "legType")
LegType getLegType();
@@ -4,7 +4,7 @@ import com.sap.sailing.domain.common.Speed;
import com.sap.sse.datamining.data.Cluster;
import com.sap.sse.datamining.shared.annotations.Dimension;
public interface MovingAveragePolarClusterKey extends TackAndLegTypePolarClusterKey {
public interface MovingAveragePolarClusterKey extends LegTypePolarClusterKey {
/**
*
@@ -6,14 +6,13 @@ import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.Speed;
import com.sap.sailing.domain.common.Tack;
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
public interface MovingAverageProcessor extends Processor<GroupedDataEntry<GPSFixMovingWithPolarContext>, Void>{
SpeedWithBearingWithConfidence<Void> getAverageSpeedAndCourseOverGround(BoatClass boatClass,
Speed windSpeed, LegType legType, Tack tack) throws NotEnoughDataHasBeenAddedException;
Speed windSpeed, LegType legType) throws NotEnoughDataHasBeenAddedException;
Set<BoatClass> getAvailableBoatClasses();
}
@@ -16,7 +16,6 @@ import com.sap.sailing.domain.common.LegType;
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.confidence.BearingWithConfidence;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
@@ -77,7 +76,7 @@ public class MovingAverageProcessorImpl implements MovingAverageProcessor {
averageAngleContainers.put(key, averageAngleContainer);
}
}
BearingWithConfidence<Integer> angleToTheWind = fix.getAngleToTheWind();
BearingWithConfidence<Void> angleToTheWind = fix.getAbsoluteAngleToTheWind();
WindWithConfidence<Pair<Position, TimePoint>> windSpeed = fix.getWind();
SpeedWithBearingWithConfidence<TimePoint> boatSpeedWithConfidence = fix.getBoatSpeed();
availableBoatClasses.add(element.getDataEntry().getBoatClass());
@@ -177,21 +176,20 @@ public class MovingAverageProcessorImpl implements MovingAverageProcessor {
@Override
public SpeedWithBearingWithConfidence<Void> getAverageSpeedAndCourseOverGround(BoatClass boatClass,
Speed windSpeed, LegType legType, Tack tack) throws NotEnoughDataHasBeenAddedException {
SpeedWithBearingWithConfidence<Void> result = estimateSpeedAndAngle(boatClass, windSpeed, legType, tack);
Speed windSpeed, LegType legType) throws NotEnoughDataHasBeenAddedException {
SpeedWithBearingWithConfidence<Void> result = estimateSpeedAndAngle(boatClass, windSpeed, legType);
return result;
}
private SpeedWithBearingWithConfidence<Void> estimateSpeedAndAngle(BoatClass boatClass, Speed windSpeed, LegType legType, Tack tack) throws NotEnoughDataHasBeenAddedException {
GroupKey key = createGroupKey(boatClass, windSpeed, legType, tack);
private SpeedWithBearingWithConfidence<Void> estimateSpeedAndAngle(BoatClass boatClass, Speed windSpeed, LegType legType) throws NotEnoughDataHasBeenAddedException {
GroupKey key = createGroupKey(boatClass, windSpeed, legType);
Bearing angleDiffTrueWindToBoat = estimateAngle(key);
SpeedWithConfidence<Void> estimatedSpeed = estimateBoatSpeed(key).getSpeedWithConfidence();
SpeedWithBearing speedWithBearing = new KnotSpeedWithBearingImpl(estimatedSpeed.getObject().getKnots(), angleDiffTrueWindToBoat);
return new SpeedWithBearingWithConfidenceImpl<Void>(speedWithBearing, estimatedSpeed.getConfidence(), null);
}
private GroupKey createGroupKey(final BoatClass boatClass, final Speed windSpeed, final LegType legType,
final Tack tack) {
private GroupKey createGroupKey(final BoatClass boatClass, final Speed windSpeed, final LegType legType) {
MovingAveragePolarClusterKey key = new MovingAveragePolarClusterKey() {
@Override
@@ -204,11 +202,6 @@ public class MovingAverageProcessorImpl implements MovingAverageProcessor {
return speedClusterGroup.getClusterFor(windSpeed);
}
@Override
public Tack getTack() {
return tack;
}
@Override
public LegType getLegType() {
return legType;
@@ -6,7 +6,6 @@ import java.util.Collection;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.Tack;
import com.sap.sse.datamining.data.Cluster;
import com.sap.sse.datamining.factories.FunctionFactory;
import com.sap.sse.datamining.functions.Function;
@@ -30,13 +29,9 @@ public class PolarDataDimensionCollectionFactory {
private static void addTackAndLegTypeDimensions(Collection<Function<?>> dimensions, FunctionFactory functionFactory)
throws NoSuchMethodException {
Function<Tack> tackFunction = functionFactory
.createMethodWrappingFunction(MovingAveragePolarClusterKey.class.getMethod("getTack",
new Class<?>[0]));
Function<LegType> legTypeFunction = functionFactory
.createMethodWrappingFunction(MovingAveragePolarClusterKey.class.getMethod("getLegType",
new Class<?>[0]));
dimensions.add(tackFunction);
dimensions.add(legTypeFunction);
}
@@ -38,8 +38,8 @@ import com.sap.sailing.domain.common.impl.PolarSheetGenerationSettingsImpl;
import com.sap.sailing.domain.common.impl.PolarSheetsDataImpl;
import com.sap.sailing.domain.common.impl.PolarSheetsHistogramDataImpl;
import com.sap.sailing.domain.common.impl.WindSpeedSteppingWithMaxDistance;
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.polars.impl.CubicEquation;
import com.sap.sse.datamining.components.FilterCriterion;
@@ -212,7 +212,7 @@ public class PolarDataMiner {
private ClusterGroup<Bearing> createAngleClusterGroup() {
return new BearingClusterGroup(-180, 180, 5);
return new BearingClusterGroup(0, 180, 5);
}
public void addFix(GPSFixMoving fix, Competitor competitor, TrackedRace trackedRace) {
@@ -392,24 +392,24 @@ public class PolarDataMiner {
}
public SpeedWithBearingWithConfidence<Void> getAverageSpeedAndCourseOverGround(BoatClass boatClass,
Speed windSpeed, LegType legType, Tack tack, boolean useRegressionForSpeed) throws NotEnoughDataHasBeenAddedException {
Speed windSpeed, LegType legType, boolean useRegressionForSpeed) throws NotEnoughDataHasBeenAddedException {
SpeedWithBearingWithConfidence<Void> averageSpeedAndCourseOverGround = null;
if (useRegressionForSpeed) {
averageSpeedAndCourseOverGround = cubicRegressionPerCourseProcessor.getAverageSpeedAndCourseOverGround(boatClass, windSpeed, legType, tack);
averageSpeedAndCourseOverGround = cubicRegressionPerCourseProcessor.getAverageSpeedAndCourseOverGround(boatClass, windSpeed, legType);
} else {
averageSpeedAndCourseOverGround = movingAverageProcessor.getAverageSpeedAndCourseOverGround(boatClass, windSpeed, legType, tack);
averageSpeedAndCourseOverGround = movingAverageProcessor.getAverageSpeedAndCourseOverGround(boatClass, windSpeed, legType);
}
return averageSpeedAndCourseOverGround;
}
public PolynomialFunction getSpeedRegressionFunction(BoatClass boatClass, LegType legType, Tack tack)
public PolynomialFunction getSpeedRegressionFunction(BoatClass boatClass, LegType legType)
throws NotEnoughDataHasBeenAddedException {
return cubicRegressionPerCourseProcessor.getSpeedRegressionFunction(boatClass, legType, tack);
return cubicRegressionPerCourseProcessor.getSpeedRegressionFunction(boatClass, legType);
}
public PolynomialFunction getAngleRegressionFunction(BoatClass boatClass, LegType legType, Tack tack)
public PolynomialFunction getAngleRegressionFunction(BoatClass boatClass, LegType legType)
throws NotEnoughDataHasBeenAddedException {
return cubicRegressionPerCourseProcessor.getAngleRegressionFunction(boatClass, legType, tack);
return cubicRegressionPerCourseProcessor.getAngleRegressionFunction(boatClass, legType);
}
public PolynomialFunction getSpeedRegressionFunction(BoatClass boatClass, double trueWindAngle)
@@ -69,7 +69,7 @@ public class PolarFixFilterCriteria implements FilterCriterion<GPSFixMovingWithP
}
private void checkForAbnormalFixesAndLog(GPSFixMovingWithPolarContext element) {
double twa = element.getAngleToTheWind().getObject().getDegrees();
double twa = element.getAbsoluteAngleToTheWind().getObject().getDegrees();
if (element.getLegType() == LegType.DOWNWIND) {
if (Math.abs(twa) < 100) {
logger.warning(String.format(
@@ -93,7 +93,7 @@ public class PolarFixFilterCriteria implements FilterCriterion<GPSFixMovingWithP
}
private boolean importantDataIsNotNull(GPSFixMovingWithPolarContext element) {
BearingWithConfidence<Integer> angleToTheWind = element.getAngleToTheWind();
BearingWithConfidence<Void> angleToTheWind = element.getAbsoluteAngleToTheWind();
WindWithConfidence<Pair<Position, TimePoint>> windSpeed = element.getWind();
SpeedWithBearingWithConfidence<TimePoint> boatSpeedWithConfidence = element.getBoatSpeed();
boolean result = false;
@@ -85,16 +85,15 @@ public class PolarResource extends AbstractSailingServerResource {
StringBuilder stringBuilder = new StringBuilder();
for (BoatClass boatClass : boatClasses) {
for (LegType legType : new LegType[] { LegType.UPWIND, LegType.DOWNWIND }) {
for (Tack tack : new Tack[] { Tack.PORT, Tack.STARBOARD }) {
try {
PolynomialFunction speedFunction = polarDataService.getSpeedRegressionFunction(boatClass, legType, tack);
stringBuilder.append("Speed: " + boatClass + " " + legType + " " + tack + ": " + speedFunction.toString() + "\n");
PolynomialFunction angleFunction = polarDataService.getAngleRegressionFunction(boatClass, legType, tack);
stringBuilder.append("Angle: " + boatClass + " " + legType + " " + tack + ": " + angleFunction.toString() + "\n");
} catch (NotEnoughDataHasBeenAddedException e) {
stringBuilder.append("No data for " + boatClass + " " + legType + " " + tack + "\n");
}
}
try {
PolynomialFunction speedFunction = polarDataService.getSpeedRegressionFunction(boatClass, legType);
stringBuilder.append("Speed: " + boatClass + " " + legType + ": " + speedFunction.toString() + "\n");
PolynomialFunction angleFunction = polarDataService.getAngleRegressionFunction(boatClass, legType);
stringBuilder.append("Angle: " + boatClass + " " + legType + ": " + angleFunction.toString() + "\n");
} catch (NotEnoughDataHasBeenAddedException e) {
stringBuilder.append("No data for " + boatClass + " " + legType + "\n");
}
}
for (double trueWindAngle = -177.5; trueWindAngle < 180; trueWindAngle = trueWindAngle + 5) {
try {