From: Keith Packard Date: Mon, 14 Jul 2014 08:08:09 +0000 (-0700) Subject: ao-tools: Add ao-fakeflight X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=248aaf5e76292c8e6bfa3600d2cf9b194bf66c86 ao-tools: Add ao-fakeflight This generates a TeleMetrumV2 eeprom file with a fake flight for use in testing. Signed-off-by: Keith Packard --- diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index fb554857..dfb19e10 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -2,7 +2,7 @@ SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list \ ao-load ao-telem ao-send-telem ao-sky-flash \ ao-dumpflash ao-edit-telem ao-dump-up ao-elftohex \ ao-flash ao-usbload ao-test-igniter ao-test-baro \ - ao-test-flash ao-cal-accel ao-test-gps ao-usbtrng \ + ao-test-flash ao-cal-accel ao-fakeflight ao-test-gps ao-usbtrng \ ao-cal-freq ao-chaosread ao-makebin if LIBSTLINK SUBDIRS += ao-stmload diff --git a/ao-tools/ao-fakeflight/Makefile.am b/ao-tools/ao-fakeflight/Makefile.am new file mode 100644 index 00000000..cf88795d --- /dev/null +++ b/ao-tools/ao-fakeflight/Makefile.am @@ -0,0 +1,25 @@ +bin_PROGRAMS=ao-fakeflight + +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) -I$(top_srcdir)/src/drivers -O0 -g +AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a + +ao_fakeflight_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS) + +ao_fakeflight_LDADD=$(AO_POSTFLIGHT_LIBS) + +LIBS=-lm + +ao_fakeflight_SOURCES = \ + ao-fakeflight.c \ + ao-fakeflight.h \ + ao-fake-convert.c \ + ao-fake-log.c \ + ao-physics.c \ + ao-rocket.c + +clean-local: + $(RM) $(BUILT_SOURCES) + +ALTOS=$(top_srcdir)/src +DRIVERS=$(ALTOS)/drivers +KERNEL=$(ALTOS)/kernel diff --git a/ao-tools/ao-fakeflight/ao-fake-convert.c b/ao-tools/ao-fakeflight/ao-fake-convert.c new file mode 100644 index 00000000..035d1471 --- /dev/null +++ b/ao-tools/ao-fakeflight/ao-fake-convert.c @@ -0,0 +1,169 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "cc.h" +#include +#include +#include + +/* From mega serial 1246 */ + +struct ao_ms5607_prom ao_ms5607_prom = { + .reserved = 156, + .sens = 44229, + .off = 38634, + .tcs = 27789, + .tco = 25015, + .tref = 32003, + .tempsens = 27647, + .crc = 50256, +}; + +struct ao_config { + int16_t accel_plus_g; + int16_t accel_minus_g; +}; + +struct ao_config ao_config = { + .accel_plus_g = 2028, + .accel_minus_g = 2065 +}; + +#define MIN_VALUE 0 +#define MAX_VALUE 16777216 +#define MID_VALUE ((MAX_VALUE - MIN_VALUE) / 2) + +static void +ao_ms5607_search (struct ao_ms5607_value *goal_value, + struct ao_ms5607_sample *goal_sample, + int search_temp) +{ + struct ao_ms5607_sample sample; + struct ao_ms5607_value value; + uint32_t hi, lo, mid; + int32_t goal; + int32_t result; + + if (search_temp) { + sample.pres = MID_VALUE; + goal = goal_value->temp; + } else { + sample.temp = goal_sample->temp; + goal = goal_value->pres; + } + + lo = MIN_VALUE; + hi = MAX_VALUE; + for (;;) { + mid = (hi + lo) >> 1; + + if (mid == lo) + break; + + if (search_temp) + sample.temp = mid; + else + sample.pres = mid; + + ao_ms5607_convert(&sample, &value); + + if (search_temp) + result = value.temp; + else + result = value.pres; + + if (result == goal) + break; + + if (result < goal) + lo = mid; + else + hi = mid; + } + *goal_sample = sample; +} + +void +ao_ms5607_unconvert(double altitude, + struct ao_ms5607_sample *ret) +{ + double pressure = cc_altitude_to_pressure(altitude); + double temperature = cc_altitude_to_temperature(altitude); + + struct ao_ms5607_value value; + + value.pres = floor (pressure + 0.5); + value.temp = floor (temperature * 100 + 0.5); + + /* First back-convert temperature; that's independent of pressure */ + + ao_ms5607_search(&value, ret, 1); + + /* Now search for pressure */ + + ao_ms5607_search(&value, ret, 0); +} + +int16_t +ao_accel_unconvert(double accel) +{ + int16_t ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + double ao_accel_0g = (ao_config.accel_minus_g + ao_config.accel_plus_g) / 2.0; + double ao_accel_scale = GRAVITY * 2.0 / ao_accel_2g; + + int16_t ao_sample_accel = ao_accel_0g - accel/ao_accel_scale; + + return ao_sample_accel; +} + +static void +ao_ms5607_show(FILE *f, struct rocket *r) +{ + fprintf(f, "ms5607 reserved: %u\n", ao_ms5607_prom.reserved); + fprintf(f, "ms5607 sens: %u\n", ao_ms5607_prom.sens); + fprintf(f, "ms5607 off: %u\n", ao_ms5607_prom.off); + fprintf(f, "ms5607 tcs: %u\n", ao_ms5607_prom.tcs); + fprintf(f, "ms5607 tco: %u\n", ao_ms5607_prom.tco); + fprintf(f, "ms5607 tref: %u\n", ao_ms5607_prom.tref); + fprintf(f, "ms5607 tempsens: %u\n", ao_ms5607_prom.tempsens); + fprintf(f, "ms5607 crc: %u\n", ao_ms5607_prom.crc); +} + +static void +ao_config_show(FILE *f, struct rocket *r) +{ + fprintf(f, "Config version: 1.18\n"); + fprintf(f, "Accel cal +1g: %d -1g: %d\n", + ao_config.accel_plus_g, ao_config.accel_minus_g); + fprintf(f, "Main deploy: %d meters\n", (int) r->main_deploy); +} + +#include "config.h" + +void +ao_show_header(FILE *f, struct rocket *r) +{ + ao_config_show(f, r); + ao_ms5607_show(f, r); + fprintf(f, "serial-number 1\n"); + fprintf(f, "current-flight 1\n"); + fprintf(f, "log-format %u\n", AO_LOG_FORMAT_TELEMETRUM); + fprintf(f, "altitude-32 1\n"); + fprintf(f, "software-version %s\n", PACKAGE_VERSION); +} + +#include "ao_ms5607_convert.c" diff --git a/ao-tools/ao-fakeflight/ao-fake-log.c b/ao-tools/ao-fakeflight/ao-fake-log.c new file mode 100644 index 00000000..4a14bec2 --- /dev/null +++ b/ao-tools/ao-fakeflight/ao-fake-log.c @@ -0,0 +1,168 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao-fakeflight.h" + +static uint8_t +ao_log_csum(uint8_t *b) +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_metrum); i++) + sum += *b++; + return -sum; +} + +void +ao_log_metrum(FILE *file, struct ao_log_metrum *log) +{ + uint8_t *d; + + /* set checksum */ + log->csum = 0; + log->csum = ao_log_csum((uint8_t *) log); + int i; + + fprintf (file, "%c %04x", log->type, log->tick); + d = (void *) &log->u; + for (i = 0; i < sizeof (log->u); i++) + fprintf(file, " %02x", d[i]); + fprintf (file, "\n"); +} + +void +ao_log_flight(FILE *file, struct flight *f, struct rocket *r) +{ + static struct ao_log_metrum log; + + log.type = AO_LOG_FLIGHT; + log.tick = (f->time * 100); + log.u.flight.ground_accel = ao_accel_unconvert(GRAVITY); + log.u.flight.ground_pres = cc_altitude_to_pressure(f->altitude); + log.u.flight.flight = 1; + ao_log_metrum(file, &log); +} + +void +ao_log_sensor(FILE *file, struct flight *f, struct rocket *r) +{ + static struct ao_log_metrum log; + struct ao_ms5607_sample sample_baro; + int16_t sample_accel; + + ao_ms5607_unconvert(f->altitude, &sample_baro); + sample_accel = ao_accel_unconvert(f->accel); + + log.type = AO_LOG_SENSOR; + log.tick = (f->time * 100); + log.u.sensor.pres = sample_baro.pres; + log.u.sensor.temp = sample_baro.temp; + log.u.sensor.accel = sample_accel; + ao_log_metrum(file, &log); +} + +void +ao_log_gps(FILE *file, struct flight *f, struct rocket *r) +{ + static struct ao_log_metrum log; + static double gps_time; + static int been_here; + int32_t altitude; + int32_t seconds; + + if (been_here && (f->time - gps_time) < 1) + return; + been_here = 1; + gps_time = f->time; + + altitude = f->altitude; + seconds = f->time; + + log.type = AO_LOG_GPS_POS; + log.tick = (f->time * 100); + log.u.gps.latitude = 45 * 1e7; + log.u.gps.longitude = -121 * 1e7; + log.u.gps.altitude_low = altitude; + log.u.gps.altitude_high = altitude >> 16; + ao_log_metrum(file, &log); + + log.type = AO_LOG_GPS_TIME; + log.tick = (f->time * 100); + log.u.gps_time.hour = seconds / 3600; + log.u.gps_time.minute = (seconds / 60) % 60; + log.u.gps_time.second = seconds % 60; + log.u.gps_time.flags = AO_GPS_VALID | AO_GPS_RUNNING | AO_GPS_DATE_VALID | AO_GPS_COURSE_VALID | (12 << AO_GPS_NUM_SAT_SHIFT); + log.u.gps_time.year = 114; + log.u.gps_time.month = 7; + log.u.gps_time.day = 1; + log.u.gps_time.pdop = 1; + + ao_log_metrum(file, &log); +} + +void +ao_log_state(FILE *file, struct flight *f, struct rocket *r) +{ + static struct ao_log_metrum log; + static int log_state = ao_flight_startup; + int flight_state; + + switch (f->state) { + case state_ascent: + if (f->speed == 0 && f->altitude == 0) + flight_state = ao_flight_pad; + else if (f->accel > 0) + flight_state = ao_flight_boost; + else if (f->speed > 300) + flight_state = ao_flight_fast; + else + flight_state = ao_flight_coast; + break; + case state_drogue: + flight_state = ao_flight_drogue; + break; + case state_main: + flight_state = ao_flight_main; + break; + case state_landed: + flight_state = ao_flight_landed; + break; + } + if (flight_state != log_state) { + log.type = AO_LOG_STATE; + log.tick = (f->time * 100); + log.u.state.state = flight_state; + log.u.state.reason = 0; + ao_log_metrum(file, &log); + log_state = flight_state; + } +} + +void +ao_log(FILE *file, struct flight *f, struct rocket *r) +{ + static int been_here = 0; + + if (!been_here) { + been_here = 1; + ao_log_flight(file, f, r); + } + ao_log_sensor(file, f, r); + ao_log_state(file, f, r); + ao_log_gps(file, f, r); +} diff --git a/ao-tools/ao-fakeflight/ao-fakeflight.c b/ao-tools/ao-fakeflight/ao-fakeflight.c new file mode 100644 index 00000000..8a992593 --- /dev/null +++ b/ao-tools/ao-fakeflight/ao-fakeflight.c @@ -0,0 +1,179 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao-fakeflight.h" + +char *state_name[] = { + [state_ascent] = "ascent", + [state_drogue] = "drogue", + [state_main] = "main", + [state_landed] = "landed", +}; + +struct rocket o5778 = { + .models = { + [state_ascent] = { + .cd = 0.5, + .diameter = .100 + }, + [state_drogue] = { + .cd = 1.3, + .diameter = .300 + }, + [state_main] = { + .cd = 1.3, + .diameter = 1.0 + }, + }, + .empty_mass = 15.0, + .main_deploy = 250, + .motors = { + [0] = { + .fuel_mass = 18.021, + .average_thrust = 5778.0, + .burn_time = 8.52, + .delay = 0.0, + }, + [1] = { + .fuel_mass = 18.021, + .average_thrust = 5778.0, + .burn_time = 0, /* 17.04 */ + .delay = 18.0, + }, + }, +}; + +struct rocket n5778 = { + .models = { + [state_ascent] = { + .cd = 0.5, + .diameter = .100 + }, + [state_drogue] = { + .cd = 1.3, + .diameter = .300 + }, + [state_main] = { + .cd = 1.3, + .diameter = 1.0 + }, + }, + .empty_mass = 15.0, + .main_deploy = 250, + .motors = { + [0] = { + .fuel_mass = 9.0105, + .average_thrust = 5778.0, + .burn_time = 4.26, + .delay = 0.0, + }, + }, +}; + +/* + * Move the flight one tick forward + */ +void +step(struct flight *f, struct rocket *r) +{ + double drag = rocket_drag(f, r); + double thrust = rocket_thrust(f, r); + double gravity = rocket_gravity(f, r); + double mass = rocket_mass(f, r); + double accel; + + /* This is our acceleration relative to the earth */ + accel = (drag + thrust - gravity) / mass; + + /* Because the accelerometer is also affected by gravity, it + * only measures *other* forces applied to the rocket + */ + f->accel = (drag + thrust) / mass; + + f->altitude += f->speed * STEP + 0.5 * (accel * STEP) * (accel * STEP); + f->speed += accel * STEP; + f->time += STEP; +} + +void +init(struct flight *f, struct rocket *r) +{ + double gravity = rocket_gravity(f, r); + + /* The pad is pushing up on the rocket to counter + * gravity, so the accelerometer, which only measures + * forces other than gravity, sees only this + */ + f->accel = gravity / rocket_mass(f, r); + f->speed = 0; + f->altitude = 0; + f->time += STEP; +} + +void +fly(FILE *file, struct rocket *r) +{ + struct flight f = { + .time = -1, + .altitude = 0, + .speed = 0, + .accel = 0, + .state = state_ascent, + }; + + double max_speed = 0; + double max_alt = 0; + double max_accel = 0; + + + ao_show_header(file, r); + while (f.time < 0) { + init(&f, r); + ao_log(file, &f, r); + } + while (f.altitude >= 0) { + step(&f, r); + switch (f.state) { + case state_ascent: + if (f.speed >= 0) + break; + f.state = state_drogue; + /* fall through */ + case state_drogue: + if (f.altitude > o5778.main_deploy) + break; + f.state = state_main; + /* fall through */ + case state_main: + break; + } + ao_log(file, &f, r); + max_speed = fmax(max_speed, f.speed); + max_accel = fmax(max_accel, f.accel); + max_alt = fmax(max_alt, f.altitude); + } + fprintf(stderr, "max alt %9.1f speed %9.1f accel %9.1f\n", + max_alt, max_speed, max_accel); +} + +int +main(int argc, char **argv) +{ + fly(stdout, &o5778); +// fly(stdout, &n5778); + return 0; +} diff --git a/ao-tools/ao-fakeflight/ao-fakeflight.h b/ao-tools/ao-fakeflight/ao-fakeflight.h new file mode 100644 index 00000000..fd576a6f --- /dev/null +++ b/ao-tools/ao-fakeflight/ao-fakeflight.h @@ -0,0 +1,140 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FAKEFLIGHT_H_ +#define _AO_FAKEFLIGHT_H_ + +#define __xdata +#include +#include +#include +#include +#include "cc.h" + +#define GAS_CONSTANT 287.05 +#define STEP 0.01 +#define GRAVITATIONAL_CONSTANT 6.67384e-11 +#define GRAVITY 9.807 +#define EARTH_MASS 5.9726e24 +#define EARTH_RADIUS 6375313 + +enum flight_state { + state_ascent, + state_drogue, + state_main, + state_landed, + state_num +}; + +extern char *state_name[]; + +struct model { + double cd; + double diameter; +}; + +struct motor { + double fuel_mass; + double average_thrust; + double burn_time; + double delay; +}; + +#define MAX_MOTORS 12 + +struct rocket { + struct model models[state_num]; + double empty_mass; + double main_deploy; + struct motor motors[MAX_MOTORS]; +}; + +/* Flight state */ + +struct flight { + double time; + double altitude; + double speed; + double accel; + enum flight_state state; +}; + +/* ao-physics.c */ + +/* Density of dry air in kg/m³ for a given pressure and temperature. */ +/* Density of dry air in kg/m³ for a given pressure and temperature. */ +double +density_air(double pressure, /* Pa */ + double temperature); /* °C */ + +/* Area of a circle */ +double +area_circle(double diameter); + +/* Force due to drag (N) */ +double +force_drag(double speed, /* m/s */ + double rho, /* kg/m³ */ + double cd, /* unitless */ + double area); /* m² */ + +/* Force due to gravity (N) */ +double +force_gravity(double mass, /* kg */ + double altitude); /* m */ + +/* ao-rocket.c */ + +/* Mass (kg) of the airframe */ +double +rocket_mass(struct flight *f, struct rocket *r); + +/* Force (N) due to thrust */ +double +rocket_thrust(struct flight *f, struct rocket *r); + +/* Drag (N) due to air resistance */ +double +rocket_drag(struct flight *f, struct rocket *r); + +/* Force (N) due to gravity */ +double +rocket_gravity(struct flight *f, struct rocket *r); + +/* ao-fake-convert.c */ +void +ao_ms5607_unconvert(double altitude, + struct ao_ms5607_sample *ret); + +int16_t +ao_accel_unconvert(double accel); + +void +ao_show_header(FILE *f, struct rocket *r); + +/* ao-fake-log.c */ + +void +ao_log_flight(FILE *file, struct flight *f, struct rocket *r); + +void +ao_log_sensor(FILE *file, struct flight *f, struct rocket *r); + +void +ao_log_state(FILE *file, struct flight *f, struct rocket *r); + +#endif diff --git a/ao-tools/ao-fakeflight/ao-physics.c b/ao-tools/ao-fakeflight/ao-physics.c new file mode 100644 index 00000000..114b9e0f --- /dev/null +++ b/ao-tools/ao-fakeflight/ao-physics.c @@ -0,0 +1,53 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao-fakeflight.h" + +/* Density of dry air in kg/m³ for a given pressure and temperature. */ +double +density_air(double pressure, /* Pa */ + double temperature) /* °C */ +{ + return pressure / (GAS_CONSTANT * (temperature + 273.15)); +} + +/* Area of a circle */ +double +area_circle(double diameter) +{ + double radius = diameter / 2; + return M_PI * radius * radius; +} + +/* Force due to drag (N) */ +double +force_drag(double speed, /* m/s */ + double rho, /* kg/m³ */ + double cd, /* unitless */ + double area) /* m² */ +{ + return 0.5 * rho * (speed * speed) * cd * area; +} + +/* Force due to gravity (N) */ +double +force_gravity(double mass, /* kg */ + double altitude) /* m */ +{ + double distance = altitude + EARTH_RADIUS; + return GRAVITATIONAL_CONSTANT * EARTH_MASS * mass / (distance * distance); +} diff --git a/ao-tools/ao-fakeflight/ao-rocket.c b/ao-tools/ao-fakeflight/ao-rocket.c new file mode 100644 index 00000000..18808c65 --- /dev/null +++ b/ao-tools/ao-fakeflight/ao-rocket.c @@ -0,0 +1,79 @@ +/* + * Copyright © 2014 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao-fakeflight.h" + +/* Mass (kg) of the airframe */ +double +rocket_mass(struct flight *f, struct rocket *r) +{ + double time = f->time; + double m = r->empty_mass; + int n; + + for (n = 0; n < MAX_MOTORS; n++) { + struct motor *motor = &r->motors[n]; + if (motor->burn_time) { + double fuel_time_remain = fmin (motor->burn_time, fmax(motor->burn_time - (time - motor->delay), 0.0)); + double fuel_fraction = fuel_time_remain / motor->burn_time; + m += fuel_fraction * motor->fuel_mass; + } + } + return m; +} + +/* Force (N) due to thrust */ +double +rocket_thrust(struct flight *f, struct rocket *r) +{ + double time = f->time; + double thrust = 0.0; + int n; + + for (n = 0; n < MAX_MOTORS; n++) { + struct motor *motor = &r->motors[n]; + if (motor->burn_time) { + if (motor->delay <= time && time < motor->delay + motor->burn_time) + thrust += motor->average_thrust; + } + } + return thrust; +} + +/* Drag (N) due to air resistance */ +double +rocket_drag(struct flight *f, struct rocket *r) +{ + double pressure = cc_altitude_to_pressure(f->altitude); + double temperature = cc_altitude_to_temperature(f->altitude); + double drag = force_drag(f->speed, density_air(pressure, temperature), + r->models[f->state].cd, + area_circle(r->models[f->state].diameter)); + + /* drag operates in opposition to motion through air */ + if (f->speed >= 0) + drag = -drag; + + return drag; +} + +/* Force (N) due to gravity */ +double +rocket_gravity(struct flight *f, struct rocket *r) +{ + double gravity = force_gravity(rocket_mass (f, r), f->altitude); +} diff --git a/configure.ac b/configure.ac index 9943b92d..b4ecfb98 100644 --- a/configure.ac +++ b/configure.ac @@ -563,6 +563,7 @@ ao-tools/ao-test-gps/Makefile ao-tools/ao-usbtrng/Makefile ao-tools/ao-chaosread/Makefile ao-tools/ao-makebin/Makefile +ao-tools/ao-fakeflight/Makefile ao-utils/Makefile src/Version ])