package com.aerodynelabs.habtk.ui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import javax.swing.JPanel;
import javax.swing.SpringLayout;
import javax.swing.JLabel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.Timer;
import com.aerodynelabs.habtk.tracking.PositionEvent;
import com.aerodynelabs.habtk.tracking.PositionListener;
import com.aerodynelabs.map.MapPoint;
/**
* A panel to display tracking information
* @author Ethan Harstad
*
*/
@SuppressWarnings("serial")
public class TrackingPanel extends JPanel implements PositionListener, ActionListener {
private JTextField curAlt;
private JTextField curLon;
private JTextField curLat;
private JTextField curTime;
private JTextField curSpd;
private JTextField curAR;
private JTextField burAlt;
private JTextField burLon;
private JTextField burLat;
private JTextField burTime;
private JTextField lndAlt;
private JTextField lndLon;
private JTextField lndLat;
private JTextField lndTime;
private JTextField curVOR;
private JTextField burVOR;
private JTextField lndVOR;
private Date time, cTime, bTime, lTime;
private MapPoint prevPoint;
private Timer timer;
public TrackingPanel() {
super();
SpringLayout springLayout = new SpringLayout();
setLayout(springLayout);
// Curent Values
JLabel lblCurrent = new JLabel("Current");
springLayout.putConstraint(SpringLayout.NORTH, lblCurrent, 6, SpringLayout.NORTH, this);
springLayout.putConstraint(SpringLayout.WEST, lblCurrent, 10, SpringLayout.WEST, this);
add(lblCurrent);
JSeparator sepCurrent = new JSeparator();
springLayout.putConstraint(SpringLayout.VERTICAL_CENTER, sepCurrent, 0, SpringLayout.VERTICAL_CENTER, lblCurrent);
springLayout.putConstraint(SpringLayout.WEST, sepCurrent, 6, SpringLayout.EAST, lblCurrent);
springLayout.putConstraint(SpringLayout.EAST, sepCurrent, -6, SpringLayout.EAST, this);
add(sepCurrent);
JLabel lblCurLat = new JLabel("Latitude:");
JLabel lblCurLon = new JLabel("Longitude:");
JLabel lblCurAlt = new JLabel("Altitude:");
JLabel lblCurTime = new JLabel("Time:");
JLabel lblCurSpd = new JLabel("Speed:");
JLabel lblCurAR = new JLabel("Ascent Rate:");
JLabel lblCurVOR = new JLabel("VOR:");
curAlt = new JTextField();
curAlt.setEditable(false);
curLon = new JTextField();
curLon.setEditable(false);
curLat = new JTextField();
curLat.setEditable(false);
curTime = new JTextField();
curTime.setEditable(false);
curSpd = new JTextField();
curSpd.setEditable(false);
curAR = new JTextField();
curAR.setEditable(false);
curVOR = new JTextField();
curVOR.setEditable(false);
springLayout.putConstraint(SpringLayout.WEST, lblCurLon, 6, SpringLayout.WEST, lblCurrent);
springLayout.putConstraint(SpringLayout.EAST, lblCurLat, 0, SpringLayout.EAST, lblCurLon);
springLayout.putConstraint(SpringLayout.EAST, lblCurAlt, 0, SpringLayout.EAST, lblCurLon);
springLayout.putConstraint(SpringLayout.EAST, lblCurTime, 0, SpringLayout.EAST, lblCurLon);
springLayout.putConstraint(SpringLayout.EAST, lblCurSpd, 0, SpringLayout.EAST, lblCurLon);
springLayout.putConstraint(SpringLayout.EAST, lblCurAR, 0, SpringLayout.EAST, lblCurLon);
springLayout.putConstraint(SpringLayout.BASELINE, lblCurLat, 0, SpringLayout.BASELINE, curLat);
springLayout.putConstraint(SpringLayout.BASELINE, lblCurLon, 0, SpringLayout.BASELINE, curLon);
springLayout.putConstraint(SpringLayout.BASELINE, lblCurAlt, 0, SpringLayout.BASELINE, curAlt);
springLayout.putConstraint(SpringLayout.BASELINE, lblCurTime, 0, SpringLayout.BASELINE, curTime);
springLayout.putConstraint(SpringLayout.BASELINE, lblCurSpd, 0, SpringLayout.BASELINE, curSpd);
springLayout.putConstraint(SpringLayout.BASELINE, lblCurAR, 0, SpringLayout.BASELINE, curAR);
springLayout.putConstraint(SpringLayout.NORTH, curLat, 6, SpringLayout.SOUTH, curTime);
springLayout.putConstraint(SpringLayout.NORTH, curLon, 6, SpringLayout.SOUTH, curLat);
springLayout.putConstraint(SpringLayout.NORTH, curAlt, 6, SpringLayout.SOUTH, curLon);
springLayout.putConstraint(SpringLayout.NORTH, curTime, 6, SpringLayout.SOUTH, lblCurrent);
springLayout.putConstraint(SpringLayout.NORTH, curSpd, 6, SpringLayout.SOUTH, curAlt);
springLayout.putConstraint(SpringLayout.NORTH, curAR, 6, SpringLayout.SOUTH, curSpd);
springLayout.putConstraint(SpringLayout.WEST, curLat, 6, SpringLayout.EAST, lblCurLat);
springLayout.putConstraint(SpringLayout.WEST, curLon, 6, SpringLayout.EAST, lblCurLon);
springLayout.putConstraint(SpringLayout.WEST, curAlt, 6, SpringLayout.EAST, lblCurAlt);
springLayout.putConstraint(SpringLayout.WEST, curTime, 6, SpringLayout.EAST, lblCurTime);
springLayout.putConstraint(SpringLayout.WEST, curSpd, 6, SpringLayout.EAST, lblCurSpd);
springLayout.putConstraint(SpringLayout.WEST, curAR, 6, SpringLayout.EAST, lblCurAR);
springLayout.putConstraint(SpringLayout.EAST, curLat, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.EAST, curLon, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.EAST, curAlt, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.EAST, curTime, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.EAST, curSpd, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.EAST, curAR, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.NORTH, curVOR, 6, SpringLayout.SOUTH, curAR);
springLayout.putConstraint(SpringLayout.BASELINE, lblCurVOR, 0, SpringLayout.BASELINE, curVOR);
springLayout.putConstraint(SpringLayout.EAST, lblCurVOR, 0, SpringLayout.EAST, lblCurLon);
springLayout.putConstraint(SpringLayout.WEST, curVOR, 6, SpringLayout.EAST, lblCurVOR);
springLayout.putConstraint(SpringLayout.EAST, curVOR, -6, SpringLayout.EAST, this);
add(lblCurLat);
add(lblCurLon);
add(lblCurAlt);
add(lblCurTime);
add(lblCurSpd);
add(lblCurAR);
add(lblCurVOR);
add(curLat);
add(curLon);
add(curAlt);
add(curTime);
add(curSpd);
add(curAR);
add(curVOR);
// Burst Values
JLabel lblBurst = new JLabel("Burst");
springLayout.putConstraint(SpringLayout.NORTH, lblBurst, 6, SpringLayout.SOUTH, curVOR);
springLayout.putConstraint(SpringLayout.WEST, lblBurst, 10, SpringLayout.WEST, this);
add(lblBurst);
JSeparator sepBurst = new JSeparator();
springLayout.putConstraint(SpringLayout.VERTICAL_CENTER, sepBurst, 0, SpringLayout.VERTICAL_CENTER, lblBurst);
springLayout.putConstraint(SpringLayout.WEST, sepBurst, 6, SpringLayout.EAST, lblBurst);
springLayout.putConstraint(SpringLayout.EAST, sepBurst, -6, SpringLayout.EAST, this);
add(sepBurst);
JLabel lblBurTime = new JLabel("Time:");
JLabel lblBurLat = new JLabel("Latitude:");
JLabel lblBurLon = new JLabel("Longitude:");
JLabel lblBurAlt = new JLabel("Altitude:");
JLabel lblBurVOR = new JLabel("VOR:");
burTime = new JTextField();
burTime.setEditable(false);
burLat = new JTextField();
burLat.setEditable(false);
burLon = new JTextField();
burLon.setEditable(false);
burAlt = new JTextField();
burAlt.setEditable(false);
burVOR = new JTextField();
burVOR.setEditable(false);
springLayout.putConstraint(SpringLayout.WEST, lblBurLon, 6, SpringLayout.WEST, lblBurst);
springLayout.putConstraint(SpringLayout.EAST, lblBurTime, 0, SpringLayout.EAST, lblBurLon);
springLayout.putConstraint(SpringLayout.EAST, lblBurLat, 0, SpringLayout.EAST, lblBurLon);
springLayout.putConstraint(SpringLayout.EAST, lblBurAlt, 0, SpringLayout.EAST, lblBurLon);
springLayout.putConstraint(SpringLayout.WEST, burTime, 6, SpringLayout.EAST, lblBurTime);
springLayout.putConstraint(SpringLayout.WEST, burLat, 6, SpringLayout.EAST, lblBurLat);
springLayout.putConstraint(SpringLayout.WEST, burLon, 6, SpringLayout.EAST, lblBurLon);
springLayout.putConstraint(SpringLayout.WEST, burAlt, 6, SpringLayout.EAST, lblBurAlt);
springLayout.putConstraint(SpringLayout.EAST, burTime, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.EAST, burLat, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.EAST, burLon, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.EAST, burAlt, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.NORTH, burTime, 6, SpringLayout.SOUTH, lblBurst);
springLayout.putConstraint(SpringLayout.NORTH, burLat, 6, SpringLayout.SOUTH, burTime);
springLayout.putConstraint(SpringLayout.NORTH, burLon, 6, SpringLayout.SOUTH, burLat);
springLayout.putConstraint(SpringLayout.NORTH, burAlt, 6, SpringLayout.SOUTH, burLon);
springLayout.putConstraint(SpringLayout.BASELINE, lblBurTime, 0, SpringLayout.BASELINE, burTime);
springLayout.putConstraint(SpringLayout.BASELINE, lblBurLat, 0, SpringLayout.BASELINE, burLat);
springLayout.putConstraint(SpringLayout.BASELINE, lblBurLon, 0, SpringLayout.BASELINE, burLon);
springLayout.putConstraint(SpringLayout.BASELINE, lblBurAlt, 0, SpringLayout.BASELINE, burAlt);
springLayout.putConstraint(SpringLayout.NORTH, burVOR, 6, SpringLayout.SOUTH, burAlt);
springLayout.putConstraint(SpringLayout.BASELINE, lblBurVOR, 0, SpringLayout.BASELINE, burVOR);
springLayout.putConstraint(SpringLayout.EAST, lblBurVOR, 0, SpringLayout.EAST, lblBurLon);
springLayout.putConstraint(SpringLayout.WEST, burVOR, 6, SpringLayout.EAST, lblBurVOR);
springLayout.putConstraint(SpringLayout.EAST, burVOR, -6, SpringLayout.EAST, this);
add(lblBurTime);
add(lblBurLat);
add(lblBurLon);
add(lblBurAlt);
add(lblBurVOR);
add(burTime);
add(burLat);
add(burLon);
add(burAlt);
add(burVOR);
// Landing values
JLabel lblLanding = new JLabel("Landing");
springLayout.putConstraint(SpringLayout.NORTH, lblLanding, 6, SpringLayout.SOUTH, burVOR);
springLayout.putConstraint(SpringLayout.WEST, lblLanding, 10, SpringLayout.WEST, this);
add(lblLanding);
JSeparator sepLanding = new JSeparator();
springLayout.putConstraint(SpringLayout.VERTICAL_CENTER, sepLanding, 0, SpringLayout.VERTICAL_CENTER, lblLanding);
springLayout.putConstraint(SpringLayout.WEST, sepLanding, 6, SpringLayout.EAST, lblLanding);
springLayout.putConstraint(SpringLayout.EAST, sepLanding, -6, SpringLayout.EAST, this);
add(sepLanding);
JLabel lblLndTime = new JLabel("Time:");
JLabel lblLndLat = new JLabel("Latitude:");
JLabel lblLndLon = new JLabel("Longitude:");
JLabel lblLndAlt = new JLabel("Altitude:");
JLabel lblLndVOR = new JLabel("VOR:");
lndTime = new JTextField();
lndTime.setEditable(false);
lndLat = new JTextField();
lndLat.setEditable(false);
lndLon = new JTextField();
lndLon.setEditable(false);
lndAlt = new JTextField();
lndAlt.setEditable(false);
lndVOR = new JTextField();
lndVOR.setEditable(false);
springLayout.putConstraint(SpringLayout.WEST, lblLndLon, 6, SpringLayout.WEST, lblLanding);
springLayout.putConstraint(SpringLayout.EAST, lblLndTime, 0, SpringLayout.EAST, lblLndLon);
springLayout.putConstraint(SpringLayout.EAST, lblLndLat, 0, SpringLayout.EAST, lblLndLon);
springLayout.putConstraint(SpringLayout.EAST, lblLndAlt, 0, SpringLayout.EAST, lblLndLon);
springLayout.putConstraint(SpringLayout.WEST, lndTime, 6, SpringLayout.EAST, lblLndLat);
springLayout.putConstraint(SpringLayout.WEST, lndLat, 6, SpringLayout.EAST, lblLndLat);
springLayout.putConstraint(SpringLayout.WEST, lndLon, 6, SpringLayout.EAST, lblLndLon);
springLayout.putConstraint(SpringLayout.WEST, lndAlt, 6, SpringLayout.EAST, lblLndAlt);
springLayout.putConstraint(SpringLayout.NORTH, lndTime, 6, SpringLayout.SOUTH, lblLanding);
springLayout.putConstraint(SpringLayout.NORTH, lndLat, 6, SpringLayout.SOUTH, lndTime);
springLayout.putConstraint(SpringLayout.NORTH, lndLon, 6, SpringLayout.SOUTH, lndLat);
springLayout.putConstraint(SpringLayout.NORTH, lndAlt, 6, SpringLayout.SOUTH, lndLon);
springLayout.putConstraint(SpringLayout.EAST, lndTime, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.EAST, lndLat, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.EAST, lndLon, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.EAST, lndAlt, -6, SpringLayout.EAST, this);
springLayout.putConstraint(SpringLayout.BASELINE, lblLndTime, 0, SpringLayout.BASELINE, lndTime);
springLayout.putConstraint(SpringLayout.BASELINE, lblLndLat, 0, SpringLayout.BASELINE, lndLat);
springLayout.putConstraint(SpringLayout.BASELINE, lblLndLon, 0, SpringLayout.BASELINE, lndLon);
springLayout.putConstraint(SpringLayout.BASELINE, lblLndAlt, 0, SpringLayout.BASELINE, lndAlt);
springLayout.putConstraint(SpringLayout.NORTH, lndVOR, 6, SpringLayout.SOUTH, lndAlt);
springLayout.putConstraint(SpringLayout.BASELINE, lblLndVOR, 0, SpringLayout.BASELINE, lndVOR);
springLayout.putConstraint(SpringLayout.EAST, lblLndVOR, 0, SpringLayout.EAST, lblLndLon);
springLayout.putConstraint(SpringLayout.WEST, lndVOR, 6, SpringLayout.EAST, lblLndVOR);
springLayout.putConstraint(SpringLayout.EAST, lndVOR, -6, SpringLayout.EAST, this);
add(lblLndTime);
add(lblLndLat);
add(lblLndLon);
add(lblLndAlt);
add(lblLndVOR);
add(lndTime);
add(lndLat);
add(lndLon);
add(lndAlt);
add(lndVOR);
timer = new Timer(1000, this);
timer.start();
}
@Override
public void positionUpdateEvent(PositionEvent e) {
switch(e.getSource()) {
case PositionEvent.PRIMARY:
//curLat.setText(Double.toString(e.getPosition().getLatitude()));
curLat.setText(formatPosition(e.getPosition().getLatitude(), e.getPosition().getLongitude()));
curLon.setText(Double.toString(e.getPosition().getLongitude()));
curAlt.setText(Double.toString(e.getPosition().getAltitude()));
cTime = new Date(e.getPosition().getTime() * 1000);
updateTimes();
// Compute derived fields
MapPoint p = e.getPosition();
if(prevPoint != null) {
// Ascent rate
long dt = p.getTime() - prevPoint.getTime();
double dz = p.getAltitude() - prevPoint.getAltitude();
double ar = dz / dt;
double ars = Math.round(ar * 10.0) / 10.0;
double arm = Math.round((ar * 60.0) * 10.0) / 10.0;
curAR.setText(ars + " m/s (" + arm + "m/min)");
// Speed
double R = 6371008.7714;
double dLat = Math.toRadians(p.getLatitude() - prevPoint.getLatitude());
double dLon = Math.toRadians(p.getLongitude() - prevPoint.getLongitude());
double lat1 = Math.toRadians(prevPoint.getLatitude());
double lat2 = Math.toRadians(p.getLatitude());
double a = Math.sin(dLat / 2.0) * Math.sin(dLat / 2.0) + Math.sin(dLon / 2.0) * Math.sin(dLon / 2.0) * Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double d = R * c;
double spd = d / dt;
double spds = Math.round(spd * 10.0) / 10.0;
double spdh = Math.round(spd * 60 * 60 * 10) / 10000;
curSpd.setText(spds + " m/s (" + spdh + " km/h)");
}
prevPoint = p;
break;
case PositionEvent.SECONDARY:
break;
case PositionEvent.RECOVERY:
break;
case PositionEvent.BURST:
burLat.setText(Double.toString(e.getPosition().getLatitude()));
burLon.setText(Double.toString(e.getPosition().getLongitude()));
burAlt.setText(Double.toString(e.getPosition().getAltitude()));
bTime = new Date(e.getPosition().getTime() * 1000);
updateTimes();
break;
case PositionEvent.LANDING:
lndLat.setText(Double.toString(e.getPosition().getLatitude()));
lndLon.setText(Double.toString(e.getPosition().getLongitude()));
lndAlt.setText(Double.toString(e.getPosition().getAltitude()));
lTime = new Date(e.getPosition().getTime() * 1000);
updateTimes();
break;
}
}
private String formatPosition(double lat, double lon) {
return String.format("%+#.4f, %+#.4f", lat, lon);
}
private void updateTimes() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
String prefix;
Date tMinus;
time = new Date();
if(cTime != null) {
tMinus = new Date(time.getTime() - cTime.getTime());
prefix = tMinus.getTime() < 0 ? "T-" : "T+";
curTime.setText(prefix + sdf.format(tMinus) + " (" + sdf.format(cTime) + ")");
}
if(bTime != null) {
tMinus = new Date(bTime.getTime() - time.getTime());
prefix = tMinus.getTime() < 0 ? "T+" : "T-";
burTime.setText(prefix + sdf.format(tMinus) + " (" + sdf.format(bTime) + ")");
}
if(lTime != null) {
tMinus = new Date(lTime.getTime() - time.getTime());
prefix = tMinus.getTime() < 0 ? "T+" : "T-";
lndTime.setText(prefix + sdf.format(tMinus) + " (" + sdf.format(lTime) + ")");
}
}
@Override
public void actionPerformed(ActionEvent e) {
updateTimes();
}
}