ao-tools: Add ao-fakeflight
[fw/altos] / ao-tools / ao-fakeflight / ao-fakeflight.c
1 /*
2  * Copyright © 2014 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 #include "ao-fakeflight.h"
19
20 char *state_name[] = {
21         [state_ascent] = "ascent",
22         [state_drogue] = "drogue",
23         [state_main] = "main",
24         [state_landed] = "landed",
25 };
26
27 struct rocket o5778 = {
28         .models = {
29                 [state_ascent] = {
30                         .cd = 0.5,
31                         .diameter = .100
32                 },
33                 [state_drogue] = {
34                         .cd = 1.3,
35                         .diameter = .300
36                 },
37                 [state_main] = {
38                         .cd = 1.3,
39                         .diameter = 1.0
40                 },
41         },
42         .empty_mass = 15.0,
43         .main_deploy = 250,
44         .motors = {
45                 [0] = {
46                         .fuel_mass = 18.021,
47                         .average_thrust = 5778.0,
48                         .burn_time = 8.52,
49                         .delay = 0.0,
50                 },
51                 [1] = {
52                         .fuel_mass = 18.021,
53                         .average_thrust = 5778.0,
54                         .burn_time = 0, /* 17.04 */
55                         .delay = 18.0,
56                 },
57         },
58 };
59
60 struct rocket n5778 = {
61         .models = {
62                 [state_ascent] = {
63                         .cd = 0.5,
64                         .diameter = .100
65                 },
66                 [state_drogue] = {
67                         .cd = 1.3,
68                         .diameter = .300
69                 },
70                 [state_main] = {
71                         .cd = 1.3,
72                         .diameter = 1.0
73                 },
74         },
75         .empty_mass = 15.0,
76         .main_deploy = 250,
77         .motors = {
78                 [0] = {
79                         .fuel_mass = 9.0105,
80                         .average_thrust = 5778.0,
81                         .burn_time = 4.26,
82                         .delay = 0.0,
83                 },
84         },
85 };
86
87 /*
88  * Move the flight one tick forward
89  */
90 void
91 step(struct flight *f, struct rocket *r)
92 {
93         double  drag = rocket_drag(f, r);
94         double  thrust = rocket_thrust(f, r);
95         double  gravity = rocket_gravity(f, r);
96         double  mass = rocket_mass(f, r);
97         double  accel;
98
99         /* This is our acceleration relative to the earth */
100         accel = (drag + thrust - gravity) / mass;
101
102         /* Because the accelerometer is also affected by gravity, it
103          * only measures *other* forces applied to the rocket
104          */
105         f->accel = (drag + thrust) / mass;
106
107         f->altitude += f->speed * STEP + 0.5 * (accel * STEP) * (accel * STEP);
108         f->speed += accel * STEP;
109         f->time += STEP;
110 }
111
112 void
113 init(struct flight *f, struct rocket *r)
114 {
115         double gravity = rocket_gravity(f, r);
116
117         /* The pad is pushing up on the rocket to counter
118          * gravity, so the accelerometer, which only measures
119          * forces other than gravity, sees only this
120          */
121         f->accel = gravity / rocket_mass(f, r);
122         f->speed = 0;
123         f->altitude = 0;
124         f->time += STEP;
125 }
126
127 void
128 fly(FILE *file, struct rocket *r)
129 {
130         struct flight f = {
131                 .time = -1,
132                 .altitude = 0,
133                 .speed = 0,
134                 .accel = 0,
135                 .state = state_ascent,
136         };
137
138         double  max_speed = 0;
139         double  max_alt = 0;
140         double  max_accel = 0;
141
142
143         ao_show_header(file, r);
144         while (f.time < 0) {
145                 init(&f, r);
146                 ao_log(file, &f, r);
147         }
148         while (f.altitude >= 0) {
149                 step(&f, r);
150                 switch (f.state) {
151                 case state_ascent:
152                         if (f.speed >= 0)
153                                 break;
154                         f.state = state_drogue;
155                         /* fall through */
156                 case state_drogue:
157                         if (f.altitude > o5778.main_deploy)
158                                 break;
159                         f.state = state_main;
160                         /* fall through */
161                 case state_main:
162                         break;
163                 }
164                 ao_log(file, &f, r);
165                 max_speed = fmax(max_speed, f.speed);
166                 max_accel = fmax(max_accel, f.accel);
167                 max_alt = fmax(max_alt, f.altitude);
168         }
169         fprintf(stderr, "max alt %9.1f speed %9.1f accel %9.1f\n",
170                 max_alt, max_speed, max_accel);
171 }
172
173 int
174 main(int argc, char **argv)
175 {
176         fly(stdout, &o5778);
177 //      fly(stdout, &n5778);
178         return 0;
179 }