support start-line initialization in tree-grow-360; fix orientation in initial steps of opportunist-360;

This commit is contained in:
Christopher Ronnewinkel (D036654) committed 2015-04-27 17:29:01 +02:00
1 parent 93f1c21764
commit 797d3876d3
7 files changed
+123 -38

No files matched your search

@@ -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();
@@ -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;
@@ -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;
}
}
@@ -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++) {
@@ -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 {
@@ -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;