b80d7b2ec6a26514884cff6fadfb4b4cd3353c70
[fw/altos] / altoslib / AltosState.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; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 /*
19  * Track flight state from telemetry or eeprom data stream
20  */
21
22 package org.altusmetrum.altoslib_1;
23
24 public class AltosState implements Cloneable {
25         public AltosRecord record;
26
27         public static final int set_position = 1;
28         public static final int set_gps = 2;
29         public static final int set_data = 4;
30
31         public int set;
32
33         /* derived data */
34
35         public long     received_time;
36
37         public double   time;
38         public double   prev_time;
39         public double   time_change;
40         public int      tick;
41         public int      boost_tick;
42
43         public int      state;
44         public int      flight;
45         public int      serial;
46         public boolean  landed;
47         public boolean  ascent; /* going up? */
48         public boolean  boost;  /* under power */
49         public int      rssi;
50         public int      status;
51         public int      device_type;
52         public int      config_major;
53         public int      config_minor;
54         public int      apogee_delay;
55         public int      main_deploy;
56         public int      flight_log_max;
57
58         public double   ground_altitude;
59         public double   ground_pressure;
60         public double   altitude;
61         public double   height;
62         public double   pressure;
63         public double   acceleration;
64         public double   battery_voltage;
65         public double   pyro_voltage;
66         public double   temperature;
67         public double   apogee_voltage;
68         public double   main_voltage;
69         public double   speed;
70         public double   ignitor_voltage[];
71
72         public double   prev_height;
73         public double   prev_speed;
74         public double   prev_acceleration;
75
76         public double   prev_max_height;
77         public double   prev_max_acceleration;
78         public double   prev_max_speed;
79
80         public double   max_height;
81         public double   max_acceleration;
82         public double   max_speed;
83
84         public double   kalman_height, kalman_speed, kalman_acceleration;
85
86         public AltosGPS gps;
87         public AltosGPS temp_gps;
88         public boolean  gps_pending;
89         public int gps_sequence;
90
91         public AltosIMU imu;
92         public AltosMag mag;
93
94         public static final int MIN_PAD_SAMPLES = 10;
95
96         public int      npad;
97         public int      gps_waiting;
98         public boolean  gps_ready;
99
100         public int      ngps;
101
102         public AltosGreatCircle from_pad;
103         public double   elevation;      /* from pad */
104         public double   range;          /* total distance */
105
106         public double   gps_height;
107
108         public double pad_lat, pad_lon, pad_alt;
109
110         public int      speak_tick;
111         public double   speak_altitude;
112
113         public String   callsign;
114         public String   firmware_version;
115
116         public double   accel_plus_g;
117         public double   accel_minus_g;
118         public double   accel;
119         public double   ground_accel;
120         public double   ground_accel_avg;
121
122         public int      log_format;
123
124         public AltosMs5607      baro;
125
126         public AltosRecordCompanion     companion;
127
128         public double speed() {
129                 return speed;
130         }
131
132         public double max_speed() {
133                 return max_speed;
134         }
135
136         public void set_npad(int npad) {
137                 this.npad = npad;
138                 gps_waiting = MIN_PAD_SAMPLES - npad;
139                 if (this.gps_waiting < 0)
140                         gps_waiting = 0;
141                 gps_ready = gps_waiting == 0;
142         }
143
144         public void init() {
145                 record = null;
146
147                 set = 0;
148
149                 received_time = System.currentTimeMillis();
150                 time = AltosRecord.MISSING;
151                 time_change = AltosRecord.MISSING;
152                 prev_time = AltosRecord.MISSING;
153                 tick = AltosRecord.MISSING;
154                 boost_tick = AltosRecord.MISSING;
155                 state = AltosLib.ao_flight_invalid;
156                 flight = AltosRecord.MISSING;
157                 landed = false;
158                 boost = false;
159                 rssi = AltosRecord.MISSING;
160                 status = 0;
161                 device_type = AltosRecord.MISSING;
162                 config_major = AltosRecord.MISSING;
163                 config_minor = AltosRecord.MISSING;
164                 apogee_delay = AltosRecord.MISSING;
165                 main_deploy = AltosRecord.MISSING;
166                 flight_log_max = AltosRecord.MISSING;
167
168                 ground_altitude = AltosRecord.MISSING;
169                 ground_pressure = AltosRecord.MISSING;
170                 altitude = AltosRecord.MISSING;
171                 height = AltosRecord.MISSING;
172                 pressure = AltosRecord.MISSING;
173                 acceleration = AltosRecord.MISSING;
174                 temperature = AltosRecord.MISSING;
175
176                 prev_height = AltosRecord.MISSING;
177                 prev_speed = AltosRecord.MISSING;
178                 prev_acceleration = AltosRecord.MISSING;
179
180                 prev_max_height = 0;
181                 prev_max_speed = 0;
182                 prev_max_acceleration = 0;
183
184                 battery_voltage = AltosRecord.MISSING;
185                 pyro_voltage = AltosRecord.MISSING;
186                 apogee_voltage = AltosRecord.MISSING;
187                 main_voltage = AltosRecord.MISSING;
188                 ignitor_voltage = null;
189
190                 speed = AltosRecord.MISSING;
191
192                 kalman_height = AltosRecord.MISSING;
193                 kalman_speed = AltosRecord.MISSING;
194                 kalman_acceleration = AltosRecord.MISSING;
195
196                 max_speed = 0;
197                 max_height = 0;
198                 max_acceleration = 0;
199
200                 gps = null;
201                 temp_gps = null;
202                 gps_sequence = 0;
203                 gps_pending = false;
204
205                 imu = null;
206                 mag = null;
207
208                 set_npad(0);
209                 ngps = 0;
210
211                 from_pad = null;
212                 elevation = AltosRecord.MISSING;
213                 range = AltosRecord.MISSING;
214                 gps_height = AltosRecord.MISSING;
215
216                 pad_lat = AltosRecord.MISSING;
217                 pad_lon = AltosRecord.MISSING;
218                 pad_alt = AltosRecord.MISSING;
219
220                 speak_tick = AltosRecord.MISSING;
221                 speak_altitude = AltosRecord.MISSING;
222
223                 callsign = null;
224
225                 accel_plus_g = AltosRecord.MISSING;
226                 accel_minus_g = AltosRecord.MISSING;
227                 accel = AltosRecord.MISSING;
228                 ground_accel = AltosRecord.MISSING;
229                 ground_accel_avg = AltosRecord.MISSING;
230                 log_format = AltosRecord.MISSING;
231                 serial = AltosRecord.MISSING;
232
233                 baro = null;
234                 companion = null;
235         }
236
237         void copy(AltosState old) {
238
239                 record = null;
240
241                 if (old == null) {
242                         init();
243                         return;
244                 }
245
246                 received_time = old.received_time;
247                 time = old.time;
248                 time_change = 0;
249                 tick = old.tick;
250                 boost_tick = old.boost_tick;
251
252                 state = old.state;
253                 flight = old.flight;
254                 landed = old.landed;
255                 ascent = old.ascent;
256                 boost = old.boost;
257                 rssi = old.rssi;
258                 status = old.status;
259                 device_type = old.device_type;
260                 config_major = old.config_major;
261                 config_minor = old.config_minor;
262                 apogee_delay = old.apogee_delay;
263                 main_deploy = old.main_deploy;
264                 flight_log_max = old.flight_log_max;
265                 
266                 set = 0;
267
268                 ground_altitude = old.ground_altitude;
269                 altitude = old.altitude;
270                 height = old.height;
271                 pressure = old.pressure;
272                 acceleration = old.acceleration;
273                 battery_voltage = old.battery_voltage;
274                 pyro_voltage = old.pyro_voltage;
275                 temperature = old.temperature;
276                 apogee_voltage = old.apogee_voltage;
277                 main_voltage = old.main_voltage;
278                 ignitor_voltage = old.ignitor_voltage;
279                 speed = old.speed;
280
281                 prev_height = old.height;
282                 prev_speed = old.speed;
283                 prev_acceleration = old.acceleration;
284
285                 prev_max_height = old.max_height;
286                 prev_max_speed = old.max_speed;
287                 prev_max_acceleration = old.max_acceleration;
288                 prev_time = old.time;
289
290                 max_height = old.max_height;
291                 max_acceleration = old.max_acceleration;
292                 max_speed = old.max_speed;
293
294                 kalman_height = old.kalman_height;
295                 kalman_speed = old.kalman_speed;
296                 kalman_acceleration = old.kalman_acceleration;
297
298                 if (old.gps != null)
299                         gps = old.gps.clone();
300                 else
301                         gps = null;
302                 if (old.temp_gps != null)
303                         temp_gps = old.temp_gps.clone();
304                 else
305                         temp_gps = null;
306                 gps_sequence = old.gps_sequence;
307                 gps_pending = old.gps_pending;
308
309                 if (old.imu != null)
310                         imu = old.imu.clone();
311                 else
312                         imu = null;
313
314                 if (old.mag != null)
315                         mag = old.mag.clone();
316                 else
317                         mag = null;
318
319                 npad = old.npad;
320                 gps_waiting = old.gps_waiting;
321                 gps_ready = old.gps_ready;
322                 ngps = old.ngps;
323
324                 if (old.from_pad != null)
325                         from_pad = old.from_pad.clone();
326                 else
327                         from_pad = null;
328
329                 elevation = old.elevation;
330                 range = old.range;
331
332                 gps_height = old.gps_height;
333                 pad_lat = old.pad_lat;
334                 pad_lon = old.pad_lon;
335                 pad_alt = old.pad_alt;
336
337                 speak_tick = old.speak_tick;
338                 speak_altitude = old.speak_altitude;
339
340                 callsign = old.callsign;
341
342                 accel_plus_g = old.accel_plus_g;
343                 accel_minus_g = old.accel_minus_g;
344                 accel = old.accel;
345                 ground_accel = old.ground_accel;
346                 ground_accel_avg = old.ground_accel_avg;
347
348                 log_format = old.log_format;
349                 serial = old.serial;
350
351                 baro = old.baro;
352                 companion = old.companion;
353         }
354
355         double altitude() {
356                 if (altitude != AltosRecord.MISSING)
357                         return altitude;
358                 if (gps != null)
359                         return gps.alt;
360                 return AltosRecord.MISSING;
361         }
362
363         void update_vertical_pos() {
364
365                 double  alt = altitude();
366
367                 if (state == AltosLib.ao_flight_pad && alt != AltosRecord.MISSING && ground_pressure == AltosRecord.MISSING) {
368                         if (ground_altitude == AltosRecord.MISSING)
369                                 ground_altitude = alt;
370                         else
371                                 ground_altitude = (ground_altitude * 7 + alt) / 8;
372                 }
373
374                 if (kalman_height != AltosRecord.MISSING)
375                         height = kalman_height;
376                 else if (altitude != AltosRecord.MISSING && ground_altitude != AltosRecord.MISSING)
377                         height = altitude - ground_altitude;
378                 else
379                         height = AltosRecord.MISSING;
380
381                 if (height != AltosRecord.MISSING && height > prev_max_height)
382                         max_height = height;
383
384                 update_speed();
385         }
386
387         double motion_filter_value() {
388                 return 1/ Math.exp(time_change/2.0);
389         }
390
391         void update_speed() {
392                 if (kalman_speed != AltosRecord.MISSING)
393                         speed = kalman_speed;
394                 else if (state != AltosLib.ao_flight_invalid &&
395                          time_change != AltosRecord.MISSING)
396                 {
397                         if (ascent && acceleration != AltosRecord.MISSING)
398                         {
399                                 if (prev_speed == AltosRecord.MISSING)
400                                         speed = acceleration * time_change;
401                                 else
402                                         speed = prev_speed + acceleration * time_change;
403                         }
404                         else if (height != AltosRecord.MISSING &&
405                                  prev_height != AltosRecord.MISSING &&
406                                  time_change != 0)
407                         {
408                                 double  new_speed = (height - prev_height) / time_change;
409
410                                 if (prev_speed == AltosRecord.MISSING)
411                                         speed = new_speed;
412                                 else {
413                                         double  filter = motion_filter_value();
414
415                                         speed = prev_speed * filter + new_speed * (1-filter);
416                                 }
417                         }
418                 }
419                 if (acceleration == AltosRecord.MISSING) {
420                         if (prev_speed != AltosRecord.MISSING && time_change != 0) {
421                                 double  new_acceleration = (speed - prev_speed) / time_change;
422
423                                 if (prev_acceleration == AltosRecord.MISSING)
424                                         acceleration = new_acceleration;
425                                 else {
426                                         double filter = motion_filter_value();
427
428                                         acceleration = prev_acceleration * filter + new_acceleration * (1-filter);
429                                 }
430                         }
431                 }
432                 if (boost && speed != AltosRecord.MISSING && speed > prev_max_speed)
433                         max_speed = speed;
434         }
435         
436         void update_accel() {
437                 if (kalman_acceleration != AltosRecord.MISSING) {
438                         acceleration = kalman_acceleration;
439                 } else {
440                         double  ground = ground_accel;
441
442                         if (ground == AltosRecord.MISSING)
443                                 ground = ground_accel_avg;
444                         if (accel == AltosRecord.MISSING)
445                                 return;
446                         if (ground == AltosRecord.MISSING)
447                                 return;
448                         if (accel_plus_g == AltosRecord.MISSING)
449                                 return;
450                         if (accel_minus_g == AltosRecord.MISSING)
451                                 return;
452
453                         double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0;
454                         double counts_per_mss = counts_per_g / 9.80665;
455                         acceleration = (ground - accel) / counts_per_mss;
456                 }
457
458                 /* Only look at accelerometer data under boost */
459                 if (boost && acceleration != AltosRecord.MISSING && acceleration > prev_max_acceleration)
460                         max_acceleration = acceleration;
461                 update_speed();
462         }
463
464         void update_time() {
465                 if (tick != AltosRecord.MISSING) {
466                         time = tick / 100.0;
467                         if (prev_time != AltosRecord.MISSING)
468                                 time_change = time - prev_time;
469                 }
470         }
471
472         void update_gps() {
473                 elevation = 0;
474                 range = -1;
475                 gps_height = 0;
476
477                 if (gps == null)
478                         return;
479
480                 if (gps.locked && gps.nsat >= 4) {
481                         /* Track consecutive 'good' gps reports, waiting for 10 of them */
482                         if (state == AltosLib.ao_flight_pad) {
483                                 set_npad(npad+1);
484                                 if (pad_lat != AltosRecord.MISSING) {
485                                         pad_lat = (pad_lat * 31 + gps.lat) / 32;
486                                         pad_lon = (pad_lon * 31 + gps.lon) / 32;
487                                         pad_alt = (pad_alt * 31 + gps.alt) / 32;
488                                 }
489                         }
490                         if (pad_lat == AltosRecord.MISSING) {
491                                 pad_lat = gps.lat;
492                                 pad_lon = gps.lon;
493                                 pad_alt = gps.alt;
494                         }
495                 }
496                 if (gps.lat != 0 && gps.lon != 0 &&
497                     pad_lat != AltosRecord.MISSING &&
498                     pad_lon != AltosRecord.MISSING)
499                 {
500                         double h = height;
501
502                         if (h == AltosRecord.MISSING)
503                                 h = 0;
504                         from_pad = new AltosGreatCircle(pad_lat, pad_lon, 0, gps.lat, gps.lon, h);
505                         elevation = from_pad.elevation;
506                         range = from_pad.range;
507                         gps_height = gps.alt - pad_alt;
508                 }
509         }
510
511         public void set_tick(int tick) {
512                 if (tick != AltosRecord.MISSING) {
513                         if (this.tick != AltosRecord.MISSING) {
514                                 while (tick < this.tick)
515                                         tick += 65536;
516                                 time_change = (tick - this.tick) / 100.0;
517                         } else
518                                 time_change = 0;
519                         this.tick = tick;
520                         update_time();
521                 }
522         }
523
524         public void set_boost_tick(int boost_tick) {
525                 if (boost_tick != AltosRecord.MISSING)
526                         this.boost_tick = boost_tick;
527         }
528
529         public String state_name() {
530                 return AltosLib.state_name(state);
531         }
532
533         public void set_state(int state) {
534                 if (state != AltosLib.ao_flight_invalid) {
535                         this.state = state;
536                         ascent = (AltosLib.ao_flight_boost <= state &&
537                                   state <= AltosLib.ao_flight_coast);
538                         boost = (AltosLib.ao_flight_boost == state);
539                 }
540
541         }
542
543         public void set_device_type(int device_type) {
544                 this.device_type = device_type;
545         }
546
547         public void set_config(int major, int minor, int apogee_delay, int main_deploy, int flight_log_max) {
548                 config_major = major;
549                 config_minor = minor;
550                 this.apogee_delay = apogee_delay;
551                 this.main_deploy = main_deploy;
552                 this.flight_log_max = flight_log_max;
553         }
554
555         public void set_callsign(String callsign) {
556                 this.callsign = callsign;
557         }
558
559         public void set_firmware_version(String version) {
560                 firmware_version = version;
561         }
562
563         public void set_flight(int flight) {
564
565                 /* When the flight changes, reset the state */
566                 if (flight != AltosRecord.MISSING) {
567                         if (this.flight != AltosRecord.MISSING &&
568                             this.flight != flight) {
569                                 init();
570                         }
571                         this.flight = flight;
572                 }
573         }
574
575         public void set_serial(int serial) {
576                 /* When the serial changes, reset the state */
577                 if (serial != AltosRecord.MISSING) {
578                         if (this.serial != AltosRecord.MISSING &&
579                             this.serial != serial) {
580                                 init();
581                         }
582                         this.serial = serial;
583                 }
584         }
585
586         public int rssi() {
587                 if (rssi == AltosRecord.MISSING)
588                         return 0;
589                 return rssi;
590         }
591
592         public void set_rssi(int rssi, int status) {
593                 if (rssi != AltosRecord.MISSING) {
594                         this.rssi = rssi;
595                         this.status = status;
596                 }
597         }
598
599         public void set_received_time(long ms) {
600                 received_time = ms;
601         }
602
603         public void set_altitude(double altitude) {
604                 if (altitude != AltosRecord.MISSING) {
605                         this.altitude = altitude;
606                         update_vertical_pos();
607                         set |= set_position;
608                 }
609         }
610
611         public void set_ground_altitude(double ground_altitude) {
612                 if (ground_altitude != AltosRecord.MISSING) {
613                         this.ground_altitude = ground_altitude;
614                         update_vertical_pos();
615                 }
616         }
617
618         public void set_ground_pressure (double pressure) {
619                 if (pressure != AltosRecord.MISSING) {
620                         this.ground_pressure = pressure;
621                         set_ground_altitude(AltosConvert.pressure_to_altitude(pressure));
622                         update_vertical_pos();
623                 }
624         }
625
626         public void set_gps(AltosGPS gps, int sequence) {
627                 if (gps != null) {
628                         this.gps = gps.clone();
629                         gps_sequence = sequence;
630                         update_gps();
631                         update_vertical_pos();
632                         set |= set_gps;
633                 }
634         }
635
636         public void set_kalman(double height, double speed, double acceleration) {
637                 if (height != AltosRecord.MISSING) {
638                         kalman_height = height;
639                         kalman_speed = speed;
640                         kalman_acceleration = acceleration;
641                         update_vertical_pos();
642                         update_speed();
643                         update_accel();
644                 }
645         }
646
647         public void set_pressure(double pressure) {
648                 if (pressure != AltosRecord.MISSING) {
649                         this.pressure = pressure;
650                         set_altitude(AltosConvert.pressure_to_altitude(pressure));
651                 }
652         }
653
654         public void make_baro() {
655                 if (baro == null)
656                         baro = new AltosMs5607();
657         }
658
659         public void set_ms5607(int pres, int temp) {
660                 if (baro != null) {
661                         baro.set(pres, temp);
662
663                         set_pressure(baro.pa);
664                         set_temperature(baro.cc / 100.0);
665                 }
666         }
667
668         public void make_companion (int nchannels) {
669                 if (companion == null)
670                         companion = new AltosRecordCompanion(nchannels);
671         }
672
673         public void set_companion(AltosRecordCompanion companion) {
674                 this.companion = companion;
675         }
676
677         public void set_accel_g(double accel_plus_g, double accel_minus_g) {
678                 if (accel_plus_g != AltosRecord.MISSING) {
679                         this.accel_plus_g = accel_plus_g;
680                         this.accel_minus_g = accel_minus_g;
681                         update_accel();
682                 }
683         }
684         public void set_ground_accel(double ground_accel) {
685                 if (ground_accel != AltosRecord.MISSING) {
686                         this.ground_accel = ground_accel;
687                         update_accel();
688                 }
689         }
690
691         public void set_accel(double accel) {
692                 if (accel != AltosRecord.MISSING) {
693                         this.accel = accel;
694                         if (state == AltosLib.ao_flight_pad) {
695                                 if (ground_accel_avg == AltosRecord.MISSING)
696                                         ground_accel_avg = accel;
697                                 else
698                                         ground_accel_avg = (ground_accel_avg * 7 + accel) / 8;
699                         }
700                 }
701                 update_accel();
702         }
703
704         public void set_temperature(double temperature) {
705                 if (temperature != AltosRecord.MISSING) {
706                         this.temperature = temperature;
707                         set |= set_data;
708                 }
709         }
710
711         public void set_battery_voltage(double battery_voltage) {
712                 if (battery_voltage != AltosRecord.MISSING) {
713                         this.battery_voltage = battery_voltage;
714                         set |= set_data;
715                 }
716         }
717
718         public void set_pyro_voltage(double pyro_voltage) {
719                 if (pyro_voltage != AltosRecord.MISSING) {
720                         this.pyro_voltage = pyro_voltage;
721                         set |= set_data;
722                 }
723         }
724
725         public void set_apogee_voltage(double apogee_voltage) {
726                 if (apogee_voltage != AltosRecord.MISSING) {
727                         this.apogee_voltage = apogee_voltage;
728                         set |= set_data;
729                 }
730         }
731
732         public void set_main_voltage(double main_voltage) {
733                 if (main_voltage != AltosRecord.MISSING) {
734                         this.main_voltage = main_voltage;
735                         set |= set_data;
736                 }
737         }
738
739         public void set_ignitor_voltage(double[] voltage) {
740                 this.ignitor_voltage = voltage;
741         }
742
743         public double time_since_boost() {
744                 if (tick == AltosRecord.MISSING)
745                         return 0.0;
746
747                 if (boost_tick != AltosRecord.MISSING) {
748                         return (tick - boost_tick) / 100.0;
749                 }
750                 return tick / 100.0;
751         }
752
753         public boolean valid() {
754                 return tick != AltosRecord.MISSING && serial != AltosRecord.MISSING;
755         }
756
757         public AltosGPS make_temp_gps() {
758                 if (temp_gps == null) {
759                         temp_gps = new AltosGPS(gps);
760                         temp_gps.cc_gps_sat = null;
761                 }
762                 gps_pending = true;
763                 return temp_gps;
764         }
765
766         public void set_temp_gps() {
767                 set_gps(temp_gps, gps_sequence + 1);
768                 gps_pending = false;
769                 temp_gps = null;
770         }
771
772         public AltosState clone() {
773                 AltosState s = new AltosState();
774                 s.copy(this);
775                 return s;
776         }
777
778
779         public void init (AltosRecord cur, AltosState prev_state) {
780
781                 System.out.printf ("init\n");
782                 if (cur == null)
783                         cur = new AltosRecord();
784
785                 record = cur;
786
787                 /* Discard previous state if it was for a different board */
788                 if (prev_state != null && prev_state.serial != cur.serial)
789                         prev_state = null;
790
791                 copy(prev_state);
792
793                 set_ground_altitude(cur.ground_altitude());
794                 set_altitude(cur.altitude());
795
796                 set_kalman(cur.kalman_height, cur.kalman_speed, cur.kalman_acceleration);
797
798                 received_time = System.currentTimeMillis();
799
800                 set_temperature(cur.temperature());
801                 set_apogee_voltage(cur.drogue_voltage());
802                 set_main_voltage(cur.main_voltage());
803                 set_battery_voltage(cur.battery_voltage());
804
805                 set_pressure(cur.pressure());
806
807                 set_tick(cur.tick);
808                 set_state(cur.state);
809
810                 set_accel_g (cur.accel_minus_g, cur.accel_plus_g);
811                 set_ground_accel(cur.ground_accel);
812                 set_accel (cur.accel);
813
814                 if (cur.gps_sequence != gps_sequence)
815                         set_gps(cur.gps, cur.gps_sequence);
816
817         }
818
819         public AltosState(AltosRecord cur) {
820                 init(cur, null);
821         }
822
823         public AltosState (AltosRecord cur, AltosState prev) {
824                 init(cur, prev);
825         }
826
827
828         public AltosState () {
829                 init();
830         }
831 }