/* * Copyright (c) 1994, Riley Rainey, riley@netcon.com * * Permission to use, copy, modify and distribute (without charge) this * software, documentation, images, etc. is granted, provided that this * comment and the author's name is retained. * * This software is provided by the author as is, and without any expressed * or implied warranties, including, but not limited to, the implied * warranties of merchantability and fitness for a particular purpose. In no * event shall the author be liable for any direct, indirect, incidental, or * consequential damages arising in any way out of the use of this software. */ #include "gedit.h" #include "cell.h" #include #include #include struct balance_data { double weight; /* weight for this test */ VPoint rm; /* rest main gear location (input) */ VPoint rn; /* rest nose gear location (input) */ double cm, cn; /* rest compression values of each strut */ double Gm, Gn; /* strut + tire lengths */ double Km, Kn; /* string constants (output) */ double Gpz; /* the old "grounding point" Z value */ double theta; }; void balance (s) struct balance_data *s; { double theta, cosTheta, sinTheta; double Fmz; /* * Determine the rest pitch angle of the aircraft body */ theta = - atan2 (s->rn.z - s->rm.z, s->rn.x - s->rm.x); cosTheta = cos(theta); sinTheta = sin(theta); s->theta = theta; /* * Determine correct rm/rn values */ s->rn.z = s->rn.z - s->Gn - s->cn; s->rm.z = s->rm.z - s->Gm - s->cm; /* * Determine spring constants */ Fmz = (s->weight * cosTheta * s->rn.x) / (s->rm.x - s->rn.x); s->Km = - Fmz * s->cm; s->Kn = (- Fmz - s->weight * cosTheta) * - s->cn; /* * Determine the initial grounding point */ s->Gpz = s->rm.x * sinTheta + (s->rm.z + s->Gm + s->cm) * cosTheta; } extern Widget CreatePanelDialog (); extern void SetCellValueDouble(), SetCellValueString(); extern double GetCellValueDouble(); enum { InfoName, InfoEmptyWeight, InfoIxx, InfoIyy, InfoIzz, InfoWingSpan, InfoWingArea, InfoWingChord, GearGm, GearcmMax, GearDm, GearKm, GearGn, GearcnMax, GearDn, GearKn, DerivClda, DerivCldr, DerivClp, DerivCmq, DerivCnr, DerivCmAlpha, DerivCmFactor, PowerplantFuel, PowerplantThrust, PowerplantABThrust, PowerplantLag, PowerplantSpFuelConsump, PowerplantSpABFuelConsump }; struct cell info_dialog_items[] = { { InfoName, "Aircraft Name", "Unknown", 10, NULL, NULL }, { InfoEmptyWeight, "Empty Weight [lbs]", "10000", 10, NULL, NULL }, { InfoIxx, "Ixx [slug*ft^2]", "5000", 10, NULL, NULL }, { InfoIyy, "Iyy [slug*ft^2]", "50000", 10, NULL, NULL }, { InfoIzz, "Izz [slug*ft^2]", "50000", 10, NULL, NULL }, { InfoWingSpan, "WingSpan [ft]", "50000", 10, NULL, NULL }, { InfoWingArea, "Wing Area [ft]", "50000", 10, NULL, NULL }, { InfoWingChord, "Wing Chord [ft]", "50000", 10, NULL, NULL }, { -1, NULL, NULL, 0, NULL, NULL } }; struct cell gear_dialog_items[] = { { GearGm, "Main Gear Assembly Length (Gm) [ft]", "2.0", 10, NULL, NULL }, { GearcmMax, "Main Gear Max Extension (cmMax) [ft]", "1.0", 10, NULL, NULL }, { GearDm, "Main Gear Damping Factor (Dm) [lb/ft/sec]", "2.0", 10, NULL, NULL }, { GearKm, "Main Gear Spring Factor (Km) [*]", "0.0", 10, NULL, NULL }, { GearGn, "Nose Gear Assembly Length (Gn) [ft]", "2.0", 10, NULL, NULL }, { GearcnMax, "Nose Gear Max Extension (cnMax) [ft]", "1.0", 10, NULL, NULL }, { GearDn, "Nose Gear Damping Factor (Dn) [lb/ft/sec]", "2.0", 10, NULL, NULL }, { GearKn, "Nose Gear Spring Factor (Kn) [*]", "0.0", 10, NULL, NULL }, { -1, NULL, NULL, 0, NULL, NULL } }; struct cell deriv_dialog_items[] = { { DerivClda, "Roll moment from aileron offset", "0.03", 10, NULL, NULL }, { DerivCldr, "Roll moment from rudder offset", "0.003", 10, NULL, NULL }, { DerivClp, "Roll damping", "-0.3", 10, NULL, NULL }, { DerivCmq, "Pitch damping", "-8.0", 10, NULL, NULL }, { DerivCnr, "Yaw damping", "-2.0", 10, NULL, NULL }, { DerivCmAlpha, "Pitch due to angle of attack", "-0.3", 10, NULL, NULL }, { DerivClda, "Pitch due to angle of attack [stalled]", "-0.2", 10, NULL, NULL }, { -1, NULL, NULL, 0, NULL, NULL } }; struct cell pwr_dialog_items[] = { { PowerplantFuel, "Internal Fuel Capacity [lbs]", "1000", 10, NULL, NULL }, { PowerplantThrust, "Military Thrust [lbs]", "10000", 10, NULL, NULL }, { PowerplantABThrust, "Afterburner Thrust [lbs]", "10000", 10, NULL, NULL }, { PowerplantLag, "Engine response lag [negative value]", "-3.0", 10, NULL, NULL }, { PowerplantSpFuelConsump, "Specific fuel consumption, afterburner off [lb fuel/lb T * hr]", "0.7", 10, NULL, NULL }, { PowerplantSpABFuelConsump, "Specific fuel consumption, afterburner on [lb fuel/lb T * hr]", "2.50", 10, NULL, NULL }, { -1, NULL, NULL, 0, NULL, NULL } }; Widget CreateInfoDialog(parent) Widget parent; { return CreatePanelDialog("info_dialog", parent, info_dialog_items, XtNumber(info_dialog_items), MENU_INFO_CALCULATE, MENU_INFO_CANCEL); } Widget CreateGearDialog(parent) Widget parent; { return CreatePanelDialog("gear_dialog", parent, gear_dialog_items, XtNumber(gear_dialog_items), MENU_GEAR_CALCULATE, MENU_GEAR_CANCEL); } Widget CreateDerivDialog(parent) Widget parent; { return CreatePanelDialog("stability_dialog", parent, deriv_dialog_items, XtNumber(deriv_dialog_items), MENU_DERIV_CALCULATE, MENU_DERIV_CANCEL); } Widget CreatePowerplantDialog(parent) Widget parent; { return CreatePanelDialog("powerplant_dialog", parent, pwr_dialog_items, XtNumber(pwr_dialog_items), MENU_PWR_CALCULATE, MENU_PWR_CANCEL); } void InitializeDialogs(c) craftType *c; { SetCellValueString (info_dialog_items, InfoName, craft_name); SetCellValueDouble (info_dialog_items, InfoEmptyWeight, c->emptyWeight); SetCellValueDouble (info_dialog_items, InfoIxx, c->I.m[0][0]); SetCellValueDouble (info_dialog_items, InfoIyy, c->I.m[1][1]); SetCellValueDouble (info_dialog_items, InfoIzz, c->I.m[2][2]); SetCellValueDouble (info_dialog_items, InfoWingSpan, c->wings * 2.0); SetCellValueDouble (info_dialog_items, InfoWingArea, c->wingS); SetCellValueDouble (info_dialog_items, InfoWingChord, c->c); SetCellValueDouble (gear_dialog_items, GearGm, c->Gm); SetCellValueDouble (gear_dialog_items, GearcmMax, c->cmMax); SetCellValueDouble (gear_dialog_items, GearDm, c->Dm); SetCellValueDouble (gear_dialog_items, GearKm, c->Km); SetCellValueDouble (gear_dialog_items, GearGn, c->Gn); SetCellValueDouble (gear_dialog_items, GearcnMax, c->cnMax); SetCellValueDouble (gear_dialog_items, GearDn, c->Dn); SetCellValueDouble (gear_dialog_items, GearKn, c->Kn); SetCellValueDouble (pwr_dialog_items, PowerplantFuel, c->maxFuel); SetCellValueDouble (pwr_dialog_items, PowerplantThrust, c->maxThrust); SetCellValueDouble (pwr_dialog_items, PowerplantABThrust, c->maxABThrust); SetCellValueDouble (pwr_dialog_items, PowerplantLag, c->engineLag); SetCellValueDouble (pwr_dialog_items, PowerplantSpFuelConsump, c->spFuelConsump); SetCellValueDouble (pwr_dialog_items, PowerplantSpABFuelConsump, c->spABFuelConsump); } void GetCraftInfo(c) craftType *c; { GetCellValueString (info_dialog_items, InfoName, craft_name); GetCellValueDouble (info_dialog_items, InfoEmptyWeight, &c->emptyWeight); GetCellValueDouble (info_dialog_items, InfoIxx, &c->I.m[0][0]); GetCellValueDouble (info_dialog_items, InfoIyy, &c->I.m[1][1]); GetCellValueDouble (info_dialog_items, InfoIzz, &c->I.m[2][2]); GetCellValueDouble (info_dialog_items, InfoWingSpan, &c->wings); c->wings /= 2.0; GetCellValueDouble (info_dialog_items, InfoWingArea, &c->wingS); GetCellValueDouble (info_dialog_items, InfoWingChord, &c->c); GetCellValueDouble (gear_dialog_items, GearGm, &c->Gm); GetCellValueDouble (gear_dialog_items, GearcmMax, &c->cmMax); GetCellValueDouble (gear_dialog_items, GearDm, &c->Dm); GetCellValueDouble (gear_dialog_items, GearKm, &c->Km); GetCellValueDouble (gear_dialog_items, GearGn, &c->Gn); GetCellValueDouble (gear_dialog_items, GearcnMax, &c->cnMax); GetCellValueDouble (gear_dialog_items, GearDn, &c->Dn); GetCellValueDouble (gear_dialog_items, GearKn, &c->Kn); GetCellValueDouble (pwr_dialog_items, PowerplantFuel, &c->maxFuel); GetCellValueDouble (pwr_dialog_items, PowerplantThrust, &c->maxThrust); GetCellValueDouble (pwr_dialog_items, PowerplantABThrust, &c->maxABThrust); GetCellValueDouble (pwr_dialog_items, PowerplantLag, &c->engineLag); GetCellValueDouble (pwr_dialog_items, PowerplantSpFuelConsump, &c->spFuelConsump); GetCellValueDouble (pwr_dialog_items, PowerplantSpABFuelConsump, &c->spABFuelConsump); c->viewPoint = marker_list[MARKER_HEAD].location.point; } void GearCalculate(c) craftType *c; { struct balance_data b; b.weight = c->emptyWeight + c->maxFuel; b.rm = marker_list[MARKER_MAIN_GEAR].location.point; b.rn = marker_list[MARKER_NOSE_GEAR].location.point; b.cm = GetCellValueDouble (gear_dialog_items, GearcmMax, &c->cmMax); b.cm *= 0.6; b.cn = GetCellValueDouble (gear_dialog_items, GearcnMax, &c->cnMax); b.cn *= 0.6; b.Gm = GetCellValueDouble (gear_dialog_items, GearGm, &c->Gm); b.Gn = GetCellValueDouble (gear_dialog_items, GearGn, &c->Gn); #ifdef notdef printf ("Input:\n"); printf ("nose contact = %lf %lf %lf\n", b.rn.x, b.rn.y, b.rn.z); printf ("main's contact = %lf %lf %lf\n", b.rm.x, b.rm.y, b.rm.z); printf ("Weight = %lf\n", b.weight); #endif balance (&b); #ifdef notdef printf ("\nOutput:\n"); printf ("rm = %lf, %lf, %lf\n", b.rm.x, b.rm.y, b.rm.z); printf ("rn = %lf, %lf, %lf\n", b.rn.x, b.rn.y, b.rn.z); printf ("Km = %lf\n", b.Km); printf ("Kn = %lf\n", b.Kn); printf ("Grounding point (z) = %lf\n", b.Gpz); printf ("\n\"inventory\" form:\n\n"); printf ("\tRm\t\t{%lg, %lg, %lg}\n", b.rm.x, b.rm.y, b.rm.z); printf ("\tRn\t\t{%lg, %lg, %lg}\n", b.rn.x, b.rn.y, b.rn.z); printf ("\tKm\t\t%lg\n", b.Km); printf ("\tKn\t\t%lg\n", b.Kn); printf ("\tGm\t\t%lg\n", b.Gm); printf ("\tGn\t\t%lg\n", b.Gn); printf ("\tCmMax\t\t%lg\n", c->cmMax); printf ("\tCnMax\t\t%lg\n", c->cnMax); printf ("\tGroundingPoint\t{0.0, 0.0, %lg}\n", b.Gpz); #endif c->rm = b.rm; c->rn = b.rn; c->Km = b.Km; c->Kn = b.Kn; c->groundingPoint.x = c->groundingPoint.y = 0.0; c->groundingPoint.z = b.Gpz; SetCellValueDouble (gear_dialog_items, GearKm, c->Km); SetCellValueDouble (gear_dialog_items, GearKn, c->Kn); }