mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
Merge remote-tracking branch 'origin/wake_remake' into wake_remake
This commit is contained in:
@@ -18,11 +18,14 @@ import seng302.models.BoatGroup;
|
|||||||
import seng302.models.Colors;
|
import seng302.models.Colors;
|
||||||
import seng302.models.RaceObject;
|
import seng302.models.RaceObject;
|
||||||
import seng302.models.mark.*;
|
import seng302.models.mark.*;
|
||||||
|
import seng302.models.parsers.StreamPacket;
|
||||||
import seng302.models.parsers.StreamParser;
|
import seng302.models.parsers.StreamParser;
|
||||||
|
import seng302.models.parsers.packets.BoatPositionPacket;
|
||||||
|
|
||||||
import java.sql.Time;
|
import java.sql.Time;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.PriorityBlockingQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by ptg19 on 15/03/17.
|
* Created by ptg19 on 15/03/17.
|
||||||
@@ -103,13 +106,8 @@ public class CanvasController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(long now) {
|
public void handle(long now) {
|
||||||
boolean raceFinished = true;
|
|
||||||
boolean descending;
|
|
||||||
boolean leftToRight;
|
|
||||||
int boatIndex = 0;
|
|
||||||
|
|
||||||
Mark nextMark;
|
|
||||||
|
|
||||||
|
//fps stuff
|
||||||
long oldFrameTime = frameTimes[frameTimeIndex] ;
|
long oldFrameTime = frameTimes[frameTimeIndex] ;
|
||||||
frameTimes[frameTimeIndex] = now ;
|
frameTimes[frameTimeIndex] = now ;
|
||||||
frameTimeIndex = (frameTimeIndex + 1) % frameTimes.length ;
|
frameTimeIndex = (frameTimeIndex + 1) % frameTimes.length ;
|
||||||
@@ -123,21 +121,11 @@ public class CanvasController {
|
|||||||
Double frameRate = 1_000_000_000.0 / elapsedNanosPerFrame ;
|
Double frameRate = 1_000_000_000.0 / elapsedNanosPerFrame ;
|
||||||
drawFps(frameRate.intValue());
|
drawFps(frameRate.intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
||||||
for (RaceObject raceObject : raceObjects) {
|
updateRaceObjects();
|
||||||
raceObject.updatePosition(elapsedNanos);
|
|
||||||
for (int id : raceObject.getRaceIds()) {
|
|
||||||
if (StreamParser.getBoatPositions().containsKey((long) id)) {
|
|
||||||
Point3D p = StreamParser.getBoatPositions().get((long) id);
|
|
||||||
Point2D p2d = latLonToXY(p.getX(), p.getY());
|
|
||||||
double speed = StreamParser.getBoatSpeeds().get((long) id);
|
|
||||||
double heading = 360.0 / 0xffff * p.getZ();
|
|
||||||
raceObject.setDestination(p2d.getX(), p2d.getY(), heading, speed, id);
|
|
||||||
}
|
|
||||||
StreamParser.getBoatPositions().remove((long) id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (Mark m : raceViewController.getRace().getCourse()) {
|
for (Mark m : raceViewController.getRace().getCourse()) {
|
||||||
@@ -146,6 +134,46 @@ public class CanvasController {
|
|||||||
//timer.start();
|
//timer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateRaceObjects(){
|
||||||
|
for (RaceObject raceObject : raceObjects) {
|
||||||
|
raceObject.updatePosition(1000 / 60);
|
||||||
|
// some raceObjects will have multiply ID's (for instance gate marks)
|
||||||
|
for (long id : raceObject.getRaceIds()) {
|
||||||
|
//checking if the current "ID" has any updates associated with it
|
||||||
|
if (StreamParser.boatPositions.containsKey(id)) {
|
||||||
|
move(id, raceObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void move(long id, RaceObject raceObject){
|
||||||
|
PriorityBlockingQueue<BoatPositionPacket> movementQueue = StreamParser.boatPositions.get(id);
|
||||||
|
if (movementQueue.size() > 0){
|
||||||
|
BoatPositionPacket positionPacket = movementQueue.peek();
|
||||||
|
|
||||||
|
//this code adds a delay to reading from the movementQueue
|
||||||
|
//in case things being put into the movement queue are slightly
|
||||||
|
//out of order
|
||||||
|
int delayTime = 1000;
|
||||||
|
int loopTime = delayTime * 10;
|
||||||
|
long timeDiff = (System.currentTimeMillis()%loopTime - positionPacket.getTimeValid()%loopTime);
|
||||||
|
if (timeDiff < 0){
|
||||||
|
timeDiff = loopTime + timeDiff;
|
||||||
|
}
|
||||||
|
if (timeDiff > delayTime) {
|
||||||
|
try {
|
||||||
|
positionPacket = movementQueue.take();
|
||||||
|
Point2D p2d = latLonToXY(positionPacket.getLat(), positionPacket.getLon());
|
||||||
|
double heading = 360.0 / 0xffff * positionPacket.getHeading();
|
||||||
|
raceObject.setDestination(p2d.getX(), p2d.getY(), heading, positionPacket.getGroundSpeed(), (int) id);
|
||||||
|
} catch (InterruptedException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ResizableCanvas extends Canvas {
|
class ResizableCanvas extends Canvas {
|
||||||
|
|
||||||
ResizableCanvas() {
|
ResizableCanvas() {
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import org.w3c.dom.Document;
|
|||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import seng302.models.Boat;
|
import seng302.models.Boat;
|
||||||
|
import seng302.models.parsers.packets.BoatPositionPacket;
|
||||||
|
import seng302.models.parsers.packets.StreamPacket;
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
@@ -13,12 +15,11 @@ import javax.xml.parsers.ParserConfigurationException;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.PriorityBlockingQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The purpose of this class is to take in the stream of divided packets so they can be read
|
* The purpose of this class is to take in the stream of divided packets so they can be read
|
||||||
@@ -28,8 +29,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
*/
|
*/
|
||||||
public class StreamParser extends Thread{
|
public class StreamParser extends Thread{
|
||||||
|
|
||||||
private static ConcurrentHashMap<Long,Point3D> boatPositions = new ConcurrentHashMap<>();
|
public static ConcurrentHashMap<Long, PriorityBlockingQueue<BoatPositionPacket>> boatPositions = new ConcurrentHashMap<>();
|
||||||
private static ConcurrentHashMap<Long,Double> boatSpeeds = new ConcurrentHashMap<>();
|
|
||||||
private String threadName;
|
private String threadName;
|
||||||
private Thread t;
|
private Thread t;
|
||||||
private static boolean raceStarted = false;
|
private static boolean raceStarted = false;
|
||||||
@@ -40,7 +40,7 @@ public class StreamParser extends Thread{
|
|||||||
private static List<Boat> boats = new ArrayList<>();
|
private static List<Boat> boats = new ArrayList<>();
|
||||||
|
|
||||||
public StreamParser(String threadName){
|
public StreamParser(String threadName){
|
||||||
this.threadName = threadName;
|
this.threadName = threadName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,28 +55,27 @@ public class StreamParser extends Thread{
|
|||||||
while (StreamReceiver.packetBuffer == null || StreamReceiver.packetBuffer.size() < 1) {
|
while (StreamReceiver.packetBuffer == null || StreamReceiver.packetBuffer.size() < 1) {
|
||||||
Thread.sleep(1);
|
Thread.sleep(1);
|
||||||
}
|
}
|
||||||
while (StreamReceiver.packetBuffer.peek() != null){
|
while (true){
|
||||||
// StreamPacket packet = StreamReceiver.packetBuffer.peek();
|
StreamPacket packet = StreamReceiver.packetBuffer.peek();
|
||||||
// int delayTime = 1000;
|
//this code adds a delay to reading from the packetBuffer so
|
||||||
// int loopTime = delayTime + 1000;
|
//out of order packets have time to order themselves in the queue
|
||||||
// long sleepTime = 0;
|
int delayTime = 1000;
|
||||||
// long transitTime = (System.currentTimeMillis()%loopTime - packet.getTimeStamp()%loopTime);
|
int loopTime = delayTime * 10;
|
||||||
// if (transitTime < 0){
|
long transitTime = (System.currentTimeMillis()%loopTime - packet.getTimeStamp()%loopTime);
|
||||||
// transitTime = loopTime + delayTime;
|
if (transitTime < 0){
|
||||||
// }
|
transitTime = loopTime + transitTime;
|
||||||
// if (transitTime < delayTime) {
|
}
|
||||||
// sleepTime = delayTime - (transitTime);
|
if (transitTime < delayTime) {
|
||||||
// Thread.sleep(sleepTime);
|
long sleepTime = delayTime - (transitTime);
|
||||||
// }
|
Thread.sleep(sleepTime);
|
||||||
// System.out.println(sleepTime);
|
}
|
||||||
StreamPacket packet = StreamReceiver.packetBuffer.take();
|
packet = StreamReceiver.packetBuffer.take();
|
||||||
parsePacket(packet);
|
parsePacket(packet);
|
||||||
Thread.sleep(1);
|
Thread.sleep(1);
|
||||||
while (StreamReceiver.packetBuffer.peek() == null) {
|
while (StreamReceiver.packetBuffer.peek() == null) {
|
||||||
Thread.sleep(1);
|
Thread.sleep(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println("END OF STREAM");
|
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -311,28 +310,30 @@ public class StreamParser extends Thread{
|
|||||||
byte[] headingBytes = Arrays.copyOfRange(payload,28,30);
|
byte[] headingBytes = Arrays.copyOfRange(payload,28,30);
|
||||||
byte[] groundSpeedBytes = Arrays.copyOfRange(payload,38,40);
|
byte[] groundSpeedBytes = Arrays.copyOfRange(payload,38,40);
|
||||||
|
|
||||||
long timeStamp = bytesToLong(Arrays.copyOfRange(payload,1,7));
|
long timeValid = bytesToLong(Arrays.copyOfRange(payload,1,7));
|
||||||
// int boatSeq = ByteBuffer.wrap(seqBytes).getInt();
|
// int boatSeq = ByteBuffer.wrap(seqBytes).getInt();
|
||||||
long seq = bytesToLong(seqBytes);
|
long seq = bytesToLong(seqBytes);
|
||||||
long boatId = bytesToLong(boatIdBytes);
|
long boatId = bytesToLong(boatIdBytes);
|
||||||
long lat = bytesToLong(latBytes);
|
long rawLat = bytesToLong(latBytes);
|
||||||
long lon = bytesToLong(lonBytes);
|
long rawLon = bytesToLong(lonBytes);
|
||||||
|
double lat = ((180d * (double)rawLat)/Math.pow(2,31));
|
||||||
|
double lon = ((180d *(double)rawLon)/Math.pow(2,31));
|
||||||
long heading = bytesToLong(headingBytes);
|
long heading = bytesToLong(headingBytes);
|
||||||
// long speed = bytesToLong(speedBytes);
|
|
||||||
double groundSpeed = bytesToLong(groundSpeedBytes)/1000.0;
|
double groundSpeed = bytesToLong(groundSpeedBytes)/1000.0;
|
||||||
short s = (short) ((groundSpeedBytes[1] & 0xFF) << 8 | (groundSpeedBytes[0] & 0xFF));
|
short s = (short) ((groundSpeedBytes[1] & 0xFF) << 8 | (groundSpeedBytes[0] & 0xFF));
|
||||||
if ((int)deviceType == 1 || (int)deviceType == 3){
|
if ((int)deviceType == 1 || (int)deviceType == 3){
|
||||||
// System.out.println("boatId = " + boatId);
|
|
||||||
// System.out.println("deviceType = " + (long)deviceType);
|
BoatPositionPacket boatPacket = new BoatPositionPacket(boatId, timeValid, lat, lon, heading, groundSpeed);
|
||||||
// System.out.println("seq = " + seq);
|
|
||||||
//needs to be validated
|
if (!boatPositions.containsKey(boatId)){
|
||||||
Point3D point = new Point3D(((180d * (double)lat)/Math.pow(2,31)),((180d *(double)lon)/Math.pow(2,31)),(double)heading);
|
boatPositions.put(boatId, new PriorityBlockingQueue<BoatPositionPacket>(256, new Comparator<BoatPositionPacket>() {
|
||||||
boatPositions.put(boatId, point);
|
@Override
|
||||||
boatSpeeds.put(boatId, groundSpeed);
|
public int compare(BoatPositionPacket p1, BoatPositionPacket p2) {
|
||||||
// boatPositions.replace(boatId, point);
|
return (int) (p1.getTimeValid() - p2.getTimeValid());
|
||||||
// boatSpeeds.replace(boatId, groundSpeed);
|
}
|
||||||
// System.out.println("lon = " + ((180d * (double)lon)/Math.pow(2,31)));
|
}));
|
||||||
// System.out.println("lat = " + ((180d *(double)lat)/Math.pow(2,31)));
|
}
|
||||||
|
boatPositions.get(boatId).put(boatPacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,14 +448,6 @@ public class StreamParser extends Thread{
|
|||||||
return boats;
|
return boats;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ConcurrentHashMap<Long, Point3D> getBoatPositions() {
|
|
||||||
return boatPositions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConcurrentHashMap<Long, Double> getBoatSpeeds() {
|
|
||||||
return boatSpeeds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static XMLParser getXmlObject() {
|
public static XMLParser getXmlObject() {
|
||||||
return xmlObject;
|
return xmlObject;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package seng302.models.parsers;
|
package seng302.models.parsers;
|
||||||
|
|
||||||
|
import seng302.models.parsers.packets.StreamPacket;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -85,9 +87,6 @@ public class StreamReceiver extends Thread {
|
|||||||
long computedCrc = checksum.getValue();
|
long computedCrc = checksum.getValue();
|
||||||
long packetCrc = bytesToLong(getBytes(4));
|
long packetCrc = bytesToLong(getBytes(4));
|
||||||
if (computedCrc == packetCrc) {
|
if (computedCrc == packetCrc) {
|
||||||
// System.out.println("message type: " + type);
|
|
||||||
// System.out.println("timeStamp = " + timeStamp);
|
|
||||||
// System.out.println("payload length: " + payloadLength);
|
|
||||||
packetBuffer.add(new StreamPacket(type, payloadLength, timeStamp, payload));
|
packetBuffer.add(new StreamPacket(type, payloadLength, timeStamp, payload));
|
||||||
} else {
|
} else {
|
||||||
System.err.println("Packet has been dropped");
|
System.err.println("Packet has been dropped");
|
||||||
@@ -133,7 +132,7 @@ public class StreamReceiver extends Thread {
|
|||||||
* takes an array of up to 7 bytes in little endian format and
|
* takes an array of up to 7 bytes in little endian format and
|
||||||
* returns a positive long constructed from the input bytes
|
* returns a positive long constructed from the input bytes
|
||||||
*
|
*
|
||||||
* @return a positive long if there is less than 7 bytes -1 otherwise
|
* @return a positive long if there is less than 8 bytes -1 otherwise
|
||||||
*/
|
*/
|
||||||
private long bytesToLong(byte[] bytes){
|
private long bytesToLong(byte[] bytes){
|
||||||
long partialLong = 0;
|
long partialLong = 0;
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package seng302.models.parsers.packets;
|
||||||
|
|
||||||
|
public class BoatPositionPacket {
|
||||||
|
private long boatId;
|
||||||
|
private long timeValid;
|
||||||
|
private double lat;
|
||||||
|
private double lon;
|
||||||
|
private double heading;
|
||||||
|
private double groundSpeed;
|
||||||
|
|
||||||
|
public BoatPositionPacket(long boatId, long timeValid, double lat, double lon, double heading, double groundSpeed) {
|
||||||
|
this.boatId = boatId;
|
||||||
|
this.timeValid = timeValid;
|
||||||
|
this.lat = lat;
|
||||||
|
this.lon = lon;
|
||||||
|
this.heading = heading;
|
||||||
|
this.groundSpeed = groundSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimeValid() {
|
||||||
|
return timeValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLat() {
|
||||||
|
return lat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLon() {
|
||||||
|
return lon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeading() {
|
||||||
|
return heading;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getGroundSpeed() {
|
||||||
|
return groundSpeed;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package seng302.models.parsers.packets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Kusal on 4/24/2017.
|
||||||
|
*/
|
||||||
|
public enum PacketType {
|
||||||
|
HEARTBEAT,
|
||||||
|
RACE_STATUS,
|
||||||
|
DISPLAY_TEXT_MESSAGE,
|
||||||
|
XML_MESSAGE,
|
||||||
|
RACE_START_STATUS,
|
||||||
|
YACHT_EVENT_CODE,
|
||||||
|
YACHT_ACTION_CODE,
|
||||||
|
CHATTER_TEXT,
|
||||||
|
BOAT_LOCATION,
|
||||||
|
MARK_ROUNDING,
|
||||||
|
COURSE_WIND,
|
||||||
|
AVG_WIND,
|
||||||
|
OTHER;
|
||||||
|
|
||||||
|
public static PacketType assignPacketType(int packetType){
|
||||||
|
switch(packetType){
|
||||||
|
case 1:
|
||||||
|
return HEARTBEAT;
|
||||||
|
case 12:
|
||||||
|
return RACE_STATUS;
|
||||||
|
case 20:
|
||||||
|
return DISPLAY_TEXT_MESSAGE;
|
||||||
|
case 26:
|
||||||
|
return XML_MESSAGE;
|
||||||
|
case 27:
|
||||||
|
return RACE_START_STATUS;
|
||||||
|
case 29:
|
||||||
|
return YACHT_EVENT_CODE;
|
||||||
|
case 31:
|
||||||
|
return YACHT_ACTION_CODE;
|
||||||
|
case 36:
|
||||||
|
return CHATTER_TEXT;
|
||||||
|
case 37:
|
||||||
|
return BOAT_LOCATION;
|
||||||
|
case 38:
|
||||||
|
return MARK_ROUNDING;
|
||||||
|
case 44:
|
||||||
|
return COURSE_WIND;
|
||||||
|
case 47:
|
||||||
|
return AVG_WIND;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package seng302.models.parsers.packets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by kre39 on 23/04/17.
|
||||||
|
*/
|
||||||
|
public class StreamPacket {
|
||||||
|
|
||||||
|
//Change int to an ENUM for the type
|
||||||
|
private PacketType type;
|
||||||
|
|
||||||
|
private long messageLength;
|
||||||
|
private long timeStamp;
|
||||||
|
private byte[] payload;
|
||||||
|
|
||||||
|
public StreamPacket(int type, long messageLength, long timeStamp, byte[] payload) {
|
||||||
|
this.type = PacketType.assignPacketType(type);
|
||||||
|
this.messageLength = messageLength;
|
||||||
|
this.timeStamp = timeStamp;
|
||||||
|
this.payload = payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMessageLength() {
|
||||||
|
return messageLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getPayload() {
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimeStamp() {
|
||||||
|
return timeStamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user