From: Keith Packard Date: Sun, 10 Feb 2013 23:34:56 +0000 (-0800) Subject: altosui: Add map and GPS data to graph window. Trac #50 X-Git-Tag: altosdroid_v1.2-1~114 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=cbd9dd989a662f41ddcb0c9e0f4453840687fd4a 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 --- 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);