summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2013-02-10 15:34:56 -0800
committerKeith Packard <keithp@keithp.com>2013-02-10 18:15:25 -0800
commitcbd9dd989a662f41ddcb0c9e0f4453840687fd4a (patch)
tree527a04c75036b5db1003fa8b48a53fbbc081ca78
parentf0a125503e502d213711df0d7774d837d4d98447 (diff)
altosui: Add map and GPS data to graph window. Trac #50
See where the rocket landed without having to replay the whole flight. Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--altosui/AltosFlightStats.java11
-rw-r--r--altosui/AltosFlightStatsTable.java56
-rw-r--r--altosui/AltosGraphUI.java23
-rw-r--r--altosui/AltosSiteMap.java16
4 files changed, 94 insertions, 12 deletions
diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java
index 0f32ae5e..7f0c9adb 100644
--- a/altosui/AltosFlightStats.java
+++ b/altosui/AltosFlightStats.java
@@ -34,6 +34,8 @@ public class AltosFlightStats {
int flight;
int year, month, day;
int hour, minute, second;
+ double lat, lon;
+ double pad_lat, pad_lon;
double landed_time(AltosRecordIterable iterable) {
AltosState state = null;
@@ -98,6 +100,7 @@ public class AltosFlightStats {
year = month = day = -1;
hour = minute = second = -1;
serial = flight = -1;
+ lat = lon = -1;
for (AltosRecord record : iterable) {
if (serial < 0)
serial = record.serial;
@@ -137,6 +140,14 @@ public class AltosFlightStats {
max_speed = state.max_baro_speed;
max_acceleration = state.max_acceleration;
}
+ if (state.gps.locked && state.gps.nsat >= 4) {
+ if (state.state <= Altos.ao_flight_pad) {
+ pad_lat = state.gps.lat;
+ pad_lon = state.gps.lon;
+ }
+ lat = state.gps.lat;
+ lon = state.gps.lon;
+ }
}
for (int s = Altos.ao_flight_startup; s <= Altos.ao_flight_landed; s++) {
if (state_count[s] > 0) {
diff --git a/altosui/AltosFlightStatsTable.java b/altosui/AltosFlightStatsTable.java
index 2b3e4d5d..5ed53c1a 100644
--- a/altosui/AltosFlightStatsTable.java
+++ b/altosui/AltosFlightStatsTable.java
@@ -58,6 +58,17 @@ public class AltosFlightStatsTable extends JComponent {
}
+ static String pos(double p, String pos, String neg) {
+ String h = pos;
+ if (p < 0) {
+ h = neg;
+ p = -p;
+ }
+ int deg = (int) Math.floor(p);
+ double min = (p - Math.floor(p)) * 60.0;
+ return String.format("%s %4d° %9.6f'", h, deg, min);
+ }
+
public AltosFlightStatsTable(AltosFlightStats stats) {
layout = new GridBagLayout();
@@ -65,12 +76,18 @@ public class AltosFlightStatsTable extends JComponent {
int y = 0;
new FlightStat(layout, y++, "Serial", String.format("%d", stats.serial));
new FlightStat(layout, y++, "Flight", String.format("%d", stats.flight));
- if (stats.year > 0)
- new FlightStat(layout, y++, "Date",
- String.format("%04d-%02d-%02d", stats.year, stats.month, stats.day));
- if (stats.hour > 0)
- new FlightStat(layout, y++, "Time",
+ if (stats.year > 0 && stats.hour > 0)
+ new FlightStat(layout, y++, "Date/Time",
+ String.format("%04d-%02d-%02d", stats.year, stats.month, stats.day),
String.format("%02d:%02d:%02d UTC", stats.hour, stats.minute, stats.second));
+ else {
+ if (stats.year > 0)
+ new FlightStat(layout, y++, "Date",
+ String.format("%04d-%02d-%02d", stats.year, stats.month, stats.day));
+ if (stats.hour > 0)
+ new FlightStat(layout, y++, "Time",
+ String.format("%02d:%02d:%02d UTC", stats.hour, stats.minute, stats.second));
+ }
new FlightStat(layout, y++, "Maximum height",
String.format("%5.0f m", stats.max_height),
String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height)));
@@ -94,14 +111,29 @@ public class AltosFlightStatsTable extends JComponent {
new FlightStat(layout, y++, "Main descent rate",
String.format("%5.0f m/s", stats.state_baro_speed[Altos.ao_flight_main]),
String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_baro_speed[Altos.ao_flight_main])));
- for (int s = Altos.ao_flight_boost; s <= Altos.ao_flight_main; s++) {
- new FlightStat(layout, y++, String.format("%s time", AltosLib.state_name_capital(s)),
- String.format("%6.0f s", stats.state_end[s] - stats.state_start[s]));
- }
- new FlightStat(layout, y++, "Flight Time",
- String.format("%6.0f s", stats.state_end[Altos.ao_flight_main] -
+ new FlightStat(layout, y++, "Ascent time",
+ String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_boost] - stats.state_start[AltosLib.ao_flight_boost],
+ AltosLib.state_name(Altos.ao_flight_boost)),
+ String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_fast] - stats.state_start[AltosLib.ao_flight_fast],
+ AltosLib.state_name(Altos.ao_flight_fast)),
+ String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_coast] - stats.state_start[AltosLib.ao_flight_coast],
+ AltosLib.state_name(Altos.ao_flight_coast)));
+ new FlightStat(layout, y++, "Descent time",
+ String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_drogue] - stats.state_start[AltosLib.ao_flight_drogue],
+ AltosLib.state_name(Altos.ao_flight_drogue)),
+ String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_main] - stats.state_start[AltosLib.ao_flight_main],
+ AltosLib.state_name(Altos.ao_flight_main)));
+ new FlightStat(layout, y++, "Flight time",
+ String.format("%6.1f s", stats.state_end[Altos.ao_flight_main] -
stats.state_start[Altos.ao_flight_boost]));
-
+ if (stats.lat != -1 && stats.lon != -1) {
+ new FlightStat(layout, y++, "Pad location",
+ pos(stats.pad_lat,"N","S"),
+ pos(stats.pad_lon,"E","W"));
+ new FlightStat(layout, y++, "Last reported location",
+ pos(stats.lat,"N","S"),
+ pos(stats.lon,"E","W"));
+ }
}
} \ No newline at end of file
diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java
index b376f7de..ac20f84b 100644
--- a/altosui/AltosGraphUI.java
+++ b/altosui/AltosGraphUI.java
@@ -21,8 +21,24 @@ public class AltosGraphUI extends AltosUIFrame
JTabbedPane pane;
AltosGraph graph;
AltosUIEnable enable;
+ AltosSiteMap map;
+ AltosState state;
+
+ boolean fill_map(AltosRecordIterable records) {
+ boolean any_gps = false;
+ for (AltosRecord record : records) {
+ state = new AltosState(record, state);
+ if (state.data.gps != null) {
+ map.show(state, 0);
+ any_gps = true;
+ }
+ }
+ return any_gps;
+ }
AltosGraphUI(AltosRecordIterable records, String file) throws InterruptedException, IOException {
+ state = null;
+
pane = new JTabbedPane();
enable = new AltosUIEnable();
@@ -31,17 +47,24 @@ public class AltosGraphUI extends AltosUIFrame
graph.setDataSet(new AltosGraphDataSet(records));
+ map = new AltosSiteMap();
+
pane.add("Flight Graph", graph.panel);
pane.add("Configure Graph", enable);
AltosFlightStatsTable stats = new AltosFlightStatsTable(new AltosFlightStats(records));
pane.add("Flight Statistics", stats);
+ if (fill_map(records))
+ pane.add("Map", map);
+
setContentPane (pane);
pack();
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setVisible(true);
+ if (state != null)
+ map.centre(state);
}
}
diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java
index f111e62d..f614eae6 100644
--- a/altosui/AltosSiteMap.java
+++ b/altosui/AltosSiteMap.java
@@ -322,6 +322,22 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay {
last_state = state.state;
}
+ public void centre(Point2D.Double pt) {
+ Rectangle r = comp.getVisibleRect();
+ Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft));
+ int dx = (int)copt.x - r.width/2 - r.x;
+ int dy = (int)copt.y - r.height/2 - r.y;
+ r.x += dx;
+ r.y += dy;
+ comp.scrollRectToVisible(r);
+ }
+
+ public void centre(AltosState state) {
+ if (!state.gps.locked && state.gps.nsat < 4)
+ return;
+ centre(pt(state.gps.lat, state.gps.lon));
+ }
+
public void draw_circle(double lat, double lon) {
final Point2D.Double pt = pt(lat, lon);