mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-01 08:40:52 +00:00
Only estimated wind is used for bearing in backend polars
This commit is contained in:
1 parent
4763026d86
commit
0b9843cb56
8 files changed
+102
-34
No files matched your search
+2
-2
@@ -5,9 +5,9 @@ import com.sap.sailing.domain.common.PolarSheetGenerationSettings;
|
||||
public class PolarSheetGenerationSettingsImpl implements PolarSheetGenerationSettings {
|
||||
|
||||
public static PolarSheetGenerationSettings createStandardPolarSettings() {
|
||||
Integer[] levels = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34 };
|
||||
Integer[] levels = { 4, 6, 8, 10, 12, 14, 16, 20, 25, 30 };
|
||||
WindSteppingWithMaxDistance windStepping = new WindSteppingWithMaxDistance(levels, 2.5);
|
||||
return new PolarSheetGenerationSettingsImpl(200, 0.1, 10, 20, 0.1, true, true, 2, 0.05, true, windStepping,
|
||||
return new PolarSheetGenerationSettingsImpl(50, 0.1, 20, 20, 0.1, true, true, 2, 0.05, true, windStepping,
|
||||
false);
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -121,7 +121,7 @@ public class PolarSheetsChartPanel extends DockLayoutPanel {
|
||||
createSeriesForWindspeed(seriesId, i, result.getStepping().getRawStepping()[i]);
|
||||
}
|
||||
Series series = seriesMap.get(seriesId)[i];
|
||||
series.setPoints(result.getAveragedPolarDataByWindSpeed()[i], false);
|
||||
//series.setPoints(result.getAveragedPolarDataByWindSpeed()[i], false);
|
||||
Point[] points = createPointsWithMarkerAlphaAccordingToDataCount(result, i);
|
||||
if (points != null) {
|
||||
series.setPoints(points);
|
||||
@@ -154,14 +154,16 @@ public class PolarSheetsChartPanel extends DockLayoutPanel {
|
||||
Point[] points = new Point[360];
|
||||
List<Integer> dataCountList = Arrays.asList(result.getDataCountPerAngleForWindspeed(windspeed));
|
||||
Integer max = Collections.max(dataCountList);
|
||||
if (max <= 0) {
|
||||
if (max < settings.getMinimumDataCountPerAngle()) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < 360; i++) {
|
||||
if (result.getHistogramDataMap().get(windspeed) == null
|
||||
|| result.getHistogramDataMap().get(windspeed).get(i) == null
|
||||
|| result.getHistogramDataMap().get(windspeed).get(i).getConfidenceMeasure() < settings
|
||||
.getMinimumConfidenceMeasure()) {
|
||||
.getMinimumConfidenceMeasure()
|
||||
|| result.getHistogramDataMap().get(windspeed).get(i).getDataCount() < settings
|
||||
.getMinimumDataCountPerAngle()) {
|
||||
points[i] = new Point(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
+34
-1
@@ -1,10 +1,15 @@
|
||||
package com.sap.sailing.polars.mining;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.Wind;
|
||||
@@ -17,6 +22,7 @@ public class GPSFixMovingWithPolarContext implements PolarClusterKey {
|
||||
private final TrackedRace race;
|
||||
private final Competitor competitor;
|
||||
private final ClusterGroup<Speed> windSpeedClusterGroup;
|
||||
private final Set<WindSource> windSourcesToExcludeForBearing;
|
||||
|
||||
public GPSFixMovingWithPolarContext(GPSFixMoving fix, TrackedRace race, Competitor competitor,
|
||||
ClusterGroup<Speed> windSpeedClusterGroup) {
|
||||
@@ -24,6 +30,7 @@ public class GPSFixMovingWithPolarContext implements PolarClusterKey {
|
||||
this.race = race;
|
||||
this.competitor = competitor;
|
||||
this.windSpeedClusterGroup = windSpeedClusterGroup;
|
||||
this.windSourcesToExcludeForBearing = collectWindSourcesToIgnoreForBearing();
|
||||
}
|
||||
|
||||
public GPSFixMoving getFix() {
|
||||
@@ -45,7 +52,7 @@ public class GPSFixMovingWithPolarContext implements PolarClusterKey {
|
||||
|
||||
public Bearing getAngleToTheWind() {
|
||||
SpeedWithBearing boatSpeed = race.getTrack(competitor).getEstimatedSpeed(fix.getTimePoint());
|
||||
Wind wind = race.getWind(fix.getPosition(), fix.getTimePoint());
|
||||
Wind wind = race.getWind(fix.getPosition(), fix.getTimePoint(), windSourcesToExcludeForBearing);
|
||||
Bearing bearing = boatSpeed.getBearing();
|
||||
return wind.getFrom().getDifferenceTo(bearing);
|
||||
}
|
||||
@@ -69,5 +76,31 @@ public class GPSFixMovingWithPolarContext implements PolarClusterKey {
|
||||
public BoatClass getBoatClass() {
|
||||
return race.getRace().getBoatClass();
|
||||
}
|
||||
|
||||
private Set<WindSource> collectWindSourcesToIgnoreForBearing() {
|
||||
Set<WindSource> windSourcesToExclude = new HashSet<WindSource>();
|
||||
Iterable<WindSource> combinedSources = race.getWindSources(WindSourceType.COMBINED);
|
||||
for (WindSource combinedSource : combinedSources) {
|
||||
windSourcesToExclude.add(combinedSource);
|
||||
}
|
||||
Iterable<WindSource> courseSources = race.getWindSources(WindSourceType.COURSE_BASED);
|
||||
for (WindSource courseSource : courseSources) {
|
||||
windSourcesToExclude.add(courseSource);
|
||||
}
|
||||
|
||||
Iterable<WindSource> expSources = race.getWindSources(WindSourceType.EXPEDITION);
|
||||
for (WindSource expSource : expSources) {
|
||||
windSourcesToExclude.add(expSource);
|
||||
}
|
||||
Iterable<WindSource> rcSources = race.getWindSources(WindSourceType.RACECOMMITTEE);
|
||||
for (WindSource rcSource : rcSources) {
|
||||
windSourcesToExclude.add(rcSource);
|
||||
}
|
||||
Iterable<WindSource> webSources = race.getWindSources(WindSourceType.WEB);
|
||||
for (WindSource webSource : webSources) {
|
||||
windSourcesToExclude.add(webSource);
|
||||
}
|
||||
return windSourcesToExclude;
|
||||
}
|
||||
|
||||
}
|
||||
+6
-2
@@ -13,6 +13,7 @@ import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
|
||||
import com.sap.sailing.polars.regression.BoatSpeedEstimator;
|
||||
import com.sap.sailing.polars.regression.NotEnoughDataHasBeenAddedException;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.datamining.AdditionalResultDataBuilder;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.data.Cluster;
|
||||
@@ -67,9 +68,10 @@ public class IncrementalRegressionProcessor implements Processor<GroupedDataEntr
|
||||
return null;
|
||||
}
|
||||
|
||||
public SpeedWithConfidence<Integer> estimateBoatSpeed(final BoatClass boatClass, final Speed windSpeed,
|
||||
public Pair<SpeedWithConfidence<Integer>, Integer> estimateBoatSpeed(final BoatClass boatClass, final Speed windSpeed,
|
||||
final Bearing angleToTheWind)
|
||||
throws NotEnoughDataHasBeenAddedException {
|
||||
int dataCount = 0;
|
||||
PolarClusterKey key = new PolarClusterKey() {
|
||||
@Override
|
||||
public RoundedAngleToTheWind getRoundedAngleToTheWind() {
|
||||
@@ -100,7 +102,9 @@ public class IncrementalRegressionProcessor implements Processor<GroupedDataEntr
|
||||
}
|
||||
KnotSpeedImpl speedWithoutConfidence = new KnotSpeedImpl(boatSpeedEstimator.estimateSpeed(windSpeed.getKnots(),
|
||||
angleToTheWind.getDegrees()));
|
||||
return new SpeedWithConfidenceImpl<Integer>(speedWithoutConfidence, /* FIXME */1.0, /* FIXME */0);
|
||||
dataCount = boatSpeedEstimator.getDataCount();
|
||||
return new Pair<SpeedWithConfidence<Integer>, Integer>(new SpeedWithConfidenceImpl<Integer>(
|
||||
speedWithoutConfidence, /* FIXME */1.0, /* FIXME */0), dataCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.sap.sailing.domain.common.impl.WindSteppingWithMaxDistance;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.polars.regression.NotEnoughDataHasBeenAddedException;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.data.ClusterGroup;
|
||||
@@ -111,7 +112,7 @@ public class PolarDataMiner {
|
||||
|
||||
public SpeedWithConfidence<Integer> estimateBoatSpeed(BoatClass boatClass, Speed windSpeed, Bearing angleToTheWind)
|
||||
throws NotEnoughDataHasBeenAddedException {
|
||||
return incrementalRegressionProcessor.estimateBoatSpeed(boatClass, windSpeed, angleToTheWind);
|
||||
return incrementalRegressionProcessor.estimateBoatSpeed(boatClass, windSpeed, angleToTheWind).getA();
|
||||
}
|
||||
|
||||
|
||||
@@ -119,41 +120,39 @@ public class PolarDataMiner {
|
||||
public PolarSheetsData createFullSheetForBoatClass(BoatClass boatClass) {
|
||||
Integer[] defaultWindSpeeds = defaultPolarSheetGenerationSettings.getWindStepping().getRawStepping();
|
||||
Number[][] averagedPolarDataByWindSpeed = new Number[defaultWindSpeeds.length][360];
|
||||
|
||||
Map<Integer, Integer[]> dataCountPerAngleForWindspeed = new HashMap<>();
|
||||
Map<Integer, Map<Integer, PolarSheetsHistogramData>> histogramDataMap = new HashMap<>();
|
||||
|
||||
int totalDataCount = 0;
|
||||
|
||||
for (int windIndex = 0; windIndex < defaultWindSpeeds.length; windIndex++) {
|
||||
Integer windSpeed = defaultWindSpeeds[windIndex];
|
||||
|
||||
Integer[] perAngle = new Integer[360];
|
||||
Map<Integer, PolarSheetsHistogramData> perWindSpeed = new HashMap<>();
|
||||
for (int angle = 0; angle < 360; angle++) {
|
||||
SpeedWithConfidence<Integer> speedWithConfidence;
|
||||
Pair<SpeedWithConfidence<Integer>, Integer> speedWithConfidenceAndDataCount;
|
||||
try {
|
||||
int convertedAngle = angle;
|
||||
if (angle > 180) {
|
||||
convertedAngle = angle - 360;
|
||||
}
|
||||
speedWithConfidence = incrementalRegressionProcessor.estimateBoatSpeed(boatClass, new KnotSpeedImpl(windSpeed), new DegreeBearingImpl(convertedAngle));
|
||||
speedWithConfidenceAndDataCount = incrementalRegressionProcessor.estimateBoatSpeed(boatClass, new KnotSpeedImpl(windSpeed), new DegreeBearingImpl(convertedAngle));
|
||||
} catch (NotEnoughDataHasBeenAddedException e) {
|
||||
speedWithConfidence = new SpeedWithConfidenceImpl<Integer>(new KnotSpeedImpl(0), 0, 0);
|
||||
speedWithConfidenceAndDataCount = new Pair<SpeedWithConfidence<Integer>, Integer>(new SpeedWithConfidenceImpl<Integer>(new KnotSpeedImpl(0), 0, 0), 0);
|
||||
}
|
||||
averagedPolarDataByWindSpeed[windIndex][angle] = speedWithConfidence.getObject().getKnots();
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME Remove hard coded size values
|
||||
Map<Integer, Integer[]> dataCountPerAngleForWindspeed = new HashMap<>();
|
||||
Map<Integer, Map<Integer, PolarSheetsHistogramData>> histogramDataMap = new HashMap<>();
|
||||
for (int windIndex = 0; windIndex < defaultWindSpeeds.length; windIndex++) {
|
||||
Integer[] perAngle = new Integer[360];
|
||||
Map<Integer, PolarSheetsHistogramData> perWindSpeed = new HashMap<>();
|
||||
for (int angle = 0; angle < 360; angle++) {
|
||||
perAngle[angle] = /* FIXME */100;
|
||||
Number[] xValues = {5};
|
||||
Number[] yValues = {10};;
|
||||
Map<String, Integer[]> yValuesByGaugeIds = new HashMap<>();
|
||||
Map<String, Integer[]> yValuesByDay = new HashMap<>();
|
||||
Map<String, Integer[]> yValuesByDayAndGaugeId = new HashMap<>();
|
||||
int dataCount = 100;
|
||||
|
||||
averagedPolarDataByWindSpeed[windIndex][angle] = speedWithConfidenceAndDataCount.getA().getObject().getKnots();
|
||||
int dataCount = speedWithConfidenceAndDataCount.getB();
|
||||
|
||||
totalDataCount = totalDataCount + dataCount;
|
||||
//FIXME hard coded
|
||||
double coefficiantOfVariation = 0.8;
|
||||
PolarSheetsHistogramDataImpl polarSheetsHistogramDataImpl = new PolarSheetsHistogramDataImpl(angle, xValues, yValues, yValuesByGaugeIds,
|
||||
yValuesByDay, yValuesByDayAndGaugeId, dataCount, coefficiantOfVariation);
|
||||
polarSheetsHistogramDataImpl.setConfidenceMeasure(0.5);
|
||||
double confidenceMeasure = 0.5;
|
||||
|
||||
PolarSheetsHistogramDataImpl polarSheetsHistogramDataImpl = createEmptyHistogramData(perAngle, angle,
|
||||
dataCount, coefficiantOfVariation, confidenceMeasure);
|
||||
perWindSpeed.put(angle, polarSheetsHistogramDataImpl);
|
||||
}
|
||||
histogramDataMap.put(windIndex, perWindSpeed);
|
||||
@@ -161,13 +160,32 @@ public class PolarDataMiner {
|
||||
}
|
||||
|
||||
|
||||
PolarSheetsData data = new PolarSheetsDataImpl(averagedPolarDataByWindSpeed, /* FIXME */100000,
|
||||
PolarSheetsData data = new PolarSheetsDataImpl(averagedPolarDataByWindSpeed, totalDataCount,
|
||||
dataCountPerAngleForWindspeed, defaultPolarSheetGenerationSettings.getWindStepping(), histogramDataMap);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private PolarSheetsHistogramDataImpl createEmptyHistogramData(Integer[] perAngle, int angle, int dataCount,
|
||||
double coefficiantOfVariation, double confidenceMeasure) {
|
||||
perAngle[angle] = dataCount;
|
||||
Number[] xValues = {};
|
||||
Number[] yValues = {};;
|
||||
Map<String, Integer[]> yValuesByGaugeIds = new HashMap<>();
|
||||
Map<String, Integer[]> yValuesByDay = new HashMap<>();
|
||||
Map<String, Integer[]> yValuesByDayAndGaugeId = new HashMap<>();
|
||||
|
||||
|
||||
PolarSheetsHistogramDataImpl polarSheetsHistogramDataImpl = new PolarSheetsHistogramDataImpl(angle, xValues, yValues, yValuesByGaugeIds,
|
||||
yValuesByDay, yValuesByDayAndGaugeId, dataCount, coefficiantOfVariation);
|
||||
|
||||
polarSheetsHistogramDataImpl.setConfidenceMeasure(confidenceMeasure);
|
||||
return polarSheetsHistogramDataImpl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Set<BoatClass> getAvailableBoatClasses() {
|
||||
return incrementalRegressionProcessor.getAvailableBoatClasses();
|
||||
}
|
||||
|
||||
+4
@@ -47,4 +47,8 @@ public class BoatSpeedEstimator {
|
||||
}
|
||||
}
|
||||
|
||||
public int getDataCount() {
|
||||
return windSpeedRegression.getDataCount();
|
||||
}
|
||||
|
||||
}
|
||||
+2
@@ -10,4 +10,6 @@ public interface IncrementalLinearRegressionProcessor {
|
||||
|
||||
double getIntercept();
|
||||
|
||||
int getDataCount();
|
||||
|
||||
}
|
||||
+5
@@ -114,4 +114,9 @@ public class IncrementalLeastSquaresProcessor implements IncrementalLinearRegres
|
||||
return alpha0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDataCount() {
|
||||
return numberOfPointsAdded;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user