Fixed an issue in updatePositions(...) where unconstrained bounds could be passed into the calculateVMG function (e.g., lower = -182391, upper = 188221), but they need to be in the interval [0, 360).
Mock.Polars:
Added more test cases. Still working on getting the assertions correct.
Refactored and bugfixed the calculateVMG(...) function. There were a few bugs (and ugly "fixes") because we didn't bother enforcing a strict interval on the lower and upper bound angles.
Also added a few more comments to explain the function better.
#story[873]
//We also add the same values with a negative angle, as the data file contains data for 0-180 degrees, but we also need 180-360 degrees. This is because it may turn out that going 5 degrees into the wind gives us, say, 9knots, but -5 into the wind may give us 10knots, towards our destination.
//We also add the same values with a complementary angle (e.g., angle = 50, complement = 360 - 50 = 310). This is because the data file contains angles [0, 180), but we need [0, 360).
//Create the array to store angles for this wind speed if it doesn't exist.
if(!this.polarAngles.containsKey(trueWindSpeed)){
@ -56,6 +56,7 @@ public class Polars {
while(negativeAngle>=360d){
negativeAngle-=360d;
}
//Ensure that the positive and negative angles aren't the same (e.g., pos = 0, neg = 360 - 0 = 0.
//If the lower bound is greater than the upper bound, we have a "flipped" interval. That is for, e.g., [70, 55) the lower bound is greater than the upper bound, and so it checks that (VMGAngle >= 70 OR VMGAngle < 55), instead of (VMGAngle >= 70 AND VMGAngle < 55).
booleanflippedInterval=false;
if(bearingLowerBound>bearingUpperBound){
flippedInterval=true;
}
//We need to find the upper and lower wind speeds from the Polars table, for a given current wind speed (e.g., current wind speed is 11kn, therefore lower = 8kn, upper = 12kn).
doublepolarWindSpeedLowerBound=0;
doublepolarWindSpeedUpperBound=9999999;//Start this off with a value larger than any in the Polars table so that it actually works.
doublepolarWindSpeedLowerBound=0d;
doublepolarWindSpeedUpperBound=9999999d;//Start this off with a value larger than any in the Polars table so that it actually works.
//This indicates whether or not we've managed to find a wind speed larger than the current wind speed (the upper bound) in the Polars table (in cases where the current wind speed is larger than any in the file we will never find an upper bound).
//If the angle is too small or too great, don't use it - skip to the next iteration.
//We continue (skip to next iteration) if it is outside of the interval.
if(flippedInterval){
//Bearing must be inside [lower, upper), where lower > upper. So, bearing must be >= lower, or bearing < upper. We use inverted logic since we are skipping if it is true.
//Check that the velocity is better, if so, update our best VMG so far, for this wind speed.
if(interpolatedVelocity>bestVMGVelocity){
bestVMGVelocity=interpolatedVelocity;
bestVMGSpeed=interpolatedSpeed;
bestVMGAngle=trueBoatBearing;
}
@ -231,17 +254,16 @@ public class Polars {
//Angle iteration loop is finished.
//Create the VMG, and add to list.
VMGvmg=newVMG(bestVMGVelocity,bestVMGAngle);
VMGvmg=newVMG(bestVMGSpeed,bestVMGAngle);
vmgs.add(vmg);
}
//If we never found an upper bound for the wind speed, we will only have one VMG (for the lower bound), so we can't interpolate/extrapolate anything.
if(!foundUpperBoundSpeed){
if(!foundUpperBoundWindSpeed){
returnvmgs.get(0);
}
else{
}else{
//We may have more than one VMG. If we found an upper and lower bound we will have two, if we only found an upper bound (e.g., wind speed = 2kn, upper = 4kn, lower = n/a) we will only have one VMG, but must interpolate between that and a new VMG with 0kn speed.
//We do a simple linear interpolation.
@ -251,10 +273,11 @@ public class Polars {
if(vmgs.size()>1){
//If we have a second VMG use it.
vmg2=vmgs.get(1);
}
else{
//Otherwise create a VMG with zero speed, but the same angle.
vmg2=newVMG(0,vmg1.getBearing());
}else{
//Otherwise create a VMG with zero speed, but the same angle. This is what our VMG would be with 0 knot wind speed (boats don't move at 0 knots).
//We also need to swap them around, as vmg1 needs to be the vmg for the lower bound wind speed, and vmg2 is the upper bound wind speed.
//This test has a bearing bound of [340, 5), which has a lower bound > upper bound, which is complementary to [5, 340). Due to the wind, dest angles, and bearing bounds, it cannot actually find a VMG > 0 (valid VMGs will actually be in the angle interval [10, 190]), so it will return the VMG(angle=0, speed=0).