FlightGear next
yasim-test.cpp
Go to the documentation of this file.
1#include <stdio.h>
2
3#include <cstring>
4#include <cstdlib>
5
6#include <simgear/props/props.hxx>
7#include <simgear/xml/easyxml.hxx>
8#include <simgear/misc/sg_path.hxx>
9
10#include "yasim-common.hpp"
11#include "FGFDM.hpp"
12#include "Atmosphere.hpp"
13#include "RigidBody.hpp"
14#include "Airplane.hpp"
15
16using namespace yasim;
17using std::string;
18
19// Stubs. Not needed by a batch program, but required to link.
20bool fgSetFloat (const char * name, float val) { return false; }
21bool fgSetBool(char const * name, bool val) { return false; }
22bool fgGetBool(char const * name, bool def) { return false; }
23bool fgSetString(char const * name, char const * str) { return false; }
24SGPropertyNode* fgGetNode (const char * path, bool create) { return 0; }
25SGPropertyNode* fgGetNode (const char * path, int i, bool create) { return 0; }
26float fgGetFloat (const char * name, float defaultValue) { return 0; }
27double fgGetDouble (const char * name, double defaultValue = 0.0) { return 0; }
28bool fgSetDouble (const char * name, double defaultValue = 0.0) { return 0; }
29
30
31void _setup(Airplane* a, Airplane::Configuration cfgID, float altitude)
32{
33 Model* m = a->getModel();
34 m->setStandardAtmosphere(altitude);
35 switch (cfgID) {
36 case Airplane::APPROACH:
37 fprintf(stderr,"Setting approach controls.\n");
38 a->setApproachControls();
39 break;
40 case Airplane::CRUISE:
41 fprintf(stderr,"Setting cruise controls.\n");
42 a->setCruiseControls();
43 break;
44 default:
45 break;
46 }
47 m->getBody()->recalc();
48};
49
50void _calculateAcceleration(Airplane* a, float aoa_rad, float speed_mps, float* output)
51{
52 Model* m = a->getModel();
53 State s;
54 s.setupState(aoa_rad, speed_mps, 0);
55 m->getBody()->reset();
56 m->initIteration();
57 m->calcForces(&s);
58 m->getBody()->getAccel(output);
59 s.localToGlobal(output, output);
60};
61
62// Comments are incorrect: Historically this function only produces lift, drag curves
63// For lift, drag and LD three column output please use --yasim-graph-detailed
64//
65// Generate a graph of lift, drag and L/D against AoA at the specified
66// speed and altitude. The result is a tab-separated file of
67// numbers: "aoa lift drag LD" (aoa in degrees, lift and drag in
68// G's). You can use this in gnuplot like so (assuming the output is
69// in a file named "dat":
70/*
71 plot "dat" using 1:2 with lines title 'lift', \
72 "dat" using 1:3 with lines title 'drag', \
73 "dat" using 1:4 with lines title 'LD'
74*/
75void yasim_graph(Airplane* a, const float alt, const float kts, Airplane::Configuration cfgID)
76{
77 _setup(a, cfgID, alt);
78 float speed = kts * KTS2MPS;
79 float acc[3] {0,0,0};
80 float cl_max = 0, cd_min = 1e6, ld_max = 0;
81 int cl_max_deg = 0, cd_min_deg = 0, ld_max_deg = 0;
82
83 printf("aoa\tlift\tdrag\n");
84 for(int deg=-15; deg<=90; deg++) {
85 float aoa = deg * DEG2RAD;
86 _calculateAcceleration(a, aoa, speed, acc);
87 float drag = acc[0] * (-1/9.8);
88 float lift = 1 + acc[2] * (1/9.8);
89 float ld = lift/drag;
90
91 if (cd_min > drag) {
92 cd_min = drag;
93 cd_min_deg = deg;
94 }
95 if (cl_max < lift) {
96 cl_max = lift;
97 cl_max_deg = deg;
98 }
99 if (ld_max < ld) {
100 ld_max= ld;
101 ld_max_deg = deg;
102 }
103 printf("%2d\t%.4f\t%.4f\n", deg, lift, drag);
104 }
105 printf("# cl_max %.4f at %d deg\n", cl_max, cl_max_deg);
106 printf("# cd_min %.4f at %d deg\n", cd_min, cd_min_deg);
107 printf("# ld_max %.4f at %d deg\n", ld_max, ld_max_deg);
108}
109
110void yasim_masses(Airplane* a)
111{
112 RigidBody* body = a->getModel()->getBody();
113 int N = body->numMasses();
114 float pos[3];
115 float m, mass = 0;
116 printf("id\tposx\tposy\tposz\tmass\n");
117 for (int i = 0; i < N; i++)
118 {
119 body->getMassPosition(i, pos);
120 m = body->getMass(i);
121 printf("%d\t%.3f\t%.3f\t%.3f\t%.3f\n", i, pos[0], pos[1], pos[2], m);
122 mass += m;
123 }
124 printf("Total mass: %g", mass);
125}
126
127void yasim_drag(Airplane* a, const float aoa, const float alt, Airplane::Configuration cfgID)
128{
129 _setup(a, cfgID, alt);
130
131 float cd_min = 1e6;
132 int cd_min_kts = 0;
133 float acc[3] {0,0,0};
134
135 printf("#kts, drag\n");
136 for(int kts=15; kts<=150; kts++) {
137 _calculateAcceleration(a, aoa,kts * KTS2MPS, acc);
138 float drag = acc[0] * (-1/9.8);
139 if (cd_min > drag) {
140 cd_min = drag;
141 cd_min_kts = kts;
142 }
143 printf("%d %g\n", kts, drag);
144 }
145 printf("# cd_min %g at %d kts\n", cd_min, cd_min_kts);
146}
147
148/* Returns AoA for zero lift at specified altitude and speed. */
149float yasim_find_zero_lift_aoa(Airplane* a, const float alt, float kts, Airplane::Configuration cfgID, float* acc)
150{
151 _setup(a, cfgID, alt);
152 float aoa_deg = 0;
153 float aoa_deg_delta = 10;
154 while (1) {
155 float aoa = aoa_deg * DEG2RAD;
156 _calculateAcceleration(a, aoa, kts * KTS2MPS, acc);
157 float lift = acc[2];
158 if (lift > 0) aoa_deg -= aoa_deg_delta;
159 if (lift < 0) aoa_deg += aoa_deg_delta;
160 aoa_deg_delta /= 2;
161 if (aoa_deg_delta < 0.001) break;
162 //printf("aoa_deg=%g\n", aoa_deg);
163 }
164 //printf("alt=%g kts=%g: aoa_deg=%g\n", alt, kts, aoa_deg);
165 return aoa_deg;
166}
167
168/* Returns info about best speed at a particular height. */
169void yasim_best_speed_at_height(Airplane* a, const float alt, Airplane::Configuration cfgID,
170 bool verbose, float& o_best_speed_kts, float& o_best_drag, float& o_best_aoa_deg)
171{
172 o_best_speed_kts = 0;
173 o_best_drag = 1e9;
174 o_best_aoa_deg = 0.0f;
175
176 /* Could probably use a gradient-descent method, but for now we just use
177 linear list of speeds. */
178 for (float kts = 50; kts < 600; kts += 1) {
179 float acc[3];
180 float aoa_deg = yasim_find_zero_lift_aoa(a, alt, kts, cfgID, acc);
181 float aoa = aoa_deg * DEG2RAD;
182 float drag = acc[0] / -9.8;
183 float idrag = 9.8 * tan(aoa);
184 float drag_total = drag + idrag;
185
186 if (verbose) {
187 printf("acc=(% 10.4f % 10.2g % 10.4f)."
188 " alt=% 10.4f kts=% 10.4f: aoa_deg=% 10.4f drag=% 10.4f"
189 " idrag=% 10.4f drag_total=% 10.4f\n",
190 acc[0], acc[1], acc[2],
191 alt, kts, aoa_deg, drag,
192 idrag, drag_total);
193 }
194
195 if (drag_total < o_best_drag) {
196 o_best_speed_kts = kts;
197 o_best_drag = drag_total;
198 o_best_aoa_deg = aoa_deg;
199 }
200 }
201}
202
203/* Shows best speed at various heights. */
204void yasim_show_best_speed_at_heights(Airplane* a, Airplane::Configuration cfgID)
205{
206 for (int alt_ft=0; alt_ft < 50*1000; alt_ft += 1000) {
207 float alt_m = alt_ft * 12.0 * 2.54 / 100.0;
208 float best_speed_kts;
209 float best_drag;
210 float best_aoa_deg;
211
212 yasim_best_speed_at_height(a, alt_m, cfgID, false /*verbose*/,
213 best_speed_kts, best_drag, best_aoa_deg);
214
215 printf("altitude=% 6ift: best_speed=%gkts best_aoa=%.2fdeg drag=%g\n",
216 alt_ft, best_speed_kts, best_aoa_deg, best_drag);
217 }
218}
219
220
221void findMinSpeed(Airplane* a, float alt)
222{
223 a->addControlSetting(Airplane::CRUISE, "/controls/flight/elevator-trim", 0.7f);
224 _setup(a, Airplane::CRUISE, alt);
225 float acc[3];
226
227 printf("aoa\tknots\tlift\n");
228 for(int deg=0; deg<=20; deg++) {
229 float aoa = deg * DEG2RAD;
230 for(int kts=15; kts<=180; kts++) {
231 _calculateAcceleration(a, aoa, kts * KTS2MPS, acc);
232 float lift = acc[2];
233 if (lift > 0) {
234 printf("%d\t%d\t%f\n", deg, kts, lift);
235 break;
236 }
237 }
238 }
239}
240
241// Additional command functions with 10x detail, smaller AoA range
242//
243// Generate a graph of lift, drag and L/D against AoA at the specified
244// speed and altitude with fine deteil. The result is a tab-separated file of
245// numbers: "aoa lift drag LD" (aoa in degrees, lift and drag in
246// G's). You can use this in gnuplot like so (assuming the output is
247// in a file named "dat":
248/*
249 plot "dat" using 1:2 with lines title 'lift', \
250 "dat" using 1:3 with lines title 'drag', \
251 "dat" using 1:4 with lines title 'LD'
252*/
253void yasim_graph_detailed(Airplane* a, const float alt, const float kts, Airplane::Configuration cfgID)
254{
255 _setup(a, cfgID, alt);
256 float speed = kts * KTS2MPS;
257 float acc[3] {0,0,0};
258 float cl_max = 0, cd_min = 1e6, ld_max = 0;
259 // int cl_max_deg = 0, cd_min_deg = 0, ld_max_deg = 0;
260
261 printf("aoa\tlift\tdrag\tLD\n");
262 for(float deg=-2.0; deg<=25.0 ; deg+= 0.10 ) {
263 float aoa = deg * DEG2RAD;
264 _calculateAcceleration(a, aoa, speed, acc);
265 float drag = acc[0] * (-1/9.8);
266 float lift = 1 + acc[2] * (1/9.8);
267 float ld = lift/drag;
268
269 if (cd_min > drag) {
270 cd_min = drag;
271 // cd_min_deg = deg;
272 }
273 if (cl_max < lift) {
274 cl_max = lift;
275 // cl_max_deg = deg;
276 }
277 if (ld_max < ld) {
278 ld_max= ld;
279 // ld_max_deg = deg;
280 }
281 printf("%-2.1f\t%-2.3f\t%-2.3f\t%-2.3f\n", deg, lift, drag, ld);
282 }
283 //printf("# cl_max %.4f at %d deg\n", cl_max, cl_max_deg);
284 //printf("# cd_min %.4f at %d deg\n", cd_min, cd_min_deg);
285 //printf("# ld_max %.4f at %d deg\n", ld_max, ld_max_deg);
286}
287
288void yasim_drag_detailed(Airplane* a, const float aoa, const float alt, Airplane::Configuration cfgID)
289{
290 _setup(a, cfgID, alt);
291
292 float cd_min = 1e6;
293 // int cd_min_kts = 0;
294 float acc[3] {0,0,0};
295
296 printf("knots\tdrag\n");
297 for(float kts=0; kts<=100; kts += 0.1) {
298 _calculateAcceleration(a, aoa,kts * KTS2MPS, acc);
299 float drag = acc[0] * (-1/9.8);
300 if (cd_min > drag) {
301 cd_min = drag;
302 // cd_min_kts = kts;
303 }
304 printf("%-2.3f\t%-2.3f\n", kts, drag);
305 }
306 //printf("# cd_min %g at %d kts\n", cd_min, cd_min_kts);
307}
308
309void findMinSpeedDetailed(Airplane* a, float alt)
310{
311 a->addControlSetting(Airplane::CRUISE, "/controls/flight/elevator-trim", 0.7f);
312 _setup(a, Airplane::CRUISE, alt);
313 float acc[3];
314
315 printf("aoa\tknots\tlift\n");
316 for(float deg=-2; deg<=25.0; deg+=0.10) {
317 float aoa = deg * DEG2RAD;
318 for(float kts = 0; kts <= 180.0; kts += 0.1) {
319 _calculateAcceleration(a, aoa, kts * KTS2MPS, acc);
320 float lift = acc[2];
321 if (lift > 0) {
322 printf("%-2.1f \t %-2.3f \t %-2.3f\n", deg, kts, ( 100 + 100 * lift));
323 break;
324 }
325 }
326 }
327}
328
329void report(Airplane* a)
330{
331 printf("==========================\n");
332 printf("= YASim solution results =\n");
333 printf("==========================\n");
334 float aoa = a->getCruiseAoA() * RAD2DEG;
335 float tailIncidence = a->getTailIncidence() * RAD2DEG;
336 float drag = 1000 * a->getDragCoefficient();
337 float cg[3];
338 a->getModel()->getBody()->getCG(cg);
339 a->getModel()->getBody()->recalc();
340
341 float SI_inertia[9];
342 a->getModel()->getBody()->getInertiaMatrix(SI_inertia);
343 float MAC = 0, MACx = 0, MACy = 0;
344 float sweepMin = 0, sweepMax = 0;
345 Wing* wing {nullptr};
346 Wing* tail {nullptr};
347 if (a->hasWing()) {
348 wing = a->getWing();
349 tail = a->getTail();
350 }
351 printf("Iterations : %d\n", a->getSolutionIterations());
352 printf("Drag Coefficient : %.3f\n", drag);
353 printf("Lift Ratio : %.3f\n", a->getLiftRatio());
354 printf("Cruise AoA : %.2f deg\n", aoa);
355 printf("Tail Incidence : %.2f deg\n", tailIncidence);
356 printf("Approach Elevator : %.3f\n\n", a->getApproachElevator());
357 printf("CG : x:%.3f, y:%.3f, z:%.3f\n", cg[0], cg[1], cg[2]);
358 if (wing) {
359 MAC = wing->getMACLength();
360 MACx = wing->getMACx();
361 MACy = wing->getMACy();
362 sweepMin = wing->getSweepLEMin() * RAD2DEG;
363 sweepMax = wing->getSweepLEMax() * RAD2DEG;
364 printf("Wing MAC : (x:%.3f, y:%.3f), length:%.3f \n", MACx, MACy, MAC);
365 printf("hard limit CG-x : %.3f m\n", a->getCGHardLimitXMax());
366 printf("soft limit CG-x : %.3f m\n", a->getCGSoftLimitXMax());
367 printf("CG-x : %.3f m\n", cg[0]);
368 printf("CG-x rel. MAC : %3.0f%%\n", a->getCGMAC()*100);
369 printf("soft limit CG-x : %.3f m\n", a->getCGSoftLimitXMin());
370 printf("hard limit CG-x : %.3f m\n", a->getCGHardLimitXMin());
371 printf("\n");
372 printf("wing lever : %.3f m\n", a->getWingLever());
373 printf("tail lever : %.3f m\n", a->getTailLever());
374 printf("\n");
375 printf("max thrust : %.2f kN\n", a->getMaxThrust()/1000);
376 printf("thrust/empty : %.2f\n", a->getThrust2WeightEmpty());
377 printf("thrust/mtow : %.2f\n", a->getThrust2WeightMTOW());
378 printf("\n");
379 printf("wing span : %.2f m\n", a->getWingSpan());
380 printf("sweep lead. edge : %.1f .. %.1f deg\n", sweepMin, sweepMax);
381 printf("wing area : %.2f m^2\n", a->getWingArea());
382 printf("wing load empty : %.2f kg/m^2 (Empty %.0f kg)\n", a->getWingLoadEmpty(), a->getEmptyWeight());
383 printf("wing load MTOW : %.2f kg/m^2 (MTOW %.0f kg)\n", a->getWingLoadMTOW(), a->getMTOW());
384 printf("\n");
385 printf("tail span : %.3f m\n", tail->getSpan());
386 printf("tail area : %.3f m^2\n", tail->getArea());
387 printf("\n");
388 wing->printSectionInfo();
389 }
390 printf("\nInertia Tensor [kg*m^2], ( Angular Moments ) Origo at CG:\n\n");
391 printf(" Effect on Axis\n");
392 printf(" x Roll y Pitch z Yaw\n");
393 printf("Impulse x Roll %7.0f %7.0f %7.0f\n", SI_inertia[0], SI_inertia[1], SI_inertia[2]);
394 printf(" on y Pitch %7.0f %7.0f %7.0f\n", SI_inertia[3], SI_inertia[4], SI_inertia[5]);
395 printf(" Axis z Yaw %7.0f %7.0f %7.0f\n", SI_inertia[6], SI_inertia[7], SI_inertia[8]);
396}
397
398int usage()
399{
400 fprintf(stderr, "Usage: \n");
401 fprintf(stderr, " yasim <aircraft.xml> [-g [-a meters] [-s kts] [-approach | -cruise] ]\n");
402 fprintf(stderr, " yasim <aircraft.xml> [-d [-a meters] [-approach | -cruise] ]\n");
403 fprintf(stderr, " yasim <aircraft.xml> [-m] [-h] [--min-speed]\n");
404 fprintf(stderr, " yasim <aircraft.xml> [-test] [-a meters] [-s kts] [-approach | -cruise] ]\n");
405 fprintf(stderr, " -g print lift/drag table: aoa, lift, drag, lift/drag \n");
406 fprintf(stderr, " -d print drag over TAS: kts, drag\n");
407 fprintf(stderr, " -D print kts at lowest drag at specified altitude\n");
408 fprintf(stderr, " --aD print kts at lowest drag at different altitudes\n");
409 fprintf(stderr, " -a set altitude in meters!\n");
410 fprintf(stderr, " -s set speed in knots\n");
411 fprintf(stderr, " -m print mass distribution table: id, x, y, z, mass \n");
412 fprintf(stderr, " Options to generate LD curve and greater detailed plotting\n");
413 fprintf(stderr, " yasim <aircraft.xml> [--detailed-graph] [--detailed-drag]\n");
414 fprintf(stderr, " yasim <aircraft.xml> [--detailed-min-speed -approach]\n");
415 fprintf(stderr, " yasim <aircraft.xml> [--detailed-min-speed -cruise]\n");
416 fprintf(stderr, " -test print summary and output like -g -m \n");
417 return 1;
418}
419
420
421int main(int argc, char** argv)
422{
423 FGFDM* fdm = new FGFDM();
424 Airplane* a = fdm->getAirplane();
425
426 if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
427 return usage();
428 }
429 // Read
430 try {
431 string file = argv[1];
432 readXML(SGPath(file), *fdm);
433 }
434 catch (const sg_exception &e) {
435 printf("XML parse error: %s (%s)\n", e.getFormattedMessage().c_str(), e.getOrigin());
436 }
437 // ... and run
438 bool verbose {false};
439 if (argc > 2 && strcmp(argv[2], "-v") == 0) {
440 verbose=true;
441 }
442 if ((argc == 4) && (strcmp(argv[2], "--tweak") == 0)) {
443 float tweak = std::atof(argv[3]);
444 a->setSolverTweak(tweak);
445 a->setSolverMaxIterations(2000);
446 verbose=true;
447 }
448 a->compile(verbose);
449 if(a->getFailureMsg()) {
450 printf("SOLUTION FAILURE: %s\n", a->getFailureMsg());
451 }
452 if(!a->getFailureMsg() && argc > 2 ) {
453 bool test = (strcmp(argv[2], "-test") == 0);
454 Airplane::Configuration cfg = Airplane::NONE;
455 float alt = 5000, kts = 100;
456
457// command extensions tested first to preserve precedence
458 if((strcmp(argv[2], "--detailed-graph") == 0) || test) {
459 for(int i=3; i<argc; i++) {
460 if (std::strcmp(argv[i], "-a") == 0) {
461 if (i+1 < argc) alt = std::atof(argv[++i]);
462 }
463 else if(std::strcmp(argv[i], "-s") == 0) {
464 if(i+1 < argc) kts = std::atof(argv[++i]);
465 }
466 else if(std::strcmp(argv[i], "-approach") == 0) cfg = Airplane::APPROACH;
467 else if(std::strcmp(argv[i], "-cruise") == 0) cfg = Airplane::CRUISE;
468 else return usage();
469 }
470 if (test) {
471 report(a);
472 printf("\n#-- lift, drag at altitude %.0f meters, %.0f knots, Config %d --\n", alt, kts, cfg);
473 }
474 yasim_graph_detailed(a, alt, kts, cfg);
475 if (test) {
476 printf("\n#-- mass distribution --\n");
477 yasim_masses(a);
478 }
479 }
480 else if(strcmp(argv[2], "--detailed-drag") == 0) {
481 float alt = 2000, aoa = a->getCruiseAoA();
482 for(int i=3; i<argc; i++) {
483 if (std::strcmp(argv[i], "-a") == 0) {
484 if (i+1 < argc) alt = std::atof(argv[++i]);
485 }
486 else if(std::strcmp(argv[i], "-approach") == 0) cfg = Airplane::APPROACH;
487 else if(std::strcmp(argv[i], "-cruise") == 0) cfg = Airplane::CRUISE;
488 else return usage();
489 }
490 yasim_drag_detailed(a, aoa, alt, cfg);
491 }
492 else if(strcmp(argv[2], "--detailed-min-speed") == 0) {
493 alt = 10;
494 for(int i=3; i<argc; i++) {
495 if (std::strcmp(argv[i], "-a") == 0) {
496 if (i+1 < argc) alt = std::atof(argv[++i]);
497 }
498 else if(std::strcmp(argv[i], "-approach") == 0) cfg = Airplane::APPROACH;
499 else if(std::strcmp(argv[i], "-cruise") == 0) cfg = Airplane::CRUISE;
500 else return usage();
501 }
502 findMinSpeedDetailed(a, alt);
503 }
504 else if((strcmp(argv[2], "-g") == 0) || test) {
505 for(int i=3; i<argc; i++) {
506 if (std::strcmp(argv[i], "-a") == 0) {
507 if (i+1 < argc) alt = std::atof(argv[++i]);
508 }
509 else if(std::strcmp(argv[i], "-s") == 0) {
510 if(i+1 < argc) kts = std::atof(argv[++i]);
511 }
512 else if(std::strcmp(argv[i], "-approach") == 0) cfg = Airplane::APPROACH;
513 else if(std::strcmp(argv[i], "-cruise") == 0) cfg = Airplane::CRUISE;
514 else return usage();
515 }
516 if (test) {
517 report(a);
518 printf("\n#-- lift, drag at altitude %.0f meters, %.0f knots, Config %d --\n", alt, kts, cfg);
519 }
520 yasim_graph(a, alt, kts, cfg);
521 if (test) {
522 printf("\n#-- mass distribution --\n");
523 yasim_masses(a);
524 }
525 }
526 else if(!strcmp(argv[2], "-d") || !strcmp(argv[2], "-D") || !strcmp(argv[2], "--aD")) {
527 float alt = 2000;
528 for(int i=3; i<argc; i++) {
529 if (std::strcmp(argv[i], "-a") == 0) {
530 if (i+1 < argc) alt = std::atof(argv[++i]);
531 }
532 else if(std::strcmp(argv[i], "-approach") == 0) cfg = Airplane::APPROACH;
533 else if(std::strcmp(argv[i], "-cruise") == 0) cfg = Airplane::CRUISE;
534 else return usage();
535 }
536 if (strcmp(argv[2], "-d") == 0) {
537 float aoa = a->getCruiseAoA();
538 yasim_drag(a, aoa, alt, cfg);
539 }
540 else if (!strcmp(argv[2], "-D")) {
541 float best_speed_kts;
542 float best_drag;
543 float best_aoa_deg;
544 yasim_best_speed_at_height(a, alt, cfg, true /*verbose*/, best_speed_kts, best_drag, best_aoa_deg);
545 printf("altitude=%gm: best speed=%g best_aoa_deg=%g drag=%g\n", alt, best_speed_kts, best_aoa_deg, best_drag);
546 }
547 else if (!strcmp(argv[2], "--aD")) {
549 }
550 }
551 else if(strcmp(argv[2], "-m") == 0) {
552 yasim_masses(a);
553 }
554 else if(strcmp(argv[2], "--min-speed") == 0) {
555 alt = 10;
556 for(int i=3; i<argc; i++) {
557 if (std::strcmp(argv[i], "-a") == 0) {
558 if (i+1 < argc) alt = std::atof(argv[++i]);
559 }
560 else if(std::strcmp(argv[i], "-approach") == 0) cfg = Airplane::APPROACH;
561 else if(std::strcmp(argv[i], "-cruise") == 0) cfg = Airplane::CRUISE;
562 else return usage();
563 }
564 findMinSpeed(a, alt);
565 }
566 }
567 else {
568 report(a);
569 }
570 delete fdm;
571 return 0;
572}
double altitude
Definition ADA.cxx:46
#define i(x)
const char * name
int main()
#define N
static const float DEG2RAD
Definition Gear.cpp:19
void report(Airplane *a)
void yasim_masses(Airplane *a)
void findMinSpeedDetailed(Airplane *a, float alt)
void yasim_drag_detailed(Airplane *a, const float aoa, const float alt, Airplane::Configuration cfgID)
double fgGetDouble(const char *name, double defaultValue=0.0)
Get a double value for a property.
void yasim_graph_detailed(Airplane *a, const float alt, const float kts, Airplane::Configuration cfgID)
bool fgGetBool(char const *name, bool def)
Get a bool value for a property.
bool fgSetBool(char const *name, bool val)
Set a bool value for a property.
void yasim_graph(Airplane *a, const float alt, const float kts, Airplane::Configuration cfgID)
void yasim_best_speed_at_height(Airplane *a, const float alt, Airplane::Configuration cfgID, bool verbose, float &o_best_speed_kts, float &o_best_drag, float &o_best_aoa_deg)
bool fgSetDouble(const char *name, double defaultValue=0.0)
Set a double value for a property.
float yasim_find_zero_lift_aoa(Airplane *a, const float alt, float kts, Airplane::Configuration cfgID, float *acc)
bool fgSetString(char const *name, char const *str)
Set a string value for a property.
void _setup(Airplane *a, Airplane::Configuration cfgID, float altitude)
void yasim_drag(Airplane *a, const float aoa, const float alt, Airplane::Configuration cfgID)
void yasim_show_best_speed_at_heights(Airplane *a, Airplane::Configuration cfgID)
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
float fgGetFloat(const char *name, float defaultValue)
Get a float value for a property.
int usage()
bool fgSetFloat(const char *name, float val)
Set a float value for a property.
void _calculateAcceleration(Airplane *a, float aoa_rad, float speed_mps, float *output)
void findMinSpeed(Airplane *a, float alt)