From aaa3dc93f13ba639b044ee78723b0efa4a60b006 Mon Sep 17 00:00:00 2001 From: Peter Galloway Date: Wed, 17 May 2017 17:34:47 +1200 Subject: [PATCH] boat movement working reliably now, still need to fix one bug at initialization #story[923] --- src/main/java/seng302/App.java | 2 +- .../seng302/controllers/CanvasController.java | 65 +++++++++++-------- src/main/java/seng302/models/BoatGroup.java | 55 +++++++++++----- .../server/messages/BoatLocationMessage.java | 2 +- 4 files changed, 77 insertions(+), 47 deletions(-) diff --git a/src/main/java/seng302/App.java b/src/main/java/seng302/App.java index 92aab87a..aab0a8eb 100644 --- a/src/main/java/seng302/App.java +++ b/src/main/java/seng302/App.java @@ -62,7 +62,7 @@ public class App extends Application } //Change the StreamReceiver in this else block to change the default data source. else{ - sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream"); + sr = new StreamReceiver("localhost", 4949, "RaceStream"); } sr.start(); diff --git a/src/main/java/seng302/controllers/CanvasController.java b/src/main/java/seng302/controllers/CanvasController.java index c1a642fc..d2e7ce02 100644 --- a/src/main/java/seng302/controllers/CanvasController.java +++ b/src/main/java/seng302/controllers/CanvasController.java @@ -51,10 +51,12 @@ public class CanvasController { private Mark maxLonPoint; private double referencePointX; private double referencePointY; + private List markGroups = new ArrayList<>(); private List boatGroups = new ArrayList<>(); //FRAME RATE + private Double frameRate = 60.0; private final long[] frameTimes = new long[30]; private int frameTimeIndex = 0; private boolean arrayFilled = false; @@ -93,7 +95,7 @@ public class CanvasController { // TODO: 1/05/17 wmu16 - Change this call to now draw the marks as from the xml - drawBoats(); + initializeBoats(); timer = new AnimationTimer() { @Override @@ -110,7 +112,7 @@ public class CanvasController { if (arrayFilled) { elapsedNanos = now - oldFrameTime ; long elapsedNanosPerFrame = elapsedNanos / frameTimes.length ; - Double frameRate = 1_000_000_000.0 / elapsedNanosPerFrame ; + frameRate = 1_000_000_000.0 / elapsedNanosPerFrame ; drawFps(frameRate.intValue()); } @@ -167,30 +169,38 @@ public class CanvasController { private void updateGroups(){ for (BoatGroup boatGroup : boatGroups) { - boatGroup.updatePosition(); // some raceObjects will have multiple ID's (for instance gate marks) //checking if the current "ID" has any updates associated with it if (StreamParser.boatPositions.containsKey(boatGroup.getRaceId())) { - moveBoatGroup(boatGroup); + if (boatGroup.isStopped()) { + updateBoatGroup(boatGroup); + } } + boatGroup.move(); } for (MarkGroup markGroup : markGroups) { for (int id : markGroup.getRaceIds()) { if (StreamParser.boatPositions.containsKey(id)) { - moveMarkGroup(id, markGroup); + UpdateMarkGroup(id, markGroup); } } } } - private void moveBoatGroup(BoatGroup boatGroup) { + private void updateBoatGroup(BoatGroup boatGroup) { PriorityBlockingQueue movementQueue = StreamParser.boatPositions.get(boatGroup.getRaceId()); - if (movementQueue.size() > 0){ + // giving the movementQueue a 5 packet buffer to account for slightly out of order packets + if (movementQueue.size() > 5){ try { BoatPositionPacket positionPacket = movementQueue.take(); Point2D p2d = findScaledXY(positionPacket.getLat(), positionPacket.getLon()); + if (boatGroup.getRaceId() == 106){ +// System.out.println("p2d.getX() = " + p2d.getX()); +// System.out.println("p2d.getY() = " + p2d.getY()); +// System.out.println("positionPacket.getTimeValid() = " + positionPacket.getTimeValid()); + } double heading = 360.0 / 0xffff * positionPacket.getHeading(); - boatGroup.setDestination(p2d.getX(), p2d.getY(), heading, positionPacket.getGroundSpeed(), boatGroup.getRaceId()); + boatGroup.setDestination(p2d.getX(), p2d.getY(), heading, positionPacket.getGroundSpeed(), positionPacket.getTimeValid(), frameRate, boatGroup.getRaceId()); } catch (InterruptedException e){ e.printStackTrace(); } @@ -198,7 +208,7 @@ public class CanvasController { } } - void moveMarkGroup (int raceId, MarkGroup markGroup) { + void UpdateMarkGroup (int raceId, MarkGroup markGroup) { PriorityBlockingQueue movementQueue = StreamParser.boatPositions.get(raceId); if (movementQueue.size() > 0){ try { @@ -211,6 +221,23 @@ public class CanvasController { } } + /** + * Draws all the boats. + */ + private void initializeBoats() { + Map boats = StreamParser.getBoats(); + Group boatAnnotations = new Group(); + + for (Yacht boat : boats.values()) { + boat.setColour(Colors.getColor()); + BoatGroup boatGroup = new BoatGroup(boat, boat.getColour()); + boatGroups.add(boatGroup); + boatAnnotations.getChildren().add(boatGroup.getLowPriorityAnnotations()); + } + group.getChildren().add(boatAnnotations); + group.getChildren().addAll(boatGroups); + } + class ResizableCanvas extends Canvas { ResizableCanvas() { @@ -236,11 +263,11 @@ public class CanvasController { public double prefWidth(double height) { return getWidth(); } - @Override public double prefHeight(double width) { return getHeight(); } + } private void drawFps(int fps){ @@ -259,23 +286,6 @@ public class CanvasController { } } - /** - * Draws all the boats. - */ - private void drawBoats() { - Map boats = StreamParser.getBoats(); - Group boatAnnotations = new Group(); - - for (Yacht boat : boats.values()) { - boat.setColour(Colors.getColor()); - BoatGroup boatGroup = new BoatGroup(boat, boat.getColour()); - boatGroups.add(boatGroup); - boatAnnotations.getChildren().add(boatGroup.getLowPriorityAnnotations()); - } - group.getChildren().add(boatAnnotations); - group.getChildren().addAll(boatGroups); - } - /** * Calculates x and y location for every marker that fits it to the canvas the race will be drawn on. */ @@ -382,6 +392,7 @@ public class CanvasController { * Give all markers in the course an x,y location relative to a given reference with a known x,y location. Distances * are scaled according to the distanceScaleFactor variable. */ + // DEPRECATED create an initialize marks method like the initialize boats method private void givePointsXY() { // List allPoints = StreamParser.getXmlObject().getRaceXML().getCompoundMarks(); // List processed = new ArrayList<>(); diff --git a/src/main/java/seng302/models/BoatGroup.java b/src/main/java/seng302/models/BoatGroup.java index ed594276..3de6d3a8 100644 --- a/src/main/java/seng302/models/BoatGroup.java +++ b/src/main/java/seng302/models/BoatGroup.java @@ -29,13 +29,16 @@ public class BoatGroup extends Group{ private static final double BOAT_HEIGHT = 15d; private static final double BOAT_WIDTH = 10d; //Variables for boat logic. + private boolean isStopped = true; + private double xIncrement; + private double yIncrement; + private long lastTimeValid = 0; + private long framesToMove; private Point2D lastPoint; double oldTime; double newTime; double lastYValue = 0; double lastXValue = 0; - private double dx; - private double dy; private double pixelVelocityX; private double pixelVelocityY; private static final int expectedUpdateInterval = 200; @@ -118,8 +121,6 @@ public class BoatGroup extends Group{ teamNameObject.setLayoutY(teamNameObject.getLayoutY() + dy); velocityObject.setLayoutX(velocityObject.getLayoutX() + dx); velocityObject.setLayoutY(velocityObject.getLayoutY() + dy); - wake.setLayoutX(wake.getLayoutX() + dx); - wake.setLayoutY(wake.getLayoutY() + dy); } @@ -136,16 +137,18 @@ public class BoatGroup extends Group{ teamNameObject.setLayoutY(y); velocityObject.setLayoutX(x); velocityObject.setLayoutY(y); - wake.setLayoutX(x); - wake.setLayoutY(y); } public void rotateTo (double rotation) { boatPoly.getTransforms().setAll(new Rotate(rotation)); } - public void updatePosition () { - moveGroupBy(dx, dy); + public void move() { + moveGroupBy(xIncrement, yIncrement); + framesToMove = framesToMove - 1; + if (framesToMove <= 0){ + isStopped = true; + } } /** @@ -153,20 +156,32 @@ public class BoatGroup extends Group{ * @param newXValue The X co-ordinate the boat needs to move to. * @param newYValue The Y co-ordinate the boat needs to move to. * @param rotation Rotation to move graphics to. - * @param raceIds RaceID of the object to move. + * @param timeValid the time the position values are valid for */ - public void setDestination (double newXValue, double newYValue, double rotation, double groundSpeed, long raceIds) { - System.currentTimeMillis(); - moveTo(lastXValue, lastYValue, rotation); + public void setDestination (double newXValue, double newYValue, double rotation, double groundSpeed, long timeValid, double frameRate, long id) { + if (lastTimeValid == 0){ + lastTimeValid = timeValid - 200; + moveTo(newXValue, newYValue, rotation); + } - dx = (newXValue - lastXValue)/12; - dy = (newYValue - lastYValue)/12; - lastXValue = newXValue; - lastYValue = newYValue; + rotateTo(rotation); + framesToMove = Math.round((frameRate/(1000.0f/(timeValid-lastTimeValid)))); - boat.setVelocity(groundSpeed); - velocityObject.setText(String.format("%.2f m/s", boat.getVelocity())); + double dx = newXValue - boatPoly.getLayoutX(); + double dy = newYValue - boatPoly.getLayoutY(); + + xIncrement = dx/framesToMove; + yIncrement = dy/framesToMove; + + if (id == 106){ + System.out.println(framesToMove); + System.out.println("xIncrement = " + xIncrement); + } + + velocityObject.setText(String.format("%.2f m/s", groundSpeed)); + lastTimeValid = timeValid; + isStopped = false; } @@ -230,4 +245,8 @@ public class BoatGroup extends Group{ group.getChildren().addAll(wake, lineGroup); return group; } + + public boolean isStopped() { + return isStopped; + } } \ No newline at end of file diff --git a/src/main/java/seng302/server/messages/BoatLocationMessage.java b/src/main/java/seng302/server/messages/BoatLocationMessage.java index 6cf0739d..57f31dd6 100644 --- a/src/main/java/seng302/server/messages/BoatLocationMessage.java +++ b/src/main/java/seng302/server/messages/BoatLocationMessage.java @@ -44,7 +44,7 @@ public class BoatLocationMessage extends Message { public BoatLocationMessage(int sourceId, int sequenceNum, double latitude, double longitude, double heading, long boatSpeed){ boatSpeed /= 10; messageVersionNumber = 1; - time = System.currentTimeMillis() / 1000L; + time = System.currentTimeMillis(); this.sourceId = sourceId; this.sequenceNum = sequenceNum; this.deviceType = DeviceType.RACING_YACHT;