"invalid"
};
+static const char *kml_state_colours[] = {
+ "FF000000",
+ "FF000000",
+ "FF000000",
+ "FF0000FF",
+ "FF4080FF",
+ "FF00FFFF",
+ "FFFF0000",
+ "FF00FF00",
+ "FF000000",
+ "FFFFFFFF"
+};
+
static int plot_colors[3][3] = {
{ 0, 0x90, 0 }, /* height */
{ 0xa0, 0, 0 }, /* speed */
return pd;
}
-static const char kml_header[] =
+static const char kml_header_start[] =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<kml xmlns=\"http://earth.google.com/kml/2.0\">\n"
+ "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
+ "<Document>\n"
+ " <name>%s</name>\n"
+ " <description>\n";
+static const char kml_header_end[] =
+ " </description>\n"
+ " <open>0</open>\n";
+
+static const char kml_style_start[] =
+ " <Style id=\"ao-flightstate-%s\">\n"
+ " <LineStyle><color>%s</color><width>4</width></LineStyle>\n"
+ " <BalloonStyle>\n"
+ " <text>\n";
+static const char kml_style_end[] =
+ " </text>\n"
+ " </BalloonStyle>\n"
+ " </Style>\n";
+
+static const char kml_placemark_start[] =
" <Placemark>\n"
- " <name>gps</name>\n"
- " <Style id=\"khStyle690\">\n"
- " <LineStyle id=\"khLineStyle694\">\n"
- " <color>ff00ffff</color>\n"
- " <width>4</width>\n"
- " </LineStyle>\n"
- " </Style>\n"
- " <MultiGeometry id=\"khMultiGeometry697\">\n"
- " <LineString id=\"khLineString698\">\n"
- " <tessellate>1</tessellate>\n"
- " <altitudeMode>absolute</altitudeMode>\n"
- " <coordinates>\n";
+ " <name>%s</name>\n"
+ " <styleUrl>#ao-flightstate-%s</styleUrl>\n"
+ " <LineString>\n"
+ " <tessellate>1</tessellate>\n"
+ " <altitudeMode>absolute</altitudeMode>\n"
+ " <coordinates>\n";
+
+static const char kml_coord_fmt[] =
+ " %12.7f, %12.7f, %12.7f <!-- alt %12.7f time %12.7f sats %d -->\n";
+
+static const char kml_placemark_end[] =
+ " </coordinates>\n"
+ " </LineString>\n"
+ " </Placemark>\n";
static const char kml_footer[] =
- "</coordinates>\n"
+ " </coordinates>\n"
" </LineString>\n"
- " </MultiGeometry>\n"
- "</Placemark>\n"
+ " </Placemark>\n"
+ "</Document>\n"
"</kml>\n";
static unsigned
double state_start, state_stop;
struct cc_flightcooked *cooked;
double apogee;
+ char buf[128];
+
+ if (kml_file) {
+ snprintf(buf, sizeof (buf), "AO Flight#%d S/N: %03d", f->flight, f->serial);
+ fprintf(kml_file, kml_header_start, buf);
+ }
fprintf(summary_file,
"Serial: %9d\n"
"Flight: %9d\n",
f->serial, f->flight);
+
if (f->year) {
- fprintf(summary_file,
+ snprintf(buf, sizeof (buf),
"Date: %04d-%02d-%02d\n",
f->year, f->month, f->day);
+ fprintf(summary_file, "%s", buf);
+ if (kml_file) fprintf(kml_file, "%s", buf);
}
if (f->gps.num) {
- fprintf(summary_file,
+ snprintf(buf, sizeof (buf),
"Time: %2d:%02d:%02d\n",
f->gps.data[0].hour,
f->gps.data[0].minute,
f->gps.data[0].second);
+ fprintf(summary_file, "%s", buf);
+ if (kml_file) fprintf(kml_file, "%s", buf);
}
boost_start = f->accel.data[0].time;
boost_stop = f->accel.data[f->accel.num-1].time;
min_pres = f->pres.data[pres_i].value;
height = cc_barometer_to_altitude(min_pres) -
cc_barometer_to_altitude(f->ground_pres);
- fprintf(summary_file, "Max height: %9.2fm %9.2fft %9.2fs\n",
+ apogee = f->pres.data[pres_i].time;
+ snprintf(buf, sizeof (buf), "Max height: %9.2fm %9.2fft %9.2fs\n",
height, height * 100 / 2.54 / 12,
(f->pres.data[pres_i].time - boost_start) / 100.0);
- apogee = f->pres.data[pres_i].time;
+ fprintf(summary_file, "%s", buf);
+ if (kml_file) fprintf(kml_file, "%s", buf);
}
cooked = cc_flight_cook(f);
speed_i = cc_perioddata_max(&cooked->accel_speed, boost_start, boost_stop);
if (speed_i >= 0) {
speed = cooked->accel_speed.data[speed_i];
- fprintf(summary_file, "Max speed: %9.2fm/s %9.2fft/s %9.2fs\n",
+ snprintf(buf, sizeof (buf), "Max speed: %9.2fm/s %9.2fft/s %9.2fs\n",
speed, speed * 100 / 2.4 / 12.0,
(cooked->accel_speed.start + speed_i * cooked->accel_speed.step - boost_start) / 100.0);
+ fprintf(summary_file, "%s", buf);
+ if (kml_file) fprintf(kml_file, "%s", buf);
}
}
accel_i = cc_timedata_min(&f->accel, boost_start, boost_stop);
{
accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value,
f->ground_accel);
- fprintf(summary_file, "Max accel: %9.2fm/s² %9.2fg %9.2fs\n",
+ snprintf(buf, sizeof (buf), "Max accel: %9.2fm/s² %9.2fg %9.2fs\n",
accel, accel / 9.80665,
(f->accel.data[accel_i].time - boost_start) / 100.0);
+ fprintf(summary_file, "%s", buf);
+ if (kml_file) fprintf(kml_file, "%s", buf);
}
+ if (kml_file)
+ fprintf(kml_file, "%s", kml_header_end);
+
for (i = 0; i < f->state.num; i++) {
state = f->state.data[i].value;
state_start = f->state.data[i].time;
fprintf(summary_file, "State: %s\n", state_names[state]);
fprintf(summary_file, "\tStart: %9.2fs\n", (state_start - boost_start) / 100.0);
fprintf(summary_file, "\tDuration: %9.2fs\n", (state_stop - state_start) / 100.0);
+ if (kml_file) {
+ fprintf(kml_file, kml_style_start, state_names[state], kml_state_colours[state]);
+ fprintf(kml_file, "\tState: %s\n", state_names[state]);
+ fprintf(kml_file, "\tStart: %9.2fs\n", (state_start - boost_start) / 100.0);
+ fprintf(kml_file, "\tDuration: %9.2fs\n", (state_stop - state_start) / 100.0);
+ }
+
accel_i = cc_timedata_min(&f->accel, state_start, state_stop);
if (accel_i >= 0)
{
accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value,
f->ground_accel);
- fprintf(summary_file, "\tMax accel: %9.2fm/s² %9.2fg %9.2fs\n",
+ snprintf(buf, sizeof (buf), "\tMax accel: %9.2fm/s² %9.2fg %9.2fs\n",
accel, accel / 9.80665,
(f->accel.data[accel_i].time - boost_start) / 100.0);
+ fprintf(summary_file, "%s", buf);
+ if (kml_file) fprintf(kml_file, "%s", buf);
}
if (cooked) {
}
if (speed_i >= 0)
{
- fprintf(summary_file, "\tMax speed: %9.2fm/s %9.2fft/s %9.2fs\n",
+ snprintf(buf, sizeof (buf), "\tMax speed: %9.2fm/s %9.2fft/s %9.2fs\n",
speed, speed * 100 / 2.4 / 12.0,
(cooked->accel_speed.start + speed_i * cooked->accel_speed.step - boost_start) / 100.0);
- fprintf(summary_file, "\tAvg speed: %9.2fm/s %9.2fft/s\n",
+ fprintf(summary_file, "%s", buf);
+ if (kml_file) fprintf(kml_file, "%s", buf);
+
+ snprintf(buf, sizeof (buf), "\tAvg speed: %9.2fm/s %9.2fft/s\n",
avg_speed, avg_speed * 100 / 2.4 / 12.0);
+ fprintf(summary_file, "%s", buf);
+ if (kml_file) fprintf(kml_file, "%s", buf);
}
}
pres_i = cc_timedata_min(&f->pres, state_start, state_stop);
min_pres = f->pres.data[pres_i].value;
height = cc_barometer_to_altitude(min_pres) -
cc_barometer_to_altitude(f->ground_pres);
- fprintf(summary_file, "\tMax height: %9.2fm %9.2fft %9.2fs\n",
+ snprintf(buf, sizeof (buf), "\tMax height: %9.2fm %9.2fft %9.2fs\n",
height, height * 100 / 2.54 / 12,
(f->pres.data[pres_i].time - boost_start) / 100.0);
+ fprintf(summary_file, "%s", buf);
+ if (kml_file) fprintf(kml_file, "%s", buf);
}
+ if (kml_file) fprintf(kml_file, "%s", kml_style_end);
}
if (cooked && detail_file) {
double max_height = 0;
daytime = compute_daytime_ms(time, &f->gps);
else
daytime = 0;
- fprintf(raw_file, "%9.2f %9.2f %9.2f %9.2f %02d:%02d:%02d.%03d\n",
+ fprintf(raw_file, "%9.2f %9.2f %9.2f %02d:%02d:%02d.%03d\n",
time, pres, accel,
daytime_hour(daytime),
daytime_minute(daytime),
int j = 0, baro_pos;
double baro_offset;
double baro = 0.0;
+ int state_idx = 0;
if (gps_file)
fprintf(gps_file, "%2s %2s %2s %9s %12s %12s %9s %8s %5s\n",
"hr", "mn", "sc",
"time", "lat", "lon", "alt", "baro", "nsat");
if (kml_file)
- fprintf(kml_file, "%s", kml_header);
+ fprintf(kml_file, kml_placemark_start,
+ state_names[(int)f->state.data[state_idx].value],
+ state_names[(int)f->state.data[state_idx].value]);
+
if (f->gps.num)
baro_offset = f->gps.data[0].alt;
else
f->gps.data[i].lon,
f->gps.data[i].alt,
baro + baro_offset);
- if (kml_file) {
- fprintf(kml_file, "%12.7f, %12.7f, %12.7f <!-- alt %12.7f time %12.7f sats %d -->",
- f->gps.data[i].lon,
- f->gps.data[i].lat,
- baro + baro_offset,
- f->gps.data[i].alt,
- (f->gps.data[i].time - boost_start) / 100.0,
- nsat);
- if (i < f->gps.num - 1)
- fprintf(kml_file, ",\n");
- else
- fprintf(kml_file, "\n");
- }
nsat = 0;
if (f->gps.sats) {
fprintf(gps_file, "\n");
}
}
+
+ if (kml_file) {
+ snprintf(buf, sizeof (buf), kml_coord_fmt,
+ f->gps.data[i].lon,
+ f->gps.data[i].lat,
+ baro + baro_offset,
+ f->gps.data[i].alt,
+ (f->gps.data[i].time - boost_start) / 100.0,
+ nsat);
+ fprintf(kml_file, "%s", buf);
+ if (state_idx + 1 < f->state.num && f->state.data[state_idx + 1].time <= f->gps.data[i].time) {
+ state_idx++;
+ if (f->state.data[state_idx - 1].value != f->state.data[state_idx].value) {
+ fprintf(kml_file, "%s", kml_placemark_end);
+ fprintf(kml_file, kml_placemark_start,
+ state_names[(int)f->state.data[state_idx].value],
+ state_names[(int)f->state.data[state_idx].value]);
+ fprintf(kml_file, "%s", buf);
+ }
+ }
+ }
+
}
if (kml_file)
fprintf(kml_file, "%s", kml_footer);
if (has_gps && !gps_file)
gps_file = open_output(gps_name, argv[i], ".gps");
if (has_kml && !kml_file)
- kml_file = open_output(gps_name, argv[i], ".kml");
+ kml_file = open_output(kml_name, argv[i], ".kml");
s = strstr(argv[i], "-serial-");
if (s)
serial = atoi(s + 8);