diff --git a/mock/src/main/java/seng302/Model/Polars.java b/mock/src/main/java/seng302/Model/Polars.java index cef438c2..4de5b570 100644 --- a/mock/src/main/java/seng302/Model/Polars.java +++ b/mock/src/main/java/seng302/Model/Polars.java @@ -2,6 +2,7 @@ package seng302.Model; import javafx.util.Pair; +import java.util.ArrayList; import java.util.HashMap; /** @@ -36,6 +37,63 @@ public class Polars { //TODO calculate VMG from (windAngle, destAngle, windSpeed). + /** + * Calculates the VMG for a given wind angle, wind speed, and angle to destination. + * @param trueWindAngle The current true wind angle. + * @param trueWindSpeed The current true wind speed. + * @param destinationAngle The angle between the boat and the destination point. + * @return + */ + public VMG calculateVMG(double trueWindAngle, double trueWindSpeed, double destinationAngle) { + + //Currently a fairly simple implementation where we find the wind speed that is less than or equal to the current wind speed (the lower bound), and then find the specific angle (with no interpolation) that gives the best VMG. + + double polarWindSpeed = 0; + + //Find the lower bound wind speed from the polar table. + for (Pair key : this.polarValues.keySet()) { + + double currentPolarSpeed = key.getKey(); + + //If the speed from the table we are looking at is greater than the last speed, and less than or equal to the current wind speed. + if ((currentPolarSpeed > polarWindSpeed) && (currentPolarSpeed <= trueWindSpeed)) { + polarWindSpeed = currentPolarSpeed; + } + } + + //We create a list of wind angles because we need (speed, angle) pairs to look into the map. + ArrayList windAngles = new ArrayList<>(); + for (Pair key : this.polarValues.keySet()) { + + windAngles.add(key.getValue()); + } + + //Find the angle with the best VMG. + double bestVMGAngle = 0; + double bestVMGVelocity = 0; + for (double tackAngle : windAngles) { + //This is the velocity from the polar table at this wind speed/angle. + double estVelocity = this.polarValues.get(new Pair(polarWindSpeed, tackAngle)); + double angleBetweenDestAndTack = tackAngle - destinationAngle; + //This is the estimated velocity towards the target (e.g., angling away from the target reduces velocity). + double vmgTemp = Math.cos(angleBetweenDestAndTack) * estVelocity; + + //Check that the velocity is better. + if (vmgTemp > bestVMGVelocity) { + bestVMGVelocity = vmgTemp; + bestVMGAngle = tackAngle; + } + + } + + + //Create the VMG object and return it. + return new VMG(bestVMGVelocity, bestVMGAngle); + + + } + + /** * Returns the hashmap used to store polar data. * @return A hashmap containing estimated boat speeds for a given (windSpeed, windAngle) pair. diff --git a/mock/src/main/java/seng302/Model/VMG.java b/mock/src/main/java/seng302/Model/VMG.java new file mode 100644 index 00000000..2a6bb065 --- /dev/null +++ b/mock/src/main/java/seng302/Model/VMG.java @@ -0,0 +1,45 @@ +package seng302.Model; + +/** + * Created by f123 on 10-May-17. + */ + +/** + * This class encapsulates VMG - that is, velocity made good. It has a speed component and a bearing component. + */ +public class VMG { + + ///Speed component of the VMG. + double speed; + + ///Bearing component of the VMG. + double bearing; + + + /** + * Ctor. Creates a VMG object with a given speed and bearing (that is, a velocity). + * @param speed Speed component of the VMG. + * @param bearing Bearing component of the VMG. + */ + public VMG(double speed, double bearing) { + this.speed = speed; + this.bearing = bearing; + } + + + /** + * Returns the speed component of this VMG object. + * @return Speed component of this VMG object. + */ + public double getSpeed() { + return speed; + } + + /** + * Returns the bearing component of this VMG object. + * @return Bearing component of this VMG object. + */ + public double getBearing() { + return bearing; + } +}