Merge remote-tracking branch 'origin/wake_remake' into wake_remake

This commit is contained in:
Alistair McIntyre
2017-05-01 17:35:51 +12:00
5 changed files with 61 additions and 34 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ public class App extends Application
sr = new StreamReceiver("localhost", 8085, "TestThread1"); sr = new StreamReceiver("localhost", 8085, "TestThread1");
} }
else{ else{
//StreamReceiver sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"TestThread1"); // sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"TestThread1");
sr = new StreamReceiver("livedata.americascup.com", 4941, "TestThread1"); sr = new StreamReceiver("livedata.americascup.com", 4941, "TestThread1");
} }
@@ -125,7 +125,6 @@ public class CanvasController {
} }
// TODO: 1/05/17 cir27 - Make the RaceObjects update on the actual delay. // TODO: 1/05/17 cir27 - Make the RaceObjects update on the actual delay.
elapsedNanos = 1000 / 60; elapsedNanos = 1000 / 60;
System.out.println("elapsedNanos = " + elapsedNanos);
for (RaceObject raceObject : raceObjects) { for (RaceObject raceObject : raceObjects) {
raceObject.updatePosition(elapsedNanos); raceObject.updatePosition(elapsedNanos);
for (int id : raceObject.getRaceIds()) { for (int id : raceObject.getRaceIds()) {
+39 -16
View File
@@ -22,11 +22,11 @@ public class BoatGroup extends RaceObject{
private static final double VELOCITY_Y_OFFSET = -5d; private static final double VELOCITY_Y_OFFSET = -5d;
private static final double BOAT_HEIGHT = 15d; private static final double BOAT_HEIGHT = 15d;
private static final double BOAT_WIDTH = 10d; private static final double BOAT_WIDTH = 10d;
private static final int LINE_INTERVAL = 30; private static double expectedUpdateInterval = 200;
private double framesForNewLine = 0;
private boolean destinationSet; private boolean destinationSet;
private Point2D lastPoint; private Point2D lastPoint;
private int wakeGenerationDelay; private int wakeGenerationDelay = 10;
private double distanceTravelled;
private Boat boat; private Boat boat;
private Group lineGroup = new Group(); private Group lineGroup = new Group();
@@ -81,7 +81,6 @@ public class BoatGroup extends RaceObject{
destinationSet = false; destinationSet = false;
wake = new Wake(0, -BOAT_HEIGHT); wake = new Wake(0, -BOAT_HEIGHT);
wakeGenerationDelay = wake.numWakes;
super.getChildren().addAll(teamNameObject, velocityObject, boatPoly); super.getChildren().addAll(teamNameObject, velocityObject, boatPoly);
} }
@@ -150,10 +149,11 @@ public class BoatGroup extends RaceObject{
double dx = pixelVelocityX * timeInterval; double dx = pixelVelocityX * timeInterval;
double dy = pixelVelocityY * timeInterval; double dy = pixelVelocityY * timeInterval;
double rotation = rotationalVelocity * timeInterval; double rotation = rotationalVelocity * timeInterval;
distanceTravelled += Math.abs(dx) + Math.abs(dy);
moveGroupBy(dx, dy, rotation); moveGroupBy(dx, dy, rotation);
//Draw a new section of the trail every 20 pixels of movement.
if (framesForNewLine-- == 0) { if (distanceTravelled > 20) {
framesForNewLine = LINE_INTERVAL; distanceTravelled = 0;
if (lastPoint != null) { if (lastPoint != null) {
Line l = new Line( Line l = new Line(
lastPoint.getX(), lastPoint.getX(),
@@ -161,19 +161,24 @@ public class BoatGroup extends RaceObject{
boatPoly.getLayoutX(), boatPoly.getLayoutX(),
boatPoly.getLayoutY() boatPoly.getLayoutY()
); );
l.getStrokeDashArray().setAll(4d, 6d); l.getStrokeDashArray().setAll(3d, 7d);
l.setStroke(boatPoly.getFill()); l.setStroke(boatPoly.getFill());
lineGroup.getChildren().add(l); lineGroup.getChildren().add(l);
} }
if (destinationSet){ if (destinationSet){ //Only begin drawing after the first destination is set
lastPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY()); lastPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY());
} }
if (lineGroup.getChildren().size() > 60)
lineGroup.getChildren().remove(0);
} }
wake.updatePosition(timeInterval); wake.updatePosition(timeInterval);
} }
/**
* Sets the destination of the boat and the headng it should have once it reaches
* @param newXValue
* @param newYValue
* @param rotation Rotation to move graphics to.
* @param raceIds RaceID of the object to move.
*/
public void setDestination (double newXValue, double newYValue, double rotation, int... raceIds) { public void setDestination (double newXValue, double newYValue, double rotation, int... raceIds) {
if (hasRaceId(raceIds)) { if (hasRaceId(raceIds)) {
destinationSet = true; destinationSet = true;
@@ -187,19 +192,37 @@ public class BoatGroup extends RaceObject{
pixelVelocityX = dx / expectedUpdateInterval; pixelVelocityX = dx / expectedUpdateInterval;
} }
double dy = newYValue - boatPoly.getLayoutY(); double dy = newYValue - boatPoly.getLayoutY();
if ((dy > 0 && pixelVelocityY < 0) || (dy < 0 && pixelVelocityY > 0)) { //Check movement is reasonable. Assumes a 1000 * 1000 canvas
pixelVelocityY = 0; if (Math.abs(dx) > 50 || Math.abs(dy) > 50) {
} else { // System.out.println("dx = " + dx);
pixelVelocityY = dy / expectedUpdateInterval; // System.out.println("dy = " + dy);
dx = 0;
dy = 0;
moveTo(newXValue, newYValue);
} }
//Slight delay on changing X/Y direction that could help jitter. Disabled since there was an issue with
//packets that might be causing it.
// if ((dx > 0 && pixelVelocityX < 0) || (dx < 0 && pixelVelocityX > 0)) {
// pixelVelocityX = 0;
// } else {
// pixelVelocityX = dx / expectedUpdateInterval;
// }
// if ((dy > 0 && pixelVelocityY < 0) || (dy < 0 && pixelVelocityY > 0)) {
// pixelVelocityY = 0;
// } else {
// pixelVelocityY = dy / expectedUpdateInterval;
// }
pixelVelocityX = dx / expectedUpdateInterval;
pixelVelocityY = dy / expectedUpdateInterval;
rotationalGoal = rotation; rotationalGoal = rotation;
calculateRotationalVelocity(); calculateRotationalVelocity();
if (wakeGenerationDelay > 0) { if (wakeGenerationDelay > 0) {
wake.rotate(rotationalGoal); wake.rotate(rotationalGoal);
wakeGenerationDelay--; wakeGenerationDelay--;
} else { } else {
wake.setRotationalVelocity(rotationalVelocity, currentRotation, pixelVelocityX, pixelVelocityY); wake.setRotationalVelocity(rotationalVelocity, currentRotation, boat.getVelocity());
} }
velocityObject.setText(String.format("%.2f m/s", boat.getVelocity()));
} }
} }
+17 -12
View File
@@ -15,12 +15,13 @@ import javafx.scene.transform.Rotate;
*/ */
class Wake extends Group { class Wake extends Group {
final int numWakes = 5; private int numWakes = 5;
private double[] velocities = new double[13]; private double[] velocities = new double[13];
private Arc[] arcs = new Arc[numWakes]; private Arc[] arcs = new Arc[numWakes];
private double[] rotations = new double[numWakes]; private double[] rotations = new double[numWakes];
private int[] velocityIndices = new int[numWakes]; private int[] velocityIndices = new int[numWakes];
private double sum = 0; private double sum = 0;
private static double max;
/** /**
* Create a wake at the given location. * Create a wake at the given location.
@@ -46,15 +47,19 @@ class Wake extends Group {
* Sets the rotationalVelocity of each arc. Each arc is 3 velocities behind the next smallest arc. The smallest uses * Sets the rotationalVelocity of each arc. Each arc is 3 velocities behind the next smallest arc. The smallest uses
* the latest given velocity. * the latest given velocity.
* @param rotationalVelocity The rotationalVelocity the wake should move at. * @param rotationalVelocity The rotationalVelocity the wake should move at.
* @param rotationGoal Where the wake will rotate to if the wake is calculated to be on a straight section. This is
* used to prevent desynchronisation with the Boat polygon.
* @param velocity The real world velocity of the boat in m/s.
*/ */
void setRotationalVelocity (double rotationalVelocity, double rotationGoal, double velocityX, double velocityY) { void setRotationalVelocity (double rotationalVelocity, double rotationGoal, double velocity) {
if (Math.abs(rotationalVelocity) > 0.5) { // if (Math.abs(rotationalVelocity) > 0.5) {
rotationalVelocity = 0; // rotationalVelocity = 0;
} // }
sum -= Math.abs(velocities[(velocityIndices[0] + 10) % 13]); sum -= Math.abs(velocities[(velocityIndices[0] + 10) % 13]);
sum += Math.abs(rotationalVelocity); sum += Math.abs(rotationalVelocity);
System.out.println("sum = " + sum); // System.out.println("sum = " + sum);
if (sum < 0.9) max = Math.max(max, rotationalVelocity);
if (sum < max)
rotate (rotationGoal); //In relatively straight segments the wake snaps to match the boats current position. rotate (rotationGoal); //In relatively straight segments the wake snaps to match the boats current position.
//This stops the wake from eventually becoming out of sync with the boat. //This stops the wake from eventually becoming out of sync with the boat.
@@ -65,14 +70,14 @@ class Wake extends Group {
for (int i = 1; i < numWakes; i++) for (int i = 1; i < numWakes; i++)
velocityIndices[i] = (velocityIndices[0] + 3 * i) % 13; velocityIndices[i] = (velocityIndices[0] + 3 * i) % 13;
//Scale wakes based on velocity. Assumes boats are always moving at a decent pace. //Scale wakes based on velocity.
double scaleFactor = Math.abs(Math.log10(Math.abs(velocityX) + Math.abs(velocityY))); double baseRad = 20;
double baseRad = 25; double rad;
for (Arc arc :arcs) { for (Arc arc :arcs) {
double rad = Math.min(baseRad + 5 * scaleFactor, baseRad + 15); rad = baseRad + velocity;
arc.setRadiusX(rad); arc.setRadiusX(rad);
arc.setRadiusY(rad); arc.setRadiusY(rad);
baseRad += 10; baseRad += 5 + (velocity / 2);
} }
} }
@@ -142,13 +142,13 @@ public class MarkGroup extends RaceObject {
if (nodePixelVelocitiesX[0] > 0 && markCircle.getCenterX() > nodeDestinations[0].getX() || if (nodePixelVelocitiesX[0] > 0 && markCircle.getCenterX() > nodeDestinations[0].getX() ||
nodePixelVelocitiesX[0] < 0 && markCircle.getCenterX() < nodeDestinations[0].getY()) nodePixelVelocitiesX[0] < 0 && markCircle.getCenterX() < nodeDestinations[0].getY())
nodePixelVelocitiesX[0] = 0; nodePixelVelocitiesX[0] = 0;
else else if (nodePixelVelocitiesX[0] != 0)
markCircle.setCenterX(markCircle.getCenterX() + nodePixelVelocitiesX[0] * timeInterval); markCircle.setCenterX(markCircle.getCenterX() + nodePixelVelocitiesX[0] * timeInterval);
if (nodePixelVelocitiesY[0] > 0 && markCircle.getCenterY() > nodeDestinations[0].getY() || if (nodePixelVelocitiesY[0] > 0 && markCircle.getCenterY() > nodeDestinations[0].getY() ||
nodePixelVelocitiesY[0] < 0 && markCircle.getCenterY() < nodeDestinations[0].getY()) nodePixelVelocitiesY[0] < 0 && markCircle.getCenterY() < nodeDestinations[0].getY())
nodePixelVelocitiesY[0] = 0; nodePixelVelocitiesY[0] = 0;
else else if (nodePixelVelocitiesY[0] != 0)
markCircle.setCenterY(markCircle.getCenterY() + nodePixelVelocitiesY[0] * timeInterval); markCircle.setCenterY(markCircle.getCenterY() + nodePixelVelocitiesY[0] * timeInterval);
if (mainMark.getMarkType() != MarkType.SINGLE_MARK) { if (mainMark.getMarkType() != MarkType.SINGLE_MARK) {
@@ -162,13 +162,13 @@ public class MarkGroup extends RaceObject {
if (nodePixelVelocitiesX[1] > 0 && markCircle.getCenterX() >= nodeDestinations[1].getX() || if (nodePixelVelocitiesX[1] > 0 && markCircle.getCenterX() >= nodeDestinations[1].getX() ||
nodePixelVelocitiesX[1] < 0 && markCircle.getCenterX() <= nodeDestinations[1].getX()) nodePixelVelocitiesX[1] < 0 && markCircle.getCenterX() <= nodeDestinations[1].getX())
nodePixelVelocitiesX[1] = 0; nodePixelVelocitiesX[1] = 0;
else else if (nodePixelVelocitiesX[1] != 0)
markCircle.setCenterX(markCircle.getCenterX() + nodePixelVelocitiesX[1] * timeInterval); markCircle.setCenterX(markCircle.getCenterX() + nodePixelVelocitiesX[1] * timeInterval);
if (nodePixelVelocitiesY[1] > 0 && markCircle.getCenterY() > nodeDestinations[1].getY() || if (nodePixelVelocitiesY[1] > 0 && markCircle.getCenterY() > nodeDestinations[1].getY() ||
nodePixelVelocitiesY[1] < 0 && markCircle.getCenterY() < nodeDestinations[1].getY()) nodePixelVelocitiesY[1] < 0 && markCircle.getCenterY() < nodeDestinations[1].getY())
nodePixelVelocitiesY[1] = 0; nodePixelVelocitiesY[1] = 0;
else else if (nodePixelVelocitiesY[1] != 0)
markCircle.setCenterY(markCircle.getCenterY() + nodePixelVelocitiesY[1] * timeInterval); markCircle.setCenterY(markCircle.getCenterY() + nodePixelVelocitiesY[1] * timeInterval);
line.setEndX(markCircle.getCenterX()); line.setEndX(markCircle.getCenterX());
line.setEndY(markCircle.getCenterY()); line.setEndY(markCircle.getCenterY());