VMG now works however some little bug in the interpolation in some quadrant that is making the speed all the same in the quadrant #story[1182]
This commit is contained in:
+22
-2
@@ -25,10 +25,30 @@
|
|||||||
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
|
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-all</artifactId>
|
<artifactId>mockito-core</artifactId>
|
||||||
<version>1.9.5</version>
|
<version>2.9.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Maven Dependencies block START-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.bytebuddy</groupId>
|
||||||
|
<artifactId>byte-buddy</artifactId>
|
||||||
|
<version>1.7.0</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.bytebuddy</groupId>
|
||||||
|
<artifactId>byte-buddy-agent</artifactId>
|
||||||
|
<version>1.7.0</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.objenesis</groupId>
|
||||||
|
<artifactId>objenesis</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- Maven Dependencies block END-->
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ public class PolarParser {
|
|||||||
/**
|
/**
|
||||||
* Given a filename, this function parses it and generates a Polar object, which can be queried for polar information.
|
* Given a filename, this function parses it and generates a Polar object, which can be queried for polar information.
|
||||||
* @param filename The filename to load and read data from (loaded as a resource).
|
* @param filename The filename to load and read data from (loaded as a resource).
|
||||||
* @return A Polar table containing data from the given file.
|
|
||||||
*/
|
*/
|
||||||
public static void parseNewPolars(String filename) throws InvalidPolarFileException {
|
public static void parseNewPolars(String filename) throws InvalidPolarFileException {
|
||||||
NewPolars newPolars = new NewPolars();
|
NewPolars newPolars = new NewPolars();
|
||||||
|
|||||||
@@ -209,7 +209,9 @@ public class MockRace extends Race {
|
|||||||
boat.setStatus(BoatStatusEnum.PRESTART);
|
boat.setStatus(BoatStatusEnum.PRESTART);
|
||||||
|
|
||||||
//We set a large time since tack change so that it calculates a new VMG when the simulation starts.
|
//We set a large time since tack change so that it calculates a new VMG when the simulation starts.
|
||||||
boat.setTimeSinceTackChange(Long.MAX_VALUE);
|
//boat.setTimeSinceTackChange(Long.MAX_VALUE);
|
||||||
|
boat.setTimeSinceTackChange(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -353,8 +355,8 @@ public class MockRace extends Race {
|
|||||||
|
|
||||||
private void newOptimalVMG(MockBoat boat) {
|
private void newOptimalVMG(MockBoat boat) {
|
||||||
long tackPeriod = 1000;
|
long tackPeriod = 1000;
|
||||||
|
|
||||||
if (boat.getTimeSinceTackChange() > tackPeriod) {
|
if (boat.getTimeSinceTackChange() > tackPeriod) {
|
||||||
|
//System.out.println("optim called");
|
||||||
//Calculate the new VMG.
|
//Calculate the new VMG.
|
||||||
// VMG newVMG = boat.getPolars().calculateVMG(
|
// VMG newVMG = boat.getPolars().calculateVMG(
|
||||||
// this.getWindDirection(),
|
// this.getWindDirection(),
|
||||||
@@ -364,7 +366,7 @@ public class MockRace extends Race {
|
|||||||
// Bearing.fromDegrees(359.99999d));
|
// Bearing.fromDegrees(359.99999d));
|
||||||
|
|
||||||
VMG newVMG = NewPolars.setBestVMG(this.getWindDirection(), this.getWindSpeed(), boat.getBearing());
|
VMG newVMG = NewPolars.setBestVMG(this.getWindDirection(), this.getWindSpeed(), boat.getBearing());
|
||||||
System.out.println(newVMG);
|
//System.out.println(newVMG);
|
||||||
//If the new vmg improves velocity, use it.
|
//If the new vmg improves velocity, use it.
|
||||||
if (improvesVelocity(boat, newVMG)) {
|
if (improvesVelocity(boat, newVMG)) {
|
||||||
boat.setVMG(newVMG);
|
boat.setVMG(newVMG);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ 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));
|
//System.out.println(String.format("tws %f, twa %f, bs %f", tws, twa, bs));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void linearInterpolatePolars(){
|
public static void linearInterpolatePolars(){
|
||||||
@@ -69,7 +69,7 @@ public class NewPolars {
|
|||||||
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(newSpeed);
|
||||||
System.out.println(String.format("tws %f, twa %f, bs %f", windSpeed, i, 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;
|
||||||
@@ -104,8 +104,10 @@ public class NewPolars {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static double getBestSpeedInQuadrant(int quad, Map<Double, Double> set){
|
private static double getBestSpeedInQuadrant(int quad, Map<Double, Double> set){
|
||||||
double min = quad* 90;
|
double min = (quad - 1)* 90;
|
||||||
double max = (quad + 1) * 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;
|
||||||
for (Double s: set.keySet()){
|
for (Double s: set.keySet()){
|
||||||
@@ -116,9 +118,6 @@ public class NewPolars {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (quad > 2){
|
|
||||||
maxAngle += 180;
|
|
||||||
}
|
|
||||||
return maxAngle;
|
return maxAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,13 +129,12 @@ public class NewPolars {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
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");
|
||||||
//speed
|
//speed
|
||||||
double closestSpeed = getClosest(trueWindSpeed, polars.keySet());
|
double closestSpeed = getClosest(trueWindSpeed, polars.keySet());
|
||||||
|
|
||||||
//not using true vmg, using general concept
|
double angle = ((boatAngle.degrees() - trueWindAngle.degrees()) % 360 + 360) % 360;
|
||||||
double angle = Math.abs(trueWindAngle.degrees() - boatAngle.degrees());
|
int quad = getQuadrant(angle);
|
||||||
|
|
||||||
int quad = getQuadrant(boatAngle.degrees());
|
|
||||||
double bestAngle = getBestSpeedInQuadrant(quad, polars.get(closestSpeed));
|
double bestAngle = getBestSpeedInQuadrant(quad, polars.get(closestSpeed));
|
||||||
|
|
||||||
Bearing vmgAngle = Bearing.fromDegrees((bestAngle) % 360);
|
Bearing vmgAngle = Bearing.fromDegrees((bestAngle) % 360);
|
||||||
@@ -159,4 +157,9 @@ public class NewPolars {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<Double, TreeMap<Double, Double>> getPolars(){
|
||||||
|
//this function is just for testing so therefore it is private
|
||||||
|
return polars;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package mock.model;
|
||||||
|
|
||||||
|
import mock.dataInput.PolarParser;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import shared.model.Bearing;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by fwy13 on 5/09/17.
|
||||||
|
*/
|
||||||
|
public class NewPolarsTest {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp(){
|
||||||
|
PolarParser.parseNewPolars("mock/polars/acc_polars.csv");
|
||||||
|
NewPolars.linearInterpolatePolars();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuads() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||||
|
//reflection for private class
|
||||||
|
Class[] parameterTypes = new Class[1];
|
||||||
|
parameterTypes[0] = Double.TYPE;
|
||||||
|
Method getQuads = NewPolars.class.getDeclaredMethod("getQuadrant", parameterTypes);
|
||||||
|
getQuads.setAccessible(true);
|
||||||
|
|
||||||
|
//start invoking
|
||||||
|
Object[] paras1 = new Object[1];
|
||||||
|
paras1[0] = (new Double(0)).doubleValue();
|
||||||
|
int q1 = (int) getQuads.invoke(NewPolars.newPolars, paras1);
|
||||||
|
assertEquals(q1, 1);
|
||||||
|
|
||||||
|
//start invoking
|
||||||
|
Object[] paras2 = new Object[1];
|
||||||
|
paras2[0] = (new Double(90)).doubleValue();
|
||||||
|
int q2 = (int) getQuads.invoke(NewPolars.newPolars, paras2);
|
||||||
|
assertEquals(q2, 2);
|
||||||
|
|
||||||
|
//start invoking
|
||||||
|
Object[] paras3 = new Object[1];
|
||||||
|
paras3[0] = (new Double(180)).doubleValue();
|
||||||
|
int q3 = (int) getQuads.invoke(NewPolars.newPolars, paras3);
|
||||||
|
assertEquals(q3, 3);
|
||||||
|
|
||||||
|
//start invoking
|
||||||
|
Object[] paras4 = new Object[1];
|
||||||
|
paras4[0] = (new Double(270)).doubleValue();
|
||||||
|
int q4 = (int) getQuads.invoke(NewPolars.newPolars, paras4);
|
||||||
|
assertEquals(q4, 4);
|
||||||
|
|
||||||
|
//start invoking
|
||||||
|
Object[] paras5 = new Object[1];
|
||||||
|
paras5[0] = (new Double(360)).doubleValue();
|
||||||
|
int q5 = (int) getQuads.invoke(NewPolars.newPolars, paras5);
|
||||||
|
assertEquals(q5, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEdgeSpeeds(){
|
||||||
|
//just make sure that speeds at certain angles do not throw a null exception and are not negative
|
||||||
|
double maxTWS = 15;
|
||||||
|
|
||||||
|
for (double tws = 0; tws < maxTWS; tws += 0.1){
|
||||||
|
for (double j = 0; j < 360; j++){
|
||||||
|
Bearing twa = Bearing.fromDegrees(j);
|
||||||
|
for (double i = 0; i < 360; i++){
|
||||||
|
Bearing boatBearing = Bearing.fromDegrees(i);
|
||||||
|
double speed = NewPolars.calculateSpeed(twa, tws, boatBearing);
|
||||||
|
assertTrue(speed >= 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClosestSpeeds() throws NoSuchMethodException, NoSuchFieldException, InvocationTargetException, IllegalAccessException {
|
||||||
|
//reflection for private class
|
||||||
|
Method getClosest = NewPolars.class.getDeclaredMethod("getClosest", double.class, Set.class);
|
||||||
|
getClosest.setAccessible(true);
|
||||||
|
|
||||||
|
Method getPolars = NewPolars.class.getDeclaredMethod("getPolars");
|
||||||
|
getPolars.setAccessible(true);
|
||||||
|
|
||||||
|
double maxTWS = 15;
|
||||||
|
|
||||||
|
//only catches for nulls
|
||||||
|
for (double tws = 0; tws < maxTWS; tws += 0.1){
|
||||||
|
Map<Double, TreeMap<Double, Double>> polars = (Map<Double, TreeMap<Double, Double>>) getPolars.invoke(NewPolars.newPolars);
|
||||||
|
double speed = (double) getClosest.invoke(NewPolars.newPolars, tws, polars.keySet());
|
||||||
|
assertTrue(speed >= 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user