From c776d22941170ec9ba7a4b434bc9e1c7837e2e5b Mon Sep 17 00:00:00 2001 From: Kusal Ekanayake Date: Wed, 26 Apr 2017 18:45:58 +1200 Subject: [PATCH] Linking up course stream with visualiser. Boats moving, and course drawing. Boats however are not moving as intended. Needs to be fixed/looked into. #story[820] #pair[kre39,cir27] --- .../seng302/controllers/CanvasController.java | 138 ++++++++++++------ .../controllers/RaceViewController.java | 5 +- src/main/java/seng302/models/Boat.java | 21 ++- src/main/java/seng302/models/BoatGroup.java | 13 ++ .../seng302/models/parsers/StreamPacket.java | 10 +- .../seng302/models/parsers/StreamParser.java | 66 +++++++-- .../models/parsers/StreamReceiver.java | 49 +++++-- .../seng302/models/parsers/TeamsParser.java | 3 +- src/test/java/seng302/BoatTest.java | 2 +- 9 files changed, 222 insertions(+), 85 deletions(-) diff --git a/src/main/java/seng302/controllers/CanvasController.java b/src/main/java/seng302/controllers/CanvasController.java index 41ae6ddf..117a88fc 100644 --- a/src/main/java/seng302/controllers/CanvasController.java +++ b/src/main/java/seng302/controllers/CanvasController.java @@ -4,6 +4,7 @@ import javafx.animation.*; import javafx.beans.property.SimpleDoubleProperty; import javafx.fxml.FXML; import javafx.geometry.Point2D; +import javafx.geometry.Point3D; import javafx.scene.Group; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; @@ -18,6 +19,8 @@ import seng302.models.mark.GateMark; import seng302.models.mark.Mark; import seng302.models.mark.MarkType; import seng302.models.mark.SingleMark; +import seng302.models.parsers.StreamParser; +import seng302.models.parsers.StreamReceiver; import java.sql.Time; import java.util.*; @@ -132,8 +135,12 @@ public class CanvasController { //}catch (Exception e) { // e.printStackTrace(); //} - timer = new AnimationTimer() { + StreamReceiver sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"TestThread1"); +// StreamReceiver sr = new StreamReceiver("livedata.americascup.com", 4941, "TestThread1"); + sr.start(); + + timer = new AnimationTimer() { private int countdown = 60; private int[] currentRaceMarker = {1, 1, 1, 1, 1, 1}; List marks = raceViewController.getRace().getCourse(); @@ -144,44 +151,56 @@ public class CanvasController { boolean descending; boolean leftToRight; int boatIndex = 0; + Mark nextMark; - if (countdown == 0) { + //if (countdown == 0) { for (BoatGroup boatGroup : boatGroups) { - if (currentRaceMarker[boatIndex] < marks.size()) { - if (currentRaceMarker[boatIndex] == 6) { - int debugLine = 4; - } + //if (currentRaceMarker[boatIndex] < marks.size()) { + //if (currentRaceMarker[boatIndex] == 6) { + // int debugLine = 4; + //} double xb4 = boatGroup.getLayoutX(); double yb4 = boatGroup.getLayoutY(); nextMark = marks.get(currentRaceMarker[boatIndex]); - descending = nextMark.getY() > boatGroup.getLayoutY(); - leftToRight = nextMark.getX() < boatGroup.getLayoutX(); + //descending = nextMark.getY() > boatGroup.getLayoutY(); + //leftToRight = nextMark.getX() < boatGroup.getLayoutX(); - boatGroup.updatePosition(1000 / 60); -// Point2D p = latLonToXY(lat, lon); -// boatGroup.setDestination(p.getX(), p.getY()); - if (descending && nextMark.getY() < boatGroup.getLayoutY()) { - currentRaceMarker[boatIndex]++; - boatGroup.setDestination( - marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() - ); - } else if (!descending && nextMark.getY() > boatGroup.getLayoutY()) { - currentRaceMarker[boatIndex]++; - boatGroup.setDestination( - marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() - ); - } else if (leftToRight && nextMark.getX() > boatGroup.getLayoutX()) { - currentRaceMarker[boatIndex]++; - boatGroup.setDestination( - marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() - ); - } else if (!leftToRight && nextMark.getX() < boatGroup.getLayoutX()) { - currentRaceMarker[boatIndex]++; - boatGroup.setDestination( - marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() - ); + boatGroup.updatePosition(1000 / 6); + Point3D p = StreamParser.boatPositions.get((long)boatGroup.getBoat().getId()); + //System.out.println("boatGroup = " + boatGroup.getBoat().getId()); + //System.out.println("StreamParser.boatPositions.toString() = " + StreamParser.boatPositions.toString()); + if (p != null) { + Point2D p2d = latLonToXY(p.getX(), p.getY()); + System.out.println("p2d = " + p2d); + if (!boatGroup.getBoat().isSamePos(p2d)) { + //System.out.println("p.toString() = " + p.toString()); + double heading = 360.0 / 0xffff * p.getZ(); + System.out.println("heading = " + heading); + boatGroup.setDestination(p.getX(), p.getY(), heading); + } } +// if (descending && nextMark.getY() < boatGroup.getLayoutY()) { +// currentRaceMarker[boatIndex]++; +// boatGroup.setDestination( +// marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() +// ); +// } else if (!descending && nextMark.getY() > boatGroup.getLayoutY()) { +// currentRaceMarker[boatIndex]++; +// boatGroup.setDestination( +// marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() +// ); +// } else if (leftToRight && nextMark.getX() > boatGroup.getLayoutX()) { +// currentRaceMarker[boatIndex]++; +// boatGroup.setDestination( +// marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() +// ); +// } else if (!leftToRight && nextMark.getX() < boatGroup.getLayoutX()) { +// currentRaceMarker[boatIndex]++; +// boatGroup.setDestination( +// marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() +// ); +// } double xnew = boatGroup.getLayoutX(); double ynew = boatGroup.getLayoutY(); @@ -190,18 +209,19 @@ public class CanvasController { raceFinished = false; boatIndex++; } - } - if (raceFinished) { - System.out.println("DONZEO LADS"); - this.stop(); - } - } else { - countdown--; - } + //} + //if (raceFinished) { + // System.out.println("DONZEO LADS"); + // this.stop(); + //} + //} else { + // countdown--; + //} } }; - for (Mark m : raceViewController.getRace().getCourse()) + for (Mark m : raceViewController.getRace().getCourse()) { System.out.println(m.getName()); + } //timer.start(); } @@ -261,7 +281,7 @@ public class CanvasController { for (Boat boat : boats) { BoatGroup boatGroup = new BoatGroup(boat, Colors.getColor()); boatGroup.moveBoatTo(startingX, startingY, 0d); - boatGroup.setDestination(firstMarkX, firstMarkY); +// boatGroup.setDestination(firstMarkX, firstMarkY); boatGroup.forceRotation(); group.getChildren().add(boatGroup); boatGroups.add(boatGroup); @@ -515,6 +535,7 @@ public class CanvasController { } private Point2D findScaledXY (Mark unscaled) { + System.out.println("unscaled.getName() = " + unscaled.getName()); return findScaledXY (minLatPoint.getLatitude(), minLatPoint.getLongitude(), unscaled.getLatitude(), unscaled.getLongitude()); } @@ -527,15 +548,36 @@ public class CanvasController { angleFromReference = Mark.calculateHeadingRad(latA, lonA, latB, lonB); distanceFromReference = Mark.calculateDistance(latA, lonA, latB, lonB); - - if (angleFromReference > (Math.PI / 2)) { - angleFromReference = (Math.PI * 2) - angleFromReference; - xAxisLocation -= (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); - } else { + if (angleFromReference >= 0 && angleFromReference <= Math.PI / 2) { + //System.out.println("1"); xAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); + yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); + } else if (angleFromReference >= 0) { + //System.out.println("2"); + angleFromReference = angleFromReference - Math.PI / 2; + xAxisLocation += (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); + yAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); + } else if (angleFromReference < 0 && angleFromReference >= -Math.PI / 2) { + //System.out.println("3"); + System.out.println(distanceFromReference); + angleFromReference = Math.abs(angleFromReference); + System.out.println(Math.cos(angleFromReference) * distanceFromReference); + xAxisLocation -= (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); + yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); + } else { + //System.out.println("4"); + angleFromReference = Math.abs(angleFromReference) - Math.PI / 2; + xAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); + yAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); } - yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); - +// if (angleFromReference > (Math.PI / 2)) { +// angleFromReference = (Math.PI * 2) - angleFromReference; +// xAxisLocation -= (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); +// } else { +// xAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); +// } +// yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); + //System.out.println(xAxisLocation + " *** " + yAxisLocation); return new Point2D(xAxisLocation, yAxisLocation); } diff --git a/src/main/java/seng302/controllers/RaceViewController.java b/src/main/java/seng302/controllers/RaceViewController.java index 8acfba2b..e781c8d3 100644 --- a/src/main/java/seng302/controllers/RaceViewController.java +++ b/src/main/java/seng302/controllers/RaceViewController.java @@ -25,7 +25,7 @@ import java.util.*; /** * Created by ptg19 on 29/03/17. */ -public class RaceViewController { +public class RaceViewController extends Thread{ @FXML private VBox positionVbox; @FXML @@ -48,6 +48,7 @@ public class RaceViewController { private Race race; public void initialize() { + RaceController raceController = new RaceController(); raceController.initializeRace(); race = raceController.getRace(); @@ -73,6 +74,8 @@ public class RaceViewController { includedCanvasController.timer.start(); } + + private void initializeSettings(){ displayAnnotations = true; displayFps = true; diff --git a/src/main/java/seng302/models/Boat.java b/src/main/java/seng302/models/Boat.java index 004ddc57..fda8441b 100644 --- a/src/main/java/seng302/models/Boat.java +++ b/src/main/java/seng302/models/Boat.java @@ -1,5 +1,6 @@ package seng302.models; +import javafx.geometry.Point2D; import javafx.scene.paint.Color; import javafx.scene.shape.Polygon; import javafx.scene.text.Text; @@ -19,6 +20,8 @@ public class Boat { private double heading; private int markLastPast; private String shortName; + private int id; + private Point2D currentPos; public Boat(String teamName) { this.teamName = teamName; @@ -26,6 +29,16 @@ public class Boat { this.lat = 0.0; this.lon = 0.0; this.shortName = ""; + currentPos = null; + } + + public boolean isSamePos(Point2D newPos){ + if(newPos.equals(currentPos)){ + return true; + } else { + currentPos = newPos; + return false; + } } /** @@ -35,10 +48,13 @@ public class Boat { * @param boatVelocity The speed of the boat in meters/second * @param shortName A shorter version of the teams name */ - public Boat(String teamName, double boatVelocity, String shortName) { + public Boat(String teamName, double boatVelocity, String shortName, int id) { this.teamName = teamName; this.velocity = boatVelocity; this.shortName = shortName; + this.id = id; + currentPos = null; + } /** @@ -133,4 +149,7 @@ public class Boat { return this.shortName; } + public int getId() { + return id; + } } \ No newline at end of file diff --git a/src/main/java/seng302/models/BoatGroup.java b/src/main/java/seng302/models/BoatGroup.java index f304ba90..82912d08 100644 --- a/src/main/java/seng302/models/BoatGroup.java +++ b/src/main/java/seng302/models/BoatGroup.java @@ -117,6 +117,15 @@ public class BoatGroup extends Group{ moveBy(dx, dy, rotation); } + public void setDestination (double newXValue, double newYValue, double rotation) { + this.pixelVelocityX = (newXValue - super.getLayoutX()) / expectedUpdateInterval; + this.pixelVelocityY = (newYValue - super.getLayoutY()) / expectedUpdateInterval; + //this.destinationX = newXValue; + //this.destinationY = newYValue; + this.rotationalGoal = rotation; + this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval; + } + public void setDestination (double newXValue, double newYValue) { this.pixelVelocityX = (newXValue - super.getLayoutX()) / expectedUpdateInterval; this.pixelVelocityY = (newYValue - super.getLayoutY()) / expectedUpdateInterval; @@ -174,4 +183,8 @@ public class BoatGroup extends Group{ super.getChildren().get(2).setVisible(false); super.getChildren().get(3).setVisible(false); } + + public Boat getBoat() { + return boat; + } } diff --git a/src/main/java/seng302/models/parsers/StreamPacket.java b/src/main/java/seng302/models/parsers/StreamPacket.java index 87f7bc63..444d0344 100644 --- a/src/main/java/seng302/models/parsers/StreamPacket.java +++ b/src/main/java/seng302/models/parsers/StreamPacket.java @@ -19,11 +19,11 @@ public class StreamPacket { this.payload = payload; // System.out.println("type = " + this.type.toString()); //switch the packet type to deal with what ever specific packet you want to deal with - if (this.type == PacketType.XML_MESSAGE){ - System.out.println("--------"); - System.out.println(new String(payload)); - StreamParser.parsePacket(this); - } +// if (this.type == PacketType.XML_MESSAGE){ +// System.out.println("--------"); +// System.out.println(new String(payload)); +// StreamParser.parsePacket(this); +// } } PacketType getType() { diff --git a/src/main/java/seng302/models/parsers/StreamParser.java b/src/main/java/seng302/models/parsers/StreamParser.java index bdc3ace0..438bc5b9 100644 --- a/src/main/java/seng302/models/parsers/StreamParser.java +++ b/src/main/java/seng302/models/parsers/StreamParser.java @@ -1,6 +1,8 @@ package seng302.models.parsers; +import javafx.geometry.Point2D; +import javafx.geometry.Point3D; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -13,13 +15,48 @@ import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; /** * Created by kre39 on 23/04/17. */ -public class StreamParser { +public class StreamParser extends Thread{ + public static ConcurrentHashMap boatPositions = new ConcurrentHashMap<>(); private static ArrayList boat_IDS = new ArrayList<>(); + private String threadName; + private Thread t; + + StreamParser(String threadName){ + this.threadName = threadName; + } + + public void run(){ + try { + while (StreamReceiver.packetBuffer.size() <= 1) { + Thread.sleep(1); + } + StreamPacket packet = StreamReceiver.packetBuffer.take(); + while (packet != null){ + parsePacket(packet); + Thread.sleep(10); + packet = StreamReceiver.packetBuffer.take(); + } + } catch (Exception e){ + e.printStackTrace(); + } + } + + public void start () { + System.out.println("Starting " + threadName ); + if (t == null) { + t = new Thread (this, threadName); + t.start (); + } + } + static void parsePacket(StreamPacket packet) { switch (packet.getType()){ case HEARTBEAT: @@ -65,7 +102,7 @@ public class StreamParser { private static void extractHeartBeat(StreamPacket packet) { long heartbeat = bytesToLong(packet.getPayload()); - System.out.println("Heartbeat: " + heartbeat); +// System.out.println("Heartbeat: " + heartbeat); } @@ -75,7 +112,7 @@ public class StreamParser { long currentTime = extractTimeStamp(Arrays.copyOfRange(payload,1,7), 6); long raceId = bytesToLong(Arrays.copyOfRange(payload,7,11)); int raceStatus = payload[11]; - System.out.println("raceStatus = " + raceStatus); +// System.out.println("raceStatus = " + raceStatus); long expectedStartTime = extractTimeStamp(Arrays.copyOfRange(payload,12,18), 6); long windDir = bytesToLong(Arrays.copyOfRange(payload,18,20)); long windSpeed = bytesToLong(Arrays.copyOfRange(payload,20,22)); @@ -172,7 +209,7 @@ public class StreamParser { long subjectId = bytesToLong(Arrays.copyOfRange(payload,9,13)); long incidentId = bytesToLong(Arrays.copyOfRange(payload,13,17)); int eventId = payload[17]; - System.out.println("eventId = " + eventId); +// System.out.println("eventId = " + eventId); } private static void extractChatterText(StreamPacket packet){ @@ -191,27 +228,26 @@ public class StreamParser { byte[] latBytes = Arrays.copyOfRange(payload,16,20); byte[] lonBytes = Arrays.copyOfRange(payload,20,24); byte[] boatIdBytes = Arrays.copyOfRange(payload,7,11); + byte[] headingBytes = Arrays.copyOfRange(payload,28,30); long timeStamp = extractTimeStamp(Arrays.copyOfRange(payload,1,7), 6); // int boatSeq = ByteBuffer.wrap(seqBytes).getInt(); long seq = bytesToLong(seqBytes); long boatId = bytesToLong(boatIdBytes); long lat = bytesToLong(latBytes); long lon = bytesToLong(lonBytes); + long heading = bytesToLong(headingBytes); if ((int)deviceType == 1){ - if (!boat_IDS.contains(boatId)){ - boat_IDS.add(boatId); - } - System.out.println("boatId = " + boatId); - System.out.println("deviceType = " + (long)deviceType); - System.out.println("seq = " + seq); +// System.out.println("boatId = " + boatId); +// System.out.println("deviceType = " + (long)deviceType); +// System.out.println("seq = " + seq); //needs to be validated - System.out.println("lon = " + ((180d * (double)lon)/Math.pow(2,31))); - System.out.println("lat = " + ((180d *(double)lat)/Math.pow(2,31))); + Point3D point = new Point3D(((180d * (double)lat)/Math.pow(2,31)),((180d *(double)lon)/Math.pow(2,31)),(double)heading); + boatPositions.putIfAbsent(boatId, point); + boatPositions.replace(boatId, point); +// System.out.println("lon = " + ((180d * (double)lon)/Math.pow(2,31))); +// System.out.println("lat = " + ((180d *(double)lat)/Math.pow(2,31))); } - - System.out.println("boat_IDS = " + boat_IDS); - System.out.println("boat_IDS = " + boat_IDS.size()); } diff --git a/src/main/java/seng302/models/parsers/StreamReceiver.java b/src/main/java/seng302/models/parsers/StreamReceiver.java index d5127ce4..e357101d 100644 --- a/src/main/java/seng302/models/parsers/StreamReceiver.java +++ b/src/main/java/seng302/models/parsers/StreamReceiver.java @@ -12,22 +12,47 @@ import java.util.zip.CRC32; import java.util.zip.Checksum; -public class StreamReceiver { +public class StreamReceiver extends Thread { private InputStream stream; private Socket host; private ByteArrayOutputStream crcBuffer; - public PriorityBlockingQueue packetBuffer; + private Thread t; + private String threadName; + public static PriorityBlockingQueue packetBuffer; - public StreamReceiver(String hostAddress, int hostPort, PriorityBlockingQueue packetBuffer) { + public StreamReceiver(String hostAddress, int hostPort, String threadName) { + this.threadName = threadName; try { host = new Socket(hostAddress, hostPort); } catch (IOException e) { e.printStackTrace(); System.exit(1); } - this.packetBuffer = packetBuffer; } + public void run(){ + PriorityBlockingQueue pq = new PriorityBlockingQueue<>(256, new Comparator() { + @Override + public int compare(StreamPacket s1, StreamPacket s2) { + return (int) (s1.getTimeStamp() - s2.getTimeStamp()); + } + }); + packetBuffer = pq; + connect(); + StreamParser streamParser = new StreamParser("TestThread2"); + + streamParser.start(); + } + + public void start () { + System.out.println("Starting " + threadName ); + if (t == null) { + t = new Thread (this, threadName); + t.start (); + } + } + + public void connect(){ try { stream = host.getInputStream(); @@ -121,15 +146,13 @@ public class StreamReceiver { } + + public static void main(String[] args) { - PriorityBlockingQueue pq = new PriorityBlockingQueue<>(256, new Comparator() { - @Override - public int compare(StreamPacket s1, StreamPacket s2) { - return (int) (s1.getTimeStamp() - s2.getTimeStamp()); - } - }); - StreamReceiver sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941, pq); -// StreamReceiver sr = new StreamReceiver("livedata.americascup.com", 4941, pq); - sr.connect(); + + StreamReceiver sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"TestThread1"); + //StreamReceiver sr = new StreamReceiver("livedata.americascup.com", 4941, pq); + sr.start(); + } } diff --git a/src/main/java/seng302/models/parsers/TeamsParser.java b/src/main/java/seng302/models/parsers/TeamsParser.java index 1b19724a..afa31410 100644 --- a/src/main/java/seng302/models/parsers/TeamsParser.java +++ b/src/main/java/seng302/models/parsers/TeamsParser.java @@ -27,7 +27,8 @@ public class TeamsParser extends FileParser { String name = element.getElementsByTagName("name").item(0).getTextContent(); String alias = element.getElementsByTagName("alias").item(0).getTextContent(); double velocity = Double.valueOf(element.getElementsByTagName("velocity").item(0).getTextContent()); - Boat boat = new Boat(name, velocity, alias); + int id = Integer.valueOf(element.getElementsByTagName("id").item(0).getTextContent()); + Boat boat = new Boat(name, velocity, alias, id); return boat; } else { throw new NoSuchElementException("Cannot generate a boat by given node"); diff --git a/src/test/java/seng302/BoatTest.java b/src/test/java/seng302/BoatTest.java index 0160bb8d..c415c046 100644 --- a/src/test/java/seng302/BoatTest.java +++ b/src/test/java/seng302/BoatTest.java @@ -26,7 +26,7 @@ public class BoatTest { @Test public void testSetVelocity() { - Boat boat1 = new Boat("Team 1", 29.0, ""); + Boat boat1 = new Boat("Team 1", 29.0, "", 100); assertEquals(boat1.getVelocity(), (double) 29.0, 1e-15); boat1.setVelocity(12.0);