Mock.Polars:

Fixed a bug where calculateVMG was placing velocity into the VMG object, instead of speed.
Maybe fixed a bug when a bearingLowerBound which is greater than bearingUpperBound is provided.
Added another test case.

Mock.Constants:
Added knots to millimeters per second conversion factor.

Mock.Boat:
Added calculateDIstanceToNextMarker function, which returns the distance, in nautical miles, to the next mark.

Mock.Race:
Added wind direction as a race property.
Added wind speed as a race property.
The race status messages sent by Race now use Race's wind speed and direction.

#story[873]
This commit is contained in:
fjc40
2017-05-14 22:34:05 +12:00
parent 7f37dbbcb5
commit f4d5df9df2
6 changed files with 71 additions and 8 deletions
@@ -8,5 +8,8 @@ public class Constants {
public static final int NMToMetersConversion = 1852; // 1 nautical mile = 1852 meters
///1 knot = 514.444 millimeters per second.
public static final double KnotsToMMPerSecond = 514.444;
}
@@ -1,6 +1,7 @@
package seng302.Model;
import org.geotools.referencing.GeodeticCalculator;
import seng302.Constants;
/**
@@ -85,6 +86,31 @@ public class Boat {
}
/**
* Calculates the distance between the boat and its target marker in nautical miles (1.852 km).
* @return The distance (in nautical miles) between the boat and its target marker.
*/
public double calculateDistanceToNextMarker() {
GeodeticCalculator calc = new GeodeticCalculator();
GPSCoordinate startMarker = this.getCurrentPosition();
//When boats finish, their "current leg" doesn't have an end marker.
if (this.getCurrentLeg().getEndMarker() == null) {
return 0d;
}
GPSCoordinate endMarker = this.getCurrentLeg().getEndMarker().getAverageGPSCoordinate();
//Add points to calculator.
calc.setStartingGeographicPoint(startMarker.getLongitude(), startMarker.getLatitude());
calc.setDestinationGeographicPoint(endMarker.getLongitude(), endMarker.getLatitude());
//Convert meters to nautical miles.
return calc.getOrthodromicDistance() / Constants.NMToMetersConversion;
}
public String getName() {
return name;
}
+8 -3
View File
@@ -85,10 +85,16 @@ public class Polars {
* @param destinationAngle The angle between the boat and the destination point.
* @param bearingLowerBound The lowest bearing (angle) that the boat may travel on.
* @param bearingUpperBound The highest bearing (angle) that the boat may travel on.
* @return
* @return The VMG.
*/
public VMG calculateVMG(double trueWindAngle, double trueWindSpeed, double destinationAngle, double bearingLowerBound, double bearingUpperBound) {
//TODO BUG there may be a bug when you provide a bearingUpperBound < bearingLowerBound (e.g., lower = 340, upper = 15).
bearingLowerBound = ((bearingLowerBound % 360d) + 360d) % 360d;
bearingUpperBound = ((bearingUpperBound % 360d) + 360d) % 360d;
if (bearingLowerBound > bearingUpperBound) {
bearingLowerBound -= 360d;
}
//Sorts polar angles.
for (ArrayList<Double> angles : this.polarAngles.values()) {
@@ -119,7 +125,6 @@ public class Polars {
}
}
//TODO for wind speeds larger than any in the Polars table, we will simply not find an upper bound, and therefore never calculate an upper VMG, or interpolate between them.
@@ -218,7 +223,7 @@ public class Polars {
//Check that the velocity is better.
if (vmgTemp > bestVMGVelocity) {
bestVMGVelocity = vmgTemp;
bestVMGVelocity = interpolatedSpeed;
bestVMGAngle = trueBoatBearing;
}
+14 -4
View File
@@ -10,6 +10,7 @@ import org.geotools.referencing.GeodeticCalculator;
import seng302.Constants;
import seng302.DataInput.RaceDataSource;
import seng302.MockOutput;
import seng302.Networking.Messages.BoatLocation;
import seng302.Networking.Messages.BoatStatus;
import seng302.Networking.Messages.Enums.BoatStatusEnum;
import seng302.Networking.Messages.RaceStatus;
@@ -47,6 +48,11 @@ public class Race implements Runnable {
private int finished = 0;
private List<GPSCoordinate> boundary;
///Wind direction bearing.
private double windDirection = 0;
///Wind speed (knots). Convert this to millimeters per second before passing to RaceStatus.
private double windSpeed = 0;
/**
* Initailiser for Race
@@ -65,6 +71,9 @@ public class Race implements Runnable {
this.mockOutput = mockOutput;
this.boundary = boundary;
this.windSpeed = 12;//TODO could use input parameters for these. And should fluctuate during race.
this.windDirection = 0;
//TODO refactor
this.startTime = System.currentTimeMillis() + (this.PRERACE_TIME / this.scaleFactor);
@@ -140,7 +149,7 @@ public class Race implements Runnable {
boatOffset = (boatOffset + 1) % (startingBoats.size());
if (timeLeft <= 60000/scaleFactor && timeLeft > 0) {
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 2, startTime, 0, 2300, 1, boatStatuses);
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 2, startTime, BoatLocation.convertHeadingDoubleToInt(windDirection), (int) (windSpeed * Constants.KnotsToMMPerSecond), 1, boatStatuses);
mockOutput.parseRaceStatus(raceStatus);
}
else if (timeLeft <= 0) {
@@ -151,7 +160,7 @@ public class Race implements Runnable {
stop();
}
else {
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 1, startTime, 0, 2300,1, boatStatuses);
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 1, startTime, BoatLocation.convertHeadingDoubleToInt(windDirection), (int) (windSpeed * Constants.KnotsToMMPerSecond),1, boatStatuses);
mockOutput.parseRaceStatus(raceStatus);
}
currentTime = System.currentTimeMillis();
@@ -182,6 +191,7 @@ public class Race implements Runnable {
if (boatsFinished < startingBoats.size()) {
//Get the current time.
long currentTime = System.currentTimeMillis();
//Update the total elapsed time.
totalTimeElapsed = currentTime - timeRaceStarted;
ArrayList<BoatStatus> boatStatuses = new ArrayList<BoatStatus>();
@@ -205,7 +215,7 @@ public class Race implements Runnable {
boat.getCurrentLeg().getLegNumber() >= 0 ? BoatStatusEnum.RACING : BoatStatusEnum.DNF, boat.getCurrentLeg().getLegNumber()));
}
if (startingBoats.size()==finished){
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 4, startTime, 0, 2300, 2, boatStatuses);//TODO FIX the second currentTime is a placeholder! Also, replace magic values.
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 4, startTime, BoatLocation.convertHeadingDoubleToInt(windDirection), (int) (windSpeed * Constants.KnotsToMMPerSecond), 2, boatStatuses);//TODO FIX replace magic values.
mockOutput.parseRaceStatus(raceStatus);
}
} else {
@@ -213,7 +223,7 @@ public class Race implements Runnable {
}
}
boatOffset = (boatOffset + 1) % (startingBoats.size());
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 3, startTime, 0, 2300, 2, boatStatuses);//TODO FIX the second currentTime is a placeholder! Also, replace magic values.
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 3, startTime, BoatLocation.convertHeadingDoubleToInt(windDirection), (int) (windSpeed * Constants.KnotsToMMPerSecond), 2, boatStatuses);//TODO FIX replace magic values.
mockOutput.parseRaceStatus(raceStatus);
}
}