Tidied up code

- Removed prints from tests
- Added Javadocs in necessary places
- Reenabled boat status message to send
- Added boat average angle
- pulled out modulateAngle function
- Commented harder to read loops
- Disabled toggled VMG
#story[1182]
main
Fan-Wu Yang 8 years ago
parent d602c1ec6f
commit 06517b7b47

@ -343,6 +343,7 @@ public class MockRace extends Race {
if (boat.getAutoVMG()) { if (boat.getAutoVMG()) {
newOptimalVMG(boat); newOptimalVMG(boat);
boat.setAutoVMG(false);
} }
} else { } else {

@ -8,7 +8,8 @@ import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
/** /**
* Created by fwy13 on 4/09/17. * New Polars are the revampe of the old Polars class which interpolates the data after being parsed from the Polar Parser
* There can only be one NewPolars instance stored statically however if a boat does happen to have a special case it can be assigned.
*/ */
public class NewPolars { public class NewPolars {
@ -22,6 +23,12 @@ public class NewPolars {
newPolars = this; newPolars = this;
} }
/**
* Add polars from the polar table
* @param trueWindSpeed True Wind Speed that the true wind angle and speed corresponds to
* @param trueWindAngle True Wind Angle of the race
* @param boatSpeed The speed the boat should be going at given the true wind angle
*/
public static void addPolars(double trueWindSpeed, Bearing trueWindAngle, double boatSpeed){ public static void addPolars(double trueWindSpeed, Bearing trueWindAngle, double boatSpeed){
double tws = trueWindSpeed; double tws = trueWindSpeed;
double bs = boatSpeed; double bs = boatSpeed;
@ -31,31 +38,33 @@ public class NewPolars {
} }
polars.get(tws).putIfAbsent(twa, bs); polars.get(tws).putIfAbsent(twa, bs);
polars.get(tws).putIfAbsent(360d - twa, bs); polars.get(tws).putIfAbsent(360d - twa, bs);
//System.out.println(String.format("tws %f, twa %f, bs %f", tws, twa, bs));
} }
/**
* Linearly Interpolates this should only be called once per parsing of a polar table
*/
public static void linearInterpolatePolars(){ public static void linearInterpolatePolars(){
// double maxTWS = 0;
// for (double key: polars.keySet()){
// if (maxTWS < key){
// maxTWS = key;
// }
// }
/*for (double windSpeed: polars.keySet()){
if (!polars.get(windSpeed).containsKey(180d)){
polars.get(windSpeed).put(180d, windSpeed);
}
}*/
TreeMap<Double, Double> prevTWS = null; TreeMap<Double, Double> prevTWS = null;
TreeMap<Double, TreeMap<Double, Double>> iterablePolars = new TreeMap<>(polars); TreeMap<Double, TreeMap<Double, Double>> iterablePolars = new TreeMap<>(polars);
//this loop averages out the speed between tow angles
//Example: Pair one: 0 degrees, 0 knots
// Pair two: 3 degrees, 6 knots
//This loop will add
//Pair one: 0 degrees, 0 knots
//Pair two: 1 degrees, 2 knots
//Pair three: 2 degrees, 4 knots
//Pair four: 3 degrees, 6 knots
for (double windSpeed: iterablePolars.keySet()){ for (double windSpeed: iterablePolars.keySet()){
TreeMap<Double, Double> tws = iterablePolars.get(windSpeed); TreeMap<Double, Double> tws = iterablePolars.get(windSpeed);
if (prevTWS == null){ if (prevTWS == null){
prevTWS = tws; prevTWS = tws;
continue; continue;
} }
double previousTWA = -1; double previousTWA = -1;
TreeMap<Double, Double> iterableTWS = new TreeMap<>(tws); TreeMap<Double, Double> iterableTWS = new TreeMap<>(tws);
for (double twa: iterableTWS.keySet()){ for (double twa: iterableTWS.keySet()){
if (previousTWA == -1){ if (previousTWA == -1){
previousTWA = twa; previousTWA = twa;
@ -65,11 +74,10 @@ public class NewPolars {
double speedDiff = iterableTWS.get(twa) - iterableTWS.get(previousTWA); double speedDiff = iterableTWS.get(twa) - iterableTWS.get(previousTWA);
double prevSpeed = iterableTWS.get(previousTWA); double prevSpeed = iterableTWS.get(previousTWA);
double diff = speedDiff/twaDiff; double diff = speedDiff/twaDiff;
for (double i = previousTWA; i < twa; i ++){ for (double i = previousTWA; i < twa; i ++){
double mult = i - previousTWA; double mult = i - previousTWA;
double newSpeed = diff * mult + prevSpeed; double newSpeed = diff * mult + prevSpeed;
//System.out.println(newSpeed);
//System.out.println(String.format("tws %f, twa %f, bs %f", windSpeed, i, newSpeed));
tws.put(i, newSpeed); tws.put(i, newSpeed);
} }
previousTWA = twa; previousTWA = twa;
@ -100,17 +108,18 @@ public class NewPolars {
* @return * @return
*/ */
private static int getQuadrant(double degrees){ private static int getQuadrant(double degrees){
return ((((int) degrees % 360) + 360) % 360) / 90 + 1; return (int) modulateAngle(degrees) / 90 + 1;
} }
private static double getBestSpeedInQuadrant(int quad, Map<Double, Double> set){ private static double getBestSpeedInQuadrant(int quad, Map<Double, Double> set){
double min = (quad - 1)* 90; double min = (quad - 1)* 90;
double max = quad * 90; double max = quad * 90;
//System.out.println(quad);
//System.out.println(min + " " + max);
double maxAngle = 0; double maxAngle = 0;
double maxSpeed = 0; double maxSpeed = 0;
double dupAngle = 0;//index where speed is duplicated double dupAngle = 0;
//DupAngle will average the angle between maxAngles that have the same speed
//Example: if 150 degrees, 180 degrees, and 210 degrees all go at 10 knots
//then the average will be taken as (150 + 210) / 2 and the angle will be returned on that.
for (Double s: set.keySet()){ for (Double s: set.keySet()){
if (s >= min && s < max){ if (s >= min && s < max){
if (set.get(s) > maxSpeed){ if (set.get(s) > maxSpeed){
@ -121,42 +130,48 @@ public class NewPolars {
dupAngle = s; dupAngle = s;
} }
} }
}/* }
if (dupAngle != 0 ){ if (dupAngle != 0 ){
return getClosest((dupAngle + maxAngle) / 2, set.keySet()); return getClosest((dupAngle + maxAngle) / 2, set.keySet());
}*/ }
return maxAngle; return maxAngle;
} }
/** /**
* * Returns the best VMG that the boat can change to given it's current diagonal heading direction.
* @param trueWindAngle * @param trueWindAngle True wind angle of the race
* @param trueWindSpeed * @param trueWindSpeed True wind speed of the race
* @param boatAngle * @param boatAngle Angle that the boat is currently at
* @return * @return the best vmg that the boat can change to
*/ */
public static VMG setBestVMG(Bearing trueWindAngle, double trueWindSpeed, Bearing boatAngle){ public static VMG setBestVMG(Bearing trueWindAngle, double trueWindSpeed, Bearing boatAngle){
//System.out.println("VMG AUTO CALLED"); //System.out.println("VMG AUTO CALLED");
//speed //speed
double closestSpeed = getClosest(trueWindSpeed, polars.keySet()); double closestSpeed = getClosest(trueWindSpeed, polars.keySet());
double angle = ((boatAngle.degrees() - trueWindAngle.degrees()) % 360 + 360) % 360; double angle = modulateAngle(boatAngle.degrees() - trueWindAngle.degrees());
int quad = getQuadrant(angle); int quad = getQuadrant(angle);
double bestAngle = getBestSpeedInQuadrant(quad, polars.get(closestSpeed)); double bestAngle = getBestSpeedInQuadrant(quad, polars.get(closestSpeed));
Bearing vmgAngle = Bearing.fromDegrees((bestAngle) % 360);
double boatSpeed = polars.get(closestSpeed).get(bestAngle); double boatSpeed = polars.get(closestSpeed).get(bestAngle);
double newAngle = (bestAngle + trueWindAngle.degrees() % 360 + 360) % 360; double newAngle = modulateAngle(bestAngle + trueWindAngle.degrees());
return new VMG(boatSpeed, Bearing.fromDegrees(newAngle)); return new VMG(boatSpeed, Bearing.fromDegrees(newAngle));
} }
/**
* Calculates the speed that a certain angle should be doing
* @param trueWindAngle TrueWind Angle of the race
* @param trueWindSpeed True Wind Speed of the race
* @param boatAngle Angle that the boat is current at
* @return the speed that the boat should be traveling at.
*/
public static double calculateSpeed(Bearing trueWindAngle, double trueWindSpeed, Bearing boatAngle){ public static double calculateSpeed(Bearing trueWindAngle, double trueWindSpeed, Bearing boatAngle){
//speed //speed
double closestSpeed = getClosest(trueWindSpeed, polars.keySet()); double closestSpeed = getClosest(trueWindSpeed, polars.keySet());
double angleDiff = ((boatAngle.degrees() - trueWindAngle.degrees()) % 360 + 360) % 360; double angleDiff = modulateAngle(boatAngle.degrees() - trueWindAngle.degrees());
double closestAngle = getClosest(angleDiff, polars.get(closestSpeed).keySet()); double closestAngle = getClosest(angleDiff, polars.get(closestSpeed).keySet());
double boatSpeed = polars.get(closestSpeed).get(closestAngle); double boatSpeed = polars.get(closestSpeed).get(closestAngle);
@ -166,6 +181,10 @@ public class NewPolars {
} }
public static double modulateAngle(double angle){
return (angle % 360 + 360) % 360;
}
private Map<Double, TreeMap<Double, Double>> getPolars(){ private Map<Double, TreeMap<Double, Double>> getPolars(){
//this function is just for testing so therefore it is private //this function is just for testing so therefore it is private
return polars; return polars;
@ -178,7 +197,6 @@ public class NewPolars {
System.out.println("=================================================="); System.out.println("==================================================");
for (double twa: polars.get(tws).keySet()){ for (double twa: polars.get(tws).keySet()){
System.out.println("TWA: " + twa + ", Boat Speed: " + polars.get(tws).get(twa)); System.out.println("TWA: " + twa + ", Boat Speed: " + polars.get(tws).get(twa));
//System.out.println("--------------------------------------------------");
} }
} }
} }

@ -151,7 +151,7 @@ public class RaceServer {
List<BoatStatus> boatStatuses = new ArrayList<>(); List<BoatStatus> boatStatuses = new ArrayList<>();
//Add each boat status to the status list. //Add each boat status to the status list.
/*for (MockBoat boat : race.getBoats()) { for (MockBoat boat : race.getBoats()) {
BoatStatus boatStatus = new BoatStatus( BoatStatus boatStatus = new BoatStatus(
boat.getSourceID(), boat.getSourceID(),
@ -160,7 +160,7 @@ public class RaceServer {
boat.getEstimatedTimeAtNextMark().toInstant().toEpochMilli() ); boat.getEstimatedTimeAtNextMark().toInstant().toEpochMilli() );
boatStatuses.add(boatStatus); boatStatuses.add(boatStatus);
}*/ }

@ -40,6 +40,7 @@ public class MainController extends Controller {
* Transitions from the StartController screen (displays pre-race information) to the RaceController (displays the actual race). * Transitions from the StartController screen (displays pre-race information) to the RaceController (displays the actual race).
* @param visualiserRace The object modelling the race. * @param visualiserRace The object modelling the race.
* @param controllerClient Socket Client that manipulates the controller. * @param controllerClient Socket Client that manipulates the controller.
* @param isHost whether this window is the host of the race or not.
*/ */
public void beginRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient, Boolean isHost) { public void beginRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient, Boolean isHost) {
raceController.startRace(visualiserRace, controllerClient, isHost); raceController.startRace(visualiserRace, controllerClient, isHost);

@ -26,20 +26,22 @@ public class NewPolarsTest {
PolarParser.parseNewPolars("mock/polars/acc_polars.csv"); PolarParser.parseNewPolars("mock/polars/acc_polars.csv");
NewPolars.linearInterpolatePolars(); NewPolars.linearInterpolatePolars();
Method getPolars = null;
try { // Uncomment if you want to read the linear interpolation in text
getPolars = NewPolars.class.getDeclaredMethod("printOutLinearInterpolated"); // Method getPolars = null;
} catch (NoSuchMethodException e) { // try {
e.printStackTrace(); // getPolars = NewPolars.class.getDeclaredMethod("printOutLinearInterpolated");
} // } catch (NoSuchMethodException e) {
getPolars.setAccessible(true); // e.printStackTrace();
try { // }
getPolars.invoke(NewPolars.newPolars); // getPolars.setAccessible(true);
} catch (IllegalAccessException e) { // try {
e.printStackTrace(); // getPolars.invoke(NewPolars.newPolars);
} catch (InvocationTargetException e) { // } catch (IllegalAccessException e) {
e.printStackTrace(); // e.printStackTrace();
} // } catch (InvocationTargetException e) {
// e.printStackTrace();
// }
} }
@Test @Test

Loading…
Cancel
Save