mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-01 08:40:52 +00:00
support start-line initialization in tree-grow-360; fix orientation in initial steps of opportunist-360;
This commit is contained in:
1 parent
93f1c21764
commit
797d3876d3
7 files changed
+123
-38
No files matched your search
+20
-2
@@ -304,12 +304,26 @@ public class SimulationServiceImpl implements SimulationService {
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Position> getLinePositions(Waypoint wayPoint, TimePoint at, TrackedRace trackedRace) {
|
||||
List<Position> line = new ArrayList<Position>();
|
||||
if (wayPoint != null) {
|
||||
for (Mark lineMark : wayPoint.getMarks()) {
|
||||
Position estimatedMarkPosition = trackedRace.getOrCreateTrack(lineMark).getEstimatedPosition(at, /* extrapolate */ false);
|
||||
if (estimatedMarkPosition != null) {
|
||||
line.add(estimatedMarkPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
public SimulationResults computeSimulationResults(LegIdentifier legIdentifier) throws InterruptedException,
|
||||
ExecutionException {
|
||||
SimulationResults result = null;
|
||||
TrackedRace trackedRace = racingEventService.getTrackedRace(legIdentifier);
|
||||
if (trackedRace != null) {
|
||||
Leg leg = trackedRace.getRace().getCourse().getLegs().get(legIdentifier.getLegNumber());
|
||||
int legNumber = legIdentifier.getLegNumber();
|
||||
Leg leg = trackedRace.getRace().getCourse().getLegs().get(legNumber);
|
||||
// get previous mark or start line as start-position
|
||||
Waypoint fromWaypoint = leg.getFrom();
|
||||
// get next mark as end-position
|
||||
@@ -341,9 +355,13 @@ public class SimulationServiceImpl implements SimulationService {
|
||||
legDuration = endTimePoint.asMillis() - startTimePoint.asMillis();
|
||||
}
|
||||
Position startPosition = null;
|
||||
List<Position> startLine = null;
|
||||
Position endPosition = null;
|
||||
if (startTimePoint != null) {
|
||||
startPosition = trackedRace.getApproximatePosition(fromWaypoint, startTimePoint);
|
||||
if (legNumber == 0) {
|
||||
startLine = this.getLinePositions(fromWaypoint, startTimePoint, trackedRace);
|
||||
}
|
||||
}
|
||||
if (endTimePoint != null) {
|
||||
endPosition = trackedRace.getApproximatePosition(toWaypoint, endTimePoint);
|
||||
@@ -380,7 +398,7 @@ public class SimulationServiceImpl implements SimulationService {
|
||||
double simuStepSeconds = startPosition.getDistance(endPosition).getNauticalMiles()
|
||||
/ ((PolarDiagramGPS) polarDiagram).getAvgSpeed() * 3600 / 100;
|
||||
Duration simuStep = new MillisecondsDurationImpl(Math.round(simuStepSeconds) * 1000);
|
||||
SimulationParameters simulationPars = new SimulationParametersImpl(course, polarDiagram, windField,
|
||||
SimulationParameters simulationPars = new SimulationParametersImpl(course, startLine, polarDiagram, windField,
|
||||
simuStep, SailingSimulatorConstants.ModeEvent, true, true, legType);
|
||||
Map<PathType, Path> paths = null;
|
||||
if (polarDiagram != null) {
|
||||
|
||||
@@ -13,6 +13,8 @@ public interface SimulationParameters {
|
||||
void setCourse(List<Position> course);
|
||||
|
||||
List<Position> getCourse();
|
||||
|
||||
List<Position> getStartLine();
|
||||
|
||||
PolarDiagram getBoatPolarDiagram();
|
||||
|
||||
|
||||
+4
-1
@@ -1,11 +1,12 @@
|
||||
package com.sap.sailing.simulator.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.simulator.TimedPosition;
|
||||
|
||||
public class PathCandidate implements Comparable<PathCandidate> {
|
||||
|
||||
public PathCandidate(TimedPosition pos, boolean reached, double vrt, double hrz, int trn, String path, char sid, Wind wind) {
|
||||
public PathCandidate(TimedPosition pos, boolean reached, double vrt, double hrz, int trn, String path, char sid, Wind wind, Position start) {
|
||||
this.pos = pos; // time and position
|
||||
this.wind = wind;
|
||||
this.reached = reached;
|
||||
@@ -14,6 +15,7 @@ public class PathCandidate implements Comparable<PathCandidate> {
|
||||
this.trn = trn; // number of turns
|
||||
this.path = path; // path as sequence of steps from start to pos
|
||||
this.sid = sid; // side of wind of step reaching pos
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
TimedPosition pos;
|
||||
@@ -24,6 +26,7 @@ public class PathCandidate implements Comparable<PathCandidate> {
|
||||
int trn;
|
||||
String path;
|
||||
char sid;
|
||||
Position start;
|
||||
|
||||
public int getIndexOfTurnLR() {
|
||||
String tmpPath = path;
|
||||
|
||||
+4
-4
@@ -193,9 +193,9 @@ public class PathGeneratorOpportunistEuclidian360 extends PathGeneratorBase {
|
||||
prevDirection = BoatDirection.BEAT_LEFT;
|
||||
} else {
|
||||
path.add(new TimedPositionWithSpeedImpl(nextTime, nextBoatPositionRight, currentWind));
|
||||
pathStr += "l";
|
||||
pathStr += "r";
|
||||
currentPosition = nextBoatPositionRight;
|
||||
prevDirection = BoatDirection.JIBE_LEFT;
|
||||
prevDirection = BoatDirection.JIBE_RIGHT;
|
||||
}
|
||||
} else {
|
||||
if (pointOfSail == PointOfSail.TACKING) {
|
||||
@@ -205,9 +205,9 @@ public class PathGeneratorOpportunistEuclidian360 extends PathGeneratorBase {
|
||||
prevDirection = BoatDirection.BEAT_RIGHT;
|
||||
} else {
|
||||
path.add(new TimedPositionWithSpeedImpl(nextTime, nextBoatPositionLeft, currentWind));
|
||||
pathStr += "r";
|
||||
pathStr += "l";
|
||||
currentPosition = nextBoatPositionLeft;
|
||||
prevDirection = BoatDirection.JIBE_RIGHT;
|
||||
prevDirection = BoatDirection.JIBE_LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -231,7 +231,7 @@ public class PathGeneratorTreeGrow extends PathGeneratorBase {
|
||||
// extend path-string by step-direction
|
||||
String pathStr = path.path + nextDirection;
|
||||
|
||||
return (new PathCandidate(pathPos, reachedEnd, vrtDist, hrzDist, turnCount, pathStr, nextDirection, posWind));
|
||||
return (new PathCandidate(pathPos, reachedEnd, vrtDist, hrzDist, turnCount, pathStr, nextDirection, posWind, null));
|
||||
}
|
||||
|
||||
// generate path candidates based on beat angles
|
||||
@@ -526,8 +526,7 @@ public class PathGeneratorTreeGrow extends PathGeneratorBase {
|
||||
logger.fine("Time step :" + usedTimeStep);
|
||||
|
||||
// calculate initial position according to initPathStr
|
||||
PathCandidate initPath = new PathCandidate(new TimedPositionImpl(currentTime, currentPosition), false, 0.0,
|
||||
0.0, 0, "0", '0', wndStart);
|
||||
PathCandidate initPath = new PathCandidate(new TimedPositionImpl(currentTime, currentPosition), false, 0.0, 0.0, 0, "0", '0', wndStart, null);
|
||||
if (initPathStr.length() > 1) {
|
||||
char nextDirection = '0';
|
||||
for (int idx = 1; idx < initPathStr.length(); idx++) {
|
||||
|
||||
+66
-24
@@ -47,7 +47,7 @@ public class PathGeneratorTreeGrow360 extends PathGeneratorBase {
|
||||
|
||||
public PathGeneratorTreeGrow360(SimulationParameters params) {
|
||||
PolarDiagram polarDiagramClone = new PolarDiagramBase((PolarDiagramBase)params.getBoatPolarDiagram());
|
||||
this.parameters = new SimulationParametersImpl(params.getCourse(), polarDiagramClone, params.getWindField(),
|
||||
this.parameters = new SimulationParametersImpl(params.getCourse(), params.getStartLine(), polarDiagramClone, params.getWindField(),
|
||||
params.getSimuStep(), params.getMode(), params.showOmniscient(), params.showOpportunist(), params.getLegType());
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ public class PathGeneratorTreeGrow360 extends PathGeneratorBase {
|
||||
// extend path-string by step-direction
|
||||
String pathStr = path.path + nextDirection;
|
||||
|
||||
return (new PathCandidate(pathPos, reachedEnd, vrtDist, hrzDist, turnCount, pathStr, getBaseDirection(nextDirection), posWind));
|
||||
return (new PathCandidate(pathPos, reachedEnd, vrtDist, hrzDist, turnCount, pathStr, getBaseDirection(nextDirection), posWind, path.start));
|
||||
}
|
||||
|
||||
// generate path candidates based on bearing to target
|
||||
@@ -593,11 +593,7 @@ public class PathGeneratorTreeGrow360 extends PathGeneratorBase {
|
||||
|
||||
Position startPos = this.parameters.getCourse().get(0);
|
||||
Position endPos = this.parameters.getCourse().get(1);
|
||||
|
||||
// test downwind: exchange start and end
|
||||
// Position startPos = this.parameters.getCourse().get(1);
|
||||
// Position endPos = this.parameters.getCourse().get(0);
|
||||
|
||||
|
||||
TimePoint startTime = wf.getStartTime();// new MillisecondsTimePoint(0);
|
||||
List<TimedPositionWithSpeed> path = new ArrayList<TimedPositionWithSpeed>();
|
||||
|
||||
@@ -655,31 +651,77 @@ public class PathGeneratorTreeGrow360 extends PathGeneratorBase {
|
||||
logger.fine("Time step :" + usedTimeStep);
|
||||
|
||||
// calculate initial position according to initPathStr
|
||||
PathCandidate initPath = new PathCandidate(new TimedPositionImpl(currentTime, currentPosition), false, 0.0,
|
||||
0.0, 0, "0", '0', wndStart);
|
||||
List<PathCandidate> initPaths = new ArrayList<PathCandidate>();
|
||||
List<PathCandidate> allPaths = new ArrayList<PathCandidate>();
|
||||
List<PathCandidate> trgPaths = new ArrayList<PathCandidate>();
|
||||
List<Position> startLine = this.parameters.getStartLine();
|
||||
|
||||
// check if start-line has two marks as expected; if not fall back to start-position
|
||||
if ((startLine != null) && (startLine.size() > 2)) {
|
||||
startLine = null;
|
||||
}
|
||||
if (startLine == null) {
|
||||
// initialize with a single path from start position
|
||||
PathCandidate initPath = new PathCandidate(new TimedPositionImpl(currentTime, currentPosition), false, 0.0, 0.0, 0, "0", '0', wndStart, startPos);
|
||||
initPaths.add(initPath);
|
||||
} else {
|
||||
Bearing bearLine = startLine.get(0).getBearingGreatCircle(startLine.get(1));
|
||||
double diffLineVrt = bearVrt.getDifferenceTo(bearLine).getDegrees();
|
||||
Position startPositionLeft;
|
||||
Position startPositionRight;
|
||||
if ((diffLineVrt > 0) && (diffLineVrt < 180)) {
|
||||
startPositionLeft = startLine.get(0);
|
||||
startPositionRight = startLine.get(1);
|
||||
} else {
|
||||
startPositionLeft = startLine.get(1);
|
||||
startPositionRight = startLine.get(0);
|
||||
}
|
||||
// initialize with a multiple paths along the start line
|
||||
if (startLine.size() == 2) {
|
||||
if ((this.maxTurns == 1) && (initPathStr.length() > 1)) {
|
||||
PathCandidate initPath;
|
||||
if (initPathStr.charAt(1) == 'L') {
|
||||
initPath = new PathCandidate(new TimedPositionImpl(currentTime, startPositionLeft), false, 0.0, 0.0, 0, "0", '0', wndStart, startPositionLeft);
|
||||
} else {
|
||||
initPath = new PathCandidate(new TimedPositionImpl(currentTime, startPositionRight), false, 0.0, 0.0, 0, "0", '0', wndStart, startPositionRight);
|
||||
}
|
||||
initPaths.add(initPath);
|
||||
} else {
|
||||
Bearing bearStartLine = startPositionLeft.getBearingGreatCircle(startPositionRight);
|
||||
int nParts = 10;
|
||||
for(int idx=0; idx<=nParts; idx++) {
|
||||
Distance deltaStartLine = startPositionLeft.getDistance(startPositionRight).scale(((double)idx)/nParts);
|
||||
Position tmpPosition = startPositionLeft.translateGreatCircle(bearStartLine, deltaStartLine);
|
||||
Wind tmpWind = wf.getWind(new TimedPositionWithSpeedImpl(currentTime, tmpPosition, null));
|
||||
PathCandidate initPath = new PathCandidate(new TimedPositionImpl(currentTime, tmpPosition), false, 0.0, 0.0, 0, "0", '0', tmpWind, tmpPosition);
|
||||
initPaths.add(initPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// construct initialization steps, e.g. first left-going step for left-going 1-turner
|
||||
if (initPathStr.length() > 1) {
|
||||
String initPathStrCaps = initPathStr.toUpperCase();
|
||||
if (!this.upwindLeg) {
|
||||
initPathStrCaps = initPathStrCaps.replace('L', 'r');
|
||||
initPathStrCaps = initPathStrCaps.replace('R', 'l');
|
||||
}
|
||||
char nextDirection = '0';
|
||||
for (int idx = 1; idx < initPathStrCaps.length(); idx++) {
|
||||
nextDirection = initPathStrCaps.charAt(idx);
|
||||
PathCandidate newPathCand = getPathCandWind(initPath, nextDirection, usedTimeStep, turnLoss, startPos,
|
||||
endPos, distStartEndMeters);
|
||||
initPath = newPathCand;
|
||||
for (PathCandidate cand : initPaths) {
|
||||
char nextDirection = '0';
|
||||
PathCandidate tmpCand1 = cand;
|
||||
for (int idx = 1; idx < initPathStrCaps.length(); idx++) {
|
||||
nextDirection = initPathStrCaps.charAt(idx);
|
||||
tmpCand1 = getPathCandWind(tmpCand1, nextDirection, usedTimeStep, turnLoss, startPos, endPos, distStartEndMeters);
|
||||
}
|
||||
allPaths.add(tmpCand1);
|
||||
}
|
||||
} else {
|
||||
allPaths = initPaths;
|
||||
}
|
||||
List<PathCandidate> allPaths = new ArrayList<PathCandidate>();
|
||||
List<PathCandidate> trgPaths = new ArrayList<PathCandidate>();
|
||||
allPaths.add(initPath);
|
||||
|
||||
TimedPosition tstPosition = this.getStep(new TimedPositionImpl(startTime, startPos), wndStart, endPos, usedTimeStep,
|
||||
turnLoss, true, (this.upwindLeg?'L':'l'));
|
||||
|
||||
TimedPosition tstPosition = this.getStep(new TimedPositionImpl(startTime, startPos), wndStart, endPos, usedTimeStep, turnLoss, true, (this.upwindLeg?'L':'l'));
|
||||
double tstDist1 = startPos.getDistance(tstPosition.getPosition()).getMeters();
|
||||
tstPosition = this.getStep(new TimedPositionImpl(startTime, startPos), wndStart, endPos, usedTimeStep, turnLoss, true,
|
||||
(this.upwindLeg?'R':'r'));
|
||||
tstPosition = this.getStep(new TimedPositionImpl(startTime, startPos), wndStart, endPos, usedTimeStep, turnLoss, true, (this.upwindLeg?'R':'r'));
|
||||
double tstDist2 = startPos.getDistance(tstPosition.getPosition()).getMeters();
|
||||
|
||||
double hrzBinSize = (tstDist1 + tstDist2) / 6.0; // horizontal bin size in meters
|
||||
@@ -863,7 +905,7 @@ public class PathGeneratorTreeGrow360 extends PathGeneratorBase {
|
||||
|
||||
if (nextDirection == '0') {
|
||||
|
||||
curPosition = new TimedPositionWithSpeedImpl(startTime, startPos, null);
|
||||
curPosition = new TimedPositionWithSpeedImpl(startTime, bestCand.start, null);
|
||||
path.add(curPosition);
|
||||
|
||||
} else {
|
||||
|
||||
+25
-4
@@ -13,6 +13,7 @@ import com.sap.sse.common.Duration;
|
||||
public class SimulationParametersImpl implements SimulationParameters {
|
||||
|
||||
private List<Position> course;
|
||||
private List<Position> startLine;
|
||||
private PolarDiagram polarDiagram;
|
||||
private WindFieldGenerator windField;
|
||||
private Duration simuStep;
|
||||
@@ -21,9 +22,10 @@ public class SimulationParametersImpl implements SimulationParameters {
|
||||
private boolean showOpportunist;
|
||||
private LegType legType;
|
||||
|
||||
public SimulationParametersImpl(List<Position> crs, PolarDiagram pd, WindFieldGenerator wf, Duration simuStep,
|
||||
public SimulationParametersImpl(List<Position> course, PolarDiagram pd, WindFieldGenerator wf, Duration simuStep,
|
||||
char mode, boolean showOmniscient, boolean showOpportunist) {
|
||||
this.course = crs;
|
||||
this.course = course;
|
||||
this.startLine = null;
|
||||
this.polarDiagram = pd;
|
||||
this.windField = wf;
|
||||
this.simuStep = simuStep;
|
||||
@@ -33,9 +35,23 @@ public class SimulationParametersImpl implements SimulationParameters {
|
||||
this.legType = null;
|
||||
}
|
||||
|
||||
public SimulationParametersImpl(List<Position> crs, PolarDiagram pd, WindFieldGenerator wf, Duration simuStep,
|
||||
public SimulationParametersImpl(List<Position> course, PolarDiagram pd, WindFieldGenerator wf, Duration simuStep,
|
||||
char mode, boolean showOmniscient, boolean showOpportunist, LegType legType) {
|
||||
this.course = crs;
|
||||
this.course = course;
|
||||
this.startLine = null;
|
||||
this.polarDiagram = pd;
|
||||
this.windField = wf;
|
||||
this.simuStep = simuStep;
|
||||
this.mode = mode;
|
||||
this.showOmniscient = showOmniscient;
|
||||
this.showOpportunist = showOpportunist;
|
||||
this.legType = legType;
|
||||
}
|
||||
|
||||
public SimulationParametersImpl(List<Position> course, List<Position> startLine, PolarDiagram pd, WindFieldGenerator wf, Duration simuStep,
|
||||
char mode, boolean showOmniscient, boolean showOpportunist, LegType legType) {
|
||||
this.course = course;
|
||||
this.startLine = startLine;
|
||||
this.polarDiagram = pd;
|
||||
this.windField = wf;
|
||||
this.simuStep = simuStep;
|
||||
@@ -60,6 +76,11 @@ public class SimulationParametersImpl implements SimulationParameters {
|
||||
return course;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Position> getStartLine() {
|
||||
return startLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolarDiagram getBoatPolarDiagram() {
|
||||
return polarDiagram;
|
||||
|
||||
Reference in new issue
Block a user