altoslib: Don't crash if there's no GPS coord to write KML
[fw/altos] / altoslib / AltosReplayReader.java
1 /*
2  * Copyright © 2010 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 package org.altusmetrum.altoslib_12;
20
21 import java.io.*;
22 import java.util.*;
23 import java.util.concurrent.*;
24
25 /*
26  * Open an existing telemetry file and replay it in realtime
27  */
28
29 class AltosReplay extends AltosDataListener implements Runnable {
30
31         AltosState      state;
32         AltosRecordSet  record_set;
33         double          last_time = AltosLib.MISSING;
34         Semaphore       semaphore = new Semaphore(1);;
35         boolean         done = false;
36
37         public void set_time(double time) {
38                 if (last_time != AltosLib.MISSING) {
39                         semaphore.release();
40                         double  delay = Math.min(time - last_time,10);
41                         if (delay > 0) {
42                                 try {
43                                         Thread.sleep((int) (delay * 1000));
44                                 } catch (InterruptedException ie) {
45                                 }
46                         }
47                 }
48                 last_time = time;
49                 super.set_time(time);
50                 state.set_time(time);
51         }
52
53         public void set_state(int state) {
54                 super.set_state(state);
55                 this.state.set_state(state);
56         }
57
58         public void set_rssi(int rssi, int status) { state.set_rssi(rssi, status); }
59         public void set_received_time(long received_time) { }
60
61         public void set_acceleration(double accel) { state.set_acceleration(accel); }
62         public void set_pressure(double pa) { state.set_pressure(pa); }
63         public void set_thrust(double N) { state.set_thrust(N); }
64
65         public void set_kalman(double height, double speed, double accel) { state.set_kalman(height, speed, accel); }
66
67         public void set_temperature(double deg_c) { state.set_temperature(deg_c); }
68         public void set_battery_voltage(double volts) { state.set_battery_voltage(volts); }
69
70         public void set_apogee_voltage(double volts) { state.set_apogee_voltage(volts); }
71         public void set_main_voltage(double volts) { state.set_main_voltage(volts); }
72
73         public void set_gps(AltosGPS gps) { state.set_gps(gps); }
74
75         public void set_orient(double orient) { state.set_orient(orient); }
76         public void set_gyro(double roll, double pitch, double yaw) { state.set_gyro(roll, pitch, yaw); }
77         public void set_accel_ground(double along, double across, double through) { state.set_accel_ground(along, across, through); }
78         public void set_accel(double along, double across, double through) { state.set_accel(along, across, through); }
79         public void set_mag(double along, double across, double through) { state.set_mag(along, across, through); }
80         public void set_pyro_voltage(double volts) { state.set_pyro_voltage(volts); }
81         public void set_igniter_voltage(double[] voltage) { state.set_igniter_voltage(voltage); }
82         public void set_pyro_fired(int pyro_mask) { state.set_pyro_fired(pyro_mask); }
83         public void set_companion(AltosCompanion companion) { state.set_companion(companion); }
84
85         public void run () {
86                 /* Run the flight */
87                 record_set.capture_series(this);
88                 /* All done, signal that it's over */
89                 done = true;
90                 semaphore.release();
91         }
92
93         public AltosReplay(AltosRecordSet record_set) {
94                 super(record_set.cal_data());
95                 state = new AltosState(record_set.cal_data());
96                 this.record_set = record_set;
97                 try {
98                         semaphore.acquire();
99                 } catch (InterruptedException ie) {
100                 }
101         }
102 }
103
104 public class AltosReplayReader extends AltosFlightReader {
105         File            file;
106         AltosReplay     replay;
107         Thread          t;
108         int             reads;
109
110         public AltosCalData cal_data() {
111                 return replay.state.cal_data();
112         }
113
114         public AltosState read() {
115                 switch (reads) {
116                 case 0:
117                         /* Tell the display that we're in pad mode */
118                         replay.state.set_state(AltosLib.ao_flight_pad);
119                         break;
120                 case 1:
121                         t = new Thread(replay);
122                         t.start();
123                         /* fall through */
124                 default:
125                         /* Wait for something to change */
126                         try {
127                                 replay.semaphore.acquire();
128                         } catch (InterruptedException ie) {
129                         }
130                         break;
131                 }
132                 reads++;
133
134                 /* When done, let the display know */
135                 if (replay.done)
136                         return null;
137
138                 /* Fake out the received time */
139                 replay.state.set_received_time(System.currentTimeMillis());
140                 return replay.state;
141         }
142
143         public void close (boolean interrupted) {
144         }
145
146         public File backing_file() { return file; }
147
148         public AltosReplayReader(AltosRecordSet record_set, File in_file) {
149                 reads = 0;
150                 file = in_file;
151                 name = file.getName();
152                 replay = new AltosReplay(record_set);
153         }
154 }