diff --git a/java/com.sap.sailing.windestimation.lab/src/com/sap/sailing/windestimation/data/importer/TwdTransitionImporter.java b/java/com.sap.sailing.windestimation.lab/src/com/sap/sailing/windestimation/data/importer/TwdTransitionImporter.java index da0aa5380e9..77f4b663830 100644 --- a/java/com.sap.sailing.windestimation.lab/src/com/sap/sailing/windestimation/data/importer/TwdTransitionImporter.java +++ b/java/com.sap.sailing.windestimation.lab/src/com/sap/sailing/windestimation/data/importer/TwdTransitionImporter.java @@ -85,7 +85,8 @@ public class TwdTransitionImporter { private static List getTwdTransitions( List sortedManeuvers, String regattaName) { - SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator simpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator = new SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator(); + SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator simpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator = new SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator( + true); List result = new ArrayList<>(sortedManeuvers.size() * ManeuverTypeForClassification.values().length * ManeuverTypeForClassification.values().length); int maneuverIndex = 0; diff --git a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/ManeuverClassificationsAggregatorFactory.java b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/ManeuverClassificationsAggregatorFactory.java index 1d995a323ab..5767be77048 100644 --- a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/ManeuverClassificationsAggregatorFactory.java +++ b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/ManeuverClassificationsAggregatorFactory.java @@ -15,14 +15,18 @@ import com.sap.sailing.windestimation.aggregator.advancedhmm.DistanceAndDuration import com.sap.sailing.windestimation.aggregator.clustering.ManeuverClassificationForClusteringImpl; import com.sap.sailing.windestimation.aggregator.clustering.ManeuverClusteringBasedWindEstimationTrackImpl; import com.sap.sailing.windestimation.aggregator.hmm.BestPathsCalculator; +import com.sap.sailing.windestimation.aggregator.hmm.GraphNodeTransitionProbabilitiesCalculator; import com.sap.sailing.windestimation.aggregator.hmm.IntersectedWindRangeBasedTransitionProbabilitiesCalculator; import com.sap.sailing.windestimation.aggregator.hmm.ManeuverSequenceGraph; +import com.sap.sailing.windestimation.aggregator.hmm.SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator; +import com.sap.sailing.windestimation.aggregator.hmm.TwdTransitionClassifierBasedTransitionProbabilitiesCalculator; import com.sap.sailing.windestimation.aggregator.outlierremoval.MeanBasedOutlierRemovalWindEstimator; import com.sap.sailing.windestimation.aggregator.outlierremoval.NeighborBasedOutlierRemovalWindEstimator; import com.sap.sailing.windestimation.data.ManeuverTypeForClassification; import com.sap.sailing.windestimation.data.RaceWithEstimationData; import com.sap.sailing.windestimation.model.classifier.maneuver.ManeuverWithEstimatedType; import com.sap.sailing.windestimation.model.classifier.maneuver.ManeuverWithProbabilisticTypeClassification; +import com.sap.sailing.windestimation.model.classifier.twdtransition.TwdTransitionClassifiersCache; import com.sap.sailing.windestimation.model.regressor.twdtransition.GaussianBasedTwdTransitionDistributionCache; import com.sap.sailing.windestimation.model.store.ModelStore; import com.sap.sailing.windestimation.windinference.MiddleCourseBasedTwdCalculatorImpl; @@ -40,9 +44,30 @@ public class ManeuverClassificationsAggregatorFactory { this.modelCacheKeepAliveMillis = modelCacheKeepAliveMillis; } - public ManeuverClassificationsAggregator hmm() { - return new ManeuverSequenceGraph( - new BestPathsCalculator(new IntersectedWindRangeBasedTransitionProbabilitiesCalculator())); + public ManeuverClassificationsAggregator hmm( + HmmTransitionProbabilitiesCalculator transitionProbabilitiesCalculatorType, + boolean propagateIntersectedWindRangeOfHeadupAndBearAway) { + GraphNodeTransitionProbabilitiesCalculator transitionProbabilitiesCalculator = null; + switch (transitionProbabilitiesCalculatorType) { + case SIMPLE: + transitionProbabilitiesCalculator = new SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator( + propagateIntersectedWindRangeOfHeadupAndBearAway); + break; + case INTERSECTED: + transitionProbabilitiesCalculator = new IntersectedWindRangeBasedTransitionProbabilitiesCalculator( + propagateIntersectedWindRangeOfHeadupAndBearAway); + break; + case CLASSIFIER: + transitionProbabilitiesCalculator = new TwdTransitionClassifierBasedTransitionProbabilitiesCalculator( + new TwdTransitionClassifiersCache(modelStore, modelCacheKeepAliveMillis), + propagateIntersectedWindRangeOfHeadupAndBearAway); + break; + case GAUSSIAN_REGRESSOR: + transitionProbabilitiesCalculator = new DistanceAndDurationAwareWindTransitionProbabilitiesCalculator( + new GaussianBasedTwdTransitionDistributionCache(modelStore, modelCacheKeepAliveMillis), + propagateIntersectedWindRangeOfHeadupAndBearAway); + } + return new ManeuverSequenceGraph(new BestPathsCalculator(transitionProbabilitiesCalculator)); } public ManeuverClassificationsAggregator clustering() { @@ -92,10 +117,15 @@ public class ManeuverClassificationsAggregatorFactory { return new NeighborBasedOutlierRemovalWindEstimator(new MiddleCourseBasedTwdCalculatorImpl()); } - public ManeuverClassificationsAggregator advancedHmm() { + public ManeuverClassificationsAggregator advancedHmm(boolean propagateIntersectedWindRangeOfHeadupAndBearAway) { return new AdvancedManeuverGraph( new AdvancedBestPathsCalculatorImpl(new DistanceAndDurationAwareWindTransitionProbabilitiesCalculator( - new GaussianBasedTwdTransitionDistributionCache(modelStore, modelCacheKeepAliveMillis)))); + new GaussianBasedTwdTransitionDistributionCache(modelStore, modelCacheKeepAliveMillis), + propagateIntersectedWindRangeOfHeadupAndBearAway))); + } + + public enum HmmTransitionProbabilitiesCalculator { + INTERSECTED, SIMPLE, CLASSIFIER, GAUSSIAN_REGRESSOR } } diff --git a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/SimpleConfigurableManeuverBasedWindEstimationComponentImpl.java b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/SimpleConfigurableManeuverBasedWindEstimationComponentImpl.java index a29cd4cc7fe..a8cecb6733d 100644 --- a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/SimpleConfigurableManeuverBasedWindEstimationComponentImpl.java +++ b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/SimpleConfigurableManeuverBasedWindEstimationComponentImpl.java @@ -2,6 +2,7 @@ package com.sap.sailing.windestimation; import com.sap.sailing.domain.maneuverdetection.CompleteManeuverCurveWithEstimationData; import com.sap.sailing.domain.polars.PolarDataService; +import com.sap.sailing.windestimation.ManeuverClassificationsAggregatorFactory.HmmTransitionProbabilitiesCalculator; import com.sap.sailing.windestimation.data.ManeuverForEstimation; import com.sap.sailing.windestimation.data.RaceWithEstimationData; import com.sap.sailing.windestimation.data.transformer.ManeuverForEstimationTransformer; @@ -19,6 +20,8 @@ public class SimpleConfigurableManeuverBasedWindEstimationComponentImpl extends ManeuverBasedWindEstimationComponentImpl> { private static final int MODEL_CACHE_KEEP_ALIVE_MILLIS = 3600000; + private static final HmmTransitionProbabilitiesCalculator transitionProbabilitiesCalculatorType = HmmTransitionProbabilitiesCalculator.INTERSECTED; + private static final boolean propagateIntersectedWindRangeOfHeadupAndBearAway = true; public SimpleConfigurableManeuverBasedWindEstimationComponentImpl(ManeuverFeatures maneuverFeatures, ModelStore modelStore, PolarDataService polarService, @@ -54,9 +57,10 @@ public class SimpleConfigurableManeuverBasedWindEstimationComponentImpl extends polarService, modelStore, modelCacheKeepAliveMillis); switch (this) { case HMM: - return factory.hmm(); + return factory.hmm(transitionProbabilitiesCalculatorType, + propagateIntersectedWindRangeOfHeadupAndBearAway); case ADVANCED_HMM: - return factory.advancedHmm(); + return factory.advancedHmm(propagateIntersectedWindRangeOfHeadupAndBearAway); case CLUSTERING: return factory.clustering(); case MEAN_OUTLIER: @@ -67,4 +71,5 @@ public class SimpleConfigurableManeuverBasedWindEstimationComponentImpl extends throw new IllegalArgumentException(this + " implementation type is unsupported"); } } + } diff --git a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/advancedhmm/DistanceAndDurationAwareWindTransitionProbabilitiesCalculator.java b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/advancedhmm/DistanceAndDurationAwareWindTransitionProbabilitiesCalculator.java index dbe8244ab1a..be8b5fc223a 100644 --- a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/advancedhmm/DistanceAndDurationAwareWindTransitionProbabilitiesCalculator.java +++ b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/advancedhmm/DistanceAndDurationAwareWindTransitionProbabilitiesCalculator.java @@ -15,7 +15,9 @@ public class DistanceAndDurationAwareWindTransitionProbabilitiesCalculator private final GaussianBasedTwdTransitionDistributionCache gaussianBasedTwdTransitionDistributionCache; public DistanceAndDurationAwareWindTransitionProbabilitiesCalculator( - GaussianBasedTwdTransitionDistributionCache gaussianBasedTwdTransitionDistributionCache) { + GaussianBasedTwdTransitionDistributionCache gaussianBasedTwdTransitionDistributionCache, + boolean propagateIntersectedWindRangeOfHeadupAndBearAway) { + super(propagateIntersectedWindRangeOfHeadupAndBearAway); this.gaussianBasedTwdTransitionDistributionCache = gaussianBasedTwdTransitionDistributionCache; } diff --git a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/IntersectedWindRangeBasedTransitionProbabilitiesCalculator.java b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/IntersectedWindRangeBasedTransitionProbabilitiesCalculator.java index b524ec98603..0cf0f22ba32 100644 --- a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/IntersectedWindRangeBasedTransitionProbabilitiesCalculator.java +++ b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/IntersectedWindRangeBasedTransitionProbabilitiesCalculator.java @@ -15,6 +15,12 @@ public class IntersectedWindRangeBasedTransitionProbabilitiesCalculator protected static final int MIN_BEATING_ANGLE_PLUS_MIN_RUNNING_ANGLE = 40; private static final double MAX_ABS_WIND_COURSE_DEVIATION_TOLERANCE_WITHIN_ANALYSIS_INTERVAL_IN_DEGREES = 40; + private final boolean propagateIntersectedWindRangeOfHeadupAndBearAway; + + public IntersectedWindRangeBasedTransitionProbabilitiesCalculator( + boolean propagateIntersectedWindRangeOfHeadupAndBearAway) { + this.propagateIntersectedWindRangeOfHeadupAndBearAway = propagateIntersectedWindRangeOfHeadupAndBearAway; + } @Override public Pair mergeWindRangeAndGetTransitionProbability(GraphNode previousNode, @@ -26,11 +32,11 @@ public class IntersectedWindRangeBasedTransitionProbabilitiesCalculator double transitionProbabilityUntilCurrentNode = -1; IntersectedWindRange intersectedWindRangeUntilCurrentNode = null; for (GraphNode node : currentLevel.getLevelNodes()) { - WindCourseRange previousWindCourseRange = previousNode - .getManeuverType() == ManeuverTypeForClassification.BEAR_AWAY - || previousNode.getManeuverType() == ManeuverTypeForClassification.HEAD_UP - ? previousIntersectedWindRange - : previousNode.getValidWindRange(); + WindCourseRange previousWindCourseRange = propagateIntersectedWindRangeOfHeadupAndBearAway + && (previousNode.getManeuverType() == ManeuverTypeForClassification.BEAR_AWAY + || previousNode.getManeuverType() == ManeuverTypeForClassification.HEAD_UP) + ? previousIntersectedWindRange + : previousNode.getValidWindRange(); IntersectedWindRange intersectedWindRange = previousWindCourseRange.intersect(node.getValidWindRange(), CombinationModeOnViolation.INTERSECTION); TwdTransition twdTransition = constructTwdTransition(durationPassed, distancePassed, diff --git a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator.java b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator.java index 9c1e0ff002d..0a96658268b 100644 --- a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator.java +++ b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator.java @@ -6,6 +6,11 @@ import com.sap.sse.common.Bearing; public class SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator extends IntersectedWindRangeBasedTransitionProbabilitiesCalculator { + public SimpleIntersectedWindRangeBasedTransitionProbabilitiesCalculator( + boolean propagateIntersectedWindRangeOfHeadupAndBearAway) { + super(propagateIntersectedWindRangeOfHeadupAndBearAway); + } + @Override protected WindCourseRange getJibeWindRange(ManeuverForEstimation maneuver) { Bearing middleCourse = maneuver.getMiddleCourse(); diff --git a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/TwdTransitionClassifierBasedTransitionProbabilitiesCalculator.java b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/TwdTransitionClassifierBasedTransitionProbabilitiesCalculator.java index 4e6e413a000..3b5d7d64d91 100644 --- a/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/TwdTransitionClassifierBasedTransitionProbabilitiesCalculator.java +++ b/java/com.sap.sailing.windestimation/src/com/sap/sailing/windestimation/aggregator/hmm/TwdTransitionClassifierBasedTransitionProbabilitiesCalculator.java @@ -10,7 +10,9 @@ public class TwdTransitionClassifierBasedTransitionProbabilitiesCalculator private final TwdTransitionClassifiersCache twdTransitionClassifiersCache; public TwdTransitionClassifierBasedTransitionProbabilitiesCalculator( - TwdTransitionClassifiersCache twdTransitionClassifiersCache) { + TwdTransitionClassifiersCache twdTransitionClassifiersCache, + boolean propagateIntersectedWindRangeOfHeadupAndBearAway) { + super(propagateIntersectedWindRangeOfHeadupAndBearAway); this.twdTransitionClassifiersCache = twdTransitionClassifiersCache; }