diff --git a/COPYING b/COPYING old mode 100644 new mode 100755 diff --git a/INSTALL b/INSTALL old mode 100644 new mode 100755 diff --git a/JSBSim.dox b/JSBSim.dox old mode 100644 new mode 100755 diff --git a/JSBSim.vcproj b/JSBSim.vcproj old mode 100644 new mode 100755 index 1291330246cde4ed2a626ac5eac4a9afee0fe956..0dd9aa889f5fcb9dc30b66a9b3069ee3863665a9 --- a/JSBSim.vcproj +++ b/JSBSim.vcproj @@ -124,7 +124,7 @@ /> <Tool Name="VCCLCompilerTool" - Optimization="3" + Optimization="2" EnableIntrinsicFunctions="true" FavorSizeOrSpeed="1" WholeProgramOptimization="true" @@ -133,10 +133,11 @@ BasicRuntimeChecks="0" RuntimeLibrary="2" EnableEnhancedInstructionSet="2" + FloatingPointModel="2" UsePrecompiledHeader="0" GenerateXMLDocumentationFiles="false" - WarningLevel="3" - Detect64BitPortabilityProblems="true" + WarningLevel="4" + Detect64BitPortabilityProblems="false" DebugInformationFormat="3" /> <Tool @@ -154,6 +155,7 @@ Version="0.9.13" LinkIncremental="1" AdditionalLibraryDirectories=""C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib"" + GenerateManifest="false" GenerateDebugInformation="false" SubSystem="1" OptimizeReferences="2" @@ -389,6 +391,10 @@ RelativePath=".\src\models\FGModel.h" > </File> + <File + RelativePath=".\src\math\FGModelFunctions.h" + > + </File> <File RelativePath=".\src\models\atmosphere\FGMSIS.h" > @@ -757,6 +763,10 @@ RelativePath=".\src\models\FGModel.cpp" > </File> + <File + RelativePath=".\src\math\FGModelFunctions.cpp" + > + </File> <File RelativePath=".\src\models\atmosphere\FGMSIS.cpp" > diff --git a/JSBSim.xsd b/JSBSim.xsd old mode 100644 new mode 100755 diff --git a/JSBSim.xsl b/JSBSim.xsl old mode 100644 new mode 100755 diff --git a/JSBSimScript.xsd b/JSBSimScript.xsd old mode 100644 new mode 100755 diff --git a/JSBSimScript.xsl b/JSBSimScript.xsl old mode 100644 new mode 100755 diff --git a/JSBSimSystem.xsd b/JSBSimSystem.xsd old mode 100644 new mode 100755 diff --git a/Makefile.am b/Makefile.am index d6fea1dfa14267d8d306f5efc788c5314ed42978..2e45b6e8edb3817699d3418e7d5f44f406f7a378 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ EXTRA_DIST = \ autogen.sh JSBSim.xsd JSBSim.xsl JSBSim.vcproj JSBSim.dox -SUBDIRS = src systems aircraft engine scripts data_output data_plot check_cases scicoslab +SUBDIRS = src systems aircraft engine scripts data_output data_plot check_cases dist-hook: (cd $(top_srcdir)) diff --git a/admin/createfgfs.pl b/admin/createfgfs.pl old mode 100644 new mode 100755 diff --git a/admin/jsb2fg b/admin/jsb2fg old mode 100644 new mode 100755 diff --git a/admin/syncacft b/admin/syncacft old mode 100644 new mode 100755 diff --git a/aircraft/737/cruise_init.xml b/aircraft/737/cruise_init.xml old mode 100644 new mode 100755 diff --git a/aircraft/737/cruise_steady_turn_init.xml b/aircraft/737/cruise_steady_turn_init.xml old mode 100644 new mode 100755 diff --git a/aircraft/737/reset00.xml b/aircraft/737/reset00.xml old mode 100644 new mode 100755 diff --git a/aircraft/B17/B17.xml b/aircraft/B17/B17.xml old mode 100644 new mode 100755 diff --git a/aircraft/B17/reset00.xml b/aircraft/B17/reset00.xml old mode 100644 new mode 100755 diff --git a/aircraft/B747/B747.xml b/aircraft/B747/B747.xml old mode 100644 new mode 100755 diff --git a/aircraft/B747/reset00.xml b/aircraft/B747/reset00.xml old mode 100644 new mode 100755 diff --git a/aircraft/C130/C130.xml b/aircraft/C130/C130.xml old mode 100644 new mode 100755 diff --git a/aircraft/Concorde/Concorde.xml b/aircraft/Concorde/Concorde.xml old mode 100644 new mode 100755 diff --git a/aircraft/EasyStar/Datcom/.gitignore b/aircraft/EasyStar/Datcom/.gitignore deleted file mode 100644 index 3475cc469826f05531fd60b7e8a42f3815b69ad6..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/Datcom/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -*.ac -*.csv -*.lfi -*.xml -*.dat -*.out -*.jiff diff --git a/aircraft/EasyStar/Datcom/EasyStar.dcm b/aircraft/EasyStar/Datcom/EasyStar.dcm deleted file mode 100644 index 9e7df88e1c346bd33e63b8e931a4ed6b337d1567..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/Datcom/EasyStar.dcm +++ /dev/null @@ -1,943 +0,0 @@ -* -* File : EasyStar.dcm -* -* Purpose : This is an input file for the Digital Datcom program. -* -* Author : James Goppert -* jgoppert@users.sourceforge.net -* -* Last update: 6/4/2010 - Initial creation. -* -* Model-Specific notes: -* o The CG locations were based on 1/4 chord. Adjust weight to meet this -* assumption. -* -* General Notes : -* 1. In general, we aren't concerned with anything faster than the -* subsonic speed regime. DATCOM can handle transonic, supersonic, -* and hypersonic, so check the book for more information. -* -* 2. DATCOM pg 47 states : -* -* "In general, the eight flap types defined using SYMFLP -* (variable FTYPE) are assumed to be located on the most -* aft lifting surface, either horizontal tail or wing if -* a horizontal tail is not defined." -* -* We are going to assume that this means that we will have to -* perform a wing-body-vertical_tail analysis in order to get -* the flap effects, then add the horizontal tail in order to -* get it's effects and trim points. The first case is used -* ONLY to get the flap effects. -* -* 3. The page references below are from The USAF Stability and -* Control Digital DATCOM, volume 1, Users Manual, April 1979 -* -* - -************************ -* List of Command Card -************************ -* -* Note : Command cards MUST start in column 1. They may appear in -* any order, with the exception of NEXT CASE. -* -* NAMELIST The contents of each applicatble namelist is dumped for the -* case in the input system of units. (Very useful to see -* input parameter values). -* SAVE Preserve the input data for the case to be used in the following -* cases. This would be useful if multiple or comparison cases -* are built. -* DIM FT Sets the system units of measure. Options are FT, IN, M, CM -* NEXT CASE Terminates the reading of input cards and begins execution of -* the case. Case data are destroyed following execution of a case, -* unless the SAVE card is present. -* TRIM Trim calculations will be performed for each subsonic Mach number -* within the case. A vehicle may be trimmed by deflecting a control -* device on the wing or horizontal tail or by deflecting an -* all-moveable horizontal stabilizer. -* DAMP Provides dynamic-derivative results in addition to the standard -* static-derivative output -* CASEID Provides a case identification that is printed as part of the -* output header. -* DUMP ALL Prints the contents of the named arrays in the foot-pound-second -* system. See Appendix C for list of arrays and their contents. -* DUMP CASE will print all the arrays that are used during case -* execution prior to the conventional output. (Not particularily -* useful, as all data is in nasty arrays) -* DUMP INPT will print dump of all input data blocks used for the case. -* (also not useful) -* DUMP IOM will print all the output arrays for the case. (not useful) -* DUMP ALL will print all program arrays, even if not used for the case. -* (surprisingly, not useful) -* DERIV DEG Defines the output units of measure for the static and dynamic -* stability derivatives, either RAD or DEG. The following parameters -* are affected: CLa, Cma, Cyb, Cnb, Clb, CLq, Cmq, Clp, Cyp, Cnp, -* Cnr, Clr, CLad, CMad. JSBSim XML output is also switched between -* degrees and radians for alpha, beta, etc. -* PART Provides auxiliary and partial outputs at each Mach number in the -* case. These outputs are automatically provided for all cases at -* transonic Mach numbers. -* BUILD This command provides configuration build-up data. Conventional -* static and dynamic stability data are output for a LOT of items. -* PLOT Causes data generated by the program to be written to logical -* unit 13, which can be retained for input to the Plot Module. -* (Looks like it dumps the data arrays out in column format. Not -* too useful). - -DIM IN -DAMP -DERIV DEG -PART -DUMP IOM - -********************** -* Flight Conditions * -********************** -* WT Vehicle Weight -* LOOP Program Looping Control -* 1 = vary altitude and mach together (NOTE: NMACH(must)=NALT) -* 2 = vary Mach, at fixed altitude (NOTE: number of executions= -* NMACH*NALT) -* 3 = vary altitude, at fixed Mach -* NMACH Number of Mach numbers or velocities to be run, max of 20 -* Note: This parameter, along with NALT, may affect the -* proper setting of the LOOP control parameter. -* MACH Array(20) Values of freestream Mach number -* VINF Array(20) Values of freestream speed (unit: l/t) -* NALPHA Number of angles of attack to be run, max of 20 -* ALSCHD Array(20) Values of angles of attack, in ascending order -* RNNUB Array(20) Reynolds number per unit length -* Freestream Reynolds numbers. Each array element must -* correspond to the respective Mach number/freestream -* speed input, use LOOP=1.0 -* NALT Number of atmospheric conditions to be run, max of 20 -* input as either altitude or pressure and temperature -* Note: This parameter, along with NMACH, may affect the -* proper setting of the LOOP control parameter. -* ALT Array(20) Values of geometric altitude -* Number of altitude and values. Note, Atmospheric conditions -* are input either as altitude or pressure and temperature. (MAX 20) -* PINF Array(20) Values of freestream Static Pressure -* TINF Array(20) Values of freestream Temperature -* HYPERS =.true. Hypersonic analysis at all Mach numbers > 1.4 -* STMACH Upper limit of Mach numbers for subsonic analysis -* (0.6<STMACH<0.99), Default to 0.6 if not input. -* TSMACH Lower limit of Mach number for Supersonic analysis -* (1.01<=TSMACH<=1.4) Default to 1.4 -* TR Drag due to lift transition flag, for regression analysis -* of wing-body configuration. -* = 0.0 for no transition (default) -* = 1.0 for transition strips or full scale flight -* GAMMA Flight path angle - - - - $FLTCON WT=2.0, LOOP=1.0, -* around 40 km/h cruise speed - NMACH=1.0, MACH(1)=0.03635, - NALT=1.0, ALT(1)=0.0, - NALPHA=20.0, - ALSCHD(1)= -16.0, -8.0, -6.0, -4.0, -2.0, - 0.0, 2.0, 4.0, 8.0, 9.0, - 10.0, 12.0, 14.0, 16.0, 18.0, - 19.0, 20.0, 21.0, 22.0, 24.0, -* NOTE: a conflict between the units of angle of attacks used - STMACH=0.6, TSMACH=1.4, TR=1.0$ - - - -************************* -* Reference Parameters * pg 29 -************************* -* SREF Reference area value of theoretical wing area used by program -* if not input -* CBARR Longitudinal reference length value of theoritcal wing -* Mean Aerodynamic Chord used by program if not input -* BLREF Lateral reference length value of wing span used by program -* ROUGFC Surface roughness factor, equivalent sand roughness, default -* to 0.16e-3 inches (Natural sheet metal) -* 0.02/0.08E-3 - Polished metal or wood -* 0.16E-3 - Natural sheet metal -* 0.25E-3 - Smooth matte paint, carefully applied -* 0.40E-3 - Standard camouflage paint, average application - -* guess of styrofoam roughness (NOTE:Key in understanding the aerodynamic model) - $OPTINS ROUGFC=0.40E-3$ - - - - - -************************************** -* Group II Synthesis Parameters * pg 33 -************************************** -* -* page 33 -* -* XCG Longitudinal location of cg (moment ref. center) -* ZCG Vertical location of CG relative to reference plane -* XW Longitudinal location of theoretical wing apex (NOTE: where -* leading edge would intersect long axis) -* ZW Vertical location of theoretical wing apex relative to -* reference plane -* ALIW Wing root chord incident angle measured from reference plane -* XH Longitudinal location of theoretical horizontal tail apex. -* If HINAX is input, XH and ZH are evaluated at zero incidence. -* ZH Vertical location of theoretical horizontal tail apex -* relative to reference plane. If HINAX is input, XH and ZH -* are evaluated at zero incidence. -* ALIH Horizontal tail root chord incidence angle measured from -* reference plane -* XV Longitudinal location of theoretical vertical tail apex -* XVF Longitudinal location of theoretical ventral fin apex -* ZV Vertical location of theoretical vertical tail apex -* This kinda makes sense only for twin tails that are canted -* ZVF Vertical location of theoretical ventral fin apex -* This kinda makes sense only for twin tails that are canted -* SCALE Vehicle scale factor (multiplier to input dimensions) -* VERTUP Vertical panel above reference plane (default=true) -* HINAX Longitudinal location of horizontal tail hinge axis. -* Required only for all-moveable horizontal tail trim option. - - - $SYNTHS XCG=11.0, ZCG=0.0, - XW=9.0, ZW=2.0, ALIW=0.0, - XH=31.0, ZH=0.0, ALIH=0.0, - XV=29.5, ZV=0.0, HINAX=32.0, - SCALE=1.0, VERTUP=.TRUE.$ - -********************************** -* Body Configuration Parameters * pg 36 -********************************** -* Here is an error message output by DIGDAT concerning body geometry: -* IN NAMELIST BODY, ONLY THE FOLLOWING COMBINATIONS OF VARIABLES CAN BE USED -* FOR A CIRCULAR BODY, SPECIFY X AND R OR X AND S -* FOR AN ELLIPTICAL BODY, SPECIFY X AND R OR X AND S, AND THE VARIABLE ELLIP -* FOR OTHER BODY SHAPES X, R, S, AND P MUST ALL BE SPECIFIED -* -* NX Number of longitudinal body stations at which data is -* specified, max of 20 -* X Array(20) Longitudinal distance measured from arbitray location -* S Array(20) Cross sectional area at station. See note above. -* P Array(20) Periphery at station Xi. See note above. -* R Array(20) Planform half width at station Xi. See note above. -* ZU Array(20) Z-coordinate at upper body surface at station Xi -* (positive when above centerline) -* [Only required for subsonic asymmetric bodies] -* ZL Array(20) Z-coordinate at lower body surface at station Xi -* (negative when below centerline) -* [Only required for subsonic asymmetric bodies] -* BNOSE Nosecone type 1.0 = conical (rounded), 2.0 = ogive (sharp point) -* [Not required in subsonic speed regime] -* BTAIL Tailcone type 1.0 = conical, 2.0 = ogive, omit for lbt = 0 -* [Not required in subsonic speed regime] -* BLN Length of body nose -* Not required in subsonic speed regime -* BLA Length of cylindrical afterbody segment, =0.0 for nose alone -* or nose-tail configuration -* Not required in subsonic speed regime -* DS Nose bluntness diameter, zero for sharp nosebodies -* [Hypersonic speed regime only] -* ITYPE 1.0 = straight wing, no area rule -* 2.0 = swept wing, no area rule (default) -* 3.0 = swept wing, area rule -* METHOD 1.0 = Use existing methods (default) -* 2.0 = Use Jorgensen method - - $BODY NX=12.0, - X(1) =0.0, 0.5, 2.0, 5.0, 6.0, 8.0, 12.0, 18.0, 19.0, 20.0, 32.0, 33.0, - R(1) =0.0, 0.44, 1.25, 1.63, 1.44, 1.63, 1.38, 1.13, 1.0, 1.0, 0.5, 0.0, - ZU(1)=0.0, 1.5, 2.25, 3.25, 3.25, 3.25, 3.75, 4.63, 0.7, 0.6, 0.5, 0.0, - ZL(1)=0.0, 0.0, -0.5, -1.23, -1.23, -1.8, -1.25, -1.0, -0.7, -0.6, -0.5, 0.0, - ITYPE=1.0, METHOD=1.0$ - - -********************************** -* Wing planform variables pg 37-38 -********************************** -* CHRDR Chord root -* CHRDBP Chord at breakpoint. Not required for straight -* tapered planform. -* CHRDTP Tip chord -* SSPN Semi-span theoretical panel from theoretical root chord -* SSPNE Semi-span exposed panel, See diagram on pg 37. -* SSPNOP Semi-span outboard panel. Not required for straight -* tapered planform. -* SAVSI Inboard panel sweep angle -* SAVSO Outboard panel sweep angle -* CHSTAT Reference chord station for inboard and outboard panel -* sweep angles, fraction of chord -* TWISTA Twist angle, negative leading edge rotated down (from -* exposed root to tip) -* SSPNDD Semi-span of outboard panel with dihedral -* DHDADI Dihedral angle of inboard panel -* DHDADO Dihedral angle of outboard panel. If DHDADI=DHDADO only -* input DHDADI -* TYPE 1.0 - Straight tapered planform -* 2.0 - Double delta planform (aspect ratio <= 3) -* 3.0 - Cranked planform (aspect ratio > 3) -*NOTE: The wave-drag factors for the sharp nose airfoils? - - $WGPLNF CHRDTP=1.0,SSPNE=24.0,SSPNOP=6.0, SSPN=27.0, - CHRDBP=7.0,CHRDR=7.8, SAVSI=6.0,SAVSO=60.0, SSPNDD=4.0, TWISTA=0.0, - CHSTAT=0.0, DHDADI=0.0, DHDADO=20.9, TYPE=1.0$ - -********************************************** -* Wing Sectional Characteristics Parameters * pg 39-40 -********************************************** -* The section aerodynamic characteristics for these surfaces are -* input using either the sectional characteristics namelists WGSCHR, -* HTSCHR, VTSCHR and VFSCHR and/or the NACA control cards. Airfoil -* characteristics are assummed constant for each panel of the planform. -* -* To avoid having to input all the airfoil sectional characteristics, -* you can specify the NACA airfoil designation. Starts in Column 1. -* -* NACA x y zzzzzz -* -* where: -* column 1-4 NACA -* 5 any deliminator -* 6 W, H, V, or F Planform for which the airfoil -* designation applies: Wing, Horizontal -* tail, Vertical tail, or Ventral fin. -* 7 any deliminator -* 8 1,4,5,6,S Type of airfoil section: 1-series, -* 4-digit, 5-digit, 6-series, or Supersonic -* 9 any deliminator -* 10-80 Designation, columns are free format, blanks are ignored -* -* TOVC Maximum airfoil section thickness fraction of chord -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* DELTAY Difference between airfoil ordinates at 6% and 15% chord, -* percent chord (% correct ???) -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* XOVC Chord location of maximum airfoil thickness, fraction of chord -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* CLI Airfoil section design lift coefficient -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* ALPHAI Angle of attack at section design lift coefficient, deg -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* CLALPA Airfoil section lift curve slope dCl/dAlpha, per deg (array 20) -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* CLMAX Airfoil section maximum lift cofficient (array 20) -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* CMO Section zero lift pitching moment coefficient -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* LERI Airfoil leading edge radius, fraction of chord -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* LERO RLE for outboard panel, fraction of chord -* [Required input]. -* Not required for straight tapered planforms. -* CAMBER Cambered airfoil flag flag -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* TOVCO t/c for outboard panel -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* Not required for straight tapered planforms. -* XOVCO (x/c)max for outboard panel -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* Not required for straight tapered planforms. -* CMOT Cmo for outboard panel -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* Not required for straight tapered planforms. -* CLMAXL Airfoil maximum lift coefficient at mach = 0.0 -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* CLAMO Airfoil section lift curve slope at Mach=0.0, per deg -* [Not required for subsonic speed regime. Required input -* for transonic speed regime, user supplied or computed if -* NACA card supplied] -* TCEFF Planform effective thickness ratio, fraction of chord -* [Not required for subsonic speed regime. Required input -* for transonic speed regime, user supplied or computed if -* NACA card supplied] -* KSHARP Wave-drag factor for sharp-nosed airfoil section, not -* input for round-nosed airfoils -* [Not required for subsonic speed regime. Required input -* for transonic speed regime, user supplied or computed if -* NACA card supplied] -* SLOPE Airfoil surface slope at 0,20,40,60,80 and 100% chord, deg. -* Positive when the tangent intersects the chord plane forward -* of the reference chord point -* [Not required for subsonic speed regime. Required input -* for transonic speed regime, user supplied or computed if -* NACA card supplied] -* ARCL Aspect ratio classification (see table 9, pg 41) -* [Optional input] -* XAC Section Aerodynamic Center, fraction of chord -* [Optional input, computed by airfoil section module if airfoil -* defined with NACA card or section coordinates] -* DWASH Subsonic downwash method flag -* = 1.0 use DATCOM method 1 -* = 2.0 use DATCOM method 2 -* = 3.0 use DATCOM method 3 -* Supersonic, use DATCOM method 2 -* [Optional input] -* See figure 9 on page 41. -* YCM Airfoil maximum camber, fraction of chord -* [Required input, user supplied or computed by airfoil -* section module if airfoil defined with NACA card or -* section coordinates] -* CLD Conical camber design lift coefficient for M=1.0 design -* see NACA RM A55G19 (default to 0.0) -* [Required input] -* TYPEIN Type of airfoil section coordinates input for airfoil -* section module -* = 1.0 upper and lower surface coordinates (YUPPER and YLOWER) -* = 2.0 Mean line and thickness distribution (MEAN and THICK) -* [Optional input] -* NPTS Number of section points input, max = 50.0 -* [Optional input] -* XCORD Abscissas of inputs points, TYPEIN=1.0 or 2.0, XCORD(1)=0.0 -* XCORD(NPTS)= 1.0 required. -* [Optional input] -* YUPPER Ordinates of upper surface, TYPEIN=1.0, fraction of chord, and -* requires YUPPER(1)=0.0 and YUPPER(NPTS)=0.0 -* [Optional input] -* YLOWER Ordinates of lower surface, TYPEIN=1.0, fraction of chord, -* and requires YLOWER(1)=0.0 and YLOWER(NPTS)=0.0 -* [Optional input] -* MEAN Ordinates of mean line, TYPEIN=2.0, fraction of chord, and -* requires MEAN(1)=0.0 and MEAN(NPTS)=0.0 -* [Optional input] -* THICK Thickness distribution, TYPEIN=2.0, fraction of chord, and -* requires THICK(1)=0.0 and THICK(NPTS)=0.0 -* [Optional input] -* -* Note : Only one airfoil section can be defined, so we're going to -* with the airfoil at the root. The actual airfoil is a -* 5-series modified (23016-5), but I'm not really sure how -* to get the -5 part in, and what it means, and where the max -* thickness is. The tip is NACA 23012. (shoudl be able to get the the -* thickness and the max thickness derived from the -* - - -NACA W 5 65415 - - - - - -****************************** -* Ground effects parameters -****************************** -* NGH Number of ground heights to be run, maximum of 10. -* GRDHT Values of ground heights. Ground heights equal altitude -* of reference plane relative to ground. Ground effect output -* may be obtained at a maximum of ten different ground heights. -* According to the DATCOM, the ground effects become neglible -* when the ground height exceeds the wing span. Through -* testing, there is a minimal effect up to twice the wing -* span, so to keep our tables smooth, let's make the last -* point 1.5b, and the output adds a point at 2b of 0.0. The -* smallest value should NOT be 0.0, which would be the wing -* sitting on the ground. It should be the height of the wing -* with the aircraft sitting on the ground. -* - -* $GRNDEF NGH=10.0, GRDHT=5.0,10.0,15.0,20.0,25.0,30.0,40.0,50.0,60.0,77.55$ - -SAVE - - -****************************************** -* Symetrical Flap Deflection parameters -****************************************** -* DATCOM pg 47 states : -* -* "In general, the eight flap types defined using SYMFLP -* (variable FTYPE) are assumed to be located on the most -* aft lifting surface, either horizontal tail or wing if -* a horizontal tail is not defined." -* -* FTYPE Flap type -* 1.0 Plain flaps -* 2.0 Single slotted flaps -* 3.0 Fowler flaps -* 4.0 Double slotted flaps -* 5.0 Split flaps -* 6.0 Leading edge flap -* 7.0 Leading edge slats -* 8.0 Krueger -* NDELTA Number of flap or slat deflection angles, max of 9 -* -* DELTA Flap deflection angles measured streamwise -* (NDELTA values in array) -* PHETE Tangent of airfoil trailine edge angle based on ordinates at -* 90 and 99 percent chord -* PHETEP Tangent of airfoil trailing edge angle based on ordinates at -* 95 and 99 percent chord -* CHRDFI Flap chord at inboard end of flap, measured parallel to -* longitudinal axis -* CHRDFO Flap chord at outboard end of flap, measured parallel to -* longitudinal axis -* SPANFI Span location of inboard end of flap, measured perpendicular -* to vertical plane of symmetry -* SPANFO Span location of outboard end of flap, measured perpendicular -* to vertical plane of symmetry -* CPRMEI Total wing chord at inboard end of flap (translating devices -* only) measured parallel to longitudinal axis -* (NDELTA values in array) -* Single-slotted, Fowler, Double-slotted, leading-edge -* slats, Krueger flap, jet flap -* CPRMEO Total wing chord at outboard end of flap (translating devices -* only) measured parallel to longitudinal axis -* (NDELTA values in array) -* Single-slotted, Fowler, Double-slotted, leading-edge -* slats, Krueger flap, jet flap -* CAPINS (double-slotted flaps only) -* CAPOUT (double-slotted flaps only) -* DOSDEF (double-slotted flaps only) -* DOBCIN (double-slotted flaps only) -* DOBCOT (double-slotted flaps only) -* SCLD Increment in section lift coefficient due to -* deflecting flap to angle DELTA[i] (optional) -* (NDELTA values in array) -* SCMD Increment in section pitching moment coefficient due to -* deflecting flap to angle DELTA[i] (optional) -* (NDELTA values in array) -* CB Average chord of the balance (plain flaps only) -* TC Average thickness of the control at hinge line -* (plain flaps only) -* NTYPE Type of nose -* 1.0 Round nose flap -* 2.0 Elliptic nose flap -* 3.0 Sharp nose flap -* JETFLP Type of flap -* 1.0 Pure jet flap -* 2.0 IBF -* 3.0 EBF -* CMU Two-dimensional jet efflux coefficient -* DELJET Jet deflection angle -* (NDELTA values in array) -* EFFJET EBF Effective jet deflection angle -* (NDELTA values in array) - -* no flaps -* $SYMFLP FTYPE=2.0, NDELTA=9.0, -* DELTA(1)=0.0,5.0,10.0,15.0,20.0,25.0,30.0,35.0,40.0, -* PHETE=0.0522, PHETEP=0.0391, -* CHRDFI=2.0, CHRDFO=1.6, -* SPANFI=5.78, SPANFO=15.3, -* CPRMEI(1)=8.1,8.1,8.2,8.2,8.3,8.3,8.3,8.4,8.4, -* CPRMEO(1)=3.7,3.7,3.8,3.8,3.9,3.9,3.9,4.0,4.0, -* NTYPE=2.0$ -* At this point, we are going to terminate the case so that we can get -* the flap effects. We can't save this data, as we are -* also going to do control surfaces on the horizontal tail. - -*CASEID FLAPS: Citation II Model 550 Aircraft -*NEXT CASE - -************************************************************* -* Asymmetrical Control Deflection parameters : Ailerons -************************************************************* -* STYPE Type -* 1.0 Flap spoiler on wing -* 2.0 Plug spoiler on wing -* 3.0 Spoiler-slot-deflection on wing -* 4.0 Plain flap aileron -* 5.0 Differentially deflected all moveable horizontal tail -* NDELTA Number of control deflection angles, required for all controls, -* max of 9 -* DELTAL Defelction angle for left hand plain flap aileron or left -* hand panel all moveable horizontal tail, measured in -* vertical plane of symmetry -* DELTAR Defelction angle for right hand plain flap aileron or right -* hand panel all moveable horizontal tail, measured in -* vertical plane of symmetry -* SPANFI Span location of inboard end of flap or spoiler control, -* measured perpendicular to vertical plane of symmetry -* SPANFO Span location of outboard end of flap or spoiler control, -* measured perpendicular to vertical plane of symmetry -* PHETE Tangent of airfoil trailing edge angle based on ordinates -* at x/c - 0.90 and 0.99 -* CHRDFI Aileron chord at inboard end of plain flap aileron, -* measured parallel to longitudinal axis -* CHRDFO Aileron chord at outboard end of plain flap aileron, -* measured parallel to longitudinal axis -* DELTAD Projected height of deflector, spoiler-slot-deflector -* control, fraction of chord -* DELTAS Projected height of spoiler, flap spoiler, plug spoiler and -* spoiler-slot-deflector control; fraction of chord -* XSOC Distance from wing leading edge to spoiler lip measured -* parallel to streamwise wng chord, flap and plug spoilers, -* fraction of chord -* XSPRME Distance from wing leading edge to spoiler hinge line -* measured parallel to streamwise chord, flap spoiler, -* plug spoiler and spoiler-slot-deflector control, fraction -* of chord -* HSOC Projected height of spoiler measured from and normal to -* airfoil mean line, flap spoiler, plug spoiler and spoiler- -* slot-reflector, fraction of chord - -* no ailerons -* $ASYFLP STYPE=4.0, -* NDELTA=9.0, -* DELTAL(1)=-28.0, -20.0, -10.0, -5.0, 0.0, 5.0, 10.0, 20.0, 28.0, -* DELTAR(1)= 28.0, 20.0, 10.0, 5.0, 0.0, -5.0, -10.0, -20.0, -28.0, -* SPANFI=12.4, SPANFO=18.8, -* PHETE=0.05228, CHRDFI=0.886, CHRDFO=0.886$ -* - -* $ASYFLP STYPE=4.0, NDELTA=9.0, -* DELTAL(1)=-32.0,-20.0,-10.0,-5.0,0.0,5.0,10.0,20.0,32.0, -* DELTAR(1)=32.0,20.0,10.0,5.0,0.0,-5.0,-10.0,-20.0,-32.0, -* SPANFI=15.2, SPANFO=24.0, -* PHETE=0.05228, -* CHRDFI=1.87, CHRDFO=1.2$ - - - -* Terminates the reading of input cards and begins execution of -* the case. Case data are destroyed following execution of a case, -* unless the SAVE card is present. -*CASEID AILERONS: Citation II Model 550 Aircraft -*SAVE -*NEXT CASE - - -************************************************* -* Horizontal Tail Sectional Characteristics pg 39-40 -************************************************* - -NACA H 4 0009 - - -********************************************* -* Horizontal Tail planform variables pg 37-38 -********************************************* -* CHRDTP Tip chord -* SSPNOP Semi-span outboard panel. Not required for straight -* tapered planform. -* SSPNE Semi-span exposed panel -* SSPN Semi-span theoretical panel from theoretical root chord -* CHRDBP Chord at breakpoint -* CHRDR Chord root -* SAVSI Inboard panel sweep angle -* CHSTAT Reference chord station for inboard and outboard panel -* sweep angles, fraction of chord -* TWISTA Twist angle, negative leading edge rotated down (from -* exposed root to tip) -* SSPNDD Semi-span of outboard panel with dihedral -* DHDADI Dihedral angle of inboard panel -* DHDADO Dihedral angle of outboard panel. If DHDADI=DHDADO only -* input DHDADI -* TYPE 1.0 - Straight tapered planform -* 2.0 - Double delta planform (aspect ratio <= 3) -* 3.0 - Cranked planform (aspect ratio > 3) -* SHB Portion of fuselage side area that lies between Mach lines -* originating from leading and trailing edges of horizontal -* tail exposed root chord (array 20). -* Only required for supersonic and hypersonic speed regimes. -* SEXT Portion of extended fueslage side area that lies between -* Mach lines originating from leading and trailing edges of -* horizontal tail exposed root chord (array 20) -* Only required for supersonic and hypersonic speed regimes. -* RLPH Longitudinal distance between CG and centroid of Sh(B) -* positive aft of CG -* Only required for supersonic and hypersonic speed regimes. - - $HTPLNF CHRDTP=1.5, SSPNOP=3.0, SSPNE=8.75, SSPN=9.25, - CHRDBP=3.75, CHRDR=4.0, SAVSI=0.0, SAVSO=49.4, TWISTA=0.0, - CHSTAT=0.0, TYPE=1.0$ - - -****************************************** -* Vertical Tail planform variables pg 37-38 -****************************************** -* CHRDTP Tip chord -* SSPNOP Semi-span outboard panel -* SSPNE Semi-span exposed panel -* SSPN Semi-span theoretical panel from theoretical root chord -* CHRDBP Chord at breakpoint -* CHRDR Chord root -* SAVSI Inboard panel sweep angle -* SAVSO Outboard panel sweep angle -* CHSTAT Reference chord station for inboard and outboard panel -* sweep angles, fraction of chord -* TYPE 1.0 - Straight tapered planform -* 2.0 - Double delta planform (aspect ratio <= 3) -* 3.0 - Cranked planform (aspect ratio > 3) -* SVWB Portion of exposed vertical panel area that lies between -* Mach lines emanating from leading and trailing edges of -* wing exposed root chord (array 20) -* Only required for supersonic and hypersonic speed regimes. -* SVB Area of exposed vertical panel not influenced by wing or -* horizontal tail (array 20) -* Only required for supersonic and hypersonic speed regimes. -* SVHB Portion of exposed vertical panel area that lies between Mach -* lines emanating from leading and and trailing edges of -* horizontal tail exposed root chord (array 20) -* Only required for supersonic and hypersonic speed regimes. - - $VTPLNF CHRDTP=1.0, SSPNE=6.5, SSPN=7.25, - CHRDR=4.63, SAVSI=30.0, CHSTAT=0.0, TYPE=1.0$ - - -****************************************** -* Vertical Fin planform variables pg 37-38 -****************************************** -* CHRDR Chord root -* CHRDBP Chord at breakpoint -* CHRDTP Tip chord -* SSPNOP Semi-span outboard panel -* SSPNE Semi-span exposed panel -* SSPN Semi-span theoretical panel from theoretical root chord -* SAVSI Inboard panel sweep angle -* CHSTAT Reference chord station for inboard and outboard panel -* sweep angles, fraction of chord -* DHDADO Dihedral angle of outboard panel. If DHDADI=DHDADO only -* input DHDADI -* DHDADO Dihedral angle of outboard panel. If DHDADI=DHDADO only -* input DHDADI -* TYPE 1.0 - Straight tapered planform -* 2.0 - Double delta planform (aspect ratio <= 3) -* 3.0 - Cranked planform (aspect ratio > 3) -* SVWB Portion of exposed vertical panel area that lies between -* Mach lines emanating from leading and trailing edges of -* wing exposed root chord (array 20) -* Only required for supersonic and hypersonic speed regimes. -* SVB Area of exposed vertical panel not influenced by wing or -* horizontal tail (array 20) -* Only required for supersonic and hypersonic speed regimes. -* SVHB Portion of exposed vertical panel area that lies between Mach -* lines emanating from leading and and trailing edges of -* horizontal tail exposed root chord (array 20) -* Only required for supersonic and hypersonic speed regimes. - -* no vertical fin -* $VFPLNF CHRDTP=1.0, SSPNOP=2.5, SSPNE=6.5, SSPN=7.25, -* CHRDBP=3.0, CHRDR=4.63, SAVSI=30.0, SAVSO=70.0, -* CHSTAT=0.0, TYPE=1.0$ - - -*********************************** -* Elevator Deflection parameters -*********************************** -* FTYPE Flap type -* 1.0 Plain flaps -* 2.0 Single slotted flaps -* 3.0 Fowler flaps -* 4.0 Double slotted flaps -* 5.0 Split flaps -* 6.0 Leading edge flap -* 7.0 Leading edge slats -* 8.0 Krueger -* NDELTA Number of flap or slat deflection angles, max of 9 -* DELTA Flap deflection angles measured streamwise -* (NDELTA values in array) -* PHETE Tangent of airfoil trailine edge angle based on ordinates at -* 90 and 99 percent chord -* PHETEP Tangent of airfoil trailing edge angle based on ordinates at -* 95 and 99 percent chord -* CHRDFI Flap chord at inboard end of flap, measured parallel to -* longitudinal axis -* CHRDFO Flap chord at outboard end of flap, measured parallel to -* longitudinal axis -* SPANFI Span location of inboard end of flap, measured perpendicular -* to vertical plane of symmetry -* SPANFO Span location of outboard end of flap, measured perpendicular -* to vertical plane of symmetry -* CPRMEI Total wing chord at inboard end of flap (translating devices -* only) measured parallel to longitudinal axis -* (NDELTA values in array) -* Single-slotted, Fowler, Double-slotted, leading-edge -* slats, Krueger flap, jet flap -* CPRMEO Total wing chord at outboard end of flap (translating devices -* only) measured parallel to longitudinal axis -* (NDELTA values in array) -* Single-slotted, Fowler, Double-slotted, leading-edge -* slats, Krueger flap, jet flap -* CAPINS (double-slotted flaps only) (NDELTA values in array) -* CAPOUT (double-slotted flaps only) (NDELTA values in array) -* DOSDEF (double-slotted flaps only) (NDELTA values in array) -* DOBCIN (double-slotted flaps only) -* DOBCOT (double-slotted flaps only) -* SCLD Increment in section lift coefficient due to -* deflecting flap to angle DELTA[i] (optional) -* (NDELTA values in array) -* SCMD Increment in section pitching moment coefficient due to -* deflecting flap to angle DELTA[i] (optional) -* (NDELTA values in array) -* CB Average chord of the balance (plain flaps only) -* TC Average thickness of the control at hinge line -* (plain flaps only) -* NTYPE Type of nose -* 1.0 Round nose flap -* 2.0 Elliptic nose flap -* 3.0 Sharp nose flap -* JETFLP Type of flap -* 1.0 Pure jet flap -* 2.0 IBF -* 3.0 EBF -* CMU Two-dimensional jet efflux coefficient -* DELJET Jet deflection angle -* (NDELTA values in array) -* EFFJET EBF Effective jet deflection angle -* (NDELTA values in array) - - $SYMFLP FTYPE=1.0, - NDELTA=9.0, DELTA(1)=-20.0,-15.0,-10.0,-5.0,0.0,5.0,10.0,13.0,16.0, - PHETE=0.0522, PHETEP=0.0523, - CHRDFI=1.25, CHRDFO=1.00, - SPANFI=0.0, SPANFO=6.25, - CB=0.84, TC=0.3, NTYPE=1.0$ - - - -************************************** -* Vertical Tail Sectional Characteristics pg 39-40 -************************************** -* Same build up as wing, if you'd like to use that instead. - -NACA V 4 0009 - - - -********************************************** -* Ventral Fin Sectional Characteristics pg 39-40 -********************************************** - -* no vertical fin -*NACA F 4 0012 - - - -************************************ -* Twin Vertical Panel parameters -************************************ -* BVP Vertical panel span above lifting surface -* BV Vertical panel span -* BDV Fuselage depth at quarter chord point of vertical -* panel mean aerodynamic chord -* BH Distance between vertical panels -* SV Plan form area of one vertical panel -* VPHITE Total training edge angle of vertical panel airfoil section -* VLP Distance parallel to long. axis bewteen the C.G. and the -* quarter chord point of the MAC of the panel, positive -* if aft of C.G. -* ZP Distance in the Z direction between the C.G. and the MAC -* of the panel, positive for panel above C.G. - - - -***************************** -* Control Tabs parameters DATCOM User's manual, pg 68/69 -***************************** -* TTYPE Type -* 1.0 Tab Control -* 2.0 Trim Tab -* 3.0 Both -* CFITC Control tab inboard chord -* CFOTC Control tab outboard chord -* BITC Control tab inboard span location -* BOTC Control tab outboard span location -* CFITT Trim tab inboard chord -* CFOTT Trim tab outboard chord -* BITT Trim tab inboard span location -* BOTT Trim tab outboard span location -* B1 Ch(delta) for control tab -* B2 Ch(delta) for trim tab -* B3 Ch(alpha) for control tab -* B4 Ch(alpha) for trim tab -* D1 see table 11, pg 70-71 -* D2 see table 11, pg 70-71 -* D3 see table 11, pg 70-71 -* GCMAX Maximum Stick gearing -* KS Tab spring effectiveness -* RL Aerodynamic boost link ratio (RL > 0). -* To input RL infinity, set RL < 0 -* BGR Control tab gear ratio -* DELR -DELTAtc(max)/DELTAc(max) for a maximum control deflection -* The value of DELR is positive because DELTAtc(max) and -* DELTAc(max) will have opposite signs. -* When R(L) 0, DELR = 1.0 - -********************************* -* Propeller Power -********************************* -* AITELP Angle of incidence of engine thrust axis -* NENGSP Number of engines -* THSTCP Thrust coefficient -* PHALOC Axial location of propeller hub -* PHVLOC Vertical location of prepller hub -* PRPRAD Propeller radius -* BWAPR3 Blade width at 0.3 propeller radius -* BWAPR6 Blade width at 0.6 propeller radius -* BWAPR9 Blade width at 0.9 propeller radius -* NOPBPE Number of blades per engine -* BAPR75 Blade angle at 0.75 propller radius -* YP Lateral location of engine -* CROT True if counter rotating, false if non counter rotating - $PROPWR AIETLP=-5.19, NENGSP=1.0, THSTCP=0.0, - PHALOC=19.0, PHVLOC=4.0, PRPRAD=2.69, - BWAPR3=0.5, BWAPR6=0.38, BWAPR9=0.25, BAPR75=26.7, - NOPBPE=1.0, YP=0.0, CROT=.FALSE.$ - -********************************* -* Jet Power Effects parameters pg 51 -********************************* -* -* IMPORTANT NOTE: The effects of POWER are including in the DATCOM -* output file (Citation.out in this case), at the bottom where the -* total aircraft parameters are listed (CD, CL, CM, etc.). For the -* Datcom+ output files, the power effects are removed and presented -* (if not now, they will be some day) in a separate table. That way, -* you can interpolate to get power settings between zero (off) and -* whatever the maximum that you specify here. -* -* AIETLJ Angle of incidence of engine thrust line, deg -* AMBSTP Ambient static pressure -* AMBTMP Ambient temperature, deg -* JEALOC Axial location of jet engine exit, feet -* JEANGL Jet exit angle -* JELLOC Lateral location of jet engine, ft -* JERAD Radius of jet exit -* JESTMP Jet exit static temperature -* JETOTP Jet exit total pressure -* JEVELO Jet exit velocity -* JEVLOC Vertical location of jet engine exit, feet -* JIALOC Axial location of jet engine inlet, feet -* JINLTA Jet engine inlet area, square feet -* NENGSJ Number of engines (1 or 2) -* THSTCJ Thrust coefficient 2T/(PV^2*Sref) -* Set this to 0 to keep power effects out of coefficients. - -* doesn't have a jet -* $JETPWR NENGSJ=2.0, AIETLJ=2.0, THSTCJ=0.0, -* JIALOC=25.8, JELLOC=4.33, JEVLOC=5.625, -* JEALOC=33.3, JINLTA=2.243, -* AMBTMP=59.7, AMBSTP=2116.8, JERAD=0.755$ - - -CASEID TOTAL: Multiplex Easy Star diff --git a/aircraft/EasyStar/Datcom/Makefile.am b/aircraft/EasyStar/Datcom/Makefile.am deleted file mode 100644 index 493469ee6df9031e693f7cf8de70613fa1690453..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/Datcom/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -aircraft_EasyStar_Datcomdir = ${pkgdatadir}/aircraft/EasyStar/Datcom -aircraft_EasyStar_Datcom_DATA = \ - EasyStar.dcm -EXTRA_DIST=$(aircraft_EasyStar_Datcom_data) diff --git a/aircraft/EasyStar/EasyStar-datcom-set.xml b/aircraft/EasyStar/EasyStar-datcom-set.xml deleted file mode 100644 index 32d5786963b136c4906138d591cc308362bb1aa0..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/EasyStar-datcom-set.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0"?> -<PropertyList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../XMLSchemas/PropertyList.xsd"> - <sim> - <author>James Goppert</author> - <description>Multiplex Easy Star (DATCOM)</description> - <aircraft-version>0.0.0</aircraft-version> - <status>early-production</status> - <startup> - <splash-title>Multiplex Easy Star</splash-title> - </startup> - <model> - <path>Aircraft/EasyStar/Models/EasyStar-model.xml</path> - </model> - <sound> - <path>Aircraft/EasyStar/EasyStar-sound.xml</path> - </sound> - <flight-model>jsb</flight-model> - <aero>EasyStar-datcom</aero> - </sim> -</PropertyList> diff --git a/aircraft/EasyStar/EasyStar-datcom.xml b/aircraft/EasyStar/EasyStar-datcom.xml deleted file mode 100644 index 3f91cb2a3b077f87c3d7b94c6fd26b46aea03468..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/EasyStar-datcom.xml +++ /dev/null @@ -1,1372 +0,0 @@ -<?xml version="1.0"?> -<!-- - This is the JSBSim config file for a PA34-200T SenecaII. - The aerodynamics sections was generated by datcom using - as much real input as available. - - Changes from datcom.xml - - - function attribute NAME must be lowercase - - missing function Delta_lift_due_to_flap_deflection in axis LIFT - - missing function Lift_due_to_Elevator_Deflection in axis LIFT ---> -<?xml-stylesheet href="JSBSim.xsl" type="application/xml"?> -<fdm_config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="file:/home/torsten/FlightGear/Aircraft/SenecaII/JSBSim.xsd" - name="EasyStar-datcom" version="2.0" release="BETA"> - - <fileheader> - <author>James Goppert</author> - <filecreationdate>2010-6-3</filecreationdate> - <description>Multiplex Easy Star (DATCOM)</description> - <reference title="Multiplex Easy Star (DATCOM)"/> - </fileheader> - - <!-- ********************************************************************** - METRICS - ********************************************************************** --> - <metrics> - <wingarea unit="FT2"> 2.2792 </wingarea> - <wingspan unit="FT"> 4.5000 </wingspan> - <chord unit="FT"> .5606 </chord> - <htailarea unit="FT2"> .4457 </htailarea> - <htailarm unit="FT"> .4280 </htailarm> - <vtailarea unit="FT2"> .1606 </vtailarea> - <vtailarm unit="FT"> .7127 </vtailarm> - <!-- - the aerodynamic reference point, common point for - aerodynamic forces (lift and drag) - --> - <location name="AERORP" unit="IN"> - <x> 4.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <!-- the eyepoint of the pilot (left or right eye?) --> - <location name="EYEPOINT" unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <!-- the visual reference point of the 3d model --> - <location name="VRP" unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - </metrics> - - <!-- ********************************************************************** - MASS_BALANCE - ********************************************************************** --> - <mass_balance> - <ixx unit="SLUG*FT2"> .1 </ixx> - <iyy unit="SLUG*FT2"> .1 </iyy> - <izz unit="SLUG*FT2"> .1 </izz> - <ixz unit="SLUG*FT2"> 0 </ixz> - <emptywt unit="LBS"> 2.0 </emptywt> - <!-- the center of gravity --> - <location name="CG" unit="IN"> - <x> 3.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <!--<pointmass name="PAYLOAD">--> - <!--<weight unit="LBS"> 0.0 </weight>--> - <!--<location name="POINTMASS" unit="IN">--> - <!--<x> 39.3 </x>--> - <!--<y> 0 </y>--> - <!--<z> 35.3 </z>--> - <!--</location>--> - <!--</pointmass>--> - </mass_balance> - <!-- ********************************************************************** - UNDERCARRIAGE - ********************************************************************** --> - <ground_reactions> - <contact type="STRUCTURE" name="TAIL_SKID"> - <location unit="IN"> - <x> 27.0 </x> - <y> 0 </y> - <z>-2.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="NOSE"> - <location unit="IN"> - <x> -5.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="BOTTOM_CANOPY"> - <location unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> -3.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - - <contact type="STRUCTURE" name="LEFT_WING"> - <location unit="IN"> - <x> -3.0 </x> - <y> -27.5 </y> - <z> 1.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="RIGHT_WING"> - <location unit="IN"> - <x> -3.0 </x> - <y> 27.5 </y> - <z> 1.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="VERTICAL_TAIL"> - <location unit="IN"> - <x> 27.0 </x> - <y> 0.0 </y> - <z> 6.5 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="CABIN_TOP"> - <location unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 2.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - </ground_reactions> - <!-- ********************************************************************** - PROPULSION - ********************************************************************** --> - <propulsion> - <engine file="HB2815-2000"> - <location unit="IN"> - <x> 10.0 </x> - <y> 0 </y> - <z> 3.0 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> -5 </pitch> - <yaw> 0 </yaw> - </orient> - <feed>0</feed> - <thruster file="apc6x4"> - <location unit="IN"> - <x> 10.0 </x> - <y> 0 </y> - <z> 3.0 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> -5.0 </pitch> - <yaw> 0.0 </yaw> - </orient> - <p_factor>1.0</p_factor> - </thruster> - </engine> - <!--throws warning if tank not included, no real purpose--> - <tank type="FUEL"> <!-- Tank number 0 --> - <location unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <capacity unit="LBS"> 0.0001 </capacity> - <contents unit="LBS"> 0 </contents> - </tank> - </propulsion> - <!-- ********************************************************************** - FLIGHT CONTROLS - ********************************************************************** --> - <flight_control name="EasyStar"> - <!-- - Elevator - --> - <channel name="Pitch"> - <summer name="Pitch Trim Sum"> - <input>fcs/elevator-cmd-norm</input> - <input>fcs/pitch-trim-cmd-norm</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - <output>fcs/elevator-pos-norm</output> - </summer> - <aerosurface_scale name="Elevator Control"> - <input>fcs/pitch-trim-sum</input> - <gain>0.01745</gain> - <range> - <min>-28</min> - <max>23</max> - </range> - <output>fcs/elevator-pos-rad</output> - </aerosurface_scale> - </channel> - <!-- - Rudder - --> - <channel name="Yaw"> - <summer name="Yaw Trim Sum"> - <input>fcs/rudder-cmd-norm</input> - <input>fcs/yaw-trim-cmd-norm</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - </summer> - <!--<pure_gain name="Aileron Crossfeed">--> - <!--<input>fcs/aileron-cmd-norm</input>--> - <!--<gain>-1</gain>--> - <!--<output>fcs/rudder-pos-norm</output>--> - <!--</pure_gain>--> - <summer name="Yaw Mix"> - <input>fcs/yaw-trim-sum</input> - <!--<input>fcs/aileron-crossfeed</input>--> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - </summer> - <aerosurface_scale name="Rudder Control"> - <input>fcs/yaw-mix</input> - <gain>0.01745</gain> - <range> - <min>-27</min> - <max>27</max> - </range> - <output>fcs/rudder-pos-rad</output> - </aerosurface_scale> - </channel> - <!-- - Throttle (linear vs rpm approx.) - --> - <channel name="Throttle"> - <fcs_function name="fcs/rpm-scaled-throttle"> - <function> - <pow> - <property>fcs/throttle-cmd-norm</property> - <value>3</value> - </pow> - </function> - </fcs_function> - <aerosurface_scale name="Throttle Control"> - <input>fcs/rpm-scaled-throttle</input> - <range> - <min>-1</min> - <max>1</max> - </range> - <output>fcs/throttle-pos-norm</output> - </aerosurface_scale> - </channel> - - </flight_control> - -<!-- - - - ****************** IMPORTANT NOTICES ********************** - - This is an alpha version release of the DATCOM+ program for - JSBSIM. Nothing, and I do mean NOTHING, as been checked to - verify that the parameters, units, sign conventions, or - basically anything else is correct. Your mileage may vary. - - *********************************************************** - - This file was generated by the USAF Digital DATCOM program. - This file is considered an intermediary file in the - DATCOM/JSBSim process. This file may be overwritten without - warning, so any changes that you make in here may be lost. - - If you intend to use this file as it is and modify it, make - sure that you take the necessary precautions to prevent it - from being overwritten, like renaming it. - - - *********************************************************** - - - DISCLAIMER REQUIRED BY HQ USAF FOR PUBLIC RELEASE APPROVAL - - THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION - IS RELEASED "AS IS". THE U.S. GOVERNMENT MAKES NO - WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, CONCERNING - THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION, - INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - IN NO EVENT WILL THE U.S. GOVERNMENT BE LIABLE FOR ANY - DAMAGES, INCLUDING LOST PROFITS, LOST SAVINGS OR OTHER - INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE - USE, OR INABILITY TO USE, THIS SOFTWARE OR ANY - ACCOMPANYING DOCUMENTATION, EVEN IF INFORMED IN ADVANCE - OF THE POSSIBILITY OF SUCH DAMAGES. - - - *********************************************************** ---> - - - - - - - -<!-- ********************************************************************** - AERODYNAMICS - ********************************************************************** ---> - - - <aerodynamics> - - <alphalimits unit="DEG"> - <min> -16.00 </min> - <max> 24.00 </max> - </alphalimits> - - - - - <!-- ************************* - Sign Conventions - ************************* - - Control displacements - Stick FWD + / Aft - - Stick Left + / Right - - Wheel CCW + / CW - - Pedal Left + / Right - - Elevator trim Nose Up + / Nose down - - - Surfaces - Elevator TED + / TEU - - R Ail TED + / TEU - - L Ail TED + / TEU - - Rudder TEL + / TER - - - F&M, Accel, Rates, Displacements - Pitch Up + / Down - - Roll Rgt + / Left - - Yaw Rgt + / Left - - - Other - Alpha Up + / Down - - Beta Wind in right ear + / Wind in left ear - - Slip Ball right of center + / left of center - - --> - - - - - <!-- ************************************** - ASSUMPTIONS AND LIMITATIONS - - There is no interaction between deflected surfaces modeled - so there is no change in elevator effects with the flaps - deflected, for example. - - Terms known to be missing from DATCOM: - Power effects - Ground effects - Cyr, CyDr, Cyda, ClDr, Cndr - - ************************************** - --> - - - <!-- - The following ground effect tables are NOT generated - by DATCOM, but provide representative effects. - These terms are not currently used in this model. - --> - - - <function name="aero/function/ground-effect-factor-lift"> - <description>Change in lift due to ground effect factor</description> - <product> - <table> - <independentVar lookup="row">aero/h_b-mac-ft</independentVar> - <tableData> - 0.0 1.203 - 0.1 1.127 - 0.15 1.090 - 0.2 1.073 - 0.3 1.046 - 0.4 1.055 - 0.5 1.019 - 0.6 1.013 - 0.7 1.008 - 0.8 1.006 - 0.9 1.003 - 1.0 1.002 - 1.1 1.0 - </tableData> - </table> - </product> - </function> - - <function name="aero/function/ground-effect-factor-drag"> - <description>Change in drag due to ground effect</description> - <product> - <table> - <independentVar lookup="row">aero/h_b-mac-ft</independentVar> - <tableData> - 0.0 0.480 - 0.1 0.515 - 0.15 0.629 - 0.2 0.709 - 0.3 0.815 - 0.4 0.882 - 0.5 0.928 - 0.6 0.962 - 0.7 0.988 - 0.8 1.0 - 0.9 1.0 - 1.0 1.0 - 1.1 1.0 - </tableData> - </table> - </product> - </function> - - - - - -<!-- ********************************************************************** --> - - - <axis name="LIFT"> - - - <function name="aero/coefficient/CLwbh"> - <description> - Lift due to alpha - Increase in CL decreases Period and damping,Dutch Roll damping - CL is low for landing - </description> - <product> - <property>aero/function/ground-effect-factor-lift</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -1.216 - -8.000 -.4490 - -6.000 -.2713 - -4.000 -.9559E-01 - -2.000 .7950E-01 - .000 .2620 - 2.000 .4513 - 4.000 .6466 - 8.000 1.053 - 9.000 1.157 - 10.00 1.248 - 12.00 1.403 - 14.00 1.529 - 16.00 1.620 - 18.00 1.660 - 19.00 1.659 - 20.00 1.545 - 21.00 1.332 - 22.00 1.097 - 24.00 .8071 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CLq"> - <description> - Basic Lift Coefficient due to pitch rate(per degree) - </description> - <product> - <property>velocities/q-aero-rad_sec</property> - <value>57.29577951</value> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/ci2vel</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .1523 - -8.000 .1523 - -6.000 .1523 - -4.000 .1523 - -2.000 .1523 - .000 .1523 - 2.000 .1523 - 4.000 .1523 - 8.000 .1523 - 9.000 .1523 - 10.00 .1523 - 12.00 .1523 - 14.00 .1523 - 16.00 .1523 - 18.00 .1523 - 19.00 .1523 - 20.00 .1523 - 21.00 .1523 - 22.00 .1523 - 24.00 .1523 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CLad"> - <description> - Basic Lift Coefficient due to AOA rate(per degree) - Important contributor to Short-Period damping - For low Cla, aircraft must land at high alpha - </description> - <product> - <property>aero/alphadot-deg_sec</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/ci2vel</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .3510E-01 - -8.000 .3144E-01 - -6.000 .3313E-01 - -4.000 .3315E-01 - -2.000 .3284E-01 - .000 .3296E-01 - 2.000 .3277E-01 - 4.000 .3230E-01 - 8.000 .2898E-01 - 9.000 .2806E-01 - 10.00 .2572E-01 - 12.00 .1946E-01 - 14.00 .1550E-01 - 16.00 .1016E-01 - 18.00 -.2053E-02 - 19.00 -.1167E-01 - 20.00 -.3353E-01 - 21.00 -.5670E-01 - 22.00 -.5279E-01 - 24.00 -.3183E-01 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CLDe"> - <description> - Lift Coefficient due to Elevator Deflection - Positive surface deflection is trailing edge down - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 -.6476E-01 - -15.00 -.5856E-01 - -10.00 -.4002E-01 - -5.000 -.2001E-01 - .000 .4002E-04 - 5.000 .2001E-01 - 10.00 .4002E-01 - 13.00 .5157E-01 - 16.00 .6162E-01 - </tableData> - </table> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="DRAG"> - - - <function name="aero/coefficient/CD"> - <description> - Basic Drag Coefficient - Sense: Always positive - Main contributor to Phugoid damping: Greater Cd, Better damping - </description> - <product> - <property>aero/function/ground-effect-factor-lift</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .1667 - -8.000 .4475E-01 - -6.000 .3290E-01 - -4.000 .2639E-01 - -2.000 .2554E-01 - .000 .3065E-01 - 2.000 .4245E-01 - 4.000 .6156E-01 - 8.000 .1232 - 9.000 .1436 - 10.00 .1636 - 12.00 .2014 - 14.00 .2355 - 16.00 .2637 - 18.00 .2813 - 19.00 .2851 - 20.00 .2611 - 21.00 .2185 - 22.00 .1816 - 24.00 .1539 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CdDe"> - <description> - Drag Coefficient due to Elevator Deflection - Positive surface deflection is trailing edge down - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <independentVar lookup="column">fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 -15.00 -10.00 -5.000 .000 5.000 10.00 13.00 16.00 - -16.00 .5945E-02 .5210E-02 .3237E-02 .1444E-02 -.2539E-05 -.1095E-02 -.1842E-02 -.2114E-02 -.2256E-02 - -8.000 .3346E-02 .2862E-02 .1633E-02 .6419E-03 -.9344E-06 -.2931E-03 -.2373E-03 -.4624E-04 .2148E-03 - -6.000 .2700E-02 .2278E-02 .1234E-02 .4425E-03 -.5355E-06 -.9363E-04 .1616E-03 .4677E-03 .8290E-03 - -4.000 .2027E-02 .1671E-02 .8186E-03 .2349E-03 -.1202E-06 .1140E-03 .5768E-03 .1003E-02 .1468E-02 - -2.000 .1338E-02 .1048E-02 .3930E-03 .2209E-04 .3054E-06 .3268E-03 .1002E-02 .1551E-02 .2124E-02 - .000 .6550E-03 .4315E-03 -.2832E-04 -.1886E-03 .7268E-06 .5375E-03 .1424E-02 .2094E-02 .2773E-02 - 2.000 -.3080E-04 -.1879E-03 -.4516E-03 -.4002E-03 .1150E-05 .7491E-03 .1847E-02 .2640E-02 .3425E-02 - 4.000 -.7194E-03 -.8099E-03 -.8767E-03 -.6128E-03 .1575E-05 .9616E-03 .2272E-02 .3187E-02 .4079E-02 - 8.000 -.2133E-02 -.2087E-02 -.1749E-02 -.1049E-02 .2448E-05 .1398E-02 .3145E-02 .4312E-02 .5423E-02 - 9.000 -.2513E-02 -.2429E-02 -.1984E-02 -.1166E-02 .2683E-05 .1515E-02 .3379E-02 .4614E-02 .5784E-02 - 10.00 -.2896E-02 -.2776E-02 -.2220E-02 -.1285E-02 .2920E-05 .1633E-02 .3616E-02 .4919E-02 .6148E-02 - 12.00 -.3763E-02 -.3559E-02 -.2755E-02 -.1552E-02 .3453E-05 .1901E-02 .4151E-02 .5608E-02 .6972E-02 - 14.00 -.4698E-02 -.4403E-02 -.3333E-02 -.1841E-02 .4031E-05 .2190E-02 .4728E-02 .6352E-02 .7861E-02 - 16.00 -.5692E-02 -.5301E-02 -.3946E-02 -.2148E-02 .4650E-05 .2496E-02 .5342E-02 .7143E-02 .8806E-02 - 18.00 -.6799E-02 -.6301E-02 -.4629E-02 -.2489E-02 .5328E-05 .2838E-02 .6025E-02 .8023E-02 .9858E-02 - 19.00 -.7457E-02 -.6895E-02 -.5036E-02 -.2692E-02 .5729E-05 .3041E-02 .6431E-02 .8547E-02 .1048E-01 - 20.00 -.8200E-02 -.7566E-02 -.5494E-02 -.2921E-02 .6195E-05 .3270E-02 .6889E-02 .9137E-02 .1119E-01 - 21.00 -.9209E-02 -.8478E-02 -.6117E-02 -.3233E-02 .6812E-05 .3582E-02 .7512E-02 .9940E-02 .1215E-01 - 22.00 -.1032E-01 -.9484E-02 -.6805E-02 -.3577E-02 .7499E-05 .3926E-02 .8201E-02 .1083E-01 .1321E-01 - 24.00 -.1205E-01 -.1104E-01 -.7870E-02 -.4109E-02 .8561E-05 .4458E-02 .9265E-02 .1220E-01 .1485E-01 - </tableData> - </table> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="SIDE"> - - - <function name="aero/coefficient/Cyb"> - <description> - Side Force coefficient due to Sideslip(per degree) - Contributes to damping of Dutch Roll mode - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/beta-deg</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.3898E-02 - -8.000 -.3898E-02 - -6.000 -.3898E-02 - -4.000 -.3898E-02 - -2.000 -.3898E-02 - .000 -.3898E-02 - 2.000 -.3898E-02 - 4.000 -.3898E-02 - 8.000 -.3898E-02 - 9.000 -.3898E-02 - 10.00 -.3898E-02 - 12.00 -.3898E-02 - 14.00 -.3898E-02 - 16.00 -.3898E-02 - 18.00 -.3898E-02 - 19.00 -.3898E-02 - 20.00 -.3898E-02 - 21.00 -.3898E-02 - 22.00 -.3898E-02 - 24.00 -.3898E-02 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cyp"> - <description> - Side Force Coefficient due to Roll Rate(per degree) - </description> - <product> - <property>velocities/p-aero-rad_sec</property> - <value>57.29577951</value> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/bi2vel</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.6446E-03 - -8.000 -.1072E-02 - -6.000 -.1171E-02 - -4.000 -.1268E-02 - -2.000 -.1364E-02 - .000 -.1460E-02 - 2.000 -.1555E-02 - 4.000 -.1651E-02 - 8.000 -.1855E-02 - 9.000 -.1955E-02 - 10.00 -.2099E-02 - 12.00 -.2372E-02 - 14.00 -.2653E-02 - 16.00 -.3034E-02 - 18.00 -.3638E-02 - 19.00 -.1454E-01 - 20.00 -.5140E-03 - 21.00 -.1285E-02 - 22.00 -.1322E-02 - 24.00 -.1076E-02 - </tableData> - </table> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/Cyr"> - <description> - Side Force due to Yaw Rate(DATCOM does not calculate) - Effect is small - </description> - <product> - <property>velocities/r-aero-rad_sec</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/bi2vel</property> - <value> .000 </value> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/CyDr"> - <description> - Side Force due to rudder(DATCOM does not calculate) - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>fcs/rudder-pos-deg</property> - <value> .000 </value> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/CyDa"> - <description> - Side Force due to aileron(DATCOM does not calculate) - Usually neglected - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>fcs/left-aileron-pos-deg</property> - <value> .000 </value> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="ROLL"> - - - <function name="aero/coefficient/Clb"> - <description> - Roll Moment coefficient due to Beta(per degree) - Decrease of Clb to small negative value improves Dutch Roll Damping - High Positive value leads to excessive spiral instability - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/beta-deg</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.1224E-02 - -8.000 -.1221E-02 - -6.000 -.1219E-02 - -4.000 -.1216E-02 - -2.000 -.1212E-02 - .000 -.1208E-02 - 2.000 -.1206E-02 - 4.000 -.1204E-02 - 8.000 -.1203E-02 - 9.000 -.1204E-02 - 10.00 -.1202E-02 - 12.00 -.1194E-02 - 14.00 -.1181E-02 - 16.00 -.1162E-02 - 18.00 -.1134E-02 - 19.00 -.1116E-02 - 20.00 -.1082E-02 - 21.00 -.1034E-02 - 22.00 -.9825E-03 - 24.00 -.9008E-03 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Clp"> - <description> - Roll Moment coefficient due to roll rate(per degree) - Clp alone determines damping-in-roll characteristics - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/p-aero-rad_sec</property> - <!--Manually increased roll damping, problem with datcom?--> - <value>-0.5</value> - <!--<table>--> - <!--<independentVar lookup="row">aero/alpha-deg</independentVar>--> - <!--<tableData>--> - <!---16.00 -.7650E-02--> - <!---8.000 -.7063E-02--> - <!---6.000 -.6859E-02--> - <!---4.000 -.6653E-02--> - <!---2.000 -.6738E-02--> - <!--.000 -.7039E-02--> - <!--2.000 -.7303E-02--> - <!--4.000 -.7498E-02--> - <!--8.000 -.7737E-02--> - <!--9.000 -.7239E-02--> - <!--10.00 -.6298E-02--> - <!--12.00 -.4816E-02--> - <!--14.00 -.3420E-02--> - <!--16.00 -.1548E-02--> - <!--18.00 .8581E-03--> - <!--19.00 .5957E-02--> - <!--20.00 .1465E-01--> - <!--21.00 .1964E-01--> - <!--22.00 .1776E-01--> - <!--24.00 .7247E-02--> - <!--</tableData>--> - <!--</table>--> - </product> - </function> - - <function name="aero/coefficient/Clr"> - <description> - Roll Moment coefficient due to yaw rate(per degree) - Considerable effect on Spiral mode. Large - positive values leads to strong sprial instability. - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/r-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.3497E-02 - -8.000 -.1073E-02 - -6.000 -.4976E-03 - -4.000 .5472E-04 - -2.000 .5948E-03 - .000 .1162E-02 - 2.000 .1754E-02 - 4.000 .2366E-02 - 8.000 .3626E-02 - 9.000 .3944E-02 - 10.00 .4217E-02 - 12.00 .4651E-02 - 14.00 .4975E-02 - 16.00 .5166E-02 - 18.00 .5164E-02 - 19.00 .5079E-02 - 20.00 .4606E-02 - 21.00 .3766E-02 - 22.00 .2861E-02 - 24.00 .1748E-02 - </tableData> - </table> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/ClDr"> - <description> - Roll moment due to rudder(DATCOM does not calculate) - Usually insignificant in dynamic stability considerations - but is used in autopilot work - </description> - <product> - <property>metrics/bw-ft</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>fcs/rudder-pos-deg</property> - <value> .000 </value> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="PITCH"> - - - <function name="aero/coefficient/Cm_basic"> - <description> - Basic_Pitch_moment_coefficient - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .6261 - -8.000 .2937 - -6.000 .2325 - -4.000 .1590 - -2.000 .7771E-01 - .000 -.5162E-02 - 2.000 -.9019E-01 - 4.000 -.1784 - 8.000 -.3681 - 9.000 -.4190 - 10.00 -.4685 - 12.00 -.5701 - 14.00 -.6714 - 16.00 -.7712 - 18.00 .000 - 19.00 .000 - 20.00 .000 - 21.00 .000 - 22.00 .000 - 24.00 .000 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cmq"> - <description> - Pitch moment coefficient due to pitch rate(per degree) - Pitch Damping Derivative - Very important to Short Period damping of oscillations - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <property>aero/ci2vel</property> - <property>velocities/q-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.2485 - -8.000 -.2485 - -6.000 -.2485 - -4.000 -.2485 - -2.000 -.2485 - .000 -.2485 - 2.000 -.2485 - 4.000 -.2485 - 8.000 -.2485 - 9.000 -.2485 - 10.00 -.2485 - 12.00 -.2485 - 14.00 -.2485 - 16.00 -.2485 - 18.00 -.2485 - 19.00 -.2485 - 20.00 -.2485 - 21.00 -.2485 - 22.00 -.2485 - 24.00 -.2485 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cmadot"> - <description> - Pitch moment coefficient due to AOA rate(per degree) - Negitive Cmad increase Short Period damping - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <property>aero/ci2vel</property> - <property>aero/alphadot-deg_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.1061 - -8.000 -.9502E-01 - -6.000 -.1001 - -4.000 -.1002 - -2.000 -.9926E-01 - .000 -.9960E-01 - 2.000 -.9904E-01 - 4.000 -.9762E-01 - 8.000 -.8757E-01 - 9.000 -.8480E-01 - 10.00 -.7772E-01 - 12.00 -.5882E-01 - 14.00 -.4683E-01 - 16.00 -.3071E-01 - 18.00 .6206E-02 - 19.00 .3526E-01 - 20.00 .1013 - 21.00 .1714 - 22.00 .1595 - 24.00 .9619E-01 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CmDe"> - <description> - Pitch moment coefficient due to elevator deflection - Positive surface deflection is trailing edge down - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <table> - <independentVar lookup="row">fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 .2086 - -15.00 .1871 - -10.00 .1282 - -5.000 .6409E-01 - .000 -.1282E-03 - 5.000 -.6409E-01 - 10.00 -.1282 - 13.00 -.1648 - 16.00 -.1970 - </tableData> - </table> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="YAW"> - - - <function name="aero/coefficient/Cnb"> - <description> - Yaw moment coefficient due to sideslip(per degree) - Determines Dutch Roll and Spiral characteristics - Prevents side-slip and yawing moments - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/beta-deg</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .6403E-03 - -8.000 .6403E-03 - -6.000 .6403E-03 - -4.000 .6403E-03 - -2.000 .6403E-03 - .000 .6403E-03 - 2.000 .6403E-03 - 4.000 .6403E-03 - 8.000 .6403E-03 - 9.000 .6403E-03 - 10.00 .6403E-03 - 12.00 .6403E-03 - 14.00 .6403E-03 - 16.00 .6403E-03 - 18.00 .6403E-03 - 19.00 .6403E-03 - 20.00 .6403E-03 - 21.00 .6403E-03 - 22.00 .6403E-03 - 24.00 .6403E-03 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cnp"> - <description> - Yaw moment coefficient due to roll rate(per degree) - Reduces Dutch Roll damping - positive value desireable - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/p-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .2909E-03 - -8.000 .1580E-03 - -6.000 .1150E-03 - -4.000 .5960E-04 - -2.000 .8267E-06 - .000 -.4457E-04 - 2.000 -.7403E-04 - 4.000 -.9603E-04 - 8.000 -.1448E-03 - 9.000 -.2952E-03 - 10.00 -.5744E-03 - 12.00 -.1081E-02 - 14.00 -.1590E-02 - 16.00 -.2209E-02 - 18.00 -.2839E-02 - 19.00 -.1963E-02 - 20.00 -.6663E-02 - 21.00 -.6409E-02 - 22.00 -.4810E-02 - 24.00 -.2047E-02 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cnr"> - <description> - Yaw Moment coefficient due to yaw rate(per degree) - Main contributor to damping of Dutch Roll - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/r-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.8275E-03 - -8.000 -.7745E-03 - -6.000 -.7758E-03 - -4.000 -.7821E-03 - -2.000 -.7927E-03 - .000 -.8079E-03 - 2.000 -.8285E-03 - 4.000 -.8551E-03 - 8.000 -.9275E-03 - 9.000 -.9496E-03 - 10.00 -.9698E-03 - 12.00 -.1004E-02 - 14.00 -.1030E-02 - 16.00 -.1043E-02 - 18.00 -.1037E-02 - 19.00 -.1026E-02 - 20.00 -.9793E-03 - 21.00 -.9093E-03 - 22.00 -.8479E-03 - 24.00 -.7868E-03 - </tableData> - </table> - </product> - </function> - - - <!-- ****************************************************** - CnDr is not calculated by DATCOM+, but a default value - is supplied - ******************************************************--> - - <function name="aero/coefficient/CnDr"> - <description> - Yaw Coefficient due to rudder(DATCOM does not calculate) - High value for controllablity, low value - for good dynamic stability - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>fcs/rudder-pos-deg</property> - <value> -.1047E-02</value> - </product> - </function> - - - </axis> - - - - -<!-- ********************************************************************** --> - - - <function name="aero/elev_hinge_moment_ft_lbs"> - <description> - Elevator hinge moment in ft-lbs - HM = q * S * Cbar * ( Ch0 + Cha*alpha + Chd*delta ) - Positive causes trailing edge down movement - Ch0 is used to artifically trim HM to zero - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <value> .4492E-01</value> <!-- surface area of elevator --> - <value> .9414E-01</value> <!-- MAC of elevator --> - <sum> - <!-- - <property>aero/Ch0_elev</property> - --> - <product> - <property>aero/alpha-deg</property> - <table> <!-- Ch-alpha --> - <independentVar lookup="row"> - aero/alpha-deg</independentVar> - <tableData> - -16.00 .2169E-02 - -8.000 .2169E-02 - -6.000 .2169E-02 - -4.000 .2169E-02 - -2.000 .2169E-02 - .000 .2169E-02 - 2.000 .2169E-02 - 4.000 .2169E-02 - 8.000 .2169E-02 - 9.000 .2169E-02 - 10.00 .1730E-01 - 12.00 .1723E-01 - 14.00 .1723E-01 - 16.00 .1723E-01 - 18.00 .1723E-01 - 19.00 .1723E-01 - 20.00 .1723E-01 - 21.00 .1723E-01 - 22.00 .1724E-01 - 24.00 .1723E-01 - </tableData> - </table> - </product> - <product> - <property>fcs/elevator-pos-deg</property> - <table> <!-- Ch-delta elevator --> - <independentVar lookup="row"> - fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 .1730E-01 - -15.00 .1723E-01 - -10.00 .1723E-01 - -5.000 .1723E-01 - .000 .1723E-01 - 5.000 .1723E-01 - 10.00 .1723E-01 - 13.00 .1723E-01 - 16.00 .1724E-01 - </tableData> - </table> - </product> - </sum> - </product> - </function> - - </aerodynamics> -</fdm_config> diff --git a/aircraft/EasyStar/EasyStar-set.xml b/aircraft/EasyStar/EasyStar-set.xml deleted file mode 100644 index 5d4be3ebe4f7fb4577d3f93793c9052b2d7ec2d4..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/EasyStar-set.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0"?> -<PropertyList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../XMLSchemas/PropertyList.xsd"> - <sim> - <author>James Goppert</author> - <description>Multiplex Easy Star</description> - <aircraft-version>0.0.0</aircraft-version> - <status>early-production</status> - <startup> - <splash-title>Multiplex Easy Star</splash-title> - </startup> - <model> - <path>Aircraft/EasyStar/Models/EasyStar-model.xml</path> - </model> - <sound> - <path>Aircraft/EasyStar/EasyStar-sound.xml</path> - </sound> - <flight-model>jsb</flight-model> - <aero>EasyStar</aero> - </sim> -</PropertyList> diff --git a/aircraft/EasyStar/EasyStar-sound.xml b/aircraft/EasyStar/EasyStar-sound.xml deleted file mode 100644 index c9c9ea46d1f5e1367cdb7c4cb23e758a93829c3e..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/EasyStar-sound.xml +++ /dev/null @@ -1,146 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<PropertyList> - <fx> - <!--<crank>--> - <!--<name>engstart</name>--> - <!--<path>Sounds/engstart.wav</path>--> - <!--<property>/engines/engine[0]/cranking</property>--> - <!--<position>--> - <!--<x>-2.0</x>--> - <!--<y>0.0</y>--> - <!--<z>-2.0</z>--> - <!--</position>--> - <!--<volume>--> - <!--<offset>0.4</offset>--> - <!--</volume>--> - <!--</crank>--> - <!--<crank>--> - <!--<name>crank</name>--> - <!--<mode>looped</mode>--> - <!--<path>Sounds/cranking.wav</path>--> - <!--<condition>--> - <!--<property>/engines/engine[0]/cranking</property>--> - <!--<not>--> - <!--<property>/engines/engine[0]/running</property>--> - <!--</not>--> - <!--</condition>--> - <!--<position>--> - <!--<x>-2.0</x>--> - <!--<y>0.0</y>--> - <!--<z>-2.0</z>--> - <!--</position>--> - <!--<volume>--> - <!--<offset>0.5</offset>--> - <!--</volume>--> - <!--</crank>--> - <!--<crank>--> - <!--<name>cough</name>--> - <!--<path>Sounds/coughing.wav</path>--> - <!--<property>/engines/engine[0]/running</property>--> - <!--<position>--> - <!--<x>-2.0</x>--> - <!--<y>0.0</y>--> - <!--<z>-2.0</z>--> - <!--</position>--> - <!--<volume>--> - <!--<offset>0.3</offset>--> - <!--</volume>--> - <!--</crank>--> - <engine> - <name>engine</name> - <mode>looped</mode> - <path>Sounds/wasp.wav</path> - <property>/engines/engine[0]/running</property> - <position> - <x>-2.0</x> - <y>0.0</y> - <z>-2.0</z> - </position> - <volume> - <property>/engines/engine[0]/mp-osi</property> - <factor>0.009</factor> - <min>0.15</min> - <max>0.6</max> - <offset>0.15</offset> - </volume> - <pitch> - <property>/engines/engine[0]/rpm</property> - <factor>0.0004</factor> - <min>0.1</min> - <max>2.0</max> - <offset>0.3</offset> - </pitch> - </engine> - - <squeal> - <name>squeal</name> - <path>Sounds/squeal.wav</path> - <condition> - <or> - <property>/gear/gear[0]/wow</property> - <property>/gear/gear[1]/wow</property> - <property>/gear/gear[2]/wow</property> - </or> - </condition> - <volume> - <property>/velocities/speed-down-fps</property> - <factor>0.05</factor> - </volume> - <volume> - <property>/velocities/airspeed-kt</property> - <factor>0.01</factor> - </volume> - <volume> - <internal>dt_stop</internal> - <factor>0.05</factor> - <max>1.0</max> - </volume> - <pitch> - <property>/velocities/airspeed-kt</property> - <factor>0.0025</factor> - <offset>1.2</offset> - </pitch> - </squeal> - <wind> - <name>wind</name> - <mode>looped</mode> - <path>Sounds/wind.wav</path> - <property>/velocities/airspeed-kt</property> - <volume> - <property>/position/altitude-ft</property> - <factor>-0.000015</factor> - <offset>1.0</offset> - <min>0.1</min> - <max>1.0</max> - </volume> - <volume> - <property>/velocities/airspeed-kt</property> - <factor>0.0015</factor> - <min>0.03</min> - <max>0.25</max> - </volume> - <pitch> - <property>/velocities/airspeed-kt</property> - <factor>0.01</factor> - <offset>1.25</offset> - </pitch> - </wind> - <stall> - <name>stall</name> - <path>Sounds/stall.wav</path> - <property>/sim/alarms/stall-warning</property> - <volume> - <property>/velocities/airspeed-kt</property> - <min>30.0</min> - </volume> - <reference-dist>10.0</reference-dist> - <max-dist>20.0</max-dist> - </stall> - <!-- no binding yet? - <click> - <name>click</name> - <path>Sounds/click.wav</path> - </click> ---> - </fx> -</PropertyList> diff --git a/aircraft/EasyStar/EasyStar-windtunnel-set.xml b/aircraft/EasyStar/EasyStar-windtunnel-set.xml deleted file mode 100644 index 2be996c8c5338f99d3d377e5263abb5121c97475..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/EasyStar-windtunnel-set.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0"?> -<PropertyList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../XMLSchemas/PropertyList.xsd"> - <sim> - <author>James Goppert</author> - <description>Multiplex Easy Star (wind tunnel)</description> - <aircraft-version>0.0.0</aircraft-version> - <status>early-production</status> - <startup> - <splash-title>Multiplex Easy Star</splash-title> - </startup> - <model> - <path>Aircraft/EasyStar/Models/EasyStar-model.xml</path> - </model> - <sound> - <path>Aircraft/EasyStar/EasyStar-sound.xml</path> - </sound> - <flight-model>jsb</flight-model> - <aero>EasyStar-windtunnel</aero> - </sim> -</PropertyList> diff --git a/aircraft/EasyStar/EasyStar-windtunnel.xml b/aircraft/EasyStar/EasyStar-windtunnel.xml deleted file mode 100644 index e4e281625d3d50c203b61696b2e9be394c277b6f..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/EasyStar-windtunnel.xml +++ /dev/null @@ -1,1366 +0,0 @@ -<?xml version="1.0"?> -<!-- - This is the JSBSim config file for a PA34-200T SenecaII. - The aerodynamics sections was generated by datcom using - as much real input as available. - - Changes from datcom.xml - - - function attribute NAME must be lowercase - - missing function Delta_lift_due_to_flap_deflection in axis LIFT - - missing function Lift_due_to_Elevator_Deflection in axis LIFT ---> -<?xml-stylesheet href="JSBSim.xsl" type="application/xml"?> -<fdm_config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="file:/home/torsten/FlightGear/Aircraft/SenecaII/JSBSim.xsd" - name="EasyStar-windtunnel" version="2.0" release="BETA"> - - <fileheader> - <author>James Goppert</author> - <filecreationdate>2010-6-3</filecreationdate> - <description>Multiplex Easy Star (wind tunnel)</description> - <reference title="Multiplex Easy Star (wind tunnel)"/> - </fileheader> - - <!-- ********************************************************************** - METRICS - ********************************************************************** --> - <metrics> - <wingarea unit="FT2"> 2.2792 </wingarea> - <wingspan unit="FT"> 4.5000 </wingspan> - <chord unit="FT"> .5606 </chord> - <htailarea unit="FT2"> .4457 </htailarea> - <htailarm unit="FT"> .4280 </htailarm> - <vtailarea unit="FT2"> .1606 </vtailarea> - <vtailarm unit="FT"> .7127 </vtailarm> - <!-- - the aerodynamic reference point, common point for - aerodynamic forces (lift and drag) - --> - <location name="AERORP" unit="IN"> - <x> 4.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <!-- the eyepoint of the pilot (left or right eye?) --> - <location name="EYEPOINT" unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <!-- the visual reference point of the 3d model --> - <location name="VRP" unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - </metrics> - - <!-- ********************************************************************** - MASS_BALANCE - ********************************************************************** --> - <mass_balance> - <ixx unit="SLUG*FT2"> .1 </ixx> - <iyy unit="SLUG*FT2"> .1 </iyy> - <izz unit="SLUG*FT2"> .1 </izz> - <ixz unit="SLUG*FT2"> 0 </ixz> - <emptywt unit="LBS"> 2.0 </emptywt> - <!-- the center of gravity --> - <location name="CG" unit="IN"> - <x> 3.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <!--<pointmass name="PAYLOAD">--> - <!--<weight unit="LBS"> 0.0 </weight>--> - <!--<location name="POINTMASS" unit="IN">--> - <!--<x> 39.3 </x>--> - <!--<y> 0 </y>--> - <!--<z> 35.3 </z>--> - <!--</location>--> - <!--</pointmass>--> - </mass_balance> - <!-- ********************************************************************** - UNDERCARRIAGE - ********************************************************************** --> - <ground_reactions> - <contact type="STRUCTURE" name="TAIL_SKID"> - <location unit="IN"> - <x> 27.0 </x> - <y> 0 </y> - <z>-2.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="NOSE"> - <location unit="IN"> - <x> -5.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="BOTTOM_CANOPY"> - <location unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> -3.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - - <contact type="STRUCTURE" name="LEFT_WING"> - <location unit="IN"> - <x> -3.0 </x> - <y> -27.5 </y> - <z> 1.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="RIGHT_WING"> - <location unit="IN"> - <x> -3.0 </x> - <y> 27.5 </y> - <z> 1.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="VERTICAL_TAIL"> - <location unit="IN"> - <x> 27.0 </x> - <y> 0.0 </y> - <z> 6.5 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="CABIN_TOP"> - <location unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 2.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - </ground_reactions> - <!-- ********************************************************************** - PROPULSION - ********************************************************************** --> - <propulsion> - <engine file="HB2815-2000"> - <location unit="IN"> - <x> 10.0 </x> - <y> 0 </y> - <z> 3.0 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> -5 </pitch> - <yaw> 0 </yaw> - </orient> - <feed>0</feed> - <thruster file="apc6x4"> - <location unit="IN"> - <x> 10.0 </x> - <y> 0 </y> - <z> 3.0 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> -5.0 </pitch> - <yaw> 0.0 </yaw> - </orient> - <p_factor>1.0</p_factor> - </thruster> - </engine> - <!--throws warning if tank not included, no real purpose--> - <tank type="FUEL"> <!-- Tank number 0 --> - <location unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <capacity unit="LBS"> 0.0001 </capacity> - <contents unit="LBS"> 0 </contents> - </tank> - </propulsion> - <!-- ********************************************************************** - FLIGHT CONTROLS - ********************************************************************** --> - <flight_control name="EasyStar"> - <!-- - Elevator - --> - <channel name="Pitch"> - <summer name="Pitch Trim Sum"> - <input>fcs/elevator-cmd-norm</input> - <input>fcs/pitch-trim-cmd-norm</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - <output>fcs/elevator-pos-norm</output> - </summer> - <aerosurface_scale name="Elevator Control"> - <input>fcs/pitch-trim-sum</input> - <gain>0.01745</gain> - <range> - <min>-28</min> - <max>23</max> - </range> - <output>fcs/elevator-pos-rad</output> - </aerosurface_scale> - </channel> - <!-- - Rudder - --> - <channel name="Yaw"> - <summer name="Yaw Trim Sum"> - <input>fcs/rudder-cmd-norm</input> - <input>fcs/yaw-trim-cmd-norm</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - </summer> - <!--<pure_gain name="Aileron Crossfeed">--> - <!--<input>fcs/aileron-cmd-norm</input>--> - <!--<gain>-1</gain>--> - <!--<output>fcs/rudder-pos-norm</output>--> - <!--</pure_gain>--> - <summer name="Yaw Mix"> - <input>fcs/yaw-trim-sum</input> - <!--<input>fcs/aileron-crossfeed</input>--> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - </summer> - <aerosurface_scale name="Rudder Control"> - <input>fcs/yaw-mix</input> - <gain>0.01745</gain> - <range> - <min>-27</min> - <max>27</max> - </range> - <output>fcs/rudder-pos-rad</output> - </aerosurface_scale> - </channel> - <!-- - Throttle (linear vs rpm approx.) - --> - <channel name="Throttle"> - <fcs_function name="fcs/rpm-scaled-throttle"> - <function> - <pow> - <property>fcs/throttle-cmd-norm</property> - <value>3</value> - </pow> - </function> - </fcs_function> - <aerosurface_scale name="Throttle Control"> - <input>fcs/rpm-scaled-throttle</input> - <range> - <min>-1</min> - <max>1</max> - </range> - <output>fcs/throttle-pos-norm</output> - </aerosurface_scale> - </channel> - - </flight_control> - -<!-- - - - ****************** IMPORTANT NOTICES ********************** - - This is an alpha version release of the DATCOM+ program for - JSBSIM. Nothing, and I do mean NOTHING, as been checked to - verify that the parameters, units, sign conventions, or - basically anything else is correct. Your mileage may vary. - - *********************************************************** - - This file was generated by the USAF Digital DATCOM program. - This file is considered an intermediary file in the - DATCOM/JSBSim process. This file may be overwritten without - warning, so any changes that you make in here may be lost. - - If you intend to use this file as it is and modify it, make - sure that you take the necessary precautions to prevent it - from being overwritten, like renaming it. - - - *********************************************************** - - - DISCLAIMER REQUIRED BY HQ USAF FOR PUBLIC RELEASE APPROVAL - - THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION - IS RELEASED "AS IS". THE U.S. GOVERNMENT MAKES NO - WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, CONCERNING - THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION, - INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - IN NO EVENT WILL THE U.S. GOVERNMENT BE LIABLE FOR ANY - DAMAGES, INCLUDING LOST PROFITS, LOST SAVINGS OR OTHER - INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE - USE, OR INABILITY TO USE, THIS SOFTWARE OR ANY - ACCOMPANYING DOCUMENTATION, EVEN IF INFORMED IN ADVANCE - OF THE POSSIBILITY OF SUCH DAMAGES. - - - *********************************************************** ---> - - - - - - - -<!-- ********************************************************************** - AERODYNAMICS - ********************************************************************** ---> - - - <aerodynamics> - - <alphalimits unit="DEG"> - <min> -16.00 </min> - <max> 24.00 </max> - </alphalimits> - - - - - <!-- ************************* - Sign Conventions - ************************* - - Control displacements - Stick FWD + / Aft - - Stick Left + / Right - - Wheel CCW + / CW - - Pedal Left + / Right - - Elevator trim Nose Up + / Nose down - - - Surfaces - Elevator TED + / TEU - - R Ail TED + / TEU - - L Ail TED + / TEU - - Rudder TEL + / TER - - - F&M, Accel, Rates, Displacements - Pitch Up + / Down - - Roll Rgt + / Left - - Yaw Rgt + / Left - - - Other - Alpha Up + / Down - - Beta Wind in right ear + / Wind in left ear - - Slip Ball right of center + / left of center - - --> - - - - - <!-- ************************************** - ASSUMPTIONS AND LIMITATIONS - - There is no interaction between deflected surfaces modeled - so there is no change in elevator effects with the flaps - deflected, for example. - - Terms known to be missing from DATCOM: - Power effects - Ground effects - Cyr, CyDr, Cyda, ClDr, Cndr - - ************************************** - --> - - - <!-- - The following ground effect tables are NOT generated - by DATCOM, but provide representative effects. - These terms are not currently used in this model. - --> - - - <function name="aero/function/ground-effect-factor-lift"> - <description>Change in lift due to ground effect factor</description> - <product> - <table> - <independentVar lookup="row">aero/h_b-mac-ft</independentVar> - <tableData> - 0.0 1.203 - 0.1 1.127 - 0.15 1.090 - 0.2 1.073 - 0.3 1.046 - 0.4 1.055 - 0.5 1.019 - 0.6 1.013 - 0.7 1.008 - 0.8 1.006 - 0.9 1.003 - 1.0 1.002 - 1.1 1.0 - </tableData> - </table> - </product> - </function> - - <function name="aero/function/ground-effect-factor-drag"> - <description>Change in drag due to ground effect</description> - <product> - <table> - <independentVar lookup="row">aero/h_b-mac-ft</independentVar> - <tableData> - 0.0 0.480 - 0.1 0.515 - 0.15 0.629 - 0.2 0.709 - 0.3 0.815 - 0.4 0.882 - 0.5 0.928 - 0.6 0.962 - 0.7 0.988 - 0.8 1.0 - 0.9 1.0 - 1.0 1.0 - 1.1 1.0 - </tableData> - </table> - </product> - </function> - - - - - -<!-- ********************************************************************** --> - - - <axis name="LIFT"> - - - <function name="aero/coefficient/CLwbh"> - <description> - Lift due to alpha - Increase in CL decreases Period and damping,Dutch Roll damping - CL is low for landing - </description> - <product> - <property>aero/function/ground-effect-factor-lift</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -8.00 -0.06335 - -6.00 0.038907 - -4.00 0.206593 - -2.00 0.345895 - 0.00 0.457604 - 2.00 0.590396 - 4.00 0.716654 - 6.00 0.881424 - 8.00 0.979728 - 10.00 1.086794 - 11.00 1.132822 - 12.00 1.181349 - 13.00 1.193517 - 14.00 1.204571 - 15.00 1.21972 - 16.00 1.216158 - 17.00 1.155675 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CLq"> - <description> - Basic Lift Coefficient due to pitch rate(per degree) - </description> - <product> - <property>velocities/q-aero-rad_sec</property> - <value>57.29577951</value> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/ci2vel</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .1523 - -8.000 .1523 - -6.000 .1523 - -4.000 .1523 - -2.000 .1523 - .000 .1523 - 2.000 .1523 - 4.000 .1523 - 8.000 .1523 - 9.000 .1523 - 10.00 .1523 - 12.00 .1523 - 14.00 .1523 - 16.00 .1523 - 18.00 .1523 - 19.00 .1523 - 20.00 .1523 - 21.00 .1523 - 22.00 .1523 - 24.00 .1523 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CLad"> - <description> - Basic Lift Coefficient due to AOA rate(per degree) - Important contributor to Short-Period damping - For low Cla, aircraft must land at high alpha - </description> - <product> - <property>aero/alphadot-deg_sec</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/ci2vel</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - <!---16.00 .3510E-01--> - <!---8.000 .3144E-01--> - <!---6.000 .3313E-01--> - <!---4.000 .3315E-01--> - <!---2.000 .3284E-01--> - <!--.000 .3296E-01--> - <!--2.000 .3277E-01--> - <!--4.000 .3230E-01--> - <!--8.000 .2898E-01--> - <!--9.000 .2806E-01--> - <!--10.00 .2572E-01--> - <!--12.00 .1946E-01--> - <!--14.00 .1550E-01--> - <!--16.00 .1016E-01--> - <!--18.00 -.2053E-02--> - <!--19.00 -.1167E-01--> - <!--20.00 -.3353E-01--> - <!--21.00 -.5670E-01--> - <!--22.00 -.5279E-01--> - <!--24.00 -.3183E-01--> - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CLDe"> - <description> - Lift Coefficient due to Elevator Deflection - Positive surface deflection is trailing edge down - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 -.6476E-01 - -15.00 -.5856E-01 - -10.00 -.4002E-01 - -5.000 -.2001E-01 - .000 .4002E-04 - 5.000 .2001E-01 - 10.00 .4002E-01 - 13.00 .5157E-01 - 16.00 .6162E-01 - </tableData> - </table> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="DRAG"> - - - <function name="aero/coefficient/CD"> - <description> - Basic Drag Coefficient - Sense: Always positive - Main contributor to Phugoid damping: Greater Cd, Better damping - </description> - <product> - <property>aero/function/ground-effect-factor-lift</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -8.00 0.054935 - -6.00 0.054319 - -4.00 0.049043 - -2.00 0.054276 - 0.00 0.058332 - 2.00 0.053311 - 4.00 0.058928 - 6.00 0.068195 - 8.00 0.083696 - 10.00 0.090816 - 11.00 0.105498 - 12.00 0.123163 - 13.00 0.125782 - 14.00 0.141154 - 15.00 0.147641 - 16.00 0.174355 - 17.00 0.207037 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CdDe"> - <description> - Drag Coefficient due to Elevator Deflection - Positive surface deflection is trailing edge down - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <independentVar lookup="column">fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 -15.00 -10.00 -5.000 .000 5.000 10.00 13.00 16.00 - -16.00 .5945E-02 .5210E-02 .3237E-02 .1444E-02 -.2539E-05 -.1095E-02 -.1842E-02 -.2114E-02 -.2256E-02 - -8.000 .3346E-02 .2862E-02 .1633E-02 .6419E-03 -.9344E-06 -.2931E-03 -.2373E-03 -.4624E-04 .2148E-03 - -6.000 .2700E-02 .2278E-02 .1234E-02 .4425E-03 -.5355E-06 -.9363E-04 .1616E-03 .4677E-03 .8290E-03 - -4.000 .2027E-02 .1671E-02 .8186E-03 .2349E-03 -.1202E-06 .1140E-03 .5768E-03 .1003E-02 .1468E-02 - -2.000 .1338E-02 .1048E-02 .3930E-03 .2209E-04 .3054E-06 .3268E-03 .1002E-02 .1551E-02 .2124E-02 - .000 .6550E-03 .4315E-03 -.2832E-04 -.1886E-03 .7268E-06 .5375E-03 .1424E-02 .2094E-02 .2773E-02 - 2.000 -.3080E-04 -.1879E-03 -.4516E-03 -.4002E-03 .1150E-05 .7491E-03 .1847E-02 .2640E-02 .3425E-02 - 4.000 -.7194E-03 -.8099E-03 -.8767E-03 -.6128E-03 .1575E-05 .9616E-03 .2272E-02 .3187E-02 .4079E-02 - 8.000 -.2133E-02 -.2087E-02 -.1749E-02 -.1049E-02 .2448E-05 .1398E-02 .3145E-02 .4312E-02 .5423E-02 - 9.000 -.2513E-02 -.2429E-02 -.1984E-02 -.1166E-02 .2683E-05 .1515E-02 .3379E-02 .4614E-02 .5784E-02 - 10.00 -.2896E-02 -.2776E-02 -.2220E-02 -.1285E-02 .2920E-05 .1633E-02 .3616E-02 .4919E-02 .6148E-02 - 12.00 -.3763E-02 -.3559E-02 -.2755E-02 -.1552E-02 .3453E-05 .1901E-02 .4151E-02 .5608E-02 .6972E-02 - 14.00 -.4698E-02 -.4403E-02 -.3333E-02 -.1841E-02 .4031E-05 .2190E-02 .4728E-02 .6352E-02 .7861E-02 - 16.00 -.5692E-02 -.5301E-02 -.3946E-02 -.2148E-02 .4650E-05 .2496E-02 .5342E-02 .7143E-02 .8806E-02 - 18.00 -.6799E-02 -.6301E-02 -.4629E-02 -.2489E-02 .5328E-05 .2838E-02 .6025E-02 .8023E-02 .9858E-02 - 19.00 -.7457E-02 -.6895E-02 -.5036E-02 -.2692E-02 .5729E-05 .3041E-02 .6431E-02 .8547E-02 .1048E-01 - 20.00 -.8200E-02 -.7566E-02 -.5494E-02 -.2921E-02 .6195E-05 .3270E-02 .6889E-02 .9137E-02 .1119E-01 - 21.00 -.9209E-02 -.8478E-02 -.6117E-02 -.3233E-02 .6812E-05 .3582E-02 .7512E-02 .9940E-02 .1215E-01 - 22.00 -.1032E-01 -.9484E-02 -.6805E-02 -.3577E-02 .7499E-05 .3926E-02 .8201E-02 .1083E-01 .1321E-01 - 24.00 -.1205E-01 -.1104E-01 -.7870E-02 -.4109E-02 .8561E-05 .4458E-02 .9265E-02 .1220E-01 .1485E-01 - </tableData> - </table> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="SIDE"> - - - <function name="aero/coefficient/Cyb"> - <description> - Side Force coefficient due to Sideslip(per degree) - Contributes to damping of Dutch Roll mode - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/beta-deg</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.3898E-02 - -8.000 -.3898E-02 - -6.000 -.3898E-02 - -4.000 -.3898E-02 - -2.000 -.3898E-02 - .000 -.3898E-02 - 2.000 -.3898E-02 - 4.000 -.3898E-02 - 8.000 -.3898E-02 - 9.000 -.3898E-02 - 10.00 -.3898E-02 - 12.00 -.3898E-02 - 14.00 -.3898E-02 - 16.00 -.3898E-02 - 18.00 -.3898E-02 - 19.00 -.3898E-02 - 20.00 -.3898E-02 - 21.00 -.3898E-02 - 22.00 -.3898E-02 - 24.00 -.3898E-02 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cyp"> - <description> - Side Force Coefficient due to Roll Rate(per degree) - </description> - <product> - <property>velocities/p-aero-rad_sec</property> - <value>57.29577951</value> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/bi2vel</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.6446E-03 - -8.000 -.1072E-02 - -6.000 -.1171E-02 - -4.000 -.1268E-02 - -2.000 -.1364E-02 - .000 -.1460E-02 - 2.000 -.1555E-02 - 4.000 -.1651E-02 - 8.000 -.1855E-02 - 9.000 -.1955E-02 - 10.00 -.2099E-02 - 12.00 -.2372E-02 - 14.00 -.2653E-02 - 16.00 -.3034E-02 - 18.00 -.3638E-02 - 19.00 -.1454E-01 - 20.00 -.5140E-03 - 21.00 -.1285E-02 - 22.00 -.1322E-02 - 24.00 -.1076E-02 - </tableData> - </table> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/Cyr"> - <description> - Side Force due to Yaw Rate(DATCOM does not calculate) - Effect is small - </description> - <product> - <property>velocities/r-aero-rad_sec</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/bi2vel</property> - <value> .000 </value> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/CyDr"> - <description> - Side Force due to rudder(DATCOM does not calculate) - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>fcs/rudder-pos-deg</property> - <value> .000 </value> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/CyDa"> - <description> - Side Force due to aileron(DATCOM does not calculate) - Usually neglected - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>fcs/left-aileron-pos-deg</property> - <value> .000 </value> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="ROLL"> - - - <function name="aero/coefficient/Clb"> - <description> - Roll Moment coefficient due to Beta(per degree) - Decrease of Clb to small negative value improves Dutch Roll Damping - High Positive value leads to excessive spiral instability - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/beta-deg</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.1224E-02 - -8.000 -.1221E-02 - -6.000 -.1219E-02 - -4.000 -.1216E-02 - -2.000 -.1212E-02 - .000 -.1208E-02 - 2.000 -.1206E-02 - 4.000 -.1204E-02 - 8.000 -.1203E-02 - 9.000 -.1204E-02 - 10.00 -.1202E-02 - 12.00 -.1194E-02 - 14.00 -.1181E-02 - 16.00 -.1162E-02 - 18.00 -.1134E-02 - 19.00 -.1116E-02 - 20.00 -.1082E-02 - 21.00 -.1034E-02 - 22.00 -.9825E-03 - 24.00 -.9008E-03 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Clp"> - <description> - Roll Moment coefficient due to roll rate(per degree) - Clp alone determines damping-in-roll characteristics - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/p-aero-rad_sec</property> - <!--Manually increased roll damping, problem with datcom?--> - <value>-0.5</value> - <!--<table>--> - <!--<independentVar lookup="row">aero/alpha-deg</independentVar>--> - <!--<tableData>--> - <!---16.00 -.7650E-02--> - <!---8.000 -.7063E-02--> - <!---6.000 -.6859E-02--> - <!---4.000 -.6653E-02--> - <!---2.000 -.6738E-02--> - <!--.000 -.7039E-02--> - <!--2.000 -.7303E-02--> - <!--4.000 -.7498E-02--> - <!--8.000 -.7737E-02--> - <!--9.000 -.7239E-02--> - <!--10.00 -.6298E-02--> - <!--12.00 -.4816E-02--> - <!--14.00 -.3420E-02--> - <!--16.00 -.1548E-02--> - <!--18.00 .8581E-03--> - <!--19.00 .5957E-02--> - <!--20.00 .1465E-01--> - <!--21.00 .1964E-01--> - <!--22.00 .1776E-01--> - <!--24.00 .7247E-02--> - <!--</tableData>--> - <!--</table>--> - </product> - </function> - - <function name="aero/coefficient/Clr"> - <description> - Roll Moment coefficient due to yaw rate(per degree) - Considerable effect on Spiral mode. Large - positive values leads to strong sprial instability. - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/r-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.3497E-02 - -8.000 -.1073E-02 - -6.000 -.4976E-03 - -4.000 .5472E-04 - -2.000 .5948E-03 - .000 .1162E-02 - 2.000 .1754E-02 - 4.000 .2366E-02 - 8.000 .3626E-02 - 9.000 .3944E-02 - 10.00 .4217E-02 - 12.00 .4651E-02 - 14.00 .4975E-02 - 16.00 .5166E-02 - 18.00 .5164E-02 - 19.00 .5079E-02 - 20.00 .4606E-02 - 21.00 .3766E-02 - 22.00 .2861E-02 - 24.00 .1748E-02 - </tableData> - </table> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/ClDr"> - <description> - Roll moment due to rudder(DATCOM does not calculate) - Usually insignificant in dynamic stability considerations - but is used in autopilot work - </description> - <product> - <property>metrics/bw-ft</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>fcs/rudder-pos-deg</property> - <value> .000 </value> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="PITCH"> - - - <function name="aero/coefficient/Cm_basic"> - <description> - Basic_Pitch_moment_coefficient - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .6261 - -8.000 .2937 - -6.000 .2325 - -4.000 .1590 - -2.000 .7771E-01 - .000 -.5162E-02 - 2.000 -.9019E-01 - 4.000 -.1784 - 8.000 -.3681 - 9.000 -.4190 - 10.00 -.4685 - 12.00 -.5701 - 14.00 -.6714 - 16.00 -.7712 - 18.00 .000 - 19.00 .000 - 20.00 .000 - 21.00 .000 - 22.00 .000 - 24.00 .000 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cmq"> - <description> - Pitch moment coefficient due to pitch rate(per degree) - Pitch Damping Derivative - Very important to Short Period damping of oscillations - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <property>aero/ci2vel</property> - <property>velocities/q-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.2485 - -8.000 -.2485 - -6.000 -.2485 - -4.000 -.2485 - -2.000 -.2485 - .000 -.2485 - 2.000 -.2485 - 4.000 -.2485 - 8.000 -.2485 - 9.000 -.2485 - 10.00 -.2485 - 12.00 -.2485 - 14.00 -.2485 - 16.00 -.2485 - 18.00 -.2485 - 19.00 -.2485 - 20.00 -.2485 - 21.00 -.2485 - 22.00 -.2485 - 24.00 -.2485 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cmadot"> - <description> - Pitch moment coefficient due to AOA rate(per degree) - Negitive Cmad increase Short Period damping - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <property>aero/ci2vel</property> - <property>aero/alphadot-deg_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.1061 - -8.000 -.9502E-01 - -6.000 -.1001 - -4.000 -.1002 - -2.000 -.9926E-01 - .000 -.9960E-01 - 2.000 -.9904E-01 - 4.000 -.9762E-01 - 8.000 -.8757E-01 - 9.000 -.8480E-01 - 10.00 -.7772E-01 - 12.00 -.5882E-01 - 14.00 -.4683E-01 - 16.00 -.3071E-01 - 18.00 .6206E-02 - 19.00 .3526E-01 - 20.00 .1013 - 21.00 .1714 - 22.00 .1595 - 24.00 .9619E-01 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CmDe"> - <description> - Pitch moment coefficient due to elevator deflection - Positive surface deflection is trailing edge down - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <table> - <independentVar lookup="row">fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 .2086 - -15.00 .1871 - -10.00 .1282 - -5.000 .6409E-01 - .000 -.1282E-03 - 5.000 -.6409E-01 - 10.00 -.1282 - 13.00 -.1648 - 16.00 -.1970 - </tableData> - </table> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="YAW"> - - - <function name="aero/coefficient/Cnb"> - <description> - Yaw moment coefficient due to sideslip(per degree) - Determines Dutch Roll and Spiral characteristics - Prevents side-slip and yawing moments - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/beta-deg</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .6403E-03 - -8.000 .6403E-03 - -6.000 .6403E-03 - -4.000 .6403E-03 - -2.000 .6403E-03 - .000 .6403E-03 - 2.000 .6403E-03 - 4.000 .6403E-03 - 8.000 .6403E-03 - 9.000 .6403E-03 - 10.00 .6403E-03 - 12.00 .6403E-03 - 14.00 .6403E-03 - 16.00 .6403E-03 - 18.00 .6403E-03 - 19.00 .6403E-03 - 20.00 .6403E-03 - 21.00 .6403E-03 - 22.00 .6403E-03 - 24.00 .6403E-03 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cnp"> - <description> - Yaw moment coefficient due to roll rate(per degree) - Reduces Dutch Roll damping - positive value desireable - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/p-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .2909E-03 - -8.000 .1580E-03 - -6.000 .1150E-03 - -4.000 .5960E-04 - -2.000 .8267E-06 - .000 -.4457E-04 - 2.000 -.7403E-04 - 4.000 -.9603E-04 - 8.000 -.1448E-03 - 9.000 -.2952E-03 - 10.00 -.5744E-03 - 12.00 -.1081E-02 - 14.00 -.1590E-02 - 16.00 -.2209E-02 - 18.00 -.2839E-02 - 19.00 -.1963E-02 - 20.00 -.6663E-02 - 21.00 -.6409E-02 - 22.00 -.4810E-02 - 24.00 -.2047E-02 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cnr"> - <description> - Yaw Moment coefficient due to yaw rate(per degree) - Main contributor to damping of Dutch Roll - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/r-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.8275E-03 - -8.000 -.7745E-03 - -6.000 -.7758E-03 - -4.000 -.7821E-03 - -2.000 -.7927E-03 - .000 -.8079E-03 - 2.000 -.8285E-03 - 4.000 -.8551E-03 - 8.000 -.9275E-03 - 9.000 -.9496E-03 - 10.00 -.9698E-03 - 12.00 -.1004E-02 - 14.00 -.1030E-02 - 16.00 -.1043E-02 - 18.00 -.1037E-02 - 19.00 -.1026E-02 - 20.00 -.9793E-03 - 21.00 -.9093E-03 - 22.00 -.8479E-03 - 24.00 -.7868E-03 - </tableData> - </table> - </product> - </function> - - - <!-- ****************************************************** - CnDr is not calculated by DATCOM+, but a default value - is supplied - ******************************************************--> - - <function name="aero/coefficient/CnDr"> - <description> - Yaw Coefficient due to rudder(DATCOM does not calculate) - High value for controllablity, low value - for good dynamic stability - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>fcs/rudder-pos-deg</property> - <value> -.1047E-02</value> - </product> - </function> - - - </axis> - - - - -<!-- ********************************************************************** --> - - - <function name="aero/elev_hinge_moment_ft_lbs"> - <description> - Elevator hinge moment in ft-lbs - HM = q * S * Cbar * ( Ch0 + Cha*alpha + Chd*delta ) - Positive causes trailing edge down movement - Ch0 is used to artifically trim HM to zero - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <value> .4492E-01</value> <!-- surface area of elevator --> - <value> .9414E-01</value> <!-- MAC of elevator --> - <sum> - <!-- - <property>aero/Ch0_elev</property> - --> - <product> - <property>aero/alpha-deg</property> - <table> <!-- Ch-alpha --> - <independentVar lookup="row"> - aero/alpha-deg</independentVar> - <tableData> - -16.00 .2169E-02 - -8.000 .2169E-02 - -6.000 .2169E-02 - -4.000 .2169E-02 - -2.000 .2169E-02 - .000 .2169E-02 - 2.000 .2169E-02 - 4.000 .2169E-02 - 8.000 .2169E-02 - 9.000 .2169E-02 - 10.00 .1730E-01 - 12.00 .1723E-01 - 14.00 .1723E-01 - 16.00 .1723E-01 - 18.00 .1723E-01 - 19.00 .1723E-01 - 20.00 .1723E-01 - 21.00 .1723E-01 - 22.00 .1724E-01 - 24.00 .1723E-01 - </tableData> - </table> - </product> - <product> - <property>fcs/elevator-pos-deg</property> - <table> <!-- Ch-delta elevator --> - <independentVar lookup="row"> - fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 .1730E-01 - -15.00 .1723E-01 - -10.00 .1723E-01 - -5.000 .1723E-01 - .000 .1723E-01 - 5.000 .1723E-01 - 10.00 .1723E-01 - 13.00 .1723E-01 - 16.00 .1724E-01 - </tableData> - </table> - </product> - </sum> - </product> - </function> - - </aerodynamics> -</fdm_config> diff --git a/aircraft/EasyStar/EasyStar.xml b/aircraft/EasyStar/EasyStar.xml deleted file mode 100644 index 09ce76806ae262f6acf89d2ac815dbbf16091eb2..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/EasyStar.xml +++ /dev/null @@ -1,1372 +0,0 @@ -<?xml version="1.0"?> -<!-- - This is the JSBSim config file for a PA34-200T SenecaII. - The aerodynamics sections was generated by datcom using - as much real input as available. - - Changes from datcom.xml - - - function attribute NAME must be lowercase - - missing function Delta_lift_due_to_flap_deflection in axis LIFT - - missing function Lift_due_to_Elevator_Deflection in axis LIFT ---> -<?xml-stylesheet href="JSBSim.xsl" type="application/xml"?> -<fdm_config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="file:/home/torsten/FlightGear/Aircraft/SenecaII/JSBSim.xsd" - name="EasyStar" version="2.0" release="BETA"> - - <fileheader> - <author>James Goppert</author> - <filecreationdate>2010-6-3</filecreationdate> - <description>Multiplex Easy Star JSBSim Flight Dynamics Model</description> - <reference title="Multiplex Easy Star JSBSim Flight Dynamics Model"/> - </fileheader> - - <!-- ********************************************************************** - METRICS - ********************************************************************** --> - <metrics> - <wingarea unit="FT2"> 2.2792 </wingarea> - <wingspan unit="FT"> 4.5000 </wingspan> - <chord unit="FT"> .5606 </chord> - <htailarea unit="FT2"> .4457 </htailarea> - <htailarm unit="FT"> .4280 </htailarm> - <vtailarea unit="FT2"> .1606 </vtailarea> - <vtailarm unit="FT"> .7127 </vtailarm> - <!-- - the aerodynamic reference point, common point for - aerodynamic forces (lift and drag) - --> - <location name="AERORP" unit="IN"> - <x> 4.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <!-- the eyepoint of the pilot (left or right eye?) --> - <location name="EYEPOINT" unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <!-- the visual reference point of the 3d model --> - <location name="VRP" unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - </metrics> - - <!-- ********************************************************************** - MASS_BALANCE - ********************************************************************** --> - <mass_balance> - <ixx unit="SLUG*FT2"> .1 </ixx> - <iyy unit="SLUG*FT2"> .1 </iyy> - <izz unit="SLUG*FT2"> .1 </izz> - <ixz unit="SLUG*FT2"> 0 </ixz> - <emptywt unit="LBS"> 2.0 </emptywt> - <!-- the center of gravity --> - <location name="CG" unit="IN"> - <x> 3.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <!--<pointmass name="PAYLOAD">--> - <!--<weight unit="LBS"> 0.0 </weight>--> - <!--<location name="POINTMASS" unit="IN">--> - <!--<x> 39.3 </x>--> - <!--<y> 0 </y>--> - <!--<z> 35.3 </z>--> - <!--</location>--> - <!--</pointmass>--> - </mass_balance> - <!-- ********************************************************************** - UNDERCARRIAGE - ********************************************************************** --> - <ground_reactions> - <contact type="STRUCTURE" name="TAIL_SKID"> - <location unit="IN"> - <x> 27.0 </x> - <y> 0 </y> - <z>-2.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="NOSE"> - <location unit="IN"> - <x> -5.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="BOTTOM_CANOPY"> - <location unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> -3.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - - <contact type="STRUCTURE" name="LEFT_WING"> - <location unit="IN"> - <x> -3.0 </x> - <y> -27.5 </y> - <z> 1.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="RIGHT_WING"> - <location unit="IN"> - <x> -3.0 </x> - <y> 27.5 </y> - <z> 1.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="VERTICAL_TAIL"> - <location unit="IN"> - <x> 27.0 </x> - <y> 0.0 </y> - <z> 6.5 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - <contact type="STRUCTURE" name="CABIN_TOP"> - <location unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 2.0 </z> - </location> - <static_friction> 1.0 </static_friction> - <dynamic_friction> 0.8 </dynamic_friction> - <spring_coeff unit="LBS/FT"> 12 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 1 </damping_coeff> - </contact> - </ground_reactions> - <!-- ********************************************************************** - PROPULSION - ********************************************************************** --> - <propulsion> - <engine file="HB2815-2000"> - <location unit="IN"> - <x> 10.0 </x> - <y> 0 </y> - <z> 3.0 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> -5 </pitch> - <yaw> 0 </yaw> - </orient> - <feed>0</feed> - <thruster file="apc6x4"> - <location unit="IN"> - <x> 10.0 </x> - <y> 0 </y> - <z> 3.0 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> -5.0 </pitch> - <yaw> 0.0 </yaw> - </orient> - <p_factor>1.0</p_factor> - </thruster> - </engine> - <!--throws warning if tank not included, no real purpose--> - <tank type="FUEL"> <!-- Tank number 0 --> - <location unit="IN"> - <x> 0.0 </x> - <y> 0.0 </y> - <z> 0.0 </z> - </location> - <capacity unit="LBS"> 0.0001 </capacity> - <contents unit="LBS"> 0 </contents> - </tank> - </propulsion> - <!-- ********************************************************************** - FLIGHT CONTROLS - ********************************************************************** --> - <flight_control name="EasyStar"> - <!-- - Elevator - --> - <channel name="Pitch"> - <summer name="Pitch Trim Sum"> - <input>fcs/elevator-cmd-norm</input> - <input>fcs/pitch-trim-cmd-norm</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - <output>fcs/elevator-pos-norm</output> - </summer> - <aerosurface_scale name="Elevator Control"> - <input>fcs/pitch-trim-sum</input> - <gain>0.01745</gain> - <range> - <min>-28</min> - <max>23</max> - </range> - <output>fcs/elevator-pos-rad</output> - </aerosurface_scale> - </channel> - <!-- - Rudder - --> - <channel name="Yaw"> - <summer name="Yaw Trim Sum"> - <input>fcs/rudder-cmd-norm</input> - <input>fcs/yaw-trim-cmd-norm</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - </summer> - <!--<pure_gain name="Aileron Crossfeed">--> - <!--<input>fcs/aileron-cmd-norm</input>--> - <!--<gain>-1</gain>--> - <!--<output>fcs/rudder-pos-norm</output>--> - <!--</pure_gain>--> - <summer name="Yaw Mix"> - <input>fcs/yaw-trim-sum</input> - <!--<input>fcs/aileron-crossfeed</input>--> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - </summer> - <aerosurface_scale name="Rudder Control"> - <input>fcs/yaw-mix</input> - <gain>0.01745</gain> - <range> - <min>-27</min> - <max>27</max> - </range> - <output>fcs/rudder-pos-rad</output> - </aerosurface_scale> - </channel> - <!-- - Throttle (linear vs rpm approx.) - --> - <channel name="Throttle"> - <fcs_function name="fcs/rpm-scaled-throttle"> - <function> - <pow> - <property>fcs/throttle-cmd-norm</property> - <value>3</value> - </pow> - </function> - </fcs_function> - <aerosurface_scale name="Throttle Control"> - <input>fcs/rpm-scaled-throttle</input> - <range> - <min>-1</min> - <max>1</max> - </range> - <output>fcs/throttle-pos-norm</output> - </aerosurface_scale> - </channel> - - </flight_control> - -<!-- - - - ****************** IMPORTANT NOTICES ********************** - - This is an alpha version release of the DATCOM+ program for - JSBSIM. Nothing, and I do mean NOTHING, as been checked to - verify that the parameters, units, sign conventions, or - basically anything else is correct. Your mileage may vary. - - *********************************************************** - - This file was generated by the USAF Digital DATCOM program. - This file is considered an intermediary file in the - DATCOM/JSBSim process. This file may be overwritten without - warning, so any changes that you make in here may be lost. - - If you intend to use this file as it is and modify it, make - sure that you take the necessary precautions to prevent it - from being overwritten, like renaming it. - - - *********************************************************** - - - DISCLAIMER REQUIRED BY HQ USAF FOR PUBLIC RELEASE APPROVAL - - THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION - IS RELEASED "AS IS". THE U.S. GOVERNMENT MAKES NO - WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, CONCERNING - THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION, - INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - IN NO EVENT WILL THE U.S. GOVERNMENT BE LIABLE FOR ANY - DAMAGES, INCLUDING LOST PROFITS, LOST SAVINGS OR OTHER - INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE - USE, OR INABILITY TO USE, THIS SOFTWARE OR ANY - ACCOMPANYING DOCUMENTATION, EVEN IF INFORMED IN ADVANCE - OF THE POSSIBILITY OF SUCH DAMAGES. - - - *********************************************************** ---> - - - - - - - -<!-- ********************************************************************** - AERODYNAMICS - ********************************************************************** ---> - - - <aerodynamics> - - <alphalimits unit="DEG"> - <min> -16.00 </min> - <max> 24.00 </max> - </alphalimits> - - - - - <!-- ************************* - Sign Conventions - ************************* - - Control displacements - Stick FWD + / Aft - - Stick Left + / Right - - Wheel CCW + / CW - - Pedal Left + / Right - - Elevator trim Nose Up + / Nose down - - - Surfaces - Elevator TED + / TEU - - R Ail TED + / TEU - - L Ail TED + / TEU - - Rudder TEL + / TER - - - F&M, Accel, Rates, Displacements - Pitch Up + / Down - - Roll Rgt + / Left - - Yaw Rgt + / Left - - - Other - Alpha Up + / Down - - Beta Wind in right ear + / Wind in left ear - - Slip Ball right of center + / left of center - - --> - - - - - <!-- ************************************** - ASSUMPTIONS AND LIMITATIONS - - There is no interaction between deflected surfaces modeled - so there is no change in elevator effects with the flaps - deflected, for example. - - Terms known to be missing from DATCOM: - Power effects - Ground effects - Cyr, CyDr, Cyda, ClDr, Cndr - - ************************************** - --> - - - <!-- - The following ground effect tables are NOT generated - by DATCOM, but provide representative effects. - These terms are not currently used in this model. - --> - - - <function name="aero/function/ground-effect-factor-lift"> - <description>Change in lift due to ground effect factor</description> - <product> - <table> - <independentVar lookup="row">aero/h_b-mac-ft</independentVar> - <tableData> - 0.0 1.203 - 0.1 1.127 - 0.15 1.090 - 0.2 1.073 - 0.3 1.046 - 0.4 1.055 - 0.5 1.019 - 0.6 1.013 - 0.7 1.008 - 0.8 1.006 - 0.9 1.003 - 1.0 1.002 - 1.1 1.0 - </tableData> - </table> - </product> - </function> - - <function name="aero/function/ground-effect-factor-drag"> - <description>Change in drag due to ground effect</description> - <product> - <table> - <independentVar lookup="row">aero/h_b-mac-ft</independentVar> - <tableData> - 0.0 0.480 - 0.1 0.515 - 0.15 0.629 - 0.2 0.709 - 0.3 0.815 - 0.4 0.882 - 0.5 0.928 - 0.6 0.962 - 0.7 0.988 - 0.8 1.0 - 0.9 1.0 - 1.0 1.0 - 1.1 1.0 - </tableData> - </table> - </product> - </function> - - - - - -<!-- ********************************************************************** --> - - - <axis name="LIFT"> - - - <function name="aero/coefficient/CLwbh"> - <description> - Lift due to alpha - Increase in CL decreases Period and damping,Dutch Roll damping - CL is low for landing - </description> - <product> - <property>aero/function/ground-effect-factor-lift</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -1.216 - -8.000 -.4490 - -6.000 -.2713 - -4.000 -.9559E-01 - -2.000 .7950E-01 - .000 .2620 - 2.000 .4513 - 4.000 .6466 - 8.000 1.053 - 9.000 1.157 - 10.00 1.248 - 12.00 1.403 - 14.00 1.529 - 16.00 1.620 - 18.00 1.660 - 19.00 1.659 - 20.00 1.545 - 21.00 1.332 - 22.00 1.097 - 24.00 .8071 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CLq"> - <description> - Basic Lift Coefficient due to pitch rate(per degree) - </description> - <product> - <property>velocities/q-aero-rad_sec</property> - <value>57.29577951</value> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/ci2vel</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .1523 - -8.000 .1523 - -6.000 .1523 - -4.000 .1523 - -2.000 .1523 - .000 .1523 - 2.000 .1523 - 4.000 .1523 - 8.000 .1523 - 9.000 .1523 - 10.00 .1523 - 12.00 .1523 - 14.00 .1523 - 16.00 .1523 - 18.00 .1523 - 19.00 .1523 - 20.00 .1523 - 21.00 .1523 - 22.00 .1523 - 24.00 .1523 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CLad"> - <description> - Basic Lift Coefficient due to AOA rate(per degree) - Important contributor to Short-Period damping - For low Cla, aircraft must land at high alpha - </description> - <product> - <property>aero/alphadot-deg_sec</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/ci2vel</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .3510E-01 - -8.000 .3144E-01 - -6.000 .3313E-01 - -4.000 .3315E-01 - -2.000 .3284E-01 - .000 .3296E-01 - 2.000 .3277E-01 - 4.000 .3230E-01 - 8.000 .2898E-01 - 9.000 .2806E-01 - 10.00 .2572E-01 - 12.00 .1946E-01 - 14.00 .1550E-01 - 16.00 .1016E-01 - 18.00 -.2053E-02 - 19.00 -.1167E-01 - 20.00 -.3353E-01 - 21.00 -.5670E-01 - 22.00 -.5279E-01 - 24.00 -.3183E-01 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CLDe"> - <description> - Lift Coefficient due to Elevator Deflection - Positive surface deflection is trailing edge down - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 -.6476E-01 - -15.00 -.5856E-01 - -10.00 -.4002E-01 - -5.000 -.2001E-01 - .000 .4002E-04 - 5.000 .2001E-01 - 10.00 .4002E-01 - 13.00 .5157E-01 - 16.00 .6162E-01 - </tableData> - </table> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="DRAG"> - - - <function name="aero/coefficient/CD"> - <description> - Basic Drag Coefficient - Sense: Always positive - Main contributor to Phugoid damping: Greater Cd, Better damping - </description> - <product> - <property>aero/function/ground-effect-factor-lift</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .1667 - -8.000 .4475E-01 - -6.000 .3290E-01 - -4.000 .2639E-01 - -2.000 .2554E-01 - .000 .3065E-01 - 2.000 .4245E-01 - 4.000 .6156E-01 - 8.000 .1232 - 9.000 .1436 - 10.00 .1636 - 12.00 .2014 - 14.00 .2355 - 16.00 .2637 - 18.00 .2813 - 19.00 .2851 - 20.00 .2611 - 21.00 .2185 - 22.00 .1816 - 24.00 .1539 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CdDe"> - <description> - Drag Coefficient due to Elevator Deflection - Positive surface deflection is trailing edge down - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <independentVar lookup="column">fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 -15.00 -10.00 -5.000 .000 5.000 10.00 13.00 16.00 - -16.00 .5945E-02 .5210E-02 .3237E-02 .1444E-02 -.2539E-05 -.1095E-02 -.1842E-02 -.2114E-02 -.2256E-02 - -8.000 .3346E-02 .2862E-02 .1633E-02 .6419E-03 -.9344E-06 -.2931E-03 -.2373E-03 -.4624E-04 .2148E-03 - -6.000 .2700E-02 .2278E-02 .1234E-02 .4425E-03 -.5355E-06 -.9363E-04 .1616E-03 .4677E-03 .8290E-03 - -4.000 .2027E-02 .1671E-02 .8186E-03 .2349E-03 -.1202E-06 .1140E-03 .5768E-03 .1003E-02 .1468E-02 - -2.000 .1338E-02 .1048E-02 .3930E-03 .2209E-04 .3054E-06 .3268E-03 .1002E-02 .1551E-02 .2124E-02 - .000 .6550E-03 .4315E-03 -.2832E-04 -.1886E-03 .7268E-06 .5375E-03 .1424E-02 .2094E-02 .2773E-02 - 2.000 -.3080E-04 -.1879E-03 -.4516E-03 -.4002E-03 .1150E-05 .7491E-03 .1847E-02 .2640E-02 .3425E-02 - 4.000 -.7194E-03 -.8099E-03 -.8767E-03 -.6128E-03 .1575E-05 .9616E-03 .2272E-02 .3187E-02 .4079E-02 - 8.000 -.2133E-02 -.2087E-02 -.1749E-02 -.1049E-02 .2448E-05 .1398E-02 .3145E-02 .4312E-02 .5423E-02 - 9.000 -.2513E-02 -.2429E-02 -.1984E-02 -.1166E-02 .2683E-05 .1515E-02 .3379E-02 .4614E-02 .5784E-02 - 10.00 -.2896E-02 -.2776E-02 -.2220E-02 -.1285E-02 .2920E-05 .1633E-02 .3616E-02 .4919E-02 .6148E-02 - 12.00 -.3763E-02 -.3559E-02 -.2755E-02 -.1552E-02 .3453E-05 .1901E-02 .4151E-02 .5608E-02 .6972E-02 - 14.00 -.4698E-02 -.4403E-02 -.3333E-02 -.1841E-02 .4031E-05 .2190E-02 .4728E-02 .6352E-02 .7861E-02 - 16.00 -.5692E-02 -.5301E-02 -.3946E-02 -.2148E-02 .4650E-05 .2496E-02 .5342E-02 .7143E-02 .8806E-02 - 18.00 -.6799E-02 -.6301E-02 -.4629E-02 -.2489E-02 .5328E-05 .2838E-02 .6025E-02 .8023E-02 .9858E-02 - 19.00 -.7457E-02 -.6895E-02 -.5036E-02 -.2692E-02 .5729E-05 .3041E-02 .6431E-02 .8547E-02 .1048E-01 - 20.00 -.8200E-02 -.7566E-02 -.5494E-02 -.2921E-02 .6195E-05 .3270E-02 .6889E-02 .9137E-02 .1119E-01 - 21.00 -.9209E-02 -.8478E-02 -.6117E-02 -.3233E-02 .6812E-05 .3582E-02 .7512E-02 .9940E-02 .1215E-01 - 22.00 -.1032E-01 -.9484E-02 -.6805E-02 -.3577E-02 .7499E-05 .3926E-02 .8201E-02 .1083E-01 .1321E-01 - 24.00 -.1205E-01 -.1104E-01 -.7870E-02 -.4109E-02 .8561E-05 .4458E-02 .9265E-02 .1220E-01 .1485E-01 - </tableData> - </table> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="SIDE"> - - - <function name="aero/coefficient/Cyb"> - <description> - Side Force coefficient due to Sideslip(per degree) - Contributes to damping of Dutch Roll mode - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/beta-deg</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.3898E-02 - -8.000 -.3898E-02 - -6.000 -.3898E-02 - -4.000 -.3898E-02 - -2.000 -.3898E-02 - .000 -.3898E-02 - 2.000 -.3898E-02 - 4.000 -.3898E-02 - 8.000 -.3898E-02 - 9.000 -.3898E-02 - 10.00 -.3898E-02 - 12.00 -.3898E-02 - 14.00 -.3898E-02 - 16.00 -.3898E-02 - 18.00 -.3898E-02 - 19.00 -.3898E-02 - 20.00 -.3898E-02 - 21.00 -.3898E-02 - 22.00 -.3898E-02 - 24.00 -.3898E-02 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cyp"> - <description> - Side Force Coefficient due to Roll Rate(per degree) - </description> - <product> - <property>velocities/p-aero-rad_sec</property> - <value>57.29577951</value> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/bi2vel</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.6446E-03 - -8.000 -.1072E-02 - -6.000 -.1171E-02 - -4.000 -.1268E-02 - -2.000 -.1364E-02 - .000 -.1460E-02 - 2.000 -.1555E-02 - 4.000 -.1651E-02 - 8.000 -.1855E-02 - 9.000 -.1955E-02 - 10.00 -.2099E-02 - 12.00 -.2372E-02 - 14.00 -.2653E-02 - 16.00 -.3034E-02 - 18.00 -.3638E-02 - 19.00 -.1454E-01 - 20.00 -.5140E-03 - 21.00 -.1285E-02 - 22.00 -.1322E-02 - 24.00 -.1076E-02 - </tableData> - </table> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/Cyr"> - <description> - Side Force due to Yaw Rate(DATCOM does not calculate) - Effect is small - </description> - <product> - <property>velocities/r-aero-rad_sec</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/bi2vel</property> - <value> .000 </value> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/CyDr"> - <description> - Side Force due to rudder(DATCOM does not calculate) - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>fcs/rudder-pos-deg</property> - <value> .000 </value> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/CyDa"> - <description> - Side Force due to aileron(DATCOM does not calculate) - Usually neglected - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>fcs/left-aileron-pos-deg</property> - <value> .000 </value> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="ROLL"> - - - <function name="aero/coefficient/Clb"> - <description> - Roll Moment coefficient due to Beta(per degree) - Decrease of Clb to small negative value improves Dutch Roll Damping - High Positive value leads to excessive spiral instability - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/beta-deg</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.1224E-02 - -8.000 -.1221E-02 - -6.000 -.1219E-02 - -4.000 -.1216E-02 - -2.000 -.1212E-02 - .000 -.1208E-02 - 2.000 -.1206E-02 - 4.000 -.1204E-02 - 8.000 -.1203E-02 - 9.000 -.1204E-02 - 10.00 -.1202E-02 - 12.00 -.1194E-02 - 14.00 -.1181E-02 - 16.00 -.1162E-02 - 18.00 -.1134E-02 - 19.00 -.1116E-02 - 20.00 -.1082E-02 - 21.00 -.1034E-02 - 22.00 -.9825E-03 - 24.00 -.9008E-03 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Clp"> - <description> - Roll Moment coefficient due to roll rate(per degree) - Clp alone determines damping-in-roll characteristics - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/p-aero-rad_sec</property> - <!--Manually increased roll damping, problem with datcom?--> - <value>-0.5</value> - <!--<table>--> - <!--<independentVar lookup="row">aero/alpha-deg</independentVar>--> - <!--<tableData>--> - <!---16.00 -.7650E-02--> - <!---8.000 -.7063E-02--> - <!---6.000 -.6859E-02--> - <!---4.000 -.6653E-02--> - <!---2.000 -.6738E-02--> - <!--.000 -.7039E-02--> - <!--2.000 -.7303E-02--> - <!--4.000 -.7498E-02--> - <!--8.000 -.7737E-02--> - <!--9.000 -.7239E-02--> - <!--10.00 -.6298E-02--> - <!--12.00 -.4816E-02--> - <!--14.00 -.3420E-02--> - <!--16.00 -.1548E-02--> - <!--18.00 .8581E-03--> - <!--19.00 .5957E-02--> - <!--20.00 .1465E-01--> - <!--21.00 .1964E-01--> - <!--22.00 .1776E-01--> - <!--24.00 .7247E-02--> - <!--</tableData>--> - <!--</table>--> - </product> - </function> - - <function name="aero/coefficient/Clr"> - <description> - Roll Moment coefficient due to yaw rate(per degree) - Considerable effect on Spiral mode. Large - positive values leads to strong sprial instability. - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/r-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.3497E-02 - -8.000 -.1073E-02 - -6.000 -.4976E-03 - -4.000 .5472E-04 - -2.000 .5948E-03 - .000 .1162E-02 - 2.000 .1754E-02 - 4.000 .2366E-02 - 8.000 .3626E-02 - 9.000 .3944E-02 - 10.00 .4217E-02 - 12.00 .4651E-02 - 14.00 .4975E-02 - 16.00 .5166E-02 - 18.00 .5164E-02 - 19.00 .5079E-02 - 20.00 .4606E-02 - 21.00 .3766E-02 - 22.00 .2861E-02 - 24.00 .1748E-02 - </tableData> - </table> - </product> - </function> - - - <!-- ************************* - Not calculated by DATCOM+ - ************************* - --> - - <function name="aero/coefficient/ClDr"> - <description> - Roll moment due to rudder(DATCOM does not calculate) - Usually insignificant in dynamic stability considerations - but is used in autopilot work - </description> - <product> - <property>metrics/bw-ft</property> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>fcs/rudder-pos-deg</property> - <value> .000 </value> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="PITCH"> - - - <function name="aero/coefficient/Cm_basic"> - <description> - Basic_Pitch_moment_coefficient - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .6261 - -8.000 .2937 - -6.000 .2325 - -4.000 .1590 - -2.000 .7771E-01 - .000 -.5162E-02 - 2.000 -.9019E-01 - 4.000 -.1784 - 8.000 -.3681 - 9.000 -.4190 - 10.00 -.4685 - 12.00 -.5701 - 14.00 -.6714 - 16.00 -.7712 - 18.00 .000 - 19.00 .000 - 20.00 .000 - 21.00 .000 - 22.00 .000 - 24.00 .000 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cmq"> - <description> - Pitch moment coefficient due to pitch rate(per degree) - Pitch Damping Derivative - Very important to Short Period damping of oscillations - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <property>aero/ci2vel</property> - <property>velocities/q-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.2485 - -8.000 -.2485 - -6.000 -.2485 - -4.000 -.2485 - -2.000 -.2485 - .000 -.2485 - 2.000 -.2485 - 4.000 -.2485 - 8.000 -.2485 - 9.000 -.2485 - 10.00 -.2485 - 12.00 -.2485 - 14.00 -.2485 - 16.00 -.2485 - 18.00 -.2485 - 19.00 -.2485 - 20.00 -.2485 - 21.00 -.2485 - 22.00 -.2485 - 24.00 -.2485 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cmadot"> - <description> - Pitch moment coefficient due to AOA rate(per degree) - Negitive Cmad increase Short Period damping - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <property>aero/ci2vel</property> - <property>aero/alphadot-deg_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.1061 - -8.000 -.9502E-01 - -6.000 -.1001 - -4.000 -.1002 - -2.000 -.9926E-01 - .000 -.9960E-01 - 2.000 -.9904E-01 - 4.000 -.9762E-01 - 8.000 -.8757E-01 - 9.000 -.8480E-01 - 10.00 -.7772E-01 - 12.00 -.5882E-01 - 14.00 -.4683E-01 - 16.00 -.3071E-01 - 18.00 .6206E-02 - 19.00 .3526E-01 - 20.00 .1013 - 21.00 .1714 - 22.00 .1595 - 24.00 .9619E-01 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/CmDe"> - <description> - Pitch moment coefficient due to elevator deflection - Positive surface deflection is trailing edge down - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/cbarw-ft</property> - <table> - <independentVar lookup="row">fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 .2086 - -15.00 .1871 - -10.00 .1282 - -5.000 .6409E-01 - .000 -.1282E-03 - 5.000 -.6409E-01 - 10.00 -.1282 - 13.00 -.1648 - 16.00 -.1970 - </tableData> - </table> - </product> - </function> - - </axis> - - - - -<!-- ********************************************************************** --> - - - <axis name="YAW"> - - - <function name="aero/coefficient/Cnb"> - <description> - Yaw moment coefficient due to sideslip(per degree) - Determines Dutch Roll and Spiral characteristics - Prevents side-slip and yawing moments - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/beta-deg</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .6403E-03 - -8.000 .6403E-03 - -6.000 .6403E-03 - -4.000 .6403E-03 - -2.000 .6403E-03 - .000 .6403E-03 - 2.000 .6403E-03 - 4.000 .6403E-03 - 8.000 .6403E-03 - 9.000 .6403E-03 - 10.00 .6403E-03 - 12.00 .6403E-03 - 14.00 .6403E-03 - 16.00 .6403E-03 - 18.00 .6403E-03 - 19.00 .6403E-03 - 20.00 .6403E-03 - 21.00 .6403E-03 - 22.00 .6403E-03 - 24.00 .6403E-03 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cnp"> - <description> - Yaw moment coefficient due to roll rate(per degree) - Reduces Dutch Roll damping - positive value desireable - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/p-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 .2909E-03 - -8.000 .1580E-03 - -6.000 .1150E-03 - -4.000 .5960E-04 - -2.000 .8267E-06 - .000 -.4457E-04 - 2.000 -.7403E-04 - 4.000 -.9603E-04 - 8.000 -.1448E-03 - 9.000 -.2952E-03 - 10.00 -.5744E-03 - 12.00 -.1081E-02 - 14.00 -.1590E-02 - 16.00 -.2209E-02 - 18.00 -.2839E-02 - 19.00 -.1963E-02 - 20.00 -.6663E-02 - 21.00 -.6409E-02 - 22.00 -.4810E-02 - 24.00 -.2047E-02 - </tableData> - </table> - </product> - </function> - - <function name="aero/coefficient/Cnr"> - <description> - Yaw Moment coefficient due to yaw rate(per degree) - Main contributor to damping of Dutch Roll - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>aero/bi2vel</property> - <property>velocities/r-aero-rad_sec</property> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <tableData> - -16.00 -.8275E-03 - -8.000 -.7745E-03 - -6.000 -.7758E-03 - -4.000 -.7821E-03 - -2.000 -.7927E-03 - .000 -.8079E-03 - 2.000 -.8285E-03 - 4.000 -.8551E-03 - 8.000 -.9275E-03 - 9.000 -.9496E-03 - 10.00 -.9698E-03 - 12.00 -.1004E-02 - 14.00 -.1030E-02 - 16.00 -.1043E-02 - 18.00 -.1037E-02 - 19.00 -.1026E-02 - 20.00 -.9793E-03 - 21.00 -.9093E-03 - 22.00 -.8479E-03 - 24.00 -.7868E-03 - </tableData> - </table> - </product> - </function> - - - <!-- ****************************************************** - CnDr is not calculated by DATCOM+, but a default value - is supplied - ******************************************************--> - - <function name="aero/coefficient/CnDr"> - <description> - Yaw Coefficient due to rudder(DATCOM does not calculate) - High value for controllablity, low value - for good dynamic stability - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>metrics/bw-ft</property> - <property>fcs/rudder-pos-deg</property> - <value> -.1047E-02</value> - </product> - </function> - - - </axis> - - - - -<!-- ********************************************************************** --> - - - <function name="aero/elev_hinge_moment_ft_lbs"> - <description> - Elevator hinge moment in ft-lbs - HM = q * S * Cbar * ( Ch0 + Cha*alpha + Chd*delta ) - Positive causes trailing edge down movement - Ch0 is used to artifically trim HM to zero - </description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <value> .4492E-01</value> <!-- surface area of elevator --> - <value> .9414E-01</value> <!-- MAC of elevator --> - <sum> - <!-- - <property>aero/Ch0_elev</property> - --> - <product> - <property>aero/alpha-deg</property> - <table> <!-- Ch-alpha --> - <independentVar lookup="row"> - aero/alpha-deg</independentVar> - <tableData> - -16.00 .2169E-02 - -8.000 .2169E-02 - -6.000 .2169E-02 - -4.000 .2169E-02 - -2.000 .2169E-02 - .000 .2169E-02 - 2.000 .2169E-02 - 4.000 .2169E-02 - 8.000 .2169E-02 - 9.000 .2169E-02 - 10.00 .1730E-01 - 12.00 .1723E-01 - 14.00 .1723E-01 - 16.00 .1723E-01 - 18.00 .1723E-01 - 19.00 .1723E-01 - 20.00 .1723E-01 - 21.00 .1723E-01 - 22.00 .1724E-01 - 24.00 .1723E-01 - </tableData> - </table> - </product> - <product> - <property>fcs/elevator-pos-deg</property> - <table> <!-- Ch-delta elevator --> - <independentVar lookup="row"> - fcs/elevator-pos-deg</independentVar> - <tableData> - -20.00 .1730E-01 - -15.00 .1723E-01 - -10.00 .1723E-01 - -5.000 .1723E-01 - .000 .1723E-01 - 5.000 .1723E-01 - 10.00 .1723E-01 - 13.00 .1723E-01 - 16.00 .1724E-01 - </tableData> - </table> - </product> - </sum> - </product> - </function> - - </aerodynamics> -</fdm_config> diff --git a/aircraft/EasyStar/Engines/HB2815-2000.xml b/aircraft/EasyStar/Engines/HB2815-2000.xml deleted file mode 100644 index f49a5ce4d9fc4c8ea97658103b40d00174f73261..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/Engines/HB2815-2000.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0"?> -<!-- HB2815-2000 --> - -<electric_engine name="electric_250watt"> - <power unit="WATTS"> 250 </power> -</electric_engine> diff --git a/aircraft/EasyStar/Engines/Makefile.am b/aircraft/EasyStar/Engines/Makefile.am deleted file mode 100644 index f79a8d00951c7070b071516a6bfda38fa67a7f5f..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/Engines/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -aircraft_EasyStar_Enginesdir = ${pkgdatadir}/aircraft/EasyStar/Engines -aircraft_EasyStar_Engines_DATA = \ - HB2815-2000.xml \ - apc6x4.xml -EXTRA_DIST=$(aircraft_EasyStar_Engines_data) diff --git a/aircraft/EasyStar/Engines/apc6x4.xml b/aircraft/EasyStar/Engines/apc6x4.xml deleted file mode 100644 index 00e84320c7401f504d12edba93cd251486763193..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/Engines/apc6x4.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0"?> - -<propeller name="apc 6x4"> - <ixx> 0.0001 </ixx> - <diameter unit="IN"> 6.0 </diameter> - <numblades> 2 </numblades> - <minpitch> 30 </minpitch> - <maxpitch> 30 </maxpitch> - <minrpm> 0</minrpm> - <maxrpm> 40000</maxrpm> - - <table name="C_THRUST" type="internal"> - <tableData> - 0.0 0.0776 - 0.1 0.0744 - 0.2 0.0712 - 0.3 0.0655 - 0.4 0.0588 - 0.5 0.0518 - 0.6 0.0419 - 0.7 0.0318 - 0.8 0.0172 - 1.0 -0.0058 - 1.4 -0.0549 - </tableData> - </table> - - <table name="C_POWER" type = "internal"> - <tableData> - 0.0 0.0902 - 0.1 0.0893 - 0.2 0.0880 - 0.3 0.0860 - 0.4 0.0810 - 0.5 0.0742 - 0.6 0.0681 - 0.7 0.0572 - 0.8 0.0467 - 1.0 0.0167 - 1.4 -0.0803 - </tableData> - </table> - -</propeller> diff --git a/aircraft/EasyStar/Makefile.am b/aircraft/EasyStar/Makefile.am deleted file mode 100644 index 2ba46b7f6db4ff384bb92343c868a2ae154c599b..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/Makefile.am +++ /dev/null @@ -1,13 +0,0 @@ -SUBDIRS = \ - Models \ - Datcom \ - scripts \ - Engines -aircraft_EasyStardir = ${pkgdatadir}/aircraft/EasyStar -aircraft_EasyStar_DATA = \ - EasyStar-set.xml \ - reset00.xml \ - reset01.xml \ - EasyStar.xml \ - EasyStar-sound.xml -EXTRA_DIST=$(aircraft_EasyStar_data) diff --git a/aircraft/EasyStar/Models/EasyStar-model.xml b/aircraft/EasyStar/Models/EasyStar-model.xml deleted file mode 100644 index ea6fee1c6d7316bca295af04efdd8a60620730ac..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/Models/EasyStar-model.xml +++ /dev/null @@ -1,114 +0,0 @@ -<?xml version="1.0"?> -<PropertyList> - - <!--Plane--> - <path>EasyStar.ac</path> - <offsets> - <z-m>0.0</z-m> - <y-m>0</y-m> - <x-m>0.0</x-m> - <pitch-deg>0</pitch-deg> - </offsets> - - <!--Elevator--> - <animation> - <type>rotate</type> - <object-name>Elevator</object-name> - <property>/surface-positions/elevator-pos-norm</property> - <factor>22.5</factor> - <axis> - <x1-m>0.701</x1-m> - <y1-m>-0.174</y1-m> - <z1-m>-0.010</z1-m> - <x2-m>0.701</x2-m> - <y2-m>0.0174</y2-m> - <z2-m>-0.010</z2-m> - </axis> - </animation> - - <!--Rudder--> - <animation> - <type>rotate</type> - <object-name>Rudder</object-name> - <property>/surface-positions/rudder-pos-norm</property> - <factor>25</factor> - <axis> - <x1-m>0.716</x1-m> - <y1-m>0.000</y1-m> - <z1-m>0.000</z1-m> - <x2-m>0.715</x2-m> - <y2-m>0.000</y2-m> - <z2-m>0.083</z2-m> - </axis> - </animation> - - <!-- Propeller --> - <animation> - <type>noshadow</type> - <object-name>Propeller.Spinning</object-name> - </animation> - <animation> - <type>material</type> - <object-name>Propeller.Spinning</object-name> - <threshold>0.001</threshold> - <transparency> - <alpha>0.2</alpha> - <factor-prop>/engines/engine[0]/rpm-norm-inv</factor-prop> - <min>0.0</min> - <max>1.0</max> - </transparency> - </animation> - <animation> - <type>select</type> - <object-name>Propeller.Spinning</object-name> - <condition> - <greater-than> - <property>/engines/engine[0]/rpm</property> - <value>350</value> - </greater-than> - </condition> - </animation> - <animation> - <type>spin</type> - <object-name>Propeller.Spinning</object-name> - <property>/engines/engine[0]/rpm</property> - <factor>1</factor> - <axis> - <x1-m>0.277</x1-m> - <y1-m>0.000</y1-m> - <z1-m>0.078</z1-m> - <x2-m>0.309</x2-m> - <y2-m>0.000</y2-m> - <z2-m>0.086</z2-m> - </axis> - </animation> - <animation> - <type>noshadow</type> - <object-name>Propeller</object-name> - </animation> - <animation> - <type>spin</type> - <object-name>Propeller</object-name> - <property>/engines/engine[0]/rpm</property> - <factor>1</factor> - <axis> - <x1-m>0.277</x1-m> - <y1-m>0.000</y1-m> - <z1-m>0.078</z1-m> - <x2-m>0.309</x2-m> - <y2-m>0.000</y2-m> - <z2-m>0.086</z2-m> - </axis> - </animation> - <animation> - <type>select</type> - <object-name>Propeller</object-name> - <condition> - <less-than> - <property>/engines/engine[0]/rpm</property> - <value>400</value> - </less-than> - </condition> - </animation> - -</PropertyList> diff --git a/aircraft/EasyStar/Models/EasyStar.ac b/aircraft/EasyStar/Models/EasyStar.ac deleted file mode 100644 index f5725e754a43e0562871dccadbbd2b9bb42a0b09..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/Models/EasyStar.ac +++ /dev/null @@ -1,32516 +0,0 @@ -AC3Db -MATERIAL "DefaultWhite" rgb 1 1 1 amb 1 1 1 emis 0 0 0 spec 0.5 0.5 0.5 shi 64 trans 0 -MATERIAL "Styrofoam" rgb 1 1 1 amb 0 0 0 emis 0 0 0 spec 1 1 1 shi 32 trans 0 -MATERIAL "Styrofoam.001" rgb 0.141176 0.141176 0.141176 amb 0 0 0 emis 0 0 0 spec 1 1 1 shi 21 trans 0 -MATERIAL "Material.007" rgb 0.537255 0.54902 0.54902 amb 0.5 0.5 0.5 emis 0 0 0 spec 1 1 1 shi 84 trans 0 -MATERIAL "Material.006" rgb 0.28 0.28 0.28 amb 0 0 0 emis 0 0 0 spec 1 1 1 shi 101 trans 0 -MATERIAL "Material.001" rgb 0.278431 0.278431 0.278431 amb 0.5 0.5 0.5 emis 0 0 0 spec 1 1 1 shi 32 trans 0 -OBJECT world -kids 3 -OBJECT group -name "Fueselage" -kids 10 -OBJECT poly -name "Fueselage" -data 13 -Fuesalage.001 -crease 30.000000 -numvert 368 --0.18844 -0.025817 -0.007443 --0.18844 -0.025817 0.007443 --0.18844 -0.026866 0 --0.198425 -0.008389 0 --0.18844 -0.022831 -0.013684 --0.18844 -0.022831 0.013684 --0.188441 -0.018362 -0.017853 --0.188441 -0.018362 0.017853 --0.18844 -0.01309 -0.019318 --0.18844 -0.01309 0.019318 --0.18844 -0.007818 -0.017853 --0.18844 -0.007818 0.017853 --0.188439 -0.003348 -0.013684 --0.188439 -0.003348 0.013684 --0.188438 -0.000362 -0.007443 --0.188438 -0.000362 0.007443 --0.188438 0.000686 0 --1e-05 0 -0.042975 --1e-05 0 0.042975 --0.066101 -0.018965 -0.043395 --0.066101 -0.018965 0.043395 --0.073055 -0.001712 -0.040098 --0.073055 -0.001712 0.040098 --0.082891 0.022687 -0.016657 --0.082891 0.022687 0.016657 --0.084274 0.026119 0 --0.07895 0.012914 -0.030709 --0.07895 0.012914 0.030709 -0.289524 -0.015336 -0.024511 -0.289524 -0.015336 0.024511 -0.238233 0.01197 -0.021239 -0.238233 0.01197 0.021239 -0.243331 0.022978 -0.019035 -0.243331 0.022978 0.019035 -0.037862 0.063817 -0.013502 -0.037862 0.063817 0.013502 -0.014639 0.024682 0 -0.038931 0.06597 0 -0.274245 0.0587 0 -0.27342 0.059582 -0.00687 -0.27342 0.059582 0.00687 -0.273836 0.062678 -0.01355 -0.273836 0.062678 0.01355 -0.272572 0.068947 -0.017823 -0.272572 0.068947 0.017823 -0.27108 0.076342 -0.019323 -0.27108 0.076342 0.019323 -0.269589 0.083737 -0.017823 -0.269589 0.083737 0.017823 -0.268325 0.090006 -0.013549 -0.268325 0.090006 0.013549 -0.26748 0.094194 -0.007154 -0.26748 0.094194 0.007154 -0.267184 0.095665 0 -0.209278 0.077769 0 -0.115944 0.067384 -0.013502 -0.115944 0.067384 0.013502 -0.216526 0.088103 -0.007154 -0.216526 0.088103 0.007154 -0.289514 -0.051894 0 -0.289515 -0.049881 -0.010202 -0.289515 -0.049881 0.010202 -0.289516 -0.044149 -0.018779 -0.289516 -0.044149 0.018779 -0.289518 -0.035572 -0.024511 -0.289518 -0.035572 0.024511 -0.289521 -0.025454 -0.026523 -0.289521 -0.025454 0.026523 -0.289526 -0.006758 -0.018779 -0.289526 -0.006758 0.018779 -0.289528 -0.001027 -0.010201 -0.289528 -0.001027 0.010201 -0.289528 0.000986 0 -0.2356 -0.056159 0 -0.235601 -0.052229 -0.011002 -0.235601 -0.052229 0.011002 -0.235605 -0.041037 -0.020259 -0.235605 -0.041037 0.020259 -0.23561 -0.024288 -0.026444 -0.23561 -0.024288 0.026444 -0.235613 -0.00453 -0.028616 -0.235613 -0.00453 0.028616 -0.20806 -0.058335 0 -0.208062 -0.055056 -0.012117 -0.208062 -0.055056 0.012117 -0.208066 -0.042722 -0.022318 -0.208066 -0.042722 0.022318 -0.208071 -0.024263 -0.029135 -0.208071 -0.024263 0.029135 -0.208076 -0.002489 -0.031528 -0.208076 -0.002489 0.031528 -0.199951 0.014603 -0.023182 -0.199951 0.014603 0.023182 -0.1149 -0.061816 0 -0.114902 -0.055643 -0.013636 -0.114902 -0.055643 0.013636 -0.114907 -0.043309 -0.025127 -0.114907 -0.043309 0.025127 -0.114913 -0.024869 -0.032804 -0.114913 -0.024869 0.032804 -0.114917 -0.002438 -0.0355 -0.114917 -0.002438 0.0355 -0.09479 0.018489 -0.032804 -0.09479 0.018489 0.032804 -0.032853 -0.06438 0 -0.032855 -0.059063 -0.015818 -0.032855 -0.059063 0.015818 -0.032862 -0.043922 -0.029157 -0.032862 -0.043922 0.029157 -0.032868 -0.021263 -0.03807 -0.032868 -0.021263 0.03807 -0.032872 0.005466 -0.0412 -0.032872 0.005466 0.0412 -0.03287 0.032154 -0.03807 -0.03287 0.032154 0.03807 --0.033183 -0.064838 0 --0.030656 -0.059903 -0.016497 --0.030656 -0.059903 0.016497 --0.023463 -0.045847 -0.030412 --0.023463 -0.045847 0.030412 --0.012701 -0.024812 -0.03971 --0.012701 -0.024812 0.03971 --0.153208 -0.046195 0 --0.153208 -0.043898 -0.012504 --0.153208 -0.043898 0.012504 --0.049315 -0.060617 -0.016657 --0.049315 -0.060617 0.016657 --0.047932 -0.064049 0 --0.153207 -0.037359 -0.023034 --0.153207 -0.037359 0.023034 --0.053253 -0.050844 -0.030709 --0.053253 -0.050844 0.030709 --0.153207 -0.027572 -0.03007 --0.153207 -0.027572 0.03007 --0.059147 -0.036218 -0.040098 --0.059147 -0.036218 0.040098 --0.153205 -0.016027 -0.032541 --0.153205 -0.016027 0.032541 --0.153204 -0.004483 -0.03007 --0.153204 -0.004483 0.03007 --0.153203 0.005304 -0.023034 --0.153203 0.005304 0.023034 --0.153202 0.011843 -0.012504 --0.153202 0.011843 0.012504 --0.153201 0.014139 0 -0.257037 0.025486 -0.017324 -0.257037 0.025486 0.017324 -0.26665 0.026788 -0.009485 -0.26665 0.026788 0.009485 -0.269992 0.027282 0 -0.22111 0.033801 -0.01845 -0.22111 0.033801 0.01845 -0.246039 0.046314 -0.017342 -0.246039 0.046314 0.017342 -0.264434 0.048105 -0.009335 -0.264434 0.048105 0.009335 -0.269833 0.049698 0 -0.188879 0.041149 -0.023532 -0.188879 0.041149 0.023532 -0.200063 0.05979 -0.025339 -0.200063 0.05979 0.025339 -0.11474 0.052316 -0.022943 -0.11474 0.052316 0.022943 -0.115462 0.059569 -0.024878 -0.115462 0.059569 0.024878 -0.050217 0.051939 -0.02681 -0.050217 0.051939 0.02681 -0.034454 0.057905 -0.024877 -0.034454 0.057905 0.024877 -0.116113 0.070519 0 -0.01463 0.024682 -0.03971 -0.01463 0.024682 0.03971 -0 0 0 -0.218635 0.077645 -0.017823 -0.218635 0.077645 0.017823 -0.21737 0.083914 -0.013549 -0.21737 0.083914 0.013549 -0.255908 0.091709 -0.013549 -0.255908 0.091709 0.013549 -0.257173 0.08544 -0.017823 -0.257173 0.08544 0.017823 -0.255064 0.095898 -0.007154 -0.255064 0.095898 0.007154 -0.216229 0.089574 0 -0.254767 0.097369 0 -0.260155 0.070651 -0.017823 -0.260155 0.070651 0.017823 -0.258664 0.078045 -0.019323 -0.258664 0.078045 0.019323 -0.238235 0.012891 0 -0.243332 0.023899 0 -0.221111 0.034721 0 -0.18888 0.04231 0 -0.114741 0.053767 0 -0.05022 0.05317 0 -0.032877 0.033378 0 -0.094795 0.019904 0 -0.199952 0.015536 0 -0.68265 -0.028723 -0.01833 -0.68265 -0.028723 0.01833 -0.687489 -0.022918 -0.019833 -0.687489 -0.022918 0.019833 -0.692327 -0.017112 -0.01833 -0.692327 -0.017112 0.01833 -0.674846 -0.038089 0 -0.675808 -0.036934 -0.007642 -0.675808 -0.036934 0.007642 -0.678549 -0.033646 -0.014049 -0.678549 -0.033646 0.014049 -0.696429 -0.009206 -0.014049 -0.696429 -0.009206 0.014049 -0.69917 -0.009213 -0.007642 -0.69917 -0.009213 0.007642 -0.700132 -0.009221 0 --0.073033 -0.001725 0 -0.289527 -0.003892 -0.01449 -0.289527 -0.003892 0.01449 -0.289517 -0.039861 -0.021645 -0.289517 -0.039861 0.021645 -0.289515 -0.047015 -0.01449 -0.289515 -0.047015 0.01449 -0.28952 -0.030513 -0.025517 -0.28952 -0.030513 0.025517 -0.289515 -0.050887 -0.005101 -0.289515 -0.050887 0.005101 -0.289525 -0.011047 -0.021645 -0.289525 -0.011047 0.021645 -0.289528 -2.1e-05 -0.005101 -0.289528 -2.1e-05 0.005101 -0.289523 -0.020395 -0.025517 -0.289523 -0.020395 0.025517 -0.68507 -0.02582 -0.019082 -0.68507 -0.02582 0.019082 -0.689908 -0.020015 -0.019082 -0.689908 -0.020015 0.019082 -0.675327 -0.037512 -0.003821 -0.675327 -0.037512 0.003821 -0.677178 -0.03529 -0.010845 -0.677178 -0.03529 0.010845 -0.6806 -0.031184 -0.016189 -0.6806 -0.031184 0.016189 -0.694378 -0.013159 -0.016189 -0.694378 -0.013159 0.016189 -0.697799 -0.00921 -0.010845 -0.697799 -0.00921 0.010845 -0.69965 -0.009217 -0.003821 -0.69965 -0.009217 0.003821 -0.687488 -0.023655 0 -0.49417 -0.00512 -0.008922 -0.49417 -0.00512 0.008922 -0.4928 -0.007982 -0.016414 -0.4928 -0.007982 0.016414 -0.49075 -0.016224 -0.02142 -0.49075 -0.016224 0.02142 -0.488332 -0.024186 -0.023178 -0.488332 -0.024186 0.023178 -0.485914 -0.032148 -0.02142 -0.485914 -0.032148 0.02142 -0.483864 -0.038898 -0.016414 -0.483864 -0.038898 0.016414 -0.482495 -0.043408 -0.008922 -0.482495 -0.043408 0.008922 -0.494651 -0.004118 0 -0.482014 -0.044991 0 -0.289523 -0.025454 0 -0.488332 -0.024554 0 -0.494411 -0.004619 -0.004461 -0.494411 -0.004619 0.004461 -0.493485 -0.006551 -0.012668 -0.493485 -0.006551 0.012668 -0.491775 -0.012103 -0.018917 -0.491775 -0.012103 0.018917 -0.489541 -0.020205 -0.022299 -0.489541 -0.020205 0.022299 -0.487123 -0.028167 -0.022299 -0.487123 -0.028167 0.022299 -0.484889 -0.035522 -0.018917 -0.484889 -0.035522 0.018917 -0.48318 -0.041152 -0.012668 -0.48318 -0.041152 0.012668 -0.482254 -0.044199 -0.004461 -0.482254 -0.044199 0.004461 --0.153367 0.000776 -0.027094 --0.153367 0.000776 0.027094 --0.153073 -0.044648 -0.005134 --0.153073 -0.044648 0.005134 --0.171129 0.00802 0 --0.153384 -0.021954 -0.031944 --0.153384 -0.021954 0.031944 --0.172421 -0.031723 -0.019758 --0.172421 -0.031723 0.019758 --0.19385 -0.005482 -0.007185 --0.19385 -0.005482 0.007185 --0.171807 -0.023734 -0.025548 --0.171807 -0.023734 0.025548 --0.194375 -0.016133 -0.007443 --0.194375 -0.016133 0.007443 --0.18819 -0.026118 -0.003171 --0.18819 -0.026118 0.003171 --0.153397 -0.032844 -0.027057 --0.153397 -0.032844 0.027057 --0.172358 -0.014538 -0.028055 --0.172358 -0.014538 0.028055 --0.188616 -0.005435 -0.015982 --0.188616 -0.005435 0.015982 --0.188597 -0.001652 -0.010685 --0.188597 -0.001652 0.010685 --0.153089 0.012561 -0.005454 --0.153089 0.012561 0.005454 --0.188627 -0.015766 -0.018797 --0.188627 -0.015766 0.018797 --0.171877 0.002354 -0.019514 --0.171877 0.002354 0.019514 --0.153372 -0.010135 -0.031959 --0.153372 -0.010135 0.031959 --0.153369 0.009109 -0.018118 --0.153369 0.009109 0.018118 --0.171606 -0.005468 -0.025394 --0.171606 -0.005468 0.025394 --0.188609 -0.010402 -0.018792 --0.188609 -0.010402 0.018792 --0.171406 -0.037257 0 --0.188261 -9.2e-05 -0.003182 --0.188261 -9.2e-05 0.003182 --0.194852 -0.017765 0 --0.194437 -0.003728 0 --0.171317 0.006865 -0.010381 --0.171317 0.006865 0.010381 --0.188619 -0.020712 -0.015951 --0.188619 -0.020712 0.015951 --0.193936 -0.010744 -0.010312 --0.193936 -0.010744 0.010312 --0.153406 -0.041144 -0.01808 --0.153406 -0.041144 0.01808 --0.188621 -0.024484 -0.010664 --0.188621 -0.024484 0.010664 --0.171836 -0.036527 -0.010574 --0.171836 -0.036527 0.010574 --0.189991 -0.012761 -0.003029 --0.189991 -0.012761 0.003029 --0.154799 -0.014671 -0.007808 --0.154799 -0.014671 0.007808 --0.19133 -0.002599 -0.005448 --0.19133 -0.002599 0.005448 --0.191791 -0.016012 -0.013585 --0.191791 -0.016012 0.013585 --0.191883 -0.021331 -0.005703 --0.191883 -0.021331 0.005703 --0.191574 -0.007842 -0.01345 --0.191574 -0.007842 0.01345 --0.173132 -0.013662 -0.006626 --0.173132 -0.013662 0.006626 --0.171089 0.007146 -0.00501 --0.171089 0.007146 0.00501 --0.171759 0.005052 -0.015155 --0.171759 0.005052 0.015155 --0.171948 -0.001286 -0.022894 --0.171948 -0.001286 0.022894 --0.172179 -0.009817 -0.027225 --0.172179 -0.009817 0.027225 --0.172314 -0.019308 -0.027295 --0.172314 -0.019308 0.027295 --0.172327 -0.027972 -0.023084 --0.172327 -0.027972 0.023084 --0.172336 -0.034534 -0.015364 --0.172336 -0.034534 0.015364 --0.171476 -0.036669 -0.005274 --0.171476 -0.036669 0.005274 -numsurf 470 -SURF 0x10 -mat 1 -refs 3 -19 0.0 1.0 -21 -1.19209289551e-07 -1.19209289551e-07 -17 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -18 1.0 1.0 -22 -1.19209289551e-07 -1.19209289551e-07 -20 0.0 1.0 -SURF 0x10 -mat 1 -refs 3 -36 -4.76837158203e-07 0.999999463558 -37 -1.19209289551e-07 -2.38418579102e-07 -34 0.999999821186 0.999999701977 -SURF 0x10 -mat 1 -refs 3 -35 0.999999821186 0.999999701977 -37 -1.19209289551e-07 -2.38418579102e-07 -36 -4.76837158203e-07 0.999999463558 -SURF 0x10 -mat 1 -refs 3 -26 0.0 1.0 -214 0.0 0.0 -21 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -22 1.0 1.0 -214 0.0 0.0 -27 0.0 1.0 -SURF 0x10 -mat 1 -refs 3 -122 0.0 0.0 -214 1.0 1.0 -127 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -45 0.0 1.0 -47 0.0 0.0 -43 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -44 1.0 1.0 -48 0.0 0.0 -46 0.0 1.0 -SURF 0x10 -mat 1 -refs 3 -55 0.0 1.0 -169 0.0 0.0 -54 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -54 1.0 1.0 -169 0.0 0.0 -56 0.0 1.0 -SURF 0x10 -mat 1 -refs 3 -38 0.0 0.0 -184 1.0 1.0 -53 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -38 0.0 0.0 -156 1.0 0.0 -191 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -36 0.0 0.0 -195 1.0 0.0 -196 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -159 1.0 0.0 -54 0.0 0.0 -173 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -174 1.0 1.0 -54 0.0 0.0 -160 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -187 -7.15255737305e-07 -1.19209289551e-07 -185 1.00000011921 -3.57627868652e-07 -152 0.999999940395 0.999999821186 -SURF 0x10 -mat 1 -refs 3 -153 0.999999940395 0.999999821186 -186 1.00000011921 -3.57627868652e-07 -188 -7.15255737305e-07 -1.19209289551e-07 -SURF 0x10 -mat 1 -refs 3 -43 -4.76837158203e-07 -1.66893005371e-06 -41 0.999998688698 -1.78813934326e-06 -185 -1.31130218506e-06 0.999998211861 -SURF 0x10 -mat 1 -refs 3 -186 -1.31130218506e-06 0.999998211861 -42 0.999998688698 -1.78813934326e-06 -44 -4.76837158203e-07 -1.66893005371e-06 -SURF 0x10 -mat 1 -refs 3 -39 -2.62260437012e-06 -1.00135803223e-05 -154 1.0 0.0 -41 -2.62260437012e-06 0.999991893768 -SURF 0x10 -mat 1 -refs 3 -42 -2.62260437012e-06 0.999991893768 -155 1.0 0.0 -40 -2.62260437012e-06 -1.00135803223e-05 -SURF 0x10 -mat 1 -refs 3 -157 2.38418579102e-07 5.36441802979e-07 -159 1.0 0.0 -150 4.17232513428e-07 1.00000023842 -SURF 0x10 -mat 1 -refs 3 -151 4.17232513428e-07 1.00000023842 -160 1.0 0.0 -158 2.38418579102e-07 5.36441802979e-07 -SURF 0x10 -mat 1 -refs 3 -80 0.0 0.0 -30 1.0 0.0 -28 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -29 1.0 1.0 -31 1.0 0.0 -81 0.0 0.0 -SURF 0x10 -mat 1 -refs 3 -183 0.0 0.0 -57 0.0 1.0 -54 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -54 1.0 1.0 -58 0.0 1.0 -183 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -145 1.00000238419 5.96046447754e-07 -28 0.0 1.0 -30 0.0 1.0 -32 -1.19209289551e-07 -2.38418579102e-07 -SURF 0x10 -mat 1 -refs 4 -31 0.0 1.0 -29 0.0 1.0 -146 1.00000238419 5.96046447754e-07 -33 -1.19209289551e-07 -2.38418579102e-07 -SURF 0x10 -mat 1 -refs 4 -150 4.17232513428e-07 1.00000023842 -159 1.0 0.0 -187 -7.15255737305e-07 -1.19209289551e-07 -152 0.999999940395 0.999999821186 -SURF 0x10 -mat 1 -refs 4 -188 -7.15255737305e-07 -1.19209289551e-07 -160 1.0 0.0 -151 4.17232513428e-07 1.00000023842 -153 0.999999940395 0.999999821186 -SURF 0x10 -mat 1 -refs 4 -154 1.0 0.0 -152 0.999999642372 1.00000059605 -185 -1.31130218506e-06 0.999998211861 -41 0.999998688698 -1.78813934326e-06 -SURF 0x10 -mat 1 -refs 4 -186 -1.31130218506e-06 0.999998211861 -153 0.999999642372 1.00000059605 -155 1.0 0.0 -42 0.999998688698 -1.78813934326e-06 -SURF 0x10 -mat 1 -refs 4 -57 0.0 1.0 -175 0.0 0.0 -173 1.0 1.0 -54 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -174 1.0 1.0 -176 0.0 0.0 -58 0.0 1.0 -54 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -93 0.0 0.0 -104 0.0 1.0 -36 0.0 0.0 -196 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -184 1.0 1.0 -38 0.0 0.0 -191 1.0 1.0 -192 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -183 1.0 0.0 -184 1.0 0.0 -192 1.0 1.0 -54 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -36 0.0 0.0 -104 0.0 0.0 -115 0.0 1.0 -172 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -127 1.0 0.0 -214 1.0 1.0 -172 1.0 0.0 -115 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -54 0.0 0.0 -192 1.0 0.0 -193 1.0 1.0 -169 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -37 0.0 0.0 -169 1.0 0.0 -193 1.0 1.0 -194 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -49 1.0 0.0 -41 1.0 1.0 -43 0.0 1.0 -47 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -44 0.0 1.0 -42 1.0 1.0 -50 1.0 0.0 -48 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -51 1.0 0.0 -39 1.0 1.0 -41 0.0 1.0 -49 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -42 0.0 1.0 -40 1.0 1.0 -52 1.0 0.0 -50 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -53 1.0 0.0 -38 1.0 1.0 -39 0.0 1.0 -51 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -40 0.0 1.0 -38 1.0 1.0 -53 1.0 0.0 -52 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -149 0.0 0.0 -190 1.0 0.0 -191 1.0 1.0 -156 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -72 0.0 0.0 -189 1.0 0.0 -190 1.0 1.0 -149 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -73 0.0 0.0 -82 0.0 1.0 -197 1.0 1.0 -189 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -82 0.0 0.0 -93 1.0 0.0 -196 1.0 1.0 -197 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -36 0.0 0.0 -37 1.0 0.0 -194 1.0 1.0 -195 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -26 0.0 1.0 -23 1.0 1.0 -25 1.0 0.0 -214 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -25 1.0 0.0 -24 1.0 1.0 -27 0.0 1.0 -214 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -214 0.0 0.0 -172 0.0 1.0 -17 1.0 1.0 -21 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -18 1.0 1.0 -172 0.0 1.0 -214 0.0 0.0 -22 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -163 0.0 0.0 -55 1.0 0.0 -54 1.0 1.0 -159 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -54 1.0 1.0 -56 1.0 0.0 -164 0.0 0.0 -160 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -189 1.0 0.0 -30 1.0 1.0 -91 5.36441802979e-07 1.0 -197 5.36441802979e-07 0.0 -SURF 0x10 -mat 1 -refs 4 -92 5.36441802979e-07 1.0 -31 1.0 1.0 -189 1.0 0.0 -197 5.36441802979e-07 0.0 -SURF 0x10 -mat 1 -refs 4 -197 1.00000023842 1.19209289551e-07 -91 1.00000023842 1.00000011921 -102 0.0 1.0 -196 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -103 0.0 1.0 -92 1.00000023842 1.00000011921 -197 1.00000023842 1.19209289551e-07 -196 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -196 1.0 0.0 -102 1.0 1.0 -113 5.96046447754e-08 1.0 -195 5.96046447754e-08 0.0 -SURF 0x10 -mat 1 -refs 4 -114 5.96046447754e-08 1.0 -103 1.0 1.0 -196 1.0 0.0 -195 5.96046447754e-08 0.0 -SURF 0x10 -mat 1 -refs 4 -194 0.0 0.0 -195 0.999999880791 0.0 -113 0.999999880791 1.0 -165 -3.57627868652e-07 1.00000011921 -SURF 0x10 -mat 1 -refs 4 -114 0.999999880791 1.0 -195 0.999999880791 0.0 -194 0.0 0.0 -166 -3.57627868652e-07 1.00000011921 -SURF 0x10 -mat 1 -refs 4 -165 1.00000011921 5.96046447754e-08 -161 1.0 1.0 -193 0.0 1.0 -194 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -193 0.0 1.0 -162 1.0 1.0 -166 1.00000011921 5.96046447754e-08 -194 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -161 1.0 0.0 -157 1.0 1.00000023842 -192 0.0 1.0 -193 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -192 0.0 1.0 -158 1.0 1.00000023842 -162 1.0 0.0 -193 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -157 1.00000011921 6.55651092529e-07 -150 1.00000011921 1.00000059605 -191 1.78813934326e-07 1.00000059605 -192 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -191 1.78813934326e-07 1.00000059605 -151 1.00000011921 1.00000059605 -158 1.00000011921 6.55651092529e-07 -192 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -191 0.0 8.94069671631e-07 -150 1.0 8.94069671631e-07 -32 1.0 1.0 -190 0.0 1.00000095367 -SURF 0x10 -mat 1 -refs 4 -33 1.0 1.0 -151 1.0 8.94069671631e-07 -191 0.0 8.94069671631e-07 -190 0.0 1.00000095367 -SURF 0x10 -mat 1 -refs 4 -190 0.0 0.0 -32 1.0 -2.38418579102e-07 -30 1.0 1.0 -189 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -31 1.0 1.0 -33 1.0 -2.38418579102e-07 -190 0.0 0.0 -189 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -159 1.0 0.0 -173 1.00000011921 1.00000035763 -179 -3.57627868652e-07 0.99999922514 -187 0.0 6.55651092529e-07 -SURF 0x10 -mat 1 -refs 4 -180 -3.57627868652e-07 0.99999922514 -174 1.00000011921 1.00000035763 -160 1.0 0.0 -188 0.0 6.55651092529e-07 -SURF 0x10 -mat 1 -refs 4 -38 -2.02655792236e-06 -1.41859054565e-05 -156 1.0 0.0 -154 1.0 1.0 -39 -1.54972076416e-06 0.999983906746 -SURF 0x10 -mat 1 -refs 4 -155 1.0 1.0 -156 1.0 0.0 -38 -2.02655792236e-06 -1.41859054565e-05 -40 -1.54972076416e-06 0.999983906746 -SURF 0x10 -mat 1 -refs 4 -51 1.0 0.0 -181 1.0 1.0 -184 0.0 1.0 -53 -1.90734863281e-06 -1.66893005371e-06 -SURF 0x10 -mat 1 -refs 4 -184 0.0 1.0 -182 1.0 1.0 -52 1.0 0.0 -53 -1.90734863281e-06 -1.66893005371e-06 -SURF 0x10 -mat 1 -refs 4 -49 0.999999344349 -1.66893005371e-06 -177 0.999999344349 0.99999833107 -181 0.0 1.0 -51 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -182 0.0 1.0 -178 0.999999344349 0.99999833107 -50 0.999999344349 -1.66893005371e-06 -52 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -47 0.999998688698 -1.78813934326e-06 -179 0.999999523163 0.99999833107 -177 -4.76837158203e-07 0.99999833107 -49 -4.76837158203e-07 -1.66893005371e-06 -SURF 0x10 -mat 1 -refs 4 -178 -4.76837158203e-07 0.99999833107 -180 0.999999523163 0.99999833107 -48 0.999998688698 -1.78813934326e-06 -50 -4.76837158203e-07 -1.66893005371e-06 -SURF 0x10 -mat 1 -refs 4 -45 1.0 0.0 -187 0.999999284744 0.999999940395 -179 -3.57627868652e-07 0.99999833107 -47 -1.07288360596e-06 -1.78813934326e-06 -SURF 0x10 -mat 1 -refs 4 -180 -3.57627868652e-07 0.99999833107 -188 0.999999284744 0.999999940395 -46 1.0 0.0 -48 -1.07288360596e-06 -1.78813934326e-06 -SURF 0x10 -mat 1 -refs 4 -43 0.999999642372 -1.66893005371e-06 -185 0.999998927116 0.999998211861 -187 -7.15255737305e-07 0.999999940395 -45 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -188 -7.15255737305e-07 0.999999940395 -186 0.999998927116 0.999998211861 -44 0.999999642372 -1.66893005371e-06 -46 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -181 1.0 0.0 -57 0.999996066093 0.999999463558 -183 -3.93390655518e-06 0.999999463558 -184 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -183 -3.93390655518e-06 0.999999463558 -58 0.999996066093 0.999999463558 -182 1.0 0.0 -184 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -181 0.0 0.0 -177 1.00000095367 -4.76837158203e-07 -175 0.999998807907 1.0 -57 -1.43051147461e-06 0.999999463558 -SURF 0x10 -mat 1 -refs 4 -176 0.999998807907 1.0 -178 1.00000095367 -4.76837158203e-07 -182 0.0 0.0 -58 -1.43051147461e-06 0.999999463558 -SURF 0x10 -mat 1 -refs 4 -177 5.96046447754e-07 -4.76837158203e-07 -179 1.00000059605 -4.76837158203e-07 -173 0.99999922514 1.0 -175 -8.34465026855e-07 1.0 -SURF 0x10 -mat 1 -refs 4 -174 0.99999922514 1.0 -180 1.00000059605 -4.76837158203e-07 -178 5.96046447754e-07 -4.76837158203e-07 -176 -8.34465026855e-07 1.0 -SURF 0x10 -mat 1 -refs 4 -34 1.00000023842 2.38418579102e-07 -167 1.0 1.0 -170 1.19209289551e-07 1.00000011921 -36 5.96046447754e-08 0.0 -SURF 0x10 -mat 1 -refs 4 -171 1.19209289551e-07 1.00000011921 -168 1.0 1.0 -35 1.00000023842 2.38418579102e-07 -36 5.96046447754e-08 0.0 -SURF 0x10 -mat 1 -refs 4 -36 0.0 -1.19209289551e-07 -170 1.0 -1.19209289551e-07 -17 1.0 1.0 -172 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -18 1.0 1.0 -171 1.0 -1.19209289551e-07 -36 0.0 -1.19209289551e-07 -172 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -113 1.00000011921 0.0 -111 1.0 1.0 -17 0.0 1.0 -170 -1.19209289551e-07 -1.19209289551e-07 -SURF 0x10 -mat 1 -refs 4 -18 0.0 1.0 -112 1.0 1.0 -114 1.00000011921 0.0 -171 -1.19209289551e-07 -1.19209289551e-07 -SURF 0x10 -mat 1 -refs 4 -165 1.00000047684 2.38418579102e-07 -113 1.00000023842 1.00000011921 -170 -1.19209289551e-07 0.999999940395 -167 2.98023223877e-07 -1.19209289551e-07 -SURF 0x10 -mat 1 -refs 4 -171 -1.19209289551e-07 0.999999940395 -114 1.00000023842 1.00000011921 -166 1.00000047684 2.38418579102e-07 -168 2.98023223877e-07 -1.19209289551e-07 -SURF 0x10 -mat 1 -refs 4 -167 0.0 5.96046447754e-08 -34 1.00000059605 0.0 -55 1.00000059605 1.00000011921 -163 6.55651092529e-07 1.0 -SURF 0x10 -mat 1 -refs 4 -56 1.00000059605 1.00000011921 -35 1.00000059605 0.0 -168 0.0 5.96046447754e-08 -164 6.55651092529e-07 1.0 -SURF 0x10 -mat 1 -refs 4 -167 1.0 5.96046447754e-08 -163 1.00000047684 1.0 -161 0.0 1.0 -165 0.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 4 -162 0.0 1.0 -164 1.00000047684 1.0 -168 1.0 5.96046447754e-08 -166 0.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 4 -161 0.0 0.0 -163 1.00000023842 0.0 -159 1.0 1.0 -157 1.19209289551e-07 1.00000023842 -SURF 0x10 -mat 1 -refs 4 -160 1.0 1.0 -164 1.00000023842 0.0 -162 0.0 0.0 -158 1.19209289551e-07 1.00000023842 -SURF 0x10 -mat 1 -refs 4 -156 1.0 0.0 -149 1.00000607967 1.00000011921 -147 5.96046447754e-08 0.999999880791 -154 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -148 5.96046447754e-08 0.999999880791 -149 1.00000607967 1.00000011921 -156 1.0 0.0 -155 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -152 1.19209289551e-07 -2.38418579102e-07 -154 1.0 0.0 -147 1.0 0.999999880791 -145 2.08616256714e-06 1.00000011921 -SURF 0x10 -mat 1 -refs 4 -148 1.0 0.999999880791 -155 1.0 0.0 -153 1.19209289551e-07 -2.38418579102e-07 -146 2.08616256714e-06 1.00000011921 -SURF 0x10 -mat 1 -refs 4 -150 4.76837158203e-07 3.57627868652e-07 -152 1.00000023842 -2.38418579102e-07 -145 1.0000013113 1.00000011921 -32 1.19209289551e-07 0.999999880791 -SURF 0x10 -mat 1 -refs 4 -146 1.0000013113 1.00000011921 -153 1.00000023842 -2.38418579102e-07 -151 4.76837158203e-07 3.57627868652e-07 -33 1.19209289551e-07 0.999999880791 -SURF 0x10 -mat 1 -refs 4 -17 1.0 0.0 -120 0.999999940395 1.0 -134 0.0 1.0 -19 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -135 0.0 1.0 -121 0.999999940395 1.0 -18 1.0 0.0 -20 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -120 1.0 0.0 -118 1.0 1.0 -130 -1.19209289551e-07 0.999999940395 -134 -1.19209289551e-07 1.19209289551e-07 -SURF 0x10 -mat 1 -refs 4 -131 -1.19209289551e-07 0.999999940395 -119 1.0 1.0 -121 1.0 0.0 -135 -1.19209289551e-07 1.19209289551e-07 -SURF 0x10 -mat 1 -refs 4 -118 1.0 0.0 -116 1.0 1.00000035763 -125 -1.19209289551e-07 1.00000035763 -130 -1.19209289551e-07 -1.19209289551e-07 -SURF 0x10 -mat 1 -refs 4 -126 -1.19209289551e-07 1.00000035763 -117 1.0 1.00000035763 -119 1.0 0.0 -131 -1.19209289551e-07 -1.19209289551e-07 -SURF 0x10 -mat 1 -refs 4 -116 1.0 1.01327896118e-06 -115 1.00000011921 1.00000095367 -127 -1.19209289551e-07 1.00000107288 -125 -3.57627868652e-07 1.37090682983e-06 -SURF 0x10 -mat 1 -refs 4 -127 -1.19209289551e-07 1.00000107288 -115 1.00000011921 1.00000095367 -117 1.0 1.01327896118e-06 -126 -3.57627868652e-07 1.37090682983e-06 -SURF 0x10 -mat 1 -refs 4 -120 0.0 0.0 -17 1.0 0.0 -111 1.0 1.0 -109 0.0 1.00000011921 -SURF 0x10 -mat 1 -refs 4 -112 1.0 1.0 -18 1.0 0.0 -121 0.0 0.0 -110 0.0 1.00000011921 -SURF 0x10 -mat 1 -refs 4 -118 0.0 0.0 -120 1.0 0.0 -109 1.0 1.0 -107 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -110 1.0 1.0 -121 1.0 0.0 -119 0.0 0.0 -108 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -116 -3.57627868652e-07 0.0 -118 1.0 0.0 -107 1.0 1.0 -105 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -108 1.0 1.0 -119 1.0 0.0 -117 -3.57627868652e-07 0.0 -106 0.0 1.0 -SURF 0x10 -mat 1 -refs 4 -115 -9.53674316406e-07 5.96046447754e-08 -116 0.999998986721 0.0 -105 1.0 1.0 -104 -9.53674316406e-07 1.0 -SURF 0x10 -mat 1 -refs 4 -106 1.0 1.0 -117 0.999998986721 0.0 -115 -9.53674316406e-07 5.96046447754e-08 -104 -9.53674316406e-07 1.0 -SURF 0x10 -mat 1 -refs 4 -113 1.0 5.96046447754e-08 -102 1.0 1.0 -100 0.0 1.0 -111 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -101 0.0 1.0 -103 1.0 1.0 -114 1.0 5.96046447754e-08 -112 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -111 1.0 0.0 -100 1.0 1.0 -98 5.96046447754e-08 1.00000011921 -109 0.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 4 -99 5.96046447754e-08 1.00000011921 -101 1.0 1.0 -112 1.0 0.0 -110 0.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 4 -109 1.0 5.96046447754e-08 -98 1.0 1.00000011921 -96 0.0 1.0 -107 0.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 4 -97 0.0 1.0 -99 1.0 1.00000011921 -110 1.0 5.96046447754e-08 -108 0.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 4 -107 1.0 5.96046447754e-08 -96 1.0 1.0 -94 -3.57627868652e-07 1.0 -105 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -95 -3.57627868652e-07 1.0 -97 1.0 1.0 -108 1.0 5.96046447754e-08 -106 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -104 -9.53674316406e-07 0.0 -105 1.0 5.96046447754e-08 -94 0.999999165535 1.0 -93 -9.53674316406e-07 1.00000011921 -SURF 0x10 -mat 1 -refs 4 -95 0.999999165535 1.0 -106 1.0 5.96046447754e-08 -104 -9.53674316406e-07 0.0 -93 -9.53674316406e-07 1.00000011921 -SURF 0x10 -mat 1 -refs 4 -102 1.00000011921 0.0 -91 1.0 1.00000023842 -89 0.0 1.00000023842 -100 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -90 0.0 1.00000023842 -92 1.0 1.00000023842 -103 1.00000011921 0.0 -101 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -98 0.0 1.19209289551e-07 -100 1.0 0.0 -89 1.0 1.00000023842 -87 -1.19209289551e-07 1.00000023842 -SURF 0x10 -mat 1 -refs 4 -90 1.0 1.00000023842 -101 1.0 0.0 -99 0.0 1.19209289551e-07 -88 -1.19209289551e-07 1.00000023842 -SURF 0x10 -mat 1 -refs 4 -98 1.0 1.19209289551e-07 -87 0.999999880791 1.00000023842 -85 -3.57627868652e-07 1.00000023842 -96 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -86 -3.57627868652e-07 1.00000023842 -88 0.999999880791 1.00000023842 -99 1.0 1.19209289551e-07 -97 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -96 1.0 0.0 -85 0.999999582767 1.00000023842 -83 -3.57627868652e-07 1.0 -94 -3.57627868652e-07 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 4 -84 -3.57627868652e-07 1.0 -86 0.999999582767 1.00000023842 -97 1.0 0.0 -95 -3.57627868652e-07 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 4 -94 0.999999165535 0.0 -83 0.999998450279 1.0 -82 -8.34465026855e-07 1.0 -93 -8.34465026855e-07 1.78813934326e-07 -SURF 0x10 -mat 1 -refs 4 -82 -8.34465026855e-07 1.0 -84 0.999998450279 1.0 -95 0.999999165535 0.0 -93 -8.34465026855e-07 1.78813934326e-07 -SURF 0x10 -mat 1 -refs 4 -91 1.00000011921 5.36441802979e-07 -30 1.0 1.0 -80 0.0 1.0 -89 5.96046447754e-08 7.7486038208e-07 -SURF 0x10 -mat 1 -refs 4 -81 0.0 1.0 -31 1.0 1.0 -92 1.00000011921 5.36441802979e-07 -90 5.96046447754e-08 7.7486038208e-07 -SURF 0x10 -mat 1 -refs 4 -89 1.00000011921 7.15255737305e-07 -80 1.0 1.0 -78 0.0 1.00000071526 -87 -1.19209289551e-07 7.15255737305e-07 -SURF 0x10 -mat 1 -refs 4 -79 0.0 1.00000071526 -81 1.0 1.0 -90 1.00000011921 7.15255737305e-07 -88 -1.19209289551e-07 7.15255737305e-07 -SURF 0x10 -mat 1 -refs 4 -87 0.999999821186 7.15255737305e-07 -78 0.999999821186 1.00000071526 -76 -1.19209289551e-07 1.00000071526 -85 -3.57627868652e-07 7.7486038208e-07 -SURF 0x10 -mat 1 -refs 4 -77 -1.19209289551e-07 1.00000071526 -79 0.999999821186 1.00000071526 -88 0.999999821186 7.15255737305e-07 -86 -3.57627868652e-07 7.7486038208e-07 -SURF 0x10 -mat 1 -refs 4 -83 -3.57627868652e-07 5.96046447754e-08 -85 0.999999463558 7.15255737305e-07 -76 0.999999642372 1.00000071526 -74 -1.19209289551e-07 1.00000071526 -SURF 0x10 -mat 1 -refs 4 -77 0.999999642372 1.00000071526 -86 0.999999463558 7.15255737305e-07 -84 -3.57627868652e-07 5.96046447754e-08 -75 -1.19209289551e-07 1.00000071526 -SURF 0x10 -mat 1 -refs 4 -82 -1.54972076416e-06 0.0 -83 0.999998450279 0.0 -74 0.999999463558 1.00000071526 -73 -4.76837158203e-07 1.00000071526 -SURF 0x10 -mat 1 -refs 4 -75 0.999999463558 1.00000071526 -84 0.999998450279 0.0 -82 -1.54972076416e-06 0.0 -73 -4.76837158203e-07 1.00000071526 -SURF 0x10 -mat 1 -refs 4 -169 0.0 0.0 -55 0.0 1.0 -34 1.0 1.0 -37 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -35 1.0 1.0 -56 0.0 1.0 -169 0.0 0.0 -37 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -70 1.0 1.0 -215 0.500002205372 1.00000047684 -147 1.00000047684 0.0 -SURF 0x10 -mat 1 -refs 3 -148 1.00000047684 0.0 -216 0.500002205372 1.00000047684 -71 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -215 0.500002205372 1.00000047684 -68 4.29153442383e-06 1.00000083447 -147 1.00000047684 0.0 -SURF 0x10 -mat 1 -refs 3 -148 1.00000047684 0.0 -69 4.29153442383e-06 1.00000083447 -216 0.500002205372 1.00000047684 -SURF 0x10 -mat 1 -refs 3 -64 1.00000023842 1.00000035763 -217 0.500000238419 1.00000011921 -76 -1.19209289551e-07 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 3 -77 -1.19209289551e-07 3.57627868652e-07 -218 0.500000238419 1.00000011921 -65 1.00000023842 1.00000035763 -SURF 0x10 -mat 1 -refs 3 -217 0.500000238419 1.00000011921 -62 4.76837158203e-07 1.00000035763 -76 -1.19209289551e-07 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 3 -77 -1.19209289551e-07 3.57627868652e-07 -63 4.76837158203e-07 1.00000035763 -218 0.500000238419 1.00000011921 -SURF 0x10 -mat 1 -refs 3 -225 1.68838084846e-06 1.00000095367 -145 1.00000238419 5.96046447754e-07 -147 1.00000047684 0.0 -SURF 0x10 -mat 1 -refs 3 -148 1.00000047684 0.0 -146 1.00000238419 5.96046447754e-07 -226 1.68838084846e-06 1.00000095367 -SURF 0x10 -mat 1 -refs 3 -68 4.29153442383e-06 1.00000083447 -225 1.68838084846e-06 1.00000095367 -147 1.00000047684 0.0 -SURF 0x10 -mat 1 -refs 3 -148 1.00000047684 0.0 -226 1.68838084846e-06 1.00000095367 -69 4.29153442383e-06 1.00000083447 -SURF 0x10 -mat 1 -refs 3 -225 1.68838084846e-06 1.00000095367 -28 0.0 1.0 -145 1.00000238419 5.96046447754e-07 -SURF 0x10 -mat 1 -refs 3 -146 1.00000238419 5.96046447754e-07 -29 0.0 1.0 -226 1.68838084846e-06 1.00000095367 -SURF 0x10 -mat 1 -refs 3 -229 0.500000357628 1.00000023842 -78 1.19209289551e-07 4.17232513428e-07 -80 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -81 1.0 0.0 -79 1.19209289551e-07 4.17232513428e-07 -230 0.500000357628 1.00000023842 -SURF 0x10 -mat 1 -refs 3 -28 1.0 1.0 -229 0.500000357628 1.00000023842 -80 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -81 1.0 0.0 -230 0.500000357628 1.00000023842 -29 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -229 0.500000357628 1.00000023842 -66 1.07288360596e-06 1.00000035763 -78 1.19209289551e-07 4.17232513428e-07 -SURF 0x10 -mat 1 -refs 3 -79 1.19209289551e-07 4.17232513428e-07 -67 1.07288360596e-06 1.00000035763 -230 0.500000357628 1.00000023842 -SURF 0x10 -mat 1 -refs 3 -221 0.500000834465 1.00000059605 -76 -1.19209289551e-07 3.57627868652e-07 -78 1.00000023842 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 3 -79 1.00000023842 3.57627868652e-07 -77 -1.19209289551e-07 3.57627868652e-07 -222 0.500000834465 1.00000059605 -SURF 0x10 -mat 1 -refs 3 -66 1.00000083447 1.00000035763 -221 0.500000834465 1.00000059605 -78 1.00000023842 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 3 -79 1.00000023842 3.57627868652e-07 -222 0.500000834465 1.00000059605 -67 1.00000083447 1.00000035763 -SURF 0x10 -mat 1 -refs 3 -221 0.500000834465 1.00000059605 -64 5.36441802979e-07 1.00000035763 -76 -1.19209289551e-07 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 3 -77 -1.19209289551e-07 3.57627868652e-07 -65 5.36441802979e-07 1.00000035763 -222 0.500000834465 1.00000059605 -SURF 0x10 -mat 1 -refs 3 -239 0.499959170818 1.00000798702 -198 -8.34465026855e-07 0.999999642372 -231 -4.17232513428e-07 0.999999821186 -SURF 0x10 -mat 1 -refs 3 -232 -4.17232513428e-07 0.999999821186 -199 -8.34465026855e-07 0.999999642372 -240 0.499959170818 1.00000798702 -SURF 0x10 -mat 1 -refs 3 -231 -4.17232513428e-07 0.999999821186 -200 0.0 1.0 -233 5.96044209544e-08 0.499999731779 -SURF 0x10 -mat 1 -refs 3 -234 5.96044209544e-08 0.499999731779 -201 0.0 1.0 -232 -4.17232513428e-07 0.999999821186 -SURF 0x10 -mat 1 -refs 4 -207 0.999918937683 1.00001633167 -239 0.499959170818 1.00000798702 -233 5.96044209544e-08 0.499999731779 -202 1.19209289551e-07 1.19209289551e-07 -SURF 0x10 -mat 1 -refs 4 -234 5.96044209544e-08 0.499999731779 -240 0.499959170818 1.00000798702 -208 0.999918937683 1.00001633167 -203 1.19209289551e-07 1.19209289551e-07 -SURF 0x10 -mat 1 -refs 3 -231 -4.17232513428e-07 0.999999821186 -233 5.96044209544e-08 0.499999731779 -239 0.499959170818 1.00000798702 -SURF 0x10 -mat 1 -refs 3 -240 0.499959170818 1.00000798702 -234 5.96044209544e-08 0.499999731779 -232 -4.17232513428e-07 0.999999821186 -SURF 0x10 -mat 1 -refs 4 -247 0.499999970198 7.0966585497e-08 -204 0.0 0.0 -263 0.0 0.5 -265 0.382202118635 0.48361492157 -SURF 0x10 -mat 1 -refs 4 -213 1.0 0.0 -247 0.499999970198 7.0966585497e-08 -265 0.382202118635 0.48361492157 -262 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -265 0.382202118635 0.48361492157 -263 0.0 0.5 -59 0.0 1.0 -264 0.5 1.0 -SURF 0x10 -mat 1 -refs 4 -262 1.0 0.5 -265 0.382202118635 0.48361492157 -264 0.5 1.0 -72 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -264 0.0 0.5 -73 1.0 0.0 -189 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -72 0.0 1.0 -264 0.0 0.5 -189 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -264 0.0 0.5 -59 0.0 0.0 -73 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -209 0.0 0.0 -243 0.500000059605 -2.0935158121e-11 -237 0.501342833042 0.99984061718 -207 0.00130832195282 0.999844789505 -SURF 0x10 -mat 1 -refs 4 -238 0.501342833042 0.99984061718 -244 0.500000059605 -2.0935158121e-11 -210 0.0 0.0 -208 0.00130832195282 0.999844789505 -SURF 0x10 -mat 1 -refs 4 -243 0.500000059605 -2.0935158121e-11 -211 1.0 0.0 -205 1.00137722492 0.999836683273 -237 0.501342833042 0.99984061718 -SURF 0x10 -mat 1 -refs 4 -206 1.00137722492 0.999836683273 -212 1.0 0.0 -244 0.500000059605 -2.0935158121e-11 -238 0.501342833042 0.99984061718 -SURF 0x10 -mat 1 -refs 3 -245 0.5 0.0 -213 1.0 0.0 -247 1.0 0.500000059605 -SURF 0x10 -mat 1 -refs 3 -247 1.0 0.500000059605 -213 1.0 0.0 -246 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -247 1.0 0.500000059605 -204 1.0 1.00000011921 -235 0.5 1.0 -SURF 0x10 -mat 1 -refs 3 -236 0.5 1.0 -204 1.0 1.00000011921 -247 1.0 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -211 0.0 0.0 -245 0.5 0.0 -235 0.5 1.0 -205 0.0 1.00000011921 -SURF 0x10 -mat 1 -refs 4 -236 0.5 1.0 -246 0.5 0.0 -212 0.0 0.0 -206 0.0 1.00000011921 -SURF 0x10 -mat 1 -refs 3 -247 1.0 0.500000059605 -235 0.5 1.0 -245 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -246 0.5 0.0 -236 0.5 1.0 -247 1.0 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -245 0.999999940395 0.5 -211 1.0 1.0 -248 0.500000059605 1.0 -266 0.5005864501 0.562873005867 -SURF 0x10 -mat 1 -refs 4 -249 0.500000059605 1.0 -212 1.0 1.0 -246 0.999999940395 0.5 -267 0.5005864501 0.562873005867 -SURF 0x10 -mat 1 -refs 4 -213 1.0 0.0 -245 0.999999940395 0.5 -266 0.5005864501 0.562873005867 -262 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -267 0.5005864501 0.562873005867 -246 0.999999940395 0.5 -213 1.0 0.0 -262 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -266 0.5005864501 0.562873005867 -248 0.500000059605 1.0 -70 0.0 1.0 -227 -3.63402143932e-08 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -71 0.0 1.0 -249 0.500000059605 1.0 -267 0.5005864501 0.562873005867 -228 -3.63402143932e-08 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -262 0.5 0.0 -266 0.5005864501 0.562873005867 -227 -3.63402143932e-08 0.499999970198 -72 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -228 -3.63402143932e-08 0.499999970198 -267 0.5005864501 0.562873005867 -262 0.5 0.0 -72 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -243 0.999999880791 0.499999910593 -209 1.0 1.0 -250 0.500000059605 1.0 -268 0.501681685448 0.564189553261 -SURF 0x10 -mat 1 -refs 4 -251 0.500000059605 1.0 -210 1.0 1.0 -244 0.999999880791 0.499999910593 -269 0.501681685448 0.564189553261 -SURF 0x10 -mat 1 -refs 4 -211 1.0 0.0 -243 0.999999880791 0.499999910593 -268 0.501681685448 0.564189553261 -248 0.5 8.74296617326e-08 -SURF 0x10 -mat 1 -refs 4 -269 0.501681685448 0.564189553261 -244 0.999999880791 0.499999910593 -212 1.0 0.0 -249 0.5 8.74296617326e-08 -SURF 0x10 -mat 1 -refs 4 -268 0.501681685448 0.564189553261 -250 0.500000059605 1.0 -68 5.96046447754e-08 0.999999940395 -215 6.63868604533e-08 0.499999940395 -SURF 0x10 -mat 1 -refs 4 -69 5.96046447754e-08 0.999999940395 -251 0.500000059605 1.0 -269 0.501681685448 0.564189553261 -216 6.63868604533e-08 0.499999940395 -SURF 0x10 -mat 1 -refs 4 -248 0.5 8.74296617326e-08 -268 0.501681685448 0.564189553261 -215 6.63868604533e-08 0.499999940395 -70 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -216 6.63868604533e-08 0.499999940395 -269 0.501681685448 0.564189553261 -249 0.5 8.74296617326e-08 -71 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -241 0.999999880791 0.500000059605 -202 1.0 1.00000011921 -252 0.500000059605 1.00000011921 -270 0.502542376518 0.519077003002 -SURF 0x10 -mat 1 -refs 4 -253 0.500000059605 1.00000011921 -203 1.0 1.00000011921 -242 0.999999880791 0.500000059605 -271 0.502542376518 0.519077003002 -SURF 0x10 -mat 1 -refs 4 -209 1.0 0.0 -241 0.999999880791 0.500000059605 -270 0.502542376518 0.519077003002 -250 0.5 2.34894812934e-07 -SURF 0x10 -mat 1 -refs 4 -271 0.502542376518 0.519077003002 -242 0.999999880791 0.500000059605 -210 1.0 0.0 -251 0.5 2.34894812934e-07 -SURF 0x10 -mat 1 -refs 4 -270 0.502542376518 0.519077003002 -252 0.500000059605 1.00000011921 -28 0.0 1.0 -225 6.67597888082e-08 0.500000238419 -SURF 0x10 -mat 1 -refs 4 -29 0.0 1.0 -253 0.500000059605 1.00000011921 -271 0.502542376518 0.519077003002 -226 6.67597888082e-08 0.500000238419 -SURF 0x10 -mat 1 -refs 4 -250 0.5 2.34894812934e-07 -270 0.502542376518 0.519077003002 -225 6.67597888082e-08 0.500000238419 -68 5.96046447754e-08 0.0 -SURF 0x10 -mat 1 -refs 4 -226 6.67597888082e-08 0.500000238419 -271 0.502542376518 0.519077003002 -251 0.5 2.34894812934e-07 -69 5.96046447754e-08 0.0 -SURF 0x10 -mat 1 -refs 4 -233 1.00000011921 0.500000178814 -200 1.00000023842 1.00000011921 -254 0.500000059605 0.999999880791 -272 0.503035724163 0.607305049896 -SURF 0x10 -mat 1 -refs 4 -255 0.500000059605 0.999999880791 -201 1.00000023842 1.00000011921 -234 1.00000011921 0.500000178814 -273 0.503035724163 0.607305049896 -SURF 0x10 -mat 1 -refs 4 -202 1.0 2.38418579102e-07 -233 1.00000011921 0.500000178814 -272 0.503035724163 0.607305049896 -252 0.500000059605 1.07947634831e-07 -SURF 0x10 -mat 1 -refs 4 -273 0.503035724163 0.607305049896 -234 1.00000011921 0.500000178814 -203 1.0 2.38418579102e-07 -253 0.500000059605 1.07947634831e-07 -SURF 0x10 -mat 1 -refs 4 -272 0.503035724163 0.607305049896 -254 0.500000059605 0.999999880791 -66 5.96046447754e-08 1.0 -229 2.98031856971e-08 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -67 5.96046447754e-08 1.0 -255 0.500000059605 0.999999880791 -273 0.503035724163 0.607305049896 -230 2.98031856971e-08 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -252 0.500000059605 1.07947634831e-07 -272 0.503035724163 0.607305049896 -229 2.98031856971e-08 0.500000178814 -28 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -230 2.98031856971e-08 0.500000178814 -273 0.503035724163 0.607305049896 -253 0.500000059605 1.07947634831e-07 -29 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -231 1.00000023842 0.500000417233 -198 1.0 1.00000047684 -256 0.5 1.00000047684 -274 0.503073096275 0.608623504639 -SURF 0x10 -mat 1 -refs 4 -257 0.5 1.00000047684 -199 1.0 1.00000047684 -232 1.00000023842 0.500000417233 -275 0.503073096275 0.608623504639 -SURF 0x10 -mat 1 -refs 4 -200 1.00000023842 2.38418579102e-07 -231 1.00000023842 0.500000417233 -274 0.503073096275 0.608623504639 -254 0.500000119209 -2.19743611751e-07 -SURF 0x10 -mat 1 -refs 4 -275 0.503073096275 0.608623504639 -232 1.00000023842 0.500000417233 -201 1.00000023842 2.38418579102e-07 -255 0.500000119209 -2.19743611751e-07 -SURF 0x10 -mat 1 -refs 4 -274 0.503073096275 0.608623504639 -256 0.5 1.00000047684 -64 5.96046447754e-08 1.00000047684 -221 9.74689413624e-08 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -65 5.96046447754e-08 1.00000047684 -257 0.5 1.00000047684 -275 0.503073096275 0.608623504639 -222 9.74689413624e-08 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -254 0.500000119209 -2.19743611751e-07 -274 0.503073096275 0.608623504639 -221 9.74689413624e-08 0.500000059605 -66 5.96046447754e-08 0.0 -SURF 0x10 -mat 1 -refs 4 -222 9.74689413624e-08 0.500000059605 -275 0.503073096275 0.608623504639 -255 0.500000119209 -2.19743611751e-07 -67 5.96046447754e-08 0.0 -SURF 0x10 -mat 1 -refs 4 -239 1.0 0.500000238419 -207 1.00000011921 1.00000023842 -258 0.500000119209 1.00000023842 -276 0.502632558346 0.609767258167 -SURF 0x10 -mat 1 -refs 4 -259 0.500000119209 1.00000023842 -208 1.00000011921 1.00000023842 -240 1.0 0.500000238419 -277 0.502632558346 0.609767258167 -SURF 0x10 -mat 1 -refs 4 -198 1.0 5.36441802979e-07 -239 1.0 0.500000238419 -276 0.502632558346 0.609767258167 -256 0.5 4.47034835815e-07 -SURF 0x10 -mat 1 -refs 4 -277 0.502632558346 0.609767258167 -240 1.0 0.500000238419 -199 1.0 5.36441802979e-07 -257 0.5 4.47034835815e-07 -SURF 0x10 -mat 1 -refs 4 -276 0.502632558346 0.609767258167 -258 0.500000119209 1.00000023842 -62 5.96046447754e-08 1.00000011921 -217 2.13407567173e-08 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -63 5.96046447754e-08 1.00000011921 -259 0.500000119209 1.00000023842 -277 0.502632558346 0.609767258167 -218 2.13407567173e-08 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -256 0.5 4.47034835815e-07 -276 0.502632558346 0.609767258167 -217 2.13407567173e-08 0.500000178814 -64 5.96046447754e-08 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 4 -218 2.13407567173e-08 0.500000178814 -277 0.502632558346 0.609767258167 -257 0.5 4.47034835815e-07 -65 5.96046447754e-08 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 4 -237 1.00000011921 0.50000089407 -205 1.00000011921 1.00000119209 -260 0.500000059605 1.00000071526 -278 0.501771390438 0.562733590603 -SURF 0x10 -mat 1 -refs 4 -261 0.500000059605 1.00000071526 -206 1.00000011921 1.00000119209 -238 1.00000011921 0.50000089407 -279 0.501771390438 0.562733590603 -SURF 0x10 -mat 1 -refs 4 -207 1.00000011921 4.17232513428e-07 -237 1.00000011921 0.50000089407 -278 0.501771390438 0.562733590603 -258 0.500000119209 2.82617975245e-07 -SURF 0x10 -mat 1 -refs 4 -279 0.501771390438 0.562733590603 -238 1.00000011921 0.50000089407 -208 1.00000011921 4.17232513428e-07 -259 0.500000119209 2.82617975245e-07 -SURF 0x10 -mat 1 -refs 4 -278 0.501771390438 0.562733590603 -260 0.500000059605 1.00000071526 -60 5.96046447754e-08 1.00000023842 -219 6.83370799948e-08 0.500000119209 -SURF 0x10 -mat 1 -refs 4 -61 5.96046447754e-08 1.00000023842 -261 0.500000059605 1.00000071526 -279 0.501771390438 0.562733590603 -220 6.83370799948e-08 0.500000119209 -SURF 0x10 -mat 1 -refs 4 -258 0.500000119209 2.82617975245e-07 -278 0.501771390438 0.562733590603 -219 6.83370799948e-08 0.500000119209 -62 0.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 4 -220 6.83370799948e-08 0.500000119209 -279 0.501771390438 0.562733590603 -259 0.500000119209 2.82617975245e-07 -63 0.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 4 -235 1.0 0.5 -204 1.0 1.0 -263 0.5 1.0 -280 0.500623703003 0.562729597092 -SURF 0x10 -mat 1 -refs 4 -263 0.5 1.0 -204 1.0 1.0 -236 1.0 0.5 -281 0.500623703003 0.562729597092 -SURF 0x10 -mat 1 -refs 4 -205 1.00000011921 0.0 -235 1.0 0.5 -280 0.500623703003 0.562729597092 -260 0.500000119209 -3.04425213926e-08 -SURF 0x10 -mat 1 -refs 4 -281 0.500623703003 0.562729597092 -236 1.0 0.5 -206 1.00000011921 0.0 -261 0.500000119209 -3.04425213926e-08 -SURF 0x10 -mat 1 -refs 4 -280 0.500623703003 0.562729597092 -263 0.5 1.0 -59 5.96046447754e-08 1.0 -223 5.96046447754e-08 0.5 -SURF 0x10 -mat 1 -refs 4 -59 5.96046447754e-08 1.0 -263 0.5 1.0 -281 0.500623703003 0.562729597092 -224 5.96046447754e-08 0.5 -SURF 0x10 -mat 1 -refs 4 -260 0.500000119209 -3.04425213926e-08 -280 0.500623703003 0.562729597092 -223 5.96046447754e-08 0.5 -60 5.96046447754e-08 0.0 -SURF 0x10 -mat 1 -refs 4 -224 5.96046447754e-08 0.5 -281 0.500623703003 0.562729597092 -261 0.500000119209 -3.04425213926e-08 -61 5.96046447754e-08 0.0 -SURF 0x10 -mat 1 -refs 3 -227 0.5 0.999999940395 -147 5.36441802979e-07 -1.19209289551e-07 -149 1.00001347065 1.01327896118e-06 -SURF 0x10 -mat 1 -refs 3 -149 1.00001347065 1.01327896118e-06 -148 5.36441802979e-07 -1.19209289551e-07 -228 0.5 0.999999940395 -SURF 0x10 -mat 1 -refs 3 -72 1.0 1.0 -227 0.5 0.999999940395 -149 1.00001347065 1.01327896118e-06 -SURF 0x10 -mat 1 -refs 3 -149 1.00001347065 1.01327896118e-06 -228 0.5 0.999999940395 -72 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -227 0.5 0.999999940395 -70 0.0 1.0 -147 5.36441802979e-07 -1.19209289551e-07 -SURF 0x10 -mat 1 -refs 3 -148 5.36441802979e-07 -1.19209289551e-07 -71 0.0 1.0 -228 0.5 0.999999940395 -SURF 0x10 -mat 1 -refs 3 -219 0.500000238419 1.00000059605 -74 -1.19209289551e-07 3.57627868652e-07 -76 0.999999761581 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 3 -77 0.999999761581 3.57627868652e-07 -75 -1.19209289551e-07 3.57627868652e-07 -220 0.500000238419 1.00000059605 -SURF 0x10 -mat 1 -refs 3 -62 1.00000023842 1.00000035763 -219 0.500000238419 1.00000059605 -76 0.999999761581 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 3 -77 0.999999761581 3.57627868652e-07 -220 0.500000238419 1.00000059605 -63 1.00000023842 1.00000035763 -SURF 0x10 -mat 1 -refs 3 -219 0.500000238419 1.00000059605 -60 1.78813934326e-07 1.00000035763 -74 -1.19209289551e-07 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 3 -75 -1.19209289551e-07 3.57627868652e-07 -61 1.78813934326e-07 1.00000035763 -220 0.500000238419 1.00000059605 -SURF 0x10 -mat 1 -refs 3 -223 0.499998956919 1.00000035763 -73 -3.57627868652e-07 4.17232513428e-07 -74 0.999999582767 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 3 -75 0.999999582767 3.57627868652e-07 -73 -3.57627868652e-07 4.17232513428e-07 -224 0.499998956919 1.00000035763 -SURF 0x10 -mat 1 -refs 3 -60 0.999999582767 1.00000035763 -223 0.499998956919 1.00000035763 -74 0.999999582767 3.57627868652e-07 -SURF 0x10 -mat 1 -refs 3 -75 0.999999582767 3.57627868652e-07 -224 0.499998956919 1.00000035763 -61 0.999999582767 1.00000035763 -SURF 0x10 -mat 1 -refs 3 -223 0.499998956919 1.00000035763 -59 -1.66893005371e-06 1.00000035763 -73 -3.57627868652e-07 4.17232513428e-07 -SURF 0x10 -mat 1 -refs 3 -73 -3.57627868652e-07 4.17232513428e-07 -59 -1.66893005371e-06 1.00000035763 -224 0.499998956919 1.00000035763 -SURF 0x10 -mat 1 -refs 3 -202 1.0 1.0 -241 0.499999880791 0.499999910593 -207 0.0 1.0 -SURF 0x10 -mat 1 -refs 3 -208 0.0 1.0 -242 0.499999880791 0.499999910593 -203 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -241 0.499999880791 0.499999910593 -209 0.0 0.0 -207 0.0 1.0 -SURF 0x10 -mat 1 -refs 3 -208 0.0 1.0 -210 0.0 0.0 -242 0.499999880791 0.499999910593 -SURF 0x10 -mat 1 -refs 3 -325 0.560789644718 -0.0398667193949 -16 0.0 0.0 -338 0.592417478561 0.436826646328 -SURF 0x10 -mat 1 -refs 3 -339 0.592417478561 0.436826646328 -16 0.0 0.0 -325 0.560789644718 -0.0398667193949 -SURF 0x10 -mat 1 -refs 3 -338 0.592417478561 0.436826646328 -324 1.10034954548 0.458175092936 -325 0.560789644718 -0.0398667193949 -SURF 0x10 -mat 1 -refs 3 -325 0.560789644718 -0.0398667193949 -324 1.10034954548 0.458175092936 -339 0.592417478561 0.436826646328 -SURF 0x10 -mat 1 -refs 3 -3 1.0 0.0 -325 0.560789644718 -0.0398667193949 -324 1.10034954548 0.458175092936 -SURF 0x10 -mat 1 -refs 3 -324 1.10034954548 0.458175092936 -338 0.592417478561 0.436826646328 -2 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -2 1.0 1.0 -339 0.592417478561 0.436826646328 -324 1.10034954548 0.458175092936 -SURF 0x10 -mat 1 -refs 4 -322 0.536163687706 0.963646709919 -14 0.0 1.0 -305 1.56593728207e-06 1.02257657051 -342 9.81325456451e-07 0.72461694479 -SURF 0x10 -mat 1 -refs 4 -306 1.56593728207e-06 1.02257657051 -15 0.0 1.0 -323 0.536163687706 0.963646709919 -343 9.81325456451e-07 0.72461694479 -SURF 0x10 -mat 1 -refs 4 -16 1.0 1.0 -322 0.536163687706 0.963646709919 -342 9.81325456451e-07 0.72461694479 -325 0.429186344147 0.532285869122 -SURF 0x10 -mat 1 -refs 4 -343 9.81325456451e-07 0.72461694479 -323 0.536163687706 0.963646709919 -16 1.0 1.0 -325 0.429186344147 0.532285869122 -SURF 0x10 -mat 1 -refs 4 -342 9.81325456451e-07 0.72461694479 -305 1.56593728207e-06 1.02257657051 -12 3.33786010742e-06 0.999997973442 -291 3.22759456139e-06 0.547514736652 -SURF 0x10 -mat 1 -refs 4 -13 3.33786010742e-06 0.999997973442 -306 1.56593728207e-06 1.02257657051 -343 9.81325456451e-07 0.72461694479 -292 3.22759456139e-06 0.547514736652 -SURF 0x10 -mat 1 -refs 4 -325 0.429186344147 0.532285869122 -342 9.81325456451e-07 0.72461694479 -291 3.22759456139e-06 0.547514736652 -3 3.45706939697e-06 -2.02655792236e-06 -SURF 0x10 -mat 1 -refs 4 -292 3.22759456139e-06 0.547514736652 -343 9.81325456451e-07 0.72461694479 -325 0.429186344147 0.532285869122 -3 3.45706939697e-06 -2.02655792236e-06 -SURF 0x10 -mat 1 -refs 4 -309 0.512685716152 1.01079308987 -6 -4.05311584473e-06 0.999997973442 -328 -1.99153896574e-06 1.01067709923 -344 -4.62828074888e-06 0.762097716331 -SURF 0x10 -mat 1 -refs 4 -329 -1.99153896574e-06 1.01067709923 -7 -4.05311584473e-06 0.999997973442 -310 0.512685716152 1.01079308987 -345 -4.62828074888e-06 0.762097716331 -SURF 0x10 -mat 1 -refs 4 -8 0.999996185303 0.999997973442 -309 0.512685716152 1.01079308987 -344 -4.62828074888e-06 0.762097716331 -330 0.559194147587 0.531713068485 -SURF 0x10 -mat 1 -refs 4 -345 -4.62828074888e-06 0.762097716331 -310 0.512685716152 1.01079308987 -9 0.999996185303 0.999997973442 -331 0.559194147587 0.531713068485 -SURF 0x10 -mat 1 -refs 4 -344 -4.62828074888e-06 0.762097716331 -328 -1.99153896574e-06 1.01067709923 -4 0.0 1.0 -295 -3.06638230541e-06 0.54010862112 -SURF 0x10 -mat 1 -refs 4 -5 0.0 1.0 -329 -1.99153896574e-06 1.01067709923 -345 -4.62828074888e-06 0.762097716331 -296 -3.06638230541e-06 0.54010862112 -SURF 0x10 -mat 1 -refs 4 -330 0.559194147587 0.531713068485 -344 -4.62828074888e-06 0.762097716331 -295 -3.06638230541e-06 0.54010862112 -3 -6.55651092529e-06 -2.02655792236e-06 -SURF 0x10 -mat 1 -refs 4 -296 -3.06638230541e-06 0.54010862112 -345 -4.62828074888e-06 0.762097716331 -331 0.559194147587 0.531713068485 -3 -6.55651092529e-06 -2.02655792236e-06 -SURF 0x10 -mat 1 -refs 4 -334 0.50432151556 1.00994110107 -0 -8.34465026855e-07 1.0 -297 -3.55542084662e-07 0.98369127512 -346 0.0234350245446 0.746605694294 -SURF 0x10 -mat 1 -refs 4 -298 -3.55542084662e-07 0.98369127512 -1 -8.34465026855e-07 1.0 -335 0.50432151556 1.00994110107 -347 0.0234350245446 0.746605694294 -SURF 0x10 -mat 1 -refs 4 -4 1.0 1.0 -334 0.50432151556 1.00994110107 -346 0.0234350245446 0.746605694294 -295 0.550307333469 0.538623511791 -SURF 0x10 -mat 1 -refs 4 -347 0.0234350245446 0.746605694294 -335 0.50432151556 1.00994110107 -5 1.0 1.0 -296 0.550307333469 0.538623511791 -SURF 0x10 -mat 1 -refs 4 -346 0.0234350245446 0.746605694294 -297 -3.55542084662e-07 0.98369127512 -2 0.0 1.0 -324 -1.32387228291e-07 0.516469597816 -SURF 0x10 -mat 1 -refs 4 -2 0.0 1.0 -298 -3.55542084662e-07 0.98369127512 -347 0.0234350245446 0.746605694294 -324 -1.32387228291e-07 0.516469597816 -SURF 0x10 -mat 1 -refs 4 -295 0.550307333469 0.538623511791 -346 0.0234350245446 0.746605694294 -324 -1.32387228291e-07 0.516469597816 -3 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -324 -1.32387228291e-07 0.516469597816 -347 0.0234350245446 0.746605694294 -296 0.550307333469 0.538623511791 -3 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -303 0.530565738678 1.01910400391 -10 2.38418579102e-07 0.999997973442 -319 -7.32834905648e-07 1.01228499413 -348 0.0253739226609 0.759291291237 -SURF 0x10 -mat 1 -refs 4 -320 -7.32834905648e-07 1.01228499413 -11 2.38418579102e-07 0.999997973442 -304 0.530565738678 1.01910400391 -349 0.0253739226609 0.759291291237 -SURF 0x10 -mat 1 -refs 4 -12 1.00000023842 0.999997973442 -303 0.530565738678 1.01910400391 -348 0.0253739226609 0.759291291237 -291 0.581568777561 0.538272321224 -SURF 0x10 -mat 1 -refs 4 -349 0.0253739226609 0.759291291237 -304 0.530565738678 1.01910400391 -13 1.00000023842 0.999997973442 -292 0.581568777561 0.538272321224 -SURF 0x10 -mat 1 -refs 4 -348 0.0253739226609 0.759291291237 -319 -7.32834905648e-07 1.01228499413 -8 -1.78813934326e-06 0.999997973442 -330 -1.72436637058e-06 0.53618144989 -SURF 0x10 -mat 1 -refs 4 -9 -1.78813934326e-06 0.999997973442 -320 -7.32834905648e-07 1.01228499413 -349 0.0253739226609 0.759291291237 -331 -1.72436637058e-06 0.53618144989 -SURF 0x10 -mat 1 -refs 4 -291 0.581568777561 0.538272321224 -348 0.0253739226609 0.759291291237 -330 -1.72436637058e-06 0.53618144989 -3 -1.78813934326e-06 -2.02655792236e-06 -SURF 0x10 -mat 1 -refs 4 -331 -1.72436637058e-06 0.53618144989 -349 0.0253739226609 0.759291291237 -292 0.581568777561 0.538272321224 -3 -1.78813934326e-06 -2.02655792236e-06 -SURF 0x10 -mat 1 -refs 3 -340 1.01995933056 0.462798833847 -25 0.0 0.0 -214 0.0 1.0 -SURF 0x10 -mat 1 -refs 3 -214 0.0 1.0 -25 0.0 0.0 -341 1.01995933056 0.462798833847 -SURF 0x10 -mat 1 -refs 3 -122 1.0 1.0 -340 1.01995933056 0.462798833847 -214 0.0 1.0 -SURF 0x10 -mat 1 -refs 3 -214 0.0 1.0 -341 1.01995933056 0.462798833847 -122 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -340 1.01995933056 0.462798833847 -144 1.0 0.0 -25 0.0 0.0 -SURF 0x10 -mat 1 -refs 3 -25 0.0 0.0 -144 1.0 0.0 -341 1.01995933056 0.462798833847 -SURF 0x10 -mat 1 -refs 4 -321 0.483414173126 -0.0173592474312 -2 0.0 0.0 -338 -0.0440843254328 0.533447682858 -350 0.434275716543 0.357974231243 -SURF 0x10 -mat 1 -refs 4 -339 -0.0440843254328 0.533447682858 -2 0.0 0.0 -321 0.483414173126 -0.0173592474312 -351 0.434275716543 0.357974231243 -SURF 0x10 -mat 1 -refs 4 -122 1.0 0.0 -321 0.483414173126 -0.0173592474312 -350 0.434275716543 0.357974231243 -340 0.954562008381 0.507933557034 -SURF 0x10 -mat 1 -refs 4 -351 0.434275716543 0.357974231243 -321 0.483414173126 -0.0173592474312 -122 1.0 0.0 -341 0.954562008381 0.507933557034 -SURF 0x10 -mat 1 -refs 4 -350 0.434275716543 0.357974231243 -338 -0.0440843254328 0.533447682858 -16 0.0 1.0 -286 0.491140902042 1.0263531208 -SURF 0x10 -mat 1 -refs 4 -16 0.0 1.0 -339 -0.0440843254328 0.533447682858 -351 0.434275716543 0.357974231243 -286 0.491140902042 1.0263531208 -SURF 0x10 -mat 1 -refs 4 -340 0.954562008381 0.507933557034 -350 0.434275716543 0.357974231243 -286 0.491140902042 1.0263531208 -144 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -286 0.491140902042 1.0263531208 -351 0.434275716543 0.357974231243 -341 0.954562008381 0.507933557034 -144 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -282 0.460907906294 1.00219893456 -26 0.0 1.19209289551e-07 -21 1.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -22 1.0 5.96046447754e-08 -27 0.0 1.19209289551e-07 -283 0.460907906294 1.00219893456 -SURF 0x10 -mat 1 -refs 3 -138 1.0 1.0 -282 0.460907906294 1.00219893456 -21 1.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -22 1.0 5.96046447754e-08 -283 0.460907906294 1.00219893456 -139 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -282 0.460907906294 1.00219893456 -140 -1.19209289551e-07 1.00000011921 -26 0.0 1.19209289551e-07 -SURF 0x10 -mat 1 -refs 3 -27 0.0 1.19209289551e-07 -141 -1.19209289551e-07 1.00000011921 -283 0.460907906294 1.00219893456 -SURF 0x10 -mat 1 -refs 4 -286 0.887036204338 0.491141051054 -144 1.0 1.0 -307 0.565110385418 1.00319027901 -352 0.393864154816 0.49230197072 -SURF 0x10 -mat 1 -refs 4 -308 0.565110385418 1.00319027901 -144 1.0 1.0 -286 0.887036204338 0.491141051054 -353 0.393864154816 0.49230197072 -SURF 0x10 -mat 1 -refs 4 -16 1.0 0.0 -286 0.887036204338 0.491141051054 -352 0.393864154816 0.49230197072 -322 0.572516739368 0.0050320844166 -SURF 0x10 -mat 1 -refs 4 -353 0.393864154816 0.49230197072 -286 0.887036204338 0.491141051054 -16 1.0 0.0 -323 0.572516739368 0.0050320844166 -SURF 0x10 -mat 1 -refs 4 -352 0.393864154816 0.49230197072 -307 0.565110385418 1.00319027901 -142 -2.38418579102e-07 0.999999701977 -326 -0.038295507431 0.485841721296 -SURF 0x10 -mat 1 -refs 4 -143 -2.38418579102e-07 0.999999701977 -308 0.565110385418 1.00319027901 -353 0.393864154816 0.49230197072 -327 -0.038295507431 0.485841721296 -SURF 0x10 -mat 1 -refs 4 -322 0.572516739368 0.0050320844166 -352 0.393864154816 0.49230197072 -326 -0.038295507431 0.485841721296 -14 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -327 -0.038295507431 0.485841721296 -353 0.393864154816 0.49230197072 -323 0.572516739368 0.0050320844166 -15 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -326 0.923269450665 0.485841810703 -142 1.00000059605 0.999999701977 -315 0.462623268366 0.995265126228 -354 0.280570209026 0.473311334848 -SURF 0x10 -mat 1 -refs 4 -316 0.462623268366 0.995265126228 -143 1.00000059605 0.999999701977 -327 0.923269450665 0.485841810703 -355 0.280570209026 0.473311334848 -SURF 0x10 -mat 1 -refs 4 -14 1.0 0.0 -326 0.923269450665 0.485841810703 -354 0.280570209026 0.473311334848 -305 0.476901680231 -0.00449139624834 -SURF 0x10 -mat 1 -refs 4 -355 0.280570209026 0.473311334848 -327 0.923269450665 0.485841810703 -15 1.0 0.0 -306 0.476901680231 -0.00449139624834 -SURF 0x10 -mat 1 -refs 4 -354 0.280570209026 0.473311334848 -315 0.462623268366 0.995265126228 -140 5.96046447754e-07 0.999999701977 -311 -0.136368900537 0.469962507486 -SURF 0x10 -mat 1 -refs 4 -141 5.96046447754e-07 0.999999701977 -316 0.462623268366 0.995265126228 -355 0.280570209026 0.473311334848 -312 -0.136368900537 0.469962507486 -SURF 0x10 -mat 1 -refs 4 -305 0.476901680231 -0.00449139624834 -354 0.280570209026 0.473311334848 -311 -0.136368900537 0.469962507486 -12 1.60932540894e-06 -5.96046447754e-07 -SURF 0x10 -mat 1 -refs 4 -312 -0.136368900537 0.469962507486 -355 0.280570209026 0.473311334848 -306 0.476901680231 -0.00449139624834 -13 1.60932540894e-06 -5.96046447754e-07 -SURF 0x10 -mat 1 -refs 4 -311 1.36615371704 0.469962209463 -140 1.00000023842 0.999999701977 -282 0.538962185383 0.995363295078 -356 0.555465102196 0.467977374792 -SURF 0x10 -mat 1 -refs 4 -283 0.538962185383 0.995363295078 -141 1.00000023842 0.999999701977 -312 1.36615371704 0.469962209463 -357 0.555465102196 0.467977374792 -SURF 0x10 -mat 1 -refs 4 -12 1.00000035763 -5.96046447754e-07 -311 1.36615371704 0.469962209463 -356 0.555465102196 0.467977374792 -303 0.542687773705 -0.00500043900684 -SURF 0x10 -mat 1 -refs 4 -357 0.555465102196 0.467977374792 -312 1.36615371704 0.469962209463 -13 1.00000035763 -5.96046447754e-07 -304 0.542687773705 -0.00500043900684 -SURF 0x10 -mat 1 -refs 4 -356 0.555465102196 0.467977374792 -282 0.538962185383 0.995363295078 -138 0.0 1.0 -317 0.0773486793041 0.477716207504 -SURF 0x10 -mat 1 -refs 4 -139 0.0 1.0 -283 0.538962185383 0.995363295078 -357 0.555465102196 0.467977374792 -318 0.0773486793041 0.477716207504 -SURF 0x10 -mat 1 -refs 4 -303 0.542687773705 -0.00500043900684 -356 0.555465102196 0.467977374792 -317 0.0773486793041 0.477716207504 -10 4.76837158203e-07 -5.96046447754e-07 -SURF 0x10 -mat 1 -refs 4 -318 0.0773486793041 0.477716207504 -357 0.555465102196 0.467977374792 -304 0.542687773705 -0.00500043900684 -11 4.76837158203e-07 -5.96046447754e-07 -SURF 0x10 -mat 1 -refs 4 -317 1.14359176159 0.477716207504 -138 1.0 1.0 -313 0.509185254574 0.995261788368 -358 0.400883287191 0.46147146821 -SURF 0x10 -mat 1 -refs 4 -314 0.509185254574 0.995261788368 -139 1.0 1.0 -318 1.14359176159 0.477716207504 -359 0.400883287191 0.46147146821 -SURF 0x10 -mat 1 -refs 4 -10 0.999999701977 -5.96046447754e-07 -317 1.14359176159 0.477716207504 -358 0.400883287191 0.46147146821 -319 0.512810409069 -0.00478910049424 -SURF 0x10 -mat 1 -refs 4 -359 0.400883287191 0.46147146821 -318 1.14359176159 0.477716207504 -11 0.999999701977 -5.96046447754e-07 -320 0.512810409069 -0.00478910049424 -SURF 0x10 -mat 1 -refs 4 -358 0.400883287191 0.46147146821 -313 0.509185254574 0.995261788368 -136 0.0 1.0 -301 -0.0093521727249 0.456389188766 -SURF 0x10 -mat 1 -refs 4 -137 0.0 1.0 -314 0.509185254574 0.995261788368 -359 0.400883287191 0.46147146821 -302 -0.0093521727249 0.456389188766 -SURF 0x10 -mat 1 -refs 4 -319 0.512810409069 -0.00478910049424 -358 0.400883287191 0.46147146821 -301 -0.0093521727249 0.456389188766 -8 -3.57627868652e-07 -5.96046447754e-07 -SURF 0x10 -mat 1 -refs 4 -302 -0.0093521727249 0.456389188766 -359 0.400883287191 0.46147146821 -320 0.512810409069 -0.00478910049424 -9 -3.57627868652e-07 -5.96046447754e-07 -SURF 0x10 -mat 1 -refs 4 -301 0.97952067852 0.456389218569 -136 1.0 1.0 -287 0.482649326324 0.994964659214 -360 0.28315910697 0.457658499479 -SURF 0x10 -mat 1 -refs 4 -288 0.482649326324 0.994964659214 -137 1.0 1.0 -302 0.97952067852 0.456389218569 -361 0.28315910697 0.457658499479 -SURF 0x10 -mat 1 -refs 4 -8 0.999998986721 -5.96046447754e-07 -301 0.97952067852 0.456389218569 -360 0.28315910697 0.457658499479 -309 0.489325582981 -0.00528151867911 -SURF 0x10 -mat 1 -refs 4 -361 0.28315910697 0.457658499479 -302 0.97952067852 0.456389218569 -9 0.999998986721 -5.96046447754e-07 -310 0.489325582981 -0.00528151867911 -SURF 0x10 -mat 1 -refs 4 -360 0.28315910697 0.457658499479 -287 0.482649326324 0.994964659214 -132 -4.76837158203e-07 1.0 -293 -0.088741004467 0.472047656775 -SURF 0x10 -mat 1 -refs 4 -133 -4.76837158203e-07 1.0 -288 0.482649326324 0.994964659214 -361 0.28315910697 0.457658499479 -294 -0.088741004467 0.472047656775 -SURF 0x10 -mat 1 -refs 4 -309 0.489325582981 -0.00528151867911 -360 0.28315910697 0.457658499479 -293 -0.088741004467 0.472047656775 -6 -1.19209289551e-06 -5.96046447754e-07 -SURF 0x10 -mat 1 -refs 4 -294 -0.088741004467 0.472047656775 -361 0.28315910697 0.457658499479 -310 0.489325582981 -0.00528151867911 -7 -1.19209289551e-06 -5.96046447754e-07 -SURF 0x10 -mat 1 -refs 4 -293 0.770777106285 0.472047120333 -132 0.999999761581 1.0 -299 0.453351974487 0.994626522064 -362 0.153510525823 0.45731061697 -SURF 0x10 -mat 1 -refs 4 -300 0.453351974487 0.994626522064 -133 0.999999761581 1.0 -294 0.770777106285 0.472047120333 -363 0.153510525823 0.45731061697 -SURF 0x10 -mat 1 -refs 4 -6 0.999997854233 -5.96046447754e-07 -293 0.770777106285 0.472047120333 -362 0.153510525823 0.45731061697 -328 0.463695436716 -0.00506257079542 -SURF 0x10 -mat 1 -refs 4 -363 0.153510525823 0.45731061697 -294 0.770777106285 0.472047120333 -7 0.999997854233 -5.96046447754e-07 -329 0.463695436716 -0.00506257079542 -SURF 0x10 -mat 1 -refs 4 -362 0.153510525823 0.45731061697 -299 0.453351974487 0.994626522064 -128 -5.96046447754e-07 1.0 -289 -0.23376493156 0.454615592957 -SURF 0x10 -mat 1 -refs 4 -129 -5.96046447754e-07 1.0 -300 0.453351974487 0.994626522064 -363 0.153510525823 0.45731061697 -290 -0.23376493156 0.454615592957 -SURF 0x10 -mat 1 -refs 4 -328 0.463695436716 -0.00506257079542 -362 0.153510525823 0.45731061697 -289 -0.23376493156 0.454615592957 -4 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -290 -0.23376493156 0.454615592957 -363 0.153510525823 0.45731061697 -329 0.463695436716 -0.00506257079542 -5 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -336 0.0708863884211 0.471222609282 -0 -8.34465026855e-07 0.0 -334 0.523856937885 -0.00512412143871 -364 0.584350764751 0.457052767277 -SURF 0x10 -mat 1 -refs 4 -335 0.523856937885 -0.00512412143871 -1 -8.34465026855e-07 0.0 -337 0.0708863884211 0.471222609282 -365 0.584350764751 0.457052767277 -SURF 0x10 -mat 1 -refs 4 -123 0.0 1.0 -336 0.0708863884211 0.471222609282 -364 0.584350764751 0.457052767277 -332 0.532192349434 0.994375824928 -SURF 0x10 -mat 1 -refs 4 -365 0.584350764751 0.457052767277 -337 0.0708863884211 0.471222609282 -124 0.0 1.0 -333 0.532192349434 0.994375824928 -SURF 0x10 -mat 1 -refs 4 -364 0.584350764751 0.457052767277 -334 0.523856937885 -0.00512412143871 -4 1.0 0.0 -289 1.29220366478 0.454615622759 -SURF 0x10 -mat 1 -refs 4 -5 1.0 0.0 -335 0.523856937885 -0.00512412143871 -365 0.584350764751 0.457052767277 -290 1.29220366478 0.454615622759 -SURF 0x10 -mat 1 -refs 4 -332 0.532192349434 0.994375824928 -364 0.584350764751 0.457052767277 -289 1.29220366478 0.454615622759 -128 0.999999582767 1.0 -SURF 0x10 -mat 1 -refs 4 -290 1.29220366478 0.454615622759 -365 0.584350764751 0.457052767277 -333 0.532192349434 0.994375824928 -129 0.999999582767 1.0 -SURF 0x10 -mat 1 -refs 4 -336 1.10028839111 0.471222758293 -123 1.0 1.0 -284 0.410562515259 1.00379860401 -366 0.421781182289 0.481428980827 -SURF 0x10 -mat 1 -refs 4 -285 0.410562515259 1.00379860401 -124 1.0 1.0 -337 1.10028839111 0.471222758293 -367 0.421781182289 0.481428980827 -SURF 0x10 -mat 1 -refs 4 -0 1.0 0.0 -336 1.10028839111 0.471222758293 -366 0.421781182289 0.481428980827 -297 0.421258598566 0.00707953982055 -SURF 0x10 -mat 1 -refs 4 -367 0.421781182289 0.481428980827 -337 1.10028839111 0.471222758293 -1 1.0 0.0 -298 0.421258598566 0.00707953982055 -SURF 0x10 -mat 1 -refs 4 -366 0.421781182289 0.481428980827 -284 0.410562515259 1.00379860401 -122 0.0 0.999999701977 -321 0.101958267391 0.483414381742 -SURF 0x10 -mat 1 -refs 4 -122 0.0 0.999999701977 -285 0.410562515259 1.00379860401 -367 0.421781182289 0.481428980827 -321 0.101958267391 0.483414381742 -SURF 0x10 -mat 1 -refs 4 -297 0.421258598566 0.00707953982055 -366 0.421781182289 0.481428980827 -321 0.101958267391 0.483414381742 -2 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -321 0.101958267391 0.483414381742 -367 0.421781182289 0.481428980827 -298 0.421258598566 0.00707953982055 -2 0.0 0.0 -SURF 0x10 -mat 1 -refs 3 -307 0.436180233955 0.998370051384 -25 -7.15255737305e-07 0.0 -23 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -24 1.0 0.0 -25 -7.15255737305e-07 0.0 -308 0.436180233955 0.998370051384 -SURF 0x10 -mat 1 -refs 3 -142 0.999999344349 1.00000011921 -307 0.436180233955 0.998370051384 -23 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -24 1.0 0.0 -308 0.436180233955 0.998370051384 -143 0.999999344349 1.00000011921 -SURF 0x10 -mat 1 -refs 3 -307 0.436180233955 0.998370051384 -144 -3.57627868652e-07 1.0 -25 -7.15255737305e-07 0.0 -SURF 0x10 -mat 1 -refs 3 -25 -7.15255737305e-07 0.0 -144 -3.57627868652e-07 1.0 -308 0.436180233955 0.998370051384 -SURF 0x10 -mat 1 -refs 3 -315 0.53410834074 1.00237131119 -23 0.0 0.0 -26 0.999999940395 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -27 0.999999940395 5.96046447754e-08 -24 0.0 0.0 -316 0.53410834074 1.00237131119 -SURF 0x10 -mat 1 -refs 3 -140 0.999999821186 1.00000011921 -315 0.53410834074 1.00237131119 -26 0.999999940395 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -27 0.999999940395 5.96046447754e-08 -316 0.53410834074 1.00237131119 -141 0.999999821186 1.00000011921 -SURF 0x10 -mat 1 -refs 3 -315 0.53410834074 1.00237131119 -142 -1.19209289551e-07 1.00000011921 -23 0.0 0.0 -SURF 0x10 -mat 1 -refs 3 -24 0.0 0.0 -143 -1.19209289551e-07 1.00000011921 -316 0.53410834074 1.00237131119 -SURF 0x10 -mat 1 -refs 3 -313 0.48910933733 1.00208163261 -21 0.0 5.96046447754e-08 -19 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -20 1.0 0.0 -22 0.0 5.96046447754e-08 -314 0.48910933733 1.00208163261 -SURF 0x10 -mat 1 -refs 3 -136 1.0 1.0 -313 0.48910933733 1.00208163261 -19 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -20 1.0 0.0 -314 0.48910933733 1.00208163261 -137 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -313 0.48910933733 1.00208163261 -138 0.0 1.0 -21 0.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -22 0.0 5.96046447754e-08 -139 0.0 1.0 -314 0.48910933733 1.00208163261 -SURF 0x10 -mat 1 -refs 3 -287 0.513851225376 1.00203537941 -19 0.0 0.0 -134 1.00000023842 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -135 1.00000023842 5.96046447754e-08 -20 0.0 0.0 -288 0.513851225376 1.00203537941 -SURF 0x10 -mat 1 -refs 3 -132 1.00000023842 1.0 -287 0.513851225376 1.00203537941 -134 1.00000023842 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -135 1.00000023842 5.96046447754e-08 -288 0.513851225376 1.00203537941 -133 1.00000023842 1.0 -SURF 0x10 -mat 1 -refs 3 -287 0.513851225376 1.00203537941 -136 0.0 1.0 -19 0.0 0.0 -SURF 0x10 -mat 1 -refs 3 -20 0.0 0.0 -137 0.0 1.0 -288 0.513851225376 1.00203537941 -SURF 0x10 -mat 1 -refs 3 -299 0.540448248386 1.00201141834 -134 2.38418579102e-07 5.96046447754e-08 -130 1.00000011921 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -131 1.00000011921 5.96046447754e-08 -135 2.38418579102e-07 5.96046447754e-08 -300 0.540448248386 1.00201141834 -SURF 0x10 -mat 1 -refs 3 -128 1.00000023842 1.0 -299 0.540448248386 1.00201141834 -130 1.00000011921 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -131 1.00000011921 5.96046447754e-08 -300 0.540448248386 1.00201141834 -129 1.00000023842 1.0 -SURF 0x10 -mat 1 -refs 3 -299 0.540448248386 1.00201141834 -132 2.38418579102e-07 1.0 -134 2.38418579102e-07 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -135 2.38418579102e-07 5.96046447754e-08 -133 2.38418579102e-07 1.0 -300 0.540448248386 1.00201141834 -SURF 0x10 -mat 1 -refs 3 -332 0.469066590071 1.00198101997 -130 5.96046447754e-08 5.96046447754e-08 -125 1.00000095367 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -126 1.00000095367 5.96046447754e-08 -131 5.96046447754e-08 5.96046447754e-08 -333 0.469066590071 1.00198101997 -SURF 0x10 -mat 1 -refs 3 -123 1.0 1.0 -332 0.469066590071 1.00198101997 -125 1.00000095367 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -126 1.00000095367 5.96046447754e-08 -333 0.469066590071 1.00198101997 -124 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -332 0.469066590071 1.00198101997 -128 4.17232513428e-07 1.0 -130 5.96046447754e-08 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -131 5.96046447754e-08 5.96046447754e-08 -129 4.17232513428e-07 1.0 -333 0.469066590071 1.00198101997 -SURF 0x10 -mat 1 -refs 3 -284 0.589865088463 0.998712778091 -125 0.0 5.96046447754e-08 -127 1.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -127 1.0 5.96046447754e-08 -126 0.0 5.96046447754e-08 -285 0.589865088463 0.998712778091 -SURF 0x10 -mat 1 -refs 3 -122 1.0 1.00000011921 -284 0.589865088463 0.998712778091 -127 1.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -127 1.0 5.96046447754e-08 -285 0.589865088463 0.998712778091 -122 1.0 1.00000011921 -SURF 0x10 -mat 1 -refs 3 -284 0.589865088463 0.998712778091 -123 0.0 1.0 -125 0.0 5.96046447754e-08 -SURF 0x10 -mat 1 -refs 3 -126 0.0 5.96046447754e-08 -124 0.0 1.0 -285 0.589865088463 0.998712778091 -kids 0 -OBJECT poly -name "Canopy" -data 6 -Canopy -crease 30.000000 -numvert 106 -0.020724 0.042588 0.026433 -0.020724 0.042588 -0.026433 -0.009439 0.02391 0.036043 -0.009439 0.02391 -0.036043 --0.003442 0.001082 0.037102 --0.003442 0.001082 -0.037102 -0.031287 0.0622 0 -0.028251 0.055388 0.018563 -0.028251 0.055388 -0.018563 --0.001234 0.003703 0 --0.072704 -0.000229 0 --0.030111 1.8e-05 0 --0.080522 0.021943 0.015552 --0.080522 0.021943 -0.015552 --0.081613 0.026402 0 --0.070763 -0.000297 0.03506 --0.070763 -0.000297 -0.03506 --0.076754 0.01342 0.02946 --0.076754 0.01342 -0.02946 --0.028936 0.045846 0.015211 --0.028936 0.045846 -0.015211 --0.029258 0.049495 0 --0.030098 0.000633 0.03653 --0.030098 0.000633 -0.03653 --0.029279 0.018666 0.036077 --0.029279 0.018666 -0.036077 --0.029061 0.034806 0.027223 --0.029061 0.034806 -0.027223 --0.051457 -0.000693 0 --0.050341 0.000317 0.036096 --0.050341 0.000317 -0.036096 -0.015147 0.03048 0.010228 -0.015147 0.03048 -0.010228 -0.011103 0.023781 0.014521 -0.011103 0.023781 -0.014521 -0.015176 0.033087 0.03139 -0.015176 0.033087 -0.03139 -0.003285 0.012416 0.036828 -0.003285 0.012416 -0.036828 --0.009009 0.021655 0.036093 --0.009009 0.021655 -0.036093 --0.003122 0.001134 0.019806 --0.003122 0.001134 -0.019806 --0.016021 0.000754 0.03706 --0.016021 0.000754 -0.03706 --0.016248 6e-05 0 -0.030256 0.059126 0.009164 -0.030256 0.059126 -0.009164 -0.002226 0.056344 0 --0.002981 0.03974 0.027213 --0.002981 0.03974 -0.027213 -0.024419 0.048324 0.022238 -0.024419 0.048324 -0.022238 -0.001028 0.051892 0.017179 -0.001028 0.051892 -0.017179 --0.055819 0.034078 0.015563 --0.055819 0.034078 -0.015563 --0.05673 0.037646 0 --0.053997 0.023871 0.028393 --0.053997 0.023871 -0.028393 --0.050228 0.008841 0.036212 --0.050228 0.008841 -0.036212 --0.078885 0.017531 0.02281 --0.078885 0.017531 -0.02281 --0.028992 0.040522 0.021312 --0.028992 0.040522 -0.021312 --0.078052 0.010603 0.00836 --0.078052 0.010603 -0.00836 --0.081423 0.02423 0.007562 --0.081423 0.02423 -0.007562 --0.029104 0.047899 0.007653 --0.029104 0.047899 -0.007653 --0.030111 2.3e-05 0.018878 --0.030111 2.3e-05 -0.018878 --0.030722 0.009173 0.037019 --0.030722 0.009173 -0.037019 --0.0722 -0.000805 0.018351 --0.0722 -0.000805 -0.018351 --0.074712 0.006444 0.032289 --0.074712 0.006444 -0.032289 --0.029163 0.026861 0.031817 --0.029163 0.026861 -0.031817 -0.023504 0.0447 0 -0.007169 0.017217 0.025606 -0.007169 0.017217 -0.025606 --0.080608 0.017108 0 --0.077032 0.007971 0.020598 --0.077032 0.007971 -0.020598 --0.051457 -0.000689 0.01853 --0.051457 -0.000689 -0.01853 --0.052634 0.016463 0.032444 --0.052634 0.016463 -0.032444 --0.056318 0.036078 0.007824 --0.056318 0.036078 -0.007824 --0.054937 0.029154 0.022101 --0.054937 0.029154 -0.022101 --0.000901 0.046029 0.022326 --0.000901 0.046029 -0.022326 -0.001708 0.054378 0.008708 -0.001708 0.054378 -0.008708 --0.016248 6.4e-05 0.01916 --0.016248 6.4e-05 -0.01916 --0.012609 0.01092 0.037317 --0.012609 0.01092 -0.037317 --0.005944 0.030845 0.031775 --0.005944 0.030845 -0.031775 -numsurf 112 -SURF 0x10 -mat 2 -refs 3 -74 0.5 -2.99629245026e-11 -24 0.0 0.0 -60 0.499999970198 0.5 -SURF 0x10 -mat 2 -refs 3 -60 0.499999970198 0.5 -29 1.0 0.5 -74 0.5 -2.99629245026e-11 -SURF 0x10 -mat 2 -refs 3 -22 1.0 0.0 -74 0.5 -2.99629245026e-11 -29 1.0 0.5 -SURF 0x10 -mat 2 -refs 3 -29 1.0 0.5 -60 0.499999970198 0.5 -15 1.0 1.0 -SURF 0x10 -mat 2 -refs 3 -75 0.5 -2.99629245026e-11 -23 1.0 0.0 -30 1.0 0.5 -SURF 0x10 -mat 2 -refs 3 -30 1.0 0.5 -61 0.499999970198 0.5 -75 0.5 -2.99629245026e-11 -SURF 0x10 -mat 2 -refs 3 -25 0.0 0.0 -75 0.5 -2.99629245026e-11 -61 0.499999970198 0.5 -SURF 0x10 -mat 2 -refs 3 -61 0.499999970198 0.5 -30 1.0 0.5 -16 1.0 1.0 -SURF 0x10 -mat 2 -refs 3 -31 0.5 0.5 -7 1.0 1.0 -51 1.0 0.5 -SURF 0x10 -mat 2 -refs 3 -51 1.0 0.5 -33 0.5 -6.82619782921e-09 -31 0.5 0.5 -SURF 0x10 -mat 2 -refs 3 -9 0.0 0.0 -31 0.5 0.5 -33 0.5 -6.82619782921e-09 -SURF 0x10 -mat 2 -refs 3 -51 1.0 0.5 -0 1.0 0.0 -33 0.5 -6.82619782921e-09 -SURF 0x10 -mat 2 -refs 3 -32 0.5 0.5 -9 0.0 0.0 -34 0.5 -6.82619782921e-09 -SURF 0x10 -mat 2 -refs 3 -34 0.5 -6.82619782921e-09 -52 1.0 0.5 -32 0.5 0.5 -SURF 0x10 -mat 2 -refs 3 -8 1.0 1.0 -32 0.5 0.5 -52 1.0 0.5 -SURF 0x10 -mat 2 -refs 3 -52 1.0 0.5 -34 0.5 -6.82619782921e-09 -1 1.0 0.0 -SURF 0x10 -mat 2 -refs 4 -31 0.5 -2.76792433418e-09 -9 0.0 0.0 -32 0.5 -2.76792433418e-09 -82 0.707208931446 0.707208931446 -SURF 0x10 -mat 2 -refs 4 -7 1.0 0.0 -31 0.5 -2.76792433418e-09 -82 0.707208931446 0.707208931446 -46 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -82 0.707208931446 0.707208931446 -32 0.5 -2.76792433418e-09 -8 1.0 0.0 -47 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -46 1.0 0.5 -82 0.707208931446 0.707208931446 -47 1.0 0.5 -6 1.0 1.0 -SURF 0x10 -mat 2 -refs 4 -35 0.5 0.0 -2 0.0 0.0 -37 0.5 0.0 -83 0.00295890239067 0.0 -SURF 0x10 -mat 2 -refs 4 -0 1.0 0.0 -35 0.5 0.0 -83 0.00295890239067 0.0 -33 0.5 0.0 -SURF 0x10 -mat 2 -refs 4 -83 0.00295890239067 0.0 -37 0.5 0.0 -4 1.0 0.0 -41 0.5 0.0 -SURF 0x10 -mat 2 -refs 4 -33 0.5 0.0 -83 0.00295890239067 0.0 -41 0.5 0.0 -9 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -38 1.0 0.5 -3 1.0 1.0 -36 1.0 0.5 -84 1.0 0.997041106224 -SURF 0x10 -mat 2 -refs 4 -5 1.0 0.0 -38 1.0 0.5 -84 1.0 0.997041106224 -42 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -84 1.0 0.997041106224 -36 1.0 0.5 -1 1.0 0.0 -34 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -42 1.0 0.5 -84 1.0 0.997041106224 -34 1.0 0.5 -9 1.0 1.0 -SURF 0x10 -mat 2 -refs 4 -68 1.0 0.5 -14 1.0 0.0 -69 1.0 0.5 -85 0.68388313055 0.0 -SURF 0x10 -mat 2 -refs 4 -12 1.0 1.0 -68 1.0 0.5 -85 0.68388313055 0.0 -66 0.5 0.5 -SURF 0x10 -mat 2 -refs 4 -85 0.68388313055 0.0 -69 1.0 0.5 -13 1.0 1.0 -67 0.5 0.5 -SURF 0x10 -mat 2 -refs 4 -66 0.5 0.5 -85 0.68388313055 0.0 -67 0.5 0.5 -10 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -66 0.5 0.0 -10 0.0 0.0 -76 0.5 0.5 -86 0.685612916946 0.0183454230428 -SURF 0x10 -mat 2 -refs 4 -12 1.0 0.0 -66 0.5 0.0 -86 0.685612916946 0.0183454230428 -62 1.0 0.0 -SURF 0x10 -mat 2 -refs 4 -86 0.685612916946 0.0183454230428 -76 0.5 0.5 -15 1.0 1.0 -78 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -62 1.0 0.0 -86 0.685612916946 0.0183454230428 -78 1.0 0.5 -17 1.0 0.0 -SURF 0x10 -mat 2 -refs 4 -63 1.0 0.499999910593 -18 1.0 1.0 -79 1.0 1.0 -87 0.685612976551 0.685612976551 -SURF 0x10 -mat 2 -refs 4 -13 1.0 0.0 -63 1.0 0.499999910593 -87 0.685612976551 0.685612976551 -67 0.5 1.90149600472e-15 -SURF 0x10 -mat 2 -refs 4 -87 0.685612976551 0.685612976551 -79 1.0 1.0 -16 1.0 1.0 -77 0.5 0.5 -SURF 0x10 -mat 2 -refs 4 -67 0.5 1.90149600472e-15 -87 0.685612976551 0.685612976551 -77 0.5 0.5 -10 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -28 0.5 0.5 -11 1.0 1.0 -72 1.0 0.5 -88 0.499999970198 0.49067774415 -SURF 0x10 -mat 2 -refs 4 -10 0.0 0.0 -28 0.5 0.5 -88 0.499999970198 0.49067774415 -76 5.07412503602e-15 5.07412503602e-15 -SURF 0x10 -mat 2 -refs 4 -88 0.499999970198 0.49067774415 -72 1.0 0.5 -22 1.0 0.0 -29 0.499999970198 -7.72299557639e-10 -SURF 0x10 -mat 2 -refs 4 -76 5.07412503602e-15 5.07412503602e-15 -88 0.499999970198 0.49067774415 -29 0.499999970198 -7.72299557639e-10 -15 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -77 0.5 5.07412503602e-15 -16 1.0 0.0 -30 1.0 -7.72299557639e-10 -89 1.0 0.49067774415 -SURF 0x10 -mat 2 -refs 4 -10 0.0 0.0 -77 0.5 5.07412503602e-15 -89 1.0 0.49067774415 -28 0.5 0.5 -SURF 0x10 -mat 2 -refs 4 -89 1.0 0.49067774415 -30 1.0 -7.72299557639e-10 -23 1.0 0.0 -73 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -28 0.5 0.5 -89 1.0 0.49067774415 -73 1.0 0.5 -11 1.0 1.0 -SURF 0x10 -mat 2 -refs 4 -58 0.5 0.5 -17 1.0 1.0 -78 1.0 0.5 -90 0.472009927034 0.472009927034 -SURF 0x10 -mat 2 -refs 4 -26 0.0 0.0 -58 0.5 0.5 -90 0.472009927034 0.472009927034 -80 3.74302864259e-08 3.74302864259e-08 -SURF 0x10 -mat 2 -refs 4 -90 0.472009927034 0.472009927034 -78 1.0 0.5 -15 1.0 0.0 -60 0.5 2.5444238716e-08 -SURF 0x10 -mat 2 -refs 4 -80 3.74302864259e-08 3.74302864259e-08 -90 0.472009927034 0.472009927034 -60 0.5 2.5444238716e-08 -24 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -81 0.499999970198 3.74302864259e-08 -25 1.0 0.0 -61 1.0 2.5444238716e-08 -91 0.97979593277 0.472009927034 -SURF 0x10 -mat 2 -refs 4 -27 0.0 0.0 -81 0.499999970198 3.74302864259e-08 -91 0.97979593277 0.472009927034 -59 0.499999910593 0.5 -SURF 0x10 -mat 2 -refs 4 -91 0.97979593277 0.472009927034 -61 1.0 2.5444238716e-08 -16 1.0 0.0 -79 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -59 0.499999910593 0.5 -91 0.97979593277 0.472009927034 -79 1.0 0.5 -18 1.0 1.0 -SURF 0x10 -mat 2 -refs 4 -57 0.5 0.5 -14 1.0 1.0 -68 1.0 0.5 -92 0.495653748512 0.483700931072 -SURF 0x10 -mat 2 -refs 4 -21 0.0 0.0 -57 0.5 0.5 -92 0.495653748512 0.483700931072 -70 3.42239729889e-08 3.42239729889e-08 -SURF 0x10 -mat 2 -refs 4 -92 0.495653748512 0.483700931072 -68 1.0 0.5 -12 1.0 0.0 -55 0.5 1.11563791538e-09 -SURF 0x10 -mat 2 -refs 4 -70 3.42239729889e-08 3.42239729889e-08 -92 0.495653748512 0.483700931072 -55 0.5 1.11563791538e-09 -19 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -71 0.500000059605 3.42239729889e-08 -20 1.0 0.0 -56 1.0 1.11563791538e-09 -93 1.0 0.483700931072 -SURF 0x10 -mat 2 -refs 4 -21 0.0 0.0 -71 0.500000059605 3.42239729889e-08 -93 1.0 0.483700931072 -57 0.5 0.5 -SURF 0x10 -mat 2 -refs 4 -93 1.0 0.483700931072 -56 1.0 1.11563791538e-09 -13 1.0 0.0 -69 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -57 0.5 0.5 -93 1.0 0.483700931072 -69 1.0 0.5 -14 1.0 1.0 -SURF 0x10 -mat 2 -refs 4 -55 0.5 0.5 -12 1.0 1.0 -62 1.0 0.500000059605 -94 0.484075069427 0.467779874802 -SURF 0x10 -mat 2 -refs 4 -19 0.0 0.0 -55 0.5 0.5 -94 0.484075069427 0.467779874802 -64 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -94 0.484075069427 0.467779874802 -62 1.0 0.500000059605 -17 1.0 0.0 -58 0.5 3.54789220225e-09 -SURF 0x10 -mat 2 -refs 4 -64 0.0 0.0 -94 0.484075069427 0.467779874802 -58 0.5 3.54789220225e-09 -26 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -65 0.499999910593 0.0 -27 1.0 0.0 -59 1.0 3.54789220225e-09 -95 1.0 0.467779755592 -SURF 0x10 -mat 2 -refs 4 -20 0.0 0.0 -65 0.499999910593 0.0 -95 1.0 0.467779755592 -56 0.5 0.5 -SURF 0x10 -mat 2 -refs 4 -95 1.0 0.467779755592 -59 1.0 3.54789220225e-09 -18 1.0 0.0 -63 1.0 0.500000059605 -SURF 0x10 -mat 2 -refs 4 -56 0.5 0.5 -95 1.0 0.467779755592 -63 1.0 0.500000059605 -13 1.0 1.0 -SURF 0x10 -mat 2 -refs 4 -49 0.499999970198 -1.96916985828e-07 -0 0.0 0.0 -51 -4.83519748684e-08 -4.83519748684e-08 -96 0.468652904034 0.468652904034 -SURF 0x10 -mat 2 -refs 4 -26 1.0 0.0 -49 0.499999970198 -1.96916985828e-07 -96 0.468652904034 0.468652904034 -64 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -96 0.468652904034 0.468652904034 -51 -4.83519748684e-08 -4.83519748684e-08 -7 0.0 0.0 -53 0.500000059605 0.500000059605 -SURF 0x10 -mat 2 -refs 4 -64 1.0 0.5 -96 0.468652904034 0.468652904034 -53 0.500000059605 0.500000059605 -19 1.0 1.0 -SURF 0x10 -mat 2 -refs 4 -52 0.499999850988 -4.83519748684e-08 -1 1.0 0.0 -50 1.0 -1.96916985828e-07 -97 0.953756332397 0.468652904034 -SURF 0x10 -mat 2 -refs 4 -8 0.0 0.0 -52 0.499999850988 -4.83519748684e-08 -97 0.953756332397 0.468652904034 -54 0.500000059605 0.500000059605 -SURF 0x10 -mat 2 -refs 4 -97 0.953756332397 0.468652904034 -50 1.0 -1.96916985828e-07 -27 1.0 0.0 -65 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -54 0.500000059605 0.500000059605 -97 0.953756332397 0.468652904034 -65 1.0 0.5 -20 1.0 1.0 -SURF 0x10 -mat 2 -refs 4 -53 0.499999970198 0.499999970198 -7 1.0 1.0 -46 1.0 0.5 -98 0.510115087032 0.441994518042 -SURF 0x10 -mat 2 -refs 4 -19 0.0 0.0 -53 0.499999970198 0.499999970198 -98 0.510115087032 0.441994518042 -70 -3.08414094263e-08 -3.08414094263e-08 -SURF 0x10 -mat 2 -refs 4 -98 0.510115087032 0.441994518042 -46 1.0 0.5 -6 1.0 0.0 -48 0.5 0.0 -SURF 0x10 -mat 2 -refs 4 -70 -3.08414094263e-08 -3.08414094263e-08 -98 0.510115087032 0.441994518042 -48 0.5 0.0 -21 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -71 0.499999970198 -3.08414094263e-08 -21 1.0 0.0 -48 1.0 0.0 -99 1.0 0.441994518042 -SURF 0x10 -mat 2 -refs 4 -20 0.0 0.0 -71 0.499999970198 -3.08414094263e-08 -99 1.0 0.441994518042 -54 0.499999970198 0.499999970198 -SURF 0x10 -mat 2 -refs 4 -99 1.0 0.441994518042 -48 1.0 0.0 -6 1.0 0.0 -47 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -54 0.499999970198 0.499999970198 -99 1.0 0.441994518042 -47 1.0 0.5 -8 1.0 1.0 -SURF 0x10 -mat 2 -refs 4 -45 0.5 0.5 -9 1.0 1.0 -41 1.0 0.5 -100 0.5 0.492857187986 -SURF 0x10 -mat 2 -refs 4 -11 0.0 0.0 -45 0.5 0.5 -100 0.5 0.492857187986 -72 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -100 0.5 0.492857187986 -41 1.0 0.5 -4 1.0 0.0 -43 0.5 4.79135664477e-08 -SURF 0x10 -mat 2 -refs 4 -72 0.0 0.0 -100 0.5 0.492857187986 -43 0.5 4.79135664477e-08 -22 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -73 0.5 0.0 -23 1.0 0.0 -44 1.0 4.79135664477e-08 -101 1.0 0.492857187986 -SURF 0x10 -mat 2 -refs 4 -11 0.0 0.0 -73 0.5 0.0 -101 1.0 0.492857187986 -45 0.5 0.5 -SURF 0x10 -mat 2 -refs 4 -101 1.0 0.492857187986 -44 1.0 4.79135664477e-08 -5 1.0 0.0 -42 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -45 0.5 0.5 -101 1.0 0.492857187986 -42 1.0 0.5 -9 1.0 1.0 -SURF 0x10 -mat 2 -refs 4 -43 0.5 0.5 -4 1.0 1.0 -37 1.0 0.5 -102 0.571844756603 0.46288433671 -SURF 0x10 -mat 2 -refs 4 -22 0.0 0.0 -43 0.5 0.5 -102 0.571844756603 0.46288433671 -74 4.91473216291e-11 4.91473216291e-11 -SURF 0x10 -mat 2 -refs 4 -102 0.571844756603 0.46288433671 -37 1.0 0.5 -2 1.0 0.0 -39 0.5 0.0 -SURF 0x10 -mat 2 -refs 4 -74 4.91473216291e-11 4.91473216291e-11 -102 0.571844756603 0.46288433671 -39 0.5 0.0 -24 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -75 0.5 4.91473216291e-11 -25 1.0 0.0 -40 1.0 0.0 -103 1.0 0.46288433671 -SURF 0x10 -mat 2 -refs 4 -23 0.0 0.0 -75 0.5 4.91473216291e-11 -103 1.0 0.46288433671 -44 0.5 0.5 -SURF 0x10 -mat 2 -refs 4 -103 1.0 0.46288433671 -40 1.0 0.0 -3 1.0 0.0 -38 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -44 0.5 0.5 -103 1.0 0.46288433671 -38 1.0 0.5 -5 1.0 1.0 -SURF 0x10 -mat 2 -refs 4 -49 0.499999940395 0.499999940395 -26 1.0 1.0 -80 1.0 0.5 -104 0.448497921228 0.448497921228 -SURF 0x10 -mat 2 -refs 4 -0 0.0 0.0 -49 0.499999940395 0.499999940395 -104 0.448497921228 0.448497921228 -35 7.92489132095e-08 7.92489132095e-08 -SURF 0x10 -mat 2 -refs 4 -104 0.448497921228 0.448497921228 -80 1.0 0.5 -24 1.0 0.0 -39 0.5 0.0 -SURF 0x10 -mat 2 -refs 4 -35 7.92489132095e-08 7.92489132095e-08 -104 0.448497921228 0.448497921228 -39 0.5 0.0 -2 0.0 0.0 -SURF 0x10 -mat 2 -refs 4 -36 0.500000059605 7.92489132095e-08 -3 1.0 0.0 -40 1.0 0.0 -105 0.921673893929 0.448497891426 -SURF 0x10 -mat 2 -refs 4 -1 0.0 0.0 -36 0.500000059605 7.92489132095e-08 -105 0.921673893929 0.448497891426 -50 0.500000059605 0.499999940395 -SURF 0x10 -mat 2 -refs 4 -105 0.921673893929 0.448497891426 -40 1.0 0.0 -25 1.0 0.0 -81 1.0 0.5 -SURF 0x10 -mat 2 -refs 4 -50 0.500000059605 0.499999940395 -105 0.921673893929 0.448497891426 -81 1.0 0.5 -27 1.0 1.0 -kids 0 -OBJECT poly -name "Elevator" -data 9 -Plane.006 -crease 30.000000 -numvert 154 -0.729078 -0.01125 0.17394 -0.729078 -0.01125 -0.17394 -0.729147 -0.010482 0.173932 -0.729147 -0.010482 -0.173932 -0.719362 -0.009081 0.174371 -0.719362 -0.009081 -0.174371 -0.719771 -0.012245 0.174385 -0.719771 -0.012245 -0.174385 -0.709482 -0.008452 0.17437 -0.709482 -0.008452 -0.17437 -0.709677 -0.012564 0.174388 -0.709677 -0.012564 -0.174388 -0.70058 -0.008658 0.173927 -0.70058 -0.008658 -0.173927 -0.70094 -0.011614 0.173949 -0.70094 -0.011614 -0.173949 -0.701039 -0.011845 0.130516 -0.701039 -0.011845 -0.130516 -0.700628 -0.008505 0.130492 -0.700628 -0.008505 -0.130492 -0.709661 -0.013067 0.130515 -0.709661 -0.013067 -0.130515 -0.709432 -0.008186 0.130494 -0.709432 -0.008186 -0.130494 -0.720851 -0.012674 0.130511 -0.720851 -0.012674 -0.130511 -0.720363 -0.008918 0.130495 -0.720363 -0.008918 -0.130495 -0.731343 -0.010512 0.130498 -0.731343 -0.010512 -0.130498 -0.731258 -0.011351 0.130506 -0.731258 -0.011351 -0.130506 -0.700546 -0.012148 0 -0.700114 -0.008637 0 -0.711418 -0.013578 0 -0.711177 -0.008446 0 -0.723242 -0.013162 0 -0.72273 -0.009213 0 -0.734 -0.010664 0 -0.733911 -0.011546 0 -0.719534 -0.010659 0.175702 -0.719534 -0.010659 -0.175702 -0.709584 -0.010505 0.175703 -0.709584 -0.010505 -0.175703 -0.700662 -0.010131 0.174379 -0.700662 -0.010131 -0.174379 -0.700558 -0.01016 0.130504 -0.700558 -0.01016 -0.130504 -0.699972 -0.010372 0 -0.700787 -0.012005 0.06668 -0.700787 -0.012005 -0.06668 -0.700364 -0.008571 0.066667 -0.700364 -0.008571 -0.066667 -0.710569 -0.013337 0.066679 -0.710569 -0.013337 -0.066679 -0.710333 -0.008318 0.066668 -0.710333 -0.008318 -0.066668 -0.722103 -0.012932 0.066678 -0.722103 -0.012932 -0.066678 -0.721603 -0.00907 0.066669 -0.721603 -0.00907 -0.066669 -0.732663 -0.011454 0.066675 -0.732663 -0.011454 -0.066675 -0.732751 -0.010591 0.066671 -0.732751 -0.010591 -0.066671 -0.72445 -0.009796 0.174372 -0.72445 -0.009796 -0.174372 -0.730242 -0.010499 0.154519 -0.730242 -0.010499 -0.154519 -0.729193 -0.010868 0.174377 -0.729193 -0.010868 -0.174377 -0.730161 -0.011295 0.154527 -0.730161 -0.011295 -0.154527 -0.724621 -0.011739 0.174383 -0.724621 -0.011739 -0.174383 -0.714408 -0.008738 0.174371 -0.714408 -0.008738 -0.174371 -0.719815 -0.008941 0.154516 -0.719815 -0.008941 -0.154516 -0.720277 -0.012504 0.154532 -0.720277 -0.012504 -0.154532 -0.714715 -0.012438 0.174387 -0.714716 -0.012438 -0.174387 -0.704826 -0.008531 0.174369 -0.704826 -0.008531 -0.174369 -0.709423 -0.008245 0.154515 -0.709423 -0.008245 -0.154515 -0.70964 -0.012876 0.154536 -0.709641 -0.012876 -0.154536 -0.705104 -0.012104 0.174389 -0.705104 -0.012104 -0.174389 -0.700563 -0.008565 0.154513 -0.700563 -0.008565 -0.154513 -0.700953 -0.011734 0.154537 -0.700953 -0.011734 -0.154537 -0.705181 -0.012517 0.130516 -0.705181 -0.012517 -0.130516 -0.704851 -0.008279 0.130492 -0.704851 -0.008279 -0.130492 -0.715224 -0.01291 0.130513 -0.715224 -0.01291 -0.130513 -0.714859 -0.008522 0.130494 -0.71486 -0.008522 -0.130494 -0.726229 -0.012019 0.130509 -0.726229 -0.012019 -0.130509 -0.731646 -0.010936 0.130502 -0.731646 -0.010936 -0.130502 -0.726027 -0.009714 0.130497 -0.726027 -0.009714 -0.130497 -0.705803 -0.012928 0 -0.705457 -0.008471 0 -0.717335 -0.013419 0 -0.716952 -0.008805 0 -0.728761 -0.012361 0 -0.73431 -0.011102 0 -0.728548 -0.009938 0 -0.727355 -0.009829 0.06667 -0.727355 -0.009829 -0.06667 -0.733057 -0.011023 0.066673 -0.733057 -0.011023 -0.066673 -0.727563 -0.012199 0.066676 -0.727563 -0.012199 -0.066676 -0.715948 -0.008667 0.066669 -0.715948 -0.008667 -0.066669 -0.716323 -0.013179 0.066678 -0.716323 -0.013179 -0.066678 -0.705165 -0.008376 0.066668 -0.705165 -0.008376 -0.066668 -0.705503 -0.012734 0.06668 -0.705503 -0.012734 -0.06668 -0.705136 -0.012363 0.154537 -0.705136 -0.012363 -0.154537 -0.704823 -0.008342 0.154514 -0.704823 -0.008342 -0.154514 -0.714939 -0.012727 0.154534 -0.714939 -0.012727 -0.154534 -0.714593 -0.008564 0.154516 -0.714593 -0.008564 -0.154516 -0.725385 -0.011905 0.15453 -0.725385 -0.011905 -0.15453 -0.730529 -0.010902 0.154523 -0.730529 -0.010902 -0.154523 -0.725193 -0.009719 0.154518 -0.725193 -0.009719 -0.154518 -0.700258 -0.01027 0.066674 -0.700258 -0.01027 -0.066674 -0.700477 -0.010136 0.154525 -0.700477 -0.010136 -0.154525 -0.704964 -0.010315 0.175703 -0.704964 -0.010315 -0.175703 -0.714548 -0.010585 0.175702 -0.714548 -0.010585 -0.175702 -0.724485 -0.010765 0.175701 -0.724485 -0.010765 -0.175701 -numsurf 152 -SURF 0x30 -mat 1 -refs 4 -115 0 0 -37 0 0 -59 0 0 -116 0 0 -SURF 0x30 -mat 1 -refs 4 -38 0 0 -115 0 0 -116 0 0 -63 0 0 -SURF 0x30 -mat 1 -refs 4 -116 0 0 -59 0 0 -26 0 0 -107 0 0 -SURF 0x30 -mat 1 -refs 4 -63 0 0 -116 0 0 -107 0 0 -28 0 0 -SURF 0x30 -mat 1 -refs 4 -64 0 0 -29 0 0 -108 0 0 -117 0 0 -SURF 0x30 -mat 1 -refs 4 -38 0 0 -64 0 0 -117 0 0 -115 0 0 -SURF 0x30 -mat 1 -refs 4 -117 0 0 -108 0 0 -27 0 0 -60 0 0 -SURF 0x30 -mat 1 -refs 4 -115 0 0 -117 0 0 -60 0 0 -37 0 0 -SURF 0x30 -mat 1 -refs 4 -63 0 0 -28 0 0 -105 0 0 -118 0 0 -SURF 0x30 -mat 1 -refs 4 -38 0 0 -63 0 0 -118 0 0 -114 0 0 -SURF 0x30 -mat 1 -refs 4 -118 0 0 -105 0 0 -30 0 0 -61 0 0 -SURF 0x30 -mat 1 -refs 4 -114 0 0 -118 0 0 -61 0 0 -39 0 0 -SURF 0x30 -mat 1 -refs 4 -114 0 0 -39 0 0 -62 0 0 -119 0 0 -SURF 0x30 -mat 1 -refs 4 -38 0 0 -114 0 0 -119 0 0 -64 0 0 -SURF 0x30 -mat 1 -refs 4 -119 0 0 -62 0 0 -31 0 0 -106 0 0 -SURF 0x30 -mat 1 -refs 4 -64 0 0 -119 0 0 -106 0 0 -29 0 0 -SURF 0x30 -mat 1 -refs 4 -61 0 0 -30 0 0 -103 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 4 -39 0 0 -61 0 0 -120 0 0 -113 0 0 -SURF 0x30 -mat 1 -refs 4 -120 0 0 -103 0 0 -24 0 0 -57 0 0 -SURF 0x30 -mat 1 -refs 4 -113 0 0 -120 0 0 -57 0 0 -36 0 0 -SURF 0x30 -mat 1 -refs 4 -113 0 0 -36 0 0 -58 0 0 -121 0 0 -SURF 0x30 -mat 1 -refs 4 -39 0 0 -113 0 0 -121 0 0 -62 0 0 -SURF 0x30 -mat 1 -refs 4 -121 0 0 -58 0 0 -25 0 0 -104 0 0 -SURF 0x30 -mat 1 -refs 4 -62 0 0 -121 0 0 -104 0 0 -31 0 0 -SURF 0x30 -mat 1 -refs 4 -112 0 0 -35 0 0 -55 0 0 -122 0 0 -SURF 0x30 -mat 1 -refs 4 -37 0 0 -112 0 0 -122 0 0 -59 0 0 -SURF 0x30 -mat 1 -refs 4 -122 0 0 -55 0 0 -22 0 0 -101 0 0 -SURF 0x30 -mat 1 -refs 4 -59 0 0 -122 0 0 -101 0 0 -26 0 0 -SURF 0x30 -mat 1 -refs 4 -60 0 0 -27 0 0 -102 0 0 -123 0 0 -SURF 0x30 -mat 1 -refs 4 -37 0 0 -60 0 0 -123 0 0 -112 0 0 -SURF 0x30 -mat 1 -refs 4 -123 0 0 -102 0 0 -23 0 0 -56 0 0 -SURF 0x30 -mat 1 -refs 4 -112 0 0 -123 0 0 -56 0 0 -35 0 0 -SURF 0x30 -mat 1 -refs 4 -57 0 0 -24 0 0 -99 0 0 -124 0 0 -SURF 0x30 -mat 1 -refs 4 -36 0 0 -57 0 0 -124 0 0 -111 0 0 -SURF 0x30 -mat 1 -refs 4 -124 0 0 -99 0 0 -20 0 0 -53 0 0 -SURF 0x30 -mat 1 -refs 4 -111 0 0 -124 0 0 -53 0 0 -34 0 0 -SURF 0x30 -mat 1 -refs 4 -111 0 0 -34 0 0 -54 0 0 -125 0 0 -SURF 0x30 -mat 1 -refs 4 -36 0 0 -111 0 0 -125 0 0 -58 0 0 -SURF 0x30 -mat 1 -refs 4 -125 0 0 -54 0 0 -21 0 0 -100 0 0 -SURF 0x30 -mat 1 -refs 4 -58 0 0 -125 0 0 -100 0 0 -25 0 0 -SURF 0x30 -mat 1 -refs 4 -110 0 0 -33 0 0 -51 0 0 -126 0 0 -SURF 0x30 -mat 1 -refs 4 -35 0 0 -110 0 0 -126 0 0 -55 0 0 -SURF 0x30 -mat 1 -refs 4 -126 0 0 -51 0 0 -18 0 0 -97 0 0 -SURF 0x30 -mat 1 -refs 4 -55 0 0 -126 0 0 -97 0 0 -22 0 0 -SURF 0x30 -mat 1 -refs 4 -56 0 0 -23 0 0 -98 0 0 -127 0 0 -SURF 0x30 -mat 1 -refs 4 -35 0 0 -56 0 0 -127 0 0 -110 0 0 -SURF 0x30 -mat 1 -refs 4 -127 0 0 -98 0 0 -19 0 0 -52 0 0 -SURF 0x30 -mat 1 -refs 4 -110 0 0 -127 0 0 -52 0 0 -33 0 0 -SURF 0x30 -mat 1 -refs 4 -53 0 0 -20 0 0 -95 0 0 -128 0 0 -SURF 0x30 -mat 1 -refs 4 -34 0 0 -53 0 0 -128 0 0 -109 0 0 -SURF 0x30 -mat 1 -refs 4 -128 0 0 -95 0 0 -16 0 0 -49 0 0 -SURF 0x30 -mat 1 -refs 4 -109 0 0 -128 0 0 -49 0 0 -32 0 0 -SURF 0x30 -mat 1 -refs 4 -109 0 0 -32 0 0 -50 0 0 -129 0 0 -SURF 0x30 -mat 1 -refs 4 -34 0 0 -109 0 0 -129 0 0 -54 0 0 -SURF 0x30 -mat 1 -refs 4 -129 0 0 -50 0 0 -17 0 0 -96 0 0 -SURF 0x30 -mat 1 -refs 4 -54 0 0 -129 0 0 -96 0 0 -21 0 0 -SURF 0x30 -mat 1 -refs 4 -87 0 0 -10 0 0 -89 0 0 -130 0 0 -SURF 0x30 -mat 1 -refs 4 -20 0 0 -87 0 0 -130 0 0 -95 0 0 -SURF 0x30 -mat 1 -refs 4 -130 0 0 -89 0 0 -14 0 0 -93 0 0 -SURF 0x30 -mat 1 -refs 4 -95 0 0 -130 0 0 -93 0 0 -16 0 0 -SURF 0x30 -mat 1 -refs 4 -96 0 0 -17 0 0 -94 0 0 -131 0 0 -SURF 0x30 -mat 1 -refs 4 -21 0 0 -96 0 0 -131 0 0 -88 0 0 -SURF 0x30 -mat 1 -refs 4 -131 0 0 -94 0 0 -15 0 0 -90 0 0 -SURF 0x30 -mat 1 -refs 4 -88 0 0 -131 0 0 -90 0 0 -11 0 0 -SURF 0x30 -mat 1 -refs 4 -97 0 0 -18 0 0 -91 0 0 -132 0 0 -SURF 0x30 -mat 1 -refs 4 -22 0 0 -97 0 0 -132 0 0 -85 0 0 -SURF 0x30 -mat 1 -refs 4 -132 0 0 -91 0 0 -12 0 0 -83 0 0 -SURF 0x30 -mat 1 -refs 4 -85 0 0 -132 0 0 -83 0 0 -8 0 0 -SURF 0x30 -mat 1 -refs 4 -86 0 0 -9 0 0 -84 0 0 -133 0 0 -SURF 0x30 -mat 1 -refs 4 -23 0 0 -86 0 0 -133 0 0 -98 0 0 -SURF 0x30 -mat 1 -refs 4 -133 0 0 -84 0 0 -13 0 0 -92 0 0 -SURF 0x30 -mat 1 -refs 4 -98 0 0 -133 0 0 -92 0 0 -19 0 0 -SURF 0x30 -mat 1 -refs 4 -79 0 0 -6 0 0 -81 0 0 -134 0 0 -SURF 0x30 -mat 1 -refs 4 -24 0 0 -79 0 0 -134 0 0 -99 0 0 -SURF 0x30 -mat 1 -refs 4 -134 0 0 -81 0 0 -10 0 0 -87 0 0 -SURF 0x30 -mat 1 -refs 4 -99 0 0 -134 0 0 -87 0 0 -20 0 0 -SURF 0x30 -mat 1 -refs 4 -100 0 0 -21 0 0 -88 0 0 -135 0 0 -SURF 0x30 -mat 1 -refs 4 -25 0 0 -100 0 0 -135 0 0 -80 0 0 -SURF 0x30 -mat 1 -refs 4 -135 0 0 -88 0 0 -11 0 0 -82 0 0 -SURF 0x30 -mat 1 -refs 4 -80 0 0 -135 0 0 -82 0 0 -7 0 0 -SURF 0x30 -mat 1 -refs 4 -101 0 0 -22 0 0 -85 0 0 -136 0 0 -SURF 0x30 -mat 1 -refs 4 -26 0 0 -101 0 0 -136 0 0 -77 0 0 -SURF 0x30 -mat 1 -refs 4 -136 0 0 -85 0 0 -8 0 0 -75 0 0 -SURF 0x30 -mat 1 -refs 4 -77 0 0 -136 0 0 -75 0 0 -4 0 0 -SURF 0x30 -mat 1 -refs 4 -78 0 0 -5 0 0 -76 0 0 -137 0 0 -SURF 0x30 -mat 1 -refs 4 -27 0 0 -78 0 0 -137 0 0 -102 0 0 -SURF 0x30 -mat 1 -refs 4 -137 0 0 -76 0 0 -9 0 0 -86 0 0 -SURF 0x30 -mat 1 -refs 4 -102 0 0 -137 0 0 -86 0 0 -23 0 0 -SURF 0x30 -mat 1 -refs 4 -71 0 0 -0 0 0 -73 0 0 -138 0 0 -SURF 0x30 -mat 1 -refs 4 -30 0 0 -71 0 0 -138 0 0 -103 0 0 -SURF 0x30 -mat 1 -refs 4 -138 0 0 -73 0 0 -6 0 0 -79 0 0 -SURF 0x30 -mat 1 -refs 4 -103 0 0 -138 0 0 -79 0 0 -24 0 0 -SURF 0x30 -mat 1 -refs 4 -74 0 0 -1 0 0 -72 0 0 -139 0 0 -SURF 0x30 -mat 1 -refs 4 -7 0 0 -74 0 0 -139 0 0 -80 0 0 -SURF 0x30 -mat 1 -refs 4 -139 0 0 -72 0 0 -31 0 0 -104 0 0 -SURF 0x30 -mat 1 -refs 4 -80 0 0 -139 0 0 -104 0 0 -25 0 0 -SURF 0x30 -mat 1 -refs 4 -71 0 0 -30 0 0 -105 0 0 -140 0 0 -SURF 0x30 -mat 1 -refs 4 -0 0 0 -71 0 0 -140 0 0 -69 0 0 -SURF 0x30 -mat 1 -refs 4 -140 0 0 -105 0 0 -28 0 0 -67 0 0 -SURF 0x30 -mat 1 -refs 4 -69 0 0 -140 0 0 -67 0 0 -2 0 0 -SURF 0x30 -mat 1 -refs 4 -70 0 0 -3 0 0 -68 0 0 -141 0 0 -SURF 0x30 -mat 1 -refs 4 -1 0 0 -70 0 0 -141 0 0 -72 0 0 -SURF 0x30 -mat 1 -refs 4 -141 0 0 -68 0 0 -29 0 0 -106 0 0 -SURF 0x30 -mat 1 -refs 4 -72 0 0 -141 0 0 -106 0 0 -31 0 0 -SURF 0x30 -mat 1 -refs 4 -107 0 0 -26 0 0 -77 0 0 -142 0 0 -SURF 0x30 -mat 1 -refs 4 -28 0 0 -107 0 0 -142 0 0 -67 0 0 -SURF 0x30 -mat 1 -refs 4 -142 0 0 -77 0 0 -4 0 0 -65 0 0 -SURF 0x30 -mat 1 -refs 4 -67 0 0 -142 0 0 -65 0 0 -2 0 0 -SURF 0x30 -mat 1 -refs 4 -68 0 0 -3 0 0 -66 0 0 -143 0 0 -SURF 0x30 -mat 1 -refs 4 -29 0 0 -68 0 0 -143 0 0 -108 0 0 -SURF 0x30 -mat 1 -refs 4 -143 0 0 -66 0 0 -5 0 0 -78 0 0 -SURF 0x30 -mat 1 -refs 4 -108 0 0 -143 0 0 -78 0 0 -27 0 0 -SURF 0x30 -mat 1 -refs 4 -48 0 0 -32 0 0 -49 0 0 -144 0 0 -SURF 0x30 -mat 1 -refs 4 -33 0 0 -48 0 0 -144 0 0 -51 0 0 -SURF 0x30 -mat 1 -refs 4 -144 0 0 -49 0 0 -16 0 0 -46 0 0 -SURF 0x30 -mat 1 -refs 4 -51 0 0 -144 0 0 -46 0 0 -18 0 0 -SURF 0x30 -mat 1 -refs 4 -52 0 0 -19 0 0 -47 0 0 -145 0 0 -SURF 0x30 -mat 1 -refs 4 -33 0 0 -52 0 0 -145 0 0 -48 0 0 -SURF 0x30 -mat 1 -refs 4 -145 0 0 -47 0 0 -17 0 0 -50 0 0 -SURF 0x30 -mat 1 -refs 4 -48 0 0 -145 0 0 -50 0 0 -32 0 0 -SURF 0x30 -mat 1 -refs 4 -46 0 0 -16 0 0 -93 0 0 -146 0 0 -SURF 0x30 -mat 1 -refs 4 -18 0 0 -46 0 0 -146 0 0 -91 0 0 -SURF 0x30 -mat 1 -refs 4 -146 0 0 -93 0 0 -14 0 0 -44 0 0 -SURF 0x30 -mat 1 -refs 4 -91 0 0 -146 0 0 -44 0 0 -12 0 0 -SURF 0x30 -mat 1 -refs 4 -92 0 0 -13 0 0 -45 0 0 -147 0 0 -SURF 0x30 -mat 1 -refs 4 -19 0 0 -92 0 0 -147 0 0 -47 0 0 -SURF 0x30 -mat 1 -refs 4 -147 0 0 -45 0 0 -15 0 0 -94 0 0 -SURF 0x30 -mat 1 -refs 4 -47 0 0 -147 0 0 -94 0 0 -17 0 0 -SURF 0x30 -mat 1 -refs 4 -44 0 0 -14 0 0 -89 0 0 -148 0 0 -SURF 0x30 -mat 1 -refs 4 -12 0 0 -44 0 0 -148 0 0 -83 0 0 -SURF 0x30 -mat 1 -refs 4 -148 0 0 -89 0 0 -10 0 0 -42 0 0 -SURF 0x30 -mat 1 -refs 4 -83 0 0 -148 0 0 -42 0 0 -8 0 0 -SURF 0x30 -mat 1 -refs 4 -84 0 0 -9 0 0 -43 0 0 -149 0 0 -SURF 0x30 -mat 1 -refs 4 -13 0 0 -84 0 0 -149 0 0 -45 0 0 -SURF 0x30 -mat 1 -refs 4 -149 0 0 -43 0 0 -11 0 0 -90 0 0 -SURF 0x30 -mat 1 -refs 4 -45 0 0 -149 0 0 -90 0 0 -15 0 0 -SURF 0x30 -mat 1 -refs 4 -42 0 0 -10 0 0 -81 0 0 -150 0 0 -SURF 0x30 -mat 1 -refs 4 -8 0 0 -42 0 0 -150 0 0 -75 0 0 -SURF 0x30 -mat 1 -refs 4 -150 0 0 -81 0 0 -6 0 0 -40 0 0 -SURF 0x30 -mat 1 -refs 4 -75 0 0 -150 0 0 -40 0 0 -4 0 0 -SURF 0x30 -mat 1 -refs 4 -76 0 0 -5 0 0 -41 0 0 -151 0 0 -SURF 0x30 -mat 1 -refs 4 -9 0 0 -76 0 0 -151 0 0 -43 0 0 -SURF 0x30 -mat 1 -refs 4 -151 0 0 -41 0 0 -7 0 0 -82 0 0 -SURF 0x30 -mat 1 -refs 4 -43 0 0 -151 0 0 -82 0 0 -11 0 0 -SURF 0x30 -mat 1 -refs 4 -69 0 0 -2 0 0 -65 0 0 -152 0 0 -SURF 0x30 -mat 1 -refs 4 -0 0 0 -69 0 0 -152 0 0 -73 0 0 -SURF 0x30 -mat 1 -refs 4 -152 0 0 -65 0 0 -4 0 0 -40 0 0 -SURF 0x30 -mat 1 -refs 4 -73 0 0 -152 0 0 -40 0 0 -6 0 0 -SURF 0x30 -mat 1 -refs 4 -74 0 0 -7 0 0 -41 0 0 -153 0 0 -SURF 0x30 -mat 1 -refs 4 -1 0 0 -74 0 0 -153 0 0 -70 0 0 -SURF 0x30 -mat 1 -refs 4 -153 0 0 -41 0 0 -5 0 0 -66 0 0 -SURF 0x30 -mat 1 -refs 4 -70 0 0 -153 0 0 -66 0 0 -3 0 0 -kids 0 -OBJECT poly -name "LeftTail" -data 4 -Tail -crease 30.000000 -numvert 478 -0.632646 -0.00581 0.004183 -0.632334 -0.0118 0.004184 -0.626565 -0.010097 0.005582 -0.627624 -0.006845 0.005581 -0.639753 -0.005601 0.004183 -0.639389 -0.012925 0.004184 -0.652747 -0.013041 0.004184 -0.652234 -0.005189 0.004183 -0.665104 -0.013003 0.004184 -0.664903 -0.004956 0.004183 -0.677032 -0.012802 0.004184 -0.67703 -0.005117 0.004183 -0.688801 -0.012256 0.004184 -0.688665 -0.005485 0.004183 -0.696797 -0.012047 0.005582 -0.696359 -0.006146 0.005581 -0.696981 -0.006001 0.131355 -0.69741 -0.011726 0.13138 -0.687762 -0.005215 0.131353 -0.687899 -0.012074 0.131383 -0.676652 -0.004836 0.131353 -0.676653 -0.012621 0.131387 -0.665131 -0.004672 0.131354 -0.665333 -0.012824 0.13139 -0.652936 -0.004914 0.133005 -0.653612 -0.012853 0.131391 -0.640857 -0.012697 0.133041 -0.641084 -0.005312 0.131361 -0.629682 -0.0067 0.131369 -0.628643 -0.009827 0.131382 -0.634043 -0.011568 0.131389 -0.634381 -0.005578 0.131363 -0.642733 -0.005849 0.177257 -0.642431 -0.01125 0.17729 -0.637189 -0.009712 0.176222 -0.638116 -0.006816 0.176202 -0.648888 -0.005608 0.177219 -0.648185 -0.012221 0.17725 -0.659392 -0.012357 0.177201 -0.658946 -0.005262 0.177166 -0.669876 -0.012334 0.177102 -0.669687 -0.005055 0.177074 -0.679983 -0.012157 0.177013 -0.679977 -0.005193 0.176983 -0.690231 -0.011658 0.177669 -0.689853 -0.005527 0.176897 -0.697799 -0.011385 0.176882 -0.697413 -0.006206 0.177489 -0.707798 -0.011278 0.178038 -0.707596 -0.00714 0.178021 -0.718302 -0.010928 0.177946 -0.717877 -0.007797 0.177936 -0.728013 -0.009146 0.178016 -0.727943 -0.00996 0.178025 -0.728188 -0.009829 0.193645 -0.728247 -0.009189 0.193619 -0.720661 -0.007974 0.196196 -0.720997 -0.0106 0.196094 -0.713146 -0.007423 0.199436 -0.713308 -0.010897 0.199394 -0.706406 -0.006672 0.201163 -0.706709 -0.010978 0.201078 -0.700185 -0.00626 0.204147 -0.700097 -0.011076 0.204138 -0.692506 -0.005951 0.206157 -0.692516 -0.011451 0.206179 -0.684813 -0.005827 0.20883 -0.68495 -0.011596 0.208805 -0.676785 -0.005971 0.21162 -0.677116 -0.011611 0.211532 -0.668728 -0.011503 0.214425 -0.668945 -0.006243 0.214318 -0.660393 -0.007186 0.216062 -0.659699 -0.0095 0.216312 -0.664082 -0.010732 0.215969 -0.664303 -0.006427 0.21587 -0.696456 -0.00777 0.239121 -0.696328 -0.010388 0.239236 -0.693518 -0.009633 0.240114 -0.693881 -0.008212 0.239852 -0.698899 -0.007668 0.237445 -0.698793 -0.010849 0.237542 -0.703178 -0.010914 0.234445 -0.703004 -0.007508 0.234553 -0.707259 -0.010908 0.231552 -0.707188 -0.007427 0.231588 -0.711614 -0.010813 0.229161 -0.711197 -0.007508 0.228748 -0.714927 -0.010607 0.226017 -0.715227 -0.007705 0.226493 -0.71887 -0.010538 0.223866 -0.718713 -0.007983 0.223965 -0.721836 -0.010507 0.221102 -0.721749 -0.008389 0.221154 -0.725685 -0.01033 0.218293 -0.725513 -0.008711 0.218407 -0.729518 -0.009374 0.215043 -0.729496 -0.009816 0.215066 -0.733865 -0.00984 0.234298 -0.733869 -0.009647 0.234287 -0.732707 -0.009526 0.236323 -0.732758 -0.0102 0.236257 -0.731513 -0.009387 0.237902 -0.731542 -0.010271 0.23787 -0.730331 -0.009177 0.238922 -0.730382 -0.010289 0.238862 -0.729541 -0.009107 0.240549 -0.729557 -0.010308 0.240535 -0.728485 -0.009041 0.242006 -0.728366 -0.0104 0.242099 -0.72727 -0.009005 0.243603 -0.727291 -0.010428 0.243582 -0.726002 -0.009035 0.24527 -0.726055 -0.010431 0.245206 -0.724723 -0.010405 0.246961 -0.724751 -0.009099 0.246912 -0.723396 -0.009343 0.248615 -0.722706 -0.009904 0.248626 -0.723946 -0.010222 0.24794 -0.72337 -0.009107 0.24778 -0.734549 -0.010168 0.241927 -0.629293 -0.01094 0.004184 -0.632436 -0.008812 -1.2e-05 -0.629995 -0.00632 0.004183 -0.627015 -0.00847 0.004183 -0.635743 -0.01239 0.004184 -0.639528 -0.009271 -1.2e-05 -0.636083 -0.005694 0.004183 -0.645983 -0.013002 0.004184 -0.652468 -0.009123 -1.2e-05 -0.645904 -0.005395 0.004183 -0.658952 -0.013027 0.004184 -0.665001 -0.008988 -1.2e-05 -0.658576 -0.005063 0.004183 -0.671074 -0.012912 0.004184 -0.677047 -0.008967 -1.2e-05 -0.670982 -0.005027 0.004183 -0.682975 -0.012528 0.004184 -0.688768 -0.008878 -1.2e-05 -0.682915 -0.005293 0.004183 -0.693027 -0.012177 0.004183 -0.696655 -0.009102 0.004183 -0.692731 -0.005792 0.004183 -0.696708 -0.00604 0.067095 -0.697149 -0.011927 0.067108 -0.692539 -0.005519 0.131354 -0.688177 -0.005232 0.067094 -0.688317 -0.012284 0.067109 -0.692838 -0.011986 0.131382 -0.682237 -0.005018 0.131353 -0.676788 -0.004842 0.067094 -0.676789 -0.012847 0.067111 -0.682298 -0.012347 0.131385 -0.670906 -0.004744 0.131354 -0.664941 -0.004673 0.067094 -0.66515 -0.013056 0.067113 -0.671 -0.012731 0.131388 -0.659118 -0.004776 0.131356 -0.65256 -0.004908 0.067096 -0.653098 -0.013085 0.067114 -0.659499 -0.012843 0.13139 -0.646834 -0.005112 0.131359 -0.640406 -0.005326 0.067098 -0.640024 -0.012956 0.067114 -0.647174 -0.012808 0.131392 -0.637621 -0.005434 0.131362 -0.633464 -0.005573 0.067099 -0.63314 -0.011815 0.067112 -0.637267 -0.012158 0.131391 -0.628491 -0.006759 0.067102 -0.628996 -0.008254 0.131375 -0.627422 -0.009974 0.067109 -0.632068 -0.006105 0.133013 -0.63134 -0.010709 0.133033 -0.632585 -0.009799 0.15472 -0.640288 -0.01048 0.178314 -0.640923 -0.006317 0.178282 -0.633571 -0.006727 0.154707 -0.637701 -0.008249 0.177273 -0.645021 -0.011788 0.176213 -0.64432 -0.012462 0.156888 -0.645711 -0.005718 0.177238 -0.653716 -0.012305 0.177226 -0.656378 -0.01261 0.155808 -0.655777 -0.005081 0.156853 -0.653753 -0.00542 0.176145 -0.664657 -0.012349 0.177151 -0.667499 -0.012583 0.155806 -0.667307 -0.004849 0.155772 -0.664323 -0.00515 0.17712 -0.674935 -0.012253 0.177057 -0.678238 -0.012391 0.155804 -0.678237 -0.005004 0.155771 -0.674845 -0.005115 0.177029 -0.685019 -0.011916 0.176969 -0.688886 -0.011871 0.1558 -0.688756 -0.005364 0.155771 -0.684965 -0.005353 0.17694 -0.694047 -0.011585 0.176801 -0.69735 -0.011542 0.155797 -0.696943 -0.006109 0.155773 -0.693557 -0.005796 0.176856 -0.702782 -0.011312 0.178073 -0.702493 -0.006706 0.178055 -0.71305 -0.011119 0.177992 -0.712731 -0.007459 0.177979 -0.72334 -0.010437 0.177902 -0.728086 -0.009556 0.177854 -0.723163 -0.008486 0.177893 -0.728166 -0.009168 0.185388 -0.724685 -0.008597 0.195362 -0.719116 -0.007808 0.186764 -0.728096 -0.009894 0.185405 -0.728461 -0.009517 0.193545 -0.719517 -0.01083 0.186716 -0.72482 -0.01021 0.195325 -0.716794 -0.007679 0.197537 -0.710082 -0.007181 0.188134 -0.710272 -0.01117 0.188123 -0.71705 -0.010765 0.197463 -0.709614 -0.007031 0.200062 -0.701812 -0.00637 0.189959 -0.702107 -0.01125 0.189241 -0.709847 -0.010947 0.199999 -0.703012 -0.006432 0.201709 -0.694916 -0.011367 0.191235 -0.703298 -0.011026 0.202271 -0.696195 -0.006087 0.204861 -0.695937 -0.011281 0.204193 -0.688669 -0.005882 0.20749 -0.688737 -0.01153 0.207491 -0.680804 -0.005892 0.210223 -0.68105 -0.011607 0.210162 -0.672808 -0.006107 0.212989 -0.672868 -0.01157 0.212998 -0.666549 -0.006328 0.21512 -0.66633 -0.011136 0.215224 -0.648759 -0.006986 0.196432 -0.660482 -0.008335 0.21712 -0.647945 -0.009604 0.196565 -0.66335 -0.006815 0.217129 -0.662883 -0.01012 0.217315 -0.67639 -0.009558 0.228814 -0.696036 -0.01002 0.240261 -0.695565 -0.007984 0.239746 -0.676919 -0.007679 0.228552 -0.694393 -0.008929 0.240538 -0.697522 -0.01063 0.238417 -0.698301 -0.007751 0.238651 -0.700958 -0.010889 0.236014 -0.700922 -0.007588 0.23602 -0.705227 -0.010913 0.232992 -0.705099 -0.007464 0.233068 -0.709234 -0.010868 0.230154 -0.709198 -0.007464 0.230164 -0.712738 -0.010723 0.22682 -0.707636 -0.010832 0.215565 -0.707567 -0.006966 0.215581 -0.712682 -0.00755 0.226862 -0.716744 -0.010573 0.224731 -0.712573 -0.010758 0.212393 -0.712342 -0.007298 0.212488 -0.716637 -0.007805 0.224793 -0.720194 -0.010528 0.222268 -0.7176 -0.010694 0.210593 -0.717477 -0.00791 0.210642 -0.720071 -0.00817 0.222343 -0.723483 -0.010438 0.219213 -0.723351 -0.008517 0.219297 -0.727833 -0.01007 0.217379 -0.728648 -0.009834 0.20404 -0.729855 -0.009606 0.21545 -0.728683 -0.009254 0.204016 -0.727758 -0.00906 0.217424 -0.731668 -0.009506 0.22491 -0.733431 -0.009606 0.23571 -0.731654 -0.00982 0.224926 -0.734138 -0.009757 0.234836 -0.733455 -0.010027 0.235682 -0.73224 -0.00948 0.237292 -0.73228 -0.01024 0.237244 -0.730718 -0.009259 0.23822 -0.724916 -0.008621 0.232051 -0.725017 -0.010403 0.231971 -0.73076 -0.010285 0.238173 -0.730019 -0.00915 0.239793 -0.722742 -0.00843 0.234025 -0.722394 -0.010451 0.233617 -0.730052 -0.010296 0.239756 -0.72893 -0.00907 0.241114 -0.720323 -0.010599 0.236175 -0.72918 -0.010349 0.241404 -0.72811 -0.009053 0.242871 -0.727727 -0.010418 0.242675 -0.726908 -0.009051 0.244466 -0.726946 -0.010424 0.244421 -0.725679 -0.009098 0.246094 -0.725692 -0.010415 0.246086 -0.724703 -0.009148 0.247373 -0.709826 -0.008424 0.243756 -0.724673 -0.010313 0.247422 -0.709369 -0.008807 0.24497 -0.723724 -0.009631 0.248624 -0.708459 -0.009764 0.244938 -0.724032 -0.009261 0.248213 -0.724013 -0.010073 0.248274 -0.729474 -0.00965 0.245381 -0.734703 -0.009923 0.23817 -0.7347 -0.010013 0.238175 -0.7341 -0.009856 0.239001 -0.734126 -0.0102 0.238967 -0.733501 -0.009789 0.239862 -0.733516 -0.010246 0.239844 -0.732398 -0.009633 0.241383 -0.732406 -0.010271 0.241376 -0.731781 -0.00959 0.242199 -0.731782 -0.010315 0.2422 -0.731148 -0.009573 0.243071 -0.73116 -0.010333 0.243058 -0.730489 -0.009591 0.243981 -0.730515 -0.010333 0.243949 -0.729854 -0.009624 0.244857 -0.729837 -0.010315 0.244884 -0.729214 -0.009762 0.24574 -0.729455 -0.010211 0.24541 -0.729165 -0.010039 0.245809 -0.6975 -0.008871 0.131368 -0.697625 -0.008815 0.176007 -0.707533 -0.009211 0.177356 -0.718008 -0.009365 0.177355 -0.709334 -0.01012 0.244302 -0.71154 -0.010523 0.243256 -0.71089 -0.008378 0.242977 -0.714079 -0.010652 0.241197 -0.714005 -0.008313 0.241227 -0.716751 -0.010663 0.238842 -0.716687 -0.008236 0.238893 -0.71971 -0.010616 0.236957 -0.71929 -0.008258 0.23661 -0.722143 -0.008393 0.234791 -0.725527 -0.010395 0.231323 -0.725436 -0.008711 0.231389 -0.727399 -0.010346 0.228949 -0.72733 -0.008963 0.229009 -0.72993 -0.010068 0.226184 -0.729848 -0.009192 0.226236 -0.72513 -0.008677 0.205297 -0.725281 -0.0102 0.205257 -0.719444 -0.008078 0.209284 -0.71961 -0.010611 0.209203 -0.705656 -0.006881 0.216898 -0.705701 -0.01094 0.2169 -0.69958 -0.00667 0.219107 -0.699618 -0.011184 0.219101 -0.693631 -0.006652 0.22199 -0.693792 -0.011254 0.22192 -0.687545 -0.006811 0.224909 -0.687659 -0.011229 0.224912 -0.68241 -0.007 0.227166 -0.682233 -0.01094 0.227267 -0.678407 -0.007289 0.228011 -0.678096 -0.010159 0.228202 -0.650235 -0.010369 0.196555 -0.650762 -0.006484 0.196411 -0.655766 -0.011486 0.196897 -0.656036 -0.006 0.196835 -0.663708 -0.01194 0.196099 -0.663597 -0.005734 0.196027 -0.673225 -0.011977 0.19458 -0.672958 -0.005492 0.194614 -0.68223 -0.01188 0.193179 -0.68216 -0.005488 0.193175 -0.691295 -0.011548 0.192447 -0.690981 -0.005721 0.191799 -0.69856 -0.006147 0.191038 -0.650703 -0.005254 0.156855 -0.641643 -0.005558 0.155779 -0.641386 -0.011999 0.156886 -0.635821 -0.00616 0.154704 -0.635153 -0.010661 0.154724 -0.638285 -0.011343 0.155805 -0.638775 -0.00585 0.155781 -0.646023 -0.005398 0.155777 -0.694686 -0.005924 0.191133 -0.6866 -0.005598 0.192485 -0.68666 -0.011726 0.192501 -0.677568 -0.005482 0.193893 -0.677739 -0.011934 0.193876 -0.668252 -0.005609 0.19533 -0.668451 -0.011967 0.195349 -0.659742 -0.005863 0.196444 -0.659663 -0.011731 0.196511 -0.653634 -0.006236 0.197136 -0.653242 -0.010941 0.197241 -0.68057 -0.010565 0.228042 -0.680807 -0.00715 0.227897 -0.684899 -0.011096 0.226113 -0.68493 -0.006903 0.226062 -0.69072 -0.011247 0.223423 -0.690575 -0.006728 0.223459 -0.696712 -0.011223 0.220507 -0.696611 -0.006655 0.220546 -0.702493 -0.011071 0.217717 -0.702454 -0.006755 0.217717 -0.722308 -0.010418 0.207224 -0.722141 -0.008355 0.207287 -0.728619 -0.009075 0.227879 -0.728697 -0.010215 0.227821 -0.726205 -0.00882 0.230014 -0.726286 -0.010378 0.229951 -0.720548 -0.008307 0.235507 -0.717991 -0.008244 0.237749 -0.718029 -0.010646 0.237721 -0.715343 -0.008272 0.240065 -0.715415 -0.01066 0.240022 -0.712792 -0.008363 0.242222 -0.71279 -0.010593 0.242245 -0.710795 -0.010334 0.243891 -0.73198 -0.009496 0.240151 -0.732002 -0.010268 0.240125 -0.723211 -0.009464 0.177354 -0.712768 -0.009292 0.177355 -0.702412 -0.00901 0.177356 -0.697413 -0.008833 0.155785 -0.697206 -0.008991 0.067101 -0.709891 -0.008621 0.244514 -0.709216 -0.009272 0.245105 -0.721138 -0.01053 0.234713 -0.723559 -0.010428 0.2326 -0.723491 -0.008489 0.232651 -0.731973 -0.00967 0.225259 -0.729089 -0.009558 0.204444 -0.714762 -0.007587 0.211325 -0.71494 -0.010734 0.211254 -0.7098 -0.00711 0.21371 -0.709955 -0.010795 0.213652 -0.677336 -0.008622 0.22933 -0.648686 -0.008282 0.197506 -0.698476 -0.011307 0.189857 -0.706157 -0.011214 0.188685 -0.705885 -0.006773 0.188707 -0.714884 -0.011014 0.187423 -0.714583 -0.007485 0.187453 -0.723951 -0.010368 0.186039 -0.728415 -0.009538 0.185353 -0.723784 -0.008486 0.186054 -0.693008 -0.005652 0.155771 -0.693292 -0.011788 0.155799 -0.683537 -0.005177 0.155771 -0.683594 -0.01213 0.155802 -0.672785 -0.004917 0.155771 -0.672875 -0.012495 0.155805 -0.661601 -0.004948 0.155773 -0.661963 -0.012601 0.155807 -0.65027 -0.012568 0.155809 -0.633023 -0.008247 0.155792 -0.630158 -0.010929 0.067111 -0.630889 -0.006117 0.0671 -0.627786 -0.008356 0.067105 -0.636467 -0.012413 0.067113 -0.636821 -0.005438 0.067098 -0.646478 -0.013039 0.067114 -0.646396 -0.005117 0.067097 -0.65915 -0.013075 0.067113 -0.658758 -0.004781 0.067095 -0.670976 -0.01296 0.067112 -0.670879 -0.004748 0.067094 -0.682593 -0.012565 0.06711 -0.682531 -0.00503 0.067094 -0.692922 -0.012194 0.067109 -0.692614 -0.005544 0.067094 -0.692886 -0.008992 -1.2e-05 -0.682971 -0.008918 -1.2e-05 -0.671035 -0.008977 -1.2e-05 -0.658752 -0.009053 -1.2e-05 -0.64591 -0.009207 -1.2e-05 -0.635864 -0.00905 -1.2e-05 -0.629585 -0.008637 -1.2e-05 -numsurf 560 -SURF 0x30 -mat 1 -refs 3 -305 0 0 -118 0 0 -324 0 0 -SURF 0x30 -mat 1 -refs 3 -324 0 0 -325 0 0 -305 0 0 -SURF 0x30 -mat 1 -refs 3 -117 0 0 -305 0 0 -325 0 0 -SURF 0x30 -mat 1 -refs 3 -325 0 0 -324 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -304 0 0 -116 0 0 -323 0 0 -SURF 0x30 -mat 1 -refs 3 -323 0 0 -306 0 0 -304 0 0 -SURF 0x30 -mat 1 -refs 3 -119 0 0 -304 0 0 -306 0 0 -SURF 0x30 -mat 1 -refs 3 -306 0 0 -323 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -302 0 0 -117 0 0 -325 0 0 -SURF 0x30 -mat 1 -refs 3 -325 0 0 -323 0 0 -302 0 0 -SURF 0x30 -mat 1 -refs 3 -116 0 0 -302 0 0 -323 0 0 -SURF 0x30 -mat 1 -refs 3 -323 0 0 -325 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -300 0 0 -114 0 0 -322 0 0 -SURF 0x30 -mat 1 -refs 3 -322 0 0 -324 0 0 -300 0 0 -SURF 0x30 -mat 1 -refs 3 -118 0 0 -300 0 0 -324 0 0 -SURF 0x30 -mat 1 -refs 3 -324 0 0 -322 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -298 0 0 -119 0 0 -306 0 0 -SURF 0x30 -mat 1 -refs 3 -306 0 0 -321 0 0 -298 0 0 -SURF 0x30 -mat 1 -refs 3 -115 0 0 -298 0 0 -321 0 0 -SURF 0x30 -mat 1 -refs 3 -321 0 0 -306 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -297 0 0 -113 0 0 -320 0 0 -SURF 0x30 -mat 1 -refs 3 -320 0 0 -322 0 0 -297 0 0 -SURF 0x30 -mat 1 -refs 3 -114 0 0 -297 0 0 -322 0 0 -SURF 0x30 -mat 1 -refs 3 -322 0 0 -320 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -296 0 0 -115 0 0 -321 0 0 -SURF 0x30 -mat 1 -refs 3 -321 0 0 -319 0 0 -296 0 0 -SURF 0x30 -mat 1 -refs 3 -112 0 0 -296 0 0 -319 0 0 -SURF 0x30 -mat 1 -refs 3 -319 0 0 -321 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -295 0 0 -111 0 0 -318 0 0 -SURF 0x30 -mat 1 -refs 3 -318 0 0 -320 0 0 -295 0 0 -SURF 0x30 -mat 1 -refs 3 -113 0 0 -295 0 0 -320 0 0 -SURF 0x30 -mat 1 -refs 3 -320 0 0 -318 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -294 0 0 -112 0 0 -319 0 0 -SURF 0x30 -mat 1 -refs 3 -319 0 0 -317 0 0 -294 0 0 -SURF 0x30 -mat 1 -refs 3 -110 0 0 -294 0 0 -317 0 0 -SURF 0x30 -mat 1 -refs 3 -317 0 0 -319 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -293 0 0 -109 0 0 -316 0 0 -SURF 0x30 -mat 1 -refs 3 -316 0 0 -318 0 0 -293 0 0 -SURF 0x30 -mat 1 -refs 3 -111 0 0 -293 0 0 -318 0 0 -SURF 0x30 -mat 1 -refs 3 -318 0 0 -316 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -292 0 0 -110 0 0 -317 0 0 -SURF 0x30 -mat 1 -refs 3 -317 0 0 -315 0 0 -292 0 0 -SURF 0x30 -mat 1 -refs 3 -108 0 0 -292 0 0 -315 0 0 -SURF 0x30 -mat 1 -refs 3 -315 0 0 -317 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -291 0 0 -107 0 0 -314 0 0 -SURF 0x30 -mat 1 -refs 3 -314 0 0 -316 0 0 -291 0 0 -SURF 0x30 -mat 1 -refs 3 -109 0 0 -291 0 0 -316 0 0 -SURF 0x30 -mat 1 -refs 3 -316 0 0 -314 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -289 0 0 -108 0 0 -315 0 0 -SURF 0x30 -mat 1 -refs 3 -315 0 0 -313 0 0 -289 0 0 -SURF 0x30 -mat 1 -refs 3 -106 0 0 -289 0 0 -313 0 0 -SURF 0x30 -mat 1 -refs 3 -313 0 0 -315 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -280 0 0 -101 0 0 -310 0 0 -SURF 0x30 -mat 1 -refs 3 -310 0 0 -312 0 0 -280 0 0 -SURF 0x30 -mat 1 -refs 3 -103 0 0 -280 0 0 -312 0 0 -SURF 0x30 -mat 1 -refs 3 -312 0 0 -310 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -279 0 0 -102 0 0 -311 0 0 -SURF 0x30 -mat 1 -refs 3 -311 0 0 -309 0 0 -279 0 0 -SURF 0x30 -mat 1 -refs 3 -100 0 0 -279 0 0 -309 0 0 -SURF 0x30 -mat 1 -refs 3 -309 0 0 -311 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -278 0 0 -98 0 0 -308 0 0 -SURF 0x30 -mat 1 -refs 3 -308 0 0 -310 0 0 -278 0 0 -SURF 0x30 -mat 1 -refs 3 -101 0 0 -278 0 0 -310 0 0 -SURF 0x30 -mat 1 -refs 3 -310 0 0 -308 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -277 0 0 -99 0 0 -307 0 0 -SURF 0x30 -mat 1 -refs 3 -307 0 0 -308 0 0 -277 0 0 -SURF 0x30 -mat 1 -refs 3 -98 0 0 -277 0 0 -308 0 0 -SURF 0x30 -mat 1 -refs 3 -308 0 0 -307 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -275 0 0 -100 0 0 -309 0 0 -SURF 0x30 -mat 1 -refs 3 -309 0 0 -307 0 0 -275 0 0 -SURF 0x30 -mat 1 -refs 3 -99 0 0 -275 0 0 -307 0 0 -SURF 0x30 -mat 1 -refs 3 -307 0 0 -309 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 3 -243 0 0 -77 0 0 -330 0 0 -SURF 0x30 -mat 1 -refs 3 -330 0 0 -303 0 0 -243 0 0 -SURF 0x30 -mat 1 -refs 3 -78 0 0 -243 0 0 -303 0 0 -SURF 0x30 -mat 1 -refs 3 -303 0 0 -330 0 0 -117 0 0 -SURF 0x30 -mat 1 -refs 3 -248 0 0 -76 0 0 -299 0 0 -SURF 0x30 -mat 1 -refs 3 -299 0 0 -332 0 0 -248 0 0 -SURF 0x30 -mat 1 -refs 3 -80 0 0 -248 0 0 -332 0 0 -SURF 0x30 -mat 1 -refs 3 -332 0 0 -299 0 0 -119 0 0 -SURF 0x30 -mat 1 -refs 3 -337 0 0 -86 0 0 -290 0 0 -SURF 0x30 -mat 1 -refs 3 -290 0 0 -293 0 0 -337 0 0 -SURF 0x30 -mat 1 -refs 3 -111 0 0 -337 0 0 -293 0 0 -SURF 0x30 -mat 1 -refs 3 -293 0 0 -290 0 0 -109 0 0 -SURF 0x30 -mat 1 -refs 3 -286 0 0 -89 0 0 -339 0 0 -SURF 0x30 -mat 1 -refs 3 -339 0 0 -289 0 0 -286 0 0 -SURF 0x30 -mat 1 -refs 3 -106 0 0 -286 0 0 -289 0 0 -SURF 0x30 -mat 1 -refs 3 -289 0 0 -339 0 0 -108 0 0 -SURF 0x30 -mat 1 -refs 3 -283 0 0 -90 0 0 -340 0 0 -SURF 0x30 -mat 1 -refs 3 -340 0 0 -284 0 0 -283 0 0 -SURF 0x30 -mat 1 -refs 3 -105 0 0 -283 0 0 -284 0 0 -SURF 0x30 -mat 1 -refs 3 -284 0 0 -340 0 0 -103 0 0 -SURF 0x30 -mat 1 -refs 3 -341 0 0 -91 0 0 -282 0 0 -SURF 0x30 -mat 1 -refs 3 -282 0 0 -281 0 0 -341 0 0 -SURF 0x30 -mat 1 -refs 3 -102 0 0 -341 0 0 -281 0 0 -SURF 0x30 -mat 1 -refs 3 -281 0 0 -282 0 0 -104 0 0 -SURF 0x30 -mat 1 -refs 3 -269 0 0 -97 0 0 -276 0 0 -SURF 0x30 -mat 1 -refs 3 -276 0 0 -344 0 0 -269 0 0 -SURF 0x30 -mat 1 -refs 3 -94 0 0 -269 0 0 -344 0 0 -SURF 0x30 -mat 1 -refs 3 -344 0 0 -276 0 0 -98 0 0 -SURF 0x30 -mat 1 -refs 3 -273 0 0 -95 0 0 -345 0 0 -SURF 0x30 -mat 1 -refs 3 -345 0 0 -274 0 0 -273 0 0 -SURF 0x30 -mat 1 -refs 3 -96 0 0 -273 0 0 -274 0 0 -SURF 0x30 -mat 1 -refs 3 -274 0 0 -345 0 0 -99 0 0 -SURF 0x30 -mat 1 -refs 3 -210 0 0 -56 0 0 -346 0 0 -SURF 0x30 -mat 1 -refs 3 -346 0 0 -272 0 0 -210 0 0 -SURF 0x30 -mat 1 -refs 3 -55 0 0 -210 0 0 -272 0 0 -SURF 0x30 -mat 1 -refs 3 -272 0 0 -346 0 0 -96 0 0 -SURF 0x30 -mat 1 -refs 3 -215 0 0 -54 0 0 -270 0 0 -SURF 0x30 -mat 1 -refs 3 -270 0 0 -347 0 0 -215 0 0 -SURF 0x30 -mat 1 -refs 3 -57 0 0 -215 0 0 -347 0 0 -SURF 0x30 -mat 1 -refs 3 -347 0 0 -270 0 0 -97 0 0 -SURF 0x30 -mat 1 -refs 3 -348 0 0 -58 0 0 -265 0 0 -SURF 0x30 -mat 1 -refs 3 -265 0 0 -268 0 0 -348 0 0 -SURF 0x30 -mat 1 -refs 3 -95 0 0 -348 0 0 -268 0 0 -SURF 0x30 -mat 1 -refs 3 -268 0 0 -265 0 0 -93 0 0 -SURF 0x30 -mat 1 -refs 3 -264 0 0 -59 0 0 -349 0 0 -SURF 0x30 -mat 1 -refs 3 -349 0 0 -267 0 0 -264 0 0 -SURF 0x30 -mat 1 -refs 3 -92 0 0 -264 0 0 -267 0 0 -SURF 0x30 -mat 1 -refs 3 -267 0 0 -349 0 0 -94 0 0 -SURF 0x30 -mat 1 -refs 3 -257 0 0 -62 0 0 -350 0 0 -SURF 0x30 -mat 1 -refs 3 -350 0 0 -258 0 0 -257 0 0 -SURF 0x30 -mat 1 -refs 3 -89 0 0 -257 0 0 -258 0 0 -SURF 0x30 -mat 1 -refs 3 -258 0 0 -350 0 0 -87 0 0 -SURF 0x30 -mat 1 -refs 3 -351 0 0 -63 0 0 -256 0 0 -SURF 0x30 -mat 1 -refs 3 -256 0 0 -255 0 0 -351 0 0 -SURF 0x30 -mat 1 -refs 3 -86 0 0 -351 0 0 -255 0 0 -SURF 0x30 -mat 1 -refs 3 -255 0 0 -256 0 0 -88 0 0 -SURF 0x30 -mat 1 -refs 3 -240 0 0 -72 0 0 -245 0 0 -SURF 0x30 -mat 1 -refs 3 -245 0 0 -360 0 0 -240 0 0 -SURF 0x30 -mat 1 -refs 3 -75 0 0 -240 0 0 -360 0 0 -SURF 0x30 -mat 1 -refs 3 -360 0 0 -245 0 0 -79 0 0 -SURF 0x30 -mat 1 -refs 3 -241 0 0 -74 0 0 -361 0 0 -SURF 0x30 -mat 1 -refs 3 -361 0 0 -242 0 0 -241 0 0 -SURF 0x30 -mat 1 -refs 3 -73 0 0 -241 0 0 -242 0 0 -SURF 0x30 -mat 1 -refs 3 -242 0 0 -361 0 0 -78 0 0 -SURF 0x30 -mat 1 -refs 3 -175 0 0 -33 0 0 -362 0 0 -SURF 0x30 -mat 1 -refs 3 -362 0 0 -239 0 0 -175 0 0 -SURF 0x30 -mat 1 -refs 3 -34 0 0 -175 0 0 -239 0 0 -SURF 0x30 -mat 1 -refs 3 -239 0 0 -362 0 0 -73 0 0 -SURF 0x30 -mat 1 -refs 3 -176 0 0 -35 0 0 -237 0 0 -SURF 0x30 -mat 1 -refs 3 -237 0 0 -363 0 0 -176 0 0 -SURF 0x30 -mat 1 -refs 3 -32 0 0 -176 0 0 -363 0 0 -SURF 0x30 -mat 1 -refs 3 -363 0 0 -237 0 0 -72 0 0 -SURF 0x30 -mat 1 -refs 3 -372 0 0 -44 0 0 -225 0 0 -SURF 0x30 -mat 1 -refs 3 -225 0 0 -228 0 0 -372 0 0 -SURF 0x30 -mat 1 -refs 3 -65 0 0 -372 0 0 -228 0 0 -SURF 0x30 -mat 1 -refs 3 -228 0 0 -225 0 0 -63 0 0 -SURF 0x30 -mat 1 -refs 3 -221 0 0 -47 0 0 -374 0 0 -SURF 0x30 -mat 1 -refs 3 -374 0 0 -224 0 0 -221 0 0 -SURF 0x30 -mat 1 -refs 3 -60 0 0 -221 0 0 -224 0 0 -SURF 0x30 -mat 1 -refs 3 -224 0 0 -374 0 0 -62 0 0 -SURF 0x30 -mat 1 -refs 3 -184 0 0 -24 0 0 -375 0 0 -SURF 0x30 -mat 1 -refs 3 -375 0 0 -185 0 0 -184 0 0 -SURF 0x30 -mat 1 -refs 3 -39 0 0 -184 0 0 -185 0 0 -SURF 0x30 -mat 1 -refs 3 -185 0 0 -375 0 0 -36 0 0 -SURF 0x30 -mat 1 -refs 3 -377 0 0 -26 0 0 -180 0 0 -SURF 0x30 -mat 1 -refs 3 -180 0 0 -179 0 0 -377 0 0 -SURF 0x30 -mat 1 -refs 3 -33 0 0 -377 0 0 -179 0 0 -SURF 0x30 -mat 1 -refs 3 -179 0 0 -180 0 0 -37 0 0 -SURF 0x30 -mat 1 -refs 3 -172 0 0 -28 0 0 -177 0 0 -SURF 0x30 -mat 1 -refs 3 -177 0 0 -378 0 0 -172 0 0 -SURF 0x30 -mat 1 -refs 3 -31 0 0 -172 0 0 -378 0 0 -SURF 0x30 -mat 1 -refs 3 -378 0 0 -177 0 0 -35 0 0 -SURF 0x30 -mat 1 -refs 3 -173 0 0 -30 0 0 -379 0 0 -SURF 0x30 -mat 1 -refs 3 -379 0 0 -174 0 0 -173 0 0 -SURF 0x30 -mat 1 -refs 3 -29 0 0 -173 0 0 -174 0 0 -SURF 0x30 -mat 1 -refs 3 -174 0 0 -379 0 0 -34 0 0 -SURF 0x30 -mat 1 -refs 4 -377 0 0 -33 0 0 -175 0 0 -380 0 0 -SURF 0x30 -mat 1 -refs 4 -26 0 0 -377 0 0 -380 0 0 -168 0 0 -SURF 0x30 -mat 1 -refs 4 -380 0 0 -175 0 0 -34 0 0 -379 0 0 -SURF 0x30 -mat 1 -refs 4 -168 0 0 -380 0 0 -379 0 0 -30 0 0 -SURF 0x30 -mat 1 -refs 4 -165 0 0 -31 0 0 -378 0 0 -381 0 0 -SURF 0x30 -mat 1 -refs 4 -27 0 0 -165 0 0 -381 0 0 -376 0 0 -SURF 0x30 -mat 1 -refs 4 -381 0 0 -378 0 0 -35 0 0 -176 0 0 -SURF 0x30 -mat 1 -refs 4 -376 0 0 -381 0 0 -176 0 0 -32 0 0 -SURF 0x30 -mat 1 -refs 4 -161 0 0 -27 0 0 -376 0 0 -382 0 0 -SURF 0x30 -mat 1 -refs 4 -24 0 0 -161 0 0 -382 0 0 -375 0 0 -SURF 0x30 -mat 1 -refs 4 -382 0 0 -376 0 0 -32 0 0 -181 0 0 -SURF 0x30 -mat 1 -refs 4 -375 0 0 -382 0 0 -181 0 0 -36 0 0 -SURF 0x30 -mat 1 -refs 4 -227 0 0 -62 0 0 -374 0 0 -383 0 0 -SURF 0x30 -mat 1 -refs 4 -64 0 0 -227 0 0 -383 0 0 -373 0 0 -SURF 0x30 -mat 1 -refs 4 -383 0 0 -374 0 0 -47 0 0 -201 0 0 -SURF 0x30 -mat 1 -refs 4 -373 0 0 -383 0 0 -201 0 0 -45 0 0 -SURF 0x30 -mat 1 -refs 4 -229 0 0 -64 0 0 -373 0 0 -384 0 0 -SURF 0x30 -mat 1 -refs 4 -66 0 0 -229 0 0 -384 0 0 -371 0 0 -SURF 0x30 -mat 1 -refs 4 -384 0 0 -373 0 0 -45 0 0 -197 0 0 -SURF 0x30 -mat 1 -refs 4 -371 0 0 -384 0 0 -197 0 0 -43 0 0 -SURF 0x30 -mat 1 -refs 4 -370 0 0 -42 0 0 -194 0 0 -385 0 0 -SURF 0x30 -mat 1 -refs 4 -67 0 0 -370 0 0 -385 0 0 -230 0 0 -SURF 0x30 -mat 1 -refs 4 -385 0 0 -194 0 0 -44 0 0 -372 0 0 -SURF 0x30 -mat 1 -refs 4 -230 0 0 -385 0 0 -372 0 0 -65 0 0 -SURF 0x30 -mat 1 -refs 4 -231 0 0 -66 0 0 -371 0 0 -386 0 0 -SURF 0x30 -mat 1 -refs 4 -68 0 0 -231 0 0 -386 0 0 -369 0 0 -SURF 0x30 -mat 1 -refs 4 -386 0 0 -371 0 0 -43 0 0 -193 0 0 -SURF 0x30 -mat 1 -refs 4 -369 0 0 -386 0 0 -193 0 0 -41 0 0 -SURF 0x30 -mat 1 -refs 4 -368 0 0 -40 0 0 -190 0 0 -387 0 0 -SURF 0x30 -mat 1 -refs 4 -69 0 0 -368 0 0 -387 0 0 -232 0 0 -SURF 0x30 -mat 1 -refs 4 -387 0 0 -190 0 0 -42 0 0 -370 0 0 -SURF 0x30 -mat 1 -refs 4 -232 0 0 -387 0 0 -370 0 0 -67 0 0 -SURF 0x30 -mat 1 -refs 4 -233 0 0 -68 0 0 -369 0 0 -388 0 0 -SURF 0x30 -mat 1 -refs 4 -71 0 0 -233 0 0 -388 0 0 -367 0 0 -SURF 0x30 -mat 1 -refs 4 -388 0 0 -369 0 0 -41 0 0 -189 0 0 -SURF 0x30 -mat 1 -refs 4 -367 0 0 -388 0 0 -189 0 0 -39 0 0 -SURF 0x30 -mat 1 -refs 4 -366 0 0 -38 0 0 -186 0 0 -389 0 0 -SURF 0x30 -mat 1 -refs 4 -70 0 0 -366 0 0 -389 0 0 -234 0 0 -SURF 0x30 -mat 1 -refs 4 -389 0 0 -186 0 0 -40 0 0 -368 0 0 -SURF 0x30 -mat 1 -refs 4 -234 0 0 -389 0 0 -368 0 0 -69 0 0 -SURF 0x30 -mat 1 -refs 4 -235 0 0 -71 0 0 -367 0 0 -390 0 0 -SURF 0x30 -mat 1 -refs 4 -75 0 0 -235 0 0 -390 0 0 -365 0 0 -SURF 0x30 -mat 1 -refs 4 -390 0 0 -367 0 0 -39 0 0 -185 0 0 -SURF 0x30 -mat 1 -refs 4 -365 0 0 -390 0 0 -185 0 0 -36 0 0 -SURF 0x30 -mat 1 -refs 4 -364 0 0 -37 0 0 -182 0 0 -391 0 0 -SURF 0x30 -mat 1 -refs 4 -74 0 0 -364 0 0 -391 0 0 -236 0 0 -SURF 0x30 -mat 1 -refs 4 -391 0 0 -182 0 0 -38 0 0 -366 0 0 -SURF 0x30 -mat 1 -refs 4 -236 0 0 -391 0 0 -366 0 0 -70 0 0 -SURF 0x30 -mat 1 -refs 4 -240 0 0 -75 0 0 -365 0 0 -392 0 0 -SURF 0x30 -mat 1 -refs 4 -72 0 0 -240 0 0 -392 0 0 -363 0 0 -SURF 0x30 -mat 1 -refs 4 -392 0 0 -365 0 0 -36 0 0 -181 0 0 -SURF 0x30 -mat 1 -refs 4 -363 0 0 -392 0 0 -181 0 0 -32 0 0 -SURF 0x30 -mat 1 -refs 4 -362 0 0 -33 0 0 -179 0 0 -393 0 0 -SURF 0x30 -mat 1 -refs 4 -73 0 0 -362 0 0 -393 0 0 -241 0 0 -SURF 0x30 -mat 1 -refs 4 -393 0 0 -179 0 0 -37 0 0 -364 0 0 -SURF 0x30 -mat 1 -refs 4 -241 0 0 -393 0 0 -364 0 0 -74 0 0 -SURF 0x30 -mat 1 -refs 4 -359 0 0 -77 0 0 -243 0 0 -394 0 0 -SURF 0x30 -mat 1 -refs 4 -70 0 0 -359 0 0 -394 0 0 -236 0 0 -SURF 0x30 -mat 1 -refs 4 -394 0 0 -243 0 0 -78 0 0 -361 0 0 -SURF 0x30 -mat 1 -refs 4 -236 0 0 -394 0 0 -361 0 0 -74 0 0 -SURF 0x30 -mat 1 -refs 4 -235 0 0 -75 0 0 -360 0 0 -395 0 0 -SURF 0x30 -mat 1 -refs 4 -71 0 0 -235 0 0 -395 0 0 -358 0 0 -SURF 0x30 -mat 1 -refs 4 -395 0 0 -360 0 0 -79 0 0 -244 0 0 -SURF 0x30 -mat 1 -refs 4 -358 0 0 -395 0 0 -244 0 0 -76 0 0 -SURF 0x30 -mat 1 -refs 4 -357 0 0 -81 0 0 -247 0 0 -396 0 0 -SURF 0x30 -mat 1 -refs 4 -69 0 0 -357 0 0 -396 0 0 -234 0 0 -SURF 0x30 -mat 1 -refs 4 -396 0 0 -247 0 0 -77 0 0 -359 0 0 -SURF 0x30 -mat 1 -refs 4 -234 0 0 -396 0 0 -359 0 0 -70 0 0 -SURF 0x30 -mat 1 -refs 4 -233 0 0 -71 0 0 -358 0 0 -397 0 0 -SURF 0x30 -mat 1 -refs 4 -68 0 0 -233 0 0 -397 0 0 -356 0 0 -SURF 0x30 -mat 1 -refs 4 -397 0 0 -358 0 0 -76 0 0 -248 0 0 -SURF 0x30 -mat 1 -refs 4 -356 0 0 -397 0 0 -248 0 0 -80 0 0 -SURF 0x30 -mat 1 -refs 4 -355 0 0 -82 0 0 -249 0 0 -398 0 0 -SURF 0x30 -mat 1 -refs 4 -67 0 0 -355 0 0 -398 0 0 -232 0 0 -SURF 0x30 -mat 1 -refs 4 -398 0 0 -249 0 0 -81 0 0 -357 0 0 -SURF 0x30 -mat 1 -refs 4 -232 0 0 -398 0 0 -357 0 0 -69 0 0 -SURF 0x30 -mat 1 -refs 4 -231 0 0 -68 0 0 -356 0 0 -399 0 0 -SURF 0x30 -mat 1 -refs 4 -66 0 0 -231 0 0 -399 0 0 -354 0 0 -SURF 0x30 -mat 1 -refs 4 -399 0 0 -356 0 0 -80 0 0 -250 0 0 -SURF 0x30 -mat 1 -refs 4 -354 0 0 -399 0 0 -250 0 0 -83 0 0 -SURF 0x30 -mat 1 -refs 4 -353 0 0 -84 0 0 -251 0 0 -400 0 0 -SURF 0x30 -mat 1 -refs 4 -65 0 0 -353 0 0 -400 0 0 -230 0 0 -SURF 0x30 -mat 1 -refs 4 -400 0 0 -251 0 0 -82 0 0 -355 0 0 -SURF 0x30 -mat 1 -refs 4 -230 0 0 -400 0 0 -355 0 0 -67 0 0 -SURF 0x30 -mat 1 -refs 4 -229 0 0 -66 0 0 -354 0 0 -401 0 0 -SURF 0x30 -mat 1 -refs 4 -64 0 0 -229 0 0 -401 0 0 -352 0 0 -SURF 0x30 -mat 1 -refs 4 -401 0 0 -354 0 0 -83 0 0 -252 0 0 -SURF 0x30 -mat 1 -refs 4 -352 0 0 -401 0 0 -252 0 0 -85 0 0 -SURF 0x30 -mat 1 -refs 4 -351 0 0 -86 0 0 -253 0 0 -402 0 0 -SURF 0x30 -mat 1 -refs 4 -63 0 0 -351 0 0 -402 0 0 -228 0 0 -SURF 0x30 -mat 1 -refs 4 -402 0 0 -253 0 0 -84 0 0 -353 0 0 -SURF 0x30 -mat 1 -refs 4 -228 0 0 -402 0 0 -353 0 0 -65 0 0 -SURF 0x30 -mat 1 -refs 4 -227 0 0 -64 0 0 -352 0 0 -403 0 0 -SURF 0x30 -mat 1 -refs 4 -62 0 0 -227 0 0 -403 0 0 -350 0 0 -SURF 0x30 -mat 1 -refs 4 -403 0 0 -352 0 0 -85 0 0 -254 0 0 -SURF 0x30 -mat 1 -refs 4 -350 0 0 -403 0 0 -254 0 0 -87 0 0 -SURF 0x30 -mat 1 -refs 4 -269 0 0 -94 0 0 -349 0 0 -404 0 0 -SURF 0x30 -mat 1 -refs 4 -97 0 0 -269 0 0 -404 0 0 -347 0 0 -SURF 0x30 -mat 1 -refs 4 -404 0 0 -349 0 0 -59 0 0 -219 0 0 -SURF 0x30 -mat 1 -refs 4 -347 0 0 -404 0 0 -219 0 0 -57 0 0 -SURF 0x30 -mat 1 -refs 4 -346 0 0 -56 0 0 -216 0 0 -405 0 0 -SURF 0x30 -mat 1 -refs 4 -96 0 0 -346 0 0 -405 0 0 -273 0 0 -SURF 0x30 -mat 1 -refs 4 -405 0 0 -216 0 0 -58 0 0 -348 0 0 -SURF 0x30 -mat 1 -refs 4 -273 0 0 -405 0 0 -348 0 0 -95 0 0 -SURF 0x30 -mat 1 -refs 4 -343 0 0 -100 0 0 -275 0 0 -406 0 0 -SURF 0x30 -mat 1 -refs 4 -93 0 0 -343 0 0 -406 0 0 -268 0 0 -SURF 0x30 -mat 1 -refs 4 -406 0 0 -275 0 0 -99 0 0 -345 0 0 -SURF 0x30 -mat 1 -refs 4 -268 0 0 -406 0 0 -345 0 0 -95 0 0 -SURF 0x30 -mat 1 -refs 4 -267 0 0 -94 0 0 -344 0 0 -407 0 0 -SURF 0x30 -mat 1 -refs 4 -92 0 0 -267 0 0 -407 0 0 -342 0 0 -SURF 0x30 -mat 1 -refs 4 -407 0 0 -344 0 0 -98 0 0 -278 0 0 -SURF 0x30 -mat 1 -refs 4 -342 0 0 -407 0 0 -278 0 0 -101 0 0 -SURF 0x30 -mat 1 -refs 4 -341 0 0 -102 0 0 -279 0 0 -408 0 0 -SURF 0x30 -mat 1 -refs 4 -91 0 0 -341 0 0 -408 0 0 -266 0 0 -SURF 0x30 -mat 1 -refs 4 -408 0 0 -279 0 0 -100 0 0 -343 0 0 -SURF 0x30 -mat 1 -refs 4 -266 0 0 -408 0 0 -343 0 0 -93 0 0 -SURF 0x30 -mat 1 -refs 4 -263 0 0 -92 0 0 -342 0 0 -409 0 0 -SURF 0x30 -mat 1 -refs 4 -90 0 0 -263 0 0 -409 0 0 -340 0 0 -SURF 0x30 -mat 1 -refs 4 -409 0 0 -342 0 0 -101 0 0 -280 0 0 -SURF 0x30 -mat 1 -refs 4 -340 0 0 -409 0 0 -280 0 0 -103 0 0 -SURF 0x30 -mat 1 -refs 4 -292 0 0 -108 0 0 -339 0 0 -410 0 0 -SURF 0x30 -mat 1 -refs 4 -110 0 0 -292 0 0 -410 0 0 -338 0 0 -SURF 0x30 -mat 1 -refs 4 -410 0 0 -339 0 0 -89 0 0 -258 0 0 -SURF 0x30 -mat 1 -refs 4 -338 0 0 -410 0 0 -258 0 0 -87 0 0 -SURF 0x30 -mat 1 -refs 4 -294 0 0 -110 0 0 -338 0 0 -411 0 0 -SURF 0x30 -mat 1 -refs 4 -112 0 0 -294 0 0 -411 0 0 -336 0 0 -SURF 0x30 -mat 1 -refs 4 -411 0 0 -338 0 0 -87 0 0 -254 0 0 -SURF 0x30 -mat 1 -refs 4 -336 0 0 -411 0 0 -254 0 0 -85 0 0 -SURF 0x30 -mat 1 -refs 4 -335 0 0 -84 0 0 -253 0 0 -412 0 0 -SURF 0x30 -mat 1 -refs 4 -113 0 0 -335 0 0 -412 0 0 -295 0 0 -SURF 0x30 -mat 1 -refs 4 -412 0 0 -253 0 0 -86 0 0 -337 0 0 -SURF 0x30 -mat 1 -refs 4 -295 0 0 -412 0 0 -337 0 0 -111 0 0 -SURF 0x30 -mat 1 -refs 4 -296 0 0 -112 0 0 -336 0 0 -413 0 0 -SURF 0x30 -mat 1 -refs 4 -115 0 0 -296 0 0 -413 0 0 -334 0 0 -SURF 0x30 -mat 1 -refs 4 -413 0 0 -336 0 0 -85 0 0 -252 0 0 -SURF 0x30 -mat 1 -refs 4 -334 0 0 -413 0 0 -252 0 0 -83 0 0 -SURF 0x30 -mat 1 -refs 4 -333 0 0 -82 0 0 -251 0 0 -414 0 0 -SURF 0x30 -mat 1 -refs 4 -114 0 0 -333 0 0 -414 0 0 -297 0 0 -SURF 0x30 -mat 1 -refs 4 -414 0 0 -251 0 0 -84 0 0 -335 0 0 -SURF 0x30 -mat 1 -refs 4 -297 0 0 -414 0 0 -335 0 0 -113 0 0 -SURF 0x30 -mat 1 -refs 4 -298 0 0 -115 0 0 -334 0 0 -415 0 0 -SURF 0x30 -mat 1 -refs 4 -119 0 0 -298 0 0 -415 0 0 -332 0 0 -SURF 0x30 -mat 1 -refs 4 -415 0 0 -334 0 0 -83 0 0 -250 0 0 -SURF 0x30 -mat 1 -refs 4 -332 0 0 -415 0 0 -250 0 0 -80 0 0 -SURF 0x30 -mat 1 -refs 4 -331 0 0 -81 0 0 -249 0 0 -416 0 0 -SURF 0x30 -mat 1 -refs 4 -118 0 0 -331 0 0 -416 0 0 -300 0 0 -SURF 0x30 -mat 1 -refs 4 -416 0 0 -249 0 0 -82 0 0 -333 0 0 -SURF 0x30 -mat 1 -refs 4 -300 0 0 -416 0 0 -333 0 0 -114 0 0 -SURF 0x30 -mat 1 -refs 4 -330 0 0 -77 0 0 -247 0 0 -417 0 0 -SURF 0x30 -mat 1 -refs 4 -117 0 0 -330 0 0 -417 0 0 -305 0 0 -SURF 0x30 -mat 1 -refs 4 -417 0 0 -247 0 0 -81 0 0 -331 0 0 -SURF 0x30 -mat 1 -refs 4 -305 0 0 -417 0 0 -331 0 0 -118 0 0 -SURF 0x30 -mat 1 -refs 4 -313 0 0 -120 0 0 -311 0 0 -418 0 0 -SURF 0x30 -mat 1 -refs 4 -106 0 0 -313 0 0 -418 0 0 -285 0 0 -SURF 0x30 -mat 1 -refs 4 -418 0 0 -311 0 0 -102 0 0 -281 0 0 -SURF 0x30 -mat 1 -refs 4 -285 0 0 -418 0 0 -281 0 0 -104 0 0 -SURF 0x30 -mat 1 -refs 4 -288 0 0 -105 0 0 -284 0 0 -419 0 0 -SURF 0x30 -mat 1 -refs 4 -107 0 0 -288 0 0 -419 0 0 -314 0 0 -SURF 0x30 -mat 1 -refs 4 -419 0 0 -284 0 0 -103 0 0 -312 0 0 -SURF 0x30 -mat 1 -refs 4 -314 0 0 -419 0 0 -312 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 4 -206 0 0 -50 0 0 -329 0 0 -420 0 0 -SURF 0x30 -mat 1 -refs 4 -53 0 0 -206 0 0 -420 0 0 -207 0 0 -SURF 0x30 -mat 1 -refs 4 -420 0 0 -329 0 0 -51 0 0 -208 0 0 -SURF 0x30 -mat 1 -refs 4 -207 0 0 -420 0 0 -208 0 0 -52 0 0 -SURF 0x30 -mat 1 -refs 4 -204 0 0 -48 0 0 -328 0 0 -421 0 0 -SURF 0x30 -mat 1 -refs 4 -50 0 0 -204 0 0 -421 0 0 -329 0 0 -SURF 0x30 -mat 1 -refs 4 -421 0 0 -328 0 0 -49 0 0 -205 0 0 -SURF 0x30 -mat 1 -refs 4 -329 0 0 -421 0 0 -205 0 0 -51 0 0 -SURF 0x30 -mat 1 -refs 4 -202 0 0 -46 0 0 -327 0 0 -422 0 0 -SURF 0x30 -mat 1 -refs 4 -48 0 0 -202 0 0 -422 0 0 -328 0 0 -SURF 0x30 -mat 1 -refs 4 -422 0 0 -327 0 0 -47 0 0 -203 0 0 -SURF 0x30 -mat 1 -refs 4 -328 0 0 -422 0 0 -203 0 0 -49 0 0 -SURF 0x30 -mat 1 -refs 4 -200 0 0 -47 0 0 -327 0 0 -423 0 0 -SURF 0x30 -mat 1 -refs 4 -16 0 0 -200 0 0 -423 0 0 -326 0 0 -SURF 0x30 -mat 1 -refs 4 -423 0 0 -327 0 0 -46 0 0 -199 0 0 -SURF 0x30 -mat 1 -refs 4 -326 0 0 -423 0 0 -199 0 0 -17 0 0 -SURF 0x30 -mat 1 -refs 4 -144 0 0 -14 0 0 -141 0 0 -424 0 0 -SURF 0x30 -mat 1 -refs 4 -17 0 0 -144 0 0 -424 0 0 -326 0 0 -SURF 0x30 -mat 1 -refs 4 -424 0 0 -141 0 0 -15 0 0 -143 0 0 -SURF 0x30 -mat 1 -refs 4 -326 0 0 -424 0 0 -143 0 0 -16 0 0 -SURF 0x30 -mat 1 -refs 4 -301 0 0 -116 0 0 -304 0 0 -425 0 0 -SURF 0x30 -mat 1 -refs 4 -79 0 0 -301 0 0 -425 0 0 -244 0 0 -SURF 0x30 -mat 1 -refs 4 -425 0 0 -304 0 0 -119 0 0 -299 0 0 -SURF 0x30 -mat 1 -refs 4 -244 0 0 -425 0 0 -299 0 0 -76 0 0 -SURF 0x30 -mat 1 -refs 4 -303 0 0 -117 0 0 -302 0 0 -426 0 0 -SURF 0x30 -mat 1 -refs 4 -78 0 0 -303 0 0 -426 0 0 -246 0 0 -SURF 0x30 -mat 1 -refs 4 -426 0 0 -302 0 0 -116 0 0 -301 0 0 -SURF 0x30 -mat 1 -refs 4 -246 0 0 -426 0 0 -301 0 0 -79 0 0 -SURF 0x30 -mat 1 -refs 4 -255 0 0 -88 0 0 -287 0 0 -427 0 0 -SURF 0x30 -mat 1 -refs 4 -86 0 0 -255 0 0 -427 0 0 -290 0 0 -SURF 0x30 -mat 1 -refs 4 -427 0 0 -287 0 0 -107 0 0 -291 0 0 -SURF 0x30 -mat 1 -refs 4 -290 0 0 -427 0 0 -291 0 0 -109 0 0 -SURF 0x30 -mat 1 -refs 4 -259 0 0 -90 0 0 -283 0 0 -428 0 0 -SURF 0x30 -mat 1 -refs 4 -88 0 0 -259 0 0 -428 0 0 -287 0 0 -SURF 0x30 -mat 1 -refs 4 -428 0 0 -283 0 0 -105 0 0 -288 0 0 -SURF 0x30 -mat 1 -refs 4 -287 0 0 -428 0 0 -288 0 0 -107 0 0 -SURF 0x30 -mat 1 -refs 4 -286 0 0 -106 0 0 -285 0 0 -429 0 0 -SURF 0x30 -mat 1 -refs 4 -89 0 0 -286 0 0 -429 0 0 -262 0 0 -SURF 0x30 -mat 1 -refs 4 -429 0 0 -285 0 0 -104 0 0 -282 0 0 -SURF 0x30 -mat 1 -refs 4 -262 0 0 -429 0 0 -282 0 0 -91 0 0 -SURF 0x30 -mat 1 -refs 4 -274 0 0 -99 0 0 -277 0 0 -430 0 0 -SURF 0x30 -mat 1 -refs 4 -96 0 0 -274 0 0 -430 0 0 -271 0 0 -SURF 0x30 -mat 1 -refs 4 -430 0 0 -277 0 0 -98 0 0 -276 0 0 -SURF 0x30 -mat 1 -refs 4 -271 0 0 -430 0 0 -276 0 0 -97 0 0 -SURF 0x30 -mat 1 -refs 4 -272 0 0 -96 0 0 -271 0 0 -431 0 0 -SURF 0x30 -mat 1 -refs 4 -55 0 0 -272 0 0 -431 0 0 -213 0 0 -SURF 0x30 -mat 1 -refs 4 -431 0 0 -271 0 0 -97 0 0 -270 0 0 -SURF 0x30 -mat 1 -refs 4 -213 0 0 -431 0 0 -270 0 0 -54 0 0 -SURF 0x30 -mat 1 -refs 4 -220 0 0 -60 0 0 -261 0 0 -432 0 0 -SURF 0x30 -mat 1 -refs 4 -58 0 0 -220 0 0 -432 0 0 -265 0 0 -SURF 0x30 -mat 1 -refs 4 -432 0 0 -261 0 0 -91 0 0 -266 0 0 -SURF 0x30 -mat 1 -refs 4 -265 0 0 -432 0 0 -266 0 0 -93 0 0 -SURF 0x30 -mat 1 -refs 4 -264 0 0 -92 0 0 -263 0 0 -433 0 0 -SURF 0x30 -mat 1 -refs 4 -59 0 0 -264 0 0 -433 0 0 -223 0 0 -SURF 0x30 -mat 1 -refs 4 -433 0 0 -263 0 0 -90 0 0 -260 0 0 -SURF 0x30 -mat 1 -refs 4 -223 0 0 -433 0 0 -260 0 0 -61 0 0 -SURF 0x30 -mat 1 -refs 4 -257 0 0 -89 0 0 -262 0 0 -434 0 0 -SURF 0x30 -mat 1 -refs 4 -62 0 0 -257 0 0 -434 0 0 -224 0 0 -SURF 0x30 -mat 1 -refs 4 -434 0 0 -262 0 0 -91 0 0 -261 0 0 -SURF 0x30 -mat 1 -refs 4 -224 0 0 -434 0 0 -261 0 0 -60 0 0 -SURF 0x30 -mat 1 -refs 4 -226 0 0 -61 0 0 -260 0 0 -435 0 0 -SURF 0x30 -mat 1 -refs 4 -63 0 0 -226 0 0 -435 0 0 -256 0 0 -SURF 0x30 -mat 1 -refs 4 -435 0 0 -260 0 0 -90 0 0 -259 0 0 -SURF 0x30 -mat 1 -refs 4 -256 0 0 -435 0 0 -259 0 0 -88 0 0 -SURF 0x30 -mat 1 -refs 4 -242 0 0 -78 0 0 -246 0 0 -436 0 0 -SURF 0x30 -mat 1 -refs 4 -73 0 0 -242 0 0 -436 0 0 -238 0 0 -SURF 0x30 -mat 1 -refs 4 -436 0 0 -246 0 0 -79 0 0 -245 0 0 -SURF 0x30 -mat 1 -refs 4 -238 0 0 -436 0 0 -245 0 0 -72 0 0 -SURF 0x30 -mat 1 -refs 4 -239 0 0 -73 0 0 -238 0 0 -437 0 0 -SURF 0x30 -mat 1 -refs 4 -34 0 0 -239 0 0 -437 0 0 -178 0 0 -SURF 0x30 -mat 1 -refs 4 -437 0 0 -238 0 0 -72 0 0 -237 0 0 -SURF 0x30 -mat 1 -refs 4 -178 0 0 -437 0 0 -237 0 0 -35 0 0 -SURF 0x30 -mat 1 -refs 4 -198 0 0 -46 0 0 -222 0 0 -438 0 0 -SURF 0x30 -mat 1 -refs 4 -44 0 0 -198 0 0 -438 0 0 -225 0 0 -SURF 0x30 -mat 1 -refs 4 -438 0 0 -222 0 0 -61 0 0 -226 0 0 -SURF 0x30 -mat 1 -refs 4 -225 0 0 -438 0 0 -226 0 0 -63 0 0 -SURF 0x30 -mat 1 -refs 4 -202 0 0 -48 0 0 -218 0 0 -439 0 0 -SURF 0x30 -mat 1 -refs 4 -46 0 0 -202 0 0 -439 0 0 -222 0 0 -SURF 0x30 -mat 1 -refs 4 -439 0 0 -218 0 0 -59 0 0 -223 0 0 -SURF 0x30 -mat 1 -refs 4 -222 0 0 -439 0 0 -223 0 0 -61 0 0 -SURF 0x30 -mat 1 -refs 4 -221 0 0 -60 0 0 -220 0 0 -440 0 0 -SURF 0x30 -mat 1 -refs 4 -47 0 0 -221 0 0 -440 0 0 -203 0 0 -SURF 0x30 -mat 1 -refs 4 -440 0 0 -220 0 0 -58 0 0 -217 0 0 -SURF 0x30 -mat 1 -refs 4 -203 0 0 -440 0 0 -217 0 0 -49 0 0 -SURF 0x30 -mat 1 -refs 4 -204 0 0 -50 0 0 -214 0 0 -441 0 0 -SURF 0x30 -mat 1 -refs 4 -48 0 0 -204 0 0 -441 0 0 -218 0 0 -SURF 0x30 -mat 1 -refs 4 -441 0 0 -214 0 0 -57 0 0 -219 0 0 -SURF 0x30 -mat 1 -refs 4 -218 0 0 -441 0 0 -219 0 0 -59 0 0 -SURF 0x30 -mat 1 -refs 4 -217 0 0 -58 0 0 -216 0 0 -442 0 0 -SURF 0x30 -mat 1 -refs 4 -49 0 0 -217 0 0 -442 0 0 -205 0 0 -SURF 0x30 -mat 1 -refs 4 -442 0 0 -216 0 0 -56 0 0 -211 0 0 -SURF 0x30 -mat 1 -refs 4 -205 0 0 -442 0 0 -211 0 0 -51 0 0 -SURF 0x30 -mat 1 -refs 4 -212 0 0 -54 0 0 -215 0 0 -443 0 0 -SURF 0x30 -mat 1 -refs 4 -53 0 0 -212 0 0 -443 0 0 -206 0 0 -SURF 0x30 -mat 1 -refs 4 -443 0 0 -215 0 0 -57 0 0 -214 0 0 -SURF 0x30 -mat 1 -refs 4 -206 0 0 -443 0 0 -214 0 0 -50 0 0 -SURF 0x30 -mat 1 -refs 4 -209 0 0 -55 0 0 -213 0 0 -444 0 0 -SURF 0x30 -mat 1 -refs 4 -52 0 0 -209 0 0 -444 0 0 -207 0 0 -SURF 0x30 -mat 1 -refs 4 -444 0 0 -213 0 0 -54 0 0 -212 0 0 -SURF 0x30 -mat 1 -refs 4 -207 0 0 -444 0 0 -212 0 0 -53 0 0 -SURF 0x30 -mat 1 -refs 4 -208 0 0 -51 0 0 -211 0 0 -445 0 0 -SURF 0x30 -mat 1 -refs 4 -52 0 0 -208 0 0 -445 0 0 -209 0 0 -SURF 0x30 -mat 1 -refs 4 -445 0 0 -211 0 0 -56 0 0 -210 0 0 -SURF 0x30 -mat 1 -refs 4 -209 0 0 -445 0 0 -210 0 0 -55 0 0 -SURF 0x30 -mat 1 -refs 4 -196 0 0 -45 0 0 -201 0 0 -446 0 0 -SURF 0x30 -mat 1 -refs 4 -18 0 0 -196 0 0 -446 0 0 -145 0 0 -SURF 0x30 -mat 1 -refs 4 -446 0 0 -201 0 0 -47 0 0 -200 0 0 -SURF 0x30 -mat 1 -refs 4 -145 0 0 -446 0 0 -200 0 0 -16 0 0 -SURF 0x30 -mat 1 -refs 4 -148 0 0 -17 0 0 -199 0 0 -447 0 0 -SURF 0x30 -mat 1 -refs 4 -19 0 0 -148 0 0 -447 0 0 -195 0 0 -SURF 0x30 -mat 1 -refs 4 -447 0 0 -199 0 0 -46 0 0 -198 0 0 -SURF 0x30 -mat 1 -refs 4 -195 0 0 -447 0 0 -198 0 0 -44 0 0 -SURF 0x30 -mat 1 -refs 4 -192 0 0 -43 0 0 -197 0 0 -448 0 0 -SURF 0x30 -mat 1 -refs 4 -20 0 0 -192 0 0 -448 0 0 -149 0 0 -SURF 0x30 -mat 1 -refs 4 -448 0 0 -197 0 0 -45 0 0 -196 0 0 -SURF 0x30 -mat 1 -refs 4 -149 0 0 -448 0 0 -196 0 0 -18 0 0 -SURF 0x30 -mat 1 -refs 4 -152 0 0 -19 0 0 -195 0 0 -449 0 0 -SURF 0x30 -mat 1 -refs 4 -21 0 0 -152 0 0 -449 0 0 -191 0 0 -SURF 0x30 -mat 1 -refs 4 -449 0 0 -195 0 0 -44 0 0 -194 0 0 -SURF 0x30 -mat 1 -refs 4 -191 0 0 -449 0 0 -194 0 0 -42 0 0 -SURF 0x30 -mat 1 -refs 4 -188 0 0 -41 0 0 -193 0 0 -450 0 0 -SURF 0x30 -mat 1 -refs 4 -22 0 0 -188 0 0 -450 0 0 -153 0 0 -SURF 0x30 -mat 1 -refs 4 -450 0 0 -193 0 0 -43 0 0 -192 0 0 -SURF 0x30 -mat 1 -refs 4 -153 0 0 -450 0 0 -192 0 0 -20 0 0 -SURF 0x30 -mat 1 -refs 4 -156 0 0 -21 0 0 -191 0 0 -451 0 0 -SURF 0x30 -mat 1 -refs 4 -23 0 0 -156 0 0 -451 0 0 -187 0 0 -SURF 0x30 -mat 1 -refs 4 -451 0 0 -191 0 0 -42 0 0 -190 0 0 -SURF 0x30 -mat 1 -refs 4 -187 0 0 -451 0 0 -190 0 0 -40 0 0 -SURF 0x30 -mat 1 -refs 4 -184 0 0 -39 0 0 -189 0 0 -452 0 0 -SURF 0x30 -mat 1 -refs 4 -24 0 0 -184 0 0 -452 0 0 -157 0 0 -SURF 0x30 -mat 1 -refs 4 -452 0 0 -189 0 0 -41 0 0 -188 0 0 -SURF 0x30 -mat 1 -refs 4 -157 0 0 -452 0 0 -188 0 0 -22 0 0 -SURF 0x30 -mat 1 -refs 4 -160 0 0 -23 0 0 -187 0 0 -453 0 0 -SURF 0x30 -mat 1 -refs 4 -25 0 0 -160 0 0 -453 0 0 -183 0 0 -SURF 0x30 -mat 1 -refs 4 -453 0 0 -187 0 0 -40 0 0 -186 0 0 -SURF 0x30 -mat 1 -refs 4 -183 0 0 -453 0 0 -186 0 0 -38 0 0 -SURF 0x30 -mat 1 -refs 4 -164 0 0 -25 0 0 -183 0 0 -454 0 0 -SURF 0x30 -mat 1 -refs 4 -26 0 0 -164 0 0 -454 0 0 -180 0 0 -SURF 0x30 -mat 1 -refs 4 -454 0 0 -183 0 0 -38 0 0 -182 0 0 -SURF 0x30 -mat 1 -refs 4 -180 0 0 -454 0 0 -182 0 0 -37 0 0 -SURF 0x30 -mat 1 -refs 4 -174 0 0 -34 0 0 -178 0 0 -455 0 0 -SURF 0x30 -mat 1 -refs 4 -29 0 0 -174 0 0 -455 0 0 -170 0 0 -SURF 0x30 -mat 1 -refs 4 -455 0 0 -178 0 0 -35 0 0 -177 0 0 -SURF 0x30 -mat 1 -refs 4 -170 0 0 -455 0 0 -177 0 0 -28 0 0 -SURF 0x30 -mat 1 -refs 4 -121 0 0 -1 0 0 -167 0 0 -456 0 0 -SURF 0x30 -mat 1 -refs 4 -2 0 0 -121 0 0 -456 0 0 -171 0 0 -SURF 0x30 -mat 1 -refs 4 -456 0 0 -167 0 0 -30 0 0 -173 0 0 -SURF 0x30 -mat 1 -refs 4 -171 0 0 -456 0 0 -173 0 0 -29 0 0 -SURF 0x30 -mat 1 -refs 4 -166 0 0 -0 0 0 -123 0 0 -457 0 0 -SURF 0x30 -mat 1 -refs 4 -31 0 0 -166 0 0 -457 0 0 -172 0 0 -SURF 0x30 -mat 1 -refs 4 -457 0 0 -123 0 0 -3 0 0 -169 0 0 -SURF 0x30 -mat 1 -refs 4 -172 0 0 -457 0 0 -169 0 0 -28 0 0 -SURF 0x30 -mat 1 -refs 4 -171 0 0 -29 0 0 -170 0 0 -458 0 0 -SURF 0x30 -mat 1 -refs 4 -2 0 0 -171 0 0 -458 0 0 -124 0 0 -SURF 0x30 -mat 1 -refs 4 -458 0 0 -170 0 0 -28 0 0 -169 0 0 -SURF 0x30 -mat 1 -refs 4 -124 0 0 -458 0 0 -169 0 0 -3 0 0 -SURF 0x30 -mat 1 -refs 4 -125 0 0 -5 0 0 -163 0 0 -459 0 0 -SURF 0x30 -mat 1 -refs 4 -1 0 0 -125 0 0 -459 0 0 -167 0 0 -SURF 0x30 -mat 1 -refs 4 -459 0 0 -163 0 0 -26 0 0 -168 0 0 -SURF 0x30 -mat 1 -refs 4 -167 0 0 -459 0 0 -168 0 0 -30 0 0 -SURF 0x30 -mat 1 -refs 4 -166 0 0 -31 0 0 -165 0 0 -460 0 0 -SURF 0x30 -mat 1 -refs 4 -0 0 0 -166 0 0 -460 0 0 -127 0 0 -SURF 0x30 -mat 1 -refs 4 -460 0 0 -165 0 0 -27 0 0 -162 0 0 -SURF 0x30 -mat 1 -refs 4 -127 0 0 -460 0 0 -162 0 0 -4 0 0 -SURF 0x30 -mat 1 -refs 4 -128 0 0 -6 0 0 -159 0 0 -461 0 0 -SURF 0x30 -mat 1 -refs 4 -5 0 0 -128 0 0 -461 0 0 -163 0 0 -SURF 0x30 -mat 1 -refs 4 -461 0 0 -159 0 0 -25 0 0 -164 0 0 -SURF 0x30 -mat 1 -refs 4 -163 0 0 -461 0 0 -164 0 0 -26 0 0 -SURF 0x30 -mat 1 -refs 4 -162 0 0 -27 0 0 -161 0 0 -462 0 0 -SURF 0x30 -mat 1 -refs 4 -4 0 0 -162 0 0 -462 0 0 -130 0 0 -SURF 0x30 -mat 1 -refs 4 -462 0 0 -161 0 0 -24 0 0 -158 0 0 -SURF 0x30 -mat 1 -refs 4 -130 0 0 -462 0 0 -158 0 0 -7 0 0 -SURF 0x30 -mat 1 -refs 4 -131 0 0 -8 0 0 -155 0 0 -463 0 0 -SURF 0x30 -mat 1 -refs 4 -6 0 0 -131 0 0 -463 0 0 -159 0 0 -SURF 0x30 -mat 1 -refs 4 -463 0 0 -155 0 0 -23 0 0 -160 0 0 -SURF 0x30 -mat 1 -refs 4 -159 0 0 -463 0 0 -160 0 0 -25 0 0 -SURF 0x30 -mat 1 -refs 4 -158 0 0 -24 0 0 -157 0 0 -464 0 0 -SURF 0x30 -mat 1 -refs 4 -7 0 0 -158 0 0 -464 0 0 -133 0 0 -SURF 0x30 -mat 1 -refs 4 -464 0 0 -157 0 0 -22 0 0 -154 0 0 -SURF 0x30 -mat 1 -refs 4 -133 0 0 -464 0 0 -154 0 0 -9 0 0 -SURF 0x30 -mat 1 -refs 4 -151 0 0 -21 0 0 -156 0 0 -465 0 0 -SURF 0x30 -mat 1 -refs 4 -10 0 0 -151 0 0 -465 0 0 -134 0 0 -SURF 0x30 -mat 1 -refs 4 -465 0 0 -156 0 0 -23 0 0 -155 0 0 -SURF 0x30 -mat 1 -refs 4 -134 0 0 -465 0 0 -155 0 0 -8 0 0 -SURF 0x30 -mat 1 -refs 4 -136 0 0 -9 0 0 -154 0 0 -466 0 0 -SURF 0x30 -mat 1 -refs 4 -11 0 0 -136 0 0 -466 0 0 -150 0 0 -SURF 0x30 -mat 1 -refs 4 -466 0 0 -154 0 0 -22 0 0 -153 0 0 -SURF 0x30 -mat 1 -refs 4 -150 0 0 -466 0 0 -153 0 0 -20 0 0 -SURF 0x30 -mat 1 -refs 4 -147 0 0 -19 0 0 -152 0 0 -467 0 0 -SURF 0x30 -mat 1 -refs 4 -12 0 0 -147 0 0 -467 0 0 -137 0 0 -SURF 0x30 -mat 1 -refs 4 -467 0 0 -152 0 0 -21 0 0 -151 0 0 -SURF 0x30 -mat 1 -refs 4 -137 0 0 -467 0 0 -151 0 0 -10 0 0 -SURF 0x30 -mat 1 -refs 4 -139 0 0 -11 0 0 -150 0 0 -468 0 0 -SURF 0x30 -mat 1 -refs 4 -13 0 0 -139 0 0 -468 0 0 -146 0 0 -SURF 0x30 -mat 1 -refs 4 -468 0 0 -150 0 0 -20 0 0 -149 0 0 -SURF 0x30 -mat 1 -refs 4 -146 0 0 -468 0 0 -149 0 0 -18 0 0 -SURF 0x30 -mat 1 -refs 4 -144 0 0 -17 0 0 -148 0 0 -469 0 0 -SURF 0x30 -mat 1 -refs 4 -14 0 0 -144 0 0 -469 0 0 -140 0 0 -SURF 0x30 -mat 1 -refs 4 -469 0 0 -148 0 0 -19 0 0 -147 0 0 -SURF 0x30 -mat 1 -refs 4 -140 0 0 -469 0 0 -147 0 0 -12 0 0 -SURF 0x30 -mat 1 -refs 4 -142 0 0 -13 0 0 -146 0 0 -470 0 0 -SURF 0x30 -mat 1 -refs 4 -15 0 0 -142 0 0 -470 0 0 -143 0 0 -SURF 0x30 -mat 1 -refs 4 -470 0 0 -146 0 0 -18 0 0 -145 0 0 -SURF 0x30 -mat 1 -refs 4 -143 0 0 -470 0 0 -145 0 0 -16 0 0 -SURF 0x30 -mat 1 -refs 4 -142 0 0 -15 0 0 -141 0 0 -471 0 0 -SURF 0x30 -mat 1 -refs 4 -13 0 0 -142 0 0 -471 0 0 -138 0 0 -SURF 0x30 -mat 1 -refs 4 -471 0 0 -141 0 0 -14 0 0 -140 0 0 -SURF 0x30 -mat 1 -refs 4 -138 0 0 -471 0 0 -140 0 0 -12 0 0 -SURF 0x30 -mat 1 -refs 4 -135 0 0 -11 0 0 -139 0 0 -472 0 0 -SURF 0x30 -mat 1 -refs 4 -10 0 0 -135 0 0 -472 0 0 -137 0 0 -SURF 0x30 -mat 1 -refs 4 -472 0 0 -139 0 0 -13 0 0 -138 0 0 -SURF 0x30 -mat 1 -refs 4 -137 0 0 -472 0 0 -138 0 0 -12 0 0 -SURF 0x30 -mat 1 -refs 4 -136 0 0 -11 0 0 -135 0 0 -473 0 0 -SURF 0x30 -mat 1 -refs 4 -9 0 0 -136 0 0 -473 0 0 -132 0 0 -SURF 0x30 -mat 1 -refs 4 -473 0 0 -135 0 0 -10 0 0 -134 0 0 -SURF 0x30 -mat 1 -refs 4 -132 0 0 -473 0 0 -134 0 0 -8 0 0 -SURF 0x30 -mat 1 -refs 4 -133 0 0 -9 0 0 -132 0 0 -474 0 0 -SURF 0x30 -mat 1 -refs 4 -7 0 0 -133 0 0 -474 0 0 -129 0 0 -SURF 0x30 -mat 1 -refs 4 -474 0 0 -132 0 0 -8 0 0 -131 0 0 -SURF 0x30 -mat 1 -refs 4 -129 0 0 -474 0 0 -131 0 0 -6 0 0 -SURF 0x30 -mat 1 -refs 4 -126 0 0 -4 0 0 -130 0 0 -475 0 0 -SURF 0x30 -mat 1 -refs 4 -5 0 0 -126 0 0 -475 0 0 -128 0 0 -SURF 0x30 -mat 1 -refs 4 -475 0 0 -130 0 0 -7 0 0 -129 0 0 -SURF 0x30 -mat 1 -refs 4 -128 0 0 -475 0 0 -129 0 0 -6 0 0 -SURF 0x30 -mat 1 -refs 4 -127 0 0 -4 0 0 -126 0 0 -476 0 0 -SURF 0x30 -mat 1 -refs 4 -0 0 0 -127 0 0 -476 0 0 -122 0 0 -SURF 0x30 -mat 1 -refs 4 -476 0 0 -126 0 0 -5 0 0 -125 0 0 -SURF 0x30 -mat 1 -refs 4 -122 0 0 -476 0 0 -125 0 0 -1 0 0 -SURF 0x30 -mat 1 -refs 4 -122 0 0 -1 0 0 -121 0 0 -477 0 0 -SURF 0x30 -mat 1 -refs 4 -0 0 0 -122 0 0 -477 0 0 -123 0 0 -SURF 0x30 -mat 1 -refs 4 -477 0 0 -121 0 0 -2 0 0 -124 0 0 -SURF 0x30 -mat 1 -refs 4 -123 0 0 -477 0 0 -124 0 0 -3 0 0 -kids 0 -OBJECT poly -name "LeftTail.001" -data 8 -Tail.001 -crease 30.000000 -numvert 478 -0.632646 -0.00581 -0.004194 -0.632334 -0.0118 -0.004195 -0.626565 -0.010097 -0.005593 -0.627624 -0.006845 -0.005593 -0.639753 -0.005601 -0.004194 -0.639389 -0.012925 -0.004195 -0.652747 -0.01304 -0.004195 -0.652234 -0.005189 -0.004194 -0.665103 -0.013003 -0.004195 -0.664903 -0.004956 -0.004194 -0.677032 -0.012802 -0.004195 -0.67703 -0.005117 -0.004194 -0.688801 -0.012256 -0.004195 -0.688665 -0.005485 -0.004194 -0.696797 -0.012047 -0.005593 -0.696359 -0.006146 -0.005592 -0.696981 -0.006001 -0.131367 -0.69741 -0.011726 -0.131392 -0.687762 -0.005215 -0.131365 -0.687899 -0.012074 -0.131395 -0.676652 -0.004836 -0.131365 -0.676653 -0.012621 -0.131399 -0.665131 -0.004672 -0.131366 -0.665333 -0.012824 -0.131401 -0.652936 -0.004914 -0.133017 -0.653612 -0.012853 -0.131403 -0.640856 -0.012697 -0.133052 -0.641084 -0.005312 -0.131372 -0.629682 -0.0067 -0.13138 -0.628643 -0.009827 -0.131394 -0.634043 -0.011568 -0.1314 -0.634381 -0.005578 -0.131375 -0.642733 -0.005849 -0.177269 -0.642431 -0.01125 -0.177301 -0.637189 -0.009712 -0.176234 -0.638116 -0.006816 -0.176214 -0.648888 -0.005608 -0.17723 -0.648185 -0.012221 -0.177262 -0.659392 -0.012357 -0.177212 -0.658946 -0.005262 -0.177178 -0.669876 -0.012334 -0.177114 -0.669687 -0.005055 -0.177086 -0.679983 -0.012157 -0.177024 -0.679977 -0.005193 -0.176995 -0.690231 -0.011658 -0.17768 -0.689853 -0.005527 -0.176909 -0.697799 -0.011385 -0.176894 -0.697413 -0.006206 -0.177501 -0.707798 -0.011278 -0.178049 -0.707596 -0.00714 -0.178033 -0.718302 -0.010928 -0.177958 -0.717877 -0.007797 -0.177948 -0.728013 -0.009146 -0.178028 -0.727943 -0.00996 -0.178036 -0.728188 -0.009829 -0.193657 -0.728247 -0.009189 -0.19363 -0.720661 -0.007974 -0.196207 -0.720997 -0.0106 -0.196106 -0.713146 -0.007423 -0.199448 -0.713308 -0.010897 -0.199406 -0.706406 -0.006672 -0.201175 -0.706709 -0.010978 -0.20109 -0.700185 -0.00626 -0.204159 -0.700097 -0.011076 -0.204149 -0.692506 -0.005951 -0.206168 -0.692516 -0.011451 -0.20619 -0.684813 -0.005827 -0.208842 -0.68495 -0.011596 -0.208817 -0.676785 -0.005971 -0.211632 -0.677116 -0.011611 -0.211543 -0.668728 -0.011503 -0.214437 -0.668945 -0.006243 -0.214329 -0.660393 -0.007185 -0.216074 -0.659699 -0.0095 -0.216324 -0.664082 -0.010732 -0.21598 -0.664303 -0.006427 -0.215882 -0.696456 -0.00777 -0.239133 -0.696328 -0.010388 -0.239247 -0.693518 -0.009633 -0.240126 -0.693881 -0.008212 -0.239864 -0.698899 -0.007668 -0.237456 -0.698793 -0.010849 -0.237553 -0.703178 -0.010914 -0.234457 -0.703004 -0.007508 -0.234564 -0.707259 -0.010908 -0.231564 -0.707188 -0.007427 -0.231599 -0.711614 -0.010813 -0.229173 -0.711197 -0.007508 -0.228759 -0.714927 -0.010607 -0.226028 -0.715227 -0.007705 -0.226504 -0.71887 -0.010538 -0.223877 -0.718713 -0.007983 -0.223977 -0.721836 -0.010507 -0.221114 -0.721749 -0.008389 -0.221166 -0.725685 -0.01033 -0.218304 -0.725513 -0.008711 -0.218418 -0.729518 -0.009374 -0.215054 -0.729496 -0.009816 -0.215077 -0.733865 -0.00984 -0.23431 -0.733869 -0.009647 -0.234299 -0.732707 -0.009526 -0.236335 -0.732758 -0.0102 -0.236269 -0.731513 -0.009387 -0.237913 -0.731542 -0.010271 -0.237882 -0.730331 -0.009177 -0.238933 -0.730382 -0.010289 -0.238873 -0.729541 -0.009107 -0.240561 -0.729557 -0.010308 -0.240547 -0.728485 -0.009041 -0.242018 -0.728366 -0.0104 -0.24211 -0.72727 -0.009005 -0.243614 -0.727291 -0.010428 -0.243593 -0.726002 -0.009035 -0.245282 -0.726055 -0.010431 -0.245217 -0.724723 -0.010405 -0.246972 -0.724751 -0.009099 -0.246923 -0.723396 -0.009343 -0.248627 -0.722706 -0.009904 -0.248638 -0.723946 -0.010222 -0.247951 -0.72337 -0.009107 -0.247791 -0.734549 -0.010168 -0.241939 -0.629293 -0.01094 -0.004195 -0.632436 -0.008812 0 -0.629995 -0.00632 -0.004195 -0.627015 -0.00847 -0.004195 -0.635743 -0.01239 -0.004195 -0.639528 -0.009271 0 -0.636083 -0.005694 -0.004194 -0.645983 -0.013002 -0.004195 -0.652468 -0.009123 0 -0.645904 -0.005395 -0.004194 -0.658952 -0.013027 -0.004195 -0.665001 -0.008988 0 -0.658576 -0.005063 -0.004194 -0.671074 -0.012912 -0.004195 -0.677047 -0.008967 0 -0.670982 -0.005027 -0.004194 -0.682975 -0.012528 -0.004195 -0.688768 -0.008878 0 -0.682915 -0.005293 -0.004194 -0.693027 -0.012177 -0.004195 -0.696655 -0.009102 -0.004195 -0.692731 -0.005792 -0.004194 -0.696708 -0.00604 -0.067107 -0.697149 -0.011927 -0.067119 -0.692539 -0.005519 -0.131366 -0.688176 -0.005232 -0.067105 -0.688317 -0.012284 -0.067121 -0.692838 -0.011986 -0.131393 -0.682237 -0.005018 -0.131365 -0.676788 -0.004842 -0.067105 -0.676789 -0.012847 -0.067123 -0.682298 -0.012347 -0.131397 -0.670906 -0.004744 -0.131366 -0.664941 -0.004673 -0.067106 -0.66515 -0.013056 -0.067124 -0.670999 -0.012731 -0.1314 -0.659118 -0.004776 -0.131367 -0.65256 -0.004908 -0.067107 -0.653097 -0.013085 -0.067125 -0.659499 -0.012843 -0.131402 -0.646834 -0.005112 -0.131371 -0.640406 -0.005326 -0.067109 -0.640024 -0.012956 -0.067126 -0.647174 -0.012808 -0.131404 -0.637621 -0.005434 -0.131373 -0.633463 -0.005573 -0.06711 -0.63314 -0.011815 -0.067124 -0.637267 -0.012158 -0.131402 -0.628491 -0.006759 -0.067113 -0.628996 -0.008254 -0.131387 -0.627422 -0.009974 -0.06712 -0.632068 -0.006105 -0.133025 -0.63134 -0.010709 -0.133045 -0.632585 -0.009799 -0.154732 -0.640288 -0.01048 -0.178326 -0.640923 -0.006317 -0.178294 -0.633571 -0.006727 -0.154718 -0.637701 -0.008249 -0.177285 -0.645021 -0.011788 -0.176225 -0.64432 -0.012462 -0.156899 -0.645711 -0.005718 -0.17725 -0.653716 -0.012305 -0.177237 -0.656378 -0.01261 -0.155819 -0.655777 -0.005081 -0.156865 -0.653753 -0.00542 -0.176156 -0.664657 -0.012349 -0.177163 -0.667499 -0.012583 -0.155818 -0.667307 -0.004849 -0.155783 -0.664323 -0.00515 -0.177132 -0.674935 -0.012253 -0.177069 -0.678238 -0.012391 -0.155815 -0.678237 -0.005004 -0.155782 -0.674845 -0.005115 -0.17704 -0.685019 -0.011916 -0.17698 -0.688886 -0.011871 -0.155811 -0.688756 -0.005364 -0.155782 -0.684965 -0.005353 -0.176952 -0.694047 -0.011585 -0.176812 -0.69735 -0.011542 -0.155809 -0.696943 -0.006109 -0.155784 -0.693557 -0.005796 -0.176868 -0.702782 -0.011312 -0.178085 -0.702493 -0.006706 -0.178067 -0.71305 -0.011119 -0.178004 -0.712731 -0.007459 -0.17799 -0.72334 -0.010437 -0.177914 -0.728086 -0.009556 -0.177865 -0.723163 -0.008485 -0.177904 -0.728166 -0.009168 -0.185399 -0.724685 -0.008597 -0.195373 -0.719116 -0.007808 -0.186775 -0.728096 -0.009894 -0.185417 -0.728461 -0.009517 -0.193557 -0.719517 -0.01083 -0.186728 -0.72482 -0.01021 -0.195337 -0.716794 -0.007679 -0.197548 -0.710082 -0.007181 -0.188146 -0.710272 -0.01117 -0.188134 -0.71705 -0.010765 -0.197474 -0.709614 -0.007031 -0.200074 -0.701812 -0.00637 -0.189971 -0.702107 -0.01125 -0.189253 -0.709847 -0.010947 -0.200011 -0.703012 -0.006432 -0.201721 -0.694916 -0.011367 -0.191247 -0.703298 -0.011026 -0.202283 -0.696195 -0.006087 -0.204873 -0.695937 -0.011281 -0.204205 -0.688669 -0.005882 -0.207501 -0.688737 -0.01153 -0.207502 -0.680804 -0.005892 -0.210235 -0.68105 -0.011607 -0.210174 -0.672808 -0.006107 -0.213001 -0.672868 -0.01157 -0.213009 -0.666549 -0.006327 -0.215132 -0.66633 -0.011136 -0.215236 -0.648759 -0.006986 -0.196443 -0.660482 -0.008335 -0.217132 -0.647945 -0.009604 -0.196577 -0.66335 -0.006815 -0.217141 -0.662883 -0.010119 -0.217327 -0.67639 -0.009558 -0.228825 -0.696036 -0.01002 -0.240272 -0.695565 -0.007984 -0.239758 -0.676919 -0.007679 -0.228564 -0.694393 -0.008929 -0.240549 -0.697522 -0.01063 -0.238429 -0.698301 -0.007751 -0.238662 -0.700958 -0.010889 -0.236025 -0.700922 -0.007588 -0.236032 -0.705227 -0.010913 -0.233004 -0.705099 -0.007464 -0.23308 -0.709234 -0.010868 -0.230166 -0.709198 -0.007464 -0.230176 -0.712738 -0.010723 -0.226831 -0.707636 -0.010832 -0.215577 -0.707566 -0.006966 -0.215593 -0.712682 -0.00755 -0.226874 -0.716744 -0.010573 -0.224743 -0.712573 -0.010757 -0.212405 -0.712342 -0.007298 -0.2125 -0.716637 -0.007805 -0.224805 -0.720194 -0.010528 -0.222279 -0.7176 -0.010694 -0.210605 -0.717477 -0.00791 -0.210653 -0.720071 -0.00817 -0.222355 -0.723483 -0.010438 -0.219224 -0.723351 -0.008517 -0.219309 -0.727833 -0.01007 -0.217391 -0.728648 -0.009834 -0.204052 -0.729855 -0.009606 -0.215461 -0.728683 -0.009254 -0.204027 -0.727758 -0.00906 -0.217436 -0.731668 -0.009506 -0.224921 -0.733431 -0.009606 -0.235721 -0.731654 -0.00982 -0.224937 -0.734138 -0.009757 -0.234848 -0.733455 -0.010027 -0.235693 -0.73224 -0.00948 -0.237304 -0.73228 -0.01024 -0.237255 -0.730718 -0.009259 -0.238231 -0.724916 -0.008621 -0.232062 -0.725017 -0.010403 -0.231983 -0.73076 -0.010285 -0.238184 -0.730019 -0.00915 -0.239805 -0.722742 -0.00843 -0.234037 -0.722394 -0.010451 -0.233629 -0.730052 -0.010296 -0.239767 -0.72893 -0.00907 -0.241125 -0.720323 -0.010599 -0.236186 -0.72918 -0.010349 -0.241415 -0.72811 -0.009053 -0.242883 -0.727727 -0.010418 -0.242686 -0.726908 -0.009051 -0.244478 -0.726946 -0.010424 -0.244433 -0.725679 -0.009098 -0.246105 -0.725692 -0.010414 -0.246098 -0.724703 -0.009148 -0.247385 -0.709826 -0.008424 -0.243768 -0.724673 -0.010313 -0.247433 -0.709369 -0.008807 -0.244981 -0.723724 -0.009631 -0.248635 -0.708459 -0.009764 -0.244949 -0.724032 -0.009261 -0.248225 -0.724013 -0.010073 -0.248286 -0.729474 -0.00965 -0.245392 -0.734703 -0.009923 -0.238182 -0.7347 -0.010013 -0.238186 -0.7341 -0.009856 -0.239013 -0.734126 -0.0102 -0.238979 -0.733501 -0.009789 -0.239873 -0.733516 -0.010246 -0.239856 -0.732398 -0.009633 -0.241394 -0.732406 -0.010271 -0.241387 -0.731781 -0.00959 -0.24221 -0.731782 -0.010315 -0.242212 -0.731148 -0.009573 -0.243083 -0.73116 -0.010333 -0.24307 -0.730489 -0.009591 -0.243992 -0.730515 -0.010333 -0.24396 -0.729854 -0.009624 -0.244869 -0.729837 -0.010315 -0.244896 -0.729214 -0.009762 -0.245752 -0.729455 -0.010211 -0.245422 -0.729165 -0.010039 -0.245821 -0.6975 -0.008871 -0.131379 -0.697625 -0.008815 -0.176019 -0.707533 -0.009211 -0.177367 -0.718008 -0.009365 -0.177366 -0.709334 -0.01012 -0.244314 -0.71154 -0.010523 -0.243268 -0.71089 -0.008378 -0.242988 -0.714079 -0.010652 -0.241209 -0.714005 -0.008313 -0.241239 -0.716751 -0.010663 -0.238853 -0.716687 -0.008236 -0.238905 -0.71971 -0.010616 -0.236969 -0.71929 -0.008258 -0.236621 -0.722143 -0.008393 -0.234802 -0.725527 -0.010395 -0.231334 -0.725436 -0.008711 -0.231401 -0.727399 -0.010346 -0.22896 -0.72733 -0.008962 -0.229021 -0.72993 -0.010068 -0.226196 -0.729848 -0.009192 -0.226247 -0.72513 -0.008677 -0.205309 -0.725281 -0.0102 -0.205269 -0.719444 -0.008078 -0.209296 -0.719609 -0.010611 -0.209215 -0.705656 -0.006881 -0.21691 -0.705701 -0.01094 -0.216911 -0.69958 -0.00667 -0.219119 -0.699618 -0.011184 -0.219113 -0.693631 -0.006652 -0.222002 -0.693792 -0.011254 -0.221932 -0.687545 -0.006811 -0.22492 -0.687659 -0.011229 -0.224923 -0.68241 -0.007 -0.227178 -0.682233 -0.01094 -0.227279 -0.678407 -0.007289 -0.228022 -0.678096 -0.010159 -0.228214 -0.650235 -0.010369 -0.196566 -0.650762 -0.006484 -0.196423 -0.655766 -0.011486 -0.196909 -0.656036 -0.006 -0.196847 -0.663708 -0.01194 -0.19611 -0.663597 -0.005734 -0.196039 -0.673225 -0.011977 -0.194591 -0.672958 -0.005492 -0.194625 -0.68223 -0.01188 -0.193191 -0.68216 -0.005488 -0.193187 -0.691295 -0.011548 -0.192458 -0.690981 -0.005721 -0.191811 -0.69856 -0.006147 -0.19105 -0.650703 -0.005254 -0.156866 -0.641643 -0.005558 -0.15579 -0.641385 -0.011999 -0.156898 -0.635821 -0.00616 -0.154715 -0.635153 -0.010661 -0.154736 -0.638285 -0.011343 -0.155817 -0.638775 -0.00585 -0.155792 -0.646023 -0.005398 -0.155789 -0.694686 -0.005924 -0.191145 -0.6866 -0.005598 -0.192497 -0.68666 -0.011726 -0.192513 -0.677568 -0.005482 -0.193905 -0.677739 -0.011934 -0.193888 -0.668252 -0.005609 -0.195342 -0.668451 -0.011967 -0.195361 -0.659742 -0.005863 -0.196456 -0.659663 -0.011731 -0.196523 -0.653634 -0.006236 -0.197147 -0.653242 -0.010941 -0.197253 -0.68057 -0.010565 -0.228053 -0.680807 -0.00715 -0.227909 -0.684899 -0.011096 -0.226125 -0.68493 -0.006903 -0.226073 -0.69072 -0.011247 -0.223435 -0.690575 -0.006728 -0.223471 -0.696712 -0.011223 -0.220518 -0.696611 -0.006655 -0.220558 -0.702493 -0.011071 -0.217729 -0.702454 -0.006755 -0.217729 -0.722308 -0.010418 -0.207235 -0.722141 -0.008355 -0.207298 -0.728619 -0.009075 -0.22789 -0.728697 -0.010215 -0.227833 -0.726205 -0.00882 -0.230026 -0.726286 -0.010378 -0.229962 -0.720548 -0.008307 -0.235519 -0.717991 -0.008244 -0.237761 -0.718029 -0.010646 -0.237732 -0.715343 -0.008272 -0.240077 -0.715415 -0.01066 -0.240033 -0.712792 -0.008363 -0.242233 -0.71279 -0.010593 -0.242256 -0.710795 -0.010334 -0.243903 -0.73198 -0.009496 -0.240163 -0.732002 -0.010268 -0.240137 -0.723211 -0.009464 -0.177366 -0.712768 -0.009292 -0.177367 -0.702412 -0.00901 -0.177367 -0.697413 -0.008833 -0.155796 -0.697206 -0.008991 -0.067113 -0.709891 -0.008621 -0.244525 -0.709216 -0.009272 -0.245117 -0.721138 -0.01053 -0.234724 -0.723559 -0.010428 -0.232612 -0.723491 -0.008489 -0.232662 -0.731973 -0.00967 -0.22527 -0.729089 -0.009558 -0.204455 -0.714762 -0.007587 -0.211337 -0.71494 -0.010734 -0.211266 -0.7098 -0.00711 -0.213722 -0.709955 -0.010795 -0.213664 -0.677336 -0.008622 -0.229342 -0.648686 -0.008282 -0.197517 -0.698476 -0.011307 -0.189868 -0.706157 -0.011214 -0.188696 -0.705885 -0.006773 -0.188718 -0.714884 -0.011014 -0.187435 -0.714583 -0.007485 -0.187465 -0.723951 -0.010368 -0.18605 -0.728415 -0.009538 -0.185364 -0.723784 -0.008486 -0.186065 -0.693008 -0.005652 -0.155783 -0.693292 -0.011788 -0.15581 -0.683537 -0.005177 -0.155782 -0.683594 -0.01213 -0.155813 -0.672785 -0.004917 -0.155783 -0.672875 -0.012495 -0.155816 -0.661601 -0.004948 -0.155785 -0.661963 -0.012601 -0.155819 -0.65027 -0.012568 -0.15582 -0.633023 -0.008247 -0.155804 -0.630158 -0.010929 -0.067122 -0.630889 -0.006117 -0.067112 -0.627786 -0.008356 -0.067117 -0.636467 -0.012413 -0.067125 -0.636821 -0.005438 -0.06711 -0.646478 -0.013039 -0.067126 -0.646396 -0.005117 -0.067108 -0.65915 -0.013075 -0.067125 -0.658758 -0.004781 -0.067107 -0.670976 -0.01296 -0.067124 -0.670879 -0.004748 -0.067106 -0.682593 -0.012565 -0.067122 -0.682531 -0.00503 -0.067105 -0.692922 -0.012194 -0.06712 -0.692614 -0.005544 -0.067106 -0.692886 -0.008992 0 -0.68297 -0.008918 0 -0.671035 -0.008977 0 -0.658752 -0.009053 0 -0.64591 -0.009207 0 -0.635864 -0.00905 0 -0.629585 -0.008637 0 -numsurf 560 -SURF 0x30 -mat 1 -refs 3 -324 0 0 -118 0 0 -305 0 0 -SURF 0x30 -mat 1 -refs 3 -305 0 0 -325 0 0 -324 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -324 0 0 -325 0 0 -SURF 0x30 -mat 1 -refs 3 -325 0 0 -305 0 0 -117 0 0 -SURF 0x30 -mat 1 -refs 3 -323 0 0 -116 0 0 -304 0 0 -SURF 0x30 -mat 1 -refs 3 -304 0 0 -306 0 0 -323 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -323 0 0 -306 0 0 -SURF 0x30 -mat 1 -refs 3 -306 0 0 -304 0 0 -119 0 0 -SURF 0x30 -mat 1 -refs 3 -325 0 0 -117 0 0 -302 0 0 -SURF 0x30 -mat 1 -refs 3 -302 0 0 -323 0 0 -325 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -325 0 0 -323 0 0 -SURF 0x30 -mat 1 -refs 3 -323 0 0 -302 0 0 -116 0 0 -SURF 0x30 -mat 1 -refs 3 -322 0 0 -114 0 0 -300 0 0 -SURF 0x30 -mat 1 -refs 3 -300 0 0 -324 0 0 -322 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -322 0 0 -324 0 0 -SURF 0x30 -mat 1 -refs 3 -324 0 0 -300 0 0 -118 0 0 -SURF 0x30 -mat 1 -refs 3 -306 0 0 -119 0 0 -298 0 0 -SURF 0x30 -mat 1 -refs 3 -298 0 0 -321 0 0 -306 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -306 0 0 -321 0 0 -SURF 0x30 -mat 1 -refs 3 -321 0 0 -298 0 0 -115 0 0 -SURF 0x30 -mat 1 -refs 3 -320 0 0 -113 0 0 -297 0 0 -SURF 0x30 -mat 1 -refs 3 -297 0 0 -322 0 0 -320 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -320 0 0 -322 0 0 -SURF 0x30 -mat 1 -refs 3 -322 0 0 -297 0 0 -114 0 0 -SURF 0x30 -mat 1 -refs 3 -321 0 0 -115 0 0 -296 0 0 -SURF 0x30 -mat 1 -refs 3 -296 0 0 -319 0 0 -321 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -321 0 0 -319 0 0 -SURF 0x30 -mat 1 -refs 3 -319 0 0 -296 0 0 -112 0 0 -SURF 0x30 -mat 1 -refs 3 -318 0 0 -111 0 0 -295 0 0 -SURF 0x30 -mat 1 -refs 3 -295 0 0 -320 0 0 -318 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -318 0 0 -320 0 0 -SURF 0x30 -mat 1 -refs 3 -320 0 0 -295 0 0 -113 0 0 -SURF 0x30 -mat 1 -refs 3 -319 0 0 -112 0 0 -294 0 0 -SURF 0x30 -mat 1 -refs 3 -294 0 0 -317 0 0 -319 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -319 0 0 -317 0 0 -SURF 0x30 -mat 1 -refs 3 -317 0 0 -294 0 0 -110 0 0 -SURF 0x30 -mat 1 -refs 3 -316 0 0 -109 0 0 -293 0 0 -SURF 0x30 -mat 1 -refs 3 -293 0 0 -318 0 0 -316 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -316 0 0 -318 0 0 -SURF 0x30 -mat 1 -refs 3 -318 0 0 -293 0 0 -111 0 0 -SURF 0x30 -mat 1 -refs 3 -317 0 0 -110 0 0 -292 0 0 -SURF 0x30 -mat 1 -refs 3 -292 0 0 -315 0 0 -317 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -317 0 0 -315 0 0 -SURF 0x30 -mat 1 -refs 3 -315 0 0 -292 0 0 -108 0 0 -SURF 0x30 -mat 1 -refs 3 -314 0 0 -107 0 0 -291 0 0 -SURF 0x30 -mat 1 -refs 3 -291 0 0 -316 0 0 -314 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -314 0 0 -316 0 0 -SURF 0x30 -mat 1 -refs 3 -316 0 0 -291 0 0 -109 0 0 -SURF 0x30 -mat 1 -refs 3 -315 0 0 -108 0 0 -289 0 0 -SURF 0x30 -mat 1 -refs 3 -289 0 0 -313 0 0 -315 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -315 0 0 -313 0 0 -SURF 0x30 -mat 1 -refs 3 -313 0 0 -289 0 0 -106 0 0 -SURF 0x30 -mat 1 -refs 3 -310 0 0 -101 0 0 -280 0 0 -SURF 0x30 -mat 1 -refs 3 -280 0 0 -312 0 0 -310 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -310 0 0 -312 0 0 -SURF 0x30 -mat 1 -refs 3 -312 0 0 -280 0 0 -103 0 0 -SURF 0x30 -mat 1 -refs 3 -311 0 0 -102 0 0 -279 0 0 -SURF 0x30 -mat 1 -refs 3 -279 0 0 -309 0 0 -311 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -311 0 0 -309 0 0 -SURF 0x30 -mat 1 -refs 3 -309 0 0 -279 0 0 -100 0 0 -SURF 0x30 -mat 1 -refs 3 -308 0 0 -98 0 0 -278 0 0 -SURF 0x30 -mat 1 -refs 3 -278 0 0 -310 0 0 -308 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -308 0 0 -310 0 0 -SURF 0x30 -mat 1 -refs 3 -310 0 0 -278 0 0 -101 0 0 -SURF 0x30 -mat 1 -refs 3 -307 0 0 -99 0 0 -277 0 0 -SURF 0x30 -mat 1 -refs 3 -277 0 0 -308 0 0 -307 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -307 0 0 -308 0 0 -SURF 0x30 -mat 1 -refs 3 -308 0 0 -277 0 0 -98 0 0 -SURF 0x30 -mat 1 -refs 3 -309 0 0 -100 0 0 -275 0 0 -SURF 0x30 -mat 1 -refs 3 -275 0 0 -307 0 0 -309 0 0 -SURF 0x30 -mat 1 -refs 3 -120 0 0 -309 0 0 -307 0 0 -SURF 0x30 -mat 1 -refs 3 -307 0 0 -275 0 0 -99 0 0 -SURF 0x30 -mat 1 -refs 3 -330 0 0 -77 0 0 -243 0 0 -SURF 0x30 -mat 1 -refs 3 -243 0 0 -303 0 0 -330 0 0 -SURF 0x30 -mat 1 -refs 3 -117 0 0 -330 0 0 -303 0 0 -SURF 0x30 -mat 1 -refs 3 -303 0 0 -243 0 0 -78 0 0 -SURF 0x30 -mat 1 -refs 3 -299 0 0 -76 0 0 -248 0 0 -SURF 0x30 -mat 1 -refs 3 -248 0 0 -332 0 0 -299 0 0 -SURF 0x30 -mat 1 -refs 3 -119 0 0 -299 0 0 -332 0 0 -SURF 0x30 -mat 1 -refs 3 -332 0 0 -248 0 0 -80 0 0 -SURF 0x30 -mat 1 -refs 3 -290 0 0 -86 0 0 -337 0 0 -SURF 0x30 -mat 1 -refs 3 -337 0 0 -293 0 0 -290 0 0 -SURF 0x30 -mat 1 -refs 3 -109 0 0 -290 0 0 -293 0 0 -SURF 0x30 -mat 1 -refs 3 -293 0 0 -337 0 0 -111 0 0 -SURF 0x30 -mat 1 -refs 3 -339 0 0 -89 0 0 -286 0 0 -SURF 0x30 -mat 1 -refs 3 -286 0 0 -289 0 0 -339 0 0 -SURF 0x30 -mat 1 -refs 3 -108 0 0 -339 0 0 -289 0 0 -SURF 0x30 -mat 1 -refs 3 -289 0 0 -286 0 0 -106 0 0 -SURF 0x30 -mat 1 -refs 3 -340 0 0 -90 0 0 -283 0 0 -SURF 0x30 -mat 1 -refs 3 -283 0 0 -284 0 0 -340 0 0 -SURF 0x30 -mat 1 -refs 3 -103 0 0 -340 0 0 -284 0 0 -SURF 0x30 -mat 1 -refs 3 -284 0 0 -283 0 0 -105 0 0 -SURF 0x30 -mat 1 -refs 3 -282 0 0 -91 0 0 -341 0 0 -SURF 0x30 -mat 1 -refs 3 -341 0 0 -281 0 0 -282 0 0 -SURF 0x30 -mat 1 -refs 3 -104 0 0 -282 0 0 -281 0 0 -SURF 0x30 -mat 1 -refs 3 -281 0 0 -341 0 0 -102 0 0 -SURF 0x30 -mat 1 -refs 3 -276 0 0 -97 0 0 -269 0 0 -SURF 0x30 -mat 1 -refs 3 -269 0 0 -344 0 0 -276 0 0 -SURF 0x30 -mat 1 -refs 3 -98 0 0 -276 0 0 -344 0 0 -SURF 0x30 -mat 1 -refs 3 -344 0 0 -269 0 0 -94 0 0 -SURF 0x30 -mat 1 -refs 3 -345 0 0 -95 0 0 -273 0 0 -SURF 0x30 -mat 1 -refs 3 -273 0 0 -274 0 0 -345 0 0 -SURF 0x30 -mat 1 -refs 3 -99 0 0 -345 0 0 -274 0 0 -SURF 0x30 -mat 1 -refs 3 -274 0 0 -273 0 0 -96 0 0 -SURF 0x30 -mat 1 -refs 3 -346 0 0 -56 0 0 -210 0 0 -SURF 0x30 -mat 1 -refs 3 -210 0 0 -272 0 0 -346 0 0 -SURF 0x30 -mat 1 -refs 3 -96 0 0 -346 0 0 -272 0 0 -SURF 0x30 -mat 1 -refs 3 -272 0 0 -210 0 0 -55 0 0 -SURF 0x30 -mat 1 -refs 3 -270 0 0 -54 0 0 -215 0 0 -SURF 0x30 -mat 1 -refs 3 -215 0 0 -347 0 0 -270 0 0 -SURF 0x30 -mat 1 -refs 3 -97 0 0 -270 0 0 -347 0 0 -SURF 0x30 -mat 1 -refs 3 -347 0 0 -215 0 0 -57 0 0 -SURF 0x30 -mat 1 -refs 3 -265 0 0 -58 0 0 -348 0 0 -SURF 0x30 -mat 1 -refs 3 -348 0 0 -268 0 0 -265 0 0 -SURF 0x30 -mat 1 -refs 3 -93 0 0 -265 0 0 -268 0 0 -SURF 0x30 -mat 1 -refs 3 -268 0 0 -348 0 0 -95 0 0 -SURF 0x30 -mat 1 -refs 3 -349 0 0 -59 0 0 -264 0 0 -SURF 0x30 -mat 1 -refs 3 -264 0 0 -267 0 0 -349 0 0 -SURF 0x30 -mat 1 -refs 3 -94 0 0 -349 0 0 -267 0 0 -SURF 0x30 -mat 1 -refs 3 -267 0 0 -264 0 0 -92 0 0 -SURF 0x30 -mat 1 -refs 3 -350 0 0 -62 0 0 -257 0 0 -SURF 0x30 -mat 1 -refs 3 -257 0 0 -258 0 0 -350 0 0 -SURF 0x30 -mat 1 -refs 3 -87 0 0 -350 0 0 -258 0 0 -SURF 0x30 -mat 1 -refs 3 -258 0 0 -257 0 0 -89 0 0 -SURF 0x30 -mat 1 -refs 3 -256 0 0 -63 0 0 -351 0 0 -SURF 0x30 -mat 1 -refs 3 -351 0 0 -255 0 0 -256 0 0 -SURF 0x30 -mat 1 -refs 3 -88 0 0 -256 0 0 -255 0 0 -SURF 0x30 -mat 1 -refs 3 -255 0 0 -351 0 0 -86 0 0 -SURF 0x30 -mat 1 -refs 3 -245 0 0 -72 0 0 -240 0 0 -SURF 0x30 -mat 1 -refs 3 -240 0 0 -360 0 0 -245 0 0 -SURF 0x30 -mat 1 -refs 3 -79 0 0 -245 0 0 -360 0 0 -SURF 0x30 -mat 1 -refs 3 -360 0 0 -240 0 0 -75 0 0 -SURF 0x30 -mat 1 -refs 3 -361 0 0 -74 0 0 -241 0 0 -SURF 0x30 -mat 1 -refs 3 -241 0 0 -242 0 0 -361 0 0 -SURF 0x30 -mat 1 -refs 3 -78 0 0 -361 0 0 -242 0 0 -SURF 0x30 -mat 1 -refs 3 -242 0 0 -241 0 0 -73 0 0 -SURF 0x30 -mat 1 -refs 3 -362 0 0 -33 0 0 -175 0 0 -SURF 0x30 -mat 1 -refs 3 -175 0 0 -239 0 0 -362 0 0 -SURF 0x30 -mat 1 -refs 3 -73 0 0 -362 0 0 -239 0 0 -SURF 0x30 -mat 1 -refs 3 -239 0 0 -175 0 0 -34 0 0 -SURF 0x30 -mat 1 -refs 3 -237 0 0 -35 0 0 -176 0 0 -SURF 0x30 -mat 1 -refs 3 -176 0 0 -363 0 0 -237 0 0 -SURF 0x30 -mat 1 -refs 3 -72 0 0 -237 0 0 -363 0 0 -SURF 0x30 -mat 1 -refs 3 -363 0 0 -176 0 0 -32 0 0 -SURF 0x30 -mat 1 -refs 3 -225 0 0 -44 0 0 -372 0 0 -SURF 0x30 -mat 1 -refs 3 -372 0 0 -228 0 0 -225 0 0 -SURF 0x30 -mat 1 -refs 3 -63 0 0 -225 0 0 -228 0 0 -SURF 0x30 -mat 1 -refs 3 -228 0 0 -372 0 0 -65 0 0 -SURF 0x30 -mat 1 -refs 3 -374 0 0 -47 0 0 -221 0 0 -SURF 0x30 -mat 1 -refs 3 -221 0 0 -224 0 0 -374 0 0 -SURF 0x30 -mat 1 -refs 3 -62 0 0 -374 0 0 -224 0 0 -SURF 0x30 -mat 1 -refs 3 -224 0 0 -221 0 0 -60 0 0 -SURF 0x30 -mat 1 -refs 3 -375 0 0 -24 0 0 -184 0 0 -SURF 0x30 -mat 1 -refs 3 -184 0 0 -185 0 0 -375 0 0 -SURF 0x30 -mat 1 -refs 3 -36 0 0 -375 0 0 -185 0 0 -SURF 0x30 -mat 1 -refs 3 -185 0 0 -184 0 0 -39 0 0 -SURF 0x30 -mat 1 -refs 3 -180 0 0 -26 0 0 -377 0 0 -SURF 0x30 -mat 1 -refs 3 -377 0 0 -179 0 0 -180 0 0 -SURF 0x30 -mat 1 -refs 3 -37 0 0 -180 0 0 -179 0 0 -SURF 0x30 -mat 1 -refs 3 -179 0 0 -377 0 0 -33 0 0 -SURF 0x30 -mat 1 -refs 3 -177 0 0 -28 0 0 -172 0 0 -SURF 0x30 -mat 1 -refs 3 -172 0 0 -378 0 0 -177 0 0 -SURF 0x30 -mat 1 -refs 3 -35 0 0 -177 0 0 -378 0 0 -SURF 0x30 -mat 1 -refs 3 -378 0 0 -172 0 0 -31 0 0 -SURF 0x30 -mat 1 -refs 3 -379 0 0 -30 0 0 -173 0 0 -SURF 0x30 -mat 1 -refs 3 -173 0 0 -174 0 0 -379 0 0 -SURF 0x30 -mat 1 -refs 3 -34 0 0 -379 0 0 -174 0 0 -SURF 0x30 -mat 1 -refs 3 -174 0 0 -173 0 0 -29 0 0 -SURF 0x30 -mat 1 -refs 4 -168 0 0 -30 0 0 -379 0 0 -380 0 0 -SURF 0x30 -mat 1 -refs 4 -26 0 0 -168 0 0 -380 0 0 -377 0 0 -SURF 0x30 -mat 1 -refs 4 -380 0 0 -379 0 0 -34 0 0 -175 0 0 -SURF 0x30 -mat 1 -refs 4 -377 0 0 -380 0 0 -175 0 0 -33 0 0 -SURF 0x30 -mat 1 -refs 4 -376 0 0 -32 0 0 -176 0 0 -381 0 0 -SURF 0x30 -mat 1 -refs 4 -27 0 0 -376 0 0 -381 0 0 -165 0 0 -SURF 0x30 -mat 1 -refs 4 -381 0 0 -176 0 0 -35 0 0 -378 0 0 -SURF 0x30 -mat 1 -refs 4 -165 0 0 -381 0 0 -378 0 0 -31 0 0 -SURF 0x30 -mat 1 -refs 4 -375 0 0 -36 0 0 -181 0 0 -382 0 0 -SURF 0x30 -mat 1 -refs 4 -24 0 0 -375 0 0 -382 0 0 -161 0 0 -SURF 0x30 -mat 1 -refs 4 -382 0 0 -181 0 0 -32 0 0 -376 0 0 -SURF 0x30 -mat 1 -refs 4 -161 0 0 -382 0 0 -376 0 0 -27 0 0 -SURF 0x30 -mat 1 -refs 4 -373 0 0 -45 0 0 -201 0 0 -383 0 0 -SURF 0x30 -mat 1 -refs 4 -64 0 0 -373 0 0 -383 0 0 -227 0 0 -SURF 0x30 -mat 1 -refs 4 -383 0 0 -201 0 0 -47 0 0 -374 0 0 -SURF 0x30 -mat 1 -refs 4 -227 0 0 -383 0 0 -374 0 0 -62 0 0 -SURF 0x30 -mat 1 -refs 4 -371 0 0 -43 0 0 -197 0 0 -384 0 0 -SURF 0x30 -mat 1 -refs 4 -66 0 0 -371 0 0 -384 0 0 -229 0 0 -SURF 0x30 -mat 1 -refs 4 -384 0 0 -197 0 0 -45 0 0 -373 0 0 -SURF 0x30 -mat 1 -refs 4 -229 0 0 -384 0 0 -373 0 0 -64 0 0 -SURF 0x30 -mat 1 -refs 4 -230 0 0 -65 0 0 -372 0 0 -385 0 0 -SURF 0x30 -mat 1 -refs 4 -67 0 0 -230 0 0 -385 0 0 -370 0 0 -SURF 0x30 -mat 1 -refs 4 -385 0 0 -372 0 0 -44 0 0 -194 0 0 -SURF 0x30 -mat 1 -refs 4 -370 0 0 -385 0 0 -194 0 0 -42 0 0 -SURF 0x30 -mat 1 -refs 4 -369 0 0 -41 0 0 -193 0 0 -386 0 0 -SURF 0x30 -mat 1 -refs 4 -68 0 0 -369 0 0 -386 0 0 -231 0 0 -SURF 0x30 -mat 1 -refs 4 -386 0 0 -193 0 0 -43 0 0 -371 0 0 -SURF 0x30 -mat 1 -refs 4 -231 0 0 -386 0 0 -371 0 0 -66 0 0 -SURF 0x30 -mat 1 -refs 4 -232 0 0 -67 0 0 -370 0 0 -387 0 0 -SURF 0x30 -mat 1 -refs 4 -69 0 0 -232 0 0 -387 0 0 -368 0 0 -SURF 0x30 -mat 1 -refs 4 -387 0 0 -370 0 0 -42 0 0 -190 0 0 -SURF 0x30 -mat 1 -refs 4 -368 0 0 -387 0 0 -190 0 0 -40 0 0 -SURF 0x30 -mat 1 -refs 4 -367 0 0 -39 0 0 -189 0 0 -388 0 0 -SURF 0x30 -mat 1 -refs 4 -71 0 0 -367 0 0 -388 0 0 -233 0 0 -SURF 0x30 -mat 1 -refs 4 -388 0 0 -189 0 0 -41 0 0 -369 0 0 -SURF 0x30 -mat 1 -refs 4 -233 0 0 -388 0 0 -369 0 0 -68 0 0 -SURF 0x30 -mat 1 -refs 4 -234 0 0 -69 0 0 -368 0 0 -389 0 0 -SURF 0x30 -mat 1 -refs 4 -70 0 0 -234 0 0 -389 0 0 -366 0 0 -SURF 0x30 -mat 1 -refs 4 -389 0 0 -368 0 0 -40 0 0 -186 0 0 -SURF 0x30 -mat 1 -refs 4 -366 0 0 -389 0 0 -186 0 0 -38 0 0 -SURF 0x30 -mat 1 -refs 4 -365 0 0 -36 0 0 -185 0 0 -390 0 0 -SURF 0x30 -mat 1 -refs 4 -75 0 0 -365 0 0 -390 0 0 -235 0 0 -SURF 0x30 -mat 1 -refs 4 -390 0 0 -185 0 0 -39 0 0 -367 0 0 -SURF 0x30 -mat 1 -refs 4 -235 0 0 -390 0 0 -367 0 0 -71 0 0 -SURF 0x30 -mat 1 -refs 4 -236 0 0 -70 0 0 -366 0 0 -391 0 0 -SURF 0x30 -mat 1 -refs 4 -74 0 0 -236 0 0 -391 0 0 -364 0 0 -SURF 0x30 -mat 1 -refs 4 -391 0 0 -366 0 0 -38 0 0 -182 0 0 -SURF 0x30 -mat 1 -refs 4 -364 0 0 -391 0 0 -182 0 0 -37 0 0 -SURF 0x30 -mat 1 -refs 4 -363 0 0 -32 0 0 -181 0 0 -392 0 0 -SURF 0x30 -mat 1 -refs 4 -72 0 0 -363 0 0 -392 0 0 -240 0 0 -SURF 0x30 -mat 1 -refs 4 -392 0 0 -181 0 0 -36 0 0 -365 0 0 -SURF 0x30 -mat 1 -refs 4 -240 0 0 -392 0 0 -365 0 0 -75 0 0 -SURF 0x30 -mat 1 -refs 4 -241 0 0 -74 0 0 -364 0 0 -393 0 0 -SURF 0x30 -mat 1 -refs 4 -73 0 0 -241 0 0 -393 0 0 -362 0 0 -SURF 0x30 -mat 1 -refs 4 -393 0 0 -364 0 0 -37 0 0 -179 0 0 -SURF 0x30 -mat 1 -refs 4 -362 0 0 -393 0 0 -179 0 0 -33 0 0 -SURF 0x30 -mat 1 -refs 4 -236 0 0 -74 0 0 -361 0 0 -394 0 0 -SURF 0x30 -mat 1 -refs 4 -70 0 0 -236 0 0 -394 0 0 -359 0 0 -SURF 0x30 -mat 1 -refs 4 -394 0 0 -361 0 0 -78 0 0 -243 0 0 -SURF 0x30 -mat 1 -refs 4 -359 0 0 -394 0 0 -243 0 0 -77 0 0 -SURF 0x30 -mat 1 -refs 4 -358 0 0 -76 0 0 -244 0 0 -395 0 0 -SURF 0x30 -mat 1 -refs 4 -71 0 0 -358 0 0 -395 0 0 -235 0 0 -SURF 0x30 -mat 1 -refs 4 -395 0 0 -244 0 0 -79 0 0 -360 0 0 -SURF 0x30 -mat 1 -refs 4 -235 0 0 -395 0 0 -360 0 0 -75 0 0 -SURF 0x30 -mat 1 -refs 4 -234 0 0 -70 0 0 -359 0 0 -396 0 0 -SURF 0x30 -mat 1 -refs 4 -69 0 0 -234 0 0 -396 0 0 -357 0 0 -SURF 0x30 -mat 1 -refs 4 -396 0 0 -359 0 0 -77 0 0 -247 0 0 -SURF 0x30 -mat 1 -refs 4 -357 0 0 -396 0 0 -247 0 0 -81 0 0 -SURF 0x30 -mat 1 -refs 4 -356 0 0 -80 0 0 -248 0 0 -397 0 0 -SURF 0x30 -mat 1 -refs 4 -68 0 0 -356 0 0 -397 0 0 -233 0 0 -SURF 0x30 -mat 1 -refs 4 -397 0 0 -248 0 0 -76 0 0 -358 0 0 -SURF 0x30 -mat 1 -refs 4 -233 0 0 -397 0 0 -358 0 0 -71 0 0 -SURF 0x30 -mat 1 -refs 4 -232 0 0 -69 0 0 -357 0 0 -398 0 0 -SURF 0x30 -mat 1 -refs 4 -67 0 0 -232 0 0 -398 0 0 -355 0 0 -SURF 0x30 -mat 1 -refs 4 -398 0 0 -357 0 0 -81 0 0 -249 0 0 -SURF 0x30 -mat 1 -refs 4 -355 0 0 -398 0 0 -249 0 0 -82 0 0 -SURF 0x30 -mat 1 -refs 4 -354 0 0 -83 0 0 -250 0 0 -399 0 0 -SURF 0x30 -mat 1 -refs 4 -66 0 0 -354 0 0 -399 0 0 -231 0 0 -SURF 0x30 -mat 1 -refs 4 -399 0 0 -250 0 0 -80 0 0 -356 0 0 -SURF 0x30 -mat 1 -refs 4 -231 0 0 -399 0 0 -356 0 0 -68 0 0 -SURF 0x30 -mat 1 -refs 4 -230 0 0 -67 0 0 -355 0 0 -400 0 0 -SURF 0x30 -mat 1 -refs 4 -65 0 0 -230 0 0 -400 0 0 -353 0 0 -SURF 0x30 -mat 1 -refs 4 -400 0 0 -355 0 0 -82 0 0 -251 0 0 -SURF 0x30 -mat 1 -refs 4 -353 0 0 -400 0 0 -251 0 0 -84 0 0 -SURF 0x30 -mat 1 -refs 4 -352 0 0 -85 0 0 -252 0 0 -401 0 0 -SURF 0x30 -mat 1 -refs 4 -64 0 0 -352 0 0 -401 0 0 -229 0 0 -SURF 0x30 -mat 1 -refs 4 -401 0 0 -252 0 0 -83 0 0 -354 0 0 -SURF 0x30 -mat 1 -refs 4 -229 0 0 -401 0 0 -354 0 0 -66 0 0 -SURF 0x30 -mat 1 -refs 4 -228 0 0 -65 0 0 -353 0 0 -402 0 0 -SURF 0x30 -mat 1 -refs 4 -63 0 0 -228 0 0 -402 0 0 -351 0 0 -SURF 0x30 -mat 1 -refs 4 -402 0 0 -353 0 0 -84 0 0 -253 0 0 -SURF 0x30 -mat 1 -refs 4 -351 0 0 -402 0 0 -253 0 0 -86 0 0 -SURF 0x30 -mat 1 -refs 4 -350 0 0 -87 0 0 -254 0 0 -403 0 0 -SURF 0x30 -mat 1 -refs 4 -62 0 0 -350 0 0 -403 0 0 -227 0 0 -SURF 0x30 -mat 1 -refs 4 -403 0 0 -254 0 0 -85 0 0 -352 0 0 -SURF 0x30 -mat 1 -refs 4 -227 0 0 -403 0 0 -352 0 0 -64 0 0 -SURF 0x30 -mat 1 -refs 4 -347 0 0 -57 0 0 -219 0 0 -404 0 0 -SURF 0x30 -mat 1 -refs 4 -97 0 0 -347 0 0 -404 0 0 -269 0 0 -SURF 0x30 -mat 1 -refs 4 -404 0 0 -219 0 0 -59 0 0 -349 0 0 -SURF 0x30 -mat 1 -refs 4 -269 0 0 -404 0 0 -349 0 0 -94 0 0 -SURF 0x30 -mat 1 -refs 4 -273 0 0 -95 0 0 -348 0 0 -405 0 0 -SURF 0x30 -mat 1 -refs 4 -96 0 0 -273 0 0 -405 0 0 -346 0 0 -SURF 0x30 -mat 1 -refs 4 -405 0 0 -348 0 0 -58 0 0 -216 0 0 -SURF 0x30 -mat 1 -refs 4 -346 0 0 -405 0 0 -216 0 0 -56 0 0 -SURF 0x30 -mat 1 -refs 4 -268 0 0 -95 0 0 -345 0 0 -406 0 0 -SURF 0x30 -mat 1 -refs 4 -93 0 0 -268 0 0 -406 0 0 -343 0 0 -SURF 0x30 -mat 1 -refs 4 -406 0 0 -345 0 0 -99 0 0 -275 0 0 -SURF 0x30 -mat 1 -refs 4 -343 0 0 -406 0 0 -275 0 0 -100 0 0 -SURF 0x30 -mat 1 -refs 4 -342 0 0 -101 0 0 -278 0 0 -407 0 0 -SURF 0x30 -mat 1 -refs 4 -92 0 0 -342 0 0 -407 0 0 -267 0 0 -SURF 0x30 -mat 1 -refs 4 -407 0 0 -278 0 0 -98 0 0 -344 0 0 -SURF 0x30 -mat 1 -refs 4 -267 0 0 -407 0 0 -344 0 0 -94 0 0 -SURF 0x30 -mat 1 -refs 4 -266 0 0 -93 0 0 -343 0 0 -408 0 0 -SURF 0x30 -mat 1 -refs 4 -91 0 0 -266 0 0 -408 0 0 -341 0 0 -SURF 0x30 -mat 1 -refs 4 -408 0 0 -343 0 0 -100 0 0 -279 0 0 -SURF 0x30 -mat 1 -refs 4 -341 0 0 -408 0 0 -279 0 0 -102 0 0 -SURF 0x30 -mat 1 -refs 4 -340 0 0 -103 0 0 -280 0 0 -409 0 0 -SURF 0x30 -mat 1 -refs 4 -90 0 0 -340 0 0 -409 0 0 -263 0 0 -SURF 0x30 -mat 1 -refs 4 -409 0 0 -280 0 0 -101 0 0 -342 0 0 -SURF 0x30 -mat 1 -refs 4 -263 0 0 -409 0 0 -342 0 0 -92 0 0 -SURF 0x30 -mat 1 -refs 4 -338 0 0 -87 0 0 -258 0 0 -410 0 0 -SURF 0x30 -mat 1 -refs 4 -110 0 0 -338 0 0 -410 0 0 -292 0 0 -SURF 0x30 -mat 1 -refs 4 -410 0 0 -258 0 0 -89 0 0 -339 0 0 -SURF 0x30 -mat 1 -refs 4 -292 0 0 -410 0 0 -339 0 0 -108 0 0 -SURF 0x30 -mat 1 -refs 4 -336 0 0 -85 0 0 -254 0 0 -411 0 0 -SURF 0x30 -mat 1 -refs 4 -112 0 0 -336 0 0 -411 0 0 -294 0 0 -SURF 0x30 -mat 1 -refs 4 -411 0 0 -254 0 0 -87 0 0 -338 0 0 -SURF 0x30 -mat 1 -refs 4 -294 0 0 -411 0 0 -338 0 0 -110 0 0 -SURF 0x30 -mat 1 -refs 4 -295 0 0 -111 0 0 -337 0 0 -412 0 0 -SURF 0x30 -mat 1 -refs 4 -113 0 0 -295 0 0 -412 0 0 -335 0 0 -SURF 0x30 -mat 1 -refs 4 -412 0 0 -337 0 0 -86 0 0 -253 0 0 -SURF 0x30 -mat 1 -refs 4 -335 0 0 -412 0 0 -253 0 0 -84 0 0 -SURF 0x30 -mat 1 -refs 4 -334 0 0 -83 0 0 -252 0 0 -413 0 0 -SURF 0x30 -mat 1 -refs 4 -115 0 0 -334 0 0 -413 0 0 -296 0 0 -SURF 0x30 -mat 1 -refs 4 -413 0 0 -252 0 0 -85 0 0 -336 0 0 -SURF 0x30 -mat 1 -refs 4 -296 0 0 -413 0 0 -336 0 0 -112 0 0 -SURF 0x30 -mat 1 -refs 4 -297 0 0 -113 0 0 -335 0 0 -414 0 0 -SURF 0x30 -mat 1 -refs 4 -114 0 0 -297 0 0 -414 0 0 -333 0 0 -SURF 0x30 -mat 1 -refs 4 -414 0 0 -335 0 0 -84 0 0 -251 0 0 -SURF 0x30 -mat 1 -refs 4 -333 0 0 -414 0 0 -251 0 0 -82 0 0 -SURF 0x30 -mat 1 -refs 4 -332 0 0 -80 0 0 -250 0 0 -415 0 0 -SURF 0x30 -mat 1 -refs 4 -119 0 0 -332 0 0 -415 0 0 -298 0 0 -SURF 0x30 -mat 1 -refs 4 -415 0 0 -250 0 0 -83 0 0 -334 0 0 -SURF 0x30 -mat 1 -refs 4 -298 0 0 -415 0 0 -334 0 0 -115 0 0 -SURF 0x30 -mat 1 -refs 4 -300 0 0 -114 0 0 -333 0 0 -416 0 0 -SURF 0x30 -mat 1 -refs 4 -118 0 0 -300 0 0 -416 0 0 -331 0 0 -SURF 0x30 -mat 1 -refs 4 -416 0 0 -333 0 0 -82 0 0 -249 0 0 -SURF 0x30 -mat 1 -refs 4 -331 0 0 -416 0 0 -249 0 0 -81 0 0 -SURF 0x30 -mat 1 -refs 4 -305 0 0 -118 0 0 -331 0 0 -417 0 0 -SURF 0x30 -mat 1 -refs 4 -117 0 0 -305 0 0 -417 0 0 -330 0 0 -SURF 0x30 -mat 1 -refs 4 -417 0 0 -331 0 0 -81 0 0 -247 0 0 -SURF 0x30 -mat 1 -refs 4 -330 0 0 -417 0 0 -247 0 0 -77 0 0 -SURF 0x30 -mat 1 -refs 4 -285 0 0 -104 0 0 -281 0 0 -418 0 0 -SURF 0x30 -mat 1 -refs 4 -106 0 0 -285 0 0 -418 0 0 -313 0 0 -SURF 0x30 -mat 1 -refs 4 -418 0 0 -281 0 0 -102 0 0 -311 0 0 -SURF 0x30 -mat 1 -refs 4 -313 0 0 -418 0 0 -311 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 4 -314 0 0 -120 0 0 -312 0 0 -419 0 0 -SURF 0x30 -mat 1 -refs 4 -107 0 0 -314 0 0 -419 0 0 -288 0 0 -SURF 0x30 -mat 1 -refs 4 -419 0 0 -312 0 0 -103 0 0 -284 0 0 -SURF 0x30 -mat 1 -refs 4 -288 0 0 -419 0 0 -284 0 0 -105 0 0 -SURF 0x30 -mat 1 -refs 4 -207 0 0 -52 0 0 -208 0 0 -420 0 0 -SURF 0x30 -mat 1 -refs 4 -53 0 0 -207 0 0 -420 0 0 -206 0 0 -SURF 0x30 -mat 1 -refs 4 -420 0 0 -208 0 0 -51 0 0 -329 0 0 -SURF 0x30 -mat 1 -refs 4 -206 0 0 -420 0 0 -329 0 0 -50 0 0 -SURF 0x30 -mat 1 -refs 4 -329 0 0 -51 0 0 -205 0 0 -421 0 0 -SURF 0x30 -mat 1 -refs 4 -50 0 0 -329 0 0 -421 0 0 -204 0 0 -SURF 0x30 -mat 1 -refs 4 -421 0 0 -205 0 0 -49 0 0 -328 0 0 -SURF 0x30 -mat 1 -refs 4 -204 0 0 -421 0 0 -328 0 0 -48 0 0 -SURF 0x30 -mat 1 -refs 4 -328 0 0 -49 0 0 -203 0 0 -422 0 0 -SURF 0x30 -mat 1 -refs 4 -48 0 0 -328 0 0 -422 0 0 -202 0 0 -SURF 0x30 -mat 1 -refs 4 -422 0 0 -203 0 0 -47 0 0 -327 0 0 -SURF 0x30 -mat 1 -refs 4 -202 0 0 -422 0 0 -327 0 0 -46 0 0 -SURF 0x30 -mat 1 -refs 4 -326 0 0 -17 0 0 -199 0 0 -423 0 0 -SURF 0x30 -mat 1 -refs 4 -16 0 0 -326 0 0 -423 0 0 -200 0 0 -SURF 0x30 -mat 1 -refs 4 -423 0 0 -199 0 0 -46 0 0 -327 0 0 -SURF 0x30 -mat 1 -refs 4 -200 0 0 -423 0 0 -327 0 0 -47 0 0 -SURF 0x30 -mat 1 -refs 4 -326 0 0 -16 0 0 -143 0 0 -424 0 0 -SURF 0x30 -mat 1 -refs 4 -17 0 0 -326 0 0 -424 0 0 -144 0 0 -SURF 0x30 -mat 1 -refs 4 -424 0 0 -143 0 0 -15 0 0 -141 0 0 -SURF 0x30 -mat 1 -refs 4 -144 0 0 -424 0 0 -141 0 0 -14 0 0 -SURF 0x30 -mat 1 -refs 4 -244 0 0 -76 0 0 -299 0 0 -425 0 0 -SURF 0x30 -mat 1 -refs 4 -79 0 0 -244 0 0 -425 0 0 -301 0 0 -SURF 0x30 -mat 1 -refs 4 -425 0 0 -299 0 0 -119 0 0 -304 0 0 -SURF 0x30 -mat 1 -refs 4 -301 0 0 -425 0 0 -304 0 0 -116 0 0 -SURF 0x30 -mat 1 -refs 4 -246 0 0 -79 0 0 -301 0 0 -426 0 0 -SURF 0x30 -mat 1 -refs 4 -78 0 0 -246 0 0 -426 0 0 -303 0 0 -SURF 0x30 -mat 1 -refs 4 -426 0 0 -301 0 0 -116 0 0 -302 0 0 -SURF 0x30 -mat 1 -refs 4 -303 0 0 -426 0 0 -302 0 0 -117 0 0 -SURF 0x30 -mat 1 -refs 4 -290 0 0 -109 0 0 -291 0 0 -427 0 0 -SURF 0x30 -mat 1 -refs 4 -86 0 0 -290 0 0 -427 0 0 -255 0 0 -SURF 0x30 -mat 1 -refs 4 -427 0 0 -291 0 0 -107 0 0 -287 0 0 -SURF 0x30 -mat 1 -refs 4 -255 0 0 -427 0 0 -287 0 0 -88 0 0 -SURF 0x30 -mat 1 -refs 4 -287 0 0 -107 0 0 -288 0 0 -428 0 0 -SURF 0x30 -mat 1 -refs 4 -88 0 0 -287 0 0 -428 0 0 -259 0 0 -SURF 0x30 -mat 1 -refs 4 -428 0 0 -288 0 0 -105 0 0 -283 0 0 -SURF 0x30 -mat 1 -refs 4 -259 0 0 -428 0 0 -283 0 0 -90 0 0 -SURF 0x30 -mat 1 -refs 4 -262 0 0 -91 0 0 -282 0 0 -429 0 0 -SURF 0x30 -mat 1 -refs 4 -89 0 0 -262 0 0 -429 0 0 -286 0 0 -SURF 0x30 -mat 1 -refs 4 -429 0 0 -282 0 0 -104 0 0 -285 0 0 -SURF 0x30 -mat 1 -refs 4 -286 0 0 -429 0 0 -285 0 0 -106 0 0 -SURF 0x30 -mat 1 -refs 4 -271 0 0 -97 0 0 -276 0 0 -430 0 0 -SURF 0x30 -mat 1 -refs 4 -96 0 0 -271 0 0 -430 0 0 -274 0 0 -SURF 0x30 -mat 1 -refs 4 -430 0 0 -276 0 0 -98 0 0 -277 0 0 -SURF 0x30 -mat 1 -refs 4 -274 0 0 -430 0 0 -277 0 0 -99 0 0 -SURF 0x30 -mat 1 -refs 4 -213 0 0 -54 0 0 -270 0 0 -431 0 0 -SURF 0x30 -mat 1 -refs 4 -55 0 0 -213 0 0 -431 0 0 -272 0 0 -SURF 0x30 -mat 1 -refs 4 -431 0 0 -270 0 0 -97 0 0 -271 0 0 -SURF 0x30 -mat 1 -refs 4 -272 0 0 -431 0 0 -271 0 0 -96 0 0 -SURF 0x30 -mat 1 -refs 4 -265 0 0 -93 0 0 -266 0 0 -432 0 0 -SURF 0x30 -mat 1 -refs 4 -58 0 0 -265 0 0 -432 0 0 -220 0 0 -SURF 0x30 -mat 1 -refs 4 -432 0 0 -266 0 0 -91 0 0 -261 0 0 -SURF 0x30 -mat 1 -refs 4 -220 0 0 -432 0 0 -261 0 0 -60 0 0 -SURF 0x30 -mat 1 -refs 4 -223 0 0 -61 0 0 -260 0 0 -433 0 0 -SURF 0x30 -mat 1 -refs 4 -59 0 0 -223 0 0 -433 0 0 -264 0 0 -SURF 0x30 -mat 1 -refs 4 -433 0 0 -260 0 0 -90 0 0 -263 0 0 -SURF 0x30 -mat 1 -refs 4 -264 0 0 -433 0 0 -263 0 0 -92 0 0 -SURF 0x30 -mat 1 -refs 4 -224 0 0 -60 0 0 -261 0 0 -434 0 0 -SURF 0x30 -mat 1 -refs 4 -62 0 0 -224 0 0 -434 0 0 -257 0 0 -SURF 0x30 -mat 1 -refs 4 -434 0 0 -261 0 0 -91 0 0 -262 0 0 -SURF 0x30 -mat 1 -refs 4 -257 0 0 -434 0 0 -262 0 0 -89 0 0 -SURF 0x30 -mat 1 -refs 4 -256 0 0 -88 0 0 -259 0 0 -435 0 0 -SURF 0x30 -mat 1 -refs 4 -63 0 0 -256 0 0 -435 0 0 -226 0 0 -SURF 0x30 -mat 1 -refs 4 -435 0 0 -259 0 0 -90 0 0 -260 0 0 -SURF 0x30 -mat 1 -refs 4 -226 0 0 -435 0 0 -260 0 0 -61 0 0 -SURF 0x30 -mat 1 -refs 4 -238 0 0 -72 0 0 -245 0 0 -436 0 0 -SURF 0x30 -mat 1 -refs 4 -73 0 0 -238 0 0 -436 0 0 -242 0 0 -SURF 0x30 -mat 1 -refs 4 -436 0 0 -245 0 0 -79 0 0 -246 0 0 -SURF 0x30 -mat 1 -refs 4 -242 0 0 -436 0 0 -246 0 0 -78 0 0 -SURF 0x30 -mat 1 -refs 4 -178 0 0 -35 0 0 -237 0 0 -437 0 0 -SURF 0x30 -mat 1 -refs 4 -34 0 0 -178 0 0 -437 0 0 -239 0 0 -SURF 0x30 -mat 1 -refs 4 -437 0 0 -237 0 0 -72 0 0 -238 0 0 -SURF 0x30 -mat 1 -refs 4 -239 0 0 -437 0 0 -238 0 0 -73 0 0 -SURF 0x30 -mat 1 -refs 4 -225 0 0 -63 0 0 -226 0 0 -438 0 0 -SURF 0x30 -mat 1 -refs 4 -44 0 0 -225 0 0 -438 0 0 -198 0 0 -SURF 0x30 -mat 1 -refs 4 -438 0 0 -226 0 0 -61 0 0 -222 0 0 -SURF 0x30 -mat 1 -refs 4 -198 0 0 -438 0 0 -222 0 0 -46 0 0 -SURF 0x30 -mat 1 -refs 4 -222 0 0 -61 0 0 -223 0 0 -439 0 0 -SURF 0x30 -mat 1 -refs 4 -46 0 0 -222 0 0 -439 0 0 -202 0 0 -SURF 0x30 -mat 1 -refs 4 -439 0 0 -223 0 0 -59 0 0 -218 0 0 -SURF 0x30 -mat 1 -refs 4 -202 0 0 -439 0 0 -218 0 0 -48 0 0 -SURF 0x30 -mat 1 -refs 4 -203 0 0 -49 0 0 -217 0 0 -440 0 0 -SURF 0x30 -mat 1 -refs 4 -47 0 0 -203 0 0 -440 0 0 -221 0 0 -SURF 0x30 -mat 1 -refs 4 -440 0 0 -217 0 0 -58 0 0 -220 0 0 -SURF 0x30 -mat 1 -refs 4 -221 0 0 -440 0 0 -220 0 0 -60 0 0 -SURF 0x30 -mat 1 -refs 4 -218 0 0 -59 0 0 -219 0 0 -441 0 0 -SURF 0x30 -mat 1 -refs 4 -48 0 0 -218 0 0 -441 0 0 -204 0 0 -SURF 0x30 -mat 1 -refs 4 -441 0 0 -219 0 0 -57 0 0 -214 0 0 -SURF 0x30 -mat 1 -refs 4 -204 0 0 -441 0 0 -214 0 0 -50 0 0 -SURF 0x30 -mat 1 -refs 4 -205 0 0 -51 0 0 -211 0 0 -442 0 0 -SURF 0x30 -mat 1 -refs 4 -49 0 0 -205 0 0 -442 0 0 -217 0 0 -SURF 0x30 -mat 1 -refs 4 -442 0 0 -211 0 0 -56 0 0 -216 0 0 -SURF 0x30 -mat 1 -refs 4 -217 0 0 -442 0 0 -216 0 0 -58 0 0 -SURF 0x30 -mat 1 -refs 4 -206 0 0 -50 0 0 -214 0 0 -443 0 0 -SURF 0x30 -mat 1 -refs 4 -53 0 0 -206 0 0 -443 0 0 -212 0 0 -SURF 0x30 -mat 1 -refs 4 -443 0 0 -214 0 0 -57 0 0 -215 0 0 -SURF 0x30 -mat 1 -refs 4 -212 0 0 -443 0 0 -215 0 0 -54 0 0 -SURF 0x30 -mat 1 -refs 4 -207 0 0 -53 0 0 -212 0 0 -444 0 0 -SURF 0x30 -mat 1 -refs 4 -52 0 0 -207 0 0 -444 0 0 -209 0 0 -SURF 0x30 -mat 1 -refs 4 -444 0 0 -212 0 0 -54 0 0 -213 0 0 -SURF 0x30 -mat 1 -refs 4 -209 0 0 -444 0 0 -213 0 0 -55 0 0 -SURF 0x30 -mat 1 -refs 4 -209 0 0 -55 0 0 -210 0 0 -445 0 0 -SURF 0x30 -mat 1 -refs 4 -52 0 0 -209 0 0 -445 0 0 -208 0 0 -SURF 0x30 -mat 1 -refs 4 -445 0 0 -210 0 0 -56 0 0 -211 0 0 -SURF 0x30 -mat 1 -refs 4 -208 0 0 -445 0 0 -211 0 0 -51 0 0 -SURF 0x30 -mat 1 -refs 4 -145 0 0 -16 0 0 -200 0 0 -446 0 0 -SURF 0x30 -mat 1 -refs 4 -18 0 0 -145 0 0 -446 0 0 -196 0 0 -SURF 0x30 -mat 1 -refs 4 -446 0 0 -200 0 0 -47 0 0 -201 0 0 -SURF 0x30 -mat 1 -refs 4 -196 0 0 -446 0 0 -201 0 0 -45 0 0 -SURF 0x30 -mat 1 -refs 4 -195 0 0 -44 0 0 -198 0 0 -447 0 0 -SURF 0x30 -mat 1 -refs 4 -19 0 0 -195 0 0 -447 0 0 -148 0 0 -SURF 0x30 -mat 1 -refs 4 -447 0 0 -198 0 0 -46 0 0 -199 0 0 -SURF 0x30 -mat 1 -refs 4 -148 0 0 -447 0 0 -199 0 0 -17 0 0 -SURF 0x30 -mat 1 -refs 4 -149 0 0 -18 0 0 -196 0 0 -448 0 0 -SURF 0x30 -mat 1 -refs 4 -20 0 0 -149 0 0 -448 0 0 -192 0 0 -SURF 0x30 -mat 1 -refs 4 -448 0 0 -196 0 0 -45 0 0 -197 0 0 -SURF 0x30 -mat 1 -refs 4 -192 0 0 -448 0 0 -197 0 0 -43 0 0 -SURF 0x30 -mat 1 -refs 4 -191 0 0 -42 0 0 -194 0 0 -449 0 0 -SURF 0x30 -mat 1 -refs 4 -21 0 0 -191 0 0 -449 0 0 -152 0 0 -SURF 0x30 -mat 1 -refs 4 -449 0 0 -194 0 0 -44 0 0 -195 0 0 -SURF 0x30 -mat 1 -refs 4 -152 0 0 -449 0 0 -195 0 0 -19 0 0 -SURF 0x30 -mat 1 -refs 4 -153 0 0 -20 0 0 -192 0 0 -450 0 0 -SURF 0x30 -mat 1 -refs 4 -22 0 0 -153 0 0 -450 0 0 -188 0 0 -SURF 0x30 -mat 1 -refs 4 -450 0 0 -192 0 0 -43 0 0 -193 0 0 -SURF 0x30 -mat 1 -refs 4 -188 0 0 -450 0 0 -193 0 0 -41 0 0 -SURF 0x30 -mat 1 -refs 4 -187 0 0 -40 0 0 -190 0 0 -451 0 0 -SURF 0x30 -mat 1 -refs 4 -23 0 0 -187 0 0 -451 0 0 -156 0 0 -SURF 0x30 -mat 1 -refs 4 -451 0 0 -190 0 0 -42 0 0 -191 0 0 -SURF 0x30 -mat 1 -refs 4 -156 0 0 -451 0 0 -191 0 0 -21 0 0 -SURF 0x30 -mat 1 -refs 4 -157 0 0 -22 0 0 -188 0 0 -452 0 0 -SURF 0x30 -mat 1 -refs 4 -24 0 0 -157 0 0 -452 0 0 -184 0 0 -SURF 0x30 -mat 1 -refs 4 -452 0 0 -188 0 0 -41 0 0 -189 0 0 -SURF 0x30 -mat 1 -refs 4 -184 0 0 -452 0 0 -189 0 0 -39 0 0 -SURF 0x30 -mat 1 -refs 4 -183 0 0 -38 0 0 -186 0 0 -453 0 0 -SURF 0x30 -mat 1 -refs 4 -25 0 0 -183 0 0 -453 0 0 -160 0 0 -SURF 0x30 -mat 1 -refs 4 -453 0 0 -186 0 0 -40 0 0 -187 0 0 -SURF 0x30 -mat 1 -refs 4 -160 0 0 -453 0 0 -187 0 0 -23 0 0 -SURF 0x30 -mat 1 -refs 4 -180 0 0 -37 0 0 -182 0 0 -454 0 0 -SURF 0x30 -mat 1 -refs 4 -26 0 0 -180 0 0 -454 0 0 -164 0 0 -SURF 0x30 -mat 1 -refs 4 -454 0 0 -182 0 0 -38 0 0 -183 0 0 -SURF 0x30 -mat 1 -refs 4 -164 0 0 -454 0 0 -183 0 0 -25 0 0 -SURF 0x30 -mat 1 -refs 4 -170 0 0 -28 0 0 -177 0 0 -455 0 0 -SURF 0x30 -mat 1 -refs 4 -29 0 0 -170 0 0 -455 0 0 -174 0 0 -SURF 0x30 -mat 1 -refs 4 -455 0 0 -177 0 0 -35 0 0 -178 0 0 -SURF 0x30 -mat 1 -refs 4 -174 0 0 -455 0 0 -178 0 0 -34 0 0 -SURF 0x30 -mat 1 -refs 4 -171 0 0 -29 0 0 -173 0 0 -456 0 0 -SURF 0x30 -mat 1 -refs 4 -2 0 0 -171 0 0 -456 0 0 -121 0 0 -SURF 0x30 -mat 1 -refs 4 -456 0 0 -173 0 0 -30 0 0 -167 0 0 -SURF 0x30 -mat 1 -refs 4 -121 0 0 -456 0 0 -167 0 0 -1 0 0 -SURF 0x30 -mat 1 -refs 4 -123 0 0 -0 0 0 -166 0 0 -457 0 0 -SURF 0x30 -mat 1 -refs 4 -3 0 0 -123 0 0 -457 0 0 -169 0 0 -SURF 0x30 -mat 1 -refs 4 -457 0 0 -166 0 0 -31 0 0 -172 0 0 -SURF 0x30 -mat 1 -refs 4 -169 0 0 -457 0 0 -172 0 0 -28 0 0 -SURF 0x30 -mat 1 -refs 4 -124 0 0 -3 0 0 -169 0 0 -458 0 0 -SURF 0x30 -mat 1 -refs 4 -2 0 0 -124 0 0 -458 0 0 -171 0 0 -SURF 0x30 -mat 1 -refs 4 -458 0 0 -169 0 0 -28 0 0 -170 0 0 -SURF 0x30 -mat 1 -refs 4 -171 0 0 -458 0 0 -170 0 0 -29 0 0 -SURF 0x30 -mat 1 -refs 4 -167 0 0 -30 0 0 -168 0 0 -459 0 0 -SURF 0x30 -mat 1 -refs 4 -1 0 0 -167 0 0 -459 0 0 -125 0 0 -SURF 0x30 -mat 1 -refs 4 -459 0 0 -168 0 0 -26 0 0 -163 0 0 -SURF 0x30 -mat 1 -refs 4 -125 0 0 -459 0 0 -163 0 0 -5 0 0 -SURF 0x30 -mat 1 -refs 4 -127 0 0 -4 0 0 -162 0 0 -460 0 0 -SURF 0x30 -mat 1 -refs 4 -0 0 0 -127 0 0 -460 0 0 -166 0 0 -SURF 0x30 -mat 1 -refs 4 -460 0 0 -162 0 0 -27 0 0 -165 0 0 -SURF 0x30 -mat 1 -refs 4 -166 0 0 -460 0 0 -165 0 0 -31 0 0 -SURF 0x30 -mat 1 -refs 4 -163 0 0 -26 0 0 -164 0 0 -461 0 0 -SURF 0x30 -mat 1 -refs 4 -5 0 0 -163 0 0 -461 0 0 -128 0 0 -SURF 0x30 -mat 1 -refs 4 -461 0 0 -164 0 0 -25 0 0 -159 0 0 -SURF 0x30 -mat 1 -refs 4 -128 0 0 -461 0 0 -159 0 0 -6 0 0 -SURF 0x30 -mat 1 -refs 4 -130 0 0 -7 0 0 -158 0 0 -462 0 0 -SURF 0x30 -mat 1 -refs 4 -4 0 0 -130 0 0 -462 0 0 -162 0 0 -SURF 0x30 -mat 1 -refs 4 -462 0 0 -158 0 0 -24 0 0 -161 0 0 -SURF 0x30 -mat 1 -refs 4 -162 0 0 -462 0 0 -161 0 0 -27 0 0 -SURF 0x30 -mat 1 -refs 4 -159 0 0 -25 0 0 -160 0 0 -463 0 0 -SURF 0x30 -mat 1 -refs 4 -6 0 0 -159 0 0 -463 0 0 -131 0 0 -SURF 0x30 -mat 1 -refs 4 -463 0 0 -160 0 0 -23 0 0 -155 0 0 -SURF 0x30 -mat 1 -refs 4 -131 0 0 -463 0 0 -155 0 0 -8 0 0 -SURF 0x30 -mat 1 -refs 4 -133 0 0 -9 0 0 -154 0 0 -464 0 0 -SURF 0x30 -mat 1 -refs 4 -7 0 0 -133 0 0 -464 0 0 -158 0 0 -SURF 0x30 -mat 1 -refs 4 -464 0 0 -154 0 0 -22 0 0 -157 0 0 -SURF 0x30 -mat 1 -refs 4 -158 0 0 -464 0 0 -157 0 0 -24 0 0 -SURF 0x30 -mat 1 -refs 4 -134 0 0 -8 0 0 -155 0 0 -465 0 0 -SURF 0x30 -mat 1 -refs 4 -10 0 0 -134 0 0 -465 0 0 -151 0 0 -SURF 0x30 -mat 1 -refs 4 -465 0 0 -155 0 0 -23 0 0 -156 0 0 -SURF 0x30 -mat 1 -refs 4 -151 0 0 -465 0 0 -156 0 0 -21 0 0 -SURF 0x30 -mat 1 -refs 4 -150 0 0 -20 0 0 -153 0 0 -466 0 0 -SURF 0x30 -mat 1 -refs 4 -11 0 0 -150 0 0 -466 0 0 -136 0 0 -SURF 0x30 -mat 1 -refs 4 -466 0 0 -153 0 0 -22 0 0 -154 0 0 -SURF 0x30 -mat 1 -refs 4 -136 0 0 -466 0 0 -154 0 0 -9 0 0 -SURF 0x30 -mat 1 -refs 4 -137 0 0 -10 0 0 -151 0 0 -467 0 0 -SURF 0x30 -mat 1 -refs 4 -12 0 0 -137 0 0 -467 0 0 -147 0 0 -SURF 0x30 -mat 1 -refs 4 -467 0 0 -151 0 0 -21 0 0 -152 0 0 -SURF 0x30 -mat 1 -refs 4 -147 0 0 -467 0 0 -152 0 0 -19 0 0 -SURF 0x30 -mat 1 -refs 4 -146 0 0 -18 0 0 -149 0 0 -468 0 0 -SURF 0x30 -mat 1 -refs 4 -13 0 0 -146 0 0 -468 0 0 -139 0 0 -SURF 0x30 -mat 1 -refs 4 -468 0 0 -149 0 0 -20 0 0 -150 0 0 -SURF 0x30 -mat 1 -refs 4 -139 0 0 -468 0 0 -150 0 0 -11 0 0 -SURF 0x30 -mat 1 -refs 4 -140 0 0 -12 0 0 -147 0 0 -469 0 0 -SURF 0x30 -mat 1 -refs 4 -14 0 0 -140 0 0 -469 0 0 -144 0 0 -SURF 0x30 -mat 1 -refs 4 -469 0 0 -147 0 0 -19 0 0 -148 0 0 -SURF 0x30 -mat 1 -refs 4 -144 0 0 -469 0 0 -148 0 0 -17 0 0 -SURF 0x30 -mat 1 -refs 4 -143 0 0 -16 0 0 -145 0 0 -470 0 0 -SURF 0x30 -mat 1 -refs 4 -15 0 0 -143 0 0 -470 0 0 -142 0 0 -SURF 0x30 -mat 1 -refs 4 -470 0 0 -145 0 0 -18 0 0 -146 0 0 -SURF 0x30 -mat 1 -refs 4 -142 0 0 -470 0 0 -146 0 0 -13 0 0 -SURF 0x30 -mat 1 -refs 4 -138 0 0 -12 0 0 -140 0 0 -471 0 0 -SURF 0x30 -mat 1 -refs 4 -13 0 0 -138 0 0 -471 0 0 -142 0 0 -SURF 0x30 -mat 1 -refs 4 -471 0 0 -140 0 0 -14 0 0 -141 0 0 -SURF 0x30 -mat 1 -refs 4 -142 0 0 -471 0 0 -141 0 0 -15 0 0 -SURF 0x30 -mat 1 -refs 4 -137 0 0 -12 0 0 -138 0 0 -472 0 0 -SURF 0x30 -mat 1 -refs 4 -10 0 0 -137 0 0 -472 0 0 -135 0 0 -SURF 0x30 -mat 1 -refs 4 -472 0 0 -138 0 0 -13 0 0 -139 0 0 -SURF 0x30 -mat 1 -refs 4 -135 0 0 -472 0 0 -139 0 0 -11 0 0 -SURF 0x30 -mat 1 -refs 4 -132 0 0 -8 0 0 -134 0 0 -473 0 0 -SURF 0x30 -mat 1 -refs 4 -9 0 0 -132 0 0 -473 0 0 -136 0 0 -SURF 0x30 -mat 1 -refs 4 -473 0 0 -134 0 0 -10 0 0 -135 0 0 -SURF 0x30 -mat 1 -refs 4 -136 0 0 -473 0 0 -135 0 0 -11 0 0 -SURF 0x30 -mat 1 -refs 4 -129 0 0 -6 0 0 -131 0 0 -474 0 0 -SURF 0x30 -mat 1 -refs 4 -7 0 0 -129 0 0 -474 0 0 -133 0 0 -SURF 0x30 -mat 1 -refs 4 -474 0 0 -131 0 0 -8 0 0 -132 0 0 -SURF 0x30 -mat 1 -refs 4 -133 0 0 -474 0 0 -132 0 0 -9 0 0 -SURF 0x30 -mat 1 -refs 4 -128 0 0 -6 0 0 -129 0 0 -475 0 0 -SURF 0x30 -mat 1 -refs 4 -5 0 0 -128 0 0 -475 0 0 -126 0 0 -SURF 0x30 -mat 1 -refs 4 -475 0 0 -129 0 0 -7 0 0 -130 0 0 -SURF 0x30 -mat 1 -refs 4 -126 0 0 -475 0 0 -130 0 0 -4 0 0 -SURF 0x30 -mat 1 -refs 4 -122 0 0 -1 0 0 -125 0 0 -476 0 0 -SURF 0x30 -mat 1 -refs 4 -0 0 0 -122 0 0 -476 0 0 -127 0 0 -SURF 0x30 -mat 1 -refs 4 -476 0 0 -125 0 0 -5 0 0 -126 0 0 -SURF 0x30 -mat 1 -refs 4 -127 0 0 -476 0 0 -126 0 0 -4 0 0 -SURF 0x30 -mat 1 -refs 4 -123 0 0 -3 0 0 -124 0 0 -477 0 0 -SURF 0x30 -mat 1 -refs 4 -0 0 0 -123 0 0 -477 0 0 -122 0 0 -SURF 0x30 -mat 1 -refs 4 -477 0 0 -124 0 0 -2 0 0 -121 0 0 -SURF 0x30 -mat 1 -refs 4 -122 0 0 -477 0 0 -121 0 0 -1 0 0 -kids 0 -OBJECT poly -name "LeftWing" -data 4 -Wing -crease 30.000000 -numvert 766 -0.149492 0.04245 0.00106 -0.148054 0.019982 0.001061 -0.122396 0.046023 0.001059 -0.120955 0.020507 0.00106 -0.09791 0.048011 0.001059 -0.095931 0.022447 0.00106 -0.076772 0.048084 0.001059 -0.075273 0.025574 0.00106 -0.061423 0.046093 0.001059 -0.060659 0.028058 0.001059 -0.051559 0.03049 0.001059 -0.052212 0.043409 0.001059 -0.045015 0.0331 0.001058 -0.045765 0.040953 0.001059 -0.041737 0.036405 0.001373 -0.04272 0.039428 0.0014 -0.180991 0.036048 0.00106 -0.179832 0.019132 0.001061 -0.202989 0.032027 0.001061 -0.202009 0.01858 0.001061 -0.218596 0.017185 0.001062 -0.219461 0.028523 0.001061 -0.235774 0.015131 0.001405 -0.236322 0.024438 0.001405 -0.221091 0.028594 0.044868 -0.220212 0.017089 0.04488 -0.203193 0.018093 0.044874 -0.204245 0.032536 0.044858 -0.180726 0.018589 0.044866 -0.181971 0.036798 0.044846 -0.044015 0.039418 0.0448 -0.043135 0.036423 0.044802 -0.047196 0.041319 0.044799 -0.046388 0.032922 0.044808 -0.05362 0.043913 0.044798 -0.052909 0.030101 0.044813 -0.062199 0.02748 0.044819 -0.063053 0.046719 0.044798 -0.076442 0.024881 0.044826 -0.078439 0.048783 0.0448 -0.097159 0.021764 0.052803 -0.099494 0.048819 0.044807 -0.1224 0.01975 0.044846 -0.123973 0.046845 0.044817 -0.149712 0.019224 0.044855 -0.151232 0.043089 0.044829 -0.236707 0.018207 0.044884 -0.236969 0.021872 0.04488 -0.232841 0.02249 0.43679 -0.232634 0.019749 0.436795 -0.21866 0.028941 0.436777 -0.217873 0.01865 0.436791 -0.202604 0.01956 0.436785 -0.203547 0.03251 0.436767 -0.182454 0.020007 0.436778 -0.18357 0.036336 0.436756 -0.059908 0.038678 0.436714 -0.059123 0.035994 0.436717 -0.062762 0.040386 0.436712 -0.062037 0.032858 0.436723 -0.068359 0.042645 0.436711 -0.067718 0.030398 0.436727 -0.076012 0.027949 0.42841 -0.076749 0.045153 0.436711 -0.089634 0.025547 0.436741 -0.09039 0.047019 0.436712 -0.107629 0.022868 0.441023 -0.109459 0.047082 0.440986 -0.130182 0.021051 0.436761 -0.131594 0.045335 0.436727 -0.154674 0.020575 0.436769 -0.156036 0.041966 0.436739 -0.16115 0.041378 0.535687 -0.159933 0.022212 0.535972 -0.139348 0.044355 0.535661 -0.138076 0.022667 0.535972 -0.119792 0.045898 0.535655 -0.118159 0.024237 0.535955 -0.103623 0.04583 0.53567 -0.102354 0.026639 0.535928 -0.091249 0.044225 0.535701 -0.090545 0.028795 0.535902 -0.082993 0.0309 0.535875 -0.083569 0.042006 0.535736 -0.077269 0.033092 0.53377 -0.077916 0.039961 0.53368 -0.075033 0.035979 0.535814 -0.075734 0.038376 0.535779 -0.185689 0.036402 0.535739 -0.184686 0.021706 0.535966 -0.204002 0.032965 0.537513 -0.203161 0.021402 0.537716 -0.216982 0.020471 0.53596 -0.217687 0.029692 0.535825 -0.230174 0.021419 0.535949 -0.23037 0.024099 0.535891 -0.179125 0.041748 0.598072 -0.17818 0.026962 0.60061 -0.161797 0.044177 0.597999 -0.160805 0.027358 0.600874 -0.146272 0.04546 0.598083 -0.145005 0.028579 0.600959 -0.132936 0.045488 0.598332 -0.131941 0.030519 0.600867 -0.123135 0.044265 0.59872 -0.122584 0.032221 0.600749 -0.116597 0.033873 0.600576 -0.117046 0.04255 0.59912 -0.111528 0.035507 0.598794 -0.112038 0.040891 0.597911 -0.110267 0.037855 0.600018 -0.11082 0.039722 0.599692 -0.1983 0.037877 0.598358 -0.19752 0.026527 0.600308 -0.211982 0.035252 0.598525 -0.21132 0.026188 0.600071 -0.222454 0.025747 0.601198 -0.223003 0.032915 0.599949 -0.23286 0.026308 0.599671 -0.232994 0.028242 0.599151 -0.239677 0.037211 0.643062 -0.239587 0.035839 0.643313 -0.232693 0.04087 0.644521 -0.2323 0.035711 0.645394 -0.224582 0.03608 0.645873 -0.225057 0.042603 0.644782 -0.214437 0.036602 0.647537 -0.215 0.044828 0.646167 -0.152369 0.04768 0.656226 -0.15198 0.046333 0.656497 -0.152861 0.04833 0.654624 -0.152515 0.044421 0.655279 -0.156853 0.049647 0.655201 -0.156583 0.043299 0.656215 -0.160829 0.042025 0.655714 -0.161233 0.050787 0.654304 -0.167544 0.040627 0.654816 -0.168267 0.051501 0.653028 -0.176902 0.038998 0.653503 -0.177814 0.051244 0.651468 -0.188206 0.037845 0.651782 -0.188924 0.050039 0.649784 -0.200646 0.037254 0.649783 -0.201329 0.047965 0.648016 -0.223019 0.055669 0.673444 -0.222612 0.04932 0.675619 -0.215422 0.057545 0.675278 -0.214978 0.050328 0.677732 -0.208633 0.058814 0.677047 -0.20811 0.051555 0.679528 -0.202845 0.059434 0.678697 -0.202415 0.052933 0.680901 -0.198524 0.059391 0.680083 -0.198259 0.054118 0.681842 -0.19457 0.054851 0.681848 -0.19573 0.058962 0.681108 -0.193619 0.05614 0.682657 -0.193916 0.058451 0.681845 -0.192743 0.057152 0.682616 -0.191975 0.05772 0.681768 -0.231 0.053292 0.671644 -0.230658 0.048303 0.673371 -0.237443 0.051615 0.670641 -0.236926 0.047466 0.671605 -0.241773 0.047058 0.670672 -0.241855 0.049706 0.669255 -0.245666 0.046727 0.669006 -0.245726 0.047591 0.668703 -0.249727 0.057951 0.682265 -0.249888 0.057253 0.682139 -0.248174 0.058984 0.682626 -0.248081 0.057738 0.683237 -0.246166 0.058242 0.684087 -0.246138 0.059964 0.683293 -0.243538 0.058899 0.685232 -0.243684 0.06103 0.684183 -0.226883 0.06473 0.690998 -0.226742 0.064468 0.691332 -0.228052 0.065031 0.690839 -0.227904 0.06404 0.691353 -0.228833 0.065161 0.690361 -0.22801 0.063346 0.691016 -0.229924 0.062921 0.69078 -0.230042 0.0652 0.689691 -0.231698 0.062209 0.690145 -0.231882 0.064999 0.68879 -0.234107 0.061354 0.689231 -0.234326 0.064449 0.687717 -0.237003 0.060504 0.688049 -0.237193 0.063572 0.686557 -0.240065 0.059469 0.686469 -0.240245 0.062271 0.685107 -0.241468 0.063423 0.688864 -0.121633 0.033264 3.2e-05 -0.14872 0.031219 3.2e-05 -0.110063 0.047074 0.001059 -0.09688 0.035228 3.2e-05 -0.108345 0.021431 0.00106 -0.087199 0.048113 0.001059 -0.075982 0.03683 3.2e-05 -0.085437 0.024 0.00106 -0.068908 0.047133 0.001059 -0.061003 0.037074 3.2e-05 -0.067783 0.026827 0.00106 -0.056678 0.044758 0.001059 -0.051856 0.036947 3.2e-05 -0.055984 0.029272 0.001059 -0.048894 0.042162 0.001059 -0.04536 0.037023 3.1e-05 -0.048199 0.031779 0.001059 -0.044127 0.040156 0.001058 -0.042185 0.037926 0.001044 -0.043245 0.034798 0.001044 -0.135826 0.044311 0.00106 -0.134392 0.020225 0.001061 -0.16402 0.019558 0.001061 -0.180383 0.027586 3.2e-05 -0.165322 0.039256 0.00106 -0.19117 0.018866 0.001061 -0.202458 0.025304 3.2e-05 -0.192236 0.033986 0.001061 -0.210365 0.017914 0.001062 -0.21897 0.022856 3.2e-05 -0.21129 0.030275 0.001061 -0.227527 0.016051 0.001062 -0.236226 0.019748 0.001062 -0.228237 0.026475 0.001061 -0.220332 0.028742 0.016497 -0.219429 0.016923 0.016503 -0.21276 0.030609 0.044863 -0.203646 0.032505 0.016491 -0.202596 0.01809 0.0165 -0.211787 0.017564 0.044877 -0.193334 0.034626 0.044852 -0.181476 0.036711 0.016485 -0.180233 0.018557 0.016496 -0.192188 0.018348 0.04487 -0.166681 0.039951 0.044838 -0.150309 0.043164 0.016477 -0.148779 0.019205 0.01649 -0.165296 0.018906 0.044861 -0.121529 0.019681 0.016485 -0.135956 0.019467 0.044851 -0.137499 0.045037 0.044823 -0.123086 0.046886 0.01647 -0.04215 0.036423 0.016448 -0.044644 0.034669 0.044805 -0.045436 0.032882 0.016465 -0.043096 0.039442 0.016461 -0.043474 0.037947 0.044801 -0.046241 0.041282 0.016461 -0.045519 0.040375 0.044799 -0.049556 0.031497 0.04481 -0.051982 0.030077 0.016468 -0.052686 0.043896 0.01646 -0.050311 0.042601 0.044798 -0.057427 0.028788 0.044816 -0.06119 0.02746 0.016471 -0.062025 0.046731 0.01646 -0.058196 0.045324 0.044798 -0.069283 0.026223 0.052789 -0.075836 0.024802 0.016475 -0.077432 0.048838 0.016461 -0.070561 0.047795 0.044799 -0.086489 0.023313 0.044831 -0.096485 0.021618 0.01648 -0.098572 0.048871 0.016465 -0.088824 0.048865 0.044803 -0.109816 0.020673 0.044841 -0.111638 0.047891 0.044812 -0.237361 0.019949 0.044882 -0.234956 0.022106 0.239947 -0.225988 0.025703 0.436784 -0.234726 0.019012 0.23995 -0.233204 0.021032 0.436793 -0.225487 0.019143 0.436793 -0.211185 0.030771 0.436772 -0.210314 0.019081 0.436788 -0.19376 0.034387 0.436762 -0.192732 0.01979 0.436782 -0.169874 0.039158 0.436747 -0.168632 0.020291 0.436774 -0.142339 0.020795 0.436765 -0.143722 0.043713 0.436733 -0.060476 0.034423 0.43672 -0.059426 0.03736 0.436715 -0.061258 0.039538 0.436713 -0.065119 0.031644 0.440996 -0.065797 0.041463 0.440982 -0.071738 0.029218 0.43673 -0.072428 0.043906 0.436711 -0.082879 0.026761 0.436737 -0.083404 0.046126 0.436711 -0.098308 0.024123 0.428423 -0.099626 0.047119 0.436715 -0.118903 0.021877 0.436756 -0.120536 0.046273 0.436722 -0.135493 0.044805 0.491697 -0.129493 0.045174 0.535658 -0.114519 0.046462 0.493928 -0.112784 0.023514 0.494061 -0.128035 0.023418 0.535964 -0.134155 0.021788 0.491826 -0.111462 0.045946 0.533592 -0.109983 0.025344 0.533855 -0.097288 0.045063 0.535685 -0.096306 0.027724 0.535915 -0.087296 0.043122 0.535718 -0.086668 0.029846 0.535889 -0.081594 0.040955 0.53749 -0.069991 0.040186 0.489474 -0.069305 0.032904 0.489512 -0.08099 0.032071 0.537624 -0.076941 0.039144 0.535768 -0.067523 0.038497 0.491726 -0.075303 0.037199 0.535796 -0.066779 0.035952 0.49174 -0.076242 0.034576 0.535834 -0.15867 0.041611 0.491717 -0.150166 0.042922 0.535673 -0.148925 0.022423 0.535972 -0.157378 0.021337 0.491831 -0.172371 0.021959 0.535969 -0.183717 0.020798 0.491836 -0.184775 0.036275 0.491751 -0.173483 0.038896 0.535713 -0.193968 0.021509 0.535962 -0.202823 0.020373 0.49184 -0.203717 0.032648 0.491772 -0.194891 0.034638 0.535761 -0.210222 0.02086 0.535957 -0.217302 0.019508 0.491848 -0.218049 0.029277 0.491791 -0.211002 0.031312 0.535807 -0.223787 0.020889 0.535955 -0.231295 0.020531 0.491847 -0.230691 0.022683 0.53592 -0.231497 0.023242 0.491824 -0.224241 0.026889 0.535857 -0.153974 0.044855 0.598036 -0.15284 0.027943 0.600922 -0.139514 0.045514 0.598202 -0.13837 0.029542 0.600916 -0.127919 0.044904 0.598523 -0.127149 0.031376 0.600809 -0.120002 0.043413 0.598921 -0.11951 0.033046 0.600664 -0.115871 0.041872 0.600757 -0.115399 0.034945 0.601929 -0.111774 0.040318 0.599571 -0.11048 0.038805 0.599853 -0.111223 0.036759 0.600184 -0.170395 0.043006 0.598029 -0.169429 0.027148 0.600745 -0.187898 0.026744 0.600459 -0.188762 0.039817 0.598214 -0.204522 0.026202 0.598684 -0.205245 0.03641 0.596972 -0.216806 0.025847 0.600021 -0.217418 0.034029 0.598618 -0.227808 0.025873 0.599809 -0.233257 0.027216 0.599416 -0.228152 0.030455 0.598915 -0.236282 0.032627 0.621694 -0.236246 0.038894 0.643382 -0.227805 0.036799 0.622965 -0.236171 0.030978 0.622086 -0.239867 0.036477 0.643155 -0.227334 0.030631 0.624029 -0.236002 0.035599 0.643943 -0.228639 0.041411 0.643245 -0.228197 0.035478 0.644236 -0.22013 0.043695 0.64546 -0.219611 0.036341 0.646688 -0.2082 0.046399 0.647085 -0.207576 0.036927 0.648654 -0.194381 0.037542 0.650791 -0.19508 0.049034 0.648903 -0.131042 0.041949 0.62885 -0.152661 0.045523 0.656507 -0.13188 0.039764 0.627611 -0.131514 0.043556 0.628547 -0.152129 0.04702 0.656368 -0.132319 0.044415 0.626803 -0.154048 0.04833 0.656894 -0.155039 0.043973 0.656369 -0.15534 0.049092 0.655536 -0.159542 0.042971 0.656812 -0.15898 0.050222 0.654763 -0.164106 0.041332 0.655278 -0.164667 0.051166 0.653677 -0.172149 0.039809 0.654173 -0.172976 0.051403 0.652255 -0.182507 0.038404 0.652653 -0.183326 0.050669 0.65063 -0.211999 0.058199 0.676165 -0.211514 0.050935 0.678642 -0.2057 0.059145 0.677878 -0.205219 0.052245 0.680228 -0.200637 0.059429 0.6794 -0.20029 0.053532 0.681385 -0.197088 0.059184 0.680606 -0.175147 0.048936 0.669393 -0.197681 0.054876 0.682453 -0.194795 0.058707 0.681485 -0.173637 0.050444 0.670334 -0.19449 0.055651 0.682536 -0.194309 0.058398 0.682409 -0.17177 0.052591 0.669381 -0.192807 0.057553 0.68247 -0.172465 0.05176 0.670318 -0.19315 0.056649 0.682646 -0.219199 0.056626 0.674362 -0.218773 0.04982 0.676683 -0.226655 0.048808 0.674489 -0.22703 0.054481 0.672537 -0.233845 0.047879 0.672473 -0.234159 0.05233 0.67093 -0.239112 0.04682 0.670359 -0.237111 0.041377 0.658596 -0.237417 0.045403 0.657651 -0.23943 0.050293 0.669156 -0.243724 0.046723 0.669612 -0.242666 0.041262 0.656632 -0.245821 0.047125 0.668826 -0.24274 0.042379 0.656358 -0.243866 0.048635 0.668958 -0.247946 0.052848 0.675779 -0.24888 0.058614 0.682634 -0.245263 0.054418 0.676239 -0.247901 0.052215 0.676038 -0.249863 0.05764 0.682262 -0.245263 0.05263 0.677391 -0.249047 0.057541 0.68274 -0.247119 0.059603 0.683142 -0.24208 0.05601 0.677416 -0.247023 0.05792 0.683571 -0.244814 0.060424 0.683643 -0.244852 0.058729 0.684812 -0.241973 0.061718 0.684731 -0.24181 0.059256 0.685939 -0.238628 0.060034 0.68731 -0.238812 0.062958 0.685885 -0.210564 0.061022 0.687421 -0.227493 0.064302 0.691391 -0.21118 0.060283 0.687449 -0.209834 0.061417 0.686943 -0.227351 0.064692 0.691294 -0.228299 0.064956 0.691009 -0.228731 0.063829 0.691274 -0.211688 0.059292 0.686998 -0.228875 0.065103 0.690631 -0.229733 0.063276 0.69099 -0.229833 0.065188 0.690072 -0.231159 0.062649 0.690499 -0.231304 0.065114 0.689306 -0.233187 0.061881 0.689745 -0.233384 0.06475 0.68834 -0.235767 0.061043 0.688722 -0.235967 0.064055 0.687247 -0.246331 0.060677 0.685522 -0.245599 0.061176 0.685678 -0.245479 0.060556 0.686049 -0.244505 0.061717 0.686044 -0.244439 0.060806 0.686503 -0.243114 0.062327 0.686564 -0.243036 0.061183 0.687138 -0.234684 0.064402 0.690341 -0.234847 0.063969 0.690448 -0.234826 0.064503 0.690194 -0.235181 0.063703 0.690364 -0.235229 0.064569 0.689936 -0.235795 0.063389 0.690161 -0.235857 0.064587 0.689573 -0.23672 0.063002 0.689819 -0.236816 0.064479 0.689085 -0.239502 0.062086 0.688699 -0.237984 0.062535 0.689324 -0.238101 0.064185 0.688499 -0.239604 0.063721 0.687887 -0.231535 0.026053 0.568239 -0.23137 0.023737 0.568534 -0.220161 0.031074 0.567954 -0.219533 0.022865 0.568651 -0.207965 0.034018 0.569362 -0.207215 0.023731 0.570275 -0.092233 0.036782 0.568424 -0.092861 0.038917 0.568242 -0.093822 0.034159 0.567014 -0.094402 0.040309 0.56654 -0.104434 0.047981 0.239875 -0.102292 0.022298 0.250252 -0.084441 0.047946 0.239868 -0.069828 0.045989 0.239865 -0.069008 0.027634 0.229538 -0.060862 0.043325 0.239866 -0.060187 0.030206 0.23988 -0.054762 0.040863 0.239866 -0.051738 0.039053 0.239867 -0.053994 0.032887 0.239875 -0.050907 0.036209 0.23987 -0.127683 0.046107 0.239884 -0.126187 0.020378 0.239913 -0.152134 0.019874 0.239922 -0.153577 0.042537 0.239897 -0.181564 0.019273 0.239933 -0.182747 0.036572 0.239913 -0.202911 0.018799 0.23994 -0.20391 0.032519 0.239925 -0.219089 0.017845 0.239946 -0.219923 0.028753 0.239934 -0.229296 0.025226 0.044874 -0.22872 0.017577 0.044882 -0.236806 0.023193 0.016503 -0.236394 0.01656 0.016505 -0.224982 0.061165 0.681905 -0.224651 0.056017 0.683925 -0.220415 0.062071 0.683342 -0.220062 0.057083 0.685291 -0.216657 0.062475 0.68463 -0.21639 0.058143 0.686298 -0.213957 0.062429 0.685666 -0.212912 0.058818 0.686748 -0.212225 0.062153 0.68642 -0.210249 0.06164 0.686729 -0.230156 0.059797 0.680391 -0.229857 0.055068 0.682262 -0.235506 0.054139 0.680417 -0.235765 0.057999 0.678863 -0.240333 0.053302 0.678783 -0.240764 0.056567 0.677874 -0.244232 0.052881 0.677832 -0.235073 0.046247 0.658123 -0.234732 0.041698 0.659247 -0.227911 0.047957 0.658721 -0.227501 0.042177 0.660133 -0.218822 0.050275 0.660349 -0.218334 0.042947 0.662129 -0.207548 0.043784 0.664357 -0.208114 0.052806 0.662235 -0.172433 0.05298 0.669203 -0.175382 0.054032 0.669276 -0.177098 0.048326 0.669141 -0.178415 0.054861 0.668444 -0.182772 0.047414 0.669037 -0.183259 0.055449 0.667268 -0.189473 0.045991 0.66788 -0.190149 0.055359 0.665758 -0.197942 0.044701 0.666297 -0.198564 0.054458 0.66405 -0.169411 0.047624 0.625277 -0.168455 0.033035 0.627772 -0.156892 0.048371 0.626103 -0.155889 0.034481 0.628479 -0.146739 0.047999 0.626874 -0.146047 0.036163 0.628886 -0.139723 0.046787 0.627525 -0.139295 0.037657 0.629084 -0.134205 0.045163 0.626632 -0.133796 0.038931 0.627716 -0.183592 0.045841 0.624472 -0.182759 0.032267 0.62677 -0.198765 0.031765 0.625611 -0.199499 0.042847 0.623736 -0.212885 0.031269 0.624364 -0.213497 0.039903 0.622897 -0.223592 0.030925 0.624593 -0.224106 0.037791 0.623419 -0.201223 0.035307 0.569253 -0.200415 0.023899 0.570353 -0.182287 0.038943 0.567492 -0.181311 0.024188 0.568887 -0.1602 0.024625 0.568997 -0.161302 0.042654 0.567399 -0.09626 0.03309 0.567032 -0.096803 0.041281 0.566523 -0.102995 0.031212 0.568757 -0.103561 0.043247 0.567913 -0.111833 0.029315 0.568864 -0.112737 0.044943 0.567701 -0.124753 0.027217 0.568949 -0.126074 0.04559 0.567507 -0.141309 0.025455 0.56902 -0.142585 0.044795 0.567403 -0.072033 0.031703 0.489515 -0.072678 0.041277 0.489473 -0.079248 0.029407 0.491774 -0.079918 0.043575 0.491706 -0.089551 0.027156 0.491788 -0.090606 0.045624 0.491694 -0.104822 0.024702 0.49405 -0.106388 0.046471 0.493929 -0.093417 0.023624 0.250247 -0.075892 0.026368 0.229541 -0.098277 0.046092 0.491691 -0.096964 0.025917 0.491795 -0.085123 0.044622 0.4917 -0.084269 0.028285 0.491781 -0.07641 0.042423 0.491712 -0.075762 0.030555 0.491767 -0.218772 0.038732 0.622595 -0.218208 0.030974 0.623918 -0.206587 0.041363 0.623314 -0.205914 0.031519 0.624983 -0.191548 0.044363 0.624104 -0.190764 0.032012 0.626194 -0.175552 0.032636 0.627278 -0.176447 0.046768 0.624873 -0.137023 0.038406 0.629117 -0.137435 0.046077 0.627798 -0.142586 0.036913 0.62899 -0.143141 0.047409 0.627203 -0.150876 0.035322 0.62869 -0.151729 0.048216 0.626491 -0.162103 0.033744 0.628134 -0.163089 0.048031 0.625691 -0.203302 0.053658 0.663146 -0.194315 0.054932 0.664909 -0.193662 0.045338 0.667101 -0.202708 0.044236 0.665337 -0.186648 0.055427 0.666521 -0.186063 0.046704 0.668472 -0.180776 0.055169 0.667866 -0.180387 0.048022 0.66942 -0.176853 0.054449 0.668869 -0.174393 0.053636 0.669566 -0.213475 0.051551 0.66129 -0.212948 0.043363 0.663244 -0.222979 0.042561 0.661119 -0.223427 0.049106 0.659525 -0.231058 0.041794 0.659362 -0.231436 0.04698 0.658097 -0.242236 0.052949 0.678137 -0.238187 0.057165 0.678199 -0.23795 0.053717 0.679591 -0.232966 0.058903 0.679624 -0.232687 0.054602 0.681339 -0.227237 0.05554 0.683101 -0.227552 0.060495 0.681149 -0.211664 0.061987 0.686688 -0.213066 0.062296 0.686051 -0.215057 0.058588 0.686637 -0.215275 0.062463 0.685156 -0.218195 0.057616 0.685805 -0.218507 0.062288 0.683993 -0.222333 0.056548 0.684618 -0.222677 0.061633 0.682627 -0.241053 0.062839 0.686512 -0.247724 0.059315 0.6844 -0.240926 0.060858 0.687498 -0.231778 0.064451 0.69098 -0.191749 0.037083 0.567591 -0.190854 0.023982 0.568824 -0.170755 0.0244 0.568944 -0.171794 0.040824 0.567442 -0.100013 0.032176 0.568693 -0.100559 0.04228 0.568008 -0.107302 0.030266 0.568812 -0.108031 0.044115 0.567807 -0.118171 0.028264 0.568907 -0.11929 0.045306 0.567602 -0.150681 0.025019 0.569011 -0.132938 0.026316 0.568986 -0.134246 0.045236 0.567452 -0.151872 0.043771 0.567398 -0.084654 0.02499 0.239894 -0.228165 0.016614 0.016504 -0.237141 0.01978 0.016504 -0.228833 0.026018 0.0165 -0.211795 0.059911 0.687346 -0.210606 0.061305 0.687302 -0.21085 0.060655 0.687442 -0.243587 0.055098 0.676647 -0.246557 0.052259 0.676533 -0.248011 0.052505 0.675885 -0.246658 0.053622 0.675992 -0.2401 0.043743 0.656657 -0.242883 0.041779 0.656464 -0.239907 0.041142 0.657262 -0.173009 0.051103 0.670336 -0.172571 0.052303 0.67018 -0.174788 0.049855 0.6702 -0.132333 0.044064 0.628395 -0.131223 0.042768 0.628701 -0.131861 0.040996 0.62894 -0.231847 0.030639 0.622472 -0.236509 0.031749 0.621876 -0.232141 0.034576 0.621733 -0.226038 0.028556 0.568094 -0.231827 0.024828 0.568389 -0.225638 0.023253 0.568597 -0.214166 0.032524 0.567881 -0.213471 0.023214 0.568663 -0.093317 0.03553 0.56852 -0.092475 0.037868 0.568332 -0.093943 0.039601 0.568177 -0.224998 0.02625 0.491807 -0.231839 0.021805 0.491836 -0.22452 0.019963 0.491848 -0.210961 0.031004 0.491782 -0.210134 0.019918 0.491844 -0.194438 0.034427 0.491762 -0.193463 0.020592 0.491838 -0.171789 0.038949 0.491734 -0.170613 0.021067 0.491834 -0.145682 0.021545 0.491829 -0.146994 0.043267 0.491707 -0.068061 0.034464 0.491749 -0.067065 0.037247 0.491733 -0.068803 0.039312 0.491722 -0.123461 0.022572 0.491821 -0.125008 0.045694 0.491691 -0.115968 0.0471 0.239879 -0.114238 0.021254 0.239908 -0.094302 0.048024 0.239871 -0.07696 0.047009 0.239867 -0.065212 0.044665 0.239865 -0.064481 0.028959 0.239883 -0.05772 0.04208 0.239866 -0.057002 0.031533 0.239878 -0.053169 0.039964 0.239867 -0.051227 0.037657 0.239869 -0.052339 0.034545 0.239873 -0.140532 0.044388 0.23989 -0.139066 0.020107 0.239918 -0.166922 0.019574 0.239927 -0.168237 0.039562 0.239905 -0.192454 0.019043 0.239936 -0.193542 0.034507 0.239919 -0.21108 0.018297 0.239943 -0.212003 0.030681 0.239929 -0.227154 0.018365 0.239948 -0.235336 0.02047 0.239949 -0.22769 0.02542 0.239941 -0.110736 0.047936 0.016467 -0.108906 0.020605 0.016483 -0.087859 0.048919 0.016463 -0.085996 0.023199 0.016478 -0.069541 0.047829 0.016461 -0.068332 0.026141 0.016473 -0.057216 0.045321 0.01646 -0.05646 0.028766 0.016469 -0.049368 0.042572 0.01646 -0.048618 0.031464 0.016467 -0.044584 0.040369 0.016461 -0.042523 0.037961 0.016454 -0.043674 0.034648 0.016456 -0.136587 0.045097 0.016473 -0.135048 0.019423 0.016488 -0.164583 0.018881 0.016493 -0.165972 0.039945 0.016481 -0.191653 0.018332 0.016498 -0.192797 0.034562 0.016488 -0.211086 0.017508 0.016501 -0.212067 0.030646 0.016494 -0.227841 0.021259 3.2e-05 -0.210778 0.024096 3.2e-05 -0.191668 0.026425 3.2e-05 -0.164631 0.029406 3.2e-05 -0.135062 0.032269 3.2e-05 -0.043656 0.037475 2.4e-05 -0.048517 0.036968 3.2e-05 -0.056297 0.037013 3.2e-05 -0.068306 0.03698 3.2e-05 -0.086277 0.036057 3.2e-05 -0.109163 0.034251 3.2e-05 -numsurf 840 -SURF 0x10 -mat 1 -refs 3 -459 0.5 0.0 -187 0.0 0.0 -478 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -478 0.5 0.5 -479 1.0 0.5 -459 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -189 1.0 0.0 -459 0.5 0.0 -479 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -479 1.0 0.5 -478 0.5 0.5 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -458 0.499999433756 -2.17116593149e-07 -188 0.0 0.0 -476 0.500001192093 0.499999463558 -SURF 0x10 -mat 1 -refs 3 -476 0.500001192093 0.499999463558 -477 0.999998211861 0.500000298023 -458 0.499999433756 -2.17116593149e-07 -SURF 0x10 -mat 1 -refs 3 -186 1.0 0.0 -458 0.499999433756 -2.17116593149e-07 -477 0.999998211861 0.500000298023 -SURF 0x10 -mat 1 -refs 3 -477 0.999998211861 0.500000298023 -476 0.500001192093 0.499999463558 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -457 0.5 0.0 -185 0.0 0.0 -475 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -475 0.5 0.5 -478 1.0 0.5 -457 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -187 1.0 0.0 -457 0.5 0.0 -478 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -478 1.0 0.5 -475 0.5 0.5 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -456 0.499998480082 3.86105426742e-07 -186 0.0 0.0 -477 0.499998450279 0.500000357628 -SURF 0x10 -mat 1 -refs 3 -477 0.499998450279 0.500000357628 -474 1.0 0.5 -456 0.499998480082 3.86105426742e-07 -SURF 0x10 -mat 1 -refs 3 -184 1.0 0.0 -456 0.499998480082 3.86105426742e-07 -474 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -474 1.0 0.5 -477 0.499998450279 0.500000357628 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -455 0.499966084957 6.13281372353e-06 -183 0.0 0.0 -473 0.499966084957 0.500006139278 -SURF 0x10 -mat 1 -refs 3 -473 0.499966084957 0.500006139278 -475 1.0 0.5 -455 0.499966084957 6.13281372353e-06 -SURF 0x10 -mat 1 -refs 3 -185 1.0 0.0 -455 0.499966084957 6.13281372353e-06 -475 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -475 1.0 0.5 -473 0.499966084957 0.500006139278 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -454 0.499998480082 4.17143610321e-07 -184 0.0 0.0 -474 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -474 0.5 0.5 -472 0.999998450279 0.500000417233 -454 0.499998480082 4.17143610321e-07 -SURF 0x10 -mat 1 -refs 3 -182 1.0 0.0 -454 0.499998480082 4.17143610321e-07 -472 0.999998450279 0.500000417233 -SURF 0x10 -mat 1 -refs 3 -472 0.999998450279 0.500000417233 -474 0.5 0.5 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -453 0.499945670366 6.00236899118e-06 -180 0.0 0.0 -471 0.499998778105 0.50000077486 -SURF 0x10 -mat 1 -refs 3 -471 0.499998778105 0.50000077486 -473 0.999946951866 0.500005245209 -453 0.499945670366 6.00236899118e-06 -SURF 0x10 -mat 1 -refs 3 -183 1.0 0.0 -453 0.499945670366 6.00236899118e-06 -473 0.999946951866 0.500005245209 -SURF 0x10 -mat 1 -refs 3 -473 0.999946951866 0.500005245209 -471 0.499998778105 0.50000077486 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -452 0.5 0.0 -182 0.0 0.0 -472 0.499998569489 0.500000476837 -SURF 0x10 -mat 1 -refs 3 -472 0.499998569489 0.500000476837 -470 1.00000143051 0.499999552965 -452 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -181 1.0 0.0 -452 0.5 0.0 -470 1.00000143051 0.499999552965 -SURF 0x10 -mat 1 -refs 3 -470 1.00000143051 0.499999552965 -472 0.499998569489 0.500000476837 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -451 0.499917715788 5.39123948329e-06 -178 0.0 0.0 -469 0.499920427799 0.500004649162 -SURF 0x10 -mat 1 -refs 3 -469 0.499920427799 0.500004649162 -471 0.999997258186 0.500000715256 -451 0.499917715788 5.39123948329e-06 -SURF 0x10 -mat 1 -refs 3 -180 1.0 0.0 -451 0.499917715788 5.39123948329e-06 -471 0.999997258186 0.500000715256 -SURF 0x10 -mat 1 -refs 3 -471 0.999997258186 0.500000715256 -469 0.499920427799 0.500004649162 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -449 0.5 0.0 -181 0.0 0.0 -470 0.500001132488 0.499999523163 -SURF 0x10 -mat 1 -refs 3 -470 0.500001132488 0.499999523163 -468 1.00000119209 0.499999523163 -449 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -179 1.0 0.0 -449 0.5 0.0 -468 1.00000119209 0.499999523163 -SURF 0x10 -mat 1 -refs 3 -468 1.00000119209 0.499999523163 -470 0.500001132488 0.499999523163 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -448 0.499866068363 4.35418314737e-06 -176 0.0 0.0 -467 0.499994724989 0.500000715256 -SURF 0x10 -mat 1 -refs 3 -467 0.499994724989 0.500000715256 -469 0.999871373177 0.500003635883 -448 0.499866068363 4.35418314737e-06 -SURF 0x10 -mat 1 -refs 3 -178 1.0 0.0 -448 0.499866068363 4.35418314737e-06 -469 0.999871373177 0.500003635883 -SURF 0x10 -mat 1 -refs 3 -469 0.999871373177 0.500003635883 -467 0.499994724989 0.500000715256 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -438 0.499996870756 4.74882199342e-07 -172 0.0 0.0 -464 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -464 0.5 0.5 -466 1.00000309944 0.499999523163 -438 0.499996870756 4.74882199342e-07 -SURF 0x10 -mat 1 -refs 3 -174 1.0 0.0 -438 0.499996870756 4.74882199342e-07 -466 1.00000309944 0.499999523163 -SURF 0x10 -mat 1 -refs 3 -466 1.00000309944 0.499999523163 -464 0.5 0.5 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -437 0.499995917082 -7.01680562543e-07 -175 0.0 0.0 -465 0.499986708164 0.499992281199 -SURF 0x10 -mat 1 -refs 3 -465 0.499986708164 0.499992281199 -463 0.99999076128 0.499992966652 -437 0.499995917082 -7.01680562543e-07 -SURF 0x10 -mat 1 -refs 3 -173 1.0 0.0 -437 0.499995917082 -7.01680562543e-07 -463 0.99999076128 0.499992966652 -SURF 0x10 -mat 1 -refs 3 -463 0.99999076128 0.499992966652 -465 0.499986708164 0.499992281199 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -436 0.500004768372 -5.00195994846e-07 -171 0.0 0.0 -462 0.499995231628 0.500000476837 -SURF 0x10 -mat 1 -refs 3 -462 0.499995231628 0.500000476837 -464 1.0 0.5 -436 0.500004768372 -5.00195994846e-07 -SURF 0x10 -mat 1 -refs 3 -172 1.0 0.0 -436 0.500004768372 -5.00195994846e-07 -464 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -464 1.0 0.5 -462 0.499995231628 0.500000476837 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -434 0.499994248152 -6.35181265807e-07 -173 0.0 0.0 -463 0.499981433153 0.499993115664 -SURF 0x10 -mat 1 -refs 3 -463 0.499981433153 0.499993115664 -461 0.999975681305 0.499992489815 -434 0.499994248152 -6.35181265807e-07 -SURF 0x10 -mat 1 -refs 3 -170 1.0 0.0 -434 0.499994248152 -6.35181265807e-07 -461 0.999975681305 0.499992489815 -SURF 0x10 -mat 1 -refs 3 -461 0.999975681305 0.499992489815 -463 0.499981433153 0.499993115664 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -428 0.5 0.0 -170 0.0 0.0 -461 0.499966591597 0.499993532896 -SURF 0x10 -mat 1 -refs 3 -461 0.499966591597 0.499993532896 -460 0.999966621399 0.499993532896 -428 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -168 1.0 0.0 -428 0.5 0.0 -460 0.999966621399 0.499993532896 -SURF 0x10 -mat 1 -refs 3 -460 0.999966621399 0.499993532896 -461 0.499966591597 0.499993532896 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -403 0.500000596046 4.33204156991e-08 -153 0.0 0.0 -522 0.500000536442 0.499999821186 -SURF 0x10 -mat 1 -refs 3 -522 0.500000536442 0.499999821186 -450 0.999998867512 0.500000119209 -403 0.500000596046 4.33204156991e-08 -SURF 0x10 -mat 1 -refs 3 -154 1.0 0.0 -403 0.500000596046 4.33204156991e-08 -450 0.999998867512 0.500000119209 -SURF 0x10 -mat 1 -refs 3 -450 0.999998867512 0.500000119209 -522 0.500000536442 0.499999821186 -181 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -407 0.499997168779 -1.4246332114e-07 -159 0.0 0.0 -446 0.499954491854 0.500000953674 -SURF 0x10 -mat 1 -refs 3 -446 0.499954491854 0.500000953674 -524 0.999957382679 0.500001132488 -407 0.499997168779 -1.4246332114e-07 -SURF 0x10 -mat 1 -refs 3 -157 1.0 0.0 -407 0.499997168779 -1.4246332114e-07 -524 0.999957382679 0.500001132488 -SURF 0x10 -mat 1 -refs 3 -524 0.999957382679 0.500001132488 -446 0.499954491854 0.500000953674 -176 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -435 0.500000178814 -2.25347866945e-06 -162 0.0 0.0 -530 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -530 0.5 0.5 -437 0.999999880791 0.500002264977 -435 0.500000178814 -2.25347866945e-06 -SURF 0x10 -mat 1 -refs 3 -173 1.0 0.0 -435 0.500000178814 -2.25347866945e-06 -437 0.999999880791 0.500002264977 -SURF 0x10 -mat 1 -refs 3 -437 0.999999880791 0.500002264977 -530 0.5 0.5 -175 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -531 0.499998301268 7.55132123231e-06 -164 0.0 0.0 -432 0.499998092651 0.500004351139 -SURF 0x10 -mat 1 -refs 3 -432 0.499998092651 0.500004351139 -436 0.999999761581 0.499996811152 -531 0.499998301268 7.55132123231e-06 -SURF 0x10 -mat 1 -refs 3 -172 1.0 0.0 -531 0.499998301268 7.55132123231e-06 -436 0.999999761581 0.499996811152 -SURF 0x10 -mat 1 -refs 3 -436 0.999999761581 0.499996811152 -432 0.499998092651 0.500004351139 -171 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -420 0.499998956919 -3.59487034984e-06 -122 0.0 0.0 -532 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -532 0.5 0.5 -421 0.999998807907 0.499999284744 -420 0.499998956919 -3.59487034984e-06 -SURF 0x10 -mat 1 -refs 3 -165 1.0 0.0 -420 0.499998956919 -3.59487034984e-06 -421 0.999998807907 0.499999284744 -SURF 0x10 -mat 1 -refs 3 -421 0.999998807907 0.499999284744 -532 0.5 0.5 -162 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -533 0.499999910593 -1.46663558098e-06 -123 0.0 0.0 -419 0.499998927116 0.500001013279 -SURF 0x10 -mat 1 -refs 3 -419 0.499998927116 0.500001013279 -418 0.999999046326 0.500002503395 -533 0.499999910593 -1.46663558098e-06 -SURF 0x10 -mat 1 -refs 3 -163 1.0 0.0 -533 0.499999910593 -1.46663558098e-06 -418 0.999999046326 0.500002503395 -SURF 0x10 -mat 1 -refs 3 -418 0.999999046326 0.500002503395 -419 0.499998927116 0.500001013279 -164 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -384 0.499977380037 8.24271126021e-07 -128 0.0 0.0 -408 0.499973624945 0.50000077486 -SURF 0x10 -mat 1 -refs 3 -408 0.499973624945 0.50000077486 -540 1.0 0.5 -384 0.499977380037 8.24271126021e-07 -SURF 0x10 -mat 1 -refs 3 -130 1.0 0.0 -384 0.499977380037 8.24271126021e-07 -540 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -540 1.0 0.5 -408 0.499973624945 0.50000077486 -159 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -387 0.50000077486 -1.54451669232e-08 -134 0.0 0.0 -542 0.500001490116 0.499999970198 -SURF 0x10 -mat 1 -refs 3 -542 0.500001490116 0.499999970198 -402 0.99999922514 0.5 -387 0.50000077486 -1.54451669232e-08 -SURF 0x10 -mat 1 -refs 3 -133 1.0 0.0 -387 0.50000077486 -1.54451669232e-08 -402 0.99999922514 0.5 -SURF 0x10 -mat 1 -refs 3 -402 0.99999922514 0.5 -542 0.500001490116 0.499999970198 -154 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -347 0.499995529652 4.90296542921e-07 -109 0.0 0.0 -383 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -383 0.5 0.5 -558 0.999995529652 0.500000476837 -347 0.499995529652 4.90296542921e-07 -SURF 0x10 -mat 1 -refs 3 -107 1.0 0.0 -347 0.499995529652 4.90296542921e-07 -558 0.999995529652 0.500000476837 -SURF 0x10 -mat 1 -refs 3 -558 0.999995529652 0.500000476837 -383 0.5 0.5 -130 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -348 0.499999076128 -3.98093247256e-09 -106 0.0 0.0 -559 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -559 0.5 0.5 -380 1.00000095367 0.5 -348 0.499999076128 -3.98093247256e-09 -SURF 0x10 -mat 1 -refs 3 -108 1.0 0.0 -348 0.499999076128 -3.98093247256e-09 -380 1.00000095367 0.5 -SURF 0x10 -mat 1 -refs 3 -380 1.00000095367 0.5 -559 0.5 0.5 -131 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -566 0.500000655651 -1.89869027167e-07 -116 0.0 0.0 -368 0.500000655651 0.50000077486 -SURF 0x10 -mat 1 -refs 3 -368 0.500000655651 0.50000077486 -371 1.0 0.500000953674 -566 0.500000655651 -1.89869027167e-07 -SURF 0x10 -mat 1 -refs 3 -124 1.0 0.0 -566 0.500000655651 -1.89869027167e-07 -371 1.0 0.500000953674 -SURF 0x10 -mat 1 -refs 3 -371 1.0 0.500000953674 -368 0.500000655651 0.50000077486 -123 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -365 0.500000655651 8.25563120088e-07 -117 0.0 0.0 -567 0.500000655651 0.499999880791 -SURF 0x10 -mat 1 -refs 3 -567 0.500000655651 0.499999880791 -370 1.0 0.499999046326 -365 0.500000655651 8.25563120088e-07 -SURF 0x10 -mat 1 -refs 3 -122 1.0 0.0 -365 0.500000655651 8.25563120088e-07 -370 1.0 0.499999046326 -SURF 0x10 -mat 1 -refs 3 -370 1.0 0.499999046326 -567 0.500000655651 0.499999880791 -125 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -484 0.500000476837 2.79571537476e-07 -90 0.0 0.0 -568 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -568 0.5 0.5 -357 0.999999523163 0.499999731779 -484 0.500000476837 2.79571537476e-07 -SURF 0x10 -mat 1 -refs 3 -114 1.0 0.0 -484 0.500000476837 2.79571537476e-07 -357 0.999999523163 0.499999731779 -SURF 0x10 -mat 1 -refs 3 -357 0.999999523163 0.499999731779 -568 0.5 0.5 -112 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -569 0.5 0.0 -91 0.0 0.0 -485 0.500000476837 0.500000178814 -SURF 0x10 -mat 1 -refs 3 -485 0.500000476837 0.500000178814 -356 1.00000047684 0.500000178814 -569 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -113 1.0 0.0 -569 0.5 0.0 -356 1.00000047684 0.500000178814 -SURF 0x10 -mat 1 -refs 3 -356 1.00000047684 0.500000178814 -485 0.500000476837 0.500000178814 -115 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -312 0.499996870756 -4.67448785457e-07 -82 0.0 0.0 -574 0.499997228384 0.499999523163 -SURF 0x10 -mat 1 -refs 3 -574 0.499997228384 0.499999523163 -488 1.00000035763 0.5 -312 0.499996870756 -4.67448785457e-07 -SURF 0x10 -mat 1 -refs 3 -84 1.0 0.0 -312 0.499996870756 -4.67448785457e-07 -488 1.00000035763 0.5 -SURF 0x10 -mat 1 -refs 3 -488 1.00000035763 0.5 -574 0.499997228384 0.499999523163 -108 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -309 0.499997287989 4.71542989544e-07 -85 0.0 0.0 -489 0.500002324581 0.499999523163 -SURF 0x10 -mat 1 -refs 3 -489 0.500002324581 0.499999523163 -575 0.999999642372 0.5 -309 0.499997287989 4.71542989544e-07 -SURF 0x10 -mat 1 -refs 3 -83 1.0 0.0 -309 0.499997287989 4.71542989544e-07 -575 0.999999642372 0.5 -SURF 0x10 -mat 1 -refs 3 -575 0.999999642372 0.5 -489 0.500002324581 0.499999523163 -109 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -287 0.500000417233 1.65939383123e-07 -61 0.0 0.0 -584 0.500000178814 0.5 -SURF 0x10 -mat 1 -refs 3 -584 0.500000178814 0.5 -311 0.999999761581 0.499999821186 -287 0.500000417233 1.65939383123e-07 -SURF 0x10 -mat 1 -refs 3 -59 1.0 0.0 -287 0.500000417233 1.65939383123e-07 -311 0.999999761581 0.499999821186 -SURF 0x10 -mat 1 -refs 3 -311 0.999999761581 0.499999821186 -584 0.500000178814 0.5 -84 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -288 0.499999850988 -1.50183739143e-12 -58 0.0 0.0 -310 0.499999761581 0.500000178814 -SURF 0x10 -mat 1 -refs 3 -310 0.499999761581 0.500000178814 -585 0.999999880791 0.500000178814 -288 0.499999850988 -1.50183739143e-12 -SURF 0x10 -mat 1 -refs 3 -60 1.0 0.0 -288 0.499999850988 -1.50183739143e-12 -585 0.999999880791 0.500000178814 -SURF 0x10 -mat 1 -refs 3 -585 0.999999880791 0.500000178814 -310 0.499999761581 0.500000178814 -85 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -590 0.5 1.12242453554e-07 -66 0.0 0.0 -300 0.5 0.499999761581 -SURF 0x10 -mat 1 -refs 3 -300 0.5 0.499999761581 -304 0.999999642372 0.499999761581 -590 0.5 1.12242453554e-07 -SURF 0x10 -mat 1 -refs 3 -79 1.0 0.0 -590 0.5 1.12242453554e-07 -304 0.999999642372 0.499999761581 -SURF 0x10 -mat 1 -refs 3 -304 0.999999642372 0.499999761581 -300 0.5 0.499999761581 -77 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -299 0.5 0.0 -67 0.0 0.0 -591 0.5 0.500000238419 -SURF 0x10 -mat 1 -refs 3 -591 0.5 0.500000238419 -303 1.00000035763 0.500000417233 -299 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -76 1.0 0.0 -299 0.5 0.0 -303 1.00000035763 0.500000417233 -SURF 0x10 -mat 1 -refs 3 -303 1.00000035763 0.500000417233 -591 0.5 0.500000238419 -78 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -592 0.5 -1.06428693414e-07 -40 0.0 0.0 -491 0.499999970198 0.499999880791 -SURF 0x10 -mat 1 -refs 3 -491 0.499999970198 0.499999880791 -293 1.0 0.5 -592 0.5 -1.06428693414e-07 -SURF 0x10 -mat 1 -refs 3 -64 1.0 0.0 -592 0.5 -1.06428693414e-07 -293 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -293 1.0 0.5 -491 0.499999970198 0.499999880791 -66 1.0 1.0 -SURF 0x10 -mat 1 -refs 3 -260 0.499999940395 -4.50094361781e-09 -38 0.0 0.0 -593 0.499999970198 0.499999970198 -SURF 0x10 -mat 1 -refs 3 -593 0.499999970198 0.499999970198 -494 0.999999940395 0.5 -260 0.499999940395 -4.50094361781e-09 -SURF 0x10 -mat 1 -refs 3 -36 1.0 0.0 -260 0.499999940395 -4.50094361781e-09 -494 0.999999940395 0.5 -SURF 0x10 -mat 1 -refs 3 -494 0.999999940395 0.5 -593 0.499999970198 0.499999970198 -62 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -305 1.00000023842 0.500000298023 -78 1.0 0.0 -591 0.999999761581 0.0 -594 0.586517691612 0.0 -SURF 0x10 -mat 1 -refs 4 -80 1.0 1.0 -305 1.00000023842 0.500000298023 -594 0.586517691612 0.0 -589 0.499999850988 0.499999850988 -SURF 0x10 -mat 1 -refs 4 -594 0.586517691612 0.0 -591 0.999999761581 0.0 -67 1.0 0.0 -294 0.499999940395 0.0 -SURF 0x10 -mat 1 -refs 4 -589 0.499999850988 0.499999850988 -594 0.586517691612 0.0 -294 0.499999940395 0.0 -65 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -588 0.5 0.0 -64 0.0 0.0 -293 0.0 0.0 -595 0.499959677458 0.499959677458 -SURF 0x10 -mat 1 -refs 4 -81 1.0 0.0 -588 0.5 0.0 -595 0.499959677458 0.499959677458 -306 1.0 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -595 0.499959677458 0.499959677458 -293 0.0 0.0 -66 0.0 0.0 -590 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -306 1.0 0.500000178814 -595 0.499959677458 0.499959677458 -590 0.5 0.5 -79 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -307 0.999999642372 0.499999642372 -80 1.0 0.0 -589 1.0 0.0 -596 0.613853871822 0.0 -SURF 0x10 -mat 1 -refs 4 -83 1.0 1.0 -307 0.999999642372 0.499999642372 -596 0.613853871822 0.0 -587 0.499999821186 0.499999701977 -SURF 0x10 -mat 1 -refs 4 -596 0.613853871822 0.0 -589 1.0 0.0 -65 1.0 0.0 -292 0.499999850988 0.0 -SURF 0x10 -mat 1 -refs 4 -587 0.499999821186 0.499999701977 -596 0.613853871822 0.0 -292 0.499999850988 0.0 -63 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -586 0.500000178814 1.15166677972e-07 -62 0.0 0.0 -291 1.65868542013e-07 1.65868542013e-07 -597 0.499952614307 0.499952614307 -SURF 0x10 -mat 1 -refs 4 -82 1.0 0.0 -586 0.500000178814 1.15166677972e-07 -597 0.499952614307 0.499952614307 -308 0.999999642372 0.500000536442 -SURF 0x10 -mat 1 -refs 4 -597 0.499952614307 0.499952614307 -291 1.65868542013e-07 1.65868542013e-07 -64 0.0 0.0 -588 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -308 0.999999642372 0.500000536442 -597 0.499952614307 0.499952614307 -588 0.5 0.5 -81 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -309 1.00000023842 0.50000089407 -83 1.0 0.0 -587 1.00000011921 0.0 -598 0.595433354378 0.0 -SURF 0x10 -mat 1 -refs 4 -85 1.0 1.0 -309 1.00000023842 0.50000089407 -598 0.595433354378 0.0 -585 0.500000178814 0.500000298023 -SURF 0x10 -mat 1 -refs 4 -598 0.595433354378 0.0 -587 1.00000011921 0.0 -63 1.0 0.0 -290 0.500000119209 0.0 -SURF 0x10 -mat 1 -refs 4 -585 0.500000178814 0.500000298023 -598 0.595433354378 0.0 -290 0.500000119209 0.0 -60 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -584 0.5 -1.77222261755e-07 -61 0.0 0.0 -289 1.65894547877e-07 1.65894547877e-07 -599 0.499946832657 0.499946832657 -SURF 0x10 -mat 1 -refs 4 -84 1.0 0.0 -584 0.5 -1.77222261755e-07 -599 0.499946832657 0.499946832657 -312 0.999999701977 0.500000596046 -SURF 0x10 -mat 1 -refs 4 -599 0.499946832657 0.499946832657 -289 1.65894547877e-07 1.65894547877e-07 -62 0.0 0.0 -586 0.500000178814 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -312 0.999999701977 0.500000596046 -599 0.499946832657 0.499946832657 -586 0.500000178814 0.500000178814 -82 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -372 1.0 0.500000715256 -125 1.0 0.0 -567 1.00000059605 0.0 -600 0.510695874691 0.0 -SURF 0x10 -mat 1 -refs 4 -127 1.0 1.0 -372 1.0 0.500000715256 -600 0.510695874691 0.0 -565 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -600 0.510695874691 0.0 -567 1.00000059605 0.0 -117 1.0 0.0 -359 0.499999880791 0.0 -SURF 0x10 -mat 1 -refs 4 -565 0.5 0.5 -600 0.510695874691 0.0 -359 0.499999880791 0.0 -114 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -564 0.5 -7.27682390789e-07 -115 0.0 0.0 -358 0.0 0.0 -601 0.508976221085 0.508976221085 -SURF 0x10 -mat 1 -refs 4 -126 1.0 0.0 -564 0.5 -7.27682390789e-07 -601 0.508976221085 0.508976221085 -373 1.00000071526 0.500000536442 -SURF 0x10 -mat 1 -refs 4 -601 0.508976221085 0.508976221085 -358 0.0 0.0 -116 0.0 0.0 -566 0.500000655651 0.500000655651 -SURF 0x10 -mat 1 -refs 4 -373 1.00000071526 0.500000536442 -601 0.508976221085 0.508976221085 -566 0.500000655651 0.500000655651 -124 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -374 1.00000059605 0.500000178814 -127 1.0 0.0 -565 1.0 0.0 -602 0.510801136494 0.0128724472597 -SURF 0x10 -mat 1 -refs 4 -143 1.0 1.0 -374 1.00000059605 0.500000178814 -602 0.510801136494 0.0128724472597 -563 0.499999940395 0.500000476837 -SURF 0x10 -mat 1 -refs 4 -602 0.510801136494 0.0128724472597 -565 1.0 0.0 -114 1.0 0.0 -357 0.500000119209 0.0 -SURF 0x10 -mat 1 -refs 4 -563 0.499999940395 0.500000476837 -602 0.510801136494 0.0128724472597 -357 0.500000119209 0.0 -112 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -562 0.499999374151 -4.03749169209e-07 -113 0.0 0.0 -356 6.26263727099e-07 6.26263727099e-07 -603 0.510821282864 0.497726976871 -SURF 0x10 -mat 1 -refs 4 -142 1.0 0.0 -562 0.499999374151 -4.03749169209e-07 -603 0.510821282864 0.497726976871 -375 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -603 0.510821282864 0.497726976871 -356 6.26263727099e-07 6.26263727099e-07 -115 0.0 0.0 -564 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -375 1.0 0.5 -603 0.510821282864 0.497726976871 -564 0.5 0.5 -126 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -377 1.0 0.5 -143 1.0 0.0 -563 0.999999642372 0.0 -604 0.592199683189 0.0 -SURF 0x10 -mat 1 -refs 4 -141 1.0 1.0 -377 1.0 0.5 -604 0.592199683189 0.0 -560 0.499999433756 0.499998986721 -SURF 0x10 -mat 1 -refs 4 -604 0.592199683189 0.0 -563 0.999999642372 0.0 -112 1.0 0.0 -355 0.500000298023 0.0 -SURF 0x10 -mat 1 -refs 4 -560 0.499999433756 0.499998986721 -604 0.592199683189 0.0 -355 0.500000298023 0.0 -96 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -561 0.500000536442 -4.68275601406e-07 -97 0.0 0.0 -354 5.9695236132e-07 5.9695236132e-07 -605 0.509557664394 0.509557664394 -SURF 0x10 -mat 1 -refs 4 -140 1.0 0.0 -561 0.500000536442 -4.68275601406e-07 -605 0.509557664394 0.509557664394 -376 0.999999463558 0.500000476837 -SURF 0x10 -mat 1 -refs 4 -605 0.509557664394 0.509557664394 -354 5.9695236132e-07 5.9695236132e-07 -113 0.0 0.0 -562 0.499999403954 0.499999403954 -SURF 0x10 -mat 1 -refs 4 -376 0.999999463558 0.500000476837 -605 0.509557664394 0.509557664394 -562 0.499999403954 0.499999403954 -142 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -551 0.500000536442 -4.5604244292e-07 -99 0.0 0.0 -353 9.43448985602e-10 9.43448985602e-10 -606 0.507931172848 0.507931172848 -SURF 0x10 -mat 1 -refs 4 -138 1.0 0.0 -551 0.500000536442 -4.5604244292e-07 -606 0.507931172848 0.507931172848 -393 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -606 0.507931172848 0.507931172848 -353 9.43448985602e-10 9.43448985602e-10 -97 0.0 0.0 -561 0.500000596046 0.500000596046 -SURF 0x10 -mat 1 -refs 4 -393 1.0 0.5 -606 0.507931172848 0.507931172848 -561 0.500000596046 0.500000596046 -140 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -394 0.999999523163 0.499998092651 -141 1.0 0.0 -560 1.00000035763 0.0 -607 0.584155201912 0.0 -SURF 0x10 -mat 1 -refs 4 -139 1.0 1.0 -394 0.999999523163 0.499998092651 -607 0.584155201912 0.0 -550 0.499999493361 0.499998390675 -SURF 0x10 -mat 1 -refs 4 -607 0.584155201912 0.0 -560 1.00000035763 0.0 -96 1.0 0.0 -352 0.500000119209 0.0 -SURF 0x10 -mat 1 -refs 4 -550 0.499999493361 0.499998390675 -607 0.584155201912 0.0 -352 0.500000119209 0.0 -98 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -557 0.5 0.5 -133 1.0 1.0 -385 1.00000047684 0.499993801117 -608 0.501856803894 0.501856803894 -SURF 0x10 -mat 1 -refs 4 -105 0.0 0.0 -557 0.5 0.5 -608 0.501856803894 0.501856803894 -346 5.41566407719e-07 5.41566407719e-07 -SURF 0x10 -mat 1 -refs 4 -608 0.501856803894 0.501856803894 -385 1.00000047684 0.499993801117 -131 1.0 0.0 -559 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -346 5.41566407719e-07 5.41566407719e-07 -608 0.501856803894 0.501856803894 -559 0.5 0.0 -106 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -345 0.5 0.0 -107 0.0 0.0 -558 0.500000476837 0.500006198883 -609 0.615569829941 0.0 -SURF 0x10 -mat 1 -refs 4 -104 1.0 0.0 -345 0.5 0.0 -609 0.615569829941 0.0 -556 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -609 0.615569829941 0.0 -558 0.500000476837 0.500006198883 -130 1.0 1.0 -386 0.999999523163 0.499993801117 -SURF 0x10 -mat 1 -refs 4 -556 1.0 0.0 -609 0.615569829941 0.0 -386 0.999999523163 0.499993801117 -132 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -555 0.499999463558 0.499999463558 -134 1.0 1.0 -387 1.0 0.499999165535 -610 0.502711474895 0.502711474895 -SURF 0x10 -mat 1 -refs 4 -103 0.0 0.0 -555 0.499999463558 0.499999463558 -610 0.502711474895 0.502711474895 -344 -5.40381108749e-07 -5.40381108749e-07 -SURF 0x10 -mat 1 -refs 4 -610 0.502711474895 0.502711474895 -387 1.0 0.499999165535 -133 1.0 0.0 -557 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -344 -5.40381108749e-07 -5.40381108749e-07 -610 0.502711474895 0.502711474895 -557 0.5 0.0 -105 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -343 0.5 0.0 -104 0.0 0.0 -556 0.5 0.5 -611 0.631908178329 0.0 -SURF 0x10 -mat 1 -refs 4 -102 1.0 0.0 -343 0.5 0.0 -611 0.631908178329 0.0 -554 0.999999642372 0.0 -SURF 0x10 -mat 1 -refs 4 -611 0.631908178329 0.0 -556 0.5 0.5 -132 1.0 1.0 -388 1.0 0.49999922514 -SURF 0x10 -mat 1 -refs 4 -554 0.999999642372 0.0 -611 0.631908178329 0.0 -388 1.0 0.49999922514 -135 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -553 0.500000536442 0.500000536442 -136 1.0 1.0 -389 1.0 0.5 -612 0.50467056036 0.50467056036 -SURF 0x10 -mat 1 -refs 4 -101 0.0 0.0 -553 0.500000536442 0.500000536442 -612 0.50467056036 0.50467056036 -342 7.09478809036e-10 7.09478809036e-10 -SURF 0x10 -mat 1 -refs 4 -612 0.50467056036 0.50467056036 -389 1.0 0.5 -134 1.0 0.0 -555 0.499999493361 2.20369133785e-06 -SURF 0x10 -mat 1 -refs 4 -342 7.09478809036e-10 7.09478809036e-10 -612 0.50467056036 0.50467056036 -555 0.499999493361 2.20369133785e-06 -103 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -341 0.5 0.0 -102 0.0 0.0 -554 0.5 0.500000476837 -613 0.61085832119 0.0 -SURF 0x10 -mat 1 -refs 4 -100 1.0 0.0 -341 0.5 0.0 -613 0.61085832119 0.0 -552 1.00000095367 0.0 -SURF 0x10 -mat 1 -refs 4 -613 0.61085832119 0.0 -554 0.5 0.500000476837 -135 1.0 1.0 -390 1.00000047684 0.500002920628 -SURF 0x10 -mat 1 -refs 4 -552 1.00000095367 0.0 -613 0.61085832119 0.0 -390 1.00000047684 0.500002920628 -137 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -551 0.500000536442 0.500000536442 -138 1.0 1.0 -391 0.999999523163 0.500000536442 -614 0.506308436394 0.506308436394 -SURF 0x10 -mat 1 -refs 4 -99 0.0 0.0 -551 0.500000536442 0.500000536442 -614 0.506308436394 0.506308436394 -340 -5.60829391816e-07 -5.60829391816e-07 -SURF 0x10 -mat 1 -refs 4 -614 0.506308436394 0.506308436394 -391 0.999999523163 0.500000536442 -136 1.0 0.0 -553 0.500000536442 -8.83747134139e-07 -SURF 0x10 -mat 1 -refs 4 -340 -5.60829391816e-07 -5.60829391816e-07 -614 0.506308436394 0.506308436394 -553 0.500000536442 -8.83747134139e-07 -101 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -339 0.500000238419 0.0 -100 0.0 0.0 -552 0.499999493361 0.49999833107 -615 0.588320732117 0.0 -SURF 0x10 -mat 1 -refs 4 -98 1.0 0.0 -339 0.500000238419 0.0 -615 0.588320732117 0.0 -550 1.00000083447 0.0 -SURF 0x10 -mat 1 -refs 4 -615 0.588320732117 0.0 -552 0.499999493361 0.49999833107 -137 1.0 1.0 -392 1.0 0.499999284744 -SURF 0x10 -mat 1 -refs 4 -550 1.00000083447 0.0 -615 0.588320732117 0.0 -392 1.0 0.499999284744 -139 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -377 0.5 0.0 -141 0.0 0.0 -549 0.499999910593 0.500000834465 -616 0.605205059052 0.0 -SURF 0x10 -mat 1 -refs 4 -143 1.0 0.0 -377 0.5 0.0 -616 0.605205059052 0.0 -539 0.999998271465 0.0 -SURF 0x10 -mat 1 -refs 4 -616 0.605205059052 0.0 -549 0.499999910593 0.500000834465 -148 1.0 1.0 -395 1.00000095367 0.500003635883 -SURF 0x10 -mat 1 -refs 4 -539 0.999998271465 0.0 -616 0.605205059052 0.0 -395 1.00000095367 0.500003635883 -146 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -397 1.0 0.5 -148 1.0 0.0 -549 0.999999403954 0.0 -617 0.608679890633 0.0 -SURF 0x10 -mat 1 -refs 4 -150 1.0 1.0 -397 1.0 0.5 -617 0.608679890633 0.0 -547 0.499999135733 0.499995321035 -SURF 0x10 -mat 1 -refs 4 -617 0.608679890633 0.0 -549 0.999999403954 0.0 -141 1.0 0.0 -394 0.500002384186 0.0 -SURF 0x10 -mat 1 -refs 4 -547 0.499999135733 0.499995321035 -617 0.608679890633 0.0 -394 0.500002384186 0.0 -139 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -546 0.50000089407 -4.06020626542e-06 -138 0.0 0.0 -393 0.0 0.0 -618 0.504001259804 0.504001259804 -SURF 0x10 -mat 1 -refs 4 -151 1.0 0.0 -546 0.50000089407 -4.06020626542e-06 -618 0.504001259804 0.504001259804 -398 0.999999940395 0.499998927116 -SURF 0x10 -mat 1 -refs 4 -618 0.504001259804 0.504001259804 -393 0.0 0.0 -140 0.0 0.0 -548 0.499999076128 0.499999076128 -SURF 0x10 -mat 1 -refs 4 -398 0.999999940395 0.499998927116 -618 0.504001259804 0.504001259804 -548 0.499999076128 0.499999076128 -149 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -538 0.5 0.5 -147 1.0 1.0 -396 0.999999880791 0.499999076128 -619 0.505600273609 0.505600273609 -SURF 0x10 -mat 1 -refs 4 -142 0.0 0.0 -538 0.5 0.5 -619 0.505600273609 0.505600273609 -376 -9.86463646768e-07 -9.86463646768e-07 -SURF 0x10 -mat 1 -refs 4 -619 0.505600273609 0.505600273609 -396 0.999999880791 0.499999076128 -149 1.0 0.0 -548 0.499999165535 3.56722853212e-06 -SURF 0x10 -mat 1 -refs 4 -376 -9.86463646768e-07 -9.86463646768e-07 -619 0.505600273609 0.505600273609 -548 0.499999165535 3.56722853212e-06 -140 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -399 1.00000083447 0.500006616116 -150 1.0 0.0 -547 1.0000025034 0.0 -620 0.624245405197 0.0 -SURF 0x10 -mat 1 -refs 4 -152 1.0 1.0 -399 1.00000083447 0.500006616116 -620 0.624245405197 0.0 -545 0.500000059605 0.499998807907 -SURF 0x10 -mat 1 -refs 4 -620 0.624245405197 0.0 -547 1.0000025034 0.0 -139 1.0 0.0 -392 0.500000715256 0.0 -SURF 0x10 -mat 1 -refs 4 -545 0.500000059605 0.499998807907 -620 0.624245405197 0.0 -392 0.500000715256 0.0 -137 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -544 0.5 0.0 -136 0.0 0.0 -391 -9.99683379632e-07 -9.99683379632e-07 -621 0.502808749676 0.502808749676 -SURF 0x10 -mat 1 -refs 4 -153 1.0 0.0 -544 0.5 0.0 -621 0.502808749676 0.502808749676 -400 0.999999940395 0.499998569489 -SURF 0x10 -mat 1 -refs 4 -621 0.502808749676 0.502808749676 -391 -9.99683379632e-07 -9.99683379632e-07 -138 0.0 0.0 -546 0.500000953674 0.500000953674 -SURF 0x10 -mat 1 -refs 4 -400 0.999999940395 0.499998569489 -621 0.502808749676 0.502808749676 -546 0.500000953674 0.500000953674 -151 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -401 0.999999165535 0.499991327524 -152 1.0 0.0 -545 1.00000095367 0.0 -622 0.635665357113 0.0 -SURF 0x10 -mat 1 -refs 4 -155 1.0 1.0 -401 0.999999165535 0.499991327524 -622 0.635665357113 0.0 -543 0.499999970198 0.50000089407 -SURF 0x10 -mat 1 -refs 4 -622 0.635665357113 0.0 -545 1.00000095367 0.0 -137 1.0 0.0 -390 0.499995529652 0.0 -SURF 0x10 -mat 1 -refs 4 -543 0.499999970198 0.50000089407 -622 0.635665357113 0.0 -390 0.499995529652 0.0 -135 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -542 0.499999940395 -2.21158416025e-06 -134 0.0 0.0 -389 0.0 0.0 -623 0.501285552979 0.501285552979 -SURF 0x10 -mat 1 -refs 4 -154 1.0 0.0 -542 0.499999940395 -2.21158416025e-06 -623 0.501285552979 0.501285552979 -403 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -623 0.501285552979 0.501285552979 -389 0.0 0.0 -136 0.0 0.0 -544 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -403 1.0 0.5 -623 0.501285552979 0.501285552979 -544 0.5 0.5 -153 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -404 1.00000071526 0.500015616417 -155 1.0 0.0 -543 0.999999284744 0.0 -624 0.623109459877 0.0 -SURF 0x10 -mat 1 -refs 4 -157 1.0 1.0 -404 1.00000071526 0.500015616417 -624 0.623109459877 0.0 -541 0.499999374151 0.499981820583 -SURF 0x10 -mat 1 -refs 4 -624 0.623109459877 0.0 -543 0.999999284744 0.0 -135 1.0 0.0 -388 0.500000655651 0.0 -SURF 0x10 -mat 1 -refs 4 -541 0.499999374151 0.499981820583 -624 0.623109459877 0.0 -388 0.500000655651 0.0 -132 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -407 0.999999940395 0.500004589558 -157 1.0 0.0 -541 1.0000128746 0.0 -625 0.649331092834 0.0 -SURF 0x10 -mat 1 -refs 4 -159 1.0 1.0 -407 0.999999940395 0.500004589558 -625 0.649331092834 0.0 -540 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -625 0.649331092834 0.0 -541 1.0000128746 0.0 -132 1.0 0.0 -386 0.500010967255 0.0 -SURF 0x10 -mat 1 -refs 4 -540 0.5 0.5 -625 0.649331092834 0.0 -386 0.500010967255 0.0 -130 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -374 0.499999940395 0.0 -143 0.0 0.0 -539 0.50000089407 0.500003635883 -626 0.611721992493 0.0 -SURF 0x10 -mat 1 -refs 4 -127 1.0 0.0 -374 0.499999940395 0.0 -626 0.611721992493 0.0 -536 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -626 0.611721992493 0.0 -539 0.50000089407 0.500003635883 -146 1.0 1.0 -412 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -536 1.0 0.0 -626 0.611721992493 0.0 -412 1.0 0.5 -144 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -537 0.500001013279 0.500001013279 -145 1.0 1.0 -413 1.00000095367 0.499998211861 -627 0.507554531097 0.507554531097 -SURF 0x10 -mat 1 -refs 4 -126 0.0 0.0 -537 0.500001013279 0.500001013279 -627 0.507554531097 0.507554531097 -375 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -627 0.507554531097 0.507554531097 -413 1.00000095367 0.499998211861 -147 1.0 0.0 -538 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -375 0.0 0.0 -627 0.507554531097 0.507554531097 -538 0.5 0.0 -142 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -535 0.500001072884 0.500001072884 -161 1.0 1.0 -414 1.00000095367 0.499999046326 -628 0.508349716663 0.508349716663 -SURF 0x10 -mat 1 -refs 4 -124 0.0 0.0 -535 0.500001072884 0.500001072884 -628 0.508349716663 0.508349716663 -373 1.09434506612e-06 1.09434506612e-06 -SURF 0x10 -mat 1 -refs 4 -628 0.508349716663 0.508349716663 -414 1.00000095367 0.499999046326 -145 1.0 0.0 -537 0.500001013279 -9.55497171162e-07 -SURF 0x10 -mat 1 -refs 4 -373 1.09434506612e-06 1.09434506612e-06 -628 0.508349716663 0.508349716663 -537 0.500001013279 -9.55497171162e-07 -126 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -372 0.499999284744 0.0 -127 0.0 0.0 -536 0.5 0.5 -629 0.543397426605 0.0 -SURF 0x10 -mat 1 -refs 4 -125 1.0 0.0 -372 0.499999284744 0.0 -629 0.543397426605 0.0 -534 0.999999344349 0.0 -SURF 0x10 -mat 1 -refs 4 -629 0.543397426605 0.0 -536 0.5 0.5 -144 1.0 1.0 -415 1.00000095367 0.500002801418 -SURF 0x10 -mat 1 -refs 4 -534 0.999999344349 0.0 -629 0.543397426605 0.0 -415 1.00000095367 0.500002801418 -160 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -533 0.499999970198 0.499999970198 -163 1.0 1.0 -416 1.00000095367 0.499997913837 -630 0.507047891617 0.507047891617 -SURF 0x10 -mat 1 -refs 4 -123 0.0 0.0 -533 0.499999970198 0.499999970198 -630 0.507047891617 0.507047891617 -371 4.34617319911e-08 4.34617319911e-08 -SURF 0x10 -mat 1 -refs 4 -630 0.507047891617 0.507047891617 -416 1.00000095367 0.499997913837 -161 1.0 0.0 -535 0.500001072884 1.27035235664e-07 -SURF 0x10 -mat 1 -refs 4 -371 4.34617319911e-08 4.34617319911e-08 -630 0.507047891617 0.507047891617 -535 0.500001072884 1.27035235664e-07 -124 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -370 0.500000953674 0.0 -125 0.0 0.0 -534 0.500001072884 0.500002086163 -631 0.540586769581 0.0 -SURF 0x10 -mat 1 -refs 4 -122 1.0 0.0 -370 0.500000953674 0.0 -631 0.540586769581 0.0 -532 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -631 0.540586769581 0.0 -534 0.500001072884 0.500002086163 -160 1.0 1.0 -417 1.00000119209 0.500001013279 -SURF 0x10 -mat 1 -refs 4 -532 1.0 0.0 -631 0.540586769581 0.0 -417 1.00000119209 0.500001013279 -162 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -529 0.500000238419 2.29982970268e-06 -163 0.0 0.0 -418 -1.84052225904e-06 -1.84052225904e-06 -632 0.507163226604 0.507163226604 -SURF 0x10 -mat 1 -refs 4 -174 1.0 0.0 -529 0.500000238419 2.29982970268e-06 -632 0.507163226604 0.507163226604 -438 1.00000023842 0.500002324581 -SURF 0x10 -mat 1 -refs 4 -632 0.507163226604 0.507163226604 -418 -1.84052225904e-06 -1.84052225904e-06 -164 0.0 0.0 -531 0.499998152256 0.499998152256 -SURF 0x10 -mat 1 -refs 4 -438 1.00000023842 0.500002324581 -632 0.507163226604 0.507163226604 -531 0.499998152256 0.499998152256 -172 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -439 0.999998271465 0.49999320507 -175 1.0 0.0 -530 1.0 0.0 -633 0.608557581902 0.0 -SURF 0x10 -mat 1 -refs 4 -191 1.0 1.0 -439 0.999998271465 0.49999320507 -633 0.608557581902 0.0 -528 0.500000178814 0.499998390675 -SURF 0x10 -mat 1 -refs 4 -633 0.608557581902 0.0 -530 1.0 0.0 -162 1.0 0.0 -417 0.499998986721 0.0 -SURF 0x10 -mat 1 -refs 4 -528 0.500000178814 0.499998390675 -633 0.608557581902 0.0 -417 0.499998986721 0.0 -160 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -527 0.499998301268 4.97047585668e-06 -161 0.0 0.0 -416 1.78645257165e-06 1.78645257165e-06 -634 0.508584260941 0.508584260941 -SURF 0x10 -mat 1 -refs 4 -190 1.0 0.0 -527 0.499998301268 4.97047585668e-06 -634 0.508584260941 0.508584260941 -440 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -634 0.508584260941 0.508584260941 -416 1.78645257165e-06 1.78645257165e-06 -163 0.0 0.0 -529 0.500000119209 0.500000119209 -SURF 0x10 -mat 1 -refs 4 -440 1.0 0.5 -634 0.508584260941 0.508584260941 -529 0.500000119209 0.500000119209 -174 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -442 1.0 0.5 -191 1.0 0.0 -528 1.00000071526 0.0 -635 0.64407235384 0.0 -SURF 0x10 -mat 1 -refs 4 -189 1.0 1.0 -442 1.0 0.5 -635 0.64407235384 0.0 -525 0.499998420477 0.499990969896 -SURF 0x10 -mat 1 -refs 4 -635 0.64407235384 0.0 -528 1.00000071526 0.0 -160 1.0 0.0 -415 0.499996989965 0.0 -SURF 0x10 -mat 1 -refs 4 -525 0.499998420477 0.499990969896 -635 0.64407235384 0.0 -415 0.499996989965 0.0 -144 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -526 0.499998420477 7.45142187952e-06 -145 0.0 0.0 -414 1.86162344562e-06 1.86162344562e-06 -636 0.507936120033 0.507936120033 -SURF 0x10 -mat 1 -refs 4 -188 1.0 0.0 -526 0.499998420477 7.45142187952e-06 -636 0.507936120033 0.507936120033 -441 1.00000154972 0.499992549419 -SURF 0x10 -mat 1 -refs 4 -636 0.507936120033 0.507936120033 -414 1.86162344562e-06 1.86162344562e-06 -161 0.0 0.0 -527 0.499998152256 0.499998152256 -SURF 0x10 -mat 1 -refs 4 -441 1.00000154972 0.499992549419 -636 0.507936120033 0.507936120033 -527 0.499998152256 0.499998152256 -190 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -516 0.500001549721 -1.05182652987e-05 -147 0.0 0.0 -413 1.80308211384e-06 1.80308211384e-06 -637 0.505881011486 0.505881011486 -SURF 0x10 -mat 1 -refs 4 -186 1.0 0.0 -516 0.500001549721 -1.05182652987e-05 -637 0.505881011486 0.505881011486 -458 0.999998450279 0.500010490417 -SURF 0x10 -mat 1 -refs 4 -637 0.505881011486 0.505881011486 -413 1.80308211384e-06 1.80308211384e-06 -145 0.0 0.0 -526 0.499998182058 0.499998182058 -SURF 0x10 -mat 1 -refs 4 -458 0.999998450279 0.500010490417 -637 0.505881011486 0.505881011486 -526 0.499998182058 0.499998182058 -188 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -459 1.0 0.5 -189 1.0 0.0 -525 1.00000357628 0.0 -638 0.642685234547 0.0 -SURF 0x10 -mat 1 -refs 4 -187 1.0 1.0 -459 1.0 0.5 -638 0.642685234547 0.0 -515 0.500001430511 0.500011503696 -SURF 0x10 -mat 1 -refs 4 -638 0.642685234547 0.0 -525 1.00000357628 0.0 -144 1.0 0.0 -412 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -515 0.500001430511 0.500011503696 -638 0.642685234547 0.0 -412 0.5 0.0 -146 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -404 0.499976426363 0.0 -157 0.0 0.0 -524 0.500000834465 0.500076115131 -639 0.669776380062 0.0 -SURF 0x10 -mat 1 -refs 4 -155 1.0 0.0 -404 0.499976426363 0.0 -639 0.669776380062 0.0 -523 0.999974727631 0.0 -SURF 0x10 -mat 1 -refs 4 -639 0.669776380062 0.0 -524 0.500000834465 0.500076115131 -176 1.0 1.0 -448 1.00000095367 0.500071287155 -SURF 0x10 -mat 1 -refs 4 -523 0.999974727631 0.0 -639 0.669776380062 0.0 -448 1.00000095367 0.500071287155 -178 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -401 0.500014305115 0.0 -155 0.0 0.0 -523 0.50000077486 0.500047028065 -640 0.656186342239 0.0 -SURF 0x10 -mat 1 -refs 4 -152 1.0 0.0 -401 0.500014305115 0.0 -640 0.656186342239 0.0 -521 1.00001680851 0.0 -SURF 0x10 -mat 1 -refs 4 -640 0.656186342239 0.0 -523 0.50000077486 0.500047028065 -178 1.0 1.0 -451 1.00000107288 0.5000410676 -SURF 0x10 -mat 1 -refs 4 -521 1.00001680851 0.0 -640 0.656186342239 0.0 -451 1.00000107288 0.5000410676 -180 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -520 0.499999940395 0.499999940395 -182 1.0 1.0 -452 1.0 0.5 -641 0.503381431103 0.503381431103 -SURF 0x10 -mat 1 -refs 4 -151 0.0 0.0 -520 0.499999940395 0.499999940395 -641 0.503381431103 0.503381431103 -400 -1.18080357936e-07 -1.18080357936e-07 -SURF 0x10 -mat 1 -refs 4 -641 0.503381431103 0.503381431103 -452 1.0 0.5 -181 1.0 0.0 -522 0.499999821186 -1.48145306866e-06 -SURF 0x10 -mat 1 -refs 4 -400 -1.18080357936e-07 -1.18080357936e-07 -641 0.503381431103 0.503381431103 -522 0.499999821186 -1.48145306866e-06 -153 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -399 0.499990284443 0.0 -152 0.0 0.0 -521 0.49999910593 0.499968081713 -642 0.659423589706 0.0 -SURF 0x10 -mat 1 -refs 4 -150 1.0 0.0 -399 0.499990284443 0.0 -642 0.659423589706 0.0 -519 1.00000977516 0.0 -SURF 0x10 -mat 1 -refs 4 -642 0.659423589706 0.0 -521 0.49999910593 0.499968081713 -180 1.0 1.0 -453 1.00000119209 0.500027537346 -SURF 0x10 -mat 1 -refs 4 -519 1.00000977516 0.0 -642 0.659423589706 0.0 -453 1.00000119209 0.500027537346 -183 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -518 0.500000059605 0.500000059605 -184 1.0 1.0 -454 1.00000011921 0.500002741814 -643 0.504193484783 0.504193484783 -SURF 0x10 -mat 1 -refs 4 -149 0.0 0.0 -518 0.500000059605 0.500000059605 -643 0.504193484783 0.504193484783 -398 -5.54863284208e-08 -5.54863284208e-08 -SURF 0x10 -mat 1 -refs 4 -643 0.504193484783 0.504193484783 -454 1.00000011921 0.500002741814 -182 1.0 0.0 -520 0.499999970198 7.01830003891e-07 -SURF 0x10 -mat 1 -refs 4 -398 -5.54863284208e-08 -5.54863284208e-08 -643 0.504193484783 0.504193484783 -520 0.499999970198 7.01830003891e-07 -151 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -397 0.5 0.0 -150 0.0 0.0 -519 0.499998807907 0.499980181456 -644 0.651329994202 0.0 -SURF 0x10 -mat 1 -refs 4 -148 1.0 0.0 -397 0.5 0.0 -644 0.651329994202 0.0 -517 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -644 0.651329994202 0.0 -519 0.499998807907 0.499980181456 -183 1.0 1.0 -455 1.00000119209 0.500019848347 -SURF 0x10 -mat 1 -refs 4 -517 1.0 0.0 -644 0.651329994202 0.0 -455 1.00000119209 0.500019848347 -185 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -516 0.500001788139 0.500001788139 -186 1.0 1.0 -456 1.00000011921 0.50000166893 -645 0.504385650158 0.504385650158 -SURF 0x10 -mat 1 -refs 4 -147 0.0 0.0 -516 0.500001788139 0.500001788139 -645 0.504385650158 0.504385650158 -396 -1.19369403251e-07 -1.19369403251e-07 -SURF 0x10 -mat 1 -refs 4 -645 0.504385650158 0.504385650158 -456 1.00000011921 0.50000166893 -184 1.0 0.0 -518 0.499998509884 1.54564822878e-05 -SURF 0x10 -mat 1 -refs 4 -396 -1.19369403251e-07 -1.19369403251e-07 -645 0.504385650158 0.504385650158 -518 0.499998509884 1.54564822878e-05 -149 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -395 0.499995082617 0.0 -148 0.0 0.0 -517 0.5 0.5 -646 0.642947554588 0.0 -SURF 0x10 -mat 1 -refs 4 -146 1.0 0.0 -395 0.499995082617 0.0 -646 0.642947554588 0.0 -515 0.999995112419 0.0 -SURF 0x10 -mat 1 -refs 4 -646 0.642947554588 0.0 -517 0.5 0.5 -185 1.0 1.0 -457 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -515 0.999995112419 0.0 -646 0.642947554588 0.0 -457 1.0 0.5 -187 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -479 0.5 0.5 -192 1.0 1.0 -465 0.999995589256 0.499992281199 -647 0.267773479223 0.255623370409 -SURF 0x10 -mat 1 -refs 4 -189 0.0 0.0 -479 0.5 0.5 -647 0.267773479223 0.255623370409 -442 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -647 0.267773479223 0.255623370409 -465 0.999995589256 0.499992281199 -175 1.0 0.0 -439 0.499995619059 -7.72269322624e-06 -SURF 0x10 -mat 1 -refs 4 -442 0.0 0.0 -647 0.267773479223 0.255623370409 -439 0.499995619059 -7.72269322624e-06 -191 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -433 0.5 0.0 -169 0.0 0.0 -431 -8.74118200045e-07 -8.74118200045e-07 -648 0.413214415312 0.270958125591 -SURF 0x10 -mat 1 -refs 4 -171 1.0 0.0 -433 0.5 0.0 -648 0.413214415312 0.270958125591 -462 0.999994635582 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -648 0.413214415312 0.270958125591 -431 -8.74118200045e-07 -8.74118200045e-07 -168 0.0 0.0 -460 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -462 0.999994635582 0.500000178814 -648 0.413214415312 0.270958125591 -460 0.5 0.5 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -441 0.5 0.0 -190 0.0 0.0 -440 0.0 0.0 -649 0.251867949963 0.251867949963 -SURF 0x10 -mat 1 -refs 4 -188 1.0 0.0 -441 0.5 0.0 -649 0.251867949963 0.251867949963 -476 1.00000166893 0.499999523163 -SURF 0x10 -mat 1 -refs 4 -649 0.251867949963 0.251867949963 -440 0.0 0.0 -174 0.0 0.0 -466 0.499999552965 0.499999552965 -SURF 0x10 -mat 1 -refs 4 -476 1.00000166893 0.499999523163 -649 0.251867949963 0.251867949963 -466 0.499999552965 0.499999552965 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -447 0.50000244379 5.26163262293e-07 -177 0.0 0.0 -444 -5.74012005927e-07 -5.74012005927e-07 -650 0.256190061569 0.256190061569 -SURF 0x10 -mat 1 -refs 4 -176 1.0 0.0 -447 0.50000244379 5.26163262293e-07 -650 0.256190061569 0.256190061569 -467 1.00000524521 0.500000536442 -SURF 0x10 -mat 1 -refs 4 -650 0.256190061569 0.256190061569 -444 -5.74012005927e-07 -5.74012005927e-07 -179 0.0 0.0 -468 0.499999493361 0.499999493361 -SURF 0x10 -mat 1 -refs 4 -467 1.00000524521 0.500000536442 -650 0.256190061569 0.256190061569 -468 0.499999493361 0.499999493361 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -329 0.500000417233 0.0 -88 0.0 0.0 -570 0.500000476837 0.500000298023 -651 0.498746216297 0.023163786158 -SURF 0x10 -mat 1 -refs 4 -90 1.0 0.0 -329 0.500000417233 0.0 -651 0.498746216297 0.023163786158 -568 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -651 0.498746216297 0.023163786158 -570 0.500000476837 0.500000298023 -96 1.0 1.0 -355 1.00000047684 0.499999910593 -SURF 0x10 -mat 1 -refs 4 -568 1.0 0.0 -651 0.498746216297 0.023163786158 -355 1.00000047684 0.499999910593 -112 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -569 0.5 0.5 -113 1.0 1.0 -354 1.00000047684 0.499999791384 -652 0.500910520554 0.476342439651 -SURF 0x10 -mat 1 -refs 4 -91 0.0 0.0 -569 0.5 0.5 -652 0.500910520554 0.476342439651 -326 4.65776508918e-07 4.65776508918e-07 -SURF 0x10 -mat 1 -refs 4 -652 0.500910520554 0.476342439651 -354 1.00000047684 0.499999791384 -97 1.0 0.0 -571 0.5 3.75045800638e-07 -SURF 0x10 -mat 1 -refs 4 -326 4.65776508918e-07 4.65776508918e-07 -652 0.500910520554 0.476342439651 -571 0.5 3.75045800638e-07 -89 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -571 0.5 0.5 -97 1.0 1.0 -353 1.0 0.500000238419 -653 0.500883340836 0.500883340836 -SURF 0x10 -mat 1 -refs 4 -89 0.0 0.0 -571 0.5 0.5 -653 0.500883340836 0.500883340836 -322 -3.28620355754e-12 -3.28620355754e-12 -SURF 0x10 -mat 1 -refs 4 -653 0.500883340836 0.500883340836 -353 1.0 0.500000238419 -99 1.0 0.0 -572 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -322 -3.28620355754e-12 -3.28620355754e-12 -653 0.500883340836 0.500883340836 -572 0.5 0.0 -73 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -325 0.500000298023 0.0 -72 0.0 0.0 -573 0.5 0.499999791384 -654 0.577424824238 0.0 -SURF 0x10 -mat 1 -refs 4 -88 1.0 0.0 -325 0.500000298023 0.0 -654 0.577424824238 0.0 -570 1.00000011921 0.0 -SURF 0x10 -mat 1 -refs 4 -654 0.577424824238 0.0 -573 0.5 0.499999791384 -98 1.0 1.0 -352 0.999999523163 0.499999731779 -SURF 0x10 -mat 1 -refs 4 -570 1.00000011921 0.0 -654 0.577424824238 0.0 -352 0.999999523163 0.499999731779 -96 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -574 0.499999523163 2.99620228361e-06 -82 0.0 0.0 -308 -4.65537851824e-07 -4.65537851824e-07 -655 0.499102473259 0.499102473259 -SURF 0x10 -mat 1 -refs 4 -108 1.0 0.0 -574 0.499999523163 2.99620228361e-06 -655 0.499102473259 0.499102473259 -348 1.0 0.500000953674 -SURF 0x10 -mat 1 -refs 4 -655 0.499102473259 0.499102473259 -308 -4.65537851824e-07 -4.65537851824e-07 -81 0.0 0.0 -576 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -348 1.0 0.500000953674 -655 0.499102473259 0.499102473259 -576 0.5 0.5 -106 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -347 1.00000047684 0.500003755093 -107 1.0 0.0 -577 1.0 0.0 -656 0.609612703323 0.0 -SURF 0x10 -mat 1 -refs 4 -109 1.0 1.0 -347 1.00000047684 0.500003755093 -656 0.609612703323 0.0 -575 0.499999970198 0.500000417233 -SURF 0x10 -mat 1 -refs 4 -656 0.609612703323 0.0 -577 1.0 0.0 -80 1.0 0.0 -307 0.500001430511 0.0 -SURF 0x10 -mat 1 -refs 4 -575 0.499999970198 0.500000417233 -656 0.609612703323 0.0 -307 0.500001430511 0.0 -83 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -576 0.5 0.0 -81 0.0 0.0 -306 -5.02187354201e-11 -5.02187354201e-11 -657 0.499285936356 0.499285936356 -SURF 0x10 -mat 1 -refs 4 -106 1.0 0.0 -576 0.5 0.0 -657 0.499285936356 0.499285936356 -346 1.00000047684 0.499997854233 -SURF 0x10 -mat 1 -refs 4 -657 0.499285936356 0.499285936356 -306 -5.02187354201e-11 -5.02187354201e-11 -79 0.0 0.0 -578 0.500000476837 0.500000476837 -SURF 0x10 -mat 1 -refs 4 -346 1.00000047684 0.499997854233 -657 0.499285936356 0.499285936356 -578 0.500000476837 0.500000476837 -105 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -345 1.0 0.5 -104 1.0 0.0 -579 0.99999922514 0.0 -658 0.627924203873 0.0 -SURF 0x10 -mat 1 -refs 4 -107 1.0 1.0 -345 1.0 0.5 -658 0.627924203873 0.0 -577 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -658 0.627924203873 0.0 -579 0.99999922514 0.0 -78 1.0 0.0 -305 0.49999922514 0.0 -SURF 0x10 -mat 1 -refs 4 -577 0.5 0.5 -658 0.627924203873 0.0 -305 0.49999922514 0.0 -80 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -578 0.500000476837 -8.37589084313e-07 -79 0.0 0.0 -304 -4.62915068056e-07 -4.62915068056e-07 -659 0.499501466751 0.499501466751 -SURF 0x10 -mat 1 -refs 4 -105 1.0 0.0 -578 0.500000476837 -8.37589084313e-07 -659 0.499501466751 0.499501466751 -344 0.999999523163 0.500000655651 -SURF 0x10 -mat 1 -refs 4 -659 0.499501466751 0.499501466751 -304 -4.62915068056e-07 -4.62915068056e-07 -77 0.0 0.0 -580 0.500000476837 0.500000476837 -SURF 0x10 -mat 1 -refs 4 -344 0.999999523163 0.500000655651 -659 0.499501466751 0.499501466751 -580 0.500000476837 0.500000476837 -103 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -343 1.0 0.5 -102 1.0 0.0 -581 0.999999761581 0.0 -660 0.605253040791 0.0 -SURF 0x10 -mat 1 -refs 4 -104 1.0 1.0 -343 1.0 0.5 -660 0.605253040791 0.0 -579 0.500000476837 0.500001430511 -SURF 0x10 -mat 1 -refs 4 -660 0.605253040791 0.0 -581 0.999999761581 0.0 -76 1.0 0.0 -303 0.499999403954 0.0 -SURF 0x10 -mat 1 -refs 4 -579 0.500000476837 0.500001430511 -660 0.605253040791 0.0 -303 0.499999403954 0.0 -78 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -572 0.5 0.5 -99 1.0 1.0 -340 0.999999523163 0.500000178814 -661 0.500178039074 0.500178039074 -SURF 0x10 -mat 1 -refs 4 -73 0.0 0.0 -572 0.5 0.5 -661 0.500178039074 0.500178039074 -320 4.622696963e-07 4.622696963e-07 -SURF 0x10 -mat 1 -refs 4 -661 0.500178039074 0.500178039074 -340 0.999999523163 0.500000178814 -101 1.0 0.0 -582 0.5 2.34866220694e-07 -SURF 0x10 -mat 1 -refs 4 -320 4.622696963e-07 4.622696963e-07 -661 0.500178039074 0.500178039074 -582 0.5 2.34866220694e-07 -75 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -580 0.500000476837 -4.74324110655e-07 -77 0.0 0.0 -301 -4.61970671495e-07 -4.61970671495e-07 -662 0.499510288239 0.499510288239 -SURF 0x10 -mat 1 -refs 4 -103 1.0 0.0 -580 0.500000476837 -4.74324110655e-07 -662 0.499510288239 0.499510288239 -342 1.0 0.499999701977 -SURF 0x10 -mat 1 -refs 4 -662 0.499510288239 0.499510288239 -301 -4.61970671495e-07 -4.61970671495e-07 -75 0.0 0.0 -582 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -342 1.0 0.499999701977 -662 0.499510288239 0.499510288239 -582 0.5 0.5 -101 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -341 1.0 0.5 -100 1.0 0.0 -583 1.00000023842 0.0 -663 0.579814970493 0.0 -SURF 0x10 -mat 1 -refs 4 -102 1.0 1.0 -341 1.0 0.5 -663 0.579814970493 0.0 -581 0.5 0.500000298023 -SURF 0x10 -mat 1 -refs 4 -663 0.579814970493 0.0 -583 1.00000023842 0.0 -74 1.0 0.0 -298 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -581 0.5 0.500000298023 -663 0.579814970493 0.0 -298 0.5 0.0 -76 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -319 0.500000178814 0.0 -74 0.0 0.0 -583 0.5 0.499999761581 -664 0.572734117508 0.0 -SURF 0x10 -mat 1 -refs 4 -72 1.0 0.0 -319 0.500000178814 0.0 -664 0.572734117508 0.0 -573 1.00000023842 0.0 -SURF 0x10 -mat 1 -refs 4 -664 0.572734117508 0.0 -583 0.5 0.499999761581 -100 1.0 1.0 -339 1.0 0.499999761581 -SURF 0x10 -mat 1 -refs 4 -573 1.00000023842 0.0 -664 0.572734117508 0.0 -339 1.0 0.499999761581 -98 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -592 0.5 0.5 -64 1.0 1.0 -291 1.0 0.5 -665 0.499999821186 0.499999821186 -SURF 0x10 -mat 1 -refs 4 -40 0.0 0.0 -592 0.5 0.5 -665 0.499999821186 0.499999821186 -264 4.49748904785e-09 4.49748904785e-09 -SURF 0x10 -mat 1 -refs 4 -665 0.499999821186 0.499999821186 -291 1.0 0.5 -62 1.0 0.0 -593 0.499999970198 -2.8312449607e-10 -SURF 0x10 -mat 1 -refs 4 -264 4.49748904785e-09 4.49748904785e-09 -665 0.499999821186 0.499999821186 -593 0.499999970198 -2.8312449607e-10 -38 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -224 0.500000417233 0.500000417233 -22 1.0 1.0 -514 1.00000047684 0.5 -666 0.486777722836 0.486777722836 -SURF 0x10 -mat 1 -refs 4 -20 0.0 0.0 -224 0.500000417233 0.500000417233 -666 0.486777722836 0.486777722836 -228 -1.8017796144e-09 -1.8017796144e-09 -SURF 0x10 -mat 1 -refs 4 -666 0.486777722836 0.486777722836 -514 1.00000047684 0.5 -46 1.0 0.0 -512 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -228 -1.8017796144e-09 -1.8017796144e-09 -666 0.486777722836 0.486777722836 -512 0.5 0.0 -25 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -225 0.499999940395 0.499999940395 -23 1.0 1.0 -513 1.0 0.499999970198 -667 0.33244946599 0.33244946599 -SURF 0x10 -mat 1 -refs 4 -22 0.0 0.0 -225 0.499999940395 0.499999940395 -667 0.33244946599 0.33244946599 -514 -1.68193570182e-09 -1.68193570182e-09 -SURF 0x10 -mat 1 -refs 4 -667 0.33244946599 0.33244946599 -513 1.0 0.499999970198 -47 1.0 0.0 -270 0.500000119209 -1.58291487556e-11 -SURF 0x10 -mat 1 -refs 4 -514 -1.68193570182e-09 -1.68193570182e-09 -667 0.33244946599 0.33244946599 -270 0.500000119209 -1.58291487556e-11 -46 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -227 0.5 0.5 -24 1.0 1.0 -511 1.0 0.5 -668 0.50010150671 0.50010150671 -SURF 0x10 -mat 1 -refs 4 -21 0.0 0.0 -227 0.5 0.5 -668 0.50010150671 0.50010150671 -226 5.52406731469e-11 5.52406731469e-11 -SURF 0x10 -mat 1 -refs 4 -668 0.50010150671 0.50010150671 -511 1.0 0.5 -47 1.0 0.0 -513 0.5 7.88152487718e-10 -SURF 0x10 -mat 1 -refs 4 -226 5.52406731469e-11 5.52406731469e-11 -668 0.50010150671 0.50010150671 -513 0.5 7.88152487718e-10 -23 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -406 0.499999344349 0.0 -154 0.0 0.0 -450 0.500000178814 0.500002861023 -669 0.627667188644 0.0 -SURF 0x10 -mat 1 -refs 4 -156 1.0 0.0 -406 0.499999344349 0.0 -669 0.627667188644 0.0 -445 1.00000190735 0.0 -SURF 0x10 -mat 1 -refs 4 -669 0.627667188644 0.0 -450 0.500000178814 0.500002861023 -181 1.0 1.0 -449 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -445 1.00000190735 0.0 -669 0.627667188644 0.0 -449 1.0 0.5 -179 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -443 0.5 0.5 -177 1.0 1.0 -447 1.00000023842 0.500004768372 -670 0.499937713146 0.499937713146 -SURF 0x10 -mat 1 -refs 4 -158 0.0 0.0 -443 0.5 0.5 -670 0.499937713146 0.499937713146 -409 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -670 0.499937713146 0.499937713146 -447 1.00000023842 0.500004768372 -176 1.0 0.0 -446 0.499999791384 -4.78465426568e-06 -SURF 0x10 -mat 1 -refs 4 -409 0.0 0.0 -670 0.499937713146 0.499937713146 -446 0.499999791384 -4.78465426568e-06 -159 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -411 0.50000077486 0.0 -156 0.0 0.0 -445 0.499999850988 0.499995052814 -671 0.636126160622 0.0 -SURF 0x10 -mat 1 -refs 4 -158 1.0 0.0 -411 0.50000077486 0.0 -671 0.636126160622 0.0 -443 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -671 0.636126160622 0.0 -445 0.499999850988 0.499995052814 -179 1.0 1.0 -444 0.999999821186 0.499996721745 -SURF 0x10 -mat 1 -refs 4 -443 1.0 0.0 -671 0.636126160622 0.0 -444 0.999999821186 0.499996721745 -177 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -435 0.500000119209 0.500000119209 -173 1.0 1.0 -434 0.999999821186 0.500003159046 -672 0.495647907257 0.495647907257 -SURF 0x10 -mat 1 -refs 4 -162 0.0 0.0 -435 0.500000119209 0.500000119209 -672 0.495647907257 0.495647907257 -421 -2.10951588997e-06 -2.10951588997e-06 -SURF 0x10 -mat 1 -refs 4 -672 0.495647907257 0.495647907257 -434 0.999999821186 0.500003159046 -170 1.0 0.0 -429 0.499998211861 -9.53951348492e-06 -SURF 0x10 -mat 1 -refs 4 -421 -2.10951588997e-06 -2.10951588997e-06 -672 0.495647907257 0.495647907257 -429 0.499998211861 -9.53951348492e-06 -165 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -422 0.499998420477 0.0 -166 0.0 0.0 -430 0.500000238419 0.500004172325 -673 0.642973661423 0.0 -SURF 0x10 -mat 1 -refs 4 -164 1.0 0.0 -422 0.499998420477 0.0 -673 0.642973661423 0.0 -432 0.999996721745 0.0 -SURF 0x10 -mat 1 -refs 4 -673 0.642973661423 0.0 -430 0.500000238419 0.500004172325 -169 1.0 1.0 -433 0.999998092651 0.500003159046 -SURF 0x10 -mat 1 -refs 4 -432 0.999996721745 0.0 -673 0.642973661423 0.0 -433 0.999998092651 0.500003159046 -171 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -424 0.5 0.0 -167 0.0 0.0 -427 0.5 0.499999165535 -674 0.619586110115 0.0 -SURF 0x10 -mat 1 -refs 4 -166 1.0 0.0 -424 0.5 0.0 -674 0.619586110115 0.0 -430 1.00000047684 0.0 -SURF 0x10 -mat 1 -refs 4 -674 0.619586110115 0.0 -427 0.5 0.499999165535 -168 1.0 1.0 -431 1.0 0.50000166893 -SURF 0x10 -mat 1 -refs 4 -430 1.00000047684 0.0 -674 0.619586110115 0.0 -431 1.0 0.50000166893 -169 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -426 0.499999523163 0.0 -165 0.0 0.0 -429 0.499998122454 0.499985337257 -675 0.647795319557 0.0 -SURF 0x10 -mat 1 -refs 4 -167 1.0 0.0 -426 0.499999523163 0.0 -675 0.647795319557 0.0 -427 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -675 0.647795319557 0.0 -429 0.499998122454 0.499985337257 -170 1.0 1.0 -428 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -427 1.0 0.0 -675 0.647795319557 0.0 -428 1.0 0.5 -168 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -364 0.500000953674 0.0 -122 0.0 0.0 -420 0.499998927116 0.499994456768 -676 0.614621341228 0.0 -SURF 0x10 -mat 1 -refs 4 -120 1.0 0.0 -364 0.500000953674 0.0 -676 0.614621341228 0.0 -425 1.00000095367 0.0 -SURF 0x10 -mat 1 -refs 4 -676 0.614621341228 0.0 -420 0.499998927116 0.499994456768 -165 1.0 1.0 -426 1.00000119209 0.500002026558 -SURF 0x10 -mat 1 -refs 4 -425 1.00000095367 0.0 -676 0.614621341228 0.0 -426 1.00000119209 0.500002026558 -167 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -367 0.5 0.0 -120 0.0 0.0 -425 0.5 0.500000178814 -677 0.578554034233 0.0 -SURF 0x10 -mat 1 -refs 4 -121 1.0 0.0 -367 0.5 0.0 -677 0.578554034233 0.0 -423 0.999999880791 0.0 -SURF 0x10 -mat 1 -refs 4 -677 0.578554034233 0.0 -425 0.5 0.500000178814 -167 1.0 1.0 -424 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -423 0.999999880791 0.0 -677 0.578554034233 0.0 -424 1.0 0.5 -166 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -369 0.499998629093 0.0 -121 0.0 0.0 -423 0.500000119209 0.500001788139 -678 0.609701395035 0.0 -SURF 0x10 -mat 1 -refs 4 -123 1.0 0.0 -369 0.499998629093 0.0 -678 0.609701395035 0.0 -419 0.999998629093 0.0 -SURF 0x10 -mat 1 -refs 4 -678 0.609701395035 0.0 -423 0.500000119209 0.500001788139 -166 1.0 1.0 -422 1.00000011921 0.500001788139 -SURF 0x10 -mat 1 -refs 4 -419 0.999998629093 0.0 -678 0.609701395035 0.0 -422 1.00000011921 0.500001788139 -164 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -379 0.5 0.0 -131 0.0 0.0 -405 0.499999910593 0.499999076128 -679 0.596390843391 0.0 -SURF 0x10 -mat 1 -refs 4 -129 1.0 0.0 -379 0.5 0.0 -679 0.596390843391 0.0 -410 0.999999523163 0.0 -SURF 0x10 -mat 1 -refs 4 -679 0.596390843391 0.0 -405 0.499999910593 0.499999076128 -156 1.0 1.0 -411 1.0 0.499999284744 -SURF 0x10 -mat 1 -refs 4 -410 0.999999523163 0.0 -679 0.596390843391 0.0 -411 1.0 0.499999284744 -158 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -410 0.500000119209 0.500000119209 -158 1.0 1.0 -409 1.0 0.5 -680 0.499653309584 0.499653309584 -SURF 0x10 -mat 1 -refs 4 -129 0.0 0.0 -410 0.500000119209 0.500000119209 -680 0.499653309584 0.499653309584 -382 -9.92566668856e-08 -9.92566668856e-08 -SURF 0x10 -mat 1 -refs 4 -680 0.499653309584 0.499653309584 -409 1.0 0.5 -159 1.0 0.0 -408 0.499999791384 -3.85637031286e-06 -SURF 0x10 -mat 1 -refs 4 -382 -9.92566668856e-08 -9.92566668856e-08 -680 0.499653309584 0.499653309584 -408 0.499999791384 -3.85637031286e-06 -128 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -385 0.5 0.0 -133 0.0 0.0 -402 0.5 0.500001072884 -681 0.580321311951 0.0 -SURF 0x10 -mat 1 -refs 4 -131 1.0 0.0 -385 0.5 0.0 -681 0.580321311951 0.0 -405 1.00000047684 0.0 -SURF 0x10 -mat 1 -refs 4 -681 0.580321311951 0.0 -402 0.5 0.500001072884 -154 1.0 1.0 -406 1.0 0.500000596046 -SURF 0x10 -mat 1 -refs 4 -405 1.00000047684 0.0 -681 0.580321311951 0.0 -406 1.0 0.500000596046 -156 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -381 0.5 0.5 -128 1.0 1.0 -384 1.00000047684 0.500012636185 -682 0.499195873737 0.499195873737 -SURF 0x10 -mat 1 -refs 4 -111 0.0 0.0 -381 0.5 0.5 -682 0.499195873737 0.499195873737 -349 -4.85450073029e-07 -4.85450073029e-07 -SURF 0x10 -mat 1 -refs 4 -682 0.499195873737 0.499195873737 -384 1.00000047684 0.500012636185 -130 1.0 0.0 -383 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -349 -4.85450073029e-07 -4.85450073029e-07 -682 0.499195873737 0.499195873737 -383 0.5 0.0 -109 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -378 0.5 0.5 -129 1.0 1.0 -382 1.0 0.5 -683 0.499884337187 0.499884337187 -SURF 0x10 -mat 1 -refs 4 -110 0.0 0.0 -378 0.5 0.5 -683 0.499884337187 0.499884337187 -350 -3.59374696668e-10 -3.59374696668e-10 -SURF 0x10 -mat 1 -refs 4 -683 0.499884337187 0.499884337187 -382 1.0 0.5 -128 1.0 0.0 -381 0.5 -1.66923584288e-07 -SURF 0x10 -mat 1 -refs 4 -350 -3.59374696668e-10 -3.59374696668e-10 -683 0.499884337187 0.499884337187 -381 0.5 -1.66923584288e-07 -111 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -351 0.5 0.0 -108 0.0 0.0 -380 0.5 0.499999970198 -684 0.568934082985 0.0 -SURF 0x10 -mat 1 -refs 4 -110 1.0 0.0 -351 0.5 0.0 -684 0.568934082985 0.0 -378 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -684 0.568934082985 0.0 -380 0.5 0.499999970198 -131 1.0 1.0 -379 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -378 1.0 0.0 -684 0.568934082985 0.0 -379 1.0 0.5 -129 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -360 0.5 0.0 -118 0.0 0.0 -366 0.5 0.500000953674 -685 0.566195130348 0.0 -SURF 0x10 -mat 1 -refs 4 -116 1.0 0.0 -360 0.5 0.0 -685 0.566195130348 0.0 -368 0.999999880791 0.0 -SURF 0x10 -mat 1 -refs 4 -685 0.566195130348 0.0 -366 0.5 0.500000953674 -121 1.0 1.0 -369 0.999999284744 0.499999910593 -SURF 0x10 -mat 1 -refs 4 -368 0.999999880791 0.0 -685 0.566195130348 0.0 -369 0.999999284744 0.499999910593 -123 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -363 0.500000655651 0.500000655651 -120 1.0 1.0 -367 1.0 0.5 -686 0.499136120081 0.499136120081 -SURF 0x10 -mat 1 -refs 4 -119 0.0 0.0 -363 0.500000655651 0.500000655651 -686 0.499136120081 0.499136120081 -361 6.37067898879e-07 6.37067898879e-07 -SURF 0x10 -mat 1 -refs 4 -686 0.499136120081 0.499136120081 -367 1.0 0.5 -121 1.0 0.0 -366 0.5 8.4228815922e-08 -SURF 0x10 -mat 1 -refs 4 -361 6.37067898879e-07 6.37067898879e-07 -686 0.499136120081 0.499136120081 -366 0.5 8.4228815922e-08 -118 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -365 0.500000655651 0.500000655651 -122 1.0 1.0 -364 1.0 0.499998986721 -687 0.493729352951 0.493729352951 -SURF 0x10 -mat 1 -refs 4 -117 0.0 0.0 -365 0.500000655651 0.500000655651 -687 0.493729352951 0.493729352951 -362 -8.47103898138e-09 -8.47103898138e-09 -SURF 0x10 -mat 1 -refs 4 -687 0.493729352951 0.493729352951 -364 1.0 0.499998986721 -120 1.0 0.0 -363 0.500000655651 6.1467511614e-07 -SURF 0x10 -mat 1 -refs 4 -362 -8.47103898138e-09 -8.47103898138e-09 -687 0.493729352951 0.493729352951 -363 0.500000655651 6.1467511614e-07 -119 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -482 0.5 0.5 -117 1.0 1.0 -362 1.0 0.499999284744 -688 0.501930058002 0.501930058002 -SURF 0x10 -mat 1 -refs 4 -93 0.0 0.0 -482 0.5 0.5 -688 0.501930058002 0.501930058002 -338 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -688 0.501930058002 0.501930058002 -362 1.0 0.499999284744 -119 1.0 0.0 -480 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -338 0.0 0.0 -688 0.501930058002 0.501930058002 -480 0.5 0.0 -95 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -480 0.5 0.5 -119 1.0 1.0 -361 1.00000047684 0.499998569489 -689 0.502086281776 0.502086281776 -SURF 0x10 -mat 1 -refs 4 -95 0.0 0.0 -480 0.5 0.5 -689 0.502086281776 0.502086281776 -336 -4.72511800353e-07 -4.72511800353e-07 -SURF 0x10 -mat 1 -refs 4 -689 0.502086281776 0.502086281776 -361 1.00000047684 0.499998569489 -118 1.0 0.0 -481 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -336 -4.72511800353e-07 -4.72511800353e-07 -689 0.502086281776 0.502086281776 -481 0.5 0.0 -94 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -334 0.499999463558 0.0 -94 0.0 0.0 -481 0.5 0.5 -690 0.552353620529 0.0 -SURF 0x10 -mat 1 -refs 4 -92 1.0 0.0 -334 0.499999463558 0.0 -690 0.552353620529 0.0 -483 1.00000047684 0.0 -SURF 0x10 -mat 1 -refs 4 -690 0.552353620529 0.0 -481 0.5 0.5 -118 1.0 1.0 -360 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -483 1.00000047684 0.0 -690 0.552353620529 0.0 -360 1.0 0.5 -116 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -484 0.500000476837 0.500000476837 -114 1.0 1.0 -359 1.00000047684 0.500000238419 -691 0.500897824764 0.500897824764 -SURF 0x10 -mat 1 -refs 4 -90 0.0 0.0 -484 0.500000476837 0.500000476837 -691 0.500897824764 0.500897824764 -333 2.51519471917e-10 2.51519471917e-10 -SURF 0x10 -mat 1 -refs 4 -691 0.500897824764 0.500897824764 -359 1.00000047684 0.500000238419 -117 1.0 0.0 -482 0.5 -7.05431205006e-07 -SURF 0x10 -mat 1 -refs 4 -333 2.51519471917e-10 2.51519471917e-10 -691 0.500897824764 0.500897824764 -482 0.5 -7.05431205006e-07 -93 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -330 0.500000238419 0.0 -92 0.0 0.0 -483 0.5 0.499999314547 -692 0.552870571613 0.0 -SURF 0x10 -mat 1 -refs 4 -91 1.0 0.0 -330 0.500000238419 0.0 -692 0.552870571613 0.0 -485 1.00000023842 0.0 -SURF 0x10 -mat 1 -refs 4 -692 0.552870571613 0.0 -483 0.5 0.499999314547 -116 1.0 1.0 -358 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -485 1.00000023842 0.0 -692 0.552870571613 0.0 -358 1.0 0.5 -115 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -317 0.500000238419 0.0 -84 0.0 0.0 -488 0.499999970198 0.5 -693 0.554753005505 0.0 -SURF 0x10 -mat 1 -refs 4 -86 1.0 0.0 -317 0.500000238419 0.0 -693 0.554753005505 0.0 -486 0.999999761581 0.0 -SURF 0x10 -mat 1 -refs 4 -693 0.554753005505 0.0 -488 0.499999970198 0.5 -108 1.0 1.0 -351 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -486 0.999999761581 0.0 -693 0.554753005505 0.0 -351 1.0 0.5 -110 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -486 0.500000476837 0.500000476837 -110 1.0 1.0 -350 1.0 0.500000059605 -694 0.498737692833 0.498737692833 -SURF 0x10 -mat 1 -refs 4 -86 0.0 0.0 -486 0.500000476837 0.500000476837 -694 0.498737692833 0.498737692833 -315 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -694 0.498737692833 0.498737692833 -350 1.0 0.500000059605 -111 1.0 0.0 -487 0.499999523163 -3.54182304818e-07 -SURF 0x10 -mat 1 -refs 4 -315 0.0 0.0 -694 0.498737692833 0.498737692833 -487 0.499999523163 -3.54182304818e-07 -87 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -487 0.499999523163 0.499999523163 -111 1.0 1.0 -349 0.999999582767 0.499993979931 -695 0.499114274979 0.499114274979 -SURF 0x10 -mat 1 -refs 4 -87 0.0 0.0 -487 0.499999523163 0.499999523163 -695 0.499114274979 0.499114274979 -313 -4.69686881388e-07 -4.69686881388e-07 -SURF 0x10 -mat 1 -refs 4 -695 0.499114274979 0.499114274979 -349 0.999999582767 0.499993979931 -109 1.0 0.0 -489 0.499999523163 -6.90623846822e-06 -SURF 0x10 -mat 1 -refs 4 -313 -4.69686881388e-07 -4.69686881388e-07 -695 0.499114274979 0.499114274979 -489 0.499999523163 -6.90623846822e-06 -85 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -272 0.499999493361 0.0 -50 0.0 0.0 -332 0.499999850988 0.499999284744 -696 0.525528669357 0.0 -SURF 0x10 -mat 1 -refs 4 -48 1.0 0.0 -272 0.499999493361 0.0 -696 0.525528669357 0.0 -337 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -696 0.525528669357 0.0 -332 0.499999850988 0.499999284744 -93 1.0 1.0 -338 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -337 1.0 0.0 -696 0.525528669357 0.0 -338 1.0 0.5 -95 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -274 0.500000178814 0.0 -48 0.0 0.0 -337 0.500000178814 0.499999880791 -697 0.499886542559 0.0022679772228 -SURF 0x10 -mat 1 -refs 4 -49 1.0 0.0 -274 0.500000178814 0.0 -697 0.499886542559 0.0022679772228 -335 1.00000023842 0.0 -SURF 0x10 -mat 1 -refs 4 -697 0.499886542559 0.0022679772228 -337 0.500000178814 0.499999880791 -95 1.0 1.0 -336 0.999999642372 0.499999701977 -SURF 0x10 -mat 1 -refs 4 -335 1.00000023842 0.0 -697 0.499886542559 0.0022679772228 -336 0.999999642372 0.499999701977 -94 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -335 0.500000178814 0.500000178814 -94 1.0 1.0 -334 1.0 0.500000536442 -698 0.500021159649 0.500021159649 -SURF 0x10 -mat 1 -refs 4 -49 0.0 0.0 -335 0.500000178814 0.500000178814 -698 0.500021159649 0.500021159649 -275 1.65864804558e-07 1.65864804558e-07 -SURF 0x10 -mat 1 -refs 4 -698 0.500021159649 0.500021159649 -334 1.0 0.500000536442 -92 1.0 0.0 -331 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -275 1.65864804558e-07 1.65864804558e-07 -698 0.500021159649 0.500021159649 -331 0.5 0.0 -51 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -276 0.5 0.0 -53 0.0 0.0 -328 0.5 0.5 -699 0.525595843792 0.0 -SURF 0x10 -mat 1 -refs 4 -50 1.0 0.0 -276 0.5 0.0 -699 0.525595843792 0.0 -332 1.00000047684 0.0 -SURF 0x10 -mat 1 -refs 4 -699 0.525595843792 0.0 -328 0.5 0.5 -90 1.0 1.0 -333 1.0 0.500000536442 -SURF 0x10 -mat 1 -refs 4 -332 1.00000047684 0.0 -699 0.525595843792 0.0 -333 1.0 0.500000536442 -93 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -331 0.5 0.5 -92 1.0 1.0 -330 0.999999642372 0.499999463558 -700 0.499989807606 0.499989807606 -SURF 0x10 -mat 1 -refs 4 -51 0.0 0.0 -331 0.5 0.5 -700 0.499989807606 0.499989807606 -277 1.65830542187e-07 1.65830542187e-07 -SURF 0x10 -mat 1 -refs 4 -700 0.499989807606 0.499989807606 -330 0.999999642372 0.499999463558 -91 1.0 0.0 -327 0.499999821186 -5.43558371646e-07 -SURF 0x10 -mat 1 -refs 4 -277 1.65830542187e-07 1.65830542187e-07 -700 0.499989807606 0.499989807606 -327 0.499999821186 -5.43558371646e-07 -52 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -324 0.500000178814 0.500000178814 -88 1.0 1.0 -329 1.0 0.499999582767 -701 0.500061869621 0.500061869621 -SURF 0x10 -mat 1 -refs 4 -55 0.0 0.0 -324 0.500000178814 0.500000178814 -701 0.500061869621 0.500061869621 -278 1.66120585732e-07 1.66120585732e-07 -SURF 0x10 -mat 1 -refs 4 -701 0.500061869621 0.500061869621 -329 1.0 0.499999582767 -90 1.0 0.0 -328 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -278 1.66120585732e-07 1.66120585732e-07 -701 0.500061869621 0.500061869621 -328 0.5 0.0 -53 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -279 0.5 0.0 -52 0.0 0.0 -327 0.499999850988 0.499999433756 -702 0.525634169579 0.0 -SURF 0x10 -mat 1 -refs 4 -54 1.0 0.0 -279 0.5 0.0 -702 0.525634169579 0.0 -323 1.00000035763 0.0 -SURF 0x10 -mat 1 -refs 4 -702 0.525634169579 0.0 -327 0.499999850988 0.499999433756 -91 1.0 1.0 -326 1.00000023842 0.500000298023 -SURF 0x10 -mat 1 -refs 4 -323 1.00000035763 0.0 -702 0.525634169579 0.0 -326 1.00000023842 0.500000298023 -89 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -318 0.5 0.5 -72 1.0 1.0 -325 1.0 0.499999701977 -703 0.500108361244 0.500108361244 -SURF 0x10 -mat 1 -refs 4 -71 0.0 0.0 -318 0.5 0.5 -703 0.500108361244 0.500108361244 -280 1.66147628988e-07 1.66147628988e-07 -SURF 0x10 -mat 1 -refs 4 -703 0.500108361244 0.500108361244 -325 1.0 0.499999701977 -88 1.0 0.0 -324 0.500000178814 1.61930771014e-08 -SURF 0x10 -mat 1 -refs 4 -280 1.66147628988e-07 1.66147628988e-07 -703 0.500108361244 0.500108361244 -324 0.500000178814 1.61930771014e-08 -55 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -281 0.5 0.0 -54 0.0 0.0 -323 0.5 0.499999701977 -704 0.525683283806 0.0 -SURF 0x10 -mat 1 -refs 4 -70 1.0 0.0 -281 0.5 0.0 -704 0.525683283806 0.0 -321 1.00000011921 0.0 -SURF 0x10 -mat 1 -refs 4 -704 0.525683283806 0.0 -323 0.5 0.499999701977 -89 1.0 1.0 -322 1.0 0.500000119209 -SURF 0x10 -mat 1 -refs 4 -321 1.00000011921 0.0 -704 0.525683283806 0.0 -322 1.0 0.500000119209 -73 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -282 0.5 0.0 -70 0.0 0.0 -321 0.5 0.499999821186 -705 0.525634646416 0.0 -SURF 0x10 -mat 1 -refs 4 -68 1.0 0.0 -282 0.5 0.0 -705 0.525634646416 0.0 -302 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -705 0.525634646416 0.0 -321 0.5 0.499999821186 -73 1.0 1.0 -320 1.00000035763 0.500000417233 -SURF 0x10 -mat 1 -refs 4 -302 1.0 0.0 -705 0.525634646416 0.0 -320 1.00000035763 0.500000417233 -75 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -297 0.5 0.5 -74 1.0 1.0 -319 1.0 0.499999821186 -706 0.500047206879 0.500047206879 -SURF 0x10 -mat 1 -refs 4 -69 0.0 0.0 -297 0.5 0.5 -706 0.500047206879 0.500047206879 -283 1.9995050754e-11 1.9995050754e-11 -SURF 0x10 -mat 1 -refs 4 -706 0.500047206879 0.500047206879 -319 1.0 0.499999821186 -72 1.0 0.0 -318 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -283 1.9995050754e-11 1.9995050754e-11 -706 0.500047206879 0.500047206879 -318 0.5 0.0 -71 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -284 0.5 0.0 -59 0.0 0.0 -311 0.499999821186 0.499999850988 -707 0.525880157948 0.0 -SURF 0x10 -mat 1 -refs 4 -57 1.0 0.0 -284 0.5 0.0 -707 0.525880157948 0.0 -316 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -707 0.525880157948 0.0 -311 0.499999821186 0.499999850988 -84 1.0 1.0 -317 0.999999642372 0.499999642372 -SURF 0x10 -mat 1 -refs 4 -316 1.0 0.0 -707 0.525880157948 0.0 -317 0.999999642372 0.499999642372 -86 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -316 0.500000178814 0.500000178814 -86 1.0 1.0 -315 1.0 0.5 -708 0.499934643507 0.499934643507 -SURF 0x10 -mat 1 -refs 4 -57 0.0 0.0 -316 0.500000178814 0.500000178814 -708 0.499934643507 0.499934643507 -285 1.68088497765e-13 1.68088497765e-13 -SURF 0x10 -mat 1 -refs 4 -708 0.499934643507 0.499934643507 -315 1.0 0.5 -87 1.0 0.0 -314 0.499999821186 -2.48488483123e-08 -SURF 0x10 -mat 1 -refs 4 -285 1.68088497765e-13 1.68088497765e-13 -708 0.499934643507 0.499934643507 -314 0.499999821186 -2.48488483123e-08 -56 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -314 0.499999821186 0.499999821186 -87 1.0 1.0 -313 0.999999642372 0.499998778105 -709 0.499961048365 0.499961048365 -SURF 0x10 -mat 1 -refs 4 -56 0.0 0.0 -314 0.499999821186 0.499999821186 -709 0.499961048365 0.499961048365 -286 3.50592710245e-12 3.50592710245e-12 -SURF 0x10 -mat 1 -refs 4 -709 0.499961048365 0.499961048365 -313 0.999999642372 0.499998778105 -85 1.0 0.0 -310 0.500000178814 9.73554620032e-07 -SURF 0x10 -mat 1 -refs 4 -286 3.50592710245e-12 3.50592710245e-12 -709 0.499961048365 0.499961048365 -310 0.500000178814 9.73554620032e-07 -58 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -295 0.500000178814 0.0 -68 0.0 0.0 -302 0.5 0.5 -710 0.525664389133 0.0 -SURF 0x10 -mat 1 -refs 4 -66 1.0 0.0 -295 0.500000178814 0.0 -710 0.525664389133 0.0 -300 1.00000023842 0.0 -SURF 0x10 -mat 1 -refs 4 -710 0.525664389133 0.0 -302 0.5 0.5 -75 1.0 1.0 -301 0.999999642372 0.499999791384 -SURF 0x10 -mat 1 -refs 4 -300 1.00000023842 0.0 -710 0.525664389133 0.0 -301 0.999999642372 0.499999791384 -77 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -299 0.5 0.5 -76 1.0 1.0 -298 1.0 0.5 -711 0.500015616417 0.500015616417 -SURF 0x10 -mat 1 -refs 4 -67 0.0 0.0 -299 0.5 0.5 -711 0.500015616417 0.500015616417 -296 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -711 0.500015616417 0.500015616417 -298 1.0 0.5 -74 1.0 0.0 -297 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -296 0.0 0.0 -711 0.500015616417 0.500015616417 -297 0.5 0.0 -69 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -490 0.5 0.5 -67 1.0 1.0 -296 1.0 0.5 -712 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -41 0.0 0.0 -490 0.5 0.5 -712 0.5 0.5 -269 -3.76376143793e-12 -3.76376143793e-12 -SURF 0x10 -mat 1 -refs 4 -712 0.5 0.5 -296 1.0 0.5 -69 1.0 0.0 -501 0.5 1.60568469632e-09 -SURF 0x10 -mat 1 -refs 4 -269 -3.76376143793e-12 -3.76376143793e-12 -712 0.5 0.5 -501 0.5 1.60568469632e-09 -43 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -268 0.499999940395 0.0 -42 0.0 0.0 -502 0.5 0.5 -713 0.526778519154 0.0 -SURF 0x10 -mat 1 -refs 4 -40 1.0 0.0 -268 0.499999940395 0.0 -713 0.526778519154 0.0 -491 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -713 0.526778519154 0.0 -502 0.5 0.5 -68 1.0 1.0 -295 1.0 0.499999821186 -SURF 0x10 -mat 1 -refs 4 -491 1.0 0.0 -713 0.526778519154 0.0 -295 1.0 0.499999821186 -66 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -492 0.5 0.5 -65 1.0 1.0 -294 0.999999940395 0.499999970198 -714 0.499999970198 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -39 0.0 0.0 -492 0.5 0.5 -714 0.499999970198 0.499999970198 -267 4.50115189565e-09 4.50115189565e-09 -SURF 0x10 -mat 1 -refs 4 -714 0.499999970198 0.499999970198 -294 0.999999940395 0.499999970198 -67 1.0 0.0 -490 0.5 1.99307208959e-07 -SURF 0x10 -mat 1 -refs 4 -267 4.50115189565e-09 4.50115189565e-09 -714 0.499999970198 0.499999970198 -490 0.5 1.99307208959e-07 -41 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -493 0.5 0.5 -63 1.0 1.0 -292 1.0 0.500000119209 -715 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -37 0.0 0.0 -493 0.5 0.5 -715 0.5 0.5 -263 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -715 0.5 0.5 -292 1.0 0.500000119209 -65 1.0 0.0 -492 0.499999970198 -1.35025956638e-07 -SURF 0x10 -mat 1 -refs 4 -263 0.0 0.0 -715 0.5 0.5 -492 0.499999970198 -1.35025956638e-07 -39 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -495 0.5 0.5 -60 1.0 1.0 -290 1.0 0.499999880791 -716 0.500000059605 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -34 0.0 0.0 -495 0.5 0.5 -716 0.500000059605 0.500000059605 -259 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -716 0.500000059605 0.500000059605 -290 1.0 0.499999880791 -63 1.0 0.0 -493 0.500000059605 3.09462571124e-08 -SURF 0x10 -mat 1 -refs 4 -259 0.0 0.0 -716 0.500000059605 0.500000059605 -493 0.500000059605 3.09462571124e-08 -37 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -256 0.5 0.0 -36 0.0 0.0 -494 0.5 0.500000119209 -717 0.52678078413 0.0 -SURF 0x10 -mat 1 -refs 4 -35 1.0 0.0 -256 0.5 0.0 -717 0.52678078413 0.0 -496 0.999999880791 0.0 -SURF 0x10 -mat 1 -refs 4 -717 0.52678078413 0.0 -494 0.5 0.500000119209 -62 1.0 1.0 -289 1.0 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -496 0.999999880791 0.0 -717 0.52678078413 0.0 -289 1.0 0.500000059605 -61 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -497 0.5 0.5 -58 1.0 1.0 -288 1.0 0.500000178814 -718 0.499999970198 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -32 0.0 0.0 -497 0.5 0.5 -718 0.499999970198 0.499999970198 -255 1.57048582038e-13 1.57048582038e-13 -SURF 0x10 -mat 1 -refs 4 -718 0.499999970198 0.499999970198 -288 1.0 0.500000178814 -60 1.0 0.0 -495 0.5 -1.6152867488e-07 -SURF 0x10 -mat 1 -refs 4 -255 1.57048582038e-13 1.57048582038e-13 -718 0.499999970198 0.499999970198 -495 0.5 -1.6152867488e-07 -34 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -252 0.5 0.0 -35 0.0 0.0 -496 0.499999970198 0.500000178814 -719 0.526780724525 0.0 -SURF 0x10 -mat 1 -refs 4 -33 1.0 0.0 -252 0.5 0.0 -719 0.526780724525 0.0 -499 0.999999880791 0.0 -SURF 0x10 -mat 1 -refs 4 -719 0.526780724525 0.0 -496 0.499999970198 0.500000178814 -61 1.0 1.0 -287 1.0 0.499999940395 -SURF 0x10 -mat 1 -refs 4 -499 0.999999880791 0.0 -719 0.526780724525 0.0 -287 1.0 0.499999940395 -59 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -498 0.5 0.5 -56 1.0 1.0 -286 1.0 0.499999672174 -720 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -30 0.0 0.0 -498 0.5 0.5 -720 0.5 0.5 -251 4.49967219041e-09 4.49967219041e-09 -SURF 0x10 -mat 1 -refs 4 -720 0.5 0.5 -286 1.0 0.499999672174 -58 1.0 0.0 -497 0.499999970198 -2.16302126432e-07 -SURF 0x10 -mat 1 -refs 4 -251 4.49967219041e-09 4.49967219041e-09 -720 0.5 0.5 -497 0.499999970198 -2.16302126432e-07 -32 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -500 0.5 0.5 -57 1.0 1.0 -285 1.0 0.5 -721 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -31 0.0 0.0 -500 0.5 0.5 -721 0.5 0.5 -249 4.49954518089e-09 4.49954518089e-09 -SURF 0x10 -mat 1 -refs 4 -721 0.5 0.5 -285 1.0 0.5 -56 1.0 0.0 -498 0.5 -4.70071590541e-08 -SURF 0x10 -mat 1 -refs 4 -249 4.49954518089e-09 4.49954518089e-09 -721 0.5 0.5 -498 0.5 -4.70071590541e-08 -30 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -246 0.5 0.0 -33 0.0 0.0 -499 0.499999970198 0.499999940395 -722 0.526778280735 0.0 -SURF 0x10 -mat 1 -refs 4 -31 1.0 0.0 -246 0.5 0.0 -722 0.526778280735 0.0 -500 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -722 0.526778280735 0.0 -499 0.499999970198 0.499999940395 -59 1.0 1.0 -284 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -500 1.0 0.0 -722 0.526778280735 0.0 -284 1.0 0.5 -57 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -501 0.5 0.5 -69 1.0 1.0 -283 1.0 0.500000178814 -723 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -43 0.0 0.0 -501 0.5 0.5 -723 0.5 0.5 -243 4.49970016803e-09 4.49970016803e-09 -SURF 0x10 -mat 1 -refs 4 -723 0.5 0.5 -283 1.0 0.500000178814 -71 1.0 0.0 -504 0.5 -1.5269505127e-07 -SURF 0x10 -mat 1 -refs 4 -243 4.49970016803e-09 4.49970016803e-09 -723 0.5 0.5 -504 0.5 -1.5269505127e-07 -45 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -242 0.500000119209 0.0 -44 0.0 0.0 -503 0.5 0.499999850988 -724 0.52678000927 0.0 -SURF 0x10 -mat 1 -refs 4 -42 1.0 0.0 -242 0.500000119209 0.0 -724 0.52678000927 0.0 -502 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -724 0.52678000927 0.0 -503 0.5 0.499999850988 -70 1.0 1.0 -282 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -502 1.0 0.0 -724 0.52678000927 0.0 -282 1.0 0.5 -68 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -240 0.500000119209 0.0 -28 0.0 0.0 -505 0.5 0.5 -725 0.526777803898 0.0 -SURF 0x10 -mat 1 -refs 4 -44 1.0 0.0 -240 0.500000119209 0.0 -725 0.526777803898 0.0 -503 1.00000011921 0.0 -SURF 0x10 -mat 1 -refs 4 -725 0.526777803898 0.0 -505 0.5 0.5 -54 1.0 1.0 -281 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -503 1.00000011921 0.0 -725 0.526777803898 0.0 -281 1.0 0.5 -70 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -504 0.5 0.5 -71 1.0 1.0 -280 1.0 0.5 -726 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -45 0.0 0.0 -504 0.5 0.5 -726 0.5 0.5 -237 4.5047801045e-09 4.5047801045e-09 -SURF 0x10 -mat 1 -refs 4 -726 0.5 0.5 -280 1.0 0.5 -55 1.0 0.0 -506 0.5 2.67510586127e-07 -SURF 0x10 -mat 1 -refs 4 -237 4.5047801045e-09 4.5047801045e-09 -726 0.5 0.5 -506 0.5 2.67510586127e-07 -29 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -236 0.5 0.0 -26 0.0 0.0 -507 0.5 0.5 -727 0.52678000927 0.0 -SURF 0x10 -mat 1 -refs 4 -28 1.0 0.0 -236 0.5 0.0 -727 0.52678000927 0.0 -505 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -727 0.52678000927 0.0 -507 0.5 0.5 -52 1.0 1.0 -279 1.0 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -505 1.0 0.0 -727 0.52678000927 0.0 -279 1.0 0.500000059605 -54 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -506 0.5 0.5 -55 1.0 1.0 -278 1.0 0.500000357628 -728 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -29 0.0 0.0 -506 0.5 0.5 -728 0.5 0.5 -233 -9.76264902253e-12 -9.76264902253e-12 -SURF 0x10 -mat 1 -refs 4 -728 0.5 0.5 -278 1.0 0.500000357628 -53 1.0 0.0 -508 0.499999970198 -3.75172305667e-07 -SURF 0x10 -mat 1 -refs 4 -233 -9.76264902253e-12 -9.76264902253e-12 -728 0.5 0.5 -508 0.499999970198 -3.75172305667e-07 -27 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -509 0.5 0.5 -51 1.0 1.0 -277 1.0 0.5 -729 0.499999970198 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -25 0.0 0.0 -509 0.5 0.5 -729 0.499999970198 0.499999970198 -232 -7.18236537953e-12 -7.18236537953e-12 -SURF 0x10 -mat 1 -refs 4 -729 0.499999970198 0.499999970198 -277 1.0 0.5 -52 1.0 0.0 -507 0.5 2.1121054905e-10 -SURF 0x10 -mat 1 -refs 4 -232 -7.18236537953e-12 -7.18236537953e-12 -729 0.499999970198 0.499999970198 -507 0.5 2.1121054905e-10 -26 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -229 0.5 0.0 -27 0.0 0.0 -508 0.5 0.499999493361 -730 0.526794433594 0.0 -SURF 0x10 -mat 1 -refs 4 -24 1.0 0.0 -229 0.5 0.0 -730 0.526794433594 0.0 -510 0.999999523163 0.0 -SURF 0x10 -mat 1 -refs 4 -730 0.526794433594 0.0 -508 0.5 0.499999493361 -53 1.0 1.0 -276 1.0 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -510 0.999999523163 0.0 -730 0.526794433594 0.0 -276 1.0 0.499999970198 -50 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -273 0.5 0.5 -49 1.0 1.0 -275 1.0 0.499999523163 -731 0.500000059605 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -46 0.0 0.0 -273 0.5 0.5 -731 0.500000059605 0.500000059605 -512 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -731 0.500000059605 0.500000059605 -275 1.0 0.499999523163 -51 1.0 0.0 -509 0.499999970198 4.87085856093e-07 -SURF 0x10 -mat 1 -refs 4 -512 0.0 0.0 -731 0.500000059605 0.500000059605 -509 0.499999970198 4.87085856093e-07 -25 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -270 0.499999850988 0.0 -47 0.0 0.0 -271 0.5 0.5 -732 0.557642161846 0.0 -SURF 0x10 -mat 1 -refs 4 -46 1.0 0.0 -270 0.499999850988 0.0 -732 0.557642161846 0.0 -273 0.999999761581 0.0 -SURF 0x10 -mat 1 -refs 4 -732 0.557642161846 0.0 -271 0.5 0.5 -48 1.0 1.0 -274 1.0 0.499999821186 -SURF 0x10 -mat 1 -refs 4 -273 0.999999761581 0.0 -732 0.557642161846 0.0 -274 1.0 0.499999821186 -49 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -511 0.5 0.0 -24 0.0 0.0 -510 0.5 0.500000536442 -733 0.527098596096 0.0 -SURF 0x10 -mat 1 -refs 4 -47 1.0 0.0 -511 0.5 0.0 -733 0.527098596096 0.0 -271 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -733 0.527098596096 0.0 -510 0.5 0.500000536442 -50 1.0 1.0 -272 1.0 0.500000536442 -SURF 0x10 -mat 1 -refs 4 -271 1.0 0.0 -733 0.527098596096 0.0 -272 1.0 0.500000536442 -48 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -266 0.5 0.5 -41 1.0 1.0 -269 1.0 0.499999850988 -734 0.500077605247 0.4989990592 -SURF 0x10 -mat 1 -refs 4 -4 0.0 0.0 -266 0.5 0.5 -734 0.500077605247 0.4989990592 -195 9.10086079848e-14 9.10086079848e-14 -SURF 0x10 -mat 1 -refs 4 -734 0.500077605247 0.4989990592 -269 1.0 0.499999850988 -43 1.0 0.0 -244 0.499999970198 1.50581882963e-07 -SURF 0x10 -mat 1 -refs 4 -195 9.10086079848e-14 9.10086079848e-14 -734 0.500077605247 0.4989990592 -244 0.499999970198 1.50581882963e-07 -2 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -197 0.500000059605 0.0 -3 0.0 0.0 -241 0.499999970198 0.500000119209 -735 0.500144779682 0.0 -SURF 0x10 -mat 1 -refs 4 -5 1.0 0.0 -197 0.500000059605 0.0 -735 0.500144779682 0.0 -265 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -735 0.500144779682 0.0 -241 0.499999970198 0.500000119209 -42 1.0 1.0 -268 1.0 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -265 1.0 0.0 -735 0.500144779682 0.0 -268 1.0 0.500000059605 -40 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -262 0.499999970198 0.499999970198 -39 1.0 1.0 -267 1.00000011921 0.500000119209 -736 0.500052392483 0.500052392483 -SURF 0x10 -mat 1 -refs 4 -6 0.0 0.0 -262 0.499999970198 0.499999970198 -736 0.500052392483 0.500052392483 -198 5.53577531037e-11 5.53577531037e-11 -SURF 0x10 -mat 1 -refs 4 -736 0.500052392483 0.500052392483 -267 1.00000011921 0.500000119209 -41 1.0 0.0 -266 0.5 8.87201210276e-08 -SURF 0x10 -mat 1 -refs 4 -198 5.53577531037e-11 5.53577531037e-11 -736 0.500052392483 0.500052392483 -266 0.5 8.87201210276e-08 -4 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -200 0.5 0.0 -5 0.0 0.0 -265 0.5 0.5 -737 0.500078439713 0.000257721054368 -SURF 0x10 -mat 1 -refs 4 -7 1.0 0.0 -200 0.5 0.0 -737 0.500078439713 0.000257721054368 -261 0.999999880791 0.0 -SURF 0x10 -mat 1 -refs 4 -737 0.500078439713 0.000257721054368 -265 0.5 0.5 -40 1.0 1.0 -264 1.0 0.500000119209 -SURF 0x10 -mat 1 -refs 4 -261 0.999999880791 0.0 -737 0.500078439713 0.000257721054368 -264 1.0 0.500000119209 -38 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -258 0.5 0.5 -37 1.0 1.0 -263 1.0 0.5 -738 0.500019669533 0.498987257481 -SURF 0x10 -mat 1 -refs 4 -8 0.0 0.0 -258 0.5 0.5 -738 0.500019669533 0.498987257481 -201 -5.53621315458e-11 -5.53621315458e-11 -SURF 0x10 -mat 1 -refs 4 -738 0.500019669533 0.498987257481 -263 1.0 0.5 -39 1.0 0.0 -262 0.499999970198 -2.33931984894e-09 -SURF 0x10 -mat 1 -refs 4 -201 -5.53621315458e-11 -5.53621315458e-11 -738 0.500019669533 0.498987257481 -262 0.499999970198 -2.33931984894e-09 -6 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -203 0.499999940395 0.0 -7 0.0 0.0 -261 0.500000059605 0.500000178814 -739 0.50005877018 0.0021026188042 -SURF 0x10 -mat 1 -refs 4 -9 1.0 0.0 -203 0.499999940395 0.0 -739 0.50005877018 0.0021026188042 -257 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -739 0.50005877018 0.0021026188042 -261 0.500000059605 0.500000178814 -38 1.0 1.0 -260 0.999999940395 0.5 -SURF 0x10 -mat 1 -refs 4 -257 1.0 0.0 -739 0.50005877018 0.0021026188042 -260 0.999999940395 0.5 -36 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -254 0.5 0.5 -34 1.0 1.0 -259 1.0 0.5 -740 0.499998569489 0.492397278547 -SURF 0x10 -mat 1 -refs 4 -11 0.0 0.0 -254 0.5 0.5 -740 0.499998569489 0.492397278547 -204 5.53618054178e-11 5.53618054178e-11 -SURF 0x10 -mat 1 -refs 4 -740 0.499998569489 0.492397278547 -259 1.0 0.5 -37 1.0 0.0 -258 0.5 8.2044432359e-10 -SURF 0x10 -mat 1 -refs 4 -204 5.53618054178e-11 5.53618054178e-11 -740 0.499998569489 0.492397278547 -258 0.5 8.2044432359e-10 -8 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -206 0.499999940395 0.0 -9 0.0 0.0 -257 0.5 0.5 -741 0.500044465065 0.00686141289771 -SURF 0x10 -mat 1 -refs 4 -10 1.0 0.0 -206 0.499999940395 0.0 -741 0.500044465065 0.00686141289771 -253 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -741 0.500044465065 0.00686141289771 -257 0.5 0.5 -36 1.0 1.0 -256 0.999999940395 0.499999940395 -SURF 0x10 -mat 1 -refs 4 -253 1.0 0.0 -741 0.500044465065 0.00686141289771 -256 0.999999940395 0.499999940395 -35 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -250 0.5 0.5 -32 1.0 1.0 -255 1.0 0.499999940395 -742 0.499993175268 0.499993175268 -SURF 0x10 -mat 1 -refs 4 -13 0.0 0.0 -250 0.5 0.5 -742 0.499993175268 0.499993175268 -207 -5.53642548473e-11 -5.53642548473e-11 -SURF 0x10 -mat 1 -refs 4 -742 0.499993175268 0.499993175268 -255 1.0 0.499999940395 -34 1.0 0.0 -254 0.5 -1.79376113962e-09 -SURF 0x10 -mat 1 -refs 4 -207 -5.53642548473e-11 -5.53642548473e-11 -742 0.499993175268 0.499993175268 -254 0.5 -1.79376113962e-09 -11 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -209 0.499999970198 0.0 -10 0.0 0.0 -253 0.499999970198 0.499999910593 -743 0.50046646595 0.0 -SURF 0x10 -mat 1 -refs 4 -12 1.0 0.0 -209 0.499999970198 0.0 -743 0.50046646595 0.0 -247 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -743 0.50046646595 0.0 -253 0.499999970198 0.499999910593 -35 1.0 1.0 -252 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -247 1.0 0.0 -743 0.50046646595 0.0 -252 1.0 0.5 -33 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -248 0.5 0.5 -30 1.0 1.0 -251 1.0 0.499999970198 -744 0.499992549419 0.491295009851 -SURF 0x10 -mat 1 -refs 4 -15 0.0 0.0 -248 0.5 0.5 -744 0.499992549419 0.491295009851 -210 5.53544675375e-11 5.53544675375e-11 -SURF 0x10 -mat 1 -refs 4 -744 0.499992549419 0.491295009851 -251 1.0 0.499999970198 -32 1.0 0.0 -250 0.499999970198 -7.68840493492e-08 -SURF 0x10 -mat 1 -refs 4 -210 5.53544675375e-11 5.53544675375e-11 -744 0.499992549419 0.491295009851 -250 0.499999970198 -7.68840493492e-08 -13 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -245 0.5 0.5 -31 1.0 1.0 -249 1.0 0.5 -745 0.499735534191 0.499735534191 -SURF 0x10 -mat 1 -refs 4 -14 0.0 0.0 -245 0.5 0.5 -745 0.499735534191 0.499735534191 -211 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -745 0.499735534191 0.499735534191 -249 1.0 0.5 -30 1.0 0.0 -248 0.5 1.28599448798e-11 -SURF 0x10 -mat 1 -refs 4 -211 0.0 0.0 -745 0.499735534191 0.499735534191 -248 0.5 1.28599448798e-11 -15 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -212 0.5 0.0 -12 0.0 0.0 -247 0.5 0.499999970198 -746 0.504721462727 0.0 -SURF 0x10 -mat 1 -refs 4 -14 1.0 0.0 -212 0.5 0.0 -746 0.504721462727 0.0 -245 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -746 0.504721462727 0.0 -247 0.5 0.499999970198 -33 1.0 1.0 -246 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -245 1.0 0.0 -746 0.504721462727 0.0 -246 1.0 0.5 -31 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -238 0.5 6.3819549645e-10 -0 0.0 0.0 -213 2.11196498115e-13 2.11196498115e-13 -747 0.500098407269 0.497135579586 -SURF 0x10 -mat 1 -refs 4 -45 1.0 0.0 -238 0.5 6.3819549645e-10 -747 0.500098407269 0.497135579586 -243 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -747 0.500098407269 0.497135579586 -213 2.11196498115e-13 2.11196498115e-13 -2 0.0 0.0 -244 0.499999970198 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -243 1.0 0.5 -747 0.500098407269 0.497135579586 -244 0.499999970198 0.499999970198 -43 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -214 0.499999850988 0.0 -1 0.0 0.0 -239 0.5 0.499999880791 -748 0.500070691109 0.00351682538167 -SURF 0x10 -mat 1 -refs 4 -3 1.0 0.0 -214 0.499999850988 0.0 -748 0.500070691109 0.00351682538167 -241 0.999999880791 0.0 -SURF 0x10 -mat 1 -refs 4 -748 0.500070691109 0.00351682538167 -239 0.5 0.499999880791 -44 1.0 1.0 -242 1.0 0.499999850988 -SURF 0x10 -mat 1 -refs 4 -241 0.999999880791 0.0 -748 0.500070691109 0.00351682538167 -242 1.0 0.499999850988 -42 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -215 0.5 0.0 -17 0.0 0.0 -235 0.5 0.5 -749 0.506132602692 0.0 -SURF 0x10 -mat 1 -refs 4 -1 1.0 0.0 -215 0.5 0.0 -749 0.506132602692 0.0 -239 1.00000011921 0.0 -SURF 0x10 -mat 1 -refs 4 -749 0.506132602692 0.0 -235 0.5 0.5 -28 1.0 1.0 -240 1.0 0.499999880791 -SURF 0x10 -mat 1 -refs 4 -239 1.00000011921 0.0 -749 0.506132602692 0.0 -240 1.0 0.499999880791 -44 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -238 0.5 0.5 -45 1.0 1.0 -237 1.0 0.500000119209 -750 0.50013333559 0.50013333559 -SURF 0x10 -mat 1 -refs 4 -0 0.0 0.0 -238 0.5 0.5 -750 0.50013333559 0.50013333559 -217 5.50568236835e-11 5.50568236835e-11 -SURF 0x10 -mat 1 -refs 4 -750 0.50013333559 0.50013333559 -237 1.0 0.500000119209 -29 1.0 0.0 -234 0.5 2.39011626491e-07 -SURF 0x10 -mat 1 -refs 4 -217 5.50568236835e-11 5.50568236835e-11 -750 0.50013333559 0.50013333559 -234 0.5 2.39011626491e-07 -16 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -218 0.499999672174 0.0 -19 0.0 0.0 -231 0.5 0.500000357628 -751 0.500058472157 0.00472383154556 -SURF 0x10 -mat 1 -refs 4 -17 1.0 0.0 -218 0.499999672174 0.0 -751 0.500058472157 0.00472383154556 -235 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -751 0.500058472157 0.00472383154556 -231 0.5 0.500000357628 -26 1.0 1.0 -236 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -235 1.0 0.0 -751 0.500058472157 0.00472383154556 -236 1.0 0.5 -28 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -234 0.5 0.5 -29 1.0 1.0 -233 1.0 0.499999672174 -752 0.500089585781 0.495344668627 -SURF 0x10 -mat 1 -refs 4 -16 0.0 0.0 -234 0.5 0.5 -752 0.500089585781 0.495344668627 -220 4.75710941993e-13 4.75710941993e-13 -SURF 0x10 -mat 1 -refs 4 -752 0.500089585781 0.495344668627 -233 1.0 0.499999672174 -27 1.0 0.0 -230 0.5 -3.35125349693e-07 -SURF 0x10 -mat 1 -refs 4 -220 4.75710941993e-13 4.75710941993e-13 -752 0.500089585781 0.495344668627 -230 0.5 -3.35125349693e-07 -18 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -221 0.5 0.0 -20 0.0 0.0 -228 0.5 0.5 -753 0.500049293041 0.00849551800638 -SURF 0x10 -mat 1 -refs 4 -19 1.0 0.0 -221 0.5 0.0 -753 0.500049293041 0.00849551800638 -231 0.999999523163 0.0 -SURF 0x10 -mat 1 -refs 4 -753 0.500049293041 0.00849551800638 -228 0.5 0.5 -25 1.0 1.0 -232 1.0 0.500000417233 -SURF 0x10 -mat 1 -refs 4 -231 0.999999523163 0.0 -753 0.500049293041 0.00849551800638 -232 1.0 0.500000417233 -26 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -230 0.5 0.5 -27 1.0 1.0 -229 1.0 0.5 -754 0.500072538853 0.492137163877 -SURF 0x10 -mat 1 -refs 4 -18 0.0 0.0 -230 0.5 0.5 -754 0.500072538853 0.492137163877 -223 -5.57656837374e-11 -5.57656837374e-11 -SURF 0x10 -mat 1 -refs 4 -754 0.500072538853 0.492137163877 -229 1.0 0.5 -24 1.0 0.0 -227 0.5 7.70699393193e-10 -SURF 0x10 -mat 1 -refs 4 -223 -5.57656837374e-11 -5.57656837374e-11 -754 0.500072538853 0.492137163877 -227 0.5 7.70699393193e-10 -21 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -226 0.5 0.5 -23 1.0 1.0 -225 1.0 0.499999970198 -755 0.502800822258 0.502800822258 -SURF 0x10 -mat 1 -refs 4 -21 0.0 0.0 -226 0.5 0.5 -755 0.502800822258 0.502800822258 -222 4.13228860907e-07 4.13228860907e-07 -SURF 0x10 -mat 1 -refs 4 -755 0.502800822258 0.502800822258 -225 1.0 0.499999970198 -22 1.0 0.0 -224 0.500000417233 9.46387288536e-08 -SURF 0x10 -mat 1 -refs 4 -222 4.13228860907e-07 4.13228860907e-07 -755 0.502800822258 0.502800822258 -224 0.500000417233 9.46387288536e-08 -20 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -223 0.500000476837 0.500000476837 -21 1.0 1.0 -222 1.00000047684 0.500000059605 -756 0.499279558659 0.499279558659 -SURF 0x10 -mat 1 -refs 4 -18 0.0 0.0 -223 0.500000476837 0.500000476837 -756 0.499279558659 0.499279558659 -219 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -756 0.499279558659 0.499279558659 -222 1.00000047684 0.500000059605 -20 1.0 0.0 -221 0.5 7.65526095847e-08 -SURF 0x10 -mat 1 -refs 4 -219 0.0 0.0 -756 0.499279558659 0.499279558659 -221 0.5 7.65526095847e-08 -19 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -220 0.499999672174 0.499999672174 -18 1.0 1.0 -219 1.0 0.5 -757 0.499286293983 0.499286293983 -SURF 0x10 -mat 1 -refs 4 -16 0.0 0.0 -220 0.499999672174 0.499999672174 -757 0.499286293983 0.499286293983 -216 -3.27237514863e-10 -3.27237514863e-10 -SURF 0x10 -mat 1 -refs 4 -757 0.499286293983 0.499286293983 -219 1.0 0.5 -19 1.0 0.0 -218 0.500000357628 9.38187216803e-09 -SURF 0x10 -mat 1 -refs 4 -216 -3.27237514863e-10 -3.27237514863e-10 -757 0.499286293983 0.499286293983 -218 0.500000357628 9.38187216803e-09 -17 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -217 0.500000119209 0.500000119209 -16 1.0 1.0 -216 1.0 0.5 -758 0.499395042658 0.499395042658 -SURF 0x10 -mat 1 -refs 4 -0 0.0 0.0 -217 0.500000119209 0.500000119209 -758 0.499395042658 0.499395042658 -194 1.14438734045e-07 1.14438734045e-07 -SURF 0x10 -mat 1 -refs 4 -758 0.499395042658 0.499395042658 -216 1.0 0.5 -17 1.0 0.0 -215 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -194 1.14438734045e-07 1.14438734045e-07 -758 0.499395042658 0.499395042658 -215 0.5 0.0 -1 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -213 0.500000119209 0.0 -0 0.0 0.0 -194 0.499999970198 0.500000119209 -759 0.501957058907 0.0 -SURF 0x10 -mat 1 -refs 4 -2 1.0 0.0 -213 0.500000119209 0.0 -759 0.501957058907 0.0 -193 1.00000011921 0.0 -SURF 0x10 -mat 1 -refs 4 -759 0.501957058907 0.0 -194 0.499999970198 0.500000119209 -1 1.0 1.0 -214 1.0 0.500000119209 -SURF 0x10 -mat 1 -refs 4 -193 1.00000011921 0.0 -759 0.501957058907 0.0 -214 1.0 0.500000119209 -3 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -212 0.5 0.5 -14 1.0 1.0 -211 1.0 0.5 -760 0.445699423552 0.445699423552 -SURF 0x10 -mat 1 -refs 4 -12 0.0 0.0 -212 0.5 0.5 -760 0.445699423552 0.445699423552 -208 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -760 0.445699423552 0.445699423552 -211 1.0 0.5 -15 1.0 0.0 -210 0.5 2.10990940275e-08 -SURF 0x10 -mat 1 -refs 4 -208 0.0 0.0 -760 0.445699423552 0.445699423552 -210 0.5 2.10990940275e-08 -13 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -205 0.5 0.0 -10 0.0 0.0 -209 0.499999940395 0.499999940395 -761 0.600902378559 0.0 -SURF 0x10 -mat 1 -refs 4 -11 1.0 0.0 -205 0.5 0.0 -761 0.600902378559 0.0 -207 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -761 0.600902378559 0.0 -209 0.499999940395 0.499999940395 -12 1.0 1.0 -208 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -207 1.0 0.0 -761 0.600902378559 0.0 -208 1.0 0.5 -13 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -202 0.499999970198 0.0 -9 0.0 0.0 -206 0.499999940395 0.499999940395 -762 0.571702599525 0.0 -SURF 0x10 -mat 1 -refs 4 -8 1.0 0.0 -202 0.499999970198 0.0 -762 0.571702599525 0.0 -204 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -762 0.571702599525 0.0 -206 0.499999940395 0.499999940395 -10 1.0 1.0 -205 0.999999940395 0.499999940395 -SURF 0x10 -mat 1 -refs 4 -204 1.0 0.0 -762 0.571702599525 0.0 -205 0.999999940395 0.499999940395 -11 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -199 0.5 0.0 -7 0.0 0.0 -203 0.499999940395 0.499999940395 -763 0.549147069454 0.0 -SURF 0x10 -mat 1 -refs 4 -6 1.0 0.0 -199 0.5 0.0 -763 0.549147069454 0.0 -201 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -763 0.549147069454 0.0 -203 0.499999940395 0.499999940395 -9 1.0 1.0 -202 0.999999940395 0.499999940395 -SURF 0x10 -mat 1 -refs 4 -201 1.0 0.0 -763 0.549147069454 0.0 -202 0.999999940395 0.499999940395 -8 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -200 0.5 0.5 -7 1.0 1.0 -199 1.0 0.5 -764 0.503366172314 0.503366172314 -SURF 0x10 -mat 1 -refs 4 -5 0.0 0.0 -200 0.5 0.5 -764 0.503366172314 0.503366172314 -196 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -764 0.503366172314 0.503366172314 -199 1.0 0.5 -6 1.0 0.0 -198 0.5 1.93571363383e-08 -SURF 0x10 -mat 1 -refs 4 -196 0.0 0.0 -764 0.503366172314 0.503366172314 -198 0.5 1.93571363383e-08 -4 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -197 0.500000059605 0.500000059605 -5 1.0 1.0 -196 1.0 0.5 -765 0.493701249361 0.493701249361 -SURF 0x10 -mat 1 -refs 4 -3 0.0 0.0 -197 0.500000059605 0.500000059605 -765 0.493701249361 0.493701249361 -193 1.47640136561e-07 1.47640136561e-07 -SURF 0x10 -mat 1 -refs 4 -765 0.493701249361 0.493701249361 -196 1.0 0.5 -4 1.0 0.0 -195 0.500000059605 2.24260023884e-08 -SURF 0x10 -mat 1 -refs 4 -193 1.47640136561e-07 1.47640136561e-07 -765 0.493701249361 0.493701249361 -195 0.500000059605 2.24260023884e-08 -2 0.0 0.0 -kids 0 -OBJECT group -name "Motor" -kids 2 -OBJECT poly -name "Motor" -data 8 -Tube.002 -crease 30.000000 -numvert 149 -0.277256 0.078425 0 -0.277256 0.078425 4.5e-05 -0.277256 0.078425 4.5e-05 -0.277256 0.078425 0 -0.243118 0.071183 0 -0.243118 0.071183 4.5e-05 -0.243118 0.071183 4.5e-05 -0.243118 0.071183 0 -0.274153 0.093942 0 -0.274153 0.093942 4.5e-05 -0.274153 0.093942 4.5e-05 -0.274153 0.093942 0 -0.274146 0.093072 0.006157 -0.274146 0.093072 -0.006113 -0.274843 0.08973 0.011266 -0.274843 0.08973 -0.011222 -0.275889 0.08473 0.01468 -0.275889 0.08473 -0.014635 -0.277123 0.078831 0.015878 -0.277123 0.078831 -0.015834 -0.278359 0.072933 0.01468 -0.278359 0.072933 -0.014635 -0.279408 0.067933 0.011266 -0.279408 0.067933 -0.011222 -0.28011 0.064592 0.006158 -0.28011 0.064592 -0.006113 -0.28036 0.062907 0 -0.28036 0.062907 4.5e-05 -0.28036 0.062907 4.5e-05 -0.28036 0.062907 0 -0.240014 0.086701 0 -0.240014 0.086701 4.5e-05 -0.240014 0.086701 4.5e-05 -0.240014 0.086701 0 -0.240505 0.085888 0.006174 -0.240505 0.085888 -0.00613 -0.241202 0.082547 0.011283 -0.241202 0.082547 -0.011239 -0.242248 0.077546 0.014697 -0.242248 0.077546 -0.014652 -0.243482 0.071647 0.015895 -0.243482 0.071647 -0.015851 -0.244718 0.065749 0.014697 -0.244718 0.065749 -0.014652 -0.245767 0.060749 0.011283 -0.245767 0.060749 -0.011239 -0.24647 0.057409 0.006175 -0.24647 0.057409 -0.00613 -0.246221 0.0567 0 -0.246221 0.0567 4.5e-05 -0.246221 0.0567 4.5e-05 -0.246221 0.0567 0 -0.309342 0.085654 2.2e-05 -0.307921 0.088115 2.2e-05 -0.307949 0.087912 0.001052 -0.307949 0.087912 -0.001007 -0.30803 0.087334 0.001924 -0.30803 0.087334 -0.00188 -0.30815 0.08647 0.002508 -0.30815 0.08647 -0.002463 -0.308291 0.08545 0.002712 -0.308291 0.08545 -0.002668 -0.308433 0.08443 0.002508 -0.308433 0.08443 -0.002463 -0.308553 0.083566 0.001924 -0.308553 0.083566 -0.00188 -0.308633 0.082988 0.001052 -0.308633 0.082988 -0.001007 -0.308661 0.082785 2.2e-05 -0.29347 0.088267 2.2e-05 -0.293564 0.087805 0.002392 -0.293564 0.087805 -0.002347 -0.293836 0.086492 0.004398 -0.293836 0.086492 -0.004354 -0.294244 0.084526 0.005739 -0.294244 0.084526 -0.005695 -0.294727 0.082208 0.006209 -0.294727 0.082208 -0.006165 -0.29521 0.07989 0.005738 -0.29521 0.07989 -0.005693 -0.295621 0.077926 0.004396 -0.295621 0.077926 -0.004352 -0.295897 0.076614 0.002389 -0.295897 0.076614 -0.002344 -0.295996 0.076154 2.2e-05 -0.293145 0.086586 2.2e-05 -0.293216 0.086235 0.00182 -0.293216 0.086235 -0.001776 -0.293422 0.085238 0.003344 -0.293422 0.085238 -0.0033 -0.293732 0.083745 0.004362 -0.293732 0.083745 -0.004318 -0.294098 0.081986 0.004719 -0.294098 0.081986 -0.004675 -0.294466 0.080226 0.004361 -0.294466 0.080226 -0.004317 -0.294778 0.078735 0.003342 -0.294778 0.078735 -0.003298 -0.294987 0.077738 0.001818 -0.294987 0.077738 -0.001774 -0.295062 0.077389 2.2e-05 -0.281026 0.08437 2.2e-05 -0.281096 0.084017 0.001822 -0.281096 0.084017 -0.001778 -0.281288 0.083015 0.003345 -0.281288 0.083015 -0.003301 -0.281573 0.081517 0.004361 -0.281573 0.081517 -0.004317 -0.281909 0.07975 0.004717 -0.281909 0.07975 -0.004672 -0.282244 0.077985 0.004357 -0.282244 0.077985 -0.004313 -0.282527 0.076488 0.003337 -0.282527 0.076488 -0.003293 -0.282715 0.07549 0.001812 -0.282715 0.07549 -0.001767 -0.282779 0.07514 2.2e-05 -0.281245 0.081819 2.2e-05 -0.281276 0.081658 0.000839 -0.281276 0.081658 -0.000794 -0.281363 0.081203 0.001531 -0.281363 0.081203 -0.001486 -0.281493 0.080523 0.001992 -0.281493 0.080523 -0.001948 -0.281646 0.07972 0.002154 -0.281646 0.07972 -0.002109 -0.281798 0.078918 0.00199 -0.281798 0.078918 -0.001946 -0.281926 0.078238 0.001527 -0.281926 0.078238 -0.001482 -0.282012 0.077785 0.000834 -0.282012 0.077785 -0.00079 -0.282041 0.077626 2.2e-05 -0.272916 0.080182 2.2e-05 -0.272948 0.080021 0.000845 -0.272948 0.080021 -0.0008 -0.273035 0.079567 0.001535 -0.273035 0.079567 -0.001491 -0.273164 0.078888 0.001996 -0.273164 0.078888 -0.001952 -0.273317 0.078087 0.002157 -0.273317 0.078087 -0.002113 -0.273468 0.077286 0.001994 -0.273468 0.077286 -0.00195 -0.273597 0.076608 0.001531 -0.273597 0.076608 -0.001487 -0.273682 0.076155 0.00084 -0.273682 0.076155 -0.000796 -0.273711 0.075997 2.2e-05 -numsurf 132 -SURF 0x30 -mat 3 -refs 4 -14 0 0 -0 0 0 -8 0 0 -12 0 0 -SURF 0x30 -mat 3 -refs 4 -9 0 0 -1 0 0 -15 0 0 -13 0 0 -SURF 0x30 -mat 3 -refs 4 -30 0 0 -4 0 0 -36 0 0 -34 0 0 -SURF 0x30 -mat 3 -refs 4 -31 0 0 -35 0 0 -37 0 0 -5 0 0 -SURF 0x30 -mat 3 -refs 4 -18 0 0 -0 0 0 -14 0 0 -16 0 0 -SURF 0x30 -mat 3 -refs 4 -15 0 0 -1 0 0 -19 0 0 -17 0 0 -SURF 0x30 -mat 3 -refs 4 -36 0 0 -4 0 0 -40 0 0 -38 0 0 -SURF 0x30 -mat 3 -refs 4 -37 0 0 -39 0 0 -41 0 0 -5 0 0 -SURF 0x30 -mat 3 -refs 4 -22 0 0 -0 0 0 -18 0 0 -20 0 0 -SURF 0x30 -mat 3 -refs 4 -19 0 0 -1 0 0 -23 0 0 -21 0 0 -SURF 0x30 -mat 3 -refs 4 -40 0 0 -4 0 0 -44 0 0 -42 0 0 -SURF 0x30 -mat 3 -refs 4 -41 0 0 -43 0 0 -45 0 0 -5 0 0 -SURF 0x30 -mat 3 -refs 4 -26 0 0 -0 0 0 -22 0 0 -24 0 0 -SURF 0x30 -mat 3 -refs 4 -23 0 0 -1 0 0 -27 0 0 -25 0 0 -SURF 0x30 -mat 3 -refs 4 -44 0 0 -4 0 0 -48 0 0 -46 0 0 -SURF 0x30 -mat 3 -refs 4 -45 0 0 -47 0 0 -49 0 0 -5 0 0 -SURF 0x30 -mat 3 -refs 4 -66 0 0 -68 0 0 -67 0 0 -52 0 0 -SURF 0x30 -mat 3 -refs 4 -62 0 0 -64 0 0 -66 0 0 -52 0 0 -SURF 0x30 -mat 3 -refs 4 -63 0 0 -52 0 0 -67 0 0 -65 0 0 -SURF 0x30 -mat 3 -refs 4 -58 0 0 -60 0 0 -62 0 0 -52 0 0 -SURF 0x30 -mat 3 -refs 4 -59 0 0 -52 0 0 -63 0 0 -61 0 0 -SURF 0x30 -mat 3 -refs 4 -54 0 0 -56 0 0 -58 0 0 -52 0 0 -SURF 0x30 -mat 3 -refs 4 -55 0 0 -52 0 0 -59 0 0 -57 0 0 -SURF 0x30 -mat 3 -refs 4 -54 0 0 -52 0 0 -55 0 0 -53 0 0 -SURF 0x30 -mat 3 -refs 4 -148 0 0 -132 0 0 -130 0 0 -146 0 0 -SURF 0x30 -mat 3 -refs 4 -148 0 0 -147 0 0 -131 0 0 -132 0 0 -SURF 0x30 -mat 3 -refs 4 -146 0 0 -130 0 0 -128 0 0 -144 0 0 -SURF 0x30 -mat 3 -refs 4 -147 0 0 -145 0 0 -129 0 0 -131 0 0 -SURF 0x30 -mat 3 -refs 4 -144 0 0 -128 0 0 -126 0 0 -142 0 0 -SURF 0x30 -mat 3 -refs 4 -145 0 0 -143 0 0 -127 0 0 -129 0 0 -SURF 0x30 -mat 3 -refs 4 -142 0 0 -126 0 0 -124 0 0 -140 0 0 -SURF 0x30 -mat 3 -refs 4 -143 0 0 -141 0 0 -125 0 0 -127 0 0 -SURF 0x30 -mat 3 -refs 4 -140 0 0 -124 0 0 -122 0 0 -138 0 0 -SURF 0x30 -mat 3 -refs 4 -141 0 0 -139 0 0 -123 0 0 -125 0 0 -SURF 0x30 -mat 3 -refs 4 -138 0 0 -122 0 0 -120 0 0 -136 0 0 -SURF 0x30 -mat 3 -refs 4 -139 0 0 -137 0 0 -121 0 0 -123 0 0 -SURF 0x30 -mat 3 -refs 4 -136 0 0 -120 0 0 -118 0 0 -134 0 0 -SURF 0x30 -mat 3 -refs 4 -137 0 0 -135 0 0 -119 0 0 -121 0 0 -SURF 0x30 -mat 3 -refs 4 -134 0 0 -118 0 0 -117 0 0 -133 0 0 -SURF 0x30 -mat 3 -refs 4 -135 0 0 -133 0 0 -117 0 0 -119 0 0 -SURF 0x30 -mat 3 -refs 4 -130 0 0 -132 0 0 -116 0 0 -114 0 0 -SURF 0x30 -mat 3 -refs 4 -131 0 0 -115 0 0 -116 0 0 -132 0 0 -SURF 0x30 -mat 3 -refs 4 -128 0 0 -130 0 0 -114 0 0 -112 0 0 -SURF 0x30 -mat 3 -refs 4 -129 0 0 -113 0 0 -115 0 0 -131 0 0 -SURF 0x30 -mat 3 -refs 4 -126 0 0 -128 0 0 -112 0 0 -110 0 0 -SURF 0x30 -mat 3 -refs 4 -127 0 0 -111 0 0 -113 0 0 -129 0 0 -SURF 0x30 -mat 3 -refs 4 -124 0 0 -126 0 0 -110 0 0 -108 0 0 -SURF 0x30 -mat 3 -refs 4 -125 0 0 -109 0 0 -111 0 0 -127 0 0 -SURF 0x30 -mat 3 -refs 4 -122 0 0 -124 0 0 -108 0 0 -106 0 0 -SURF 0x30 -mat 3 -refs 4 -123 0 0 -107 0 0 -109 0 0 -125 0 0 -SURF 0x30 -mat 3 -refs 4 -120 0 0 -122 0 0 -106 0 0 -104 0 0 -SURF 0x30 -mat 3 -refs 4 -121 0 0 -105 0 0 -107 0 0 -123 0 0 -SURF 0x30 -mat 3 -refs 4 -118 0 0 -120 0 0 -104 0 0 -102 0 0 -SURF 0x30 -mat 3 -refs 4 -119 0 0 -103 0 0 -105 0 0 -121 0 0 -SURF 0x30 -mat 3 -refs 4 -117 0 0 -118 0 0 -102 0 0 -101 0 0 -SURF 0x30 -mat 3 -refs 4 -117 0 0 -101 0 0 -103 0 0 -119 0 0 -SURF 0x30 -mat 3 -refs 4 -114 0 0 -116 0 0 -100 0 0 -98 0 0 -SURF 0x30 -mat 3 -refs 4 -115 0 0 -99 0 0 -100 0 0 -116 0 0 -SURF 0x30 -mat 3 -refs 4 -112 0 0 -114 0 0 -98 0 0 -96 0 0 -SURF 0x30 -mat 3 -refs 4 -113 0 0 -97 0 0 -99 0 0 -115 0 0 -SURF 0x30 -mat 3 -refs 4 -110 0 0 -112 0 0 -96 0 0 -94 0 0 -SURF 0x30 -mat 3 -refs 4 -111 0 0 -95 0 0 -97 0 0 -113 0 0 -SURF 0x30 -mat 3 -refs 4 -108 0 0 -110 0 0 -94 0 0 -92 0 0 -SURF 0x30 -mat 3 -refs 4 -109 0 0 -93 0 0 -95 0 0 -111 0 0 -SURF 0x30 -mat 3 -refs 4 -106 0 0 -108 0 0 -92 0 0 -90 0 0 -SURF 0x30 -mat 3 -refs 4 -107 0 0 -91 0 0 -93 0 0 -109 0 0 -SURF 0x30 -mat 3 -refs 4 -104 0 0 -106 0 0 -90 0 0 -88 0 0 -SURF 0x30 -mat 3 -refs 4 -105 0 0 -89 0 0 -91 0 0 -107 0 0 -SURF 0x30 -mat 3 -refs 4 -102 0 0 -104 0 0 -88 0 0 -86 0 0 -SURF 0x30 -mat 3 -refs 4 -103 0 0 -87 0 0 -89 0 0 -105 0 0 -SURF 0x30 -mat 3 -refs 4 -101 0 0 -102 0 0 -86 0 0 -85 0 0 -SURF 0x30 -mat 3 -refs 4 -101 0 0 -85 0 0 -87 0 0 -103 0 0 -SURF 0x30 -mat 3 -refs 4 -100 0 0 -84 0 0 -82 0 0 -98 0 0 -SURF 0x30 -mat 3 -refs 4 -100 0 0 -99 0 0 -83 0 0 -84 0 0 -SURF 0x30 -mat 3 -refs 4 -98 0 0 -82 0 0 -80 0 0 -96 0 0 -SURF 0x30 -mat 3 -refs 4 -99 0 0 -97 0 0 -81 0 0 -83 0 0 -SURF 0x30 -mat 3 -refs 4 -96 0 0 -80 0 0 -78 0 0 -94 0 0 -SURF 0x30 -mat 3 -refs 4 -97 0 0 -95 0 0 -79 0 0 -81 0 0 -SURF 0x30 -mat 3 -refs 4 -94 0 0 -78 0 0 -76 0 0 -92 0 0 -SURF 0x30 -mat 3 -refs 4 -95 0 0 -93 0 0 -77 0 0 -79 0 0 -SURF 0x30 -mat 3 -refs 4 -92 0 0 -76 0 0 -74 0 0 -90 0 0 -SURF 0x30 -mat 3 -refs 4 -93 0 0 -91 0 0 -75 0 0 -77 0 0 -SURF 0x30 -mat 3 -refs 4 -90 0 0 -74 0 0 -72 0 0 -88 0 0 -SURF 0x30 -mat 3 -refs 4 -91 0 0 -89 0 0 -73 0 0 -75 0 0 -SURF 0x30 -mat 3 -refs 4 -88 0 0 -72 0 0 -70 0 0 -86 0 0 -SURF 0x30 -mat 3 -refs 4 -89 0 0 -87 0 0 -71 0 0 -73 0 0 -SURF 0x30 -mat 3 -refs 4 -86 0 0 -70 0 0 -69 0 0 -85 0 0 -SURF 0x30 -mat 3 -refs 4 -87 0 0 -85 0 0 -69 0 0 -71 0 0 -SURF 0x30 -mat 3 -refs 4 -84 0 0 -68 0 0 -66 0 0 -82 0 0 -SURF 0x30 -mat 3 -refs 4 -84 0 0 -83 0 0 -67 0 0 -68 0 0 -SURF 0x30 -mat 3 -refs 4 -82 0 0 -66 0 0 -64 0 0 -80 0 0 -SURF 0x30 -mat 3 -refs 4 -83 0 0 -81 0 0 -65 0 0 -67 0 0 -SURF 0x30 -mat 3 -refs 4 -80 0 0 -64 0 0 -62 0 0 -78 0 0 -SURF 0x30 -mat 3 -refs 4 -81 0 0 -79 0 0 -63 0 0 -65 0 0 -SURF 0x30 -mat 3 -refs 4 -78 0 0 -62 0 0 -60 0 0 -76 0 0 -SURF 0x30 -mat 3 -refs 4 -79 0 0 -77 0 0 -61 0 0 -63 0 0 -SURF 0x30 -mat 3 -refs 4 -76 0 0 -60 0 0 -58 0 0 -74 0 0 -SURF 0x30 -mat 3 -refs 4 -77 0 0 -75 0 0 -59 0 0 -61 0 0 -SURF 0x30 -mat 3 -refs 4 -74 0 0 -58 0 0 -56 0 0 -72 0 0 -SURF 0x30 -mat 3 -refs 4 -75 0 0 -73 0 0 -57 0 0 -59 0 0 -SURF 0x30 -mat 3 -refs 4 -72 0 0 -56 0 0 -54 0 0 -70 0 0 -SURF 0x30 -mat 3 -refs 4 -73 0 0 -71 0 0 -55 0 0 -57 0 0 -SURF 0x30 -mat 3 -refs 4 -70 0 0 -54 0 0 -53 0 0 -69 0 0 -SURF 0x30 -mat 3 -refs 4 -71 0 0 -69 0 0 -53 0 0 -55 0 0 -SURF 0x30 -mat 3 -refs 4 -48 0 0 -26 0 0 -24 0 0 -46 0 0 -SURF 0x30 -mat 3 -refs 4 -49 0 0 -47 0 0 -25 0 0 -27 0 0 -SURF 0x30 -mat 3 -refs 4 -46 0 0 -24 0 0 -22 0 0 -44 0 0 -SURF 0x30 -mat 3 -refs 4 -47 0 0 -45 0 0 -23 0 0 -25 0 0 -SURF 0x30 -mat 3 -refs 4 -44 0 0 -22 0 0 -20 0 0 -42 0 0 -SURF 0x30 -mat 3 -refs 4 -45 0 0 -43 0 0 -21 0 0 -23 0 0 -SURF 0x30 -mat 3 -refs 4 -42 0 0 -20 0 0 -18 0 0 -40 0 0 -SURF 0x30 -mat 3 -refs 4 -43 0 0 -41 0 0 -19 0 0 -21 0 0 -SURF 0x30 -mat 3 -refs 4 -40 0 0 -18 0 0 -16 0 0 -38 0 0 -SURF 0x30 -mat 3 -refs 4 -41 0 0 -39 0 0 -17 0 0 -19 0 0 -SURF 0x30 -mat 3 -refs 4 -38 0 0 -16 0 0 -14 0 0 -36 0 0 -SURF 0x30 -mat 3 -refs 4 -39 0 0 -37 0 0 -15 0 0 -17 0 0 -SURF 0x30 -mat 3 -refs 4 -36 0 0 -14 0 0 -12 0 0 -34 0 0 -SURF 0x30 -mat 3 -refs 4 -37 0 0 -35 0 0 -13 0 0 -15 0 0 -SURF 0x30 -mat 3 -refs 4 -30 0 0 -34 0 0 -12 0 0 -8 0 0 -SURF 0x30 -mat 3 -refs 4 -31 0 0 -9 0 0 -13 0 0 -35 0 0 -SURF 0x02 -mat 3 -refs 2 -10 0 0 -32 0 0 -SURF 0x02 -mat 3 -refs 2 -11 0 0 -33 0 0 -SURF 0x02 -mat 3 -refs 2 -28 0 0 -50 0 0 -SURF 0x02 -mat 3 -refs 2 -29 0 0 -51 0 0 -SURF 0x02 -mat 3 -refs 2 -2 0 0 -10 0 0 -SURF 0x02 -mat 3 -refs 2 -3 0 0 -11 0 0 -SURF 0x02 -mat 3 -refs 2 -6 0 0 -32 0 0 -SURF 0x02 -mat 3 -refs 2 -7 0 0 -33 0 0 -SURF 0x02 -mat 3 -refs 2 -2 0 0 -28 0 0 -SURF 0x02 -mat 3 -refs 2 -3 0 0 -29 0 0 -SURF 0x02 -mat 3 -refs 2 -6 0 0 -50 0 0 -SURF 0x02 -mat 3 -refs 2 -7 0 0 -51 0 0 -kids 0 -OBJECT poly -name "Propeller" -data 9 -Plane.003 -crease 30.000000 -numvert 184 -0.285367 0.084672 -0.004298 -0.28692 0.076378 -0.004298 -0.285117 0.085967 -0.002324 -0.287155 0.075081 -0.002324 -0.285029 0.086421 4e-06 -0.287238 0.074626 4e-06 -0.285117 0.085965 0.002331 -0.287155 0.075082 0.002331 -0.285367 0.08467 0.004304 -0.286919 0.07638 0.004304 -0.285741 0.082732 0.005622 -0.286566 0.078322 0.005622 -0.286161 0.080529 0.006085 -0.286162 0.080529 -0.00608 -0.28574 0.082735 -0.005616 -0.286567 0.078319 -0.005616 -0.292121 0.085975 -0.004297 -0.293688 0.077607 -0.004297 -0.291872 0.087269 -0.002324 -0.293924 0.076311 -0.002324 -0.291784 0.087723 4e-06 -0.294006 0.075856 4e-06 -0.291872 0.087268 0.002331 -0.293923 0.076312 0.002331 -0.292122 0.085973 0.004304 -0.293688 0.07761 0.004304 -0.292495 0.084035 0.005622 -0.293335 0.079551 0.005622 -0.292927 0.081796 0.006085 -0.292928 0.081796 -0.00608 -0.292495 0.084038 -0.005616 -0.293336 0.079549 -0.005616 -0.292888 0.081788 -0.002167 -0.292893 0.081789 -0.002346 -0.292893 0.081789 0.002351 -0.292888 0.081788 0.002172 -0.292587 0.083375 0.001664 -0.293182 0.0802 0.001664 -0.292491 0.083875 0.000902 -0.293273 0.079699 0.000902 -0.292457 0.084051 3e-06 -0.293305 0.079523 3e-06 -0.292491 0.083875 -0.000896 -0.293273 0.079699 -0.000896 -0.292587 0.083376 -0.001658 -0.293182 0.0802 -0.001658 -0.286196 0.080535 -0.002167 -0.286196 0.080535 -0.002346 -0.286196 0.080535 0.002351 -0.286196 0.080535 0.002172 -0.285901 0.082085 0.001663 -0.286482 0.078983 0.001663 -0.285805 0.082585 0.000902 -0.286573 0.078482 0.000902 -0.285771 0.082761 3e-06 -0.286605 0.078306 3e-06 -0.285805 0.082586 -0.000896 -0.286573 0.078482 -0.000896 -0.285901 0.082086 -0.001658 -0.286482 0.078982 -0.001658 -0.300784 0.009461 0.000229 -0.300637 0.011799 0.002358 -0.300673 0.012895 0.002933 -0.300852 0.012146 0.002148 -0.300539 0.010294 -0.001258 -0.29459 0.042534 0.002728 -0.293187 0.043318 0.004002 -0.293545 0.043103 0.002163 -0.298228 0.040483 -0.005619 -0.293787 0.072725 3e-06 -0.286905 0.065632 0.00248 -0.29872 0.063433 -0.004034 -0.288331 0.065375 0.000559 -0.29006 0.079097 0.003796 -0.291652 0.078322 -0.004623 -0.288929 0.078775 0.003395 -0.289014 0.078697 0.004957 -0.300698 0.009393 -0.000418 -0.300915 0.010388 0.001593 -0.300807 0.010102 0.00124 -0.300936 0.010275 0.00114 -0.300605 0.010794 0.000489 -0.297801 0.026105 0.002648 -0.300664 0.012375 0.002665 -0.296944 0.028282 0.003538 -0.300875 0.012018 0.002542 -0.297292 0.027309 0.002216 -0.300722 0.010975 0.00038 -0.299363 0.025023 -0.003492 -0.296629 0.042088 -0.001744 -0.293707 0.04293 0.003558 -0.289951 0.054174 0.003252 -0.293268 0.043267 0.003238 -0.290756 0.054528 0.001458 -0.295954 0.041753 -0.001904 -0.298517 0.051822 -0.004802 -0.296363 0.068552 -0.002169 -0.291827 0.076087 0.001985 -0.29037 0.069156 0.001318 -0.287866 0.072982 0.003756 -0.287296 0.065511 0.001596 -0.293562 0.064949 -0.00197 -0.295131 0.071466 -0.004398 -0.289521 0.079062 0.004424 -0.288923 0.078664 0.004318 -0.290162 0.078791 -0.000652 -0.289496 0.079199 0.003695 -0.290062 0.072136 -0.002215 -0.287716 0.072862 0.003018 -0.293048 0.075598 -0.002515 -0.290605 0.05424 0.002706 -0.296817 0.053187 -0.000892 -0.297622 0.027183 0.003071 -0.293545 0.061387 0.000312 -0.288604 0.072548 0.000401 -0.291112 0.077705 0.0006 -0.289859 0.07433 0.002913 -0.294739 0.05341 -0.001888 -0.290109 0.054682 0.002465 -0.29836 0.026132 -0.000762 -0.297152 0.027447 0.002984 -0.298536 0.025908 -0.000546 -0.273119 0.152611 -0.000227 -0.273847 0.150384 -0.002356 -0.274286 0.149379 -0.002931 -0.274175 0.150141 -0.002146 -0.2732 0.151747 0.00126 -0.27961 0.119595 -0.002726 -0.278596 0.118347 -0.004 -0.27885 0.118679 -0.00216 -0.282232 0.122847 0.00562 -0.290044 0.091252 -3e-06 -0.281024 0.095293 -0.002477 -0.291187 0.101711 0.004033 -0.282253 0.09606 -0.000557 -0.288939 0.083953 -0.003795 -0.290134 0.085263 0.004624 -0.287769 0.083833 -0.003394 -0.287819 0.083937 -0.004955 -0.273013 0.152642 0.00042 -0.273583 0.151798 -0.001591 -0.273377 0.152024 -0.001238 -0.273561 0.151911 -0.001138 -0.273445 0.151306 -0.000487 -0.276509 0.136045 -0.002646 -0.274085 0.149859 -0.002663 -0.276519 0.133705 -0.003536 -0.274149 0.150269 -0.00254 -0.276482 0.134738 -0.002214 -0.273622 0.151181 -0.000378 -0.277562 0.137629 0.003494 -0.28134 0.120764 0.001745 -0.278935 0.118899 -0.003556 -0.27961 0.107064 -0.00325 -0.278653 0.118424 -0.003236 -0.28049 0.107034 -0.001456 -0.280589 0.120825 0.001905 -0.286699 0.112422 0.004802 -0.290891 0.096083 0.002169 -0.289467 0.087404 -0.001984 -0.285547 0.093302 -0.001316 -0.284637 0.088821 -0.003754 -0.281342 0.09555 -0.001593 -0.286956 0.098392 0.00197 -0.290827 0.09292 0.004398 -0.288425 0.083786 -0.004422 -0.287723 0.083935 -0.004317 -0.288922 0.084276 0.000653 -0.288454 0.083649 -0.003694 -0.286366 0.09042 0.002217 -0.284453 0.088877 -0.003016 -0.290421 0.08831 0.002515 -0.280242 0.107245 -0.002704 -0.285624 0.110523 0.000892 -0.276742 0.134978 -0.003069 -0.28562 0.101695 -0.000311 -0.285163 0.089498 -0.000399 -0.289403 0.085636 -0.0006 -0.286987 0.088307 -0.002911 -0.283777 0.109547 0.001889 -0.279945 0.106651 -0.002463 -0.277039 0.136227 0.000763 -0.276403 0.134558 -0.002982 -0.277121 0.136501 0.000548 -numsurf 230 -SURF 0x30 -mat 4 -refs 4 -14 0 0 -0 0 0 -16 0 0 -30 0 0 -SURF 0x30 -mat 4 -refs 4 -17 0 0 -1 0 0 -15 0 0 -31 0 0 -SURF 0x30 -mat 4 -refs 4 -30 0 0 -29 0 0 -13 0 0 -14 0 0 -SURF 0x30 -mat 4 -refs 4 -13 0 0 -29 0 0 -31 0 0 -15 0 0 -SURF 0x30 -mat 4 -refs 4 -28 0 0 -26 0 0 -10 0 0 -12 0 0 -SURF 0x30 -mat 4 -refs 4 -11 0 0 -27 0 0 -28 0 0 -12 0 0 -SURF 0x30 -mat 4 -refs 4 -26 0 0 -24 0 0 -8 0 0 -10 0 0 -SURF 0x30 -mat 4 -refs 4 -9 0 0 -25 0 0 -27 0 0 -11 0 0 -SURF 0x30 -mat 4 -refs 4 -24 0 0 -22 0 0 -6 0 0 -8 0 0 -SURF 0x30 -mat 4 -refs 4 -7 0 0 -23 0 0 -25 0 0 -9 0 0 -SURF 0x30 -mat 4 -refs 4 -22 0 0 -20 0 0 -4 0 0 -6 0 0 -SURF 0x30 -mat 4 -refs 4 -5 0 0 -21 0 0 -23 0 0 -7 0 0 -SURF 0x30 -mat 4 -refs 4 -20 0 0 -18 0 0 -2 0 0 -4 0 0 -SURF 0x30 -mat 4 -refs 4 -3 0 0 -19 0 0 -21 0 0 -5 0 0 -SURF 0x30 -mat 4 -refs 4 -0 0 0 -2 0 0 -18 0 0 -16 0 0 -SURF 0x30 -mat 4 -refs 4 -19 0 0 -3 0 0 -1 0 0 -17 0 0 -SURF 0x30 -mat 4 -refs 4 -2 0 0 -0 0 0 -58 0 0 -56 0 0 -SURF 0x30 -mat 4 -refs 4 -59 0 0 -1 0 0 -3 0 0 -57 0 0 -SURF 0x30 -mat 4 -refs 4 -42 0 0 -44 0 0 -16 0 0 -18 0 0 -SURF 0x30 -mat 4 -refs 4 -17 0 0 -45 0 0 -43 0 0 -19 0 0 -SURF 0x30 -mat 4 -refs 4 -56 0 0 -54 0 0 -4 0 0 -2 0 0 -SURF 0x30 -mat 4 -refs 4 -5 0 0 -55 0 0 -57 0 0 -3 0 0 -SURF 0x30 -mat 4 -refs 4 -40 0 0 -42 0 0 -18 0 0 -20 0 0 -SURF 0x30 -mat 4 -refs 4 -19 0 0 -43 0 0 -41 0 0 -21 0 0 -SURF 0x30 -mat 4 -refs 4 -54 0 0 -52 0 0 -6 0 0 -4 0 0 -SURF 0x30 -mat 4 -refs 4 -7 0 0 -53 0 0 -55 0 0 -5 0 0 -SURF 0x30 -mat 4 -refs 4 -38 0 0 -40 0 0 -20 0 0 -22 0 0 -SURF 0x30 -mat 4 -refs 4 -21 0 0 -41 0 0 -39 0 0 -23 0 0 -SURF 0x30 -mat 4 -refs 4 -52 0 0 -50 0 0 -8 0 0 -6 0 0 -SURF 0x30 -mat 4 -refs 4 -9 0 0 -51 0 0 -53 0 0 -7 0 0 -SURF 0x30 -mat 4 -refs 4 -36 0 0 -38 0 0 -22 0 0 -24 0 0 -SURF 0x30 -mat 4 -refs 4 -23 0 0 -39 0 0 -37 0 0 -25 0 0 -SURF 0x30 -mat 4 -refs 4 -50 0 0 -49 0 0 -10 0 0 -8 0 0 -SURF 0x30 -mat 4 -refs 4 -11 0 0 -49 0 0 -51 0 0 -9 0 0 -SURF 0x30 -mat 4 -refs 4 -35 0 0 -36 0 0 -24 0 0 -26 0 0 -SURF 0x30 -mat 4 -refs 4 -25 0 0 -37 0 0 -35 0 0 -27 0 0 -SURF 0x30 -mat 4 -refs 4 -49 0 0 -48 0 0 -12 0 0 -10 0 0 -SURF 0x30 -mat 4 -refs 4 -12 0 0 -48 0 0 -49 0 0 -11 0 0 -SURF 0x30 -mat 4 -refs 4 -34 0 0 -35 0 0 -26 0 0 -28 0 0 -SURF 0x30 -mat 4 -refs 4 -27 0 0 -35 0 0 -34 0 0 -28 0 0 -SURF 0x30 -mat 4 -refs 4 -47 0 0 -46 0 0 -14 0 0 -13 0 0 -SURF 0x30 -mat 4 -refs 4 -15 0 0 -46 0 0 -47 0 0 -13 0 0 -SURF 0x30 -mat 4 -refs 4 -32 0 0 -33 0 0 -29 0 0 -30 0 0 -SURF 0x30 -mat 4 -refs 4 -29 0 0 -33 0 0 -32 0 0 -31 0 0 -SURF 0x30 -mat 4 -refs 4 -0 0 0 -14 0 0 -46 0 0 -58 0 0 -SURF 0x30 -mat 4 -refs 4 -46 0 0 -15 0 0 -1 0 0 -59 0 0 -SURF 0x30 -mat 4 -refs 4 -44 0 0 -32 0 0 -30 0 0 -16 0 0 -SURF 0x30 -mat 4 -refs 4 -31 0 0 -32 0 0 -45 0 0 -17 0 0 -SURF 0x30 -mat 4 -refs 4 -46 0 0 -32 0 0 -44 0 0 -58 0 0 -SURF 0x30 -mat 4 -refs 4 -45 0 0 -32 0 0 -46 0 0 -59 0 0 -SURF 0x30 -mat 4 -refs 4 -47 0 0 -33 0 0 -32 0 0 -46 0 0 -SURF 0x30 -mat 4 -refs 4 -49 0 0 -35 0 0 -34 0 0 -48 0 0 -SURF 0x30 -mat 4 -refs 4 -50 0 0 -36 0 0 -35 0 0 -49 0 0 -SURF 0x30 -mat 4 -refs 4 -35 0 0 -37 0 0 -51 0 0 -49 0 0 -SURF 0x30 -mat 4 -refs 4 -52 0 0 -38 0 0 -36 0 0 -50 0 0 -SURF 0x30 -mat 4 -refs 4 -37 0 0 -39 0 0 -53 0 0 -51 0 0 -SURF 0x30 -mat 4 -refs 4 -54 0 0 -40 0 0 -38 0 0 -52 0 0 -SURF 0x30 -mat 4 -refs 4 -39 0 0 -41 0 0 -55 0 0 -53 0 0 -SURF 0x30 -mat 4 -refs 4 -56 0 0 -42 0 0 -40 0 0 -54 0 0 -SURF 0x30 -mat 4 -refs 4 -41 0 0 -43 0 0 -57 0 0 -55 0 0 -SURF 0x30 -mat 4 -refs 4 -58 0 0 -44 0 0 -42 0 0 -56 0 0 -SURF 0x30 -mat 4 -refs 4 -43 0 0 -45 0 0 -59 0 0 -57 0 0 -SURF 0x30 -mat 4 -refs 3 -81 0 0 -61 0 0 -79 0 0 -SURF 0x30 -mat 4 -refs 3 -79 0 0 -77 0 0 -81 0 0 -SURF 0x30 -mat 4 -refs 3 -64 0 0 -81 0 0 -77 0 0 -SURF 0x30 -mat 4 -refs 3 -79 0 0 -60 0 0 -77 0 0 -SURF 0x30 -mat 4 -refs 3 -83 0 0 -62 0 0 -78 0 0 -SURF 0x30 -mat 4 -refs 3 -78 0 0 -79 0 0 -83 0 0 -SURF 0x30 -mat 4 -refs 3 -61 0 0 -83 0 0 -79 0 0 -SURF 0x30 -mat 4 -refs 3 -78 0 0 -60 0 0 -79 0 0 -SURF 0x30 -mat 4 -refs 3 -85 0 0 -63 0 0 -80 0 0 -SURF 0x30 -mat 4 -refs 3 -80 0 0 -78 0 0 -85 0 0 -SURF 0x30 -mat 4 -refs 3 -62 0 0 -85 0 0 -78 0 0 -SURF 0x30 -mat 4 -refs 3 -80 0 0 -60 0 0 -78 0 0 -SURF 0x30 -mat 4 -refs 3 -87 0 0 -64 0 0 -77 0 0 -SURF 0x30 -mat 4 -refs 3 -77 0 0 -80 0 0 -87 0 0 -SURF 0x30 -mat 4 -refs 3 -63 0 0 -87 0 0 -80 0 0 -SURF 0x30 -mat 4 -refs 3 -77 0 0 -60 0 0 -80 0 0 -SURF 0x30 -mat 4 -refs 3 -104 0 0 -76 0 0 -103 0 0 -SURF 0x30 -mat 4 -refs 3 -103 0 0 -106 0 0 -104 0 0 -SURF 0x30 -mat 4 -refs 3 -75 0 0 -104 0 0 -106 0 0 -SURF 0x30 -mat 4 -refs 3 -106 0 0 -103 0 0 -73 0 0 -SURF 0x30 -mat 4 -refs 3 -107 0 0 -74 0 0 -102 0 0 -SURF 0x30 -mat 4 -refs 3 -102 0 0 -101 0 0 -107 0 0 -SURF 0x30 -mat 4 -refs 3 -72 0 0 -107 0 0 -101 0 0 -SURF 0x30 -mat 4 -refs 3 -101 0 0 -102 0 0 -71 0 0 -SURF 0x30 -mat 4 -refs 3 -99 0 0 -76 0 0 -104 0 0 -SURF 0x30 -mat 4 -refs 3 -104 0 0 -108 0 0 -99 0 0 -SURF 0x30 -mat 4 -refs 3 -70 0 0 -99 0 0 -108 0 0 -SURF 0x30 -mat 4 -refs 3 -108 0 0 -104 0 0 -75 0 0 -SURF 0x30 -mat 4 -refs 3 -102 0 0 -74 0 0 -109 0 0 -SURF 0x30 -mat 4 -refs 3 -109 0 0 -96 0 0 -102 0 0 -SURF 0x30 -mat 4 -refs 3 -71 0 0 -102 0 0 -96 0 0 -SURF 0x30 -mat 4 -refs 3 -96 0 0 -109 0 0 -69 0 0 -SURF 0x30 -mat 4 -refs 3 -110 0 0 -70 0 0 -91 0 0 -SURF 0x30 -mat 4 -refs 3 -91 0 0 -90 0 0 -110 0 0 -SURF 0x30 -mat 4 -refs 3 -65 0 0 -110 0 0 -90 0 0 -SURF 0x30 -mat 4 -refs 3 -90 0 0 -91 0 0 -66 0 0 -SURF 0x30 -mat 4 -refs 3 -95 0 0 -71 0 0 -111 0 0 -SURF 0x30 -mat 4 -refs 3 -111 0 0 -89 0 0 -95 0 0 -SURF 0x30 -mat 4 -refs 3 -68 0 0 -95 0 0 -89 0 0 -SURF 0x30 -mat 4 -refs 3 -89 0 0 -111 0 0 -65 0 0 -SURF 0x30 -mat 4 -refs 3 -112 0 0 -65 0 0 -90 0 0 -SURF 0x30 -mat 4 -refs 3 -90 0 0 -84 0 0 -112 0 0 -SURF 0x30 -mat 4 -refs 3 -62 0 0 -112 0 0 -84 0 0 -SURF 0x30 -mat 4 -refs 3 -84 0 0 -90 0 0 -66 0 0 -SURF 0x30 -mat 4 -refs 3 -82 0 0 -65 0 0 -112 0 0 -SURF 0x30 -mat 4 -refs 3 -112 0 0 -83 0 0 -82 0 0 -SURF 0x30 -mat 4 -refs 3 -61 0 0 -82 0 0 -83 0 0 -SURF 0x30 -mat 4 -refs 3 -83 0 0 -112 0 0 -62 0 0 -SURF 0x30 -mat 4 -refs 4 -110 0 0 -65 0 0 -111 0 0 -113 0 0 -SURF 0x30 -mat 4 -refs 4 -70 0 0 -110 0 0 -113 0 0 -98 0 0 -SURF 0x30 -mat 4 -refs 4 -113 0 0 -111 0 0 -71 0 0 -96 0 0 -SURF 0x30 -mat 4 -refs 4 -98 0 0 -113 0 0 -96 0 0 -69 0 0 -SURF 0x30 -mat 4 -refs 4 -107 0 0 -72 0 0 -100 0 0 -114 0 0 -SURF 0x30 -mat 4 -refs 4 -74 0 0 -107 0 0 -114 0 0 -105 0 0 -SURF 0x30 -mat 4 -refs 4 -114 0 0 -100 0 0 -70 0 0 -108 0 0 -SURF 0x30 -mat 4 -refs 4 -105 0 0 -114 0 0 -108 0 0 -75 0 0 -SURF 0x30 -mat 4 -refs 4 -106 0 0 -73 0 0 -97 0 0 -115 0 0 -SURF 0x30 -mat 4 -refs 4 -75 0 0 -106 0 0 -115 0 0 -105 0 0 -SURF 0x30 -mat 4 -refs 4 -115 0 0 -97 0 0 -69 0 0 -109 0 0 -SURF 0x30 -mat 4 -refs 4 -105 0 0 -115 0 0 -109 0 0 -74 0 0 -SURF 0x30 -mat 4 -refs 4 -103 0 0 -76 0 0 -99 0 0 -116 0 0 -SURF 0x30 -mat 4 -refs 4 -73 0 0 -103 0 0 -116 0 0 -97 0 0 -SURF 0x30 -mat 4 -refs 4 -116 0 0 -99 0 0 -70 0 0 -98 0 0 -SURF 0x30 -mat 4 -refs 4 -97 0 0 -116 0 0 -98 0 0 -69 0 0 -SURF 0x30 -mat 4 -refs 4 -101 0 0 -71 0 0 -95 0 0 -117 0 0 -SURF 0x30 -mat 4 -refs 4 -72 0 0 -101 0 0 -117 0 0 -93 0 0 -SURF 0x30 -mat 4 -refs 4 -117 0 0 -95 0 0 -68 0 0 -94 0 0 -SURF 0x30 -mat 4 -refs 4 -93 0 0 -117 0 0 -94 0 0 -67 0 0 -SURF 0x30 -mat 4 -refs 4 -100 0 0 -72 0 0 -93 0 0 -118 0 0 -SURF 0x30 -mat 4 -refs 4 -70 0 0 -100 0 0 -118 0 0 -91 0 0 -SURF 0x30 -mat 4 -refs 4 -118 0 0 -93 0 0 -67 0 0 -92 0 0 -SURF 0x30 -mat 4 -refs 4 -91 0 0 -118 0 0 -92 0 0 -66 0 0 -SURF 0x30 -mat 4 -refs 4 -94 0 0 -68 0 0 -88 0 0 -119 0 0 -SURF 0x30 -mat 4 -refs 4 -67 0 0 -94 0 0 -119 0 0 -86 0 0 -SURF 0x30 -mat 4 -refs 4 -119 0 0 -88 0 0 -64 0 0 -87 0 0 -SURF 0x30 -mat 4 -refs 4 -86 0 0 -119 0 0 -87 0 0 -63 0 0 -SURF 0x30 -mat 4 -refs 4 -92 0 0 -67 0 0 -86 0 0 -120 0 0 -SURF 0x30 -mat 4 -refs 4 -66 0 0 -92 0 0 -120 0 0 -84 0 0 -SURF 0x30 -mat 4 -refs 4 -120 0 0 -86 0 0 -63 0 0 -85 0 0 -SURF 0x30 -mat 4 -refs 4 -84 0 0 -120 0 0 -85 0 0 -62 0 0 -SURF 0x30 -mat 4 -refs 4 -82 0 0 -61 0 0 -81 0 0 -121 0 0 -SURF 0x30 -mat 4 -refs 4 -65 0 0 -82 0 0 -121 0 0 -89 0 0 -SURF 0x30 -mat 4 -refs 4 -121 0 0 -81 0 0 -64 0 0 -88 0 0 -SURF 0x30 -mat 4 -refs 4 -89 0 0 -121 0 0 -88 0 0 -68 0 0 -SURF 0x30 -mat 4 -refs 3 -143 0 0 -123 0 0 -141 0 0 -SURF 0x30 -mat 4 -refs 3 -141 0 0 -139 0 0 -143 0 0 -SURF 0x30 -mat 4 -refs 3 -126 0 0 -143 0 0 -139 0 0 -SURF 0x30 -mat 4 -refs 3 -141 0 0 -122 0 0 -139 0 0 -SURF 0x30 -mat 4 -refs 3 -145 0 0 -124 0 0 -140 0 0 -SURF 0x30 -mat 4 -refs 3 -140 0 0 -141 0 0 -145 0 0 -SURF 0x30 -mat 4 -refs 3 -123 0 0 -145 0 0 -141 0 0 -SURF 0x30 -mat 4 -refs 3 -140 0 0 -122 0 0 -141 0 0 -SURF 0x30 -mat 4 -refs 3 -147 0 0 -125 0 0 -142 0 0 -SURF 0x30 -mat 4 -refs 3 -142 0 0 -140 0 0 -147 0 0 -SURF 0x30 -mat 4 -refs 3 -124 0 0 -147 0 0 -140 0 0 -SURF 0x30 -mat 4 -refs 3 -142 0 0 -122 0 0 -140 0 0 -SURF 0x30 -mat 4 -refs 3 -149 0 0 -126 0 0 -139 0 0 -SURF 0x30 -mat 4 -refs 3 -139 0 0 -142 0 0 -149 0 0 -SURF 0x30 -mat 4 -refs 3 -125 0 0 -149 0 0 -142 0 0 -SURF 0x30 -mat 4 -refs 3 -139 0 0 -122 0 0 -142 0 0 -SURF 0x30 -mat 4 -refs 3 -166 0 0 -138 0 0 -165 0 0 -SURF 0x30 -mat 4 -refs 3 -165 0 0 -168 0 0 -166 0 0 -SURF 0x30 -mat 4 -refs 3 -137 0 0 -166 0 0 -168 0 0 -SURF 0x30 -mat 4 -refs 3 -168 0 0 -165 0 0 -135 0 0 -SURF 0x30 -mat 4 -refs 3 -169 0 0 -136 0 0 -164 0 0 -SURF 0x30 -mat 4 -refs 3 -164 0 0 -163 0 0 -169 0 0 -SURF 0x30 -mat 4 -refs 3 -134 0 0 -169 0 0 -163 0 0 -SURF 0x30 -mat 4 -refs 3 -163 0 0 -164 0 0 -133 0 0 -SURF 0x30 -mat 4 -refs 3 -161 0 0 -138 0 0 -166 0 0 -SURF 0x30 -mat 4 -refs 3 -166 0 0 -170 0 0 -161 0 0 -SURF 0x30 -mat 4 -refs 3 -132 0 0 -161 0 0 -170 0 0 -SURF 0x30 -mat 4 -refs 3 -170 0 0 -166 0 0 -137 0 0 -SURF 0x30 -mat 4 -refs 3 -164 0 0 -136 0 0 -171 0 0 -SURF 0x30 -mat 4 -refs 3 -171 0 0 -158 0 0 -164 0 0 -SURF 0x30 -mat 4 -refs 3 -133 0 0 -164 0 0 -158 0 0 -SURF 0x30 -mat 4 -refs 3 -158 0 0 -171 0 0 -131 0 0 -SURF 0x30 -mat 4 -refs 3 -172 0 0 -132 0 0 -153 0 0 -SURF 0x30 -mat 4 -refs 3 -153 0 0 -152 0 0 -172 0 0 -SURF 0x30 -mat 4 -refs 3 -127 0 0 -172 0 0 -152 0 0 -SURF 0x30 -mat 4 -refs 3 -152 0 0 -153 0 0 -128 0 0 -SURF 0x30 -mat 4 -refs 3 -157 0 0 -133 0 0 -173 0 0 -SURF 0x30 -mat 4 -refs 3 -173 0 0 -151 0 0 -157 0 0 -SURF 0x30 -mat 4 -refs 3 -130 0 0 -157 0 0 -151 0 0 -SURF 0x30 -mat 4 -refs 3 -151 0 0 -173 0 0 -127 0 0 -SURF 0x30 -mat 4 -refs 3 -174 0 0 -127 0 0 -152 0 0 -SURF 0x30 -mat 4 -refs 3 -152 0 0 -146 0 0 -174 0 0 -SURF 0x30 -mat 4 -refs 3 -124 0 0 -174 0 0 -146 0 0 -SURF 0x30 -mat 4 -refs 3 -146 0 0 -152 0 0 -128 0 0 -SURF 0x30 -mat 4 -refs 3 -144 0 0 -127 0 0 -174 0 0 -SURF 0x30 -mat 4 -refs 3 -174 0 0 -145 0 0 -144 0 0 -SURF 0x30 -mat 4 -refs 3 -123 0 0 -144 0 0 -145 0 0 -SURF 0x30 -mat 4 -refs 3 -145 0 0 -174 0 0 -124 0 0 -SURF 0x30 -mat 4 -refs 4 -172 0 0 -127 0 0 -173 0 0 -175 0 0 -SURF 0x30 -mat 4 -refs 4 -132 0 0 -172 0 0 -175 0 0 -160 0 0 -SURF 0x30 -mat 4 -refs 4 -175 0 0 -173 0 0 -133 0 0 -158 0 0 -SURF 0x30 -mat 4 -refs 4 -160 0 0 -175 0 0 -158 0 0 -131 0 0 -SURF 0x30 -mat 4 -refs 4 -169 0 0 -134 0 0 -162 0 0 -176 0 0 -SURF 0x30 -mat 4 -refs 4 -136 0 0 -169 0 0 -176 0 0 -167 0 0 -SURF 0x30 -mat 4 -refs 4 -176 0 0 -162 0 0 -132 0 0 -170 0 0 -SURF 0x30 -mat 4 -refs 4 -167 0 0 -176 0 0 -170 0 0 -137 0 0 -SURF 0x30 -mat 4 -refs 4 -168 0 0 -135 0 0 -159 0 0 -177 0 0 -SURF 0x30 -mat 4 -refs 4 -137 0 0 -168 0 0 -177 0 0 -167 0 0 -SURF 0x30 -mat 4 -refs 4 -177 0 0 -159 0 0 -131 0 0 -171 0 0 -SURF 0x30 -mat 4 -refs 4 -167 0 0 -177 0 0 -171 0 0 -136 0 0 -SURF 0x30 -mat 4 -refs 4 -165 0 0 -138 0 0 -161 0 0 -178 0 0 -SURF 0x30 -mat 4 -refs 4 -135 0 0 -165 0 0 -178 0 0 -159 0 0 -SURF 0x30 -mat 4 -refs 4 -178 0 0 -161 0 0 -132 0 0 -160 0 0 -SURF 0x30 -mat 4 -refs 4 -159 0 0 -178 0 0 -160 0 0 -131 0 0 -SURF 0x30 -mat 4 -refs 4 -163 0 0 -133 0 0 -157 0 0 -179 0 0 -SURF 0x30 -mat 4 -refs 4 -134 0 0 -163 0 0 -179 0 0 -155 0 0 -SURF 0x30 -mat 4 -refs 4 -179 0 0 -157 0 0 -130 0 0 -156 0 0 -SURF 0x30 -mat 4 -refs 4 -155 0 0 -179 0 0 -156 0 0 -129 0 0 -SURF 0x30 -mat 4 -refs 4 -162 0 0 -134 0 0 -155 0 0 -180 0 0 -SURF 0x30 -mat 4 -refs 4 -132 0 0 -162 0 0 -180 0 0 -153 0 0 -SURF 0x30 -mat 4 -refs 4 -180 0 0 -155 0 0 -129 0 0 -154 0 0 -SURF 0x30 -mat 4 -refs 4 -153 0 0 -180 0 0 -154 0 0 -128 0 0 -SURF 0x30 -mat 4 -refs 4 -156 0 0 -130 0 0 -150 0 0 -181 0 0 -SURF 0x30 -mat 4 -refs 4 -129 0 0 -156 0 0 -181 0 0 -148 0 0 -SURF 0x30 -mat 4 -refs 4 -181 0 0 -150 0 0 -126 0 0 -149 0 0 -SURF 0x30 -mat 4 -refs 4 -148 0 0 -181 0 0 -149 0 0 -125 0 0 -SURF 0x30 -mat 4 -refs 4 -154 0 0 -129 0 0 -148 0 0 -182 0 0 -SURF 0x30 -mat 4 -refs 4 -128 0 0 -154 0 0 -182 0 0 -146 0 0 -SURF 0x30 -mat 4 -refs 4 -182 0 0 -148 0 0 -125 0 0 -147 0 0 -SURF 0x30 -mat 4 -refs 4 -146 0 0 -182 0 0 -147 0 0 -124 0 0 -SURF 0x30 -mat 4 -refs 4 -144 0 0 -123 0 0 -143 0 0 -183 0 0 -SURF 0x30 -mat 4 -refs 4 -127 0 0 -144 0 0 -183 0 0 -151 0 0 -SURF 0x30 -mat 4 -refs 4 -183 0 0 -143 0 0 -126 0 0 -150 0 0 -SURF 0x30 -mat 4 -refs 4 -151 0 0 -183 0 0 -150 0 0 -130 0 0 -kids 0 -OBJECT poly -name "RightWing" -data 8 -Wing.001 -crease 30.000000 -numvert 766 -0.149491 0.04245 -0.00106 -0.148054 0.019982 -0.001061 -0.122396 0.046023 -0.001059 -0.120954 0.020507 -0.001061 -0.09791 0.048011 -0.001059 -0.095931 0.022447 -0.00106 -0.076772 0.048084 -0.001059 -0.075273 0.025574 -0.00106 -0.061423 0.046093 -0.001059 -0.060658 0.028058 -0.00106 -0.051559 0.03049 -0.001059 -0.052212 0.043409 -0.001059 -0.045014 0.0331 -0.001058 -0.045765 0.040953 -0.001059 -0.041737 0.036405 -0.001373 -0.042719 0.039428 -0.0014 -0.180991 0.036048 -0.001061 -0.179832 0.019132 -0.001061 -0.202989 0.032027 -0.001061 -0.202008 0.01858 -0.001061 -0.218596 0.017185 -0.001062 -0.219461 0.028523 -0.001061 -0.235774 0.015131 -0.001405 -0.236322 0.024438 -0.001405 -0.221091 0.028594 -0.044868 -0.220212 0.017089 -0.04488 -0.203193 0.018093 -0.044874 -0.204245 0.032536 -0.044858 -0.180726 0.018589 -0.044866 -0.181971 0.036798 -0.044846 -0.044015 0.039418 -0.0448 -0.043135 0.036423 -0.044802 -0.047196 0.041319 -0.044799 -0.046388 0.032922 -0.044808 -0.05362 0.043913 -0.044798 -0.052909 0.030101 -0.044813 -0.062198 0.02748 -0.044819 -0.063053 0.046719 -0.044798 -0.076442 0.024881 -0.044826 -0.078439 0.048783 -0.0448 -0.097159 0.021764 -0.052803 -0.099494 0.048819 -0.044807 -0.1224 0.019751 -0.044846 -0.123973 0.046845 -0.044817 -0.149711 0.019224 -0.044855 -0.151232 0.043089 -0.044829 -0.236707 0.018207 -0.044884 -0.236969 0.021872 -0.04488 -0.232841 0.02249 -0.43679 -0.232634 0.019749 -0.436795 -0.21866 0.028941 -0.436777 -0.217873 0.01865 -0.436791 -0.202604 0.01956 -0.436785 -0.203547 0.03251 -0.436767 -0.182454 0.020007 -0.436778 -0.18357 0.036336 -0.436756 -0.059908 0.038678 -0.436714 -0.059123 0.035994 -0.436717 -0.062762 0.040386 -0.436712 -0.062037 0.032858 -0.436723 -0.068359 0.042645 -0.436712 -0.067718 0.030398 -0.436727 -0.076012 0.027949 -0.428411 -0.076749 0.045153 -0.436711 -0.089634 0.025547 -0.436741 -0.09039 0.04702 -0.436712 -0.107629 0.022868 -0.441023 -0.109459 0.047082 -0.440986 -0.130182 0.021051 -0.436761 -0.131594 0.045335 -0.436727 -0.154674 0.020575 -0.436769 -0.156036 0.041966 -0.436739 -0.16115 0.041378 -0.535687 -0.159933 0.022212 -0.535972 -0.139348 0.044355 -0.535661 -0.138076 0.022667 -0.535972 -0.119792 0.045898 -0.535655 -0.118159 0.024237 -0.535955 -0.103623 0.045831 -0.53567 -0.102354 0.026639 -0.535928 -0.091249 0.044225 -0.535701 -0.090545 0.028795 -0.535902 -0.082993 0.0309 -0.535875 -0.083569 0.042006 -0.535736 -0.077269 0.033092 -0.53377 -0.077916 0.039961 -0.533681 -0.075033 0.035979 -0.535814 -0.075734 0.038376 -0.535779 -0.185689 0.036402 -0.535739 -0.184686 0.021706 -0.535966 -0.204002 0.032965 -0.537513 -0.203161 0.021402 -0.537716 -0.216982 0.020471 -0.53596 -0.217687 0.029692 -0.535825 -0.230174 0.021419 -0.535949 -0.23037 0.024099 -0.535891 -0.179125 0.041748 -0.598072 -0.17818 0.026962 -0.600611 -0.161797 0.044177 -0.598 -0.160805 0.027358 -0.600874 -0.146272 0.04546 -0.598083 -0.145005 0.028579 -0.600959 -0.132936 0.045489 -0.598332 -0.13194 0.030519 -0.600868 -0.123134 0.044265 -0.59872 -0.122584 0.032221 -0.600749 -0.116597 0.033873 -0.600576 -0.117046 0.04255 -0.599121 -0.111528 0.035507 -0.598794 -0.112038 0.040891 -0.597912 -0.110267 0.037855 -0.600018 -0.11082 0.039722 -0.599692 -0.1983 0.037877 -0.598359 -0.19752 0.026527 -0.600308 -0.211982 0.035252 -0.598525 -0.21132 0.026188 -0.600071 -0.222454 0.025747 -0.601198 -0.223003 0.032915 -0.599949 -0.23286 0.026308 -0.599671 -0.232993 0.028242 -0.599151 -0.239677 0.037211 -0.643062 -0.239587 0.035839 -0.643314 -0.232693 0.04087 -0.644521 -0.2323 0.035711 -0.645394 -0.224582 0.03608 -0.645873 -0.225057 0.042603 -0.644782 -0.214437 0.036602 -0.647537 -0.215 0.044828 -0.646167 -0.152369 0.04768 -0.656226 -0.151979 0.046333 -0.656497 -0.152861 0.04833 -0.654624 -0.152515 0.044421 -0.655279 -0.156853 0.049647 -0.655201 -0.156583 0.043299 -0.656215 -0.160829 0.042025 -0.655714 -0.161233 0.050787 -0.654305 -0.167544 0.040627 -0.654816 -0.168267 0.051501 -0.653028 -0.176902 0.038998 -0.653503 -0.177814 0.051244 -0.651469 -0.188206 0.037845 -0.651782 -0.188924 0.050039 -0.649785 -0.200646 0.037254 -0.649783 -0.201329 0.047965 -0.648016 -0.223019 0.055669 -0.673444 -0.222612 0.04932 -0.675619 -0.215422 0.057545 -0.675278 -0.214978 0.050328 -0.677732 -0.208633 0.058814 -0.677047 -0.20811 0.051555 -0.679529 -0.202845 0.059434 -0.678697 -0.202415 0.052933 -0.680901 -0.198524 0.059391 -0.680083 -0.198259 0.054118 -0.681842 -0.19457 0.054851 -0.681848 -0.19573 0.058962 -0.681108 -0.193619 0.05614 -0.682658 -0.193916 0.058451 -0.681845 -0.192743 0.057152 -0.682617 -0.191974 0.05772 -0.681768 -0.231 0.053292 -0.671644 -0.230658 0.048303 -0.673371 -0.237443 0.051615 -0.670641 -0.236926 0.047466 -0.671605 -0.241773 0.047058 -0.670672 -0.241855 0.049706 -0.669255 -0.245666 0.046727 -0.669006 -0.245726 0.047591 -0.668703 -0.249727 0.057951 -0.682265 -0.249888 0.057253 -0.682139 -0.248174 0.058984 -0.682626 -0.248081 0.057738 -0.683237 -0.246166 0.058242 -0.684087 -0.246138 0.059964 -0.683294 -0.243538 0.058899 -0.685233 -0.243684 0.06103 -0.684183 -0.226883 0.064731 -0.690998 -0.226742 0.064468 -0.691332 -0.228052 0.065031 -0.690839 -0.227904 0.06404 -0.691353 -0.228833 0.065161 -0.690361 -0.22801 0.063346 -0.691016 -0.229924 0.062921 -0.69078 -0.230042 0.0652 -0.689691 -0.231698 0.062209 -0.690145 -0.231882 0.064999 -0.68879 -0.234107 0.061354 -0.689232 -0.234326 0.064449 -0.687717 -0.237003 0.060504 -0.688049 -0.237193 0.063572 -0.686558 -0.240065 0.059469 -0.686469 -0.240245 0.062271 -0.685107 -0.241468 0.063423 -0.688864 -0.121633 0.033264 -3.2e-05 -0.14872 0.031219 -3.2e-05 -0.110062 0.047074 -0.001059 -0.09688 0.035228 -3.2e-05 -0.108345 0.021431 -0.00106 -0.087199 0.048113 -0.001059 -0.075982 0.03683 -3.2e-05 -0.085437 0.024 -0.00106 -0.068908 0.047133 -0.001059 -0.061003 0.037074 -3.2e-05 -0.067783 0.026827 -0.00106 -0.056678 0.044758 -0.001059 -0.051856 0.036947 -3.2e-05 -0.055984 0.029272 -0.001059 -0.048894 0.042162 -0.001059 -0.04536 0.037023 -3.2e-05 -0.048199 0.031779 -0.001059 -0.044126 0.040156 -0.001058 -0.042185 0.037926 -0.001044 -0.043245 0.034798 -0.001044 -0.135826 0.044311 -0.00106 -0.134392 0.020225 -0.001061 -0.16402 0.019558 -0.001061 -0.180383 0.027586 -3.2e-05 -0.165322 0.039256 -0.00106 -0.191169 0.018866 -0.001061 -0.202458 0.025304 -3.2e-05 -0.192236 0.033987 -0.001061 -0.210365 0.017914 -0.001062 -0.21897 0.022856 -3.2e-05 -0.21129 0.030275 -0.001061 -0.227526 0.016051 -0.001062 -0.236226 0.019748 -0.001062 -0.228237 0.026475 -0.001061 -0.220331 0.028742 -0.016497 -0.219429 0.016923 -0.016503 -0.212759 0.030609 -0.044863 -0.203646 0.032505 -0.016491 -0.202596 0.01809 -0.0165 -0.211787 0.017564 -0.044877 -0.193334 0.034626 -0.044852 -0.181476 0.036711 -0.016485 -0.180233 0.018557 -0.016496 -0.192188 0.018348 -0.04487 -0.16668 0.039951 -0.044838 -0.150309 0.043164 -0.016477 -0.148779 0.019205 -0.01649 -0.165295 0.018906 -0.044861 -0.121528 0.019681 -0.016485 -0.135956 0.019467 -0.044851 -0.137498 0.045037 -0.044823 -0.123085 0.046886 -0.01647 -0.042149 0.036424 -0.016448 -0.044644 0.034669 -0.044805 -0.045436 0.032882 -0.016465 -0.043096 0.039442 -0.016461 -0.043474 0.037947 -0.044801 -0.046241 0.041282 -0.016461 -0.045519 0.040375 -0.044799 -0.049555 0.031497 -0.04481 -0.051982 0.030077 -0.016468 -0.052686 0.043896 -0.01646 -0.050311 0.042601 -0.044798 -0.057427 0.028788 -0.044816 -0.06119 0.02746 -0.016471 -0.062025 0.046731 -0.01646 -0.058196 0.045324 -0.044798 -0.069283 0.026224 -0.052789 -0.075835 0.024802 -0.016475 -0.077432 0.048838 -0.016461 -0.070561 0.047795 -0.044799 -0.086489 0.023313 -0.044831 -0.096485 0.021618 -0.01648 -0.098572 0.048871 -0.016465 -0.088824 0.048865 -0.044803 -0.109816 0.020673 -0.044841 -0.111637 0.047891 -0.044812 -0.237361 0.019949 -0.044882 -0.234956 0.022106 -0.239947 -0.225988 0.025703 -0.436784 -0.234726 0.019012 -0.23995 -0.233204 0.021032 -0.436793 -0.225487 0.019143 -0.436793 -0.211185 0.030771 -0.436772 -0.210314 0.019081 -0.436788 -0.19376 0.034387 -0.436762 -0.192732 0.01979 -0.436782 -0.169874 0.039158 -0.436748 -0.168632 0.020291 -0.436774 -0.142339 0.020795 -0.436765 -0.143722 0.043713 -0.436733 -0.060476 0.034423 -0.43672 -0.059426 0.03736 -0.436715 -0.061258 0.039538 -0.436713 -0.065119 0.031644 -0.440996 -0.065797 0.041463 -0.440982 -0.071738 0.029218 -0.43673 -0.072428 0.043906 -0.436711 -0.082879 0.026761 -0.436737 -0.083404 0.046126 -0.436711 -0.098308 0.024123 -0.428423 -0.099626 0.047119 -0.436715 -0.118903 0.021877 -0.436756 -0.120536 0.046273 -0.436722 -0.135493 0.044805 -0.491698 -0.129493 0.045174 -0.535658 -0.114519 0.046462 -0.493928 -0.112784 0.023514 -0.494061 -0.128034 0.023418 -0.535964 -0.134155 0.021788 -0.491826 -0.111462 0.045946 -0.533592 -0.109983 0.025344 -0.533855 -0.097288 0.045063 -0.535685 -0.096306 0.027724 -0.535915 -0.087296 0.043122 -0.535718 -0.086667 0.029846 -0.535889 -0.081594 0.040955 -0.53749 -0.069991 0.040186 -0.489474 -0.069305 0.032904 -0.489512 -0.08099 0.032071 -0.537624 -0.076941 0.039144 -0.535768 -0.067523 0.038497 -0.491726 -0.075303 0.037199 -0.535797 -0.066778 0.035953 -0.49174 -0.076242 0.034576 -0.535834 -0.15867 0.041611 -0.491717 -0.150166 0.042922 -0.535673 -0.148925 0.022423 -0.535972 -0.157378 0.021337 -0.491831 -0.172371 0.021959 -0.535969 -0.183717 0.020798 -0.491836 -0.184775 0.036275 -0.491751 -0.173483 0.038896 -0.535713 -0.193968 0.021509 -0.535963 -0.202823 0.020373 -0.49184 -0.203717 0.032648 -0.491772 -0.194891 0.034638 -0.535761 -0.210222 0.02086 -0.535957 -0.217302 0.019508 -0.491848 -0.218049 0.029277 -0.491791 -0.211002 0.031312 -0.535807 -0.223787 0.020889 -0.535955 -0.231295 0.020531 -0.491847 -0.230691 0.022683 -0.535921 -0.231497 0.023242 -0.491824 -0.224241 0.026889 -0.535857 -0.153974 0.044855 -0.598036 -0.15284 0.027943 -0.600922 -0.139514 0.045514 -0.598202 -0.13837 0.029542 -0.600916 -0.127919 0.044904 -0.598523 -0.127149 0.031376 -0.600809 -0.120001 0.043413 -0.598921 -0.11951 0.033046 -0.600664 -0.115871 0.041872 -0.600757 -0.115399 0.034945 -0.601929 -0.111774 0.040318 -0.599572 -0.11048 0.038805 -0.599853 -0.111223 0.036759 -0.600184 -0.170395 0.043006 -0.598029 -0.169429 0.027148 -0.600745 -0.187898 0.026744 -0.600459 -0.188762 0.039817 -0.598214 -0.204522 0.026202 -0.598684 -0.205245 0.03641 -0.596972 -0.216806 0.025847 -0.600021 -0.217418 0.034029 -0.598618 -0.227808 0.025873 -0.599809 -0.233257 0.027216 -0.599416 -0.228152 0.030455 -0.598915 -0.236282 0.032627 -0.621694 -0.236246 0.038894 -0.643382 -0.227805 0.036799 -0.622966 -0.236171 0.030978 -0.622086 -0.239867 0.036477 -0.643155 -0.227334 0.030631 -0.624029 -0.236002 0.0356 -0.643943 -0.228639 0.041411 -0.643246 -0.228196 0.035478 -0.644236 -0.22013 0.043695 -0.64546 -0.219611 0.036341 -0.646688 -0.2082 0.046399 -0.647085 -0.207576 0.036927 -0.648654 -0.194381 0.037542 -0.650791 -0.19508 0.049034 -0.648903 -0.131042 0.041949 -0.62885 -0.152661 0.045523 -0.656507 -0.13188 0.039764 -0.627611 -0.131514 0.043556 -0.628547 -0.152129 0.04702 -0.656368 -0.132319 0.044415 -0.626803 -0.154048 0.04833 -0.656894 -0.155038 0.043973 -0.656369 -0.15534 0.049092 -0.655536 -0.159542 0.042971 -0.656812 -0.15898 0.050222 -0.654763 -0.164106 0.041332 -0.655278 -0.164667 0.051166 -0.653678 -0.172149 0.039809 -0.654173 -0.172976 0.051403 -0.652255 -0.182507 0.038404 -0.652653 -0.183326 0.05067 -0.65063 -0.211999 0.058199 -0.676166 -0.211514 0.050935 -0.678642 -0.2057 0.059145 -0.677878 -0.205219 0.052245 -0.680229 -0.200637 0.059429 -0.6794 -0.20029 0.053532 -0.681385 -0.197088 0.059184 -0.680606 -0.175147 0.048937 -0.669393 -0.197681 0.054876 -0.682453 -0.194795 0.058707 -0.681485 -0.173637 0.050444 -0.670335 -0.19449 0.055651 -0.682536 -0.194309 0.058398 -0.682409 -0.17177 0.052591 -0.669382 -0.192807 0.057553 -0.682471 -0.172465 0.05176 -0.670319 -0.19315 0.056649 -0.682646 -0.219199 0.056626 -0.674362 -0.218773 0.04982 -0.676683 -0.226655 0.048809 -0.67449 -0.22703 0.054481 -0.672538 -0.233845 0.047879 -0.672473 -0.234159 0.052331 -0.67093 -0.239112 0.04682 -0.670359 -0.237111 0.041377 -0.658597 -0.237417 0.045403 -0.657651 -0.23943 0.050293 -0.669156 -0.243724 0.046723 -0.669612 -0.242666 0.041262 -0.656632 -0.245821 0.047125 -0.668826 -0.24274 0.042379 -0.656358 -0.243866 0.048635 -0.668958 -0.247946 0.052849 -0.675779 -0.24888 0.058614 -0.682634 -0.245263 0.054418 -0.676239 -0.247901 0.052215 -0.676038 -0.249863 0.05764 -0.682262 -0.245263 0.05263 -0.677392 -0.249047 0.057541 -0.68274 -0.247119 0.059603 -0.683142 -0.24208 0.056011 -0.677416 -0.247023 0.05792 -0.683571 -0.244814 0.060424 -0.683643 -0.244852 0.058729 -0.684812 -0.241973 0.061718 -0.684731 -0.24181 0.059256 -0.685939 -0.238628 0.060034 -0.68731 -0.238812 0.062958 -0.685885 -0.210564 0.061022 -0.687421 -0.227493 0.064302 -0.691391 -0.21118 0.060283 -0.68745 -0.209834 0.061417 -0.686944 -0.227351 0.064692 -0.691294 -0.228299 0.064956 -0.691009 -0.228731 0.063829 -0.691274 -0.211688 0.059292 -0.686998 -0.228875 0.065103 -0.690631 -0.229733 0.063276 -0.69099 -0.229833 0.065188 -0.690072 -0.231159 0.062649 -0.6905 -0.231304 0.065114 -0.689306 -0.233187 0.061881 -0.689745 -0.233384 0.06475 -0.68834 -0.235766 0.061043 -0.688722 -0.235967 0.064055 -0.687247 -0.246331 0.060677 -0.685523 -0.245599 0.061176 -0.685678 -0.245479 0.060556 -0.686049 -0.244505 0.061717 -0.686044 -0.244439 0.060806 -0.686503 -0.243114 0.062328 -0.686565 -0.243036 0.061183 -0.687138 -0.234684 0.064402 -0.690341 -0.234847 0.063969 -0.690448 -0.234826 0.064503 -0.690195 -0.235181 0.063703 -0.690364 -0.235229 0.064569 -0.689937 -0.235795 0.063389 -0.690162 -0.235857 0.064587 -0.689574 -0.23672 0.063003 -0.689819 -0.236816 0.064479 -0.689085 -0.239502 0.062086 -0.688699 -0.237984 0.062535 -0.689324 -0.238101 0.064185 -0.688499 -0.239604 0.063721 -0.687888 -0.231535 0.026053 -0.568239 -0.23137 0.023737 -0.568534 -0.220161 0.031074 -0.567954 -0.219533 0.022865 -0.568651 -0.207965 0.034018 -0.569362 -0.207215 0.023731 -0.570275 -0.092232 0.036782 -0.568424 -0.092861 0.038917 -0.568242 -0.093822 0.034159 -0.567015 -0.094402 0.040309 -0.56654 -0.104434 0.047981 -0.239875 -0.102292 0.022298 -0.250252 -0.084441 0.047947 -0.239868 -0.069828 0.045989 -0.239866 -0.069008 0.027634 -0.229538 -0.060862 0.043325 -0.239866 -0.060186 0.030206 -0.23988 -0.054762 0.040863 -0.239867 -0.051738 0.039054 -0.239868 -0.053994 0.032887 -0.239875 -0.050907 0.03621 -0.239871 -0.127682 0.046107 -0.239884 -0.126187 0.020378 -0.239913 -0.152134 0.019874 -0.239922 -0.153577 0.042537 -0.239897 -0.181564 0.019273 -0.239933 -0.182747 0.036572 -0.239913 -0.202911 0.018799 -0.23994 -0.20391 0.032519 -0.239925 -0.219088 0.017845 -0.239946 -0.219922 0.028753 -0.239934 -0.229296 0.025226 -0.044874 -0.22872 0.017577 -0.044882 -0.236806 0.023193 -0.016503 -0.236394 0.01656 -0.016505 -0.224982 0.061165 -0.681905 -0.224651 0.056017 -0.683925 -0.220415 0.062071 -0.683342 -0.220062 0.057083 -0.685291 -0.216657 0.062476 -0.684631 -0.21639 0.058143 -0.686298 -0.213957 0.06243 -0.685666 -0.212912 0.058818 -0.686748 -0.212225 0.062153 -0.686421 -0.210249 0.06164 -0.686729 -0.230156 0.059797 -0.680391 -0.229857 0.055068 -0.682262 -0.235506 0.054139 -0.680417 -0.235764 0.057999 -0.678863 -0.240332 0.053302 -0.678783 -0.240764 0.056567 -0.677874 -0.244232 0.052881 -0.677832 -0.235073 0.046248 -0.658123 -0.234732 0.041698 -0.659247 -0.227911 0.047957 -0.658721 -0.227501 0.042177 -0.660133 -0.218822 0.050275 -0.66035 -0.218334 0.042947 -0.662129 -0.207548 0.043784 -0.664357 -0.208114 0.052807 -0.662236 -0.172433 0.05298 -0.669203 -0.175382 0.054032 -0.669276 -0.177098 0.048326 -0.669141 -0.178415 0.054861 -0.668444 -0.182772 0.047414 -0.669037 -0.183259 0.055449 -0.667268 -0.189473 0.045991 -0.66788 -0.190149 0.055359 -0.665758 -0.197942 0.044701 -0.666297 -0.198564 0.054458 -0.66405 -0.169411 0.047624 -0.625278 -0.168455 0.033035 -0.627772 -0.156892 0.048371 -0.626104 -0.155889 0.034481 -0.628479 -0.146739 0.047999 -0.626874 -0.146047 0.036163 -0.628886 -0.139723 0.046787 -0.627526 -0.139295 0.037657 -0.629084 -0.134205 0.045163 -0.626632 -0.133796 0.038931 -0.627716 -0.183592 0.045842 -0.624472 -0.182759 0.032267 -0.62677 -0.198765 0.031765 -0.625611 -0.199499 0.042847 -0.623736 -0.212885 0.031269 -0.624364 -0.213497 0.039903 -0.622897 -0.223592 0.030925 -0.624593 -0.224106 0.037791 -0.623419 -0.201223 0.035307 -0.569253 -0.200415 0.023899 -0.570353 -0.182287 0.038943 -0.567492 -0.181311 0.024188 -0.568887 -0.1602 0.024625 -0.568997 -0.161302 0.042654 -0.567399 -0.09626 0.03309 -0.567032 -0.096803 0.041281 -0.566523 -0.102995 0.031212 -0.568758 -0.103561 0.043247 -0.567913 -0.111833 0.029315 -0.568865 -0.112737 0.044943 -0.567701 -0.124753 0.027217 -0.568949 -0.126074 0.04559 -0.567507 -0.141309 0.025455 -0.56902 -0.142585 0.044795 -0.567403 -0.072033 0.031703 -0.489515 -0.072678 0.041277 -0.489474 -0.079248 0.029407 -0.491774 -0.079918 0.043575 -0.491706 -0.089551 0.027156 -0.491788 -0.090606 0.045624 -0.491694 -0.104822 0.024702 -0.49405 -0.106388 0.046471 -0.493929 -0.093417 0.023624 -0.250247 -0.075892 0.026368 -0.229541 -0.098277 0.046092 -0.491691 -0.096964 0.025917 -0.491795 -0.085123 0.044622 -0.4917 -0.084269 0.028285 -0.491781 -0.07641 0.042423 -0.491712 -0.075761 0.030555 -0.491767 -0.218772 0.038732 -0.622595 -0.218208 0.030974 -0.623918 -0.206587 0.041363 -0.623314 -0.205914 0.031519 -0.624983 -0.191548 0.044363 -0.624105 -0.190764 0.032012 -0.626195 -0.175552 0.032636 -0.627278 -0.176447 0.046768 -0.624873 -0.137023 0.038406 -0.629117 -0.137435 0.046078 -0.627798 -0.142586 0.036913 -0.62899 -0.143141 0.047409 -0.627204 -0.150876 0.035322 -0.62869 -0.151729 0.048216 -0.626492 -0.162103 0.033744 -0.628135 -0.163089 0.048031 -0.625691 -0.203302 0.053658 -0.663146 -0.194315 0.054932 -0.664909 -0.193662 0.045338 -0.667101 -0.202707 0.044236 -0.665337 -0.186648 0.055428 -0.666521 -0.186063 0.046704 -0.668472 -0.180776 0.05517 -0.667867 -0.180387 0.048022 -0.66942 -0.176853 0.054449 -0.66887 -0.174393 0.053636 -0.669566 -0.213475 0.051551 -0.66129 -0.212948 0.043363 -0.663244 -0.222979 0.042561 -0.661119 -0.223427 0.049106 -0.659525 -0.231058 0.041794 -0.659363 -0.231436 0.04698 -0.658097 -0.242236 0.052949 -0.678137 -0.238187 0.057165 -0.678199 -0.23795 0.053717 -0.679591 -0.232966 0.058903 -0.679624 -0.232687 0.054602 -0.681339 -0.227237 0.05554 -0.683101 -0.227552 0.060495 -0.681149 -0.211664 0.061987 -0.686688 -0.213066 0.062296 -0.686051 -0.215057 0.058589 -0.686637 -0.215275 0.062463 -0.685157 -0.218195 0.057616 -0.685806 -0.218507 0.062288 -0.683993 -0.222333 0.056548 -0.684619 -0.222677 0.061633 -0.682627 -0.241053 0.062839 -0.686512 -0.247724 0.059315 -0.6844 -0.240926 0.060858 -0.687498 -0.231778 0.064451 -0.69098 -0.191749 0.037083 -0.567591 -0.190854 0.023982 -0.568824 -0.170755 0.0244 -0.568944 -0.171794 0.040824 -0.567442 -0.100013 0.032176 -0.568693 -0.100559 0.04228 -0.568008 -0.107302 0.030267 -0.568812 -0.108031 0.044115 -0.567807 -0.118171 0.028264 -0.568907 -0.11929 0.045306 -0.567602 -0.150681 0.025019 -0.569012 -0.132938 0.026316 -0.568986 -0.134246 0.045237 -0.567452 -0.151872 0.043771 -0.567398 -0.084654 0.02499 -0.239894 -0.228165 0.016614 -0.016504 -0.23714 0.019781 -0.016504 -0.228833 0.026018 -0.0165 -0.211795 0.059911 -0.687346 -0.210606 0.061306 -0.687302 -0.21085 0.060655 -0.687443 -0.243587 0.055098 -0.676647 -0.246557 0.052259 -0.676533 -0.248011 0.052505 -0.675885 -0.246658 0.053622 -0.675992 -0.2401 0.043743 -0.656658 -0.242883 0.041779 -0.656464 -0.239907 0.041142 -0.657262 -0.173009 0.051103 -0.670336 -0.172571 0.052303 -0.67018 -0.174788 0.049855 -0.670201 -0.132333 0.044064 -0.628395 -0.131223 0.042768 -0.628701 -0.131861 0.040996 -0.62894 -0.231847 0.030639 -0.622472 -0.236509 0.031749 -0.621876 -0.232141 0.034576 -0.621733 -0.226038 0.028556 -0.568094 -0.231827 0.024828 -0.568389 -0.225638 0.023253 -0.568597 -0.214166 0.032524 -0.567881 -0.21347 0.023214 -0.568663 -0.093317 0.03553 -0.56852 -0.092475 0.037868 -0.568332 -0.093943 0.039601 -0.568177 -0.224998 0.02625 -0.491808 -0.231839 0.021805 -0.491836 -0.22452 0.019963 -0.491848 -0.210961 0.031004 -0.491782 -0.210134 0.019918 -0.491844 -0.194437 0.034427 -0.491762 -0.193463 0.020592 -0.491838 -0.171789 0.038949 -0.491734 -0.170613 0.021067 -0.491834 -0.145682 0.021545 -0.491829 -0.146994 0.043267 -0.491707 -0.068061 0.034464 -0.491749 -0.067065 0.037247 -0.491733 -0.068803 0.039312 -0.491722 -0.123461 0.022572 -0.491821 -0.125008 0.045694 -0.491692 -0.115968 0.0471 -0.239879 -0.114238 0.021254 -0.239908 -0.094302 0.048024 -0.239871 -0.076959 0.047009 -0.239867 -0.065212 0.044665 -0.239866 -0.064481 0.028959 -0.239883 -0.05772 0.04208 -0.239866 -0.057002 0.031533 -0.239878 -0.053168 0.039964 -0.239867 -0.051227 0.037657 -0.239869 -0.052339 0.034545 -0.239873 -0.140532 0.044388 -0.23989 -0.139066 0.020107 -0.239918 -0.166922 0.019574 -0.239927 -0.168237 0.039562 -0.239905 -0.192453 0.019043 -0.239936 -0.193542 0.034507 -0.239919 -0.21108 0.018297 -0.239943 -0.212003 0.030681 -0.239929 -0.227154 0.018365 -0.239948 -0.235335 0.02047 -0.239949 -0.22769 0.02542 -0.239941 -0.110736 0.047936 -0.016467 -0.108906 0.020605 -0.016483 -0.087859 0.048919 -0.016463 -0.085996 0.023199 -0.016478 -0.069541 0.047829 -0.016461 -0.068332 0.026141 -0.016473 -0.057216 0.045321 -0.01646 -0.05646 0.028766 -0.01647 -0.049368 0.042572 -0.01646 -0.048618 0.031464 -0.016467 -0.044584 0.040369 -0.016461 -0.042522 0.037961 -0.016454 -0.043674 0.034649 -0.016456 -0.136587 0.045097 -0.016473 -0.135048 0.019423 -0.016488 -0.164583 0.018882 -0.016493 -0.165972 0.039945 -0.016481 -0.191653 0.018332 -0.016498 -0.192797 0.034562 -0.016488 -0.211086 0.017508 -0.016501 -0.212067 0.030646 -0.016494 -0.22784 0.021259 -3.2e-05 -0.210778 0.024096 -3.2e-05 -0.191668 0.026425 -3.2e-05 -0.164631 0.029406 -3.2e-05 -0.135062 0.032269 -3.2e-05 -0.043656 0.037475 -2.4e-05 -0.048517 0.036968 -3.2e-05 -0.056297 0.037013 -3.2e-05 -0.068306 0.03698 -3.2e-05 -0.086277 0.036057 -3.2e-05 -0.109162 0.034252 -3.2e-05 -numsurf 840 -SURF 0x10 -mat 1 -refs 3 -478 0.5 0.5 -187 0.0 0.0 -459 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -459 0.5 0.0 -479 1.0 0.5 -478 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -478 0.5 0.5 -479 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -479 1.0 0.5 -459 0.5 0.0 -189 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -476 0.5 0.5 -188 0.0 0.0 -458 0.499999433756 -2.17116351564e-07 -SURF 0x10 -mat 1 -refs 3 -458 0.499999433756 -2.17116351564e-07 -477 0.999999403954 0.499999791384 -476 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -476 0.5 0.5 -477 0.999999403954 0.499999791384 -SURF 0x10 -mat 1 -refs 3 -477 0.999999403954 0.499999791384 -458 0.499999433756 -2.17116351564e-07 -186 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -475 0.5 0.5 -185 0.0 0.0 -457 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -457 0.5 0.0 -478 1.0 0.5 -475 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -475 0.5 0.5 -478 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -478 1.0 0.5 -457 0.5 0.0 -187 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -477 0.499999165535 0.499999791384 -186 0.0 0.0 -456 0.499999165535 -1.94514967689e-07 -SURF 0x10 -mat 1 -refs 3 -456 0.499999165535 -1.94514967689e-07 -474 1.0 0.5 -477 0.499999165535 0.499999791384 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -477 0.499999165535 0.499999791384 -474 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -474 1.0 0.5 -456 0.499999165535 -1.94514967689e-07 -184 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -473 0.5 0.5 -183 0.0 0.0 -455 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -455 0.5 0.0 -475 1.0 0.5 -473 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -473 0.5 0.5 -475 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -475 1.0 0.5 -455 0.5 0.0 -185 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -474 0.5 0.5 -184 0.0 0.0 -454 0.499998778105 -1.77793907596e-07 -SURF 0x10 -mat 1 -refs 3 -454 0.499998778105 -1.77793907596e-07 -472 0.999998807907 0.499999821186 -474 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -474 0.5 0.5 -472 0.999998807907 0.499999821186 -SURF 0x10 -mat 1 -refs 3 -472 0.999998807907 0.499999821186 -454 0.499998778105 -1.77793907596e-07 -182 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -471 0.5 0.5 -180 0.0 0.0 -453 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -453 0.5 0.0 -473 1.0 0.5 -471 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -471 0.5 0.5 -473 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -473 1.0 0.5 -453 0.5 0.0 -183 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -472 0.49999833107 0.499999850988 -182 0.0 0.0 -452 0.49999833107 -1.46900518416e-07 -SURF 0x10 -mat 1 -refs 3 -452 0.49999833107 -1.46900518416e-07 -470 1.0 0.5 -472 0.49999833107 0.499999850988 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -472 0.49999833107 0.499999850988 -470 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -470 1.0 0.5 -452 0.49999833107 -1.46900518416e-07 -181 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -469 0.5 0.5 -178 0.0 0.0 -451 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -451 0.5 0.0 -471 1.0 0.5 -469 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -469 0.5 0.5 -471 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -471 1.0 0.5 -451 0.5 0.0 -180 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -470 0.5 0.5 -181 0.0 0.0 -449 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -449 0.5 0.0 -468 1.0 0.5 -470 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -470 0.5 0.5 -468 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -468 1.0 0.5 -449 0.5 0.0 -179 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -467 0.5 0.5 -176 0.0 0.0 -448 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -448 0.5 0.0 -469 1.0 0.5 -467 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -467 0.5 0.5 -469 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -469 1.0 0.5 -448 0.5 0.0 -178 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -464 0.5 0.5 -172 0.0 0.0 -438 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -438 0.5 0.0 -466 1.0 0.5 -464 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -464 0.5 0.5 -466 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -466 1.0 0.5 -438 0.5 0.0 -174 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -465 0.5 0.5 -175 0.0 0.0 -437 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -437 0.5 0.0 -463 1.0 0.5 -465 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -465 0.5 0.5 -463 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -463 1.0 0.5 -437 0.5 0.0 -173 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -462 0.5 0.5 -171 0.0 0.0 -436 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -436 0.5 0.0 -464 1.0 0.5 -462 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -462 0.5 0.5 -464 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -464 1.0 0.5 -436 0.5 0.0 -172 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -463 0.5 0.5 -173 0.0 0.0 -434 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -434 0.5 0.0 -461 1.0 0.5 -463 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -463 0.5 0.5 -461 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -461 1.0 0.5 -434 0.5 0.0 -170 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -461 0.5 0.5 -170 0.0 0.0 -428 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -428 0.5 0.0 -460 1.0 0.5 -461 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -192 1.0 1.0 -461 0.5 0.5 -460 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -460 1.0 0.5 -428 0.5 0.0 -168 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -522 0.499998867512 0.500000119209 -153 0.0 0.0 -403 0.500000596046 4.33204121464e-08 -SURF 0x10 -mat 1 -refs 3 -403 0.500000596046 4.33204121464e-08 -450 1.00000047684 0.499999821186 -522 0.499998867512 0.500000119209 -SURF 0x10 -mat 1 -refs 3 -181 1.0 1.0 -522 0.499998867512 0.500000119209 -450 1.00000047684 0.499999821186 -SURF 0x10 -mat 1 -refs 3 -450 1.00000047684 0.499999821186 -403 0.500000596046 4.33204121464e-08 -154 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -446 0.500002801418 0.500000119209 -159 0.0 0.0 -407 0.500002801418 1.42463008501e-07 -SURF 0x10 -mat 1 -refs 3 -407 0.500002801418 1.42463008501e-07 -524 1.0 0.5 -446 0.500002801418 0.500000119209 -SURF 0x10 -mat 1 -refs 3 -176 1.0 1.0 -446 0.500002801418 0.500000119209 -524 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -524 1.0 0.5 -407 0.500002801418 1.42463008501e-07 -157 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -530 0.5 0.5 -162 0.0 0.0 -435 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -435 0.5 0.0 -437 1.0 0.5 -530 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -175 1.0 1.0 -530 0.5 0.5 -437 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -437 1.0 0.5 -435 0.5 0.0 -173 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -432 0.5 0.5 -164 0.0 0.0 -531 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -531 0.5 0.0 -436 1.0 0.5 -432 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -171 1.0 1.0 -432 0.5 0.5 -436 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -436 1.0 0.5 -531 0.5 0.0 -172 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -532 0.5 0.5 -122 0.0 0.0 -420 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -420 0.5 0.0 -421 1.0 0.5 -532 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -162 1.0 1.0 -532 0.5 0.5 -421 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -421 1.0 0.5 -420 0.5 0.0 -165 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -419 0.5 0.5 -123 0.0 0.0 -533 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -533 0.5 0.0 -418 1.0 0.5 -419 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -164 1.0 1.0 -419 0.5 0.5 -418 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -418 1.0 0.5 -533 0.5 0.0 -163 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -408 0.500003755093 0.500000059605 -128 0.0 0.0 -384 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -384 0.5 0.0 -540 1.0 0.5 -408 0.500003755093 0.500000059605 -SURF 0x10 -mat 1 -refs 3 -159 1.0 1.0 -408 0.500003755093 0.500000059605 -540 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -540 1.0 0.5 -384 0.5 0.0 -130 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -542 0.499998539686 0.500000059605 -134 0.0 0.0 -387 0.50000077486 -1.54451669232e-08 -SURF 0x10 -mat 1 -refs 3 -387 0.50000077486 -1.54451669232e-08 -402 0.99999922514 0.5 -542 0.499998539686 0.500000059605 -SURF 0x10 -mat 1 -refs 3 -154 1.0 1.0 -542 0.499998539686 0.500000059605 -402 0.99999922514 0.5 -SURF 0x10 -mat 1 -refs 3 -402 0.99999922514 0.5 -387 0.50000077486 -1.54451669232e-08 -133 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -383 0.500000834465 0.5 -109 0.0 0.0 -347 0.500004470348 -4.90296542921e-07 -SURF 0x10 -mat 1 -refs 3 -347 0.500004470348 -4.90296542921e-07 -558 1.00000357628 0.499999493361 -383 0.500000834465 0.5 -SURF 0x10 -mat 1 -refs 3 -130 1.0 1.0 -383 0.500000834465 0.5 -558 1.00000357628 0.499999493361 -SURF 0x10 -mat 1 -refs 3 -558 1.00000357628 0.499999493361 -347 0.500004470348 -4.90296542921e-07 -107 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -559 0.499993622303 0.499999463558 -106 0.0 0.0 -348 0.500000953674 3.98092803167e-09 -SURF 0x10 -mat 1 -refs 3 -348 0.500000953674 3.98092803167e-09 -380 1.00000548363 0.500000536442 -559 0.499993622303 0.499999463558 -SURF 0x10 -mat 1 -refs 3 -131 1.0 1.0 -559 0.499993622303 0.499999463558 -380 1.00000548363 0.500000536442 -SURF 0x10 -mat 1 -refs 3 -380 1.00000548363 0.500000536442 -348 0.500000953674 3.98092803167e-09 -108 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -368 0.5 0.5 -116 0.0 0.0 -566 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -566 0.5 0.0 -371 1.0 0.5 -368 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -123 1.0 1.0 -368 0.5 0.5 -371 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -371 1.0 0.5 -566 0.5 0.0 -124 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -567 0.499999344349 0.499999165535 -117 0.0 0.0 -365 0.499999344349 -8.25561585316e-07 -SURF 0x10 -mat 1 -refs 3 -365 0.499999344349 -8.25561585316e-07 -370 1.0 0.5 -567 0.499999344349 0.499999165535 -SURF 0x10 -mat 1 -refs 3 -125 1.0 1.0 -567 0.499999344349 0.499999165535 -370 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -370 1.0 0.5 -365 0.499999344349 -8.25561585316e-07 -122 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -568 0.5 0.5 -90 0.0 0.0 -484 0.499999523163 -2.79571537476e-07 -SURF 0x10 -mat 1 -refs 3 -484 0.499999523163 -2.79571537476e-07 -357 1.00000047684 0.500000298023 -568 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -112 1.0 1.0 -568 0.5 0.5 -357 1.00000047684 0.500000298023 -SURF 0x10 -mat 1 -refs 3 -357 1.00000047684 0.500000298023 -484 0.499999523163 -2.79571537476e-07 -114 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -485 0.499999552965 0.499999821186 -91 0.0 0.0 -569 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -569 0.5 0.0 -356 0.999999523163 0.499999821186 -485 0.499999552965 0.499999821186 -SURF 0x10 -mat 1 -refs 3 -115 1.0 1.0 -485 0.499999552965 0.499999821186 -356 0.999999523163 0.499999821186 -SURF 0x10 -mat 1 -refs 3 -356 0.999999523163 0.499999821186 -569 0.5 0.0 -113 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -574 0.500002801418 0.500000476837 -82 0.0 0.0 -312 0.500003159046 4.67448785457e-07 -SURF 0x10 -mat 1 -refs 3 -312 0.500003159046 4.67448785457e-07 -488 0.999999642372 0.5 -574 0.500002801418 0.500000476837 -SURF 0x10 -mat 1 -refs 3 -108 1.0 1.0 -574 0.500002801418 0.500000476837 -488 0.999999642372 0.5 -SURF 0x10 -mat 1 -refs 3 -488 0.999999642372 0.5 -312 0.500003159046 4.67448785457e-07 -84 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -489 0.499997645617 0.500000476837 -85 0.0 0.0 -309 0.500002741814 -4.71542989544e-07 -SURF 0x10 -mat 1 -refs 3 -309 0.500002741814 -4.71542989544e-07 -575 1.00000035763 0.5 -489 0.499997645617 0.500000476837 -SURF 0x10 -mat 1 -refs 3 -109 1.0 1.0 -489 0.499997645617 0.500000476837 -575 1.00000035763 0.5 -SURF 0x10 -mat 1 -refs 3 -575 1.00000035763 0.5 -309 0.500002741814 -4.71542989544e-07 -83 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -584 0.5 0.5 -61 0.0 0.0 -287 0.500000417233 1.65939383123e-07 -SURF 0x10 -mat 1 -refs 3 -287 0.500000417233 1.65939383123e-07 -311 0.999999523163 0.499999821186 -584 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -84 1.0 1.0 -584 0.5 0.5 -311 0.999999523163 0.499999821186 -SURF 0x10 -mat 1 -refs 3 -311 0.999999523163 0.499999821186 -287 0.500000417233 1.65939383123e-07 -59 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -310 0.499999761581 0.500000178814 -58 0.0 0.0 -288 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -288 0.5 0.0 -585 0.999999761581 0.500000178814 -310 0.499999761581 0.500000178814 -SURF 0x10 -mat 1 -refs 3 -85 1.0 1.0 -310 0.499999761581 0.500000178814 -585 0.999999761581 0.500000178814 -SURF 0x10 -mat 1 -refs 3 -585 0.999999761581 0.500000178814 -288 0.5 0.0 -60 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -300 0.5 0.500000238419 -66 0.0 0.0 -590 0.5 -1.12242503292e-07 -SURF 0x10 -mat 1 -refs 3 -590 0.5 -1.12242503292e-07 -304 1.00000035763 0.500000238419 -300 0.5 0.500000238419 -SURF 0x10 -mat 1 -refs 3 -77 1.0 1.0 -300 0.5 0.500000238419 -304 1.00000035763 0.500000238419 -SURF 0x10 -mat 1 -refs 3 -304 1.00000035763 0.500000238419 -590 0.5 -1.12242503292e-07 -79 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -591 0.5 0.499999880791 -67 0.0 0.0 -299 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -299 0.5 0.0 -303 0.999999642372 0.499999701977 -591 0.5 0.499999880791 -SURF 0x10 -mat 1 -refs 3 -78 1.0 1.0 -591 0.5 0.499999880791 -303 0.999999642372 0.499999701977 -SURF 0x10 -mat 1 -refs 3 -303 0.999999642372 0.499999701977 -299 0.5 0.0 -76 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -491 0.5 0.499999910593 -40 0.0 0.0 -592 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -592 0.5 0.0 -293 1.0 0.499999910593 -491 0.5 0.499999910593 -SURF 0x10 -mat 1 -refs 3 -66 1.0 1.0 -491 0.5 0.499999910593 -293 1.0 0.499999910593 -SURF 0x10 -mat 1 -refs 3 -293 1.0 0.499999910593 -592 0.5 0.0 -64 1.0 0.0 -SURF 0x10 -mat 1 -refs 3 -593 0.5 0.5 -38 0.0 0.0 -260 0.5 0.0 -SURF 0x10 -mat 1 -refs 3 -260 0.5 0.0 -494 1.0 0.5 -593 0.5 0.5 -SURF 0x10 -mat 1 -refs 3 -62 1.0 1.0 -593 0.5 0.5 -494 1.0 0.5 -SURF 0x10 -mat 1 -refs 3 -494 1.0 0.5 -260 0.5 0.0 -36 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -589 0.499999850988 0.499999850988 -65 0.0 0.0 -294 0.499999821186 -1.66163502513e-07 -594 0.586517333984 0.500067651272 -SURF 0x10 -mat 1 -refs 4 -80 1.0 1.0 -589 0.499999850988 0.499999850988 -594 0.586517333984 0.500067651272 -305 0.999999642372 0.999999642372 -SURF 0x10 -mat 1 -refs 4 -594 0.586517333984 0.500067651272 -294 0.499999821186 -1.66163502513e-07 -67 1.0 0.0 -591 1.00000011921 0.5 -SURF 0x10 -mat 1 -refs 4 -305 0.999999642372 0.999999642372 -594 0.586517333984 0.500067651272 -591 1.00000011921 0.5 -78 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -306 1.0 0.5 -79 1.0 1.0 -590 0.500000119209 0.5 -595 0.909103035927 0.499959677458 -SURF 0x10 -mat 1 -refs 4 -81 1.0 0.0 -306 1.0 0.5 -595 0.909103035927 0.499959677458 -588 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -595 0.909103035927 0.499959677458 -590 0.500000119209 0.5 -66 0.0 0.0 -293 0.500000119209 1.04914271715e-11 -SURF 0x10 -mat 1 -refs 4 -588 1.0 0.0 -595 0.909103035927 0.499959677458 -293 0.500000119209 1.04914271715e-11 -64 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -587 0.499999821186 0.499999821186 -63 0.0 0.0 -292 0.5 0.0 -596 0.613853693008 0.500074982643 -SURF 0x10 -mat 1 -refs 4 -83 1.0 1.0 -587 0.499999821186 0.499999821186 -596 0.613853693008 0.500074982643 -307 1.00000035763 1.00000035763 -SURF 0x10 -mat 1 -refs 4 -596 0.613853693008 0.500074982643 -292 0.5 0.0 -65 1.0 0.0 -589 1.0 0.499999821186 -SURF 0x10 -mat 1 -refs 4 -307 1.00000035763 1.00000035763 -596 0.613853693008 0.500074982643 -589 1.0 0.499999821186 -80 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -308 1.0 0.499999731779 -81 1.0 1.0 -588 0.5 0.5 -597 0.891124725342 0.499952942133 -SURF 0x10 -mat 1 -refs 4 -82 1.0 0.0 -308 1.0 0.499999731779 -597 0.891124725342 0.499952942133 -586 1.0 -1.36388536021e-07 -SURF 0x10 -mat 1 -refs 4 -597 0.891124725342 0.499952942133 -588 0.5 0.5 -64 0.0 0.0 -291 0.500000178814 1.65868542013e-07 -SURF 0x10 -mat 1 -refs 4 -586 1.0 -1.36388536021e-07 -597 0.891124725342 0.499952942133 -291 0.500000178814 1.65868542013e-07 -62 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -585 0.500000178814 0.500000178814 -60 0.0 0.0 -290 0.5 0.0 -598 0.595433592796 0.500064373016 -SURF 0x10 -mat 1 -refs 4 -85 1.0 1.0 -585 0.500000178814 0.500000178814 -598 0.595433592796 0.500064373016 -309 0.999999642372 0.999999642372 -SURF 0x10 -mat 1 -refs 4 -598 0.595433592796 0.500064373016 -290 0.5 0.0 -63 1.0 0.0 -587 1.00000011921 0.499999821186 -SURF 0x10 -mat 1 -refs 4 -309 0.999999642372 0.999999642372 -598 0.595433592796 0.500064373016 -587 1.00000011921 0.499999821186 -83 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -312 1.0 0.499999433756 -82 1.0 1.0 -586 0.500000298023 0.500000178814 -599 0.909188330173 0.499946832657 -SURF 0x10 -mat 1 -refs 4 -84 1.0 0.0 -312 1.0 0.499999433756 -599 0.909188330173 0.499946832657 -584 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -599 0.909188330173 0.499946832657 -586 0.500000298023 0.500000178814 -62 0.0 0.0 -289 0.500000298023 1.659012554e-07 -SURF 0x10 -mat 1 -refs 4 -584 1.0 0.0 -599 0.909188330173 0.499946832657 -289 0.500000298023 1.659012554e-07 -61 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -565 0.499999970198 0.499999970198 -114 0.0 0.0 -359 0.500000834465 -6.50166612104e-07 -600 0.510697543621 0.508967399597 -SURF 0x10 -mat 1 -refs 4 -127 1.0 1.0 -565 0.499999970198 0.499999970198 -600 0.510697543621 0.508967399597 -372 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -600 0.510697543621 0.508967399597 -359 0.500000834465 -6.50166612104e-07 -117 1.0 0.0 -567 1.00000011921 0.499999344349 -SURF 0x10 -mat 1 -refs 4 -372 1.0 1.0 -600 0.510697543621 0.508967399597 -567 1.00000011921 0.499999344349 -125 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -373 1.0 0.5 -124 1.0 1.0 -566 0.5 0.5 -601 0.998175323009 0.508975565434 -SURF 0x10 -mat 1 -refs 4 -126 1.0 0.0 -373 1.0 0.5 -601 0.998175323009 0.508975565434 -564 1.0 7.27681594981e-07 -SURF 0x10 -mat 1 -refs 4 -601 0.998175323009 0.508975565434 -566 0.5 0.5 -116 0.0 0.0 -358 0.499999314547 6.53738174705e-10 -SURF 0x10 -mat 1 -refs 4 -564 1.0 7.27681594981e-07 -601 0.998175323009 0.508975565434 -358 0.499999314547 6.53738174705e-10 -115 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -563 0.499999403954 0.499999403954 -112 0.0 0.0 -357 0.499999880791 6.23802975497e-07 -602 0.510802328587 0.510802328587 -SURF 0x10 -mat 1 -refs 4 -143 1.0 1.0 -563 0.499999403954 0.499999403954 -602 0.510802328587 0.510802328587 -374 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -602 0.510802328587 0.510802328587 -357 0.499999880791 6.23802975497e-07 -114 1.0 0.0 -565 0.999999463558 0.5 -SURF 0x10 -mat 1 -refs 4 -374 1.0 1.0 -602 0.510802328587 0.510802328587 -565 0.999999463558 0.5 -127 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -375 1.0 0.5 -126 1.0 1.0 -564 0.499999463558 0.5 -603 1.0 0.497726738453 -SURF 0x10 -mat 1 -refs 4 -142 1.0 0.0 -375 1.0 0.5 -603 1.0 0.497726738453 -562 1.0 4.03749169209e-07 -SURF 0x10 -mat 1 -refs 4 -603 1.0 0.497726738453 -564 0.499999463558 0.5 -115 0.0 0.0 -356 0.499999254942 -6.26263727099e-07 -SURF 0x10 -mat 1 -refs 4 -562 1.0 4.03749169209e-07 -603 1.0 0.497726738453 -356 0.499999254942 -6.26263727099e-07 -113 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -560 0.5 0.5 -96 0.0 0.0 -355 0.499999701977 -5.93836659846e-07 -604 0.592199027538 0.510390043259 -SURF 0x10 -mat 1 -refs 4 -141 1.0 1.0 -560 0.5 0.5 -604 0.592199027538 0.510390043259 -377 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -604 0.592199027538 0.510390043259 -355 0.499999701977 -5.93836659846e-07 -112 1.0 0.0 -563 1.00000047684 0.499999403954 -SURF 0x10 -mat 1 -refs 4 -377 1.0 1.0 -604 0.592199027538 0.510390043259 -563 1.00000047684 0.499999403954 -143 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -376 1.0 0.5 -142 1.0 1.0 -562 0.500000298023 0.500000596046 -605 0.916085362434 0.509558856487 -SURF 0x10 -mat 1 -refs 4 -140 1.0 0.0 -376 1.0 0.5 -605 0.916085362434 0.509558856487 -561 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -605 0.916085362434 0.509558856487 -562 0.500000298023 0.500000596046 -113 0.0 0.0 -354 0.499998956919 -5.9695236132e-07 -SURF 0x10 -mat 1 -refs 4 -561 1.0 0.0 -605 0.916085362434 0.509558856487 -354 0.499998956919 -5.9695236132e-07 -97 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -393 1.0 0.5 -140 1.0 1.0 -561 0.5 0.5 -606 0.926591515541 0.507930636406 -SURF 0x10 -mat 1 -refs 4 -138 1.0 0.0 -393 1.0 0.5 -606 0.926591515541 0.507930636406 -551 1.0 3.1374256082e-07 -SURF 0x10 -mat 1 -refs 4 -606 0.926591515541 0.507930636406 -561 0.5 0.5 -97 0.0 0.0 -353 0.499999791384 9.43447875379e-10 -SURF 0x10 -mat 1 -refs 4 -551 1.0 3.1374256082e-07 -606 0.926591515541 0.507930636406 -353 0.499999791384 9.43447875379e-10 -99 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -550 0.500000536442 0.500000536442 -98 0.0 0.0 -352 0.499999433756 5.72148678657e-07 -607 0.584154903889 0.508775293827 -SURF 0x10 -mat 1 -refs 4 -139 1.0 1.0 -550 0.500000536442 0.500000536442 -607 0.584154903889 0.508775293827 -394 0.999999940395 0.999999940395 -SURF 0x10 -mat 1 -refs 4 -607 0.584154903889 0.508775293827 -352 0.499999433756 5.72148678657e-07 -96 1.0 0.0 -560 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -394 0.999999940395 0.999999940395 -607 0.584154903889 0.508775293827 -560 1.0 0.5 -141 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -346 0.49999627471 -5.41566407719e-07 -106 1.0 0.0 -559 1.0 7.3656983659e-06 -608 0.889534235001 0.501856803894 -SURF 0x10 -mat 1 -refs 4 -105 0.0 0.0 -346 0.49999627471 -5.41566407719e-07 -608 0.889534235001 0.501856803894 -557 0.500000655651 0.5 -SURF 0x10 -mat 1 -refs 4 -608 0.889534235001 0.501856803894 -559 1.0 7.3656983659e-06 -131 1.0 0.0 -385 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -557 0.500000655651 0.5 -608 0.889534235001 0.501856803894 -385 1.0 0.5 -133 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -556 1.00000286102 0.499999493361 -132 1.0 1.0 -386 1.0 1.0 -609 0.615567445755 0.501971364021 -SURF 0x10 -mat 1 -refs 4 -104 1.0 0.0 -556 1.00000286102 0.499999493361 -609 0.615567445755 0.501971364021 -345 0.499999403954 -4.28743618386e-09 -SURF 0x10 -mat 1 -refs 4 -609 0.615567445755 0.501971364021 -386 1.0 1.0 -130 1.0 1.0 -558 0.499999552965 0.499999552965 -SURF 0x10 -mat 1 -refs 4 -345 0.499999403954 -4.28743618386e-09 -609 0.615567445755 0.501971364021 -558 0.499999552965 0.499999552965 -107 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -344 0.500002264977 5.41419183264e-07 -105 1.0 0.0 -557 1.0 -8.27036785722e-07 -610 0.873875677586 0.502711474895 -SURF 0x10 -mat 1 -refs 4 -103 0.0 0.0 -344 0.500002264977 5.41419183264e-07 -610 0.873875677586 0.502711474895 -555 0.500002264977 0.500000536442 -SURF 0x10 -mat 1 -refs 4 -610 0.873875677586 0.502711474895 -557 1.0 -8.27036785722e-07 -133 1.0 0.0 -387 1.0 0.499999165535 -SURF 0x10 -mat 1 -refs 4 -555 0.500002264977 0.500000536442 -610 0.873875677586 0.502711474895 -387 1.0 0.499999165535 -134 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -554 0.999998152256 0.500000536442 -135 1.0 1.0 -388 1.0 1.0 -611 0.631910443306 0.503210842609 -SURF 0x10 -mat 1 -refs 4 -102 1.0 0.0 -554 0.999998152256 0.500000536442 -611 0.631910443306 0.503210842609 -343 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -611 0.631910443306 0.503210842609 -388 1.0 1.0 -132 1.0 1.0 -556 0.499999552965 0.499999552965 -SURF 0x10 -mat 1 -refs 4 -343 0.5 0.0 -611 0.631910443306 0.503210842609 -556 0.499999552965 0.499999552965 -104 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -342 0.500000298023 7.09478809036e-10 -103 1.0 0.0 -555 0.999999940395 -2.20369133785e-06 -612 0.88955450058 0.50467056036 -SURF 0x10 -mat 1 -refs 4 -101 0.0 0.0 -342 0.500000298023 7.09478809036e-10 -612 0.88955450058 0.50467056036 -553 0.499998211861 0.499999463558 -SURF 0x10 -mat 1 -refs 4 -612 0.88955450058 0.50467056036 -555 0.999999940395 -2.20369133785e-06 -134 1.0 0.0 -389 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -553 0.499998211861 0.499999463558 -612 0.88955450058 0.50467056036 -389 1.0 0.5 -136 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -552 0.999999165535 0.500000536442 -137 1.0 1.0 -390 1.0 1.0 -613 0.61085832119 0.505385816097 -SURF 0x10 -mat 1 -refs 4 -100 1.0 0.0 -552 0.999999165535 0.500000536442 -613 0.61085832119 0.505385816097 -341 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -613 0.61085832119 0.505385816097 -390 1.0 1.0 -135 1.0 1.0 -554 0.500000476837 0.500000476837 -SURF 0x10 -mat 1 -refs 4 -341 0.5 0.0 -613 0.61085832119 0.505385816097 -554 0.500000476837 0.500000476837 -102 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -340 0.500001132488 5.60828766538e-07 -101 1.0 0.0 -553 0.999999940395 1.63526567576e-06 -614 0.910056352615 0.506308972836 -SURF 0x10 -mat 1 -refs 4 -99 0.0 0.0 -340 0.500001132488 5.60828766538e-07 -614 0.910056352615 0.506308972836 -551 0.499999761581 0.5 -SURF 0x10 -mat 1 -refs 4 -614 0.910056352615 0.506308972836 -553 0.999999940395 1.63526567576e-06 -136 1.0 0.0 -391 1.0 0.50000077486 -SURF 0x10 -mat 1 -refs 4 -551 0.499999761581 0.5 -614 0.910056352615 0.506308972836 -391 1.0 0.50000077486 -138 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -550 0.999999642372 0.500000536442 -139 1.0 1.0 -392 1.0 1.0 -615 0.588319063187 0.507389962673 -SURF 0x10 -mat 1 -refs 4 -98 1.0 0.0 -550 0.999999642372 0.500000536442 -615 0.588319063187 0.507389962673 -339 0.500000238419 1.5537179876e-10 -SURF 0x10 -mat 1 -refs 4 -615 0.588319063187 0.507389962673 -392 1.0 1.0 -137 1.0 1.0 -552 0.500000476837 0.500000476837 -SURF 0x10 -mat 1 -refs 4 -339 0.500000238419 1.5537179876e-10 -615 0.588319063187 0.507389962673 -552 0.500000476837 0.500000476837 -100 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -539 1.0 0.5 -146 1.0 1.0 -395 0.999999880791 0.999999880791 -616 0.605205655098 0.506726026535 -SURF 0x10 -mat 1 -refs 4 -143 1.0 0.0 -539 1.0 0.5 -616 0.605205655098 0.506726026535 -377 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -616 0.605205655098 0.506726026535 -395 0.999999880791 0.999999880791 -148 1.0 1.0 -549 0.500000059605 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -377 0.5 0.0 -616 0.605205655098 0.506726026535 -549 0.500000059605 0.500000059605 -141 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -547 0.5 0.5 -139 0.0 0.0 -394 0.499999403954 -3.89745657969e-08 -617 0.608679711819 0.506393313408 -SURF 0x10 -mat 1 -refs 4 -150 1.0 1.0 -547 0.5 0.5 -617 0.608679711819 0.506393313408 -397 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -617 0.608679711819 0.506393313408 -394 0.499999403954 -3.89745657969e-08 -141 1.0 0.0 -549 1.00000059605 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -397 1.0 1.0 -617 0.608679711819 0.506393313408 -549 1.00000059605 0.500000059605 -148 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -398 0.999999940395 0.500001072884 -149 1.0 1.0 -548 0.500000536442 0.499999970198 -618 0.885869264603 0.504000306129 -SURF 0x10 -mat 1 -refs 4 -151 1.0 0.0 -398 0.999999940395 0.500001072884 -618 0.885869264603 0.504000306129 -546 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -618 0.885869264603 0.504000306129 -548 0.500000536442 0.499999970198 -140 0.0 0.0 -393 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -546 1.0 0.0 -618 0.885869264603 0.504000306129 -393 0.5 0.0 -138 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -376 0.5 0.0 -140 1.0 0.0 -548 1.0 -9.10895153083e-07 -619 0.900903522968 0.505599379539 -SURF 0x10 -mat 1 -refs 4 -142 0.0 0.0 -376 0.5 0.0 -619 0.900903522968 0.505599379539 -538 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -619 0.900903522968 0.505599379539 -548 1.0 -9.10895153083e-07 -149 1.0 0.0 -396 1.0 0.50000089407 -SURF 0x10 -mat 1 -refs 4 -538 0.5 0.5 -619 0.900903522968 0.505599379539 -396 1.0 0.50000089407 -147 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -545 0.499999910593 0.499999910593 -137 0.0 0.0 -392 0.499999344349 -4.05524964719e-08 -620 0.624242961407 0.505493938923 -SURF 0x10 -mat 1 -refs 4 -152 1.0 1.0 -545 0.499999910593 0.499999910593 -620 0.624242961407 0.505493938923 -399 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -620 0.624242961407 0.505493938923 -392 0.499999344349 -4.05524964719e-08 -139 1.0 0.0 -547 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -399 1.0 1.0 -620 0.624242961407 0.505493938923 -547 1.0 0.5 -150 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -400 0.999999940395 0.500001430511 -151 1.0 1.0 -546 0.5 0.5 -621 0.869727492332 0.502808570862 -SURF 0x10 -mat 1 -refs 4 -153 1.0 0.0 -400 0.999999940395 0.500001430511 -621 0.869727492332 0.502808570862 -544 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -621 0.869727492332 0.502808570862 -546 0.5 0.5 -138 0.0 0.0 -391 0.499999344349 3.53102755923e-08 -SURF 0x10 -mat 1 -refs 4 -544 1.0 0.0 -621 0.869727492332 0.502808570862 -391 0.499999344349 3.53102755923e-08 -136 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -543 0.499999970198 0.499999970198 -135 0.0 0.0 -390 0.499999552965 -2.17821440884e-08 -622 0.63567006588 0.503983199596 -SURF 0x10 -mat 1 -refs 4 -155 1.0 1.0 -543 0.499999970198 0.499999970198 -622 0.63567006588 0.503983199596 -401 1.00000011921 1.00000011921 -SURF 0x10 -mat 1 -refs 4 -622 0.63567006588 0.503983199596 -390 0.499999552965 -2.17821440884e-08 -137 1.0 0.0 -545 0.999999165535 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -401 1.00000011921 1.00000011921 -622 0.63567006588 0.503983199596 -545 0.999999165535 0.499999970198 -152 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -403 1.0 0.5 -153 1.0 1.0 -544 0.5 0.5 -623 0.857362151146 0.501287460327 -SURF 0x10 -mat 1 -refs 4 -154 1.0 0.0 -403 1.0 0.5 -623 0.857362151146 0.501287460327 -542 1.0 2.21158416025e-06 -SURF 0x10 -mat 1 -refs 4 -623 0.857362151146 0.501287460327 -544 0.5 0.5 -136 0.0 0.0 -389 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -542 1.0 2.21158416025e-06 -623 0.857362151146 0.501287460327 -389 0.5 0.0 -134 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -541 0.499999940395 0.499999940395 -132 0.0 0.0 -388 0.500000655651 2.36843273882e-08 -624 0.623112201691 0.502673089504 -SURF 0x10 -mat 1 -refs 4 -157 1.0 1.0 -541 0.499999940395 0.499999940395 -624 0.623112201691 0.502673089504 -404 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -624 0.623112201691 0.502673089504 -388 0.500000655651 2.36843273882e-08 -135 1.0 0.0 -543 0.999999284744 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -404 1.0 1.0 -624 0.623112201691 0.502673089504 -543 0.999999284744 0.499999970198 -155 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -540 0.5 0.5 -130 0.0 0.0 -386 0.5 0.0 -625 0.649334311485 0.501797020435 -SURF 0x10 -mat 1 -refs 4 -159 1.0 1.0 -540 0.5 0.5 -625 0.649334311485 0.501797020435 -407 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -625 0.649334311485 0.501797020435 -386 0.5 0.0 -132 1.0 0.0 -541 0.999998092651 0.499999940395 -SURF 0x10 -mat 1 -refs 4 -407 1.0 1.0 -625 0.649334311485 0.501797020435 -541 0.999998092651 0.499999940395 -157 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -536 1.0 0.5 -144 1.0 1.0 -412 1.0 1.0 -626 0.611721694469 0.507217645645 -SURF 0x10 -mat 1 -refs 4 -127 1.0 0.0 -536 1.0 0.5 -626 0.611721694469 0.507217645645 -374 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -626 0.611721694469 0.507217645645 -412 1.0 1.0 -146 1.0 1.0 -539 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -374 0.5 0.0 -626 0.611721694469 0.507217645645 -539 0.5 0.5 -143 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -375 0.5 0.0 -142 1.0 0.0 -538 1.0 0.0 -627 0.895380914211 0.507551431656 -SURF 0x10 -mat 1 -refs 4 -126 0.0 0.0 -375 0.5 0.0 -627 0.895380914211 0.507551431656 -537 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -627 0.895380914211 0.507551431656 -538 1.0 0.0 -147 1.0 0.0 -413 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -537 0.5 0.5 -627 0.895380914211 0.507551431656 -413 1.0 0.5 -145 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -373 0.5 0.0 -126 1.0 0.0 -537 1.0 0.0 -628 0.966136813164 0.508349597454 -SURF 0x10 -mat 1 -refs 4 -124 0.0 0.0 -373 0.5 0.0 -628 0.966136813164 0.508349597454 -535 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -628 0.966136813164 0.508349597454 -537 1.0 0.0 -145 1.0 0.0 -414 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -535 0.5 0.5 -628 0.966136813164 0.508349597454 -414 1.0 0.5 -161 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -534 1.0 0.5 -160 1.0 1.0 -415 1.0 1.0 -629 0.543400108814 0.506303071976 -SURF 0x10 -mat 1 -refs 4 -125 1.0 0.0 -534 1.0 0.5 -629 0.543400108814 0.506303071976 -372 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -629 0.543400108814 0.506303071976 -415 1.0 1.0 -144 1.0 1.0 -536 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -372 0.5 0.0 -629 0.543400108814 0.506303071976 -536 0.5 0.5 -127 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -371 0.5 0.0 -124 1.0 0.0 -535 1.0 0.0 -630 0.967370033264 0.507047772408 -SURF 0x10 -mat 1 -refs 4 -123 0.0 0.0 -371 0.5 0.0 -630 0.967370033264 0.507047772408 -533 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -630 0.967370033264 0.507047772408 -535 1.0 0.0 -161 1.0 0.0 -416 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -533 0.5 0.5 -630 0.967370033264 0.507047772408 -416 1.0 0.5 -163 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -532 1.0 0.5 -162 1.0 1.0 -417 1.0 1.0 -631 0.540586292744 0.505342006683 -SURF 0x10 -mat 1 -refs 4 -122 1.0 0.0 -532 1.0 0.5 -631 0.540586292744 0.505342006683 -370 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -631 0.540586292744 0.505342006683 -417 1.0 1.0 -160 1.0 1.0 -534 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -370 0.5 0.0 -631 0.540586292744 0.505342006683 -534 0.5 0.5 -125 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -438 1.0 0.5 -172 1.0 1.0 -531 0.5 0.5 -632 0.900413751602 0.507163345814 -SURF 0x10 -mat 1 -refs 4 -174 1.0 0.0 -438 1.0 0.5 -632 0.900413751602 0.507163345814 -529 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -632 0.900413751602 0.507163345814 -531 0.5 0.5 -164 0.0 0.0 -418 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -529 1.0 0.0 -632 0.900413751602 0.507163345814 -418 0.5 0.0 -163 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -528 0.5 0.5 -160 0.0 0.0 -417 0.5 0.0 -633 0.608557999134 0.507319867611 -SURF 0x10 -mat 1 -refs 4 -191 1.0 1.0 -528 0.5 0.5 -633 0.608557999134 0.507319867611 -439 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -633 0.608557999134 0.507319867611 -417 0.5 0.0 -162 1.0 0.0 -530 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -439 1.0 1.0 -633 0.608557999134 0.507319867611 -530 1.0 0.5 -175 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -440 1.0 0.5 -174 1.0 1.0 -529 0.5 0.5 -634 0.901417851448 0.508581876755 -SURF 0x10 -mat 1 -refs 4 -190 1.0 0.0 -440 1.0 0.5 -634 0.901417851448 0.508581876755 -527 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -634 0.901417851448 0.508581876755 -529 0.5 0.5 -163 0.0 0.0 -416 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -527 1.0 0.0 -634 0.901417851448 0.508581876755 -416 0.5 0.0 -161 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -525 0.5 0.5 -144 0.0 0.0 -415 0.5 0.0 -635 0.644069433212 0.508120119572 -SURF 0x10 -mat 1 -refs 4 -189 1.0 1.0 -525 0.5 0.5 -635 0.644069433212 0.508120119572 -442 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -635 0.644069433212 0.508120119572 -415 0.5 0.0 -160 1.0 0.0 -528 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -442 1.0 1.0 -635 0.644069433212 0.508120119572 -528 1.0 0.5 -191 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -441 1.0 0.5 -190 1.0 1.0 -527 0.5 0.5 -636 0.863419771194 0.507932901382 -SURF 0x10 -mat 1 -refs 4 -188 1.0 0.0 -441 1.0 0.5 -636 0.863419771194 0.507932901382 -526 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -636 0.863419771194 0.507932901382 -527 0.5 0.5 -161 0.0 0.0 -414 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -526 1.0 0.0 -636 0.863419771194 0.507932901382 -414 0.5 0.0 -145 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -458 1.0 0.5 -188 1.0 1.0 -526 0.5 0.5 -637 0.861253976822 0.505880475044 -SURF 0x10 -mat 1 -refs 4 -186 1.0 0.0 -458 1.0 0.5 -637 0.861253976822 0.505880475044 -516 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -637 0.861253976822 0.505880475044 -526 0.5 0.5 -145 0.0 0.0 -413 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -516 1.0 0.0 -637 0.861253976822 0.505880475044 -413 0.5 0.0 -147 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -515 0.5 0.5 -146 0.0 0.0 -412 0.5 0.0 -638 0.642688751221 0.507296264172 -SURF 0x10 -mat 1 -refs 4 -187 1.0 1.0 -515 0.5 0.5 -638 0.642688751221 0.507296264172 -459 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -638 0.642688751221 0.507296264172 -412 0.5 0.0 -144 1.0 0.0 -525 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -459 1.0 1.0 -638 0.642688751221 0.507296264172 -525 1.0 0.5 -189 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -523 1.0 0.5 -178 1.0 1.0 -448 1.0 1.0 -639 0.66978263855 0.501440525055 -SURF 0x10 -mat 1 -refs 4 -155 1.0 0.0 -523 1.0 0.5 -639 0.66978263855 0.501440525055 -404 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -639 0.66978263855 0.501440525055 -448 1.0 1.0 -176 1.0 1.0 -524 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -404 0.5 0.0 -639 0.66978263855 0.501440525055 -524 0.5 0.5 -157 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -521 0.999998748302 0.499999880791 -180 1.0 1.0 -451 1.0 1.0 -640 0.656184077263 0.502198576927 -SURF 0x10 -mat 1 -refs 4 -152 1.0 0.0 -521 0.999998748302 0.499999880791 -640 0.656184077263 0.502198576927 -401 0.500001251698 1.29620474354e-07 -SURF 0x10 -mat 1 -refs 4 -640 0.656184077263 0.502198576927 -451 1.0 1.0 -178 1.0 1.0 -523 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -401 0.500001251698 1.29620474354e-07 -640 0.656184077263 0.502198576927 -523 0.5 0.5 -155 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -400 0.49999910593 1.18080357936e-07 -153 1.0 0.0 -522 1.0 2.49720824286e-06 -641 0.845227599144 0.503381431103 -SURF 0x10 -mat 1 -refs 4 -151 0.0 0.0 -400 0.49999910593 1.18080357936e-07 -641 0.845227599144 0.503381431103 -520 0.499999582767 0.499999940395 -SURF 0x10 -mat 1 -refs 4 -641 0.845227599144 0.503381431103 -522 1.0 2.49720824286e-06 -181 1.0 0.0 -452 1.0 0.500001013279 -SURF 0x10 -mat 1 -refs 4 -520 0.499999582767 0.499999940395 -641 0.845227599144 0.503381431103 -452 1.0 0.500001013279 -182 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -519 0.999999046326 0.499999880791 -183 1.0 1.0 -453 1.0 1.0 -642 0.659408152103 0.503604531288 -SURF 0x10 -mat 1 -refs 4 -150 1.0 0.0 -519 0.999999046326 0.499999880791 -642 0.659408152103 0.503604531288 -399 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -642 0.659408152103 0.503604531288 -453 1.0 1.0 -180 1.0 1.0 -521 0.499999850988 0.499999850988 -SURF 0x10 -mat 1 -refs 4 -399 0.5 0.0 -642 0.659408152103 0.503604531288 -521 0.499999850988 0.499999850988 -152 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -398 0.499999135733 8.29601773944e-08 -151 1.0 0.0 -520 1.0 7.0182716172e-07 -643 0.847398281097 0.504193365574 -SURF 0x10 -mat 1 -refs 4 -149 0.0 0.0 -398 0.499999135733 8.29601773944e-08 -643 0.847398281097 0.504193365574 -518 0.500000596046 0.499999850988 -SURF 0x10 -mat 1 -refs 4 -643 0.847398281097 0.504193365574 -520 1.0 7.0182716172e-07 -182 1.0 0.0 -454 1.0 0.500000715256 -SURF 0x10 -mat 1 -refs 4 -518 0.500000596046 0.499999850988 -643 0.847398281097 0.504193365574 -454 1.0 0.500000715256 -184 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -517 1.00000083447 0.500000119209 -185 1.0 1.0 -455 1.0 1.0 -644 0.651330769062 0.505278944969 -SURF 0x10 -mat 1 -refs 4 -148 1.0 0.0 -517 1.00000083447 0.500000119209 -644 0.651330769062 0.505278944969 -397 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -644 0.651330769062 0.505278944969 -455 1.0 1.0 -183 1.0 1.0 -519 0.499999850988 0.499999850988 -SURF 0x10 -mat 1 -refs 4 -397 0.5 0.0 -644 0.651330769062 0.505278944969 -519 0.499999850988 0.499999850988 -150 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -396 0.499999374151 1.19368976925e-07 -149 1.0 0.0 -518 1.0 -1.670489155e-06 -645 0.852543354034 0.504383802414 -SURF 0x10 -mat 1 -refs 4 -147 0.0 0.0 -396 0.499999374151 1.19368976925e-07 -645 0.852543354034 0.504383802414 -516 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -645 0.852543354034 0.504383802414 -518 1.0 -1.670489155e-06 -184 1.0 0.0 -456 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -516 0.5 0.5 -645 0.852543354034 0.504383802414 -456 1.0 0.5 -186 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -515 1.0 0.5 -187 1.0 1.0 -457 1.0 1.0 -646 0.642946779728 0.506505966187 -SURF 0x10 -mat 1 -refs 4 -146 1.0 0.0 -515 1.0 0.5 -646 0.642946779728 0.506505966187 -395 0.49999922514 -1.12900600868e-07 -SURF 0x10 -mat 1 -refs 4 -646 0.642946779728 0.506505966187 -457 1.0 1.0 -185 1.0 1.0 -517 0.500000178814 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -395 0.49999922514 -1.12900600868e-07 -646 0.642946779728 0.506505966187 -517 0.500000178814 0.500000178814 -148 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -442 0.5 0.0 -191 1.0 0.0 -439 1.0 0.0 -647 1.0 0.255623579025 -SURF 0x10 -mat 1 -refs 4 -189 0.0 0.0 -442 0.5 0.0 -647 1.0 0.255623579025 -479 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -647 1.0 0.255623579025 -439 1.0 0.0 -175 1.0 0.0 -465 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -479 0.5 0.5 -647 1.0 0.255623579025 -465 1.0 0.5 -192 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -462 1.0 0.5 -192 1.0 1.0 -460 0.499997794628 0.5 -648 1.0 0.270958006382 -SURF 0x10 -mat 1 -refs 4 -171 1.0 0.0 -462 1.0 0.5 -648 1.0 0.270958006382 -433 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -648 1.0 0.270958006382 -460 0.499997794628 0.5 -168 0.0 0.0 -431 0.499997794628 7.66279928399e-09 -SURF 0x10 -mat 1 -refs 4 -433 1.0 0.0 -648 1.0 0.270958006382 -431 0.499997794628 7.66279928399e-09 -169 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -476 1.0 0.5 -192 1.0 1.0 -466 0.5 0.5 -649 0.985569357872 0.251868635416 -SURF 0x10 -mat 1 -refs 4 -188 1.0 0.0 -476 1.0 0.5 -649 0.985569357872 0.251868635416 -441 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -649 0.985569357872 0.251868635416 -466 0.5 0.5 -174 0.0 0.0 -440 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -441 1.0 0.0 -649 0.985569357872 0.251868635416 -440 0.5 0.0 -190 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -467 1.0 0.5 -192 1.0 1.0 -468 0.5 0.5 -650 0.938953518867 0.256189018488 -SURF 0x10 -mat 1 -refs 4 -176 1.0 0.0 -467 1.0 0.5 -650 0.938953518867 0.256189018488 -447 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -650 0.938953518867 0.256189018488 -468 0.5 0.5 -179 0.0 0.0 -444 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -447 1.0 0.0 -650 0.938953518867 0.256189018488 -444 0.5 0.0 -177 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -568 1.0 0.5 -112 1.0 1.0 -355 0.999999523163 0.999999523163 -651 0.498745262623 0.498745262623 -SURF 0x10 -mat 1 -refs 4 -90 1.0 0.0 -568 1.0 0.5 -651 0.498745262623 0.498745262623 -329 0.499999582767 2.1413743001e-10 -SURF 0x10 -mat 1 -refs 4 -651 0.498745262623 0.498745262623 -355 0.999999523163 0.999999523163 -96 1.0 1.0 -570 0.499999523163 0.499999523163 -SURF 0x10 -mat 1 -refs 4 -329 0.499999582767 2.1413743001e-10 -651 0.498745262623 0.498745262623 -570 0.499999523163 0.499999523163 -88 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -326 0.499999701977 -4.65776508918e-07 -89 1.0 0.0 -571 1.0 -3.75045800638e-07 -652 1.0 0.476342439651 -SURF 0x10 -mat 1 -refs 4 -91 0.0 0.0 -326 0.499999701977 -4.65776508918e-07 -652 1.0 0.476342439651 -569 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -652 1.0 0.476342439651 -571 1.0 -3.75045800638e-07 -97 1.0 0.0 -354 1.0 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -569 0.5 0.5 -652 1.0 0.476342439651 -354 1.0 0.500000178814 -113 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -322 0.499999850988 -3.28620355754e-12 -73 1.0 0.0 -572 1.0 0.0 -653 0.921689152718 0.500883340836 -SURF 0x10 -mat 1 -refs 4 -89 0.0 0.0 -322 0.499999850988 -3.28620355754e-12 -653 0.921689152718 0.500883340836 -571 0.500000298023 0.5 -SURF 0x10 -mat 1 -refs 4 -653 0.921689152718 0.500883340836 -572 1.0 0.0 -99 1.0 0.0 -353 1.0 0.500000238419 -SURF 0x10 -mat 1 -refs 4 -571 0.500000298023 0.5 -653 0.921689152718 0.500883340836 -353 1.0 0.500000238419 -97 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -570 0.999999880791 0.499999523163 -96 1.0 1.0 -352 1.00000047684 1.00000047684 -654 0.577424526215 0.499616533518 -SURF 0x10 -mat 1 -refs 4 -88 1.0 0.0 -570 0.999999880791 0.499999523163 -654 0.577424526215 0.499616533518 -325 0.499999701977 2.55250348635e-10 -SURF 0x10 -mat 1 -refs 4 -654 0.577424526215 0.499616533518 -352 1.00000047684 1.00000047684 -98 1.0 1.0 -573 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -325 0.499999701977 2.55250348635e-10 -654 0.577424526215 0.499616533518 -573 0.5 0.5 -72 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -348 1.0 0.499999076128 -106 1.0 1.0 -576 0.500000238419 0.5 -655 0.885786175728 0.499103397131 -SURF 0x10 -mat 1 -refs 4 -108 1.0 0.0 -348 1.0 0.499999076128 -655 0.885786175728 0.499103397131 -574 1.0 -2.99620137412e-06 -SURF 0x10 -mat 1 -refs 4 -655 0.885786175728 0.499103397131 -576 0.500000238419 0.5 -81 0.0 0.0 -308 0.500002145767 4.65455684662e-07 -SURF 0x10 -mat 1 -refs 4 -574 1.0 -2.99620137412e-06 -655 0.885786175728 0.499103397131 -308 0.500002145767 4.65455684662e-07 -82 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -575 0.5 0.5 -83 0.0 0.0 -307 0.49999833107 4.74329709732e-07 -656 0.609612762928 0.501349508762 -SURF 0x10 -mat 1 -refs 4 -109 1.0 1.0 -575 0.5 0.5 -656 0.609612762928 0.501349508762 -347 0.999999523163 0.999999523163 -SURF 0x10 -mat 1 -refs 4 -656 0.609612762928 0.501349508762 -307 0.49999833107 4.74329709732e-07 -80 1.0 0.0 -577 0.999999761581 0.5 -SURF 0x10 -mat 1 -refs 4 -347 0.999999523163 0.999999523163 -656 0.609612762928 0.501349508762 -577 0.999999761581 0.5 -107 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -346 1.0 0.500002145767 -105 1.0 1.0 -578 0.499998867512 0.499999523163 -657 0.872009158134 0.499285936356 -SURF 0x10 -mat 1 -refs 4 -106 1.0 0.0 -346 1.0 0.500002145767 -657 0.872009158134 0.499285936356 -576 1.0 -3.23583009276e-07 -SURF 0x10 -mat 1 -refs 4 -657 0.872009158134 0.499285936356 -578 0.499998867512 0.499999523163 -79 0.0 0.0 -306 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -576 1.0 -3.23583009276e-07 -657 0.872009158134 0.499285936356 -306 0.5 0.0 -81 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -577 0.5 0.5 -80 0.0 0.0 -305 0.50000077486 -4.77698165469e-07 -658 0.627923727036 0.501589298248 -SURF 0x10 -mat 1 -refs 4 -107 1.0 1.0 -577 0.5 0.5 -658 0.627923727036 0.501589298248 -345 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -658 0.627923727036 0.501589298248 -305 0.50000077486 -4.77698165469e-07 -78 1.0 0.0 -579 1.00000095367 0.499999523163 -SURF 0x10 -mat 1 -refs 4 -345 1.0 1.0 -658 0.627923727036 0.501589298248 -579 1.00000095367 0.499999523163 -104 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -344 1.0 0.499998956919 -103 1.0 1.0 -580 0.499999374151 0.499999523163 -659 0.88885819912 0.499501466751 -SURF 0x10 -mat 1 -refs 4 -105 1.0 0.0 -344 1.0 0.499998956919 -659 0.88885819912 0.499501466751 -578 1.0 8.37588004288e-07 -SURF 0x10 -mat 1 -refs 4 -659 0.88885819912 0.499501466751 -580 0.499999374151 0.499999523163 -77 0.0 0.0 -304 0.500000715256 4.62915068056e-07 -SURF 0x10 -mat 1 -refs 4 -578 1.0 8.37588004288e-07 -659 0.88885819912 0.499501466751 -304 0.500000715256 4.62915068056e-07 -79 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -579 0.499999552965 0.499999552965 -78 0.0 0.0 -303 0.500000476837 -4.8090709015e-07 -660 0.605253875256 0.501562476158 -SURF 0x10 -mat 1 -refs 4 -104 1.0 1.0 -579 0.499999552965 0.499999552965 -660 0.605253875256 0.501562476158 -343 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -660 0.605253875256 0.501562476158 -303 0.500000476837 -4.8090709015e-07 -76 1.0 0.0 -581 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -343 1.0 1.0 -660 0.605253875256 0.501562476158 -581 1.0 0.5 -102 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -320 0.499999344349 -4.62269383661e-07 -75 1.0 0.0 -582 1.0 2.34866220694e-07 -661 0.931028723717 0.500178039074 -SURF 0x10 -mat 1 -refs 4 -73 0.0 0.0 -320 0.499999344349 -4.62269383661e-07 -661 0.931028723717 0.500178039074 -572 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -661 0.931028723717 0.500178039074 -582 1.0 2.34866220694e-07 -101 1.0 0.0 -340 1.0 0.499999821186 -SURF 0x10 -mat 1 -refs 4 -572 0.5 0.5 -661 0.931028723717 0.500178039074 -340 1.0 0.499999821186 -99 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -342 1.0 0.499999701977 -101 1.0 1.0 -582 0.499999821186 0.5 -662 0.911859750748 0.499510288239 -SURF 0x10 -mat 1 -refs 4 -103 1.0 0.0 -342 1.0 0.499999701977 -662 0.911859750748 0.499510288239 -580 1.0 1.88861790207e-07 -SURF 0x10 -mat 1 -refs 4 -662 0.911859750748 0.499510288239 -582 0.499999821186 0.5 -75 0.0 0.0 -301 0.500000417233 4.61932501139e-07 -SURF 0x10 -mat 1 -refs 4 -580 1.0 1.88861790207e-07 -662 0.911859750748 0.499510288239 -301 0.500000417233 4.61932501139e-07 -77 1.0 0.0 -SURF 0x10 -mat 1 -refs 4 -581 0.5 0.5 -76 0.0 0.0 -298 0.5 0.0 -663 0.579815506935 0.500937998295 -SURF 0x10 -mat 1 -refs 4 -102 1.0 1.0 -581 0.5 0.5 -663 0.579815506935 0.500937998295 -341 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -663 0.579815506935 0.500937998295 -298 0.5 0.0 -74 1.0 0.0 -583 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -341 1.0 1.0 -663 0.579815506935 0.500937998295 -583 1.0 0.5 -100 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -573 1.00000023842 0.5 -98 1.0 1.0 -339 1.0 1.0 -664 0.572733938694 0.500220894814 -SURF 0x10 -mat 1 -refs 4 -72 1.0 0.0 -573 1.00000023842 0.5 -664 0.572733938694 0.500220894814 -319 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -664 0.572733938694 0.500220894814 -339 1.0 1.0 -100 1.0 1.0 -583 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -319 0.5 0.0 -664 0.572733938694 0.500220894814 -583 0.5 0.5 -74 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -264 0.5 0.0 -38 1.0 0.0 -593 1.0 0.0 -665 0.90832567215 0.499999731779 -SURF 0x10 -mat 1 -refs 4 -40 0.0 0.0 -264 0.5 0.0 -665 0.90832567215 0.499999731779 -592 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -665 0.90832567215 0.499999731779 -593 1.0 0.0 -62 1.0 0.0 -291 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -592 0.5 0.5 -665 0.90832567215 0.499999731779 -291 1.0 0.5 -64 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -228 0.5 0.0 -25 1.0 0.0 -512 1.0 0.0 -666 0.986809372902 0.486777275801 -SURF 0x10 -mat 1 -refs 4 -20 0.0 0.0 -228 0.5 0.0 -666 0.986809372902 0.486777275801 -224 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -666 0.986809372902 0.486777275801 -512 1.0 0.0 -46 1.0 0.0 -514 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -224 0.5 0.5 -666 0.986809372902 0.486777275801 -514 1.0 0.5 -22 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -514 0.499999910593 -8.96153835583e-08 -46 1.0 0.0 -270 1.0 0.0 -667 0.832420349121 0.332449585199 -SURF 0x10 -mat 1 -refs 4 -22 0.0 0.0 -514 0.499999910593 -8.96153835583e-08 -667 0.832420349121 0.332449585199 -225 0.500000059605 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -667 0.832420349121 0.332449585199 -270 1.0 0.0 -47 1.0 0.0 -513 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -225 0.500000059605 0.500000059605 -667 0.832420349121 0.332449585199 -513 1.0 0.5 -23 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -226 0.5 0.0 -23 1.0 0.0 -513 1.0 0.0 -668 0.982141256332 0.500101387501 -SURF 0x10 -mat 1 -refs 4 -21 0.0 0.0 -226 0.5 0.0 -668 0.982141256332 0.500101387501 -227 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -668 0.982141256332 0.500101387501 -513 1.0 0.0 -47 1.0 0.0 -511 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -227 0.5 0.5 -668 0.982141256332 0.500101387501 -511 1.0 0.5 -24 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -445 0.999998807907 0.500000178814 -179 1.0 1.0 -449 1.0 1.0 -669 0.627666592598 0.499044090509 -SURF 0x10 -mat 1 -refs 4 -156 1.0 0.0 -445 0.999998807907 0.500000178814 -669 0.627666592598 0.499044090509 -406 0.499999344349 -3.44248825002e-08 -SURF 0x10 -mat 1 -refs 4 -669 0.627666592598 0.499044090509 -449 1.0 1.0 -181 1.0 1.0 -450 0.499999821186 0.499999821186 -SURF 0x10 -mat 1 -refs 4 -406 0.499999344349 -3.44248825002e-08 -669 0.627666592598 0.499044090509 -450 0.499999821186 0.499999821186 -154 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -409 0.5 0.0 -159 1.0 0.0 -446 1.0 1.80391975846e-06 -670 0.854527115822 0.499937921762 -SURF 0x10 -mat 1 -refs 4 -158 0.0 0.0 -409 0.5 0.0 -670 0.854527115822 0.499937921762 -443 0.499999344349 0.500000238419 -SURF 0x10 -mat 1 -refs 4 -670 0.854527115822 0.499937921762 -446 1.0 1.80391975846e-06 -176 1.0 0.0 -447 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -443 0.499999344349 0.500000238419 -670 0.854527115822 0.499937921762 -447 1.0 0.5 -177 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -443 0.999999403954 0.500000178814 -177 1.0 1.0 -444 1.0 1.0 -671 0.636126697063 0.499726444483 -SURF 0x10 -mat 1 -refs 4 -158 1.0 0.0 -443 0.999999403954 0.500000178814 -671 0.636126697063 0.499726444483 -411 0.50000077486 1.92301694568e-08 -SURF 0x10 -mat 1 -refs 4 -671 0.636126697063 0.499726444483 -444 1.0 1.0 -179 1.0 1.0 -445 0.500000178814 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -411 0.50000077486 1.92301694568e-08 -671 0.636126697063 0.499726444483 -445 0.500000178814 0.500000178814 -156 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -421 0.5 0.0 -165 1.0 0.0 -429 1.0 0.0 -672 0.859262466431 0.495646625757 -SURF 0x10 -mat 1 -refs 4 -162 0.0 0.0 -421 0.5 0.0 -672 0.859262466431 0.495646625757 -435 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -672 0.859262466431 0.495646625757 -429 1.0 0.0 -170 1.0 0.0 -434 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -435 0.5 0.5 -672 0.859262466431 0.495646625757 -434 1.0 0.5 -173 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -432 1.0 0.5 -171 1.0 1.0 -433 1.0 1.0 -673 0.642974615097 0.495283305645 -SURF 0x10 -mat 1 -refs 4 -164 1.0 0.0 -432 1.0 0.5 -673 0.642974615097 0.495283305645 -422 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -673 0.642974615097 0.495283305645 -433 1.0 1.0 -169 1.0 1.0 -430 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -422 0.5 0.0 -673 0.642974615097 0.495283305645 -430 0.5 0.5 -166 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -430 1.0 0.5 -169 1.0 1.0 -431 1.0 1.0 -674 0.619583964348 0.499075353146 -SURF 0x10 -mat 1 -refs 4 -166 1.0 0.0 -430 1.0 0.5 -674 0.619583964348 0.499075353146 -424 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -674 0.619583964348 0.499075353146 -431 1.0 1.0 -168 1.0 1.0 -427 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -424 0.5 0.0 -674 0.619583964348 0.499075353146 -427 0.5 0.5 -167 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -427 1.0 0.5 -168 1.0 1.0 -428 1.0 1.0 -675 0.647793650627 0.502707779408 -SURF 0x10 -mat 1 -refs 4 -167 1.0 0.0 -427 1.0 0.5 -675 0.647793650627 0.502707779408 -426 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -675 0.647793650627 0.502707779408 -428 1.0 1.0 -170 1.0 1.0 -429 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -426 0.5 0.0 -675 0.647793650627 0.502707779408 -429 0.5 0.5 -165 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -425 1.0 0.5 -167 1.0 1.0 -426 1.0 1.0 -676 0.61461776495 0.501586794853 -SURF 0x10 -mat 1 -refs 4 -120 1.0 0.0 -425 1.0 0.5 -676 0.61461776495 0.501586794853 -364 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -676 0.61461776495 0.501586794853 -426 1.0 1.0 -165 1.0 1.0 -420 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -364 0.5 0.0 -676 0.61461776495 0.501586794853 -420 0.5 0.5 -122 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -423 1.0 0.5 -166 1.0 1.0 -424 1.0 1.0 -677 0.578553974628 0.498584330082 -SURF 0x10 -mat 1 -refs 4 -121 1.0 0.0 -423 1.0 0.5 -677 0.578553974628 0.498584330082 -367 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -677 0.578553974628 0.498584330082 -424 1.0 1.0 -167 1.0 1.0 -425 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -367 0.5 0.0 -677 0.578553974628 0.498584330082 -425 0.5 0.5 -120 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -419 1.0 0.5 -164 1.0 1.0 -422 1.0 1.0 -678 0.609702944756 0.494907468557 -SURF 0x10 -mat 1 -refs 4 -123 1.0 0.0 -419 1.0 0.5 -678 0.609702944756 0.494907468557 -369 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -678 0.609702944756 0.494907468557 -422 1.0 1.0 -166 1.0 1.0 -423 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -369 0.5 0.0 -678 0.609702944756 0.494907468557 -423 0.5 0.5 -121 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -410 0.999999701977 0.500000059605 -158 1.0 1.0 -411 1.0 1.0 -679 0.596391201019 0.499797940254 -SURF 0x10 -mat 1 -refs 4 -129 1.0 0.0 -410 0.999999701977 0.500000059605 -679 0.596391201019 0.499797940254 -379 0.500000238419 8.27044122076e-09 -SURF 0x10 -mat 1 -refs 4 -679 0.596391201019 0.499797940254 -411 1.0 1.0 -156 1.0 1.0 -405 0.499999910593 0.499999910593 -SURF 0x10 -mat 1 -refs 4 -379 0.500000238419 8.27044122076e-09 -679 0.596391201019 0.499797940254 -405 0.499999910593 0.499999910593 -131 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -382 0.500000715256 -9.92566668856e-08 -128 1.0 0.0 -408 1.0 3.22411187881e-06 -680 0.89724034071 0.499653726816 -SURF 0x10 -mat 1 -refs 4 -129 0.0 0.0 -382 0.500000715256 -9.92566668856e-08 -680 0.89724034071 0.499653726816 -410 0.499999701977 0.500000119209 -SURF 0x10 -mat 1 -refs 4 -680 0.89724034071 0.499653726816 -408 1.0 3.22411187881e-06 -159 1.0 0.0 -409 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -410 0.499999701977 0.500000119209 -680 0.89724034071 0.499653726816 -409 1.0 0.5 -158 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -405 1.00000047684 0.499999940395 -156 1.0 1.0 -406 1.0 1.0 -681 0.580323040485 0.498678565025 -SURF 0x10 -mat 1 -refs 4 -131 1.0 0.0 -405 1.00000047684 0.499999940395 -681 0.580323040485 0.498678565025 -385 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -681 0.580323040485 0.498678565025 -406 1.0 1.0 -154 1.0 1.0 -402 0.500000059605 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -385 0.5 0.0 -681 0.580323040485 0.498678565025 -402 0.500000059605 0.500000059605 -133 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -349 0.499992161989 4.85449561438e-07 -109 1.0 0.0 -383 0.999999940395 -2.19633784582e-06 -682 0.945219278336 0.4991953969 -SURF 0x10 -mat 1 -refs 4 -111 0.0 0.0 -349 0.499992161989 4.85449561438e-07 -682 0.945219278336 0.4991953969 -381 0.500009536743 0.499999523163 -SURF 0x10 -mat 1 -refs 4 -682 0.945219278336 0.4991953969 -383 0.999999940395 -2.19633784582e-06 -130 1.0 0.0 -384 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -381 0.500009536743 0.499999523163 -682 0.945219278336 0.4991953969 -384 1.0 0.5 -128 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -350 0.500000059605 1.79687126289e-10 -111 1.0 0.0 -381 0.999999940395 -3.01620912069e-06 -683 0.930877685547 0.499883830547 -SURF 0x10 -mat 1 -refs 4 -110 0.0 0.0 -350 0.500000059605 1.79687126289e-10 -683 0.930877685547 0.499883830547 -378 0.500001847744 0.499999493361 -SURF 0x10 -mat 1 -refs 4 -683 0.930877685547 0.499883830547 -381 0.999999940395 -3.01620912069e-06 -128 1.0 0.0 -382 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -378 0.500001847744 0.499999493361 -683 0.930877685547 0.499883830547 -382 1.0 0.5 -129 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -378 1.00000202656 0.499999493361 -129 1.0 1.0 -379 1.0 1.0 -684 0.568936049938 0.498831242323 -SURF 0x10 -mat 1 -refs 4 -110 1.0 0.0 -378 1.00000202656 0.499999493361 -684 0.568936049938 0.498831242323 -351 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -684 0.568936049938 0.498831242323 -379 1.0 1.0 -131 1.0 1.0 -380 0.500000476837 0.500000476837 -SURF 0x10 -mat 1 -refs 4 -351 0.5 0.0 -684 0.568936049938 0.498831242323 -380 0.500000476837 0.500000476837 -108 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -368 1.0 0.5 -123 1.0 1.0 -369 1.0 1.0 -685 0.566195249557 0.493275314569 -SURF 0x10 -mat 1 -refs 4 -116 1.0 0.0 -368 1.0 0.5 -685 0.566195249557 0.493275314569 -360 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -685 0.566195249557 0.493275314569 -369 1.0 1.0 -121 1.0 1.0 -366 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -360 0.5 0.0 -685 0.566195249557 0.493275314569 -366 0.5 0.5 -118 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -361 0.499996483326 -6.43014004709e-07 -118 1.0 0.0 -366 1.0 4.21144150664e-08 -686 0.922234356403 0.499134838581 -SURF 0x10 -mat 1 -refs 4 -119 0.0 0.0 -361 0.499996483326 -6.43014004709e-07 -686 0.922234356403 0.499134838581 -363 0.499996304512 0.499999374151 -SURF 0x10 -mat 1 -refs 4 -686 0.922234356403 0.499134838581 -366 1.0 4.21144150664e-08 -121 1.0 0.0 -367 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -363 0.499996304512 0.499999374151 -686 0.922234356403 0.499134838581 -367 1.0 0.5 -120 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -362 0.5 0.0 -119 1.0 0.0 -363 1.0 -6.14676366695e-07 -687 0.927007317543 0.493729382753 -SURF 0x10 -mat 1 -refs 4 -117 0.0 0.0 -362 0.5 0.0 -687 0.927007317543 0.493729382753 -365 0.499999970198 0.499999344349 -SURF 0x10 -mat 1 -refs 4 -687 0.927007317543 0.493729382753 -363 1.0 -6.14676366695e-07 -120 1.0 0.0 -364 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -365 0.499999970198 0.499999344349 -687 0.927007317543 0.493729382753 -364 1.0 0.5 -122 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -338 0.5 0.0 -95 1.0 0.0 -480 1.0 0.0 -688 0.948111534119 0.501930058002 -SURF 0x10 -mat 1 -refs 4 -93 0.0 0.0 -338 0.5 0.0 -688 0.948111534119 0.501930058002 -482 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -688 0.948111534119 0.501930058002 -480 1.0 0.0 -119 1.0 0.0 -362 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -482 0.5 0.5 -688 0.948111534119 0.501930058002 -362 1.0 0.5 -117 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -336 0.500001192093 4.72389302786e-07 -94 1.0 0.0 -481 1.0 2.42745699097e-07 -689 0.931467711926 0.502086281776 -SURF 0x10 -mat 1 -refs 4 -95 0.0 0.0 -336 0.500001192093 4.72389302786e-07 -689 0.931467711926 0.502086281776 -480 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -689 0.931467711926 0.502086281776 -481 1.0 2.42745699097e-07 -118 1.0 0.0 -361 1.0 0.500000953674 -SURF 0x10 -mat 1 -refs 4 -480 0.5 0.5 -689 0.931467711926 0.502086281776 -361 1.0 0.500000953674 -119 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -483 1.0 0.5 -116 1.0 1.0 -360 1.0 1.0 -690 0.552353560925 0.499128907919 -SURF 0x10 -mat 1 -refs 4 -92 1.0 0.0 -483 1.0 0.5 -690 0.552353560925 0.499128907919 -334 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -690 0.552353560925 0.499128907919 -360 1.0 1.0 -118 1.0 1.0 -481 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -334 0.5 0.0 -690 0.552353560925 0.499128907919 -481 0.5 0.5 -94 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -333 0.500000536442 -2.51519471917e-10 -93 1.0 0.0 -482 1.0 0.0 -691 0.947343945503 0.50089687109 -SURF 0x10 -mat 1 -refs 4 -90 0.0 0.0 -333 0.500000536442 -2.51519471917e-10 -691 0.947343945503 0.50089687109 -484 0.499999821186 0.499999523163 -SURF 0x10 -mat 1 -refs 4 -691 0.947343945503 0.50089687109 -482 1.0 0.0 -117 1.0 0.0 -359 1.0 0.499999046326 -SURF 0x10 -mat 1 -refs 4 -484 0.499999821186 0.499999523163 -691 0.947343945503 0.50089687109 -359 1.0 0.499999046326 -114 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -485 0.999999701977 0.499999523163 -115 1.0 1.0 -358 1.0 1.0 -692 0.552868843079 0.499802976847 -SURF 0x10 -mat 1 -refs 4 -91 1.0 0.0 -485 0.999999701977 0.499999523163 -692 0.552868843079 0.499802976847 -330 0.499999761581 4.67027632567e-07 -SURF 0x10 -mat 1 -refs 4 -692 0.552868843079 0.499802976847 -358 1.0 1.0 -116 1.0 1.0 -483 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -330 0.499999761581 4.67027632567e-07 -692 0.552868843079 0.499802976847 -483 0.5 0.5 -92 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -486 1.00000023842 0.499999523163 -110 1.0 1.0 -351 1.0 1.0 -693 0.554753065109 0.501299083233 -SURF 0x10 -mat 1 -refs 4 -86 1.0 0.0 -486 1.00000023842 0.499999523163 -693 0.554753065109 0.501299083233 -317 0.499999731779 4.68599836267e-07 -SURF 0x10 -mat 1 -refs 4 -693 0.554753065109 0.501299083233 -351 1.0 1.0 -108 1.0 1.0 -488 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -317 0.499999731779 4.68599836267e-07 -693 0.554753065109 0.501299083233 -488 0.5 0.5 -84 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -315 0.5 0.0 -87 1.0 0.0 -487 0.999999940395 2.61550582081e-07 -694 0.943600296974 0.498737692833 -SURF 0x10 -mat 1 -refs 4 -86 0.0 0.0 -315 0.5 0.0 -694 0.943600296974 0.498737692833 -486 0.499999850988 0.499999523163 -SURF 0x10 -mat 1 -refs 4 -694 0.943600296974 0.498737692833 -487 0.999999940395 2.61550582081e-07 -111 1.0 0.0 -350 1.0 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -486 0.499999850988 0.499999523163 -694 0.943600296974 0.498737692833 -350 1.0 0.499999970198 -110 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -313 0.499993890524 4.69514930046e-07 -85 1.0 0.0 -489 1.0 6.90623664923e-06 -695 0.958424866199 0.499115228653 -SURF 0x10 -mat 1 -refs 4 -87 0.0 0.0 -313 0.499993890524 4.69514930046e-07 -695 0.958424866199 0.499115228653 -487 0.499994635582 0.500000476837 -SURF 0x10 -mat 1 -refs 4 -695 0.958424866199 0.499115228653 -489 1.0 6.90623664923e-06 -109 1.0 0.0 -349 1.0 0.500006020069 -SURF 0x10 -mat 1 -refs 4 -487 0.499994635582 0.500000476837 -695 0.958424866199 0.499115228653 -349 1.0 0.500006020069 -111 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -337 1.0 0.500000178814 -95 1.0 1.0 -338 1.0 1.0 -696 0.525527179241 0.499881803989 -SURF 0x10 -mat 1 -refs 4 -48 1.0 0.0 -337 1.0 0.500000178814 -696 0.525527179241 0.499881803989 -272 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -696 0.525527179241 0.499881803989 -338 1.0 1.0 -93 1.0 1.0 -332 0.499999850988 0.499999850988 -SURF 0x10 -mat 1 -refs 4 -272 0.5 0.0 -696 0.525527179241 0.499881803989 -332 0.499999850988 0.499999850988 -50 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -335 1.00000047684 0.500000178814 -94 1.0 1.0 -336 1.00000023842 1.00000023842 -697 0.499886512756 0.499886512756 -SURF 0x10 -mat 1 -refs 4 -49 1.0 0.0 -335 1.00000047684 0.500000178814 -697 0.499886512756 0.499886512756 -274 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -697 0.499886512756 0.499886512756 -336 1.00000023842 1.00000023842 -95 1.0 1.0 -337 0.500000178814 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -274 0.5 0.0 -697 0.499886512756 0.499886512756 -337 0.500000178814 0.500000178814 -48 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -275 0.500000119209 1.65844838307e-07 -51 1.0 0.0 -331 1.0 0.0 -698 0.974247872829 0.500021159649 -SURF 0x10 -mat 1 -refs 4 -49 0.0 0.0 -275 0.500000119209 1.65844838307e-07 -698 0.974247872829 0.500021159649 -335 0.500000178814 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -698 0.974247872829 0.500021159649 -331 1.0 0.0 -92 1.0 0.0 -334 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -335 0.500000178814 0.500000178814 -698 0.974247872829 0.500021159649 -334 1.0 0.5 -94 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -332 1.0 0.499999821186 -93 1.0 1.0 -333 1.0 1.0 -699 0.525595843792 0.499943375587 -SURF 0x10 -mat 1 -refs 4 -50 1.0 0.0 -332 1.0 0.499999821186 -699 0.525595843792 0.499943375587 -276 0.499999463558 -1.6594796648e-07 -SURF 0x10 -mat 1 -refs 4 -699 0.525595843792 0.499943375587 -333 1.0 1.0 -90 1.0 1.0 -328 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -276 0.499999463558 -1.6594796648e-07 -699 0.525595843792 0.499943375587 -328 0.5 0.5 -53 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -277 0.500000178814 1.65830542187e-07 -52 1.0 0.0 -327 1.0 5.5575873148e-07 -700 0.974367380142 0.499989807606 -SURF 0x10 -mat 1 -refs 4 -51 0.0 0.0 -277 0.500000178814 1.65830542187e-07 -700 0.974367380142 0.499989807606 -331 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -700 0.974367380142 0.499989807606 -327 1.0 5.5575873148e-07 -91 1.0 0.0 -330 1.0 0.500000536442 -SURF 0x10 -mat 1 -refs 4 -331 0.5 0.5 -700 0.974367380142 0.499989807606 -330 1.0 0.500000536442 -92 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -278 0.500000536442 1.66030659443e-07 -53 1.0 0.0 -328 1.0 0.0 -701 0.97441983223 0.500061869621 -SURF 0x10 -mat 1 -refs 4 -55 0.0 0.0 -278 0.500000536442 1.66030659443e-07 -701 0.97441983223 0.500061869621 -324 0.500000178814 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -701 0.97441983223 0.500061869621 -328 1.0 0.0 -90 1.0 0.0 -329 1.0 0.500000417233 -SURF 0x10 -mat 1 -refs 4 -324 0.500000178814 0.500000178814 -701 0.97441983223 0.500061869621 -329 1.0 0.500000417233 -88 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -323 0.999999642372 0.5 -89 1.0 1.0 -326 0.999999642372 0.999999642372 -702 0.525634169579 0.499984592199 -SURF 0x10 -mat 1 -refs 4 -54 1.0 0.0 -323 0.999999642372 0.5 -702 0.525634169579 0.499984592199 -279 0.5 1.65827032106e-07 -SURF 0x10 -mat 1 -refs 4 -702 0.525634169579 0.499984592199 -326 0.999999642372 0.999999642372 -91 1.0 1.0 -327 0.499999821186 0.499999821186 -SURF 0x10 -mat 1 -refs 4 -279 0.5 1.65827032106e-07 -702 0.525634169579 0.499984592199 -327 0.499999821186 0.499999821186 -52 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -280 0.500000119209 1.66147628988e-07 -55 1.0 0.0 -324 1.0 1.61930771014e-08 -703 0.974403500557 0.500108361244 -SURF 0x10 -mat 1 -refs 4 -71 0.0 0.0 -280 0.500000119209 1.66147628988e-07 -703 0.974403500557 0.500108361244 -318 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -703 0.974403500557 0.500108361244 -324 1.0 1.61930771014e-08 -88 1.0 0.0 -325 1.0 0.500000298023 -SURF 0x10 -mat 1 -refs 4 -318 0.5 0.5 -703 0.974403500557 0.500108361244 -325 1.0 0.500000298023 -72 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -321 1.00000011921 0.5 -73 1.0 1.0 -322 1.0 1.0 -704 0.525682747364 0.499979585409 -SURF 0x10 -mat 1 -refs 4 -70 1.0 0.0 -321 1.00000011921 0.5 -704 0.525682747364 0.499979585409 -281 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -704 0.525682747364 0.499979585409 -322 1.0 1.0 -89 1.0 1.0 -323 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -281 0.5 0.0 -704 0.525682747364 0.499979585409 -323 0.5 0.5 -54 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -302 1.0 0.5 -75 1.0 1.0 -320 0.999999642372 0.999999642372 -705 0.525634586811 0.499978214502 -SURF 0x10 -mat 1 -refs 4 -68 1.0 0.0 -302 1.0 0.5 -705 0.525634586811 0.499978214502 -282 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -705 0.525634586811 0.499978214502 -320 0.999999642372 0.999999642372 -73 1.0 1.0 -321 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -282 0.5 0.0 -705 0.525634586811 0.499978214502 -321 0.5 0.5 -70 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -283 0.5 0.0 -71 1.0 0.0 -318 1.0 0.0 -706 0.974388599396 0.500047206879 -SURF 0x10 -mat 1 -refs 4 -69 0.0 0.0 -283 0.5 0.0 -706 0.974388599396 0.500047206879 -297 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -706 0.974388599396 0.500047206879 -318 1.0 0.0 -72 1.0 0.0 -319 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -297 0.5 0.5 -706 0.974388599396 0.500047206879 -319 1.0 0.5 -74 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -316 1.0 0.500000178814 -86 1.0 1.0 -317 1.00000035763 1.00000035763 -707 0.525880217552 0.500072538853 -SURF 0x10 -mat 1 -refs 4 -57 1.0 0.0 -316 1.0 0.500000178814 -707 0.525880217552 0.500072538853 -284 0.5 7.13211499408e-13 -SURF 0x10 -mat 1 -refs 4 -707 0.525880217552 0.500072538853 -317 1.00000035763 1.00000035763 -84 1.0 1.0 -311 0.499999850988 0.499999850988 -SURF 0x10 -mat 1 -refs 4 -284 0.5 7.13211499408e-13 -707 0.525880217552 0.500072538853 -311 0.499999850988 0.499999850988 -59 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -285 0.5 -1.6808847066e-13 -56 1.0 0.0 -314 1.0 4.72665675488e-08 -708 0.974051117897 0.499934643507 -SURF 0x10 -mat 1 -refs 4 -57 0.0 0.0 -285 0.5 -1.6808847066e-13 -708 0.974051117897 0.499934643507 -316 0.500000178814 0.500000178814 -SURF 0x10 -mat 1 -refs 4 -708 0.974051117897 0.499934643507 -314 1.0 4.72665675488e-08 -87 1.0 0.0 -315 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -316 0.500000178814 0.500000178814 -708 0.974051117897 0.499934643507 -315 1.0 0.5 -86 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -286 0.5 0.0 -58 1.0 0.0 -310 1.0 9.73553937911e-07 -709 0.974543273449 0.499961048365 -SURF 0x10 -mat 1 -refs 4 -56 0.0 0.0 -286 0.5 0.0 -709 0.974543273449 0.499961048365 -314 0.500000715256 0.499999821186 -SURF 0x10 -mat 1 -refs 4 -709 0.974543273449 0.499961048365 -310 1.0 9.73553937911e-07 -85 1.0 0.0 -313 1.0 0.500001966953 -SURF 0x10 -mat 1 -refs 4 -314 0.500000715256 0.499999821186 -709 0.974543273449 0.499961048365 -313 1.0 0.500001966953 -87 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -300 0.999999821186 0.5 -77 1.0 1.0 -301 1.00000023842 1.00000023842 -710 0.525664389133 0.500013947487 -SURF 0x10 -mat 1 -refs 4 -66 1.0 0.0 -300 0.999999821186 0.5 -710 0.525664389133 0.500013947487 -295 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -710 0.525664389133 0.500013947487 -301 1.00000023842 1.00000023842 -75 1.0 1.0 -302 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -295 0.5 0.0 -710 0.525664389133 0.500013947487 -302 0.5 0.5 -68 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -296 0.5 0.0 -69 1.0 0.0 -297 1.0 0.0 -711 0.97435593605 0.500015616417 -SURF 0x10 -mat 1 -refs 4 -67 0.0 0.0 -296 0.5 0.0 -711 0.97435593605 0.500015616417 -299 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -711 0.97435593605 0.500015616417 -297 1.0 0.0 -74 1.0 0.0 -298 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -299 0.5 0.5 -711 0.97435593605 0.500015616417 -298 1.0 0.5 -76 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -269 0.500000059605 -1.88733555694e-12 -43 1.0 0.0 -501 1.0 0.0 -712 0.973221182823 0.5 -SURF 0x10 -mat 1 -refs 4 -41 0.0 0.0 -269 0.500000059605 -1.88733555694e-12 -712 0.973221182823 0.5 -490 0.500000059605 0.5 -SURF 0x10 -mat 1 -refs 4 -712 0.973221182823 0.5 -501 1.0 0.0 -69 1.0 0.0 -296 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -490 0.500000059605 0.5 -712 0.973221182823 0.5 -296 1.0 0.5 -67 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -491 1.0 0.5 -66 1.0 1.0 -295 1.0 1.0 -713 0.526778638363 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -40 1.0 0.0 -491 1.0 0.5 -713 0.526778638363 0.499999970198 -268 0.500000059605 1.8798623682e-12 -SURF 0x10 -mat 1 -refs 4 -713 0.526778638363 0.499999970198 -295 1.0 1.0 -68 1.0 1.0 -502 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -268 0.500000059605 1.8798623682e-12 -713 0.526778638363 0.499999970198 -502 0.5 0.5 -42 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -267 0.5 0.0 -41 1.0 0.0 -490 1.0 -9.84095223089e-08 -714 0.97322010994 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -39 0.0 0.0 -267 0.5 0.0 -714 0.97322010994 0.499999970198 -492 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -714 0.97322010994 0.499999970198 -490 1.0 -9.84095223089e-08 -67 1.0 0.0 -294 1.0 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -492 0.5 0.5 -714 0.97322010994 0.499999970198 -294 1.0 0.500000059605 -65 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -263 0.5 0.0 -39 1.0 0.0 -492 1.0 0.0 -715 0.973220229149 0.5 -SURF 0x10 -mat 1 -refs 4 -37 0.0 0.0 -263 0.5 0.0 -715 0.973220229149 0.5 -493 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -715 0.973220229149 0.5 -492 1.0 0.0 -65 1.0 0.0 -292 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -493 0.5 0.5 -715 0.973220229149 0.5 -292 1.0 0.5 -63 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -259 0.500000059605 2.14563508291e-14 -37 1.0 0.0 -493 1.0 0.0 -716 0.973220229149 0.5 -SURF 0x10 -mat 1 -refs 4 -34 0.0 0.0 -259 0.500000059605 2.14563508291e-14 -716 0.973220229149 0.5 -495 0.500000059605 0.5 -SURF 0x10 -mat 1 -refs 4 -716 0.973220229149 0.5 -493 1.0 0.0 -63 1.0 0.0 -290 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -495 0.500000059605 0.5 -716 0.973220229149 0.5 -290 1.0 0.5 -60 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -496 0.999999940395 0.5 -61 1.0 1.0 -289 1.0 1.0 -717 0.526780843735 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -35 1.0 0.0 -496 0.999999940395 0.5 -717 0.526780843735 0.499999970198 -256 0.499999940395 -7.40039648485e-13 -SURF 0x10 -mat 1 -refs 4 -717 0.526780843735 0.499999970198 -289 1.0 1.0 -62 1.0 1.0 -494 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -256 0.499999940395 -7.40039648485e-13 -717 0.526780843735 0.499999970198 -494 0.5 0.5 -36 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -255 0.5 0.0 -34 1.0 0.0 -495 0.999999940395 -8.07643658618e-08 -718 0.973219275475 0.5 -SURF 0x10 -mat 1 -refs 4 -32 0.0 0.0 -255 0.5 0.0 -718 0.973219275475 0.5 -497 0.500000059605 0.5 -SURF 0x10 -mat 1 -refs 4 -718 0.973219275475 0.5 -495 0.999999940395 -8.07643658618e-08 -60 1.0 0.0 -288 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -497 0.500000059605 0.5 -718 0.973219275475 0.5 -288 1.0 0.5 -58 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -499 0.999999940395 0.5 -59 1.0 1.0 -287 1.0 1.0 -719 0.526780664921 0.5 -SURF 0x10 -mat 1 -refs 4 -33 1.0 0.0 -499 0.999999940395 0.5 -719 0.526780664921 0.5 -252 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -719 0.526780664921 0.5 -287 1.0 1.0 -61 1.0 1.0 -496 0.499999970198 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -252 0.5 0.0 -719 0.526780664921 0.5 -496 0.499999970198 0.499999970198 -35 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -251 0.499999970198 -4.50789714801e-14 -32 1.0 0.0 -497 1.00000011921 -1.65000827224e-07 -720 0.973224401474 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -30 0.0 0.0 -251 0.499999970198 -4.50789714801e-14 -720 0.973224401474 0.499999970198 -498 0.500000119209 0.5 -SURF 0x10 -mat 1 -refs 4 -720 0.973224401474 0.499999970198 -497 1.00000011921 -1.65000827224e-07 -58 1.0 0.0 -286 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -498 0.500000119209 0.5 -720 0.973224401474 0.499999970198 -286 1.0 0.5 -56 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -249 0.5 1.23890426997e-13 -30 1.0 0.0 -498 1.0 4.30979554267e-08 -721 0.973220348358 0.5 -SURF 0x10 -mat 1 -refs 4 -31 0.0 0.0 -249 0.5 1.23890426997e-13 -721 0.973220348358 0.5 -500 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -721 0.973220348358 0.5 -498 1.0 4.30979554267e-08 -56 1.0 0.0 -285 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -500 0.5 0.5 -721 0.973220348358 0.5 -285 1.0 0.5 -57 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -500 1.0 0.5 -57 1.0 1.0 -284 1.0 1.0 -722 0.52677822113 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -31 1.0 0.0 -500 1.0 0.5 -722 0.52677822113 0.500000059605 -246 0.5 1.71326901234e-13 -SURF 0x10 -mat 1 -refs 4 -722 0.52677822113 0.500000059605 -284 1.0 1.0 -59 1.0 1.0 -499 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -246 0.5 1.71326901234e-13 -722 0.52677822113 0.500000059605 -499 0.5 0.5 -33 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -243 0.499999850988 4.31888899644e-12 -45 1.0 0.0 -504 1.00000011921 -1.52695008637e-07 -723 0.97322010994 0.5 -SURF 0x10 -mat 1 -refs 4 -43 0.0 0.0 -243 0.499999850988 4.31888899644e-12 -723 0.97322010994 0.5 -501 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -723 0.97322010994 0.5 -504 1.00000011921 -1.52695008637e-07 -71 1.0 0.0 -283 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -501 0.5 0.5 -723 0.97322010994 0.5 -283 1.0 0.5 -69 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -502 1.0 0.5 -68 1.0 1.0 -282 1.0 1.0 -724 0.526780068874 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -42 1.0 0.0 -502 1.0 0.5 -724 0.526780068874 0.500000059605 -242 0.500000119209 3.11779508461e-12 -SURF 0x10 -mat 1 -refs 4 -724 0.526780068874 0.500000059605 -282 1.0 1.0 -70 1.0 1.0 -503 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -242 0.500000119209 3.11779508461e-12 -724 0.526780068874 0.500000059605 -503 0.5 0.5 -44 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -503 1.00000011921 0.5 -70 1.0 1.0 -281 1.0 1.0 -725 0.526778280735 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -44 1.0 0.0 -503 1.00000011921 0.5 -725 0.526778280735 0.499999970198 -240 0.500000119209 3.14952426118e-12 -SURF 0x10 -mat 1 -refs 4 -725 0.526778280735 0.499999970198 -281 1.0 1.0 -54 1.0 1.0 -505 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -240 0.500000119209 3.14952426118e-12 -725 0.526778280735 0.499999970198 -505 0.5 0.5 -28 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -237 0.499999880791 5.08537309485e-12 -29 1.0 0.0 -506 1.0 -2.67258485565e-07 -726 0.973222017288 0.5 -SURF 0x10 -mat 1 -refs 4 -45 0.0 0.0 -237 0.499999880791 5.08537309485e-12 -726 0.973222017288 0.5 -504 0.500000119209 0.5 -SURF 0x10 -mat 1 -refs 4 -726 0.973222017288 0.5 -506 1.0 -2.67258485565e-07 -55 1.0 0.0 -280 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -504 0.500000119209 0.5 -726 0.973222017288 0.5 -280 1.0 0.5 -71 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -505 1.0 0.5 -54 1.0 1.0 -279 1.0 1.0 -727 0.526780664921 0.5 -SURF 0x10 -mat 1 -refs 4 -28 1.0 0.0 -505 1.0 0.5 -727 0.526780664921 0.5 -236 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -727 0.526780664921 0.5 -279 1.0 1.0 -52 1.0 1.0 -507 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -236 0.5 0.0 -727 0.526780664921 0.5 -507 0.5 0.5 -26 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -233 0.499999672174 9.73854243774e-12 -27 1.0 0.0 -508 1.0 3.74986200313e-07 -728 0.973219931126 0.5 -SURF 0x10 -mat 1 -refs 4 -29 0.0 0.0 -233 0.499999672174 9.73854243774e-12 -728 0.973219931126 0.5 -506 0.500000357628 0.5 -SURF 0x10 -mat 1 -refs 4 -728 0.973219931126 0.5 -508 1.0 3.74986200313e-07 -53 1.0 0.0 -278 1.0 0.49999961257 -SURF 0x10 -mat 1 -refs 4 -506 0.500000357628 0.5 -728 0.973219931126 0.5 -278 1.0 0.49999961257 -55 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -232 0.5 0.0 -26 1.0 0.0 -507 1.0 0.0 -729 0.97320407629 0.499999940395 -SURF 0x10 -mat 1 -refs 4 -25 0.0 0.0 -232 0.5 0.0 -729 0.97320407629 0.499999940395 -509 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -729 0.97320407629 0.499999940395 -507 1.0 0.0 -52 1.0 0.0 -277 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -509 0.5 0.5 -729 0.97320407629 0.499999940395 -277 1.0 0.5 -51 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -510 1.0 0.5 -50 1.0 1.0 -276 1.0 1.0 -730 0.526794016361 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -24 1.0 0.0 -510 1.0 0.5 -730 0.526794016361 0.499999970198 -229 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -730 0.526794016361 0.499999970198 -276 1.0 1.0 -53 1.0 1.0 -508 0.499999970198 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -229 0.5 0.0 -730 0.526794016361 0.499999970198 -508 0.499999970198 0.499999970198 -27 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -512 0.5 0.0 -25 1.0 0.0 -509 1.0 0.0 -731 0.973233580589 0.500000119209 -SURF 0x10 -mat 1 -refs 4 -46 0.0 0.0 -512 0.5 0.0 -731 0.973233580589 0.500000119209 -273 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -731 0.973233580589 0.500000119209 -509 1.0 0.0 -51 1.0 0.0 -275 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -273 0.5 0.5 -731 0.973233580589 0.500000119209 -275 1.0 0.5 -49 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -273 0.999999761581 0.5 -49 1.0 1.0 -274 1.0 1.0 -732 0.55764234066 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -46 1.0 0.0 -273 0.999999761581 0.5 -732 0.55764234066 0.500000059605 -270 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -732 0.55764234066 0.500000059605 -274 1.0 1.0 -48 1.0 1.0 -271 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -270 0.5 0.0 -732 0.55764234066 0.500000059605 -271 0.5 0.5 -47 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -271 1.0 0.5 -48 1.0 1.0 -272 1.0 1.0 -733 0.527099490166 0.499999701977 -SURF 0x10 -mat 1 -refs 4 -47 1.0 0.0 -271 1.0 0.5 -733 0.527099490166 0.499999701977 -511 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -733 0.527099490166 0.499999701977 -272 1.0 1.0 -50 1.0 1.0 -510 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -511 0.5 0.0 -733 0.527099490166 0.499999701977 -510 0.5 0.5 -24 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -195 0.499999910593 1.37961175687e-13 -2 1.0 0.0 -244 1.0 0.0 -734 1.0 0.498998969793 -SURF 0x10 -mat 1 -refs 4 -4 0.0 0.0 -195 0.499999910593 1.37961175687e-13 -734 1.0 0.498998969793 -266 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -734 1.0 0.498998969793 -244 1.0 0.0 -43 1.0 0.0 -269 1.0 0.499999910593 -SURF 0x10 -mat 1 -refs 4 -266 0.5 0.5 -734 1.0 0.498998969793 -269 1.0 0.499999910593 -41 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -265 1.0 0.5 -40 1.0 1.0 -268 1.0 1.0 -735 0.500144839287 0.500079274178 -SURF 0x10 -mat 1 -refs 4 -5 1.0 0.0 -265 1.0 0.5 -735 0.500144839287 0.500079274178 -197 0.500000059605 1.34328732491e-13 -SURF 0x10 -mat 1 -refs 4 -735 0.500144839287 0.500079274178 -268 1.0 1.0 -42 1.0 1.0 -241 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -197 0.500000059605 1.34328732491e-13 -735 0.500144839287 0.500079274178 -241 0.5 0.5 -3 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -198 0.5 0.0 -4 1.0 0.0 -266 1.0 0.0 -736 0.999594211578 0.500052630901 -SURF 0x10 -mat 1 -refs 4 -6 0.0 0.0 -198 0.5 0.0 -736 0.999594211578 0.500052630901 -262 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -736 0.999594211578 0.500052630901 -266 1.0 0.0 -41 1.0 0.0 -267 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -262 0.5 0.5 -736 0.999594211578 0.500052630901 -267 1.0 0.5 -39 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -261 1.0 0.5 -38 1.0 1.0 -264 1.0 1.0 -737 0.500078320503 0.500078320503 -SURF 0x10 -mat 1 -refs 4 -7 1.0 0.0 -261 1.0 0.5 -737 0.500078320503 0.500078320503 -200 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -737 0.500078320503 0.500078320503 -264 1.0 1.0 -40 1.0 1.0 -265 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -200 0.5 0.0 -737 0.500078320503 0.500078320503 -265 0.5 0.5 -5 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -201 0.5 0.0 -6 1.0 0.0 -262 1.0 0.0 -738 1.0 0.498987287283 -SURF 0x10 -mat 1 -refs 4 -8 0.0 0.0 -201 0.5 0.0 -738 1.0 0.498987287283 -258 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -738 1.0 0.498987287283 -262 1.0 0.0 -39 1.0 0.0 -263 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -258 0.5 0.5 -738 1.0 0.498987287283 -263 1.0 0.5 -37 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -257 1.0 0.5 -36 1.0 1.0 -260 1.0 1.0 -739 0.500058412552 0.500058412552 -SURF 0x10 -mat 1 -refs 4 -9 1.0 0.0 -257 1.0 0.5 -739 0.500058412552 0.500058412552 -203 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -739 0.500058412552 0.500058412552 -260 1.0 1.0 -38 1.0 1.0 -261 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -203 0.5 0.0 -739 0.500058412552 0.500058412552 -261 0.5 0.5 -7 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -204 0.500000059605 0.0 -8 1.0 0.0 -258 1.0 0.0 -740 1.0 0.492396861315 -SURF 0x10 -mat 1 -refs 4 -11 0.0 0.0 -204 0.500000059605 0.0 -740 1.0 0.492396861315 -254 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -740 1.0 0.492396861315 -258 1.0 0.0 -37 1.0 0.0 -259 1.0 0.499999940395 -SURF 0x10 -mat 1 -refs 4 -254 0.5 0.5 -740 1.0 0.492396861315 -259 1.0 0.499999940395 -34 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -253 1.0 0.5 -35 1.0 1.0 -256 1.0 1.0 -741 0.50004452467 0.50004452467 -SURF 0x10 -mat 1 -refs 4 -10 1.0 0.0 -253 1.0 0.5 -741 0.50004452467 0.50004452467 -206 0.499999940395 -9.39261892547e-14 -SURF 0x10 -mat 1 -refs 4 -741 0.50004452467 0.50004452467 -256 1.0 1.0 -36 1.0 1.0 -257 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -206 0.499999940395 -9.39261892547e-14 -741 0.50004452467 0.50004452467 -257 0.5 0.5 -9 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -207 0.5 0.0 -11 1.0 0.0 -254 1.0 0.0 -742 0.999529123306 0.499992758036 -SURF 0x10 -mat 1 -refs 4 -13 0.0 0.0 -207 0.5 0.0 -742 0.999529123306 0.499992758036 -250 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -742 0.999529123306 0.499992758036 -254 1.0 0.0 -34 1.0 0.0 -255 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -250 0.5 0.5 -742 0.999529123306 0.499992758036 -255 1.0 0.5 -32 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -247 1.0 0.5 -33 1.0 1.0 -252 1.0 1.0 -743 0.500466644764 0.500040829182 -SURF 0x10 -mat 1 -refs 4 -12 1.0 0.0 -247 1.0 0.5 -743 0.500466644764 0.500040829182 -209 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -743 0.500466644764 0.500040829182 -252 1.0 1.0 -35 1.0 1.0 -253 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -209 0.5 0.0 -743 0.500466644764 0.500040829182 -253 0.5 0.5 -10 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -210 0.499999970198 0.0 -13 1.0 0.0 -250 1.0 0.0 -744 1.0 0.491295218468 -SURF 0x10 -mat 1 -refs 4 -15 0.0 0.0 -210 0.499999970198 0.0 -744 1.0 0.491295218468 -248 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -744 1.0 0.491295218468 -250 1.0 0.0 -32 1.0 0.0 -251 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -248 0.5 0.5 -744 1.0 0.491295218468 -251 1.0 0.5 -30 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -211 0.5 -1.56518513428e-11 -15 1.0 0.0 -248 1.0 0.0 -745 0.997083067894 0.499735295773 -SURF 0x10 -mat 1 -refs 4 -14 0.0 0.0 -211 0.5 -1.56518513428e-11 -745 0.997083067894 0.499735295773 -245 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -745 0.997083067894 0.499735295773 -248 1.0 0.0 -30 1.0 0.0 -249 1.0 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -245 0.5 0.5 -745 0.997083067894 0.499735295773 -249 1.0 0.499999970198 -31 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -245 1.0 0.5 -31 1.0 1.0 -246 1.0 1.0 -746 0.504721522331 0.499800294638 -SURF 0x10 -mat 1 -refs 4 -14 1.0 0.0 -245 1.0 0.5 -746 0.504721522331 0.499800294638 -212 0.5 1.32276299289e-11 -SURF 0x10 -mat 1 -refs 4 -746 0.504721522331 0.499800294638 -246 1.0 1.0 -33 1.0 1.0 -247 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -212 0.5 1.32276299289e-11 -746 0.504721522331 0.499800294638 -247 0.5 0.5 -12 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -213 0.499999850988 2.50053531483e-13 -0 1.0 0.0 -238 1.0 0.0 -747 1.0 0.497135430574 -SURF 0x10 -mat 1 -refs 4 -2 0.0 0.0 -213 0.499999850988 2.50053531483e-13 -747 1.0 0.497135430574 -244 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -747 1.0 0.497135430574 -238 1.0 0.0 -45 1.0 0.0 -243 1.0 0.500000119209 -SURF 0x10 -mat 1 -refs 4 -244 0.5 0.5 -747 1.0 0.497135430574 -243 1.0 0.500000119209 -43 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -241 1.0 0.5 -42 1.0 1.0 -242 1.0 1.0 -748 0.500070512295 0.500070512295 -SURF 0x10 -mat 1 -refs 4 -3 1.0 0.0 -241 1.0 0.5 -748 0.500070512295 0.500070512295 -214 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -748 0.500070512295 0.500070512295 -242 1.0 1.0 -44 1.0 1.0 -239 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -214 0.5 0.0 -748 0.500070512295 0.500070512295 -239 0.5 0.5 -1 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -239 1.00000011921 0.5 -44 1.0 1.0 -240 1.0 1.0 -749 0.506132662296 0.500083744526 -SURF 0x10 -mat 1 -refs 4 -1 1.0 0.0 -239 1.00000011921 0.5 -749 0.506132662296 0.500083744526 -215 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -749 0.506132662296 0.500083744526 -240 1.0 1.0 -28 1.0 1.0 -235 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -215 0.5 0.0 -749 0.506132662296 0.500083744526 -235 0.5 0.5 -17 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -217 0.500000119209 -2.11071042372e-13 -16 1.0 0.0 -234 1.0 -2.38634925154e-07 -750 0.994156301022 0.500133693218 -SURF 0x10 -mat 1 -refs 4 -0 0.0 0.0 -217 0.500000119209 -2.11071042372e-13 -750 0.994156301022 0.500133693218 -238 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -750 0.994156301022 0.500133693218 -234 1.0 -2.38634925154e-07 -29 1.0 0.0 -237 1.0 0.500000119209 -SURF 0x10 -mat 1 -refs 4 -238 0.5 0.5 -750 0.994156301022 0.500133693218 -237 1.0 0.500000119209 -45 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -235 1.0 0.5 -28 1.0 1.0 -236 1.0 1.0 -751 0.500058591366 0.500058591366 -SURF 0x10 -mat 1 -refs 4 -17 1.0 0.0 -235 1.0 0.5 -751 0.500058591366 0.500058591366 -218 0.500000357628 0.0 -SURF 0x10 -mat 1 -refs 4 -751 0.500058591366 0.500058591366 -236 1.0 1.0 -26 1.0 1.0 -231 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -218 0.500000357628 0.0 -751 0.500058591366 0.500058591366 -231 0.5 0.5 -19 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -220 0.500000357628 -6.17986131018e-13 -18 1.0 0.0 -230 1.0 3.34825216441e-07 -752 1.0 0.495344668627 -SURF 0x10 -mat 1 -refs 4 -16 0.0 0.0 -220 0.500000357628 -6.17986131018e-13 -752 1.0 0.495344668627 -234 0.500000357628 0.5 -SURF 0x10 -mat 1 -refs 4 -752 1.0 0.495344668627 -230 1.0 3.34825216441e-07 -27 1.0 0.0 -233 1.0 0.500000357628 -SURF 0x10 -mat 1 -refs 4 -234 0.500000357628 0.5 -752 1.0 0.495344668627 -233 1.0 0.500000357628 -29 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -231 1.00000047684 0.5 -26 1.0 1.0 -232 1.0 1.0 -753 0.500048518181 0.500048518181 -SURF 0x10 -mat 1 -refs 4 -19 1.0 0.0 -231 1.00000047684 0.5 -753 0.500048518181 0.500048518181 -221 0.499999552965 -8.25000170176e-13 -SURF 0x10 -mat 1 -refs 4 -753 0.500048518181 0.500048518181 -232 1.0 1.0 -25 1.0 1.0 -228 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -221 0.499999552965 -8.25000170176e-13 -753 0.500048518181 0.500048518181 -228 0.5 0.5 -20 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -223 0.499999552965 0.0 -21 1.0 0.0 -227 1.0 0.0 -754 1.0 0.492138087749 -SURF 0x10 -mat 1 -refs 4 -18 0.0 0.0 -223 0.499999552965 0.0 -754 1.0 0.492138087749 -230 0.499999552965 0.5 -SURF 0x10 -mat 1 -refs 4 -754 1.0 0.492138087749 -227 1.0 0.0 -24 1.0 0.0 -229 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -230 0.499999552965 0.5 -754 1.0 0.492138087749 -229 1.0 0.5 -27 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -222 0.499999970198 -9.9605623749e-10 -20 1.0 0.0 -224 0.999999940395 8.89345130872e-08 -755 0.966748058796 0.50280046463 -SURF 0x10 -mat 1 -refs 4 -21 0.0 0.0 -222 0.499999970198 -9.9605623749e-10 -755 0.966748058796 0.50280046463 -226 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -755 0.966748058796 0.50280046463 -224 0.999999940395 8.89345130872e-08 -22 1.0 0.0 -225 1.0 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -226 0.5 0.5 -755 0.966748058796 0.50280046463 -225 1.0 0.500000059605 -23 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -219 0.499999970198 -1.03105601834e-09 -19 1.0 0.0 -221 1.0 1.26376306753e-07 -756 0.960986077785 0.499279558659 -SURF 0x10 -mat 1 -refs 4 -18 0.0 0.0 -219 0.499999970198 -1.03105601834e-09 -756 0.960986077785 0.499279558659 -223 0.499999672174 0.499999552965 -SURF 0x10 -mat 1 -refs 4 -756 0.960986077785 0.499279558659 -221 1.0 1.26376306753e-07 -20 1.0 0.0 -222 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -223 0.499999672174 0.499999552965 -756 0.960986077785 0.499279558659 -222 1.0 0.5 -21 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -216 0.5 -5.19066345461e-10 -17 1.0 0.0 -218 1.0 -9.38187127986e-09 -757 0.948417305946 0.499286293983 -SURF 0x10 -mat 1 -refs 4 -16 0.0 0.0 -216 0.5 -5.19066345461e-10 -757 0.948417305946 0.499286293983 -220 0.500000298023 0.500000357628 -SURF 0x10 -mat 1 -refs 4 -757 0.948417305946 0.499286293983 -218 1.0 -9.38187127986e-09 -19 1.0 0.0 -219 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -220 0.500000298023 0.500000357628 -757 0.948417305946 0.499286293983 -219 1.0 0.5 -18 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -194 0.500000059605 1.15361224573e-07 -1 1.0 0.0 -215 1.0 0.0 -758 0.936104893684 0.499395042658 -SURF 0x10 -mat 1 -refs 4 -0 0.0 0.0 -194 0.500000059605 1.15361224573e-07 -758 0.936104893684 0.499395042658 -217 0.500000119209 0.500000119209 -SURF 0x10 -mat 1 -refs 4 -758 0.936104893684 0.499395042658 -215 1.0 0.0 -17 1.0 0.0 -216 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -217 0.500000119209 0.500000119209 -758 0.936104893684 0.499395042658 -216 1.0 0.5 -16 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -194 0.499999970198 0.499999970198 -0 0.0 0.0 -213 0.500000119209 2.66104791535e-08 -759 0.501956939697 0.470399051905 -SURF 0x10 -mat 1 -refs 4 -1 1.0 1.0 -194 0.499999970198 0.499999970198 -759 0.501956939697 0.470399051905 -214 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -759 0.501956939697 0.470399051905 -213 0.500000119209 2.66104791535e-08 -2 1.0 0.0 -193 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -214 1.0 1.0 -759 0.501956939697 0.470399051905 -193 1.0 0.5 -3 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -208 0.5 0.0 -13 1.0 0.0 -210 1.0 -1.31993571628e-08 -760 0.810484051704 0.445699781179 -SURF 0x10 -mat 1 -refs 4 -12 0.0 0.0 -208 0.5 0.0 -760 0.810484051704 0.445699781179 -212 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -760 0.810484051704 0.445699781179 -210 1.0 -1.31993571628e-08 -15 1.0 0.0 -211 1.0 0.499999970198 -SURF 0x10 -mat 1 -refs 4 -212 0.5 0.5 -760 0.810484051704 0.445699781179 -211 1.0 0.499999970198 -14 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -207 1.0 0.5 -13 1.0 1.0 -208 1.0 1.0 -761 0.600902438164 0.514776587486 -SURF 0x10 -mat 1 -refs 4 -11 1.0 0.0 -207 1.0 0.5 -761 0.600902438164 0.514776587486 -205 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -761 0.600902438164 0.514776587486 -208 1.0 1.0 -12 1.0 1.0 -209 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -205 0.5 0.0 -761 0.600902438164 0.514776587486 -209 0.5 0.5 -10 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -204 1.0 0.499999940395 -11 1.0 1.0 -205 1.0 1.0 -762 0.57170265913 0.503473222256 -SURF 0x10 -mat 1 -refs 4 -8 1.0 0.0 -204 1.0 0.499999940395 -762 0.57170265913 0.503473222256 -202 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -762 0.57170265913 0.503473222256 -205 1.0 1.0 -10 1.0 1.0 -206 0.499999940395 0.499999940395 -SURF 0x10 -mat 1 -refs 4 -202 0.5 0.0 -762 0.57170265913 0.503473222256 -206 0.499999940395 0.499999940395 -9 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -201 1.0 0.5 -8 1.0 1.0 -202 1.0 1.0 -763 0.549147069454 0.491829246283 -SURF 0x10 -mat 1 -refs 4 -6 1.0 0.0 -201 1.0 0.5 -763 0.549147069454 0.491829246283 -199 0.5 0.0 -SURF 0x10 -mat 1 -refs 4 -763 0.549147069454 0.491829246283 -202 1.0 1.0 -9 1.0 1.0 -203 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -199 0.5 0.0 -763 0.549147069454 0.491829246283 -203 0.5 0.5 -7 0.0 0.0 -SURF 0x10 -mat 1 -refs 4 -196 0.5 0.0 -4 1.0 0.0 -198 1.0 -1.93571345619e-08 -764 0.972604393959 0.503366351128 -SURF 0x10 -mat 1 -refs 4 -5 0.0 0.0 -196 0.5 0.0 -764 0.972604393959 0.503366351128 -200 0.5 0.5 -SURF 0x10 -mat 1 -refs 4 -764 0.972604393959 0.503366351128 -198 1.0 -1.93571345619e-08 -6 1.0 0.0 -199 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -200 0.5 0.5 -764 0.972604393959 0.503366351128 -199 1.0 0.5 -7 1.0 1.0 -SURF 0x10 -mat 1 -refs 4 -193 0.5 0.0 -2 1.0 0.0 -195 1.0 -1.13672333768e-08 -765 0.994680583477 0.493701398373 -SURF 0x10 -mat 1 -refs 4 -3 0.0 0.0 -193 0.5 0.0 -765 0.994680583477 0.493701398373 -197 0.5 0.500000059605 -SURF 0x10 -mat 1 -refs 4 -765 0.994680583477 0.493701398373 -195 1.0 -1.13672333768e-08 -4 1.0 0.0 -196 1.0 0.5 -SURF 0x10 -mat 1 -refs 4 -197 0.5 0.500000059605 -765 0.994680583477 0.493701398373 -196 1.0 0.5 -5 1.0 1.0 -kids 0 -OBJECT poly -name "Rudder" -data 9 -Plane.008 -crease 30.000000 -numvert 78 -0.735397 0.007406 0.00092 -0.735397 0.007406 -0.00092 -0.731049 0.004768 0.002848 -0.731049 0.004768 -0.002848 -0.716319 8.5e-05 0.00305 -0.716319 8.5e-05 -0.00305 -0.715408 0.083297 0.002528 -0.715408 0.083297 -0.002528 -0.730936 0.084839 0.002326 -0.730936 0.084839 -0.002326 -0.736114 0.083693 0.000666 -0.736114 0.083693 -0.000666 -0.737024 0.08371 4.3e-05 -0.737024 0.08371 -4.3e-05 -0.730792 0.08709 0.000119 -0.730792 0.08709 -0.000119 -0.715405 0.083277 0.000127 -0.715405 0.083277 -0.000127 -0.736994 0.009511 5.6e-05 -0.736994 0.009511 -5.6e-05 -0.716311 8.6e-05 0.000152 -0.716311 8.6e-05 -0.000152 -0.731073 0.002261 0.000141 -0.731073 0.002261 -0.000141 -0.733397 0.005613 0.001861 -0.733397 0.005613 -0.001861 -0.723543 0.001877 0.003002 -0.723543 0.001877 -0.003002 -0.715695 0.041657 0.002821 -0.715695 0.041657 -0.002821 -0.723002 0.084547 0.002467 -0.723002 0.084547 -0.002467 -0.730997 0.04481 0.002672 -0.730997 0.04481 -0.002672 -0.733809 0.084699 0.001485 -0.733809 0.084699 -0.001485 -0.735848 0.046018 0.000799 -0.735848 0.046018 -0.000799 -0.737263 0.046696 5e-05 -0.737263 0.046696 -5e-05 -0.72295 0.08708 0.000123 -0.72295 0.08708 -0.000123 -0.730916 0.087296 0.001201 -0.730916 0.087296 -0.001201 -0.715223 0.084233 0.001326 -0.715223 0.084233 -0.001326 -0.736631 0.084547 0.000343 -0.736631 0.084547 -0.000343 -0.736201 0.007537 0.000443 -0.736201 0.007537 -0.000443 -0.71519 0.041553 0.00014 -0.71519 0.041553 -0.00014 -0.716163 -0.000927 0.001605 -0.716163 -0.000927 -0.001605 -0.72347 -0.000863 0.000148 -0.72347 -0.000863 -0.000148 -0.731145 0.002206 0.001492 -0.731145 0.002206 -0.001492 -0.734355 0.004352 7.5e-05 -0.734355 0.004352 -7.5e-05 -0.734253 0.087081 8.1e-05 -0.734253 0.087081 -8.1e-05 -0.733486 0.003662 0.000557 -0.733486 0.003662 -0.000557 -0.734038 0.087197 0.000768 -0.734038 0.087197 -0.000768 -0.723515 -0.000871 0.001568 -0.723515 -0.000871 -0.001568 -0.71519 0.041553 0.001468 -0.71519 0.041553 -0.001468 -0.736635 0.046379 0.00039 -0.736635 0.046379 -0.00039 -0.722967 0.08719 0.001273 -0.722967 0.08719 -0.001273 -0.733654 0.045455 0.001744 -0.733654 0.045455 -0.001744 -0.723274 0.043215 0.002822 -0.723274 0.043215 -0.002822 -numsurf 72 -SURF 0x30 -mat 1 -refs 3 -48 0 0 -0 0 0 -62 0 0 -SURF 0x30 -mat 1 -refs 3 -62 0 0 -58 0 0 -48 0 0 -SURF 0x30 -mat 1 -refs 3 -18 0 0 -48 0 0 -58 0 0 -SURF 0x30 -mat 1 -refs 3 -58 0 0 -62 0 0 -22 0 0 -SURF 0x30 -mat 1 -refs 3 -49 0 0 -19 0 0 -59 0 0 -SURF 0x30 -mat 1 -refs 3 -59 0 0 -63 0 0 -49 0 0 -SURF 0x30 -mat 1 -refs 3 -1 0 0 -49 0 0 -63 0 0 -SURF 0x30 -mat 1 -refs 3 -63 0 0 -59 0 0 -23 0 0 -SURF 0x30 -mat 1 -refs 3 -62 0 0 -0 0 0 -24 0 0 -SURF 0x30 -mat 1 -refs 3 -24 0 0 -56 0 0 -62 0 0 -SURF 0x30 -mat 1 -refs 3 -22 0 0 -62 0 0 -56 0 0 -SURF 0x30 -mat 1 -refs 3 -56 0 0 -24 0 0 -2 0 0 -SURF 0x30 -mat 1 -refs 3 -63 0 0 -23 0 0 -57 0 0 -SURF 0x30 -mat 1 -refs 3 -57 0 0 -25 0 0 -63 0 0 -SURF 0x30 -mat 1 -refs 3 -1 0 0 -63 0 0 -25 0 0 -SURF 0x30 -mat 1 -refs 3 -25 0 0 -57 0 0 -3 0 0 -SURF 0x30 -mat 1 -refs 4 -34 0 0 -10 0 0 -46 0 0 -64 0 0 -SURF 0x30 -mat 1 -refs 4 -8 0 0 -34 0 0 -64 0 0 -42 0 0 -SURF 0x30 -mat 1 -refs 4 -64 0 0 -46 0 0 -12 0 0 -60 0 0 -SURF 0x30 -mat 1 -refs 4 -42 0 0 -64 0 0 -60 0 0 -14 0 0 -SURF 0x30 -mat 1 -refs 4 -43 0 0 -15 0 0 -61 0 0 -65 0 0 -SURF 0x30 -mat 1 -refs 4 -9 0 0 -43 0 0 -65 0 0 -35 0 0 -SURF 0x30 -mat 1 -refs 4 -65 0 0 -61 0 0 -13 0 0 -47 0 0 -SURF 0x30 -mat 1 -refs 4 -35 0 0 -65 0 0 -47 0 0 -11 0 0 -SURF 0x30 -mat 1 -refs 4 -26 0 0 -4 0 0 -52 0 0 -66 0 0 -SURF 0x30 -mat 1 -refs 4 -2 0 0 -26 0 0 -66 0 0 -56 0 0 -SURF 0x30 -mat 1 -refs 4 -66 0 0 -52 0 0 -20 0 0 -54 0 0 -SURF 0x30 -mat 1 -refs 4 -56 0 0 -66 0 0 -54 0 0 -22 0 0 -SURF 0x30 -mat 1 -refs 4 -57 0 0 -23 0 0 -55 0 0 -67 0 0 -SURF 0x30 -mat 1 -refs 4 -3 0 0 -57 0 0 -67 0 0 -27 0 0 -SURF 0x30 -mat 1 -refs 4 -67 0 0 -55 0 0 -21 0 0 -53 0 0 -SURF 0x30 -mat 1 -refs 4 -27 0 0 -67 0 0 -53 0 0 -5 0 0 -SURF 0x30 -mat 1 -refs 4 -28 0 0 -6 0 0 -44 0 0 -68 0 0 -SURF 0x30 -mat 1 -refs 4 -4 0 0 -28 0 0 -68 0 0 -52 0 0 -SURF 0x30 -mat 1 -refs 4 -68 0 0 -44 0 0 -16 0 0 -50 0 0 -SURF 0x30 -mat 1 -refs 4 -52 0 0 -68 0 0 -50 0 0 -20 0 0 -SURF 0x30 -mat 1 -refs 4 -53 0 0 -21 0 0 -51 0 0 -69 0 0 -SURF 0x30 -mat 1 -refs 4 -5 0 0 -53 0 0 -69 0 0 -29 0 0 -SURF 0x30 -mat 1 -refs 4 -69 0 0 -51 0 0 -17 0 0 -45 0 0 -SURF 0x30 -mat 1 -refs 4 -29 0 0 -69 0 0 -45 0 0 -7 0 0 -SURF 0x30 -mat 1 -refs 4 -48 0 0 -18 0 0 -38 0 0 -70 0 0 -SURF 0x30 -mat 1 -refs 4 -0 0 0 -48 0 0 -70 0 0 -36 0 0 -SURF 0x30 -mat 1 -refs 4 -70 0 0 -38 0 0 -12 0 0 -46 0 0 -SURF 0x30 -mat 1 -refs 4 -36 0 0 -70 0 0 -46 0 0 -10 0 0 -SURF 0x30 -mat 1 -refs 4 -37 0 0 -11 0 0 -47 0 0 -71 0 0 -SURF 0x30 -mat 1 -refs 4 -1 0 0 -37 0 0 -71 0 0 -49 0 0 -SURF 0x30 -mat 1 -refs 4 -71 0 0 -47 0 0 -13 0 0 -39 0 0 -SURF 0x30 -mat 1 -refs 4 -49 0 0 -71 0 0 -39 0 0 -19 0 0 -SURF 0x30 -mat 1 -refs 4 -44 0 0 -6 0 0 -30 0 0 -72 0 0 -SURF 0x30 -mat 1 -refs 4 -16 0 0 -44 0 0 -72 0 0 -40 0 0 -SURF 0x30 -mat 1 -refs 4 -72 0 0 -30 0 0 -8 0 0 -42 0 0 -SURF 0x30 -mat 1 -refs 4 -40 0 0 -72 0 0 -42 0 0 -14 0 0 -SURF 0x30 -mat 1 -refs 4 -41 0 0 -15 0 0 -43 0 0 -73 0 0 -SURF 0x30 -mat 1 -refs 4 -17 0 0 -41 0 0 -73 0 0 -45 0 0 -SURF 0x30 -mat 1 -refs 4 -73 0 0 -43 0 0 -9 0 0 -31 0 0 -SURF 0x30 -mat 1 -refs 4 -45 0 0 -73 0 0 -31 0 0 -7 0 0 -SURF 0x30 -mat 1 -refs 4 -24 0 0 -0 0 0 -36 0 0 -74 0 0 -SURF 0x30 -mat 1 -refs 4 -2 0 0 -24 0 0 -74 0 0 -32 0 0 -SURF 0x30 -mat 1 -refs 4 -74 0 0 -36 0 0 -10 0 0 -34 0 0 -SURF 0x30 -mat 1 -refs 4 -32 0 0 -74 0 0 -34 0 0 -8 0 0 -SURF 0x30 -mat 1 -refs 4 -33 0 0 -9 0 0 -35 0 0 -75 0 0 -SURF 0x30 -mat 1 -refs 4 -3 0 0 -33 0 0 -75 0 0 -25 0 0 -SURF 0x30 -mat 1 -refs 4 -75 0 0 -35 0 0 -11 0 0 -37 0 0 -SURF 0x30 -mat 1 -refs 4 -25 0 0 -75 0 0 -37 0 0 -1 0 0 -SURF 0x30 -mat 1 -refs 4 -26 0 0 -2 0 0 -32 0 0 -76 0 0 -SURF 0x30 -mat 1 -refs 4 -4 0 0 -26 0 0 -76 0 0 -28 0 0 -SURF 0x30 -mat 1 -refs 4 -76 0 0 -32 0 0 -8 0 0 -30 0 0 -SURF 0x30 -mat 1 -refs 4 -28 0 0 -76 0 0 -30 0 0 -6 0 0 -SURF 0x30 -mat 1 -refs 4 -29 0 0 -7 0 0 -31 0 0 -77 0 0 -SURF 0x30 -mat 1 -refs 4 -5 0 0 -29 0 0 -77 0 0 -27 0 0 -SURF 0x30 -mat 1 -refs 4 -77 0 0 -31 0 0 -9 0 0 -33 0 0 -SURF 0x30 -mat 1 -refs 4 -27 0 0 -77 0 0 -33 0 0 -3 0 0 -kids 0 -OBJECT poly -name "VerticalTail" -data 5 -Plane -crease 30.000000 -numvert 192 -0.73497 0.140791 7.8e-05 -0.73497 0.140791 -7.9e-05 -0.732407 0.144935 3.5e-05 -0.732407 0.144935 -3.5e-05 -0.718353 0.142559 7.8e-05 -0.718353 0.142559 -7.9e-05 -0.719494 0.137328 0.001044 -0.719494 0.137328 -0.001044 -0.697826 0.129457 0.001389 -0.697826 0.129457 -0.001389 -0.696055 0.131457 9.2e-05 -0.696055 0.131457 -9.2e-05 -0.675431 0.113838 0.000118 -0.675431 0.113838 -0.000119 -0.677612 0.112736 0.002057 -0.677612 0.112736 -0.002057 -0.735356 0.089333 0.00023 -0.735356 0.089333 -0.00023 -0.728758 0.090586 0.001479 -0.728758 0.090586 -0.001479 -0.711365 0.088064 0.002126 -0.711365 0.088064 -0.002126 -0.68804 0.087273 0.004338 -0.68804 0.087273 -0.004338 -0.660152 0.087273 0.002601 -0.660152 0.087273 -0.002601 -0.656157 0.086573 0.000141 -0.656157 0.086573 -0.000141 -0.603375 0.001754 0.000209 -0.603375 0.001754 -0.000209 -0.610464 0.001112 0.004043 -0.610464 0.001112 -0.004043 -0.68407 0.001048 0.004212 -0.68407 0.001048 -0.004212 -0.710794 -0.000952 0.003335 -0.710794 -0.000952 -0.003335 -0.692327 -0.009721 0.003658 -0.692327 -0.009721 -0.003658 -0.669639 -0.009715 0.004449 -0.669639 -0.009715 -0.004449 -0.587756 -0.009715 0.004332 -0.587756 -0.009715 -0.004332 -0.580404 -0.009636 0.000226 -0.580404 -0.009636 -0.000226 -0.711589 -0.000152 0.000177 -0.711589 -0.000152 -0.000177 -0.712221 0.085452 0.000121 -0.712221 0.085452 -0.000121 -0.728584 0.089331 0.0001 -0.728584 0.089331 -0.0001 -0.735632 0.091573 0.0001 -0.735632 0.091573 -0.0001 -0.692701 -0.009723 0.000191 -0.692701 -0.009723 -0.000191 -0.668371 -0.009981 0.000226 -0.668371 -0.009981 -0.000226 -0.587602 -0.009981 0.000226 -0.587602 -0.009981 -0.000226 -0.725978 0.144027 5.7e-05 -0.725978 0.144027 -5.7e-05 -0.707333 0.137331 8.5e-05 -0.707333 0.137331 -8.5e-05 -0.708719 0.133596 0.001223 -0.708719 0.133596 -0.001223 -0.687635 0.121355 0.001719 -0.687635 0.121355 -0.001719 -0.685635 0.122928 0.000105 -0.685635 0.122928 -0.000105 -0.666527 0.101736 0.00013 -0.666527 0.101736 -0.00013 -0.669786 0.100923 0.00237 -0.669786 0.100923 -0.00237 -0.720091 0.090774 0.001779 -0.720091 0.090774 -0.001779 -0.711284 0.042842 0.002746 -0.711284 0.042842 -0.002746 -0.699816 0.087508 0.003305 -0.699816 0.087508 -0.003305 -0.686466 0.043914 0.004307 -0.686466 0.043914 -0.004308 -0.674001 0.088297 0.003515 -0.674001 0.088297 -0.003515 -0.635401 0.043945 0.003324 -0.635401 0.043945 -0.003324 -0.629874 0.043818 0.000175 -0.629874 0.043818 -0.000175 -0.590618 -0.005838 0.000218 -0.590618 -0.005838 -0.000218 -0.646944 0.00112 0.004205 -0.646944 0.00112 -0.004205 -0.598282 -0.00572 0.004285 -0.598282 -0.00572 -0.004285 -0.698661 4.9e-05 0.003827 -0.698661 4.9e-05 -0.003827 -0.676817 -0.005752 0.004397 -0.676817 -0.005752 -0.004397 -0.70157 -0.006824 0.003534 -0.70157 -0.006824 -0.003534 -0.682342 -0.00975 0.004071 -0.682342 -0.00975 -0.004071 -0.628453 -0.009715 0.004475 -0.628453 -0.009715 -0.004475 -0.718811 0.140787 0.000548 -0.718811 0.140787 -0.000548 -0.696695 0.131144 0.000722 -0.696695 0.131144 -0.000722 -0.676316 0.113708 0.001038 -0.676316 0.113708 -0.001038 -0.657899 0.087267 0.001327 -0.657899 0.087267 -0.001327 -0.605486 0.001 0.002104 -0.605486 0.001 -0.002104 -0.582454 -0.009771 0.002213 -0.582454 -0.009771 -0.002213 -0.732663 0.08934 0.000815 -0.732663 0.08934 -0.000815 -0.732411 0.089332 0.000132 -0.732411 0.089332 -0.000132 -0.711948 0.042779 0.000149 -0.711948 0.042779 -0.000149 -0.72023 0.089331 0.000111 -0.72023 0.089331 -0.000111 -0.711709 -0.00104 0.001726 -0.711709 -0.00104 -0.001726 -0.712219 0.086431 0.001087 -0.712219 0.086431 -0.001087 -0.728969 0.08934 0.000783 -0.728969 0.08934 -0.000783 -0.732353 0.090631 0.00077 -0.732353 0.090631 -0.00077 -0.702619 -0.006877 0.000184 -0.702619 -0.006877 -0.000184 -0.692531 -0.009787 0.001922 -0.692531 -0.009787 -0.001922 -0.681937 -0.009981 0.000209 -0.681937 -0.009981 -0.000209 -0.669111 -0.009981 0.00232 -0.669111 -0.009981 -0.00232 -0.627642 -0.009981 0.000226 -0.627642 -0.009981 -0.000226 -0.586255 -0.009981 0.002219 -0.586255 -0.009981 -0.002219 -0.581779 -0.009981 0.000322 -0.581779 -0.009981 -0.000322 -0.733802 0.144027 5.7e-05 -0.733802 0.144027 -5.7e-05 -0.735505 0.116139 8.9e-05 -0.735505 0.116139 -8.9e-05 -0.727672 0.139473 0.000551 -0.727672 0.139473 -0.000551 -0.68234 0.101134 0.00323 -0.68234 0.101134 -0.00323 -0.704555 0.110044 0.001792 -0.704555 0.110044 -0.001792 -0.723987 0.114045 0.001312 -0.723987 0.114045 -0.001312 -0.714426 0.112147 0.001548 -0.714426 0.112147 -0.001548 -0.693769 0.105859 0.002531 -0.693769 0.105859 -0.002531 -0.730114 0.115164 0.000687 -0.730114 0.115164 -0.000687 -0.627753 -0.009981 0.002333 -0.627753 -0.009981 -0.002334 -0.681869 -0.009981 0.002124 -0.681869 -0.009981 -0.002124 -0.702466 -0.006868 0.001828 -0.702466 -0.006868 -0.001828 -0.720348 0.08934 0.000945 -0.720348 0.08934 -0.000945 -0.712001 0.042793 0.001408 -0.712001 0.042793 -0.001408 -0.593128 -0.00578 0.002228 -0.593128 -0.00578 -0.002228 -0.63178 0.043881 0.001716 -0.63178 0.043881 -0.001717 -0.667642 0.101635 0.001175 -0.667642 0.101635 -0.001175 -0.686424 0.12266 0.000878 -0.686424 0.12266 -0.000878 -0.707831 0.136189 0.000638 -0.707831 0.136189 -0.000638 -0.726737 0.142574 0.000297 -0.726737 0.142574 -0.000297 -0.690482 -0.006287 0.004022 -0.690482 -0.006287 -0.004022 -0.637266 -0.005716 0.004422 -0.637266 -0.005716 -0.004422 -0.660613 0.043949 0.003893 -0.660613 0.043949 -0.003893 -0.699713 0.043378 0.003585 -0.699713 0.043378 -0.003585 -numsurf 172 -SURF 0x30 -mat 1 -refs 3 -128 0 0 -18 0 0 -126 0 0 -SURF 0x30 -mat 1 -refs 3 -126 0 0 -116 0 0 -128 0 0 -SURF 0x30 -mat 1 -refs 3 -50 0 0 -128 0 0 -116 0 0 -SURF 0x30 -mat 1 -refs 3 -116 0 0 -126 0 0 -48 0 0 -SURF 0x30 -mat 1 -refs 3 -117 0 0 -49 0 0 -127 0 0 -SURF 0x30 -mat 1 -refs 3 -127 0 0 -129 0 0 -117 0 0 -SURF 0x30 -mat 1 -refs 3 -51 0 0 -117 0 0 -129 0 0 -SURF 0x30 -mat 1 -refs 3 -129 0 0 -127 0 0 -19 0 0 -SURF 0x30 -mat 1 -refs 3 -140 0 0 -40 0 0 -112 0 0 -SURF 0x30 -mat 1 -refs 3 -112 0 0 -142 0 0 -140 0 0 -SURF 0x30 -mat 1 -refs 3 -56 0 0 -140 0 0 -142 0 0 -SURF 0x30 -mat 1 -refs 3 -142 0 0 -112 0 0 -42 0 0 -SURF 0x30 -mat 1 -refs 3 -143 0 0 -43 0 0 -113 0 0 -SURF 0x30 -mat 1 -refs 3 -113 0 0 -141 0 0 -143 0 0 -SURF 0x30 -mat 1 -refs 3 -57 0 0 -143 0 0 -141 0 0 -SURF 0x30 -mat 1 -refs 3 -141 0 0 -113 0 0 -41 0 0 -SURF 0x30 -mat 1 -refs 3 -80 0 0 -22 0 0 -150 0 0 -SURF 0x30 -mat 1 -refs 3 -150 0 0 -70 0 0 -80 0 0 -SURF 0x30 -mat 1 -refs 3 -24 0 0 -80 0 0 -70 0 0 -SURF 0x30 -mat 1 -refs 3 -70 0 0 -150 0 0 -14 0 0 -SURF 0x30 -mat 1 -refs 3 -71 0 0 -15 0 0 -151 0 0 -SURF 0x30 -mat 1 -refs 3 -151 0 0 -81 0 0 -71 0 0 -SURF 0x30 -mat 1 -refs 3 -25 0 0 -71 0 0 -81 0 0 -SURF 0x30 -mat 1 -refs 3 -81 0 0 -151 0 0 -23 0 0 -SURF 0x30 -mat 1 -refs 4 -152 0 0 -20 0 0 -72 0 0 -156 0 0 -SURF 0x30 -mat 1 -refs 4 -8 0 0 -152 0 0 -156 0 0 -62 0 0 -SURF 0x30 -mat 1 -refs 4 -156 0 0 -72 0 0 -18 0 0 -154 0 0 -SURF 0x30 -mat 1 -refs 4 -62 0 0 -156 0 0 -154 0 0 -6 0 0 -SURF 0x30 -mat 1 -refs 4 -63 0 0 -7 0 0 -155 0 0 -157 0 0 -SURF 0x30 -mat 1 -refs 4 -9 0 0 -63 0 0 -157 0 0 -153 0 0 -SURF 0x30 -mat 1 -refs 4 -157 0 0 -155 0 0 -19 0 0 -73 0 0 -SURF 0x30 -mat 1 -refs 4 -153 0 0 -157 0 0 -73 0 0 -21 0 0 -SURF 0x30 -mat 1 -refs 4 -150 0 0 -22 0 0 -76 0 0 -158 0 0 -SURF 0x30 -mat 1 -refs 4 -14 0 0 -150 0 0 -158 0 0 -64 0 0 -SURF 0x30 -mat 1 -refs 4 -158 0 0 -76 0 0 -20 0 0 -152 0 0 -SURF 0x30 -mat 1 -refs 4 -64 0 0 -158 0 0 -152 0 0 -8 0 0 -SURF 0x30 -mat 1 -refs 4 -65 0 0 -9 0 0 -153 0 0 -159 0 0 -SURF 0x30 -mat 1 -refs 4 -15 0 0 -65 0 0 -159 0 0 -151 0 0 -SURF 0x30 -mat 1 -refs 4 -159 0 0 -153 0 0 -21 0 0 -77 0 0 -SURF 0x30 -mat 1 -refs 4 -151 0 0 -159 0 0 -77 0 0 -23 0 0 -SURF 0x30 -mat 1 -refs 4 -146 0 0 -0 0 0 -148 0 0 -160 0 0 -SURF 0x30 -mat 1 -refs 4 -50 0 0 -146 0 0 -160 0 0 -128 0 0 -SURF 0x30 -mat 1 -refs 4 -160 0 0 -148 0 0 -6 0 0 -154 0 0 -SURF 0x30 -mat 1 -refs 4 -128 0 0 -160 0 0 -154 0 0 -18 0 0 -SURF 0x30 -mat 1 -refs 4 -129 0 0 -19 0 0 -155 0 0 -161 0 0 -SURF 0x30 -mat 1 -refs 4 -51 0 0 -129 0 0 -161 0 0 -147 0 0 -SURF 0x30 -mat 1 -refs 4 -161 0 0 -155 0 0 -7 0 0 -149 0 0 -SURF 0x30 -mat 1 -refs 4 -147 0 0 -161 0 0 -149 0 0 -1 0 0 -SURF 0x30 -mat 1 -refs 4 -100 0 0 -40 0 0 -140 0 0 -162 0 0 -SURF 0x30 -mat 1 -refs 4 -38 0 0 -100 0 0 -162 0 0 -136 0 0 -SURF 0x30 -mat 1 -refs 4 -162 0 0 -140 0 0 -56 0 0 -138 0 0 -SURF 0x30 -mat 1 -refs 4 -136 0 0 -162 0 0 -138 0 0 -54 0 0 -SURF 0x30 -mat 1 -refs 4 -137 0 0 -55 0 0 -139 0 0 -163 0 0 -SURF 0x30 -mat 1 -refs 4 -39 0 0 -137 0 0 -163 0 0 -101 0 0 -SURF 0x30 -mat 1 -refs 4 -163 0 0 -139 0 0 -57 0 0 -141 0 0 -SURF 0x30 -mat 1 -refs 4 -101 0 0 -163 0 0 -141 0 0 -41 0 0 -SURF 0x30 -mat 1 -refs 4 -132 0 0 -36 0 0 -98 0 0 -164 0 0 -SURF 0x30 -mat 1 -refs 4 -52 0 0 -132 0 0 -164 0 0 -134 0 0 -SURF 0x30 -mat 1 -refs 4 -164 0 0 -98 0 0 -38 0 0 -136 0 0 -SURF 0x30 -mat 1 -refs 4 -134 0 0 -164 0 0 -136 0 0 -54 0 0 -SURF 0x30 -mat 1 -refs 4 -135 0 0 -55 0 0 -137 0 0 -165 0 0 -SURF 0x30 -mat 1 -refs 4 -53 0 0 -135 0 0 -165 0 0 -133 0 0 -SURF 0x30 -mat 1 -refs 4 -165 0 0 -137 0 0 -39 0 0 -99 0 0 -SURF 0x30 -mat 1 -refs 4 -133 0 0 -165 0 0 -99 0 0 -37 0 0 -SURF 0x30 -mat 1 -refs 4 -122 0 0 -34 0 0 -96 0 0 -166 0 0 -SURF 0x30 -mat 1 -refs 4 -44 0 0 -122 0 0 -166 0 0 -130 0 0 -SURF 0x30 -mat 1 -refs 4 -166 0 0 -96 0 0 -36 0 0 -132 0 0 -SURF 0x30 -mat 1 -refs 4 -130 0 0 -166 0 0 -132 0 0 -52 0 0 -SURF 0x30 -mat 1 -refs 4 -131 0 0 -53 0 0 -133 0 0 -167 0 0 -SURF 0x30 -mat 1 -refs 4 -45 0 0 -131 0 0 -167 0 0 -123 0 0 -SURF 0x30 -mat 1 -refs 4 -167 0 0 -133 0 0 -37 0 0 -97 0 0 -SURF 0x30 -mat 1 -refs 4 -123 0 0 -167 0 0 -97 0 0 -35 0 0 -SURF 0x30 -mat 1 -refs 4 -72 0 0 -20 0 0 -124 0 0 -168 0 0 -SURF 0x30 -mat 1 -refs 4 -18 0 0 -72 0 0 -168 0 0 -126 0 0 -SURF 0x30 -mat 1 -refs 4 -168 0 0 -124 0 0 -46 0 0 -120 0 0 -SURF 0x30 -mat 1 -refs 4 -126 0 0 -168 0 0 -120 0 0 -48 0 0 -SURF 0x30 -mat 1 -refs 4 -127 0 0 -49 0 0 -121 0 0 -169 0 0 -SURF 0x30 -mat 1 -refs 4 -19 0 0 -127 0 0 -169 0 0 -73 0 0 -SURF 0x30 -mat 1 -refs 4 -169 0 0 -121 0 0 -47 0 0 -125 0 0 -SURF 0x30 -mat 1 -refs 4 -73 0 0 -169 0 0 -125 0 0 -21 0 0 -SURF 0x30 -mat 1 -refs 4 -74 0 0 -34 0 0 -122 0 0 -170 0 0 -SURF 0x30 -mat 1 -refs 4 -20 0 0 -74 0 0 -170 0 0 -124 0 0 -SURF 0x30 -mat 1 -refs 4 -170 0 0 -122 0 0 -44 0 0 -118 0 0 -SURF 0x30 -mat 1 -refs 4 -124 0 0 -170 0 0 -118 0 0 -46 0 0 -SURF 0x30 -mat 1 -refs 4 -125 0 0 -47 0 0 -119 0 0 -171 0 0 -SURF 0x30 -mat 1 -refs 4 -21 0 0 -125 0 0 -171 0 0 -75 0 0 -SURF 0x30 -mat 1 -refs 4 -171 0 0 -119 0 0 -45 0 0 -123 0 0 -SURF 0x30 -mat 1 -refs 4 -75 0 0 -171 0 0 -123 0 0 -35 0 0 -SURF 0x30 -mat 1 -refs 4 -110 0 0 -28 0 0 -86 0 0 -172 0 0 -SURF 0x30 -mat 1 -refs 4 -30 0 0 -110 0 0 -172 0 0 -90 0 0 -SURF 0x30 -mat 1 -refs 4 -172 0 0 -86 0 0 -42 0 0 -112 0 0 -SURF 0x30 -mat 1 -refs 4 -90 0 0 -172 0 0 -112 0 0 -40 0 0 -SURF 0x30 -mat 1 -refs 4 -91 0 0 -41 0 0 -113 0 0 -173 0 0 -SURF 0x30 -mat 1 -refs 4 -31 0 0 -91 0 0 -173 0 0 -111 0 0 -SURF 0x30 -mat 1 -refs 4 -173 0 0 -113 0 0 -43 0 0 -87 0 0 -SURF 0x30 -mat 1 -refs 4 -111 0 0 -173 0 0 -87 0 0 -29 0 0 -SURF 0x30 -mat 1 -refs 4 -108 0 0 -26 0 0 -84 0 0 -174 0 0 -SURF 0x30 -mat 1 -refs 4 -24 0 0 -108 0 0 -174 0 0 -82 0 0 -SURF 0x30 -mat 1 -refs 4 -174 0 0 -84 0 0 -28 0 0 -110 0 0 -SURF 0x30 -mat 1 -refs 4 -82 0 0 -174 0 0 -110 0 0 -30 0 0 -SURF 0x30 -mat 1 -refs 4 -83 0 0 -31 0 0 -111 0 0 -175 0 0 -SURF 0x30 -mat 1 -refs 4 -25 0 0 -83 0 0 -175 0 0 -109 0 0 -SURF 0x30 -mat 1 -refs 4 -175 0 0 -111 0 0 -29 0 0 -85 0 0 -SURF 0x30 -mat 1 -refs 4 -109 0 0 -175 0 0 -85 0 0 -27 0 0 -SURF 0x30 -mat 1 -refs 4 -106 0 0 -12 0 0 -68 0 0 -176 0 0 -SURF 0x30 -mat 1 -refs 4 -14 0 0 -106 0 0 -176 0 0 -70 0 0 -SURF 0x30 -mat 1 -refs 4 -176 0 0 -68 0 0 -26 0 0 -108 0 0 -SURF 0x30 -mat 1 -refs 4 -70 0 0 -176 0 0 -108 0 0 -24 0 0 -SURF 0x30 -mat 1 -refs 4 -71 0 0 -25 0 0 -109 0 0 -177 0 0 -SURF 0x30 -mat 1 -refs 4 -15 0 0 -71 0 0 -177 0 0 -107 0 0 -SURF 0x30 -mat 1 -refs 4 -177 0 0 -109 0 0 -27 0 0 -69 0 0 -SURF 0x30 -mat 1 -refs 4 -107 0 0 -177 0 0 -69 0 0 -13 0 0 -SURF 0x30 -mat 1 -refs 4 -104 0 0 -10 0 0 -66 0 0 -178 0 0 -SURF 0x30 -mat 1 -refs 4 -8 0 0 -104 0 0 -178 0 0 -64 0 0 -SURF 0x30 -mat 1 -refs 4 -178 0 0 -66 0 0 -12 0 0 -106 0 0 -SURF 0x30 -mat 1 -refs 4 -64 0 0 -178 0 0 -106 0 0 -14 0 0 -SURF 0x30 -mat 1 -refs 4 -65 0 0 -15 0 0 -107 0 0 -179 0 0 -SURF 0x30 -mat 1 -refs 4 -9 0 0 -65 0 0 -179 0 0 -105 0 0 -SURF 0x30 -mat 1 -refs 4 -179 0 0 -107 0 0 -13 0 0 -67 0 0 -SURF 0x30 -mat 1 -refs 4 -105 0 0 -179 0 0 -67 0 0 -11 0 0 -SURF 0x30 -mat 1 -refs 4 -102 0 0 -4 0 0 -60 0 0 -180 0 0 -SURF 0x30 -mat 1 -refs 4 -6 0 0 -102 0 0 -180 0 0 -62 0 0 -SURF 0x30 -mat 1 -refs 4 -180 0 0 -60 0 0 -10 0 0 -104 0 0 -SURF 0x30 -mat 1 -refs 4 -62 0 0 -180 0 0 -104 0 0 -8 0 0 -SURF 0x30 -mat 1 -refs 4 -63 0 0 -9 0 0 -105 0 0 -181 0 0 -SURF 0x30 -mat 1 -refs 4 -7 0 0 -63 0 0 -181 0 0 -103 0 0 -SURF 0x30 -mat 1 -refs 4 -181 0 0 -105 0 0 -11 0 0 -61 0 0 -SURF 0x30 -mat 1 -refs 4 -103 0 0 -181 0 0 -61 0 0 -5 0 0 -SURF 0x30 -mat 1 -refs 4 -144 0 0 -2 0 0 -58 0 0 -182 0 0 -SURF 0x30 -mat 1 -refs 4 -0 0 0 -144 0 0 -182 0 0 -148 0 0 -SURF 0x30 -mat 1 -refs 4 -182 0 0 -58 0 0 -4 0 0 -102 0 0 -SURF 0x30 -mat 1 -refs 4 -148 0 0 -182 0 0 -102 0 0 -6 0 0 -SURF 0x30 -mat 1 -refs 4 -149 0 0 -7 0 0 -103 0 0 -183 0 0 -SURF 0x30 -mat 1 -refs 4 -1 0 0 -149 0 0 -183 0 0 -145 0 0 -SURF 0x30 -mat 1 -refs 4 -183 0 0 -103 0 0 -5 0 0 -59 0 0 -SURF 0x30 -mat 1 -refs 4 -145 0 0 -183 0 0 -59 0 0 -3 0 0 -SURF 0x30 -mat 1 -refs 4 -98 0 0 -36 0 0 -96 0 0 -184 0 0 -SURF 0x30 -mat 1 -refs 4 -38 0 0 -98 0 0 -184 0 0 -94 0 0 -SURF 0x30 -mat 1 -refs 4 -184 0 0 -96 0 0 -34 0 0 -92 0 0 -SURF 0x30 -mat 1 -refs 4 -94 0 0 -184 0 0 -92 0 0 -32 0 0 -SURF 0x30 -mat 1 -refs 4 -95 0 0 -33 0 0 -93 0 0 -185 0 0 -SURF 0x30 -mat 1 -refs 4 -39 0 0 -95 0 0 -185 0 0 -99 0 0 -SURF 0x30 -mat 1 -refs 4 -185 0 0 -93 0 0 -35 0 0 -97 0 0 -SURF 0x30 -mat 1 -refs 4 -99 0 0 -185 0 0 -97 0 0 -37 0 0 -SURF 0x30 -mat 1 -refs 4 -100 0 0 -38 0 0 -94 0 0 -186 0 0 -SURF 0x30 -mat 1 -refs 4 -40 0 0 -100 0 0 -186 0 0 -90 0 0 -SURF 0x30 -mat 1 -refs 4 -186 0 0 -94 0 0 -32 0 0 -88 0 0 -SURF 0x30 -mat 1 -refs 4 -90 0 0 -186 0 0 -88 0 0 -30 0 0 -SURF 0x30 -mat 1 -refs 4 -91 0 0 -31 0 0 -89 0 0 -187 0 0 -SURF 0x30 -mat 1 -refs 4 -41 0 0 -91 0 0 -187 0 0 -101 0 0 -SURF 0x30 -mat 1 -refs 4 -187 0 0 -89 0 0 -33 0 0 -95 0 0 -SURF 0x30 -mat 1 -refs 4 -101 0 0 -187 0 0 -95 0 0 -39 0 0 -SURF 0x30 -mat 1 -refs 4 -88 0 0 -32 0 0 -78 0 0 -188 0 0 -SURF 0x30 -mat 1 -refs 4 -30 0 0 -88 0 0 -188 0 0 -82 0 0 -SURF 0x30 -mat 1 -refs 4 -188 0 0 -78 0 0 -22 0 0 -80 0 0 -SURF 0x30 -mat 1 -refs 4 -82 0 0 -188 0 0 -80 0 0 -24 0 0 -SURF 0x30 -mat 1 -refs 4 -83 0 0 -25 0 0 -81 0 0 -189 0 0 -SURF 0x30 -mat 1 -refs 4 -31 0 0 -83 0 0 -189 0 0 -89 0 0 -SURF 0x30 -mat 1 -refs 4 -189 0 0 -81 0 0 -23 0 0 -79 0 0 -SURF 0x30 -mat 1 -refs 4 -89 0 0 -189 0 0 -79 0 0 -33 0 0 -SURF 0x30 -mat 1 -refs 4 -74 0 0 -20 0 0 -76 0 0 -190 0 0 -SURF 0x30 -mat 1 -refs 4 -34 0 0 -74 0 0 -190 0 0 -92 0 0 -SURF 0x30 -mat 1 -refs 4 -190 0 0 -76 0 0 -22 0 0 -78 0 0 -SURF 0x30 -mat 1 -refs 4 -92 0 0 -190 0 0 -78 0 0 -32 0 0 -SURF 0x30 -mat 1 -refs 4 -93 0 0 -33 0 0 -79 0 0 -191 0 0 -SURF 0x30 -mat 1 -refs 4 -35 0 0 -93 0 0 -191 0 0 -75 0 0 -SURF 0x30 -mat 1 -refs 4 -191 0 0 -79 0 0 -23 0 0 -77 0 0 -SURF 0x30 -mat 1 -refs 4 -75 0 0 -191 0 0 -77 0 0 -21 0 0 -SURF 0x02 -mat 1 -refs 2 -16 0 0 -114 0 0 -SURF 0x02 -mat 1 -refs 2 -18 0 0 -114 0 0 -SURF 0x02 -mat 1 -refs 2 -17 0 0 -115 0 0 -SURF 0x02 -mat 1 -refs 2 -19 0 0 -115 0 0 -kids 0 -OBJECT poly -name "Fueselage.001" -data 13 -Fuesalage.002 -crease 30.000000 -numvert 0 -numsurf 0 -kids 0 -OBJECT poly -name "Propeller.Spinning" -data 8 -Cylinder -crease 30.000000 -numvert 66 -0.296725 0.030271 -0.05171 -0.298457 0.021345 -0.040631 -0.299743 0.014713 -0.027991 -0.300535 0.010628 -0.014276 -0.300803 0.009249 -1.3e-05 -0.300535 0.010628 0.01425 -0.299743 0.014713 0.027965 -0.298457 0.021345 0.040605 -0.296725 0.030271 0.051684 -0.294616 0.041147 0.060776 -0.292209 0.053556 0.067533 -0.289597 0.06702 0.071693 -0.286881 0.081022 0.073098 -0.284165 0.095025 0.071693 -0.281553 0.108489 0.067533 -0.279146 0.120897 0.060776 -0.277036 0.131774 0.051684 -0.275305 0.1407 0.040605 -0.274018 0.147332 0.027965 -0.273226 0.151416 0.01425 -0.272959 0.152795 -1.3e-05 -0.273226 0.151416 -0.014276 -0.274018 0.147332 -0.027992 -0.275305 0.140699 -0.040631 -0.277036 0.131774 -0.05171 -0.279146 0.120897 -0.060803 -0.281553 0.108489 -0.067559 -0.284165 0.095025 -0.071719 -0.286881 0.081022 -0.073124 -0.289597 0.06702 -0.071719 -0.292209 0.053556 -0.067559 -0.294616 0.041147 -0.060803 -0.297751 0.03047 -0.05171 -0.299482 0.021544 -0.040631 -0.300769 0.014912 -0.027991 -0.301561 0.010827 -0.014276 -0.301829 0.009448 -1.3e-05 -0.301561 0.010827 0.01425 -0.300769 0.014912 0.027965 -0.299482 0.021544 0.040605 -0.297751 0.03047 0.051684 -0.295641 0.041346 0.060776 -0.293234 0.053755 0.067533 -0.290623 0.067219 0.071693 -0.287907 0.081221 0.073098 -0.285191 0.095223 0.071693 -0.282579 0.108688 0.067533 -0.280172 0.121096 0.060776 -0.278062 0.131972 0.051684 -0.276331 0.140898 0.040605 -0.275044 0.147531 0.027965 -0.274252 0.151615 0.01425 -0.273985 0.152994 -1.3e-05 -0.274252 0.151615 -0.014276 -0.275044 0.147531 -0.027991 -0.276331 0.140899 -0.040631 -0.278062 0.131973 -0.05171 -0.280172 0.121097 -0.060802 -0.282579 0.108688 -0.067559 -0.28519 0.095224 -0.071719 -0.287907 0.081222 -0.073124 -0.290623 0.06722 -0.071719 -0.293234 0.053756 -0.067559 -0.295641 0.041347 -0.060803 -0.28692 0.081021 -1.3e-05 -0.287946 0.08122 -1.3e-05 -numsurf 96 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -0 0 0 -1 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -33 0 0 -32 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -1 0 0 -2 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -34 0 0 -33 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -2 0 0 -3 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -35 0 0 -34 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -3 0 0 -4 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -36 0 0 -35 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -4 0 0 -5 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -37 0 0 -36 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -5 0 0 -6 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -38 0 0 -37 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -6 0 0 -7 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -39 0 0 -38 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -7 0 0 -8 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -40 0 0 -39 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -8 0 0 -9 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -41 0 0 -40 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -9 0 0 -10 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -42 0 0 -41 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -10 0 0 -11 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -43 0 0 -42 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -11 0 0 -12 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -44 0 0 -43 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -12 0 0 -13 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -45 0 0 -44 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -13 0 0 -14 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -46 0 0 -45 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -14 0 0 -15 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -47 0 0 -46 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -15 0 0 -16 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -48 0 0 -47 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -16 0 0 -17 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -49 0 0 -48 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -17 0 0 -18 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -50 0 0 -49 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -18 0 0 -19 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -51 0 0 -50 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -19 0 0 -20 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -52 0 0 -51 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -20 0 0 -21 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -53 0 0 -52 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -21 0 0 -22 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -54 0 0 -53 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -22 0 0 -23 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -55 0 0 -54 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -23 0 0 -24 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -56 0 0 -55 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -24 0 0 -25 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -57 0 0 -56 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -25 0 0 -26 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -58 0 0 -57 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -26 0 0 -27 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -59 0 0 -58 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -27 0 0 -28 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -60 0 0 -59 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -28 0 0 -29 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -61 0 0 -60 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -29 0 0 -30 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -62 0 0 -61 0 0 -SURF 0x20 -mat 5 -refs 3 -64 0 0 -30 0 0 -31 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -63 0 0 -62 0 0 -SURF 0x20 -mat 5 -refs 3 -31 0 0 -0 0 0 -64 0 0 -SURF 0x20 -mat 5 -refs 3 -65 0 0 -32 0 0 -63 0 0 -SURF 0x20 -mat 5 -refs 4 -0 0 0 -32 0 0 -33 0 0 -1 0 0 -SURF 0x20 -mat 5 -refs 4 -1 0 0 -33 0 0 -34 0 0 -2 0 0 -SURF 0x20 -mat 5 -refs 4 -2 0 0 -34 0 0 -35 0 0 -3 0 0 -SURF 0x20 -mat 5 -refs 4 -3 0 0 -35 0 0 -36 0 0 -4 0 0 -SURF 0x20 -mat 5 -refs 4 -4 0 0 -36 0 0 -37 0 0 -5 0 0 -SURF 0x20 -mat 5 -refs 4 -5 0 0 -37 0 0 -38 0 0 -6 0 0 -SURF 0x20 -mat 5 -refs 4 -6 0 0 -38 0 0 -39 0 0 -7 0 0 -SURF 0x20 -mat 5 -refs 4 -7 0 0 -39 0 0 -40 0 0 -8 0 0 -SURF 0x20 -mat 5 -refs 4 -8 0 0 -40 0 0 -41 0 0 -9 0 0 -SURF 0x20 -mat 5 -refs 4 -9 0 0 -41 0 0 -42 0 0 -10 0 0 -SURF 0x20 -mat 5 -refs 4 -10 0 0 -42 0 0 -43 0 0 -11 0 0 -SURF 0x20 -mat 5 -refs 4 -11 0 0 -43 0 0 -44 0 0 -12 0 0 -SURF 0x20 -mat 5 -refs 4 -12 0 0 -44 0 0 -45 0 0 -13 0 0 -SURF 0x20 -mat 5 -refs 4 -13 0 0 -45 0 0 -46 0 0 -14 0 0 -SURF 0x20 -mat 5 -refs 4 -14 0 0 -46 0 0 -47 0 0 -15 0 0 -SURF 0x20 -mat 5 -refs 4 -15 0 0 -47 0 0 -48 0 0 -16 0 0 -SURF 0x20 -mat 5 -refs 4 -16 0 0 -48 0 0 -49 0 0 -17 0 0 -SURF 0x20 -mat 5 -refs 4 -17 0 0 -49 0 0 -50 0 0 -18 0 0 -SURF 0x20 -mat 5 -refs 4 -18 0 0 -50 0 0 -51 0 0 -19 0 0 -SURF 0x20 -mat 5 -refs 4 -19 0 0 -51 0 0 -52 0 0 -20 0 0 -SURF 0x20 -mat 5 -refs 4 -20 0 0 -52 0 0 -53 0 0 -21 0 0 -SURF 0x20 -mat 5 -refs 4 -21 0 0 -53 0 0 -54 0 0 -22 0 0 -SURF 0x20 -mat 5 -refs 4 -22 0 0 -54 0 0 -55 0 0 -23 0 0 -SURF 0x20 -mat 5 -refs 4 -23 0 0 -55 0 0 -56 0 0 -24 0 0 -SURF 0x20 -mat 5 -refs 4 -24 0 0 -56 0 0 -57 0 0 -25 0 0 -SURF 0x20 -mat 5 -refs 4 -25 0 0 -57 0 0 -58 0 0 -26 0 0 -SURF 0x20 -mat 5 -refs 4 -26 0 0 -58 0 0 -59 0 0 -27 0 0 -SURF 0x20 -mat 5 -refs 4 -27 0 0 -59 0 0 -60 0 0 -28 0 0 -SURF 0x20 -mat 5 -refs 4 -28 0 0 -60 0 0 -61 0 0 -29 0 0 -SURF 0x20 -mat 5 -refs 4 -29 0 0 -61 0 0 -62 0 0 -30 0 0 -SURF 0x20 -mat 5 -refs 4 -30 0 0 -62 0 0 -63 0 0 -31 0 0 -SURF 0x20 -mat 5 -refs 4 -32 0 0 -0 0 0 -31 0 0 -63 0 0 -kids 0 diff --git a/aircraft/EasyStar/Models/EasyStar.blend b/aircraft/EasyStar/Models/EasyStar.blend deleted file mode 100644 index 2848210bbcf4c45878135d27fbeddca1f8a5961a..0000000000000000000000000000000000000000 Binary files a/aircraft/EasyStar/Models/EasyStar.blend and /dev/null differ diff --git a/aircraft/EasyStar/Models/Makefile.am b/aircraft/EasyStar/Models/Makefile.am deleted file mode 100644 index d445adc50e59e1705d9f1a637cee3378bc31abe7..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/Models/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -aircraft_EasyStar_Modelsdir = ${pkgdatadir}/aircraft/EasyStar/Models -aircraft_EasyStar_Models_DATA = \ - EasyStar.blend \ - EasyStar-model.xml \ - EasyStar.ac -EXTRA_DIST=$(aircraft_EasyStar_Models_data) diff --git a/aircraft/EasyStar/reset00.xml b/aircraft/EasyStar/reset00.xml deleted file mode 100644 index 25261d928f59b0071fe3967b6213d36c77f2f820..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/reset00.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0"?> -<initialize name="reset00"> - <!-- - This file sets up the aircraft to start off - from the runway in preparation for takeoff. - --> - <ubody unit="FT/SEC"> 50.0 </ubody> - <vbody unit="FT/SEC"> 0.0 </vbody> - <wbody unit="FT/SEC"> 0.0 </wbody> - <longitude unit="DEG"> -95.163839 </longitude> - <latitude unit="DEG"> 29.593978 </latitude> - <phi unit="DEG"> 0.0 </phi> - <theta unit="DEG"> 0.0 </theta> - <psi unit="DEG"> 200.0 </psi> - <altitude unit="FT"> 4.6 </altitude> - <elevation unit="FT"> 2000.0 </elevation> -</initialize> diff --git a/aircraft/EasyStar/reset01.xml b/aircraft/EasyStar/reset01.xml deleted file mode 100644 index bae56dfb33ae243250b6619531224d95f6f9ee74..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/reset01.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0"?> -<initialize name="reset00"> - <!-- - --> - <ubody unit="FT/SEC"> 120.0 </ubody> - <vbody unit="FT/SEC"> 0.0 </vbody> - <wbody unit="FT/SEC"> 0.0 </wbody> - <latitude unit="DEG"> 28.0 </latitude> - <longitude unit="DEG"> -90.0 </longitude> - <phi unit="DEG"> 0.0 </phi> - <theta unit="DEG"> 40.0 </theta> - <psi unit="DEG"> 40.0 </psi> - <altitude unit="FT"> 10000.0 </altitude> - <winddir unit="DEG"> 0.0 </winddir> - <vwind unit="FT/SEC"> 0.0 </vwind> -</initialize> - diff --git a/aircraft/EasyStar/scripts/Makefile.am b/aircraft/EasyStar/scripts/Makefile.am deleted file mode 100644 index 11c0b140b3be1266d351bb7cfc71465296843f73..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/scripts/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -aircraft_EasyStar_scriptsdir = ${pkgdatadir}/aircraft/EasyStar/scripts -aircraft_EasyStar_scripts_DATA = \ - trim.xml -EXTRA_DIST=$(aircraft_EasyStar_scripts_data) diff --git a/aircraft/EasyStar/scripts/trim.xml b/aircraft/EasyStar/scripts/trim.xml deleted file mode 100644 index dc29de457f9a16ac2a81d692083309cc75931ce9..0000000000000000000000000000000000000000 --- a/aircraft/EasyStar/scripts/trim.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<?xml-stylesheet type="text/xsl" href="http://jsbsim.sf.net/JSBSimScript.xsl"?> -<runscript xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://jsbsim.sf.net/JSBSimScript.xsd" - name="At-altitude autopilot test setup."> - - <use aircraft="EasyStar" initialize="reset01"/> - <run start="0.0" end="2" dt="0.000001"> - - <event name="Engine start"> - <condition>sim-time-sec ge 0.25</condition> - <set name="fcs/throttle-cmd-norm" value="0.5"/> - <notify> - <property>velocities/vc-kts</property> - <property>position/h-agl-ft</property> - </notify> - </event> - - <event name="Trim"> - <condition>sim-time-sec ge 1</condition> - <set name="simulation/do_simple_trim" value="0"/> - <notify> - <property>velocities/vc-kts</property> - <property>position/h-agl-ft</property> - </notify> - </event> - - </run> -</runscript> diff --git a/aircraft/F4N/reset00.xml b/aircraft/F4N/reset00.xml old mode 100644 new mode 100755 diff --git a/aircraft/J246/J246.xml b/aircraft/J246/J246.xml old mode 100644 new mode 100755 diff --git a/aircraft/J246/LC39.xml b/aircraft/J246/LC39.xml old mode 100644 new mode 100755 diff --git a/aircraft/J246/Systems/J246ControlSystem.xml b/aircraft/J246/Systems/J246ControlSystem.xml old mode 100644 new mode 100755 diff --git a/aircraft/J246/Systems/J246FirstStageEffectors.xml b/aircraft/J246/Systems/J246FirstStageEffectors.xml old mode 100644 new mode 100755 diff --git a/aircraft/J246/Systems/J246GuidanceExecutive.xml b/aircraft/J246/Systems/J246GuidanceExecutive.xml old mode 100644 new mode 100755 diff --git a/aircraft/J246/Systems/J246SecondStageEffectors.xml b/aircraft/J246/Systems/J246SecondStageEffectors.xml old mode 100644 new mode 100755 diff --git a/aircraft/L410/L410.xml b/aircraft/L410/L410.xml old mode 100644 new mode 100755 diff --git a/aircraft/Makefile.am b/aircraft/Makefile.am index cd2839bb5a92729850cd1bf4e023a316540ed591..0ffb334f686d218775cfc6bafc2e80e56e3861af 100644 --- a/aircraft/Makefile.am +++ b/aircraft/Makefile.am @@ -26,7 +26,6 @@ SUBDIRS = \ pogo-jsbsim \ p51d \ paraglider \ - EasyStar \ J246 \ F4N \ c310 \ diff --git a/aircraft/OV10/OV10.xml b/aircraft/OV10/OV10.xml old mode 100644 new mode 100755 diff --git a/aircraft/OV10/reset00.xml b/aircraft/OV10/reset00.xml old mode 100644 new mode 100755 diff --git a/aircraft/Shuttle/Shuttle.xml b/aircraft/Shuttle/Shuttle.xml old mode 100644 new mode 100755 diff --git a/aircraft/Shuttle/reset00.xml b/aircraft/Shuttle/reset00.xml old mode 100644 new mode 100755 diff --git a/aircraft/T38/reset00.xml b/aircraft/T38/reset00.xml old mode 100644 new mode 100755 diff --git a/aircraft/ZLT-NT/Systems/datcom_aero.xml b/aircraft/ZLT-NT/Systems/datcom_aero.xml index 33af1ff1af846c60d221d5d2ad1838456ccdb67d..7c1fa9725e5059b30fb526480b5816bb7cb923aa 100644 --- a/aircraft/ZLT-NT/Systems/datcom_aero.xml +++ b/aircraft/ZLT-NT/Systems/datcom_aero.xml @@ -1,10 +1,9 @@ <?xml version="1.0"?> -<!-- $Id: datcom_aero.xml,v 1.1 2009/08/03 20:36:37 andgi Exp $ --> <!-- - ZLT NT airship flight model for JSBSim. + Zeppelin NT-07 airship flight model for JSBSim. - Copyright (C) 2009 Anders Gidenstam (anders(at)gidenstam.org) + Copyright (C) 2009 - 2010 Anders Gidenstam (anders(at)gidenstam.org) 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 @@ -266,7 +265,7 @@ 135.0 0.202 150.0 0.065 165.0 0.000 - 180.0 -0.011 + 180.0 0.011 </tableData> </table> </product> @@ -718,7 +717,6 @@ -6.0 -0.113 -4.0 -0.071 -2.0 -0.033 - 0.0 0.000 0.0 0.000 2.0 0.033 4.0 0.071 @@ -785,6 +783,8 @@ <function name="aero/moment/Clp_tail"> <description> Roll Moment coefficient due to roll rate (per radian/sec). + This is roll moment due to the difference in angle of attack + induced by the roll rate. </description> <product> <property>aero/qbar-psf</property> @@ -801,6 +801,24 @@ </product> </function> + <function name="aero/moment/Cl_tail_damp"> + <description> + Damping Roll Moment coefficient due to roll rate (per radian/sec). + Guessed and added to retain some damping effect at low airspeed. + Assumed to be due to the considerable area of the fins. + </description> + <product> + <value>1.0</value> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>velocities/p-aero-rad_sec</property> + <!-- Clp (copied) --> + <value> 0.10 </value> <!-- Sref scaling. --> + <value> 1.5 </value> <!-- 3 fins. --> + <value> -4.574E-01 </value> + </product> + </function> + </axis> <!-- ================================================== --> diff --git a/aircraft/ball/ball.xml b/aircraft/ball/ball.xml old mode 100644 new mode 100755 diff --git a/aircraft/ball/reset00.xml b/aircraft/ball/reset00.xml old mode 100644 new mode 100755 index ba82a52a0fc44139891b68793d56b0b1f1219541..cc7723288e55296defeb0ea27ef67b2586d77040 --- a/aircraft/ball/reset00.xml +++ b/aircraft/ball/reset00.xml @@ -1,16 +1,12 @@ <?xml version="1.0"?> <initialize name="reset00"> <!-- - This file sets up the mk82 to start off - from altitude. - Velocity of Earth surface at equator: 1525.92 ft/sec. + This file sets up the ball in orbit. + Velocity of Earth surface at equator: 1525.92 ft/sec. at ground level. + Velocity of Earth surface-synchronous point at equator: 1584.26 ft/sec. at 800 kft. + 1584.2593825 + 23869.9759596 = 25454.235342 ft/sec --> -<!-- <ubody unit="FT/SEC"> 24063.28275 </ubody> --> - <!-- Circular orbit at equator --> - <!-- 25464.28 ft/sec inertial velocity - s/b 25454.2 ft/sec. --> - <!-- <ubody unit="FT/SEC"> 23938.39 </ubody> --> -<!-- <ubody unit="FT/SEC"> 23889.15 </ubody> --> - <ubody unit="FT/SEC"> 23889.14273 </ubody> + <ubody unit="FT/SEC"> 23869.9759596 </ubody> <latitude unit="DEG"> 0.0 </latitude> <longitude unit="DEG"> 0.0 </longitude> <psi unit="DEG"> 90.0 </psi> diff --git a/aircraft/c172x/c172ap.xml b/aircraft/c172x/c172ap.xml old mode 100644 new mode 100755 diff --git a/aircraft/c310/c310ap.xml b/aircraft/c310/c310ap.xml old mode 100644 new mode 100755 diff --git a/aircraft/c310/ellington.xml b/aircraft/c310/ellington.xml old mode 100644 new mode 100755 diff --git a/aircraft/f16/Systems/.cvsignore b/aircraft/f16/Systems/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..282522db0342d8750454b3dc162493b5fc709cc8 --- /dev/null +++ b/aircraft/f16/Systems/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/aircraft/f16/Systems/hook.xml b/aircraft/f16/Systems/hook.xml old mode 100644 new mode 100755 diff --git a/aircraft/f16/Systems/pushback.xml b/aircraft/f16/Systems/pushback.xml old mode 100644 new mode 100755 diff --git a/aircraft/f16/reset00.xml b/aircraft/f16/reset00.xml old mode 100644 new mode 100755 diff --git a/aircraft/f22/f22.xml b/aircraft/f22/f22.xml index 62a277e1f0b8f62e28d1cd19ffa1b7cb0a9bcaa0..56036b748357a1f3a8c5ecaf344241206673a214 100644 --- a/aircraft/f22/f22.xml +++ b/aircraft/f22/f22.xml @@ -5,775 +5,738 @@ xsi:noNamespaceSchemaLocation="http://jsbsim.sourceforge.net/JSBSim.xsd"> <fileheader> - <author>Brian Mills </author> - <filecreationdate> 2009-05-24 </filecreationdate> - <version> $Revision: 1.36 $ </version> - <description> Models an F-22A Raptor </description> - <license> - <licenseName>GPL (General Public License)</licenseName> - <licenseURL>http://www.gnu.org/licenses/gpl.html</licenseURL> - </license> - <note> - This model was created using data that is, or has been, publically - available by means of technical reports, textbooks, image graphs or - published code. This aircraft description file is in no way related - to the manufacturer of the real aircraft. + <author>Brian Mills </author> + <filecreationdate> 2009-05-24 </filecreationdate> + <version> $Revision: 1.37 $ </version> + <description> Models an F-22A Raptor </description> + <license> + <licenseName>GPL (General Public License)</licenseName> + <licenseURL>http://www.gnu.org/licenses/gpl.html</licenseURL> + </license> + <note> + This model was created using data that is, or has been, publically + available by means of technical reports, textbooks, image graphs or + published code. This aircraft description file is in no way related + to the manufacturer of the real aircraft. Neither the name of (any of) the authors nor the names of (any of) the - manufacturers may be used to endorse or promote products derived from - this file. + manufacturers may be used to endorse or promote products derived from + this file. - The data is provided ''as is'' and any express or implied - warranties, including, but not limitted to the implied warranties of - merchantability and fitness for a particular purpose are disclaimed. - </note> - </fileheader> + The data is provided ''as is'' and any express or implied + warranties, including, but not limitted to the implied warranties of + merchantability and fitness for a particular purpose are disclaimed. + </note> + </fileheader> - <metrics> - <wingarea unit="FT2"> 840.0 </wingarea> - <wingspan unit="FT"> 44.49 </wingspan> - <chord unit="FT"> 23.06 </chord> - <htailarea unit="FT2"> 238.9 </htailarea> - <htailarm unit="FT"> 18.66 </htailarm> - <vtailarea unit="FT2"> 158.2 </vtailarea> - <vtailarm unit="FT"> 0 </vtailarm> - <location name="AERORP" unit="IN"> - <x> 417.6 </x> - <y> 0 </y> - <z> 0 </z> - </location> - <location name="EYEPOINT" unit="IN"> + <metrics> + <wingarea unit="FT2"> 840.0 </wingarea> + <wingspan unit="FT"> 44.49 </wingspan> + <chord unit="FT"> 23.06 </chord> + <htailarea unit="FT2"> 238.9 </htailarea> + <htailarm unit="FT"> 18.66 </htailarm> + <vtailarea unit="FT2"> 158.2 </vtailarea> + <vtailarm unit="FT"> 0 </vtailarm> + <location name="AERORP" unit="IN"> + <x> 417.6 </x> + <y> 0 </y> + <z> 0 </z> + </location> + <location name="EYEPOINT" unit="IN"> + <x> 148.8 </x> + <y> 0 </y> + <z> 38 </z> + </location> + <location name="VRP" unit="IN"> + <x> 100 </x> + <y> 0 </y> + <z> 0 </z> + </location> + </metrics> + + <mass_balance> + <ixx unit="SLUG*FT2"> 56005 </ixx> + <iyy unit="SLUG*FT2"> 280766 </iyy> + <izz unit="SLUG*FT2"> 354090 </izz> + <ixz unit="SLUG*FT2"> 713 </ixz> + <emptywt unit="LBS"> 43430 </emptywt> + <location name="CG" unit="IN"> + <x> 445.7 </x> + <y> 0 </y> + <z> -18.6 </z> + </location> + <pointmass name="Pilot"> + <weight unit="LBS"> 230 </weight> + <location name="POINTMASS" unit="IN"> <x> 148.8 </x> <y> 0 </y> - <z> 38 </z> - </location> - <location name="VRP" unit="IN"> - <x> 100 </x> - <y> 0 </y> - <z> 0 </z> + <z> 20 </z> </location> - </metrics> + </pointmass> + </mass_balance> - <mass_balance> - <ixx unit="SLUG*FT2"> 56005 </ixx> - <iyy unit="SLUG*FT2"> 280766 </iyy> - <izz unit="SLUG*FT2"> 354090 </izz> - <ixz unit="SLUG*FT2"> 713 </ixz> - <emptywt unit="LBS"> 43430 </emptywt> - <location name="CG" unit="IN"> - <x> 445.7 </x> + <ground_reactions> + <contact type="BOGEY" name="NOSE_LG"> + <location unit="IN"> + <x> 96.7 </x> <y> 0 </y> - <z> -18.6 </z> + <z> -89.3 </z> </location> - <pointmass name="Pilot"> - <weight unit="LBS"> 230 </weight> - <location name="POINTMASS" unit="IN"> - <x> 148.8 </x> - <y> 0 </y> - <z> 20 </z> - </location> - </pointmass> - </mass_balance> - - <ground_reactions> - <contact type="BOGEY" name="NOSE_LG"> + <static_friction> 0.8 </static_friction> + <dynamic_friction> 0.5 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 18603.4 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 6201.1 </damping_coeff> + <max_steer unit="DEG"> 80 </max_steer> + <brake_group> NONE </brake_group> + <retractable>1</retractable> + </contact> + <contact type="BOGEY" name="LEFT_MLG"> + <location unit="IN"> + <x> 468.8 </x> + <y> -48 </y> + <z> -89.3 </z> + </location> + <static_friction> 0.8 </static_friction> + <dynamic_friction> 0.5 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 82011.2 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 22402.2 </damping_coeff> + <max_steer unit="DEG"> 0.0 </max_steer> + <brake_group> LEFT </brake_group> + <retractable>1</retractable> + </contact> + <contact type="BOGEY" name="RIGHT_MLG"> + <location unit="IN"> + <x> 468.8 </x> + <y> 48 </y> + <z> -89.3 </z> + </location> + <static_friction> 0.8 </static_friction> + <dynamic_friction> 0.5 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 82011.2 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 22402.2 </damping_coeff> + <max_steer unit="DEG"> 0.0 </max_steer> + <brake_group> RIGHT </brake_group> + <retractable>1</retractable> + </contact> + </ground_reactions> + + <propulsion> + <engine file="F119-PW-1"> + <location unit="IN"> + <x> 684.131 </x> + <y> -20 </y> + <z> 0 </z> + </location> + <orient unit="DEG"> + <roll> 0.0 </roll> + <pitch> 0 </pitch> + <yaw> 0 </yaw> + </orient> + <feed>0</feed> + <feed>1</feed> + <thruster file="direct"> <location unit="IN"> - <x> 96.7 </x> - <y> 0 </y> - <z> -89.3 </z> + <x> 684.131 </x> + <y>-20 </y> + <z> 0 </z> </location> - <static_friction> 0.8 </static_friction> - <dynamic_friction> 0.5 </dynamic_friction> - <rolling_friction> 0.02 </rolling_friction> - <spring_coeff unit="LBS/FT"> 18603.4 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 6201.1 </damping_coeff> - <max_steer unit="DEG"> 80 </max_steer> - <brake_group> NONE </brake_group> - <retractable>1</retractable> - </contact> - <contact type="BOGEY" name="LEFT_MLG"> + <orient unit="DEG"> + <roll> 0.0 </roll> + <pitch> 0.0 </pitch> + <yaw> 0.0 </yaw> + </orient> + </thruster> + </engine> + <engine file="F119-PW-1"> + <location unit="IN"> + <x> 684.131 </x> + <y> 20 </y> + <z> 0 </z> + </location> + <orient unit="DEG"> + <roll> 0.0 </roll> + <pitch> 0 </pitch> + <yaw> 0 </yaw> + </orient> + <feed>0</feed> + <feed>1</feed> + <thruster file="direct"> <location unit="IN"> - <x> 468.8 </x> - <y> -48 </y> - <z> -89.3 </z> - </location> - <static_friction> 0.8 </static_friction> - <dynamic_friction> 0.5 </dynamic_friction> - <rolling_friction> 0.02 </rolling_friction> - <spring_coeff unit="LBS/FT"> 82011.2 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 22402.2 </damping_coeff> - <max_steer unit="DEG"> 0.0 </max_steer> - <brake_group> LEFT </brake_group> - <retractable>1</retractable> - </contact> - <contact type="BOGEY" name="RIGHT_MLG"> - <location unit="IN"> - <x> 468.8 </x> - <y> 48 </y> - <z> -89.3 </z> - </location> - <static_friction> 0.8 </static_friction> - <dynamic_friction> 0.5 </dynamic_friction> - <rolling_friction> 0.02 </rolling_friction> - <spring_coeff unit="LBS/FT"> 82011.2 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 22402.2 </damping_coeff> - <max_steer unit="DEG"> 0.0 </max_steer> - <brake_group> RIGHT </brake_group> - <retractable>1</retractable> - </contact> - </ground_reactions> - <propulsion> - <engine file="F119-PW-1"> - <location unit="IN"> - <x> 684.131 </x> - <y> -20 </y> - <z> 0 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> 0 </pitch> - <yaw> 0 </yaw> - </orient> - <feed>0</feed> - <feed>1</feed> - <thruster file="direct"> - <location unit="IN"> - <x> 684.131 </x> - <y>-20 </y> - <z> 0 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> 0.0 </pitch> - <yaw> 0.0 </yaw> - </orient> - </thruster> - </engine> - <engine file="F119-PW-1"> - <location unit="IN"> - <x> 684.131 </x> - <y> 20 </y> - <z> 0 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> 0 </pitch> - <yaw> 0 </yaw> - </orient> - <feed>0</feed> - <feed>1</feed> - <thruster file="direct"> - <location unit="IN"> - <x> 684.131 </x> - <y> 20 </y> - <z> 0 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> 0.0 </pitch> - <yaw> 0.0 </yaw> - </orient> - </thruster> - </engine> + <x> 684.131 </x> + <y> 20 </y> + <z> 0 </z> + </location> + <orient unit="DEG"> + <roll> 0.0 </roll> + <pitch> 0.0 </pitch> + <yaw> 0.0 </yaw> + </orient> + </thruster> + </engine> <tank type="FUEL"> - <location unit="IN"> - <x> 446.478 </x> - <y> -36 </y> - <z> -18.6033 </z> - </location> - <capacity unit="LBS"> 9350 </capacity> - <contents unit="LBS"> 9350 </contents> - </tank> - <tank type="FUEL"> - <location unit="IN"> - <x> 446.478 </x> - <y> 36 </y> - <z> -18.6033 </z> - </location> - <capacity unit="LBS"> 9350 </capacity> - <contents unit="LBS"> 9350 </contents> - </tank> - + <location unit="IN"> + <x> 446.478 </x> + <y> -36 </y> + <z> -18.6033 </z> + </location> + <capacity unit="LBS"> 9350 </capacity> + <contents unit="LBS"> 9350 </contents> + </tank> + <tank type="FUEL"> + <location unit="IN"> + <x> 446.478 </x> + <y> 36 </y> + <z> -18.6033 </z> + </location> + <capacity unit="LBS"> 9350 </capacity> + <contents unit="LBS"> 9350 </contents> + </tank> </propulsion> + <flight_control name="F-22 FC"> - <!-- Declare some interface properties --> - <property>fcs/alpha-norm</property> - <property>fcs/tvc-pos-norm</property> - <property>fcs/tvc-pos-rad</property> - <property>fcs/thrust-norm</property> - <property>fcs/lef-pos-rad</property> - <property>fcs/lef-pos-norm</property> - <property>fcs/throttle-override</property> - <property>fcs/speedbrake-aileron</property> - <property>fcs/speedbrake-aileron-right</property> - <property>fcs/speedbrake-rudder</property> - <property>fcs/speedbrake-flap</property> - <property>fcs/yaw-rate-integrator</property> - <property>fcs/roll-rate-integrator</property> - <property>fcs/pitch-rate-integrator</property> - <property>fcs/tvc-inhibit</property> - <channel name="Lateral"> - - <!-- Normalize the u-velocity to m/s--> - <pure_gain name="u velocity norm"> - <input>velocities/u-fps</input> - <gain>0.3048</gain> - </pure_gain> - - <summer name="aileron cmd limiter"> - <input>fcs/aileron-cmd-norm</input> - <input>fcs/roll-trim-cmd-norm</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - </summer> - - <!-- Stick filter --> - <lag_filter name="roll cmd filter"> - <input>fcs/aileron-cmd-limiter</input> - <c1>10</c1> - </lag_filter> - - <!-- Limit roll rate command in radians based on altitude, mach and AoA--> - <fcs_function name="roll cmd limit"> - <function> - <table> - <independentVar lookup="column">velocities/mach</independentVar> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <independentVar lookup="table">position/h-sl-ft</independentVar> - <tableData breakPoint="0"> - 0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 - -90 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 - -25 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 - -20 0.6 0.85 1 1 1 1 1 1 1 - -15 0.6 0.85 1.5 1.5 1.5 1.5 1.5 1.5 1.5 - -10 0.6 1 2.5 3.14 3.14 3.14 3.14 2.617 2.1 - 0 0.6 1.5 2.5 3.66 4 4 3.14 2.617 2.1 - 10 0.6 1 2.5 3.14 3.14 3.14 3.14 2.617 2.1 - 15 0.6 0.85 2.5 2.617 2.617 2.617 2.617 2.617 2.1 - 20 0.6 0.85 2.1 2.1 2.1 2.1 2.1 2.1 2.1 - 25 0.6 0.85 1.5 1.5 1.5 1.5 1.5 1.5 1.5 - 30 0.6 0.85 1.3 1.3 1.3 1.3 1.3 1.3 1.3 - 35 0.6 0.85 1 1 1 1 1 1 1 - 40 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 - 45 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 - 180 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 - </tableData> - <tableData breakPoint="30000"> - 0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 - -90 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 - -25 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 - -20 0.6 0.85 1 1 1 1 1 1 1 - -15 0.6 0.85 1.5 1.5 1.5 1.5 1.5 1.5 1.5 - -10 0.6 0.85 2.5 3.14 3.14 3.14 3.14 2.617 2.1 - 0 0.6 0.85 2.5 3.66 4 4 3.14 2.617 2.1 - 10 0.6 0.85 2.5 3.14 3.14 3.14 3.14 2.617 2.1 - 15 0.6 0.85 2.5 2.617 2.617 2.617 2.617 2.617 2.1 - 20 0.6 0.85 2.1 2.1 2.1 2.1 2.1 2.1 2.1 - 25 0.6 0.85 1.5 1.5 1.5 1.5 1.5 1.5 1.5 - 30 0.6 0.85 1.3 1.3 1.3 1.3 1.3 1.3 1.3 - 35 0.6 0.85 1 1 1 1 1 1 1 - 40 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 - 45 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 - 180 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 - </tableData> - <tableData breakPoint="70000"> - 0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 - -90 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 - -25 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 - -20 0.6 0.85 1 1 1 1 1 1 1 - -15 0.6 0.85 1 1.25 1.5 1.5 1.5 1.5 1.5 - -10 0.6 0.85 1.5 1.5 2 2.25 2.25 2.25 2 - 0 0.6 0.85 1.5 2 2.5 2.5 2.75 2.75 2.5 - 10 0.6 0.85 1.5 1.5 2 2.25 2.25 2.25 2 - 15 0.6 0.85 1.5 2 2 2 2 2 2 - 20 0.6 0.85 1 1.25 1.5 2 2 2 2 - 25 0.6 0.85 1 1.25 1.5 1.5 1.5 1.5 1.5 - 30 0.6 0.85 1 1 1.3 1.3 1.3 1.3 1.3 - 35 0.6 0.85 1 1 1 1 1 1 1 - 40 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 - 45 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 - 180 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 - </tableData> - </table> - </function> - </fcs_function> - - <!-- Calculate the normalized commanded roll rate absolutely limited to +230 deg/s -230 deg/s--> - <pure_gain name="roll rate cmd"> - <input>fcs/roll-cmd-filter</input> - <gain>fcs/roll-cmd-limit</gain> - <clipto> - <min>-4</min> - <max>4</max> - </clipto> - </pure_gain> - - - <deadband name="roll windup trigger"> - <input>fcs/roll-rate-integrator</input> - <width>8</width> - <clipto> - <min>-4</min> - <max>4</max> - </clipto> - </deadband> - - <summer name="roll rate error"> - <input>fcs/roll-rate-cmd</input> - <input>-velocities/p-aero-rad_sec</input> - <input>-fcs/roll-windup-trigger</input> - </summer> - - <integrator name="roll rate integrator"> - <!--trigger>fcs/aileron-int-trigger</trigger--> - <input>fcs/roll-rate-error</input> - <c1> 1 </c1> - <clipto> - <min>-4</min> - <max>4</max> - </clipto> - <output>fcs/roll-rate-integrator</output> - - </integrator> - - - - <!-- Normalize the v-velocity to m/s--> - <pure_gain name="v velocity norm"> - <input>velocities/v-fps</input> - <gain>0.3048</gain> - </pure_gain> - - <pure_gain name="rudder cmd limiter"> - <input>fcs/rudder-cmd-norm</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - </pure_gain> - - <!-- Rudder pedal filter --> - <lag_filter name="rudder cmd filter"> - <input>fcs/rudder-cmd-limiter</input> - <c1>10</c1> - </lag_filter> - - <!-- Limit yaw rate command in radians based on mach and altitude --> - <fcs_function name="yaw rate limit"> - <function> - <table> - <independentVar lookup="row">velocities/mach</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> + <!-- Declare some interface properties --> +<!-- <property>fcs/alpha-norm</property> + <property>fcs/tvc-pos-norm</property> + <property>fcs/tvc-pos-rad</property> + <property>fcs/thrust-norm</property> + <property>fcs/lef-pos-rad</property> + <property>fcs/lef-pos-norm</property> + <property>fcs/throttle-override</property> + <property>fcs/speedbrake-aileron</property> + <property>fcs/speedbrake-aileron-right</property> + <property>fcs/speedbrake-rudder</property> + <property>fcs/speedbrake-flap</property> + <property>fcs/yaw-rate-integrator</property> + <property>fcs/pitch-rate-integrator</property> + <property>fcs/tvc-inhibit</property> --> + + <channel name="Lateral"> + + <!-- Normalize the u-velocity to m/s--> + <pure_gain name="fcs/u-velocity-norm"> + <input>velocities/u-fps</input> + <gain>0.3048</gain> + </pure_gain> + + <summer name="fcs/aileron-cmd-limiter"> + <input>fcs/aileron-cmd-norm</input> + <input>fcs/roll-trim-cmd-norm</input> + <clipto> + <min>-1</min> + <max>1</max> + </clipto> + </summer> + + <!-- Stick filter --> + <lag_filter name="fcs/roll-cmd-filter"> + <input>fcs/aileron-cmd-limiter</input> + <c1>10</c1> + </lag_filter> + + <!-- Limit roll rate command in radians based on altitude, mach and AoA--> + <fcs_function name="fcs/roll-cmd-limit"> + <function> + <table> + <independentVar lookup="column">velocities/mach</independentVar> + <independentVar lookup="row">aero/alpha-deg</independentVar> + <independentVar lookup="table">position/h-sl-ft</independentVar> + <tableData breakPoint="0"> + 0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 + -90 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 + -25 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 + -20 0.6 0.85 1 1 1 1 1 1 1 + -15 0.6 0.85 1.5 1.5 1.5 1.5 1.5 1.5 1.5 + -10 0.6 1 2.5 3.14 3.14 3.14 3.14 2.617 2.1 + 0 0.6 1.5 2.5 3.66 4 4 3.14 2.617 2.1 + 10 0.6 1 2.5 3.14 3.14 3.14 3.14 2.617 2.1 + 15 0.6 0.85 2.5 2.617 2.617 2.617 2.617 2.617 2.1 + 20 0.6 0.85 2.1 2.1 2.1 2.1 2.1 2.1 2.1 + 25 0.6 0.85 1.5 1.5 1.5 1.5 1.5 1.5 1.5 + 30 0.6 0.85 1.3 1.3 1.3 1.3 1.3 1.3 1.3 + 35 0.6 0.85 1 1 1 1 1 1 1 + 40 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 45 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 180 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + </tableData> + <tableData breakPoint="30000"> + 0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 + -90 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 + -25 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 + -20 0.6 0.85 1 1 1 1 1 1 1 + -15 0.6 0.85 1.5 1.5 1.5 1.5 1.5 1.5 1.5 + -10 0.6 0.85 2.5 3.14 3.14 3.14 3.14 2.617 2.1 + 0 0.6 0.85 2.5 3.66 4 4 3.14 2.617 2.1 + 10 0.6 0.85 2.5 3.14 3.14 3.14 3.14 2.617 2.1 + 15 0.6 0.85 2.5 2.617 2.617 2.617 2.617 2.617 2.1 + 20 0.6 0.85 2.1 2.1 2.1 2.1 2.1 2.1 2.1 + 25 0.6 0.85 1.5 1.5 1.5 1.5 1.5 1.5 1.5 + 30 0.6 0.85 1.3 1.3 1.3 1.3 1.3 1.3 1.3 + 35 0.6 0.85 1 1 1 1 1 1 1 + 40 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 45 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 180 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + </tableData> + <tableData breakPoint="70000"> + 0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 + -90 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 + -25 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 + -20 0.6 0.85 1 1 1 1 1 1 1 + -15 0.6 0.85 1 1.25 1.5 1.5 1.5 1.5 1.5 + -10 0.6 0.85 1.5 1.5 2 2.25 2.25 2.25 2 + 0 0.6 0.85 1.5 2 2.5 2.5 2.75 2.75 2.5 + 10 0.6 0.85 1.5 1.5 2 2.25 2.25 2.25 2 + 15 0.6 0.85 1.5 2 2 2 2 2 2 + 20 0.6 0.85 1 1.25 1.5 2 2 2 2 + 25 0.6 0.85 1 1.25 1.5 1.5 1.5 1.5 1.5 + 30 0.6 0.85 1 1 1.3 1.3 1.3 1.3 1.3 + 35 0.6 0.85 1 1 1 1 1 1 1 + 40 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 45 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 180 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + </tableData> + </table> + </function> + </fcs_function> + + <!-- Calculate the normalized commanded roll rate absolutely limited to +230 deg/s -230 deg/s--> + <pure_gain name="fcs/roll-rate-cmd"> + <input>fcs/roll-cmd-filter</input> + <gain>fcs/roll-cmd-limit</gain> + <clipto> + <min>-4</min> + <max>4</max> + </clipto> + </pure_gain> + + <deadband name="fcs/roll-windup-trigger"> + <input>fcs/roll-rate-integrator</input> + <width>8</width> + <clipto> + <min>-4</min> + <max>4</max> + </clipto> + </deadband> + + <summer name="fcs/roll-rate-error"> + <input>fcs/roll-rate-cmd</input> + <input>-velocities/p-aero-rad_sec</input> + <input>-fcs/roll-windup-trigger</input> + </summer> + + <integrator name="fcs/roll-rate-integrator"> + <!--trigger>fcs/aileron-int-trigger</trigger--> + <input>fcs/roll-rate-error</input> + <c1> 1 </c1> + <clipto> + <min>-4</min> + <max>4</max> + </clipto> + </integrator> + + <!-- Normalize the v-velocity to m/s--> + <pure_gain name="fcs/v-velocity-norm"> + <input>velocities/v-fps</input> + <gain>0.3048</gain> + </pure_gain> + + <pure_gain name="fcs/rudder-cmd-limiter"> + <input>fcs/rudder-cmd-norm</input> + <gain> 1.0 </gain> + <clipto> + <min>-1</min> + <max>1</max> + </clipto> + </pure_gain> + + <!-- Rudder pedal filter --> + <lag_filter name="fcs/rudder-cmd-filter"> + <input>fcs/rudder-cmd-limiter</input> + <c1>10</c1> + </lag_filter> + + <!-- Limit yaw rate command in radians based on mach and altitude --> + <fcs_function name="fcs/yaw-rate-limit"> + <function> + <table> + <independentVar lookup="row">velocities/mach</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> + <tableData> + 0 36000 + 0 -0.436 -0.436 + 0.4 -0.349 -0.349 + 0.8 -0.1745 -0.1745 + 1.0 -0.1 -0.1 + 2.0 -0.1 -0.1 + </tableData> + </table> + </function> + </fcs_function> + + <pure_gain name="fcs/yaw-rate-cmd"> + <input>fcs/rudder-cmd-filter</input> + <gain>fcs/yaw-rate-limit</gain> + </pure_gain> + + <!-- washout filter to fullfill handling qualities--> + <washout_filter name="fcs/yaw-rate-filter"> + <input>velocities/r-aero-rad_sec</input> + <c1> 1.2 </c1> + </washout_filter> + + <deadband name="fcs/yaw-windup-trigger"> + <input>fcs/yaw-rate-integrator</input> + <width>0.872</width> + <clipto> + <min>-0.436</min> + <max>0.436</max> + </clipto> + </deadband> + + <summer name="fcs/yaw-rate-error"> + <input> -fcs/yaw-rate-filter </input> + <input> -fcs/yaw-windup-trigger </input> + <input> fcs/yaw-rate-cmd </input> + </summer> + + <integrator name="fcs/yaw-rate-integrator"> + <!--trigger>fcs/rudder-int-trigger</trigger--> + <input>fcs/yaw-rate-error</input> + <c1> 1 </c1> + <clipto> + <min>-0.436</min> + <max>0.436</max> + </clipto> + <output>fcs/yaw-rate-integrator</output> + </integrator> + + <!-- if yaw rate exceeds limits based on rate and mach, then apply opposite rudder--> + <fcs_function name="fcs/yaw-rate-override"> + <function> + <table> + <independentVar lookup="row">velocities/r-aero-rad_sec</independentVar> + <independentVar lookup="column">velocities/mach</independentVar> + <tableData> + 0 0.4 0.8 1.0 2.0 + -0.440 0.872 0.7 0.35 0.2 0.2 + -0.436 0 0.7 0.35 0.2 0.2 + -0.360 0 0.7 0.35 0.2 0.2 + -0.349 0 0 0.35 0.2 0.2 + -0.180 0 0 0.35 0.2 0.2 + -0.1745 0 0 0 0.2 0.2 + -0.11 0 0 0 0.2 0.2 + -0.1 0 0 0 0 0 + 0 0 0 0 0 0 + 0.1 0 0 0 0 0 + 0.11 0 0 0 -0.2 -0.2 + 0.1745 0 0 0 -0.2 -0.2 + 0.18 0 0 -0.35 -0.2 -0.2 + 0.349 0 0 -0.35 -0.2 -0.2 + 0.36 0 -0.7 -0.35 -0.2 -0.2 + 0.436 0 -0.7 -0.35 -0.2 -0.2 + 0.440 -0.872 -0.7 -0.35 -0.2 -0.2 + </tableData> + </table> + </function> + </fcs_function> + + <summer name="fcs/yaw-cmd-summer"> + <input>fcs/yaw-rate-integrator</input> + <input>fcs/yaw-rate-override</input> + </summer> + + <!-- LQR Tracker Integral aileron roll-rate control--> + <fcs_function name="fcs/roll-cmd"> + <function> + <product> + <sum> + <product> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> + <tableData> + 0 33000 50000 + 160 0.5 0.35 0.3 + 270 0.5 0.35 0.3 + 400 0.45 0.4 0.3 + 500 0.45 0.4 0.35 + 580 0.5 0.45 0.35 + 1000 0.5 0.45 0.4 + </tableData> + </table> + <property> fcs/roll-rate-integrator </property> + <value> -1 </value> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> + <tableData> + 0 33000 50000 + 160 -28.4059 -31.1627 -31.1627 + 270 -30.9146 -32.6575 -32.6575 + 330 -35.9146 -32.6575 -32.6575 + 400 -44.4687 -38.7651 -38.7651 + 580 -44.2746 -36.5662 -36.5662 + 700 -39.0735 -34.9842 -34.9842 + </tableData> + </table> + </product> + <product> + <property> fcs/v-velocity-norm </property> + <value> 0 </value> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> + <tableData> + 0 33000 50000 + 160 -0.0494 -0.0266 -0.0266 + 270 0.0067 -0.0160 -0.0160 + 330 0.0067 -0.0160 -0.0160 + 400 -0.1082 -0.0108 -0.0108 + 580 -0.0104 -0.0091 -0.0091 + 700 -0.0095 -0.0118 -0.0118 + </tableData> + </table> + </product> + <product> + <!--table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> + <tableData> + 0 33000 50000 + 160 1 1.5 2 + 270 1 1.35 1.75 + 400 1 1.2 1.5 + 500 1.0 1.1 1.0 + 580 1.0 1.0 1.0 + 1000 1.0 1.0 1.0 + </tableData> + </table--> + <property>velocities/p-aero-rad_sec</property> + <value>-.35</value> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> + <tableData> + 0 33000 50000 + 160 11.7952 13.4573 13.4573 + 270 11.9041 13.1381 13.1381 + 330 11.9041 13.1381 13.1381 + 400 12.0644 10.6808 10.6808 + 580 11.0366 10.7511 10.7511 + 700 9.3909 10.8556 10.8556 + </tableData> + </table> + </product> + </sum> + <!--table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">aero/alpha-rad</independentVar> + <tableData> + -1 -0.25 0 0.25 0.5 1 2 3 + 160 1.5 1.25 1 1.25 1.5 2 2.5 3 + 270 1.5 1.25 1 1.25 1.5 2 2.5 3 + 400 1.5 1.25 1 1.25 1.5 2 2.5 3 + 500 1.5 1.15 1 1.15 1.35 2 2.5 3 + 580 1.5 1.15 1 1.15 1.35 2 2.5 3 + 1000 1.5 1.15 1 1.15 1.35 2 2.5 3 + + </tableData> + </table--> + </product> + </function> + <clipto> + <min>-5</min> + <max>5</max> + </clipto> + </fcs_function> + + <aerosurface_scale name="fcs/roll-reg-scale"> + <input> fcs/roll-cmd </input> + <domain> + <min> -5 </min> + <max> 5 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + </aerosurface_scale > + + <actuator name="fcs/aileron-act"> + <input> fcs/roll-reg-scale</input> + <lag> 0.00 </lag> + <rate_limit> 2.29 </rate_limit> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + </actuator> + + <summer name="fcs/left-aileron-out"> + <input>fcs/aileron-act</input> + <input>fcs/speedbrake-aileron</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + <output>fcs/left-aileron-pos-norm</output> + </summer> + + <aerosurface_scale name="fcs/left-aileron-control"> + <input>fcs/aileron-act</input> + <range> + <min>-0.436</min> + <max>0.436</max> + </range> + <output>fcs/left-aileron-pos-rad</output> + </aerosurface_scale> + + <pure_gain name="fcs/left-aileron-neg"> + <input>fcs/aileron-act</input> + <gain>-1</gain> + </pure_gain> + + <summer name="fcs/right-aileron-out"> + <input>fcs/left-aileron-neg</input> + <input>fcs/speedbrake-aileron-right</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + <output>fcs/right-aileron-pos-norm</output> + </summer> + + <aerosurface_scale name="fcs/right-aileron-control"> + <input>fcs/left-aileron-neg</input> + <range> + <min>-0.436</min> + <max>0.436</max> + </range> + <output>fcs/right-aileron-pos-rad</output> + </aerosurface_scale> + + <!-- LQR Tracker Integral rudder yaw-rate control--> + <fcs_function name="fcs/yaw-cmd"> + <function> + <product> + <sum> + <product> + <property>fcs/yaw-cmd-summer</property> + <value>-0.2</value> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> <tableData> - 0 36000 - 0 -0.436 -0.436 - 0.4 -0.349 -0.349 - 0.8 -0.1745 -0.1745 - 1.0 -0.1 -0.1 - 2.0 -0.1 -0.1 - </tableData> - </table> - </function> - </fcs_function> - - <pure_gain name="yaw rate cmd"> - <input>fcs/rudder-cmd-filter</input> - <gain>fcs/yaw-rate-limit</gain> - - </pure_gain> - - <!-- washout filter to fullfill handling qualities--> - <washout_filter name="yaw rate filter"> - <input>velocities/r-aero-rad_sec</input> - <c1> 1.2 </c1> - </washout_filter> - - <deadband name="yaw windup trigger"> - <input>fcs/yaw-rate-integrator</input> - <width>0.872</width> - <clipto> - <min>-0.436</min> - <max>0.436</max> - </clipto> - </deadband> - - <summer name="yaw rate error"> - <value>fcs/yaw-rate-cmd</value> - <input>-fcs/yaw-rate-filter</input> - <input>-fcs/yaw-windup-trigger</input> - </summer> - - <integrator name="yaw rate integrator"> - <!--trigger>fcs/rudder-int-trigger</trigger--> - <input>fcs/yaw-rate-error</input> - <c1> 1 </c1> - <clipto> - <min>-0.436</min> - <max>0.436</max> - </clipto> - <output>fcs/yaw-rate-integrator</output> - </integrator> - - <!-- if yaw rate exceeds limits based on rate and mach, then apply opposite rudder--> - <fcs_function name="yaw rate override"> - <function> - <table> - <independentVar lookup="row">velocities/r-aero-rad_sec</independentVar> - <independentVar lookup="column">velocities/mach</independentVar> + 0 33000 50000 + 160 22.1027 22.1741 22.1741 + 270 22.1775 15.7518 15.7518 + 400 14.0894 14.0894 14.0894 + 580 12.8629 12.8629 12.8629 + 700 14.8347 12.8631 12.8631 + </tableData> + </table> + </product> + <product> + <property>fcs/yaw-rate-filter</property> + <value>-0.2</value> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> <tableData> - 0 0.4 0.8 1.0 2.0 - -0.440 0.872 0.7 0.35 0.2 0.2 - -0.436 0 0.7 0.35 0.2 0.2 - -0.360 0 0.7 0.35 0.2 0.2 - -0.349 0 0 0.35 0.2 0.2 - -0.180 0 0 0.35 0.2 0.2 - -0.1745 0 0 0 0.2 0.2 - -0.11 0 0 0 0.2 0.2 - -0.1 0 0 0 0 0 - 0 0 0 0 0 0 - 0.1 0 0 0 0 0 - 0.11 0 0 0 -0.2 -0.2 - 0.1745 0 0 0 -0.2 -0.2 - 0.18 0 0 -0.35 -0.2 -0.2 - 0.349 0 0 -0.35 -0.2 -0.2 - 0.36 0 -0.7 -0.35 -0.2 -0.2 - 0.436 0 -0.7 -0.35 -0.2 -0.2 - 0.440 -0.872 -0.7 -0.35 -0.2 -0.2 - </tableData> - </table> - </function> - </fcs_function> - - <summer name="yaw cmd summer"> - <input>fcs/yaw-rate-integrator</input> - <input>fcs/yaw-rate-override</input> - </summer> - - - - <!-- LQR Tracker Integral aileron roll-rate control--> - <fcs_function name="roll cmd"> - - <function> - <product> - <sum> - - <product> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> - <tableData> - 0 33000 50000 - 160 0.5 0.35 0.3 - 270 0.5 0.35 0.3 - 400 0.45 0.4 0.3 - 500 0.45 0.4 0.35 - 580 0.5 0.45 0.35 - 1000 0.5 0.45 0.4 - - </tableData> - </table> - - <property>fcs/roll-rate-integrator</property> - <value>-1</value> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> - <tableData> - 0 33000 50000 - 160 -28.4059 -31.1627 -31.1627 - 270 -30.9146 -32.6575 -32.6575 - 330 -35.9146 -32.6575 -32.6575 - 400 -44.4687 -38.7651 -38.7651 - 580 -44.2746 -36.5662 -36.5662 - 700 -39.0735 -34.9842 -34.9842 - </tableData> - </table> - </product> - - <product> - - <property>fcs/v-velocity-norm</property> - <value>0</value> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> - <tableData> - 0 33000 50000 - 160 -0.0494 -0.0266 -0.0266 - 270 0.0067 -0.0160 -0.0160 - 330 0.0067 -0.0160 -0.0160 - 400 -0.1082 -0.0108 -0.0108 - 580 -0.0104 -0.0091 -0.0091 - 700 -0.0095 -0.0118 -0.0118 - </tableData> - </table> - </product> - - <product> - - <!--table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> - <tableData> - 0 33000 50000 - 160 1 1.5 2 - 270 1 1.35 1.75 - 400 1 1.2 1.5 - 500 1.0 1.1 1.0 - 580 1.0 1.0 1.0 - 1000 1.0 1.0 1.0 - - </tableData> - </table--> - <property>velocities/p-aero-rad_sec</property> - <value>-.35</value> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> - <tableData> - 0 33000 50000 - 160 11.7952 13.4573 13.4573 - 270 11.9041 13.1381 13.1381 - 330 11.9041 13.1381 13.1381 - 400 12.0644 10.6808 10.6808 - 580 11.0366 10.7511 10.7511 - 700 9.3909 10.8556 10.8556 - </tableData> - </table> - </product> - - </sum> - <!--table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">aero/alpha-rad</independentVar> - <tableData> - -1 -0.25 0 0.25 0.5 1 2 3 - 160 1.5 1.25 1 1.25 1.5 2 2.5 3 - 270 1.5 1.25 1 1.25 1.5 2 2.5 3 - 400 1.5 1.25 1 1.25 1.5 2 2.5 3 - 500 1.5 1.15 1 1.15 1.35 2 2.5 3 - 580 1.5 1.15 1 1.15 1.35 2 2.5 3 - 1000 1.5 1.15 1 1.15 1.35 2 2.5 3 - - </tableData> - </table--> - </product> - </function> - <clipto> - <min>-5</min> - <max>5</max> - </clipto> - </fcs_function> - - - - <aerosurface_scale name="roll reg scale"> - <input> fcs/roll-cmd </input> - <domain> - <min> -5 </min> - <max> 5 </max> - </domain> - <range> - <min> -1 </min> - <max> 1 </max> - </range> - </aerosurface_scale > - - - <actuator name="Aileron Act"> - <input> fcs/roll-reg-scale</input> - <lag> 0.00 </lag> - <rate_limit> 2.29 </rate_limit> - - <clipto> - - <min> -1 </min> - <max> 1 </max> - </clipto> - - </actuator> - - <summer name="Left Aileron Out"> - <input>fcs/aileron-act</input> - <input>fcs/speedbrake-aileron</input> - <clipto> - - <min> -1 </min> - <max> 1 </max> - </clipto> - <output>fcs/left-aileron-pos-norm</output> - </summer> - - <aerosurface_scale name="Left Aileron Control"> - <input>fcs/aileron-act</input> - - <range> - <min>-0.436</min> - <max>0.436</max> - </range> - <output>fcs/left-aileron-pos-rad</output> - </aerosurface_scale> - - <pure_gain name="Left Aileron Neg"> - <input>fcs/aileron-act</input> - <gain>-1</gain> - - </pure_gain> - - <summer name="Right Aileron Out"> - <input>fcs/left-aileron-neg</input> - <input>fcs/speedbrake-aileron-right</input> - <clipto> - - <min> -1 </min> - <max> 1 </max> - </clipto> - <output>fcs/right-aileron-pos-norm</output> - </summer> - - <aerosurface_scale name="Right Aileron Control"> - <input>fcs/left-aileron-neg</input> - - <range> - <min>-0.436</min> - <max>0.436</max> - </range> - <output>fcs/right-aileron-pos-rad</output> - </aerosurface_scale> - - <!-- LQR Tracker Integral rudder yaw-rate control--> - <fcs_function name="yaw cmd"> - <function> - <product> - <sum> - - - <product> - <property>fcs/yaw-cmd-summer</property> - <value>-0.2</value> - - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> - <tableData> - 0 33000 50000 - 160 22.1027 22.1741 22.1741 - 270 22.1775 15.7518 15.7518 - 400 14.0894 14.0894 14.0894 - 580 12.8629 12.8629 12.8629 - 700 14.8347 12.8631 12.8631 - </tableData> - </table> - </product> - - <product> - <property>fcs/yaw-rate-filter</property> - <value>-0.2</value> - - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> - <tableData> - 0 33000 50000 - 160 -21.4844 -29.9948 -29.9948 - 270 -19.5573 -17.5259 -17.5259 - 400 -13.6930 -13.6930 -13.6930 - 580 -9.6423 -9.6423 -9.6423 - 700 -7.7903 -6.1197 -6.1197 - </tableData> - </table> - </product> - </sum> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> - <tableData> - 0 33000 50000 - 160 1 1.2 1.2 - 270 1 1.1 1.1 - 400 0.5 0.55 0.6 - 580 0.3 0.35 0.4 - 700 0.2 0.25 0.3 - </tableData> - </table> - <table> - <independentVar lookup="row">aero/alpha-deg</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> - <tableData> - 0 33000 50000 - -60 3 3.5 4 - -40 2 2.5 3 - -20 1.5 1.75 2 - 0 0.7 0.8 0.9 - 20 1.75 2 2.5 - 40 2.5 3 3.5 - 60 3 3.5 4 - 80 3.5 4 5 - </tableData> - </table> - - - </product> - </function> - <clipto> - <min>-5</min> - <max>5</max> - </clipto> - </fcs_function> - - <aerosurface_scale name="yaw reg scale"> - <input> fcs/yaw-cmd </input> - <domain> - <min> -5 </min> - <max> 5 </max> - </domain> - <range> - <min> -1 </min> - <max> 1 </max> - </range> - </aerosurface_scale > - - <actuator name="rudder act"> - <input> fcs/yaw-reg-scale</input> - <lag> 0 </lag> - <rate_limit> 2.673 </rate_limit> - - <clipto> - - <min> -1 </min> - <max> 1 </max> - </clipto> - </actuator> - - - <summer name="rudder pos out"> - <input>fcs/rudder-act</input> - <input>fcs/speedbrake-rudder</input> - <clipto> - - <min> -1 </min> - <max> 1 </max> - </clipto> - <output>fcs/rudder-pos-norm</output> - </summer> - - <aerosurface_scale name="rudder position"> - <input>fcs/rudder-act</input> - - <range> - <min>-0.5236</min> - <max>0.5236</max> - </range> - <output>fcs/rudder-pos-rad</output> - </aerosurface_scale> - </channel> - - <channel name="Pitch"> - - <!-- + 0 33000 50000 + 160 -21.4844 -29.9948 -29.9948 + 270 -19.5573 -17.5259 -17.5259 + 400 -13.6930 -13.6930 -13.6930 + 580 -9.6423 -9.6423 -9.6423 + 700 -7.7903 -6.1197 -6.1197 + </tableData> + </table> + </product> + </sum> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> + <tableData> + 0 33000 50000 + 160 1 1.2 1.2 + 270 1 1.1 1.1 + 400 0.5 0.55 0.6 + 580 0.3 0.35 0.4 + 700 0.2 0.25 0.3 + </tableData> + </table> + <table> + <independentVar lookup="row">aero/alpha-deg</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> + <tableData> + 0 33000 50000 + -60 3 3.5 4 + -40 2 2.5 3 + -20 1.5 1.75 2 + 0 0.7 0.8 0.9 + 20 1.75 2 2.5 + 40 2.5 3 3.5 + 60 3 3.5 4 + 80 3.5 4 5 + </tableData> + </table> + </product> + </function> + <clipto> + <min>-5</min> + <max>5</max> + </clipto> + </fcs_function> + + <aerosurface_scale name="fcs/yaw-reg-scale"> + <input> fcs/yaw-cmd </input> + <domain> + <min> -5 </min> + <max> 5 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + </aerosurface_scale > + + <actuator name="fcs/rudder-act"> + <input> fcs/yaw-reg-scale</input> + <lag> 0 </lag> + <rate_limit> 2.673 </rate_limit> + + <clipto> + + <min> -1 </min> + <max> 1 </max> + </clipto> + </actuator> + + <summer name="fcs/rudder-pos-out"> + <input>fcs/rudder-act</input> + <input>fcs/speedbrake-rudder</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + <output>fcs/rudder-pos-norm</output> + </summer> + + <aerosurface_scale name="fcs/rudder-position"> + <input>fcs/rudder-act</input> + <range> + <min>-0.5236</min> + <max>0.5236</max> + </range> + <output>fcs/rudder-pos-rad</output> + </aerosurface_scale> + </channel> + + <channel name="Pitch"> + + <!-- - accelerations/n-pilot-z-norm has the disadvantage that it - has an offset of 1G when positioned horizontal (and -1G - when upside down). To calculate the difference between the @@ -781,738 +744,691 @@ - to be eliminated. The following function calculates an offset - to compensate for the earth's gravity. --> - <fcs_function name="n pilot z correction"> - <function> - <product> - <cos> - <property>attitude/pitch-rad</property> - </cos> - <cos> - <property>attitude/roll-rad</property> - </cos> - </product> - </function> - </fcs_function> - - <summer name="g load corrected"> - <input>accelerations/n-pilot-z-norm</input> - <input>-fcs/n-pilot-z-correction</input> - </summer> - - <pure_gain name="g load norm"> - <input>fcs/g-load-corrected</input> - <gain>-1.0</gain> - </pure_gain> - - <!-- Pilot stick filter --> - <lag_filter name="stick filter"> - <input>fcs/elevator-cmd-norm</input> - <c1>10</c1> - </lag_filter> - - <!-- Do not allow TVC to operate when gear is down! --> - <switch name="tvc inhibit"> - <default value="1"/> - <test logic="AND" value="0"> - gear/gear-pos-norm gt 0 - </test> - <output>fcs/tvc-inhibit</output> - </switch> - - - <summer name="elevator cmd limiter"> - <input>fcs/stick-filter</input> - <input>fcs/pitch-trim-cmd-norm</input> - <clipto> - <min>-1</min> - <max>0.6</max> - </clipto> - </summer> - - <!-- Limit pitch rate command based on altitude and mach. Max of +50/-30 deg/sec command --> - <fcs_function name="pitch cmd limiter"> - <function> - <table> - <independentVar lookup="row">velocities/mach</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> - <tableData> - 0 30000 60000 - 0 0.7 0.5236 0.349 - 0.2 0.8727 0.5236 0.349 - 0.4 0.8727 0.5236 0.349 - 0.6 0.8727 0.7 0.349 - 0.8 0.8727 0.7 0.349 - 1.0 0.7845 0.7 0.4363 - 1.2 0.611 0.611 0.4363 - 1.4 0.611 0.5236 0.349 - 1.6 0.5236 0.4363 0.349 - 1.8 0.4363 0.4363 0.349 - 2.0 0.349 0.349 0.349 - - </tableData> - </table> - </function> - </fcs_function> - - <pure_gain name="pitch rate cmd"> - <input>fcs/elevator-cmd-limiter</input> - <gain>-fcs/pitch-cmd-limiter</gain> - </pure_gain> - - <!-- G-limiter based on mach. +9.5/-3.5 G limit. --> - <fcs_function name="pitch cmd g limiter"> - <function> - <table> - <independentVar lookup="column">velocities/mach</independentVar> - <independentVar lookup="row">fcs/g-load-norm</independentVar> - <tableData> - 0 0.4 0.8 1.0 1.2 1.4 1.6 1.8 2.0 - -3.75 0 0 0 0 0 0 0 0 0 - -3.5 1 1 1 1 0 0 0 0 0 - -3.25 1 1 1 1 1 1 0 0 0 - -3.0 1 1 1 1 1 1 1 1 1 - 0 1 1 1 1 1 1 1 1 1 - 7 1 1 1 1 1 1 1 1 1 - 7.25 1 1 1 1 1 -.1 -.1 -.1 -.1 - 7.5 1 1 1 1 1 -.1 -.1 -.1 -.1 - 7.75 1 1 1 1 -.1 -.1 -.1 -.1 -.1 - 8.0 1 1 1 1 -.1 -.1 -.1 -.1 -.1 - 8.25 1 1 1 1 -.1 -.1 -.1 -.1 -.1 - 8.5 1 1 1 1 -.1 -.1 -.1 -.1 -.1 - 8.75 1 1 1 1 -.1 -.1 -.1 -.1 -.1 - 9.0 1 1 1 1 -.1 -.1 -.1 -.1 -.1 - 9.25 1 1 1 1 -.1 -.1 -.1 -.1 -.1 - 9.5 1 1 1 1 -.1 -.1 -.1 -.1 -.1 - 9.75 -.1 -.1 -.1 -.1 -.1 -.1 0 0 0 - 10.0 -1 -1 -1 -1 -1 -1 -1 -1 -1 - </tableData> - </table> - </function> - </fcs_function> - - <pure_gain name="g limiter"> - <input>fcs/pitch-rate-cmd</input> - <gain>fcs/pitch-cmd-g-limiter</gain> - <clipto> - <min>-0.5236</min> - <max>0.8727</max> - </clipto> - </pure_gain> - - <!-- Limit pitch rate command when gear is down--> - <switch name="gear down q limit"> - <default value="1"/> - <test logic="AND" value=".3"> - gear/gear-pos-norm gt 0 - </test> - </switch> - - <pure_gain name="q gear down limiter"> - <input>fcs/g-limiter</input> - <gain>fcs/gear-down-q-limit</gain> - <clipto> - <min>-0.5236</min> - <max>0.8727</max> - </clipto> - </pure_gain> - - - - <deadband name="pitch windup trigger"> - <input>fcs/pitch-rate-integrator</input> - <width>1.4</width> - <clipto> - <min>-0.5236</min> - <max>0.8727</max> - </clipto> - </deadband> - - <summer name="pitch rate error"> - <input>fcs/q-gear-down-limiter</input> - <input>-velocities/q-aero-rad_sec</input> - <input>-fcs/pitch-windup-trigger</input> + <fcs_function name="fcs/n-pilot-z-correction"> + <function> + <product> + <cos> + <property>attitude/pitch-rad</property> + </cos> + <cos> + <property>attitude/roll-rad</property> + </cos> + </product> + </function> + </fcs_function> + + <summer name="fcs/g-load-corrected"> + <input>accelerations/n-pilot-z-norm</input> + <input>-fcs/n-pilot-z-correction</input> </summer> - <integrator name="pitch rate integrator"> - <!--trigger>fcs/pitch-int-trigger</trigger--> - <input>fcs/pitch-rate-error</input> - <c1> 1 </c1> - <clipto> - <min>-0.5236</min> - <max>0.8727</max> - - </clipto> - <output>fcs/pitch-rate-integrator</output> - </integrator> - - <summer name="pitch cmd summer"> - <input>fcs/pitch-rate-integrator</input> - <!--input>fcs/pitch-rate-override</input--> + <pure_gain name="fcs/g-load-norm"> + <input>fcs/g-load-corrected</input> + <gain>-1.0</gain> + </pure_gain> + + <!-- Pilot stick filter --> + <lag_filter name="fcs/stick-filter"> + <input>fcs/elevator-cmd-norm</input> + <c1>10</c1> + </lag_filter> + + <!-- Do not allow TVC to operate when gear is down! --> + <switch name="fcs/tvc-inhibit"> + <default value="1"/> + <test logic="AND" value="0"> + gear/gear-pos-norm gt 0 + </test> + <output>fcs/tvc-inhibit</output> + </switch> + + <summer name="fcs/elevator-cmd-limiter"> + <input>fcs/stick-filter</input> + <input>fcs/pitch-trim-cmd-norm</input> + <clipto> + <min>-1</min> + <max>0.6</max> + </clipto> </summer> - - - <!-- Normalize the w-velocity to m/s --> - <pure_gain name="w velocity norm"> - <input>velocities/w-fps</input> - <gain>0.3048</gain> + + <!-- Limit pitch rate command based on altitude and mach. Max of +50/-30 deg/sec command --> + <fcs_function name="fcs/pitch-cmd-limiter"> + <function> + <table> + <independentVar lookup="row">velocities/mach</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> + <tableData> + 0 30000 60000 + 0 0.7 0.5236 0.349 + 0.2 0.8727 0.5236 0.349 + 0.4 0.8727 0.5236 0.349 + 0.6 0.8727 0.7 0.349 + 0.8 0.8727 0.7 0.349 + 1.0 0.7845 0.7 0.4363 + 1.2 0.611 0.611 0.4363 + 1.4 0.611 0.5236 0.349 + 1.6 0.5236 0.4363 0.349 + 1.8 0.4363 0.4363 0.349 + 2.0 0.349 0.349 0.349 + </tableData> + </table> + </function> + </fcs_function> + + <pure_gain name="fcs/pitch-rate-cmd"> + <input>fcs/elevator-cmd-limiter</input> + <gain>-fcs/pitch-cmd-limiter</gain> </pure_gain> + + <!-- G-limiter based on mach. +9.5/-3.5 G limit. --> + <fcs_function name="fcs/pitch-cmd-g-limiter"> + <function> + <table> + <independentVar lookup="column">velocities/mach</independentVar> + <independentVar lookup="row">fcs/g-load-norm</independentVar> + <tableData> + 0 0.4 0.8 1.0 1.2 1.4 1.6 1.8 2.0 + -3.75 0 0 0 0 0 0 0 0 0 + -3.5 1 1 1 1 0 0 0 0 0 + -3.25 1 1 1 1 1 1 0 0 0 + -3.0 1 1 1 1 1 1 1 1 1 + 0 1 1 1 1 1 1 1 1 1 + 7 1 1 1 1 1 1 1 1 1 + 7.25 1 1 1 1 1 -0.1 -0.1 -0.1 -0.1 + 7.5 1 1 1 1 1 -0.1 -0.1 -0.1 -0.1 + 7.75 1 1 1 1 -0.1 -0.1 -0.1 -0.1 -0.1 + 8.0 1 1 1 1 -0.1 -0.1 -0.1 -0.1 -0.1 + 8.25 1 1 1 1 -0.1 -0.1 -0.1 -0.1 -0.1 + 8.5 1 1 1 1 -0.1 -0.1 -0.1 -0.1 -0.1 + 8.75 1 1 1 1 -0.1 -0.1 -0.1 -0.1 -0.1 + 9.0 1 1 1 1 -0.1 -0.1 -0.1 -0.1 -0.1 + 9.25 1 1 1 1 -0.1 -0.1 -0.1 -0.1 -0.1 + 9.5 1 1 1 1 -0.1 -0.1 -0.1 -0.1 -0.1 + 9.75 -0.1 -0.1 -0.1 -0.1 -0.1 -0.1 0 0 0 + 10.0 -1 -1 -1 -1 -1 -1 -1 -1 -1 + </tableData> + </table> + </function> + </fcs_function> + + <pure_gain name="fcs/g-limiter"> + <input>fcs/pitch-rate-cmd</input> + <gain>fcs/pitch-cmd-g-limiter</gain> + <clipto> + <min>-0.5236</min> + <max>0.8727</max> + </clipto> + </pure_gain> + + <!-- Limit pitch rate command when gear is down--> + <switch name="fcs/gear-down-q-limit"> + <default value="1"/> + <test logic="AND" value=".3"> + gear/gear-pos-norm gt 0 + </test> + </switch> - <!-- LQR Tracker Integral elevator pitch rate controller--> - <fcs_function name="el pitch cmd"> - <function> - <sum> - <product> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">aero/alpha-deg</independentVar> - <tableData> - 19 25 35 - 90 1 1 1 - 180 1 1 1 - 200 1 1 1 - 215 1 1 1 - 230 1 1 1 - 380 1 1 1 - 500 1 1 1 - 900 1 1 1 - - </tableData> - </table> - - <property>fcs/pitch-cmd-summer</property> - <value>-0.5</value> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">aero/alpha-deg</independentVar> - <tableData> - 19 25 35 - 90 38.8840 25.9906 25.9906 - 180 38.8840 25.9906 25.9906 - 200 38.8840 25.9906 25.9906 - 215 58.8840 25.9906 25.9906 - 230 81.9605 58.8840 25.9906 - 380 63.4645 56.8517 34.4889 - 500 61.1371 58.5955 33.0386 - 900 48.8597 42.1147 42.1147 - - </tableData> - </table> - - </product> - - - <product> - <property>fcs/w-velocity-norm</property> - <value>0</value> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">aero/alpha-deg</independentVar> - <tableData> - 19 25 35 - 90 -0.0231 -0.0119 -0.0119 - 180 -0.0231 -0.0119 -0.0119 - 200 -0.0231 -0.0119 -0.0119 - 215 -0.0231 -0.0119 -0.0119 - 230 -0.0406 -0.0231 -0.0119 - 380 -0.0244 -0.0195 -0.0159 - 500 -0.0115 -0.0085 -0.0061 - 900 -0.0045 -0.0029 -0.0029 - - </tableData> - </table> - </product> - <product> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">aero/alpha-deg</independentVar> - <tableData> - 19 25 35 - 90 1 1 1 - 180 1 1 1 - 200 1 1 1 - 215 1 1 1 - 230 1 1 1 - 380 1 1 1 - 500 1 1 1 - 900 1 1 1 - - </tableData> - </table> - - <property>velocities/q-aero-rad_sec</property> - <value>-0.3</value> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">aero/alpha-deg</independentVar> - <tableData> - 19 25 35 - 90 -34.0297 -19.6316 -19.6316 - 180 -34.0297 -19.6316 -19.6316 - 200 -34.0297 -19.6316 -19.6316 - 215 -44.0297 -19.6316 -19.6316 - 230 -62.1151 -44.0297 -19.6316 - 380 -47.3350 -42.1836 -26.0436 - 500 -45.4195 -43.0593 -24.6616 - 900 -35.7627 -30.5733 -30.5733 - </tableData> - </table> - </product> - - </sum> - - </function> - <clipto> - <min>-5</min> - <max>5</max> - </clipto> - - </fcs_function> - - <aerosurface_scale name="el reg scale"> - <input> fcs/el-pitch-cmd </input> - <domain> - <min> -5 </min> - <max> 5 </max> - </domain> - <range> - <min> -1 </min> - <max> 1 </max> - </range> - </aerosurface_scale > - - - <actuator name="elevator act"> - <input> fcs/el-reg-scale</input> - <lag> 0.0 </lag> - <rate_limit> 2 </rate_limit> - - <clipto> - - <min> -1 </min> - <max> 1 </max> - </clipto> - <output>fcs/elevator-pos-norm</output> - </actuator> - - <aerosurface_scale name="elevator position"> - <input>fcs/elevator-pos-norm</input> - - <range> - <min>-0.5236</min> - <max>0.5236</max> - </range> - <output>fcs/elevator-pos-rad</output> - </aerosurface_scale> - - - <summer name="dht left pos rad"> - <input>-fcs/elevator-pos-rad</input> - <input>-fcs/left-aileron-pos-rad</input> - <clipto> - <min>-0.5236</min> - <max>0.5236</max> - </clipto> - </summer> - - <summer name="dht right pos rad"> - <input>fcs/elevator-pos-rad</input> - <input>fcs/right-aileron-pos-rad</input> - <clipto> - <min>-0.5236</min> - <max>0.5236</max> - </clipto> - </summer> - - <!-- Reduce TVC gains if AB is on--> - <switch name="tvc gain select"> - <default value="1"/> - <test logic="AND" value="0.6"> - fcs/throttle-pos-norm ge 0.99 - </test> - </switch> - - <!-- LQR Tracker Integral TVC pitch rate controller--> - <fcs_function name="tvc pitch cmd"> - <description>thrust vector control lqr regulator</description> - <function> - <product> - <sum> - - <product> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">aero/alpha-deg</independentVar> - <tableData> - 12 20 30 60 - 70 0.4 0.4 0.3 0.3 - 140 0.4 0.4 0.3 0.3 - 200 0.4 0.45 0.35 0.3 - 215 0.4 0.45 0.35 0.3 - 230 0.4 0.45 0.35 0.3 - 330 0.4 0.45 0.35 0.3 - 380 0.4 0.4 0.4 0.4 - 500 0.4 0.4 0.4 0.4 - 900 0.4 0.4 0.4 0.4 - </tableData> - </table> - <property>fcs/pitch-cmd-summer</property> - <value>-1</value> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">aero/alpha-deg</independentVar> - <independentVar lookup="table">position/h-sl-ft</independentVar> - <tableData breakPoint="-1000"> - 12 20 30 - 70 97.6705 95.6705 95.6705 - 140 97.6705 95.6705 95.6705 - 200 97.6705 95.6705 95.6705 - 215 67.9777 95.6705 95.6705 - 230 0 67.9777 95.6705 - 330 0 0 0 - 380 0 0 0 - 500 0 0 0 - 900 0 0 0 - - </tableData> - <tableData breakPoint="30000"> - 12 20 30 - 70 97.6705 95.6705 95.6705 - 140 97.6705 95.6705 95.6705 - 200 97.6705 95.6705 95.6705 - 215 67.9777 95.6705 95.6705 - 230 0 67.9777 95.6705 - 330 0 49.6594 70.1697 - 380 0 34.2680 34.2680 - 500 0 0 0 - 900 0 0 0 - - </tableData> - <tableData breakPoint="70000"> - 12 20 30 - 70 97.6705 95.6705 95.6705 - 140 97.6705 95.6705 95.6705 - 200 97.6705 95.6705 95.6705 - 215 67.9777 95.6705 95.6705 - 230 0 67.9777 95.6705 - 330 0 56.0773 75.1918 - 380 0 56.0773 75.1918 - 500 0 49.6594 70.1697 - 900 0 34.2680 34.2680 - - </tableData> - </table> - </product> - - - <product> - <property>fcs/w-velocity-norm</property> - <value>-0</value> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">aero/alpha-deg</independentVar> - <independentVar lookup="table">position/h-sl-ft</independentVar> - <tableData breakPoint="-1000"> - 12 20 30 - 70 -0.0444 -0.0444 -0.0444 - 140 -0.0444 -0.0444 -0.0444 - 200 -0.0444 -0.0444 -0.0444 - 215 -0.0271 -0.0444 -0.0444 - 230 0 -0.0271 -0.0444 - 330 0 0 0 - 380 0 0 0 - 500 0 0 0 - 900 0 0 0 - </tableData> - <tableData breakPoint="30000"> - 12 20 30 - 70 -0.0444 -0.0444 -0.0444 - 140 -0.0444 -0.0444 -0.0444 - 200 -0.0444 -0.0444 -0.0444 - 215 -0.0271 -0.0444 -0.0444 - 230 0 -0.0271 -0.0444 - 330 0 -0.0073 -0.0130 - 380 0 -0.0024 -0.0024 - 500 0 0 0 - 900 0 0 0 - - </tableData> - <tableData breakPoint="70000"> - 12 20 30 - 70 -0.0444 -0.0444 -0.0444 - 140 -0.0444 -0.0444 -0.0444 - 200 -0.0444 -0.0444 -0.0444 - 215 -0.0271 -0.0444 -0.0444 - 230 0 -0.0271 -0.0444 - 330 0 -0.0195 -0.0349 - 380 0 -0.0195 -0.0349 - 500 0 -0.0073 -0.0130 - 900 0 -0.0024 -0.0024 - - </tableData> - </table> - </product> - <product> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">aero/alpha-deg</independentVar> - <tableData> - 12 20 30 - 70 0.2 0.2 0.2 - 140 0.2 0.2 0.2 - 200 0.2 0.2 0.2 - 215 0.2 0.2 0.2 - 230 0.225 0.2 0.2 - 330 0.225 0.225 0.2 - 380 0.225 0.225 0.2 - 500 0.225 0.225 0.2 - 900 0.225 0.225 0.2 - </tableData> - </table> - - <property>velocities/q-aero-rad_sec</property> - <value>-1</value> - <table> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <independentVar lookup="column">aero/alpha-deg</independentVar> - <independentVar lookup="table">position/h-sl-ft</independentVar> - <tableData breakPoint="-1000"> - 12 20 30 - 70 -72.1205 -72.1205 -72.1205 - 140 -72.1205 -72.1205 -72.1205 - 200 -72.1205 -72.1205 -72.1205 - 215 -50.7416 -72.1205 -72.1205 - 230 0 -50.7416 -72.1205 - 330 0 0 0 - 380 0 0 0 - 500 0 0 0 - 900 0 0 0 - - </tableData> - <tableData breakPoint="30000"> - 12 20 30 - 70 -72.1205 -72.1205 -72.1205 - 140 -72.1205 -72.1205 -72.1205 - 200 -72.1205 -72.1205 -72.1205 - 215 -50.7416 -72.1205 -72.1205 - 230 0 -50.7416 -72.1205 - 330 0 -36.1358 -51.7437 - 380 0 -24.8715 -24.8715 - 500 0 0 0 - 900 0 0 0 - </tableData> - <tableData breakPoint="70000"> - 12 20 30 - 70 -72.1205 -72.1205 -72.1205 - 140 -72.1205 -72.1205 -72.1205 - 200 -72.1205 -72.1205 -72.1205 - 215 -50.7416 -72.1205 -72.1205 - 230 0 -50.7416 -72.1205 - 330 0 -41.5043 -56.5934 - 380 0 -41.5043 -56.5934 - 500 0 -36.1358 -51.7437 - 900 0 -24.8715 -24.8715 - - </tableData> - </table> - </product> - </sum> - <value>1</value> - - </product> - </function> - <clipto> - <min>-5</min> - <max>5</max> - </clipto> - </fcs_function> - - <!-- inhibit the tvc if gear down --> - <pure_gain name="tvc gain"> - <input>fcs/tvc-pitch-cmd</input> - <gain>fcs/tvc-inhibit</gain> + <pure_gain name="fcs/q-gear-down-limiter"> + <input>fcs/g-limiter</input> + <gain>fcs/gear-down-q-limit</gain> + <clipto> + <min>-0.5236</min> + <max>0.8727</max> + </clipto> </pure_gain> - <!-- reduce tvc gain for burner on --> - <pure_gain name="tvc gain hi lo"> - <input>fcs/tvc-gain</input> - <gain>1</gain> + <deadband name="fcs/pitch-windup-trigger"> + <input>fcs/pitch-rate-integrator</input> + <width>1.4</width> + <clipto> + <min>-0.5236</min> + <max>0.8727</max> + </clipto> + </deadband> + + <summer name="fcs/pitch-rate-error"> + <input>fcs/q-gear-down-limiter</input> + <input>-velocities/q-aero-rad_sec</input> + <input>-fcs/pitch-windup-trigger</input> + </summer> + + <integrator name="fcs/pitch-rate-integrator"> + <!--trigger>fcs/pitch-int-trigger</trigger--> + <input>fcs/pitch-rate-error</input> + <c1> 1 </c1> + <clipto> + <min>-0.5236</min> + <max>0.8727</max> + </clipto> + <output>fcs/pitch-rate-integrator</output> + </integrator> + + <summer name="fcs/pitch-cmd-summer"> + <input>fcs/pitch-rate-integrator</input> + <!--input>fcs/pitch-rate-override</input--> + </summer> + + <!-- Normalize the w-velocity to m/s --> + <pure_gain name="fcs/w-velocity-norm"> + <input>velocities/w-fps</input> + <gain>0.3048</gain> </pure_gain> + <!-- LQR Tracker Integral elevator pitch rate controller--> + <fcs_function name="fcs/el-pitch-cmd"> + <function> + <sum> + <product> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">aero/alpha-deg</independentVar> + <tableData> + 19 25 35 + 90 1 1 1 + 180 1 1 1 + 200 1 1 1 + 215 1 1 1 + 230 1 1 1 + 380 1 1 1 + 500 1 1 1 + 900 1 1 1 + </tableData> + </table> + + <property>fcs/pitch-cmd-summer</property> + <value>-0.5</value> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">aero/alpha-deg</independentVar> + <tableData> + 19 25 35 + 90 38.8840 25.9906 25.9906 + 180 38.8840 25.9906 25.9906 + 200 38.8840 25.9906 25.9906 + 215 58.8840 25.9906 25.9906 + 230 81.9605 58.8840 25.9906 + 380 63.4645 56.8517 34.4889 + 500 61.1371 58.5955 33.0386 + 900 48.8597 42.1147 42.1147 + </tableData> + </table> + </product> + <product> + <property>fcs/w-velocity-norm</property> + <value>0</value> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">aero/alpha-deg</independentVar> + <tableData> + 19 25 35 + 90 -0.0231 -0.0119 -0.0119 + 180 -0.0231 -0.0119 -0.0119 + 200 -0.0231 -0.0119 -0.0119 + 215 -0.0231 -0.0119 -0.0119 + 230 -0.0406 -0.0231 -0.0119 + 380 -0.0244 -0.0195 -0.0159 + 500 -0.0115 -0.0085 -0.0061 + 900 -0.0045 -0.0029 -0.0029 + </tableData> + </table> + </product> + <product> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">aero/alpha-deg</independentVar> + <tableData> + 19 25 35 + 90 1 1 1 + 180 1 1 1 + 200 1 1 1 + 215 1 1 1 + 230 1 1 1 + 380 1 1 1 + 500 1 1 1 + 900 1 1 1 + </tableData> + </table> + <property>velocities/q-aero-rad_sec</property> + <value>-0.3</value> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">aero/alpha-deg</independentVar> + <tableData> + 19 25 35 + 90 -34.0297 -19.6316 -19.6316 + 180 -34.0297 -19.6316 -19.6316 + 200 -34.0297 -19.6316 -19.6316 + 215 -44.0297 -19.6316 -19.6316 + 230 -62.1151 -44.0297 -19.6316 + 380 -47.3350 -42.1836 -26.0436 + 500 -45.4195 -43.0593 -24.6616 + 900 -35.7627 -30.5733 -30.5733 + </tableData> + </table> + </product> + </sum> + </function> + <clipto> + <min>-5</min> + <max>5</max> + </clipto> + </fcs_function> + + <aerosurface_scale name="fcs/el-reg-scale"> + <input> fcs/el-pitch-cmd </input> + <domain> + <min> -5 </min> + <max> 5 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + </aerosurface_scale > + + <actuator name="fcs/elevator-act"> + <input> fcs/el-reg-scale</input> + <lag> 0.0 </lag> + <rate_limit> 2 </rate_limit> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + <output>fcs/elevator-pos-norm</output> + </actuator> + + <aerosurface_scale name="fcs/elevator-position"> + <input>fcs/elevator-pos-norm</input> + <range> + <min>-0.5236</min> + <max>0.5236</max> + </range> + <output>fcs/elevator-pos-rad</output> + </aerosurface_scale> - <!--TVC used for trim in high altitude supersonic flight--> - <!-- Uses TVC to reduce trim setting of elevator for reduced drag--> - <fcs_function name="ss trim"> - - <function> - <product> - - <sum> - <product> - <value>7.0626</value> - <property>fcs/pitch-rate-integrator</property> - </product> - <product> - <value>-0.0019</value> - <property>fcs/u-velocity-norm</property> - </product> - <product> - <value>0.0083</value> - <property>fcs/w-velocity-norm</property> - </product> - <product> - <value>-5.1005</value> - <property>velocities/q-aero-rad_sec</property> - </product> - - </sum> - <table> - <independentVar lookup="row">velocities/mach</independentVar> - <independentVar lookup="column">position/h-sl-ft</independentVar> - <tableData> - 45000 50000 - 0.92 0 0 - 0.95 0 1.5 - 1.00 0 2.5 - 1.10 0 3.5 - 1.15 0 4 - 1.20 0 2.5 - 1.25 0 2 - 1.30 0 1.5 - 1.35 0 1.5 - 1.40 0 1 - 1.45 0 .9 - 1.50 0 .75 - 1.55 0 .7 - 1.60 0 .65 - 1.7 0 .6 - 1.8 0 .6 - 1.9 0 .6 - 2.0 0 .6 - </tableData> - </table> - </product> - </function> - <clipto> - <min>-0.7</min> - <max>0.05</max> - </clipto> - - </fcs_function> - - <!-- In situations where TVC control is not called for, disable TVC SS Trim if manuevering--> - <fcs_function name="ss trim override"> - <function> - <table> - <independentVar lookup="row">velocities/q-aero-rad_sec</independentVar> - <tableData> - -0.15 0 - -0.1 1 - 0.0 1 - 0.1 1 - 0.15 0 - </tableData> - </table> - </function> - </fcs_function> - - <!-- inhibit the ss trim if manuevering--> - <pure_gain name="ss trim gain"> - <input>fcs/ss-trim</input> - <gain>fcs/ss-trim-override</gain> - </pure_gain> - - - <summer name="tvc summer"> - <input>fcs/tvc-gain-hi-lo</input> - <input>fcs/ss-trim-gain</input> - </summer> - - <aerosurface_scale name="tvc reg scale"> - <input> fcs/tvc-summer</input> - <domain> - <min> -5 </min> - <max> 5 </max> - </domain> - <range> - <min> -1 </min> - <max> 1 </max> - </range> - </aerosurface_scale > - - - <actuator name="tvc act"> - <input> fcs/tvc-reg-scale</input> - <lag> 0.00 </lag> - <rate_limit> 2 </rate_limit> - - <clipto> - - <min> -1 </min> - <max> 1 </max> - </clipto> - <output>fcs/tvc-pos-norm</output> - </actuator> - - - - <aerosurface_scale name="tvc position"> - <input>fcs/tvc-pos-norm</input> - - <range> - <min>-0.349</min> - <max>0.349</max> - </range> - <output>fcs/tvc-pos-rad</output> - </aerosurface_scale> + <summer name="fcs/dht-left-pos-rad"> + <input>-fcs/elevator-pos-rad</input> + <input>-fcs/left-aileron-pos-rad</input> + <clipto> + <min>-0.5236</min> + <max>0.5236</max> + </clipto> + </summer> + + <summer name="fcs/dht-right-pos-rad"> + <input>fcs/elevator-pos-rad</input> + <input>fcs/right-aileron-pos-rad</input> + <clipto> + <min>-0.5236</min> + <max>0.5236</max> + </clipto> + </summer> + + <!-- Reduce TVC gains if AB is on--> + <switch name="fcs/tvc-gain-select"> + <default value="1"/> + <test logic="AND" value="0.6"> + fcs/throttle-pos-norm ge 0.99 + </test> + </switch> + + <!-- LQR Tracker Integral TVC pitch rate controller--> + <fcs_function name="fcs/tvc-pitch-cmd"> + <description>thrust vector control lqr regulator</description> + <function> + <product> + <sum> + <product> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">aero/alpha-deg</independentVar> + <tableData> + 12 20 30 60 + 70 0.4 0.4 0.3 0.3 + 140 0.4 0.4 0.3 0.3 + 200 0.4 0.45 0.35 0.3 + 215 0.4 0.45 0.35 0.3 + 230 0.4 0.45 0.35 0.3 + 330 0.4 0.45 0.35 0.3 + 380 0.4 0.4 0.4 0.4 + 500 0.4 0.4 0.4 0.4 + 900 0.4 0.4 0.4 0.4 + </tableData> + </table> + <property>fcs/pitch-cmd-summer</property> + <value>-1</value> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">aero/alpha-deg</independentVar> + <independentVar lookup="table">position/h-sl-ft</independentVar> + <tableData breakPoint="-1000"> + 12 20 30 + 70 97.6705 95.6705 95.6705 + 140 97.6705 95.6705 95.6705 + 200 97.6705 95.6705 95.6705 + 215 67.9777 95.6705 95.6705 + 230 0 67.9777 95.6705 + 330 0 0 0 + 380 0 0 0 + 500 0 0 0 + 900 0 0 0 + </tableData> + <tableData breakPoint="30000"> + 12 20 30 + 70 97.6705 95.6705 95.6705 + 140 97.6705 95.6705 95.6705 + 200 97.6705 95.6705 95.6705 + 215 67.9777 95.6705 95.6705 + 230 0 67.9777 95.6705 + 330 0 49.6594 70.1697 + 380 0 34.2680 34.2680 + 500 0 0 0 + 900 0 0 0 + </tableData> + <tableData breakPoint="70000"> + 12 20 30 + 70 97.6705 95.6705 95.6705 + 140 97.6705 95.6705 95.6705 + 200 97.6705 95.6705 95.6705 + 215 67.9777 95.6705 95.6705 + 230 0 67.9777 95.6705 + 330 0 56.0773 75.1918 + 380 0 56.0773 75.1918 + 500 0 49.6594 70.1697 + 900 0 34.2680 34.2680 + </tableData> + </table> + </product> + <product> + <property>fcs/w-velocity-norm</property> + <value>-0</value> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">aero/alpha-deg</independentVar> + <independentVar lookup="table">position/h-sl-ft</independentVar> + <tableData breakPoint="-1000"> + 12 20 30 + 70 -0.0444 -0.0444 -0.0444 + 140 -0.0444 -0.0444 -0.0444 + 200 -0.0444 -0.0444 -0.0444 + 215 -0.0271 -0.0444 -0.0444 + 230 0 -0.0271 -0.0444 + 330 0 0 0 + 380 0 0 0 + 500 0 0 0 + 900 0 0 0 + </tableData> + <tableData breakPoint="30000"> + 12 20 30 + 70 -0.0444 -0.0444 -0.0444 + 140 -0.0444 -0.0444 -0.0444 + 200 -0.0444 -0.0444 -0.0444 + 215 -0.0271 -0.0444 -0.0444 + 230 0 -0.0271 -0.0444 + 330 0 -0.0073 -0.0130 + 380 0 -0.0024 -0.0024 + 500 0 0 0 + 900 0 0 0 + </tableData> + <tableData breakPoint="70000"> + 12 20 30 + 70 -0.0444 -0.0444 -0.0444 + 140 -0.0444 -0.0444 -0.0444 + 200 -0.0444 -0.0444 -0.0444 + 215 -0.0271 -0.0444 -0.0444 + 230 0 -0.0271 -0.0444 + 330 0 -0.0195 -0.0349 + 380 0 -0.0195 -0.0349 + 500 0 -0.0073 -0.0130 + 900 0 -0.0024 -0.0024 + </tableData> + </table> + </product> + <product> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">aero/alpha-deg</independentVar> + <tableData> + 12 20 30 + 70 0.2 0.2 0.2 + 140 0.2 0.2 0.2 + 200 0.2 0.2 0.2 + 215 0.2 0.2 0.2 + 230 0.225 0.2 0.2 + 330 0.225 0.225 0.2 + 380 0.225 0.225 0.2 + 500 0.225 0.225 0.2 + 900 0.225 0.225 0.2 + </tableData> + </table> + <property>velocities/q-aero-rad_sec</property> + <value>-1</value> + <table> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <independentVar lookup="column">aero/alpha-deg</independentVar> + <independentVar lookup="table">position/h-sl-ft</independentVar> + <tableData breakPoint="-1000"> + 12 20 30 + 70 -72.1205 -72.1205 -72.1205 + 140 -72.1205 -72.1205 -72.1205 + 200 -72.1205 -72.1205 -72.1205 + 215 -50.7416 -72.1205 -72.1205 + 230 0 -50.7416 -72.1205 + 330 0 0 0 + 380 0 0 0 + 500 0 0 0 + 900 0 0 0 + </tableData> + <tableData breakPoint="30000"> + 12 20 30 + 70 -72.1205 -72.1205 -72.1205 + 140 -72.1205 -72.1205 -72.1205 + 200 -72.1205 -72.1205 -72.1205 + 215 -50.7416 -72.1205 -72.1205 + 230 0 -50.7416 -72.1205 + 330 0 -36.1358 -51.7437 + 380 0 -24.8715 -24.8715 + 500 0 0 0 + 900 0 0 0 + </tableData> + <tableData breakPoint="70000"> + 12 20 30 + 70 -72.1205 -72.1205 -72.1205 + 140 -72.1205 -72.1205 -72.1205 + 200 -72.1205 -72.1205 -72.1205 + 215 -50.7416 -72.1205 -72.1205 + 230 0 -50.7416 -72.1205 + 330 0 -41.5043 -56.5934 + 380 0 -41.5043 -56.5934 + 500 0 -36.1358 -51.7437 + 900 0 -24.8715 -24.8715 + </tableData> + </table> + </product> + </sum> + <value>1</value> + </product> + </function> + <clipto> + <min>-5</min> + <max>5</max> + </clipto> + </fcs_function> + + <!-- inhibit the tvc if gear down --> + <pure_gain name="fcs/tvc-gain"> + <input>fcs/tvc-pitch-cmd</input> + <gain>fcs/tvc-inhibit</gain> + </pure_gain> + + <!-- reduce tvc gain for burner on --> + <pure_gain name="fcs/tvc-gain-hi-lo"> + <input>fcs/tvc-gain</input> + <gain>1</gain> + </pure_gain> + + <!--TVC used for trim in high altitude supersonic flight--> + <!-- Uses TVC to reduce trim setting of elevator for reduced drag--> + <fcs_function name="fcs/ss-trim"> + <function> + <product> + <sum> + <product> + <value>7.0626</value> + <property>fcs/pitch-rate-integrator</property> + </product> + <product> + <value>-0.0019</value> + <property>fcs/u-velocity-norm</property> + </product> + <product> + <value>0.0083</value> + <property>fcs/w-velocity-norm</property> + </product> + <product> + <value>-5.1005</value> + <property>velocities/q-aero-rad_sec</property> + </product> + </sum> + <table> + <independentVar lookup="row">velocities/mach</independentVar> + <independentVar lookup="column">position/h-sl-ft</independentVar> + <tableData> + 45000 50000 + 0.92 0 0 + 0.95 0 1.5 + 1.00 0 2.5 + 1.10 0 3.5 + 1.15 0 4 + 1.20 0 2.5 + 1.25 0 2 + 1.30 0 1.5 + 1.35 0 1.5 + 1.40 0 1 + 1.45 0 0.9 + 1.50 0 0.75 + 1.55 0 0.7 + 1.60 0 0.65 + 1.7 0 0.6 + 1.8 0 0.6 + 1.9 0 0.6 + 2.0 0 0.6 + </tableData> + </table> + </product> + </function> + <clipto> + <min>-0.7</min> + <max>0.05</max> + </clipto> + </fcs_function> + + <!-- In situations where TVC control is not called for, disable TVC SS Trim if manuevering--> + <fcs_function name="fcs/ss-trim-override"> + <function> + <table> + <independentVar lookup="row">velocities/q-aero-rad_sec</independentVar> + <tableData> + -0.15 0 + -0.1 1 + 0.0 1 + 0.1 1 + 0.15 0 + </tableData> + </table> + </function> + </fcs_function> + + <!-- inhibit the ss trim if manuevering--> + <pure_gain name="fcs/ss-trim-gain"> + <input>fcs/ss-trim</input> + <gain>fcs/ss-trim-override</gain> + </pure_gain> + + <summer name="fcs/tvc-summer"> + <input>fcs/tvc-gain-hi-lo</input> + <input>fcs/ss-trim-gain</input> + </summer> + + <aerosurface_scale name="fcs/tvc-reg-scale"> + <input> fcs/tvc-summer</input> + <domain> + <min> -5 </min> + <max> 5 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + </aerosurface_scale > + + <actuator name="fcs/tvc-act"> + <input> fcs/tvc-reg-scale</input> + <lag> 0.00 </lag> + <rate_limit> 2 </rate_limit> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + <output>fcs/tvc-pos-norm</output> + </actuator> + + <aerosurface_scale name="fcs/tvc-position"> + <input>fcs/tvc-pos-norm</input> + <range> + <min>-0.349</min> + <max>0.349</max> + </range> + <output>fcs/tvc-pos-rad</output> + </aerosurface_scale> </channel> <channel name="Leading Edge Flap"> - <pure_gain name="lef alpha gain"> - <input>aero/alpha-deg</input> - <gain>1.38</gain> - </pure_gain> - - <lead_lag_filter name="lef alpha filter"> - <input>fcs/lef-alpha-gain</input> - <c1> 2 </c1> - <c2> 7.25 </c2> - <c3> 1 </c3> - <c4> 7.25 </c4> - </lead_lag_filter> - - <fcs_function name="lef transfer function"> - <function> - <description>leading edge flap control function</description> - <sum> - <property> fcs/lef-alpha-filter </property> - <product> - <quotient> - <property>aero/qbar-psf</property> - <property>atmosphere/P-psf</property> - </quotient> - <value>-9.05</value> - </product> - <value>1.45</value> - </sum> - - </function> - </fcs_function> + <pure_gain name="fcs/lef-alpha-gain"> + <input>aero/alpha-deg</input> + <gain>1.38</gain> + </pure_gain> + + <lead_lag_filter name="fcs/lef-alpha-filter"> + <input>fcs/lef-alpha-gain</input> + <c1> 2 </c1> + <c2> 7.25 </c2> + <c3> 1 </c3> + <c4> 7.25 </c4> + </lead_lag_filter> + + <fcs_function name="fcs/lef-transfer-function"> + <function> + <description>leading edge flap control function</description> + <sum> + <property> fcs/lef-alpha-filter </property> + <product> + <quotient> + <property>aero/qbar-psf</property> + <property>atmosphere/P-psf</property> + </quotient> + <value>-9.05</value> + </product> + <value>1.45</value> + </sum> + </function> + </fcs_function> - <pure_gain name="lef deg to rad"> - <input>fcs/lef-transfer-function</input> - <gain>0.01745</gain> - <clipto> - <min> -0.001 </min> - <max> 0.6108 </max> - </clipto> - </pure_gain> - - <switch name="lef pos"> + <pure_gain name="fcs/lef-deg-to-rad"> + <input>fcs/lef-transfer-function</input> + <gain>0.01745</gain> + <clipto> + <min> -0.001 </min> + <max> 0.6108 </max> + </clipto> + </pure_gain> + + <switch name="fcs/lef-pos"> <default value="0.0"/> <test logic="AND" value="0"> - fcs/gear-wow eq 1 + gear/wow eq 1 gear/gear-pos-norm gt 0 </test> <test value="fcs/lef-deg-to-rad"> @@ -1523,235 +1439,221 @@ </test> </switch> - <pure_gain name="lef norm"> - <input>fcs/lef-pos</input> - <gain>1.637197</gain> - + <pure_gain name="fcs/lef-norm"> + <input>fcs/lef-pos</input> + <gain>1.637197</gain> </pure_gain> - <kinematic name="lef control"> + <kinematic name="fcs/lef-control"> <input>fcs/lef-norm</input> <traverse> - <setting> + <setting> <position>-1.0</position> <time>0.55</time> </setting> - <setting> <position>1.0</position> <time>0.55</time> </setting> </traverse> - <output>fcs/lef-pos-norm</output> + <output>fcs/lef-pos-norm</output> </kinematic> - <aerosurface_scale name="lef deg"> - <input>fcs/lef-control</input> - <domain> - <min>-1.0</min> - <max>1.0</max> - </domain> - <range> - <min>0</min> - <max>35</max> - </range> - <output>fcs/lef-pos-deg</output> + <aerosurface_scale name="fcs/lef-deg"> + <input>fcs/lef-control</input> + <domain> + <min>-1.0</min> + <max>1.0</max> + </domain> + <range> + <min>0</min> + <max>35</max> + </range> + <output>fcs/lef-pos-deg</output> </aerosurface_scale> - <aerosurface_scale name="lef pos rad"> - <input>fcs/lef-control</input> - <domain> - <min>-1.0</min> - <max>1.0</max> - </domain> - <range> - <min>0</min> - <max>0.6108</max> - </range> - <output>fcs/lef-pos-rad</output> - </aerosurface_scale> - + <aerosurface_scale name="fcs/lef-pos-rad"> + <input>fcs/lef-control</input> + <domain> + <min>-1.0</min> + <max>1.0</max> + </domain> + <range> + <min>0</min> + <max>0.6108</max> + </range> + <output>fcs/lef-pos-rad</output> + </aerosurface_scale> </channel> <channel name="Throttle"> - <!--FADEC function to automatically add throttle in post stall conditions for TVC pitch authority--> - <fcs_function name="throttle adjust"> - <function> - <table> - <independentVar lookup="column">aero/alpha-deg</independentVar> - <independentVar lookup="row">velocities/vc-kts</independentVar> - <tableData> - 0 20 30 40 50 - 0 0.85 0.9 .98 1 1 - 50 0.8 0.85 0.95 1 1 - 60 0.75 0.65 0.93 1 1 - 70 0.7 0.55 0.9 .98 1 - 80 0.65 0.5 0.85 .98 1 - 90 0.6 0.7 0.8 .95 1 - 100 0.55 0.65 0.75 .85 1 - 110 0.4 0.5 0.6 .65 1 - 120 0.2 0.3 0.35 .35 1 - 130 0.1 0.2 0.25 .25 .5 - 1000 0.1 0.1 0.2 .25 .5 - </tableData> - </table> - </function> - </fcs_function> - - <pure_gain name="throttle gain"> - <input>fcs/throttle-adjust</input> - <gain>fcs/tvc-inhibit</gain> - <output>fcs/throttle-override</output> - </pure_gain> - - <!-- Throttle filter --> - <lag_filter name="throttle filter"> - <input>fcs/throttle-cmd-norm</input> - <c1>1</c1> - </lag_filter> - - - <summer name="t1 summer"> - <input>fcs/throttle-filter</input> - <!--input>fcs/throttle-override</input--> - <clipto> - <min>fcs/throttle-override</min> - <max>1</max> - </clipto> - - </summer> - - <pure_gain name="Throttle1"> + <!--FADEC function to automatically add throttle in post stall conditions for TVC pitch authority--> + <fcs_function name="fcs/throttle-adjust"> + <function> + <table> + <independentVar lookup="column">aero/alpha-deg</independentVar> + <independentVar lookup="row">velocities/vc-kts</independentVar> + <tableData> + 0 20 30 40 50 + 0 0.85 0.9 0.98 1 1 + 50 0.8 0.85 0.95 1 1 + 60 0.75 0.65 0.93 1 1 + 70 0.7 0.55 0.9 0.98 1 + 80 0.65 0.5 0.85 0.98 1 + 90 0.6 0.7 0.8 0.95 1 + 100 0.55 0.65 0.75 0.85 1 + 110 0.4 0.5 0.6 0.65 1 + 120 0.2 0.3 0.35 0.35 1 + 130 0.1 0.2 0.25 0.25 0.5 + 1000 0.1 0.1 0.2 0.25 0.5 + </tableData> + </table> + </function> + </fcs_function> + + <pure_gain name="fcs/throttle-gain"> + <input>fcs/throttle-adjust</input> + <gain>fcs/tvc-inhibit</gain> + <output>fcs/throttle-override</output> + </pure_gain> + + <!-- Throttle filter --> + <lag_filter name="fcs/throttle-filter"> + <input>fcs/throttle-cmd-norm</input> + <c1>1</c1> + </lag_filter> + + <summer name="fcs/t1-summer"> + <input>fcs/throttle-filter</input> + <!--input>fcs/throttle-override</input--> + <clipto> + <min>fcs/throttle-override</min> + <max>1</max> + </clipto> + </summer> + + <pure_gain name="fcs/throttle1"> <input>fcs/t1-summer</input> <gain>1.001</gain> - <output>fcs/throttle-pos-norm</output> - </pure_gain> - - <!-- Throttle filter --> - <lag_filter name="throttle1 filter"> - <input>fcs/throttle-cmd-norm[1]</input> - <c1>1</c1> - </lag_filter> - - - <summer name="T2 summer"> - <input>fcs/throttle1-filter</input> - <!--input>fcs/throttle-override</input--> - <clipto> - <min>fcs/throttle-override</min> - <max>1</max> - </clipto> - - </summer> - - <pure_gain name="Throttle2"> - <input>fcs/t2-summer</input> - <gain>1.001</gain> - <output>fcs/throttle-pos-norm[1]</output> - </pure_gain> - - <!-- Needed to compute TVC pitch moment contribution--> - <fcs_function name="thrust normalized"> - <description>Normalized thrust output</description> - <function> - <quotient> - <property>propulsion/engine/thrust-lbs</property> - <value>26550</value> - </quotient> - </function> - <clipto> - <min> 0 </min> - <max> 1.5 </max> - </clipto> - <output>fcs/thrust-norm</output> - </fcs_function> - + <output>fcs/throttle-pos-norm</output> + </pure_gain> + + <!-- Throttle filter --> + <lag_filter name="fcs/throttle1-filter"> + <input>fcs/throttle-cmd-norm[1]</input> + <c1>1</c1> + </lag_filter> + + <summer name="fcs/t2-summer"> + <input>fcs/throttle1-filter</input> + <!--input>fcs/throttle-override</input--> + <clipto> + <min>fcs/throttle-override</min> + <max>1</max> + </clipto> + </summer> + + <pure_gain name="fcs/throttle2"> + <input>fcs/t2-summer</input> + <gain>1.001</gain> + <output>fcs/throttle-pos-norm[1]</output> + </pure_gain> + + <!-- Needed to compute TVC pitch moment contribution--> + <fcs_function name="fcs/thrust-normalized"> + <description>Normalized thrust output</description> + <function> + <quotient> + <property>propulsion/engine/thrust-lbs</property> + <value>26550</value> + </quotient> + </function> + <clipto> + <min> 0 </min> + <max> 1.5 </max> + </clipto> + <output>fcs/thrust-norm</output> + </fcs_function> + </channel> - + <channel name="Flaps"> - <switch name="tef pos"> + <switch name="fcs/tef-pos"> <default value="0.0"/> - - <test logic="AND" value="1"> + <test logic="AND" value="1"> velocities/vc-kts lt 180 - velocities/mach lt 0.4 + velocities/mach lt 0.4 </test> <test logic="AND" value="0.5235"> velocities/vc-kts lt 200 - velocities/mach lt 0.45 + velocities/mach lt 0.45 </test> - <test logic="AND" value="0.26175"> velocities/vc-kts lt 225 - velocities/mach lt 0.5 + velocities/mach lt 0.5 </test> - <test logic="AND" value="0.13"> + <test logic="AND" value="0.13"> velocities/vc-kts lt 240 - velocities/mach lt 0.55 + velocities/mach lt 0.55 </test> - <test logic="AND" value="0.065"> + <test logic="AND" value="0.065"> velocities/vc-kts lt 255 - velocities/mach lt 0.6 + velocities/mach lt 0.6 </test> - </switch> - <pure_gain name="tef norm"> - <input>fcs/tef-pos</input> - <gain>1.91</gain> + <pure_gain name="fcs/tef-norm"> + <input>fcs/tef-pos</input> + <gain>1.91</gain> </pure_gain> - <kinematic name="flap controller"> + <kinematic name="fcs/flap-controller"> <input>fcs/tef-norm</input> <traverse> <setting> <position>0</position> <time>0</time> </setting> - - <setting> - <position>0.5</position> - <time>3.0</time> - </setting> - + <setting> + <position>0.5</position> + <time>3.0</time> + </setting> <setting> <position>1.0</position> <time>3.0</time> </setting> </traverse> - <output>fcs/flap-pos-norm</output> + <output>fcs/flap-pos-norm</output> </kinematic> + + <summer name="fcs/flap-pos-out"> + <input>fcs/flap-controller</input> + <input>fcs/speedbrake-flap</input> + <clipto> + <min> 0 </min> + <max> 1 </max> + </clipto> + </summer> - - <summer name="flap pos out"> - <input>fcs/flap-controller</input> - <input>fcs/speedbrake-flap</input> - <clipto> - - <min> 0 </min> - <max> 1 </max> - </clipto> - </summer> - - <aerosurface_scale name="flap pos deg"> - <input>fcs/flap-pos-out</input> - <domain> - <min>0</min> - <max>1.0</max> - </domain> - <range> - <min>0</min> - <max>30</max> - </range> - <output>fcs/tef-pos-deg</output> + <aerosurface_scale name="fcs/tef-pos-deg"> + <input>fcs/flap-pos-out</input> + <domain> + <min>0</min> + <max>1.0</max> + </domain> + <range> + <min>0</min> + <max>30</max> + </range> + <output>fcs/flap-pos-deg</output> </aerosurface_scale> </channel> -<!-- Speedbrake currently borrowed from F-16 --> + <!-- Speedbrake currently borrowed from F-16 --> <channel name="Speedbrake"> <!-- - To prevent deep stall the Flight Computer commands speedbrake @@ -1759,7 +1661,7 @@ - will provide just enough pitch down moment to keep the aircraft - under control. --> - <switch name="speedbrake alpha limiter"> + <switch name="fcs/speedbrake-alpha-limiter"> <default value="0"/> <test logic="AND" value="1"> aero/alpha-deg ge 120 @@ -1767,7 +1669,7 @@ </test> </switch> - <switch name="speedbrake initiate"> + <switch name="fcs/speedbrake-initiate"> <default value="0"/> <test logic="OR" value="1"> fcs/speedbrake-alpha-limiter eq 1 @@ -1775,7 +1677,7 @@ </test> </switch> - <kinematic name="Speedbrake Control"> + <kinematic name="fcs/speedbrake-control"> <input>fcs/speedbrake-initiate</input> <traverse> <setting> @@ -1790,57 +1692,50 @@ <output>fcs/speedbrake-pos-deg</output> </kinematic> - <aerosurface_scale name="Speedbrake Position Normalizer"> - <input>fcs/speedbrake-control</input> - <domain> - <min>0</min> - <max>60</max> - </domain> - <range> - <min>0</min> - <max>1</max> - </range> - <output>fcs/speedbrake-pos-norm</output> + <aerosurface_scale name="fcs/speedbrake-position-normalizer"> + <input>fcs/speedbrake-control</input> + <domain> + <min>0</min> + <max>60</max> + </domain> + <range> + <min>0</min> + <max>1</max> + </range> + <output>fcs/speedbrake-pos-norm</output> </aerosurface_scale> - <!-- F-22 uses flaps, ailerons and rudders for speedbrakes. Outputs are used to animate surfaces during speedbrake deployment--> - <pure_gain name="speedbrake-aileron"> - <input>fcs/speedbrake-pos-norm</input> - <gain>-1</gain> - <output>fcs/speedbrake-aileron</output> - </pure_gain> - - <pure_gain name="speedbrake-ail-right"> - <input>fcs/speedbrake-pos-norm</input> - <gain>-1</gain> - <output>fcs/speedbrake-aileron-right</output> - </pure_gain> - - <pure_gain name="speedbrake-rudder"> - <input>fcs/speedbrake-pos-norm</input> - <gain>1</gain> - <output>fcs/speedbrake-rudder</output> - </pure_gain> - - <pure_gain name="speedbrake-flaps"> - <input>fcs/speedbrake-pos-norm</input> - <gain>1</gain> - <output>fcs/speedbrake-flap</output> - </pure_gain> + <!-- F-22 uses flaps, ailerons and rudders for speedbrakes. Outputs are + used to animate surfaces during speedbrake deployment--> + <pure_gain name="fcs/speedbrake-aileron"> + <input>fcs/speedbrake-pos-norm</input> + <gain>-1</gain> + <output>fcs/speedbrake-aileron</output> + </pure_gain> + + <pure_gain name="fcs/speedbrake-ail-right"> + <input>fcs/speedbrake-pos-norm</input> + <gain>-1</gain> + <output>fcs/speedbrake-aileron-right</output> + </pure_gain> + + <pure_gain name="fcs/speedbrake-rudder"> + <input>fcs/speedbrake-pos-norm</input> + <gain>1</gain> + <output>fcs/speedbrake-rudder</output> + </pure_gain> + + <pure_gain name="fcs/speedbrake-flaps"> + <input>fcs/speedbrake-pos-norm</input> + <gain>1</gain> + <output>fcs/speedbrake-flap</output> + </pure_gain> </channel> <channel name="Landing Gear"> - <switch name="gear-wow"> - <default value="0"/> - <test logic="AND" value="1"> - gear/unit[1]/WOW eq 1 - gear/unit[2]/WOW eq 1 - </test> - </switch> - - <kinematic name="Gear Control"> + <kinematic name="fcs/gear-control"> <input>gear/gear-cmd-norm</input> <traverse> <setting> @@ -1855,7 +1750,7 @@ <output>gear/gear-pos-norm</output> </kinematic> - <scheduled_gain name="Scheduled Steer Pos Deg"> + <scheduled_gain name="fcs/scheduled-steer-pos-deg"> <input>fcs/steer-cmd-norm</input> <table> <independentVar>velocities/vg-fps</independentVar> @@ -1871,168 +1766,177 @@ </channel> </flight_control> - <aerodynamics> - - <!-- Shift the aero ref point aft. F-22 is 10% unstable at subsonic, stable at around Mach 1.2+ --> - <aero_ref_pt_shift_x> - <function> - <table> - <independentVar>velocities/mach</independentVar> - <tableData> - 0.0000 0.0000 - 0.6000 0.01 - 0.8000 0.025 - 0.9000 0.035 - 1.0000 0.045 - 1.1000 0.1 - 1.2000 0.105 - 1.3000 0.11 - - </tableData> + + <aerodynamics> + + <!-- Shift the aero ref point aft. F-22 is 10% unstable at subsonic, stable at around Mach 1.2+ --> + <aero_ref_pt_shift_x> + <function> + <table> + <independentVar>velocities/mach</independentVar> + <tableData> + 0.0000 0.0000 + 0.6000 0.01 + 0.8000 0.025 + 0.9000 0.035 + 1.0000 0.045 + 1.1000 0.1 + 1.2000 0.105 + 1.3000 0.11 + </tableData> + </table> + </function> + </aero_ref_pt_shift_x> + + <function name="aero/function/kCLge"> + <description>Change_in_lift_due_to_ground_effect</description> + <product> + <table> + <independentVar>aero/h_b-mac-ft</independentVar> + <tableData> + 0.0000 1.3893 + 0.1000 1.2108 + 0.1500 1.1972 + 0.2000 1.2108 + 0.3000 1.1785 + 0.4000 1.0697 + 0.5000 1.0578 + 0.6000 1.0323 + 0.7000 1.0136 + 0.8000 1.0051 + 0.9000 1.0017 + 1.0000 1.0000 + 1.1000 1.0000 + </tableData> + </table> + </product> + </function> + + <function name="aero/function/kCDge"> + <description>Change_in_drag_due_to_ground_effect</description> + <product> + <table> + <independentVar>aero/h_b-mac-ft</independentVar> + <tableData> + 0.0000 0.5235 + 0.1000 0.4759 + 0.1500 0.5250 + 0.2000 0.5388 + 0.3000 0.5924 + 0.4000 0.6471 + 0.5000 0.6941 + 0.6000 0.7624 + 0.7000 0.8253 + 0.8000 0.8812 + 0.9000 0.9412 + 1.0000 1.0000 + 1.1000 1.0000 + </tableData> + </table> + </product> + </function> + + <axis name="DRAG"> + + <function name="aero/coefficient/CD0"> + <description>Drag_at_zero_lift</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/function/kCDge</property> + <table> + <independentVar>aero/alpha-rad</independentVar> + <tableData> + -1.5700 1.5000 + -0.2600 0.0480 + 0.0000 0.00820 + 0.2600 0.0480 + 1.5700 1.5000 + </tableData> </table> - </function> - </aero_ref_pt_shift_x> - - <function name="aero/function/kCLge"> - <description>Change_in_lift_due_to_ground_effect</description> - <product> - <table> - <independentVar>aero/h_b-mac-ft</independentVar> - <tableData> - 0.0000 1.3893 - 0.1000 1.2108 - 0.1500 1.1972 - 0.2000 1.2108 - 0.3000 1.1785 - 0.4000 1.0697 - 0.5000 1.0578 - 0.6000 1.0323 - 0.7000 1.0136 - 0.8000 1.0051 - 0.9000 1.0017 - 1.0000 1.0000 - 1.1000 1.0000 - </tableData> - </table> - </product> - </function> - <function name="aero/function/kCDge"> - <description>Change_in_drag_due_to_ground_effect</description> - <product> - <table> - <independentVar>aero/h_b-mac-ft</independentVar> - <tableData> - 0.0000 0.5235 - 0.1000 0.4759 - 0.1500 0.5250 - 0.2000 0.5388 - 0.3000 0.5924 - 0.4000 0.6471 - 0.5000 0.6941 - 0.6000 0.7624 - 0.7000 0.8253 - 0.8000 0.8812 - 0.9000 0.9412 - 1.0000 1.0000 - 1.1000 1.0000 - </tableData> - </table> - </product> - </function> - - <axis name="DRAG"> - <function name="aero/coefficient/CD0"> - <description>Drag_at_zero_lift</description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/function/kCDge</property> - <table> - <independentVar>aero/alpha-rad</independentVar> - <tableData> - -1.5700 1.5000 - -0.2600 0.0480 - 0.0000 0.00820 - 0.2600 0.0480 - 1.5700 1.5000 - </tableData> - </table> - </product> - </function> - <function name="aero/coefficient/CDi"> - <description>Induced_drag</description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/cl-squared</property> - <property>aero/function/kCDge</property> - <value>0.0700</value> - </product> - </function> - <function name="aero/coefficient/CDmach"> - <description>Drag_due_to_mach</description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <table> - <independentVar>velocities/mach</independentVar> - <tableData> - 0.0000 0.0000 - 0.8100 0.0000 - 1.1000 0.0220 - 1.8000 0.0140 - 2.4000 0.020 - </tableData> - </table> - </product> - </function> - <function name="aero/coefficient/CDflap"> - <description>Drag_due_to_flaps</description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>fcs/flap-pos-norm</property> - <property>aero/function/kCDge</property> - <value>0.0750</value> - </product> - </function> - <function name="aero/coefficient/CDgear"> - <description>Drag_due_to_gear</description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>gear/gear-pos-norm</property> - <value>0.0200</value> - </product> - </function> - <function name="aero/coefficient/CDsb"> - <description>Drag_due_to_speedbrakes</description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>fcs/speedbrake-pos-norm</property> - <value>0.0240</value> - </product> - </function> - <function name="aero/coefficient/CDbeta"> - <description>Drag_due_to_sideslip</description> - <product> - <property>aero/qbar-psf</property> - <property>metrics/Sw-sqft</property> - <property>aero/function/kCDge</property> - <table> - <independentVar>aero/beta-rad</independentVar> - <tableData> - -1.5700 1.2300 - -0.2600 0.0500 - 0.0000 0.0000 - 0.2600 0.0500 - 1.5700 1.2300 - </tableData> - </table> - </product> - </function> - <function name="aero/coefficient/CDde"> + </product> + </function> + + <function name="aero/coefficient/CDi"> + <description>Induced_drag</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/cl-squared</property> + <property>aero/function/kCDge</property> + <value>0.0700</value> + </product> + </function> + + <function name="aero/coefficient/CDmach"> + <description>Drag_due_to_mach</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <table> + <independentVar>velocities/mach</independentVar> + <tableData> + 0.0000 0.0000 + 0.8100 0.0000 + 1.1000 0.0220 + 1.8000 0.0140 + 2.4000 0.020 + </tableData> + </table> + </product> + </function> + + <function name="aero/coefficient/CDflap"> + <description>Drag_due_to_flaps</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/flap-pos-norm</property> + <property>aero/function/kCDge</property> + <value>0.0750</value> + </product> + </function> + + <function name="aero/coefficient/CDgear"> + <description>Drag_due_to_gear</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>gear/gear-pos-norm</property> + <value>0.0200</value> + </product> + </function> + + <function name="aero/coefficient/CDsb"> + <description>Drag_due_to_speedbrakes</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/speedbrake-pos-norm</property> + <value>0.0240</value> + </product> + </function> + + <function name="aero/coefficient/CDbeta"> + <description>Drag_due_to_sideslip</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/function/kCDge</property> + <table> + <independentVar>aero/beta-rad</independentVar> + <tableData> + -1.5700 1.2300 + -0.2600 0.0500 + 0.0000 0.0000 + 0.2600 0.0500 + 1.5700 1.2300 + </tableData> + </table> + </product> + </function> + + <function name="aero/coefficient/CDde"> <description>Drag_due_to_Elevator_Deflection</description> <product> <property>aero/qbar-psf</property> @@ -2041,92 +1945,92 @@ <table> <independentVar>fcs/elevator-pos-rad</independentVar> <tableData> - -0.5236 0.075 - -0.218 0.0375 - 0 0.010 - 0.218 0.0375 - 0.5236 0.077 - </tableData> + -0.5236 0.075 + -0.218 0.0375 + 0 0.010 + 0.218 0.0375 + 0.5236 0.077 + </tableData> </table> </product> </function> - <function name="aero/coefficient/CDDlef"> + <function name="aero/coefficient/CDDlef"> <description>Drag_due_to_leading_edge_flap_deflection</description> <product> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>aero/function/kCDge</property> - <property>fcs/lef-pos-rad</property> + <property>fcs/lef-pos-rad</property> <table> <independentVar>aero/alpha-rad</independentVar> <tableData> - -0.175 0.003 - -0.087 0.001 - 0.000 0.000 - 0.087 0.001 - 0.175 0.002 - 0.262 0.004 - 0.349 0.007 - 0.436 0.011 - 0.524 0.015 - 0.611 0.019 - 0.698 0.023 - 0.785 0.024 - </tableData> + -0.175 0.003 + -0.087 0.001 + 0.000 0.000 + 0.087 0.001 + 0.175 0.002 + 0.262 0.004 + 0.349 0.007 + 0.436 0.011 + 0.524 0.015 + 0.611 0.019 + 0.698 0.023 + 0.785 0.024 + </tableData> </table> </product> </function> - <function name="aero/coefficient/CDq"> + <function name="aero/coefficient/CDq"> <description>Drag_due_to_pitch_rate</description> <product> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>velocities/q-aero-rad_sec</property> - <property>aero/ci2vel</property> + <property>aero/ci2vel</property> <table> <independentVar>aero/alpha-rad</independentVar> <tableData> - -0.175 -1.265 - -0.087 -2.139 - 0.000 -0.308 - 0.087 1.402 - 0.175 3.369 - 0.262 5.135 - 0.349 6.880 - 0.436 8.060 - 0.524 11.201 - 0.611 13.872 - 0.698 19.217 - 0.785 22.105 - </tableData> + -0.175 -1.265 + -0.087 -2.139 + 0.000 -0.308 + 0.087 1.402 + 0.175 3.369 + 0.262 5.135 + 0.349 6.880 + 0.436 8.060 + 0.524 11.201 + 0.611 13.872 + 0.698 19.217 + 0.785 22.105 + </tableData> </table> </product> </function> - <function name="aero/coefficient/CDq_Dlef"> + <function name="aero/coefficient/CDq_Dlef"> <description>Drag_due_to_pitch_rate_and_leading_edge_flap_deflection</description> <product> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>velocities/q-aero-rad_sec</property> - <property>aero/ci2vel</property> - <property>fcs/lef-pos-rad</property> + <property>aero/ci2vel</property> + <property>fcs/lef-pos-rad</property> <table> <independentVar>aero/alpha-rad</independentVar> <tableData> - -0.175 0.067 - -0.087 0.034 - 0.000 0.028 - 0.087 0.029 - 0.175 0.033 - 0.262 0.059 - 0.349 0.061 - 0.436 0.027 - 0.524 0.036 - 0.611 0.047 - 0.698 0.029 - 0.785 0.015 - </tableData> + -0.175 0.067 + -0.087 0.034 + 0.000 0.028 + 0.087 0.029 + 0.175 0.033 + 0.262 0.059 + 0.349 0.061 + 0.436 0.027 + 0.524 0.036 + 0.611 0.047 + 0.698 0.029 + 0.785 0.015 + </tableData> </table> </product> </function> @@ -2142,7 +2046,7 @@ <value>-1.7875</value> </product> </function> - <function name="aero/coefficient/CYb_M"> + <function name="aero/coefficient/CYb_M"> <description>Side_force_due_to_beta_due_to_mach</description> <product> <property>aero/qbar-psf</property> @@ -2151,11 +2055,11 @@ <table> <independentVar>velocities/mach</independentVar> <tableData> - 0.4 0.0 - 1.2 0.0573 - 1.6 -0.1719 - </tableData> - </table> + 0.4 0.0 + 1.2 0.0573 + 1.6 -0.1719 + </tableData> + </table> </product> </function> <function name="aero/coefficient/CYbdot"> @@ -2167,7 +2071,7 @@ <value>-0.0458</value> </product> </function> - <function name="aero/coefficient/CYDa"> + <function name="aero/coefficient/CYDa"> <description>Side_force_due_to_aileron</description> <product> <property>aero/qbar-psf</property> @@ -2225,13 +2129,13 @@ </product> </function> - <function name="aero/coefficient/CLDlef"> + <function name="aero/coefficient/CLDlef"> <description>Lift_due_to_leading_edge_flap_deflection</description> <product> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> - <property>fcs/lef-pos-rad</property> - <property>aero/function/kCLge</property> + <property>fcs/lef-pos-rad</property> + <property>aero/function/kCLge</property> <table> <independentVar>aero/alpha-rad</independentVar> <tableData> @@ -2247,10 +2151,10 @@ 0.6110 0.0280 0.6980 0.0300 0.7850 0.032 - 0.8727 0.03 - 1.0472 0.028 - 1.2217 0.025 - 1.3963 0.02 + 0.8727 0.03 + 1.0472 0.028 + 1.2217 0.025 + 1.3963 0.02 </tableData> </table> </product> @@ -2270,24 +2174,24 @@ <product> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> - <property>velocities/q-aero-rad_sec</property> - <property>aero/ci2vel</property> - <property>aero/function/kCLge</property> + <property>velocities/q-aero-rad_sec</property> + <property>aero/ci2vel</property> + <property>aero/function/kCLge</property> <table> <independentVar>aero/alpha-rad</independentVar> <tableData> -0.175 8.7127 - -0.087 25.7114 - 0.000 28.9000 - 0.087 31.3973 - 0.175 31.0872 - 0.262 30.4071 - 0.349 28.9735 - 0.436 28.4242 - 0.524 27.8647 - 0.611 27.2654 - 0.698 30.5158 - 0.785 27.8165 + -0.087 25.7114 + 0.000 28.9000 + 0.087 31.3973 + 0.175 31.0872 + 0.262 30.4071 + 0.349 28.9735 + 0.436 28.4242 + 0.524 27.8647 + 0.611 27.2654 + 0.698 30.5158 + 0.785 27.8165 </tableData> </table> </product> @@ -2298,7 +2202,7 @@ <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>fcs/flap-pos-norm</property> - <property>aero/function/kCLge</property> + <property>aero/function/kCLge</property> <value>0.3500</value> </product> </function> @@ -2308,12 +2212,12 @@ <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>fcs/speedbrake-pos-norm</property> - <property>aero/function/kCLge</property> + <property>aero/function/kCLge</property> <value>0.3500</value> </product> </function> <!-- - <function name="aero/coefficient/CLDh"> + <function name="aero/coefficient/CLDh"> <description>Lift_due_to_horizontal_tail_deflection</description> <product> <property>aero/qbar-psf</property> @@ -2323,16 +2227,16 @@ <independentVar lookup="row">aero/alpha-rad</independentVar> <independentVar lookup="column">fcs/elevator-pos-rad</independentVar> <tableData> - -0.1745 -0.4279 - 0.0000 0.1346 - 0.7854 2.00 - 1.3963 1.0726 - + -0.1745 -0.4279 + 0.0000 0.1346 + 0.7854 2.00 + 1.3963 1.0726 + </tableData> </table> </product> </function> - + <function name="aero/coefficient/CLDh"> <description>Lift_due_to_horizontal_tail_deflection</description> <product> @@ -2356,7 +2260,7 @@ 0.611 1.829 0.698 1.930 0.785 2.000 - 0.8727 1.982 + 0.8727 1.982 1.0472 1.830 1.2217 1.548 1.3963 1.073 @@ -2365,13 +2269,13 @@ </product> </function> --> - <function name="aero/coefficient/CLde"> + <function name="aero/coefficient/CLde"> <description>Lift_due_to_elevator</description> <product> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>fcs/elevator-pos-rad</property> - <property>aero/function/kCLge</property> + <property>aero/function/kCLge</property> <value>0.190</value> </product> </function> @@ -2401,37 +2305,37 @@ </table> </product> </function> - <function name="aero/coefficient/Clda_M"> + <function name="aero/coefficient/Clda_M"> <description>Change_in_Roll_moment_due_to_aileron_due_to_mach</description> <product> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>metrics/bw-ft</property> <property>aero/alpha-rad</property> - <property>fcs/left-aileron-pos-rad</property> + <property>fcs/left-aileron-pos-rad</property> <table> <independentVar>velocities/mach</independentVar> <tableData> 0.6 0.0 - 1.2 -0.063 - 1.6 -0.063 + 1.2 -0.063 + 1.6 -0.063 </tableData> </table> </product> </function> - <function name="aero/coefficient/Cldr_M"> + <function name="aero/coefficient/Cldr_M"> <description>Change_in_Roll_moment_due_to_rudder_due_to_mach</description> <product> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>metrics/bw-ft</property> <property>aero/alpha-rad</property> - <property>fcs/rudder-pos-rad</property> + <property>fcs/rudder-pos-rad</property> <table> <independentVar>velocities/mach</independentVar> <tableData> 0.6 0.0 - 1.6 -0.0201 + 1.6 -0.0201 </tableData> </table> </product> @@ -2476,17 +2380,17 @@ <independentVar>aero/alpha-rad</independentVar> <tableData> -0.175 -0.126 - -0.087 -0.026 - 0.0 0.063 - 0.087 0.113 - 0.175 0.208 - 0.262 0.230 - 0.349 0.319 - 0.436 0.437 - 0.524 0.680 - 0.611 0.100 - 0.698 0.447 - 0.785 -0.330 + -0.087 -0.026 + 0.0 0.063 + 0.087 0.113 + 0.175 0.208 + 0.262 0.230 + 0.349 0.319 + 0.436 0.437 + 0.524 0.680 + 0.611 0.100 + 0.698 0.447 + 0.785 -0.330 </tableData> </table> </product> @@ -2494,7 +2398,7 @@ <function name="aero/coefficient/Clda"> <description>Roll_moment_due_to_aileron</description> <product> - <value>4</value> + <value>4</value> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>metrics/bw-ft</property> @@ -2503,21 +2407,21 @@ <independentVar>aero/alpha-rad</independentVar> <tableData> -0.1745 0.045 - -0.0873 0.052 - 0.0000 0.060 - 0.0873 0.057 - 0.1745 0.052 - 0.2618 0.047 - 0.3491 0.040 - 0.4363 0.034 - 0.5236 0.029 - 0.6109 0.023 - 0.6981 0.019 - 0.7854 0.015 - 0.8727 0.012 - 1.0472 0.011 - 1.2217 0.009 - 1.3963 0.008 + -0.0873 0.052 + 0.0000 0.060 + 0.0873 0.057 + 0.1745 0.052 + 0.2618 0.047 + 0.3491 0.040 + 0.4363 0.034 + 0.5236 0.029 + 0.6109 0.023 + 0.6981 0.019 + 0.7854 0.015 + 0.8727 0.012 + 1.0472 0.011 + 1.2217 0.009 + 1.3963 0.008 </tableData> </table> </product> @@ -2525,7 +2429,7 @@ <function name="aero/coefficient/ClDr"> <description>Roll_moment_due_to_rudder</description> <product> - <value>2</value> + <value>2</value> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>metrics/bw-ft</property> @@ -2559,7 +2463,7 @@ <function name="aero/coefficient/CmDh"> <description>Pitch_moment_due_to_horizontal_tail_deflection</description> <product> - + <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>metrics/cbarw-ft</property> @@ -2568,7 +2472,7 @@ <independentVar lookup="column">fcs/elevator-pos-rad</independentVar> <tableData> -0.5236 0.0 0.5236 - -0.0873 0.3222 -0.0546 -0.4911 + -0.0873 0.3222 -0.0546 -0.4911 0.0000 0.3482 0.0000 -0.4729 0.0873 0.3897 0.0286 -0.4782 0.1745 0.3689 0.0156 -0.4988 @@ -2585,14 +2489,14 @@ </tableData> </table> - <value>1.5</value> + <value>1.5</value> </product> </function> <function name="aero/coefficient/CmDtv"> <description>Pitch_moment_due_to_thrust_vectoring</description> <product> - <value>1.25</value> + <value>1.25</value> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>metrics/cbarw-ft</property> @@ -2601,27 +2505,27 @@ <independentVar lookup="row">aero/alpha-rad</independentVar> <independentVar lookup="column">fcs/tvc-pos-rad</independentVar> <tableData> - -0.3491 0.0 0.3491 - -0.0873 0.4417 0.0 -0.7924 - 0.0000 0.4650 0.0 -0.8366 - 0.0873 0.4448 0.0 -0.8808 - 0.1745 0.4677 0.0 -0.8886 - 0.2618 0.4755 0.0 -0.8600 - 0.3491 0.4625 0.0 -0.7534 - 0.4363 0.4963 0.0 -0.6901 - 0.5236 0.4936 0.0 -0.6408 - 0.6109 0.4781 0.0 -0.6000 - 0.6981 0.5025 0.0 -0.5454 - 0.7854 0.5015 0.0 -0.5143 - 0.8727 0.4209 0.0 -0.5284 - 1.0472 0.4417 0.0 -0.5047 - 1.2217 0.2988 0.0 -0.4883 + -0.3491 0.0 0.3491 + -0.0873 0.4417 0.0 -0.7924 + 0.0000 0.4650 0.0 -0.8366 + 0.0873 0.4448 0.0 -0.8808 + 0.1745 0.4677 0.0 -0.8886 + 0.2618 0.4755 0.0 -0.8600 + 0.3491 0.4625 0.0 -0.7534 + 0.4363 0.4963 0.0 -0.6901 + 0.5236 0.4936 0.0 -0.6408 + 0.6109 0.4781 0.0 -0.6000 + 0.6981 0.5025 0.0 -0.5454 + 0.7854 0.5015 0.0 -0.5143 + 0.8727 0.4209 0.0 -0.5284 + 1.0472 0.4417 0.0 -0.5047 + 1.2217 0.2988 0.0 -0.4883 </tableData> </table> </product> </function> - <function name="aero/coefficient/Cma_M"> + <function name="aero/coefficient/Cma_M"> <description>Change_in_Pitch_moment_due_to_alpha_due_to_mach</description> <product> <property>aero/qbar-psf</property> @@ -2631,12 +2535,12 @@ <table> <independentVar>velocities/mach</independentVar> <tableData> - 0.6000 0.0000 - 0.8000 0.0974 - 0.9000 -0.3323 - 1.0000 -0.9626 - 1.1000 -0.8480 - 1.2000 -0.7907 + 0.6000 0.0000 + 0.8000 0.0974 + 0.9000 -0.3323 + 1.0000 -0.9626 + 1.1000 -0.8480 + 1.2000 -0.7907 </tableData> </table> </product> @@ -2652,18 +2556,18 @@ <table> <independentVar>aero/alpha-rad</independentVar> <tableData> - -0.1750 -7.2100 - -0.0870 -5.4000 - 0.0000 -5.2300 - 0.0870 -5.2600 - 0.1750 -6.1100 - 0.2620 -6.6400 - 0.3490 -5.6900 - 0.4360 -6.0000 - 0.5240 -6.2000 - 0.6110 -6.4000 - 0.6980 -6.6000 - 0.7850 -6.0000 + -0.1750 -7.2100 + -0.0870 -5.4000 + 0.0000 -5.2300 + 0.0870 -5.2600 + 0.1750 -6.1100 + 0.2620 -6.6400 + 0.3490 -5.6900 + 0.4360 -6.0000 + 0.5240 -6.2000 + 0.6110 -6.4000 + 0.6980 -6.6000 + 0.7850 -6.0000 </tableData> </table> </product> @@ -2698,9 +2602,9 @@ <table> <independentVar>aero/alpha-rad</independentVar> <tableData> - -0.349 0.0745 - 0.000 0.1780 - 0.873 0.0086 + -0.349 0.0745 + 0.000 0.1780 + 0.873 0.0086 </tableData> @@ -2718,13 +2622,13 @@ <independentVar>velocities/mach</independentVar> <tableData> 0.6000 0.0000 - 0.7000 -0.0688 - 0.8000 -0.0172 - 0.9000 0.0229 - 1.0000 0.0000 - 1.2000 -0.0688 - 1.4000 0.0057 - 1.6000 0.0688 + 0.7000 -0.0688 + 0.8000 -0.0172 + 0.9000 0.0229 + 1.0000 0.0000 + 1.2000 -0.0688 + 1.4000 0.0057 + 1.6000 0.0688 </tableData> </table> </product> @@ -2782,7 +2686,7 @@ <function name="aero/coefficient/CnDr"> <description>Yaw_moment_due_to_rudder</description> <product> - <value>5</value> + <value>5</value> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>metrics/bw-ft</property> @@ -2791,7 +2695,7 @@ <independentVar>aero/alpha-rad</independentVar> <tableData> - -0.1745 -0.048 + -0.1745 -0.048 -0.0873 -0.045 0.0000 -0.045 0.0873 -0.045 @@ -2812,20 +2716,20 @@ </table> </product> </function> - <function name="aero/coefficient/Cndr_M"> + <function name="aero/coefficient/Cndr_M"> <description>Change_in_Yaw_moment_due_to_rudder_due_to_mach</description> <product> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>metrics/bw-ft</property> - <property>aero/alpha-rad</property> + <property>aero/alpha-rad</property> <property>fcs/rudder-pos-rad</property> <table> <independentVar>velocities/mach</independentVar> <tableData> 0.6000 0.0000 - 1.2000 0.0401 - 1.6000 0.0716 + 1.2000 0.0401 + 1.6000 0.0716 </tableData> </table> </product> @@ -2833,7 +2737,7 @@ <function name="aero/coefficient/Cnda"> <description>Adverse_yaw</description> <product> - <value>2</value> + <value>2</value> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> <property>metrics/bw-ft</property> @@ -2841,24 +2745,24 @@ <table> <independentVar>aero/alpha-rad</independentVar> <tableData> - -0.1745 0.01 - -0.0873 0.009 - 0.0000 0.010 - 0.0873 0.009 - 0.1745 0.008 - 0.2618 0.006 - 0.3491 -0.002 - 0.4363 -0.003 - 0.5236 -0.005 - 0.6109 -0.008 - 0.6981 -0.006 - 0.7854 -0.006 - 0.8727 -0.008 - 1.0472 -0.01 - 1.2217 -0.011 - 1.3963 -0.013 - </tableData> - </table> + -0.1745 0.01 + -0.0873 0.009 + 0.0000 0.010 + 0.0873 0.009 + 0.1745 0.008 + 0.2618 0.006 + 0.3491 -0.002 + 0.4363 -0.003 + 0.5236 -0.005 + 0.6109 -0.008 + 0.6981 -0.006 + 0.7854 -0.006 + 0.8727 -0.008 + 1.0472 -0.01 + 1.2217 -0.011 + 1.3963 -0.013 + </tableData> + </table> </product> </function> </axis> diff --git a/aircraft/fokker100/Makefile.am b/aircraft/fokker100/Makefile.am index 4f75dc940d8c11b03d0eaae1870ba8c0e7c553e9..6f13a76dbacdf3561d39a7a2db4759925b9fc430 100644 --- a/aircraft/fokker100/Makefile.am +++ b/aircraft/fokker100/Makefile.am @@ -1,4 +1,8 @@ +SUBDIRS = \ + Systems aircraft_fokker100dir = ${pkgdatadir}/aircraft/fokker100 aircraft_fokker100_DATA = \ - fokker100.xml + xf100.xml \ + fokker100.xml \ + fokker70.xml EXTRA_DIST=$(aircraft_fokker100_data) diff --git a/aircraft/fokker100/Systems/.cvsignore b/aircraft/fokker100/Systems/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..282522db0342d8750454b3dc162493b5fc709cc8 --- /dev/null +++ b/aircraft/fokker100/Systems/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/aircraft/fokker100/Systems/Makefile.am b/aircraft/fokker100/Systems/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..55149be297d37e2a4a71f6db1f5cd8fb15a107f7 --- /dev/null +++ b/aircraft/fokker100/Systems/Makefile.am @@ -0,0 +1,4 @@ +aircraft_fokker100_Systemsdir = ${pkgdatadir}/aircraft/fokker100/Systems +aircraft_fokker100_Systems_DATA = \ + pushback.xml +EXTRA_DIST=$(aircraft_fokker100_Systems_data) diff --git a/aircraft/fokker100/Systems/pushback.xml b/aircraft/fokker100/Systems/pushback.xml new file mode 100644 index 0000000000000000000000000000000000000000..4477f7084e1aa86ac8d54414bdb3720f2a55bc4d --- /dev/null +++ b/aircraft/fokker100/Systems/pushback.xml @@ -0,0 +1,38 @@ +<?xml version='1.0' encoding='UTF-8' ?> +<system name="pushback"> + <property>/sim/model/pushback/target-speed-fps</property> + <channel name="Pushback"> + + <switch name="systems/pushback/linked"> + <default value="-1"/> + <test value="0"> + /sim/model/pushback/position-norm gt 0.95 + /gear/gear/wow == 1 + gear/unit[0]/wheel-speed-fps lt 50 + </test> + </switch> + + <summer name="systems/pushback/speed-error"> + <input>/sim/model/pushback/target-speed-fps</input> + <input>-gear/unit[0]/wheel-speed-fps</input> + </summer> + + <pid name="systems/pushback/force"> + <input>systems/pushback/speed-error</input> + <kp>/sim/model/pushback/kp</kp> + <ki>/sim/model/pushback/ki</ki> + <kd>/sim/model/pushback/kd</kd> + <trigger>systems/pushback/linked</trigger> + <output>/sim/model/pushback/force</output> + </pid> + + <switch name="systems/pushback/force-output"> + <default value="0"/> + <test value="systems/pushback/force"> + systems/pushback/linked == 0 + </test> + <output>external_reactions/pushback/magnitude</output> + </switch> + + </channel> +</system> \ No newline at end of file diff --git a/aircraft/fokker100/fokker100.xml b/aircraft/fokker100/fokker100.xml index 39647b3b8ae63e1463569bb0fdb762b1d18c35e1..32aa66ce069f5adec86300f42d939ae56514450d 100644 --- a/aircraft/fokker100/fokker100.xml +++ b/aircraft/fokker100/fokker100.xml @@ -1,436 +1,564 @@ <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="http://jsbsim.sourceforge.net/JSBSim.xsl"?> -<fdm_config name="Fokker 100" version="2.0" release="BETA" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://jsbsim.sourceforge.net/JSBSim.xsd"> - - <fileheader> - <author> Erik Hofman </author> - <filecreationdate> 2003-01-01 </filecreationdate> - <version> $Revision: 1.26 $ </version> - <description> Fokker 100 commercial airliner </description> - <reference refID="None" author="n/a" title="n/a" date="n/a"/> - <reference title="Butterworth-Heinemann - Civil Jet Aircraft Design (BH) - http://www.bh.com/companions/034074152X/appendices/data-a/default.htm"/> - <reference title="Lissys - PIANO aircraft analysis software +<fdm_config name="Fokker-100" version="2.0" release="ALPHA" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://jsbsim.sourceforge.net/JSBSim.xsd"> + + <fileheader> + <author> Erik Hofman </author> + <filecreationdate>2010-08-08</filecreationdate> + <version>$Revision: 1.29 $</version> + <description> Fokker-100 commercial airliner </description> + <reference title="Butterworth-Heinemann - Civil Jet Aircraft Design (BH) + http://www.elsevierdirect.com/companions/9780340741528/appendices/data-a/table-8/table.htm"/> + <reference title="Lissys - PIANO aircraft analysis software http://www.lissys.demon.co.uk/f7tx2.html"/> - <reference title="Advanced Topics in Aerodynamics, Aerodynamic Database (AD) - http://aerodyn.org/HighLift/tables.html"/> - </fileheader> - - <metrics> - <wingarea unit="FT2"> 1006.53 </wingarea> - <wingspan unit="FT"> 92.13 </wingspan> - <chord unit="FT"> 12.41 </chord> - <htailarea unit="FT2"> 244.47 </htailarea> - <htailarm unit="FT"> 47.22 </htailarm> - <vtailarea unit="FT2"> 178.83 </vtailarea> - <vtailarm unit="FT"> 0 </vtailarm> - <location name="AERORP" unit="IN"> - <x> 627.4 </x> - <y> 0 </y> - <z> 18.1 </z> - </location> - <location name="EYEPOINT" unit="IN"> - <x> 94.5 </x> - <y> -22.4 </y> - <z> 49.2 </z> - </location> - <location name="VRP" unit="IN"> - <x> 0 </x> - <y> 0 </y> - <z> 0 </z> - </location> - </metrics> - - <mass_balance> - <ixx unit="SLUG*FT2"> 587012 </ixx> - <iyy unit="SLUG*FT2"> 2.12516e+06 </iyy> - <izz unit="SLUG*FT2"> 2.51927e+06 </izz> - <emptywt unit="LBS"> 54218 </emptywt> - <location name="CG" unit="IN"> - <x> 627.4 </x> - <y> 0 </y> - <z> -16.5 </z> - </location> - <pointmass name="name"> - <weight unit="LBS"> 230 </weight> - <location name="POINTMASS" unit="IN"> - <x> 94.5 </x> - <y> -22.4 </y> - <z> 25.6 </z> - </location> - </pointmass> - <pointmass name="name"> - <weight unit="LBS"> 230 </weight> - <location name="POINTMASS" unit="IN"> - <x> 94.5 </x> - <y> 22.4 </y> - <z> 25.6 </z> - </location> - </pointmass> - <pointmass name="name"> - <weight unit="LBS"> 400 </weight> - <location name="POINTMASS" unit="IN"> - <x> 206 </x> - <y> 22.4 </y> - <z> 25.6 </z> - </location> - </pointmass> - </mass_balance> - - <ground_reactions> - <contact type="BOGEY" name="NOSE_LG"> - <location unit="IN"> - <x> 137 </x> - <y> 0 </y> - <z> -81.5 </z> - </location> - <static_friction> 0.8 </static_friction> - <dynamic_friction> 0.5 </dynamic_friction> - <rolling_friction> 0.02 </rolling_friction> - <spring_coeff unit="LBS/FT"> 28504 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 9501.3 </damping_coeff> - <max_steer unit="DEG"> 5 </max_steer> - <brake_group> NONE </brake_group> - <retractable>1</retractable> - </contact> - <contact type="BOGEY" name="LEFT_MLG"> - <location unit="IN"> - <x> 700.4 </x> - <y> -113 </y> - <z> -89.8 </z> - </location> - <static_friction> 0.8 </static_friction> - <dynamic_friction> 0.5 </dynamic_friction> - <rolling_friction> 0.02 </rolling_friction> - <spring_coeff unit="LBS/FT"> 95013.4 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 19002.7 </damping_coeff> - <max_steer unit="DEG"> 0.0 </max_steer> - <brake_group> LEFT </brake_group> - <retractable>1</retractable> - </contact> - <contact type="BOGEY" name="RIGHT_MLG"> - <location unit="IN"> - <x> 700.4 </x> - <y> 113 </y> - <z> -89.8 </z> - </location> - <static_friction> 0.8 </static_friction> - <dynamic_friction> 0.5 </dynamic_friction> - <rolling_friction> 0.02 </rolling_friction> - <spring_coeff unit="LBS/FT"> 95013.4 </spring_coeff> - <damping_coeff unit="LBS/FT/SEC"> 19002.7 </damping_coeff> - <max_steer unit="DEG"> 0.0 </max_steer> - <brake_group> RIGHT </brake_group> - <retractable>1</retractable> - </contact> - </ground_reactions> - <propulsion> - <engine file="Tay-651"> - <location unit="IN"> - <x> 1028.74 </x> - <y> -101.6 </y> - <z> -49.2 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> 0 </pitch> - <yaw> 0 </yaw> - </orient> - <feed>0</feed> - <thruster file="direct"> - <location unit="IN"> - <x> 1028.74 </x> - <y> -101.6 </y> - <z> -49.2 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> 0.0 </pitch> - <yaw> 0.0 </yaw> - </orient> - </thruster> - </engine> - <engine file="Tay-651"> - <location unit="IN"> - <x> 1028.74 </x> - <y> 101.6 </y> - <z> -49.2 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> 0 </pitch> - <yaw> 0 </yaw> - </orient> - <feed>1</feed> - <thruster file="direct"> - <location unit="IN"> - <x> 1028.74 </x> - <y> 101.6 </y> - <z> -49.2 </z> - </location> - <orient unit="DEG"> - <roll> 0.0 </roll> - <pitch> 0.0 </pitch> - <yaw> 0.0 </yaw> - </orient> - </thruster> - </engine> - <tank type="FUEL"> <!-- Tank number 0 --> - <location unit="IN"> - <x> 587.4 </x> - <y> 0 </y> - <z> -16.5 </z> - </location> - <capacity unit="LBS"> 1377 </capacity> - <contents unit="LBS"> 688.5 </contents> - </tank> - <tank type="FUEL"> <!-- Tank number 1 --> - <location unit="IN"> - <x> 587.4 </x> - <y> 0 </y> - <z> -16.5 </z> - </location> - <capacity unit="LBS"> 1377 </capacity> - <contents unit="LBS"> 688.5 </contents> - </tank> - <tank type="FUEL"> <!-- Tank number 2 --> - <location unit="IN"> - <x> 587.4 </x> - <y> 0 </y> - <z> -16.5 </z> - </location> - <capacity unit="LBS"> 1377 </capacity> - <contents unit="LBS"> 688.5 </contents> - </tank> - </propulsion> - <flight_control name="Fokker 100"> - <channel name="Pitch"> - <summer name="Pitch Trim Sum"> - <input>fcs/elevator-cmd-norm</input> - <input>fcs/pitch-trim-cmd-norm</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - <output>fcs/elevator-pos-norm</output> - </summer> - - <aerosurface_scale name="Elevator Control"> - <input>fcs/pitch-trim-sum</input> - <range> - <min>-0.35</min> - <max>0.3</max> - </range> - <output>fcs/elevator-pos-rad</output> - </aerosurface_scale> - </channel> - <channel name="Roll"> - <summer name="Roll Trim Sum"> - <input>fcs/aileron-cmd-norm</input> - <input>fcs/roll-trim-cmd-norm</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - <output>fcs/left-aileron-pos-norm</output> - </summer> - - <aerosurface_scale name="Left Aileron Control"> - <input>fcs/roll-trim-sum</input> - <range> - <min>-0.35</min> - <max>0.35</max> - </range> - <output>fcs/left-aileron-pos-rad</output> - </aerosurface_scale> - - <aerosurface_scale name="Right Aileron Control"> - <input>-fcs/roll-trim-sum</input> - <range> - <min>-0.35</min> - <max>0.35</max> - </range> - <output>fcs/right-aileron-pos-rad</output> - </aerosurface_scale> - </channel> - <channel name="Yaw"> - <summer name="Rudder Command Sum"> - <input>fcs/rudder-cmd-norm</input> - <input>fcs/yaw-trim-cmd-norm</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - </summer> - - <scheduled_gain name="Yaw Damper Rate"> - <input>velocities/r-aero-rad_sec</input> - <table> - <independentVar>aero/qbar-psf</independentVar> - <tableData> - 3.00 0.00 - 11.00 2.00 - </tableData> - </table> - </scheduled_gain> - - <scheduled_gain name="Yaw Damper Beta"> - <input>aero/beta-rad</input> - <table> - <independentVar>aero/qbar-psf</independentVar> - <tableData> - 3.00 0.00 - 11.00 0.00 - </tableData> - </table> - </scheduled_gain> - - <summer name="Yaw Damper Sum"> - <input>fcs/yaw-damper-beta</input> - <input>fcs/yaw-damper-rate</input> - <clipto> - <min>-0.2</min> - <max>0.2</max> - </clipto> - </summer> - - <scheduled_gain name="Yaw Damper Final"> - <input>fcs/yaw-damper-sum</input> - <table> - <independentVar>aero/qbar-psf</independentVar> - <tableData> - 2.99 0.00 - 3.00 1.00 - </tableData> - </table> - </scheduled_gain> - - <summer name="Rudder Sum"> - <input>fcs/rudder-command-sum</input> - <input>fcs/yaw-damper-final</input> - <clipto> - <min>-1</min> - <max>1</max> - </clipto> - <output>fcs/rudder-pos-norm</output> - </summer> - - <aerosurface_scale name="Rudder Control"> - <input>fcs/rudder-sum</input> - <range> - <min>-0.35</min> - <max>0.35</max> - </range> - <output>fcs/rudder-pos-rad</output> - </aerosurface_scale> - </channel> - <channel name="Flaps"> - <kinematic name="Flaps Control"> - <input>fcs/flap-cmd-norm</input> - <traverse> - <setting> - <position>0</position> - <time>0</time> - </setting> - <setting> - <position>8</position> - <time>3</time> - </setting> - <setting> - <position>15</position> - <time>3</time> - </setting> - <setting> - <position>25</position> - <time>4</time> - </setting> - <setting> - <position>42</position> - <time>4</time> - </setting> - </traverse> - <output>fcs/flap-pos-deg</output> - </kinematic> - - <aerosurface_scale name="Flaps Control Normalizer"> - <input>fcs/flap-pos-deg</input> - <domain> - <min>0</min> - <max>42</max> - </domain> - <range> - <min>0</min> - <max>1</max> - </range> - <output> fcs/flap-pos-norm </output> - </aerosurface_scale> - </channel> - <channel name="Landing Gear"> - <kinematic name="Gear Control"> - <input>gear/gear-cmd-norm</input> - <traverse> - <setting> - <position>0</position> - <time>0</time> - </setting> - <setting> - <position>1</position> - <time>5</time> - </setting> - </traverse> - <output>gear/gear-pos-norm</output> - </kinematic> - </channel> - <channel name="Speedbrake"> - <kinematic name="Speedbrake Control"> - <input>fcs/speedbrake-cmd-norm</input> - <traverse> - <setting> - <position>0</position> - <time>0</time> - </setting> - <setting> - <position>1</position> - <time>1</time> - </setting> - </traverse> - <output>fcs/speedbrake-pos-norm</output> - </kinematic> - </channel> - <channel name="Spoilers"> - <kinematic name="Spoiler Control"> - <input>fcs/spoiler-cmd-norm</input> - <traverse> - <setting> - <position>0</position> - <time>0</time> - </setting> - <setting> - <position>1</position> - <time>1</time> - </setting> - </traverse> - <output>fcs/spoiler-pos-norm</output> - </kinematic> - - <kinematic name="Reverser Pos Norm"> - <input>fcs/spoiler-cmd-norm</input> - <traverse> - <setting> - <position>0</position> - <time>0</time> - </setting> - <setting> - <position>1</position> - <time>1</time> - </setting> - </traverse> - </kinematic> - </channel> - </flight_control> - <aerodynamics> + <reference title="Aerodynamic Design of Transport Aircraft + http://www.scribd.com/doc/23956816/Aerodynamic-Design-of-Transport-Aircraft"/> + </fileheader> + +<!-- + File: Fokker-100.xml + Inputs: + name: Fokker-100 + type: two-engine transonic transport + max weight: 95013.45 lb + wing span: 92.13048 ft + length: 106.6325 ft + wing area: 1006.5275 sq-ft + gear type: tricycle + retractable?: yes + # engines: 2 + engine type: turbine + engine layout: aft fuselage + yaw damper? yes + + Outputs: + wing loading: 94.40 lb/sq-ft + CL-alpha: 4.4 per radian + CL-0: 0.2 + CL-max: 1.72 + CD-0: 0.02 + K: 0.043 + +--> + + <metrics> + <wingarea unit="FT2"> 1006.53 </wingarea> + <wingspan unit="FT" > 92.13 </wingspan> + <wing_incidence> 2.00 </wing_incidence> + <chord unit="FT" > 12.4671 </chord> + <htailarea unit="FT2"> 233.792 </htailarea> + <htailarm unit="FT" > 52.4934 </htailarm> + <vtailarea unit="FT2"> 132.396 </vtailarea> + <vtailarm unit="FT" > 44.6194 </vtailarm> + <location name="AERORP" unit="IN"> + <x> 699.48 </x> <!-- 668.48 --> + <y> 0.00 </y> + <z> 38.00 </z> + </location> + <location name="EYEPOINT" unit="IN"> + <x> 122.04 </x> + <y> -30.00 </y> + <z> 88.94 </z> + </location> + <location name="VRP" unit="IN"> + <x> 101.65 </x> + <y> 0.0 </y> + <z> 0.0 </z> + </location> + </metrics> + + <mass_balance> + <ixx unit="SLUG*FT2"> 234805 </ixx> + <iyy unit="SLUG*FT2"> 726720 </iyy> + <izz unit="SLUG*FT2"> 925012 </izz> + <emptywt unit="LBS" > 54217 </emptywt> + <location name="CG" unit="IN"> + <x> 719.81 </x> <!-- 693.81 --> + <y> 0.00 </y> + <z> 38.12 </z> + </location> + <pointmass name="pilot"> + <weight unit="LBS"> 230 </weight> + <location name="POINTMASS" unit="IN"> + <x> 122.04 </x> + <y> -30.0 </y> + <z> 66.0 </z> + </location> + </pointmass> + <pointmass name="copilot"> + <weight unit="LBS"> 230 </weight> + <location name="POINTMASS" unit="IN"> + <x> 122.04 </x> + <y> 30.0 </y> + <z> 66.0 </z> + </location> + </pointmass> + <pointmass name="steward"> + <weight unit="LBS"> 400 </weight> + <location name="POINTMASS" unit="IN"> + <x> 218 </x> + <y> 32.0 </y> + <z> 66.0 </z> + </location> + </pointmass> + </mass_balance> + + <ground_reactions> + + <contact type="BOGEY" name="NOSE"> + <location unit="IN"> + <x> 172.87 </x> + <y> 0.00 </y> + <z> -55.73 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 7750.03 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 1600.34 </damping_coeff> + <max_steer unit="DEG"> 5.00 </max_steer> + <brake_group>NONE</brake_group> + <retractable>1</retractable> + </contact> + + <contact type="BOGEY" name="LEFT_MAIN"> + <location unit="IN"> + <x> 731.93 </x> + <y>-101.65 </y> + <z> -63.53 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 95013.45 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 19002.69 </damping_coeff> + <max_steer unit="DEG">0</max_steer> + <brake_group>LEFT</brake_group> + <retractable>1</retractable> + </contact> + + <contact type="BOGEY" name="RIGHT_MAIN"> + <location unit="IN"> + <x> 731.93 </x> + <y> 101.65 </y> + <z> -63.53 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 95013.45 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 19002.69 </damping_coeff> + <max_steer unit="DEG">0</max_steer> + <brake_group>RIGHT</brake_group> + <retractable>1</retractable> + </contact> + + <contact type="STRUCTURE" name="LEFT_WING"> + <location unit="IN"> + <x> 753.77 </x> + <y>-1105.4 </y> + <z> 0.0 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <spring_coeff unit="LBS/FT"> 95013.45 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 19002.69 </damping_coeff> + </contact> + + <contact type="STRUCTURE" name="RIGHT_WING"> + <location unit="IN"> + <x> 753.77 </x> + <y> 1105.4 </y> + <z> 0.0 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <spring_coeff unit="LBS/FT"> 95013.45 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 19002.69 </damping_coeff> + </contact> + + </ground_reactions> + + <external_reactions> + <force name="pushback" frame="BODY"> + <location unit="IN"> + <x>-139</x> + <y>0</y> + <z>-71</z> + </location> + <direction> + <x>1</x> + <y>0</y> + <z>0</z> + </direction> + </force> + </external_reactions> + + <propulsion> + + <engine file="Tay-620"> + <location unit="IN"> + <x> 922.52 </x> + <y> -101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + <feed>0</feed> + <thruster file="direct"> + <location unit="IN"> + <x> 922.52 </x> + <y> -101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + </thruster> + </engine> + + <engine file="Tay-620"> + <location unit="IN"> + <x> 922.52 </x> + <y> 101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + <feed>1</feed> + <thruster file="direct"> + <location unit="IN"> + <x> 922.52 </x> + <y> 101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + </thruster> + </engine> + + <tank type="FUEL" number="0"> + <location unit="IN"> + <x> 713.81 </x> + <y>-190.59 </y> + <z> 0.0 </z> + </location> + <capacity unit="LBS"> 13360.01 </capacity> + <contents unit="LBS"> 688.50 </contents> + </tank> + + <tank type="FUEL" number="1"> + <location unit="IN"> + <x> 713.81 </x> + <y> 190.59 </y> + <z> 0.0 </z> + </location> + <capacity unit="LBS"> 13360.01 </capacity> + <contents unit="LBS"> 688.50 </contents> + </tank> +<!-- + <tank type="FUEL" number="2"> + <location unit="IN"> + <x> 703.77 </x> + <y> 0.00 </y> + <z> -31.99 </z> + </location> + <capacity unit="LBS"> 1377.01 </capacity> + <contents unit="LBS"> 688.50 </contents> + </tank> +--> + </propulsion> + + <system file="pushback"/> + + <flight_control name="FCS: Fokker-100"> + + <channel name="Pitch"> + <summer name="fcs/pitch-trim-sum"> + <input>fcs/elevator-cmd-norm</input> + <input>fcs/pitch-trim-cmd-norm</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + </summer> + + <aerosurface_scale name="fcs/elevator-control"> + <input>fcs/pitch-trim-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/elevator-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/elevator-normalization"> + <input>fcs/elevator-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/elevator-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Roll"> + <summer name="fcs/roll-trim-sum"> + <input>fcs/aileron-cmd-norm</input> + <input>fcs/roll-trim-cmd-norm</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + </summer> + + <aerosurface_scale name="fcs/left-aileron-control"> + <input>fcs/roll-trim-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/left-aileron-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/right-aileron-control"> + <input>fcs/roll-trim-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/right-aileron-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/left-aileron-normalization"> + <input>fcs/left-aileron-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/left-aileron-pos-norm</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/right-aileron-normalization"> + <input>fcs/right-aileron-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/right-aileron-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Yaw"> + <summer name="fcs/rudder-command-sum"> + <input>fcs/rudder-cmd-norm</input> + <input>fcs/yaw-trim-cmd-norm</input> + <clipto> + <min> -0.35 </min> + <max> 0.35 </max> + </clipto> + </summer> + + <scheduled_gain name="fcs/yaw-damper-rate"> + <input>velocities/r-aero-rad_sec</input> + <table> + <independentVar lookup="row">velocities/ve-kts</independentVar> + <tableData> + 30 0.00 + 60 2.00 + </tableData> + </table> + </scheduled_gain> + + <scheduled_gain name="fcs/yaw-damper-beta"> + <input>aero/beta-rad</input> + <table> + <independentVar lookup="row">velocities/ve-kts</independentVar> + <tableData> + 30 0.00 + 60 0.00 + </tableData> + </table> + </scheduled_gain> + + <summer name="fcs/yaw-damper-sum"> + <input>fcs/yaw-damper-beta</input> + <input>fcs/yaw-damper-rate</input> + <clipto> + <min> -0.1 </min> + <max> 0.1 </max> + </clipto> + </summer> + + <scheduled_gain name="fcs/yaw-damper-final"> + <input>fcs/yaw-damper-sum</input> + <table> + <independentVar lookup="row">velocities/ve-kts</independentVar> + <tableData> + 30 0.0 + 31 1.0 + </tableData> + </table> + </scheduled_gain> + + <summer name="fcs/rudder-sum"> + <input>fcs/rudder-command-sum</input> + <input>fcs/yaw-damper-final</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + </summer> + + <aerosurface_scale name="fcs/rudder-control"> + <input>fcs/rudder-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/rudder-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="rcs/rudder-normalization"> + <input>fcs/rudder-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/rudder-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Flaps"> + <kinematic name="fcs/flaps-control"> + <input>fcs/flap-cmd-norm</input> + <traverse> + <setting> + <position>0</position> + <time>0</time> + </setting> + <setting> + <position>8</position> + <time>3</time> + </setting> + <setting> + <position>15</position> + <time>3</time> + </setting> + <setting> + <position>25</position> + <time>4</time> + </setting> + <setting> + <position>42</position> + <time>4</time> + </setting> + </traverse> + <output>fcs/flap-pos-deg</output> + </kinematic> + + <aerosurface_scale name="fcs/flap-normalization"> + <input>fcs/flap-pos-deg</input> + <domain> + <min>0</min> + <max>42</max> + </domain> + <range> + <min>0</min> + <max>1</max> + </range> + <output>fcs/flap-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Landing Gear"> + <kinematic name="fcs/gear-control"> + <input>gear/gear-cmd-norm</input> + <traverse> + <setting> + <position> 0 </position> + <time> 0 </time> + </setting> + <setting> + <position> 1 </position> + <time> 5 </time> + </setting> + </traverse> + <output>gear/gear-pos-norm</output> + </kinematic> + + </channel> + + <channel name="Speedbrake"> + <kinematic name="fcs/speedbrake-control"> + <input>fcs/speedbrake-cmd-norm</input> + <traverse> + <setting> + <position> 0 </position> + <time> 0 </time> + </setting> + <setting> + <position> 1 </position> + <time> 1 </time> + </setting> + </traverse> + <output>fcs/speedbrake-pos-norm</output> + </kinematic> + </channel> + + + <channel name="Spoilers"> + <kinematic name="fcs/spoiler-control"> + <input>fcs/spoiler-cmd-norm</input> + <traverse> + <setting> + <position>0</position> + <time>0</time> + </setting> + <setting> + <position>1</position> + <time>1</time> + </setting> + </traverse> + <output>fcs/spoiler-pos-norm</output> + </kinematic> + </channel> + </flight_control> + + <aerodynamics> <function name="aero/function/kCDge"> <description>Change_in_drag_due_to_ground_effect</description> @@ -492,7 +620,7 @@ <tableData> -1.5700 1.5000 -0.2600 0.0400 - 0.0000 0.0192 + 0.0000 0.01922 0.2600 0.0400 1.5700 1.5000 </tableData> @@ -506,7 +634,7 @@ <property>metrics/Sw-sqft</property> <property>aero/cl-squared</property> <property>aero/function/kCDge</property> - <value>0.0448</value> + <value>0.00717</value> </product> </function> <function name="aero/coefficient/CDflap"> @@ -564,6 +692,16 @@ <value>0.0280</value> </product> </function> + <function name="aero/coefficient/CDrv"> + <description>Drag_due_to_reverse</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>propulsion/engine[0]/reverser-angle-rad</property> + <property>propulsion/engine[1]/reverser-angle-rad</property> + <value>0.0187</value> + </product> + </function> <function name="aero/coefficient/CDbeta"> <description>Drag_due_to_sideslip</description> <product> @@ -586,7 +724,7 @@ <product> <property>aero/qbar-psf</property> <property>metrics/Sw-sqft</property> - <abs><property>fcs/elevator-pos-norm</property></abs> + <property>fcs/mag-elevator-pos-rad</property> <value>0.0590</value> </product> </function> @@ -614,10 +752,10 @@ <table> <independentVar>aero/alpha-rad</independentVar> <tableData> - -0.2000 -0.6800 - 0.0000 0.2000 - 0.2300 1.3000 - 0.6000 0.6000 + -0.20 -0.680 + 0.00 0.217 + 0.23 1.300 + 0.60 0.600 </tableData> </table> </product> @@ -752,7 +890,7 @@ <property>metrics/Sw-sqft</property> <property>metrics/cbarw-ft</property> <property>aero/function/kCmge</property> - <value>-0.0748</value> + <value>-0.000737</value> </product> </function> <function name="aero/coefficient/Cmalpha"> @@ -789,7 +927,7 @@ <property>metrics/cbarw-ft</property> <property>aero/ci2vel</property> <property>velocities/q-aero-rad_sec</property> - <value>-17.0000</value> + <value>-31.0000</value> </product> </function> <function name="aero/coefficient/Cmadot"> @@ -800,7 +938,7 @@ <property>metrics/cbarw-ft</property> <property>aero/ci2vel</property> <property>aero/alphadot-rad_sec</property> - <value>-6.0000</value> + <value>-16.0000</value> </product> </function> </axis> diff --git a/aircraft/fokker100/fokker70.xml b/aircraft/fokker100/fokker70.xml new file mode 100644 index 0000000000000000000000000000000000000000..0f11128660653c57517918aff193419616f01f14 --- /dev/null +++ b/aircraft/fokker100/fokker70.xml @@ -0,0 +1,995 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/xsl" href="http://jsbsim.sourceforge.net/JSBSim.xsl"?> +<fdm_config name="Fokker 70" version="2.0" release="BETA" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://jsbsim.sourceforge.net/JSBSim.xsd"> + + <fileheader> + <author> Erik Hofman </author> + <filecreationdate> 2010-08-08 </filecreationdate> + <version> $Revision: 1.3 $ </version> + <description> Fokker 70 commercial airliner </description> + <reference title="Butterworth-Heinemann - Civil Jet Aircraft Design (BH) + http://www.elsevierdirect.com/companions/9780340741528/appendices/data-a/table-8/table.htm"/> + <reference title="Lissys - PIANO aircraft analysis software + http://www.lissys.demon.co.uk/f7tx2.html"/> + <reference title="Aerodynamic Design of Transport Aircraft + http://www.scribd.com/doc/23956816/Aerodynamic-Design-of-Transport-Aircraft"/> + </fileheader> + +<!-- + File: Fokker-70.xml + Inputs: + name: Fokker-70 + type: two-engine transonic transport + max weight: 81011.7 lb + wing span: 92.13048 ft + length: 91.47428 ft + wing area: 1006.5275 sq-ft + gear type: tricycle + retractable?: yes + # engines: 2 + engine type: turbine + engine layout: aft fuselage + yaw damper? yes + + Outputs: + wing loading: 80.49 lb/sq-ft + CL-alpha: 4.4 per radian + CL-0: 0.2 + CL-max: 1.72 + CD-0: 0.02 + K: 0.043 + +--> + + + <metrics> + <wingarea unit="FT2"> 1006.53 </wingarea> + <wingspan unit="FT" > 92.13 </wingspan> + <wing_incidence> 2.00 </wing_incidence> + <chord unit="FT" > 12.4671 </chord> + <htailarea unit="FT2"> 233.792 </htailarea> + <htailarm unit="FT" > 47.2440 </htailarm> + <vtailarea unit="FT2"> 132.396 </vtailarea> + <vtailarm unit="FT" > 37.4015 </vtailarm> + <location name="AERORP" unit="IN"> + <x> 587.73 </x> + <y> 0.00 </y> + <z> 38.00 </z> + </location> + <location name="EYEPOINT" unit="IN"> + <x> 76.84 </x> + <y> -30.00 </y> + <z> 88.94 </z> + </location> + <location name="VRP" unit="IN"> + <x> 101.65 </x> + <y> 0.0 </y> + <z> 0.0 </z> + </location> + </metrics> + + <mass_balance> + <ixx unit="SLUG*FT2"> 200203 </ixx> + <iyy unit="SLUG*FT2"> 455983 </iyy> + <izz unit="SLUG*FT2"> 672987 </izz> + <emptywt unit="LBS" > 49985 </emptywt> + <location name="CG" unit="IN"> + <x> 605.73 </x> + <y> 0.00 </y> + <z> 38.12 </z> + </location> + + <pointmass name="pilot"> + <weight unit="LBS"> 230 </weight> + <location name="POINTMASS" unit="IN"> + <x> 96.84 </x> + <y> -30.0 </y> + <z> 66.0 </z> + </location> + </pointmass> + <pointmass name="copilot"> + <weight unit="LBS"> 230 </weight> + <location name="POINTMASS" unit="IN"> + <x> 96.84 </x> + <y> 30.0 </y> + <z> 66.0 </z> + </location> + </pointmass> + <pointmass name="steward"> + <weight unit="LBS"> 400 </weight> + <location name="POINTMASS" unit="IN"> + <x> 206 </x> + <y> 30.0 </y> + <z> 66.0 </z> + </location> + </pointmass> + + </mass_balance> + + <ground_reactions> + + <contact type="BOGEY" name="NOSE"> + <location unit="IN"> + <x> 142.70 </x> + <y> 0.00 </y> + <z> -55.73 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 7750.51 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 1600.17 </damping_coeff> + <max_steer unit="DEG"> 5.00 </max_steer> + <brake_group>NONE</brake_group> + <retractable>1</retractable> + </contact> + + <contact type="BOGEY" name="LEFT_MAIN"> + <location unit="IN"> + <x> 627.88 </x> + <y>-101.65 </y> + <z> -63.53 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 81011.70 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 16202.34 </damping_coeff> + <max_steer unit="DEG">0</max_steer> + <brake_group>LEFT</brake_group> + <retractable>1</retractable> + </contact> + + <contact type="BOGEY" name="RIGHT_MAIN"> + <location unit="IN"> + <x> 627.88 </x> + <y> 101.65 </y> + <z> -63.53 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 81011.70 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 16202.34 </damping_coeff> + <max_steer unit="DEG">0</max_steer> + <brake_group>RIGHT</brake_group> + <retractable>1</retractable> + </contact> + + <contact type="STRUCTURE" name="LEFT_WING"> + <location unit="IN"> + <x> 603.73 </x> + <y>-1105.4 </y> + <z> 0.0 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <spring_coeff unit="LBS/FT"> 81011.70 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 16202.34 </damping_coeff> + </contact> + + <contact type="STRUCTURE" name="RIGHT_WING"> + <location unit="IN"> + <x> 603.73 </x> + <y> 1105.4 </y> + <z> 0.0 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <spring_coeff unit="LBS/FT"> 81011.70 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 16202.34 </damping_coeff> + </contact> + + </ground_reactions> + + <external_reactions> + <force name="pushback" frame="BODY"> + <location unit="IN"> + <x>-139</x> + <y>0</y> + <z>-71</z> + </location> + <direction> + <x>1</x> + <y>0</y> + <z>0</z> + </direction> + </force> + </external_reactions> + + <propulsion> + + <engine file="Tay-620"> + <location unit="IN"> + <x> 893.52 </x> + <y> -101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + <feed>0</feed> + <thruster file="direct"> + <location unit="IN"> + <x> 893.52 </x> + <y> -101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + </thruster> + </engine> + + <engine file="Tay-620"> + <location unit="IN"> + <x> 893.52 </x> + <y> 101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + <feed>1</feed> + <thruster file="direct"> + <location unit="IN"> + <x> 893.52 </x> + <y> 101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + </thruster> + </engine> + + <tank type="FUEL" number="0"> + <location unit="IN"> + <x> 601.73 </x> + <y>-190.59 </y> + <z> 0.0 </z> + </location> + <capacity unit="LBS"> 1174.08 </capacity> + <contents unit="LBS"> 587.04 </contents> + </tank> + + <tank type="FUEL" number="1"> + <location unit="IN"> + <x> 601.73 </x> + <y> 190.59 </y> + <z> 0.0 </z> + </location> + <capacity unit="LBS"> 1174.08 </capacity> + <contents unit="LBS"> 587.04 </contents> + </tank> +<!-- + <tank type="FUEL" number="2"> + <location unit="IN"> + <x> 603.73 </x> + <y> 0.00 </y> + <z> -27.44 </z> + </location> + <capacity unit="LBS"> 1174.08 </capacity> + <contents unit="LBS"> 587.04 </contents> + </tank> +--> + </propulsion> + + <system file="pushback"/> + + <flight_control name="FCS: Fokker-70"> + + <channel name="Pitch"> + <summer name="fcs/pitch-trim-sum"> + <input>fcs/elevator-cmd-norm</input> + <input>fcs/pitch-trim-cmd-norm</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + </summer> + + <aerosurface_scale name="fcs/elevator-control"> + <input>fcs/pitch-trim-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/elevator-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/elevator-normalization"> + <input>fcs/elevator-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/elevator-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Roll"> + <summer name="fcs/roll-trim-sum"> + <input>fcs/aileron-cmd-norm</input> + <input>fcs/roll-trim-cmd-norm</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + </summer> + + <aerosurface_scale name="fcs/left-aileron-control"> + <input>fcs/roll-trim-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/left-aileron-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/right-aileron-control"> + <input>fcs/roll-trim-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/right-aileron-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/left-aileron-normalization"> + <input>fcs/left-aileron-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/left-aileron-pos-norm</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/right-aileron-normalization"> + <input>fcs/right-aileron-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/right-aileron-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Yaw"> + <summer name="fcs/rudder-command-sum"> + <input>fcs/rudder-cmd-norm</input> + <input>fcs/yaw-trim-cmd-norm</input> + <clipto> + <min> -0.35 </min> + <max> 0.35 </max> + </clipto> + </summer> + + <scheduled_gain name="fcs/yaw-damper-rate"> + <input>velocities/r-aero-rad_sec</input> + <table> + <independentVar lookup="row">velocities/ve-kts</independentVar> + <tableData> + 30 0.00 + 60 2.00 + </tableData> + </table> + </scheduled_gain> + + <scheduled_gain name="fcs/yaw-damper-beta"> + <input>aero/beta-rad</input> + <table> + <independentVar lookup="row">velocities/ve-kts</independentVar> + <tableData> + 30 0.00 + 60 0.00 + </tableData> + </table> + </scheduled_gain> + + <summer name="fcs/yaw-damper-sum"> + <input>fcs/yaw-damper-beta</input> + <input>fcs/yaw-damper-rate</input> + <clipto> + <min> -0.1 </min> + <max> 0.1 </max> + </clipto> + </summer> + + <scheduled_gain name="fcs/yaw-damper-final"> + <input>fcs/yaw-damper-sum</input> + <table> + <independentVar lookup="row">velocities/ve-kts</independentVar> + <tableData> + 30 0.0 + 31 1.0 + </tableData> + </table> + </scheduled_gain> + + <summer name="fcs/rudder-sum"> + <input>fcs/rudder-command-sum</input> + <input>fcs/yaw-damper-final</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + </summer> + + <aerosurface_scale name="fcs/rudder-control"> + <input>fcs/rudder-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/rudder-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/rudder-normalization"> + <input>fcs/rudder-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/rudder-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Flaps"> + <kinematic name="fcs/flaps-control"> + <input>fcs/flap-cmd-norm</input> + <traverse> + <setting> + <position>0</position> + <time>0</time> + </setting> + <setting> + <position>8</position> + <time>3</time> + </setting> + <setting> + <position>15</position> + <time>3</time> + </setting> + <setting> + <position>25</position> + <time>4</time> + </setting> + <setting> + <position>42</position> + <time>4</time> + </setting> + </traverse> + <output>fcs/flap-pos-deg</output> + </kinematic> + + <aerosurface_scale name="fcs/flap-normalization"> + <input>fcs/flap-pos-deg</input> + <domain> + <min>0</min> + <max>42</max> + </domain> + <range> + <min>0</min> + <max>1</max> + </range> + <output>fcs/flap-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Landing Gear"> + <kinematic name="fcs/gear-control"> + <input>gear/gear-cmd-norm</input> + <traverse> + <setting> + <position> 0 </position> + <time> 0 </time> + </setting> + <setting> + <position> 1 </position> + <time> 5 </time> + </setting> + </traverse> + <output>gear/gear-pos-norm</output> + </kinematic> + + </channel> + + <channel name="Speedbrake"> + <kinematic name="fcs/speedbrake-control"> + <input>fcs/speedbrake-cmd-norm</input> + <traverse> + <setting> + <position> 0 </position> + <time> 0 </time> + </setting> + <setting> + <position> 1 </position> + <time> 1 </time> + </setting> + </traverse> + <output>fcs/speedbrake-pos-norm</output> + </kinematic> + + </channel> + + <channel name="Spoilers"> + <kinematic name="fcs/spoiler-control"> + <input>fcs/spoiler-cmd-norm</input> + <traverse> + <setting> + <position>0</position> + <time>0</time> + </setting> + <setting> + <position>1</position> + <time>1</time> + </setting> + </traverse> + <output>fcs/spoiler-pos-norm</output> + </kinematic> + </channel> + + </flight_control> + + + <aerodynamics> + + <function name="aero/function/kCDge"> + <description>Change_in_drag_due_to_ground_effect</description> + <product> + <table> + <independentVar>aero/h_b-mac-ft</independentVar> + <tableData> + 0.0000 0.0350 + 0.1000 0.4170 + 0.1500 0.5390 + 0.2000 0.6240 + 0.3000 0.7510 + 0.4000 0.8000 + 0.5000 0.8960 + 0.6000 0.9390 + 0.7000 0.9740 + 0.8000 0.9810 + 0.9000 0.9900 + 1.0000 0.9940 + 1.1000 1.0000 + </tableData> + </table> + </product> + </function> + + <function name="aero/function/kCLge"> + <description>Change_in_lift_due_to_ground_effect</description> + <product> + <table> + <independentVar>aero/h_b-mac-ft</independentVar> + <tableData> + 0.0000 1.3910 + 0.1000 1.2350 + 0.1500 1.1670 + 0.2000 1.1350 + 0.3000 1.0850 + 0.4000 1.1020 + 0.5000 1.0350 + 0.6000 1.0240 + 0.7000 1.0150 + 0.8000 1.0110 + 0.9000 1.0060 + 1.0000 1.0040 + 1.1000 1.0000 + </tableData> + </table> + </product> + </function> + + <axis name="DRAG"> + <function name="aero/coefficient/CD0"> + <description>Drag_at_zero_lift</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/function/kCDge</property> + <table> + <independentVar>aero/alpha-rad</independentVar> + <tableData> + -1.5700 1.5000 + -0.2600 0.0400 + 0.0000 0.0192 + 0.2600 0.0400 + 1.5700 1.5000 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/CDi"> + <description>Induced_drag</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/cl-squared</property> + <property>aero/function/kCDge</property> + <value>0.00717</value> + </product> + </function> + <function name="aero/coefficient/CDflap"> + <description>Drag_due_to_flaps</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/flap-pos-norm</property> + <property>aero/function/kCDge</property> + <value>0.0830</value> + </product> + </function> + <function name="aero/coefficient/CDmach"> + <description>Drag_due_to_mach</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <table> + <independentVar>velocities/mach</independentVar> + <tableData> + 0.0000 0.0000 + 0.6500 0.0000 + 0.7700 0.0015 + 0.8600 0.0200 + 1.1000 0.0390 + 1.8000 0.0260 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/CDgear"> + <description>Drag_due_to_gear</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>gear/gear-pos-norm</property> + <value>0.0120</value> + </product> + </function> + <function name="aero/coefficient/CDsb"> + <description>Drag_due_to_speedbrakes</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/speedbrake-pos-norm</property> + <value>0.1200</value> + </product> + </function> + <function name="aero/coefficient/CDsp"> + <description>Drag_due_to_spoilers</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/spoiler-pos-norm</property> + <value>0.0280</value> + </product> + </function> + <function name="aero/coefficient/CDrv"> + <description>Drag_due_to_reverse</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>propulsion/engine[0]/reverser-angle-rad</property> + <property>propulsion/engine[1]/reverser-angle-rad</property> + <value>0.0187</value> + </product> + </function> + <function name="aero/coefficient/CDbeta"> + <description>Drag_due_to_sideslip</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <table> + <independentVar>aero/beta-rad</independentVar> + <tableData> + -1.5700 1.2300 + -0.2600 0.0500 + 0.0000 0.0000 + 0.2600 0.0500 + 1.5700 1.2300 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/CDde"> + <description>Drag_due_to_Elevator_Deflection</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/mag-elevator-pos-rad</property> + <value>0.0590</value> + </product> + </function> + </axis> + + <axis name="SIDE"> + <function name="aero/coefficient/CYb"> + <description>Side_force_due_to_beta</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/beta-rad</property> + <value>-1.0000</value> + </product> + </function> + </axis> + + <axis name="LIFT"> + <function name="aero/coefficient/CLalpha"> + <description>Lift_due_to_alpha</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/function/kCLge</property> + <table> + <independentVar>aero/alpha-rad</independentVar> + <tableData> + -0.20 -0.680 + 0.00 0.217 + 0.23 1.300 + 0.60 0.600 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/dCLflap"> + <description>Delta_Lift_due_to_flaps</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/function/kCLge</property> + <table> + <independentVar>fcs/flap-pos-norm</independentVar> + <tableData> + 0.0000 0.0000 + 0.3570 0.4900 + 1.0000 1.1800 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/dCLsp"> + <description>Delta_Lift_due_to_spoiler</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/spoiler-pos-norm</property> + <property>aero/function/kCLge</property> + <value>-0.1200</value> + </product> + </function> + <function name="aero/coefficient/CLde"> + <description>Lift_due_to_Elevator_Deflection</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/elevator-pos-rad</property> + <value>0.2000</value> + </product> + </function> + </axis> + + <axis name="ROLL"> + <function name="aero/coefficient/Clb"> + <description>Roll_moment_due_to_beta</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>aero/beta-rad</property> + <value>-0.1000</value> + </product> + </function> + <function name="aero/coefficient/Clp"> + <description>Roll_moment_due_to_roll_rate</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>aero/bi2vel</property> + <property>velocities/p-aero-rad_sec</property> + <value>-0.4000</value> + </product> + </function> + <function name="aero/coefficient/Clr"> + <description>Roll_moment_due_to_yaw_rate</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>aero/bi2vel</property> + <property>velocities/r-aero-rad_sec</property> + <value>0.1500</value> + </product> + </function> + <function name="aero/coefficient/Clda"> + <description>Roll_moment_due_to_aileron</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>fcs/left-aileron-pos-rad</property> + <table> + <independentVar>velocities/mach</independentVar> + <tableData> + 0.0000 0.1000 + 2.0000 0.0330 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/Cldr"> + <description>Roll_moment_due_to_rudder</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>fcs/rudder-pos-rad</property> + <value>0.0100</value> + </product> + </function> + </axis> + + <axis name="PITCH"> + <function name="aero/function/kCmge"> + <description>Change_in_lift_due_to_ground_effect</description> + <product> + <table> + <independentVar>aero/h_b-mac-ft</independentVar> + <tableData> + 0.0000 1.2030 + 0.1000 1.1270 + 0.1500 1.0900 + 0.2000 1.0730 + 0.3000 1.0460 + 0.4000 1.0550 + 0.5000 1.0190 + 0.6000 1.0130 + 0.7000 1.0080 + 0.8000 1.0060 + 0.9000 1.0030 + 1.0000 1.0020 + 1.1000 1.0000 + </tableData> + </table> + </product> + </function> + + <function name="aero/coefficient/Cmo"> + <description>Pitching_moment_at_zero_alpha</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/cbarw-ft</property> + <property>aero/function/kCmge</property> + <value>-0.000737</value> + </product> + </function> + <function name="aero/coefficient/Cmalpha"> + <description>Pitch_moment_due_to_alpha</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/cbarw-ft</property> + <property>aero/alpha-rad</property> + <value>-0.6000</value> + </product> + </function> + <function name="aero/coefficient/Cmde"> + <description>Pitch_moment_due_to_elevator</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/cbarw-ft</property> + <property>fcs/elevator-pos-rad</property> + <table> + <independentVar>velocities/mach</independentVar> + <tableData> + 0.0000 -1.2000 + 2.0000 -0.3000 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/Cmq"> + <description>Pitch_moment_due_to_pitch_rate</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/cbarw-ft</property> + <property>aero/ci2vel</property> + <property>velocities/q-aero-rad_sec</property> + <value>-31.0000</value> + </product> + </function> + <function name="aero/coefficient/Cmadot"> + <description>Pitch_moment_due_to_alpha_rate</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/cbarw-ft</property> + <property>aero/ci2vel</property> + <property>aero/alphadot-rad_sec</property> + <value>-16.0000</value> + </product> + </function> + </axis> + + <axis name="YAW"> + <function name="aero/coefficient/Cnb"> + <description>Yaw_moment_due_to_beta</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>aero/beta-rad</property> + <value>0.1200</value> + </product> + </function> + <function name="aero/coefficient/Cnr"> + <description>Yaw_moment_due_to_yaw_rate</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>aero/bi2vel</property> + <property>velocities/r-aero-rad_sec</property> + <value>-0.1500</value> + </product> + </function> + <function name="aero/coefficient/Cndr"> + <description>Yaw_moment_due_to_rudder</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>fcs/rudder-pos-rad</property> + <value>-0.1000</value> + </product> + </function> + <function name="aero/coefficient/Cnda"> + <description>Adverse_yaw</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>fcs/left-aileron-pos-rad</property> + <value>0.0000</value> + </product> + </function> + </axis> + </aerodynamics> +</fdm_config> diff --git a/aircraft/fokker100/xf100.xml b/aircraft/fokker100/xf100.xml new file mode 100644 index 0000000000000000000000000000000000000000..ba754c75e5845d30c7c6e7d6d9155187df4b8863 --- /dev/null +++ b/aircraft/fokker100/xf100.xml @@ -0,0 +1,988 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/xsl" href="http://jsbsim.sourceforge.net/JSBSim.xsl"?> +<fdm_config name="Fokker-100" version="2.0" release="ALPHA" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://jsbsim.sourceforge.net/JSBSim.xsd"> + + <fileheader> + <author> Erik Hofman </author> + <filecreationdate> 2010-08-08 </filecreationdate> + <version>$Revision: 1.3 $</version> + <description> Fokker-100 commercial airliner </description> + <reference title="Butterworth-Heinemann - Civil Jet Aircraft Design (BH) + http://www.elsevierdirect.com/companions/9780340741528/appendices/data-a/table-8/table.htm"/> + <reference title="Lissys - PIANO aircraft analysis software + http://www.lissys.demon.co.uk/f7tx2.html"/> + <reference title="Aerodynamic Design of Transport Aircraft + http://www.scribd.com/doc/23956816/Aerodynamic-Design-of-Transport-Aircraft"/> + </fileheader> + +<!-- + File: xf100.xml + Inputs: + name: NG-Aircraft XF-100 (Fokker 100NG) + type: two-engine transonic transport + max weight: 95013.45 lb + wing span: 92.13048 ft + length: 106.6325 ft + wing area: 1025.9045 sq-ft + gear type: tricycle + retractable?: yes + # engines: 2 + engine type: turbine + engine layout: aft fuselage + yaw damper? yes + + Outputs: + wing loading: 83.35 lb/sq-ft + CL-alpha: 4.4 per radian + CL-0: 0.2 + CL-max: 1.72 + CD-0: 0.02 + K: 0.043 + +--> + + <metrics> + <wingarea unit="FT2"> 1025.90 </wingarea> + <wingspan unit="FT" > 92.13 </wingspan> + <wing_incidence> 2.00 </wing_incidence> + <chord unit="FT" > 12.4671 </chord> + <htailarea unit="FT2"> 233.792 </htailarea> + <htailarm unit="FT" > 52.4934 </htailarm> + <vtailarea unit="FT2"> 132.396 </vtailarea> + <vtailarm unit="FT" > 44.6194 </vtailarm> + <location name="AERORP" unit="IN"> + <x> 699.48 </x> <!-- 668.48 --> + <y> 0.00 </y> + <z> 38.00 </z> + </location> + <location name="EYEPOINT" unit="IN"> + <x> 122.04 </x> + <y> -30.00 </y> + <z> 88.94 </z> + </location> + <location name="VRP" unit="IN"> + <x> 101.65 </x> + <y> 0.0 </y> + <z> 0.0 </z> + </location> + </metrics> + + <mass_balance> + <ixx unit="SLUG*FT2"> 218368 </ixx> + <iyy unit="SLUG*FT2"> 675849 </iyy> + <izz unit="SLUG*FT2"> 860261 </izz> + <emptywt unit="LBS" > 51307 </emptywt> + <location name="CG" unit="IN"> + <x> 719.81 </x> <!-- 693.81 --> + <y> 0.00 </y> + <z> 38.12 </z> + </location> + <pointmass name="pilot"> + <weight unit="LBS"> 230 </weight> + <location name="POINTMASS" unit="IN"> + <x> 122.04 </x> + <y> -30.0 </y> + <z> 66.0 </z> + </location> + </pointmass> + <pointmass name="copilot"> + <weight unit="LBS"> 230 </weight> + <location name="POINTMASS" unit="IN"> + <x> 122.04 </x> + <y> 30.0 </y> + <z> 66.0 </z> + </location> + </pointmass> + <pointmass name="steward"> + <weight unit="LBS"> 400 </weight> + <location name="POINTMASS" unit="IN"> + <x> 218 </x> + <y> 32.0 </y> + <z> 66.0 </z> + </location> + </pointmass> + </mass_balance> + + <ground_reactions> + + <contact type="BOGEY" name="NOSE"> + <location unit="IN"> + <x> 172.87 </x> + <y> 0.00 </y> + <z> -55.73 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 7750.03 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 1600.34 </damping_coeff> + <max_steer unit="DEG"> 5.00 </max_steer> + <brake_group>NONE</brake_group> + <retractable>1</retractable> + </contact> + + <contact type="BOGEY" name="LEFT_MAIN"> + <location unit="IN"> + <x> 731.93 </x> + <y>-101.65 </y> + <z> -63.53 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 95013.45 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 19002.69 </damping_coeff> + <max_steer unit="DEG">0</max_steer> + <brake_group>LEFT</brake_group> + <retractable>1</retractable> + </contact> + + <contact type="BOGEY" name="RIGHT_MAIN"> + <location unit="IN"> + <x> 731.93 </x> + <y> 101.65 </y> + <z> -63.53 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <rolling_friction> 0.02 </rolling_friction> + <spring_coeff unit="LBS/FT"> 95013.45 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 19002.69 </damping_coeff> + <max_steer unit="DEG">0</max_steer> + <brake_group>RIGHT</brake_group> + <retractable>1</retractable> + </contact> + + <contact type="STRUCTURE" name="LEFT_WING"> + <location unit="IN"> + <x> 753.77 </x> + <y>-1105.4 </y> + <z> 0.0 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <spring_coeff unit="LBS/FT"> 95013.45 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 19002.69 </damping_coeff> + </contact> + + <contact type="STRUCTURE" name="RIGHT_WING"> + <location unit="IN"> + <x> 753.77 </x> + <y> 1105.4 </y> + <z> 0.0 </z> + </location> + <static_friction> 0.80 </static_friction> + <dynamic_friction> 0.50 </dynamic_friction> + <spring_coeff unit="LBS/FT"> 95013.45 </spring_coeff> + <damping_coeff unit="LBS/FT/SEC"> 19002.69 </damping_coeff> + </contact> + + </ground_reactions> + + <external_reactions> + <force name="pushback" frame="BODY"> + <location unit="IN"> + <x>-139</x> + <y>0</y> + <z>-71</z> + </location> + <direction> + <x>1</x> + <y>0</y> + <z>0</z> + </direction> + </force> + </external_reactions> + + <propulsion> + + <engine file="BR-725"> + <location unit="IN"> + <x> 922.52 </x> + <y> -101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + <feed>0</feed> + <thruster file="direct"> + <location unit="IN"> + <x> 922.52 </x> + <y> -101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + </thruster> + </engine> + + <engine file="BR-725"> + <location unit="IN"> + <x> 922.52 </x> + <y> 101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + <feed>1</feed> + <thruster file="direct"> + <location unit="IN"> + <x> 922.52 </x> + <y> 101.65 </y> + <z> 43.53 </z> + </location> + <orient unit="DEG"> + <pitch> 0.00 </pitch> + <roll> 0.00 </roll> + <yaw> 0.00 </yaw> + </orient> + </thruster> + </engine> + + <tank type="FUEL" number="0"> + <location unit="IN"> + <x> 713.81 </x> + <y>-190.59 </y> + <z> 0.0 </z> + </location> + <capacity unit="LBS"> 13360.01 </capacity> + <contents unit="LBS"> 688.50 </contents> + </tank> + + <tank type="FUEL" number="1"> + <location unit="IN"> + <x> 713.81 </x> + <y> 190.59 </y> + <z> 0.0 </z> + </location> + <capacity unit="LBS"> 13360.01 </capacity> + <contents unit="LBS"> 688.50 </contents> + </tank> + <tank type="FUEL" number="2"> + <location unit="IN"> + <x> 703.77 </x> + <y> 0.00 </y> + <z> -31.99 </z> + </location> + <capacity unit="LBS"> 1377.01 </capacity> + <contents unit="LBS"> 688.50 </contents> + </tank> + </propulsion> + + <system file="pushback"/> + + <flight_control name="FCS: Fokker-100"> + + <channel name="Pitch"> + <summer name="fcs/pitch-trim-sum"> + <input>fcs/elevator-cmd-norm</input> + <input>fcs/pitch-trim-cmd-norm</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + </summer> + + <aerosurface_scale name="fcs/elevator-control"> + <input>fcs/pitch-trim-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/elevator-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/elevator-normalization"> + <input>fcs/elevator-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/elevator-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Roll"> + <summer name="fcs/roll-trim-sum"> + <input>fcs/aileron-cmd-norm</input> + <input>fcs/roll-trim-cmd-norm</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + </summer> + + <aerosurface_scale name="fcs/left-aileron-control"> + <input>fcs/roll-trim-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/left-aileron-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/right-aileron-control"> + <input>fcs/roll-trim-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/right-aileron-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/left-aileron-normalization"> + <input>fcs/left-aileron-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/left-aileron-pos-norm</output> + </aerosurface_scale> + + <aerosurface_scale name="fcs/right-aileron-normalization"> + <input>fcs/right-aileron-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/right-aileron-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Yaw"> + <summer name="fcs/rudder-command-sum"> + <input>fcs/rudder-cmd-norm</input> + <input>fcs/yaw-trim-cmd-norm</input> + <clipto> + <min> -0.35 </min> + <max> 0.35 </max> + </clipto> + </summer> + + <scheduled_gain name="fcs/yaw-damper-rate"> + <input>velocities/r-aero-rad_sec</input> + <table> + <independentVar lookup="row">velocities/ve-kts</independentVar> + <tableData> + 30 0.00 + 60 2.00 + </tableData> + </table> + </scheduled_gain> + + <scheduled_gain name="fcs/yaw-damper-beta"> + <input>aero/beta-rad</input> + <table> + <independentVar lookup="row">velocities/ve-kts</independentVar> + <tableData> + 30 0.00 + 60 0.00 + </tableData> + </table> + </scheduled_gain> + + <summer name="fcs/yaw-damper-sum"> + <input>fcs/yaw-damper-beta</input> + <input>fcs/yaw-damper-rate</input> + <clipto> + <min> -0.1 </min> + <max> 0.1 </max> + </clipto> + </summer> + + <scheduled_gain name="fcs/yaw-damper-final"> + <input>fcs/yaw-damper-sum</input> + <table> + <independentVar lookup="row">velocities/ve-kts</independentVar> + <tableData> + 30 0.0 + 31 1.0 + </tableData> + </table> + </scheduled_gain> + + <summer name="fcs/rudder-sum"> + <input>fcs/rudder-command-sum</input> + <input>fcs/yaw-damper-final</input> + <clipto> + <min> -1 </min> + <max> 1 </max> + </clipto> + </summer> + + <aerosurface_scale name="fcs/rudder-control"> + <input>fcs/rudder-sum</input> + <range> + <min> -0.35 </min> + <max> 0.35 </max> + </range> + <output>fcs/rudder-pos-rad</output> + </aerosurface_scale> + + <aerosurface_scale name="rcs/rudder-normalization"> + <input>fcs/rudder-pos-rad</input> + <domain> + <min> -0.35 </min> + <max> 0.35 </max> + </domain> + <range> + <min> -1 </min> + <max> 1 </max> + </range> + <output>fcs/rudder-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Flaps"> + <kinematic name="fcs/flaps-control"> + <input>fcs/flap-cmd-norm</input> + <traverse> + <setting> + <position>0</position> + <time>0</time> + </setting> + <setting> + <position>8</position> + <time>3</time> + </setting> + <setting> + <position>15</position> + <time>3</time> + </setting> + <setting> + <position>25</position> + <time>4</time> + </setting> + <setting> + <position>42</position> + <time>4</time> + </setting> + </traverse> + <output>fcs/flap-pos-deg</output> + </kinematic> + + <aerosurface_scale name="fcs/flap-normalization"> + <input>fcs/flap-pos-deg</input> + <domain> + <min>0</min> + <max>42</max> + </domain> + <range> + <min>0</min> + <max>1</max> + </range> + <output>fcs/flap-pos-norm</output> + </aerosurface_scale> + + </channel> + + <channel name="Landing Gear"> + <kinematic name="fcs/gear-control"> + <input>gear/gear-cmd-norm</input> + <traverse> + <setting> + <position> 0 </position> + <time> 0 </time> + </setting> + <setting> + <position> 1 </position> + <time> 5 </time> + </setting> + </traverse> + <output>gear/gear-pos-norm</output> + </kinematic> + + </channel> + + <channel name="Speedbrake"> + <kinematic name="fcs/speedbrake-control"> + <input>fcs/speedbrake-cmd-norm</input> + <traverse> + <setting> + <position> 0 </position> + <time> 0 </time> + </setting> + <setting> + <position> 1 </position> + <time> 1 </time> + </setting> + </traverse> + <output>fcs/speedbrake-pos-norm</output> + </kinematic> + </channel> + + + <channel name="Spoilers"> + <kinematic name="fcs/spoiler-control"> + <input>fcs/spoiler-cmd-norm</input> + <traverse> + <setting> + <position>0</position> + <time>0</time> + </setting> + <setting> + <position>1</position> + <time>1</time> + </setting> + </traverse> + <output>fcs/spoiler-pos-norm</output> + </kinematic> + </channel> + </flight_control> + + <aerodynamics> + + <function name="aero/function/kCDge"> + <description>Change_in_drag_due_to_ground_effect</description> + <product> + <table> + <independentVar>aero/h_b-mac-ft</independentVar> + <tableData> + 0.0000 0.0350 + 0.1000 0.4170 + 0.1500 0.5390 + 0.2000 0.6240 + 0.3000 0.7510 + 0.4000 0.8000 + 0.5000 0.8960 + 0.6000 0.9390 + 0.7000 0.9740 + 0.8000 0.9810 + 0.9000 0.9900 + 1.0000 0.9940 + 1.1000 1.0000 + </tableData> + </table> + </product> + </function> + + <function name="aero/function/kCLge"> + <description>Change_in_lift_due_to_ground_effect</description> + <product> + <table> + <independentVar>aero/h_b-mac-ft</independentVar> + <tableData> + 0.0000 1.3910 + 0.1000 1.2350 + 0.1500 1.1670 + 0.2000 1.1350 + 0.3000 1.0850 + 0.4000 1.1020 + 0.5000 1.0350 + 0.6000 1.0240 + 0.7000 1.0150 + 0.8000 1.0110 + 0.9000 1.0060 + 1.0000 1.0040 + 1.1000 1.0000 + </tableData> + </table> + </product> + </function> + + <axis name="DRAG"> + <function name="aero/coefficient/CD0"> + <description>Drag_at_zero_lift</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/function/kCDge</property> + <table> + <independentVar>aero/alpha-rad</independentVar> + <tableData> + -1.5700 1.5000 + -0.2600 0.0392 + 0.0000 0.01884 + 0.2600 0.0392 + 1.5700 1.4700 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/CDi"> + <description>Induced_drag</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/cl-squared</property> + <property>aero/function/kCDge</property> + <value>0.00717</value> + </product> + </function> + <function name="aero/coefficient/CDflap"> + <description>Drag_due_to_flaps</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/flap-pos-norm</property> + <property>aero/function/kCDge</property> + <value>0.0830</value> + </product> + </function> + <function name="aero/coefficient/CDmach"> + <description>Drag_due_to_mach</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <table> + <independentVar>velocities/mach</independentVar> + <tableData> + 0.0000 0.0000 + 0.6500 0.0000 + 0.7700 0.0015 + 0.8600 0.0200 + 1.1000 0.0390 + 1.8000 0.0260 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/CDgear"> + <description>Drag_due_to_gear</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>gear/gear-pos-norm</property> + <value>0.0120</value> + </product> + </function> + <function name="aero/coefficient/CDsb"> + <description>Drag_due_to_speedbrakes</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/speedbrake-pos-norm</property> + <value>0.1200</value> + </product> + </function> + <function name="aero/coefficient/CDsp"> + <description>Drag_due_to_spoilers</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/spoiler-pos-norm</property> + <value>0.0280</value> + </product> + </function> + <function name="aero/coefficient/CDrv"> + <description>Drag_due_to_reverse</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>propulsion/engine[0]/reverser-angle-rad</property> + <property>propulsion/engine[1]/reverser-angle-rad</property> + <value>0.0187</value> + </product> + </function> + <function name="aero/coefficient/CDbeta"> + <description>Drag_due_to_sideslip</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <table> + <independentVar>aero/beta-rad</independentVar> + <tableData> + -1.5700 1.2300 + -0.2600 0.0500 + 0.0000 0.0000 + 0.2600 0.0500 + 1.5700 1.2300 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/CDde"> + <description>Drag_due_to_Elevator_Deflection</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/mag-elevator-pos-rad</property> + <value>0.0590</value> + </product> + </function> + </axis> + + <axis name="SIDE"> + <function name="aero/coefficient/CYb"> + <description>Side_force_due_to_beta</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/beta-rad</property> + <value>-1.0000</value> + </product> + </function> + </axis> + + <axis name="LIFT"> + <function name="aero/coefficient/CLalpha"> + <description>Lift_due_to_alpha</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/function/kCLge</property> + <table> + <independentVar>aero/alpha-rad</independentVar> + <tableData> + -0.20 -0.680 + 0.00 0.221 + 0.23 1.300 + 0.60 0.612 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/dCLflap"> + <description>Delta_Lift_due_to_flaps</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>aero/function/kCLge</property> + <table> + <independentVar>fcs/flap-pos-norm</independentVar> + <tableData> + 0.0000 0.0000 + 0.3570 0.4900 + 1.0000 1.1800 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/dCLsp"> + <description>Delta_Lift_due_to_spoiler</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/spoiler-pos-norm</property> + <property>aero/function/kCLge</property> + <value>-0.1200</value> + </product> + </function> + <function name="aero/coefficient/CLde"> + <description>Lift_due_to_Elevator_Deflection</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>fcs/elevator-pos-rad</property> + <value>0.2000</value> + </product> + </function> + </axis> + + <axis name="ROLL"> + <function name="aero/coefficient/Clb"> + <description>Roll_moment_due_to_beta</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>aero/beta-rad</property> + <value>-0.1000</value> + </product> + </function> + <function name="aero/coefficient/Clp"> + <description>Roll_moment_due_to_roll_rate</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>aero/bi2vel</property> + <property>velocities/p-aero-rad_sec</property> + <value>-0.4000</value> + </product> + </function> + <function name="aero/coefficient/Clr"> + <description>Roll_moment_due_to_yaw_rate</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>aero/bi2vel</property> + <property>velocities/r-aero-rad_sec</property> + <value>0.1500</value> + </product> + </function> + <function name="aero/coefficient/Clda"> + <description>Roll_moment_due_to_aileron</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>fcs/left-aileron-pos-rad</property> + <table> + <independentVar>velocities/mach</independentVar> + <tableData> + 0.0000 0.1000 + 2.0000 0.0330 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/Cldr"> + <description>Roll_moment_due_to_rudder</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>fcs/rudder-pos-rad</property> + <value>0.0100</value> + </product> + </function> + </axis> + + <axis name="PITCH"> + <function name="aero/function/kCmge"> + <description>Change_in_lift_due_to_ground_effect</description> + <product> + <table> + <independentVar>aero/h_b-mac-ft</independentVar> + <tableData> + 0.0000 1.2030 + 0.1000 1.1270 + 0.1500 1.0900 + 0.2000 1.0730 + 0.3000 1.0460 + 0.4000 1.0550 + 0.5000 1.0190 + 0.6000 1.0130 + 0.7000 1.0080 + 0.8000 1.0060 + 0.9000 1.0030 + 1.0000 1.0020 + 1.1000 1.0000 + </tableData> + </table> + </product> + </function> + + <function name="aero/coefficient/Cmo"> + <description>Pitching_moment_at_zero_alpha</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/cbarw-ft</property> + <property>aero/function/kCmge</property> + <value>-0.000737</value> + </product> + </function> + <function name="aero/coefficient/Cmalpha"> + <description>Pitch_moment_due_to_alpha</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/cbarw-ft</property> + <property>aero/alpha-rad</property> + <value>-0.6000</value> + </product> + </function> + <function name="aero/coefficient/Cmde"> + <description>Pitch_moment_due_to_elevator</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/cbarw-ft</property> + <property>fcs/elevator-pos-rad</property> + <table> + <independentVar>velocities/mach</independentVar> + <tableData> + 0.0000 -1.2000 + 2.0000 -0.3000 + </tableData> + </table> + </product> + </function> + <function name="aero/coefficient/Cmq"> + <description>Pitch_moment_due_to_pitch_rate</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/cbarw-ft</property> + <property>aero/ci2vel</property> + <property>velocities/q-aero-rad_sec</property> + <value>-31.0000</value> + </product> + </function> + <function name="aero/coefficient/Cmadot"> + <description>Pitch_moment_due_to_alpha_rate</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/cbarw-ft</property> + <property>aero/ci2vel</property> + <property>aero/alphadot-rad_sec</property> + <value>-16.0000</value> + </product> + </function> + </axis> + + <axis name="YAW"> + <function name="aero/coefficient/Cnb"> + <description>Yaw_moment_due_to_beta</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>aero/beta-rad</property> + <value>0.1200</value> + </product> + </function> + <function name="aero/coefficient/Cnr"> + <description>Yaw_moment_due_to_yaw_rate</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>aero/bi2vel</property> + <property>velocities/r-aero-rad_sec</property> + <value>-0.1500</value> + </product> + </function> + <function name="aero/coefficient/Cndr"> + <description>Yaw_moment_due_to_rudder</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>fcs/rudder-pos-rad</property> + <value>-0.1000</value> + </product> + </function> + <function name="aero/coefficient/Cnda"> + <description>Adverse_yaw</description> + <product> + <property>aero/qbar-psf</property> + <property>metrics/Sw-sqft</property> + <property>metrics/bw-ft</property> + <property>fcs/left-aileron-pos-rad</property> + <value>0.0000</value> + </product> + </function> + </axis> + </aerodynamics> +</fdm_config> diff --git a/aircraft/mk82/reset01.xml b/aircraft/mk82/reset01.xml old mode 100644 new mode 100755 diff --git a/aircraft/t6texan2/t6texan2.xml b/aircraft/t6texan2/t6texan2.xml old mode 100644 new mode 100755 diff --git a/check_cases/Makefile.am b/check_cases/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/Makefile.am b/check_cases/ground_tests/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/aircraft/Makefile.am b/check_cases/ground_tests/aircraft/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/aircraft/groundtest/Makefile.am b/check_cases/ground_tests/aircraft/groundtest/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/aircraft/groundtest/groundtest.xml b/check_cases/ground_tests/aircraft/groundtest/groundtest.xml old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/aircraft/groundtest/reset00.xml b/check_cases/ground_tests/aircraft/groundtest/reset00.xml old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/data_output/Makefile.am b/check_cases/ground_tests/data_output/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/data_output/ground_reactions120hz.xml b/check_cases/ground_tests/data_output/ground_reactions120hz.xml old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/data_plot/Makefile.am b/check_cases/ground_tests/data_plot/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/engine/Makefile.am b/check_cases/ground_tests/engine/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/logged_data/Makefile.am b/check_cases/ground_tests/logged_data/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/scripts/Makefile.am b/check_cases/ground_tests/scripts/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/scripts/groundtest.xml b/check_cases/ground_tests/scripts/groundtest.xml old mode 100644 new mode 100755 diff --git a/check_cases/ground_tests/systems/Makefile.am b/check_cases/ground_tests/systems/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/orbit/.cvsignore b/check_cases/orbit/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..282522db0342d8750454b3dc162493b5fc709cc8 --- /dev/null +++ b/check_cases/orbit/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/check_cases/orbit/Makefile.am b/check_cases/orbit/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/orbit/aircraft/.cvsignore b/check_cases/orbit/aircraft/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..282522db0342d8750454b3dc162493b5fc709cc8 --- /dev/null +++ b/check_cases/orbit/aircraft/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/check_cases/orbit/aircraft/Makefile.am b/check_cases/orbit/aircraft/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/orbit/aircraft/ball/.cvsignore b/check_cases/orbit/aircraft/ball/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..282522db0342d8750454b3dc162493b5fc709cc8 --- /dev/null +++ b/check_cases/orbit/aircraft/ball/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/check_cases/orbit/aircraft/ball/Makefile.am b/check_cases/orbit/aircraft/ball/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/orbit/aircraft/ball/ball.xml b/check_cases/orbit/aircraft/ball/ball.xml old mode 100644 new mode 100755 diff --git a/check_cases/orbit/aircraft/ball/reset00.xml b/check_cases/orbit/aircraft/ball/reset00.xml old mode 100644 new mode 100755 diff --git a/check_cases/orbit/data_output/.cvsignore b/check_cases/orbit/data_output/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..282522db0342d8750454b3dc162493b5fc709cc8 --- /dev/null +++ b/check_cases/orbit/data_output/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/check_cases/orbit/data_output/Makefile.am b/check_cases/orbit/data_output/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/orbit/data_output/position.xml b/check_cases/orbit/data_output/position.xml old mode 100644 new mode 100755 diff --git a/check_cases/orbit/data_output/rates.xml b/check_cases/orbit/data_output/rates.xml old mode 100644 new mode 100755 diff --git a/check_cases/orbit/data_output/velocities.xml b/check_cases/orbit/data_output/velocities.xml old mode 100644 new mode 100755 diff --git a/check_cases/orbit/data_plot/.cvsignore b/check_cases/orbit/data_plot/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..282522db0342d8750454b3dc162493b5fc709cc8 --- /dev/null +++ b/check_cases/orbit/data_plot/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/check_cases/orbit/data_plot/Makefile.am b/check_cases/orbit/data_plot/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/orbit/data_plot/position.xml b/check_cases/orbit/data_plot/position.xml old mode 100644 new mode 100755 diff --git a/check_cases/orbit/data_plot/rates.xml b/check_cases/orbit/data_plot/rates.xml old mode 100644 new mode 100755 diff --git a/check_cases/orbit/data_plot/velocities.xml b/check_cases/orbit/data_plot/velocities.xml old mode 100644 new mode 100755 diff --git a/check_cases/orbit/engine/.cvsignore b/check_cases/orbit/engine/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..282522db0342d8750454b3dc162493b5fc709cc8 --- /dev/null +++ b/check_cases/orbit/engine/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/check_cases/orbit/engine/Makefile.am b/check_cases/orbit/engine/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/orbit/logged_data/.cvsignore b/check_cases/orbit/logged_data/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..282522db0342d8750454b3dc162493b5fc709cc8 --- /dev/null +++ b/check_cases/orbit/logged_data/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/check_cases/orbit/logged_data/Makefile.am b/check_cases/orbit/logged_data/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/orbit/scripts/.cvsignore b/check_cases/orbit/scripts/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..282522db0342d8750454b3dc162493b5fc709cc8 --- /dev/null +++ b/check_cases/orbit/scripts/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/check_cases/orbit/scripts/Makefile.am b/check_cases/orbit/scripts/Makefile.am old mode 100644 new mode 100755 diff --git a/check_cases/orbit/scripts/ball_orbit.xml b/check_cases/orbit/scripts/ball_orbit.xml old mode 100644 new mode 100755 diff --git a/check_cases/orbit/systems/.cvsignore b/check_cases/orbit/systems/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..282522db0342d8750454b3dc162493b5fc709cc8 --- /dev/null +++ b/check_cases/orbit/systems/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/check_cases/orbit/systems/Makefile.am b/check_cases/orbit/systems/Makefile.am old mode 100644 new mode 100755 diff --git a/configure.in b/configure.in index f7e65b90e7af3614f29f70ade530dba63c45b9aa..1de19794437a393597b2a41f1ac404e4993be9d3 100644 --- a/configure.in +++ b/configure.in @@ -1,10 +1,10 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT(JSBSim.cpp, 1.0, jon@jsbsim.org) +AC_INIT(JSBSim.cpp, 1.0-adv-trim, jon@jsbsim.org) dnl set the $host variable based on local machine/os AC_CANONICAL_TARGET -AM_INIT_AUTOMAKE(JSBSim, 1.0) +AM_INIT_AUTOMAKE(JSBSim, 1.0-adv-trim) AC_ARG_ENABLE([libraries], [AS_HELP_STRING([--enable-libraries], @@ -13,13 +13,6 @@ AC_ARG_ENABLE([libraries], [build_libraries=no]) AM_CONDITIONAL(BUILD_LIBRARIES, test "x$build_libraries" = xyes) -AC_ARG_ENABLE([scicoslab], - [AS_HELP_STRING([--enable-scicoslab], - [build Scicoslab components [default=no]])], - [build_scicoslab=$enableval], - [build_scicoslab=no]) -AM_CONDITIONAL(BUILD_SCICOSLAB, test "x$build_scicoslab" = xyes) - dnl Checks for programs. AC_DISABLE_SHARED AC_PROG_CPP @@ -84,6 +77,7 @@ AC_MSG_RESULT(size_t) AC_DEFINE(socklen_t,size_t)], [ AC_MSG_RESULT(int) AC_DEFINE(socklen_t,int)])]) + AC_OUTPUT( \ Makefile \ check_cases/Makefile \ @@ -146,6 +140,7 @@ AC_OUTPUT( \ aircraft/pc7/Makefile \ aircraft/OV10/Makefile \ aircraft/x24b/Makefile \ + aircraft/fokker100/Systems/Makefile \ aircraft/fokker100/Makefile \ aircraft/dr1/Makefile \ aircraft/737/Makefile \ @@ -157,11 +152,6 @@ AC_OUTPUT( \ aircraft/p51d/Makefile \ aircraft/p51d/Engines/Makefile \ aircraft/paraglider/Makefile \ - aircraft/EasyStar/Makefile \ - aircraft/EasyStar/Models/Makefile \ - aircraft/EasyStar/Datcom/Makefile \ - aircraft/EasyStar/scripts/Makefile \ - aircraft/EasyStar/Engines/Makefile \ aircraft/J246/Systems/Makefile \ aircraft/J246/Makefile \ aircraft/F4N/Makefile \ @@ -191,6 +181,5 @@ AC_OUTPUT( \ aircraft/X15/Makefile \ aircraft/F80C/Makefile \ aircraft/Boeing314/Makefile \ - data_plot/Makefile \ - scicoslab/Makefile + data_plot/Makefile ) diff --git a/data_output/aerodynamics.xml b/data_output/aerodynamics.xml old mode 100644 new mode 100755 diff --git a/data_output/aerosurfaces.xml b/data_output/aerosurfaces.xml old mode 100644 new mode 100755 diff --git a/data_output/atmosphere.xml b/data_output/atmosphere.xml old mode 100644 new mode 100755 diff --git a/data_output/fcs.xml b/data_output/fcs.xml old mode 100644 new mode 100755 diff --git a/data_output/ground_reactions.xml b/data_output/ground_reactions.xml old mode 100644 new mode 100755 diff --git a/data_output/position.xml b/data_output/position.xml old mode 100644 new mode 100755 diff --git a/data_output/rates.xml b/data_output/rates.xml old mode 100644 new mode 100755 diff --git a/data_output/velocities.xml b/data_output/velocities.xml old mode 100644 new mode 100755 diff --git a/data_plot/aerodynamics.xml b/data_plot/aerodynamics.xml old mode 100644 new mode 100755 diff --git a/data_plot/aerosurfaces.xml b/data_plot/aerosurfaces.xml old mode 100644 new mode 100755 diff --git a/data_plot/atmosphere.xml b/data_plot/atmosphere.xml old mode 100644 new mode 100755 diff --git a/data_plot/fcs.xml b/data_plot/fcs.xml old mode 100644 new mode 100755 diff --git a/data_plot/ground_reactions.xml b/data_plot/ground_reactions.xml old mode 100644 new mode 100755 diff --git a/data_plot/position.xml b/data_plot/position.xml old mode 100644 new mode 100755 diff --git a/data_plot/rates.xml b/data_plot/rates.xml old mode 100644 new mode 100755 diff --git a/data_plot/velocities.xml b/data_plot/velocities.xml old mode 100644 new mode 100755 diff --git a/engine/BR-725.xml b/engine/BR-725.xml new file mode 100644 index 0000000000000000000000000000000000000000..9c819aa3378657838adea51fea7eb4fe3b783ad8 --- /dev/null +++ b/engine/BR-725.xml @@ -0,0 +1,61 @@ +<?xml version="1.0"?> +<!-- + File: BR700-725.xml + Author: Aero-Matic v 0.81 + + Inputs: + name: BR700-725 + type: turbine + thrust: 15460 lb + augmented? no + injected? no +--> + +<turbine_engine name="BR700-725"> + <milthrust> 15460.0 </milthrust> + <bypassratio> 4.4 </bypassratio> + <tsfc> 0.657 </tsfc> + <bleed> 0.03</bleed> + <idlen1> 30.0 </idlen1> + <idlen2> 60.0 </idlen2> + <maxn1> 100.0 </maxn1> + <maxn2> 100.0 </maxn2> + <augmented> 0 </augmented> + <injected> 0 </injected> + + <function name="IdleThrust"> + <table> + <independentVar lookup="row">velocities/mach</independentVar> + <independentVar lookup="column">atmosphere/density-altitude</independentVar> + <tableData> + -10000 0 10000 20000 30000 40000 50000 + 0.0 0.0430 0.0488 0.0528 0.0694 0.0899 0.1183 0.1467 + 0.2 0.0500 0.0501 0.0335 0.0544 0.0797 0.1049 0.1342 + 0.4 0.0040 0.0047 0.0020 0.0272 0.0595 0.0891 0.1203 + 0.6 0.0 0.0 0.0 0.0 0.0276 0.0718 0.1073 + 0.8 0.0 0.0 0.0 0.0 0.0474 0.0868 0.0900 + 1.0 0.0 0.0 0.0 0.0 0.0 0.0552 0.0800 + </tableData> + </table> + </function> + + <function name="MilThrust"> + <table> + <independentVar lookup="row">velocities/mach</independentVar> + <independentVar lookup="column">atmosphere/density-altitude</independentVar> + <tableData> + -10000 0 10000 20000 30000 40000 50000 + 0.0 1.2600 1.0000 0.7400 0.5340 0.3720 0.2410 0.1490 + 0.2 1.1710 0.9340 0.6970 0.5060 0.3550 0.2310 0.1430 + 0.4 1.1500 0.9210 0.6920 0.5060 0.3570 0.2330 0.1450 + 0.6 1.1810 0.9510 0.7210 0.5320 0.3780 0.2480 0.1540 + 0.8 1.2580 1.0200 0.7820 0.5820 0.4170 0.2750 0.1700 + 1.0 1.3690 1.1200 0.8710 0.6510 0.4750 0.3150 0.1950 + 1.2 1.4850 1.2300 0.9750 0.7440 0.5450 0.3640 0.2250 + 1.4 1.5941 1.3400 1.0860 0.8450 0.6280 0.4240 0.2630 + </tableData> + </table> + </function> + +</turbine_engine> + diff --git a/engine/GE-CF6-80C2-B1F.xml b/engine/GE-CF6-80C2-B1F.xml old mode 100644 new mode 100755 diff --git a/engine/HamiltonStd6243A-3.xml b/engine/HamiltonStd6243A-3.xml old mode 100644 new mode 100755 diff --git a/engine/Makefile.am b/engine/Makefile.am index 04375a096dbf6bc5f371094674316270e1f159f7..3e5fc1892064961dcc12b5148470ac274490959b 100644 --- a/engine/Makefile.am +++ b/engine/Makefile.am @@ -47,6 +47,7 @@ engine_DATA = \ R-1820-97.xml \ RB211-524.xml \ J79-GE-11A.xml \ + BR-725.xml \ RollsRoyce.xml \ J52.xml \ propHO-V373-D.xml \ @@ -71,6 +72,7 @@ engine_DATA = \ J69-T25.xml \ TRENT-900.xml \ RL10.xml \ + Tay-620.xml \ eng_io320.xml \ CFM56_5.xml \ prop_75in2f.xml \ diff --git a/engine/Olympus593Mrk610.xml b/engine/Olympus593Mrk610.xml old mode 100644 new mode 100755 diff --git a/engine/P51prop.xml b/engine/P51prop.xml old mode 100644 new mode 100755 diff --git a/engine/R-1820-97.xml b/engine/R-1820-97.xml old mode 100644 new mode 100755 diff --git a/engine/RL10.xml b/engine/RL10.xml old mode 100644 new mode 100755 diff --git a/engine/RL10_nozzle.xml b/engine/RL10_nozzle.xml old mode 100644 new mode 100755 diff --git a/engine/SRB.xml b/engine/SRB.xml old mode 100644 new mode 100755 diff --git a/engine/SRB_nozzle.xml b/engine/SRB_nozzle.xml old mode 100644 new mode 100755 diff --git a/engine/SSME.xml b/engine/SSME.xml old mode 100644 new mode 100755 diff --git a/engine/SSME_nozzle.xml b/engine/SSME_nozzle.xml old mode 100644 new mode 100755 diff --git a/engine/Tay-620.xml b/engine/Tay-620.xml new file mode 100644 index 0000000000000000000000000000000000000000..d1dff8cfb055627134ddb9b2f3d75038ec5429f1 --- /dev/null +++ b/engine/Tay-620.xml @@ -0,0 +1,61 @@ +<?xml version="1.0"?> +<!-- + File: my_engine.xml + Author: Aero-Matic v 0.81 + + Inputs: + name: my_engine + type: turbine + thrust: 13847.68 lb + augmented? no + injected? no +--> + +<turbine_engine name="Tay-620"> + <milthrust> 13847.7 </milthrust> + <bypassratio> 3.04 </bypassratio> + <tsfc> 0.69 </tsfc> + <bleed> 0.03</bleed> + <idlen1> 30.0 </idlen1> + <idlen2> 60.0 </idlen2> + <maxn1> 100.0 </maxn1> + <maxn2> 100.0 </maxn2> + <augmented> 0 </augmented> + <injected> 0 </injected> + + <function name="IdleThrust"> + <table> + <independentVar lookup="row">velocities/mach</independentVar> + <independentVar lookup="column">atmosphere/density-altitude</independentVar> + <tableData> + -10000 0 10000 20000 30000 40000 50000 + 0.0 0.0430 0.0488 0.0528 0.0694 0.0899 0.1183 0.1467 + 0.2 0.0500 0.0501 0.0335 0.0544 0.0797 0.1049 0.1342 + 0.4 0.0040 0.0047 0.0020 0.0272 0.0595 0.0891 0.1203 + 0.6 0.0 0.0 0.0 0.0 0.0276 0.0718 0.1073 + 0.8 0.0 0.0 0.0 0.0 0.0474 0.0868 0.0900 + 1.0 0.0 0.0 0.0 0.0 0.0 0.0552 0.0800 + </tableData> + </table> + </function> + + <function name="MilThrust"> + <table> + <independentVar lookup="row">velocities/mach</independentVar> + <independentVar lookup="column">atmosphere/density-altitude</independentVar> + <tableData> + -10000 0 10000 20000 30000 40000 50000 + 0.0 1.2600 1.0000 0.7400 0.5340 0.3720 0.2410 0.1490 + 0.2 1.1710 0.9340 0.6970 0.5060 0.3550 0.2310 0.1430 + 0.4 1.1500 0.9210 0.6920 0.5060 0.3570 0.2330 0.1450 + 0.6 1.1810 0.9510 0.7210 0.5320 0.3780 0.2480 0.1540 + 0.8 1.2580 1.0200 0.7820 0.5820 0.4170 0.2750 0.1700 + 1.0 1.3690 1.1200 0.8710 0.6510 0.4750 0.3150 0.1950 + 1.2 1.4850 1.2300 0.9750 0.7440 0.5450 0.3640 0.2250 + 1.4 1.5941 1.3400 1.0860 0.8450 0.6280 0.4240 0.2630 + </tableData> + </table> + </function> + +</turbine_engine> + diff --git a/engine/engtm601.xml b/engine/engtm601.xml old mode 100644 new mode 100755 diff --git a/engine/propHS139v.xml b/engine/propHS139v.xml old mode 100644 new mode 100755 diff --git a/engine/prop_Clark_Y7570.xml b/engine/prop_Clark_Y7570.xml old mode 100644 new mode 100755 diff --git a/engine/prop_PT6.xml b/engine/prop_PT6.xml old mode 100644 new mode 100755 diff --git a/engine/t56.xml b/engine/t56.xml old mode 100644 new mode 100755 diff --git a/engine/t56_prop.xml b/engine/t56_prop.xml old mode 100644 new mode 100755 diff --git a/engine/vrtule2.xml b/engine/vrtule2.xml old mode 100644 new mode 100755 diff --git a/helper b/helper deleted file mode 100755 index 026b5f2ef85be4a8478a157a1af06f25a6fa8fd3..0000000000000000000000000000000000000000 --- a/helper +++ /dev/null @@ -1,107 +0,0 @@ -#!/bin/bash - -source ~/.develrc -projectPath=${JSBSim} - -function usage { -cat << EOF -Options: - c - create a new class - d - generate doxygen documentation - f - format source code - r - refactor - t - generate tags for stl, project libraries, and local code - u - display usage - v - view documentation - x - make a distribution -Examples: - Format all of the source code: - $0 -f -EOF -} - -if [ $# == 0 ] -then - usage -fi - -while getopts "c:difrtun:p:vx" opt; do - case ${opt} in - c) class=${OPTARG} - echo helper: creating class ${class} - if ! ( test $firstName ) ; then echo first name:; read firstName; fi - if ! ( test $lastName ) ; then echo last name:; read lastName; fi - if ! ( test $email ); then echo email:; read email; fi - year=$(date +%G) - cp ${projectPath}/templates/template.cpp ${class}.cpp - cp ${projectPath}/templates/template.h ${class}.h - find . -regex ".*${class}.\(cpp\|h\)" \ - -exec sed -i " - s/@CLASS@/${class}/g; - s/@FIRSTNAME@/${firstName}/g; - s/@LASTNAME@/${lastName}/g; - s/@EMAIL@/${email}/g; - s/@YEAR@/${year}/g; - s/@NAMESPACE@/JSBSim/g;" {} \; - ;; - d) echo helper: generating doxygen documentaion - doxygen ${projectPath}/doc/Doxyfile - ;; - f) echo helper: formatting source code - astyle --style=ansi $(find . -regex '.*\.\(cpp\|c\|cc\|h\|hpp\)') - rm -f $(find . -regex '.*\.orig') - ;; - r) echo helper: refactoring - echo -n "original name: "; read orig - echo -n "new name: "; read new - find . -regex '.*\.\(cpp\|c\|cc\|h\|hpp\|.am\)' \ - -exec sed -i "s|$orig|$new|g" {} \; - ;; - t) echo helper: generating tags - vimrc=~/.vimrc - tagFile="~/.vim/tags/${projectPath}Tags" - - # Create the directory - if [ -f ~/.vim/tags ] - then - rm ~/.vim/tags - fi - mkdir -p ~/.vim/tags - - # Generate project tags - ctags -RV --c++-kinds=+p --fields=+iaS \ - --extra=+q -f ${projectPath}/tags \ - ${projectPath} - - # Add tags to .vimrc - if grep -q "set tags+=$tagFile" $vimrc; then - echo "Tags found in .vimrc" - else - echo "set tags+=$tagFile" >> $vimrc - echo "I added them to .vimrc" - fi - ;; - u) usage - ;; - v) echo helper: viewing documentation - firefox ${ath}/doc/html/index.html - ;; - x) echo helper: packaing a distribution - git clean -dxf - ./autogen.sh - make distcheck - ;; - ?) usage - ;; - esac -done - -# vim:ts=4:sw=4 diff --git a/scicoslab/.gitignore b/scicoslab/.gitignore deleted file mode 100644 index d969048e02ce18e6423648a8f7cedbe8466a221b..0000000000000000000000000000000000000000 --- a/scicoslab/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -Makelib -*.bin -*.so -*.a -*.lo -*.la -lib -names -src/loader.sce diff --git a/scicoslab/Makefile.am b/scicoslab/Makefile.am deleted file mode 100644 index b42f36ef9e5511c1216fae039ac36ece5454ce5a..0000000000000000000000000000000000000000 --- a/scicoslab/Makefile.am +++ /dev/null @@ -1,57 +0,0 @@ -EXTRA_DIST= - -if BUILD_SCICOSLAB -sci_gateway/libjsbsim_sci_gateway.so: $(top_builddir)/src/libJSBSim.la sci_gateway/*.cpp - find . -regex ".*\.\(o\|lo\|a\|la\|so\)" -exec rm -f {} \; - scicoslab -args -nouserstartup -nwni -f autobuild.sce -clean-scicos: - find . -regex ".*\.\(o\|lo\|a\|la\|so\)" -exec rm -f {} \; -clean-local: clean-scicos -all-local: sci_gateway/libjsbsim_sci_gateway.so -endif - - -scicoslabdir=$(pkgdatadir)/scicoslab -scicoslab_DATA= \ - builder.sce \ - loader.sce -EXTRA_DIST+= $(scicoslab_DATA) - -scicoslabdemosdir=$(scicoslabdir)/demos -scicoslabdemos_DATA= \ - demos/loader.sce \ - demos/BacksidePIDAutopilot.cos \ - demos/Trim.cos - -EXTRA_DIST+= $(scicoslabdemos_DATA) - -scicoslabincludesdir=$(scicoslabdir)/includes -scicoslabincludes_DATA= \ - includes/definitions.hpp -EXTRA_DIST+= $(scicoslabincludes_DATA) - -scicoslabsci_gatewaydir=$(scicoslabdir)/sci_gateway -scicoslabsci_gateway_DATA= \ - sci_gateway/builder.sce \ - sci_gateway/loader.sce \ - sci_gateway/sci_jsbsimComm.cpp \ - sci_gateway/sci_jsbsimTrim.cpp -EXTRA_DIST+= $(scicoslabsci_gateway_DATA) - -scicoslabscicosdir=$(scicoslabdir)/scicos -scicoslabscicos_DATA= \ - builder.sce \ - loader.sce -EXTRA_DIST+= $(scicoslabscicos_DATA) - -scicoslabscicosjsbsimdir=$(scicoslabscicosdir)/jsbsim -scicoslabscicosjsbsim_DATA= \ - scicos/jsbsim/jsbsimComm.sci -EXTRA_DIST+= $(scicoslabscicosoooark_DATA) - -scicoslabscriptsdir=$(scicoslabdir)/scripts -scicoslabscripts_DATA= \ - scripts/fgrun.sh -EXTRA_DIST+= $(scicoslabscripts_DATA) - -.PHONY: clean-scicos diff --git a/scicoslab/autobuild.sce b/scicoslab/autobuild.sce deleted file mode 100644 index fdea0202d93d17a1e588503dbe355468e4b04298..0000000000000000000000000000000000000000 --- a/scicoslab/autobuild.sce +++ /dev/null @@ -1,3 +0,0 @@ -exec builder.sce -disp('builder finished') -quit diff --git a/scicoslab/builder.sce b/scicoslab/builder.sce deleted file mode 100644 index 77162cee913caceadcf5420580d769bc684c9a22..0000000000000000000000000000000000000000 --- a/scicoslab/builder.sce +++ /dev/null @@ -1,40 +0,0 @@ -mode(-1); - -jsbsimIncludeDir=getenv("JSBSim")+'/src'; -jsbsimLibDir=getenv("JSBSim")+'/src/.libs'; - -// check version -ierr = execstr("getversion(""scilab"")", "errcatch"); -if ierr == 0 then - disp("JSBSim doesn''t work with Scilab >= 5. Please use ScicosLab."); - abort; -end - -// build subdirectories -CurrentDirectory = pwd(); -mainpathB = get_absolute_file_path("builder.sce"); -chdir(mainpathB); -if isdir("src") then - chdir("src"); - exec("builder.sce"); - chdir(".."); -end -if isdir("sci_gateway") then - chdir("sci_gateway"); - exec("builder.sce"); - chdir(".."); -end -if isdir("macros") then - chdir("macros"); - exec("builder.sce"); - chdir(".."); -end -if ~MSDOS & isdir("scicos") then - chdir("scicos"); - exec("builder.sce"); - chdir(".."); -end -chdir(CurrentDirectory); - -// clean workspace -clear mainpathB get_absolute_file_path isdir CurrentDirectory ierr diff --git a/scicoslab/demos/.gitignore b/scicoslab/demos/.gitignore deleted file mode 100644 index a29f92e36ce496b7fcfa321cb2a145df817f6c28..0000000000000000000000000000000000000000 --- a/scicoslab/demos/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*lin.sce diff --git a/scicoslab/demos/ArduPilotMegaHIL.cos b/scicoslab/demos/ArduPilotMegaHIL.cos deleted file mode 100644 index 5eaa8e9712f490544e33a71b1c1c80e23938164a..0000000000000000000000000000000000000000 Binary files a/scicoslab/demos/ArduPilotMegaHIL.cos and /dev/null differ diff --git a/scicoslab/demos/BacksidePIDAutopilot.cos b/scicoslab/demos/BacksidePIDAutopilot.cos deleted file mode 100644 index 42a3599bf3f201dde1b93c77bead0ebbc01dc99d..0000000000000000000000000000000000000000 Binary files a/scicoslab/demos/BacksidePIDAutopilot.cos and /dev/null differ diff --git a/scicoslab/demos/BacksidePIDAutopilotLinear.cos b/scicoslab/demos/BacksidePIDAutopilotLinear.cos deleted file mode 100644 index 9b550ec12ca09c7ae8c6cbcc5352563e9cf92ebb..0000000000000000000000000000000000000000 Binary files a/scicoslab/demos/BacksidePIDAutopilotLinear.cos and /dev/null differ diff --git a/scicoslab/demos/JSBSimCommPorts.cos b/scicoslab/demos/JSBSimCommPorts.cos deleted file mode 100644 index 5ceafabc368287c3125a3b8740d9d1e81f456eb0..0000000000000000000000000000000000000000 Binary files a/scicoslab/demos/JSBSimCommPorts.cos and /dev/null differ diff --git a/scicoslab/demos/Trim.cos b/scicoslab/demos/Trim.cos deleted file mode 100644 index 6aff5acf1927a6569f5ad741b55d59e06d8d650d..0000000000000000000000000000000000000000 Binary files a/scicoslab/demos/Trim.cos and /dev/null differ diff --git a/scicoslab/demos/linearAnalysis.sce b/scicoslab/demos/linearAnalysis.sce deleted file mode 100644 index 29790ee2ca557836321c7c7885bd0d889696b2b7..0000000000000000000000000000000000000000 --- a/scicoslab/demos/linearAnalysis.sce +++ /dev/null @@ -1,32 +0,0 @@ -clc; clear - -exec EasyStar_lin.sce; - -load JSBSimCommPorts.cos -sys_airframe = lincos(scs_m,x0,u0); -commandedStates=[5;1;9;10;7]; - -disp(norm(sys_airframe.A-sys.A)) -sys_airframe = sys_airframe(commandedStates,:); - -load BacksidePIDAutopilot.cos -servoPlantNum=529; // watch this, can change when saving -controllerPlantnum = 394; // watch this, can change when saving - - -sys_servos = lincos(scs_m.objs(servoPlantNum).model.rpar,u0,u0); -sys_controller = lincos(scs_m.objs(controllerPlantnum).model.rpar,.. - zeros(10,1),.. // set low pass filter poles and integratotr poles to zero - zeros(5,1)); // set initial command errors to zero -sys2 = sys_airframe*sys_servos; - -//[a,b,c,d] = abcd(sys2); -//ac1 = a - b*c; -//s1 = syslin('c',ac1,b,c,d); -t=linspace(0,10); - -n=4; -//s2 = s1(n,n)/(1+s1(n,n)); - -scf(1); clf(1); -plot(t,csim("step",t,sys2(n,n))); diff --git a/scicoslab/demos/loader.sce b/scicoslab/demos/loader.sce deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/scicoslab/includes/definitions.hpp b/scicoslab/includes/definitions.hpp deleted file mode 100644 index 4b315ce54e3e823cf78bb9daaf37c275c72ae518..0000000000000000000000000000000000000000 --- a/scicoslab/includes/definitions.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * definitions.hpp - * Copyright (C) James Goppert 2010 <jgoppert@users.sourceforge.net> - * - * definitions.hpp 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, either version 3 of the License, or - * (at your option) any later version. - * - * definitions.hpp 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, see <http://www.gnu.org/licenses/>. - */ - -#ifndef definitions_HPP -#define definitions_HPP - -namespace scicos -{ - -enum enumScicosFlags -{ - computeDeriv=0, - computeOutput=1, - updateState=2, - outputTimeDelays=3, - initialize=4, - terminate=5, - reinitialize=6, - internal=7, - computeZeroCrossSurfsSetModes=8, - computeZeroCrossSurfs=9 -}; - -} - -#endif - -// vim:ts=4:sw=4 diff --git a/scicoslab/includes/utilities.hpp b/scicoslab/includes/utilities.hpp deleted file mode 100644 index f5af9310857d9a2f100245e1634a09527b5ccb35..0000000000000000000000000000000000000000 --- a/scicoslab/includes/utilities.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * utilities.hpp - * Copyright (C) James Goppert 2010 <james.goppert@gmail.com> - * - * utilities.hpp 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, either version 2 of the License, or - * (at your option) any later version. - * - * utilities.hpp 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, see <http://www.gnu.org/licenses/>. - */ - -#ifndef JSBSim_utilities_H -#define JSBSim_utilities_H - -namespace JSBSim -{ - -} // JSBSim - -#endif - -// vim:ts=4:sw=4 diff --git a/scicoslab/loader.sce b/scicoslab/loader.sce deleted file mode 100644 index 27d4b5f871fe8b25f56e101f3499ea698c7ca328..0000000000000000000000000000000000000000 --- a/scicoslab/loader.sce +++ /dev/null @@ -1,37 +0,0 @@ -mode(-1); - -CurrentDirectory = pwd(); -mainpathL = get_absolute_file_path("loader.sce"); -chdir(mainpathL); -if isdir("sci_gateway") then - chdir("sci_gateway"); - exec("loader.sce"); - chdir(".."); -end -if isdir("macros") then - chdir("macros"); - exec("loader.sce"); - chdir(".."); -end -if isdir("src") then - chdir("src"); - exec("loader.sce"); - chdir(".."); -end -if isdir("help") then - chdir("help"); - exec("loader.sce"); - chdir(".."); -end -if isdir("scicos") then - chdir("scicos"); - exec("loader.sce"); - chdir(".."); -end -if isdir("demos") then - chdir("demos"); - exec("loader.sce"); - chdir(".."); -end -chdir(CurrentDirectory); -clear mainpathL get_absolute_file_path isdir get_file_path functions CurrentDirectory diff --git a/scicoslab/macros/builder.sce b/scicoslab/macros/builder.sce deleted file mode 100644 index 2e6df59021500bb68170152d2bb9984a239533b9..0000000000000000000000000000000000000000 --- a/scicoslab/macros/builder.sce +++ /dev/null @@ -1 +0,0 @@ -mode(-1); diff --git a/scicoslab/macros/jsbsimTrim.sci b/scicoslab/macros/jsbsimTrim.sci deleted file mode 100644 index 4be42c28c44393d76eb06bb7732c6e777b1c9019..0000000000000000000000000000000000000000 --- a/scicoslab/macros/jsbsimTrim.sci +++ /dev/null @@ -1,4 +0,0 @@ -function []=jsbsimTrim() -// jsbsimTrim -call('sci_jsbsimTrim'); -endfunction diff --git a/scicoslab/macros/loader.sce b/scicoslab/macros/loader.sce deleted file mode 100644 index 4fa4858dbf4a1a38ff05a7903a396e871b60517b..0000000000000000000000000000000000000000 --- a/scicoslab/macros/loader.sce +++ /dev/null @@ -1,2 +0,0 @@ -mode(-1); -genlib('lib_oooarkMacros',pwd()); diff --git a/scicoslab/macros/loopClosure.sce b/scicoslab/macros/loopClosure.sce deleted file mode 100644 index 526a50e231dfc3e8751d404020f14f3402e7de58..0000000000000000000000000000000000000000 --- a/scicoslab/macros/loopClosure.sce +++ /dev/null @@ -1,220 +0,0 @@ -clc; clear; -mode(-1) - -exec EasyStar_lin.sce; - -plant.x.vt=1; -plant.x.alpha=2; -plant.x.theta=3; -plant.x.q=4; -plant.x.rpm=5; -plant.x.alt=6; -plant.x.beta=7; -plant.x.phi=8; -plant.x.p=9; -plant.x.r=10; -plant.x.psi=11; -plant.x.lon=12; -plant.x.lat=13; - -plant.y.vt=1; -plant.y.alpha=2; -plant.y.theta=3; -plant.y.q=4; -plant.y.rpm=5; -plant.y.alt=6; -plant.y.beta=7; -plant.y.phi=8; -plant.y.p=9; -plant.y.r=10; -plant.y.psi=11; -plant.y.lon=12; -plant.y.lat=13; - -plant.u.th=1; -plant.u.da=2; -plant.u.de=3; -plant.u.dr=4; - -// complete plant -plant.sys=EasyStar.sys; -[ap,bp,cp,dp] = abcd(plant.sys); - -// lateral subsystem -latSub.indx=[plant.x.beta, plant.x.phi, plant.x.p, plant.x.r, plant.x.psi]; -latSub.indy=[plant.y.beta, plant.y.phi, plant.y.p, plant.y.r, plant.y.psi]; -latSub.indu=[plant.u.da, plant.u.dr]; -latSub.sys=syslin('c',ap(latSub.indx,latSub.indx),bp(latSub.indx,latSub.indu),.. - cp(latSub.indy,latSub.indx),dp(latSub.indx,latSub.indu)); - -latSub.x.beta=1; -latSub.x.phi=2; -latSub.x.p=3; -latSub.x.r=4; -latSub.x.psi=5; - -latSub.y.beta=1; -latSub.y.phi=2; -latSub.y.p=3; -latSub.y.r=4; -latSub.y.psi=5; - -latSub.u.da=1; -latSub.u.dr=2; - -// longitudinal subsystem -lonSub.indx=[plant.x.vt, plant.x.alpha, plant.x.theta, plant.x.q, plant.x.rpm, plant.x.alt]; -lonSub.indy=[plant.y.vt, plant.y.alpha, plant.y.theta, plant.y.q, plant.y.rpm, plant.y.alt]; -lonSub.indu=[plant.u.th, plant.u.de]; -lonSub.sys=syslin('c',ap(lonSub.indx,lonSub.indx),bp(lonSub.indx,lonSub.indu),.. - cp(lonSub.indy,lonSub.indx),dp(lonSub.indx,lonSub.indu)); - -lonSub.x.vt=1; -lonSub.x.alpha=2; -lonSub.x.theta=3; -lonSub.x.q=4; -lonSub.x.rpm=5; -lonSub.x.alt=6; - -lonSub.y.vt=1; -lonSub.y.alpha=2; -lonSub.y.theta=3; -lonSub.y.q=4; -lonSub.y.rpm=5; -lonSub.y.alt=6; - -lonSub.u.th=1; -lonSub.u.de=2; - -iFig = 0; - - -// rudder -//plant = minss(EasyStar.sys); // beta, phi, p, r, psi | rudder - - -//lat.sys=syslin('c',ap(lat.indx,lat.indx),bp(lat.indx,lat.indu),cp(lat.indy,lat.indx),dp(lat.indx,lat.indu)); - -// actuator -//actuator=tf2ss(20*%s/(20+%s)); -//plant_act = plant*actuator; // series 2 * series 1 - -// phi -gc_phi = tf2ss(.004); // pid compensator -phi_open = latSub.sys(:,latSub.u.dr)*gc_phi; -[a,b,c,d] = abcd(phi_open); -phi_closed = syslin('c',a+b*c(latSub.y.phi,:),b,c,d); // simo -disp('phi controller') -disp('phase margin:') -disp(p_margin(phi_open(latSub.y.phi,:))) -disp('gain margin:') -disp(g_margin(phi_open(latSub.y.phi,:))) - -iFig = iFig +1; scf(iFig); clf(iFig); -f=gcf(); f.figure_name = "phi -> rudder | open bode /closed bode /open evans/ step"; -subplot(1,4,1) -bode(phi_open(latSub.y.phi,:)); -subplot(1,4,2) -bode(phi_closed(latSub.y.phi,:)) -subplot(1,4,3) -e=gce(); p1=e.children(1); p2=e.children(2); -p1.foreground=color("purple"); p2.foreground=color("navy blue"); -cmap=xget("colormap"); cmap(8,:)=0; xset("colormap",cmap); // fix white -evans(minss(phi_open(latSub.y.phi,:),.1e-2),100) -mtlb_axis([-30,40,-30,30]) -subplot(1,4,4) -t=linspace(0,100); -plot(csim("step",t,phi_closed(latSub.y.phi,1))); - -// yaw damper -gc_yawdamp = tf2ss(.005); // pid compensator -yawdamp_open = phi_closed*gc_yawdamp; -[a,b,c,d] = abcd(yawdamp_open); -yawdamp_closed = syslin('c',a+b*c(latSub.y.r,:),b,c,d); // simo -disp('yaw damper controller') -disp('phase margin:') -disp(p_margin(yawdamp_open(latSub.y.r,:))) -disp('gain margin:') -disp(g_margin(yawdamp_open(latSub.y.r,:))) - -iFig = iFig +1; scf(iFig); clf(iFig); -f=gcf(); f.figure_name = "yaw rate -> rudder | open bode /closed bode /closed evans/ step"; -subplot(1,4,1) -bode(yawdamp_open(latSub.y.r,:)); -subplot(1,4,2) -bode(yawdamp_closed(latSub.y.r,:)) -subplot(1,4,3) -e=gce(); p1=e.children(1); p2=e.children(2); -p1.foreground=color("purple"); p2.foreground=color("navy blue"); -cmap=xget("colormap"); cmap(8,:)=0; xset("colormap",cmap); // fix white -//evans(minss(yawdamp_open(latSub.y.r,:),.1e-2),100) -mtlb_axis([-30,40,-30,30]) -subplot(1,4,4) -t=linspace(0,100); -//plot(csim("step",t,yawdamp_closed(latSub.y.r,1))); - -// psi -gc_psi = tf2ss(.65); // pid compensator -psi_open = yawdamp_closed*gc_psi; -[a,b,c,d] = abcd(psi_open); -psi_closed = syslin('c',a+b*c(latSub.y.psi,:),b,c,d); // simo -disp('psi controller') -disp('phase margin:') -disp(p_margin(psi_open(latSub.y.psi,:))) -disp('gain margin:') -disp(g_margin(psi_open(latSub.y.psi,:))) - -iFig = iFig +1; scf(iFig); clf(iFig); -f=gcf(); f.figure_name = "psi -> rudder | open bode /closed bode /closed evans/ step"; -subplot(1,4,1) -bode(psi_open(latSub.y.psi,:)); -subplot(1,4,2) -bode(psi_open(latSub.y.psi,:)) -subplot(1,4,3) -e=gce(); p1=e.children(1); p2=e.children(2); -p1.foreground=color("purple"); p2.foreground=color("navy blue"); -cmap=xget("colormap"); cmap(8,:)=0; xset("colormap",cmap); // fix white -//evans(minss(psi_open(latSub.y.r,:),.1e-2),100) -//mtlb_axis([-30,40,-30,30]) -subplot(1,4,4) -t=linspace(0,100); -plot(csim("step",t,psi_closed(latSub.y.psi,1))); - -//gc_phi = tf2ss(1); // pid compensator -//phi_open = yawdamp_closed*gc_phi; -//[a,b,c,d] = abcd(phi_open); -//phi_closed = syslin('c',a+b*c(2,:),b,c,d); // simo -//disp('phi controller') -//disp('phase margin:') -//disp(p_margin(phi_closed(2,:))) -//disp('gain margin:') -//disp(g_margin(phi_closed(2,:))) - - -//psi loop -//gc_psi = tf2ss(1); pid compensator -//psi_open = phi_closed*gc_psi; -//[a,b,c,d] = abcd(psi_open); -//psi_closed = syslin('c',a+b*c(5,:),b,c,d); -//disp('psi controller') -//disp('phase margin:') -//disp(p_margin(psi_closed(5,:))) -//disp('gain margin:') -//disp(g_margin(psi_closed(5,:))) - - -//scf(3); clf(3); -//f=gcf(); f.figure_name = "phi open/closed | rudder"; -//subplot(1,2,1); -//bode(phi_open(1,:)) -//subplot(1,2,2); -//bode(phi_closed(1,:)) -//legend('phi','psi') - -//scf(4); clf(4); -//f=gcf(); f.figure_name = "psi open/closed | rudder"; -//subplot(1,2,1); -//bode(psi_open(3,:)) -//subplot(1,2,2); -//bode(psi_closed(3,:)) -//legend('phi','psi') diff --git a/scicoslab/macros/rlocus.sci b/scicoslab/macros/rlocus.sci deleted file mode 100644 index 3fab79cf7d064863a33e4391392f7cc405a043b8..0000000000000000000000000000000000000000 --- a/scicoslab/macros/rlocus.sci +++ /dev/null @@ -1,24 +0,0 @@ -function rlocus(G_open,kmin,kmax,axis) -mode(1) -// figure setup -scf(1) - -// closed loop -closedLoopPoles=[]; -for kval=logspace(kmin,kmax) - //solve close loop char. eq - ce = denom(G_open)+kval*numer(G_open); - closedLoopPoles = [closedLoopPoles,roots(ce)]; -end -real(closedLoopPoles) -plot(real(closedLoopPoles),imag(closedLoopPoles),'r'); -plot(real(closedLoopPoles),-imag(closedLoopPoles),'g'); - -// open loop -openLoopZeros = roots(numer(G_open)); -plot(real(openLoopZeros),imag(openLoopZeros),'bo'); -openLoopPoles = roots(denom(G_open)); -plot(real(openLoopPoles),imag(openLoopPoles),'bx'); -//mtlb_axis(axis); - -endfunction diff --git a/scicoslab/macros/steadycos2.sci b/scicoslab/macros/steadycos2.sci deleted file mode 100644 index 93be3cf9b5b3cd371ac8ad48eb123bd5137affe7..0000000000000000000000000000000000000000 --- a/scicoslab/macros/steadycos2.sci +++ /dev/null @@ -1,183 +0,0 @@ -function [X,U,Y,XP]=steadycos2(scs_m,X,U,Y,Indx,Indu,Indy,Indxp,param) -// steadycos2 -// Finds an equilibrium state of a general -// dynamical system described by a scicos diagram -// Same as standard steadycos but takes the optimization method as a -// parameter. - -// CALLING SEQUENCE -// -// [X,U,Y,XP]=steadycos(scs_m,X,U,Y,Indx,Indu,Indy [,Indxp [,param ] ]) -// -// scs_m: a Scicos data structure -// X: column vector. Continuous state. Can be set to [] if zero. -// U: column vector. Input. Can be set to [] if zero. -// Y: column vector. Output. Can be set to [] if zero. -// Indx: index of entries of X that are not fixed. If all can vary, set to 1:$ -// Indu: index of entries of U that are not fixed. If all can vary, set to 1:$ -// Indy: index of entries of Y that are not fixed. If all can vary, set to 1:$ -// Indxp: index of entries of XP (derivative of x) that need not be zero. -// If all can vary, set to 1:$. Default []. -// param: list with three elements (default list(1.d-6,0,'qn')) -// param(1): scalar. Perturbation level for linearization; the following variation is used -// del([x;u])_i = param(1)+param(1)*1d-4*abs([x;u])_i -// param(2): scalar. Time t. -// param(3): method, 'qn': quasi netwon (default), 'nd' : nelder meade, .. -// param(4): max func evals -// param(5): max interations - -load SCI/macros/scicos/lib - -[lhs,rhs]=argn(0) -IN=[];OUT=[]; - -[ierr,scicos_ver,scs_m]=update_version(scs_m) -if ierr<>0 then - message("Can''t convert old diagram (problem in version)") - return -end - -// //check version -// current_version = get_scicos_version() -// scicos_ver = find_scicos_version(scs_m) -// -// //do version -// if scicos_ver<>current_version then -// ierr=execstr('scs_m=do_version(scs_m,scicos_ver)','errcatch') -// if ierr<>0 then -// error('Can''t convert old diagram (problem in version)') -// return -// end -// end - -if rhs==7 then - Indxp=[ ];param=list(1.d-6,0,'qn',100,100) -elseif rhs==8 then - param=list(1.d-6,0,'qn',100,100) -elseif rhs==9 then -else - error('wrong number of arguments. 7, 8 or 9 expected.') -end - -for i=1:length(scs_m.objs) - if typeof(scs_m.objs(i))=='Block' then - if scs_m.objs(i).gui=='IN_f' then - scs_m.objs(i).gui='INPUTPORT'; - IN=[IN scs_m.objs(i).model.ipar] - elseif scs_m.objs(i).gui=='OUT_f' then - scs_m.objs(i).gui='OUTPUTPORT'; - OUT=[OUT scs_m.objs(i).model.ipar] - end - end -end -IN=-sort(-IN); -if or(IN<>[1:size(IN,'*')]) then - error('Input ports are not numbered properly.') -end -OUT=-sort(-OUT); -if or(OUT<>[1:size(OUT,'*')]) then - error('Output ports are not numbered properly.') -end -//load scicos lib -load('SCI/macros/scicos/lib') -//compile scs_m -[bllst,connectmat,clkconnect,cor,corinv,ok]=c_pass1(scs_m); -if ~ok then - error('Diagram does not compile in pass 1'); -end -%cpr=c_pass2(bllst,connectmat,clkconnect,cor,corinv,'silent'); -if %cpr==list() then - ok=%f, -end -if ~ok then - error('Diagram does not compile in pass 2'); -end -sim=%cpr.sim;state=%cpr.state; -// -inplnk=sim.inplnk;inpptr=sim.inpptr; -outlnk=sim.outlnk;outptr=sim.outptr;ipptr=sim.ipptr; - -ki=[];ko=[];nyptr=1; -for kfun=1:length(sim.funs) - if sim.funs(kfun)=='output' then - sim.funs(kfun)='bidon' - ko=[ko;[kfun,sim.ipar(ipptr(kfun))]]; - - elseif sim.funs(kfun)=='input' then - sim.funs(kfun)='bidon' - ki=[ki;[kfun,sim.ipar(ipptr(kfun))]]; - - end -end -[junk,ind]=sort(-ko(:,2));ko=ko(ind,1); -[junk,ind]=sort(-ki(:,2));ki=ki(ind,1); - -pointo=[]; -for k=ko' - pointo=[pointo;inplnk(inpptr(k))] -end -pointi=[]; -for k=ki' - pointi=[pointi;outlnk(outptr(k))] -end -nx=size(state.x,'*'); -nu=0; for k=pointi', nu=nu+size(state.outtb(k),'*'), end -ny=0; for k=pointo', ny=ny+size(state.outtb(k),'*'), end - -if X==[] then X=zeros(nx,1);end -if Y==[] then Y=zeros(ny,1);end -if U==[] then U=zeros(nu,1);end -if param(1)==0 then param(1)=1.d-6;end -t=param(2) -optimMethod=param(3) -nap=param(4); -iter=param(5); - -ux0=[U(Indu);X(Indx)]; -sindu=size(U(Indu),'*');sindx=size(X(Indx),'*'); -[err,uxopt,gopt]=optim(cost,ux0,optimMethod,'ar',nap,iter) -U(Indu)=uxopt(1:sindu); -X(Indx)=uxopt(sindu+1:sindx+sindu); -state.x=X; -Uind=1 -for k=pointi' - state.outtb(k)=matrix(U(Uind:Uind+size(state.outtb(k),'*')-1),size(state.outtb(k))); - Uind=size(state.outtb(k),'*')+1; -end -[state,t]=scicosim(state,t,t,sim,'linear',[.1,.1,.1,.1]); -XP=state.x; -Yind=1 -for k=pointo' - Y(Yind:Yind+size(state.outtb(k),'*')-1)=state.outtb(k)(:); - Yind=size(state.outtb(k),'*')+Yind -end -endfunction - -function [f,g,ind]=cost(ux,ind) -state; -X; -U; -X(Indx)=ux(sindu+1:sindx+sindu); -U(Indu)=ux(1:sindu); -state.x=X; -Uind=1 -for k=pointi' - state.outtb(k)=matrix(U(Uind:Uind+size(state.outtb(k),'*')-1),size(state.outtb(k))); - Uind=size(state.outtb(k),'*')+1; -end -// state.outtb(pointi)=U; -[state,t]=scicosim(state,t,t,sim,'linear',[.1,.1,.1,.1]); -zer=ones(X);zer(Indxp)=0;xp=zer.*state.x; -Yind=1 -for k=pointo' - y(Yind:Yind+size(state.outtb(k),'*')-1)=state.outtb(k)(:); - Yind=size(state.outtb(k),'*')+Yind -end -// y=state.outtb(pointo); -zer=ones(y);zer(Indy)=0;err=zer.*(Y-y); -f=.5*(norm(xp,2)+norm(err,2)); - -sys=lincos(scs_m,X,U,param) -g=xp'*[sys.B(:,Indu) sys.A(:,Indx)]-.. - err'*[sys.D(:,Indu) sys.C(:,Indx)]; -endfunction diff --git a/scicoslab/sci_gateway/.gitignore b/scicoslab/sci_gateway/.gitignore deleted file mode 100644 index 37d2d05d00bd50905394d1435d72fd36997e4880..0000000000000000000000000000000000000000 --- a/scicoslab/sci_gateway/.gitignore +++ /dev/null @@ -1 +0,0 @@ -loader.sce diff --git a/scicoslab/sci_gateway/AsyncSerial.cpp b/scicoslab/sci_gateway/AsyncSerial.cpp deleted file mode 100644 index 6d310ee4c582ac310c043bf6e9dba45bfc12b368..0000000000000000000000000000000000000000 --- a/scicoslab/sci_gateway/AsyncSerial.cpp +++ /dev/null @@ -1,696 +0,0 @@ -/* - * File: AsyncSerial.cpp - * Author: Terraneo Federico - * Distributed under the Boost Software License, Version 1.0. - * Created on September 7, 2009, 10:46 AM - * - * v1.01: Fixed a bug that did not allow to reopen a closed serial port. - * - * v1.00: First release. - * - * IMPORTANT: - * On Mac OS X boost asio's serial ports have bugs, and the usual implementation - * of this class does not work. So a workaround class was written temporarily, - * until asio (hopefully) will fix Mac compatibility for serial ports. - * - * Please note that unlike said in the documentation on OS X until asio will - * be fixed serial port *writes* are *not* asynchronous, but at least - * asynchronous *read* works. - * In addition the serial port open ignores the following options: parity, - * character size, flow, stop bits, and defaults to 8N1 format. - * I know it is bad but at least it's better than nothing. - * - */ - -#include "AsyncSerial.h" - -#include <string> -#include <algorithm> -#include <iostream> -#include <boost/bind.hpp> - -using namespace std; -using namespace boost; - -// -//Class AsyncSerial -// - -#ifndef __APPLE__ - -class AsyncSerialImpl: private boost::noncopyable -{ -public: - AsyncSerialImpl(): io(), port(io), backgroundThread(), open(false), - error(false) {} - - boost::asio::io_service io; ///< Io service object - boost::asio::serial_port port; ///< Serial port object - boost::thread backgroundThread; ///< Thread that runs read/write operations - bool open; ///< True if port open - bool error; ///< Error flag - mutable boost::mutex errorMutex; ///< Mutex for access to error - - /// Data are queued here before they go in writeBuffer - std::vector<char> writeQueue; - boost::shared_array<char> writeBuffer; ///< Data being written - size_t writeBufferSize; ///< Size of writeBuffer - boost::mutex writeQueueMutex; ///< Mutex for access to writeQueue - char readBuffer[AsyncSerial::readBufferSize]; ///< data being read - - /// Read complete callback - boost::function<void (const char*, size_t)> callback; -}; - -AsyncSerial::AsyncSerial(): pimpl(new AsyncSerialImpl) -{ - -} - -AsyncSerial::AsyncSerial(const std::string& devname, unsigned int baud_rate, - asio::serial_port_base::parity opt_parity, - asio::serial_port_base::character_size opt_csize, - asio::serial_port_base::flow_control opt_flow, - asio::serial_port_base::stop_bits opt_stop) - : pimpl(new AsyncSerialImpl) -{ - open(devname,baud_rate,opt_parity,opt_csize,opt_flow,opt_stop); -} - -void AsyncSerial::open(const std::string& devname, unsigned int baud_rate, - asio::serial_port_base::parity opt_parity, - asio::serial_port_base::character_size opt_csize, - asio::serial_port_base::flow_control opt_flow, - asio::serial_port_base::stop_bits opt_stop) -{ - if (isOpen()) close(); - - setErrorStatus(true);//If an exception is thrown, error_ remains true - pimpl->port.open(devname); - pimpl->port.set_option(asio::serial_port_base::baud_rate(baud_rate)); - pimpl->port.set_option(opt_parity); - pimpl->port.set_option(opt_csize); - pimpl->port.set_option(opt_flow); - pimpl->port.set_option(opt_stop); - - //This gives some work to the io_service before it is started - pimpl->io.post(bind(&AsyncSerial::doRead, this)); - - thread t(bind(&asio::io_service::run, &pimpl->io)); - pimpl->backgroundThread.swap(t); - setErrorStatus(false);//If we get here, no error - pimpl->open=true; //Port is now open -} - -bool AsyncSerial::isOpen() const -{ - return pimpl->open; -} - -bool AsyncSerial::errorStatus() const -{ - lock_guard<mutex> l(pimpl->errorMutex); - return pimpl->error; -} - -void AsyncSerial::close() -{ - if (!isOpen()) return; - - pimpl->open=false; - pimpl->io.post(bind(&AsyncSerial::doClose, this)); - pimpl->backgroundThread.join(); - pimpl->io.reset(); - if (errorStatus()) - { - throw(boost::system::system_error(boost::system::error_code(), - "Error while closing the device")); - } -} - -void AsyncSerial::write(const char *data, size_t size) -{ - { - lock_guard<mutex> l(pimpl->writeQueueMutex); - pimpl->writeQueue.insert(pimpl->writeQueue.end(),data,data+size); - } - pimpl->io.post(bind(&AsyncSerial::doWrite, this)); -} - -void AsyncSerial::write(const std::vector<char>& data) -{ - { - lock_guard<mutex> l(pimpl->writeQueueMutex); - pimpl->writeQueue.insert(pimpl->writeQueue.end(),data.begin(), - data.end()); - } - pimpl->io.post(bind(&AsyncSerial::doWrite, this)); -} - -void AsyncSerial::writeString(const std::string& s) -{ - { - lock_guard<mutex> l(pimpl->writeQueueMutex); - pimpl->writeQueue.insert(pimpl->writeQueue.end(),s.begin(),s.end()); - } - pimpl->io.post(bind(&AsyncSerial::doWrite, this)); -} - -AsyncSerial::~AsyncSerial() -{ - if (isOpen()) - { - try - { - close(); - } - catch (...) - { - //Don't throw from a destructor - } - } -} - -void AsyncSerial::doRead() -{ - pimpl->port.async_read_some(asio::buffer(pimpl->readBuffer,readBufferSize), - bind(&AsyncSerial::readEnd, - this, - asio::placeholders::error, - asio::placeholders::bytes_transferred)); -} - -void AsyncSerial::readEnd(const boost::system::error_code& error, - size_t bytes_transferred) -{ - if (error) - { -#ifdef __APPLE__ - if (error.value()==45) - { - //Bug on OS X, it might be necessary to repeat the setup - //http://osdir.com/ml/lib.boost.asio.user/2008-08/msg00004.html - doRead(); - return; - } -#endif //__APPLE__ - //error can be true even because the serial port was closed. - //In this case it is not a real error, so ignore - if (isOpen()) - { - doClose(); - setErrorStatus(true); - } - } - else - { - if (pimpl->callback) pimpl->callback(pimpl->readBuffer, - bytes_transferred); - doRead(); - } -} - -void AsyncSerial::doWrite() -{ - //If a write operation is already in progress, do nothing - if (pimpl->writeBuffer==0) - { - lock_guard<mutex> l(pimpl->writeQueueMutex); - pimpl->writeBufferSize=pimpl->writeQueue.size(); - pimpl->writeBuffer.reset(new char[pimpl->writeQueue.size()]); - copy(pimpl->writeQueue.begin(),pimpl->writeQueue.end(), - pimpl->writeBuffer.get()); - pimpl->writeQueue.clear(); - async_write(pimpl->port,asio::buffer(pimpl->writeBuffer.get(), - pimpl->writeBufferSize), - bind(&AsyncSerial::writeEnd, this, asio::placeholders::error)); - } -} - -void AsyncSerial::writeEnd(const boost::system::error_code& error) -{ - if (!error) - { - lock_guard<mutex> l(pimpl->writeQueueMutex); - if (pimpl->writeQueue.empty()) - { - pimpl->writeBuffer.reset(); - pimpl->writeBufferSize=0; - - return; - } - pimpl->writeBufferSize=pimpl->writeQueue.size(); - pimpl->writeBuffer.reset(new char[pimpl->writeQueue.size()]); - copy(pimpl->writeQueue.begin(),pimpl->writeQueue.end(), - pimpl->writeBuffer.get()); - pimpl->writeQueue.clear(); - async_write(pimpl->port,asio::buffer(pimpl->writeBuffer.get(), - pimpl->writeBufferSize), - bind(&AsyncSerial::writeEnd, this, asio::placeholders::error)); - } - else - { - setErrorStatus(true); - doClose(); - } -} - -void AsyncSerial::doClose() -{ - boost::system::error_code ec; - pimpl->port.cancel(ec); - if (ec) setErrorStatus(true); - pimpl->port.close(ec); - if (ec) setErrorStatus(true); -} - -void AsyncSerial::setErrorStatus(bool e) -{ - lock_guard<mutex> l(pimpl->errorMutex); - pimpl->error=e; -} - -void AsyncSerial::setReadCallback(const - function<void (const char*, size_t)>& callback) -{ - pimpl->callback=callback; -} - -void AsyncSerial::clearReadCallback() -{ - pimpl->callback.clear(); -} - -#else //__APPLE__ - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <termios.h> -#include <unistd.h> - -class AsyncSerialImpl: private boost::noncopyable -{ -public: - AsyncSerialImpl(): backgroundThread(), open(false), error(false) {} - - boost::thread backgroundThread; ///< Thread that runs read operations - bool open; ///< True if port open - bool error; ///< Error flag - mutable boost::mutex errorMutex; ///< Mutex for access to error - - int fd; ///< File descriptor for serial port - - char readBuffer[AsyncSerial::readBufferSize]; ///< data being read - - /// Read complete callback - boost::function<void (const char*, size_t)> callback; -}; - -AsyncSerial::AsyncSerial(): pimpl(new AsyncSerialImpl) -{ - -} - -AsyncSerial::AsyncSerial(const std::string& devname, unsigned int baud_rate, - asio::serial_port_base::parity opt_parity, - asio::serial_port_base::character_size opt_csize, - asio::serial_port_base::flow_control opt_flow, - asio::serial_port_base::stop_bits opt_stop) - : pimpl(new AsyncSerialImpl) -{ - open(devname,baud_rate,opt_parity,opt_csize,opt_flow,opt_stop); -} - -void AsyncSerial::open(const std::string& devname, unsigned int baud_rate, - asio::serial_port_base::parity opt_parity, - asio::serial_port_base::character_size opt_csize, - asio::serial_port_base::flow_control opt_flow, - asio::serial_port_base::stop_bits opt_stop) -{ - if (isOpen()) close(); - - setErrorStatus(true);//If an exception is thrown, error remains true - - struct termios new_attributes; - speed_t speed; - int status; - - // Open port - pimpl->fd=::open(devname.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); - if (pimpl->fd<0) throw(boost::system::system_error( - boost::system::error_code(),"Failed to open port")); - - // Set Port parameters. - status=tcgetattr(pimpl->fd,&new_attributes); - if (status<0 || !isatty(pimpl->fd)) - { - ::close(pimpl->fd); - throw(boost::system::system_error( - boost::system::error_code(),"Device is not a tty")); - } - new_attributes.c_iflag = IGNBRK; - new_attributes.c_oflag = 0; - new_attributes.c_lflag = 0; - new_attributes.c_cflag = (CS8 | CREAD | CLOCAL);//8 data bit,Enable receiver,Ignore modem - /* In non canonical mode (Ctrl-C and other disabled, no echo,...) VMIN and VTIME work this way: - if the function read() has'nt read at least VMIN chars it waits until has read at least VMIN - chars (even if VTIME timeout expires); once it has read at least vmin chars, if subsequent - chars do not arrive before VTIME expires, it returns error; if a char arrives, it resets the - timeout, so the internal timer will again start from zero (for the nex char,if any)*/ - new_attributes.c_cc[VMIN]=1;// Minimum number of characters to read before returning error - new_attributes.c_cc[VTIME]=1;// Set timeouts in tenths of second - - // Set baud rate - switch (baud_rate) - { - case 50: - speed= B50; - break; - case 75: - speed= B75; - break; - case 110: - speed= B110; - break; - case 134: - speed= B134; - break; - case 150: - speed= B150; - break; - case 200: - speed= B200; - break; - case 300: - speed= B300; - break; - case 600: - speed= B600; - break; - case 1200: - speed= B1200; - break; - case 1800: - speed= B1800; - break; - case 2400: - speed= B2400; - break; - case 4800: - speed= B4800; - break; - case 9600: - speed= B9600; - break; - case 19200: - speed= B19200; - break; - case 38400: - speed= B38400; - break; - case 57600: - speed= B57600; - break; - case 115200: - speed= B115200; - break; - case 230400: - speed= B230400; - break; - default: - { - ::close(pimpl->fd); - throw(boost::system::system_error( - boost::system::error_code(),"Unsupported baud rate")); - } - } - - cfsetospeed(&new_attributes,speed); - cfsetispeed(&new_attributes,speed); - - //Make changes effective - status=tcsetattr(pimpl->fd, TCSANOW, &new_attributes); - if (status<0) - { - ::close(pimpl->fd); - throw(boost::system::system_error( - boost::system::error_code(),"Can't set port attributes")); - } - - //These 3 lines clear the O_NONBLOCK flag - status=fcntl(pimpl->fd, F_GETFL, 0); - if (status!=-1) fcntl(pimpl->fd, F_SETFL, status & ~O_NONBLOCK); - - setErrorStatus(false);//If we get here, no error - pimpl->open=true; //Port is now open - - thread t(bind(&AsyncSerial::doRead, this)); - pimpl->backgroundThread.swap(t); -} - -bool AsyncSerial::isOpen() const -{ - return pimpl->open; -} - -bool AsyncSerial::errorStatus() const -{ - lock_guard<mutex> l(pimpl->errorMutex); - return pimpl->error; -} - -void AsyncSerial::close() -{ - if (!isOpen()) return; - - pimpl->open=false; - - ::close(pimpl->fd); //The thread waiting on I/O should return - - pimpl->backgroundThread.join(); - if (errorStatus()) - { - throw(boost::system::system_error(boost::system::error_code(), - "Error while closing the device")); - } -} - -void AsyncSerial::write(const char *data, size_t size) -{ - if (::write(pimpl->fd,data,size)!=size) setErrorStatus(true); -} - -void AsyncSerial::write(const std::vector<char>& data) -{ - if (::write(pimpl->fd,&data[0],data.size())!=data.size()) - setErrorStatus(true); -} - -void AsyncSerial::writeString(const std::string& s) -{ - if (::write(pimpl->fd,&s[0],s.size())!=s.size()) setErrorStatus(true); -} - -AsyncSerial::~AsyncSerial() -{ - if (isOpen()) - { - try - { - close(); - } - catch (...) - { - //Don't throw from a destructor - } - } -} - -void AsyncSerial::doRead() -{ - //Read loop in spawned thread - for (;;) - { - int received=::read(pimpl->fd,pimpl->readBuffer,readBufferSize); - if (received<0) - { - if (isOpen()==false) return; //Thread interrupted because port closed - else - { - setErrorStatus(true); - continue; - } - } - if (pimpl->callback) pimpl->callback(pimpl->readBuffer, received); - } -} - -void AsyncSerial::readEnd(const boost::system::error_code& error, - size_t bytes_transferred) -{ - //Not used -} - -void AsyncSerial::doWrite() -{ - //Not used -} - -void AsyncSerial::writeEnd(const boost::system::error_code& error) -{ - //Not used -} - -void AsyncSerial::doClose() -{ - //Not used -} - -void AsyncSerial::setErrorStatus(bool e) -{ - lock_guard<mutex> l(pimpl->errorMutex); - pimpl->error=e; -} - -void AsyncSerial::setReadCallback(const - function<void (const char*, size_t)>& callback) -{ - pimpl->callback=callback; -} - -void AsyncSerial::clearReadCallback() -{ - pimpl->callback.clear(); -} - -#endif //__APPLE__ - -// -//Class CallbackAsyncSerial -// - -CallbackAsyncSerial::CallbackAsyncSerial(): AsyncSerial() -{ - -} - -CallbackAsyncSerial::CallbackAsyncSerial(const std::string& devname, - unsigned int baud_rate, - asio::serial_port_base::parity opt_parity, - asio::serial_port_base::character_size opt_csize, - asio::serial_port_base::flow_control opt_flow, - asio::serial_port_base::stop_bits opt_stop) - :AsyncSerial(devname,baud_rate,opt_parity,opt_csize,opt_flow,opt_stop) -{ - -} - -void CallbackAsyncSerial::setCallback(const - function<void (const char*, size_t)>& callback) -{ - setReadCallback(callback); -} - -void CallbackAsyncSerial::clearCallback() -{ - clearReadCallback(); -} - -CallbackAsyncSerial::~CallbackAsyncSerial() -{ - clearReadCallback(); -} - -// -//Class BufferedAsyncSerial -// - -BufferedAsyncSerial::BufferedAsyncSerial(): AsyncSerial() -{ - -} - -BufferedAsyncSerial::BufferedAsyncSerial(const std::string& devname, - unsigned int baud_rate, - asio::serial_port_base::parity opt_parity, - asio::serial_port_base::character_size opt_csize, - asio::serial_port_base::flow_control opt_flow, - asio::serial_port_base::stop_bits opt_stop) - :AsyncSerial(devname,baud_rate,opt_parity,opt_csize,opt_flow,opt_stop) -{ - setReadCallback(bind(&BufferedAsyncSerial::readCallback, this, _1, _2)); -} - -size_t BufferedAsyncSerial::read(char *data, size_t size) -{ - lock_guard<mutex> l(readQueueMutex); - size_t result=min(size,readQueue.size()); - vector<char>::iterator it=readQueue.begin()+result; - copy(readQueue.begin(),it,data); - readQueue.erase(readQueue.begin(),it); - return result; -} - -std::vector<char> BufferedAsyncSerial::read() -{ - lock_guard<mutex> l(readQueueMutex); - vector<char> result; - result.swap(readQueue); - return result; -} - -std::string BufferedAsyncSerial::readString() -{ - lock_guard<mutex> l(readQueueMutex); - string result(readQueue.begin(),readQueue.end()); - readQueue.clear(); - return result; -} - -std::string BufferedAsyncSerial::readStringUntil(const std::string delim) -{ - lock_guard<mutex> l(readQueueMutex); - vector<char>::iterator it=findStringInVector(readQueue,delim); - if (it==readQueue.end()) return ""; - string result(readQueue.begin(),it); - it+=delim.size();//Do remove the delimiter from the queue - readQueue.erase(readQueue.begin(),it); - return result; -} - -void BufferedAsyncSerial::readCallback(const char *data, size_t len) -{ - lock_guard<mutex> l(readQueueMutex); - readQueue.insert(readQueue.end(),data,data+len); -} - -std::vector<char>::iterator BufferedAsyncSerial::findStringInVector( - std::vector<char>& v,const std::string& s) -{ - if (s.size()==0) return v.end(); - - vector<char>::iterator it=v.begin(); - for (;;) - { - vector<char>::iterator result=find(it,v.end(),s[0]); - if (result==v.end()) return v.end();//If not found return - - for (size_t i=0;i<s.size();i++) - { - vector<char>::iterator temp=result+i; - if (temp==v.end()) return v.end(); - if (s[i]!=*temp) goto mismatch; - } - //Found - return result; - -mismatch: - it=result+1; - } -} - -BufferedAsyncSerial::~BufferedAsyncSerial() -{ - clearReadCallback(); -} diff --git a/scicoslab/sci_gateway/AsyncSerial.h b/scicoslab/sci_gateway/AsyncSerial.h deleted file mode 100644 index e032e9c25413245cca8325d785cdcf83476dcc8d..0000000000000000000000000000000000000000 --- a/scicoslab/sci_gateway/AsyncSerial.h +++ /dev/null @@ -1,321 +0,0 @@ -/* - * File: AsyncSerial.h - * Author: Terraneo Federico - * Distributed under the Boost Software License, Version 1.0. - * Created on September 7, 2009, 10:46 AM - */ - -#ifndef _ASYNCSERIAL_H -#define _ASYNCSERIAL_H - -#include <vector> -#include <boost/asio.hpp> -#include <boost/thread.hpp> -#include <boost/utility.hpp> -#include <boost/function.hpp> -#include <boost/shared_array.hpp> - -/** - * Used internally (pimpl) - */ -class AsyncSerialImpl; - -/** - * Asyncronous serial class. - * Intended to be a base class. - */ -class AsyncSerial: private boost::noncopyable -{ -public: - AsyncSerial(); - - /** - * Constructor. Creates and opens a serial device. - * \param devname serial device name, example "/dev/ttyS0" or "COM1" - * \param baud_rate serial baud rate - * \param opt_parity serial parity, default none - * \param opt_csize serial character size, default 8bit - * \param opt_flow serial flow control, default none - * \param opt_stop serial stop bits, default 1 - * \throws boost::system::system_error if cannot open the - * serial device - */ - AsyncSerial(const std::string& devname, unsigned int baud_rate, - boost::asio::serial_port_base::parity opt_parity= - boost::asio::serial_port_base::parity( - boost::asio::serial_port_base::parity::none), - boost::asio::serial_port_base::character_size opt_csize= - boost::asio::serial_port_base::character_size(8), - boost::asio::serial_port_base::flow_control opt_flow= - boost::asio::serial_port_base::flow_control( - boost::asio::serial_port_base::flow_control::none), - boost::asio::serial_port_base::stop_bits opt_stop= - boost::asio::serial_port_base::stop_bits( - boost::asio::serial_port_base::stop_bits::one)); - - /** - * Opens a serial device. - * \param devname serial device name, example "/dev/ttyS0" or "COM1" - * \param baud_rate serial baud rate - * \param opt_parity serial parity, default none - * \param opt_csize serial character size, default 8bit - * \param opt_flow serial flow control, default none - * \param opt_stop serial stop bits, default 1 - * \throws boost::system::system_error if cannot open the - * serial device - */ - void open(const std::string& devname, unsigned int baud_rate, - boost::asio::serial_port_base::parity opt_parity= - boost::asio::serial_port_base::parity( - boost::asio::serial_port_base::parity::none), - boost::asio::serial_port_base::character_size opt_csize= - boost::asio::serial_port_base::character_size(8), - boost::asio::serial_port_base::flow_control opt_flow= - boost::asio::serial_port_base::flow_control( - boost::asio::serial_port_base::flow_control::none), - boost::asio::serial_port_base::stop_bits opt_stop= - boost::asio::serial_port_base::stop_bits( - boost::asio::serial_port_base::stop_bits::one)); - - /** - * \return true if serial device is open - */ - bool isOpen() const; - - /** - * \return true if error were found - */ - bool errorStatus() const; - - /** - * Close the serial device - * \throws boost::system::system_error if any error - */ - void close(); - - /** - * Write data asynchronously. Returns immediately. - * \param data array of char to be sent through the serial device - * \param size array size - */ - void write(const char *data, size_t size); - - /** - * Write data asynchronously. Returns immediately. - * \param data to be sent through the serial device - */ - void write(const std::vector<char>& data); - - /** - * Write a string asynchronously. Returns immediately. - * Can be used to send ASCII data to the serial device. - * To send binary data, use write() - * \param s string to send - */ - void writeString(const std::string& s); - - virtual ~AsyncSerial()=0; - - /** - * Read buffer maximum size - */ - static const int readBufferSize=512; -private: - - /** - * Callback called to start an asynchronous read operation. - * This callback is called by the io_service in the spawned thread. - */ - void doRead(); - - /** - * Callback called at the end of the asynchronous operation. - * This callback is called by the io_service in the spawned thread. - */ - void readEnd(const boost::system::error_code& error, - size_t bytes_transferred); - - /** - * Callback called to start an asynchronous write operation. - * If it is already in progress, does nothing. - * This callback is called by the io_service in the spawned thread. - */ - void doWrite(); - - /** - * Callback called at the end of an asynchronuous write operation, - * if there is more data to write, restarts a new write operation. - * This callback is called by the io_service in the spawned thread. - */ - void writeEnd(const boost::system::error_code& error); - - /** - * Callback to close serial port - */ - void doClose(); - - boost::shared_ptr<AsyncSerialImpl> pimpl; - -protected: - - /** - * To allow derived classes to report errors - * \param e error status - */ - void setErrorStatus(bool e); - - /** - * To allow derived classes to set a read callback - */ - void setReadCallback(const - boost::function<void (const char*, size_t)>& callback); - - /** - * To unregister the read callback in the derived class destructor so it - * does not get called after the derived class destructor but before the - * base class destructor - */ - void clearReadCallback(); - -}; - -/** - * Asynchronous serial class with read callback. User code can write data - * from one thread, and read data will be reported through a callback called - * from a separate thred. - */ -class CallbackAsyncSerial: public AsyncSerial -{ -public: - CallbackAsyncSerial(); - - /** - * Opens a serial device. - * \param devname serial device name, example "/dev/ttyS0" or "COM1" - * \param baud_rate serial baud rate - * \param opt_parity serial parity, default none - * \param opt_csize serial character size, default 8bit - * \param opt_flow serial flow control, default none - * \param opt_stop serial stop bits, default 1 - * \throws boost::system::system_error if cannot open the - * serial device - */ - CallbackAsyncSerial(const std::string& devname, unsigned int baud_rate, - boost::asio::serial_port_base::parity opt_parity= - boost::asio::serial_port_base::parity( - boost::asio::serial_port_base::parity::none), - boost::asio::serial_port_base::character_size opt_csize= - boost::asio::serial_port_base::character_size(8), - boost::asio::serial_port_base::flow_control opt_flow= - boost::asio::serial_port_base::flow_control( - boost::asio::serial_port_base::flow_control::none), - boost::asio::serial_port_base::stop_bits opt_stop= - boost::asio::serial_port_base::stop_bits( - boost::asio::serial_port_base::stop_bits::one)); - - /** - * Set the read callback, the callback will be called from a thread - * owned by the CallbackAsyncSerial class when data arrives from the - * serial port. - * \param callback the receive callback - */ - void setCallback(const - boost::function<void (const char*, size_t)>& callback); - - /** - * Removes the callback. Any data received after this function call will - * be lost. - */ - void clearCallback(); - - virtual ~CallbackAsyncSerial(); -}; - -class BufferedAsyncSerial: public AsyncSerial -{ -public: - BufferedAsyncSerial(); - - /** - * Opens a serial device. - * \param devname serial device name, example "/dev/ttyS0" or "COM1" - * \param baud_rate serial baud rate - * \param opt_parity serial parity, default none - * \param opt_csize serial character size, default 8bit - * \param opt_flow serial flow control, default none - * \param opt_stop serial stop bits, default 1 - * \throws boost::system::system_error if cannot open the - * serial device - */ - BufferedAsyncSerial(const std::string& devname, unsigned int baud_rate, - boost::asio::serial_port_base::parity opt_parity= - boost::asio::serial_port_base::parity( - boost::asio::serial_port_base::parity::none), - boost::asio::serial_port_base::character_size opt_csize= - boost::asio::serial_port_base::character_size(8), - boost::asio::serial_port_base::flow_control opt_flow= - boost::asio::serial_port_base::flow_control( - boost::asio::serial_port_base::flow_control::none), - boost::asio::serial_port_base::stop_bits opt_stop= - boost::asio::serial_port_base::stop_bits( - boost::asio::serial_port_base::stop_bits::one)); - - /** - * Read some data asynchronously. Returns immediately. - * \param data array of char to be read through the serial device - * \param size array size - * \return numbr of character actually read 0<=return<=size - */ - size_t read(char *data, size_t size); - - /** - * Read all available data asynchronously. Returns immediately. - * \return the receive buffer. It iempty if no data is available - */ - std::vector<char> read(); - - /** - * Read a string asynchronously. Returns immediately. - * Can only be used if the user is sure that the serial device will not - * send binary data. For binary data read, use read() - * The returned string is empty if no data has arrived - * \return a string with the received data. - */ - std::string readString(); - - /** - * Read a line asynchronously. Returns immediately. - * Can only be used if the user is sure that the serial device will not - * send binary data. For binary data read, use read() - * The returned string is empty if the line delimiter has not yet arrived. - * \param delimiter line delimiter, default='\n' - * \return a string with the received data. The delimiter is removed from - * the string. - */ - std::string readStringUntil(const std::string delim="\n"); - - virtual ~BufferedAsyncSerial(); - -private: - - /** - * Read callback, stores data in the buffer - */ - void readCallback(const char *data, size_t len); - - /** - * Finds a substring in a vector of char. Used to look for the delimiter. - * \param v vector where to find the string - * \param s string to find - * \return the beginning of the place in the vector where the first - * occurrence of the string is, or v.end() if the string was not found - */ - static std::vector<char>::iterator findStringInVector(std::vector<char>& v, - const std::string& s); - - std::vector<char> readQueue; - boost::mutex readQueueMutex; -}; - -#endif /* _ASYNCSERIAL_H */ - diff --git a/scicoslab/sci_gateway/builder.sce b/scicoslab/sci_gateway/builder.sce deleted file mode 100644 index cb9a4838774d2702e7b35ad2e30c45206608cf52..0000000000000000000000000000000000000000 --- a/scicoslab/sci_gateway/builder.sce +++ /dev/null @@ -1,16 +0,0 @@ -mode(-1) -names=['sci_jsbsimComm','sci_jsbsimTrim','sci_ardupilotmegaHil']; -files=['sci_jsbsimComm.o','sci_jsbsimTrim.o','sci_ardupilotmegaHil.o','utilities.o','AsyncSerial.o']; -libs=[jsbsimLibDir+'/libJSBSim']; -flag='c'; -makename='Makelib'; -loadername='loader.sce'; -libname='jsbsim_sci_gateway'; -ldflags='-lboost_system-mt -lboost_thread-mt -lboost_date_time-mt'; -cflags='-I../includes -I'+jsbsimIncludeDir; -fflags=''; -cc=''; -ilib_for_link(names,files,libs,flag,makename,loadername,libname,ldflags,cflags,fflags,cc); - -clear names files libs flag makename loadername -clear libname ldflags cflags fflags cc diff --git a/scicoslab/sci_gateway/sci_ardupilotmegaHil.cpp b/scicoslab/sci_gateway/sci_ardupilotmegaHil.cpp deleted file mode 100644 index 77e791c1a3c6a470b6a80be6c8411cace112ecfa..0000000000000000000000000000000000000000 --- a/scicoslab/sci_gateway/sci_ardupilotmegaHil.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * sci_ardupilotmegaHil.cpp - * Copyright (C) James Goppert 2010 <jgoppert@users.sourceforge.net> - * - * sci_ardupilotmegaHil.cpp 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, either version 3 of the License, or - * (at your option) any later version. - * - * sci_ardupilotmegaHil.cpp 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, see <http://www.gnu.org/licenses/>. - */ - -#include "utilities.h" -#include "AsyncSerial.h" -#include <iostream> - -class ArdupilotmegaHil -{ -public: - // data - double roll, pitch, throttle, rudder, wpDistance, bearingError; - double nextWpAlt, energyError; - int wpIndex, controlMode; - - // commmunication - BufferedAsyncSerial serial; - int headerCount; - bool headerFound; - std::vector<char> message; - std::vector<char> header; - std::vector<char> headerOut; - std::vector<char> messageOut; - - // constants - static const int packetLength = 18; - - // constructor - ArdupilotmegaHil(const std::string & device, const int baudRate) : - roll(), pitch(), throttle(), rudder(), wpDistance(), bearingError(), - nextWpAlt(), energyError(), wpIndex(), controlMode(), - serial(device,baudRate), headerCount(0), headerFound(false), - message(), header() - { - header.push_back('A'); - header.push_back('A'); - header.push_back('A'); - - headerOut.push_back(0x44); - headerOut.push_back(0x49); - headerOut.push_back(0x59); - headerOut.push_back(0x64); - } - - // read new data - void read(double * u) - { - //std::cout << "reading" << std::endl; - std::vector<char> buffer = serial.read(); - - int i = 0; - - // look for header - if (!headerFound) - { - while(i<buffer.size()) - { - if(buffer[i++] == header[headerCount]) headerCount++; - else headerCount = 0; - - // read message - if (headerCount >= header.size()) - { - //std::cout << "header found" << std::endl; - headerCount = 0; - headerFound = true; - break; - } - } - } - - // read message - if (headerFound) - { - //std::cout << "header found" << std::endl; - while(i<buffer.size()) message.push_back(buffer[i++]); - if (message.size() >= packetLength) - { - //std::cout << "message found" << std::endl; - // message complete, read into packet - decode(); - //print(); - headerFound = false; - //std::cout << "message emptying" << std::endl; - message.clear(); - } - } - - // set u - u[0] = throttle; - u[1] = roll; - u[2] = pitch; - u[3] = rudder; - } - - // if message complete, then decode - void decode() - { - // message complete, read into packet - roll = (*(int16_t *)&message[0])/255.0; - pitch = (*(int16_t *)&message[2])/255.0; - throttle = (*(int16_t *)&message[4])/255.0; - rudder = (*(int16_t *)&message[6])/255.0; - wpDistance = (*(int16_t *)&message[8]); - bearingError = (*(int16_t *)&message[10]); - nextWpAlt = (*(int16_t *)&message[12]); - energyError = (*(int16_t *)&message[14]); - wpIndex = message[16]; - controlMode = message[17]; - } - - void write(double * x) - { - // add header - for (int i=0;i<headerOut.size();i++) messageOut.push_back(headerOut[i]); - - // add xplane packet - int16_t rollOut = x[6]*180.0/M_PI*100; - int16_t pitchOut = x[2]*180.0/M_PI*100; - int16_t headingOut = x[9]*180.0/M_PI*100; - int16_t vtOut = x[0]*3.2808399*100; - std::cout << "roll out: " << rollOut << std::endl; - std::cout << "pitch out: " << pitchOut << std::endl; - std::cout << "heading out: " << headingOut << std::endl; - std::cout << "vt out: " << vtOut << std::endl; - messageOut.push_back(8); - messageOut.push_back(0x04); // xplane packet - messageOut.push_back((uint8_t)(rollOut)); - messageOut.push_back((uint8_t)(rollOut >> 8)); - messageOut.push_back((uint8_t)(pitchOut)); - messageOut.push_back((uint8_t)(pitchOut >> 8)); - messageOut.push_back((uint8_t)(headingOut)); - messageOut.push_back((uint8_t)(headingOut >> 8)); - messageOut.push_back((uint8_t)(vtOut)); - messageOut.push_back((uint8_t)(vtOut >> 8)); - - // compute checksum - uint8_t ck_a = 0, ck_b = 0; - for (int i=headerOut.size();i<messageOut.size();i++) - { - ck_a += messageOut[i]; - ck_b += ck_a; - } - messageOut.push_back(ck_a); - messageOut.push_back(ck_b); - - // output to serial - serial.write(messageOut); - messageOut.clear(); - } - - void print() - { - std::cout - << "\nroll:\t\t\t" << roll - << "\npitch:\t\t\t" << pitch - << "\nthrottle:\t\t" << throttle - << "\nrudder:\t\t\t" << rudder - << "\nwaypoint distance:\t" << wpDistance - << "\nbearing errror:\t\t" << bearingError - << "\nnext waypoint alt:\t" << nextWpAlt - << "\nenergy error:\t\t" << energyError - << "\nwaypoint index:\t\t" << wpIndex - << "\ncontrol mode:\t\t" << controlMode - << std::endl; - } -}; - -extern "C" -{ - -#include <scicos/scicos_block4.h> -#include <math.h> -#include "definitions.hpp" - - void sci_ardupilotmegaHil(scicos_block *block, scicos::enumScicosFlags flag) - { - // data - double * x=GetRealInPortPtrs(block,1); - double * u=GetRealOutPortPtrs(block,1); - int * ipar=block->ipar; - static char * device; - static int baudRate; - static char ** stringArray; - static int * intArray; - - // serial port - static ArdupilotmegaHil * hil = NULL; - - - //handle flags - if (flag==scicos::initialize || flag==scicos::reinitialize) - { - if (!hil) - { - getIpars(1,1,ipar,&stringArray,&intArray); - device = stringArray[0]; - baudRate = intArray[0]; - hil = new ArdupilotmegaHil(device,baudRate); - } - } - else if (flag==scicos::terminate) - { - if (hil) - { - delete hil; - hil = NULL; - } - } - else if (flag==scicos::updateState) - { - } - else if (flag==scicos::computeDeriv) - { - } - else if (flag==scicos::computeOutput) - { - hil->write(x); - hil->read(u); - } - else - { - } - } - -} // extern c - -// vim:ts=4:sw=4 diff --git a/scicoslab/sci_gateway/sci_jsbsimComm.cpp b/scicoslab/sci_gateway/sci_jsbsimComm.cpp deleted file mode 100644 index e4b44a71ef9c0674452fda52af83dd7379cb10a6..0000000000000000000000000000000000000000 --- a/scicoslab/sci_gateway/sci_jsbsimComm.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* - * sci_jsbsimComm.cpp - * Copyright (C) James Goppert 2010 <jgoppert@users.sourceforge.net> - * - * sci_jsbsimComm.cpp 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, either version 3 of the License, or - * (at your option) any later version. - * - * sci_jsbsimComm.cpp 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, see <http://www.gnu.org/licenses/>. - */ - -#include "FGFDMExec.h" -#include "models/FGFCS.h" -#include "math/FGStateSpace.h" -#include <iostream> -#include <string> -#include <cstdlib> -#include "input_output/FGPropertyManager.h" -#include "input_output/flightGearIO.h" -#include "utilities.h" - -namespace JSBSim -{ - -class JSBSimComm -{ -public: - JSBSimComm(char * aircraftPath, char * enginePath, - char * systemsPath, char * modelName, - double * x0, double * u0, int debugLevel, - bool enableFlightGearComm, char * flightGearHost, int flightGearPort) : - prop(), fdm(&prop), ss(fdm), socket() - { - std::cout << "initializing JSBSim" << std::endl; - fdm.SetDebugLevel(debugLevel); - fdm.LoadModel(std::string(aircraftPath), - std::string(enginePath), - std::string(systemsPath), - std::string(modelName)); - - if (enableFlightGearComm) - { - std::cout << "initializing FlightGear communication" << std::endl; - socket = new FGfdmSocket(flightGearHost,flightGearPort,FGfdmSocket::ptUDP); - } - - // defaults - bool variablePropPitch = false; - - // get propulsion pointer to determine type/ etc. - FGEngine * engine0 = fdm.GetPropulsion()->GetEngine(0); - FGThruster * thruster0 = engine0->GetThruster(); - - // longitudinal states - ss.x.add(new FGStateSpace::Vt); - ss.x.add(new FGStateSpace::Alpha); - ss.x.add(new FGStateSpace::Theta); - ss.x.add(new FGStateSpace::Q); - ss.x.add(new FGStateSpace::Alt); - - // lateral states - ss.x.add(new FGStateSpace::Beta); - ss.x.add(new FGStateSpace::Phi); - ss.x.add(new FGStateSpace::P); - ss.x.add(new FGStateSpace::R); - ss.x.add(new FGStateSpace::Psi); - - // nav states - ss.x.add(new FGStateSpace::Longitude); - ss.x.add(new FGStateSpace::Latitude); - - // propulsion states - if (thruster0->GetType()==FGThruster::ttPropeller) - { - ss.x.add(new FGStateSpace::Rpm); - if (variablePropPitch) ss.x.add(new FGStateSpace::PropPitch); - } - - // input - ss.u.add(new FGStateSpace::ThrottleCmd); - ss.u.add(new FGStateSpace::DaCmd); - ss.u.add(new FGStateSpace::DeCmd); - ss.u.add(new FGStateSpace::DrCmd); - - // state feedback - ss.y = ss.x; - - // turn on propulsion - fdm.GetPropulsion()->InitRunning(-1); - - // set initial conditions - ss.x.set(x0); - ss.u.set(u0); - } - virtual ~JSBSimComm() - { - if (socket) delete socket; - } - void sendToFlightGear() - { - FGNetFDM netFdm; - JSBSim2FlightGearNetFDM(fdm,netFdm); - if (socket) socket->Send((char *)(& netFdm), sizeof(netFdm)); - //std::cout << ss << std::endl; - //std::cout << ss.x.getDeriv() << std::endl; - } -public: - FGPropertyManager prop; - FGFDMExec fdm; - FGStateSpace ss; - FGfdmSocket * socket; -}; - -} // JSBSim - -extern "C" -{ - -#include <scicos/scicos_block4.h> -#include <math.h> -#include "definitions.hpp" - - void sci_jsbsimComm(scicos_block *block, scicos::enumScicosFlags flag) - { - static JSBSim::JSBSimComm * comm = NULL; - static JSBSim::FGPropertyManager propManager; - static char * modelName, * aircraftPath, * enginePath, - * systemsPath, * flightGearHost; - static int debugLevel; - static int enableFlightGearComm, flightGearPort; - static char ** stringArray; - static int * intArray; - - // data - double *u=(double*)GetInPortPtrs(block,1); - double *xOut=(double*)GetOutPortPtrs(block,1); - double *y=(double*)GetOutPortPtrs(block,2); - double *x=(double*)GetState(block); - double *xd=(double*)GetDerState(block); - int * ipar=block->ipar; - - // make sure you have initialized the block - if (!comm && flag!=scicos::initialize) - { - sci_jsbsimComm(block,scicos::initialize); - } - - //handle flags - if (flag==scicos::initialize || flag==scicos::reinitialize) - { - if (!comm) - { - getIpars(5,3,ipar,&stringArray,&intArray); - aircraftPath = stringArray[0]; - enginePath = stringArray[1]; - systemsPath = stringArray[2]; - modelName = stringArray[3]; - flightGearHost=stringArray[4]; - debugLevel = intArray[0]; - enableFlightGearComm = intArray[1]; - flightGearPort = intArray[2]; - comm = new JSBSim::JSBSimComm(aircraftPath,enginePath,systemsPath,modelName,x,u,debugLevel, - enableFlightGearComm,flightGearHost,flightGearPort); - sci_jsbsimComm(block,scicos::updateState); - } - } - else if (flag==scicos::terminate) - { - if (comm) - { - delete comm; - comm = NULL; - } - } - else if (flag==scicos::updateState) - { - //std::cout << "updating state" << std::endl; - comm->ss.u.set(u); - comm->ss.x.set(x); - if (enableFlightGearComm==1) - { - comm->sendToFlightGear(); - } - } - else if (flag==scicos::computeDeriv) - { - //std::cout << "computing deriv" << std::endl; - comm->ss.x.getDeriv(xd); - } - else if (flag==scicos::computeOutput) - { - //std::cout << "computing output" << std::endl; - sci_jsbsimComm(block,scicos::updateState); - comm->ss.x.get(xOut); - comm->ss.y.get(y); - } - else - { - std::cout << "unhandled flag: " << flag << std::endl; - } - } - -} // extern c - -// vim:ts=4:sw=4 diff --git a/scicoslab/sci_gateway/sci_jsbsimTrim.cpp b/scicoslab/sci_gateway/sci_jsbsimTrim.cpp deleted file mode 100644 index f51495ec8c67dbd9d924898351be254633f59754..0000000000000000000000000000000000000000 --- a/scicoslab/sci_gateway/sci_jsbsimTrim.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* - * sci_jsbsimTrim.cpp - * Copyright (C) James Goppert 2010 <james.goppert@gmail.com> - * - * sci_jsbsimTrim.cpp 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, either version 2 of the License, or - * (at your option) any later version. - * - * sci_jsbsimTrim.cpp 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, see <http://www.gnu.org/licenses/>. - */ - -#include <cstdlib> -#include "initialization/FGTrimmer.h" -#include "math/FGStateSpace.h" -#include <iomanip> -#include <fstream> -#include "models/FGAircraft.h" -#include "models/propulsion/FGEngine.h" -#include "models/propulsion/FGTurbine.h" -#include "models/propulsion/FGTurboProp.h" - -template <class varType> -void prompt(const std::string & str, varType & var) -{ - std::cout << str + " [" << std::setw(10) << var << "]\t: "; - if (std::cin.peek() != '\n') - { - std::cin >> var; - std::cin.ignore(1000, '\n'); - } - else std::cin.get(); -} - -void trimFunction () -{ - using namespace JSBSim; - - // variables - FGFDMExec fdm; - fdm.Setdt(1./120); - FGTrimmer::Constraints constraints; - - std::cout << "\n==============================================\n"; - std::cout << "\tJSBSim Trimming Utility\n"; - std::cout << "==============================================\n" << std::endl; - - // defaults - constraints.velocity = 45; - std::string aircraft="EasyStar"; - std::string aircraftPath(std::string(getenv("JSBSim"))+"/aircraft"); - std::string enginePath(std::string(getenv("JSBSim"))+"/engine"); - std::string systemsPath(std::string(getenv("JSBSim"))+"/systems"); - double rtol = std::numeric_limits<float>::epsilon(); - double abstol = std::numeric_limits<double>::epsilon(); - double speed = 2.0; - int iterMax = 2000; - bool showConvergeStatus = false; - bool pause = false; - bool showSimplex = false; - bool variablePropPitch = false; - int debugLevel = 0; - - // input - std::cout << "input ( press enter to accept [default] )\n" << std::endl; - - // load model - prompt("\tdebug level\t\t",debugLevel); - fdm.SetDebugLevel(debugLevel); - std::cout << "model selection" << std::endl; - while (1) - { - prompt("\taircraft\t\t",aircraft); - prompt("\taircraft path\t\t",aircraftPath); - prompt("\tengine path\t\t",enginePath); - prompt("\tsystems path\t\t",systemsPath); - fdm.LoadModel(aircraftPath,enginePath,systemsPath,aircraft); - std::string aircraftName = fdm.GetAircraft()->GetAircraftName(); - if (aircraftName == "") - { - std::cout << "\tfailed to load aircraft" << std::endl; - } - else - { - std::cout << "\tsuccessfully loaded: " << aircraftName << std::endl; - break; - } - } - - // Turn on propulsion system - fdm.GetPropulsion()->InitRunning(-1); - - // get propulsion pointer to determine type/ etc. - FGEngine * engine0 = fdm.GetPropulsion()->GetEngine(0); - FGThruster * thruster0 = engine0->GetThruster(); - - // flight conditions - std::cout << "\nflight conditions: " << std::endl; - prompt("\taltitude, ft\t\t",constraints.altitude); - prompt("\tvelocity, ft/s\t\t",constraints.velocity); - prompt("\tgamma, deg\t\t",constraints.gamma); - if (thruster0->GetType()==FGThruster::ttPropeller) - prompt("\tvariable prop pitch?\t\t",variablePropPitch); - constraints.gamma *= M_PI/180; - - // mode menu - while (1) - { - int mode = 0; - prompt("\tmode < non-turning(0), rolling(1), pitching(2), yawing(3) >",mode); - constraints.rollRate = 0; - constraints.pitchRate = 0; - constraints.yawRate = 0; - if (mode == 0) break; - else if (mode == 1) - { - prompt("\troll rate, rad/s",constraints.rollRate); - prompt("\tstability axis roll",constraints.stabAxisRoll); - break; - } - else if (mode == 2) - { - prompt("\tpitch rate, rad/s",constraints.pitchRate); - break; - } - else if (mode == 3) - { - prompt("\tyaw rate, rad/s",constraints.yawRate); - break; - } - else std::cout << "\tunknown mode: " << mode << std::endl; - } - - // solver properties - std::cout << "\nsolver properties: " << std::endl; - std::cout << std::scientific; - prompt("\tshow converge status?\t",showConvergeStatus); - prompt("\tshow simplex?\t\t",showSimplex); - prompt("\tpause?\t\t\t",pause); - //prompt("\trelative tolerance\t",rtol); - //prompt("\tabsolute tolerance\t",abstol); - //prompt("\tmax iterations\t\t",iterMax); - //prompt("\tconvergence speed\t",speed); - std::cout << std::fixed; - - // initial solver state - int n = 6; - std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n); - - lowerBound[0] = 0; //throttle - lowerBound[1] = -1; // elevator - lowerBound[2] = -90*M_PI/180; // alpha - lowerBound[3] = -1; // aileron - lowerBound[4] = -1; // rudder - lowerBound[5] = -90*M_PI/180; // beta - - upperBound[0] = 1; //throttle - upperBound[1] = 1; // elevator - upperBound[2] = 90*M_PI/180; // alpha - upperBound[3] = 1; // aileron - upperBound[4] = 1; // rudder - upperBound[5] = 90*M_PI/180; // beta - - initialStepSize[0] = 0.2; //throttle - initialStepSize[1] = 0.1; // elevator - initialStepSize[2] = 0.1; // alpha - initialStepSize[3] = 0.1; // aileron - initialStepSize[4] = 0.1; // rudder - initialStepSize[5] = 0.1; // beta - - initialGuess[0] = 0.5; // throttle - initialGuess[1] = 0; // elevator - initialGuess[2] = 0; // alpha - initialGuess[3] = 0; // aileron - initialGuess[4] = 0; // rudder - initialGuess[5] = 0; // beta - - // solve - FGTrimmer trimmer(fdm, constraints); - FGNelderMead solver(trimmer,initialGuess, lowerBound, upperBound, initialStepSize, - iterMax,rtol,abstol,speed,showConvergeStatus,showSimplex,pause); - - // output - trimmer.printSolution(solver.getSolution()); // this also loads the solution into the fdm - - //std::cout << "\nsimulating flight to determine trim stability" << std::endl; - - //std::cout << "\nt = 5 seconds" << std::endl; - //for (int i=0;i<5*120;i++) fdm.Run(); - //trimmer.printState(); - - //std::cout << "\nt = 10 seconds" << std::endl; - //for (int i=0;i<5*120;i++) fdm.Run(); - //trimmer.printState(); - - std::cout << "\nlinearization: " << std::endl; - FGStateSpace ss(fdm); - - // longitudinal states - ss.x.add(new FGStateSpace::Vt); - ss.x.add(new FGStateSpace::Alpha); - ss.x.add(new FGStateSpace::Theta); - ss.x.add(new FGStateSpace::Q); - ss.x.add(new FGStateSpace::Alt); - - // lateral states - ss.x.add(new FGStateSpace::Beta); - ss.x.add(new FGStateSpace::Phi); - ss.x.add(new FGStateSpace::P); - ss.x.add(new FGStateSpace::R); - ss.x.add(new FGStateSpace::Psi); - - // nav states - ss.x.add(new FGStateSpace::Longitude); - ss.x.add(new FGStateSpace::Latitude); - - // propulsion states - if (thruster0->GetType()==FGThruster::ttPropeller) - { - ss.x.add(new FGStateSpace::Rpm); - if (variablePropPitch) ss.x.add(new FGStateSpace::PropPitch); - } - - // input - ss.u.add(new FGStateSpace::ThrottleCmd); - ss.u.add(new FGStateSpace::DaCmd); - ss.u.add(new FGStateSpace::DeCmd); - ss.u.add(new FGStateSpace::DrCmd); - - // state feedback - ss.y = ss.x; - - std::vector< std::vector<double> > A,B,C,D; - std::vector<double> x0 = ss.x.get(), u0 = ss.u.get(); - std::vector<double> y0 = x0; // state feedback - std::cout << ss << std::endl; - - ss.linearize(x0,u0,y0,A,B,C,D); - - int width=10; - std::cout.precision(3); - std::cout - << std::fixed - << std::right - << "\nA=\n" << std::setw(width) << A - << "\nB=\n" << std::setw(width) << B - << "\nC=\n" << std::setw(width) << C - << "\nD=\n" << std::setw(width) << D - << std::endl; - - // write scicoslab file - std::ofstream scicos(std::string(aircraft+"_lin.sce").c_str()); - scicos.precision(10); - width=20; - scicos - << std::scientific - << "x0=..\n" << std::setw(width) << x0 << ";\n" - << "u0=..\n" << std::setw(width) << u0 << ";\n" - << "sys = syslin('c',..\n" - << std::setw(width) << A << ",..\n" - << std::setw(width) << B << ",..\n" - << std::setw(width) << C << ",..\n" - << std::setw(width) << D << ");\n" - << "tfm = ss2tf(sys);\n" - << std::endl; -} - -extern "C" -{ - void sci_jsbsimTrim() - { - trimFunction(); - } - -} - - -// vim:ts=4:sw=4 diff --git a/scicoslab/sci_gateway/utilities.cpp b/scicoslab/sci_gateway/utilities.cpp deleted file mode 100644 index 977a2b130e6a1fbb3677d65d362897f3ac5c5a67..0000000000000000000000000000000000000000 --- a/scicoslab/sci_gateway/utilities.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * utilities.cpp - * Copyright (C) James Goppert 2010 <james.goppert@gmail.com> - * - * utilities.cpp 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, either version 2 of the License, or - * (at your option) any later version. - * - * utilities.cpp 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, see <http://www.gnu.org/licenses/>. - */ - -#include "utilities.h" -#include <cstdlib> - -void getIpars(int nStrings, int nInts, int * ipar, char *** stringArray, int ** intArray) -{ - // allocate memory - int iInt = 0, iString=0, iStringChar=0; - *stringArray = (char**)calloc(nStrings+1,sizeof(char*)); - *intArray = (int*)calloc(nInts,sizeof(int)); - - // get strings - while (1) - { - // if start of a new string - if (iStringChar==0) - { - int n = ipar[iInt]; - //printf("\nnew string of length : %d\n", n); - (*stringArray)[iString] = (char *)calloc(n+1, sizeof(char)); - iInt++; - } - - // read character - char c = ipar[iInt]; - //printf("iString: %d, iInt: %d, Char: %c\n", iString, iInt, c); - - (*stringArray)[iString][iStringChar] = c; - //printf("stringArray: %c\n", (*stringArray)[iString][iStringChar]); - - iStringChar++; - iInt++; - - // check for string completion - if (c==0) - { - iStringChar = 0; - iString++; - if (iString >= nStrings) break; // finished - } - } - for (int i=0;i<nInts;i++) - { - (*intArray)[i] = ipar[iInt]; - iInt = iInt + 1; - } -} - -// vim:ts=4:sw=4 diff --git a/scicoslab/sci_gateway/utilities.h b/scicoslab/sci_gateway/utilities.h deleted file mode 100644 index 0718a451b82799e649dbda1829e0625e9e651623..0000000000000000000000000000000000000000 --- a/scicoslab/sci_gateway/utilities.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * utilities.h - * Copyright (C) James Goppert 2010 <james.goppert@gmail.com> - * - * utilities.h 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, either version 2 of the License, or - * (at your option) any later version. - * - * utilities.h 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, see <http://www.gnu.org/licenses/>. - */ - -#ifndef JSBSim_utilities_H -#define JSBSim_utilities_H - -void getIpars(int nStrings, int nInts, int * ipar, char *** stringArray, int ** intArray); - -#endif - -// vim:ts=4:sw=4 diff --git a/scicoslab/scicos/builder.sce b/scicoslab/scicos/builder.sce deleted file mode 100644 index 2e6df59021500bb68170152d2bb9984a239533b9..0000000000000000000000000000000000000000 --- a/scicoslab/scicos/builder.sce +++ /dev/null @@ -1 +0,0 @@ -mode(-1); diff --git a/scicoslab/scicos/jsbsim/.gitignore b/scicoslab/scicos/jsbsim/.gitignore deleted file mode 100644 index 9cd6228514ff44bacbf60fd27b3ee08b7e92c680..0000000000000000000000000000000000000000 --- a/scicoslab/scicos/jsbsim/.gitignore +++ /dev/null @@ -1 +0,0 @@ -oooark.cosf diff --git a/scicoslab/scicos/jsbsim/ardupilotmegaHil.sci b/scicoslab/scicos/jsbsim/ardupilotmegaHil.sci deleted file mode 100644 index 885e65c135e84d573d2717ae964e800f1b5cc4c8..0000000000000000000000000000000000000000 --- a/scicoslab/scicos/jsbsim/ardupilotmegaHil.sci +++ /dev/null @@ -1,78 +0,0 @@ -function [x,y,typ]=ardupilotmegaHil(job,arg1,arg2) -// -// ardupilotmegaHil.sci -// Copyright (C) James Goppert 2010 <jgoppert@users.sourceforge.net> -// -// ardupilotmegaHil.sci 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, either version 3 of the License, or -// (at your option) any later version. -// -// ardupilotmegaHil.sci 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, see <http://www.gnu.org/licenses/>. -// - -x=[];y=[];typ=[]; - -select job - case 'plot' then - standard_draw(arg1) - case 'getinputs' then - [x,y,typ]=standard_inputs(arg1) - case 'getoutputs' then - [x,y,typ]=standard_outputs(arg1) - case 'getorigin' then - [x,y]=standard_origin(arg1) - case 'set' then - x=arg1; - graphics=arg1.graphics;exprs=graphics.exprs - model=arg1.model; - while %t do - labels=['device';'baud rate']; - [ok,device,baudRate,exprs]=.. - getvalue('Set ArduPilotMega HIL Parameters',labels,.. - list('str',-1,'vec',1),exprs); - if ~ok then break,end - [model,graphics,ok]=check_io(model,graphics,[13],[4],[1],[]) - if ok then - model.ipar=[.. - length(evstr(device)),ascii(evstr(device)),0,.. - baudRate]; - graphics.exprs=exprs; - x.graphics=graphics; - x.model=model; - break - end - end - case 'define' then - // set model properties - model=scicos_model() - model.sim=list('sci_ardupilotmegaHil',4) - model.in=[13] - model.out=[4] - model.evtin=[1] - model.blocktype='c' - model.dep_ut=[%f %t] - - // jsbsim parameters - device="""/dev/ttyUSB1"""; - baudRate=38400; - model.ipar=[.. - length(evstr(device)),ascii(evstr(device)),0,.. - baudRate]; - - // initialize strings for gui - exprs=[strcat(device),strcat(sci2exp(baudRate))]; - - // setup icon - gr_i=['xstringb(orig(1),orig(2),''ArduPilotMega HIL'',sz(1),sz(2),''fill'');'] - x=standard_define([5 2],model,exprs,gr_i) - end -endfunction - -// vim:ts=4:sw=4 diff --git a/scicoslab/scicos/jsbsim/jsbsim.cosf b/scicoslab/scicos/jsbsim/jsbsim.cosf deleted file mode 100644 index 347b03e3cca145d9a6cf2682051f0db8022bd385..0000000000000000000000000000000000000000 --- a/scicoslab/scicos/jsbsim/jsbsim.cosf +++ /dev/null @@ -1,104 +0,0 @@ -scs_m=scicos_diagram(.. - version="scicos4.4",.. - props=scicos_params(.. - wpar=[600,450,0,0,600,450],.. - Title=["jsbsim","jsbsim/"],.. - tol=[0.000001,0.000001,1.000D-10,31,0,0],.. - tf=30,.. - context=[],.. - void1=[],.. - options=tlist(["scsopt","3D","Background","Link","ID","Cmap"],list(%t,33),[8,1],[1,5,2],.. - list([4,1,10,1],[4,1,2,1]),[0.8,0.8,0.8]),.. - void2=[],.. - void3=[],.. - doc=list())) -scs_m.objs(1)=scicos_block(.. - gui="PAL_f",.. - graphics=scicos_graphics(.. - orig=[0,0],.. - sz=[40,40],.. - flip=%t,.. - theta=0,.. - exprs=[],.. - pin=[],.. - pout=[],.. - pein=[],.. - peout=[],.. - gr_i=list(.. - ["thick=xget(''thickness'');xset(''thickness'',2);"; - "xx=orig(1)+ [1 3 5 1 3 5 1 3 5]*(sz(1)/7);"; - "yy=orig(2)+sz(2)-[1 1 1 4 4 4 7 7 7]*(sz(2)/10);"; - "xrects([xx;yy;[sz(1)/7;sz(2)/5]*ones(1,9)]);"; - "xset(''thickness'',thick)"],8),.. - id="jsbsim",.. - in_implicit=[],.. - out_implicit=[]),.. - model=scicos_model(.. - sim="jsbsim",.. - in=[],.. - in2=[],.. - intyp=1,.. - out=[],.. - out2=[],.. - outtyp=1,.. - evtin=[],.. - evtout=[],.. - state=[],.. - dstate=[],.. - odstate=list(),.. - rpar=mlist(["diagram","props","objs","version","contrib","codegen"],.. - tlist(.. - ["params","wpar","title","tol","tf","context","void1","options","void2","void3",.. - "doc"],[600,450,0,0,600,450],["jsbsim","jsbsim/"],.. - [0.000001,0.000001,1.000D-10,31,0,0],30,[],[],.. - tlist(["scsopt","3D","Background","Link","ID","Cmap"],list(%t,33),[8,1],[1,5,2],.. - list([4,1,10,1],[4,1,2,1]),[0.8,0.8,0.8]),[],[],list()),.. - list(.. - mlist(["Block","graphics","model","gui","doc"],.. - mlist(.. - ["graphics","orig","sz","flip","theta","exprs","pin","pout","pein","peout","gr_i",.. - "id","in_implicit","out_implicit"],[0,0],[100,40],%t,0,.. - ["getenv(""JSBSim"")+""/aircraft""","getenv(""JSBSim"")+""/engine""",.. - "getenv(""JSBSim"")+""/systems""","""EasyStar""","[]","0","0","""localhost""",.. - "5500"],0,[0;0],[],[],.. - list("xstringb(orig(1),orig(2),''JSBSimComm'',sz(1),sz(2),''fill'');",8),"","E",.. - ["E";"E"]),.. - mlist(.. - ["model","sim","in","in2","intyp","out","out2","outtyp","evtin","evtout","state",.. - "dstate","odstate","rpar","ipar","opar","blocktype","firing","dep_ut","label",.. - "nzcross","nmode","equations"],list("sci_jsbsimComm",4),4,[],1,[13;13],[],1,[],.. - [],[],[],list(),[],.. - [39,47,104,111,109,101,47,106,103,111,112,112,101,114,116,47,80,114,111,106,101,.. - 99,116,115,47,74,83,66,83,105,109,47,97,105,114,99,114,97,102,116,0,37,47,104,.. - 111,109,101,47,106,103,111,112,112,101,114,116,47,80,114,111,106,101,99,116,.. - 115,47,74,83,66,83,105,109,47,101,110,103,105,110,101,0,38,47,104,111,109,101,.. - 47,106,103,111,112,112,101,114,116,47,80,114,111,106,101,99,116,115,47,74,83,.. - 66,83,105,109,47,115,121,115,116,101,109,115,0,8,69,97,115,121,83,116,97,114,0,.. - 9,108,111,99,97,108,104,111,115,116,0,0,0,5500],list(),"c",[],[%f,%t],"",0,0,.. - list()),"jsbsimComm",list()),.. - mlist(["Block","graphics","model","gui","doc"],.. - mlist(.. - ["graphics","orig","sz","flip","theta","exprs","pin","pout","pein","peout","gr_i",.. - "id","in_implicit","out_implicit"],[130,0],[100,40],%t,0,.. - ["""/dev/ttyUSB1""","38400"],0,0,0,[],.. - list("xstringb(orig(1),orig(2),''ArduPilotMega HIL'',sz(1),sz(2),''fill'');",8),.. - "","E","E"),.. - mlist(.. - ["model","sim","in","in2","intyp","out","out2","outtyp","evtin","evtout","state",.. - "dstate","odstate","rpar","ipar","opar","blocktype","firing","dep_ut","label",.. - "nzcross","nmode","equations"],list("sci_ardupilotmegaHil",4),13,[],1,4,[],1,1,.. - [],[],[],list(),[],[12,47,100,101,118,47,116,116,121,85,83,66,49,0,38400],list(),.. - "c",[],[%f,%t],"",0,0,list()),"ardupilotmegaHil",list())),"",list(),.. - mlist(.. - ["codegeneration","silent","cblock","rdnom","rpat","libs","opt","enable_debug",.. - "scopes","remove","replace"],0,0,[],[],[],1,0,[],[],[])),.. - ipar=[],.. - opar=list(),.. - blocktype="h",.. - firing=[],.. - dep_ut=[%f,%f],.. - label="",.. - nzcross=0,.. - nmode=0,.. - equations=list()),.. - doc=list()) diff --git a/scicoslab/scicos/jsbsim/jsbsimComm.sci b/scicoslab/scicos/jsbsim/jsbsimComm.sci deleted file mode 100644 index 579ce20f49d993a2f2bb2cb15bc4e3037c90375c..0000000000000000000000000000000000000000 --- a/scicoslab/scicos/jsbsim/jsbsimComm.sci +++ /dev/null @@ -1,115 +0,0 @@ -function [x,y,typ]=jsbsimComm(job,arg1,arg2) -// -// jsbsimComm.sci -// Copyright (C) James Goppert 2010 <jgoppert@users.sourceforge.net> -// -// jsbsimComm.sci 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, either version 3 of the License, or -// (at your option) any later version. -// -// jsbsimComm.sci 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, see <http://www.gnu.org/licenses/>. -// - -x=[];y=[];typ=[]; - -select job - case 'plot' then - standard_draw(arg1) - case 'getinputs' then - [x,y,typ]=standard_inputs(arg1) - case 'getoutputs' then - [x,y,typ]=standard_outputs(arg1) - case 'getorigin' then - [x,y]=standard_origin(arg1) - case 'set' then - x=arg1; - graphics=arg1.graphics;exprs=graphics.exprs - model=arg1.model; - while %t do - labels=[.. - 'aircraft path';.. - 'engine path';.. - 'systems path';.. - 'model name';.. - 'x0';.. - 'debug level';.. - 'enable Flight Gear comm';.. - 'Flight Gear host';.. - 'Flight Gear port']; - [ok,AircraftPath,EnginePath,SystemsPath,ModelName,x0,DebugLevel,.. - EnableFlightGearComm,FlightGearHost,FlightGearPort,exprs]=.. - getvalue('Set JSBSim Parameters',labels,.. - list('str',-1,'str',-1,'str',-1,'str',-1,'vec',-1,'vec',1,.. - 'vec',1,'str',-1,'vec',1),exprs); - if ~ok then break,end - n=size(x0,1) - model.out=[n;n]; - [model,graphics,ok]=check_io(model,graphics,[4],[n;n],[],[]) - if ok then - model.state=[x0]; - model.ipar=[.. - length(evstr(AircraftPath)),ascii(evstr(AircraftPath)),0,.. - length(evstr(EnginePath)),ascii(evstr(EnginePath)),0,.. - length(evstr(SystemsPath)),ascii(evstr(SystemsPath)),0,.. - length(evstr(ModelName)),ascii(evstr(ModelName)),0,.. - length(evstr(FlightGearHost)),ascii(evstr(FlightGearHost)),0,.. - DebugLevel,EnableFlightGearComm,FlightGearPort]; - graphics.exprs=exprs; - x.graphics=graphics; - x.model=model; - break - end - end - case 'define' then - // set model properties - model=scicos_model() - model.sim=list('sci_jsbsimComm',4) - model.in=4 - model.out=[13;13] - model.blocktype='c' - model.dep_ut=[%f %t] - - // jsbsim parameters - ModelName="""EasyStar"""; - AircraftPath="getenv(""JSBSim"")+""/aircraft"""; - EnginePath="getenv(""JSBSim"")+""/engine"""; - SystemsPath="getenv(""JSBSim"")+""/systems"""; - DebugLevel=0; - FlightGearHost="""localhost"""; - FlightGearPort=5500; - EnableFlightGearComm=0; - model.ipar=[.. - length(evstr(AircraftPath)),ascii(evstr(AircraftPath)),0,.. - length(evstr(EnginePath)),ascii(evstr(EnginePath)),0,.. - length(evstr(SystemsPath)),ascii(evstr(SystemsPath)),0,.. - length(evstr(ModelName)),ascii(evstr(ModelName)),0,.. - length(evstr(FlightGearHost)),ascii(evstr(FlightGearHost)),0,.. - DebugLevel,EnableFlightGearComm,FlightGearPort]; - - // intial state - x0=[] - - // save state - model.state=x0; - - // initialize strings for gui - exprs=[strcat(AircraftPath),strcat(EnginePath),.. - strcat(SystemsPath),strcat(ModelName),.. - strcat(sci2exp(x0)),strcat(sci2exp(DebugLevel)),.. - strcat(sci2exp(EnableFlightGearComm)),strcat(FlightGearHost),.. - strcat(sci2exp(FlightGearPort))]; - - // setup icon - gr_i=['xstringb(orig(1),orig(2),''JSBSimComm'',sz(1),sz(2),''fill'');'] - x=standard_define([5 2],model,exprs,gr_i) - end -endfunction - -// vim:ts=4:sw=4 diff --git a/scicoslab/scicos/loader.sce b/scicoslab/scicos/loader.sce deleted file mode 100644 index b695508698712b11f5dbfa051cc7bc9b9f8cca36..0000000000000000000000000000000000000000 --- a/scicoslab/scicos/loader.sce +++ /dev/null @@ -1,4 +0,0 @@ -mode(-1); -genlib('lib_jsbsimBlocks',pwd()+'/jsbsim'); -create_palette('jsbsim'); -add_palette('jsbsim',pwd()+'/jsbsim/jsbsim.cosf'); diff --git a/scicoslab/scripts/fgmrun.sh b/scicoslab/scripts/fgmrun.sh deleted file mode 100755 index b56524333c635d22c596963cbe9e47ab45da6a65..0000000000000000000000000000000000000000 --- a/scicoslab/scripts/fgmrun.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash -#--native-ctrls=socket,out,119,,5501,udp \ -#--native-ctrls=socket,in,120,,5502,udp \ -if [[ $# != 3 ]] -then - echo usage: $0 ip-address num aircraft - exit -fi -ip=$1 -num=$2 -aircraft=$3 -port=$((5000+$num)) -callsign=f-$num -echo callsign: $callsign -echo port: $port -portFdm=5500+$num -#--fdm=external \ -#--native-fdm=socket,in,120,,portFdm,udp \ -fgfs \ ---callsign=$callsign \ ---aircraft=$aircraft \ ---geometry=400x300 \ ---multiplay=in,10,$ip,$port \ ---multiplay=out,10,mpserver05.flightgear.org,5000 \ ---airport=KSFO \ ---runway=28R -#--shading-flat \ -#--fog-disable \ -#--disable-textures \ -#--disable-specular-highlight \ -#--disable-skyblend \ -#--disable-random-objects \ -#--disable-panel \ -#--disable-horizon-effect \ -#--disable-clouds \ -#--disable-anti-alias-hud diff --git a/scicoslab/scripts/fgrun.sh b/scicoslab/scripts/fgrun.sh deleted file mode 100755 index 3f77e5f69aa3250d48be285126623a2c13d76f74..0000000000000000000000000000000000000000 --- a/scicoslab/scripts/fgrun.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -#--disable-textures \ -if [ $# != 1 ] -then - echo usage: $0 aircraft - exit -fi -aircraft=$1 -fgfs \ ---aircraft=$aircraft \ ---geometry=400x300 \ ---vc=30 \ ---altitude=1000 \ ---heading=90 \ ---roll=0 \ ---pitch=0 \ ---wind=0@0 \ ---turbulence=0.0 \ ---timeofday=noon \ ---shading-flat \ ---notrim \ ---fog-disable \ ---disable-specular-highlight \ ---disable-skyblend \ ---disable-random-objects \ ---disable-panel \ ---disable-horizon-effect \ ---disable-clouds \ ---disable-anti-alias-hud diff --git a/scicoslab/scripts/fgrunExt.sh b/scicoslab/scripts/fgrunExt.sh deleted file mode 100755 index ed9bd8012acf9ff87ab04f83484b411fef26ee3b..0000000000000000000000000000000000000000 --- a/scicoslab/scripts/fgrunExt.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -#--native-ctrls=socket,out,119,,5501,udp \ -#--native-ctrls=socket,in,120,,5502,udp \ -#--disable-textures \ -if [ $# != 1 ] -then - echo usage: $0 aircraft - exit -fi -aircraft=$1 -fgfs \ ---fdm=external \ ---aircraft=$aircraft \ ---geometry=400x300 \ ---native-fdm=socket,in,120,,5500,udp \ ---vc=30 \ ---altitude=1000 \ ---heading=90 \ ---roll=0 \ ---pitch=0 \ ---wind=0@0 \ ---turbulence=0.0 \ ---timeofday=noon \ ---shading-flat \ ---notrim \ ---fog-disable \ ---disable-specular-highlight \ ---disable-skyblend \ ---disable-random-objects \ ---disable-panel \ ---disable-horizon-effect \ ---disable-clouds \ ---disable-anti-alias-hud diff --git a/scripts/737_cruise.xml b/scripts/737_cruise.xml old mode 100644 new mode 100755 diff --git a/scripts/737_cruise_steady_turn.xml b/scripts/737_cruise_steady_turn.xml old mode 100644 new mode 100755 diff --git a/scripts/B737_Runway.xml b/scripts/B737_Runway.xml old mode 100644 new mode 100755 diff --git a/scripts/B747_script1.xml b/scripts/B747_script1.xml old mode 100644 new mode 100755 diff --git a/scripts/F4N_runway_test.xml b/scripts/F4N_runway_test.xml old mode 100644 new mode 100755 diff --git a/scripts/J2461.xml b/scripts/J2461.xml old mode 100644 new mode 100755 diff --git a/scripts/L410.xml b/scripts/L410.xml old mode 100644 new mode 100755 diff --git a/scripts/Postfix.kml b/scripts/Postfix.kml old mode 100644 new mode 100755 diff --git a/scripts/Prefix.kml b/scripts/Prefix.kml old mode 100644 new mode 100755 diff --git a/scripts/StellarJ_Fly.xml b/scripts/StellarJ_Fly.xml old mode 100644 new mode 100755 diff --git a/scripts/T38.xml b/scripts/T38.xml old mode 100644 new mode 100755 diff --git a/scripts/b171.xml b/scripts/b171.xml old mode 100644 new mode 100755 diff --git a/scripts/b737_runway_new.xml b/scripts/b737_runway_new.xml old mode 100644 new mode 100755 diff --git a/scripts/ball.xml b/scripts/ball.xml old mode 100644 new mode 100755 diff --git a/scripts/ball_chute.xml b/scripts/ball_chute.xml old mode 100644 new mode 100755 diff --git a/scripts/ball_orbit.xml b/scripts/ball_orbit.xml index 19fe0ca645ccea5b51e4342faee752363ee1f0e2..77e733900c69f6dc0a2dd940cb58309bd8a51a59 100644 --- a/scripts/ball_orbit.xml +++ b/scripts/ball_orbit.xml @@ -4,7 +4,7 @@ xsi:noNamespaceSchemaLocation="http://jsbsim.sf.net/JSBSimScript.xsd" name="cannon ball test"> <use aircraft="ball" initialize="reset00"/> - <run start="0.0" end="10800" dt="0.1"> + <run start="0.0" end="10800" dt="0.01"> <description> Integrators diff --git a/scripts/c1723.xml b/scripts/c1723.xml old mode 100644 new mode 100755 diff --git a/scripts/c1724.xml b/scripts/c1724.xml old mode 100644 new mode 100755 diff --git a/scripts/c172_cruise_8K.xml b/scripts/c172_cruise_8K.xml old mode 100644 new mode 100755 diff --git a/scripts/c172_elevation_test.xml b/scripts/c172_elevation_test.xml old mode 100644 new mode 100755 diff --git a/scripts/c3104.xml b/scripts/c3104.xml old mode 100644 new mode 100755 diff --git a/scripts/cannonball.xml b/scripts/cannonball.xml old mode 100644 new mode 100755 diff --git a/scripts/f16_runway_test.xml b/scripts/f16_runway_test.xml old mode 100644 new mode 100755 diff --git a/scripts/f16_test.xml b/scripts/f16_test.xml old mode 100644 new mode 100755 diff --git a/scripts/kml_output.xml b/scripts/kml_output.xml old mode 100644 new mode 100755 diff --git a/scripts/plotfile.xml b/scripts/plotfile.xml old mode 100644 new mode 100755 diff --git a/scripts/x152.xml b/scripts/x152.xml old mode 100644 new mode 100755 diff --git a/src/.gitignore b/src/.gitignore deleted file mode 100644 index 2b1a523606e943d6b2391a2542d2f361288469b4..0000000000000000000000000000000000000000 --- a/src/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.sce diff --git a/src/FGComm.cpp b/src/FGComm.cpp deleted file mode 100644 index 015ca3fcd7630c7d16a1d1f30f068333678d1e20..0000000000000000000000000000000000000000 --- a/src/FGComm.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * FGComm.cpp - * Copyright (C) James Goppert 2010 <james.goppert@gmail.com> - * - * FGComm.cpp 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, either version 2 of the License, or - * (at your option) any later version. - * - * FGComm.cpp 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, see <http://www.gnu.org/licenses/>. - */ - -#include "FGFDMExec.h" -#include "math/FGStateSpace.h" -#include "input_output/flightGearIO.h" - -int main (int argc, char const* argv[]) -{ - using namespace JSBSim; - FGFDMExec fdm; - fdm.LoadModel("../aircraft","../engine","../systems","c172p"); - fdm.Setdt(1./120.); - - // Turn on propulsion system - fdm.GetPropulsion()->InitRunning(-1); - - // get propulsion pointer to determine type/ etc. - FGEngine * engine0 = fdm.GetPropulsion()->GetEngine(0); - FGThruster * thruster0 = engine0->GetThruster(); - - bool variablePropPitch = false; - - FGStateSpace ss(fdm); - ss.x.add(new FGStateSpace::Vt); - ss.x.add(new FGStateSpace::Alpha); - ss.x.add(new FGStateSpace::Theta); - ss.x.add(new FGStateSpace::Q); - - if (thruster0->GetType()==FGThruster::ttPropeller) - { - ss.x.add(new FGStateSpace::Rpm); - if (variablePropPitch) ss.x.add(new FGStateSpace::PropPitch); - } - ss.x.add(new FGStateSpace::Beta); - ss.x.add(new FGStateSpace::Phi); - ss.x.add(new FGStateSpace::P); - ss.x.add(new FGStateSpace::R); - ss.x.add(new FGStateSpace::Alt); - ss.x.add(new FGStateSpace::Psi); - ss.x.add(new FGStateSpace::Longitude); - ss.x.add(new FGStateSpace::Latitude); - - ss.u.add(new FGStateSpace::ThrottleCmd); - ss.u.add(new FGStateSpace::DaCmd); - ss.u.add(new FGStateSpace::DeCmd); - ss.u.add(new FGStateSpace::DrCmd); - - // state feedback - ss.y = ss.x; - - double x0[] = - { 1.2000005040e+02, - 7.5858289225e-02, - 7.5858289225e-02, - -5.7341647634e-06, - 1.8532553592e+03, - -7.2931141482e-03, - 0.0000000000e+00, - -4.1700389256e-08, - -3.1694019426e-09, - 1.0000000000e+03, - 0.0000000000e+00, - 8.4822065863e-01, - 1.2929548335e-02, - -2.6633415566e-02, - -1.7816482429e-02 - }; - double u0[] = - { 8.4822065863e-01, - 4.9396555243e-02, - -5.4509651179e-02, - -6.3812616150e-02 - }; - ss.x.set(x0), - ss.u.set(u0); - - // stabilize propulsion - fdm.GetPropulsion()->GetSteadyState(); - - FGNetFDM netFdm; - FGfdmSocket socket("localhost",5500,FGfdmSocket::ptUDP); - while (1) - { - JSBSim2FlightGearNetFDM(fdm,netFdm); - socket.Send((char *)(& netFdm), sizeof(netFdm)); - for (int i=0;i<10;i++) - { - fdm.Run(); - std::cout << std::scientific << std::endl; - std::cout << "theta dot netfdm" << netFdm.thetadot << std::endl; - std::cout << "theta dot jsbsim" << fdm.GetAuxiliary()->GetEulerRates(2) << std::endl; - std::cout << ss << std::endl; - std::cout << std::fixed<< std::endl; - } - usleep(10*1.0e6*fdm.GetDeltaT()); - } - return 0; -} - -// vim:ts=4:sw=4 diff --git a/src/FGFDMExec.cpp b/src/FGFDMExec.cpp index 535a78369f90c4880eccbd33b109eb1c1cea6d3f..4cba2d0f9f3aa391485866edaa6db6525b1086af 100644 --- a/src/FGFDMExec.cpp +++ b/src/FGFDMExec.cpp @@ -69,10 +69,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.79 2010/07/25 13:52:20 jberndt Exp $"; +static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.80 2010/08/21 22:56:10 jberndt Exp $"; static const char *IdHdr = ID_FDMEXEC; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -88,21 +87,18 @@ CLASS IMPLEMENTATION void checkTied ( FGPropertyManager *node ) { - int N = node->nChildren(); - string name; - - for (int i=0; i<N; i++) - { - if (node->getChild(i)->nChildren() ) - { - checkTied( (FGPropertyManager*)node->getChild(i) ); - } - if ( node->getChild(i)->isTied() ) - { - name = ((FGPropertyManager*)node->getChild(i))->GetFullyQualifiedName(); - node->Untie(name); - } + int N = node->nChildren(); + string name; + + for (int i=0; i<N; i++) { + if (node->getChild(i)->nChildren() ) { + checkTied( (FGPropertyManager*)node->getChild(i) ); + } + if ( node->getChild(i)->isTied() ) { + name = ((FGPropertyManager*)node->getChild(i))->GetFullyQualifiedName(); + node->Untie(name); } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -111,245 +107,234 @@ void checkTied ( FGPropertyManager *node ) FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root) { - Frame = 0; - Error = 0; - GroundCallback = 0; - Atmosphere = 0; - FCS = 0; - Propulsion = 0; - MassBalance = 0; - Aerodynamics = 0; - Inertial = 0; - GroundReactions = 0; - ExternalReactions = 0; - BuoyantForces = 0; - Aircraft = 0; - Propagate = 0; - Auxiliary = 0; - Input = 0; - IC = 0; - Trim = 0; - Script = 0; - - RootDir = ""; - - modelLoaded = false; - IsChild = false; - holding = false; - Terminate = false; - - sim_time = 0.0; - dT = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is - // run in standalone mode with no initialization file. - - IdFDM = FDMctr; // The main (parent) JSBSim instance is always the "zeroth" - FDMctr++; // instance. "child" instances are loaded last. - - try - { - char* num = getenv("JSBSIM_DEBUG"); - if (num) debug_lvl = atoi(num); // set debug level - } - catch (...) // if error set to 1 - { - debug_lvl = 1; - } + Frame = 0; + Error = 0; + GroundCallback = 0; + Atmosphere = 0; + FCS = 0; + Propulsion = 0; + MassBalance = 0; + Aerodynamics = 0; + Inertial = 0; + GroundReactions = 0; + ExternalReactions = 0; + BuoyantForces = 0; + Aircraft = 0; + Propagate = 0; + Auxiliary = 0; + Input = 0; + IC = 0; + Trim = 0; + Script = 0; + + RootDir = ""; + + modelLoaded = false; + IsChild = false; + holding = false; + Terminate = false; + + sim_time = 0.0; + dT = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is + // run in standalone mode with no initialization file. + + IdFDM = FDMctr; // The main (parent) JSBSim instance is always the "zeroth" + FDMctr++; // instance. "child" instances are loaded last. + + try { + char* num = getenv("JSBSIM_DEBUG"); + if (num) debug_lvl = atoi(num); // set debug level + } catch (...) { // if error set to 1 + debug_lvl = 1; + } - if (Root == 0) - { - if (master == 0) - master = new FGPropertyManager; - Root = master; - } + if (Root == 0) { + if (master == 0) + master = new FGPropertyManager; + Root = master; + } - instance = Root->GetNode("/fdm/jsbsim",IdFDM,true); - Debug(0); - // this is to catch errors in binding member functions to the property tree. - try - { - Allocate(); - } - catch ( string msg ) - { - cout << "Caught error: " << msg << endl; - exit(1); - } + instance = Root->GetNode("/fdm/jsbsim",IdFDM,true); + Debug(0); + // this is to catch errors in binding member functions to the property tree. + try { + Allocate(); + } catch ( string msg ) { + cout << "Caught error: " << msg << endl; + exit(1); + } - trim_status = false; - ta_mode = 99; + trim_status = false; + ta_mode = 99; - Constructing = true; - typedef int (FGFDMExec::*iPMF)(void) const; + Constructing = true; + typedef int (FGFDMExec::*iPMF)(void) const; // instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis); - instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim); - instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions); - instance->Tie("simulation/terminate", (int *)&Terminate); - instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime); - instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel); + instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim); + instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions); + instance->Tie("simulation/terminate", (int *)&Terminate); + instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime); + instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel); - Constructing = false; + Constructing = false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGFDMExec::~FGFDMExec() { - try - { - checkTied( instance ); - DeAllocate(); - if (Root == 0) delete master; - } - catch ( string msg ) - { - cout << "Caught error: " << msg << endl; - } + try { + checkTied( instance ); + DeAllocate(); + if (Root == 0) delete master; + } catch ( string msg ) { + cout << "Caught error: " << msg << endl; + } - for (unsigned int i=1; i<ChildFDMList.size(); i++) delete ChildFDMList[i]->exec; - ChildFDMList.clear(); + for (unsigned int i=1; i<ChildFDMList.size(); i++) delete ChildFDMList[i]->exec; + ChildFDMList.clear(); - PropertyCatalog.clear(); + PropertyCatalog.clear(); - FDMctr--; + FDMctr--; - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFDMExec::Allocate(void) { - bool result=true; - - Atmosphere = new FGAtmosphere(this); - FCS = new FGFCS(this); - Propulsion = new FGPropulsion(this); - MassBalance = new FGMassBalance(this); - Aerodynamics = new FGAerodynamics (this); - Inertial = new FGInertial(this); - - GroundCallback = new FGGroundCallback(Inertial->GetRefRadius()); - - GroundReactions = new FGGroundReactions(this); - ExternalReactions = new FGExternalReactions(this); - BuoyantForces = new FGBuoyantForces(this); - Aircraft = new FGAircraft(this); - Propagate = new FGPropagate(this); - Auxiliary = new FGAuxiliary(this); - Input = new FGInput(this); - - // Schedule a model. The second arg (the integer) is the pass number. For - // instance, the atmosphere model could get executed every fifth pass it is called. - - Schedule(Input, 1); - Schedule(Atmosphere, 1); - Schedule(FCS, 1); - Schedule(Propulsion, 1); - Schedule(MassBalance, 1); - Schedule(Aerodynamics, 1); - Schedule(Inertial, 1); - Schedule(GroundReactions, 1); - Schedule(ExternalReactions, 1); - Schedule(BuoyantForces, 1); - Schedule(Aircraft, 1); - Schedule(Propagate, 1); - Schedule(Auxiliary, 1); - - // Initialize models so they can communicate with each other - - vector <FGModel*>::iterator it; - for (it = Models.begin(); it != Models.end(); ++it) (*it)->InitModel(); - - IC = new FGInitialCondition(this); - - modelLoaded = false; - - return result; + bool result=true; + + Atmosphere = new FGAtmosphere(this); + FCS = new FGFCS(this); + Propulsion = new FGPropulsion(this); + MassBalance = new FGMassBalance(this); + Aerodynamics = new FGAerodynamics (this); + Inertial = new FGInertial(this); + + GroundCallback = new FGGroundCallback(Inertial->GetRefRadius()); + + GroundReactions = new FGGroundReactions(this); + ExternalReactions = new FGExternalReactions(this); + BuoyantForces = new FGBuoyantForces(this); + Aircraft = new FGAircraft(this); + Propagate = new FGPropagate(this); + Auxiliary = new FGAuxiliary(this); + Input = new FGInput(this); + + // Schedule a model. The second arg (the integer) is the pass number. For + // instance, the atmosphere model could get executed every fifth pass it is called. + + Schedule(Input, 1); + Schedule(Atmosphere, 1); + Schedule(FCS, 1); + Schedule(Propulsion, 1); + Schedule(MassBalance, 1); + Schedule(Aerodynamics, 1); + Schedule(Inertial, 1); + Schedule(GroundReactions, 1); + Schedule(ExternalReactions, 1); + Schedule(BuoyantForces, 1); + Schedule(Aircraft, 1); + Schedule(Propagate, 1); + Schedule(Auxiliary, 1); + + // Initialize models so they can communicate with each other + + vector <FGModel*>::iterator it; + for (it = Models.begin(); it != Models.end(); ++it) (*it)->InitModel(); + + IC = new FGInitialCondition(this); + + modelLoaded = false; + + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFDMExec::DeAllocate(void) { - delete Input; - delete Atmosphere; - delete FCS; - delete Propulsion; - delete MassBalance; - delete Aerodynamics; - delete Inertial; - delete GroundReactions; - delete ExternalReactions; - delete BuoyantForces; - delete Aircraft; - delete Propagate; - delete Auxiliary; - delete Script; - - for (unsigned i=0; i<Outputs.size(); i++) delete Outputs[i]; - Outputs.clear(); - - delete IC; - delete Trim; - - delete GroundCallback; - - Error = 0; - - Input = 0; - Atmosphere = 0; - FCS = 0; - Propulsion = 0; - MassBalance = 0; - Aerodynamics = 0; - Inertial = 0; - GroundReactions = 0; - ExternalReactions = 0; - BuoyantForces = 0; - Aircraft = 0; - Propagate = 0; - Auxiliary = 0; - Script = 0; - - Models.clear(); - - modelLoaded = false; - return modelLoaded; + delete Input; + delete Atmosphere; + delete FCS; + delete Propulsion; + delete MassBalance; + delete Aerodynamics; + delete Inertial; + delete GroundReactions; + delete ExternalReactions; + delete BuoyantForces; + delete Aircraft; + delete Propagate; + delete Auxiliary; + delete Script; + + for (unsigned i=0; i<Outputs.size(); i++) delete Outputs[i]; + Outputs.clear(); + + delete IC; + delete Trim; + + delete GroundCallback; + + Error = 0; + + Input = 0; + Atmosphere = 0; + FCS = 0; + Propulsion = 0; + MassBalance = 0; + Aerodynamics = 0; + Inertial = 0; + GroundReactions = 0; + ExternalReactions = 0; + BuoyantForces = 0; + Aircraft = 0; + Propagate = 0; + Auxiliary = 0; + Script = 0; + + Models.clear(); + + modelLoaded = false; + return modelLoaded; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFDMExec::Schedule(FGModel* model, int rate) { - model->SetRate(rate); - Models.push_back(model); + model->SetRate(rate); + Models.push_back(model); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFDMExec::Run(void) { - bool success=true; + bool success=true; - Debug(2); + Debug(2); - for (unsigned int i=1; i<ChildFDMList.size(); i++) - { - ChildFDMList[i]->AssignState(Propagate); // Transfer state to the child FDM - ChildFDMList[i]->Run(); - } + for (unsigned int i=1; i<ChildFDMList.size(); i++) { + ChildFDMList[i]->AssignState(Propagate); // Transfer state to the child FDM + ChildFDMList[i]->Run(); + } - // returns true if success, false if complete - if (Script != 0 && !IntegrationSuspended()) success = Script->RunScript(); + // returns true if success, false if complete + if (Script != 0 && !IntegrationSuspended()) success = Script->RunScript(); - vector <FGModel*>::iterator it; - for (it = Models.begin(); it != Models.end(); ++it) (*it)->Run(); + vector <FGModel*>::iterator it; + for (it = Models.begin(); it != Models.end(); ++it) (*it)->Run(); - Frame++; - if (!Holding()) IncrTime(); - if (Terminate) success = false; + Frame++; + if (!Holding()) IncrTime(); + if (Terminate) success = false; - return (success); + return (success); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -357,47 +342,47 @@ bool FGFDMExec::Run(void) bool FGFDMExec::RunIC(void) { - SuspendIntegration(); // saves the integration rate, dt, then sets it to 0.0. - Initialize(IC); - Run(); - ResumeIntegration(); // Restores the integration rate to what it was. + SuspendIntegration(); // saves the integration rate, dt, then sets it to 0.0. + Initialize(IC); + Run(); + ResumeIntegration(); // Restores the integration rate to what it was. - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFDMExec::Initialize(FGInitialCondition *FGIC) { - Propagate->SetInitialState( FGIC ); + Propagate->SetInitialState( FGIC ); - Atmosphere->Run(); - Atmosphere->SetWindNED( FGIC->GetWindNFpsIC(), - FGIC->GetWindEFpsIC(), - FGIC->GetWindDFpsIC() ); + Atmosphere->Run(); + Atmosphere->SetWindNED( FGIC->GetWindNFpsIC(), + FGIC->GetWindEFpsIC(), + FGIC->GetWindDFpsIC() ); - FGColumnVector3 vAeroUVW; - vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED(); + FGColumnVector3 vAeroUVW; + vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED(); - double alpha, beta; - if (vAeroUVW(eW) != 0.0) - alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0; - else - alpha = 0.0; - if (vAeroUVW(eV) != 0.0) - beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), (fabs(vAeroUVW(eU))/vAeroUVW(eU))*sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0; - else - beta = 0.0; + double alpha, beta; + if (vAeroUVW(eW) != 0.0) + alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0; + else + alpha = 0.0; + if (vAeroUVW(eV) != 0.0) + beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), (fabs(vAeroUVW(eU))/vAeroUVW(eU))*sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0; + else + beta = 0.0; - Auxiliary->SetAB(alpha, beta); + Auxiliary->SetAB(alpha, beta); - double Vt = vAeroUVW.Magnitude(); - Auxiliary->SetVt(Vt); + double Vt = vAeroUVW.Magnitude(); + Auxiliary->SetVt(Vt); - Auxiliary->SetMach(Vt/Atmosphere->GetSoundSpeed()); + Auxiliary->SetMach(Vt/Atmosphere->GetSoundSpeed()); - double qbar = 0.5*Vt*Vt*Atmosphere->GetDensity(); - Auxiliary->Setqbar(qbar); + double qbar = 0.5*Vt*Vt*Atmosphere->GetDensity(); + Auxiliary->Setqbar(qbar); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -407,637 +392,573 @@ void FGFDMExec::Initialize(FGInitialCondition *FGIC) void FGFDMExec::ResetToInitialConditions(int mode) { - if (mode == 1) - { - for (unsigned int i=0; i<Outputs.size(); i++) - { - Outputs[i]->SetStartNewFile(true); - } + if (mode == 1) { + for (unsigned int i=0; i<Outputs.size(); i++) { + Outputs[i]->SetStartNewFile(true); } - - ResetToInitialConditions(); + } + + ResetToInitialConditions(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFDMExec::ResetToInitialConditions(void) { - if (Constructing) return; + if (Constructing) return; - vector <FGModel*>::iterator it; - for (it = Models.begin(); it != Models.end(); ++it) (*it)->InitModel(); + vector <FGModel*>::iterator it; + for (it = Models.begin(); it != Models.end(); ++it) (*it)->InitModel(); - RunIC(); - if (Script) Script->ResetEvents(); + RunIC(); + if (Script) Script->ResetEvents(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFDMExec::SetGroundCallback(FGGroundCallback* p) { - delete GroundCallback; - GroundCallback = p; + delete GroundCallback; + GroundCallback = p; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% vector <string> FGFDMExec::EnumerateFDMs(void) { - vector <string> FDMList; + vector <string> FDMList; - FDMList.push_back(Aircraft->GetAircraftName()); + FDMList.push_back(Aircraft->GetAircraftName()); - for (unsigned int i=1; i<ChildFDMList.size(); i++) - { - FDMList.push_back(ChildFDMList[i]->exec->GetAircraft()->GetAircraftName()); - } + for (unsigned int i=1; i<ChildFDMList.size(); i++) { + FDMList.push_back(ChildFDMList[i]->exec->GetAircraft()->GetAircraftName()); + } - return FDMList; + return FDMList; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFDMExec::LoadScript(string script, double deltaT) { - bool result; + bool result; - Script = new FGScript(this); - result = Script->LoadScript(RootDir + script, deltaT); + Script = new FGScript(this); + result = Script->LoadScript(RootDir + script, deltaT); - return result; + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string SystemsPath, - string model, bool addModelToPath) + string model, bool addModelToPath) { - FGFDMExec::AircraftPath = RootDir + AircraftPath; - FGFDMExec::EnginePath = RootDir + EnginePath; - FGFDMExec::SystemsPath = RootDir + SystemsPath; + FGFDMExec::AircraftPath = RootDir + AircraftPath; + FGFDMExec::EnginePath = RootDir + EnginePath; + FGFDMExec::SystemsPath = RootDir + SystemsPath; - return LoadModel(model, addModelToPath); + return LoadModel(model, addModelToPath); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFDMExec::LoadModel(string model, bool addModelToPath) { - string token; - string aircraftCfgFileName; - Element* element = 0L; - bool result = false; // initialize result to false, indicating input file not yet read - - modelName = model; // Set the class modelName attribute - - if ( AircraftPath.empty() || EnginePath.empty() || SystemsPath.empty()) - { - cerr << "Error: attempted to load aircraft with undefined "; - cerr << "aircraft, engine, and system paths" << endl; - return false; + string token; + string aircraftCfgFileName; + Element* element = 0L; + bool result = false; // initialize result to false, indicating input file not yet read + + modelName = model; // Set the class modelName attribute + + if( AircraftPath.empty() || EnginePath.empty() || SystemsPath.empty()) { + cerr << "Error: attempted to load aircraft with undefined "; + cerr << "aircraft, engine, and system paths" << endl; + return false; + } + + FullAircraftPath = AircraftPath; + if (addModelToPath) FullAircraftPath += "/" + model; + aircraftCfgFileName = FullAircraftPath + "/" + model + ".xml"; + + if (modelLoaded) { + DeAllocate(); + Allocate(); + } + + int saved_debug_lvl = debug_lvl; + + document = LoadXMLDocument(aircraftCfgFileName); // "document" is a class member + if (document) { + if (IsChild) debug_lvl = 0; + + ReadPrologue(document); + + if (IsChild) debug_lvl = saved_debug_lvl; + + // Process the fileheader element in the aircraft config file. This element is OPTIONAL. + element = document->FindElement("fileheader"); + if (element) { + result = ReadFileHeader(element); + if (!result) { + cerr << endl << "Aircraft fileheader element has problems in file " << aircraftCfgFileName << endl; + return result; + } } - FullAircraftPath = AircraftPath; - if (addModelToPath) FullAircraftPath += "/" + model; - aircraftCfgFileName = FullAircraftPath + "/" + model + ".xml"; + if (IsChild) debug_lvl = 0; - if (modelLoaded) - { - DeAllocate(); - Allocate(); + // Process the metrics element. This element is REQUIRED. + element = document->FindElement("metrics"); + if (element) { + result = Aircraft->Load(element); + if (!result) { + cerr << endl << "Aircraft metrics element has problems in file " << aircraftCfgFileName << endl; + return result; + } + } else { + cerr << endl << "No metrics element was found in the aircraft config file." << endl; + return false; + } + + // Process the mass_balance element. This element is REQUIRED. + element = document->FindElement("mass_balance"); + if (element) { + result = MassBalance->Load(element); + if (!result) { + cerr << endl << "Aircraft mass_balance element has problems in file " << aircraftCfgFileName << endl; + return result; + } + } else { + cerr << endl << "No mass_balance element was found in the aircraft config file." << endl; + return false; + } + + // Process the ground_reactions element. This element is REQUIRED. + element = document->FindElement("ground_reactions"); + if (element) { + result = GroundReactions->Load(element); + if (!result) { + cerr << endl << "Aircraft ground_reactions element has problems in file " << aircraftCfgFileName << endl; + return result; + } + } else { + cerr << endl << "No ground_reactions element was found in the aircraft config file." << endl; + return false; + } + + // Process the external_reactions element. This element is OPTIONAL. + element = document->FindElement("external_reactions"); + if (element) { + result = ExternalReactions->Load(element); + if (!result) { + cerr << endl << "Aircraft external_reactions element has problems in file " << aircraftCfgFileName << endl; + return result; + } + } + + // Process the buoyant_forces element. This element is OPTIONAL. + element = document->FindElement("buoyant_forces"); + if (element) { + result = BuoyantForces->Load(element); + if (!result) { + cerr << endl << "Aircraft buoyant_forces element has problems in file " << aircraftCfgFileName << endl; + return result; + } + } + + // Process the propulsion element. This element is OPTIONAL. + element = document->FindElement("propulsion"); + if (element) { + result = Propulsion->Load(element); + if (!result) { + cerr << endl << "Aircraft propulsion element has problems in file " << aircraftCfgFileName << endl; + return result; + } + } + + // Process the system element[s]. This element is OPTIONAL, and there may be more than one. + element = document->FindElement("system"); + while (element) { + result = FCS->Load(element, FGFCS::stSystem); + if (!result) { + cerr << endl << "Aircraft system element has problems in file " << aircraftCfgFileName << endl; + return result; + } + element = document->FindNextElement("system"); } - int saved_debug_lvl = debug_lvl; - - document = LoadXMLDocument(aircraftCfgFileName); // "document" is a class member - if (document) - { - if (IsChild) debug_lvl = 0; - - ReadPrologue(document); - - if (IsChild) debug_lvl = saved_debug_lvl; - - // Process the fileheader element in the aircraft config file. This element is OPTIONAL. - element = document->FindElement("fileheader"); - if (element) - { - result = ReadFileHeader(element); - if (!result) - { - cerr << endl << "Aircraft fileheader element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - - if (IsChild) debug_lvl = 0; - - // Process the metrics element. This element is REQUIRED. - element = document->FindElement("metrics"); - if (element) - { - result = Aircraft->Load(element); - if (!result) - { - cerr << endl << "Aircraft metrics element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - else - { - cerr << endl << "No metrics element was found in the aircraft config file." << endl; - return false; - } - - // Process the mass_balance element. This element is REQUIRED. - element = document->FindElement("mass_balance"); - if (element) - { - result = MassBalance->Load(element); - if (!result) - { - cerr << endl << "Aircraft mass_balance element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - else - { - cerr << endl << "No mass_balance element was found in the aircraft config file." << endl; - return false; - } - - // Process the ground_reactions element. This element is REQUIRED. - element = document->FindElement("ground_reactions"); - if (element) - { - result = GroundReactions->Load(element); - if (!result) - { - cerr << endl << "Aircraft ground_reactions element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - else - { - cerr << endl << "No ground_reactions element was found in the aircraft config file." << endl; - return false; - } - - // Process the external_reactions element. This element is OPTIONAL. - element = document->FindElement("external_reactions"); - if (element) - { - result = ExternalReactions->Load(element); - if (!result) - { - cerr << endl << "Aircraft external_reactions element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - - // Process the buoyant_forces element. This element is OPTIONAL. - element = document->FindElement("buoyant_forces"); - if (element) - { - result = BuoyantForces->Load(element); - if (!result) - { - cerr << endl << "Aircraft buoyant_forces element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - - // Process the propulsion element. This element is OPTIONAL. - element = document->FindElement("propulsion"); - if (element) - { - result = Propulsion->Load(element); - if (!result) - { - cerr << endl << "Aircraft propulsion element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - - // Process the system element[s]. This element is OPTIONAL, and there may be more than one. - element = document->FindElement("system"); - while (element) - { - result = FCS->Load(element, FGFCS::stSystem); - if (!result) - { - cerr << endl << "Aircraft system element has problems in file " << aircraftCfgFileName << endl; - return result; - } - element = document->FindNextElement("system"); - } - - // Process the autopilot element. This element is OPTIONAL. - element = document->FindElement("autopilot"); - if (element) - { - result = FCS->Load(element, FGFCS::stAutoPilot); - if (!result) - { - cerr << endl << "Aircraft autopilot element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - - // Process the flight_control element. This element is OPTIONAL. - element = document->FindElement("flight_control"); - if (element) - { - result = FCS->Load(element, FGFCS::stFCS); - if (!result) - { - cerr << endl << "Aircraft flight_control element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - - // Process the aerodynamics element. This element is OPTIONAL, but almost always expected. - element = document->FindElement("aerodynamics"); - if (element) - { - result = Aerodynamics->Load(element); - if (!result) - { - cerr << endl << "Aircraft aerodynamics element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - else - { - cerr << endl << "No expected aerodynamics element was found in the aircraft config file." << endl; - } - - // Process the input element. This element is OPTIONAL. - element = document->FindElement("input"); - if (element) - { - result = Input->Load(element); - if (!result) - { - cerr << endl << "Aircraft input element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - - // Process the output element[s]. This element is OPTIONAL, and there may be more than one. - unsigned int idx=0; - typedef int (FGOutput::*iOPMF)(void) const; - element = document->FindElement("output"); - while (element) - { - if (debug_lvl > 0) cout << endl << " Output data set: " << idx << " "; - FGOutput* Output = new FGOutput(this); - Output->InitModel(); - Schedule(Output, 1); - result = Output->Load(element); - if (!result) - { - cerr << endl << "Aircraft output element has problems in file " << aircraftCfgFileName << endl; - return result; - } - else - { - Outputs.push_back(Output); - string outputProp = CreateIndexedPropertyName("simulation/output",idx); - instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate); - idx++; - } - element = document->FindNextElement("output"); - } - - // Lastly, process the child element. This element is OPTIONAL - and NOT YET SUPPORTED. - element = document->FindElement("child"); - if (element) - { - result = ReadChild(element); - if (!result) - { - cerr << endl << "Aircraft child element has problems in file " << aircraftCfgFileName << endl; - return result; - } - } - - modelLoaded = true; - - if (debug_lvl > 0) - { - MassBalance->Run(); // Update all mass properties for the report. - MassBalance->GetMassPropertiesReport(); - - cout << endl << fgblue << highint - << "End of vehicle configuration loading." << endl - << "-------------------------------------------------------------------------------" - << reset << endl; - } - - if (IsChild) debug_lvl = saved_debug_lvl; + // Process the autopilot element. This element is OPTIONAL. + element = document->FindElement("autopilot"); + if (element) { + result = FCS->Load(element, FGFCS::stAutoPilot); + if (!result) { + cerr << endl << "Aircraft autopilot element has problems in file " << aircraftCfgFileName << endl; + return result; + } + } + // Process the flight_control element. This element is OPTIONAL. + element = document->FindElement("flight_control"); + if (element) { + result = FCS->Load(element, FGFCS::stFCS); + if (!result) { + cerr << endl << "Aircraft flight_control element has problems in file " << aircraftCfgFileName << endl; + return result; + } } - else - { - cerr << fgred - << " JSBSim failed to open the configuration file: " << aircraftCfgFileName - << fgdef << endl; + + // Process the aerodynamics element. This element is OPTIONAL, but almost always expected. + element = document->FindElement("aerodynamics"); + if (element) { + result = Aerodynamics->Load(element); + if (!result) { + cerr << endl << "Aircraft aerodynamics element has problems in file " << aircraftCfgFileName << endl; + return result; + } + } else { + cerr << endl << "No expected aerodynamics element was found in the aircraft config file." << endl; } + // Process the input element. This element is OPTIONAL. + element = document->FindElement("input"); + if (element) { + result = Input->Load(element); + if (!result) { + cerr << endl << "Aircraft input element has problems in file " << aircraftCfgFileName << endl; + return result; + } + } + + // Process the output element[s]. This element is OPTIONAL, and there may be more than one. + unsigned int idx=0; + typedef int (FGOutput::*iOPMF)(void) const; + element = document->FindElement("output"); + while (element) { + if (debug_lvl > 0) cout << endl << " Output data set: " << idx << " "; + FGOutput* Output = new FGOutput(this); + Output->InitModel(); + Schedule(Output, 1); + result = Output->Load(element); + if (!result) { + cerr << endl << "Aircraft output element has problems in file " << aircraftCfgFileName << endl; + return result; + } else { + Outputs.push_back(Output); + string outputProp = CreateIndexedPropertyName("simulation/output",idx); + instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate); + idx++; + } + element = document->FindNextElement("output"); + } + + // Lastly, process the child element. This element is OPTIONAL - and NOT YET SUPPORTED. + element = document->FindElement("child"); + if (element) { + result = ReadChild(element); + if (!result) { + cerr << endl << "Aircraft child element has problems in file " << aircraftCfgFileName << endl; + return result; + } + } + + modelLoaded = true; + + if (debug_lvl > 0) { + MassBalance->Run(); // Update all mass properties for the report. + MassBalance->GetMassPropertiesReport(); + + cout << endl << fgblue << highint + << "End of vehicle configuration loading." << endl + << "-------------------------------------------------------------------------------" + << reset << endl; + } + + if (IsChild) debug_lvl = saved_debug_lvl; + + } else { + cerr << fgred + << " JSBSim failed to open the configuration file: " << aircraftCfgFileName + << fgdef << endl; + } + + // Late bind previously undefined FCS inputs. + try { + FCS->LateBind(); + } catch (string prop) { + cerr << endl << fgred << " Could not late bind property " << prop + << ". Aborting." << endl; + result = false; + } + + if (result) { struct PropertyCatalogStructure masterPCS; masterPCS.base_string = ""; masterPCS.node = (FGPropertyManager*)Root; - BuildPropertyCatalog(&masterPCS); + } - return result; + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs) { - struct PropertyCatalogStructure* pcsNew = new struct PropertyCatalogStructure; - int node_idx = 0; - - for (int i=0; i<pcs->node->nChildren(); i++) - { - pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName(); - node_idx = pcs->node->getChild(i)->getIndex(); - if (node_idx != 0) - { - pcsNew->base_string = CreateIndexedPropertyName(pcsNew->base_string, node_idx); - } - if (pcs->node->getChild(i)->nChildren() == 0) - { - if (pcsNew->base_string.substr(0,11) == string("/fdm/jsbsim")) - { - pcsNew->base_string = pcsNew->base_string.erase(0,12); - } - PropertyCatalog.push_back(pcsNew->base_string); - } - else - { - pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i); - BuildPropertyCatalog(pcsNew); - } + struct PropertyCatalogStructure* pcsNew = new struct PropertyCatalogStructure; + int node_idx = 0; + + for (int i=0; i<pcs->node->nChildren(); i++) { + pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName(); + node_idx = pcs->node->getChild(i)->getIndex(); + if (node_idx != 0) { + pcsNew->base_string = CreateIndexedPropertyName(pcsNew->base_string, node_idx); + } + if (pcs->node->getChild(i)->nChildren() == 0) { + if (pcsNew->base_string.substr(0,11) == string("/fdm/jsbsim")) { + pcsNew->base_string = pcsNew->base_string.erase(0,12); + } + PropertyCatalog.push_back(pcsNew->base_string); + } else { + pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i); + BuildPropertyCatalog(pcsNew); } - delete pcsNew; + } + delete pcsNew; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGFDMExec::QueryPropertyCatalog(string in) { - string results=""; - for (unsigned i=0; i<PropertyCatalog.size(); i++) - { - if (PropertyCatalog[i].find(in) != string::npos) results += PropertyCatalog[i] + "\n"; - } - if (results.empty()) return "No matches found\n"; - return results; + string results=""; + for (unsigned i=0; i<PropertyCatalog.size(); i++) { + if (PropertyCatalog[i].find(in) != string::npos) results += PropertyCatalog[i] + "\n"; + } + if (results.empty()) return "No matches found\n"; + return results; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFDMExec::PrintPropertyCatalog(void) { - cout << endl; - cout << " " << fgblue << highint << underon << "Property Catalog for " - << modelName << reset << endl << endl; - for (unsigned i=0; i<PropertyCatalog.size(); i++) - { - cout << " " << PropertyCatalog[i] << endl; - } + cout << endl; + cout << " " << fgblue << highint << underon << "Property Catalog for " + << modelName << reset << endl << endl; + for (unsigned i=0; i<PropertyCatalog.size(); i++) { + cout << " " << PropertyCatalog[i] << endl; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFDMExec::ReadFileHeader(Element* el) { - bool result = true; // true for success + bool result = true; // true for success - if (debug_lvl == 0) return result; + if (debug_lvl == 0) return result; - if (IsChild) - { - cout << endl <<highint << fgblue << "Reading child model: " << IdFDM << reset << endl << endl; - } + if (IsChild) { + cout << endl <<highint << fgblue << "Reading child model: " << IdFDM << reset << endl << endl; + } - if (el->FindElement("description")) - cout << " Description: " << el->FindElement("description")->GetDataLine() << endl; - if (el->FindElement("author")) - cout << " Model Author: " << el->FindElement("author")->GetDataLine() << endl; - if (el->FindElement("filecreationdate")) - cout << " Creation Date: " << el->FindElement("filecreationdate")->GetDataLine() << endl; - if (el->FindElement("version")) - cout << " Version: " << el->FindElement("version")->GetDataLine() << endl; + if (el->FindElement("description")) + cout << " Description: " << el->FindElement("description")->GetDataLine() << endl; + if (el->FindElement("author")) + cout << " Model Author: " << el->FindElement("author")->GetDataLine() << endl; + if (el->FindElement("filecreationdate")) + cout << " Creation Date: " << el->FindElement("filecreationdate")->GetDataLine() << endl; + if (el->FindElement("version")) + cout << " Version: " << el->FindElement("version")->GetDataLine() << endl; - return result; + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFDMExec::ReadPrologue(Element* el) // el for ReadPrologue is the document element { - bool result = true; // true for success + bool result = true; // true for success - if (!el) return false; + if (!el) return false; - string AircraftName = el->GetAttributeValue("name"); - Aircraft->SetAircraftName(AircraftName); + string AircraftName = el->GetAttributeValue("name"); + Aircraft->SetAircraftName(AircraftName); - if (debug_lvl & 1) cout << underon << "Reading Aircraft Configuration File" - << underoff << ": " << highint << AircraftName << normint << endl; + if (debug_lvl & 1) cout << underon << "Reading Aircraft Configuration File" + << underoff << ": " << highint << AircraftName << normint << endl; - CFGVersion = el->GetAttributeValue("version"); - Release = el->GetAttributeValue("release"); + CFGVersion = el->GetAttributeValue("version"); + Release = el->GetAttributeValue("release"); - if (debug_lvl & 1) - cout << " Version: " << highint << CFGVersion - << normint << endl; - if (CFGVersion != needed_cfg_version) - { - cerr << endl << fgred << "YOU HAVE AN INCOMPATIBLE CFG FILE FOR THIS AIRCRAFT." - " RESULTS WILL BE UNPREDICTABLE !!" << endl; - cerr << "Current version needed is: " << needed_cfg_version << endl; - cerr << " You have version: " << CFGVersion << endl << fgdef << endl; - return false; - } + if (debug_lvl & 1) + cout << " Version: " << highint << CFGVersion + << normint << endl; + if (CFGVersion != needed_cfg_version) { + cerr << endl << fgred << "YOU HAVE AN INCOMPATIBLE CFG FILE FOR THIS AIRCRAFT." + " RESULTS WILL BE UNPREDICTABLE !!" << endl; + cerr << "Current version needed is: " << needed_cfg_version << endl; + cerr << " You have version: " << CFGVersion << endl << fgdef << endl; + return false; + } - if (Release == "ALPHA" && (debug_lvl & 1)) - { - cout << endl << endl - << highint << "This aircraft model is an " << fgred << Release - << reset << highint << " release!!!" << endl << endl << reset - << "This aircraft model may not even properly load, and probably" - << " will not fly as expected." << endl << endl - << fgred << highint << "Use this model for development purposes ONLY!!!" - << normint << reset << endl << endl; - } - else if (Release == "BETA" && (debug_lvl & 1)) - { - cout << endl << endl - << highint << "This aircraft model is a " << fgred << Release - << reset << highint << " release!!!" << endl << endl << reset - << "This aircraft model probably will not fly as expected." << endl << endl - << fgblue << highint << "Use this model for development purposes ONLY!!!" - << normint << reset << endl << endl; - } - else if (Release == "PRODUCTION" && (debug_lvl & 1)) - { - cout << endl << endl - << highint << "This aircraft model is a " << fgblue << Release - << reset << highint << " release." << endl << endl << reset; - } - else if (debug_lvl & 1) - { - cout << endl << endl - << highint << "This aircraft model is an " << fgred << Release - << reset << highint << " release!!!" << endl << endl << reset - << "This aircraft model may not even properly load, and probably" - << " will not fly as expected." << endl << endl - << fgred << highint << "Use this model for development purposes ONLY!!!" - << normint << reset << endl << endl; - } + if (Release == "ALPHA" && (debug_lvl & 1)) { + cout << endl << endl + << highint << "This aircraft model is an " << fgred << Release + << reset << highint << " release!!!" << endl << endl << reset + << "This aircraft model may not even properly load, and probably" + << " will not fly as expected." << endl << endl + << fgred << highint << "Use this model for development purposes ONLY!!!" + << normint << reset << endl << endl; + } else if (Release == "BETA" && (debug_lvl & 1)) { + cout << endl << endl + << highint << "This aircraft model is a " << fgred << Release + << reset << highint << " release!!!" << endl << endl << reset + << "This aircraft model probably will not fly as expected." << endl << endl + << fgblue << highint << "Use this model for development purposes ONLY!!!" + << normint << reset << endl << endl; + } else if (Release == "PRODUCTION" && (debug_lvl & 1)) { + cout << endl << endl + << highint << "This aircraft model is a " << fgblue << Release + << reset << highint << " release." << endl << endl << reset; + } else if (debug_lvl & 1) { + cout << endl << endl + << highint << "This aircraft model is an " << fgred << Release + << reset << highint << " release!!!" << endl << endl << reset + << "This aircraft model may not even properly load, and probably" + << " will not fly as expected." << endl << endl + << fgred << highint << "Use this model for development purposes ONLY!!!" + << normint << reset << endl << endl; + } - return result; + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFDMExec::ReadChild(Element* el) { - // Add a new childData object to the child FDM list - // Populate that childData element with a new FDMExec object - // Set the IsChild flag for that FDMExec object - // Get the aircraft name - // set debug level to print out no additional data for child objects - // Load the model given the aircraft name - // reset debug level to prior setting - - string token; - - struct childData* child = new childData; - - child->exec = new FGFDMExec(); - child->exec->SetChild(true); - - string childAircraft = el->GetAttributeValue("name"); - string sMated = el->GetAttributeValue("mated"); - if (sMated == "false") child->mated = false; // child objects are mated by default. - string sInternal = el->GetAttributeValue("internal"); - if (sInternal == "true") child->internal = true; // child objects are external by default. - - child->exec->SetAircraftPath( AircraftPath ); - child->exec->SetEnginePath( EnginePath ); - child->exec->SetSystemsPath( SystemsPath ); - child->exec->LoadModel(childAircraft); - - Element* location = el->FindElement("location"); - if (location) - { - child->Loc = location->FindElementTripletConvertTo("IN"); - } - else - { - cerr << endl << highint << fgred << " No location was found for this child object!" << reset << endl; - exit(-1); - } - - Element* orientation = el->FindElement("orient"); - if (orientation) - { - child->Orient = orientation->FindElementTripletConvertTo("RAD"); - } - else if (debug_lvl > 0) - { - cerr << endl << highint << " No orientation was found for this child object! Assuming 0,0,0." << reset << endl; - } + // Add a new childData object to the child FDM list + // Populate that childData element with a new FDMExec object + // Set the IsChild flag for that FDMExec object + // Get the aircraft name + // set debug level to print out no additional data for child objects + // Load the model given the aircraft name + // reset debug level to prior setting + + string token; + + struct childData* child = new childData; + + child->exec = new FGFDMExec(); + child->exec->SetChild(true); + + string childAircraft = el->GetAttributeValue("name"); + string sMated = el->GetAttributeValue("mated"); + if (sMated == "false") child->mated = false; // child objects are mated by default. + string sInternal = el->GetAttributeValue("internal"); + if (sInternal == "true") child->internal = true; // child objects are external by default. + + child->exec->SetAircraftPath( AircraftPath ); + child->exec->SetEnginePath( EnginePath ); + child->exec->SetSystemsPath( SystemsPath ); + child->exec->LoadModel(childAircraft); + + Element* location = el->FindElement("location"); + if (location) { + child->Loc = location->FindElementTripletConvertTo("IN"); + } else { + cerr << endl << highint << fgred << " No location was found for this child object!" << reset << endl; + exit(-1); + } + + Element* orientation = el->FindElement("orient"); + if (orientation) { + child->Orient = orientation->FindElementTripletConvertTo("RAD"); + } else if (debug_lvl > 0) { + cerr << endl << highint << " No orientation was found for this child object! Assuming 0,0,0." << reset << endl; + } - ChildFDMList.push_back(child); + ChildFDMList.push_back(child); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGPropertyManager* FGFDMExec::GetPropertyManager(void) { - return instance; + return instance; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGTrim* FGFDMExec::GetTrim(void) { - delete Trim; - Trim = new FGTrim(this,tNone); - return Trim; + delete Trim; + Trim = new FGTrim(this,tNone); + return Trim; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFDMExec::DisableOutput(void) { - for (unsigned i=0; i<Outputs.size(); i++) - { - Outputs[i]->Disable(); - } + for (unsigned i=0; i<Outputs.size(); i++) { + Outputs[i]->Disable(); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFDMExec::EnableOutput(void) { - for (unsigned i=0; i<Outputs.size(); i++) - { - Outputs[i]->Enable(); - } + for (unsigned i=0; i<Outputs.size(); i++) { + Outputs[i]->Enable(); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFDMExec::SetOutputDirectives(string fname) { - bool result; - - FGOutput* Output = new FGOutput(this); - Output->SetDirectivesFile(RootDir + fname); - Output->InitModel(); - Schedule(Output, 1); - result = Output->Load(0); - - if (result) - { - Outputs.push_back(Output); - typedef int (FGOutput::*iOPMF)(void) const; - string outputProp = CreateIndexedPropertyName("simulation/output",Outputs.size()-1); - instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate); - } + bool result; + + FGOutput* Output = new FGOutput(this); + Output->SetDirectivesFile(RootDir + fname); + Output->InitModel(); + Schedule(Output, 1); + result = Output->Load(0); + + if (result) { + Outputs.push_back(Output); + typedef int (FGOutput::*iOPMF)(void) const; + string outputProp = CreateIndexedPropertyName("simulation/output",Outputs.size()-1); + instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate); + } - return result; + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFDMExec::DoTrim(int mode) { - double saved_time; + double saved_time; - if (Constructing) return; + if (Constructing) return; - if (mode < 0 || mode > JSBSim::tNone) - { - cerr << endl << "Illegal trimming mode!" << endl << endl; - return; - } - saved_time = sim_time; - FGTrim trim(this, (JSBSim::TrimMode)mode); - if ( !trim.DoTrim() ) cerr << endl << "Trim Failed" << endl << endl; - trim.Report(); - sim_time = saved_time; + if (mode < 0 || mode > JSBSim::tNone) { + cerr << endl << "Illegal trimming mode!" << endl << endl; + return; + } + saved_time = sim_time; + FGTrim trim(this, (JSBSim::TrimMode)mode); + if ( !trim.DoTrim() ) cerr << endl << "Trim Failed" << endl << endl; + trim.Report(); + sim_time = saved_time; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1076,29 +997,28 @@ void FGFDMExec::DoTrimAnalysis(int mode) void FGFDMExec::UseAtmosphereMSIS(void) { - FGAtmosphere *oldAtmosphere = Atmosphere; - Atmosphere = new MSIS(this); - if (!Atmosphere->InitModel()) - { - cerr << fgred << "MSIS Atmosphere model init failed" << fgdef << endl; - Error+=1; - } - delete oldAtmosphere; + FGAtmosphere *oldAtmosphere = Atmosphere; + Atmosphere = new MSIS(this); + if (!Atmosphere->InitModel()) { + cerr << fgred << "MSIS Atmosphere model init failed" << fgdef << endl; + Error+=1; + } + delete oldAtmosphere; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFDMExec::UseAtmosphereMars(void) { - /* - FGAtmosphere *oldAtmosphere = Atmosphere; - Atmosphere = new FGMars(this); - if (!Atmosphere->InitModel()) { - cerr << fgred << "Mars Atmosphere model init failed" << fgdef << endl; - Error+=1; - } - delete oldAtmosphere; - */ +/* + FGAtmosphere *oldAtmosphere = Atmosphere; + Atmosphere = new FGMars(this); + if (!Atmosphere->InitModel()) { + cerr << fgred << "Mars Atmosphere model init failed" << fgdef << endl; + Error+=1; + } + delete oldAtmosphere; +*/ } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1122,49 +1042,38 @@ void FGFDMExec::UseAtmosphereMars(void) void FGFDMExec::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1 && IdFDM == 0) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << "\n\n " << highint << underon << "JSBSim Flight Dynamics Model v" - << JSBSim_version << underoff << normint << endl; - cout << halfint << " [JSBSim-ML v" << needed_cfg_version << "]\n\n"; - cout << normint << "JSBSim startup beginning ...\n\n"; - } - else if (from == 3) - { - cout << "\n\nJSBSim startup complete\n\n"; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGFDMExec" << endl; - if (from == 1) cout << "Destroyed: FGFDMExec" << endl; + if (debug_lvl <= 0) return; + + if (debug_lvl & 1 && IdFDM == 0) { // Standard console startup message output + if (from == 0) { // Constructor + cout << "\n\n " << highint << underon << "JSBSim Flight Dynamics Model v" + << JSBSim_version << underoff << normint << endl; + cout << halfint << " [JSBSim-ML v" << needed_cfg_version << "]\n\n"; + cout << normint << "JSBSim startup beginning ...\n\n"; + } else if (from == 3) { + cout << "\n\nJSBSim startup complete\n\n"; } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - if (from == 2) - { - cout << "================== Frame: " << Frame << " Time: " - << sim_time << " dt: " << dT << endl; - } - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGFDMExec" << endl; + if (from == 1) cout << "Destroyed: FGFDMExec" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + if (from == 2) { + cout << "================== Frame: " << Frame << " Time: " + << sim_time << " dt: " << dT << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/FGFDMExec.h b/src/FGFDMExec.h index b7cbbf6f43951dfcd74a326e0c1e7d4dab19a641..8c91cb2c9ce09430404a0103387788ccd005532b 100644 --- a/src/FGFDMExec.h +++ b/src/FGFDMExec.h @@ -66,8 +66,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGScript; class FGTrim; @@ -179,556 +178,401 @@ CLASS DECLARATION class FGFDMExec : public FGJSBBase, public FGXMLFileRead { - struct childData - { - FGFDMExec* exec; - string info; - FGColumnVector3 Loc; - FGColumnVector3 Orient; - bool mated; - bool internal; - - childData(void) - { - info = ""; - Loc = FGColumnVector3(0,0,0); - Orient = FGColumnVector3(0,0,0); - mated = true; - internal = false; - } - - void Run(void) - { - exec->Run(); - } - void AssignState(FGPropagate* source_prop) - { - exec->GetPropagate()->SetVState(source_prop->GetVState()); - } - - ~childData(void) - { - delete exec; - } - }; - -public: + struct childData { + FGFDMExec* exec; + string info; + FGColumnVector3 Loc; + FGColumnVector3 Orient; + bool mated; + bool internal; - /// Default constructor - FGFDMExec(FGPropertyManager* root = 0); - - /// Default destructor - ~FGFDMExec(); - - /** This routine places a model into the runlist at the specified rate. The - "rate" is not really a clock rate. It represents how many calls to the - FGFDMExec::Run() method must be made before the model is executed. A - value of 1 means that the model will be executed for each call to the - exec's Run() method. A value of 5 means that the model will only be - executed every 5th call to the exec's Run() method. Use of a rate other than - one is at this time not recommended. - @param model A pointer to the model being scheduled. - @param rate The rate at which to execute the model as described above. - @return Currently returns 0 always. */ - void Schedule(FGModel* model, int rate); - - /** This function executes each scheduled model in succession. - @return true if successful, false if sim should be ended */ - bool Run(void); - - /** Initializes the sim from the initial condition object and executes - each scheduled model without integrating i.e. dt=0. - @return true if successful */ - bool RunIC(void); - - /** Sets the ground callback pointer. - @param gc A pointer to a ground callback object. */ - void SetGroundCallback(FGGroundCallback* gc); - - /** Loads an aircraft model. - @param AircraftPath path to the aircraft/ directory. For instance: - "aircraft". Under aircraft, then, would be directories for various - modeled aircraft such as C172/, x15/, etc. - @param EnginePath path to the directory under which engine config - files are kept, for instance "engine" - @param SystemsPath path to the directory under which systems config - files are kept, for instance "systems" - @param model the name of the aircraft model itself. This file will - be looked for in the directory specified in the AircraftPath variable, - and in turn under the directory with the same name as the model. For - instance: "aircraft/x15/x15.xml" - @param addModelToPath set to true to add the model name to the - AircraftPath, defaults to true - @return true if successful */ - bool LoadModel(string AircraftPath, string EnginePath, string SystemsPath, - string model, bool addModelToPath = true); - - /** Loads an aircraft model. The paths to the aircraft and engine - config file directories must be set prior to calling this. See - below. - @param model the name of the aircraft model itself. This file will - be looked for in the directory specified in the AircraftPath variable, - and in turn under the directory with the same name as the model. For - instance: "aircraft/x15/x15.xml" - @param addModelToPath set to true to add the model name to the - AircraftPath, defaults to true - @return true if successful*/ - bool LoadModel(string model, bool addModelToPath = true); - - /** Loads a script - @param Script the full path name and file name for the script to be loaded. - @return true if successfully loadsd; false otherwise. */ - bool LoadScript(string Script, double deltaT); - - /** Sets the path to the engine config file directories. - @param path path to the directory under which engine config - files are kept, for instance "engine" */ - bool SetEnginePath(string path) - { - EnginePath = RootDir + path; - return true; + childData(void) { + info = ""; + Loc = FGColumnVector3(0,0,0); + Orient = FGColumnVector3(0,0,0); + mated = true; + internal = false; } - - /** Sets the path to the aircraft config file directories. - @param path path to the aircraft directory. For instance: - "aircraft". Under aircraft, then, would be directories for various - modeled aircraft such as C172/, x15/, etc. */ - bool SetAircraftPath(string path) - { - AircraftPath = RootDir + path; - return true; + + void Run(void) {exec->Run();} + void AssignState(FGPropagate* source_prop) { + exec->GetPropagate()->SetVState(source_prop->GetVState()); } - /** Sets the path to the systems config file directories. - @param path path to the directory under which systems config - files are kept, for instance "systems" */ - bool SetSystemsPath(string path) - { - SystemsPath = RootDir + path; - return true; + ~childData(void) { + delete exec; } + }; - /// @name Top-level executive State and Model retrieval mechanism - //@{ - /// Returns the FGAtmosphere pointer. - inline FGAtmosphere* GetAtmosphere(void) - { - return Atmosphere; - } - /// Returns the FGFCS pointer. - inline FGFCS* GetFCS(void) - { - return FCS; - } - /// Returns the FGPropulsion pointer. - inline FGPropulsion* GetPropulsion(void) - { - return Propulsion; - } - /// Returns the FGAircraft pointer. - inline FGMassBalance* GetMassBalance(void) - { - return MassBalance; - } - /// Returns the FGAerodynamics pointer - inline FGAerodynamics* GetAerodynamics(void) - { - return Aerodynamics; - } - /// Returns the FGInertial pointer. - inline FGInertial* GetInertial(void) - { - return Inertial; - } - /// Returns the FGGroundReactions pointer. - inline FGGroundReactions* GetGroundReactions(void) - { - return GroundReactions; - } - /// Returns the FGExternalReactions pointer. - inline FGExternalReactions* GetExternalReactions(void) - { - return ExternalReactions; - } - /// Returns the FGBuoyantForces pointer. - inline FGBuoyantForces* GetBuoyantForces(void) - { - return BuoyantForces; - } - /// Returns the FGAircraft pointer. - inline FGAircraft* GetAircraft(void) - { - return Aircraft; - } - /// Returns the FGPropagate pointer. - inline FGPropagate* GetPropagate(void) - { - return Propagate; - } - /// Returns the FGAuxiliary pointer. - inline FGAuxiliary* GetAuxiliary(void) - { - return Auxiliary; - } - /// Returns the FGInput pointer. - inline FGInput* GetInput(void) - { - return Input; - } - /// Returns the FGGroundCallback pointer. - inline FGGroundCallback* GetGroundCallback(void) - { - return GroundCallback; - } - /// Retrieves the script object - inline FGScript* GetScript(void) - { - return Script; - } - // Returns a pointer to the FGInitialCondition object - inline FGInitialCondition* GetIC(void) - { - return IC; - } - // Returns a pointer to the FGTrim object - FGTrim* GetTrim(void); - //@} - - /// Retrieves the engine path. - inline string GetEnginePath(void) - { - return EnginePath; - } - /// Retrieves the aircraft path. - inline string GetAircraftPath(void) - { - return AircraftPath; - } - /// Retrieves the systems path. - inline string GetSystemsPath(void) - { - return SystemsPath; - } - /// Retrieves the full aircraft path name. - inline string GetFullAircraftPath(void) - { - return FullAircraftPath; - } - - /** Retrieves the value of a property. - @param property the name of the property - @result the value of the specified property */ - inline double GetPropertyValue(string property) - { - return instance->GetDouble(property); - } - - /** Sets a property value. - @param property the property to be set - @param value the value to set the property to */ - inline void SetPropertyValue(string property, double value) - { - instance->SetDouble(property, value); - } - - /// Returns the model name. - string GetModelName(void) - { - return modelName; - } - /* - /// Returns the current time. - double GetSimTime(void); +public: - /// Returns the current frame time (delta T). - double GetDeltaT(void); + /// Default constructor + FGFDMExec(FGPropertyManager* root = 0); + + /// Default destructor + ~FGFDMExec(); + + /** This routine places a model into the runlist at the specified rate. The + "rate" is not really a clock rate. It represents how many calls to the + FGFDMExec::Run() method must be made before the model is executed. A + value of 1 means that the model will be executed for each call to the + exec's Run() method. A value of 5 means that the model will only be + executed every 5th call to the exec's Run() method. Use of a rate other than + one is at this time not recommended. + @param model A pointer to the model being scheduled. + @param rate The rate at which to execute the model as described above. + @return Currently returns 0 always. */ + void Schedule(FGModel* model, int rate); + + /** This function executes each scheduled model in succession. + @return true if successful, false if sim should be ended */ + bool Run(void); + + /** Initializes the sim from the initial condition object and executes + each scheduled model without integrating i.e. dt=0. + @return true if successful */ + bool RunIC(void); + + /** Sets the ground callback pointer. + @param gc A pointer to a ground callback object. */ + void SetGroundCallback(FGGroundCallback* gc); + + /** Loads an aircraft model. + @param AircraftPath path to the aircraft/ directory. For instance: + "aircraft". Under aircraft, then, would be directories for various + modeled aircraft such as C172/, x15/, etc. + @param EnginePath path to the directory under which engine config + files are kept, for instance "engine" + @param SystemsPath path to the directory under which systems config + files are kept, for instance "systems" + @param model the name of the aircraft model itself. This file will + be looked for in the directory specified in the AircraftPath variable, + and in turn under the directory with the same name as the model. For + instance: "aircraft/x15/x15.xml" + @param addModelToPath set to true to add the model name to the + AircraftPath, defaults to true + @return true if successful */ + bool LoadModel(string AircraftPath, string EnginePath, string SystemsPath, + string model, bool addModelToPath = true); + + /** Loads an aircraft model. The paths to the aircraft and engine + config file directories must be set prior to calling this. See + below. + @param model the name of the aircraft model itself. This file will + be looked for in the directory specified in the AircraftPath variable, + and in turn under the directory with the same name as the model. For + instance: "aircraft/x15/x15.xml" + @param addModelToPath set to true to add the model name to the + AircraftPath, defaults to true + @return true if successful*/ + bool LoadModel(string model, bool addModelToPath = true); + + /** Loads a script + @param Script the full path name and file name for the script to be loaded. + @return true if successfully loadsd; false otherwise. */ + bool LoadScript(string Script, double deltaT); + + /** Sets the path to the engine config file directories. + @param path path to the directory under which engine config + files are kept, for instance "engine" */ + bool SetEnginePath(string path) { EnginePath = RootDir + path; return true; } + + /** Sets the path to the aircraft config file directories. + @param path path to the aircraft directory. For instance: + "aircraft". Under aircraft, then, would be directories for various + modeled aircraft such as C172/, x15/, etc. */ + bool SetAircraftPath(string path) { AircraftPath = RootDir + path; return true; } + + /** Sets the path to the systems config file directories. + @param path path to the directory under which systems config + files are kept, for instance "systems" */ + bool SetSystemsPath(string path) { SystemsPath = RootDir + path; return true; } + + /// @name Top-level executive State and Model retrieval mechanism + //@{ + /// Returns the FGAtmosphere pointer. + inline FGAtmosphere* GetAtmosphere(void) {return Atmosphere;} + /// Returns the FGFCS pointer. + inline FGFCS* GetFCS(void) {return FCS;} + /// Returns the FGPropulsion pointer. + inline FGPropulsion* GetPropulsion(void) {return Propulsion;} + /// Returns the FGAircraft pointer. + inline FGMassBalance* GetMassBalance(void) {return MassBalance;} + /// Returns the FGAerodynamics pointer + inline FGAerodynamics* GetAerodynamics(void){return Aerodynamics;} + /// Returns the FGInertial pointer. + inline FGInertial* GetInertial(void) {return Inertial;} + /// Returns the FGGroundReactions pointer. + inline FGGroundReactions* GetGroundReactions(void) {return GroundReactions;} + /// Returns the FGExternalReactions pointer. + inline FGExternalReactions* GetExternalReactions(void) {return ExternalReactions;} + /// Returns the FGBuoyantForces pointer. + inline FGBuoyantForces* GetBuoyantForces(void) {return BuoyantForces;} + /// Returns the FGAircraft pointer. + inline FGAircraft* GetAircraft(void) {return Aircraft;} + /// Returns the FGPropagate pointer. + inline FGPropagate* GetPropagate(void) {return Propagate;} + /// Returns the FGAuxiliary pointer. + inline FGAuxiliary* GetAuxiliary(void) {return Auxiliary;} + /// Returns the FGInput pointer. + inline FGInput* GetInput(void) {return Input;} + /// Returns the FGGroundCallback pointer. + inline FGGroundCallback* GetGroundCallback(void) {return GroundCallback;} + /// Retrieves the script object + inline FGScript* GetScript(void) {return Script;} + // Returns a pointer to the FGInitialCondition object + inline FGInitialCondition* GetIC(void) {return IC;} + // Returns a pointer to the FGTrim object + FGTrim* GetTrim(void); + //@} + + /// Retrieves the engine path. + inline string GetEnginePath(void) {return EnginePath;} + /// Retrieves the aircraft path. + inline string GetAircraftPath(void) {return AircraftPath;} + /// Retrieves the systems path. + inline string GetSystemsPath(void) {return SystemsPath;} + /// Retrieves the full aircraft path name. + inline string GetFullAircraftPath(void) {return FullAircraftPath;} + + /** Retrieves the value of a property. + @param property the name of the property + @result the value of the specified property */ + inline double GetPropertyValue(string property) {return instance->GetDouble(property);} + + /** Sets a property value. + @param property the property to be set + @param value the value to set the property to */ + inline void SetPropertyValue(string property, double value) { + instance->SetDouble(property, value); + } + + /// Returns the model name. + string GetModelName(void) { return modelName; } +/* + /// Returns the current time. + double GetSimTime(void); + + /// Returns the current frame time (delta T). + double GetDeltaT(void); +*/ + /// Returns a pointer to the property manager object. + FGPropertyManager* GetPropertyManager(void); + /// Returns a vector of strings representing the names of all loaded models (future) + vector <string> EnumerateFDMs(void); + /// Gets the number of child FDMs. + int GetFDMCount(void) {return (int)ChildFDMList.size();} + /// Gets a particular child FDM. + childData* GetChildFDM(int i) {return ChildFDMList[i];} + /// Marks this instance of the Exec object as a "child" object. + void SetChild(bool ch) {IsChild = ch;} + + /** Sets the output (logging) mechanism for this run. + Calling this function passes the name of an output directives file to + the FGOutput object associated with this run. The call to this function + should be made prior to loading an aircraft model. This call results in an + FGOutput object being built as the first Output object in the FDMExec-managed + list of Output objects that may be created for an aircraft model. If this call + is made after an aircraft model is loaded, there is no effect. Any Output + objects added by the aircraft model itself (in an <output> element) will be + added after this one. Care should be taken not to refer to the same file + name. + An output directives file contains an <output> </output> element, within + which should be specified the parameters or parameter groups that should + be logged. + @param fname the filename of an output directives file. */ - /// Returns a pointer to the property manager object. - FGPropertyManager* GetPropertyManager(void); - /// Returns a vector of strings representing the names of all loaded models (future) - vector <string> EnumerateFDMs(void); - /// Gets the number of child FDMs. - int GetFDMCount(void) - { - return (int)ChildFDMList.size(); - } - /// Gets a particular child FDM. - childData* GetChildFDM(int i) - { - return ChildFDMList[i]; - } - /// Marks this instance of the Exec object as a "child" object. - void SetChild(bool ch) - { - IsChild = ch; - } - - /** Sets the output (logging) mechanism for this run. - Calling this function passes the name of an output directives file to - the FGOutput object associated with this run. The call to this function - should be made prior to loading an aircraft model. This call results in an - FGOutput object being built as the first Output object in the FDMExec-managed - list of Output objects that may be created for an aircraft model. If this call - is made after an aircraft model is loaded, there is no effect. Any Output - objects added by the aircraft model itself (in an <output> element) will be - added after this one. Care should be taken not to refer to the same file - name. - An output directives file contains an <output> </output> element, within - which should be specified the parameters or parameter groups that should - be logged. - @param fname the filename of an output directives file. - */ - bool SetOutputDirectives(string fname); - - /** Sets (or overrides) the output filename - @param fname the name of the file to output data to - @return true if successful, false if there is no output specified for the flight model */ - bool SetOutputFileName(string fname) - { - if (Outputs.size() > 0) Outputs[0]->SetOutputFileName(fname); - else return false; - return true; - } - - /** Retrieves the current output filename. - @return the name of the output file for the first output specified by the flight model. - If none is specified, the empty string is returned. */ - string GetOutputFileName(void) - { - if (Outputs.size() > 0) return Outputs[0]->GetOutputFileName(); - else return string(""); - } - - /** Executes trimming in the selected mode. - * @param mode Specifies how to trim: - * - tLongitudinal=0 - * - tFull - * - tGround - * - tPullup - * - tCustom - * - tTurn - * - tNone */ - void DoTrim(int mode); + bool SetOutputDirectives(string fname); + + /** Sets (or overrides) the output filename + @param fname the name of the file to output data to + @return true if successful, false if there is no output specified for the flight model */ + bool SetOutputFileName(string fname) { + if (Outputs.size() > 0) Outputs[0]->SetOutputFileName(fname); + else return false; + return true; + } + + /** Retrieves the current output filename. + @return the name of the output file for the first output specified by the flight model. + If none is specified, the empty string is returned. */ + string GetOutputFileName(void) { + if (Outputs.size() > 0) return Outputs[0]->GetOutputFileName(); + else return string(""); + } + + /** Executes trimming in the selected mode. + * @param mode Specifies how to trim: + * - tLongitudinal=0 + * - tFull + * - tGround + * - tPullup + * - tCustom + * - tTurn + * - tNone */ + void DoTrim(int mode); // void DoTrimAnalysis(int mode); - /// Disables data logging to all outputs. - void DisableOutput(void); - /// Enables data logging to all outputs. - void EnableOutput(void); - /// Pauses execution by preventing time from incrementing. - void Hold(void) - { - holding = true; - } - /// Resumes execution from a "Hold". - void Resume(void) - { - holding = false; - } - /// Returns true if the simulation is Holding (i.e. simulation time is not moving). - bool Holding(void) - { - return holding; - } - /// Resets the initial conditions object and prepares the simulation to run again. - void ResetToInitialConditions(void); - /// Sets the debug level. - void SetDebugLevel(int level) - { - debug_lvl = level; - } - - struct PropertyCatalogStructure - { - /// Name of the property. - string base_string; - /// The node for the property. - FGPropertyManager *node; - }; - - /** Builds a catalog of properties. - * This function descends the property tree and creates a list (an STL vector) - * containing the name and node for all properties. - * @param pcs The "root" property catalog structure pointer. */ - void BuildPropertyCatalog(struct PropertyCatalogStructure* pcs); - - /** Retrieves property or properties matching the supplied string. - * A string is returned that contains a carriage return delimited list of all - * strings in the property catalog that matches the supplied check string. - * @param check The string to search for in the property catalog. - * @return the carriage-return-delimited string containing all matching strings - * in the catalog. */ - string QueryPropertyCatalog(string check); - - // Print the contents of the property catalog for the loaded aircraft. - void PrintPropertyCatalog(void); - - vector<string>& GetPropertyCatalog(void) - { - return PropertyCatalog; - } - - /// Use the MSIS atmosphere model. - void UseAtmosphereMSIS(void); - - /// Use the Mars atmosphere model. (Not operative yet.) - void UseAtmosphereMars(void); - - void SetTrimStatus(bool status) - { - trim_status = status; - } - bool GetTrimStatus(void) const - { - return trim_status; - } - void SetTrimMode(int mode) - { - ta_mode = mode; - } - int GetTrimMode(void) const - { - return ta_mode; - } - - /// Returns the cumulative simulation time in seconds. - double GetSimTime(void) const - { - return sim_time; - } - - /// Returns the simulation delta T. - double GetDeltaT(void) - { - return dT; - } - - /// Suspends the simulation and sets the delta T to zero. - void SuspendIntegration(void) - { - saved_dT = dT; - dT = 0.0; - } - - /// Resumes the simulation by resetting delta T to the correct value. - void ResumeIntegration(void) - { - dT = saved_dT; - } - - /** Returns the simulation suspension state. - @return true if suspended, false if executing */ - bool IntegrationSuspended(void) - { - return dT == 0.0; - } - - /** Sets the current sim time. - @param cur_time the current time - @return the current simulation time. */ - double Setsim_time(double cur_time) - { - sim_time = cur_time; - return sim_time; - } - - /** Sets the integration time step for the simulation executive. - @param delta_t the time step in seconds. */ - void Setdt(double delta_t) - { - dT = delta_t; - } - - /** Sets the root directory where JSBSim starts looking for its system directories. - @param rootDir the string containing the root directory. */ - void SetRootDir(string rootDir) - { - RootDir = rootDir; - } - - /** Retrieves teh Root Directory. - @return the string representing the root (base) JSBSim directory. */ - string GetRootDir(void) const - { - return RootDir; - } - - /** Increments the simulation time. - @return the new simulation time. */ - double IncrTime(void) - { - sim_time += dT; - return sim_time; - } - - /** Retrieves the current debug level setting. */ - int GetDebugLevel(void) const - { - return debug_lvl; - }; + /// Disables data logging to all outputs. + void DisableOutput(void); + /// Enables data logging to all outputs. + void EnableOutput(void); + /// Pauses execution by preventing time from incrementing. + void Hold(void) {holding = true;} + /// Resumes execution from a "Hold". + void Resume(void) {holding = false;} + /// Returns true if the simulation is Holding (i.e. simulation time is not moving). + bool Holding(void) {return holding;} + /// Resets the initial conditions object and prepares the simulation to run again. + void ResetToInitialConditions(void); + /// Sets the debug level. + void SetDebugLevel(int level) {debug_lvl = level;} + + struct PropertyCatalogStructure { + /// Name of the property. + string base_string; + /// The node for the property. + FGPropertyManager *node; + }; + + /** Builds a catalog of properties. + * This function descends the property tree and creates a list (an STL vector) + * containing the name and node for all properties. + * @param pcs The "root" property catalog structure pointer. */ + void BuildPropertyCatalog(struct PropertyCatalogStructure* pcs); + + /** Retrieves property or properties matching the supplied string. + * A string is returned that contains a carriage return delimited list of all + * strings in the property catalog that matches the supplied check string. + * @param check The string to search for in the property catalog. + * @return the carriage-return-delimited string containing all matching strings + * in the catalog. */ + string QueryPropertyCatalog(string check); + + // Print the contents of the property catalog for the loaded aircraft. + void PrintPropertyCatalog(void); + + vector<string>& GetPropertyCatalog(void) {return PropertyCatalog;} + + /// Use the MSIS atmosphere model. + void UseAtmosphereMSIS(void); + + /// Use the Mars atmosphere model. (Not operative yet.) + void UseAtmosphereMars(void); + + void SetTrimStatus(bool status){ trim_status = status; } + bool GetTrimStatus(void) const { return trim_status; } + void SetTrimMode(int mode){ ta_mode = mode; } + int GetTrimMode(void) const { return ta_mode; } + + /// Returns the cumulative simulation time in seconds. + double GetSimTime(void) const { return sim_time; } + + /// Returns the simulation delta T. + double GetDeltaT(void) {return dT;} + + /// Suspends the simulation and sets the delta T to zero. + void SuspendIntegration(void) {saved_dT = dT; dT = 0.0;} + + /// Resumes the simulation by resetting delta T to the correct value. + void ResumeIntegration(void) {dT = saved_dT;} + + /** Returns the simulation suspension state. + @return true if suspended, false if executing */ + bool IntegrationSuspended(void) {return dT == 0.0;} + + /** Sets the current sim time. + @param cur_time the current time + @return the current simulation time. */ + double Setsim_time(double cur_time) { + sim_time = cur_time; + return sim_time; + } + + /** Sets the integration time step for the simulation executive. + @param delta_t the time step in seconds. */ + void Setdt(double delta_t) { dT = delta_t; } + + /** Sets the root directory where JSBSim starts looking for its system directories. + @param rootDir the string containing the root directory. */ + void SetRootDir(string rootDir) {RootDir = rootDir;} + + /** Retrieves teh Root Directory. + @return the string representing the root (base) JSBSim directory. */ + string GetRootDir(void) const {return RootDir;} + + /** Increments the simulation time. + @return the new simulation time. */ + double IncrTime(void) { + sim_time += dT; + return sim_time; + } + + /** Retrieves the current debug level setting. */ + int GetDebugLevel(void) const {return debug_lvl;}; private: - static unsigned int FDMctr; - int Error; - unsigned int Frame; - unsigned int IdFDM; - unsigned short Terminate; - double dT; - double saved_dT; - double sim_time; - bool holding; - bool Constructing; - bool modelLoaded; - bool IsChild; - string modelName; - string AircraftPath; - string FullAircraftPath; - string EnginePath; - string SystemsPath; - string CFGVersion; - string Release; - string RootDir; - - bool trim_status; - int ta_mode; - - static FGPropertyManager *master; - - FGGroundCallback* GroundCallback; - FGAtmosphere* Atmosphere; - FGFCS* FCS; - FGPropulsion* Propulsion; - FGMassBalance* MassBalance; - FGAerodynamics* Aerodynamics; - FGInertial* Inertial; - FGGroundReactions* GroundReactions; - FGExternalReactions* ExternalReactions; - FGBuoyantForces* BuoyantForces; - FGAircraft* Aircraft; - FGPropagate* Propagate; - FGAuxiliary* Auxiliary; - FGInput* Input; - FGScript* Script; - FGInitialCondition* IC; - FGTrim* Trim; - - FGPropertyManager* Root; - FGPropertyManager* instance; - - vector <string> PropertyCatalog; - vector <FGOutput*> Outputs; - vector <childData*> ChildFDMList; - vector <FGModel*> Models; - - bool ReadFileHeader(Element*); - bool ReadChild(Element*); - bool ReadPrologue(Element*); - void ResetToInitialConditions(int mode); - bool Allocate(void); - bool DeAllocate(void); - void Initialize(FGInitialCondition *FGIC); - - void Debug(int from); + static unsigned int FDMctr; + int Error; + unsigned int Frame; + unsigned int IdFDM; + unsigned short Terminate; + double dT; + double saved_dT; + double sim_time; + bool holding; + bool Constructing; + bool modelLoaded; + bool IsChild; + string modelName; + string AircraftPath; + string FullAircraftPath; + string EnginePath; + string SystemsPath; + string CFGVersion; + string Release; + string RootDir; + + bool trim_status; + int ta_mode; + + static FGPropertyManager *master; + + FGGroundCallback* GroundCallback; + FGAtmosphere* Atmosphere; + FGFCS* FCS; + FGPropulsion* Propulsion; + FGMassBalance* MassBalance; + FGAerodynamics* Aerodynamics; + FGInertial* Inertial; + FGGroundReactions* GroundReactions; + FGExternalReactions* ExternalReactions; + FGBuoyantForces* BuoyantForces; + FGAircraft* Aircraft; + FGPropagate* Propagate; + FGAuxiliary* Auxiliary; + FGInput* Input; + FGScript* Script; + FGInitialCondition* IC; + FGTrim* Trim; + + FGPropertyManager* Root; + FGPropertyManager* instance; + + vector <string> PropertyCatalog; + vector <FGOutput*> Outputs; + vector <childData*> ChildFDMList; + vector <FGModel*> Models; + + bool ReadFileHeader(Element*); + bool ReadChild(Element*); + bool ReadPrologue(Element*); + void ResetToInitialConditions(int mode); + bool Allocate(void); + bool DeAllocate(void); + void Initialize(FGInitialCondition *FGIC); + + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FGJSBBase.cpp b/src/FGJSBBase.cpp index 99d7972104336688646077bc634acd2ed8b5a9c0..a361a37d256732250ebef9803ba2fd9c8e5b23f1 100644 --- a/src/FGJSBBase.cpp +++ b/src/FGJSBBase.cpp @@ -42,10 +42,7 @@ INCLUDES #include <sstream> #include <cstdlib> -namespace JSBSim -{ - -using namespace std; +namespace JSBSim { static const char *IdSrc = "$Id: FGJSBBase.cpp,v 1.29 2010/03/18 13:19:21 jberndt Exp $"; static const char *IdHdr = ID_JSBBASE; @@ -55,29 +52,29 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _MSC_VER -char FGJSBBase::highint[5] = {27, '[', '1', 'm', '\0' }; -char FGJSBBase::halfint[5] = {27, '[', '2', 'm', '\0' }; -char FGJSBBase::normint[6] = {27, '[', '2', '2', 'm', '\0' }; -char FGJSBBase::reset[5] = {27, '[', '0', 'm', '\0' }; -char FGJSBBase::underon[5] = {27, '[', '4', 'm', '\0' }; -char FGJSBBase::underoff[6] = {27, '[', '2', '4', 'm', '\0' }; -char FGJSBBase::fgblue[6] = {27, '[', '3', '4', 'm', '\0' }; -char FGJSBBase::fgcyan[6] = {27, '[', '3', '6', 'm', '\0' }; -char FGJSBBase::fgred[6] = {27, '[', '3', '1', 'm', '\0' }; -char FGJSBBase::fggreen[6] = {27, '[', '3', '2', 'm', '\0' }; -char FGJSBBase::fgdef[6] = {27, '[', '3', '9', 'm', '\0' }; + char FGJSBBase::highint[5] = {27, '[', '1', 'm', '\0' }; + char FGJSBBase::halfint[5] = {27, '[', '2', 'm', '\0' }; + char FGJSBBase::normint[6] = {27, '[', '2', '2', 'm', '\0' }; + char FGJSBBase::reset[5] = {27, '[', '0', 'm', '\0' }; + char FGJSBBase::underon[5] = {27, '[', '4', 'm', '\0' }; + char FGJSBBase::underoff[6] = {27, '[', '2', '4', 'm', '\0' }; + char FGJSBBase::fgblue[6] = {27, '[', '3', '4', 'm', '\0' }; + char FGJSBBase::fgcyan[6] = {27, '[', '3', '6', 'm', '\0' }; + char FGJSBBase::fgred[6] = {27, '[', '3', '1', 'm', '\0' }; + char FGJSBBase::fggreen[6] = {27, '[', '3', '2', 'm', '\0' }; + char FGJSBBase::fgdef[6] = {27, '[', '3', '9', 'm', '\0' }; #else -char FGJSBBase::highint[5] = {'\0' }; -char FGJSBBase::halfint[5] = {'\0' }; -char FGJSBBase::normint[6] = {'\0' }; -char FGJSBBase::reset[5] = {'\0' }; -char FGJSBBase::underon[5] = {'\0' }; -char FGJSBBase::underoff[6] = {'\0' }; -char FGJSBBase::fgblue[6] = {'\0' }; -char FGJSBBase::fgcyan[6] = {'\0' }; -char FGJSBBase::fgred[6] = {'\0' }; -char FGJSBBase::fggreen[6] = {'\0' }; -char FGJSBBase::fgdef[6] = {'\0' }; + char FGJSBBase::highint[5] = {'\0' }; + char FGJSBBase::halfint[5] = {'\0' }; + char FGJSBBase::normint[6] = {'\0' }; + char FGJSBBase::reset[5] = {'\0' }; + char FGJSBBase::underon[5] = {'\0' }; + char FGJSBBase::underoff[6] = {'\0' }; + char FGJSBBase::fgblue[6] = {'\0' }; + char FGJSBBase::fgcyan[6] = {'\0' }; + char FGJSBBase::fgred[6] = {'\0' }; + char FGJSBBase::fggreen[6] = {'\0' }; + char FGJSBBase::fgdef[6] = {'\0' }; #endif const double FGJSBBase::radtodeg = 57.295779513082320876798154814105; @@ -123,98 +120,96 @@ using std::endl; void FGJSBBase::PutMessage(const Message& msg) { - Messages.push(msg); + Messages.push(msg); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGJSBBase::PutMessage(const string& text) { - Message msg; - msg.text = text; - msg.messageId = messageId++; - msg.subsystem = "FDM"; - msg.type = Message::eText; - Messages.push(msg); + Message msg; + msg.text = text; + msg.messageId = messageId++; + msg.subsystem = "FDM"; + msg.type = Message::eText; + Messages.push(msg); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGJSBBase::PutMessage(const string& text, bool bVal) { - Message msg; - msg.text = text; - msg.messageId = messageId++; - msg.subsystem = "FDM"; - msg.type = Message::eBool; - msg.bVal = bVal; - Messages.push(msg); + Message msg; + msg.text = text; + msg.messageId = messageId++; + msg.subsystem = "FDM"; + msg.type = Message::eBool; + msg.bVal = bVal; + Messages.push(msg); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGJSBBase::PutMessage(const string& text, int iVal) { - Message msg; - msg.text = text; - msg.messageId = messageId++; - msg.subsystem = "FDM"; - msg.type = Message::eInteger; - msg.bVal = (iVal != 0); - Messages.push(msg); + Message msg; + msg.text = text; + msg.messageId = messageId++; + msg.subsystem = "FDM"; + msg.type = Message::eInteger; + msg.bVal = (iVal != 0); + Messages.push(msg); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGJSBBase::PutMessage(const string& text, double dVal) { - Message msg; - msg.text = text; - msg.messageId = messageId++; - msg.subsystem = "FDM"; - msg.type = Message::eDouble; - msg.bVal = (dVal != 0.0); - Messages.push(msg); + Message msg; + msg.text = text; + msg.messageId = messageId++; + msg.subsystem = "FDM"; + msg.type = Message::eDouble; + msg.bVal = (dVal != 0.0); + Messages.push(msg); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% int FGJSBBase::SomeMessages(void) { - return !Messages.empty(); + return !Messages.empty(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGJSBBase::ProcessMessage(void) { - if (Messages.empty()) return; - localMsg = Messages.front(); - - while (Messages.size() > 0) - { - switch (localMsg.type) - { - case JSBSim::FGJSBBase::Message::eText: - cout << localMsg.messageId << ": " << localMsg.text << endl; - break; - case JSBSim::FGJSBBase::Message::eBool: - cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.bVal << endl; - break; - case JSBSim::FGJSBBase::Message::eInteger: - cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.iVal << endl; - break; - case JSBSim::FGJSBBase::Message::eDouble: - cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.dVal << endl; - break; - default: - cerr << "Unrecognized message type." << endl; - break; - } - Messages.pop(); - if (Messages.size() > 0) localMsg = Messages.front(); - else break; - } + if (Messages.empty()) return; + localMsg = Messages.front(); + + while (Messages.size() > 0) { + switch (localMsg.type) { + case JSBSim::FGJSBBase::Message::eText: + cout << localMsg.messageId << ": " << localMsg.text << endl; + break; + case JSBSim::FGJSBBase::Message::eBool: + cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.bVal << endl; + break; + case JSBSim::FGJSBBase::Message::eInteger: + cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.iVal << endl; + break; + case JSBSim::FGJSBBase::Message::eDouble: + cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.dVal << endl; + break; + default: + cerr << "Unrecognized message type." << endl; + break; + } + Messages.pop(); + if (Messages.size() > 0) localMsg = Messages.front(); + else break; + } } @@ -222,70 +217,65 @@ void FGJSBBase::ProcessMessage(void) FGJSBBase::Message* FGJSBBase::ProcessNextMessage(void) { - if (Messages.empty()) return NULL; - localMsg = Messages.front(); + if (Messages.empty()) return NULL; + localMsg = Messages.front(); - Messages.pop(); - return &localMsg; + Messages.pop(); + return &localMsg; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGJSBBase::disableHighLighting(void) -{ - highint[0]='\0'; - halfint[0]='\0'; - normint[0]='\0'; - reset[0]='\0'; - underon[0]='\0'; - underoff[0]='\0'; - fgblue[0]='\0'; - fgcyan[0]='\0'; - fgred[0]='\0'; - fggreen[0]='\0'; - fgdef[0]='\0'; +void FGJSBBase::disableHighLighting(void) { + highint[0]='\0'; + halfint[0]='\0'; + normint[0]='\0'; + reset[0]='\0'; + underon[0]='\0'; + underoff[0]='\0'; + fgblue[0]='\0'; + fgcyan[0]='\0'; + fgred[0]='\0'; + fggreen[0]='\0'; + fgdef[0]='\0'; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGJSBBase::CreateIndexedPropertyName(const string& Property, int index) { - std::ostringstream buf; - buf << Property << '[' << index << ']'; - return buf.str(); + std::ostringstream buf; + buf << Property << '[' << index << ']'; + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGJSBBase::GaussianRandomNumber(void) { - static double V1, V2, S; - static int phase = 0; - double X; + static double V1, V2, S; + static int phase = 0; + double X; - if (phase == 0) - { - V1 = V2 = S = X = 0.0; + if (phase == 0) { + V1 = V2 = S = X = 0.0; - do - { - double U1 = (double)rand() / RAND_MAX; - double U2 = (double)rand() / RAND_MAX; + do { + double U1 = (double)rand() / RAND_MAX; + double U2 = (double)rand() / RAND_MAX; - V1 = 2 * U1 - 1; - V2 = 2 * U2 - 1; - S = V1 * V1 + V2 * V2; - } - while (S >= 1 || S == 0); + V1 = 2 * U1 - 1; + V2 = 2 * U2 - 1; + S = V1 * V1 + V2 * V2; + } while(S >= 1 || S == 0); - X = V1 * sqrt(-2 * log(S) / S); - } - else - X = V2 * sqrt(-2 * log(S) / S); + X = V1 * sqrt(-2 * log(S) / S); + } else + X = V2 * sqrt(-2 * log(S) / S); - phase = 1 - phase; + phase = 1 - phase; - return X; + return X; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FGJSBBase.h b/src/FGJSBBase.h index 2665adfdcb77f329f5e9971f04060274db5715b7..2049a3cadb5ec2af5e8d4e76ae164e4d80bb7bf8 100644 --- a/src/FGJSBBase.h +++ b/src/FGJSBBase.h @@ -52,10 +52,10 @@ INCLUDES #if defined(_MSC_VER) && (_MSC_VER < 1300) namespace std { -template <class T> inline T max(const T& a, const T& b) -{ + template <class T> inline T max(const T& a, const T& b) + { return (a > b) ? a : b; -} + } } #endif @@ -69,8 +69,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -87,308 +86,280 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGJSBBase -{ +class FGJSBBase { public: - /// Constructor for FGJSBBase. - FGJSBBase() {}; - - /// Destructor for FGJSBBase. - ~FGJSBBase() {}; - - /// JSBSim Message structure - class Message - { - public: - unsigned int fdmId; - unsigned int messageId; - std::string text; - std::string subsystem; - enum mType {eText, eInteger, eDouble, eBool} type; - bool bVal; - int iVal; - double dVal; - }; - - /// First order, (low pass / lag) filter - class Filter - { - double prev_in; - double prev_out; - double ca; - double cb; - public: - Filter(void) {} - public: - Filter(double coeff, double dt) - { - prev_in = prev_out = 0.0; - double denom = 2.0 + coeff*dt; - ca = coeff*dt/denom; - cb = (2.0 - coeff*dt)/denom; - } - public: - double execute(double in) - { - double out = (in + prev_in)*ca + prev_out*cb; - prev_in = in; - prev_out = out; - return out; - } - }; - - ///@name JSBSim console output highlighting terms. - //@{ - /// highlights text - static char highint[5]; - /// low intensity text - static char halfint[5]; - /// normal intensity text - static char normint[6]; - /// resets text properties - static char reset[5]; - /// underlines text - static char underon[5]; - /// underline off - static char underoff[6]; - /// blue text - static char fgblue[6]; - /// cyan text - static char fgcyan[6]; - /// red text - static char fgred[6]; - /// green text - static char fggreen[6]; - /// default text - static char fgdef[6]; - //@} - - ///@name JSBSim Messaging functions - //@{ - /** Places a Message structure on the Message queue. - @param msg pointer to a Message structure - @return pointer to a Message structure */ - void PutMessage(const Message& msg); - /** Creates a message with the given text and places it on the queue. - @param text message text - @return pointer to a Message structure */ - void PutMessage(const std::string& text); - /** Creates a message with the given text and boolean value and places it on the queue. - @param text message text - @param bVal boolean value associated with the message - @return pointer to a Message structure */ - void PutMessage(const std::string& text, bool bVal); - /** Creates a message with the given text and integer value and places it on the queue. - @param text message text - @param iVal integer value associated with the message - @return pointer to a Message structure */ - void PutMessage(const std::string& text, int iVal); - /** Creates a message with the given text and double value and places it on the queue. - @param text message text - @param dVal double value associated with the message - @return pointer to a Message structure */ - void PutMessage(const std::string& text, double dVal); - /** Reads the message on the queue (but does not delete it). - @return 1 if some messages */ - int SomeMessages(void); - /** Reads the message on the queue and removes it from the queue. - This function also prints out the message.*/ - void ProcessMessage(void); - /** Reads the next message on the queue and removes it from the queue. - This function also prints out the message. - @return a pointer to the message, or NULL if there are no messages.*/ - Message* ProcessNextMessage(void); - //@} - - /** Returns the version number of JSBSim. - * @return The version number of JSBSim. */ - std::string GetVersion(void) - { - return JSBSim_version; - } - - /// Disables highlighting in the console output. - void disableHighLighting(void); - - static short debug_lvl; - - /** Converts from degrees Kelvin to degrees Fahrenheit. - * @param kelvin The temperature in degrees Kelvin. - * @return The temperature in Fahrenheit. */ - static double KelvinToFahrenheit (double kelvin) - { - return 1.8*kelvin - 459.4; - } - - /** Converts from degrees Celsius to degrees Rankine. - * @param celsius The temperature in degrees Celsius. - * @return The temperature in Rankine. */ - static double CelsiusToRankine (double celsius) - { - return celsius * 1.8 + 491.67; - } - - /** Converts from degrees Rankine to degrees Celsius. - * @param rankine The temperature in degrees Rankine. - * @return The temperature in Celsius. */ - static double RankineToCelsius (double rankine) - { - return (rankine - 491.67)/1.8; - } - - /** Converts from degrees Kelvin to degrees Rankine. - * @param kelvin The temperature in degrees Kelvin. - * @return The temperature in Rankine. */ - static double KelvinToRankine (double kelvin) - { - return kelvin * 1.8; - } - - /** Converts from degrees Rankine to degrees Kelvin. - * @param rankine The temperature in degrees Rankine. - * @return The temperature in Kelvin. */ - static double RankineToKelvin (double rankine) - { - return rankine/1.8; - } - - /** Converts from degrees Fahrenheit to degrees Celsius. - * @param fahrenheit The temperature in degrees Fahrenheit. - * @return The temperature in Celsius. */ - static double FahrenheitToCelsius (double fahrenheit) - { - return (fahrenheit - 32.0)/1.8; + /// Constructor for FGJSBBase. + FGJSBBase() {}; + + /// Destructor for FGJSBBase. + ~FGJSBBase() {}; + + /// JSBSim Message structure + class Message { + public: + unsigned int fdmId; + unsigned int messageId; + std::string text; + std::string subsystem; + enum mType {eText, eInteger, eDouble, eBool} type; + bool bVal; + int iVal; + double dVal; + }; + + /// First order, (low pass / lag) filter + class Filter { + double prev_in; + double prev_out; + double ca; + double cb; + public: Filter(void) {} + public: Filter(double coeff, double dt) { + prev_in = prev_out = 0.0; + double denom = 2.0 + coeff*dt; + ca = coeff*dt/denom; + cb = (2.0 - coeff*dt)/denom; } - - /** Converts from degrees Celsius to degrees Fahrenheit. - * @param celsius The temperature in degrees Celsius. - * @return The temperature in Fahrenheit. */ - static double CelsiusToFahrenheit (double celsius) - { - return celsius * 1.8 + 32.0; - } - - /** Converts from degrees Celsius to degrees Kelvin - * @param celsius The temperature in degrees Celsius. - * @return The temperature in Kelvin. */ - static double CelsiusToKelvin (double celsius) - { - return celsius + 273.15; - } - - /** Converts from degrees Kelvin to degrees Celsius - * @param celsius The temperature in degrees Kelvin. - * @return The temperature in Celsius. */ - static double KelvinToCelsius (double kelvin) - { - return kelvin - 273.15; - } - - /** Finite precision comparison. - @param a first value to compare - @param b second value to compare - @return if the two values can be considered equal up to roundoff */ - static bool EqualToRoundoff(double a, double b) - { - double eps = 2.0*DBL_EPSILON; - return std::fabs(a - b) <= eps*std::max(std::fabs(a), std::fabs(b)); - } - - /** Finite precision comparison. - @param a first value to compare - @param b second value to compare - @return if the two values can be considered equal up to roundoff */ - static bool EqualToRoundoff(float a, float b) - { - float eps = 2.0*FLT_EPSILON; - return std::fabs(a - b) <= eps*std::max(std::fabs(a), std::fabs(b)); - } - - /** Finite precision comparison. - @param a first value to compare - @param b second value to compare - @return if the two values can be considered equal up to roundoff */ - static bool EqualToRoundoff(float a, double b) - { - return EqualToRoundoff(a, (float)b); - } - - /** Finite precision comparison. - @param a first value to compare - @param b second value to compare - @return if the two values can be considered equal up to roundoff */ - static bool EqualToRoundoff(double a, float b) - { - return EqualToRoundoff((float)a, b); - } - - /** Constrain a value between a minimum and a maximum value. - */ - static double Constrain(double min, double value, double max) - { - return value<min?(min):(value>max?(max):(value)); - } - - static double sign(double num) - { - return num>=0.0?1.0:-1.0; + public: double execute(double in) { + double out = (in + prev_in)*ca + prev_out*cb; + prev_in = in; + prev_out = out; + return out; } + }; + + ///@name JSBSim console output highlighting terms. + //@{ + /// highlights text + static char highint[5]; + /// low intensity text + static char halfint[5]; + /// normal intensity text + static char normint[6]; + /// resets text properties + static char reset[5]; + /// underlines text + static char underon[5]; + /// underline off + static char underoff[6]; + /// blue text + static char fgblue[6]; + /// cyan text + static char fgcyan[6]; + /// red text + static char fgred[6]; + /// green text + static char fggreen[6]; + /// default text + static char fgdef[6]; + //@} + + ///@name JSBSim Messaging functions + //@{ + /** Places a Message structure on the Message queue. + @param msg pointer to a Message structure + @return pointer to a Message structure */ + void PutMessage(const Message& msg); + /** Creates a message with the given text and places it on the queue. + @param text message text + @return pointer to a Message structure */ + void PutMessage(const std::string& text); + /** Creates a message with the given text and boolean value and places it on the queue. + @param text message text + @param bVal boolean value associated with the message + @return pointer to a Message structure */ + void PutMessage(const std::string& text, bool bVal); + /** Creates a message with the given text and integer value and places it on the queue. + @param text message text + @param iVal integer value associated with the message + @return pointer to a Message structure */ + void PutMessage(const std::string& text, int iVal); + /** Creates a message with the given text and double value and places it on the queue. + @param text message text + @param dVal double value associated with the message + @return pointer to a Message structure */ + void PutMessage(const std::string& text, double dVal); + /** Reads the message on the queue (but does not delete it). + @return 1 if some messages */ + int SomeMessages(void); + /** Reads the message on the queue and removes it from the queue. + This function also prints out the message.*/ + void ProcessMessage(void); + /** Reads the next message on the queue and removes it from the queue. + This function also prints out the message. + @return a pointer to the message, or NULL if there are no messages.*/ + Message* ProcessNextMessage(void); + //@} + + /** Returns the version number of JSBSim. + * @return The version number of JSBSim. */ + std::string GetVersion(void) {return JSBSim_version;} + + /// Disables highlighting in the console output. + void disableHighLighting(void); + + static short debug_lvl; + + /** Converts from degrees Kelvin to degrees Fahrenheit. + * @param kelvin The temperature in degrees Kelvin. + * @return The temperature in Fahrenheit. */ + static double KelvinToFahrenheit (double kelvin) { + return 1.8*kelvin - 459.4; + } + + /** Converts from degrees Celsius to degrees Rankine. + * @param celsius The temperature in degrees Celsius. + * @return The temperature in Rankine. */ + static double CelsiusToRankine (double celsius) { + return celsius * 1.8 + 491.67; + } + + /** Converts from degrees Rankine to degrees Celsius. + * @param rankine The temperature in degrees Rankine. + * @return The temperature in Celsius. */ + static double RankineToCelsius (double rankine) { + return (rankine - 491.67)/1.8; + } + + /** Converts from degrees Kelvin to degrees Rankine. + * @param kelvin The temperature in degrees Kelvin. + * @return The temperature in Rankine. */ + static double KelvinToRankine (double kelvin) { + return kelvin * 1.8; + } + + /** Converts from degrees Rankine to degrees Kelvin. + * @param rankine The temperature in degrees Rankine. + * @return The temperature in Kelvin. */ + static double RankineToKelvin (double rankine) { + return rankine/1.8; + } + + /** Converts from degrees Fahrenheit to degrees Celsius. + * @param fahrenheit The temperature in degrees Fahrenheit. + * @return The temperature in Celsius. */ + static double FahrenheitToCelsius (double fahrenheit) { + return (fahrenheit - 32.0)/1.8; + } + + /** Converts from degrees Celsius to degrees Fahrenheit. + * @param celsius The temperature in degrees Celsius. + * @return The temperature in Fahrenheit. */ + static double CelsiusToFahrenheit (double celsius) { + return celsius * 1.8 + 32.0; + } + + /** Converts from degrees Celsius to degrees Kelvin + * @param celsius The temperature in degrees Celsius. + * @return The temperature in Kelvin. */ + static double CelsiusToKelvin (double celsius) { + return celsius + 273.15; + } + + /** Converts from degrees Kelvin to degrees Celsius + * @param celsius The temperature in degrees Kelvin. + * @return The temperature in Celsius. */ + static double KelvinToCelsius (double kelvin) { + return kelvin - 273.15; + } + + /** Finite precision comparison. + @param a first value to compare + @param b second value to compare + @return if the two values can be considered equal up to roundoff */ + static bool EqualToRoundoff(double a, double b) { + double eps = 2.0*DBL_EPSILON; + return std::fabs(a - b) <= eps*std::max(std::fabs(a), std::fabs(b)); + } + + /** Finite precision comparison. + @param a first value to compare + @param b second value to compare + @return if the two values can be considered equal up to roundoff */ + static bool EqualToRoundoff(float a, float b) { + float eps = 2.0*FLT_EPSILON; + return std::fabs(a - b) <= eps*std::max(std::fabs(a), std::fabs(b)); + } + + /** Finite precision comparison. + @param a first value to compare + @param b second value to compare + @return if the two values can be considered equal up to roundoff */ + static bool EqualToRoundoff(float a, double b) { + return EqualToRoundoff(a, (float)b); + } + + /** Finite precision comparison. + @param a first value to compare + @param b second value to compare + @return if the two values can be considered equal up to roundoff */ + static bool EqualToRoundoff(double a, float b) { + return EqualToRoundoff((float)a, b); + } + + /** Constrain a value between a minimum and a maximum value. + */ + static double Constrain(double min, double value, double max) { + return value<min?(min):(value>max?(max):(value)); + } + + static double sign(double num) {return num>=0.0?1.0:-1.0;} protected: - static Message localMsg; - - static std::queue <Message> Messages; - - void Debug(int) {}; - - static unsigned int messageId; - - static const double radtodeg; - static const double degtorad; - static const double hptoftlbssec; - static const double psftoinhg; - static const double psftopa; - static const double fpstokts; - static const double ktstofps; - static const double inchtoft; - static const double in3tom3; - static const double m3toft3; - static const double inhgtopa; - static const double fttom; - static double Reng; // Specific Gas Constant,ft^2/(sec^2*R) - static const double SHRatio; - static const double lbtoslug; - static const double slugtolb; - static const double kgtolb; - static const double kgtoslug; - static const std::string needed_cfg_version; - static const std::string JSBSim_version; - - static std::string CreateIndexedPropertyName(const std::string& Property, int index); - - static double GaussianRandomNumber(void); + static Message localMsg; + + static std::queue <Message> Messages; + + void Debug(int) {}; + + static unsigned int messageId; + + static const double radtodeg; + static const double degtorad; + static const double hptoftlbssec; + static const double psftoinhg; + static const double psftopa; + static const double fpstokts; + static const double ktstofps; + static const double inchtoft; + static const double in3tom3; + static const double m3toft3; + static const double inhgtopa; + static const double fttom; + static double Reng; // Specific Gas Constant,ft^2/(sec^2*R) + static const double SHRatio; + static const double lbtoslug; + static const double slugtolb; + static const double kgtolb; + static const double kgtoslug; + static const std::string needed_cfg_version; + static const std::string JSBSim_version; + + static std::string CreateIndexedPropertyName(const std::string& Property, int index); + + static double GaussianRandomNumber(void); public: /// Moments L, M, N - enum {eL = 1, eM, eN }; +enum {eL = 1, eM, eN }; /// Rates P, Q, R - enum {eP = 1, eQ, eR }; +enum {eP = 1, eQ, eR }; /// Velocities U, V, W - enum {eU = 1, eV, eW }; +enum {eU = 1, eV, eW }; /// Positions X, Y, Z - enum {eX = 1, eY, eZ }; +enum {eX = 1, eY, eZ }; /// Euler angles Phi, Theta, Psi - enum {ePhi = 1, eTht, ePsi }; +enum {ePhi = 1, eTht, ePsi }; /// Stability axis forces, Drag, Side force, Lift - enum {eDrag = 1, eSide, eLift }; +enum {eDrag = 1, eSide, eLift }; /// Local frame orientation Roll, Pitch, Yaw - enum {eRoll = 1, ePitch, eYaw }; +enum {eRoll = 1, ePitch, eYaw }; /// Local frame position North, East, Down - enum {eNorth = 1, eEast, eDown }; +enum {eNorth = 1, eEast, eDown }; /// Locations Radius, Latitude, Longitude - enum {eLat = 1, eLong, eRad }; +enum {eLat = 1, eLong, eRad }; /// Conversion specifiers - enum {inNone = 0, inDegrees, inRadians, inMeters, inFeet }; +enum {inNone = 0, inDegrees, inRadians, inMeters, inFeet }; }; diff --git a/src/FGState.cpp b/src/FGState.cpp index f1b20bf14353ffeea7e0437bd73f695bc89637dc..08e38a690cf9639e34511e76d19b0806fdcd1476 100644 --- a/src/FGState.cpp +++ b/src/FGState.cpp @@ -43,8 +43,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGState.cpp,v 1.15 2009/10/24 22:59:30 jberndt Exp $"; static const char *IdHdr = ID_STATE; @@ -59,76 +58,76 @@ CLASS IMPLEMENTATION FGState::FGState(FGFDMExec* fdex) { - FDMExec = fdex; + FDMExec = fdex; - sim_time = 0.0; - dt = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is - // run in standalone mode with no initialization file. + sim_time = 0.0; + dt = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is + // run in standalone mode with no initialization file. - Aircraft = FDMExec->GetAircraft(); - Propagate = FDMExec->GetPropagate(); - Auxiliary = FDMExec->GetAuxiliary(); - FCS = FDMExec->GetFCS(); - Atmosphere = FDMExec->GetAtmosphere(); - Aerodynamics = FDMExec->GetAerodynamics(); - GroundReactions = FDMExec->GetGroundReactions(); - Propulsion = FDMExec->GetPropulsion(); - PropertyManager = FDMExec->GetPropertyManager(); + Aircraft = FDMExec->GetAircraft(); + Propagate = FDMExec->GetPropagate(); + Auxiliary = FDMExec->GetAuxiliary(); + FCS = FDMExec->GetFCS(); + Atmosphere = FDMExec->GetAtmosphere(); + Aerodynamics = FDMExec->GetAerodynamics(); + GroundReactions = FDMExec->GetGroundReactions(); + Propulsion = FDMExec->GetPropulsion(); + PropertyManager = FDMExec->GetPropertyManager(); - bind(); + bind(); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGState::~FGState() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGState::Initialize(FGInitialCondition *FGIC) { - sim_time = 0.0; + sim_time = 0.0; - Propagate->SetInitialState( FGIC ); + Propagate->SetInitialState( FGIC ); - Atmosphere->Run(); - Atmosphere->SetWindNED( FGIC->GetWindNFpsIC(), - FGIC->GetWindEFpsIC(), - FGIC->GetWindDFpsIC() ); + Atmosphere->Run(); + Atmosphere->SetWindNED( FGIC->GetWindNFpsIC(), + FGIC->GetWindEFpsIC(), + FGIC->GetWindDFpsIC() ); - FGColumnVector3 vAeroUVW; - vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED(); + FGColumnVector3 vAeroUVW; + vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED(); - double alpha, beta; - if (vAeroUVW(eW) != 0.0) - alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0; - else - alpha = 0.0; - if (vAeroUVW(eV) != 0.0) - beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), (fabs(vAeroUVW(eU))/vAeroUVW(eU))*sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0; - else - beta = 0.0; + double alpha, beta; + if (vAeroUVW(eW) != 0.0) + alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0; + else + alpha = 0.0; + if (vAeroUVW(eV) != 0.0) + beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), (fabs(vAeroUVW(eU))/vAeroUVW(eU))*sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0; + else + beta = 0.0; - Auxiliary->SetAB(alpha, beta); + Auxiliary->SetAB(alpha, beta); - double Vt = vAeroUVW.Magnitude(); - Auxiliary->SetVt(Vt); + double Vt = vAeroUVW.Magnitude(); + Auxiliary->SetVt(Vt); - Auxiliary->SetMach(Vt/Atmosphere->GetSoundSpeed()); + Auxiliary->SetMach(Vt/Atmosphere->GetSoundSpeed()); - double qbar = 0.5*Vt*Vt*Atmosphere->GetDensity(); - Auxiliary->Setqbar(qbar); + double qbar = 0.5*Vt*Vt*Atmosphere->GetDensity(); + Auxiliary->Setqbar(qbar); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGState::bind(void) { - PropertyManager->Tie("sim-time-sec", this, &FGState::Getsim_time); + PropertyManager->Tie("sim-time-sec", this, &FGState::Getsim_time); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -152,36 +151,28 @@ void FGState::bind(void) void FGState::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGState" << endl; - if (from == 1) cout << "Destroyed: FGState" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGState" << endl; + if (from == 1) cout << "Destroyed: FGState" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/FGState.h b/src/FGState.h index 2297ee6ae57b31093f11126cca53eece6bc9c0bf..220f042fd2b066e07db3dff8ca15d293f8a6281f 100644 --- a/src/FGState.h +++ b/src/FGState.h @@ -68,8 +68,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -89,96 +88,75 @@ CLASS DECLARATION class FGState : public FGJSBBase { public: - /** Constructor - @param Executive a pointer to the parent executive object */ - FGState(FGFDMExec*); - /// Destructor - ~FGState(); - - /** Initializes the simulation state based on parameters from an Initial Conditions object. - @param FGIC pointer to an initial conditions object. - @see FGInitialConditions. */ - void Initialize(FGInitialCondition *FGIC); - - /// Returns the cumulative simulation time in seconds. - inline double Getsim_time(void) const - { - return sim_time; - } - - /// Returns the simulation delta T. - inline double Getdt(void) - { - return dt; - } - - /// Suspends the simulation and sets the delta T to zero. - inline void SuspendIntegration(void) - { - saved_dt = dt; - dt = 0.0; - } - - /// Resumes the simulation by resetting delta T to the correct value. - inline void ResumeIntegration(void) - { - dt = saved_dt; - } - - /** Returns the simulation suspension state. - @return true if suspended, false if executing */ - bool IntegrationSuspended(void) - { - return dt == 0.0; - } - - /** Sets the current sim time. - @param cur_time the current time - @return the current simulation time. */ - inline double Setsim_time(double cur_time) - { - sim_time = cur_time; - return sim_time; - } - - /** Sets the integration time step for the simulation executive. - @param delta_t the time step in seconds. */ - inline void Setdt(double delta_t) - { - dt = delta_t; - } - - /** Increments the simulation time. - @return the new simulation time. */ - inline double IncrTime(void) - { - sim_time+=dt; - return sim_time; - } - - /** Prints a summary of simulator state (speed, altitude, - configuration, etc.) */ + /** Constructor + @param Executive a pointer to the parent executive object */ + FGState(FGFDMExec*); + /// Destructor + ~FGState(); + + /** Initializes the simulation state based on parameters from an Initial Conditions object. + @param FGIC pointer to an initial conditions object. + @see FGInitialConditions. */ + void Initialize(FGInitialCondition *FGIC); + + /// Returns the cumulative simulation time in seconds. + inline double Getsim_time(void) const { return sim_time; } + + /// Returns the simulation delta T. + inline double Getdt(void) {return dt;} + + /// Suspends the simulation and sets the delta T to zero. + inline void SuspendIntegration(void) {saved_dt = dt; dt = 0.0;} + + /// Resumes the simulation by resetting delta T to the correct value. + inline void ResumeIntegration(void) {dt = saved_dt;} + + /** Returns the simulation suspension state. + @return true if suspended, false if executing */ + bool IntegrationSuspended(void) {return dt == 0.0;} + + /** Sets the current sim time. + @param cur_time the current time + @return the current simulation time. */ + inline double Setsim_time(double cur_time) { + sim_time = cur_time; + return sim_time; + } + + /** Sets the integration time step for the simulation executive. + @param delta_t the time step in seconds. */ + inline void Setdt(double delta_t) { dt = delta_t; } + + /** Increments the simulation time. + @return the new simulation time. */ + inline double IncrTime(void) { + sim_time+=dt; + return sim_time; + } + + /** Prints a summary of simulator state (speed, altitude, + configuration, etc.) */ // void ReportState(void); private: - double sim_time, dt; - double saved_dt; + double sim_time, dt; + double saved_dt; - FGFDMExec* FDMExec; + FGFDMExec* FDMExec; - FGAircraft* Aircraft; - FGPropagate* Propagate; - FGAtmosphere* Atmosphere; - FGFCS* FCS; - FGAerodynamics* Aerodynamics; - FGGroundReactions* GroundReactions; - FGPropulsion* Propulsion; - FGAuxiliary* Auxiliary; - FGPropertyManager* PropertyManager; + FGAircraft* Aircraft; + FGPropagate* Propagate; + FGAtmosphere* Atmosphere; + FGFCS* FCS; + FGAerodynamics* Aerodynamics; + FGGroundReactions* GroundReactions; + FGPropulsion* Propulsion; + FGAuxiliary* Auxiliary; + FGPropertyManager* PropertyManager; - void bind(); + void bind(); - void Debug(int from); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/JSBSim.cpp b/src/JSBSim.cpp index aff4492b8ae60a442475e1d18a202ff336d22115..fe406fbdbb1f144f32ff97179ea58f412d8e15c0 100644 --- a/src/JSBSim.cpp +++ b/src/JSBSim.cpp @@ -100,37 +100,37 @@ bool options(int, char**); void PrintHelp(void); #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__) -double getcurrentseconds(void) -{ + double getcurrentseconds(void) + { struct timeb tm_ptr; ftime(&tm_ptr); return tm_ptr.time + tm_ptr.millitm*0.001; -} + } #else -double getcurrentseconds(void) -{ + double getcurrentseconds(void) + { struct timeval tval; struct timezone tz; gettimeofday(&tval, &tz); return (tval.tv_sec + tval.tv_usec*1e-6); -} + } #endif #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__) -void sim_nsleep(long nanosec) -{ + void sim_nsleep(long nanosec) + { Sleep(nanosec*1e-6); // convert nanoseconds (passed in) to milliseconds for Win32. -} + } #else -void sim_nsleep(long nanosec) -{ + void sim_nsleep(long nanosec) + { struct timespec ts, ts1; ts.tv_sec = 0; ts.tv_nsec = nanosec; nanosleep(&ts, &ts1); -} + } #endif /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -240,475 +240,373 @@ IMPLEMENTATION int main(int argc, char* argv[]) { - // *** INITIALIZATIONS *** // - - ScriptName = ""; - AircraftName = ""; - ResetName = ""; - LogOutputName = ""; - LogDirectiveName.clear(); - bool result = false, success; - bool was_paused = false; - - double frame_duration; - - double new_five_second_value = 0.0; - double actual_elapsed_time = 0; - double initial_seconds = 0; - double current_seconds = 0.0; - double paused_seconds = 0.0; - double sim_lag_time = 0; - double cycle_duration = 0.0; - double override_sim_rate_value = 0.0; - long sleep_nseconds = 0; - - realtime = false; - play_nice = false; - suspend = false; - catalog=false; - - // *** PARSE OPTIONS PASSED INTO THIS SPECIFIC APPLICATION: JSBSim *** // - success = options(argc, argv); - if (!success) - { - PrintHelp(); - exit(-1); + // *** INITIALIZATIONS *** // + + ScriptName = ""; + AircraftName = ""; + ResetName = ""; + LogOutputName = ""; + LogDirectiveName.clear(); + bool result = false, success; + bool was_paused = false; + + double frame_duration; + + double new_five_second_value = 0.0; + double actual_elapsed_time = 0; + double initial_seconds = 0; + double current_seconds = 0.0; + double paused_seconds = 0.0; + double sim_lag_time = 0; + double cycle_duration = 0.0; + double override_sim_rate_value = 0.0; + long sleep_nseconds = 0; + + realtime = false; + play_nice = false; + suspend = false; + catalog=false; + + // *** PARSE OPTIONS PASSED INTO THIS SPECIFIC APPLICATION: JSBSim *** // + success = options(argc, argv); + if (!success) { + PrintHelp(); + exit(-1); + } + + // *** SET UP JSBSIM *** // + FDMExec = new JSBSim::FGFDMExec(); + FDMExec->SetRootDir(RootDir); + FDMExec->SetAircraftPath("aircraft"); + FDMExec->SetEnginePath("engine"); + FDMExec->SetSystemsPath("systems"); + FDMExec->GetPropertyManager()->Tie("simulation/frame_start_time", &actual_elapsed_time); + FDMExec->GetPropertyManager()->Tie("simulation/cycle_duration", &cycle_duration); + + if (simulation_rate < 1.0 ) + FDMExec->Setdt(simulation_rate); + else + FDMExec->Setdt(1.0/simulation_rate); + + if (override_sim_rate) override_sim_rate_value = FDMExec->GetDeltaT(); + + // *** OPTION A: LOAD A SCRIPT, WHICH LOADS EVERYTHING ELSE *** // + if (!ScriptName.empty()) { + + result = FDMExec->LoadScript(ScriptName, override_sim_rate_value); + + if (!result) { + cerr << "Script file " << ScriptName << " was not successfully loaded" << endl; + delete FDMExec; + exit(-1); } - // *** SET UP JSBSIM *** // - FDMExec = new JSBSim::FGFDMExec(); - FDMExec->SetRootDir(RootDir); - FDMExec->SetAircraftPath("aircraft"); - FDMExec->SetEnginePath("engine"); - FDMExec->SetSystemsPath("systems"); - FDMExec->GetPropertyManager()->Tie("simulation/frame_start_time", &actual_elapsed_time); - FDMExec->GetPropertyManager()->Tie("simulation/cycle_duration", &cycle_duration); - - if (simulation_rate < 1.0 ) - FDMExec->Setdt(simulation_rate); - else - FDMExec->Setdt(1.0/simulation_rate); - - if (override_sim_rate) override_sim_rate_value = FDMExec->GetDeltaT(); - - // *** OPTION A: LOAD A SCRIPT, WHICH LOADS EVERYTHING ELSE *** // - if (!ScriptName.empty()) - { - - result = FDMExec->LoadScript(ScriptName, override_sim_rate_value); - - if (!result) - { - cerr << "Script file " << ScriptName << " was not successfully loaded" << endl; - delete FDMExec; - exit(-1); - } + // *** OPTION B: LOAD AN AIRCRAFT AND A SET OF INITIAL CONDITIONS *** // + } else if (!AircraftName.empty() || !ResetName.empty()) { - // *** OPTION B: LOAD AN AIRCRAFT AND A SET OF INITIAL CONDITIONS *** // - } - else if (!AircraftName.empty() || !ResetName.empty()) - { - - if (catalog) FDMExec->SetDebugLevel(0); - - if ( ! FDMExec->LoadModel( "aircraft", - "engine", - "systems", - AircraftName)) - { - cerr << " JSBSim could not be started" << endl << endl; - delete FDMExec; - exit(-1); - } + if (catalog) FDMExec->SetDebugLevel(0); - if (catalog) - { - FDMExec->PrintPropertyCatalog(); - delete FDMExec; - return 0; - } + if ( ! FDMExec->LoadModel( "aircraft", + "engine", + "systems", + AircraftName)) { + cerr << " JSBSim could not be started" << endl << endl; + delete FDMExec; + exit(-1); + } - JSBSim::FGInitialCondition *IC = FDMExec->GetIC(); - if ( ! IC->Load(ResetName)) - { - delete FDMExec; - cerr << "Initialization unsuccessful" << endl; - exit(-1); - } + if (catalog) { + FDMExec->PrintPropertyCatalog(); + delete FDMExec; + return 0; + } + JSBSim::FGInitialCondition *IC = FDMExec->GetIC(); + if ( ! IC->Load(ResetName)) { + delete FDMExec; + cerr << "Initialization unsuccessful" << endl; + exit(-1); } - else - { - cout << " No Aircraft, Script, or Reset information given" << endl << endl; + + } else { + cout << " No Aircraft, Script, or Reset information given" << endl << endl; + delete FDMExec; + exit(-1); + } + + // Load output directives file, if given + for (unsigned int i=0; i<LogDirectiveName.size(); i++) { + if (!LogDirectiveName[i].empty()) { + if (!FDMExec->SetOutputDirectives(LogDirectiveName[i])) { + cout << "Output directives not properly set in file " << LogDirectiveName[i] << endl; delete FDMExec; exit(-1); + } } - - // Load output directives file, if given - for (unsigned int i=0; i<LogDirectiveName.size(); i++) - { - if (!LogDirectiveName[i].empty()) - { - if (!FDMExec->SetOutputDirectives(LogDirectiveName[i])) - { - cout << "Output directives not properly set in file " << LogDirectiveName[i] << endl; - delete FDMExec; - exit(-1); - } - } + } + + // OVERRIDE OUTPUT FILE NAME. THIS IS USEFUL FOR CASES WHERE MULTIPLE + // RUNS ARE BEING MADE (SUCH AS IN A MONTE CARLO STUDY) AND THE OUTPUT FILE + // NAME MUST BE SET EACH TIME TO AVOID THE PREVIOUS RUN DATA FROM BEING OVER- + // WRITTEN. THIS OVERRIDES ONLY THE FILENAME FOR THE FIRST FILE. + if (!LogOutputName.empty()) { + string old_filename = FDMExec->GetOutputFileName(); + if (!FDMExec->SetOutputFileName(LogOutputName)) { + cout << "Output filename could not be set" << endl; + } else { + cout << "Output filename change from " << old_filename << " from aircraft" + " configuration file to " << LogOutputName << " specified on" + " command line" << endl; } + } - // OVERRIDE OUTPUT FILE NAME. THIS IS USEFUL FOR CASES WHERE MULTIPLE - // RUNS ARE BEING MADE (SUCH AS IN A MONTE CARLO STUDY) AND THE OUTPUT FILE - // NAME MUST BE SET EACH TIME TO AVOID THE PREVIOUS RUN DATA FROM BEING OVER- - // WRITTEN. THIS OVERRIDES ONLY THE FILENAME FOR THE FIRST FILE. - if (!LogOutputName.empty()) - { - string old_filename = FDMExec->GetOutputFileName(); - if (!FDMExec->SetOutputFileName(LogOutputName)) - { - cout << "Output filename could not be set" << endl; - } - else - { - cout << "Output filename change from " << old_filename << " from aircraft" - " configuration file to " << LogOutputName << " specified on" - " command line" << endl; - } + // SET PROPERTY VALUES THAT ARE GIVEN ON THE COMMAND LINE + + for (unsigned int i=0; i<CommandLineProperties.size(); i++) { + + if (!FDMExec->GetPropertyManager()->GetNode(CommandLineProperties[i])) { + cerr << endl << " No property by the name " << CommandLineProperties[i] << endl; + goto quit; + } else { + FDMExec->SetPropertyValue(CommandLineProperties[i], CommandLinePropertyValues[i]); } + } - // SET PROPERTY VALUES THAT ARE GIVEN ON THE COMMAND LINE + cout << endl << JSBSim::FGFDMExec::fggreen << JSBSim::FGFDMExec::highint + << "---- JSBSim Execution beginning ... --------------------------------------------" + << JSBSim::FGFDMExec::reset << endl << endl; - for (unsigned int i=0; i<CommandLineProperties.size(); i++) - { + result = FDMExec->Run(); // MAKE AN INITIAL RUN - if (!FDMExec->GetPropertyManager()->GetNode(CommandLineProperties[i])) - { - cerr << endl << " No property by the name " << CommandLineProperties[i] << endl; - goto quit; - } - else - { - FDMExec->SetPropertyValue(CommandLineProperties[i], CommandLinePropertyValues[i]); - } - } + if (suspend) FDMExec->Hold(); + + // Print actual time at start + char s[100]; + time_t tod; + time(&tod); + strftime(s, 99, "%A %B %d %Y %X", localtime(&tod)); + cout << "Start: " << s << " (HH:MM:SS)" << endl; + + frame_duration = FDMExec->GetDeltaT(); + if (realtime) sleep_nseconds = (long)(frame_duration*1e9); + else sleep_nseconds = (10000000); // 0.01 seconds + + tzset(); + current_seconds = initial_seconds = getcurrentseconds(); + + // *** CYCLIC EXECUTION LOOP, AND MESSAGE READING *** // + while (result && FDMExec->GetSimTime() <= end_time) { + + FDMExec->ProcessMessage(); // Process messages, if any. - cout << endl << JSBSim::FGFDMExec::fggreen << JSBSim::FGFDMExec::highint - << "---- JSBSim Execution beginning ... --------------------------------------------" - << JSBSim::FGFDMExec::reset << endl << endl; - - result = FDMExec->Run(); // MAKE AN INITIAL RUN - - if (suspend) FDMExec->Hold(); - - // Print actual time at start - char s[100]; - time_t tod; - time(&tod); - strftime(s, 99, "%A %B %d %Y %X", localtime(&tod)); - cout << "Start: " << s << " (HH:MM:SS)" << endl; - - frame_duration = FDMExec->GetDeltaT(); - if (realtime) sleep_nseconds = (long)(frame_duration*1e9); - else sleep_nseconds = (10000000); // 0.01 seconds - - tzset(); - current_seconds = initial_seconds = getcurrentseconds(); - - // *** CYCLIC EXECUTION LOOP, AND MESSAGE READING *** // - while (result && FDMExec->GetSimTime() <= end_time) - { - - FDMExec->ProcessMessage(); // Process messages, if any. - - // if running realtime, throttle the execution, else just run flat-out fast - // unless "playing nice", in which case sleep for a while (0.01 seconds) each frame. - // If suspended, then don't increment cumulative realtime "stopwatch". - - if ( ! FDMExec->Holding()) - { - if ( ! realtime ) // ------------ RUNNING IN BATCH MODE - { - - result = FDMExec->Run(); - - if (play_nice) sim_nsleep(sleep_nseconds); - - } - else // ------------ RUNNING IN REALTIME MODE - { - - // "was_paused" will be true if entering this "run" loop from a paused state. - if (was_paused) - { - initial_seconds += paused_seconds; - was_paused = false; - } - current_seconds = getcurrentseconds(); // Seconds since 1 Jan 1970 - actual_elapsed_time = current_seconds - initial_seconds; // Real world elapsed seconds since start - sim_lag_time = actual_elapsed_time - FDMExec->GetSimTime(); // How far behind sim-time is from actual - // elapsed time. - for (int i=0; i<(int)(sim_lag_time/frame_duration); i++) // catch up sim time to actual elapsed time. - { - result = FDMExec->Run(); - cycle_duration = getcurrentseconds() - current_seconds; // Calculate cycle duration - current_seconds = getcurrentseconds(); // Get new current_seconds - if (FDMExec->Holding()) break; - } - - if (play_nice) sim_nsleep(sleep_nseconds); - - if (FDMExec->GetSimTime() >= new_five_second_value) // Print out elapsed time every five seconds. - { - cout << "Simulation elapsed time: " << FDMExec->GetSimTime() << endl; - new_five_second_value += 5.0; - } - } + // if running realtime, throttle the execution, else just run flat-out fast + // unless "playing nice", in which case sleep for a while (0.01 seconds) each frame. + // If suspended, then don't increment cumulative realtime "stopwatch". + + if ( ! FDMExec->Holding()) { + if ( ! realtime ) { // ------------ RUNNING IN BATCH MODE + + result = FDMExec->Run(); + + if (play_nice) sim_nsleep(sleep_nseconds); + + } else { // ------------ RUNNING IN REALTIME MODE + + // "was_paused" will be true if entering this "run" loop from a paused state. + if (was_paused) { + initial_seconds += paused_seconds; + was_paused = false; } - else // Suspended - { - was_paused = true; - paused_seconds = getcurrentseconds() - current_seconds; - sim_nsleep(sleep_nseconds); - result = FDMExec->Run(); + current_seconds = getcurrentseconds(); // Seconds since 1 Jan 1970 + actual_elapsed_time = current_seconds - initial_seconds; // Real world elapsed seconds since start + sim_lag_time = actual_elapsed_time - FDMExec->GetSimTime(); // How far behind sim-time is from actual + // elapsed time. + for (int i=0; i<(int)(sim_lag_time/frame_duration); i++) { // catch up sim time to actual elapsed time. + result = FDMExec->Run(); + cycle_duration = getcurrentseconds() - current_seconds; // Calculate cycle duration + current_seconds = getcurrentseconds(); // Get new current_seconds + if (FDMExec->Holding()) break; } + if (play_nice) sim_nsleep(sleep_nseconds); + + if (FDMExec->GetSimTime() >= new_five_second_value) { // Print out elapsed time every five seconds. + cout << "Simulation elapsed time: " << FDMExec->GetSimTime() << endl; + new_five_second_value += 5.0; + } + } + } else { // Suspended + was_paused = true; + paused_seconds = getcurrentseconds() - current_seconds; + sim_nsleep(sleep_nseconds); + result = FDMExec->Run(); } + } + quit: - // PRINT ENDING CLOCK TIME - time(&tod); - strftime(s, 99, "%A %B %d %Y %X", localtime(&tod)); - cout << "End: " << s << " (HH:MM:SS)" << endl; + // PRINT ENDING CLOCK TIME + time(&tod); + strftime(s, 99, "%A %B %d %Y %X", localtime(&tod)); + cout << "End: " << s << " (HH:MM:SS)" << endl; - // CLEAN UP - delete FDMExec; + // CLEAN UP + delete FDMExec; - return 0; + return 0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool options(int count, char **arg) { - int i; - bool result = true; + int i; + bool result = true; - if (count == 1) - { - PrintHelp(); - exit(0); - } + if (count == 1) { + PrintHelp(); + exit(0); + } - cout.setf(ios_base::fixed); + cout.setf(ios_base::fixed); #define gripe cerr << "Option '" << keyword \ << "' requires a value, as in '" \ << keyword << "=something'" << endl << endl;/**/ - for (i=1; i<count; i++) - { - string argument = string(arg[i]); - string keyword(argument); - string value(""); - string::size_type n=argument.find("="); - if (n != string::npos && n > 0) - { - keyword = argument.substr(0, n); - value = argument.substr(n+1); - } - - if (keyword == "--help") - { - PrintHelp(); - exit(0); - } - else if (keyword == "--version") - { - cout << endl << " JSBSim Version: " << FDMExec->GetVersion() << endl << endl; - exit (0); - } - else if (keyword == "--realtime") - { - realtime = true; - } - else if (keyword == "--nice") - { - play_nice = true; - } - else if (keyword == "--suspend") - { - suspend = true; - } - else if (keyword == "--outputlogfile") - { - if (n != string::npos) - { - LogOutputName = value; - } - else - { - LogOutputName = "JSBout.csv"; - cerr << " Output log file name must be specified with an = sign. Using JSBout.csv as default"; - } - } - else if (keyword == "--logdirectivefile") - { - if (n != string::npos) - { - LogDirectiveName.push_back(value); - } - else - { - gripe; - exit(1); - } - } - else if (keyword == "--root") - { - if (n != string::npos) - { - RootDir = value; - if (RootDir[RootDir.length()-1] != '/') - { - RootDir += '/'; - } - } - else - { - gripe; - exit(1); - } - } - else if (keyword == "--aircraft") - { - if (n != string::npos) - { - AircraftName = value; - } - else - { - gripe; - exit(1); - } - } - else if (keyword == "--script") - { - if (n != string::npos) - { - ScriptName = value; - } - else - { - gripe; - exit(1); - } - } - else if (keyword == "--initfile") - { - if (n != string::npos) - { - ResetName = value; - } - else - { - gripe; - exit(1); - } - - } - else if (keyword == "--property") - { - if (n != string::npos) - { - string propName = value.substr(0,value.find("=")); - string propValueString = value.substr(value.find("=")+1); - double propValue = atof(propValueString.c_str()); - CommandLineProperties.push_back(propName); - CommandLinePropertyValues.push_back(propValue); - } - else - { - gripe; - exit(1); - } - - } - else if (keyword == "--end-time") - { - if (n != string::npos) - { - try - { - end_time = atof( value.c_str() ); - } - catch (...) - { - cerr << endl << " Invalid end time given!" << endl << endl; - result = false; - } - } - else - { - gripe; - exit(1); - } - - } - else if (keyword == "--simulation-rate") - { - if (n != string::npos) - { - try - { - simulation_rate = atof( value.c_str() ); - override_sim_rate = true; - } - catch (...) - { - cerr << endl << " Invalid simulation rate given!" << endl << endl; - result = false; - } - } - else - { - gripe; - exit(1); - } + for (i=1; i<count; i++) { + string argument = string(arg[i]); + string keyword(argument); + string value(""); + string::size_type n=argument.find("="); + if (n != string::npos && n > 0) { + keyword = argument.substr(0, n); + value = argument.substr(n+1); + } + if (keyword == "--help") { + PrintHelp(); + exit(0); + } else if (keyword == "--version") { + cout << endl << " JSBSim Version: " << FDMExec->GetVersion() << endl << endl; + exit (0); + } else if (keyword == "--realtime") { + realtime = true; + } else if (keyword == "--nice") { + play_nice = true; + } else if (keyword == "--suspend") { + suspend = true; + } else if (keyword == "--outputlogfile") { + if (n != string::npos) { + LogOutputName = value; + } else { + LogOutputName = "JSBout.csv"; + cerr << " Output log file name must be specified with an = sign. Using JSBout.csv as default"; + } + } else if (keyword == "--logdirectivefile") { + if (n != string::npos) { + LogDirectiveName.push_back(value); + } else { + gripe; + exit(1); + } + } else if (keyword == "--root") { + if (n != string::npos) { + RootDir = value; + if (RootDir[RootDir.length()-1] != '/') { + RootDir += '/'; } - else if (keyword == "--catalog") - { - catalog = true; - if (value.size() > 0) AircraftName=value; + } else { + gripe; + exit(1); + } + } else if (keyword == "--aircraft") { + if (n != string::npos) { + AircraftName = value; + } else { + gripe; + exit(1); + } + } else if (keyword == "--script") { + if (n != string::npos) { + ScriptName = value; + } else { + gripe; + exit(1); + } + } else if (keyword == "--initfile") { + if (n != string::npos) { + ResetName = value; + } else { + gripe; + exit(1); + } + + } else if (keyword == "--property") { + if (n != string::npos) { + string propName = value.substr(0,value.find("=")); + string propValueString = value.substr(value.find("=")+1); + double propValue = atof(propValueString.c_str()); + CommandLineProperties.push_back(propName); + CommandLinePropertyValues.push_back(propValue); + } else { + gripe; + exit(1); + } + + } else if (keyword == "--end-time") { + if (n != string::npos) { + try { + end_time = atof( value.c_str() ); + } catch (...) { + cerr << endl << " Invalid end time given!" << endl << endl; + result = false; } - else - { - cerr << endl << " Parameter: " << argument << " not understood" << endl; - result = false; + } else { + gripe; + exit(1); + } + + } else if (keyword == "--simulation-rate") { + if (n != string::npos) { + try { + simulation_rate = atof( value.c_str() ); + override_sim_rate = true; + } catch (...) { + cerr << endl << " Invalid simulation rate given!" << endl << endl; + result = false; } + } else { + gripe; + exit(1); + } + + } else if (keyword == "--catalog") { + catalog = true; + if (value.size() > 0) AircraftName=value; + } else { + cerr << endl << " Parameter: " << argument << " not understood" << endl; + result = false; } + } - // Post-processing for script options. check for incompatible options. + // Post-processing for script options. check for incompatible options. - if (catalog && !ScriptName.empty()) - { - cerr << "Cannot specify catalog with script option" << endl << endl; - result = false; - } - if (AircraftName.size() > 0 && ResetName.size() == 0 && !catalog) - { - cerr << "You must specify an initialization file with the aircraft name." << endl << endl; - result = false; - } - if ((ScriptName.size() > 0 && AircraftName.size() > 0) || (ScriptName.size() > 0 && ResetName.size() > 0)) - { - cerr << "You cannot specify an aircraft or initialization file with a script." << endl; - result = false; - } + if (catalog && !ScriptName.empty()) { + cerr << "Cannot specify catalog with script option" << endl << endl; + result = false; + } + if (AircraftName.size() > 0 && ResetName.size() == 0 && !catalog) { + cerr << "You must specify an initialization file with the aircraft name." << endl << endl; + result = false; + } + if ((ScriptName.size() > 0 && AircraftName.size() > 0) || (ScriptName.size() > 0 && ResetName.size() > 0)) { + cerr << "You cannot specify an aircraft or initialization file with a script." << endl; + result = false; + } - return result; + return result; } @@ -716,9 +614,9 @@ bool options(int count, char **arg) void PrintHelp(void) { - cout << endl << " JSBSim version " << FDMExec->GetVersion() << endl << endl; - cout << " Usage: jsbsim <options>" << endl << endl; - cout << " options:" << endl; + cout << endl << " JSBSim version " << FDMExec->GetVersion() << endl << endl; + cout << " Usage: jsbsim <options>" << endl << endl; + cout << " options:" << endl; cout << " --help returns this message" << endl; cout << " --version returns the version number" << endl; cout << " --outputlogfile=<filename> sets (overrides) the name of the first data output file" << endl; @@ -737,7 +635,7 @@ void PrintHelp(void) cout << " --simulation-rate=<rate (double)> specifies the sim dT time or frequency" << endl; cout << " --end-time=<time (double)> specifies the sim end time" << endl << endl; - cout << " NOTE: There can be no spaces around the = sign when" << endl; - cout << " an option is followed by a filename" << endl << endl; + cout << " NOTE: There can be no spaces around the = sign when" << endl; + cout << " an option is followed by a filename" << endl << endl; } diff --git a/src/JSBSim.hxx b/src/JSBSim.hxx index 38c952bd260fdcd46965aa2a1c61625540706f6b..7225f53795a2fdbc5cfa57e660fdb61623c6dc3e 100644 --- a/src/JSBSim.hxx +++ b/src/JSBSim.hxx @@ -58,7 +58,6 @@ FORWARD DECLARATIONS #include <FDM/JSBSim/FGFDMExec.h> namespace JSBSim { -class FGState; class FGAtmosphere; class FGFCS; class FGPropulsion; @@ -86,7 +85,7 @@ CLASS DOCUMENTATION documentation for main for direction on running JSBSim apart from FlightGear. @author Curtis L. Olson (original) @author Tony Peden (Maintained and refined) - @version $Id: JSBSim.hxx,v 1.13 2010/07/07 20:46:36 andgi Exp $ + @version $Id: JSBSim.hxx,v 1.14 2010/09/22 11:33:40 jberndt Exp $ @see main in file JSBSim.cpp (use main() wrapper for standalone usage) */ @@ -214,7 +213,6 @@ private: JSBSim::FGInitialCondition *fgic; bool needTrim; - JSBSim::FGState* State; JSBSim::FGAtmosphere* Atmosphere; JSBSim::FGFCS* FCS; JSBSim::FGPropulsion* Propulsion; diff --git a/src/Makefile.am b/src/Makefile.am index f1eaf6f659d3a5d31f571bf283d67f9a09487515..8e7a19aab1b89f6e449c1cb01b6053e3274f67f1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,8 +9,7 @@ LIBRARY_SOURCES = FGFDMExec.cpp FGJSBBase.cpp LIBRARY_INCLUDES = FGFDMExec.h FGJSBBase.h -noinst_PROGRAMS = JSBSim FGComm - +noinst_PROGRAMS = JSBSim if BUILD_LIBRARIES @@ -34,9 +33,6 @@ libJSBSim_la_CXXFLAGS = $(AM_CXXFLAGS) JSBSim_SOURCES = JSBSim.cpp JSBSim_LDADD = libJSBSim.la -lm -FGComm_SOURCES = FGComm.cpp -FGComm_LDADD = libJSBSim.la -lm - else noinst_HEADERS = $(LIBRARY_INCLUDES) @@ -55,20 +51,6 @@ JSBSim_LDADD = \ simgear/magvar/libcoremag.a \ -lm -FGComm_SOURCES = FGComm.cpp $(LIBRARY_SOURCES) -FGComm_LDADD = \ - initialization/libInit.a \ - models/libModels.a \ - models/flight_control/libFlightControl.a \ - models/atmosphere/libAtmosphere.a \ - models/propulsion/libPropulsion.a \ - input_output/libInputOutput.a \ - math/libMath.a \ - simgear/props/libProperties.a \ - simgear/xml/libExpat.a \ - simgear/magvar/libcoremag.a \ - -lm - endif INCLUDES = -I$(top_srcdir)/src diff --git a/src/initialization/FGInitialCondition.cpp b/src/initialization/FGInitialCondition.cpp index eee4a950d9543a7aa5fd15a82ade391a90a246c0..ed17c6944aa0b46fa60343d6c5812697fa04a314 100644 --- a/src/initialization/FGInitialCondition.cpp +++ b/src/initialization/FGInitialCondition.cpp @@ -60,40 +60,36 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.40 2010/06/02 04:05:13 jberndt Exp $"; +static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.44 2010/09/18 22:48:12 jberndt Exp $"; static const char *IdHdr = ID_INITIALCONDITION; //****************************************************************************** FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec) : fdmex(FDMExec) { - InitializeIC(); - - if (FDMExec != NULL ) - { - fdmex->GetPropagate()->SetAltitudeASL(altitudeASL); - fdmex->GetAtmosphere()->Run(); - PropertyManager=fdmex->GetPropertyManager(); - Constructing = true; - bind(); - Constructing = false; - } - else - { - cout << "FGInitialCondition: This class requires a pointer to a valid FGFDMExec object" << endl; - } + InitializeIC(); - Debug(0); + if(FDMExec != NULL ) { + fdmex->GetPropagate()->SetAltitudeASL(altitudeASL); + fdmex->GetAtmosphere()->Run(); + PropertyManager=fdmex->GetPropertyManager(); + Constructing = true; + bind(); + Constructing = false; + } else { + cout << "FGInitialCondition: This class requires a pointer to a valid FGFDMExec object" << endl; + } + + Debug(0); } //****************************************************************************** FGInitialCondition::~FGInitialCondition() { - Debug(1); + Debug(1); } //****************************************************************************** @@ -105,46 +101,34 @@ void FGInitialCondition::ResetIC(double u0, double v0, double w0, double latRad0, double lonRad0, double altAGLFt0, double gamma0) { - InitializeIC(); - - u = u0; - v = v0; - w = w0; - p = p0; - q = q0; - r = r0; - alpha = alpha0; - beta = beta0; - phi = phi0; - theta = theta0; - psi = psi0; - gamma = gamma0; - - latitude = latRad0; - longitude = lonRad0; - SetAltitudeAGLFtIC(altAGLFt0); - - cphi = cos(phi); - sphi = sin(phi); // phi, rad - ctheta = cos(theta); - stheta = sin(theta); // theta, rad - cpsi = cos(psi); - spsi = sin(psi); // psi, rad - - FGQuaternion Quat( phi, theta, psi ); - Quat.Normalize(); - - const FGMatrix33& _Tl2b = Quat.GetT(); // local to body frame - const FGMatrix33& _Tb2l = Quat.GetTInv(); // body to local - - FGColumnVector3 _vUVW_BODY(u,v,w); - FGColumnVector3 _vUVW_NED = _Tb2l * _vUVW_BODY; - FGColumnVector3 _vWIND_NED(wnorth,weast,wdown); + InitializeIC(); + + u = u0; v = v0; w = w0; + p = p0; q = q0; r = r0; + alpha = alpha0; beta = beta0; + phi = phi0; theta = theta0; psi = psi0; + gamma = gamma0; + + latitude = latRad0; + longitude = lonRad0; + SetAltitudeAGLFtIC(altAGLFt0); + + cphi = cos(phi); sphi = sin(phi); // phi, rad + ctheta = cos(theta); stheta = sin(theta); // theta, rad + cpsi = cos(psi); spsi = sin(psi); // psi, rad + + FGQuaternion Quat( phi, theta, psi ); + Quat.Normalize(); + + const FGMatrix33& _Tl2b = Quat.GetT(); // local to body frame + const FGMatrix33& _Tb2l = Quat.GetTInv(); // body to local + + FGColumnVector3 _vUVW_BODY(u,v,w); + FGColumnVector3 _vUVW_NED = _Tb2l * _vUVW_BODY; + FGColumnVector3 _vWIND_NED(wnorth,weast,wdown); // FGColumnVector3 _vUVWAero = _Tl2b * ( _vUVW_NED + _vWIND_NED ); - uw=_vWIND_NED(1); - vw=_vWIND_NED(2); - ww=_vWIND_NED(3); + uw=_vWIND_NED(1); vw=_vWIND_NED(2); ww=_vWIND_NED(3); } @@ -152,453 +136,397 @@ void FGInitialCondition::ResetIC(double u0, double v0, double w0, void FGInitialCondition::InitializeIC(void) { - vt=vc=ve=vg=0; - mach=0; - alpha=beta=gamma=0; - theta=phi=psi=0; - altitudeASL=hdot=0; - latitude=longitude=0; - u=v=w=0; - p=q=r=0; - uw=vw=ww=0; - vnorth=veast=vdown=0; - wnorth=weast=wdown=0; - whead=wcross=0; - wdir=wmag=0; - lastSpeedSet=setvt; - lastWindSet=setwned; - radius_to_vehicle = sea_level_radius = fdmex->GetInertial()->GetRefRadius(); - terrain_elevation = 0; - - targetNlfIC = 1.0; - - salpha=sbeta=stheta=sphi=spsi=sgamma=0; - calpha=cbeta=ctheta=cphi=cpsi=cgamma=1; + vt=vc=ve=vg=0; + mach=0; + alpha=beta=gamma=0; + theta=phi=psi=0; + altitudeASL=hdot=0; + latitude=longitude=0; + u=v=w=0; + p=q=r=0; + uw=vw=ww=0; + vnorth=veast=vdown=0; + wnorth=weast=wdown=0; + whead=wcross=0; + wdir=wmag=0; + lastSpeedSet=setvt; + lastWindSet=setwned; + radius_to_vehicle = sea_level_radius = fdmex->GetInertial()->GetRefRadius(); + terrain_elevation = 0; + + targetNlfIC = 1.0; + + salpha=sbeta=stheta=sphi=spsi=sgamma=0; + calpha=cbeta=ctheta=cphi=cpsi=cgamma=1; } //****************************************************************************** void FGInitialCondition::WriteStateFile(int num) { - if (Constructing) return; - - string filename = fdmex->GetFullAircraftPath(); - - if (filename.empty()) - filename = "initfile.xml"; - else - filename.append("/initfile.xml"); - - ofstream outfile(filename.c_str()); - FGPropagate* Propagate = fdmex->GetPropagate(); - - if (outfile.is_open()) - { - outfile << "<?xml version=\"1.0\"?>" << endl; - outfile << "<initialize name=\"reset00\">" << endl; - outfile << " <ubody unit=\"FT/SEC\"> " << Propagate->GetUVW(eX) << " </ubody> " << endl; - outfile << " <vbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eY) << " </vbody> " << endl; - outfile << " <wbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eZ) << " </wbody> " << endl; - outfile << " <phi unit=\"DEG\"> " << Propagate->GetEuler(ePhi) << " </phi>" << endl; - outfile << " <theta unit=\"DEG\"> " << Propagate->GetEuler(eTht) << " </theta>" << endl; - outfile << " <psi unit=\"DEG\"> " << Propagate->GetEuler(ePsi) << " </psi>" << endl; - outfile << " <longitude unit=\"DEG\"> " << Propagate->GetLongitudeDeg() << " </longitude>" << endl; - outfile << " <latitude unit=\"DEG\"> " << Propagate->GetLatitudeDeg() << " </latitude>" << endl; - outfile << " <altitude unit=\"FT\"> " << Propagate->GetAltitudeASL() << " </altitude>" << endl; - outfile << "</initialize>" << endl; - outfile.close(); - } - else - { - cerr << "Could not open and/or write the state to the initial conditions file: " << filename << endl; - } + if (Constructing) return; + + string filename = fdmex->GetFullAircraftPath(); + + if (filename.empty()) + filename = "initfile.xml"; + else + filename.append("/initfile.xml"); + + ofstream outfile(filename.c_str()); + FGPropagate* Propagate = fdmex->GetPropagate(); + + if (outfile.is_open()) { + outfile << "<?xml version=\"1.0\"?>" << endl; + outfile << "<initialize name=\"reset00\">" << endl; + outfile << " <ubody unit=\"FT/SEC\"> " << Propagate->GetUVW(eX) << " </ubody> " << endl; + outfile << " <vbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eY) << " </vbody> " << endl; + outfile << " <wbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eZ) << " </wbody> " << endl; + outfile << " <phi unit=\"DEG\"> " << Propagate->GetEuler(ePhi) << " </phi>" << endl; + outfile << " <theta unit=\"DEG\"> " << Propagate->GetEuler(eTht) << " </theta>" << endl; + outfile << " <psi unit=\"DEG\"> " << Propagate->GetEuler(ePsi) << " </psi>" << endl; + outfile << " <longitude unit=\"DEG\"> " << Propagate->GetLongitudeDeg() << " </longitude>" << endl; + outfile << " <latitude unit=\"DEG\"> " << Propagate->GetLatitudeDeg() << " </latitude>" << endl; + outfile << " <altitude unit=\"FT\"> " << Propagate->GetAltitudeASL() << " </altitude>" << endl; + outfile << "</initialize>" << endl; + outfile.close(); + } else { + cerr << "Could not open and/or write the state to the initial conditions file: " << filename << endl; + } } //****************************************************************************** -void FGInitialCondition::SetVcalibratedKtsIC(double tt) -{ +void FGInitialCondition::SetVcalibratedKtsIC(double tt) { - if (getMachFromVcas(&mach,tt*ktstofps)) - { - //cout << "Mach: " << mach << endl; - lastSpeedSet=setvc; - vc=tt*ktstofps; - vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed(); - ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); - //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl; - } - else - { - cout << "Failed to get Mach number for given Vc and altitude, Vc unchanged." << endl; - cout << "Please mail the set of initial conditions used to apeden@earthlink.net" << endl; - } + if(getMachFromVcas(&mach,tt*ktstofps)) { + //cout << "Mach: " << mach << endl; + lastSpeedSet=setvc; + vc=tt*ktstofps; + vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed(); + ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); + //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl; + } + else { + cout << "Failed to get Mach number for given Vc and altitude, Vc unchanged." << endl; + cout << "Please mail the set of initial conditions used to apeden@earthlink.net" << endl; + } } //****************************************************************************** -void FGInitialCondition::SetVequivalentKtsIC(double tt) -{ - ve=tt*ktstofps; - lastSpeedSet=setve; - vt=ve*1/sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); - mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); - vc=calcVcas(mach); +void FGInitialCondition::SetVequivalentKtsIC(double tt) { + ve=tt*ktstofps; + lastSpeedSet=setve; + vt=ve*1/sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); + mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); + vc=calcVcas(mach); } //****************************************************************************** -void FGInitialCondition::SetVgroundFpsIC(double tt) -{ - double ua,va,wa; - double vxz; - - vg=tt; - lastSpeedSet=setvg; - vnorth = vg*cos(psi); - veast = vg*sin(psi); - vdown = 0; - calcUVWfromNED(); - ua = u + uw; - va = v + vw; - wa = w + ww; - vt = sqrt( ua*ua + va*va + wa*wa ); - alpha = beta = 0; - vxz = sqrt( u*u + w*w ); - if ( w != 0 ) alpha = atan2( w, u ); - if ( vxz != 0 ) beta = atan2( v, vxz ); - mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); - vc=calcVcas(mach); - ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); +void FGInitialCondition::SetVgroundFpsIC(double tt) { + double ua,va,wa; + double vxz; + + vg=tt; + lastSpeedSet=setvg; + vnorth = vg*cos(psi); veast = vg*sin(psi); vdown = 0; + calcUVWfromNED(); + ua = u + uw; va = v + vw; wa = w + ww; + vt = sqrt( ua*ua + va*va + wa*wa ); + alpha = beta = 0; + vxz = sqrt( u*u + w*w ); + if( w != 0 ) alpha = atan2( w, u ); + if( vxz != 0 ) beta = atan2( v, vxz ); + mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); + vc=calcVcas(mach); + ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); } //****************************************************************************** -void FGInitialCondition::SetVtrueFpsIC(double tt) -{ - vt=tt; - lastSpeedSet=setvt; - mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); - vc=calcVcas(mach); - ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); +void FGInitialCondition::SetVtrueFpsIC(double tt) { + vt=tt; + lastSpeedSet=setvt; + mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); + vc=calcVcas(mach); + ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); } //****************************************************************************** -void FGInitialCondition::SetMachIC(double tt) -{ - mach=tt; - lastSpeedSet=setmach; - vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed(); - vc=calcVcas(mach); - ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); - //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl; +void FGInitialCondition::SetMachIC(double tt) { + mach=tt; + lastSpeedSet=setmach; + vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed(); + vc=calcVcas(mach); + ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); + //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl; } //****************************************************************************** -void FGInitialCondition::SetClimbRateFpmIC(double tt) -{ - SetClimbRateFpsIC(tt/60.0); +void FGInitialCondition::SetClimbRateFpmIC(double tt) { + SetClimbRateFpsIC(tt/60.0); } //****************************************************************************** -void FGInitialCondition::SetClimbRateFpsIC(double tt) -{ +void FGInitialCondition::SetClimbRateFpsIC(double tt) { - if (vt > 0.1) - { - hdot=tt; - gamma=asin(hdot/vt); - sgamma=sin(gamma); - cgamma=cos(gamma); - } + if(vt > 0.1) { + hdot=tt; + gamma=asin(hdot/vt); + sgamma=sin(gamma); cgamma=cos(gamma); + } } //****************************************************************************** -void FGInitialCondition::SetFlightPathAngleRadIC(double tt) -{ - gamma=tt; - sgamma=sin(gamma); - cgamma=cos(gamma); - getTheta(); - hdot=vt*sgamma; +void FGInitialCondition::SetFlightPathAngleRadIC(double tt) { + gamma=tt; + sgamma=sin(gamma); cgamma=cos(gamma); + getTheta(); + hdot=vt*sgamma; } //****************************************************************************** -void FGInitialCondition::SetAlphaRadIC(double tt) -{ - alpha=tt; - salpha=sin(alpha); - calpha=cos(alpha); - getTheta(); +void FGInitialCondition::SetAlphaRadIC(double tt) { + alpha=tt; + salpha=sin(alpha); calpha=cos(alpha); + getTheta(); } //****************************************************************************** -void FGInitialCondition::SetThetaRadIC(double tt) -{ - theta=tt; - stheta=sin(theta); - ctheta=cos(theta); - getAlpha(); +void FGInitialCondition::SetThetaRadIC(double tt) { + theta=tt; + stheta=sin(theta); ctheta=cos(theta); + getAlpha(); } //****************************************************************************** -void FGInitialCondition::SetBetaRadIC(double tt) -{ - beta=tt; - sbeta=sin(beta); - cbeta=cos(beta); - getTheta(); +void FGInitialCondition::SetBetaRadIC(double tt) { + beta=tt; + sbeta=sin(beta); cbeta=cos(beta); + getTheta(); } //****************************************************************************** -void FGInitialCondition::SetPhiRadIC(double tt) -{ - phi=tt; - sphi=sin(phi); - cphi=cos(phi); - getTheta(); +void FGInitialCondition::SetPhiRadIC(double tt) { + phi=tt; + sphi=sin(phi); cphi=cos(phi); + getTheta(); } //****************************************************************************** -void FGInitialCondition::SetPsiRadIC(double tt) -{ +void FGInitialCondition::SetPsiRadIC(double tt) { psi=tt; - spsi=sin(psi); - cpsi=cos(psi); + spsi=sin(psi); cpsi=cos(psi); calcWindUVW(); } //****************************************************************************** -void FGInitialCondition::SetUBodyFpsIC(double tt) -{ - u=tt; - vt=sqrt(u*u + v*v + w*w); - lastSpeedSet=setuvw; +void FGInitialCondition::SetUBodyFpsIC(double tt) { + u=tt; + vt=sqrt(u*u + v*v + w*w); + lastSpeedSet=setuvw; } //****************************************************************************** -void FGInitialCondition::SetVBodyFpsIC(double tt) -{ - v=tt; - vt=sqrt(u*u + v*v + w*w); - lastSpeedSet=setuvw; +void FGInitialCondition::SetVBodyFpsIC(double tt) { + v=tt; + vt=sqrt(u*u + v*v + w*w); + lastSpeedSet=setuvw; } //****************************************************************************** -void FGInitialCondition::SetWBodyFpsIC(double tt) -{ - w=tt; - vt=sqrt( u*u + v*v + w*w ); - lastSpeedSet=setuvw; +void FGInitialCondition::SetWBodyFpsIC(double tt) { + w=tt; + vt=sqrt( u*u + v*v + w*w ); + lastSpeedSet=setuvw; } //****************************************************************************** -void FGInitialCondition::SetVNorthFpsIC(double tt) -{ - double ua,va,wa; - double vxz; - vnorth = tt; - calcUVWfromNED(); - ua = u + uw; - va = v + vw; - wa = w + ww; - vt = sqrt( ua*ua + va*va + wa*wa ); - alpha = beta = 0; - vxz = sqrt( u*u + w*w ); - if ( w != 0 ) alpha = atan2( w, u ); - if ( vxz != 0 ) beta = atan2( v, vxz ); - mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); - vc=calcVcas(mach); - ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); - lastSpeedSet=setned; +void FGInitialCondition::SetVNorthFpsIC(double tt) { + double ua,va,wa; + double vxz; + vnorth = tt; + calcUVWfromNED(); + ua = u + uw; va = v + vw; wa = w + ww; + vt = sqrt( ua*ua + va*va + wa*wa ); + alpha = beta = 0; + vxz = sqrt( u*u + w*w ); + if( w != 0 ) alpha = atan2( w, u ); + if( vxz != 0 ) beta = atan2( v, vxz ); + mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); + vc=calcVcas(mach); + ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); + lastSpeedSet=setned; } //****************************************************************************** -void FGInitialCondition::SetVEastFpsIC(double tt) -{ - double ua,va,wa; - double vxz; - veast = tt; - calcUVWfromNED(); - ua = u + uw; - va = v + vw; - wa = w + ww; - vt = sqrt( ua*ua + va*va + wa*wa ); - alpha = beta = 0; - vxz = sqrt( u*u + w*w ); - if ( w != 0 ) alpha = atan2( w, u ); - if ( vxz != 0 ) beta = atan2( v, vxz ); - mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); - vc=calcVcas(mach); - ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); - lastSpeedSet=setned; +void FGInitialCondition::SetVEastFpsIC(double tt) { + double ua,va,wa; + double vxz; + veast = tt; + calcUVWfromNED(); + ua = u + uw; va = v + vw; wa = w + ww; + vt = sqrt( ua*ua + va*va + wa*wa ); + alpha = beta = 0; + vxz = sqrt( u*u + w*w ); + if( w != 0 ) alpha = atan2( w, u ); + if( vxz != 0 ) beta = atan2( v, vxz ); + mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); + vc=calcVcas(mach); + ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); + lastSpeedSet=setned; } //****************************************************************************** -void FGInitialCondition::SetVDownFpsIC(double tt) -{ - double ua,va,wa; - double vxz; - vdown = tt; - calcUVWfromNED(); - ua = u + uw; - va = v + vw; - wa = w + ww; - vt = sqrt( ua*ua + va*va + wa*wa ); - alpha = beta = 0; - vxz = sqrt( u*u + w*w ); - if ( w != 0 ) alpha = atan2( w, u ); - if ( vxz != 0 ) beta = atan2( v, vxz ); - mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); - vc=calcVcas(mach); - ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); - SetClimbRateFpsIC(-1*vdown); - lastSpeedSet=setned; +void FGInitialCondition::SetVDownFpsIC(double tt) { + double ua,va,wa; + double vxz; + vdown = tt; + calcUVWfromNED(); + ua = u + uw; va = v + vw; wa = w + ww; + vt = sqrt( ua*ua + va*va + wa*wa ); + alpha = beta = 0; + vxz = sqrt( u*u + w*w ); + if( w != 0 ) alpha = atan2( w, u ); + if( vxz != 0 ) beta = atan2( v, vxz ); + mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); + vc=calcVcas(mach); + ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); + SetClimbRateFpsIC(-1*vdown); + lastSpeedSet=setned; } //****************************************************************************** -double FGInitialCondition::GetUBodyFpsIC(void) const -{ +double FGInitialCondition::GetUBodyFpsIC(void) const { if (lastSpeedSet == setvg || lastSpeedSet == setned) - return u; + return u; else - return vt*calpha*cbeta - uw; + return vt*calpha*cbeta - uw; } //****************************************************************************** -double FGInitialCondition::GetVBodyFpsIC(void) const -{ +double FGInitialCondition::GetVBodyFpsIC(void) const { if (lastSpeedSet == setvg || lastSpeedSet == setned) - return v; - else - { - return vt*sbeta - vw; + return v; + else { + return vt*sbeta - vw; } } //****************************************************************************** -double FGInitialCondition::GetWBodyFpsIC(void) const -{ +double FGInitialCondition::GetWBodyFpsIC(void) const { if (lastSpeedSet == setvg || lastSpeedSet == setned) - return w; + return w; else - return vt*salpha*cbeta -ww; + return vt*salpha*cbeta -ww; } //****************************************************************************** -void FGInitialCondition::SetWindNEDFpsIC(double wN, double wE, double wD ) -{ - wnorth = wN; - weast = wE; - wdown = wD; - lastWindSet = setwned; - calcWindUVW(); - if (lastSpeedSet == setvg) - SetVgroundFpsIC(vg); +void FGInitialCondition::SetWindNEDFpsIC(double wN, double wE, double wD ) { + wnorth = wN; weast = wE; wdown = wD; + lastWindSet = setwned; + calcWindUVW(); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); } //****************************************************************************** -void FGInitialCondition::SetCrossWindKtsIC(double cross) -{ +void FGInitialCondition::SetCrossWindKtsIC(double cross){ wcross=cross*ktstofps; lastWindSet=setwhc; calcWindUVW(); - if (lastSpeedSet == setvg) - SetVgroundFpsIC(vg); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); } //****************************************************************************** // positive from left -void FGInitialCondition::SetHeadWindKtsIC(double head) -{ +void FGInitialCondition::SetHeadWindKtsIC(double head){ whead=head*ktstofps; lastWindSet=setwhc; calcWindUVW(); - if (lastSpeedSet == setvg) - SetVgroundFpsIC(vg); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); } //****************************************************************************** -void FGInitialCondition::SetWindDownKtsIC(double wD) -{ +void FGInitialCondition::SetWindDownKtsIC(double wD) { wdown=wD; calcWindUVW(); - if (lastSpeedSet == setvg) - SetVgroundFpsIC(vg); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); } //****************************************************************************** -void FGInitialCondition::SetWindMagKtsIC(double mag) -{ - wmag=mag*ktstofps; - lastWindSet=setwmd; - calcWindUVW(); - if (lastSpeedSet == setvg) - SetVgroundFpsIC(vg); +void FGInitialCondition::SetWindMagKtsIC(double mag) { + wmag=mag*ktstofps; + lastWindSet=setwmd; + calcWindUVW(); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); } //****************************************************************************** -void FGInitialCondition::SetWindDirDegIC(double dir) -{ - wdir=dir*degtorad; - lastWindSet=setwmd; - calcWindUVW(); - if (lastSpeedSet == setvg) - SetVgroundFpsIC(vg); +void FGInitialCondition::SetWindDirDegIC(double dir) { + wdir=dir*degtorad; + lastWindSet=setwmd; + calcWindUVW(); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); } //****************************************************************************** -void FGInitialCondition::calcWindUVW(void) -{ +void FGInitialCondition::calcWindUVW(void) { - switch (lastWindSet) - { - case setwmd: + switch(lastWindSet) { + case setwmd: wnorth=wmag*cos(wdir); weast=wmag*sin(wdir); - break; - case setwhc: + break; + case setwhc: wnorth=whead*cos(psi) + wcross*cos(psi+M_PI/2); weast=whead*sin(psi) + wcross*sin(psi+M_PI/2); - break; - case setwned: - break; + break; + case setwned: + break; } uw=wnorth*ctheta*cpsi + weast*ctheta*spsi - wdown*stheta; vw=wnorth*( sphi*stheta*cpsi - cphi*spsi ) + - weast*( sphi*stheta*spsi + cphi*cpsi ) + + weast*( sphi*stheta*spsi + cphi*cpsi ) + wdown*sphi*ctheta; ww=wnorth*(cphi*stheta*cpsi + sphi*spsi) + weast*(cphi*stheta*spsi - sphi*cpsi) + @@ -618,376 +546,333 @@ void FGInitialCondition::calcWindUVW(void) void FGInitialCondition::SetAltitudeASLFtIC(double tt) { - altitudeASL=tt; - fdmex->GetPropagate()->SetAltitudeASL(altitudeASL); - fdmex->GetAtmosphere()->Run(); - //lets try to make sure the user gets what they intended - - switch (lastSpeedSet) - { - case setned: - case setuvw: - case setvt: - SetVtrueKtsIC(vt*fpstokts); - break; - case setvc: - SetVcalibratedKtsIC(vc*fpstokts); - break; - case setve: - SetVequivalentKtsIC(ve*fpstokts); - break; - case setmach: - SetMachIC(mach); - break; - case setvg: - SetVgroundFpsIC(vg); - break; - } + altitudeASL=tt; + fdmex->GetPropagate()->SetAltitudeASL(altitudeASL); + fdmex->GetAtmosphere()->Run(); + //lets try to make sure the user gets what they intended + + switch(lastSpeedSet) { + case setned: + case setuvw: + case setvt: + SetVtrueKtsIC(vt*fpstokts); + break; + case setvc: + SetVcalibratedKtsIC(vc*fpstokts); + break; + case setve: + SetVequivalentKtsIC(ve*fpstokts); + break; + case setmach: + SetMachIC(mach); + break; + case setvg: + SetVgroundFpsIC(vg); + break; + } } //****************************************************************************** void FGInitialCondition::SetAltitudeAGLFtIC(double tt) { - SetAltitudeASLFtIC(terrain_elevation + tt); + SetAltitudeASLFtIC(terrain_elevation + tt); } //****************************************************************************** void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt) { - sea_level_radius = tt; + sea_level_radius = tt; } //****************************************************************************** void FGInitialCondition::SetTerrainElevationFtIC(double tt) { - terrain_elevation=tt; + terrain_elevation=tt; } //****************************************************************************** void FGInitialCondition::calcUVWfromNED(void) { - u=vnorth*ctheta*cpsi + - veast*ctheta*spsi - - vdown*stheta; - v=vnorth*( sphi*stheta*cpsi - cphi*spsi ) + - veast*( sphi*stheta*spsi + cphi*cpsi ) + - vdown*sphi*ctheta; - w=vnorth*( cphi*stheta*cpsi + sphi*spsi ) + - veast*( cphi*stheta*spsi - sphi*cpsi ) + - vdown*cphi*ctheta; + u=vnorth*ctheta*cpsi + + veast*ctheta*spsi - + vdown*stheta; + v=vnorth*( sphi*stheta*cpsi - cphi*spsi ) + + veast*( sphi*stheta*spsi + cphi*cpsi ) + + vdown*sphi*ctheta; + w=vnorth*( cphi*stheta*cpsi + sphi*spsi ) + + veast*( cphi*stheta*spsi - sphi*cpsi ) + + vdown*cphi*ctheta; } //****************************************************************************** -bool FGInitialCondition::getMachFromVcas(double *Mach,double vcas) -{ - - bool result=false; - double guess=1.5; - xlo=xhi=0; - xmin=0; - xmax=50; - sfunc=&FGInitialCondition::calcVcas; - if (findInterval(vcas,guess)) - { - if (solve(&mach,vcas)) - result=true; - } - return result; +bool FGInitialCondition::getMachFromVcas(double *Mach,double vcas) { + + bool result=false; + double guess=1.5; + xlo=xhi=0; + xmin=0;xmax=50; + sfunc=&FGInitialCondition::calcVcas; + if(findInterval(vcas,guess)) { + if(solve(&mach,vcas)) + result=true; + } + return result; } //****************************************************************************** -bool FGInitialCondition::getAlpha(void) -{ - bool result=false; - double guess=theta-gamma; - - if (vt < 0.01) return 0; - - xlo=xhi=0; - xmin=fdmex->GetAerodynamics()->GetAlphaCLMin(); - xmax=fdmex->GetAerodynamics()->GetAlphaCLMax(); - sfunc=&FGInitialCondition::GammaEqOfAlpha; - if (findInterval(0,guess)) - { - if (solve(&alpha,0)) - { - result=true; - salpha=sin(alpha); - calpha=cos(alpha); - } +bool FGInitialCondition::getAlpha(void) { + bool result=false; + double guess=theta-gamma; + + if(vt < 0.01) return 0; + + xlo=xhi=0; + xmin=fdmex->GetAerodynamics()->GetAlphaCLMin(); + xmax=fdmex->GetAerodynamics()->GetAlphaCLMax(); + sfunc=&FGInitialCondition::GammaEqOfAlpha; + if(findInterval(0,guess)){ + if(solve(&alpha,0)){ + result=true; + salpha=sin(alpha); + calpha=cos(alpha); } - calcWindUVW(); - return result; + } + calcWindUVW(); + return result; } //****************************************************************************** -bool FGInitialCondition::getTheta(void) -{ - bool result=false; - double guess=alpha+gamma; - - if (vt < 0.01) return 0; - - xlo=xhi=0; - xmin=-89; - xmax=89; - sfunc=&FGInitialCondition::GammaEqOfTheta; - if (findInterval(0,guess)) - { - if (solve(&theta,0)) - { - result=true; - stheta=sin(theta); - ctheta=cos(theta); - } - } - calcWindUVW(); - return result; -} - -//****************************************************************************** +bool FGInitialCondition::getTheta(void) { + bool result=false; + double guess=alpha+gamma; -double FGInitialCondition::GammaEqOfTheta(double Theta) -{ - double a,b,c; - double sTheta,cTheta; + if(vt < 0.01) return 0; - //theta=Theta; stheta=sin(theta); ctheta=cos(theta); - sTheta=sin(Theta); - cTheta=cos(Theta); - calcWindUVW(); - a=wdown + vt*calpha*cbeta + uw; - b=vt*sphi*sbeta + vw*sphi; - c=vt*cphi*salpha*cbeta + ww*cphi; - return vt*sgamma - ( a*sTheta - (b+c)*cTheta); + xlo=xhi=0; + xmin=-89;xmax=89; + sfunc=&FGInitialCondition::GammaEqOfTheta; + if(findInterval(0,guess)){ + if(solve(&theta,0)){ + result=true; + stheta=sin(theta); + ctheta=cos(theta); + } + } + calcWindUVW(); + return result; } //****************************************************************************** -double FGInitialCondition::GammaEqOfAlpha(double Alpha) -{ - double a,b,c; - double sAlpha,cAlpha; - sAlpha=sin(Alpha); - cAlpha=cos(Alpha); - a=wdown + vt*cAlpha*cbeta + uw; - b=vt*sphi*sbeta + vw*sphi; - c=vt*cphi*sAlpha*cbeta + ww*cphi; - - return vt*sgamma - ( a*stheta - (b+c)*ctheta ); +double FGInitialCondition::GammaEqOfTheta(double Theta) { + double a,b,c; + double sTheta,cTheta; + + //theta=Theta; stheta=sin(theta); ctheta=cos(theta); + sTheta=sin(Theta); cTheta=cos(Theta); + calcWindUVW(); + a=wdown + vt*calpha*cbeta + uw; + b=vt*sphi*sbeta + vw*sphi; + c=vt*cphi*salpha*cbeta + ww*cphi; + return vt*sgamma - ( a*sTheta - (b+c)*cTheta); } //****************************************************************************** -double FGInitialCondition::calcVcas(double Mach) -{ +double FGInitialCondition::GammaEqOfAlpha(double Alpha) { + double a,b,c; + double sAlpha,cAlpha; + sAlpha=sin(Alpha); cAlpha=cos(Alpha); + a=wdown + vt*cAlpha*cbeta + uw; + b=vt*sphi*sbeta + vw*sphi; + c=vt*cphi*sAlpha*cbeta + ww*cphi; - double p=fdmex->GetAtmosphere()->GetPressure(); - double psl=fdmex->GetAtmosphere()->GetPressureSL(); - double rhosl=fdmex->GetAtmosphere()->GetDensitySL(); - double pt,A,B,D,vcas; + return vt*sgamma - ( a*stheta - (b+c)*ctheta ); +} - if (Mach < 0) Mach=0; - if (Mach < 1) //calculate total pressure assuming isentropic flow - pt=p*pow((1 + 0.2*Mach*Mach),3.5); - else - { - // shock in front of pitot tube, we'll assume its normal and use - // the Rayleigh Pitot Tube Formula, i.e. the ratio of total - // pressure behind the shock to the static pressure in front of - // the normal shock assumption should not be a bad one -- most supersonic - // aircraft place the pitot probe out front so that it is the forward - // most point on the aircraft. The real shock would, of course, take - // on something like the shape of a rounded-off cone but, here again, - // the assumption should be good since the opening of the pitot probe - // is very small and, therefore, the effects of the shock curvature - // should be small as well. AFAIK, this approach is fairly well accepted - // within the aerospace community - - B = 5.76*Mach*Mach/(5.6*Mach*Mach - 0.8); - - // The denominator above is zero for Mach ~ 0.38, for which - // we'll never be here, so we're safe - - D = (2.8*Mach*Mach-0.4)*0.4167; - pt = p*pow(B,3.5)*D; - } +//****************************************************************************** - A = pow(((pt-p)/psl+1),0.28571); - vcas = sqrt(7*psl/rhosl*(A-1)); - //cout << "calcVcas: vcas= " << vcas*fpstokts << " mach= " << Mach << " pressure: " << pt << endl; - return vcas; +double FGInitialCondition::calcVcas(double Mach) { + + double p=fdmex->GetAtmosphere()->GetPressure(); + double psl=fdmex->GetAtmosphere()->GetPressureSL(); + double rhosl=fdmex->GetAtmosphere()->GetDensitySL(); + double pt,A,B,D,vcas; + + if (Mach < 0) Mach=0; + if (Mach < 1) //calculate total pressure assuming isentropic flow + pt=p*pow((1 + 0.2*Mach*Mach),3.5); + else { + // shock in front of pitot tube, we'll assume its normal and use + // the Rayleigh Pitot Tube Formula, i.e. the ratio of total + // pressure behind the shock to the static pressure in front of + // the normal shock assumption should not be a bad one -- most supersonic + // aircraft place the pitot probe out front so that it is the forward + // most point on the aircraft. The real shock would, of course, take + // on something like the shape of a rounded-off cone but, here again, + // the assumption should be good since the opening of the pitot probe + // is very small and, therefore, the effects of the shock curvature + // should be small as well. AFAIK, this approach is fairly well accepted + // within the aerospace community + + B = 5.76*Mach*Mach/(5.6*Mach*Mach - 0.8); + + // The denominator above is zero for Mach ~ 0.38, for which + // we'll never be here, so we're safe + + D = (2.8*Mach*Mach-0.4)*0.4167; + pt = p*pow(B,3.5)*D; + } + + A = pow(((pt-p)/psl+1),0.28571); + vcas = sqrt(7*psl/rhosl*(A-1)); + //cout << "calcVcas: vcas= " << vcas*fpstokts << " mach= " << Mach << " pressure: " << pt << endl; + return vcas; } //****************************************************************************** -bool FGInitialCondition::findInterval(double x,double guess) -{ - //void find_interval(inter_params &ip,eqfunc f,double y,double constant, int &flag){ - - int i=0; - bool found=false; - double flo,fhi,fguess; - double lo,hi,step; - step=0.1; - fguess=(this->*sfunc)(guess)-x; - lo=hi=guess; - do - { - step=2*step; - lo-=step; - hi+=step; - if (lo < xmin) lo=xmin; - if (hi > xmax) hi=xmax; - i++; - flo=(this->*sfunc)(lo)-x; - fhi=(this->*sfunc)(hi)-x; - if (flo*fhi <=0) //found interval with root - { - found=true; - if (flo*fguess <= 0) //narrow interval down a bit - { - hi=lo+step; //to pass solver interval that is as - //small as possible - } - else if (fhi*fguess <= 0) - { - lo=hi-step; - } - } - //cout << "findInterval: i=" << i << " Lo= " << lo << " Hi= " << hi << endl; +bool FGInitialCondition::findInterval(double x,double guess) { + //void find_interval(inter_params &ip,eqfunc f,double y,double constant, int &flag){ + + int i=0; + bool found=false; + double flo,fhi,fguess; + double lo,hi,step; + step=0.1; + fguess=(this->*sfunc)(guess)-x; + lo=hi=guess; + do { + step=2*step; + lo-=step; + hi+=step; + if(lo < xmin) lo=xmin; + if(hi > xmax) hi=xmax; + i++; + flo=(this->*sfunc)(lo)-x; + fhi=(this->*sfunc)(hi)-x; + if(flo*fhi <=0) { //found interval with root + found=true; + if(flo*fguess <= 0) { //narrow interval down a bit + hi=lo+step; //to pass solver interval that is as + //small as possible + } + else if(fhi*fguess <= 0) { + lo=hi-step; + } } - while ((found == 0) && (i <= 100)); - xlo=lo; - xhi=hi; - return found; + //cout << "findInterval: i=" << i << " Lo= " << lo << " Hi= " << hi << endl; + } + while((found == 0) && (i <= 100)); + xlo=lo; + xhi=hi; + return found; } //****************************************************************************** bool FGInitialCondition::solve(double *y,double x) { - double x1,x2,x3,f1,f2,f3,d,d0; - double eps=1E-5; - double const relax =0.9; - int i; - bool success=false; - - //initializations - d=1; - x2 = 0; - x1=xlo; - x3=xhi; - f1=(this->*sfunc)(x1)-x; - f3=(this->*sfunc)(x3)-x; - d0=fabs(x3-x1); - - //iterations - i=0; - while ((fabs(d) > eps) && (i < 100)) - { - d=(x3-x1)/d0; - x2 = x1-d*d0*f1/(f3-f1); - - f2=(this->*sfunc)(x2)-x; - //cout << "solve x1,x2,x3: " << x1 << "," << x2 << "," << x3 << endl; - //cout << " " << f1 << "," << f2 << "," << f3 << endl; - - if (fabs(f2) <= 0.001) - { - x1=x3=x2; - } - else if (f1*f2 <= 0.0) - { - x3=x2; - f3=f2; - f1=relax*f1; - } - else if (f2*f3 <= 0) - { - x1=x2; - f1=f2; - f3=relax*f3; - } - //cout << i << endl; - i++; - }//end while - if (i < 100) - { - success=true; - *y=x2; + double x1,x2,x3,f1,f2,f3,d,d0; + double eps=1E-5; + double const relax =0.9; + int i; + bool success=false; + + //initializations + d=1; + x2 = 0; + x1=xlo;x3=xhi; + f1=(this->*sfunc)(x1)-x; + f3=(this->*sfunc)(x3)-x; + d0=fabs(x3-x1); + + //iterations + i=0; + while ((fabs(d) > eps) && (i < 100)) { + d=(x3-x1)/d0; + x2 = x1-d*d0*f1/(f3-f1); + + f2=(this->*sfunc)(x2)-x; + //cout << "solve x1,x2,x3: " << x1 << "," << x2 << "," << x3 << endl; + //cout << " " << f1 << "," << f2 << "," << f3 << endl; + + if(fabs(f2) <= 0.001) { + x1=x3=x2; + } else if(f1*f2 <= 0.0) { + x3=x2; + f3=f2; + f1=relax*f1; + } else if(f2*f3 <= 0) { + x1=x2; + f1=f2; + f3=relax*f3; } - - //cout << "Success= " << success << " Vcas: " << vcas*fpstokts << " Mach: " << x2 << endl; - return success; + //cout << i << endl; + i++; + }//end while + if(i < 100) { + success=true; + *y=x2; + } + + //cout << "Success= " << success << " Vcas: " << vcas*fpstokts << " Mach: " << x2 << endl; + return success; } //****************************************************************************** -double FGInitialCondition::GetWindDirDegIC(void) const -{ - if (weast != 0.0) - return atan2(weast,wnorth)*radtodeg; - else if (wnorth > 0) - return 0.0; - else - return 180.0; +double FGInitialCondition::GetWindDirDegIC(void) const { + if(weast != 0.0) + return atan2(weast,wnorth)*radtodeg; + else if(wnorth > 0) + return 0.0; + else + return 180.0; } //****************************************************************************** bool FGInitialCondition::Load(string rstfile, bool useStoredPath) { - string sep = "/"; - if ( useStoredPath ) - { - init_file_name = fdmex->GetFullAircraftPath() + sep + rstfile + ".xml"; - } - else - { - init_file_name = rstfile; - } - - document = LoadXMLDocument(init_file_name); - - // Make sure that the document is valid - if (!document) - { - cerr << "File: " << init_file_name << " could not be read." << endl; - exit(-1); - } - - if (document->GetName() != string("initialize")) - { - cerr << "File: " << init_file_name << " is not a reset file." << endl; - exit(-1); - } - - double version = document->GetAttributeValueAsNumber("version"); - if (version == HUGE_VAL) - { - return Load_v1(); // Default to the old version - } - else if (version >= 3.0) - { - cerr << "Only initialization file formats 1 and 2 are currently supported" << endl; - exit (-1); - } - else if (version >= 2.0) - { - return Load_v2(); - } - else if (version >= 1.0) - { - return Load_v1(); - } + string sep = "/"; + if( useStoredPath ) { + init_file_name = fdmex->GetFullAircraftPath() + sep + rstfile + ".xml"; + } else { + init_file_name = rstfile; + } + + document = LoadXMLDocument(init_file_name); + + // Make sure that the document is valid + if (!document) { + cerr << "File: " << init_file_name << " could not be read." << endl; + exit(-1); + } + + if (document->GetName() != string("initialize")) { + cerr << "File: " << init_file_name << " is not a reset file." << endl; + exit(-1); + } + + double version = document->GetAttributeValueAsNumber("version"); + if (version == HUGE_VAL) { + return Load_v1(); // Default to the old version + } else if (version >= 3.0) { + cerr << "Only initialization file formats 1 and 2 are currently supported" << endl; + exit (-1); + } else if (version >= 2.0) { + return Load_v2(); + } else if (version >= 1.0) { + return Load_v1(); + } } @@ -995,554 +880,508 @@ bool FGInitialCondition::Load(string rstfile, bool useStoredPath) bool FGInitialCondition::Load_v1(void) { - int n; - - if (document->FindElement("latitude")) - SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG")); - if (document->FindElement("longitude")) - SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG")); - if (document->FindElement("elevation")) - SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT")); - - if (document->FindElement("altitude")) // This is feet above ground level - SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT")); - else if (document->FindElement("altitudeAGL")) // This is feet above ground level - SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitudeAGL", "FT")); - else if (document->FindElement("altitudeMSL")) // This is feet above sea level - SetAltitudeASLFtIC(document->FindElementValueAsNumberConvertTo("altitudeMSL", "FT")); - - if (document->FindElement("ubody")) - SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC")); - if (document->FindElement("vbody")) - SetVBodyFpsIC(document->FindElementValueAsNumberConvertTo("vbody", "FT/SEC")); - if (document->FindElement("wbody")) - SetWBodyFpsIC(document->FindElementValueAsNumberConvertTo("wbody", "FT/SEC")); - if (document->FindElement("vnorth")) - SetVNorthFpsIC(document->FindElementValueAsNumberConvertTo("vnorth", "FT/SEC")); - if (document->FindElement("veast")) - SetVEastFpsIC(document->FindElementValueAsNumberConvertTo("veast", "FT/SEC")); - if (document->FindElement("vdown")) - SetVDownFpsIC(document->FindElementValueAsNumberConvertTo("vdown", "FT/SEC")); - if (document->FindElement("winddir")) - SetWindDirDegIC(document->FindElementValueAsNumberConvertTo("winddir", "DEG")); - if (document->FindElement("vwind")) - SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo("vwind", "KTS")); - if (document->FindElement("hwind")) - SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo("hwind", "KTS")); - if (document->FindElement("xwind")) - SetCrossWindKtsIC(document->FindElementValueAsNumberConvertTo("xwind", "KTS")); - if (document->FindElement("vc")) - SetVcalibratedKtsIC(document->FindElementValueAsNumberConvertTo("vc", "KTS")); - if (document->FindElement("vt")) - SetVtrueKtsIC(document->FindElementValueAsNumberConvertTo("vt", "KTS")); - if (document->FindElement("mach")) - SetMachIC(document->FindElementValueAsNumber("mach")); - if (document->FindElement("phi")) - SetPhiDegIC(document->FindElementValueAsNumberConvertTo("phi", "DEG")); - if (document->FindElement("theta")) - SetThetaDegIC(document->FindElementValueAsNumberConvertTo("theta", "DEG")); - if (document->FindElement("psi")) - SetPsiDegIC(document->FindElementValueAsNumberConvertTo("psi", "DEG")); - if (document->FindElement("alpha")) - SetAlphaDegIC(document->FindElementValueAsNumberConvertTo("alpha", "DEG")); - if (document->FindElement("beta")) - SetBetaDegIC(document->FindElementValueAsNumberConvertTo("beta", "DEG")); - if (document->FindElement("gamma")) - SetFlightPathAngleDegIC(document->FindElementValueAsNumberConvertTo("gamma", "DEG")); - if (document->FindElement("roc")) - SetClimbRateFpsIC(document->FindElementValueAsNumberConvertTo("roc", "FT/SEC")); - if (document->FindElement("vground")) - SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo("vground", "KTS")); - if (document->FindElement("targetNlf")) - { - SetTargetNlfIC(document->FindElementValueAsNumber("targetNlf")); - } - - // Check to see if any engines are specified to be initialized in a running state - FGPropulsion* propulsion = fdmex->GetPropulsion(); - Element* running_elements = document->FindElement("running"); - while (running_elements) - { - n = int(running_elements->GetDataAsNumber()); - propulsion->InitRunning(n); - running_elements = document->FindNextElement("running"); - } - - fdmex->RunIC(); - - return true; + int n; + + if (document->FindElement("latitude")) + SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG")); + if (document->FindElement("longitude")) + SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG")); + if (document->FindElement("elevation")) + SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT")); + + if (document->FindElement("altitude")) // This is feet above ground level + SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT")); + else if (document->FindElement("altitudeAGL")) // This is feet above ground level + SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitudeAGL", "FT")); + else if (document->FindElement("altitudeMSL")) // This is feet above sea level + SetAltitudeASLFtIC(document->FindElementValueAsNumberConvertTo("altitudeMSL", "FT")); + + if (document->FindElement("ubody")) + SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC")); + if (document->FindElement("vbody")) + SetVBodyFpsIC(document->FindElementValueAsNumberConvertTo("vbody", "FT/SEC")); + if (document->FindElement("wbody")) + SetWBodyFpsIC(document->FindElementValueAsNumberConvertTo("wbody", "FT/SEC")); + if (document->FindElement("vnorth")) + SetVNorthFpsIC(document->FindElementValueAsNumberConvertTo("vnorth", "FT/SEC")); + if (document->FindElement("veast")) + SetVEastFpsIC(document->FindElementValueAsNumberConvertTo("veast", "FT/SEC")); + if (document->FindElement("vdown")) + SetVDownFpsIC(document->FindElementValueAsNumberConvertTo("vdown", "FT/SEC")); + if (document->FindElement("winddir")) + SetWindDirDegIC(document->FindElementValueAsNumberConvertTo("winddir", "DEG")); + if (document->FindElement("vwind")) + SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo("vwind", "KTS")); + if (document->FindElement("hwind")) + SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo("hwind", "KTS")); + if (document->FindElement("xwind")) + SetCrossWindKtsIC(document->FindElementValueAsNumberConvertTo("xwind", "KTS")); + if (document->FindElement("vc")) + SetVcalibratedKtsIC(document->FindElementValueAsNumberConvertTo("vc", "KTS")); + if (document->FindElement("vt")) + SetVtrueKtsIC(document->FindElementValueAsNumberConvertTo("vt", "KTS")); + if (document->FindElement("mach")) + SetMachIC(document->FindElementValueAsNumber("mach")); + if (document->FindElement("phi")) + SetPhiDegIC(document->FindElementValueAsNumberConvertTo("phi", "DEG")); + if (document->FindElement("theta")) + SetThetaDegIC(document->FindElementValueAsNumberConvertTo("theta", "DEG")); + if (document->FindElement("psi")) + SetPsiDegIC(document->FindElementValueAsNumberConvertTo("psi", "DEG")); + if (document->FindElement("alpha")) + SetAlphaDegIC(document->FindElementValueAsNumberConvertTo("alpha", "DEG")); + if (document->FindElement("beta")) + SetBetaDegIC(document->FindElementValueAsNumberConvertTo("beta", "DEG")); + if (document->FindElement("gamma")) + SetFlightPathAngleDegIC(document->FindElementValueAsNumberConvertTo("gamma", "DEG")); + if (document->FindElement("roc")) + SetClimbRateFpsIC(document->FindElementValueAsNumberConvertTo("roc", "FT/SEC")); + if (document->FindElement("vground")) + SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo("vground", "KTS")); + if (document->FindElement("targetNlf")) + { + SetTargetNlfIC(document->FindElementValueAsNumber("targetNlf")); + } + + // Check to see if any engines are specified to be initialized in a running state + FGPropulsion* propulsion = fdmex->GetPropulsion(); + Element* running_elements = document->FindElement("running"); + while (running_elements) { + n = int(running_elements->GetDataAsNumber()); + propulsion->InitRunning(n); + running_elements = document->FindNextElement("running"); + } + + fdmex->RunIC(); + + return true; } //****************************************************************************** bool FGInitialCondition::Load_v2(void) { - int n; - FGColumnVector3 vLoc, vOrient; - bool result = true; - FGInertial* Inertial = fdmex->GetInertial(); - FGPropagate* Propagate = fdmex->GetPropagate(); - - if (document->FindElement("earth_position_angle")) - { - double epa = document->FindElementValueAsNumberConvertTo("earth_position_angle", "RAD"); - Inertial->SetEarthPositionAngle(epa); - } - - // Initialize vehicle position - // - // Allowable frames: - // - ECI (Earth Centered Inertial) - // - ECEF (Earth Centered, Earth Fixed) - - Element* position = document->FindElement("position"); - if (position) - { - vLoc = position->FindElementTripletConvertTo("FT"); - string frame = position->GetAttributeValue("frame"); - frame = to_lower(frame); - if (frame == "eci") - { - // Need to transform vLoc to ECEF for storage and use in FGLocation. - vLoc = Propagate->GetTi2ec()*vLoc; - } - else if (frame == "ecef") - { - // Move vLoc query until after lat/lon/alt query to eliminate spurious warning msgs. - if (vLoc.Magnitude() == 0.0) - { - Propagate->SetLatitudeDeg(position->FindElementValueAsNumberConvertTo("latitude", "DEG")); - Propagate->SetLongitudeDeg(position->FindElementValueAsNumberConvertTo("longitude", "DEG")); - if (position->FindElement("radius")) - { - radius_to_vehicle = position->FindElementValueAsNumberConvertTo("radius", "FT"); - SetAltitudeASLFtIC(radius_to_vehicle - sea_level_radius); - } - else if (position->FindElement("altitudeAGL")) - { - SetAltitudeAGLFtIC(position->FindElementValueAsNumberConvertTo("altitudeAGL", "FT")); - } - else if (position->FindElement("altitudeMSL")) - { - SetAltitudeASLFtIC(position->FindElementValueAsNumberConvertTo("altitudeMSL", "FT")); - } - else - { - cerr << endl << " No altitude or radius initial condition is given." << endl; - result = false; - } - } - } - else - { - cerr << endl << " Neither ECI nor ECEF frame is specified for initial position." << endl; - result = false; + int n; + FGColumnVector3 vLoc, vOrient; + bool result = true; + FGInertial* Inertial = fdmex->GetInertial(); + FGPropagate* Propagate = fdmex->GetPropagate(); + FGColumnVector3 vOmegaEarth = FGColumnVector3(0.0, 0.0, Inertial->omega()); + + if (document->FindElement("earth_position_angle")) { + double epa = document->FindElementValueAsNumberConvertTo("earth_position_angle", "RAD"); + Inertial->SetEarthPositionAngle(epa); + Propagate->GetVState()->vLocation.SetEarthPositionAngle(epa); + } + + Propagate->SetSeaLevelRadius(GetSeaLevelRadiusFtIC()); + + if (document->FindElement("elevation")) { + SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT")); + Propagate->SetTerrainElevation(terrain_elevation); + } + + // Initialize vehicle position + // + // Allowable frames: + // - ECI (Earth Centered Inertial) + // - ECEF (Earth Centered, Earth Fixed) + + Element* position = document->FindElement("position"); + if (position) { + vLoc = position->FindElementTripletConvertTo("FT"); + string frame = position->GetAttributeValue("frame"); + frame = to_lower(frame); + if (frame == "eci") { // Need to transform vLoc to ECEF for storage and use in FGLocation. + vLoc = Propagate->GetTi2ec()*vLoc; + Propagate->SetLocation(vLoc); + } else if (frame == "ecef") { + double AltitudeASL = 0.0; + if (vLoc.Magnitude() == 0.0) { + if (position->FindElement("radius")) { + AltitudeASL = position->FindElementValueAsNumberConvertTo("radius", "FT") - sea_level_radius; + } else if (position->FindElement("altitudeAGL")) { + AltitudeASL = terrain_elevation + position->FindElementValueAsNumberConvertTo("altitudeAGL", "FT"); + } else if (position->FindElement("altitudeMSL")) { + AltitudeASL = position->FindElementValueAsNumberConvertTo("altitudeMSL", "FT"); + } else { + cerr << endl << " No altitude or radius initial condition is given." << endl; + result = false; } + Propagate->SetPosition( + position->FindElementValueAsNumberConvertTo("longitude", "RAD"), + position->FindElementValueAsNumberConvertTo("latitude", "RAD"), + AltitudeASL + GetSeaLevelRadiusFtIC()); + } else { + Propagate->SetLocation(vLoc); + } + } else { + cerr << endl << " Neither ECI nor ECEF frame is specified for initial position." << endl; + result = false; } - else - { - cerr << endl << " Initial position not specified in this initialization file." << endl; - result = false; - } - - // End of position initialization - - // Initialize vehicle orientation - // Allowable frames - // - ECI (Earth Centered Inertial) - // - ECEF (Earth Centered, Earth Fixed) - // - Local - // - // Need to convert the provided orientation to an ECI orientation, using - // the given orientation and knowledge of the Earth position angle. - // This could be done using matrices (where in the subscript "b/a", - // it is meant "b with respect to a", and where b=body frame, - // i=inertial frame, and e=ecef frame) as: - // - // C_b/i = C_b/e * C_e/i - // - // Using quaternions (note reverse ordering compared to matrix representation): - // - // Q_b/i = Q_e/i * Q_b/e - // - // Use the specific matrices as needed. The above example of course is for the whole - // body to inertial orientation. - // The new orientation angles can be extracted from the matrix or the quaternion. - // ToDo: Do we need to deal with normalization of the quaternions here? - - Element* orientation_el = document->FindElement("orientation"); - if (orientation_el) - { - string frame = orientation_el->GetAttributeValue("frame"); - frame = to_lower(frame); - vOrient = orientation_el->FindElementTripletConvertTo("RAD"); - FGQuaternion QuatI2Body; - if (frame == "eci") - { - - QuatI2Body = FGQuaternion(vOrient); + } else { + cerr << endl << " Initial position not specified in this initialization file." << endl; + result = false; + } + + // End of position initialization + + // Initialize vehicle orientation + // Allowable frames + // - ECI (Earth Centered Inertial) + // - ECEF (Earth Centered, Earth Fixed) + // - Local + // + // Need to convert the provided orientation to an ECI orientation, using + // the given orientation and knowledge of the Earth position angle. + // This could be done using matrices (where in the subscript "b/a", + // it is meant "b with respect to a", and where b=body frame, + // i=inertial frame, and e=ecef frame) as: + // + // C_b/i = C_b/e * C_e/i + // + // Using quaternions (note reverse ordering compared to matrix representation): + // + // Q_b/i = Q_e/i * Q_b/e + // + // Use the specific matrices as needed. The above example of course is for the whole + // body to inertial orientation. + // The new orientation angles can be extracted from the matrix or the quaternion. + // ToDo: Do we need to deal with normalization of the quaternions here? + + Element* orientation_el = document->FindElement("orientation"); + FGQuaternion QuatI2Body; + if (orientation_el) { + string frame = orientation_el->GetAttributeValue("frame"); + frame = to_lower(frame); + vOrient = orientation_el->FindElementTripletConvertTo("RAD"); + if (frame == "eci") { + + QuatI2Body = FGQuaternion(vOrient); + + } else if (frame == "ecef") { + + // In this case we are given the Euler angles representing the orientation of + // the body with respect to the ECEF system, represented by the C_b/e Matrix. + // We want the body orientation with respect to the inertial system: + // + // C_b/i = C_b/e * C_e/i + // + // Using quaternions (note reverse ordering compared to matrix representation): + // + // Q_b/i = Q_e/i * Q_b/e + + FGQuaternion QuatEC2Body(vOrient); // Store relationship of Body frame wrt ECEF frame, Q_b/e + FGQuaternion QuatI2EC = Propagate->GetTi2ec(); // Get Q_e/i from matrix + QuatI2Body = QuatI2EC * QuatEC2Body; // Q_b/i = Q_e/i * Q_b/e + + } else if (frame == "local") { + + // In this case, we are supplying the Euler angles for the vehicle with + // respect to the local (NED frame), also called the navigation frame. + // This is the most common way of initializing the orientation of + // aircraft. The matrix representation is: + // + // C_b/i = C_b/n * C_n/e * C_e/i + // + // Or, using quaternions (note reverse ordering compared to matrix representation): + // + // Q_b/i = Q_e/i * Q_n/e * Q_b/n + + FGQuaternion QuatLocal2Body = FGQuaternion(vOrient); // Store relationship of Body frame wrt local (NED) frame, Q_b/n + FGQuaternion QuatEC2Local = Propagate->GetTec2l(); // Get Q_n/e from matrix + FGQuaternion QuatI2EC = Propagate->GetTi2ec(); // Get Q_e/i from matrix + QuatI2Body = QuatI2EC * QuatEC2Local * QuatLocal2Body; // Q_b/i = Q_e/i * Q_n/e * Q_b/n + + } else { + + cerr << endl << fgred << " Orientation frame type: \"" << frame + << "\" is not supported!" << reset << endl << endl; + result = false; - } - else if (frame == "ecef") - { - - // In this case we are given the Euler angles representing the orientation of - // the body with respect to the ECEF system, represented by the C_b/e Matrix. - // We want the body orientation with respect to the inertial system: - // - // C_b/i = C_b/e * C_e/i - // - // Using quaternions (note reverse ordering compared to matrix representation): - // - // Q_b/i = Q_e/i * Q_b/e - - FGQuaternion QuatEC2Body(vOrient); // Store relationship of Body frame wrt ECEF frame, Q_b/e - FGQuaternion QuatI2EC = Propagate->GetTi2ec(); // Get Q_e/i from matrix - QuatI2Body = QuatI2EC * QuatEC2Body; // Q_b/i = Q_e/i * Q_b/e - - } - else if (frame == "local") - { - - // In this case, we are supplying the Euler angles for the vehicle with - // respect to the local (NED frame), also called the navigation frame. - // This is the most common way of initializing the orientation of - // aircraft. The matrix representation is: - // - // C_b/i = C_b/n * C_n/e * C_e/i - // - // Or, using quaternions (note reverse ordering compared to matrix representation): - // - // Q_b/i = Q_e/i * Q_n/e * Q_b/n - - FGQuaternion QuatLocal2Body = FGQuaternion(vOrient); // Store relationship of Body frame wrt local (NED) frame, Q_b/n - FGQuaternion QuatEC2Local = Propagate->GetTec2l(); // Get Q_n/e from matrix - FGQuaternion QuatI2EC = Propagate->GetTi2ec(); // Get Q_e/i from matrix - QuatI2Body = QuatI2EC * QuatEC2Local * QuatLocal2Body; // Q_b/i = Q_e/i * Q_n/e * Q_b/n - - } - else - { - - cerr << endl << fgred << " Orientation frame type: \"" << frame - << "\" is not supported!" << reset << endl << endl; - result = false; - - } - - Propagate->SetInertialOrientation(QuatI2Body); } + } + + Propagate->SetInertialOrientation(QuatI2Body); + + // Initialize vehicle velocity + // Allowable frames + // - ECI (Earth Centered Inertial) + // - ECEF (Earth Centered, Earth Fixed) + // - Local + // - Body + // The vehicle will be defaulted to (0,0,0) in the Body frame if nothing is provided. + + Element* velocity_el = document->FindElement("velocity"); + FGColumnVector3 vInertialVelocity; + FGColumnVector3 vInitVelocity = FGColumnVector3(0.0, 0.0, 0.0); + FGColumnVector3 omega_cross_r = vOmegaEarth * Propagate->GetInertialPosition(); + FGMatrix33 mTl2i = Propagate->GetTl2i(); + FGMatrix33 mTec2i = Propagate->GetTec2i(); // Get C_i/e + FGMatrix33 mTb2i = Propagate->GetTb2i(); + if (velocity_el) { + + string frame = velocity_el->GetAttributeValue("frame"); + frame = to_lower(frame); + FGColumnVector3 vInitVelocity = velocity_el->FindElementTripletConvertTo("FT/SEC"); + + if (frame == "eci") { + vInertialVelocity = vInitVelocity; + } else if (frame == "ecef") { + vInertialVelocity = mTec2i * vInitVelocity + omega_cross_r; + } else if (frame == "local") { + vInertialVelocity = mTl2i * vInitVelocity + omega_cross_r; + } else if (frame == "body") { + vInertialVelocity = mTb2i * vInitVelocity + omega_cross_r; + } else { + + cerr << endl << fgred << " Velocity frame type: \"" << frame + << "\" is not supported!" << reset << endl << endl; + result = false; - // Initialize vehicle velocity - // Allowable frames - // - ECI (Earth Centered Inertial) - // - ECEF (Earth Centered, Earth Fixed) - // - Local - // - Body - // The vehicle will be defaulted to (0,0,0) in the Body frame if nothing is provided. - - Element* velocity_el = document->FindElement("velocity"); - FGColumnVector3 vInertialVelocity; - FGColumnVector3 vInitVelocity = FGColumnVector3(0.0, 0.0, 0.0); - if (velocity_el) - { - - string frame = velocity_el->GetAttributeValue("frame"); - frame = to_lower(frame); - FGColumnVector3 vInitVelocity = velocity_el->FindElementTripletConvertTo("FT/SEC"); - FGColumnVector3 omega_cross_r = Inertial->omega() * Propagate->GetInertialPosition(); - - if (frame == "eci") - { - vInertialVelocity = vInitVelocity; - } - else if (frame == "ecef") - { - FGMatrix33 mTec2i = Propagate->GetTec2i(); // Get C_i/e - vInertialVelocity = mTec2i * vInitVelocity + omega_cross_r; - } - else if (frame == "local") - { - FGMatrix33 mTl2i = Propagate->GetTl2i(); - vInertialVelocity = mTl2i * vInitVelocity + omega_cross_r; - } - else if (frame == "body") - { - FGMatrix33 mTb2i = Propagate->GetTb2i(); - vInertialVelocity = mTb2i * vInitVelocity + omega_cross_r; - } - else - { - - cerr << endl << fgred << " Velocity frame type: \"" << frame - << "\" is not supported!" << reset << endl << endl; - result = false; - - } - - } - else - { - - FGMatrix33 mTb2i = Propagate->GetTb2i(); - vInertialVelocity = mTb2i * vInitVelocity + (Inertial->omega() * Propagate->GetInertialPosition()); - - } - - Propagate->SetInertialVelocity(vInertialVelocity); - - // Allowable frames - // - ECI (Earth Centered Inertial) - // - ECEF (Earth Centered, Earth Fixed) - // - Body - - FGColumnVector3 vInertialRate; - Element* attrate_el = document->FindElement("attitude_rate"); - if (attrate_el) - { - - string frame = attrate_el->GetAttributeValue("frame"); - frame = to_lower(frame); - FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo("RAD/SEC"); - - if (frame == "eci") - { - vInertialRate = vAttRate; - } - else if (frame == "ecef") - { -// vInertialRate = vAttRate + Inertial->omega(); - } - else if (frame == "body") - { - //Todo: determine local frame rate - FGMatrix33 mTb2l = Propagate->GetTb2l(); -// vInertialRate = mTb2l*vAttRate + Inertial->omega(); - } - else if (!frame.empty()) // misspelling of frame - { - - cerr << endl << fgred << " Attitude rate frame type: \"" << frame - << "\" is not supported!" << reset << endl << endl; - result = false; - - } - else if (frame.empty()) - { - - } - - } - else // Body frame attitude rate assumed 0 relative to local. - { - /* - //Todo: determine local frame rate - - FGMatrix33 mTi2l = Propagate->GetTi2l(); - vVel = mTi2l * vInertialVelocity; - - // Compute the local frame ECEF velocity - vVel = Tb2l * VState.vUVW; - - FGColumnVector3 vOmegaLocal = FGColumnVector3( - radInv*vVel(eEast), - -radInv*vVel(eNorth), - -radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() ); - */ } - // Check to see if any engines are specified to be initialized in a running state - FGPropulsion* propulsion = fdmex->GetPropulsion(); - Element* running_elements = document->FindElement("running"); - while (running_elements) - { - n = int(running_elements->GetDataAsNumber()); - propulsion->InitRunning(n); - running_elements = document->FindNextElement("running"); + } else { + + vInertialVelocity = mTb2i * vInitVelocity + omega_cross_r; + + } + + Propagate->SetInertialVelocity(vInertialVelocity); + + // Initialize vehicle body rates + // Allowable frames + // - ECI (Earth Centered Inertial) + // - ECEF (Earth Centered, Earth Fixed) + // - Body + + FGColumnVector3 vInertialRate; + Element* attrate_el = document->FindElement("attitude_rate"); + double radInv = 1.0/Propagate->GetRadius(); + FGColumnVector3 vVel = Propagate->GetVel(); + FGColumnVector3 vOmegaLocal = FGColumnVector3( + radInv*vVel(eEast), + -radInv*vVel(eNorth), + -radInv*vVel(eEast)*Propagate->GetLocation().GetTanLatitude() ); + + if (attrate_el) { + + string frame = attrate_el->GetAttributeValue("frame"); + frame = to_lower(frame); + FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo("RAD/SEC"); + + if (frame == "eci") { + vInertialRate = vAttRate; + } else if (frame == "ecef") { + vInertialRate = vAttRate + vOmegaEarth; + } else if (frame == "local") { + vInertialRate = vOmegaEarth + Propagate->GetTl2i() * vOmegaLocal + Propagate->GetTb2i() * vAttRate; + } else if (!frame.empty()) { // misspelling of frame + + cerr << endl << fgred << " Attitude rate frame type: \"" << frame + << "\" is not supported!" << reset << endl << endl; + result = false; + + } else if (frame.empty()) { + } - - // fdmex->RunIC(); - - return result; + + } else { // Body frame attitude rate assumed 0 relative to local. + vInertialRate = vOmegaEarth + Propagate->GetTl2i() * vOmegaLocal; + } + Propagate->SetInertialRates(vInertialRate); + Propagate->InitializeDerivatives(); + + // Check to see if any engines are specified to be initialized in a running state + FGPropulsion* propulsion = fdmex->GetPropulsion(); + Element* running_elements = document->FindElement("running"); + while (running_elements) { + n = int(running_elements->GetDataAsNumber()); + propulsion->InitRunning(n); + running_elements = document->FindNextElement("running"); + } + + // fdmex->RunIC(); + + return result; } //****************************************************************************** -void FGInitialCondition::bind(void) -{ - PropertyManager->Tie("ic/vc-kts", this, - &FGInitialCondition::GetVcalibratedKtsIC, - &FGInitialCondition::SetVcalibratedKtsIC, - true); - PropertyManager->Tie("ic/ve-kts", this, - &FGInitialCondition::GetVequivalentKtsIC, - &FGInitialCondition::SetVequivalentKtsIC, - true); - PropertyManager->Tie("ic/vg-kts", this, - &FGInitialCondition::GetVgroundKtsIC, - &FGInitialCondition::SetVgroundKtsIC, - true); - PropertyManager->Tie("ic/vt-kts", this, - &FGInitialCondition::GetVtrueKtsIC, - &FGInitialCondition::SetVtrueKtsIC, - true); - PropertyManager->Tie("ic/mach", this, - &FGInitialCondition::GetMachIC, - &FGInitialCondition::SetMachIC, - true); - PropertyManager->Tie("ic/roc-fpm", this, - &FGInitialCondition::GetClimbRateFpmIC, - &FGInitialCondition::SetClimbRateFpmIC, - true); - PropertyManager->Tie("ic/gamma-deg", this, - &FGInitialCondition::GetFlightPathAngleDegIC, - &FGInitialCondition::SetFlightPathAngleDegIC, - true); - PropertyManager->Tie("ic/alpha-deg", this, - &FGInitialCondition::GetAlphaDegIC, - &FGInitialCondition::SetAlphaDegIC, - true); - PropertyManager->Tie("ic/beta-deg", this, - &FGInitialCondition::GetBetaDegIC, - &FGInitialCondition::SetBetaDegIC, - true); - PropertyManager->Tie("ic/theta-deg", this, - &FGInitialCondition::GetThetaDegIC, - &FGInitialCondition::SetThetaDegIC, - true); - PropertyManager->Tie("ic/phi-deg", this, - &FGInitialCondition::GetPhiDegIC, - &FGInitialCondition::SetPhiDegIC, - true); - PropertyManager->Tie("ic/psi-true-deg", this, - &FGInitialCondition::GetPsiDegIC ); - PropertyManager->Tie("ic/lat-gc-deg", this, - &FGInitialCondition::GetLatitudeDegIC, - &FGInitialCondition::SetLatitudeDegIC, - true); - PropertyManager->Tie("ic/long-gc-deg", this, - &FGInitialCondition::GetLongitudeDegIC, - &FGInitialCondition::SetLongitudeDegIC, - true); - PropertyManager->Tie("ic/h-sl-ft", this, - &FGInitialCondition::GetAltitudeASLFtIC, - &FGInitialCondition::SetAltitudeASLFtIC, - true); - PropertyManager->Tie("ic/h-agl-ft", this, - &FGInitialCondition::GetAltitudeAGLFtIC, - &FGInitialCondition::SetAltitudeAGLFtIC, - true); - PropertyManager->Tie("ic/sea-level-radius-ft", this, - &FGInitialCondition::GetSeaLevelRadiusFtIC, - &FGInitialCondition::SetSeaLevelRadiusFtIC, - true); - PropertyManager->Tie("ic/terrain-elevation-ft", this, - &FGInitialCondition::GetTerrainElevationFtIC, - &FGInitialCondition::SetTerrainElevationFtIC, - true); - PropertyManager->Tie("ic/vg-fps", this, - &FGInitialCondition::GetVgroundFpsIC, - &FGInitialCondition::SetVgroundFpsIC, - true); - PropertyManager->Tie("ic/vt-fps", this, - &FGInitialCondition::GetVtrueFpsIC, - &FGInitialCondition::SetVtrueFpsIC, - true); - PropertyManager->Tie("ic/vw-bx-fps", this, - &FGInitialCondition::GetWindUFpsIC); - PropertyManager->Tie("ic/vw-by-fps", this, - &FGInitialCondition::GetWindVFpsIC); - PropertyManager->Tie("ic/vw-bz-fps", this, - &FGInitialCondition::GetWindWFpsIC); - PropertyManager->Tie("ic/vw-north-fps", this, - &FGInitialCondition::GetWindNFpsIC); - PropertyManager->Tie("ic/vw-east-fps", this, - &FGInitialCondition::GetWindEFpsIC); - PropertyManager->Tie("ic/vw-down-fps", this, - &FGInitialCondition::GetWindDFpsIC); - PropertyManager->Tie("ic/vw-mag-fps", this, - &FGInitialCondition::GetWindFpsIC); - PropertyManager->Tie("ic/vw-dir-deg", this, - &FGInitialCondition::GetWindDirDegIC, - &FGInitialCondition::SetWindDirDegIC, - true); - - PropertyManager->Tie("ic/roc-fps", this, - &FGInitialCondition::GetClimbRateFpsIC, - &FGInitialCondition::SetClimbRateFpsIC, - true); - PropertyManager->Tie("ic/u-fps", this, - &FGInitialCondition::GetUBodyFpsIC, - &FGInitialCondition::SetUBodyFpsIC, - true); - PropertyManager->Tie("ic/v-fps", this, - &FGInitialCondition::GetVBodyFpsIC, - &FGInitialCondition::SetVBodyFpsIC, - true); - PropertyManager->Tie("ic/w-fps", this, - &FGInitialCondition::GetWBodyFpsIC, - &FGInitialCondition::SetWBodyFpsIC, - true); - PropertyManager->Tie("ic/vn-fps", this, - &FGInitialCondition::GetVNorthFpsIC, - &FGInitialCondition::SetVNorthFpsIC, - true); - PropertyManager->Tie("ic/ve-fps", this, - &FGInitialCondition::GetVEastFpsIC, - &FGInitialCondition::SetVEastFpsIC, - true); - PropertyManager->Tie("ic/vd-fps", this, - &FGInitialCondition::GetVDownFpsIC, - &FGInitialCondition::SetVDownFpsIC, - true); - PropertyManager->Tie("ic/gamma-rad", this, - &FGInitialCondition::GetFlightPathAngleRadIC, - &FGInitialCondition::SetFlightPathAngleRadIC, - true); - PropertyManager->Tie("ic/alpha-rad", this, - &FGInitialCondition::GetAlphaRadIC, - &FGInitialCondition::SetAlphaRadIC, - true); - PropertyManager->Tie("ic/theta-rad", this, - &FGInitialCondition::GetThetaRadIC, - &FGInitialCondition::SetThetaRadIC, - true); - PropertyManager->Tie("ic/beta-rad", this, - &FGInitialCondition::GetBetaRadIC, - &FGInitialCondition::SetBetaRadIC, - true); - PropertyManager->Tie("ic/phi-rad", this, - &FGInitialCondition::GetPhiRadIC, - &FGInitialCondition::SetPhiRadIC, - true); - PropertyManager->Tie("ic/psi-true-rad", this, - &FGInitialCondition::GetPsiRadIC); - PropertyManager->Tie("ic/lat-gc-rad", this, - &FGInitialCondition::GetLatitudeRadIC, - &FGInitialCondition::SetLatitudeRadIC, - true); - PropertyManager->Tie("ic/long-gc-rad", this, - &FGInitialCondition::GetLongitudeRadIC, - &FGInitialCondition::SetLongitudeRadIC, - true); - PropertyManager->Tie("ic/p-rad_sec", this, - &FGInitialCondition::GetPRadpsIC, - &FGInitialCondition::SetPRadpsIC, - true); - PropertyManager->Tie("ic/q-rad_sec", this, - &FGInitialCondition::GetQRadpsIC, - &FGInitialCondition::SetQRadpsIC, - true); - PropertyManager->Tie("ic/r-rad_sec", this, - &FGInitialCondition::GetRRadpsIC, - &FGInitialCondition::SetRRadpsIC, - true); - - typedef int (FGInitialCondition::*iPMF)(void) const; - PropertyManager->Tie("simulation/write-state-file", - this, - (iPMF)0, - &FGInitialCondition::WriteStateFile); +void FGInitialCondition::bind(void){ + PropertyManager->Tie("ic/vc-kts", this, + &FGInitialCondition::GetVcalibratedKtsIC, + &FGInitialCondition::SetVcalibratedKtsIC, + true); + PropertyManager->Tie("ic/ve-kts", this, + &FGInitialCondition::GetVequivalentKtsIC, + &FGInitialCondition::SetVequivalentKtsIC, + true); + PropertyManager->Tie("ic/vg-kts", this, + &FGInitialCondition::GetVgroundKtsIC, + &FGInitialCondition::SetVgroundKtsIC, + true); + PropertyManager->Tie("ic/vt-kts", this, + &FGInitialCondition::GetVtrueKtsIC, + &FGInitialCondition::SetVtrueKtsIC, + true); + PropertyManager->Tie("ic/mach", this, + &FGInitialCondition::GetMachIC, + &FGInitialCondition::SetMachIC, + true); + PropertyManager->Tie("ic/roc-fpm", this, + &FGInitialCondition::GetClimbRateFpmIC, + &FGInitialCondition::SetClimbRateFpmIC, + true); + PropertyManager->Tie("ic/gamma-deg", this, + &FGInitialCondition::GetFlightPathAngleDegIC, + &FGInitialCondition::SetFlightPathAngleDegIC, + true); + PropertyManager->Tie("ic/alpha-deg", this, + &FGInitialCondition::GetAlphaDegIC, + &FGInitialCondition::SetAlphaDegIC, + true); + PropertyManager->Tie("ic/beta-deg", this, + &FGInitialCondition::GetBetaDegIC, + &FGInitialCondition::SetBetaDegIC, + true); + PropertyManager->Tie("ic/theta-deg", this, + &FGInitialCondition::GetThetaDegIC, + &FGInitialCondition::SetThetaDegIC, + true); + PropertyManager->Tie("ic/phi-deg", this, + &FGInitialCondition::GetPhiDegIC, + &FGInitialCondition::SetPhiDegIC, + true); + PropertyManager->Tie("ic/psi-true-deg", this, + &FGInitialCondition::GetPsiDegIC ); + PropertyManager->Tie("ic/lat-gc-deg", this, + &FGInitialCondition::GetLatitudeDegIC, + &FGInitialCondition::SetLatitudeDegIC, + true); + PropertyManager->Tie("ic/long-gc-deg", this, + &FGInitialCondition::GetLongitudeDegIC, + &FGInitialCondition::SetLongitudeDegIC, + true); + PropertyManager->Tie("ic/h-sl-ft", this, + &FGInitialCondition::GetAltitudeASLFtIC, + &FGInitialCondition::SetAltitudeASLFtIC, + true); + PropertyManager->Tie("ic/h-agl-ft", this, + &FGInitialCondition::GetAltitudeAGLFtIC, + &FGInitialCondition::SetAltitudeAGLFtIC, + true); + PropertyManager->Tie("ic/sea-level-radius-ft", this, + &FGInitialCondition::GetSeaLevelRadiusFtIC, + &FGInitialCondition::SetSeaLevelRadiusFtIC, + true); + PropertyManager->Tie("ic/terrain-elevation-ft", this, + &FGInitialCondition::GetTerrainElevationFtIC, + &FGInitialCondition::SetTerrainElevationFtIC, + true); + PropertyManager->Tie("ic/vg-fps", this, + &FGInitialCondition::GetVgroundFpsIC, + &FGInitialCondition::SetVgroundFpsIC, + true); + PropertyManager->Tie("ic/vt-fps", this, + &FGInitialCondition::GetVtrueFpsIC, + &FGInitialCondition::SetVtrueFpsIC, + true); + PropertyManager->Tie("ic/vw-bx-fps", this, + &FGInitialCondition::GetWindUFpsIC); + PropertyManager->Tie("ic/vw-by-fps", this, + &FGInitialCondition::GetWindVFpsIC); + PropertyManager->Tie("ic/vw-bz-fps", this, + &FGInitialCondition::GetWindWFpsIC); + PropertyManager->Tie("ic/vw-north-fps", this, + &FGInitialCondition::GetWindNFpsIC); + PropertyManager->Tie("ic/vw-east-fps", this, + &FGInitialCondition::GetWindEFpsIC); + PropertyManager->Tie("ic/vw-down-fps", this, + &FGInitialCondition::GetWindDFpsIC); + PropertyManager->Tie("ic/vw-mag-fps", this, + &FGInitialCondition::GetWindFpsIC); + PropertyManager->Tie("ic/vw-dir-deg", this, + &FGInitialCondition::GetWindDirDegIC, + &FGInitialCondition::SetWindDirDegIC, + true); + + PropertyManager->Tie("ic/roc-fps", this, + &FGInitialCondition::GetClimbRateFpsIC, + &FGInitialCondition::SetClimbRateFpsIC, + true); + PropertyManager->Tie("ic/u-fps", this, + &FGInitialCondition::GetUBodyFpsIC, + &FGInitialCondition::SetUBodyFpsIC, + true); + PropertyManager->Tie("ic/v-fps", this, + &FGInitialCondition::GetVBodyFpsIC, + &FGInitialCondition::SetVBodyFpsIC, + true); + PropertyManager->Tie("ic/w-fps", this, + &FGInitialCondition::GetWBodyFpsIC, + &FGInitialCondition::SetWBodyFpsIC, + true); + PropertyManager->Tie("ic/vn-fps", this, + &FGInitialCondition::GetVNorthFpsIC, + &FGInitialCondition::SetVNorthFpsIC, + true); + PropertyManager->Tie("ic/ve-fps", this, + &FGInitialCondition::GetVEastFpsIC, + &FGInitialCondition::SetVEastFpsIC, + true); + PropertyManager->Tie("ic/vd-fps", this, + &FGInitialCondition::GetVDownFpsIC, + &FGInitialCondition::SetVDownFpsIC, + true); + PropertyManager->Tie("ic/gamma-rad", this, + &FGInitialCondition::GetFlightPathAngleRadIC, + &FGInitialCondition::SetFlightPathAngleRadIC, + true); + PropertyManager->Tie("ic/alpha-rad", this, + &FGInitialCondition::GetAlphaRadIC, + &FGInitialCondition::SetAlphaRadIC, + true); + PropertyManager->Tie("ic/theta-rad", this, + &FGInitialCondition::GetThetaRadIC, + &FGInitialCondition::SetThetaRadIC, + true); + PropertyManager->Tie("ic/beta-rad", this, + &FGInitialCondition::GetBetaRadIC, + &FGInitialCondition::SetBetaRadIC, + true); + PropertyManager->Tie("ic/phi-rad", this, + &FGInitialCondition::GetPhiRadIC, + &FGInitialCondition::SetPhiRadIC, + true); + PropertyManager->Tie("ic/psi-true-rad", this, + &FGInitialCondition::GetPsiRadIC); + PropertyManager->Tie("ic/lat-gc-rad", this, + &FGInitialCondition::GetLatitudeRadIC, + &FGInitialCondition::SetLatitudeRadIC, + true); + PropertyManager->Tie("ic/long-gc-rad", this, + &FGInitialCondition::GetLongitudeRadIC, + &FGInitialCondition::SetLongitudeRadIC, + true); + PropertyManager->Tie("ic/p-rad_sec", this, + &FGInitialCondition::GetPRadpsIC, + &FGInitialCondition::SetPRadpsIC, + true); + PropertyManager->Tie("ic/q-rad_sec", this, + &FGInitialCondition::GetQRadpsIC, + &FGInitialCondition::SetQRadpsIC, + true); + PropertyManager->Tie("ic/r-rad_sec", this, + &FGInitialCondition::GetRRadpsIC, + &FGInitialCondition::SetRRadpsIC, + true); + + typedef int (FGInitialCondition::*iPMF)(void) const; + PropertyManager->Tie("simulation/write-state-file", + this, + (iPMF)0, + &FGInitialCondition::WriteStateFile); } @@ -1567,32 +1406,25 @@ void FGInitialCondition::bind(void) void FGInitialCondition::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGInitialCondition" << endl; - if (from == 1) cout << "Destroyed: FGInitialCondition" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGInitialCondition" << endl; + if (from == 1) cout << "Destroyed: FGInitialCondition" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/initialization/FGInitialCondition.h b/src/initialization/FGInitialCondition.h index a17e1c15777a6848dcaf32f78b8ad4610014b474..b5c8c281924e284b5f49af57e62ac7fbcbe9e016 100644 --- a/src/initialization/FGInitialCondition.h +++ b/src/initialization/FGInitialCondition.h @@ -62,8 +62,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { typedef enum { setvt, setvc, setve, setmach, setuvw, setned, setvg } speedset; typedef enum { setwned, setwmd, setwhc } windset; @@ -213,651 +212,462 @@ CLASS DECLARATION class FGInitialCondition : public FGJSBBase, public FGXMLFileRead { public: - /// Constructor - FGInitialCondition(FGFDMExec *fdmex); - /// Destructor - ~FGInitialCondition(); - - /** Set calibrated airspeed initial condition in knots. - @param vc Calibrated airspeed in knots */ - void SetVcalibratedKtsIC(double vc); - - /** Set equivalent airspeed initial condition in knots. - @param ve Equivalent airspeed in knots */ - void SetVequivalentKtsIC(double ve); - - /** Set true airspeed initial condition in knots. - @param vt True airspeed in knots */ - inline void SetVtrueKtsIC(double vt) - { - SetVtrueFpsIC(vt*ktstofps); - } - - /** Set ground speed initial condition in knots. - @param vg Ground speed in knots */ - inline void SetVgroundKtsIC(double vg) - { - SetVgroundFpsIC(vg*ktstofps); - } - - /** Set mach initial condition. - @param mach Mach number */ - void SetMachIC(double mach); - - /** Sets angle of attack initial condition in degrees. - @param a Alpha in degrees */ - inline void SetAlphaDegIC(double a) - { - SetAlphaRadIC(a*degtorad); - } - - /** Sets angle of sideslip initial condition in degrees. - @param B Beta in degrees */ - inline void SetBetaDegIC(double B) - { - SetBetaRadIC(B*degtorad); - } - - /** Sets pitch angle initial condition in degrees. - @param theta Theta (pitch) angle in degrees */ - inline void SetThetaDegIC(double theta) - { - SetThetaRadIC(theta*degtorad); - } - - /** Resets the IC data structure to new values - @param u, v, w, ... **/ - void ResetIC(double u0, double v0, double w0, double p0, double q0, double r0, - double alpha0, double beta0, double phi0, double theta0, double psi0, - double latitudeRad0, double longitudeRad0, double altitudeAGL0, - double gamma0); - - /** Sets the roll angle initial condition in degrees. - @param phi roll angle in degrees */ - inline void SetPhiDegIC(double phi) - { - SetPhiRadIC(phi*degtorad); - } - - /** Sets the heading angle initial condition in degrees. - @param psi Heading angle in degrees */ - inline void SetPsiDegIC(double psi) - { - SetPsiRadIC(psi*degtorad); - } - - /** Sets the climb rate initial condition in feet/minute. - @param roc Rate of Climb in feet/minute */ - void SetClimbRateFpmIC(double roc); - - /** Sets the flight path angle initial condition in degrees. - @param gamma Flight path angle in degrees */ - inline void SetFlightPathAngleDegIC(double gamma) - { - SetFlightPathAngleRadIC(gamma*degtorad); - } - - /** Sets the altitude above sea level initial condition in feet. - @param altitudeASL Altitude above sea level in feet */ - void SetAltitudeASLFtIC(double altitudeASL); - - /** Sets the initial Altitude above ground level. - @param agl Altitude above ground level in feet */ - void SetAltitudeAGLFtIC(double agl); - - /** Sets the initial sea level radius from planet center - @param sl_rad sea level radius in feet */ - void SetSeaLevelRadiusFtIC(double sl_rad); - - /** Sets the initial terrain elevation. - @param elev Initial terrain elevation in feet */ - void SetTerrainElevationFtIC(double elev); - - /** Sets the initial latitude. - @param lat Initial latitude in degrees */ - inline void SetLatitudeDegIC(double lat) - { - latitude=lat*degtorad; - } - - /** Sets the initial longitude. - @param lon Initial longitude in degrees */ - inline void SetLongitudeDegIC(double lon) - { - longitude=lon*degtorad; - } - - /** Gets the initial calibrated airspeed. - @return Initial calibrated airspeed in knots */ - inline double GetVcalibratedKtsIC(void) const - { - return vc*fpstokts; - } - - /** Gets the initial equivalent airspeed. - @return Initial equivalent airspeed in knots */ - inline double GetVequivalentKtsIC(void) const - { - return ve*fpstokts; - } - - /** Gets the initial ground speed. - @return Initial ground speed in knots */ - inline double GetVgroundKtsIC(void) const - { - return vg*fpstokts; - } - - /** Gets the initial true velocity. - @return Initial true airspeed in knots. */ - inline double GetVtrueKtsIC(void) const - { - return vt*fpstokts; - } - - /** Gets the initial mach. - @return Initial mach number */ - inline double GetMachIC(void) const - { - return mach; - } - - /** Gets the initial climb rate. - @return Initial climb rate in feet/minute */ - inline double GetClimbRateFpmIC(void) const - { - return hdot*60; - } - - /** Gets the initial flight path angle. - @return Initial flight path angle in degrees */ - inline double GetFlightPathAngleDegIC(void)const - { - return gamma*radtodeg; - } - - /** Gets the initial angle of attack. - @return Initial alpha in degrees */ - inline double GetAlphaDegIC(void) const - { - return alpha*radtodeg; - } - - /** Gets the initial sideslip angle. - @return Initial beta in degrees */ - inline double GetBetaDegIC(void) const - { - return beta*radtodeg; - } - - /** Gets the initial pitch angle. - @return Initial pitch angle in degrees */ - inline double GetThetaDegIC(void) const - { - return theta*radtodeg; - } - - /** Gets the initial roll angle. - @return Initial phi in degrees */ - inline double GetPhiDegIC(void) const - { - return phi*radtodeg; - } - - /** Gets the initial heading angle. - @return Initial psi in degrees */ - inline double GetPsiDegIC(void) const - { - return psi*radtodeg; - } - - /** Gets the initial latitude. - @return Initial geocentric latitude in degrees */ - inline double GetLatitudeDegIC(void) const - { - return latitude*radtodeg; - } - - /** Gets the initial longitude. - @return Initial longitude in degrees */ - inline double GetLongitudeDegIC(void) const - { - return longitude*radtodeg; - } - - /** Gets the initial altitude above sea level. - @return Initial altitude in feet. */ - inline double GetAltitudeASLFtIC(void) const - { - return altitudeASL; - } - - /** Gets the initial altitude above ground level. - @return Initial altitude AGL in feet */ - inline double GetAltitudeAGLFtIC(void) const - { - return altitudeASL - terrain_elevation; - } - - /** Gets the initial sea level radius. - @return Initial sea level radius */ - inline double GetSeaLevelRadiusFtIC(void) const - { - return sea_level_radius; - } - - /** Gets the initial terrain elevation. - @return Initial terrain elevation in feet */ - inline double GetTerrainElevationFtIC(void) const - { - return terrain_elevation; - } - - /** Sets the initial ground speed. - @param vg Initial ground speed in feet/second */ - void SetVgroundFpsIC(double vg); - - /** Sets the initial true airspeed. - @param vt Initial true airspeed in feet/second */ - void SetVtrueFpsIC(double vt); - - /** Sets the initial body axis X velocity. - @param ubody Initial X velocity in feet/second */ - void SetUBodyFpsIC(double ubody); - - /** Sets the initial body axis Y velocity. - @param vbody Initial Y velocity in feet/second */ - void SetVBodyFpsIC(double vbody); - - /** Sets the initial body axis Z velocity. - @param wbody Initial Z velocity in feet/second */ - void SetWBodyFpsIC(double wbody); - - /** Sets the initial local axis north velocity. - @param vn Initial north velocity in feet/second */ - void SetVNorthFpsIC(double vn); - - /** Sets the initial local axis east velocity. - @param ve Initial east velocity in feet/second */ - void SetVEastFpsIC(double ve); - - /** Sets the initial local axis down velocity. - @param vd Initial down velocity in feet/second */ - void SetVDownFpsIC(double vd); - - /** Sets the initial roll rate. - @param P Initial roll rate in radians/second */ - void SetPRadpsIC(double P) - { - p = P; - } - - /** Sets the initial pitch rate. - @param Q Initial pitch rate in radians/second */ - void SetQRadpsIC(double Q) - { - q = Q; - } - - /** Sets the initial yaw rate. - @param R initial yaw rate in radians/second */ - void SetRRadpsIC(double R) - { - r = R; - } - - /** Sets the initial wind velocity. - @param wN Initial wind velocity in local north direction, feet/second - @param wE Initial wind velocity in local east direction, feet/second - @param wD Initial wind velocity in local down direction, feet/second */ - void SetWindNEDFpsIC(double wN, double wE, double wD); - - /** Sets the initial total wind speed. - @param mag Initial wind velocity magnitude in knots */ - void SetWindMagKtsIC(double mag); - - /** Sets the initial wind direction. - @param dir Initial direction wind is coming from in degrees */ - void SetWindDirDegIC(double dir); - - /** Sets the initial headwind velocity. - @param head Initial headwind speed in knots */ - void SetHeadWindKtsIC(double head); - - /** Sets the initial crosswind speed. - @param cross Initial crosswind speed, positive from left to right */ - void SetCrossWindKtsIC(double cross); - - /** Sets the initial wind downward speed. - @param wD Initial downward wind speed in knots*/ - void SetWindDownKtsIC(double wD); - - /** Sets the initial climb rate. - @param roc Initial Rate of climb in feet/second */ - void SetClimbRateFpsIC(double roc); - - /** Gets the initial ground velocity. - @return Initial ground velocity in feet/second */ - inline double GetVgroundFpsIC(void) const - { - return vg; - } - - /** Gets the initial true velocity. - @return Initial true velocity in feet/second */ - inline double GetVtrueFpsIC(void) const - { - return vt; - } - - /** Gets the initial body axis X wind velocity. - @return Initial body axis X wind velocity in feet/second */ - inline double GetWindUFpsIC(void) const - { - return uw; - } - - /** Gets the initial body axis Y wind velocity. - @return Initial body axis Y wind velocity in feet/second */ - inline double GetWindVFpsIC(void) const - { - return vw; - } - - /** Gets the initial body axis Z wind velocity. - @return Initial body axis Z wind velocity in feet/second */ - inline double GetWindWFpsIC(void) const - { - return ww; - } - - /** Gets the initial wind velocity in local frame. - @return Initial wind velocity toward north in feet/second */ - inline double GetWindNFpsIC(void) const - { - return wnorth; - } - - /** Gets the initial wind velocity in local frame. - @return Initial wind velocity eastwards in feet/second */ - inline double GetWindEFpsIC(void) const - { - return weast; - } - - /** Gets the initial wind velocity in local frame. - @return Initial wind velocity downwards in feet/second */ - inline double GetWindDFpsIC(void) const - { - return wdown; - } - - /** Gets the initial total wind velocity in feet/sec. - @return Initial wind velocity in feet/second */ - inline double GetWindFpsIC(void) const - { - return sqrt(wnorth*wnorth + weast*weast); - } - - /** Gets the initial wind direction. - @return Initial wind direction in feet/second */ - double GetWindDirDegIC(void) const; - - /** Gets the initial climb rate. - @return Initial rate of climb in feet/second */ - inline double GetClimbRateFpsIC(void) const - { - return hdot; - } - - /** Gets the initial body axis X velocity. - @return Initial body axis X velocity in feet/second. */ - double GetUBodyFpsIC(void) const; - - /** Gets the initial body axis Y velocity. - @return Initial body axis Y velocity in feet/second. */ - double GetVBodyFpsIC(void) const; - - /** Gets the initial body axis Z velocity. - @return Initial body axis Z velocity in feet/second. */ - double GetWBodyFpsIC(void) const; - - /** Gets the initial local frame X (North) velocity. - @return Initial local frame X (North) axis velocity in feet/second. */ - double GetVNorthFpsIC(void) const - { - return vnorth; - }; - - /** Gets the initial local frame Y (East) velocity. - @return Initial local frame Y (East) axis velocity in feet/second. */ - double GetVEastFpsIC(void) const - { - return veast; - }; - - /** Gets the initial local frame Z (Down) velocity. - @return Initial local frame Z (Down) axis velocity in feet/second. */ - double GetVDownFpsIC(void) const - { - return vdown; - }; - - /** Gets the initial body axis roll rate. - @return Initial body axis roll rate in radians/second */ - double GetPRadpsIC() const - { - return p; - } - - /** Gets the initial body axis pitch rate. - @return Initial body axis pitch rate in radians/second */ - double GetQRadpsIC() const - { - return q; - } - - /** Gets the initial body axis yaw rate. - @return Initial body axis yaw rate in radians/second */ - double GetRRadpsIC() const - { - return r; - } - - /** Sets the initial flight path angle. - @param gamma Initial flight path angle in radians */ - void SetFlightPathAngleRadIC(double gamma); - - /** Sets the initial angle of attack. - @param alpha Initial angle of attack in radians */ - void SetAlphaRadIC(double alpha); - - /** Sets the initial pitch angle. - @param theta Initial pitch angle in radians */ - void SetThetaRadIC(double theta); - - /** Sets the initial sideslip angle. - @param beta Initial angle of sideslip in radians. */ - void SetBetaRadIC(double beta); - - /** Sets the initial roll angle. - @param phi Initial roll angle in radians */ - void SetPhiRadIC(double phi); - - /** Sets the initial heading angle. - @param psi Initial heading angle in radians */ - void SetPsiRadIC(double psi); - - /** Sets the initial latitude. - @param lat Initial latitude in radians */ - inline void SetLatitudeRadIC(double lat) - { - latitude=lat; - } - - /** Sets the initial longitude. - @param lon Initial longitude in radians */ - inline void SetLongitudeRadIC(double lon) - { - longitude=lon; - } - - /** Sets the target normal load factor. - @param nlf Normal load factor*/ - inline void SetTargetNlfIC(double nlf) - { - targetNlfIC=nlf; - } - - /** Gets the initial flight path angle. - @return Initial flight path angle in radians */ - inline double GetFlightPathAngleRadIC(void) const - { - return gamma; - } - - /** Gets the initial angle of attack. - @return Initial alpha in radians */ - inline double GetAlphaRadIC(void) const - { - return alpha; - } - - /** Gets the initial angle of sideslip. - @return Initial sideslip angle in radians */ - inline double GetBetaRadIC(void) const - { - return beta; - } - - /** Gets the initial roll angle. - @return Initial roll angle in radians */ - inline double GetPhiRadIC(void) const - { - return phi; - } - - /** Gets the initial latitude. - @return Initial latitude in radians */ - inline double GetLatitudeRadIC(void) const - { - return latitude; - } - - /** Gets the initial longitude. - @return Initial longitude in radians */ - inline double GetLongitudeRadIC(void) const - { - return longitude; - } - - /** Gets the initial pitch angle. - @return Initial pitch angle in radians */ - inline double GetThetaRadIC(void) const - { - return theta; - } - - /** Gets the initial heading angle. - @return Initial heading angle in radians */ - inline double GetPsiRadIC(void) const - { - return psi; - } - - /** Gets the initial speedset. - @return Initial speedset */ - inline speedset GetSpeedSet(void) - { - return lastSpeedSet; - } - - /** Gets the initial windset. - @return Initial windset */ - inline windset GetWindSet(void) - { - return lastWindSet; - } - - /** Gets the target normal load factor set from IC. - @return target normal load factor set from IC*/ - inline double GetTargetNlfIC(void) - { - return targetNlfIC; - } - - /** Loads the initial conditions. - @param rstname The name of an initial conditions file - @param useStoredPath true if the stored path to the IC file should be used - @return true if successful */ - bool Load(string rstname, bool useStoredPath = true ); - - /** Get init-file name - */ - string GetInitFile(void) - { - return init_file_name; - } - /** Set init-file name - */ - void SetInitFile(string f) - { - init_file_name = f; - } - void WriteStateFile(int num); + /// Constructor + FGInitialCondition(FGFDMExec *fdmex); + /// Destructor + ~FGInitialCondition(); + + /** Set calibrated airspeed initial condition in knots. + @param vc Calibrated airspeed in knots */ + void SetVcalibratedKtsIC(double vc); + + /** Set equivalent airspeed initial condition in knots. + @param ve Equivalent airspeed in knots */ + void SetVequivalentKtsIC(double ve); + + /** Set true airspeed initial condition in knots. + @param vt True airspeed in knots */ + inline void SetVtrueKtsIC(double vt) { SetVtrueFpsIC(vt*ktstofps); } + + /** Set ground speed initial condition in knots. + @param vg Ground speed in knots */ + inline void SetVgroundKtsIC(double vg) { SetVgroundFpsIC(vg*ktstofps); } + + /** Set mach initial condition. + @param mach Mach number */ + void SetMachIC(double mach); + + /** Sets angle of attack initial condition in degrees. + @param a Alpha in degrees */ + inline void SetAlphaDegIC(double a) { SetAlphaRadIC(a*degtorad); } + + /** Sets angle of sideslip initial condition in degrees. + @param B Beta in degrees */ + inline void SetBetaDegIC(double B) { SetBetaRadIC(B*degtorad);} + + /** Sets pitch angle initial condition in degrees. + @param theta Theta (pitch) angle in degrees */ + inline void SetThetaDegIC(double theta) { SetThetaRadIC(theta*degtorad); } + + /** Resets the IC data structure to new values + @param u, v, w, ... **/ + void ResetIC(double u0, double v0, double w0, double p0, double q0, double r0, + double alpha0, double beta0, double phi0, double theta0, double psi0, + double latitudeRad0, double longitudeRad0, double altitudeAGL0, + double gamma0); + + /** Sets the roll angle initial condition in degrees. + @param phi roll angle in degrees */ + inline void SetPhiDegIC(double phi) { SetPhiRadIC(phi*degtorad);} + + /** Sets the heading angle initial condition in degrees. + @param psi Heading angle in degrees */ + inline void SetPsiDegIC(double psi){ SetPsiRadIC(psi*degtorad); } + + /** Sets the climb rate initial condition in feet/minute. + @param roc Rate of Climb in feet/minute */ + void SetClimbRateFpmIC(double roc); + + /** Sets the flight path angle initial condition in degrees. + @param gamma Flight path angle in degrees */ + inline void SetFlightPathAngleDegIC(double gamma) { SetFlightPathAngleRadIC(gamma*degtorad); } + + /** Sets the altitude above sea level initial condition in feet. + @param altitudeASL Altitude above sea level in feet */ + void SetAltitudeASLFtIC(double altitudeASL); + + /** Sets the initial Altitude above ground level. + @param agl Altitude above ground level in feet */ + void SetAltitudeAGLFtIC(double agl); + + /** Sets the initial sea level radius from planet center + @param sl_rad sea level radius in feet */ + void SetSeaLevelRadiusFtIC(double sl_rad); + + /** Sets the initial terrain elevation. + @param elev Initial terrain elevation in feet */ + void SetTerrainElevationFtIC(double elev); + + /** Sets the initial latitude. + @param lat Initial latitude in degrees */ + inline void SetLatitudeDegIC(double lat) { latitude=lat*degtorad; } + + /** Sets the initial longitude. + @param lon Initial longitude in degrees */ + inline void SetLongitudeDegIC(double lon) { longitude=lon*degtorad; } + + /** Gets the initial calibrated airspeed. + @return Initial calibrated airspeed in knots */ + inline double GetVcalibratedKtsIC(void) const { return vc*fpstokts; } + + /** Gets the initial equivalent airspeed. + @return Initial equivalent airspeed in knots */ + inline double GetVequivalentKtsIC(void) const { return ve*fpstokts; } + + /** Gets the initial ground speed. + @return Initial ground speed in knots */ + inline double GetVgroundKtsIC(void) const { return vg*fpstokts; } + + /** Gets the initial true velocity. + @return Initial true airspeed in knots. */ + inline double GetVtrueKtsIC(void) const { return vt*fpstokts; } + + /** Gets the initial mach. + @return Initial mach number */ + inline double GetMachIC(void) const { return mach; } + + /** Gets the initial climb rate. + @return Initial climb rate in feet/minute */ + inline double GetClimbRateFpmIC(void) const { return hdot*60; } + + /** Gets the initial flight path angle. + @return Initial flight path angle in degrees */ + inline double GetFlightPathAngleDegIC(void)const { return gamma*radtodeg; } + + /** Gets the initial angle of attack. + @return Initial alpha in degrees */ + inline double GetAlphaDegIC(void) const { return alpha*radtodeg; } + + /** Gets the initial sideslip angle. + @return Initial beta in degrees */ + inline double GetBetaDegIC(void) const { return beta*radtodeg; } + + /** Gets the initial pitch angle. + @return Initial pitch angle in degrees */ + inline double GetThetaDegIC(void) const { return theta*radtodeg; } + + /** Gets the initial roll angle. + @return Initial phi in degrees */ + inline double GetPhiDegIC(void) const { return phi*radtodeg; } + + /** Gets the initial heading angle. + @return Initial psi in degrees */ + inline double GetPsiDegIC(void) const { return psi*radtodeg; } + + /** Gets the initial latitude. + @return Initial geocentric latitude in degrees */ + inline double GetLatitudeDegIC(void) const { return latitude*radtodeg; } + + /** Gets the initial longitude. + @return Initial longitude in degrees */ + inline double GetLongitudeDegIC(void) const { return longitude*radtodeg; } + + /** Gets the initial altitude above sea level. + @return Initial altitude in feet. */ + inline double GetAltitudeASLFtIC(void) const { return altitudeASL; } + + /** Gets the initial altitude above ground level. + @return Initial altitude AGL in feet */ + inline double GetAltitudeAGLFtIC(void) const { return altitudeASL - terrain_elevation; } + + /** Gets the initial sea level radius. + @return Initial sea level radius */ + inline double GetSeaLevelRadiusFtIC(void) const { return sea_level_radius; } + + /** Gets the initial terrain elevation. + @return Initial terrain elevation in feet */ + inline double GetTerrainElevationFtIC(void) const { return terrain_elevation; } + + /** Sets the initial ground speed. + @param vg Initial ground speed in feet/second */ + void SetVgroundFpsIC(double vg); + + /** Sets the initial true airspeed. + @param vt Initial true airspeed in feet/second */ + void SetVtrueFpsIC(double vt); + + /** Sets the initial body axis X velocity. + @param ubody Initial X velocity in feet/second */ + void SetUBodyFpsIC(double ubody); + + /** Sets the initial body axis Y velocity. + @param vbody Initial Y velocity in feet/second */ + void SetVBodyFpsIC(double vbody); + + /** Sets the initial body axis Z velocity. + @param wbody Initial Z velocity in feet/second */ + void SetWBodyFpsIC(double wbody); + + /** Sets the initial local axis north velocity. + @param vn Initial north velocity in feet/second */ + void SetVNorthFpsIC(double vn); + + /** Sets the initial local axis east velocity. + @param ve Initial east velocity in feet/second */ + void SetVEastFpsIC(double ve); + + /** Sets the initial local axis down velocity. + @param vd Initial down velocity in feet/second */ + void SetVDownFpsIC(double vd); + + /** Sets the initial roll rate. + @param P Initial roll rate in radians/second */ + void SetPRadpsIC(double P) { p = P; } + + /** Sets the initial pitch rate. + @param Q Initial pitch rate in radians/second */ + void SetQRadpsIC(double Q) { q = Q; } + + /** Sets the initial yaw rate. + @param R initial yaw rate in radians/second */ + void SetRRadpsIC(double R) { r = R; } + + /** Sets the initial wind velocity. + @param wN Initial wind velocity in local north direction, feet/second + @param wE Initial wind velocity in local east direction, feet/second + @param wD Initial wind velocity in local down direction, feet/second */ + void SetWindNEDFpsIC(double wN, double wE, double wD); + + /** Sets the initial total wind speed. + @param mag Initial wind velocity magnitude in knots */ + void SetWindMagKtsIC(double mag); + + /** Sets the initial wind direction. + @param dir Initial direction wind is coming from in degrees */ + void SetWindDirDegIC(double dir); + + /** Sets the initial headwind velocity. + @param head Initial headwind speed in knots */ + void SetHeadWindKtsIC(double head); + + /** Sets the initial crosswind speed. + @param cross Initial crosswind speed, positive from left to right */ + void SetCrossWindKtsIC(double cross); + + /** Sets the initial wind downward speed. + @param wD Initial downward wind speed in knots*/ + void SetWindDownKtsIC(double wD); + + /** Sets the initial climb rate. + @param roc Initial Rate of climb in feet/second */ + void SetClimbRateFpsIC(double roc); + + /** Gets the initial ground velocity. + @return Initial ground velocity in feet/second */ + inline double GetVgroundFpsIC(void) const { return vg; } + + /** Gets the initial true velocity. + @return Initial true velocity in feet/second */ + inline double GetVtrueFpsIC(void) const { return vt; } + + /** Gets the initial body axis X wind velocity. + @return Initial body axis X wind velocity in feet/second */ + inline double GetWindUFpsIC(void) const { return uw; } + + /** Gets the initial body axis Y wind velocity. + @return Initial body axis Y wind velocity in feet/second */ + inline double GetWindVFpsIC(void) const { return vw; } + + /** Gets the initial body axis Z wind velocity. + @return Initial body axis Z wind velocity in feet/second */ + inline double GetWindWFpsIC(void) const { return ww; } + + /** Gets the initial wind velocity in local frame. + @return Initial wind velocity toward north in feet/second */ + inline double GetWindNFpsIC(void) const { return wnorth; } + + /** Gets the initial wind velocity in local frame. + @return Initial wind velocity eastwards in feet/second */ + inline double GetWindEFpsIC(void) const { return weast; } + + /** Gets the initial wind velocity in local frame. + @return Initial wind velocity downwards in feet/second */ + inline double GetWindDFpsIC(void) const { return wdown; } + + /** Gets the initial total wind velocity in feet/sec. + @return Initial wind velocity in feet/second */ + inline double GetWindFpsIC(void) const { return sqrt(wnorth*wnorth + weast*weast); } + + /** Gets the initial wind direction. + @return Initial wind direction in feet/second */ + double GetWindDirDegIC(void) const; + + /** Gets the initial climb rate. + @return Initial rate of climb in feet/second */ + inline double GetClimbRateFpsIC(void) const { return hdot; } + + /** Gets the initial body axis X velocity. + @return Initial body axis X velocity in feet/second. */ + double GetUBodyFpsIC(void) const; + + /** Gets the initial body axis Y velocity. + @return Initial body axis Y velocity in feet/second. */ + double GetVBodyFpsIC(void) const; + + /** Gets the initial body axis Z velocity. + @return Initial body axis Z velocity in feet/second. */ + double GetWBodyFpsIC(void) const; + + /** Gets the initial local frame X (North) velocity. + @return Initial local frame X (North) axis velocity in feet/second. */ + double GetVNorthFpsIC(void) const {return vnorth;}; + + /** Gets the initial local frame Y (East) velocity. + @return Initial local frame Y (East) axis velocity in feet/second. */ + double GetVEastFpsIC(void) const {return veast;}; + + /** Gets the initial local frame Z (Down) velocity. + @return Initial local frame Z (Down) axis velocity in feet/second. */ + double GetVDownFpsIC(void) const {return vdown;}; + + /** Gets the initial body axis roll rate. + @return Initial body axis roll rate in radians/second */ + double GetPRadpsIC() const { return p; } + + /** Gets the initial body axis pitch rate. + @return Initial body axis pitch rate in radians/second */ + double GetQRadpsIC() const { return q; } + + /** Gets the initial body axis yaw rate. + @return Initial body axis yaw rate in radians/second */ + double GetRRadpsIC() const { return r; } + + /** Sets the initial flight path angle. + @param gamma Initial flight path angle in radians */ + void SetFlightPathAngleRadIC(double gamma); + + /** Sets the initial angle of attack. + @param alpha Initial angle of attack in radians */ + void SetAlphaRadIC(double alpha); + + /** Sets the initial pitch angle. + @param theta Initial pitch angle in radians */ + void SetThetaRadIC(double theta); + + /** Sets the initial sideslip angle. + @param beta Initial angle of sideslip in radians. */ + void SetBetaRadIC(double beta); + + /** Sets the initial roll angle. + @param phi Initial roll angle in radians */ + void SetPhiRadIC(double phi); + + /** Sets the initial heading angle. + @param psi Initial heading angle in radians */ + void SetPsiRadIC(double psi); + + /** Sets the initial latitude. + @param lat Initial latitude in radians */ + inline void SetLatitudeRadIC(double lat) { latitude=lat; } + + /** Sets the initial longitude. + @param lon Initial longitude in radians */ + inline void SetLongitudeRadIC(double lon) { longitude=lon; } + + /** Sets the target normal load factor. + @param nlf Normal load factor*/ + inline void SetTargetNlfIC(double nlf) { targetNlfIC=nlf; } + + /** Gets the initial flight path angle. + @return Initial flight path angle in radians */ + inline double GetFlightPathAngleRadIC(void) const { return gamma; } + + /** Gets the initial angle of attack. + @return Initial alpha in radians */ + inline double GetAlphaRadIC(void) const { return alpha; } + + /** Gets the initial angle of sideslip. + @return Initial sideslip angle in radians */ + inline double GetBetaRadIC(void) const { return beta; } + + /** Gets the initial roll angle. + @return Initial roll angle in radians */ + inline double GetPhiRadIC(void) const { return phi; } + + /** Gets the initial latitude. + @return Initial latitude in radians */ + inline double GetLatitudeRadIC(void) const { return latitude; } + + /** Gets the initial longitude. + @return Initial longitude in radians */ + inline double GetLongitudeRadIC(void) const { return longitude; } + + /** Gets the initial pitch angle. + @return Initial pitch angle in radians */ + inline double GetThetaRadIC(void) const { return theta; } + + /** Gets the initial heading angle. + @return Initial heading angle in radians */ + inline double GetPsiRadIC(void) const { return psi; } + + /** Gets the initial speedset. + @return Initial speedset */ + inline speedset GetSpeedSet(void) { return lastSpeedSet; } + + /** Gets the initial windset. + @return Initial windset */ + inline windset GetWindSet(void) { return lastWindSet; } + + /** Gets the target normal load factor set from IC. + @return target normal load factor set from IC*/ + inline double GetTargetNlfIC(void) { return targetNlfIC; } + + /** Loads the initial conditions. + @param rstname The name of an initial conditions file + @param useStoredPath true if the stored path to the IC file should be used + @return true if successful */ + bool Load(string rstname, bool useStoredPath = true ); + + /** Get init-file name + */ + string GetInitFile(void) {return init_file_name;} + /** Set init-file name + */ + void SetInitFile(string f) { init_file_name = f;} + void WriteStateFile(int num); private: - double vt,vc,ve,vg; - double mach; - double altitudeASL,hdot; - double latitude,longitude; - double u,v,w; - double p,q,r; - double uw,vw,ww; - double vnorth,veast,vdown; - double wnorth,weast,wdown; - double whead, wcross, wdir, wmag; - double sea_level_radius; - double terrain_elevation; - double radius_to_vehicle; - double targetNlfIC; - - double alpha, beta, theta, phi, psi, gamma; - double salpha,sbeta,stheta,sphi,spsi,sgamma; - double calpha,cbeta,ctheta,cphi,cpsi,cgamma; - - double xlo, xhi,xmin,xmax; - - typedef double (FGInitialCondition::*fp)(double x); - fp sfunc; - - speedset lastSpeedSet; - windset lastWindSet; - - FGFDMExec *fdmex; - FGPropertyManager *PropertyManager; - - bool Load_v1(void); - bool Load_v2(void); - - bool Constructing; - bool getAlpha(void); - bool getTheta(void); - bool getMachFromVcas(double *Mach,double vcas); - - double GammaEqOfTheta(double Theta); - void InitializeIC(void); - double GammaEqOfAlpha(double Alpha); - double calcVcas(double Mach); - void calcUVWfromNED(void); - void calcWindUVW(void); - - bool findInterval(double x,double guess); - bool solve(double *y, double x); - void bind(void); - void Debug(int from); - - string init_file_name; + double vt,vc,ve,vg; + double mach; + double altitudeASL,hdot; + double latitude,longitude; + double u,v,w; + double p,q,r; + double uw,vw,ww; + double vnorth,veast,vdown; + double wnorth,weast,wdown; + double whead, wcross, wdir, wmag; + double sea_level_radius; + double terrain_elevation; + double radius_to_vehicle; + double targetNlfIC; + + double alpha, beta, theta, phi, psi, gamma; + double salpha,sbeta,stheta,sphi,spsi,sgamma; + double calpha,cbeta,ctheta,cphi,cpsi,cgamma; + + double xlo, xhi,xmin,xmax; + + typedef double (FGInitialCondition::*fp)(double x); + fp sfunc; + + speedset lastSpeedSet; + windset lastWindSet; + + FGFDMExec *fdmex; + FGPropertyManager *PropertyManager; + + bool Load_v1(void); + bool Load_v2(void); + + bool Constructing; + bool getAlpha(void); + bool getTheta(void); + bool getMachFromVcas(double *Mach,double vcas); + + double GammaEqOfTheta(double Theta); + void InitializeIC(void); + double GammaEqOfAlpha(double Alpha); + double calcVcas(double Mach); + void calcUVWfromNED(void); + void calcWindUVW(void); + + bool findInterval(double x,double guess); + bool solve(double *y, double x); + void bind(void); + void Debug(int from); + + string init_file_name; }; } #endif diff --git a/src/initialization/FGTrim.cpp b/src/initialization/FGTrim.cpp index 70df895447a4944cc0e64c7d0e9a5c3f009d5cbe..6b0cd81c05f665e568067d08ed859a6b7c2682bc 100644 --- a/src/initialization/FGTrim.cpp +++ b/src/initialization/FGTrim.cpp @@ -61,101 +61,90 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGTrim.cpp,v 1.13 2010/04/23 17:23:40 dpculp Exp $"; static const char *IdHdr = ID_TRIM; //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FGTrim::FGTrim(FGFDMExec *FDMExec,TrimMode tt) -{ - - N=Nsub=0; - max_iterations=60; - max_sub_iterations=100; - Tolerance=1E-3; - A_Tolerance = Tolerance / 10; - - Debug=0; - DebugLevel=0; - fdmex=FDMExec; - fgic=fdmex->GetIC(); - total_its=0; - trimudot=true; - gamma_fallback=false; - axis_count=0; - mode=tt; - xlo=xhi=alo=ahi=0.0; - targetNlf=1.0; - debug_axis=tAll; - SetMode(tt); - if (debug_lvl & 2) cout << "Instantiated: FGTrim" << endl; +FGTrim::FGTrim(FGFDMExec *FDMExec,TrimMode tt) { + + N=Nsub=0; + max_iterations=60; + max_sub_iterations=100; + Tolerance=1E-3; + A_Tolerance = Tolerance / 10; + + Debug=0;DebugLevel=0; + fdmex=FDMExec; + fgic=fdmex->GetIC(); + total_its=0; + trimudot=true; + gamma_fallback=false; + axis_count=0; + mode=tt; + xlo=xhi=alo=ahi=0.0; + targetNlf=1.0; + debug_axis=tAll; + SetMode(tt); + if (debug_lvl & 2) cout << "Instantiated: FGTrim" << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FGTrim::~FGTrim(void) -{ - for (current_axis=0; current_axis<TrimAxes.size(); current_axis++) - { - delete TrimAxes[current_axis]; - } - delete[] sub_iterations; - delete[] successful; - delete[] solution; - if (debug_lvl & 2) cout << "Destroyed: FGTrim" << endl; +FGTrim::~FGTrim(void) { + for(current_axis=0; current_axis<TrimAxes.size(); current_axis++) { + delete TrimAxes[current_axis]; + } + delete[] sub_iterations; + delete[] successful; + delete[] solution; + if (debug_lvl & 2) cout << "Destroyed: FGTrim" << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrim::TrimStats() -{ - int run_sum=0; - cout << endl << " Trim Statistics: " << endl; - cout << " Total Iterations: " << total_its << endl; - if ( total_its > 0) - { - cout << " Sub-iterations:" << endl; - for (current_axis=0; current_axis<TrimAxes.size(); current_axis++) - { - run_sum += TrimAxes[current_axis]->GetRunCount(); - cout << " " << setw(5) << TrimAxes[current_axis]->GetStateName().c_str() - << ": " << setprecision(3) << sub_iterations[current_axis] - << " average: " << setprecision(5) << sub_iterations[current_axis]/double(total_its) - << " successful: " << setprecision(3) << successful[current_axis] - << " stability: " << setprecision(5) << TrimAxes[current_axis]->GetAvgStability() - << endl; - } - cout << " Run Count: " << run_sum << endl; +void FGTrim::TrimStats() { + int run_sum=0; + cout << endl << " Trim Statistics: " << endl; + cout << " Total Iterations: " << total_its << endl; + if( total_its > 0) { + cout << " Sub-iterations:" << endl; + for (current_axis=0; current_axis<TrimAxes.size(); current_axis++) { + run_sum += TrimAxes[current_axis]->GetRunCount(); + cout << " " << setw(5) << TrimAxes[current_axis]->GetStateName().c_str() + << ": " << setprecision(3) << sub_iterations[current_axis] + << " average: " << setprecision(5) << sub_iterations[current_axis]/double(total_its) + << " successful: " << setprecision(3) << successful[current_axis] + << " stability: " << setprecision(5) << TrimAxes[current_axis]->GetAvgStability() + << endl; } + cout << " Run Count: " << run_sum << endl; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrim::Report(void) -{ - cout << " Trim Results: " << endl; - for (current_axis=0; current_axis<TrimAxes.size(); current_axis++) - TrimAxes[current_axis]->AxisReport(); +void FGTrim::Report(void) { + cout << " Trim Results: " << endl; + for(current_axis=0; current_axis<TrimAxes.size(); current_axis++) + TrimAxes[current_axis]->AxisReport(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrim::ClearStates(void) -{ +void FGTrim::ClearStates(void) { FGTrimAxis* ta; mode=tCustom; vector<FGTrimAxis*>::iterator iAxes; iAxes = TrimAxes.begin(); - while (iAxes != TrimAxes.end()) - { - ta=*iAxes; - delete ta; - iAxes++; + while (iAxes != TrimAxes.end()) { + ta=*iAxes; + delete ta; + iAxes++; } TrimAxes.clear(); //cout << "TrimAxes.size(): " << TrimAxes.size() << endl; @@ -163,321 +152,273 @@ void FGTrim::ClearStates(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGTrim::AddState( State state, Control control ) -{ - FGTrimAxis* ta; - bool result=true; - - mode = tCustom; - vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin(); - while (iAxes != TrimAxes.end()) - { - ta=*iAxes; - if ( ta->GetStateType() == state ) - result=false; - iAxes++; - } - if (result) - { - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,state,control)); - delete[] sub_iterations; - delete[] successful; - delete[] solution; - sub_iterations=new double[TrimAxes.size()]; - successful=new double[TrimAxes.size()]; - solution=new bool[TrimAxes.size()]; - } - return result; +bool FGTrim::AddState( State state, Control control ) { + FGTrimAxis* ta; + bool result=true; + + mode = tCustom; + vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin(); + while (iAxes != TrimAxes.end()) { + ta=*iAxes; + if( ta->GetStateType() == state ) + result=false; + iAxes++; + } + if(result) { + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,state,control)); + delete[] sub_iterations; + delete[] successful; + delete[] solution; + sub_iterations=new double[TrimAxes.size()]; + successful=new double[TrimAxes.size()]; + solution=new bool[TrimAxes.size()]; + } + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGTrim::RemoveState( State state ) -{ - FGTrimAxis* ta; - bool result=false; - - mode = tCustom; - vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin(); - while (iAxes != TrimAxes.end()) - { - ta=*iAxes; - if ( ta->GetStateType() == state ) - { - delete ta; - iAxes = TrimAxes.erase(iAxes); - result=true; - continue; - } - iAxes++; - } - if (result) - { - delete[] sub_iterations; - delete[] successful; - delete[] solution; - sub_iterations=new double[TrimAxes.size()]; - successful=new double[TrimAxes.size()]; - solution=new bool[TrimAxes.size()]; - } - return result; +bool FGTrim::RemoveState( State state ) { + FGTrimAxis* ta; + bool result=false; + + mode = tCustom; + vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin(); + while (iAxes != TrimAxes.end()) { + ta=*iAxes; + if( ta->GetStateType() == state ) { + delete ta; + iAxes = TrimAxes.erase(iAxes); + result=true; + continue; + } + iAxes++; + } + if(result) { + delete[] sub_iterations; + delete[] successful; + delete[] solution; + sub_iterations=new double[TrimAxes.size()]; + successful=new double[TrimAxes.size()]; + solution=new bool[TrimAxes.size()]; + } + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGTrim::EditState( State state, Control new_control ) -{ - FGTrimAxis* ta; - bool result=false; - - mode = tCustom; - vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin(); - while (iAxes != TrimAxes.end()) - { - ta=*iAxes; - if ( ta->GetStateType() == state ) - { - TrimAxes.insert(iAxes,1,new FGTrimAxis(fdmex,fgic,state,new_control)); - delete ta; - TrimAxes.erase(iAxes+1); - result=true; - break; - } - iAxes++; - } - return result; +bool FGTrim::EditState( State state, Control new_control ){ + FGTrimAxis* ta; + bool result=false; + + mode = tCustom; + vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin(); + while (iAxes != TrimAxes.end()) { + ta=*iAxes; + if( ta->GetStateType() == state ) { + TrimAxes.insert(iAxes,1,new FGTrimAxis(fdmex,fgic,state,new_control)); + delete ta; + TrimAxes.erase(iAxes+1); + result=true; + break; + } + iAxes++; + } + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGTrim::DoTrim(void) -{ +bool FGTrim::DoTrim(void) { - trim_failed=false; - int i; + trim_failed=false; + int i; - for (i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++) - { - fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(false); - } + for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){ + fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(false); + } - fdmex->DisableOutput(); - - setEngineTrimMode(true); - - fgic->SetPRadpsIC(0.0); - fgic->SetQRadpsIC(0.0); - fgic->SetRRadpsIC(0.0); - - //clear the sub iterations counts & zero out the controls - for (current_axis=0;current_axis<TrimAxes.size();current_axis++) - { - //cout << current_axis << " " << TrimAxes[current_axis]->GetStateName() - //<< " " << TrimAxes[current_axis]->GetControlName()<< endl; - if (TrimAxes[current_axis]->GetStateType() == tQdot) - { - if (mode == tGround) - { - TrimAxes[current_axis]->initTheta(); - } - } - xlo=TrimAxes[current_axis]->GetControlMin(); - xhi=TrimAxes[current_axis]->GetControlMax(); - TrimAxes[current_axis]->SetControl((xlo+xhi)/2); - TrimAxes[current_axis]->Run(); - //TrimAxes[current_axis]->AxisReport(); - sub_iterations[current_axis]=0; - successful[current_axis]=0; - solution[current_axis]=false; - } + fdmex->DisableOutput(); + setEngineTrimMode(true); - if (mode == tPullup ) - { - cout << "Setting pitch rate and nlf... " << endl; - setupPullup(); - cout << "pitch rate done ... " << endl; - TrimAxes[0]->SetStateTarget(targetNlf); - cout << "nlf done" << endl; - } - else if (mode == tTurn) - { - setupTurn(); - //TrimAxes[0]->SetStateTarget(targetNlf); - } + fgic->SetPRadpsIC(0.0); + fgic->SetQRadpsIC(0.0); + fgic->SetRRadpsIC(0.0); - do - { - axis_count=0; - for (current_axis=0;current_axis<TrimAxes.size();current_axis++) - { - setDebug(); - updateRates(); - Nsub=0; - if (!solution[current_axis]) - { - if (checkLimits()) - { - solution[current_axis]=true; - solve(); - } - } - else if (findInterval()) - { - solve(); - } - else - { - solution[current_axis]=false; - } - sub_iterations[current_axis]+=Nsub; - } - for (current_axis=0;current_axis<TrimAxes.size();current_axis++) - { - //these checks need to be done after all the axes have run - if (Debug > 0) TrimAxes[current_axis]->AxisReport(); - if (TrimAxes[current_axis]->InTolerance()) - { - axis_count++; - successful[current_axis]++; - } - } - - - if ((axis_count == TrimAxes.size()-1) && (TrimAxes.size() > 1)) - { - //cout << TrimAxes.size()-1 << " out of " << TrimAxes.size() << "!" << endl; - //At this point we can check the input limits of the failed axis - //and declare the trim failed if there is no sign change. If there - //is, keep going until success or max iteration count - - //Oh, well: two out of three ain't bad - for (current_axis=0;current_axis<TrimAxes.size();current_axis++) - { - //these checks need to be done after all the axes have run - if (!TrimAxes[current_axis]->InTolerance()) - { - if (!checkLimits()) - { - // special case this for now -- if other cases arise proper - // support can be added to FGTrimAxis - if ( (gamma_fallback) && - (TrimAxes[current_axis]->GetStateType() == tUdot) && - (TrimAxes[current_axis]->GetControlType() == tThrottle)) - { - cout << " Can't trim udot with throttle, trying flight" - << " path angle. (" << N << ")" << endl; - if (TrimAxes[current_axis]->GetState() > 0) - TrimAxes[current_axis]->SetControlToMin(); - else - TrimAxes[current_axis]->SetControlToMax(); - TrimAxes[current_axis]->Run(); - delete TrimAxes[current_axis]; - TrimAxes[current_axis]=new FGTrimAxis(fdmex,fgic,tUdot, - tGamma ); - } - else - { - cout << " Sorry, " << TrimAxes[current_axis]->GetStateName() - << " doesn't appear to be trimmable" << endl; - //total_its=k; - trim_failed=true; //force the trim to fail - } //gamma_fallback - } - } //solution check - } //for loop - } //all-but-one check - N++; - if (N > max_iterations) - trim_failed=true; + //clear the sub iterations counts & zero out the controls + for(current_axis=0;current_axis<TrimAxes.size();current_axis++) { + //cout << current_axis << " " << TrimAxes[current_axis]->GetStateName() + //<< " " << TrimAxes[current_axis]->GetControlName()<< endl; + if(TrimAxes[current_axis]->GetStateType() == tQdot) { + if(mode == tGround) { + TrimAxes[current_axis]->initTheta(); + } } - while ((axis_count < TrimAxes.size()) && (!trim_failed)); - if ((!trim_failed) && (axis_count >= TrimAxes.size())) - { - total_its=N; - if (debug_lvl > 0) - cout << endl << " Trim successful" << endl; - } - else - { - total_its=N; - if (debug_lvl > 0) - cout << endl << " Trim failed" << endl; + xlo=TrimAxes[current_axis]->GetControlMin(); + xhi=TrimAxes[current_axis]->GetControlMax(); + TrimAxes[current_axis]->SetControl((xlo+xhi)/2); + TrimAxes[current_axis]->Run(); + //TrimAxes[current_axis]->AxisReport(); + sub_iterations[current_axis]=0; + successful[current_axis]=0; + solution[current_axis]=false; + } + + + if(mode == tPullup ) { + cout << "Setting pitch rate and nlf... " << endl; + setupPullup(); + cout << "pitch rate done ... " << endl; + TrimAxes[0]->SetStateTarget(targetNlf); + cout << "nlf done" << endl; + } else if (mode == tTurn) { + setupTurn(); + //TrimAxes[0]->SetStateTarget(targetNlf); + } + + do { + axis_count=0; + for(current_axis=0;current_axis<TrimAxes.size();current_axis++) { + setDebug(); + updateRates(); + Nsub=0; + if(!solution[current_axis]) { + if(checkLimits()) { + solution[current_axis]=true; + solve(); + } + } else if(findInterval()) { + solve(); + } else { + solution[current_axis]=false; + } + sub_iterations[current_axis]+=Nsub; } - for (i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++) - { - fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true); + for(current_axis=0;current_axis<TrimAxes.size();current_axis++) { + //these checks need to be done after all the axes have run + if(Debug > 0) TrimAxes[current_axis]->AxisReport(); + if(TrimAxes[current_axis]->InTolerance()) { + axis_count++; + successful[current_axis]++; + } } - setEngineTrimMode(false); - fdmex->EnableOutput(); - return !trim_failed; + + + if((axis_count == TrimAxes.size()-1) && (TrimAxes.size() > 1)) { + //cout << TrimAxes.size()-1 << " out of " << TrimAxes.size() << "!" << endl; + //At this point we can check the input limits of the failed axis + //and declare the trim failed if there is no sign change. If there + //is, keep going until success or max iteration count + + //Oh, well: two out of three ain't bad + for(current_axis=0;current_axis<TrimAxes.size();current_axis++) { + //these checks need to be done after all the axes have run + if(!TrimAxes[current_axis]->InTolerance()) { + if(!checkLimits()) { + // special case this for now -- if other cases arise proper + // support can be added to FGTrimAxis + if( (gamma_fallback) && + (TrimAxes[current_axis]->GetStateType() == tUdot) && + (TrimAxes[current_axis]->GetControlType() == tThrottle)) { + cout << " Can't trim udot with throttle, trying flight" + << " path angle. (" << N << ")" << endl; + if(TrimAxes[current_axis]->GetState() > 0) + TrimAxes[current_axis]->SetControlToMin(); + else + TrimAxes[current_axis]->SetControlToMax(); + TrimAxes[current_axis]->Run(); + delete TrimAxes[current_axis]; + TrimAxes[current_axis]=new FGTrimAxis(fdmex,fgic,tUdot, + tGamma ); + } else { + cout << " Sorry, " << TrimAxes[current_axis]->GetStateName() + << " doesn't appear to be trimmable" << endl; + //total_its=k; + trim_failed=true; //force the trim to fail + } //gamma_fallback + } + } //solution check + } //for loop + } //all-but-one check + N++; + if(N > max_iterations) + trim_failed=true; + } while((axis_count < TrimAxes.size()) && (!trim_failed)); + if((!trim_failed) && (axis_count >= TrimAxes.size())) { + total_its=N; + if (debug_lvl > 0) + cout << endl << " Trim successful" << endl; + } else { + total_its=N; + if (debug_lvl > 0) + cout << endl << " Trim failed" << endl; + } + for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){ + fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true); + } + setEngineTrimMode(false); + fdmex->EnableOutput(); + return !trim_failed; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGTrim::solve(void) -{ - - double x1,x2,x3,f1,f2,f3,d,d0; - const double relax =0.9; - double eps=TrimAxes[current_axis]->GetSolverEps(); - - x1=x2=x3=0; - d=1; - bool success=false; - //initializations - if ( solutionDomain != 0) - { - /* if(ahi > alo) { */ - x1=xlo; - f1=alo; - x3=xhi; - f3=ahi; - /* } else { - x1=xhi;f1=ahi; - x3=xlo;f3=alo; - } */ - d0=fabs(x3-x1); - //iterations - //max_sub_iterations=TrimAxes[current_axis]->GetIterationLimit(); - while ( (TrimAxes[current_axis]->InTolerance() == false ) - && (fabs(d) > eps) && (Nsub < max_sub_iterations)) - { - Nsub++; - d=(x3-x1)/d0; - x2=x1-d*d0*f1/(f3-f1); - TrimAxes[current_axis]->SetControl(x2); - TrimAxes[current_axis]->Run(); - f2=TrimAxes[current_axis]->GetState(); - if (Debug > 1) - { - cout << "FGTrim::solve Nsub,x1,x2,x3: " << Nsub << ", " << x1 - << ", " << x2 << ", " << x3 << endl; - cout << " " << f1 << ", " << f2 << ", " << f3 << endl; - } - if (f1*f2 <= 0.0) - { - x3=x2; - f3=f2; - f1=relax*f1; - //cout << "Solution is between x1 and x2" << endl; - } - else if (f2*f3 <= 0.0) - { - x1=x2; - f1=f2; - f3=relax*f3; - //cout << "Solution is between x2 and x3" << endl; - - } - //cout << i << endl; - - - }//end while - if (Nsub < max_sub_iterations) success=true; - } - return success; +bool FGTrim::solve(void) { + + double x1,x2,x3,f1,f2,f3,d,d0; + const double relax =0.9; + double eps=TrimAxes[current_axis]->GetSolverEps(); + + x1=x2=x3=0; + d=1; + bool success=false; + //initializations + if( solutionDomain != 0) { + /* if(ahi > alo) { */ + x1=xlo;f1=alo; + x3=xhi;f3=ahi; + /* } else { + x1=xhi;f1=ahi; + x3=xlo;f3=alo; + } */ + d0=fabs(x3-x1); + //iterations + //max_sub_iterations=TrimAxes[current_axis]->GetIterationLimit(); + while ( (TrimAxes[current_axis]->InTolerance() == false ) + && (fabs(d) > eps) && (Nsub < max_sub_iterations)) { + Nsub++; + d=(x3-x1)/d0; + x2=x1-d*d0*f1/(f3-f1); + TrimAxes[current_axis]->SetControl(x2); + TrimAxes[current_axis]->Run(); + f2=TrimAxes[current_axis]->GetState(); + if(Debug > 1) { + cout << "FGTrim::solve Nsub,x1,x2,x3: " << Nsub << ", " << x1 + << ", " << x2 << ", " << x3 << endl; + cout << " " << f1 << ", " << f2 << ", " << f3 << endl; + } + if(f1*f2 <= 0.0) { + x3=x2; + f3=f2; + f1=relax*f1; + //cout << "Solution is between x1 and x2" << endl; + } + else if(f2*f3 <= 0.0) { + x1=x2; + f1=f2; + f3=relax*f3; + //cout << "Solution is between x2 and x3" << endl; + + } + //cout << i << endl; + + + }//end while + if(Nsub < max_sub_iterations) success=true; + } + return success; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -505,70 +446,59 @@ bool FGTrim::solve(void) no assumptions about the state of the sim after this function has run can be made. */ -bool FGTrim::findInterval(void) -{ - bool found=false; - double step; - double current_control=TrimAxes[current_axis]->GetControl(); - double current_accel=TrimAxes[current_axis]->GetState();; - double xmin=TrimAxes[current_axis]->GetControlMin(); - double xmax=TrimAxes[current_axis]->GetControlMax(); - double lastxlo,lastxhi,lastalo,lastahi; - - step=0.025*fabs(xmax); - xlo=xhi=current_control; - alo=ahi=current_accel; - lastxlo=xlo; - lastxhi=xhi; - lastalo=alo; - lastahi=ahi; - do - { - - Nsub++; - step*=2; - xlo-=step; - if (xlo < xmin) xlo=xmin; - xhi+=step; - if (xhi > xmax) xhi=xmax; - TrimAxes[current_axis]->SetControl(xlo); - TrimAxes[current_axis]->Run(); - alo=TrimAxes[current_axis]->GetState(); - TrimAxes[current_axis]->SetControl(xhi); - TrimAxes[current_axis]->Run(); - ahi=TrimAxes[current_axis]->GetState(); - if (fabs(ahi-alo) <= TrimAxes[current_axis]->GetTolerance()) continue; - if (alo*ahi <=0) //found interval with root - { - found=true; - if (alo*current_accel <= 0) //narrow interval down a bit - { - solutionDomain=-1; - xhi=lastxlo; - ahi=lastalo; - //xhi=current_control; - //ahi=current_accel; - } - else - { - solutionDomain=1; - xlo=lastxhi; - alo=lastahi; - //xlo=current_control; - //alo=current_accel; - } - } - lastxlo=xlo; - lastxhi=xhi; - lastalo=alo; - lastahi=ahi; - if ( !found && xlo==xmin && xhi==xmax ) continue; - if (Debug > 1) - cout << "FGTrim::findInterval: Nsub=" << Nsub << " Lo= " << xlo - << " Hi= " << xhi << " alo*ahi: " << alo*ahi << endl; +bool FGTrim::findInterval(void) { + bool found=false; + double step; + double current_control=TrimAxes[current_axis]->GetControl(); + double current_accel=TrimAxes[current_axis]->GetState();; + double xmin=TrimAxes[current_axis]->GetControlMin(); + double xmax=TrimAxes[current_axis]->GetControlMax(); + double lastxlo,lastxhi,lastalo,lastahi; + + step=0.025*fabs(xmax); + xlo=xhi=current_control; + alo=ahi=current_accel; + lastxlo=xlo;lastxhi=xhi; + lastalo=alo;lastahi=ahi; + do { + + Nsub++; + step*=2; + xlo-=step; + if(xlo < xmin) xlo=xmin; + xhi+=step; + if(xhi > xmax) xhi=xmax; + TrimAxes[current_axis]->SetControl(xlo); + TrimAxes[current_axis]->Run(); + alo=TrimAxes[current_axis]->GetState(); + TrimAxes[current_axis]->SetControl(xhi); + TrimAxes[current_axis]->Run(); + ahi=TrimAxes[current_axis]->GetState(); + if(fabs(ahi-alo) <= TrimAxes[current_axis]->GetTolerance()) continue; + if(alo*ahi <=0) { //found interval with root + found=true; + if(alo*current_accel <= 0) { //narrow interval down a bit + solutionDomain=-1; + xhi=lastxlo; + ahi=lastalo; + //xhi=current_control; + //ahi=current_accel; + } else { + solutionDomain=1; + xlo=lastxhi; + alo=lastahi; + //xlo=current_control; + //alo=current_accel; + } } - while (!found && (Nsub <= max_sub_iterations) ); - return found; + lastxlo=xlo;lastxhi=xhi; + lastalo=alo;lastahi=ahi; + if( !found && xlo==xmin && xhi==xmax ) continue; + if(Debug > 1) + cout << "FGTrim::findInterval: Nsub=" << Nsub << " Lo= " << xlo + << " Hi= " << xhi << " alo*ahi: " << alo*ahi << endl; + } while(!found && (Nsub <= max_sub_iterations) ); + return found; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -586,154 +516,131 @@ bool FGTrim::findInterval(void) //xhi=xmax and ahi=accel(xmax) //in all cases the sim is left such that the control=xmax and accel=ahi -bool FGTrim::checkLimits(void) -{ - bool solutionExists; - double current_control=TrimAxes[current_axis]->GetControl(); - double current_accel=TrimAxes[current_axis]->GetState(); - xlo=TrimAxes[current_axis]->GetControlMin(); - xhi=TrimAxes[current_axis]->GetControlMax(); - - TrimAxes[current_axis]->SetControl(xlo); - TrimAxes[current_axis]->Run(); - alo=TrimAxes[current_axis]->GetState(); - TrimAxes[current_axis]->SetControl(xhi); - TrimAxes[current_axis]->Run(); - ahi=TrimAxes[current_axis]->GetState(); - if (Debug > 1) - cout << "checkLimits() xlo,xhi,alo,ahi: " << xlo << ", " << xhi << ", " - << alo << ", " << ahi << endl; - solutionDomain=0; - solutionExists=false; - if (fabs(ahi-alo) > TrimAxes[current_axis]->GetTolerance()) - { - if (alo*current_accel <= 0) - { - solutionExists=true; - solutionDomain=-1; - xhi=current_control; - ahi=current_accel; - } - else if (current_accel*ahi < 0) - { - solutionExists=true; - solutionDomain=1; - xlo=current_control; - alo=current_accel; - } +bool FGTrim::checkLimits(void) { + bool solutionExists; + double current_control=TrimAxes[current_axis]->GetControl(); + double current_accel=TrimAxes[current_axis]->GetState(); + xlo=TrimAxes[current_axis]->GetControlMin(); + xhi=TrimAxes[current_axis]->GetControlMax(); + + TrimAxes[current_axis]->SetControl(xlo); + TrimAxes[current_axis]->Run(); + alo=TrimAxes[current_axis]->GetState(); + TrimAxes[current_axis]->SetControl(xhi); + TrimAxes[current_axis]->Run(); + ahi=TrimAxes[current_axis]->GetState(); + if(Debug > 1) + cout << "checkLimits() xlo,xhi,alo,ahi: " << xlo << ", " << xhi << ", " + << alo << ", " << ahi << endl; + solutionDomain=0; + solutionExists=false; + if(fabs(ahi-alo) > TrimAxes[current_axis]->GetTolerance()) { + if(alo*current_accel <= 0) { + solutionExists=true; + solutionDomain=-1; + xhi=current_control; + ahi=current_accel; + } else if(current_accel*ahi < 0){ + solutionExists=true; + solutionDomain=1; + xlo=current_control; + alo=current_accel; } - TrimAxes[current_axis]->SetControl(current_control); - TrimAxes[current_axis]->Run(); - return solutionExists; + } + TrimAxes[current_axis]->SetControl(current_control); + TrimAxes[current_axis]->Run(); + return solutionExists; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrim::setupPullup() -{ - double g,q,cgamma; - g=fdmex->GetInertial()->gravity(); - cgamma=cos(fgic->GetFlightPathAngleRadIC()); - cout << "setPitchRateInPullup(): " << g << ", " << cgamma << ", " - << fgic->GetVtrueFpsIC() << endl; - q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC(); - cout << targetNlf << ", " << q << endl; - fgic->SetQRadpsIC(q); - cout << "setPitchRateInPullup() complete" << endl; +void FGTrim::setupPullup() { + double g,q,cgamma; + g=fdmex->GetInertial()->gravity(); + cgamma=cos(fgic->GetFlightPathAngleRadIC()); + cout << "setPitchRateInPullup(): " << g << ", " << cgamma << ", " + << fgic->GetVtrueFpsIC() << endl; + q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC(); + cout << targetNlf << ", " << q << endl; + fgic->SetQRadpsIC(q); + cout << "setPitchRateInPullup() complete" << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrim::setupTurn(void) -{ - double g,phi; - phi = fgic->GetPhiRadIC(); - if ( fabs(phi) > 0.001 && fabs(phi) < 1.56 ) - { - targetNlf = 1 / cos(phi); - g = fdmex->GetInertial()->gravity(); - psidot = g*tan(phi) / fgic->GetUBodyFpsIC(); - cout << targetNlf << ", " << psidot << endl; - } +void FGTrim::setupTurn(void){ + double g,phi; + phi = fgic->GetPhiRadIC(); + if( fabs(phi) > 0.001 && fabs(phi) < 1.56 ) { + targetNlf = 1 / cos(phi); + g = fdmex->GetInertial()->gravity(); + psidot = g*tan(phi) / fgic->GetUBodyFpsIC(); + cout << targetNlf << ", " << psidot << endl; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrim::updateRates(void) -{ - if ( mode == tTurn ) - { - double phi = fgic->GetPhiRadIC(); - double g = fdmex->GetInertial()->gravity(); - double p,q,r,theta; - if (fabs(phi) > 0.001 && fabs(phi) < 1.56 ) - { - theta=fgic->GetThetaRadIC(); - phi=fgic->GetPhiRadIC(); - psidot = g*tan(phi) / fgic->GetUBodyFpsIC(); - p=-psidot*sin(theta); - q=psidot*cos(theta)*sin(phi); - r=psidot*cos(theta)*cos(phi); - } - else - { - p=q=r=0; - } - fgic->SetPRadpsIC(p); - fgic->SetQRadpsIC(q); - fgic->SetRRadpsIC(r); - } - else if ( mode == tPullup && fabs(targetNlf-1) > 0.01) - { - double g,q,cgamma; - g=fdmex->GetInertial()->gravity(); - cgamma=cos(fgic->GetFlightPathAngleRadIC()); - q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC(); - fgic->SetQRadpsIC(q); +void FGTrim::updateRates(void){ + if( mode == tTurn ) { + double phi = fgic->GetPhiRadIC(); + double g = fdmex->GetInertial()->gravity(); + double p,q,r,theta; + if(fabs(phi) > 0.001 && fabs(phi) < 1.56 ) { + theta=fgic->GetThetaRadIC(); + phi=fgic->GetPhiRadIC(); + psidot = g*tan(phi) / fgic->GetUBodyFpsIC(); + p=-psidot*sin(theta); + q=psidot*cos(theta)*sin(phi); + r=psidot*cos(theta)*cos(phi); + } else { + p=q=r=0; } + fgic->SetPRadpsIC(p); + fgic->SetQRadpsIC(q); + fgic->SetRRadpsIC(r); + } else if( mode == tPullup && fabs(targetNlf-1) > 0.01) { + double g,q,cgamma; + g=fdmex->GetInertial()->gravity(); + cgamma=cos(fgic->GetFlightPathAngleRadIC()); + q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC(); + fgic->SetQRadpsIC(q); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrim::setDebug(void) -{ - if (debug_axis == tAll || - TrimAxes[current_axis]->GetStateType() == debug_axis ) - { - Debug=DebugLevel; - return; - } - else - { - Debug=0; - return; - } +void FGTrim::setDebug(void) { + if(debug_axis == tAll || + TrimAxes[current_axis]->GetStateType() == debug_axis ) { + Debug=DebugLevel; + return; + } else { + Debug=0; + return; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrim::setEngineTrimMode(bool mode) -{ - FGPropulsion* prop = fdmex->GetPropulsion(); - for (unsigned int i=0; i<prop->GetNumEngines(); i++) - { - prop->GetEngine(i)->SetTrimMode(mode); - } +void FGTrim::setEngineTrimMode(bool mode) { + FGPropulsion* prop = fdmex->GetPropulsion(); + for (unsigned int i=0; i<prop->GetNumEngines(); i++) { + prop->GetEngine(i)->SetTrimMode(mode); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrim::SetMode(TrimMode tt) -{ +void FGTrim::SetMode(TrimMode tt) { ClearStates(); mode=tt; - switch (tt) - { - case tFull: + switch(tt) { + case tFull: if (debug_lvl > 0) - cout << " Full Trim" << endl; + cout << " Full Trim" << endl; TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); @@ -742,21 +649,21 @@ void FGTrim::SetMode(TrimMode tt) TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder )); break; - case tLongitudinal: + case tLongitudinal: if (debug_lvl > 0) - cout << " Longitudinal Trim" << endl; + cout << " Longitudinal Trim" << endl; TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); break; - case tGround: + case tGround: if (debug_lvl > 0) - cout << " Ground Trim" << endl; + cout << " Ground Trim" << endl; TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAltAGL )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tTheta )); //TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tPhi )); break; - case tPullup: + case tPullup: TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tNlf,tAlpha )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); @@ -765,7 +672,7 @@ void FGTrim::SetMode(TrimMode tt) TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder )); break; - case tTurn: + case tTurn: TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); @@ -773,8 +680,8 @@ void FGTrim::SetMode(TrimMode tt) TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder )); break; - case tCustom: - case tNone: + case tCustom: + case tNone: break; } //cout << "TrimAxes.size(): " << TrimAxes.size() << endl; diff --git a/src/initialization/FGTrim.h b/src/initialization/FGTrim.h index df456d7463632f38f273ccf8f4337ffab9f83fc2..0d6e3092cdd260745df07ada44d3edfa6082bf19 100644 --- a/src/initialization/FGTrim.h +++ b/src/initialization/FGTrim.h @@ -66,12 +66,10 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { typedef enum { tLongitudinal=0, tFull, tGround, tPullup, - tCustom, tTurn, tNone - } TrimMode; + tCustom, tTurn, tNone } TrimMode; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -120,7 +118,7 @@ CLASS DOCUMENTATION } fgt.Report(); @endcode - + @author Tony Peden @version "$Id: FGTrim.h,v 1.7 2010/04/23 17:23:40 dpculp Exp $" */ @@ -133,190 +131,162 @@ class FGTrim : public FGJSBBase { private: - vector<FGTrimAxis*> TrimAxes; - unsigned int current_axis; - int N, Nsub; - TrimMode mode; - int DebugLevel, Debug; - double Tolerance, A_Tolerance; - double wdot,udot,qdot; - double dth; - double *sub_iterations; - double *successful; - bool *solution; - int max_sub_iterations; - int max_iterations; - int total_its; - bool trimudot; - bool gamma_fallback; - bool trim_failed; - unsigned int axis_count; - int solutionDomain; - double xlo,xhi,alo,ahi; - double targetNlf; - int debug_axis; - - double psidot,thetadot; - - FGFDMExec* fdmex; - FGInitialCondition* fgic; - - bool solve(void); - - /** @return false if there is no change in the current axis accel - between accel(control_min) and accel(control_max). If there is a - change, sets solutionDomain to: - 0 for no sign change, - -1 if sign change between accel(control_min) and accel(0) - 1 if sign between accel(0) and accel(control_max) - */ - bool findInterval(void); - - bool checkLimits(void); - - void setupPullup(void); - void setupTurn(void); - - void updateRates(void); - void setEngineTrimMode(bool mode); - void setDebug(void); + vector<FGTrimAxis*> TrimAxes; + unsigned int current_axis; + int N, Nsub; + TrimMode mode; + int DebugLevel, Debug; + double Tolerance, A_Tolerance; + double wdot,udot,qdot; + double dth; + double *sub_iterations; + double *successful; + bool *solution; + int max_sub_iterations; + int max_iterations; + int total_its; + bool trimudot; + bool gamma_fallback; + bool trim_failed; + unsigned int axis_count; + int solutionDomain; + double xlo,xhi,alo,ahi; + double targetNlf; + int debug_axis; + + double psidot,thetadot; + + FGFDMExec* fdmex; + FGInitialCondition* fgic; + + bool solve(void); + + /** @return false if there is no change in the current axis accel + between accel(control_min) and accel(control_max). If there is a + change, sets solutionDomain to: + 0 for no sign change, + -1 if sign change between accel(control_min) and accel(0) + 1 if sign between accel(0) and accel(control_max) + */ + bool findInterval(void); + + bool checkLimits(void); + + void setupPullup(void); + void setupTurn(void); + + void updateRates(void); + void setEngineTrimMode(bool mode); + void setDebug(void); public: - /** Initializes the trimming class - @param FDMExec pointer to a JSBSim executive object. - @param tm trim mode - */ - FGTrim(FGFDMExec *FDMExec, TrimMode tm=tGround ); - - ~FGTrim(void); - - /** Execute the trim - */ - bool DoTrim(void); - - /** Print the results of the trim. For each axis trimmed, this - includes the final state value, control value, and tolerance - used. - @return true if trim succeeds - */ - void Report(void); - - /** Iteration statistics - */ - void TrimStats(); - - /** Clear all state-control pairs and set a predefined trim mode - @param tm the set of axes to trim. Can be: - tLongitudinal, tFull, tGround, tCustom, or tNone - */ - void SetMode(TrimMode tm); - - /** Clear all state-control pairs from the current configuration. - The trimming routine must have at least one state-control pair - configured to be useful - */ - void ClearStates(void); - - /** Add a state-control pair to the current configuration. See the enums - State and Control in FGTrimAxis.h for the available options. - Will fail if the given state is already configured. - @param state the accel or other condition to zero - @param control the control used to zero the state - @return true if add is successful - */ - bool AddState( State state, Control control ); - - /** Remove a specific state-control pair from the current configuration - @param state the state to remove - @return true if removal is successful - */ - bool RemoveState( State state ); - - /** Change the control used to zero a state previously configured - @param state the accel or other condition to zero - @param new_control the control used to zero the state - */ - bool EditState( State state, Control new_control ); - - /** automatically switch to trimming longitudinal acceleration with - flight path angle (gamma) once it becomes apparent that there - is not enough/too much thrust. - @param bb true to enable fallback - */ - inline void SetGammaFallback(bool bb) - { - gamma_fallback=bb; - } - - /** query the fallback state - @return true if fallback is enabled. - */ - inline bool GetGammaFallback(void) - { - return gamma_fallback; - } - - /** Set the iteration limit. DoTrim() will return false if limit - iterations are reached before trim is achieved. The default - is 60. This does not ordinarily need to be changed. - @param ii integer iteration limit - */ - inline void SetMaxCycles(int ii) - { - max_iterations = ii; - } - - /** Set the per-axis iteration limit. Attempt to zero each state - by iterating limit times before moving on to the next. The - default limit is 100 and also does not ordinarily need to - be changed. - @param ii integer iteration limit - */ - inline void SetMaxCyclesPerAxis(int ii) - { - max_sub_iterations = ii; - } - - /** Set the tolerance for declaring a state trimmed. Angular accels are - held to a tolerance of 1/10th of the given. The default is - 0.001 for the recti-linear accelerations and 0.0001 for the angular. - */ - inline void SetTolerance(double tt) - { - Tolerance = tt; - A_Tolerance = tt / 10; - } - - /** - Debug level 1 shows results of each top-level iteration - Debug level 2 shows level 1 & results of each per-axis iteration - */ - inline void SetDebug(int level) - { - DebugLevel = level; - } - inline void ClearDebug(void) - { - DebugLevel = 0; - } - - /** - Output debug data for one of the axes - The State enum is defined in FGTrimAxis.h - */ - inline void DebugState(State state) - { - debug_axis=state; - } - - inline void SetTargetNlf(double nlf) - { - targetNlf=nlf; - } - inline double GetTargetNlf(void) - { - return targetNlf; - } + /** Initializes the trimming class + @param FDMExec pointer to a JSBSim executive object. + @param tm trim mode + */ + FGTrim(FGFDMExec *FDMExec, TrimMode tm=tGround ); + + ~FGTrim(void); + + /** Execute the trim + */ + bool DoTrim(void); + + /** Print the results of the trim. For each axis trimmed, this + includes the final state value, control value, and tolerance + used. + @return true if trim succeeds + */ + void Report(void); + + /** Iteration statistics + */ + void TrimStats(); + + /** Clear all state-control pairs and set a predefined trim mode + @param tm the set of axes to trim. Can be: + tLongitudinal, tFull, tGround, tCustom, or tNone + */ + void SetMode(TrimMode tm); + + /** Clear all state-control pairs from the current configuration. + The trimming routine must have at least one state-control pair + configured to be useful + */ + void ClearStates(void); + + /** Add a state-control pair to the current configuration. See the enums + State and Control in FGTrimAxis.h for the available options. + Will fail if the given state is already configured. + @param state the accel or other condition to zero + @param control the control used to zero the state + @return true if add is successful + */ + bool AddState( State state, Control control ); + + /** Remove a specific state-control pair from the current configuration + @param state the state to remove + @return true if removal is successful + */ + bool RemoveState( State state ); + + /** Change the control used to zero a state previously configured + @param state the accel or other condition to zero + @param new_control the control used to zero the state + */ + bool EditState( State state, Control new_control ); + + /** automatically switch to trimming longitudinal acceleration with + flight path angle (gamma) once it becomes apparent that there + is not enough/too much thrust. + @param bb true to enable fallback + */ + inline void SetGammaFallback(bool bb) { gamma_fallback=bb; } + + /** query the fallback state + @return true if fallback is enabled. + */ + inline bool GetGammaFallback(void) { return gamma_fallback; } + + /** Set the iteration limit. DoTrim() will return false if limit + iterations are reached before trim is achieved. The default + is 60. This does not ordinarily need to be changed. + @param ii integer iteration limit + */ + inline void SetMaxCycles(int ii) { max_iterations = ii; } + + /** Set the per-axis iteration limit. Attempt to zero each state + by iterating limit times before moving on to the next. The + default limit is 100 and also does not ordinarily need to + be changed. + @param ii integer iteration limit + */ + inline void SetMaxCyclesPerAxis(int ii) { max_sub_iterations = ii; } + + /** Set the tolerance for declaring a state trimmed. Angular accels are + held to a tolerance of 1/10th of the given. The default is + 0.001 for the recti-linear accelerations and 0.0001 for the angular. + */ + inline void SetTolerance(double tt) { + Tolerance = tt; + A_Tolerance = tt / 10; + } + + /** + Debug level 1 shows results of each top-level iteration + Debug level 2 shows level 1 & results of each per-axis iteration + */ + inline void SetDebug(int level) { DebugLevel = level; } + inline void ClearDebug(void) { DebugLevel = 0; } + + /** + Output debug data for one of the axes + The State enum is defined in FGTrimAxis.h + */ + inline void DebugState(State state) { debug_axis=state; } + + inline void SetTargetNlf(double nlf) { targetNlf=nlf; } + inline double GetTargetNlf(void) { return targetNlf; } }; } diff --git a/src/initialization/FGTrimAnalysis.cpp b/src/initialization/FGTrimAnalysis.cpp old mode 100644 new mode 100755 index 8a530df3171a51313483162e199b63bdbe89bc9b..165659d48372537ebe229eee066bf902e8a9d101 --- a/src/initialization/FGTrimAnalysis.cpp +++ b/src/initialization/FGTrimAnalysis.cpp @@ -84,127 +84,126 @@ INCLUDES #pragma warning (disable : 4786 4788) #endif -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGTrimAnalysis.cpp,v 1.13 2009/10/02 10:30:08 jberndt Exp $"; static const char *IdHdr = ID_FGTRIMANALYSIS; -/** Wrapping function for the effective Full Trim cost function, to be called by optimization method - @param vars number ofcontrol varables - @param v reference to a vector containing controls variables - @param f function value - @param success - @param t_ptr - * the following method is friend rather then member of FGTrimAnalysis because - * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. - * - * Note that in the call masked by this methods, the void pointer - * should be cast to a pointer of the class type. - */ -//friend void find_CostFunctionFull(long vars, Vector<double> &v, double & f, -void find_CostFunctionFull(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr) -{ - (*(Objective*)t_ptr).CostFunctionFull(vars, v, f); - success = true; -} -/** Wrapping function for the effective Wings Level Trim cost function, to be called by optimization method - @param vars number ofcontrol varables - @param v reference to a vector containing controls variables - @param f function value - @param success - @param t_ptr - * the following method is friend rather then member of FGTrimAnalysis because - * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. - * - * Note that in the call masked by this methods, the void pointer - * should be cast to a pointer of the class type. - */ -//friend void find_CostFunctionFullWingsLevel(long vars, Vector<double> &v, double & f, -void find_CostFunctionFullWingsLevel(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr) -{ - (*(Objective*)t_ptr).CostFunctionFullWingsLevel(vars, v, f); - success = true; -} -/** Wrapping function for the effective Longitudinal Trim cost function, to be called by optimization method - @param vars number ofcontrol varables - @param v reference to a vector containing controls variables - @param f function value - @param success - @param t_ptr - * the following method is friend rather then member of FGTrimAnalysis because - * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. - * - * Note that in the call masked by this methods, the void pointer - * should be cast to a pointer of the class type. - */ -//friend void find_CostFunctionLongitudinal(long vars, Vector<double> &v, double & f, -void find_CostFunctionLongitudinal(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr) -{ - (*(Objective*)t_ptr).CostFunctionLongitudinal(vars, v, f); - success = true; -} -/** Wrapping function for the effective Steady Turn Trim cost function, to be called by optimization method - @param vars number ofcontrol varables - @param v reference to a vector containing controls variables - @param f function value - @param success - @param t_ptr - * the following method is friend rather then member of FGTrimAnalysis because - * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. - * - * Note that in the call masked by this methods, the void pointer - * should be cast to a pointer of the class type. - */ -//friend void find_CostFunctionFullCoordinatedTurn(long vars, Vector<double> &v, double & f, -void find_CostFunctionFullCoordinatedTurn(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr) -{ - (*(Objective*)t_ptr).CostFunctionFullCoordinatedTurn(vars, v, f); - success = true; -} -/** Wrapping function for the effective Steady Turn Trim cost function, to be called by optimization method - @param vars number ofcontrol varables - @param v reference to a vector containing controls variables - @param f function value - @param success - @param t_ptr - * the following method is friend rather then member of FGTrimAnalysis because - * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. - * - * Note that in the call masked by this methods, the void pointer - * should be cast to a pointer of the class type. - */ -//fryyiend void find_CostFunctionFullTurn(long vars, Vector<double> &v, double & f, -void find_CostFunctionFullTurn(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr) -{ - (*(Objective*)t_ptr).CostFunctionFullTurn(vars, v, f); - success = true; -} -/** Wrapping function for the effective Pullup Trim cost function, to be called by optimization method - @param vars number ofcontrol varables - @param v reference to a vector containing controls variables - @param f function value - @param success - @param t_ptr - * the following method is friend rather then member of FGTrimAnalysis because - * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. - * - * Note that in the call masked by this methods, the void pointer - * should be cast to a pointer of the class type. - */ -//friend void find_CostFunctionPullUp(long vars, Vector<double> &v, double & f, -void find_CostFunctionPullUp(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr) -{ - (*(Objective*)t_ptr).CostFunctionPullUp(vars, v, f); - success = true; -} + /** Wrapping function for the effective Full Trim cost function, to be called by optimization method + @param vars number ofcontrol varables + @param v reference to a vector containing controls variables + @param f function value + @param success + @param t_ptr + * the following method is friend rather then member of FGTrimAnalysis because + * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. + * + * Note that in the call masked by this methods, the void pointer + * should be cast to a pointer of the class type. + */ + //friend void find_CostFunctionFull(long vars, Vector<double> &v, double & f, + void find_CostFunctionFull(long vars, Vector<double> &v, double & f, + bool & success, void* t_ptr) + { + (*(Objective*)t_ptr).CostFunctionFull(vars, v, f); + success = true; + } + /** Wrapping function for the effective Wings Level Trim cost function, to be called by optimization method + @param vars number ofcontrol varables + @param v reference to a vector containing controls variables + @param f function value + @param success + @param t_ptr + * the following method is friend rather then member of FGTrimAnalysis because + * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. + * + * Note that in the call masked by this methods, the void pointer + * should be cast to a pointer of the class type. + */ + //friend void find_CostFunctionFullWingsLevel(long vars, Vector<double> &v, double & f, + void find_CostFunctionFullWingsLevel(long vars, Vector<double> &v, double & f, + bool & success, void* t_ptr) + { + (*(Objective*)t_ptr).CostFunctionFullWingsLevel(vars, v, f); + success = true; + } + /** Wrapping function for the effective Longitudinal Trim cost function, to be called by optimization method + @param vars number ofcontrol varables + @param v reference to a vector containing controls variables + @param f function value + @param success + @param t_ptr + * the following method is friend rather then member of FGTrimAnalysis because + * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. + * + * Note that in the call masked by this methods, the void pointer + * should be cast to a pointer of the class type. + */ + //friend void find_CostFunctionLongitudinal(long vars, Vector<double> &v, double & f, + void find_CostFunctionLongitudinal(long vars, Vector<double> &v, double & f, + bool & success, void* t_ptr) + { + (*(Objective*)t_ptr).CostFunctionLongitudinal(vars, v, f); + success = true; + } + /** Wrapping function for the effective Steady Turn Trim cost function, to be called by optimization method + @param vars number ofcontrol varables + @param v reference to a vector containing controls variables + @param f function value + @param success + @param t_ptr + * the following method is friend rather then member of FGTrimAnalysis because + * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. + * + * Note that in the call masked by this methods, the void pointer + * should be cast to a pointer of the class type. + */ + //friend void find_CostFunctionFullCoordinatedTurn(long vars, Vector<double> &v, double & f, + void find_CostFunctionFullCoordinatedTurn(long vars, Vector<double> &v, double & f, + bool & success, void* t_ptr) + { + (*(Objective*)t_ptr).CostFunctionFullCoordinatedTurn(vars, v, f); + success = true; + } + /** Wrapping function for the effective Steady Turn Trim cost function, to be called by optimization method + @param vars number ofcontrol varables + @param v reference to a vector containing controls variables + @param f function value + @param success + @param t_ptr + * the following method is friend rather then member of FGTrimAnalysis because + * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. + * + * Note that in the call masked by this methods, the void pointer + * should be cast to a pointer of the class type. + */ + //fryyiend void find_CostFunctionFullTurn(long vars, Vector<double> &v, double & f, + void find_CostFunctionFullTurn(long vars, Vector<double> &v, double & f, + bool & success, void* t_ptr) + { + (*(Objective*)t_ptr).CostFunctionFullTurn(vars, v, f); + success = true; + } + /** Wrapping function for the effective Pullup Trim cost function, to be called by optimization method + @param vars number ofcontrol varables + @param v reference to a vector containing controls variables + @param f function value + @param success + @param t_ptr + * the following method is friend rather then member of FGTrimAnalysis because + * we want our FGTrimAnalysis::DoTrim() to be able to pass pointers to it. + * + * Note that in the call masked by this methods, the void pointer + * should be cast to a pointer of the class type. + */ + //friend void find_CostFunctionPullUp(long vars, Vector<double> &v, double & f, + void find_CostFunctionPullUp(long vars, Vector<double> &v, double & f, + bool & success, void* t_ptr) + { + (*(Objective*)t_ptr).CostFunctionPullUp(vars, v, f); + success = true; + } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //public: @@ -220,104 +219,92 @@ Objective::Objective(FGFDMExec* fdmex, FGTrimAnalysis* ta, double x) : _x(x), Tr void Objective::CostFunctionFull(long vars, Vector<double> &v, double & f) { - if (vars != 7) - { - cerr << "\nError: (Cost function for taFull mode) Dimension must be 7 !!\n"; - exit(1); - } - if (TrimAnalysis->GetMode()!=taFull) - { - cerr << "\nError: must be taFull mode !!\n"; - exit(1); - } - - f = myCostFunctionFull(v); - return; + if (vars != 7) { + cerr << "\nError: (Cost function for taFull mode) Dimension must be 7 !!\n"; + exit(1); + } + if (TrimAnalysis->GetMode()!=taFull){ + cerr << "\nError: must be taFull mode !!\n"; + exit(1); + } + + f = myCostFunctionFull(v); + return; } void Objective::CostFunctionFullWingsLevel(long vars, Vector<double> &v, double & f) { - if (vars != 6) - { - cerr << "\nError: (Cost function for taFullWingsLevel mode) Dimension must be 6 !!\n"; - exit(1); - } - if (TrimAnalysis->GetMode()!=taFullWingsLevel) - { - cerr << "\nError: must be taFull mode !!\n"; - exit(1); - } - - f = myCostFunctionFullWingsLevel(v); - return; + if (vars != 6) { + cerr << "\nError: (Cost function for taFullWingsLevel mode) Dimension must be 6 !!\n"; + exit(1); + } + if (TrimAnalysis->GetMode()!=taFullWingsLevel){ + cerr << "\nError: must be taFull mode !!\n"; + exit(1); + } + + f = myCostFunctionFullWingsLevel(v); + return; } void Objective::CostFunctionLongitudinal(long vars, Vector<double> &v, double & f) { - if (vars != 3) - { - cerr << "\nError: (Cost function for taLongitudinal mode) Dimension must be 3 !!\n"; - exit(1); - } - if (TrimAnalysis->GetMode()!=taLongitudinal) - { - cerr << "\nError: trim mode must be taLongitudinal mode !!\n"; - exit(1); - } - - f = myCostFunctionLongitudinal(v); - return; + if (vars != 3) { + cerr << "\nError: (Cost function for taLongitudinal mode) Dimension must be 3 !!\n"; + exit(1); + } + if (TrimAnalysis->GetMode()!=taLongitudinal){ + cerr << "\nError: trim mode must be taLongitudinal mode !!\n"; + exit(1); + } + + f = myCostFunctionLongitudinal(v); + return; } void Objective::CostFunctionFullCoordinatedTurn(long vars, Vector<double> &v, double & f) { - if (vars != 5) - { - cerr << "\nError: (Cost function for taTurn mode) Dimension must be 5 !!\n"; - exit(1); - } - if (TrimAnalysis->GetMode()!=taTurn) - { - cerr << "\nError: trim mode must be taTurn mode !!\n"; - exit(1); - } - - f = myCostFunctionFullCoordinatedTurn(v); - return; + if (vars != 5) { + cerr << "\nError: (Cost function for taTurn mode) Dimension must be 5 !!\n"; + exit(1); + } + if (TrimAnalysis->GetMode()!=taTurn){ + cerr << "\nError: trim mode must be taTurn mode !!\n"; + exit(1); + } + + f = myCostFunctionFullCoordinatedTurn(v); + return; } void Objective::CostFunctionFullTurn(long vars, Vector<double> &v, double & f) { - if (vars != 6) - { - cerr << "\nError: (Cost function for taTurn mode) Dimension must be 6 !!\n"; - exit(1); - } - if (TrimAnalysis->GetMode()!=taTurnFull) - { - cerr << "\nError: trim mode must be taTurnFull ("<< (int)taTurnFull << ") mode !!\n"; - exit(1); - } - - f = myCostFunctionFullTurn(v); - return; + if (vars != 6) { + cerr << "\nError: (Cost function for taTurn mode) Dimension must be 6 !!\n"; + exit(1); + } + if (TrimAnalysis->GetMode()!=taTurnFull){ + cerr << "\nError: trim mode must be taTurnFull ("<< (int)taTurnFull << ") mode !!\n"; + exit(1); + } + + f = myCostFunctionFullTurn(v); + return; } void Objective::CostFunctionPullUp(long vars, Vector<double> &v, double & f) { - if (vars != 5) - { - cerr << "\nError: (Cost function for taPullup mode) Dimension must be 5 !!\n"; - exit(1); - } - if (TrimAnalysis->GetMode()!=taPullup) - { - cerr << "\nError: trim mode must be taPullup mode !!\n"; - exit(1); - } - - f = myCostFunctionPullUp(v); - return; + if (vars != 5) { + cerr << "\nError: (Cost function for taPullup mode) Dimension must be 5 !!\n"; + exit(1); + } + if (TrimAnalysis->GetMode()!=taPullup){ + cerr << "\nError: trim mode must be taPullup mode !!\n"; + exit(1); + } + + f = myCostFunctionPullUp(v); + return; } void Objective::Set_x_val(double new_x) @@ -332,110 +319,101 @@ void Objective::Set_x_val(double new_x) FGTrimAnalysis::FGTrimAnalysis(FGFDMExec *FDMExec,TrimAnalysisMode tt) { - SetDebug(2); - - N=0; - - trim_failed = true; - - max_iterations=2500; - stop_criterion="Stop-On-Delta"; - - Debug=0; - DebugLevel=0; - - fdmex=FDMExec; - - fgic=fdmex->GetIC(); - total_its=0; - trimudot=true; - gamma_fallback=true; - ctrl_count=0; - mode=tt; - _targetNlf=1.0; - _targetNlf=fgic->GetTargetNlfIC(); - - _vtIC = fgic->GetVtrueFpsIC(); - _hIC = fgic->GetAltitudeFtIC(); - _gamma = fgic->GetFlightPathAngleRadIC(); - _rocIC = _vtIC*cos(_gamma); - _vdownIC = _rocIC; - - // state variables - _u = fgic->GetUBodyFpsIC(); - _v = fgic->GetVBodyFpsIC(); - _w = fgic->GetWBodyFpsIC(); - _p = fgic->GetPRadpsIC(); - _q = fgic->GetQRadpsIC(); - _r = fgic->GetRRadpsIC(); - _alpha = fgic->GetAlphaRadIC(); - _beta = fgic->GetBetaRadIC(); - _theta = fgic->GetThetaRadIC(); - _phi = fgic->GetPhiRadIC(); - _psiIC = fgic->GetPsiRadIC(); - _psi = _psiIC; - _psigtIC = _psi; - - _phiW = _psiW = 0.0; - - _vgIC = _vtIC*cos(_gamma); - _vnorthIC = _vgIC * cos(_psigtIC); - _veastIC = _vgIC * sin(_psigtIC); - wnorthIC = _weastIC = _wdownIC = 0.; - - _udot=_vdot=_wdot=_pdot=_qdot=_rdot=0.; - _psidot=_thetadot=0.; - _psiWdot = _phiWdot = _gammadot = 0.; - - C1 = C2 = C3 = 1.0; - _cbeta = cos(_beta); - _sbeta = sin(_beta); - _sphi = sin(_phi); - - SetMode(tt); // creates vTrimAnalysisControls - fdmex->SetTrimMode( (int)tt ); - - trim_id = "default-trim"; - - // direct search stuff - search_type = "Nelder-Mead"; - sigma_nm = 0.5; - alpha_nm = 1.0; - beta_nm = 0.5; - gamma_nm = 2.0; - initial_step = 0.01; - tolerance = 1.0E-10; // 0.0000000001 - cost_function_value = 9999.0; - - rf_name = ""; - if (rf.is_open()) rf.close(); - - Auxiliary = fdmex->GetAuxiliary(); - Aerodynamics = fdmex->GetAerodynamics(); - Propulsion = fdmex->GetPropulsion(); - FCS = fdmex->GetFCS(); + SetDebug(2); + + N=0; + + trim_failed = true; + + max_iterations=2500; + stop_criterion="Stop-On-Delta"; + + Debug=0;DebugLevel=0; + + fdmex=FDMExec; + + fgic=fdmex->GetIC(); + total_its=0; + trimudot=true; + gamma_fallback=true; + ctrl_count=0; + mode=tt; + _targetNlf=1.0; + _targetNlf=fgic->GetTargetNlfIC(); + + _vtIC = fgic->GetVtrueFpsIC(); + _hIC = fgic->GetAltitudeFtIC(); + _gamma = fgic->GetFlightPathAngleRadIC(); + _rocIC = _vtIC*cos(_gamma); + _vdownIC = _rocIC; + + // state variables + _u = fgic->GetUBodyFpsIC(); + _v = fgic->GetVBodyFpsIC(); + _w = fgic->GetWBodyFpsIC(); + _p = fgic->GetPRadpsIC(); + _q = fgic->GetQRadpsIC(); + _r = fgic->GetRRadpsIC(); + _alpha = fgic->GetAlphaRadIC(); + _beta = fgic->GetBetaRadIC(); + _theta = fgic->GetThetaRadIC(); + _phi = fgic->GetPhiRadIC(); + _psiIC = fgic->GetPsiRadIC(); + _psi = _psiIC; + _psigtIC = _psi; + + _phiW = _psiW = 0.0; + + _vgIC = _vtIC*cos(_gamma); + _vnorthIC = _vgIC * cos(_psigtIC); + _veastIC = _vgIC * sin(_psigtIC); + wnorthIC = _weastIC = _wdownIC = 0.; + + _udot=_vdot=_wdot=_pdot=_qdot=_rdot=0.; + _psidot=_thetadot=0.; + _psiWdot = _phiWdot = _gammadot = 0.; + + C1 = C2 = C3 = 1.0; + _cbeta = cos(_beta); + _sbeta = sin(_beta); + _sphi = sin(_phi); + + SetMode(tt); // creates vTrimAnalysisControls + fdmex->SetTrimMode( (int)tt ); + + trim_id = "default-trim"; + + // direct search stuff + search_type = "Nelder-Mead"; + sigma_nm = 0.5; alpha_nm = 1.0; beta_nm = 0.5; gamma_nm = 2.0; + initial_step = 0.01; + tolerance = 1.0E-10; // 0.0000000001 + cost_function_value = 9999.0; + + rf_name = ""; + if (rf.is_open()) rf.close(); + + Auxiliary = fdmex->GetAuxiliary(); + Aerodynamics = fdmex->GetAerodynamics(); + Propulsion = fdmex->GetPropulsion(); + FCS = fdmex->GetFCS(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FGTrimAnalysis::~FGTrimAnalysis(void) -{ +FGTrimAnalysis::~FGTrimAnalysis(void) { - ClearControls(); + ClearControls(); - vAlphaDeg.clear(); - vCL.clear(); - vCD.clear(); - vCm.clear(); - vThrottleCmd.clear(); - vElevatorCmd.clear(); - vVn.clear(); - vTn.clear(); + vAlphaDeg.clear(); + vCL.clear(); vCD.clear(); vCm.clear(); + vThrottleCmd.clear(); vElevatorCmd.clear(); + vVn.clear(); vTn.clear(); - if (rf.is_open()) rf.close(); + if (rf.is_open()) rf.close(); - fdmex->SetTrimStatus(false); - fdmex->SetTrimMode( 99 ); + fdmex->SetTrimStatus(false); + fdmex->SetTrimMode( 99 ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -443,18 +421,10 @@ FGTrimAnalysis::~FGTrimAnalysis(void) void FGTrimAnalysis::SetState(double u0, double v0, double w0, double p0, double q0, double r0, double alpha0, double beta0, double phi0, double theta0, double psi0, double gamma0) { - _u=u0; - _v=v0; - _w=w0; - _p=p0; - _q=q0; - _r=r0; - _alpha=alpha0; - _beta=beta0; - _gamma=gamma0; - _theta=theta0; - _phi=phi0; - _psi=psi0; + _u=u0; _v=v0; _w=w0; + _p=p0; _q=q0; _r=r0; + _alpha=alpha0; _beta=beta0; _gamma=gamma0; + _theta=theta0; _phi=phi0; _psi=psi0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -462,15 +432,9 @@ void FGTrimAnalysis::SetState(double u0, double v0, double w0, double p0, double void FGTrimAnalysis::SetEulerAngles(double phi, double theta, double psi) { // feed into private variables - _phi = phi; - _cphi = cos(_phi); - _sphi = sin(_phi); - _theta = theta; - _ctheta = cos(_theta); - _stheta = sin(_theta); - _psi = psi; - _cpsi = cos(_psi); - _spsi = sin(_psi); + _phi = phi; _cphi = cos(_phi); _sphi = sin(_phi); + _theta = theta; _ctheta = cos(_theta); _stheta = sin(_theta); + _psi = psi; _cpsi = cos(_psi); _spsi = sin(_psi); } @@ -478,12 +442,7 @@ void FGTrimAnalysis::SetEulerAngles(double phi, double theta, double psi) void FGTrimAnalysis::SetDottedValues(double udot, double vdot, double wdot, double pdot, double qdot, double rdot) { - _udot=udot; - _vdot=vdot; - _wdot=wdot; - _pdot=pdot; - _qdot=qdot; - _rdot=rdot; + _udot=udot; _vdot=vdot; _wdot=wdot; _pdot=pdot; _qdot=qdot; _rdot=rdot; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -499,20 +458,16 @@ bool FGTrimAnalysis::Load(string fname, bool useStoredPath) sep = ";"; # endif - if ( useStoredPath ) - { + if( useStoredPath ) { trimDef = fdmex->GetFullAircraftPath() + sep + fname + ".xml"; - } - else - { + } else { trimDef = fname; } document = this->LoadXMLDocument(trimDef); trimCfg = document->FindElement("trim_config"); - if (!trimCfg) - { + if (!trimCfg) { cerr << "File: " << trimDef << " does not contain a trim configuration tag" << endl; return false; } @@ -523,16 +478,12 @@ bool FGTrimAnalysis::Load(string fname, bool useStoredPath) // First, find "search" element that specifies the type of cost function minimum search search_element = trimCfg->FindElement("search"); - if (!search_element) - { + if (!search_element) { cerr << "Using the Nelder-Mead search algorithm (default)." << endl; - } - else - { + } else { type = search_element->GetAttributeValue("type"); if (type.size() > 0) search_type = type; // if search type is not set, default is already Nelder-Mead - if (search_type == "Nelder-Mead") - { + if (search_type == "Nelder-Mead") { // Read settings from search // Note: all of these have defaults set above if ( search_element->FindElement("sigma_nm") ) @@ -548,16 +499,13 @@ bool FGTrimAnalysis::Load(string fname, bool useStoredPath) // if (search_type == "Sequential-Multiple-Nelder-Mead") { } // if (search_type == "Multicompass") { } // etc ... - if ( search_element->FindElement("tolerance") ) - { + if ( search_element->FindElement("tolerance") ) { tolerance = search_element->FindElement("tolerance")->GetAttributeValueAsNumber("value"); } - if ( search_element->FindElement("max_iterations") ) - { + if ( search_element->FindElement("max_iterations") ) { max_iterations = (unsigned int)search_element->FindElement("max_iterations")->GetAttributeValueAsNumber("value"); } - if ( search_element->FindElement("stop_criterion") ) - { + if ( search_element->FindElement("stop_criterion") ) { stop_criterion = search_element->FindElement("stop_criterion")->GetAttributeValue("type"); } } @@ -569,24 +517,23 @@ bool FGTrimAnalysis::Load(string fname, bool useStoredPath) element = trimCfg->FindElement("phi"); InitializeTrimControl(fgic->GetPhiRadIC(), element, "RAD", JSBSim::taPhi); if ( ( fabs(_phi) < 89.5*(FGJSBBase::degtorad ) ) && ( mode == taTurn )) - _targetNlf = 1./cos(_phi); + _targetNlf = 1./cos(_phi); element = trimCfg->FindElement("theta"); InitializeTrimControl(fgic->GetThetaRadIC(), element, "RAD", JSBSim::taTheta); - + element = trimCfg->FindElement("psi"); InitializeTrimControl(fgic->GetPsiRadIC(), element, "RAD", JSBSim::taHeading); element = trimCfg->FindElement("gamma"); _gamma = fgic->GetFlightPathAngleRadIC(); if (element) - if (element->GetNumDataLines() > 0) _gamma = element->GetDataAsNumber(); + if (element->GetNumDataLines() > 0) _gamma = element->GetDataAsNumber(); element = trimCfg->FindElement("nlf"); - if (element) - { - if (element->GetNumDataLines() > 0) _targetNlf = element->GetDataAsNumber(); - CalculatePhiWFromTargetNlfTurn(_targetNlf); + if (element) { + if (element->GetNumDataLines() > 0) _targetNlf = element->GetDataAsNumber(); + CalculatePhiWFromTargetNlfTurn(_targetNlf); } element = trimCfg->FindElement("throttle_cmd"); @@ -602,15 +549,11 @@ bool FGTrimAnalysis::Load(string fname, bool useStoredPath) if (element) InitializeTrimControl(0, element, "", JSBSim::taAileron); output_element = trimCfg->FindElement("output_file"); - if (output_element) - { + if (output_element) { rf_name = output_element->GetAttributeValue("name"); - if (rf_name.empty()) - { + if (rf_name.empty()) { cerr << "name must be specified in output_file \"name\" attribute."<< endl; - } - else - { + } else { if ( !SetResultsFile(rf_name) ) cerr << "Unable to use output file "<< rf_name << endl; } @@ -622,112 +565,103 @@ bool FGTrimAnalysis::Load(string fname, bool useStoredPath) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGTrimAnalysis::InitializeTrimControl(double default_value, Element* el, - string unit, TaControl type) + string unit, TaControl type) { - Element *step_size_element=0, *trim_config=0; - double iv = 0.0; - double step = 0.0; // default step value - bool set_override = false; - - iv = default_value; - - if (el != 0) - { - string name = el->GetName(); - trim_config = el->GetParent(); - set_override = el->GetNumDataLines() != 0; - if (set_override) - { - if (unit.empty()) iv = trim_config->FindElementValueAsNumber(name); - else iv = trim_config->FindElementValueAsNumberConvertTo(name, unit); - } - if (el->GetAttributeValueAsNumber("step_size") != HUGE_VAL) - step = el->GetAttributeValueAsNumber("step_size"); - } - - for (unsigned int i=0; i<vTrimAnalysisControls.size(); i++) - { - if (vTrimAnalysisControls[i]->GetControlType() == type) - { - vTrimAnalysisControls[i]->SetControlInitialValue(iv); - vTrimAnalysisControls[i]->SetControlStep(step); - break; - } - } - - return set_override; + Element *step_size_element=0, *trim_config=0; + double iv = 0.0; + double step = 0.0; // default step value + bool set_override = false; + + iv = default_value; + + if (el != 0) { + string name = el->GetName(); + trim_config = el->GetParent(); + set_override = el->GetNumDataLines() != 0; + if (set_override) { + if (unit.empty()) iv = trim_config->FindElementValueAsNumber(name); + else iv = trim_config->FindElementValueAsNumberConvertTo(name, unit); + } + if (el->GetAttributeValueAsNumber("step_size") != HUGE_VAL) + step = el->GetAttributeValueAsNumber("step_size"); + } + + for (unsigned int i=0; i<vTrimAnalysisControls.size(); i++) { + if (vTrimAnalysisControls[i]->GetControlType() == type) { + vTrimAnalysisControls[i]->SetControlInitialValue(iv); + vTrimAnalysisControls[i]->SetControlStep(step); + break; + } + } + + return set_override; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrimAnalysis::TrimStats() -{ - int run_sum=0; - cout << endl << " Trim Statistics: " << endl; - cout << " Total Iterations: " << total_its << endl; +void FGTrimAnalysis::TrimStats() { + int run_sum=0; + cout << endl << " Trim Statistics: " << endl; + cout << " Total Iterations: " << total_its << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrimAnalysis::Report(void) -{ +void FGTrimAnalysis::Report(void) { cout << "---------------------------------------------------------------------\n"; cout << "Trim report: " << endl; - cout << "\tTrim algorithm terminated with the following values:" << endl; - cout << "\tu, v, w (ft/s): " << _u <<", "<< _v <<", "<< _w << endl - << "\tp, q, r (rad/s): " << _p <<", "<< _q <<", "<< _r << endl - << "\talpha, beta (deg): " << _alpha*57.3 <<", "<< _beta*57.3 << endl - << "\tphi, theta, psi (deg): " << _phi*57.3 <<", "<< _theta*57.3 << ", " << _psi*57.3 << endl - << "\tCost function value : " << cost_function_value << endl - << "\tCycles executed : " << total_its << endl << endl; - - cout << "\tTrim variables adjusted:" << endl; - for (unsigned int i=0; i<vTrimAnalysisControls.size();i++) - { - cout << "\t\t" << vTrimAnalysisControls[i]->GetControlName() <<": "; - cout << vTrimAnalysisControls[i]->GetControl() << endl; - } - //... - - cout << endl; - - cout << "\t** Initial -> Final Conditions **" << endl; - cout << "\tAlpha IC: " << fgic->GetAlphaDegIC() << " Degrees" << endl; - cout << "\t Final: " << Auxiliary->Getalpha()*57.3 << " Degrees" << endl; - cout << "\tBeta IC: " << fgic->GetBetaDegIC() << " Degrees" << endl; - cout << "\t Final: " << Auxiliary->Getbeta()*57.3 << " Degrees" << endl; - cout << "\tGamma IC: " << fgic->GetFlightPathAngleDegIC() << " Degrees" << endl; - cout << "\t Final: " << Auxiliary->GetGamma()*57.3 << " Degrees" << endl; - cout << "\tPhi IC : " << fgic->GetPhiDegIC() << " Degrees" << endl; - cout << "\t Final: " << fdmex->GetPropagate()->GetEuler(1)*57.3 << " Degrees" << endl; - cout << "\tTheta IC: " << fgic->GetThetaDegIC() << " Degrees" << endl; - cout << "\t Final: " << fdmex->GetPropagate()->GetEuler(2)*57.3 << " Degrees" << endl; - cout << "\tPsi IC : " << fgic->GetPsiDegIC() << " Degrees" << endl; - cout << "\t Final: " << fdmex->GetPropagate()->GetEuler(3)*57.3 << " Degrees" << endl; - cout << endl; - cout << "--------------------------------------------------------------------- \n\n"; - - fdmex->EnableOutput(); + cout << "\tTrim algorithm terminated with the following values:" << endl; + cout << "\tu, v, w (ft/s): " << _u <<", "<< _v <<", "<< _w << endl + << "\tp, q, r (rad/s): " << _p <<", "<< _q <<", "<< _r << endl + << "\talpha, beta (deg): " << _alpha*57.3 <<", "<< _beta*57.3 << endl + << "\tphi, theta, psi (deg): " << _phi*57.3 <<", "<< _theta*57.3 << ", " << _psi*57.3 << endl + << "\tCost function value : " << cost_function_value << endl + << "\tCycles executed : " << total_its << endl << endl; + + cout << "\tTrim variables adjusted:" << endl; + for (unsigned int i=0; i<vTrimAnalysisControls.size();i++){ + cout << "\t\t" << vTrimAnalysisControls[i]->GetControlName() <<": "; + cout << vTrimAnalysisControls[i]->GetControl() << endl; + } + //... + + cout << endl; + + cout << "\t** Initial -> Final Conditions **" << endl; + cout << "\tAlpha IC: " << fgic->GetAlphaDegIC() << " Degrees" << endl; + cout << "\t Final: " << Auxiliary->Getalpha()*57.3 << " Degrees" << endl; + cout << "\tBeta IC: " << fgic->GetBetaDegIC() << " Degrees" << endl; + cout << "\t Final: " << Auxiliary->Getbeta()*57.3 << " Degrees" << endl; + cout << "\tGamma IC: " << fgic->GetFlightPathAngleDegIC() << " Degrees" << endl; + cout << "\t Final: " << Auxiliary->GetGamma()*57.3 << " Degrees" << endl; + cout << "\tPhi IC : " << fgic->GetPhiDegIC() << " Degrees" << endl; + cout << "\t Final: " << fdmex->GetPropagate()->GetEuler(1)*57.3 << " Degrees" << endl; + cout << "\tTheta IC: " << fgic->GetThetaDegIC() << " Degrees" << endl; + cout << "\t Final: " << fdmex->GetPropagate()->GetEuler(2)*57.3 << " Degrees" << endl; + cout << "\tPsi IC : " << fgic->GetPsiDegIC() << " Degrees" << endl; + cout << "\t Final: " << fdmex->GetPropagate()->GetEuler(3)*57.3 << " Degrees" << endl; + cout << endl; + cout << "--------------------------------------------------------------------- \n\n"; + + fdmex->EnableOutput(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrimAnalysis::ClearControls(void) -{ +void FGTrimAnalysis::ClearControls(void) { FGTrimAnalysisControl* tac; mode=taCustom; vector<FGTrimAnalysisControl*>::iterator iControls; iControls = vTrimAnalysisControls.begin(); - while (iControls != vTrimAnalysisControls.end()) - { - tac=*iControls; - delete tac; + while (iControls != vTrimAnalysisControls.end()) { + tac=*iControls; + delete tac; - iControls++; + iControls++; } vTrimAnalysisControls.clear(); @@ -736,384 +670,346 @@ void FGTrimAnalysis::ClearControls(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGTrimAnalysis::AddControl( TaControl control ) -{ - - FGTrimAnalysisControl* tac; - bool result=true; - - mode = taCustom; - vector <FGTrimAnalysisControl*>::iterator iControls = vTrimAnalysisControls.begin(); - while (iControls != vTrimAnalysisControls.end()) - { - tac=*iControls; - if ( tac->GetControlType() == control ) - result=false; - iControls++; - } - if (result) - { - vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,control)); - } - return result; +bool FGTrimAnalysis::AddControl( TaControl control ) { + + FGTrimAnalysisControl* tac; + bool result=true; + + mode = taCustom; + vector <FGTrimAnalysisControl*>::iterator iControls = vTrimAnalysisControls.begin(); + while (iControls != vTrimAnalysisControls.end()) { + tac=*iControls; + if( tac->GetControlType() == control ) + result=false; + iControls++; + } + if(result) { + vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,control)); + } + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGTrimAnalysis::RemoveControl( TaControl control ) -{ +bool FGTrimAnalysis::RemoveControl( TaControl control ) { - FGTrimAnalysisControl* tac; - bool result=false; + FGTrimAnalysisControl* tac; + bool result=false; - mode = taCustom; - vector <FGTrimAnalysisControl*>::iterator iControls = vTrimAnalysisControls.begin(); - while (iControls != vTrimAnalysisControls.end()) - { - tac=*iControls; - if ( tac->GetControlType() == control ) - { - delete tac; - vTrimAnalysisControls.erase(iControls); - result=true; - continue; - } - iControls++; - } - - return result; + mode = taCustom; + vector <FGTrimAnalysisControl*>::iterator iControls = vTrimAnalysisControls.begin(); + while (iControls != vTrimAnalysisControls.end()) { + tac=*iControls; + if( tac->GetControlType() == control ) { + delete tac; + vTrimAnalysisControls.erase(iControls); + result=true; + continue; + } + iControls++; + } + + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGTrimAnalysis::EditState( TaControl new_control, double new_initvalue, double new_step, double new_min, double new_max ) -{ - FGTrimAnalysisControl* tac; - bool result=false; +bool FGTrimAnalysis::EditState( TaControl new_control, double new_initvalue, double new_step, double new_min, double new_max ) { + FGTrimAnalysisControl* tac; + bool result=false; - mode = taCustom; - vector <FGTrimAnalysisControl*>::iterator iControls = vTrimAnalysisControls.begin(); - while (iControls != vTrimAnalysisControls.end()) - { - tac=*iControls; - if ( tac->GetControlType() == new_control ) - { - vTrimAnalysisControls.insert(iControls,1,new FGTrimAnalysisControl(fdmex,fgic,new_control)); - delete tac; - vTrimAnalysisControls.erase(iControls+1); - result=true; - break; - } - iControls++; - } - return result; + mode = taCustom; + vector <FGTrimAnalysisControl*>::iterator iControls = vTrimAnalysisControls.begin(); + while (iControls != vTrimAnalysisControls.end()) { + tac=*iControls; + if( tac->GetControlType() == new_control ) { + vTrimAnalysisControls.insert(iControls,1,new FGTrimAnalysisControl(fdmex,fgic,new_control)); + delete tac; + vTrimAnalysisControls.erase(iControls+1); + result=true; + break; + } + iControls++; + } + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrimAnalysis::setupPullup() -{ - double g,q,cgamma; - g=fdmex->GetInertial()->gravity(); - cgamma=cos(fgic->GetFlightPathAngleRadIC()); - q=g*(_targetNlf-cgamma)/fgic->GetVtrueFpsIC(); - cout << _targetNlf << ", " << q << endl; - fgic->SetQRadpsIC(q); - updateRates(); +void FGTrimAnalysis::setupPullup() { + double g,q,cgamma; + g=fdmex->GetInertial()->gravity(); + cgamma=cos(fgic->GetFlightPathAngleRadIC()); + q=g*(_targetNlf-cgamma)/fgic->GetVtrueFpsIC(); + cout << _targetNlf << ", " << q << endl; + fgic->SetQRadpsIC(q); + updateRates(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrimAnalysis::CalculatePhiWFromTargetNlfTurn(double nlf) -{ - if ( ( mode == taTurn ) || ( mode == taTurnFull ) ) - { - // target Nlf is given - // set _phiW according to given Nlf - _targetNlf = nlf; - _phiW = atan2( sqrt(_targetNlf*_targetNlf-cos(_gamma)*cos(_gamma)), cos(_gamma) ); - } +void FGTrimAnalysis::CalculatePhiWFromTargetNlfTurn(double nlf){ + if ( ( mode == taTurn ) || ( mode == taTurnFull ) ) { + // target Nlf is given + // set _phiW according to given Nlf + _targetNlf = nlf; + _phiW = atan2( sqrt(_targetNlf*_targetNlf-cos(_gamma)*cos(_gamma)), cos(_gamma) ); + } } //ToDo: check formulas for nonzero gamma -void FGTrimAnalysis::setupTurn(void) -{ - - if ( mode == taTurn ) - { - // target Nlf is given - // set _phiW according to given Nlf - _phiW = atan2( sqrt(_targetNlf*_targetNlf-cos(_gamma)*cos(_gamma)), cos(_gamma) ); - C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ - sin(_phiW) *cos(_theta)*cos(_psi) ; - C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ - cos(_phiW)*sin(_gamma)*sin(_theta) ; - C3 = sin(_phiW) *sin(_theta)+ - cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; - _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) - /( sqrt(C1*C1 + C2*C2 + C3*C3) ); - _sbeta = sqrt(1.-_cbeta*_cbeta ); - _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); - _phi = asin(_sphi); - - // theta_underlined (see paper on Trim) for coordinated turn - _theta = atan2( sin(_psi)*cos(_gamma)+cos(_psi)*sin(_gamma), cos(_gamma) ); - - double g,V; - V = sqrt( _u*_u +_v*_v + _w*_w ); - g=fdmex->GetInertial()->gravity(); - _psiWdot = (g/V)*tan(_phiW); - updateRates(); - } - if ( mode == taTurnFull ) - { - // target Nlf is given - C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ - sin(_phiW) *cos(_theta)*cos(_psi) ; - C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ - cos(_phiW)*sin(_gamma)*sin(_theta) ; - C3 = sin(_phiW) *sin(_theta)+ - cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; - _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) - /( sqrt(C1*C1 + C2*C2 + C3*C3) ); - _sbeta = sqrt(1.-_cbeta*_cbeta ); - _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); - _phi = asin(_sphi); - - double g,V; - V = sqrt( _u*_u +_v*_v + _w*_w ); - g=fdmex->GetInertial()->gravity(); - _psiWdot = (g/V)*tan(_phiW); - updateRates(); - } +void FGTrimAnalysis::setupTurn(void){ + + if ( mode == taTurn ) { + // target Nlf is given + // set _phiW according to given Nlf + _phiW = atan2( sqrt(_targetNlf*_targetNlf-cos(_gamma)*cos(_gamma)), cos(_gamma) ); + C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ + sin(_phiW) *cos(_theta)*cos(_psi) ; + C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ + cos(_phiW)*sin(_gamma)*sin(_theta) ; + C3 = sin(_phiW) *sin(_theta)+ + cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; + _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) + /( sqrt(C1*C1 + C2*C2 + C3*C3) ); + _sbeta = sqrt(1.-_cbeta*_cbeta ); + _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); + _phi = asin(_sphi); + + // theta_underlined (see paper on Trim) for coordinated turn + _theta = atan2( sin(_psi)*cos(_gamma)+cos(_psi)*sin(_gamma), cos(_gamma) ); + + double g,V; + V = sqrt( _u*_u +_v*_v + _w*_w ); + g=fdmex->GetInertial()->gravity(); + _psiWdot = (g/V)*tan(_phiW); + updateRates(); + } + if ( mode == taTurnFull ) { + // target Nlf is given + C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ + sin(_phiW) *cos(_theta)*cos(_psi) ; + C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ + cos(_phiW)*sin(_gamma)*sin(_theta) ; + C3 = sin(_phiW) *sin(_theta)+ + cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; + _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) + /( sqrt(C1*C1 + C2*C2 + C3*C3) ); + _sbeta = sqrt(1.-_cbeta*_cbeta ); + _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); + _phi = asin(_sphi); + + double g,V; + V = sqrt( _u*_u +_v*_v + _w*_w ); + g=fdmex->GetInertial()->gravity(); + _psiWdot = (g/V)*tan(_phiW); + updateRates(); + } } -void FGTrimAnalysis::setupTurn(double phiW) -{ - if ( mode == taTurn ) - { - _phiW = phiW; - // recalculate target Nlf - _targetNlf = sqrt( cos(_gamma)*cos(_gamma)*tan(_phiW)*tan(_phiW) + cos(_gamma)*cos(_gamma) ); - - C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ - sin(_phiW) *cos(_theta)*cos(_psi) ; - C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ - cos(_phiW)*sin(_gamma)*sin(_theta) ; - C3 = sin(_phiW) *sin(_theta)+ - cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; - _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) - /( sqrt(C1*C1 + C2*C2 + C3*C3) ); - _sbeta = sqrt(1.-_cbeta*_cbeta ); - _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); - _phi = asin(_sphi); - - _cphi = cos(_phi); - - // theta_underlined (see paper on Trim) for coordinated turn - //_theta = atan2( sin(_psi)*cos(_gamma)+cos(_psi)*sin(_gamma), cos(_gamma) ); - - double g,V; - V = sqrt( _u*_u +_v*_v + _w*_w ); - g=fdmex->GetInertial()->gravity(); - _psiWdot = (g/V)*tan(_phiW); - updateRates(); - } - if ( mode == taTurnFull ) - { - _phiW = phiW; - // recalculate target Nlf - _targetNlf = sqrt( cos(_gamma)*cos(_gamma)*tan(_phiW)*tan(_phiW) + cos(_gamma)*cos(_gamma) ); - - C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ - sin(_phiW) *cos(_theta)*cos(_psi) ; - C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ - cos(_phiW)*sin(_gamma)*sin(_theta) ; - C3 = sin(_phiW) *sin(_theta)+ - cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; - _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) - /( sqrt(C1*C1 + C2*C2 + C3*C3) ); - _sbeta = sqrt(1.-_cbeta*_cbeta ); - _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); - _phi = asin(_sphi); - - _cphi = cos(_phi); - - // theta_underlined (see paper on Trim) for coordinated turn - //_theta = atan2( sin(_psi)*cos(_gamma)+cos(_psi)*sin(_gamma), cos(_gamma) ); - - double g,V; - V = sqrt( _u*_u +_v*_v + _w*_w ); - g=fdmex->GetInertial()->gravity(); - _psiWdot = (g/V)*tan(_phiW); - updateRates(); - } +void FGTrimAnalysis::setupTurn(double phiW){ + if ( mode == taTurn ) { + _phiW = phiW; + // recalculate target Nlf + _targetNlf = sqrt( cos(_gamma)*cos(_gamma)*tan(_phiW)*tan(_phiW) + cos(_gamma)*cos(_gamma) ); + + C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ + sin(_phiW) *cos(_theta)*cos(_psi) ; + C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ + cos(_phiW)*sin(_gamma)*sin(_theta) ; + C3 = sin(_phiW) *sin(_theta)+ + cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; + _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) + /( sqrt(C1*C1 + C2*C2 + C3*C3) ); + _sbeta = sqrt(1.-_cbeta*_cbeta ); + _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); + _phi = asin(_sphi); + + _cphi = cos(_phi); + + // theta_underlined (see paper on Trim) for coordinated turn + //_theta = atan2( sin(_psi)*cos(_gamma)+cos(_psi)*sin(_gamma), cos(_gamma) ); + + double g,V; + V = sqrt( _u*_u +_v*_v + _w*_w ); + g=fdmex->GetInertial()->gravity(); + _psiWdot = (g/V)*tan(_phiW); + updateRates(); + } + if ( mode == taTurnFull ) { + _phiW = phiW; + // recalculate target Nlf + _targetNlf = sqrt( cos(_gamma)*cos(_gamma)*tan(_phiW)*tan(_phiW) + cos(_gamma)*cos(_gamma) ); + + C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ + sin(_phiW) *cos(_theta)*cos(_psi) ; + C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ + cos(_phiW)*sin(_gamma)*sin(_theta) ; + C3 = sin(_phiW) *sin(_theta)+ + cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; + _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) + /( sqrt(C1*C1 + C2*C2 + C3*C3) ); + _sbeta = sqrt(1.-_cbeta*_cbeta ); + _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); + _phi = asin(_sphi); + + _cphi = cos(_phi); + + // theta_underlined (see paper on Trim) for coordinated turn + //_theta = atan2( sin(_psi)*cos(_gamma)+cos(_psi)*sin(_gamma), cos(_gamma) ); + + double g,V; + V = sqrt( _u*_u +_v*_v + _w*_w ); + g=fdmex->GetInertial()->gravity(); + _psiWdot = (g/V)*tan(_phiW); + updateRates(); + } } //ToDo: check formulas for nonzero gamma -void FGTrimAnalysis::setupTurnPhi(double psi, double theta) -{ - if ( mode == taTurn ) - { - _psi = psi; - _cpsi = cos(_psi); - _spsi = sin(_psi); - _theta = theta; - _ctheta = cos(_theta); - _stheta = sin(_theta); - - C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ - sin(_phiW) *cos(_theta)*cos(_psi) ; - C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ - cos(_phiW)*sin(_gamma)*sin(_theta) ; - C3 = sin(_phiW) *sin(_theta)+ - cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; - _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) - /( sqrt(C1*C1 + C2*C2 + C3*C3) ); - _sbeta = sqrt(1.-_cbeta*_cbeta ); - - _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); - _phi = asin(_sphi); - _cphi = cos(_phi); - } - if ( mode == taTurnFull ) - { - _psi = psi; - _cpsi = cos(_psi); - _spsi = sin(_psi); - _theta = theta; - _ctheta = cos(_theta); - _stheta = sin(_theta); - - C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ - sin(_phiW) *cos(_theta)*cos(_psi) ; - C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ - cos(_phiW)*sin(_gamma)*sin(_theta) ; - C3 = sin(_phiW) *sin(_theta)+ - cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; - _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) - /( sqrt(C1*C1 + C2*C2 + C3*C3) ); - _sbeta = sqrt(1.-_cbeta*_cbeta ); - - _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); - _phi = asin(_sphi); - _cphi = cos(_phi); - - } +void FGTrimAnalysis::setupTurnPhi(double psi, double theta){ + if ( mode == taTurn ) { + _psi = psi; _cpsi = cos(_psi); _spsi = sin(_psi); + _theta = theta; _ctheta = cos(_theta); _stheta = sin(_theta); + + C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ + sin(_phiW) *cos(_theta)*cos(_psi) ; + C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ + cos(_phiW)*sin(_gamma)*sin(_theta) ; + C3 = sin(_phiW) *sin(_theta)+ + cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; + _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) + /( sqrt(C1*C1 + C2*C2 + C3*C3) ); + _sbeta = sqrt(1.-_cbeta*_cbeta ); + + _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); + _phi = asin(_sphi); + _cphi = cos(_phi); + } + if ( mode == taTurnFull ) { + _psi = psi; _cpsi = cos(_psi); _spsi = sin(_psi); + _theta = theta; _ctheta = cos(_theta); _stheta = sin(_theta); + + C1 = cos(_phiW)*sin(_gamma)*cos(_theta)*sin(_psi)+ + sin(_phiW) *cos(_theta)*cos(_psi) ; + C2 = cos(_phiW)*cos(_gamma)*cos(_theta)*cos(_psi)+ + cos(_phiW)*sin(_gamma)*sin(_theta) ; + C3 = sin(_phiW) *sin(_theta)+ + cos(_phiW)*cos(_gamma)*cos(_theta)*sin(_psi) ; + _cbeta = ( C1*sin(_phiW)*cos(_gamma)+C2*cos(_phiW) + C3*sin(_phiW)*sin(_gamma) ) + /( sqrt(C1*C1 + C2*C2 + C3*C3) ); + _sbeta = sqrt(1.-_cbeta*_cbeta ); + + _sphi = ( _cbeta*sin(_phiW) * cos(_gamma) - _sbeta*sin(_gamma) )/cos(_theta); + _phi = asin(_sphi); + _cphi = cos(_phi); + + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FGColumnVector3 FGTrimAnalysis::UpdateRatesTurn(double psi, double theta, double phi, double phiW) -{ - _psi = psi; - setupTurn(phiW); // calls updateRates: updates _p,_q,_r - return FGColumnVector3(_p,_q,_r); +FGColumnVector3 FGTrimAnalysis::UpdateRatesTurn(double psi, double theta, double phi, double phiW){ + _psi = psi; + setupTurn(phiW); // calls updateRates: updates _p,_q,_r + return FGColumnVector3(_p,_q,_r); } -FGColumnVector3 FGTrimAnalysis::UpdateRatesPullup(void) -{ - double g,cgamma; - g=fdmex->GetInertial()->gravity(); - cgamma=cos(fgic->GetFlightPathAngleRadIC()); - _p = 0; - _q = g*(_targetNlf-cgamma)/fgic->GetVtrueFpsIC(); - _r = 0.; - - fgic->SetQRadpsIC(_q); - return FGColumnVector3(_p,_q,_r); +FGColumnVector3 FGTrimAnalysis::UpdateRatesPullup(void){ + double g,cgamma; + g=fdmex->GetInertial()->gravity(); + cgamma=cos(fgic->GetFlightPathAngleRadIC()); + _p = 0; + _q = g*(_targetNlf-cgamma)/fgic->GetVtrueFpsIC(); + _r = 0.; + + fgic->SetQRadpsIC(_q); + return FGColumnVector3(_p,_q,_r); } -void FGTrimAnalysis::updateRates(void) -{ - if ( ( mode == taTurn ) || ( mode == taTurnFull ) ) - { - // this is the result of a Matlab symbolic expression - double cth2 = cos(_theta)*cos(_theta), - sth2 = sin(_theta)*sin(_theta), - scth = sin(_theta)*cos(_theta), - cph2 = cos(_phiW)*cos(_phiW), - sph2 = sin(_phiW)*sin(_phiW), - scph = sin(_phiW)*cos(_phiW), - cga2 = cos(_gamma)*cos(_gamma), - scga = sin(_gamma)*cos(_gamma), - cps2 = cos(_psi)*cos(_psi), - scps = sin(_psi)*cos(_psi); - _calpha = - sqrt( - 1-cth2 - +cph2*cth2 - -2*scph*scth*cos(_gamma)*sin(_psi)+cph2*cga2*cth2 - +cph2*cga2*cth2*(1-cps2) - +2*cph2*scga*scth*cos(_psi) - -cga2*cph2 - -2*cph2*cth2*cps2 - +2*scph*sin(_gamma)*cth2*scps - +cps2*cth2 ), +void FGTrimAnalysis::updateRates(void){ + if ( ( mode == taTurn ) || ( mode == taTurnFull ) ){ + // this is the result of a Matlab symbolic expression + double cth2 = cos(_theta)*cos(_theta), + sth2 = sin(_theta)*sin(_theta), + scth = sin(_theta)*cos(_theta), + cph2 = cos(_phiW)*cos(_phiW), + sph2 = sin(_phiW)*sin(_phiW), + scph = sin(_phiW)*cos(_phiW), + cga2 = cos(_gamma)*cos(_gamma), + scga = sin(_gamma)*cos(_gamma), + cps2 = cos(_psi)*cos(_psi), + scps = sin(_psi)*cos(_psi); + _calpha = + sqrt( + 1-cth2 + +cph2*cth2 + -2*scph*scth*cos(_gamma)*sin(_psi)+cph2*cga2*cth2 + +cph2*cga2*cth2*(1-cps2) + +2*cph2*scga*scth*cos(_psi) + -cga2*cph2 + -2*cph2*cth2*cps2 + +2*scph*sin(_gamma)*cth2*scps + +cps2*cth2 ), _salpha = sqrt( 1. - _calpha*_calpha ); - _p = -_psiWdot* - ( sin(_gamma)*_calpha*_cbeta - +cos(_gamma)*sin(_phiW)*_calpha*_sbeta - +cos(_gamma)*cos(_phiW)*_salpha - ); - - _q = -_psiWdot* - ( sin(_gamma)*_sbeta - -cos(_gamma)*sin(_phiW)*_cbeta - ); - - _r = -_psiWdot* - ( sin(_gamma)*_salpha*_cbeta - +cos(_gamma)*sin(_phiW)*_salpha*_sbeta - -cos(_gamma)*cos(_phiW)*_calpha - ); - - } - else if ( mode == taPullup && fabs(_targetNlf-1) > 0.01) - { - - double g,q,cgamma; - g=fdmex->GetInertial()->gravity(); - cgamma=cos(fgic->GetFlightPathAngleRadIC()); - q=g*(_targetNlf-cgamma)/fgic->GetVtrueFpsIC(); - _q=q; - fgic->SetQRadpsIC(q); - } + _p = -_psiWdot* + ( sin(_gamma)*_calpha*_cbeta + +cos(_gamma)*sin(_phiW)*_calpha*_sbeta + +cos(_gamma)*cos(_phiW)*_salpha + ); + + _q = -_psiWdot* + ( sin(_gamma)*_sbeta + -cos(_gamma)*sin(_phiW)*_cbeta + ); + + _r = -_psiWdot* + ( sin(_gamma)*_salpha*_cbeta + +cos(_gamma)*sin(_phiW)*_salpha*_sbeta + -cos(_gamma)*cos(_phiW)*_calpha + ); + + } else if( mode == taPullup && fabs(_targetNlf-1) > 0.01) { + + double g,q,cgamma; + g=fdmex->GetInertial()->gravity(); + cgamma=cos(fgic->GetFlightPathAngleRadIC()); + q=g*(_targetNlf-cgamma)/fgic->GetVtrueFpsIC(); + _q=q; + fgic->SetQRadpsIC(q); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrimAnalysis::setDebug(void) -{ +void FGTrimAnalysis::setDebug(void) { Debug=0; return; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGTrimAnalysis::SetMode(TrimAnalysisMode tt) -{ +void FGTrimAnalysis::SetMode(TrimAnalysisMode tt) { ClearControls(); cout << "---------------------------------------------------------------------" << endl; cout << "Trim analysis performed: "; mode=tt; - switch (tt) - { - case taLongitudinal: + switch(tt) { + case taLongitudinal: if (debug_lvl > 0) - cout << " Longitudinal Trim" << endl; + cout << " Longitudinal Trim" << endl; vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taThrottle )); vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taElevator )); // TODO: taPitchTrim vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taTheta )); break; - case taFull: + case taFull: if (debug_lvl > 0) - cout << " Full Trim" << endl; + cout << " Full Trim" << endl; vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taThrottle )); vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taElevator )); // TODO: taPitchTrim vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taAileron )); // TODO: taRollTrim @@ -1122,9 +1018,9 @@ void FGTrimAnalysis::SetMode(TrimAnalysisMode tt) vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taTheta )); vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taHeading )); break; - case taFullWingsLevel: + case taFullWingsLevel: if (debug_lvl > 0) - cout << " Full Trim, Wings-Level" << endl; + cout << " Full Trim, Wings-Level" << endl; vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taThrottle )); vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taElevator )); // TODO: taPitchTrim vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taAileron )); // TODO: taRollTrim @@ -1132,11 +1028,11 @@ void FGTrimAnalysis::SetMode(TrimAnalysisMode tt) vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taTheta )); vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taHeading )); break; - case taTurn: - // ToDo: set target NLF here !!! - // ToDo: assign psiDot here !! + case taTurn: + // ToDo: set target NLF here !!! + // ToDo: assign psiDot here !! if (debug_lvl > 0) - cout << " Full Trim, Coordinated turn" << endl; + cout << " Full Trim, Coordinated turn" << endl; vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taThrottle )); vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taElevator )); // TODO: taPitchTrim vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taAileron )); // TODO: taRollTrim @@ -1145,9 +1041,9 @@ void FGTrimAnalysis::SetMode(TrimAnalysisMode tt) //vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taTheta )); vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taHeading )); break; - case taTurnFull: + case taTurnFull: if (debug_lvl > 0) - cout << " Non-coordinated Turn Trim" << endl; + cout << " Non-coordinated Turn Trim" << endl; vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taThrottle )); vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taElevator )); // TODO: taPitchTrim vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taAileron )); // TODO: taRollTrim @@ -1157,11 +1053,11 @@ void FGTrimAnalysis::SetMode(TrimAnalysisMode tt) vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taTheta )); vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taHeading )); break; - case taPullup: - // ToDo: set target NLF here !!! - // ToDo: assign qDot here !! + case taPullup: + // ToDo: set target NLF here !!! + // ToDo: assign qDot here !! if (debug_lvl > 0) - cout << " Full Trim, Pullup" << endl; + cout << " Full Trim, Pullup" << endl; vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taThrottle )); vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taElevator )); // TODO: taPitchTrim vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taAileron )); @@ -1170,17 +1066,17 @@ void FGTrimAnalysis::SetMode(TrimAnalysisMode tt) vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taTheta )); //vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taHeading )); break; - case taGround: + case taGround: if (debug_lvl > 0) - cout << " Ground Trim" << endl; + cout << " Ground Trim" << endl; vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taAltAGL )); vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taTheta )); //vTrimAnalysisControls.push_back(new FGTrimAnalysisControl(fdmex,fgic,taPhi )); break; - case taCustom: + case taCustom: // agodemar... // ...agodemar - case taNone: + case taNone: break; } @@ -1194,10 +1090,9 @@ bool FGTrimAnalysis::SetResultsFile(string name) rf_name = name; rf.open(rf_name.c_str(), ios::out); - if ( !rf.is_open() ) - { - cerr << "Unable to open " << rf_name << endl; - return false; + if ( !rf.is_open() ) { + cerr << "Unable to open " << rf_name << endl; + return false; } //rf << "# ... complete this " << endl; //rf << "# iteration, CostFunc, size, dT, dE, dA, dR, Psi (rad), Theta (rad), Phi (rad)\n"; @@ -1212,31 +1107,28 @@ bool FGTrimAnalysis::ensureRunning() if ( Propulsion == 0L ) return false; - for (unsigned i=0;i<Propulsion->GetNumEngines();i++) - { - if (!Propulsion->GetEngine(i)->GetRunning() ) - { - Propulsion->GetEngine(i)->SetStarter( true ); - if ( Propulsion->GetEngine(i)->GetType() == JSBSim::FGEngine::etPiston ) - { - FGPiston * Piston = (FGPiston*)Propulsion->GetEngine(i); - Piston->SetMagnetos(3); - } - else if ( Propulsion->GetEngine(i)->GetType() == FGEngine::etTurbine ) - { - FGTurbine * Turbine = (FGTurbine*)Propulsion->GetEngine(i); - Turbine->SetCutoff(false); - Turbine->SetStarter(true); - Turbine->Calculate(); - } - Propulsion->GetEngine(i)->SetRunning( true ); - Propulsion->Run(); - } - else - { - success = true; // at least one engine is found in a running state - Propulsion->SetActiveEngine(i); - } + for(unsigned i=0;i<Propulsion->GetNumEngines();i++) + { + if (!Propulsion->GetEngine(i)->GetRunning() ) { + Propulsion->GetEngine(i)->SetStarter( true ); + if ( Propulsion->GetEngine(i)->GetType() == JSBSim::FGEngine::etPiston ) + { + FGPiston * Piston = (FGPiston*)Propulsion->GetEngine(i); + Piston->SetMagnetos(3); + } + else if ( Propulsion->GetEngine(i)->GetType() == FGEngine::etTurbine ) + { + FGTurbine * Turbine = (FGTurbine*)Propulsion->GetEngine(i); + Turbine->SetCutoff(false); + Turbine->SetStarter(true); + Turbine->Calculate(); + } + Propulsion->GetEngine(i)->SetRunning( true ); + Propulsion->Run(); + } else { + success = true; // at least one engine is found in a running state + Propulsion->SetActiveEngine(i); + } } return success; } @@ -1250,30 +1142,27 @@ bool FGTrimAnalysis::ensureRunning(unsigned int i) if ( i < Propulsion->GetNumEngines() ) { - if (!Propulsion->GetEngine(i)->GetRunning() ) - { - Propulsion->GetEngine(i)->SetStarter( true ); - if ( Propulsion->GetEngine(i)->GetType() == JSBSim::FGEngine::etPiston ) - { - FGPiston * Piston = (FGPiston*)Propulsion->GetEngine(i); - Piston->SetMagnetos(3); - } - else if ( Propulsion->GetEngine(i)->GetType() == FGEngine::etTurbine ) - { - FGTurbine * Turbine = (FGTurbine*)Propulsion->GetEngine(i); - Turbine->SetCutoff(false); - Turbine->SetStarter(true); - Turbine->Calculate(); - } - Propulsion->GetEngine(i)->SetRunning( true ); - Propulsion->Run(); - - } - else - { - success = true; // at least one engine is found in a running state - Propulsion->SetActiveEngine(i); - } + if (!Propulsion->GetEngine(i)->GetRunning() ) { + Propulsion->GetEngine(i)->SetStarter( true ); + if ( Propulsion->GetEngine(i)->GetType() == JSBSim::FGEngine::etPiston ) + { + FGPiston * Piston = (FGPiston*)Propulsion->GetEngine(i); + Piston->SetMagnetos(3); + } + else if ( Propulsion->GetEngine(i)->GetType() == FGEngine::etTurbine ) + { + FGTurbine * Turbine = (FGTurbine*)Propulsion->GetEngine(i); + Turbine->SetCutoff(false); + Turbine->SetStarter(true); + Turbine->Calculate(); + } + Propulsion->GetEngine(i)->SetRunning( true ); + Propulsion->Run(); + + } else { + success = true; // at least one engine is found in a running state + Propulsion->SetActiveEngine(i); + } } else success=false; // i not in range @@ -1283,25 +1172,24 @@ bool FGTrimAnalysis::ensureRunning(unsigned int i) bool FGTrimAnalysis::runForAWhile(int nruns) { - bool result = fdmex->Run(); // MAKE AN INITIAL RUN + bool result = fdmex->Run(); // MAKE AN INITIAL RUN - int counter = 0; + int counter = 0; - // *** CYCLIC EXECUTION LOOP, AND MESSAGE READING *** // - while ( counter < nruns ) // (result && (counter < nruns)) - { - counter++; - result = fdmex->Run(); - } - return result; + // *** CYCLIC EXECUTION LOOP, AND MESSAGE READING *** // + while ( counter < nruns ) { // (result && (counter < nruns)) + counter++; + result = fdmex->Run(); + } + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGTrimAnalysis::populateVecAlphaDeg(double vmin, double vmax, int n) { if ( !vAlphaDeg.empty() ) return false; - for (int i=0; i<n; i++) - vAlphaDeg.push_back( vmin + double(i)*(vmax - vmin)/double(n-1) ); + for(int i=0; i<n; i++) + vAlphaDeg.push_back( vmin + double(i)*(vmax - vmin)/double(n-1) ); return true; } @@ -1309,28 +1197,28 @@ bool FGTrimAnalysis::populateVecAlphaDeg(double vmin, double vmax, int n) bool FGTrimAnalysis::populateVecThrottleCmd(double vmin, double vmax, int n) { if ( !vThrottleCmd.empty() ) return false; - for (int i=0; i<n; i++) - vThrottleCmd.push_back( vmin + double(i)*(vmax - vmin)/double(n-1) ); + for(int i=0; i<n; i++) + vThrottleCmd.push_back( vmin + double(i)*(vmax - vmin)/double(n-1) ); return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGTrimAnalysis::populateVecElevatorCmd(double vmin, double vmax, int n) { if ( !vElevatorCmd.empty() ) return false; - for (int i=0; i<n; i++) - vElevatorCmd.push_back( vmin + double(i)*(vmax - vmin)/double(n-1) ); + for(int i=0; i<n; i++) + vElevatorCmd.push_back( vmin + double(i)*(vmax - vmin)/double(n-1) ); return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGTrimAnalysis::calculateAerodynamics( - double dE_cmd, - double Vt, - double alpha_deg, - double altitude, - double rho, - double S, double mac, double bw, - double& CL, double& CD, double& Cm) + double dE_cmd, + double Vt, + double alpha_deg, + double altitude, + double rho, + double S, double mac, double bw, + double& CL, double& CD, double& Cm) { double qBar = 0.5 * rho * Vt*Vt; double qBar_S = qBar * S; @@ -1361,19 +1249,19 @@ bool FGTrimAnalysis::calculateAerodynamics( CL = 0.; unsigned int axis_ctr = 2; // means LIFT, 0=DRAG, 1=SIDE, 3,4,5=ROLL,PITCH,YAW for (unsigned int ctr=0; ctr < Coeff[axis_ctr].size(); ctr++) - CL += Coeff[axis_ctr][ctr]->GetValue(); + CL += Coeff[axis_ctr][ctr]->GetValue(); CL /= qBar_S; CD = 0.; axis_ctr = 0; // means DRAG for (unsigned int ctr=0; ctr < Coeff[axis_ctr].size(); ctr++) - CD += Coeff[axis_ctr][ctr]->GetValue(); + CD += Coeff[axis_ctr][ctr]->GetValue(); CD /= qBar_S; Cm=0.; axis_ctr = 4; // means PITCH 0=DRAG, 1=SIDE, 2=LIFT, 3=ROLL, 4=PITCH, 5=YAW for (unsigned int ctr=0; ctr < Coeff[axis_ctr].size(); ctr++) - Cm += Coeff[axis_ctr][ctr]->GetValue(); + Cm += Coeff[axis_ctr][ctr]->GetValue(); Cm /= ( qBar_S*mac ); @@ -1383,8 +1271,7 @@ bool FGTrimAnalysis::calculateAerodynamics( //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGTrimAnalysis::DoTrim(void) -{ +bool FGTrimAnalysis::DoTrim(void) { // retrieve initial conditions fdmex->RunIC(); @@ -1422,21 +1309,21 @@ bool FGTrimAnalysis::DoTrim(void) //-------------------------------------------------------- - for (unsigned i=0;i<Propulsion->GetNumEngines();i++) + for(unsigned i=0;i<Propulsion->GetNumEngines();i++) { - int engineStartCount = 0; - bool engine_started = false; + int engineStartCount = 0; + bool engine_started = false; - int n_attempts = 100; - if (Propulsion->GetEngine(i)->GetType()==FGEngine::etTurbine) - n_attempts = 5000; // a turbine engine, e.g. 737's cfm56, takes a little longer to get running + int n_attempts = 100; + if (Propulsion->GetEngine(i)->GetType()==FGEngine::etTurbine) + n_attempts = 5000; // a turbine engine, e.g. 737's cfm56, takes a little longer to get running - while ( !engine_started && (engineStartCount < n_attempts) ) - { - engine_started = ensureRunning(i); - fdmex->Run(); - engineStartCount++; - } + while ( !engine_started && (engineStartCount < n_attempts) ) + { + engine_started = ensureRunning(i); + fdmex->Run(); + engineStartCount++; + } } @@ -1450,8 +1337,7 @@ bool FGTrimAnalysis::DoTrim(void) trim_failed=false; - for (int i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++) - { + for(int i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){ fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(false); } @@ -1461,384 +1347,365 @@ bool FGTrimAnalysis::DoTrim(void) fgic->SetQRadpsIC(0.0); fgic->SetRRadpsIC(0.0); - if (mode == taPullup ) - { + if(mode == taPullup ) { setupPullup(); // also calls updateRates() - } - else if (mode == taTurn) - { + } else if (mode == taTurn) { setupTurn(); // also calls updateRates() - } - else if (mode == taTurnFull) - { + } else if (mode == taTurnFull) { setupTurn(); // also calls updateRates() - } - else - { + } else { fgic->SetPRadpsIC(0.0); fgic->SetQRadpsIC(0.0); fgic->SetRRadpsIC(0.0); _p = _q = _r = 0.; } - // ** DO HERE THE TRIM ** // - - //--------------------------------------------------------------------------- - // REMINDER: - // n. of control variables for full trim (taFull): 7 - // ordering: the four commands first, then the three Euler angles, - // [0] throttle cmd, [1] elevator cmd, 2) aileron cmd, [3] rudder cmd - // [4] phi, [5] theta, [6] psi (alias taHeading) - //----------------------------------------------------------------------------------------------------------------- - - // re-run ICs - fdmex->RunIC(); - - // write trim results on file, rf=results file - if ( rf.is_open() ) - rf << - "# iteration, costf, dT, dE, dA, dR, Phi (rad), Theta (rad), Psi (rad), uDot (fps2), vDot (fps2), wDot (fps2), pDot (rad/s2), qDot (rad/s2), rDot (rad/s2), u (fps), v (fps), w (fps), p (rad/s), q (rad/s), r (rad/s), alpha (rad), beta (rad), alphaDot (rad/s), betaDot (rad/s), Thrust" - << endl; - - long n = vTrimAnalysisControls.size(); // number of variables (dimension of the search) - - /* we'll initialize an n-entry Vector whose value is startVal, - * and use it as our starting point. - */ - - // a Vec, needed in the search constructor - Vector<double>* minVec = new Vector<double>(n, 0.0); - - // a Vec needed to store the minimum point later - Vector<double>* Sminimum; - new_Vector_Init(Sminimum,*minVec); - - /* - * now construct the search object: - * NMS = Nelder-Mead Search algorithm; - * if n parameters have to be adjusted, then user has to provide - * n+1 initial combinations where the cost function is going to be sampled. - * The class has the capability of automatically initialize those points, - * but here I prefer giving them explicitly so that the initial steps in - * all parameter "directions" are well defined. - */ - - NMSearch NMS( - n, *minVec, /* minVec, */ - sigma_nm, alpha_nm, beta_nm, gamma_nm, - initial_step, tolerance, - //find_CostFunctionFull, // gets the proper member function from the - // object of class Objective (see main_obj.cc from DirectSearch examples) - 0L, // gets the proper member function from the - (void *)obj_ptr - ); - - if ( GetMode()==taLongitudinal ) - { - NMS.SetFcnName(find_CostFunctionLongitudinal); - } - if ( GetMode()==taFull ) - { - NMS.SetFcnName(find_CostFunctionFull); - } - if ( GetMode()==taFullWingsLevel ) - { - NMS.SetFcnName(find_CostFunctionFullWingsLevel); - } - if ( GetMode()==taTurn ) - { - NMS.SetFcnName(find_CostFunctionFullCoordinatedTurn); - } - if ( GetMode()==taTurnFull ) - { - NMS.SetFcnName(find_CostFunctionFullTurn); - } - if ( GetMode()==taPullup ) - { - NMS.SetFcnName(find_CostFunctionPullUp); - } - - //----------------------------------------- - // initialize simplex (n+1 conditions) - //----------------------------------------- - // InitGeneralSimplex(plex) where... - // Matrix<double> *plex = NULL; - // new_Matrix(plex, n+1,n); // create one more row, see Dyn_alloc.h - // ... - - //------------------------------------------------------------------------------ - // In this stringstream we I put the n+1 sequences, each of n values (n-ples) - // The stream is then used to initialize the simplex by a call to the method - // ReadInFile - //------------------------------------------------------------------------------ - stringstream ss (stringstream::in | stringstream::out); - - // first feed the trial minimizer, zeroth point of the simplex - for (unsigned int k=0; k<vTrimAnalysisControls.size();k++) - ss << vTrimAnalysisControls[k]->GetControlInitialValue() << " "; - - // then the rest of n-ples - for (unsigned int k=0; k<vTrimAnalysisControls.size();k++) - { - for (vector<FGTrimAnalysisControl*>::iterator vi=vTrimAnalysisControls.begin(); - vi!=vTrimAnalysisControls.end();vi++) - { + // ** DO HERE THE TRIM ** // + + //--------------------------------------------------------------------------- + // REMINDER: + // n. of control variables for full trim (taFull): 7 + // ordering: the four commands first, then the three Euler angles, + // [0] throttle cmd, [1] elevator cmd, 2) aileron cmd, [3] rudder cmd + // [4] phi, [5] theta, [6] psi (alias taHeading) + //----------------------------------------------------------------------------------------------------------------- + + // re-run ICs + fdmex->RunIC(); + + // write trim results on file, rf=results file + if ( rf.is_open() ) + rf << + "# iteration, costf, dT, dE, dA, dR, Phi (rad), Theta (rad), Psi (rad), uDot (fps2), vDot (fps2), wDot (fps2), pDot (rad/s2), qDot (rad/s2), rDot (rad/s2), u (fps), v (fps), w (fps), p (rad/s), q (rad/s), r (rad/s), alpha (rad), beta (rad), alphaDot (rad/s), betaDot (rad/s), Thrust" + << endl; + + long n = vTrimAnalysisControls.size(); // number of variables (dimension of the search) + + /* we'll initialize an n-entry Vector whose value is startVal, + * and use it as our starting point. + */ + + // a Vec, needed in the search constructor + Vector<double>* minVec = new Vector<double>(n, 0.0); + + // a Vec needed to store the minimum point later + Vector<double>* Sminimum; + new_Vector_Init(Sminimum,*minVec); + + /* + * now construct the search object: + * NMS = Nelder-Mead Search algorithm; + * if n parameters have to be adjusted, then user has to provide + * n+1 initial combinations where the cost function is going to be sampled. + * The class has the capability of automatically initialize those points, + * but here I prefer giving them explicitly so that the initial steps in + * all parameter "directions" are well defined. + */ + + NMSearch NMS( + n, *minVec, /* minVec, */ + sigma_nm, alpha_nm, beta_nm, gamma_nm, + initial_step, tolerance, + //find_CostFunctionFull, // gets the proper member function from the + // object of class Objective (see main_obj.cc from DirectSearch examples) + 0L, // gets the proper member function from the + (void *)obj_ptr + ); + + if ( GetMode()==taLongitudinal ) { + NMS.SetFcnName(find_CostFunctionLongitudinal); + } + if ( GetMode()==taFull ) { + NMS.SetFcnName(find_CostFunctionFull); + } + if ( GetMode()==taFullWingsLevel ) { + NMS.SetFcnName(find_CostFunctionFullWingsLevel); + } + if ( GetMode()==taTurn ) { + NMS.SetFcnName(find_CostFunctionFullCoordinatedTurn); + } + if ( GetMode()==taTurnFull ) { + NMS.SetFcnName(find_CostFunctionFullTurn); + } + if ( GetMode()==taPullup ) { + NMS.SetFcnName(find_CostFunctionPullUp); + } + + //----------------------------------------- + // initialize simplex (n+1 conditions) + //----------------------------------------- + // InitGeneralSimplex(plex) where... + // Matrix<double> *plex = NULL; + // new_Matrix(plex, n+1,n); // create one more row, see Dyn_alloc.h + // ... + + //------------------------------------------------------------------------------ + // In this stringstream we I put the n+1 sequences, each of n values (n-ples) + // The stream is then used to initialize the simplex by a call to the method + // ReadInFile + //------------------------------------------------------------------------------ + stringstream ss (stringstream::in | stringstream::out); + + // first feed the trial minimizer, zeroth point of the simplex + for (unsigned int k=0; k<vTrimAnalysisControls.size();k++) + ss << vTrimAnalysisControls[k]->GetControlInitialValue() << " "; + + // then the rest of n-ples + for (unsigned int k=0; k<vTrimAnalysisControls.size();k++) + { + for(vector<FGTrimAnalysisControl*>::iterator vi=vTrimAnalysisControls.begin(); + vi!=vTrimAnalysisControls.end();vi++) { if ( (*vi)->GetControlType()==vTrimAnalysisControls[k]->GetControlType() ) ss << (*vi)->GetControlInitialValue() + (*vi)->GetControlStep() << " "; else ss << (*vi)->GetControlInitialValue() << " "; - }// this complets the k-th n-ple - }// this completes the (N+1) n-ples + }// this complets the k-th n-ple + }// this completes the (N+1) n-ples - NMS.ReadInFile(ss); // assign the initial combinations of parameters + NMS.ReadInFile(ss); // assign the initial combinations of parameters - /* - If Stop_on_std is set to false in an NMSearch, the standard-deviation test is used until that test is met. - Then (and in subsequent iterations of the same search) the more expensive ``delta'' test will be used. - We realize that there will be times when the standard deviation test will actually take more function calls than - the ``delta'' test, but this is not typically the case, and we make this compromise for the sake of efficiency. - */ + /* + If Stop_on_std is set to false in an NMSearch, the standard-deviation test is used until that test is met. + Then (and in subsequent iterations of the same search) the more expensive ``delta'' test will be used. + We realize that there will be times when the standard deviation test will actually take more function calls than + the ``delta'' test, but this is not typically the case, and we make this compromise for the sake of efficiency. + */ - NMS.SetMaxCalls(max_iterations); - //NMS.SetMaxCallsExact(20000); - if ( stop_criterion=="Stop-On-Std" ) - NMS.Set_Stop_on_std(); - if ( stop_criterion=="Stop-On-Delta" ) - NMS.Set_Stop_on_delta(); + NMS.SetMaxCalls(max_iterations); + //NMS.SetMaxCallsExact(20000); + if ( stop_criterion=="Stop-On-Std" ) + NMS.Set_Stop_on_std(); + if ( stop_criterion=="Stop-On-Delta" ) + NMS.Set_Stop_on_delta(); - double SMinVal; - long Scalls; + double SMinVal; + long Scalls; // NMS.PrintDesign(); - fdmex->SetDebugLevel(0); - - /* start searching */ - NMS.BeginSearch(); // stops when the simplex shrinks to a point - - // WATCH this !! - delete obj_ptr; - - /* recover information about the search */ - NMS.GetMinPoint(*Sminimum); - NMS.GetMinVal(SMinVal); - Scalls = NMS.GetFunctionCalls(); - - // Apply the set of controls found by the minimization procedure - - if ( ( mode == taFull ) || - ( mode == taTurnFull ) ) - { - FCS->SetDeCmd( (*Sminimum)[1] ); // elevator - FCS->SetDaCmd( (*Sminimum)[2] ); // ailerons - FCS->SetDrCmd( (*Sminimum)[3] ); // rudder - double tMin,tMax; - for (unsigned i=0;i<Propulsion->GetNumEngines();i++) - { - tMin=Propulsion->GetEngine(i)->GetThrottleMin(); - tMax=Propulsion->GetEngine(i)->GetThrottleMax(); - FCS->SetThrottleCmd(i,tMin + (*Sminimum)[0] *(tMax-tMin)); - FCS->Run(); // apply throttle change - } - Propulsion->GetSteadyState(); // GetSteadyState processes all engines - FCS->Run(); // apply throttle, yoke & pedal changes - - FGQuaternion quat( (*Sminimum)[4], (*Sminimum)[5], (*Sminimum)[6] ); // phi, theta, psi - quat.Normalize(); - - fgic->ResetIC(_u, _v, _w, _p, _q, _r, _alpha, _beta, _phi, _theta, _psi, _gamma); - - FGPropagate::VehicleState vstate = fdmex->GetPropagate()->GetVState(); - vstate.vQtrn = FGQuaternion(_phi,_theta,_psi); - fdmex->GetPropagate()->SetVState(vstate); - Auxiliary->Setalpha( _alpha ); // need to get Auxiliary updated - Auxiliary->Setbeta ( _beta ); - - // NOTE: _do not_ fdmex->RunIC() here ! We just reset the state - /* */ - //fdmex->RunIC(); - fdmex->Run(); - - } // end taFull - - if ( mode == taLongitudinal ) - { - FCS->SetDeCmd( (*Sminimum)[1] ); // elevator - double tMin,tMax; - for (unsigned i=0;i<Propulsion->GetNumEngines();i++) - { - tMin=Propulsion->GetEngine(i)->GetThrottleMin(); - tMax=Propulsion->GetEngine(i)->GetThrottleMax(); - FCS->SetThrottleCmd(i,tMin + (*Sminimum)[0] *(tMax-tMin)); - FCS->Run(); // apply throttle change - } - Propulsion->GetSteadyState(); // GetSteadyState processes all engines - FCS->Run(); // apply throttle, yoke & pedal changes + fdmex->SetDebugLevel(0); + + /* start searching */ + NMS.BeginSearch(); // stops when the simplex shrinks to a point + + // WATCH this !! + delete obj_ptr; + + /* recover information about the search */ + NMS.GetMinPoint(*Sminimum); + NMS.GetMinVal(SMinVal); + Scalls = NMS.GetFunctionCalls(); + + // Apply the set of controls found by the minimization procedure + + if ( ( mode == taFull ) || + ( mode == taTurnFull ) ) + { + FCS->SetDeCmd( (*Sminimum)[1] ); // elevator + FCS->SetDaCmd( (*Sminimum)[2] ); // ailerons + FCS->SetDrCmd( (*Sminimum)[3] ); // rudder + double tMin,tMax; + for(unsigned i=0;i<Propulsion->GetNumEngines();i++) + { + tMin=Propulsion->GetEngine(i)->GetThrottleMin(); + tMax=Propulsion->GetEngine(i)->GetThrottleMax(); + FCS->SetThrottleCmd(i,tMin + (*Sminimum)[0] *(tMax-tMin)); + FCS->Run(); // apply throttle change + } + Propulsion->GetSteadyState(); // GetSteadyState processes all engines + FCS->Run(); // apply throttle, yoke & pedal changes + + FGQuaternion quat( (*Sminimum)[4], (*Sminimum)[5], (*Sminimum)[6] ); // phi, theta, psi + quat.Normalize(); + + fgic->ResetIC(_u, _v, _w, _p, _q, _r, _alpha, _beta, _phi, _theta, _psi, _gamma); + + FGPropagate::VehicleState vstate = fdmex->GetPropagate()->GetVState(); + vstate.vQtrn = FGQuaternion(_phi,_theta,_psi); + fdmex->GetPropagate()->SetVState(vstate); + Auxiliary->Setalpha( _alpha ); // need to get Auxiliary updated + Auxiliary->Setbeta ( _beta ); + + // NOTE: _do not_ fdmex->RunIC() here ! We just reset the state + /* */ + //fdmex->RunIC(); + fdmex->Run(); + + } // end taFull + + if ( mode == taLongitudinal ) + { + FCS->SetDeCmd( (*Sminimum)[1] ); // elevator + double tMin,tMax; + for(unsigned i=0;i<Propulsion->GetNumEngines();i++) + { + tMin=Propulsion->GetEngine(i)->GetThrottleMin(); + tMax=Propulsion->GetEngine(i)->GetThrottleMax(); + FCS->SetThrottleCmd(i,tMin + (*Sminimum)[0] *(tMax-tMin)); + FCS->Run(); // apply throttle change + } + Propulsion->GetSteadyState(); // GetSteadyState processes all engines + FCS->Run(); // apply throttle, yoke & pedal changes + + FGQuaternion quat( 0, (*Sminimum)[2], fgic->GetPsiRadIC() ); // phi, theta, psi + quat.Normalize(); + + // enforce the current state to IC object + + fgic->ResetIC(_u, _v, _w, _p, _q, _r, _alpha, _beta, _phi, _theta, _psi, _gamma); + + // NOTE: _do not_ fdmex->RunIC() here ! We just reset the state + // which means that we populate IC private variables with our set of values + //fdmex->RunIC(); + + FGPropagate::VehicleState vstate = fdmex->GetPropagate()->GetVState(); + vstate.vQtrn = FGQuaternion(_phi,_theta,_psi); + fdmex->GetPropagate()->SetVState(vstate); + Auxiliary->Setalpha( _alpha ); // need to get Auxiliary updated + Auxiliary->Setbeta ( _beta ); + + fdmex->Run(); + + } // end taLongitudinal + + if ( mode == taFullWingsLevel) + { + FCS->SetDeCmd( (*Sminimum)[1] ); // elevator + FCS->SetDaCmd( (*Sminimum)[2] ); // ailerons + FCS->SetDrCmd( (*Sminimum)[3] ); // rudder + + double tMin,tMax; + for(unsigned i=0;i<Propulsion->GetNumEngines();i++) + { + tMin=Propulsion->GetEngine(i)->GetThrottleMin(); + tMax=Propulsion->GetEngine(i)->GetThrottleMax(); + FCS->SetThrottleCmd(i,tMin + (*Sminimum)[0] *(tMax-tMin)); + FCS->Run(); // apply throttle change + } + Propulsion->GetSteadyState(); // GetSteadyState processes all engines + FCS->Run(); // apply throttle, yoke & pedal changes + + FGQuaternion quat( 0, (*Sminimum)[2], fgic->GetPsiRadIC() ); // phi, theta, psi + quat.Normalize(); + + //... + // enforce the current state to IC object + + fgic->ResetIC(_u, _v, _w, _p, _q, _r, _alpha, _beta, _phi, _theta, _psi, _gamma); + + // NOTE: _do not_ fdmex->RunIC() here ! We just reset the state + // which means that we populate IC private variables with our set of values + //fdmex->RunIC(); + + FGPropagate::VehicleState vstate = fdmex->GetPropagate()->GetVState(); + vstate.vQtrn = FGQuaternion(_phi,_theta,_psi); + fdmex->GetPropagate()->SetVState(vstate); + Auxiliary->Setalpha( _alpha ); // need to get Auxiliary updated + Auxiliary->Setbeta ( _beta ); + + fdmex->Run(); + }// end taFullWingsLevel + + if ( mode == taTurn ) + { + FCS->SetDeCmd( (*Sminimum)[1] ); // elevator + FCS->SetDaCmd( (*Sminimum)[2] ); // ailerons + FCS->SetDrCmd( (*Sminimum)[3] ); // rudder + + double tMin,tMax; + for(unsigned i=0;i<Propulsion->GetNumEngines();i++) + { + tMin=Propulsion->GetEngine(i)->GetThrottleMin(); + tMax=Propulsion->GetEngine(i)->GetThrottleMax(); + FCS->SetThrottleCmd(i,tMin + (*Sminimum)[0] *(tMax-tMin)); + FCS->Run(); // apply throttle change + } + Propulsion->GetSteadyState(); // GetSteadyState processes all engines + FCS->Run(); // apply throttle, yoke & pedal changes + + FGQuaternion quat( fgic->GetPhiRadIC(), (*Sminimum)[2], fgic->GetPsiRadIC() ); // phi, theta, psi + quat.Normalize(); + + //... + // enforce the current state to IC object + + fgic->ResetIC(_u, _v, _w, _p, _q, _r, _alpha, _beta, _phi, _theta, _psi, _gamma); + + // NOTE: _do not_ fdmex->RunIC() here ! We just reset the state + // which means that we populate IC private variables with our set of values + //fdmex->RunIC(); + + FGPropagate::VehicleState vstate = fdmex->GetPropagate()->GetVState(); + vstate.vQtrn = FGQuaternion(_phi,_theta,_psi); + fdmex->GetPropagate()->SetVState(vstate); + Auxiliary->Setalpha( _alpha ); // need to get Auxiliary updated + Auxiliary->Setbeta ( 0.0 ); + Auxiliary->SetGamma( fgic->GetFlightPathAngleRadIC() ); + + fdmex->Run(); + }// end ta turn + + if ( mode == taPullup ) + { + FCS->SetDeCmd( (*Sminimum)[1] ); // elevator + FCS->SetDaCmd( (*Sminimum)[2] ); // ailerons + FCS->SetDrCmd( (*Sminimum)[3] ); // rudder + + double tMin,tMax; + for(unsigned i=0;i<Propulsion->GetNumEngines();i++) + { + tMin=Propulsion->GetEngine(i)->GetThrottleMin(); + tMax=Propulsion->GetEngine(i)->GetThrottleMax(); + FCS->SetThrottleCmd(i,tMin + (*Sminimum)[0] *(tMax-tMin)); + FCS->Run(); // apply throttle change + } + Propulsion->GetSteadyState(); // GetSteadyState processes all engines + FCS->Run(); // apply throttle, yoke & pedal changes + + FGQuaternion quat( 0, (*Sminimum)[2], fgic->GetPRadpsIC() ); // phi, theta, psi + quat.Normalize(); + + //... + // enforce the current state to IC object + + fgic->ResetIC(_u, _v, _w, _p, _q, _r, _alpha, _beta, _phi, _theta, _psi, _gamma); + + // NOTE: _do not_ fdmex->RunIC() here ! We just reset the state + // which means that we populate IC private variables with our set of values + //fdmex->RunIC(); + + FGPropagate::VehicleState vstate = fdmex->GetPropagate()->GetVState(); + vstate.vQtrn = FGQuaternion(_phi,_theta,_psi); + fdmex->GetPropagate()->SetVState(vstate); + Auxiliary->Setalpha( _alpha ); // need to get Auxiliary updated + Auxiliary->Setbeta ( 0.0 ); + Auxiliary->SetGamma( fgic->GetFlightPathAngleRadIC() ); + + fdmex->Run(); + }//end taPullup - FGQuaternion quat( 0, (*Sminimum)[2], fgic->GetPsiRadIC() ); // phi, theta, psi - quat.Normalize(); - - // enforce the current state to IC object - - fgic->ResetIC(_u, _v, _w, _p, _q, _r, _alpha, _beta, _phi, _theta, _psi, _gamma); - - // NOTE: _do not_ fdmex->RunIC() here ! We just reset the state - // which means that we populate IC private variables with our set of values - //fdmex->RunIC(); - - FGPropagate::VehicleState vstate = fdmex->GetPropagate()->GetVState(); - vstate.vQtrn = FGQuaternion(_phi,_theta,_psi); - fdmex->GetPropagate()->SetVState(vstate); - Auxiliary->Setalpha( _alpha ); // need to get Auxiliary updated - Auxiliary->Setbeta ( _beta ); - - fdmex->Run(); - - } // end taLongitudinal - - if ( mode == taFullWingsLevel) - { - FCS->SetDeCmd( (*Sminimum)[1] ); // elevator - FCS->SetDaCmd( (*Sminimum)[2] ); // ailerons - FCS->SetDrCmd( (*Sminimum)[3] ); // rudder - - double tMin,tMax; - for (unsigned i=0;i<Propulsion->GetNumEngines();i++) - { - tMin=Propulsion->GetEngine(i)->GetThrottleMin(); - tMax=Propulsion->GetEngine(i)->GetThrottleMax(); - FCS->SetThrottleCmd(i,tMin + (*Sminimum)[0] *(tMax-tMin)); - FCS->Run(); // apply throttle change - } - Propulsion->GetSteadyState(); // GetSteadyState processes all engines - FCS->Run(); // apply throttle, yoke & pedal changes - - FGQuaternion quat( 0, (*Sminimum)[2], fgic->GetPsiRadIC() ); // phi, theta, psi - quat.Normalize(); - - //... - // enforce the current state to IC object - - fgic->ResetIC(_u, _v, _w, _p, _q, _r, _alpha, _beta, _phi, _theta, _psi, _gamma); - - // NOTE: _do not_ fdmex->RunIC() here ! We just reset the state - // which means that we populate IC private variables with our set of values - //fdmex->RunIC(); - - FGPropagate::VehicleState vstate = fdmex->GetPropagate()->GetVState(); - vstate.vQtrn = FGQuaternion(_phi,_theta,_psi); - fdmex->GetPropagate()->SetVState(vstate); - Auxiliary->Setalpha( _alpha ); // need to get Auxiliary updated - Auxiliary->Setbeta ( _beta ); - - fdmex->Run(); - }// end taFullWingsLevel - - if ( mode == taTurn ) - { - FCS->SetDeCmd( (*Sminimum)[1] ); // elevator - FCS->SetDaCmd( (*Sminimum)[2] ); // ailerons - FCS->SetDrCmd( (*Sminimum)[3] ); // rudder - - double tMin,tMax; - for (unsigned i=0;i<Propulsion->GetNumEngines();i++) - { - tMin=Propulsion->GetEngine(i)->GetThrottleMin(); - tMax=Propulsion->GetEngine(i)->GetThrottleMax(); - FCS->SetThrottleCmd(i,tMin + (*Sminimum)[0] *(tMax-tMin)); - FCS->Run(); // apply throttle change - } - Propulsion->GetSteadyState(); // GetSteadyState processes all engines - FCS->Run(); // apply throttle, yoke & pedal changes - - FGQuaternion quat( fgic->GetPhiRadIC(), (*Sminimum)[2], fgic->GetPsiRadIC() ); // phi, theta, psi - quat.Normalize(); - - //... - // enforce the current state to IC object - - fgic->ResetIC(_u, _v, _w, _p, _q, _r, _alpha, _beta, _phi, _theta, _psi, _gamma); - - // NOTE: _do not_ fdmex->RunIC() here ! We just reset the state - // which means that we populate IC private variables with our set of values - //fdmex->RunIC(); - - FGPropagate::VehicleState vstate = fdmex->GetPropagate()->GetVState(); - vstate.vQtrn = FGQuaternion(_phi,_theta,_psi); - fdmex->GetPropagate()->SetVState(vstate); - Auxiliary->Setalpha( _alpha ); // need to get Auxiliary updated - Auxiliary->Setbeta ( 0.0 ); - Auxiliary->SetGamma( fgic->GetFlightPathAngleRadIC() ); - - fdmex->Run(); - }// end ta turn - - if ( mode == taPullup ) - { - FCS->SetDeCmd( (*Sminimum)[1] ); // elevator - FCS->SetDaCmd( (*Sminimum)[2] ); // ailerons - FCS->SetDrCmd( (*Sminimum)[3] ); // rudder - - double tMin,tMax; - for (unsigned i=0;i<Propulsion->GetNumEngines();i++) - { - tMin=Propulsion->GetEngine(i)->GetThrottleMin(); - tMax=Propulsion->GetEngine(i)->GetThrottleMax(); - FCS->SetThrottleCmd(i,tMin + (*Sminimum)[0] *(tMax-tMin)); - FCS->Run(); // apply throttle change - } - Propulsion->GetSteadyState(); // GetSteadyState processes all engines - FCS->Run(); // apply throttle, yoke & pedal changes - - FGQuaternion quat( 0, (*Sminimum)[2], fgic->GetPRadpsIC() ); // phi, theta, psi - quat.Normalize(); - - //... - // enforce the current state to IC object - - fgic->ResetIC(_u, _v, _w, _p, _q, _r, _alpha, _beta, _phi, _theta, _psi, _gamma); - - // NOTE: _do not_ fdmex->RunIC() here ! We just reset the state - // which means that we populate IC private variables with our set of values - //fdmex->RunIC(); - - FGPropagate::VehicleState vstate = fdmex->GetPropagate()->GetVState(); - vstate.vQtrn = FGQuaternion(_phi,_theta,_psi); - fdmex->GetPropagate()->SetVState(vstate); - Auxiliary->Setalpha( _alpha ); // need to get Auxiliary updated - Auxiliary->Setbeta ( 0.0 ); - Auxiliary->SetGamma( fgic->GetFlightPathAngleRadIC() ); - - fdmex->Run(); - }//end taPullup - - delete minVec; - delete Sminimum; - - //----------------------------------------------------------------------------------------------------------------- - - total_its = NMS.GetFunctionCalls(); - - if ( !trim_failed ) - { - if (debug_lvl > 0) - { - cout << endl << " Trim successful. (Cost function value: " << cost_function_value << ")" << endl; - } - } - else - { - if (debug_lvl > 0) - cout << endl << " Trim failed" << endl; - } - - - for (unsigned int i=0; i<(unsigned int)fdmex->GetGroundReactions()->GetNumGearUnits();i++) - { - fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true); - } - - return !trim_failed; + delete minVec; + delete Sminimum; + + //----------------------------------------------------------------------------------------------------------------- + + total_its = NMS.GetFunctionCalls(); + + if( !trim_failed ) { + if (debug_lvl > 0) { + cout << endl << " Trim successful. (Cost function value: " << cost_function_value << ")" << endl; + } + } else { + if (debug_lvl > 0) + cout << endl << " Trim failed" << endl; + } + + + for (unsigned int i=0; i<(unsigned int)fdmex->GetGroundReactions()->GetNumGearUnits();i++){ + fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true); + } + + return !trim_failed; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1904,24 +1771,20 @@ double Objective::myCostFunctionFull(Vector<double> & x) // x variations come fr // ToDo: manage bounds via the FGTrimAnalysisControl class //---------------------------------------------------------------------------- bool penalty = ( (delta_cmd_T < 0) || (delta_cmd_T > 1) ) - || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) - || ( (delta_cmd_A < -1) || (delta_cmd_A > 1) ) - || ( (delta_cmd_R < -1) || (delta_cmd_R > 1) ) - || ( (psi < 0.0 ) || (psi > 2.0*M_PI) ) - || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ) - || ( (phi < - M_PI) || (phi > M_PI) ) - ; - - if ( penalty ) - { + || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) + || ( (delta_cmd_A < -1) || (delta_cmd_A > 1) ) + || ( (delta_cmd_R < -1) || (delta_cmd_R > 1) ) + || ( (psi < 0.0 ) || (psi > 2.0*M_PI) ) + || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ) + || ( (phi < - M_PI) || (phi > M_PI) ) + ; + + if ( penalty ) { //------------------------------------------------- // just return an "infinite" value return HUGE_VAL; //------------------------------------------------- - } - else - { - calculateDottedStates(delta_cmd_T, delta_cmd_E, delta_cmd_A, delta_cmd_R, + } else {calculateDottedStates(delta_cmd_T, delta_cmd_E, delta_cmd_A, delta_cmd_R, phi, theta, psi, TrimAnalysis->GetMode(), alpha, beta, gamma, @@ -1930,29 +1793,21 @@ double Objective::myCostFunctionFull(Vector<double> & x) // x variations come fr } double u , v , w , - p , q , r , - uDot, vDot, wDot, - pDot, qDot, rDot; - u = VState.vUVW (1); - v = VState.vUVW (2); - w = VState.vUVW (3); - p = VState.vPQR (1); - q = VState.vPQR (2); - r = VState.vPQR (3); - uDot = vUVWdot(1); - vDot = vUVWdot(2); - wDot = vUVWdot(3); - pDot = vPQRdot(1); - qDot = vPQRdot(2); - rDot = vPQRdot(3); + p , q , r , + uDot, vDot, wDot, + pDot, qDot, rDot; + u = VState.vUVW (1); v = VState.vUVW (2); w = VState.vUVW (3); + p = VState.vPQR (1); q = VState.vPQR (2); r = VState.vPQR (3); + uDot = vUVWdot(1); vDot = vUVWdot(2); wDot = vUVWdot(3); + pDot = vPQRdot(1); qDot = vPQRdot(2); rDot = vPQRdot(3); double f = 1.000*uDot*uDot - + vDot*vDot - + 1.000*wDot*wDot - + 0.010*pDot*pDot - + 0.010*qDot*qDot - + 0.010*rDot*rDot; + + vDot*vDot + + 1.000*wDot*wDot + + 0.010*pDot*pDot + + 0.010*qDot*qDot + + 0.010*rDot*rDot; static int count = 0; count++; @@ -1961,8 +1816,8 @@ double Objective::myCostFunctionFull(Vector<double> & x) // x variations come fr { // feed into the vector of TrimAnalysis Controls the current values vector<FGTrimAnalysisControl*>::iterator vi; - for (vi=TrimAnalysis->GetControls()->begin(); - vi!=TrimAnalysis->GetControls()->end();vi++) + for(vi=TrimAnalysis->GetControls()->begin(); + vi!=TrimAnalysis->GetControls()->end();vi++) { if ( (*vi)->GetControlType()==JSBSim::taThrottle ) (*vi)->SetControl(delta_cmd_T); if ( (*vi)->GetControlType()==JSBSim::taElevator ) (*vi)->SetControl(delta_cmd_E); // TODO: taPitchTrim @@ -1988,13 +1843,13 @@ double Objective::myCostFunctionFull(Vector<double> & x) // x variations come fr (*rfp) << count <<", "<< f <<", " // 1, 2 << delta_cmd_T <<", "<< delta_cmd_E <<", "<< delta_cmd_A <<", "<< delta_cmd_R <<", " - // 3, 4, 5, 6 + // 3, 4, 5, 6 << phi <<", "<< theta <<", "<< psi <<", " // 7, 8, 9 << uDot <<", "<< vDot <<", "<< wDot <<", " // 10, 11, 12 << pDot <<", "<< qDot <<", "<< rDot <<", " // 13, 14, 15 << u <<", "<< v <<", "<< w << ", " // 16, 17, 18 << VState.vPQR(1) <<", "<< VState.vPQR(2) <<", "<< VState.vPQR(3) << ", " - // 19, 20, 21 + // 19, 20, 21 << FDMExec->GetAuxiliary()->Getalpha() << ", " // 22 << FDMExec->GetAuxiliary()->Getbeta() << ", " // 23 << FDMExec->GetAuxiliary()->Getadot() << ", " // 24 @@ -2010,7 +1865,7 @@ double Objective::myCostFunctionFull(Vector<double> & x) // x variations come fr TrimAnalysis->SetCostFunctionValue(f); } - + return f; } @@ -2077,23 +1932,20 @@ double Objective::myCostFunctionFullWingsLevel(Vector<double> & x) // x variatio // ToDo: manage bounds via the FGTrimAnalysisControl class //---------------------------------------------------------------------------- bool penalty = ( (delta_cmd_T < 0) || (delta_cmd_T > 1) ) - || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) - || ( (delta_cmd_A < -1) || (delta_cmd_A > 1) ) - || ( (delta_cmd_R < -1) || (delta_cmd_R > 1) ) - || ( (psi < 0.0 ) || (psi > 2.0*M_PI) ) - || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ) - // || ( (phi < - M_PI) || (phi > M_PI) ) ...always zero here - ; - - if ( penalty ) - { + || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) + || ( (delta_cmd_A < -1) || (delta_cmd_A > 1) ) + || ( (delta_cmd_R < -1) || (delta_cmd_R > 1) ) + || ( (psi < 0.0 ) || (psi > 2.0*M_PI) ) + || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ) + // || ( (phi < - M_PI) || (phi > M_PI) ) ...always zero here + ; + + if ( penalty ) { //------------------------------------------------- // just return an "infinite" value return HUGE_VAL; //------------------------------------------------- - } - else - { + } else { calculateDottedStates(delta_cmd_T, delta_cmd_E, delta_cmd_A, delta_cmd_R, phi, theta, psi, TrimAnalysis->GetMode(), @@ -2103,29 +1955,21 @@ double Objective::myCostFunctionFullWingsLevel(Vector<double> & x) // x variatio } double u , v , w , - p , q , r , - uDot, vDot, wDot, - pDot, qDot, rDot; - u = VState.vUVW (1); - v = VState.vUVW (2); - w = VState.vUVW (3); - p = VState.vPQR (1); - q = VState.vPQR (2); - r = VState.vPQR (3); - uDot = vUVWdot(1); - vDot = vUVWdot(2); - wDot = vUVWdot(3); - pDot = vPQRdot(1); - qDot = vPQRdot(2); - rDot = vPQRdot(3); + p , q , r , + uDot, vDot, wDot, + pDot, qDot, rDot; + u = VState.vUVW (1); v = VState.vUVW (2); w = VState.vUVW (3); + p = VState.vPQR (1); q = VState.vPQR (2); r = VState.vPQR (3); + uDot = vUVWdot(1); vDot = vUVWdot(2); wDot = vUVWdot(3); + pDot = vPQRdot(1); qDot = vPQRdot(2); rDot = vPQRdot(3); double f = 1.000*uDot*uDot - + vDot*vDot - + 1.000*wDot*wDot - + 0.010*pDot*pDot - + 0.010*qDot*qDot - + 0.010*rDot*rDot; + + vDot*vDot + + 1.000*wDot*wDot + + 0.010*pDot*pDot + + 0.010*qDot*qDot + + 0.010*rDot*rDot; static int count = 0; count++; @@ -2134,8 +1978,8 @@ double Objective::myCostFunctionFullWingsLevel(Vector<double> & x) // x variatio { // feed into the vector of TrimAnalysis Controls the current values vector<FGTrimAnalysisControl*>::iterator vi; - for (vi=TrimAnalysis->GetControls()->begin(); - vi!=TrimAnalysis->GetControls()->end();vi++) + for(vi=TrimAnalysis->GetControls()->begin(); + vi!=TrimAnalysis->GetControls()->end();vi++) { if ( (*vi)->GetControlType()==JSBSim::taThrottle ) (*vi)->SetControl(delta_cmd_T); if ( (*vi)->GetControlType()==JSBSim::taElevator ) (*vi)->SetControl(delta_cmd_E); // TODO: taPitchTrim @@ -2161,13 +2005,13 @@ double Objective::myCostFunctionFullWingsLevel(Vector<double> & x) // x variatio (*rfp) << count <<", "<< f <<", " // 1, 2 << delta_cmd_T <<", "<< delta_cmd_E <<", "<< delta_cmd_A <<", "<< delta_cmd_R <<", " - // 3, 4, 5, 6 + // 3, 4, 5, 6 << phi <<", "<< theta <<", "<< psi <<", " // 7, 8, 9 << uDot <<", "<< vDot <<", "<< wDot <<", " // 10, 11, 12 << pDot <<", "<< qDot <<", "<< rDot <<", " // 13, 14, 15 << u <<", "<< v <<", "<< w << ", " // 16, 17, 18 << VState.vPQR(1) <<", "<< VState.vPQR(2) <<", "<< VState.vPQR(3) << ", " - // 19, 20, 21 + // 19, 20, 21 << FDMExec->GetAuxiliary()->Getalpha() << ", " // 22 << FDMExec->GetAuxiliary()->Getbeta() << ", " // 23 << FDMExec->GetAuxiliary()->Getadot() << ", " // 24 @@ -2249,19 +2093,16 @@ double Objective::myCostFunctionLongitudinal(Vector<double> & x) // ToDo: manage bounds via the FGTrimAnalysisControl class //---------------------------------------------------------------------------- bool penalty = ( (delta_cmd_T < 0) || (delta_cmd_T > 1) ) - || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) - || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ) - ; + || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) + || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ) + ; - if ( penalty ) - { + if ( penalty ) { //------------------------------------------------- // just return an "infinite" value return HUGE_VAL; //------------------------------------------------- - } - else - { + } else { calculateDottedStates(delta_cmd_T, delta_cmd_E, delta_cmd_A, delta_cmd_R, phi, theta, psi, TrimAnalysis->GetMode(), @@ -2271,26 +2112,18 @@ double Objective::myCostFunctionLongitudinal(Vector<double> & x) } double u , v , w , - p , q , r , - uDot, vDot, wDot, - pDot, qDot, rDot; - u = VState.vUVW (1); - v = VState.vUVW (2); - w = VState.vUVW (3); - p = VState.vPQR (1); - q = VState.vPQR (2); - r = VState.vPQR (3); - uDot = vUVWdot(1); - vDot = vUVWdot(2); - wDot = vUVWdot(3); - pDot = vPQRdot(1); - qDot = vPQRdot(2); - rDot = vPQRdot(3); + p , q , r , + uDot, vDot, wDot, + pDot, qDot, rDot; + u = VState.vUVW (1); v = VState.vUVW (2); w = VState.vUVW (3); + p = VState.vPQR (1); q = VState.vPQR (2); r = VState.vPQR (3); + uDot = vUVWdot(1); vDot = vUVWdot(2); wDot = vUVWdot(3); + pDot = vPQRdot(1); qDot = vPQRdot(2); rDot = vPQRdot(3); double f = 1.000*uDot*uDot - + 1.000*wDot*wDot - + //1.0 + + 1.000*wDot*wDot + + //1.0 0.010 *qDot*qDot; @@ -2301,8 +2134,8 @@ double Objective::myCostFunctionLongitudinal(Vector<double> & x) { // feed into the vector of TrimAnalysis Controls the current values vector<FGTrimAnalysisControl*>::iterator vi; - for (vi=TrimAnalysis->GetControls()->begin(); - vi!=TrimAnalysis->GetControls()->end();vi++) + for(vi=TrimAnalysis->GetControls()->begin(); + vi!=TrimAnalysis->GetControls()->end();vi++) { if ( (*vi)->GetControlType()==JSBSim::taThrottle ) (*vi)->SetControl(delta_cmd_T); if ( (*vi)->GetControlType()==JSBSim::taElevator ) (*vi)->SetControl(delta_cmd_E); // TODO: taPitchTrim @@ -2334,7 +2167,7 @@ double Objective::myCostFunctionLongitudinal(Vector<double> & x) << pDot <<", "<< qDot <<", "<< rDot <<", " // 13, 14, 15 << u <<", "<< v <<", "<< w << ", " // 16, 17, 18 << VState.vPQR(1) <<", "<< VState.vPQR(2) <<", "<< VState.vPQR(3) << ", " - // 19, 20, 21 + // 19, 20, 21 << FDMExec->GetAuxiliary()->Getalpha() << ", " // 22 << FDMExec->GetAuxiliary()->Getbeta() << ", " // 23 << FDMExec->GetAuxiliary()->Getadot() << ", " // 24 @@ -2424,22 +2257,19 @@ double Objective::myCostFunctionFullCoordinatedTurn(Vector<double> & x) // ToDo: manage bounds via the FGTrimAnalysisControl class //---------------------------------------------------------------------------- bool penalty = ( (delta_cmd_T < 0) || (delta_cmd_T > 1) ) - || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) - || ( (delta_cmd_A < -1) || (delta_cmd_A > 1) ) - || ( (delta_cmd_R < -1) || (delta_cmd_R > 1) ) - || ( (psi < 0.0 ) || (psi > 2.0*M_PI) ) - || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ) // may go out of range - ; - - if ( penalty ) - { + || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) + || ( (delta_cmd_A < -1) || (delta_cmd_A > 1) ) + || ( (delta_cmd_R < -1) || (delta_cmd_R > 1) ) + || ( (psi < 0.0 ) || (psi > 2.0*M_PI) ) + || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ) // may go out of range + ; + + if ( penalty ) { //------------------------------------------------- // just return an "infinite" value return HUGE_VAL; //------------------------------------------------- - } - else - { + } else { calculateDottedStates(delta_cmd_T, delta_cmd_E, delta_cmd_A, delta_cmd_R, phi, theta, psi, TrimAnalysis->GetMode(), @@ -2449,29 +2279,21 @@ double Objective::myCostFunctionFullCoordinatedTurn(Vector<double> & x) } double u , v , w , - p , q , r , - uDot, vDot, wDot, - pDot, qDot, rDot; - u = VState.vUVW (1); - v = VState.vUVW (2); - w = VState.vUVW (3); - p = VState.vPQR (1); - q = VState.vPQR (2); - r = VState.vPQR (3); - uDot = vUVWdot(1); - vDot = vUVWdot(2); - wDot = vUVWdot(3); - pDot = vPQRdot(1); - qDot = vPQRdot(2); - rDot = vPQRdot(3); + p , q , r , + uDot, vDot, wDot, + pDot, qDot, rDot; + u = VState.vUVW (1); v = VState.vUVW (2); w = VState.vUVW (3); + p = VState.vPQR (1); q = VState.vPQR (2); r = VState.vPQR (3); + uDot = vUVWdot(1); vDot = vUVWdot(2); wDot = vUVWdot(3); + pDot = vPQRdot(1); qDot = vPQRdot(2); rDot = vPQRdot(3); double f = 1.000*uDot*uDot - + vDot*vDot - + 1.000*wDot*wDot - + 0.010*pDot*pDot - + 0.010*qDot*qDot - + 0.010*rDot*rDot; + + vDot*vDot + + 1.000*wDot*wDot + + 0.010*pDot*pDot + + 0.010*qDot*qDot + + 0.010*rDot*rDot; static int count = 0; count++; @@ -2480,8 +2302,8 @@ double Objective::myCostFunctionFullCoordinatedTurn(Vector<double> & x) { // feed into the vector of TrimAnalysis Controls the current values vector<FGTrimAnalysisControl*>::iterator vi; - for (vi=TrimAnalysis->GetControls()->begin(); - vi!=TrimAnalysis->GetControls()->end();vi++) + for(vi=TrimAnalysis->GetControls()->begin(); + vi!=TrimAnalysis->GetControls()->end();vi++) { if ( (*vi)->GetControlType()==JSBSim::taThrottle ) (*vi)->SetControl(delta_cmd_T); if ( (*vi)->GetControlType()==JSBSim::taElevator ) (*vi)->SetControl(delta_cmd_E); // TODO: taPitchTrim @@ -2513,7 +2335,7 @@ double Objective::myCostFunctionFullCoordinatedTurn(Vector<double> & x) << pDot <<", "<< qDot <<", "<< rDot <<", " // 13, 14, 15 << u <<", "<< v <<", "<< w << ", " // 16, 17, 18 << VState.vPQR(1) <<", "<< VState.vPQR(2) <<", "<< VState.vPQR(3) << ", " - // 19, 20, 21 + // 19, 20, 21 << FDMExec->GetAuxiliary()->Getalpha() << ", " // 22 << FDMExec->GetAuxiliary()->Getbeta() << ", " // 23 << FDMExec->GetAuxiliary()->Getadot() << ", " // 24 @@ -2601,22 +2423,19 @@ double Objective::myCostFunctionFullTurn(Vector<double> & x) // ToDo: manage bounds via the FGTrimAnalysisControl class //---------------------------------------------------------------------------- bool penalty = ( (delta_cmd_T < 0) || (delta_cmd_T > 1) ) - || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) - || ( (delta_cmd_A < -1) || (delta_cmd_A > 1) ) - || ( (delta_cmd_R < -1) || (delta_cmd_R > 1) ) - || ( (psi < 0.0 ) || (psi > 2.0*M_PI) ) - || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ) // may go out of range - ; - - if ( penalty ) - { + || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) + || ( (delta_cmd_A < -1) || (delta_cmd_A > 1) ) + || ( (delta_cmd_R < -1) || (delta_cmd_R > 1) ) + || ( (psi < 0.0 ) || (psi > 2.0*M_PI) ) + || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ) // may go out of range + ; + + if ( penalty ) { //------------------------------------------------- // just return an "infinite" value return HUGE_VAL; //------------------------------------------------- - } - else - { + } else { calculateDottedStates(delta_cmd_T, delta_cmd_E, delta_cmd_A, delta_cmd_R, phi, theta, psi, TrimAnalysis->GetMode(), @@ -2626,29 +2445,21 @@ double Objective::myCostFunctionFullTurn(Vector<double> & x) } double u , v , w , - p , q , r , - uDot, vDot, wDot, - pDot, qDot, rDot; - u = VState.vUVW (1); - v = VState.vUVW (2); - w = VState.vUVW (3); - p = VState.vPQR (1); - q = VState.vPQR (2); - r = VState.vPQR (3); - uDot = vUVWdot(1); - vDot = vUVWdot(2); - wDot = vUVWdot(3); - pDot = vPQRdot(1); - qDot = vPQRdot(2); - rDot = vPQRdot(3); + p , q , r , + uDot, vDot, wDot, + pDot, qDot, rDot; + u = VState.vUVW (1); v = VState.vUVW (2); w = VState.vUVW (3); + p = VState.vPQR (1); q = VState.vPQR (2); r = VState.vPQR (3); + uDot = vUVWdot(1); vDot = vUVWdot(2); wDot = vUVWdot(3); + pDot = vPQRdot(1); qDot = vPQRdot(2); rDot = vPQRdot(3); double f = 1.000*uDot*uDot - + vDot*vDot - + 1.000*wDot*wDot - + 0.010*pDot*pDot - + 0.010*qDot*qDot - + 0.010*rDot*rDot; + + vDot*vDot + + 1.000*wDot*wDot + + 0.010*pDot*pDot + + 0.010*qDot*qDot + + 0.010*rDot*rDot; static int count = 0; count++; @@ -2657,8 +2468,8 @@ double Objective::myCostFunctionFullTurn(Vector<double> & x) { // feed into the vector of TrimAnalysis Controls the current values vector<FGTrimAnalysisControl*>::iterator vi; - for (vi=TrimAnalysis->GetControls()->begin(); - vi!=TrimAnalysis->GetControls()->end();vi++) + for(vi=TrimAnalysis->GetControls()->begin(); + vi!=TrimAnalysis->GetControls()->end();vi++) { if ( (*vi)->GetControlType()==JSBSim::taThrottle ) (*vi)->SetControl(delta_cmd_T); if ( (*vi)->GetControlType()==JSBSim::taElevator ) (*vi)->SetControl(delta_cmd_E); // TODO: taPitchTrim @@ -2690,13 +2501,13 @@ double Objective::myCostFunctionFullTurn(Vector<double> & x) << pDot <<", "<< qDot <<", "<< rDot <<", " // 13, 14, 15 << u <<", "<< v <<", "<< w << ", " // 16, 17, 18 << VState.vPQR(1) <<", "<< VState.vPQR(2) <<", "<< VState.vPQR(3) << ", " - // 19, 20, 21 + // 19, 20, 21 << FDMExec->GetAuxiliary()->Getalpha() << ", " // 22 << FDMExec->GetAuxiliary()->Getbeta() << ", " // 23 << FDMExec->GetAuxiliary()->Getadot() << ", " // 24 << FDMExec->GetAuxiliary()->Getbdot() << ", " // 25 - << FDMExec->GetPropulsion()->GetEngine(0)->GetThrust() << "\n"; // + << FDMExec->GetPropulsion()->GetEngine(0)->GetThrust() << "\n"; // FDMExec->GetPropagate()->SetVState( VState ); // ?? is this really necessary @@ -2772,20 +2583,17 @@ double Objective::myCostFunctionPullUp(Vector<double> & x) // ToDo: manage bounds via the FGTrimAnalysisControl class //---------------------------------------------------------------------------- bool penalty = ( (delta_cmd_T < 0) || (delta_cmd_T > 1) ) - || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) - || ( (delta_cmd_A < -1) || (delta_cmd_A > 1) ) - || ( (delta_cmd_R < -1) || (delta_cmd_R > 1) ) - || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ); + || ( (delta_cmd_E < -1) || (delta_cmd_E > 1) ) + || ( (delta_cmd_A < -1) || (delta_cmd_A > 1) ) + || ( (delta_cmd_R < -1) || (delta_cmd_R > 1) ) + || ( (theta < -0.5*M_PI) || (theta > 0.5*M_PI) ); - if ( penalty ) - { + if ( penalty ) { //------------------------------------------------- // just return an "infinite" value return HUGE_VAL; //------------------------------------------------- - } - else - { + } else { calculateDottedStates(delta_cmd_T, delta_cmd_E, delta_cmd_A, delta_cmd_R, phi, theta, psi, TrimAnalysis->GetMode(), @@ -2795,29 +2603,21 @@ double Objective::myCostFunctionPullUp(Vector<double> & x) } double u , v , w , - p , q , r , - uDot, vDot, wDot, - pDot, qDot, rDot; - u = VState.vUVW (1); - v = VState.vUVW (2); - w = VState.vUVW (3); - p = VState.vPQR (1); - q = VState.vPQR (2); - r = VState.vPQR (3); - uDot = vUVWdot(1); - vDot = vUVWdot(2); - wDot = vUVWdot(3); - pDot = vPQRdot(1); - qDot = vPQRdot(2); - rDot = vPQRdot(3); + p , q , r , + uDot, vDot, wDot, + pDot, qDot, rDot; + u = VState.vUVW (1); v = VState.vUVW (2); w = VState.vUVW (3); + p = VState.vPQR (1); q = VState.vPQR (2); r = VState.vPQR (3); + uDot = vUVWdot(1); vDot = vUVWdot(2); wDot = vUVWdot(3); + pDot = vPQRdot(1); qDot = vPQRdot(2); rDot = vPQRdot(3); double f = 1.000*uDot*uDot - + vDot*vDot - + 1.000*wDot*wDot - + 0.010*pDot*pDot - + 0.010*qDot*qDot - + 0.010*rDot*rDot; + + vDot*vDot + + 1.000*wDot*wDot + + 0.010*pDot*pDot + + 0.010*qDot*qDot + + 0.010*rDot*rDot; static int count = 0; count++; @@ -2826,8 +2626,8 @@ double Objective::myCostFunctionPullUp(Vector<double> & x) { // feed into the vector of TrimAnalysis Controls the current values vector<FGTrimAnalysisControl*>::iterator vi; - for (vi=TrimAnalysis->GetControls()->begin(); - vi!=TrimAnalysis->GetControls()->end();vi++) + for(vi=TrimAnalysis->GetControls()->begin(); + vi!=TrimAnalysis->GetControls()->end();vi++) { if ( (*vi)->GetControlType()==JSBSim::taThrottle ) (*vi)->SetControl(delta_cmd_T); if ( (*vi)->GetControlType()==JSBSim::taElevator ) (*vi)->SetControl(delta_cmd_E); // TODO: taPitchTrim @@ -2859,7 +2659,7 @@ double Objective::myCostFunctionPullUp(Vector<double> & x) << pDot <<", "<< qDot <<", "<< rDot <<", " // 13, 14, 15 << u <<", "<< v <<", "<< w << ", " // 16, 17, 18 << VState.vPQR(1) <<", "<< VState.vPQR(2) <<", "<< VState.vPQR(3) << ", " - // 19, 20, 21 + // 19, 20, 21 << FDMExec->GetAuxiliary()->Getalpha() << ", " // 22 << FDMExec->GetAuxiliary()->Getbeta() << ", " // 23 << FDMExec->GetAuxiliary()->Getadot() << ", " // 24 @@ -2899,12 +2699,9 @@ void Objective::calculateDottedStates(double delta_cmd_T, double delta_cmd_E, do phiW = TrimAnalysis->GetPhiWRad(); } - cphi = cos(phi); - sphi = sin(phi); // phi, rad - ctheta = cos(theta); - stheta = sin(theta); // theta, rad - cpsi = cos(psi); - spsi = sin(psi); // psi, rad + cphi = cos(phi); sphi = sin(phi); // phi, rad + ctheta = cos(theta); stheta = sin(theta); // theta, rad + cpsi = cos(psi); spsi = sin(psi); // psi, rad TrimAnalysis->SetEulerAngles(phi, theta, psi); @@ -2913,18 +2710,17 @@ void Objective::calculateDottedStates(double delta_cmd_T, double delta_cmd_E, do //------------------------------------------------- // make sure the engines are running - for (unsigned int i=0; i<Propulsion->GetNumEngines(); i++) - { - Propulsion->GetEngine(i)->SetRunning(true); + for (unsigned int i=0; i<Propulsion->GetNumEngines(); i++) { + Propulsion->GetEngine(i)->SetRunning(true); } double tMin,tMax; - for (unsigned i=0;i<Propulsion->GetNumEngines();i++) + for(unsigned i=0;i<Propulsion->GetNumEngines();i++) { - tMin=Propulsion->GetEngine(i)->GetThrottleMin(); - tMax=Propulsion->GetEngine(i)->GetThrottleMax(); - FCS->SetThrottleCmd(i,tMin + delta_cmd_T *(tMax-tMin)); - FCS->Run(); // apply throttle change + tMin=Propulsion->GetEngine(i)->GetThrottleMin(); + tMax=Propulsion->GetEngine(i)->GetThrottleMax(); + FCS->SetThrottleCmd(i,tMin + delta_cmd_T *(tMax-tMin)); + FCS->Run(); // apply throttle change } Propulsion->GetSteadyState(); // GetSteadyState processes all engines @@ -3009,27 +2805,27 @@ void Objective::calculateDottedStates(double delta_cmd_T, double delta_cmd_E, do double u, v, w; u=vnorthIC*ctheta*cpsi + - veastIC*ctheta*spsi - - vdownIC*stheta; + veastIC*ctheta*spsi - + vdownIC*stheta; v=vnorthIC*( sphi*stheta*cpsi - cphi*spsi ) + - veastIC*( sphi*stheta*spsi + cphi*cpsi ) + - vdownIC*sphi*ctheta; + veastIC*( sphi*stheta*spsi + cphi*cpsi ) + + vdownIC*sphi*ctheta; w=vnorthIC*( cphi*stheta*cpsi + sphi*spsi ) + - veastIC*( cphi*stheta*spsi - sphi*cpsi ) + - vdownIC*cphi*ctheta; + veastIC*( cphi*stheta*spsi - sphi*cpsi ) + + vdownIC*cphi*ctheta; // Wind domponents in body-frame (from NED) double uw, vw, ww; uw=wnorthIC*ctheta*cpsi + - weastIC*ctheta*spsi - - wdownIC*stheta; + weastIC*ctheta*spsi - + wdownIC*stheta; vw=wnorthIC*( sphi*stheta*cpsi - cphi*spsi ) + - weastIC*( sphi*stheta*spsi + cphi*cpsi ) + - wdownIC*sphi*ctheta; + weastIC*( sphi*stheta*spsi + cphi*cpsi ) + + wdownIC*sphi*ctheta; ww=wnorthIC*(cphi*stheta*cpsi + sphi*spsi) + - weastIC*(cphi*stheta*spsi - sphi*cpsi) + - wdownIC*cphi*ctheta; + weastIC*(cphi*stheta*spsi - sphi*cpsi) + + wdownIC*cphi*ctheta; /********************************************************************************************** P R O P A G A T I O N start . . . @@ -3053,23 +2849,18 @@ void Objective::calculateDottedStates(double delta_cmd_T, double delta_cmd_E, do v=0.0; // no sideslip } - ua = u + uw; - va = v + vw; - wa = w + ww; + ua = u + uw; va = v + vw; wa = w + ww; // from FGAuxiliary::Run() - if ( vtIC > 0.05) - { - if ( wa != 0.0 ) alpha = ua*ua > 0.0 ? atan2(wa, ua) : 0.0; // this goes out to the caller - if ( va != 0.0 ) beta = ua*ua+wa*wa > 0.0 ? atan2(va,sqrt(ua*ua+wa*wa)) : 0.0; // this goes out to the caller - double mUW = (ua*ua + wa*wa); - double signU=1; - if (ua != 0.0) signU = ua/fabs(ua); - adot = bdot = 0; // enforce zero aerodyn. angle rates - } - else - { - alpha = beta = adot = bdot = 0; // this goes out to the caller + if ( vtIC > 0.05) { + if ( wa != 0.0 ) alpha = ua*ua > 0.0 ? atan2(wa, ua) : 0.0; // this goes out to the caller + if ( va != 0.0 ) beta = ua*ua+wa*wa > 0.0 ? atan2(va,sqrt(ua*ua+wa*wa)) : 0.0; // this goes out to the caller + double mUW = (ua*ua + wa*wa); + double signU=1; + if (ua != 0.0) signU = ua/fabs(ua); + adot = bdot = 0; // enforce zero aerodyn. angle rates + } else { + alpha = beta = adot = bdot = 0; // this goes out to the caller } //------------------------------------------------------------------------------------ @@ -3084,24 +2875,24 @@ void Objective::calculateDottedStates(double delta_cmd_T, double delta_cmd_E, do if ( ( trimMode == taTurn ) || ( trimMode == taTurnFull ) ) //... Coordinated turn: p,q,r not zero { - double g=FDMExec->GetInertial()->gravity(); - //double cgamma=cos(FDMExec->GetIC()->GetFlightPathAngleRadIC()); + double g=FDMExec->GetInertial()->gravity(); + //double cgamma=cos(FDMExec->GetIC()->GetFlightPathAngleRadIC()); - // assume that the given phiIC is the desired phi_Wind - // phiW ... see above at the beginning - double turnRate = g*tan(phiW) / FDMExec->GetIC()->GetVtrueFpsIC(); //FDMExec->GetIC()->GetUBodyFpsIC(); - double pW = 0.0; - double qW = turnRate*sin(phiW); - double rW = turnRate*cos(phiW); + // assume that the given phiIC is the desired phi_Wind + // phiW ... see above at the beginning + double turnRate = g*tan(phiW) / FDMExec->GetIC()->GetVtrueFpsIC(); //FDMExec->GetIC()->GetUBodyFpsIC(); + double pW = 0.0; + double qW = turnRate*sin(phiW); + double rW = turnRate*cos(phiW); - FGColumnVector3 pqr = TrimAnalysis->UpdateRatesTurn(psi, theta, phi, phiW); + FGColumnVector3 pqr = TrimAnalysis->UpdateRatesTurn(psi, theta, phi, phiW); - // finally calculate the body frame angular rates - p = pqr(1); - q = pqr(2); - r = pqr(3); + // finally calculate the body frame angular rates + p = pqr(1); + q = pqr(2); + r = pqr(3); - Auxiliary->SetGamma(0.); + Auxiliary->SetGamma(0.); } if ( trimMode == taPullup ) //... then p,q,r not zero @@ -3222,11 +3013,7 @@ void Objective::calculateDottedStates(double delta_cmd_T, double delta_cmd_E, do const FGMatrix33& Jinv = FDMExec->GetMassBalance()->GetJinv(); // inertia matrix inverse double rd = FDMExec->GetPropagate()->GetRadius(); // radius - if (rd == 0.0) - { - cerr << "radius = 0 !" << endl; // radius check - rd = 1e-16; - } + if (rd == 0.0) {cerr << "radius = 0 !" << endl; rd = 1e-16;} // radius check double rdInv = 1.0/rd; FGColumnVector3 gAccel( 0.0, 0.0, FDMExec->GetInertial()->GetGAccel(rd) ); @@ -3263,8 +3050,7 @@ void Objective::calculateDottedStates(double delta_cmd_T, double delta_cmd_E, do FGColumnVector3 ace = 2.0*omega*ecVel; //... vUVWdot -= Tl2b*(Tec2l*ace); - if (!FDMExec->GetGroundReactions()->GetWOW()) - { + if (!FDMExec->GetGroundReactions()->GetWOW()) { // Centrifugal acceleration. FGColumnVector3 aeec = omega*(omega*VState.vLocation); } @@ -3276,8 +3062,8 @@ void Objective::calculateDottedStates(double delta_cmd_T, double delta_cmd_E, do FGColumnVector3 vLocationDot = Tl2ec * vVel; FGColumnVector3 omegaLocal( rdInv*vVel(2), // East - -rdInv*vVel(1), // North - -rdInv*vVel(2)*VState.vLocation.GetTanLatitude() ); + -rdInv*vVel(1), // North + -rdInv*vVel(2)*VState.vLocation.GetTanLatitude() ); // Compute quaternion orientation derivative on current body rates //... FGQuaternion vQtrndot = VState.vQtrn.GetQDot( VState.vPQR - Tl2b*omegaLocal ); @@ -3291,16 +3077,16 @@ void Objective::calculateDottedStates(double delta_cmd_T, double delta_cmd_E, do bool FGTrimAnalysis::getSteadyState(int nrepeat ) { - double currentThrust = 0, lastThrust=-1; - int steady_count=0; - bool steady=false; - - while ( !steady && steady_count <= nrepeat ) - { - steady_count++; - steady = Propulsion->GetSteadyState(); - } - return steady; + double currentThrust = 0, lastThrust=-1; + int steady_count=0; + bool steady=false; + + while ( !steady && steady_count <= nrepeat ) + { + steady_count++; + steady = Propulsion->GetSteadyState(); + } + return steady; } //................................................................................ diff --git a/src/initialization/FGTrimAnalysis.h b/src/initialization/FGTrimAnalysis.h old mode 100644 new mode 100755 index d9feb8413b2193dc7a1abe8a559d34623f466fc4..824ca689abee6691b302b4a602cf7ef2fc33a506 --- a/src/initialization/FGTrimAnalysis.h +++ b/src/initialization/FGTrimAnalysis.h @@ -77,19 +77,17 @@ DEFINITIONS #define ID_FGTRIMANALYSIS "$Id: FGTrimAnalysis.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $" #if defined(_WIN32) && !defined(__CYGWIN__) -#define snprintf _snprintf + #define snprintf _snprintf #endif /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { typedef enum { taLongitudinal=0, taFull, taFullWingsLevel, taTurn, taPullup, taTurnFull, - taGround, taCustom, taNone - } TrimAnalysisMode; + taGround, taCustom, taNone } TrimAnalysisMode; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -128,8 +126,7 @@ CLASS DECLARATION class FGTrimAnalysis; -class Objective -{ +class Objective { public: /** Constructor */ @@ -201,7 +198,7 @@ public: * should be cast to a pointer of the class type. */ friend void find_CostFunctionFull(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr); + bool & success, void* t_ptr); /* function definiation moved outside of class declaration */ /** Wrapping function for the effective Wings Level Trim cost function, to be called by optimization method @@ -217,7 +214,7 @@ public: * should be cast to a pointer of the class type. */ friend void find_CostFunctionFullWingsLevel(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr); + bool & success, void* t_ptr); /* function definiation moved outside of class declaration */ /** Wrapping function for the effective Longitudinal Trim cost function, to be called by optimization method @@ -233,7 +230,7 @@ public: * should be cast to a pointer of the class type. */ friend void find_CostFunctionLongitudinal(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr); + bool & success, void* t_ptr); /* function definiation moved outside of class declaration */ /** Wrapping function for the effective Steady Turn Trim cost function, to be called by optimization method @@ -249,7 +246,7 @@ public: * should be cast to a pointer of the class type. */ friend void find_CostFunctionFullCoordinatedTurn(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr); + bool & success, void* t_ptr); /* function definiation moved outside of class declaration */ /** Wrapping function for the effective Steady Turn Trim cost function, to be called by optimization method @@ -265,7 +262,7 @@ public: * should be cast to a pointer of the class type. */ friend void find_CostFunctionFullTurn(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr); + bool & success, void* t_ptr); /* function definiation moved outside of class declaration */ /** Wrapping function for the effective Pullup Trim cost function, to be called by optimization method @@ -281,14 +278,11 @@ public: * should be cast to a pointer of the class type. */ friend void find_CostFunctionPullUp(long vars, Vector<double> &v, double & f, - bool & success, void* t_ptr); + bool & success, void* t_ptr); /* function definiation moved outside of class declaration */ void Set_x_val(double new_x); - double Get_x_val() const - { - return _x; - } + double Get_x_val() const {return _x;} /** Pointer to cost function implementation */ @@ -336,411 +330,340 @@ private: class FGTrimAnalysis : public FGJSBBase, public FGXMLFileRead { private: - vector<FGTrimAnalysisControl*> vTrimAnalysisControls; - double cost_function_value; - unsigned int current_ctrl; - int N, Nsub; - TrimAnalysisMode mode; - int DebugLevel, Debug; - - double dth; - bool trimudot; - bool gamma_fallback; - - bool trim_failed; - unsigned int ctrl_count; - - FGFDMExec* fdmex; - FGInitialCondition * fgic; // IC; - - FGAuxiliary * Auxiliary; - FGAerodynamics * Aerodynamics; - FGPropulsion * Propulsion; - FGFCS * FCS; - - vector<double> vAlphaDeg, vAlphaTrimDeg; // DEG !!! - vector<double> vCL, vCD, vCm; - vector<double> vCLE, vCDE, vCmE; - vector<vector <double> > mCL, mCD, mCm, mTa; - vector<double> vThrottleCmd, vElevatorCmd; - vector<double> vVn, vTn, vTa, vVnE, vTE; - vector<double> vCt, vCq, vRPM; - vector<vector <double> > mCt, mCq, mRPM; - vector<bool> hasThrustTrim, hasCmTrim; - - string trim_id; - - // direct search stuff - string search_type; - double sigma_nm, alpha_nm, beta_nm, gamma_nm; - double initial_step; - double tolerance; - string stop_criterion; - int max_iterations; - int total_its; - - // results file - mutable ofstream rf; // see Stroustrup 10.2.7.2; alternative: use a cache struct - string rf_name; - - double _u,_v,_w; - double _p,_q,_r; - //double uw,vw,ww; - //double vnorth,veast,vdown; - //double wnorth,weast,wdown; - double _alpha, _beta, _theta, _phi, _psi, _psiW, _gamma, _phiW; - - double _stheta, _sphi, _spsi; - double _ctheta, _cphi, _cpsi; - - double _vtIC, _hIC, _gammaIC, _rocIC, _vdownIC, _psiIC, _psigtIC, _vgIC, - _vnorthIC, _veastIC, wnorthIC, _weastIC, _wdownIC; - - double _udot, _vdot, _wdot, _pdot, _qdot, _rdot; - double _targetNlf; - double _psiWdot, _phiWdot, _gammadot, _psidot, _thetadot; - - double C1, C2, C3, _calpha, _salpha, _cbeta, _sbeta; - - void setupPullup(void); - void setupTurn(void); - void setupTurn(double phiW); // recalculate target Nlf - void setupTurnPhi(double psi, double theta); // recalculate only phi - - void updateRates(void); - - void setDebug(void); - - bool ensureRunning(void); - bool ensureRunning(unsigned int i); - bool runForAWhile(int nruns); - - bool populateVecAlphaDeg(double vmin, double vmax, int n); - bool populateVecThrottleCmd(double vmin, double vmax, int n); - bool populateVecElevatorCmd(double vmin, double vmax, int n); - - bool calculateAerodynamics( - double dE_cmd, - double Vt, - double alpha_deg, - double altitude, - double rho, - double S, double mac, double bw, - double& CL, double& CD, double& Cm); - - - bool getSteadyState(int nrepeat); - bool InitializeTrimControl(double default_value, Element* el, - string unit, TaControl type); + vector<FGTrimAnalysisControl*> vTrimAnalysisControls; + double cost_function_value; + unsigned int current_ctrl; + int N, Nsub; + TrimAnalysisMode mode; + int DebugLevel, Debug; + + double dth; + bool trimudot; + bool gamma_fallback; + + bool trim_failed; + unsigned int ctrl_count; + + FGFDMExec* fdmex; + FGInitialCondition * fgic; // IC; + + FGAuxiliary * Auxiliary; + FGAerodynamics * Aerodynamics; + FGPropulsion * Propulsion; + FGFCS * FCS; + + vector<double> vAlphaDeg, vAlphaTrimDeg; // DEG !!! + vector<double> vCL, vCD, vCm; + vector<double> vCLE, vCDE, vCmE; + vector<vector <double> > mCL, mCD, mCm, mTa; + vector<double> vThrottleCmd, vElevatorCmd; + vector<double> vVn, vTn, vTa, vVnE, vTE; + vector<double> vCt, vCq, vRPM; + vector<vector <double> > mCt, mCq, mRPM; + vector<bool> hasThrustTrim, hasCmTrim; + + string trim_id; + + // direct search stuff + string search_type; + double sigma_nm, alpha_nm, beta_nm, gamma_nm; + double initial_step; + double tolerance; + string stop_criterion; + int max_iterations; + int total_its; + + // results file + mutable ofstream rf; // see Stroustrup 10.2.7.2; alternative: use a cache struct + string rf_name; + + double _u,_v,_w; + double _p,_q,_r; + //double uw,vw,ww; + //double vnorth,veast,vdown; + //double wnorth,weast,wdown; + double _alpha, _beta, _theta, _phi, _psi, _psiW, _gamma, _phiW; + + double _stheta, _sphi, _spsi; + double _ctheta, _cphi, _cpsi; + + double _vtIC, _hIC, _gammaIC, _rocIC, _vdownIC, _psiIC, _psigtIC, _vgIC, + _vnorthIC, _veastIC, wnorthIC, _weastIC, _wdownIC; + + double _udot, _vdot, _wdot, _pdot, _qdot, _rdot; + double _targetNlf; + double _psiWdot, _phiWdot, _gammadot, _psidot, _thetadot; + + double C1, C2, C3, _calpha, _salpha, _cbeta, _sbeta; + + void setupPullup(void); + void setupTurn(void); + void setupTurn(double phiW); // recalculate target Nlf + void setupTurnPhi(double psi, double theta); // recalculate only phi + + void updateRates(void); + + void setDebug(void); + + bool ensureRunning(void); + bool ensureRunning(unsigned int i); + bool runForAWhile(int nruns); + + bool populateVecAlphaDeg(double vmin, double vmax, int n); + bool populateVecThrottleCmd(double vmin, double vmax, int n); + bool populateVecElevatorCmd(double vmin, double vmax, int n); + + bool calculateAerodynamics( + double dE_cmd, + double Vt, + double alpha_deg, + double altitude, + double rho, + double S, double mac, double bw, + double& CL, double& CD, double& Cm); + + + bool getSteadyState(int nrepeat); + bool InitializeTrimControl(double default_value, Element* el, + string unit, TaControl type); public: - /** Initializes the trimming class - @param FDMExec pointer to a JSBSim executive object. - @param tam trim mode - */ - FGTrimAnalysis(FGFDMExec *FDMExec, TrimAnalysisMode tam=taFull ); - - /// Destructor - ~FGTrimAnalysis(void); - - friend class Objective; - - /** Loads the trim configuration from file. - @param fname The name of a trim configuration file - @param useStoredPath true if the stored path to the trim config file should be used - @return true if successful */ - bool Load(string fname, bool useStoredPath = true ); - - /** Execute the trim - */ - bool DoTrim(void); - - /** Print the results of the trim. For each axis trimmed, this - includes the final state value, control value, and tolerance - used. - @return true if trim succeeds - */ - void Report(void); - - /** Iteration statistics - */ - void TrimStats(); - - /** Set the file where trim analysis results are written, - open and get ready - @param name the file name - @return true if file open is successful - */ - bool SetResultsFile(string name); - - /** Get the pointer to the file where trim analysis results are written, - @return non null pointer if file is open - */ - ofstream* GetResultsFile() const - { - if (rf.is_open()) return &rf; // const_cast<ofstream*>(&rf) (if rf is not mutable) - else return 0; - } - - /** Set the value of the cost function - @param value the cost function value - */ - inline void SetCostFunctionValue(double value) - { - cost_function_value = value; - } - - /** @return The current cost function value - */ - inline double GetCostFunctionValue() const - { - return cost_function_value; - } - - /** Clear all controls and set a predefined trim mode - (Note: controls are intended here as those variables to be - adjusted for attaining convergence of the trimming algorithm) - @param tam the set of axes to trim. Can be: - taLongitudinal, taFull, taGround, taCustom, or taNone - */ - void SetMode(TrimAnalysisMode tam); - - /** @return The Trim Analysis mode - taLongitudinal, taFull, taGround, taCustom, or taNone - */ - inline TrimAnalysisMode GetMode() const - { - return mode; - }; - - inline vector<FGTrimAnalysisControl*>* GetControls() - { - return &vTrimAnalysisControls; - } - - /** Clear all controls from the current configuration. - The trimming routine must have at least one control - configured to be useful - (Note: controls are intended here as those variables to be - adjusted for attaining convergence of the trimming algorithm) - */ - void ClearControls(void); - - /** Add a control to the current configuration. See the enums - TaControl in FGTrimAnalysisControl.h for the available options. - (Note: controls are intended here as those variables to be - adjusted for attaining convergence of the trimming algorithm) - Will fail if the given state is already configured. - @param control the control to be adjusted in the trimming algorithm - @return true if add is successful - */ - bool AddControl( TaControl control ); - - /** Remove a specific control from the current configuration - @param control the state to remove - @return true if removal is successful - */ - bool RemoveControl( TaControl control ); - - /** Change the control settings previously configured - @param new_control the control used to zero the state - @param new_initvalue a new initial value - @param new_step a new adjusting step - @param new_min, new_max a new range - @return true if editing is successful - */ - bool EditState( TaControl new_control, double new_initvalue, double new_step, double new_min, double new_max ); - - - /** Return the current flight path angle in TrimAnalysis object - @return value of gamma - */ - inline double GetGamma() - { - return _gamma; - } - - /** automatically switch to trimming longitudinal acceleration with - flight path angle (gamma) once it becomes apparent that there - is not enough/too much thrust. - @param bb true to enable fallback - */ - inline void SetGammaFallback(bool bb) - { - gamma_fallback=bb; - } - - /** query the fallback state - @return true if fallback is enabled. - */ - inline bool GetGammaFallback(void) - { - return gamma_fallback; - } - - /** Set the iteration limit. DoTrim() will return false if limit - iterations are reached before trim is achieved. The default - is 60. This does not ordinarily need to be changed. - @param ii integer iteration limit - */ - inline void SetMaxCycles(int ii) - { - max_iterations = ii; - } - - /** Set the tolerance for declaring a state trimmed. - (In the evaluation of the cost function, squares of angular accels are - devided by 100) - The default is 1e-8. - @param tt user defined tolerance - */ - inline void SetTolerance(double tt) - { - tolerance = tt; - } - /** Get the tolerance for declaring a state trimmed. - @return tolerance. - */ - inline double GetTolerance(void) - { - return tolerance; - } - - /** Sets trim result status - @param tf (boolean) - */ - inline void SetTrimFailed(bool tf) - { - trim_failed = tf; - } - /** Gets trim result status - @return trim_failed (boolean) - */ - inline bool GetTrimFailed(void) - { - return trim_failed; - } - inline void SetTrimSuccessfull() - { - trim_failed = false; - } - - - /** Sets state variables - @param u0 - @param v0 - @param w0 - @param p0 - @param q0 - @param r0 - @param alpha0 - @param beta0 - @param phi0 - @param psi0 - @param theta0 - @param gamma0 - **/ - void SetState(double u0, double v0, double w0, double p0, double q0, double r0, - double alpha0, double beta0, double phi0, double theta0, double psi0, double gamma0); - - /** Sets Euler angles - @param phi0, theta0, psi0 **/ - void SetEulerAngles(double phi0, double theta0, double psi0); - - /** Gets Euler angle phi - @return phi [rad] - */ - double GetPhiRad () - { - return _phi; - } - /** Gets Euler angle theta - @return phi [rad] - */ - double GetThetaRad() - { - return _theta; - } - /** Gets Euler angle psi - @return phi [rad] - */ - double GetPsiRad () - { - return _psi; - } - - /** Gets Euler angle phiW (wind axes) - @return phiW [rad] - */ - double GetPhiWRad () - { - return _phiW; - } - /** Gets flight path angle - @return gamma [rad] - */ - double GetGammaRad () - { - return _gamma; - } - /** Gets true speed [fps] from IC - @return Vt [fps] - */ - double GetVtFps () - { - return _vtIC; - } - - /** Calculate the wind axis bank angle from a given Nlf (sets also the target Nlf) - @param nlf - */ - void CalculatePhiWFromTargetNlfTurn(double nlf); - - /** Updates angular rates for turn trim according to turning trim constraints - @param psi, theta, phi - @return p, q, r - */ - FGColumnVector3 UpdateRatesTurn(double psi, double theta, double phi, double phiW); - - /** Updates angular rates for pull-up trim - @return p, q, r - */ - FGColumnVector3 UpdateRatesPullup(void); - - /** Sets Dotted values - @param udot, vdot, wdot, pdot, qdot, rdot **/ - void SetDottedValues(double udot, double vdot, double wdot, double pdot, double qdot, double rdot); - - /** - Debug level 1 shows results of each top-level iteration - Debug level 2 shows level 1 & results of each per-axis iteration - */ - inline void SetDebug(int level) - { - DebugLevel = level; - } - inline void ClearDebug(void) - { - DebugLevel = 0; - } - - /** Sets target normal load factor in steady turn - @param nlf target normal load factor **/ - inline void SetTargetNlf(double nlf) - { - _targetNlf=nlf; - } - - /** Gets target normal load factor in steady turn - @return _targetNlf - */ - inline double GetTargetNlf(void) - { - return _targetNlf; - } - - //void eom_costf (long vars, Vector<double> &x, double & f, bool& flag, void* an_obj); - //inline FGFDMExec* GetFDMExec() const { return fdmex; } + /** Initializes the trimming class + @param FDMExec pointer to a JSBSim executive object. + @param tam trim mode + */ + FGTrimAnalysis(FGFDMExec *FDMExec, TrimAnalysisMode tam=taFull ); + + /// Destructor + ~FGTrimAnalysis(void); + + friend class Objective; + + /** Loads the trim configuration from file. + @param fname The name of a trim configuration file + @param useStoredPath true if the stored path to the trim config file should be used + @return true if successful */ + bool Load(string fname, bool useStoredPath = true ); + + /** Execute the trim + */ + bool DoTrim(void); + + /** Print the results of the trim. For each axis trimmed, this + includes the final state value, control value, and tolerance + used. + @return true if trim succeeds + */ + void Report(void); + + /** Iteration statistics + */ + void TrimStats(); + + /** Set the file where trim analysis results are written, + open and get ready + @param name the file name + @return true if file open is successful + */ + bool SetResultsFile(string name); + + /** Get the pointer to the file where trim analysis results are written, + @return non null pointer if file is open + */ + ofstream* GetResultsFile() const { if (rf.is_open()) return &rf; else return 0; } // const_cast<ofstream*>(&rf) (if rf is not mutable) + + /** Set the value of the cost function + @param value the cost function value + */ + inline void SetCostFunctionValue(double value){cost_function_value = value;} + + /** @return The current cost function value + */ + inline double GetCostFunctionValue() const { return cost_function_value;} + + /** Clear all controls and set a predefined trim mode + (Note: controls are intended here as those variables to be + adjusted for attaining convergence of the trimming algorithm) + @param tam the set of axes to trim. Can be: + taLongitudinal, taFull, taGround, taCustom, or taNone + */ + void SetMode(TrimAnalysisMode tam); + + /** @return The Trim Analysis mode + taLongitudinal, taFull, taGround, taCustom, or taNone + */ + inline TrimAnalysisMode GetMode() const { return mode;}; + + inline vector<FGTrimAnalysisControl*>* GetControls(){return &vTrimAnalysisControls;} + + /** Clear all controls from the current configuration. + The trimming routine must have at least one control + configured to be useful + (Note: controls are intended here as those variables to be + adjusted for attaining convergence of the trimming algorithm) + */ + void ClearControls(void); + + /** Add a control to the current configuration. See the enums + TaControl in FGTrimAnalysisControl.h for the available options. + (Note: controls are intended here as those variables to be + adjusted for attaining convergence of the trimming algorithm) + Will fail if the given state is already configured. + @param control the control to be adjusted in the trimming algorithm + @return true if add is successful + */ + bool AddControl( TaControl control ); + + /** Remove a specific control from the current configuration + @param control the state to remove + @return true if removal is successful + */ + bool RemoveControl( TaControl control ); + + /** Change the control settings previously configured + @param new_control the control used to zero the state + @param new_initvalue a new initial value + @param new_step a new adjusting step + @param new_min, new_max a new range + @return true if editing is successful + */ + bool EditState( TaControl new_control, double new_initvalue, double new_step, double new_min, double new_max ); + + + /** Return the current flight path angle in TrimAnalysis object + @return value of gamma + */ + inline double GetGamma() { return _gamma; } + + /** automatically switch to trimming longitudinal acceleration with + flight path angle (gamma) once it becomes apparent that there + is not enough/too much thrust. + @param bb true to enable fallback + */ + inline void SetGammaFallback(bool bb) { gamma_fallback=bb; } + + /** query the fallback state + @return true if fallback is enabled. + */ + inline bool GetGammaFallback(void) { return gamma_fallback; } + + /** Set the iteration limit. DoTrim() will return false if limit + iterations are reached before trim is achieved. The default + is 60. This does not ordinarily need to be changed. + @param ii integer iteration limit + */ + inline void SetMaxCycles(int ii) { max_iterations = ii; } + + /** Set the tolerance for declaring a state trimmed. + (In the evaluation of the cost function, squares of angular accels are + devided by 100) + The default is 1e-8. + @param tt user defined tolerance + */ + inline void SetTolerance(double tt) { + tolerance = tt; + } + /** Get the tolerance for declaring a state trimmed. + @return tolerance. + */ + inline double GetTolerance(void) {return tolerance; } + + /** Sets trim result status + @param tf (boolean) + */ + inline void SetTrimFailed(bool tf) { trim_failed = tf; } + /** Gets trim result status + @return trim_failed (boolean) + */ + inline bool GetTrimFailed(void) { return trim_failed; } + inline void SetTrimSuccessfull() { trim_failed = false; } + + + /** Sets state variables + @param u0 + @param v0 + @param w0 + @param p0 + @param q0 + @param r0 + @param alpha0 + @param beta0 + @param phi0 + @param psi0 + @param theta0 + @param gamma0 + **/ + void SetState(double u0, double v0, double w0, double p0, double q0, double r0, + double alpha0, double beta0, double phi0, double theta0, double psi0, double gamma0); + + /** Sets Euler angles + @param phi0, theta0, psi0 **/ + void SetEulerAngles(double phi0, double theta0, double psi0); + + /** Gets Euler angle phi + @return phi [rad] + */ + double GetPhiRad (){ return _phi;} + /** Gets Euler angle theta + @return phi [rad] + */ + double GetThetaRad(){ return _theta;} + /** Gets Euler angle psi + @return phi [rad] + */ + double GetPsiRad (){ return _psi;} + + /** Gets Euler angle phiW (wind axes) + @return phiW [rad] + */ + double GetPhiWRad (){ return _phiW;} + /** Gets flight path angle + @return gamma [rad] + */ + double GetGammaRad (){ return _gamma;} + /** Gets true speed [fps] from IC + @return Vt [fps] + */ + double GetVtFps (){ return _vtIC;} + + /** Calculate the wind axis bank angle from a given Nlf (sets also the target Nlf) + @param nlf + */ + void CalculatePhiWFromTargetNlfTurn(double nlf); + + /** Updates angular rates for turn trim according to turning trim constraints + @param psi, theta, phi + @return p, q, r + */ + FGColumnVector3 UpdateRatesTurn(double psi, double theta, double phi, double phiW); + + /** Updates angular rates for pull-up trim + @return p, q, r + */ + FGColumnVector3 UpdateRatesPullup(void); + + /** Sets Dotted values + @param udot, vdot, wdot, pdot, qdot, rdot **/ + void SetDottedValues(double udot, double vdot, double wdot, double pdot, double qdot, double rdot); + + /** + Debug level 1 shows results of each top-level iteration + Debug level 2 shows level 1 & results of each per-axis iteration + */ + inline void SetDebug(int level) { DebugLevel = level; } + inline void ClearDebug(void) { DebugLevel = 0; } + + /** Sets target normal load factor in steady turn + @param nlf target normal load factor **/ + inline void SetTargetNlf(double nlf) { _targetNlf=nlf; } + + /** Gets target normal load factor in steady turn + @return _targetNlf + */ + inline double GetTargetNlf(void) { return _targetNlf; } + + //void eom_costf (long vars, Vector<double> &x, double & f, bool& flag, void* an_obj); + //inline FGFDMExec* GetFDMExec() const { return fdmex; } }; } diff --git a/src/initialization/FGTrimAnalysisControl.cpp b/src/initialization/FGTrimAnalysisControl.cpp old mode 100644 new mode 100755 index 9acb45dfa426423a0de79264f4762bc681b46f8e..fc288a39ba303807412da097b5334893ef7eba6e --- a/src/initialization/FGTrimAnalysisControl.cpp +++ b/src/initialization/FGTrimAnalysisControl.cpp @@ -52,8 +52,7 @@ SENTRY #include "models/FGPropulsion.h" #include "models/FGAerodynamics.h" -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGTrimAnalysisControl.cpp,v 1.4 2009/10/02 10:30:09 jberndt Exp $"; static const char *IdHdr = ID_TRIMANALYSISCONTROL; @@ -61,298 +60,218 @@ static const char *IdHdr = ID_TRIMANALYSISCONTROL; /*****************************************************************************/ FGTrimAnalysisControl::FGTrimAnalysisControl(FGFDMExec* fdex, FGInitialCondition* ic, - //State st, - TaControl ctrl) -{ - fdmex=fdex; - fgic=ic; - state=taAll; - control=ctrl; - control_initial_value = 0.; - control_value=0; - state_convert=1.0; - control_convert=1.0; - state_value=0; - state_target=0; - control_tolerance = DEFAULT_TOLERANCE; - - switch (control) - { - case taThrottle: - control_min=0; - control_max=1; - control_step=0.2; - control_initial_value = 0.5; - control_value=control_initial_value; - control_name = "Throttle (cmd,norm)"; - break; - case taBeta: - control_min=-30*degtorad; - control_max=30*degtorad; - control_step=1*degtorad; - control_convert=radtodeg; - break; - case taAlpha: - control_min=fdmex->GetAerodynamics()->GetAlphaCLMin(); - control_max=fdmex->GetAerodynamics()->GetAlphaCLMax(); - if (control_max <= control_min) - { - control_max=20*degtorad; - control_min=-5*degtorad; - } - control_step=1*degtorad; - control_initial_value = (control_min+control_max)/2; - control_value= control_initial_value; - control_convert=radtodeg; - break; - case taPitchTrim: - control_name = "Pitch Trim (cmd,norm)"; - control_min=-1; - control_max=1; - control_step=0.1; - state_convert=radtodeg; - break; - case taElevator: - control_name = "Elevator (cmd,norm)"; - control_min=-1; - control_max=1; - control_step=0.1; - state_convert=radtodeg; - break; - case taRollTrim: - control_name = "Roll Trim (cmd,norm)"; - control_min=-1; - control_max=1; - control_step=0.1; - state_convert=radtodeg; - break; - case taAileron: - control_name = "Ailerons (cmd,norm)"; - control_min=-1; - control_max=1; - control_step=0.1; - state_convert=radtodeg; - break; - case taYawTrim: - control_name = "Yaw Trim (cmd,norm)"; - control_min=-1; - control_max=1; - control_step=0.1; - state_convert=radtodeg; - break; - case taRudder: - control_name = "Rudder (cmd,norm)"; - control_min=-1; - control_max=1; - control_step=0.1; - state_convert=radtodeg; - break; - case taAltAGL: - control_name = "Altitude (ft)"; - control_min=0; - control_max=30; - control_step=2; - control_initial_value = fdmex->GetPropagate()->GetDistanceAGL(); - control_value = control_initial_value; - break; - case taPhi: - control_name = "Phi (rad)"; - control_min=fdmex->GetPropagate()->GetEuler(ePhi) - 30*degtorad; - control_max=fdmex->GetPropagate()->GetEuler(ePhi) + 30*degtorad; - control_step=1*degtorad; - state_convert=radtodeg; - control_convert=radtodeg; - break; - case taTheta: - control_name = "Theta (rad)"; - control_min=fdmex->GetPropagate()->GetEuler(eTht) - 5*degtorad; - control_max=fdmex->GetPropagate()->GetEuler(eTht) + 5*degtorad; - control_step=1*degtorad; - state_convert=radtodeg; - break; - case taHeading: - control_name = "Heading (rad)"; - control_min=fdmex->GetPropagate()->GetEuler(ePsi) - 30*degtorad; - control_max=fdmex->GetPropagate()->GetEuler(ePsi) + 30*degtorad; - control_step=1*degtorad; - state_convert=radtodeg; - break; - case taGamma: - control_name = "Gamma (rad)"; - control_min=-80*degtorad; - control_max=80*degtorad; - control_step=1*degtorad; - control_convert=radtodeg; - break; + //State st, + TaControl ctrl) { + fdmex=fdex; + fgic=ic; + state=taAll; + control=ctrl; + control_initial_value = 0.; + control_value=0; + state_convert=1.0; + control_convert=1.0; + state_value=0; + state_target=0; + control_tolerance = DEFAULT_TOLERANCE; + + switch(control) { + case taThrottle: + control_min=0; + control_max=1; + control_step=0.2; + control_initial_value = 0.5; + control_value=control_initial_value; + control_name = "Throttle (cmd,norm)"; + break; + case taBeta: + control_min=-30*degtorad; + control_max=30*degtorad; + control_step=1*degtorad; + control_convert=radtodeg; + break; + case taAlpha: + control_min=fdmex->GetAerodynamics()->GetAlphaCLMin(); + control_max=fdmex->GetAerodynamics()->GetAlphaCLMax(); + if(control_max <= control_min) { + control_max=20*degtorad; + control_min=-5*degtorad; } + control_step=1*degtorad; + control_initial_value = (control_min+control_max)/2; + control_value= control_initial_value; + control_convert=radtodeg; + break; + case taPitchTrim: + control_name = "Pitch Trim (cmd,norm)"; + control_min=-1; + control_max=1; + control_step=0.1; + state_convert=radtodeg; + break; + case taElevator: + control_name = "Elevator (cmd,norm)"; + control_min=-1; + control_max=1; + control_step=0.1; + state_convert=radtodeg; + break; + case taRollTrim: + control_name = "Roll Trim (cmd,norm)"; + control_min=-1; + control_max=1; + control_step=0.1; + state_convert=radtodeg; + break; + case taAileron: + control_name = "Ailerons (cmd,norm)"; + control_min=-1; + control_max=1; + control_step=0.1; + state_convert=radtodeg; + break; + case taYawTrim: + control_name = "Yaw Trim (cmd,norm)"; + control_min=-1; + control_max=1; + control_step=0.1; + state_convert=radtodeg; + break; + case taRudder: + control_name = "Rudder (cmd,norm)"; + control_min=-1; + control_max=1; + control_step=0.1; + state_convert=radtodeg; + break; + case taAltAGL: + control_name = "Altitude (ft)"; + control_min=0; + control_max=30; + control_step=2; + control_initial_value = fdmex->GetPropagate()->GetDistanceAGL(); + control_value = control_initial_value; + break; + case taPhi: + control_name = "Phi (rad)"; + control_min=fdmex->GetPropagate()->GetEuler(ePhi) - 30*degtorad; + control_max=fdmex->GetPropagate()->GetEuler(ePhi) + 30*degtorad; + control_step=1*degtorad; + state_convert=radtodeg; + control_convert=radtodeg; + break; + case taTheta: + control_name = "Theta (rad)"; + control_min=fdmex->GetPropagate()->GetEuler(eTht) - 5*degtorad; + control_max=fdmex->GetPropagate()->GetEuler(eTht) + 5*degtorad; + control_step=1*degtorad; + state_convert=radtodeg; + break; + case taHeading: + control_name = "Heading (rad)"; + control_min=fdmex->GetPropagate()->GetEuler(ePsi) - 30*degtorad; + control_max=fdmex->GetPropagate()->GetEuler(ePsi) + 30*degtorad; + control_step=1*degtorad; + state_convert=radtodeg; + break; + case taGamma: + control_name = "Gamma (rad)"; + control_min=-80*degtorad; + control_max=80*degtorad; + control_step=1*degtorad; + control_convert=radtodeg; + break; + } // if (debug_lvl > 0) // cout << "FGTrimAnalysisControl created: "<< control_name << endl; - Debug(0); + Debug(0); } /*****************************************************************************/ FGTrimAnalysisControl::~FGTrimAnalysisControl(void) { - Debug(1); + Debug(1); } /*****************************************************************************/ -void FGTrimAnalysisControl::getState(void) -{ - switch (state) - { - case taUdot: - state_value=fdmex->GetPropagate()->GetUVWdot(1)-state_target; - break; - case taVdot: - state_value=fdmex->GetPropagate()->GetUVWdot(2)-state_target; - break; - case taWdot: - state_value=fdmex->GetPropagate()->GetUVWdot(3)-state_target; - break; - case taPdot: - state_value=fdmex->GetPropagate()->GetPQRdot(1)-state_target; - break; - case taQdot: - state_value=fdmex->GetPropagate()->GetPQRdot(2)-state_target; - break; - case taRdot: - state_value=fdmex->GetPropagate()->GetPQRdot(3)-state_target; - break; - case taHmgt: - state_value=computeHmgt()-state_target; - break; - case taNlf: - state_value=fdmex->GetAircraft()->GetNlf()-state_target; - break; - case taAll: - break; - } +void FGTrimAnalysisControl::getState(void) { + switch(state) { + case taUdot: state_value=fdmex->GetPropagate()->GetUVWdot(1)-state_target; break; + case taVdot: state_value=fdmex->GetPropagate()->GetUVWdot(2)-state_target; break; + case taWdot: state_value=fdmex->GetPropagate()->GetUVWdot(3)-state_target; break; + case taPdot: state_value=fdmex->GetPropagate()->GetPQRdot(1)-state_target; break; + case taQdot: state_value=fdmex->GetPropagate()->GetPQRdot(2)-state_target;break; + case taRdot: state_value=fdmex->GetPropagate()->GetPQRdot(3)-state_target; break; + case taHmgt: state_value=computeHmgt()-state_target; break; + case taNlf: state_value=fdmex->GetAircraft()->GetNlf()-state_target; break; + case taAll: break; + } } /*****************************************************************************/ //States are not settable -void FGTrimAnalysisControl::getControl(void) -{ - switch (control) - { - case taThrottle: - control_value=fdmex->GetFCS()->GetThrottleCmd(0); - break; - case taBeta: - control_value=fdmex->GetAuxiliary()->Getbeta(); - break; - case taAlpha: - control_value=fdmex->GetAuxiliary()->Getalpha(); - break; - case taPitchTrim: - control_value=fdmex->GetFCS()->GetPitchTrimCmd(); - break; - case taElevator: - control_value=fdmex->GetFCS()->GetDeCmd(); - break; - case taRollTrim: - case taAileron: - control_value=fdmex->GetFCS()->GetDaCmd(); - break; - case taYawTrim: - case taRudder: - control_value=fdmex->GetFCS()->GetDrCmd(); - break; - case taAltAGL: - control_value=fdmex->GetPropagate()->GetDistanceAGL(); - break; - case taTheta: - control_value=fdmex->GetPropagate()->GetEuler(eTht); - break; - case taPhi: - control_value=fdmex->GetPropagate()->GetEuler(ePhi); - break; - case taGamma: - control_value=fdmex->GetAuxiliary()->GetGamma(); - break; - case taHeading: - control_value=fdmex->GetPropagate()->GetEuler(ePsi); - break; - } +void FGTrimAnalysisControl::getControl(void) { + switch(control) { + case taThrottle: control_value=fdmex->GetFCS()->GetThrottleCmd(0); break; + case taBeta: control_value=fdmex->GetAuxiliary()->Getbeta(); break; + case taAlpha: control_value=fdmex->GetAuxiliary()->Getalpha(); break; + case taPitchTrim: control_value=fdmex->GetFCS()->GetPitchTrimCmd(); break; + case taElevator: control_value=fdmex->GetFCS()->GetDeCmd(); break; + case taRollTrim: + case taAileron: control_value=fdmex->GetFCS()->GetDaCmd(); break; + case taYawTrim: + case taRudder: control_value=fdmex->GetFCS()->GetDrCmd(); break; + case taAltAGL: control_value=fdmex->GetPropagate()->GetDistanceAGL();break; + case taTheta: control_value=fdmex->GetPropagate()->GetEuler(eTht); break; + case taPhi: control_value=fdmex->GetPropagate()->GetEuler(ePhi); break; + case taGamma: control_value=fdmex->GetAuxiliary()->GetGamma();break; + case taHeading: control_value=fdmex->GetPropagate()->GetEuler(ePsi); break; + } } /*****************************************************************************/ -double FGTrimAnalysisControl::computeHmgt(void) -{ - double diff; +double FGTrimAnalysisControl::computeHmgt(void) { + double diff; - diff = fdmex->GetPropagate()->GetEuler(ePsi) - + diff = fdmex->GetPropagate()->GetEuler(ePsi) - fdmex->GetAuxiliary()->GetGroundTrack(); - if ( diff < -M_PI ) - { - return (diff + 2*M_PI); - } - else if ( diff > M_PI ) - { - return (diff - 2*M_PI); - } - else - { - return diff; - } + if( diff < -M_PI ) { + return (diff + 2*M_PI); + } else if( diff > M_PI ) { + return (diff - 2*M_PI); + } else { + return diff; + } } /*****************************************************************************/ -void FGTrimAnalysisControl::setControl(void) -{ - switch (control) - { - case taThrottle: - setThrottlesPct(); - break; - case taBeta: - fgic->SetBetaRadIC(control_value); - break; - case taAlpha: - fgic->SetAlphaRadIC(control_value); - break; - case taPitchTrim: - fdmex->GetFCS()->SetPitchTrimCmd(control_value); - break; - case taElevator: - fdmex->GetFCS()->SetDeCmd(control_value); - break; - case taRollTrim: - case taAileron: - fdmex->GetFCS()->SetDaCmd(control_value); - break; - case taYawTrim: - case taRudder: - fdmex->GetFCS()->SetDrCmd(control_value); - break; - case taAltAGL: - fgic->SetAltitudeAGLFtIC(control_value); - break; - case taTheta: - fgic->SetThetaRadIC(control_value); - break; - case taPhi: - fgic->SetPhiRadIC(control_value); - break; - case taGamma: - fgic->SetFlightPathAngleRadIC(control_value); - break; - case taHeading: - fgic->SetPsiRadIC(control_value); - break; - } +void FGTrimAnalysisControl::setControl(void) { + switch(control) { + case taThrottle: setThrottlesPct(); break; + case taBeta: fgic->SetBetaRadIC(control_value); break; + case taAlpha: fgic->SetAlphaRadIC(control_value); break; + case taPitchTrim: fdmex->GetFCS()->SetPitchTrimCmd(control_value); break; + case taElevator: fdmex->GetFCS()->SetDeCmd(control_value); break; + case taRollTrim: + case taAileron: fdmex->GetFCS()->SetDaCmd(control_value); break; + case taYawTrim: + case taRudder: fdmex->GetFCS()->SetDrCmd(control_value); break; + case taAltAGL: fgic->SetAltitudeAGLFtIC(control_value); break; + case taTheta: fgic->SetThetaRadIC(control_value); break; + case taPhi: fgic->SetPhiRadIC(control_value); break; + case taGamma: fgic->SetFlightPathAngleRadIC(control_value); break; + case taHeading: fgic->SetPsiRadIC(control_value); break; + } } @@ -367,183 +286,162 @@ void FGTrimAnalysisControl::setControl(void) // new center of rotation, pick a gear unit as a reference and use its // location vector to calculate the new height change. i.e. new altitude = // earth z component of that vector (which is in body axes ) -void FGTrimAnalysisControl::SetThetaOnGround(double ff) -{ - int center,i,ref; - - // favor an off-center unit so that the same one can be used for both - // pitch and roll. An on-center unit is used (for pitch)if that's all - // that's in contact with the ground. - i=0; - ref=-1; - center=-1; - while ( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) - { - if (fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) - { - if (fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01) - ref=i; - else - center=i; - } - i++; - } - if ((ref < 0) && (center >= 0)) - { - ref=center; - } - cout << "SetThetaOnGround ref gear: " << ref << endl; - if (ref >= 0) - { - double sp = fdmex->GetPropagate()->GetSinEuler(ePhi); - double cp = fdmex->GetPropagate()->GetCosEuler(ePhi); - double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); - double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); - double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); - double hagl = -1*lx*sin(ff) + - ly*sp*cos(ff) + - lz*cp*cos(ff); - - fgic->SetAltitudeAGLFtIC(hagl); - cout << "SetThetaOnGround new alt: " << hagl << endl; +void FGTrimAnalysisControl::SetThetaOnGround(double ff) { + int center,i,ref; + + // favor an off-center unit so that the same one can be used for both + // pitch and roll. An on-center unit is used (for pitch)if that's all + // that's in contact with the ground. + i=0; ref=-1; center=-1; + while( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) { + if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) { + if(fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01) + ref=i; + else + center=i; } - fgic->SetThetaRadIC(ff); - cout << "SetThetaOnGround new theta: " << ff << endl; + i++; + } + if((ref < 0) && (center >= 0)) { + ref=center; + } + cout << "SetThetaOnGround ref gear: " << ref << endl; + if(ref >= 0) { + double sp = fdmex->GetPropagate()->GetSinEuler(ePhi); + double cp = fdmex->GetPropagate()->GetCosEuler(ePhi); + double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); + double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); + double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); + double hagl = -1*lx*sin(ff) + + ly*sp*cos(ff) + + lz*cp*cos(ff); + + fgic->SetAltitudeAGLFtIC(hagl); + cout << "SetThetaOnGround new alt: " << hagl << endl; + } + fgic->SetThetaRadIC(ff); + cout << "SetThetaOnGround new theta: " << ff << endl; } /*****************************************************************************/ -bool FGTrimAnalysisControl::initTheta(void) -{ - int i,N; - int iForward = 0; - int iAft = 1; - double zAft,zForward,zDiff,theta; - double xAft,xForward,xDiff; - bool level; - double saveAlt; - - saveAlt=fgic->GetAltitudeAGLFtIC(); - fgic->SetAltitudeAGLFtIC(100); - - - N=fdmex->GetGroundReactions()->GetNumGearUnits(); - - //find the first wheel unit forward of the cg - //the list is short so a simple linear search is fine - for ( i=0; i<N; i++ ) - { - if (fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) > 0 ) - { - iForward=i; - break; - } +bool FGTrimAnalysisControl::initTheta(void) { + int i,N; + int iForward = 0; + int iAft = 1; + double zAft,zForward,zDiff,theta; + double xAft,xForward,xDiff; + bool level; + double saveAlt; + + saveAlt=fgic->GetAltitudeAGLFtIC(); + fgic->SetAltitudeAGLFtIC(100); + + + N=fdmex->GetGroundReactions()->GetNumGearUnits(); + + //find the first wheel unit forward of the cg + //the list is short so a simple linear search is fine + for( i=0; i<N; i++ ) { + if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) > 0 ) { + iForward=i; + break; } - //now find the first wheel unit aft of the cg - for ( i=0; i<N; i++ ) - { - if (fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) < 0 ) - { - iAft=i; - break; - } + } + //now find the first wheel unit aft of the cg + for( i=0; i<N; i++ ) { + if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) < 0 ) { + iAft=i; + break; } - - // now adjust theta till the wheels are the same distance from the ground - xAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetBodyLocation(1); - xForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetBodyLocation(1); - xDiff = xForward - xAft; + } + + // now adjust theta till the wheels are the same distance from the ground + xAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetBodyLocation(1); + xForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetBodyLocation(1); + xDiff = xForward - xAft; + zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3); + zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3); + zDiff = zForward - zAft; + level=false; + theta=fgic->GetThetaDegIC(); + while(!level && (i < 100)) { + theta+=radtodeg*atan(zDiff/xDiff); + fgic->SetThetaDegIC(theta); + fdmex->RunIC(); zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3); zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3); zDiff = zForward - zAft; - level=false; - theta=fgic->GetThetaDegIC(); - while (!level && (i < 100)) - { - theta+=radtodeg*atan(zDiff/xDiff); - fgic->SetThetaDegIC(theta); - fdmex->RunIC(); - zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3); - zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3); - zDiff = zForward - zAft; - //cout << endl << theta << " " << zDiff << endl; - //cout << "0: " << fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear() << endl; - //cout << "1: " << fdmex->GetGroundReactions()->GetGearUnit(1)->GetLocalGear() << endl; - if (fabs(zDiff ) < 0.1) - level=true; - i++; - } - //cout << i << endl; - if (debug_lvl > 0) - { - cout << " Initial Theta: " << fdmex->GetPropagate()->GetEuler(eTht)*radtodeg << endl; - cout << " Used gear unit " << iAft << " as aft and " << iForward << " as forward" << endl; - } - control_min=(theta+5)*degtorad; - control_max=(theta-5)*degtorad; - fgic->SetAltitudeAGLFtIC(saveAlt); - if (i < 100) - return true; - else - return false; + //cout << endl << theta << " " << zDiff << endl; + //cout << "0: " << fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear() << endl; + //cout << "1: " << fdmex->GetGroundReactions()->GetGearUnit(1)->GetLocalGear() << endl; + if(fabs(zDiff ) < 0.1) + level=true; + i++; + } + //cout << i << endl; + if (debug_lvl > 0) { + cout << " Initial Theta: " << fdmex->GetPropagate()->GetEuler(eTht)*radtodeg << endl; + cout << " Used gear unit " << iAft << " as aft and " << iForward << " as forward" << endl; + } + control_min=(theta+5)*degtorad; + control_max=(theta-5)*degtorad; + fgic->SetAltitudeAGLFtIC(saveAlt); + if(i < 100) + return true; + else + return false; } /*****************************************************************************/ -void FGTrimAnalysisControl::SetPhiOnGround(double ff) -{ - int i,ref; - - i=0; - ref=-1; - //must have an off-center unit here - while ( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) - { - if ( (fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) && - (fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01)) - ref=i; - i++; - } - if (ref >= 0) - { - double st = fdmex->GetPropagate()->GetSinEuler(eTht); - double ct = fdmex->GetPropagate()->GetCosEuler(eTht); - double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); - double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); - double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); - double hagl = -1*lx*st + - ly*sin(ff)*ct + - lz*cos(ff)*ct; - - fgic->SetAltitudeAGLFtIC(hagl); - } - fgic->SetPhiRadIC(ff); +void FGTrimAnalysisControl::SetPhiOnGround(double ff) { + int i,ref; + + i=0; ref=-1; + //must have an off-center unit here + while ( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) { + if ( (fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) && + (fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01)) + ref=i; + i++; + } + if (ref >= 0) { + double st = fdmex->GetPropagate()->GetSinEuler(eTht); + double ct = fdmex->GetPropagate()->GetCosEuler(eTht); + double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); + double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); + double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); + double hagl = -1*lx*st + + ly*sin(ff)*ct + + lz*cos(ff)*ct; + + fgic->SetAltitudeAGLFtIC(hagl); + } + fgic->SetPhiRadIC(ff); } /*****************************************************************************/ -void FGTrimAnalysisControl::Run(void) -{ +void FGTrimAnalysisControl::Run(void) { // ... what's going on here ?? } /*****************************************************************************/ -void FGTrimAnalysisControl::setThrottlesPct(void) -{ - double tMin,tMax; - for (unsigned i=0;i<fdmex->GetPropulsion()->GetNumEngines();i++) - { - tMin=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMin(); - tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax(); - //cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value; - fdmex->GetFCS()->SetThrottleCmd(i,tMin+control_value*(tMax-tMin)); - //cout << "setThrottlespct: " << fdmex->GetFCS()->GetThrottleCmd(i) << endl; - fdmex->RunIC(); //apply throttle change - fdmex->GetPropulsion()->GetSteadyState(); - } +void FGTrimAnalysisControl::setThrottlesPct(void) { + double tMin,tMax; + for(unsigned i=0;i<fdmex->GetPropulsion()->GetNumEngines();i++) { + tMin=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMin(); + tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax(); + //cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value; + fdmex->GetFCS()->SetThrottleCmd(i,tMin+control_value*(tMax-tMin)); + //cout << "setThrottlespct: " << fdmex->GetFCS()->GetThrottleCmd(i) << endl; + fdmex->RunIC(); //apply throttle change + fdmex->GetPropulsion()->GetSteadyState(); + } } /*****************************************************************************/ @@ -571,35 +469,27 @@ void FGTrimAnalysisControl::setThrottlesPct(void) void FGTrimAnalysisControl::Debug(int from) { - if (debug_lvl <= 0) return; - if (debug_lvl & 1 ) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl <= 0) return; + if (debug_lvl & 1 ) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGTrimAnalysisControl" << endl; - if (from == 1) cout << "Destroyed: FGTrimAnalysisControl" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGTrimAnalysisControl" << endl; + if (from == 1) cout << "Destroyed: FGTrimAnalysisControl" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/initialization/FGTrimAnalysisControl.h b/src/initialization/FGTrimAnalysisControl.h old mode 100644 new mode 100755 index ca92c5f61e920c3e6d0c0a7781abd3ffe39dbbd6..273891f7be068651e4f13db537fff416e345d096 --- a/src/initialization/FGTrimAnalysisControl.h +++ b/src/initialization/FGTrimAnalysisControl.h @@ -62,8 +62,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGInitialCondition; @@ -78,8 +77,7 @@ enum TaControl { taThrottle = 0, taPitchTrim, taRollTrim, taYawTrim, taElevator, taAileron, taRudder, taPhi, taTheta, taHeading, - taGamma, taAltAGL, taBeta, taAlpha - }; + taGamma, taAltAGL, taBeta, taAlpha}; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -95,209 +93,160 @@ CLASS DECLARATION class FGTrimAnalysisControl : public FGJSBBase { public: - /** Constructor for Trim Analysis Control class. - @param fdmex FGFDMExec pointer - @param IC pointer to initial conditions instance - @param control a Control type (enum) */ - FGTrimAnalysisControl(FGFDMExec* fdmex, - FGInitialCondition *IC, - //State state, - TaControl control ); - /// Destructor - ~FGTrimAnalysisControl(); - - /** This function iterates through a call to the FGFDMExec::RunIC() - function until the desired trimming condition falls inside a tolerance.*/ - void Run(void); - - //double GetState(void) { getState(); return state_value; } - //Accels are not settable - - /** Sets the control value - @param value - */ - inline void SetControl(double value ) - { - control_value=value; - } - - /** Gets the control value - @return value - */ - inline double GetControl(void) - { - return control_value; - } - - //inline State GetStateType(void) { return state; } - /** Return the control type - @return TaControl - */ - inline TaControl GetControlType(void) - { - return control; - } - - //inline string GetStateName(void) { return StateNames[state]; } - - /** Gets the control name - @return control name - */ - inline string GetControlName(void) - { - return control_name; - } - - /** Gets the control minimum value - @return control min value - */ - inline double GetControlMin(void) - { - return control_min; - } - - /** Gets the control maximum value - @return control nax value - */inline double GetControlMax(void) - { - return control_max; - } - - /** Set control step - @param value of control step - */ - inline void SetControlStep(double value) - { - control_step = value; - } - /** Get control step - @return value of control step - */ - inline double GetControlStep(void) - { - return control_step; - } - - /** Set control initial value - @param value of control initial value - */ - inline void SetControlInitialValue(double value) - { - control_initial_value = value; - } - - /** Get control step - @return value of control initial value - */ - inline double GetControlInitialValue(void) - { - return control_initial_value; - } - - /** Set control value to minimum - */ - inline void SetControlToMin(void) - { - control_value=control_min; - } - - /** Set control value to maximum - */ - inline void SetControlToMax(void) - { - control_value=control_max; - } - - /** Set both control limits - @param max control max - @param min control min - */ - inline void SetControlLimits(double min, double max) - { - control_min=min; - control_max=max; - } - - /** Set control tolerance - @param ff value of control tolerance - */ - inline void SetTolerance(double ff) - { - control_tolerance=ff; - } - - /** Get control tolerance - @return value of control tolerance - */ - inline double GetTolerance(void) - { - return control_tolerance; - } - - /** Set theta value on ground for trim - @param ff - */ - void SetThetaOnGround(double ff); - - /** Set phi value on ground for trim - @param ff - */ - void SetPhiOnGround(double ff); - - /** Set target state value for trim - @param target - */ - inline void SetStateTarget(double target) - { - state_target=target; - } - - /** Get target state value for trim - @return state target - */ - inline double GetStateTarget(void) - { - return state_target; - } - - /** Calculate steady state thetas value on ground - @return true if successful - */ - bool initTheta(void); + /** Constructor for Trim Analysis Control class. + @param fdmex FGFDMExec pointer + @param IC pointer to initial conditions instance + @param control a Control type (enum) */ + FGTrimAnalysisControl(FGFDMExec* fdmex, + FGInitialCondition *IC, + //State state, + TaControl control ); + /// Destructor + ~FGTrimAnalysisControl(); + + /** This function iterates through a call to the FGFDMExec::RunIC() + function until the desired trimming condition falls inside a tolerance.*/ + void Run(void); + + //double GetState(void) { getState(); return state_value; } + //Accels are not settable + + /** Sets the control value + @param value + */ + inline void SetControl(double value ) { control_value=value; } + + /** Gets the control value + @return value + */ + inline double GetControl(void) { return control_value; } + + //inline State GetStateType(void) { return state; } + /** Return the control type + @return TaControl + */ + inline TaControl GetControlType(void) { return control; } + + //inline string GetStateName(void) { return StateNames[state]; } + + /** Gets the control name + @return control name + */ + inline string GetControlName(void) { return control_name; } + + /** Gets the control minimum value + @return control min value + */ + inline double GetControlMin(void) { return control_min; } + + /** Gets the control maximum value + @return control nax value + */inline double GetControlMax(void) { return control_max; } + + /** Set control step + @param value of control step + */ + inline void SetControlStep(double value) { control_step = value; } + /** Get control step + @return value of control step + */ + inline double GetControlStep(void) { return control_step; } + + /** Set control initial value + @param value of control initial value + */ + inline void SetControlInitialValue(double value) { control_initial_value = value; } + + /** Get control step + @return value of control initial value + */ + inline double GetControlInitialValue(void) { return control_initial_value; } + + /** Set control value to minimum + */ + inline void SetControlToMin(void) { control_value=control_min; } + + /** Set control value to maximum + */ + inline void SetControlToMax(void) { control_value=control_max; } + + /** Set both control limits + @param max control max + @param min control min + */ + inline void SetControlLimits(double min, double max) { + control_min=min; + control_max=max; + } + + /** Set control tolerance + @param ff value of control tolerance + */ + inline void SetTolerance(double ff) { control_tolerance=ff;} + + /** Get control tolerance + @return value of control tolerance + */ + inline double GetTolerance(void) { return control_tolerance; } + + /** Set theta value on ground for trim + @param ff + */ + void SetThetaOnGround(double ff); + + /** Set phi value on ground for trim + @param ff + */ + void SetPhiOnGround(double ff); + + /** Set target state value for trim + @param target + */ + inline void SetStateTarget(double target) { state_target=target; } + + /** Get target state value for trim + @return state target + */ + inline double GetStateTarget(void) { return state_target; } + + /** Calculate steady state thetas value on ground + @return true if successful + */ + bool initTheta(void); private: - FGFDMExec *fdmex; - FGInitialCondition *fgic; + FGFDMExec *fdmex; + FGInitialCondition *fgic; - TaState state; - TaControl control; + TaState state; + TaControl control; - string control_name; + string control_name; - double state_target; + double state_target; - double state_value; - double control_value; + double state_value; + double control_value; - double control_min; - double control_max; + double control_min; + double control_max; - double control_initial_value; - double control_step; - double control_tolerance; + double control_initial_value; + double control_step; + double control_tolerance; - double state_convert; - double control_convert; + double state_convert; + double control_convert; - void setThrottlesPct(void); + void setThrottlesPct(void); - void getState(void); - void getControl(void); - void setControl(void); + void getState(void); + void getControl(void); + void setControl(void); - double computeHmgt(void); + double computeHmgt(void); - void Debug(int from); + void Debug(int from); }; } #endif diff --git a/src/initialization/FGTrimAxis.cpp b/src/initialization/FGTrimAxis.cpp index 5b6b7cf65c0ad1312047b6e1907f7486a362b319..e0378793fb68141b0dd5fd822b2a5db215debb2d 100644 --- a/src/initialization/FGTrimAxis.cpp +++ b/src/initialization/FGTrimAxis.cpp @@ -53,8 +53,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGTrimAxis.cpp,v 1.10 2010/07/08 11:36:28 jberndt Exp $"; static const char *IdHdr = ID_TRIMAXIS; @@ -62,284 +61,185 @@ static const char *IdHdr = ID_TRIMAXIS; /*****************************************************************************/ FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st, - Control ctrl) -{ - - fdmex=fdex; - fgic=ic; - state=st; - control=ctrl; - max_iterations=10; - control_value=0; - its_to_stable_value=0; - total_iterations=0; - total_stability_iterations=0; - state_convert=1.0; - control_convert=1.0; - state_value=0; - state_target=0; - switch (state) - { - case tUdot: - tolerance = DEFAULT_TOLERANCE; - break; - case tVdot: - tolerance = DEFAULT_TOLERANCE; - break; - case tWdot: - tolerance = DEFAULT_TOLERANCE; - break; - case tQdot: - tolerance = DEFAULT_TOLERANCE / 10; - break; - case tPdot: - tolerance = DEFAULT_TOLERANCE / 10; - break; - case tRdot: - tolerance = DEFAULT_TOLERANCE / 10; - break; - case tHmgt: - tolerance = 0.01; - break; - case tNlf: - state_target=1.0; - tolerance = 1E-5; - break; - case tAll: - break; + Control ctrl) { + + fdmex=fdex; + fgic=ic; + state=st; + control=ctrl; + max_iterations=10; + control_value=0; + its_to_stable_value=0; + total_iterations=0; + total_stability_iterations=0; + state_convert=1.0; + control_convert=1.0; + state_value=0; + state_target=0; + switch(state) { + case tUdot: tolerance = DEFAULT_TOLERANCE; break; + case tVdot: tolerance = DEFAULT_TOLERANCE; break; + case tWdot: tolerance = DEFAULT_TOLERANCE; break; + case tQdot: tolerance = DEFAULT_TOLERANCE / 10; break; + case tPdot: tolerance = DEFAULT_TOLERANCE / 10; break; + case tRdot: tolerance = DEFAULT_TOLERANCE / 10; break; + case tHmgt: tolerance = 0.01; break; + case tNlf: state_target=1.0; tolerance = 1E-5; break; + case tAll: break; + } + + solver_eps=tolerance; + switch(control) { + case tThrottle: + control_min=0; + control_max=1; + control_value=0.5; + break; + case tBeta: + control_min=-30*degtorad; + control_max=30*degtorad; + control_convert=radtodeg; + break; + case tAlpha: + control_min=fdmex->GetAerodynamics()->GetAlphaCLMin(); + control_max=fdmex->GetAerodynamics()->GetAlphaCLMax(); + if(control_max <= control_min) { + control_max=20*degtorad; + control_min=-5*degtorad; } - - solver_eps=tolerance; - switch (control) - { - case tThrottle: - control_min=0; - control_max=1; - control_value=0.5; - break; - case tBeta: - control_min=-30*degtorad; - control_max=30*degtorad; - control_convert=radtodeg; - break; - case tAlpha: - control_min=fdmex->GetAerodynamics()->GetAlphaCLMin(); - control_max=fdmex->GetAerodynamics()->GetAlphaCLMax(); - if (control_max <= control_min) - { - control_max=20*degtorad; - control_min=-5*degtorad; - } - control_value= (control_min+control_max)/2; - control_convert=radtodeg; - solver_eps=tolerance/100; - break; - case tPitchTrim: - case tElevator: - case tRollTrim: - case tAileron: - case tYawTrim: - case tRudder: - control_min=-1; - control_max=1; - state_convert=radtodeg; - solver_eps=tolerance/100; - break; - case tAltAGL: - control_min=0; - control_max=30; - control_value=fdmex->GetPropagate()->GetDistanceAGL(); - solver_eps=tolerance/100; - break; - case tTheta: - control_min=fdmex->GetPropagate()->GetEuler(eTht) - 5*degtorad; - control_max=fdmex->GetPropagate()->GetEuler(eTht) + 5*degtorad; - state_convert=radtodeg; - break; - case tPhi: - control_min=fdmex->GetPropagate()->GetEuler(ePhi) - 30*degtorad; - control_max=fdmex->GetPropagate()->GetEuler(ePhi) + 30*degtorad; - state_convert=radtodeg; - control_convert=radtodeg; - break; - case tGamma: - solver_eps=tolerance/100; - control_min=-80*degtorad; - control_max=80*degtorad; - control_convert=radtodeg; - break; - case tHeading: - control_min=fdmex->GetPropagate()->GetEuler(ePsi) - 30*degtorad; - control_max=fdmex->GetPropagate()->GetEuler(ePsi) + 30*degtorad; - state_convert=radtodeg; - break; - } - - - Debug(0); + control_value= (control_min+control_max)/2; + control_convert=radtodeg; + solver_eps=tolerance/100; + break; + case tPitchTrim: + case tElevator: + case tRollTrim: + case tAileron: + case tYawTrim: + case tRudder: + control_min=-1; + control_max=1; + state_convert=radtodeg; + solver_eps=tolerance/100; + break; + case tAltAGL: + control_min=0; + control_max=30; + control_value=fdmex->GetPropagate()->GetDistanceAGL(); + solver_eps=tolerance/100; + break; + case tTheta: + control_min=fdmex->GetPropagate()->GetEuler(eTht) - 5*degtorad; + control_max=fdmex->GetPropagate()->GetEuler(eTht) + 5*degtorad; + state_convert=radtodeg; + break; + case tPhi: + control_min=fdmex->GetPropagate()->GetEuler(ePhi) - 30*degtorad; + control_max=fdmex->GetPropagate()->GetEuler(ePhi) + 30*degtorad; + state_convert=radtodeg; + control_convert=radtodeg; + break; + case tGamma: + solver_eps=tolerance/100; + control_min=-80*degtorad; + control_max=80*degtorad; + control_convert=radtodeg; + break; + case tHeading: + control_min=fdmex->GetPropagate()->GetEuler(ePsi) - 30*degtorad; + control_max=fdmex->GetPropagate()->GetEuler(ePsi) + 30*degtorad; + state_convert=radtodeg; + break; + } + + + Debug(0); } /*****************************************************************************/ FGTrimAxis::~FGTrimAxis(void) { - Debug(1); + Debug(1); } /*****************************************************************************/ -void FGTrimAxis::getState(void) -{ - switch (state) - { - case tUdot: - state_value=fdmex->GetPropagate()->GetUVWdot(1)-state_target; - break; - case tVdot: - state_value=fdmex->GetPropagate()->GetUVWdot(2)-state_target; - break; - case tWdot: - state_value=fdmex->GetPropagate()->GetUVWdot(3)-state_target; - break; - case tQdot: - state_value=fdmex->GetPropagate()->GetPQRdot(2)-state_target; - break; - case tPdot: - state_value=fdmex->GetPropagate()->GetPQRdot(1)-state_target; - break; - case tRdot: - state_value=fdmex->GetPropagate()->GetPQRdot(3)-state_target; - break; - case tHmgt: - state_value=computeHmgt()-state_target; - break; - case tNlf: - state_value=fdmex->GetAircraft()->GetNlf()-state_target; - break; - case tAll: - break; - } +void FGTrimAxis::getState(void) { + switch(state) { + case tUdot: state_value=fdmex->GetPropagate()->GetUVWdot(1)-state_target; break; + case tVdot: state_value=fdmex->GetPropagate()->GetUVWdot(2)-state_target; break; + case tWdot: state_value=fdmex->GetPropagate()->GetUVWdot(3)-state_target; break; + case tQdot: state_value=fdmex->GetPropagate()->GetPQRdot(2)-state_target;break; + case tPdot: state_value=fdmex->GetPropagate()->GetPQRdot(1)-state_target; break; + case tRdot: state_value=fdmex->GetPropagate()->GetPQRdot(3)-state_target; break; + case tHmgt: state_value=computeHmgt()-state_target; break; + case tNlf: state_value=fdmex->GetAircraft()->GetNlf()-state_target; break; + case tAll: break; + } } /*****************************************************************************/ //States are not settable -void FGTrimAxis::getControl(void) -{ - switch (control) - { - case tThrottle: - control_value=fdmex->GetFCS()->GetThrottleCmd(0); - break; - case tBeta: - control_value=fdmex->GetAuxiliary()->Getbeta(); - break; - case tAlpha: - control_value=fdmex->GetAuxiliary()->Getalpha(); - break; - case tPitchTrim: - control_value=fdmex->GetFCS() -> GetPitchTrimCmd(); - break; - case tElevator: - control_value=fdmex->GetFCS() -> GetDeCmd(); - break; - case tRollTrim: - case tAileron: - control_value=fdmex->GetFCS() -> GetDaCmd(); - break; - case tYawTrim: - case tRudder: - control_value=fdmex->GetFCS() -> GetDrCmd(); - break; - case tAltAGL: - control_value=fdmex->GetPropagate()->GetDistanceAGL(); - break; - case tTheta: - control_value=fdmex->GetPropagate()->GetEuler(eTht); - break; - case tPhi: - control_value=fdmex->GetPropagate()->GetEuler(ePhi); - break; - case tGamma: - control_value=fdmex->GetAuxiliary()->GetGamma(); - break; - case tHeading: - control_value=fdmex->GetPropagate()->GetEuler(ePsi); - break; - } +void FGTrimAxis::getControl(void) { + switch(control) { + case tThrottle: control_value=fdmex->GetFCS()->GetThrottleCmd(0); break; + case tBeta: control_value=fdmex->GetAuxiliary()->Getbeta(); break; + case tAlpha: control_value=fdmex->GetAuxiliary()->Getalpha(); break; + case tPitchTrim: control_value=fdmex->GetFCS() -> GetPitchTrimCmd(); break; + case tElevator: control_value=fdmex->GetFCS() -> GetDeCmd(); break; + case tRollTrim: + case tAileron: control_value=fdmex->GetFCS() -> GetDaCmd(); break; + case tYawTrim: + case tRudder: control_value=fdmex->GetFCS() -> GetDrCmd(); break; + case tAltAGL: control_value=fdmex->GetPropagate()->GetDistanceAGL();break; + case tTheta: control_value=fdmex->GetPropagate()->GetEuler(eTht); break; + case tPhi: control_value=fdmex->GetPropagate()->GetEuler(ePhi); break; + case tGamma: control_value=fdmex->GetAuxiliary()->GetGamma();break; + case tHeading: control_value=fdmex->GetPropagate()->GetEuler(ePsi); break; + } } /*****************************************************************************/ -double FGTrimAxis::computeHmgt(void) -{ - double diff; +double FGTrimAxis::computeHmgt(void) { + double diff; - diff = fdmex->GetPropagate()->GetEuler(ePsi) - + diff = fdmex->GetPropagate()->GetEuler(ePsi) - fdmex->GetAuxiliary()->GetGroundTrack(); - if ( diff < -M_PI ) - { - return (diff + 2*M_PI); - } - else if ( diff > M_PI ) - { - return (diff - 2*M_PI); - } - else - { - return diff; - } + if( diff < -M_PI ) { + return (diff + 2*M_PI); + } else if( diff > M_PI ) { + return (diff - 2*M_PI); + } else { + return diff; + } } /*****************************************************************************/ -void FGTrimAxis::setControl(void) -{ - switch (control) - { - case tThrottle: - setThrottlesPct(); - break; - case tBeta: - fgic->SetBetaRadIC(control_value); - break; - case tAlpha: - fgic->SetAlphaRadIC(control_value); - break; - case tPitchTrim: - fdmex->GetFCS()->SetPitchTrimCmd(control_value); - break; - case tElevator: - fdmex->GetFCS()->SetDeCmd(control_value); - break; - case tRollTrim: - case tAileron: - fdmex->GetFCS()->SetDaCmd(control_value); - break; - case tYawTrim: - case tRudder: - fdmex->GetFCS()->SetDrCmd(control_value); - break; - case tAltAGL: - fgic->SetAltitudeAGLFtIC(control_value); - break; - case tTheta: - fgic->SetThetaRadIC(control_value); - break; - case tPhi: - fgic->SetPhiRadIC(control_value); - break; - case tGamma: - fgic->SetFlightPathAngleRadIC(control_value); - break; - case tHeading: - fgic->SetPsiRadIC(control_value); - break; - } +void FGTrimAxis::setControl(void) { + switch(control) { + case tThrottle: setThrottlesPct(); break; + case tBeta: fgic->SetBetaRadIC(control_value); break; + case tAlpha: fgic->SetAlphaRadIC(control_value); break; + case tPitchTrim: fdmex->GetFCS()->SetPitchTrimCmd(control_value); break; + case tElevator: fdmex->GetFCS()->SetDeCmd(control_value); break; + case tRollTrim: + case tAileron: fdmex->GetFCS()->SetDaCmd(control_value); break; + case tYawTrim: + case tRudder: fdmex->GetFCS()->SetDrCmd(control_value); break; + case tAltAGL: fgic->SetAltitudeAGLFtIC(control_value); break; + case tTheta: fgic->SetThetaRadIC(control_value); break; + case tPhi: fgic->SetPhiRadIC(control_value); break; + case tGamma: fgic->SetFlightPathAngleRadIC(control_value); break; + case tHeading: fgic->SetPsiRadIC(control_value); break; + } } @@ -354,239 +254,213 @@ void FGTrimAxis::setControl(void) // new center of rotation, pick a gear unit as a reference and use its // location vector to calculate the new height change. i.e. new altitude = // earth z component of that vector (which is in body axes ) -void FGTrimAxis::SetThetaOnGround(double ff) -{ - int center,i,ref; - - // favor an off-center unit so that the same one can be used for both - // pitch and roll. An on-center unit is used (for pitch)if that's all - // that's in contact with the ground. - i=0; - ref=-1; - center=-1; - while ( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) - { - if (fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) - { - if (fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01) - ref=i; - else - center=i; - } - i++; +void FGTrimAxis::SetThetaOnGround(double ff) { + int center,i,ref; + + // favor an off-center unit so that the same one can be used for both + // pitch and roll. An on-center unit is used (for pitch)if that's all + // that's in contact with the ground. + i=0; ref=-1; center=-1; + while( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) { + if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) { + if(fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01) + ref=i; + else + center=i; } - if ((ref < 0) && (center >= 0)) - { - ref=center; - } - cout << "SetThetaOnGround ref gear: " << ref << endl; - if (ref >= 0) - { - double sp = fdmex->GetPropagate()->GetSinEuler(ePhi); - double cp = fdmex->GetPropagate()->GetCosEuler(ePhi); - double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); - double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); - double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); - double hagl = -1*lx*sin(ff) + - ly*sp*cos(ff) + - lz*cp*cos(ff); - - fgic->SetAltitudeAGLFtIC(hagl); - cout << "SetThetaOnGround new alt: " << hagl << endl; - } - fgic->SetThetaRadIC(ff); - cout << "SetThetaOnGround new theta: " << ff << endl; + i++; + } + if((ref < 0) && (center >= 0)) { + ref=center; + } + cout << "SetThetaOnGround ref gear: " << ref << endl; + if(ref >= 0) { + double sp = fdmex->GetPropagate()->GetSinEuler(ePhi); + double cp = fdmex->GetPropagate()->GetCosEuler(ePhi); + double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); + double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); + double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); + double hagl = -1*lx*sin(ff) + + ly*sp*cos(ff) + + lz*cp*cos(ff); + + fgic->SetAltitudeAGLFtIC(hagl); + cout << "SetThetaOnGround new alt: " << hagl << endl; + } + fgic->SetThetaRadIC(ff); + cout << "SetThetaOnGround new theta: " << ff << endl; } /*****************************************************************************/ -bool FGTrimAxis::initTheta(void) -{ - int i,N; - int iForward = 0; - int iAft = 1; - double zAft,zForward,zDiff,theta; - double xAft,xForward,xDiff; - bool level; - double saveAlt; - - saveAlt=fgic->GetAltitudeAGLFtIC(); - fgic->SetAltitudeAGLFtIC(100); - - - N=fdmex->GetGroundReactions()->GetNumGearUnits(); - - //find the first wheel unit forward of the cg - //the list is short so a simple linear search is fine - for ( i=0; i<N; i++ ) - { - if (fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) > 0 ) - { - iForward=i; - break; - } +bool FGTrimAxis::initTheta(void) { + int i,N; + int iForward = 0; + int iAft = 1; + double zAft,zForward,zDiff,theta; + double xAft,xForward,xDiff; + bool level; + double saveAlt; + + saveAlt=fgic->GetAltitudeAGLFtIC(); + fgic->SetAltitudeAGLFtIC(100); + + + N=fdmex->GetGroundReactions()->GetNumGearUnits(); + + //find the first wheel unit forward of the cg + //the list is short so a simple linear search is fine + for( i=0; i<N; i++ ) { + if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) > 0 ) { + iForward=i; + break; } - //now find the first wheel unit aft of the cg - for ( i=0; i<N; i++ ) - { - if (fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) < 0 ) - { - iAft=i; - break; - } + } + //now find the first wheel unit aft of the cg + for( i=0; i<N; i++ ) { + if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) < 0 ) { + iAft=i; + break; } - - // now adjust theta till the wheels are the same distance from the ground - xAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetBodyLocation(1); - xForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetBodyLocation(1); - xDiff = xForward - xAft; + } + + // now adjust theta till the wheels are the same distance from the ground + xAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetBodyLocation(1); + xForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetBodyLocation(1); + xDiff = xForward - xAft; + zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3); + zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3); + zDiff = zForward - zAft; + level=false; + theta=fgic->GetThetaDegIC(); + while(!level && (i < 100)) { + theta+=radtodeg*atan(zDiff/xDiff); + fgic->SetThetaDegIC(theta); + fdmex->RunIC(); zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3); zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3); zDiff = zForward - zAft; - level=false; - theta=fgic->GetThetaDegIC(); - while (!level && (i < 100)) - { - theta+=radtodeg*atan(zDiff/xDiff); - fgic->SetThetaDegIC(theta); - fdmex->RunIC(); - zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3); - zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3); - zDiff = zForward - zAft; - //cout << endl << theta << " " << zDiff << endl; - //cout << "0: " << fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear() << endl; - //cout << "1: " << fdmex->GetGroundReactions()->GetGearUnit(1)->GetLocalGear() << endl; - if (fabs(zDiff ) < 0.1) - level=true; - i++; - } - //cout << i << endl; - if (debug_lvl > 0) - { - cout << " Initial Theta: " << fdmex->GetPropagate()->GetEuler(eTht)*radtodeg << endl; - cout << " Used gear unit " << iAft << " as aft and " << iForward << " as forward" << endl; - } - control_min=(theta+5)*degtorad; - control_max=(theta-5)*degtorad; - fgic->SetAltitudeAGLFtIC(saveAlt); - if (i < 100) - return true; - else - return false; + //cout << endl << theta << " " << zDiff << endl; + //cout << "0: " << fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear() << endl; + //cout << "1: " << fdmex->GetGroundReactions()->GetGearUnit(1)->GetLocalGear() << endl; + if(fabs(zDiff ) < 0.1) + level=true; + i++; + } + //cout << i << endl; + if (debug_lvl > 0) { + cout << " Initial Theta: " << fdmex->GetPropagate()->GetEuler(eTht)*radtodeg << endl; + cout << " Used gear unit " << iAft << " as aft and " << iForward << " as forward" << endl; + } + control_min=(theta+5)*degtorad; + control_max=(theta-5)*degtorad; + fgic->SetAltitudeAGLFtIC(saveAlt); + if(i < 100) + return true; + else + return false; } /*****************************************************************************/ -void FGTrimAxis::SetPhiOnGround(double ff) -{ - int i,ref; - - i=0; - ref=-1; - //must have an off-center unit here - while ( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) - { - if ( (fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) && - (fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01)) - ref=i; - i++; - } - if (ref >= 0) - { - double st = fdmex->GetPropagate()->GetSinEuler(eTht); - double ct = fdmex->GetPropagate()->GetCosEuler(eTht); - double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); - double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); - double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); - double hagl = -1*lx*st + - ly*sin(ff)*ct + - lz*cos(ff)*ct; - - fgic->SetAltitudeAGLFtIC(hagl); - } - fgic->SetPhiRadIC(ff); +void FGTrimAxis::SetPhiOnGround(double ff) { + int i,ref; + + i=0; ref=-1; + //must have an off-center unit here + while ( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) { + if ( (fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) && + (fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01)) + ref=i; + i++; + } + if (ref >= 0) { + double st = fdmex->GetPropagate()->GetSinEuler(eTht); + double ct = fdmex->GetPropagate()->GetCosEuler(eTht); + double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); + double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); + double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); + double hagl = -1*lx*st + + ly*sin(ff)*ct + + lz*cos(ff)*ct; + + fgic->SetAltitudeAGLFtIC(hagl); + } + fgic->SetPhiRadIC(ff); } /*****************************************************************************/ -void FGTrimAxis::Run(void) -{ - - double last_state_value; - int i; - setControl(); - //cout << "FGTrimAxis::Run: " << control_value << endl; - i=0; - bool stable=false; - while (!stable) - { - i++; - last_state_value=state_value; - fdmex->RunIC(); - getState(); - if (i > 1) - { - if ((fabs(last_state_value - state_value) < tolerance) || (i >= 100) ) - stable=true; - } +void FGTrimAxis::Run(void) { + + double last_state_value; + int i; + setControl(); + //cout << "FGTrimAxis::Run: " << control_value << endl; + i=0; + bool stable=false; + while(!stable) { + i++; + last_state_value=state_value; + fdmex->RunIC(); + getState(); + if(i > 1) { + if((fabs(last_state_value - state_value) < tolerance) || (i >= 100) ) + stable=true; } + } - its_to_stable_value=i; - total_stability_iterations+=its_to_stable_value; - total_iterations++; + its_to_stable_value=i; + total_stability_iterations+=its_to_stable_value; + total_iterations++; } /*****************************************************************************/ -void FGTrimAxis::setThrottlesPct(void) -{ - double tMin,tMax; - for (unsigned i=0;i<fdmex->GetPropulsion()->GetNumEngines();i++) - { - tMin=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMin(); - tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax(); - //cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value; - fdmex->GetFCS()->SetThrottleCmd(i,tMin+control_value*(tMax-tMin)); - //cout << "setThrottlespct: " << fdmex->GetFCS()->GetThrottleCmd(i) << endl; - fdmex->RunIC(); //apply throttle change - fdmex->GetPropulsion()->GetSteadyState(); - } +void FGTrimAxis::setThrottlesPct(void) { + double tMin,tMax; + for(unsigned i=0;i<fdmex->GetPropulsion()->GetNumEngines();i++) { + tMin=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMin(); + tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax(); + //cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value; + fdmex->GetFCS()->SetThrottleCmd(i,tMin+control_value*(tMax-tMin)); + //cout << "setThrottlespct: " << fdmex->GetFCS()->GetThrottleCmd(i) << endl; + fdmex->RunIC(); //apply throttle change + fdmex->GetPropulsion()->GetSteadyState(); + } } /*****************************************************************************/ -void FGTrimAxis::AxisReport(void) -{ - // Save original cout format characteristics - std::ios_base::fmtflags originalFormat = cout.flags(); - std::streamsize originalPrecision = cout.precision(); - std::streamsize originalWidth = cout.width(); - cout << " " << setw(20) << GetControlName() << ": "; - cout << setw(6) << setprecision(2) << GetControl()*control_convert << ' '; - cout << setw(5) << GetStateName() << ": "; - cout << setw(9) << setprecision(2) << scientific << GetState()+state_target; - cout << " Tolerance: " << setw(3) << setprecision(0) << scientific << GetTolerance(); - - if ( fabs(GetState()+state_target) < fabs(GetTolerance()) ) - cout << " Passed" << endl; - else - cout << " Failed" << endl; - // Restore original cout format characteristics - cout.flags(originalFormat); - cout.precision(originalPrecision); - cout.width(originalWidth); +void FGTrimAxis::AxisReport(void) { + // Save original cout format characteristics + std::ios_base::fmtflags originalFormat = cout.flags(); + std::streamsize originalPrecision = cout.precision(); + std::streamsize originalWidth = cout.width(); + cout << " " << setw(20) << GetControlName() << ": "; + cout << setw(6) << setprecision(2) << GetControl()*control_convert << ' '; + cout << setw(5) << GetStateName() << ": "; + cout << setw(9) << setprecision(2) << scientific << GetState()+state_target; + cout << " Tolerance: " << setw(3) << setprecision(0) << scientific << GetTolerance(); + + if( fabs(GetState()+state_target) < fabs(GetTolerance()) ) + cout << " Passed" << endl; + else + cout << " Failed" << endl; + // Restore original cout format characteristics + cout.flags(originalFormat); + cout.precision(originalPrecision); + cout.width(originalWidth); } /*****************************************************************************/ -double FGTrimAxis::GetAvgStability( void ) -{ - if (total_iterations > 0) - { - return double(total_stability_iterations)/double(total_iterations); - } - return 0; +double FGTrimAxis::GetAvgStability( void ) { + if(total_iterations > 0) { + return double(total_stability_iterations)/double(total_iterations); + } + return 0; } /*****************************************************************************/ @@ -611,35 +485,27 @@ double FGTrimAxis::GetAvgStability( void ) void FGTrimAxis::Debug(int from) { - if (debug_lvl <= 0) return; - if (debug_lvl & 1 ) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl <= 0) return; + if (debug_lvl & 1 ) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGTrimAxis" << endl; - if (from == 1) cout << "Destroyed: FGTrimAxis" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGTrimAxis" << endl; + if (from == 1) cout << "Destroyed: FGTrimAxis" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/initialization/FGTrimAxis.h b/src/initialization/FGTrimAxis.h index ac30756021d4d72c0af4a2256026b17624095857..afd516782e4f225984b37e0a51e2f5e1d80b8c6b 100644 --- a/src/initialization/FGTrimAxis.h +++ b/src/initialization/FGTrimAxis.h @@ -1,32 +1,32 @@ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + Header: FGTrimAxis.h Author: Tony Peden Date started: 7/3/00 - + ------------- Copyright (C) 1999 Anthony K. Peden (apeden@earthlink.net) ------------- - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser 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. - + Further information about the GNU Lesser General Public License can also be found on the world wide web at http://www.gnu.org. - + HISTORY -------------------------------------------------------------------------------- 7/3/00 TP Created - + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SENTRY %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ @@ -48,7 +48,7 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_TRIMAXIS "$Id: FGTrimAxis.h,v 1.4 2006/10/01 22:47:47 jberndt Exp $" +#define ID_TRIMAXIS "$Id: FGTrimAxis.h,v 1.5 2010/09/07 18:36:29 andgi Exp $" #define DEFAULT_TOLERANCE 0.001 @@ -56,16 +56,15 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { -const string StateNames[10]= { "all","udot","vdot","wdot","qdot","pdot","rdot", - "hmgt","nlf" - }; -const string ControlNames[14]= { "Throttle","Sideslip","Angle of Attack", +const string StateNames[] = { "all","udot","vdot","wdot","qdot","pdot","rdot", + "hmgt","nlf" + }; +const string ControlNames[] = { "Throttle","Sideslip","Angle of Attack", "Elevator","Ailerons","Rudder", "Altitude AGL", "Pitch Angle", - "Roll Angle", "Flight Path Angle", + "Roll Angle", "Flight Path Angle", "Pitch Trim", "Roll Trim", "Yaw Trim", "Heading" }; @@ -85,181 +84,111 @@ CLASS DECLARATION enum State { tAll,tUdot,tVdot,tWdot,tQdot,tPdot,tRdot,tHmgt,tNlf }; enum Control { tThrottle, tBeta, tAlpha, tElevator, tAileron, tRudder, tAltAGL, - tTheta, tPhi, tGamma, tPitchTrim, tRollTrim, tYawTrim, tHeading - }; + tTheta, tPhi, tGamma, tPitchTrim, tRollTrim, tYawTrim, tHeading }; class FGTrimAxis : public FGJSBBase { public: - /** Constructor for Trim Axis class. - @param fdmex FGFDMExec pointer - @param IC pointer to initial conditions instance - @param state a State type (enum) - @param control a Control type (enum) */ - FGTrimAxis(FGFDMExec* fdmex, - FGInitialCondition *IC, - State state, - Control control ); - /// Destructor - ~FGTrimAxis(); - - /** This function iterates through a call to the FGFDMExec::RunIC() - function until the desired trimming condition falls inside a tolerance.*/ - void Run(void); - - double GetState(void) - { - getState(); - return state_value; - } - //Accels are not settable - inline void SetControl(double value ) - { - control_value=value; - } - inline double GetControl(void) - { - return control_value; - } - - inline State GetStateType(void) - { - return state; - } - inline Control GetControlType(void) - { - return control; - } - - inline string GetStateName(void) - { - return StateNames[state]; - } - inline string GetControlName(void) - { - return ControlNames[control]; - } - - inline double GetControlMin(void) - { - return control_min; - } - inline double GetControlMax(void) - { - return control_max; - } - - inline void SetControlToMin(void) - { - control_value=control_min; - } - inline void SetControlToMax(void) - { - control_value=control_max; - } - - inline void SetControlLimits(double min, double max) - { - control_min=min; - control_max=max; - } - - inline void SetTolerance(double ff) - { - tolerance=ff; - } - inline double GetTolerance(void) - { - return tolerance; - } - - inline double GetSolverEps(void) - { - return solver_eps; - } - inline void SetSolverEps(double ff) - { - solver_eps=ff; - } - - inline int GetIterationLimit(void) - { - return max_iterations; - } - inline void SetIterationLimit(int ii) - { - max_iterations=ii; - } - - inline int GetStability(void) - { - return its_to_stable_value; - } - inline int GetRunCount(void) - { - return total_stability_iterations; - } - double GetAvgStability( void ); - - void SetThetaOnGround(double ff); - void SetPhiOnGround(double ff); - - inline void SetStateTarget(double target) - { - state_target=target; - } - inline double GetStateTarget(void) - { - return state_target; - } - - bool initTheta(void); - - void AxisReport(void); - - bool InTolerance(void) - { - getState(); - return (fabs(state_value) <= tolerance); - } + /** Constructor for Trim Axis class. + @param fdmex FGFDMExec pointer + @param IC pointer to initial conditions instance + @param state a State type (enum) + @param control a Control type (enum) */ + FGTrimAxis(FGFDMExec* fdmex, + FGInitialCondition *IC, + State state, + Control control ); + /// Destructor + ~FGTrimAxis(); + + /** This function iterates through a call to the FGFDMExec::RunIC() + function until the desired trimming condition falls inside a tolerance.*/ + void Run(void); + + double GetState(void) { getState(); return state_value; } + //Accels are not settable + inline void SetControl(double value ) { control_value=value; } + inline double GetControl(void) { return control_value; } + + inline State GetStateType(void) { return state; } + inline Control GetControlType(void) { return control; } + + inline string GetStateName(void) { return StateNames[state]; } + inline string GetControlName(void) { return ControlNames[control]; } + + inline double GetControlMin(void) { return control_min; } + inline double GetControlMax(void) { return control_max; } + + inline void SetControlToMin(void) { control_value=control_min; } + inline void SetControlToMax(void) { control_value=control_max; } + + inline void SetControlLimits(double min, double max) { + control_min=min; + control_max=max; + } + + inline void SetTolerance(double ff) { tolerance=ff;} + inline double GetTolerance(void) { return tolerance; } + + inline double GetSolverEps(void) { return solver_eps; } + inline void SetSolverEps(double ff) { solver_eps=ff; } + + inline int GetIterationLimit(void) { return max_iterations; } + inline void SetIterationLimit(int ii) { max_iterations=ii; } + + inline int GetStability(void) { return its_to_stable_value; } + inline int GetRunCount(void) { return total_stability_iterations; } + double GetAvgStability( void ); + + void SetThetaOnGround(double ff); + void SetPhiOnGround(double ff); + + inline void SetStateTarget(double target) { state_target=target; } + inline double GetStateTarget(void) { return state_target; } + + bool initTheta(void); + + void AxisReport(void); + + bool InTolerance(void) { getState(); return (fabs(state_value) <= tolerance); } private: - FGFDMExec *fdmex; - FGInitialCondition *fgic; - - State state; - Control control; - - double state_target; - - double state_value; - double control_value; - - double control_min; - double control_max; + FGFDMExec *fdmex; + FGInitialCondition *fgic; - double tolerance; + State state; + Control control; + + double state_target; + + double state_value; + double control_value; - double solver_eps; + double control_min; + double control_max; - double state_convert; - double control_convert; + double tolerance; - int max_iterations; + double solver_eps; - int its_to_stable_value; - int total_stability_iterations; - int total_iterations; + double state_convert; + double control_convert; - void setThrottlesPct(void); + int max_iterations; - void getState(void); - void getControl(void); - void setControl(void); + int its_to_stable_value; + int total_stability_iterations; + int total_iterations; - double computeHmgt(void); + void setThrottlesPct(void); - void Debug(int from); + void getState(void); + void getControl(void); + void setControl(void); + + double computeHmgt(void); + + void Debug(int from); }; } #endif diff --git a/src/initialization/FGTrimmer.cpp b/src/initialization/FGTrimmer.cpp index 091e10d5523378a2e605dea7c84a1f4b4e168380..e77932f963f8a5904b97b7da99431bdae44a7685 100644 --- a/src/initialization/FGTrimmer.cpp +++ b/src/initialization/FGTrimmer.cpp @@ -69,8 +69,8 @@ void FGTrimmer::constrain(const std::vector<double> & v) a = 1 - gc*tAlpha*sBeta; b = sGam/cBeta; double c = 1 + gc*gc*cBeta*cBeta; - phi = atan((gc*cBeta*(a-b*b)+ - b*tAlpha*sqrt(c*(1-b*b)+gc*gc*sBeta*sBeta))/ + phi = atan((gc*cBeta*((a-b*b)+ + b*tAlpha*sqrt(c*(1-b*b)+gc*gc*sBeta*sBeta)))/ (cAlpha*(a*a-b*b*(1+c*tAlpha*tAlpha)))); // turn rates diff --git a/src/input_output/FGGroundCallback.cpp b/src/input_output/FGGroundCallback.cpp index c4bc013524d1d86d798aa49d7ed437a135730f65..bf1cfb1b592c5eaa9fc46b5864774e0ead9dd135 100644 --- a/src/input_output/FGGroundCallback.cpp +++ b/src/input_output/FGGroundCallback.cpp @@ -35,21 +35,20 @@ SENTRY #include "math/FGLocation.h" #include "FGGroundCallback.h" -namespace JSBSim -{ +namespace JSBSim { //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGGroundCallback::FGGroundCallback() { - mReferenceRadius = 20925650.0; // Sea level radius + mReferenceRadius = 20925650.0; // Sea level radius } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGGroundCallback::FGGroundCallback(double ReferenceRadius) { - mReferenceRadius = ReferenceRadius; + mReferenceRadius = ReferenceRadius; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -62,7 +61,7 @@ FGGroundCallback::~FGGroundCallback() double FGGroundCallback::GetAltitude(const FGLocation& loc) const { - return loc.GetRadius() - mReferenceRadius; + return loc.GetRadius() - mReferenceRadius; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -71,13 +70,13 @@ double FGGroundCallback::GetAGLevel(double t, const FGLocation& loc, FGLocation& contact, FGColumnVector3& normal, FGColumnVector3& vel) const { - vel = FGColumnVector3(0.0, 0.0, 0.0); - normal = FGColumnVector3(loc).Normalize(); - double loc_radius = loc.GetRadius(); // Get the radius of the given location - // (e.g. the CG) - double agl = loc_radius - mReferenceRadius; - contact = (mReferenceRadius/loc_radius)*FGColumnVector3(loc); - return agl; + vel = FGColumnVector3(0.0, 0.0, 0.0); + normal = FGColumnVector3(loc).Normalize(); + double loc_radius = loc.GetRadius(); // Get the radius of the given location + // (e.g. the CG) + double agl = loc_radius - mReferenceRadius; + contact = (mReferenceRadius/loc_radius)*FGColumnVector3(loc); + return agl; } } diff --git a/src/input_output/FGGroundCallback.h b/src/input_output/FGGroundCallback.h index eafc537fc0a588fce4fa1805afd7c93ec72c2ba6..63955a4d07674817ad3dc30db01c4cac282264f6 100644 --- a/src/input_output/FGGroundCallback.h +++ b/src/input_output/FGGroundCallback.h @@ -47,8 +47,7 @@ DEFINITIONS #define ID_GROUNDCALLBACK "$Id: FGGroundCallback.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $" -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -70,34 +69,28 @@ CLASS DECLARATION class FGGroundCallback : public FGJSBBase { public: - /** Default constructor. - Within this constructor, the reference radius is set to the WGS84 equatorial - radius. This constructor should really not be called, instead relying on the - constructor that takes reference radius as an argument. */ - FGGroundCallback(); - - /** Constructor - This constructor accepts the reference radius in feet. This is the preferred - constructor. */ - FGGroundCallback(double ReferenceRadius); - virtual ~FGGroundCallback(); - - /** Compute the altitude above sealevel. */ - virtual double GetAltitude(const FGLocation& l) const; - /** Compute the altitude above ground. Defaults to sealevel altitude. */ - virtual double GetAGLevel(double t, const FGLocation& l, FGLocation& cont, - FGColumnVector3& n, FGColumnVector3& v) const; - virtual void SetTerrainGeoCentRadius(double radius) - { - mReferenceRadius = radius; - } - virtual double GetTerrainGeoCentRadius(void) const - { - return mReferenceRadius; - } + /** Default constructor. + Within this constructor, the reference radius is set to the WGS84 equatorial + radius. This constructor should really not be called, instead relying on the + constructor that takes reference radius as an argument. */ + FGGroundCallback(); + + /** Constructor + This constructor accepts the reference radius in feet. This is the preferred + constructor. */ + FGGroundCallback(double ReferenceRadius); + virtual ~FGGroundCallback(); + + /** Compute the altitude above sealevel. */ + virtual double GetAltitude(const FGLocation& l) const; + /** Compute the altitude above ground. Defaults to sealevel altitude. */ + virtual double GetAGLevel(double t, const FGLocation& l, FGLocation& cont, + FGColumnVector3& n, FGColumnVector3& v) const; + virtual void SetTerrainGeoCentRadius(double radius) {mReferenceRadius = radius;} + virtual double GetTerrainGeoCentRadius(void) const {return mReferenceRadius;} private: - /// Reference radius. - double mReferenceRadius; + /// Reference radius. + double mReferenceRadius; }; } diff --git a/src/input_output/FGPropertyManager.cpp b/src/input_output/FGPropertyManager.cpp old mode 100644 new mode 100755 index 04936abab72b67d4e97363b165ba19f89c86ea34..11e566965259e1b58ec854de18892233a718b209 --- a/src/input_output/FGPropertyManager.cpp +++ b/src/input_output/FGPropertyManager.cpp @@ -46,28 +46,25 @@ COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ -namespace JSBSim -{ +namespace JSBSim { bool FGPropertyManager::suppress_warning = true; //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -string FGPropertyManager::mkPropertyName(string name, bool lowercase) -{ - - /* do this two pass to avoid problems with characters getting skipped - because the index changed */ - unsigned i; - for (i=0;i<name.length();i++) - { - if ( lowercase && isupper(name[i]) ) - name[i]=tolower(name[i]); - else if ( isspace(name[i]) ) - name[i]='-'; - } - - return name; +string FGPropertyManager::mkPropertyName(string name, bool lowercase) { + + /* do this two pass to avoid problems with characters getting skipped + because the index changed */ + unsigned i; + for(i=0;i<name.length();i++) { + if( lowercase && isupper(name[i]) ) + name[i]=tolower(name[i]); + else if( isspace(name[i]) ) + name[i]='-'; + } + + return name; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -75,12 +72,11 @@ string FGPropertyManager::mkPropertyName(string name, bool lowercase) FGPropertyManager* FGPropertyManager::GetNode (const string &path, bool create) { - SGPropertyNode* node=this->getNode(path.c_str(), create); - if (node == 0 && !suppress_warning) - { - cerr << "FGPropertyManager::GetNode() No node found for " << path << endl; - } - return (FGPropertyManager*)node; + SGPropertyNode* node=this->getNode(path.c_str(), create); + if (node == 0 && !suppress_warning) { + cerr << "FGPropertyManager::GetNode() No node found for " << path << endl; + } + return (FGPropertyManager*)node; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -96,64 +92,60 @@ FGPropertyManager::GetNode (const string &relpath, int index, bool create) bool FGPropertyManager::HasNode (const string &path) { - // Checking if a node exists shouldn't write a warning if it doesn't exist - suppress_warning = true; - bool has_node = (GetNode(path, false) != 0); - suppress_warning = false; - return has_node; + // Checking if a node exists shouldn't write a warning if it doesn't exist + suppress_warning = true; + bool has_node = (GetNode(path, false) != 0); + suppress_warning = false; + return has_node; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGPropertyManager::GetName( void ) { - return string( getName() ); + return string( getName() ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGPropertyManager::GetPrintableName( void ) { - string temp_string(getName()); - size_t initial_location=0; - size_t found_location; - - found_location = temp_string.rfind("/"); - if (found_location != string::npos) - temp_string = temp_string.substr(found_location); - + string temp_string(getName()); + size_t initial_location=0; + size_t found_location; + + found_location = temp_string.rfind("/"); + if (found_location != string::npos) + temp_string = temp_string.substr(found_location); + + found_location = temp_string.find('_',initial_location); + while (found_location != string::npos) { + temp_string.replace(found_location,1," "); + initial_location = found_location+1; found_location = temp_string.find('_',initial_location); - while (found_location != string::npos) - { - temp_string.replace(found_location,1," "); - initial_location = found_location+1; - found_location = temp_string.find('_',initial_location); - } - return temp_string; + } + return temp_string; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -string FGPropertyManager::GetFullyQualifiedName(void) -{ +string FGPropertyManager::GetFullyQualifiedName(void) { vector<string> stack; stack.push_back( getDisplayName(true) ); SGPropertyNode* tmpn=getParent(); bool atroot=false; - while ( !atroot ) - { - stack.push_back( tmpn->getDisplayName(true) ); - if ( !tmpn->getParent() ) - atroot=true; - else - tmpn=tmpn->getParent(); + while( !atroot ) { + stack.push_back( tmpn->getDisplayName(true) ); + if( !tmpn->getParent() ) + atroot=true; + else + tmpn=tmpn->getParent(); } string fqname=""; - for (unsigned i=stack.size()-1;i>0;i--) - { - fqname+= stack[i]; - fqname+= "/"; + for(unsigned i=stack.size()-1;i>0;i--) { + fqname+= stack[i]; + fqname+= "/"; } fqname+= stack[0]; return fqname; @@ -164,13 +156,12 @@ string FGPropertyManager::GetFullyQualifiedName(void) string FGPropertyManager::GetRelativeName( const string &path ) { - string temp_string = GetFullyQualifiedName(); - size_t len = path.length(); - if ( (len > 0) && (temp_string.substr(0,len) == path) ) - { - temp_string = temp_string.erase(0,len); - } - return temp_string; + string temp_string = GetFullyQualifiedName(); + size_t len = path.length(); + if ( (len > 0) && (temp_string.substr(0,len) == path) ) { + temp_string = temp_string.erase(0,len); + } + return temp_string; } @@ -179,184 +170,184 @@ string FGPropertyManager::GetRelativeName( const string &path ) bool FGPropertyManager::GetBool (const string &name, bool defaultValue) { - return getBoolValue(name.c_str(), defaultValue); + return getBoolValue(name.c_str(), defaultValue); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% int FGPropertyManager::GetInt (const string &name, int defaultValue ) { - return getIntValue(name.c_str(), defaultValue); + return getIntValue(name.c_str(), defaultValue); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% int FGPropertyManager::GetLong (const string &name, long defaultValue ) { - return getLongValue(name.c_str(), defaultValue); + return getLongValue(name.c_str(), defaultValue); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% float FGPropertyManager::GetFloat (const string &name, float defaultValue ) { - return getFloatValue(name.c_str(), defaultValue); + return getFloatValue(name.c_str(), defaultValue); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGPropertyManager::GetDouble (const string &name, double defaultValue ) { - return getDoubleValue(name.c_str(), defaultValue); + return getDoubleValue(name.c_str(), defaultValue); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGPropertyManager::GetString (const string &name, string defaultValue ) { - return string(getStringValue(name.c_str(), defaultValue.c_str())); + return string(getStringValue(name.c_str(), defaultValue.c_str())); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPropertyManager::SetBool (const string &name, bool val) { - return setBoolValue(name.c_str(), val); + return setBoolValue(name.c_str(), val); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPropertyManager::SetInt (const string &name, int val) { - return setIntValue(name.c_str(), val); + return setIntValue(name.c_str(), val); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPropertyManager::SetLong (const string &name, long val) { - return setLongValue(name.c_str(), val); + return setLongValue(name.c_str(), val); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPropertyManager::SetFloat (const string &name, float val) { - return setFloatValue(name.c_str(), val); + return setFloatValue(name.c_str(), val); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPropertyManager::SetDouble (const string &name, double val) { - return setDoubleValue(name.c_str(), val); + return setDoubleValue(name.c_str(), val); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPropertyManager::SetString (const string &name, const string &val) { - return setStringValue(name.c_str(), val.c_str()); + return setStringValue(name.c_str(), val.c_str()); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropertyManager::SetArchivable (const string &name, bool state ) { - SGPropertyNode * node = getNode(name.c_str()); - if (node == 0) - cerr << - "Attempt to set archive flag for non-existent property " - << name << endl; - else - node->setAttribute(SGPropertyNode::ARCHIVE, state); + SGPropertyNode * node = getNode(name.c_str()); + if (node == 0) + cerr << + "Attempt to set archive flag for non-existent property " + << name << endl; + else + node->setAttribute(SGPropertyNode::ARCHIVE, state); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropertyManager::SetReadable (const string &name, bool state ) { - SGPropertyNode * node = getNode(name.c_str()); - if (node == 0) - cerr << - "Attempt to set read flag for non-existant property " - << name << endl; - else - node->setAttribute(SGPropertyNode::READ, state); + SGPropertyNode * node = getNode(name.c_str()); + if (node == 0) + cerr << + "Attempt to set read flag for non-existant property " + << name << endl; + else + node->setAttribute(SGPropertyNode::READ, state); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropertyManager::SetWritable (const string &name, bool state ) { - SGPropertyNode * node = getNode(name.c_str()); - if (node == 0) - cerr << - "Attempt to set write flag for non-existant property " - << name << endl; - else - node->setAttribute(SGPropertyNode::WRITE, state); + SGPropertyNode * node = getNode(name.c_str()); + if (node == 0) + cerr << + "Attempt to set write flag for non-existant property " + << name << endl; + else + node->setAttribute(SGPropertyNode::WRITE, state); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropertyManager::Untie (const string &name) { - if (!untie(name.c_str())) - cerr << "Failed to untie property " << name << endl; + if (!untie(name.c_str())) + cerr << "Failed to untie property " << name << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault) { - if (!tie(name.c_str(), SGRawValuePointer<bool>(pointer), useDefault)) - cerr << "Failed to tie property " << name << " to a pointer" << endl; - else if (debug_lvl & 0x20) - cout << name << endl; + if (!tie(name.c_str(), SGRawValuePointer<bool>(pointer), useDefault)) + cerr << "Failed to tie property " << name << " to a pointer" << endl; + else if (debug_lvl & 0x20) + cout << name << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropertyManager::Tie (const string &name, int *pointer, - bool useDefault ) + bool useDefault ) { - if (!tie(name.c_str(), SGRawValuePointer<int>(pointer), useDefault)) - cerr << "Failed to tie property " << name << " to a pointer" << endl; - else if (debug_lvl & 0x20) - cout << name << endl; + if (!tie(name.c_str(), SGRawValuePointer<int>(pointer), useDefault)) + cerr << "Failed to tie property " << name << " to a pointer" << endl; + else if (debug_lvl & 0x20) + cout << name << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropertyManager::Tie (const string &name, long *pointer, - bool useDefault ) + bool useDefault ) { - if (!tie(name.c_str(), SGRawValuePointer<long>(pointer), useDefault)) - cerr << "Failed to tie property " << name << " to a pointer" << endl; - else if (debug_lvl & 0x20) - cout << name << endl; + if (!tie(name.c_str(), SGRawValuePointer<long>(pointer), useDefault)) + cerr << "Failed to tie property " << name << " to a pointer" << endl; + else if (debug_lvl & 0x20) + cout << name << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropertyManager::Tie (const string &name, float *pointer, - bool useDefault ) + bool useDefault ) { - if (!tie(name.c_str(), SGRawValuePointer<float>(pointer), useDefault)) - cerr << "Failed to tie property " << name << " to a pointer" << endl; - else if (debug_lvl & 0x20) - cout << name << endl; + if (!tie(name.c_str(), SGRawValuePointer<float>(pointer), useDefault)) + cerr << "Failed to tie property " << name << " to a pointer" << endl; + else if (debug_lvl & 0x20) + cout << name << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropertyManager::Tie (const string &name, double *pointer, bool useDefault) { - if (!tie(name.c_str(), SGRawValuePointer<double>(pointer), useDefault)) - cerr << "Failed to tie property " << name << " to a pointer" << endl; - else if (debug_lvl & 0x20) - cout << name << endl; + if (!tie(name.c_str(), SGRawValuePointer<double>(pointer), useDefault)) + cerr << "Failed to tie property " << name << " to a pointer" << endl; + else if (debug_lvl & 0x20) + cout << name << endl; } } // namespace JSBSim diff --git a/src/input_output/FGPropertyManager.h b/src/input_output/FGPropertyManager.h index 56344a2e4c715bafda23be8981fd8d7c1bb7ea36..81f7bea06a2569bace1b1487d44ddea69a0488a4 100644 --- a/src/input_output/FGPropertyManager.h +++ b/src/input_output/FGPropertyManager.h @@ -59,8 +59,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -76,14 +75,11 @@ CLASS DECLARATION class FGPropertyManager : public SGPropertyNode, public FGJSBBase { -private: + private: static bool suppress_warning; -public: + public: /// Constructor - FGPropertyManager(void) - { - suppress_warning = false; - } + FGPropertyManager(void) {suppress_warning = false;} /// Destructor virtual ~FGPropertyManager(void) {} @@ -404,7 +400,7 @@ public: void Untie (const std::string &name); - // Templates cause ambiguity here + // Templates cause ambiguity here /** * Tie a property to an external bool variable. @@ -508,30 +504,30 @@ public: V (T::*getter)(int) const, void (T::*setter)(int, V) = 0, bool useDefault = true); */ - /** - * Tie a property to a pair of simple functions. - * - * Every time the property value is queried, the getter (if any) will - * be invoked; every time the property value is modified, the setter - * (if any) will be invoked. The getter can be 0 to make the property - * unreadable, and the setter can be 0 to make the property - * unmodifiable. - * - * @param name The property name to tie (full path). - * @param getter The getter function, or 0 if the value is unreadable. - * @param setter The setter function, or 0 if the value is unmodifiable. - * @param useDefault true if the setter should be invoked with any existing - * property value should be; false if the old value should be - * discarded; defaults to true. - */ + /** + * Tie a property to a pair of simple functions. + * + * Every time the property value is queried, the getter (if any) will + * be invoked; every time the property value is modified, the setter + * (if any) will be invoked. The getter can be 0 to make the property + * unreadable, and the setter can be 0 to make the property + * unmodifiable. + * + * @param name The property name to tie (full path). + * @param getter The getter function, or 0 if the value is unreadable. + * @param setter The setter function, or 0 if the value is unmodifiable. + * @param useDefault true if the setter should be invoked with any existing + * property value should be; false if the old value should be + * discarded; defaults to true. + */ template <class V> inline void Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true) { - if (!tie(name.c_str(), SGRawValueFunctions<V>(getter, setter), useDefault)) - std::cerr << "Failed to tie property " << name << " to functions" << std::endl; - else if (debug_lvl & 0x20) - std::cout << name << std::endl; + if (!tie(name.c_str(), SGRawValueFunctions<V>(getter, setter), useDefault)) + std::cerr << "Failed to tie property " << name << " to functions" << std::endl; + else if (debug_lvl & 0x20) + std::cout << name << std::endl; } @@ -554,12 +550,12 @@ public: * discarded; defaults to true. */ template <class V> inline void Tie (const std::string &name, int index, V (*getter)(int), - void (*setter)(int, V) = 0, bool useDefault = true) + void (*setter)(int, V) = 0, bool useDefault = true) { - if (!tie(name.c_str(), SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault)) - std::cerr << "Failed to tie property " << name << " to indexed functions" << std::endl; - else if (debug_lvl & 0x20) - std::cout << name << std::endl; + if (!tie(name.c_str(), SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault)) + std::cerr << "Failed to tie property " << name << " to indexed functions" << std::endl; + else if (debug_lvl & 0x20) + std::cout << name << std::endl; } @@ -584,12 +580,12 @@ public: */ template <class T, class V> inline void Tie (const std::string &name, T * obj, V (T::*getter)() const, - void (T::*setter)(V) = 0, bool useDefault = true) + void (T::*setter)(V) = 0, bool useDefault = true) { - if (!tie(name.c_str(), SGRawValueMethods<T,V>(*obj, getter, setter), useDefault)) - std::cerr << "Failed to tie property " << name << " to object methods" << std::endl; - else if (debug_lvl & 0x20) - std::cout << name << std::endl; + if (!tie(name.c_str(), SGRawValueMethods<T,V>(*obj, getter, setter), useDefault)) + std::cerr << "Failed to tie property " << name << " to object methods" << std::endl; + else if (debug_lvl & 0x20) + std::cout << name << std::endl; } /** @@ -613,13 +609,13 @@ public: */ template <class T, class V> inline void Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const, - void (T::*setter)(int, V) = 0, bool useDefault = true) + void (T::*setter)(int, V) = 0, bool useDefault = true) { - if (!tie(name.c_str(), SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault)) - std::cerr << "Failed to tie property " << name << " to indexed object methods" << std::endl; - else if (debug_lvl & 0x20) - std::cout << name << std::endl; - } + if (!tie(name.c_str(), SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault)) + std::cerr << "Failed to tie property " << name << " to indexed object methods" << std::endl; + else if (debug_lvl & 0x20) + std::cout << name << std::endl; + } }; } #endif // FGPROPERTYMANAGER_H diff --git a/src/input_output/FGScript.cpp b/src/input_output/FGScript.cpp old mode 100644 new mode 100755 index eed01e1635216f178551efa8e11b6f1f5b82361a..bd940bb4c4c4264a1bcf25747dea30f2b7cff30e --- a/src/input_output/FGScript.cpp +++ b/src/input_output/FGScript.cpp @@ -52,8 +52,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGScript.cpp,v 1.41 2010/07/08 11:36:28 jberndt Exp $"; static const char *IdHdr = ID_FGSCRIPT; @@ -70,429 +69,373 @@ CLASS IMPLEMENTATION FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex) { - PropertyManager=FDMExec->GetPropertyManager(); + PropertyManager=FDMExec->GetPropertyManager(); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGScript::~FGScript() { - unsigned int i; + unsigned int i; - for (i=0; i<local_properties.size(); i++) delete local_properties[i]; - local_properties.clear(); + for (i=0; i<local_properties.size(); i++) delete local_properties[i]; + local_properties.clear(); - for (i=0; i<Events.size(); i++) delete Events[i].Condition; - Events.clear(); + for (i=0; i<Events.size(); i++) delete Events[i].Condition; + Events.clear(); - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGScript::LoadScript(string script, double deltaT) { - string aircraft="", initialize="", comparison = "", prop_name=""; - string notifyPropertyName=""; - Element *element=0, *run_element=0, *event_element=0; - Element *condition_element=0, *set_element=0, *delay_element=0; - Element *notify_element = 0L, *notify_property_element = 0L; - Element *property_element = 0L; - Element *output_element = 0L; - Element *input_element = 0L; - bool result = false; - double dt = 0.0, value = 0.0; - struct event *newEvent; - FGCondition *newCondition; - - document = LoadXMLDocument(script); - - if (!document) - { - cerr << "File: " << script << " could not be loaded." << endl; - return false; + string aircraft="", initialize="", comparison = "", prop_name=""; + string notifyPropertyName=""; + Element *element=0, *run_element=0, *event_element=0; + Element *condition_element=0, *set_element=0, *delay_element=0; + Element *notify_element = 0L, *notify_property_element = 0L; + Element *property_element = 0L; + Element *output_element = 0L; + Element *input_element = 0L; + bool result = false; + double dt = 0.0, value = 0.0; + struct event *newEvent; + FGCondition *newCondition; + + document = LoadXMLDocument(script); + + if (!document) { + cerr << "File: " << script << " could not be loaded." << endl; + return false; + } + + // Set up input and output files if specified + + output_element = document->FindElement("output"); + input_element = document->FindElement("input"); + + if (document->GetName() != string("runscript")) { + cerr << "File: " << script << " is not a script file" << endl; + return false; + } + + ScriptName = document->GetAttributeValue("name"); + + // First, find "run" element and set delta T + + run_element = document->FindElement("run"); + + if (!run_element) { + cerr << "No \"run\" element found in script." << endl; + return false; + } + + // Set sim timing + + StartTime = run_element->GetAttributeValueAsNumber("start"); + FDMExec->Setsim_time(StartTime); + EndTime = run_element->GetAttributeValueAsNumber("end"); + + if (deltaT == 0.0) + dt = run_element->GetAttributeValueAsNumber("dt"); + else { + dt = deltaT; + cout << endl << "Overriding simulation step size from the command line. New step size is: " + << deltaT << " seconds (" << 1/deltaT << " Hz)" << endl << endl; + } + + FDMExec->Setdt(dt); + + // read aircraft and initialization files + + element = document->FindElement("use"); + if (element) { + aircraft = element->GetAttributeValue("aircraft"); + if (!aircraft.empty()) { + result = FDMExec->LoadModel(aircraft); + if (!result) return false; + } else { + cerr << "Aircraft must be specified in use element." << endl; + return false; } - // Set up input and output files if specified - - output_element = document->FindElement("output"); - input_element = document->FindElement("input"); - - if (document->GetName() != string("runscript")) - { - cerr << "File: " << script << " is not a script file" << endl; - return false; + initialize = element->GetAttributeValue("initialize"); + if (initialize.empty()) { + cerr << "Initialization file must be specified in use element." << endl; + return false; } - ScriptName = document->GetAttributeValue("name"); - -// First, find "run" element and set delta T - - run_element = document->FindElement("run"); - - if (!run_element) - { - cerr << "No \"run\" element found in script." << endl; - return false; + } else { + cerr << "No \"use\" directives in the script file." << endl; + return false; + } + + // Now, read input spec if given. + if (input_element > 0) { + FDMExec->GetInput()->Load(input_element); + } + + // Now, read output spec if given. + if (output_element > 0) { + string output_file = output_element->GetAttributeValue("file"); + if (output_file.empty()) { + cerr << "No logging directives file was specified." << endl; + } else { + if (!FDMExec->SetOutputDirectives(output_file)) return false; } - - // Set sim timing - - StartTime = run_element->GetAttributeValueAsNumber("start"); - FDMExec->Setsim_time(StartTime); - EndTime = run_element->GetAttributeValueAsNumber("end"); - - if (deltaT == 0.0) - dt = run_element->GetAttributeValueAsNumber("dt"); - else - { - dt = deltaT; - cout << endl << "Overriding simulation step size from the command line. New step size is: " - << deltaT << " seconds (" << 1/deltaT << " Hz)" << endl << endl; + } + + // Read local property/value declarations + property_element = run_element->FindElement("property"); + while (property_element) { + + double value=0.0; + string title=""; + + title = property_element->GetDataLine(); + if ( ! property_element->GetAttributeValue("value").empty()) + value = property_element->GetAttributeValueAsNumber("value"); + + LocalProps *localProp = new LocalProps(value); + localProp->title = title; + local_properties.push_back(localProp); + if (PropertyManager->HasNode(title)) { + PropertyManager->GetNode(title)->setDoubleValue(value); + } else { + PropertyManager->Tie(localProp->title, localProp->value); } + property_element = run_element->FindNextElement("property"); + } - FDMExec->Setdt(dt); + // Read "events" from script - // read aircraft and initialization files + event_element = run_element->FindElement("event"); + while (event_element) { // event processing - element = document->FindElement("use"); - if (element) - { - aircraft = element->GetAttributeValue("aircraft"); - if (!aircraft.empty()) - { - result = FDMExec->LoadModel(aircraft); - if (!result) return false; - } - else - { - cerr << "Aircraft must be specified in use element." << endl; - return false; - } + // Create the event structure + newEvent = new struct event(); - initialize = element->GetAttributeValue("initialize"); - if (initialize.empty()) - { - cerr << "Initialization file must be specified in use element." << endl; - return false; - } + // Retrieve the event name if given + newEvent->Name = event_element->GetAttributeValue("name"); - } - else - { - cerr << "No \"use\" directives in the script file." << endl; - return false; + // Is this event persistent? That is, does it execute every time the + // condition triggers to true, or does it execute as a one-shot event, only? + if (event_element->GetAttributeValue("persistent") == string("true")) { + newEvent->Persistent = true; } - // Now, read input spec if given. - if (input_element > 0) - { - FDMExec->GetInput()->Load(input_element); + // Does this event execute continuously when triggered to true? + if (event_element->GetAttributeValue("continuous") == string("true")) { + newEvent->Continuous = true; } - // Now, read output spec if given. - if (output_element > 0) - { - string output_file = output_element->GetAttributeValue("file"); - if (output_file.empty()) - { - cerr << "No logging directives file was specified." << endl; - } - else - { - if (!FDMExec->SetOutputDirectives(output_file)) return false; - } + // Process the conditions + condition_element = event_element->FindElement("condition"); + if (condition_element != 0) { + try { + newCondition = new FGCondition(condition_element, PropertyManager); + } catch(string str) { + cout << endl << fgred << str << reset << endl << endl; + return false; + } + newEvent->Condition = newCondition; + } else { + cerr << "No condition specified in script event " << newEvent->Name << endl; + return false; } - // Read local property/value declarations - property_element = run_element->FindElement("property"); - while (property_element) - { - - double value=0.0; - string title=""; - - title = property_element->GetDataLine(); - if ( ! property_element->GetAttributeValue("value").empty()) - value = property_element->GetAttributeValueAsNumber("value"); - - LocalProps *localProp = new LocalProps(value); - localProp->title = title; - local_properties.push_back(localProp); - if (PropertyManager->HasNode(title)) - { - PropertyManager->GetNode(title)->setDoubleValue(value); - } - else - { - PropertyManager->Tie(localProp->title, localProp->value); + // Is there a delay between the time this event is triggered, and when the event + // actions are executed? + + delay_element = event_element->FindElement("delay"); + if (delay_element) newEvent->Delay = event_element->FindElementValueAsNumber("delay"); + else newEvent->Delay = 0.0; + + // Notify about when this event is triggered? + if ((notify_element = event_element->FindElement("notify")) != 0) { + newEvent->Notify = true; + notify_property_element = notify_element->FindElement("property"); + while (notify_property_element) { + notifyPropertyName = notify_property_element->GetDataLine(); + if (PropertyManager->GetNode(notifyPropertyName)) { + newEvent->NotifyProperties.push_back( PropertyManager->GetNode(notifyPropertyName) ); + } else { + cout << endl << fgred << " Could not find the property named " + << notifyPropertyName << " in script" << endl << " \"" + << ScriptName << "\". This unknown property will not be " + << "echoed for notification." << reset << endl; } - property_element = run_element->FindNextElement("property"); + notify_property_element = notify_element->FindNextElement("property"); + } } - // Read "events" from script - - event_element = run_element->FindElement("event"); - while (event_element) // event processing - { - - // Create the event structure - newEvent = new struct event(); - - // Retrieve the event name if given - newEvent->Name = event_element->GetAttributeValue("name"); - - // Is this event persistent? That is, does it execute every time the - // condition triggers to true, or does it execute as a one-shot event, only? - if (event_element->GetAttributeValue("persistent") == string("true")) - { - newEvent->Persistent = true; - } - - // Does this event execute continuously when triggered to true? - if (event_element->GetAttributeValue("continuous") == string("true")) - { - newEvent->Continuous = true; - } - - // Process the conditions - condition_element = event_element->FindElement("condition"); - if (condition_element != 0) - { - try - { - newCondition = new FGCondition(condition_element, PropertyManager); - } - catch (string str) - { - cout << endl << fgred << str << reset << endl << endl; - return false; - } - newEvent->Condition = newCondition; - } - else - { - cerr << "No condition specified in script event " << newEvent->Name << endl; - return false; - } - - // Is there a delay between the time this event is triggered, and when the event - // actions are executed? - - delay_element = event_element->FindElement("delay"); - if (delay_element) newEvent->Delay = event_element->FindElementValueAsNumber("delay"); - else newEvent->Delay = 0.0; - - // Notify about when this event is triggered? - if ((notify_element = event_element->FindElement("notify")) != 0) - { - newEvent->Notify = true; - notify_property_element = notify_element->FindElement("property"); - while (notify_property_element) - { - notifyPropertyName = notify_property_element->GetDataLine(); - if (PropertyManager->GetNode(notifyPropertyName)) - { - newEvent->NotifyProperties.push_back( PropertyManager->GetNode(notifyPropertyName) ); - } - else - { - cout << endl << fgred << " Could not find the property named " - << notifyPropertyName << " in script" << endl << " \"" - << ScriptName << "\". This unknown property will not be " - << "echoed for notification." << reset << endl; - } - notify_property_element = notify_element->FindNextElement("property"); - } - } - - // Read set definitions (these define the actions to be taken when the event is triggered). - set_element = event_element->FindElement("set"); - while (set_element) - { - prop_name = set_element->GetAttributeValue("name"); - newEvent->SetParam.push_back( PropertyManager->GetNode(prop_name) ); - //Todo - should probably do some safety checking here to make sure one or the other - //of value or function is specified. - if (!set_element->GetAttributeValue("value").empty()) - { - value = set_element->GetAttributeValueAsNumber("value"); - newEvent->Functions.push_back((FGFunction*)0L); - } - else if (set_element->FindElement("function")) - { - value = 0.0; - newEvent->Functions.push_back(new FGFunction(PropertyManager, set_element->FindElement("function"))); - } - newEvent->SetValue.push_back(value); - newEvent->OriginalValue.push_back(0.0); - newEvent->newValue.push_back(0.0); - newEvent->ValueSpan.push_back(0.0); - string tempCompare = set_element->GetAttributeValue("type"); - if (to_lower(tempCompare).find("delta") != string::npos) newEvent->Type.push_back(FG_DELTA); - else if (to_lower(tempCompare).find("bool") != string::npos) newEvent->Type.push_back(FG_BOOL); - else if (to_lower(tempCompare).find("value") != string::npos) newEvent->Type.push_back(FG_VALUE); - else newEvent->Type.push_back(FG_VALUE); // DEFAULT - tempCompare = set_element->GetAttributeValue("action"); - if (to_lower(tempCompare).find("ramp") != string::npos) newEvent->Action.push_back(FG_RAMP); - else if (to_lower(tempCompare).find("step") != string::npos) newEvent->Action.push_back(FG_STEP); - else if (to_lower(tempCompare).find("exp") != string::npos) newEvent->Action.push_back(FG_EXP); - else newEvent->Action.push_back(FG_STEP); // DEFAULT - - if (!set_element->GetAttributeValue("tc").empty()) - newEvent->TC.push_back(set_element->GetAttributeValueAsNumber("tc")); - else - newEvent->TC.push_back(1.0); // DEFAULT - - newEvent->Transiting.push_back(false); - - set_element = event_element->FindNextElement("set"); - } - Events.push_back(*newEvent); - delete newEvent; - - event_element = run_element->FindNextElement("event"); + // Read set definitions (these define the actions to be taken when the event is triggered). + set_element = event_element->FindElement("set"); + while (set_element) { + prop_name = set_element->GetAttributeValue("name"); + newEvent->SetParam.push_back( PropertyManager->GetNode(prop_name) ); + //Todo - should probably do some safety checking here to make sure one or the other + //of value or function is specified. + if (!set_element->GetAttributeValue("value").empty()) { + value = set_element->GetAttributeValueAsNumber("value"); + newEvent->Functions.push_back((FGFunction*)0L); + } else if (set_element->FindElement("function")) { + value = 0.0; + newEvent->Functions.push_back(new FGFunction(PropertyManager, set_element->FindElement("function"))); + } + newEvent->SetValue.push_back(value); + newEvent->OriginalValue.push_back(0.0); + newEvent->newValue.push_back(0.0); + newEvent->ValueSpan.push_back(0.0); + string tempCompare = set_element->GetAttributeValue("type"); + if (to_lower(tempCompare).find("delta") != string::npos) newEvent->Type.push_back(FG_DELTA); + else if (to_lower(tempCompare).find("bool") != string::npos) newEvent->Type.push_back(FG_BOOL); + else if (to_lower(tempCompare).find("value") != string::npos) newEvent->Type.push_back(FG_VALUE); + else newEvent->Type.push_back(FG_VALUE); // DEFAULT + tempCompare = set_element->GetAttributeValue("action"); + if (to_lower(tempCompare).find("ramp") != string::npos) newEvent->Action.push_back(FG_RAMP); + else if (to_lower(tempCompare).find("step") != string::npos) newEvent->Action.push_back(FG_STEP); + else if (to_lower(tempCompare).find("exp") != string::npos) newEvent->Action.push_back(FG_EXP); + else newEvent->Action.push_back(FG_STEP); // DEFAULT + + if (!set_element->GetAttributeValue("tc").empty()) + newEvent->TC.push_back(set_element->GetAttributeValueAsNumber("tc")); + else + newEvent->TC.push_back(1.0); // DEFAULT + + newEvent->Transiting.push_back(false); + + set_element = event_element->FindNextElement("set"); } + Events.push_back(*newEvent); + delete newEvent; - Debug(4); + event_element = run_element->FindNextElement("event"); + } - FGInitialCondition *IC=FDMExec->GetIC(); - if ( ! IC->Load( initialize )) - { - cerr << "Initialization unsuccessful" << endl; - exit(-1); - } + Debug(4); - return true; + FGInitialCondition *IC=FDMExec->GetIC(); + if ( ! IC->Load( initialize )) { + cerr << "Initialization unsuccessful" << endl; + exit(-1); + } + + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGScript::RunScript(void) { - unsigned i, j; - unsigned event_ctr = 0; - - double currentTime = FDMExec->GetSimTime(); - double newSetValue = 0; - - if (currentTime > EndTime) return false; //Script done! - - // Iterate over all events. - for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) - { - // Determine whether the set of conditional tests for this condition equate - // to true and should cause the event to execute. If the conditions evaluate - // to true, then the event is triggered. If the event is not persistent, - // then this trigger will remain set true. If the event is persistent, - // the trigger will reset to false when the condition evaluates to false. - if (Events[ev_ctr].Condition->Evaluate()) - { - if (!Events[ev_ctr].Triggered) - { - - // The conditions are true, do the setting of the desired Event parameters - for (i=0; i<Events[ev_ctr].SetValue.size(); i++) - { - Events[ev_ctr].OriginalValue[i] = Events[ev_ctr].SetParam[i]->getDoubleValue(); - if (Events[ev_ctr].Functions[i] != 0) // Parameter should be set to a function value - { - Events[ev_ctr].SetValue[i] = Events[ev_ctr].Functions[i]->GetValue(); - } - switch (Events[ev_ctr].Type[i]) - { - case FG_VALUE: - case FG_BOOL: - Events[ev_ctr].newValue[i] = Events[ev_ctr].SetValue[i]; - break; - case FG_DELTA: - Events[ev_ctr].newValue[i] = Events[ev_ctr].OriginalValue[i] + Events[ev_ctr].SetValue[i]; - break; - default: - cerr << "Invalid Type specified" << endl; - break; - } - Events[ev_ctr].StartTime = currentTime + Events[ev_ctr].Delay; - Events[ev_ctr].ValueSpan[i] = Events[ev_ctr].newValue[i] - Events[ev_ctr].OriginalValue[i]; - Events[ev_ctr].Transiting[i] = true; - } - } - Events[ev_ctr].Triggered = true; - + unsigned i, j; + unsigned event_ctr = 0; + + double currentTime = FDMExec->GetSimTime(); + double newSetValue = 0; + + if (currentTime > EndTime) return false; //Script done! + + // Iterate over all events. + for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) { + // Determine whether the set of conditional tests for this condition equate + // to true and should cause the event to execute. If the conditions evaluate + // to true, then the event is triggered. If the event is not persistent, + // then this trigger will remain set true. If the event is persistent, + // the trigger will reset to false when the condition evaluates to false. + if (Events[ev_ctr].Condition->Evaluate()) { + if (!Events[ev_ctr].Triggered) { + + // The conditions are true, do the setting of the desired Event parameters + for (i=0; i<Events[ev_ctr].SetValue.size(); i++) { + Events[ev_ctr].OriginalValue[i] = Events[ev_ctr].SetParam[i]->getDoubleValue(); + if (Events[ev_ctr].Functions[i] != 0) { // Parameter should be set to a function value + Events[ev_ctr].SetValue[i] = Events[ev_ctr].Functions[i]->GetValue(); + } + switch (Events[ev_ctr].Type[i]) { + case FG_VALUE: + case FG_BOOL: + Events[ev_ctr].newValue[i] = Events[ev_ctr].SetValue[i]; + break; + case FG_DELTA: + Events[ev_ctr].newValue[i] = Events[ev_ctr].OriginalValue[i] + Events[ev_ctr].SetValue[i]; + break; + default: + cerr << "Invalid Type specified" << endl; + break; + } + Events[ev_ctr].StartTime = currentTime + Events[ev_ctr].Delay; + Events[ev_ctr].ValueSpan[i] = Events[ev_ctr].newValue[i] - Events[ev_ctr].OriginalValue[i]; + Events[ev_ctr].Transiting[i] = true; } - else if (Events[ev_ctr].Persistent) // If the event is persistent, reset the trigger. - { + } + Events[ev_ctr].Triggered = true; - Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events - Events[ev_ctr].Notified = false; // Also reset the notification flag - } + } else if (Events[ev_ctr].Persistent) { // If the event is persistent, reset the trigger. - if ((currentTime >= Events[ev_ctr].StartTime) && Events[ev_ctr].Triggered) - { - - for (i=0; i<Events[ev_ctr].SetValue.size(); i++) - { - if (Events[ev_ctr].Transiting[i]) - { - Events[ev_ctr].TimeSpan = currentTime - Events[ev_ctr].StartTime; - switch (Events[ev_ctr].Action[i]) - { - case FG_RAMP: - if (Events[ev_ctr].TimeSpan <= Events[ev_ctr].TC[i]) - { - newSetValue = Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i]; - } - else - { - newSetValue = Events[ev_ctr].newValue[i]; - if (Events[ev_ctr].Continuous != true) Events[ev_ctr].Transiting[i] = false; - } - break; - case FG_STEP: - newSetValue = Events[ev_ctr].newValue[i]; - - // If this is not a continuous event, reset the transiting flag. - // Otherwise, it is known that the event is a continuous event. - // Furthermore, if the event is to be determined by a function, - // then the function will be continuously calculated. - if (Events[ev_ctr].Continuous != true) - Events[ev_ctr].Transiting[i] = false; - else if (Events[ev_ctr].Functions[i] != 0) - newSetValue = Events[ev_ctr].Functions[i]->GetValue(); - - break; - case FG_EXP: - newSetValue = (1 - exp( -Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] )) * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i]; - break; - default: - cerr << "Invalid Action specified" << endl; - break; - } - Events[ev_ctr].SetParam[i]->setDoubleValue(newSetValue); - } - } + Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events + Events[ev_ctr].Notified = false; // Also reset the notification flag + } - // Print notification values after setting them - if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) - { - cout << endl << " Event " << event_ctr << " (" << Events[ev_ctr].Name << ")" - << " executed at time: " << currentTime << endl; - for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) - { - cout << " " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName() - << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl; - } - cout << endl; - Events[ev_ctr].Notified = true; + if ((currentTime >= Events[ev_ctr].StartTime) && Events[ev_ctr].Triggered) { + + for (i=0; i<Events[ev_ctr].SetValue.size(); i++) { + if (Events[ev_ctr].Transiting[i]) { + Events[ev_ctr].TimeSpan = currentTime - Events[ev_ctr].StartTime; + switch (Events[ev_ctr].Action[i]) { + case FG_RAMP: + if (Events[ev_ctr].TimeSpan <= Events[ev_ctr].TC[i]) { + newSetValue = Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i]; + } else { + newSetValue = Events[ev_ctr].newValue[i]; + if (Events[ev_ctr].Continuous != true) Events[ev_ctr].Transiting[i] = false; } - + break; + case FG_STEP: + newSetValue = Events[ev_ctr].newValue[i]; + + // If this is not a continuous event, reset the transiting flag. + // Otherwise, it is known that the event is a continuous event. + // Furthermore, if the event is to be determined by a function, + // then the function will be continuously calculated. + if (Events[ev_ctr].Continuous != true) + Events[ev_ctr].Transiting[i] = false; + else if (Events[ev_ctr].Functions[i] != 0) + newSetValue = Events[ev_ctr].Functions[i]->GetValue(); + + break; + case FG_EXP: + newSetValue = (1 - exp( -Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] )) * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i]; + break; + default: + cerr << "Invalid Action specified" << endl; + break; + } + Events[ev_ctr].SetParam[i]->setDoubleValue(newSetValue); } + } + + // Print notification values after setting them + if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) { + cout << endl << " Event " << event_ctr << " (" << Events[ev_ctr].Name << ")" + << " executed at time: " << currentTime << endl; + for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) { + cout << " " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName() + << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl; + } + cout << endl; + Events[ev_ctr].Notified = true; + } - event_ctr++; } - return true; + + event_ctr++; + } + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -516,153 +459,128 @@ bool FGScript::RunScript(void) void FGScript::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - } - else if (from == 3) - { - } - else if (from == 4) // print out script data - { - cout << endl; - cout << "Script: \"" << ScriptName << "\"" << endl; - cout << " begins at " << StartTime << " seconds and runs to " << EndTime - << " seconds with dt = " << setprecision(6) << FDMExec->GetDeltaT() << " (" << - ceil(1.0/FDMExec->GetDeltaT()) << " Hz)" << endl; - cout << endl; - - for (unsigned int i=0; i<local_properties.size(); i++) - { - cout << "Local property: " << local_properties[i]->title - << " = " << PropertyManager->GetNode(local_properties[i]->title)->getDoubleValue() - << endl; + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + } else if (from == 3) { + } else if (from == 4) { // print out script data + cout << endl; + cout << "Script: \"" << ScriptName << "\"" << endl; + cout << " begins at " << StartTime << " seconds and runs to " << EndTime + << " seconds with dt = " << setprecision(6) << FDMExec->GetDeltaT() << " (" << + ceil(1.0/FDMExec->GetDeltaT()) << " Hz)" << endl; + cout << endl; + + for (unsigned int i=0; i<local_properties.size(); i++) { + cout << "Local property: " << local_properties[i]->title + << " = " << PropertyManager->GetNode(local_properties[i]->title)->getDoubleValue() + << endl; + } + + if (local_properties.size() > 0) cout << endl; + + for (unsigned i=0; i<Events.size(); i++) { + cout << "Event " << i; + if (!Events[i].Name.empty()) cout << " (" << Events[i].Name << ")"; + cout << ":" << endl; + + if (Events[i].Persistent) + cout << " " << "Always executes"; + else + cout << " " << "Executes once"; + + Events[i].Condition->PrintCondition(); + + cout << endl << " Actions taken"; + if (Events[i].Delay > 0.0) + cout << " (after a delay of " << Events[i].Delay << " secs)"; + cout << ":" << endl << " {"; + for (unsigned j=0; j<Events[i].SetValue.size(); j++) { + if (Events[i].SetValue[j] == 0.0 && Events[i].Functions[j] != 0L) { + if (Events[i].SetParam[j] == 0) { + cerr << fgred << highint << endl + << " An attempt has been made to access a non-existent property" << endl + << " in this event. Please check the property names used, spelling, etc." + << reset << endl; + exit(-1); } - - if (local_properties.size() > 0) cout << endl; - - for (unsigned i=0; i<Events.size(); i++) - { - cout << "Event " << i; - if (!Events[i].Name.empty()) cout << " (" << Events[i].Name << ")"; - cout << ":" << endl; - - if (Events[i].Persistent) - cout << " " << "Always executes"; - else - cout << " " << "Executes once"; - - Events[i].Condition->PrintCondition(); - - cout << endl << " Actions taken"; - if (Events[i].Delay > 0.0) - cout << " (after a delay of " << Events[i].Delay << " secs)"; - cout << ":" << endl << " {"; - for (unsigned j=0; j<Events[i].SetValue.size(); j++) - { - if (Events[i].SetValue[j] == 0.0 && Events[i].Functions[j] != 0L) - { - if (Events[i].SetParam[j] == 0) - { - cerr << fgred << highint << endl - << " An attempt has been made to access a non-existent property" << endl - << " in this event. Please check the property names used, spelling, etc." - << reset << endl; - exit(-1); - } - cout << endl << " set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/") - << " to function value"; - } - else - { - if (Events[i].SetParam[j] == 0) - { - cerr << fgred << highint << endl - << " An attempt has been made to access a non-existent property" << endl - << " in this event. Please check the property names used, spelling, etc." - << reset << endl; - exit(-1); - } - cout << endl << " set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/") - << " to " << Events[i].SetValue[j]; - } - - switch (Events[i].Type[j]) - { - case FG_VALUE: - case FG_BOOL: - cout << " (constant"; - break; - case FG_DELTA: - cout << " (delta"; - break; - default: - cout << " (unspecified type"; - } - - switch (Events[i].Action[j]) - { - case FG_RAMP: - cout << " via ramp"; - break; - case FG_STEP: - cout << " via step)"; - break; - case FG_EXP: - cout << " via exponential approach"; - break; - default: - cout << " via unspecified action)"; - } - - if (Events[i].Action[j] == FG_RAMP || Events[i].Action[j] == FG_EXP) - cout << " with time constant " << Events[i].TC[j] << ")"; - } - cout << endl << " }" << endl; - - // Print notifications - if (Events[i].Notify) - { - if (Events[i].NotifyProperties.size() > 0) - { - cout << " Notifications" << ":" << endl << " {" << endl; - for (unsigned j=0; j<Events[i].NotifyProperties.size();j++) - { - cout << " " - << Events[i].NotifyProperties[j]->GetRelativeName("/fdm/jsbsim/") - << endl; - } - cout << " }" << endl; - } - } - cout << endl; + cout << endl << " set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/") + << " to function value"; + } else { + if (Events[i].SetParam[j] == 0) { + cerr << fgred << highint << endl + << " An attempt has been made to access a non-existent property" << endl + << " in this event. Please check the property names used, spelling, etc." + << reset << endl; + exit(-1); } + cout << endl << " set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/") + << " to " << Events[i].SetValue[j]; + } + + switch (Events[i].Type[j]) { + case FG_VALUE: + case FG_BOOL: + cout << " (constant"; + break; + case FG_DELTA: + cout << " (delta"; + break; + default: + cout << " (unspecified type"; + } + + switch (Events[i].Action[j]) { + case FG_RAMP: + cout << " via ramp"; + break; + case FG_STEP: + cout << " via step)"; + break; + case FG_EXP: + cout << " via exponential approach"; + break; + default: + cout << " via unspecified action)"; + } + + if (Events[i].Action[j] == FG_RAMP || Events[i].Action[j] == FG_EXP) + cout << " with time constant " << Events[i].TC[j] << ")"; } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGScript" << endl; - if (from == 1) cout << "Destroyed: FGScript" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; + cout << endl << " }" << endl; + + // Print notifications + if (Events[i].Notify) { + if (Events[i].NotifyProperties.size() > 0) { + cout << " Notifications" << ":" << endl << " {" << endl; + for (unsigned j=0; j<Events[i].NotifyProperties.size();j++) { + cout << " " + << Events[i].NotifyProperties[j]->GetRelativeName("/fdm/jsbsim/") + << endl; + } + cout << " }" << endl; + } } + cout << endl; + } + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGScript" << endl; + if (from == 1) cout << "Destroyed: FGScript" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/input_output/FGScript.h b/src/input_output/FGScript.h index 60aec0d39d986cb98250d76d5fd2e50416057f92..9f8d3ef8e84984bab04bd7857f64fa9ec717ee6d 100644 --- a/src/input_output/FGScript.h +++ b/src/input_output/FGScript.h @@ -54,8 +54,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -168,110 +167,102 @@ CLASS DECLARATION class FGScript : public FGJSBBase, public FGXMLFileRead { public: - /// Default constructor - FGScript(FGFDMExec* exec); - - /// Default destructor - ~FGScript(); - - /** Loads a script to drive JSBSim (usually in standalone mode). - The language is the Script Directives for JSBSim. If a simulation step size - has been supplied on the command line, it will be override the script- - specified simulation step size. - @param script the filename (including path name, if any) for the script. - @param deltaT a simulation step size from the command line - @return true if successful */ - bool LoadScript(string script, double deltaT); - - /** This function is called each pass through the executive Run() method IF - scripting is enabled. - @return false if script should exit (i.e. if time limits are violated */ - bool RunScript(void); - - void ResetEvents(void) - { - for (unsigned int i=0; i<Events.size(); i++) Events[i].reset(); - } + /// Default constructor + FGScript(FGFDMExec* exec); + + /// Default destructor + ~FGScript(); + + /** Loads a script to drive JSBSim (usually in standalone mode). + The language is the Script Directives for JSBSim. If a simulation step size + has been supplied on the command line, it will be override the script- + specified simulation step size. + @param script the filename (including path name, if any) for the script. + @param deltaT a simulation step size from the command line + @return true if successful */ + bool LoadScript(string script, double deltaT); + + /** This function is called each pass through the executive Run() method IF + scripting is enabled. + @return false if script should exit (i.e. if time limits are violated */ + bool RunScript(void); + + void ResetEvents(void) { + for (unsigned int i=0; i<Events.size(); i++) Events[i].reset(); + } private: - enum eAction - { - FG_RAMP = 1, - FG_STEP = 2, - FG_EXP = 3 - }; - - enum eType - { - FG_VALUE = 1, - FG_DELTA = 2, - FG_BOOL = 3 - }; - - struct event - { - FGCondition *Condition; - bool Persistent; - bool Continuous; - bool Triggered; - bool Notify; - bool Notified; - double Delay; - double StartTime; - double TimeSpan; - string Name; - vector <FGPropertyManager*> SetParam; - vector <FGPropertyManager*> NotifyProperties; - vector <eAction> Action; - vector <eType> Type; - vector <double> SetValue; - vector <double> TC; - vector <double> newValue; - vector <double> OriginalValue; - vector <double> ValueSpan; - vector <bool> Transiting; - vector <FGFunction*> Functions; - - event() - { - Triggered = false; - Persistent = false; - Continuous = false; - Delay = 0.0; - Notify = Notified = false; - Name = ""; - StartTime = 0.0; - TimeSpan = 0.0; - } - - void reset(void) - { - Triggered = false; - Notified = false; - StartTime = 0.0; - } - }; - - struct LocalProps - { - double *value; - string title; - LocalProps(double initial_value=0) - { - value = new double(initial_value); - title = ""; - } - }; - - string ScriptName; - double StartTime; - double EndTime; - vector <struct event> Events; - vector <LocalProps*> local_properties; - - FGFDMExec* FDMExec; - FGPropertyManager* PropertyManager; - void Debug(int from); + enum eAction { + FG_RAMP = 1, + FG_STEP = 2, + FG_EXP = 3 + }; + + enum eType { + FG_VALUE = 1, + FG_DELTA = 2, + FG_BOOL = 3 + }; + + struct event { + FGCondition *Condition; + bool Persistent; + bool Continuous; + bool Triggered; + bool Notify; + bool Notified; + double Delay; + double StartTime; + double TimeSpan; + string Name; + vector <FGPropertyManager*> SetParam; + vector <FGPropertyManager*> NotifyProperties; + vector <eAction> Action; + vector <eType> Type; + vector <double> SetValue; + vector <double> TC; + vector <double> newValue; + vector <double> OriginalValue; + vector <double> ValueSpan; + vector <bool> Transiting; + vector <FGFunction*> Functions; + + event() { + Triggered = false; + Persistent = false; + Continuous = false; + Delay = 0.0; + Notify = Notified = false; + Name = ""; + StartTime = 0.0; + TimeSpan = 0.0; + } + + void reset(void) { + Triggered = false; + Notified = false; + StartTime = 0.0; + } + }; + + struct LocalProps { + double *value; + string title; + LocalProps(double initial_value=0) { + value = new double(initial_value); + title = ""; + } + }; + + string ScriptName; + double StartTime; + double EndTime; + vector <struct event> Events; + vector <LocalProps*> local_properties; + + FGFDMExec* FDMExec; + FGPropertyManager* PropertyManager; + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/input_output/FGXMLElement.cpp b/src/input_output/FGXMLElement.cpp old mode 100644 new mode 100755 index 7fe0d039e9efde7f3bb57d726fe75a2322d98232..3f7becc5c4768ed4bd208cdea7a5ee1241f6b5a3 --- a/src/input_output/FGXMLElement.cpp +++ b/src/input_output/FGXMLElement.cpp @@ -40,10 +40,9 @@ using namespace std; FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.29 2010/03/18 13:18:31 jberndt Exp $"; +static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.30 2010/09/04 14:15:15 jberndt Exp $"; static const char *IdHdr = ID_XMLELEMENT; bool Element::converterIsInitialized = false; @@ -55,546 +54,498 @@ CLASS IMPLEMENTATION Element::Element(const string& nm) { - name = nm; - parent = 0L; - element_index = 0; - - if (!converterIsInitialized) - { - converterIsInitialized = true; - // convert ["from"]["to"] = factor, so: from * factor = to - // Length - convert["M"]["FT"] = 3.2808399; - convert["FT"]["M"] = 1.0/convert["M"]["FT"]; - convert["FT"]["IN"] = 12.0; - convert["IN"]["FT"] = 1.0/convert["FT"]["IN"]; - convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"]; - convert["M"]["IN"] = convert["M"]["FT"] * convert["FT"]["IN"]; - // Area - convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"]; - convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"]; - convert["M2"]["IN2"] = convert["M"]["IN"]*convert["M"]["IN"]; - convert["IN2"]["M2"] = 1.0/convert["M2"]["IN2"]; - convert["FT2"]["IN2"] = 144.0; - convert["IN2"]["FT2"] = 1.0/convert["FT2"]["IN2"]; - // Volume - convert["IN3"]["CC"] = 16.387064; - convert["CC"]["IN3"] = 1.0/convert["IN3"]["CC"]; - convert["FT3"]["IN3"] = 1728.0; - convert["IN3"]["FT3"] = 1.0/convert["FT3"]["IN3"]; - convert["M3"]["FT3"] = 35.3146667; - convert["FT3"]["M3"] = 1.0/convert["M3"]["FT3"]; - convert["LTR"]["IN3"] = 61.0237441; - convert["IN3"]["LTR"] = 1.0/convert["LTR"]["IN3"]; - // Mass & Weight - convert["LBS"]["KG"] = 0.45359237; - convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"]; - convert["SLUG"]["KG"] = 14.59390; - convert["KG"]["SLUG"] = 1.0/convert["SLUG"]["KG"]; - // Moments of Inertia - convert["SLUG*FT2"]["KG*M2"] = 1.35594; - convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"]; - // Angles - convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926); - convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"]; - // Spring force - convert["LBS/FT"]["N/M"] = 14.5939; - convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"]; - // Damping force - convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939; - convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"]; - // Damping force (Square Law) - convert["LBS/FT2/SEC2"]["N/M2/SEC2"] = 47.880259; - convert["N/M2/SEC2"]["LBS/FT2/SEC2"] = 1.0/convert["LBS/FT2/SEC2"]["N/M2/SEC2"]; - // Power - convert["WATTS"]["HP"] = 0.001341022; - convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"]; - // Force - convert["N"]["LBS"] = 0.22482; - convert["LBS"]["N"] = 1.0/convert["N"]["LBS"]; - // Velocity - convert["KTS"]["FT/SEC"] = 1.68781; - convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"]; - convert["M/S"]["FT/S"] = 3.2808399; - convert["M/SEC"]["FT/SEC"] = 3.2808399; - convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"]; - convert["M/SEC"]["FT/SEC"] = 3.2808399; - convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"]; - // Torque - convert["FT*LBS"]["N*M"] = 1.35581795; - convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"]; - // Valve - convert["M4*SEC/KG"]["FT4*SEC/SLUG"] = convert["M"]["FT"]*convert["M"]["FT"]* - convert["M"]["FT"]*convert["M"]["FT"]/convert["KG"]["SLUG"]; - convert["FT4*SEC/SLUG"]["M4*SEC/KG"] = - 1.0/convert["M4*SEC/KG"]["FT4*SEC/SLUG"]; - // Pressure - convert["INHG"]["PSF"] = 70.7180803; - convert["PSF"]["INHG"] = 1.0/convert["INHG"]["PSF"]; - convert["ATM"]["INHG"] = 29.9246899; - convert["INHG"]["ATM"] = 1.0/convert["ATM"]["INHG"]; - convert["PSI"]["INHG"] = 2.03625437; - convert["INHG"]["PSI"] = 1.0/convert["PSI"]["INHG"]; - convert["INHG"]["PA"] = 3386.0; // inches Mercury to pascals - convert["PA"]["INHG"] = 1.0/convert["INHG"]["PA"]; - convert["LBS/FT2"]["N/M2"] = 14.5939/convert["FT"]["M"]; - convert["N/M2"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["N/M2"]; - convert["LBS/FT2"]["PA"] = convert["LBS/FT2"]["N/M2"]; - convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"]; - // Mass flow - convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"]; - // Fuel Consumption - convert["LBS/HP*HR"]["KG/KW*HR"] = 0.6083; - convert["KG/KW*HR"]["LBS/HP*HR"] = 1.0/convert["LBS/HP*HR"]["KG/KW*HR"]; - // Density - convert["KG/L"]["LBS/GAL"] = 8.3454045; - convert["LBS/GAL"]["KG/L"] = 1.0/convert["KG/L"]["LBS/GAL"]; - - // Length - convert["M"]["M"] = 1.00; - convert["FT"]["FT"] = 1.00; - convert["IN"]["IN"] = 1.00; - // Area - convert["M2"]["M2"] = 1.00; - convert["FT2"]["FT2"] = 1.00; - // Volume - convert["IN3"]["IN3"] = 1.00; - convert["CC"]["CC"] = 1.0; - convert["M3"]["M3"] = 1.0; - convert["FT3"]["FT3"] = 1.0; - convert["LTR"]["LTR"] = 1.0; - // Mass & Weight - convert["KG"]["KG"] = 1.00; - convert["LBS"]["LBS"] = 1.00; - // Moments of Inertia - convert["KG*M2"]["KG*M2"] = 1.00; - convert["SLUG*FT2"]["SLUG*FT2"] = 1.00; - // Angles - convert["DEG"]["DEG"] = 1.00; - convert["RAD"]["RAD"] = 1.00; - // Spring force - convert["LBS/FT"]["LBS/FT"] = 1.00; - convert["N/M"]["N/M"] = 1.00; - // Damping force - convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00; - convert["N/M/SEC"]["N/M/SEC"] = 1.00; - // Damping force (Square law) - convert["LBS/FT2/SEC2"]["LBS/FT2/SEC2"] = 1.00; - convert["N/M2/SEC2"]["N/M2/SEC2"] = 1.00; - // Power - convert["HP"]["HP"] = 1.00; - convert["WATTS"]["WATTS"] = 1.00; - // Force - convert["N"]["N"] = 1.00; - // Velocity - convert["FT/SEC"]["FT/SEC"] = 1.00; - convert["KTS"]["KTS"] = 1.00; - convert["M/S"]["M/S"] = 1.0; - convert["M/SEC"]["M/SEC"] = 1.0; - // Torque - convert["FT*LBS"]["FT*LBS"] = 1.00; - convert["N*M"]["N*M"] = 1.00; - // Valve - convert["M4*SEC/KG"]["M4*SEC/KG"] = 1.0; - convert["FT4*SEC/SLUG"]["FT4*SEC/SLUG"] = 1.0; - // Pressure - convert["PSI"]["PSI"] = 1.00; - convert["PSF"]["PSF"] = 1.00; - convert["INHG"]["INHG"] = 1.00; - convert["ATM"]["ATM"] = 1.0; - convert["PA"]["PA"] = 1.0; - convert["N/M2"]["N/M2"] = 1.00; - convert["LBS/FT2"]["LBS/FT2"] = 1.00; - // Mass flow - convert["LBS/SEC"]["LBS/SEC"] = 1.00; - convert["KG/MIN"]["KG/MIN"] = 1.0; - convert["LBS/MIN"]["LBS/MIN"] = 1.0; - // Fuel Consumption - convert["LBS/HP*HR"]["LBS/HP*HR"] = 1.0; - convert["KG/KW*HR"]["KG/KW*HR"] = 1.0; - // Density - convert["KG/L"]["KG/L"] = 1.0; - convert["LBS/GAL"]["LBS/GAL"] = 1.0; - } + name = nm; + parent = 0L; + element_index = 0; + + if (!converterIsInitialized) { + converterIsInitialized = true; + // convert ["from"]["to"] = factor, so: from * factor = to + // Length + convert["M"]["FT"] = 3.2808399; + convert["FT"]["M"] = 1.0/convert["M"]["FT"]; + convert["FT"]["IN"] = 12.0; + convert["IN"]["FT"] = 1.0/convert["FT"]["IN"]; + convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"]; + convert["M"]["IN"] = convert["M"]["FT"] * convert["FT"]["IN"]; + // Area + convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"]; + convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"]; + convert["M2"]["IN2"] = convert["M"]["IN"]*convert["M"]["IN"]; + convert["IN2"]["M2"] = 1.0/convert["M2"]["IN2"]; + convert["FT2"]["IN2"] = 144.0; + convert["IN2"]["FT2"] = 1.0/convert["FT2"]["IN2"]; + // Volume + convert["IN3"]["CC"] = 16.387064; + convert["CC"]["IN3"] = 1.0/convert["IN3"]["CC"]; + convert["FT3"]["IN3"] = 1728.0; + convert["IN3"]["FT3"] = 1.0/convert["FT3"]["IN3"]; + convert["M3"]["FT3"] = 35.3146667; + convert["FT3"]["M3"] = 1.0/convert["M3"]["FT3"]; + convert["LTR"]["IN3"] = 61.0237441; + convert["IN3"]["LTR"] = 1.0/convert["LTR"]["IN3"]; + // Mass & Weight + convert["LBS"]["KG"] = 0.45359237; + convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"]; + convert["SLUG"]["KG"] = 14.59390; + convert["KG"]["SLUG"] = 1.0/convert["SLUG"]["KG"]; + // Moments of Inertia + convert["SLUG*FT2"]["KG*M2"] = 1.35594; + convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"]; + // Angles + convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926); + convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"]; + // Angular rates + convert["RAD/SEC"]["DEG/SEC"] = 360.0/(2.0*3.1415926); + convert["DEG/SEC"]["RAD/SEC"] = 1.0/convert["RAD/SEC"]["DEG/SEC"]; + // Spring force + convert["LBS/FT"]["N/M"] = 14.5939; + convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"]; + // Damping force + convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939; + convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"]; + // Damping force (Square Law) + convert["LBS/FT2/SEC2"]["N/M2/SEC2"] = 47.880259; + convert["N/M2/SEC2"]["LBS/FT2/SEC2"] = 1.0/convert["LBS/FT2/SEC2"]["N/M2/SEC2"]; + // Power + convert["WATTS"]["HP"] = 0.001341022; + convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"]; + // Force + convert["N"]["LBS"] = 0.22482; + convert["LBS"]["N"] = 1.0/convert["N"]["LBS"]; + // Velocity + convert["KTS"]["FT/SEC"] = 1.68781; + convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"]; + convert["M/S"]["FT/S"] = 3.2808399; + convert["M/SEC"]["FT/SEC"] = 3.2808399; + convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"]; + convert["M/SEC"]["FT/SEC"] = 3.2808399; + convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"]; + // Torque + convert["FT*LBS"]["N*M"] = 1.35581795; + convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"]; + // Valve + convert["M4*SEC/KG"]["FT4*SEC/SLUG"] = convert["M"]["FT"]*convert["M"]["FT"]* + convert["M"]["FT"]*convert["M"]["FT"]/convert["KG"]["SLUG"]; + convert["FT4*SEC/SLUG"]["M4*SEC/KG"] = + 1.0/convert["M4*SEC/KG"]["FT4*SEC/SLUG"]; + // Pressure + convert["INHG"]["PSF"] = 70.7180803; + convert["PSF"]["INHG"] = 1.0/convert["INHG"]["PSF"]; + convert["ATM"]["INHG"] = 29.9246899; + convert["INHG"]["ATM"] = 1.0/convert["ATM"]["INHG"]; + convert["PSI"]["INHG"] = 2.03625437; + convert["INHG"]["PSI"] = 1.0/convert["PSI"]["INHG"]; + convert["INHG"]["PA"] = 3386.0; // inches Mercury to pascals + convert["PA"]["INHG"] = 1.0/convert["INHG"]["PA"]; + convert["LBS/FT2"]["N/M2"] = 14.5939/convert["FT"]["M"]; + convert["N/M2"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["N/M2"]; + convert["LBS/FT2"]["PA"] = convert["LBS/FT2"]["N/M2"]; + convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"]; + // Mass flow + convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"]; + // Fuel Consumption + convert["LBS/HP*HR"]["KG/KW*HR"] = 0.6083; + convert["KG/KW*HR"]["LBS/HP*HR"] = 1.0/convert["LBS/HP*HR"]["KG/KW*HR"]; + // Density + convert["KG/L"]["LBS/GAL"] = 8.3454045; + convert["LBS/GAL"]["KG/L"] = 1.0/convert["KG/L"]["LBS/GAL"]; + + // Length + convert["M"]["M"] = 1.00; + convert["FT"]["FT"] = 1.00; + convert["IN"]["IN"] = 1.00; + // Area + convert["M2"]["M2"] = 1.00; + convert["FT2"]["FT2"] = 1.00; + // Volume + convert["IN3"]["IN3"] = 1.00; + convert["CC"]["CC"] = 1.0; + convert["M3"]["M3"] = 1.0; + convert["FT3"]["FT3"] = 1.0; + convert["LTR"]["LTR"] = 1.0; + // Mass & Weight + convert["KG"]["KG"] = 1.00; + convert["LBS"]["LBS"] = 1.00; + // Moments of Inertia + convert["KG*M2"]["KG*M2"] = 1.00; + convert["SLUG*FT2"]["SLUG*FT2"] = 1.00; + // Angles + convert["DEG"]["DEG"] = 1.00; + convert["RAD"]["RAD"] = 1.00; + // Angular rates + convert["DEG/SEC"]["DEG/SEC"] = 1.00; + convert["RAD/SEC"]["RAD/SEC"] = 1.00; + // Spring force + convert["LBS/FT"]["LBS/FT"] = 1.00; + convert["N/M"]["N/M"] = 1.00; + // Damping force + convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00; + convert["N/M/SEC"]["N/M/SEC"] = 1.00; + // Damping force (Square law) + convert["LBS/FT2/SEC2"]["LBS/FT2/SEC2"] = 1.00; + convert["N/M2/SEC2"]["N/M2/SEC2"] = 1.00; + // Power + convert["HP"]["HP"] = 1.00; + convert["WATTS"]["WATTS"] = 1.00; + // Force + convert["N"]["N"] = 1.00; + // Velocity + convert["FT/SEC"]["FT/SEC"] = 1.00; + convert["KTS"]["KTS"] = 1.00; + convert["M/S"]["M/S"] = 1.0; + convert["M/SEC"]["M/SEC"] = 1.0; + // Torque + convert["FT*LBS"]["FT*LBS"] = 1.00; + convert["N*M"]["N*M"] = 1.00; + // Valve + convert["M4*SEC/KG"]["M4*SEC/KG"] = 1.0; + convert["FT4*SEC/SLUG"]["FT4*SEC/SLUG"] = 1.0; + // Pressure + convert["PSI"]["PSI"] = 1.00; + convert["PSF"]["PSF"] = 1.00; + convert["INHG"]["INHG"] = 1.00; + convert["ATM"]["ATM"] = 1.0; + convert["PA"]["PA"] = 1.0; + convert["N/M2"]["N/M2"] = 1.00; + convert["LBS/FT2"]["LBS/FT2"] = 1.00; + // Mass flow + convert["LBS/SEC"]["LBS/SEC"] = 1.00; + convert["KG/MIN"]["KG/MIN"] = 1.0; + convert["LBS/MIN"]["LBS/MIN"] = 1.0; + // Fuel Consumption + convert["LBS/HP*HR"]["LBS/HP*HR"] = 1.0; + convert["KG/KW*HR"]["KG/KW*HR"] = 1.0; + // Density + convert["KG/L"]["KG/L"] = 1.0; + convert["LBS/GAL"]["LBS/GAL"] = 1.0; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Element::~Element(void) { - for (unsigned int i=0; i<children.size(); i++) delete children[i]; - data_lines.clear(); - attributes.clear(); - attribute_key.clear(); + for (unsigned int i=0; i<children.size(); i++) delete children[i]; + data_lines.clear(); + attributes.clear(); + attribute_key.clear(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string Element::GetAttributeValue(const string& attr) { - int select=-1; - for (unsigned int i=0; i<attribute_key.size(); i++) - { - if (attribute_key[i] == attr) select = i; - } - if (select < 0) return string(""); - else return attributes[attr]; + int select=-1; + for (unsigned int i=0; i<attribute_key.size(); i++) { + if (attribute_key[i] == attr) select = i; + } + if (select < 0) return string(""); + else return attributes[attr]; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double Element::GetAttributeValueAsNumber(const string& attr) { - string attribute = GetAttributeValue(attr); + string attribute = GetAttributeValue(attr); - if (attribute.empty()) return HUGE_VAL; - else return (atof(attribute.c_str())); + if (attribute.empty()) return HUGE_VAL; + else return (atof(attribute.c_str())); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Element* Element::GetElement(unsigned int el) { - if (children.size() > el) - { - element_index = el; - return children[el]; - } - else - { - element_index = 0; - return 0L; - } + if (children.size() > el) { + element_index = el; + return children[el]; + } + else { + element_index = 0; + return 0L; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Element* Element::GetNextElement(void) { - if (children.size() > element_index+1) - { - element_index++; - return children[element_index]; - } - else - { - element_index = 0; - return 0L; - } + if (children.size() > element_index+1) { + element_index++; + return children[element_index]; + } else { + element_index = 0; + return 0L; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string Element::GetDataLine(unsigned int i) { - if (data_lines.size() > 0) return data_lines[i]; - else return string(""); + if (data_lines.size() > 0) return data_lines[i]; + else return string(""); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double Element::GetDataAsNumber(void) { - if (data_lines.size() == 1) - { - return atof(data_lines[0].c_str()); - } - else if (data_lines.size() == 0) - { - return HUGE_VAL; - } - else - { - cerr << "Attempting to get single data value from multiple lines in element " << name << endl; - return HUGE_VAL; - } + if (data_lines.size() == 1) { + return atof(data_lines[0].c_str()); + } else if (data_lines.size() == 0) { + return HUGE_VAL; + } else { + cerr << "Attempting to get single data value from multiple lines in element " << name << endl; + return HUGE_VAL; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% unsigned int Element::GetNumElements(const string& element_name) { - unsigned int number_of_elements=0; - Element* el=FindElement(element_name); - while (el) - { - number_of_elements++; - el=FindNextElement(element_name); - } - return number_of_elements; + unsigned int number_of_elements=0; + Element* el=FindElement(element_name); + while (el) { + number_of_elements++; + el=FindNextElement(element_name); + } + return number_of_elements; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Element* Element::FindElement(const string& el) { - if (el.empty() && children.size() >= 1) - { - element_index = 1; - return children[0]; - } - for (unsigned int i=0; i<children.size(); i++) - { - if (el == children[i]->GetName()) - { - element_index = i+1; - return children[i]; - } - } - element_index = 0; - return 0L; + if (el.empty() && children.size() >= 1) { + element_index = 1; + return children[0]; + } + for (unsigned int i=0; i<children.size(); i++) { + if (el == children[i]->GetName()) { + element_index = i+1; + return children[i]; + } + } + element_index = 0; + return 0L; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Element* Element::FindNextElement(const string& el) { - if (el.empty()) - { - if (element_index < children.size()) - { - return children[element_index++]; - } - else - { - element_index = 0; - return 0L; - } - } - for (unsigned int i=element_index; i<children.size(); i++) - { - if (el == children[i]->GetName()) - { - element_index = i+1; - return children[i]; - } - } - element_index = 0; - return 0L; + if (el.empty()) { + if (element_index < children.size()) { + return children[element_index++]; + } else { + element_index = 0; + return 0L; + } + } + for (unsigned int i=element_index; i<children.size(); i++) { + if (el == children[i]->GetName()) { + element_index = i+1; + return children[i]; + } + } + element_index = 0; + return 0L; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double Element::FindElementValueAsNumber(const string& el) { - Element* element = FindElement(el); - if (element) - { - return element->GetDataAsNumber(); - } - else - { - cerr << "Attempting to get single data value from multiple lines" << endl; - return 0; - } + Element* element = FindElement(el); + if (element) { + return element->GetDataAsNumber(); + } else { + cerr << "Attempting to get single data value from multiple lines" << endl; + return 0; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string Element::FindElementValue(const string& el) { - Element* element = FindElement(el); - if (element) - { - return element->GetDataLine(); - } - else - { - return ""; - } + Element* element = FindElement(el); + if (element) { + return element->GetDataLine(); + } else { + return ""; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double Element::FindElementValueAsNumberConvertTo(const string& el, const string& target_units) { - Element* element = FindElement(el); + Element* element = FindElement(el); - if (!element) - { - cerr << "Attempting to get non-existent element " << el << endl; - exit(0); - } + if (!element) { + cerr << "Attempting to get non-existent element " << el << endl; + exit(0); + } - string supplied_units = element->GetAttributeValue("unit"); - - if (!supplied_units.empty()) - { - if (convert.find(supplied_units) == convert.end()) - { - cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit" - << " conversion in FGXMLElement.cpp." << endl; - exit(-1); - } - if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) - { - cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " - << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl; - exit(-1); - } - } + string supplied_units = element->GetAttributeValue("unit"); - double value = element->GetDataAsNumber(); - if (!supplied_units.empty()) - { - value *= convert[supplied_units][target_units]; + if (!supplied_units.empty()) { + if (convert.find(supplied_units) == convert.end()) { + cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit" + << " conversion in FGXMLElement.cpp." << endl; + exit(-1); + } + if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) { + cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " + << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl; + exit(-1); } + } - return value; + double value = element->GetDataAsNumber(); + if (!supplied_units.empty()) { + value *= convert[supplied_units][target_units]; + } + + return value; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double Element::FindElementValueAsNumberConvertFromTo( const string& el, - const string& supplied_units, - const string& target_units) + const string& supplied_units, + const string& target_units) { - Element* element = FindElement(el); + Element* element = FindElement(el); - if (!element) - { - cerr << "Attempting to get non-existent element " << el << endl; - exit(0); - } + if (!element) { + cerr << "Attempting to get non-existent element " << el << endl; + exit(0); + } - if (!supplied_units.empty()) - { - if (convert.find(supplied_units) == convert.end()) - { - cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit" - << " conversion in FGXMLElement.cpp." << endl; - exit(-1); - } - if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) - { - cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " - << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl; - exit(-1); - } + if (!supplied_units.empty()) { + if (convert.find(supplied_units) == convert.end()) { + cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit" + << " conversion in FGXMLElement.cpp." << endl; + exit(-1); } - - double value = element->GetDataAsNumber(); - if (!supplied_units.empty()) - { - value *= convert[supplied_units][target_units]; + if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) { + cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " + << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl; + exit(-1); } + } - return value; + double value = element->GetDataAsNumber(); + if (!supplied_units.empty()) { + value *= convert[supplied_units][target_units]; + } + + return value; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3 Element::FindElementTripletConvertTo( const string& target_units) { - FGColumnVector3 triplet; - Element* item; - double value=0.0; - string supplied_units = GetAttributeValue("unit"); - - if (!supplied_units.empty()) - { - if (convert.find(supplied_units) == convert.end()) - { - cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit" - << " conversion in FGXMLElement.cpp." << endl; - exit(-1); - } - if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) - { - cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " - << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl; - exit(-1); - } - } - - item = FindElement("x"); - if (!item) item = FindElement("roll"); - if (item) - { - value = item->GetDataAsNumber(); - if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; - } - else - { - value = 0.0; - cerr << "Could not find an X triplet item for this column vector." << endl; - } - triplet(1) = value; - - item = FindElement("y"); - if (!item) item = FindElement("pitch"); - if (item) - { - value = item->GetDataAsNumber(); - if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; - } - else - { - value = 0.0; - cerr << "Could not find a Y triplet item for this column vector." << endl; - } - triplet(2) = value; - - item = FindElement("z"); - if (!item) item = FindElement("yaw"); - if (item) - { - value = item->GetDataAsNumber(); - if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; - } - else - { - value = 0.0; - cerr << "Could not find a Z triplet item for this column vector." << endl; - } - triplet(3) = value; - - return triplet; + FGColumnVector3 triplet; + Element* item; + double value=0.0; + string supplied_units = GetAttributeValue("unit"); + + if (!supplied_units.empty()) { + if (convert.find(supplied_units) == convert.end()) { + cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit" + << " conversion in FGXMLElement.cpp." << endl; + exit(-1); + } + if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) { + cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " + << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl; + exit(-1); + } + } + + item = FindElement("x"); + if (!item) item = FindElement("roll"); + if (item) { + value = item->GetDataAsNumber(); + if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; + } else { + value = 0.0; + cerr << "Could not find an X triplet item for this column vector." << endl; + } + triplet(1) = value; + + item = FindElement("y"); + if (!item) item = FindElement("pitch"); + if (item) { + value = item->GetDataAsNumber(); + if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; + } else { + value = 0.0; + cerr << "Could not find a Y triplet item for this column vector." << endl; + } + triplet(2) = value; + + item = FindElement("z"); + if (!item) item = FindElement("yaw"); + if (item) { + value = item->GetDataAsNumber(); + if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; + } else { + value = 0.0; + cerr << "Could not find a Z triplet item for this column vector." << endl; + } + triplet(3) = value; + + return triplet; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void Element::Print(unsigned int level) { - unsigned int i, spaces; - - level+=2; + unsigned int i, spaces; + + level+=2; + for (spaces=0; spaces<=level; spaces++) cout << " "; // format output + cout << "Element Name: " << name; + for (i=0; i<attributes.size(); i++) { + cout << " " << attribute_key[i] << " = " << attributes[attribute_key[i]]; + } + cout << endl; + for (i=0; i<data_lines.size(); i++) { for (spaces=0; spaces<=level; spaces++) cout << " "; // format output - cout << "Element Name: " << name; - for (i=0; i<attributes.size(); i++) - { - cout << " " << attribute_key[i] << " = " << attributes[attribute_key[i]]; - } - cout << endl; - for (i=0; i<data_lines.size(); i++) - { - for (spaces=0; spaces<=level; spaces++) cout << " "; // format output - cout << data_lines[i] << endl; - } - for (i=0; i<children.size(); i++) - { - children[i]->Print(level); - } + cout << data_lines[i] << endl; + } + for (i=0; i<children.size(); i++) { + children[i]->Print(level); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void Element::AddAttribute(const string& name, const string& value) { - attribute_key.push_back(name); - attributes[name] = value; + attribute_key.push_back(name); + attributes[name] = value; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void Element::AddData(string d) { - string::size_type string_start = d.find_first_not_of(" \t"); - if (string_start != string::npos && string_start > 0) - { - d.erase(0,string_start); - } - data_lines.push_back(d); + string::size_type string_start = d.find_first_not_of(" \t"); + if (string_start != string::npos && string_start > 0) { + d.erase(0,string_start); + } + data_lines.push_back(d); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/input_output/FGXMLElement.h b/src/input_output/FGXMLElement.h old mode 100644 new mode 100755 index 7d1bd7c6bb539ba5223acc65cf255fc5ff3c1215..21af97275d2251a8af575465723b0ab2e57ddcd5 --- a/src/input_output/FGXMLElement.h +++ b/src/input_output/FGXMLElement.h @@ -50,8 +50,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -134,7 +133,7 @@ CLASS DOCUMENTATION - HP = horsepower - HR = hour - L = liter - - GAL = gallon (U.S. liquid) + - GAL = gallon (U.S. liquid) @author Jon S. Berndt @version $Id: FGXMLElement.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $ @@ -144,217 +143,198 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class Element -{ +class Element { public: - /** Constructor - @param nm the name of this element (if given) - */ - Element(const std::string& nm); - /// Destructor - ~Element(void); - - /** Retrieves an attribute. - @param key specifies the attribute key to retrieve the value of. - @return the key value (as a string), or the empty string if no such - attribute exists. */ - std::string GetAttributeValue(const std::string& key); - - /** Retrieves an attribute value as a double precision real number. - @param key specifies the attribute key to retrieve the value of. - @return the key value (as a number), or the HUGE_VAL if no such - attribute exists. */ - double GetAttributeValueAsNumber(const std::string& key); - - /** Retrieves the element name. - @return the element name, or the empty string if no name has been set.*/ - const std::string& GetName(void) const - { - return name; - } - - /** Gets a line of data belonging to an element. - @param i the index of the data line to return (0 by default). - @return a string representing the data line requested, or the empty string - if none exists.*/ - std::string GetDataLine(unsigned int i=0); - - /// Returns the number of lines of data stored - unsigned int GetNumDataLines(void) - { - return (unsigned int)data_lines.size(); - } - - /// Returns the number of child elements for this element. - unsigned int GetNumElements(void) - { - return (unsigned int)children.size(); - } - - /// Returns the number of named child elements for this element. - unsigned int GetNumElements(const std::string& element_name); - - /** Converts the element data to a number. - This function attempts to convert the first (and presumably only) line of - data "owned" by the element into a real number. If there is not exactly one - line of data owned by the element, then HUGE_VAL is returned. - @return the numeric value of the data owned by the element.*/ - double GetDataAsNumber(void); - - /** Returns a pointer to the element requested by index. - This function also resets an internal counter to the index, so that - subsequent calls to GetNextElement() will return the following - elements sequentially, until the last element is reached. At that point, - GetNextElement() will return NULL. - @param el the index of the requested element (0 by default) - @return a pointer to the Element, or 0 if no valid element exists. */ - Element* GetElement(unsigned int el=0); - - /** Returns a pointer to the next element in the list. - The function GetElement() must be called first to be sure that this - function will return the correct element. The call to GetElement() resets - the internal counter to zero. Subsequent calls to GetNextElement() return - a pointer to subsequent elements in the list. When the final element is - reached, 0 is returned. - @return a pointer to the next Element in the sequence, or 0 if no valid - Element is present. */ - Element* GetNextElement(void); - - /** Returns a pointer to the parent of an element. - @return a pointer to the parent Element, or 0 if this is the top level Element. */ - Element* GetParent(void) - { - return parent; - } - - /** Searches for a specified element. - Finds the first element that matches the supplied string, or simply the first - element if no search string is supplied. This function call resets the internal - element counter to the first element. - @param el the search string (empty string by default). - @return a pointer to the first element that matches the supplied search string. */ - Element* FindElement(const std::string& el=""); - - /** Searches for the next element as specified. - This function would be called after FindElement() is first called (in order to - reset the internal counter). If no argument is supplied (or the empty string) - a pointer to the very next element is returned. Otherwise, the next occurence - of the named element is returned. If the end of the list is reached, 0 is - returned. - @param el the name of the next element to find. - @return the pointer to the found element, or 0 if no appropriate element us - found.*/ - Element* FindNextElement(const std::string& el=""); - - /** Searches for the named element and returns the string data belonging to it. - This function allows the data belonging to a named element to be returned - as a string. If no element is found, the empty string is returned. If no - argument is supplied, the data string for the first element is returned. - @param el the name of the element being searched for (the empty string by - default) - @return the data value for the named element as a string, or the empty - string if the element cannot be found. */ - std::string FindElementValue(const std::string& el=""); - - /** Searches for the named element and returns the data belonging to it as a number. - This function allows the data belonging to a named element to be returned - as a double. If no element is found, HUGE_VAL is returned. If no - argument is supplied, the data for the first element is returned. - @param el the name of the element being searched for (the empty string by - default) - @return the data value for the named element as a double, or HUGE_VAL if the - data is missing. */ - double FindElementValueAsNumber(const std::string& el=""); - - /** Searches for the named element and converts and returns the data belonging to it. - This function allows the data belonging to a named element to be returned - as a double. If no element is found, HUGE_VAL is returned. If no - argument is supplied, the data for the first element is returned. Additionally, - this function converts the value from the units specified in the config file (via - the UNITS="" attribute in the element definition) to the native units used by - JSBSim itself, as specified by the target_units parameter. The currently - allowable unit conversions are seen in the source file FGXMLElement.cpp. - Also, see above in the main documentation for this class. - @param el the name of the element being searched for (the empty string by - default) - @param target_units the string representing the native units used by JSBSim - to which the value returned will be converted. - @return the unit-converted data value for the named element as a double, - or HUGE_VAL if the data is missing. */ - double FindElementValueAsNumberConvertTo(const std::string& el, const std::string& target_units); - - /** Searches for the named element and converts and returns the data belonging to it. - This function allows the data belonging to a named element to be returned - as a double. If no element is found, HUGE_VAL is returned. If no - argument is supplied, the data for the first element is returned. Additionally, - this function converts the value from the units specified in the supplied_units - parameter to the units specified in the target_units parameter. JSBSim itself, - as specified by the target_units parameter. The currently allowable unit - conversions are seen in the source file FGXMLElement.cpp. Also, see above - in the main documentation for this class. - @param el the name of the element being searched for (the empty string by - default) - @param supplied_units the string representing the units of the value as - supplied by the config file. - @param target_units the string representing the native units used by JSBSim - to which the value returned will be converted. - @return the unit-converted data value for the named element as a double, - or HUGE_VAL if the data is missing. */ - double FindElementValueAsNumberConvertFromTo( const std::string& el, - const std::string& supplied_units, - const std::string& target_units); - - /** Composes a 3-element column vector for the supplied location or orientation. - This function processes a LOCATION or ORIENTATION construct, returning a - filled-out 3-element column vector containing the X, Y, Z or ROLL, PITCH, - YAW elements found in the supplied element. If one of the mentioned components - is not found, that component is set to zero and a warning message is printed. - All three elements should be supplied. - @param target_units the string representing the native units used by JSBSim - to which the value returned will be converted. - @return a column vector object built from the LOCATION or ORIENT components. */ - FGColumnVector3 FindElementTripletConvertTo( const std::string& target_units); - - /** This function sets the value of the parent class attribute to the supplied - Element pointer. - @param p pointer to the parent Element. */ - void SetParent(Element* p) - { - parent = p; - } - - /** Adds a child element to the list of children stored for this element. - * @param el Child element to add. */ - void AddChildElement(Element* el) - { - children.push_back(el); - } - - /** Stores an attribute belonging to this element. - * @param name The string name of the attribute. - * @param value The string value of the attribute. */ - void AddAttribute(const std::string& name, const std::string& value); - - /** Stores data belonging to this element. - * @param d the data to store. */ - void AddData(std::string d); - - /** Prints the element. - * Prints this element and calls the Print routine for child elements. - * @param d The tab level. A level corresponds to a single space. */ - void Print(unsigned int level=0); + /** Constructor + @param nm the name of this element (if given) + */ + Element(const std::string& nm); + /// Destructor + ~Element(void); + + /** Retrieves an attribute. + @param key specifies the attribute key to retrieve the value of. + @return the key value (as a string), or the empty string if no such + attribute exists. */ + std::string GetAttributeValue(const std::string& key); + + /** Retrieves an attribute value as a double precision real number. + @param key specifies the attribute key to retrieve the value of. + @return the key value (as a number), or the HUGE_VAL if no such + attribute exists. */ + double GetAttributeValueAsNumber(const std::string& key); + + /** Retrieves the element name. + @return the element name, or the empty string if no name has been set.*/ + const std::string& GetName(void) const {return name;} + + /** Gets a line of data belonging to an element. + @param i the index of the data line to return (0 by default). + @return a string representing the data line requested, or the empty string + if none exists.*/ + std::string GetDataLine(unsigned int i=0); + + /// Returns the number of lines of data stored + unsigned int GetNumDataLines(void) {return (unsigned int)data_lines.size();} + + /// Returns the number of child elements for this element. + unsigned int GetNumElements(void) {return (unsigned int)children.size();} + + /// Returns the number of named child elements for this element. + unsigned int GetNumElements(const std::string& element_name); + + /** Converts the element data to a number. + This function attempts to convert the first (and presumably only) line of + data "owned" by the element into a real number. If there is not exactly one + line of data owned by the element, then HUGE_VAL is returned. + @return the numeric value of the data owned by the element.*/ + double GetDataAsNumber(void); + + /** Returns a pointer to the element requested by index. + This function also resets an internal counter to the index, so that + subsequent calls to GetNextElement() will return the following + elements sequentially, until the last element is reached. At that point, + GetNextElement() will return NULL. + @param el the index of the requested element (0 by default) + @return a pointer to the Element, or 0 if no valid element exists. */ + Element* GetElement(unsigned int el=0); + + /** Returns a pointer to the next element in the list. + The function GetElement() must be called first to be sure that this + function will return the correct element. The call to GetElement() resets + the internal counter to zero. Subsequent calls to GetNextElement() return + a pointer to subsequent elements in the list. When the final element is + reached, 0 is returned. + @return a pointer to the next Element in the sequence, or 0 if no valid + Element is present. */ + Element* GetNextElement(void); + + /** Returns a pointer to the parent of an element. + @return a pointer to the parent Element, or 0 if this is the top level Element. */ + Element* GetParent(void) {return parent;} + + /** Searches for a specified element. + Finds the first element that matches the supplied string, or simply the first + element if no search string is supplied. This function call resets the internal + element counter to the first element. + @param el the search string (empty string by default). + @return a pointer to the first element that matches the supplied search string. */ + Element* FindElement(const std::string& el=""); + + /** Searches for the next element as specified. + This function would be called after FindElement() is first called (in order to + reset the internal counter). If no argument is supplied (or the empty string) + a pointer to the very next element is returned. Otherwise, the next occurence + of the named element is returned. If the end of the list is reached, 0 is + returned. + @param el the name of the next element to find. + @return the pointer to the found element, or 0 if no appropriate element us + found.*/ + Element* FindNextElement(const std::string& el=""); + + /** Searches for the named element and returns the string data belonging to it. + This function allows the data belonging to a named element to be returned + as a string. If no element is found, the empty string is returned. If no + argument is supplied, the data string for the first element is returned. + @param el the name of the element being searched for (the empty string by + default) + @return the data value for the named element as a string, or the empty + string if the element cannot be found. */ + std::string FindElementValue(const std::string& el=""); + + /** Searches for the named element and returns the data belonging to it as a number. + This function allows the data belonging to a named element to be returned + as a double. If no element is found, HUGE_VAL is returned. If no + argument is supplied, the data for the first element is returned. + @param el the name of the element being searched for (the empty string by + default) + @return the data value for the named element as a double, or HUGE_VAL if the + data is missing. */ + double FindElementValueAsNumber(const std::string& el=""); + + /** Searches for the named element and converts and returns the data belonging to it. + This function allows the data belonging to a named element to be returned + as a double. If no element is found, HUGE_VAL is returned. If no + argument is supplied, the data for the first element is returned. Additionally, + this function converts the value from the units specified in the config file (via + the UNITS="" attribute in the element definition) to the native units used by + JSBSim itself, as specified by the target_units parameter. The currently + allowable unit conversions are seen in the source file FGXMLElement.cpp. + Also, see above in the main documentation for this class. + @param el the name of the element being searched for (the empty string by + default) + @param target_units the string representing the native units used by JSBSim + to which the value returned will be converted. + @return the unit-converted data value for the named element as a double, + or HUGE_VAL if the data is missing. */ + double FindElementValueAsNumberConvertTo(const std::string& el, const std::string& target_units); + + /** Searches for the named element and converts and returns the data belonging to it. + This function allows the data belonging to a named element to be returned + as a double. If no element is found, HUGE_VAL is returned. If no + argument is supplied, the data for the first element is returned. Additionally, + this function converts the value from the units specified in the supplied_units + parameter to the units specified in the target_units parameter. JSBSim itself, + as specified by the target_units parameter. The currently allowable unit + conversions are seen in the source file FGXMLElement.cpp. Also, see above + in the main documentation for this class. + @param el the name of the element being searched for (the empty string by + default) + @param supplied_units the string representing the units of the value as + supplied by the config file. + @param target_units the string representing the native units used by JSBSim + to which the value returned will be converted. + @return the unit-converted data value for the named element as a double, + or HUGE_VAL if the data is missing. */ + double FindElementValueAsNumberConvertFromTo( const std::string& el, + const std::string& supplied_units, + const std::string& target_units); + + /** Composes a 3-element column vector for the supplied location or orientation. + This function processes a LOCATION or ORIENTATION construct, returning a + filled-out 3-element column vector containing the X, Y, Z or ROLL, PITCH, + YAW elements found in the supplied element. If one of the mentioned components + is not found, that component is set to zero and a warning message is printed. + All three elements should be supplied. + @param target_units the string representing the native units used by JSBSim + to which the value returned will be converted. + @return a column vector object built from the LOCATION or ORIENT components. */ + FGColumnVector3 FindElementTripletConvertTo( const std::string& target_units); + + /** This function sets the value of the parent class attribute to the supplied + Element pointer. + @param p pointer to the parent Element. */ + void SetParent(Element* p) {parent = p;} + + /** Adds a child element to the list of children stored for this element. + * @param el Child element to add. */ + void AddChildElement(Element* el) {children.push_back(el);} + + /** Stores an attribute belonging to this element. + * @param name The string name of the attribute. + * @param value The string value of the attribute. */ + void AddAttribute(const std::string& name, const std::string& value); + + /** Stores data belonging to this element. + * @param d the data to store. */ + void AddData(std::string d); + + /** Prints the element. + * Prints this element and calls the Print routine for child elements. + * @param d The tab level. A level corresponds to a single space. */ + void Print(unsigned int level=0); private: - std::string name; - std::map <std::string, std::string> attributes; - std::vector <std::string> data_lines; - std::vector <Element*> children; - std::vector <std::string> attribute_key; - Element *parent; - unsigned int element_index; - typedef std::map <std::string, std::map <std::string, double> > tMapConvert; - static tMapConvert convert; - static bool converterIsInitialized; + std::string name; + std::map <std::string, std::string> attributes; + std::vector <std::string> data_lines; + std::vector <Element*> children; + std::vector <std::string> attribute_key; + Element *parent; + unsigned int element_index; + typedef std::map <std::string, std::map <std::string, double> > tMapConvert; + static tMapConvert convert; + static bool converterIsInitialized; }; } // namespace JSBSim diff --git a/src/input_output/FGXMLFileRead.h b/src/input_output/FGXMLFileRead.h old mode 100644 new mode 100755 index 62f0a4d992cc6ad9bff759da335d44abe1910445..d7366db7c996745e7eb34ab728564e50b908f6e9 --- a/src/input_output/FGXMLFileRead.h +++ b/src/input_output/FGXMLFileRead.h @@ -49,51 +49,42 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { -class FGXMLFileRead -{ +class FGXMLFileRead { public: - FGXMLFileRead(void) {} - ~FGXMLFileRead(void) {} + FGXMLFileRead(void) {} + ~FGXMLFileRead(void) {} protected: - Element* document; - Element* LoadXMLDocument(std::string XML_filename) - { - std::ifstream infile; - - if ( !XML_filename.empty() ) - { - if (XML_filename.find(".xml") == std::string::npos) XML_filename += ".xml"; - infile.open(XML_filename.c_str()); - if ( !infile.is_open()) - { - std::cerr << "Could not open file: " << XML_filename << std::endl; - return 0L; - } - } - else - { - std::cerr << "No filename given." << std::endl; - return 0L; - } - - readXML(infile, file_parser, XML_filename); - document = file_parser.GetDocument(); - infile.close(); - - return document; + Element* document; + Element* LoadXMLDocument(std::string XML_filename) + { + std::ifstream infile; + + if ( !XML_filename.empty() ) { + if (XML_filename.find(".xml") == std::string::npos) XML_filename += ".xml"; + infile.open(XML_filename.c_str()); + if ( !infile.is_open()) { + std::cerr << "Could not open file: " << XML_filename << std::endl; + return 0L; + } + } else { + std::cerr << "No filename given." << std::endl; + return 0L; } - void ResetParser(void) - { - file_parser.reset(); - } + readXML(infile, file_parser, XML_filename); + document = file_parser.GetDocument(); + infile.close(); + + return document; + } + + void ResetParser(void) {file_parser.reset();} private: - FGXMLParse file_parser; + FGXMLParse file_parser; }; } #endif diff --git a/src/input_output/FGXMLParse.cpp b/src/input_output/FGXMLParse.cpp old mode 100644 new mode 100755 index c07675f2979661252b84a76318f685f583582583..90fe0e7b90d7b7b5882cb4b384ea66139de0c332 --- a/src/input_output/FGXMLParse.cpp +++ b/src/input_output/FGXMLParse.cpp @@ -38,8 +38,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGXMLParse.cpp,v 1.10 2009/10/24 22:59:30 jberndt Exp $"; static const char *IdHdr = ID_XMLPARSE; @@ -54,15 +53,15 @@ using namespace std; FGXMLParse::FGXMLParse(void) { - first_element_read = false; - current_element = document = 0L; + first_element_read = false; + current_element = document = 0L; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGXMLParse::~FGXMLParse(void) { - delete document; + delete document; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -75,71 +74,65 @@ void FGXMLParse::startXML(void) void FGXMLParse::reset(void) { - delete document; - first_element_read = false; - current_element = document = 0L; + delete document; + first_element_read = false; + current_element = document = 0L; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGXMLParse::endXML(void) { - // At this point, document should equal current_element ? + // At this point, document should equal current_element ? } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGXMLParse::startElement (const char * name, const XMLAttributes &atts) { - string Name(name); - Element *temp_element; - - working_string.erase(); - - if (!first_element_read) - { - document = new Element(Name); - current_element = document; - first_element_read = true; - } - else - { - temp_element = new Element(Name); - temp_element->SetParent(current_element); - current_element->AddChildElement(temp_element); - current_element = temp_element; - } - - if (current_element == 0L) - { - cerr << "No current element read (no top-level element in XML file?)" << endl; - exit (-1); - } - - for (int i=0; i<atts.size();i++) - { - current_element->AddAttribute(atts.getName(i), atts.getValue(i)); - } + string Name(name); + Element *temp_element; + + working_string.erase(); + + if (!first_element_read) { + document = new Element(Name); + current_element = document; + first_element_read = true; + } else { + temp_element = new Element(Name); + temp_element->SetParent(current_element); + current_element->AddChildElement(temp_element); + current_element = temp_element; + } + + if (current_element == 0L) { + cerr << "No current element read (no top-level element in XML file?)" << endl; + exit (-1); + } + + for (int i=0; i<atts.size();i++) { + current_element->AddAttribute(atts.getName(i), atts.getValue(i)); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGXMLParse::endElement (const char * name) { - if (!working_string.empty()) - { - vector <string> work_strings = split(working_string, '\n'); - for (int i=0; i<work_strings.size(); i++) current_element->AddData(work_strings[i]); - } + if (!working_string.empty()) { + vector <string> work_strings = split(working_string, '\n'); + for (int i=0; i<work_strings.size(); i++) current_element->AddData(work_strings[i]); + } - current_element = current_element->GetParent(); + current_element = current_element->GetParent(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGXMLParse::data (const char * s, int length) { - working_string += string(s, length); + working_string += string(s, length); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -152,7 +145,7 @@ void FGXMLParse::pi (const char * target, const char * data) void FGXMLParse::warning (const char * message, int line, int column) { - cerr << "Warning: " << message << " line: " << line << " column: " << column << endl; + cerr << "Warning: " << message << " line: " << line << " column: " << column << endl; } } // end namespace JSBSim diff --git a/src/input_output/FGXMLParse.h b/src/input_output/FGXMLParse.h old mode 100644 new mode 100755 index 3528d042f637f226d761fa4254f82025ada469a8..350e3e6a7894c01918f59e132dbc422bdba834cc --- a/src/input_output/FGXMLParse.h +++ b/src/input_output/FGXMLParse.h @@ -47,8 +47,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class Element; @@ -68,28 +67,25 @@ CLASS DECLARATION class FGXMLParse : public XMLVisitor { public: - FGXMLParse(void); - virtual ~FGXMLParse(void); - - Element* GetDocument(void) - { - return document; - } - - void startXML(); - void endXML(); - void startElement (const char * name, const XMLAttributes &atts); - void endElement (const char * name); - void data (const char * s, int length); - void pi (const char * target, const char * data); - void warning (const char * message, int line, int column); - void reset(void); + FGXMLParse(void); + virtual ~FGXMLParse(void); + + Element* GetDocument(void) {return document;} + + void startXML(); + void endXML(); + void startElement (const char * name, const XMLAttributes &atts); + void endElement (const char * name); + void data (const char * s, int length); + void pi (const char * target, const char * data); + void warning (const char * message, int line, int column); + void reset(void); private: - bool first_element_read; - mutable string working_string; - Element *document; - Element *current_element; + bool first_element_read; + mutable string working_string; + Element *document; + Element *current_element; }; } // namespace JSBSim diff --git a/src/input_output/FGfdmSocket.cpp b/src/input_output/FGfdmSocket.cpp index fa354d793ba3b391104bd89116d6540e0ac7eeac..d1edb67394876a630d64a7fd39311f8437d78143 100644 --- a/src/input_output/FGfdmSocket.cpp +++ b/src/input_output/FGfdmSocket.cpp @@ -50,8 +50,7 @@ using std::cerr; using std::endl; using std::string; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGfdmSocket.cpp,v 1.27 2010/05/13 03:07:59 jberndt Exp $"; static const char *IdHdr = ID_FDMSOCKET; @@ -62,340 +61,294 @@ CLASS IMPLEMENTATION FGfdmSocket::FGfdmSocket(const string& address, int port, int protocol) { - sckt = sckt_in = 0; - connected = false; + sckt = sckt_in = 0; + connected = false; -#if defined(_MSC_VER) || defined(__MINGW32__) + #if defined(_MSC_VER) || defined(__MINGW32__) WSADATA wsaData; int wsaReturnCode; wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData); if (wsaReturnCode == 0) cout << "Winsock DLL loaded ..." << endl; else cout << "Winsock DLL not initialized ..." << endl; -#endif + #endif - if (!is_number(address)) - { - if ((host = gethostbyname(address.c_str())) == NULL) - { - cout << "Could not get host net address by name..." << endl; - } + if (!is_number(address)) { + if ((host = gethostbyname(address.c_str())) == NULL) { + cout << "Could not get host net address by name..." << endl; } - else - { - unsigned int ip; - ip = inet_addr(address.c_str()); - if ((host = gethostbyaddr((char*)&ip, address.size(), PF_INET)) == NULL) - { - cout << "Could not get host net address by number..." << endl; - } + } else { + unsigned int ip; + ip = inet_addr(address.c_str()); + if ((host = gethostbyaddr((char*)&ip, address.size(), PF_INET)) == NULL) { + cout << "Could not get host net address by number..." << endl; } + } - if (host != NULL) - { - if (protocol == ptUDP) //use udp protocol - { - sckt = socket(AF_INET, SOCK_DGRAM, 0); - cout << "Creating UDP socket on port " << port << endl; - } - else //use tcp protocol - { - sckt = socket(AF_INET, SOCK_STREAM, 0); - cout << "Creating TCP socket on port " << port << endl; - } + if (host != NULL) { + if (protocol == ptUDP) { //use udp protocol + sckt = socket(AF_INET, SOCK_DGRAM, 0); + cout << "Creating UDP socket on port " << port << endl; + } + else { //use tcp protocol + sckt = socket(AF_INET, SOCK_STREAM, 0); + cout << "Creating TCP socket on port " << port << endl; + } - if (sckt >= 0) // successful - { - memset(&scktName, 0, sizeof(struct sockaddr_in)); - scktName.sin_family = AF_INET; - scktName.sin_port = htons(port); - memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length); - int len = sizeof(struct sockaddr_in); - if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) // successful - { - cout << "Successfully connected to socket for output ..." << endl; - connected = true; - } - else // unsuccessful - { - cout << "Could not connect to socket for output ..." << endl; - } - } - else // unsuccessful - { - cout << "Could not create socket for FDM output, error = " << errno << endl; - } + if (sckt >= 0) { // successful + memset(&scktName, 0, sizeof(struct sockaddr_in)); + scktName.sin_family = AF_INET; + scktName.sin_port = htons(port); + memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length); + int len = sizeof(struct sockaddr_in); + if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) { // successful + cout << "Successfully connected to socket for output ..." << endl; + connected = true; + } else { // unsuccessful + cout << "Could not connect to socket for output ..." << endl; + } + } else { // unsuccessful + cout << "Could not create socket for FDM output, error = " << errno << endl; } - Debug(0); + } + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGfdmSocket::FGfdmSocket(const string& address, int port) { - sckt = sckt_in = 0; - connected = false; + sckt = sckt_in = 0; + connected = false; -#if defined(_MSC_VER) || defined(__MINGW32__) + #if defined(_MSC_VER) || defined(__MINGW32__) WSADATA wsaData; int wsaReturnCode; wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData); if (wsaReturnCode == 0) cout << "Winsock DLL loaded ..." << endl; else cout << "Winsock DLL not initialized ..." << endl; -#endif + #endif - cout << "... Socket Configuration Sanity Check ..." << endl; - cout << "Host name... " << address << ", Port... " << port << "." << endl; - cout << "Host name... (char) " << address.c_str() << "." << endl; + cout << "... Socket Configuration Sanity Check ..." << endl; + cout << "Host name... " << address << ", Port... " << port << "." << endl; + cout << "Host name... (char) " << address.c_str() << "." << endl; - if (!is_number(address)) - { - if ((host = gethostbyname(address.c_str())) == NULL) - { - cout << "Could not get host net address by name..." << endl; - } + if (!is_number(address)) { + if ((host = gethostbyname(address.c_str())) == NULL) { + cout << "Could not get host net address by name..." << endl; } - else - { - if ((host = gethostbyaddr(address.c_str(), address.size(), PF_INET)) == NULL) - { - cout << "Could not get host net address by number..." << endl; - } + } else { + if ((host = gethostbyaddr(address.c_str(), address.size(), PF_INET)) == NULL) { + cout << "Could not get host net address by number..." << endl; } + } - if (host != NULL) - { - cout << "Got host net address..." << endl; - sckt = socket(AF_INET, SOCK_STREAM, 0); - - if (sckt >= 0) // successful - { - memset(&scktName, 0, sizeof(struct sockaddr_in)); - scktName.sin_family = AF_INET; - scktName.sin_port = htons(port); - memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length); - int len = sizeof(struct sockaddr_in); - if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) // successful - { - cout << "Successfully connected to socket for output ..." << endl; - connected = true; - } - else // unsuccessful - { - cout << "Could not connect to socket for output ..." << endl; - } - } - else // unsuccessful - { - cout << "Could not create socket for FDM output, error = " << errno << endl; - } + if (host != NULL) { + cout << "Got host net address..." << endl; + sckt = socket(AF_INET, SOCK_STREAM, 0); + + if (sckt >= 0) { // successful + memset(&scktName, 0, sizeof(struct sockaddr_in)); + scktName.sin_family = AF_INET; + scktName.sin_port = htons(port); + memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length); + int len = sizeof(struct sockaddr_in); + if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) { // successful + cout << "Successfully connected to socket for output ..." << endl; + connected = true; + } else { // unsuccessful + cout << "Could not connect to socket for output ..." << endl; + } + } else { // unsuccessful + cout << "Could not create socket for FDM output, error = " << errno << endl; } - Debug(0); + } + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGfdmSocket::FGfdmSocket(int port) { - connected = false; - unsigned long NoBlock = true; + connected = false; + unsigned long NoBlock = true; -#if defined(_MSC_VER) || defined(__MINGW32__) + #if defined(_MSC_VER) || defined(__MINGW32__) WSADATA wsaData; int wsaReturnCode; wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData); if (wsaReturnCode == 0) cout << "Winsock DLL loaded ..." << endl; else cerr << "Winsock DLL not initialized ..." << endl; -#endif + #endif - sckt = socket(AF_INET, SOCK_STREAM, 0); + sckt = socket(AF_INET, SOCK_STREAM, 0); - if (sckt >= 0) // successful - { - memset(&scktName, 0, sizeof(struct sockaddr_in)); - scktName.sin_family = AF_INET; - scktName.sin_port = htons(port); - int len = sizeof(struct sockaddr_in); - if (bind(sckt, (struct sockaddr*)&scktName, len) == 0) // successful - { - cout << "Successfully bound to socket for input on port " << port << endl; - if (listen(sckt, 5) >= 0) // successful listen() - { -#if defined(_MSC_VER) || defined(__MINGW32__) - ioctlsocket(sckt, FIONBIO, &NoBlock); - sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len); -#else - ioctl(sckt, FIONBIO, &NoBlock); - sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len); -#endif - } - else - { - cerr << "Could not listen ..." << endl; - } - connected = true; - } - else // unsuccessful - { - cerr << "Could not bind to socket for input ..." << endl; - } - } - else // unsuccessful - { - cerr << "Could not create socket for FDM input, error = " << errno << endl; + if (sckt >= 0) { // successful + memset(&scktName, 0, sizeof(struct sockaddr_in)); + scktName.sin_family = AF_INET; + scktName.sin_port = htons(port); + int len = sizeof(struct sockaddr_in); + if (bind(sckt, (struct sockaddr*)&scktName, len) == 0) { // successful + cout << "Successfully bound to socket for input on port " << port << endl; + if (listen(sckt, 5) >= 0) { // successful listen() + #if defined(_MSC_VER) || defined(__MINGW32__) + ioctlsocket(sckt, FIONBIO, &NoBlock); + sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len); + #else + ioctl(sckt, FIONBIO, &NoBlock); + sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len); + #endif + } else { + cerr << "Could not listen ..." << endl; + } + connected = true; + } else { // unsuccessful + cerr << "Could not bind to socket for input ..." << endl; } + } else { // unsuccessful + cerr << "Could not create socket for FDM input, error = " << errno << endl; + } - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGfdmSocket::~FGfdmSocket() { - if (sckt) shutdown(sckt,2); - if (sckt_in) shutdown(sckt_in,2); - Debug(1); + if (sckt) shutdown(sckt,2); + if (sckt_in) shutdown(sckt_in,2); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGfdmSocket::Receive(void) { - char buf[1024]; - int len = sizeof(struct sockaddr_in); - int num_chars=0; - unsigned long NoBlock = true; - string data; // todo: should allocate this with a standard size as a - // class attribute and pass as a reference? - - if (sckt_in <= 0) - { -#if defined(_MSC_VER) || defined(__MINGW32__) - sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len); -#else - sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len); -#endif - if (sckt_in > 0) - { -#if defined(_MSC_VER) || defined(__MINGW32__) - ioctlsocket(sckt_in, FIONBIO,&NoBlock); -#else - ioctl(sckt_in, FIONBIO, &NoBlock); -#endif - send(sckt_in, "Connected to JSBSim server\nJSBSim> ", 35, 0); - } + char buf[1024]; + int len = sizeof(struct sockaddr_in); + int num_chars=0; + unsigned long NoBlock = true; + string data; // todo: should allocate this with a standard size as a + // class attribute and pass as a reference? + + if (sckt_in <= 0) { + #if defined(_MSC_VER) || defined(__MINGW32__) + sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len); + #else + sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len); + #endif + if (sckt_in > 0) { + #if defined(_MSC_VER) || defined(__MINGW32__) + ioctlsocket(sckt_in, FIONBIO,&NoBlock); + #else + ioctl(sckt_in, FIONBIO, &NoBlock); + #endif + send(sckt_in, "Connected to JSBSim server\nJSBSim> ", 35, 0); } + } - if (sckt_in > 0) - { - while ((num_chars = recv(sckt_in, buf, sizeof buf, 0)) > 0) - { - data.append(buf, num_chars); - } + if (sckt_in > 0) { + while ((num_chars = recv(sckt_in, buf, sizeof buf, 0)) > 0) { + data.append(buf, num_chars); + } #if defined(_MSC_VER) - // when nothing received and the error isn't "would block" - // then assume that the client has closed the socket. - if (num_chars == 0) - { - DWORD err = WSAGetLastError (); - if (err != WSAEWOULDBLOCK) - { - printf ("Socket Closed. back to listening\n"); - closesocket (sckt_in); - sckt_in = -1; - } + // when nothing received and the error isn't "would block" + // then assume that the client has closed the socket. + if (num_chars == 0) { + DWORD err = WSAGetLastError (); + if (err != WSAEWOULDBLOCK) { + printf ("Socket Closed. back to listening\n"); + closesocket (sckt_in); + sckt_in = -1; } -#endif } +#endif + } - return data; + return data; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% int FGfdmSocket::Reply(const string& text) { - int num_chars_sent=0; - - if (sckt_in >= 0) - { - num_chars_sent = send(sckt_in, text.c_str(), text.size(), 0); - send(sckt_in, "JSBSim> ", 8, 0); - } - else - { - cerr << "Socket reply must be to a valid socket" << endl; - return -1; - } - return num_chars_sent; + int num_chars_sent=0; + + if (sckt_in >= 0) { + num_chars_sent = send(sckt_in, text.c_str(), text.size(), 0); + send(sckt_in, "JSBSim> ", 8, 0); + } else { + cerr << "Socket reply must be to a valid socket" << endl; + return -1; + } + return num_chars_sent; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGfdmSocket::Close(void) { - close(sckt_in); + close(sckt_in); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGfdmSocket::Clear(void) { - buffer.str(string()); + buffer.str(string()); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGfdmSocket::Clear(const string& s) { - Clear(); - buffer << s << ' '; + Clear(); + buffer << s << ' '; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGfdmSocket::Append(const char* item) { - if (buffer.tellp() > 0) buffer << ','; - buffer << item; + if (buffer.tellp() > 0) buffer << ','; + buffer << item; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGfdmSocket::Append(double item) { - if (buffer.tellp() > 0) buffer << ','; - buffer << std::setw(12) << std::setprecision(7) << item; + if (buffer.tellp() > 0) buffer << ','; + buffer << std::setw(12) << std::setprecision(7) << item; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGfdmSocket::Append(long item) { - if (buffer.tellp() > 0) buffer << ','; - buffer << std::setw(12) << item; + if (buffer.tellp() > 0) buffer << ','; + buffer << std::setw(12) << item; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGfdmSocket::Send(void) { - buffer << '\n'; - string str = buffer.str(); - if ((send(sckt,str.c_str(),str.size(),0)) <= 0) - { - perror("send"); - } + buffer << '\n'; + string str = buffer.str(); + if ((send(sckt,str.c_str(),str.size(),0)) <= 0) { + perror("send"); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGfdmSocket::Send(const char *data, int length) { - if ((send(sckt,data,length,0)) <= 0) - { - perror("send"); - } + if ((send(sckt,data,length,0)) <= 0) { + perror("send"); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -419,35 +372,27 @@ void FGfdmSocket::Send(const char *data, int length) void FGfdmSocket::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - } + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGfdmSocket" << endl; - if (from == 1) cout << "Destroyed: FGfdmSocket" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGfdmSocket" << endl; + if (from == 1) cout << "Destroyed: FGfdmSocket" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/input_output/FGfdmSocket.h b/src/input_output/FGfdmSocket.h index a22a3874ab8f1ac61a23ce223ce772928aac86ff..4c9e34b3ca77a07bd46701fb8b5fc11bcff02b80 100644 --- a/src/input_output/FGfdmSocket.h +++ b/src/input_output/FGfdmSocket.h @@ -45,16 +45,16 @@ INCLUDES #include "FGJSBBase.h" #if defined(_MSC_VER) || defined(__MINGW32__) -#include <winsock.h> -#include <io.h> + #include <winsock.h> + #include <io.h> #else -#include <unistd.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <errno.h> -#include <sys/ioctl.h> + #include <unistd.h> + #include <sys/socket.h> + #include <netinet/in.h> + #include <arpa/inet.h> + #include <netdb.h> + #include <errno.h> + #include <sys/ioctl.h> #endif #ifdef _MSC_VER @@ -71,8 +71,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -80,7 +79,7 @@ CLASS DOCUMENTATION /** Encapsulates an object that enables JSBSim to communicate via socket (input and/or output). - + */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -90,40 +89,34 @@ CLASS DECLARATION class FGfdmSocket : public FGJSBBase { public: - FGfdmSocket(const std::string&, int); - FGfdmSocket(const std::string&, int, int); - FGfdmSocket(int); - ~FGfdmSocket(); - void Send(void); - void Send(const char *data, int length); - - std::string Receive(void); - int Reply(const std::string& text); - void Append(const std::string& s) - { - Append(s.c_str()); - } - void Append(const char*); - void Append(double); - void Append(long); - void Clear(void); - void Clear(const std::string& s); - void Close(void); - bool GetConnectStatus(void) - { - return connected; - } - - enum {ptUDP, ptTCP}; + FGfdmSocket(const std::string&, int); + FGfdmSocket(const std::string&, int, int); + FGfdmSocket(int); + ~FGfdmSocket(); + void Send(void); + void Send(const char *data, int length); + + std::string Receive(void); + int Reply(const std::string& text); + void Append(const std::string& s) {Append(s.c_str());} + void Append(const char*); + void Append(double); + void Append(long); + void Clear(void); + void Clear(const std::string& s); + void Close(void); + bool GetConnectStatus(void) {return connected;} + + enum {ptUDP, ptTCP}; private: - int sckt; - int sckt_in; - struct sockaddr_in scktName; - struct hostent *host; - std::ostringstream buffer; - bool connected; - void Debug(int from); + int sckt; + int sckt_in; + struct sockaddr_in scktName; + struct hostent *host; + std::ostringstream buffer; + bool connected; + void Debug(int from); }; } #endif diff --git a/src/input_output/Makefile.am b/src/input_output/Makefile.am index 7e43017b1a4d8701d48745a2ae845340423c5c85..6369b0f8b056d378ae6743a04f83ccf3d402bb06 100644 --- a/src/input_output/Makefile.am +++ b/src/input_output/Makefile.am @@ -1,8 +1,11 @@ includedir = @includedir@/JSBSim/input_output -LIBRARY_SOURCES = FGGroundCallback.cpp FGPropertyManager.cpp FGScript.cpp FGXMLElement.cpp FGXMLParse.cpp FGfdmSocket.cpp flightGearIO.cpp +LIBRARY_SOURCES = FGGroundCallback.cpp FGPropertyManager.cpp FGScript.cpp \ + FGXMLElement.cpp FGXMLParse.cpp FGfdmSocket.cpp flightGearIO.cpp -LIBRARY_INCLUDES = FGGroundCallback.h FGPropertyManager.h FGScript.h FGXMLElement.h FGXMLParse.h FGfdmSocket.h FGXMLFileRead.h net_fdm.hxx string_utilities.h flightGearIO.h +LIBRARY_INCLUDES = FGGroundCallback.h FGPropertyManager.h FGScript.h \ + FGXMLElement.h FGXMLParse.h FGfdmSocket.h FGXMLFileRead.h \ + net_fdm.hxx string_utilities.h flightGearIO.h if BUILD_LIBRARIES noinst_LTLIBRARIES = libInputOutput.la diff --git a/src/input_output/net_fdm.hxx b/src/input_output/net_fdm.hxx index 022712a581c32b5326a621da16179a3d03badf70..2aa8d4f75ac3509254b8f4d0b3a62d3399ab5ebf 100644 --- a/src/input_output/net_fdm.hxx +++ b/src/input_output/net_fdm.hxx @@ -6,7 +6,7 @@ // // This file is in the Public Domain, and comes with no warranty. // -// $Id: net_fdm.hxx,v 1.24 2006-03-21 18:51:57 curt Exp $ +// $Id: net_fdm.hxx,v 1.4 2009/10/27 17:38:35 andgi Exp $ #ifndef _NET_FDM_HXX diff --git a/src/input_output/string_utilities.h b/src/input_output/string_utilities.h index 4119bd991a4187ba0e3761a50a869e35836ef2d2..b55073f8b910e1504380587ef1988403bdfb9b0f 100644 --- a/src/input_output/string_utilities.h +++ b/src/input_output/string_utilities.h @@ -40,12 +40,13 @@ INCLUDES #include <string> #include <vector> +#include <stdio.h> /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_STRINGUTILS "$Id: string_utilities.h,v 1.13 2010/07/07 11:59:48 jberndt Exp $" +#define ID_STRINGUTILS "$Id: string_utilities.h,v 1.14 2010/08/21 17:13:47 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -61,107 +62,112 @@ CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #if !defined(BASE) -extern std::string& trim_left(std::string& str); -extern std::string& trim_right(std::string& str); -extern std::string& trim(std::string& str); -extern std::string& trim_all_space(std::string& str); -extern std::string& to_upper(std::string& str); -extern std::string& to_lower(std::string& str); -extern bool is_number(const std::string& str); -std::vector <std::string> split(std::string str, char d); + extern std::string& trim_left(std::string& str); + extern std::string& trim_right(std::string& str); + extern std::string& trim(std::string& str); + extern std::string& trim_all_space(std::string& str); + extern std::string& to_upper(std::string& str); + extern std::string& to_lower(std::string& str); + extern bool is_number(const std::string& str); + std::vector <std::string> split(std::string str, char d); + extern std::string to_string(int); + extern std::string replace(std::string str, const std::string& old, const std::string& newstr); #else -#include <cctype> + #include <cctype> + using namespace std; -std::string& trim_left(std::string& str) -{ - using namespace std; - while (str.size() && isspace((unsigned char)str[0])) - { - str = str.erase(0,1); + string& trim_left(string& str) + { + while (str.size() && isspace((unsigned char)str[0])) { + str = str.erase(0,1); } return str; -} - -std::string& trim_right(std::string& str) -{ - using namespace std; - while (str.size() && isspace((unsigned char)str[str.size()-1])) - { - str = str.erase(str.size()-1,1); + } + + string& trim_right(string& str) + { + while (str.size() && isspace((unsigned char)str[str.size()-1])) { + str = str.erase(str.size()-1,1); } return str; -} + } -std::string& trim(std::string& str) -{ - using namespace std; + string& trim(string& str) + { if (str.size() == 0) return str; string temp_str = trim_right(str); return str = trim_left(temp_str); -} - -std::string& trim_all_space(std::string& str) -{ - - using namespace std; - - for (size_t i=0; i<str.size(); i++) - { - if (isspace((unsigned char)str[i])) - { - str = str.erase(i,1); - --i; - } + } + + string& trim_all_space(string& str) + { + for (size_t i=0; i<str.size(); i++) { + if (isspace((unsigned char)str[i])) { + str = str.erase(i,1); + --i; + } } return str; -} + } -std::string& to_upper(std::string& str) -{ - using namespace std; + string& to_upper(string& str) + { for (size_t i=0; i<str.size(); i++) str[i] = toupper(str[i]); return str; -} + } -std::string& to_lower(std::string& str) -{ - using namespace std; + string& to_lower(string& str) + { for (size_t i=0; i<str.size(); i++) str[i] = tolower(str[i]); return str; -} + } -bool is_number(const std::string& str) -{ - using namespace std; + bool is_number(const string& str) + { return (str.find_first_not_of("+-.0123456789Ee") == string::npos); -} + } -std::vector <std::string> split(std::string str, char d) -{ - using namespace std; + vector <string> split(string str, char d) + { vector <string> str_array; size_t index=0; string temp = ""; trim(str); index = str.find(d); - while (index != string::npos) - { - temp = str.substr(0,index); - trim(temp); - if (temp.size() > 0) str_array.push_back(temp); - str = str.erase(0,index+1); - index = str.find(d); + while (index != string::npos) { + temp = str.substr(0,index); + trim(temp); + if (temp.size() > 0) str_array.push_back(temp); + str = str.erase(0,index+1); + index = str.find(d); } - if (str.size() > 0) - { - temp = trim(str); - if (temp.size() > 0) str_array.push_back(temp); + if (str.size() > 0) { + temp = trim(str); + if (temp.size() > 0) str_array.push_back(temp); } return str_array; -} + } + + string to_string(int i) + { + char buffer[32]; + sprintf(buffer, "%d", i); + return string(buffer); + } + + string replace(string str, const string& oldstr, const string& newstr) + { + int old_idx; + string temp; + old_idx = str.find(oldstr); + if (old_idx >= 0) { + temp = str.replace(old_idx, 1, newstr); + } + return temp; + } #endif diff --git a/src/math/FGColumnVector3.cpp b/src/math/FGColumnVector3.cpp index 25c95df4caaa573411fd4b3b94625aa69192f08e..5b91dcdb6f7066719a6661f6f1a180713eef9097 100644 --- a/src/math/FGColumnVector3.cpp +++ b/src/math/FGColumnVector3.cpp @@ -45,8 +45,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGColumnVector3.cpp,v 1.13 2010/08/08 00:19:21 jberndt Exp $"; static const char *IdHdr = ID_COLUMNVECTOR3; @@ -57,73 +56,73 @@ CLASS IMPLEMENTATION FGColumnVector3::FGColumnVector3(void) { - data[0] = data[1] = data[2] = 0.0; - // Debug(0); + data[0] = data[1] = data[2] = 0.0; + // Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGColumnVector3::Dump(const string& delimiter) const { - ostringstream buffer; - buffer << std::setw(18) << std::setprecision(16) << data[0] << delimiter; - buffer << std::setw(18) << std::setprecision(16) << data[1] << delimiter; - buffer << std::setw(18) << std::setprecision(16) << data[2]; - return buffer.str(); + ostringstream buffer; + buffer << std::setw(18) << std::setprecision(16) << data[0] << delimiter; + buffer << std::setw(18) << std::setprecision(16) << data[1] << delimiter; + buffer << std::setw(18) << std::setprecision(16) << data[2]; + return buffer.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ostream& operator<<(ostream& os, const FGColumnVector3& col) { - os << col(1) << " , " << col(2) << " , " << col(3); - return os; + os << col(1) << " , " << col(2) << " , " << col(3); + return os; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3 FGColumnVector3::operator/(const double scalar) const { - if (scalar != 0.0) - return operator*( 1.0/scalar ); + if (scalar != 0.0) + return operator*( 1.0/scalar ); - cerr << "Attempt to divide by zero in method \ + cerr << "Attempt to divide by zero in method \ FGColumnVector3::operator/(const double scalar), \ object " << data[0] << " , " << data[1] << " , " << data[2] << endl; - return FGColumnVector3(); + return FGColumnVector3(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3& FGColumnVector3::operator/=(const double scalar) { - if (scalar != 0.0) - operator*=( 1.0/scalar ); - else - cerr << "Attempt to divide by zero in method \ + if (scalar != 0.0) + operator*=( 1.0/scalar ); + else + cerr << "Attempt to divide by zero in method \ FGColumnVector3::operator/=(const double scalar), \ object " << data[0] << " , " << data[1] << " , " << data[2] << endl; - return *this; + return *this; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGColumnVector3::Magnitude(void) const { - return sqrt( data[0]*data[0] + data[1]*data[1] + data[2]*data[2] ); + return sqrt( data[0]*data[0] + data[1]*data[1] + data[2]*data[2] ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3& FGColumnVector3::Normalize(void) { - double Mag = Magnitude(); + double Mag = Magnitude(); - if (Mag != 0.0) - operator*=( 1.0/Mag ); + if (Mag != 0.0) + operator*=( 1.0/Mag ); - return *this; + return *this; } /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ @@ -147,33 +146,26 @@ FGColumnVector3& FGColumnVector3::Normalize(void) void FGColumnVector3::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGColumnVector3" << endl; - if (from == 1) cout << "Destroyed: FGColumnVector3" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGColumnVector3" << endl; + if (from == 1) cout << "Destroyed: FGColumnVector3" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } // namespace JSBSim diff --git a/src/math/FGColumnVector3.h b/src/math/FGColumnVector3.h index cbb8e07df3fd07d5ea278b4f93751f6f60b99842..fe8ce0c382e2338d4d66784ef63e367d16684a60 100644 --- a/src/math/FGColumnVector3.h +++ b/src/math/FGColumnVector3.h @@ -53,8 +53,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -72,239 +71,200 @@ CLASS DECLARATION class FGColumnVector3 : public FGJSBBase { public: - /** Default initializer. - Create a zero vector. */ - FGColumnVector3(void); - - /** Initialization by given values. - @param X value of the x-conponent. - @param Y value of the y-conponent. - @param Z value of the z-conponent. - Create a vector from the doubles given in the arguments. */ - FGColumnVector3(double X, double Y, double Z) - { - data[0] = X; - data[1] = Y; - data[2] = Z; + /** Default initializer. + Create a zero vector. */ + FGColumnVector3(void); + + /** Initialization by given values. + @param X value of the x-conponent. + @param Y value of the y-conponent. + @param Z value of the z-conponent. + Create a vector from the doubles given in the arguments. */ + FGColumnVector3(double X, double Y, double Z) { + data[0] = X; + data[1] = Y; + data[2] = Z; // Debug(0); - } - - /** Copy constructor. - @param v Vector which is used for initialization. - Create copy of the vector given in the argument. */ - FGColumnVector3(const FGColumnVector3& v) - { - data[0] = v.data[0]; - data[1] = v.data[1]; - data[2] = v.data[2]; + } + + /** Copy constructor. + @param v Vector which is used for initialization. + Create copy of the vector given in the argument. */ + FGColumnVector3(const FGColumnVector3& v) { + data[0] = v.data[0]; + data[1] = v.data[1]; + data[2] = v.data[2]; // Debug(0); - } - - /// Destructor. - ~FGColumnVector3(void) - { /* Debug(1); */ } - - /** Read access the entries of the vector. - @param idx the component index. - Return the value of the matrix entry at the given index. - Indices are counted starting with 1. - Note that the index given in the argument is unchecked. */ - double operator()(unsigned int idx) const - { - return data[idx-1]; - } - - /** Write access the entries of the vector. - @param idx the component index. - Return a reference to the vector entry at the given index. - Indices are counted starting with 1. - Note that the index given in the argument is unchecked. */ - double& operator()(unsigned int idx) - { - return data[idx-1]; - } - - /** Read access the entries of the vector. - @param idx the component index. - Return the value of the matrix entry at the given index. - Indices are counted starting with 1. - This function is just a shortcut for the <tt>double - operator()(unsigned int idx) const</tt> function. It is - used internally to access the elements in a more convenient way. - Note that the index given in the argument is unchecked. */ - double Entry(unsigned int idx) const - { - return data[idx-1]; - } - - /** Write access the entries of the vector. - @param idx the component index. - Return a reference to the vector entry at the given index. - Indices are counted starting with 1. - This function is just a shortcut for the <tt>double& - operator()(unsigned int idx)</tt> function. It is - used internally to access the elements in a more convenient way. - Note that the index given in the argument is unchecked. */ - double& Entry(unsigned int idx) - { - return data[idx-1]; - } - - /** Prints the contents of the vector - @param delimeter the item separator (tab or comma) - @return a string with the delimeter-separated contents of the vector */ - std::string Dump(const std::string& delimeter) const; - - /** Assignment operator. - @param b source vector. - Copy the content of the vector given in the argument into *this. */ - FGColumnVector3& operator=(const FGColumnVector3& b) - { - data[0] = b.data[0]; - data[1] = b.data[1]; - data[2] = b.data[2]; - return *this; - } - - /** Comparison operator. - @param b other vector. - Returns true if both vectors are exactly the same. */ - bool operator==(const FGColumnVector3& b) const - { - return data[0] == b.data[0] && data[1] == b.data[1] && data[2] == b.data[2]; - } - - /** Comparison operator. - @param b other vector. - Returns false if both vectors are exactly the same. */ - bool operator!=(const FGColumnVector3& b) const - { - return ! operator==(b); - } - - /** Multiplication by a scalar. - @param scalar scalar value to multiply the vector with. - @return The resulting vector from the multiplication with that scalar. - Multiply the vector with the scalar given in the argument. */ - FGColumnVector3 operator*(const double scalar) const - { - return FGColumnVector3(scalar*data[0], scalar*data[1], scalar*data[2]); - } - - /** Multiply by 1/scalar. - @param scalar scalar value to devide the vector through. - @return The resulting vector from the division through that scalar. - Multiply the vector with the 1/scalar given in the argument. */ - FGColumnVector3 operator/(const double scalar) const; - - /** Cross product multiplication. - @param V vector to multiply with. - @return The resulting vector from the cross product multiplication. - Compute and return the cross product of the current vector with - the given argument. */ - FGColumnVector3 operator*(const FGColumnVector3& V) const - { - return FGColumnVector3( data[1] * V(3) - data[2] * V(2), - data[2] * V(1) - data[0] * V(3), - data[0] * V(2) - data[1] * V(1) ); - } - - /// Addition operator. - FGColumnVector3 operator+(const FGColumnVector3& B) const - { - return FGColumnVector3( data[0] + B(1), data[1] + B(2), data[2] + B(3) ); - } - - /// Subtraction operator. - FGColumnVector3 operator-(const FGColumnVector3& B) const - { - return FGColumnVector3( data[0] - B(1), data[1] - B(2), data[2] - B(3) ); - } - - /// Subtract an other vector. - FGColumnVector3& operator-=(const FGColumnVector3 &B) - { - data[0] -= B(1); - data[1] -= B(2); - data[2] -= B(3); - return *this; - } - - /// Add an other vector. - FGColumnVector3& operator+=(const FGColumnVector3 &B) - { - data[0] += B(1); - data[1] += B(2); - data[2] += B(3); - return *this; - } - - /// Scale by a scalar. - FGColumnVector3& operator*=(const double scalar) - { - data[0] *= scalar; - data[1] *= scalar; - data[2] *= scalar; - return *this; - } - - /// Scale by a 1/scalar. - FGColumnVector3& operator/=(const double scalar); - - void InitMatrix(void) - { - data[0] = data[1] = data[2] = 0.0; - } - void InitMatrix(double a) - { - data[0] = data[1] = data[2] = a; - } - void InitMatrix(double a, double b, double c) - { - data[0]=a; - data[1]=b; - data[2]=c; - } - - /** Length of the vector. - Compute and return the euclidean norm of this vector. */ - double Magnitude(void) const; - - /** Length of the vector in a coordinate axis plane. - Compute and return the euclidean norm of this vector projected into - the coordinate axis plane idx1-idx2. */ - double Magnitude(int idx1, int idx2) const - { - return sqrt( data[idx1-1]*data[idx1-1] + data[idx2-1]*data[idx2-1] ); - } - - /** Normalize. - Normalize the vector to have the Magnitude() == 1.0. If the vector - is equal to zero it is left untouched. */ - FGColumnVector3& Normalize(void); - - /** Dot product of two vectors - Compute and return the euclidean dot (or scalar) product of two vectors - v1 and v2 */ - friend inline double DotProduct(const FGColumnVector3& v1, const FGColumnVector3& v2) - { - return v1(1)*v2(1) + v1(2)*v2(2) + v1(3)*v2(3); - } + } + + /// Destructor. + ~FGColumnVector3(void) { /* Debug(1); */ } + + /** Read access the entries of the vector. + @param idx the component index. + Return the value of the matrix entry at the given index. + Indices are counted starting with 1. + Note that the index given in the argument is unchecked. */ + double operator()(unsigned int idx) const { return data[idx-1]; } + + /** Write access the entries of the vector. + @param idx the component index. + Return a reference to the vector entry at the given index. + Indices are counted starting with 1. + Note that the index given in the argument is unchecked. */ + double& operator()(unsigned int idx) { return data[idx-1]; } + + /** Read access the entries of the vector. + @param idx the component index. + Return the value of the matrix entry at the given index. + Indices are counted starting with 1. + This function is just a shortcut for the <tt>double + operator()(unsigned int idx) const</tt> function. It is + used internally to access the elements in a more convenient way. + Note that the index given in the argument is unchecked. */ + double Entry(unsigned int idx) const { return data[idx-1]; } + + /** Write access the entries of the vector. + @param idx the component index. + Return a reference to the vector entry at the given index. + Indices are counted starting with 1. + This function is just a shortcut for the <tt>double& + operator()(unsigned int idx)</tt> function. It is + used internally to access the elements in a more convenient way. + Note that the index given in the argument is unchecked. */ + double& Entry(unsigned int idx) { return data[idx-1]; } + + /** Prints the contents of the vector + @param delimeter the item separator (tab or comma) + @return a string with the delimeter-separated contents of the vector */ + std::string Dump(const std::string& delimeter) const; + + /** Assignment operator. + @param b source vector. + Copy the content of the vector given in the argument into *this. */ + FGColumnVector3& operator=(const FGColumnVector3& b) { + data[0] = b.data[0]; + data[1] = b.data[1]; + data[2] = b.data[2]; + return *this; + } + + /** Comparison operator. + @param b other vector. + Returns true if both vectors are exactly the same. */ + bool operator==(const FGColumnVector3& b) const { + return data[0] == b.data[0] && data[1] == b.data[1] && data[2] == b.data[2]; + } + + /** Comparison operator. + @param b other vector. + Returns false if both vectors are exactly the same. */ + bool operator!=(const FGColumnVector3& b) const { return ! operator==(b); } + + /** Multiplication by a scalar. + @param scalar scalar value to multiply the vector with. + @return The resulting vector from the multiplication with that scalar. + Multiply the vector with the scalar given in the argument. */ + FGColumnVector3 operator*(const double scalar) const { + return FGColumnVector3(scalar*data[0], scalar*data[1], scalar*data[2]); + } + + /** Multiply by 1/scalar. + @param scalar scalar value to devide the vector through. + @return The resulting vector from the division through that scalar. + Multiply the vector with the 1/scalar given in the argument. */ + FGColumnVector3 operator/(const double scalar) const; + + /** Cross product multiplication. + @param V vector to multiply with. + @return The resulting vector from the cross product multiplication. + Compute and return the cross product of the current vector with + the given argument. */ + FGColumnVector3 operator*(const FGColumnVector3& V) const { + return FGColumnVector3( data[1] * V(3) - data[2] * V(2), + data[2] * V(1) - data[0] * V(3), + data[0] * V(2) - data[1] * V(1) ); + } + + /// Addition operator. + FGColumnVector3 operator+(const FGColumnVector3& B) const { + return FGColumnVector3( data[0] + B(1), data[1] + B(2), data[2] + B(3) ); + } + + /// Subtraction operator. + FGColumnVector3 operator-(const FGColumnVector3& B) const { + return FGColumnVector3( data[0] - B(1), data[1] - B(2), data[2] - B(3) ); + } + + /// Subtract an other vector. + FGColumnVector3& operator-=(const FGColumnVector3 &B) { + data[0] -= B(1); + data[1] -= B(2); + data[2] -= B(3); + return *this; + } + + /// Add an other vector. + FGColumnVector3& operator+=(const FGColumnVector3 &B) { + data[0] += B(1); + data[1] += B(2); + data[2] += B(3); + return *this; + } + + /// Scale by a scalar. + FGColumnVector3& operator*=(const double scalar) { + data[0] *= scalar; + data[1] *= scalar; + data[2] *= scalar; + return *this; + } + + /// Scale by a 1/scalar. + FGColumnVector3& operator/=(const double scalar); + + void InitMatrix(void) { data[0] = data[1] = data[2] = 0.0; } + void InitMatrix(double a) { data[0] = data[1] = data[2] = a; } + void InitMatrix(double a, double b, double c) { + data[0]=a; data[1]=b; data[2]=c; + } + + /** Length of the vector. + Compute and return the euclidean norm of this vector. */ + double Magnitude(void) const; + + /** Length of the vector in a coordinate axis plane. + Compute and return the euclidean norm of this vector projected into + the coordinate axis plane idx1-idx2. */ + double Magnitude(int idx1, int idx2) const { + return sqrt( data[idx1-1]*data[idx1-1] + data[idx2-1]*data[idx2-1] ); + } + + /** Normalize. + Normalize the vector to have the Magnitude() == 1.0. If the vector + is equal to zero it is left untouched. */ + FGColumnVector3& Normalize(void); + + /** Dot product of two vectors + Compute and return the euclidean dot (or scalar) product of two vectors + v1 and v2 */ + friend inline double DotProduct(const FGColumnVector3& v1, const FGColumnVector3& v2) { + return v1(1)*v2(1) + v1(2)*v2(2) + v1(3)*v2(3); + } private: - double data[3]; + double data[3]; - void Debug(int from); + void Debug(int from); }; /** Scalar multiplication. @param scalar scalar value to multiply with. @param A Vector to multiply. Multiply the Vector with a scalar value.*/ -inline FGColumnVector3 operator*(double scalar, const FGColumnVector3& A) -{ - // use already defined operation. - return A*scalar; +inline FGColumnVector3 operator*(double scalar, const FGColumnVector3& A) { + // use already defined operation. + return A*scalar; } /** Write vector to a stream. diff --git a/src/math/FGCondition.cpp b/src/math/FGCondition.cpp index b5cc490f7717ae361cbc01d9fc6db2054dc6a0ff..2a1ffd47f2415b2e574451ba985e3a94fbd921ac 100644 --- a/src/math/FGCondition.cpp +++ b/src/math/FGCondition.cpp @@ -42,8 +42,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGCondition.cpp,v 1.13 2010/07/14 05:50:40 ehofman Exp $"; static const char *IdHdr = ID_CONDITION; @@ -56,47 +55,41 @@ string FGCondition::indent = " "; // This constructor is called when tests are inside an element FGCondition::FGCondition(Element* element, FGPropertyManager* PropertyManager) : - PropertyManager(PropertyManager), isGroup(true) + PropertyManager(PropertyManager), isGroup(true) { - string property1, property2, logic; - Element* condition_element; - - InitializeConditionals(); - - TestParam1 = TestParam2 = 0L; - TestValue = 0.0; - Comparison = ecUndef; - Logic = elUndef; - conditions.clear(); - - logic = element->GetAttributeValue("logic"); - if (!logic.empty()) - { - if (logic == "OR") Logic = eOR; - else if (logic == "AND") Logic = eAND; - else // error - { - cerr << "Unrecognized LOGIC token " << logic << endl; - } - } - else - { - Logic = eAND; // default + string property1, property2, logic; + Element* condition_element; + + InitializeConditionals(); + + TestParam1 = TestParam2 = 0L; + TestValue = 0.0; + Comparison = ecUndef; + Logic = elUndef; + conditions.clear(); + + logic = element->GetAttributeValue("logic"); + if (!logic.empty()) { + if (logic == "OR") Logic = eOR; + else if (logic == "AND") Logic = eAND; + else { // error + cerr << "Unrecognized LOGIC token " << logic << endl; } - - condition_element = element->GetElement(); - while (condition_element) - { - conditions.push_back(new FGCondition(condition_element, PropertyManager)); - condition_element = element->GetNextElement(); - } - for (unsigned int i=0; i<element->GetNumDataLines(); i++) - { - string data = element->GetDataLine(i); - conditions.push_back(new FGCondition(data, PropertyManager)); - } - - Debug(0); + } else { + Logic = eAND; // default + } + + condition_element = element->GetElement(); + while (condition_element) { + conditions.push_back(new FGCondition(condition_element, PropertyManager)); + condition_element = element->GetNextElement(); + } + for (unsigned int i=0; i<element->GetNumDataLines(); i++) { + string data = element->GetDataLine(i); + conditions.push_back(new FGCondition(data, PropertyManager)); + } + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -104,205 +97,183 @@ FGCondition::FGCondition(Element* element, FGPropertyManager* PropertyManager) : // condition FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager) : - PropertyManager(PropertyManager), isGroup(false) + PropertyManager(PropertyManager), isGroup(false) { - string property1, property2, compare_string; - vector <string> test_strings; - - InitializeConditionals(); - - TestParam1 = TestParam2 = 0L; - TestValue = 0.0; - Comparison = ecUndef; - Logic = elUndef; - conditions.clear(); - - test_strings = split(test, ' '); - if (test_strings.size() == 3) - { - property1 = test_strings[0]; - conditional = test_strings[1]; - property2 = test_strings[2]; - } - else - { - cerr << endl << " Conditional test is invalid: \"" << test - << "\" has " << test_strings.size() << " elements in the " - << "test condition." << endl; - exit(-1); - } - - TestParam1 = PropertyManager->GetNode(property1, false); - if (!TestParam1) - { + string property1, property2, compare_string; + vector <string> test_strings; + + InitializeConditionals(); + + TestParam1 = TestParam2 = 0L; + TestValue = 0.0; + Comparison = ecUndef; + Logic = elUndef; + conditions.clear(); + + test_strings = split(test, ' '); + if (test_strings.size() == 3) { + property1 = test_strings[0]; + conditional = test_strings[1]; + property2 = test_strings[2]; + } else { + cerr << endl << " Conditional test is invalid: \"" << test + << "\" has " << test_strings.size() << " elements in the " + << "test condition." << endl; + exit(-1); + } + + TestParam1 = PropertyManager->GetNode(property1, false); + if (!TestParam1) { + cerr << fgred << " In condition: " << test << ". Unknown property " + << property1 << " referenced." << endl + << "Creating property. Check usage." << reset << endl; + TestParam1 = PropertyManager->GetNode(property1, true); + } + Comparison = mComparison[conditional]; + if (Comparison == ecUndef) { + throw("Comparison operator: \""+conditional+"\" does not exist. Please check the conditional."); + } + if (is_number(property2)) { + TestValue = atof(property2.c_str()); + } else { + TestParam2 = PropertyManager->GetNode(property2, false); + if (!TestParam2) { cerr << fgred << " In condition: " << test << ". Unknown property " - << property1 << " referenced." << endl + << property2 << " referenced." << endl << "Creating property. Check usage." << reset << endl; - TestParam1 = PropertyManager->GetNode(property1, true); - } - Comparison = mComparison[conditional]; - if (Comparison == ecUndef) - { - throw("Comparison operator: \""+conditional+"\" does not exist. Please check the conditional."); - } - if (is_number(property2)) - { - TestValue = atof(property2.c_str()); - } - else - { - TestParam2 = PropertyManager->GetNode(property2, false); - if (!TestParam2) - { - cerr << fgred << " In condition: " << test << ". Unknown property " - << property2 << " referenced." << endl - << "Creating property. Check usage." << reset << endl; - TestParam2 = PropertyManager->GetNode(property2, true); - } + TestParam2 = PropertyManager->GetNode(property2, true); } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGCondition::InitializeConditionals(void) { - mComparison["EQ"] = eEQ; - mComparison["NE"] = eNE; - mComparison["GT"] = eGT; - mComparison["GE"] = eGE; - mComparison["LT"] = eLT; - mComparison["LE"] = eLE; - mComparison["eq"] = eEQ; - mComparison["ne"] = eNE; - mComparison["gt"] = eGT; - mComparison["ge"] = eGE; - mComparison["lt"] = eLT; - mComparison["le"] = eLE; - mComparison["=="] = eEQ; - mComparison["!="] = eNE; - mComparison[">"] = eGT; - mComparison[">="] = eGE; - mComparison["<"] = eLT; - mComparison["<="] = eLE; + mComparison["EQ"] = eEQ; + mComparison["NE"] = eNE; + mComparison["GT"] = eGT; + mComparison["GE"] = eGE; + mComparison["LT"] = eLT; + mComparison["LE"] = eLE; + mComparison["eq"] = eEQ; + mComparison["ne"] = eNE; + mComparison["gt"] = eGT; + mComparison["ge"] = eGE; + mComparison["lt"] = eLT; + mComparison["le"] = eLE; + mComparison["=="] = eEQ; + mComparison["!="] = eNE; + mComparison[">"] = eGT; + mComparison[">="] = eGE; + mComparison["<"] = eLT; + mComparison["<="] = eLE; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGCondition::~FGCondition(void) { - for (unsigned int i=0; i<conditions.size(); i++) delete conditions[i]; + for (unsigned int i=0; i<conditions.size(); i++) delete conditions[i]; - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGCondition::Evaluate(void ) { - bool pass = false; - double compareValue; + bool pass = false; + double compareValue; - if (TestParam1 == 0L) - { + if (TestParam1 == 0L) { - if (Logic == eAND) - { + if (Logic == eAND) { - pass = true; - for (unsigned int i=0; i<conditions.size(); i++) - { - if (!conditions[i]->Evaluate()) pass = false; - } + pass = true; + for (unsigned int i=0; i<conditions.size(); i++) { + if (!conditions[i]->Evaluate()) pass = false; + } - } - else // Logic must be eOR - { + } else { // Logic must be eOR - pass = false; - for (unsigned int i=0; i<conditions.size(); i++) - { - if (conditions[i]->Evaluate()) pass = true; - } - - } + pass = false; + for (unsigned int i=0; i<conditions.size(); i++) { + if (conditions[i]->Evaluate()) pass = true; + } } - else - { - - if (TestParam2 != 0L) compareValue = TestParam2->getDoubleValue(); - else compareValue = TestValue; - - switch (Comparison) - { - case ecUndef: - cerr << "Undefined comparison operator." << endl; - break; - case eEQ: - pass = TestParam1->getDoubleValue() == compareValue; - break; - case eNE: - pass = TestParam1->getDoubleValue() != compareValue; - break; - case eGT: - pass = TestParam1->getDoubleValue() > compareValue; - break; - case eGE: - pass = TestParam1->getDoubleValue() >= compareValue; - break; - case eLT: - pass = TestParam1->getDoubleValue() < compareValue; - break; - case eLE: - pass = TestParam1->getDoubleValue() <= compareValue; - break; - default: - cerr << "Unknown comparison operator." << endl; - } + + } else { + + if (TestParam2 != 0L) compareValue = TestParam2->getDoubleValue(); + else compareValue = TestValue; + + switch (Comparison) { + case ecUndef: + cerr << "Undefined comparison operator." << endl; + break; + case eEQ: + pass = TestParam1->getDoubleValue() == compareValue; + break; + case eNE: + pass = TestParam1->getDoubleValue() != compareValue; + break; + case eGT: + pass = TestParam1->getDoubleValue() > compareValue; + break; + case eGE: + pass = TestParam1->getDoubleValue() >= compareValue; + break; + case eLT: + pass = TestParam1->getDoubleValue() < compareValue; + break; + case eLE: + pass = TestParam1->getDoubleValue() <= compareValue; + break; + default: + cerr << "Unknown comparison operator." << endl; } + } - return pass; + return pass; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGCondition::PrintCondition(void ) { - string scratch; - - if (isGroup) - { - switch (Logic) - { - case (elUndef): - scratch = " UNSET"; - cerr << "unset logic for test condition" << endl; - break; - case (eAND): - scratch = " if all of the following are true:"; - break; - case (eOR): - scratch = " if any of the following are true:"; - break; - default: - scratch = " UNKNOWN"; - cerr << "Unknown logic for test condition" << endl; - } - - cout << scratch << endl; - for (unsigned int i=0; i<conditions.size(); i++) conditions[i]->PrintCondition(); - + string scratch; + + if (isGroup) { + switch(Logic) { + case (elUndef): + scratch = " UNSET"; + cerr << "unset logic for test condition" << endl; + break; + case (eAND): + scratch = " if all of the following are true:"; + break; + case (eOR): + scratch = " if any of the following are true:"; + break; + default: + scratch = " UNKNOWN"; + cerr << "Unknown logic for test condition" << endl; } + + cout << scratch << endl; + for (unsigned int i=0; i<conditions.size(); i++) conditions[i]->PrintCondition(); + + } else { + if (TestParam2 != 0L) + cout << " " << TestParam1->GetRelativeName() << " " + << conditional << " " + << TestParam2->GetRelativeName(); else - { - if (TestParam2 != 0L) - cout << " " << TestParam1->GetRelativeName() << " " - << conditional << " " - << TestParam2->GetRelativeName(); - else - cout << " " << TestParam1->GetRelativeName() << " " - << conditional << " " << TestValue; - } + cout << " " << TestParam1->GetRelativeName() << " " + << conditional << " " << TestValue; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -326,37 +297,29 @@ void FGCondition::PrintCondition(void ) void FGCondition::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGCondition" << endl; - if (from == 1) cout << "Destroyed: FGCondition" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGCondition" << endl; + if (from == 1) cout << "Destroyed: FGCondition" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } //namespace JSBSim diff --git a/src/math/FGCondition.h b/src/math/FGCondition.h index 82b96a404e5f10197ec523d7e63536535bcd35a1..2cd75bdfbf2a9761547e42c5a1aefc0c17a07dc8 100644 --- a/src/math/FGCondition.h +++ b/src/math/FGCondition.h @@ -50,8 +50,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGPropertyManager; class Element; @@ -70,31 +69,31 @@ CLASS DECLARATION class FGCondition : public FGJSBBase { public: - FGCondition(Element* element, FGPropertyManager* PropertyManager); - FGCondition(const std::string& test, FGPropertyManager* PropertyManager); - ~FGCondition(void); + FGCondition(Element* element, FGPropertyManager* PropertyManager); + FGCondition(const std::string& test, FGPropertyManager* PropertyManager); + ~FGCondition(void); - bool Evaluate(void); - void PrintCondition(void); + bool Evaluate(void); + void PrintCondition(void); private: - enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE}; - enum eLogic {elUndef=0, eAND, eOR}; - std::map <std::string, eComparison> mComparison; - eLogic Logic; + enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE}; + enum eLogic {elUndef=0, eAND, eOR}; + std::map <std::string, eComparison> mComparison; + eLogic Logic; - FGPropertyManager *TestParam1, *TestParam2, *PropertyManager; - double TestValue; - eComparison Comparison; - bool isGroup; - std::string conditional; + FGPropertyManager *TestParam1, *TestParam2, *PropertyManager; + double TestValue; + eComparison Comparison; + bool isGroup; + std::string conditional; - static std::string indent; + static std::string indent; - std::vector <FGCondition*> conditions; - void InitializeConditionals(void); + std::vector <FGCondition*> conditions; + void InitializeConditionals(void); - void Debug(int from); + void Debug(int from); }; } #endif diff --git a/src/math/FGFunction.cpp b/src/math/FGFunction.cpp old mode 100644 new mode 100755 index dd9f9a0dde22f66611c487b6925bf48ab5340682..9ad7c7a9974ad66ba87eb02f36ce465946e7fc0a --- a/src/math/FGFunction.cpp +++ b/src/math/FGFunction.cpp @@ -41,10 +41,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGFunction.cpp,v 1.32 2010/03/18 13:21:24 jberndt Exp $"; +static const char *IdSrc = "$Id: FGFunction.cpp,v 1.35 2010/08/28 12:41:56 jberndt Exp $"; static const char *IdHdr = ID_FUNCTION; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -52,400 +51,356 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& prefix) - : PropertyManager(propMan), Prefix(prefix) + : PropertyManager(propMan), Prefix(prefix) { - Element* element; - string operation, property_name; - cached = false; - cachedValue = -HUGE_VAL; - invlog2val = 1.0/log10(2.0); - - property_string = "property"; - value_string = "value"; - table_string = "table"; - p_string = "p"; - v_string = "v"; - t_string = "t"; - - function_string = "function"; - description_string = "description"; - sum_string = "sum"; - difference_string = "difference"; - product_string = "product"; - quotient_string = "quotient"; - pow_string = "pow"; - exp_string = "exp"; - log2_string = "log2"; - ln_string = "ln"; - log10_string = "log10"; - abs_string = "abs"; - sin_string = "sin"; - cos_string = "cos"; - tan_string = "tan"; - asin_string = "asin"; - acos_string = "acos"; - atan_string = "atan"; - atan2_string = "atan2"; - min_string = "min"; - max_string = "max"; - avg_string = "avg"; - fraction_string = "fraction"; - mod_string = "mod"; - random_string = "random"; - integer_string = "integer"; - - Name = el->GetAttributeValue("name"); - operation = el->GetName(); - - if (operation == function_string) - { - Type = eTopLevel; - } - else if (operation == product_string) - { - Type = eProduct; - } - else if (operation == difference_string) - { - Type = eDifference; - } - else if (operation == sum_string) - { - Type = eSum; - } - else if (operation == quotient_string) - { - Type = eQuotient; - } - else if (operation == pow_string) - { - Type = ePow; - } - else if (operation == log2_string) - { - Type = eLog2; - } - else if (operation == ln_string) - { - Type = eLn; - } - else if (operation == log10_string) - { - Type = eLog10; - } - else if (operation == abs_string) - { - Type = eAbs; - } - else if (operation == sin_string) - { - Type = eSin; - } - else if (operation == exp_string) - { - Type = eExp; - } - else if (operation == cos_string) - { - Type = eCos; - } - else if (operation == tan_string) - { - Type = eTan; - } - else if (operation == asin_string) - { - Type = eASin; - } - else if (operation == acos_string) - { - Type = eACos; - } - else if (operation == atan_string) - { - Type = eATan; - } - else if (operation == atan2_string) - { - Type = eATan2; - } - else if (operation == min_string) - { - Type = eMin; - } - else if (operation == max_string) - { - Type = eMax; - } - else if (operation == avg_string) - { - Type = eAvg; - } - else if (operation == fraction_string) - { - Type = eFrac; - } - else if (operation == integer_string) - { - Type = eInteger; - } - else if (operation == mod_string) - { - Type = eMod; - } - else if (operation == random_string) - { - Type = eRandom; - } - else if (operation != description_string) - { - cerr << "Bad operation " << operation << " detected in configuration file" << endl; - } - - element = el->GetElement(); - if (!element) - { - cerr << fgred << highint << endl; - cerr << " No element was specified as an argument to the \"" << operation << "\" operation" << endl; - cerr << " This can happen when, for instance, a cos operation is specified and a " << endl; - cerr << " property name is given explicitly, but is not placed within a" << endl; - cerr << " <property></property> element tag pair." << endl; - cerr << reset; - exit(-2); - } - - while (element) - { - operation = element->GetName(); - - // data types - if (operation == property_string || operation == p_string) - { - property_name = element->GetDataLine(); - FGPropertyManager* newNode = PropertyManager->GetNode(property_name); - if (newNode == 0) - { - cerr << "The property " << property_name << " is undefined." << endl; - abort(); - } - else - { - Parameters.push_back(new FGPropertyValue( newNode )); - } - } - else if (operation == value_string || operation == v_string) - { - Parameters.push_back(new FGRealValue(element->GetDataAsNumber())); - } - else if (operation == table_string || operation == t_string) - { - Parameters.push_back(new FGTable(PropertyManager, element)); - // operations - } - else if (operation == product_string || - operation == difference_string || - operation == sum_string || - operation == quotient_string || - operation == pow_string || - operation == exp_string || - operation == log2_string || - operation == ln_string || - operation == log10_string || - operation == abs_string || - operation == sin_string || - operation == cos_string || - operation == tan_string || - operation == asin_string || - operation == acos_string || - operation == atan_string || - operation == atan2_string || - operation == min_string || - operation == max_string || - operation == fraction_string || - operation == integer_string || - operation == mod_string || - operation == random_string || - operation == avg_string ) - { - Parameters.push_back(new FGFunction(PropertyManager, element)); - } - else if (operation != description_string) - { - cerr << "Bad operation " << operation << " detected in configuration file" << endl; + Element* element; + string operation, property_name; + cached = false; + cachedValue = -HUGE_VAL; + invlog2val = 1.0/log10(2.0); + + property_string = "property"; + value_string = "value"; + table_string = "table"; + p_string = "p"; + v_string = "v"; + t_string = "t"; + + function_string = "function"; + description_string = "description"; + sum_string = "sum"; + difference_string = "difference"; + product_string = "product"; + quotient_string = "quotient"; + pow_string = "pow"; + exp_string = "exp"; + log2_string = "log2"; + ln_string = "ln"; + log10_string = "log10"; + abs_string = "abs"; + sin_string = "sin"; + cos_string = "cos"; + tan_string = "tan"; + asin_string = "asin"; + acos_string = "acos"; + atan_string = "atan"; + atan2_string = "atan2"; + min_string = "min"; + max_string = "max"; + avg_string = "avg"; + fraction_string = "fraction"; + mod_string = "mod"; + random_string = "random"; + integer_string = "integer"; + + Name = el->GetAttributeValue("name"); + operation = el->GetName(); + + if (operation == function_string) { + Type = eTopLevel; + } else if (operation == product_string) { + Type = eProduct; + } else if (operation == difference_string) { + Type = eDifference; + } else if (operation == sum_string) { + Type = eSum; + } else if (operation == quotient_string) { + Type = eQuotient; + } else if (operation == pow_string) { + Type = ePow; + } else if (operation == log2_string) { + Type = eLog2; + } else if (operation == ln_string) { + Type = eLn; + } else if (operation == log10_string) { + Type = eLog10; + } else if (operation == abs_string) { + Type = eAbs; + } else if (operation == sin_string) { + Type = eSin; + } else if (operation == exp_string) { + Type = eExp; + } else if (operation == cos_string) { + Type = eCos; + } else if (operation == tan_string) { + Type = eTan; + } else if (operation == asin_string) { + Type = eASin; + } else if (operation == acos_string) { + Type = eACos; + } else if (operation == atan_string) { + Type = eATan; + } else if (operation == atan2_string) { + Type = eATan2; + } else if (operation == min_string) { + Type = eMin; + } else if (operation == max_string) { + Type = eMax; + } else if (operation == avg_string) { + Type = eAvg; + } else if (operation == fraction_string) { + Type = eFrac; + } else if (operation == integer_string) { + Type = eInteger; + } else if (operation == mod_string) { + Type = eMod; + } else if (operation == random_string) { + Type = eRandom; + } else if (operation != description_string) { + cerr << "Bad operation " << operation << " detected in configuration file" << endl; + } + + element = el->GetElement(); + if (!element) { + cerr << fgred << highint << endl; + cerr << " No element was specified as an argument to the \"" << operation << "\" operation" << endl; + cerr << " This can happen when, for instance, a cos operation is specified and a " << endl; + cerr << " property name is given explicitly, but is not placed within a" << endl; + cerr << " <property></property> element tag pair." << endl; + cerr << reset; + exit(-2); + } + + while (element) { + operation = element->GetName(); + + // data types + if (operation == property_string || operation == p_string) { + property_name = element->GetDataLine(); + if (property_name.find("#") != string::npos) { + if (is_number(Prefix)) { + property_name = replace(property_name,"#",Prefix); } - element = el->GetNextElement(); - } - - bind(); // Allow any function to save its value - - Debug(0); + } + FGPropertyManager* newNode = 0L; + if (PropertyManager->HasNode(property_name)) { + newNode = PropertyManager->GetNode(property_name); + Parameters.push_back(new FGPropertyValue( newNode )); + } else { + cerr << fgcyan << "The property " + property_name + " is initially undefined." + << reset << endl; + Parameters.push_back(new FGPropertyValue( property_name )); + } + } else if (operation == value_string || operation == v_string) { + Parameters.push_back(new FGRealValue(element->GetDataAsNumber())); + } else if (operation == table_string || operation == t_string) { + Parameters.push_back(new FGTable(PropertyManager, element)); + // operations + } else if (operation == product_string || + operation == difference_string || + operation == sum_string || + operation == quotient_string || + operation == pow_string || + operation == exp_string || + operation == log2_string || + operation == ln_string || + operation == log10_string || + operation == abs_string || + operation == sin_string || + operation == cos_string || + operation == tan_string || + operation == asin_string || + operation == acos_string || + operation == atan_string || + operation == atan2_string || + operation == min_string || + operation == max_string || + operation == fraction_string || + operation == integer_string || + operation == mod_string || + operation == random_string || + operation == avg_string ) + { + Parameters.push_back(new FGFunction(PropertyManager, element, Prefix)); + } else if (operation != description_string) { + cerr << "Bad operation " << operation << " detected in configuration file" << endl; + } + element = el->GetNextElement(); + } + + bind(); // Allow any function to save its value + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGFunction::~FGFunction(void) { - for (unsigned int i=0; i<Parameters.size(); i++) delete Parameters[i]; + for (unsigned int i=0; i<Parameters.size(); i++) delete Parameters[i]; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFunction::cacheValue(bool cache) { - cached = false; // Must set cached to false prior to calling GetValue(), else - // it will _never_ calculate the value; - if (cache) - { - cachedValue = GetValue(); - cached = true; - } + cached = false; // Must set cached to false prior to calling GetValue(), else + // it will _never_ calculate the value; + if (cache) { + cachedValue = GetValue(); + cached = true; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGFunction::GetValue(void) const { - unsigned int i; - double scratch; - - if (cached) return cachedValue; - - double temp = Parameters[0]->GetValue(); - - switch (Type) - { - case eTopLevel: - break; - case eProduct: - for (i=1;i<Parameters.size();i++) - { - temp *= Parameters[i]->GetValue(); - } - break; - case eDifference: - for (i=1;i<Parameters.size();i++) - { - temp -= Parameters[i]->GetValue(); - } - break; - case eSum: - for (i=1;i<Parameters.size();i++) - { - temp += Parameters[i]->GetValue(); - } - break; - case eQuotient: - if (Parameters[1]->GetValue() != 0.0) - temp /= Parameters[1]->GetValue(); - else - temp = HUGE_VAL; - break; - case ePow: - temp = pow(temp,Parameters[1]->GetValue()); - break; - case eExp: - temp = exp(temp); - break; - case eLog2: - if (temp > 0.00) temp = log10(temp)*invlog2val; - else temp = -HUGE_VAL; - break; - case eLn: - if (temp > 0.00) temp = log(temp); - else temp = -HUGE_VAL; - break; - case eLog10: - if (temp > 0.00) temp = log10(temp); - else temp = -HUGE_VAL; - break; - case eAbs: - temp = fabs(temp); - break; - case eSin: - temp = sin(temp); - break; - case eCos: - temp = cos(temp); - break; - case eTan: - temp = tan(temp); - break; - case eACos: - temp = acos(temp); - break; - case eASin: - temp = asin(temp); - break; - case eATan: - temp = atan(temp); - break; - case eATan2: - temp = atan2(temp, Parameters[1]->GetValue()); - break; - case eMod: - temp = ((int)temp) % ((int) Parameters[1]->GetValue()); - break; - case eMin: - for (i=1;i<Parameters.size();i++) - { - if (Parameters[i]->GetValue() < temp) temp = Parameters[i]->GetValue(); - } - break; - case eMax: - for (i=1;i<Parameters.size();i++) - { - if (Parameters[i]->GetValue() > temp) temp = Parameters[i]->GetValue(); - } - break; - case eAvg: - for (i=1;i<Parameters.size();i++) - { - temp += Parameters[i]->GetValue(); - } - temp /= Parameters.size(); - break; - case eFrac: - temp = modf(temp, &scratch); - break; - case eInteger: - modf(temp, &scratch); - temp = scratch; - break; - case eRandom: - temp = GaussianRandomNumber(); - break; - default: - cerr << "Unknown function operation type" << endl; - break; - } - - return temp; + unsigned int i; + double scratch; + double temp=0; + + if (cached) return cachedValue; + + try { + temp = Parameters[0]->GetValue(); + } catch (string prop) { + if (PropertyManager->HasNode(prop)) { + ((FGPropertyValue*)Parameters[0])->SetNode(PropertyManager->GetNode(prop)); + temp = Parameters[0]->GetValue(); + } else { + throw("Property " + prop + " was not defined anywhere."); + } + } + + switch (Type) { + case eTopLevel: + break; + case eProduct: + for (i=1;i<Parameters.size();i++) { + temp *= Parameters[i]->GetValue(); + } + break; + case eDifference: + for (i=1;i<Parameters.size();i++) { + temp -= Parameters[i]->GetValue(); + } + break; + case eSum: + for (i=1;i<Parameters.size();i++) { + temp += Parameters[i]->GetValue(); + } + break; + case eQuotient: + if (Parameters[1]->GetValue() != 0.0) + temp /= Parameters[1]->GetValue(); + else + temp = HUGE_VAL; + break; + case ePow: + temp = pow(temp,Parameters[1]->GetValue()); + break; + case eExp: + temp = exp(temp); + break; + case eLog2: + if (temp > 0.00) temp = log10(temp)*invlog2val; + else temp = -HUGE_VAL; + break; + case eLn: + if (temp > 0.00) temp = log(temp); + else temp = -HUGE_VAL; + break; + case eLog10: + if (temp > 0.00) temp = log10(temp); + else temp = -HUGE_VAL; + break; + case eAbs: + temp = fabs(temp); + break; + case eSin: + temp = sin(temp); + break; + case eCos: + temp = cos(temp); + break; + case eTan: + temp = tan(temp); + break; + case eACos: + temp = acos(temp); + break; + case eASin: + temp = asin(temp); + break; + case eATan: + temp = atan(temp); + break; + case eATan2: + temp = atan2(temp, Parameters[1]->GetValue()); + break; + case eMod: + temp = ((int)temp) % ((int) Parameters[1]->GetValue()); + break; + case eMin: + for (i=1;i<Parameters.size();i++) { + if (Parameters[i]->GetValue() < temp) temp = Parameters[i]->GetValue(); + } + break; + case eMax: + for (i=1;i<Parameters.size();i++) { + if (Parameters[i]->GetValue() > temp) temp = Parameters[i]->GetValue(); + } + break; + case eAvg: + for (i=1;i<Parameters.size();i++) { + temp += Parameters[i]->GetValue(); + } + temp /= Parameters.size(); + break; + case eFrac: + temp = modf(temp, &scratch); + break; + case eInteger: + modf(temp, &scratch); + temp = scratch; + break; + case eRandom: + temp = GaussianRandomNumber(); + break; + default: + cerr << "Unknown function operation type" << endl; + break; + } + + return temp; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGFunction::GetValueAsString(void) const { - ostringstream buffer; + ostringstream buffer; - buffer << setw(9) << setprecision(6) << GetValue(); - return buffer.str(); + buffer << setw(9) << setprecision(6) << GetValue(); + return buffer.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFunction::bind(void) { - if ( !Name.empty() ) - { - string tmp; - if (Prefix.empty()) - tmp = PropertyManager->mkPropertyName(Name, false); // Allow upper case - else - tmp = PropertyManager->mkPropertyName(Prefix + "/" + Name, false); // Allow upper case - - PropertyManager->Tie( tmp, this, &FGFunction::GetValue); + if ( !Name.empty() ) { + string tmp; + if (Prefix.empty()) + tmp = PropertyManager->mkPropertyName(Name, false); + else { + if (is_number(Prefix)) { + if (Name.find("#") != string::npos) { // if "#" is found + Name = replace(Name,"#",Prefix); + tmp = PropertyManager->mkPropertyName(Name, false); + } else { + cerr << "Malformed function name with number: " << Prefix + << " and property name: " << Name + << " but no \"#\" sign for substitution." << endl; + } + } else { + tmp = PropertyManager->mkPropertyName(Prefix + "/" + Name, false); + } } + + PropertyManager->Tie( tmp, this, &FGFunction::GetValue); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -469,38 +424,30 @@ void FGFunction::bind(void) void FGFunction::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - if (Type == eTopLevel) - cout << " Function: " << Name << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGFunction" << endl; - if (from == 1) cout << "Destroyed: FGFunction" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + if (Type == eTopLevel) + cout << " Function: " << Name << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGFunction" << endl; + if (from == 1) cout << "Destroyed: FGFunction" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; + } + } } } diff --git a/src/math/FGFunction.h b/src/math/FGFunction.h old mode 100644 new mode 100755 index 5fdf52fd968e14cfd9e7afd175f911f3067c8d61..91a811f9acacf7972e4fe1d04b2965bd2e6465af --- a/src/math/FGFunction.h +++ b/src/math/FGFunction.h @@ -48,8 +48,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGPropertyManager; class Element; @@ -155,93 +154,89 @@ class FGFunction : public FGParameter { public: - /** Constructor. - When this constructor is called, the XML element pointed to in memory by the - element argument is traversed. If other FGParameter-derived objects (values, - functions, properties, or tables) are encountered, this instance of the - FGFunction object will store a pointer to the found object and pass the relevant - Element pointer to the constructor for the new object. In other words, each - FGFunction object maintains a list of "child" FGParameter-derived objects which - in turn may each contain its own list, and so on. At runtime, each object - evaluates its child parameters, which each may have its own child parameters to - evaluate. - @param PropertyManager a pointer to the property manager instance. - @param element a pointer to the Element object containing the function definition. - @param prefix an optional prefix to prepend to the name given to the property - that represents this function (if given). - */ - FGFunction(FGPropertyManager* PropertyManager, Element* element, const std::string& prefix=""); - /// Destructor. - virtual ~FGFunction(); - - /** Retrieves the value of the function object. - @return the total value of the function. */ - double GetValue(void) const; - - /** The value that the function evaluates to, as a string. - @return the value of the function as a string. */ - std::string GetValueAsString(void) const; +/** Constructor. + When this constructor is called, the XML element pointed to in memory by the + element argument is traversed. If other FGParameter-derived objects (values, + functions, properties, or tables) are encountered, this instance of the + FGFunction object will store a pointer to the found object and pass the relevant + Element pointer to the constructor for the new object. In other words, each + FGFunction object maintains a list of "child" FGParameter-derived objects which + in turn may each contain its own list, and so on. At runtime, each object + evaluates its child parameters, which each may have its own child parameters to + evaluate. + @param PropertyManager a pointer to the property manager instance. + @param element a pointer to the Element object containing the function definition. + @param prefix an optional prefix to prepend to the name given to the property + that represents this function (if given). +*/ + FGFunction(FGPropertyManager* PropertyManager, Element* element, const std::string& prefix=""); + /// Destructor. + virtual ~FGFunction(); + +/** Retrieves the value of the function object. + @return the total value of the function. */ + double GetValue(void) const; + +/** The value that the function evaluates to, as a string. + @return the value of the function as a string. */ + std::string GetValueAsString(void) const; /// Retrieves the name of the function. - std::string GetName(void) const - { - return Name; - } - - /** Specifies whether to cache the value of the function, so it is calculated only - once per frame. - If shouldCache is true, then the value of the function is calculated, and - a flag is set so further calculations done this frame will use the cached value. - In order to turn off caching, cacheValue must be called with a false argument. - @param shouldCache specifies whether the function should cache the computed value. */ - void cacheValue(bool shouldCache); + std::string GetName(void) const {return Name;} + +/** Specifies whether to cache the value of the function, so it is calculated only + once per frame. + If shouldCache is true, then the value of the function is calculated, and + a flag is set so further calculations done this frame will use the cached value. + In order to turn off caching, cacheValue must be called with a false argument. + @param shouldCache specifies whether the function should cache the computed value. */ + void cacheValue(bool shouldCache); private: - std::vector <FGParameter*> Parameters; - FGPropertyManager* const PropertyManager; - bool cached; - double invlog2val; - std::string Prefix; - std::string description_string; - std::string property_string; - std::string value_string; - std::string table_string; - std::string p_string; - std::string v_string; - std::string t_string; - std::string function_string; - std::string sum_string; - std::string difference_string; - std::string product_string; - std::string quotient_string; - std::string pow_string; - std::string exp_string; - std::string log2_string; - std::string ln_string; - std::string log10_string; - std::string abs_string; - std::string sin_string; - std::string cos_string; - std::string tan_string; - std::string asin_string; - std::string acos_string; - std::string atan_string; - std::string atan2_string; - std::string min_string; - std::string max_string; - std::string avg_string; - std::string fraction_string; - std::string mod_string; - std::string random_string; - std::string integer_string; - double cachedValue; - enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow, - eExp, eAbs, eSin, eCos, eTan, eASin, eACos, eATan, eATan2, - eMin, eMax, eAvg, eFrac, eInteger, eMod, eRandom, eLog2, eLn, eLog10 - } Type; - std::string Name; - void bind(void); - void Debug(int from); + std::vector <FGParameter*> Parameters; + FGPropertyManager* const PropertyManager; + bool cached; + double invlog2val; + std::string Prefix; + std::string description_string; + std::string property_string; + std::string value_string; + std::string table_string; + std::string p_string; + std::string v_string; + std::string t_string; + std::string function_string; + std::string sum_string; + std::string difference_string; + std::string product_string; + std::string quotient_string; + std::string pow_string; + std::string exp_string; + std::string log2_string; + std::string ln_string; + std::string log10_string; + std::string abs_string; + std::string sin_string; + std::string cos_string; + std::string tan_string; + std::string asin_string; + std::string acos_string; + std::string atan_string; + std::string atan2_string; + std::string min_string; + std::string max_string; + std::string avg_string; + std::string fraction_string; + std::string mod_string; + std::string random_string; + std::string integer_string; + double cachedValue; + enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow, + eExp, eAbs, eSin, eCos, eTan, eASin, eACos, eATan, eATan2, + eMin, eMax, eAvg, eFrac, eInteger, eMod, eRandom, eLog2, eLn, eLog10} Type; + std::string Name; + void bind(void); + void Debug(int from); }; } // namespace JSBSim diff --git a/src/math/FGLocation.cpp b/src/math/FGLocation.cpp index 8b32f93ba60f9b96656b80b36888a8dfc6355a1e..fcba3289e19de9132180e7758b50701944f5311c 100644 --- a/src/math/FGLocation.cpp +++ b/src/math/FGLocation.cpp @@ -43,187 +43,177 @@ INCLUDES #include "FGLocation.h" #include "input_output/FGPropertyManager.h" -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGLocation.cpp,v 1.21 2010/07/02 01:48:12 jberndt Exp $"; +static const char *IdSrc = "$Id: FGLocation.cpp,v 1.23 2010/09/22 11:34:09 jberndt Exp $"; static const char *IdHdr = ID_LOCATION; - +using std::cerr; +using std::endl; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGLocation::FGLocation(void) { - mCacheValid = false; - initial_longitude = 0.0; - a = 0.0; - b = 0.0; - a2 = 0.0; - b2 = 0.0; - e2 = 1.0; - e = 1.0; - eps2 = -1.0; - f = 1.0; - epa = 0.0; - - mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0; - + mCacheValid = false; + initial_longitude = 0.0; + a = 0.0; + b = 0.0; + a2 = 0.0; + b2 = 0.0; + e2 = 1.0; + e = 1.0; + eps2 = -1.0; + f = 1.0; + epa = 0.0; + + mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0; + // initial_longitude = 0.0; - mTl2ec.InitMatrix(); - mTec2l.InitMatrix(); - mTi2ec.InitMatrix(); - mTec2i.InitMatrix(); - mTi2l.InitMatrix(); - mTl2i.InitMatrix(); - mECLoc.InitMatrix(); + mTl2ec.InitMatrix(); + mTec2l.InitMatrix(); + mTi2ec.InitMatrix(); + mTec2i.InitMatrix(); + mTi2l.InitMatrix(); + mTl2i.InitMatrix(); + mECLoc.InitMatrix(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGLocation::FGLocation(double lon, double lat, double radius) { - mCacheValid = false; - - double sinLat = sin(lat); - double cosLat = cos(lat); - double sinLon = sin(lon); - double cosLon = cos(lon); - - a = 0.0; - b = 0.0; - a2 = 0.0; - b2 = 0.0; - e2 = 1.0; - e = 1.0; - eps2 = -1.0; - f = 1.0; - epa = 0.0; - mECLoc = FGColumnVector3( radius*cosLat*cosLon, - radius*cosLat*sinLon, - radius*sinLat ); - mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0; - -// initial_longitude = 0.0 - - ComputeDerived(); + mCacheValid = false; + + double sinLat = sin(lat); + double cosLat = cos(lat); + double sinLon = sin(lon); + double cosLon = cos(lon); + + a = 0.0; + b = 0.0; + a2 = 0.0; + b2 = 0.0; + e2 = 1.0; + e = 1.0; + eps2 = -1.0; + f = 1.0; + epa = 0.0; + mECLoc = FGColumnVector3( radius*cosLat*cosLon, + radius*cosLat*sinLon, + radius*sinLat ); + mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGLocation::SetLongitude(double longitude) { - double rtmp = mECLoc.Magnitude(eX, eY); - // Check if we have zero radius. - // If so set it to 1, so that we can set a position - if (0.0 == mECLoc.Magnitude()) - rtmp = 1.0; + double rtmp = mECLoc.Magnitude(eX, eY); + // Check if we have zero radius. + // If so set it to 1, so that we can set a position + if (0.0 == mECLoc.Magnitude()) + rtmp = 1.0; - // Fast return if we are on the north or south pole ... - if (rtmp == 0.0) - return; + // Fast return if we are on the north or south pole ... + if (rtmp == 0.0) + return; - mCacheValid = false; + mCacheValid = false; - // Need to figure out how to set the initial_longitude here + // Need to figure out how to set the initial_longitude here - mECLoc(eX) = rtmp*cos(longitude); - mECLoc(eY) = rtmp*sin(longitude); + mECLoc(eX) = rtmp*cos(longitude); + mECLoc(eY) = rtmp*sin(longitude); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGLocation::SetLatitude(double latitude) { - mCacheValid = false; - - double r = mECLoc.Magnitude(); - if (r == 0.0) - { - mECLoc(eX) = 1.0; - r = 1.0; - } - - double rtmp = mECLoc.Magnitude(eX, eY); - if (rtmp != 0.0) - { - double fac = r/rtmp*cos(latitude); - mECLoc(eX) *= fac; - mECLoc(eY) *= fac; - } - else - { - mECLoc(eX) = r*cos(latitude); - mECLoc(eY) = 0.0; - } - mECLoc(eZ) = r*sin(latitude); + mCacheValid = false; + + double r = mECLoc.Magnitude(); + if (r == 0.0) { + mECLoc(eX) = 1.0; + r = 1.0; + } + + double rtmp = mECLoc.Magnitude(eX, eY); + if (rtmp != 0.0) { + double fac = r/rtmp*cos(latitude); + mECLoc(eX) *= fac; + mECLoc(eY) *= fac; + } else { + mECLoc(eX) = r*cos(latitude); + mECLoc(eY) = 0.0; + } + mECLoc(eZ) = r*sin(latitude); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGLocation::SetRadius(double radius) { - mCacheValid = false; + mCacheValid = false; - double rold = mECLoc.Magnitude(); - if (rold == 0.0) - mECLoc(eX) = radius; - else - mECLoc *= radius/rold; + double rold = mECLoc.Magnitude(); + if (rold == 0.0) + mECLoc(eX) = radius; + else + mECLoc *= radius/rold; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGLocation::SetPosition(double lon, double lat, double radius) { - mCacheValid = false; + mCacheValid = false; - double sinLat = sin(lat); - double cosLat = cos(lat); - double sinLon = sin(lon); - double cosLon = cos(lon); + double sinLat = sin(lat); + double cosLat = cos(lat); + double sinLon = sin(lon); + double cosLon = cos(lon); // initial_longitude = lon; - mECLoc = FGColumnVector3( radius*cosLat*cosLon, - radius*cosLat*sinLon, - radius*sinLat ); - ComputeDerived(); + mECLoc = FGColumnVector3( radius*cosLat*cosLon, + radius*cosLat*sinLon, + radius*sinLat ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGLocation::SetPositionGeodetic(double lon, double lat, double height) { - mCacheValid = false; - - mGeodLat = lat; - mLon = lon; - GeodeticAltitude = height; + mCacheValid = false; + + mGeodLat = lat; + mLon = lon; + GeodeticAltitude = height; // initial_longitude = mLon; - double RN = a / sqrt(1.0 - e2*sin(mGeodLat)*sin(mGeodLat)); - - mECLoc(eX) = (RN + GeodeticAltitude)*cos(mGeodLat)*cos(mLon); - mECLoc(eY) = (RN + GeodeticAltitude)*cos(mGeodLat)*sin(mLon); - mECLoc(eZ) = ((1 - e2)*RN + GeodeticAltitude)*sin(mGeodLat); + double RN = a / sqrt(1.0 - e2*sin(mGeodLat)*sin(mGeodLat)); + mECLoc(eX) = (RN + GeodeticAltitude)*cos(mGeodLat)*cos(mLon); + mECLoc(eY) = (RN + GeodeticAltitude)*cos(mGeodLat)*sin(mLon); + mECLoc(eZ) = ((1 - e2)*RN + GeodeticAltitude)*sin(mGeodLat); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGLocation::SetEllipse(double semimajor, double semiminor) { - mCacheValid = false; - - a = semimajor; - b = semiminor; - a2 = a*a; - b2 = b*b; - e2 = 1.0 - b2/a2; - e = sqrt(e2); - eps2 = a2/b2 - 1.0; - f = 1.0 - b/a; + mCacheValid = false; + + a = semimajor; + b = semiminor; + a2 = a*a; + b2 = b*b; + e2 = 1.0 - b2/a2; + e = sqrt(e2); + eps2 = a2/b2 - 1.0; + f = 1.0 - b/a; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -233,7 +223,8 @@ void FGLocation::SetEllipse(double semimajor, double semiminor) const FGMatrix33& FGLocation::GetTec2i(void) { - return mTec2i; + ComputeDerived(); + return mTec2i; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -245,123 +236,122 @@ const FGMatrix33& FGLocation::GetTec2i(void) const FGMatrix33& FGLocation::GetTi2ec(void) { - return mTi2ec; + ComputeDerived(); + return mTi2ec; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGLocation::ComputeDerivedUnconditional(void) const { - // The radius is just the Euclidean norm of the vector. - mRadius = mECLoc.Magnitude(); - - // The distance of the location to the Z-axis, which is the axis - // through the poles. - double r02 = mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY); - double rxy = sqrt(r02); - - // Compute the sin/cos values of the longitude - double sinLon, cosLon; - if (rxy == 0.0) - { - sinLon = 0.0; - cosLon = 1.0; - } - else - { - sinLon = mECLoc(eY)/rxy; - cosLon = mECLoc(eX)/rxy; - } - - // Compute the sin/cos values of the latitude - double sinLat, cosLat; - if (mRadius == 0.0) - { - sinLat = 0.0; - cosLat = 1.0; - } - else - { - sinLat = mECLoc(eZ)/mRadius; - cosLat = rxy/mRadius; - } - - // Compute the longitude and latitude itself - if ( mECLoc( eX ) == 0.0 && mECLoc( eY ) == 0.0 ) - mLon = 0.0; - else - mLon = atan2( mECLoc( eY ), mECLoc( eX ) ); - - if ( rxy == 0.0 && mECLoc( eZ ) == 0.0 ) - mLat = 0.0; - else - mLat = atan2( mECLoc(eZ), rxy ); - - // Compute the transform matrices from and to the earth centered frame. - // See Stevens and Lewis, "Aircraft Control and Simulation", Second Edition, - // Eqn. 1.4-13, page 40. In Stevens and Lewis notation, this is C_n/e - the - // orientation of the navigation (local) frame relative to the ECEF frame, - // and a transformation from ECEF to nav (local) frame. - - mTec2l = FGMatrix33( -cosLon*sinLat, -sinLon*sinLat, cosLat, - -sinLon , cosLon , 0.0 , - -cosLon*cosLat, -sinLon*cosLat, -sinLat ); - - // In Stevens and Lewis notation, this is C_e/n - the - // orientation of the ECEF frame relative to the nav (local) frame, - // and a transformation from nav (local) to ECEF frame. - - mTl2ec = mTec2l.Transposed(); - - // Calculate the inertial to ECEF and transpose matrices - double cos_epa = cos(epa); - double sin_epa = sin(epa); - mTi2ec = FGMatrix33( cos_epa, sin_epa, 0.0, - -sin_epa, cos_epa, 0.0, - 0.0, 0.0, 1.0 ); - mTec2i = mTi2ec.Transposed(); - - // Now calculate the local (or nav, or ned) frame to inertial transform matrix, - // and the inverse. - mTl2i = mTec2i * mTl2ec; - mTi2l = mTl2i.Transposed(); - - // Calculate the geodetic latitude base on AIAA Journal of Guidance and Control paper, - // "Improved Method for Calculating Exact Geodetic Latitude and Altitude", and - // "Improved Method for Calculating Exact Geodetic Latitude and Altitude, Revisited", - // author: I. Sofair - - if (a != 0.0 && b != 0.0) + // The radius is just the Euclidean norm of the vector. + mRadius = mECLoc.Magnitude(); + + // The distance of the location to the Z-axis, which is the axis + // through the poles. + double r02 = mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY); + double rxy = sqrt(r02); + + // Compute the sin/cos values of the longitude + double sinLon, cosLon; + if (rxy == 0.0) { + sinLon = 0.0; + cosLon = 1.0; + } else { + sinLon = mECLoc(eY)/rxy; + cosLon = mECLoc(eX)/rxy; + } + + // Compute the sin/cos values of the latitude + double sinLat, cosLat; + if (mRadius == 0.0) { + sinLat = 0.0; + cosLat = 1.0; + } else { + sinLat = mECLoc(eZ)/mRadius; + cosLat = rxy/mRadius; + } + + // Compute the longitude and latitude itself + if ( mECLoc( eX ) == 0.0 && mECLoc( eY ) == 0.0 ) + mLon = 0.0; + else + mLon = atan2( mECLoc( eY ), mECLoc( eX ) ); + + if ( rxy == 0.0 && mECLoc( eZ ) == 0.0 ) + mLat = 0.0; + else + mLat = atan2( mECLoc(eZ), rxy ); + + // Compute the transform matrices from and to the earth centered frame. + // See Stevens and Lewis, "Aircraft Control and Simulation", Second Edition, + // Eqn. 1.4-13, page 40. In Stevens and Lewis notation, this is C_n/e - the + // orientation of the navigation (local) frame relative to the ECEF frame, + // and a transformation from ECEF to nav (local) frame. + + mTec2l = FGMatrix33( -cosLon*sinLat, -sinLon*sinLat, cosLat, + -sinLon , cosLon , 0.0 , + -cosLon*cosLat, -sinLon*cosLat, -sinLat ); + + // In Stevens and Lewis notation, this is C_e/n - the + // orientation of the ECEF frame relative to the nav (local) frame, + // and a transformation from nav (local) to ECEF frame. + + mTl2ec = mTec2l.Transposed(); + + // Calculate the inertial to ECEF and transpose matrices + double cos_epa = cos(epa); + double sin_epa = sin(epa); + mTi2ec = FGMatrix33( cos_epa, sin_epa, 0.0, + -sin_epa, cos_epa, 0.0, + 0.0, 0.0, 1.0 ); + mTec2i = mTi2ec.Transposed(); + + // Now calculate the local (or nav, or ned) frame to inertial transform matrix, + // and the inverse. + mTl2i = mTec2i * mTl2ec; + mTi2l = mTl2i.Transposed(); + + // Calculate the geodetic latitude base on AIAA Journal of Guidance and Control paper, + // "Improved Method for Calculating Exact Geodetic Latitude and Altitude", and + // "Improved Method for Calculating Exact Geodetic Latitude and Altitude, Revisited", + // author: I. Sofair + + if (a != 0.0 && b != 0.0) { + double c, p, q, s, t, u, v, w, z, p2, u2, r0; + double Ne, P, Q0, Q, signz0, sqrt_q, z_term; + p = fabs(mECLoc(eZ))/eps2; + s = r02/(e2*eps2); + p2 = p*p; + q = p2 - b2 + s; + sqrt_q = sqrt(q); + if (q>0) { - double c, p, q, s, t, u, v, w, z, p2, u2, r0; - double Ne, P, Q0, Q, signz0, sqrt_q; - p = fabs(mECLoc(eZ))/eps2; - s = r02/(e2*eps2); - p2 = p*p; - q = p2 - b2 + s; - sqrt_q = sqrt(q); - if (q>0) - { - u = p/sqrt_q; - u2 = p2/q; - v = b2*u2/q; - P = 27.0*v*s/q; - Q0 = sqrt(P+1) + sqrt(P); - Q = pow(Q0, 0.66666666667); - t = (1.0 + Q + 1.0/Q)/6.0; - c = sqrt(u2 - 1 + 2.0*t); - w = (c - u)/2.0; - signz0 = mECLoc(eZ)>=0?1.0:-1.0; - z = signz0*sqrt_q*(w+sqrt(sqrt(t*t+v)-u*w-0.5*t-0.25)); - Ne = a*sqrt(1+eps2*z*z/b2); - mGeodLat = asin((eps2+1.0)*(z/Ne)); - r0 = rxy; - GeodeticAltitude = r0*cos(mGeodLat) + mECLoc(eZ)*sin(mGeodLat) - a2/Ne; - } + u = p/sqrt_q; + u2 = p2/q; + v = b2*u2/q; + P = 27.0*v*s/q; + Q0 = sqrt(P+1) + sqrt(P); + Q = pow(Q0, 0.66666666667); + t = (1.0 + Q + 1.0/Q)/6.0; + c = sqrt(u2 - 1 + 2.0*t); + w = (c - u)/2.0; + signz0 = mECLoc(eZ)>=0?1.0:-1.0; + z_term = sqrt(t*t+v)-u*w-0.5*t-0.25; + if (z_term < 0.0) { + z = 0.0; + } else { + z = signz0*sqrt_q*(w+sqrt(z_term)); + } + Ne = a*sqrt(1+eps2*z*z/b2); + mGeodLat = asin((eps2+1.0)*(z/Ne)); + r0 = rxy; + GeodeticAltitude = r0*cos(mGeodLat) + mECLoc(eZ)*sin(mGeodLat) - a2/Ne; } + } - // Mark the cached values as valid - mCacheValid = true; + // Mark the cached values as valid + mCacheValid = true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/math/FGLocation.h b/src/math/FGLocation.h index 67bfea575d4dd4d3ef933eada816798bedd76a36..46a1b0d9994242f07bbf030529529c676771be72 100644 --- a/src/math/FGLocation.h +++ b/src/math/FGLocation.h @@ -48,14 +48,13 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_LOCATION "$Id: FGLocation.h,v 1.23 2010/08/04 07:28:21 ehofman Exp $" +#define ID_LOCATION "$Id: FGLocation.h,v 1.25 2010/09/18 22:47:24 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -112,11 +111,11 @@ CLASS DOCUMENTATION -that we model a vehicle near the Earth -that the Earth surface radius is about 2*10^7, ft -that we use double values for the representation of the location - + we have an accuracy of about - + 1e-16*2e7ft/1 = 2e-9 ft - + left. This should be sufficient for our needs. Note that this is the same relative accuracy we would have when we compute directly with lon/lat/radius. For the radius value this is clear. For the lon/lat pair @@ -143,7 +142,7 @@ CLASS DOCUMENTATION @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 @author Mathias Froehlich - @version $Id: FGLocation.h,v 1.23 2010/08/04 07:28:21 ehofman Exp $ + @version $Id: FGLocation.h,v 1.25 2010/09/18 22:47:24 jberndt Exp $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -153,519 +152,425 @@ CLASS DECLARATION class FGLocation : virtual FGJSBBase { public: - /** Default constructor. */ - FGLocation(void); - - /** Constructor to set the longitude, latitude and the distance - from the center of the earth. - @param lon longitude - @param lat GEOCENTRIC latitude - @param radius distance from center of earth to vehicle in feet*/ - FGLocation(double lon, double lat, double radius); - - /** Column constructor. */ - FGLocation(const FGColumnVector3& lv) : mECLoc(lv), mCacheValid(false) - { - a = 0.0; - b = 0.0; - a2 = 0.0; - b2 = 0.0; - e2 = 1.0; - e = 1.0; - eps2 = -1.0; - f = 1.0; - } - - /** Copy constructor. */ - FGLocation(const FGLocation& l) - : mECLoc(l.mECLoc), mCacheValid(l.mCacheValid) - { + /** Default constructor. */ + FGLocation(void); + + /** Constructor to set the longitude, latitude and the distance + from the center of the earth. + @param lon longitude + @param lat GEOCENTRIC latitude + @param radius distance from center of earth to vehicle in feet*/ + FGLocation(double lon, double lat, double radius); + + /** Column constructor. */ + FGLocation(const FGColumnVector3& lv) : mECLoc(lv), mCacheValid(false) + { + a = 0.0; + b = 0.0; + a2 = 0.0; + b2 = 0.0; + e2 = 1.0; + e = 1.0; + eps2 = -1.0; + f = 1.0; + } + + /** Copy constructor. */ + FGLocation(const FGLocation& l) + : mECLoc(l.mECLoc), mCacheValid(l.mCacheValid) + { // if (!mCacheValid) return; // This doesn't seem right. - mLon = l.mLon; - mLat = l.mLat; - mRadius = l.mRadius; - - mTl2ec = l.mTl2ec; - mTec2l = l.mTec2l; - - a = l.a; - b = l.b; - a2 = l.a2; - b2 = l.b2; - e2 = l.e2; - e = l.e; - eps2 = l.eps2; - f = l.f; - - initial_longitude = l.initial_longitude; - } - - /** Set the longitude. - @param longitude Longitude in rad to set. - Sets the longitude of the location represented with this class - instance to the value of the given argument. The value is meant - to be in rad. The latitude and the radius value are preserved - with this call with the exception of radius being equal to - zero. If the radius is previously set to zero it is changed to be - equal to 1.0 past this call. Longitude is positive east and negative west. */ - void SetLongitude(double longitude); - - /** Set the latitude. - @param latitude Latitude in rad to set. - Sets the latitude of the location represented with this class - instance to the value of the given argument. The value is meant - to be in rad. The longitude and the radius value are preserved - with this call with the exception of radius being equal to - zero. If the radius is previously set to zero it is changed to be - equal to 1.0 past this call. - Latitude is positive north and negative south. - The arguments should be within the bounds of -pi/2 <= lat <= pi/2. - The behavior of this function with arguments outside this range is - left as an exercise to the gentle reader ... */ - void SetLatitude(double latitude); - - /** Set the distance from the center of the earth. - @param radius Radius in ft to set. - Sets the radius of the location represented with this class - instance to the value of the given argument. The value is meant - to be in ft. The latitude and longitude values are preserved - with this call with the exception of radius being equal to - zero. If the radius is previously set to zero, latitude and - longitude is set equal to zero past this call. - The argument should be positive. - The behavior of this function called with a negative argument is - left as an exercise to the gentle reader ... */ - void SetRadius(double radius); - - /** Sets the longitude, latitude and the distance from the center of the earth. - @param lon longitude in radians - @param lat GEOCENTRIC latitude in radians - @param radius distance from center of earth to vehicle in feet*/ - void SetPosition(double lon, double lat, double radius); - - /** Sets the longitude, latitude and the distance above the reference ellipsoid. - @param lon longitude in radians - @param lat GEODETIC latitude in radians - @param height distance above the reference ellipsoid to vehicle in feet*/ - void SetPositionGeodetic(double lon, double lat, double height); - - /** Sets the semimajor and semiminor axis lengths for this planet. - The eccentricity and flattening are calculated from the semimajor - and semiminor axis lengths */ - void SetEllipse(double semimajor, double semiminor); - - /** Sets the Earth position angle. - This is the relative orientation of the ECEF frame with respect to the - Inertial frame. - @param EPA Earth fixed frame (ECEF) rotation offset about the axis with - respect to the Inertial (ECI) frame in radians. */ - void SetEarthPositionAngle(double EPA) - { - epa = EPA; - mCacheValid = false; - ComputeDerived(); - } - - /** Get the longitude. - @return the longitude in rad of the location represented with this - class instance. The returned values are in the range between - -pi <= lon <= pi. Longitude is positive east and negative west. */ - double GetLongitude() const - { - ComputeDerived(); - return mLon; - } - - /** Get the longitude. - @return the longitude in deg of the location represented with this - class instance. The returned values are in the range between - -180 <= lon <= 180. Longitude is positive east and negative west. */ - double GetLongitudeDeg() const - { - ComputeDerived(); - return radtodeg*mLon; - } - - /** Get the sine of Longitude. */ - double GetSinLongitude() const - { - ComputeDerived(); - return -mTec2l(2,1); - } - - /** Get the cosine of Longitude. */ - double GetCosLongitude() const - { - ComputeDerived(); - return mTec2l(2,2); - } - - /** Get the latitude. - @return the latitude in rad of the location represented with this - class instance. The returned values are in the range between - -pi/2 <= lon <= pi/2. Latitude is positive north and negative south. */ - double GetLatitude() const - { - ComputeDerived(); - return mLat; - } - - /** Get the geodetic latitude. - @return the geodetic latitude in rad of the location represented with this - class instance. The returned values are in the range between - -pi/2 <= lon <= pi/2. Latitude is positive north and negative south. */ - double GetGeodLatitudeRad(void) const - { - ComputeDerived(); - return mGeodLat; - } - - /** Get the latitude. - @return the latitude in deg of the location represented with this - class instance. The returned value is in the range between - -90 <= lon <= 90. Latitude is positive north and negative south. */ - double GetLatitudeDeg() const - { - ComputeDerived(); - return radtodeg*mLat; - } - - /** Get the geodetic latitude in degrees. - @return the geodetic latitude in degrees of the location represented by - this class instance. The returned value is in the range between - -90 <= lon <= 90. Latitude is positive north and negative south. */ - double GetGeodLatitudeDeg(void) const - { - ComputeDerived(); - return radtodeg*mGeodLat; - } - - /** Gets the geodetic altitude in feet. */ - double GetGeodAltitude(void) const - { - return GeodeticAltitude; - } - - /** Get the sine of Latitude. */ - double GetSinLatitude() const - { - ComputeDerived(); - return -mTec2l(3,3); - } - - /** Get the cosine of Latitude. */ - double GetCosLatitude() const - { - ComputeDerived(); - return mTec2l(1,3); - } - - /** Get the cosine of Latitude. */ - double GetTanLatitude() const - { - ComputeDerived(); - double cLat = mTec2l(1,3); - if (cLat == 0.0) - return 0.0; - else - return -mTec2l(3,3)/cLat; - } - - /** Get the distance from the center of the earth. - @return the distance of the location represented with this class - instance to the center of the earth in ft. The radius value is - always positive. */ - //double GetRadius() const { return mECLoc.Magnitude(); } // may not work with FlightGear - double GetRadius() const - { - ComputeDerived(); - return mRadius; - } - - /** Transform matrix from local horizontal to earth centered frame. - Returns a const reference to the rotation matrix of the transform from - the local horizontal frame to the earth centered frame. */ - const FGMatrix33& GetTl2ec(void) const - { - ComputeDerived(); - return mTl2ec; - } - - /** Transform matrix from the earth centered to local horizontal frame. - Returns a const reference to the rotation matrix of the transform from - the earth centered frame to the local horizontal frame. */ - const FGMatrix33& GetTec2l(void) const - { - ComputeDerived(); - return mTec2l; - } - - /** Transform matrix from inertial to earth centered frame. - Returns a const reference to the rotation matrix of the transform from - the inertial frame to the earth centered frame (ECI to ECEF). */ - const FGMatrix33& GetTi2ec(void); - - /** Transform matrix from the earth centered to inertial frame. - Returns a const reference to the rotation matrix of the transform from - the earth centered frame to the inertial frame (ECEF to ECI). */ - const FGMatrix33& GetTec2i(void); - - const FGMatrix33& GetTi2l(void) const - { - return mTi2l; - } - - const FGMatrix33& GetTl2i(void) const - { - return mTl2i; - } - - /** Conversion from Local frame coordinates to a location in the - earth centered and fixed frame. - @param lvec Vector in the local horizontal coordinate frame - @return The location in the earth centered and fixed frame */ - FGLocation LocalToLocation(const FGColumnVector3& lvec) const - { - ComputeDerived(); - return mTl2ec*lvec + mECLoc; - } - - /** Conversion from a location in the earth centered and fixed frame - to local horizontal frame coordinates. - @param ecvec Vector in the earth centered and fixed frame - @return The vector in the local horizontal coordinate frame */ - FGColumnVector3 LocationToLocal(const FGColumnVector3& ecvec) const - { - ComputeDerived(); - return mTec2l*(ecvec - mECLoc); - } - - // For time-stepping, locations have vector properties... - - /** Read access the entries of the vector. - @param idx the component index. - Return the value of the matrix entry at the given index. - Indices are counted starting with 1. - Note that the index given in the argument is unchecked. */ - double operator()(unsigned int idx) const - { - return mECLoc.Entry(idx); - } - - /** Write access the entries of the vector. - @param idx the component index. - @return a reference to the vector entry at the given index. - Indices are counted starting with 1. - Note that the index given in the argument is unchecked. */ - double& operator()(unsigned int idx) - { - mCacheValid = false; - return mECLoc.Entry(idx); - } - - /** Read access the entries of the vector. - @param idx the component index. - @return the value of the matrix entry at the given index. - Indices are counted starting with 1. - This function is just a shortcut for the <tt>double - operator()(unsigned int idx) const</tt> function. It is - used internally to access the elements in a more convenient way. - Note that the index given in the argument is unchecked. */ - double Entry(unsigned int idx) const - { - return mECLoc.Entry(idx); - } - - /** Write access the entries of the vector. - @param idx the component index. - @return a reference to the vector entry at the given index. - Indices are counted starting with 1. - This function is just a shortcut for the double& - operator()(unsigned int idx) function. It is - used internally to access the elements in a more convenient way. - Note that the index given in the argument is unchecked. */ - double& Entry(unsigned int idx) - { - mCacheValid = false; - return mECLoc.Entry(idx); - } - - /** Sets this location via the supplied vector. - The location can be set by an Earth-centered, Earth-fixed (ECEF) frame - position vector. The cache is marked as invalid, so any future requests - for selected important data will cause the parameters to be calculated. - @param v the ECEF column vector in feet. - @return a reference to the FGLocation object. */ - const FGLocation& operator=(const FGColumnVector3& v) - { - mECLoc(eX) = v(eX); - mECLoc(eY) = v(eY); - mECLoc(eZ) = v(eZ); - mCacheValid = false; - ComputeDerived(); - return *this; - } - - /** Sets this location via the supplied location object. - @param v A location object reference. - @return a reference to the FGLocation object. */ - const FGLocation& operator=(const FGLocation& l) - { - mECLoc = l.mECLoc; - mCacheValid = l.mCacheValid; + mLon = l.mLon; + mLat = l.mLat; + mRadius = l.mRadius; + + mTl2ec = l.mTl2ec; + mTec2l = l.mTec2l; + + a = l.a; + b = l.b; + a2 = l.a2; + b2 = l.b2; + e2 = l.e2; + e = l.e; + eps2 = l.eps2; + f = l.f; + + initial_longitude = l.initial_longitude; + } + + /** Set the longitude. + @param longitude Longitude in rad to set. + Sets the longitude of the location represented with this class + instance to the value of the given argument. The value is meant + to be in rad. The latitude and the radius value are preserved + with this call with the exception of radius being equal to + zero. If the radius is previously set to zero it is changed to be + equal to 1.0 past this call. Longitude is positive east and negative west. */ + void SetLongitude(double longitude); + + /** Set the latitude. + @param latitude Latitude in rad to set. + Sets the latitude of the location represented with this class + instance to the value of the given argument. The value is meant + to be in rad. The longitude and the radius value are preserved + with this call with the exception of radius being equal to + zero. If the radius is previously set to zero it is changed to be + equal to 1.0 past this call. + Latitude is positive north and negative south. + The arguments should be within the bounds of -pi/2 <= lat <= pi/2. + The behavior of this function with arguments outside this range is + left as an exercise to the gentle reader ... */ + void SetLatitude(double latitude); + + /** Set the distance from the center of the earth. + @param radius Radius in ft to set. + Sets the radius of the location represented with this class + instance to the value of the given argument. The value is meant + to be in ft. The latitude and longitude values are preserved + with this call with the exception of radius being equal to + zero. If the radius is previously set to zero, latitude and + longitude is set equal to zero past this call. + The argument should be positive. + The behavior of this function called with a negative argument is + left as an exercise to the gentle reader ... */ + void SetRadius(double radius); + + /** Sets the longitude, latitude and the distance from the center of the earth. + @param lon longitude in radians + @param lat GEOCENTRIC latitude in radians + @param radius distance from center of earth to vehicle in feet*/ + void SetPosition(double lon, double lat, double radius); + + /** Sets the longitude, latitude and the distance above the reference ellipsoid. + @param lon longitude in radians + @param lat GEODETIC latitude in radians + @param height distance above the reference ellipsoid to vehicle in feet*/ + void SetPositionGeodetic(double lon, double lat, double height); + + /** Sets the semimajor and semiminor axis lengths for this planet. + The eccentricity and flattening are calculated from the semimajor + and semiminor axis lengths */ + void SetEllipse(double semimajor, double semiminor); + + /** Sets the Earth position angle. + This is the relative orientation of the ECEF frame with respect to the + Inertial frame. + @param EPA Earth fixed frame (ECEF) rotation offset about the axis with + respect to the Inertial (ECI) frame in radians. */ + void SetEarthPositionAngle(double EPA) {epa = EPA; mCacheValid = false;} + + /** Get the longitude. + @return the longitude in rad of the location represented with this + class instance. The returned values are in the range between + -pi <= lon <= pi. Longitude is positive east and negative west. */ + double GetLongitude() const { ComputeDerived(); return mLon; } + + /** Get the longitude. + @return the longitude in deg of the location represented with this + class instance. The returned values are in the range between + -180 <= lon <= 180. Longitude is positive east and negative west. */ + double GetLongitudeDeg() const { ComputeDerived(); return radtodeg*mLon; } + + /** Get the sine of Longitude. */ + double GetSinLongitude() const { ComputeDerived(); return -mTec2l(2,1); } + + /** Get the cosine of Longitude. */ + double GetCosLongitude() const { ComputeDerived(); return mTec2l(2,2); } + + /** Get the latitude. + @return the latitude in rad of the location represented with this + class instance. The returned values are in the range between + -pi/2 <= lon <= pi/2. Latitude is positive north and negative south. */ + double GetLatitude() const { ComputeDerived(); return mLat; } + + /** Get the geodetic latitude. + @return the geodetic latitude in rad of the location represented with this + class instance. The returned values are in the range between + -pi/2 <= lon <= pi/2. Latitude is positive north and negative south. */ + double GetGeodLatitudeRad(void) const { ComputeDerived(); return mGeodLat; } + + /** Get the latitude. + @return the latitude in deg of the location represented with this + class instance. The returned value is in the range between + -90 <= lon <= 90. Latitude is positive north and negative south. */ + double GetLatitudeDeg() const { ComputeDerived(); return radtodeg*mLat; } + + /** Get the geodetic latitude in degrees. + @return the geodetic latitude in degrees of the location represented by + this class instance. The returned value is in the range between + -90 <= lon <= 90. Latitude is positive north and negative south. */ + double GetGeodLatitudeDeg(void) const { ComputeDerived(); return radtodeg*mGeodLat; } + + /** Gets the geodetic altitude in feet. */ + double GetGeodAltitude(void) const {ComputeDerived(); return GeodeticAltitude;} + + /** Get the sine of Latitude. */ + double GetSinLatitude() const { ComputeDerived(); return -mTec2l(3,3); } + + /** Get the cosine of Latitude. */ + double GetCosLatitude() const { ComputeDerived(); return mTec2l(1,3); } + + /** Get the cosine of Latitude. */ + double GetTanLatitude() const { + ComputeDerived(); + double cLat = mTec2l(1,3); + if (cLat == 0.0) + return 0.0; + else + return -mTec2l(3,3)/cLat; + } + + /** Get the distance from the center of the earth. + @return the distance of the location represented with this class + instance to the center of the earth in ft. The radius value is + always positive. */ + //double GetRadius() const { return mECLoc.Magnitude(); } // may not work with FlightGear + double GetRadius() const { ComputeDerived(); return mRadius; } + + /** Transform matrix from local horizontal to earth centered frame. + Returns a const reference to the rotation matrix of the transform from + the local horizontal frame to the earth centered frame. */ + const FGMatrix33& GetTl2ec(void) const { ComputeDerived(); return mTl2ec; } + + /** Transform matrix from the earth centered to local horizontal frame. + Returns a const reference to the rotation matrix of the transform from + the earth centered frame to the local horizontal frame. */ + const FGMatrix33& GetTec2l(void) const { ComputeDerived(); return mTec2l; } + + /** Transform matrix from inertial to earth centered frame. + Returns a const reference to the rotation matrix of the transform from + the inertial frame to the earth centered frame (ECI to ECEF). */ + const FGMatrix33& GetTi2ec(void); + + /** Transform matrix from the earth centered to inertial frame. + Returns a const reference to the rotation matrix of the transform from + the earth centered frame to the inertial frame (ECEF to ECI). */ + const FGMatrix33& GetTec2i(void); + + const FGMatrix33& GetTi2l(void) const {ComputeDerived(); return mTi2l;} + + const FGMatrix33& GetTl2i(void) const {ComputeDerived(); return mTl2i;} + + /** Conversion from Local frame coordinates to a location in the + earth centered and fixed frame. + @param lvec Vector in the local horizontal coordinate frame + @return The location in the earth centered and fixed frame */ + FGLocation LocalToLocation(const FGColumnVector3& lvec) const { + ComputeDerived(); return mTl2ec*lvec + mECLoc; + } + + /** Conversion from a location in the earth centered and fixed frame + to local horizontal frame coordinates. + @param ecvec Vector in the earth centered and fixed frame + @return The vector in the local horizontal coordinate frame */ + FGColumnVector3 LocationToLocal(const FGColumnVector3& ecvec) const { + ComputeDerived(); return mTec2l*(ecvec - mECLoc); + } + + // For time-stepping, locations have vector properties... + + /** Read access the entries of the vector. + @param idx the component index. + Return the value of the matrix entry at the given index. + Indices are counted starting with 1. + Note that the index given in the argument is unchecked. */ + double operator()(unsigned int idx) const { return mECLoc.Entry(idx); } + + /** Write access the entries of the vector. + @param idx the component index. + @return a reference to the vector entry at the given index. + Indices are counted starting with 1. + Note that the index given in the argument is unchecked. */ + double& operator()(unsigned int idx) { mCacheValid = false; return mECLoc.Entry(idx); } + + /** Read access the entries of the vector. + @param idx the component index. + @return the value of the matrix entry at the given index. + Indices are counted starting with 1. + This function is just a shortcut for the <tt>double + operator()(unsigned int idx) const</tt> function. It is + used internally to access the elements in a more convenient way. + Note that the index given in the argument is unchecked. */ + double Entry(unsigned int idx) const { return mECLoc.Entry(idx); } + + /** Write access the entries of the vector. + @param idx the component index. + @return a reference to the vector entry at the given index. + Indices are counted starting with 1. + This function is just a shortcut for the double& + operator()(unsigned int idx) function. It is + used internally to access the elements in a more convenient way. + Note that the index given in the argument is unchecked. */ + double& Entry(unsigned int idx) { + mCacheValid = false; return mECLoc.Entry(idx); + } + + /** Sets this location via the supplied vector. + The location can be set by an Earth-centered, Earth-fixed (ECEF) frame + position vector. The cache is marked as invalid, so any future requests + for selected important data will cause the parameters to be calculated. + @param v the ECEF column vector in feet. + @return a reference to the FGLocation object. */ + const FGLocation& operator=(const FGColumnVector3& v) + { + mECLoc(eX) = v(eX); + mECLoc(eY) = v(eY); + mECLoc(eZ) = v(eZ); + mCacheValid = false; + ComputeDerived(); + return *this; + } + + /** Sets this location via the supplied location object. + @param v A location object reference. + @return a reference to the FGLocation object. */ + const FGLocation& operator=(const FGLocation& l) + { + mECLoc = l.mECLoc; + mCacheValid = l.mCacheValid; // if (!mCacheValid) return *this; // Why is this here for an assignment operator? - mLon = l.mLon; - mLat = l.mLat; - mRadius = l.mRadius; - - mTl2ec = l.mTl2ec; - mTec2l = l.mTec2l; - - a = l.a; - b = l.b; - a2 = l.a2; - b2 = l.b2; - e2 = l.e2; - e = l.e; - eps2 = l.eps2; - f = l.f; - - initial_longitude = l.initial_longitude; - - return *this; - } - - /** This operator returns true if the ECEF location vectors for the two - location objects are equal. */ - bool operator==(const FGLocation& l) const - { - return mECLoc == l.mECLoc; - } - - /** This operator returns true if the ECEF location vectors for the two - location objects are not equal. */ - bool operator!=(const FGLocation& l) const - { - return ! operator==(l); - } - - /** This operator adds the ECEF position vectors. - The supplied vector (right side) is added to the ECEF position vector - on the left side of the equality, and a pointer to this object is - returned. */ - const FGLocation& operator+=(const FGLocation &l) - { - mCacheValid = false; - mECLoc += l.mECLoc; - return *this; - } - - const FGLocation& operator-=(const FGLocation &l) - { - mCacheValid = false; - mECLoc -= l.mECLoc; - return *this; - } - - const FGLocation& operator*=(double scalar) - { - mCacheValid = false; - mECLoc *= scalar; - return *this; - } - - const FGLocation& operator/=(double scalar) - { - return operator*=(1.0/scalar); - } - - FGLocation operator+(const FGLocation& l) const - { - return FGLocation(mECLoc + l.mECLoc); - } - - FGLocation operator-(const FGLocation& l) const - { - return FGLocation(mECLoc - l.mECLoc); - } - - FGLocation operator*(double scalar) const - { - return FGLocation(scalar*mECLoc); - } - - /** Cast to a simple 3d vector */ - operator const FGColumnVector3&() const - { - return mECLoc; - } + mLon = l.mLon; + mLat = l.mLat; + mRadius = l.mRadius; + + mTl2ec = l.mTl2ec; + mTec2l = l.mTec2l; + + a = l.a; + b = l.b; + a2 = l.a2; + b2 = l.b2; + e2 = l.e2; + e = l.e; + eps2 = l.eps2; + f = l.f; + + initial_longitude = l.initial_longitude; + mGeodLat = l.mGeodLat; + GeodeticAltitude = l.GeodeticAltitude; + + return *this; + } + + /** This operator returns true if the ECEF location vectors for the two + location objects are equal. */ + bool operator==(const FGLocation& l) const { + return mECLoc == l.mECLoc; + } + + /** This operator returns true if the ECEF location vectors for the two + location objects are not equal. */ + bool operator!=(const FGLocation& l) const { return ! operator==(l); } + + /** This operator adds the ECEF position vectors. + The supplied vector (right side) is added to the ECEF position vector + on the left side of the equality, and a pointer to this object is + returned. */ + const FGLocation& operator+=(const FGLocation &l) { + mCacheValid = false; + mECLoc += l.mECLoc; + return *this; + } + + const FGLocation& operator-=(const FGLocation &l) { + mCacheValid = false; + mECLoc -= l.mECLoc; + return *this; + } + + const FGLocation& operator*=(double scalar) { + mCacheValid = false; + mECLoc *= scalar; + return *this; + } + + const FGLocation& operator/=(double scalar) { + return operator*=(1.0/scalar); + } + + FGLocation operator+(const FGLocation& l) const { + return FGLocation(mECLoc + l.mECLoc); + } + + FGLocation operator-(const FGLocation& l) const { + return FGLocation(mECLoc - l.mECLoc); + } + + FGLocation operator*(double scalar) const { + return FGLocation(scalar*mECLoc); + } + + /** Cast to a simple 3d vector */ + operator const FGColumnVector3&() const { + return mECLoc; + } private: - /** Computation of derived values. - This function re-computes the derived values like lat/lon and - transformation matrices. It does this unconditionally. */ - void ComputeDerivedUnconditional(void) const; - - /** Computation of derived values. - This function checks if the derived values like lat/lon and - transformation matrices are already computed. If so, it - returns. If they need to be computed this is done here. */ - void ComputeDerived(void) const - { - if (!mCacheValid) - ComputeDerivedUnconditional(); - } - - /** The coordinates in the earth centered frame. This is the master copy. - The coordinate frame has its center in the middle of the earth. - Its x-axis points from the center of the earth towards a - location with zero latitude and longitude on the earths - surface. The y-axis points from the center of the earth towards a - location with zero latitude and 90deg longitude on the earths - surface. The z-axis points from the earths center to the - geographic north pole. - @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 */ - FGColumnVector3 mECLoc; - - /** The cached lon/lat/radius values. */ - mutable double mLon; - mutable double mLat; - mutable double mRadius; - mutable double mGeodLat; - mutable double GeodeticAltitude; - - double initial_longitude; - - /** The cached rotation matrices from and to the associated frames. */ - mutable FGMatrix33 mTl2ec; - mutable FGMatrix33 mTec2l; - mutable FGMatrix33 mTi2ec; - mutable FGMatrix33 mTec2i; - mutable FGMatrix33 mTi2l; - mutable FGMatrix33 mTl2i; - - double epa; - - /* Terms for geodetic latitude calculation. Values are from WGS84 model */ - double a; // Earth semimajor axis in feet (6,378,137.0 meters) - double b; // Earth semiminor axis in feet (6,356,752.3142 meters) - double a2; - double b2; - double e; // Earth eccentricity - double e2; // Earth eccentricity squared - double eps2; // - double f; // Flattening - - /** A data validity flag. - This class implements caching of the derived values like the - orthogonal rotation matrices or the lon/lat/radius values. For caching we - carry a flag which signals if the values are valid or not. - The C++ keyword "mutable" tells the compiler that the data member is - allowed to change during a const member function. */ - mutable bool mCacheValid; + /** Computation of derived values. + This function re-computes the derived values like lat/lon and + transformation matrices. It does this unconditionally. */ + void ComputeDerivedUnconditional(void) const; + + /** Computation of derived values. + This function checks if the derived values like lat/lon and + transformation matrices are already computed. If so, it + returns. If they need to be computed this is done here. */ + void ComputeDerived(void) const { + if (!mCacheValid) + ComputeDerivedUnconditional(); + } + + /** The coordinates in the earth centered frame. This is the master copy. + The coordinate frame has its center in the middle of the earth. + Its x-axis points from the center of the earth towards a + location with zero latitude and longitude on the earths + surface. The y-axis points from the center of the earth towards a + location with zero latitude and 90deg longitude on the earths + surface. The z-axis points from the earths center to the + geographic north pole. + @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 */ + FGColumnVector3 mECLoc; + + /** The cached lon/lat/radius values. */ + mutable double mLon; + mutable double mLat; + mutable double mRadius; + mutable double mGeodLat; + mutable double GeodeticAltitude; + + double initial_longitude; + + /** The cached rotation matrices from and to the associated frames. */ + mutable FGMatrix33 mTl2ec; + mutable FGMatrix33 mTec2l; + mutable FGMatrix33 mTi2ec; + mutable FGMatrix33 mTec2i; + mutable FGMatrix33 mTi2l; + mutable FGMatrix33 mTl2i; + + double epa; + + /* Terms for geodetic latitude calculation. Values are from WGS84 model */ + double a; // Earth semimajor axis in feet (6,378,137.0 meters) + double b; // Earth semiminor axis in feet (6,356,752.3142 meters) + double a2; + double b2; + double e; // Earth eccentricity + double e2; // Earth eccentricity squared + double eps2; // + double f; // Flattening + + /** A data validity flag. + This class implements caching of the derived values like the + orthogonal rotation matrices or the lon/lat/radius values. For caching we + carry a flag which signals if the values are valid or not. + The C++ keyword "mutable" tells the compiler that the data member is + allowed to change during a const member function. */ + mutable bool mCacheValid; }; /** Scalar multiplication. @@ -676,7 +581,7 @@ private: Multiply the Vector with a scalar value. */ inline FGLocation operator*(double scalar, const FGLocation& l) { - return l.operator*(scalar); + return l.operator*(scalar); } } // namespace JSBSim diff --git a/src/math/FGMatrix33.cpp b/src/math/FGMatrix33.cpp index bb45ef1d36a9bc5da4bebcdc5e93e0ecf21f679e..379b370048469bdf569c156b4a2f29a6fed7c345 100644 --- a/src/math/FGMatrix33.cpp +++ b/src/math/FGMatrix33.cpp @@ -46,8 +46,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGMatrix33.cpp,v 1.10 2010/07/01 23:13:19 jberndt Exp $"; static const char *IdHdr = ID_MATRIX33; @@ -60,184 +59,174 @@ CLASS IMPLEMENTATION FGMatrix33::FGMatrix33(void) { - data[0] = data[1] = data[2] = data[3] = data[4] = data[5] = - data[6] = data[7] = data[8] = 0.0; + data[0] = data[1] = data[2] = data[3] = data[4] = data[5] = + data[6] = data[7] = data[8] = 0.0; - // Debug(0); + // Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGMatrix33::Dump(const string& delimiter) const { - ostringstream buffer; - buffer << setw(12) << setprecision(10) << data[0] << delimiter; - buffer << setw(12) << setprecision(10) << data[3] << delimiter; - buffer << setw(12) << setprecision(10) << data[6] << delimiter; - buffer << setw(12) << setprecision(10) << data[1] << delimiter; - buffer << setw(12) << setprecision(10) << data[4] << delimiter; - buffer << setw(12) << setprecision(10) << data[7] << delimiter; - buffer << setw(12) << setprecision(10) << data[2] << delimiter; - buffer << setw(12) << setprecision(10) << data[5] << delimiter; - buffer << setw(12) << setprecision(10) << data[8]; - return buffer.str(); + ostringstream buffer; + buffer << setw(12) << setprecision(10) << data[0] << delimiter; + buffer << setw(12) << setprecision(10) << data[3] << delimiter; + buffer << setw(12) << setprecision(10) << data[6] << delimiter; + buffer << setw(12) << setprecision(10) << data[1] << delimiter; + buffer << setw(12) << setprecision(10) << data[4] << delimiter; + buffer << setw(12) << setprecision(10) << data[7] << delimiter; + buffer << setw(12) << setprecision(10) << data[2] << delimiter; + buffer << setw(12) << setprecision(10) << data[5] << delimiter; + buffer << setw(12) << setprecision(10) << data[8]; + return buffer.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGMatrix33::Dump(const string& delimiter, const string& prefix) const { - ostringstream buffer; + ostringstream buffer; - buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[0] << delimiter; - buffer << right << fixed << setw(9) << setprecision(6) << data[3] << delimiter; - buffer << right << fixed << setw(9) << setprecision(6) << data[6] << endl; + buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[0] << delimiter; + buffer << right << fixed << setw(9) << setprecision(6) << data[3] << delimiter; + buffer << right << fixed << setw(9) << setprecision(6) << data[6] << endl; - buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[1] << delimiter; - buffer << right << fixed << setw(9) << setprecision(6) << data[4] << delimiter; - buffer << right << fixed << setw(9) << setprecision(6) << data[7] << endl; + buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[1] << delimiter; + buffer << right << fixed << setw(9) << setprecision(6) << data[4] << delimiter; + buffer << right << fixed << setw(9) << setprecision(6) << data[7] << endl; - buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[2] << delimiter; - buffer << right << fixed << setw(9) << setprecision(6) << data[5] << delimiter; - buffer << right << fixed << setw(9) << setprecision(6) << data[8]; + buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[2] << delimiter; + buffer << right << fixed << setw(9) << setprecision(6) << data[5] << delimiter; + buffer << right << fixed << setw(9) << setprecision(6) << data[8]; - buffer << setw(0) << left; + buffer << setw(0) << left; - return buffer.str(); + return buffer.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGQuaternion FGMatrix33::GetQuaternion(void) { - FGQuaternion Q; + FGQuaternion Q; - double tempQ[4]; - int idx; + double tempQ[4]; + int idx; - tempQ[0] = 1.0 + data[0] + data[4] + data[8]; - tempQ[1] = 1.0 + data[0] - data[4] - data[8]; - tempQ[2] = 1.0 - data[0] + data[4] - data[8]; - tempQ[3] = 1.0 - data[0] - data[4] + data[8]; + tempQ[0] = 1.0 + data[0] + data[4] + data[8]; + tempQ[1] = 1.0 + data[0] - data[4] - data[8]; + tempQ[2] = 1.0 - data[0] + data[4] - data[8]; + tempQ[3] = 1.0 - data[0] - data[4] + data[8]; - // Find largest of the above - idx = 0; - for (int i=1; i<4; i++) if (tempQ[i] > tempQ[idx]) idx = i; + // Find largest of the above + idx = 0; + for (int i=1; i<4; i++) if (tempQ[i] > tempQ[idx]) idx = i; - switch (idx) - { + switch(idx) { case 0: - Q(1) = 0.50*sqrt(tempQ[0]); - Q(2) = 0.25*(data[7] - data[5])/Q(1); - Q(3) = 0.25*(data[2] - data[6])/Q(1); - Q(4) = 0.25*(data[3] - data[1])/Q(1); - break; + Q(1) = 0.50*sqrt(tempQ[0]); + Q(2) = 0.25*(data[7] - data[5])/Q(1); + Q(3) = 0.25*(data[2] - data[6])/Q(1); + Q(4) = 0.25*(data[3] - data[1])/Q(1); + break; case 1: - Q(2) = 0.50*sqrt(tempQ[1]); - Q(1) = 0.25*(data[7] - data[5])/Q(2); - Q(3) = 0.25*(data[3] + data[1])/Q(2); - Q(4) = 0.25*(data[2] + data[6])/Q(2); - break; + Q(2) = 0.50*sqrt(tempQ[1]); + Q(1) = 0.25*(data[7] - data[5])/Q(2); + Q(3) = 0.25*(data[3] + data[1])/Q(2); + Q(4) = 0.25*(data[2] + data[6])/Q(2); + break; case 2: - Q(3) = 0.50*sqrt(tempQ[2]); - Q(1) = 0.25*(data[2] - data[6])/Q(3); - Q(2) = 0.25*(data[3] + data[1])/Q(3); - Q(4) = 0.25*(data[7] + data[5])/Q(3); - break; + Q(3) = 0.50*sqrt(tempQ[2]); + Q(1) = 0.25*(data[2] - data[6])/Q(3); + Q(2) = 0.25*(data[3] + data[1])/Q(3); + Q(4) = 0.25*(data[7] + data[5])/Q(3); + break; case 3: - Q(4) = 0.50*sqrt(tempQ[3]); - Q(1) = 0.25*(data[3] - data[1])/Q(4); - Q(2) = 0.25*(data[6] + data[2])/Q(4); - Q(3) = 0.25*(data[7] + data[5])/Q(4); - break; + Q(4) = 0.50*sqrt(tempQ[3]); + Q(1) = 0.25*(data[3] - data[1])/Q(4); + Q(2) = 0.25*(data[6] + data[2])/Q(4); + Q(3) = 0.25*(data[7] + data[5])/Q(4); + break; default: - //error - break; - } + //error + break; + } - return (Q); + return (Q); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ostream& operator<<(ostream& os, const FGMatrix33& M) { - for (unsigned int i=1; i<=M.Rows(); i++) - { - for (unsigned int j=1; j<=M.Cols(); j++) - { - if (i == M.Rows() && j == M.Cols()) - os << M(i,j); - else - os << M(i,j) << ", "; - } + for (unsigned int i=1; i<=M.Rows(); i++) { + for (unsigned int j=1; j<=M.Cols(); j++) { + if (i == M.Rows() && j == M.Cols()) + os << M(i,j); + else + os << M(i,j) << ", "; } - return os; + } + return os; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% istream& operator>>(istream& is, FGMatrix33& M) { - for (unsigned int i=1; i<=M.Rows(); i++) - { - for (unsigned int j=1; j<=M.Cols(); j++) - { - is >> M(i,j); - } + for (unsigned int i=1; i<=M.Rows(); i++) { + for (unsigned int j=1; j<=M.Cols(); j++) { + is >> M(i,j); } - return is; + } + return is; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -double FGMatrix33::Determinant(void) const -{ - return data[0]*data[4]*data[8] + data[3]*data[7]*data[2] - + data[6]*data[1]*data[5] - data[6]*data[4]*data[2] - - data[3]*data[1]*data[8] - data[7]*data[5]*data[0]; +double FGMatrix33::Determinant(void) const { + return data[0]*data[4]*data[8] + data[3]*data[7]*data[2] + + data[6]*data[1]*data[5] - data[6]*data[4]*data[2] + - data[3]*data[1]*data[8] - data[7]*data[5]*data[0]; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FGMatrix33 FGMatrix33::Inverse(void) const -{ - // Compute the inverse of a general matrix using Cramers rule. - // I guess googling for cramers rule gives tons of references - // for this. :) - - if (Determinant() != 0.0) - { - double rdet = 1.0/Determinant(); - - double i11 = rdet*(data[4]*data[8]-data[7]*data[5]); - double i21 = rdet*(data[7]*data[2]-data[1]*data[8]); - double i31 = rdet*(data[1]*data[5]-data[4]*data[2]); - double i12 = rdet*(data[6]*data[5]-data[3]*data[8]); - double i22 = rdet*(data[0]*data[8]-data[6]*data[2]); - double i32 = rdet*(data[3]*data[2]-data[0]*data[5]); - double i13 = rdet*(data[3]*data[7]-data[6]*data[4]); - double i23 = rdet*(data[6]*data[1]-data[0]*data[7]); - double i33 = rdet*(data[0]*data[4]-data[3]*data[1]); - - return FGMatrix33( i11, i12, i13, - i21, i22, i23, - i31, i32, i33 ); - } - else - { - return FGMatrix33( 0, 0, 0, - 0, 0, 0, - 0, 0, 0 ); - } +FGMatrix33 FGMatrix33::Inverse(void) const { + // Compute the inverse of a general matrix using Cramers rule. + // I guess googling for cramers rule gives tons of references + // for this. :) + + if (Determinant() != 0.0) { + double rdet = 1.0/Determinant(); + + double i11 = rdet*(data[4]*data[8]-data[7]*data[5]); + double i21 = rdet*(data[7]*data[2]-data[1]*data[8]); + double i31 = rdet*(data[1]*data[5]-data[4]*data[2]); + double i12 = rdet*(data[6]*data[5]-data[3]*data[8]); + double i22 = rdet*(data[0]*data[8]-data[6]*data[2]); + double i32 = rdet*(data[3]*data[2]-data[0]*data[5]); + double i13 = rdet*(data[3]*data[7]-data[6]*data[4]); + double i23 = rdet*(data[6]*data[1]-data[0]*data[7]); + double i33 = rdet*(data[0]*data[4]-data[3]*data[1]); + + return FGMatrix33( i11, i12, i13, + i21, i22, i23, + i31, i32, i33 ); + } else { + return FGMatrix33( 0, 0, 0, + 0, 0, 0, + 0, 0, 0 ); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGMatrix33::InitMatrix(void) { - data[0] = data[1] = data[2] = data[3] = data[4] = data[5] = - data[6] = data[7] = data[8] = 0.0; + data[0] = data[1] = data[2] = data[3] = data[4] = data[5] = + data[6] = data[7] = data[8] = 0.0; } // ***************************************************************************** @@ -246,79 +235,79 @@ void FGMatrix33::InitMatrix(void) FGMatrix33 FGMatrix33::operator-(const FGMatrix33& M) const { - return FGMatrix33( data[0] - M.data[0], - data[3] - M.data[3], - data[6] - M.data[6], - data[1] - M.data[1], - data[4] - M.data[4], - data[7] - M.data[7], - data[2] - M.data[2], - data[5] - M.data[5], - data[8] - M.data[8] ); + return FGMatrix33( data[0] - M.data[0], + data[3] - M.data[3], + data[6] - M.data[6], + data[1] - M.data[1], + data[4] - M.data[4], + data[7] - M.data[7], + data[2] - M.data[2], + data[5] - M.data[5], + data[8] - M.data[8] ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33& FGMatrix33::operator-=(const FGMatrix33 &M) { - data[0] -= M.data[0]; - data[1] -= M.data[1]; - data[2] -= M.data[2]; - data[3] -= M.data[3]; - data[4] -= M.data[4]; - data[5] -= M.data[5]; - data[6] -= M.data[6]; - data[7] -= M.data[7]; - data[8] -= M.data[8]; - - return *this; + data[0] -= M.data[0]; + data[1] -= M.data[1]; + data[2] -= M.data[2]; + data[3] -= M.data[3]; + data[4] -= M.data[4]; + data[5] -= M.data[5]; + data[6] -= M.data[6]; + data[7] -= M.data[7]; + data[8] -= M.data[8]; + + return *this; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33 FGMatrix33::operator+(const FGMatrix33& M) const { - return FGMatrix33( data[0] + M.data[0], - data[3] + M.data[3], - data[6] + M.data[6], - data[1] + M.data[1], - data[4] + M.data[4], - data[7] + M.data[7], - data[2] + M.data[2], - data[5] + M.data[5], - data[8] + M.data[8] ); + return FGMatrix33( data[0] + M.data[0], + data[3] + M.data[3], + data[6] + M.data[6], + data[1] + M.data[1], + data[4] + M.data[4], + data[7] + M.data[7], + data[2] + M.data[2], + data[5] + M.data[5], + data[8] + M.data[8] ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M) { - data[0] += M.data[0]; - data[3] += M.data[3]; - data[6] += M.data[6]; - data[1] += M.data[1]; - data[4] += M.data[4]; - data[7] += M.data[7]; - data[2] += M.data[2]; - data[5] += M.data[5]; - data[8] += M.data[8]; - - return *this; + data[0] += M.data[0]; + data[3] += M.data[3]; + data[6] += M.data[6]; + data[1] += M.data[1]; + data[4] += M.data[4]; + data[7] += M.data[7]; + data[2] += M.data[2]; + data[5] += M.data[5]; + data[8] += M.data[8]; + + return *this; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33 FGMatrix33::operator*(const double scalar) const { - return FGMatrix33( scalar * data[0], - scalar * data[3], - scalar * data[6], - scalar * data[1], - scalar * data[4], - scalar * data[7], - scalar * data[2], - scalar * data[5], - scalar * data[8] ); + return FGMatrix33( scalar * data[0], + scalar * data[3], + scalar * data[6], + scalar * data[1], + scalar * data[4], + scalar * data[7], + scalar * data[2], + scalar * data[5], + scalar * data[8] ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -340,163 +329,151 @@ FGMatrix33 operator*(double scalar, FGMatrix33 &M) FGMatrix33& FGMatrix33::operator*=(const double scalar) { - data[0] *= scalar; - data[3] *= scalar; - data[6] *= scalar; - data[1] *= scalar; - data[4] *= scalar; - data[7] *= scalar; - data[2] *= scalar; - data[5] *= scalar; - data[8] *= scalar; - - return *this; + data[0] *= scalar; + data[3] *= scalar; + data[6] *= scalar; + data[1] *= scalar; + data[4] *= scalar; + data[7] *= scalar; + data[2] *= scalar; + data[5] *= scalar; + data[8] *= scalar; + + return *this; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33 FGMatrix33::operator*(const FGMatrix33& M) const { - FGMatrix33 Product; - - Product.data[0] = data[0]*M.data[0] + data[3]*M.data[1] + data[6]*M.data[2]; - Product.data[3] = data[0]*M.data[3] + data[3]*M.data[4] + data[6]*M.data[5]; - Product.data[6] = data[0]*M.data[6] + data[3]*M.data[7] + data[6]*M.data[8]; - Product.data[1] = data[1]*M.data[0] + data[4]*M.data[1] + data[7]*M.data[2]; - Product.data[4] = data[1]*M.data[3] + data[4]*M.data[4] + data[7]*M.data[5]; - Product.data[7] = data[1]*M.data[6] + data[4]*M.data[7] + data[7]*M.data[8]; - Product.data[2] = data[2]*M.data[0] + data[5]*M.data[1] + data[8]*M.data[2]; - Product.data[5] = data[2]*M.data[3] + data[5]*M.data[4] + data[8]*M.data[5]; - Product.data[8] = data[2]*M.data[6] + data[5]*M.data[7] + data[8]*M.data[8]; - - return Product; + FGMatrix33 Product; + + Product.data[0] = data[0]*M.data[0] + data[3]*M.data[1] + data[6]*M.data[2]; + Product.data[3] = data[0]*M.data[3] + data[3]*M.data[4] + data[6]*M.data[5]; + Product.data[6] = data[0]*M.data[6] + data[3]*M.data[7] + data[6]*M.data[8]; + Product.data[1] = data[1]*M.data[0] + data[4]*M.data[1] + data[7]*M.data[2]; + Product.data[4] = data[1]*M.data[3] + data[4]*M.data[4] + data[7]*M.data[5]; + Product.data[7] = data[1]*M.data[6] + data[4]*M.data[7] + data[7]*M.data[8]; + Product.data[2] = data[2]*M.data[0] + data[5]*M.data[1] + data[8]*M.data[2]; + Product.data[5] = data[2]*M.data[3] + data[5]*M.data[4] + data[8]*M.data[5]; + Product.data[8] = data[2]*M.data[6] + data[5]*M.data[7] + data[8]*M.data[8]; + + return Product; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33& FGMatrix33::operator*=(const FGMatrix33& M) { - // FIXME: Make compiler friendlier - double a,b,c; - - a = data[0]; - b=data[3]; - c=data[6]; - data[0] = a*M.data[0] + b*M.data[1] + c*M.data[2]; - data[3] = a*M.data[3] + b*M.data[4] + c*M.data[5]; - data[6] = a*M.data[6] + b*M.data[7] + c*M.data[8]; - - a = data[1]; - b=data[4]; - c=data[7]; - data[1] = a*M.data[0] + b*M.data[1] + c*M.data[2]; - data[4] = a*M.data[3] + b*M.data[4] + c*M.data[5]; - data[7] = a*M.data[6] + b*M.data[7] + c*M.data[8]; - - a = data[2]; - b=data[5]; - c=data[8]; - data[2] = a*M.data[0] + b*M.data[1] + c*M.data[2]; - data[5] = a*M.data[3] + b*M.data[4] + c*M.data[5]; - data[8] = a*M.data[6] + b*M.data[7] + c*M.data[8]; - - return *this; + // FIXME: Make compiler friendlier + double a,b,c; + + a = data[0]; b=data[3]; c=data[6]; + data[0] = a*M.data[0] + b*M.data[1] + c*M.data[2]; + data[3] = a*M.data[3] + b*M.data[4] + c*M.data[5]; + data[6] = a*M.data[6] + b*M.data[7] + c*M.data[8]; + + a = data[1]; b=data[4]; c=data[7]; + data[1] = a*M.data[0] + b*M.data[1] + c*M.data[2]; + data[4] = a*M.data[3] + b*M.data[4] + c*M.data[5]; + data[7] = a*M.data[6] + b*M.data[7] + c*M.data[8]; + + a = data[2]; b=data[5]; c=data[8]; + data[2] = a*M.data[0] + b*M.data[1] + c*M.data[2]; + data[5] = a*M.data[3] + b*M.data[4] + c*M.data[5]; + data[8] = a*M.data[6] + b*M.data[7] + c*M.data[8]; + + return *this; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33 FGMatrix33::operator/(const double scalar) const { - FGMatrix33 Quot; - - if ( scalar != 0 ) - { - double tmp = 1.0/scalar; - Quot.data[0] = data[0] * tmp; - Quot.data[3] = data[3] * tmp; - Quot.data[6] = data[6] * tmp; - Quot.data[1] = data[1] * tmp; - Quot.data[4] = data[4] * tmp; - Quot.data[7] = data[7] * tmp; - Quot.data[2] = data[2] * tmp; - Quot.data[5] = data[5] * tmp; - Quot.data[8] = data[8] * tmp; - } - else - { - MatrixException mE; - mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)"; - throw mE; - } - return Quot; + FGMatrix33 Quot; + + if ( scalar != 0 ) { + double tmp = 1.0/scalar; + Quot.data[0] = data[0] * tmp; + Quot.data[3] = data[3] * tmp; + Quot.data[6] = data[6] * tmp; + Quot.data[1] = data[1] * tmp; + Quot.data[4] = data[4] * tmp; + Quot.data[7] = data[7] * tmp; + Quot.data[2] = data[2] * tmp; + Quot.data[5] = data[5] * tmp; + Quot.data[8] = data[8] * tmp; + } else { + MatrixException mE; + mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)"; + throw mE; + } + return Quot; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33& FGMatrix33::operator/=(const double scalar) { - if ( scalar != 0 ) - { - double tmp = 1.0/scalar; - data[0] *= tmp; - data[3] *= tmp; - data[6] *= tmp; - data[1] *= tmp; - data[4] *= tmp; - data[7] *= tmp; - data[2] *= tmp; - data[5] *= tmp; - data[8] *= tmp; - } - else - { - MatrixException mE; - mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)"; - throw mE; - } - return *this; + if ( scalar != 0 ) { + double tmp = 1.0/scalar; + data[0] *= tmp; + data[3] *= tmp; + data[6] *= tmp; + data[1] *= tmp; + data[4] *= tmp; + data[7] *= tmp; + data[2] *= tmp; + data[5] *= tmp; + data[8] *= tmp; + } else { + MatrixException mE; + mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)"; + throw mE; + } + return *this; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGMatrix33::T(void) { - double tmp; + double tmp; - tmp = data[3]; - data[3] = data[1]; - data[1] = tmp; + tmp = data[3]; + data[3] = data[1]; + data[1] = tmp; - tmp = data[6]; - data[6] = data[2]; - data[2] = tmp; + tmp = data[6]; + data[6] = data[2]; + data[2] = tmp; - tmp = data[7]; - data[7] = data[5]; - data[5] = tmp; + tmp = data[7]; + data[7] = data[5]; + data[5] = tmp; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const { - double v1 = v(1); - double v2 = v(2); - double v3 = v(3); + double v1 = v(1); + double v2 = v(2); + double v3 = v(3); - double tmp1 = v1*data[0]; //[(col-1)*eRows+row-1] - double tmp2 = v1*data[1]; - double tmp3 = v1*data[2]; + double tmp1 = v1*data[0]; //[(col-1)*eRows+row-1] + double tmp2 = v1*data[1]; + double tmp3 = v1*data[2]; - tmp1 += v2*data[3]; - tmp2 += v2*data[4]; - tmp3 += v2*data[5]; + tmp1 += v2*data[3]; + tmp2 += v2*data[4]; + tmp3 += v2*data[5]; - tmp1 += v3*data[6]; - tmp2 += v3*data[7]; - tmp3 += v3*data[8]; + tmp1 += v3*data[6]; + tmp2 += v3*data[7]; + tmp3 += v3*data[8]; - return FGColumnVector3( tmp1, tmp2, tmp3 ); + return FGColumnVector3( tmp1, tmp2, tmp3 ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -520,36 +497,28 @@ FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const void FGMatrix33::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGMatrix33" << endl; - if (from == 1) cout << "Destroyed: FGMatrix33" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGMatrix33" << endl; + if (from == 1) cout << "Destroyed: FGMatrix33" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/math/FGMatrix33.h b/src/math/FGMatrix33.h index d35c1a95247ab07c33c00dbcbcab466617bfd201..d937f910a2f240c783625b83ee4e9fe2a0bde9e2 100644 --- a/src/math/FGMatrix33.h +++ b/src/math/FGMatrix33.h @@ -50,14 +50,13 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_MATRIX33 "$Id: FGMatrix33.h,v 1.11 2010/06/30 03:13:40 jberndt Exp $" +#define ID_MATRIX33 "$Id: FGMatrix33.h,v 1.12 2010/08/21 17:13:47 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGColumnVector3; class FGQuaternion; @@ -76,16 +75,16 @@ DECLARATION: MatrixException class MatrixException : public FGJSBBase { public: - std::string Message; + std::string Message; }; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -/** Handles matrix math operations. - @author Tony Peden, Jon Berndt, Mathias Froelich -*/ + /** Handles matrix math operations. + @author Tony Peden, Jon Berndt, Mathias Froelich + */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DECLARATION: FGMatrix33 @@ -95,367 +94,348 @@ class FGMatrix33 : public FGJSBBase { public: - enum - { - eRows = 3, - eColumns = 3 - }; - - /** Default initializer. - - Create a zero matrix. - */ - FGMatrix33(void); - - /** Copy constructor. - - @param M Matrix which is used for initialization. - - Create copy of the matrix given in the argument. - */ - FGMatrix33(const FGMatrix33& M) - { - data[0] = M.data[0]; - data[1] = M.data[1]; - data[2] = M.data[2]; - data[3] = M.data[3]; - data[4] = M.data[4]; - data[5] = M.data[5]; - data[6] = M.data[6]; - data[7] = M.data[7]; - data[8] = M.data[8]; - -// Debug(0); - } - - /** Initialization by given values. - - @param m11 value of the 1,1 Matrix element. - @param m12 value of the 1,2 Matrix element. - @param m13 value of the 1,3 Matrix element. - @param m21 value of the 2,1 Matrix element. - @param m22 value of the 2,2 Matrix element. - @param m23 value of the 2,3 Matrix element. - @param m31 value of the 3,1 Matrix element. - @param m32 value of the 3,2 Matrix element. - @param m33 value of the 3,3 Matrix element. - - Create a matrix from the doubles given in the arguments. - */ - FGMatrix33(double m11, double m12, double m13, - double m21, double m22, double m23, - double m31, double m32, double m33) - { - data[0] = m11; - data[1] = m21; - data[2] = m31; - data[3] = m12; - data[4] = m22; - data[5] = m32; - data[6] = m13; - data[7] = m23; - data[8] = m33; - - // Debug(0); - } - - /** Destructor. - */ - ~FGMatrix33(void) - { /* Debug(1); */ } - - /** Prints the contents of the matrix. - @param delimeter the item separator (tab or comma) - @return a string with the delimeter-separated contents of the matrix */ - std::string Dump(const std::string& delimeter) const; - - /** Prints the contents of the matrix. - @param delimeter the item separator (tab or comma, etc.) - @param prefix an additional prefix that is used to indent the 3X3 matrix printout - @return a string with the delimeter-separated contents of the matrix */ - std::string Dump(const std::string& delimiter, const std::string& prefix) const; - - /** Read access the entries of the matrix. - @param row Row index. - @param col Column index. - - @return the value of the matrix entry at the given row and - column indices. Indices are counted starting with 1. - */ - double operator()(unsigned int row, unsigned int col) const - { - return data[(col-1)*eRows+row-1]; - } - - /** Write access the entries of the matrix. - Note that the indices given in the arguments are unchecked. - - @param row Row index. - @param col Column index. - - @return a reference to the matrix entry at the given row and - column indices. Indices are counted starting with 1. - */ - double& operator()(unsigned int row, unsigned int col) - { - return data[(col-1)*eRows+row-1]; - } - - /** Read access the entries of the matrix. - This function is just a shortcut for the <tt>double& - operator()(unsigned int row, unsigned int col)</tt> function. It is - used internally to access the elements in a more convenient way. - - Note that the indices given in the arguments are unchecked. - - @param row Row index. - @param col Column index. - - @return the value of the matrix entry at the given row and - column indices. Indices are counted starting with 1. - */ - double Entry(unsigned int row, unsigned int col) const - { - return data[(col-1)*eRows+row-1]; - } - - /** Write access the entries of the matrix. - This function is just a shortcut for the <tt>double& - operator()(unsigned int row, unsigned int col)</tt> function. It is - used internally to access the elements in a more convenient way. - - Note that the indices given in the arguments are unchecked. - - @param row Row index. - @param col Column index. - - @return a reference to the matrix entry at the given row and - column indices. Indices are counted starting with 1. - */ - double& Entry(unsigned int row, unsigned int col) - { - return data[(col-1)*eRows+row-1]; - } - - /** Number of rows in the matrix. - @return the number of rows in the matrix. - */ - unsigned int Rows(void) const - { - return eRows; - } - - /** Number of cloumns in the matrix. - @return the number of columns in the matrix. - */ - unsigned int Cols(void) const - { - return eColumns; - } - - /** Transposed matrix. - This function only returns the transpose of this matrix. This matrix itself - remains unchanged. - @return the transposed matrix. - */ - FGMatrix33 Transposed(void) const - { - return FGMatrix33( data[0], data[1], data[2], - data[3], data[4], data[5], - data[6], data[7], data[8] ); - } - - /** Transposes this matrix. - This function only transposes this matrix. Nothing is returned. - */ - void T(void); - - /** Initialize the matrix. - This function initializes a matrix to all 0.0. - */ - void InitMatrix(void); - - /** Initialize the matrix. - This function initializes a matrix to user specified values. - */ - void InitMatrix(double m11, double m12, double m13, - double m21, double m22, double m23, - double m31, double m32, double m33) - { - data[0] = m11; - data[1] = m21; - data[2] = m31; - data[3] = m12; - data[4] = m22; - data[5] = m32; - data[6] = m13; - data[7] = m23; - data[8] = m33; - } - - /** Returns the quaternion associated with this direction cosine (rotation) matrix. - */ - FGQuaternion GetQuaternion(void); - - /** Determinant of the matrix. - @return the determinant of the matrix. - */ - double Determinant(void) const; - - /** Return if the matrix is invertible. - Checks and returns if the matrix is nonsingular and thus - invertible. This is done by simply computing the determinant and - check if it is zero. Note that this test does not cover any - instabilities caused by nearly singular matirces using finite - arithmetics. It only checks exact singularity. - */ - bool Invertible(void) const - { - return 0.0 != Determinant(); - } - - /** Return the inverse of the matrix. - Computes and returns if the inverse of the matrix. It is computed - by Cramers Rule. Also there are no checks performed if the matrix - is invertible. If you are not sure that it really is check this - with the @ref Invertible() call before. - */ - FGMatrix33 Inverse(void) const; - - /** Assignment operator. - - @param A source matrix. - - Copy the content of the matrix given in the argument into *this. - */ - FGMatrix33& operator=(const FGMatrix33& A) - { - data[0] = A.data[0]; - data[1] = A.data[1]; - data[2] = A.data[2]; - data[3] = A.data[3]; - data[4] = A.data[4]; - data[5] = A.data[5]; - data[6] = A.data[6]; - data[7] = A.data[7]; - data[8] = A.data[8]; - return *this; - } - - /** Matrix vector multiplication. - - @param v vector to multiply with. - @return matric vector product. - - Compute and return the product of the current matrix with the - vector given in the argument. - */ - FGColumnVector3 operator*(const FGColumnVector3& v) const; - - /** Matrix subtraction. - - @param B matrix to add to. - @return difference of the matrices. - - Compute and return the sum of the current matrix and the matrix - B given in the argument. - */ - FGMatrix33 operator-(const FGMatrix33& B) const; - - /** Matrix addition. - - @param B matrix to add to. - @return sum of the matrices. - - Compute and return the sum of the current matrix and the matrix - B given in the argument. - */ - FGMatrix33 operator+(const FGMatrix33& B) const; - - /** Matrix product. - - @param B matrix to add to. - @return product of the matrices. - - Compute and return the product of the current matrix and the matrix - B given in the argument. - */ - FGMatrix33 operator*(const FGMatrix33& B) const; - - /** Multiply the matrix with a scalar. - - @param scalar scalar factor to multiply with. - @return scaled matrix. + enum { + eRows = 3, + eColumns = 3 + }; + + /** Default initializer. + + Create a zero matrix. + */ + FGMatrix33(void); + + /** Copy constructor. + + @param M Matrix which is used for initialization. + + Create copy of the matrix given in the argument. + */ + FGMatrix33(const FGMatrix33& M) + { + data[0] = M.data[0]; + data[1] = M.data[1]; + data[2] = M.data[2]; + data[3] = M.data[3]; + data[4] = M.data[4]; + data[5] = M.data[5]; + data[6] = M.data[6]; + data[7] = M.data[7]; + data[8] = M.data[8]; + + // Debug(0); + } + + /** Initialization by given values. + + @param m11 value of the 1,1 Matrix element. + @param m12 value of the 1,2 Matrix element. + @param m13 value of the 1,3 Matrix element. + @param m21 value of the 2,1 Matrix element. + @param m22 value of the 2,2 Matrix element. + @param m23 value of the 2,3 Matrix element. + @param m31 value of the 3,1 Matrix element. + @param m32 value of the 3,2 Matrix element. + @param m33 value of the 3,3 Matrix element. + + Create a matrix from the doubles given in the arguments. + */ + FGMatrix33(double m11, double m12, double m13, + double m21, double m22, double m23, + double m31, double m32, double m33) { + data[0] = m11; + data[1] = m21; + data[2] = m31; + data[3] = m12; + data[4] = m22; + data[5] = m32; + data[6] = m13; + data[7] = m23; + data[8] = m33; + + // Debug(0); + } + + /** Destructor. + */ + ~FGMatrix33(void) { /* Debug(1); */ } + + /** Prints the contents of the matrix. + @param delimeter the item separator (tab or comma) + @return a string with the delimeter-separated contents of the matrix */ + std::string Dump(const std::string& delimeter) const; + + /** Prints the contents of the matrix. + @param delimeter the item separator (tab or comma, etc.) + @param prefix an additional prefix that is used to indent the 3X3 matrix printout + @return a string with the delimeter-separated contents of the matrix */ + std::string Dump(const std::string& delimiter, const std::string& prefix) const; + + /** Read access the entries of the matrix. + @param row Row index. + @param col Column index. + + @return the value of the matrix entry at the given row and + column indices. Indices are counted starting with 1. + */ + double operator()(unsigned int row, unsigned int col) const { + return data[(col-1)*eRows+row-1]; + } + + /** Write access the entries of the matrix. + Note that the indices given in the arguments are unchecked. + + @param row Row index. + @param col Column index. + + @return a reference to the matrix entry at the given row and + column indices. Indices are counted starting with 1. + */ + double& operator()(unsigned int row, unsigned int col) { + return data[(col-1)*eRows+row-1]; + } + + /** Read access the entries of the matrix. + This function is just a shortcut for the <tt>double& + operator()(unsigned int row, unsigned int col)</tt> function. It is + used internally to access the elements in a more convenient way. + + Note that the indices given in the arguments are unchecked. + + @param row Row index. + @param col Column index. + + @return the value of the matrix entry at the given row and + column indices. Indices are counted starting with 1. + */ + double Entry(unsigned int row, unsigned int col) const { + return data[(col-1)*eRows+row-1]; + } + + /** Write access the entries of the matrix. + This function is just a shortcut for the <tt>double& + operator()(unsigned int row, unsigned int col)</tt> function. It is + used internally to access the elements in a more convenient way. + + Note that the indices given in the arguments are unchecked. + + @param row Row index. + @param col Column index. + + @return a reference to the matrix entry at the given row and + column indices. Indices are counted starting with 1. + */ + double& Entry(unsigned int row, unsigned int col) { + return data[(col-1)*eRows+row-1]; + } + + /** Number of rows in the matrix. + @return the number of rows in the matrix. + */ + unsigned int Rows(void) const { return eRows; } + + /** Number of cloumns in the matrix. + @return the number of columns in the matrix. + */ + unsigned int Cols(void) const { return eColumns; } + + /** Transposed matrix. + This function only returns the transpose of this matrix. This matrix itself + remains unchanged. + @return the transposed matrix. + */ + FGMatrix33 Transposed(void) const { + return FGMatrix33( data[0], data[1], data[2], + data[3], data[4], data[5], + data[6], data[7], data[8] ); + } + + /** Transposes this matrix. + This function only transposes this matrix. Nothing is returned. + */ + void T(void); + +/** Initialize the matrix. + This function initializes a matrix to all 0.0. + */ + void InitMatrix(void); + +/** Initialize the matrix. + This function initializes a matrix to user specified values. + */ + void InitMatrix(double m11, double m12, double m13, + double m21, double m22, double m23, + double m31, double m32, double m33) { + data[0] = m11; + data[1] = m21; + data[2] = m31; + data[3] = m12; + data[4] = m22; + data[5] = m32; + data[6] = m13; + data[7] = m23; + data[8] = m33; + } + + /** Returns the quaternion associated with this direction cosine (rotation) matrix. + */ + FGQuaternion GetQuaternion(void); + + /** Determinant of the matrix. + @return the determinant of the matrix. + */ + double Determinant(void) const; + + /** Return if the matrix is invertible. + Checks and returns if the matrix is nonsingular and thus + invertible. This is done by simply computing the determinant and + check if it is zero. Note that this test does not cover any + instabilities caused by nearly singular matirces using finite + arithmetics. It only checks exact singularity. + */ + bool Invertible(void) const { return 0.0 != Determinant(); } + + /** Return the inverse of the matrix. + Computes and returns if the inverse of the matrix. It is computed + by Cramers Rule. Also there are no checks performed if the matrix + is invertible. If you are not sure that it really is check this + with the @ref Invertible() call before. + */ + FGMatrix33 Inverse(void) const; + + /** Assignment operator. + + @param A source matrix. + + Copy the content of the matrix given in the argument into *this. + */ + FGMatrix33& operator=(const FGMatrix33& A) { + data[0] = A.data[0]; + data[1] = A.data[1]; + data[2] = A.data[2]; + data[3] = A.data[3]; + data[4] = A.data[4]; + data[5] = A.data[5]; + data[6] = A.data[6]; + data[7] = A.data[7]; + data[8] = A.data[8]; + return *this; + } + + /** Matrix vector multiplication. + + @param v vector to multiply with. + @return matric vector product. + + Compute and return the product of the current matrix with the + vector given in the argument. + */ + FGColumnVector3 operator*(const FGColumnVector3& v) const; + + /** Matrix subtraction. + + @param B matrix to add to. + @return difference of the matrices. + + Compute and return the sum of the current matrix and the matrix + B given in the argument. + */ + FGMatrix33 operator-(const FGMatrix33& B) const; + + /** Matrix addition. - Compute and return the product of the current matrix with the - scalar value scalar given in the argument. - */ - FGMatrix33 operator*(const double scalar) const; + @param B matrix to add to. + @return sum of the matrices. - /** Multiply the matrix with 1.0/scalar. + Compute and return the sum of the current matrix and the matrix + B given in the argument. + */ + FGMatrix33 operator+(const FGMatrix33& B) const; - @param scalar scalar factor to divide through. - @return scaled matrix. + /** Matrix product. - Compute and return the product of the current matrix with the - scalar value 1.0/scalar, where scalar is given in the argument. - */ - FGMatrix33 operator/(const double scalar) const; + @param B matrix to add to. + @return product of the matrices. - /** In place matrix subtraction. + Compute and return the product of the current matrix and the matrix + B given in the argument. + */ + FGMatrix33 operator*(const FGMatrix33& B) const; - @param B matrix to subtract. - @return reference to the current matrix. + /** Multiply the matrix with a scalar. - Compute the diffence from the current matrix and the matrix B - given in the argument. - */ - FGMatrix33& operator-=(const FGMatrix33 &B); + @param scalar scalar factor to multiply with. + @return scaled matrix. - /** In place matrix addition. + Compute and return the product of the current matrix with the + scalar value scalar given in the argument. + */ + FGMatrix33 operator*(const double scalar) const; - @param B matrix to add. - @return reference to the current matrix. + /** Multiply the matrix with 1.0/scalar. - Compute the sum of the current matrix and the matrix B - given in the argument. - */ - FGMatrix33& operator+=(const FGMatrix33 &B); + @param scalar scalar factor to divide through. + @return scaled matrix. - /** In place matrix multiplication. + Compute and return the product of the current matrix with the + scalar value 1.0/scalar, where scalar is given in the argument. + */ + FGMatrix33 operator/(const double scalar) const; - @param B matrix to multiply with. - @return reference to the current matrix. + /** In place matrix subtraction. - Compute the product of the current matrix and the matrix B - given in the argument. - */ - FGMatrix33& operator*=(const FGMatrix33 &B); + @param B matrix to subtract. + @return reference to the current matrix. - /** In place matrix scale. + Compute the diffence from the current matrix and the matrix B + given in the argument. + */ + FGMatrix33& operator-=(const FGMatrix33 &B); - @param scalar scalar value to multiply with. - @return reference to the current matrix. + /** In place matrix addition. - Compute the product of the current matrix and the scalar value scalar - given in the argument. - */ - FGMatrix33& operator*=(const double scalar); + @param B matrix to add. + @return reference to the current matrix. - /** In place matrix scale. + Compute the sum of the current matrix and the matrix B + given in the argument. + */ + FGMatrix33& operator+=(const FGMatrix33 &B); - @param scalar scalar value to divide through. - @return reference to the current matrix. + /** In place matrix multiplication. - Compute the product of the current matrix and the scalar value - 1.0/scalar, where scalar is given in the argument. - */ - FGMatrix33& operator/=(const double scalar); + @param B matrix to multiply with. + @return reference to the current matrix. + + Compute the product of the current matrix and the matrix B + given in the argument. + */ + FGMatrix33& operator*=(const FGMatrix33 &B); + + /** In place matrix scale. + + @param scalar scalar value to multiply with. + @return reference to the current matrix. + + Compute the product of the current matrix and the scalar value scalar + given in the argument. + */ + FGMatrix33& operator*=(const double scalar); + + /** In place matrix scale. + + @param scalar scalar value to divide through. + @return reference to the current matrix. + + Compute the product of the current matrix and the scalar value + 1.0/scalar, where scalar is given in the argument. + */ + FGMatrix33& operator/=(const double scalar); private: - double data[eRows*eColumns]; + double data[eRows*eColumns]; - void Debug(int from); + void Debug(int from); }; /** Scalar multiplication. @@ -465,10 +445,9 @@ private: Multiply the Matrix with a scalar value. */ -inline FGMatrix33 operator*(double scalar, const FGMatrix33& A) -{ - // use already defined operation. - return A*scalar; +inline FGMatrix33 operator*(double scalar, const FGMatrix33& A) { + // use already defined operation. + return A*scalar; } /** Write matrix to a stream. diff --git a/src/math/FGModelFunctions.cpp b/src/math/FGModelFunctions.cpp new file mode 100755 index 0000000000000000000000000000000000000000..62a7e26f89e828f3ac8464b4a16a3e66179f5eae --- /dev/null +++ b/src/math/FGModelFunctions.cpp @@ -0,0 +1,166 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGModelFunctions.cpp + Author: Jon S. Berndt + Date started: August 2010 + + ------- Copyright (C) 2010 Jon S. Berndt (jon@jsbsim.org) ------------------ + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any later + version. + + 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser 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. + + Further information about the GNU Lesser General Public License can also be found on + the world wide web at http://www.gnu.org. + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- + +HISTORY +-------------------------------------------------------------------------------- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +COMMENTS, REFERENCES, and NOTES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGModelFunctions.h" +#include <string> + +using namespace std; + +namespace JSBSim { + +static const char *IdSrc = "$Id: FGModelFunctions.cpp,v 1.4 2010/09/07 00:40:03 jberndt Exp $"; +static const char *IdHdr = ID_MODELFUNCTIONS; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGModelFunctions::~FGModelFunctions() +{ + for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i]; + interface_properties.clear(); + + for (unsigned int i=0; i<PreFunctions.size(); i++) delete PreFunctions[i]; + for (unsigned int i=0; i<PostFunctions.size(); i++) delete PostFunctions[i]; + + if (debug_lvl & 2) cout << "Destroyed: FGModelFunctions" << endl; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGModelFunctions::Load(Element* el, FGPropertyManager* PM, string prefix) +{ + // Interface properties are all stored in the interface properties array. + string interface_property_string = ""; + + Element *property_element = el->FindElement("property"); + if (property_element && debug_lvl > 0) cout << endl << " Declared properties" + << endl << endl; + while (property_element) { + interface_property_string = property_element->GetDataLine(); + if (PM->HasNode(interface_property_string)) { + cerr << " Property " << interface_property_string + << " is already defined." << endl; + } else { + double value=0.0; + if ( ! property_element->GetAttributeValue("value").empty()) + value = property_element->GetAttributeValueAsNumber("value"); + interface_properties.push_back(new double(value)); + PM->Tie(interface_property_string, interface_properties.back()); + if (debug_lvl > 0) + cout << " " << interface_property_string << " (initial value: " + << value << ")" << endl << endl; + } + property_element = el->FindNextElement("property"); + } + + // End of interface property loading logic + + PreLoad(el, PM, prefix); + + return true; // TODO: Need to make this value mean something. +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGModelFunctions::PreLoad(Element* el, FGPropertyManager* PM, string prefix) +{ + // Load model post-functions, if any + + Element *function = el->FindElement("function"); + + while (function) { + if (function->GetAttributeValue("type") == "pre") { + PreFunctions.push_back(new FGFunction(PM, function, prefix)); + } else if (function->GetAttributeValue("type").empty()) { // Assume pre-function + string funcname = function->GetAttributeValue("name"); + if (funcname.find("IdleThrust") == string::npos && // Do not process functions that are + funcname.find("MilThrust") == string::npos && // already pre-defined turbine engine + funcname.find("AugThrust") == string::npos && // functions. These are loaded within + funcname.find("Injection") == string::npos ) // the Turbine::Load() method. + { + PreFunctions.push_back(new FGFunction(PM, function, prefix)); + } + } + function = el->FindNextElement("function"); + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGModelFunctions::PostLoad(Element* el, FGPropertyManager* PM, string prefix) +{ + // Load model post-functions, if any + + Element *function = el->FindElement("function"); + while (function) { + if (function->GetAttributeValue("type") == "post") { + PostFunctions.push_back(new FGFunction(PM, function, prefix)); + } + function = el->FindNextElement("function"); + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// Tell the Functions to cache values, so when the function values +// are being used in the model, the functions do not get +// calculated each time, but instead use the values that have already +// been calculated for this frame. + +void FGModelFunctions::RunPreFunctions(void) +{ + vector <FGFunction*>::iterator it; + for (it = PreFunctions.begin(); it != PreFunctions.end(); it++) + (*it)->cacheValue(true); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// Tell the Functions to cache values, so when the function values +// are being used in the model, the functions do not get +// calculated each time, but instead use the values that have already +// been calculated for this frame. + +void FGModelFunctions::RunPostFunctions(void) +{ + vector <FGFunction*>::iterator it; + for (it = PostFunctions.begin(); it != PostFunctions.end(); it++) + (*it)->GetValue(); +} + +} diff --git a/src/math/FGModelFunctions.h b/src/math/FGModelFunctions.h new file mode 100755 index 0000000000000000000000000000000000000000..f98f2b4bf507adf79b7916a269983920f1ceadf5 --- /dev/null +++ b/src/math/FGModelFunctions.h @@ -0,0 +1,85 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Header: FGModelFunctions.h +Author: Jon Berndt +Date started: August 2010 + + ------------- Copyright (C) 2010 Jon S. Berndt (jon@jsbsim.org) ------------- + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any later + version. + + 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser 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. + + Further information about the GNU Lesser General Public License can also be found on + the world wide web at http://www.gnu.org. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGMODELFUNCTIONS_H +#define FGMODELFUNCTIONS_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGJSBBase.h" +#include <vector> +#include "math/FGFunction.h" +#include "input_output/FGPropertyManager.h" +#include "input_output/FGXMLElement.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_MODELFUNCTIONS "$Id: FGModelFunctions.h,v 1.2 2010/08/24 10:30:14 jberndt Exp $" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** +@author Jon Berndt +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DECLARATION: FGModelFunctions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + class FGModelFunctions : public FGJSBBase +{ +public: + ~FGModelFunctions(); + void RunPreFunctions(void); + void RunPostFunctions(void); + bool Load(Element* el, FGPropertyManager* PropertyManager, std::string prefix=""); + void PreLoad(Element* el, FGPropertyManager* PropertyManager, std::string prefix=""); + void PostLoad(Element* el, FGPropertyManager* PropertyManager, std::string prefix=""); + +protected: + std::vector <FGFunction*> PreFunctions; + std::vector <FGFunction*> PostFunctions; + std::vector <double*> interface_properties; +}; + +} // namespace JSBSim + +#endif diff --git a/src/math/FGParameter.h b/src/math/FGParameter.h old mode 100644 new mode 100755 index 855eba146118789efb549d2714b9c2c05ed7ba61..85b43b1af2abb8929f5fd73a2d238f76c78c3a44 --- a/src/math/FGParameter.h +++ b/src/math/FGParameter.h @@ -46,16 +46,15 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -/** Represents various types of parameters. - @author Jon Berndt -*/ + /** Represents various types of parameters. + @author Jon Berndt + */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DECLARATION: FGParameter @@ -64,8 +63,8 @@ DECLARATION: FGParameter class FGParameter : public FGJSBBase { public: - virtual ~FGParameter(void) {}; - virtual double GetValue(void) const = 0; + virtual ~FGParameter(void) {}; + virtual double GetValue(void) const = 0; protected: }; diff --git a/src/math/FGPropertyValue.cpp b/src/math/FGPropertyValue.cpp old mode 100644 new mode 100755 index 0dbdbd23ce8cc6c2db331ed86a91a3c568355f55..0824a607b93e506cd61c0dfe524b65bf3099dfd1 --- a/src/math/FGPropertyValue.cpp +++ b/src/math/FGPropertyValue.cpp @@ -30,10 +30,9 @@ INCLUDES #include "FGPropertyValue.h" -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.4 2009/08/30 03:51:28 jberndt Exp $"; +static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.6 2010/08/24 10:30:14 jberndt Exp $"; static const char *IdHdr = ID_PROPERTYVALUE; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -46,9 +45,23 @@ FGPropertyValue::FGPropertyValue(FGPropertyManager* propNode) : PropertyManager( //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FGPropertyValue::FGPropertyValue(std::string propName) : PropertyManager(0L) +{ + PropertyName = propName; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + double FGPropertyValue::GetValue(void) const { - return PropertyManager->getDoubleValue(); + double val; + try { + val = PropertyManager->getDoubleValue(); + } catch (...) { + throw(PropertyName); + } + + return val; } } diff --git a/src/math/FGPropertyValue.h b/src/math/FGPropertyValue.h old mode 100644 new mode 100755 index 74ec02fef00ebb546e815806b4d5b42850b6e9eb..753df7c624f14ca36065bc17593cce8810c6bd1b --- a/src/math/FGPropertyValue.h +++ b/src/math/FGPropertyValue.h @@ -41,22 +41,21 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.6 2009/10/02 10:30:09 jberndt Exp $" +#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.8 2010/08/24 10:30:14 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -/** Represents a property value - @author Jon Berndt -*/ + /** Represents a property value + @author Jon Berndt + */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DECLARATION: FGPropertyValue @@ -66,13 +65,16 @@ class FGPropertyValue : public FGParameter { public: - FGPropertyValue(FGPropertyManager* propNode); - ~FGPropertyValue() {}; + FGPropertyValue(FGPropertyManager* propNode); + FGPropertyValue(std::string propName); + ~FGPropertyValue() {}; - double GetValue(void) const; + double GetValue(void) const; + void SetNode(FGPropertyManager* node) {PropertyManager = node;} private: - FGPropertyManager* PropertyManager; + FGPropertyManager* PropertyManager; + std::string PropertyName; }; } // namespace JSBSim diff --git a/src/math/FGQuaternion.cpp b/src/math/FGQuaternion.cpp index e0a3e42334ae1a731fc2353bc674cce6e7d54f43..07868cfa0b0b58905efbdb807f79fe4079b8bcf0 100644 --- a/src/math/FGQuaternion.cpp +++ b/src/math/FGQuaternion.cpp @@ -55,9 +55,8 @@ using std::endl; DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ - +namespace JSBSim { + static const char *IdSrc = "$Id: FGQuaternion.cpp,v 1.16 2010/06/30 03:13:40 jberndt Exp $"; static const char *IdHdr = ID_QUATERNION; @@ -66,18 +65,17 @@ static const char *IdHdr = ID_QUATERNION; // Initialize from q FGQuaternion::FGQuaternion(const FGQuaternion& q) : mCacheValid(q.mCacheValid) { - data[0] = q(1); - data[1] = q(2); - data[2] = q(3); - data[3] = q(4); - if (mCacheValid) - { - mT = q.mT; - mTInv = q.mTInv; - mEulerAngles = q.mEulerAngles; - mEulerSines = q.mEulerSines; - mEulerCosines = q.mEulerCosines; - } + data[0] = q(1); + data[1] = q(2); + data[2] = q(3); + data[3] = q(4); + if (mCacheValid) { + mT = q.mT; + mTInv = q.mTInv; + mEulerAngles = q.mEulerAngles; + mEulerSines = q.mEulerSines; + mEulerCosines = q.mEulerCosines; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -85,72 +83,72 @@ FGQuaternion::FGQuaternion(const FGQuaternion& q) : mCacheValid(q.mCacheValid) // Initialize with the three euler angles FGQuaternion::FGQuaternion(double phi, double tht, double psi): mCacheValid(false) { - InitializeFromEulerAngles(phi, tht, psi); + InitializeFromEulerAngles(phi, tht, psi); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGQuaternion::FGQuaternion(FGColumnVector3 vOrient): mCacheValid(false) { - double phi = vOrient(ePhi); - double tht = vOrient(eTht); - double psi = vOrient(ePsi); + double phi = vOrient(ePhi); + double tht = vOrient(eTht); + double psi = vOrient(ePsi); - InitializeFromEulerAngles(phi, tht, psi); + InitializeFromEulerAngles(phi, tht, psi); } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // // This function computes the quaternion that describes the relationship of the // body frame with respect to another frame, such as the ECI or ECEF frames. The // Euler angles used represent a 3-2-1 (psi, theta, phi) rotation sequence from // the reference frame to the body frame. See "Quaternions and Rotation -// Sequences", Jack B. Kuipers, sections 9.2 and 7.6. +// Sequences", Jack B. Kuipers, sections 9.2 and 7.6. void FGQuaternion::InitializeFromEulerAngles(double phi, double tht, double psi) { - mEulerAngles(ePhi) = phi; - mEulerAngles(eTht) = tht; - mEulerAngles(ePsi) = psi; - - double thtd2 = 0.5*tht; - double psid2 = 0.5*psi; - double phid2 = 0.5*phi; - - double Sthtd2 = sin(thtd2); - double Spsid2 = sin(psid2); - double Sphid2 = sin(phid2); - - double Cthtd2 = cos(thtd2); - double Cpsid2 = cos(psid2); - double Cphid2 = cos(phid2); - - double Cphid2Cthtd2 = Cphid2*Cthtd2; - double Cphid2Sthtd2 = Cphid2*Sthtd2; - double Sphid2Sthtd2 = Sphid2*Sthtd2; - double Sphid2Cthtd2 = Sphid2*Cthtd2; - - data[0] = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2; - data[1] = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2; - data[2] = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2; - data[3] = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2; - - Normalize(); + mEulerAngles(ePhi) = phi; + mEulerAngles(eTht) = tht; + mEulerAngles(ePsi) = psi; + + double thtd2 = 0.5*tht; + double psid2 = 0.5*psi; + double phid2 = 0.5*phi; + + double Sthtd2 = sin(thtd2); + double Spsid2 = sin(psid2); + double Sphid2 = sin(phid2); + + double Cthtd2 = cos(thtd2); + double Cpsid2 = cos(psid2); + double Cphid2 = cos(phid2); + + double Cphid2Cthtd2 = Cphid2*Cthtd2; + double Cphid2Sthtd2 = Cphid2*Sthtd2; + double Sphid2Sthtd2 = Sphid2*Sthtd2; + double Sphid2Cthtd2 = Sphid2*Cthtd2; + + data[0] = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2; + data[1] = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2; + data[2] = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2; + data[3] = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2; + + Normalize(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Initialize with a direction cosine (rotation) matrix FGQuaternion::FGQuaternion(const FGMatrix33& m) : mCacheValid(false) { - data[0] = 0.50*sqrt(1.0 + m(1,1) + m(2,2) + m(3,3)); - double t = 0.25/data[0]; - data[1] = t*(m(2,3) - m(3,2)); - data[2] = t*(m(3,1) - m(1,3)); - data[3] = t*(m(1,2) - m(2,1)); + data[0] = 0.50*sqrt(1.0 + m(1,1) + m(2,2) + m(3,3)); + double t = 0.25/data[0]; + data[1] = t*(m(2,3) - m(3,2)); + data[2] = t*(m(3,1) - m(1,3)); + data[3] = t*(m(1,2) - m(2,1)); - ComputeDerivedUnconditional(); + ComputeDerivedUnconditional(); - Normalize(); + Normalize(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -158,33 +156,33 @@ FGQuaternion::FGQuaternion(const FGMatrix33& m) : mCacheValid(false) /** Returns the derivative of the quaternion corresponding to the angular velocities PQR. See Stevens and Lewis, "Aircraft Control and Simulation", Second Edition, - Equation 1.3-36. + Equation 1.3-36. Also see Jack Kuipers, "Quaternions and Rotation Sequences", Equation 11.12. */ FGQuaternion FGQuaternion::GetQDot(const FGColumnVector3& PQR) { - return FGQuaternion( - -0.5*( data[1]*PQR(eP) + data[2]*PQR(eQ) + data[3]*PQR(eR)), - 0.5*( data[0]*PQR(eP) - data[3]*PQR(eQ) + data[2]*PQR(eR)), - 0.5*( data[3]*PQR(eP) + data[0]*PQR(eQ) - data[1]*PQR(eR)), - 0.5*(-data[2]*PQR(eP) + data[1]*PQR(eQ) + data[0]*PQR(eR)) - ); + return FGQuaternion( + -0.5*( data[1]*PQR(eP) + data[2]*PQR(eQ) + data[3]*PQR(eR)), + 0.5*( data[0]*PQR(eP) - data[3]*PQR(eQ) + data[2]*PQR(eR)), + 0.5*( data[3]*PQR(eP) + data[0]*PQR(eQ) - data[1]*PQR(eR)), + 0.5*(-data[2]*PQR(eP) + data[1]*PQR(eQ) + data[0]*PQR(eR)) + ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGQuaternion::Normalize() { - // Note: this does not touch the cache since it does not change the orientation - double norm = Magnitude(); - if (norm == 0.0 || fabs(norm - 1.000) < 1e-10) return; + // Note: this does not touch the cache since it does not change the orientation + double norm = Magnitude(); + if (norm == 0.0 || fabs(norm - 1.000) < 1e-10) return; - double rnorm = 1.0/norm; + double rnorm = 1.0/norm; - data[0] *= rnorm; - data[1] *= rnorm; - data[2] *= rnorm; - data[3] *= rnorm; + data[0] *= rnorm; + data[1] *= rnorm; + data[2] *= rnorm; + data[3] *= rnorm; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -192,73 +190,72 @@ void FGQuaternion::Normalize() // Compute the derived values if required ... void FGQuaternion::ComputeDerivedUnconditional(void) const { - mCacheValid = true; - - double q0 = data[0]; // use some aliases/shorthand for the quat elements. - double q1 = data[1]; - double q2 = data[2]; - double q3 = data[3]; - - // Now compute the transformation matrix. - double q0q0 = q0*q0; - double q1q1 = q1*q1; - double q2q2 = q2*q2; - double q3q3 = q3*q3; - double q0q1 = q0*q1; - double q0q2 = q0*q2; - double q0q3 = q0*q3; - double q1q2 = q1*q2; - double q1q3 = q1*q3; - double q2q3 = q2*q3; - - mT(1,1) = q0q0 + q1q1 - q2q2 - q3q3; // This is found from Eqn. 1.3-32 in - mT(1,2) = 2.0*(q1q2 + q0q3); // Stevens and Lewis - mT(1,3) = 2.0*(q1q3 - q0q2); - mT(2,1) = 2.0*(q1q2 - q0q3); - mT(2,2) = q0q0 - q1q1 + q2q2 - q3q3; - mT(2,3) = 2.0*(q2q3 + q0q1); - mT(3,1) = 2.0*(q1q3 + q0q2); - mT(3,2) = 2.0*(q2q3 - q0q1); - mT(3,3) = q0q0 - q1q1 - q2q2 + q3q3; - - // Since this is an orthogonal matrix, the inverse is simply the transpose. - - mTInv = mT; - mTInv.T(); - - // Compute the Euler-angles - // Also see Jack Kuipers, "Quaternions and Rotation Sequences", section 7.8.. - - if (mT(3,3) == 0.0) - mEulerAngles(ePhi) = 0.5*M_PI; - else - mEulerAngles(ePhi) = atan2(mT(2,3), mT(3,3)); - - if (mT(1,3) < -1.0) - mEulerAngles(eTht) = 0.5*M_PI; - else if (1.0 < mT(1,3)) - mEulerAngles(eTht) = -0.5*M_PI; - else - mEulerAngles(eTht) = asin(-mT(1,3)); - - if (mT(1,1) == 0.0) - mEulerAngles(ePsi) = 0.5*M_PI; - else - { - double psi = atan2(mT(1,2), mT(1,1)); - if (psi < 0.0) - psi += 2*M_PI; - mEulerAngles(ePsi) = psi; - } - - // FIXME: may be one can compute those values easier ??? - mEulerSines(ePhi) = sin(mEulerAngles(ePhi)); - // mEulerSines(eTht) = sin(mEulerAngles(eTht)); - mEulerSines(eTht) = -mT(1,3); - mEulerSines(ePsi) = sin(mEulerAngles(ePsi)); - mEulerCosines(ePhi) = cos(mEulerAngles(ePhi)); - mEulerCosines(eTht) = cos(mEulerAngles(eTht)); - mEulerCosines(ePsi) = cos(mEulerAngles(ePsi)); + mCacheValid = true; + + double q0 = data[0]; // use some aliases/shorthand for the quat elements. + double q1 = data[1]; + double q2 = data[2]; + double q3 = data[3]; + + // Now compute the transformation matrix. + double q0q0 = q0*q0; + double q1q1 = q1*q1; + double q2q2 = q2*q2; + double q3q3 = q3*q3; + double q0q1 = q0*q1; + double q0q2 = q0*q2; + double q0q3 = q0*q3; + double q1q2 = q1*q2; + double q1q3 = q1*q3; + double q2q3 = q2*q3; + + mT(1,1) = q0q0 + q1q1 - q2q2 - q3q3; // This is found from Eqn. 1.3-32 in + mT(1,2) = 2.0*(q1q2 + q0q3); // Stevens and Lewis + mT(1,3) = 2.0*(q1q3 - q0q2); + mT(2,1) = 2.0*(q1q2 - q0q3); + mT(2,2) = q0q0 - q1q1 + q2q2 - q3q3; + mT(2,3) = 2.0*(q2q3 + q0q1); + mT(3,1) = 2.0*(q1q3 + q0q2); + mT(3,2) = 2.0*(q2q3 - q0q1); + mT(3,3) = q0q0 - q1q1 - q2q2 + q3q3; + + // Since this is an orthogonal matrix, the inverse is simply the transpose. + + mTInv = mT; + mTInv.T(); + + // Compute the Euler-angles + // Also see Jack Kuipers, "Quaternions and Rotation Sequences", section 7.8.. + + if (mT(3,3) == 0.0) + mEulerAngles(ePhi) = 0.5*M_PI; + else + mEulerAngles(ePhi) = atan2(mT(2,3), mT(3,3)); + + if (mT(1,3) < -1.0) + mEulerAngles(eTht) = 0.5*M_PI; + else if (1.0 < mT(1,3)) + mEulerAngles(eTht) = -0.5*M_PI; + else + mEulerAngles(eTht) = asin(-mT(1,3)); + + if (mT(1,1) == 0.0) + mEulerAngles(ePsi) = 0.5*M_PI; + else { + double psi = atan2(mT(1,2), mT(1,1)); + if (psi < 0.0) + psi += 2*M_PI; + mEulerAngles(ePsi) = psi; + } + + // FIXME: may be one can compute those values easier ??? + mEulerSines(ePhi) = sin(mEulerAngles(ePhi)); + // mEulerSines(eTht) = sin(mEulerAngles(eTht)); + mEulerSines(eTht) = -mT(1,3); + mEulerSines(ePsi) = sin(mEulerAngles(ePsi)); + mEulerCosines(ePhi) = cos(mEulerAngles(ePhi)); + mEulerCosines(eTht) = cos(mEulerAngles(eTht)); + mEulerCosines(ePsi) = cos(mEulerAngles(ePsi)); // Debug(2); } @@ -284,38 +281,30 @@ void FGQuaternion::ComputeDerivedUnconditional(void) const void FGQuaternion::Debug(int from) const { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGQuaternion" << endl; - if (from == 1) cout << "Destroyed: FGQuaternion" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - if (!EqualToRoundoff(Magnitude(), 1.0)) - { - cout << "Quaternion magnitude differs from 1.0 !" << endl; - cout << "\tdelta from 1.0: " << std::scientific << Magnitude()-1.0 << endl; - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGQuaternion" << endl; + if (from == 1) cout << "Destroyed: FGQuaternion" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + if (!EqualToRoundoff(Magnitude(), 1.0)) { + cout << "Quaternion magnitude differs from 1.0 !" << endl; + cout << "\tdelta from 1.0: " << std::scientific << Magnitude()-1.0 << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } // namespace JSBSim diff --git a/src/math/FGQuaternion.h b/src/math/FGQuaternion.h index 3398379d384798b7fbfe01414bb09b1deb306492..104a52f39a5301ef9ba71bfc0d13d337e5aa5616 100644 --- a/src/math/FGQuaternion.h +++ b/src/math/FGQuaternion.h @@ -49,8 +49,7 @@ SENTRY #define ID_QUATERNION "$Id: FGQuaternion.h,v 1.17 2010/06/30 03:13:40 jberndt Exp $" -namespace JSBSim -{ +namespace JSBSim { class FGMatrix33; @@ -89,482 +88,418 @@ class FGMatrix33; CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGQuaternion : virtual FGJSBBase -{ +class FGQuaternion : virtual FGJSBBase { public: - /** Default initializer. - Default initializer, initializes the class with the identity rotation. */ - FGQuaternion() : mCacheValid(false) - { - data[0] = 1.0; - data[1] = data[2] = data[3] = 0.0; - } - - /** Copy constructor. - Copy constructor, initializes the quaternion. - @param q a constant reference to another FGQuaternion instance */ - FGQuaternion(const FGQuaternion& q); - - /** Initializer by euler angles. - Initialize the quaternion with the euler angles. - @param phi The euler X axis (roll) angle in radians - @param tht The euler Y axis (attitude) angle in radians - @param psi The euler Z axis (heading) angle in radians */ - FGQuaternion(double phi, double tht, double psi); - - /** Initializer by euler angle vector. - Initialize the quaternion with the euler angle vector. - @param vOrient The euler axis angle vector in radians (phi, tht, psi) */ - FGQuaternion(FGColumnVector3 vOrient); - - /** Initializer by one euler angle. - Initialize the quaternion with the single euler angle where its index - is given in the first argument. - @param idx Index of the euler angle to initialize - @param angle The euler angle in radians */ - FGQuaternion(int idx, double angle) - : mCacheValid(false) - { - - double angle2 = 0.5*angle; - - double Sangle2 = sin(angle2); - double Cangle2 = cos(angle2); - - if (idx == ePhi) - { - data[0] = Cangle2; - data[1] = Sangle2; - data[2] = 0.0; - data[3] = 0.0; - - } - else if (idx == eTht) - { - data[0] = Cangle2; - data[1] = 0.0; - data[2] = Sangle2; - data[3] = 0.0; - - } - else - { - data[0] = Cangle2; - data[1] = 0.0; - data[2] = 0.0; - data[3] = Sangle2; - - } - } - - /** Initializer by matrix. - Initialize the quaternion with the matrix representing a transform from one frame - to another using the standard aerospace sequence, Yaw-Pitch-Roll (3-2-1). - @param m the rotation matrix */ - FGQuaternion(const FGMatrix33& m); - - /// Destructor. - ~FGQuaternion() {} - - /** Quaternion derivative for given angular rates. - Computes the quaternion derivative which results from the given - angular velocities - @param PQR a constant reference to a rotation rate vector - @return the quaternion derivative - @see Stevens and Lewis, "Aircraft Control and Simulation", Second Edition, - Equation 1.3-36. */ - FGQuaternion GetQDot(const FGColumnVector3& PQR); - - /** Transformation matrix. - @return a reference to the transformation/rotation matrix - corresponding to this quaternion rotation. */ - const FGMatrix33& GetT(void) const - { - ComputeDerived(); - return mT; - } - - /** Backward transformation matrix. - @return a reference to the inverse transformation/rotation matrix - corresponding to this quaternion rotation. */ - const FGMatrix33& GetTInv(void) const - { - ComputeDerived(); - return mTInv; - } - - /** Retrieves the Euler angles. - @return a reference to the triad of euler angles corresponding - to this quaternion rotation. - units radians */ - const FGColumnVector3& GetEuler(void) const - { - ComputeDerived(); - return mEulerAngles; - } - - /** Retrieves the Euler angles. - @param i the euler angle index. - units radians. - @return a reference to the i-th euler angles corresponding - to this quaternion rotation. - */ - double GetEuler(int i) const - { - ComputeDerived(); - return mEulerAngles(i); - } - - /** Retrieves the Euler angles. - @param i the euler angle index. - @return a reference to the i-th euler angles corresponding - to this quaternion rotation. - units degrees */ - double GetEulerDeg(int i) const - { - ComputeDerived(); - return radtodeg*mEulerAngles(i); - } - - /** Retrieves sine of the given euler angle. - @return the sine of the Euler angle theta (pitch attitude) corresponding - to this quaternion rotation. */ - double GetSinEuler(int i) const - { - ComputeDerived(); - return mEulerSines(i); - } - - /** Retrieves cosine of the given euler angle. - @return the sine of the Euler angle theta (pitch attitude) corresponding - to this quaternion rotation. */ - double GetCosEuler(int i) const - { - ComputeDerived(); - return mEulerCosines(i); - } - - /** Read access the entries of the vector. - - @param idx the component index. - - Return the value of the matrix entry at the given index. - Indices are counted starting with 1. - - Note that the index given in the argument is unchecked. - */ - double operator()(unsigned int idx) const - { - return data[idx-1]; - } - - /** Write access the entries of the vector. - - @param idx the component index. - - Return a reference to the vector entry at the given index. - Indices are counted starting with 1. - - Note that the index given in the argument is unchecked. - */ - double& operator()(unsigned int idx) - { - mCacheValid = false; - return data[idx-1]; - } - - /** Read access the entries of the vector. - - @param idx the component index. - - Return the value of the matrix entry at the given index. - Indices are counted starting with 1. - - This function is just a shortcut for the <tt>double - operator()(unsigned int idx) const</tt> function. It is - used internally to access the elements in a more convenient way. - - Note that the index given in the argument is unchecked. - */ - double Entry(unsigned int idx) const - { - return data[idx-1]; - } - - /** Write access the entries of the vector. - - @param idx the component index. - - Return a reference to the vector entry at the given index. - Indices are counted starting with 1. - - This function is just a shortcut for the <tt>double& - operator()(unsigned int idx)</tt> function. It is - used internally to access the elements in a more convenient way. - - Note that the index given in the argument is unchecked. - */ - double& Entry(unsigned int idx) - { - mCacheValid = false; - return data[idx-1]; - } - - /** Assignment operator "=". - Assign the value of q to the current object. Cached values are - conserved. - @param q reference to an FGQuaternion instance - @return reference to a quaternion object */ - const FGQuaternion& operator=(const FGQuaternion& q) - { - // Copy the master values ... - data[0] = q(1); - data[1] = q(2); - data[2] = q(3); - data[3] = q(4); - ComputeDerived(); - // .. and copy the derived values if they are valid - mCacheValid = q.mCacheValid; - if (mCacheValid) - { - mT = q.mT; - mTInv = q.mTInv; - mEulerAngles = q.mEulerAngles; - mEulerSines = q.mEulerSines; - mEulerCosines = q.mEulerCosines; - } - return *this; - } - - /// Conversion from Quat to Matrix - operator FGMatrix33() const - { - return GetT(); - } - - /** Comparison operator "==". - @param q a quaternion reference - @return true if both quaternions represent the same rotation. */ - bool operator==(const FGQuaternion& q) const - { - return data[0] == q(1) && data[1] == q(2) - && data[2] == q(3) && data[3] == q(4); - } - - /** Comparison operator "!=". - @param q a quaternion reference - @return true if both quaternions do not represent the same rotation. */ - bool operator!=(const FGQuaternion& q) const - { - return ! operator==(q); - } - const FGQuaternion& operator+=(const FGQuaternion& q) - { - // Copy the master values ... - data[0] += q(1); - data[1] += q(2); - data[2] += q(3); - data[3] += q(4); - mCacheValid = false; - return *this; - } - - /** Arithmetic operator "-=". - @param q a quaternion reference. - @return a quaternion reference representing Q, where Q = Q - q. */ - const FGQuaternion& operator-=(const FGQuaternion& q) - { - // Copy the master values ... - data[0] -= q(1); - data[1] -= q(2); - data[2] -= q(3); - data[3] -= q(4); - mCacheValid = false; - return *this; - } - - /** Arithmetic operator "*=". - @param scalar a multiplicative value. - @return a quaternion reference representing Q, where Q = Q * scalar. */ - const FGQuaternion& operator*=(double scalar) - { - data[0] *= scalar; - data[1] *= scalar; - data[2] *= scalar; - data[3] *= scalar; - mCacheValid = false; - return *this; - } - - /** Arithmetic operator "/=". - @param scalar a divisor value. - @return a quaternion reference representing Q, where Q = Q / scalar. */ - const FGQuaternion& operator/=(double scalar) - { - return operator*=(1.0/scalar); - } - - /** Arithmetic operator "+". - @param q a quaternion to be summed. - @return a quaternion representing Q, where Q = Q + q. */ - FGQuaternion operator+(const FGQuaternion& q) const - { - return FGQuaternion(data[0]+q(1), data[1]+q(2), - data[2]+q(3), data[3]+q(4)); - } - - /** Arithmetic operator "-". - @param q a quaternion to be subtracted. - @return a quaternion representing Q, where Q = Q - q. */ - FGQuaternion operator-(const FGQuaternion& q) const - { - return FGQuaternion(data[0]-q(1), data[1]-q(2), - data[2]-q(3), data[3]-q(4)); - } - - /** Arithmetic operator "*". - Multiplication of two quaternions is like performing successive rotations. - @param q a quaternion to be multiplied. - @return a quaternion representing Q, where Q = Q * q. */ - FGQuaternion operator*(const FGQuaternion& q) const - { - return FGQuaternion(data[0]*q(1)-data[1]*q(2)-data[2]*q(3)-data[3]*q(4), - data[0]*q(2)+data[1]*q(1)+data[2]*q(4)-data[3]*q(3), - data[0]*q(3)-data[1]*q(4)+data[2]*q(1)+data[3]*q(2), - data[0]*q(4)+data[1]*q(3)-data[2]*q(2)+data[3]*q(1)); - } - - /** Arithmetic operator "*=". - Multiplication of two quaternions is like performing successive rotations. - @param q a quaternion to be multiplied. - @return a quaternion reference representing Q, where Q = Q * q. */ - const FGQuaternion& operator*=(const FGQuaternion& q) - { - double q0 = data[0]*q(1)-data[1]*q(2)-data[2]*q(3)-data[3]*q(4); - double q1 = data[0]*q(2)+data[1]*q(1)+data[2]*q(4)-data[3]*q(3); - double q2 = data[0]*q(3)-data[1]*q(4)+data[2]*q(1)+data[3]*q(2); - double q3 = data[0]*q(4)+data[1]*q(3)-data[2]*q(2)+data[3]*q(1); - data[0] = q0; - data[1] = q1; - data[2] = q2; - data[3] = q3; - mCacheValid = false; - return *this; - } - - /** Inverse of the quaternion. - - Compute and return the inverse of the quaternion so that the orientation - represented with *this multiplied with the returned value is equal to - the identity orientation. - */ - FGQuaternion Inverse(void) const - { - double norm = SqrMagnitude(); - if (norm == 0.0) - return *this; - double rNorm = 1.0/norm; - return FGQuaternion( data[0]*rNorm, -data[1]*rNorm, - -data[2]*rNorm, -data[3]*rNorm ); - } - - /** Conjugate of the quaternion. - - Compute and return the conjugate of the quaternion. This one is equal - to the inverse iff the quaternion is normalized. - */ - FGQuaternion Conjugate(void) const - { - return FGQuaternion( data[0], -data[1], -data[2], -data[3] ); - } - - friend FGQuaternion operator*(double, const FGQuaternion&); - - /** Length of the vector. - - Compute and return the euclidean norm of this vector. - */ - double Magnitude(void) const - { - return sqrt(SqrMagnitude()); - } - - /** Square of the length of the vector. - - Compute and return the square of the euclidean norm of this vector. - */ - double SqrMagnitude(void) const - { - return data[0]*data[0] + data[1]*data[1] - + data[2]*data[2] + data[3]*data[3]; - } - - /** Normalize. - - Normalize the vector to have the Magnitude() == 1.0. If the vector - is equal to zero it is left untouched. - */ - void Normalize(void); - - /** Zero quaternion vector. Does not represent any orientation. - Useful for initialization of increments */ - static FGQuaternion zero(void) - { - return FGQuaternion( 0.0, 0.0, 0.0, 0.0 ); - } + /** Default initializer. + Default initializer, initializes the class with the identity rotation. */ + FGQuaternion() : mCacheValid(false) { + data[0] = 1.0; + data[1] = data[2] = data[3] = 0.0; + } + + /** Copy constructor. + Copy constructor, initializes the quaternion. + @param q a constant reference to another FGQuaternion instance */ + FGQuaternion(const FGQuaternion& q); + + /** Initializer by euler angles. + Initialize the quaternion with the euler angles. + @param phi The euler X axis (roll) angle in radians + @param tht The euler Y axis (attitude) angle in radians + @param psi The euler Z axis (heading) angle in radians */ + FGQuaternion(double phi, double tht, double psi); + + /** Initializer by euler angle vector. + Initialize the quaternion with the euler angle vector. + @param vOrient The euler axis angle vector in radians (phi, tht, psi) */ + FGQuaternion(FGColumnVector3 vOrient); + + /** Initializer by one euler angle. + Initialize the quaternion with the single euler angle where its index + is given in the first argument. + @param idx Index of the euler angle to initialize + @param angle The euler angle in radians */ + FGQuaternion(int idx, double angle) + : mCacheValid(false) { + + double angle2 = 0.5*angle; + + double Sangle2 = sin(angle2); + double Cangle2 = cos(angle2); + + if (idx == ePhi) { + data[0] = Cangle2; + data[1] = Sangle2; + data[2] = 0.0; + data[3] = 0.0; + + } else if (idx == eTht) { + data[0] = Cangle2; + data[1] = 0.0; + data[2] = Sangle2; + data[3] = 0.0; + + } else { + data[0] = Cangle2; + data[1] = 0.0; + data[2] = 0.0; + data[3] = Sangle2; + + } + } + + /** Initializer by matrix. + Initialize the quaternion with the matrix representing a transform from one frame + to another using the standard aerospace sequence, Yaw-Pitch-Roll (3-2-1). + @param m the rotation matrix */ + FGQuaternion(const FGMatrix33& m); + + /// Destructor. + ~FGQuaternion() {} + + /** Quaternion derivative for given angular rates. + Computes the quaternion derivative which results from the given + angular velocities + @param PQR a constant reference to a rotation rate vector + @return the quaternion derivative + @see Stevens and Lewis, "Aircraft Control and Simulation", Second Edition, + Equation 1.3-36. */ + FGQuaternion GetQDot(const FGColumnVector3& PQR); + + /** Transformation matrix. + @return a reference to the transformation/rotation matrix + corresponding to this quaternion rotation. */ + const FGMatrix33& GetT(void) const { ComputeDerived(); return mT; } + + /** Backward transformation matrix. + @return a reference to the inverse transformation/rotation matrix + corresponding to this quaternion rotation. */ + const FGMatrix33& GetTInv(void) const { ComputeDerived(); return mTInv; } + + /** Retrieves the Euler angles. + @return a reference to the triad of euler angles corresponding + to this quaternion rotation. + units radians */ + const FGColumnVector3& GetEuler(void) const { + ComputeDerived(); + return mEulerAngles; + } + + /** Retrieves the Euler angles. + @param i the euler angle index. + units radians. + @return a reference to the i-th euler angles corresponding + to this quaternion rotation. + */ + double GetEuler(int i) const { + ComputeDerived(); + return mEulerAngles(i); + } + + /** Retrieves the Euler angles. + @param i the euler angle index. + @return a reference to the i-th euler angles corresponding + to this quaternion rotation. + units degrees */ + double GetEulerDeg(int i) const { + ComputeDerived(); + return radtodeg*mEulerAngles(i); + } + + /** Retrieves sine of the given euler angle. + @return the sine of the Euler angle theta (pitch attitude) corresponding + to this quaternion rotation. */ + double GetSinEuler(int i) const { + ComputeDerived(); + return mEulerSines(i); + } + + /** Retrieves cosine of the given euler angle. + @return the sine of the Euler angle theta (pitch attitude) corresponding + to this quaternion rotation. */ + double GetCosEuler(int i) const { + ComputeDerived(); + return mEulerCosines(i); + } + + /** Read access the entries of the vector. + + @param idx the component index. + + Return the value of the matrix entry at the given index. + Indices are counted starting with 1. + + Note that the index given in the argument is unchecked. + */ + double operator()(unsigned int idx) const { return data[idx-1]; } + + /** Write access the entries of the vector. + + @param idx the component index. + + Return a reference to the vector entry at the given index. + Indices are counted starting with 1. + + Note that the index given in the argument is unchecked. + */ + double& operator()(unsigned int idx) { mCacheValid = false; return data[idx-1]; } + + /** Read access the entries of the vector. + + @param idx the component index. + + Return the value of the matrix entry at the given index. + Indices are counted starting with 1. + + This function is just a shortcut for the <tt>double + operator()(unsigned int idx) const</tt> function. It is + used internally to access the elements in a more convenient way. + + Note that the index given in the argument is unchecked. + */ + double Entry(unsigned int idx) const { return data[idx-1]; } + + /** Write access the entries of the vector. + + @param idx the component index. + + Return a reference to the vector entry at the given index. + Indices are counted starting with 1. + + This function is just a shortcut for the <tt>double& + operator()(unsigned int idx)</tt> function. It is + used internally to access the elements in a more convenient way. + + Note that the index given in the argument is unchecked. + */ + double& Entry(unsigned int idx) { + mCacheValid = false; + return data[idx-1]; + } + + /** Assignment operator "=". + Assign the value of q to the current object. Cached values are + conserved. + @param q reference to an FGQuaternion instance + @return reference to a quaternion object */ + const FGQuaternion& operator=(const FGQuaternion& q) { + // Copy the master values ... + data[0] = q(1); + data[1] = q(2); + data[2] = q(3); + data[3] = q(4); + ComputeDerived(); + // .. and copy the derived values if they are valid + mCacheValid = q.mCacheValid; + if (mCacheValid) { + mT = q.mT; + mTInv = q.mTInv; + mEulerAngles = q.mEulerAngles; + mEulerSines = q.mEulerSines; + mEulerCosines = q.mEulerCosines; + } + return *this; + } + + /// Conversion from Quat to Matrix + operator FGMatrix33() const { return GetT(); } + + /** Comparison operator "==". + @param q a quaternion reference + @return true if both quaternions represent the same rotation. */ + bool operator==(const FGQuaternion& q) const { + return data[0] == q(1) && data[1] == q(2) + && data[2] == q(3) && data[3] == q(4); + } + + /** Comparison operator "!=". + @param q a quaternion reference + @return true if both quaternions do not represent the same rotation. */ + bool operator!=(const FGQuaternion& q) const { return ! operator==(q); } + const FGQuaternion& operator+=(const FGQuaternion& q) { + // Copy the master values ... + data[0] += q(1); + data[1] += q(2); + data[2] += q(3); + data[3] += q(4); + mCacheValid = false; + return *this; + } + + /** Arithmetic operator "-=". + @param q a quaternion reference. + @return a quaternion reference representing Q, where Q = Q - q. */ + const FGQuaternion& operator-=(const FGQuaternion& q) { + // Copy the master values ... + data[0] -= q(1); + data[1] -= q(2); + data[2] -= q(3); + data[3] -= q(4); + mCacheValid = false; + return *this; + } + + /** Arithmetic operator "*=". + @param scalar a multiplicative value. + @return a quaternion reference representing Q, where Q = Q * scalar. */ + const FGQuaternion& operator*=(double scalar) { + data[0] *= scalar; + data[1] *= scalar; + data[2] *= scalar; + data[3] *= scalar; + mCacheValid = false; + return *this; + } + + /** Arithmetic operator "/=". + @param scalar a divisor value. + @return a quaternion reference representing Q, where Q = Q / scalar. */ + const FGQuaternion& operator/=(double scalar) { + return operator*=(1.0/scalar); + } + + /** Arithmetic operator "+". + @param q a quaternion to be summed. + @return a quaternion representing Q, where Q = Q + q. */ + FGQuaternion operator+(const FGQuaternion& q) const { + return FGQuaternion(data[0]+q(1), data[1]+q(2), + data[2]+q(3), data[3]+q(4)); + } + + /** Arithmetic operator "-". + @param q a quaternion to be subtracted. + @return a quaternion representing Q, where Q = Q - q. */ + FGQuaternion operator-(const FGQuaternion& q) const { + return FGQuaternion(data[0]-q(1), data[1]-q(2), + data[2]-q(3), data[3]-q(4)); + } + + /** Arithmetic operator "*". + Multiplication of two quaternions is like performing successive rotations. + @param q a quaternion to be multiplied. + @return a quaternion representing Q, where Q = Q * q. */ + FGQuaternion operator*(const FGQuaternion& q) const { + return FGQuaternion(data[0]*q(1)-data[1]*q(2)-data[2]*q(3)-data[3]*q(4), + data[0]*q(2)+data[1]*q(1)+data[2]*q(4)-data[3]*q(3), + data[0]*q(3)-data[1]*q(4)+data[2]*q(1)+data[3]*q(2), + data[0]*q(4)+data[1]*q(3)-data[2]*q(2)+data[3]*q(1)); + } + + /** Arithmetic operator "*=". + Multiplication of two quaternions is like performing successive rotations. + @param q a quaternion to be multiplied. + @return a quaternion reference representing Q, where Q = Q * q. */ + const FGQuaternion& operator*=(const FGQuaternion& q) { + double q0 = data[0]*q(1)-data[1]*q(2)-data[2]*q(3)-data[3]*q(4); + double q1 = data[0]*q(2)+data[1]*q(1)+data[2]*q(4)-data[3]*q(3); + double q2 = data[0]*q(3)-data[1]*q(4)+data[2]*q(1)+data[3]*q(2); + double q3 = data[0]*q(4)+data[1]*q(3)-data[2]*q(2)+data[3]*q(1); + data[0] = q0; + data[1] = q1; + data[2] = q2; + data[3] = q3; + mCacheValid = false; + return *this; + } + + /** Inverse of the quaternion. + + Compute and return the inverse of the quaternion so that the orientation + represented with *this multiplied with the returned value is equal to + the identity orientation. + */ + FGQuaternion Inverse(void) const { + double norm = SqrMagnitude(); + if (norm == 0.0) + return *this; + double rNorm = 1.0/norm; + return FGQuaternion( data[0]*rNorm, -data[1]*rNorm, + -data[2]*rNorm, -data[3]*rNorm ); + } + + /** Conjugate of the quaternion. + + Compute and return the conjugate of the quaternion. This one is equal + to the inverse iff the quaternion is normalized. + */ + FGQuaternion Conjugate(void) const { + return FGQuaternion( data[0], -data[1], -data[2], -data[3] ); + } + + friend FGQuaternion operator*(double, const FGQuaternion&); + + /** Length of the vector. + + Compute and return the euclidean norm of this vector. + */ + double Magnitude(void) const { return sqrt(SqrMagnitude()); } + + /** Square of the length of the vector. + + Compute and return the square of the euclidean norm of this vector. + */ + double SqrMagnitude(void) const { + return data[0]*data[0] + data[1]*data[1] + + data[2]*data[2] + data[3]*data[3]; + } + + /** Normalize. + + Normalize the vector to have the Magnitude() == 1.0. If the vector + is equal to zero it is left untouched. + */ + void Normalize(void); + + /** Zero quaternion vector. Does not represent any orientation. + Useful for initialization of increments */ + static FGQuaternion zero(void) { return FGQuaternion( 0.0, 0.0, 0.0, 0.0 ); } private: - /** Copying by assigning the vector valued components. */ - FGQuaternion(double q1, double q2, double q3, double q4) : mCacheValid(false) - { - data[0] = q1; - data[1] = q2; - data[2] = q3; - data[3] = q4; - } - - /** Computation of derived values. - This function recomputes the derived values like euler angles and - transformation matrices. It does this unconditionally. */ - void ComputeDerivedUnconditional(void) const; - - /** Computation of derived values. - This function checks if the derived values like euler angles and - transformation matrices are already computed. If so, it - returns. If they need to be computed the real worker routine - FGQuaternion::ComputeDerivedUnconditional(void) const - is called. */ - void ComputeDerived(void) const - { - if (!mCacheValid) - ComputeDerivedUnconditional(); - } - - /** The quaternion values itself. This is the master copy. */ - double data[4]; - - /** A data validity flag. - This class implements caching of the derived values like the - orthogonal rotation matrices or the Euler angles. For caching we - carry a flag which signals if the values are valid or not. - The C++ keyword "mutable" tells the compiler that the data member is - allowed to change during a const member function. */ - mutable bool mCacheValid; - - /** This stores the transformation matrices. */ - mutable FGMatrix33 mT; - mutable FGMatrix33 mTInv; - - /** The cached euler angles. */ - mutable FGColumnVector3 mEulerAngles; - - /** The cached sines and cosines of the euler angles. */ - mutable FGColumnVector3 mEulerSines; - mutable FGColumnVector3 mEulerCosines; - - void Debug(int from) const; - - void InitializeFromEulerAngles(double phi, double tht, double psi); + /** Copying by assigning the vector valued components. */ + FGQuaternion(double q1, double q2, double q3, double q4) : mCacheValid(false) + { data[0] = q1; data[1] = q2; data[2] = q3; data[3] = q4; } + + /** Computation of derived values. + This function recomputes the derived values like euler angles and + transformation matrices. It does this unconditionally. */ + void ComputeDerivedUnconditional(void) const; + + /** Computation of derived values. + This function checks if the derived values like euler angles and + transformation matrices are already computed. If so, it + returns. If they need to be computed the real worker routine + FGQuaternion::ComputeDerivedUnconditional(void) const + is called. */ + void ComputeDerived(void) const { + if (!mCacheValid) + ComputeDerivedUnconditional(); + } + + /** The quaternion values itself. This is the master copy. */ + double data[4]; + + /** A data validity flag. + This class implements caching of the derived values like the + orthogonal rotation matrices or the Euler angles. For caching we + carry a flag which signals if the values are valid or not. + The C++ keyword "mutable" tells the compiler that the data member is + allowed to change during a const member function. */ + mutable bool mCacheValid; + + /** This stores the transformation matrices. */ + mutable FGMatrix33 mT; + mutable FGMatrix33 mTInv; + + /** The cached euler angles. */ + mutable FGColumnVector3 mEulerAngles; + + /** The cached sines and cosines of the euler angles. */ + mutable FGColumnVector3 mEulerSines; + mutable FGColumnVector3 mEulerCosines; + + void Debug(int from) const; + + void InitializeFromEulerAngles(double phi, double tht, double psi); }; /** Scalar multiplication. @@ -574,9 +509,8 @@ private: Multiply the Vector with a scalar value. */ -inline FGQuaternion operator*(double scalar, const FGQuaternion& q) -{ - return FGQuaternion(scalar*q(1), scalar*q(2), scalar*q(3), scalar*q(4)); +inline FGQuaternion operator*(double scalar, const FGQuaternion& q) { + return FGQuaternion(scalar*q(1), scalar*q(2), scalar*q(3), scalar*q(4)); } } // namespace JSBSim diff --git a/src/math/FGRealValue.cpp b/src/math/FGRealValue.cpp old mode 100644 new mode 100755 index d6f42324f9c546427ebed53c336b0a33e00f08f4..a30f9fccee4d4a21d464f86713b958cddcaae0e9 --- a/src/math/FGRealValue.cpp +++ b/src/math/FGRealValue.cpp @@ -30,8 +30,7 @@ INCLUDES #include "FGRealValue.h" -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGRealValue.cpp,v 1.4 2009/08/30 03:51:28 jberndt Exp $"; static const char *IdHdr = ID_REALVALUE; @@ -48,7 +47,7 @@ FGRealValue::FGRealValue(double value) : Value(value) double FGRealValue::GetValue(void) const { - return Value; + return Value; } } diff --git a/src/math/FGRealValue.h b/src/math/FGRealValue.h old mode 100644 new mode 100755 index aa267bf35c3ea935ef42bb6802292eaf09e8c671..277c595c1b2f0a4aa8e0a3794b23c6a1a576d16b --- a/src/math/FGRealValue.h +++ b/src/math/FGRealValue.h @@ -46,16 +46,15 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -/** Represents a real value - @author Jon Berndt -*/ + /** Represents a real value + @author Jon Berndt + */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DECLARATION: FGRealValue @@ -65,13 +64,13 @@ class FGRealValue : public FGParameter { public: - FGRealValue(double val); - ~FGRealValue() {}; + FGRealValue(double val); + ~FGRealValue() {}; - double GetValue(void) const; + double GetValue(void) const; private: - double Value; + double Value; }; } // namespace JSBSim diff --git a/src/math/FGRungeKutta.cpp b/src/math/FGRungeKutta.cpp index d35b82cdc4ca46fbd81b3a358fe9dfccdb53debd..bc3dabc0796abefa62dcd723e0c9aef367e4273f 100644 --- a/src/math/FGRungeKutta.cpp +++ b/src/math/FGRungeKutta.cpp @@ -42,9 +42,8 @@ using std::cout; using std::endl; -namespace JSBSim -{ - +namespace JSBSim { + static const char *IdSrc = "$Id: FGRungeKutta.cpp,v 1.1 2010/06/02 04:05:13 jberndt Exp $"; static const char *IdHdr = ID_RUNGEKUTTA; @@ -58,18 +57,17 @@ FGRungeKutta::~FGRungeKutta() { }; int FGRungeKutta::init(double x_start, double x_end, int intervals) { - x0 = x_start; - x1 = x_end; - h = (x_end - x_start)/intervals; - safer_x1 = x1 - h*1e-6; // avoid 'intervals*h < x1' - h05 = h*0.5; - err = 0.0; - - if (x0>=x1) - { - status &= eFaultyInit; - } - return status; + x0 = x_start; + x1 = x_end; + h = (x_end - x_start)/intervals; + safer_x1 = x1 - h*1e-6; // avoid 'intervals*h < x1' + h05 = h*0.5; + err = 0.0; + + if (x0>=x1) { + status &= eFaultyInit; + } + return status; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -77,58 +75,47 @@ int FGRungeKutta::init(double x_start, double x_end, int intervals) /* Make sure that a numerical result is within +/-RealLimit. This is a hapless try to be portable. - (There will be at least one architecture/compiler combination + (There will be at least one architecture/compiler combination where this will fail.) */ bool FGRungeKutta::sane_val(double x) { - // assuming +/- inf behave as expected and 'nan' comparisons yield to false - if ( x < RealLimit && x > -RealLimit ) return true; - return false; + // assuming +/- inf behave as expected and 'nan' comparisons yield to false + if ( x < RealLimit && x > -RealLimit ) return true; + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGRungeKutta::evolve(double y_0, FGRungeKuttaProblem *pf) { - double x = x0; - double y = y_0; - pfo = pf; - - iterations = 0; - - if (!trace_values) - { - while (x<safer_x1) - { - y = approximate(x,y); - if (!sane_val(y)) - { - status &= eMathError; - } - x += h; - iterations++; - } + double x = x0; + double y = y_0; + pfo = pf; + + iterations = 0; + + if (!trace_values) { + while (x<safer_x1) { + y = approximate(x,y); + if (!sane_val(y)) { status &= eMathError; } + x += h; + iterations++; } - else - { - while (x<safer_x1) - { - cout << x << " " << y << endl; - y = approximate(x,y); - if (!sane_val(y)) - { - status &= eMathError; - } - x += h; - iterations++; - } - cout << x << " " << y << endl; + } else { + while (x<safer_x1) { + cout << x << " " << y << endl; + y = approximate(x,y); + if (!sane_val(y)) { status &= eMathError; } + x += h; + iterations++; } + cout << x << " " << y << endl; + } - x_end = x; // twimc, store the last x used. - return y; + x_end = x; // twimc, store the last x used. + return y; } @@ -143,18 +130,18 @@ FGRK4::~FGRK4() { }; double FGRK4::approximate(double x, double y) { - double k1,k2,k3,k4; + double k1,k2,k3,k4; - k1 = pfo->pFunc(x , y ); - k2 = pfo->pFunc(x + h05, y + h05*k1); - k3 = pfo->pFunc(x + h05, y + h05*k2); - k4 = pfo->pFunc(x + h , y + h *k3); + k1 = pfo->pFunc(x , y ); + k2 = pfo->pFunc(x + h05, y + h05*k1); + k3 = pfo->pFunc(x + h05, y + h05*k2); + k4 = pfo->pFunc(x + h , y + h *k3); - y += h/6.0 * ( k1 + 2.0*k2 + 2.0*k3 + k4 ); + y += h/6.0 * ( k1 + 2.0*k2 + 2.0*k3 + k4 ); - return y; + return y; } - + /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS IMPLEMENTATION @@ -180,70 +167,63 @@ FGRKFehlberg::~FGRKFehlberg() { }; double FGRKFehlberg::approximate(double x, double y) { - double k1,k2,k3,k4,k5,k6, as; + double k1,k2,k3,k4,k5,k6, as; - double y4_val; - double y5_val; - double abs_err; - double est_step; - int done = 0; + double y4_val; + double y5_val; + double abs_err; + double est_step; + int done = 0; - while (!done) - { + while (!done) { - err = h*h*h*h*h; // h might change + err = h*h*h*h*h; // h might change - k1 = pfo->pFunc(x , y ); + k1 = pfo->pFunc(x , y ); - as = h*A2[1]*k1; - k2 = pfo->pFunc(x + C[2]*h , y + as ); + as = h*A2[1]*k1; + k2 = pfo->pFunc(x + C[2]*h , y + as ); - as = h*(A3[1]*k1 + A3[2]*k2); - k3 = pfo->pFunc(x + C[3]*h , y + as ); + as = h*(A3[1]*k1 + A3[2]*k2); + k3 = pfo->pFunc(x + C[3]*h , y + as ); - as = h*(A4[1]*k1 + A4[2]*k2 + A4[3]*k3); - k4 = pfo->pFunc(x + C[4]*h , y + as ); + as = h*(A4[1]*k1 + A4[2]*k2 + A4[3]*k3); + k4 = pfo->pFunc(x + C[4]*h , y + as ); - as = h*(A5[1]*k1 + A5[2]*k2 + A5[3]*k3 + A5[4]*k4); - k5 = pfo->pFunc(x + C[5]*h , y + as ); + as = h*(A5[1]*k1 + A5[2]*k2 + A5[3]*k3 + A5[4]*k4); + k5 = pfo->pFunc(x + C[5]*h , y + as ); - as = h*(A6[1]*k1 + A6[2]*k2 + A6[3]*k3 + A6[4]*k4 + A6[5]*k5); - k6 = pfo->pFunc(x + C[6]*h , y + as ); + as = h*(A6[1]*k1 + A6[2]*k2 + A6[3]*k3 + A6[4]*k4 + A6[5]*k5); + k6 = pfo->pFunc(x + C[6]*h , y + as ); - /* B[2]*k2 and Bs[2]*k2 are zero */ - y5_val = y + h * ( B[1]*k1 + B[3]*k3 + B[4]*k4 + B[5]*k5 + B[6]*k6); - y4_val = y + h * (Bs[1]*k1 + Bs[3]*k3 + Bs[4]*k4 + Bs[5]*k5); + /* B[2]*k2 and Bs[2]*k2 are zero */ + y5_val = y + h * ( B[1]*k1 + B[3]*k3 + B[4]*k4 + B[5]*k5 + B[6]*k6); + y4_val = y + h * (Bs[1]*k1 + Bs[3]*k3 + Bs[4]*k4 + Bs[5]*k5); - abs_err = fabs(y4_val-y5_val); - // same in green - // abs_err = h * (Ee[1] * k1 + Ee[3] * k3 + Ee[4] * k4 + Ee[5] * k5 + Ee[6] * k6); + abs_err = fabs(y4_val-y5_val); + // same in green + // abs_err = h * (Ee[1] * k1 + Ee[3] * k3 + Ee[4] * k4 + Ee[5] * k5 + Ee[6] * k6); - // estimate step size - if (abs_err > epsilon) - { - est_step = sqrt(sqrt(epsilon*h/abs_err)); - } - else - { - est_step=2.0*h; // cheat - } - - // check if a smaller step size is proposed + // estimate step size + if (abs_err > epsilon) { + est_step = sqrt(sqrt(epsilon*h/abs_err)); + } else { + est_step=2.0*h; // cheat + } - if (shrink_avail>0 && est_step<h) - { - h/=2.0; - shrink_avail--; - } - else - { - done = 1; - } + // check if a smaller step size is proposed + if (shrink_avail>0 && est_step<h) { + h/=2.0; + shrink_avail--; + } else { + done = 1; } - return y4_val; + } + + return y4_val; } diff --git a/src/math/FGRungeKutta.h b/src/math/FGRungeKutta.h index 06e9349a0bfb24f111664d14081d20e6858ac6a1..692957725914d8bd8dc259ff74f7318a098087b6 100644 --- a/src/math/FGRungeKutta.h +++ b/src/math/FGRungeKutta.h @@ -46,8 +46,7 @@ SENTRY #define ID_RUNGEKUTTA "$Id: FGRungeKutta.h,v 1.1 2010/06/02 04:05:13 jberndt Exp $" -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -59,7 +58,7 @@ CLASS DOCUMENTATION are a standard for solving ordinary differential equation (ODE) initial value problems. The code follows closely the description given on Wikipedia, see http://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods. - + For more powerfull routines see GNU Scientific Library (GSL) or GNU Plotutils 'ode'. */ @@ -72,9 +71,8 @@ DECLARATION: FGRungeKuttaProblem /** Abstract base for the function to solve. */ -class FGRungeKuttaProblem -{ -public: +class FGRungeKuttaProblem { + public: virtual double pFunc(double x, double y) = 0; }; @@ -85,10 +83,9 @@ DECLARATION: FGRungeKutta Abstract base. */ -class FGRungeKutta -{ +class FGRungeKutta { -public: + public: enum eStates { eNoError=0, eMathError=1, eFaultyInit=2, eEvolve=4, eUnknown=8} ; @@ -96,33 +93,15 @@ public: double evolve(double y_0, FGRungeKuttaProblem *pf); - double getXEnd() - { - return x_end; - } - double getError() - { - return err; - } - - int getStatus() - { - return status; - } - int getIterations() - { - return iterations; - } - void clearStatus() - { - status = eNoError; - } - void setTrace(bool t) - { - trace_values = t; - } - -protected: + double getXEnd() { return x_end; } + double getError() { return err; } + + int getStatus() { return status; } + int getIterations() { return iterations; } + void clearStatus() { status = eNoError; } + void setTrace(bool t) { trace_values = t; } + + protected: // avoid accidents FGRungeKutta(): status(eNoError), trace_values(false), iterations(0) {}; virtual ~FGRungeKutta(); @@ -133,7 +112,7 @@ protected: double h05; // h*0.5, halfwidth double err; -private: + private: virtual double approximate(double x, double y) = 0; @@ -159,10 +138,9 @@ DECLARATION: FGRK4 Classical RK4. */ -class FGRK4 : public FGRungeKutta -{ +class FGRK4 : public FGRungeKutta { virtual ~FGRK4(); -private: + private: double approximate(double x, double y); }; @@ -183,30 +161,17 @@ DECLARATION: FGRKFehlberg */ -class FGRKFehlberg : public FGRungeKutta -{ +class FGRKFehlberg : public FGRungeKutta { -public: + public: FGRKFehlberg() : shrink_avail(4), epsilon(1e-12) { }; virtual ~FGRKFehlberg(); - double getEpsilon() - { - return epsilon; - } - int getShrinkAvail() - { - return shrink_avail; - } - void setEpsilon(double e) - { - epsilon = e; - } - void setShrinkAvail(int s) - { - shrink_avail = s; - } - -private: + double getEpsilon() { return epsilon; } + int getShrinkAvail() { return shrink_avail; } + void setEpsilon(double e) { epsilon = e; } + void setShrinkAvail(int s) { shrink_avail = s; } + + private: double approximate(double x, double y); diff --git a/src/math/FGTable.cpp b/src/math/FGTable.cpp index e34cbc7d32e41b8d20010ec4c5a92c76bb14752b..8d40f8c3d871bb8291576570985dd3e78d3fe664 100644 --- a/src/math/FGTable.cpp +++ b/src/math/FGTable.cpp @@ -45,10 +45,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGTable.cpp,v 1.21 2010/04/07 03:08:37 jberndt Exp $"; +static const char *IdSrc = "$Id: FGTable.cpp,v 1.24 2010/09/23 11:34:29 jberndt Exp $"; static const char *IdHdr = ID_TABLE; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -57,608 +56,586 @@ CLASS IMPLEMENTATION FGTable::FGTable(int NRows) : nRows(NRows), nCols(1), PropertyManager(0) { - Type = tt1D; - colCounter = 0; - rowCounter = 1; - nTables = 0; + Type = tt1D; + colCounter = 0; + rowCounter = 1; + nTables = 0; + + Data = Allocate(); + Debug(0); + lastRowIndex=lastColumnIndex=2; +} - Data = Allocate(); - Debug(0); - lastRowIndex=lastColumnIndex=2; +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGTable::FGTable(int NRows, int NCols) : nRows(NRows), nCols(NCols), PropertyManager(0) +{ + Type = tt2D; + colCounter = 1; + rowCounter = 0; + nTables = 0; + + Data = Allocate(); + Debug(0); + lastRowIndex=lastColumnIndex=2; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGTable::FGTable(const FGTable& t) : PropertyManager(t.PropertyManager) { - Type = t.Type; - colCounter = t.colCounter; - rowCounter = t.rowCounter; - tableCounter = t.tableCounter; - nRows = t.nRows; - nCols = t.nCols; - nTables = t.nTables; - dimension = t.dimension; - internal = t.internal; - Name = t.Name; - lookupProperty[0] = t.lookupProperty[0]; - lookupProperty[1] = t.lookupProperty[1]; - lookupProperty[2] = t.lookupProperty[2]; - - Tables = t.Tables; - Data = Allocate(); - for (unsigned int r=0; r<=nRows; r++) - { - for (unsigned int c=0; c<=nCols; c++) - { - Data[r][c] = t.Data[r][c]; - } - } - lastRowIndex = t.lastRowIndex; - lastColumnIndex = t.lastColumnIndex; - lastTableIndex = t.lastTableIndex; + Type = t.Type; + colCounter = t.colCounter; + rowCounter = t.rowCounter; + tableCounter = t.tableCounter; + nRows = t.nRows; + nCols = t.nCols; + nTables = t.nTables; + dimension = t.dimension; + internal = t.internal; + Name = t.Name; + lookupProperty[0] = t.lookupProperty[0]; + lookupProperty[1] = t.lookupProperty[1]; + lookupProperty[2] = t.lookupProperty[2]; + + Tables = t.Tables; + Data = Allocate(); + for (unsigned int r=0; r<=nRows; r++) { + for (unsigned int c=0; c<=nCols; c++) { + Data[r][c] = t.Data[r][c]; + } + } + lastRowIndex = t.lastRowIndex; + lastColumnIndex = t.lastColumnIndex; + lastTableIndex = t.lastTableIndex; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(propMan) { - unsigned int i; - - stringstream buf; - string property_string; - string lookup_axis; - string call_type; - string parent_type; - string brkpt_string; - FGPropertyManager* node; - Element *tableData=0; - Element *parent_element=0; - Element *axisElement=0; - string operation_types = "function, product, sum, difference, quotient," - "pow, abs, sin, cos, asin, acos, tan, atan, table"; - - nTables = 0; - - // Is this an internal lookup table? - - internal = false; - Name = el->GetAttributeValue("name"); // Allow this table to be named with a property - call_type = el->GetAttributeValue("type"); - if (call_type == string("internal")) - { - parent_element = el->GetParent(); - parent_type = parent_element->GetName(); - if (operation_types.find(parent_type) == string::npos) - { - internal = true; - } - else - { - // internal table is a child element of a restricted type - cerr << endl << fgred << " An internal table cannot be nested within another type," << endl; - cerr << " such as a function. The 'internal' keyword is ignored." << fgdef << endl << endl; - } - } - else if (!call_type.empty()) - { - cerr << endl << fgred << " An unknown table type attribute is listed: " << call_type - << ". Execution cannot continue." << fgdef << endl << endl; - abort(); - } - - // Determine and store the lookup properties for this table unless this table - // is part of a 3D table, in which case its independentVar property indexes will - // be set by a call from the owning table during creation - - dimension = 0; - - axisElement = el->FindElement("independentVar"); - if (axisElement) - { - - // The 'internal' attribute of the table element cannot be specified - // at the same time that independentVars are specified. - if (internal) - { - cerr << endl << fgred << " This table specifies both 'internal' call type" << endl; - cerr << " and specific lookup properties via the 'independentVar' element." << endl; - cerr << " These are mutually exclusive specifications. The 'internal'" << endl; - cerr << " attribute will be ignored." << fgdef << endl << endl; - internal = false; - } - - for (i=0; i<3; i++) lookupProperty[i] = 0; - - while (axisElement) - { - property_string = axisElement->GetDataLine(); - // The property string passed into GetNode() must have no spaces or tabs. - node = PropertyManager->GetNode(property_string); - - if (node == 0) - { - throw("IndependenVar property, " + property_string + " in Table definition is not defined."); - } - - lookup_axis = axisElement->GetAttributeValue("lookup"); - if (lookup_axis == string("row")) - { - lookupProperty[eRow] = node; - } - else if (lookup_axis == string("column")) - { - lookupProperty[eColumn] = node; - } - else if (lookup_axis == string("table")) - { - lookupProperty[eTable] = node; - } - else if (!lookup_axis.empty()) - { - throw("Lookup table axis specification not understood: " + lookup_axis); - } - else // assumed single dimension table; row lookup - { - lookupProperty[eRow] = node; - } - dimension++; - axisElement = el->FindNextElement("independentVar"); - } - - } - else if (internal) // This table is an internal table - { - - // determine how many rows, columns, and tables in this table (dimension). - - if (el->GetNumElements("tableData") > 1) - { - dimension = 3; // this is a 3D table - } - else - { - tableData = el->FindElement("tableData"); - string test_line = tableData->GetDataLine(1); // examine second line in table for dimension - if (FindNumColumns(test_line) == 2) dimension = 1; // 1D table - else if (FindNumColumns(test_line) > 2) dimension = 2; // 2D table - else - { - cerr << "Invalid number of columns in table" << endl; - } - } - - } - else - { - brkpt_string = el->GetAttributeValue("breakPoint"); - if (brkpt_string.empty()) - { - // no independentVars found, and table is not marked as internal, nor is it a 3D table - cerr << endl << fgred << "No independent variable found for table." << fgdef << endl << endl; - abort(); - } - } - // end lookup property code + unsigned int i; + + stringstream buf; + string property_string; + string lookup_axis; + string call_type; + string parent_type; + string brkpt_string; + FGPropertyManager* node; + Element *tableData=0; + Element *parent_element=0; + Element *axisElement=0; + string operation_types = "function, product, sum, difference, quotient," + "pow, abs, sin, cos, asin, acos, tan, atan, table"; + + nTables = 0; + + // Is this an internal lookup table? + + internal = false; + Name = el->GetAttributeValue("name"); // Allow this table to be named with a property + call_type = el->GetAttributeValue("type"); + if (call_type == string("internal")) { + parent_element = el->GetParent(); + parent_type = parent_element->GetName(); + if (operation_types.find(parent_type) == string::npos) { + internal = true; + } else { + // internal table is a child element of a restricted type + cerr << endl << fgred << " An internal table cannot be nested within another type," << endl; + cerr << " such as a function. The 'internal' keyword is ignored." << fgdef << endl << endl; + } + } else if (!call_type.empty()) { + cerr << endl << fgred << " An unknown table type attribute is listed: " << call_type + << ". Execution cannot continue." << fgdef << endl << endl; + abort(); + } + + // Determine and store the lookup properties for this table unless this table + // is part of a 3D table, in which case its independentVar property indexes will + // be set by a call from the owning table during creation + + dimension = 0; + + axisElement = el->FindElement("independentVar"); + if (axisElement) { + + // The 'internal' attribute of the table element cannot be specified + // at the same time that independentVars are specified. + if (internal) { + cerr << endl << fgred << " This table specifies both 'internal' call type" << endl; + cerr << " and specific lookup properties via the 'independentVar' element." << endl; + cerr << " These are mutually exclusive specifications. The 'internal'" << endl; + cerr << " attribute will be ignored." << fgdef << endl << endl; + internal = false; + } + + for (i=0; i<3; i++) lookupProperty[i] = 0; + + while (axisElement) { + property_string = axisElement->GetDataLine(); + // The property string passed into GetNode() must have no spaces or tabs. + node = PropertyManager->GetNode(property_string); + + if (node == 0) { + throw("IndependentVar property, " + property_string + " in Table definition is not defined."); + } + + lookup_axis = axisElement->GetAttributeValue("lookup"); + if (lookup_axis == string("row")) { + lookupProperty[eRow] = node; + } else if (lookup_axis == string("column")) { + lookupProperty[eColumn] = node; + } else if (lookup_axis == string("table")) { + lookupProperty[eTable] = node; + } else if (!lookup_axis.empty()) { + throw("Lookup table axis specification not understood: " + lookup_axis); + } else { // assumed single dimension table; row lookup + lookupProperty[eRow] = node; + } + dimension++; + axisElement = el->FindNextElement("independentVar"); + } + + } else if (internal) { // This table is an internal table + + // determine how many rows, columns, and tables in this table (dimension). + + if (el->GetNumElements("tableData") > 1) { + dimension = 3; // this is a 3D table + } else { + tableData = el->FindElement("tableData"); + string test_line = tableData->GetDataLine(1); // examine second line in table for dimension + if (FindNumColumns(test_line) == 2) dimension = 1; // 1D table + else if (FindNumColumns(test_line) > 2) dimension = 2; // 2D table + else { + cerr << "Invalid number of columns in table" << endl; + } + } + + } else { + brkpt_string = el->GetAttributeValue("breakPoint"); + if (brkpt_string.empty()) { + // no independentVars found, and table is not marked as internal, nor is it a 3D table + cerr << endl << fgred << "No independent variable found for table." << fgdef << endl << endl; + abort(); + } + } + // end lookup property code + + if (brkpt_string.empty()) { // Not a 3D table "table element" + tableData = el->FindElement("tableData"); + } else { // This is a table in a 3D table + tableData = el; + dimension = 2; // Currently, infers 2D table + } + + for (i=0; i<tableData->GetNumDataLines(); i++) { + buf << tableData->GetDataLine(i) << string(" "); + } + switch (dimension) { + case 1: + nRows = tableData->GetNumDataLines(); + nCols = 1; + Type = tt1D; + colCounter = 0; + rowCounter = 1; + Data = Allocate(); + Debug(0); + lastRowIndex = lastColumnIndex = 2; + *this << buf; + break; + case 2: + nRows = tableData->GetNumDataLines()-1; - if (brkpt_string.empty()) // Not a 3D table "table element" - { - tableData = el->FindElement("tableData"); - } - else // This is a table in a 3D table - { - tableData = el; - dimension = 2; // Currently, infers 2D table + if (nRows >= 2) nCols = FindNumColumns(tableData->GetDataLine(0)); + else { + cerr << endl << fgred << "Not enough rows in this table." << fgdef << endl; + abort(); } - for (i=0; i<tableData->GetNumDataLines(); i++) - { - buf << tableData->GetDataLine(i) << string(" "); - } - switch (dimension) - { - case 1: - nRows = tableData->GetNumDataLines(); - nCols = 1; - Type = tt1D; - colCounter = 0; - rowCounter = 1; - Data = Allocate(); - Debug(0); - lastRowIndex = lastColumnIndex = 2; - *this << buf; - break; - case 2: - nRows = tableData->GetNumDataLines()-1; - - if (nRows >= 2) nCols = FindNumColumns(tableData->GetDataLine(0)); - else - { - cerr << endl << fgred << "Not enough rows in this table." << fgdef << endl; - abort(); - } + Type = tt2D; + colCounter = 1; + rowCounter = 0; - Type = tt2D; - colCounter = 1; - rowCounter = 0; - - Data = Allocate(); - lastRowIndex = lastColumnIndex = 2; - *this << buf; - break; - case 3: - nTables = el->GetNumElements("tableData"); - nRows = nTables; - nCols = 1; - Type = tt3D; - colCounter = 1; - rowCounter = 1; - lastRowIndex = lastColumnIndex = 2; - - Data = Allocate(); // this data array will contain the keys for the associated tables - Tables.reserve(nTables); // necessary? - tableData = el->FindElement("tableData"); - for (i=0; i<nTables; i++) - { - Tables.push_back(new FGTable(PropertyManager, tableData)); - Data[i+1][1] = tableData->GetAttributeValueAsNumber("breakPoint"); - Tables[i]->SetRowIndexProperty(lookupProperty[eRow]); - Tables[i]->SetColumnIndexProperty(lookupProperty[eColumn]); - tableData = el->FindNextElement("tableData"); - } + Data = Allocate(); + lastRowIndex = lastColumnIndex = 2; + *this << buf; + break; + case 3: + nTables = el->GetNumElements("tableData"); + nRows = nTables; + nCols = 1; + Type = tt3D; + colCounter = 1; + rowCounter = 1; + lastRowIndex = lastColumnIndex = 2; - Debug(0); - break; - default: - cout << "No dimension given" << endl; - break; + Data = Allocate(); // this data array will contain the keys for the associated tables + Tables.reserve(nTables); // necessary? + tableData = el->FindElement("tableData"); + for (i=0; i<nTables; i++) { + Tables.push_back(new FGTable(PropertyManager, tableData)); + Data[i+1][1] = tableData->GetAttributeValueAsNumber("breakPoint"); + Tables[i]->SetRowIndexProperty(lookupProperty[eRow]); + Tables[i]->SetColumnIndexProperty(lookupProperty[eColumn]); + tableData = el->FindNextElement("tableData"); } - bind(); - - if (debug_lvl & 1) Print(); + Debug(0); + break; + default: + cout << "No dimension given" << endl; + break; + } + + // Sanity checks: lookup indices must be increasing monotonically + unsigned int r,c,b; + + // find next xml element containing a name attribute + // to indicate where the error occured + Element* nameel = el; + while (nameel != 0 && nameel->GetAttributeValue("name") == "") + nameel=nameel->GetParent(); + + // check breakpoints, if applicable + if (dimension > 2) { + for (b=2; b<=nTables; ++b) { + if (Data[b][1] <= Data[b-1][1]) { + cerr << fgred << highint << endl + << " FGTable: breakpoint lookup is not monotonically increasing" << endl + << " in breakpoint " << b; + if (nameel != 0) + cerr << " of table in " << nameel->GetAttributeValue("name"); + cerr << ":" << reset << endl + << " " << Data[b][1] << "<=" << Data[b-1][1] << endl; + exit(-1); + } + } + } + + // check columns, if applicable + if (dimension > 1) { + for (c=2; c<=nCols; ++c) { + if (Data[0][c] <= Data[0][c-1]) { + cerr << fgred << highint << endl + << " FGTable: column lookup is not monotonically increasing" << endl + << " in column " << c; + if (nameel != 0) + cerr << " of table in " << nameel->GetAttributeValue("name"); + cerr << ":" << reset << endl + << " " << Data[0][c] << "<=" << Data[0][c-1] << endl; + exit(-1); + } + } + } + + // check rows + if (dimension < 3) { // in 3D tables, check only rows of subtables + for (r=2; r<=nRows; ++r) { + if (Data[r][0]<=Data[r-1][0]) { + cerr << fgred << highint << endl + << " FGTable: row lookup is not monotonically increasing" << endl + << " in row " << r; + if (nameel != 0) + cerr << " of table in " << nameel->GetAttributeValue("name"); + cerr << ":" << reset << endl + << " " << Data[r][0] << "<=" << Data[r-1][0] << endl; + exit(-1); + } + } + } + bind(); + + if (debug_lvl & 1) Print(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double** FGTable::Allocate(void) { - Data = new double*[nRows+1]; - for (unsigned int r=0; r<=nRows; r++) - { - Data[r] = new double[nCols+1]; - for (unsigned int c=0; c<=nCols; c++) - { - Data[r][c] = 0.0; - } - } - return Data; + Data = new double*[nRows+1]; + for (unsigned int r=0; r<=nRows; r++) { + Data[r] = new double[nCols+1]; + for (unsigned int c=0; c<=nCols; c++) { + Data[r][c] = 0.0; + } + } + return Data; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGTable::~FGTable() { - if (nTables > 0) - { - for (unsigned int i=0; i<nTables; i++) delete Tables[i]; - Tables.clear(); - } - for (unsigned int r=0; r<=nRows; r++) delete[] Data[r]; - delete[] Data; - - Debug(1); + if (nTables > 0) { + for (unsigned int i=0; i<nTables; i++) delete Tables[i]; + Tables.clear(); + } + for (unsigned int r=0; r<=nRows; r++) delete[] Data[r]; + delete[] Data; + + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% unsigned int FGTable::FindNumColumns(const string& test_line) { - // determine number of data columns in table (first column is row lookup - don't count) - size_t position=0; - unsigned int nCols=0; - while ((position = test_line.find_first_not_of(" \t", position)) != string::npos) - { - nCols++; - position = test_line.find_first_of(" \t", position); - } - return nCols; + // determine number of data columns in table (first column is row lookup - don't count) + size_t position=0; + unsigned int nCols=0; + while ((position = test_line.find_first_not_of(" \t", position)) != string::npos) { + nCols++; + position = test_line.find_first_of(" \t", position); + } + return nCols; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTable::GetValue(void) const { - double temp = 0; - double temp2 = 0; - - switch (Type) - { - case tt1D: - temp = lookupProperty[eRow]->getDoubleValue(); - temp2 = GetValue(temp); - return temp2; - case tt2D: - return GetValue(lookupProperty[eRow]->getDoubleValue(), - lookupProperty[eColumn]->getDoubleValue()); - case tt3D: - return GetValue(lookupProperty[eRow]->getDoubleValue(), - lookupProperty[eColumn]->getDoubleValue(), - lookupProperty[eTable]->getDoubleValue()); - default: - cerr << "Attempted to GetValue() for invalid/unknown table type" << endl; - throw(string("Attempted to GetValue() for invalid/unknown table type")); - } + double temp = 0; + double temp2 = 0; + + switch (Type) { + case tt1D: + temp = lookupProperty[eRow]->getDoubleValue(); + temp2 = GetValue(temp); + return temp2; + case tt2D: + return GetValue(lookupProperty[eRow]->getDoubleValue(), + lookupProperty[eColumn]->getDoubleValue()); + case tt3D: + return GetValue(lookupProperty[eRow]->getDoubleValue(), + lookupProperty[eColumn]->getDoubleValue(), + lookupProperty[eTable]->getDoubleValue()); + default: + cerr << "Attempted to GetValue() for invalid/unknown table type" << endl; + throw(string("Attempted to GetValue() for invalid/unknown table type")); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTable::GetValue(double key) const { - double Factor, Value, Span; - unsigned int r = lastRowIndex; - - //if the key is off the end of the table, just return the - //end-of-table value, do not extrapolate - if ( key <= Data[1][0] ) - { - lastRowIndex=2; - //cout << "Key underneath table: " << key << endl; - return Data[1][1]; - } - else if ( key >= Data[nRows][0] ) - { - lastRowIndex=nRows; - //cout << "Key over table: " << key << endl; - return Data[nRows][1]; - } - - // the key is somewhere in the middle, search for the right breakpoint - // The search is particularly efficient if - // the correct breakpoint has not changed since last frame or - // has only changed very little - - while (r > 2 && Data[r-1][0] > key) - { - r--; - } - while (r < nRows && Data[r][0] < key) - { - r++; - } - - lastRowIndex=r; - // make sure denominator below does not go to zero. - - Span = Data[r][0] - Data[r-1][0]; - if (Span != 0.0) - { - Factor = (key - Data[r-1][0]) / Span; - if (Factor > 1.0) Factor = 1.0; - } - else - { - Factor = 1.0; - } - - Value = Factor*(Data[r][1] - Data[r-1][1]) + Data[r-1][1]; - - return Value; + double Factor, Value, Span; + unsigned int r = lastRowIndex; + + //if the key is off the end of the table, just return the + //end-of-table value, do not extrapolate + if( key <= Data[1][0] ) { + lastRowIndex=2; + //cout << "Key underneath table: " << key << endl; + return Data[1][1]; + } else if ( key >= Data[nRows][0] ) { + lastRowIndex=nRows; + //cout << "Key over table: " << key << endl; + return Data[nRows][1]; + } + + // the key is somewhere in the middle, search for the right breakpoint + // The search is particularly efficient if + // the correct breakpoint has not changed since last frame or + // has only changed very little + + while (r > 2 && Data[r-1][0] > key) { r--; } + while (r < nRows && Data[r][0] < key) { r++; } + + lastRowIndex=r; + // make sure denominator below does not go to zero. + + Span = Data[r][0] - Data[r-1][0]; + if (Span != 0.0) { + Factor = (key - Data[r-1][0]) / Span; + if (Factor > 1.0) Factor = 1.0; + } else { + Factor = 1.0; + } + + Value = Factor*(Data[r][1] - Data[r-1][1]) + Data[r-1][1]; + + return Value; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTable::GetValue(double rowKey, double colKey) const { - double rFactor, cFactor, col1temp, col2temp, Value; - unsigned int r = lastRowIndex; - unsigned int c = lastColumnIndex; + double rFactor, cFactor, col1temp, col2temp, Value; + unsigned int r = lastRowIndex; + unsigned int c = lastColumnIndex; - while (r > 2 && Data[r-1][0] > rowKey) - { - r--; - } - while (r < nRows && Data[r] [0] < rowKey) - { - r++; - } + while(r > 2 && Data[r-1][0] > rowKey) { r--; } + while(r < nRows && Data[r] [0] < rowKey) { r++; } - while (c > 2 && Data[0][c-1] > colKey) - { - c--; - } - while (c < nCols && Data[0][c] < colKey) - { - c++; - } + while(c > 2 && Data[0][c-1] > colKey) { c--; } + while(c < nCols && Data[0][c] < colKey) { c++; } - lastRowIndex=r; - lastColumnIndex=c; + lastRowIndex=r; + lastColumnIndex=c; - rFactor = (rowKey - Data[r-1][0]) / (Data[r][0] - Data[r-1][0]); - cFactor = (colKey - Data[0][c-1]) / (Data[0][c] - Data[0][c-1]); + rFactor = (rowKey - Data[r-1][0]) / (Data[r][0] - Data[r-1][0]); + cFactor = (colKey - Data[0][c-1]) / (Data[0][c] - Data[0][c-1]); - if (rFactor > 1.0) rFactor = 1.0; - else if (rFactor < 0.0) rFactor = 0.0; + if (rFactor > 1.0) rFactor = 1.0; + else if (rFactor < 0.0) rFactor = 0.0; - if (cFactor > 1.0) cFactor = 1.0; - else if (cFactor < 0.0) cFactor = 0.0; + if (cFactor > 1.0) cFactor = 1.0; + else if (cFactor < 0.0) cFactor = 0.0; - col1temp = rFactor*(Data[r][c-1] - Data[r-1][c-1]) + Data[r-1][c-1]; - col2temp = rFactor*(Data[r][c] - Data[r-1][c]) + Data[r-1][c]; + col1temp = rFactor*(Data[r][c-1] - Data[r-1][c-1]) + Data[r-1][c-1]; + col2temp = rFactor*(Data[r][c] - Data[r-1][c]) + Data[r-1][c]; - Value = col1temp + cFactor*(col2temp - col1temp); + Value = col1temp + cFactor*(col2temp - col1temp); - return Value; + return Value; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTable::GetValue(double rowKey, double colKey, double tableKey) const { - double Factor, Value, Span; - unsigned int r = lastRowIndex; - - //if the key is off the end (or before the beginning) of the table, - // just return the boundary-table value, do not extrapolate - - if ( tableKey <= Data[1][1] ) - { - lastRowIndex=2; - return Tables[0]->GetValue(rowKey, colKey); - } - else if ( tableKey >= Data[nRows][1] ) - { - lastRowIndex=nRows; - return Tables[nRows-1]->GetValue(rowKey, colKey); - } - - // the key is somewhere in the middle, search for the right breakpoint - // The search is particularly efficient if - // the correct breakpoint has not changed since last frame or - // has only changed very little - - while (r > 2 && Data[r-1][1] > tableKey) - { - r--; - } - while (r < nRows && Data[r] [1] < tableKey) - { - r++; - } - - lastRowIndex=r; - // make sure denominator below does not go to zero. - - Span = Data[r][1] - Data[r-1][1]; - if (Span != 0.0) - { - Factor = (tableKey - Data[r-1][1]) / Span; - if (Factor > 1.0) Factor = 1.0; - } - else - { - Factor = 1.0; - } - - Value = Factor*(Tables[r-1]->GetValue(rowKey, colKey) - Tables[r-2]->GetValue(rowKey, colKey)) - + Tables[r-2]->GetValue(rowKey, colKey); - - return Value; + double Factor, Value, Span; + unsigned int r = lastRowIndex; + + //if the key is off the end (or before the beginning) of the table, + // just return the boundary-table value, do not extrapolate + + if( tableKey <= Data[1][1] ) { + lastRowIndex=2; + return Tables[0]->GetValue(rowKey, colKey); + } else if ( tableKey >= Data[nRows][1] ) { + lastRowIndex=nRows; + return Tables[nRows-1]->GetValue(rowKey, colKey); + } + + // the key is somewhere in the middle, search for the right breakpoint + // The search is particularly efficient if + // the correct breakpoint has not changed since last frame or + // has only changed very little + + while(r > 2 && Data[r-1][1] > tableKey) { r--; } + while(r < nRows && Data[r] [1] < tableKey) { r++; } + + lastRowIndex=r; + // make sure denominator below does not go to zero. + + Span = Data[r][1] - Data[r-1][1]; + if (Span != 0.0) { + Factor = (tableKey - Data[r-1][1]) / Span; + if (Factor > 1.0) Factor = 1.0; + } else { + Factor = 1.0; + } + + Value = Factor*(Tables[r-1]->GetValue(rowKey, colKey) - Tables[r-2]->GetValue(rowKey, colKey)) + + Tables[r-2]->GetValue(rowKey, colKey); + + return Value; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGTable::operator<<(istream& in_stream) { - int startRow=0; - int startCol=0; + int startRow=0; + int startCol=0; // In 1D table, no pseudo-row of column-headers (i.e. keys): - if (Type == tt1D) startRow = 1; - - for (unsigned int r=startRow; r<=nRows; r++) - { - for (unsigned int c=startCol; c<=nCols; c++) - { - if (r != 0 || c != 0) - { - in_stream >> Data[r][c]; - } - } + if (Type == tt1D) startRow = 1; + + for (unsigned int r=startRow; r<=nRows; r++) { + for (unsigned int c=startCol; c<=nCols; c++) { + if (r != 0 || c != 0) { + in_stream >> Data[r][c]; + } } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGTable& FGTable::operator<<(const double n) { - Data[rowCounter][colCounter] = n; - if (colCounter == (int)nCols) - { - colCounter = 0; - rowCounter++; - } - else - { - colCounter++; - } - return *this; + Data[rowCounter][colCounter] = n; + if (colCounter == (int)nCols) { + colCounter = 0; + rowCounter++; + } else { + colCounter++; + } + return *this; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGTable& FGTable::operator<<(const int n) { - *this << (double)n; - return *this; + *this << (double)n; + return *this; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGTable::Print(void) { - int startRow=0; - int startCol=0; + int startRow=0; + int startCol=0; - if (Type == tt1D || Type == tt3D) startRow = 1; - if (Type == tt3D) startCol = 1; + if (Type == tt1D || Type == tt3D) startRow = 1; + if (Type == tt3D) startCol = 1; #if defined (sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) - unsigned long flags = cout.setf(ios::fixed); + unsigned long flags = cout.setf(ios::fixed); #else - ios::fmtflags flags = cout.setf(ios::fixed); // set up output stream + ios::fmtflags flags = cout.setf(ios::fixed); // set up output stream #endif - switch (Type) - { + switch(Type) { case tt1D: - cout << " 1 dimensional table with " << nRows << " rows." << endl; - break; + cout << " 1 dimensional table with " << nRows << " rows." << endl; + break; case tt2D: - cout << " 2 dimensional table with " << nRows << " rows, " << nCols << " columns." << endl; - break; + cout << " 2 dimensional table with " << nRows << " rows, " << nCols << " columns." << endl; + break; case tt3D: - cout << " 3 dimensional table with " << nRows << " rows, " - << nCols << " columns " - << nTables << " tables." << endl; - break; - } - cout.precision(4); - for (unsigned int r=startRow; r<=nRows; r++) - { + cout << " 3 dimensional table with " << nRows << " rows, " + << nCols << " columns " + << nTables << " tables." << endl; + break; + } + cout.precision(4); + for (unsigned int r=startRow; r<=nRows; r++) { + cout << " "; + for (unsigned int c=startCol; c<=nCols; c++) { + if (r == 0 && c == 0) { cout << " "; - for (unsigned int c=startCol; c<=nCols; c++) - { - if (r == 0 && c == 0) - { - cout << " "; - } - else - { - cout << Data[r][c] << " "; - if (Type == tt3D) - { - cout << endl; - Tables[r-1]->Print(); - } - } + } else { + cout << Data[r][c] << " "; + if (Type == tt3D) { + cout << endl; + Tables[r-1]->Print(); } - cout << endl; + } } - cout.setf(flags); // reset + cout << endl; + } + cout.setf(flags); // reset } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGTable::bind(void) { - typedef double (FGTable::*PMF)(void) const; - if ( !Name.empty() && !internal) - { - string tmp = PropertyManager->mkPropertyName(Name, false); // Allow upper - PropertyManager->Tie( tmp, this, (PMF)&FGTable::GetValue); - } + typedef double (FGTable::*PMF)(void) const; + if ( !Name.empty() && !internal) { + string tmp = PropertyManager->mkPropertyName(Name, false); // Allow upper + PropertyManager->Tie( tmp, this, (PMF)&FGTable::GetValue); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // The bitmasked value choices are as follows: @@ -681,36 +658,28 @@ void FGTable::bind(void) void FGTable::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGTable" << endl; - if (from == 1) cout << "Destroyed: FGTable" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGTable" << endl; + if (from == 1) cout << "Destroyed: FGTable" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; + } + } } } diff --git a/src/math/FGTable.h b/src/math/FGTable.h index 4ddaf500fb8beefb75e7ffd37a265cb628384c39..2f2e271cdf2198318d29c46224c56fe02eda66ba 100644 --- a/src/math/FGTable.h +++ b/src/math/FGTable.h @@ -47,14 +47,13 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_TABLE "$Id: FGTable.h,v 1.11 2009/10/24 22:59:30 jberndt Exp $" +#define ID_TABLE "$Id: FGTable.h,v 1.12 2010/09/16 11:01:24 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGPropertyManager; class Element; @@ -234,7 +233,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio @endcode @author Jon S. Berndt -@version $Id: FGTable.h,v 1.11 2009/10/24 22:59:30 jberndt Exp $ +@version $Id: FGTable.h,v 1.12 2010/09/16 11:01:24 jberndt Exp $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -244,80 +243,72 @@ CLASS DECLARATION class FGTable : public FGParameter { public: - /// Destructor - ~FGTable(); - - /** This is the very important copy constructor. - @param table a const reference to a table.*/ - FGTable(const FGTable& table); - - /// The constructor for a table - FGTable (FGPropertyManager* propMan, Element* el); - FGTable (int ); - double GetValue(void) const; - double GetValue(double key) const; - double GetValue(double rowKey, double colKey) const; - double GetValue(double rowKey, double colKey, double TableKey) const; - /** Read the table in. - Data in the config file should be in matrix format with the row - independents as the first column and the column independents in - the first row. The implication of this layout is that there should - be no value in the upper left corner of the matrix e.g: - <pre> - 0 10 20 30 ... - -5 1 2 3 4 ... - ... - </pre> - - For multiple-table (i.e. 3D) data sets there is an additional number - key in the table definition. For example: - - <pre> - 0.0 - 0 10 20 30 ... - -5 1 2 3 4 ... - ... - </pre> - */ - - void operator<<(std::istream&); - FGTable& operator<<(const double n); - FGTable& operator<<(const int n); - - inline double GetElement(int r, int c) - { - return Data[r][c]; - } - inline double GetElement(int r, int c, int t); - - void SetRowIndexProperty(FGPropertyManager *node) - { - lookupProperty[eRow] = node; - } - void SetColumnIndexProperty(FGPropertyManager *node) - { - lookupProperty[eColumn] = node; - } - - void Print(void); + /// Destructor + ~FGTable(); + + /** This is the very important copy constructor. + @param table a const reference to a table.*/ + FGTable(const FGTable& table); + + /// The constructor for a table + FGTable (FGPropertyManager* propMan, Element* el); + FGTable (int ); + FGTable (int, int); + double GetValue(void) const; + double GetValue(double key) const; + double GetValue(double rowKey, double colKey) const; + double GetValue(double rowKey, double colKey, double TableKey) const; + /** Read the table in. + Data in the config file should be in matrix format with the row + independents as the first column and the column independents in + the first row. The implication of this layout is that there should + be no value in the upper left corner of the matrix e.g: + <pre> + 0 10 20 30 ... + -5 1 2 3 4 ... + ... + </pre> + + For multiple-table (i.e. 3D) data sets there is an additional number + key in the table definition. For example: + + <pre> + 0.0 + 0 10 20 30 ... + -5 1 2 3 4 ... + ... + </pre> + */ + + void operator<<(std::istream&); + FGTable& operator<<(const double n); + FGTable& operator<<(const int n); + + inline double GetElement(int r, int c) {return Data[r][c];} + inline double GetElement(int r, int c, int t); + + void SetRowIndexProperty(FGPropertyManager *node) {lookupProperty[eRow] = node;} + void SetColumnIndexProperty(FGPropertyManager *node) {lookupProperty[eColumn] = node;} + + void Print(void); private: - enum type {tt1D, tt2D, tt3D} Type; - enum axis {eRow=0, eColumn, eTable}; - bool internal; - FGPropertyManager *lookupProperty[3]; - double** Data; - std::vector <FGTable*> Tables; - unsigned int nRows, nCols, nTables, dimension; - int colCounter, rowCounter, tableCounter; - mutable int lastRowIndex, lastColumnIndex, lastTableIndex; - double** Allocate(void); - FGPropertyManager* const PropertyManager; - std::string Name; - void bind(void); - - unsigned int FindNumColumns(const std::string&); - void Debug(int from); + enum type {tt1D, tt2D, tt3D} Type; + enum axis {eRow=0, eColumn, eTable}; + bool internal; + FGPropertyManager *lookupProperty[3]; + double** Data; + std::vector <FGTable*> Tables; + unsigned int nRows, nCols, nTables, dimension; + int colCounter, rowCounter, tableCounter; + mutable int lastRowIndex, lastColumnIndex, lastTableIndex; + double** Allocate(void); + FGPropertyManager* const PropertyManager; + std::string Name; + void bind(void); + + unsigned int FindNumColumns(const std::string&); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/math/Makefile.am b/src/math/Makefile.am index d263c180c2f7e1ce671b24a26bda6609b2d92fed..0fde26ec45e52f3572c7191b7543cd1800bd590b 100644 --- a/src/math/Makefile.am +++ b/src/math/Makefile.am @@ -2,11 +2,13 @@ includedir = @includedir@/JSBSim/math LIBRARY_SOURCES = FGColumnVector3.cpp FGFunction.cpp FGLocation.cpp FGMatrix33.cpp \ FGPropertyValue.cpp FGQuaternion.cpp FGRealValue.cpp FGTable.cpp \ - FGCondition.cpp FGRungeKutta.cpp FGNelderMead.cpp FGStateSpace.cpp + FGCondition.cpp FGRungeKutta.cpp FGModelFunctions.cpp \ + FGNelderMead.cpp FGStateSpace.cpp LIBRARY_INCLUDES = FGColumnVector3.h FGFunction.h FGLocation.h FGMatrix33.h \ - FGParameter.h FGPropertyValue.h FGQuaternion.h FGRealValue.h FGTable.h \ - FGCondition.h FGRungeKutta.h FGNelderMead.h FGStateSpace.h + FGParameter.h FGPropertyValue.h FGQuaternion.h FGRealValue.h FGTable.h \ + FGCondition.h FGRungeKutta.h FGModelFunctions.h \ + FGNelderMead.h FGStateSpace.h if BUILD_LIBRARIES noinst_LTLIBRARIES = libMath.la diff --git a/src/models/FGAerodynamics.cpp b/src/models/FGAerodynamics.cpp index a91482a9191f1c1fb91c033abed660913a160333..7f5359e98df13028ce2c4baa2f068ecb2a6a7044 100644 --- a/src/models/FGAerodynamics.cpp +++ b/src/models/FGAerodynamics.cpp @@ -50,10 +50,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.31 2009/11/28 14:30:11 andgi Exp $"; +static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.32 2010/09/07 00:40:03 jberndt Exp $"; static const char *IdHdr = ID_AERODYNAMICS; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -63,189 +62,172 @@ CLASS IMPLEMENTATION FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec) { - Name = "FGAerodynamics"; + Name = "FGAerodynamics"; - AxisIdx["DRAG"] = 0; - AxisIdx["SIDE"] = 1; - AxisIdx["LIFT"] = 2; - AxisIdx["ROLL"] = 3; - AxisIdx["PITCH"] = 4; - AxisIdx["YAW"] = 5; + AxisIdx["DRAG"] = 0; + AxisIdx["SIDE"] = 1; + AxisIdx["LIFT"] = 2; + AxisIdx["ROLL"] = 3; + AxisIdx["PITCH"] = 4; + AxisIdx["YAW"] = 5; - AxisIdx["AXIAL"] = 0; - AxisIdx["NORMAL"] = 2; + AxisIdx["AXIAL"] = 0; + AxisIdx["NORMAL"] = 2; - AxisIdx["X"] = 0; - AxisIdx["Y"] = 1; - AxisIdx["Z"] = 2; + AxisIdx["X"] = 0; + AxisIdx["Y"] = 1; + AxisIdx["Z"] = 2; - axisType = atNone; + axisType = atNone; - Coeff = new CoeffArray[6]; + Coeff = new CoeffArray[6]; - impending_stall = stall_hyst = 0.0; - alphaclmin = alphaclmax = 0.0; - alphahystmin = alphahystmax = 0.0; - clsq = lod = 0.0; - alphaw = 0.0; - bi2vel = ci2vel = 0.0; - AeroRPShift = 0; - vDeltaRP.InitMatrix(); + impending_stall = stall_hyst = 0.0; + alphaclmin = alphaclmax = 0.0; + alphahystmin = alphahystmax = 0.0; + clsq = lod = 0.0; + alphaw = 0.0; + bi2vel = ci2vel = 0.0; + AeroRPShift = 0; + vDeltaRP.InitMatrix(); - bind(); + bind(); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGAerodynamics::~FGAerodynamics() { - unsigned int i,j; + unsigned int i,j; - for (i=0; i<6; i++) - for (j=0; j<Coeff[i].size(); j++) - delete Coeff[i][j]; + for (i=0; i<6; i++) + for (j=0; j<Coeff[i].size(); j++) + delete Coeff[i][j]; - delete[] Coeff; + delete[] Coeff; - delete AeroRPShift; + delete AeroRPShift; - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGAerodynamics::InitModel(void) { - if (!FGModel::InitModel()) return false; - - impending_stall = stall_hyst = 0.0; - alphaclmin = alphaclmax = 0.0; - alphahystmin = alphahystmax = 0.0; - clsq = lod = 0.0; - alphaw = 0.0; - bi2vel = ci2vel = 0.0; - AeroRPShift = 0; - vDeltaRP.InitMatrix(); - - return true; + if (!FGModel::InitModel()) return false; + + impending_stall = stall_hyst = 0.0; + alphaclmin = alphaclmax = 0.0; + alphahystmin = alphahystmax = 0.0; + clsq = lod = 0.0; + alphaw = 0.0; + bi2vel = ci2vel = 0.0; + AeroRPShift = 0; + vDeltaRP.InitMatrix(); + + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGAerodynamics::Run(void) { - unsigned int axis_ctr, ctr; - double alpha, twovel; - - if (FGModel::Run()) return true; - if (FDMExec->Holding()) return false; // if paused don't execute - - RunPreFunctions(); - - // calculate some oft-used quantities for speed - - twovel = 2*Auxiliary->GetVt(); - if (twovel != 0) - { - bi2vel = Aircraft->GetWingSpan() / twovel; - ci2vel = Aircraft->Getcbar() / twovel; - } - alphaw = Auxiliary->Getalpha() + Aircraft->GetWingIncidence(); - alpha = Auxiliary->Getalpha(); - qbar_area = Aircraft->GetWingArea() * Auxiliary->Getqbar(); - - if (alphaclmax != 0) - { - if (alpha > 0.85*alphaclmax) - { - impending_stall = 10*(alpha/alphaclmax - 0.85); - } - else - { - impending_stall = 0; - } + unsigned int axis_ctr, ctr; + double alpha, twovel; + + if (FGModel::Run()) return true; + if (FDMExec->Holding()) return false; // if paused don't execute + + RunPreFunctions(); + + // calculate some oft-used quantities for speed + + twovel = 2*Auxiliary->GetVt(); + if (twovel != 0) { + bi2vel = Aircraft->GetWingSpan() / twovel; + ci2vel = Aircraft->Getcbar() / twovel; + } + alphaw = Auxiliary->Getalpha() + Aircraft->GetWingIncidence(); + alpha = Auxiliary->Getalpha(); + qbar_area = Aircraft->GetWingArea() * Auxiliary->Getqbar(); + + if (alphaclmax != 0) { + if (alpha > 0.85*alphaclmax) { + impending_stall = 10*(alpha/alphaclmax - 0.85); + } else { + impending_stall = 0; } + } - if (alphahystmax != 0.0 && alphahystmin != 0.0) - { - if (alpha > alphahystmax) - { - stall_hyst = 1; - } - else if (alpha < alphahystmin) - { - stall_hyst = 0; - } + if (alphahystmax != 0.0 && alphahystmin != 0.0) { + if (alpha > alphahystmax) { + stall_hyst = 1; + } else if (alpha < alphahystmin) { + stall_hyst = 0; } + } - vFw.InitMatrix(); - vFnative.InitMatrix(); + vFw.InitMatrix(); + vFnative.InitMatrix(); - for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) - { - for (ctr=0; ctr < Coeff[axis_ctr].size(); ctr++) - { - vFnative(axis_ctr+1) += Coeff[axis_ctr][ctr]->GetValue(); - } + for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) { + for (ctr=0; ctr < Coeff[axis_ctr].size(); ctr++) { + vFnative(axis_ctr+1) += Coeff[axis_ctr][ctr]->GetValue(); } + } - // Note that we still need to convert to wind axes here, because it is - // used in the L/D calculation, and we still may want to look at Lift - // and Drag. + // Note that we still need to convert to wind axes here, because it is + // used in the L/D calculation, and we still may want to look at Lift + // and Drag. - switch (axisType) - { + switch (axisType) { case atBodyXYZ: // Forces already in body axes; no manipulation needed - vFw = GetTb2w()*vFnative; - vForces = vFnative; - break; + vFw = GetTb2w()*vFnative; + vForces = vFnative; + break; case atLiftDrag: // Copy forces into wind axes - vFw = vFnative; - vFw(eDrag)*=-1; - vFw(eLift)*=-1; - vForces = GetTw2b()*vFw; - break; + vFw = vFnative; + vFw(eDrag)*=-1; vFw(eLift)*=-1; + vForces = GetTw2b()*vFw; + break; case atAxialNormal: // Convert native forces into Axial|Normal|Side system - vFw = GetTb2w()*vFnative; - vFnative(eX)*=-1; - vFnative(eZ)*=-1; - vForces = vFnative; - break; + vFw = GetTb2w()*vFnative; + vFnative(eX)*=-1; vFnative(eZ)*=-1; + vForces = vFnative; + break; default: - cerr << endl << " A proper axis type has NOT been selected. Check " - << "your aerodynamics definition." << endl; - exit(-1); - } + cerr << endl << " A proper axis type has NOT been selected. Check " + << "your aerodynamics definition." << endl; + exit(-1); + } - // Calculate aerodynamic reference point shift, if any - if (AeroRPShift) vDeltaRP(eX) = AeroRPShift->GetValue()*Aircraft->Getcbar()*12.0; + // Calculate aerodynamic reference point shift, if any + if (AeroRPShift) vDeltaRP(eX) = AeroRPShift->GetValue()*Aircraft->Getcbar()*12.0; - // Calculate lift coefficient squared - if ( Auxiliary->Getqbar() > 0) - { - clsq = vFw(eLift) / (Aircraft->GetWingArea()*Auxiliary->Getqbar()); - clsq *= clsq; - } + // Calculate lift coefficient squared + if ( Auxiliary->Getqbar() > 0) { + clsq = vFw(eLift) / (Aircraft->GetWingArea()*Auxiliary->Getqbar()); + clsq *= clsq; + } - // Calculate lift Lift over Drag - if ( fabs(vFw(eDrag)) > 0.0) lod = fabs( vFw(eLift) / vFw(eDrag) ); + // Calculate lift Lift over Drag + if ( fabs(vFw(eDrag)) > 0.0) lod = fabs( vFw(eLift) / vFw(eDrag) ); - vDXYZcg = MassBalance->StructuralToBody(Aircraft->GetXYZrp() + vDeltaRP); + vDXYZcg = MassBalance->StructuralToBody(Aircraft->GetXYZrp() + vDeltaRP); - vMoments = vDXYZcg*vForces; // M = r X F + vMoments = vDXYZcg*vForces; // M = r X F - for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) - { - for (ctr = 0; ctr < Coeff[axis_ctr+3].size(); ctr++) - { - vMoments(axis_ctr+1) += Coeff[axis_ctr+3][ctr]->GetValue(); - } + for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) { + for (ctr = 0; ctr < Coeff[axis_ctr+3].size(); ctr++) { + vMoments(axis_ctr+1) += Coeff[axis_ctr+3][ctr]->GetValue(); } + } - RunPostFunctions(); + RunPostFunctions(); - return false; + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -266,278 +248,251 @@ bool FGAerodynamics::Run(void) FGMatrix33& FGAerodynamics::GetTw2b(void) { - double ca, cb, sa, sb; - - double alpha = Auxiliary->Getalpha(); - double beta = Auxiliary->Getbeta(); - - ca = cos(alpha); - sa = sin(alpha); - cb = cos(beta); - sb = sin(beta); - - mTw2b(1,1) = ca*cb; - mTw2b(1,2) = -ca*sb; - mTw2b(1,3) = -sa; - mTw2b(2,1) = sb; - mTw2b(2,2) = cb; - mTw2b(2,3) = 0.0; - mTw2b(3,1) = sa*cb; - mTw2b(3,2) = -sa*sb; - mTw2b(3,3) = ca; - - return mTw2b; + double ca, cb, sa, sb; + + double alpha = Auxiliary->Getalpha(); + double beta = Auxiliary->Getbeta(); + + ca = cos(alpha); + sa = sin(alpha); + cb = cos(beta); + sb = sin(beta); + + mTw2b(1,1) = ca*cb; + mTw2b(1,2) = -ca*sb; + mTw2b(1,3) = -sa; + mTw2b(2,1) = sb; + mTw2b(2,2) = cb; + mTw2b(2,3) = 0.0; + mTw2b(3,1) = sa*cb; + mTw2b(3,2) = -sa*sb; + mTw2b(3,3) = ca; + + return mTw2b; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33& FGAerodynamics::GetTb2w(void) { - double alpha,beta; - double ca, cb, sa, sb; - - alpha = Auxiliary->Getalpha(); - beta = Auxiliary->Getbeta(); - - ca = cos(alpha); - sa = sin(alpha); - cb = cos(beta); - sb = sin(beta); - - mTb2w(1,1) = ca*cb; - mTb2w(1,2) = sb; - mTb2w(1,3) = sa*cb; - mTb2w(2,1) = -ca*sb; - mTb2w(2,2) = cb; - mTb2w(2,3) = -sa*sb; - mTb2w(3,1) = -sa; - mTb2w(3,2) = 0.0; - mTb2w(3,3) = ca; - - return mTb2w; + double alpha,beta; + double ca, cb, sa, sb; + + alpha = Auxiliary->Getalpha(); + beta = Auxiliary->Getbeta(); + + ca = cos(alpha); + sa = sin(alpha); + cb = cos(beta); + sb = sin(beta); + + mTb2w(1,1) = ca*cb; + mTb2w(1,2) = sb; + mTb2w(1,3) = sa*cb; + mTb2w(2,1) = -ca*sb; + mTb2w(2,2) = cb; + mTb2w(2,3) = -sa*sb; + mTb2w(3,1) = -sa; + mTb2w(3,2) = 0.0; + mTb2w(3,3) = ca; + + return mTb2w; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGAerodynamics::Load(Element *element) { - string parameter, axis, scratch; - string scratch_unit=""; - string fname="", file=""; - Element *temp_element, *axis_element, *function_element; - - string separator = "/"; - - fname = element->GetAttributeValue("file"); - if (!fname.empty()) - { - file = FDMExec->GetFullAircraftPath() + separator + fname; - document = LoadXMLDocument(file); - } - else - { - document = element; - } - - FGModel::Load(document); // Perform base class Pre-Load - - DetermineAxisSystem(); // Detemine if Lift/Side/Drag, etc. is used. - - Debug(2); - - if ((temp_element = document->FindElement("alphalimits"))) - { - scratch_unit = temp_element->GetAttributeValue("unit"); - if (scratch_unit.empty()) scratch_unit = "RAD"; - alphaclmin = temp_element->FindElementValueAsNumberConvertFromTo("min", scratch_unit, "RAD"); - alphaclmax = temp_element->FindElementValueAsNumberConvertFromTo("max", scratch_unit, "RAD"); - } - - if ((temp_element = document->FindElement("hysteresis_limits"))) - { - scratch_unit = temp_element->GetAttributeValue("unit"); - if (scratch_unit.empty()) scratch_unit = "RAD"; - alphahystmin = temp_element->FindElementValueAsNumberConvertFromTo("min", scratch_unit, "RAD"); - alphahystmax = temp_element->FindElementValueAsNumberConvertFromTo("max", scratch_unit, "RAD"); - } - - if ((temp_element = document->FindElement("aero_ref_pt_shift_x"))) - { - function_element = temp_element->FindElement("function"); - AeroRPShift = new FGFunction(PropertyManager, function_element); - } - - axis_element = document->FindElement("axis"); - while (axis_element) - { - CoeffArray ca; - axis = axis_element->GetAttributeValue("name"); - function_element = axis_element->FindElement("function"); - while (function_element) - { - ca.push_back( new FGFunction(PropertyManager, function_element) ); - function_element = axis_element->FindNextElement("function"); - } - Coeff[AxisIdx[axis]] = ca; - axis_element = document->FindNextElement("axis"); + string parameter, axis, scratch; + string scratch_unit=""; + string fname="", file=""; + Element *temp_element, *axis_element, *function_element; + + string separator = "/"; + + fname = element->GetAttributeValue("file"); + if (!fname.empty()) { + file = FDMExec->GetFullAircraftPath() + separator + fname; + document = LoadXMLDocument(file); + } else { + document = element; + } + + FGModel::Load(document); // Perform base class Pre-Load + + DetermineAxisSystem(); // Detemine if Lift/Side/Drag, etc. is used. + + Debug(2); + + if ((temp_element = document->FindElement("alphalimits"))) { + scratch_unit = temp_element->GetAttributeValue("unit"); + if (scratch_unit.empty()) scratch_unit = "RAD"; + alphaclmin = temp_element->FindElementValueAsNumberConvertFromTo("min", scratch_unit, "RAD"); + alphaclmax = temp_element->FindElementValueAsNumberConvertFromTo("max", scratch_unit, "RAD"); + } + + if ((temp_element = document->FindElement("hysteresis_limits"))) { + scratch_unit = temp_element->GetAttributeValue("unit"); + if (scratch_unit.empty()) scratch_unit = "RAD"; + alphahystmin = temp_element->FindElementValueAsNumberConvertFromTo("min", scratch_unit, "RAD"); + alphahystmax = temp_element->FindElementValueAsNumberConvertFromTo("max", scratch_unit, "RAD"); + } + + if ((temp_element = document->FindElement("aero_ref_pt_shift_x"))) { + function_element = temp_element->FindElement("function"); + AeroRPShift = new FGFunction(PropertyManager, function_element); + } + + axis_element = document->FindElement("axis"); + while (axis_element) { + CoeffArray ca; + axis = axis_element->GetAttributeValue("name"); + function_element = axis_element->FindElement("function"); + while (function_element) { + ca.push_back( new FGFunction(PropertyManager, function_element) ); + function_element = axis_element->FindNextElement("function"); } + Coeff[AxisIdx[axis]] = ca; + axis_element = document->FindNextElement("axis"); + } - FGModel::PostLoad(document); // Perform base class Post-Load + PostLoad(document, PropertyManager); // Perform base class Post-Load - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // // This private class function checks to verify consistency in the choice of -// aerodynamic axes used in the config file. One set of LIFT|DRAG|SIDE, or +// aerodynamic axes used in the config file. One set of LIFT|DRAG|SIDE, or // X|Y|Z, or AXIAL|NORMAL|SIDE must be chosen; mixed system axes are not allowed. -// Note that if the "SIDE" axis specifier is entered first in a config file, +// Note that if the "SIDE" axis specifier is entered first in a config file, // a warning message will be given IF the AXIAL|NORMAL specifiers are also given. // This is OK, and the warning is due to the SIDE specifier used for both // the Lift/Drag and Axial/Normal axis systems. void FGAerodynamics::DetermineAxisSystem() { - Element* axis_element = document->FindElement("axis"); - string axis; - while (axis_element) - { - axis = axis_element->GetAttributeValue("name"); - if (axis == "LIFT" || axis == "DRAG" || axis == "SIDE") - { - if (axisType == atNone) axisType = atLiftDrag; - else if (axisType != atLiftDrag) - { - cerr << endl << " Mixed aerodynamic axis systems have been used in the" + Element* axis_element = document->FindElement("axis"); + string axis; + while (axis_element) { + axis = axis_element->GetAttributeValue("name"); + if (axis == "LIFT" || axis == "DRAG" || axis == "SIDE") { + if (axisType == atNone) axisType = atLiftDrag; + else if (axisType != atLiftDrag) { + cerr << endl << " Mixed aerodynamic axis systems have been used in the" << " aircraft config file." << endl; - } - } - else if (axis == "AXIAL" || axis == "NORMAL") - { - if (axisType == atNone) axisType = atAxialNormal; - else if (axisType != atAxialNormal) - { - cerr << endl << " Mixed aerodynamic axis systems have been used in the" + } + } else if (axis == "AXIAL" || axis == "NORMAL") { + if (axisType == atNone) axisType = atAxialNormal; + else if (axisType != atAxialNormal) { + cerr << endl << " Mixed aerodynamic axis systems have been used in the" << " aircraft config file." << endl; - } - } - else if (axis == "X" || axis == "Y" || axis == "Z") - { - if (axisType == atNone) axisType = atBodyXYZ; - else if (axisType != atBodyXYZ) - { - cerr << endl << " Mixed aerodynamic axis systems have been used in the" + } + } else if (axis == "X" || axis == "Y" || axis == "Z") { + if (axisType == atNone) axisType = atBodyXYZ; + else if (axisType != atBodyXYZ) { + cerr << endl << " Mixed aerodynamic axis systems have been used in the" << " aircraft config file." << endl; - } - } - else if (axis != "ROLL" && axis != "PITCH" && axis != "YAW") // error - { - cerr << endl << " An unknown axis type, " << axis << " has been specified" - << " in the aircraft configuration file." << endl; - exit(-1); - } - axis_element = document->FindNextElement("axis"); - } - if (axisType == atNone) - { - axisType = atLiftDrag; - cerr << endl << " The aerodynamic axis system has been set by default" - << " to the Lift/Side/Drag system." << endl; + } + } else if (axis != "ROLL" && axis != "PITCH" && axis != "YAW") { // error + cerr << endl << " An unknown axis type, " << axis << " has been specified" + << " in the aircraft configuration file." << endl; + exit(-1); } + axis_element = document->FindNextElement("axis"); + } + if (axisType == atNone) { + axisType = atLiftDrag; + cerr << endl << " The aerodynamic axis system has been set by default" + << " to the Lift/Side/Drag system." << endl; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGAerodynamics::GetCoefficientStrings(const string& delimeter) const { - string CoeffStrings = ""; - bool firstime = true; - unsigned int axis, sd; - - for (axis = 0; axis < 6; axis++) - { - for (sd = 0; sd < Coeff[axis].size(); sd++) - { - if (firstime) - { - firstime = false; - } - else - { - CoeffStrings += delimeter; - } - CoeffStrings += Coeff[axis][sd]->GetName(); - } + string CoeffStrings = ""; + bool firstime = true; + unsigned int axis, sd; + + for (axis = 0; axis < 6; axis++) { + for (sd = 0; sd < Coeff[axis].size(); sd++) { + if (firstime) { + firstime = false; + } else { + CoeffStrings += delimeter; + } + CoeffStrings += Coeff[axis][sd]->GetName(); } - return CoeffStrings; + } + return CoeffStrings; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGAerodynamics::GetCoefficientValues(const string& delimeter) const { - ostringstream buf; - - for (unsigned int axis = 0; axis < 6; axis++) - { - for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) - { - if (buf.tellp() > 0) buf << delimeter; - buf << setw(9) << Coeff[axis][sd]->GetValue(); - } + ostringstream buf; + + for (unsigned int axis = 0; axis < 6; axis++) { + for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) { + if (buf.tellp() > 0) buf << delimeter; + buf << setw(9) << Coeff[axis][sd]->GetValue(); } + } - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGAerodynamics::bind(void) { - typedef double (FGAerodynamics::*PMF)(int) const; - - PropertyManager->Tie("forces/fbx-aero-lbs", this,1, - (PMF)&FGAerodynamics::GetForces); - PropertyManager->Tie("forces/fby-aero-lbs", this,2, - (PMF)&FGAerodynamics::GetForces); - PropertyManager->Tie("forces/fbz-aero-lbs", this,3, - (PMF)&FGAerodynamics::GetForces); - PropertyManager->Tie("moments/l-aero-lbsft", this,1, - (PMF)&FGAerodynamics::GetMoments); - PropertyManager->Tie("moments/m-aero-lbsft", this,2, - (PMF)&FGAerodynamics::GetMoments); - PropertyManager->Tie("moments/n-aero-lbsft", this,3, - (PMF)&FGAerodynamics::GetMoments); - PropertyManager->Tie("forces/fwx-aero-lbs", this,1, - (PMF)&FGAerodynamics::GetvFw); - PropertyManager->Tie("forces/fwy-aero-lbs", this,2, - (PMF)&FGAerodynamics::GetvFw); - PropertyManager->Tie("forces/fwz-aero-lbs", this,3, - (PMF)&FGAerodynamics::GetvFw); - PropertyManager->Tie("forces/lod-norm", this, - &FGAerodynamics::GetLoD); - PropertyManager->Tie("aero/cl-squared", this, - &FGAerodynamics::GetClSquared); - PropertyManager->Tie("aero/qbar-area", &qbar_area); - PropertyManager->Tie("aero/alpha-max-rad", this, - &FGAerodynamics::GetAlphaCLMax, - &FGAerodynamics::SetAlphaCLMax, - true); - PropertyManager->Tie("aero/alpha-min-rad", this, - &FGAerodynamics::GetAlphaCLMin, - &FGAerodynamics::SetAlphaCLMin, - true); - PropertyManager->Tie("aero/bi2vel", this, - &FGAerodynamics::GetBI2Vel); - PropertyManager->Tie("aero/ci2vel", this, - &FGAerodynamics::GetCI2Vel); - PropertyManager->Tie("aero/alpha-wing-rad", this, - &FGAerodynamics::GetAlphaW); - PropertyManager->Tie("systems/stall-warn-norm", this, - &FGAerodynamics::GetStallWarn); - PropertyManager->Tie("aero/stall-hyst-norm", this, - &FGAerodynamics::GetHysteresisParm); + typedef double (FGAerodynamics::*PMF)(int) const; + + PropertyManager->Tie("forces/fbx-aero-lbs", this,1, + (PMF)&FGAerodynamics::GetForces); + PropertyManager->Tie("forces/fby-aero-lbs", this,2, + (PMF)&FGAerodynamics::GetForces); + PropertyManager->Tie("forces/fbz-aero-lbs", this,3, + (PMF)&FGAerodynamics::GetForces); + PropertyManager->Tie("moments/l-aero-lbsft", this,1, + (PMF)&FGAerodynamics::GetMoments); + PropertyManager->Tie("moments/m-aero-lbsft", this,2, + (PMF)&FGAerodynamics::GetMoments); + PropertyManager->Tie("moments/n-aero-lbsft", this,3, + (PMF)&FGAerodynamics::GetMoments); + PropertyManager->Tie("forces/fwx-aero-lbs", this,1, + (PMF)&FGAerodynamics::GetvFw); + PropertyManager->Tie("forces/fwy-aero-lbs", this,2, + (PMF)&FGAerodynamics::GetvFw); + PropertyManager->Tie("forces/fwz-aero-lbs", this,3, + (PMF)&FGAerodynamics::GetvFw); + PropertyManager->Tie("forces/lod-norm", this, + &FGAerodynamics::GetLoD); + PropertyManager->Tie("aero/cl-squared", this, + &FGAerodynamics::GetClSquared); + PropertyManager->Tie("aero/qbar-area", &qbar_area); + PropertyManager->Tie("aero/alpha-max-rad", this, + &FGAerodynamics::GetAlphaCLMax, + &FGAerodynamics::SetAlphaCLMax, + true); + PropertyManager->Tie("aero/alpha-min-rad", this, + &FGAerodynamics::GetAlphaCLMin, + &FGAerodynamics::SetAlphaCLMin, + true); + PropertyManager->Tie("aero/bi2vel", this, + &FGAerodynamics::GetBI2Vel); + PropertyManager->Tie("aero/ci2vel", this, + &FGAerodynamics::GetCI2Vel); + PropertyManager->Tie("aero/alpha-wing-rad", this, + &FGAerodynamics::GetAlphaW); + PropertyManager->Tie("systems/stall-warn-norm", this, + &FGAerodynamics::GetStallWarn); + PropertyManager->Tie("aero/stall-hyst-norm", this, + &FGAerodynamics::GetHysteresisParm); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -561,51 +516,42 @@ void FGAerodynamics::bind(void) void FGAerodynamics::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 2) // Loader - { - switch (axisType) - { - case (atLiftDrag): - cout << endl << " Aerodynamics (Lift|Side|Drag axes):" << endl << endl; - break; - case (atAxialNormal): - cout << endl << " Aerodynamics (Axial|Side|Normal axes):" << endl << endl; - break; - case (atBodyXYZ): - cout << endl << " Aerodynamics (X|Y|Z axes):" << endl << endl; - break; - case (atNone): - cout << endl << " Aerodynamics (undefined axes):" << endl << endl; - break; - } - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGAerodynamics" << endl; - if (from == 1) cout << "Destroyed: FGAerodynamics" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 2) { // Loader + switch (axisType) { + case (atLiftDrag): + cout << endl << " Aerodynamics (Lift|Side|Drag axes):" << endl << endl; + break; + case (atAxialNormal): + cout << endl << " Aerodynamics (Axial|Side|Normal axes):" << endl << endl; + break; + case (atBodyXYZ): + cout << endl << " Aerodynamics (X|Y|Z axes):" << endl << endl; + break; + case (atNone): + cout << endl << " Aerodynamics (undefined axes):" << endl << endl; + break; + } } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGAerodynamics" << endl; + if (from == 1) cout << "Destroyed: FGAerodynamics" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } // namespace JSBSim diff --git a/src/models/FGAerodynamics.h b/src/models/FGAerodynamics.h index bd4e4907f2602f33c8762d45e22dd2fb3343b068..0f966d8459b236f37d4abc46eb57ffca57f65de6 100644 --- a/src/models/FGAerodynamics.h +++ b/src/models/FGAerodynamics.h @@ -58,8 +58,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -81,11 +80,11 @@ CLASS DOCUMENTATION <min> {number} </min> <max> {number} </max> </hysteresis_limits> - <aero_ref_pt_shift_x> + <aero_ref_pt_shift_x> <function> {function contents} - </function> - </aero_ref_pt_shift_x> + </function> + </aero_ref_pt_shift_x> <function> {function contents} </function> @@ -121,175 +120,121 @@ class FGAerodynamics : public FGModel, public FGXMLFileRead { public: - /** Constructor - @param Executive a pointer to the parent executive object */ - FGAerodynamics(FGFDMExec* Executive); - /// Destructor - ~FGAerodynamics(); - - bool InitModel(void); - - /** Runs the Aerodynamics model; called by the Executive - @return false if no error */ - bool Run(void); - - /** Loads the Aerodynamics model. - The Load function for this class expects the XML parser to - have found the aerodynamics keyword in the configuration file. - @param element pointer to the current XML element for aerodynamics parameters. - @return true if successful */ - bool Load(Element* element); - - /** Gets the total aerodynamic force vector. - @return a force vector reference. */ - FGColumnVector3& GetForces(void) - { - return vForces; - } - - /** Gets the aerodynamic force for an axis. - @param n Axis index. This could be 0, 1, or 2, or one of the - axis enums: eX, eY, eZ. - @return the force acting on an axis */ - double GetForces(int n) const - { - return vForces(n); - } - - /** Gets the total aerodynamic moment vector. - @return a moment vector reference. */ - FGColumnVector3& GetMoments(void) - { - return vMoments; - } - - /** Gets the aerodynamic moment for an axis. - @return the moment about a single axis (as described also in the - similar call to GetForces(int n).*/ - double GetMoments(int n) const - { - return vMoments(n); - } - - /** Retrieves the aerodynamic forces in the wind axes. - @return a reference to a column vector containing the wind axis forces. */ - FGColumnVector3& GetvFw(void) - { - return vFw; - } - - /** Retrieves the aerodynamic forces in the wind axes, given an axis. - @param axis the axis to return the force for (eX, eY, eZ). - @return a reference to a column vector containing the requested wind - axis force. */ - double GetvFw(int axis) const - { - return vFw(axis); - } - - /** Retrieves the lift over drag ratio */ - inline double GetLoD(void) const - { - return lod; - } - - /** Retrieves the square of the lift coefficient. */ - inline double GetClSquared(void) const - { - return clsq; - } - inline double GetAlphaCLMax(void) const - { - return alphaclmax; - } - inline double GetAlphaCLMin(void) const - { - return alphaclmin; - } - - inline double GetHysteresisParm(void) const - { - return stall_hyst; - } - inline double GetStallWarn(void) const - { - return impending_stall; - } - double GetAlphaW(void) const - { - return alphaw; - } - - double GetBI2Vel(void) const - { - return bi2vel; - } - double GetCI2Vel(void) const - { - return ci2vel; - } - - inline void SetAlphaCLMax(double tt) - { - alphaclmax=tt; - } - inline void SetAlphaCLMin(double tt) - { - alphaclmin=tt; - } - - /** Gets the strings for the current set of coefficients. - @param delimeter either a tab or comma string depending on output type - @return a string containing the descriptive names for all coefficients */ - std::string GetCoefficientStrings(const std::string& delimeter) const; - - /** Gets the coefficient values. - @param delimeter either a tab or comma string depending on output type - @return a string containing the numeric values for the current set of - coefficients */ - std::string GetCoefficientValues(const std::string& delimeter) const; - - /** Calculates and returns the wind-to-body axis transformation matrix. - @return a reference to the wind-to-body transformation matrix. - */ - FGMatrix33& GetTw2b(void); - - /** Calculates and returns the body-to-wind axis transformation matrix. - @return a reference to the wind-to-body transformation matrix. - */ - FGMatrix33& GetTb2w(void); - - std::vector <FGFunction*> * GetCoeff(void) const - { - return Coeff; - } + /** Constructor + @param Executive a pointer to the parent executive object */ + FGAerodynamics(FGFDMExec* Executive); + /// Destructor + ~FGAerodynamics(); + + bool InitModel(void); + + /** Runs the Aerodynamics model; called by the Executive + @return false if no error */ + bool Run(void); + + /** Loads the Aerodynamics model. + The Load function for this class expects the XML parser to + have found the aerodynamics keyword in the configuration file. + @param element pointer to the current XML element for aerodynamics parameters. + @return true if successful */ + bool Load(Element* element); + + /** Gets the total aerodynamic force vector. + @return a force vector reference. */ + FGColumnVector3& GetForces(void) {return vForces;} + + /** Gets the aerodynamic force for an axis. + @param n Axis index. This could be 0, 1, or 2, or one of the + axis enums: eX, eY, eZ. + @return the force acting on an axis */ + double GetForces(int n) const {return vForces(n);} + + /** Gets the total aerodynamic moment vector. + @return a moment vector reference. */ + FGColumnVector3& GetMoments(void) {return vMoments;} + + /** Gets the aerodynamic moment for an axis. + @return the moment about a single axis (as described also in the + similar call to GetForces(int n).*/ + double GetMoments(int n) const {return vMoments(n);} + + /** Retrieves the aerodynamic forces in the wind axes. + @return a reference to a column vector containing the wind axis forces. */ + FGColumnVector3& GetvFw(void) { return vFw; } + + /** Retrieves the aerodynamic forces in the wind axes, given an axis. + @param axis the axis to return the force for (eX, eY, eZ). + @return a reference to a column vector containing the requested wind + axis force. */ + double GetvFw(int axis) const { return vFw(axis); } + + /** Retrieves the lift over drag ratio */ + inline double GetLoD(void) const { return lod; } + + /** Retrieves the square of the lift coefficient. */ + inline double GetClSquared(void) const { return clsq; } + inline double GetAlphaCLMax(void) const { return alphaclmax; } + inline double GetAlphaCLMin(void) const { return alphaclmin; } + + inline double GetHysteresisParm(void) const { return stall_hyst; } + inline double GetStallWarn(void) const { return impending_stall; } + double GetAlphaW(void) const { return alphaw; } + + double GetBI2Vel(void) const { return bi2vel; } + double GetCI2Vel(void) const { return ci2vel; } + + inline void SetAlphaCLMax(double tt) { alphaclmax=tt; } + inline void SetAlphaCLMin(double tt) { alphaclmin=tt; } + + /** Gets the strings for the current set of coefficients. + @param delimeter either a tab or comma string depending on output type + @return a string containing the descriptive names for all coefficients */ + std::string GetCoefficientStrings(const std::string& delimeter) const; + + /** Gets the coefficient values. + @param delimeter either a tab or comma string depending on output type + @return a string containing the numeric values for the current set of + coefficients */ + std::string GetCoefficientValues(const std::string& delimeter) const; + + /** Calculates and returns the wind-to-body axis transformation matrix. + @return a reference to the wind-to-body transformation matrix. + */ + FGMatrix33& GetTw2b(void); + + /** Calculates and returns the body-to-wind axis transformation matrix. + @return a reference to the wind-to-body transformation matrix. + */ + FGMatrix33& GetTb2w(void); + + std::vector <FGFunction*> * GetCoeff(void) const { return Coeff; } private: - enum eAxisType {atNone, atLiftDrag, atAxialNormal, atBodyXYZ} axisType; - typedef std::map<std::string,int> AxisIndex; - AxisIndex AxisIdx; - FGFunction* AeroRPShift; - typedef vector <FGFunction*> CoeffArray; - CoeffArray* Coeff; - FGColumnVector3 vFnative; - FGColumnVector3 vFw; - FGColumnVector3 vForces; - FGColumnVector3 vMoments; - FGColumnVector3 vDXYZcg; - FGColumnVector3 vDeltaRP; - FGMatrix33 mTw2b; - FGMatrix33 mTb2w; - double alphaclmax, alphaclmin; - double alphahystmax, alphahystmin; - double impending_stall, stall_hyst; - double bi2vel, ci2vel,alphaw; - double clsq, lod, qbar_area; - - typedef double (FGAerodynamics::*PMF)(int) const; - void DetermineAxisSystem(void); - void bind(void); - - void Debug(int from); + enum eAxisType {atNone, atLiftDrag, atAxialNormal, atBodyXYZ} axisType; + typedef std::map<std::string,int> AxisIndex; + AxisIndex AxisIdx; + FGFunction* AeroRPShift; + typedef vector <FGFunction*> CoeffArray; + CoeffArray* Coeff; + FGColumnVector3 vFnative; + FGColumnVector3 vFw; + FGColumnVector3 vForces; + FGColumnVector3 vMoments; + FGColumnVector3 vDXYZcg; + FGColumnVector3 vDeltaRP; + FGMatrix33 mTw2b; + FGMatrix33 mTb2w; + double alphaclmax, alphaclmin; + double alphahystmax, alphahystmin; + double impending_stall, stall_hyst; + double bi2vel, ci2vel,alphaw; + double clsq, lod, qbar_area; + + typedef double (FGAerodynamics::*PMF)(int) const; + void DetermineAxisSystem(void); + void bind(void); + + void Debug(int from); }; } // namespace JSBSim diff --git a/src/models/FGAircraft.cpp b/src/models/FGAircraft.cpp index 4753de7aa81658284f73d9ae8e3a80c5c312dcb8..0ed6ac74f33975f09d0dcdca72953d51d0e7ab09 100644 --- a/src/models/FGAircraft.cpp +++ b/src/models/FGAircraft.cpp @@ -58,8 +58,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS @@ -69,7 +68,7 @@ DEFINITIONS GLOBAL DATA %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -static const char *IdSrc = "$Id: FGAircraft.cpp,v 1.27 2010/07/27 23:18:19 jberndt Exp $"; +static const char *IdSrc = "$Id: FGAircraft.cpp,v 1.28 2010/09/07 00:40:03 jberndt Exp $"; static const char *IdHdr = ID_AIRCRAFT; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -78,184 +77,177 @@ CLASS IMPLEMENTATION FGAircraft::FGAircraft(FGFDMExec* fdmex) : FGModel(fdmex) { - Name = "FGAircraft"; - WingSpan = 0.0; - HTailArea = VTailArea = 0.0; - HTailArm = VTailArm = 0.0; - lbarh = lbarv = 0.0; - vbarh = vbarv = 0.0; - WingIncidence = 0.0; - HoldDown = 0; - - bind(); - - Debug(0); + Name = "FGAircraft"; + WingSpan = 0.0; + HTailArea = VTailArea = 0.0; + HTailArm = VTailArm = 0.0; + lbarh = lbarv = 0.0; + vbarh = vbarv = 0.0; + WingIncidence = 0.0; + HoldDown = 0; + + bind(); + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGAircraft::~FGAircraft() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGAircraft::InitModel(void) { - if (!FGModel::InitModel()) return false; + if (!FGModel::InitModel()) return false; - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGAircraft::Run(void) { - if (FGModel::Run()) return true; - if (FDMExec->Holding()) return false; - - RunPreFunctions(); - - vForces.InitMatrix(); - if (!HoldDown) - { - vForces += Aerodynamics->GetForces(); - vForces += Propulsion->GetForces(); - vForces += GroundReactions->GetForces(); - vForces += ExternalReactions->GetForces(); - vForces += BuoyantForces->GetForces(); - } - else - { - const FGMatrix33& mTl2b = Propagate->GetTl2b(); - vForces = mTl2b * FGColumnVector3(0,0,-MassBalance->GetWeight()); - } - - vMoments.InitMatrix(); - if (!HoldDown) - { - vMoments += Aerodynamics->GetMoments(); - vMoments += Propulsion->GetMoments(); - vMoments += GroundReactions->GetMoments(); - vMoments += ExternalReactions->GetMoments(); - vMoments += BuoyantForces->GetMoments(); - } - - vBodyAccel = vForces/MassBalance->GetMass(); - - vNcg = vBodyAccel/Inertial->SLgravity(); - - vNwcg = Aerodynamics->GetTb2w() * vNcg; - vNwcg(3) = 1.0 - vNwcg(3); - - RunPostFunctions(); - - return false; + if (FGModel::Run()) return true; + if (FDMExec->Holding()) return false; + + RunPreFunctions(); + + vForces.InitMatrix(); + if (!HoldDown) { + vForces += Aerodynamics->GetForces(); + vForces += Propulsion->GetForces(); + vForces += GroundReactions->GetForces(); + vForces += ExternalReactions->GetForces(); + vForces += BuoyantForces->GetForces(); + } else { + const FGMatrix33& mTl2b = Propagate->GetTl2b(); + vForces = mTl2b * FGColumnVector3(0,0,-MassBalance->GetWeight()); + } + + vMoments.InitMatrix(); + if (!HoldDown) { + vMoments += Aerodynamics->GetMoments(); + vMoments += Propulsion->GetMoments(); + vMoments += GroundReactions->GetMoments(); + vMoments += ExternalReactions->GetMoments(); + vMoments += BuoyantForces->GetMoments(); + } + + vBodyAccel = vForces/MassBalance->GetMass(); + + vNcg = vBodyAccel/Inertial->SLgravity(); + + vNwcg = Aerodynamics->GetTb2w() * vNcg; + vNwcg(3) = 1.0 - vNwcg(3); + + RunPostFunctions(); + + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGAircraft::GetNlf(void) const { - return -1*Aerodynamics->GetvFw(3)/MassBalance->GetWeight(); + return -1*Aerodynamics->GetvFw(3)/MassBalance->GetWeight(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGAircraft::Load(Element* el) { - string element_name; - Element* element; - - FGModel::Load(el); - - if (el->FindElement("wingarea")) - WingArea = el->FindElementValueAsNumberConvertTo("wingarea", "FT2"); - if (el->FindElement("wingspan")) - WingSpan = el->FindElementValueAsNumberConvertTo("wingspan", "FT"); - if (el->FindElement("chord")) - cbar = el->FindElementValueAsNumberConvertTo("chord", "FT"); - if (el->FindElement("wing_incidence")) - WingIncidence = el->FindElementValueAsNumberConvertTo("wing_incidence", "RAD"); - if (el->FindElement("htailarea")) - HTailArea = el->FindElementValueAsNumberConvertTo("htailarea", "FT2"); - if (el->FindElement("htailarm")) - HTailArm = el->FindElementValueAsNumberConvertTo("htailarm", "FT"); - if (el->FindElement("vtailarea")) - VTailArea = el->FindElementValueAsNumberConvertTo("vtailarea", "FT2"); - if (el->FindElement("vtailarm")) - VTailArm = el->FindElementValueAsNumberConvertTo("vtailarm", "FT"); - - // Find all LOCATION elements that descend from this METRICS branch of the - // config file. This would be CG location, eyepoint, etc. - - element = el->FindElement("location"); - while (element) - { - element_name = element->GetAttributeValue("name"); - - if (element_name == "AERORP") vXYZrp = element->FindElementTripletConvertTo("IN"); - else if (element_name == "EYEPOINT") vXYZep = element->FindElementTripletConvertTo("IN"); - else if (element_name == "VRP") vXYZvrp = element->FindElementTripletConvertTo("IN"); - - element = el->FindNextElement("location"); - } - - // calculate some derived parameters - if (cbar != 0.0) - { - lbarh = HTailArm/cbar; - lbarv = VTailArm/cbar; - if (WingArea != 0.0) - { - vbarh = HTailArm*HTailArea / (cbar*WingArea); - vbarv = VTailArm*VTailArea / (WingSpan*WingArea); - } + string element_name; + Element* element; + + FGModel::Load(el); + + if (el->FindElement("wingarea")) + WingArea = el->FindElementValueAsNumberConvertTo("wingarea", "FT2"); + if (el->FindElement("wingspan")) + WingSpan = el->FindElementValueAsNumberConvertTo("wingspan", "FT"); + if (el->FindElement("chord")) + cbar = el->FindElementValueAsNumberConvertTo("chord", "FT"); + if (el->FindElement("wing_incidence")) + WingIncidence = el->FindElementValueAsNumberConvertTo("wing_incidence", "RAD"); + if (el->FindElement("htailarea")) + HTailArea = el->FindElementValueAsNumberConvertTo("htailarea", "FT2"); + if (el->FindElement("htailarm")) + HTailArm = el->FindElementValueAsNumberConvertTo("htailarm", "FT"); + if (el->FindElement("vtailarea")) + VTailArea = el->FindElementValueAsNumberConvertTo("vtailarea", "FT2"); + if (el->FindElement("vtailarm")) + VTailArm = el->FindElementValueAsNumberConvertTo("vtailarm", "FT"); + + // Find all LOCATION elements that descend from this METRICS branch of the + // config file. This would be CG location, eyepoint, etc. + + element = el->FindElement("location"); + while (element) { + element_name = element->GetAttributeValue("name"); + + if (element_name == "AERORP") vXYZrp = element->FindElementTripletConvertTo("IN"); + else if (element_name == "EYEPOINT") vXYZep = element->FindElementTripletConvertTo("IN"); + else if (element_name == "VRP") vXYZvrp = element->FindElementTripletConvertTo("IN"); + + element = el->FindNextElement("location"); + } + + // calculate some derived parameters + if (cbar != 0.0) { + lbarh = HTailArm/cbar; + lbarv = VTailArm/cbar; + if (WingArea != 0.0) { + vbarh = HTailArm*HTailArea / (cbar*WingArea); + vbarv = VTailArm*VTailArea / (WingSpan*WingArea); } + } - FGModel::PostLoad(el); + PostLoad(el, PropertyManager); - Debug(2); + Debug(2); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGAircraft::bind(void) { - typedef double (FGAircraft::*PMF)(int) const; - PropertyManager->Tie("metrics/Sw-sqft", this, &FGAircraft::GetWingArea, &FGAircraft::SetWingArea); - PropertyManager->Tie("metrics/bw-ft", this, &FGAircraft::GetWingSpan); - PropertyManager->Tie("metrics/cbarw-ft", this, &FGAircraft::Getcbar); - PropertyManager->Tie("metrics/iw-rad", this, &FGAircraft::GetWingIncidence); - PropertyManager->Tie("metrics/iw-deg", this, &FGAircraft::GetWingIncidenceDeg); - PropertyManager->Tie("metrics/Sh-sqft", this, &FGAircraft::GetHTailArea); - PropertyManager->Tie("metrics/lh-ft", this, &FGAircraft::GetHTailArm); - PropertyManager->Tie("metrics/Sv-sqft", this, &FGAircraft::GetVTailArea); - PropertyManager->Tie("metrics/lv-ft", this, &FGAircraft::GetVTailArm); - PropertyManager->Tie("metrics/lh-norm", this, &FGAircraft::Getlbarh); - PropertyManager->Tie("metrics/lv-norm", this, &FGAircraft::Getlbarv); - PropertyManager->Tie("metrics/vbarh-norm", this, &FGAircraft::Getvbarh); - PropertyManager->Tie("metrics/vbarv-norm", this, &FGAircraft::Getvbarv); - PropertyManager->Tie("metrics/aero-rp-x-in", this, eX, (PMF)&FGAircraft::GetXYZrp); - PropertyManager->Tie("metrics/aero-rp-y-in", this, eY, (PMF)&FGAircraft::GetXYZrp); - PropertyManager->Tie("metrics/aero-rp-z-in", this, eZ, (PMF)&FGAircraft::GetXYZrp); - PropertyManager->Tie("metrics/eyepoint-x-in", this, eX, (PMF)&FGAircraft::GetXYZep); - PropertyManager->Tie("metrics/eyepoint-y-in", this, eY,(PMF)&FGAircraft::GetXYZep); - PropertyManager->Tie("metrics/eyepoint-z-in", this, eZ, (PMF)&FGAircraft::GetXYZep); - PropertyManager->Tie("metrics/visualrefpoint-x-in", this, eX, (PMF)&FGAircraft::GetXYZvrp); - PropertyManager->Tie("metrics/visualrefpoint-y-in", this, eY, (PMF)&FGAircraft::GetXYZvrp); - PropertyManager->Tie("metrics/visualrefpoint-z-in", this, eZ, (PMF)&FGAircraft::GetXYZvrp); - PropertyManager->Tie("forces/fbx-total-lbs", this, eX, (PMF)&FGAircraft::GetForces); - PropertyManager->Tie("forces/fby-total-lbs", this, eY, (PMF)&FGAircraft::GetForces); - PropertyManager->Tie("forces/fbz-total-lbs", this, eZ, (PMF)&FGAircraft::GetForces); - PropertyManager->Tie("forces/load-factor", this, &FGAircraft::GetNlf); - PropertyManager->Tie("forces/hold-down", this, &FGAircraft::GetHoldDown, &FGAircraft::SetHoldDown); - PropertyManager->Tie("moments/l-total-lbsft", this, eL, (PMF)&FGAircraft::GetMoments); - PropertyManager->Tie("moments/m-total-lbsft", this, eM, (PMF)&FGAircraft::GetMoments); - PropertyManager->Tie("moments/n-total-lbsft", this, eN, (PMF)&FGAircraft::GetMoments); + typedef double (FGAircraft::*PMF)(int) const; + PropertyManager->Tie("metrics/Sw-sqft", this, &FGAircraft::GetWingArea, &FGAircraft::SetWingArea); + PropertyManager->Tie("metrics/bw-ft", this, &FGAircraft::GetWingSpan); + PropertyManager->Tie("metrics/cbarw-ft", this, &FGAircraft::Getcbar); + PropertyManager->Tie("metrics/iw-rad", this, &FGAircraft::GetWingIncidence); + PropertyManager->Tie("metrics/iw-deg", this, &FGAircraft::GetWingIncidenceDeg); + PropertyManager->Tie("metrics/Sh-sqft", this, &FGAircraft::GetHTailArea); + PropertyManager->Tie("metrics/lh-ft", this, &FGAircraft::GetHTailArm); + PropertyManager->Tie("metrics/Sv-sqft", this, &FGAircraft::GetVTailArea); + PropertyManager->Tie("metrics/lv-ft", this, &FGAircraft::GetVTailArm); + PropertyManager->Tie("metrics/lh-norm", this, &FGAircraft::Getlbarh); + PropertyManager->Tie("metrics/lv-norm", this, &FGAircraft::Getlbarv); + PropertyManager->Tie("metrics/vbarh-norm", this, &FGAircraft::Getvbarh); + PropertyManager->Tie("metrics/vbarv-norm", this, &FGAircraft::Getvbarv); + PropertyManager->Tie("metrics/aero-rp-x-in", this, eX, (PMF)&FGAircraft::GetXYZrp); + PropertyManager->Tie("metrics/aero-rp-y-in", this, eY, (PMF)&FGAircraft::GetXYZrp); + PropertyManager->Tie("metrics/aero-rp-z-in", this, eZ, (PMF)&FGAircraft::GetXYZrp); + PropertyManager->Tie("metrics/eyepoint-x-in", this, eX, (PMF)&FGAircraft::GetXYZep); + PropertyManager->Tie("metrics/eyepoint-y-in", this, eY,(PMF)&FGAircraft::GetXYZep); + PropertyManager->Tie("metrics/eyepoint-z-in", this, eZ, (PMF)&FGAircraft::GetXYZep); + PropertyManager->Tie("metrics/visualrefpoint-x-in", this, eX, (PMF)&FGAircraft::GetXYZvrp); + PropertyManager->Tie("metrics/visualrefpoint-y-in", this, eY, (PMF)&FGAircraft::GetXYZvrp); + PropertyManager->Tie("metrics/visualrefpoint-z-in", this, eZ, (PMF)&FGAircraft::GetXYZvrp); + PropertyManager->Tie("forces/fbx-total-lbs", this, eX, (PMF)&FGAircraft::GetForces); + PropertyManager->Tie("forces/fby-total-lbs", this, eY, (PMF)&FGAircraft::GetForces); + PropertyManager->Tie("forces/fbz-total-lbs", this, eZ, (PMF)&FGAircraft::GetForces); + PropertyManager->Tie("forces/load-factor", this, &FGAircraft::GetNlf); + PropertyManager->Tie("forces/hold-down", this, &FGAircraft::GetHoldDown, &FGAircraft::SetHoldDown); + PropertyManager->Tie("moments/l-total-lbsft", this, eL, (PMF)&FGAircraft::GetMoments); + PropertyManager->Tie("moments/m-total-lbsft", this, eM, (PMF)&FGAircraft::GetMoments); + PropertyManager->Tie("moments/n-total-lbsft", this, eN, (PMF)&FGAircraft::GetMoments); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -279,48 +271,40 @@ void FGAircraft::bind(void) void FGAircraft::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 2) // Loading - { - cout << endl << " Aircraft Metrics:" << endl; - cout << " WingArea: " << WingArea << endl; - cout << " WingSpan: " << WingSpan << endl; - cout << " Incidence: " << WingIncidence << endl; - cout << " Chord: " << cbar << endl; - cout << " H. Tail Area: " << HTailArea << endl; - cout << " H. Tail Arm: " << HTailArm << endl; - cout << " V. Tail Area: " << VTailArea << endl; - cout << " V. Tail Arm: " << VTailArm << endl; - cout << " Eyepoint (x, y, z): " << vXYZep << endl; - cout << " Ref Pt (x, y, z): " << vXYZrp << endl; - cout << " Visual Ref Pt (x, y, z): " << vXYZvrp << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGAircraft" << endl; - if (from == 1) cout << "Destroyed: FGAircraft" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 2) { // Loading + cout << endl << " Aircraft Metrics:" << endl; + cout << " WingArea: " << WingArea << endl; + cout << " WingSpan: " << WingSpan << endl; + cout << " Incidence: " << WingIncidence << endl; + cout << " Chord: " << cbar << endl; + cout << " H. Tail Area: " << HTailArea << endl; + cout << " H. Tail Arm: " << HTailArm << endl; + cout << " V. Tail Area: " << VTailArea << endl; + cout << " V. Tail Arm: " << VTailArm << endl; + cout << " Eyepoint (x, y, z): " << vXYZep << endl; + cout << " Ref Pt (x, y, z): " << vXYZrp << endl; + cout << " Visual Ref Pt (x, y, z): " << vXYZvrp << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGAircraft" << endl; + if (from == 1) cout << "Destroyed: FGAircraft" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } // namespace JSBSim diff --git a/src/models/FGAircraft.h b/src/models/FGAircraft.h index 76e0469317a0a1b5f0503743ccf0f693de2ea039..a03656895c1db137e2e88b2f8eabf10bd3b1d4b9 100644 --- a/src/models/FGAircraft.h +++ b/src/models/FGAircraft.h @@ -55,8 +55,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -109,198 +108,95 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGAircraft : public FGModel -{ +class FGAircraft : public FGModel { public: - /** Constructor - @param Executive a pointer to the parent executive object */ - FGAircraft(FGFDMExec *Executive); - - /// Destructor - ~FGAircraft(); - - /** Runs the Aircraft model; called by the Executive - @see JSBSim.cpp documentation - @return false if no error */ - bool Run(void); - - bool InitModel(void); - - /** Loads the aircraft. - The executive calls this method to load the aircraft into JSBSim. - @param el a pointer to the element tree - @return true if successful */ - bool Load(Element* el); - - /** Gets the aircraft name - @return the name of the aircraft as a string type */ - const std::string& GetAircraftName(void) const - { - return AircraftName; - } - - /// Gets the wing area - double GetWingArea(void) const - { - return WingArea; - } - /// Gets the wing span - double GetWingSpan(void) const - { - return WingSpan; - } - /// Gets the average wing chord - double Getcbar(void) const - { - return cbar; - } - inline double GetWingIncidence(void) const - { - return WingIncidence; - } - inline double GetWingIncidenceDeg(void) const - { - return WingIncidence*radtodeg; - } - inline double GetHTailArea(void) const - { - return HTailArea; - } - inline double GetHTailArm(void) const - { - return HTailArm; - } - inline double GetVTailArea(void) const - { - return VTailArea; - } - inline double GetVTailArm(void) const - { - return VTailArm; - } - inline double Getlbarh(void) const - { - return lbarh; // HTailArm / cbar - } - inline double Getlbarv(void) const - { - return lbarv; // VTailArm / cbar - } - inline double Getvbarh(void) const - { - return vbarh; // H. Tail Volume - } - inline double Getvbarv(void) const - { - return vbarv; // V. Tail Volume - } - inline FGColumnVector3& GetMoments(void) - { - return vMoments; - } - inline double GetMoments(int idx) const - { - return vMoments(idx); - } - inline FGColumnVector3& GetForces(void) - { - return vForces; - } - inline double GetForces(int idx) const - { - return vForces(idx); - } - inline FGColumnVector3& GetBodyAccel(void) - { - return vBodyAccel; - } - inline double GetBodyAccel(int idx) - { - return vBodyAccel(idx); - } - inline FGColumnVector3& GetNcg (void) - { - return vNcg; - } - inline double GetNcg(int idx) - { - return vNcg(idx); - } - inline FGColumnVector3& GetXYZrp(void) - { - return vXYZrp; - } - inline FGColumnVector3& GetXYZvrp(void) - { - return vXYZvrp; - } - inline FGColumnVector3& GetXYZep(void) - { - return vXYZep; - } - inline double GetXYZrp(int idx) const - { - return vXYZrp(idx); - } - inline double GetXYZvrp(int idx) const - { - return vXYZvrp(idx); - } - inline double GetXYZep(int idx) const - { - return vXYZep(idx); - } - inline void SetAircraftName(const std::string& name) - { - AircraftName = name; - } - inline void SetHoldDown(int hd) - { - HoldDown = hd; - } - inline int GetHoldDown(void) const - { - return HoldDown; - } - - void SetXYZrp(int idx, double value) - { - vXYZrp(idx) = value; - } - - void SetWingArea(double S) - { - WingArea = S; - } - - double GetNlf(void) const; - - inline FGColumnVector3& GetNwcg(void) - { - return vNwcg; - } - - void bind(void); - void unbind(void); + /** Constructor + @param Executive a pointer to the parent executive object */ + FGAircraft(FGFDMExec *Executive); + + /// Destructor + ~FGAircraft(); + + /** Runs the Aircraft model; called by the Executive + @see JSBSim.cpp documentation + @return false if no error */ + bool Run(void); + + bool InitModel(void); + + /** Loads the aircraft. + The executive calls this method to load the aircraft into JSBSim. + @param el a pointer to the element tree + @return true if successful */ + bool Load(Element* el); + + /** Gets the aircraft name + @return the name of the aircraft as a string type */ + const std::string& GetAircraftName(void) const { return AircraftName; } + + /// Gets the wing area + double GetWingArea(void) const { return WingArea; } + /// Gets the wing span + double GetWingSpan(void) const { return WingSpan; } + /// Gets the average wing chord + double Getcbar(void) const { return cbar; } + inline double GetWingIncidence(void) const { return WingIncidence; } + inline double GetWingIncidenceDeg(void) const { return WingIncidence*radtodeg; } + inline double GetHTailArea(void) const { return HTailArea; } + inline double GetHTailArm(void) const { return HTailArm; } + inline double GetVTailArea(void) const { return VTailArea; } + inline double GetVTailArm(void) const { return VTailArm; } + inline double Getlbarh(void) const { return lbarh; } // HTailArm / cbar + inline double Getlbarv(void) const { return lbarv; } // VTailArm / cbar + inline double Getvbarh(void) const { return vbarh; } // H. Tail Volume + inline double Getvbarv(void) const { return vbarv; } // V. Tail Volume + inline FGColumnVector3& GetMoments(void) { return vMoments; } + inline double GetMoments(int idx) const { return vMoments(idx); } + inline FGColumnVector3& GetForces(void) { return vForces; } + inline double GetForces(int idx) const { return vForces(idx); } + inline FGColumnVector3& GetBodyAccel(void) { return vBodyAccel; } + inline double GetBodyAccel(int idx) { return vBodyAccel(idx); } + inline FGColumnVector3& GetNcg (void) { return vNcg; } + inline double GetNcg(int idx) { return vNcg(idx); } + inline FGColumnVector3& GetXYZrp(void) { return vXYZrp; } + inline FGColumnVector3& GetXYZvrp(void) { return vXYZvrp; } + inline FGColumnVector3& GetXYZep(void) { return vXYZep; } + inline double GetXYZrp(int idx) const { return vXYZrp(idx); } + inline double GetXYZvrp(int idx) const { return vXYZvrp(idx); } + inline double GetXYZep(int idx) const { return vXYZep(idx); } + inline void SetAircraftName(const std::string& name) {AircraftName = name;} + inline void SetHoldDown(int hd) {HoldDown = hd;} + inline int GetHoldDown(void) const {return HoldDown;} + + void SetXYZrp(int idx, double value) {vXYZrp(idx) = value;} + + void SetWingArea(double S) {WingArea = S;} + + double GetNlf(void) const; + + inline FGColumnVector3& GetNwcg(void) { return vNwcg; } + + void bind(void); + void unbind(void); private: - FGColumnVector3 vMoments; - FGColumnVector3 vForces; - FGColumnVector3 vXYZrp; - FGColumnVector3 vXYZvrp; - FGColumnVector3 vXYZep; - FGColumnVector3 vDXYZcg; - FGColumnVector3 vBodyAccel; - FGColumnVector3 vNcg; - FGColumnVector3 vNwcg; - - double WingArea, WingSpan, cbar, WingIncidence; - double HTailArea, VTailArea, HTailArm, VTailArm; - double lbarh,lbarv,vbarh,vbarv; - int HoldDown; - std::string AircraftName; - - void Debug(int from); + FGColumnVector3 vMoments; + FGColumnVector3 vForces; + FGColumnVector3 vXYZrp; + FGColumnVector3 vXYZvrp; + FGColumnVector3 vXYZep; + FGColumnVector3 vDXYZcg; + FGColumnVector3 vBodyAccel; + FGColumnVector3 vNcg; + FGColumnVector3 vNwcg; + + double WingArea, WingSpan, cbar, WingIncidence; + double HTailArea, VTailArea, HTailArm, VTailArm; + double lbarh,lbarv,vbarh,vbarv; + int HoldDown; + std::string AircraftName; + + void Debug(int from); }; } // namespace JSBSim diff --git a/src/models/FGAtmosphere.cpp b/src/models/FGAtmosphere.cpp index cdf850af2e57e7dad3b1d292e94dbba0d7c6fe63..12fb084a70f879c384bcf25f3962d8d0f4f37a9f 100644 --- a/src/models/FGAtmosphere.cpp +++ b/src/models/FGAtmosphere.cpp @@ -59,10 +59,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.35 2010/08/11 11:51:33 jberndt Exp $"; +static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.38 2010/09/16 11:01:24 jberndt Exp $"; static const char *IdHdr = ID_ATMOSPHERE; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -71,94 +70,107 @@ CLASS IMPLEMENTATION FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex) { - Name = "FGAtmosphere"; - lastIndex = 0; - h = 0.0; - psiw = 0.0; - htab[0]=0; - htab[1]= 36089.0; - htab[2]= 65617.0; - htab[3]=104987.0; - htab[4]=154199.0; - htab[5]=167322.0; - htab[6]=232940.0; - htab[7]=278385.0; //ft. - - MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0; + Name = "FGAtmosphere"; + lastIndex = 0; + h = 0.0; + psiw = 0.0; + htab[0]=0; + htab[1]= 36089.0; + htab[2]= 65617.0; + htab[3]=104987.0; + htab[4]=154199.0; + htab[5]=167322.0; + htab[6]=232940.0; + htab[7]=278385.0; //ft. + + MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0; // SetTurbType( ttCulp ); - SetTurbType( ttNone ); - TurbGain = 1.0; - TurbRate = 10.0; - Rhythmicity = 0.1; - spike = target_time = strength = 0.0; - wind_from_clockwise = 0.0; - SutherlandConstant = 198.72; // deg Rankine - Beta = 2.269690E-08; // slug/(sec ft R^0.5) - - T_dev_sl = T_dev = delta_T = 0.0; - StandardTempOnly = false; - first_pass = true; - vGustNED.InitMatrix(); - vTurbulenceNED.InitMatrix(); - - bind(); - Debug(0); + SetTurbType( ttNone ); + TurbGain = 1.0; + TurbRate = 10.0; + Rhythmicity = 0.1; + spike = target_time = strength = 0.0; + wind_from_clockwise = 0.0; + SutherlandConstant = 198.72; // deg Rankine + Beta = 2.269690E-08; // slug/(sec ft R^0.5) + + T_dev_sl = T_dev = delta_T = 0.0; + StandardTempOnly = false; + first_pass = true; + vGustNED.InitMatrix(); + vTurbulenceNED.InitMatrix(); + + // Milspec turbulence model + windspeed_at_20ft = 0.; + probability_of_exceedence_index = 0; + POE_Table = new FGTable(7,12); + // this is Figure 7 from p. 49 of MIL-F-8785C + // rows: probability of exceedance curve index, cols: altitude in ft + *POE_Table + << 500.0 << 1750.0 << 3750.0 << 7500.0 << 15000.0 << 25000.0 << 35000.0 << 45000.0 << 55000.0 << 65000.0 << 75000.0 << 80000.0 + << 1 << 3.2 << 2.2 << 1.5 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 + << 2 << 4.2 << 3.6 << 3.3 << 1.6 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 + << 3 << 6.6 << 6.9 << 7.4 << 6.7 << 4.6 << 2.7 << 0.4 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 + << 4 << 8.6 << 9.6 << 10.6 << 10.1 << 8.0 << 6.6 << 5.0 << 4.2 << 2.7 << 0.0 << 0.0 << 0.0 + << 5 << 11.8 << 13.0 << 16.0 << 15.1 << 11.6 << 9.7 << 8.1 << 8.2 << 7.9 << 4.9 << 3.2 << 2.1 + << 6 << 15.6 << 17.6 << 23.0 << 23.6 << 22.1 << 20.0 << 16.0 << 15.1 << 12.1 << 7.9 << 6.2 << 5.1 + << 7 << 18.7 << 21.5 << 28.4 << 30.2 << 30.7 << 31.0 << 25.2 << 23.1 << 17.5 << 10.7 << 8.4 << 7.2; + + bind(); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGAtmosphere::~FGAtmosphere() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGAtmosphere::InitModel(void) { - if (!FGModel::InitModel()) return false; + if (!FGModel::InitModel()) return false; - UseInternal(); // this is the default + UseInternal(); // this is the default - Calculate(h); - StdSLtemperature = SLtemperature = 518.67; - StdSLpressure = SLpressure = 2116.22; - StdSLdensity = SLdensity = 0.00237767; - StdSLsoundspeed = SLsoundspeed = sqrt(SHRatio*Reng*StdSLtemperature); - rSLtemperature = 1.0/StdSLtemperature; - rSLpressure = 1.0/StdSLpressure; - rSLdensity = 1.0/StdSLdensity; - rSLsoundspeed = 1.0/StdSLsoundspeed; - - return true; + Calculate(h); + StdSLtemperature = SLtemperature = 518.67; + StdSLpressure = SLpressure = 2116.22; + StdSLdensity = SLdensity = 0.00237767; + StdSLsoundspeed = SLsoundspeed = sqrt(SHRatio*Reng*StdSLtemperature); + rSLtemperature = 1.0/StdSLtemperature; + rSLpressure = 1.0/StdSLpressure; + rSLdensity = 1.0/StdSLdensity; + rSLsoundspeed = 1.0/StdSLsoundspeed; + + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGAtmosphere::Run(void) { - if (FGModel::Run()) return true; - if (FDMExec->Holding()) return false; + if (FGModel::Run()) return true; + if (FDMExec->Holding()) return false; - RunPreFunctions(); + RunPreFunctions(); - T_dev = 0.0; - h = Propagate->GetAltitudeASL(); + T_dev = 0.0; + h = Propagate->GetAltitudeASL(); - if (!useExternal) - { - Calculate(h); - CalculateDerived(); - } - else - { - CalculateDerived(); - } + if (!useExternal) { + Calculate(h); + CalculateDerived(); + } else { + CalculateDerived(); + } - RunPostFunctions(); + RunPostFunctions(); - Debug(2); - return false; + Debug(2); + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -167,129 +179,111 @@ bool FGAtmosphere::Run(void) void FGAtmosphere::Calculate(double altitude) { - double slope, reftemp, refpress; - int i = lastIndex; - - if (altitude < htab[lastIndex]) - { - if (altitude <= 0) - { - i = 0; - altitude=0; - } - else - { - i = lastIndex-1; - while (htab[i] > altitude) i--; - } - } - else if (altitude > htab[lastIndex+1]) - { - if (altitude >= htab[7]) - { - i = 7; - altitude = htab[7]; - } - else - { - i = lastIndex+1; - while (htab[i+1] < altitude) i++; - } - } - - switch (i) - { - case 0: // Sea level - slope = -0.00356616; // R/ft. - reftemp = 518.67; // in degrees Rankine, 288.15 Kelvin - refpress = 2116.22; // psf - //refdens = 0.00237767; // slugs/cubic ft. - break; - case 1: // 36089 ft. or 11 km - slope = 0; - reftemp = 389.97; // in degrees Rankine, 216.65 Kelvin - refpress = 472.763; - //refdens = 0.000706032; - break; - case 2: // 65616 ft. or 20 km - slope = 0.00054864; - reftemp = 389.97; // in degrees Rankine, 216.65 Kelvin - refpress = 114.636; - //refdens = 0.000171306; - break; - case 3: // 104986 ft. or 32 km - slope = 0.001536192; - reftemp = 411.57; // in degrees Rankine, 228.65 Kelvin - refpress = 18.128; - //refdens = 1.18422e-05; - break; - case 4: // 154199 ft. 47 km - slope = 0; - reftemp = 487.17; // in degrees Rankine, 270.65 Kelvin - refpress = 2.316; - //refdens = 4.00585e-7; - break; - case 5: // 167322 ft. or 51 km - slope = -0.001536192; - reftemp = 487.17; // in degrees Rankine, 270.65 Kelvin - refpress = 1.398; - //refdens = 8.17102e-7; - break; - case 6: // 232940 ft. or 71 km - slope = -0.00109728; - reftemp = 386.368; // in degrees Rankine, 214.649 Kelvin - refpress = 0.0826; - //refdens = 8.77702e-9; - break; - case 7: // 278385 ft. or 84.8520 km - slope = 0; - reftemp = 336.5; // in degrees Rankine, 186.94 Kelvin - refpress = 0.00831; - //refdens = 2.19541e-10; - break; - default: // sea level - slope = -0.00356616; // R/ft. - reftemp = 518.67; // in degrees Rankine, 288.15 Kelvin - refpress = 2116.22; // psf - //refdens = 0.00237767; // slugs/cubic ft. - break; - - } - - // If delta_T is set, then that is our temperature deviation at any altitude. - // If not, then we'll estimate a deviation based on the sea level deviation (if set). - - if (!StandardTempOnly) - { - T_dev = 0.0; - if (delta_T != 0.0) - { - T_dev = delta_T; - } - else - { - if ((altitude < 36089.239) && (T_dev_sl != 0.0)) - { - T_dev = T_dev_sl * ( 1.0 - (altitude/36089.239)); - } - } - reftemp+=T_dev; + double slope, reftemp, refpress; + int i = lastIndex; + + if (altitude < htab[lastIndex]) { + if (altitude <= 0) { + i = 0; + altitude=0; + } else { + i = lastIndex-1; + while (htab[i] > altitude) i--; } - - if (slope == 0) - { - intTemperature = reftemp; - intPressure = refpress*exp(-Inertial->SLgravity()/(reftemp*Reng)*(altitude-htab[i])); - intDensity = intPressure/(Reng*intTemperature); + } else if (altitude > htab[lastIndex+1]) { + if (altitude >= htab[7]) { + i = 7; + altitude = htab[7]; + } else { + i = lastIndex+1; + while (htab[i+1] < altitude) i++; } - else - { - intTemperature = reftemp+slope*(altitude-htab[i]); - intPressure = refpress*pow(intTemperature/reftemp,-Inertial->SLgravity()/(slope*Reng)); - intDensity = intPressure/(Reng*intTemperature); + } + + switch(i) { + case 0: // Sea level + slope = -0.00356616; // R/ft. + reftemp = 518.67; // in degrees Rankine, 288.15 Kelvin + refpress = 2116.22; // psf + //refdens = 0.00237767; // slugs/cubic ft. + break; + case 1: // 36089 ft. or 11 km + slope = 0; + reftemp = 389.97; // in degrees Rankine, 216.65 Kelvin + refpress = 472.763; + //refdens = 0.000706032; + break; + case 2: // 65616 ft. or 20 km + slope = 0.00054864; + reftemp = 389.97; // in degrees Rankine, 216.65 Kelvin + refpress = 114.636; + //refdens = 0.000171306; + break; + case 3: // 104986 ft. or 32 km + slope = 0.001536192; + reftemp = 411.57; // in degrees Rankine, 228.65 Kelvin + refpress = 18.128; + //refdens = 1.18422e-05; + break; + case 4: // 154199 ft. 47 km + slope = 0; + reftemp = 487.17; // in degrees Rankine, 270.65 Kelvin + refpress = 2.316; + //refdens = 4.00585e-7; + break; + case 5: // 167322 ft. or 51 km + slope = -0.001536192; + reftemp = 487.17; // in degrees Rankine, 270.65 Kelvin + refpress = 1.398; + //refdens = 8.17102e-7; + break; + case 6: // 232940 ft. or 71 km + slope = -0.00109728; + reftemp = 386.368; // in degrees Rankine, 214.649 Kelvin + refpress = 0.0826; + //refdens = 8.77702e-9; + break; + case 7: // 278385 ft. or 84.8520 km + slope = 0; + reftemp = 336.5; // in degrees Rankine, 186.94 Kelvin + refpress = 0.00831; + //refdens = 2.19541e-10; + break; + default: // sea level + slope = -0.00356616; // R/ft. + reftemp = 518.67; // in degrees Rankine, 288.15 Kelvin + refpress = 2116.22; // psf + //refdens = 0.00237767; // slugs/cubic ft. + break; + + } + + // If delta_T is set, then that is our temperature deviation at any altitude. + // If not, then we'll estimate a deviation based on the sea level deviation (if set). + + if(!StandardTempOnly) { + T_dev = 0.0; + if (delta_T != 0.0) { + T_dev = delta_T; + } else { + if ((altitude < 36089.239) && (T_dev_sl != 0.0)) { + T_dev = T_dev_sl * ( 1.0 - (altitude/36089.239)); + } } - - lastIndex=i; + reftemp+=T_dev; + } + + if (slope == 0) { + intTemperature = reftemp; + intPressure = refpress*exp(-Inertial->SLgravity()/(reftemp*Reng)*(altitude-htab[i])); + intDensity = intPressure/(Reng*intTemperature); + } else { + intTemperature = reftemp+slope*(altitude-htab[i]); + intPressure = refpress*pow(intTemperature/reftemp,-Inertial->SLgravity()/(slope*Reng)); + intDensity = intPressure/(Reng*intTemperature); + } + + lastIndex=i; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -298,67 +292,63 @@ void FGAtmosphere::Calculate(double altitude) void FGAtmosphere::CalculateDerived(void) { - T_dev = (*temperature) - GetTemperature(h); + T_dev = (*temperature) - GetTemperature(h); - if (T_dev == 0.0) density_altitude = h; - else density_altitude = 518.4/0.00357 * (1.0 - pow(GetDensityRatio(),0.235)); + if (T_dev == 0.0) density_altitude = h; + else density_altitude = 518.67/0.00356616 * (1.0 - pow(GetDensityRatio(),0.235)); - if (turbType != ttNone) Turbulence(); + if (turbType != ttNone) Turbulence(); - vTotalWindNED = vWindNED + vGustNED + vTurbulenceNED; + vTotalWindNED = vWindNED + vGustNED + vTurbulenceNED; - // psiw (Wind heading) is the direction the wind is blowing towards - if (vWindNED(eX) != 0.0) psiw = atan2( vWindNED(eY), vWindNED(eX) ); - if (psiw < 0) psiw += 2*M_PI; + // psiw (Wind heading) is the direction the wind is blowing towards + if (vWindNED(eX) != 0.0) psiw = atan2( vWindNED(eY), vWindNED(eX) ); + if (psiw < 0) psiw += 2*M_PI; - soundspeed = sqrt(SHRatio*Reng*(*temperature)); + soundspeed = sqrt(SHRatio*Reng*(*temperature)); - intViscosity = Beta * pow(intTemperature, 1.5) / (SutherlandConstant + intTemperature); - intKinematicViscosity = intViscosity / intDensity; + intViscosity = Beta * pow(intTemperature, 1.5) / (SutherlandConstant + intTemperature); + intKinematicViscosity = intViscosity / intDensity; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Get the standard atmospheric properties at a specified altitude -void FGAtmosphere::GetStdAtmosphere(double altitude) -{ - StandardTempOnly = true; - Calculate(altitude); - StandardTempOnly = false; - atmosphere.Temperature = intTemperature; - atmosphere.Pressure = intPressure; - atmosphere.Density = intDensity; - - // Reset the internal atmospheric state - Calculate(h); +void FGAtmosphere::GetStdAtmosphere(double altitude) { + StandardTempOnly = true; + Calculate(altitude); + StandardTempOnly = false; + atmosphere.Temperature = intTemperature; + atmosphere.Pressure = intPressure; + atmosphere.Density = intDensity; + + // Reset the internal atmospheric state + Calculate(h); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Get the standard pressure at a specified altitude -double FGAtmosphere::GetPressure(double altitude) -{ - GetStdAtmosphere(altitude); - return atmosphere.Pressure; +double FGAtmosphere::GetPressure(double altitude) { + GetStdAtmosphere(altitude); + return atmosphere.Pressure; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Get the standard temperature at a specified altitude -double FGAtmosphere::GetTemperature(double altitude) -{ - GetStdAtmosphere(altitude); - return atmosphere.Temperature; +double FGAtmosphere::GetTemperature(double altitude) { + GetStdAtmosphere(altitude); + return atmosphere.Temperature; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Get the standard density at a specified altitude -double FGAtmosphere::GetDensity(double altitude) -{ - GetStdAtmosphere(altitude); - return atmosphere.Density; +double FGAtmosphere::GetDensity(double altitude) { + GetStdAtmosphere(altitude); + return atmosphere.Density; } @@ -373,30 +363,30 @@ static inline double square_signed (double value) return value * value; } +/// simply square a value +static inline double sqr(double x) { return x*x; } + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // // psi is the angle that the wind is blowing *towards* void FGAtmosphere::SetWindspeed(double speed) { - if (vWindNED.Magnitude() == 0.0) - { - psiw = 0.0; - vWindNED(eNorth) = speed; - } - else - { - vWindNED(eNorth) = speed * cos(psiw); - vWindNED(eEast) = speed * sin(psiw); - vWindNED(eDown) = 0.0; - } + if (vWindNED.Magnitude() == 0.0) { + psiw = 0.0; + vWindNED(eNorth) = speed; + } else { + vWindNED(eNorth) = speed * cos(psiw); + vWindNED(eEast) = speed * sin(psiw); + vWindNED(eDown) = 0.0; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGAtmosphere::GetWindspeed(void) const { - return vWindNED.Magnitude(); + return vWindNED.Magnitude(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -405,273 +395,400 @@ double FGAtmosphere::GetWindspeed(void) const void FGAtmosphere::SetWindPsi(double dir) { - double mag = GetWindspeed(); - psiw = dir; - SetWindspeed(mag); + double mag = GetWindspeed(); + psiw = dir; + SetWindspeed(mag); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGAtmosphere::Turbulence(void) { - double DeltaT = rate*FDMExec->GetDeltaT(); - - switch (turbType) - { - case ttStandard: - { - // TurbGain = TurbGain * TurbGain * 100.0; // what is this!? - - vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX)); - vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX)); - vDirectiondAccelDt(eZ) = 1 - 2.0*(double(rand())/double(RAND_MAX)); - - MagnitudedAccelDt = 1 - 2.0*(double(rand())/double(RAND_MAX)) - Magnitude; - // Scale the magnitude so that it moves - // away from the peaks - MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) / - (1 + fabs(Magnitude))); - MagnitudeAccel += MagnitudedAccelDt*TurbRate*DeltaT; - Magnitude += MagnitudeAccel*DeltaT; - Magnitude = fabs(Magnitude); - - vDirectiondAccelDt.Normalize(); - - // deemphasise non-vertical forces - vDirectiondAccelDt(eX) = square_signed(vDirectiondAccelDt(eX)); - vDirectiondAccelDt(eY) = square_signed(vDirectiondAccelDt(eY)); - - vDirectionAccel += vDirectiondAccelDt*TurbRate*DeltaT; - vDirectionAccel.Normalize(); - vDirection += vDirectionAccel*DeltaT; - - vDirection.Normalize(); - - // Diminish turbulence within three wingspans - // of the ground - vTurbulenceNED = TurbGain * Magnitude * vDirection; - double HOverBMAC = Auxiliary->GetHOverBMAC(); - if (HOverBMAC < 3.0) - vTurbulenceNED *= (HOverBMAC / 3.0) * (HOverBMAC / 3.0); - - // I don't believe these next two statements calculate the proper gradient over - // the aircraft body. One reason is because this has no relationship with the - // orientation or velocity of the aircraft, which it must have. What is vTurbulenceGrad - // supposed to represent? And the direction and magnitude of the turbulence can change, - // so both accelerations need to be accounted for, no? - - // Need to determine the turbulence change in body axes between two time points. - - vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection; - vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad; - - if (Aircraft->GetWingSpan() > 0) - { - vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan(); - } - else - { - vTurbPQR(eP) = vBodyTurbGrad(eY)/30.0; - } + double DeltaT = rate*FDMExec->GetDeltaT(); + + switch (turbType) { + case ttStandard: { + // TurbGain = TurbGain * TurbGain * 100.0; // what is this!? + + vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX)); + vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX)); + vDirectiondAccelDt(eZ) = 1 - 2.0*(double(rand())/double(RAND_MAX)); + + MagnitudedAccelDt = 1 - 2.0*(double(rand())/double(RAND_MAX)) - Magnitude; + // Scale the magnitude so that it moves + // away from the peaks + MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) / + (1 + fabs(Magnitude))); + MagnitudeAccel += MagnitudedAccelDt*TurbRate*DeltaT; + Magnitude += MagnitudeAccel*DeltaT; + Magnitude = fabs(Magnitude); + + vDirectiondAccelDt.Normalize(); + + // deemphasise non-vertical forces + vDirectiondAccelDt(eX) = square_signed(vDirectiondAccelDt(eX)); + vDirectiondAccelDt(eY) = square_signed(vDirectiondAccelDt(eY)); + + vDirectionAccel += vDirectiondAccelDt*TurbRate*DeltaT; + vDirectionAccel.Normalize(); + vDirection += vDirectionAccel*DeltaT; + + vDirection.Normalize(); + + // Diminish turbulence within three wingspans + // of the ground + vTurbulenceNED = TurbGain * Magnitude * vDirection; + double HOverBMAC = Auxiliary->GetHOverBMAC(); + if (HOverBMAC < 3.0) + vTurbulenceNED *= (HOverBMAC / 3.0) * (HOverBMAC / 3.0); + + // I don't believe these next two statements calculate the proper gradient over + // the aircraft body. One reason is because this has no relationship with the + // orientation or velocity of the aircraft, which it must have. What is vTurbulenceGrad + // supposed to represent? And the direction and magnitude of the turbulence can change, + // so both accelerations need to be accounted for, no? + + // Need to determine the turbulence change in body axes between two time points. + + vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection; + vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad; + + if (Aircraft->GetWingSpan() > 0) { + vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan(); + } else { + vTurbPQR(eP) = vBodyTurbGrad(eY)/30.0; + } // if (Aircraft->GetHTailArm() != 0.0) // vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm(); // else // vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0; - if (Aircraft->GetVTailArm() > 0) - vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm(); - else - vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0; + if (Aircraft->GetVTailArm() > 0) + vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm(); + else + vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0; - // Clear the horizontal forces - // actually felt by the plane, now - // that we've used them to calculate - // moments. - // Why? (JSB) + // Clear the horizontal forces + // actually felt by the plane, now + // that we've used them to calculate + // moments. + // Why? (JSB) // vTurbulenceNED(eX) = 0.0; // vTurbulenceNED(eY) = 0.0; - break; + break; + } + case ttBerndt: { // This is very experimental and incomplete at the moment. + + vDirectiondAccelDt(eX) = GaussianRandomNumber(); + vDirectiondAccelDt(eY) = GaussianRandomNumber(); + vDirectiondAccelDt(eZ) = GaussianRandomNumber(); +/* + MagnitudedAccelDt = GaussianRandomNumber(); + MagnitudeAccel += MagnitudedAccelDt * DeltaT; + Magnitude += MagnitudeAccel * DeltaT; +*/ + Magnitude += GaussianRandomNumber() * DeltaT; + + vDirectiondAccelDt.Normalize(); + vDirectionAccel += TurbRate * vDirectiondAccelDt * DeltaT; + vDirectionAccel.Normalize(); + vDirection += vDirectionAccel*DeltaT; + + // Diminish z-vector within two wingspans of the ground + double HOverBMAC = Auxiliary->GetHOverBMAC(); + if (HOverBMAC < 2.0) vDirection(eZ) *= HOverBMAC / 2.0; + + vDirection.Normalize(); + + vTurbulenceNED = TurbGain*Magnitude * vDirection; + vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection; + + vBodyTurbGrad = Propagate->GetTl2b() * vTurbulenceGrad; + vTurbPQR(eP) = vBodyTurbGrad(eY) / Aircraft->GetWingSpan(); + if (Aircraft->GetHTailArm() > 0) + vTurbPQR(eQ) = vBodyTurbGrad(eZ) / Aircraft->GetHTailArm(); + else + vTurbPQR(eQ) = vBodyTurbGrad(eZ) / 10.0; + + if (Aircraft->GetVTailArm() > 0) + vTurbPQR(eR) = vBodyTurbGrad(eX) / Aircraft->GetVTailArm(); + else + vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0; + + break; + } + case ttCulp: { + + vTurbPQR(eP) = wind_from_clockwise; + if (TurbGain == 0.0) return; + + // keep the inputs within allowable limts for this model + if (TurbGain < 0.0) TurbGain = 0.0; + if (TurbGain > 1.0) TurbGain = 1.0; + if (TurbRate < 0.0) TurbRate = 0.0; + if (TurbRate > 30.0) TurbRate = 30.0; + if (Rhythmicity < 0.0) Rhythmicity = 0.0; + if (Rhythmicity > 1.0) Rhythmicity = 1.0; + + // generate a sine wave corresponding to turbulence rate in hertz + double time = FDMExec->GetSimTime(); + double sinewave = sin( time * TurbRate * 6.283185307 ); + + double random = 0.0; + if (target_time == 0.0) { + strength = random = 1 - 2.0*(double(rand())/double(RAND_MAX)); + target_time = time + 0.71 + (random * 0.5); } - case ttBerndt: // This is very experimental and incomplete at the moment. - { - - vDirectiondAccelDt(eX) = GaussianRandomNumber(); - vDirectiondAccelDt(eY) = GaussianRandomNumber(); - vDirectiondAccelDt(eZ) = GaussianRandomNumber(); - /* - MagnitudedAccelDt = GaussianRandomNumber(); - MagnitudeAccel += MagnitudedAccelDt * DeltaT; - Magnitude += MagnitudeAccel * DeltaT; - */ - Magnitude += GaussianRandomNumber() * DeltaT; - - vDirectiondAccelDt.Normalize(); - vDirectionAccel += TurbRate * vDirectiondAccelDt * DeltaT; - vDirectionAccel.Normalize(); - vDirection += vDirectionAccel*DeltaT; - - // Diminish z-vector within two wingspans of the ground - double HOverBMAC = Auxiliary->GetHOverBMAC(); - if (HOverBMAC < 2.0) vDirection(eZ) *= HOverBMAC / 2.0; - - vDirection.Normalize(); - - vTurbulenceNED = TurbGain*Magnitude * vDirection; - vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection; - - vBodyTurbGrad = Propagate->GetTl2b() * vTurbulenceGrad; - vTurbPQR(eP) = vBodyTurbGrad(eY) / Aircraft->GetWingSpan(); - if (Aircraft->GetHTailArm() > 0) - vTurbPQR(eQ) = vBodyTurbGrad(eZ) / Aircraft->GetHTailArm(); - else - vTurbPQR(eQ) = vBodyTurbGrad(eZ) / 10.0; - - if (Aircraft->GetVTailArm() > 0) - vTurbPQR(eR) = vBodyTurbGrad(eX) / Aircraft->GetVTailArm(); - else - vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0; - - break; + if (time > target_time) { + spike = 1.0; + target_time = 0.0; + } + + // max vertical wind speed in fps, corresponds to TurbGain = 1.0 + double max_vs = 40; + + vTurbulenceNED(1) = vTurbulenceNED(2) = vTurbulenceNED(3) = 0.0; + double delta = strength * max_vs * TurbGain * (1-Rhythmicity) * spike; + + // Vertical component of turbulence. + vTurbulenceNED(3) = sinewave * max_vs * TurbGain * Rhythmicity; + vTurbulenceNED(3)+= delta; + double HOverBMAC = Auxiliary->GetHOverBMAC(); + if (HOverBMAC < 3.0) + vTurbulenceNED(3) *= HOverBMAC * 0.3333; + + // Yaw component of turbulence. + vTurbulenceNED(1) = sin( delta * 3.0 ); + vTurbulenceNED(2) = cos( delta * 3.0 ); + + // Roll component of turbulence. Clockwise vortex causes left roll. + vTurbPQR(eP) += delta * 0.04; + + spike = spike * 0.9; + break; + } + case ttMilspec: + case ttTustin: { + // an index of zero means turbulence is disabled + if (probability_of_exceedence_index == 0) { + vTurbulenceNED(1) = vTurbulenceNED(2) = vTurbulenceNED(3) = 0.0; + vTurbPQR(1) = vTurbPQR(2) = vTurbPQR(3) = 0.0; + return; } - case ttCulp: - { - - vTurbPQR(eP) = wind_from_clockwise; - if (TurbGain == 0.0) return; - - // keep the inputs within allowable limts for this model - if (TurbGain < 0.0) TurbGain = 0.0; - if (TurbGain > 1.0) TurbGain = 1.0; - if (TurbRate < 0.0) TurbRate = 0.0; - if (TurbRate > 30.0) TurbRate = 30.0; - if (Rhythmicity < 0.0) Rhythmicity = 0.0; - if (Rhythmicity > 1.0) Rhythmicity = 1.0; - - // generate a sine wave corresponding to turbulence rate in hertz - double time = FDMExec->GetSimTime(); - double sinewave = sin( time * TurbRate * 6.283185307 ); - - double random = 0.0; - if (target_time == 0.0) - { - strength = random = 1 - 2.0*(double(rand())/double(RAND_MAX)); - target_time = time + 0.71 + (random * 0.5); - } - if (time > target_time) - { - spike = 1.0; - target_time = 0.0; - } - - // max vertical wind speed in fps, corresponds to TurbGain = 1.0 - double max_vs = 40; - - vTurbulenceNED(1) = vTurbulenceNED(2) = vTurbulenceNED(3) = 0.0; - double delta = strength * max_vs * TurbGain * (1-Rhythmicity) * spike; - - // Vertical component of turbulence. - vTurbulenceNED(3) = sinewave * max_vs * TurbGain * Rhythmicity; - vTurbulenceNED(3)+= delta; - double HOverBMAC = Auxiliary->GetHOverBMAC(); - if (HOverBMAC < 3.0) - vTurbulenceNED(3) *= HOverBMAC * 0.3333; - - // Yaw component of turbulence. - vTurbulenceNED(1) = sin( delta * 3.0 ); - vTurbulenceNED(2) = cos( delta * 3.0 ); - - // Roll component of turbulence. Clockwise vortex causes left roll. - vTurbPQR(eP) += delta * 0.04; - - spike = spike * 0.9; - break; + + // Turbulence model according to MIL-F-8785C (Flying Qualities of Piloted Aircraft) + double + h = Propagate->GetDistanceAGL(), + V = Auxiliary->GetVt(), // true airspeed in ft/s + b_w = Aircraft->GetWingSpan(), + L_u, L_w, sig_u, sig_w; + + // clip height functions at 10 ft + if (h <= 10.) h = 10; + + // Scale lengths L and amplitudes sigma as function of height + if (h <= 1000) { + L_u = h/pow(0.177 + 0.000823*h, 1.2); // MIL-F-8785c, Fig. 10, p. 55 + L_w = h; + sig_w = 0.1*windspeed_at_20ft; + sig_u = sig_w/pow(0.177 + 0.000823*h, 0.4); // MIL-F-8785c, Fig. 11, p. 56 + } else if (h <= 2000) { + // linear interpolation between low altitude and high altitude models + L_u = L_w = 1000 + (h-1000.)/1000.*750.; + sig_u = sig_w = 0.1*windspeed_at_20ft + + (h-1000.)/1000.*(POE_Table->GetValue(probability_of_exceedence_index, h) - 0.1*windspeed_at_20ft); + } else { + L_u = L_w = 1750.; // MIL-F-8785c, Sec. 3.7.2.1, p. 48 + sig_u = sig_w = POE_Table->GetValue(probability_of_exceedence_index, h); } - default: - break; + + // keep values from last timesteps + // TODO maybe use deque? + static double + xi_u_km1 = 0, nu_u_km1 = 0, + xi_v_km1 = 0, xi_v_km2 = 0, nu_v_km1 = 0, nu_v_km2 = 0, + xi_w_km1 = 0, xi_w_km2 = 0, nu_w_km1 = 0, nu_w_km2 = 0, + xi_p_km1 = 0, nu_p_km1 = 0, + xi_q_km1 = 0, xi_r_km1 = 0; + + + double + T_V = DeltaT, // for compatibility of nomenclature + sig_p = 1.9/sqrt(L_w*b_w)*sig_w, // Yeager1998, eq. (8) + sig_q = sqrt(M_PI/2/L_w/b_w), // eq. (14) + sig_r = sqrt(2*M_PI/3/L_w/b_w), // eq. (17) + L_p = sqrt(L_w*b_w)/2.6, // eq. (10) + tau_u = L_u/V, // eq. (6) + tau_w = L_w/V, // eq. (3) + tau_p = L_p/V, // eq. (9) + tau_q = 4*b_w/M_PI/V, // eq. (13) + tau_r =3*b_w/M_PI/V, // eq. (17) + nu_u = GaussianRandomNumber(), + nu_v = GaussianRandomNumber(), + nu_w = GaussianRandomNumber(), + nu_p = GaussianRandomNumber(), + xi_u, xi_v, xi_w, xi_p, xi_q, xi_r; + + // values of turbulence NED velocities + + if (turbType == ttTustin) { + // the following is the Tustin formulation of Yeager's report + double + omega_w = V/L_w, // hidden in nomenclature p. 3 + omega_v = V/L_u, // this is defined nowhere + C_BL = 1/tau_u/tan(T_V/2/tau_u), // eq. (19) + C_BLp = 1/tau_p/tan(T_V/2/tau_p), // eq. (22) + C_BLq = 1/tau_q/tan(T_V/2/tau_q), // eq. (24) + C_BLr = 1/tau_r/tan(T_V/2/tau_r); // eq. (26) + + xi_u = -(1 - C_BL*tau_u)/(1 + C_BL*tau_u)*xi_u_km1 + + sig_u*sqrt(2*tau_u/T_V)/(1 + C_BL*tau_u)*(nu_u + nu_u_km1); // eq. (18) + xi_v = -2*(sqr(omega_v) - sqr(C_BL))/sqr(omega_v + C_BL)*xi_v_km1 + - sqr(omega_v - C_BL)/sqr(omega_v + C_BL) * xi_v_km2 + + sig_u*sqrt(3*omega_v/T_V)/sqr(omega_v + C_BL)*( + (C_BL + omega_v/sqrt(3.))*nu_v + + 2/sqrt(3.)*omega_v*nu_v_km1 + + (omega_v/sqrt(3.) - C_BL)*nu_v_km2); // eq. (20) for v + xi_w = -2*(sqr(omega_w) - sqr(C_BL))/sqr(omega_w + C_BL)*xi_w_km1 + - sqr(omega_w - C_BL)/sqr(omega_w + C_BL) * xi_w_km2 + + sig_w*sqrt(3*omega_w/T_V)/sqr(omega_w + C_BL)*( + (C_BL + omega_w/sqrt(3.))*nu_w + + 2/sqrt(3.)*omega_w*nu_w_km1 + + (omega_w/sqrt(3.) - C_BL)*nu_w_km2); // eq. (20) for w + xi_p = -(1 - C_BLp*tau_p)/(1 + C_BLp*tau_p)*xi_p_km1 + + sig_p*sqrt(2*tau_p/T_V)/(1 + C_BLp*tau_p) * (nu_p + nu_p_km1); // eq. (21) + xi_q = -(1 - 4*b_w*C_BLq/M_PI/V)/(1 + 4*b_w*C_BLq/M_PI/V) * xi_q_km1 + + C_BLq/V/(1 + 4*b_w*C_BLq/M_PI/V) * (xi_w - xi_w_km1); // eq. (23) + xi_r = - (1 - 3*b_w*C_BLr/M_PI/V)/(1 + 3*b_w*C_BLr/M_PI/V) * xi_r_km1 + + C_BLr/V/(1 + 3*b_w*C_BLr/M_PI/V) * (xi_v - xi_v_km1); // eq. (25) + + } else if (turbType == ttMilspec) { + // the following is the MIL-STD-1797A formulation + // as cited in Yeager's report + xi_u = (1 - T_V/tau_u) *xi_u_km1 + sig_u*sqrt(2*T_V/tau_u)*nu_u; // eq. (30) + xi_v = (1 - 2*T_V/tau_u)*xi_v_km1 + sig_u*sqrt(4*T_V/tau_u)*nu_v; // eq. (31) + xi_w = (1 - 2*T_V/tau_w)*xi_w_km1 + sig_w*sqrt(4*T_V/tau_w)*nu_w; // eq. (32) + xi_p = (1 - T_V/tau_p) *xi_p_km1 + sig_p*sqrt(2*T_V/tau_p)*nu_p; // eq. (33) + xi_q = (1 - T_V/tau_q) *xi_q_km1 + M_PI/4/b_w*(xi_w - xi_w_km1); // eq. (34) + xi_r = (1 - T_V/tau_r) *xi_r_km1 + M_PI/3/b_w*(xi_v - xi_v_km1); // eq. (35) } + + // rotate by wind azimuth and assign the velocities + double cospsi = cos(psiw), sinpsi = sin(psiw); + vTurbulenceNED(1) = cospsi*xi_u + sinpsi*xi_v; + vTurbulenceNED(2) = -sinpsi*xi_u + cospsi*xi_v; + vTurbulenceNED(3) = xi_w; + + vTurbPQR(1) = cospsi*xi_p + sinpsi*xi_q; + vTurbPQR(2) = -sinpsi*xi_p + cospsi*xi_q; + vTurbPQR(3) = xi_r; + + // vTurbPQR is in the body fixed frame, not NED + vTurbPQR = Propagate->GetTl2b()*vTurbPQR; + + // hand on the values for the next timestep + xi_u_km1 = xi_u; nu_u_km1 = nu_u; + xi_v_km2 = xi_v_km1; xi_v_km1 = xi_v; nu_v_km2 = nu_v_km1; nu_v_km1 = nu_v; + xi_w_km2 = xi_w_km1; xi_w_km1 = xi_w; nu_w_km2 = nu_w_km1; nu_w_km1 = nu_w; + xi_p_km1 = xi_p; nu_p_km1 = nu_p; + xi_q_km1 = xi_q; + xi_r_km1 = xi_r; + + } + default: + break; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGAtmosphere::UseExternal(void) { - temperature=&exTemperature; - pressure=&exPressure; - density=&exDensity; - useExternal=true; + temperature=&exTemperature; + pressure=&exPressure; + density=&exDensity; + useExternal=true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGAtmosphere::UseInternal(void) { - temperature=&intTemperature; - pressure=&intPressure; - density=&intDensity; - useExternal=false; + temperature=&intTemperature; + pressure=&intPressure; + density=&intDensity; + useExternal=false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGAtmosphere::bind(void) { - typedef double (FGAtmosphere::*PMF)(int) const; - typedef double (FGAtmosphere::*PMFv)(void) const; - typedef int (FGAtmosphere::*PMFt)(void) const; - typedef void (FGAtmosphere::*PMFd)(int,double); - typedef void (FGAtmosphere::*PMFi)(int); - PropertyManager->Tie("atmosphere/T-R", this, (PMFv)&FGAtmosphere::GetTemperature); - PropertyManager->Tie("atmosphere/rho-slugs_ft3", this, (PMFv)&FGAtmosphere::GetDensity); - PropertyManager->Tie("atmosphere/P-psf", this, (PMFv)&FGAtmosphere::GetPressure); - PropertyManager->Tie("atmosphere/a-fps", this, &FGAtmosphere::GetSoundSpeed); - PropertyManager->Tie("atmosphere/T-sl-R", this, &FGAtmosphere::GetTemperatureSL); - PropertyManager->Tie("atmosphere/rho-sl-slugs_ft3", this, &FGAtmosphere::GetDensitySL); - PropertyManager->Tie("atmosphere/P-sl-psf", this, &FGAtmosphere::GetPressureSL); - PropertyManager->Tie("atmosphere/a-sl-fps", this, &FGAtmosphere::GetSoundSpeedSL); - PropertyManager->Tie("atmosphere/theta", this, &FGAtmosphere::GetTemperatureRatio); - PropertyManager->Tie("atmosphere/sigma", this, &FGAtmosphere::GetDensityRatio); - PropertyManager->Tie("atmosphere/delta", this, &FGAtmosphere::GetPressureRatio); - PropertyManager->Tie("atmosphere/a-ratio", this, &FGAtmosphere::GetSoundSpeedRatio); - PropertyManager->Tie("atmosphere/psiw-rad", this, &FGAtmosphere::GetWindPsi, &FGAtmosphere::SetWindPsi); - PropertyManager->Tie("atmosphere/delta-T", this, &FGAtmosphere::GetDeltaT, &FGAtmosphere::SetDeltaT); - PropertyManager->Tie("atmosphere/T-sl-dev-F", this, &FGAtmosphere::GetSLTempDev, &FGAtmosphere::SetSLTempDev); - PropertyManager->Tie("atmosphere/density-altitude", this, &FGAtmosphere::GetDensityAltitude); - - PropertyManager->Tie("atmosphere/wind-north-fps", this, eNorth, (PMF)&FGAtmosphere::GetWindNED, - (PMFd)&FGAtmosphere::SetWindNED); - PropertyManager->Tie("atmosphere/wind-east-fps", this, eEast, (PMF)&FGAtmosphere::GetWindNED, - (PMFd)&FGAtmosphere::SetWindNED); - PropertyManager->Tie("atmosphere/wind-down-fps", this, eDown, (PMF)&FGAtmosphere::GetWindNED, - (PMFd)&FGAtmosphere::SetWindNED); - PropertyManager->Tie("atmosphere/wind-mag-fps", this, &FGAtmosphere::GetWindspeed, - &FGAtmosphere::SetWindspeed); - PropertyManager->Tie("atmosphere/total-wind-north-fps", this, eNorth, (PMF)&FGAtmosphere::GetTotalWindNED); - PropertyManager->Tie("atmosphere/total-wind-east-fps", this, eEast, (PMF)&FGAtmosphere::GetTotalWindNED); - PropertyManager->Tie("atmosphere/total-wind-down-fps", this, eDown, (PMF)&FGAtmosphere::GetTotalWindNED); - - PropertyManager->Tie("atmosphere/gust-north-fps", this, eNorth, (PMF)&FGAtmosphere::GetGustNED, - (PMFd)&FGAtmosphere::SetGustNED); - PropertyManager->Tie("atmosphere/gust-east-fps", this, eEast, (PMF)&FGAtmosphere::GetGustNED, - (PMFd)&FGAtmosphere::SetGustNED); - PropertyManager->Tie("atmosphere/gust-down-fps", this, eDown, (PMF)&FGAtmosphere::GetGustNED, - (PMFd)&FGAtmosphere::SetGustNED); - - PropertyManager->Tie("atmosphere/turb-north-fps", this, eNorth, (PMF)&FGAtmosphere::GetTurbNED, - (PMFd)&FGAtmosphere::SetTurbNED); - PropertyManager->Tie("atmosphere/turb-east-fps", this, eEast, (PMF)&FGAtmosphere::GetTurbNED, - (PMFd)&FGAtmosphere::SetTurbNED); - PropertyManager->Tie("atmosphere/turb-down-fps", this, eDown, (PMF)&FGAtmosphere::GetTurbNED, - (PMFd)&FGAtmosphere::SetTurbNED); - - PropertyManager->Tie("atmosphere/p-turb-rad_sec", this,1, (PMF)&FGAtmosphere::GetTurbPQR); - PropertyManager->Tie("atmosphere/q-turb-rad_sec", this,2, (PMF)&FGAtmosphere::GetTurbPQR); - PropertyManager->Tie("atmosphere/r-turb-rad_sec", this,3, (PMF)&FGAtmosphere::GetTurbPQR); - PropertyManager->Tie("atmosphere/turb-type", this, (PMFt)&FGAtmosphere::GetTurbType, (PMFi)&FGAtmosphere::SetTurbType); - PropertyManager->Tie("atmosphere/turb-rate", this, &FGAtmosphere::GetTurbRate, &FGAtmosphere::SetTurbRate); - PropertyManager->Tie("atmosphere/turb-gain", this, &FGAtmosphere::GetTurbGain, &FGAtmosphere::SetTurbGain); - PropertyManager->Tie("atmosphere/turb-rhythmicity", this, &FGAtmosphere::GetRhythmicity, - &FGAtmosphere::SetRhythmicity); + typedef double (FGAtmosphere::*PMF)(int) const; + typedef double (FGAtmosphere::*PMFv)(void) const; + typedef int (FGAtmosphere::*PMFt)(void) const; + typedef void (FGAtmosphere::*PMFd)(int,double); + typedef void (FGAtmosphere::*PMFi)(int); + PropertyManager->Tie("atmosphere/T-R", this, (PMFv)&FGAtmosphere::GetTemperature); + PropertyManager->Tie("atmosphere/rho-slugs_ft3", this, (PMFv)&FGAtmosphere::GetDensity); + PropertyManager->Tie("atmosphere/P-psf", this, (PMFv)&FGAtmosphere::GetPressure); + PropertyManager->Tie("atmosphere/a-fps", this, &FGAtmosphere::GetSoundSpeed); + PropertyManager->Tie("atmosphere/T-sl-R", this, &FGAtmosphere::GetTemperatureSL); + PropertyManager->Tie("atmosphere/rho-sl-slugs_ft3", this, &FGAtmosphere::GetDensitySL); + PropertyManager->Tie("atmosphere/P-sl-psf", this, &FGAtmosphere::GetPressureSL); + PropertyManager->Tie("atmosphere/a-sl-fps", this, &FGAtmosphere::GetSoundSpeedSL); + PropertyManager->Tie("atmosphere/theta", this, &FGAtmosphere::GetTemperatureRatio); + PropertyManager->Tie("atmosphere/sigma", this, &FGAtmosphere::GetDensityRatio); + PropertyManager->Tie("atmosphere/delta", this, &FGAtmosphere::GetPressureRatio); + PropertyManager->Tie("atmosphere/a-ratio", this, &FGAtmosphere::GetSoundSpeedRatio); + PropertyManager->Tie("atmosphere/psiw-rad", this, &FGAtmosphere::GetWindPsi, &FGAtmosphere::SetWindPsi); + PropertyManager->Tie("atmosphere/delta-T", this, &FGAtmosphere::GetDeltaT, &FGAtmosphere::SetDeltaT); + PropertyManager->Tie("atmosphere/T-sl-dev-F", this, &FGAtmosphere::GetSLTempDev, &FGAtmosphere::SetSLTempDev); + PropertyManager->Tie("atmosphere/density-altitude", this, &FGAtmosphere::GetDensityAltitude); + + PropertyManager->Tie("atmosphere/wind-north-fps", this, eNorth, (PMF)&FGAtmosphere::GetWindNED, + (PMFd)&FGAtmosphere::SetWindNED); + PropertyManager->Tie("atmosphere/wind-east-fps", this, eEast, (PMF)&FGAtmosphere::GetWindNED, + (PMFd)&FGAtmosphere::SetWindNED); + PropertyManager->Tie("atmosphere/wind-down-fps", this, eDown, (PMF)&FGAtmosphere::GetWindNED, + (PMFd)&FGAtmosphere::SetWindNED); + PropertyManager->Tie("atmosphere/wind-mag-fps", this, &FGAtmosphere::GetWindspeed, + &FGAtmosphere::SetWindspeed); + PropertyManager->Tie("atmosphere/total-wind-north-fps", this, eNorth, (PMF)&FGAtmosphere::GetTotalWindNED); + PropertyManager->Tie("atmosphere/total-wind-east-fps", this, eEast, (PMF)&FGAtmosphere::GetTotalWindNED); + PropertyManager->Tie("atmosphere/total-wind-down-fps", this, eDown, (PMF)&FGAtmosphere::GetTotalWindNED); + + PropertyManager->Tie("atmosphere/gust-north-fps", this, eNorth, (PMF)&FGAtmosphere::GetGustNED, + (PMFd)&FGAtmosphere::SetGustNED); + PropertyManager->Tie("atmosphere/gust-east-fps", this, eEast, (PMF)&FGAtmosphere::GetGustNED, + (PMFd)&FGAtmosphere::SetGustNED); + PropertyManager->Tie("atmosphere/gust-down-fps", this, eDown, (PMF)&FGAtmosphere::GetGustNED, + (PMFd)&FGAtmosphere::SetGustNED); + + PropertyManager->Tie("atmosphere/turb-north-fps", this, eNorth, (PMF)&FGAtmosphere::GetTurbNED, + (PMFd)&FGAtmosphere::SetTurbNED); + PropertyManager->Tie("atmosphere/turb-east-fps", this, eEast, (PMF)&FGAtmosphere::GetTurbNED, + (PMFd)&FGAtmosphere::SetTurbNED); + PropertyManager->Tie("atmosphere/turb-down-fps", this, eDown, (PMF)&FGAtmosphere::GetTurbNED, + (PMFd)&FGAtmosphere::SetTurbNED); + + PropertyManager->Tie("atmosphere/p-turb-rad_sec", this,1, (PMF)&FGAtmosphere::GetTurbPQR); + PropertyManager->Tie("atmosphere/q-turb-rad_sec", this,2, (PMF)&FGAtmosphere::GetTurbPQR); + PropertyManager->Tie("atmosphere/r-turb-rad_sec", this,3, (PMF)&FGAtmosphere::GetTurbPQR); + PropertyManager->Tie("atmosphere/turb-type", this, (PMFt)&FGAtmosphere::GetTurbType, (PMFi)&FGAtmosphere::SetTurbType); + PropertyManager->Tie("atmosphere/turb-rate", this, &FGAtmosphere::GetTurbRate, &FGAtmosphere::SetTurbRate); + PropertyManager->Tie("atmosphere/turb-gain", this, &FGAtmosphere::GetTurbGain, &FGAtmosphere::SetTurbGain); + PropertyManager->Tie("atmosphere/turb-rhythmicity", this, &FGAtmosphere::GetRhythmicity, + &FGAtmosphere::SetRhythmicity); + + PropertyManager->Tie("atmosphere/turbulence/milspec/windspeed_at_20ft_AGL-fps", + this, &FGAtmosphere::GetWindspeed20ft, + &FGAtmosphere::SetWindspeed20ft); + PropertyManager->Tie("atmosphere/turbulence/milspec/severity", + this, &FGAtmosphere::GetProbabilityOfExceedence, + &FGAtmosphere::SetProbabilityOfExceedence); + } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -695,52 +812,41 @@ void FGAtmosphere::bind(void) void FGAtmosphere::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGAtmosphere" << endl; - if (from == 1) cout << "Destroyed: FGAtmosphere" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor } - if (debug_lvl & 128) // Turbulence - { - if (first_pass && from == 2) - { - first_pass = false; - cout << "vTurbulenceNED(X), vTurbulenceNED(Y), vTurbulenceNED(Z), " - << "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), " - << "vDirection(X), vDirection(Y), vDirection(Z), " - << "Magnitude, " - << "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl; - } - if (from == 2) - { - cout << vTurbulenceNED << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGAtmosphere" << endl; + if (from == 1) cout << "Destroyed: FGAtmosphere" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 128) { // Turbulence + if (first_pass && from == 2) { + first_pass = false; + cout << "vTurbulenceNED(X), vTurbulenceNED(Y), vTurbulenceNED(Z), " + << "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), " + << "vDirection(X), vDirection(Y), vDirection(Z), " + << "Magnitude, " + << "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl; + } + if (from == 2) { + cout << vTurbulenceNED << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } // namespace JSBSim diff --git a/src/models/FGAtmosphere.h b/src/models/FGAtmosphere.h index e7ddafc4da992f5c0995b7416860e6552787288d..d6561fa86206547edf9edaf5d2690f55968d9cec 100644 --- a/src/models/FGAtmosphere.h +++ b/src/models/FGAtmosphere.h @@ -44,19 +44,19 @@ INCLUDES #include "FGModel.h" #include "math/FGColumnVector3.h" +#include "math/FGTable.h" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_ATMOSPHERE "$Id: FGAtmosphere.h,v 1.22 2009/10/02 10:30:09 jberndt Exp $" +#define ID_ATMOSPHERE "$Id: FGAtmosphere.h,v 1.23 2010/09/16 11:01:24 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -64,376 +64,282 @@ CLASS DOCUMENTATION /** Models the 1976 Standard Atmosphere. @author Tony Peden, Jon Berndt - @version $Id: FGAtmosphere.h,v 1.22 2009/10/02 10:30:09 jberndt Exp $ + @version $Id: FGAtmosphere.h,v 1.23 2010/09/16 11:01:24 jberndt Exp $ @see Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill, 1989, ISBN 0-07-001641-0 + + Additionally, various turbulence models are available. They are specified + via the property <tt>atmosphere/turb-type</tt>. The following models are + available: + - 0: ttNone (turbulence disabled) + - 1: ttStandard + - 2: ttBerndt + - 3: ttCulp + - 4: ttMilspec (Dryden spectrum) + - 5: ttTustin (Dryden spectrum) + + The Milspec and Tustin models are described in the Yeager report cited below. + They both use a Dryden spectrum model whose parameters (scale lengths and intensities) + are modelled according to MIL-F-8785C. Parameters are modelled differently + for altitudes below 1000ft and above 2000ft, for altitudes in between they + are interpolated linearly. + + The two models differ in the implementation of the transfer functions + described in the milspec. + + To use one of these two models, set <tt>atmosphere/turb-type</tt> to 4 resp. 5, + and specify values for <tt>atmosphere/turbulence/milspec/windspeed_at_20ft_AGL-fps<tt> + and <tt>atmosphere/turbulence/milspec/severity<tt> (the latter corresponds to + the probability of exceedence curves from Fig. 7 of the milspec, allowable + range is 0 (disabled) to 7). <tt>atmosphere/psiw-rad</tt> is respected as well; + note that you have to specify a positive wind magnitude to prevent psiw from + being reset to zero. + + Reference values (cf. figures 7 and 9 from the milspec): + <table> + <tr><td><b>Intensity</b></td> + <td><b><tt>windspeed_at_20ft_AGL-fps</tt></b></td> + <td><b><tt>severity</tt></b></td></tr> + <tr><td>light</td> + <td>25 (15 knots)</td> + <td>3</td></tr> + <tr><td>moderate</td> + <td>50 (30 knots)</td> + <td>4</td></tr> + <tr><td>severe</td> + <td>75 (45 knots)</td> + <td>6</td></tr> + </table> + + @see Yeager, Jessie C.: "Implementation and Testing of Turbulence Models for + the F18-HARV" (<a + href="http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19980028448_1998081596.pdf"> + pdf</a>), NASA CR-1998-206937, 1998 + + @see MIL-F-8785C: Military Specification: Flying Qualities of Piloted Aircraft + */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGAtmosphere : public FGModel -{ +class FGAtmosphere : public FGModel { public: - /// Constructor - FGAtmosphere(FGFDMExec*); - /// Destructor - ~FGAtmosphere(); - /** Runs the Atmosphere model; called by the Executive - @return false if no error */ - bool Run(void); - bool InitModel(void); - enum tType {ttNone, ttStandard, ttBerndt, ttCulp} turbType; - - /// Returns the temperature in degrees Rankine. - double GetTemperature(void) const - { - return *temperature; - } - /** Returns the density in slugs/ft^3. - <i>This function may <b>only</b> be used if Run() is called first.</i> */ - double GetDensity(void) const - { - return *density; - } - /// Returns the pressure in psf. - double GetPressure(void) const - { - return *pressure; - } - /// Returns the standard pressure at a specified altitude - double GetPressure(double altitude); - /// Returns the standard temperature at a specified altitude - double GetTemperature(double altitude); - /// Returns the standard density at a specified altitude - double GetDensity(double altitude); - /// Returns the speed of sound in ft/sec. - double GetSoundSpeed(void) const - { - return soundspeed; - } - /// Returns the absolute viscosity. - double GetAbsoluteViscosity(void) const - { - return intViscosity; - } - /// Returns the kinematic viscosity. - double GetKinematicViscosity(void) const - { - return intKinematicViscosity; - } - - /// Returns the sea level temperature in degrees Rankine. - double GetTemperatureSL(void) const - { - return SLtemperature; - } - /// Returns the sea level density in slugs/ft^3 - double GetDensitySL(void) const - { - return SLdensity; - } - /// Returns the sea level pressure in psf. - double GetPressureSL(void) const - { - return SLpressure; - } - /// Returns the sea level speed of sound in ft/sec. - double GetSoundSpeedSL(void) const - { - return SLsoundspeed; - } - - /// Returns the ratio of at-altitude temperature over the sea level value. - double GetTemperatureRatio(void) const - { - return (*temperature)*rSLtemperature; - } - /// Returns the ratio of at-altitude density over the sea level value. - double GetDensityRatio(void) const - { - return (*density)*rSLdensity; - } - /// Returns the ratio of at-altitude pressure over the sea level value. - double GetPressureRatio(void) const - { - return (*pressure)*rSLpressure; - } - /// Returns the ratio of at-altitude sound speed over the sea level value. - double GetSoundSpeedRatio(void) const - { - return soundspeed*rSLsoundspeed; - } - - /// Tells the simulator to use an externally calculated atmosphere model. - void UseExternal(void); - /// Tells the simulator to use the internal atmosphere model. - void UseInternal(void); //this is the default - /// Gets the boolean that tells if the external atmosphere model is being used. - bool External(void) - { - return useExternal; - } - - /// Provides the external atmosphere model with an interface to set the temperature. - void SetExTemperature(double t) - { - exTemperature=t; - } - /// Provides the external atmosphere model with an interface to set the density. - void SetExDensity(double d) - { - exDensity=d; - } - /// Provides the external atmosphere model with an interface to set the pressure. - void SetExPressure(double p) - { - exPressure=p; - } - - /// Sets the temperature deviation at sea-level in degrees Fahrenheit - void SetSLTempDev(double d) - { - T_dev_sl = d; - } - /// Gets the temperature deviation at sea-level in degrees Fahrenheit - double GetSLTempDev(void) const - { - return T_dev_sl; - } - /// Sets the current delta-T in degrees Fahrenheit - void SetDeltaT(double d) - { - delta_T = d; - } - /// Gets the current delta-T in degrees Fahrenheit - double GetDeltaT(void) const - { - return delta_T; - } - /// Gets the at-altitude temperature deviation in degrees Fahrenheit - double GetTempDev(void) const - { - return T_dev; - } - /// Gets the density altitude in feet - double GetDensityAltitude(void) const - { - return density_altitude; - } - - // TOTAL WIND access functions (wind + gust + turbulence) - - /// Retrieves the total wind components in NED frame. - FGColumnVector3& GetTotalWindNED(void) - { - return vTotalWindNED; - } - - /// Retrieves a total wind component in NED frame. - double GetTotalWindNED(int idx) const - { - return vTotalWindNED(idx); - } - - // WIND access functions - - /// Sets the wind components in NED frame. - void SetWindNED(double wN, double wE, double wD) - { - vWindNED(1)=wN; - vWindNED(2)=wE; - vWindNED(3)=wD; - } - - /// Sets a wind component in NED frame. - void SetWindNED(int idx, double wind) - { - vWindNED(idx)=wind; - } - - /// Retrieves the wind components in NED frame. - FGColumnVector3& GetWindNED(void) - { - return vWindNED; - } - - /// Retrieves a wind component in NED frame. - double GetWindNED(int idx) const - { - return vWindNED(idx); - } - - /** Retrieves the direction that the wind is coming from. - The direction is defined as north=0 and increases counterclockwise. - The wind heading is returned in radians.*/ - double GetWindPsi(void) const - { - return psiw; - } - - /** Sets the direction that the wind is coming from. - The direction is defined as north=0 and increases counterclockwise to 2*pi (radians). The - vertical component of wind is assumed to be zero - and is forcibly set to zero. This function - sets the vWindNED vector components based on the supplied direction. The magnitude of - the wind set in the vector is preserved (assuming the vertical component is non-zero). - @param dir wind direction in the horizontal plane, in radians.*/ - void SetWindPsi(double dir); - - void SetWindspeed(double speed); - - double GetWindspeed(void) const; - - // GUST access functions - - /// Sets a gust component in NED frame. - void SetGustNED(int idx, double gust) - { - vGustNED(idx)=gust; - } - - /// Sets a turbulence component in NED frame. - void SetTurbNED(int idx, double turb) - { - vTurbulenceNED(idx)=turb; - } - - /// Sets the gust components in NED frame. - void SetGustNED(double gN, double gE, double gD) - { - vGustNED(eNorth)=gN; - vGustNED(eEast)=gE; - vGustNED(eDown)=gD; - } - - /// Retrieves a gust component in NED frame. - double GetGustNED(int idx) const - { - return vGustNED(idx); - } - - /// Retrieves a turbulence component in NED frame. - double GetTurbNED(int idx) const - { - return vTurbulenceNED(idx); - } - - /// Retrieves the gust components in NED frame. - FGColumnVector3& GetGustNED(void) - { - return vGustNED; - } - - /** Turbulence models available: ttNone, ttStandard, ttBerndt, ttCulp */ - void SetTurbType(tType tt) - { - turbType = tt; - } - tType GetTurbType() const - { - return turbType; - } - - void SetTurbGain(double tg) - { - TurbGain = tg; - } - double GetTurbGain() const - { - return TurbGain; - } - - void SetTurbRate(double tr) - { - TurbRate = tr; - } - double GetTurbRate() const - { - return TurbRate; - } - - void SetRhythmicity(double r) - { - Rhythmicity=r; - } - double GetRhythmicity() const - { - return Rhythmicity; - } - - double GetTurbPQR(int idx) const - { - return vTurbPQR(idx); - } - double GetTurbMagnitude(void) const - { - return Magnitude; - } - FGColumnVector3& GetTurbDirection(void) - { - return vDirection; - } - FGColumnVector3& GetTurbPQR(void) - { - return vTurbPQR; - } + /// Constructor + FGAtmosphere(FGFDMExec*); + /// Destructor + ~FGAtmosphere(); + /** Runs the Atmosphere model; called by the Executive + @return false if no error */ + bool Run(void); + bool InitModel(void); + enum tType {ttNone, ttStandard, ttBerndt, ttCulp, ttMilspec, ttTustin} turbType; + + /// Returns the temperature in degrees Rankine. + double GetTemperature(void) const {return *temperature;} + /** Returns the density in slugs/ft^3. + <i>This function may <b>only</b> be used if Run() is called first.</i> */ + double GetDensity(void) const {return *density;} + /// Returns the pressure in psf. + double GetPressure(void) const {return *pressure;} + /// Returns the standard pressure at a specified altitude + double GetPressure(double altitude); + /// Returns the standard temperature at a specified altitude + double GetTemperature(double altitude); + /// Returns the standard density at a specified altitude + double GetDensity(double altitude); + /// Returns the speed of sound in ft/sec. + double GetSoundSpeed(void) const {return soundspeed;} + /// Returns the absolute viscosity. + double GetAbsoluteViscosity(void) const {return intViscosity;} + /// Returns the kinematic viscosity. + double GetKinematicViscosity(void) const {return intKinematicViscosity;} + + /// Returns the sea level temperature in degrees Rankine. + double GetTemperatureSL(void) const { return SLtemperature; } + /// Returns the sea level density in slugs/ft^3 + double GetDensitySL(void) const { return SLdensity; } + /// Returns the sea level pressure in psf. + double GetPressureSL(void) const { return SLpressure; } + /// Returns the sea level speed of sound in ft/sec. + double GetSoundSpeedSL(void) const { return SLsoundspeed; } + + /// Returns the ratio of at-altitude temperature over the sea level value. + double GetTemperatureRatio(void) const { return (*temperature)*rSLtemperature; } + /// Returns the ratio of at-altitude density over the sea level value. + double GetDensityRatio(void) const { return (*density)*rSLdensity; } + /// Returns the ratio of at-altitude pressure over the sea level value. + double GetPressureRatio(void) const { return (*pressure)*rSLpressure; } + /// Returns the ratio of at-altitude sound speed over the sea level value. + double GetSoundSpeedRatio(void) const { return soundspeed*rSLsoundspeed; } + + /// Tells the simulator to use an externally calculated atmosphere model. + void UseExternal(void); + /// Tells the simulator to use the internal atmosphere model. + void UseInternal(void); //this is the default + /// Gets the boolean that tells if the external atmosphere model is being used. + bool External(void) { return useExternal; } + + /// Provides the external atmosphere model with an interface to set the temperature. + void SetExTemperature(double t) { exTemperature=t; } + /// Provides the external atmosphere model with an interface to set the density. + void SetExDensity(double d) { exDensity=d; } + /// Provides the external atmosphere model with an interface to set the pressure. + void SetExPressure(double p) { exPressure=p; } + + /// Sets the temperature deviation at sea-level in degrees Fahrenheit + void SetSLTempDev(double d) { T_dev_sl = d; } + /// Gets the temperature deviation at sea-level in degrees Fahrenheit + double GetSLTempDev(void) const { return T_dev_sl; } + /// Sets the current delta-T in degrees Fahrenheit + void SetDeltaT(double d) { delta_T = d; } + /// Gets the current delta-T in degrees Fahrenheit + double GetDeltaT(void) const { return delta_T; } + /// Gets the at-altitude temperature deviation in degrees Fahrenheit + double GetTempDev(void) const { return T_dev; } + /// Gets the density altitude in feet + double GetDensityAltitude(void) const { return density_altitude; } + + // TOTAL WIND access functions (wind + gust + turbulence) + + /// Retrieves the total wind components in NED frame. + FGColumnVector3& GetTotalWindNED(void) { return vTotalWindNED; } + + /// Retrieves a total wind component in NED frame. + double GetTotalWindNED(int idx) const {return vTotalWindNED(idx);} + + // WIND access functions + + /// Sets the wind components in NED frame. + void SetWindNED(double wN, double wE, double wD) { vWindNED(1)=wN; vWindNED(2)=wE; vWindNED(3)=wD;} + + /// Sets a wind component in NED frame. + void SetWindNED(int idx, double wind) { vWindNED(idx)=wind;} + + /// Retrieves the wind components in NED frame. + FGColumnVector3& GetWindNED(void) { return vWindNED; } + + /// Retrieves a wind component in NED frame. + double GetWindNED(int idx) const {return vWindNED(idx);} + + /** Retrieves the direction that the wind is coming from. + The direction is defined as north=0 and increases counterclockwise. + The wind heading is returned in radians.*/ + double GetWindPsi(void) const { return psiw; } + + /** Sets the direction that the wind is coming from. + The direction is defined as north=0 and increases counterclockwise to 2*pi (radians). The + vertical component of wind is assumed to be zero - and is forcibly set to zero. This function + sets the vWindNED vector components based on the supplied direction. The magnitude of + the wind set in the vector is preserved (assuming the vertical component is non-zero). + @param dir wind direction in the horizontal plane, in radians.*/ + void SetWindPsi(double dir); + + void SetWindspeed(double speed); + + double GetWindspeed(void) const; + + // GUST access functions + + /// Sets a gust component in NED frame. + void SetGustNED(int idx, double gust) { vGustNED(idx)=gust;} + + /// Sets a turbulence component in NED frame. + void SetTurbNED(int idx, double turb) { vTurbulenceNED(idx)=turb;} + + /// Sets the gust components in NED frame. + void SetGustNED(double gN, double gE, double gD) { vGustNED(eNorth)=gN; vGustNED(eEast)=gE; vGustNED(eDown)=gD;} + + /// Retrieves a gust component in NED frame. + double GetGustNED(int idx) const {return vGustNED(idx);} + + /// Retrieves a turbulence component in NED frame. + double GetTurbNED(int idx) const {return vTurbulenceNED(idx);} + + /// Retrieves the gust components in NED frame. + FGColumnVector3& GetGustNED(void) {return vGustNED;} + + /** Turbulence models available: ttNone, ttStandard, ttBerndt, ttCulp, ttMilspec, ttTustin */ + void SetTurbType(tType tt) {turbType = tt;} + tType GetTurbType() const {return turbType;} + + void SetTurbGain(double tg) {TurbGain = tg;} + double GetTurbGain() const {return TurbGain;} + + void SetTurbRate(double tr) {TurbRate = tr;} + double GetTurbRate() const {return TurbRate;} + + void SetRhythmicity(double r) {Rhythmicity=r;} + double GetRhythmicity() const {return Rhythmicity;} + + double GetTurbPQR(int idx) const {return vTurbPQR(idx);} + double GetTurbMagnitude(void) const {return Magnitude;} + FGColumnVector3& GetTurbDirection(void) {return vDirection;} + FGColumnVector3& GetTurbPQR(void) {return vTurbPQR;} + + void SetWindspeed20ft(double ws) { windspeed_at_20ft = ws;} + double GetWindspeed20ft() const { return windspeed_at_20ft;} + + /// allowable range: 0-7, 3=light, 4=moderate, 6=severe turbulence + void SetProbabilityOfExceedence( int idx) {probability_of_exceedence_index = idx;} + int GetProbabilityOfExceedence() const { return probability_of_exceedence_index;} protected: - double rho; - - struct atmType - { - double Temperature; - double Pressure; - double Density; - }; - int lastIndex; - double h; - double htab[8]; - double StdSLtemperature,StdSLdensity,StdSLpressure,StdSLsoundspeed; - double rSLtemperature,rSLdensity,rSLpressure,rSLsoundspeed; //reciprocals - double SLtemperature,SLdensity,SLpressure,SLsoundspeed; - double *temperature, *density, *pressure; - double soundspeed; - bool useExternal; - double exTemperature,exDensity,exPressure; - double intTemperature, intDensity, intPressure; - double SutherlandConstant, Beta, intViscosity, intKinematicViscosity; - double T_dev_sl, T_dev, delta_T, density_altitude; - atmType atmosphere; - bool StandardTempOnly; - bool first_pass; - - double MagnitudedAccelDt, MagnitudeAccel, Magnitude; - double TurbGain; - double TurbRate; - double Rhythmicity; - double wind_from_clockwise; - double spike, target_time, strength; - FGColumnVector3 vDirectiondAccelDt; - FGColumnVector3 vDirectionAccel; - FGColumnVector3 vDirection; - FGColumnVector3 vTurbulenceGrad; - FGColumnVector3 vBodyTurbGrad; - FGColumnVector3 vTurbPQR; - - double psiw; - FGColumnVector3 vTotalWindNED; - FGColumnVector3 vWindNED; - FGColumnVector3 vGustNED; - FGColumnVector3 vTurbulenceNED; - - /// Calculate the atmosphere for the given altitude, including effects of temperature deviation. - void Calculate(double altitude); - /// Calculate atmospheric properties other than the basic T, P and rho. - void CalculateDerived(void); - /// Get T, P and rho for a standard atmosphere at the given altitude. - void GetStdAtmosphere(double altitude); - void Turbulence(void); - void bind(void); - void Debug(int from); + double rho; + + struct atmType {double Temperature; double Pressure; double Density;}; + int lastIndex; + double h; + double htab[8]; + double StdSLtemperature,StdSLdensity,StdSLpressure,StdSLsoundspeed; + double rSLtemperature,rSLdensity,rSLpressure,rSLsoundspeed; //reciprocals + double SLtemperature,SLdensity,SLpressure,SLsoundspeed; + double *temperature, *density, *pressure; + double soundspeed; + bool useExternal; + double exTemperature,exDensity,exPressure; + double intTemperature, intDensity, intPressure; + double SutherlandConstant, Beta, intViscosity, intKinematicViscosity; + double T_dev_sl, T_dev, delta_T, density_altitude; + atmType atmosphere; + bool StandardTempOnly; + bool first_pass; + + double MagnitudedAccelDt, MagnitudeAccel, Magnitude; + double TurbGain; + double TurbRate; + double Rhythmicity; + double wind_from_clockwise; + double spike, target_time, strength; + FGColumnVector3 vDirectiondAccelDt; + FGColumnVector3 vDirectionAccel; + FGColumnVector3 vDirection; + FGColumnVector3 vTurbulenceGrad; + FGColumnVector3 vBodyTurbGrad; + FGColumnVector3 vTurbPQR; + + // Dryden turbulence model + double windspeed_at_20ft; ///< in ft/s + int probability_of_exceedence_index; ///< this is bound as the severity property + FGTable *POE_Table; ///< probability of exceedence table + + double psiw; + FGColumnVector3 vTotalWindNED; + FGColumnVector3 vWindNED; + FGColumnVector3 vGustNED; + FGColumnVector3 vTurbulenceNED; + + /// Calculate the atmosphere for the given altitude, including effects of temperature deviation. + void Calculate(double altitude); + /// Calculate atmospheric properties other than the basic T, P and rho. + void CalculateDerived(void); + /// Get T, P and rho for a standard atmosphere at the given altitude. + void GetStdAtmosphere(double altitude); + void Turbulence(void); + void bind(void); + void Debug(int from); }; } // namespace JSBSim diff --git a/src/models/FGAuxiliary.cpp b/src/models/FGAuxiliary.cpp old mode 100644 new mode 100755 index 6215ce7c9f230bbcf26ccdcf4331ac21d664b1f3..ededdc1ccb5aaa56c1d30791e18e2c87075cb4b1 --- a/src/models/FGAuxiliary.cpp +++ b/src/models/FGAuxiliary.cpp @@ -57,8 +57,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.42 2010/07/27 23:18:19 jberndt Exp $"; static const char *IdHdr = ID_AUXILIARY; @@ -70,237 +69,221 @@ CLASS IMPLEMENTATION FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex) { - Name = "FGAuxiliary"; - vcas = veas = pt = tat = 0; - psl = rhosl = 1; - qbar = 0; - qbarUW = 0.0; - qbarUV = 0.0; - Re = 0.0; - Mach = 0.0; - alpha = beta = 0.0; - adot = bdot = 0.0; - gamma = Vt = Vground = 0.0; - psigt = 0.0; - day_of_year = 1; - seconds_in_day = 0.0; - hoverbmac = hoverbcg = 0.0; - tatc = RankineToCelsius(tat); - - vPilotAccel.InitMatrix(); - vPilotAccelN.InitMatrix(); - vToEyePt.InitMatrix(); - vAeroPQR.InitMatrix(); - vEulerRates.InitMatrix(); - - bind(); - - Debug(0); + Name = "FGAuxiliary"; + vcas = veas = pt = tat = 0; + psl = rhosl = 1; + qbar = 0; + qbarUW = 0.0; + qbarUV = 0.0; + Re = 0.0; + Mach = 0.0; + alpha = beta = 0.0; + adot = bdot = 0.0; + gamma = Vt = Vground = 0.0; + psigt = 0.0; + day_of_year = 1; + seconds_in_day = 0.0; + hoverbmac = hoverbcg = 0.0; + tatc = RankineToCelsius(tat); + + vPilotAccel.InitMatrix(); + vPilotAccelN.InitMatrix(); + vToEyePt.InitMatrix(); + vAeroPQR.InitMatrix(); + vEulerRates.InitMatrix(); + + bind(); + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGAuxiliary::InitModel(void) { - if (!FGModel::InitModel()) return false; - - vcas = veas = pt = tat = 0; - psl = rhosl = 1; - qbar = 0; - qbarUW = 0.0; - qbarUV = 0.0; - Mach = 0.0; - alpha = beta = 0.0; - adot = bdot = 0.0; - gamma = Vt = Vground = 0.0; - psigt = 0.0; - day_of_year = 1; - seconds_in_day = 0.0; - hoverbmac = hoverbcg = 0.0; - - vPilotAccel.InitMatrix(); - vPilotAccelN.InitMatrix(); - vToEyePt.InitMatrix(); - vAeroPQR.InitMatrix(); - vEulerRates.InitMatrix(); - - return true; + if (!FGModel::InitModel()) return false; + + vcas = veas = pt = tat = 0; + psl = rhosl = 1; + qbar = 0; + qbarUW = 0.0; + qbarUV = 0.0; + Mach = 0.0; + alpha = beta = 0.0; + adot = bdot = 0.0; + gamma = Vt = Vground = 0.0; + psigt = 0.0; + day_of_year = 1; + seconds_in_day = 0.0; + hoverbmac = hoverbcg = 0.0; + + vPilotAccel.InitMatrix(); + vPilotAccelN.InitMatrix(); + vToEyePt.InitMatrix(); + vAeroPQR.InitMatrix(); + vEulerRates.InitMatrix(); + + return true; } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGAuxiliary::~FGAuxiliary() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGAuxiliary::Run() { - double A,B,D; + double A,B,D; - if (FGModel::Run()) return true; // return true if error returned from base class - if (FDMExec->Holding()) return false; + if (FGModel::Run()) return true; // return true if error returned from base class + if (FDMExec->Holding()) return false; - RunPreFunctions(); + RunPreFunctions(); - const FGColumnVector3& vPQR = Propagate->GetPQR(); - const FGColumnVector3& vUVW = Propagate->GetUVW(); - const FGColumnVector3& vUVWdot = Propagate->GetUVWdot(); - const FGColumnVector3& vVel = Propagate->GetVel(); + const FGColumnVector3& vPQR = Propagate->GetPQR(); + const FGColumnVector3& vUVW = Propagate->GetUVW(); + const FGColumnVector3& vUVWdot = Propagate->GetUVWdot(); + const FGColumnVector3& vVel = Propagate->GetVel(); - p = Atmosphere->GetPressure(); - rhosl = Atmosphere->GetDensitySL(); - psl = Atmosphere->GetPressureSL(); - sat = Atmosphere->GetTemperature(); + p = Atmosphere->GetPressure(); + rhosl = Atmosphere->GetDensitySL(); + psl = Atmosphere->GetPressureSL(); + sat = Atmosphere->GetTemperature(); // Rotation - double cTht = Propagate->GetCosEuler(eTht); - double sTht = Propagate->GetSinEuler(eTht); - double cPhi = Propagate->GetCosEuler(ePhi); - double sPhi = Propagate->GetSinEuler(ePhi); + double cTht = Propagate->GetCosEuler(eTht); + double sTht = Propagate->GetSinEuler(eTht); + double cPhi = Propagate->GetCosEuler(ePhi); + double sPhi = Propagate->GetSinEuler(ePhi); - vEulerRates(eTht) = vPQR(eQ)*cPhi - vPQR(eR)*sPhi; - if (cTht != 0.0) - { - vEulerRates(ePsi) = (vPQR(eQ)*sPhi + vPQR(eR)*cPhi)/cTht; - vEulerRates(ePhi) = vPQR(eP) + vEulerRates(ePsi)*sTht; - } + vEulerRates(eTht) = vPQR(eQ)*cPhi - vPQR(eR)*sPhi; + if (cTht != 0.0) { + vEulerRates(ePsi) = (vPQR(eQ)*sPhi + vPQR(eR)*cPhi)/cTht; + vEulerRates(ePhi) = vPQR(eP) + vEulerRates(ePsi)*sTht; + } // Combine the wind speed with aircraft speed to obtain wind relative speed - FGColumnVector3 wind = Propagate->GetTl2b()*Atmosphere->GetTotalWindNED(); - vAeroPQR = vPQR - Atmosphere->GetTurbPQR(); - vAeroUVW = vUVW - wind; - - Vt = vAeroUVW.Magnitude(); - if ( Vt > 0.05) - { - if (vAeroUVW(eW) != 0.0) - alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0; - if (vAeroUVW(eV) != 0.0) - beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), - sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0; - - double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW)); - double signU=1; - if (vAeroUVW(eU) != 0.0) - signU = vAeroUVW(eU)/fabs(vAeroUVW(eU)); - - if ( (mUW == 0.0) || (Vt == 0.0) ) - { - adot = 0.0; - bdot = 0.0; - } - else - { - adot = (vAeroUVW(eU)*vUVWdot(eW) - vAeroUVW(eW)*vUVWdot(eU))/mUW; - bdot = (signU*mUW*vUVWdot(eV) - vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU) - + vAeroUVW(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW)); - } - } - else - { - alpha = beta = adot = bdot = 0; + FGColumnVector3 wind = Propagate->GetTl2b()*Atmosphere->GetTotalWindNED(); + vAeroPQR = vPQR - Atmosphere->GetTurbPQR(); + vAeroUVW = vUVW - wind; + + Vt = vAeroUVW.Magnitude(); + if ( Vt > 0.05) { + if (vAeroUVW(eW) != 0.0) + alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0; + if (vAeroUVW(eV) != 0.0) + beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), + sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0; + + double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW)); + double signU=1; + if (vAeroUVW(eU) != 0.0) + signU = vAeroUVW(eU)/fabs(vAeroUVW(eU)); + + if ( (mUW == 0.0) || (Vt == 0.0) ) { + adot = 0.0; + bdot = 0.0; + } else { + adot = (vAeroUVW(eU)*vUVWdot(eW) - vAeroUVW(eW)*vUVWdot(eU))/mUW; + bdot = (signU*mUW*vUVWdot(eV) - vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU) + + vAeroUVW(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW)); } + } else { + alpha = beta = adot = bdot = 0; + } - Re = Vt * Aircraft->Getcbar() / Atmosphere->GetKinematicViscosity(); + Re = Vt * Aircraft->Getcbar() / Atmosphere->GetKinematicViscosity(); - qbar = 0.5*Atmosphere->GetDensity()*Vt*Vt; - qbarUW = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW)); - qbarUV = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV)); - Mach = Vt / Atmosphere->GetSoundSpeed(); - MachU = vMachUVW(eU) = vAeroUVW(eU) / Atmosphere->GetSoundSpeed(); - vMachUVW(eV) = vAeroUVW(eV) / Atmosphere->GetSoundSpeed(); - vMachUVW(eW) = vAeroUVW(eW) / Atmosphere->GetSoundSpeed(); + qbar = 0.5*Atmosphere->GetDensity()*Vt*Vt; + qbarUW = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW)); + qbarUV = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV)); + Mach = Vt / Atmosphere->GetSoundSpeed(); + MachU = vMachUVW(eU) = vAeroUVW(eU) / Atmosphere->GetSoundSpeed(); + vMachUVW(eV) = vAeroUVW(eV) / Atmosphere->GetSoundSpeed(); + vMachUVW(eW) = vAeroUVW(eW) / Atmosphere->GetSoundSpeed(); // Position - Vground = sqrt( vVel(eNorth)*vVel(eNorth) + vVel(eEast)*vVel(eEast) ); - - psigt = atan2(vVel(eEast), vVel(eNorth)); - if (psigt < 0.0) psigt += 2*M_PI; - gamma = atan2(-vVel(eDown), Vground); - - tat = sat*(1 + 0.2*Mach*Mach); // Total Temperature, isentropic flow - tatc = RankineToCelsius(tat); - - if (MachU < 1) // Calculate total pressure assuming isentropic flow - { - pt = p*pow((1 + 0.2*MachU*MachU),3.5); - } - else - { - // Use Rayleigh pitot tube formula for normal shock in front of pitot tube - B = 5.76*MachU*MachU/(5.6*MachU*MachU - 0.8); - D = (2.8*MachU*MachU-0.4)*0.4167; - pt = p*pow(B,3.5)*D; - } - - A = pow(((pt-p)/psl+1),0.28571); - if (MachU > 0.0) - { - vcas = sqrt(7*psl/rhosl*(A-1)); - veas = sqrt(2*qbar/rhosl); - } - else - { - vcas = veas = 0.0; - } - - vPilotAccel.InitMatrix(); - if ( Vt > 1.0 ) - { - // Use the "+=" operator to avoid the creation of temporary objects. - vAircraftAccel = Aerodynamics->GetForces(); - vAircraftAccel += Propulsion->GetForces(); - vAircraftAccel += GroundReactions->GetForces(); - vAircraftAccel += ExternalReactions->GetForces(); - vAircraftAccel += BuoyantForces->GetForces(); - - vAircraftAccel /= MassBalance->GetMass(); - // Nz is Acceleration in "g's", along normal axis (-Z body axis) - Nz = -vAircraftAccel(eZ)/Inertial->SLgravity(); - vToEyePt = MassBalance->StructuralToBody(Aircraft->GetXYZep()); - vPilotAccel = vAircraftAccel + Propagate->GetPQRdot() * vToEyePt; - vPilotAccel += vPQR * (vPQR * vToEyePt); - } - else - { - // The line below handles low velocity (and on-ground) cases, basically - // representing the opposite of the force that the landing gear would - // exert on the ground (which is just the total weight). This eliminates - // any jitter that could be introduced by the landing gear. Theoretically, - // this branch could be eliminated, with a penalty of having a short - // transient at startup (lasting only a fraction of a second). - vPilotAccel = Propagate->GetTl2b() * FGColumnVector3( 0.0, 0.0, -Inertial->SLgravity() ); - Nz = -vPilotAccel(eZ)/Inertial->SLgravity(); - } - - vPilotAccelN = vPilotAccel/Inertial->SLgravity(); - - // VRP computation - const FGLocation& vLocation = Propagate->GetLocation(); - FGColumnVector3& vrpStructural = Aircraft->GetXYZvrp(); - FGColumnVector3 vrpBody = MassBalance->StructuralToBody( vrpStructural ); - FGColumnVector3 vrpLocal = Propagate->GetTb2l() * vrpBody; - vLocationVRP = vLocation.LocalToLocation( vrpLocal ); - - // Recompute some derived values now that we know the dependent parameters values ... - hoverbcg = Propagate->GetDistanceAGL() / Aircraft->GetWingSpan(); - - FGColumnVector3 vMac = Propagate->GetTb2l()*MassBalance->StructuralToBody(Aircraft->GetXYZrp()); - hoverbmac = (Propagate->GetDistanceAGL() + vMac(3)) / Aircraft->GetWingSpan(); - - // when all model are executed, - // please calculate the distance from the initial point - - CalculateRelativePosition(); - - RunPostFunctions(); - - return false; + Vground = sqrt( vVel(eNorth)*vVel(eNorth) + vVel(eEast)*vVel(eEast) ); + + psigt = atan2(vVel(eEast), vVel(eNorth)); + if (psigt < 0.0) psigt += 2*M_PI; + gamma = atan2(-vVel(eDown), Vground); + + tat = sat*(1 + 0.2*Mach*Mach); // Total Temperature, isentropic flow + tatc = RankineToCelsius(tat); + + if (MachU < 1) { // Calculate total pressure assuming isentropic flow + pt = p*pow((1 + 0.2*MachU*MachU),3.5); + } else { + // Use Rayleigh pitot tube formula for normal shock in front of pitot tube + B = 5.76*MachU*MachU/(5.6*MachU*MachU - 0.8); + D = (2.8*MachU*MachU-0.4)*0.4167; + pt = p*pow(B,3.5)*D; + } + + A = pow(((pt-p)/psl+1),0.28571); + if (MachU > 0.0) { + vcas = sqrt(7*psl/rhosl*(A-1)); + veas = sqrt(2*qbar/rhosl); + } else { + vcas = veas = 0.0; + } + + vPilotAccel.InitMatrix(); + if ( Vt > 1.0 ) { + // Use the "+=" operator to avoid the creation of temporary objects. + vAircraftAccel = Aerodynamics->GetForces(); + vAircraftAccel += Propulsion->GetForces(); + vAircraftAccel += GroundReactions->GetForces(); + vAircraftAccel += ExternalReactions->GetForces(); + vAircraftAccel += BuoyantForces->GetForces(); + + vAircraftAccel /= MassBalance->GetMass(); + // Nz is Acceleration in "g's", along normal axis (-Z body axis) + Nz = -vAircraftAccel(eZ)/Inertial->SLgravity(); + vToEyePt = MassBalance->StructuralToBody(Aircraft->GetXYZep()); + vPilotAccel = vAircraftAccel + Propagate->GetPQRdot() * vToEyePt; + vPilotAccel += vPQR * (vPQR * vToEyePt); + } else { + // The line below handles low velocity (and on-ground) cases, basically + // representing the opposite of the force that the landing gear would + // exert on the ground (which is just the total weight). This eliminates + // any jitter that could be introduced by the landing gear. Theoretically, + // this branch could be eliminated, with a penalty of having a short + // transient at startup (lasting only a fraction of a second). + vPilotAccel = Propagate->GetTl2b() * FGColumnVector3( 0.0, 0.0, -Inertial->SLgravity() ); + Nz = -vPilotAccel(eZ)/Inertial->SLgravity(); + } + + vPilotAccelN = vPilotAccel/Inertial->SLgravity(); + + // VRP computation + const FGLocation& vLocation = Propagate->GetLocation(); + FGColumnVector3& vrpStructural = Aircraft->GetXYZvrp(); + FGColumnVector3 vrpBody = MassBalance->StructuralToBody( vrpStructural ); + FGColumnVector3 vrpLocal = Propagate->GetTb2l() * vrpBody; + vLocationVRP = vLocation.LocalToLocation( vrpLocal ); + + // Recompute some derived values now that we know the dependent parameters values ... + hoverbcg = Propagate->GetDistanceAGL() / Aircraft->GetWingSpan(); + + FGColumnVector3 vMac = Propagate->GetTb2l()*MassBalance->StructuralToBody(Aircraft->GetXYZrp()); + hoverbmac = (Propagate->GetDistanceAGL() + vMac(3)) / Aircraft->GetWingSpan(); + + // when all model are executed, + // please calculate the distance from the initial point + + CalculateRelativePosition(); + + RunPostFunctions(); + + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -310,12 +293,12 @@ bool FGAuxiliary::Run() double FGAuxiliary::GetHeadWind(void) const { - double psiw,vw; + double psiw,vw; - psiw = Atmosphere->GetWindPsi(); - vw = Atmosphere->GetTotalWindNED().Magnitude(); + psiw = Atmosphere->GetWindPsi(); + vw = Atmosphere->GetTotalWindNED().Magnitude(); - return vw*cos(psiw - Propagate->GetEuler(ePsi)); + return vw*cos(psiw - Propagate->GetEuler(ePsi)); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -326,92 +309,91 @@ double FGAuxiliary::GetHeadWind(void) const double FGAuxiliary::GetCrossWind(void) const { - double psiw,vw; + double psiw,vw; - psiw = Atmosphere->GetWindPsi(); - vw = Atmosphere->GetTotalWindNED().Magnitude(); + psiw = Atmosphere->GetWindPsi(); + vw = Atmosphere->GetTotalWindNED().Magnitude(); - return vw*sin(psiw - Propagate->GetEuler(ePsi)); + return vw*sin(psiw - Propagate->GetEuler(ePsi)); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGAuxiliary::bind(void) { - typedef double (FGAuxiliary::*PMF)(int) const; - typedef double (FGAuxiliary::*PF)(void) const; - PropertyManager->Tie("propulsion/tat-r", this, &FGAuxiliary::GetTotalTemperature); - PropertyManager->Tie("propulsion/tat-c", this, &FGAuxiliary::GetTAT_C); - PropertyManager->Tie("propulsion/pt-lbs_sqft", this, &FGAuxiliary::GetTotalPressure); - PropertyManager->Tie("velocities/vc-fps", this, &FGAuxiliary::GetVcalibratedFPS); - PropertyManager->Tie("velocities/vc-kts", this, &FGAuxiliary::GetVcalibratedKTS); - PropertyManager->Tie("velocities/ve-fps", this, &FGAuxiliary::GetVequivalentFPS); - PropertyManager->Tie("velocities/ve-kts", this, &FGAuxiliary::GetVequivalentKTS); - PropertyManager->Tie("velocities/machU", this, &FGAuxiliary::GetMachU); - PropertyManager->Tie("velocities/p-aero-rad_sec", this, eX, (PMF)&FGAuxiliary::GetAeroPQR); - PropertyManager->Tie("velocities/q-aero-rad_sec", this, eY, (PMF)&FGAuxiliary::GetAeroPQR); - PropertyManager->Tie("velocities/r-aero-rad_sec", this, eZ, (PMF)&FGAuxiliary::GetAeroPQR); - PropertyManager->Tie("velocities/phidot-rad_sec", this, ePhi, (PMF)&FGAuxiliary::GetEulerRates); - PropertyManager->Tie("velocities/thetadot-rad_sec", this, eTht, (PMF)&FGAuxiliary::GetEulerRates); - PropertyManager->Tie("velocities/psidot-rad_sec", this, ePsi, (PMF)&FGAuxiliary::GetEulerRates); - PropertyManager->Tie("velocities/u-aero-fps", this, eU, (PMF)&FGAuxiliary::GetAeroUVW); - PropertyManager->Tie("velocities/v-aero-fps", this, eV, (PMF)&FGAuxiliary::GetAeroUVW); - PropertyManager->Tie("velocities/w-aero-fps", this, eW, (PMF)&FGAuxiliary::GetAeroUVW); - PropertyManager->Tie("velocities/vt-fps", this, &FGAuxiliary::GetVt, &FGAuxiliary::SetVt, true); - PropertyManager->Tie("velocities/mach", this, &FGAuxiliary::GetMach, &FGAuxiliary::SetMach, true); - PropertyManager->Tie("velocities/vg-fps", this, &FGAuxiliary::GetVground); - PropertyManager->Tie("accelerations/a-pilot-x-ft_sec2", this, eX, (PMF)&FGAuxiliary::GetPilotAccel); - PropertyManager->Tie("accelerations/a-pilot-y-ft_sec2", this, eY, (PMF)&FGAuxiliary::GetPilotAccel); - PropertyManager->Tie("accelerations/a-pilot-z-ft_sec2", this, eZ, (PMF)&FGAuxiliary::GetPilotAccel); - PropertyManager->Tie("accelerations/n-pilot-x-norm", this, eX, (PMF)&FGAuxiliary::GetNpilot); - PropertyManager->Tie("accelerations/n-pilot-y-norm", this, eY, (PMF)&FGAuxiliary::GetNpilot); - PropertyManager->Tie("accelerations/n-pilot-z-norm", this, eZ, (PMF)&FGAuxiliary::GetNpilot); - PropertyManager->Tie("accelerations/Nz", this, &FGAuxiliary::GetNz); - /* PropertyManager->Tie("atmosphere/headwind-fps", this, &FGAuxiliary::GetHeadWind, true); - PropertyManager->Tie("atmosphere/crosswind-fps", this, &FGAuxiliary::GetCrossWind, true); */ - PropertyManager->Tie("aero/alpha-rad", this, (PF)&FGAuxiliary::Getalpha, &FGAuxiliary::Setalpha, true); - PropertyManager->Tie("aero/beta-rad", this, (PF)&FGAuxiliary::Getbeta, &FGAuxiliary::Setbeta, true); - PropertyManager->Tie("aero/mag-beta-rad", this, (PF)&FGAuxiliary::GetMagBeta); - PropertyManager->Tie("aero/alpha-deg", this, inDegrees, (PMF)&FGAuxiliary::Getalpha); - PropertyManager->Tie("aero/beta-deg", this, inDegrees, (PMF)&FGAuxiliary::Getbeta); - PropertyManager->Tie("aero/mag-beta-deg", this, inDegrees, (PMF)&FGAuxiliary::GetMagBeta); - PropertyManager->Tie("aero/Re", this, &FGAuxiliary::GetReynoldsNumber); - PropertyManager->Tie("aero/qbar-psf", this, &FGAuxiliary::Getqbar, &FGAuxiliary::Setqbar, true); - PropertyManager->Tie("aero/qbarUW-psf", this, &FGAuxiliary::GetqbarUW, &FGAuxiliary::SetqbarUW, true); - PropertyManager->Tie("aero/qbarUV-psf", this, &FGAuxiliary::GetqbarUV, &FGAuxiliary::SetqbarUV, true); - PropertyManager->Tie("aero/alphadot-rad_sec", this, (PF)&FGAuxiliary::Getadot, &FGAuxiliary::Setadot, true); - PropertyManager->Tie("aero/betadot-rad_sec", this, (PF)&FGAuxiliary::Getbdot, &FGAuxiliary::Setbdot, true); - PropertyManager->Tie("aero/alphadot-deg_sec", this, inDegrees, (PMF)&FGAuxiliary::Getadot); - PropertyManager->Tie("aero/betadot-deg_sec", this, inDegrees, (PMF)&FGAuxiliary::Getbdot); - PropertyManager->Tie("aero/h_b-cg-ft", this, &FGAuxiliary::GetHOverBCG); - PropertyManager->Tie("aero/h_b-mac-ft", this, &FGAuxiliary::GetHOverBMAC); - PropertyManager->Tie("flight-path/gamma-rad", this, &FGAuxiliary::GetGamma, &FGAuxiliary::SetGamma); - PropertyManager->Tie("flight-path/psi-gt-rad", this, &FGAuxiliary::GetGroundTrack); - - PropertyManager->Tie("position/distance-from-start-lon-mt", this, &FGAuxiliary::GetLongitudeRelativePosition); - PropertyManager->Tie("position/distance-from-start-lat-mt", this, &FGAuxiliary::GetLatitudeRelativePosition); - PropertyManager->Tie("position/distance-from-start-mag-mt", this, &FGAuxiliary::GetDistanceRelativePosition); - PropertyManager->Tie("position/vrp-gc-latitude_deg", &vLocationVRP, &FGLocation::GetLatitudeDeg); - PropertyManager->Tie("position/vrp-longitude_deg", &vLocationVRP, &FGLocation::GetLongitudeDeg); - PropertyManager->Tie("position/vrp-radius-ft", &vLocationVRP, &FGLocation::GetRadius); + typedef double (FGAuxiliary::*PMF)(int) const; + typedef double (FGAuxiliary::*PF)(void) const; + PropertyManager->Tie("propulsion/tat-r", this, &FGAuxiliary::GetTotalTemperature); + PropertyManager->Tie("propulsion/tat-c", this, &FGAuxiliary::GetTAT_C); + PropertyManager->Tie("propulsion/pt-lbs_sqft", this, &FGAuxiliary::GetTotalPressure); + PropertyManager->Tie("velocities/vc-fps", this, &FGAuxiliary::GetVcalibratedFPS); + PropertyManager->Tie("velocities/vc-kts", this, &FGAuxiliary::GetVcalibratedKTS); + PropertyManager->Tie("velocities/ve-fps", this, &FGAuxiliary::GetVequivalentFPS); + PropertyManager->Tie("velocities/ve-kts", this, &FGAuxiliary::GetVequivalentKTS); + PropertyManager->Tie("velocities/machU", this, &FGAuxiliary::GetMachU); + PropertyManager->Tie("velocities/p-aero-rad_sec", this, eX, (PMF)&FGAuxiliary::GetAeroPQR); + PropertyManager->Tie("velocities/q-aero-rad_sec", this, eY, (PMF)&FGAuxiliary::GetAeroPQR); + PropertyManager->Tie("velocities/r-aero-rad_sec", this, eZ, (PMF)&FGAuxiliary::GetAeroPQR); + PropertyManager->Tie("velocities/phidot-rad_sec", this, ePhi, (PMF)&FGAuxiliary::GetEulerRates); + PropertyManager->Tie("velocities/thetadot-rad_sec", this, eTht, (PMF)&FGAuxiliary::GetEulerRates); + PropertyManager->Tie("velocities/psidot-rad_sec", this, ePsi, (PMF)&FGAuxiliary::GetEulerRates); + PropertyManager->Tie("velocities/u-aero-fps", this, eU, (PMF)&FGAuxiliary::GetAeroUVW); + PropertyManager->Tie("velocities/v-aero-fps", this, eV, (PMF)&FGAuxiliary::GetAeroUVW); + PropertyManager->Tie("velocities/w-aero-fps", this, eW, (PMF)&FGAuxiliary::GetAeroUVW); + PropertyManager->Tie("velocities/vt-fps", this, &FGAuxiliary::GetVt, &FGAuxiliary::SetVt, true); + PropertyManager->Tie("velocities/mach", this, &FGAuxiliary::GetMach, &FGAuxiliary::SetMach, true); + PropertyManager->Tie("velocities/vg-fps", this, &FGAuxiliary::GetVground); + PropertyManager->Tie("accelerations/a-pilot-x-ft_sec2", this, eX, (PMF)&FGAuxiliary::GetPilotAccel); + PropertyManager->Tie("accelerations/a-pilot-y-ft_sec2", this, eY, (PMF)&FGAuxiliary::GetPilotAccel); + PropertyManager->Tie("accelerations/a-pilot-z-ft_sec2", this, eZ, (PMF)&FGAuxiliary::GetPilotAccel); + PropertyManager->Tie("accelerations/n-pilot-x-norm", this, eX, (PMF)&FGAuxiliary::GetNpilot); + PropertyManager->Tie("accelerations/n-pilot-y-norm", this, eY, (PMF)&FGAuxiliary::GetNpilot); + PropertyManager->Tie("accelerations/n-pilot-z-norm", this, eZ, (PMF)&FGAuxiliary::GetNpilot); + PropertyManager->Tie("accelerations/Nz", this, &FGAuxiliary::GetNz); + /* PropertyManager->Tie("atmosphere/headwind-fps", this, &FGAuxiliary::GetHeadWind, true); + PropertyManager->Tie("atmosphere/crosswind-fps", this, &FGAuxiliary::GetCrossWind, true); */ + PropertyManager->Tie("aero/alpha-rad", this, (PF)&FGAuxiliary::Getalpha, &FGAuxiliary::Setalpha, true); + PropertyManager->Tie("aero/beta-rad", this, (PF)&FGAuxiliary::Getbeta, &FGAuxiliary::Setbeta, true); + PropertyManager->Tie("aero/mag-beta-rad", this, (PF)&FGAuxiliary::GetMagBeta); + PropertyManager->Tie("aero/alpha-deg", this, inDegrees, (PMF)&FGAuxiliary::Getalpha); + PropertyManager->Tie("aero/beta-deg", this, inDegrees, (PMF)&FGAuxiliary::Getbeta); + PropertyManager->Tie("aero/mag-beta-deg", this, inDegrees, (PMF)&FGAuxiliary::GetMagBeta); + PropertyManager->Tie("aero/Re", this, &FGAuxiliary::GetReynoldsNumber); + PropertyManager->Tie("aero/qbar-psf", this, &FGAuxiliary::Getqbar, &FGAuxiliary::Setqbar, true); + PropertyManager->Tie("aero/qbarUW-psf", this, &FGAuxiliary::GetqbarUW, &FGAuxiliary::SetqbarUW, true); + PropertyManager->Tie("aero/qbarUV-psf", this, &FGAuxiliary::GetqbarUV, &FGAuxiliary::SetqbarUV, true); + PropertyManager->Tie("aero/alphadot-rad_sec", this, (PF)&FGAuxiliary::Getadot, &FGAuxiliary::Setadot, true); + PropertyManager->Tie("aero/betadot-rad_sec", this, (PF)&FGAuxiliary::Getbdot, &FGAuxiliary::Setbdot, true); + PropertyManager->Tie("aero/alphadot-deg_sec", this, inDegrees, (PMF)&FGAuxiliary::Getadot); + PropertyManager->Tie("aero/betadot-deg_sec", this, inDegrees, (PMF)&FGAuxiliary::Getbdot); + PropertyManager->Tie("aero/h_b-cg-ft", this, &FGAuxiliary::GetHOverBCG); + PropertyManager->Tie("aero/h_b-mac-ft", this, &FGAuxiliary::GetHOverBMAC); + PropertyManager->Tie("flight-path/gamma-rad", this, &FGAuxiliary::GetGamma, &FGAuxiliary::SetGamma); + PropertyManager->Tie("flight-path/psi-gt-rad", this, &FGAuxiliary::GetGroundTrack); + + PropertyManager->Tie("position/distance-from-start-lon-mt", this, &FGAuxiliary::GetLongitudeRelativePosition); + PropertyManager->Tie("position/distance-from-start-lat-mt", this, &FGAuxiliary::GetLatitudeRelativePosition); + PropertyManager->Tie("position/distance-from-start-mag-mt", this, &FGAuxiliary::GetDistanceRelativePosition); + PropertyManager->Tie("position/vrp-gc-latitude_deg", &vLocationVRP, &FGLocation::GetLatitudeDeg); + PropertyManager->Tie("position/vrp-longitude_deg", &vLocationVRP, &FGLocation::GetLongitudeDeg); + PropertyManager->Tie("position/vrp-radius-ft", &vLocationVRP, &FGLocation::GetRadius); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGAuxiliary::CalculateRelativePosition(void) -{ - const double earth_radius_mt = Inertial->GetRefRadius()*fttom; - lat_relative_position=(FDMExec->GetPropagate()->GetLatitude() - FDMExec->GetIC()->GetLatitudeDegIC() *degtorad)*earth_radius_mt; - lon_relative_position=(FDMExec->GetPropagate()->GetLongitude() - FDMExec->GetIC()->GetLongitudeDegIC()*degtorad)*earth_radius_mt; - relative_position = sqrt(lat_relative_position*lat_relative_position + lon_relative_position*lon_relative_position); +{ + const double earth_radius_mt = Inertial->GetRefRadius()*fttom; + lat_relative_position=(FDMExec->GetPropagate()->GetLatitude() - FDMExec->GetIC()->GetLatitudeDegIC() *degtorad)*earth_radius_mt; + lon_relative_position=(FDMExec->GetPropagate()->GetLongitude() - FDMExec->GetIC()->GetLongitudeDegIC()*degtorad)*earth_radius_mt; + relative_position = sqrt(lat_relative_position*lat_relative_position + lon_relative_position*lon_relative_position); }; //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGAuxiliary::BadUnits(void) const { - cerr << "Bad units" << endl; - return 0.0; + cerr << "Bad units" << endl; return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -435,41 +417,33 @@ double FGAuxiliary::BadUnits(void) const void FGAuxiliary::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGAuxiliary" << endl; - if (from == 1) cout << "Destroyed: FGAuxiliary" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - if (Mach > 100 || Mach < 0.00) - cout << "FGPropagate::Mach is out of bounds: " << Mach << endl; - if (qbar > 1e6 || qbar < 0.00) - cout << "FGPropagate::qbar is out of bounds: " << qbar << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGAuxiliary" << endl; + if (from == 1) cout << "Destroyed: FGAuxiliary" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + if (Mach > 100 || Mach < 0.00) + cout << "FGPropagate::Mach is out of bounds: " << Mach << endl; + if (qbar > 1e6 || qbar < 0.00) + cout << "FGPropagate::qbar is out of bounds: " << qbar << endl; + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } // namespace JSBSim diff --git a/src/models/FGAuxiliary.h b/src/models/FGAuxiliary.h index 2f087ad1af69dda1c0c6bc663b882629ce396fef..b47734647564d2c1057375dbee8c207607d424db 100644 --- a/src/models/FGAuxiliary.h +++ b/src/models/FGAuxiliary.h @@ -54,8 +54,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -108,369 +107,181 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGAuxiliary : public FGModel -{ +class FGAuxiliary : public FGModel { public: - /** Constructor - @param Executive a pointer to the parent executive object */ - FGAuxiliary(FGFDMExec* Executive); + /** Constructor + @param Executive a pointer to the parent executive object */ + FGAuxiliary(FGFDMExec* Executive); - /// Destructor - ~FGAuxiliary(); + /// Destructor + ~FGAuxiliary(); - bool InitModel(void); + bool InitModel(void); - /** Runs the Auxiliary routines; called by the Executive - @return false if no error */ - bool Run(void); + /** Runs the Auxiliary routines; called by the Executive + @return false if no error */ + bool Run(void); // GET functions - // Atmospheric parameters GET functions - /** Returns Calibrated airspeed in feet/second.*/ - double GetVcalibratedFPS(void) const - { - return vcas; - } - /** Returns Calibrated airspeed in knots.*/ - double GetVcalibratedKTS(void) const - { - return vcas*fpstokts; - } - /** Returns equivalent airspeed in feet/second. */ - double GetVequivalentFPS(void) const - { - return veas; - } - /** Returns equivalent airspeed in knots. */ - double GetVequivalentKTS(void) const - { - return veas*fpstokts; - } - - /** Returns the total pressure. - Total pressure is freestream total pressure for - subsonic only. For supersonic it is the 1D total pressure - behind a normal shock. */ - double GetTotalPressure(void) const - { - return pt; - } - - /** Returns the total temperature. - The total temperature ("tat", isentropic flow) is calculated: - @code - tat = sat*(1 + 0.2*Mach*Mach) - @endcode - (where "sat" is standard temperature) */ - - double GetTotalTemperature(void) const - { - return tat; - } - double GetTAT_C(void) const - { - return tatc; - } - - double GetPilotAccel(int idx) const - { - return vPilotAccel(idx); - } - double GetNpilot(int idx) const - { - return vPilotAccelN(idx); - } - double GetAeroPQR(int axis) const - { - return vAeroPQR(axis); - } - double GetEulerRates(int axis) const - { - return vEulerRates(axis); - } - - const FGColumnVector3& GetPilotAccel (void) const - { - return vPilotAccel; - } - const FGColumnVector3& GetNpilot (void) const - { - return vPilotAccelN; - } - const FGColumnVector3& GetAeroPQR (void) const - { - return vAeroPQR; - } - const FGColumnVector3& GetEulerRates (void) const - { - return vEulerRates; - } - const FGColumnVector3& GetAeroUVW (void) const - { - return vAeroUVW; - } - const FGLocation& GetLocationVRP(void) const - { - return vLocationVRP; - } - - double GethVRP(void) const - { - return vLocationVRP.GetRadius() - Propagate->GetSeaLevelRadius(); - } - double GetAeroUVW (int idx) const - { - return vAeroUVW(idx); - } - double Getalpha (void) const - { - return alpha; - } - double Getbeta (void) const - { - return beta; - } - double Getadot (void) const - { - return adot; - } - double Getbdot (void) const - { - return bdot; - } - double GetMagBeta (void) const - { - return fabs(beta); - } - - double Getalpha (int unit) const - { - if (unit == inDegrees) return alpha*radtodeg; - else return BadUnits(); - } - double Getbeta (int unit) const - { - if (unit == inDegrees) return beta*radtodeg; - else return BadUnits(); - } - double Getadot (int unit) const - { - if (unit == inDegrees) return adot*radtodeg; - else return BadUnits(); - } - double Getbdot (int unit) const - { - if (unit == inDegrees) return bdot*radtodeg; - else return BadUnits(); - } - double GetMagBeta (int unit) const - { - if (unit == inDegrees) return fabs(beta)*radtodeg; - else return BadUnits(); - } - - double Getqbar (void) const - { - return qbar; - } - double GetqbarUW (void) const - { - return qbarUW; - } - double GetqbarUV (void) const - { - return qbarUV; - } - double GetReynoldsNumber(void) const - { - return Re; - } - - /** Gets the magnitude of total vehicle velocity including wind effects in feet per second. */ - double GetVt (void) const - { - return Vt; - } - - /** Gets the ground speed in feet per second. - The magnitude is the square root of the sum of the squares (RSS) of the - vehicle north and east velocity components. - @return The magnitude of the vehicle velocity in the horizontal plane. */ - double GetVground (void) const - { - return Vground; - } - - /** Gets the Mach number. */ - double GetMach (void) const - { - return Mach; - } - - /** The mach number calculated using the vehicle X axis velocity. */ - double GetMachU (void) const - { - return MachU; - } - - /** The vertical acceleration in g's of the aircraft center of gravity. */ - double GetNz (void) const - { - return Nz; - } - - double GetHOverBCG(void) const - { - return hoverbcg; - } - double GetHOverBMAC(void) const - { - return hoverbmac; - } - - double GetGamma(void) const - { - return gamma; - } - double GetGroundTrack(void) const - { - return psigt; - } - - double GetHeadWind(void) const; - double GetCrossWind(void) const; + // Atmospheric parameters GET functions + /** Returns Calibrated airspeed in feet/second.*/ + double GetVcalibratedFPS(void) const { return vcas; } + /** Returns Calibrated airspeed in knots.*/ + double GetVcalibratedKTS(void) const { return vcas*fpstokts; } + /** Returns equivalent airspeed in feet/second. */ + double GetVequivalentFPS(void) const { return veas; } + /** Returns equivalent airspeed in knots. */ + double GetVequivalentKTS(void) const { return veas*fpstokts; } + + /** Returns the total pressure. + Total pressure is freestream total pressure for + subsonic only. For supersonic it is the 1D total pressure + behind a normal shock. */ + double GetTotalPressure(void) const { return pt; } + + /** Returns the total temperature. + The total temperature ("tat", isentropic flow) is calculated: + @code + tat = sat*(1 + 0.2*Mach*Mach) + @endcode + (where "sat" is standard temperature) */ + + double GetTotalTemperature(void) const { return tat; } + double GetTAT_C(void) const { return tatc; } + + double GetPilotAccel(int idx) const { return vPilotAccel(idx); } + double GetNpilot(int idx) const { return vPilotAccelN(idx); } + double GetAeroPQR(int axis) const { return vAeroPQR(axis); } + double GetEulerRates(int axis) const { return vEulerRates(axis); } + + const FGColumnVector3& GetPilotAccel (void) const { return vPilotAccel; } + const FGColumnVector3& GetNpilot (void) const { return vPilotAccelN; } + const FGColumnVector3& GetAeroPQR (void) const { return vAeroPQR; } + const FGColumnVector3& GetEulerRates (void) const { return vEulerRates; } + const FGColumnVector3& GetAeroUVW (void) const { return vAeroUVW; } + const FGLocation& GetLocationVRP(void) const { return vLocationVRP; } + + double GethVRP(void) const { return vLocationVRP.GetRadius() - Propagate->GetSeaLevelRadius(); } + double GetAeroUVW (int idx) const { return vAeroUVW(idx); } + double Getalpha (void) const { return alpha; } + double Getbeta (void) const { return beta; } + double Getadot (void) const { return adot; } + double Getbdot (void) const { return bdot; } + double GetMagBeta (void) const { return fabs(beta); } + + double Getalpha (int unit) const { if (unit == inDegrees) return alpha*radtodeg; + else return BadUnits(); } + double Getbeta (int unit) const { if (unit == inDegrees) return beta*radtodeg; + else return BadUnits(); } + double Getadot (int unit) const { if (unit == inDegrees) return adot*radtodeg; + else return BadUnits(); } + double Getbdot (int unit) const { if (unit == inDegrees) return bdot*radtodeg; + else return BadUnits(); } + double GetMagBeta (int unit) const { if (unit == inDegrees) return fabs(beta)*radtodeg; + else return BadUnits(); } + + double Getqbar (void) const { return qbar; } + double GetqbarUW (void) const { return qbarUW; } + double GetqbarUV (void) const { return qbarUV; } + double GetReynoldsNumber(void) const { return Re; } + + /** Gets the magnitude of total vehicle velocity including wind effects in feet per second. */ + double GetVt (void) const { return Vt; } + + /** Gets the ground speed in feet per second. + The magnitude is the square root of the sum of the squares (RSS) of the + vehicle north and east velocity components. + @return The magnitude of the vehicle velocity in the horizontal plane. */ + double GetVground (void) const { return Vground; } + + /** Gets the Mach number. */ + double GetMach (void) const { return Mach; } + + /** The mach number calculated using the vehicle X axis velocity. */ + double GetMachU (void) const { return MachU; } + + /** The vertical acceleration in g's of the aircraft center of gravity. */ + double GetNz (void) const { return Nz; } + + double GetHOverBCG(void) const { return hoverbcg; } + double GetHOverBMAC(void) const { return hoverbmac; } + + double GetGamma(void) const { return gamma; } + double GetGroundTrack(void) const { return psigt; } + + double GetHeadWind(void) const; + double GetCrossWind(void) const; // SET functions - void SetAeroUVW(FGColumnVector3 tt) - { - vAeroUVW = tt; - } - - void Setalpha (double tt) - { - alpha = tt; - } - void Setbeta (double tt) - { - beta = tt; - } - void Setqbar (double tt) - { - qbar = tt; - } - void SetqbarUW (double tt) - { - qbarUW = tt; - } - void SetqbarUV (double tt) - { - qbarUV = tt; - } - void SetVt (double tt) - { - Vt = tt; - } - void SetMach (double tt) - { - Mach=tt; - } - void Setadot (double tt) - { - adot = tt; - } - void Setbdot (double tt) - { - bdot = tt; - } - - void SetAB (double t1, double t2) - { - alpha=t1; - beta=t2; - } - void SetGamma (double tt) - { - gamma = tt; - } + void SetAeroUVW(FGColumnVector3 tt) { vAeroUVW = tt; } + + void Setalpha (double tt) { alpha = tt; } + void Setbeta (double tt) { beta = tt; } + void Setqbar (double tt) { qbar = tt; } + void SetqbarUW (double tt) { qbarUW = tt; } + void SetqbarUV (double tt) { qbarUV = tt; } + void SetVt (double tt) { Vt = tt; } + void SetMach (double tt) { Mach=tt; } + void Setadot (double tt) { adot = tt; } + void Setbdot (double tt) { bdot = tt; } + + void SetAB (double t1, double t2) { alpha=t1; beta=t2; } + void SetGamma (double tt) { gamma = tt; } // Time routines, SET and GET functions, used by FGMSIS atmosphere - void SetDayOfYear (int doy) - { - day_of_year = doy; - } - void SetSecondsInDay (double sid) - { - seconds_in_day = sid; - } - - int GetDayOfYear (void) const - { - return day_of_year; - } - double GetSecondsInDay (void) const - { - return seconds_in_day; - } - - double GetLongitudeRelativePosition (void) const - { - return lon_relative_position; - } - double GetLatitudeRelativePosition (void) const - { - return lat_relative_position; - } - double GetDistanceRelativePosition (void) const - { - return relative_position; - } - - void SetAeroPQR(FGColumnVector3 tt) - { - vAeroPQR = tt; - } + void SetDayOfYear (int doy) { day_of_year = doy; } + void SetSecondsInDay (double sid) { seconds_in_day = sid; } + + int GetDayOfYear (void) const { return day_of_year; } + double GetSecondsInDay (void) const { return seconds_in_day; } + + double GetLongitudeRelativePosition (void) const { return lon_relative_position; } + double GetLatitudeRelativePosition (void) const { return lat_relative_position; } + double GetDistanceRelativePosition (void) const { return relative_position; } + + void SetAeroPQR(FGColumnVector3 tt) { vAeroPQR = tt; } private: - double vcas, veas; - double rhosl, rho, p, psl, pt, tat, sat, tatc; // Don't add a getter for pt! - - FGColumnVector3 vPilotAccel; - FGColumnVector3 vPilotAccelN; - FGColumnVector3 vToEyePt; - FGColumnVector3 vAeroPQR; - FGColumnVector3 vAeroUVW; - FGColumnVector3 vEuler; - FGColumnVector3 vEulerRates; - FGColumnVector3 vMachUVW; - FGColumnVector3 vAircraftAccel; - FGLocation vLocationVRP; - - double Vt, Vground, Mach, MachU; - double qbar, qbarUW, qbarUV; - double Re; // Reynolds Number = V*c/mu - double alpha, beta; - double adot,bdot; - double psigt, gamma; - double Nz; - double seconds_in_day; // seconds since current GMT day began - int day_of_year; // GMT day, 1 .. 366 - - double hoverbcg, hoverbmac; - - // helper data, calculation of distance from initial position - - double lon_relative_position; - double lat_relative_position; - double relative_position; - - void CalculateRelativePosition(void); - - void bind(void); - double BadUnits(void) const; - void Debug(int from); + double vcas, veas; + double rhosl, rho, p, psl, pt, tat, sat, tatc; // Don't add a getter for pt! + + FGColumnVector3 vPilotAccel; + FGColumnVector3 vPilotAccelN; + FGColumnVector3 vToEyePt; + FGColumnVector3 vAeroPQR; + FGColumnVector3 vAeroUVW; + FGColumnVector3 vEuler; + FGColumnVector3 vEulerRates; + FGColumnVector3 vMachUVW; + FGColumnVector3 vAircraftAccel; + FGLocation vLocationVRP; + + double Vt, Vground, Mach, MachU; + double qbar, qbarUW, qbarUV; + double Re; // Reynolds Number = V*c/mu + double alpha, beta; + double adot,bdot; + double psigt, gamma; + double Nz; + double seconds_in_day; // seconds since current GMT day began + int day_of_year; // GMT day, 1 .. 366 + + double hoverbcg, hoverbmac; + + // helper data, calculation of distance from initial position + + double lon_relative_position; + double lat_relative_position; + double relative_position; + + void CalculateRelativePosition(void); + + void bind(void); + double BadUnits(void) const; + void Debug(int from); }; } // namespace JSBSim diff --git a/src/models/FGBuoyantForces.cpp b/src/models/FGBuoyantForces.cpp index c0c1a27cd8b23f06985276d964014ec451001413..1b9a63b74e5907eada749fa3607951babeee0afd 100644 --- a/src/models/FGBuoyantForces.cpp +++ b/src/models/FGBuoyantForces.cpp @@ -43,10 +43,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.12 2010/05/07 18:59:55 andgi Exp $"; +static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.13 2010/09/07 00:40:03 jberndt Exp $"; static const char *IdHdr = ID_BUOYANTFORCES; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -55,234 +54,225 @@ CLASS IMPLEMENTATION FGBuoyantForces::FGBuoyantForces(FGFDMExec* FDMExec) : FGModel(FDMExec) { - Name = "FGBuoyantForces"; + Name = "FGBuoyantForces"; - NoneDefined = true; + NoneDefined = true; - vTotalForces.InitMatrix(); - vTotalMoments.InitMatrix(); + vTotalForces.InitMatrix(); + vTotalMoments.InitMatrix(); - gasCellJ.InitMatrix(); + gasCellJ.InitMatrix(); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGBuoyantForces::~FGBuoyantForces() { - for (unsigned int i=0; i<Cells.size(); i++) delete Cells[i]; - Cells.clear(); + for (unsigned int i=0; i<Cells.size(); i++) delete Cells[i]; + Cells.clear(); - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGBuoyantForces::InitModel(void) { - if (!FGModel::InitModel()) return false; + if (!FGModel::InitModel()) return false; - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGBuoyantForces::Run(void) { - if (FGModel::Run()) return true; - if (FDMExec->Holding()) return false; // if paused don't execute - if (NoneDefined) return true; + if (FGModel::Run()) return true; + if (FDMExec->Holding()) return false; // if paused don't execute + if (NoneDefined) return true; - RunPreFunctions(); + RunPreFunctions(); - vTotalForces.InitMatrix(); - vTotalMoments.InitMatrix(); + vTotalForces.InitMatrix(); + vTotalMoments.InitMatrix(); - for (unsigned int i=0; i<Cells.size(); i++) - { - Cells[i]->Calculate(FDMExec->GetDeltaT()); - vTotalForces += Cells[i]->GetBodyForces(); - vTotalMoments += Cells[i]->GetMoments(); - } + for (unsigned int i=0; i<Cells.size(); i++) { + Cells[i]->Calculate(FDMExec->GetDeltaT()); + vTotalForces += Cells[i]->GetBodyForces(); + vTotalMoments += Cells[i]->GetMoments(); + } - RunPostFunctions(); + RunPostFunctions(); - return false; + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGBuoyantForces::Load(Element *element) { - string fname="", file=""; - Element *gas_cell_element; + string fname="", file=""; + Element *gas_cell_element; - Debug(2); + Debug(2); - string separator = "/"; + string separator = "/"; - fname = element->GetAttributeValue("file"); - if (!fname.empty()) - { - file = FDMExec->GetFullAircraftPath() + separator + fname; - document = LoadXMLDocument(file); - } - else - { - document = element; - } + fname = element->GetAttributeValue("file"); + if (!fname.empty()) { + file = FDMExec->GetFullAircraftPath() + separator + fname; + document = LoadXMLDocument(file); + } else { + document = element; + } - FGModel::Load(element); // Perform base class Load + FGModel::Load(element); // Perform base class Load - gas_cell_element = document->FindElement("gas_cell"); - while (gas_cell_element) - { - NoneDefined = false; - Cells.push_back(new FGGasCell(FDMExec, gas_cell_element, Cells.size())); - gas_cell_element = document->FindNextElement("gas_cell"); - } - - FGModel::PostLoad(element); + gas_cell_element = document->FindElement("gas_cell"); + while (gas_cell_element) { + NoneDefined = false; + Cells.push_back(new FGGasCell(FDMExec, gas_cell_element, Cells.size())); + gas_cell_element = document->FindNextElement("gas_cell"); + } + + PostLoad(element, PropertyManager); - if (!NoneDefined) - { - bind(); - } + if (!NoneDefined) { + bind(); + } - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGBuoyantForces::GetGasMass(void) { - double Gw = 0.0; + double Gw = 0.0; - for (unsigned int i = 0; i < Cells.size(); i++) - { - Gw += Cells[i]->GetMass(); - } + for (unsigned int i = 0; i < Cells.size(); i++) { + Gw += Cells[i]->GetMass(); + } - return Gw; + return Gw; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% const FGColumnVector3& FGBuoyantForces::GetGasMassMoment(void) { - vXYZgasCell_arm.InitMatrix(); - for (unsigned int i = 0; i < Cells.size(); i++) - { - vXYZgasCell_arm += Cells[i]->GetMassMoment(); - } - return vXYZgasCell_arm; + vXYZgasCell_arm.InitMatrix(); + for (unsigned int i = 0; i < Cells.size(); i++) { + vXYZgasCell_arm += Cells[i]->GetMassMoment(); + } + return vXYZgasCell_arm; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% const FGMatrix33& FGBuoyantForces::GetGasMassInertia(void) { - const unsigned int size = Cells.size(); - - if (size == 0) return gasCellJ; - - gasCellJ = FGMatrix33(); - - for (unsigned int i=0; i < size; i++) - { - FGColumnVector3 v = MassBalance->StructuralToBody( Cells[i]->GetXYZ() ); - // Body basis is in FT. - const double mass = Cells[i]->GetMass(); - - // FIXME: Verify that this is the correct way to change between the - // coordinate frames. - gasCellJ += Cells[i]->GetInertia() + - FGMatrix33( 0, - mass*v(1)*v(2), - mass*v(1)*v(3), - - mass*v(2)*v(1), 0, - mass*v(2)*v(3), - - mass*v(3)*v(1), - mass*v(3)*v(2), 0 ); - } - - return gasCellJ; + const unsigned int size = Cells.size(); + + if (size == 0) return gasCellJ; + + gasCellJ = FGMatrix33(); + + for (unsigned int i=0; i < size; i++) { + FGColumnVector3 v = MassBalance->StructuralToBody( Cells[i]->GetXYZ() ); + // Body basis is in FT. + const double mass = Cells[i]->GetMass(); + + // FIXME: Verify that this is the correct way to change between the + // coordinate frames. + gasCellJ += Cells[i]->GetInertia() + + FGMatrix33( 0, - mass*v(1)*v(2), - mass*v(1)*v(3), + - mass*v(2)*v(1), 0, - mass*v(2)*v(3), + - mass*v(3)*v(1), - mass*v(3)*v(2), 0 ); + } + + return gasCellJ; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGBuoyantForces::GetBuoyancyStrings(string delimeter) { - string CoeffStrings = ""; - /* - bool firstime = true; - for (sd = 0; sd < variables.size(); sd++) { - if (firstime) { - firstime = false; - } else { - CoeffStrings += delimeter; - } - CoeffStrings += variables[sd]->GetName(); - } - - for (axis = 0; axis < 6; axis++) { - for (sd = 0; sd < Coeff[axis].size(); sd++) { - if (firstime) { - firstime = false; - } else { - CoeffStrings += delimeter; - } - CoeffStrings += Coeff[axis][sd]->GetName(); - } + string CoeffStrings = ""; +/* + bool firstime = true; + for (sd = 0; sd < variables.size(); sd++) { + if (firstime) { + firstime = false; + } else { + CoeffStrings += delimeter; + } + CoeffStrings += variables[sd]->GetName(); + } + + for (axis = 0; axis < 6; axis++) { + for (sd = 0; sd < Coeff[axis].size(); sd++) { + if (firstime) { + firstime = false; + } else { + CoeffStrings += delimeter; } - */ - return CoeffStrings; + CoeffStrings += Coeff[axis][sd]->GetName(); + } + } +*/ + return CoeffStrings; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGBuoyantForces::GetBuoyancyValues(string delimeter) { - string SDValues = ""; - /* - bool firstime = true; - for (sd = 0; sd < variables.size(); sd++) { - if (firstime) { - firstime = false; - } else { - SDValues += delimeter; - } - SDValues += variables[sd]->GetValueAsString(); - } - - for (unsigned int axis = 0; axis < 6; axis++) { - for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) { - if (firstime) { - firstime = false; - } else { - SDValues += delimeter; - } - SDValues += Coeff[axis][sd]->GetValueAsString(); - } + string SDValues = ""; +/* + bool firstime = true; + for (sd = 0; sd < variables.size(); sd++) { + if (firstime) { + firstime = false; + } else { + SDValues += delimeter; + } + SDValues += variables[sd]->GetValueAsString(); + } + + for (unsigned int axis = 0; axis < 6; axis++) { + for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) { + if (firstime) { + firstime = false; + } else { + SDValues += delimeter; } - */ - return SDValues; + SDValues += Coeff[axis][sd]->GetValueAsString(); + } + } +*/ + return SDValues; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGBuoyantForces::bind(void) { - typedef double (FGBuoyantForces::*PMF)(int) const; - PropertyManager->Tie("moments/l-buoyancy-lbsft", this, eL, - (PMF)&FGBuoyantForces::GetMoments); - PropertyManager->Tie("moments/m-buoyancy-lbsft", this, eM, - (PMF)&FGBuoyantForces::GetMoments); - PropertyManager->Tie("moments/n-buoyancy-lbsft", this, eN, - (PMF)&FGBuoyantForces::GetMoments); - PropertyManager->Tie("forces/fbx-buoyancy-lbs", this, eX, - (PMF)&FGBuoyantForces::GetForces); - PropertyManager->Tie("forces/fby-buoyancy-lbs", this, eY, - (PMF)&FGBuoyantForces::GetForces); - PropertyManager->Tie("forces/fbz-buoyancy-lbs", this, eZ, - (PMF)&FGBuoyantForces::GetForces); + typedef double (FGBuoyantForces::*PMF)(int) const; + PropertyManager->Tie("moments/l-buoyancy-lbsft", this, eL, + (PMF)&FGBuoyantForces::GetMoments); + PropertyManager->Tie("moments/m-buoyancy-lbsft", this, eM, + (PMF)&FGBuoyantForces::GetMoments); + PropertyManager->Tie("moments/n-buoyancy-lbsft", this, eN, + (PMF)&FGBuoyantForces::GetMoments); + PropertyManager->Tie("forces/fbx-buoyancy-lbs", this, eX, + (PMF)&FGBuoyantForces::GetForces); + PropertyManager->Tie("forces/fby-buoyancy-lbs", this, eY, + (PMF)&FGBuoyantForces::GetForces); + PropertyManager->Tie("forces/fbz-buoyancy-lbs", this, eZ, + (PMF)&FGBuoyantForces::GetForces); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -306,37 +296,29 @@ void FGBuoyantForces::bind(void) void FGBuoyantForces::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 2) // Loader - { - cout << endl << " Buoyant Forces: " << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGBuoyantForces" << endl; - if (from == 1) cout << "Destroyed: FGBuoyantForces" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 2) { // Loader + cout << endl << " Buoyant Forces: " << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGBuoyantForces" << endl; + if (from == 1) cout << "Destroyed: FGBuoyantForces" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } // namespace JSBSim diff --git a/src/models/FGBuoyantForces.h b/src/models/FGBuoyantForces.h index 7f2ac27c26a2d7b20053b50b4eda626ab9d53e29..c27566d3788546219e5761dfd28504e51415bc2c 100644 --- a/src/models/FGBuoyantForces.h +++ b/src/models/FGBuoyantForces.h @@ -57,8 +57,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -67,7 +66,7 @@ CLASS DOCUMENTATION /** Encapsulates the Buoyant forces calculations. This class owns and contains the list of force/coefficients that define the Buoyant properties of an air vehicle. - + Here's an example of a gas cell specification: @code @@ -85,12 +84,12 @@ CLASS DOCUMENTATION <x_radius unit="M"> 22.86 </x_radius> <y_radius unit="M"> 4.55 </y_radius> <z_radius unit="M"> 4.55 </z_radius> - <max_overpressure unit="PA"> 340.0 </max_overpressure> + <max_overpressure unit="PA"> 340.0 </max_overpressure> <valve_coefficient unit="M4*SEC/KG"> 0.015 </valve_coefficient> </gas_cell> - + ... {other gas cells} ... - + </buoyant_forces> @endcode @@ -108,93 +107,81 @@ class FGBuoyantForces : public FGModel, public FGXMLFileRead { public: - /** Constructor - @param Executive a pointer to the parent executive object */ - FGBuoyantForces(FGFDMExec* Executive); - /// Destructor - ~FGBuoyantForces(); - - bool InitModel(void); - - /** Runs the Buoyant forces model; called by the Executive - @return false if no error */ - bool Run(void); - - /** Loads the Buoyant forces model. - The Load function for this class expects the XML parser to - have found the Buoyant_forces keyword in the configuration file. - @param element pointer to the current XML element for Buoyant forces parameters. - @return true if successful */ - bool Load(Element* element); - - /** Gets the total Buoyant force vector. - @return a force vector. */ - const FGColumnVector3& GetForces(void) const - { - return vTotalForces; - } - - /** Gets a component of the total Buoyant force vector. - @return a component of the force vector. */ - double GetForces(int idx) const - { - return vTotalForces(idx); - } - - /** Gets the total Buoyancy moment vector. - @return a moment vector. */ - const FGColumnVector3& GetMoments(void) const - { - return vTotalMoments; - } - - /** Gets a component of the total Buoyancy moment vector. - @return a component of the moment vector. */ - double GetMoments(int idx) const - { - return vTotalMoments(idx); - } - - /** Gets the total gas mass. The gas mass is part of the aircraft's - inertia. - @return mass in slugs. */ - double GetGasMass(void); - - /** Gets the total moment from the gas mass. - @return a moment vector. */ - const FGColumnVector3& GetGasMassMoment(void); - - /** Gets the total moments of inertia for the gas mass. - @return . */ - const FGMatrix33& GetGasMassInertia(void); - - /** Gets the strings for the current set of gas cells. - @param delimeter either a tab or comma string depending on output type - @return a string containing the descriptive names for all parameters */ - string GetBuoyancyStrings(string delimeter); - - /** Gets the coefficient values. - @param delimeter either a tab or comma string depending on output type - @return a string containing the numeric values for the current set of - parameters */ - string GetBuoyancyValues(string delimeter); + /** Constructor + @param Executive a pointer to the parent executive object */ + FGBuoyantForces(FGFDMExec* Executive); + /// Destructor + ~FGBuoyantForces(); + + bool InitModel(void); + + /** Runs the Buoyant forces model; called by the Executive + @return false if no error */ + bool Run(void); + + /** Loads the Buoyant forces model. + The Load function for this class expects the XML parser to + have found the Buoyant_forces keyword in the configuration file. + @param element pointer to the current XML element for Buoyant forces parameters. + @return true if successful */ + bool Load(Element* element); + + /** Gets the total Buoyant force vector. + @return a force vector. */ + const FGColumnVector3& GetForces(void) const {return vTotalForces;} + + /** Gets a component of the total Buoyant force vector. + @return a component of the force vector. */ + double GetForces(int idx) const {return vTotalForces(idx);} + + /** Gets the total Buoyancy moment vector. + @return a moment vector. */ + const FGColumnVector3& GetMoments(void) const {return vTotalMoments;} + + /** Gets a component of the total Buoyancy moment vector. + @return a component of the moment vector. */ + double GetMoments(int idx) const {return vTotalMoments(idx);} + + /** Gets the total gas mass. The gas mass is part of the aircraft's + inertia. + @return mass in slugs. */ + double GetGasMass(void); + + /** Gets the total moment from the gas mass. + @return a moment vector. */ + const FGColumnVector3& GetGasMassMoment(void); + + /** Gets the total moments of inertia for the gas mass. + @return . */ + const FGMatrix33& GetGasMassInertia(void); + + /** Gets the strings for the current set of gas cells. + @param delimeter either a tab or comma string depending on output type + @return a string containing the descriptive names for all parameters */ + string GetBuoyancyStrings(string delimeter); + + /** Gets the coefficient values. + @param delimeter either a tab or comma string depending on output type + @return a string containing the numeric values for the current set of + parameters */ + string GetBuoyancyValues(string delimeter); private: - vector <FGGasCell*> Cells; - // Buoyant forces and moments. Excluding the gas weight. - FGColumnVector3 vTotalForces; - FGColumnVector3 vTotalMoments; + vector <FGGasCell*> Cells; + // Buoyant forces and moments. Excluding the gas weight. + FGColumnVector3 vTotalForces; + FGColumnVector3 vTotalMoments; - // Gas mass related masses, inertias and moments. - FGMatrix33 gasCellJ; - FGColumnVector3 vGasCellXYZ; - FGColumnVector3 vXYZgasCell_arm; + // Gas mass related masses, inertias and moments. + FGMatrix33 gasCellJ; + FGColumnVector3 vGasCellXYZ; + FGColumnVector3 vXYZgasCell_arm; - bool NoneDefined; + bool NoneDefined; - void bind(void); + void bind(void); - void Debug(int from); + void Debug(int from); }; } // namespace JSBSim diff --git a/src/models/FGExternalForce.cpp b/src/models/FGExternalForce.cpp old mode 100644 new mode 100755 index 5e01b3b591060b8228ee0c890b241e7a179fc0ba..12ade79e70ec8c9743780c6e875db758318612d1 --- a/src/models/FGExternalForce.cpp +++ b/src/models/FGExternalForce.cpp @@ -31,9 +31,9 @@ <!-- Interface properties, a.k.a. property declarations --> <property> ... </property> - + <force name="name" frame="BODY|LOCAL|WIND"> - + <function> ... </function> <location unit="units"> <!-- location --> @@ -58,8 +58,7 @@ using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGExternalForce.cpp,v 1.10 2009/10/24 22:59:30 jberndt Exp $"; static const char *IdHdr = ID_EXTERNALFORCE; @@ -68,91 +67,73 @@ static const char *IdHdr = ID_EXTERNALFORCE; FGExternalForce::FGExternalForce(FGFDMExec *FDMExec, Element *el, int index): FGForce(FDMExec) { - Element* location_element=0; - Element* direction_element=0; - Element* function_element=0; - string sFrame; - string BasePropertyName; - FGColumnVector3 location; - Magnitude_Function = 0; - magnitude = 0.0; - azimuth = 0.0; - - PropertyManager = fdmex->GetPropertyManager(); - Name = el->GetAttributeValue("name"); - BasePropertyName = "external_reactions/" + Name; - - // The value sent to the sim through the external_forces/{force name}/magnitude - // property will be multiplied against the unit vector, which can come in - // initially in the direction vector. The frame in which the vector is defined - // is specified with the frame attribute. The vector is normalized to magnitude 1. - - function_element = el->FindElement("function"); - if (function_element) - { - Magnitude_Function = new FGFunction(PropertyManager, function_element); - } - else - { - PropertyManager->Tie( BasePropertyName + "/magnitude",(FGExternalForce*)this, &FGExternalForce::GetMagnitude, &FGExternalForce::SetMagnitude); - Magnitude_Node = PropertyManager->GetNode(BasePropertyName + "/magnitude"); - } - - - // Set frame (from FGForce). - sFrame = el->GetAttributeValue("frame"); - if (sFrame.empty()) - { - cerr << "No frame specified for external force, \"" << Name << "\"." << endl; - cerr << "Frame set to Body" << endl; - ttype = tNone; - } - else if (sFrame == "BODY") - { - ttype = tNone; - } - else if (sFrame == "LOCAL") - { - ttype = tLocalBody; - PropertyManager->Tie( BasePropertyName + "/azimuth", (FGExternalForce*)this, &FGExternalForce::GetAzimuth, &FGExternalForce::SetAzimuth); - } - else if (sFrame == "WIND") - { - ttype = tWindBody; - } - else - { - cerr << "Invalid frame specified for external force, \"" << Name << "\"." << endl; - cerr << "Frame set to Body" << endl; - ttype = tNone; - } - PropertyManager->Tie( BasePropertyName + "/x", (FGExternalForce*)this, &FGExternalForce::GetX, &FGExternalForce::SetX); - PropertyManager->Tie( BasePropertyName + "/y", (FGExternalForce*)this, &FGExternalForce::GetY, &FGExternalForce::SetY); - PropertyManager->Tie( BasePropertyName + "/z", (FGExternalForce*)this, &FGExternalForce::GetZ, &FGExternalForce::SetZ); - - location_element = el->FindElement("location"); - if (!location_element) - { - cerr << "No location element specified in force object." << endl; - } - else - { - location = location_element->FindElementTripletConvertTo("IN"); - SetLocation(location); - } - - direction_element = el->FindElement("direction"); - if (!direction_element) - { - cerr << "No direction element specified in force object. Default is (0,0,0)." << endl; - } - else - { - vDirection = direction_element->FindElementTripletConvertTo("IN"); - vDirection.Normalize(); - } - - Debug(0); + Element* location_element=0; + Element* direction_element=0; + Element* function_element=0; + string sFrame; + string BasePropertyName; + FGColumnVector3 location; + Magnitude_Function = 0; + magnitude = 0.0; + azimuth = 0.0; + + PropertyManager = fdmex->GetPropertyManager(); + Name = el->GetAttributeValue("name"); + BasePropertyName = "external_reactions/" + Name; + + // The value sent to the sim through the external_forces/{force name}/magnitude + // property will be multiplied against the unit vector, which can come in + // initially in the direction vector. The frame in which the vector is defined + // is specified with the frame attribute. The vector is normalized to magnitude 1. + + function_element = el->FindElement("function"); + if (function_element) { + Magnitude_Function = new FGFunction(PropertyManager, function_element); + } else { + PropertyManager->Tie( BasePropertyName + "/magnitude",(FGExternalForce*)this, &FGExternalForce::GetMagnitude, &FGExternalForce::SetMagnitude); + Magnitude_Node = PropertyManager->GetNode(BasePropertyName + "/magnitude"); + } + + + // Set frame (from FGForce). + sFrame = el->GetAttributeValue("frame"); + if (sFrame.empty()) { + cerr << "No frame specified for external force, \"" << Name << "\"." << endl; + cerr << "Frame set to Body" << endl; + ttype = tNone; + } else if (sFrame == "BODY") { + ttype = tNone; + } else if (sFrame == "LOCAL") { + ttype = tLocalBody; + PropertyManager->Tie( BasePropertyName + "/azimuth", (FGExternalForce*)this, &FGExternalForce::GetAzimuth, &FGExternalForce::SetAzimuth); + } else if (sFrame == "WIND") { + ttype = tWindBody; + } else { + cerr << "Invalid frame specified for external force, \"" << Name << "\"." << endl; + cerr << "Frame set to Body" << endl; + ttype = tNone; + } + PropertyManager->Tie( BasePropertyName + "/x", (FGExternalForce*)this, &FGExternalForce::GetX, &FGExternalForce::SetX); + PropertyManager->Tie( BasePropertyName + "/y", (FGExternalForce*)this, &FGExternalForce::GetY, &FGExternalForce::SetY); + PropertyManager->Tie( BasePropertyName + "/z", (FGExternalForce*)this, &FGExternalForce::GetZ, &FGExternalForce::SetZ); + + location_element = el->FindElement("location"); + if (!location_element) { + cerr << "No location element specified in force object." << endl; + } else { + location = location_element->FindElementTripletConvertTo("IN"); + SetLocation(location); + } + + direction_element = el->FindElement("direction"); + if (!direction_element) { + cerr << "No direction element specified in force object. Default is (0,0,0)." << endl; + } else { + vDirection = direction_element->FindElementTripletConvertTo("IN"); + vDirection.Normalize(); + } + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -160,60 +141,55 @@ FGExternalForce::FGExternalForce(FGFDMExec *FDMExec, Element *el, int index): FG FGExternalForce::FGExternalForce(const FGExternalForce& extForce) : FGForce(extForce) { - magnitude = extForce.magnitude; - Frame = extForce.Frame; - vDirection = extForce.vDirection; - Name = extForce.Name; - BasePropertyName = extForce.BasePropertyName; - PropertyManager = extForce.PropertyManager; + magnitude = extForce.magnitude; + Frame = extForce.Frame; + vDirection = extForce.vDirection; + Name = extForce.Name; + BasePropertyName = extForce.BasePropertyName; + PropertyManager = extForce.PropertyManager; } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGExternalForce::~FGExternalForce() { - unbind( PropertyManager->GetNode("external_reactions")); - delete Magnitude_Function; - Debug(1); + unbind( PropertyManager->GetNode("external_reactions")); + delete Magnitude_Function; + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGExternalForce::SetMagnitude(double mag) { - magnitude = mag; - vFn = vDirection*mag; + magnitude = mag; + vFn = vDirection*mag; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3& FGExternalForce::GetBodyForces(void) { - if (Magnitude_Function) - { - double mag = Magnitude_Function->GetValue(); - SetMagnitude(mag); - } - - return FGForce::GetBodyForces(); + if (Magnitude_Function) { + double mag = Magnitude_Function->GetValue(); + SetMagnitude(mag); + } + + return FGForce::GetBodyForces(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGExternalForce::unbind(FGPropertyManager *node) { - int N = node->nChildren(); - for (int i=0; i<N; i++) - { - if (node->getChild(i)->nChildren() ) - { - unbind( (FGPropertyManager*)node->getChild(i) ); - } - else if ( node->getChild(i)->isTied() ) - { - node->getChild(i)->untie(); - } - } + int N = node->nChildren(); + for (int i=0; i<N; i++) { + if (node->getChild(i)->nChildren() ) { + unbind( (FGPropertyManager*)node->getChild(i) ); + } else if ( node->getChild(i)->isTied() ) { + node->getChild(i)->untie(); + } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -237,38 +213,30 @@ void FGExternalForce::unbind(FGPropertyManager *node) void FGExternalForce::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " " << Name << endl; - cout << " Frame: " << Frame << endl; - cout << " Location: (" << vXYZn(eX) << ", " << vXYZn(eY) << ", " << vXYZn(eZ) << ")" << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGExternalForce" << endl; - if (from == 1) cout << "Destroyed: FGExternalForce" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " " << Name << endl; + cout << " Frame: " << Frame << endl; + cout << " Location: (" << vXYZn(eX) << ", " << vXYZn(eY) << ", " << vXYZn(eZ) << ")" << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGExternalForce" << endl; + if (from == 1) cout << "Destroyed: FGExternalForce" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; + } + } } } diff --git a/src/models/FGExternalForce.h b/src/models/FGExternalForce.h old mode 100644 new mode 100755 index 2660179b04e0baf34714026f5e99fb9cf7450f09..f1a6a41ac73e40bd03543b59f366375e13df1453 --- a/src/models/FGExternalForce.h +++ b/src/models/FGExternalForce.h @@ -57,8 +57,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -67,7 +66,7 @@ CLASS DOCUMENTATION /** Encapsulates code that models an individual arbitrary force. This class encapsulates an individual force applied at the specified location on the vehicle, and oriented as specified in one of three frames: - + - BODY frame is defined with the X axis positive forward, the Y axis positive out the right wing, and the Z axis completing the set positive downward out the belly of the aircraft. @@ -83,15 +82,15 @@ CLASS DOCUMENTATION Much of the substance of this class is located in the FGForce base class, from which this class is derived. - + Here is the XML definition of a force (optional items are in []): - + @code <force name="name" frame="BODY | LOCAL | WIND"> - + [<function> ... </function>] - <location unit="{IN | M}"> + <location unit="{IN | M}"> <x> {number} </x> <y> {number} </y> <z> {number} </z> @@ -107,22 +106,22 @@ CLASS DOCUMENTATION The initial direction can optionally be set by specifying a unit vector in the chosen frame (body, local, or wind). The direction is specified at runtime through setting any/all of the following properties: - + @code external_reactions/{force name}/x external_reactions/{force name}/y external_reactions/{force name}/z @endcode - + As an example, a parachute can be defined oriented in the wind axis frame so the drag always acts in the drag direction - opposite the positive X axis. That does not include the effects of parachute oscillations, but those could be handled in the calling application. - + The force direction is not actually required to be specified as a unit vector, but prior to the force vector being calculated, the direction vector is normalized. - + */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -132,79 +131,52 @@ CLASS DECLARATION class FGExternalForce : public FGForce { public: - /** Constructor. - @param FDMExec pointer to the main executive class. - */ - FGExternalForce(FGFDMExec *FDMExec); - - /** Constructor. - @param FDMExec pointer to the main executive class. - @param el pointer to the XML element defining an individual force. - @param index the position of this force object in the whole list. - */ - FGExternalForce(FGFDMExec *FDMExec, Element *el, int index); - - /** Copy Constructor - @param extForce a reference to an existing FGExternalForce object - */ - FGExternalForce(const FGExternalForce& extForce); - - /// Destructor - ~FGExternalForce(); - - void SetMagnitude(double mag); - void SetAzimuth(double az) - { - azimuth = az; - } - - FGColumnVector3& GetBodyForces(void); - double GetMagnitude(void) const - { - return magnitude; - } - double GetAzimuth(void) const - { - return azimuth; - } - double GetX(void) const - { - return vDirection(eX); - } - double GetY(void) const - { - return vDirection(eY); - } - double GetZ(void) const - { - return vDirection(eZ); - } - void SetX(double x) - { - vDirection(eX) = x; - } - void SetY(double y) - { - vDirection(eY) = y; - } - void SetZ(double z) - { - vDirection(eZ) = z; - } - + /** Constructor. + @param FDMExec pointer to the main executive class. + */ + FGExternalForce(FGFDMExec *FDMExec); + + /** Constructor. + @param FDMExec pointer to the main executive class. + @param el pointer to the XML element defining an individual force. + @param index the position of this force object in the whole list. + */ + FGExternalForce(FGFDMExec *FDMExec, Element *el, int index); + + /** Copy Constructor + @param extForce a reference to an existing FGExternalForce object + */ + FGExternalForce(const FGExternalForce& extForce); + + /// Destructor + ~FGExternalForce(); + + void SetMagnitude(double mag); + void SetAzimuth(double az) {azimuth = az;} + + FGColumnVector3& GetBodyForces(void); + double GetMagnitude(void) const {return magnitude;} + double GetAzimuth(void) const {return azimuth;} + double GetX(void) const {return vDirection(eX);} + double GetY(void) const {return vDirection(eY);} + double GetZ(void) const {return vDirection(eZ);} + void SetX(double x) {vDirection(eX) = x;} + void SetY(double y) {vDirection(eY) = y;} + void SetZ(double z) {vDirection(eZ) = z;} + private: - string Frame; - string Name; - FGPropertyManager* PropertyManager; - FGPropertyManager* Magnitude_Node; - FGFunction* Magnitude_Function; - string BasePropertyName; - FGColumnVector3 vDirection; - double magnitude; - double azimuth; - void unbind(FGPropertyManager *node); - void Debug(int from); + string Frame; + string Name; + FGPropertyManager* PropertyManager; + FGPropertyManager* Magnitude_Node; + FGFunction* Magnitude_Function; + string BasePropertyName; + FGColumnVector3 vDirection; + double magnitude; + double azimuth; + void unbind(FGPropertyManager *node); + void Debug(int from); }; } #endif diff --git a/src/models/FGExternalReactions.cpp b/src/models/FGExternalReactions.cpp old mode 100644 new mode 100755 index a2036d52e2b53f9af0dfb535bfdf7a8f0ee0cf60..e39f8fb07bf2b83bed5f22d98249731ea0751807 --- a/src/models/FGExternalReactions.cpp +++ b/src/models/FGExternalReactions.cpp @@ -43,8 +43,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS @@ -54,7 +53,7 @@ DEFINITIONS GLOBAL DATA %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -static const char *IdSrc = "$Id: FGExternalReactions.cpp,v 1.8 2009/11/12 13:08:11 jberndt Exp $"; +static const char *IdSrc = "$Id: FGExternalReactions.cpp,v 1.9 2010/09/07 00:40:03 jberndt Exp $"; static const char *IdHdr = ID_EXTERNALREACTIONS; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -63,76 +62,74 @@ CLASS IMPLEMENTATION FGExternalReactions::FGExternalReactions(FGFDMExec* fdmex) : FGModel(fdmex) { - NoneDefined = true; - Debug(0); + NoneDefined = true; + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGExternalReactions::Load(Element* el) { - FGModel::Load(el); // Call the base class Load() function to load interface properties. + FGModel::Load(el); // Call the base class Load() function to load interface properties. - Debug(2); + Debug(2); - // Parse force elements + // Parse force elements - int index=0; - Element* force_element = el->FindElement("force"); - while (force_element) - { - Forces.push_back( new FGExternalForce(FDMExec, force_element, index) ); - NoneDefined = false; - index++; - force_element = el->FindNextElement("force"); - } + int index=0; + Element* force_element = el->FindElement("force"); + while (force_element) { + Forces.push_back( new FGExternalForce(FDMExec, force_element, index) ); + NoneDefined = false; + index++; + force_element = el->FindNextElement("force"); + } - FGModel::PostLoad(el); + PostLoad(el, PropertyManager); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGExternalReactions::~FGExternalReactions() { - for (unsigned int i=0; i<Forces.size(); i++) delete Forces[i]; - Forces.clear(); + for (unsigned int i=0; i<Forces.size(); i++) delete Forces[i]; + Forces.clear(); - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGExternalReactions::InitModel(void) { - if (!FGModel::InitModel()) return false; + if (!FGModel::InitModel()) return false; - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGExternalReactions::Run() { - if (FGModel::Run()) return true; - if (FDMExec->Holding()) return false; // if paused don't execute - if (NoneDefined) return true; + if (FGModel::Run()) return true; + if (FDMExec->Holding()) return false; // if paused don't execute + if (NoneDefined) return true; - RunPreFunctions(); + RunPreFunctions(); - vTotalForces.InitMatrix(); - vTotalMoments.InitMatrix(); + vTotalForces.InitMatrix(); + vTotalMoments.InitMatrix(); - for (unsigned int i=0; i<Forces.size(); i++) - { - vTotalForces += Forces[i]->GetBodyForces(); - vTotalMoments += Forces[i]->GetMoments(); - } + for (unsigned int i=0; i<Forces.size(); i++) { + vTotalForces += Forces[i]->GetBodyForces(); + vTotalMoments += Forces[i]->GetMoments(); + } - RunPostFunctions(); + RunPostFunctions(); - return false; + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -156,40 +153,31 @@ bool FGExternalReactions::Run() void FGExternalReactions::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - loading and initialization - { - } - if (from == 2) // Loading - { - cout << endl << " External Reactions: " << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGExternalReactions" << endl; - if (from == 1) cout << "Destroyed: FGExternalReactions" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - loading and initialization } - if (debug_lvl & 16) // Sanity checking - { + if (from == 2) { // Loading + cout << endl << " External Reactions: " << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGExternalReactions" << endl; + if (from == 1) cout << "Destroyed: FGExternalReactions" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } // namespace JSBSim diff --git a/src/models/FGExternalReactions.h b/src/models/FGExternalReactions.h old mode 100644 new mode 100755 index 4630c21445e501689a2857d503715287c61bf9bf..10ad35d07c62367462adc1c830a79c0350cb149e --- a/src/models/FGExternalReactions.h +++ b/src/models/FGExternalReactions.h @@ -52,8 +52,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class Element; @@ -66,21 +65,21 @@ CLASS DOCUMENTATION "arbitrary forces", because this feature can be used to model a wide variety of forces that act on a vehicle. Some examples include: parachutes, catapult, arresting hook, and tow line. - - This class acts similarly to the other "manager classes" (FGPropulsion, + + This class acts similarly to the other "manager classes" (FGPropulsion, FGFCS, FGGroundReactions, FGAerodynamics) because it manages collections of constituent forces. The individual forces are implemented with the FGExternalForce class. - + The format of the <em>optional</em> external reactions section in the config file is as follows: - + @code <external_reactions> <!-- Interface properties, a.k.a. property declarations --> <property> ... </property> - + <force name="name" frame="BODY | LOCAL | WIND" unit="unit"> ... </force> @@ -95,11 +94,11 @@ CLASS DOCUMENTATION See the FGExternalForce class for more information on the format of the force specification itself. - + When force elements are encountered in the configuration file, a new instance of the FGExternalForce class is created and a pointer to the class is pushed onto the Forces vector. - + This class is one of a few of the manager classes that allows properties to be "declared". In code, these are represented by the <em>interface_properties</em> vector. Properties that have not yet been @@ -107,7 +106,7 @@ CLASS DOCUMENTATION used in the definition of an external force should be declared in the external_reactions section because they will not be created automatically, and so would cause an error, since the property cannot be found to exist. - + See the FGExternalForce documentation for details on how forces are actually calculated. */ @@ -119,58 +118,52 @@ CLASS DECLARATION class FGExternalReactions : public FGModel { public: - /** Constructor. - @param fdmex pointer to the main executive class. - */ - FGExternalReactions(FGFDMExec* fdmex); - - /** Destructor. - Within the destructor the Forces and interface_properties vectors are - cleared out and the items pointed to are deleted. - */ - ~FGExternalReactions(void); - - bool InitModel(void); - - /** Sum all the constituent forces for this cycle. - @return true always. - */ - bool Run(void); - - /** Loads the external forces from the XML configuration file. - If the external_reactions section is encountered in the vehicle configuration - file, this Load() method is called. All external forces will be parsed, and - a FGExternalForce object will be instantiated for each force definition. - @param el a pointer to the XML element holding the external reactions definition. - */ - bool Load(Element* el); - - /** Retrieves the total forces defined in the external reactions. - @return the total force in pounds. - */ - FGColumnVector3 GetForces(void) - { - return vTotalForces; - } - - /** Retrieves the total moment resulting from the forces defined in the external reactions. - @return the total moment in foot-pounds. - */ - FGColumnVector3 GetMoments(void) - { - return vTotalMoments; - } + /** Constructor. + @param fdmex pointer to the main executive class. + */ + FGExternalReactions(FGFDMExec* fdmex); + + /** Destructor. + Within the destructor the Forces and interface_properties vectors are + cleared out and the items pointed to are deleted. + */ + ~FGExternalReactions(void); + + bool InitModel(void); + + /** Sum all the constituent forces for this cycle. + @return true always. + */ + bool Run(void); + + /** Loads the external forces from the XML configuration file. + If the external_reactions section is encountered in the vehicle configuration + file, this Load() method is called. All external forces will be parsed, and + a FGExternalForce object will be instantiated for each force definition. + @param el a pointer to the XML element holding the external reactions definition. + */ + bool Load(Element* el); + + /** Retrieves the total forces defined in the external reactions. + @return the total force in pounds. + */ + FGColumnVector3 GetForces(void) {return vTotalForces;} + + /** Retrieves the total moment resulting from the forces defined in the external reactions. + @return the total moment in foot-pounds. + */ + FGColumnVector3 GetMoments(void) {return vTotalMoments;} private: - std::vector <FGExternalForce*> Forces; - unsigned int numForces; - FGColumnVector3 vTotalForces; - FGColumnVector3 vTotalMoments; + std::vector <FGExternalForce*> Forces; + unsigned int numForces; + FGColumnVector3 vTotalForces; + FGColumnVector3 vTotalMoments; - bool NoneDefined; + bool NoneDefined; - void Debug(int from); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/FGFCS.cpp b/src/models/FGFCS.cpp index cb22104193711c24404333a92fb2a827144f11cb..368fa90ae4e63fb7067cd876c62a237ebdbdff31 100644 --- a/src/models/FGFCS.cpp +++ b/src/models/FGFCS.cpp @@ -1,6 +1,6 @@ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - Module: FGFCS.cpp + Module: FGFCS.cpp Author: Jon Berndt Date started: 12/12/98 Purpose: Model the flight controls @@ -61,10 +61,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGFCS.cpp,v 1.69 2010/08/10 12:39:07 jberndt Exp $"; +static const char *IdSrc = "$Id: FGFCS.cpp,v 1.70 2010/08/21 22:56:11 jberndt Exp $"; static const char *IdHdr = ID_FCS; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -73,126 +72,126 @@ CLASS IMPLEMENTATION FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex) { - int i; - Name = "FGFCS"; + int i; + Name = "FGFCS"; - DaCmd = DeCmd = DrCmd = DsCmd = DfCmd = DsbCmd = DspCmd = 0; - PTrimCmd = YTrimCmd = RTrimCmd = 0.0; - GearCmd = GearPos = 1; // default to gear down - LeftBrake = RightBrake = CenterBrake = 0.0; - TailhookPos = WingFoldPos = 0.0; + DaCmd = DeCmd = DrCmd = DsCmd = DfCmd = DsbCmd = DspCmd = 0; + PTrimCmd = YTrimCmd = RTrimCmd = 0.0; + GearCmd = GearPos = 1; // default to gear down + LeftBrake = RightBrake = CenterBrake = 0.0; + TailhookPos = WingFoldPos = 0.0; - bind(); - for (i=0;i<NForms;i++) - { - DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0; - DfPos[i] = DsbPos[i] = DspPos[i] = 0.0; - } + bind(); + for (i=0;i<NForms;i++) { + DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0; + DfPos[i] = DsbPos[i] = DspPos[i] = 0.0; + } - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGFCS::~FGFCS() { - ThrottleCmd.clear(); - ThrottlePos.clear(); - MixtureCmd.clear(); - MixturePos.clear(); - PropAdvanceCmd.clear(); - PropAdvance.clear(); - SteerPosDeg.clear(); - PropFeatherCmd.clear(); - PropFeather.clear(); - - unsigned int i; - - for (i=0;i<APComponents.size();i++) delete APComponents[i]; - APComponents.clear(); - for (i=0;i<FCSComponents.size();i++) delete FCSComponents[i]; - FCSComponents.clear(); - for (i=0;i<Systems.size();i++) delete Systems[i]; - Systems.clear(); - - - Debug(1); + ThrottleCmd.clear(); + ThrottlePos.clear(); + MixtureCmd.clear(); + MixturePos.clear(); + PropAdvanceCmd.clear(); + PropAdvance.clear(); + SteerPosDeg.clear(); + PropFeatherCmd.clear(); + PropFeather.clear(); + + unsigned int i; + + for (i=0;i<APComponents.size();i++) delete APComponents[i]; + APComponents.clear(); + for (i=0;i<FCSComponents.size();i++) delete FCSComponents[i]; + FCSComponents.clear(); + for (i=0;i<Systems.size();i++) delete Systems[i]; + Systems.clear(); + + + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFCS::InitModel(void) { - unsigned int i; + unsigned int i; - if (!FGModel::InitModel()) return false; + if (!FGModel::InitModel()) return false; - for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = 0.0; - for (i=0; i<MixturePos.size(); i++) MixturePos[i] = 0.0; - for (i=0; i<ThrottleCmd.size(); i++) ThrottleCmd[i] = 0.0; - for (i=0; i<MixtureCmd.size(); i++) MixtureCmd[i] = 0.0; - for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = 0.0; - for (i=0; i<PropFeather.size(); i++) PropFeather[i] = 0.0; + for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = 0.0; + for (i=0; i<MixturePos.size(); i++) MixturePos[i] = 0.0; + for (i=0; i<ThrottleCmd.size(); i++) ThrottleCmd[i] = 0.0; + for (i=0; i<MixtureCmd.size(); i++) MixtureCmd[i] = 0.0; + for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = 0.0; + for (i=0; i<PropFeather.size(); i++) PropFeather[i] = 0.0; - DaCmd = DeCmd = DrCmd = DsCmd = DfCmd = DsbCmd = DspCmd = 0; - PTrimCmd = YTrimCmd = RTrimCmd = 0.0; - TailhookPos = WingFoldPos = 0.0; + DaCmd = DeCmd = DrCmd = DsCmd = DfCmd = DsbCmd = DspCmd = 0; + PTrimCmd = YTrimCmd = RTrimCmd = 0.0; + TailhookPos = WingFoldPos = 0.0; - for (i=0;i<NForms;i++) - { - DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0; - DfPos[i] = DsbPos[i] = DspPos[i] = 0.0; - } + for (i=0;i<NForms;i++) { + DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0; + DfPos[i] = DsbPos[i] = DspPos[i] = 0.0; + } - for (unsigned int i=0; i<Systems.size(); i++) + for (unsigned int i=0; i<Systems.size(); i++) { + if (Systems[i]->GetType() == "LAG" || + Systems[i]->GetType() == "LEAD_LAG" || + Systems[i]->GetType() == "WASHOUT" || + Systems[i]->GetType() == "SECOND_ORDER_FILTER" || + Systems[i]->GetType() == "INTEGRATOR") { - if (Systems[i]->GetType() == "LAG" || - Systems[i]->GetType() == "LEAD_LAG" || - Systems[i]->GetType() == "WASHOUT" || - Systems[i]->GetType() == "SECOND_ORDER_FILTER" || - Systems[i]->GetType() == "INTEGRATOR") - { - ((FGFilter*)Systems[i])->ResetPastStates(); - } - else if (Systems[i]->GetType() == "PID" ) - { - ((FGPID*)Systems[i])->ResetPastStates(); - } + ((FGFilter*)Systems[i])->ResetPastStates(); + } else if (Systems[i]->GetType() == "PID" ) { + ((FGPID*)Systems[i])->ResetPastStates(); } + } - for (unsigned int i=0; i<FCSComponents.size(); i++) + for (unsigned int i=0; i<FCSComponents.size(); i++) { + if (FCSComponents[i]->GetType() == "LAG" || + FCSComponents[i]->GetType() == "LEAD_LAG" || + FCSComponents[i]->GetType() == "WASHOUT" || + FCSComponents[i]->GetType() == "SECOND_ORDER_FILTER" || + FCSComponents[i]->GetType() == "INTEGRATOR") { - if (FCSComponents[i]->GetType() == "LAG" || - FCSComponents[i]->GetType() == "LEAD_LAG" || - FCSComponents[i]->GetType() == "WASHOUT" || - FCSComponents[i]->GetType() == "SECOND_ORDER_FILTER" || - FCSComponents[i]->GetType() == "INTEGRATOR") - { - ((FGFilter*)FCSComponents[i])->ResetPastStates(); - } - else if (FCSComponents[i]->GetType() == "PID" ) - { - ((FGPID*)FCSComponents[i])->ResetPastStates(); - } + ((FGFilter*)FCSComponents[i])->ResetPastStates(); + } else if (FCSComponents[i]->GetType() == "PID" ) { + ((FGPID*)FCSComponents[i])->ResetPastStates(); } + } - for (unsigned int i=0; i<APComponents.size(); i++) + for (unsigned int i=0; i<APComponents.size(); i++) { + if (APComponents[i]->GetType() == "LAG" || + APComponents[i]->GetType() == "LEAD_LAG" || + APComponents[i]->GetType() == "WASHOUT" || + APComponents[i]->GetType() == "SECOND_ORDER_FILTER" || + APComponents[i]->GetType() == "INTEGRATOR") { - if (APComponents[i]->GetType() == "LAG" || - APComponents[i]->GetType() == "LEAD_LAG" || - APComponents[i]->GetType() == "WASHOUT" || - APComponents[i]->GetType() == "SECOND_ORDER_FILTER" || - APComponents[i]->GetType() == "INTEGRATOR") - { - ((FGFilter*)APComponents[i])->ResetPastStates(); - } - else if (APComponents[i]->GetType() == "PID" ) - { - ((FGPID*)APComponents[i])->ResetPastStates(); - } + ((FGFilter*)APComponents[i])->ResetPastStates(); + } else if (APComponents[i]->GetType() == "PID" ) { + ((FGPID*)APComponents[i])->ResetPastStates(); } + } - return true; + return true; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGFCS::LateBind(void) +{ + int i; + + for (i=0; i<Systems.size(); i++) Systems[i]->LateBind(); + for (i=0; i<APComponents.size(); i++) APComponents[i]->LateBind(); + for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->LateBind(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -205,842 +204,722 @@ bool FGFCS::InitModel(void) bool FGFCS::Run(void) { - unsigned int i; + unsigned int i; - if (FGModel::Run()) return true; // fast exit if nothing to do - if (FDMExec->Holding()) return false; + if (FGModel::Run()) return true; // fast exit if nothing to do + if (FDMExec->Holding()) return false; - RunPreFunctions(); + RunPreFunctions(); - for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i]; - for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i]; - for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = PropAdvanceCmd[i]; - for (i=0; i<PropFeather.size(); i++) PropFeather[i] = PropFeatherCmd[i]; + for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i]; + for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i]; + for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = PropAdvanceCmd[i]; + for (i=0; i<PropFeather.size(); i++) PropFeather[i] = PropFeatherCmd[i]; - // Set the default steering angle - for (i=0; i<SteerPosDeg.size(); i++) - { - FGLGear* gear = GroundReactions->GetGearUnit(i); - SteerPosDeg[i] = gear->GetDefaultSteerAngle( GetDsCmd() ); - } + // Set the default steering angle + for (i=0; i<SteerPosDeg.size(); i++) { + FGLGear* gear = GroundReactions->GetGearUnit(i); + SteerPosDeg[i] = gear->GetDefaultSteerAngle( GetDsCmd() ); + } - // Execute Systems in order - for (i=0; i<Systems.size(); i++) Systems[i]->Run(); + // Execute Systems in order + for (i=0; i<Systems.size(); i++) Systems[i]->Run(); - // Execute Autopilot - for (i=0; i<APComponents.size(); i++) APComponents[i]->Run(); + // Execute Autopilot + for (i=0; i<APComponents.size(); i++) APComponents[i]->Run(); - // Execute Flight Control System - for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->Run(); + // Execute Flight Control System + for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->Run(); - RunPostFunctions(); + RunPostFunctions(); - return false; + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetDaLPos( int form , double pos ) { - switch (form) - { - case ofRad: - DaLPos[ofRad] = pos; - DaLPos[ofDeg] = pos*radtodeg; - break; - case ofDeg: - DaLPos[ofRad] = pos*degtorad; - DaLPos[ofDeg] = pos; - break; - case ofNorm: - DaLPos[ofNorm] = pos; - } - DaLPos[ofMag] = fabs(DaLPos[ofRad]); + switch(form) { + case ofRad: + DaLPos[ofRad] = pos; + DaLPos[ofDeg] = pos*radtodeg; + break; + case ofDeg: + DaLPos[ofRad] = pos*degtorad; + DaLPos[ofDeg] = pos; + break; + case ofNorm: + DaLPos[ofNorm] = pos; + } + DaLPos[ofMag] = fabs(DaLPos[ofRad]); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetDaRPos( int form , double pos ) { - switch (form) - { - case ofRad: - DaRPos[ofRad] = pos; - DaRPos[ofDeg] = pos*radtodeg; - break; - case ofDeg: - DaRPos[ofRad] = pos*degtorad; - DaRPos[ofDeg] = pos; - break; - case ofNorm: - DaRPos[ofNorm] = pos; - } - DaRPos[ofMag] = fabs(DaRPos[ofRad]); + switch(form) { + case ofRad: + DaRPos[ofRad] = pos; + DaRPos[ofDeg] = pos*radtodeg; + break; + case ofDeg: + DaRPos[ofRad] = pos*degtorad; + DaRPos[ofDeg] = pos; + break; + case ofNorm: + DaRPos[ofNorm] = pos; + } + DaRPos[ofMag] = fabs(DaRPos[ofRad]); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetDePos( int form , double pos ) { - switch (form) - { - case ofRad: - DePos[ofRad] = pos; - DePos[ofDeg] = pos*radtodeg; - break; - case ofDeg: - DePos[ofRad] = pos*degtorad; - DePos[ofDeg] = pos; - break; - case ofNorm: - DePos[ofNorm] = pos; - } - DePos[ofMag] = fabs(DePos[ofRad]); + switch(form) { + case ofRad: + DePos[ofRad] = pos; + DePos[ofDeg] = pos*radtodeg; + break; + case ofDeg: + DePos[ofRad] = pos*degtorad; + DePos[ofDeg] = pos; + break; + case ofNorm: + DePos[ofNorm] = pos; + } + DePos[ofMag] = fabs(DePos[ofRad]); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetDrPos( int form , double pos ) { - switch (form) - { - case ofRad: - DrPos[ofRad] = pos; - DrPos[ofDeg] = pos*radtodeg; - break; - case ofDeg: - DrPos[ofRad] = pos*degtorad; - DrPos[ofDeg] = pos; - break; - case ofNorm: - DrPos[ofNorm] = pos; - } - DrPos[ofMag] = fabs(DrPos[ofRad]); + switch(form) { + case ofRad: + DrPos[ofRad] = pos; + DrPos[ofDeg] = pos*radtodeg; + break; + case ofDeg: + DrPos[ofRad] = pos*degtorad; + DrPos[ofDeg] = pos; + break; + case ofNorm: + DrPos[ofNorm] = pos; + } + DrPos[ofMag] = fabs(DrPos[ofRad]); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetDfPos( int form , double pos ) { - switch (form) - { - case ofRad: - DfPos[ofRad] = pos; - DfPos[ofDeg] = pos*radtodeg; - break; - case ofDeg: - DfPos[ofRad] = pos*degtorad; - DfPos[ofDeg] = pos; - break; - case ofNorm: - DfPos[ofNorm] = pos; - } - DfPos[ofMag] = fabs(DfPos[ofRad]); + switch(form) { + case ofRad: + DfPos[ofRad] = pos; + DfPos[ofDeg] = pos*radtodeg; + break; + case ofDeg: + DfPos[ofRad] = pos*degtorad; + DfPos[ofDeg] = pos; + break; + case ofNorm: + DfPos[ofNorm] = pos; + } + DfPos[ofMag] = fabs(DfPos[ofRad]); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetDsbPos( int form , double pos ) { - switch (form) - { - case ofRad: - DsbPos[ofRad] = pos; - DsbPos[ofDeg] = pos*radtodeg; - break; - case ofDeg: - DsbPos[ofRad] = pos*degtorad; - DsbPos[ofDeg] = pos; - break; - case ofNorm: - DsbPos[ofNorm] = pos; - } - DsbPos[ofMag] = fabs(DsbPos[ofRad]); + switch(form) { + case ofRad: + DsbPos[ofRad] = pos; + DsbPos[ofDeg] = pos*radtodeg; + break; + case ofDeg: + DsbPos[ofRad] = pos*degtorad; + DsbPos[ofDeg] = pos; + break; + case ofNorm: + DsbPos[ofNorm] = pos; + } + DsbPos[ofMag] = fabs(DsbPos[ofRad]); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetDspPos( int form , double pos ) { - switch (form) - { - case ofRad: - DspPos[ofRad] = pos; - DspPos[ofDeg] = pos*radtodeg; - break; - case ofDeg: - DspPos[ofRad] = pos*degtorad; - DspPos[ofDeg] = pos; - break; - case ofNorm: - DspPos[ofNorm] = pos; - } - DspPos[ofMag] = fabs(DspPos[ofRad]); + switch(form) { + case ofRad: + DspPos[ofRad] = pos; + DspPos[ofDeg] = pos*radtodeg; + break; + case ofDeg: + DspPos[ofRad] = pos*degtorad; + DspPos[ofDeg] = pos; + break; + case ofNorm: + DspPos[ofNorm] = pos; + } + DspPos[ofMag] = fabs(DspPos[ofRad]); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetThrottleCmd(int engineNum, double setting) { - unsigned int ctr; + unsigned int ctr; - if (engineNum < (int)ThrottlePos.size()) - { - if (engineNum < 0) - { - for (ctr=0;ctr<ThrottleCmd.size();ctr++) ThrottleCmd[ctr] = setting; - } - else - { - ThrottleCmd[engineNum] = setting; - } - } - else - { - cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size() - << " engines exist, but attempted throttle command is for engine " - << engineNum << endl; + if (engineNum < (int)ThrottlePos.size()) { + if (engineNum < 0) { + for (ctr=0;ctr<ThrottleCmd.size();ctr++) ThrottleCmd[ctr] = setting; + } else { + ThrottleCmd[engineNum] = setting; } + } else { + cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size() + << " engines exist, but attempted throttle command is for engine " + << engineNum << endl; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetThrottlePos(int engineNum, double setting) { - unsigned int ctr; + unsigned int ctr; - if (engineNum < (int)ThrottlePos.size()) - { - if (engineNum < 0) - { - for (ctr=0;ctr<ThrottlePos.size();ctr++) ThrottlePos[ctr] = setting; - } - else - { - ThrottlePos[engineNum] = setting; - } - } - else - { - cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size() - << " engines exist, but attempted throttle position setting is for engine " - << engineNum << endl; + if (engineNum < (int)ThrottlePos.size()) { + if (engineNum < 0) { + for (ctr=0;ctr<ThrottlePos.size();ctr++) ThrottlePos[ctr] = setting; + } else { + ThrottlePos[engineNum] = setting; } + } else { + cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size() + << " engines exist, but attempted throttle position setting is for engine " + << engineNum << endl; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGFCS::GetThrottleCmd(int engineNum) const { - if (engineNum < (int)ThrottlePos.size()) - { - if (engineNum < 0) - { - cerr << "Cannot get throttle value for ALL engines" << endl; - } - else - { - return ThrottleCmd[engineNum]; - } - } - else - { - cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size() - << " engines exist, but throttle setting for engine " << engineNum - << " is selected" << endl; + if (engineNum < (int)ThrottlePos.size()) { + if (engineNum < 0) { + cerr << "Cannot get throttle value for ALL engines" << endl; + } else { + return ThrottleCmd[engineNum]; } - return 0.0; + } else { + cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size() + << " engines exist, but throttle setting for engine " << engineNum + << " is selected" << endl; + } + return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGFCS::GetThrottlePos(int engineNum) const { - if (engineNum < (int)ThrottlePos.size()) - { - if (engineNum < 0) - { - cerr << "Cannot get throttle value for ALL engines" << endl; - } - else - { - return ThrottlePos[engineNum]; - } + if (engineNum < (int)ThrottlePos.size()) { + if (engineNum < 0) { + cerr << "Cannot get throttle value for ALL engines" << endl; + } else { + return ThrottlePos[engineNum]; } - else - { - cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size() - << " engines exist, but attempted throttle position setting is for engine " - << engineNum << endl; - } - return 0.0; + } else { + cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size() + << " engines exist, but attempted throttle position setting is for engine " + << engineNum << endl; + } + return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetMixtureCmd(int engineNum, double setting) { - unsigned int ctr; + unsigned int ctr; - if (engineNum < (int)ThrottlePos.size()) - { - if (engineNum < 0) - { - for (ctr=0;ctr<MixtureCmd.size();ctr++) MixtureCmd[ctr] = setting; - } - else - { - MixtureCmd[engineNum] = setting; - } + if (engineNum < (int)ThrottlePos.size()) { + if (engineNum < 0) { + for (ctr=0;ctr<MixtureCmd.size();ctr++) MixtureCmd[ctr] = setting; + } else { + MixtureCmd[engineNum] = setting; } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetMixturePos(int engineNum, double setting) { - unsigned int ctr; + unsigned int ctr; - if (engineNum < (int)ThrottlePos.size()) - { - if (engineNum < 0) - { - for (ctr=0;ctr<MixtureCmd.size();ctr++) MixturePos[ctr] = MixtureCmd[ctr]; - } - else - { - MixturePos[engineNum] = setting; - } + if (engineNum < (int)ThrottlePos.size()) { + if (engineNum < 0) { + for (ctr=0;ctr<MixtureCmd.size();ctr++) MixturePos[ctr] = MixtureCmd[ctr]; + } else { + MixturePos[engineNum] = setting; } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetPropAdvanceCmd(int engineNum, double setting) { - unsigned int ctr; + unsigned int ctr; - if (engineNum < (int)ThrottlePos.size()) - { - if (engineNum < 0) - { - for (ctr=0;ctr<PropAdvanceCmd.size();ctr++) PropAdvanceCmd[ctr] = setting; - } - else - { - PropAdvanceCmd[engineNum] = setting; - } + if (engineNum < (int)ThrottlePos.size()) { + if (engineNum < 0) { + for (ctr=0;ctr<PropAdvanceCmd.size();ctr++) PropAdvanceCmd[ctr] = setting; + } else { + PropAdvanceCmd[engineNum] = setting; } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetPropAdvance(int engineNum, double setting) { - unsigned int ctr; + unsigned int ctr; - if (engineNum < (int)ThrottlePos.size()) - { - if (engineNum < 0) - { - for (ctr=0;ctr<PropAdvanceCmd.size();ctr++) PropAdvance[ctr] = PropAdvanceCmd[ctr]; - } - else - { - PropAdvance[engineNum] = setting; - } + if (engineNum < (int)ThrottlePos.size()) { + if (engineNum < 0) { + for (ctr=0;ctr<PropAdvanceCmd.size();ctr++) PropAdvance[ctr] = PropAdvanceCmd[ctr]; + } else { + PropAdvance[engineNum] = setting; } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetFeatherCmd(int engineNum, bool setting) { - unsigned int ctr; + unsigned int ctr; - if (engineNum < (int)ThrottlePos.size()) - { - if (engineNum < 0) - { - for (ctr=0;ctr<PropFeatherCmd.size();ctr++) PropFeatherCmd[ctr] = setting; - } - else - { - PropFeatherCmd[engineNum] = setting; - } + if (engineNum < (int)ThrottlePos.size()) { + if (engineNum < 0) { + for (ctr=0;ctr<PropFeatherCmd.size();ctr++) PropFeatherCmd[ctr] = setting; + } else { + PropFeatherCmd[engineNum] = setting; } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::SetPropFeather(int engineNum, bool setting) { - unsigned int ctr; + unsigned int ctr; - if (engineNum < (int)ThrottlePos.size()) - { - if (engineNum < 0) - { - for (ctr=0;ctr<PropFeatherCmd.size();ctr++) PropFeather[ctr] = PropFeatherCmd[ctr]; - } - else - { - PropFeather[engineNum] = setting; - } + if (engineNum < (int)ThrottlePos.size()) { + if (engineNum < 0) { + for (ctr=0;ctr<PropFeatherCmd.size();ctr++) PropFeather[ctr] = PropFeatherCmd[ctr]; + } else { + PropFeather[engineNum] = setting; } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFCS::Load(Element* el, SystemType systype) { - string name, file, fname="", interface_property_string, parent_name; - vector <FGFCSComponent*> *Components; - Element *component_element; - Element *channel_element; + string name, file, fname="", interface_property_string, parent_name; + vector <FGFCSComponent*> *Components; + Element *component_element; + Element *channel_element; - Components=0; + Components=0; // ToDo: The handling of name and file attributes could be improved, here, // considering that a name can be in the external file, as well. - name = el->GetAttributeValue("name"); - - if (name.empty() || !el->GetAttributeValue("file").empty()) - { - fname = el->GetAttributeValue("file"); - if (systype == stSystem) - { - file = FindSystemFullPathname(fname); - } - else - { - file = FDMExec->GetFullAircraftPath() + "/" + fname + ".xml"; - } - if (fname.empty()) - { - cerr << "FCS, Autopilot, or system does not appear to be defined inline nor in a file" << endl; - return false; - } - else - { - document = LoadXMLDocument(file); - if (!document) - { - cerr << "Error loading file " << file << endl; - return false; - } - name = document->GetAttributeValue("name"); - } - } - else - { - document = el; - } - - if (document->GetName() == "autopilot") - { - Components = &APComponents; - Name = "Autopilot: " + document->GetAttributeValue("name"); - } - else if (document->GetName() == "flight_control") - { - Components = &FCSComponents; - Name = "FCS: " + document->GetAttributeValue("name"); - } - else if (document->GetName() == "system") - { - Components = &Systems; - Name = "System: " + document->GetAttributeValue("name"); - } - Debug(2); - - if (document->GetName() == "flight_control") bindModel(); - - FGModel::Load(document); // Load interface properties from document - - // After reading interface properties in a file, read properties in the local - // flight_control, autopilot, or system element. This allows general-purpose - // systems to be defined in a file, with overrides or initial loaded constants - // supplied in the relevant element of the aircraft configuration file. - - Element* property_element = 0; - - if (!fname.empty()) - { - property_element = el->FindElement("property"); - if (property_element && debug_lvl > 0) cout << endl << " Overriding properties" << endl << endl; - while (property_element) - { - double value=0.0; - if ( ! property_element->GetAttributeValue("value").empty()) - value = property_element->GetAttributeValueAsNumber("value"); - - interface_property_string = property_element->GetDataLine(); - if (PropertyManager->HasNode(interface_property_string)) - { - FGPropertyManager* node = PropertyManager->GetNode(interface_property_string); - if (debug_lvl > 0) - cout << " " << "Overriding value for property " << interface_property_string - << " (old value: " << node->getDoubleValue() << " new value: " << value << ")" << endl; - node->setDoubleValue(value); - } - else - { - interface_properties.push_back(new double(value)); - PropertyManager->Tie(interface_property_string, interface_properties.back()); - if (debug_lvl > 0) - cout << " " << interface_property_string << " (initial value: " << value << ")" << endl; - } - - property_element = el->FindNextElement("property"); - } - } - - channel_element = document->FindElement("channel"); - while (channel_element) - { - + name = el->GetAttributeValue("name"); + + if (name.empty() || !el->GetAttributeValue("file").empty()) { + fname = el->GetAttributeValue("file"); + if (systype == stSystem) { + file = FindSystemFullPathname(fname); + } else { + file = FDMExec->GetFullAircraftPath() + "/" + fname + ".xml"; + } + if (fname.empty()) { + cerr << "FCS, Autopilot, or system does not appear to be defined inline nor in a file" << endl; + return false; + } else { + document = LoadXMLDocument(file); + if (!document) { + cerr << "Error loading file " << file << endl; + return false; + } + name = document->GetAttributeValue("name"); + } + } else { + document = el; + } + + if (document->GetName() == "autopilot") { + Components = &APComponents; + Name = "Autopilot: " + document->GetAttributeValue("name"); + } else if (document->GetName() == "flight_control") { + Components = &FCSComponents; + Name = "FCS: " + document->GetAttributeValue("name"); + } else if (document->GetName() == "system") { + Components = &Systems; + Name = "System: " + document->GetAttributeValue("name"); + } + Debug(2); + + if (document->GetName() == "flight_control") bindModel(); + + FGModel::Load(document); // Load interface properties from document + + // After reading interface properties in a file, read properties in the local + // flight_control, autopilot, or system element. This allows general-purpose + // systems to be defined in a file, with overrides or initial loaded constants + // supplied in the relevant element of the aircraft configuration file. + + Element* property_element = 0; + + if (!fname.empty()) { + property_element = el->FindElement("property"); + if (property_element && debug_lvl > 0) cout << endl << " Overriding properties" << endl << endl; + while (property_element) { + double value=0.0; + if ( ! property_element->GetAttributeValue("value").empty()) + value = property_element->GetAttributeValueAsNumber("value"); + + interface_property_string = property_element->GetDataLine(); + if (PropertyManager->HasNode(interface_property_string)) { + FGPropertyManager* node = PropertyManager->GetNode(interface_property_string); if (debug_lvl > 0) - cout << endl << highint << fgblue << " Channel " - << normint << channel_element->GetAttributeValue("name") << reset << endl; - - component_element = channel_element->GetElement(); - while (component_element) - { - try - { - if ((component_element->GetName() == string("lag_filter")) || - (component_element->GetName() == string("lead_lag_filter")) || - (component_element->GetName() == string("washout_filter")) || - (component_element->GetName() == string("second_order_filter")) || - (component_element->GetName() == string("integrator")) ) - { - Components->push_back(new FGFilter(this, component_element)); - } - else if ((component_element->GetName() == string("pure_gain")) || - (component_element->GetName() == string("scheduled_gain")) || - (component_element->GetName() == string("aerosurface_scale"))) - { - Components->push_back(new FGGain(this, component_element)); - } - else if (component_element->GetName() == string("summer")) - { - Components->push_back(new FGSummer(this, component_element)); - } - else if (component_element->GetName() == string("deadband")) - { - Components->push_back(new FGDeadBand(this, component_element)); - } - else if (component_element->GetName() == string("switch")) - { - Components->push_back(new FGSwitch(this, component_element)); - } - else if (component_element->GetName() == string("kinematic")) - { - Components->push_back(new FGKinemat(this, component_element)); - } - else if (component_element->GetName() == string("fcs_function")) - { - Components->push_back(new FGFCSFunction(this, component_element)); - } - else if (component_element->GetName() == string("pid")) - { - Components->push_back(new FGPID(this, component_element)); - } - else if (component_element->GetName() == string("actuator")) - { - Components->push_back(new FGActuator(this, component_element)); - } - else if (component_element->GetName() == string("sensor")) - { - Components->push_back(new FGSensor(this, component_element)); - } - else if (component_element->GetName() == string("accelerometer")) - { - Components->push_back(new FGAccelerometer(this, component_element)); - } - else if (component_element->GetName() == string("magnetometer")) - { - Components->push_back(new FGMagnetometer(this, component_element)); - } - else if (component_element->GetName() == string("gyro")) - { - Components->push_back(new FGGyro(this, component_element)); - } - else - { - cerr << "Unknown FCS component: " << component_element->GetName() << endl; - } - } - catch (string s) - { - cerr << highint << fgred << endl << " " << s << endl; - cerr << reset << endl; - return false; - } - component_element = channel_element->GetNextElement(); - } - channel_element = document->FindNextElement("channel"); - } - - ResetParser(); - - return true; + cout << " " << "Overriding value for property " << interface_property_string + << " (old value: " << node->getDoubleValue() << " new value: " << value << ")" << endl; + node->setDoubleValue(value); + } else { + interface_properties.push_back(new double(value)); + PropertyManager->Tie(interface_property_string, interface_properties.back()); + if (debug_lvl > 0) + cout << " " << interface_property_string << " (initial value: " << value << ")" << endl; + } + + property_element = el->FindNextElement("property"); + } + } + + channel_element = document->FindElement("channel"); + while (channel_element) { + + if (debug_lvl > 0) + cout << endl << highint << fgblue << " Channel " + << normint << channel_element->GetAttributeValue("name") << reset << endl; + + component_element = channel_element->GetElement(); + while (component_element) { + try { + if ((component_element->GetName() == string("lag_filter")) || + (component_element->GetName() == string("lead_lag_filter")) || + (component_element->GetName() == string("washout_filter")) || + (component_element->GetName() == string("second_order_filter")) || + (component_element->GetName() == string("integrator")) ) + { + Components->push_back(new FGFilter(this, component_element)); + } else if ((component_element->GetName() == string("pure_gain")) || + (component_element->GetName() == string("scheduled_gain")) || + (component_element->GetName() == string("aerosurface_scale"))) + { + Components->push_back(new FGGain(this, component_element)); + } else if (component_element->GetName() == string("summer")) { + Components->push_back(new FGSummer(this, component_element)); + } else if (component_element->GetName() == string("deadband")) { + Components->push_back(new FGDeadBand(this, component_element)); + } else if (component_element->GetName() == string("switch")) { + Components->push_back(new FGSwitch(this, component_element)); + } else if (component_element->GetName() == string("kinematic")) { + Components->push_back(new FGKinemat(this, component_element)); + } else if (component_element->GetName() == string("fcs_function")) { + Components->push_back(new FGFCSFunction(this, component_element)); + } else if (component_element->GetName() == string("pid")) { + Components->push_back(new FGPID(this, component_element)); + } else if (component_element->GetName() == string("actuator")) { + Components->push_back(new FGActuator(this, component_element)); + } else if (component_element->GetName() == string("sensor")) { + Components->push_back(new FGSensor(this, component_element)); + } else if (component_element->GetName() == string("accelerometer")) { + Components->push_back(new FGAccelerometer(this, component_element)); + } else if (component_element->GetName() == string("magnetometer")) { + Components->push_back(new FGMagnetometer(this, component_element)); + } else if (component_element->GetName() == string("gyro")) { + Components->push_back(new FGGyro(this, component_element)); + } else { + cerr << "Unknown FCS component: " << component_element->GetName() << endl; + } + } catch(string s) { + cerr << highint << fgred << endl << " " << s << endl; + cerr << reset << endl; + return false; + } + component_element = channel_element->GetNextElement(); + } + channel_element = document->FindNextElement("channel"); + } + + ResetParser(); + + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGFCS::GetBrake(FGLGear::BrakeGroup bg) { - switch (bg) - { - case FGLGear::bgLeft: - return LeftBrake; - case FGLGear::bgRight: - return RightBrake; - case FGLGear::bgCenter: - return CenterBrake; - default: - cerr << "GetBrake asked to return a bogus brake value" << endl; - } - return 0.0; + switch (bg) { + case FGLGear::bgLeft: + return LeftBrake; + case FGLGear::bgRight: + return RightBrake; + case FGLGear::bgCenter: + return CenterBrake; + default: + cerr << "GetBrake asked to return a bogus brake value" << endl; + } + return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGFCS::FindSystemFullPathname(const string& sysfilename) { - string fullpath, localpath; - string system_filename = sysfilename; - string systemPath = FDMExec->GetSystemsPath(); - string aircraftPath = FDMExec->GetFullAircraftPath(); - ifstream system_file; + string fullpath, localpath; + string system_filename = sysfilename; + string systemPath = FDMExec->GetSystemsPath(); + string aircraftPath = FDMExec->GetFullAircraftPath(); + ifstream system_file; - fullpath = systemPath + "/"; - localpath = aircraftPath + "/Systems/"; + fullpath = systemPath + "/"; + localpath = aircraftPath + "/Systems/"; - if (system_filename.length() <=4 || system_filename.substr(system_filename.length()-4, 4) != ".xml") - { - system_filename.append(".xml"); - } + if (system_filename.length() <=4 || system_filename.substr(system_filename.length()-4, 4) != ".xml") { + system_filename.append(".xml"); + } - system_file.open(string(localpath + system_filename).c_str()); - if ( !system_file.is_open()) - { - system_file.open(string(fullpath + system_filename).c_str()); - if ( !system_file.is_open()) - { - cerr << " Could not open system file: " << system_filename << " in path " - << fullpath << " or " << localpath << endl; - return string(""); - } - else - { - return string(fullpath + system_filename); - } - } - return string(localpath + system_filename); + system_file.open(string(localpath + system_filename).c_str()); + if ( !system_file.is_open()) { + system_file.open(string(fullpath + system_filename).c_str()); + if ( !system_file.is_open()) { + cerr << " Could not open system file: " << system_filename << " in path " + << fullpath << " or " << localpath << endl; + return string(""); + } else { + return string(fullpath + system_filename); + } + } + return string(localpath + system_filename); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ifstream* FGFCS::FindSystemFile(const string& sysfilename) { - string fullpath, localpath; - string system_filename = sysfilename; - string systemPath = FDMExec->GetSystemsPath(); - string aircraftPath = FDMExec->GetFullAircraftPath(); - ifstream* system_file = new ifstream(); + string fullpath, localpath; + string system_filename = sysfilename; + string systemPath = FDMExec->GetSystemsPath(); + string aircraftPath = FDMExec->GetFullAircraftPath(); + ifstream* system_file = new ifstream(); - fullpath = systemPath + "/"; - localpath = aircraftPath + "/Systems/"; + fullpath = systemPath + "/"; + localpath = aircraftPath + "/Systems/"; - if (system_filename.substr(system_filename.length()-4, 4) != ".xml") - { - system_filename.append(".xml"); - } + if (system_filename.substr(system_filename.length()-4, 4) != ".xml") { + system_filename.append(".xml"); + } - system_file->open(string(localpath + system_filename).c_str()); - if ( !system_file->is_open()) - { - system_file->open(string(fullpath + system_filename).c_str()); - if ( !system_file->is_open()) - { - cerr << " Could not open system file: " << system_filename << " in path " - << fullpath << " or " << localpath << endl; - } - } - return system_file; + system_file->open(string(localpath + system_filename).c_str()); + if ( !system_file->is_open()) { + system_file->open(string(fullpath + system_filename).c_str()); + if ( !system_file->is_open()) { + cerr << " Could not open system file: " << system_filename << " in path " + << fullpath << " or " << localpath << endl; + } + } + return system_file; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGFCS::GetComponentStrings(const string& delimiter) { - unsigned int comp; - string CompStrings = ""; - bool firstime = true; - int total_count=0; + unsigned int comp; + string CompStrings = ""; + bool firstime = true; + int total_count=0; - for (unsigned int i=0; i<Systems.size(); i++) - { - if (firstime) firstime = false; - else CompStrings += delimiter; + for (unsigned int i=0; i<Systems.size(); i++) { + if (firstime) firstime = false; + else CompStrings += delimiter; - CompStrings += Systems[i]->GetName(); - total_count++; - } + CompStrings += Systems[i]->GetName(); + total_count++; + } - for (comp = 0; comp < APComponents.size(); comp++) - { - if (firstime) firstime = false; - else CompStrings += delimiter; + for (comp = 0; comp < APComponents.size(); comp++) + { + if (firstime) firstime = false; + else CompStrings += delimiter; - CompStrings += APComponents[comp]->GetName(); - total_count++; - } + CompStrings += APComponents[comp]->GetName(); + total_count++; + } - for (comp = 0; comp < FCSComponents.size(); comp++) - { - if (firstime) firstime = false; - else CompStrings += delimiter; + for (comp = 0; comp < FCSComponents.size(); comp++) { + if (firstime) firstime = false; + else CompStrings += delimiter; - CompStrings += FCSComponents[comp]->GetName(); - total_count++; - } + CompStrings += FCSComponents[comp]->GetName(); + total_count++; + } - return CompStrings; + return CompStrings; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGFCS::GetComponentValues(const string& delimiter) { - std::ostringstream buf; + std::ostringstream buf; - unsigned int comp; - bool firstime = true; - int total_count=0; + unsigned int comp; + bool firstime = true; + int total_count=0; - for (unsigned int i=0; i<Systems.size(); i++) - { - if (firstime) firstime = false; - else buf << delimiter; + for (unsigned int i=0; i<Systems.size(); i++) { + if (firstime) firstime = false; + else buf << delimiter; - buf << setprecision(9) << Systems[i]->GetOutput(); - total_count++; - } + buf << setprecision(9) << Systems[i]->GetOutput(); + total_count++; + } - for (comp = 0; comp < APComponents.size(); comp++) - { - if (firstime) firstime = false; - else buf << delimiter; + for (comp = 0; comp < APComponents.size(); comp++) { + if (firstime) firstime = false; + else buf << delimiter; - buf << setprecision(9) << APComponents[comp]->GetOutput(); - total_count++; - } + buf << setprecision(9) << APComponents[comp]->GetOutput(); + total_count++; + } - for (comp = 0; comp < FCSComponents.size(); comp++) - { - if (firstime) firstime = false; - else buf << delimiter; + for (comp = 0; comp < FCSComponents.size(); comp++) { + if (firstime) firstime = false; + else buf << delimiter; - buf << setprecision(9) << FCSComponents[comp]->GetOutput(); - total_count++; - } + buf << setprecision(9) << FCSComponents[comp]->GetOutput(); + total_count++; + } - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::AddThrottle(void) { - ThrottleCmd.push_back(0.0); - ThrottlePos.push_back(0.0); - MixtureCmd.push_back(0.0); // assume throttle and mixture are coupled - MixturePos.push_back(0.0); - PropAdvanceCmd.push_back(0.0); // assume throttle and prop pitch are coupled - PropAdvance.push_back(0.0); - PropFeatherCmd.push_back(false); - PropFeather.push_back(false); - - unsigned int num = (unsigned int)ThrottleCmd.size()-1; - bindThrottle(num); + ThrottleCmd.push_back(0.0); + ThrottlePos.push_back(0.0); + MixtureCmd.push_back(0.0); // assume throttle and mixture are coupled + MixturePos.push_back(0.0); + PropAdvanceCmd.push_back(0.0); // assume throttle and prop pitch are coupled + PropAdvance.push_back(0.0); + PropFeatherCmd.push_back(false); + PropFeather.push_back(false); + + unsigned int num = (unsigned int)ThrottleCmd.size()-1; + bindThrottle(num); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::AddGear(void) { - SteerPosDeg.push_back(0.0); + SteerPosDeg.push_back(0.0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGFCS::GetDt(void) { - return FDMExec->GetDeltaT()*rate; + return FDMExec->GetDeltaT()*rate; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::bind(void) { - PropertyManager->Tie("fcs/aileron-cmd-norm", this, &FGFCS::GetDaCmd, &FGFCS::SetDaCmd); - PropertyManager->Tie("fcs/elevator-cmd-norm", this, &FGFCS::GetDeCmd, &FGFCS::SetDeCmd); - PropertyManager->Tie("fcs/rudder-cmd-norm", this, &FGFCS::GetDrCmd, &FGFCS::SetDrCmd); - PropertyManager->Tie("fcs/flap-cmd-norm", this, &FGFCS::GetDfCmd, &FGFCS::SetDfCmd); - PropertyManager->Tie("fcs/speedbrake-cmd-norm", this, &FGFCS::GetDsbCmd, &FGFCS::SetDsbCmd); - PropertyManager->Tie("fcs/spoiler-cmd-norm", this, &FGFCS::GetDspCmd, &FGFCS::SetDspCmd); - PropertyManager->Tie("fcs/pitch-trim-cmd-norm", this, &FGFCS::GetPitchTrimCmd, &FGFCS::SetPitchTrimCmd); - PropertyManager->Tie("fcs/roll-trim-cmd-norm", this, &FGFCS::GetRollTrimCmd, &FGFCS::SetRollTrimCmd); - PropertyManager->Tie("fcs/yaw-trim-cmd-norm", this, &FGFCS::GetYawTrimCmd, &FGFCS::SetYawTrimCmd); - - PropertyManager->Tie("fcs/left-aileron-pos-rad", this, ofRad, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos); - PropertyManager->Tie("fcs/left-aileron-pos-deg", this, ofDeg, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos); - PropertyManager->Tie("fcs/left-aileron-pos-norm", this, ofNorm, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos); - PropertyManager->Tie("fcs/mag-left-aileron-pos-rad", this, ofMag, &FGFCS::GetDaLPos); - - PropertyManager->Tie("fcs/right-aileron-pos-rad", this, ofRad, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos); - PropertyManager->Tie("fcs/right-aileron-pos-deg", this, ofDeg, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos); - PropertyManager->Tie("fcs/right-aileron-pos-norm", this, ofNorm, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos); - PropertyManager->Tie("fcs/mag-right-aileron-pos-rad", this, ofMag, &FGFCS::GetDaRPos); - - PropertyManager->Tie("fcs/elevator-pos-rad", this, ofRad, &FGFCS::GetDePos, &FGFCS::SetDePos); - PropertyManager->Tie("fcs/elevator-pos-deg", this, ofDeg, &FGFCS::GetDePos, &FGFCS::SetDePos); - PropertyManager->Tie("fcs/elevator-pos-norm", this, ofNorm, &FGFCS::GetDePos, &FGFCS::SetDePos); - PropertyManager->Tie("fcs/mag-elevator-pos-rad", this, ofMag, &FGFCS::GetDePos); - - PropertyManager->Tie("fcs/rudder-pos-rad", this,ofRad, &FGFCS::GetDrPos, &FGFCS::SetDrPos); - PropertyManager->Tie("fcs/rudder-pos-deg", this,ofDeg, &FGFCS::GetDrPos, &FGFCS::SetDrPos); - PropertyManager->Tie("fcs/rudder-pos-norm", this,ofNorm, &FGFCS::GetDrPos, &FGFCS::SetDrPos); - PropertyManager->Tie("fcs/mag-rudder-pos-rad", this,ofMag, &FGFCS::GetDrPos); - - PropertyManager->Tie("fcs/flap-pos-rad", this,ofRad, &FGFCS::GetDfPos, &FGFCS::SetDfPos); - PropertyManager->Tie("fcs/flap-pos-deg", this,ofDeg, &FGFCS::GetDfPos, &FGFCS::SetDfPos); - PropertyManager->Tie("fcs/flap-pos-norm", this,ofNorm, &FGFCS::GetDfPos, &FGFCS::SetDfPos); - - PropertyManager->Tie("fcs/speedbrake-pos-rad", this,ofRad, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos); - PropertyManager->Tie("fcs/speedbrake-pos-deg", this,ofDeg, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos); - PropertyManager->Tie("fcs/speedbrake-pos-norm", this,ofNorm, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos); - PropertyManager->Tie("fcs/mag-speedbrake-pos-rad", this,ofMag, &FGFCS::GetDsbPos); - - PropertyManager->Tie("fcs/spoiler-pos-rad", this, ofRad, &FGFCS::GetDspPos, &FGFCS::SetDspPos); - PropertyManager->Tie("fcs/spoiler-pos-deg", this, ofDeg, &FGFCS::GetDspPos, &FGFCS::SetDspPos); - PropertyManager->Tie("fcs/spoiler-pos-norm", this, ofNorm, &FGFCS::GetDspPos, &FGFCS::SetDspPos); - PropertyManager->Tie("fcs/mag-spoiler-pos-rad", this, ofMag, &FGFCS::GetDspPos); - - PropertyManager->Tie("gear/gear-pos-norm", this, &FGFCS::GetGearPos, &FGFCS::SetGearPos); - PropertyManager->Tie("gear/gear-cmd-norm", this, &FGFCS::GetGearCmd, &FGFCS::SetGearCmd); - PropertyManager->Tie("fcs/left-brake-cmd-norm", this, &FGFCS::GetLBrake, &FGFCS::SetLBrake); - PropertyManager->Tie("fcs/right-brake-cmd-norm", this, &FGFCS::GetRBrake, &FGFCS::SetRBrake); - PropertyManager->Tie("fcs/center-brake-cmd-norm", this, &FGFCS::GetCBrake, &FGFCS::SetCBrake); - PropertyManager->Tie("fcs/steer-cmd-norm", this, &FGFCS::GetDsCmd, &FGFCS::SetDsCmd); - - PropertyManager->Tie("gear/tailhook-pos-norm", this, &FGFCS::GetTailhookPos, &FGFCS::SetTailhookPos); - PropertyManager->Tie("fcs/wing-fold-pos-norm", this, &FGFCS::GetWingFoldPos, &FGFCS::SetWingFoldPos); + PropertyManager->Tie("fcs/aileron-cmd-norm", this, &FGFCS::GetDaCmd, &FGFCS::SetDaCmd); + PropertyManager->Tie("fcs/elevator-cmd-norm", this, &FGFCS::GetDeCmd, &FGFCS::SetDeCmd); + PropertyManager->Tie("fcs/rudder-cmd-norm", this, &FGFCS::GetDrCmd, &FGFCS::SetDrCmd); + PropertyManager->Tie("fcs/flap-cmd-norm", this, &FGFCS::GetDfCmd, &FGFCS::SetDfCmd); + PropertyManager->Tie("fcs/speedbrake-cmd-norm", this, &FGFCS::GetDsbCmd, &FGFCS::SetDsbCmd); + PropertyManager->Tie("fcs/spoiler-cmd-norm", this, &FGFCS::GetDspCmd, &FGFCS::SetDspCmd); + PropertyManager->Tie("fcs/pitch-trim-cmd-norm", this, &FGFCS::GetPitchTrimCmd, &FGFCS::SetPitchTrimCmd); + PropertyManager->Tie("fcs/roll-trim-cmd-norm", this, &FGFCS::GetRollTrimCmd, &FGFCS::SetRollTrimCmd); + PropertyManager->Tie("fcs/yaw-trim-cmd-norm", this, &FGFCS::GetYawTrimCmd, &FGFCS::SetYawTrimCmd); + + PropertyManager->Tie("fcs/left-aileron-pos-rad", this, ofRad, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos); + PropertyManager->Tie("fcs/left-aileron-pos-deg", this, ofDeg, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos); + PropertyManager->Tie("fcs/left-aileron-pos-norm", this, ofNorm, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos); + PropertyManager->Tie("fcs/mag-left-aileron-pos-rad", this, ofMag, &FGFCS::GetDaLPos); + + PropertyManager->Tie("fcs/right-aileron-pos-rad", this, ofRad, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos); + PropertyManager->Tie("fcs/right-aileron-pos-deg", this, ofDeg, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos); + PropertyManager->Tie("fcs/right-aileron-pos-norm", this, ofNorm, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos); + PropertyManager->Tie("fcs/mag-right-aileron-pos-rad", this, ofMag, &FGFCS::GetDaRPos); + + PropertyManager->Tie("fcs/elevator-pos-rad", this, ofRad, &FGFCS::GetDePos, &FGFCS::SetDePos); + PropertyManager->Tie("fcs/elevator-pos-deg", this, ofDeg, &FGFCS::GetDePos, &FGFCS::SetDePos); + PropertyManager->Tie("fcs/elevator-pos-norm", this, ofNorm, &FGFCS::GetDePos, &FGFCS::SetDePos); + PropertyManager->Tie("fcs/mag-elevator-pos-rad", this, ofMag, &FGFCS::GetDePos); + + PropertyManager->Tie("fcs/rudder-pos-rad", this,ofRad, &FGFCS::GetDrPos, &FGFCS::SetDrPos); + PropertyManager->Tie("fcs/rudder-pos-deg", this,ofDeg, &FGFCS::GetDrPos, &FGFCS::SetDrPos); + PropertyManager->Tie("fcs/rudder-pos-norm", this,ofNorm, &FGFCS::GetDrPos, &FGFCS::SetDrPos); + PropertyManager->Tie("fcs/mag-rudder-pos-rad", this,ofMag, &FGFCS::GetDrPos); + + PropertyManager->Tie("fcs/flap-pos-rad", this,ofRad, &FGFCS::GetDfPos, &FGFCS::SetDfPos); + PropertyManager->Tie("fcs/flap-pos-deg", this,ofDeg, &FGFCS::GetDfPos, &FGFCS::SetDfPos); + PropertyManager->Tie("fcs/flap-pos-norm", this,ofNorm, &FGFCS::GetDfPos, &FGFCS::SetDfPos); + + PropertyManager->Tie("fcs/speedbrake-pos-rad", this,ofRad, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos); + PropertyManager->Tie("fcs/speedbrake-pos-deg", this,ofDeg, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos); + PropertyManager->Tie("fcs/speedbrake-pos-norm", this,ofNorm, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos); + PropertyManager->Tie("fcs/mag-speedbrake-pos-rad", this,ofMag, &FGFCS::GetDsbPos); + + PropertyManager->Tie("fcs/spoiler-pos-rad", this, ofRad, &FGFCS::GetDspPos, &FGFCS::SetDspPos); + PropertyManager->Tie("fcs/spoiler-pos-deg", this, ofDeg, &FGFCS::GetDspPos, &FGFCS::SetDspPos); + PropertyManager->Tie("fcs/spoiler-pos-norm", this, ofNorm, &FGFCS::GetDspPos, &FGFCS::SetDspPos); + PropertyManager->Tie("fcs/mag-spoiler-pos-rad", this, ofMag, &FGFCS::GetDspPos); + + PropertyManager->Tie("gear/gear-pos-norm", this, &FGFCS::GetGearPos, &FGFCS::SetGearPos); + PropertyManager->Tie("gear/gear-cmd-norm", this, &FGFCS::GetGearCmd, &FGFCS::SetGearCmd); + PropertyManager->Tie("fcs/left-brake-cmd-norm", this, &FGFCS::GetLBrake, &FGFCS::SetLBrake); + PropertyManager->Tie("fcs/right-brake-cmd-norm", this, &FGFCS::GetRBrake, &FGFCS::SetRBrake); + PropertyManager->Tie("fcs/center-brake-cmd-norm", this, &FGFCS::GetCBrake, &FGFCS::SetCBrake); + PropertyManager->Tie("fcs/steer-cmd-norm", this, &FGFCS::GetDsCmd, &FGFCS::SetDsCmd); + + PropertyManager->Tie("gear/tailhook-pos-norm", this, &FGFCS::GetTailhookPos, &FGFCS::SetTailhookPos); + PropertyManager->Tie("fcs/wing-fold-pos-norm", this, &FGFCS::GetWingFoldPos, &FGFCS::SetWingFoldPos); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1049,49 +928,47 @@ void FGFCS::bind(void) void FGFCS::bindThrottle(unsigned int num) { - string tmp; - - tmp = CreateIndexedPropertyName("fcs/throttle-cmd-norm", num); - PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetThrottleCmd, - &FGFCS::SetThrottleCmd); - tmp = CreateIndexedPropertyName("fcs/throttle-pos-norm", num); - PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetThrottlePos, - &FGFCS::SetThrottlePos); - tmp = CreateIndexedPropertyName("fcs/mixture-cmd-norm", num); - PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetMixtureCmd, - &FGFCS::SetMixtureCmd); - tmp = CreateIndexedPropertyName("fcs/mixture-pos-norm", num); - PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetMixturePos, - &FGFCS::SetMixturePos); - tmp = CreateIndexedPropertyName("fcs/advance-cmd-norm", num); - PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropAdvanceCmd, - &FGFCS::SetPropAdvanceCmd); - tmp = CreateIndexedPropertyName("fcs/advance-pos-norm", num); - PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropAdvance, - &FGFCS::SetPropAdvance); - tmp = CreateIndexedPropertyName("fcs/feather-cmd-norm", num); - PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetFeatherCmd, - &FGFCS::SetFeatherCmd); - tmp = CreateIndexedPropertyName("fcs/feather-pos-norm", num); - PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropFeather, - &FGFCS::SetPropFeather); + string tmp; + + tmp = CreateIndexedPropertyName("fcs/throttle-cmd-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetThrottleCmd, + &FGFCS::SetThrottleCmd); + tmp = CreateIndexedPropertyName("fcs/throttle-pos-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetThrottlePos, + &FGFCS::SetThrottlePos); + tmp = CreateIndexedPropertyName("fcs/mixture-cmd-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetMixtureCmd, + &FGFCS::SetMixtureCmd); + tmp = CreateIndexedPropertyName("fcs/mixture-pos-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetMixturePos, + &FGFCS::SetMixturePos); + tmp = CreateIndexedPropertyName("fcs/advance-cmd-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropAdvanceCmd, + &FGFCS::SetPropAdvanceCmd); + tmp = CreateIndexedPropertyName("fcs/advance-pos-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropAdvance, + &FGFCS::SetPropAdvance); + tmp = CreateIndexedPropertyName("fcs/feather-cmd-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetFeatherCmd, + &FGFCS::SetFeatherCmd); + tmp = CreateIndexedPropertyName("fcs/feather-pos-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropFeather, + &FGFCS::SetPropFeather); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCS::bindModel(void) { - unsigned int i; - string tmp; + unsigned int i; + string tmp; - for (i=0; i<SteerPosDeg.size(); i++) - { - if (GroundReactions->GetGearUnit(i)->GetSteerable()) - { - tmp = CreateIndexedPropertyName("fcs/steer-pos-deg", i); - PropertyManager->Tie( tmp.c_str(), this, i, &FGFCS::GetSteerPosDeg, &FGFCS::SetSteerPosDeg); - } + for (i=0; i<SteerPosDeg.size(); i++) { + if (GroundReactions->GetGearUnit(i)->GetSteerable()) { + tmp = CreateIndexedPropertyName("fcs/steer-pos-deg", i); + PropertyManager->Tie( tmp.c_str(), this, i, &FGFCS::GetSteerPosDeg, &FGFCS::SetSteerPosDeg); } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1115,37 +992,29 @@ void FGFCS::bindModel(void) void FGFCS::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 2) // Loader - { - cout << endl << " " << Name << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGFCS" << endl; - if (from == 1) cout << "Destroyed: FGFCS" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 2) { // Loader + cout << endl << " " << Name << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGFCS" << endl; + if (from == 1) cout << "Destroyed: FGFCS" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; + } + } } } diff --git a/src/models/FGFCS.h b/src/models/FGFCS.h index a44dbf9b41a7e103a37cdfc37e3bc4970e173e78..1a57835f9bee3a27fa4f11cf46891ce3cc021e54 100644 --- a/src/models/FGFCS.h +++ b/src/models/FGFCS.h @@ -51,14 +51,13 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_FCS "$Id: FGFCS.h,v 1.28 2010/01/18 13:12:25 jberndt Exp $" +#define ID_FCS "$Id: FGFCS.h,v 1.31 2010/09/22 11:33:40 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { typedef enum { ofRad=0, ofDeg, ofNorm, ofMag , NForms} OutputForm; @@ -169,7 +168,7 @@ CLASS DOCUMENTATION @property gear/tailhook-pos-norm @author Jon S. Berndt - @version $Revision: 1.28 $ + @version $Revision: 1.31 $ @see FGActuator @see FGDeadBand @see FGFCSFunction @@ -192,541 +191,383 @@ class FGFCS : public FGModel, public FGXMLFileRead { public: - /** Constructor - @param Executive a pointer to the parent executive object */ - FGFCS(FGFDMExec*); - /// Destructor - ~FGFCS(); - - bool InitModel(void); - - /** Runs the Flight Controls model; called by the Executive - @return false if no error */ - bool Run(void); - - /// @name Pilot input command retrieval - //@{ - /** Gets the aileron command. - @return aileron command in range from -1.0 - 1.0 */ - double GetDaCmd(void) const - { - return DaCmd; - } - - /** Gets the elevator command. - @return elevator command in range from -1.0 - 1.0 */ - double GetDeCmd(void) const - { - return DeCmd; - } - - /** Gets the rudder command. - @return rudder command in range from -1.0 - 1.0 */ - double GetDrCmd(void) const - { - return DrCmd; - } - - /** Gets the steering command. - @return steering command in range from -1.0 - 1.0 */ - double GetDsCmd(void) const - { - return DsCmd; - } - - /** Gets the flaps command. - @return flaps command in range from 0 to 1.0 */ - double GetDfCmd(void) const - { - return DfCmd; - } - - /** Gets the speedbrake command. - @return speedbrake command in range from 0 to 1.0 */ - double GetDsbCmd(void) const - { - return DsbCmd; - } - - /** Gets the spoiler command. - @return spoiler command in range from 0 to 1.0 */ - double GetDspCmd(void) const - { - return DspCmd; - } - - /** Gets the throttle command. - @param engine engine ID number - @return throttle command in range from 0 - 1.0 for the given engine */ - double GetThrottleCmd(int engine) const; - - /** Gets the mixture command. - @param engine engine ID number - @return mixture command in range from 0 - 1.0 for the given engine */ - double GetMixtureCmd(int engine) const - { - return MixtureCmd[engine]; - } - - /** Gets the prop pitch command. - @param engine engine ID number - @return pitch command in range from 0.0 - 1.0 for the given engine */ - double GetPropAdvanceCmd(int engine) const - { - return PropAdvanceCmd[engine]; - } - - /** Gets the prop feather command. - @param engine engine ID number - @return feather command for the given engine (on / off)*/ - bool GetFeatherCmd(int engine) const - { - return PropFeatherCmd[engine]; - } - - /** Gets the pitch trim command. - @return pitch trim command in range from -1.0 to 1.0 */ - double GetPitchTrimCmd(void) const - { - return PTrimCmd; - } - - /** Gets the rudder trim command. - @return rudder trim command in range from -1.0 - 1.0 */ - double GetYawTrimCmd(void) const - { - return YTrimCmd; - } - - /** Gets the aileron trim command. - @return aileron trim command in range from -1.0 - 1.0 */ - double GetRollTrimCmd(void) const - { - return RTrimCmd; - } - - /** Get the gear extend/retract command. 0 commands gear up, 1 down. - defaults to down. - @return the current value of the gear extend/retract command*/ - double GetGearCmd(void) const - { - return GearCmd; - } - //@} - - /// @name Aerosurface position retrieval - //@{ - /** Gets the left aileron position. - @return aileron position in radians */ - double GetDaLPos( int form = ofRad ) - const - { - return DaLPos[form]; - } - - /// @name Aerosurface position retrieval - //@{ - /** Gets the right aileron position. - @return aileron position in radians */ - double GetDaRPos( int form = ofRad ) - const - { - return DaRPos[form]; - } - - /** Gets the elevator position. - @return elevator position in radians */ - double GetDePos( int form = ofRad ) - const - { - return DePos[form]; - } - - /** Gets the rudder position. - @return rudder position in radians */ - double GetDrPos( int form = ofRad ) - const - { - return DrPos[form]; - } - - /** Gets the speedbrake position. - @return speedbrake position in radians */ - double GetDsbPos( int form = ofRad ) - const - { - return DsbPos[form]; - } - - /** Gets the spoiler position. - @return spoiler position in radians */ - double GetDspPos( int form = ofRad ) - const - { - return DspPos[form]; - } - - /** Gets the flaps position. - @return flaps position in radians */ - double GetDfPos( int form = ofRad ) - const - { - return DfPos[form]; - } - - /** Gets the throttle position. - @param engine engine ID number - @return throttle position for the given engine in range from 0 - 1.0 */ - double GetThrottlePos(int engine) const; - - /** Gets the mixture position. - @param engine engine ID number - @return mixture position for the given engine in range from 0 - 1.0 */ - double GetMixturePos(int engine) const - { - return MixturePos[engine]; - } - - /** Gets the steering position. - @return steering position in degrees */ - double GetSteerPosDeg(int gear) const - { - return SteerPosDeg[gear]; - } - - /** Gets the gear position (0 up, 1 down), defaults to down - @return gear position (0 up, 1 down) */ - double GetGearPos(void) const - { - return GearPos; - } - - /** Gets the tailhook position (0 up, 1 down) - @return tailhook position (0 up, 1 down) */ - double GetTailhookPos(void) const - { - return TailhookPos; - } - - /** Gets the wing fold position (0 unfolded, 1 folded) - @return wing fold position (0 unfolded, 1 folded) */ - double GetWingFoldPos(void) const - { - return WingFoldPos; - } - - /** Gets the prop pitch position. - @param engine engine ID number - @return prop pitch position for the given engine in range from 0 - 1.0 */ - double GetPropAdvance(int engine) const - { - return PropAdvance[engine]; - } - - /** Gets the prop feather position. - @param engine engine ID number - @return prop fether for the given engine (on / off)*/ - bool GetPropFeather(int engine) const - { - return PropFeather[engine]; - } - //@} - - /** Retrieves the State object pointer. - This is used by the FGFCS-owned components. - @return pointer to the State object */ - FGState* GetState(void) - { - return State; - } - - /** Retrieves all component names for inclusion in output stream - @param delimiter either a tab or comma string depending on output type - @return a string containing the descriptive names for all components */ - std::string GetComponentStrings(const std::string& delimiter); - - /** Retrieves all component outputs for inclusion in output stream - @param delimiter either a tab or comma string depending on output type - @return a string containing the numeric values for the current set of - component outputs */ - std::string GetComponentValues(const std::string& delimiter); - - /// @name Pilot input command setting - //@{ - /** Sets the aileron command - @param cmd aileron command */ - void SetDaCmd( double cmd ) - { - DaCmd = cmd; - } - - /** Sets the elevator command - @param cmd elevator command in percent*/ - void SetDeCmd(double cmd ) - { - DeCmd = cmd; - } - - /** Sets the rudder command - @param cmd rudder command in percent*/ - void SetDrCmd(double cmd) - { - DrCmd = cmd; - } - - /** Sets the steering command - @param cmd steering command in percent*/ - void SetDsCmd(double cmd) - { - DsCmd = cmd; - } - - /** Sets the flaps command - @param cmd flaps command in percent*/ - void SetDfCmd(double cmd) - { - DfCmd = cmd; - } - - /** Sets the speedbrake command - @param cmd speedbrake command in percent*/ - void SetDsbCmd(double cmd) - { - DsbCmd = cmd; - } - - /** Sets the spoilers command - @param cmd spoilers command in percent*/ - void SetDspCmd(double cmd) - { - DspCmd = cmd; - } - - /** Sets the pitch trim command - @param cmd pitch trim command in percent*/ - void SetPitchTrimCmd(double cmd) - { - PTrimCmd = cmd; - } - - /** Sets the rudder trim command - @param cmd rudder trim command in percent*/ - void SetYawTrimCmd(double cmd) - { - YTrimCmd = cmd; - } - - /** Sets the aileron trim command - @param cmd aileron trim command in percent*/ - void SetRollTrimCmd(double cmd) - { - RTrimCmd = cmd; - } - - /** Sets the throttle command for the specified engine - @param engine engine ID number - @param cmd normalized throttle command (0.0 - 1.0)*/ - void SetThrottleCmd(int engine, double cmd); - - /** Sets the mixture command for the specified engine - @param engine engine ID number - @param cmd normalized mixture command (0.0 - 1.0)*/ - void SetMixtureCmd(int engine, double cmd); - - /** Set the gear extend/retract command, defaults to down - @param gear command 0 for up, 1 for down */ - void SetGearCmd(double gearcmd) - { - GearCmd = gearcmd; - } - - /** Sets the propeller pitch command for the specified engine - @param engine engine ID number - @param cmd mixture command in percent (0.0 - 1.0)*/ - void SetPropAdvanceCmd(int engine, double cmd); - - /** Sets the propeller feather command for the specified engine - @param engine engine ID number - @param cmd feather (bool)*/ - void SetFeatherCmd(int engine, bool cmd); - //@} - - /// @name Aerosurface position setting - //@{ - /** Sets the left aileron position - @param cmd left aileron position in radians*/ - void SetDaLPos( int form , double pos ); - - /** Sets the right aileron position - @param cmd right aileron position in radians*/ - void SetDaRPos( int form , double pos ); - - /** Sets the elevator position - @param cmd elevator position in radians*/ - void SetDePos( int form , double pos ); - - /** Sets the rudder position - @param cmd rudder position in radians*/ - void SetDrPos( int form , double pos ); - - /** Sets the flaps position - @param cmd flaps position in radians*/ - void SetDfPos( int form , double pos ); - - /** Sets the speedbrake position - @param cmd speedbrake position in radians*/ - void SetDsbPos( int form , double pos ); - - /** Sets the spoiler position - @param cmd spoiler position in radians*/ - void SetDspPos( int form , double pos ); - - /** Sets the actual throttle setting for the specified engine - @param engine engine ID number - @param cmd normalized throttle setting (0.0 - 1.0)*/ - void SetThrottlePos(int engine, double cmd); - - /** Sets the actual mixture setting for the specified engine - @param engine engine ID number - @param cmd normalized mixture setting (0.0 - 1.0)*/ - void SetMixturePos(int engine, double cmd); - - /** Sets the steering position - @param cmd steering position in degrees*/ - void SetSteerPosDeg(int gear, double pos) - { - SteerPosDeg[gear] = pos; - } - - /** Set the gear extend/retract position, defaults to down - @param gear position 0 up, 1 down */ - void SetGearPos(double gearpos) - { - GearPos = gearpos; - } - - /** Set the tailhook position - @param tailhook position 0 up, 1 down */ - void SetTailhookPos(double hookpos) - { - TailhookPos = hookpos; - } - - /** Set the wing fold position - @param wing fold position 0 unfolded, 1 folded */ - void SetWingFoldPos(double foldpos) - { - WingFoldPos = foldpos; - } - - /** Sets the actual prop pitch setting for the specified engine - @param engine engine ID number - @param cmd prop pitch setting in percent (0.0 - 1.0)*/ - void SetPropAdvance(int engine, double cmd); - - /** Sets the actual prop feather setting for the specified engine - @param engine engine ID number - @param cmd prop fether setting (bool)*/ - void SetPropFeather(int engine, bool cmd); - //@} + /** Constructor + @param Executive a pointer to the parent executive object */ + FGFCS(FGFDMExec*); + /// Destructor + ~FGFCS(); + + bool InitModel(void); + + /** Runs the Flight Controls model; called by the Executive + @return false if no error */ + bool Run(void); + + /// @name Pilot input command retrieval + //@{ + /** Gets the aileron command. + @return aileron command in range from -1.0 - 1.0 */ + double GetDaCmd(void) const { return DaCmd; } + + /** Gets the elevator command. + @return elevator command in range from -1.0 - 1.0 */ + double GetDeCmd(void) const { return DeCmd; } + + /** Gets the rudder command. + @return rudder command in range from -1.0 - 1.0 */ + double GetDrCmd(void) const { return DrCmd; } + + /** Gets the steering command. + @return steering command in range from -1.0 - 1.0 */ + double GetDsCmd(void) const { return DsCmd; } + + /** Gets the flaps command. + @return flaps command in range from 0 to 1.0 */ + double GetDfCmd(void) const { return DfCmd; } + + /** Gets the speedbrake command. + @return speedbrake command in range from 0 to 1.0 */ + double GetDsbCmd(void) const { return DsbCmd; } + + /** Gets the spoiler command. + @return spoiler command in range from 0 to 1.0 */ + double GetDspCmd(void) const { return DspCmd; } + + /** Gets the throttle command. + @param engine engine ID number + @return throttle command in range from 0 - 1.0 for the given engine */ + double GetThrottleCmd(int engine) const; + + /** Gets the mixture command. + @param engine engine ID number + @return mixture command in range from 0 - 1.0 for the given engine */ + double GetMixtureCmd(int engine) const { return MixtureCmd[engine]; } + + /** Gets the prop pitch command. + @param engine engine ID number + @return pitch command in range from 0.0 - 1.0 for the given engine */ + double GetPropAdvanceCmd(int engine) const { return PropAdvanceCmd[engine]; } + + /** Gets the prop feather command. + @param engine engine ID number + @return feather command for the given engine (on / off)*/ + bool GetFeatherCmd(int engine) const { return PropFeatherCmd[engine]; } + + /** Gets the pitch trim command. + @return pitch trim command in range from -1.0 to 1.0 */ + double GetPitchTrimCmd(void) const { return PTrimCmd; } + + /** Gets the rudder trim command. + @return rudder trim command in range from -1.0 - 1.0 */ + double GetYawTrimCmd(void) const { return YTrimCmd; } + + /** Gets the aileron trim command. + @return aileron trim command in range from -1.0 - 1.0 */ + double GetRollTrimCmd(void) const { return RTrimCmd; } + + /** Get the gear extend/retract command. 0 commands gear up, 1 down. + defaults to down. + @return the current value of the gear extend/retract command*/ + double GetGearCmd(void) const { return GearCmd; } + //@} + + /// @name Aerosurface position retrieval + //@{ + /** Gets the left aileron position. + @return aileron position in radians */ + double GetDaLPos( int form = ofRad ) + const { return DaLPos[form]; } + + /** Gets the right aileron position. + @return aileron position in radians */ + double GetDaRPos( int form = ofRad ) + const { return DaRPos[form]; } + + /** Gets the elevator position. + @return elevator position in radians */ + double GetDePos( int form = ofRad ) + const { return DePos[form]; } + + /** Gets the rudder position. + @return rudder position in radians */ + double GetDrPos( int form = ofRad ) + const { return DrPos[form]; } + + /** Gets the speedbrake position. + @return speedbrake position in radians */ + double GetDsbPos( int form = ofRad ) + const { return DsbPos[form]; } + + /** Gets the spoiler position. + @return spoiler position in radians */ + double GetDspPos( int form = ofRad ) + const { return DspPos[form]; } + + /** Gets the flaps position. + @return flaps position in radians */ + double GetDfPos( int form = ofRad ) + const { return DfPos[form]; } + + /** Gets the throttle position. + @param engine engine ID number + @return throttle position for the given engine in range from 0 - 1.0 */ + double GetThrottlePos(int engine) const; + + /** Gets the mixture position. + @param engine engine ID number + @return mixture position for the given engine in range from 0 - 1.0 */ + double GetMixturePos(int engine) const { return MixturePos[engine]; } + + /** Gets the steering position. + @return steering position in degrees */ + double GetSteerPosDeg(int gear) const { return SteerPosDeg[gear]; } + + /** Gets the gear position (0 up, 1 down), defaults to down + @return gear position (0 up, 1 down) */ + double GetGearPos(void) const { return GearPos; } + + /** Gets the tailhook position (0 up, 1 down) + @return tailhook position (0 up, 1 down) */ + double GetTailhookPos(void) const { return TailhookPos; } + + /** Gets the wing fold position (0 unfolded, 1 folded) + @return wing fold position (0 unfolded, 1 folded) */ + double GetWingFoldPos(void) const { return WingFoldPos; } + + /** Gets the prop pitch position. + @param engine engine ID number + @return prop pitch position for the given engine in range from 0 - 1.0 */ + double GetPropAdvance(int engine) const { return PropAdvance[engine]; } + + /** Gets the prop feather position. + @param engine engine ID number + @return prop fether for the given engine (on / off)*/ + bool GetPropFeather(int engine) const { return PropFeather[engine]; } + //@} + + /** Retrieves all component names for inclusion in output stream + @param delimiter either a tab or comma string depending on output type + @return a string containing the descriptive names for all components */ + std::string GetComponentStrings(const std::string& delimiter); + + /** Retrieves all component outputs for inclusion in output stream + @param delimiter either a tab or comma string depending on output type + @return a string containing the numeric values for the current set of + component outputs */ + std::string GetComponentValues(const std::string& delimiter); + + /// @name Pilot input command setting + //@{ + /** Sets the aileron command + @param cmd aileron command */ + void SetDaCmd( double cmd ) { DaCmd = cmd; } + + /** Sets the elevator command + @param cmd elevator command in percent*/ + void SetDeCmd(double cmd ) { DeCmd = cmd; } + + /** Sets the rudder command + @param cmd rudder command in percent*/ + void SetDrCmd(double cmd) { DrCmd = cmd; } + + /** Sets the steering command + @param cmd steering command in percent*/ + void SetDsCmd(double cmd) { DsCmd = cmd; } + + /** Sets the flaps command + @param cmd flaps command in percent*/ + void SetDfCmd(double cmd) { DfCmd = cmd; } + + /** Sets the speedbrake command + @param cmd speedbrake command in percent*/ + void SetDsbCmd(double cmd) { DsbCmd = cmd; } + + /** Sets the spoilers command + @param cmd spoilers command in percent*/ + void SetDspCmd(double cmd) { DspCmd = cmd; } + + /** Sets the pitch trim command + @param cmd pitch trim command in percent*/ + void SetPitchTrimCmd(double cmd) { PTrimCmd = cmd; } + + /** Sets the rudder trim command + @param cmd rudder trim command in percent*/ + void SetYawTrimCmd(double cmd) { YTrimCmd = cmd; } + + /** Sets the aileron trim command + @param cmd aileron trim command in percent*/ + void SetRollTrimCmd(double cmd) { RTrimCmd = cmd; } + + /** Sets the throttle command for the specified engine + @param engine engine ID number + @param cmd normalized throttle command (0.0 - 1.0)*/ + void SetThrottleCmd(int engine, double cmd); + + /** Sets the mixture command for the specified engine + @param engine engine ID number + @param cmd normalized mixture command (0.0 - 1.0)*/ + void SetMixtureCmd(int engine, double cmd); + + /** Set the gear extend/retract command, defaults to down + @param gear command 0 for up, 1 for down */ + void SetGearCmd(double gearcmd) { GearCmd = gearcmd; } + + /** Sets the propeller pitch command for the specified engine + @param engine engine ID number + @param cmd mixture command in percent (0.0 - 1.0)*/ + void SetPropAdvanceCmd(int engine, double cmd); + + /** Sets the propeller feather command for the specified engine + @param engine engine ID number + @param cmd feather (bool)*/ + void SetFeatherCmd(int engine, bool cmd); + //@} + + /// @name Aerosurface position setting + //@{ + /** Sets the left aileron position + @param cmd left aileron position in radians*/ + void SetDaLPos( int form , double pos ); + + /** Sets the right aileron position + @param cmd right aileron position in radians*/ + void SetDaRPos( int form , double pos ); + + /** Sets the elevator position + @param cmd elevator position in radians*/ + void SetDePos( int form , double pos ); + + /** Sets the rudder position + @param cmd rudder position in radians*/ + void SetDrPos( int form , double pos ); + + /** Sets the flaps position + @param cmd flaps position in radians*/ + void SetDfPos( int form , double pos ); + + /** Sets the speedbrake position + @param cmd speedbrake position in radians*/ + void SetDsbPos( int form , double pos ); + + /** Sets the spoiler position + @param cmd spoiler position in radians*/ + void SetDspPos( int form , double pos ); + + /** Sets the actual throttle setting for the specified engine + @param engine engine ID number + @param cmd normalized throttle setting (0.0 - 1.0)*/ + void SetThrottlePos(int engine, double cmd); + + /** Sets the actual mixture setting for the specified engine + @param engine engine ID number + @param cmd normalized mixture setting (0.0 - 1.0)*/ + void SetMixturePos(int engine, double cmd); + + /** Sets the steering position + @param cmd steering position in degrees*/ + void SetSteerPosDeg(int gear, double pos) { SteerPosDeg[gear] = pos; } + + /** Set the gear extend/retract position, defaults to down + @param gear position 0 up, 1 down */ + void SetGearPos(double gearpos) { GearPos = gearpos; } + + /** Set the tailhook position + @param tailhook position 0 up, 1 down */ + void SetTailhookPos(double hookpos) { TailhookPos = hookpos; } + + /** Set the wing fold position + @param wing fold position 0 unfolded, 1 folded */ + void SetWingFoldPos(double foldpos) { WingFoldPos = foldpos; } + + /** Sets the actual prop pitch setting for the specified engine + @param engine engine ID number + @param cmd prop pitch setting in percent (0.0 - 1.0)*/ + void SetPropAdvance(int engine, double cmd); + + /** Sets the actual prop feather setting for the specified engine + @param engine engine ID number + @param cmd prop fether setting (bool)*/ + void SetPropFeather(int engine, bool cmd); + //@} /// @name Landing Gear brakes - //@{ - /** Sets the left brake group - @param cmd brake setting in percent (0.0 - 1.0) */ - void SetLBrake(double cmd) - { - LeftBrake = cmd; - } - - /** Sets the right brake group - @param cmd brake setting in percent (0.0 - 1.0) */ - void SetRBrake(double cmd) - { - RightBrake = cmd; - } - - /** Sets the center brake group - @param cmd brake setting in percent (0.0 - 1.0) */ - void SetCBrake(double cmd) - { - CenterBrake = cmd; - } - - /** Gets the brake for a specified group. - @param bg which brakegroup to retrieve the command for - @return the brake setting for the supplied brake group argument */ - double GetBrake(FGLGear::BrakeGroup bg); - - /** Gets the left brake. - @return the left brake setting. */ - double GetLBrake(void) const - { - return LeftBrake; - } - - /** Gets the right brake. - @return the right brake setting. */ - double GetRBrake(void) const - { - return RightBrake; - } - - /** Gets the center brake. - @return the center brake setting. */ - double GetCBrake(void) const - { - return CenterBrake; - } - //@} - - enum SystemType { stFCS, stSystem, stAutoPilot }; - - /** Loads the Flight Control System. - Load() is called from FGFDMExec. - @param el pointer to the Element instance - @param systype type of system (FCS, Autopilot, System) - @return true if succesful */ - bool Load(Element* el, SystemType systype); - - std::ifstream* FindSystemFile(const std::string& system_filename); - std::string FindSystemFullPathname(const std::string& system_filename); - - void AddThrottle(void); - void AddGear(void); - double GetDt(void); - - FGPropertyManager* GetPropertyManager(void) - { - return PropertyManager; - } + //@{ + /** Sets the left brake group + @param cmd brake setting in percent (0.0 - 1.0) */ + void SetLBrake(double cmd) {LeftBrake = cmd;} + + /** Sets the right brake group + @param cmd brake setting in percent (0.0 - 1.0) */ + void SetRBrake(double cmd) {RightBrake = cmd;} + + /** Sets the center brake group + @param cmd brake setting in percent (0.0 - 1.0) */ + void SetCBrake(double cmd) {CenterBrake = cmd;} + + /** Gets the brake for a specified group. + @param bg which brakegroup to retrieve the command for + @return the brake setting for the supplied brake group argument */ + double GetBrake(FGLGear::BrakeGroup bg); + + /** Gets the left brake. + @return the left brake setting. */ + double GetLBrake(void) const {return LeftBrake;} + + /** Gets the right brake. + @return the right brake setting. */ + double GetRBrake(void) const {return RightBrake;} + + /** Gets the center brake. + @return the center brake setting. */ + double GetCBrake(void) const {return CenterBrake;} + //@} + + enum SystemType { stFCS, stSystem, stAutoPilot }; + + /** Loads the Flight Control System. + Load() is called from FGFDMExec. + @param el pointer to the Element instance + @param systype type of system (FCS, Autopilot, System) + @return true if succesful */ + bool Load(Element* el, SystemType systype); + + std::ifstream* FindSystemFile(const std::string& system_filename); + std::string FindSystemFullPathname(const std::string& system_filename); + + void AddThrottle(void); + void AddGear(void); + double GetDt(void); + + FGPropertyManager* GetPropertyManager(void) { return PropertyManager; } + + void LateBind(void); private: - double DaCmd, DeCmd, DrCmd, DsCmd, DfCmd, DsbCmd, DspCmd; - double DePos[NForms], DaLPos[NForms], DaRPos[NForms], DrPos[NForms]; - double DfPos[NForms], DsbPos[NForms], DspPos[NForms]; - double PTrimCmd, YTrimCmd, RTrimCmd; - std::vector <double> ThrottleCmd; - std::vector <double> ThrottlePos; - std::vector <double> MixtureCmd; - std::vector <double> MixturePos; - std::vector <double> PropAdvanceCmd; - std::vector <double> PropAdvance; - std::vector <bool> PropFeatherCmd; - std::vector <bool> PropFeather; - std::vector <double> SteerPosDeg; - double LeftBrake, RightBrake, CenterBrake; // Brake settings - double GearCmd,GearPos; - double TailhookPos, WingFoldPos; - - typedef std::vector <FGFCSComponent*> FCSCompVec; - FCSCompVec Systems; - FCSCompVec FCSComponents; - FCSCompVec APComponents; - void bind(void); - void bindModel(void); - void bindThrottle(unsigned int); - void Debug(int from); + double DaCmd, DeCmd, DrCmd, DsCmd, DfCmd, DsbCmd, DspCmd; + double DePos[NForms], DaLPos[NForms], DaRPos[NForms], DrPos[NForms]; + double DfPos[NForms], DsbPos[NForms], DspPos[NForms]; + double PTrimCmd, YTrimCmd, RTrimCmd; + std::vector <double> ThrottleCmd; + std::vector <double> ThrottlePos; + std::vector <double> MixtureCmd; + std::vector <double> MixturePos; + std::vector <double> PropAdvanceCmd; + std::vector <double> PropAdvance; + std::vector <bool> PropFeatherCmd; + std::vector <bool> PropFeather; + std::vector <double> SteerPosDeg; + double LeftBrake, RightBrake, CenterBrake; // Brake settings + double GearCmd,GearPos; + double TailhookPos, WingFoldPos; + + typedef std::vector <FGFCSComponent*> FCSCompVec; + FCSCompVec Systems; + FCSCompVec FCSComponents; + FCSCompVec APComponents; + void bind(void); + void bindModel(void); + void bindThrottle(unsigned int); + void Debug(int from); }; } diff --git a/src/models/FGGasCell.cpp b/src/models/FGGasCell.cpp index 7109b6584cfa8d51cc2c3927b7b356e1a9fd5263..8edabcd9afe9935b4b2b005d209c07cdd1557881 100644 --- a/src/models/FGGasCell.cpp +++ b/src/models/FGGasCell.cpp @@ -51,8 +51,7 @@ using std::cout; using std::string; using std::max; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGGasCell.cpp,v 1.12 2009/10/24 22:59:30 jberndt Exp $"; static const char *IdHdr = ID_GASCELL; @@ -68,217 +67,182 @@ const double FGGasCell::M_helium = 0.00027409; // [slug/mol] FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, int num) : FGForce(exec) { - string token; - Element* element; - - Auxiliary = exec->GetAuxiliary(); - Atmosphere = exec->GetAtmosphere(); - PropertyManager = exec->GetPropertyManager(); - Inertial = exec->GetInertial(); - MassBalance = exec->GetMassBalance(); - - gasCellJ = FGMatrix33(); - gasCellM = FGColumnVector3(); - - Buoyancy = MaxVolume = MaxOverpressure = Temperature = Pressure = - Contents = Volume = dVolumeIdeal = 0.0; - Xradius = Yradius = Zradius = Xwidth = Ywidth = Zwidth = 0.0; - ValveCoefficient = ValveOpen = 0.0; - CellNum = num; - - // NOTE: In the local system X points north, Y points east and Z points down. - SetTransformType(FGForce::tLocalBody); - - type = el->GetAttributeValue("type"); - if (type == "HYDROGEN") Type = ttHYDROGEN; - else if (type == "HELIUM") Type = ttHELIUM; - else if (type == "AIR") Type = ttAIR; - else Type = ttUNKNOWN; - - element = el->FindElement("location"); - if (element) - { - vXYZ = element->FindElementTripletConvertTo("IN"); - } - else - { - cerr << "Fatal Error: No location found for this gas cell." << endl; - exit(-1); - } - if ((el->FindElement("x_radius") || el->FindElement("x_width")) && - (el->FindElement("y_radius") || el->FindElement("y_width")) && - (el->FindElement("z_radius") || el->FindElement("z_width"))) - { - - if (el->FindElement("x_radius")) - { - Xradius = el->FindElementValueAsNumberConvertTo("x_radius", "FT"); - } - if (el->FindElement("y_radius")) - { - Yradius = el->FindElementValueAsNumberConvertTo("y_radius", "FT"); - } - if (el->FindElement("z_radius")) - { - Zradius = el->FindElementValueAsNumberConvertTo("z_radius", "FT"); - } - - if (el->FindElement("x_width")) - { - Xwidth = el->FindElementValueAsNumberConvertTo("x_width", "FT"); - } - if (el->FindElement("y_width")) - { - Ywidth = el->FindElementValueAsNumberConvertTo("y_width", "FT"); - } - if (el->FindElement("z_width")) - { - Zwidth = el->FindElementValueAsNumberConvertTo("z_width", "FT"); - } - - // The volume is a (potentially) extruded ellipsoid. - // However, currently only a few combinations of radius and width are - // fully supported. - if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && - (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) - { - // Ellipsoid volume. - MaxVolume = 4.0 * M_PI * Xradius * Yradius * Zradius / 3.0; - } - else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && - (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) - { - // Cylindrical volume. - MaxVolume = M_PI * Yradius * Zradius * Xwidth; - } - else - { - cerr << "Warning: Unsupported gas cell shape." << endl; - MaxVolume = - (4.0 * M_PI * Xradius * Yradius * Zradius / 3.0 + - M_PI * Yradius * Zradius * Xwidth + - M_PI * Xradius * Zradius * Ywidth + - M_PI * Xradius * Yradius * Zwidth + - 2.0 * Xradius * Ywidth * Zwidth + - 2.0 * Yradius * Xwidth * Zwidth + - 2.0 * Zradius * Xwidth * Ywidth + - Xwidth * Ywidth * Zwidth); - } - } - else - { - cerr << "Fatal Error: Gas cell shape must be given." << endl; - exit(-1); - } - if (el->FindElement("max_overpressure")) - { - MaxOverpressure = el->FindElementValueAsNumberConvertTo("max_overpressure", - "LBS/FT2"); - } - if (el->FindElement("fullness")) - { - const double Fullness = el->FindElementValueAsNumber("fullness"); - if (0 <= Fullness) - { - Volume = Fullness * MaxVolume; - } - else - { - cerr << "Warning: Invalid initial gas cell fullness value." << endl; - } - } - if (el->FindElement("valve_coefficient")) - { - ValveCoefficient = - el->FindElementValueAsNumberConvertTo("valve_coefficient", - "FT4*SEC/SLUG"); - ValveCoefficient = max(ValveCoefficient, 0.0); - } + string token; + Element* element; - // Initialize state - SetLocation(vXYZ); + Auxiliary = exec->GetAuxiliary(); + Atmosphere = exec->GetAtmosphere(); + PropertyManager = exec->GetPropertyManager(); + Inertial = exec->GetInertial(); + MassBalance = exec->GetMassBalance(); - if (Temperature == 0.0) - { - Temperature = Atmosphere->GetTemperature(); - } - if (Pressure == 0.0) - { - Pressure = Atmosphere->GetPressure(); + gasCellJ = FGMatrix33(); + gasCellM = FGColumnVector3(); + + Buoyancy = MaxVolume = MaxOverpressure = Temperature = Pressure = + Contents = Volume = dVolumeIdeal = 0.0; + Xradius = Yradius = Zradius = Xwidth = Ywidth = Zwidth = 0.0; + ValveCoefficient = ValveOpen = 0.0; + CellNum = num; + + // NOTE: In the local system X points north, Y points east and Z points down. + SetTransformType(FGForce::tLocalBody); + + type = el->GetAttributeValue("type"); + if (type == "HYDROGEN") Type = ttHYDROGEN; + else if (type == "HELIUM") Type = ttHELIUM; + else if (type == "AIR") Type = ttAIR; + else Type = ttUNKNOWN; + + element = el->FindElement("location"); + if (element) { + vXYZ = element->FindElementTripletConvertTo("IN"); + } else { + cerr << "Fatal Error: No location found for this gas cell." << endl; + exit(-1); + } + if ((el->FindElement("x_radius") || el->FindElement("x_width")) && + (el->FindElement("y_radius") || el->FindElement("y_width")) && + (el->FindElement("z_radius") || el->FindElement("z_width"))) { + + if (el->FindElement("x_radius")) { + Xradius = el->FindElementValueAsNumberConvertTo("x_radius", "FT"); } - if (Volume != 0.0) - { - // Calculate initial gas content. - Contents = Pressure * Volume / (R * Temperature); - - // Clip to max allowed value. - const double IdealPressure = Contents * R * Temperature / MaxVolume; - if (IdealPressure > Pressure + MaxOverpressure) - { - Contents = (Pressure + MaxOverpressure) * MaxVolume / (R * Temperature); - Pressure = Pressure + MaxOverpressure; - } - else - { - Pressure = max(IdealPressure, Pressure); - } + if (el->FindElement("y_radius")) { + Yradius = el->FindElementValueAsNumberConvertTo("y_radius", "FT"); } - else - { - // Calculate initial gas content. - Contents = Pressure * MaxVolume / (R * Temperature); + if (el->FindElement("z_radius")) { + Zradius = el->FindElementValueAsNumberConvertTo("z_radius", "FT"); } - Volume = Contents * R * Temperature / Pressure; - Mass = Contents * M_gas(); - - // Bind relevant properties - string property_name, base_property_name; - - base_property_name = CreateIndexedPropertyName("buoyant_forces/gas-cell", CellNum); - - property_name = base_property_name + "/max_volume-ft3"; - PropertyManager->Tie( property_name.c_str(), &MaxVolume ); - PropertyManager->SetWritable( property_name, false ); - property_name = base_property_name + "/temp-R"; - PropertyManager->Tie( property_name.c_str(), &Temperature ); - property_name = base_property_name + "/pressure-psf"; - PropertyManager->Tie( property_name.c_str(), &Pressure ); - property_name = base_property_name + "/volume-ft3"; - PropertyManager->Tie( property_name.c_str(), &Volume ); - property_name = base_property_name + "/buoyancy-lbs"; - PropertyManager->Tie( property_name.c_str(), &Buoyancy ); - property_name = base_property_name + "/contents-mol"; - PropertyManager->Tie( property_name.c_str(), &Contents ); - property_name = base_property_name + "/valve_open"; - PropertyManager->Tie( property_name.c_str(), &ValveOpen ); - - Debug(0); - - // Read heat transfer coefficients - if (Element* heat = el->FindElement("heat")) - { - Element* function_element = heat->FindElement("function"); - while (function_element) - { - HeatTransferCoeff.push_back(new FGFunction(PropertyManager, - function_element)); - function_element = heat->FindNextElement("function"); - } + if (el->FindElement("x_width")) { + Xwidth = el->FindElementValueAsNumberConvertTo("x_width", "FT"); } - - // Load ballonets if there are any - if (Element* ballonet_element = el->FindElement("ballonet")) - { - while (ballonet_element) - { - Ballonet.push_back(new FGBallonet(exec, - ballonet_element, - Ballonet.size(), - this)); - ballonet_element = el->FindNextElement("ballonet"); - } + if (el->FindElement("y_width")) { + Ywidth = el->FindElementValueAsNumberConvertTo("y_width", "FT"); } + if (el->FindElement("z_width")) { + Zwidth = el->FindElementValueAsNumberConvertTo("z_width", "FT"); + } + + // The volume is a (potentially) extruded ellipsoid. + // However, currently only a few combinations of radius and width are + // fully supported. + if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && + (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { + // Ellipsoid volume. + MaxVolume = 4.0 * M_PI * Xradius * Yradius * Zradius / 3.0; + } else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && + (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { + // Cylindrical volume. + MaxVolume = M_PI * Yradius * Zradius * Xwidth; + } else { + cerr << "Warning: Unsupported gas cell shape." << endl; + MaxVolume = + (4.0 * M_PI * Xradius * Yradius * Zradius / 3.0 + + M_PI * Yradius * Zradius * Xwidth + + M_PI * Xradius * Zradius * Ywidth + + M_PI * Xradius * Yradius * Zwidth + + 2.0 * Xradius * Ywidth * Zwidth + + 2.0 * Yradius * Xwidth * Zwidth + + 2.0 * Zradius * Xwidth * Ywidth + + Xwidth * Ywidth * Zwidth); + } + } else { + cerr << "Fatal Error: Gas cell shape must be given." << endl; + exit(-1); + } + if (el->FindElement("max_overpressure")) { + MaxOverpressure = el->FindElementValueAsNumberConvertTo("max_overpressure", + "LBS/FT2"); + } + if (el->FindElement("fullness")) { + const double Fullness = el->FindElementValueAsNumber("fullness"); + if (0 <= Fullness) { + Volume = Fullness * MaxVolume; + } else { + cerr << "Warning: Invalid initial gas cell fullness value." << endl; + } + } + if (el->FindElement("valve_coefficient")) { + ValveCoefficient = + el->FindElementValueAsNumberConvertTo("valve_coefficient", + "FT4*SEC/SLUG"); + ValveCoefficient = max(ValveCoefficient, 0.0); + } + + // Initialize state + SetLocation(vXYZ); + + if (Temperature == 0.0) { + Temperature = Atmosphere->GetTemperature(); + } + if (Pressure == 0.0) { + Pressure = Atmosphere->GetPressure(); + } + if (Volume != 0.0) { + // Calculate initial gas content. + Contents = Pressure * Volume / (R * Temperature); + + // Clip to max allowed value. + const double IdealPressure = Contents * R * Temperature / MaxVolume; + if (IdealPressure > Pressure + MaxOverpressure) { + Contents = (Pressure + MaxOverpressure) * MaxVolume / (R * Temperature); + Pressure = Pressure + MaxOverpressure; + } else { + Pressure = max(IdealPressure, Pressure); + } + } else { + // Calculate initial gas content. + Contents = Pressure * MaxVolume / (R * Temperature); + } + + Volume = Contents * R * Temperature / Pressure; + Mass = Contents * M_gas(); + + // Bind relevant properties + string property_name, base_property_name; + + base_property_name = CreateIndexedPropertyName("buoyant_forces/gas-cell", CellNum); + + property_name = base_property_name + "/max_volume-ft3"; + PropertyManager->Tie( property_name.c_str(), &MaxVolume ); + PropertyManager->SetWritable( property_name, false ); + property_name = base_property_name + "/temp-R"; + PropertyManager->Tie( property_name.c_str(), &Temperature ); + property_name = base_property_name + "/pressure-psf"; + PropertyManager->Tie( property_name.c_str(), &Pressure ); + property_name = base_property_name + "/volume-ft3"; + PropertyManager->Tie( property_name.c_str(), &Volume ); + property_name = base_property_name + "/buoyancy-lbs"; + PropertyManager->Tie( property_name.c_str(), &Buoyancy ); + property_name = base_property_name + "/contents-mol"; + PropertyManager->Tie( property_name.c_str(), &Contents ); + property_name = base_property_name + "/valve_open"; + PropertyManager->Tie( property_name.c_str(), &ValveOpen ); + + Debug(0); + + // Read heat transfer coefficients + if (Element* heat = el->FindElement("heat")) { + Element* function_element = heat->FindElement("function"); + while (function_element) { + HeatTransferCoeff.push_back(new FGFunction(PropertyManager, + function_element)); + function_element = heat->FindNextElement("function"); + } + } + + // Load ballonets if there are any + if (Element* ballonet_element = el->FindElement("ballonet")) { + while (ballonet_element) { + Ballonet.push_back(new FGBallonet(exec, + ballonet_element, + Ballonet.size(), + this)); + ballonet_element = el->FindNextElement("ballonet"); + } + } } @@ -286,216 +250,195 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, int num) : FGForce(exec) FGGasCell::~FGGasCell() { - unsigned int i; + unsigned int i; - for (i = 0; i < HeatTransferCoeff.size(); i++) delete HeatTransferCoeff[i]; - HeatTransferCoeff.clear(); + for (i = 0; i < HeatTransferCoeff.size(); i++) delete HeatTransferCoeff[i]; + HeatTransferCoeff.clear(); - for (i = 0; i < Ballonet.size(); i++) delete Ballonet[i]; - Ballonet.clear(); + for (i = 0; i < Ballonet.size(); i++) delete Ballonet[i]; + Ballonet.clear(); - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGGasCell::Calculate(double dt) { - const double AirTemperature = Atmosphere->GetTemperature(); // [Rankine] - const double AirPressure = Atmosphere->GetPressure(); // [lbs/ft²] - const double AirDensity = Atmosphere->GetDensity(); // [slug/ft³] - const double g = Inertial->gravity(); // [lbs/slug] - - const double OldTemperature = Temperature; - const double OldPressure = Pressure; - unsigned int i; - const unsigned int no_ballonets = Ballonet.size(); - - //-- Read ballonet state -- - // NOTE: This model might need a more proper integration technique. - double BallonetsVolume = 0.0; - double BallonetsHeatFlow = 0.0; - for (i = 0; i < no_ballonets; i++) - { - BallonetsVolume += Ballonet[i]->GetVolume(); - BallonetsHeatFlow += Ballonet[i]->GetHeatFlow(); - } - - //-- Gas temperature -- - - if (HeatTransferCoeff.size() > 0) - { - // The model is based on the ideal gas law. - // However, it does look a bit fishy. Please verify. - // dT/dt = dU / (Cv n R) - double dU = 0.0; - for (i = 0; i < HeatTransferCoeff.size(); i++) - { - dU += HeatTransferCoeff[i]->GetValue(); - } - // Don't include dt when accounting for adiabatic expansion/contraction. - // The rate of adiabatic cooling looks about right: ~5.4 Rankine/1000ft. - if (Contents > 0) - { - Temperature += - (dU * dt - Pressure * dVolumeIdeal - BallonetsHeatFlow) / - (Cv_gas() * Contents * R); - } - else - { - Temperature = AirTemperature; - } - } - else - { - // No simulation of complex temperature changes. - // Note: Making the gas cell behave adiabatically might be a better - // option. - Temperature = AirTemperature; - } - - //-- Pressure -- - const double IdealPressure = - Contents * R * Temperature / (MaxVolume - BallonetsVolume); - if (IdealPressure > AirPressure + MaxOverpressure) - { - Pressure = AirPressure + MaxOverpressure; - } - else - { - Pressure = max(IdealPressure, AirPressure); - } - - //-- Manual valving -- - - // FIXME: Presently the effect of manual valving is computed using - // an ad hoc formula which might not be a good representation - // of reality. - if ((ValveCoefficient > 0.0) && (ValveOpen > 0.0)) - { - // First compute the difference in pressure between the gas in the - // cell and the air above it. - // FixMe: CellHeight should depend on current volume. - const double CellHeight = 2 * Zradius + Zwidth; // [ft] - const double GasMass = Contents * M_gas(); // [slug] - const double GasVolume = Contents * R * Temperature / Pressure; // [ft³] - const double GasDensity = GasMass / GasVolume; - const double DeltaPressure = - Pressure + CellHeight * g * (AirDensity - GasDensity) - AirPressure; - const double VolumeValved = - ValveOpen * ValveCoefficient * DeltaPressure * dt; - Contents = - max(0.0, Contents - Pressure * VolumeValved / (R * Temperature)); - } - - //-- Update ballonets. -- - // Doing that here should give them the opportunity to react to the - // new pressure. - BallonetsVolume = 0.0; - for (i = 0; i < no_ballonets; i++) - { - Ballonet[i]->Calculate(dt); - BallonetsVolume += Ballonet[i]->GetVolume(); - } - - //-- Automatic safety valving. -- - if (Contents * R * Temperature / (MaxVolume - BallonetsVolume) > - AirPressure + MaxOverpressure) - { - // Gas is automatically valved. Valving capacity is assumed to be infinite. - // FIXME: This could/should be replaced by damage to the gas cell envelope. - Contents = - (AirPressure + MaxOverpressure) * - (MaxVolume - BallonetsVolume) / (R * Temperature); - } - - //-- Volume -- - Volume = Contents * R * Temperature / Pressure + BallonetsVolume; - dVolumeIdeal = - Contents * R * (Temperature / Pressure - OldTemperature / OldPressure); - - //-- Current buoyancy -- - // The buoyancy is computed using the atmospheres local density. - Buoyancy = Volume * AirDensity * g; - - // Note: This is gross buoyancy. The weight of the gas itself and - // any ballonets is not deducted here as the effects of the gas mass - // is handled by FGMassBalance. - vFn.InitMatrix(0.0, 0.0, - Buoyancy); - - // Compute the inertia of the gas cell. - // Consider the gas cell as a shape of uniform density. - // FIXME: If the cell isn't ellipsoid or cylindrical the inertia will - // be wrong. - gasCellJ = FGMatrix33(); - const double mass = Contents * M_gas(); - double Ixx, Iyy, Izz; - if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && - (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) - { - // Ellipsoid volume. - Ixx = (1.0 / 5.0) * mass * (Yradius*Yradius + Zradius*Zradius); - Iyy = (1.0 / 5.0) * mass * (Xradius*Xradius + Zradius*Zradius); - Izz = (1.0 / 5.0) * mass * (Xradius*Xradius + Yradius*Yradius); - } - else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && - (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) - { - // Cylindrical volume (might not be valid with an elliptical cross-section). - Ixx = (1.0 / 2.0) * mass * Yradius * Zradius; - Iyy = - (1.0 / 4.0) * mass * Yradius * Zradius + - (1.0 / 12.0) * mass * Xwidth * Xwidth; - Izz = - (1.0 / 4.0) * mass * Yradius * Zradius + - (1.0 / 12.0) * mass * Xwidth * Xwidth; - } - else - { - // Not supported. Revert to pointmass model. - Ixx = Iyy = Izz = 0.0; - } - // The volume is symmetric, so Ixy = Ixz = Iyz = 0. - gasCellJ(1,1) = Ixx; - gasCellJ(2,2) = Iyy; - gasCellJ(3,3) = Izz; - Mass = mass; - gasCellM.InitMatrix(); - gasCellM(eX) += - GetXYZ(eX) * Mass*slugtolb; - gasCellM(eY) += - GetXYZ(eY) * Mass*slugtolb; - gasCellM(eZ) += - GetXYZ(eZ) * Mass*slugtolb; - - if (no_ballonets > 0) - { - // Add the mass, moment and inertia of any ballonets. - const FGColumnVector3 p = MassBalance->StructuralToBody( GetXYZ() ); - - for (i = 0; i < no_ballonets; i++) - { - Mass += Ballonet[i]->GetMass(); - - // Add ballonet moments. - gasCellM(eX) += - Ballonet[i]->GetXYZ(eX) * Ballonet[i]->GetMass()*slugtolb; - gasCellM(eY) += - Ballonet[i]->GetXYZ(eY) * Ballonet[i]->GetMass()*slugtolb; - gasCellM(eZ) += - Ballonet[i]->GetXYZ(eZ) * Ballonet[i]->GetMass()*slugtolb; - - // Moments of inertia must be converted to the gas cell frame here. - FGColumnVector3 v = - MassBalance->StructuralToBody( Ballonet[i]->GetXYZ() ) - p; - // Body basis is in FT. - const double mass = Ballonet[i]->GetMass(); - gasCellJ += Ballonet[i]->GetInertia() + - FGMatrix33( 0, - mass*v(1)*v(2), - mass*v(1)*v(3), - - mass*v(2)*v(1), 0, - mass*v(2)*v(3), - - mass*v(3)*v(1), - mass*v(3)*v(2), 0 ); - } - } + const double AirTemperature = Atmosphere->GetTemperature(); // [Rankine] + const double AirPressure = Atmosphere->GetPressure(); // [lbs/ft²] + const double AirDensity = Atmosphere->GetDensity(); // [slug/ft³] + const double g = Inertial->gravity(); // [lbs/slug] + + const double OldTemperature = Temperature; + const double OldPressure = Pressure; + unsigned int i; + const unsigned int no_ballonets = Ballonet.size(); + + //-- Read ballonet state -- + // NOTE: This model might need a more proper integration technique. + double BallonetsVolume = 0.0; + double BallonetsHeatFlow = 0.0; + for (i = 0; i < no_ballonets; i++) { + BallonetsVolume += Ballonet[i]->GetVolume(); + BallonetsHeatFlow += Ballonet[i]->GetHeatFlow(); + } + + //-- Gas temperature -- + + if (HeatTransferCoeff.size() > 0) { + // The model is based on the ideal gas law. + // However, it does look a bit fishy. Please verify. + // dT/dt = dU / (Cv n R) + double dU = 0.0; + for (i = 0; i < HeatTransferCoeff.size(); i++) { + dU += HeatTransferCoeff[i]->GetValue(); + } + // Don't include dt when accounting for adiabatic expansion/contraction. + // The rate of adiabatic cooling looks about right: ~5.4 Rankine/1000ft. + if (Contents > 0) { + Temperature += + (dU * dt - Pressure * dVolumeIdeal - BallonetsHeatFlow) / + (Cv_gas() * Contents * R); + } else { + Temperature = AirTemperature; + } + } else { + // No simulation of complex temperature changes. + // Note: Making the gas cell behave adiabatically might be a better + // option. + Temperature = AirTemperature; + } + + //-- Pressure -- + const double IdealPressure = + Contents * R * Temperature / (MaxVolume - BallonetsVolume); + if (IdealPressure > AirPressure + MaxOverpressure) { + Pressure = AirPressure + MaxOverpressure; + } else { + Pressure = max(IdealPressure, AirPressure); + } + + //-- Manual valving -- + + // FIXME: Presently the effect of manual valving is computed using + // an ad hoc formula which might not be a good representation + // of reality. + if ((ValveCoefficient > 0.0) && (ValveOpen > 0.0)) { + // First compute the difference in pressure between the gas in the + // cell and the air above it. + // FixMe: CellHeight should depend on current volume. + const double CellHeight = 2 * Zradius + Zwidth; // [ft] + const double GasMass = Contents * M_gas(); // [slug] + const double GasVolume = Contents * R * Temperature / Pressure; // [ft³] + const double GasDensity = GasMass / GasVolume; + const double DeltaPressure = + Pressure + CellHeight * g * (AirDensity - GasDensity) - AirPressure; + const double VolumeValved = + ValveOpen * ValveCoefficient * DeltaPressure * dt; + Contents = + max(0.0, Contents - Pressure * VolumeValved / (R * Temperature)); + } + + //-- Update ballonets. -- + // Doing that here should give them the opportunity to react to the + // new pressure. + BallonetsVolume = 0.0; + for (i = 0; i < no_ballonets; i++) { + Ballonet[i]->Calculate(dt); + BallonetsVolume += Ballonet[i]->GetVolume(); + } + + //-- Automatic safety valving. -- + if (Contents * R * Temperature / (MaxVolume - BallonetsVolume) > + AirPressure + MaxOverpressure) { + // Gas is automatically valved. Valving capacity is assumed to be infinite. + // FIXME: This could/should be replaced by damage to the gas cell envelope. + Contents = + (AirPressure + MaxOverpressure) * + (MaxVolume - BallonetsVolume) / (R * Temperature); + } + + //-- Volume -- + Volume = Contents * R * Temperature / Pressure + BallonetsVolume; + dVolumeIdeal = + Contents * R * (Temperature / Pressure - OldTemperature / OldPressure); + + //-- Current buoyancy -- + // The buoyancy is computed using the atmospheres local density. + Buoyancy = Volume * AirDensity * g; + + // Note: This is gross buoyancy. The weight of the gas itself and + // any ballonets is not deducted here as the effects of the gas mass + // is handled by FGMassBalance. + vFn.InitMatrix(0.0, 0.0, - Buoyancy); + + // Compute the inertia of the gas cell. + // Consider the gas cell as a shape of uniform density. + // FIXME: If the cell isn't ellipsoid or cylindrical the inertia will + // be wrong. + gasCellJ = FGMatrix33(); + const double mass = Contents * M_gas(); + double Ixx, Iyy, Izz; + if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && + (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { + // Ellipsoid volume. + Ixx = (1.0 / 5.0) * mass * (Yradius*Yradius + Zradius*Zradius); + Iyy = (1.0 / 5.0) * mass * (Xradius*Xradius + Zradius*Zradius); + Izz = (1.0 / 5.0) * mass * (Xradius*Xradius + Yradius*Yradius); + } else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && + (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { + // Cylindrical volume (might not be valid with an elliptical cross-section). + Ixx = (1.0 / 2.0) * mass * Yradius * Zradius; + Iyy = + (1.0 / 4.0) * mass * Yradius * Zradius + + (1.0 / 12.0) * mass * Xwidth * Xwidth; + Izz = + (1.0 / 4.0) * mass * Yradius * Zradius + + (1.0 / 12.0) * mass * Xwidth * Xwidth; + } else { + // Not supported. Revert to pointmass model. + Ixx = Iyy = Izz = 0.0; + } + // The volume is symmetric, so Ixy = Ixz = Iyz = 0. + gasCellJ(1,1) = Ixx; + gasCellJ(2,2) = Iyy; + gasCellJ(3,3) = Izz; + Mass = mass; + gasCellM.InitMatrix(); + gasCellM(eX) += + GetXYZ(eX) * Mass*slugtolb; + gasCellM(eY) += + GetXYZ(eY) * Mass*slugtolb; + gasCellM(eZ) += + GetXYZ(eZ) * Mass*slugtolb; + + if (no_ballonets > 0) { + // Add the mass, moment and inertia of any ballonets. + const FGColumnVector3 p = MassBalance->StructuralToBody( GetXYZ() ); + + for (i = 0; i < no_ballonets; i++) { + Mass += Ballonet[i]->GetMass(); + + // Add ballonet moments. + gasCellM(eX) += + Ballonet[i]->GetXYZ(eX) * Ballonet[i]->GetMass()*slugtolb; + gasCellM(eY) += + Ballonet[i]->GetXYZ(eY) * Ballonet[i]->GetMass()*slugtolb; + gasCellM(eZ) += + Ballonet[i]->GetXYZ(eZ) * Ballonet[i]->GetMass()*slugtolb; + + // Moments of inertia must be converted to the gas cell frame here. + FGColumnVector3 v = + MassBalance->StructuralToBody( Ballonet[i]->GetXYZ() ) - p; + // Body basis is in FT. + const double mass = Ballonet[i]->GetMass(); + gasCellJ += Ballonet[i]->GetInertia() + + FGMatrix33( 0, - mass*v(1)*v(2), - mass*v(1)*v(3), + - mass*v(2)*v(1), 0, - mass*v(2)*v(3), + - mass*v(3)*v(1), - mass*v(3)*v(2), 0 ); + } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -519,59 +462,51 @@ void FGGasCell::Calculate(double dt) void FGGasCell::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " Gas cell holds " << Contents << " mol " << - type << endl; - cout << " Cell location (X, Y, Z) (in.): " << vXYZ(eX) << ", " << - vXYZ(eY) << ", " << vXYZ(eZ) << endl; - cout << " Maximum volume: " << MaxVolume << " ft3" << endl; - cout << " Relief valve release pressure: " << MaxOverpressure << - " lbs/ft2" << endl; - cout << " Manual valve coefficient: " << ValveCoefficient << - " ft4*sec/slug" << endl; - cout << " Initial temperature: " << Temperature << " Rankine" << - endl; - cout << " Initial pressure: " << Pressure << " lbs/ft2" << endl; - cout << " Initial volume: " << Volume << " ft3" << endl; - cout << " Initial mass: " << GetMass() << " slug mass" << endl; - cout << " Initial weight: " << GetMass()*lbtoslug << " lbs force" << - endl; - cout << " Heat transfer: " << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGGasCell" << endl; - if (from == 1) cout << "Destroyed: FGGasCell" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - cout << " " << type << " cell holds " << Contents << " mol " << endl; - cout << " Temperature: " << Temperature << " Rankine" << endl; - cout << " Pressure: " << Pressure << " lbs/ft2" << endl; - cout << " Volume: " << Volume << " ft3" << endl; - cout << " Mass: " << GetMass() << " slug mass" << endl; - cout << " Weight: " << GetMass()*lbtoslug << " lbs force" << endl; - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " Gas cell holds " << Contents << " mol " << + type << endl; + cout << " Cell location (X, Y, Z) (in.): " << vXYZ(eX) << ", " << + vXYZ(eY) << ", " << vXYZ(eZ) << endl; + cout << " Maximum volume: " << MaxVolume << " ft3" << endl; + cout << " Relief valve release pressure: " << MaxOverpressure << + " lbs/ft2" << endl; + cout << " Manual valve coefficient: " << ValveCoefficient << + " ft4*sec/slug" << endl; + cout << " Initial temperature: " << Temperature << " Rankine" << + endl; + cout << " Initial pressure: " << Pressure << " lbs/ft2" << endl; + cout << " Initial volume: " << Volume << " ft3" << endl; + cout << " Initial mass: " << GetMass() << " slug mass" << endl; + cout << " Initial weight: " << GetMass()*lbtoslug << " lbs force" << + endl; + cout << " Heat transfer: " << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGGasCell" << endl; + if (from == 1) cout << "Destroyed: FGGasCell" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + cout << " " << type << " cell holds " << Contents << " mol " << endl; + cout << " Temperature: " << Temperature << " Rankine" << endl; + cout << " Pressure: " << Pressure << " lbs/ft2" << endl; + cout << " Volume: " << Volume << " ft3" << endl; + cout << " Mass: " << GetMass() << " slug mass" << endl; + cout << " Weight: " << GetMass()*lbtoslug << " lbs force" << endl; + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; + } + } } /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -583,325 +518,279 @@ const double FGBallonet::Cv_air = 5.0/2.0; // [??] FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, int num, FGGasCell* parent) { - string token; - Element* element; - - Auxiliary = exec->GetAuxiliary(); - Atmosphere = exec->GetAtmosphere(); - PropertyManager = exec->GetPropertyManager(); - Inertial = exec->GetInertial(); - - ballonetJ = FGMatrix33(); - - MaxVolume = MaxOverpressure = Temperature = Pressure = - Contents = Volume = dVolumeIdeal = dU = 0.0; - Xradius = Yradius = Zradius = Xwidth = Ywidth = Zwidth = 0.0; - ValveCoefficient = ValveOpen = 0.0; - BlowerInput = NULL; - CellNum = num; - Parent = parent; - - // NOTE: In the local system X points north, Y points east and Z points down. - element = el->FindElement("location"); - if (element) - { - vXYZ = element->FindElementTripletConvertTo("IN"); - } - else - { - cerr << "Fatal Error: No location found for this ballonet." << endl; - exit(-1); - } - if ((el->FindElement("x_radius") || el->FindElement("x_width")) && - (el->FindElement("y_radius") || el->FindElement("y_width")) && - (el->FindElement("z_radius") || el->FindElement("z_width"))) - { - - if (el->FindElement("x_radius")) - { - Xradius = el->FindElementValueAsNumberConvertTo("x_radius", "FT"); - } - if (el->FindElement("y_radius")) - { - Yradius = el->FindElementValueAsNumberConvertTo("y_radius", "FT"); - } - if (el->FindElement("z_radius")) - { - Zradius = el->FindElementValueAsNumberConvertTo("z_radius", "FT"); - } - - if (el->FindElement("x_width")) - { - Xwidth = el->FindElementValueAsNumberConvertTo("x_width", "FT"); - } - if (el->FindElement("y_width")) - { - Ywidth = el->FindElementValueAsNumberConvertTo("y_width", "FT"); - } - if (el->FindElement("z_width")) - { - Zwidth = el->FindElementValueAsNumberConvertTo("z_width", "FT"); - } - - // The volume is a (potentially) extruded ellipsoid. - // FIXME: However, currently only a few combinations of radius and - // width are fully supported. - if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && - (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) - { - // Ellipsoid volume. - MaxVolume = 4.0 * M_PI * Xradius * Yradius * Zradius / 3.0; - } - else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && - (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) - { - // Cylindrical volume. - MaxVolume = M_PI * Yradius * Zradius * Xwidth; - } - else - { - cerr << "Warning: Unsupported ballonet shape." << endl; - MaxVolume = - (4.0 * M_PI * Xradius * Yradius * Zradius / 3.0 + - M_PI * Yradius * Zradius * Xwidth + - M_PI * Xradius * Zradius * Ywidth + - M_PI * Xradius * Yradius * Zwidth + - 2.0 * Xradius * Ywidth * Zwidth + - 2.0 * Yradius * Xwidth * Zwidth + - 2.0 * Zradius * Xwidth * Ywidth + - Xwidth * Ywidth * Zwidth); - } - } - else - { - cerr << "Fatal Error: Ballonet shape must be given." << endl; - exit(-1); - } - if (el->FindElement("max_overpressure")) - { - MaxOverpressure = el->FindElementValueAsNumberConvertTo("max_overpressure", - "LBS/FT2"); - } - if (el->FindElement("fullness")) - { - const double Fullness = el->FindElementValueAsNumber("fullness"); - if (0 <= Fullness) - { - Volume = Fullness * MaxVolume; - } - else - { - cerr << "Warning: Invalid initial ballonet fullness value." << endl; - } - } - if (el->FindElement("valve_coefficient")) - { - ValveCoefficient = - el->FindElementValueAsNumberConvertTo("valve_coefficient", - "FT4*SEC/SLUG"); - ValveCoefficient = max(ValveCoefficient, 0.0); - } - - // Initialize state - if (Temperature == 0.0) - { - Temperature = Parent->GetTemperature(); - } - if (Pressure == 0.0) - { - Pressure = Parent->GetPressure(); - } - if (Volume != 0.0) - { - // Calculate initial air content. - Contents = Pressure * Volume / (R * Temperature); - - // Clip to max allowed value. - const double IdealPressure = Contents * R * Temperature / MaxVolume; - if (IdealPressure > Pressure + MaxOverpressure) - { - Contents = (Pressure + MaxOverpressure) * MaxVolume / (R * Temperature); - Pressure = Pressure + MaxOverpressure; - } - else - { - Pressure = max(IdealPressure, Pressure); - } - } - else - { - // Calculate initial air content. - Contents = Pressure * MaxVolume / (R * Temperature); - } - - Volume = Contents * R * Temperature / Pressure; + string token; + Element* element; - // Bind relevant properties - string property_name, base_property_name; - base_property_name = CreateIndexedPropertyName("buoyant_forces/gas-cell", Parent->GetIndex()); - base_property_name = CreateIndexedPropertyName(base_property_name + "/ballonet", CellNum); + Auxiliary = exec->GetAuxiliary(); + Atmosphere = exec->GetAtmosphere(); + PropertyManager = exec->GetPropertyManager(); + Inertial = exec->GetInertial(); - property_name = base_property_name + "/max_volume-ft3"; - PropertyManager->Tie( property_name, &MaxVolume ); - PropertyManager->SetWritable( property_name, false ); + ballonetJ = FGMatrix33(); - property_name = base_property_name + "/temp-R"; - PropertyManager->Tie( property_name, &Temperature ); + MaxVolume = MaxOverpressure = Temperature = Pressure = + Contents = Volume = dVolumeIdeal = dU = 0.0; + Xradius = Yradius = Zradius = Xwidth = Ywidth = Zwidth = 0.0; + ValveCoefficient = ValveOpen = 0.0; + BlowerInput = NULL; + CellNum = num; + Parent = parent; - property_name = base_property_name + "/pressure-psf"; - PropertyManager->Tie( property_name, &Pressure ); + // NOTE: In the local system X points north, Y points east and Z points down. + element = el->FindElement("location"); + if (element) { + vXYZ = element->FindElementTripletConvertTo("IN"); + } else { + cerr << "Fatal Error: No location found for this ballonet." << endl; + exit(-1); + } + if ((el->FindElement("x_radius") || el->FindElement("x_width")) && + (el->FindElement("y_radius") || el->FindElement("y_width")) && + (el->FindElement("z_radius") || el->FindElement("z_width"))) { - property_name = base_property_name + "/volume-ft3"; - PropertyManager->Tie( property_name, &Volume ); - - property_name = base_property_name + "/contents-mol"; - PropertyManager->Tie( property_name, &Contents ); - - property_name = base_property_name + "/valve_open"; - PropertyManager->Tie( property_name, &ValveOpen ); - - Debug(0); + if (el->FindElement("x_radius")) { + Xradius = el->FindElementValueAsNumberConvertTo("x_radius", "FT"); + } + if (el->FindElement("y_radius")) { + Yradius = el->FindElementValueAsNumberConvertTo("y_radius", "FT"); + } + if (el->FindElement("z_radius")) { + Zradius = el->FindElementValueAsNumberConvertTo("z_radius", "FT"); + } - // Read heat transfer coefficients - if (Element* heat = el->FindElement("heat")) - { - Element* function_element = heat->FindElement("function"); - while (function_element) - { - HeatTransferCoeff.push_back(new FGFunction(PropertyManager, - function_element)); - function_element = heat->FindNextElement("function"); - } + if (el->FindElement("x_width")) { + Xwidth = el->FindElementValueAsNumberConvertTo("x_width", "FT"); } - // Read blower input function - if (Element* blower = el->FindElement("blower_input")) - { - Element* function_element = blower->FindElement("function"); - BlowerInput = new FGFunction(PropertyManager, - function_element); + if (el->FindElement("y_width")) { + Ywidth = el->FindElementValueAsNumberConvertTo("y_width", "FT"); } + if (el->FindElement("z_width")) { + Zwidth = el->FindElementValueAsNumberConvertTo("z_width", "FT"); + } + + // The volume is a (potentially) extruded ellipsoid. + // FIXME: However, currently only a few combinations of radius and + // width are fully supported. + if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && + (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { + // Ellipsoid volume. + MaxVolume = 4.0 * M_PI * Xradius * Yradius * Zradius / 3.0; + } else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && + (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { + // Cylindrical volume. + MaxVolume = M_PI * Yradius * Zradius * Xwidth; + } else { + cerr << "Warning: Unsupported ballonet shape." << endl; + MaxVolume = + (4.0 * M_PI * Xradius * Yradius * Zradius / 3.0 + + M_PI * Yradius * Zradius * Xwidth + + M_PI * Xradius * Zradius * Ywidth + + M_PI * Xradius * Yradius * Zwidth + + 2.0 * Xradius * Ywidth * Zwidth + + 2.0 * Yradius * Xwidth * Zwidth + + 2.0 * Zradius * Xwidth * Ywidth + + Xwidth * Ywidth * Zwidth); + } + } else { + cerr << "Fatal Error: Ballonet shape must be given." << endl; + exit(-1); + } + if (el->FindElement("max_overpressure")) { + MaxOverpressure = el->FindElementValueAsNumberConvertTo("max_overpressure", + "LBS/FT2"); + } + if (el->FindElement("fullness")) { + const double Fullness = el->FindElementValueAsNumber("fullness"); + if (0 <= Fullness) { + Volume = Fullness * MaxVolume; + } else { + cerr << "Warning: Invalid initial ballonet fullness value." << endl; + } + } + if (el->FindElement("valve_coefficient")) { + ValveCoefficient = + el->FindElementValueAsNumberConvertTo("valve_coefficient", + "FT4*SEC/SLUG"); + ValveCoefficient = max(ValveCoefficient, 0.0); + } + + // Initialize state + if (Temperature == 0.0) { + Temperature = Parent->GetTemperature(); + } + if (Pressure == 0.0) { + Pressure = Parent->GetPressure(); + } + if (Volume != 0.0) { + // Calculate initial air content. + Contents = Pressure * Volume / (R * Temperature); + + // Clip to max allowed value. + const double IdealPressure = Contents * R * Temperature / MaxVolume; + if (IdealPressure > Pressure + MaxOverpressure) { + Contents = (Pressure + MaxOverpressure) * MaxVolume / (R * Temperature); + Pressure = Pressure + MaxOverpressure; + } else { + Pressure = max(IdealPressure, Pressure); + } + } else { + // Calculate initial air content. + Contents = Pressure * MaxVolume / (R * Temperature); + } + + Volume = Contents * R * Temperature / Pressure; + + // Bind relevant properties + string property_name, base_property_name; + base_property_name = CreateIndexedPropertyName("buoyant_forces/gas-cell", Parent->GetIndex()); + base_property_name = CreateIndexedPropertyName(base_property_name + "/ballonet", CellNum); + + property_name = base_property_name + "/max_volume-ft3"; + PropertyManager->Tie( property_name, &MaxVolume ); + PropertyManager->SetWritable( property_name, false ); + + property_name = base_property_name + "/temp-R"; + PropertyManager->Tie( property_name, &Temperature ); + + property_name = base_property_name + "/pressure-psf"; + PropertyManager->Tie( property_name, &Pressure ); + + property_name = base_property_name + "/volume-ft3"; + PropertyManager->Tie( property_name, &Volume ); + + property_name = base_property_name + "/contents-mol"; + PropertyManager->Tie( property_name, &Contents ); + + property_name = base_property_name + "/valve_open"; + PropertyManager->Tie( property_name, &ValveOpen ); + + Debug(0); + + // Read heat transfer coefficients + if (Element* heat = el->FindElement("heat")) { + Element* function_element = heat->FindElement("function"); + while (function_element) { + HeatTransferCoeff.push_back(new FGFunction(PropertyManager, + function_element)); + function_element = heat->FindNextElement("function"); + } + } + // Read blower input function + if (Element* blower = el->FindElement("blower_input")) { + Element* function_element = blower->FindElement("function"); + BlowerInput = new FGFunction(PropertyManager, + function_element); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGBallonet::~FGBallonet() { - unsigned int i; + unsigned int i; - for (i = 0; i < HeatTransferCoeff.size(); i++) delete HeatTransferCoeff[i]; - HeatTransferCoeff.clear(); + for (i = 0; i < HeatTransferCoeff.size(); i++) delete HeatTransferCoeff[i]; + HeatTransferCoeff.clear(); - delete BlowerInput; - BlowerInput = NULL; + delete BlowerInput; + BlowerInput = NULL; - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGBallonet::Calculate(double dt) { - const double ParentPressure = Parent->GetPressure(); // [lbs/ft²] - const double AirPressure = Atmosphere->GetPressure(); // [lbs/ft²] - - const double OldTemperature = Temperature; - const double OldPressure = Pressure; - unsigned int i; - - //-- Gas temperature -- - - // The model is based on the ideal gas law. - // However, it does look a bit fishy. Please verify. - // dT/dt = dU / (Cv n R) - dU = 0.0; - for (i = 0; i < HeatTransferCoeff.size(); i++) - { - dU += HeatTransferCoeff[i]->GetValue(); - } - // dt is already accounted for in dVolumeIdeal. - if (Contents > 0) - { - Temperature += - (dU * dt - Pressure * dVolumeIdeal) / (Cv_air * Contents * R); - } - else - { - Temperature = Parent->GetTemperature(); - } - - //-- Pressure -- - const double IdealPressure = Contents * R * Temperature / MaxVolume; - // The pressure is at least that of the parent gas cell. - Pressure = max(IdealPressure, ParentPressure); - - //-- Blower input -- - if (BlowerInput) - { - const double AddedVolume = BlowerInput->GetValue() * dt; - if (AddedVolume > 0.0) - { - Contents += Pressure * AddedVolume / (R * Temperature); - } - } - - //-- Pressure relief and manual valving -- - // FIXME: Presently the effect of valving is computed using - // an ad hoc formula which might not be a good representation - // of reality. - if ((ValveCoefficient > 0.0) && - ((ValveOpen > 0.0) || (Pressure > AirPressure + MaxOverpressure))) - { - const double DeltaPressure = Pressure - AirPressure; - const double VolumeValved = - ((Pressure > AirPressure + MaxOverpressure) ? 1.0 : ValveOpen) * - ValveCoefficient * DeltaPressure * dt; - // FIXME: Too small values of Contents sometimes leads to NaN. - // Currently the minimum is restricted to a safe value. - Contents = - max(1.0, Contents - Pressure * VolumeValved / (R * Temperature)); - } - - //-- Volume -- - Volume = Contents * R * Temperature / Pressure; - dVolumeIdeal = - Contents * R * (Temperature / Pressure - OldTemperature / OldPressure); - - // Compute the inertia of the ballonet. - // Consider the ballonet as a shape of uniform density. - // FIXME: If the ballonet isn't ellipsoid or cylindrical the inertia will - // be wrong. - ballonetJ = FGMatrix33(); - const double mass = Contents * M_air; - double Ixx, Iyy, Izz; - if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && - (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) - { - // Ellipsoid volume. - Ixx = (1.0 / 5.0) * mass * (Yradius*Yradius + Zradius*Zradius); - Iyy = (1.0 / 5.0) * mass * (Xradius*Xradius + Zradius*Zradius); - Izz = (1.0 / 5.0) * mass * (Xradius*Xradius + Yradius*Yradius); - } - else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && - (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) - { - // Cylindrical volume (might not be valid with an elliptical cross-section). - Ixx = (1.0 / 2.0) * mass * Yradius * Zradius; - Iyy = - (1.0 / 4.0) * mass * Yradius * Zradius + - (1.0 / 12.0) * mass * Xwidth * Xwidth; - Izz = - (1.0 / 4.0) * mass * Yradius * Zradius + - (1.0 / 12.0) * mass * Xwidth * Xwidth; - } - else - { - // Not supported. Revert to pointmass model. - Ixx = Iyy = Izz = 0.0; - } - // The volume is symmetric, so Ixy = Ixz = Iyz = 0. - ballonetJ(1,1) = Ixx; - ballonetJ(2,2) = Iyy; - ballonetJ(3,3) = Izz; + const double ParentPressure = Parent->GetPressure(); // [lbs/ft²] + const double AirPressure = Atmosphere->GetPressure(); // [lbs/ft²] + + const double OldTemperature = Temperature; + const double OldPressure = Pressure; + unsigned int i; + + //-- Gas temperature -- + + // The model is based on the ideal gas law. + // However, it does look a bit fishy. Please verify. + // dT/dt = dU / (Cv n R) + dU = 0.0; + for (i = 0; i < HeatTransferCoeff.size(); i++) { + dU += HeatTransferCoeff[i]->GetValue(); + } + // dt is already accounted for in dVolumeIdeal. + if (Contents > 0) { + Temperature += + (dU * dt - Pressure * dVolumeIdeal) / (Cv_air * Contents * R); + } else { + Temperature = Parent->GetTemperature(); + } + + //-- Pressure -- + const double IdealPressure = Contents * R * Temperature / MaxVolume; + // The pressure is at least that of the parent gas cell. + Pressure = max(IdealPressure, ParentPressure); + + //-- Blower input -- + if (BlowerInput) { + const double AddedVolume = BlowerInput->GetValue() * dt; + if (AddedVolume > 0.0) { + Contents += Pressure * AddedVolume / (R * Temperature); + } + } + + //-- Pressure relief and manual valving -- + // FIXME: Presently the effect of valving is computed using + // an ad hoc formula which might not be a good representation + // of reality. + if ((ValveCoefficient > 0.0) && + ((ValveOpen > 0.0) || (Pressure > AirPressure + MaxOverpressure))) { + const double DeltaPressure = Pressure - AirPressure; + const double VolumeValved = + ((Pressure > AirPressure + MaxOverpressure) ? 1.0 : ValveOpen) * + ValveCoefficient * DeltaPressure * dt; + // FIXME: Too small values of Contents sometimes leads to NaN. + // Currently the minimum is restricted to a safe value. + Contents = + max(1.0, Contents - Pressure * VolumeValved / (R * Temperature)); + } + + //-- Volume -- + Volume = Contents * R * Temperature / Pressure; + dVolumeIdeal = + Contents * R * (Temperature / Pressure - OldTemperature / OldPressure); + + // Compute the inertia of the ballonet. + // Consider the ballonet as a shape of uniform density. + // FIXME: If the ballonet isn't ellipsoid or cylindrical the inertia will + // be wrong. + ballonetJ = FGMatrix33(); + const double mass = Contents * M_air; + double Ixx, Iyy, Izz; + if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && + (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { + // Ellipsoid volume. + Ixx = (1.0 / 5.0) * mass * (Yradius*Yradius + Zradius*Zradius); + Iyy = (1.0 / 5.0) * mass * (Xradius*Xradius + Zradius*Zradius); + Izz = (1.0 / 5.0) * mass * (Xradius*Xradius + Yradius*Yradius); + } else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && + (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { + // Cylindrical volume (might not be valid with an elliptical cross-section). + Ixx = (1.0 / 2.0) * mass * Yradius * Zradius; + Iyy = + (1.0 / 4.0) * mass * Yradius * Zradius + + (1.0 / 12.0) * mass * Xwidth * Xwidth; + Izz = + (1.0 / 4.0) * mass * Yradius * Zradius + + (1.0 / 12.0) * mass * Xwidth * Xwidth; + } else { + // Not supported. Revert to pointmass model. + Ixx = Iyy = Izz = 0.0; + } + // The volume is symmetric, so Ixy = Ixz = Iyz = 0. + ballonetJ(1,1) = Ixx; + ballonetJ(2,2) = Iyy; + ballonetJ(3,3) = Izz; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -925,58 +814,50 @@ void FGBallonet::Calculate(double dt) void FGBallonet::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " Ballonet holds " << Contents << " mol air" << endl; - cout << " Location (X, Y, Z) (in.): " << vXYZ(eX) << ", " << - vXYZ(eY) << ", " << vXYZ(eZ) << endl; - cout << " Maximum volume: " << MaxVolume << " ft3" << endl; - cout << " Relief valve release pressure: " << MaxOverpressure << - " lbs/ft2" << endl; - cout << " Relief valve coefficient: " << ValveCoefficient << - " ft4*sec/slug" << endl; - cout << " Initial temperature: " << Temperature << " Rankine" << - endl; - cout << " Initial pressure: " << Pressure << " lbs/ft2" << endl; - cout << " Initial volume: " << Volume << " ft3" << endl; - cout << " Initial mass: " << GetMass() << " slug mass" << endl; - cout << " Initial weight: " << GetMass()*lbtoslug << - " lbs force" << endl; - cout << " Heat transfer: " << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGBallonet" << endl; - if (from == 1) cout << "Destroyed: FGBallonet" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - cout << " Ballonet holds " << Contents << - " mol air" << endl; - cout << " Temperature: " << Temperature << " Rankine" << endl; - cout << " Pressure: " << Pressure << " lbs/ft2" << endl; - cout << " Volume: " << Volume << " ft3" << endl; - cout << " Mass: " << GetMass() << " slug mass" << endl; - cout << " Weight: " << GetMass()*lbtoslug << " lbs force" << endl; - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " Ballonet holds " << Contents << " mol air" << endl; + cout << " Location (X, Y, Z) (in.): " << vXYZ(eX) << ", " << + vXYZ(eY) << ", " << vXYZ(eZ) << endl; + cout << " Maximum volume: " << MaxVolume << " ft3" << endl; + cout << " Relief valve release pressure: " << MaxOverpressure << + " lbs/ft2" << endl; + cout << " Relief valve coefficient: " << ValveCoefficient << + " ft4*sec/slug" << endl; + cout << " Initial temperature: " << Temperature << " Rankine" << + endl; + cout << " Initial pressure: " << Pressure << " lbs/ft2" << endl; + cout << " Initial volume: " << Volume << " ft3" << endl; + cout << " Initial mass: " << GetMass() << " slug mass" << endl; + cout << " Initial weight: " << GetMass()*lbtoslug << + " lbs force" << endl; + cout << " Heat transfer: " << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGBallonet" << endl; + if (from == 1) cout << "Destroyed: FGBallonet" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + cout << " Ballonet holds " << Contents << + " mol air" << endl; + cout << " Temperature: " << Temperature << " Rankine" << endl; + cout << " Pressure: " << Pressure << " lbs/ft2" << endl; + cout << " Volume: " << Volume << " ft3" << endl; + cout << " Mass: " << GetMass() << " slug mass" << endl; + cout << " Weight: " << GetMass()*lbtoslug << " lbs force" << endl; + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; + } + } } } diff --git a/src/models/FGGasCell.h b/src/models/FGGasCell.h index c1fdbbb6467458d180de67a112bd6a7c3b0eff11..de34fb670aef7013f0baa4fa6481ce03b304a591 100644 --- a/src/models/FGGasCell.h +++ b/src/models/FGGasCell.h @@ -56,8 +56,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGBallonet; class Element; @@ -83,7 +82,7 @@ CLASS DOCUMENTATION <z_radius unit="{M | IN}"> {number} </z_radius> <max_overpressure unit="{PA | PSI}"> {number} </max_overpressure> <valve_coefficient unit="{M4*SEC/KG | FT4*SEC/SLUG}"> {number} </valve_coefficient> - <fullness> {number} </fullness> + <fullness> {number} </fullness> <heat> {heat transfer coefficients} [lbs ft / sec] </heat> @@ -98,7 +97,7 @@ CLASS DOCUMENTATION <z_radius unit="{M | IN}"> {number} </z_radius> <max_overpressure unit="{PA | PSI}"> {number} </max_overpressure> <valve_coefficient unit="{M4*SEC/KG | FT4*SEC/SLUG}"> {number} </valve_coefficient> - <fullness> {number} </fullness> + <fullness> {number} </fullness> <heat> {heat transfer coefficients} [lb ft / (sec Rankine)] </heat> @@ -173,152 +172,124 @@ CLASS DECLARATION class FGGasCell : public FGForce { public: - /** Constructor - @param exec Executive a pointer to the parent executive object - @param el Pointer to configuration file XML node - @param num Gas cell index number. */ - FGGasCell(FGFDMExec* exec, Element* el, int num); - ~FGGasCell(); - - /** Runs the gas cell model; called by BuoyantForces - */ - void Calculate(double dt); - - /** Get the index of this gas cell - @return gas cell index. */ - int GetIndex(void) const - { - return CellNum; - } - - /** Get the center of gravity location of the gas cell - (including any ballonets) - @return CoG location in the structural frame. */ - const FGColumnVector3& GetXYZ(void) const - { - return vXYZ; - } - - /** Get the center of gravity location of the gas cell - (including any ballonets) - @return CoG location in the structural frame. */ - double GetXYZ(int idx) const - { - return vXYZ(idx); - } - - /** Get the current mass of the gas cell (including any ballonets) - @return gas mass in slug. */ - double GetMass(void) const - { - return Mass; - } - - /** Get the moments of inertia of the gas cell (including any ballonets) - @return moments of inertia matrix relative the gas cell location - in slug ft<sup>2</sup>. */ - const FGMatrix33& GetInertia(void) const - { - return gasCellJ; - } - - /** Get the moment due to mass of the gas cell (including any ballonets) - - Note that the buoyancy of the gas cell is handled separately by the - FGForce part and not included here. - @return moment vector in lbs ft. */ - const FGColumnVector3& GetMassMoment(void) const - { - return gasCellM; - } - - /** Get the current gas temperature inside the gas cell - @return gas temperature in Rankine. */ - double GetTemperature(void) const - { - return Temperature; - } - - /** Get the current gas pressure inside the gas cell - @return gas pressure in lbs / ft<sup>2</sup>. */ - double GetPressure(void) const - { - return Pressure; - } + /** Constructor + @param exec Executive a pointer to the parent executive object + @param el Pointer to configuration file XML node + @param num Gas cell index number. */ + FGGasCell(FGFDMExec* exec, Element* el, int num); + ~FGGasCell(); + + /** Runs the gas cell model; called by BuoyantForces + */ + void Calculate(double dt); + + /** Get the index of this gas cell + @return gas cell index. */ + int GetIndex(void) const {return CellNum;} + + /** Get the center of gravity location of the gas cell + (including any ballonets) + @return CoG location in the structural frame. */ + const FGColumnVector3& GetXYZ(void) const {return vXYZ;} + + /** Get the center of gravity location of the gas cell + (including any ballonets) + @return CoG location in the structural frame. */ + double GetXYZ(int idx) const {return vXYZ(idx);} + + /** Get the current mass of the gas cell (including any ballonets) + @return gas mass in slug. */ + double GetMass(void) const {return Mass;} + + /** Get the moments of inertia of the gas cell (including any ballonets) + @return moments of inertia matrix relative the gas cell location + in slug ft<sup>2</sup>. */ + const FGMatrix33& GetInertia(void) const {return gasCellJ;} + + /** Get the moment due to mass of the gas cell (including any ballonets) + + Note that the buoyancy of the gas cell is handled separately by the + FGForce part and not included here. + @return moment vector in lbs ft. */ + const FGColumnVector3& GetMassMoment(void) const {return gasCellM;} + + /** Get the current gas temperature inside the gas cell + @return gas temperature in Rankine. */ + double GetTemperature(void) const {return Temperature;} + + /** Get the current gas pressure inside the gas cell + @return gas pressure in lbs / ft<sup>2</sup>. */ + double GetPressure(void) const {return Pressure;} private: - enum GasType {ttUNKNOWN, ttHYDROGEN, ttHELIUM, ttAIR}; - - GasType Type; - std::string type; - int CellNum; - // Structural constants - double MaxVolume; // [ft�] - double MaxOverpressure; // [lbs/ft�] - FGColumnVector3 vXYZ; // [in] - double Xradius, Yradius, Zradius; // [ft] - double Xwidth, Ywidth, Zwidth; // [ft] - double ValveCoefficient; // [ft^4 sec / slug] - typedef vector <FGFunction*> CoeffArray; - CoeffArray HeatTransferCoeff; - typedef vector <FGBallonet*> BallonetArray; - BallonetArray Ballonet; - // Variables - double Pressure; // [lbs/ft�] - double Contents; // [mol] - double Volume; // [ft�] - double dVolumeIdeal; // [ft�] - double Temperature; // [Rankine] - double Buoyancy; // [lbs] Note: Gross lift. - // Does not include the weight of the gas itself. - double ValveOpen; // 0 <= ValveOpen <= 1 (or higher). - double Mass; // [slug] - FGMatrix33 gasCellJ; // [slug foot�] - FGColumnVector3 gasCellM; // [lbs ft] - - FGAuxiliary* Auxiliary; - FGAtmosphere* Atmosphere; - FGPropertyManager* PropertyManager; - FGInertial* Inertial; - FGMassBalance* MassBalance; - void Debug(int from); - - /* Constants. */ - const static double R; // [lbs ft/(mol Rankine)] - const static double M_air; // [slug/mol] - const static double M_hydrogen; // [slug/mol] - const static double M_helium; // [slug/mol] - - double M_gas() // [slug/mol] - { - switch (Type) - { - case ttHYDROGEN: - return M_hydrogen; - case ttHELIUM: - return M_helium; - case ttAIR: - return M_air; - default: - return M_air; - } + enum GasType {ttUNKNOWN, ttHYDROGEN, ttHELIUM, ttAIR}; + + GasType Type; + std::string type; + int CellNum; + // Structural constants + double MaxVolume; // [ft�] + double MaxOverpressure; // [lbs/ft�] + FGColumnVector3 vXYZ; // [in] + double Xradius, Yradius, Zradius; // [ft] + double Xwidth, Ywidth, Zwidth; // [ft] + double ValveCoefficient; // [ft^4 sec / slug] + typedef vector <FGFunction*> CoeffArray; + CoeffArray HeatTransferCoeff; + typedef vector <FGBallonet*> BallonetArray; + BallonetArray Ballonet; + // Variables + double Pressure; // [lbs/ft�] + double Contents; // [mol] + double Volume; // [ft�] + double dVolumeIdeal; // [ft�] + double Temperature; // [Rankine] + double Buoyancy; // [lbs] Note: Gross lift. + // Does not include the weight of the gas itself. + double ValveOpen; // 0 <= ValveOpen <= 1 (or higher). + double Mass; // [slug] + FGMatrix33 gasCellJ; // [slug foot�] + FGColumnVector3 gasCellM; // [lbs ft] + + FGAuxiliary* Auxiliary; + FGAtmosphere* Atmosphere; + FGPropertyManager* PropertyManager; + FGInertial* Inertial; + FGMassBalance* MassBalance; + void Debug(int from); + + /* Constants. */ + const static double R; // [lbs ft/(mol Rankine)] + const static double M_air; // [slug/mol] + const static double M_hydrogen; // [slug/mol] + const static double M_helium; // [slug/mol] + + double M_gas() { // [slug/mol] + switch (Type) { + case ttHYDROGEN: + return M_hydrogen; + case ttHELIUM: + return M_helium; + case ttAIR: + return M_air; + default: + return M_air; } - - double Cv_gas() // [??] - { - switch (Type) - { - case ttHYDROGEN: - return 5.0/2.0; - case ttHELIUM: - return 3.0/2.0; - case ttAIR: - return 5.0/2.0; - default: - return 5.0/2.0; - } + } + + double Cv_gas() { // [??] + switch (Type) { + case ttHYDROGEN: + return 5.0/2.0; + case ttHELIUM: + return 3.0/2.0; + case ttAIR: + return 5.0/2.0; + default: + return 5.0/2.0; } + } }; @@ -332,87 +303,69 @@ private: class FGBallonet : public FGJSBBase { public: - FGBallonet(FGFDMExec* exec, Element* el, int num, FGGasCell* parent); - ~FGBallonet(); + FGBallonet(FGFDMExec* exec, Element* el, int num, FGGasCell* parent); + ~FGBallonet(); - /** Runs the ballonet model; called by FGGasCell - */ - void Calculate(double dt); + /** Runs the ballonet model; called by FGGasCell + */ + void Calculate(double dt); - /** Get the center of gravity location of the ballonet - @return CoG location in the structural frame. */ - const FGColumnVector3& GetXYZ(void) const - { - return vXYZ; - } - /** Get the center of gravity location of the ballonet - @return CoG location in the structural frame. */ - double GetXYZ(int idx) const - { - return vXYZ(idx); - } + /** Get the center of gravity location of the ballonet + @return CoG location in the structural frame. */ + const FGColumnVector3& GetXYZ(void) const {return vXYZ;} + /** Get the center of gravity location of the ballonet + @return CoG location in the structural frame. */ + double GetXYZ(int idx) const {return vXYZ(idx);} - /** Get the current mass of the ballonets - @return mass in slug. */ - double GetMass(void) const - { - return Contents * M_air; - } + /** Get the current mass of the ballonets + @return mass in slug. */ + double GetMass(void) const {return Contents * M_air;} - /** Get the moments of inertia of the ballonet - @return moments of inertia matrix in slug ft<sup>2</sup>. */ - const FGMatrix33& GetInertia(void) const - { - return ballonetJ; - } + /** Get the moments of inertia of the ballonet + @return moments of inertia matrix in slug ft<sup>2</sup>. */ + const FGMatrix33& GetInertia(void) const {return ballonetJ;} - /** Get the current volume of the ballonet - @return volume in ft<sup>3</sup>. */ - double GetVolume(void) const - { - return Volume; - } - /** Get the current heat flow into the ballonet - @return heat flow in lbs ft / sec. */ - double GetHeatFlow(void) const - { - return dU; // [lbs ft / sec] - } + /** Get the current volume of the ballonet + @return volume in ft<sup>3</sup>. */ + double GetVolume(void) const {return Volume;} + /** Get the current heat flow into the ballonet + @return heat flow in lbs ft / sec. */ + double GetHeatFlow(void) const {return dU;} // [lbs ft / sec] private: - int CellNum; - // Structural constants - double MaxVolume; // [ft�] - double MaxOverpressure; // [lbs/ft�] - FGColumnVector3 vXYZ; // [in] - double Xradius, Yradius, Zradius; // [ft] - double Xwidth, Ywidth, Zwidth; // [ft] - double ValveCoefficient; // [ft^4 sec / slug] - typedef vector <FGFunction*> CoeffArray; - CoeffArray HeatTransferCoeff; // [lbs ft / sec] - FGFunction* BlowerInput; // [ft^3 / sec] - FGGasCell* Parent; - // Variables - double Pressure; // [lbs/ft�] - double Contents; // [mol] - double Volume; // [ft�] - double dVolumeIdeal; // [ft�] - double dU; // [lbs ft / sec] - double Temperature; // [Rankine] - double ValveOpen; // 0 <= ValveOpen <= 1 (or higher). - FGMatrix33 ballonetJ; // [slug foot�] - - FGAuxiliary* Auxiliary; - FGAtmosphere* Atmosphere; - FGPropertyManager* PropertyManager; - FGInertial* Inertial; - void Debug(int from); - - /* Constants. */ - const static double R; // [lbs ft/(mol Rankine)] - const static double M_air; // [slug/mol] - const static double Cv_air; // [??] + int CellNum; + // Structural constants + double MaxVolume; // [ft�] + double MaxOverpressure; // [lbs/ft�] + FGColumnVector3 vXYZ; // [in] + double Xradius, Yradius, Zradius; // [ft] + double Xwidth, Ywidth, Zwidth; // [ft] + double ValveCoefficient; // [ft^4 sec / slug] + typedef vector <FGFunction*> CoeffArray; + CoeffArray HeatTransferCoeff; // [lbs ft / sec] + FGFunction* BlowerInput; // [ft^3 / sec] + FGGasCell* Parent; + // Variables + double Pressure; // [lbs/ft�] + double Contents; // [mol] + double Volume; // [ft�] + double dVolumeIdeal; // [ft�] + double dU; // [lbs ft / sec] + double Temperature; // [Rankine] + double ValveOpen; // 0 <= ValveOpen <= 1 (or higher). + FGMatrix33 ballonetJ; // [slug foot�] + + FGAuxiliary* Auxiliary; + FGAtmosphere* Atmosphere; + FGPropertyManager* PropertyManager; + FGInertial* Inertial; + void Debug(int from); + + /* Constants. */ + const static double R; // [lbs ft/(mol Rankine)] + const static double M_air; // [slug/mol] + const static double Cv_air; // [??] }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/FGGroundReactions.cpp b/src/models/FGGroundReactions.cpp index d11ddb8a66f4f34cdf9e3b657138d80dd4f529be..246cefe8cfef140e1ca53c698b6399c3b502ca23 100644 --- a/src/models/FGGroundReactions.cpp +++ b/src/models/FGGroundReactions.cpp @@ -44,10 +44,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGGroundReactions.cpp,v 1.29 2010/07/30 11:50:01 jberndt Exp $"; +static const char *IdSrc = "$Id: FGGroundReactions.cpp,v 1.30 2010/09/07 00:40:03 jberndt Exp $"; static const char *IdHdr = ID_GROUNDREACTIONS; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -55,42 +54,39 @@ CLASS IMPLEMENTATION for MultiplierIterator (See below for FGGroundReactions) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ MultiplierIterator::MultiplierIterator(FGGroundReactions* GndReactions) - : GroundReactions(GndReactions), - multiplier(NULL), - gearNum(0), - entry(0) +: GroundReactions(GndReactions), + multiplier(NULL), + gearNum(0), + entry(0) { - for (int i=0; i < GroundReactions->GetNumGearUnits(); i++) - { - FGLGear* gear = GroundReactions->GetGearUnit(i); + for (int i=0; i < GroundReactions->GetNumGearUnits(); i++) { + FGLGear* gear = GroundReactions->GetGearUnit(i); - if (!gear->GetWOW()) continue; + if (!gear->GetWOW()) continue; - gearNum = i; - multiplier = gear->GetMultiplierEntry(0); - break; - } + gearNum = i; + multiplier = gear->GetMultiplierEntry(0); + break; + } } MultiplierIterator& MultiplierIterator::operator++() { - for (int i=gearNum; i < GroundReactions->GetNumGearUnits(); i++) - { - FGLGear* gear = GroundReactions->GetGearUnit(i); - - if (!gear->GetWOW()) continue; - - multiplier = gear->GetMultiplierEntry(++entry); - if (multiplier) - { - gearNum = i; - break; - } - else - entry = -1; + for (int i=gearNum; i < GroundReactions->GetNumGearUnits(); i++) { + FGLGear* gear = GroundReactions->GetGearUnit(i); + + if (!gear->GetWOW()) continue; + + multiplier = gear->GetMultiplierEntry(++entry); + if (multiplier) { + gearNum = i; + break; } + else + entry = -1; + } - return *this; + return *this; } /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -99,74 +95,71 @@ CLASS IMPLEMENTATION FGGroundReactions::FGGroundReactions(FGFDMExec* fgex) : FGModel(fgex) { - Name = "FGGroundReactions"; + Name = "FGGroundReactions"; - bind(); + bind(); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGGroundReactions::~FGGroundReactions(void) { - for (unsigned int i=0; i<lGear.size();i++) delete lGear[i]; - lGear.clear(); + for (unsigned int i=0; i<lGear.size();i++) delete lGear[i]; + lGear.clear(); - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGGroundReactions::InitModel(void) { - if (!FGModel::InitModel()) return false; + if (!FGModel::InitModel()) return false; - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGGroundReactions::Run(void) { - if (FGModel::Run()) return true; - if (FDMExec->Holding()) return false; - - RunPreFunctions(); - - vForces.InitMatrix(); - vMoments.InitMatrix(); - - // Sum forces and moments for all gear, here. - // Some optimizations may be made here - or rather in the gear code itself. - // The gear ::Run() method is called several times - once for each gear. - // Perhaps there is some commonality for things which only need to be - // calculated once. - for (unsigned int i=0; i<lGear.size(); i++) - { - vForces += lGear[i]->GetBodyForces(); - vMoments += lGear[i]->GetMoments(); - } + if (FGModel::Run()) return true; + if (FDMExec->Holding()) return false; + + RunPreFunctions(); + + vForces.InitMatrix(); + vMoments.InitMatrix(); + + // Sum forces and moments for all gear, here. + // Some optimizations may be made here - or rather in the gear code itself. + // The gear ::Run() method is called several times - once for each gear. + // Perhaps there is some commonality for things which only need to be + // calculated once. + for (unsigned int i=0; i<lGear.size(); i++) { + vForces += lGear[i]->GetBodyForces(); + vMoments += lGear[i]->GetMoments(); + } - RunPostFunctions(); + RunPostFunctions(); - return false; + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGGroundReactions::GetWOW(void) +bool FGGroundReactions::GetWOW(void) const { - bool result = false; - for (unsigned int i=0; i<lGear.size(); i++) - { - if (lGear[i]->IsBogey() && lGear[i]->GetWOW()) - { - result = true; - break; - } + bool result = false; + for (unsigned int i=0; i<lGear.size(); i++) { + if (lGear[i]->IsBogey() && lGear[i]->GetWOW()) { + result = true; + break; } - return result; + } + return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -174,127 +167,122 @@ bool FGGroundReactions::GetWOW(void) // include them in the ground reactions total force and moment. void FGGroundReactions::UpdateForcesAndMoments(void) { - vForces.InitMatrix(); - vMoments.InitMatrix(); + vForces.InitMatrix(); + vMoments.InitMatrix(); - for (unsigned int i=0; i<lGear.size(); i++) - { - vForces += lGear[i]->UpdateForces(); - vMoments += lGear[i]->GetMoments(); - } + for (unsigned int i=0; i<lGear.size(); i++) { + vForces += lGear[i]->UpdateForces(); + vMoments += lGear[i]->GetMoments(); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGGroundReactions::Load(Element* el) { - int num=0; - - Debug(2); + int num=0; - Element* contact_element = el->FindElement("contact"); - while (contact_element) - { - lGear.push_back(new FGLGear(contact_element, FDMExec, num++)); - FCS->AddGear(); // make the FCS aware of the landing gear - contact_element = el->FindNextElement("contact"); - } + Debug(2); - FGModel::Load(el); // Perform base class Load + Element* contact_element = el->FindElement("contact"); + while (contact_element) { + lGear.push_back(new FGLGear(contact_element, FDMExec, num++)); + FCS->AddGear(); // make the FCS aware of the landing gear + contact_element = el->FindNextElement("contact"); + } + + FGModel::Load(el); // Perform base class Load - for (unsigned int i=0; i<lGear.size();i++) lGear[i]->bind(); + for (unsigned int i=0; i<lGear.size();i++) lGear[i]->bind(); - FGModel::PostLoad(el); + PostLoad(el, PropertyManager); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGGroundReactions::GetGroundReactionStrings(string delimeter) { - std::ostringstream buf; - - for (unsigned int i=0;i<lGear.size();i++) - { - if (lGear[i]->IsBogey()) - { - string name = lGear[i]->GetName(); - buf << name << " WOW" << delimeter - << name << " stroke (ft)" << delimeter - << name << " stroke velocity (ft/sec)" << delimeter - << name << " compress force (lbs)" << delimeter - << name << " wheel side force (lbs)" << delimeter - << name << " wheel roll force (lbs)" << delimeter - << name << " body X force (lbs)" << delimeter - << name << " body Y force (lbs)" << delimeter - << name << " wheel velocity vec X (ft/sec)" << delimeter - << name << " wheel velocity vec Y (ft/sec)" << delimeter - << name << " wheel rolling velocity (ft/sec)" << delimeter - << name << " wheel side velocity (ft/sec)" << delimeter - << name << " wheel slip (deg)" << delimeter; - } + std::ostringstream buf; + + for (unsigned int i=0;i<lGear.size();i++) { + if (lGear[i]->IsBogey()) { + string name = lGear[i]->GetName(); + buf << name << " WOW" << delimeter + << name << " stroke (ft)" << delimeter + << name << " stroke velocity (ft/sec)" << delimeter + << name << " compress force (lbs)" << delimeter + << name << " wheel side force (lbs)" << delimeter + << name << " wheel roll force (lbs)" << delimeter + << name << " body X force (lbs)" << delimeter + << name << " body Y force (lbs)" << delimeter + << name << " wheel velocity vec X (ft/sec)" << delimeter + << name << " wheel velocity vec Y (ft/sec)" << delimeter + << name << " wheel rolling velocity (ft/sec)" << delimeter + << name << " wheel side velocity (ft/sec)" << delimeter + << name << " wheel slip (deg)" << delimeter; } + } - buf << " Total Gear Force_X (lbs)" << delimeter - << " Total Gear Force_Y (lbs)" << delimeter - << " Total Gear Force_Z (lbs)" << delimeter - << " Total Gear Moment_L (ft-lbs)" << delimeter - << " Total Gear Moment_M (ft-lbs)" << delimeter - << " Total Gear Moment_N (ft-lbs)"; + buf << " Total Gear Force_X (lbs)" << delimeter + << " Total Gear Force_Y (lbs)" << delimeter + << " Total Gear Force_Z (lbs)" << delimeter + << " Total Gear Moment_L (ft-lbs)" << delimeter + << " Total Gear Moment_M (ft-lbs)" << delimeter + << " Total Gear Moment_N (ft-lbs)"; - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGGroundReactions::GetGroundReactionValues(string delimeter) { - std::ostringstream buf; - - for (unsigned int i=0;i<lGear.size();i++) - { - if (lGear[i]->IsBogey()) - { - FGLGear *gear = lGear[i]; - buf << (gear->GetWOW() ? "1" : "0") << delimeter - << setprecision(5) << gear->GetCompLen() << delimeter - << setprecision(6) << gear->GetCompVel() << delimeter - << setprecision(10) << gear->GetCompForce() << delimeter - << gear->GetWheelSideForce() << delimeter - << gear->GetWheelRollForce() << delimeter - << gear->GetBodyXForce() << delimeter - << gear->GetBodyYForce() << delimeter - << setprecision(6) << gear->GetWheelVel(eX) << delimeter - << gear->GetWheelVel(eY) << delimeter - << gear->GetWheelRollVel() << delimeter - << gear->GetWheelSideVel() << delimeter - << gear->GetWheelSlipAngle() << delimeter; - } + std::ostringstream buf; + + for (unsigned int i=0;i<lGear.size();i++) { + if (lGear[i]->IsBogey()) { + FGLGear *gear = lGear[i]; + buf << (gear->GetWOW() ? "1" : "0") << delimeter + << setprecision(5) << gear->GetCompLen() << delimeter + << setprecision(6) << gear->GetCompVel() << delimeter + << setprecision(10) << gear->GetCompForce() << delimeter + << gear->GetWheelSideForce() << delimeter + << gear->GetWheelRollForce() << delimeter + << gear->GetBodyXForce() << delimeter + << gear->GetBodyYForce() << delimeter + << setprecision(6) << gear->GetWheelVel(eX) << delimeter + << gear->GetWheelVel(eY) << delimeter + << gear->GetWheelRollVel() << delimeter + << gear->GetWheelSideVel() << delimeter + << gear->GetWheelSlipAngle() << delimeter; } + } - buf << vForces(eX) << delimeter - << vForces(eY) << delimeter - << vForces(eZ) << delimeter - << vMoments(eX) << delimeter - << vMoments(eY) << delimeter - << vMoments(eZ); + buf << vForces(eX) << delimeter + << vForces(eY) << delimeter + << vForces(eZ) << delimeter + << vMoments(eX) << delimeter + << vMoments(eY) << delimeter + << vMoments(eZ); - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGGroundReactions::bind(void) { - typedef double (FGGroundReactions::*PMF)(int) const; - PropertyManager->Tie("gear/num-units", this, &FGGroundReactions::GetNumGearUnits); - PropertyManager->Tie("moments/l-gear-lbsft", this, eL, (PMF)&FGGroundReactions::GetMoments); - PropertyManager->Tie("moments/m-gear-lbsft", this, eM, (PMF)&FGGroundReactions::GetMoments); - PropertyManager->Tie("moments/n-gear-lbsft", this, eN, (PMF)&FGGroundReactions::GetMoments); - PropertyManager->Tie("forces/fbx-gear-lbs", this, eX, (PMF)&FGGroundReactions::GetForces); - PropertyManager->Tie("forces/fby-gear-lbs", this, eY, (PMF)&FGGroundReactions::GetForces); - PropertyManager->Tie("forces/fbz-gear-lbs", this, eZ, (PMF)&FGGroundReactions::GetForces); + typedef double (FGGroundReactions::*PMF)(int) const; + PropertyManager->Tie("gear/num-units", this, &FGGroundReactions::GetNumGearUnits); + PropertyManager->Tie("gear/wow", this, &FGGroundReactions::GetWOW); + PropertyManager->Tie("moments/l-gear-lbsft", this, eL, (PMF)&FGGroundReactions::GetMoments); + PropertyManager->Tie("moments/m-gear-lbsft", this, eM, (PMF)&FGGroundReactions::GetMoments); + PropertyManager->Tie("moments/n-gear-lbsft", this, eN, (PMF)&FGGroundReactions::GetMoments); + PropertyManager->Tie("forces/fbx-gear-lbs", this, eX, (PMF)&FGGroundReactions::GetForces); + PropertyManager->Tie("forces/fby-gear-lbs", this, eY, (PMF)&FGGroundReactions::GetForces); + PropertyManager->Tie("forces/fbz-gear-lbs", this, eZ, (PMF)&FGGroundReactions::GetForces); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -318,36 +306,28 @@ void FGGroundReactions::bind(void) void FGGroundReactions::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 2) // Loading - { - cout << endl << " Ground Reactions: " << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGGroundReactions" << endl; - if (from == 1) cout << "Destroyed: FGGroundReactions" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 2) { // Loading + cout << endl << " Ground Reactions: " << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGGroundReactions" << endl; + if (from == 1) cout << "Destroyed: FGGroundReactions" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/FGGroundReactions.h b/src/models/FGGroundReactions.h index f8c1f8994b070d6e732c7dbc145897ee54683824..a10ff0bb13563ee3ee203c6d5ffe230f7bb0fe1d 100644 --- a/src/models/FGGroundReactions.h +++ b/src/models/FGGroundReactions.h @@ -45,14 +45,13 @@ INCLUDES #include "math/FGColumnVector3.h" #include "input_output/FGXMLElement.h" -#define ID_GROUNDREACTIONS "$Id: FGGroundReactions.h,v 1.17 2010/07/30 11:50:01 jberndt Exp $" +#define ID_GROUNDREACTIONS "$Id: FGGroundReactions.h,v 1.18 2010/09/07 00:40:03 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -60,7 +59,7 @@ CLASS DOCUMENTATION /** Manages ground reactions modeling. Maintains a list of landing gear and ground contact points, all instances of FGLGear. Sums their forces and - moments so that these may be provided to FGPropagate. Parses the + moments so that these may be provided to FGPropagate. Parses the \<ground_reactions> section of the aircraft configuration file. <h3>Configuration File Format of \<ground_reactions> Section:</h3> @code @@ -70,7 +69,7 @@ CLASS DOCUMENTATION </contact> ... {more contacts} </ground_reactions> -@endcode +@endcode */ @@ -82,69 +81,48 @@ CLASS DECLARATION class MultiplierIterator { public: - MultiplierIterator(FGGroundReactions* GndReactions); - MultiplierIterator& operator++(); - FGPropagate::LagrangeMultiplier* operator*() - { - return multiplier; - } + MultiplierIterator(FGGroundReactions* GndReactions); + MultiplierIterator& operator++(); + FGPropagate::LagrangeMultiplier* operator*() { return multiplier; } private: - FGGroundReactions* GroundReactions; - FGPropagate::LagrangeMultiplier* multiplier; - int gearNum; - int entry; + FGGroundReactions* GroundReactions; + FGPropagate::LagrangeMultiplier* multiplier; + int gearNum; + int entry; }; class FGGroundReactions : public FGModel { public: - FGGroundReactions(FGFDMExec*); - ~FGGroundReactions(void); - - bool InitModel(void); - bool Run(void); - bool Load(Element* el); - FGColumnVector3& GetForces(void) - { - return vForces; - } - double GetForces(int idx) const - { - return vForces(idx); - } - FGColumnVector3& GetMoments(void) - { - return vMoments; - } - double GetMoments(int idx) const - { - return vMoments(idx); - } - string GetGroundReactionStrings(string delimeter); - string GetGroundReactionValues(string delimeter); - bool GetWOW(void); - void UpdateForcesAndMoments(void); - - int GetNumGearUnits(void) const - { - return (int)lGear.size(); - } - - /** Gets a gear instance - @param gear index of gear instance - @return a pointer to the FGLGear instance of the gear unit requested */ - inline FGLGear* GetGearUnit(int gear) - { - return lGear[gear]; - } + FGGroundReactions(FGFDMExec*); + ~FGGroundReactions(void); + + bool InitModel(void); + bool Run(void); + bool Load(Element* el); + FGColumnVector3& GetForces(void) {return vForces;} + double GetForces(int idx) const {return vForces(idx);} + FGColumnVector3& GetMoments(void) {return vMoments;} + double GetMoments(int idx) const {return vMoments(idx);} + string GetGroundReactionStrings(string delimeter); + string GetGroundReactionValues(string delimeter); + bool GetWOW(void) const; + void UpdateForcesAndMoments(void); + + int GetNumGearUnits(void) const { return (int)lGear.size(); } + + /** Gets a gear instance + @param gear index of gear instance + @return a pointer to the FGLGear instance of the gear unit requested */ + inline FGLGear* GetGearUnit(int gear) { return lGear[gear]; } private: - vector <FGLGear*> lGear; - FGColumnVector3 vForces; - FGColumnVector3 vMoments; + vector <FGLGear*> lGear; + FGColumnVector3 vForces; + FGColumnVector3 vMoments; - void bind(void); - void Debug(int from); + void bind(void); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/FGInertial.cpp b/src/models/FGInertial.cpp index 265196e6eb8cc92e3a4ef812076b51a9f8312ea4..ab2670eb97700868ada2dc29b2ef43ad121e1157 100644 --- a/src/models/FGInertial.cpp +++ b/src/models/FGInertial.cpp @@ -43,8 +43,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGInertial.cpp,v 1.18 2010/03/28 05:57:00 jberndt Exp $"; static const char *IdHdr = ID_INERTIAL; @@ -56,81 +55,81 @@ CLASS IMPLEMENTATION FGInertial::FGInertial(FGFDMExec* fgex) : FGModel(fgex) { - Name = "FGInertial"; - - // Earth defaults - RotationRate = 0.00007292115; - GM = 14.07644180E15; // WGS84 value - RadiusReference = 20925650.00; // Equatorial radius (WGS84) - C2_0 = -4.84165371736E-04; // WGS84 value for the C2,0 coefficient - J2 = 1.0826266836E-03; // WGS84 value for J2 - a = 20925646.3255; // WGS84 semimajor axis length in feet - b = 20855486.5951; // WGS84 semiminor axis length in feet - earthPosAngle = 0.0; - - // Lunar defaults - /* - RotationRate = 0.0000026617; - GM = 1.7314079E14; // Lunar GM - RadiusReference = 5702559.05; // Equatorial radius - C2_0 = 0; // value for the C2,0 coefficient - J2 = 2.033542482111609E-4; // value for J2 - a = 5702559.05; // semimajor axis length in feet - b = 5695439.63; // semiminor axis length in feet - earthPosAngle = 0.0; - */ - - gAccelReference = GM/(RadiusReference*RadiusReference); - gAccel = GM/(RadiusReference*RadiusReference); - - bind(); - - Debug(0); + Name = "FGInertial"; + + // Earth defaults + RotationRate = 0.00007292115; + GM = 14.07644180E15; // WGS84 value + RadiusReference = 20925650.00; // Equatorial radius (WGS84) + C2_0 = -4.84165371736E-04; // WGS84 value for the C2,0 coefficient + J2 = 1.0826266836E-03; // WGS84 value for J2 + a = 20925646.3255; // WGS84 semimajor axis length in feet + b = 20855486.5951; // WGS84 semiminor axis length in feet + earthPosAngle = 0.0; + + // Lunar defaults + /* + RotationRate = 0.0000026617; + GM = 1.7314079E14; // Lunar GM + RadiusReference = 5702559.05; // Equatorial radius + C2_0 = 0; // value for the C2,0 coefficient + J2 = 2.033542482111609E-4; // value for J2 + a = 5702559.05; // semimajor axis length in feet + b = 5695439.63; // semiminor axis length in feet + earthPosAngle = 0.0; + */ + + gAccelReference = GM/(RadiusReference*RadiusReference); + gAccel = GM/(RadiusReference*RadiusReference); + + bind(); + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGInertial::~FGInertial(void) { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGInertial::InitModel(void) { - if (!FGModel::InitModel()) return false; + if (!FGModel::InitModel()) return false; - earthPosAngle = 0.0; + earthPosAngle = 0.0; - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGInertial::Run(void) { - // Fast return if we have nothing to do ... - if (FGModel::Run()) return true; - if (FDMExec->Holding()) return false; + // Fast return if we have nothing to do ... + if (FGModel::Run()) return true; + if (FDMExec->Holding()) return false; - RunPreFunctions(); + RunPreFunctions(); - // Gravitation accel - double r = Propagate->GetRadius(); - gAccel = GetGAccel(r); - earthPosAngle += FDMExec->GetDeltaT()*RotationRate; + // Gravitation accel + double r = Propagate->GetRadius(); + gAccel = GetGAccel(r); + earthPosAngle += FDMExec->GetDeltaT()*RotationRate; - RunPostFunctions(); + RunPostFunctions(); - return false; + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGInertial::GetGAccel(double r) const { - return GM/(r*r); + return GM/(r*r); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -142,30 +141,30 @@ double FGInertial::GetGAccel(double r) const FGColumnVector3 FGInertial::GetGravityJ2(FGColumnVector3 position) const { - FGColumnVector3 J2Gravity; + FGColumnVector3 J2Gravity; - // Gravitation accel - double r = position.Magnitude(); - double lat = Propagate->GetLatitude(); - double sinLat = sin(lat); + // Gravitation accel + double r = position.Magnitude(); + double lat = Propagate->GetLatitude(); + double sinLat = sin(lat); - double preCommon = 1.5*J2*(a/r)*(a/r); - double xy = 1.0 - 5.0*(sinLat*sinLat); - double z = 3.0 - 5.0*(sinLat*sinLat); - double GMOverr2 = GM/(r*r); + double preCommon = 1.5*J2*(a/r)*(a/r); + double xy = 1.0 - 5.0*(sinLat*sinLat); + double z = 3.0 - 5.0*(sinLat*sinLat); + double GMOverr2 = GM/(r*r); - J2Gravity(1) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eX)/r); - J2Gravity(2) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eY)/r); - J2Gravity(3) = -GMOverr2 * ((1.0 + (preCommon * z)) * position(eZ)/r); + J2Gravity(1) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eX)/r); + J2Gravity(2) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eY)/r); + J2Gravity(3) = -GMOverr2 * ((1.0 + (preCommon * z)) * position(eZ)/r); - return J2Gravity; + return J2Gravity; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGInertial::bind(void) { - PropertyManager->Tie("position/epa-rad", this, &FGInertial::GetEarthPositionAngle); + PropertyManager->Tie("position/epa-rad", this, &FGInertial::GetEarthPositionAngle); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -189,36 +188,28 @@ void FGInertial::bind(void) void FGInertial::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGInertial" << endl; - if (from == 1) cout << "Destroyed: FGInertial" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGInertial" << endl; + if (from == 1) cout << "Destroyed: FGInertial" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/FGInertial.h b/src/models/FGInertial.h index 8e377781fe91c575069e7c335d4b5e2e37400585..f4db378a2dc24da6060f7a18a416450a2ba3032e 100644 --- a/src/models/FGInertial.h +++ b/src/models/FGInertial.h @@ -53,8 +53,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -68,70 +67,42 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGInertial : public FGModel -{ +class FGInertial : public FGModel { public: - FGInertial(FGFDMExec*); - ~FGInertial(void); - - bool InitModel(void); - - bool Run(void); - double SLgravity(void) const - { - return gAccelReference; - } - double gravity(void) const - { - return gAccel; - } - double omega(void) const - { - return RotationRate; - } - double GetEarthPositionAngle(void) const - { - return earthPosAngle; - } - double GetEarthPositionAngleDeg(void) const - { - return earthPosAngle*radtodeg; - } - double GetGAccel(double r) const; - FGColumnVector3 GetGravityJ2(FGColumnVector3 position) const; - double GetRefRadius(void) const - { - return RadiusReference; - } - double GetSemimajor(void) const - { - return a; - } - double GetSemiminor(void) const - { - return b; - } - - void SetEarthPositionAngle(double epa) - { - earthPosAngle = epa; - } + FGInertial(FGFDMExec*); + ~FGInertial(void); + + bool InitModel(void); + + bool Run(void); + double SLgravity(void) const {return gAccelReference;} + double gravity(void) const {return gAccel;} + double omega(void) const {return RotationRate;} + double GetEarthPositionAngle(void) const { return earthPosAngle; } + double GetEarthPositionAngleDeg(void) const { return earthPosAngle*radtodeg;} + double GetGAccel(double r) const; + FGColumnVector3 GetGravityJ2(FGColumnVector3 position) const; + double GetRefRadius(void) const {return RadiusReference;} + double GetSemimajor(void) const {return a;} + double GetSemiminor(void) const {return b;} + + void SetEarthPositionAngle(double epa) {earthPosAngle = epa;} private: - double gAccel; - double gAccelReference; - double RadiusReference; - double RotationRate; - double earthPosAngle; - double GM; - double C2_0; // WGS84 value for the C2,0 coefficient - double J2; // WGS84 value for J2 - double a; // WGS84 semimajor axis length in feet - double b; // WGS84 semiminor axis length in feet - - void bind(void); - void Debug(int from); + double gAccel; + double gAccelReference; + double RadiusReference; + double RotationRate; + double earthPosAngle; + double GM; + double C2_0; // WGS84 value for the C2,0 coefficient + double J2; // WGS84 value for J2 + double a; // WGS84 semimajor axis length in feet + double b; // WGS84 semiminor axis length in feet + + void bind(void); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/FGInput.cpp b/src/models/FGInput.cpp old mode 100644 new mode 100755 index 07950685eec16f53345994752485b60c6454312b..c8cc13b83c3514e39f38489c71515d398ad114f3 --- a/src/models/FGInput.cpp +++ b/src/models/FGInput.cpp @@ -51,8 +51,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGInput.cpp,v 1.19 2010/02/25 05:21:36 jberndt Exp $"; static const char *IdHdr = ID_INPUT; @@ -63,30 +62,30 @@ CLASS IMPLEMENTATION FGInput::FGInput(FGFDMExec* fdmex) : FGModel(fdmex) { - Name = "FGInput"; - sFirstPass = dFirstPass = true; - socket = 0; - port = 0; - enabled = true; + Name = "FGInput"; + sFirstPass = dFirstPass = true; + socket = 0; + port = 0; + enabled = true; - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGInput::~FGInput() { - delete socket; - Debug(1); + delete socket; + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGInput::InitModel(void) { - if (!FGModel::InitModel()) return false; + if (!FGModel::InitModel()) return false; - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -96,190 +95,155 @@ bool FGInput::InitModel(void) bool FGInput::Run(void) { - string line, token; - size_t start=0, string_start=0, string_end=0; - double value=0; - FGPropertyManager* node=0; - - if (FGModel::Run()) return true; // fast exit if nothing to do - if (port == 0) return false; // Do nothing here if port not defined - // return false if no error - // This model DOES execute if "Exec->Holding" - - RunPreFunctions(); - - data = socket->Receive(); // get socket transmission if present - - if (data.size() > 0) - { - // parse lines - while (1) - { - string_start = data.find_first_not_of("\r\n", start); - if (string_start == string::npos) break; - string_end = data.find_first_of("\r\n", string_start); - if (string_end == string::npos) break; - line = data.substr(string_start, string_end-string_start); - if (line.size() == 0) break; - - // now parse individual line - vector <string> tokens = split(line,' '); - - string command="", argument="", str_value=""; - if (tokens.size() > 0) - { - command = to_lower(tokens[0]); - if (tokens.size() > 1) - { - argument = trim(tokens[1]); - if (tokens.size() > 2) - { - str_value = trim(tokens[2]); - } - } - } - - if (command == "set") // SET PROPERTY - { - - node = PropertyManager->GetNode(argument); - if (node == 0) - socket->Reply("Unknown property\n"); - else - { - value = atof(str_value.c_str()); - node->setDoubleValue(value); - } - socket->Reply(""); - - } - else if (command == "get") // GET PROPERTY - { - - if (argument.size() == 0) - { - socket->Reply("No property argument supplied.\n"); - break; - } - try - { - node = PropertyManager->GetNode(argument); - } - catch (...) - { - socket->Reply("Badly formed property query\n"); - break; - } - if (node == 0) - { - if (FDMExec->Holding()) // if holding can query property list - { - string query = FDMExec->QueryPropertyCatalog(argument); - socket->Reply(query); - } - else - { - socket->Reply("Must be in HOLD to search properties\n"); - } - } - else if (node > 0) - { - ostringstream buf; - buf << argument << " = " << setw(12) << setprecision(6) << node->getDoubleValue() << endl; - socket->Reply(buf.str()); - } - - } - else if (command == "hold") // PAUSE - { - - FDMExec->Hold(); - socket->Reply(""); - - } - else if (command == "resume") // RESUME - { - - FDMExec->Resume(); - socket->Reply(""); - - } - else if (command == "quit") // QUIT - { - - // close the socket connection - socket->Reply(""); - socket->Close(); - - } - else if (command == "info") // INFO - { - - // get info about the sim run and/or aircraft, etc. - ostringstream info; - info << "JSBSim version: " << JSBSim_version << endl; - info << "Config File version: " << needed_cfg_version << endl; - info << "Aircraft simulated: " << Aircraft->GetAircraftName() << endl; - info << "Simulation time: " << setw(8) << setprecision(3) << FDMExec->GetSimTime() << endl; - socket->Reply(info.str()); - - } - else if (command == "help") // HELP - { - - socket->Reply( - " JSBSim Server commands:\n\n" - " get {property name}\n" - " set {property name} {value}\n" - " hold\n" - " resume\n" - " help\n" - " quit\n" - " info\n\n"); - - } - else - { - socket->Reply(string("Unknown command: ") + token + string("\n")); - } - - start = string_end; + string line, token; + size_t start=0, string_start=0, string_end=0; + double value=0; + FGPropertyManager* node=0; + + if (FGModel::Run()) return true; // fast exit if nothing to do + if (port == 0) return false; // Do nothing here if port not defined + // return false if no error + // This model DOES execute if "Exec->Holding" + + RunPreFunctions(); + + data = socket->Receive(); // get socket transmission if present + + if (data.size() > 0) { + // parse lines + while (1) { + string_start = data.find_first_not_of("\r\n", start); + if (string_start == string::npos) break; + string_end = data.find_first_of("\r\n", string_start); + if (string_end == string::npos) break; + line = data.substr(string_start, string_end-string_start); + if (line.size() == 0) break; + + // now parse individual line + vector <string> tokens = split(line,' '); + + string command="", argument="", str_value=""; + if (tokens.size() > 0) { + command = to_lower(tokens[0]); + if (tokens.size() > 1) { + argument = trim(tokens[1]); + if (tokens.size() > 2) { + str_value = trim(tokens[2]); + } + } + } + + if (command == "set") { // SET PROPERTY + + node = PropertyManager->GetNode(argument); + if (node == 0) + socket->Reply("Unknown property\n"); + else { + value = atof(str_value.c_str()); + node->setDoubleValue(value); + } + socket->Reply(""); + + } else if (command == "get") { // GET PROPERTY + + if (argument.size() == 0) { + socket->Reply("No property argument supplied.\n"); + break; + } + try { + node = PropertyManager->GetNode(argument); + } catch(...) { + socket->Reply("Badly formed property query\n"); + break; + } + if (node == 0) { + if (FDMExec->Holding()) { // if holding can query property list + string query = FDMExec->QueryPropertyCatalog(argument); + socket->Reply(query); + } else { + socket->Reply("Must be in HOLD to search properties\n"); + } + } else if (node > 0) { + ostringstream buf; + buf << argument << " = " << setw(12) << setprecision(6) << node->getDoubleValue() << endl; + socket->Reply(buf.str()); } + + } else if (command == "hold") { // PAUSE + + FDMExec->Hold(); + socket->Reply(""); + + } else if (command == "resume") { // RESUME + + FDMExec->Resume(); + socket->Reply(""); + + } else if (command == "quit") { // QUIT + + // close the socket connection + socket->Reply(""); + socket->Close(); + + } else if (command == "info") { // INFO + + // get info about the sim run and/or aircraft, etc. + ostringstream info; + info << "JSBSim version: " << JSBSim_version << endl; + info << "Config File version: " << needed_cfg_version << endl; + info << "Aircraft simulated: " << Aircraft->GetAircraftName() << endl; + info << "Simulation time: " << setw(8) << setprecision(3) << FDMExec->GetSimTime() << endl; + socket->Reply(info.str()); + + } else if (command == "help") { // HELP + + socket->Reply( + " JSBSim Server commands:\n\n" + " get {property name}\n" + " set {property name} {value}\n" + " hold\n" + " resume\n" + " help\n" + " quit\n" + " info\n\n"); + + } else { + socket->Reply(string("Unknown command: ") + token + string("\n")); + } + + start = string_end; } + } - RunPostFunctions(); + RunPostFunctions(); - return false; + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGInput::Load(Element* element) { - string type="", parameter=""; - string name="", fname=""; - string property; - - // if the input has already been set up, print a warning message and return - if (port > 0) - { - cerr << "An input port has already been assigned for this run" << endl; - return false; - } + string type="", parameter=""; + string name="", fname=""; + string property; - port = int(element->GetAttributeValueAsNumber("port")); - if (port == 0) - { - cerr << endl << "No port assigned in input element" << endl; - } - else - { - socket = new FGfdmSocket(port); - } + // if the input has already been set up, print a warning message and return + if (port > 0) { + cerr << "An input port has already been assigned for this run" << endl; + return false; + } + + port = int(element->GetAttributeValueAsNumber("port")); + if (port == 0) { + cerr << endl << "No port assigned in input element" << endl; + } else { + socket = new FGfdmSocket(port); + } - Debug(2); + Debug(2); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -303,40 +267,31 @@ bool FGInput::Load(Element* element) void FGInput::Debug(int from) { - string scratch=""; + string scratch=""; - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - } - if (from == 2) - { - } + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGInput" << endl; - if (from == 1) cout << "Destroyed: FGInput" << endl; + if (from == 2) { } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGInput" << endl; + if (from == 1) cout << "Destroyed: FGInput" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/FGInput.h b/src/models/FGInput.h old mode 100644 new mode 100755 index 476bd54a47be1d78d7e993b8bbe35350c2a614f4..b86a428c6097d20c189cf8a585dbe840eb3b0f33 --- a/src/models/FGInput.h +++ b/src/models/FGInput.h @@ -52,8 +52,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFDMExec; class Element; @@ -73,33 +72,23 @@ CLASS DECLARATION class FGInput : public FGModel { public: - FGInput(FGFDMExec*); - ~FGInput(); - - bool InitModel(void); - bool Run(void); - - inline void Enable(void) - { - enabled = true; - } - inline void Disable(void) - { - enabled = false; - } - inline bool Toggle(void) - { - enabled = !enabled; - return enabled; - } - bool Load(Element* el); + FGInput(FGFDMExec*); + ~FGInput(); + + bool InitModel(void); + bool Run(void); + + inline void Enable(void) { enabled = true; } + inline void Disable(void) { enabled = false; } + inline bool Toggle(void) {enabled = !enabled; return enabled;} + bool Load(Element* el); private: - bool sFirstPass, dFirstPass, enabled; - unsigned int port; - FGfdmSocket* socket; - std::string data; - void Debug(int from); + bool sFirstPass, dFirstPass, enabled; + unsigned int port; + FGfdmSocket* socket; + std::string data; + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/FGLGear.cpp b/src/models/FGLGear.cpp index 70f93eb171305899e8a19c0fa56557eed11632a3..054f90ccd0354d8b0a3b1f663ee46563c790713f 100644 --- a/src/models/FGLGear.cpp +++ b/src/models/FGLGear.cpp @@ -48,11 +48,11 @@ INCLUDES #include "FGMassBalance.h" #include "math/FGTable.h" #include <cstdlib> +#include <cstring> using namespace std; -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS @@ -62,7 +62,7 @@ DEFINITIONS GLOBAL DATA %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -static const char *IdSrc = "$Id: FGLGear.cpp,v 1.76 2010/07/30 11:50:01 jberndt Exp $"; +static const char *IdSrc = "$Id: FGLGear.cpp,v 1.77 2010/09/24 19:55:33 andgi Exp $"; static const char *IdHdr = ID_LGEAR; // Body To Structural (body frame is rotated 180 deg about Y and lengths are given in @@ -74,361 +74,313 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) : - FGForce(fdmex), - GearNumber(number), - SteerAngle(0.0), - Castered(false) + FGForce(fdmex), + GearNumber(number), + SteerAngle(0.0), + Castered(false), + StaticFriction(false) { - Element *force_table=0; - Element *dampCoeff=0; - Element *dampCoeffRebound=0; - string force_type=""; - - kSpring = bDamp = bDampRebound = dynamicFCoeff = staticFCoeff = rollingFCoeff = maxSteerAngle = 0; - sSteerType = sBrakeGroup = sSteerType = ""; - isRetractable = 0; - eDampType = dtLinear; - eDampTypeRebound = dtLinear; - - name = el->GetAttributeValue("name"); - sContactType = el->GetAttributeValue("type"); - if (sContactType == "BOGEY") - { - eContactType = ctBOGEY; - } - else if (sContactType == "STRUCTURE") - { - eContactType = ctSTRUCTURE; - } - else - { - // Unknown contact point types will be treated as STRUCTURE. - eContactType = ctSTRUCTURE; - } + Element *force_table=0; + Element *dampCoeff=0; + Element *dampCoeffRebound=0; + string force_type=""; + + kSpring = bDamp = bDampRebound = dynamicFCoeff = staticFCoeff = rollingFCoeff = maxSteerAngle = 0; + sSteerType = sBrakeGroup = sSteerType = ""; + isRetractable = 0; + eDampType = dtLinear; + eDampTypeRebound = dtLinear; + + name = el->GetAttributeValue("name"); + sContactType = el->GetAttributeValue("type"); + if (sContactType == "BOGEY") { + eContactType = ctBOGEY; + } else if (sContactType == "STRUCTURE") { + eContactType = ctSTRUCTURE; + } else { + // Unknown contact point types will be treated as STRUCTURE. + eContactType = ctSTRUCTURE; + } + + if (el->FindElement("spring_coeff")) + kSpring = el->FindElementValueAsNumberConvertTo("spring_coeff", "LBS/FT"); + if (el->FindElement("damping_coeff")) { + dampCoeff = el->FindElement("damping_coeff"); + if (dampCoeff->GetAttributeValue("type") == "SQUARE") { + eDampType = dtSquare; + bDamp = el->FindElementValueAsNumberConvertTo("damping_coeff", "LBS/FT2/SEC2"); + } else { + bDamp = el->FindElementValueAsNumberConvertTo("damping_coeff", "LBS/FT/SEC"); + } + } + + if (el->FindElement("damping_coeff_rebound")) { + dampCoeffRebound = el->FindElement("damping_coeff_rebound"); + if (dampCoeffRebound->GetAttributeValue("type") == "SQUARE") { + eDampTypeRebound = dtSquare; + bDampRebound = el->FindElementValueAsNumberConvertTo("damping_coeff_rebound", "LBS/FT2/SEC2"); + } else { + bDampRebound = el->FindElementValueAsNumberConvertTo("damping_coeff_rebound", "LBS/FT/SEC"); + } + } else { + bDampRebound = bDamp; + eDampTypeRebound = eDampType; + } + + if (el->FindElement("dynamic_friction")) + dynamicFCoeff = el->FindElementValueAsNumber("dynamic_friction"); + if (el->FindElement("static_friction")) + staticFCoeff = el->FindElementValueAsNumber("static_friction"); + if (el->FindElement("rolling_friction")) + rollingFCoeff = el->FindElementValueAsNumber("rolling_friction"); + if (el->FindElement("max_steer")) + maxSteerAngle = el->FindElementValueAsNumberConvertTo("max_steer", "DEG"); + if (el->FindElement("retractable")) + isRetractable = ((unsigned int)el->FindElementValueAsNumber("retractable"))>0.0?true:false; + + ForceY_Table = 0; + force_table = el->FindElement("table"); + while (force_table) { + force_type = force_table->GetAttributeValue("type"); + if (force_type == "CORNERING_COEFF") { + ForceY_Table = new FGTable(fdmex->GetPropertyManager(), force_table); + } else { + cerr << "Undefined force table for " << name << " contact point" << endl; + } + force_table = el->FindNextElement("table"); + } + + sBrakeGroup = el->FindElementValue("brake_group"); + + if (maxSteerAngle == 360) sSteerType = "CASTERED"; + else if (maxSteerAngle == 0.0) sSteerType = "FIXED"; + else sSteerType = "STEERABLE"; + + Element* element = el->FindElement("location"); + if (element) vXYZn = element->FindElementTripletConvertTo("IN"); + else {cerr << "No location given for contact " << name << endl; exit(-1);} + SetTransformType(FGForce::tCustom); + + element = el->FindElement("orientation"); + if (element && (eContactType == ctBOGEY)) { + vGearOrient = element->FindElementTripletConvertTo("RAD"); + + double cp,sp,cr,sr,cy,sy; + + cp=cos(vGearOrient(ePitch)); sp=sin(vGearOrient(ePitch)); + cr=cos(vGearOrient(eRoll)); sr=sin(vGearOrient(eRoll)); + cy=cos(vGearOrient(eYaw)); sy=sin(vGearOrient(eYaw)); + + mTGear(1,1) = cp*cy; + mTGear(2,1) = cp*sy; + mTGear(3,1) = -sp; + + mTGear(1,2) = sr*sp*cy - cr*sy; + mTGear(2,2) = sr*sp*sy + cr*cy; + mTGear(3,2) = sr*cp; + + mTGear(1,3) = cr*sp*cy + sr*sy; + mTGear(2,3) = cr*sp*sy - sr*cy; + mTGear(3,3) = cr*cp; + } + else { + mTGear(1,1) = 1.; + mTGear(2,2) = 1.; + mTGear(3,3) = 1.; + } + + if (sBrakeGroup == "LEFT" ) eBrakeGrp = bgLeft; + else if (sBrakeGroup == "RIGHT" ) eBrakeGrp = bgRight; + else if (sBrakeGroup == "CENTER") eBrakeGrp = bgCenter; + else if (sBrakeGroup == "NOSE" ) eBrakeGrp = bgNose; + else if (sBrakeGroup == "TAIL" ) eBrakeGrp = bgTail; + else if (sBrakeGroup == "NONE" ) eBrakeGrp = bgNone; + else if (sBrakeGroup.empty() ) {eBrakeGrp = bgNone; + sBrakeGroup = "NONE (defaulted)";} + else { + cerr << "Improper braking group specification in config file: " + << sBrakeGroup << " is undefined." << endl; + } + + if (sSteerType == "STEERABLE") eSteerType = stSteer; + else if (sSteerType == "FIXED" ) eSteerType = stFixed; + else if (sSteerType == "CASTERED" ) {eSteerType = stCaster; Castered = true;} + else if (sSteerType.empty() ) {eSteerType = stFixed; + sSteerType = "FIXED (defaulted)";} + else { + cerr << "Improper steering type specification in config file: " + << sSteerType << " is undefined." << endl; + } + + Auxiliary = fdmex->GetAuxiliary(); + Propagate = fdmex->GetPropagate(); + FCS = fdmex->GetFCS(); + MassBalance = fdmex->GetMassBalance(); + GroundReactions = fdmex->GetGroundReactions(); + + GearUp = false; + GearDown = true; + GearPos = 1.0; + useFCSGearPos = false; + Servicable = true; - if (el->FindElement("spring_coeff")) - kSpring = el->FindElementValueAsNumberConvertTo("spring_coeff", "LBS/FT"); - if (el->FindElement("damping_coeff")) - { - dampCoeff = el->FindElement("damping_coeff"); - if (dampCoeff->GetAttributeValue("type") == "SQUARE") - { - eDampType = dtSquare; - bDamp = el->FindElementValueAsNumberConvertTo("damping_coeff", "LBS/FT2/SEC2"); - } - else - { - bDamp = el->FindElementValueAsNumberConvertTo("damping_coeff", "LBS/FT/SEC"); - } - } +// Add some AI here to determine if gear is located properly according to its +// brake group type ?? - if (el->FindElement("damping_coeff_rebound")) - { - dampCoeffRebound = el->FindElement("damping_coeff_rebound"); - if (dampCoeffRebound->GetAttributeValue("type") == "SQUARE") - { - eDampTypeRebound = dtSquare; - bDampRebound = el->FindElementValueAsNumberConvertTo("damping_coeff_rebound", "LBS/FT2/SEC2"); - } - else - { - bDampRebound = el->FindElementValueAsNumberConvertTo("damping_coeff_rebound", "LBS/FT/SEC"); - } - } - else - { - bDampRebound = bDamp; - eDampTypeRebound = eDampType; - } + WOW = lastWOW = false; + ReportEnable = true; + FirstContact = false; + StartedGroundRun = false; + TakeoffReported = LandingReported = false; + LandingDistanceTraveled = TakeoffDistanceTraveled = TakeoffDistanceTraveled50ft = 0.0; + MaximumStrutForce = MaximumStrutTravel = 0.0; + SinkRate = GroundSpeed = 0.0; - if (el->FindElement("dynamic_friction")) - dynamicFCoeff = el->FindElementValueAsNumber("dynamic_friction"); - if (el->FindElement("static_friction")) - staticFCoeff = el->FindElementValueAsNumber("static_friction"); - if (el->FindElement("rolling_friction")) - rollingFCoeff = el->FindElementValueAsNumber("rolling_friction"); - if (el->FindElement("max_steer")) - maxSteerAngle = el->FindElementValueAsNumberConvertTo("max_steer", "DEG"); - if (el->FindElement("retractable")) - isRetractable = ((unsigned int)el->FindElementValueAsNumber("retractable"))>0.0?true:false; - - ForceY_Table = 0; - force_table = el->FindElement("table"); - while (force_table) - { - force_type = force_table->GetAttributeValue("type"); - if (force_type == "CORNERING_COEFF") - { - ForceY_Table = new FGTable(fdmex->GetPropertyManager(), force_table); - } - else - { - cerr << "Undefined force table for " << name << " contact point" << endl; - } - force_table = el->FindNextElement("table"); - } + vWhlBodyVec = MassBalance->StructuralToBody(vXYZn); + vLocalGear = Propagate->GetTb2l() * vWhlBodyVec; + vWhlVelVec.InitMatrix(); - sBrakeGroup = el->FindElementValue("brake_group"); + compressLength = 0.0; + compressSpeed = 0.0; + brakePct = 0.0; + maxCompLen = 0.0; - if (maxSteerAngle == 360) sSteerType = "CASTERED"; - else if (maxSteerAngle == 0.0) sSteerType = "FIXED"; - else sSteerType = "STEERABLE"; + WheelSlip = 0.0; + TirePressureNorm = 1.0; - Element* element = el->FindElement("location"); - if (element) vXYZn = element->FindElementTripletConvertTo("IN"); - else - { - cerr << "No location given for contact " << name << endl; - exit(-1); - } - SetTransformType(FGForce::tCustom); + // Set Pacejka terms + + Stiffness = 0.06; + Shape = 2.8; + Peak = staticFCoeff; + Curvature = 1.03; + + // Initialize Lagrange multipliers + memset(LMultiplier, 0, sizeof(LMultiplier)); + + Debug(0); +} - element = el->FindElement("orientation"); - if (element && (eContactType == ctBOGEY)) - { - vGearOrient = element->FindElementTripletConvertTo("RAD"); +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - double cp,sp,cr,sr,cy,sy; +FGLGear::~FGLGear() +{ + delete ForceY_Table; + Debug(1); +} - cp=cos(vGearOrient(ePitch)); - sp=sin(vGearOrient(ePitch)); - cr=cos(vGearOrient(eRoll)); - sr=sin(vGearOrient(eRoll)); - cy=cos(vGearOrient(eYaw)); - sy=sin(vGearOrient(eYaw)); +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - mTGear(1,1) = cp*cy; - mTGear(2,1) = cp*sy; - mTGear(3,1) = -sp; +FGColumnVector3& FGLGear::GetBodyForces(void) +{ + double t = fdmex->GetSimTime(); + dT = fdmex->GetDeltaT()*GroundReactions->GetRate(); - mTGear(1,2) = sr*sp*cy - cr*sy; - mTGear(2,2) = sr*sp*sy + cr*cy; - mTGear(3,2) = sr*cp; + vFn.InitMatrix(); - mTGear(1,3) = cr*sp*cy + sr*sy; - mTGear(2,3) = cr*sp*sy - sr*cy; - mTGear(3,3) = cr*cp; - } - else - { - mTGear(1,1) = 1.; - mTGear(2,2) = 1.; - mTGear(3,3) = 1.; - } + if (isRetractable) ComputeRetractionState(); - if (sBrakeGroup == "LEFT" ) eBrakeGrp = bgLeft; - else if (sBrakeGroup == "RIGHT" ) eBrakeGrp = bgRight; - else if (sBrakeGroup == "CENTER") eBrakeGrp = bgCenter; - else if (sBrakeGroup == "NOSE" ) eBrakeGrp = bgNose; - else if (sBrakeGroup == "TAIL" ) eBrakeGrp = bgTail; - else if (sBrakeGroup == "NONE" ) eBrakeGrp = bgNone; - else if (sBrakeGroup.empty() ) - { - eBrakeGrp = bgNone; - sBrakeGroup = "NONE (defaulted)"; - } - else - { - cerr << "Improper braking group specification in config file: " - << sBrakeGroup << " is undefined." << endl; - } + if (GearDown) { + vWhlBodyVec = MassBalance->StructuralToBody(vXYZn); // Get wheel in body frame + vLocalGear = Propagate->GetTb2l() * vWhlBodyVec; // Get local frame wheel location - if (sSteerType == "STEERABLE") eSteerType = stSteer; - else if (sSteerType == "FIXED" ) eSteerType = stFixed; - else if (sSteerType == "CASTERED" ) - { - eSteerType = stCaster; - Castered = true; - } - else if (sSteerType.empty() ) - { - eSteerType = stFixed; - sSteerType = "FIXED (defaulted)"; - } - else - { - cerr << "Improper steering type specification in config file: " - << sSteerType << " is undefined." << endl; + gearLoc = Propagate->GetLocation().LocalToLocation(vLocalGear); + // Compute the height of the theoretical location of the wheel (if strut is + // not compressed) with respect to the ground level + double height = fdmex->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel); + vGroundNormal = Propagate->GetTec2b() * normal; + + // The height returned above is the AGL and is expressed in the Z direction + // of the ECEF coordinate frame. We now need to transform this height in + // actual compression of the strut (BOGEY) of in the normal direction to the + // ground (STRUCTURE) + double normalZ = (Propagate->GetTec2l()*normal)(eZ); + double LGearProj = -(mTGear.Transposed() * vGroundNormal)(eZ); + + switch (eContactType) { + case ctBOGEY: + compressLength = LGearProj > 0.0 ? height * normalZ / LGearProj : 0.0; + break; + case ctSTRUCTURE: + compressLength = height * normalZ / DotProduct(normal, normal); + break; } - Auxiliary = fdmex->GetAuxiliary(); - Propagate = fdmex->GetPropagate(); - FCS = fdmex->GetFCS(); - MassBalance = fdmex->GetMassBalance(); - GroundReactions = fdmex->GetGroundReactions(); + if (compressLength > 0.00) { - GearUp = false; - GearDown = true; - GearPos = 1.0; - useFCSGearPos = false; - Servicable = true; + WOW = true; -// Add some AI here to determine if gear is located properly according to its -// brake group type ?? + // The following equations use the vector to the tire contact patch + // including the strut compression. + FGColumnVector3 vWhlDisplVec; - WOW = lastWOW = false; - ReportEnable = true; - FirstContact = false; - StartedGroundRun = false; - TakeoffReported = LandingReported = false; - LandingDistanceTraveled = TakeoffDistanceTraveled = TakeoffDistanceTraveled50ft = 0.0; - MaximumStrutForce = MaximumStrutTravel = 0.0; - SinkRate = GroundSpeed = 0.0; + switch(eContactType) { + case ctBOGEY: + vWhlDisplVec = mTGear * FGColumnVector3(0., 0., -compressLength); + break; + case ctSTRUCTURE: + vWhlDisplVec = compressLength * vGroundNormal; + break; + } - vWhlBodyVec = MassBalance->StructuralToBody(vXYZn); - vLocalGear = Propagate->GetTb2l() * vWhlBodyVec; - vWhlVelVec.InitMatrix(); + FGColumnVector3 vWhlContactVec = vWhlBodyVec + vWhlDisplVec; + vActingXYZn = vXYZn + Tb2s * vWhlDisplVec; + FGColumnVector3 vBodyWhlVel = Propagate->GetPQR() * vWhlContactVec; + vBodyWhlVel += Propagate->GetUVW() - Propagate->GetTec2b() * cvel; - compressLength = 0.0; - compressSpeed = 0.0; - brakePct = 0.0; - maxCompLen = 0.0; + vWhlVelVec = mTGear.Transposed() * vBodyWhlVel; - WheelSlip = 0.0; - TirePressureNorm = 1.0; + InitializeReporting(); + ComputeSteeringAngle(); + ComputeGroundCoordSys(); - // Set Pacejka terms + vLocalWhlVel = Transform().Transposed() * vBodyWhlVel; - Stiffness = 0.06; - Shape = 2.8; - Peak = staticFCoeff; - Curvature = 1.03; + compressSpeed = -vLocalWhlVel(eX); + if (eContactType == ctBOGEY) + compressSpeed /= LGearProj; - // Initialize Lagrange multipliers - LMultiplier[ftRoll].value = 0.; - LMultiplier[ftSide].value = 0.; - LMultiplier[ftRoll].value = 0.; + ComputeVerticalStrutForce(); - Debug(0); -} + // Compute the friction coefficients in the wheel ground plane. + if (eContactType == ctBOGEY) { + ComputeSlipAngle(); + ComputeBrakeForceCoefficient(); + ComputeSideForceCoefficient(); + } -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // Prepare the Jacobians and the Lagrange multipliers for later friction + // forces calculations. + ComputeJacobian(vWhlContactVec); -FGLGear::~FGLGear() -{ - delete ForceY_Table; - Debug(1); -} + } else { // Gear is NOT compressed -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + WOW = false; + compressLength = 0.0; + compressSpeed = 0.0; + WheelSlip = 0.0; + StrutForce = 0.0; -FGColumnVector3& FGLGear::GetBodyForces(void) -{ - double t = fdmex->GetSimTime(); - dT = fdmex->GetDeltaT()*GroundReactions->GetRate(); - - vFn.InitMatrix(); - - if (isRetractable) ComputeRetractionState(); - - if (GearDown) - { - vWhlBodyVec = MassBalance->StructuralToBody(vXYZn); // Get wheel in body frame - vLocalGear = Propagate->GetTb2l() * vWhlBodyVec; // Get local frame wheel location - - gearLoc = Propagate->GetLocation().LocalToLocation(vLocalGear); - // Compute the height of the theoretical location of the wheel (if strut is - // not compressed) with respect to the ground level - double height = fdmex->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel); - vGroundNormal = Propagate->GetTec2b() * normal; - - // The height returned above is the AGL and is expressed in the Z direction - // of the ECEF coordinate frame. We now need to transform this height in - // actual compression of the strut (BOGEY) of in the normal direction to the - // ground (STRUCTURE) - double normalZ = (Propagate->GetTec2l()*normal)(eZ); - double LGearProj = -(mTGear.Transposed() * vGroundNormal)(eZ); - - switch (eContactType) - { - case ctBOGEY: - compressLength = LGearProj > 0.0 ? height * normalZ / LGearProj : 0.0; - break; - case ctSTRUCTURE: - compressLength = height * normalZ / DotProduct(normal, normal); - break; - } - - if (compressLength > 0.00) - { - - WOW = true; - - // The following equations use the vector to the tire contact patch - // including the strut compression. - FGColumnVector3 vWhlDisplVec; - - switch (eContactType) - { - case ctBOGEY: - vWhlDisplVec = mTGear * FGColumnVector3(0., 0., -compressLength); - break; - case ctSTRUCTURE: - vWhlDisplVec = compressLength * vGroundNormal; - break; - } - - FGColumnVector3 vWhlContactVec = vWhlBodyVec + vWhlDisplVec; - vActingXYZn = vXYZn + Tb2s * vWhlDisplVec; - FGColumnVector3 vBodyWhlVel = Propagate->GetPQR() * vWhlContactVec; - vBodyWhlVel += Propagate->GetUVW() - Propagate->GetTec2b() * cvel; - - vWhlVelVec = mTGear.Transposed() * vBodyWhlVel; - - InitializeReporting(); - ComputeSteeringAngle(); - ComputeGroundCoordSys(); - - vLocalWhlVel = Transform().Transposed() * vBodyWhlVel; - - compressSpeed = -vLocalWhlVel(eX); - if (eContactType == ctBOGEY) - compressSpeed /= LGearProj; - - ComputeVerticalStrutForce(); - - // Compute the friction coefficients in the wheel ground plane. - if (eContactType == ctBOGEY) - { - ComputeSlipAngle(); - ComputeBrakeForceCoefficient(); - ComputeSideForceCoefficient(); - } - - // Prepare the Jacobians and the Lagrange multipliers for later friction - // forces calculations. - ComputeJacobian(vWhlContactVec); - - } - else // Gear is NOT compressed - { - - WOW = false; - compressLength = 0.0; - compressSpeed = 0.0; - WheelSlip = 0.0; - StrutForce = 0.0; - - // Let wheel spin down slowly - vWhlVelVec(eX) -= 13.0*dT; - if (vWhlVelVec(eX) < 0.0) vWhlVelVec(eX) = 0.0; - - // Return to neutral position between 1.0 and 0.8 gear pos. - SteerAngle *= max(GetGearUnitPos()-0.8, 0.0)/0.2; - - ResetReporting(); - } + // Let wheel spin down slowly + vWhlVelVec(eX) -= 13.0*dT; + if (vWhlVelVec(eX) < 0.0) vWhlVelVec(eX) = 0.0; + + // Return to neutral position between 1.0 and 0.8 gear pos. + SteerAngle *= max(GetGearUnitPos()-0.8, 0.0)/0.2; + + ResetReporting(); } + } - ReportTakeoffOrLanding(); + ReportTakeoffOrLanding(); - // Require both WOW and LastWOW to be true before checking crash conditions - // to allow the WOW flag to be used in terminating a scripted run. - if (WOW && lastWOW) CrashDetect(); + // Require both WOW and LastWOW to be true before checking crash conditions + // to allow the WOW flag to be used in terminating a scripted run. + if (WOW && lastWOW) CrashDetect(); - lastWOW = WOW; + lastWOW = WOW; - return FGForce::GetBodyForces(); + return FGForce::GetBodyForces(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -439,60 +391,54 @@ FGColumnVector3& FGLGear::GetBodyForces(void) void FGLGear::ComputeGroundCoordSys(void) { - // Euler angles are built up to create a local frame to describe the forces - // applied to the gear by the ground. Here pitch, yaw and roll do not have - // any physical meaning. It is just a convenient notation. - // First, "pitch" and "yaw" are determined in order to align eX with the - // ground normal. - if (vGroundNormal(eZ) < -1.0) - vOrient(ePitch) = 0.5*M_PI; - else if (1.0 < vGroundNormal(eZ)) - vOrient(ePitch) = -0.5*M_PI; - else - vOrient(ePitch) = asin(-vGroundNormal(eZ)); - - if (fabs(vOrient(ePitch)) == 0.5*M_PI) - vOrient(eYaw) = 0.; - else - vOrient(eYaw) = atan2(vGroundNormal(eY), vGroundNormal(eX)); - - vOrient(eRoll) = 0.; + // Euler angles are built up to create a local frame to describe the forces + // applied to the gear by the ground. Here pitch, yaw and roll do not have + // any physical meaning. It is just a convenient notation. + // First, "pitch" and "yaw" are determined in order to align eX with the + // ground normal. + if (vGroundNormal(eZ) < -1.0) + vOrient(ePitch) = 0.5*M_PI; + else if (1.0 < vGroundNormal(eZ)) + vOrient(ePitch) = -0.5*M_PI; + else + vOrient(ePitch) = asin(-vGroundNormal(eZ)); + + if (fabs(vOrient(ePitch)) == 0.5*M_PI) + vOrient(eYaw) = 0.; + else + vOrient(eYaw) = atan2(vGroundNormal(eY), vGroundNormal(eX)); + + vOrient(eRoll) = 0.; + UpdateCustomTransformMatrix(); + + if (eContactType == ctBOGEY) { + // In the case of a bogey, the third angle "roll" is used to align the axis eY and eZ + // to the rolling and sliping direction respectively. + FGColumnVector3 updatedRollingAxis = Transform().Transposed() * mTGear + * FGColumnVector3(-sin(SteerAngle), cos(SteerAngle), 0.); + + vOrient(eRoll) = atan2(updatedRollingAxis(eY), -updatedRollingAxis(eZ)); UpdateCustomTransformMatrix(); - - if (eContactType == ctBOGEY) - { - // In the case of a bogey, the third angle "roll" is used to align the axis eY and eZ - // to the rolling and sliping direction respectively. - FGColumnVector3 updatedRollingAxis = Transform().Transposed() * mTGear - * FGColumnVector3(-sin(SteerAngle), cos(SteerAngle), 0.); - - vOrient(eRoll) = atan2(updatedRollingAxis(eY), -updatedRollingAxis(eZ)); - UpdateCustomTransformMatrix(); - } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGLGear::ComputeRetractionState(void) { - double gearPos = GetGearUnitPos(); - if (gearPos < 0.01) - { - GearUp = true; - WOW = false; - GearDown = false; - vWhlVelVec.InitMatrix(); - } - else if (gearPos > 0.99) - { - GearDown = true; - GearUp = false; - } - else - { - GearUp = false; - GearDown = false; - } + double gearPos = GetGearUnitPos(); + if (gearPos < 0.01) { + GearUp = true; + WOW = false; + GearDown = false; + vWhlVelVec.InitMatrix(); + } else if (gearPos > 0.99) { + GearDown = true; + GearUp = false; + } else { + GearUp = false; + GearDown = false; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -501,8 +447,8 @@ void FGLGear::ComputeRetractionState(void) void FGLGear::ComputeSlipAngle(void) { // Check that the speed is non-null otherwise use the current angle - if (vLocalWhlVel.Magnitude(eY,eZ) > 1E-3) - WheelSlip = -atan2(vLocalWhlVel(eZ), fabs(vLocalWhlVel(eY)))*radtodeg; + if (vLocalWhlVel.Magnitude(eY,eZ) > 1E-3) + WheelSlip = -atan2(vLocalWhlVel(eZ), fabs(vLocalWhlVel(eY)))*radtodeg; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -511,28 +457,26 @@ void FGLGear::ComputeSlipAngle(void) void FGLGear::ComputeSteeringAngle(void) { - switch (eSteerType) - { - case stSteer: - SteerAngle = degtorad * FCS->GetSteerPosDeg(GearNumber); - break; - case stFixed: - SteerAngle = 0.0; - break; - case stCaster: - if (!Castered) - SteerAngle = degtorad * FCS->GetSteerPosDeg(GearNumber); - else - { - // Check that the speed is non-null otherwise use the current angle - if (vWhlVelVec.Magnitude(eX,eY) > 0.1) - SteerAngle = atan2(vWhlVelVec(eY), fabs(vWhlVelVec(eX))); - } - break; - default: - cerr << "Improper steering type membership detected for this gear." << endl; - break; - } + switch (eSteerType) { + case stSteer: + SteerAngle = degtorad * FCS->GetSteerPosDeg(GearNumber); + break; + case stFixed: + SteerAngle = 0.0; + break; + case stCaster: + if (!Castered) + SteerAngle = degtorad * FCS->GetSteerPosDeg(GearNumber); + else { + // Check that the speed is non-null otherwise use the current angle + if (vWhlVelVec.Magnitude(eX,eY) > 0.1) + SteerAngle = atan2(vWhlVelVec(eY), fabs(vWhlVelVec(eX))); + } + break; + default: + cerr << "Improper steering type membership detected for this gear." << endl; + break; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -540,43 +484,41 @@ void FGLGear::ComputeSteeringAngle(void) void FGLGear::ResetReporting(void) { - if (Propagate->GetDistanceAGL() > 200.0) - { - FirstContact = false; - StartedGroundRun = false; - LandingReported = false; - TakeoffReported = true; - LandingDistanceTraveled = 0.0; - MaximumStrutForce = MaximumStrutTravel = 0.0; - } + if (Propagate->GetDistanceAGL() > 200.0) { + FirstContact = false; + StartedGroundRun = false; + LandingReported = false; + TakeoffReported = true; + LandingDistanceTraveled = 0.0; + MaximumStrutForce = MaximumStrutTravel = 0.0; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGLGear::InitializeReporting(void) { - // If this is the first time the wheel has made contact, remember some values - // for later printout. - - if (!FirstContact) - { - FirstContact = true; - SinkRate = compressSpeed; - GroundSpeed = Propagate->GetVel().Magnitude(); - TakeoffReported = false; - } - - // If the takeoff run is starting, initialize. - - if ((Propagate->GetVel().Magnitude() > 0.1) && - (FCS->GetBrake(bgLeft) == 0) && - (FCS->GetBrake(bgRight) == 0) && - (FCS->GetThrottlePos(0) > 0.90) && !StartedGroundRun) - { - TakeoffDistanceTraveled = 0; - TakeoffDistanceTraveled50ft = 0; - StartedGroundRun = true; - } + // If this is the first time the wheel has made contact, remember some values + // for later printout. + + if (!FirstContact) { + FirstContact = true; + SinkRate = compressSpeed; + GroundSpeed = Propagate->GetVel().Magnitude(); + TakeoffReported = false; + } + + // If the takeoff run is starting, initialize. + + if ((Propagate->GetVel().Magnitude() > 0.1) && + (FCS->GetBrake(bgLeft) == 0) && + (FCS->GetBrake(bgRight) == 0) && + (FCS->GetThrottlePos(0) > 0.90) && !StartedGroundRun) + { + TakeoffDistanceTraveled = 0; + TakeoffDistanceTraveled50ft = 0; + StartedGroundRun = true; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -584,32 +526,31 @@ void FGLGear::InitializeReporting(void) void FGLGear::ReportTakeoffOrLanding(void) { - if (FirstContact) - LandingDistanceTraveled += Auxiliary->GetVground()*dT; - - if (StartedGroundRun) - { - TakeoffDistanceTraveled50ft += Auxiliary->GetVground()*dT; - if (WOW) TakeoffDistanceTraveled += Auxiliary->GetVground()*dT; - } - - if ( ReportEnable - && Auxiliary->GetVground() <= 0.05 - && !LandingReported - && GroundReactions->GetWOW()) - { - if (debug_lvl > 0) Report(erLand); - } - - if ( ReportEnable - && !TakeoffReported - && (Propagate->GetDistanceAGL() - vLocalGear(eZ)) > 50.0 - && !GroundReactions->GetWOW()) - { - if (debug_lvl > 0) Report(erTakeoff); - } - - if (lastWOW != WOW) PutMessage("GEAR_CONTACT: " + name, WOW); + if (FirstContact) + LandingDistanceTraveled += Auxiliary->GetVground()*dT; + + if (StartedGroundRun) { + TakeoffDistanceTraveled50ft += Auxiliary->GetVground()*dT; + if (WOW) TakeoffDistanceTraveled += Auxiliary->GetVground()*dT; + } + + if ( ReportEnable + && Auxiliary->GetVground() <= 0.05 + && !LandingReported + && GroundReactions->GetWOW()) + { + if (debug_lvl > 0) Report(erLand); + } + + if ( ReportEnable + && !TakeoffReported + && (Propagate->GetDistanceAGL() - vLocalGear(eZ)) > 50.0 + && !GroundReactions->GetWOW()) + { + if (debug_lvl > 0) Report(erTakeoff); + } + + if (lastWOW != WOW) PutMessage("GEAR_CONTACT: " + name, WOW); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -617,14 +558,14 @@ void FGLGear::ReportTakeoffOrLanding(void) void FGLGear::CrashDetect(void) { - if ( (compressLength > 500.0 || - vFn.Magnitude() > 100000000.0 || - GetMoments().Magnitude() > 5000000000.0 || - SinkRate > 1.4666*30 ) && !fdmex->IntegrationSuspended()) - { - PutMessage("Crash Detected: Simulation FREEZE."); - fdmex->SuspendIntegration(); - } + if ( (compressLength > 500.0 || + vFn.Magnitude() > 100000000.0 || + GetMoments().Magnitude() > 5000000000.0 || + SinkRate > 1.4666*30 ) && !fdmex->IntegrationSuspended()) + { + PutMessage("Crash Detected: Simulation FREEZE."); + fdmex->SuspendIntegration(); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -637,35 +578,34 @@ void FGLGear::CrashDetect(void) void FGLGear::ComputeBrakeForceCoefficient(void) { - switch (eBrakeGrp) - { - case bgLeft: - BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) + - staticFCoeff*FCS->GetBrake(bgLeft) ); - break; - case bgRight: - BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) + - staticFCoeff*FCS->GetBrake(bgRight) ); - break; - case bgCenter: - BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + - staticFCoeff*FCS->GetBrake(bgCenter) ); - break; - case bgNose: - BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + - staticFCoeff*FCS->GetBrake(bgCenter) ); - break; - case bgTail: - BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + - staticFCoeff*FCS->GetBrake(bgCenter) ); - break; - case bgNone: - BrakeFCoeff = rollingFCoeff; - break; - default: - cerr << "Improper brake group membership detected for this gear." << endl; - break; - } + switch (eBrakeGrp) { + case bgLeft: + BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) + + staticFCoeff*FCS->GetBrake(bgLeft) ); + break; + case bgRight: + BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) + + staticFCoeff*FCS->GetBrake(bgRight) ); + break; + case bgCenter: + BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + + staticFCoeff*FCS->GetBrake(bgCenter) ); + break; + case bgNose: + BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + + staticFCoeff*FCS->GetBrake(bgCenter) ); + break; + case bgTail: + BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + + staticFCoeff*FCS->GetBrake(bgCenter) ); + break; + case bgNone: + BrakeFCoeff = rollingFCoeff; + break; + default: + cerr << "Improper brake group membership detected for this gear." << endl; + break; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -680,15 +620,12 @@ void FGLGear::ComputeBrakeForceCoefficient(void) void FGLGear::ComputeSideForceCoefficient(void) { - if (ForceY_Table) - { - FCoeff = ForceY_Table->GetValue(WheelSlip); - } - else - { - double StiffSlip = Stiffness*WheelSlip; - FCoeff = Peak * sin(Shape*atan(StiffSlip - Curvature*(StiffSlip - atan(StiffSlip)))); - } + if (ForceY_Table) { + FCoeff = ForceY_Table->GetValue(WheelSlip); + } else { + double StiffSlip = Stiffness*WheelSlip; + FCoeff = Peak * sin(Shape*atan(StiffSlip - Curvature*(StiffSlip - atan(StiffSlip)))); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -700,58 +637,53 @@ void FGLGear::ComputeSideForceCoefficient(void) void FGLGear::ComputeVerticalStrutForce(void) { - double springForce = 0; - double dampForce = 0; + double springForce = 0; + double dampForce = 0; - springForce = -compressLength * kSpring; + springForce = -compressLength * kSpring; - if (compressSpeed >= 0.0) - { + if (compressSpeed >= 0.0) { - if (eDampType == dtLinear) dampForce = -compressSpeed * bDamp; - else dampForce = -compressSpeed * compressSpeed * bDamp; + if (eDampType == dtLinear) dampForce = -compressSpeed * bDamp; + else dampForce = -compressSpeed * compressSpeed * bDamp; - } - else - { - - if (eDampTypeRebound == dtLinear) - dampForce = -compressSpeed * bDampRebound; - else - dampForce = compressSpeed * compressSpeed * bDampRebound; - - } + } else { - StrutForce = min(springForce + dampForce, (double)0.0); - - // The reaction force of the wheel is always normal to the ground - switch (eContactType) - { - case ctBOGEY: - // Project back the strut force in the local coordinate frame of the ground - vFn(eX) = StrutForce / (mTGear.Transposed()*vGroundNormal)(eZ); - break; - case ctSTRUCTURE: - vFn(eX) = -StrutForce; - break; - } - - // Remember these values for reporting - MaximumStrutForce = max(MaximumStrutForce, fabs(StrutForce)); - MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength)); + if (eDampTypeRebound == dtLinear) + dampForce = -compressSpeed * bDampRebound; + else + dampForce = compressSpeed * compressSpeed * bDampRebound; + + } + + StrutForce = min(springForce + dampForce, (double)0.0); + + // The reaction force of the wheel is always normal to the ground + switch (eContactType) { + case ctBOGEY: + // Project back the strut force in the local coordinate frame of the ground + vFn(eX) = StrutForce / (mTGear.Transposed()*vGroundNormal)(eZ); + break; + case ctSTRUCTURE: + vFn(eX) = -StrutForce; + break; + } + + // Remember these values for reporting + MaximumStrutForce = max(MaximumStrutForce, fabs(StrutForce)); + MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength)); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGLGear::GetGearUnitPos(void) { - // hack to provide backward compatibility to gear/gear-pos-norm property - if ( useFCSGearPos || FCS->GetGearPos() != 1.0 ) - { - useFCSGearPos = true; - return FCS->GetGearPos(); - } - return GearPos; + // hack to provide backward compatibility to gear/gear-pos-norm property + if( useFCSGearPos || FCS->GetGearPos() != 1.0 ) { + useFCSGearPos = true; + return FCS->GetGearPos(); + } + return GearPos; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -760,54 +692,51 @@ double FGLGear::GetGearUnitPos(void) void FGLGear::ComputeJacobian(const FGColumnVector3& vWhlContactVec) { - // When the point of contact is moving, dynamic friction is used - // This type of friction is limited to ctSTRUCTURE elements because their - // friction coefficient is the same in every directions - if ((eContactType == ctSTRUCTURE) && (vLocalWhlVel.Magnitude(eY,eZ) > 1E-3)) - { - FGColumnVector3 velocityDirection = vLocalWhlVel; - - StaticFriction = false; - - velocityDirection(eX) = 0.; - velocityDirection.Normalize(); - - LMultiplier[ftDynamic].ForceJacobian = Transform()*velocityDirection; - LMultiplier[ftDynamic].MomentJacobian = vWhlContactVec * LMultiplier[ftDynamic].ForceJacobian; - LMultiplier[ftDynamic].Max = 0.; - LMultiplier[ftDynamic].Min = -fabs(dynamicFCoeff * vFn(eX)); - LMultiplier[ftDynamic].value = Constrain(LMultiplier[ftDynamic].Min, LMultiplier[ftDynamic].value, LMultiplier[ftDynamic].Max); - } - else - { - // Static friction is used for ctSTRUCTURE when the contact point is not moving. - // It is always used for ctBOGEY elements because the friction coefficients - // of a tyre depend on the direction of the movement (roll & side directions). - // This cannot be handled properly by the so-called "dynamic friction". - StaticFriction = true; - - LMultiplier[ftRoll].ForceJacobian = Transform()*FGColumnVector3(0.,1.,0.); - LMultiplier[ftSide].ForceJacobian = Transform()*FGColumnVector3(0.,0.,1.); - LMultiplier[ftRoll].MomentJacobian = vWhlContactVec * LMultiplier[ftRoll].ForceJacobian; - LMultiplier[ftSide].MomentJacobian = vWhlContactVec * LMultiplier[ftSide].ForceJacobian; - - switch (eContactType) - { - case ctBOGEY: - LMultiplier[ftRoll].Max = fabs(BrakeFCoeff * vFn(eX)); - LMultiplier[ftSide].Max = fabs(FCoeff * vFn(eX)); - break; - case ctSTRUCTURE: - LMultiplier[ftRoll].Max = fabs(staticFCoeff * vFn(eX)); - LMultiplier[ftSide].Max = fabs(staticFCoeff * vFn(eX)); - break; - } - - LMultiplier[ftRoll].Min = -LMultiplier[ftRoll].Max; - LMultiplier[ftSide].Min = -LMultiplier[ftSide].Max; - LMultiplier[ftRoll].value = Constrain(LMultiplier[ftRoll].Min, LMultiplier[ftRoll].value, LMultiplier[ftRoll].Max); - LMultiplier[ftSide].value = Constrain(LMultiplier[ftSide].Min, LMultiplier[ftSide].value, LMultiplier[ftSide].Max); + // When the point of contact is moving, dynamic friction is used + // This type of friction is limited to ctSTRUCTURE elements because their + // friction coefficient is the same in every directions + if ((eContactType == ctSTRUCTURE) && (vLocalWhlVel.Magnitude(eY,eZ) > 1E-3)) { + FGColumnVector3 velocityDirection = vLocalWhlVel; + + StaticFriction = false; + + velocityDirection(eX) = 0.; + velocityDirection.Normalize(); + + LMultiplier[ftDynamic].ForceJacobian = Transform()*velocityDirection; + LMultiplier[ftDynamic].MomentJacobian = vWhlContactVec * LMultiplier[ftDynamic].ForceJacobian; + LMultiplier[ftDynamic].Max = 0.; + LMultiplier[ftDynamic].Min = -fabs(dynamicFCoeff * vFn(eX)); + LMultiplier[ftDynamic].value = Constrain(LMultiplier[ftDynamic].Min, LMultiplier[ftDynamic].value, LMultiplier[ftDynamic].Max); + } + else { + // Static friction is used for ctSTRUCTURE when the contact point is not moving. + // It is always used for ctBOGEY elements because the friction coefficients + // of a tyre depend on the direction of the movement (roll & side directions). + // This cannot be handled properly by the so-called "dynamic friction". + StaticFriction = true; + + LMultiplier[ftRoll].ForceJacobian = Transform()*FGColumnVector3(0.,1.,0.); + LMultiplier[ftSide].ForceJacobian = Transform()*FGColumnVector3(0.,0.,1.); + LMultiplier[ftRoll].MomentJacobian = vWhlContactVec * LMultiplier[ftRoll].ForceJacobian; + LMultiplier[ftSide].MomentJacobian = vWhlContactVec * LMultiplier[ftSide].ForceJacobian; + + switch(eContactType) { + case ctBOGEY: + LMultiplier[ftRoll].Max = fabs(BrakeFCoeff * vFn(eX)); + LMultiplier[ftSide].Max = fabs(FCoeff * vFn(eX)); + break; + case ctSTRUCTURE: + LMultiplier[ftRoll].Max = fabs(staticFCoeff * vFn(eX)); + LMultiplier[ftSide].Max = fabs(staticFCoeff * vFn(eX)); + break; } + + LMultiplier[ftRoll].Min = -LMultiplier[ftRoll].Max; + LMultiplier[ftSide].Min = -LMultiplier[ftSide].Max; + LMultiplier[ftRoll].value = Constrain(LMultiplier[ftRoll].Min, LMultiplier[ftRoll].value, LMultiplier[ftRoll].Max); + LMultiplier[ftSide].value = Constrain(LMultiplier[ftSide].Min, LMultiplier[ftSide].value, LMultiplier[ftSide].Max); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -820,19 +749,18 @@ void FGLGear::ComputeJacobian(const FGColumnVector3& vWhlContactVec) FGPropagate::LagrangeMultiplier* FGLGear::GetMultiplierEntry(int entry) { - switch (entry) - { - case 0: - if (StaticFriction) - return &LMultiplier[ftRoll]; - else - return &LMultiplier[ftDynamic]; - case 1: - if (StaticFriction) - return &LMultiplier[ftSide]; - default: - return NULL; - } + switch(entry) { + case 0: + if (StaticFriction) + return &LMultiplier[ftRoll]; + else + return &LMultiplier[ftDynamic]; + case 1: + if (StaticFriction) + return &LMultiplier[ftSide]; + default: + return NULL; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -840,101 +768,96 @@ FGPropagate::LagrangeMultiplier* FGLGear::GetMultiplierEntry(int entry) // friction forces of the landing gear are then updated accordingly. FGColumnVector3& FGLGear::UpdateForces(void) { - if (StaticFriction) - { - vFn(eY) = LMultiplier[ftRoll].value; - vFn(eZ) = LMultiplier[ftSide].value; - } - else - vFn += LMultiplier[ftDynamic].value * (Transform ().Transposed() * LMultiplier[ftDynamic].ForceJacobian); - - // Return the updated force in the body frame - return FGForce::GetBodyForces(); + if (StaticFriction) { + vFn(eY) = LMultiplier[ftRoll].value; + vFn(eZ) = LMultiplier[ftSide].value; + } + else + vFn += LMultiplier[ftDynamic].value * (Transform ().Transposed() * LMultiplier[ftDynamic].ForceJacobian); + + // Return the updated force in the body frame + return FGForce::GetBodyForces(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGLGear::bind(void) { - string property_name; - string base_property_name; - base_property_name = CreateIndexedPropertyName("gear/unit", GearNumber); - if (eContactType == ctBOGEY) - { - property_name = base_property_name + "/slip-angle-deg"; - fdmex->GetPropertyManager()->Tie( property_name.c_str(), &WheelSlip ); - property_name = base_property_name + "/WOW"; - fdmex->GetPropertyManager()->Tie( property_name.c_str(), &WOW ); - property_name = base_property_name + "/wheel-speed-fps"; - fdmex->GetPropertyManager()->Tie( property_name.c_str(), (FGLGear*)this, - &FGLGear::GetWheelRollVel); - property_name = base_property_name + "/z-position"; - fdmex->GetPropertyManager()->Tie( property_name.c_str(), (FGForce*)this, - &FGForce::GetLocationZ, &FGForce::SetLocationZ); - property_name = base_property_name + "/compression-ft"; - fdmex->GetPropertyManager()->Tie( property_name.c_str(), &compressLength ); - property_name = base_property_name + "/side_friction_coeff"; - fdmex->GetPropertyManager()->Tie( property_name.c_str(), &FCoeff ); - - property_name = base_property_name + "/static_friction_coeff"; - fdmex->GetPropertyManager()->Tie( property_name.c_str(), &staticFCoeff ); - - if (eSteerType == stCaster) - { - property_name = base_property_name + "/steering-angle-deg"; - fdmex->GetPropertyManager()->Tie( property_name.c_str(), this, &FGLGear::GetSteerAngleDeg ); - property_name = base_property_name + "/castered"; - fdmex->GetPropertyManager()->Tie( property_name.c_str(), &Castered); - } - } - - if ( isRetractable ) - { - property_name = base_property_name + "/pos-norm"; - fdmex->GetPropertyManager()->Tie( property_name.c_str(), &GearPos ); - } + string property_name; + string base_property_name; + base_property_name = CreateIndexedPropertyName("gear/unit", GearNumber); + if (eContactType == ctBOGEY) { + property_name = base_property_name + "/slip-angle-deg"; + fdmex->GetPropertyManager()->Tie( property_name.c_str(), &WheelSlip ); + property_name = base_property_name + "/WOW"; + fdmex->GetPropertyManager()->Tie( property_name.c_str(), &WOW ); + property_name = base_property_name + "/wheel-speed-fps"; + fdmex->GetPropertyManager()->Tie( property_name.c_str(), (FGLGear*)this, + &FGLGear::GetWheelRollVel); + property_name = base_property_name + "/z-position"; + fdmex->GetPropertyManager()->Tie( property_name.c_str(), (FGForce*)this, + &FGForce::GetLocationZ, &FGForce::SetLocationZ); + property_name = base_property_name + "/compression-ft"; + fdmex->GetPropertyManager()->Tie( property_name.c_str(), &compressLength ); + property_name = base_property_name + "/side_friction_coeff"; + fdmex->GetPropertyManager()->Tie( property_name.c_str(), &FCoeff ); + + property_name = base_property_name + "/static_friction_coeff"; + fdmex->GetPropertyManager()->Tie( property_name.c_str(), &staticFCoeff ); + + if (eSteerType == stCaster) { + property_name = base_property_name + "/steering-angle-deg"; + fdmex->GetPropertyManager()->Tie( property_name.c_str(), this, &FGLGear::GetSteerAngleDeg ); + property_name = base_property_name + "/castered"; + fdmex->GetPropertyManager()->Tie( property_name.c_str(), &Castered); + } + } + + if( isRetractable ) { + property_name = base_property_name + "/pos-norm"; + fdmex->GetPropertyManager()->Tie( property_name.c_str(), &GearPos ); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGLGear::Report(ReportType repType) { - if (fabs(TakeoffDistanceTraveled) < 0.001) return; // Don't print superfluous reports - - switch (repType) - { - case erLand: - cout << endl << "Touchdown report for " << name << " (WOW at time: " - << fdmex->GetSimTime() << " seconds)" << endl; - cout << " Sink rate at contact: " << SinkRate << " fps, " - << SinkRate*0.3048 << " mps" << endl; - cout << " Contact ground speed: " << GroundSpeed*.5925 << " knots, " - << GroundSpeed*0.3048 << " mps" << endl; - cout << " Maximum contact force: " << MaximumStrutForce << " lbs, " - << MaximumStrutForce*4.448 << " Newtons" << endl; - cout << " Maximum strut travel: " << MaximumStrutTravel*12.0 << " inches, " - << MaximumStrutTravel*30.48 << " cm" << endl; - cout << " Distance traveled: " << LandingDistanceTraveled << " ft, " - << LandingDistanceTraveled*0.3048 << " meters" << endl; - LandingReported = true; - break; - case erTakeoff: - cout << endl << "Takeoff report for " << name << " (Liftoff at time: " - << fdmex->GetSimTime() << " seconds)" << endl; - cout << " Distance traveled: " << TakeoffDistanceTraveled - << " ft, " << TakeoffDistanceTraveled*0.3048 << " meters" << endl; - cout << " Distance traveled (over 50'): " << TakeoffDistanceTraveled50ft - << " ft, " << TakeoffDistanceTraveled50ft*0.3048 << " meters" << endl; - cout << " [Altitude (ASL): " << Propagate->GetAltitudeASL() << " ft. / " - << Propagate->GetAltitudeASLmeters() << " m | Temperature: " - << fdmex->GetAtmosphere()->GetTemperature() - 459.67 << " F / " - << RankineToCelsius(fdmex->GetAtmosphere()->GetTemperature()) << " C]" << endl; - cout << " [Velocity (KCAS): " << Auxiliary->GetVcalibratedKTS() << "]" << endl; - TakeoffReported = true; - break; - case erNone: - break; - } + if (fabs(TakeoffDistanceTraveled) < 0.001) return; // Don't print superfluous reports + + switch(repType) { + case erLand: + cout << endl << "Touchdown report for " << name << " (WOW at time: " + << fdmex->GetSimTime() << " seconds)" << endl; + cout << " Sink rate at contact: " << SinkRate << " fps, " + << SinkRate*0.3048 << " mps" << endl; + cout << " Contact ground speed: " << GroundSpeed*.5925 << " knots, " + << GroundSpeed*0.3048 << " mps" << endl; + cout << " Maximum contact force: " << MaximumStrutForce << " lbs, " + << MaximumStrutForce*4.448 << " Newtons" << endl; + cout << " Maximum strut travel: " << MaximumStrutTravel*12.0 << " inches, " + << MaximumStrutTravel*30.48 << " cm" << endl; + cout << " Distance traveled: " << LandingDistanceTraveled << " ft, " + << LandingDistanceTraveled*0.3048 << " meters" << endl; + LandingReported = true; + break; + case erTakeoff: + cout << endl << "Takeoff report for " << name << " (Liftoff at time: " + << fdmex->GetSimTime() << " seconds)" << endl; + cout << " Distance traveled: " << TakeoffDistanceTraveled + << " ft, " << TakeoffDistanceTraveled*0.3048 << " meters" << endl; + cout << " Distance traveled (over 50'): " << TakeoffDistanceTraveled50ft + << " ft, " << TakeoffDistanceTraveled50ft*0.3048 << " meters" << endl; + cout << " [Altitude (ASL): " << Propagate->GetAltitudeASL() << " ft. / " + << Propagate->GetAltitudeASLmeters() << " m | Temperature: " + << fdmex->GetAtmosphere()->GetTemperature() - 459.67 << " F / " + << RankineToCelsius(fdmex->GetAtmosphere()->GetTemperature()) << " C]" << endl; + cout << " [Velocity (KCAS): " << Auxiliary->GetVcalibratedKTS() << "]" << endl; + TakeoffReported = true; + break; + case erNone: + break; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -958,60 +881,51 @@ void FGLGear::Report(ReportType repType) void FGLGear::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - loading and initialization - { - cout << " " << sContactType << " " << name << endl; - cout << " Location: " << vXYZn << endl; - cout << " Spring Constant: " << kSpring << endl; - - if (eDampType == dtLinear) - cout << " Damping Constant: " << bDamp << " (linear)" << endl; - else - cout << " Damping Constant: " << bDamp << " (square law)" << endl; - - if (eDampTypeRebound == dtLinear) - cout << " Rebound Damping Constant: " << bDampRebound << " (linear)" << endl; - else - cout << " Rebound Damping Constant: " << bDampRebound << " (square law)" << endl; - - cout << " Dynamic Friction: " << dynamicFCoeff << endl; - cout << " Static Friction: " << staticFCoeff << endl; - if (eContactType == ctBOGEY) - { - cout << " Rolling Friction: " << rollingFCoeff << endl; - cout << " Steering Type: " << sSteerType << endl; - cout << " Grouping: " << sBrakeGroup << endl; - cout << " Max Steer Angle: " << maxSteerAngle << endl; - cout << " Retractable: " << isRetractable << endl; - } - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGLGear" << endl; - if (from == 1) cout << "Destroyed: FGLGear" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - loading and initialization + cout << " " << sContactType << " " << name << endl; + cout << " Location: " << vXYZn << endl; + cout << " Spring Constant: " << kSpring << endl; + + if (eDampType == dtLinear) + cout << " Damping Constant: " << bDamp << " (linear)" << endl; + else + cout << " Damping Constant: " << bDamp << " (square law)" << endl; + + if (eDampTypeRebound == dtLinear) + cout << " Rebound Damping Constant: " << bDampRebound << " (linear)" << endl; + else + cout << " Rebound Damping Constant: " << bDampRebound << " (square law)" << endl; + + cout << " Dynamic Friction: " << dynamicFCoeff << endl; + cout << " Static Friction: " << staticFCoeff << endl; + if (eContactType == ctBOGEY) { + cout << " Rolling Friction: " << rollingFCoeff << endl; + cout << " Steering Type: " << sSteerType << endl; + cout << " Grouping: " << sBrakeGroup << endl; + cout << " Max Steer Angle: " << maxSteerAngle << endl; + cout << " Retractable: " << isRetractable << endl; + } + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGLGear" << endl; + if (from == 1) cout << "Destroyed: FGLGear" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; + } + } } } // namespace JSBSim diff --git a/src/models/FGLGear.h b/src/models/FGLGear.h index f55973e5973ef450a054b56aabd168fb268cb06f..f1828f8cf840b17c4c7ffebc6ea90ac5022d8fec 100644 --- a/src/models/FGLGear.h +++ b/src/models/FGLGear.h @@ -47,19 +47,17 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_LGEAR "$Id: FGLGear.h,v 1.40 2010/07/30 11:50:01 jberndt Exp $" +#define ID_LGEAR "$Id: FGLGear.h,v 1.41 2010/09/22 11:33:40 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGAircraft; class FGPropagate; class FGFCS; -class FGState; class FGMassBalance; class FGAuxiliary; class FGTable; @@ -182,7 +180,7 @@ CLASS DOCUMENTATION </contact> @endcode @author Jon S. Berndt - @version $Id: FGLGear.h,v 1.40 2010/07/30 11:50:01 jberndt Exp $ + @version $Id: FGLGear.h,v 1.41 2010/09/22 11:33:40 jberndt Exp $ @see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at NASA-Ames", NASA CR-2497, January 1975 @see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics", @@ -198,277 +196,180 @@ CLASS DECLARATION class FGLGear : public FGForce { public: - /// Brake grouping enumerators - enum BrakeGroup {bgNone=0, bgLeft, bgRight, bgCenter, bgNose, bgTail }; - /// Steering group membership enumerators - enum SteerType {stSteer, stFixed, stCaster}; - /// Contact point type - enum ContactType {ctBOGEY, ctSTRUCTURE}; - /// Report type enumerators - enum ReportType {erNone=0, erTakeoff, erLand}; - /// Damping types - enum DampType {dtLinear=0, dtSquare}; - /// Friction types - enum FrictionType {ftRoll=0, ftSide, ftDynamic}; - /** Constructor - @param el a pointer to the XML element that contains the CONTACT info. - @param Executive a pointer to the parent executive object - @param number integer identifier for this instance of FGLGear - */ - FGLGear(Element* el, FGFDMExec* Executive, int number); - /// Destructor - ~FGLGear(); - - /// The Force vector for this gear - FGColumnVector3& GetBodyForces(void); - - /// Gets the location of the gear in Body axes - FGColumnVector3& GetBodyLocation(void) - { - return vWhlBodyVec; - } - double GetBodyLocation(int idx) const - { - return vWhlBodyVec(idx); - } - - FGColumnVector3& GetLocalGear(void) - { - return vLocalGear; - } - double GetLocalGear(int idx) const - { - return vLocalGear(idx); - } - - /// Gets the name of the gear - string GetName(void) const - { - return name; - } - /// Gets the Weight On Wheels flag value - bool GetWOW(void) const - { - return WOW; - } - /// Gets the current compressed length of the gear in feet - double GetCompLen(void) const - { - return compressLength; - } - /// Gets the current gear compression velocity in ft/sec - double GetCompVel(void) const - { - return compressSpeed; - } - /// Gets the gear compression force in pounds - double GetCompForce(void) const - { - return StrutForce; - } - double GetBrakeFCoeff(void) const - { - return BrakeFCoeff; - } - - /// Gets the current normalized tire pressure - double GetTirePressure(void) const - { - return TirePressureNorm; - } - /// Sets the new normalized tire pressure - void SetTirePressure(double p) - { - TirePressureNorm = p; - } - - /// Sets the brake value in percent (0 - 100) - void SetBrake(double bp) - { - brakePct = bp; - } - - /// Sets the weight-on-wheels flag. - void SetWOW(bool wow) - { - WOW = wow; - } - - /** Set the console touchdown reporting feature - @param flag true turns on touchdown reporting, false turns it off */ - void SetReport(bool flag) - { - ReportEnable = flag; - } - /** Get the console touchdown reporting feature - @return true if reporting is turned on */ - bool GetReport(void) const - { - return ReportEnable; - } - double GetSteerNorm(void) const - { - return radtodeg/maxSteerAngle*SteerAngle; - } - double GetDefaultSteerAngle(double cmd) const - { - return cmd*maxSteerAngle; - } - double GetstaticFCoeff(void) const - { - return staticFCoeff; - } - - int GetBrakeGroup(void) const - { - return (int)eBrakeGrp; - } - int GetSteerType(void) const - { - return (int)eSteerType; - } - - bool GetSteerable(void) const - { - return eSteerType != stFixed; - } - bool GetRetractable(void) const - { - return isRetractable; - } - bool GetGearUnitUp(void) const - { - return GearUp; - } - bool GetGearUnitDown(void) const - { - return GearDown; - } - double GetWheelRollForce(void) - { - FGColumnVector3 vForce = mTGear.Transposed() * FGForce::GetBodyForces(); - return vForce(eX)*cos(SteerAngle) + vForce(eY)*sin(SteerAngle); - } - double GetWheelSideForce(void) - { - FGColumnVector3 vForce = mTGear.Transposed() * FGForce::GetBodyForces(); - return vForce(eY)*cos(SteerAngle) - vForce(eX)*sin(SteerAngle); - } - double GetWheelRollVel(void) const - { - return vWhlVelVec(eX)*cos(SteerAngle) - + vWhlVelVec(eY)*sin(SteerAngle); - } - double GetWheelSideVel(void) const - { - return vWhlVelVec(eY)*cos(SteerAngle) - - vWhlVelVec(eX)*sin(SteerAngle); - } - double GetWheelSlipAngle(void) const - { - return WheelSlip; - } - double GetWheelVel(int axis) const - { - return vWhlVelVec(axis); - } - bool IsBogey(void) const - { - return (eContactType == ctBOGEY); - } - double GetGearUnitPos(void); - double GetSteerAngleDeg(void) const - { - return radtodeg*SteerAngle; - } - FGPropagate::LagrangeMultiplier* GetMultiplierEntry(int entry); - void SetLagrangeMultiplier(double lambda, int entry); - FGColumnVector3& UpdateForces(void); - - void bind(void); + /// Brake grouping enumerators + enum BrakeGroup {bgNone=0, bgLeft, bgRight, bgCenter, bgNose, bgTail }; + /// Steering group membership enumerators + enum SteerType {stSteer, stFixed, stCaster}; + /// Contact point type + enum ContactType {ctBOGEY, ctSTRUCTURE}; + /// Report type enumerators + enum ReportType {erNone=0, erTakeoff, erLand}; + /// Damping types + enum DampType {dtLinear=0, dtSquare}; + /// Friction types + enum FrictionType {ftRoll=0, ftSide, ftDynamic}; + /** Constructor + @param el a pointer to the XML element that contains the CONTACT info. + @param Executive a pointer to the parent executive object + @param number integer identifier for this instance of FGLGear + */ + FGLGear(Element* el, FGFDMExec* Executive, int number); + /// Destructor + ~FGLGear(); + + /// The Force vector for this gear + FGColumnVector3& GetBodyForces(void); + + /// Gets the location of the gear in Body axes + FGColumnVector3& GetBodyLocation(void) { return vWhlBodyVec; } + double GetBodyLocation(int idx) const { return vWhlBodyVec(idx); } + + FGColumnVector3& GetLocalGear(void) { return vLocalGear; } + double GetLocalGear(int idx) const { return vLocalGear(idx); } + + /// Gets the name of the gear + string GetName(void) const {return name; } + /// Gets the Weight On Wheels flag value + bool GetWOW(void) const {return WOW; } + /// Gets the current compressed length of the gear in feet + double GetCompLen(void) const {return compressLength;} + /// Gets the current gear compression velocity in ft/sec + double GetCompVel(void) const {return compressSpeed; } + /// Gets the gear compression force in pounds + double GetCompForce(void) const {return StrutForce; } + double GetBrakeFCoeff(void) const {return BrakeFCoeff;} + + /// Gets the current normalized tire pressure + double GetTirePressure(void) const { return TirePressureNorm; } + /// Sets the new normalized tire pressure + void SetTirePressure(double p) { TirePressureNorm = p; } + + /// Sets the brake value in percent (0 - 100) + void SetBrake(double bp) {brakePct = bp;} + + /// Sets the weight-on-wheels flag. + void SetWOW(bool wow) {WOW = wow;} + + /** Set the console touchdown reporting feature + @param flag true turns on touchdown reporting, false turns it off */ + void SetReport(bool flag) { ReportEnable = flag; } + /** Get the console touchdown reporting feature + @return true if reporting is turned on */ + bool GetReport(void) const { return ReportEnable; } + double GetSteerNorm(void) const { return radtodeg/maxSteerAngle*SteerAngle; } + double GetDefaultSteerAngle(double cmd) const { return cmd*maxSteerAngle; } + double GetstaticFCoeff(void) const { return staticFCoeff; } + + int GetBrakeGroup(void) const { return (int)eBrakeGrp; } + int GetSteerType(void) const { return (int)eSteerType; } + + bool GetSteerable(void) const { return eSteerType != stFixed; } + bool GetRetractable(void) const { return isRetractable; } + bool GetGearUnitUp(void) const { return GearUp; } + bool GetGearUnitDown(void) const { return GearDown; } + double GetWheelRollForce(void) { + FGColumnVector3 vForce = mTGear.Transposed() * FGForce::GetBodyForces(); + return vForce(eX)*cos(SteerAngle) + vForce(eY)*sin(SteerAngle); } + double GetWheelSideForce(void) { + FGColumnVector3 vForce = mTGear.Transposed() * FGForce::GetBodyForces(); + return vForce(eY)*cos(SteerAngle) - vForce(eX)*sin(SteerAngle); } + double GetWheelRollVel(void) const { return vWhlVelVec(eX)*cos(SteerAngle) + + vWhlVelVec(eY)*sin(SteerAngle); } + double GetWheelSideVel(void) const { return vWhlVelVec(eY)*cos(SteerAngle) + - vWhlVelVec(eX)*sin(SteerAngle); } + double GetWheelSlipAngle(void) const { return WheelSlip; } + double GetWheelVel(int axis) const { return vWhlVelVec(axis);} + bool IsBogey(void) const { return (eContactType == ctBOGEY);} + double GetGearUnitPos(void); + double GetSteerAngleDeg(void) const { return radtodeg*SteerAngle; } + FGPropagate::LagrangeMultiplier* GetMultiplierEntry(int entry); + void SetLagrangeMultiplier(double lambda, int entry); + FGColumnVector3& UpdateForces(void); + + void bind(void); private: - int GearNumber; - static const FGMatrix33 Tb2s; - FGMatrix33 mTGear; - FGColumnVector3 vGearOrient; - FGColumnVector3 vWhlBodyVec; - FGColumnVector3 vLocalGear; - FGColumnVector3 vWhlVelVec, vLocalWhlVel; // Velocity of this wheel - FGColumnVector3 normal, cvel, vGroundNormal; - FGLocation contact, gearLoc; - FGTable *ForceY_Table; - double dT; - double SteerAngle; - double kSpring; - double bDamp; - double bDampRebound; - double compressLength; - double compressSpeed; - double staticFCoeff, dynamicFCoeff, rollingFCoeff; - double Stiffness, Shape, Peak, Curvature; // Pacejka factors - double brakePct; - double BrakeFCoeff; - double maxCompLen; - double SinkRate; - double GroundSpeed; - double TakeoffDistanceTraveled; - double TakeoffDistanceTraveled50ft; - double LandingDistanceTraveled; - double MaximumStrutForce, StrutForce; - double MaximumStrutTravel; - double FCoeff; - double WheelSlip; - double TirePressureNorm; - double GearPos; - bool useFCSGearPos; - bool WOW; - bool lastWOW; - bool FirstContact; - bool StartedGroundRun; - bool LandingReported; - bool TakeoffReported; - bool ReportEnable; - bool isRetractable; - bool GearUp, GearDown; - bool Servicable; - bool Castered; - bool StaticFriction; - std::string name; - std::string sSteerType; - std::string sBrakeGroup; - std::string sRetractable; - std::string sContactType; - - BrakeGroup eBrakeGrp; - ContactType eContactType; - SteerType eSteerType; - DampType eDampType; - DampType eDampTypeRebound; - double maxSteerAngle; - - FGPropagate::LagrangeMultiplier LMultiplier[3]; - - FGAuxiliary* Auxiliary; - FGPropagate* Propagate; - FGFCS* FCS; - FGMassBalance* MassBalance; - FGGroundReactions* GroundReactions; - - void ComputeRetractionState(void); - void ComputeBrakeForceCoefficient(void); - void ComputeSteeringAngle(void); - void ComputeSlipAngle(void); - void ComputeSideForceCoefficient(void); - void ComputeVerticalStrutForce(void); - void ComputeGroundCoordSys(void); - void ComputeJacobian(const FGColumnVector3& vWhlContactVec); - void CrashDetect(void); - void InitializeReporting(void); - void ResetReporting(void); - void ReportTakeoffOrLanding(void); - void Report(ReportType rt); - void Debug(int from); + int GearNumber; + static const FGMatrix33 Tb2s; + FGMatrix33 mTGear; + FGColumnVector3 vGearOrient; + FGColumnVector3 vWhlBodyVec; + FGColumnVector3 vLocalGear; + FGColumnVector3 vWhlVelVec, vLocalWhlVel; // Velocity of this wheel + FGColumnVector3 normal, cvel, vGroundNormal; + FGLocation contact, gearLoc; + FGTable *ForceY_Table; + double dT; + double SteerAngle; + double kSpring; + double bDamp; + double bDampRebound; + double compressLength; + double compressSpeed; + double staticFCoeff, dynamicFCoeff, rollingFCoeff; + double Stiffness, Shape, Peak, Curvature; // Pacejka factors + double brakePct; + double BrakeFCoeff; + double maxCompLen; + double SinkRate; + double GroundSpeed; + double TakeoffDistanceTraveled; + double TakeoffDistanceTraveled50ft; + double LandingDistanceTraveled; + double MaximumStrutForce, StrutForce; + double MaximumStrutTravel; + double FCoeff; + double WheelSlip; + double TirePressureNorm; + double GearPos; + bool useFCSGearPos; + bool WOW; + bool lastWOW; + bool FirstContact; + bool StartedGroundRun; + bool LandingReported; + bool TakeoffReported; + bool ReportEnable; + bool isRetractable; + bool GearUp, GearDown; + bool Servicable; + bool Castered; + bool StaticFriction; + std::string name; + std::string sSteerType; + std::string sBrakeGroup; + std::string sRetractable; + std::string sContactType; + + BrakeGroup eBrakeGrp; + ContactType eContactType; + SteerType eSteerType; + DampType eDampType; + DampType eDampTypeRebound; + double maxSteerAngle; + + FGPropagate::LagrangeMultiplier LMultiplier[3]; + + FGAuxiliary* Auxiliary; + FGPropagate* Propagate; + FGFCS* FCS; + FGMassBalance* MassBalance; + FGGroundReactions* GroundReactions; + + void ComputeRetractionState(void); + void ComputeBrakeForceCoefficient(void); + void ComputeSteeringAngle(void); + void ComputeSlipAngle(void); + void ComputeSideForceCoefficient(void); + void ComputeVerticalStrutForce(void); + void ComputeGroundCoordSys(void); + void ComputeJacobian(const FGColumnVector3& vWhlContactVec); + void CrashDetect(void); + void InitializeReporting(void); + void ResetReporting(void); + void ReportTakeoffOrLanding(void); + void Report(ReportType rt); + void Debug(int from); }; } diff --git a/src/models/FGMassBalance.cpp b/src/models/FGMassBalance.cpp index 1cff8b8d4a4fa9ae7e428e4b810661896a368c1e..95608f6bf0bc0c69e61e845044a335957c81a90e 100644 --- a/src/models/FGMassBalance.cpp +++ b/src/models/FGMassBalance.cpp @@ -49,10 +49,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGMassBalance.cpp,v 1.32 2010/08/12 04:07:11 jberndt Exp $"; +static const char *IdSrc = "$Id: FGMassBalance.cpp,v 1.33 2010/09/07 00:40:03 jberndt Exp $"; static const char *IdHdr = ID_MASSBALANCE; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -62,436 +61,407 @@ CLASS IMPLEMENTATION FGMassBalance::FGMassBalance(FGFDMExec* fdmex) : FGModel(fdmex) { - Name = "FGMassBalance"; - Weight = EmptyWeight = Mass = 0.0; + Name = "FGMassBalance"; + Weight = EmptyWeight = Mass = 0.0; - vbaseXYZcg.InitMatrix(0.0); - vXYZcg.InitMatrix(0.0); - vLastXYZcg.InitMatrix(0.0); - vDeltaXYZcg.InitMatrix(0.0); - baseJ.InitMatrix(); - mJ.InitMatrix(); - mJinv.InitMatrix(); - pmJ.InitMatrix(); + vbaseXYZcg.InitMatrix(0.0); + vXYZcg.InitMatrix(0.0); + vLastXYZcg.InitMatrix(0.0); + vDeltaXYZcg.InitMatrix(0.0); + baseJ.InitMatrix(); + mJ.InitMatrix(); + mJinv.InitMatrix(); + pmJ.InitMatrix(); - bind(); + bind(); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMassBalance::~FGMassBalance() { - for (unsigned int i=0; i<PointMasses.size(); i++) delete PointMasses[i]; - PointMasses.clear(); + for (unsigned int i=0; i<PointMasses.size(); i++) delete PointMasses[i]; + PointMasses.clear(); - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGMassBalance::InitModel(void) { - if (!FGModel::InitModel()) return false; + if (!FGModel::InitModel()) return false; - vLastXYZcg.InitMatrix(0.0); - vDeltaXYZcg.InitMatrix(0.0); + vLastXYZcg.InitMatrix(0.0); + vDeltaXYZcg.InitMatrix(0.0); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGMassBalance::Load(Element* el) { - Element *element; - string element_name = ""; - double bixx, biyy, bizz, bixy, bixz, biyz; - - FGModel::Load(el); // Perform base class Load. - - bixx = biyy = bizz = bixy = bixz = biyz = 0.0; - if (el->FindElement("ixx")) - bixx = el->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2"); - if (el->FindElement("iyy")) - biyy = el->FindElementValueAsNumberConvertTo("iyy", "SLUG*FT2"); - if (el->FindElement("izz")) - bizz = el->FindElementValueAsNumberConvertTo("izz", "SLUG*FT2"); - if (el->FindElement("ixy")) - bixy = el->FindElementValueAsNumberConvertTo("ixy", "SLUG*FT2"); - if (el->FindElement("ixz")) - bixz = el->FindElementValueAsNumberConvertTo("ixz", "SLUG*FT2"); - if (el->FindElement("iyz")) - biyz = el->FindElementValueAsNumberConvertTo("iyz", "SLUG*FT2"); - SetAircraftBaseInertias(FGMatrix33( bixx, -bixy, bixz, - -bixy, biyy, -biyz, - bixz, -biyz, bizz )); - if (el->FindElement("emptywt")) - { - EmptyWeight = el->FindElementValueAsNumberConvertTo("emptywt", "LBS"); - } - - element = el->FindElement("location"); - while (element) - { - element_name = element->GetAttributeValue("name"); - if (element_name == "CG") vbaseXYZcg = element->FindElementTripletConvertTo("IN"); - element = el->FindNextElement("location"); - } + Element *element; + string element_name = ""; + double bixx, biyy, bizz, bixy, bixz, biyz; + + FGModel::Load(el); // Perform base class Load. + + bixx = biyy = bizz = bixy = bixz = biyz = 0.0; + if (el->FindElement("ixx")) + bixx = el->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2"); + if (el->FindElement("iyy")) + biyy = el->FindElementValueAsNumberConvertTo("iyy", "SLUG*FT2"); + if (el->FindElement("izz")) + bizz = el->FindElementValueAsNumberConvertTo("izz", "SLUG*FT2"); + if (el->FindElement("ixy")) + bixy = el->FindElementValueAsNumberConvertTo("ixy", "SLUG*FT2"); + if (el->FindElement("ixz")) + bixz = el->FindElementValueAsNumberConvertTo("ixz", "SLUG*FT2"); + if (el->FindElement("iyz")) + biyz = el->FindElementValueAsNumberConvertTo("iyz", "SLUG*FT2"); + SetAircraftBaseInertias(FGMatrix33( bixx, -bixy, bixz, + -bixy, biyy, -biyz, + bixz, -biyz, bizz )); + if (el->FindElement("emptywt")) { + EmptyWeight = el->FindElementValueAsNumberConvertTo("emptywt", "LBS"); + } + + element = el->FindElement("location"); + while (element) { + element_name = element->GetAttributeValue("name"); + if (element_name == "CG") vbaseXYZcg = element->FindElementTripletConvertTo("IN"); + element = el->FindNextElement("location"); + } // Find all POINTMASS elements that descend from this METRICS branch of the // config file. - element = el->FindElement("pointmass"); - while (element) - { - AddPointMass(element); - element = el->FindNextElement("pointmass"); - } + element = el->FindElement("pointmass"); + while (element) { + AddPointMass(element); + element = el->FindNextElement("pointmass"); + } - double ChildFDMWeight = 0.0; - for (int fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) - { - if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight(); - } + double ChildFDMWeight = 0.0; + for (int fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) { + if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight(); + } - Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetTotalPointMassWeight() - + BuoyantForces->GetGasMass()*slugtolb + ChildFDMWeight; + Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetTotalPointMassWeight() + + BuoyantForces->GetGasMass()*slugtolb + ChildFDMWeight; - Mass = lbtoslug*Weight; + Mass = lbtoslug*Weight; - FGModel::PostLoad(el); + PostLoad(el, PropertyManager); - Debug(2); - return true; + Debug(2); + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGMassBalance::Run(void) { - double denom, k1, k2, k3, k4, k5, k6; - double Ixx, Iyy, Izz, Ixy, Ixz, Iyz; + double denom, k1, k2, k3, k4, k5, k6; + double Ixx, Iyy, Izz, Ixy, Ixz, Iyz; - if (FGModel::Run()) return true; - if (FDMExec->Holding()) return false; + if (FGModel::Run()) return true; + if (FDMExec->Holding()) return false; - RunPreFunctions(); + RunPreFunctions(); - double ChildFDMWeight = 0.0; - for (int fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) - { - if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight(); - } + double ChildFDMWeight = 0.0; + for (int fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) { + if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight(); + } - Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetTotalPointMassWeight() - + BuoyantForces->GetGasMass()*slugtolb + ChildFDMWeight; + Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetTotalPointMassWeight() + + BuoyantForces->GetGasMass()*slugtolb + ChildFDMWeight; - Mass = lbtoslug*Weight; + Mass = lbtoslug*Weight; // Calculate new CG - vXYZcg = (Propulsion->GetTanksMoment() + EmptyWeight*vbaseXYZcg - + GetPointMassMoment() - + BuoyantForces->GetGasMassMoment()) / Weight; + vXYZcg = (Propulsion->GetTanksMoment() + EmptyWeight*vbaseXYZcg + + GetPointMassMoment() + + BuoyantForces->GetGasMassMoment()) / Weight; - // Track frame-by-frame delta CG, and move the EOM-tracked location - // by this amount. - if (vLastXYZcg.Magnitude() == 0.0) vLastXYZcg = vXYZcg; - vDeltaXYZcg = vXYZcg - vLastXYZcg; - vDeltaXYZcgBody = StructuralToBody(vLastXYZcg) - StructuralToBody(vXYZcg); - vLastXYZcg = vXYZcg; - Propagate->NudgeBodyLocation(vDeltaXYZcgBody); + // Track frame-by-frame delta CG, and move the EOM-tracked location + // by this amount. + if (vLastXYZcg.Magnitude() == 0.0) vLastXYZcg = vXYZcg; + vDeltaXYZcg = vXYZcg - vLastXYZcg; + vDeltaXYZcgBody = StructuralToBody(vLastXYZcg) - StructuralToBody(vXYZcg); + vLastXYZcg = vXYZcg; + Propagate->NudgeBodyLocation(vDeltaXYZcgBody); // Calculate new total moments of inertia - // At first it is the base configuration inertia matrix ... - mJ = baseJ; - // ... with the additional term originating from the parallel axis theorem. - mJ += GetPointmassInertia( lbtoslug * EmptyWeight, vbaseXYZcg ); - // Then add the contributions from the additional pointmasses. - mJ += CalculatePMInertias(); - mJ += Propulsion->CalculateTankInertias(); - mJ += BuoyantForces->GetGasMassInertia(); - - Ixx = mJ(1,1); - Iyy = mJ(2,2); - Izz = mJ(3,3); - Ixy = -mJ(1,2); - Ixz = -mJ(1,3); - Iyz = -mJ(2,3); + // At first it is the base configuration inertia matrix ... + mJ = baseJ; + // ... with the additional term originating from the parallel axis theorem. + mJ += GetPointmassInertia( lbtoslug * EmptyWeight, vbaseXYZcg ); + // Then add the contributions from the additional pointmasses. + mJ += CalculatePMInertias(); + mJ += Propulsion->CalculateTankInertias(); + mJ += BuoyantForces->GetGasMassInertia(); + + Ixx = mJ(1,1); + Iyy = mJ(2,2); + Izz = mJ(3,3); + Ixy = -mJ(1,2); + Ixz = -mJ(1,3); + Iyz = -mJ(2,3); // Calculate inertia matrix inverse (ref. Stevens and Lewis, "Flight Control & Simulation") - k1 = (Iyy*Izz - Iyz*Iyz); - k2 = (Iyz*Ixz + Ixy*Izz); - k3 = (Ixy*Iyz + Iyy*Ixz); + k1 = (Iyy*Izz - Iyz*Iyz); + k2 = (Iyz*Ixz + Ixy*Izz); + k3 = (Ixy*Iyz + Iyy*Ixz); - denom = 1.0/(Ixx*k1 - Ixy*k2 - Ixz*k3 ); - k1 = k1*denom; - k2 = k2*denom; - k3 = k3*denom; - k4 = (Izz*Ixx - Ixz*Ixz)*denom; - k5 = (Ixy*Ixz + Iyz*Ixx)*denom; - k6 = (Ixx*Iyy - Ixy*Ixy)*denom; + denom = 1.0/(Ixx*k1 - Ixy*k2 - Ixz*k3 ); + k1 = k1*denom; + k2 = k2*denom; + k3 = k3*denom; + k4 = (Izz*Ixx - Ixz*Ixz)*denom; + k5 = (Ixy*Ixz + Iyz*Ixx)*denom; + k6 = (Ixx*Iyy - Ixy*Ixy)*denom; - mJinv.InitMatrix( k1, k2, k3, - k2, k4, k5, - k3, k5, k6 ); + mJinv.InitMatrix( k1, k2, k3, + k2, k4, k5, + k3, k5, k6 ); - RunPostFunctions(); + RunPostFunctions(); - Debug(0); + Debug(0); - return false; + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGMassBalance::AddPointMass(Element* el) { - double radius=0, length=0; - Element* loc_element = el->FindElement("location"); - string pointmass_name = el->GetAttributeValue("name"); - if (!loc_element) - { - cerr << "Pointmass " << pointmass_name << " has no location." << endl; - exit(-1); + double radius=0, length=0; + Element* loc_element = el->FindElement("location"); + string pointmass_name = el->GetAttributeValue("name"); + if (!loc_element) { + cerr << "Pointmass " << pointmass_name << " has no location." << endl; + exit(-1); + } + + double w = el->FindElementValueAsNumberConvertTo("weight", "LBS"); + FGColumnVector3 vXYZ = loc_element->FindElementTripletConvertTo("IN"); + + PointMass *pm = new PointMass(w, vXYZ); + pm->SetName(pointmass_name); + + Element* form_element = el->FindElement("form"); + if (form_element) { + string shape = form_element->GetAttributeValue("shape"); + Element* radius_element = form_element->FindElement("radius"); + Element* length_element = form_element->FindElement("length"); + if (radius_element) radius = form_element->FindElementValueAsNumberConvertTo("radius", "FT"); + if (length_element) length = form_element->FindElementValueAsNumberConvertTo("length", "FT"); + if (shape == "tube") { + pm->SetPointMassShapeType(PointMass::esTube); + pm->SetRadius(radius); + pm->SetLength(length); + pm->CalculateShapeInertia(); + } else if (shape == "cylinder") { + pm->SetPointMassShapeType(PointMass::esCylinder); + pm->SetRadius(radius); + pm->SetLength(length); + pm->CalculateShapeInertia(); + } else if (shape == "sphere") { + pm->SetPointMassShapeType(PointMass::esSphere); + pm->SetRadius(radius); + pm->CalculateShapeInertia(); + } else if (shape == "ball") { + pm->SetPointMassShapeType(PointMass::esBall); + pm->SetRadius(radius); + pm->CalculateShapeInertia(); + } else { } + } - double w = el->FindElementValueAsNumberConvertTo("weight", "LBS"); - FGColumnVector3 vXYZ = loc_element->FindElementTripletConvertTo("IN"); - - PointMass *pm = new PointMass(w, vXYZ); - pm->SetName(pointmass_name); - - Element* form_element = el->FindElement("form"); - if (form_element) - { - string shape = form_element->GetAttributeValue("shape"); - Element* radius_element = form_element->FindElement("radius"); - Element* length_element = form_element->FindElement("length"); - if (radius_element) radius = form_element->FindElementValueAsNumberConvertTo("radius", "FT"); - if (length_element) length = form_element->FindElementValueAsNumberConvertTo("length", "FT"); - if (shape == "tube") - { - pm->SetPointMassShapeType(PointMass::esTube); - pm->SetRadius(radius); - pm->SetLength(length); - pm->CalculateShapeInertia(); - } - else if (shape == "cylinder") - { - pm->SetPointMassShapeType(PointMass::esCylinder); - pm->SetRadius(radius); - pm->SetLength(length); - pm->CalculateShapeInertia(); - } - else if (shape == "sphere") - { - pm->SetPointMassShapeType(PointMass::esSphere); - pm->SetRadius(radius); - pm->CalculateShapeInertia(); - } - else if (shape == "ball") - { - pm->SetPointMassShapeType(PointMass::esBall); - pm->SetRadius(radius); - pm->CalculateShapeInertia(); - } - else - { - } - } - - pm->bind(PropertyManager, PointMasses.size()); - PointMasses.push_back(pm); + pm->bind(PropertyManager, PointMasses.size()); + PointMasses.push_back(pm); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGMassBalance::GetTotalPointMassWeight(void) { - double PM_total_weight = 0.0; + double PM_total_weight = 0.0; - for (unsigned int i=0; i<PointMasses.size(); i++) - { - PM_total_weight += PointMasses[i]->Weight; - } - return PM_total_weight; + for (unsigned int i=0; i<PointMasses.size(); i++) { + PM_total_weight += PointMasses[i]->Weight; + } + return PM_total_weight; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3& FGMassBalance::GetPointMassMoment(void) { - PointMassCG.InitMatrix(); + PointMassCG.InitMatrix(); - for (unsigned int i=0; i<PointMasses.size(); i++) - { - PointMassCG += PointMasses[i]->Weight*PointMasses[i]->Location; - } - return PointMassCG; + for (unsigned int i=0; i<PointMasses.size(); i++) { + PointMassCG += PointMasses[i]->Weight*PointMasses[i]->Location; + } + return PointMassCG; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33& FGMassBalance::CalculatePMInertias(void) { - unsigned int size; + unsigned int size; - size = PointMasses.size(); - if (size == 0) return pmJ; + size = PointMasses.size(); + if (size == 0) return pmJ; - pmJ = FGMatrix33(); + pmJ = FGMatrix33(); - for (unsigned int i=0; i<size; i++) - { - pmJ += GetPointmassInertia( lbtoslug * PointMasses[i]->Weight, PointMasses[i]->Location ); - pmJ += PointMasses[i]->GetPointMassInertia(); - } + for (unsigned int i=0; i<size; i++) { + pmJ += GetPointmassInertia( lbtoslug * PointMasses[i]->Weight, PointMasses[i]->Location ); + pmJ += PointMasses[i]->GetPointMassInertia(); + } - return pmJ; + return pmJ; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3 FGMassBalance::StructuralToBody(const FGColumnVector3& r) const { - // Under the assumption that in the structural frame the: - // - // - X-axis is directed afterwards, - // - Y-axis is directed towards the right, - // - Z-axis is directed upwards, - // - // (as documented in http://jsbsim.sourceforge.net/JSBSimCoordinates.pdf) - // we have to subtract first the center of gravity of the plane which - // is also defined in the structural frame: - // - // FGColumnVector3 cgOff = r - vXYZcg; - // - // Next, we do a change of units: - // - // cgOff *= inchtoft; - // - // And then a 180 degree rotation is done about the Y axis so that the: - // - // - X-axis is directed forward, - // - Y-axis is directed towards the right, - // - Z-axis is directed downward. - // - // This is needed because the structural and body frames are 180 degrees apart. - - return FGColumnVector3(inchtoft*(vXYZcg(1)-r(1)), - inchtoft*(r(2)-vXYZcg(2)), - inchtoft*(vXYZcg(3)-r(3))); + // Under the assumption that in the structural frame the: + // + // - X-axis is directed afterwards, + // - Y-axis is directed towards the right, + // - Z-axis is directed upwards, + // + // (as documented in http://jsbsim.sourceforge.net/JSBSimCoordinates.pdf) + // we have to subtract first the center of gravity of the plane which + // is also defined in the structural frame: + // + // FGColumnVector3 cgOff = r - vXYZcg; + // + // Next, we do a change of units: + // + // cgOff *= inchtoft; + // + // And then a 180 degree rotation is done about the Y axis so that the: + // + // - X-axis is directed forward, + // - Y-axis is directed towards the right, + // - Z-axis is directed downward. + // + // This is needed because the structural and body frames are 180 degrees apart. + + return FGColumnVector3(inchtoft*(vXYZcg(1)-r(1)), + inchtoft*(r(2)-vXYZcg(2)), + inchtoft*(vXYZcg(3)-r(3))); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGMassBalance::bind(void) { - typedef double (FGMassBalance::*PMF)(int) const; - PropertyManager->Tie("inertia/mass-slugs", this, - &FGMassBalance::GetMass); - PropertyManager->Tie("inertia/weight-lbs", this, - &FGMassBalance::GetWeight); - PropertyManager->Tie("inertia/empty-weight-lbs", this, - &FGMassBalance::GetEmptyWeight); - PropertyManager->Tie("inertia/cg-x-in", this,1, - (PMF)&FGMassBalance::GetXYZcg); - PropertyManager->Tie("inertia/cg-y-in", this,2, - (PMF)&FGMassBalance::GetXYZcg); - PropertyManager->Tie("inertia/cg-z-in", this,3, - (PMF)&FGMassBalance::GetXYZcg); + typedef double (FGMassBalance::*PMF)(int) const; + PropertyManager->Tie("inertia/mass-slugs", this, + &FGMassBalance::GetMass); + PropertyManager->Tie("inertia/weight-lbs", this, + &FGMassBalance::GetWeight); + PropertyManager->Tie("inertia/empty-weight-lbs", this, + &FGMassBalance::GetEmptyWeight); + PropertyManager->Tie("inertia/cg-x-in", this,1, + (PMF)&FGMassBalance::GetXYZcg); + PropertyManager->Tie("inertia/cg-y-in", this,2, + (PMF)&FGMassBalance::GetXYZcg); + PropertyManager->Tie("inertia/cg-z-in", this,3, + (PMF)&FGMassBalance::GetXYZcg); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // // This function binds properties for each pointmass object created. // -void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager, int num) -{ - string tmp = CreateIndexedPropertyName("inertia/pointmass-weight-lbs", num); - PropertyManager->Tie( tmp.c_str(), this, &PointMass::GetPointMassWeight, - &PointMass::SetPointMassWeight); - - tmp = CreateIndexedPropertyName("inertia/pointmass-location-X-inches", num); - PropertyManager->Tie( tmp.c_str(), this, eX, &PointMass::GetPointMassLocation, - &PointMass::SetPointMassLocation); - tmp = CreateIndexedPropertyName("inertia/pointmass-location-Y-inches", num); - PropertyManager->Tie( tmp.c_str(), this, eY, &PointMass::GetPointMassLocation, - &PointMass::SetPointMassLocation); - tmp = CreateIndexedPropertyName("inertia/pointmass-location-Z-inches", num); - PropertyManager->Tie( tmp.c_str(), this, eZ, &PointMass::GetPointMassLocation, - &PointMass::SetPointMassLocation); +void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager, int num) { + string tmp = CreateIndexedPropertyName("inertia/pointmass-weight-lbs", num); + PropertyManager->Tie( tmp.c_str(), this, &PointMass::GetPointMassWeight, + &PointMass::SetPointMassWeight); + + tmp = CreateIndexedPropertyName("inertia/pointmass-location-X-inches", num); + PropertyManager->Tie( tmp.c_str(), this, eX, &PointMass::GetPointMassLocation, + &PointMass::SetPointMassLocation); + tmp = CreateIndexedPropertyName("inertia/pointmass-location-Y-inches", num); + PropertyManager->Tie( tmp.c_str(), this, eY, &PointMass::GetPointMassLocation, + &PointMass::SetPointMassLocation); + tmp = CreateIndexedPropertyName("inertia/pointmass-location-Z-inches", num); + PropertyManager->Tie( tmp.c_str(), this, eZ, &PointMass::GetPointMassLocation, + &PointMass::SetPointMassLocation); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGMassBalance::GetMassPropertiesReport(void) const { - cout << endl << fgblue << highint - << " Mass Properties Report (English units: lbf, in, slug-ft^2)" - << reset << endl; - cout << " " << underon << " Weight CG-X CG-Y" - << " CG-Z Ixx Iyy Izz" << underoff << endl; - cout.precision(1); - cout << highint << setw(34) << left << " Base Vehicle " << normint - << right << setw(10) << EmptyWeight << setw(8) << vbaseXYZcg(eX) << setw(8) - << vbaseXYZcg(eY) << setw(8) << vbaseXYZcg(eZ) << setw(12) << baseJ(1,1) - << setw(12) << baseJ(2,2) << setw(12) << baseJ(3,3) << endl; - - for (unsigned int i=0;i<PointMasses.size();i++) - { - PointMass* pm = PointMasses[i]; - double pmweight = pm->GetPointMassWeight(); - cout << highint << left << setw(4) << i << setw(30) << pm->GetName() << normint - << right << setw(10) << pmweight << setw(8) << pm->GetLocation()(eX) - << setw(8) << pm->GetLocation()(eY) << setw(8) << pm->GetLocation()(eZ) - << setw(12) << pm->GetPointMassMoI(1,1) << setw(12) << pm->GetPointMassMoI(2,2) - << setw(12) << pm->GetPointMassMoI(3,3) << endl; - } - - for (unsigned int i=0;i<Propulsion->GetNumTanks() ;i++) - { - FGTank* tank = Propulsion->GetTank(i); - string tankname=""; - if (tank->GetType() == FGTank::ttFUEL && tank->GetGrainType() != FGTank::gtUNKNOWN) - { - tankname = "Solid Fuel"; - } - else if (tank->GetType() == FGTank::ttFUEL) - { - tankname = "Fuel"; - } - else if (tank->GetType() == FGTank::ttOXIDIZER) - { - tankname = "Oxidizer"; - } - else - { - tankname = "(Unknown tank type)"; - } - cout << highint << left << setw(4) << i << setw(30) << tankname << normint - << right << setw(10) << tank->GetContents() << setw(8) << tank->GetXYZ(eX) - << setw(8) << tank->GetXYZ(eY) << setw(8) << tank->GetXYZ(eZ) - << setw(12) << "*" << setw(12) << "*" - << setw(12) << "*" << endl; + cout << endl << fgblue << highint + << " Mass Properties Report (English units: lbf, in, slug-ft^2)" + << reset << endl; + cout << " " << underon << " Weight CG-X CG-Y" + << " CG-Z Ixx Iyy Izz" << underoff << endl; + cout.precision(1); + cout << highint << setw(34) << left << " Base Vehicle " << normint + << right << setw(10) << EmptyWeight << setw(8) << vbaseXYZcg(eX) << setw(8) + << vbaseXYZcg(eY) << setw(8) << vbaseXYZcg(eZ) << setw(12) << baseJ(1,1) + << setw(12) << baseJ(2,2) << setw(12) << baseJ(3,3) << endl; + + for (unsigned int i=0;i<PointMasses.size();i++) { + PointMass* pm = PointMasses[i]; + double pmweight = pm->GetPointMassWeight(); + cout << highint << left << setw(4) << i << setw(30) << pm->GetName() << normint + << right << setw(10) << pmweight << setw(8) << pm->GetLocation()(eX) + << setw(8) << pm->GetLocation()(eY) << setw(8) << pm->GetLocation()(eZ) + << setw(12) << pm->GetPointMassMoI(1,1) << setw(12) << pm->GetPointMassMoI(2,2) + << setw(12) << pm->GetPointMassMoI(3,3) << endl; + } + + for (unsigned int i=0;i<Propulsion->GetNumTanks() ;i++) { + FGTank* tank = Propulsion->GetTank(i); + string tankname=""; + if (tank->GetType() == FGTank::ttFUEL && tank->GetGrainType() != FGTank::gtUNKNOWN) { + tankname = "Solid Fuel"; + } else if (tank->GetType() == FGTank::ttFUEL) { + tankname = "Fuel"; + } else if (tank->GetType() == FGTank::ttOXIDIZER) { + tankname = "Oxidizer"; + } else { + tankname = "(Unknown tank type)"; } - - cout << underon << setw(104) << " " << underoff << endl; - cout << highint << left << setw(30) << " Total: " << right << setw(14) << Weight - << setw(8) << vXYZcg(eX) - << setw(8) << vXYZcg(eY) - << setw(8) << vXYZcg(eZ) - << setw(12) << mJ(1,1) - << setw(12) << mJ(2,2) - << setw(12) << mJ(3,3) - << normint << endl; - - cout.setf(ios_base::fixed); + cout << highint << left << setw(4) << i << setw(30) << tankname << normint + << right << setw(10) << tank->GetContents() << setw(8) << tank->GetXYZ(eX) + << setw(8) << tank->GetXYZ(eY) << setw(8) << tank->GetXYZ(eZ) + << setw(12) << "*" << setw(12) << "*" + << setw(12) << "*" << endl; + } + + cout << underon << setw(104) << " " << underoff << endl; + cout << highint << left << setw(30) << " Total: " << right << setw(14) << Weight + << setw(8) << vXYZcg(eX) + << setw(8) << vXYZcg(eY) + << setw(8) << vXYZcg(eZ) + << setw(12) << mJ(1,1) + << setw(12) << mJ(2,2) + << setw(12) << mJ(3,3) + << normint << endl; + + cout.setf(ios_base::fixed); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -515,61 +485,51 @@ void FGMassBalance::GetMassPropertiesReport(void) const void FGMassBalance::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 2) // Loading - { - cout << endl << " Mass and Balance:" << endl; - cout << " baseIxx: " << baseJ(1,1) << " slug-ft2" << endl; - cout << " baseIyy: " << baseJ(2,2) << " slug-ft2" << endl; - cout << " baseIzz: " << baseJ(3,3) << " slug-ft2" << endl; - cout << " baseIxy: " << baseJ(1,2) << " slug-ft2" << endl; - cout << " baseIxz: " << baseJ(1,3) << " slug-ft2" << endl; - cout << " baseIyz: " << baseJ(2,3) << " slug-ft2" << endl; - cout << " Empty Weight: " << EmptyWeight << " lbm" << endl; - cout << " CG (x, y, z): " << vbaseXYZcg << endl; - // ToDo: Need to add point mass outputs here - for (unsigned int i=0; i<PointMasses.size(); i++) - { - cout << " Point Mass Object: " << PointMasses[i]->Weight << " lbs. at " - << "X, Y, Z (in.): " << PointMasses[i]->Location(eX) << " " - << PointMasses[i]->Location(eY) << " " - << PointMasses[i]->Location(eZ) << endl; - } - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGMassBalance" << endl; - if (from == 1) cout << "Destroyed: FGMassBalance" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 2) { // Loading + cout << endl << " Mass and Balance:" << endl; + cout << " baseIxx: " << baseJ(1,1) << " slug-ft2" << endl; + cout << " baseIyy: " << baseJ(2,2) << " slug-ft2" << endl; + cout << " baseIzz: " << baseJ(3,3) << " slug-ft2" << endl; + cout << " baseIxy: " << baseJ(1,2) << " slug-ft2" << endl; + cout << " baseIxz: " << baseJ(1,3) << " slug-ft2" << endl; + cout << " baseIyz: " << baseJ(2,3) << " slug-ft2" << endl; + cout << " Empty Weight: " << EmptyWeight << " lbm" << endl; + cout << " CG (x, y, z): " << vbaseXYZcg << endl; + // ToDo: Need to add point mass outputs here + for (unsigned int i=0; i<PointMasses.size(); i++) { + cout << " Point Mass Object: " << PointMasses[i]->Weight << " lbs. at " + << "X, Y, Z (in.): " << PointMasses[i]->Location(eX) << " " + << PointMasses[i]->Location(eY) << " " + << PointMasses[i]->Location(eZ) << endl; + } } - if (debug_lvl & 16) // Sanity checking - { - if (from == 2) - { - if (EmptyWeight <= 0.0 || EmptyWeight > 1e9) - cout << "MassBalance::EmptyWeight out of bounds: " << EmptyWeight << endl; - if (Weight <= 0.0 || Weight > 1e9) - cout << "MassBalance::Weight out of bounds: " << Weight << endl; - if (Mass <= 0.0 || Mass > 1e9) - cout << "MassBalance::Mass out of bounds: " << Mass << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGMassBalance" << endl; + if (from == 1) cout << "Destroyed: FGMassBalance" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + if (from == 2) { + if (EmptyWeight <= 0.0 || EmptyWeight > 1e9) + cout << "MassBalance::EmptyWeight out of bounds: " << EmptyWeight << endl; + if (Weight <= 0.0 || Weight > 1e9) + cout << "MassBalance::Weight out of bounds: " << Weight << endl; + if (Mass <= 0.0 || Mass > 1e9) + cout << "MassBalance::Mass out of bounds: " << Mass << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/FGMassBalance.h b/src/models/FGMassBalance.h index 3d3a6e5cb129c802c655efba6ae291099ee48f70..be461a1e8204f950418ee91a61fb5ef07bd7471a 100644 --- a/src/models/FGMassBalance.h +++ b/src/models/FGMassBalance.h @@ -57,8 +57,7 @@ FORWARD DECLARATIONSS using std::string; -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -91,7 +90,7 @@ CLASS DOCUMENTATION <form shape="{tube | cylinder | sphere | ball}"> <radius unit="{IN | FT | M}"> {number} </radius> <length unit="{IN | FT | M}"> {number} </length> - </form> + </form> <weight unit="{LBS | KG}"> {number} </weight> <location name="{string}" unit="{IN | FT | M}"> <x> {number} </x> @@ -112,232 +111,153 @@ class FGMassBalance : public FGModel { public: - FGMassBalance(FGFDMExec*); - ~FGMassBalance(); - - bool Load(Element* el); - bool InitModel(void); - bool Run(void); - - double GetMass(void) const - { - return Mass; - } - double GetWeight(void) const - { - return Weight; - } - double GetEmptyWeight(void) const - { - return EmptyWeight; - } - const FGColumnVector3& GetXYZcg(void) const - { - return vXYZcg; - } - double GetXYZcg(int axis) const - { - return vXYZcg(axis); - } - const FGColumnVector3& GetDeltaXYZcg(void) const - { - return vDeltaXYZcg; - } - double GetDeltaXYZcg(int axis) const - { - return vDeltaXYZcg(axis); - } - - /** Computes the inertia contribution of a pointmass. - Computes and returns the inertia matrix of a pointmass of mass - slugs at the given vector r in the structural frame. The units - should be for the mass in slug and the vector in the structural - frame as usual in inches. - @param slugs the mass of this single pointmass given in slugs - @param r the location of this single pointmass in the structural frame - */ - FGMatrix33 GetPointmassInertia(double slugs, const FGColumnVector3& r) const - { - FGColumnVector3 v = StructuralToBody( r ); - FGColumnVector3 sv = slugs*v; - double xx = sv(1)*v(1); - double yy = sv(2)*v(2); - double zz = sv(3)*v(3); - double xy = -sv(1)*v(2); - double xz = -sv(1)*v(3); - double yz = -sv(2)*v(3); - return FGMatrix33( yy+zz, xy, xz, - xy, xx+zz, yz, - xz, yz, xx+yy ); + FGMassBalance(FGFDMExec*); + ~FGMassBalance(); + + bool Load(Element* el); + bool InitModel(void); + bool Run(void); + + double GetMass(void) const {return Mass;} + double GetWeight(void) const {return Weight;} + double GetEmptyWeight(void) const {return EmptyWeight;} + const FGColumnVector3& GetXYZcg(void) const {return vXYZcg;} + double GetXYZcg(int axis) const {return vXYZcg(axis);} + const FGColumnVector3& GetDeltaXYZcg(void) const {return vDeltaXYZcg;} + double GetDeltaXYZcg(int axis) const {return vDeltaXYZcg(axis);} + + /** Computes the inertia contribution of a pointmass. + Computes and returns the inertia matrix of a pointmass of mass + slugs at the given vector r in the structural frame. The units + should be for the mass in slug and the vector in the structural + frame as usual in inches. + @param slugs the mass of this single pointmass given in slugs + @param r the location of this single pointmass in the structural frame + */ + FGMatrix33 GetPointmassInertia(double slugs, const FGColumnVector3& r) const + { + FGColumnVector3 v = StructuralToBody( r ); + FGColumnVector3 sv = slugs*v; + double xx = sv(1)*v(1); + double yy = sv(2)*v(2); + double zz = sv(3)*v(3); + double xy = -sv(1)*v(2); + double xz = -sv(1)*v(3); + double yz = -sv(2)*v(3); + return FGMatrix33( yy+zz, xy, xz, + xy, xx+zz, yz, + xz, yz, xx+yy ); + } + + /** Conversion from the structural frame to the body frame. + Converts the location given in the structural frame + coordinate system to the body frame. The units of the structural + frame are assumed to be in inches. The unit of the result is in + ft. + @param r vector coordinate in the structural reference frame (X positive + aft, measurements in inches). + @return vector coordinate in the body frame, in feet. + */ + FGColumnVector3 StructuralToBody(const FGColumnVector3& r) const; + + inline void SetEmptyWeight(double EW) { EmptyWeight = EW;} + inline void SetBaseCG(const FGColumnVector3& CG) {vbaseXYZcg = vXYZcg = CG;} + + void AddPointMass(Element* el); + double GetTotalPointMassWeight(void); + + FGColumnVector3& GetPointMassMoment(void); + FGMatrix33& GetJ(void) {return mJ;} + FGMatrix33& GetJinv(void) {return mJinv;} + void SetAircraftBaseInertias(FGMatrix33 BaseJ) {baseJ = BaseJ;} + void GetMassPropertiesReport(void) const; + +private: + double Weight; + double EmptyWeight; + double Mass; + FGMatrix33 mJ; + FGMatrix33 mJinv; + FGMatrix33 pmJ; + FGMatrix33 baseJ; + FGColumnVector3 vXYZcg; + FGColumnVector3 vLastXYZcg; + FGColumnVector3 vDeltaXYZcg; + FGColumnVector3 vDeltaXYZcgBody; + FGColumnVector3 vXYZtank; + FGColumnVector3 vbaseXYZcg; + FGColumnVector3 vPMxyz; + FGColumnVector3 PointMassCG; + FGMatrix33& CalculatePMInertias(void); + + + /** The PointMass structure encapsulates a point mass object, moments of inertia + mass, location, etc. */ + struct PointMass { + PointMass(double w, FGColumnVector3& vXYZ) { + Weight = w; + Location = vXYZ; + mPMInertia.InitMatrix(); + Radius = 0.0; + Length = 0.0; } - /** Conversion from the structural frame to the body frame. - Converts the location given in the structural frame - coordinate system to the body frame. The units of the structural - frame are assumed to be in inches. The unit of the result is in - ft. - @param r vector coordinate in the structural reference frame (X positive - aft, measurements in inches). - @return vector coordinate in the body frame, in feet. - */ - FGColumnVector3 StructuralToBody(const FGColumnVector3& r) const; - - inline void SetEmptyWeight(double EW) - { - EmptyWeight = EW; - } - inline void SetBaseCG(const FGColumnVector3& CG) - { - vbaseXYZcg = vXYZcg = CG; + void CalculateShapeInertia(void) { + switch(eShapeType) { + case esTube: + mPMInertia(1,1) = (Weight/(slugtolb))*Radius*Radius; // mr^2 + mPMInertia(2,2) = (Weight/(slugtolb*12))*(6*Radius*Radius + Length*Length); + mPMInertia(3,3) = mPMInertia(2,2); + break; + case esCylinder: + mPMInertia(1,1) = (Weight/(slugtolb*2))*Radius*Radius; // 0.5*mr^2 + mPMInertia(2,2) = (Weight/(slugtolb*12))*(3*Radius*Radius + Length*Length); + mPMInertia(3,3) = mPMInertia(2,2); + break; + case esSphere: + mPMInertia(1,1) = (Weight/(slugtolb*3))*Radius*Radius*2; // (2mr^2)/3 + mPMInertia(2,2) = mPMInertia(1,1); + mPMInertia(3,3) = mPMInertia(1,1); + case esBall: + mPMInertia(1,1) = (Weight/(slugtolb*5))*Radius*Radius*2; // (2mr^2)/5 + mPMInertia(2,2) = mPMInertia(1,1); + mPMInertia(3,3) = mPMInertia(1,1); + break; + default: + break; + } } - void AddPointMass(Element* el); - double GetTotalPointMassWeight(void); - - FGColumnVector3& GetPointMassMoment(void); - FGMatrix33& GetJ(void) - { - return mJ; - } - FGMatrix33& GetJinv(void) - { - return mJinv; - } - void SetAircraftBaseInertias(FGMatrix33 BaseJ) - { - baseJ = BaseJ; - } - void GetMassPropertiesReport(void) const; - -private: - double Weight; - double EmptyWeight; - double Mass; - FGMatrix33 mJ; - FGMatrix33 mJinv; - FGMatrix33 pmJ; - FGMatrix33 baseJ; - FGColumnVector3 vXYZcg; - FGColumnVector3 vLastXYZcg; - FGColumnVector3 vDeltaXYZcg; - FGColumnVector3 vDeltaXYZcgBody; - FGColumnVector3 vXYZtank; - FGColumnVector3 vbaseXYZcg; - FGColumnVector3 vPMxyz; - FGColumnVector3 PointMassCG; - FGMatrix33& CalculatePMInertias(void); - - - /** The PointMass structure encapsulates a point mass object, moments of inertia - mass, location, etc. */ - struct PointMass - { - PointMass(double w, FGColumnVector3& vXYZ) - { - Weight = w; - Location = vXYZ; - mPMInertia.InitMatrix(); - Radius = 0.0; - Length = 0.0; - } - - void CalculateShapeInertia(void) - { - switch (eShapeType) - { - case esTube: - mPMInertia(1,1) = (Weight/(slugtolb))*Radius*Radius; // mr^2 - mPMInertia(2,2) = (Weight/(slugtolb*12))*(6*Radius*Radius + Length*Length); - mPMInertia(3,3) = mPMInertia(2,2); - break; - case esCylinder: - mPMInertia(1,1) = (Weight/(slugtolb*2))*Radius*Radius; // 0.5*mr^2 - mPMInertia(2,2) = (Weight/(slugtolb*12))*(3*Radius*Radius + Length*Length); - mPMInertia(3,3) = mPMInertia(2,2); - break; - case esSphere: - mPMInertia(1,1) = (Weight/(slugtolb*3))*Radius*Radius*2; // (2mr^2)/3 - mPMInertia(2,2) = mPMInertia(1,1); - mPMInertia(3,3) = mPMInertia(1,1); - case esBall: - mPMInertia(1,1) = (Weight/(slugtolb*5))*Radius*Radius*2; // (2mr^2)/5 - mPMInertia(2,2) = mPMInertia(1,1); - mPMInertia(3,3) = mPMInertia(1,1); - break; - default: - break; - } - } - - enum esShape {esUnspecified, esTube, esCylinder, esSphere, esBall} eShapeType; - FGColumnVector3 Location; - double Weight; /// Weight in pounds. - double Radius; /// Radius in feet. - double Length; /// Length in feet. - string Name; - FGMatrix33 mPMInertia; - - double GetPointMassLocation(int axis) const - { - return Location(axis); - } - double GetPointMassWeight(void) const - { - return Weight; - } - esShape GetShapeType(void) - { - return eShapeType; - } - FGColumnVector3 GetLocation(void) - { - return Location; - } - FGMatrix33 GetPointMassInertia(void) - { - return mPMInertia; - } - string GetName(void) - { - return Name; - } - - void SetPointMassLocation(int axis, double value) - { - Location(axis) = value; - } - void SetPointMassWeight(double wt) - { - Weight = wt; - } - void SetPointMassShapeType(esShape st) - { - eShapeType = st; - } - void SetRadius(double r) - { - Radius = r; - } - void SetLength(double l) - { - Length = l; - } - void SetName(string name) - { - Name = name; - } - double GetPointMassMoI(int r, int c) - { - return mPMInertia(r,c); - } - - void bind(FGPropertyManager* PropertyManager, int num); - }; - - std::vector <struct PointMass*> PointMasses; - - void bind(void); - void Debug(int from); + enum esShape {esUnspecified, esTube, esCylinder, esSphere, esBall} eShapeType; + FGColumnVector3 Location; + double Weight; /// Weight in pounds. + double Radius; /// Radius in feet. + double Length; /// Length in feet. + string Name; + FGMatrix33 mPMInertia; + + double GetPointMassLocation(int axis) const {return Location(axis);} + double GetPointMassWeight(void) const {return Weight;} + esShape GetShapeType(void) {return eShapeType;} + FGColumnVector3 GetLocation(void) {return Location;} + FGMatrix33 GetPointMassInertia(void) {return mPMInertia;} + string GetName(void) {return Name;} + + void SetPointMassLocation(int axis, double value) {Location(axis) = value;} + void SetPointMassWeight(double wt) {Weight = wt;} + void SetPointMassShapeType(esShape st) {eShapeType = st;} + void SetRadius(double r) {Radius = r;} + void SetLength(double l) {Length = l;} + void SetName(string name) {Name = name;} + double GetPointMassMoI(int r, int c) {return mPMInertia(r,c);} + + void bind(FGPropertyManager* PropertyManager, int num); + }; + + std::vector <struct PointMass*> PointMasses; + + void bind(void); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/FGModel.cpp b/src/models/FGModel.cpp index 3637f8b5830191076a8e6b9184cc3925ea22364d..fe8039919b2addeea9ac37346ef243f231ba89a2 100644 --- a/src/models/FGModel.cpp +++ b/src/models/FGModel.cpp @@ -55,10 +55,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGModel.cpp,v 1.14 2010/02/25 05:21:36 jberndt Exp $"; +static const char *IdSrc = "$Id: FGModel.cpp,v 1.15 2010/09/07 00:19:38 jberndt Exp $"; static const char *IdHdr = ID_MODEL; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -71,185 +70,81 @@ CLASS IMPLEMENTATION FGModel::FGModel(FGFDMExec* fdmex) { - FDMExec = fdmex; - NextModel = 0L; - - Atmosphere = 0; - FCS = 0; - Propulsion = 0; - MassBalance = 0; - Aerodynamics = 0; - Inertial = 0; - GroundReactions = 0; - ExternalReactions = 0; - Aircraft = 0; - Propagate = 0; - Auxiliary = 0; - - //in order for FGModel derived classes to self-bind (that is, call - //their bind function in the constructor, the PropertyManager pointer - //must be brought up now. - PropertyManager = FDMExec->GetPropertyManager(); - - exe_ctr = 1; - rate = 1; - - if (debug_lvl & 2) cout << " FGModel Base Class" << endl; + FDMExec = fdmex; + + Atmosphere = 0; + FCS = 0; + Propulsion = 0; + MassBalance = 0; + Aerodynamics = 0; + Inertial = 0; + GroundReactions = 0; + ExternalReactions = 0; + Aircraft = 0; + Propagate = 0; + Auxiliary = 0; + + //in order for FGModel derived classes to self-bind (that is, call + //their bind function in the constructor, the PropertyManager pointer + //must be brought up now. + PropertyManager = FDMExec->GetPropertyManager(); + + exe_ctr = 1; + rate = 1; + + if (debug_lvl & 2) cout << " FGModel Base Class" << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGModel::~FGModel() { - for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i]; - interface_properties.clear(); - - for (unsigned int i=0; i<PreFunctions.size(); i++) delete PreFunctions[i]; - for (unsigned int i=0; i<PostFunctions.size(); i++) delete PostFunctions[i]; - - if (debug_lvl & 2) cout << "Destroyed: FGModel" << endl; + if (debug_lvl & 2) cout << "Destroyed: FGModel" << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGModel::InitModel(void) { - Atmosphere = FDMExec->GetAtmosphere(); - FCS = FDMExec->GetFCS(); - Propulsion = FDMExec->GetPropulsion(); - MassBalance = FDMExec->GetMassBalance(); - Aerodynamics = FDMExec->GetAerodynamics(); - Inertial = FDMExec->GetInertial(); - GroundReactions = FDMExec->GetGroundReactions(); - ExternalReactions = FDMExec->GetExternalReactions(); - BuoyantForces = FDMExec->GetBuoyantForces(); - Aircraft = FDMExec->GetAircraft(); - Propagate = FDMExec->GetPropagate(); - Auxiliary = FDMExec->GetAuxiliary(); - - if (!Atmosphere || - !FCS || - !Propulsion || - !MassBalance || - !Aerodynamics || - !Inertial || - !GroundReactions || - !ExternalReactions || - !Aircraft || - !Propagate || - !Auxiliary) return(false); - else return(true); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGModel::Load(Element* el) -{ - // Interface properties are all stored in the interface properties array. - string interface_property_string = ""; - - Element *property_element = el->FindElement("property"); - if (property_element && debug_lvl > 0) cout << endl << " Declared properties" - << endl << endl; - while (property_element) - { - interface_property_string = property_element->GetDataLine(); - if (PropertyManager->HasNode(interface_property_string)) - { - cerr << " Property " << interface_property_string - << " is already defined." << endl; - } - else - { - double value=0.0; - if ( ! property_element->GetAttributeValue("value").empty()) - value = property_element->GetAttributeValueAsNumber("value"); - interface_properties.push_back(new double(value)); - PropertyManager->Tie(interface_property_string, interface_properties.back()); - if (debug_lvl > 0) - cout << " " << interface_property_string << " (initial value: " - << value << ")" << endl << endl; - } - property_element = el->FindNextElement("property"); - } - - // End of interface property loading logic - - // Load model pre-functions, if any - - Element *function = el->FindElement("function"); - while (function) - { - if (function->GetAttributeValue("type") == "pre") - { - PreFunctions.push_back(new FGFunction(PropertyManager, function)); - } - else if (function->GetAttributeValue("type").empty()) // Assume pre-function - { - string funcname = function->GetAttributeValue("name"); - PreFunctions.push_back(new FGFunction(PropertyManager, function)); - } - function = el->FindNextElement("function"); - } - - return true; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGModel::PostLoad(Element* el) -{ - // Load model post-functions, if any - - Element *function = el->FindElement("function"); - while (function) - { - if (function->GetAttributeValue("type") == "post") - { - PostFunctions.push_back(new FGFunction(PropertyManager, function)); - } - function = el->FindNextElement("function"); - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// Tell the Functions to cache values, so when the function values -// are being used in the model, the functions do not get -// calculated each time, but instead use the values that have already -// been calculated for this frame. - -void FGModel::RunPreFunctions(void) -{ - vector <FGFunction*>::iterator it; - for (it = PreFunctions.begin(); it != PreFunctions.end(); it++) - (*it)->GetValue(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// Tell the Functions to cache values, so when the function values -// are being used in the model, the functions do not get -// calculated each time, but instead use the values that have already -// been calculated for this frame. - -void FGModel::RunPostFunctions(void) -{ - vector <FGFunction*>::iterator it; - for (it = PostFunctions.begin(); it != PostFunctions.end(); it++) - (*it)->GetValue(); + Atmosphere = FDMExec->GetAtmosphere(); + FCS = FDMExec->GetFCS(); + Propulsion = FDMExec->GetPropulsion(); + MassBalance = FDMExec->GetMassBalance(); + Aerodynamics = FDMExec->GetAerodynamics(); + Inertial = FDMExec->GetInertial(); + GroundReactions = FDMExec->GetGroundReactions(); + ExternalReactions = FDMExec->GetExternalReactions(); + BuoyantForces = FDMExec->GetBuoyantForces(); + Aircraft = FDMExec->GetAircraft(); + Propagate = FDMExec->GetPropagate(); + Auxiliary = FDMExec->GetAuxiliary(); + + if (!Atmosphere || + !FCS || + !Propulsion || + !MassBalance || + !Aerodynamics || + !Inertial || + !GroundReactions || + !ExternalReactions || + !Aircraft || + !Propagate || + !Auxiliary) return(false); + else return(true); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGModel::Run() { - if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl; + if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl; - if (rate == 1) return false; // Fast exit if nothing to do + if (rate == 1) return false; // Fast exit if nothing to do - if (exe_ctr >= rate) exe_ctr = 1; + if (exe_ctr >= rate) exe_ctr = 1; - if (exe_ctr++ == 1) return false; - else return true; + if (exe_ctr++ == 1) return false; + else return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -273,36 +168,28 @@ bool FGModel::Run() void FGModel::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGModel" << endl; - if (from == 1) cout << "Destroyed: FGModel" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGModel" << endl; + if (from == 1) cout << "Destroyed: FGModel" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/FGModel.h b/src/models/FGModel.h index 2f9b563f16ddfb1e5e1dad1a13b8dd2e4aeb1523..775ea9f299233f5a1a6dab7976ab3f44b3398c18 100644 --- a/src/models/FGModel.h +++ b/src/models/FGModel.h @@ -38,8 +38,8 @@ SENTRY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include "FGJSBBase.h" #include "math/FGFunction.h" +#include "math/FGModelFunctions.h" #include <string> #include <vector> @@ -48,17 +48,15 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_MODEL "$Id: FGModel.h,v 1.14 2009/11/12 13:08:11 jberndt Exp $" +#define ID_MODEL "$Id: FGModel.h,v 1.16 2010/09/22 11:33:40 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFDMExec; -class FGState; class FGAtmosphere; class FGFCS; class FGPropulsion; @@ -86,76 +84,53 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGModel : public FGJSBBase +class FGModel : public FGModelFunctions { public: - /// Constructor - FGModel(FGFDMExec*); - /// Destructor - ~FGModel(); - - FGModel* NextModel; - std::string Name; - - /** Runs the model; called by the Executive - @see JSBSim.cpp documentation - @return false if no error */ - virtual bool Run(void); - virtual bool InitModel(void); - virtual void SetRate(int tt) - { - rate = tt; - } - virtual int GetRate(void) - { - return rate; - } - FGFDMExec* GetExec(void) - { - return FDMExec; - } - - void SetPropertyManager(FGPropertyManager *fgpm) - { - PropertyManager=fgpm; - } + /// Constructor + FGModel(FGFDMExec*); + /// Destructor + ~FGModel(); + + std::string Name; + + /** Runs the model; called by the Executive + @see JSBSim.cpp documentation + @return false if no error */ + virtual bool Run(void); + virtual bool InitModel(void); + virtual void SetRate(int tt) {rate = tt;} + virtual int GetRate(void) {return rate;} + FGFDMExec* GetExec(void) {return FDMExec;} + + void SetPropertyManager(FGPropertyManager *fgpm) { PropertyManager=fgpm;} protected: - int exe_ctr; - int rate; - - void RunPreFunctions(void); - void RunPostFunctions(void); - - /** Loads this model. - @param el a pointer to the element - @return true if model is successfully loaded*/ - virtual bool Load(Element* el); - - void PostLoad(Element* el); - - virtual void Debug(int from); - - FGFDMExec* FDMExec; - FGState* State; - FGAtmosphere* Atmosphere; - FGFCS* FCS; - FGPropulsion* Propulsion; - FGMassBalance* MassBalance; - FGAerodynamics* Aerodynamics; - FGInertial* Inertial; - FGGroundReactions* GroundReactions; - FGExternalReactions* ExternalReactions; - FGBuoyantForces* BuoyantForces; - FGAircraft* Aircraft; - FGPropagate* Propagate; - FGAuxiliary* Auxiliary; - FGPropertyManager* PropertyManager; - std::vector <FGFunction*> PreFunctions; - std::vector <FGFunction*> PostFunctions; - - std::vector <double*> interface_properties; + int exe_ctr; + int rate; + + /** Loads this model. + @param el a pointer to the element + @return true if model is successfully loaded*/ + virtual bool Load(Element* el) {return FGModelFunctions::Load(el, PropertyManager);} + + virtual void Debug(int from); + + FGFDMExec* FDMExec; + FGAtmosphere* Atmosphere; + FGFCS* FCS; + FGPropulsion* Propulsion; + FGMassBalance* MassBalance; + FGAerodynamics* Aerodynamics; + FGInertial* Inertial; + FGGroundReactions* GroundReactions; + FGExternalReactions* ExternalReactions; + FGBuoyantForces* BuoyantForces; + FGAircraft* Aircraft; + FGPropagate* Propagate; + FGAuxiliary* Auxiliary; + FGPropertyManager* PropertyManager; }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/FGOutput.cpp b/src/models/FGOutput.cpp index b6a856af236ff7eabcc0688b4b9030f403ba71d6..a974915f4cfd72106cdd10f8810ae7dca7810d07 100644 --- a/src/models/FGOutput.cpp +++ b/src/models/FGOutput.cpp @@ -75,8 +75,7 @@ static const int endianTest = 1; using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGOutput.cpp,v 1.48 2010/04/12 12:25:19 jberndt Exp $"; static const char *IdHdr = ID_OUTPUT; @@ -93,8 +92,7 @@ static const char *IdHdr = ID_OUTPUT; // possible static void htond (double &x) { - if ( isLittleEndian ) - { + if ( isLittleEndian ) { int *Double_Overlay; int Holding_Buffer; @@ -103,9 +101,7 @@ static void htond (double &x) Double_Overlay [0] = htonl (Double_Overlay [1]); Double_Overlay [1] = htonl (Holding_Buffer); - } - else - { + } else { return; } } @@ -113,8 +109,7 @@ static void htond (double &x) // Float version static void htonf (float &x) { - if ( isLittleEndian ) - { + if ( isLittleEndian ) { int *Float_Overlay; int Holding_Buffer; @@ -122,9 +117,7 @@ static void htonf (float &x) Holding_Buffer = Float_Overlay [0]; Float_Overlay [0] = htonl (Holding_Buffer); - } - else - { + } else { return; } } @@ -136,420 +129,360 @@ CLASS IMPLEMENTATION FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex) { - Name = "FGOutput"; - sFirstPass = dFirstPass = true; - socket = 0; - flightGearSocket = 0; - runID_postfix = 0; - Type = otNone; - SubSystems = 0; - enabled = true; - StartNewFile = false; - delimeter = ", "; - BaseFilename = Filename = ""; - DirectivesFile = ""; - output_file_name = ""; - - memset(&fgSockBuf, 0x00, sizeof(fgSockBuf)); - - Debug(0); + Name = "FGOutput"; + sFirstPass = dFirstPass = true; + socket = 0; + flightGearSocket = 0; + runID_postfix = 0; + Type = otNone; + SubSystems = 0; + enabled = true; + StartNewFile = false; + delimeter = ", "; + BaseFilename = Filename = ""; + DirectivesFile = ""; + output_file_name = ""; + + memset(&fgSockBuf, 0x00, sizeof(fgSockBuf)); + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGOutput::~FGOutput() { - delete socket; - delete flightGearSocket; - OutputProperties.clear(); - Debug(1); + delete socket; + delete flightGearSocket; + OutputProperties.clear(); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGOutput::InitModel(void) { - if (!FGModel::InitModel()) return false; - - if (Filename.size() > 0 && StartNewFile) - { - ostringstream buf; - string::size_type dot = BaseFilename.find_last_of('.'); - if (dot != string::npos) - { - buf << BaseFilename.substr(0, dot) << '_' << runID_postfix++ << BaseFilename.substr(dot); - } - else - { - buf << BaseFilename << '_' << runID_postfix++; - } - Filename = buf.str(); - datafile.close(); - StartNewFile = false; - dFirstPass = true; - } + if (!FGModel::InitModel()) return false; + + if (Filename.size() > 0 && StartNewFile) { + ostringstream buf; + string::size_type dot = BaseFilename.find_last_of('.'); + if (dot != string::npos) { + buf << BaseFilename.substr(0, dot) << '_' << runID_postfix++ << BaseFilename.substr(dot); + } else { + buf << BaseFilename << '_' << runID_postfix++; + } + Filename = buf.str(); + datafile.close(); + StartNewFile = false; + dFirstPass = true; + } - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGOutput::Run(void) { - if (FGModel::Run()) return true; - - if (enabled && !FDMExec->IntegrationSuspended()&& !FDMExec->Holding()) - { - RunPreFunctions(); - if (Type == otSocket) - { - SocketOutput(); - } - else if (Type == otFlightGear) - { - FlightGearSocketOutput(); - } - else if (Type == otCSV || Type == otTab) - { - DelimitedOutput(Filename); - } - else if (Type == otTerminal) - { - // Not done yet - } - else if (Type == otNone) - { - // Do nothing - } - else - { - // Not a valid type of output - } - RunPostFunctions(); - } - return false; + if (FGModel::Run()) return true; + + if (enabled && !FDMExec->IntegrationSuspended()&& !FDMExec->Holding()) { + RunPreFunctions(); + if (Type == otSocket) { + SocketOutput(); + } else if (Type == otFlightGear) { + FlightGearSocketOutput(); + } else if (Type == otCSV || Type == otTab) { + DelimitedOutput(Filename); + } else if (Type == otTerminal) { + // Not done yet + } else if (Type == otNone) { + // Do nothing + } else { + // Not a valid type of output + } + RunPostFunctions(); + } + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGOutput::SetType(const string& type) { - if (type == "CSV") - { - Type = otCSV; - delimeter = ", "; - } - else if (type == "TABULAR") - { - Type = otTab; - delimeter = "\t"; - } - else if (type == "SOCKET") - { - Type = otSocket; - } - else if (type == "FLIGHTGEAR") - { - Type = otFlightGear; - } - else if (type == "TERMINAL") - { - Type = otTerminal; - } - else if (type != string("NONE")) - { - Type = otUnknown; - cerr << "Unknown type of output specified in config file" << endl; - } + if (type == "CSV") { + Type = otCSV; + delimeter = ", "; + } else if (type == "TABULAR") { + Type = otTab; + delimeter = "\t"; + } else if (type == "SOCKET") { + Type = otSocket; + } else if (type == "FLIGHTGEAR") { + Type = otFlightGear; + } else if (type == "TERMINAL") { + Type = otTerminal; + } else if (type != string("NONE")) { + Type = otUnknown; + cerr << "Unknown type of output specified in config file" << endl; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGOutput::DelimitedOutput(const string& fname) { - streambuf* buffer; - string scratch = ""; - - if (fname == "COUT" || fname == "cout") - { - buffer = cout.rdbuf(); - } - else - { - if (!datafile.is_open()) datafile.open(fname.c_str()); - buffer = datafile.rdbuf(); + streambuf* buffer; + string scratch = ""; + + if (fname == "COUT" || fname == "cout") { + buffer = cout.rdbuf(); + } else { + if (!datafile.is_open()) datafile.open(fname.c_str()); + buffer = datafile.rdbuf(); + } + + ostream outstream(buffer); + + outstream.precision(10); + + if (dFirstPass) { + outstream << "Time"; + if (SubSystems & ssSimulation) { + // Nothing here, yet + } + if (SubSystems & ssAerosurfaces) { + outstream << delimeter; + outstream << "Aileron Command (norm)" + delimeter; + outstream << "Elevator Command (norm)" + delimeter; + outstream << "Rudder Command (norm)" + delimeter; + outstream << "Flap Command (norm)" + delimeter; + outstream << "Left Aileron Position (deg)" + delimeter; + outstream << "Right Aileron Position (deg)" + delimeter; + outstream << "Elevator Position (deg)" + delimeter; + outstream << "Rudder Position (deg)" + delimeter; + outstream << "Flap Position (deg)"; + } + if (SubSystems & ssRates) { + outstream << delimeter; + outstream << "P (deg/s)" + delimeter + "Q (deg/s)" + delimeter + "R (deg/s)" + delimeter; + outstream << "P dot (deg/s^2)" + delimeter + "Q dot (deg/s^2)" + delimeter + "R dot (deg/s^2)" + delimeter; + outstream << "P_{inertial} (deg/s)" + delimeter + "Q_{inertial} (deg/s)" + delimeter + "R_{inertial} (deg/s)"; + } + if (SubSystems & ssVelocities) { + outstream << delimeter; + outstream << "q bar (psf)" + delimeter; + outstream << "Reynolds Number" + delimeter; + outstream << "V_{Total} (ft/s)" + delimeter; + outstream << "V_{Inertial} (ft/s)" + delimeter; + outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter; + outstream << "Aero V_{X Body} (ft/s)" + delimeter + "Aero V_{Y Body} (ft/s)" + delimeter + "Aero V_{Z Body} (ft/s)" + delimeter; + outstream << "V_{X_{inertial}} (ft/s)" + delimeter + "V_{Y_{inertial}} (ft/s)" + delimeter + "V_{Z_{inertial}} (ft/s)" + delimeter; + outstream << "V_{North} (ft/s)" + delimeter + "V_{East} (ft/s)" + delimeter + "V_{Down} (ft/s)"; + } + if (SubSystems & ssForces) { + outstream << delimeter; + outstream << "F_{Drag} (lbs)" + delimeter + "F_{Side} (lbs)" + delimeter + "F_{Lift} (lbs)" + delimeter; + outstream << "L/D" + delimeter; + outstream << "F_{Aero x} (lbs)" + delimeter + "F_{Aero y} (lbs)" + delimeter + "F_{Aero z} (lbs)" + delimeter; + outstream << "F_{Prop x} (lbs)" + delimeter + "F_{Prop y} (lbs)" + delimeter + "F_{Prop z} (lbs)" + delimeter; + outstream << "F_{Gear x} (lbs)" + delimeter + "F_{Gear y} (lbs)" + delimeter + "F_{Gear z} (lbs)" + delimeter; + outstream << "F_{Ext x} (lbs)" + delimeter + "F_{Ext y} (lbs)" + delimeter + "F_{Ext z} (lbs)" + delimeter; + outstream << "F_{Buoyant x} (lbs)" + delimeter + "F_{Buoyant y} (lbs)" + delimeter + "F_{Buoyant z} (lbs)" + delimeter; + outstream << "F_{Total x} (lbs)" + delimeter + "F_{Total y} (lbs)" + delimeter + "F_{Total z} (lbs)"; + } + if (SubSystems & ssMoments) { + outstream << delimeter; + outstream << "L_{Aero} (ft-lbs)" + delimeter + "M_{Aero} ( ft-lbs)" + delimeter + "N_{Aero} (ft-lbs)" + delimeter; + outstream << "L_{Prop} (ft-lbs)" + delimeter + "M_{Prop} (ft-lbs)" + delimeter + "N_{Prop} (ft-lbs)" + delimeter; + outstream << "L_{Gear} (ft-lbs)" + delimeter + "M_{Gear} (ft-lbs)" + delimeter + "N_{Gear} (ft-lbs)" + delimeter; + outstream << "L_{ext} (ft-lbs)" + delimeter + "M_{ext} (ft-lbs)" + delimeter + "N_{ext} (ft-lbs)" + delimeter; + outstream << "L_{Buoyant} (ft-lbs)" + delimeter + "M_{Buoyant} (ft-lbs)" + delimeter + "N_{Buoyant} (ft-lbs)" + delimeter; + outstream << "L_{Total} (ft-lbs)" + delimeter + "M_{Total} (ft-lbs)" + delimeter + "N_{Total} (ft-lbs)"; + } + if (SubSystems & ssAtmosphere) { + outstream << delimeter; + outstream << "Rho (slugs/ft^3)" + delimeter; + outstream << "Absolute Viscosity" + delimeter; + outstream << "Kinematic Viscosity" + delimeter; + outstream << "Temperature (R)" + delimeter; + outstream << "P_{SL} (psf)" + delimeter; + outstream << "P_{Ambient} (psf)" + delimeter; + outstream << "Turbulence Magnitude (ft/sec)" + delimeter; + outstream << "Turbulence X Direction (rad)" + delimeter + "Turbulence Y Direction (rad)" + delimeter + "Turbulence Z Direction (rad)" + delimeter; + outstream << "Wind V_{North} (ft/s)" + delimeter + "Wind V_{East} (ft/s)" + delimeter + "Wind V_{Down} (ft/s)"; + } + if (SubSystems & ssMassProps) { + outstream << delimeter; + outstream << "I_{xx}" + delimeter; + outstream << "I_{xy}" + delimeter; + outstream << "I_{xz}" + delimeter; + outstream << "I_{yx}" + delimeter; + outstream << "I_{yy}" + delimeter; + outstream << "I_{yz}" + delimeter; + outstream << "I_{zx}" + delimeter; + outstream << "I_{zy}" + delimeter; + outstream << "I_{zz}" + delimeter; + outstream << "Mass" + delimeter; + outstream << "X_{cg}" + delimeter + "Y_{cg}" + delimeter + "Z_{cg}"; + } + if (SubSystems & ssPropagate) { + outstream << delimeter; + outstream << "Altitude ASL (ft)" + delimeter; + outstream << "Altitude AGL (ft)" + delimeter; + outstream << "Phi (deg)" + delimeter + "Theta (deg)" + delimeter + "Psi (deg)" + delimeter; + outstream << "Alpha (deg)" + delimeter; + outstream << "Beta (deg)" + delimeter; + outstream << "Latitude (deg)" + delimeter; + outstream << "Longitude (deg)" + delimeter; + outstream << "X_{ECI} (ft)" + delimeter + "Y_{ECI} (ft)" + delimeter + "Z_{ECI} (ft)" + delimeter; + outstream << "X_{ECEF} (ft)" + delimeter + "Y_{ECEF} (ft)" + delimeter + "Z_{ECEF} (ft)" + delimeter; + outstream << "Earth Position Angle (deg)" + delimeter; + outstream << "Distance AGL (ft)" + delimeter; + outstream << "Terrain Elevation (ft)"; + } + if (SubSystems & ssCoefficients) { + scratch = Aerodynamics->GetCoefficientStrings(delimeter); + if (scratch.length() != 0) outstream << delimeter << scratch; + } + if (SubSystems & ssFCS) { + scratch = FCS->GetComponentStrings(delimeter); + if (scratch.length() != 0) outstream << delimeter << scratch; + } + if (SubSystems & ssGroundReactions) { + outstream << delimeter; + outstream << GroundReactions->GetGroundReactionStrings(delimeter); + } + if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) { + outstream << delimeter; + outstream << Propulsion->GetPropulsionStrings(delimeter); + } + if (OutputProperties.size() > 0) { + for (unsigned int i=0;i<OutputProperties.size();i++) { + outstream << delimeter << OutputProperties[i]->GetPrintableName(); + } } - ostream outstream(buffer); - + outstream << endl; + dFirstPass = false; + } + + outstream << FDMExec->GetSimTime(); + if (SubSystems & ssSimulation) { + } + if (SubSystems & ssAerosurfaces) { + outstream << delimeter; + outstream << FCS->GetDaCmd() << delimeter; + outstream << FCS->GetDeCmd() << delimeter; + outstream << FCS->GetDrCmd() << delimeter; + outstream << FCS->GetDfCmd() << delimeter; + outstream << FCS->GetDaLPos(ofDeg) << delimeter; + outstream << FCS->GetDaRPos(ofDeg) << delimeter; + outstream << FCS->GetDePos(ofDeg) << delimeter; + outstream << FCS->GetDrPos(ofDeg) << delimeter; + outstream << FCS->GetDfPos(ofDeg); + } + if (SubSystems & ssRates) { + outstream << delimeter; + outstream << (radtodeg*Propagate->GetPQR()).Dump(delimeter) << delimeter; + outstream << (radtodeg*Propagate->GetPQRdot()).Dump(delimeter) << delimeter; + outstream << (radtodeg*Propagate->GetPQRi()).Dump(delimeter); + } + if (SubSystems & ssVelocities) { + outstream << delimeter; + outstream << Auxiliary->Getqbar() << delimeter; + outstream << Auxiliary->GetReynoldsNumber() << delimeter; + outstream << setprecision(12) << Auxiliary->GetVt() << delimeter; + outstream << Propagate->GetInertialVelocityMagnitude() << delimeter; + outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter; + outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter; + outstream << Propagate->GetInertialVelocity().Dump(delimeter) << delimeter; + outstream << Propagate->GetVel().Dump(delimeter); outstream.precision(10); - - if (dFirstPass) - { - outstream << "Time"; - if (SubSystems & ssSimulation) - { - // Nothing here, yet - } - if (SubSystems & ssAerosurfaces) - { - outstream << delimeter; - outstream << "Aileron Command (norm)" + delimeter; - outstream << "Elevator Command (norm)" + delimeter; - outstream << "Rudder Command (norm)" + delimeter; - outstream << "Flap Command (norm)" + delimeter; - outstream << "Left Aileron Position (deg)" + delimeter; - outstream << "Right Aileron Position (deg)" + delimeter; - outstream << "Elevator Position (deg)" + delimeter; - outstream << "Rudder Position (deg)" + delimeter; - outstream << "Flap Position (deg)"; - } - if (SubSystems & ssRates) - { - outstream << delimeter; - outstream << "P (deg/s)" + delimeter + "Q (deg/s)" + delimeter + "R (deg/s)" + delimeter; - outstream << "P dot (deg/s^2)" + delimeter + "Q dot (deg/s^2)" + delimeter + "R dot (deg/s^2)" + delimeter; - outstream << "P_{inertial} (deg/s)" + delimeter + "Q_{inertial} (deg/s)" + delimeter + "R_{inertial} (deg/s)"; - } - if (SubSystems & ssVelocities) - { - outstream << delimeter; - outstream << "q bar (psf)" + delimeter; - outstream << "Reynolds Number" + delimeter; - outstream << "V_{Total} (ft/s)" + delimeter; - outstream << "V_{Inertial} (ft/s)" + delimeter; - outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter; - outstream << "Aero V_{X Body} (ft/s)" + delimeter + "Aero V_{Y Body} (ft/s)" + delimeter + "Aero V_{Z Body} (ft/s)" + delimeter; - outstream << "V_{X_{inertial}} (ft/s)" + delimeter + "V_{Y_{inertial}} (ft/s)" + delimeter + "V_{Z_{inertial}} (ft/s)" + delimeter; - outstream << "V_{North} (ft/s)" + delimeter + "V_{East} (ft/s)" + delimeter + "V_{Down} (ft/s)"; - } - if (SubSystems & ssForces) - { - outstream << delimeter; - outstream << "F_{Drag} (lbs)" + delimeter + "F_{Side} (lbs)" + delimeter + "F_{Lift} (lbs)" + delimeter; - outstream << "L/D" + delimeter; - outstream << "F_{Aero x} (lbs)" + delimeter + "F_{Aero y} (lbs)" + delimeter + "F_{Aero z} (lbs)" + delimeter; - outstream << "F_{Prop x} (lbs)" + delimeter + "F_{Prop y} (lbs)" + delimeter + "F_{Prop z} (lbs)" + delimeter; - outstream << "F_{Gear x} (lbs)" + delimeter + "F_{Gear y} (lbs)" + delimeter + "F_{Gear z} (lbs)" + delimeter; - outstream << "F_{Ext x} (lbs)" + delimeter + "F_{Ext y} (lbs)" + delimeter + "F_{Ext z} (lbs)" + delimeter; - outstream << "F_{Buoyant x} (lbs)" + delimeter + "F_{Buoyant y} (lbs)" + delimeter + "F_{Buoyant z} (lbs)" + delimeter; - outstream << "F_{Total x} (lbs)" + delimeter + "F_{Total y} (lbs)" + delimeter + "F_{Total z} (lbs)"; - } - if (SubSystems & ssMoments) - { - outstream << delimeter; - outstream << "L_{Aero} (ft-lbs)" + delimeter + "M_{Aero} ( ft-lbs)" + delimeter + "N_{Aero} (ft-lbs)" + delimeter; - outstream << "L_{Prop} (ft-lbs)" + delimeter + "M_{Prop} (ft-lbs)" + delimeter + "N_{Prop} (ft-lbs)" + delimeter; - outstream << "L_{Gear} (ft-lbs)" + delimeter + "M_{Gear} (ft-lbs)" + delimeter + "N_{Gear} (ft-lbs)" + delimeter; - outstream << "L_{ext} (ft-lbs)" + delimeter + "M_{ext} (ft-lbs)" + delimeter + "N_{ext} (ft-lbs)" + delimeter; - outstream << "L_{Buoyant} (ft-lbs)" + delimeter + "M_{Buoyant} (ft-lbs)" + delimeter + "N_{Buoyant} (ft-lbs)" + delimeter; - outstream << "L_{Total} (ft-lbs)" + delimeter + "M_{Total} (ft-lbs)" + delimeter + "N_{Total} (ft-lbs)"; - } - if (SubSystems & ssAtmosphere) - { - outstream << delimeter; - outstream << "Rho (slugs/ft^3)" + delimeter; - outstream << "Absolute Viscosity" + delimeter; - outstream << "Kinematic Viscosity" + delimeter; - outstream << "Temperature (R)" + delimeter; - outstream << "P_{SL} (psf)" + delimeter; - outstream << "P_{Ambient} (psf)" + delimeter; - outstream << "Turbulence Magnitude (ft/sec)" + delimeter; - outstream << "Turbulence X Direction (rad)" + delimeter + "Turbulence Y Direction (rad)" + delimeter + "Turbulence Z Direction (rad)" + delimeter; - outstream << "Wind V_{North} (ft/s)" + delimeter + "Wind V_{East} (ft/s)" + delimeter + "Wind V_{Down} (ft/s)"; - } - if (SubSystems & ssMassProps) - { - outstream << delimeter; - outstream << "I_{xx}" + delimeter; - outstream << "I_{xy}" + delimeter; - outstream << "I_{xz}" + delimeter; - outstream << "I_{yx}" + delimeter; - outstream << "I_{yy}" + delimeter; - outstream << "I_{yz}" + delimeter; - outstream << "I_{zx}" + delimeter; - outstream << "I_{zy}" + delimeter; - outstream << "I_{zz}" + delimeter; - outstream << "Mass" + delimeter; - outstream << "X_{cg}" + delimeter + "Y_{cg}" + delimeter + "Z_{cg}"; - } - if (SubSystems & ssPropagate) - { - outstream << delimeter; - outstream << "Altitude ASL (ft)" + delimeter; - outstream << "Altitude AGL (ft)" + delimeter; - outstream << "Phi (deg)" + delimeter + "Theta (deg)" + delimeter + "Psi (deg)" + delimeter; - outstream << "Alpha (deg)" + delimeter; - outstream << "Beta (deg)" + delimeter; - outstream << "Latitude (deg)" + delimeter; - outstream << "Longitude (deg)" + delimeter; - outstream << "X_{ECI} (ft)" + delimeter + "Y_{ECI} (ft)" + delimeter + "Z_{ECI} (ft)" + delimeter; - outstream << "X_{ECEF} (ft)" + delimeter + "Y_{ECEF} (ft)" + delimeter + "Z_{ECEF} (ft)" + delimeter; - outstream << "Earth Position Angle (deg)" + delimeter; - outstream << "Distance AGL (ft)" + delimeter; - outstream << "Terrain Elevation (ft)"; - } - if (SubSystems & ssCoefficients) - { - scratch = Aerodynamics->GetCoefficientStrings(delimeter); - if (scratch.length() != 0) outstream << delimeter << scratch; - } - if (SubSystems & ssFCS) - { - scratch = FCS->GetComponentStrings(delimeter); - if (scratch.length() != 0) outstream << delimeter << scratch; - } - if (SubSystems & ssGroundReactions) - { - outstream << delimeter; - outstream << GroundReactions->GetGroundReactionStrings(delimeter); - } - if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) - { - outstream << delimeter; - outstream << Propulsion->GetPropulsionStrings(delimeter); - } - if (OutputProperties.size() > 0) - { - for (unsigned int i=0;i<OutputProperties.size();i++) - { - outstream << delimeter << OutputProperties[i]->GetPrintableName(); - } - } - - outstream << endl; - dFirstPass = false; - } - - outstream << FDMExec->GetSimTime(); - if (SubSystems & ssSimulation) - { - } - if (SubSystems & ssAerosurfaces) - { - outstream << delimeter; - outstream << FCS->GetDaCmd() << delimeter; - outstream << FCS->GetDeCmd() << delimeter; - outstream << FCS->GetDrCmd() << delimeter; - outstream << FCS->GetDfCmd() << delimeter; - outstream << FCS->GetDaLPos(ofDeg) << delimeter; - outstream << FCS->GetDaRPos(ofDeg) << delimeter; - outstream << FCS->GetDePos(ofDeg) << delimeter; - outstream << FCS->GetDrPos(ofDeg) << delimeter; - outstream << FCS->GetDfPos(ofDeg); - } - if (SubSystems & ssRates) - { - outstream << delimeter; - outstream << (radtodeg*Propagate->GetPQR()).Dump(delimeter) << delimeter; - outstream << (radtodeg*Propagate->GetPQRdot()).Dump(delimeter) << delimeter; - outstream << (radtodeg*Propagate->GetPQRi()).Dump(delimeter); - } - if (SubSystems & ssVelocities) - { - outstream << delimeter; - outstream << Auxiliary->Getqbar() << delimeter; - outstream << Auxiliary->GetReynoldsNumber() << delimeter; - outstream << setprecision(12) << Auxiliary->GetVt() << delimeter; - outstream << Propagate->GetInertialVelocityMagnitude() << delimeter; - outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter; - outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter; - outstream << Propagate->GetInertialVelocity().Dump(delimeter) << delimeter; - outstream << Propagate->GetVel().Dump(delimeter); - outstream.precision(10); - } - if (SubSystems & ssForces) - { - outstream << delimeter; - outstream << Aerodynamics->GetvFw().Dump(delimeter) << delimeter; - outstream << Aerodynamics->GetLoD() << delimeter; - outstream << Aerodynamics->GetForces().Dump(delimeter) << delimeter; - outstream << Propulsion->GetForces().Dump(delimeter) << delimeter; - outstream << GroundReactions->GetForces().Dump(delimeter) << delimeter; - outstream << ExternalReactions->GetForces().Dump(delimeter) << delimeter; - outstream << BuoyantForces->GetForces().Dump(delimeter) << delimeter; - outstream << Aircraft->GetForces().Dump(delimeter); - } - if (SubSystems & ssMoments) - { - outstream << delimeter; - outstream << Aerodynamics->GetMoments().Dump(delimeter) << delimeter; - outstream << Propulsion->GetMoments().Dump(delimeter) << delimeter; - outstream << GroundReactions->GetMoments().Dump(delimeter) << delimeter; - outstream << ExternalReactions->GetMoments().Dump(delimeter) << delimeter; - outstream << BuoyantForces->GetMoments().Dump(delimeter) << delimeter; - outstream << Aircraft->GetMoments().Dump(delimeter); - } - if (SubSystems & ssAtmosphere) - { - outstream << delimeter; - outstream << Atmosphere->GetDensity() << delimeter; - outstream << Atmosphere->GetAbsoluteViscosity() << delimeter; - outstream << Atmosphere->GetKinematicViscosity() << delimeter; - outstream << Atmosphere->GetTemperature() << delimeter; - outstream << Atmosphere->GetPressureSL() << delimeter; - outstream << Atmosphere->GetPressure() << delimeter; - outstream << Atmosphere->GetTurbMagnitude() << delimeter; - outstream << Atmosphere->GetTurbDirection().Dump(delimeter) << delimeter; - outstream << Atmosphere->GetTotalWindNED().Dump(delimeter); - } - if (SubSystems & ssMassProps) - { - outstream << delimeter; - outstream << MassBalance->GetJ().Dump(delimeter) << delimeter; - outstream << MassBalance->GetMass() << delimeter; - outstream << MassBalance->GetXYZcg().Dump(delimeter); - } - if (SubSystems & ssPropagate) - { - outstream.precision(14); - outstream << delimeter; - outstream << Propagate->GetAltitudeASL() << delimeter; - outstream << Propagate->GetDistanceAGL() << delimeter; - outstream << (radtodeg*Propagate->GetEuler()).Dump(delimeter) << delimeter; - outstream << Auxiliary->Getalpha(inDegrees) << delimeter; - outstream << Auxiliary->Getbeta(inDegrees) << delimeter; - outstream << Propagate->GetLocation().GetLatitudeDeg() << delimeter; - outstream << Propagate->GetLocation().GetLongitudeDeg() << delimeter; - outstream.precision(18); - outstream << ((FGColumnVector3)Propagate->GetInertialPosition()).Dump(delimeter) << delimeter; - outstream << ((FGColumnVector3)Propagate->GetLocation()).Dump(delimeter) << delimeter; - outstream.precision(14); - outstream << Inertial->GetEarthPositionAngleDeg() << delimeter; - outstream << Propagate->GetDistanceAGL() << delimeter; - outstream << Propagate->GetTerrainElevation(); - outstream.precision(10); - } - if (SubSystems & ssCoefficients) - { - scratch = Aerodynamics->GetCoefficientValues(delimeter); - if (scratch.length() != 0) outstream << delimeter << scratch; - } - if (SubSystems & ssFCS) - { - scratch = FCS->GetComponentValues(delimeter); - if (scratch.length() != 0) outstream << delimeter << scratch; - } - if (SubSystems & ssGroundReactions) - { - outstream << delimeter; - outstream << GroundReactions->GetGroundReactionValues(delimeter); - } - if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) - { - outstream << delimeter; - outstream << Propulsion->GetPropulsionValues(delimeter); - } - + } + if (SubSystems & ssForces) { + outstream << delimeter; + outstream << Aerodynamics->GetvFw().Dump(delimeter) << delimeter; + outstream << Aerodynamics->GetLoD() << delimeter; + outstream << Aerodynamics->GetForces().Dump(delimeter) << delimeter; + outstream << Propulsion->GetForces().Dump(delimeter) << delimeter; + outstream << GroundReactions->GetForces().Dump(delimeter) << delimeter; + outstream << ExternalReactions->GetForces().Dump(delimeter) << delimeter; + outstream << BuoyantForces->GetForces().Dump(delimeter) << delimeter; + outstream << Aircraft->GetForces().Dump(delimeter); + } + if (SubSystems & ssMoments) { + outstream << delimeter; + outstream << Aerodynamics->GetMoments().Dump(delimeter) << delimeter; + outstream << Propulsion->GetMoments().Dump(delimeter) << delimeter; + outstream << GroundReactions->GetMoments().Dump(delimeter) << delimeter; + outstream << ExternalReactions->GetMoments().Dump(delimeter) << delimeter; + outstream << BuoyantForces->GetMoments().Dump(delimeter) << delimeter; + outstream << Aircraft->GetMoments().Dump(delimeter); + } + if (SubSystems & ssAtmosphere) { + outstream << delimeter; + outstream << Atmosphere->GetDensity() << delimeter; + outstream << Atmosphere->GetAbsoluteViscosity() << delimeter; + outstream << Atmosphere->GetKinematicViscosity() << delimeter; + outstream << Atmosphere->GetTemperature() << delimeter; + outstream << Atmosphere->GetPressureSL() << delimeter; + outstream << Atmosphere->GetPressure() << delimeter; + outstream << Atmosphere->GetTurbMagnitude() << delimeter; + outstream << Atmosphere->GetTurbDirection().Dump(delimeter) << delimeter; + outstream << Atmosphere->GetTotalWindNED().Dump(delimeter); + } + if (SubSystems & ssMassProps) { + outstream << delimeter; + outstream << MassBalance->GetJ().Dump(delimeter) << delimeter; + outstream << MassBalance->GetMass() << delimeter; + outstream << MassBalance->GetXYZcg().Dump(delimeter); + } + if (SubSystems & ssPropagate) { + outstream.precision(14); + outstream << delimeter; + outstream << Propagate->GetAltitudeASL() << delimeter; + outstream << Propagate->GetDistanceAGL() << delimeter; + outstream << (radtodeg*Propagate->GetEuler()).Dump(delimeter) << delimeter; + outstream << Auxiliary->Getalpha(inDegrees) << delimeter; + outstream << Auxiliary->Getbeta(inDegrees) << delimeter; + outstream << Propagate->GetLocation().GetLatitudeDeg() << delimeter; + outstream << Propagate->GetLocation().GetLongitudeDeg() << delimeter; outstream.precision(18); - for (unsigned int i=0;i<OutputProperties.size();i++) - { - outstream << delimeter << OutputProperties[i]->getDoubleValue(); - } + outstream << ((FGColumnVector3)Propagate->GetInertialPosition()).Dump(delimeter) << delimeter; + outstream << ((FGColumnVector3)Propagate->GetLocation()).Dump(delimeter) << delimeter; + outstream.precision(14); + outstream << Inertial->GetEarthPositionAngleDeg() << delimeter; + outstream << Propagate->GetDistanceAGL() << delimeter; + outstream << Propagate->GetTerrainElevation(); outstream.precision(10); - - outstream << endl; - outstream.flush(); + } + if (SubSystems & ssCoefficients) { + scratch = Aerodynamics->GetCoefficientValues(delimeter); + if (scratch.length() != 0) outstream << delimeter << scratch; + } + if (SubSystems & ssFCS) { + scratch = FCS->GetComponentValues(delimeter); + if (scratch.length() != 0) outstream << delimeter << scratch; + } + if (SubSystems & ssGroundReactions) { + outstream << delimeter; + outstream << GroundReactions->GetGroundReactionValues(delimeter); + } + if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) { + outstream << delimeter; + outstream << Propulsion->GetPropulsionValues(delimeter); + } + + outstream.precision(18); + for (unsigned int i=0;i<OutputProperties.size();i++) { + outstream << delimeter << OutputProperties[i]->getDoubleValue(); + } + outstream.precision(10); + + outstream << endl; + outstream.flush(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -600,63 +533,59 @@ void FGOutput::SocketDataFill(FGNetFDM* net) // Engine status net->num_engines = Propulsion->GetNumEngines(); // Number of valid engines - for (i=0; i<net->num_engines; i++) - { - if (Propulsion->GetEngine(i)->GetRunning()) - net->eng_state[i] = 2; // Engine state running - else if (Propulsion->GetEngine(i)->GetCranking()) - net->eng_state[i] = 1; // Engine state cranking - else - net->eng_state[i] = 0; // Engine state off - - switch (Propulsion->GetEngine(i)->GetType()) - { - case (FGEngine::etRocket): - break; - case (FGEngine::etPiston): - net->rpm[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getRPM()); - net->fuel_flow[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getFuelFlow_gph()); - net->fuel_px[i] = 0; // Fuel pressure, psi (N/A in current model) - net->egt[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->GetEGT()); - net->cht[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getCylinderHeadTemp_degF()); - net->mp_osi[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getManifoldPressure_inHg()); - net->oil_temp[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getOilTemp_degF()); - net->oil_px[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getOilPressure_psi()); - net->tit[i] = 0; // Turbine Inlet Temperature (N/A for piston) - break; - case (FGEngine::etTurbine): - break; - case (FGEngine::etTurboprop): - break; - case (FGEngine::etElectric): - break; - case (FGEngine::etUnknown): - break; - } + for (i=0; i<net->num_engines; i++) { + if (Propulsion->GetEngine(i)->GetRunning()) + net->eng_state[i] = 2; // Engine state running + else if (Propulsion->GetEngine(i)->GetCranking()) + net->eng_state[i] = 1; // Engine state cranking + else + net->eng_state[i] = 0; // Engine state off + + switch (Propulsion->GetEngine(i)->GetType()) { + case (FGEngine::etRocket): + break; + case (FGEngine::etPiston): + net->rpm[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getRPM()); + net->fuel_flow[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getFuelFlow_gph()); + net->fuel_px[i] = 0; // Fuel pressure, psi (N/A in current model) + net->egt[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->GetEGT()); + net->cht[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getCylinderHeadTemp_degF()); + net->mp_osi[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getManifoldPressure_inHg()); + net->oil_temp[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getOilTemp_degF()); + net->oil_px[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getOilPressure_psi()); + net->tit[i] = 0; // Turbine Inlet Temperature (N/A for piston) + break; + case (FGEngine::etTurbine): + break; + case (FGEngine::etTurboprop): + break; + case (FGEngine::etElectric): + break; + case (FGEngine::etUnknown): + break; + } } // Consumables net->num_tanks = Propulsion->GetNumTanks(); // Max number of fuel tanks - for (i=0; i<net->num_tanks; i++) - { - net->fuel_quantity[i] = (float)(((FGTank *)Propulsion->GetTank(i))->GetContents()); + for (i=0; i<net->num_tanks; i++) { + net->fuel_quantity[i] = (float)(((FGTank *)Propulsion->GetTank(i))->GetContents()); } // Gear status net->num_wheels = GroundReactions->GetNumGearUnits(); - for (i=0; i<net->num_wheels; i++) - { - net->wow[i] = GroundReactions->GetGearUnit(i)->GetWOW(); - if (GroundReactions->GetGearUnit(i)->GetGearUnitDown()) - net->gear_pos[i] = 1; //gear down, using FCS convention - else - net->gear_pos[i] = 0; //gear up, using FCS convention - net->gear_steer[i] = (float)(GroundReactions->GetGearUnit(i)->GetSteerNorm()); - net->gear_compression[i] = (float)(GroundReactions->GetGearUnit(i)->GetCompLen()); + for (i=0; i<net->num_wheels; i++) { + net->wow[i] = GroundReactions->GetGearUnit(i)->GetWOW(); + if (GroundReactions->GetGearUnit(i)->GetGearUnitDown()) + net->gear_pos[i] = 1; //gear down, using FCS convention + else + net->gear_pos[i] = 0; //gear up, using FCS convention + net->gear_steer[i] = (float)(GroundReactions->GetGearUnit(i)->GetSteerNorm()); + net->gear_compression[i] = (float)(GroundReactions->GetGearUnit(i)->GetCompLen()); } @@ -680,8 +609,7 @@ void FGOutput::SocketDataFill(FGNetFDM* net) // Convert the net buffer to network format - if ( isLittleEndian ) - { + if ( isLittleEndian ) { net->version = htonl(net->version); htond(net->longitude); @@ -713,8 +641,7 @@ void FGOutput::SocketDataFill(FGNetFDM* net) htonf(net->stall_warning); htonf(net->slip_deg); - for (i=0; i<net->num_engines; ++i ) - { + for (i=0; i<net->num_engines; ++i ) { net->eng_state[i] = htonl(net->eng_state[i]); htonf(net->rpm[i]); htonf(net->fuel_flow[i]); @@ -728,14 +655,12 @@ void FGOutput::SocketDataFill(FGNetFDM* net) } net->num_engines = htonl(net->num_engines); - for (i=0; i<net->num_tanks; ++i ) - { + for (i=0; i<net->num_tanks; ++i ) { htonf(net->fuel_quantity[i]); } net->num_tanks = htonl(net->num_tanks); - for (i=0; i<net->num_wheels; ++i ) - { + for (i=0; i<net->num_wheels; ++i ) { net->wow[i] = htonl(net->wow[i]); htonf(net->gear_pos[i]); htonf(net->gear_steer[i]); @@ -764,414 +689,366 @@ void FGOutput::SocketDataFill(FGNetFDM* net) void FGOutput::FlightGearSocketOutput(void) { - int length = sizeof(fgSockBuf); + int length = sizeof(fgSockBuf); - if (flightGearSocket == NULL) return; - if (!flightGearSocket->GetConnectStatus()) return; + if (flightGearSocket == NULL) return; + if (!flightGearSocket->GetConnectStatus()) return; - SocketDataFill(&fgSockBuf); - flightGearSocket->Send((char *)&fgSockBuf, length); + SocketDataFill(&fgSockBuf); + flightGearSocket->Send((char *)&fgSockBuf, length); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGOutput::SocketOutput(void) { - string asciiData, scratch; - - if (socket == NULL) return; - if (!socket->GetConnectStatus()) return; - - socket->Clear(); - if (sFirstPass) - { - socket->Clear("<LABELS>"); - socket->Append("Time"); - - if (SubSystems & ssAerosurfaces) - { - socket->Append("Aileron Command"); - socket->Append("Elevator Command"); - socket->Append("Rudder Command"); - socket->Append("Flap Command"); - socket->Append("Left Aileron Position"); - socket->Append("Right Aileron Position"); - socket->Append("Elevator Position"); - socket->Append("Rudder Position"); - socket->Append("Flap Position"); - } - - if (SubSystems & ssRates) - { - socket->Append("P"); - socket->Append("Q"); - socket->Append("R"); - socket->Append("PDot"); - socket->Append("QDot"); - socket->Append("RDot"); - } - - if (SubSystems & ssVelocities) - { - socket->Append("QBar"); - socket->Append("Vtotal"); - socket->Append("UBody"); - socket->Append("VBody"); - socket->Append("WBody"); - socket->Append("UAero"); - socket->Append("VAero"); - socket->Append("WAero"); - socket->Append("Vn"); - socket->Append("Ve"); - socket->Append("Vd"); - } - if (SubSystems & ssForces) - { - socket->Append("F_Drag"); - socket->Append("F_Side"); - socket->Append("F_Lift"); - socket->Append("LoD"); - socket->Append("Fx"); - socket->Append("Fy"); - socket->Append("Fz"); - } - if (SubSystems & ssMoments) - { - socket->Append("L"); - socket->Append("M"); - socket->Append("N"); - } - if (SubSystems & ssAtmosphere) - { - socket->Append("Rho"); - socket->Append("SL pressure"); - socket->Append("Ambient pressure"); - socket->Append("Turbulence Magnitude"); - socket->Append("Turbulence Direction X"); - socket->Append("Turbulence Direction Y"); - socket->Append("Turbulence Direction Z"); - socket->Append("NWind"); - socket->Append("EWind"); - socket->Append("DWind"); - } - if (SubSystems & ssMassProps) - { - socket->Append("Ixx"); - socket->Append("Ixy"); - socket->Append("Ixz"); - socket->Append("Iyx"); - socket->Append("Iyy"); - socket->Append("Iyz"); - socket->Append("Izx"); - socket->Append("Izy"); - socket->Append("Izz"); - socket->Append("Mass"); - socket->Append("Xcg"); - socket->Append("Ycg"); - socket->Append("Zcg"); - } - if (SubSystems & ssPropagate) - { - socket->Append("Altitude"); - socket->Append("Phi (deg)"); - socket->Append("Tht (deg)"); - socket->Append("Psi (deg)"); - socket->Append("Alpha (deg)"); - socket->Append("Beta (deg)"); - socket->Append("Latitude (deg)"); - socket->Append("Longitude (deg)"); - } - if (SubSystems & ssCoefficients) - { - scratch = Aerodynamics->GetCoefficientStrings(","); - if (scratch.length() != 0) socket->Append(scratch); - } - if (SubSystems & ssFCS) - { - scratch = FCS->GetComponentStrings(","); - if (scratch.length() != 0) socket->Append(scratch); - } - if (SubSystems & ssGroundReactions) - { - socket->Append(GroundReactions->GetGroundReactionStrings(",")); - } - if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) - { - socket->Append(Propulsion->GetPropulsionStrings(",")); - } - if (OutputProperties.size() > 0) - { - for (unsigned int i=0;i<OutputProperties.size();i++) - { - socket->Append(OutputProperties[i]->GetPrintableName()); - } - } - - sFirstPass = false; - socket->Send(); - } - - socket->Clear(); - socket->Append(FDMExec->GetSimTime()); - - if (SubSystems & ssAerosurfaces) - { - socket->Append(FCS->GetDaCmd()); - socket->Append(FCS->GetDeCmd()); - socket->Append(FCS->GetDrCmd()); - socket->Append(FCS->GetDfCmd()); - socket->Append(FCS->GetDaLPos()); - socket->Append(FCS->GetDaRPos()); - socket->Append(FCS->GetDePos()); - socket->Append(FCS->GetDrPos()); - socket->Append(FCS->GetDfPos()); - } - if (SubSystems & ssRates) - { - socket->Append(radtodeg*Propagate->GetPQR(eP)); - socket->Append(radtodeg*Propagate->GetPQR(eQ)); - socket->Append(radtodeg*Propagate->GetPQR(eR)); - socket->Append(radtodeg*Propagate->GetPQRdot(eP)); - socket->Append(radtodeg*Propagate->GetPQRdot(eQ)); - socket->Append(radtodeg*Propagate->GetPQRdot(eR)); - } - if (SubSystems & ssVelocities) - { - socket->Append(Auxiliary->Getqbar()); - socket->Append(Auxiliary->GetVt()); - socket->Append(Propagate->GetUVW(eU)); - socket->Append(Propagate->GetUVW(eV)); - socket->Append(Propagate->GetUVW(eW)); - socket->Append(Auxiliary->GetAeroUVW(eU)); - socket->Append(Auxiliary->GetAeroUVW(eV)); - socket->Append(Auxiliary->GetAeroUVW(eW)); - socket->Append(Propagate->GetVel(eNorth)); - socket->Append(Propagate->GetVel(eEast)); - socket->Append(Propagate->GetVel(eDown)); - } - if (SubSystems & ssForces) - { - socket->Append(Aerodynamics->GetvFw()(eDrag)); - socket->Append(Aerodynamics->GetvFw()(eSide)); - socket->Append(Aerodynamics->GetvFw()(eLift)); - socket->Append(Aerodynamics->GetLoD()); - socket->Append(Aircraft->GetForces(eX)); - socket->Append(Aircraft->GetForces(eY)); - socket->Append(Aircraft->GetForces(eZ)); - } - if (SubSystems & ssMoments) - { - socket->Append(Aircraft->GetMoments(eL)); - socket->Append(Aircraft->GetMoments(eM)); - socket->Append(Aircraft->GetMoments(eN)); - } - if (SubSystems & ssAtmosphere) - { - socket->Append(Atmosphere->GetDensity()); - socket->Append(Atmosphere->GetPressureSL()); - socket->Append(Atmosphere->GetPressure()); - socket->Append(Atmosphere->GetTurbMagnitude()); - socket->Append(Atmosphere->GetTurbDirection().Dump(",")); - socket->Append(Atmosphere->GetTotalWindNED().Dump(",")); - } - if (SubSystems & ssMassProps) - { - socket->Append(MassBalance->GetJ()(1,1)); - socket->Append(MassBalance->GetJ()(1,2)); - socket->Append(MassBalance->GetJ()(1,3)); - socket->Append(MassBalance->GetJ()(2,1)); - socket->Append(MassBalance->GetJ()(2,2)); - socket->Append(MassBalance->GetJ()(2,3)); - socket->Append(MassBalance->GetJ()(3,1)); - socket->Append(MassBalance->GetJ()(3,2)); - socket->Append(MassBalance->GetJ()(3,3)); - socket->Append(MassBalance->GetMass()); - socket->Append(MassBalance->GetXYZcg()(eX)); - socket->Append(MassBalance->GetXYZcg()(eY)); - socket->Append(MassBalance->GetXYZcg()(eZ)); - } - if (SubSystems & ssPropagate) - { - socket->Append(Propagate->GetAltitudeASL()); - socket->Append(radtodeg*Propagate->GetEuler(ePhi)); - socket->Append(radtodeg*Propagate->GetEuler(eTht)); - socket->Append(radtodeg*Propagate->GetEuler(ePsi)); - socket->Append(Auxiliary->Getalpha(inDegrees)); - socket->Append(Auxiliary->Getbeta(inDegrees)); - socket->Append(Propagate->GetLocation().GetLatitudeDeg()); - socket->Append(Propagate->GetLocation().GetLongitudeDeg()); - } - if (SubSystems & ssCoefficients) - { - scratch = Aerodynamics->GetCoefficientValues(","); - if (scratch.length() != 0) socket->Append(scratch); - } - if (SubSystems & ssFCS) - { - scratch = FCS->GetComponentValues(","); - if (scratch.length() != 0) socket->Append(scratch); - } - if (SubSystems & ssGroundReactions) - { - socket->Append(GroundReactions->GetGroundReactionValues(",")); - } - if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) - { - socket->Append(Propulsion->GetPropulsionValues(",")); - } - - for (unsigned int i=0;i<OutputProperties.size();i++) - { - socket->Append(OutputProperties[i]->getDoubleValue()); - } - + string asciiData, scratch; + + if (socket == NULL) return; + if (!socket->GetConnectStatus()) return; + + socket->Clear(); + if (sFirstPass) { + socket->Clear("<LABELS>"); + socket->Append("Time"); + + if (SubSystems & ssAerosurfaces) { + socket->Append("Aileron Command"); + socket->Append("Elevator Command"); + socket->Append("Rudder Command"); + socket->Append("Flap Command"); + socket->Append("Left Aileron Position"); + socket->Append("Right Aileron Position"); + socket->Append("Elevator Position"); + socket->Append("Rudder Position"); + socket->Append("Flap Position"); + } + + if (SubSystems & ssRates) { + socket->Append("P"); + socket->Append("Q"); + socket->Append("R"); + socket->Append("PDot"); + socket->Append("QDot"); + socket->Append("RDot"); + } + + if (SubSystems & ssVelocities) { + socket->Append("QBar"); + socket->Append("Vtotal"); + socket->Append("UBody"); + socket->Append("VBody"); + socket->Append("WBody"); + socket->Append("UAero"); + socket->Append("VAero"); + socket->Append("WAero"); + socket->Append("Vn"); + socket->Append("Ve"); + socket->Append("Vd"); + } + if (SubSystems & ssForces) { + socket->Append("F_Drag"); + socket->Append("F_Side"); + socket->Append("F_Lift"); + socket->Append("LoD"); + socket->Append("Fx"); + socket->Append("Fy"); + socket->Append("Fz"); + } + if (SubSystems & ssMoments) { + socket->Append("L"); + socket->Append("M"); + socket->Append("N"); + } + if (SubSystems & ssAtmosphere) { + socket->Append("Rho"); + socket->Append("SL pressure"); + socket->Append("Ambient pressure"); + socket->Append("Turbulence Magnitude"); + socket->Append("Turbulence Direction X"); + socket->Append("Turbulence Direction Y"); + socket->Append("Turbulence Direction Z"); + socket->Append("NWind"); + socket->Append("EWind"); + socket->Append("DWind"); + } + if (SubSystems & ssMassProps) { + socket->Append("Ixx"); + socket->Append("Ixy"); + socket->Append("Ixz"); + socket->Append("Iyx"); + socket->Append("Iyy"); + socket->Append("Iyz"); + socket->Append("Izx"); + socket->Append("Izy"); + socket->Append("Izz"); + socket->Append("Mass"); + socket->Append("Xcg"); + socket->Append("Ycg"); + socket->Append("Zcg"); + } + if (SubSystems & ssPropagate) { + socket->Append("Altitude"); + socket->Append("Phi (deg)"); + socket->Append("Tht (deg)"); + socket->Append("Psi (deg)"); + socket->Append("Alpha (deg)"); + socket->Append("Beta (deg)"); + socket->Append("Latitude (deg)"); + socket->Append("Longitude (deg)"); + } + if (SubSystems & ssCoefficients) { + scratch = Aerodynamics->GetCoefficientStrings(","); + if (scratch.length() != 0) socket->Append(scratch); + } + if (SubSystems & ssFCS) { + scratch = FCS->GetComponentStrings(","); + if (scratch.length() != 0) socket->Append(scratch); + } + if (SubSystems & ssGroundReactions) { + socket->Append(GroundReactions->GetGroundReactionStrings(",")); + } + if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) { + socket->Append(Propulsion->GetPropulsionStrings(",")); + } + if (OutputProperties.size() > 0) { + for (unsigned int i=0;i<OutputProperties.size();i++) { + socket->Append(OutputProperties[i]->GetPrintableName()); + } + } + + sFirstPass = false; socket->Send(); + } + + socket->Clear(); + socket->Append(FDMExec->GetSimTime()); + + if (SubSystems & ssAerosurfaces) { + socket->Append(FCS->GetDaCmd()); + socket->Append(FCS->GetDeCmd()); + socket->Append(FCS->GetDrCmd()); + socket->Append(FCS->GetDfCmd()); + socket->Append(FCS->GetDaLPos()); + socket->Append(FCS->GetDaRPos()); + socket->Append(FCS->GetDePos()); + socket->Append(FCS->GetDrPos()); + socket->Append(FCS->GetDfPos()); + } + if (SubSystems & ssRates) { + socket->Append(radtodeg*Propagate->GetPQR(eP)); + socket->Append(radtodeg*Propagate->GetPQR(eQ)); + socket->Append(radtodeg*Propagate->GetPQR(eR)); + socket->Append(radtodeg*Propagate->GetPQRdot(eP)); + socket->Append(radtodeg*Propagate->GetPQRdot(eQ)); + socket->Append(radtodeg*Propagate->GetPQRdot(eR)); + } + if (SubSystems & ssVelocities) { + socket->Append(Auxiliary->Getqbar()); + socket->Append(Auxiliary->GetVt()); + socket->Append(Propagate->GetUVW(eU)); + socket->Append(Propagate->GetUVW(eV)); + socket->Append(Propagate->GetUVW(eW)); + socket->Append(Auxiliary->GetAeroUVW(eU)); + socket->Append(Auxiliary->GetAeroUVW(eV)); + socket->Append(Auxiliary->GetAeroUVW(eW)); + socket->Append(Propagate->GetVel(eNorth)); + socket->Append(Propagate->GetVel(eEast)); + socket->Append(Propagate->GetVel(eDown)); + } + if (SubSystems & ssForces) { + socket->Append(Aerodynamics->GetvFw()(eDrag)); + socket->Append(Aerodynamics->GetvFw()(eSide)); + socket->Append(Aerodynamics->GetvFw()(eLift)); + socket->Append(Aerodynamics->GetLoD()); + socket->Append(Aircraft->GetForces(eX)); + socket->Append(Aircraft->GetForces(eY)); + socket->Append(Aircraft->GetForces(eZ)); + } + if (SubSystems & ssMoments) { + socket->Append(Aircraft->GetMoments(eL)); + socket->Append(Aircraft->GetMoments(eM)); + socket->Append(Aircraft->GetMoments(eN)); + } + if (SubSystems & ssAtmosphere) { + socket->Append(Atmosphere->GetDensity()); + socket->Append(Atmosphere->GetPressureSL()); + socket->Append(Atmosphere->GetPressure()); + socket->Append(Atmosphere->GetTurbMagnitude()); + socket->Append(Atmosphere->GetTurbDirection().Dump(",")); + socket->Append(Atmosphere->GetTotalWindNED().Dump(",")); + } + if (SubSystems & ssMassProps) { + socket->Append(MassBalance->GetJ()(1,1)); + socket->Append(MassBalance->GetJ()(1,2)); + socket->Append(MassBalance->GetJ()(1,3)); + socket->Append(MassBalance->GetJ()(2,1)); + socket->Append(MassBalance->GetJ()(2,2)); + socket->Append(MassBalance->GetJ()(2,3)); + socket->Append(MassBalance->GetJ()(3,1)); + socket->Append(MassBalance->GetJ()(3,2)); + socket->Append(MassBalance->GetJ()(3,3)); + socket->Append(MassBalance->GetMass()); + socket->Append(MassBalance->GetXYZcg()(eX)); + socket->Append(MassBalance->GetXYZcg()(eY)); + socket->Append(MassBalance->GetXYZcg()(eZ)); + } + if (SubSystems & ssPropagate) { + socket->Append(Propagate->GetAltitudeASL()); + socket->Append(radtodeg*Propagate->GetEuler(ePhi)); + socket->Append(radtodeg*Propagate->GetEuler(eTht)); + socket->Append(radtodeg*Propagate->GetEuler(ePsi)); + socket->Append(Auxiliary->Getalpha(inDegrees)); + socket->Append(Auxiliary->Getbeta(inDegrees)); + socket->Append(Propagate->GetLocation().GetLatitudeDeg()); + socket->Append(Propagate->GetLocation().GetLongitudeDeg()); + } + if (SubSystems & ssCoefficients) { + scratch = Aerodynamics->GetCoefficientValues(","); + if (scratch.length() != 0) socket->Append(scratch); + } + if (SubSystems & ssFCS) { + scratch = FCS->GetComponentValues(","); + if (scratch.length() != 0) socket->Append(scratch); + } + if (SubSystems & ssGroundReactions) { + socket->Append(GroundReactions->GetGroundReactionValues(",")); + } + if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) { + socket->Append(Propulsion->GetPropulsionValues(",")); + } + + for (unsigned int i=0;i<OutputProperties.size();i++) { + socket->Append(OutputProperties[i]->getDoubleValue()); + } + + socket->Send(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGOutput::SocketStatusOutput(const string& out_str) { - string asciiData; + string asciiData; - if (socket == NULL) return; + if (socket == NULL) return; - socket->Clear(); - asciiData = string("<STATUS>") + out_str; - socket->Append(asciiData.c_str()); - socket->Send(); + socket->Clear(); + asciiData = string("<STATUS>") + out_str; + socket->Append(asciiData.c_str()); + socket->Send(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGOutput::Load(Element* element) { - string type="", parameter=""; - string name=""; - string protocol="tcp"; - int OutRate = 0; - string property; - unsigned int port; - Element *property_element; - - string separator = "/"; - - if (!DirectivesFile.empty()) // A directives filename from the command line overrides - { - output_file_name = DirectivesFile; // one found in the config file. - document = LoadXMLDocument(output_file_name); - } - else if (!element->GetAttributeValue("file").empty()) - { - output_file_name = FDMExec->GetRootDir() + element->GetAttributeValue("file"); - document = LoadXMLDocument(output_file_name); - } + string type="", parameter=""; + string name=""; + string protocol="tcp"; + int OutRate = 0; + string property; + unsigned int port; + Element *property_element; + + string separator = "/"; + + if (!DirectivesFile.empty()) { // A directives filename from the command line overrides + output_file_name = DirectivesFile; // one found in the config file. + document = LoadXMLDocument(output_file_name); + } else if (!element->GetAttributeValue("file").empty()) { + output_file_name = FDMExec->GetRootDir() + element->GetAttributeValue("file"); + document = LoadXMLDocument(output_file_name); + } else { + document = element; + } + + if (!document) return false; + + name = FDMExec->GetRootDir() + document->GetAttributeValue("name"); + type = document->GetAttributeValue("type"); + SetType(type); + if (!document->GetAttributeValue("port").empty() && type == string("SOCKET")) { + port = atoi(document->GetAttributeValue("port").c_str()); + socket = new FGfdmSocket(name, port); + } else if (!document->GetAttributeValue("port").empty() && type == string("FLIGHTGEAR")) { + port = atoi(document->GetAttributeValue("port").c_str()); + if (!document->GetAttributeValue("protocol").empty()) + protocol = document->GetAttributeValue("protocol"); + if (protocol == "udp") + flightGearSocket = new FGfdmSocket(name, port, FGfdmSocket::ptUDP); // create udp socket else - { - document = element; - } - - if (!document) return false; - - name = FDMExec->GetRootDir() + document->GetAttributeValue("name"); - type = document->GetAttributeValue("type"); - SetType(type); - if (!document->GetAttributeValue("port").empty() && type == string("SOCKET")) - { - port = atoi(document->GetAttributeValue("port").c_str()); - socket = new FGfdmSocket(name, port); - } - else if (!document->GetAttributeValue("port").empty() && type == string("FLIGHTGEAR")) - { - port = atoi(document->GetAttributeValue("port").c_str()); - if (!document->GetAttributeValue("protocol").empty()) - protocol = document->GetAttributeValue("protocol"); - if (protocol == "udp") - flightGearSocket = new FGfdmSocket(name, port, FGfdmSocket::ptUDP); // create udp socket - else - flightGearSocket = new FGfdmSocket(name, port, FGfdmSocket::ptTCP); // create tcp socket (default) - } - else - { - BaseFilename = Filename = name; - } - if (!document->GetAttributeValue("rate").empty()) - { - OutRate = (int)document->GetAttributeValueAsNumber("rate"); - } - else - { - OutRate = 1; - } - - if (document->FindElementValue("simulation") == string("ON")) - SubSystems += ssSimulation; - if (document->FindElementValue("aerosurfaces") == string("ON")) - SubSystems += ssAerosurfaces; - if (document->FindElementValue("rates") == string("ON")) - SubSystems += ssRates; - if (document->FindElementValue("velocities") == string("ON")) - SubSystems += ssVelocities; - if (document->FindElementValue("forces") == string("ON")) - SubSystems += ssForces; - if (document->FindElementValue("moments") == string("ON")) - SubSystems += ssMoments; - if (document->FindElementValue("atmosphere") == string("ON")) - SubSystems += ssAtmosphere; - if (document->FindElementValue("massprops") == string("ON")) - SubSystems += ssMassProps; - if (document->FindElementValue("position") == string("ON")) - SubSystems += ssPropagate; - if (document->FindElementValue("coefficients") == string("ON")) - SubSystems += ssCoefficients; - if (document->FindElementValue("ground_reactions") == string("ON")) - SubSystems += ssGroundReactions; - if (document->FindElementValue("fcs") == string("ON")) - SubSystems += ssFCS; - if (document->FindElementValue("propulsion") == string("ON")) - SubSystems += ssPropulsion; - property_element = document->FindElement("property"); - while (property_element) - { - string property_str = property_element->GetDataLine(); - FGPropertyManager* node = PropertyManager->GetNode(property_str); - if (!node) - { - cerr << fgred << highint << endl << " No property by the name " - << property_str << " has been defined. This property will " << endl - << " not be logged. You should check your configuration file." - << reset << endl; - } - else - { - OutputProperties.push_back(node); - } - property_element = document->FindNextElement("property"); - } - - SetRate(OutRate); - - Debug(2); - - return true; + flightGearSocket = new FGfdmSocket(name, port, FGfdmSocket::ptTCP); // create tcp socket (default) + } else { + BaseFilename = Filename = name; + } + if (!document->GetAttributeValue("rate").empty()) { + OutRate = (int)document->GetAttributeValueAsNumber("rate"); + } else { + OutRate = 1; + } + + if (document->FindElementValue("simulation") == string("ON")) + SubSystems += ssSimulation; + if (document->FindElementValue("aerosurfaces") == string("ON")) + SubSystems += ssAerosurfaces; + if (document->FindElementValue("rates") == string("ON")) + SubSystems += ssRates; + if (document->FindElementValue("velocities") == string("ON")) + SubSystems += ssVelocities; + if (document->FindElementValue("forces") == string("ON")) + SubSystems += ssForces; + if (document->FindElementValue("moments") == string("ON")) + SubSystems += ssMoments; + if (document->FindElementValue("atmosphere") == string("ON")) + SubSystems += ssAtmosphere; + if (document->FindElementValue("massprops") == string("ON")) + SubSystems += ssMassProps; + if (document->FindElementValue("position") == string("ON")) + SubSystems += ssPropagate; + if (document->FindElementValue("coefficients") == string("ON")) + SubSystems += ssCoefficients; + if (document->FindElementValue("ground_reactions") == string("ON")) + SubSystems += ssGroundReactions; + if (document->FindElementValue("fcs") == string("ON")) + SubSystems += ssFCS; + if (document->FindElementValue("propulsion") == string("ON")) + SubSystems += ssPropulsion; + property_element = document->FindElement("property"); + while (property_element) { + string property_str = property_element->GetDataLine(); + FGPropertyManager* node = PropertyManager->GetNode(property_str); + if (!node) { + cerr << fgred << highint << endl << " No property by the name " + << property_str << " has been defined. This property will " << endl + << " not be logged. You should check your configuration file." + << reset << endl; + } else { + OutputProperties.push_back(node); + } + property_element = document->FindNextElement("property"); + } + + SetRate(OutRate); + + Debug(2); + + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGOutput::SetRate(int rtHz) { - rtHz = rtHz>1000?1000:(rtHz<0?0:rtHz); - if (rtHz > 0) - { - rate = (int)(0.5 + 1.0/(FDMExec->GetDeltaT()*rtHz)); - Enable(); - } - else - { - rate = 1; - Disable(); - } + rtHz = rtHz>1000?1000:(rtHz<0?0:rtHz); + if (rtHz > 0) { + rate = (int)(0.5 + 1.0/(FDMExec->GetDeltaT()*rtHz)); + Enable(); + } else { + rate = 1; + Disable(); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1195,83 +1072,69 @@ void FGOutput::SetRate(int rtHz) void FGOutput::Debug(int from) { - string scratch=""; - - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - - } - if (from == 2) - { - if (output_file_name.empty()) - cout << " " << "Output parameters read inline" << endl; - else - cout << " Output parameters read from file: " << output_file_name << endl; - - if (Filename == "cout" || Filename == "COUT") - { - scratch = " Log output goes to screen console"; - } - else if (!Filename.empty()) - { - scratch = " Log output goes to file: " + Filename; - } - switch (Type) - { - case otCSV: - cout << scratch << " in CSV format output at rate " << 1/(FDMExec->GetDeltaT()*rate) << " Hz" << endl; - break; - case otNone: - default: - cout << " No log output" << endl; - break; - } - - if (SubSystems & ssSimulation) cout << " Simulation parameters logged" << endl; - if (SubSystems & ssAerosurfaces) cout << " Aerosurface parameters logged" << endl; - if (SubSystems & ssRates) cout << " Rate parameters logged" << endl; - if (SubSystems & ssVelocities) cout << " Velocity parameters logged" << endl; - if (SubSystems & ssForces) cout << " Force parameters logged" << endl; - if (SubSystems & ssMoments) cout << " Moments parameters logged" << endl; - if (SubSystems & ssAtmosphere) cout << " Atmosphere parameters logged" << endl; - if (SubSystems & ssMassProps) cout << " Mass parameters logged" << endl; - if (SubSystems & ssCoefficients) cout << " Coefficient parameters logged" << endl; - if (SubSystems & ssPropagate) cout << " Propagate parameters logged" << endl; - if (SubSystems & ssGroundReactions) cout << " Ground parameters logged" << endl; - if (SubSystems & ssFCS) cout << " FCS parameters logged" << endl; - if (SubSystems & ssPropulsion) cout << " Propulsion parameters logged" << endl; - if (OutputProperties.size() > 0) cout << " Properties logged:" << endl; - for (unsigned int i=0;i<OutputProperties.size();i++) - { - cout << " - " << OutputProperties[i]->GetName() << endl; - } - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGOutput" << endl; - if (from == 1) cout << "Destroyed: FGOutput" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } - } + string scratch=""; + + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + + } + if (from == 2) { + if (output_file_name.empty()) + cout << " " << "Output parameters read inline" << endl; + else + cout << " Output parameters read from file: " << output_file_name << endl; + + if (Filename == "cout" || Filename == "COUT") { + scratch = " Log output goes to screen console"; + } else if (!Filename.empty()) { + scratch = " Log output goes to file: " + Filename; + } + switch (Type) { + case otCSV: + cout << scratch << " in CSV format output at rate " << 1/(FDMExec->GetDeltaT()*rate) << " Hz" << endl; + break; + case otNone: + default: + cout << " No log output" << endl; + break; + } + + if (SubSystems & ssSimulation) cout << " Simulation parameters logged" << endl; + if (SubSystems & ssAerosurfaces) cout << " Aerosurface parameters logged" << endl; + if (SubSystems & ssRates) cout << " Rate parameters logged" << endl; + if (SubSystems & ssVelocities) cout << " Velocity parameters logged" << endl; + if (SubSystems & ssForces) cout << " Force parameters logged" << endl; + if (SubSystems & ssMoments) cout << " Moments parameters logged" << endl; + if (SubSystems & ssAtmosphere) cout << " Atmosphere parameters logged" << endl; + if (SubSystems & ssMassProps) cout << " Mass parameters logged" << endl; + if (SubSystems & ssCoefficients) cout << " Coefficient parameters logged" << endl; + if (SubSystems & ssPropagate) cout << " Propagate parameters logged" << endl; + if (SubSystems & ssGroundReactions) cout << " Ground parameters logged" << endl; + if (SubSystems & ssFCS) cout << " FCS parameters logged" << endl; + if (SubSystems & ssPropulsion) cout << " Propulsion parameters logged" << endl; + if (OutputProperties.size() > 0) cout << " Properties logged:" << endl; + for (unsigned int i=0;i<OutputProperties.size();i++) { + cout << " - " << OutputProperties[i]->GetName() << endl; + } + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGOutput" << endl; + if (from == 1) cout << "Destroyed: FGOutput" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; + } + } } } diff --git a/src/models/FGOutput.h b/src/models/FGOutput.h index 75caacb81c971f03947ca1c920e85b8fb4618a96..f1cfef7d0e5c2d125208b8a8e410898ecef6bae4 100644 --- a/src/models/FGOutput.h +++ b/src/models/FGOutput.h @@ -56,8 +56,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGfdmSocket; @@ -134,90 +133,64 @@ CLASS DECLARATION class FGOutput : public FGModel, public FGXMLFileRead { public: - FGOutput(FGFDMExec*); - ~FGOutput(); - - bool InitModel(void); - bool Run(void); - - void DelimitedOutput(const std::string&); - void SocketOutput(void); - void FlightGearSocketOutput(void); - void SocketStatusOutput(const std::string&); - void SocketDataFill(FGNetFDM* net); - - - void SetType(const std::string& type); - void SetStartNewFile(bool tt) - { - StartNewFile = tt; - } - void SetSubsystems(int tt) - { - SubSystems = tt; - } - void Enable(void) - { - enabled = true; - } - void Disable(void) - { - enabled = false; - } - bool Toggle(void) - { - enabled = !enabled; - return enabled; - } - bool Load(Element* el); - void SetOutputFileName(const std::string& fname) - { - Filename = fname; - } - void SetDirectivesFile(const std::string& fname) - { - DirectivesFile = fname; - } - void SetRate(int rt); - string GetOutputFileName(void) const - { - return Filename; - } - - /// Subsystem types for specifying which will be output in the FDM data logging - enum eSubSystems - { - /** Subsystem: Simulation (= 1) */ ssSimulation = 1, - /** Subsystem: Aerosurfaces (= 2) */ ssAerosurfaces = 2, - /** Subsystem: Body rates (= 4) */ ssRates = 4, - /** Subsystem: Velocities (= 8) */ ssVelocities = 8, - /** Subsystem: Forces (= 16) */ ssForces = 16, - /** Subsystem: Moments (= 32) */ ssMoments = 32, - /** Subsystem: Atmosphere (= 64) */ ssAtmosphere = 64, - /** Subsystem: Mass Properties (= 128) */ ssMassProps = 128, - /** Subsystem: Coefficients (= 256) */ ssCoefficients = 256, - /** Subsystem: Propagate (= 512) */ ssPropagate = 512, - /** Subsystem: Ground Reactions (= 1024) */ ssGroundReactions = 1024, - /** Subsystem: FCS (= 2048) */ ssFCS = 2048, - /** Subsystem: Propulsion (= 4096) */ ssPropulsion = 4096 - } subsystems; - - - FGNetFDM fgSockBuf; + FGOutput(FGFDMExec*); + ~FGOutput(); + + bool InitModel(void); + bool Run(void); + + void DelimitedOutput(const std::string&); + void SocketOutput(void); + void FlightGearSocketOutput(void); + void SocketStatusOutput(const std::string&); + void SocketDataFill(FGNetFDM* net); + + + void SetType(const std::string& type); + void SetStartNewFile(bool tt) {StartNewFile = tt;} + void SetSubsystems(int tt) {SubSystems = tt;} + void Enable(void) { enabled = true; } + void Disable(void) { enabled = false; } + bool Toggle(void) {enabled = !enabled; return enabled;} + bool Load(Element* el); + void SetOutputFileName(const std::string& fname) {Filename = fname;} + void SetDirectivesFile(const std::string& fname) {DirectivesFile = fname;} + void SetRate(int rt); + string GetOutputFileName(void) const {return Filename;} + + /// Subsystem types for specifying which will be output in the FDM data logging + enum eSubSystems { + /** Subsystem: Simulation (= 1) */ ssSimulation = 1, + /** Subsystem: Aerosurfaces (= 2) */ ssAerosurfaces = 2, + /** Subsystem: Body rates (= 4) */ ssRates = 4, + /** Subsystem: Velocities (= 8) */ ssVelocities = 8, + /** Subsystem: Forces (= 16) */ ssForces = 16, + /** Subsystem: Moments (= 32) */ ssMoments = 32, + /** Subsystem: Atmosphere (= 64) */ ssAtmosphere = 64, + /** Subsystem: Mass Properties (= 128) */ ssMassProps = 128, + /** Subsystem: Coefficients (= 256) */ ssCoefficients = 256, + /** Subsystem: Propagate (= 512) */ ssPropagate = 512, + /** Subsystem: Ground Reactions (= 1024) */ ssGroundReactions = 1024, + /** Subsystem: FCS (= 2048) */ ssFCS = 2048, + /** Subsystem: Propulsion (= 4096) */ ssPropulsion = 4096 + } subsystems; + + + FGNetFDM fgSockBuf; private: - enum {otNone, otCSV, otTab, otSocket, otTerminal, otFlightGear, otUnknown} Type; - bool sFirstPass, dFirstPass, enabled; - int SubSystems; - int runID_postfix; - bool StartNewFile; - std::string output_file_name, delimeter, BaseFilename, Filename, DirectivesFile; - std::ofstream datafile; - FGfdmSocket* socket; - FGfdmSocket* flightGearSocket; - std::vector <FGPropertyManager*> OutputProperties; - - void Debug(int from); + enum {otNone, otCSV, otTab, otSocket, otTerminal, otFlightGear, otUnknown} Type; + bool sFirstPass, dFirstPass, enabled; + int SubSystems; + int runID_postfix; + bool StartNewFile; + std::string output_file_name, delimeter, BaseFilename, Filename, DirectivesFile; + std::ofstream datafile; + FGfdmSocket* socket; + FGfdmSocket* flightGearSocket; + std::vector <FGPropertyManager*> OutputProperties; + + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/FGPropagate.cpp b/src/models/FGPropagate.cpp index 56e0bb547fbe98ccf141a8ab662db1a141373f83..1e11074f9dcab4ec33b8b16b74dac1cdced7ce83 100644 --- a/src/models/FGPropagate.cpp +++ b/src/models/FGPropagate.cpp @@ -69,10 +69,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.60 2010/08/12 19:11:22 andgi Exp $"; +static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.65 2010/09/18 22:48:12 jberndt Exp $"; static const char *IdHdr = ID_PROPAGATE; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -81,162 +80,133 @@ CLASS IMPLEMENTATION FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex) { - Debug(0); - Name = "FGPropagate"; - gravType = gtWGS84; - - vPQRdot.InitMatrix(); - vQtrndot = FGQuaternion(0,0,0); - vUVWdot.InitMatrix(); - vInertialVelocity.InitMatrix(); - - integrator_rotational_rate = eAdamsBashforth2; - integrator_translational_rate = eTrapezoidal; - integrator_rotational_position = eAdamsBashforth2; - integrator_translational_position = eTrapezoidal; - - VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0)); - VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0)); - VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0)); - VState.dqQtrndot.resize(4, FGQuaternion(0.0,0.0,0.0)); - - bind(); - Debug(0); + Debug(0); + Name = "FGPropagate"; + gravType = gtStandard; + + vPQRdot.InitMatrix(); + vQtrndot = FGQuaternion(0,0,0); + vUVWdot.InitMatrix(); + vInertialVelocity.InitMatrix(); + + integrator_rotational_rate = eAdamsBashforth2; + integrator_translational_rate = eTrapezoidal; + integrator_rotational_position = eAdamsBashforth2; + integrator_translational_position = eTrapezoidal; + + VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0)); + VState.dqUVWidot.resize(4, FGColumnVector3(0.0,0.0,0.0)); + VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0)); + VState.dqQtrndot.resize(4, FGQuaternion(0.0,0.0,0.0)); + + bind(); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGPropagate::~FGPropagate(void) { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPropagate::InitModel(void) { - if (!FGModel::InitModel()) return false; + if (!FGModel::InitModel()) return false; - // For initialization ONLY: - SeaLevelRadius = LocalTerrainRadius = Inertial->GetRefRadius(); + // For initialization ONLY: + SeaLevelRadius = LocalTerrainRadius = Inertial->GetRefRadius(); - VState.vLocation.SetRadius( LocalTerrainRadius + 4.0 ); - VState.vLocation.SetEllipse(Inertial->GetSemimajor(), Inertial->GetSemiminor()); - vOmegaEarth = FGColumnVector3( 0.0, 0.0, Inertial->omega() ); // Earth rotation vector + VState.vLocation.SetRadius( LocalTerrainRadius + 4.0 ); + VState.vLocation.SetEllipse(Inertial->GetSemimajor(), Inertial->GetSemiminor()); + vOmegaEarth = FGColumnVector3( 0.0, 0.0, Inertial->omega() ); // Earth rotation vector - vPQRdot.InitMatrix(); - vQtrndot = FGQuaternion(0,0,0); - vUVWdot.InitMatrix(); - vInertialVelocity.InitMatrix(); + vPQRdot.InitMatrix(); + vQtrndot = FGQuaternion(0,0,0); + vUVWdot.InitMatrix(); + vInertialVelocity.InitMatrix(); - VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0)); - VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0)); - VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0)); - VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0)); + VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0)); + VState.dqUVWidot.resize(4, FGColumnVector3(0.0,0.0,0.0)); + VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0)); + VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0)); - integrator_rotational_rate = eAdamsBashforth2; - integrator_translational_rate = eTrapezoidal; - integrator_rotational_position = eAdamsBashforth2; - integrator_translational_position = eTrapezoidal; + integrator_rotational_rate = eAdamsBashforth2; + integrator_translational_rate = eTrapezoidal; + integrator_rotational_position = eAdamsBashforth2; + integrator_translational_position = eTrapezoidal; - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropagate::SetInitialState(const FGInitialCondition *FGIC) { - SetSeaLevelRadius(FGIC->GetSeaLevelRadiusFtIC()); - SetTerrainElevation(FGIC->GetTerrainElevationFtIC()); - - VehicleRadius = GetRadius(); - radInv = 1.0/VehicleRadius; - - // Initialize the State Vector elements and the transformation matrices + SetSeaLevelRadius(FGIC->GetSeaLevelRadiusFtIC()); + SetTerrainElevation(FGIC->GetTerrainElevationFtIC()); - // Set the position lat/lon/radius - VState.vLocation.SetPosition( FGIC->GetLongitudeRadIC(), - FGIC->GetLatitudeRadIC(), - FGIC->GetAltitudeASLFtIC() + FGIC->GetSeaLevelRadiusFtIC() ); + // Initialize the State Vector elements and the transformation matrices - VState.vLocation.SetEarthPositionAngle(Inertial->GetEarthPositionAngle()); + // Set the position lat/lon/radius + VState.vLocation.SetPosition( FGIC->GetLongitudeRadIC(), + FGIC->GetLatitudeRadIC(), + FGIC->GetAltitudeASLFtIC() + FGIC->GetSeaLevelRadiusFtIC() ); - Ti2ec = GetTi2ec(); // ECI to ECEF transform - Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform + VState.vLocation.SetEarthPositionAngle(Inertial->GetEarthPositionAngle()); - Tl2ec = GetTl2ec(); // local to ECEF transform - Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform + Ti2ec = GetTi2ec(); // ECI to ECEF transform + Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform - Ti2l = GetTi2l(); - Tl2i = Ti2l.Transposed(); + VState.vInertialPosition = Tec2i * VState.vLocation; - // Set the orientation from the euler angles (is normalized within the - // constructor). The Euler angles represent the orientation of the body - // frame relative to the local frame. - VState.qAttitudeLocal = FGQuaternion( FGIC->GetPhiRadIC(), - FGIC->GetThetaRadIC(), - FGIC->GetPsiRadIC() ); + UpdateLocationMatrices(); - VState.qAttitudeECI = Ti2l.GetQuaternion()*VState.qAttitudeLocal; + // Set the orientation from the euler angles (is normalized within the + // constructor). The Euler angles represent the orientation of the body + // frame relative to the local frame. + VState.qAttitudeLocal = FGQuaternion( FGIC->GetPhiRadIC(), + FGIC->GetThetaRadIC(), + FGIC->GetPsiRadIC() ); - Ti2b = GetTi2b(); // ECI to body frame transform - Tb2i = Ti2b.Transposed(); // body to ECI frame transform + VState.qAttitudeECI = Ti2l.GetQuaternion()*VState.qAttitudeLocal; + UpdateBodyMatrices(); - Tl2b = VState.qAttitudeLocal; // local to body frame transform - Tb2l = Tl2b.Transposed(); // body to local frame transform + // Set the velocities in the instantaneus body frame + VState.vUVW = FGColumnVector3( FGIC->GetUBodyFpsIC(), + FGIC->GetVBodyFpsIC(), + FGIC->GetWBodyFpsIC() ); - Tec2b = Tl2b * Tec2l; // ECEF to body frame transform - Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform + // Compute the local frame ECEF velocity + vVel = Tb2l * VState.vUVW; - // Set the velocities in the instantaneus body frame - VState.vUVW = FGColumnVector3( FGIC->GetUBodyFpsIC(), - FGIC->GetVBodyFpsIC(), - FGIC->GetWBodyFpsIC() ); + // Recompute the LocalTerrainRadius. + RecomputeLocalTerrainRadius(); - VState.vInertialPosition = Tec2i * VState.vLocation; + VehicleRadius = GetRadius(); + double radInv = 1.0/VehicleRadius; - // Compute the local frame ECEF velocity - vVel = Tb2l * VState.vUVW; + // Refer to Stevens and Lewis, 1.5-14a, pg. 49. + // This is the rotation rate of the "Local" frame, expressed in the local frame. - // Refer to Stevens and Lewis, 1.5-14a, pg. 49. - // This is the rotation rate of the "Local" frame, expressed in the local frame. + FGColumnVector3 vOmegaLocal = FGColumnVector3( + radInv*vVel(eEast), + -radInv*vVel(eNorth), + -radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() ); - FGColumnVector3 vOmegaLocal = FGColumnVector3( - radInv*vVel(eEast), - -radInv*vVel(eNorth), - -radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() ); + // Set the angular velocities of the body frame relative to the ECEF frame, + // expressed in the body frame. Effectively, this is: + // w_b/e = w_b/l + w_l/e + VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(), + FGIC->GetQRadpsIC(), + FGIC->GetRRadpsIC() ) + Tl2b*vOmegaLocal; - // Set the angular velocities of the body frame relative to the ECEF frame, - // expressed in the body frame. Effectively, this is: - // w_b/e = w_b/l + w_l/e - VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(), - FGIC->GetQRadpsIC(), - FGIC->GetRRadpsIC() ) + Tl2b*vOmegaLocal; + VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth; - VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth; - - // Make an initial run and set past values - CalculatePQRdot(); // Angular rate derivative - CalculateUVWdot(); // Translational rate derivative - ResolveFrictionForces(0.); // Update rate derivatives with friction forces - CalculateQuatdot(); // Angular orientation derivative - CalculateInertialVelocity(); // Translational position derivative - - // Initialize past values deques - VState.dqPQRdot.clear(); - VState.dqUVWdot.clear(); - VState.dqInertialVelocity.clear(); - VState.dqQtrndot.clear(); - for (int i=0; i<4; i++) - { - VState.dqPQRdot.push_front(vPQRdot); - VState.dqUVWdot.push_front(vUVWdot); - VState.dqInertialVelocity.push_front(VState.vInertialVelocity); - VState.dqQtrndot.push_front(vQtrndot); - } - - // Recompute the LocalTerrainRadius. - RecomputeLocalTerrainRadius(); + // Make an initial run and set past values + InitializeDerivatives(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -252,7 +222,7 @@ This propagation is done using the current state values and current derivatives. Based on these values we compute an approximation to the state values for (now + dt). -In the code below, variables named beginning with a small "v" refer to a +In the code below, variables named beginning with a small "v" refer to a a column vector, variables named beginning with a "T" refer to a transformation matrix. ECEF refers to Earth Centered Earth Fixed. ECI refers to Earth Centered Inertial. @@ -261,72 +231,72 @@ Inertial. bool FGPropagate::Run(void) { - if (FGModel::Run()) return true; // Fast return if we have nothing to do ... - if (FDMExec->Holding()) return false; + if (FGModel::Run()) return true; // Fast return if we have nothing to do ... + if (FDMExec->Holding()) return false; + + double dt = FDMExec->GetDeltaT()*rate; // The 'stepsize' - double dt = FDMExec->GetDeltaT()*rate; // The 'stepsize' + RunPreFunctions(); - RunPreFunctions(); + // Calculate state derivatives + CalculatePQRdot(); // Angular rate derivative + CalculateUVWdot(); // Translational rate derivative + ResolveFrictionForces(dt); // Update rate derivatives with friction forces + CalculateQuatdot(); // Angular orientation derivative + CalculateUVW(); // Translational position derivative (velocities are integrated in the inertial frame) - // Calculate state derivatives - CalculatePQRdot(); // Angular rate derivative - CalculateUVWdot(); // Translational rate derivative - ResolveFrictionForces(dt); // Update rate derivatives with friction forces - CalculateQuatdot(); // Angular orientation derivative - CalculateInertialVelocity(); // Translational position derivative + // Propagate rotational / translational velocity, angular /translational position, respectively. + Integrate(VState.vPQRi, vPQRdot, VState.dqPQRdot, dt, integrator_rotational_rate); + Integrate(VState.vInertialVelocity, vUVWidot, VState.dqUVWidot, dt, integrator_translational_rate); + Integrate(VState.qAttitudeECI, vQtrndot, VState.dqQtrndot, dt, integrator_rotational_position); + Integrate(VState.vInertialPosition, VState.vInertialVelocity, VState.dqInertialVelocity, dt, integrator_translational_position); - // Propagate rotational / translational velocity, angular /translational position, respectively. - Integrate(VState.vPQRi, vPQRdot, VState.dqPQRdot, dt, integrator_rotational_rate); - Integrate(VState.vUVW, vUVWdot, VState.dqUVWdot, dt, integrator_translational_rate); - Integrate(VState.qAttitudeECI, vQtrndot, VState.dqQtrndot, dt, integrator_rotational_position); - Integrate(VState.vInertialPosition, VState.vInertialVelocity, VState.dqInertialVelocity, dt, integrator_translational_position); + // CAUTION : the order of the operations below is very important to get transformation + // matrices that are consistent with the new state of the vehicle - VState.qAttitudeECI.Normalize(); // Normalize the ECI Attitude quaternion + // 1. Update the Earth position angle (EPA) + VState.vLocation.SetEarthPositionAngle(Inertial->GetEarthPositionAngle()); - VState.vLocation.SetEarthPositionAngle(Inertial->GetEarthPositionAngle()); // Update the Earth position angle (EPA) + // 2. Update the Ti2ec and Tec2i transforms from the updated EPA + Ti2ec = GetTi2ec(); // ECI to ECEF transform + Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform - // Update the "Location-based" transformation matrices from the vLocation vector. + // 3. Update the location from the updated Ti2ec and inertial position + VState.vLocation = Ti2ec*VState.vInertialPosition; - Ti2ec = GetTi2ec(); // ECI to ECEF transform - Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform - Tl2ec = GetTl2ec(); // local to ECEF transform - Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform - Ti2l = GetTi2l(); - Tl2i = Ti2l.Transposed(); + // 4. Update the other "Location-based" transformation matrices from the updated + // vLocation vector. + UpdateLocationMatrices(); - // Update the "Orientation-based" transformation matrices from the orientation quaternion + // 5. Normalize the ECI Attitude quaternion + VState.qAttitudeECI.Normalize(); - Ti2b = GetTi2b(); // ECI to body frame transform - Tb2i = Ti2b.Transposed(); // body to ECI frame transform - Tl2b = Ti2b*Tl2i; // local to body frame transform - Tb2l = Tl2b.Transposed(); // body to local frame transform - Tec2b = Tl2b * Tec2l; // ECEF to body frame transform - Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform + // 6. Update the "Orientation-based" transformation matrices from the updated + // orientation quaternion and vLocation vector. + UpdateBodyMatrices(); - // Set auxililary state variables - VState.vLocation = Ti2ec*VState.vInertialPosition; - RecomputeLocalTerrainRadius(); + // Set auxililary state variables + RecomputeLocalTerrainRadius(); - VehicleRadius = GetRadius(); // Calculate current aircraft radius from center of planet - radInv = 1.0/VehicleRadius; + VehicleRadius = GetRadius(); // Calculate current aircraft radius from center of planet - VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth; + VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth; - VState.qAttitudeLocal = Tl2b.GetQuaternion(); + VState.qAttitudeLocal = Tl2b.GetQuaternion(); - // Compute vehicle velocity wrt ECEF frame, expressed in Local horizontal frame. - vVel = Tb2l * VState.vUVW; + // Compute vehicle velocity wrt ECEF frame, expressed in Local horizontal frame. + vVel = Tb2l * VState.vUVW; - RunPostFunctions(); + RunPostFunctions(); - Debug(2); - return false; + Debug(2); + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Compute body frame rotational accelerations based on the current body moments // -// vPQRdot is the derivative of the absolute angular velocity of the vehicle +// vPQRdot is the derivative of the absolute angular velocity of the vehicle // (body rate with respect to the inertial frame), expressed in the body frame, // where the derivative is taken in the body frame. // J is the inertia matrix @@ -334,40 +304,40 @@ bool FGPropagate::Run(void) // vMoments is the moment vector in the body frame // VState.vPQRi is the total inertial angular velocity of the vehicle // expressed in the body frame. -// Reference: See Stevens and Lewis, "Aircraft Control and Simulation", +// Reference: See Stevens and Lewis, "Aircraft Control and Simulation", // Second edition (2004), eqn 1.5-16e (page 50) void FGPropagate::CalculatePQRdot(void) { - const FGColumnVector3& vMoments = Aircraft->GetMoments(); // current moments - const FGMatrix33& J = MassBalance->GetJ(); // inertia matrix - const FGMatrix33& Jinv = MassBalance->GetJinv(); // inertia matrix inverse + const FGColumnVector3& vMoments = Aircraft->GetMoments(); // current moments + const FGMatrix33& J = MassBalance->GetJ(); // inertia matrix + const FGMatrix33& Jinv = MassBalance->GetJinv(); // inertia matrix inverse - // Compute body frame rotational accelerations based on the current body - // moments and the total inertial angular velocity expressed in the body - // frame. + // Compute body frame rotational accelerations based on the current body + // moments and the total inertial angular velocity expressed in the body + // frame. - vPQRdot = Jinv*(vMoments - VState.vPQRi*(J*VState.vPQRi)); + vPQRdot = Jinv*(vMoments - VState.vPQRi*(J*VState.vPQRi)); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Compute the quaternion orientation derivative // // vQtrndot is the quaternion derivative. -// Reference: See Stevens and Lewis, "Aircraft Control and Simulation", +// Reference: See Stevens and Lewis, "Aircraft Control and Simulation", // Second edition (2004), eqn 1.5-16b (page 50) void FGPropagate::CalculateQuatdot(void) { - // Compute quaternion orientation derivative on current body rates - vQtrndot = VState.qAttitudeECI.GetQDot( VState.vPQRi); + // Compute quaternion orientation derivative on current body rates + vQtrndot = VState.qAttitudeECI.GetQDot( VState.vPQRi); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// This set of calculations results in the body frame accelerations being -// computed. -// Compute body frame accelerations based on the current body forces. -// Include centripetal and coriolis accelerations. +// This set of calculations results in the body and inertial frame accelerations +// being computed. +// Compute body and inertial frames accelerations based on the current body +// forces including centripetal and coriolis accelerations for the former. // vOmegaEarth is the Earth angular rate - expressed in the inertial frame - // so it has to be transformed to the body frame. More completely, // vOmegaEarth is the rate of the ECEF frame relative to the Inertial @@ -377,43 +347,53 @@ void FGPropagate::CalculateQuatdot(void) // in the body frame. // VState.vUVW is the vehicle velocity relative to the ECEF frame, expressed // in the body frame. -// Reference: See Stevens and Lewis, "Aircraft Control and Simulation", +// Reference: See Stevens and Lewis, "Aircraft Control and Simulation", // Second edition (2004), eqns 1.5-13 (pg 48) and 1.5-16d (page 50) void FGPropagate::CalculateUVWdot(void) { - double mass = MassBalance->GetMass(); // mass - const FGColumnVector3& vForces = Aircraft->GetForces(); // current forces + double mass = MassBalance->GetMass(); // mass + const FGColumnVector3& vForces = Aircraft->GetForces(); // current forces - vUVWdot = vForces/mass - (VState.vPQR + 2.0*(Ti2b *vOmegaEarth)) * VState.vUVW; + vUVWdot = vForces/mass - (VState.vPQR + 2.0*(Ti2b *vOmegaEarth)) * VState.vUVW; - // Include Centripetal acceleration. - vUVWdot -= Ti2b * (vOmegaEarth*(vOmegaEarth*VState.vInertialPosition)); + // Include Centripetal acceleration. + vUVWdot -= Ti2b * (vOmegaEarth*(vOmegaEarth*VState.vInertialPosition)); - // Include Gravitation accel - switch (gravType) - { + // Include Gravitation accel + switch (gravType) { case gtStandard: - vGravAccel = Tl2b * FGColumnVector3( 0.0, 0.0, Inertial->GetGAccel(VehicleRadius) ); - break; + vGravAccel = Tl2b * FGColumnVector3( 0.0, 0.0, Inertial->GetGAccel(VehicleRadius) ); + break; case gtWGS84: - vGravAccel = Tec2b * Inertial->GetGravityJ2(VState.vLocation); - break; - } + vGravAccel = Tec2b * Inertial->GetGravityJ2(VState.vLocation); + break; + } - vUVWdot += vGravAccel; + vUVWdot += vGravAccel; + vUVWidot = Tb2i * (vForces/mass + vGravAccel); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// Transform the velocity vector of the body relative to the origin (Earth -// center) to be expressed in the inertial frame, and add the vehicle velocity -// contribution due to the rotation of the planet. -// Reference: See Stevens and Lewis, "Aircraft Control and Simulation", -// Second edition (2004), eqn 1.5-16c (page 50) + // Transform the velocity vector of the body relative to the origin (Earth + // center) to be expressed in the inertial frame, and add the vehicle velocity + // contribution due to the rotation of the planet. + // Reference: See Stevens and Lewis, "Aircraft Control and Simulation", + // Second edition (2004), eqn 1.5-16c (page 50) void FGPropagate::CalculateInertialVelocity(void) { - VState.vInertialVelocity = Tb2i * VState.vUVW + (vOmegaEarth * VState.vInertialPosition); + VState.vInertialVelocity = Tb2i * VState.vUVW + (vOmegaEarth * VState.vInertialPosition); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // Transform the velocity vector of the inertial frame to be expressed in the + // body frame relative to the origin (Earth center), and substract the vehicle + // velocity contribution due to the rotation of the planet. + +void FGPropagate::CalculateUVW(void) +{ + VState.vUVW = Ti2b * (VState.vInertialVelocity - (vOmegaEarth * VState.vInertialPosition)); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -424,29 +404,23 @@ void FGPropagate::Integrate( FGColumnVector3& Integrand, double dt, eIntegrateType integration_type) { - ValDot.push_front(Val); - ValDot.pop_back(); - - switch (integration_type) - { - case eRectEuler: - Integrand += dt*ValDot[0]; - break; - case eTrapezoidal: - Integrand += 0.5*dt*(ValDot[0] + ValDot[1]); - break; - case eAdamsBashforth2: - Integrand += dt*(1.5*ValDot[0] - 0.5*ValDot[1]); - break; - case eAdamsBashforth3: - Integrand += (1/12.0)*dt*(23.0*ValDot[0] - 16.0*ValDot[1] + 5.0*ValDot[2]); - break; - case eAdamsBashforth4: - Integrand += (1/24.0)*dt*(55.0*ValDot[0] - 59.0*ValDot[1] + 37.0*ValDot[2] - 9.0*ValDot[3]); - break; - case eNone: // do nothing, freeze translational rate - break; - } + ValDot.push_front(Val); + ValDot.pop_back(); + + switch(integration_type) { + case eRectEuler: Integrand += dt*ValDot[0]; + break; + case eTrapezoidal: Integrand += 0.5*dt*(ValDot[0] + ValDot[1]); + break; + case eAdamsBashforth2: Integrand += dt*(1.5*ValDot[0] - 0.5*ValDot[1]); + break; + case eAdamsBashforth3: Integrand += (1/12.0)*dt*(23.0*ValDot[0] - 16.0*ValDot[1] + 5.0*ValDot[2]); + break; + case eAdamsBashforth4: Integrand += (1/24.0)*dt*(55.0*ValDot[0] - 59.0*ValDot[1] + 37.0*ValDot[2] - 9.0*ValDot[3]); + break; + case eNone: // do nothing, freeze translational rate + break; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -457,195 +431,239 @@ void FGPropagate::Integrate( FGQuaternion& Integrand, double dt, eIntegrateType integration_type) { - ValDot.push_front(Val); - ValDot.pop_back(); - - switch (integration_type) - { - case eRectEuler: - Integrand += dt*ValDot[0]; - break; - case eTrapezoidal: - Integrand += 0.5*dt*(ValDot[0] + ValDot[1]); - break; - case eAdamsBashforth2: - Integrand += dt*(1.5*ValDot[0] - 0.5*ValDot[1]); - break; - case eAdamsBashforth3: - Integrand += (1/12.0)*dt*(23.0*ValDot[0] - 16.0*ValDot[1] + 5.0*ValDot[2]); - break; - case eAdamsBashforth4: - Integrand += (1/24.0)*dt*(55.0*ValDot[0] - 59.0*ValDot[1] + 37.0*ValDot[2] - 9.0*ValDot[3]); - break; - case eNone: // do nothing, freeze rotational rate - break; - } + ValDot.push_front(Val); + ValDot.pop_back(); + + switch(integration_type) { + case eRectEuler: Integrand += dt*ValDot[0]; + break; + case eTrapezoidal: Integrand += 0.5*dt*(ValDot[0] + ValDot[1]); + break; + case eAdamsBashforth2: Integrand += dt*(1.5*ValDot[0] - 0.5*ValDot[1]); + break; + case eAdamsBashforth3: Integrand += (1/12.0)*dt*(23.0*ValDot[0] - 16.0*ValDot[1] + 5.0*ValDot[2]); + break; + case eAdamsBashforth4: Integrand += (1/24.0)*dt*(55.0*ValDot[0] - 59.0*ValDot[1] + 37.0*ValDot[2] - 9.0*ValDot[3]); + break; + case eNone: // do nothing, freeze rotational rate + break; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Resolves the contact forces just before integrating the EOM. // This routine is using Lagrange multipliers and the projected Gauss-Seidel // (PGS) method. -// Reference: See Erin Catto, "Iterative Dynamics with Temporal Coherence", +// Reference: See Erin Catto, "Iterative Dynamics with Temporal Coherence", // February 22, 2005 // In JSBSim there is only one rigid body (the aircraft) and there can be // multiple points of contact between the aircraft and the ground. As a // consequence our matrix J*M^-1*J^T is not sparse and the algorithm described // in Catto's paper has been adapted accordingly. +// The friction forces are resolved in the body frame relative to the origin +// (Earth center). void FGPropagate::ResolveFrictionForces(double dt) { - const double invMass = 1.0 / MassBalance->GetMass(); - const FGMatrix33& Jinv = MassBalance->GetJinv(); - vector <FGColumnVector3> JacF, JacM; - FGColumnVector3 vdot, wdot; - FGColumnVector3 Fc, Mc; - int n = 0, i; - - // Compiles data from the ground reactions to build up the jacobian matrix - for (MultiplierIterator it=MultiplierIterator(GroundReactions); *it; ++it, n++) - { - JacF.push_back((*it)->ForceJacobian); - JacM.push_back((*it)->MomentJacobian); + const double invMass = 1.0 / MassBalance->GetMass(); + const FGMatrix33& Jinv = MassBalance->GetJinv(); + vector <FGColumnVector3> JacF, JacM; + FGColumnVector3 vdot, wdot; + FGColumnVector3 Fc, Mc; + int n = 0, i; + + // Compiles data from the ground reactions to build up the jacobian matrix + for (MultiplierIterator it=MultiplierIterator(GroundReactions); *it; ++it, n++) { + JacF.push_back((*it)->ForceJacobian); + JacM.push_back((*it)->MomentJacobian); + } + + // If no gears are in contact with the ground then return + if (!n) return; + + vector<double> a(n*n); // Will contain J*M^-1*J^T + vector<double> eta(n); + vector<double> lambda(n); + vector<double> lambdaMin(n); + vector<double> lambdaMax(n); + + // Initializes the Lagrange multipliers + i = 0; + for (MultiplierIterator it=MultiplierIterator(GroundReactions); *it; ++it, i++) { + lambda[i] = (*it)->value; + lambdaMax[i] = (*it)->Max; + lambdaMin[i] = (*it)->Min; + } + + vdot = vUVWdot; + wdot = vPQRdot; + + if (dt > 0.) { + // Instruct the algorithm to zero out the relative movement between the + // aircraft and the ground. + vdot += (VState.vUVW - Tec2b * LocalTerrainVelocity) / dt; + wdot += VState.vPQR / dt; + } + + // Assemble the linear system of equations + for (i=0; i < n; i++) { + for (int j=0; j < i; j++) + a[i*n+j] = a[j*n+i]; // Takes advantage of the symmetry of J^T*M^-1*J + for (int j=i; j < n; j++) + a[i*n+j] = DotProduct(JacF[i],invMass*JacF[j])+DotProduct(JacM[i],Jinv*JacM[j]); + } + + // Prepare the linear system for the Gauss-Seidel algorithm : + // divide every line of 'a' and eta by a[i,i]. This is in order to save + // a division computation at each iteration of Gauss-Seidel. + for (i=0; i < n; i++) { + double d = 1.0 / a[i*n+i]; + + eta[i] = -(DotProduct(JacF[i],vdot)+DotProduct(JacM[i],wdot))*d; + for (int j=0; j < n; j++) + a[i*n+j] *= d; + } + + // Resolve the Lagrange multipliers with the projected Gauss-Seidel method + for (int iter=0; iter < 50; iter++) { + double norm = 0.; + + for (i=0; i < n; i++) { + double lambda0 = lambda[i]; + double dlambda = eta[i]; + + for (int j=0; j < n; j++) + dlambda -= a[i*n+j]*lambda[j]; + + lambda[i] = Constrain(lambdaMin[i], lambda0+dlambda, lambdaMax[i]); + dlambda = lambda[i] - lambda0; + + norm += fabs(dlambda); } - // If no gears are in contact with the ground then return - if (!n) return; - - vector<double> a(n*n); // Will contain J*M^-1*J^T - vector<double> eta(n); - vector<double> lambda(n); - vector<double> lambdaMin(n); - vector<double> lambdaMax(n); - - // Initializes the Lagrange multipliers - i = 0; - for (MultiplierIterator it=MultiplierIterator(GroundReactions); *it; ++it, i++) - { - lambda[i] = (*it)->value; - lambdaMax[i] = (*it)->Max; - lambdaMin[i] = (*it)->Min; - } + if (norm < 1E-5) break; + } - vdot = vUVWdot; - wdot = vPQRdot; + // Calculate the total friction forces and moments - if (dt > 0.) - { - // First compute the ground velocity below the aircraft center of gravity - FGLocation contact; - FGColumnVector3 normal, cvel; + Fc.InitMatrix(); + Mc.InitMatrix(); - // Instruct the algorithm to zero out the relative movement between the - // aircraft and the ground. - vdot += (VState.vUVW - Tec2b * cvel) / dt; - wdot += VState.vPQR / dt; - } + for (i=0; i< n; i++) { + Fc += lambda[i]*JacF[i]; + Mc += lambda[i]*JacM[i]; + } - // Assemble the linear system of equations - for (i=0; i < n; i++) - { - for (int j=0; j < i; j++) - a[i*n+j] = a[j*n+i]; // Takes advantage of the symmetry of J^T*M^-1*J - for (int j=i; j < n; j++) - a[i*n+j] = DotProduct(JacF[i],invMass*JacF[j])+DotProduct(JacM[i],Jinv*JacM[j]); - } + vUVWdot += invMass * Fc; + vUVWidot += invMass * Tb2i * Fc; + vPQRdot += Jinv * Mc; - // Prepare the linear system for the Gauss-Seidel algorithm : - // divide every line of 'a' and eta by a[i,i]. This is in order to save - // a division computation at each iteration of Gauss-Seidel. - for (i=0; i < n; i++) - { - double d = 1.0 / a[i*n+i]; - - eta[i] = -(DotProduct(JacF[i],vdot)+DotProduct(JacM[i],wdot))*d; - for (int j=0; j < n; j++) - a[i*n+j] *= d; - } + // Save the value of the Lagrange multipliers to accelerate the convergence + // of the Gauss-Seidel algorithm at next iteration. + i = 0; + for (MultiplierIterator it=MultiplierIterator(GroundReactions); *it; ++it) + (*it)->value = lambda[i++]; - // Resolve the Lagrange multipliers with the projected Gauss-Seidel method - for (int iter=0; iter < 50; iter++) - { - double norm = 0.; - - for (i=0; i < n; i++) - { - double lambda0 = lambda[i]; - double dlambda = eta[i]; - - for (int j=0; j < n; j++) - dlambda -= a[i*n+j]*lambda[j]; - - lambda[i] = Constrain(lambdaMin[i], lambda0+dlambda, lambdaMax[i]); - dlambda = lambda[i] - lambda0; + GroundReactions->UpdateForcesAndMoments(); +} - norm += fabs(dlambda); - } +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if (norm < 1E-5) break; - } +void FGPropagate::UpdateLocationMatrices(void) +{ + Tl2ec = GetTl2ec(); // local to ECEF transform + Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform + Ti2l = GetTi2l(); + Tl2i = Ti2l.Transposed(); +} - // Calculate the total friction forces and moments +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - Fc.InitMatrix(); - Mc.InitMatrix(); +void FGPropagate::UpdateBodyMatrices(void) +{ + Ti2b = GetTi2b(); // ECI to body frame transform + Tb2i = Ti2b.Transposed(); // body to ECI frame transform + Tl2b = Ti2b*Tl2i; // local to body frame transform + Tb2l = Tl2b.Transposed(); // body to local frame transform + Tec2b = Tl2b * Tec2l; // ECEF to body frame transform + Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform +} - for (i=0; i< n; i++) - { - Fc += lambda[i]*JacF[i]; - Mc += lambda[i]*JacM[i]; - } +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - vUVWdot += invMass * Fc; - vPQRdot += Jinv * Mc; +void FGPropagate::SetInertialOrientation(FGQuaternion Qi) { + VState.qAttitudeECI = Qi; + VState.qAttitudeECI.Normalize(); + UpdateBodyMatrices(); + VState.qAttitudeLocal = Tl2b.GetQuaternion(); +} - // Save the value of the Lagrange multipliers to accelerate the convergence - // of the Gauss-Seidel algorithm at next iteration. - i = 0; - for (MultiplierIterator it=MultiplierIterator(GroundReactions); *it; ++it) - (*it)->value = lambda[i++]; +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - GroundReactions->UpdateForcesAndMoments(); +void FGPropagate::SetInertialVelocity(FGColumnVector3 Vi) { + VState.vInertialVelocity = Vi; + CalculateUVW(); + vVel = GetTb2l() * VState.vUVW; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGPropagate::SetInertialOrientation(FGQuaternion Qi) -{ - VState.qAttitudeECI = Qi; +void FGPropagate::SetInertialRates(FGColumnVector3 vRates) { + VState.vPQRi = Ti2b * vRates; + VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGPropagate::SetInertialVelocity(FGColumnVector3 Vi) +void FGPropagate::InitializeDerivatives(void) { - VState.vInertialVelocity = Vi; + // Make an initial run and set past values + CalculatePQRdot(); // Angular rate derivative + CalculateUVWdot(); // Translational rate derivative + ResolveFrictionForces(0.); // Update rate derivatives with friction forces + CalculateQuatdot(); // Angular orientation derivative + CalculateInertialVelocity(); // Translational position derivative + + // Initialize past values deques + VState.dqPQRdot.clear(); + VState.dqUVWidot.clear(); + VState.dqInertialVelocity.clear(); + VState.dqQtrndot.clear(); + for (int i=0; i<4; i++) { + VState.dqPQRdot.push_front(vPQRdot); + VState.dqUVWidot.push_front(vUVWdot); + VState.dqInertialVelocity.push_front(VState.vInertialVelocity); + VState.dqQtrndot.push_front(vQtrndot); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropagate::RecomputeLocalTerrainRadius(void) { - double t = FDMExec->GetSimTime(); - - // Get the LocalTerrain radius. - FDMExec->GetGroundCallback()->GetAGLevel(t, VState.vLocation, contactloc, dv, dv); - LocalTerrainRadius = contactloc.GetRadius(); + FGLocation contactloc; + FGColumnVector3 dv; + double t = FDMExec->GetSimTime(); + + // Get the LocalTerrain radius. + FDMExec->GetGroundCallback()->GetAGLevel(t, VState.vLocation, contactloc, dv, + LocalTerrainVelocity); + LocalTerrainRadius = contactloc.GetRadius(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropagate::SetTerrainElevation(double terrainElev) { - LocalTerrainRadius = terrainElev + SeaLevelRadius; - FDMExec->GetGroundCallback()->SetTerrainGeoCentRadius(LocalTerrainRadius); + LocalTerrainRadius = terrainElev + SeaLevelRadius; + FDMExec->GetGroundCallback()->SetTerrainGeoCentRadius(LocalTerrainRadius); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGPropagate::GetTerrainElevation(void) const { - return FDMExec->GetGroundCallback()->GetTerrainGeoCentRadius()-SeaLevelRadius; + return FDMExec->GetGroundCallback()->GetTerrainGeoCentRadius()-SeaLevelRadius; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -654,108 +672,108 @@ double FGPropagate::GetTerrainElevation(void) const // ahead of the sim and the associated calculations? const FGMatrix33& FGPropagate::GetTi2ec(void) { - return VState.vLocation.GetTi2ec(); + return VState.vLocation.GetTi2ec(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% const FGMatrix33& FGPropagate::GetTec2i(void) { - return VState.vLocation.GetTec2i(); + return VState.vLocation.GetTec2i(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropagate::SetAltitudeASL(double altASL) { - VState.vLocation.SetRadius( altASL + SeaLevelRadius ); + VState.vLocation.SetRadius( altASL + SeaLevelRadius ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGPropagate::GetLocalTerrainRadius(void) const { - return LocalTerrainRadius; + return LocalTerrainRadius; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGPropagate::GetDistanceAGL(void) const { - return VState.vLocation.GetRadius() - LocalTerrainRadius; + return VState.vLocation.GetRadius() - LocalTerrainRadius; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropagate::SetDistanceAGL(double tt) { - VState.vLocation.SetRadius( tt + LocalTerrainRadius ); + VState.vLocation.SetRadius( tt + LocalTerrainRadius ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropagate::bind(void) { - typedef double (FGPropagate::*PMF)(int) const; - - PropertyManager->Tie("velocities/h-dot-fps", this, &FGPropagate::Gethdot); - - PropertyManager->Tie("velocities/v-north-fps", this, eNorth, (PMF)&FGPropagate::GetVel); - PropertyManager->Tie("velocities/v-east-fps", this, eEast, (PMF)&FGPropagate::GetVel); - PropertyManager->Tie("velocities/v-down-fps", this, eDown, (PMF)&FGPropagate::GetVel); - - PropertyManager->Tie("velocities/u-fps", this, eU, (PMF)&FGPropagate::GetUVW); - PropertyManager->Tie("velocities/v-fps", this, eV, (PMF)&FGPropagate::GetUVW); - PropertyManager->Tie("velocities/w-fps", this, eW, (PMF)&FGPropagate::GetUVW); - - PropertyManager->Tie("velocities/p-rad_sec", this, eP, (PMF)&FGPropagate::GetPQR); - PropertyManager->Tie("velocities/q-rad_sec", this, eQ, (PMF)&FGPropagate::GetPQR); - PropertyManager->Tie("velocities/r-rad_sec", this, eR, (PMF)&FGPropagate::GetPQR); - - PropertyManager->Tie("velocities/pi-rad_sec", this, eP, (PMF)&FGPropagate::GetPQRi); - PropertyManager->Tie("velocities/qi-rad_sec", this, eQ, (PMF)&FGPropagate::GetPQRi); - PropertyManager->Tie("velocities/ri-rad_sec", this, eR, (PMF)&FGPropagate::GetPQRi); - - PropertyManager->Tie("velocities/eci-velocity-mag-fps", this, &FGPropagate::GetInertialVelocityMagnitude); - - PropertyManager->Tie("accelerations/pdot-rad_sec2", this, eP, (PMF)&FGPropagate::GetPQRdot); - PropertyManager->Tie("accelerations/qdot-rad_sec2", this, eQ, (PMF)&FGPropagate::GetPQRdot); - PropertyManager->Tie("accelerations/rdot-rad_sec2", this, eR, (PMF)&FGPropagate::GetPQRdot); - - PropertyManager->Tie("accelerations/udot-ft_sec2", this, eU, (PMF)&FGPropagate::GetUVWdot); - PropertyManager->Tie("accelerations/vdot-ft_sec2", this, eV, (PMF)&FGPropagate::GetUVWdot); - PropertyManager->Tie("accelerations/wdot-ft_sec2", this, eW, (PMF)&FGPropagate::GetUVWdot); - - PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::GetAltitudeASL, &FGPropagate::SetAltitudeASL, true); - PropertyManager->Tie("position/h-sl-meters", this, &FGPropagate::GetAltitudeASLmeters, &FGPropagate::SetAltitudeASLmeters, true); - PropertyManager->Tie("position/lat-gc-rad", this, &FGPropagate::GetLatitude, &FGPropagate::SetLatitude); - PropertyManager->Tie("position/long-gc-rad", this, &FGPropagate::GetLongitude, &FGPropagate::SetLongitude); - PropertyManager->Tie("position/lat-gc-deg", this, &FGPropagate::GetLatitudeDeg, &FGPropagate::SetLatitudeDeg); - PropertyManager->Tie("position/long-gc-deg", this, &FGPropagate::GetLongitudeDeg, &FGPropagate::SetLongitudeDeg); - PropertyManager->Tie("position/lat-geod-rad", this, &FGPropagate::GetGeodLatitudeRad); - PropertyManager->Tie("position/lat-geod-deg", this, &FGPropagate::GetGeodLatitudeDeg); - PropertyManager->Tie("position/geod-alt-ft", this, &FGPropagate::GetGeodeticAltitude); - PropertyManager->Tie("position/h-agl-ft", this, &FGPropagate::GetDistanceAGL, &FGPropagate::SetDistanceAGL); - PropertyManager->Tie("position/radius-to-vehicle-ft", this, &FGPropagate::GetRadius); - PropertyManager->Tie("position/terrain-elevation-asl-ft", this, - &FGPropagate::GetTerrainElevation, - &FGPropagate::SetTerrainElevation, false); - - PropertyManager->Tie("metrics/terrain-radius", this, &FGPropagate::GetLocalTerrainRadius); - - PropertyManager->Tie("attitude/phi-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler); - PropertyManager->Tie("attitude/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler); - PropertyManager->Tie("attitude/psi-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler); - - PropertyManager->Tie("attitude/roll-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler); - PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler); - PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler); - - PropertyManager->Tie("simulation/integrator/rate/rotational", (int*)&integrator_rotational_rate); - PropertyManager->Tie("simulation/integrator/rate/translational", (int*)&integrator_translational_rate); - PropertyManager->Tie("simulation/integrator/position/rotational", (int*)&integrator_rotational_position); - PropertyManager->Tie("simulation/integrator/position/translational", (int*)&integrator_translational_position); - PropertyManager->Tie("simulation/gravity-model", &gravType); + typedef double (FGPropagate::*PMF)(int) const; + + PropertyManager->Tie("velocities/h-dot-fps", this, &FGPropagate::Gethdot); + + PropertyManager->Tie("velocities/v-north-fps", this, eNorth, (PMF)&FGPropagate::GetVel); + PropertyManager->Tie("velocities/v-east-fps", this, eEast, (PMF)&FGPropagate::GetVel); + PropertyManager->Tie("velocities/v-down-fps", this, eDown, (PMF)&FGPropagate::GetVel); + + PropertyManager->Tie("velocities/u-fps", this, eU, (PMF)&FGPropagate::GetUVW); + PropertyManager->Tie("velocities/v-fps", this, eV, (PMF)&FGPropagate::GetUVW); + PropertyManager->Tie("velocities/w-fps", this, eW, (PMF)&FGPropagate::GetUVW); + + PropertyManager->Tie("velocities/p-rad_sec", this, eP, (PMF)&FGPropagate::GetPQR); + PropertyManager->Tie("velocities/q-rad_sec", this, eQ, (PMF)&FGPropagate::GetPQR); + PropertyManager->Tie("velocities/r-rad_sec", this, eR, (PMF)&FGPropagate::GetPQR); + + PropertyManager->Tie("velocities/pi-rad_sec", this, eP, (PMF)&FGPropagate::GetPQRi); + PropertyManager->Tie("velocities/qi-rad_sec", this, eQ, (PMF)&FGPropagate::GetPQRi); + PropertyManager->Tie("velocities/ri-rad_sec", this, eR, (PMF)&FGPropagate::GetPQRi); + + PropertyManager->Tie("velocities/eci-velocity-mag-fps", this, &FGPropagate::GetInertialVelocityMagnitude); + + PropertyManager->Tie("accelerations/pdot-rad_sec2", this, eP, (PMF)&FGPropagate::GetPQRdot); + PropertyManager->Tie("accelerations/qdot-rad_sec2", this, eQ, (PMF)&FGPropagate::GetPQRdot); + PropertyManager->Tie("accelerations/rdot-rad_sec2", this, eR, (PMF)&FGPropagate::GetPQRdot); + + PropertyManager->Tie("accelerations/udot-ft_sec2", this, eU, (PMF)&FGPropagate::GetUVWdot); + PropertyManager->Tie("accelerations/vdot-ft_sec2", this, eV, (PMF)&FGPropagate::GetUVWdot); + PropertyManager->Tie("accelerations/wdot-ft_sec2", this, eW, (PMF)&FGPropagate::GetUVWdot); + + PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::GetAltitudeASL, &FGPropagate::SetAltitudeASL, true); + PropertyManager->Tie("position/h-sl-meters", this, &FGPropagate::GetAltitudeASLmeters, &FGPropagate::SetAltitudeASLmeters, true); + PropertyManager->Tie("position/lat-gc-rad", this, &FGPropagate::GetLatitude, &FGPropagate::SetLatitude); + PropertyManager->Tie("position/long-gc-rad", this, &FGPropagate::GetLongitude, &FGPropagate::SetLongitude); + PropertyManager->Tie("position/lat-gc-deg", this, &FGPropagate::GetLatitudeDeg, &FGPropagate::SetLatitudeDeg); + PropertyManager->Tie("position/long-gc-deg", this, &FGPropagate::GetLongitudeDeg, &FGPropagate::SetLongitudeDeg); + PropertyManager->Tie("position/lat-geod-rad", this, &FGPropagate::GetGeodLatitudeRad); + PropertyManager->Tie("position/lat-geod-deg", this, &FGPropagate::GetGeodLatitudeDeg); + PropertyManager->Tie("position/geod-alt-ft", this, &FGPropagate::GetGeodeticAltitude); + PropertyManager->Tie("position/h-agl-ft", this, &FGPropagate::GetDistanceAGL, &FGPropagate::SetDistanceAGL); + PropertyManager->Tie("position/radius-to-vehicle-ft", this, &FGPropagate::GetRadius); + PropertyManager->Tie("position/terrain-elevation-asl-ft", this, + &FGPropagate::GetTerrainElevation, + &FGPropagate::SetTerrainElevation, false); + + PropertyManager->Tie("metrics/terrain-radius", this, &FGPropagate::GetLocalTerrainRadius); + + PropertyManager->Tie("attitude/phi-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler); + PropertyManager->Tie("attitude/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler); + PropertyManager->Tie("attitude/psi-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler); + + PropertyManager->Tie("attitude/roll-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler); + PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler); + PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler); + + PropertyManager->Tie("simulation/integrator/rate/rotational", (int*)&integrator_rotational_rate); + PropertyManager->Tie("simulation/integrator/rate/translational", (int*)&integrator_translational_rate); + PropertyManager->Tie("simulation/integrator/position/rotational", (int*)&integrator_rotational_position); + PropertyManager->Tie("simulation/integrator/position/translational", (int*)&integrator_translational_position); + PropertyManager->Tie("simulation/gravity-model", &gravType); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -779,143 +797,131 @@ void FGPropagate::bind(void) void FGPropagate::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGPropagate" << endl; - if (from == 1) cout << "Destroyed: FGPropagate" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 && from == 2) // Runtime state variables - { - cout << endl << fgblue << highint << left - << " Propagation Report (English units: ft, degrees) at simulation time " << FDMExec->GetSimTime() << " seconds" - << reset << endl; - cout << endl; - cout << highint << " Earth Position Angle (deg): " << setw(8) << setprecision(3) << reset - << Inertial->GetEarthPositionAngleDeg() << endl; - cout << endl; - cout << highint << " Body velocity (ft/sec): " << setw(8) << setprecision(3) << reset << VState.vUVW << endl; - cout << highint << " Local velocity (ft/sec): " << setw(8) << setprecision(3) << reset << vVel << endl; - cout << highint << " Inertial velocity (ft/sec): " << setw(8) << setprecision(3) << reset << VState.vInertialVelocity << endl; - cout << highint << " Inertial Position (ft): " << setw(10) << setprecision(3) << reset << VState.vInertialPosition << endl; - cout << highint << " Latitude (deg): " << setw(8) << setprecision(3) << reset << VState.vLocation.GetLatitudeDeg() << endl; - cout << highint << " Longitude (deg): " << setw(8) << setprecision(3) << reset << VState.vLocation.GetLongitudeDeg() << endl; - cout << highint << " Altitude ASL (ft): " << setw(8) << setprecision(3) << reset << GetAltitudeASL() << endl; - cout << highint << " Acceleration (NED, ft/sec^2): " << setw(8) << setprecision(3) << reset << Tb2l*GetUVWdot() << endl; - cout << endl; - cout << highint << " Matrix ECEF to Body (Orientation of Body with respect to ECEF): " - << reset << endl << Tec2b.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tec2b.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Body to ECEF (Orientation of ECEF with respect to Body):" - << reset << endl << Tb2ec.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tb2ec.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Local to Body (Orientation of Body with respect to Local):" - << reset << endl << Tl2b.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tl2b.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Body to Local (Orientation of Local with respect to Body):" - << reset << endl << Tb2l.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tb2l.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Local to ECEF (Orientation of ECEF with respect to Local):" - << reset << endl << Tl2ec.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tl2ec.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix ECEF to Local (Orientation of Local with respect to ECEF):" - << reset << endl << Tec2l.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tec2l.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix ECEF to Inertial (Orientation of Inertial with respect to ECEF):" - << reset << endl << Tec2i.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tec2i.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Inertial to ECEF (Orientation of ECEF with respect to Inertial):" - << reset << endl << Ti2ec.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Ti2ec.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Inertial to Body (Orientation of Body with respect to Inertial):" - << reset << endl << Ti2b.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Ti2b.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Body to Inertial (Orientation of Inertial with respect to Body):" - << reset << endl << Tb2i.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tb2i.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Inertial to Local (Orientation of Local with respect to Inertial):" - << reset << endl << Ti2l.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Ti2l.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Local to Inertial (Orientation of Inertial with respect to Local):" - << reset << endl << Tl2i.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tl2i.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << setprecision(6); // reset the output stream } - if (debug_lvl & 16) // Sanity checking - { - if (from == 2) // State sanity checking - { - if (fabs(VState.vPQR.Magnitude()) > 1000.0) - { - cerr << endl << "Vehicle rotation rate is excessive (>1000 rad/sec): " << VState.vPQR.Magnitude() << endl; - exit(-1); - } - if (fabs(VState.vUVW.Magnitude()) > 1.0e10) - { - cerr << endl << "Vehicle velocity is excessive (>1e10 ft/sec): " << VState.vUVW.Magnitude() << endl; - exit(-1); - } - if (fabs(GetDistanceAGL()) > 1e10) - { - cerr << endl << "Vehicle altitude is excessive (>1e10 ft): " << GetDistanceAGL() << endl; - exit(-1); - } - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGPropagate" << endl; + if (from == 1) cout << "Destroyed: FGPropagate" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 && from == 2) { // Runtime state variables + cout << endl << fgblue << highint << left + << " Propagation Report (English units: ft, degrees) at simulation time " << FDMExec->GetSimTime() << " seconds" + << reset << endl; + cout << endl; + cout << highint << " Earth Position Angle (deg): " << setw(8) << setprecision(3) << reset + << Inertial->GetEarthPositionAngleDeg() << endl; + cout << endl; + cout << highint << " Body velocity (ft/sec): " << setw(8) << setprecision(3) << reset << VState.vUVW << endl; + cout << highint << " Local velocity (ft/sec): " << setw(8) << setprecision(3) << reset << vVel << endl; + cout << highint << " Inertial velocity (ft/sec): " << setw(8) << setprecision(3) << reset << VState.vInertialVelocity << endl; + cout << highint << " Inertial Position (ft): " << setw(10) << setprecision(3) << reset << VState.vInertialPosition << endl; + cout << highint << " Latitude (deg): " << setw(8) << setprecision(3) << reset << VState.vLocation.GetLatitudeDeg() << endl; + cout << highint << " Longitude (deg): " << setw(8) << setprecision(3) << reset << VState.vLocation.GetLongitudeDeg() << endl; + cout << highint << " Altitude ASL (ft): " << setw(8) << setprecision(3) << reset << GetAltitudeASL() << endl; + cout << highint << " Acceleration (NED, ft/sec^2): " << setw(8) << setprecision(3) << reset << Tb2l*GetUVWdot() << endl; + cout << endl; + cout << highint << " Matrix ECEF to Body (Orientation of Body with respect to ECEF): " + << reset << endl << Tec2b.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Tec2b.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << highint << " Matrix Body to ECEF (Orientation of ECEF with respect to Body):" + << reset << endl << Tb2ec.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Tb2ec.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << highint << " Matrix Local to Body (Orientation of Body with respect to Local):" + << reset << endl << Tl2b.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Tl2b.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << highint << " Matrix Body to Local (Orientation of Local with respect to Body):" + << reset << endl << Tb2l.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Tb2l.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << highint << " Matrix Local to ECEF (Orientation of ECEF with respect to Local):" + << reset << endl << Tl2ec.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Tl2ec.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << highint << " Matrix ECEF to Local (Orientation of Local with respect to ECEF):" + << reset << endl << Tec2l.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Tec2l.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << highint << " Matrix ECEF to Inertial (Orientation of Inertial with respect to ECEF):" + << reset << endl << Tec2i.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Tec2i.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << highint << " Matrix Inertial to ECEF (Orientation of ECEF with respect to Inertial):" + << reset << endl << Ti2ec.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Ti2ec.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << highint << " Matrix Inertial to Body (Orientation of Body with respect to Inertial):" + << reset << endl << Ti2b.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Ti2b.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << highint << " Matrix Body to Inertial (Orientation of Inertial with respect to Body):" + << reset << endl << Tb2i.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Tb2i.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << highint << " Matrix Inertial to Local (Orientation of Local with respect to Inertial):" + << reset << endl << Ti2l.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Ti2l.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << highint << " Matrix Local to Inertial (Orientation of Inertial with respect to Local):" + << reset << endl << Tl2i.Dump("\t", " ") << endl; + cout << highint << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << reset << (Tl2i.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + cout << setprecision(6); // reset the output stream + } + if (debug_lvl & 16) { // Sanity checking + if (from == 2) { // State sanity checking + if (fabs(VState.vPQR.Magnitude()) > 1000.0) { + cerr << endl << "Vehicle rotation rate is excessive (>1000 rad/sec): " << VState.vPQR.Magnitude() << endl; + exit(-1); + } + if (fabs(VState.vUVW.Magnitude()) > 1.0e10) { + cerr << endl << "Vehicle velocity is excessive (>1e10 ft/sec): " << VState.vUVW.Magnitude() << endl; + exit(-1); + } + if (fabs(GetDistanceAGL()) > 1e10) { + cerr << endl << "Vehicle altitude is excessive (>1e10 ft): " << GetDistanceAGL() << endl; + exit(-1); + } } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/FGPropagate.h b/src/models/FGPropagate.h index 666d63556ad3f487ca791c084ec62265a840ac48..be8ebd224ba189a8bd2b2b84cde6b269c96296b3 100644 --- a/src/models/FGPropagate.h +++ b/src/models/FGPropagate.h @@ -49,14 +49,13 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.43 2010/07/25 15:35:11 jberndt Exp $" +#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.48 2010/09/18 22:48:12 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { using std::deque; class FGInitialCondition; @@ -79,18 +78,18 @@ CLASS DOCUMENTATION -Integrate accelerations and rates - Integration of rotational and translation position and rate can be + Integration of rotational and translation position and rate can be customized as needed or frozen by the selection of no integrator. The - selection of which integrator to use is done through the setting of + selection of which integrator to use is done through the setting of the associated property. There are four properties which can be set: - + @code simulation/integrator/rate/rotational simulation/integrator/rate/translational simulation/integrator/position/rotational simulation/integrator/position/translational @endcode - + Each of the integrators listed above can be set to one of the following values: @code @@ -103,699 +102,569 @@ CLASS DOCUMENTATION @endcode @author Jon S. Berndt, Mathias Froehlich - @version $Id: FGPropagate.h,v 1.43 2010/07/25 15:35:11 jberndt Exp $ + @version $Id: FGPropagate.h,v 1.48 2010/09/18 22:48:12 jberndt Exp $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGPropagate : public FGModel -{ +class FGPropagate : public FGModel { public: - /** The current vehicle state vector structure contains the translational and - angular position, and the translational and angular velocity. */ - struct VehicleState - { - /** Represents the current location of the vehicle in Earth centered Earth - fixed (ECEF) frame. - units ft */ - FGLocation vLocation; - - /** The velocity vector of the vehicle with respect to the ECEF frame, - expressed in the body system. - units ft/sec */ - FGColumnVector3 vUVW; - - /** The angular velocity vector for the vehicle relative to the ECEF frame, - expressed in the body frame. - units rad/sec */ - FGColumnVector3 vPQR; - - /** The angular velocity vector for the vehicle body frame relative to the - ECI frame, expressed in the body frame. - units rad/sec */ - FGColumnVector3 vPQRi; - - /** The current orientation of the vehicle, that is, the orientation of the - body frame relative to the local, NED frame. */ - FGQuaternion qAttitudeLocal; - - /** The current orientation of the vehicle, that is, the orientation of the - body frame relative to the inertial (ECI) frame. */ - FGQuaternion qAttitudeECI; - - FGColumnVector3 vInertialVelocity; - - FGColumnVector3 vInertialPosition; - - deque <FGColumnVector3> dqPQRdot; - deque <FGColumnVector3> dqUVWdot; - deque <FGColumnVector3> dqInertialVelocity; - deque <FGQuaternion> dqQtrndot; - }; - - /** Constructor. - The constructor initializes several variables, and sets the initial set - of integrators to use as follows: - - integrator, rotational rate = Adams Bashforth 2 - - integrator, translational rate = Adams Bashforth 2 - - integrator, rotational position = Trapezoidal - - integrator, translational position = Trapezoidal - @param Executive a pointer to the parent executive object */ - FGPropagate(FGFDMExec* Executive); - - /// Destructor - ~FGPropagate(); - - /// These define the indices use to select the various integrators. - enum eIntegrateType {eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3, eAdamsBashforth4}; - - /// These define the indices use to select the gravitation models. - enum eGravType {gtStandard, gtWGS84}; - - /** Initializes the FGPropagate class after instantiation and prior to first execution. - The base class FGModel::InitModel is called first, initializing pointers to the - other FGModel objects (and others). */ - bool InitModel(void); - - /** Runs the Propagate model; called by the Executive. - @return false if no error */ - bool Run(void); - - const FGQuaternion& GetQuaterniondot(void) const - { - return vQtrndot; - } - - /** Retrieves the velocity vector. - The vector returned is represented by an FGColumnVector reference. The vector - for the velocity in Local frame is organized (Vnorth, Veast, Vdown). The vector - is 1-based, so that the first element can be retrieved using the "()" operator. - In other words, vVel(1) is Vnorth. Various convenience enumerators are defined - in FGJSBBase. The relevant enumerators for the vector returned by this call are, - eNorth=1, eEast=2, eDown=3. - units ft/sec - @return The vehicle velocity vector with respect to the Earth centered frame, - expressed in Local horizontal frame. - */ - const FGColumnVector3& GetVel(void) const - { - return vVel; - } - - /** Retrieves the body frame vehicle velocity vector. - The vector returned is represented by an FGColumnVector reference. The vector - for the velocity in Body frame is organized (Vx, Vy, Vz). The vector - is 1-based, so that the first element can be retrieved using the "()" operator. - In other words, vUVW(1) is Vx. Various convenience enumerators are defined - in FGJSBBase. The relevant enumerators for the vector returned by this call are, - eX=1, eY=2, eZ=3. - units ft/sec - @return The body frame vehicle velocity vector in ft/sec. - */ - const FGColumnVector3& GetUVW(void) const - { - return VState.vUVW; - } - - /** Retrieves the body axis acceleration. - Retrieves the computed body axis accelerations based on the - applied forces and accounting for a rotating body frame. - The vector returned is represented by an FGColumnVector reference. The vector - for the acceleration in Body frame is organized (Ax, Ay, Az). The vector - is 1-based, so that the first element can be retrieved using the "()" operator. - In other words, vUVWdot(1) is Ax. Various convenience enumerators are defined - in FGJSBBase. The relevant enumerators for the vector returned by this call are, - eX=1, eY=2, eZ=3. - units ft/sec^2 - @return Body axis translational acceleration in ft/sec^2. - */ - const FGColumnVector3& GetUVWdot(void) const - { - return vUVWdot; - } - - /** Retrieves the body angular rates vector, relative to the ECEF frame. - Retrieves the body angular rates (p, q, r), which are calculated by integration - of the angular acceleration. - The vector returned is represented by an FGColumnVector reference. The vector - for the angular velocity in Body frame is organized (P, Q, R). The vector - is 1-based, so that the first element can be retrieved using the "()" operator. - In other words, vPQR(1) is P. Various convenience enumerators are defined - in FGJSBBase. The relevant enumerators for the vector returned by this call are, - eP=1, eQ=2, eR=3. - units rad/sec - @return The body frame angular rates in rad/sec. - */ - const FGColumnVector3& GetPQR(void) const - { - return VState.vPQR; - } - - /** Retrieves the body angular rates vector, relative to the ECI (inertial) frame. - Retrieves the body angular rates (p, q, r), which are calculated by integration - of the angular acceleration. - The vector returned is represented by an FGColumnVector reference. The vector - for the angular velocity in Body frame is organized (P, Q, R). The vector - is 1-based, so that the first element can be retrieved using the "()" operator. - In other words, vPQR(1) is P. Various convenience enumerators are defined - in FGJSBBase. The relevant enumerators for the vector returned by this call are, - eP=1, eQ=2, eR=3. - units rad/sec - @return The body frame inertial angular rates in rad/sec. - */ - const FGColumnVector3& GetPQRi(void) const - { - return VState.vPQRi; - } - - /** Retrieves the body axis angular acceleration vector. - Retrieves the body axis angular acceleration vector in rad/sec^2. The - angular acceleration vector is determined from the applied forces and - accounts for a rotating frame. - The vector returned is represented by an FGColumnVector reference. The vector - for the angular acceleration in Body frame is organized (Pdot, Qdot, Rdot). The vector - is 1-based, so that the first element can be retrieved using the "()" operator. - In other words, vPQRdot(1) is Pdot. Various convenience enumerators are defined - in FGJSBBase. The relevant enumerators for the vector returned by this call are, - eP=1, eQ=2, eR=3. - units rad/sec^2 - @return The angular acceleration vector. - */ - const FGColumnVector3& GetPQRdot(void) const - { - return vPQRdot; - } - - /** Retrieves the Euler angles that define the vehicle orientation. - Extracts the Euler angles from the quaternion that stores the orientation - in the Local frame. The order of rotation used is Yaw-Pitch-Roll. The - vector returned is represented by an FGColumnVector reference. The vector - for the Euler angles is organized (Phi, Theta, Psi). The vector - is 1-based, so that the first element can be retrieved using the "()" operator. - In other words, the returned vector item with subscript (1) is Phi. - Various convenience enumerators are defined in FGJSBBase. The relevant - enumerators for the vector returned by this call are, ePhi=1, eTht=2, ePsi=3. - units radians - @return The Euler angle vector, where the first item in the - vector is the angle about the X axis, the second is the - angle about the Y axis, and the third item is the angle - about the Z axis (Phi, Theta, Psi). - */ - const FGColumnVector3& GetEuler(void) const - { - return VState.qAttitudeLocal.GetEuler(); - } - - /** Retrieves a body frame velocity component. - Retrieves a body frame velocity component. The velocity returned is - extracted from the vUVW vector (an FGColumnVector). The vector for the - velocity in Body frame is organized (Vx, Vy, Vz). The vector is 1-based. - In other words, GetUVW(1) returns Vx. Various convenience enumerators - are defined in FGJSBBase. The relevant enumerators for the velocity - returned by this call are, eX=1, eY=2, eZ=3. - units ft/sec - @param idx the index of the velocity component desired (1-based). - @return The body frame velocity component. - */ - double GetUVW (int idx) const - { - return VState.vUVW(idx); - } - - /** Retrieves a body frame acceleration component. - Retrieves a body frame acceleration component. The acceleration returned - is extracted from the vUVWdot vector (an FGColumnVector). The vector for - the acceleration in Body frame is organized (Ax, Ay, Az). The vector is - 1-based. In other words, GetUVWdot(1) returns Ax. Various convenience - enumerators are defined in FGJSBBase. The relevant enumerators for the - acceleration returned by this call are, eX=1, eY=2, eZ=3. - units ft/sec^2 - @param idx the index of the acceleration component desired (1-based). - @return The body frame acceleration component. - */ - double GetUVWdot(int idx) const - { - return vUVWdot(idx); - } - - /** Retrieves a Local frame velocity component. - Retrieves a Local frame velocity component. The velocity returned is - extracted from the vVel vector (an FGColumnVector). The vector for the - velocity in Local frame is organized (Vnorth, Veast, Vdown). The vector - is 1-based. In other words, GetVel(1) returns Vnorth. Various convenience - enumerators are defined in FGJSBBase. The relevant enumerators for the - velocity returned by this call are, eNorth=1, eEast=2, eDown=3. - units ft/sec - @param idx the index of the velocity component desired (1-based). - @return The body frame velocity component. - */ - double GetVel(int idx) const - { - return vVel(idx); - } - - /** Retrieves the total inertial velocity in ft/sec. - */ - double GetInertialVelocityMagnitude(void) const - { - return VState.vInertialVelocity.Magnitude(); - } - - /** Retrieves the inertial velocity vector in ft/sec. - */ - const FGColumnVector3& GetInertialVelocity(void) const - { - return VState.vInertialVelocity; - } - - /** Retrieves the inertial position vector. - */ - const FGColumnVector3& GetInertialPosition(void) const - { - return VState.vInertialPosition; - } - - /** Returns the current altitude above sea level. - This function returns the altitude above sea level. - units ft - @return The current altitude above sea level in feet. - */ - double GetAltitudeASL(void) const - { - return VState.vLocation.GetRadius() - SeaLevelRadius; - } - - /** Returns the current altitude above sea level. - This function returns the altitude above sea level. - units meters - @return The current altitude above sea level in meters. - */ - double GetAltitudeASLmeters(void) const - { - return GetAltitudeASL()*fttom; - } - - /** Retrieves a body frame angular velocity component relative to the ECEF frame. - Retrieves a body frame angular velocity component. The angular velocity - returned is extracted from the vPQR vector (an FGColumnVector). The vector - for the angular velocity in Body frame is organized (P, Q, R). The vector - is 1-based. In other words, GetPQR(1) returns P (roll rate). Various - convenience enumerators are defined in FGJSBBase. The relevant enumerators - for the angular velocity returned by this call are, eP=1, eQ=2, eR=3. - units rad/sec - @param axis the index of the angular velocity component desired (1-based). - @return The body frame angular velocity component. - */ - double GetPQR(int axis) const - { - return VState.vPQR(axis); - } - - /** Retrieves a body frame angular velocity component relative to the ECI (inertial) frame. - Retrieves a body frame angular velocity component. The angular velocity - returned is extracted from the vPQR vector (an FGColumnVector). The vector - for the angular velocity in Body frame is organized (P, Q, R). The vector - is 1-based. In other words, GetPQR(1) returns P (roll rate). Various - convenience enumerators are defined in FGJSBBase. The relevant enumerators - for the angular velocity returned by this call are, eP=1, eQ=2, eR=3. - units rad/sec - @param axis the index of the angular velocity component desired (1-based). - @return The body frame angular velocity component. - */ - double GetPQRi(int axis) const - { - return VState.vPQRi(axis); - } - - /** Retrieves a body frame angular acceleration component. - Retrieves a body frame angular acceleration component. The angular - acceleration returned is extracted from the vPQRdot vector (an - FGColumnVector). The vector for the angular acceleration in Body frame - is organized (Pdot, Qdot, Rdot). The vector is 1-based. In other words, - GetPQRdot(1) returns Pdot (roll acceleration). Various convenience - enumerators are defined in FGJSBBase. The relevant enumerators for the - angular acceleration returned by this call are, eP=1, eQ=2, eR=3. - units rad/sec^2 - @param axis the index of the angular acceleration component desired (1-based). - @return The body frame angular acceleration component. - */ - double GetPQRdot(int axis) const - { - return vPQRdot(axis); - } - - /** Retrieves a vehicle Euler angle component. - Retrieves an Euler angle (Phi, Theta, or Psi) from the quaternion that - stores the vehicle orientation relative to the Local frame. The order of - rotations used is Yaw-Pitch-Roll. The Euler angle with subscript (1) is - Phi. Various convenience enumerators are defined in FGJSBBase. The - relevant enumerators for the Euler angle returned by this call are, - ePhi=1, eTht=2, ePsi=3 (e.g. GetEuler(eTht) returns Theta). - units radians - @return An Euler angle. - */ - double GetEuler(int axis) const - { - return VState.qAttitudeLocal.GetEuler(axis); - } - - /** Retrieves the cosine of a vehicle Euler angle component. - Retrieves the cosine of an Euler angle (Phi, Theta, or Psi) from the - quaternion that stores the vehicle orientation relative to the Local frame. - The order of rotations used is Yaw-Pitch-Roll. The Euler angle - with subscript (1) is Phi. Various convenience enumerators are defined in - FGJSBBase. The relevant enumerators for the Euler angle referred to in this - call are, ePhi=1, eTht=2, ePsi=3 (e.g. GetCosEuler(eTht) returns cos(theta)). - units none - @return The cosine of an Euler angle. - */ - double GetCosEuler(int idx) const - { - return VState.qAttitudeLocal.GetCosEuler(idx); - } - - /** Retrieves the sine of a vehicle Euler angle component. - Retrieves the sine of an Euler angle (Phi, Theta, or Psi) from the - quaternion that stores the vehicle orientation relative to the Local frame. - The order of rotations used is Yaw-Pitch-Roll. The Euler angle - with subscript (1) is Phi. Various convenience enumerators are defined in - FGJSBBase. The relevant enumerators for the Euler angle referred to in this - call are, ePhi=1, eTht=2, ePsi=3 (e.g. GetSinEuler(eTht) returns sin(theta)). - units none - @return The sine of an Euler angle. - */ - double GetSinEuler(int idx) const - { - return VState.qAttitudeLocal.GetSinEuler(idx); - } - - /** Returns the current altitude rate. - Returns the current altitude rate (rate of climb). - units ft/sec - @return The current rate of change in altitude. - */ - double Gethdot(void) const - { - return -vVel(eDown); - } - - /** Returns the "constant" LocalTerrainRadius. - The LocalTerrainRadius parameter is set by the calling application or set to - sea level + terrain elevation if JSBSim is running in standalone mode. - units feet - @return distance of the local terrain from the center of the earth. - */ - double GetLocalTerrainRadius(void) const; - - double GetSeaLevelRadius(void) const - { - return SeaLevelRadius; - } - double GetTerrainElevation(void) const; - double GetDistanceAGL(void) const; - double GetRadius(void) const - { - if (VState.vLocation.GetRadius() == 0) return 1.0; - else return VState.vLocation.GetRadius(); - } - double GetLongitude(void) const - { - return VState.vLocation.GetLongitude(); - } - double GetLatitude(void) const - { - return VState.vLocation.GetLatitude(); - } - - double GetGeodLatitudeRad(void) const - { - return VState.vLocation.GetGeodLatitudeRad(); - } - double GetGeodLatitudeDeg(void) const - { - return VState.vLocation.GetGeodLatitudeDeg(); - } - - double GetGeodeticAltitude(void) const - { - return VState.vLocation.GetGeodAltitude(); - } - - double GetLongitudeDeg(void) const - { - return VState.vLocation.GetLongitudeDeg(); - } - double GetLatitudeDeg(void) const - { - return VState.vLocation.GetLatitudeDeg(); - } - const FGLocation& GetLocation(void) const - { - return VState.vLocation; - } - - /** Retrieves the local-to-body transformation matrix. - The quaternion class, being the means by which the orientation of the - vehicle is stored, manages the local-to-body transformation matrix. - @return a reference to the local-to-body transformation matrix. */ - const FGMatrix33& GetTl2b(void) const - { - return VState.qAttitudeLocal.GetT(); - } - - /** Retrieves the body-to-local transformation matrix. - The quaternion class, being the means by which the orientation of the - vehicle is stored, manages the body-to-local transformation matrix. - @return a reference to the body-to-local matrix. */ - const FGMatrix33& GetTb2l(void) const - { - return VState.qAttitudeLocal.GetTInv(); - } - - /** Retrieves the ECEF-to-body transformation matrix. - @return a reference to the ECEF-to-body transformation matrix. */ - const FGMatrix33& GetTec2b(void) const - { - return Tec2b; - } - - /** Retrieves the body-to-ECEF transformation matrix. - @return a reference to the body-to-ECEF matrix. */ - const FGMatrix33& GetTb2ec(void) const - { - return Tb2ec; - } - - /** Retrieves the ECI-to-body transformation matrix. - @return a reference to the ECI-to-body transformation matrix. */ - const FGMatrix33& GetTi2b(void) const - { - return VState.qAttitudeECI.GetT(); - } - - /** Retrieves the body-to-ECI transformation matrix. - @return a reference to the body-to-ECI matrix. */ - const FGMatrix33& GetTb2i(void) const - { - return VState.qAttitudeECI.GetTInv(); - } - - /** Retrieves the ECEF-to-ECI transformation matrix. - @return a reference to the ECEF-to-ECI transformation matrix. */ - const FGMatrix33& GetTec2i(void); - - /** Retrieves the ECI-to-ECEF transformation matrix. - @return a reference to the ECI-to-ECEF matrix. */ - const FGMatrix33& GetTi2ec(void); - - /** Retrieves the ECEF-to-local transformation matrix. - Retrieves the ECEF-to-local transformation matrix. Note that the so-called - local from is also know as the NED frame (for North, East, Down). - @return a reference to the ECEF-to-local matrix. */ - const FGMatrix33& GetTec2l(void) const - { - return VState.vLocation.GetTec2l(); - } - - /** Retrieves the local-to-ECEF transformation matrix. - Retrieves the local-to-ECEF transformation matrix. Note that the so-called - local from is also know as the NED frame (for North, East, Down). - @return a reference to the local-to-ECEF matrix. */ - const FGMatrix33& GetTl2ec(void) const - { - return VState.vLocation.GetTl2ec(); - } - - /** Retrieves the local-to-inertial transformation matrix. - @return a reference to the local-to-inertial transformation matrix. */ - const FGMatrix33& GetTl2i(void) - { - return VState.vLocation.GetTl2i(); - } - - /** Retrieves the inertial-to-local transformation matrix. - @return a reference to the inertial-to-local matrix. */ - const FGMatrix33& GetTi2l(void) - { - return VState.vLocation.GetTi2l(); - } - - VehicleState* GetVState(void) - { - return &VState; - } - - void SetVState(VehicleState* vstate) - { - VState.vLocation = vstate->vLocation; - VState.vUVW = vstate->vUVW; - VState.vPQR = vstate->vPQR; - VState.qAttitudeLocal = vstate->qAttitudeLocal; - VState.qAttitudeECI = vstate->qAttitudeECI; - - VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0)); - VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0)); - VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0)); - VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0)); - } - - void SetInertialOrientation(FGQuaternion Qi); - void SetInertialVelocity(FGColumnVector3 Vi); - - const FGQuaternion GetQuaternion(void) const - { - return VState.qAttitudeLocal; - } - - void SetPQR(unsigned int i, double val) - { - if ((i>=1) && (i<=3) ) - VState.vPQR(i) = val; - } - - void SetUVW(unsigned int i, double val) - { - if ((i>=1) && (i<=3) ) - VState.vUVW(i) = val; - } + /** The current vehicle state vector structure contains the translational and + angular position, and the translational and angular velocity. */ + struct VehicleState { + /** Represents the current location of the vehicle in Earth centered Earth + fixed (ECEF) frame. + units ft */ + FGLocation vLocation; + + /** The velocity vector of the vehicle with respect to the ECEF frame, + expressed in the body system. + units ft/sec */ + FGColumnVector3 vUVW; + + /** The angular velocity vector for the vehicle relative to the ECEF frame, + expressed in the body frame. + units rad/sec */ + FGColumnVector3 vPQR; + + /** The angular velocity vector for the vehicle body frame relative to the + ECI frame, expressed in the body frame. + units rad/sec */ + FGColumnVector3 vPQRi; + + /** The current orientation of the vehicle, that is, the orientation of the + body frame relative to the local, NED frame. */ + FGQuaternion qAttitudeLocal; + + /** The current orientation of the vehicle, that is, the orientation of the + body frame relative to the inertial (ECI) frame. */ + FGQuaternion qAttitudeECI; + + FGColumnVector3 vInertialVelocity; + + FGColumnVector3 vInertialPosition; + + deque <FGColumnVector3> dqPQRdot; + deque <FGColumnVector3> dqUVWidot; + deque <FGColumnVector3> dqInertialVelocity; + deque <FGQuaternion> dqQtrndot; + }; + + /** Constructor. + The constructor initializes several variables, and sets the initial set + of integrators to use as follows: + - integrator, rotational rate = Adams Bashforth 2 + - integrator, translational rate = Adams Bashforth 2 + - integrator, rotational position = Trapezoidal + - integrator, translational position = Trapezoidal + @param Executive a pointer to the parent executive object */ + FGPropagate(FGFDMExec* Executive); + + /// Destructor + ~FGPropagate(); + + /// These define the indices use to select the various integrators. + enum eIntegrateType {eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3, eAdamsBashforth4}; + + /// These define the indices use to select the gravitation models. + enum eGravType {gtStandard, gtWGS84}; + + /** Initializes the FGPropagate class after instantiation and prior to first execution. + The base class FGModel::InitModel is called first, initializing pointers to the + other FGModel objects (and others). */ + bool InitModel(void); + + /** Runs the Propagate model; called by the Executive. + @return false if no error */ + bool Run(void); + + const FGQuaternion& GetQuaterniondot(void) const {return vQtrndot;} + + /** Retrieves the velocity vector. + The vector returned is represented by an FGColumnVector reference. The vector + for the velocity in Local frame is organized (Vnorth, Veast, Vdown). The vector + is 1-based, so that the first element can be retrieved using the "()" operator. + In other words, vVel(1) is Vnorth. Various convenience enumerators are defined + in FGJSBBase. The relevant enumerators for the vector returned by this call are, + eNorth=1, eEast=2, eDown=3. + units ft/sec + @return The vehicle velocity vector with respect to the Earth centered frame, + expressed in Local horizontal frame. + */ + const FGColumnVector3& GetVel(void) const { return vVel; } + + /** Retrieves the body frame vehicle velocity vector. + The vector returned is represented by an FGColumnVector reference. The vector + for the velocity in Body frame is organized (Vx, Vy, Vz). The vector + is 1-based, so that the first element can be retrieved using the "()" operator. + In other words, vUVW(1) is Vx. Various convenience enumerators are defined + in FGJSBBase. The relevant enumerators for the vector returned by this call are, + eX=1, eY=2, eZ=3. + units ft/sec + @return The body frame vehicle velocity vector in ft/sec. + */ + const FGColumnVector3& GetUVW(void) const { return VState.vUVW; } + + /** Retrieves the body axis acceleration. + Retrieves the computed body axis accelerations based on the + applied forces and accounting for a rotating body frame. + The vector returned is represented by an FGColumnVector reference. The vector + for the acceleration in Body frame is organized (Ax, Ay, Az). The vector + is 1-based, so that the first element can be retrieved using the "()" operator. + In other words, vUVWdot(1) is Ax. Various convenience enumerators are defined + in FGJSBBase. The relevant enumerators for the vector returned by this call are, + eX=1, eY=2, eZ=3. + units ft/sec^2 + @return Body axis translational acceleration in ft/sec^2. + */ + const FGColumnVector3& GetUVWdot(void) const { return vUVWdot; } + + /** Retrieves the body angular rates vector, relative to the ECEF frame. + Retrieves the body angular rates (p, q, r), which are calculated by integration + of the angular acceleration. + The vector returned is represented by an FGColumnVector reference. The vector + for the angular velocity in Body frame is organized (P, Q, R). The vector + is 1-based, so that the first element can be retrieved using the "()" operator. + In other words, vPQR(1) is P. Various convenience enumerators are defined + in FGJSBBase. The relevant enumerators for the vector returned by this call are, + eP=1, eQ=2, eR=3. + units rad/sec + @return The body frame angular rates in rad/sec. + */ + const FGColumnVector3& GetPQR(void) const {return VState.vPQR;} + + /** Retrieves the body angular rates vector, relative to the ECI (inertial) frame. + Retrieves the body angular rates (p, q, r), which are calculated by integration + of the angular acceleration. + The vector returned is represented by an FGColumnVector reference. The vector + for the angular velocity in Body frame is organized (P, Q, R). The vector + is 1-based, so that the first element can be retrieved using the "()" operator. + In other words, vPQR(1) is P. Various convenience enumerators are defined + in FGJSBBase. The relevant enumerators for the vector returned by this call are, + eP=1, eQ=2, eR=3. + units rad/sec + @return The body frame inertial angular rates in rad/sec. + */ + const FGColumnVector3& GetPQRi(void) const {return VState.vPQRi;} + + /** Retrieves the body axis angular acceleration vector. + Retrieves the body axis angular acceleration vector in rad/sec^2. The + angular acceleration vector is determined from the applied forces and + accounts for a rotating frame. + The vector returned is represented by an FGColumnVector reference. The vector + for the angular acceleration in Body frame is organized (Pdot, Qdot, Rdot). The vector + is 1-based, so that the first element can be retrieved using the "()" operator. + In other words, vPQRdot(1) is Pdot. Various convenience enumerators are defined + in FGJSBBase. The relevant enumerators for the vector returned by this call are, + eP=1, eQ=2, eR=3. + units rad/sec^2 + @return The angular acceleration vector. + */ + const FGColumnVector3& GetPQRdot(void) const {return vPQRdot;} + + /** Retrieves the Euler angles that define the vehicle orientation. + Extracts the Euler angles from the quaternion that stores the orientation + in the Local frame. The order of rotation used is Yaw-Pitch-Roll. The + vector returned is represented by an FGColumnVector reference. The vector + for the Euler angles is organized (Phi, Theta, Psi). The vector + is 1-based, so that the first element can be retrieved using the "()" operator. + In other words, the returned vector item with subscript (1) is Phi. + Various convenience enumerators are defined in FGJSBBase. The relevant + enumerators for the vector returned by this call are, ePhi=1, eTht=2, ePsi=3. + units radians + @return The Euler angle vector, where the first item in the + vector is the angle about the X axis, the second is the + angle about the Y axis, and the third item is the angle + about the Z axis (Phi, Theta, Psi). + */ + const FGColumnVector3& GetEuler(void) const { return VState.qAttitudeLocal.GetEuler(); } + + /** Retrieves a body frame velocity component. + Retrieves a body frame velocity component. The velocity returned is + extracted from the vUVW vector (an FGColumnVector). The vector for the + velocity in Body frame is organized (Vx, Vy, Vz). The vector is 1-based. + In other words, GetUVW(1) returns Vx. Various convenience enumerators + are defined in FGJSBBase. The relevant enumerators for the velocity + returned by this call are, eX=1, eY=2, eZ=3. + units ft/sec + @param idx the index of the velocity component desired (1-based). + @return The body frame velocity component. + */ + double GetUVW (int idx) const { return VState.vUVW(idx); } + + /** Retrieves a body frame acceleration component. + Retrieves a body frame acceleration component. The acceleration returned + is extracted from the vUVWdot vector (an FGColumnVector). The vector for + the acceleration in Body frame is organized (Ax, Ay, Az). The vector is + 1-based. In other words, GetUVWdot(1) returns Ax. Various convenience + enumerators are defined in FGJSBBase. The relevant enumerators for the + acceleration returned by this call are, eX=1, eY=2, eZ=3. + units ft/sec^2 + @param idx the index of the acceleration component desired (1-based). + @return The body frame acceleration component. + */ + double GetUVWdot(int idx) const { return vUVWdot(idx); } + + /** Retrieves a Local frame velocity component. + Retrieves a Local frame velocity component. The velocity returned is + extracted from the vVel vector (an FGColumnVector). The vector for the + velocity in Local frame is organized (Vnorth, Veast, Vdown). The vector + is 1-based. In other words, GetVel(1) returns Vnorth. Various convenience + enumerators are defined in FGJSBBase. The relevant enumerators for the + velocity returned by this call are, eNorth=1, eEast=2, eDown=3. + units ft/sec + @param idx the index of the velocity component desired (1-based). + @return The body frame velocity component. + */ + double GetVel(int idx) const { return vVel(idx); } + + /** Retrieves the total inertial velocity in ft/sec. + */ + double GetInertialVelocityMagnitude(void) const { return VState.vInertialVelocity.Magnitude(); } + + /** Retrieves the inertial velocity vector in ft/sec. + */ + const FGColumnVector3& GetInertialVelocity(void) const { return VState.vInertialVelocity; } + + /** Retrieves the inertial position vector. + */ + const FGColumnVector3& GetInertialPosition(void) const { return VState.vInertialPosition; } + + /** Returns the current altitude above sea level. + This function returns the altitude above sea level. + units ft + @return The current altitude above sea level in feet. + */ + double GetAltitudeASL(void) const { return VState.vLocation.GetRadius() - SeaLevelRadius; } + + /** Returns the current altitude above sea level. + This function returns the altitude above sea level. + units meters + @return The current altitude above sea level in meters. + */ + double GetAltitudeASLmeters(void) const { return GetAltitudeASL()*fttom;} + + /** Retrieves a body frame angular velocity component relative to the ECEF frame. + Retrieves a body frame angular velocity component. The angular velocity + returned is extracted from the vPQR vector (an FGColumnVector). The vector + for the angular velocity in Body frame is organized (P, Q, R). The vector + is 1-based. In other words, GetPQR(1) returns P (roll rate). Various + convenience enumerators are defined in FGJSBBase. The relevant enumerators + for the angular velocity returned by this call are, eP=1, eQ=2, eR=3. + units rad/sec + @param axis the index of the angular velocity component desired (1-based). + @return The body frame angular velocity component. + */ + double GetPQR(int axis) const {return VState.vPQR(axis);} + + /** Retrieves a body frame angular velocity component relative to the ECI (inertial) frame. + Retrieves a body frame angular velocity component. The angular velocity + returned is extracted from the vPQR vector (an FGColumnVector). The vector + for the angular velocity in Body frame is organized (P, Q, R). The vector + is 1-based. In other words, GetPQR(1) returns P (roll rate). Various + convenience enumerators are defined in FGJSBBase. The relevant enumerators + for the angular velocity returned by this call are, eP=1, eQ=2, eR=3. + units rad/sec + @param axis the index of the angular velocity component desired (1-based). + @return The body frame angular velocity component. + */ + double GetPQRi(int axis) const {return VState.vPQRi(axis);} + + /** Retrieves a body frame angular acceleration component. + Retrieves a body frame angular acceleration component. The angular + acceleration returned is extracted from the vPQRdot vector (an + FGColumnVector). The vector for the angular acceleration in Body frame + is organized (Pdot, Qdot, Rdot). The vector is 1-based. In other words, + GetPQRdot(1) returns Pdot (roll acceleration). Various convenience + enumerators are defined in FGJSBBase. The relevant enumerators for the + angular acceleration returned by this call are, eP=1, eQ=2, eR=3. + units rad/sec^2 + @param axis the index of the angular acceleration component desired (1-based). + @return The body frame angular acceleration component. + */ + double GetPQRdot(int axis) const {return vPQRdot(axis);} + + /** Retrieves a vehicle Euler angle component. + Retrieves an Euler angle (Phi, Theta, or Psi) from the quaternion that + stores the vehicle orientation relative to the Local frame. The order of + rotations used is Yaw-Pitch-Roll. The Euler angle with subscript (1) is + Phi. Various convenience enumerators are defined in FGJSBBase. The + relevant enumerators for the Euler angle returned by this call are, + ePhi=1, eTht=2, ePsi=3 (e.g. GetEuler(eTht) returns Theta). + units radians + @return An Euler angle. + */ + double GetEuler(int axis) const { return VState.qAttitudeLocal.GetEuler(axis); } + + /** Retrieves the cosine of a vehicle Euler angle component. + Retrieves the cosine of an Euler angle (Phi, Theta, or Psi) from the + quaternion that stores the vehicle orientation relative to the Local frame. + The order of rotations used is Yaw-Pitch-Roll. The Euler angle + with subscript (1) is Phi. Various convenience enumerators are defined in + FGJSBBase. The relevant enumerators for the Euler angle referred to in this + call are, ePhi=1, eTht=2, ePsi=3 (e.g. GetCosEuler(eTht) returns cos(theta)). + units none + @return The cosine of an Euler angle. + */ + double GetCosEuler(int idx) const { return VState.qAttitudeLocal.GetCosEuler(idx); } + + /** Retrieves the sine of a vehicle Euler angle component. + Retrieves the sine of an Euler angle (Phi, Theta, or Psi) from the + quaternion that stores the vehicle orientation relative to the Local frame. + The order of rotations used is Yaw-Pitch-Roll. The Euler angle + with subscript (1) is Phi. Various convenience enumerators are defined in + FGJSBBase. The relevant enumerators for the Euler angle referred to in this + call are, ePhi=1, eTht=2, ePsi=3 (e.g. GetSinEuler(eTht) returns sin(theta)). + units none + @return The sine of an Euler angle. + */ + double GetSinEuler(int idx) const { return VState.qAttitudeLocal.GetSinEuler(idx); } + + /** Returns the current altitude rate. + Returns the current altitude rate (rate of climb). + units ft/sec + @return The current rate of change in altitude. + */ + double Gethdot(void) const { return -vVel(eDown); } + + /** Returns the "constant" LocalTerrainRadius. + The LocalTerrainRadius parameter is set by the calling application or set to + sea level + terrain elevation if JSBSim is running in standalone mode. + units feet + @return distance of the local terrain from the center of the earth. + */ + double GetLocalTerrainRadius(void) const; + + double GetSeaLevelRadius(void) const { return SeaLevelRadius; } + double GetTerrainElevation(void) const; + double GetDistanceAGL(void) const; + double GetRadius(void) const { + if (VState.vLocation.GetRadius() == 0) return 1.0; + else return VState.vLocation.GetRadius(); + } + double GetLongitude(void) const { return VState.vLocation.GetLongitude(); } + double GetLatitude(void) const { return VState.vLocation.GetLatitude(); } + + double GetGeodLatitudeRad(void) const { return VState.vLocation.GetGeodLatitudeRad(); } + double GetGeodLatitudeDeg(void) const { return VState.vLocation.GetGeodLatitudeDeg(); } + + double GetGeodeticAltitude(void) const { return VState.vLocation.GetGeodAltitude(); } + + double GetLongitudeDeg(void) const { return VState.vLocation.GetLongitudeDeg(); } + double GetLatitudeDeg(void) const { return VState.vLocation.GetLatitudeDeg(); } + const FGLocation& GetLocation(void) const { return VState.vLocation; } + + /** Retrieves the local-to-body transformation matrix. + The quaternion class, being the means by which the orientation of the + vehicle is stored, manages the local-to-body transformation matrix. + @return a reference to the local-to-body transformation matrix. */ + const FGMatrix33& GetTl2b(void) const { return VState.qAttitudeLocal.GetT(); } + + /** Retrieves the body-to-local transformation matrix. + The quaternion class, being the means by which the orientation of the + vehicle is stored, manages the body-to-local transformation matrix. + @return a reference to the body-to-local matrix. */ + const FGMatrix33& GetTb2l(void) const { return VState.qAttitudeLocal.GetTInv(); } + + /** Retrieves the ECEF-to-body transformation matrix. + @return a reference to the ECEF-to-body transformation matrix. */ + const FGMatrix33& GetTec2b(void) const { return Tec2b; } + + /** Retrieves the body-to-ECEF transformation matrix. + @return a reference to the body-to-ECEF matrix. */ + const FGMatrix33& GetTb2ec(void) const { return Tb2ec; } + + /** Retrieves the ECI-to-body transformation matrix. + @return a reference to the ECI-to-body transformation matrix. */ + const FGMatrix33& GetTi2b(void) const { return VState.qAttitudeECI.GetT(); } + + /** Retrieves the body-to-ECI transformation matrix. + @return a reference to the body-to-ECI matrix. */ + const FGMatrix33& GetTb2i(void) const { return VState.qAttitudeECI.GetTInv(); } + + /** Retrieves the ECEF-to-ECI transformation matrix. + @return a reference to the ECEF-to-ECI transformation matrix. */ + const FGMatrix33& GetTec2i(void); + + /** Retrieves the ECI-to-ECEF transformation matrix. + @return a reference to the ECI-to-ECEF matrix. */ + const FGMatrix33& GetTi2ec(void); + + /** Retrieves the ECEF-to-local transformation matrix. + Retrieves the ECEF-to-local transformation matrix. Note that the so-called + local from is also know as the NED frame (for North, East, Down). + @return a reference to the ECEF-to-local matrix. */ + const FGMatrix33& GetTec2l(void) const { return VState.vLocation.GetTec2l(); } + + /** Retrieves the local-to-ECEF transformation matrix. + Retrieves the local-to-ECEF transformation matrix. Note that the so-called + local from is also know as the NED frame (for North, East, Down). + @return a reference to the local-to-ECEF matrix. */ + const FGMatrix33& GetTl2ec(void) const { return VState.vLocation.GetTl2ec(); } + + /** Retrieves the local-to-inertial transformation matrix. + @return a reference to the local-to-inertial transformation matrix. */ + const FGMatrix33& GetTl2i(void) { return VState.vLocation.GetTl2i(); } + + /** Retrieves the inertial-to-local transformation matrix. + @return a reference to the inertial-to-local matrix. */ + const FGMatrix33& GetTi2l(void) { return VState.vLocation.GetTi2l(); } + + VehicleState* GetVState(void) { return &VState; } + + void SetVState(VehicleState* vstate) { + VState.vLocation = vstate->vLocation; + UpdateLocationMatrices(); + SetInertialOrientation(vstate->qAttitudeECI); + VehicleRadius = GetRadius(); + VState.vUVW = vstate->vUVW; + vVel = GetTb2l() * VState.vUVW; + VState.vPQR = vstate->vPQR; + VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth; + VState.vInertialPosition = vstate->vInertialPosition; + + InitializeDerivatives(); + } + + void InitializeDerivatives(void); + + void SetInertialOrientation(FGQuaternion Qi); + void SetInertialVelocity(FGColumnVector3 Vi); + void SetInertialRates(FGColumnVector3 vRates); + + const FGQuaternion GetQuaternion(void) const { return VState.qAttitudeLocal; } + + void SetPQR(unsigned int i, double val) { + if ((i>=1) && (i<=3) ) + VState.vPQR(i) = val; + } + + void SetUVW(unsigned int i, double val) { + if ((i>=1) && (i<=3) ) + VState.vUVW(i) = val; + } // SET functions - void SetLongitude(double lon) - { - VState.vLocation.SetLongitude(lon); - } - void SetLongitudeDeg(double lon) - { - SetLongitude(lon*degtorad); - } - void SetLatitude(double lat) - { - VState.vLocation.SetLatitude(lat); - } - void SetLatitudeDeg(double lat) - { - SetLatitude(lat*degtorad); - } - void SetRadius(double r) - { - VState.vLocation.SetRadius(r); - } - void SetLocation(const FGLocation& l) - { - VState.vLocation = l; - } - void SetAltitudeASL(double altASL); - void SetAltitudeASLmeters(double altASL) - { - SetAltitudeASL(altASL/fttom); - } - void SetSeaLevelRadius(double tt) - { - SeaLevelRadius = tt; - } - void SetTerrainElevation(double tt); - void SetDistanceAGL(double tt); - void SetInitialState(const FGInitialCondition *); - void RecomputeLocalTerrainRadius(void); - - void NudgeBodyLocation(FGColumnVector3 deltaLoc) - { - vDeltaXYZEC = GetTb2ec()*deltaLoc; - VState.vLocation -= vDeltaXYZEC; - } - - struct LagrangeMultiplier - { - FGColumnVector3 ForceJacobian; - FGColumnVector3 MomentJacobian; - double Min; - double Max; - double value; - }; + void SetLongitude(double lon) { + VState.vLocation.SetLongitude(lon); + VState.vInertialPosition = GetTec2i() * VState.vLocation; + UpdateLocationMatrices(); + } + void SetLongitudeDeg(double lon) { SetLongitude(lon*degtorad); } + void SetLatitude(double lat) { + VState.vLocation.SetLatitude(lat); + VState.vInertialPosition = GetTec2i() * VState.vLocation; + UpdateLocationMatrices(); + } + void SetLatitudeDeg(double lat) { SetLatitude(lat*degtorad); } + void SetRadius(double r) { + VState.vLocation.SetRadius(r); + VState.vInertialPosition = GetTec2i() * VState.vLocation; + UpdateLocationMatrices(); + } + void SetLocation(const FGLocation& l) { + VState.vLocation = l; + VState.vInertialPosition = GetTec2i() * VState.vLocation; + UpdateLocationMatrices(); + } + void SetLocation(const FGColumnVector3& l) { + VState.vLocation = l; + VState.vInertialPosition = GetTec2i() * VState.vLocation; + UpdateLocationMatrices(); + } + void SetAltitudeASL(double altASL); + void SetAltitudeASLmeters(double altASL) {SetAltitudeASL(altASL/fttom);} + void SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; } + void SetTerrainElevation(double tt); + void SetDistanceAGL(double tt); + void SetInitialState(const FGInitialCondition *); + void SetPosition(const double Lon, const double Lat, const double Radius) { + VState.vLocation.SetPosition(Lon, Lat, Radius); + VState.vInertialPosition = GetTec2i() * VState.vLocation; + VehicleRadius = GetRadius(); + UpdateLocationMatrices(); + } + + void RecomputeLocalTerrainRadius(void); + + void NudgeBodyLocation(FGColumnVector3 deltaLoc) { + vDeltaXYZEC = GetTb2ec()*deltaLoc; + VState.vLocation -= vDeltaXYZEC; + } + + struct LagrangeMultiplier { + FGColumnVector3 ForceJacobian; + FGColumnVector3 MomentJacobian; + double Min; + double Max; + double value; + }; private: // state vector - struct VehicleState VState; - - FGColumnVector3 vVel; - FGColumnVector3 vPQRdot; - FGColumnVector3 vUVWdot; - FGColumnVector3 vInertialVelocity; - FGColumnVector3 vLocation; - FGColumnVector3 vDeltaXYZEC; - FGColumnVector3 vGravAccel; - FGColumnVector3 vOmegaEarth; // The Earth angular velocity vector - FGQuaternion vQtrndot; - FGMatrix33 Tec2b; - FGMatrix33 Tb2ec; - FGMatrix33 Tl2b; // local to body frame matrix copy for immediate local use - FGMatrix33 Tb2l; // body to local frame matrix copy for immediate local use - FGMatrix33 Tl2ec; // local to ECEF matrix copy for immediate local use - FGMatrix33 Tec2l; // ECEF to local frame matrix copy for immediate local use - FGMatrix33 Tec2i; // ECEF to ECI frame matrix copy for immediate local use - FGMatrix33 Ti2ec; // ECI to ECEF frame matrix copy for immediate local use - FGMatrix33 Ti2b; // ECI to body frame rotation matrix - FGMatrix33 Tb2i; // body to ECI frame rotation matrix - FGMatrix33 Ti2l; - FGMatrix33 Tl2i; - FGLocation contactloc; - FGColumnVector3 dv; - - double LocalTerrainRadius, SeaLevelRadius, VehicleRadius; - double radInv; - eIntegrateType integrator_rotational_rate; - eIntegrateType integrator_translational_rate; - eIntegrateType integrator_rotational_position; - eIntegrateType integrator_translational_position; - int gravType; - - void CalculatePQRdot(void); - void CalculateQuatdot(void); - void CalculateInertialVelocity(void); - void CalculateUVWdot(void); - - void Integrate( FGColumnVector3& Integrand, - FGColumnVector3& Val, - deque <FGColumnVector3>& ValDot, - double dt, - eIntegrateType integration_type); - - void Integrate( FGQuaternion& Integrand, - FGQuaternion& Val, - deque <FGQuaternion>& ValDot, - double dt, - eIntegrateType integration_type); - - void ResolveFrictionForces(double dt); - - void bind(void); - void Debug(int from); + struct VehicleState VState; + + FGColumnVector3 vVel; + FGColumnVector3 vPQRdot; + FGColumnVector3 vUVWdot, vUVWidot; + FGColumnVector3 vInertialVelocity; + FGColumnVector3 vLocation; + FGColumnVector3 vDeltaXYZEC; + FGColumnVector3 vGravAccel; + FGColumnVector3 vOmegaEarth; // The Earth angular velocity vector + FGQuaternion vQtrndot; + FGMatrix33 Tec2b; + FGMatrix33 Tb2ec; + FGMatrix33 Tl2b; // local to body frame matrix copy for immediate local use + FGMatrix33 Tb2l; // body to local frame matrix copy for immediate local use + FGMatrix33 Tl2ec; // local to ECEF matrix copy for immediate local use + FGMatrix33 Tec2l; // ECEF to local frame matrix copy for immediate local use + FGMatrix33 Tec2i; // ECEF to ECI frame matrix copy for immediate local use + FGMatrix33 Ti2ec; // ECI to ECEF frame matrix copy for immediate local use + FGMatrix33 Ti2b; // ECI to body frame rotation matrix + FGMatrix33 Tb2i; // body to ECI frame rotation matrix + FGMatrix33 Ti2l; + FGMatrix33 Tl2i; + + double LocalTerrainRadius, SeaLevelRadius, VehicleRadius; + FGColumnVector3 LocalTerrainVelocity; + eIntegrateType integrator_rotational_rate; + eIntegrateType integrator_translational_rate; + eIntegrateType integrator_rotational_position; + eIntegrateType integrator_translational_position; + int gravType; + + void CalculatePQRdot(void); + void CalculateQuatdot(void); + void CalculateInertialVelocity(void); + void CalculateUVW(void); + void CalculateUVWdot(void); + + void Integrate( FGColumnVector3& Integrand, + FGColumnVector3& Val, + deque <FGColumnVector3>& ValDot, + double dt, + eIntegrateType integration_type); + + void Integrate( FGQuaternion& Integrand, + FGQuaternion& Val, + deque <FGQuaternion>& ValDot, + double dt, + eIntegrateType integration_type); + + void ResolveFrictionForces(double dt); + + void UpdateLocationMatrices(void); + void UpdateBodyMatrices(void); + + void bind(void); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/FGPropulsion.cpp b/src/models/FGPropulsion.cpp index 515ee136d85aae17ef294bdf9a743ca4e9a8dfc3..f0fbe04b37650439eed87baf596331df6bbcbcd7 100644 --- a/src/models/FGPropulsion.cpp +++ b/src/models/FGPropulsion.cpp @@ -63,10 +63,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.39 2010/02/25 05:21:36 jberndt Exp $"; +static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.40 2010/09/07 00:40:03 jberndt Exp $"; static const char *IdHdr = ID_PROPULSION; extern short debug_lvl; @@ -78,669 +77,591 @@ CLASS IMPLEMENTATION FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec) { - Name = "FGPropulsion"; - - InitializedEngines = 0; - numSelectedFuelTanks = numSelectedOxiTanks = 0; - numTanks = numEngines = 0; - numOxiTanks = numFuelTanks = 0; - ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ... - tankJ.InitMatrix(); - refuel = dump = false; - DumpRate = 0.0; - fuel_freeze = false; - TotalFuelQuantity = 0.0; - IsBound = - HavePistonEngine = - HaveTurbineEngine = - HaveRocketEngine = - HaveTurboPropEngine = - HaveElectricEngine = false; - HasInitializedEngines = false; - - Debug(0); + Name = "FGPropulsion"; + + InitializedEngines = 0; + numSelectedFuelTanks = numSelectedOxiTanks = 0; + numTanks = numEngines = 0; + numOxiTanks = numFuelTanks = 0; + ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ... + tankJ.InitMatrix(); + refuel = dump = false; + DumpRate = 0.0; + fuel_freeze = false; + TotalFuelQuantity = 0.0; + IsBound = + HavePistonEngine = + HaveTurbineEngine = + HaveRocketEngine = + HaveTurboPropEngine = + HaveElectricEngine = false; + HasInitializedEngines = false; + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGPropulsion::~FGPropulsion() { - for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i]; - Engines.clear(); - for (unsigned int i=0; i<Tanks.size(); i++) delete Tanks[i]; - Tanks.clear(); - Debug(1); + for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i]; + Engines.clear(); + for (unsigned int i=0; i<Tanks.size(); i++) delete Tanks[i]; + Tanks.clear(); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPropulsion::InitModel(void) { - if (!FGModel::InitModel()) return false; - - for (unsigned int i=0; i<numTanks; i++) Tanks[i]->ResetToIC(); - - for (unsigned int i=0; i<numEngines; i++) - { - switch (Engines[i]->GetType()) - { - case FGEngine::etPiston: - ((FGPiston*)Engines[i])->ResetToIC(); - if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i); - break; - case FGEngine::etTurbine: - ((FGTurbine*)Engines[i])->ResetToIC(); - if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i); - break; - default: - break; - } - } - - return true; + if (!FGModel::InitModel()) return false; + + for (unsigned int i=0; i<numTanks; i++) Tanks[i]->ResetToIC(); + + for (unsigned int i=0; i<numEngines; i++) { + switch (Engines[i]->GetType()) { + case FGEngine::etPiston: + ((FGPiston*)Engines[i])->ResetToIC(); + if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i); + break; + case FGEngine::etTurbine: + ((FGTurbine*)Engines[i])->ResetToIC(); + if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i); + break; + default: + break; + } + } + + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPropulsion::Run(void) { - unsigned int i; + unsigned int i; - if (FGModel::Run()) return true; - if (FDMExec->Holding()) return false; + if (FGModel::Run()) return true; + if (FDMExec->Holding()) return false; - RunPreFunctions(); + RunPreFunctions(); - double dt = FDMExec->GetDeltaT(); + double dt = FDMExec->GetDeltaT(); - vForces.InitMatrix(); - vMoments.InitMatrix(); + vForces.InitMatrix(); + vMoments.InitMatrix(); - for (i=0; i<numEngines; i++) - { - Engines[i]->Calculate(); - vForces += Engines[i]->GetBodyForces(); // sum body frame forces - vMoments += Engines[i]->GetMoments(); // sum body frame moments - } + for (i=0; i<numEngines; i++) { + Engines[i]->Calculate(); + vForces += Engines[i]->GetBodyForces(); // sum body frame forces + vMoments += Engines[i]->GetMoments(); // sum body frame moments + } - TotalFuelQuantity = 0.0; - for (i=0; i<numTanks; i++) - { - Tanks[i]->Calculate( dt * rate ); - if (Tanks[i]->GetType() == FGTank::ttFUEL) - { - TotalFuelQuantity += Tanks[i]->GetContents(); - } + TotalFuelQuantity = 0.0; + for (i=0; i<numTanks; i++) { + Tanks[i]->Calculate( dt * rate ); + if (Tanks[i]->GetType() == FGTank::ttFUEL) { + TotalFuelQuantity += Tanks[i]->GetContents(); } + } - if (refuel) DoRefuel( dt * rate ); - if (dump) DumpFuel( dt * rate ); + if (refuel) DoRefuel( dt * rate ); + if (dump) DumpFuel( dt * rate ); - RunPostFunctions(); + RunPostFunctions(); - return false; + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPropulsion::GetSteadyState(void) { - double currentThrust = 0, lastThrust = -1; - int steady_count = 0, j = 0; - bool steady = false; + double currentThrust = 0, lastThrust = -1; + int steady_count = 0, j = 0; + bool steady = false; - vForces.InitMatrix(); - vMoments.InitMatrix(); + vForces.InitMatrix(); + vMoments.InitMatrix(); - if (!FGModel::Run()) - { - for (unsigned int i=0; i<numEngines; i++) - { + if (!FGModel::Run()) { + for (unsigned int i=0; i<numEngines; i++) { // cout << " Finding steady state for engine " << i << endl; - Engines[i]->SetTrimMode(true); - steady=false; - steady_count=0; - j=0; - while (!steady && j < 6000) - { - Engines[i]->Calculate(); - lastThrust = currentThrust; - currentThrust = Engines[i]->GetThruster()->GetThrust(); - if (fabs(lastThrust-currentThrust) < 0.0001) - { - steady_count++; - if (steady_count > 120) - { - steady=true; + Engines[i]->SetTrimMode(true); + steady=false; + steady_count=0; + j=0; + while (!steady && j < 6000) { + Engines[i]->Calculate(); + lastThrust = currentThrust; + currentThrust = Engines[i]->GetThruster()->GetThrust(); + if (fabs(lastThrust-currentThrust) < 0.0001) { + steady_count++; + if (steady_count > 120) { + steady=true; // cout << " Steady state found at thrust: " << currentThrust << " lbs." << endl; - } - } - else - { - steady_count=0; - } - j++; - } + } + } else { + steady_count=0; + } + j++; + } // if (j >= 6000) { // cout << " Could not find a steady state for this engine." << endl; // } - vForces += Engines[i]->GetBodyForces(); // sum body frame forces - vMoments += Engines[i]->GetMoments(); // sum body frame moments - Engines[i]->SetTrimMode(false); - } - - return false; - } - else - { - return true; + vForces += Engines[i]->GetBodyForces(); // sum body frame forces + vMoments += Engines[i]->GetMoments(); // sum body frame moments + Engines[i]->SetTrimMode(false); } + + return false; + } else { + return true; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropulsion::InitRunning(int n) { - if (n > 0) // A specific engine is supposed to be initialized - { + if (n > 0) { // A specific engine is supposed to be initialized - if (n >= (int)GetNumEngines() ) - { - cerr << "Tried to initialize a non-existent engine!" << endl; - throw; - } - FCS->SetThrottleCmd(n,1); - FCS->SetMixtureCmd(n,1); - GetEngine(n)->InitRunning(); - GetSteadyState(); + if (n >= (int)GetNumEngines() ) { + cerr << "Tried to initialize a non-existent engine!" << endl; + throw; + } + FCS->SetThrottleCmd(n,1); + FCS->SetMixtureCmd(n,1); + GetEngine(n)->InitRunning(); + GetSteadyState(); - InitializedEngines = 1 << n; - HasInitializedEngines = true; + InitializedEngines = 1 << n; + HasInitializedEngines = true; - } - else if (n < 0) // -1 refers to "All Engines" - { - - for (unsigned int i=0; i<GetNumEngines(); i++) - { - FCS->SetThrottleCmd(i,1); - FCS->SetMixtureCmd(i,1); - GetEngine(i)->InitRunning(); - } - GetSteadyState(); - InitializedEngines = -1; - HasInitializedEngines = true; + } else if (n < 0) { // -1 refers to "All Engines" + for (unsigned int i=0; i<GetNumEngines(); i++) { + FCS->SetThrottleCmd(i,1); + FCS->SetMixtureCmd(i,1); + GetEngine(i)->InitRunning(); } - else if (n == 0) // No engines are to be initialized - { - // Do nothing - } + GetSteadyState(); + InitializedEngines = -1; + HasInitializedEngines = true; + + } else if (n == 0) { // No engines are to be initialized + // Do nothing + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPropulsion::Load(Element* el) { - string type, engine_filename; - bool ThrottleAdded = false; - - Debug(2); - - FGModel::Load(el); // Perform base class Load. - - // Process tank definitions first to establish the number of fuel tanks - - Element* tank_element = el->FindElement("tank"); - while (tank_element) - { - Tanks.push_back(new FGTank(FDMExec, tank_element, numTanks)); - if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++; - else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++; - else - { - cerr << "Unknown tank type specified." << endl; - return false; - } - numTanks++; - tank_element = el->FindNextElement("tank"); - } - numSelectedFuelTanks = numFuelTanks; - numSelectedOxiTanks = numOxiTanks; - - Element* engine_element = el->FindElement("engine"); - while (engine_element) - { - engine_filename = engine_element->GetAttributeValue("file"); - - if (engine_filename.empty()) - { - cerr << "Engine definition did not supply an engine file." << endl; - return false; - } - - engine_filename = FindEngineFullPathname(engine_filename); - document = LoadXMLDocument(engine_filename); - document->SetParent(engine_element); - - type = document->GetName(); - if (type == "piston_engine") - { - HavePistonEngine = true; - if (!IsBound) bind(); - Engines.push_back(new FGPiston(FDMExec, document, numEngines)); - } - else if (type == "turbine_engine") - { - HaveTurbineEngine = true; - if (!IsBound) bind(); - Engines.push_back(new FGTurbine(FDMExec, document, numEngines)); - } - else if (type == "turboprop_engine") - { - HaveTurboPropEngine = true; - if (!IsBound) bind(); - Engines.push_back(new FGTurboProp(FDMExec, document, numEngines)); - } - else if (type == "rocket_engine") - { - HaveRocketEngine = true; - if (!IsBound) bind(); - Engines.push_back(new FGRocket(FDMExec, document, numEngines)); - } - else if (type == "electric_engine") - { - HaveElectricEngine = true; - if (!IsBound) bind(); - Engines.push_back(new FGElectric(FDMExec, document, numEngines)); - } - else - { - cerr << "Unknown engine type: " << type << endl; - exit(-5); - } - - FCS->AddThrottle(); - ThrottleAdded = true; - - numEngines++; - - engine_element = el->FindNextElement("engine"); - ResetParser(); - } - - CalculateTankInertias(); - if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle - - // Process fuel dump rate - if (el->FindElement("dump-rate")) - DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN"); - - FGModel::PostLoad(el); - - return true; + string type, engine_filename; + bool ThrottleAdded = false; + + Debug(2); + + FGModel::Load(el); // Perform base class Load. + + // Process tank definitions first to establish the number of fuel tanks + + Element* tank_element = el->FindElement("tank"); + while (tank_element) { + Tanks.push_back(new FGTank(FDMExec, tank_element, numTanks)); + if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++; + else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++; + else {cerr << "Unknown tank type specified." << endl; return false;} + numTanks++; + tank_element = el->FindNextElement("tank"); + } + numSelectedFuelTanks = numFuelTanks; + numSelectedOxiTanks = numOxiTanks; + + Element* engine_element = el->FindElement("engine"); + while (engine_element) { + engine_filename = engine_element->GetAttributeValue("file"); + + if (engine_filename.empty()) { + cerr << "Engine definition did not supply an engine file." << endl; + return false; + } + + engine_filename = FindEngineFullPathname(engine_filename); + document = LoadXMLDocument(engine_filename); + document->SetParent(engine_element); + + type = document->GetName(); + if (type == "piston_engine") { + HavePistonEngine = true; + if (!IsBound) bind(); + Engines.push_back(new FGPiston(FDMExec, document, numEngines)); + } else if (type == "turbine_engine") { + HaveTurbineEngine = true; + if (!IsBound) bind(); + Engines.push_back(new FGTurbine(FDMExec, document, numEngines)); + } else if (type == "turboprop_engine") { + HaveTurboPropEngine = true; + if (!IsBound) bind(); + Engines.push_back(new FGTurboProp(FDMExec, document, numEngines)); + } else if (type == "rocket_engine") { + HaveRocketEngine = true; + if (!IsBound) bind(); + Engines.push_back(new FGRocket(FDMExec, document, numEngines)); + } else if (type == "electric_engine") { + HaveElectricEngine = true; + if (!IsBound) bind(); + Engines.push_back(new FGElectric(FDMExec, document, numEngines)); + } else { + cerr << "Unknown engine type: " << type << endl; + exit(-5); + } + + FCS->AddThrottle(); + ThrottleAdded = true; + + numEngines++; + + engine_element = el->FindNextElement("engine"); + ResetParser(); + } + + CalculateTankInertias(); + if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle + + // Process fuel dump rate + if (el->FindElement("dump-rate")) + DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN"); + + PostLoad(el, PropertyManager); + + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGPropulsion::FindEngineFullPathname(const string& engine_filename) { - string fullpath, localpath; - string enginePath = FDMExec->GetEnginePath(); - string aircraftPath = FDMExec->GetFullAircraftPath(); - ifstream engine_file; - - string separator = "/"; - - fullpath = enginePath + separator; - localpath = aircraftPath + separator + "Engines" + separator; - - engine_file.open(string(fullpath + engine_filename + ".xml").c_str()); - if ( !engine_file.is_open()) - { - engine_file.open(string(localpath + engine_filename + ".xml").c_str()); - if ( !engine_file.is_open()) - { - cerr << " Could not open engine file: " << engine_filename << " in path " - << fullpath << " or " << localpath << endl; - return string(""); - } - else - { - return string(localpath + engine_filename + ".xml"); - } - } - return string(fullpath + engine_filename + ".xml"); + string fullpath, localpath; + string enginePath = FDMExec->GetEnginePath(); + string aircraftPath = FDMExec->GetFullAircraftPath(); + ifstream engine_file; + + string separator = "/"; + + fullpath = enginePath + separator; + localpath = aircraftPath + separator + "Engines" + separator; + + engine_file.open(string(fullpath + engine_filename + ".xml").c_str()); + if ( !engine_file.is_open()) { + engine_file.open(string(localpath + engine_filename + ".xml").c_str()); + if ( !engine_file.is_open()) { + cerr << " Could not open engine file: " << engine_filename << " in path " + << fullpath << " or " << localpath << endl; + return string(""); + } else { + return string(localpath + engine_filename + ".xml"); + } + } + return string(fullpath + engine_filename + ".xml"); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ifstream* FGPropulsion::FindEngineFile(const string& engine_filename) { - string fullpath, localpath; - string enginePath = FDMExec->GetEnginePath(); - string aircraftPath = FDMExec->GetFullAircraftPath(); - ifstream* engine_file = new ifstream(); - - string separator = "/"; - - fullpath = enginePath + separator; - localpath = aircraftPath + separator + "Engines" + separator; - - engine_file->open(string(fullpath + engine_filename + ".xml").c_str()); - if ( !engine_file->is_open()) - { - engine_file->open(string(localpath + engine_filename + ".xml").c_str()); - if ( !engine_file->is_open()) - { - cerr << " Could not open engine file: " << engine_filename << " in path " - << fullpath << " or " << localpath << endl; - } - } - return engine_file; + string fullpath, localpath; + string enginePath = FDMExec->GetEnginePath(); + string aircraftPath = FDMExec->GetFullAircraftPath(); + ifstream* engine_file = new ifstream(); + + string separator = "/"; + + fullpath = enginePath + separator; + localpath = aircraftPath + separator + "Engines" + separator; + + engine_file->open(string(fullpath + engine_filename + ".xml").c_str()); + if ( !engine_file->is_open()) { + engine_file->open(string(localpath + engine_filename + ".xml").c_str()); + if ( !engine_file->is_open()) { + cerr << " Could not open engine file: " << engine_filename << " in path " + << fullpath << " or " << localpath << endl; + } + } + return engine_file; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGPropulsion::GetPropulsionStrings(const string& delimiter) { - unsigned int i; + unsigned int i; - string PropulsionStrings = ""; - bool firstime = true; - stringstream buf; + string PropulsionStrings = ""; + bool firstime = true; + stringstream buf; - for (i=0; i<Engines.size(); i++) - { - if (firstime) firstime = false; - else PropulsionStrings += delimiter; + for (i=0; i<Engines.size(); i++) { + if (firstime) firstime = false; + else PropulsionStrings += delimiter; - PropulsionStrings += Engines[i]->GetEngineLabels(delimiter); - } - for (i=0; i<Tanks.size(); i++) - { - if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimiter << "Fuel Tank " << i; - else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimiter << "Oxidizer Tank " << i; - } + PropulsionStrings += Engines[i]->GetEngineLabels(delimiter); + } + for (i=0; i<Tanks.size(); i++) { + if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimiter << "Fuel Tank " << i; + else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimiter << "Oxidizer Tank " << i; + } - return PropulsionStrings; + return PropulsionStrings; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGPropulsion::GetPropulsionValues(const string& delimiter) { - unsigned int i; + unsigned int i; - string PropulsionValues = ""; - bool firstime = true; - stringstream buf; + string PropulsionValues = ""; + bool firstime = true; + stringstream buf; - for (i=0; i<Engines.size(); i++) - { - if (firstime) firstime = false; - else PropulsionValues += delimiter; + for (i=0; i<Engines.size(); i++) { + if (firstime) firstime = false; + else PropulsionValues += delimiter; - PropulsionValues += Engines[i]->GetEngineValues(delimiter); - } - for (i=0; i<Tanks.size(); i++) - { - buf << delimiter; - buf << Tanks[i]->GetContents(); - } + PropulsionValues += Engines[i]->GetEngineValues(delimiter); + } + for (i=0; i<Tanks.size(); i++) { + buf << delimiter; + buf << Tanks[i]->GetContents(); + } - return PropulsionValues; + return PropulsionValues; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3& FGPropulsion::GetTanksMoment(void) { - vXYZtank_arm.InitMatrix(); - for (unsigned int i=0; i<Tanks.size(); i++) - { - vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents(); - vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents(); - vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents(); - } - return vXYZtank_arm; + vXYZtank_arm.InitMatrix(); + for (unsigned int i=0; i<Tanks.size(); i++) { + vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents(); + vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents(); + vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents(); + } + return vXYZtank_arm; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGPropulsion::GetTanksWeight(void) { - double Tw = 0.0; + double Tw = 0.0; - for (unsigned int i=0; i<Tanks.size(); i++) Tw += Tanks[i]->GetContents(); + for (unsigned int i=0; i<Tanks.size(); i++) Tw += Tanks[i]->GetContents(); - return Tw; + return Tw; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33& FGPropulsion::CalculateTankInertias(void) { - unsigned int size; + unsigned int size; - size = Tanks.size(); - if (size == 0) return tankJ; + size = Tanks.size(); + if (size == 0) return tankJ; - tankJ = FGMatrix33(); + tankJ = FGMatrix33(); - for (unsigned int i=0; i<size; i++) - { - tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(), - Tanks[i]->GetXYZ() ); - tankJ(1,1) += Tanks[i]->GetIxx(); - tankJ(2,2) += Tanks[i]->GetIyy(); - tankJ(3,3) += Tanks[i]->GetIzz(); - } + for (unsigned int i=0; i<size; i++) { + tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(), + Tanks[i]->GetXYZ() ); + tankJ(1,1) += Tanks[i]->GetIxx(); + tankJ(2,2) += Tanks[i]->GetIyy(); + tankJ(3,3) += Tanks[i]->GetIzz(); + } - return tankJ; + return tankJ; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropulsion::SetMagnetos(int setting) { - if (ActiveEngine < 0) - { - for (unsigned i=0; i<Engines.size(); i++) - { - // ToDo: first need to make sure the engine Type is really appropriate: - // do a check to see if it is of type Piston. This should be done for - // all of this kind of possibly across-the-board settings. - ((FGPiston*)Engines[i])->SetMagnetos(setting); - } - } - else - { - ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting); - } + if (ActiveEngine < 0) { + for (unsigned i=0; i<Engines.size(); i++) { + // ToDo: first need to make sure the engine Type is really appropriate: + // do a check to see if it is of type Piston. This should be done for + // all of this kind of possibly across-the-board settings. + ((FGPiston*)Engines[i])->SetMagnetos(setting); + } + } else { + ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropulsion::SetStarter(int setting) { - if (ActiveEngine < 0) - { - for (unsigned i=0; i<Engines.size(); i++) - { - if (setting == 0) - Engines[i]->SetStarter(false); - else - Engines[i]->SetStarter(true); - } - } + if (ActiveEngine < 0) { + for (unsigned i=0; i<Engines.size(); i++) { + if (setting == 0) + Engines[i]->SetStarter(false); + else + Engines[i]->SetStarter(true); + } + } else { + if (setting == 0) + Engines[ActiveEngine]->SetStarter(false); else - { - if (setting == 0) - Engines[ActiveEngine]->SetStarter(false); - else - Engines[ActiveEngine]->SetStarter(true); - } + Engines[ActiveEngine]->SetStarter(true); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropulsion::SetCutoff(int setting) { - if (ActiveEngine < 0) - { - for (unsigned i=0; i<Engines.size(); i++) - { - if (setting == 0) - ((FGTurbine*)Engines[i])->SetCutoff(false); - else - ((FGTurbine*)Engines[i])->SetCutoff(true); - } - } + if (ActiveEngine < 0) { + for (unsigned i=0; i<Engines.size(); i++) { + if (setting == 0) + ((FGTurbine*)Engines[i])->SetCutoff(false); + else + ((FGTurbine*)Engines[i])->SetCutoff(true); + } + } else { + if (setting == 0) + ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false); else - { - if (setting == 0) - ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false); - else - ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true); - } + ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropulsion::SetActiveEngine(int engine) { - if (engine >= (int)Engines.size() || engine < 0) - ActiveEngine = -1; - else - ActiveEngine = engine; + if (engine >= (int)Engines.size() || engine < 0) + ActiveEngine = -1; + else + ActiveEngine = engine; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGPropulsion::Transfer(int source, int target, double amount) { - double shortage, overage; - - if (source == -1) - { - shortage = 0.0; - } - else - { - shortage = Tanks[source]->Drain(amount); - } - if (target == -1) - { - overage = 0.0; - } - else - { - overage = Tanks[target]->Fill(amount - shortage); - } - return overage; + double shortage, overage; + + if (source == -1) { + shortage = 0.0; + } else { + shortage = Tanks[source]->Drain(amount); + } + if (target == -1) { + overage = 0.0; + } else { + overage = Tanks[target]->Fill(amount - shortage); + } + return overage; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropulsion::DoRefuel(double time_slice) { - unsigned int i; + unsigned int i; - double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min - int TanksNotFull = 0; + double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min + int TanksNotFull = 0; - for (i=0; i<numTanks; i++) - { - if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull; - } + for (i=0; i<numTanks; i++) { + if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull; + } - if (TanksNotFull) - { - for (i=0; i<numTanks; i++) - { - if (Tanks[i]->GetPctFull() < 99.99) - Transfer(-1, i, fillrate/TanksNotFull); - } + if (TanksNotFull) { + for (i=0; i<numTanks; i++) { + if (Tanks[i]->GetPctFull() < 99.99) + Transfer(-1, i, fillrate/TanksNotFull); } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropulsion::DumpFuel(double time_slice) { - unsigned int i; - int TanksDumping = 0; + unsigned int i; + int TanksDumping = 0; - for (i=0; i<numTanks; i++) - { - if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping; - } + for (i=0; i<numTanks; i++) { + if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping; + } - if (TanksDumping == 0) return; + if (TanksDumping == 0) return; - double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping; + double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping; - for (i=0; i<numTanks; i++) - { - if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) - { - Transfer(i, -1, dump_rate_per_tank); - } + for (i=0; i<numTanks; i++) { + if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) { + Transfer(i, -1, dump_rate_per_tank); } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropulsion::SetFuelFreeze(bool f) { - fuel_freeze = f; - for (unsigned int i=0; i<numEngines; i++) - { - Engines[i]->SetFuelFreeze(f); - } + fuel_freeze = f; + for (unsigned int i=0; i<numEngines; i++) { + Engines[i]->SetFuelFreeze(f); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropulsion::bind(void) { - typedef double (FGPropulsion::*PMF)(int) const; - typedef int (FGPropulsion::*iPMF)(void) const; - - IsBound = true; - PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, true); - if (HaveTurbineEngine) - { - PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true); - PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, true); - } - - if (HavePistonEngine) - { - PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true); - PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true); - } - - PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine, - &FGPropulsion::SetActiveEngine, true); - PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity); - PropertyManager->Tie("propulsion/refuel", this, &FGPropulsion::GetRefuel, - &FGPropulsion::SetRefuel, true); - PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump, - &FGPropulsion::SetFuelDump, true); - PropertyManager->Tie("forces/fbx-prop-lbs", this,1, - (PMF)&FGPropulsion::GetForces); - PropertyManager->Tie("forces/fby-prop-lbs", this,2, - (PMF)&FGPropulsion::GetForces); - PropertyManager->Tie("forces/fbz-prop-lbs", this,3, - (PMF)&FGPropulsion::GetForces); - PropertyManager->Tie("moments/l-prop-lbsft", this,1, - (PMF)&FGPropulsion::GetMoments); - PropertyManager->Tie("moments/m-prop-lbsft", this,2, - (PMF)&FGPropulsion::GetMoments); - PropertyManager->Tie("moments/n-prop-lbsft", this,3, - (PMF)&FGPropulsion::GetMoments); + typedef double (FGPropulsion::*PMF)(int) const; + typedef int (FGPropulsion::*iPMF)(void) const; + + IsBound = true; + PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, true); + if (HaveTurbineEngine) { + PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true); + PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, true); + } + + if (HavePistonEngine) { + PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true); + PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true); + } + + PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine, + &FGPropulsion::SetActiveEngine, true); + PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity); + PropertyManager->Tie("propulsion/refuel", this, &FGPropulsion::GetRefuel, + &FGPropulsion::SetRefuel, true); + PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump, + &FGPropulsion::SetFuelDump, true); + PropertyManager->Tie("forces/fbx-prop-lbs", this,1, + (PMF)&FGPropulsion::GetForces); + PropertyManager->Tie("forces/fby-prop-lbs", this,2, + (PMF)&FGPropulsion::GetForces); + PropertyManager->Tie("forces/fbz-prop-lbs", this,3, + (PMF)&FGPropulsion::GetForces); + PropertyManager->Tie("moments/l-prop-lbsft", this,1, + (PMF)&FGPropulsion::GetMoments); + PropertyManager->Tie("moments/m-prop-lbsft", this,2, + (PMF)&FGPropulsion::GetMoments); + PropertyManager->Tie("moments/n-prop-lbsft", this,3, + (PMF)&FGPropulsion::GetMoments); } @@ -765,36 +686,28 @@ void FGPropulsion::bind(void) void FGPropulsion::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 2) // Loader - { - cout << endl << " Propulsion:" << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGPropulsion" << endl; - if (from == 1) cout << "Destroyed: FGPropulsion" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 2) { // Loader + cout << endl << " Propulsion:" << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGPropulsion" << endl; + if (from == 1) cout << "Destroyed: FGPropulsion" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; + } + } } } diff --git a/src/models/FGPropulsion.h b/src/models/FGPropulsion.h index 647f013323e315c99274e4afbf4561c033ae6e16..ff3502c95eb3b08226122d68d5b256b73e1b6de8 100644 --- a/src/models/FGPropulsion.h +++ b/src/models/FGPropulsion.h @@ -55,8 +55,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGTank; class FGEngine; @@ -83,7 +82,7 @@ CLASS DOCUMENTATION ... see FGEngine, FGThruster, and class for engine type ... </engine> ... more engines ... - <tank type="{FUEL | OXIDIZER}"> + <tank type="{FUEL | OXIDIZER}"> ... see FGTank ... </tank> ... more tanks ... @@ -105,173 +104,124 @@ CLASS DECLARATION class FGPropulsion : public FGModel, public FGXMLFileRead { public: - /// Constructor - FGPropulsion(FGFDMExec*); - /// Destructor - ~FGPropulsion(); - - /** Executes the propulsion model. - The initial plan for the FGPropulsion class calls for Run() to be executed, - calculating the power available from the engine. - - [Note: Should we be checking the Starved flag here?] */ - bool Run(void); - - bool InitModel(void); - - /** Loads the propulsion system (engine[s] and tank[s]). - Characteristics of the propulsion system are read in from the config file. - @param el pointer to an XML element that contains the engine information. - @return true if successfully loaded, otherwise false */ - bool Load(Element* el); - - /// Retrieves the number of engines defined for the aircraft. - inline unsigned int GetNumEngines(void) const - { - return (unsigned int)Engines.size(); - } - - /** Retrieves an engine object pointer from the list of engines. - @param index the engine index within the vector container - @return the address of the specific engine, or zero if no such engine is - available */ - inline FGEngine* GetEngine(unsigned int index) - { - if (index < Engines.size()) return Engines[index]; - else return 0L; - } - - /// Retrieves the number of tanks defined for the aircraft. - inline unsigned int GetNumTanks(void) const - { - return (unsigned int)Tanks.size(); - } - - /** Retrieves a tank object pointer from the list of tanks. - @param index the tank index within the vector container - @return the address of the specific tank, or zero if no such tank is - available */ - inline FGTank* GetTank(unsigned int index) - { - if (index < Tanks.size()) return Tanks[index]; - else return 0L; - } - - /** Returns the number of fuel tanks currently actively supplying fuel */ - inline int GetnumSelectedFuelTanks(void) const - { - return numSelectedFuelTanks; - } - - /** Returns the number of oxidizer tanks currently actively supplying oxidizer */ - inline int GetnumSelectedOxiTanks(void) const - { - return numSelectedOxiTanks; - } - - /** Loops the engines until thrust output steady (used for trimming) */ - bool GetSteadyState(void); - - /** Sets up the engines as running */ - void InitRunning(int n); - - std::string GetPropulsionStrings(const std::string& delimiter); - std::string GetPropulsionValues(const std::string& delimiter); - - inline FGColumnVector3& GetForces(void) - { - return vForces; - } - inline double GetForces(int n) const - { - return vForces(n); - } - inline FGColumnVector3& GetMoments(void) - { - return vMoments; - } - inline double GetMoments(int n) const - { - return vMoments(n); - } - - inline bool GetRefuel(void) const - { - return refuel; - } - inline void SetRefuel(bool setting) - { - refuel = setting; - } - inline bool GetFuelDump(void) const - { - return dump; - } - inline void SetFuelDump(bool setting) - { - dump = setting; - } - double Transfer(int source, int target, double amount); - void DoRefuel(double time_slice); - void DumpFuel(double time_slice); - - FGColumnVector3& GetTanksMoment(void); - double GetTanksWeight(void); - - std::ifstream* FindEngineFile(const std::string& filename); - std::string FindEngineFullPathname(const std::string& engine_filename); - inline int GetActiveEngine(void) const - { - return ActiveEngine; - } - inline bool GetFuelFreeze(void) - { - return fuel_freeze; - } - double GetTotalFuelQuantity(void) const - { - return TotalFuelQuantity; - } - - void SetMagnetos(int setting); - void SetStarter(int setting); - void SetCutoff(int setting=0); - void SetActiveEngine(int engine); - void SetFuelFreeze(bool f); - FGMatrix33& CalculateTankInertias(void); + /// Constructor + FGPropulsion(FGFDMExec*); + /// Destructor + ~FGPropulsion(); + + /** Executes the propulsion model. + The initial plan for the FGPropulsion class calls for Run() to be executed, + calculating the power available from the engine. + + [Note: Should we be checking the Starved flag here?] */ + bool Run(void); + + bool InitModel(void); + + /** Loads the propulsion system (engine[s] and tank[s]). + Characteristics of the propulsion system are read in from the config file. + @param el pointer to an XML element that contains the engine information. + @return true if successfully loaded, otherwise false */ + bool Load(Element* el); + + /// Retrieves the number of engines defined for the aircraft. + inline unsigned int GetNumEngines(void) const {return (unsigned int)Engines.size();} + + /** Retrieves an engine object pointer from the list of engines. + @param index the engine index within the vector container + @return the address of the specific engine, or zero if no such engine is + available */ + inline FGEngine* GetEngine(unsigned int index) { + if (index < Engines.size()) return Engines[index]; + else return 0L; } + + /// Retrieves the number of tanks defined for the aircraft. + inline unsigned int GetNumTanks(void) const {return (unsigned int)Tanks.size();} + + /** Retrieves a tank object pointer from the list of tanks. + @param index the tank index within the vector container + @return the address of the specific tank, or zero if no such tank is + available */ + inline FGTank* GetTank(unsigned int index) { + if (index < Tanks.size()) return Tanks[index]; + else return 0L; } + + /** Returns the number of fuel tanks currently actively supplying fuel */ + inline int GetnumSelectedFuelTanks(void) const {return numSelectedFuelTanks;} + + /** Returns the number of oxidizer tanks currently actively supplying oxidizer */ + inline int GetnumSelectedOxiTanks(void) const {return numSelectedOxiTanks;} + + /** Loops the engines until thrust output steady (used for trimming) */ + bool GetSteadyState(void); + + /** Sets up the engines as running */ + void InitRunning(int n); + + std::string GetPropulsionStrings(const std::string& delimiter); + std::string GetPropulsionValues(const std::string& delimiter); + + inline FGColumnVector3& GetForces(void) {return vForces; } + inline double GetForces(int n) const { return vForces(n);} + inline FGColumnVector3& GetMoments(void) {return vMoments;} + inline double GetMoments(int n) const {return vMoments(n);} + + inline bool GetRefuel(void) const {return refuel;} + inline void SetRefuel(bool setting) {refuel = setting;} + inline bool GetFuelDump(void) const {return dump;} + inline void SetFuelDump(bool setting) {dump = setting;} + double Transfer(int source, int target, double amount); + void DoRefuel(double time_slice); + void DumpFuel(double time_slice); + + FGColumnVector3& GetTanksMoment(void); + double GetTanksWeight(void); + + std::ifstream* FindEngineFile(const std::string& filename); + std::string FindEngineFullPathname(const std::string& engine_filename); + inline int GetActiveEngine(void) const {return ActiveEngine;} + inline bool GetFuelFreeze(void) {return fuel_freeze;} + double GetTotalFuelQuantity(void) const {return TotalFuelQuantity;} + + void SetMagnetos(int setting); + void SetStarter(int setting); + void SetCutoff(int setting=0); + void SetActiveEngine(int engine); + void SetFuelFreeze(bool f); + FGMatrix33& CalculateTankInertias(void); private: - std::vector <FGEngine*> Engines; - std::vector <FGTank*> Tanks; - unsigned int numSelectedFuelTanks; - unsigned int numSelectedOxiTanks; - unsigned int numFuelTanks; - unsigned int numOxiTanks; - unsigned int numEngines; - unsigned int numTanks; - int ActiveEngine; - FGColumnVector3 vForces; - FGColumnVector3 vMoments; - FGColumnVector3 vTankXYZ; - FGColumnVector3 vXYZtank_arm; - FGMatrix33 tankJ; - bool refuel; - bool dump; - bool fuel_freeze; - double TotalFuelQuantity; - double DumpRate; - bool IsBound; - bool HavePistonEngine; - bool HaveTurbineEngine; - bool HaveTurboPropEngine; - bool HaveRocketEngine; - bool HaveElectricEngine; - - int InitializedEngines; - bool HasInitializedEngines; - - void bind(); - void Debug(int from); + std::vector <FGEngine*> Engines; + std::vector <FGTank*> Tanks; + unsigned int numSelectedFuelTanks; + unsigned int numSelectedOxiTanks; + unsigned int numFuelTanks; + unsigned int numOxiTanks; + unsigned int numEngines; + unsigned int numTanks; + int ActiveEngine; + FGColumnVector3 vForces; + FGColumnVector3 vMoments; + FGColumnVector3 vTankXYZ; + FGColumnVector3 vXYZtank_arm; + FGMatrix33 tankJ; + bool refuel; + bool dump; + bool fuel_freeze; + double TotalFuelQuantity; + double DumpRate; + bool IsBound; + bool HavePistonEngine; + bool HaveTurbineEngine; + bool HaveTurboPropEngine; + bool HaveRocketEngine; + bool HaveElectricEngine; + + int InitializedEngines; + bool HasInitializedEngines; + + void bind(); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/atmosphere/FGMSIS.cpp b/src/models/atmosphere/FGMSIS.cpp old mode 100644 new mode 100755 index 0ed8d5076943b44bde2770ca6d709cee39fc44f3..390a11449709a7ee2502aeda5a5a1d56beb86cbe --- a/src/models/atmosphere/FGMSIS.cpp +++ b/src/models/atmosphere/FGMSIS.cpp @@ -64,8 +64,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGMSIS.cpp,v 1.13 2010/02/25 05:21:36 jberndt Exp $"; static const char *IdHdr = ID_MSIS; @@ -74,19 +73,19 @@ static const char *IdHdr = ID_MSIS; EXTERNAL GLOBAL DATA %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -/* POWER7 */ -extern double pt[150]; -extern double pd[9][150]; -extern double ps[150]; -extern double pdl[2][25]; -extern double ptl[4][100]; -extern double pma[10][100]; -extern double sam[100]; + /* POWER7 */ + extern double pt[150]; + extern double pd[9][150]; + extern double ps[150]; + extern double pdl[2][25]; + extern double ptl[4][100]; + extern double pma[10][100]; + extern double sam[100]; -/* LOWER7 */ -extern double ptm[10]; -extern double pdm[8][10]; -extern double pavgm[10]; + /* LOWER7 */ + extern double ptm[10]; + extern double pdm[8][10]; + extern double pavgm[10]; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS IMPLEMENTATION @@ -95,126 +94,124 @@ CLASS IMPLEMENTATION MSIS::MSIS(FGFDMExec* fdmex) : FGAtmosphere(fdmex) { - Name = "MSIS"; - bind(); - Debug(0); + Name = "MSIS"; + bind(); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% MSIS::~MSIS() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool MSIS::InitModel(void) { - FGModel::InitModel(); + FGModel::InitModel(); - unsigned int i; + unsigned int i; - flags.switches[0] = 0; - for (i=1;i<24;i++) flags.switches[i] = 1; + flags.switches[0] = 0; + for (i=1;i<24;i++) flags.switches[i] = 1; - for (i=0;i<7;i++) aph.a[i] = 100.0; + for (i=0;i<7;i++) aph.a[i] = 100.0; - // set some common magnetic flux values - input.f107A = 150.0; - input.f107 = 150.0; - input.ap = 4.0; + // set some common magnetic flux values + input.f107A = 150.0; + input.f107 = 150.0; + input.ap = 4.0; - SLtemperature = intTemperature = 518.0; - SLpressure = intPressure = 2116.7; - SLdensity = intDensity = 0.002378; - SLsoundspeed = sqrt(2403.0832 * SLtemperature); - rSLtemperature = 1.0/intTemperature; - rSLpressure = 1.0/intPressure; - rSLdensity = 1.0/intDensity; - rSLsoundspeed = 1.0/SLsoundspeed; - temperature = &intTemperature; - pressure = &intPressure; - density = &intDensity; + SLtemperature = intTemperature = 518.0; + SLpressure = intPressure = 2116.7; + SLdensity = intDensity = 0.002378; + SLsoundspeed = sqrt(2403.0832 * SLtemperature); + rSLtemperature = 1.0/intTemperature; + rSLpressure = 1.0/intPressure; + rSLdensity = 1.0/intDensity; + rSLsoundspeed = 1.0/SLsoundspeed; + temperature = &intTemperature; + pressure = &intPressure; + density = &intDensity; - UseInternal(); + UseInternal(); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool MSIS::Run(void) { - if (FGModel::Run()) return true; - if (FDMExec->Holding()) return false; - - RunPreFunctions(); - - //do temp, pressure, and density first - if (!useExternal) - { - // get sea-level values - Calculate(Auxiliary->GetDayOfYear(), - Auxiliary->GetSecondsInDay(), - 0.0, - Propagate->GetLocation().GetLatitudeDeg(), - Propagate->GetLocation().GetLongitudeDeg()); - SLtemperature = output.t[1] * 1.8; - SLdensity = output.d[5] * 1.940321; - SLpressure = 1716.488 * SLdensity * SLtemperature; - SLsoundspeed = sqrt(2403.0832 * SLtemperature); - rSLtemperature = 1.0/SLtemperature; - rSLpressure = 1.0/SLpressure; - rSLdensity = 1.0/SLdensity; - rSLsoundspeed = 1.0/SLsoundspeed; - - // get at-altitude values - Calculate(Auxiliary->GetDayOfYear(), - Auxiliary->GetSecondsInDay(), - Propagate->GetAltitudeASL(), - Propagate->GetLocation().GetLatitudeDeg(), - Propagate->GetLocation().GetLongitudeDeg()); - intTemperature = output.t[1] * 1.8; - intDensity = output.d[5] * 1.940321; - intPressure = 1716.488 * intDensity * intTemperature; - //cout << "T=" << intTemperature << " D=" << intDensity << " P="; - //cout << intPressure << " a=" << soundspeed << endl; - } + if (FGModel::Run()) return true; + if (FDMExec->Holding()) return false; + + RunPreFunctions(); + + //do temp, pressure, and density first + if (!useExternal) { + // get sea-level values + Calculate(Auxiliary->GetDayOfYear(), + Auxiliary->GetSecondsInDay(), + 0.0, + Propagate->GetLocation().GetLatitudeDeg(), + Propagate->GetLocation().GetLongitudeDeg()); + SLtemperature = output.t[1] * 1.8; + SLdensity = output.d[5] * 1.940321; + SLpressure = 1716.488 * SLdensity * SLtemperature; + SLsoundspeed = sqrt(2403.0832 * SLtemperature); + rSLtemperature = 1.0/SLtemperature; + rSLpressure = 1.0/SLpressure; + rSLdensity = 1.0/SLdensity; + rSLsoundspeed = 1.0/SLsoundspeed; - CalculateDerived(); + // get at-altitude values + Calculate(Auxiliary->GetDayOfYear(), + Auxiliary->GetSecondsInDay(), + Propagate->GetAltitudeASL(), + Propagate->GetLocation().GetLatitudeDeg(), + Propagate->GetLocation().GetLongitudeDeg()); + intTemperature = output.t[1] * 1.8; + intDensity = output.d[5] * 1.940321; + intPressure = 1716.488 * intDensity * intTemperature; + //cout << "T=" << intTemperature << " D=" << intDensity << " P="; + //cout << intPressure << " a=" << soundspeed << endl; + } - RunPostFunctions(); + CalculateDerived(); - Debug(2); + RunPostFunctions(); - return false; + Debug(2); + + return false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void MSIS::Calculate(int day, double sec, double alt, double lat, double lon) { - input.year = 2000; - input.doy = day; - input.sec = sec; - input.alt = alt / 3281; //feet to kilometers - input.g_lat = lat; - input.g_long = lon; - - input.lst = (sec/3600) + (lon/15); - if (input.lst > 24.0) input.lst -= 24.0; - if (input.lst < 0.0) input.lst = 24 - input.lst; - - gtd7d(&input, &flags, &output); + input.year = 2000; + input.doy = day; + input.sec = sec; + input.alt = alt / 3281; //feet to kilometers + input.g_lat = lat; + input.g_long = lon; + + input.lst = (sec/3600) + (lon/15); + if (input.lst > 24.0) input.lst -= 24.0; + if (input.lst < 0.0) input.lst = 24 - input.lst; + + gtd7d(&input, &flags, &output); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void MSIS::UseExternal(void) -{ - // do nothing, external control not allowed +void MSIS::UseExternal(void){ + // do nothing, external control not allowed } @@ -223,26 +220,22 @@ void MSIS::UseExternal(void) void MSIS::tselec(struct nrlmsise_flags *flags) { - int i; - for (i=0;i<24;i++) - { - if (i!=9) - { - if (flags->switches[i]==1) - flags->sw[i]=1; - else - flags->sw[i]=0; - if (flags->switches[i]>0) - flags->swc[i]=1; - else - flags->swc[i]=0; - } - else - { - flags->sw[i]=flags->switches[i]; - flags->swc[i]=flags->switches[i]; - } + int i; + for (i=0;i<24;i++) { + if (i!=9) { + if (flags->switches[i]==1) + flags->sw[i]=1; + else + flags->sw[i]=0; + if (flags->switches[i]>0) + flags->swc[i]=1; + else + flags->swc[i]=0; + } else { + flags->sw[i]=flags->switches[i]; + flags->swc[i]=flags->switches[i]; } + } } @@ -250,472 +243,452 @@ void MSIS::tselec(struct nrlmsise_flags *flags) void MSIS::glatf(double lat, double *gv, double *reff) { - double dgtr = 1.74533E-2; - double c2; - c2 = cos(2.0*dgtr*lat); - *gv = 980.616 * (1.0 - 0.0026373 * c2); - *reff = 2.0 * (*gv) / (3.085462E-6 + 2.27E-9 * c2) * 1.0E-5; + double dgtr = 1.74533E-2; + double c2; + c2 = cos(2.0*dgtr*lat); + *gv = 980.616 * (1.0 - 0.0026373 * c2); + *reff = 2.0 * (*gv) / (3.085462E-6 + 2.27E-9 * c2) * 1.0E-5; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double MSIS::ccor(double alt, double r, double h1, double zh) { - /* CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS - * ALT - altitude - * R - target ratio - * H1 - transition scale length - * ZH - altitude of 1/2 R - */ - double e; - double ex; - e = (alt - zh) / h1; - if (e>70) - return exp(0.0); - if (e<-70) - return exp(r); - ex = exp(e); - e = r / (1.0 + ex); - return exp(e); +/* CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS + * ALT - altitude + * R - target ratio + * H1 - transition scale length + * ZH - altitude of 1/2 R + */ + double e; + double ex; + e = (alt - zh) / h1; + if (e>70) + return exp(0.0); + if (e<-70) + return exp(r); + ex = exp(e); + e = r / (1.0 + ex); + return exp(e); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double MSIS::ccor2(double alt, double r, double h1, double zh, double h2) { - /* CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS - * ALT - altitude - * R - target ratio - * H1 - transition scale length - * ZH - altitude of 1/2 R - * H2 - transition scale length #2 ? - */ - double e1, e2; - double ex1, ex2; - double ccor2v; - e1 = (alt - zh) / h1; - e2 = (alt - zh) / h2; - if ((e1 > 70) || (e2 > 70)) - return exp(0.0); - if ((e1 < -70) && (e2 < -70)) - return exp(r); - ex1 = exp(e1); - ex2 = exp(e2); - ccor2v = r / (1.0 + 0.5 * (ex1 + ex2)); - return exp(ccor2v); +/* CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS + * ALT - altitude + * R - target ratio + * H1 - transition scale length + * ZH - altitude of 1/2 R + * H2 - transition scale length #2 ? + */ + double e1, e2; + double ex1, ex2; + double ccor2v; + e1 = (alt - zh) / h1; + e2 = (alt - zh) / h2; + if ((e1 > 70) || (e2 > 70)) + return exp(0.0); + if ((e1 < -70) && (e2 < -70)) + return exp(r); + ex1 = exp(e1); + ex2 = exp(e2); + ccor2v = r / (1.0 + 0.5 * (ex1 + ex2)); + return exp(ccor2v); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double MSIS::scalh(double alt, double xm, double temp) { - double g; - double rgas=831.4; - g = gsurf / (pow((1.0 + alt/re),2.0)); - g = rgas * temp / (g * xm); - return g; + double g; + double rgas=831.4; + g = gsurf / (pow((1.0 + alt/re),2.0)); + g = rgas * temp / (g * xm); + return g; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double MSIS::dnet (double dd, double dm, double zhm, double xmm, double xm) { - /* TURBOPAUSE CORRECTION FOR MSIS MODELS - * Root mean density - * DD - diffusive density - * DM - full mixed density - * ZHM - transition scale length - * XMM - full mixed molecular weight - * XM - species molecular weight - * DNET - combined density - */ - double a; - double ylog; - a = zhm / (xmm-xm); - if (!((dm>0) && (dd>0))) - { - cerr << "dnet log error " << dm << ' ' << dd << ' ' << xm << ' ' << endl; - if ((dd==0) && (dm==0)) - dd=1; - if (dm==0) - return dd; - if (dd==0) - return dm; - } - ylog = a * log(dm/dd); - if (ylog<-10) - return dd; - if (ylog>10) - return dm; - a = dd*pow((1.0 + exp(ylog)),(1.0/a)); - return a; +/* TURBOPAUSE CORRECTION FOR MSIS MODELS + * Root mean density + * DD - diffusive density + * DM - full mixed density + * ZHM - transition scale length + * XMM - full mixed molecular weight + * XM - species molecular weight + * DNET - combined density + */ + double a; + double ylog; + a = zhm / (xmm-xm); + if (!((dm>0) && (dd>0))) { + cerr << "dnet log error " << dm << ' ' << dd << ' ' << xm << ' ' << endl; + if ((dd==0) && (dm==0)) + dd=1; + if (dm==0) + return dd; + if (dd==0) + return dm; + } + ylog = a * log(dm/dd); + if (ylog<-10) + return dd; + if (ylog>10) + return dm; + a = dd*pow((1.0 + exp(ylog)),(1.0/a)); + return a; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void MSIS::splini (double *xa, double *ya, double *y2a, int n, double x, double *y) { - /* INTEGRATE CUBIC SPLINE FUNCTION FROM XA(1) TO X - * XA,YA: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X - * Y2A: ARRAY OF SECOND DERIVATIVES - * N: SIZE OF ARRAYS XA,YA,Y2A - * X: ABSCISSA ENDPOINT FOR INTEGRATION - * Y: OUTPUT VALUE - */ - double yi=0; - int klo=0; - int khi=1; - double xx, h, a, b, a2, b2; - while ((x>xa[klo]) && (khi<n)) - { +/* INTEGRATE CUBIC SPLINE FUNCTION FROM XA(1) TO X + * XA,YA: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X + * Y2A: ARRAY OF SECOND DERIVATIVES + * N: SIZE OF ARRAYS XA,YA,Y2A + * X: ABSCISSA ENDPOINT FOR INTEGRATION + * Y: OUTPUT VALUE + */ + double yi=0; + int klo=0; + int khi=1; + double xx, h, a, b, a2, b2; + while ((x>xa[klo]) && (khi<n)) { + xx=x; + if (khi<(n-1)) { + if (x<xa[khi]) xx=x; - if (khi<(n-1)) - { - if (x<xa[khi]) - xx=x; - else - xx=xa[khi]; - } - h = xa[khi] - xa[klo]; - a = (xa[khi] - xx)/h; - b = (xx - xa[klo])/h; - a2 = a*a; - b2 = b*b; - yi += ((1.0 - a2) * ya[klo] / 2.0 + b2 * ya[khi] / 2.0 + ((-(1.0+a2*a2)/4.0 + a2/2.0) * y2a[klo] + (b2*b2/4.0 - b2/2.0) * y2a[khi]) * h * h / 6.0) * h; - klo++; - khi++; + else + xx=xa[khi]; } - *y = yi; + h = xa[khi] - xa[klo]; + a = (xa[khi] - xx)/h; + b = (xx - xa[klo])/h; + a2 = a*a; + b2 = b*b; + yi += ((1.0 - a2) * ya[klo] / 2.0 + b2 * ya[khi] / 2.0 + ((-(1.0+a2*a2)/4.0 + a2/2.0) * y2a[klo] + (b2*b2/4.0 - b2/2.0) * y2a[khi]) * h * h / 6.0) * h; + klo++; + khi++; + } + *y = yi; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void MSIS::splint (double *xa, double *ya, double *y2a, int n, double x, double *y) { - /* CALCULATE CUBIC SPLINE INTERP VALUE - * ADAPTED FROM NUMERICAL RECIPES BY PRESS ET AL. - * XA,YA: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X - * Y2A: ARRAY OF SECOND DERIVATIVES - * N: SIZE OF ARRAYS XA,YA,Y2A - * X: ABSCISSA FOR INTERPOLATION - * Y: OUTPUT VALUE - */ - int klo=0; - int khi=n-1; - int k; - double h; - double a, b, yi; - while ((khi-klo)>1) - { - k=(khi+klo)/2; - if (xa[k]>x) - khi=k; - else - klo=k; - } - h = xa[khi] - xa[klo]; - if (h==0.0) - cerr << "bad XA input to splint" << endl; - a = (xa[khi] - x)/h; - b = (x - xa[klo])/h; - yi = a * ya[klo] + b * ya[khi] + ((a*a*a - a) * y2a[klo] + (b*b*b - b) * y2a[khi]) * h * h/6.0; - *y = yi; +/* CALCULATE CUBIC SPLINE INTERP VALUE + * ADAPTED FROM NUMERICAL RECIPES BY PRESS ET AL. + * XA,YA: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X + * Y2A: ARRAY OF SECOND DERIVATIVES + * N: SIZE OF ARRAYS XA,YA,Y2A + * X: ABSCISSA FOR INTERPOLATION + * Y: OUTPUT VALUE + */ + int klo=0; + int khi=n-1; + int k; + double h; + double a, b, yi; + while ((khi-klo)>1) { + k=(khi+klo)/2; + if (xa[k]>x) + khi=k; + else + klo=k; + } + h = xa[khi] - xa[klo]; + if (h==0.0) + cerr << "bad XA input to splint" << endl; + a = (xa[khi] - x)/h; + b = (x - xa[klo])/h; + yi = a * ya[klo] + b * ya[khi] + ((a*a*a - a) * y2a[klo] + (b*b*b - b) * y2a[khi]) * h * h/6.0; + *y = yi; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void MSIS::spline (double *x, double *y, int n, double yp1, double ypn, double *y2) { - /* CALCULATE 2ND DERIVATIVES OF CUBIC SPLINE INTERP FUNCTION - * ADAPTED FROM NUMERICAL RECIPES BY PRESS ET AL - * X,Y: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X - * N: SIZE OF ARRAYS X,Y - * YP1,YPN: SPECIFIED DERIVATIVES AT X[0] AND X[N-1]; VALUES - * >= 1E30 SIGNAL SIGNAL SECOND DERIVATIVE ZERO - * Y2: OUTPUT ARRAY OF SECOND DERIVATIVES - */ - double *u; - double sig, p, qn, un; - int i, k; - u=new double[n]; - if (u==NULL) - { - cerr << "Out Of Memory in spline - ERROR" << endl; - return; - } - if (yp1>0.99E30) - { - y2[0]=0; - u[0]=0; - } - else - { - y2[0]=-0.5; - u[0]=(3.0/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0])-yp1); - } - for (i=1;i<(n-1);i++) - { - sig = (x[i]-x[i-1])/(x[i+1] - x[i-1]); - p = sig * y2[i-1] + 2.0; - y2[i] = (sig - 1.0) / p; - u[i] = (6.0 * ((y[i+1] - y[i])/(x[i+1] - x[i]) -(y[i] - y[i-1]) / (x[i] - x[i-1]))/(x[i+1] - x[i-1]) - sig * u[i-1])/p; - } - if (ypn>0.99E30) - { - qn = 0; - un = 0; - } - else - { - qn = 0.5; - un = (3.0 / (x[n-1] - x[n-2])) * (ypn - (y[n-1] - y[n-2])/(x[n-1] - x[n-2])); - } - y2[n-1] = (un - qn * u[n-2]) / (qn * y2[n-2] + 1.0); - for (k=n-2;k>=0;k--) - y2[k] = y2[k] * y2[k+1] + u[k]; - - delete u; +/* CALCULATE 2ND DERIVATIVES OF CUBIC SPLINE INTERP FUNCTION + * ADAPTED FROM NUMERICAL RECIPES BY PRESS ET AL + * X,Y: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X + * N: SIZE OF ARRAYS X,Y + * YP1,YPN: SPECIFIED DERIVATIVES AT X[0] AND X[N-1]; VALUES + * >= 1E30 SIGNAL SIGNAL SECOND DERIVATIVE ZERO + * Y2: OUTPUT ARRAY OF SECOND DERIVATIVES + */ + double *u; + double sig, p, qn, un; + int i, k; + u=new double[n]; + if (u==NULL) { + cerr << "Out Of Memory in spline - ERROR" << endl; + return; + } + if (yp1>0.99E30) { + y2[0]=0; + u[0]=0; + } else { + y2[0]=-0.5; + u[0]=(3.0/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0])-yp1); + } + for (i=1;i<(n-1);i++) { + sig = (x[i]-x[i-1])/(x[i+1] - x[i-1]); + p = sig * y2[i-1] + 2.0; + y2[i] = (sig - 1.0) / p; + u[i] = (6.0 * ((y[i+1] - y[i])/(x[i+1] - x[i]) -(y[i] - y[i-1]) / (x[i] - x[i-1]))/(x[i+1] - x[i-1]) - sig * u[i-1])/p; + } + if (ypn>0.99E30) { + qn = 0; + un = 0; + } else { + qn = 0.5; + un = (3.0 / (x[n-1] - x[n-2])) * (ypn - (y[n-1] - y[n-2])/(x[n-1] - x[n-2])); + } + y2[n-1] = (un - qn * u[n-2]) / (qn * y2[n-2] + 1.0); + for (k=n-2;k>=0;k--) + y2[k] = y2[k] * y2[k+1] + u[k]; + + delete u; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double MSIS::zeta(double zz, double zl) { - return ((zz-zl)*(re+zl)/(re+zz)); + return ((zz-zl)*(re+zl)/(re+zz)); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double MSIS::densm(double alt, double d0, double xm, double *tz, int mn3, - double *zn3, double *tn3, double *tgn3, int mn2, double *zn2, - double *tn2, double *tgn2) + double *zn3, double *tn3, double *tgn3, int mn2, double *zn2, + double *tn2, double *tgn2) { - /* Calculate Temperature and Density Profiles for lower atmos. */ - double xs[10], ys[10], y2out[10]; - double rgas = 831.4; - double z, z1, z2, t1, t2, zg, zgdif; - double yd1, yd2; - double x, y, yi; - double expl, gamm, glb; - double densm_tmp; - int mn; - int k; - densm_tmp=d0; - if (alt>zn2[0]) - { - if (xm==0.0) - return *tz; - else - return d0; - } - - /* STRATOSPHERE/MESOSPHERE TEMPERATURE */ - if (alt>zn2[mn2-1]) - z=alt; +/* Calculate Temperature and Density Profiles for lower atmos. */ + double xs[10], ys[10], y2out[10]; + double rgas = 831.4; + double z, z1, z2, t1, t2, zg, zgdif; + double yd1, yd2; + double x, y, yi; + double expl, gamm, glb; + double densm_tmp; + int mn; + int k; + densm_tmp=d0; + if (alt>zn2[0]) { + if (xm==0.0) + return *tz; else - z=zn2[mn2-1]; - mn=mn2; - z1=zn2[0]; - z2=zn2[mn-1]; - t1=tn2[0]; - t2=tn2[mn-1]; - zg = zeta(z, z1); - zgdif = zeta(z2, z1); + return d0; + } + + /* STRATOSPHERE/MESOSPHERE TEMPERATURE */ + if (alt>zn2[mn2-1]) + z=alt; + else + z=zn2[mn2-1]; + mn=mn2; + z1=zn2[0]; + z2=zn2[mn-1]; + t1=tn2[0]; + t2=tn2[mn-1]; + zg = zeta(z, z1); + zgdif = zeta(z2, z1); + + /* set up spline nodes */ + for (k=0;k<mn;k++) { + xs[k]=zeta(zn2[k],z1)/zgdif; + ys[k]=1.0 / tn2[k]; + } + yd1=-tgn2[0] / (t1*t1) * zgdif; + yd2=-tgn2[1] / (t2*t2) * zgdif * (pow(((re+z2)/(re+z1)),2.0)); + + /* calculate spline coefficients */ + spline (xs, ys, mn, yd1, yd2, y2out); + x = zg/zgdif; + splint (xs, ys, y2out, mn, x, &y); + + /* temperature at altitude */ + *tz = 1.0 / y; + if (xm!=0.0) { + /* calaculate stratosphere / mesospehere density */ + glb = gsurf / (pow((1.0 + z1/re),2.0)); + gamm = xm * glb * zgdif / rgas; - /* set up spline nodes */ - for (k=0;k<mn;k++) - { - xs[k]=zeta(zn2[k],z1)/zgdif; - ys[k]=1.0 / tn2[k]; - } - yd1=-tgn2[0] / (t1*t1) * zgdif; - yd2=-tgn2[1] / (t2*t2) * zgdif * (pow(((re+z2)/(re+z1)),2.0)); + /* Integrate temperature profile */ + splini(xs, ys, y2out, mn, x, &yi); + expl=gamm*yi; + if (expl>50.0) + expl=50.0; - /* calculate spline coefficients */ - spline (xs, ys, mn, yd1, yd2, y2out); - x = zg/zgdif; - splint (xs, ys, y2out, mn, x, &y); + /* Density at altitude */ + densm_tmp = densm_tmp * (t1 / *tz) * exp(-expl); + } - /* temperature at altitude */ - *tz = 1.0 / y; - if (xm!=0.0) - { - /* calaculate stratosphere / mesospehere density */ - glb = gsurf / (pow((1.0 + z1/re),2.0)); - gamm = xm * glb * zgdif / rgas; - - /* Integrate temperature profile */ - splini(xs, ys, y2out, mn, x, &yi); - expl=gamm*yi; - if (expl>50.0) - expl=50.0; - - /* Density at altitude */ - densm_tmp = densm_tmp * (t1 / *tz) * exp(-expl); - } + if (alt>zn3[0]) { + if (xm==0.0) + return *tz; + else + return densm_tmp; + } + + /* troposhere / stratosphere temperature */ + z = alt; + mn = mn3; + z1=zn3[0]; + z2=zn3[mn-1]; + t1=tn3[0]; + t2=tn3[mn-1]; + zg=zeta(z,z1); + zgdif=zeta(z2,z1); + + /* set up spline nodes */ + for (k=0;k<mn;k++) { + xs[k] = zeta(zn3[k],z1) / zgdif; + ys[k] = 1.0 / tn3[k]; + } + yd1=-tgn3[0] / (t1*t1) * zgdif; + yd2=-tgn3[1] / (t2*t2) * zgdif * (pow(((re+z2)/(re+z1)),2.0)); + + /* calculate spline coefficients */ + spline (xs, ys, mn, yd1, yd2, y2out); + x = zg/zgdif; + splint (xs, ys, y2out, mn, x, &y); + + /* temperature at altitude */ + *tz = 1.0 / y; + if (xm!=0.0) { + /* calaculate tropospheric / stratosphere density */ + glb = gsurf / (pow((1.0 + z1/re),2.0)); + gamm = xm * glb * zgdif / rgas; - if (alt>zn3[0]) - { - if (xm==0.0) - return *tz; - else - return densm_tmp; - } + /* Integrate temperature profile */ + splini(xs, ys, y2out, mn, x, &yi); + expl=gamm*yi; + if (expl>50.0) + expl=50.0; + + /* Density at altitude */ + densm_tmp = densm_tmp * (t1 / *tz) * exp(-expl); + } + if (xm==0.0) + return *tz; + else + return densm_tmp; +} - /* troposhere / stratosphere temperature */ - z = alt; - mn = mn3; - z1=zn3[0]; - z2=zn3[mn-1]; - t1=tn3[0]; - t2=tn3[mn-1]; - zg=zeta(z,z1); - zgdif=zeta(z2,z1); +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +double MSIS::densu(double alt, double dlb, double tinf, double tlb, double xm, + double alpha, double *tz, double zlb, double s2, int mn1, + double *zn1, double *tn1, double *tgn1) +{ +/* Calculate Temperature and Density Profiles for MSIS models + * New lower thermo polynomial + */ + double yd2, yd1, x=0.0, y=0.0; + double rgas=831.4; + double densu_temp=1.0; + double za, z, zg2, tt, ta=0.0; + double dta, z1=0.0, z2, t1=0.0, t2, zg, zgdif=0.0; + int mn=0; + int k; + double glb; + double expl; + double yi; + double densa; + double gamma, gamm; + double xs[5], ys[5], y2out[5]; + /* joining altitudes of Bates and spline */ + za=zn1[0]; + if (alt>za) + z=alt; + else + z=za; + + /* geopotential altitude difference from ZLB */ + zg2 = zeta(z, zlb); + + /* Bates temperature */ + tt = tinf - (tinf - tlb) * exp(-s2*zg2); + ta = tt; + *tz = tt; + densu_temp = *tz; + + if (alt<za) { + /* calculate temperature below ZA + * temperature gradient at ZA from Bates profile */ + dta = (tinf - ta) * s2 * pow(((re+zlb)/(re+za)),2.0); + tgn1[0]=dta; + tn1[0]=ta; + if (alt>zn1[mn1-1]) + z=alt; + else + z=zn1[mn1-1]; + mn=mn1; + z1=zn1[0]; + z2=zn1[mn-1]; + t1=tn1[0]; + t2=tn1[mn-1]; + /* geopotental difference from z1 */ + zg = zeta (z, z1); + zgdif = zeta(z2, z1); /* set up spline nodes */ - for (k=0;k<mn;k++) - { - xs[k] = zeta(zn3[k],z1) / zgdif; - ys[k] = 1.0 / tn3[k]; + for (k=0;k<mn;k++) { + xs[k] = zeta(zn1[k], z1) / zgdif; + ys[k] = 1.0 / tn1[k]; } - yd1=-tgn3[0] / (t1*t1) * zgdif; - yd2=-tgn3[1] / (t2*t2) * zgdif * (pow(((re+z2)/(re+z1)),2.0)); - + /* end node derivatives */ + yd1 = -tgn1[0] / (t1*t1) * zgdif; + yd2 = -tgn1[1] / (t2*t2) * zgdif * pow(((re+z2)/(re+z1)),2.0); /* calculate spline coefficients */ spline (xs, ys, mn, yd1, yd2, y2out); - x = zg/zgdif; + x = zg / zgdif; splint (xs, ys, y2out, mn, x, &y); - /* temperature at altitude */ *tz = 1.0 / y; - if (xm!=0.0) - { - /* calaculate tropospheric / stratosphere density */ - glb = gsurf / (pow((1.0 + z1/re),2.0)); - gamm = xm * glb * zgdif / rgas; - - /* Integrate temperature profile */ - splini(xs, ys, y2out, mn, x, &yi); - expl=gamm*yi; - if (expl>50.0) - expl=50.0; - - /* Density at altitude */ - densm_tmp = densm_tmp * (t1 / *tz) * exp(-expl); - } - if (xm==0.0) - return *tz; - else - return densm_tmp; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double MSIS::densu(double alt, double dlb, double tinf, double tlb, double xm, - double alpha, double *tz, double zlb, double s2, int mn1, - double *zn1, double *tn1, double *tgn1) -{ - /* Calculate Temperature and Density Profiles for MSIS models - * New lower thermo polynomial - */ - double yd2, yd1, x=0.0, y=0.0; - double rgas=831.4; - double densu_temp=1.0; - double za, z, zg2, tt, ta=0.0; - double dta, z1=0.0, z2, t1=0.0, t2, zg, zgdif=0.0; - int mn=0; - int k; - double glb; - double expl; - double yi; - double densa; - double gamma, gamm; - double xs[5], ys[5], y2out[5]; - /* joining altitudes of Bates and spline */ - za=zn1[0]; - if (alt>za) - z=alt; - else - z=za; - - /* geopotential altitude difference from ZLB */ - zg2 = zeta(z, zlb); - - /* Bates temperature */ - tt = tinf - (tinf - tlb) * exp(-s2*zg2); - ta = tt; - *tz = tt; densu_temp = *tz; + } + if (xm==0) + return densu_temp; - if (alt<za) - { - /* calculate temperature below ZA - * temperature gradient at ZA from Bates profile */ - dta = (tinf - ta) * s2 * pow(((re+zlb)/(re+za)),2.0); - tgn1[0]=dta; - tn1[0]=ta; - if (alt>zn1[mn1-1]) - z=alt; - else - z=zn1[mn1-1]; - mn=mn1; - z1=zn1[0]; - z2=zn1[mn-1]; - t1=tn1[0]; - t2=tn1[mn-1]; - /* geopotental difference from z1 */ - zg = zeta (z, z1); - zgdif = zeta(z2, z1); - /* set up spline nodes */ - for (k=0;k<mn;k++) - { - xs[k] = zeta(zn1[k], z1) / zgdif; - ys[k] = 1.0 / tn1[k]; - } - /* end node derivatives */ - yd1 = -tgn1[0] / (t1*t1) * zgdif; - yd2 = -tgn1[1] / (t2*t2) * zgdif * pow(((re+z2)/(re+z1)),2.0); - /* calculate spline coefficients */ - spline (xs, ys, mn, yd1, yd2, y2out); - x = zg / zgdif; - splint (xs, ys, y2out, mn, x, &y); - /* temperature at altitude */ - *tz = 1.0 / y; - densu_temp = *tz; - } - if (xm==0) - return densu_temp; - - /* calculate density above za */ - glb = gsurf / pow((1.0 + zlb/re),2.0); - gamma = xm * glb / (s2 * rgas * tinf); - expl = exp(-s2 * gamma * zg2); - if (expl>50.0) - expl=50.0; - if (tt<=0) - expl=50.0; - - /* density at altitude */ - densa = dlb * pow((tlb/tt),((1.0+alpha+gamma))) * expl; - densu_temp=densa; - if (alt>=za) - return densu_temp; - - /* calculate density below za */ - glb = gsurf / pow((1.0 + z1/re),2.0); - gamm = xm * glb * zgdif / rgas; - - /* integrate spline temperatures */ - splini (xs, ys, y2out, mn, x, &yi); - expl = gamm * yi; - if (expl>50.0) - expl=50.0; - if (*tz<=0) - expl=50.0; - - /* density at altitude */ - densu_temp = densu_temp * pow ((t1 / *tz),(1.0 + alpha)) * exp(-expl); + /* calculate density above za */ + glb = gsurf / pow((1.0 + zlb/re),2.0); + gamma = xm * glb / (s2 * rgas * tinf); + expl = exp(-s2 * gamma * zg2); + if (expl>50.0) + expl=50.0; + if (tt<=0) + expl=50.0; + + /* density at altitude */ + densa = dlb * pow((tlb/tt),((1.0+alpha+gamma))) * expl; + densu_temp=densa; + if (alt>=za) return densu_temp; + + /* calculate density below za */ + glb = gsurf / pow((1.0 + z1/re),2.0); + gamm = xm * glb * zgdif / rgas; + + /* integrate spline temperatures */ + splini (xs, ys, y2out, mn, x, &yi); + expl = gamm * yi; + if (expl>50.0) + expl=50.0; + if (*tz<=0) + expl=50.0; + + /* density at altitude */ + densu_temp = densu_temp * pow ((t1 / *tz),(1.0 + alpha)) * exp(-expl); + return densu_temp; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -724,8 +697,8 @@ double MSIS::densu(double alt, double dlb, double tinf, double tlb, double xm, /* Eq. A24d */ double MSIS::g0(double a, double *p) { - return (a - 4.0 + (p[25] - 1.0) * (a - 4.0 + (exp(-sqrt(p[24]*p[24]) * - (a - 4.0)) - 1.0) / sqrt(p[24]*p[24]))); + return (a - 4.0 + (p[25] - 1.0) * (a - 4.0 + (exp(-sqrt(p[24]*p[24]) * + (a - 4.0)) - 1.0) / sqrt(p[24]*p[24]))); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -733,7 +706,7 @@ double MSIS::g0(double a, double *p) /* Eq. A24c */ double MSIS::sumex(double ex) { - return (1.0 + (1.0 - pow(ex,19.0)) / (1.0 - ex) * pow(ex,0.5)); + return (1.0 + (1.0 - pow(ex,19.0)) / (1.0 - ex) * pow(ex,0.5)); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -741,932 +714,889 @@ double MSIS::sumex(double ex) /* Eq. A24a */ double MSIS::sg0(double ex, double *p, double *ap) { - return (g0(ap[1],p) + (g0(ap[2],p)*ex + g0(ap[3],p)*ex*ex + - g0(ap[4],p)*pow(ex,3.0) + (g0(ap[5],p)*pow(ex,4.0) + - g0(ap[6],p)*pow(ex,12.0))*(1.0-pow(ex,8.0))/(1.0-ex)))/sumex(ex); + return (g0(ap[1],p) + (g0(ap[2],p)*ex + g0(ap[3],p)*ex*ex + + g0(ap[4],p)*pow(ex,3.0) + (g0(ap[5],p)*pow(ex,4.0) + + g0(ap[6],p)*pow(ex,12.0))*(1.0-pow(ex,8.0))/(1.0-ex)))/sumex(ex); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double MSIS::globe7(double *p, struct nrlmsise_input *input, - struct nrlmsise_flags *flags) + struct nrlmsise_flags *flags) { - /* CALCULATE G(L) FUNCTION - * Upper Thermosphere Parameters */ - double t[15]; - int i,j; - int sw9=1; - double apd; - double xlong; - double tloc; - double c, s, c2, c4, s2; - double sr = 7.2722E-5; - double dgtr = 1.74533E-2; - double dr = 1.72142E-2; - double hr = 0.2618; - double cd32, cd18, cd14, cd39; - double p32, p18, p14, p39; - double df, dfa; - double f1, f2; - double tinf; - struct ap_array *ap; - - tloc=input->lst; - for (j=0;j<14;j++) - t[j]=0; - if (flags->sw[9]>0) - sw9=1; - else if (flags->sw[9]<0) - sw9=-1; - xlong = input->g_long; - - /* calculate legendre polynomials */ - c = sin(input->g_lat * dgtr); - s = cos(input->g_lat * dgtr); - c2 = c*c; - c4 = c2*c2; - s2 = s*s; - - plg[0][1] = c; - plg[0][2] = 0.5*(3.0*c2 -1.0); - plg[0][3] = 0.5*(5.0*c*c2-3.0*c); - plg[0][4] = (35.0*c4 - 30.0*c2 + 3.0)/8.0; - plg[0][5] = (63.0*c2*c2*c - 70.0*c2*c + 15.0*c)/8.0; - plg[0][6] = (11.0*c*plg[0][5] - 5.0*plg[0][4])/6.0; - /* plg[0][7] = (13.0*c*plg[0][6] - 6.0*plg[0][5])/7.0; */ - plg[1][1] = s; - plg[1][2] = 3.0*c*s; - plg[1][3] = 1.5*(5.0*c2-1.0)*s; - plg[1][4] = 2.5*(7.0*c2*c-3.0*c)*s; - plg[1][5] = 1.875*(21.0*c4 - 14.0*c2 +1.0)*s; - plg[1][6] = (11.0*c*plg[1][5]-6.0*plg[1][4])/5.0; - /* plg[1][7] = (13.0*c*plg[1][6]-7.0*plg[1][5])/6.0; */ - /* plg[1][8] = (15.0*c*plg[1][7]-8.0*plg[1][6])/7.0; */ - plg[2][2] = 3.0*s2; - plg[2][3] = 15.0*s2*c; - plg[2][4] = 7.5*(7.0*c2 -1.0)*s2; - plg[2][5] = 3.0*c*plg[2][4]-2.0*plg[2][3]; - plg[2][6] =(11.0*c*plg[2][5]-7.0*plg[2][4])/4.0; - plg[2][7] =(13.0*c*plg[2][6]-8.0*plg[2][5])/5.0; - plg[3][3] = 15.0*s2*s; - plg[3][4] = 105.0*s2*s*c; - plg[3][5] =(9.0*c*plg[3][4]-7.*plg[3][3])/2.0; - plg[3][6] =(11.0*c*plg[3][5]-8.*plg[3][4])/3.0; - - if (!(((flags->sw[7]==0)&&(flags->sw[8]==0))&&(flags->sw[14]==0))) - { - stloc = sin(hr*tloc); - ctloc = cos(hr*tloc); - s2tloc = sin(2.0*hr*tloc); - c2tloc = cos(2.0*hr*tloc); - s3tloc = sin(3.0*hr*tloc); - c3tloc = cos(3.0*hr*tloc); - } - - cd32 = cos(dr*(input->doy-p[31])); - cd18 = cos(2.0*dr*(input->doy-p[17])); - cd14 = cos(dr*(input->doy-p[13])); - cd39 = cos(2.0*dr*(input->doy-p[38])); - p32=p[31]; - p18=p[17]; - p14=p[13]; - p39=p[38]; - - /* F10.7 EFFECT */ - df = input->f107 - input->f107A; - dfa = input->f107A - 150.0; - t[0] = p[19]*df*(1.0+p[59]*dfa) + p[20]*df*df + p[21]*dfa + p[29]*pow(dfa,2.0); - f1 = 1.0 + (p[47]*dfa +p[19]*df+p[20]*df*df)*flags->swc[1]; - f2 = 1.0 + (p[49]*dfa+p[19]*df+p[20]*df*df)*flags->swc[1]; - - /* TIME INDEPENDENT */ - t[1] = (p[1]*plg[0][2]+ p[2]*plg[0][4]+p[22]*plg[0][6]) + - (p[14]*plg[0][2])*dfa*flags->swc[1] +p[26]*plg[0][1]; - - /* SYMMETRICAL ANNUAL */ - t[2] = p[18]*cd32; - - /* SYMMETRICAL SEMIANNUAL */ - t[3] = (p[15]+p[16]*plg[0][2])*cd18; - - /* ASYMMETRICAL ANNUAL */ - t[4] = f1*(p[9]*plg[0][1]+p[10]*plg[0][3])*cd14; - - /* ASYMMETRICAL SEMIANNUAL */ - t[5] = p[37]*plg[0][1]*cd39; - - /* DIURNAL */ - if (flags->sw[7]) - { - double t71, t72; - t71 = (p[11]*plg[1][2])*cd14*flags->swc[5]; - t72 = (p[12]*plg[1][2])*cd14*flags->swc[5]; - t[6] = f2*((p[3]*plg[1][1] + p[4]*plg[1][3] + p[27]*plg[1][5] + t71) * \ - ctloc + (p[6]*plg[1][1] + p[7]*plg[1][3] + p[28]*plg[1][5] \ - + t72)*stloc); - } +/* CALCULATE G(L) FUNCTION + * Upper Thermosphere Parameters */ + double t[15]; + int i,j; + int sw9=1; + double apd; + double xlong; + double tloc; + double c, s, c2, c4, s2; + double sr = 7.2722E-5; + double dgtr = 1.74533E-2; + double dr = 1.72142E-2; + double hr = 0.2618; + double cd32, cd18, cd14, cd39; + double p32, p18, p14, p39; + double df, dfa; + double f1, f2; + double tinf; + struct ap_array *ap; + + tloc=input->lst; + for (j=0;j<14;j++) + t[j]=0; + if (flags->sw[9]>0) + sw9=1; + else if (flags->sw[9]<0) + sw9=-1; + xlong = input->g_long; + + /* calculate legendre polynomials */ + c = sin(input->g_lat * dgtr); + s = cos(input->g_lat * dgtr); + c2 = c*c; + c4 = c2*c2; + s2 = s*s; + + plg[0][1] = c; + plg[0][2] = 0.5*(3.0*c2 -1.0); + plg[0][3] = 0.5*(5.0*c*c2-3.0*c); + plg[0][4] = (35.0*c4 - 30.0*c2 + 3.0)/8.0; + plg[0][5] = (63.0*c2*c2*c - 70.0*c2*c + 15.0*c)/8.0; + plg[0][6] = (11.0*c*plg[0][5] - 5.0*plg[0][4])/6.0; +/* plg[0][7] = (13.0*c*plg[0][6] - 6.0*plg[0][5])/7.0; */ + plg[1][1] = s; + plg[1][2] = 3.0*c*s; + plg[1][3] = 1.5*(5.0*c2-1.0)*s; + plg[1][4] = 2.5*(7.0*c2*c-3.0*c)*s; + plg[1][5] = 1.875*(21.0*c4 - 14.0*c2 +1.0)*s; + plg[1][6] = (11.0*c*plg[1][5]-6.0*plg[1][4])/5.0; +/* plg[1][7] = (13.0*c*plg[1][6]-7.0*plg[1][5])/6.0; */ +/* plg[1][8] = (15.0*c*plg[1][7]-8.0*plg[1][6])/7.0; */ + plg[2][2] = 3.0*s2; + plg[2][3] = 15.0*s2*c; + plg[2][4] = 7.5*(7.0*c2 -1.0)*s2; + plg[2][5] = 3.0*c*plg[2][4]-2.0*plg[2][3]; + plg[2][6] =(11.0*c*plg[2][5]-7.0*plg[2][4])/4.0; + plg[2][7] =(13.0*c*plg[2][6]-8.0*plg[2][5])/5.0; + plg[3][3] = 15.0*s2*s; + plg[3][4] = 105.0*s2*s*c; + plg[3][5] =(9.0*c*plg[3][4]-7.*plg[3][3])/2.0; + plg[3][6] =(11.0*c*plg[3][5]-8.*plg[3][4])/3.0; + + if (!(((flags->sw[7]==0)&&(flags->sw[8]==0))&&(flags->sw[14]==0))) { + stloc = sin(hr*tloc); + ctloc = cos(hr*tloc); + s2tloc = sin(2.0*hr*tloc); + c2tloc = cos(2.0*hr*tloc); + s3tloc = sin(3.0*hr*tloc); + c3tloc = cos(3.0*hr*tloc); + } + + cd32 = cos(dr*(input->doy-p[31])); + cd18 = cos(2.0*dr*(input->doy-p[17])); + cd14 = cos(dr*(input->doy-p[13])); + cd39 = cos(2.0*dr*(input->doy-p[38])); + p32=p[31]; + p18=p[17]; + p14=p[13]; + p39=p[38]; + + /* F10.7 EFFECT */ + df = input->f107 - input->f107A; + dfa = input->f107A - 150.0; + t[0] = p[19]*df*(1.0+p[59]*dfa) + p[20]*df*df + p[21]*dfa + p[29]*pow(dfa,2.0); + f1 = 1.0 + (p[47]*dfa +p[19]*df+p[20]*df*df)*flags->swc[1]; + f2 = 1.0 + (p[49]*dfa+p[19]*df+p[20]*df*df)*flags->swc[1]; + + /* TIME INDEPENDENT */ + t[1] = (p[1]*plg[0][2]+ p[2]*plg[0][4]+p[22]*plg[0][6]) + + (p[14]*plg[0][2])*dfa*flags->swc[1] +p[26]*plg[0][1]; + + /* SYMMETRICAL ANNUAL */ + t[2] = p[18]*cd32; + + /* SYMMETRICAL SEMIANNUAL */ + t[3] = (p[15]+p[16]*plg[0][2])*cd18; + + /* ASYMMETRICAL ANNUAL */ + t[4] = f1*(p[9]*plg[0][1]+p[10]*plg[0][3])*cd14; + + /* ASYMMETRICAL SEMIANNUAL */ + t[5] = p[37]*plg[0][1]*cd39; + + /* DIURNAL */ + if (flags->sw[7]) { + double t71, t72; + t71 = (p[11]*plg[1][2])*cd14*flags->swc[5]; + t72 = (p[12]*plg[1][2])*cd14*flags->swc[5]; + t[6] = f2*((p[3]*plg[1][1] + p[4]*plg[1][3] + p[27]*plg[1][5] + t71) * \ + ctloc + (p[6]*plg[1][1] + p[7]*plg[1][3] + p[28]*plg[1][5] \ + + t72)*stloc); +} - /* SEMIDIURNAL */ - if (flags->sw[8]) - { - double t81, t82; - t81 = (p[23]*plg[2][3]+p[35]*plg[2][5])*cd14*flags->swc[5]; - t82 = (p[33]*plg[2][3]+p[36]*plg[2][5])*cd14*flags->swc[5]; - t[7] = f2*((p[5]*plg[2][2]+ p[41]*plg[2][4] + t81)*c2tloc +(p[8]*plg[2][2] + p[42]*plg[2][4] + t82)*s2tloc); - } + /* SEMIDIURNAL */ + if (flags->sw[8]) { + double t81, t82; + t81 = (p[23]*plg[2][3]+p[35]*plg[2][5])*cd14*flags->swc[5]; + t82 = (p[33]*plg[2][3]+p[36]*plg[2][5])*cd14*flags->swc[5]; + t[7] = f2*((p[5]*plg[2][2]+ p[41]*plg[2][4] + t81)*c2tloc +(p[8]*plg[2][2] + p[42]*plg[2][4] + t82)*s2tloc); + } + + /* TERDIURNAL */ + if (flags->sw[14]) { + t[13] = f2 * ((p[39]*plg[3][3]+(p[93]*plg[3][4]+p[46]*plg[3][6])*cd14*flags->swc[5])* s3tloc +(p[40]*plg[3][3]+(p[94]*plg[3][4]+p[48]*plg[3][6])*cd14*flags->swc[5])* c3tloc); +} - /* TERDIURNAL */ - if (flags->sw[14]) - { - t[13] = f2 * ((p[39]*plg[3][3]+(p[93]*plg[3][4]+p[46]*plg[3][6])*cd14*flags->swc[5])* s3tloc +(p[40]*plg[3][3]+(p[94]*plg[3][4]+p[48]*plg[3][6])*cd14*flags->swc[5])* c3tloc); + /* magnetic activity based on daily ap */ + if (flags->sw[9]==-1) { + ap = input->ap_a; + if (p[51]!=0) { + double exp1; + exp1 = exp(-10800.0*sqrt(p[51]*p[51])/(1.0+p[138]*(45.0-sqrt(input->g_lat*input->g_lat)))); + if (exp1>0.99999) + exp1=0.99999; + if (p[24]<1.0E-4) + p[24]=1.0E-4; + apt[0]=sg0(exp1,p,ap->a); + /* apt[1]=sg2(exp1,p,ap->a); + apt[2]=sg0(exp2,p,ap->a); + apt[3]=sg2(exp2,p,ap->a); + */ + if (flags->sw[9]) { + t[8] = apt[0]*(p[50]+p[96]*plg[0][2]+p[54]*plg[0][4]+ \ + (p[125]*plg[0][1]+p[126]*plg[0][3]+p[127]*plg[0][5])*cd14*flags->swc[5]+ \ + (p[128]*plg[1][1]+p[129]*plg[1][3]+p[130]*plg[1][5])*flags->swc[7]* \ + cos(hr*(tloc-p[131]))); + } } - - /* magnetic activity based on daily ap */ - if (flags->sw[9]==-1) - { - ap = input->ap_a; - if (p[51]!=0) - { - double exp1; - exp1 = exp(-10800.0*sqrt(p[51]*p[51])/(1.0+p[138]*(45.0-sqrt(input->g_lat*input->g_lat)))); - if (exp1>0.99999) - exp1=0.99999; - if (p[24]<1.0E-4) - p[24]=1.0E-4; - apt[0]=sg0(exp1,p,ap->a); - /* apt[1]=sg2(exp1,p,ap->a); - apt[2]=sg0(exp2,p,ap->a); - apt[3]=sg2(exp2,p,ap->a); - */ - if (flags->sw[9]) - { - t[8] = apt[0]*(p[50]+p[96]*plg[0][2]+p[54]*plg[0][4]+ \ - (p[125]*plg[0][1]+p[126]*plg[0][3]+p[127]*plg[0][5])*cd14*flags->swc[5]+ \ - (p[128]*plg[1][1]+p[129]*plg[1][3]+p[130]*plg[1][5])*flags->swc[7]* \ - cos(hr*(tloc-p[131]))); - } - } + } else { + double p44, p45; + apd=input->ap-4.0; + p44=p[43]; + p45=p[44]; + if (p44<0) + p44 = 1.0E-5; + apdf = apd + (p45-1.0)*(apd + (exp(-p44 * apd) - 1.0)/p44); + if (flags->sw[9]) { + t[8]=apdf*(p[32]+p[45]*plg[0][2]+p[34]*plg[0][4]+ \ + (p[100]*plg[0][1]+p[101]*plg[0][3]+p[102]*plg[0][5])*cd14*flags->swc[5]+ + (p[121]*plg[1][1]+p[122]*plg[1][3]+p[123]*plg[1][5])*flags->swc[7]* + cos(hr*(tloc-p[124]))); } - else - { - double p44, p45; - apd=input->ap-4.0; - p44=p[43]; - p45=p[44]; - if (p44<0) - p44 = 1.0E-5; - apdf = apd + (p45-1.0)*(apd + (exp(-p44 * apd) - 1.0)/p44); - if (flags->sw[9]) - { - t[8]=apdf*(p[32]+p[45]*plg[0][2]+p[34]*plg[0][4]+ \ - (p[100]*plg[0][1]+p[101]*plg[0][3]+p[102]*plg[0][5])*cd14*flags->swc[5]+ - (p[121]*plg[1][1]+p[122]*plg[1][3]+p[123]*plg[1][5])*flags->swc[7]* - cos(hr*(tloc-p[124]))); - } + } + + if ((flags->sw[10])&&(input->g_long>-1000.0)) { + + /* longitudinal */ + if (flags->sw[11]) { + t[10] = (1.0 + p[80]*dfa*flags->swc[1])* \ + ((p[64]*plg[1][2]+p[65]*plg[1][4]+p[66]*plg[1][6]\ + +p[103]*plg[1][1]+p[104]*plg[1][3]+p[105]*plg[1][5]\ + +flags->swc[5]*(p[109]*plg[1][1]+p[110]*plg[1][3]+p[111]*plg[1][5])*cd14)* \ + cos(dgtr*input->g_long) \ + +(p[90]*plg[1][2]+p[91]*plg[1][4]+p[92]*plg[1][6]\ + +p[106]*plg[1][1]+p[107]*plg[1][3]+p[108]*plg[1][5]\ + +flags->swc[5]*(p[112]*plg[1][1]+p[113]*plg[1][3]+p[114]*plg[1][5])*cd14)* \ + sin(dgtr*input->g_long)); } - if ((flags->sw[10])&&(input->g_long>-1000.0)) - { - - /* longitudinal */ - if (flags->sw[11]) - { - t[10] = (1.0 + p[80]*dfa*flags->swc[1])* \ - ((p[64]*plg[1][2]+p[65]*plg[1][4]+p[66]*plg[1][6]\ - +p[103]*plg[1][1]+p[104]*plg[1][3]+p[105]*plg[1][5]\ - +flags->swc[5]*(p[109]*plg[1][1]+p[110]*plg[1][3]+p[111]*plg[1][5])*cd14)* \ - cos(dgtr*input->g_long) \ - +(p[90]*plg[1][2]+p[91]*plg[1][4]+p[92]*plg[1][6]\ - +p[106]*plg[1][1]+p[107]*plg[1][3]+p[108]*plg[1][5]\ - +flags->swc[5]*(p[112]*plg[1][1]+p[113]*plg[1][3]+p[114]*plg[1][5])*cd14)* \ - sin(dgtr*input->g_long)); - } - - /* ut and mixed ut, longitude */ - if (flags->sw[12]) - { - t[11]=(1.0+p[95]*plg[0][1])*(1.0+p[81]*dfa*flags->swc[1])*\ - (1.0+p[119]*plg[0][1]*flags->swc[5]*cd14)*\ - ((p[68]*plg[0][1]+p[69]*plg[0][3]+p[70]*plg[0][5])*\ - cos(sr*(input->sec-p[71]))); - t[11]+=flags->swc[11]*\ - (p[76]*plg[2][3]+p[77]*plg[2][5]+p[78]*plg[2][7])*\ - cos(sr*(input->sec-p[79])+2.0*dgtr*input->g_long)*(1.0+p[137]*dfa*flags->swc[1]); - } + /* ut and mixed ut, longitude */ + if (flags->sw[12]){ + t[11]=(1.0+p[95]*plg[0][1])*(1.0+p[81]*dfa*flags->swc[1])*\ + (1.0+p[119]*plg[0][1]*flags->swc[5]*cd14)*\ + ((p[68]*plg[0][1]+p[69]*plg[0][3]+p[70]*plg[0][5])*\ + cos(sr*(input->sec-p[71]))); + t[11]+=flags->swc[11]*\ + (p[76]*plg[2][3]+p[77]*plg[2][5]+p[78]*plg[2][7])*\ + cos(sr*(input->sec-p[79])+2.0*dgtr*input->g_long)*(1.0+p[137]*dfa*flags->swc[1]); + } - /* ut, longitude magnetic activity */ - if (flags->sw[13]) - { - if (flags->sw[9]==-1) - { - if (p[51]) - { - t[12]=apt[0]*flags->swc[11]*(1.+p[132]*plg[0][1])*\ - ((p[52]*plg[1][2]+p[98]*plg[1][4]+p[67]*plg[1][6])*\ - cos(dgtr*(input->g_long-p[97])))\ - +apt[0]*flags->swc[11]*flags->swc[5]*\ - (p[133]*plg[1][1]+p[134]*plg[1][3]+p[135]*plg[1][5])*\ - cd14*cos(dgtr*(input->g_long-p[136])) \ - +apt[0]*flags->swc[12]* \ - (p[55]*plg[0][1]+p[56]*plg[0][3]+p[57]*plg[0][5])*\ - cos(sr*(input->sec-p[58])); - } - } - else - { - t[12] = apdf*flags->swc[11]*(1.0+p[120]*plg[0][1])*\ - ((p[60]*plg[1][2]+p[61]*plg[1][4]+p[62]*plg[1][6])*\ - cos(dgtr*(input->g_long-p[63])))\ - +apdf*flags->swc[11]*flags->swc[5]* \ - (p[115]*plg[1][1]+p[116]*plg[1][3]+p[117]*plg[1][5])* \ - cd14*cos(dgtr*(input->g_long-p[118])) \ - + apdf*flags->swc[12]* \ - (p[83]*plg[0][1]+p[84]*plg[0][3]+p[85]*plg[0][5])* \ - cos(sr*(input->sec-p[75])); - } + /* ut, longitude magnetic activity */ + if (flags->sw[13]) { + if (flags->sw[9]==-1) { + if (p[51]) { + t[12]=apt[0]*flags->swc[11]*(1.+p[132]*plg[0][1])*\ + ((p[52]*plg[1][2]+p[98]*plg[1][4]+p[67]*plg[1][6])*\ + cos(dgtr*(input->g_long-p[97])))\ + +apt[0]*flags->swc[11]*flags->swc[5]*\ + (p[133]*plg[1][1]+p[134]*plg[1][3]+p[135]*plg[1][5])*\ + cd14*cos(dgtr*(input->g_long-p[136])) \ + +apt[0]*flags->swc[12]* \ + (p[55]*plg[0][1]+p[56]*plg[0][3]+p[57]*plg[0][5])*\ + cos(sr*(input->sec-p[58])); } + } else { + t[12] = apdf*flags->swc[11]*(1.0+p[120]*plg[0][1])*\ + ((p[60]*plg[1][2]+p[61]*plg[1][4]+p[62]*plg[1][6])*\ + cos(dgtr*(input->g_long-p[63])))\ + +apdf*flags->swc[11]*flags->swc[5]* \ + (p[115]*plg[1][1]+p[116]*plg[1][3]+p[117]*plg[1][5])* \ + cd14*cos(dgtr*(input->g_long-p[118])) \ + + apdf*flags->swc[12]* \ + (p[83]*plg[0][1]+p[84]*plg[0][3]+p[85]*plg[0][5])* \ + cos(sr*(input->sec-p[75])); + } } + } - /* parms not used: 82, 89, 99, 139-149 */ - tinf = p[30]; - for (i=0;i<14;i++) - tinf = tinf + fabs(flags->sw[i+1])*t[i]; - return tinf; + /* parms not used: 82, 89, 99, 139-149 */ + tinf = p[30]; + for (i=0;i<14;i++) + tinf = tinf + fabs(flags->sw[i+1])*t[i]; + return tinf; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double MSIS::glob7s(double *p, struct nrlmsise_input *input, - struct nrlmsise_flags *flags) + struct nrlmsise_flags *flags) { - /* VERSION OF GLOBE FOR LOWER ATMOSPHERE 10/26/99 - */ - double pset=2.0; - double t[14]; - double tt; - double cd32, cd18, cd14, cd39; - double p32, p18, p14, p39; - int i,j; - double dr=1.72142E-2; - double dgtr=1.74533E-2; - /* confirm parameter set */ - if (p[99]==0) - p[99]=pset; - if (p[99]!=pset) - { - cerr << "Wrong parameter set for glob7s" << endl; - return -1; - } - for (j=0;j<14;j++) - t[j]=0.0; - cd32 = cos(dr*(input->doy-p[31])); - cd18 = cos(2.0*dr*(input->doy-p[17])); - cd14 = cos(dr*(input->doy-p[13])); - cd39 = cos(2.0*dr*(input->doy-p[38])); - p32=p[31]; - p18=p[17]; - p14=p[13]; - p39=p[38]; - - /* F10.7 */ - t[0] = p[21]*dfa; - - /* time independent */ - t[1]=p[1]*plg[0][2] + p[2]*plg[0][4] + p[22]*plg[0][6] + p[26]*plg[0][1] + p[14]*plg[0][3] + p[59]*plg[0][5]; - - /* SYMMETRICAL ANNUAL */ - t[2]=(p[18]+p[47]*plg[0][2]+p[29]*plg[0][4])*cd32; - - /* SYMMETRICAL SEMIANNUAL */ - t[3]=(p[15]+p[16]*plg[0][2]+p[30]*plg[0][4])*cd18; - - /* ASYMMETRICAL ANNUAL */ - t[4]=(p[9]*plg[0][1]+p[10]*plg[0][3]+p[20]*plg[0][5])*cd14; - - /* ASYMMETRICAL SEMIANNUAL */ - t[5]=(p[37]*plg[0][1])*cd39; - - /* DIURNAL */ - if (flags->sw[7]) - { - double t71, t72; - t71 = p[11]*plg[1][2]*cd14*flags->swc[5]; - t72 = p[12]*plg[1][2]*cd14*flags->swc[5]; - t[6] = ((p[3]*plg[1][1] + p[4]*plg[1][3] + t71) * ctloc + (p[6]*plg[1][1] + p[7]*plg[1][3] + t72) * stloc) ; - } - - /* SEMIDIURNAL */ - if (flags->sw[8]) - { - double t81, t82; - t81 = (p[23]*plg[2][3]+p[35]*plg[2][5])*cd14*flags->swc[5]; - t82 = (p[33]*plg[2][3]+p[36]*plg[2][5])*cd14*flags->swc[5]; - t[7] = ((p[5]*plg[2][2] + p[41]*plg[2][4] + t81) * c2tloc + (p[8]*plg[2][2] + p[42]*plg[2][4] + t82) * s2tloc); - } - - /* TERDIURNAL */ - if (flags->sw[14]) - { - t[13] = p[39] * plg[3][3] * s3tloc + p[40] * plg[3][3] * c3tloc; - } - - /* MAGNETIC ACTIVITY */ - if (flags->sw[9]) - { - if (flags->sw[9]==1) - t[8] = apdf * (p[32] + p[45] * plg[0][2] * flags->swc[2]); - if (flags->sw[9]==-1) - t[8]=(p[50]*apt[0] + p[96]*plg[0][2] * apt[0]*flags->swc[2]); - } - - /* LONGITUDINAL */ - if (!((flags->sw[10]==0) || (flags->sw[11]==0) || (input->g_long<=-1000.0))) - { - t[10] = (1.0 + plg[0][1]*(p[80]*flags->swc[5]*cos(dr*(input->doy-p[81]))\ - +p[85]*flags->swc[6]*cos(2.0*dr*(input->doy-p[86])))\ - +p[83]*flags->swc[3]*cos(dr*(input->doy-p[84]))\ - +p[87]*flags->swc[4]*cos(2.0*dr*(input->doy-p[88])))\ - *((p[64]*plg[1][2]+p[65]*plg[1][4]+p[66]*plg[1][6]\ - +p[74]*plg[1][1]+p[75]*plg[1][3]+p[76]*plg[1][5]\ - )*cos(dgtr*input->g_long)\ - +(p[90]*plg[1][2]+p[91]*plg[1][4]+p[92]*plg[1][6]\ - +p[77]*plg[1][1]+p[78]*plg[1][3]+p[79]*plg[1][5]\ - )*sin(dgtr*input->g_long)); - } - tt=0; - for (i=0;i<14;i++) - tt+=fabs(flags->sw[i+1])*t[i]; - return tt; +/* VERSION OF GLOBE FOR LOWER ATMOSPHERE 10/26/99 + */ + double pset=2.0; + double t[14]; + double tt; + double cd32, cd18, cd14, cd39; + double p32, p18, p14, p39; + int i,j; + double dr=1.72142E-2; + double dgtr=1.74533E-2; + /* confirm parameter set */ + if (p[99]==0) + p[99]=pset; + if (p[99]!=pset) { + cerr << "Wrong parameter set for glob7s" << endl; + return -1; + } + for (j=0;j<14;j++) + t[j]=0.0; + cd32 = cos(dr*(input->doy-p[31])); + cd18 = cos(2.0*dr*(input->doy-p[17])); + cd14 = cos(dr*(input->doy-p[13])); + cd39 = cos(2.0*dr*(input->doy-p[38])); + p32=p[31]; + p18=p[17]; + p14=p[13]; + p39=p[38]; + + /* F10.7 */ + t[0] = p[21]*dfa; + + /* time independent */ + t[1]=p[1]*plg[0][2] + p[2]*plg[0][4] + p[22]*plg[0][6] + p[26]*plg[0][1] + p[14]*plg[0][3] + p[59]*plg[0][5]; + + /* SYMMETRICAL ANNUAL */ + t[2]=(p[18]+p[47]*plg[0][2]+p[29]*plg[0][4])*cd32; + + /* SYMMETRICAL SEMIANNUAL */ + t[3]=(p[15]+p[16]*plg[0][2]+p[30]*plg[0][4])*cd18; + + /* ASYMMETRICAL ANNUAL */ + t[4]=(p[9]*plg[0][1]+p[10]*plg[0][3]+p[20]*plg[0][5])*cd14; + + /* ASYMMETRICAL SEMIANNUAL */ + t[5]=(p[37]*plg[0][1])*cd39; + + /* DIURNAL */ + if (flags->sw[7]) { + double t71, t72; + t71 = p[11]*plg[1][2]*cd14*flags->swc[5]; + t72 = p[12]*plg[1][2]*cd14*flags->swc[5]; + t[6] = ((p[3]*plg[1][1] + p[4]*plg[1][3] + t71) * ctloc + (p[6]*plg[1][1] + p[7]*plg[1][3] + t72) * stloc) ; + } + + /* SEMIDIURNAL */ + if (flags->sw[8]) { + double t81, t82; + t81 = (p[23]*plg[2][3]+p[35]*plg[2][5])*cd14*flags->swc[5]; + t82 = (p[33]*plg[2][3]+p[36]*plg[2][5])*cd14*flags->swc[5]; + t[7] = ((p[5]*plg[2][2] + p[41]*plg[2][4] + t81) * c2tloc + (p[8]*plg[2][2] + p[42]*plg[2][4] + t82) * s2tloc); + } + + /* TERDIURNAL */ + if (flags->sw[14]) { + t[13] = p[39] * plg[3][3] * s3tloc + p[40] * plg[3][3] * c3tloc; + } + + /* MAGNETIC ACTIVITY */ + if (flags->sw[9]) { + if (flags->sw[9]==1) + t[8] = apdf * (p[32] + p[45] * plg[0][2] * flags->swc[2]); + if (flags->sw[9]==-1) + t[8]=(p[50]*apt[0] + p[96]*plg[0][2] * apt[0]*flags->swc[2]); + } + + /* LONGITUDINAL */ + if (!((flags->sw[10]==0) || (flags->sw[11]==0) || (input->g_long<=-1000.0))) { + t[10] = (1.0 + plg[0][1]*(p[80]*flags->swc[5]*cos(dr*(input->doy-p[81]))\ + +p[85]*flags->swc[6]*cos(2.0*dr*(input->doy-p[86])))\ + +p[83]*flags->swc[3]*cos(dr*(input->doy-p[84]))\ + +p[87]*flags->swc[4]*cos(2.0*dr*(input->doy-p[88])))\ + *((p[64]*plg[1][2]+p[65]*plg[1][4]+p[66]*plg[1][6]\ + +p[74]*plg[1][1]+p[75]*plg[1][3]+p[76]*plg[1][5]\ + )*cos(dgtr*input->g_long)\ + +(p[90]*plg[1][2]+p[91]*plg[1][4]+p[92]*plg[1][6]\ + +p[77]*plg[1][1]+p[78]*plg[1][3]+p[79]*plg[1][5]\ + )*sin(dgtr*input->g_long)); + } + tt=0; + for (i=0;i<14;i++) + tt+=fabs(flags->sw[i+1])*t[i]; + return tt; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void MSIS::gtd7(struct nrlmsise_input *input, struct nrlmsise_flags *flags, - struct nrlmsise_output *output) + struct nrlmsise_output *output) { - double xlat; - double xmm; - int mn3 = 5; - double zn3[5]={32.5,20.0,15.0,10.0,0.0}; - int mn2 = 4; - double zn2[4]={72.5,55.0,45.0,32.5}; - double altt; - double zmix=62.5; - double tmp; - double dm28m; - double tz; - double dmc; - double dmr; - double dz28; - struct nrlmsise_output soutput; - int i; - - tselec(flags); - - /* Latitude variation of gravity (none for sw[2]=0) */ - xlat=input->g_lat; - if (flags->sw[2]==0) - xlat=45.0; - glatf(xlat, &gsurf, &re); - - xmm = pdm[2][4]; - - /* THERMOSPHERE / MESOSPHERE (above zn2[0]) */ - if (input->alt>zn2[0]) - altt=input->alt; - else - altt=zn2[0]; - - tmp=input->alt; - input->alt=altt; - gts7(input, flags, &soutput); + double xlat; + double xmm; + int mn3 = 5; + double zn3[5]={32.5,20.0,15.0,10.0,0.0}; + int mn2 = 4; + double zn2[4]={72.5,55.0,45.0,32.5}; + double altt; + double zmix=62.5; + double tmp; + double dm28m; + double tz; + double dmc; + double dmr; + double dz28; + struct nrlmsise_output soutput; + int i; + + tselec(flags); + + /* Latitude variation of gravity (none for sw[2]=0) */ + xlat=input->g_lat; + if (flags->sw[2]==0) + xlat=45.0; + glatf(xlat, &gsurf, &re); + + xmm = pdm[2][4]; + + /* THERMOSPHERE / MESOSPHERE (above zn2[0]) */ + if (input->alt>zn2[0]) altt=input->alt; - input->alt=tmp; - if (flags->sw[0]) /* metric adjustment */ - dm28m=dm28*1.0E6; - else - dm28m=dm28; - output->t[0]=soutput.t[0]; - output->t[1]=soutput.t[1]; - if (input->alt>=zn2[0]) - { - for (i=0;i<9;i++) - output->d[i]=soutput.d[i]; - return; - } - - /* LOWER MESOSPHERE/UPPER STRATOSPHERE (between zn3[0] and zn2[0]) - * Temperature at nodes and gradients at end nodes - * Inverse temperature a linear function of spherical harmonics - */ - meso_tgn2[0]=meso_tgn1[1]; - meso_tn2[0]=meso_tn1[4]; - meso_tn2[1]=pma[0][0]*pavgm[0]/(1.0-flags->sw[20]*glob7s(pma[0], input, flags)); - meso_tn2[2]=pma[1][0]*pavgm[1]/(1.0-flags->sw[20]*glob7s(pma[1], input, flags)); - meso_tn2[3]=pma[2][0]*pavgm[2]/(1.0-flags->sw[20]*flags->sw[22]*glob7s(pma[2], input, flags)); - meso_tgn2[1]=pavgm[8]*pma[9][0]*(1.0+flags->sw[20]*flags->sw[22]*glob7s(pma[9], input, flags))*meso_tn2[3]*meso_tn2[3]/(pow((pma[2][0]*pavgm[2]),2.0)); - meso_tn3[0]=meso_tn2[3]; - - if (input->alt<zn3[0]) - { - /* LOWER STRATOSPHERE AND TROPOSPHERE (below zn3[0]) - * Temperature at nodes and gradients at end nodes - * Inverse temperature a linear function of spherical harmonics - */ - meso_tgn3[0]=meso_tgn2[1]; - meso_tn3[1]=pma[3][0]*pavgm[3]/(1.0-flags->sw[22]*glob7s(pma[3], input, flags)); - meso_tn3[2]=pma[4][0]*pavgm[4]/(1.0-flags->sw[22]*glob7s(pma[4], input, flags)); - meso_tn3[3]=pma[5][0]*pavgm[5]/(1.0-flags->sw[22]*glob7s(pma[5], input, flags)); - meso_tn3[4]=pma[6][0]*pavgm[6]/(1.0-flags->sw[22]*glob7s(pma[6], input, flags)); - meso_tgn3[1]=pma[7][0]*pavgm[7]*(1.0+flags->sw[22]*glob7s(pma[7], input, flags)) *meso_tn3[4]*meso_tn3[4]/(pow((pma[6][0]*pavgm[6]),2.0)); - } - - /* LINEAR TRANSITION TO FULL MIXING BELOW zn2[0] */ - - dmc=0; - if (input->alt>zmix) - dmc = 1.0 - (zn2[0]-input->alt)/(zn2[0] - zmix); - dz28=soutput.d[2]; - - /**** N2 density ****/ - dmr=soutput.d[2] / dm28m - 1.0; - output->d[2]=densm(input->alt,dm28m,xmm, &tz, mn3, zn3, meso_tn3, meso_tgn3, mn2, zn2, meso_tn2, meso_tgn2); - output->d[2]=output->d[2] * (1.0 + dmr*dmc); - - /**** HE density ****/ - dmr = soutput.d[0] / (dz28 * pdm[0][1]) - 1.0; - output->d[0] = output->d[2] * pdm[0][1] * (1.0 + dmr*dmc); - - /**** O density ****/ - output->d[1] = 0; - output->d[8] = 0; - - /**** O2 density ****/ - dmr = soutput.d[3] / (dz28 * pdm[3][1]) - 1.0; - output->d[3] = output->d[2] * pdm[3][1] * (1.0 + dmr*dmc); - - /**** AR density ***/ - dmr = soutput.d[4] / (dz28 * pdm[4][1]) - 1.0; - output->d[4] = output->d[2] * pdm[4][1] * (1.0 + dmr*dmc); - - /**** Hydrogen density ****/ - output->d[6] = 0; - - /**** Atomic nitrogen density ****/ - output->d[7] = 0; - - /**** Total mass density */ - output->d[5] = 1.66E-24 * (4.0 * output->d[0] + 16.0 * output->d[1] + - 28.0 * output->d[2] + 32.0 * output->d[3] + 40.0 * output->d[4] - + output->d[6] + 14.0 * output->d[7]); - - if (flags->sw[0]) - output->d[5]=output->d[5]/1000; - - /**** temperature at altitude ****/ - dd = densm(input->alt, 1.0, 0, &tz, mn3, zn3, meso_tn3, meso_tgn3, - mn2, zn2, meso_tn2, meso_tgn2); - output->t[1]=tz; + else + altt=zn2[0]; + + tmp=input->alt; + input->alt=altt; + gts7(input, flags, &soutput); + altt=input->alt; + input->alt=tmp; + if (flags->sw[0]) /* metric adjustment */ + dm28m=dm28*1.0E6; + else + dm28m=dm28; + output->t[0]=soutput.t[0]; + output->t[1]=soutput.t[1]; + if (input->alt>=zn2[0]) { + for (i=0;i<9;i++) + output->d[i]=soutput.d[i]; + return; + } + +/* LOWER MESOSPHERE/UPPER STRATOSPHERE (between zn3[0] and zn2[0]) + * Temperature at nodes and gradients at end nodes + * Inverse temperature a linear function of spherical harmonics + */ + meso_tgn2[0]=meso_tgn1[1]; + meso_tn2[0]=meso_tn1[4]; + meso_tn2[1]=pma[0][0]*pavgm[0]/(1.0-flags->sw[20]*glob7s(pma[0], input, flags)); + meso_tn2[2]=pma[1][0]*pavgm[1]/(1.0-flags->sw[20]*glob7s(pma[1], input, flags)); + meso_tn2[3]=pma[2][0]*pavgm[2]/(1.0-flags->sw[20]*flags->sw[22]*glob7s(pma[2], input, flags)); + meso_tgn2[1]=pavgm[8]*pma[9][0]*(1.0+flags->sw[20]*flags->sw[22]*glob7s(pma[9], input, flags))*meso_tn2[3]*meso_tn2[3]/(pow((pma[2][0]*pavgm[2]),2.0)); + meso_tn3[0]=meso_tn2[3]; + + if (input->alt<zn3[0]) { +/* LOWER STRATOSPHERE AND TROPOSPHERE (below zn3[0]) + * Temperature at nodes and gradients at end nodes + * Inverse temperature a linear function of spherical harmonics + */ + meso_tgn3[0]=meso_tgn2[1]; + meso_tn3[1]=pma[3][0]*pavgm[3]/(1.0-flags->sw[22]*glob7s(pma[3], input, flags)); + meso_tn3[2]=pma[4][0]*pavgm[4]/(1.0-flags->sw[22]*glob7s(pma[4], input, flags)); + meso_tn3[3]=pma[5][0]*pavgm[5]/(1.0-flags->sw[22]*glob7s(pma[5], input, flags)); + meso_tn3[4]=pma[6][0]*pavgm[6]/(1.0-flags->sw[22]*glob7s(pma[6], input, flags)); + meso_tgn3[1]=pma[7][0]*pavgm[7]*(1.0+flags->sw[22]*glob7s(pma[7], input, flags)) *meso_tn3[4]*meso_tn3[4]/(pow((pma[6][0]*pavgm[6]),2.0)); + } + + /* LINEAR TRANSITION TO FULL MIXING BELOW zn2[0] */ + + dmc=0; + if (input->alt>zmix) + dmc = 1.0 - (zn2[0]-input->alt)/(zn2[0] - zmix); + dz28=soutput.d[2]; + + /**** N2 density ****/ + dmr=soutput.d[2] / dm28m - 1.0; + output->d[2]=densm(input->alt,dm28m,xmm, &tz, mn3, zn3, meso_tn3, meso_tgn3, mn2, zn2, meso_tn2, meso_tgn2); + output->d[2]=output->d[2] * (1.0 + dmr*dmc); + + /**** HE density ****/ + dmr = soutput.d[0] / (dz28 * pdm[0][1]) - 1.0; + output->d[0] = output->d[2] * pdm[0][1] * (1.0 + dmr*dmc); + + /**** O density ****/ + output->d[1] = 0; + output->d[8] = 0; + + /**** O2 density ****/ + dmr = soutput.d[3] / (dz28 * pdm[3][1]) - 1.0; + output->d[3] = output->d[2] * pdm[3][1] * (1.0 + dmr*dmc); + + /**** AR density ***/ + dmr = soutput.d[4] / (dz28 * pdm[4][1]) - 1.0; + output->d[4] = output->d[2] * pdm[4][1] * (1.0 + dmr*dmc); + + /**** Hydrogen density ****/ + output->d[6] = 0; + + /**** Atomic nitrogen density ****/ + output->d[7] = 0; + + /**** Total mass density */ + output->d[5] = 1.66E-24 * (4.0 * output->d[0] + 16.0 * output->d[1] + + 28.0 * output->d[2] + 32.0 * output->d[3] + 40.0 * output->d[4] + + output->d[6] + 14.0 * output->d[7]); + + if (flags->sw[0]) + output->d[5]=output->d[5]/1000; + + /**** temperature at altitude ****/ + dd = densm(input->alt, 1.0, 0, &tz, mn3, zn3, meso_tn3, meso_tgn3, + mn2, zn2, meso_tn2, meso_tgn2); + output->t[1]=tz; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void MSIS::gtd7d(struct nrlmsise_input *input, struct nrlmsise_flags *flags, - struct nrlmsise_output *output) + struct nrlmsise_output *output) { - gtd7(input, flags, output); - output->d[5] = 1.66E-24 * (4.0 * output->d[0] + 16.0 * output->d[1] + - 28.0 * output->d[2] + 32.0 * output->d[3] + 40.0 * output->d[4] - + output->d[6] + 14.0 * output->d[7] + 16.0 * output->d[8]); + gtd7(input, flags, output); + output->d[5] = 1.66E-24 * (4.0 * output->d[0] + 16.0 * output->d[1] + + 28.0 * output->d[2] + 32.0 * output->d[3] + 40.0 * output->d[4] + + output->d[6] + 14.0 * output->d[7] + 16.0 * output->d[8]); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void MSIS::ghp7(struct nrlmsise_input *input, struct nrlmsise_flags *flags, - struct nrlmsise_output *output, double press) + struct nrlmsise_output *output, double press) { - double bm = 1.3806E-19; - double rgas = 831.4; - double test = 0.00043; - double ltest = 12; - double pl, p; - double zi = 0.0; - double z; - double cl, cl2; - double ca, cd; - double xn, xm, diff; - double g, sh; - int l; - pl = log10(press); - if (pl >= -5.0) - { - if (pl>2.5) - zi = 18.06 * (3.00 - pl); - else if ((pl>0.075) && (pl<=2.5)) - zi = 14.98 * (3.08 - pl); - else if ((pl>-1) && (pl<=0.075)) - zi = 17.80 * (2.72 - pl); - else if ((pl>-2) && (pl<=-1)) - zi = 14.28 * (3.64 - pl); - else if ((pl>-4) && (pl<=-2)) - zi = 12.72 * (4.32 -pl); - else if (pl<=-4) - zi = 25.3 * (0.11 - pl); - cl = input->g_lat/90.0; - cl2 = cl*cl; - if (input->doy<182) - cd = (1.0 - (double) input->doy) / 91.25; - else - cd = ((double) input->doy) / 91.25 - 3.0; - ca = 0; - if ((pl > -1.11) && (pl<=-0.23)) - ca = 1.0; - if (pl > -0.23) - ca = (2.79 - pl) / (2.79 + 0.23); - if ((pl <= -1.11) && (pl>-3)) - ca = (-2.93 - pl)/(-2.93 + 1.11); - z = zi - 4.87 * cl * cd * ca - 1.64 * cl2 * ca + 0.31 * ca * cl; - } + double bm = 1.3806E-19; + double rgas = 831.4; + double test = 0.00043; + double ltest = 12; + double pl, p; + double zi = 0.0; + double z; + double cl, cl2; + double ca, cd; + double xn, xm, diff; + double g, sh; + int l; + pl = log10(press); + if (pl >= -5.0) { + if (pl>2.5) + zi = 18.06 * (3.00 - pl); + else if ((pl>0.075) && (pl<=2.5)) + zi = 14.98 * (3.08 - pl); + else if ((pl>-1) && (pl<=0.075)) + zi = 17.80 * (2.72 - pl); + else if ((pl>-2) && (pl<=-1)) + zi = 14.28 * (3.64 - pl); + else if ((pl>-4) && (pl<=-2)) + zi = 12.72 * (4.32 -pl); + else if (pl<=-4) + zi = 25.3 * (0.11 - pl); + cl = input->g_lat/90.0; + cl2 = cl*cl; + if (input->doy<182) + cd = (1.0 - (double) input->doy) / 91.25; else - z = 22.0 * pow((pl + 4.0),2.0) + 110.0; - - /* iteration loop */ - l = 0; - do - { - l++; - input->alt = z; - gtd7(input, flags, output); - z = input->alt; - xn = output->d[0] + output->d[1] + output->d[2] + output->d[3] + output->d[4] + output->d[6] + output->d[7]; - p = bm * xn * output->t[1]; - if (flags->sw[0]) - p = p*1.0E-6; - diff = pl - log10(p); - if (sqrt(diff*diff)<test) - return; - if (l==ltest) - { - cerr << "ERROR: ghp7 not converging for press " << press << ", diff " << diff << endl; - return; - } - xm = output->d[5] / xn / 1.66E-24; - if (flags->sw[0]) - xm = xm * 1.0E3; - g = gsurf / (pow((1.0 + z/re),2.0)); - sh = rgas * output->t[1] / (xm * g); - - /* new altitude estimate using scale height */ - if (l < 6) - z = z - sh * diff * 2.302; - else - z = z - sh * diff; + cd = ((double) input->doy) / 91.25 - 3.0; + ca = 0; + if ((pl > -1.11) && (pl<=-0.23)) + ca = 1.0; + if (pl > -0.23) + ca = (2.79 - pl) / (2.79 + 0.23); + if ((pl <= -1.11) && (pl>-3)) + ca = (-2.93 - pl)/(-2.93 + 1.11); + z = zi - 4.87 * cl * cd * ca - 1.64 * cl2 * ca + 0.31 * ca * cl; + } else + z = 22.0 * pow((pl + 4.0),2.0) + 110.0; + + /* iteration loop */ + l = 0; + do { + l++; + input->alt = z; + gtd7(input, flags, output); + z = input->alt; + xn = output->d[0] + output->d[1] + output->d[2] + output->d[3] + output->d[4] + output->d[6] + output->d[7]; + p = bm * xn * output->t[1]; + if (flags->sw[0]) + p = p*1.0E-6; + diff = pl - log10(p); + if (sqrt(diff*diff)<test) + return; + if (l==ltest) { + cerr << "ERROR: ghp7 not converging for press " << press << ", diff " << diff << endl; + return; } - while (1==1); + xm = output->d[5] / xn / 1.66E-24; + if (flags->sw[0]) + xm = xm * 1.0E3; + g = gsurf / (pow((1.0 + z/re),2.0)); + sh = rgas * output->t[1] / (xm * g); + + /* new altitude estimate using scale height */ + if (l < 6) + z = z - sh * diff * 2.302; + else + z = z - sh * diff; + } while (1==1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void MSIS::gts7(struct nrlmsise_input *input, struct nrlmsise_flags *flags, - struct nrlmsise_output *output) + struct nrlmsise_output *output) { - /* Thermospheric portion of NRLMSISE-00 - * See GTD7 for more extensive comments - * alt > 72.5 km! - */ - double za; - int i, j; - double ddum, z; - double zn1[5] = {120.0, 110.0, 100.0, 90.0, 72.5}; - double tinf; - int mn1 = 5; - double g0; - double tlb; - double s, z0, t0, tr12; - double db01, db04, db14, db16, db28, db32, db40, db48; - double zh28, zh04, zh16, zh32, zh40, zh01, zh14; - double zhm28, zhm04, zhm16, zhm32, zhm40, zhm01, zhm14; - double xmd; - double b28, b04, b16, b32, b40, b01, b14; - double tz; - double g28, g4, g16, g32, g40, g1, g14; - double zhf, xmm; - double zc04, zc16, zc32, zc40, zc01, zc14; - double hc04, hc16, hc32, hc40, hc01, hc14; - double hcc16, hcc32, hcc01, hcc14; - double zcc16, zcc32, zcc01, zcc14; - double rc16, rc32, rc01, rc14; - double rl; - double g16h, db16h, tho, zsht, zmho, zsho; - double dgtr=1.74533E-2; - double dr=1.72142E-2; - double alpha[9]={-0.38, 0.0, 0.0, 0.0, 0.17, 0.0, -0.38, 0.0, 0.0}; - double altl[8]={200.0, 300.0, 160.0, 250.0, 240.0, 450.0, 320.0, 450.0}; - double dd; - double hc216, hcc232; - za = pdl[1][15]; - zn1[0] = za; - for (j=0;j<9;j++) - output->d[j]=0; - - /* TINF VARIATIONS NOT IMPORTANT BELOW ZA OR ZN1(1) */ - if (input->alt>zn1[0]) - tinf = ptm[0]*pt[0] * \ - (1.0+flags->sw[16]*globe7(pt,input,flags)); - else - tinf = ptm[0]*pt[0]; - output->t[0]=tinf; - - /* GRADIENT VARIATIONS NOT IMPORTANT BELOW ZN1(5) */ - if (input->alt>zn1[4]) - g0 = ptm[3]*ps[0] * \ - (1.0+flags->sw[19]*globe7(ps,input,flags)); - else - g0 = ptm[3]*ps[0]; - tlb = ptm[1] * (1.0 + flags->sw[17]*globe7(pd[3],input,flags))*pd[3][0]; - s = g0 / (tinf - tlb); - - /* Lower thermosphere temp variations not significant for - * density above 300 km */ - if (input->alt<300.0) - { - meso_tn1[1]=ptm[6]*ptl[0][0]/(1.0-flags->sw[18]*glob7s(ptl[0], input, flags)); - meso_tn1[2]=ptm[2]*ptl[1][0]/(1.0-flags->sw[18]*glob7s(ptl[1], input, flags)); - meso_tn1[3]=ptm[7]*ptl[2][0]/(1.0-flags->sw[18]*glob7s(ptl[2], input, flags)); - meso_tn1[4]=ptm[4]*ptl[3][0]/(1.0-flags->sw[18]*flags->sw[20]*glob7s(ptl[3], input, flags)); - meso_tgn1[1]=ptm[8]*pma[8][0]*(1.0+flags->sw[18]*flags->sw[20]*glob7s(pma[8], input, flags))*meso_tn1[4]*meso_tn1[4]/(pow((ptm[4]*ptl[3][0]),2.0)); - } - else - { - meso_tn1[1]=ptm[6]*ptl[0][0]; - meso_tn1[2]=ptm[2]*ptl[1][0]; - meso_tn1[3]=ptm[7]*ptl[2][0]; - meso_tn1[4]=ptm[4]*ptl[3][0]; - meso_tgn1[1]=ptm[8]*pma[8][0]*meso_tn1[4]*meso_tn1[4]/(pow((ptm[4]*ptl[3][0]),2.0)); - } - - z0 = zn1[3]; - t0 = meso_tn1[3]; - tr12 = 1.0; - - /* N2 variation factor at Zlb */ - g28=flags->sw[21]*globe7(pd[2], input, flags); - - /* VARIATION OF TURBOPAUSE HEIGHT */ - zhf=pdl[1][24]*(1.0+flags->sw[5]*pdl[0][24]*sin(dgtr*input->g_lat)*cos(dr*(input->doy-pt[13]))); - output->t[0]=tinf; - xmm = pdm[2][4]; - z = input->alt; - - - /**** N2 DENSITY ****/ - - /* Diffusive density at Zlb */ - db28 = pdm[2][0]*exp(g28)*pd[2][0]; - /* Diffusive density at Alt */ - output->d[2]=densu(z,db28,tinf,tlb,28.0,alpha[2],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - dd=output->d[2]; - /* Turbopause */ - zh28=pdm[2][2]*zhf; - zhm28=pdm[2][3]*pdl[1][5]; - xmd=28.0-xmm; - /* Mixed density at Zlb */ - b28=densu(zh28,db28,tinf,tlb,xmd,(alpha[2]-1.0),&tz,ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); - if ((flags->sw[15])&&(z<=altl[2])) - { - /* Mixed density at Alt */ - dm28=densu(z,b28,tinf,tlb,xmm,alpha[2],&tz,ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - /* Net density at Alt */ - output->d[2]=dnet(output->d[2],dm28,zhm28,xmm,28.0); +/* Thermospheric portion of NRLMSISE-00 + * See GTD7 for more extensive comments + * alt > 72.5 km! + */ + double za; + int i, j; + double ddum, z; + double zn1[5] = {120.0, 110.0, 100.0, 90.0, 72.5}; + double tinf; + int mn1 = 5; + double g0; + double tlb; + double s, z0, t0, tr12; + double db01, db04, db14, db16, db28, db32, db40, db48; + double zh28, zh04, zh16, zh32, zh40, zh01, zh14; + double zhm28, zhm04, zhm16, zhm32, zhm40, zhm01, zhm14; + double xmd; + double b28, b04, b16, b32, b40, b01, b14; + double tz; + double g28, g4, g16, g32, g40, g1, g14; + double zhf, xmm; + double zc04, zc16, zc32, zc40, zc01, zc14; + double hc04, hc16, hc32, hc40, hc01, hc14; + double hcc16, hcc32, hcc01, hcc14; + double zcc16, zcc32, zcc01, zcc14; + double rc16, rc32, rc01, rc14; + double rl; + double g16h, db16h, tho, zsht, zmho, zsho; + double dgtr=1.74533E-2; + double dr=1.72142E-2; + double alpha[9]={-0.38, 0.0, 0.0, 0.0, 0.17, 0.0, -0.38, 0.0, 0.0}; + double altl[8]={200.0, 300.0, 160.0, 250.0, 240.0, 450.0, 320.0, 450.0}; + double dd; + double hc216, hcc232; + za = pdl[1][15]; + zn1[0] = za; + for (j=0;j<9;j++) + output->d[j]=0; + + /* TINF VARIATIONS NOT IMPORTANT BELOW ZA OR ZN1(1) */ + if (input->alt>zn1[0]) + tinf = ptm[0]*pt[0] * \ + (1.0+flags->sw[16]*globe7(pt,input,flags)); + else + tinf = ptm[0]*pt[0]; + output->t[0]=tinf; + + /* GRADIENT VARIATIONS NOT IMPORTANT BELOW ZN1(5) */ + if (input->alt>zn1[4]) + g0 = ptm[3]*ps[0] * \ + (1.0+flags->sw[19]*globe7(ps,input,flags)); + else + g0 = ptm[3]*ps[0]; + tlb = ptm[1] * (1.0 + flags->sw[17]*globe7(pd[3],input,flags))*pd[3][0]; + s = g0 / (tinf - tlb); + +/* Lower thermosphere temp variations not significant for + * density above 300 km */ + if (input->alt<300.0) { + meso_tn1[1]=ptm[6]*ptl[0][0]/(1.0-flags->sw[18]*glob7s(ptl[0], input, flags)); + meso_tn1[2]=ptm[2]*ptl[1][0]/(1.0-flags->sw[18]*glob7s(ptl[1], input, flags)); + meso_tn1[3]=ptm[7]*ptl[2][0]/(1.0-flags->sw[18]*glob7s(ptl[2], input, flags)); + meso_tn1[4]=ptm[4]*ptl[3][0]/(1.0-flags->sw[18]*flags->sw[20]*glob7s(ptl[3], input, flags)); + meso_tgn1[1]=ptm[8]*pma[8][0]*(1.0+flags->sw[18]*flags->sw[20]*glob7s(pma[8], input, flags))*meso_tn1[4]*meso_tn1[4]/(pow((ptm[4]*ptl[3][0]),2.0)); + } else { + meso_tn1[1]=ptm[6]*ptl[0][0]; + meso_tn1[2]=ptm[2]*ptl[1][0]; + meso_tn1[3]=ptm[7]*ptl[2][0]; + meso_tn1[4]=ptm[4]*ptl[3][0]; + meso_tgn1[1]=ptm[8]*pma[8][0]*meso_tn1[4]*meso_tn1[4]/(pow((ptm[4]*ptl[3][0]),2.0)); + } + + z0 = zn1[3]; + t0 = meso_tn1[3]; + tr12 = 1.0; + + /* N2 variation factor at Zlb */ + g28=flags->sw[21]*globe7(pd[2], input, flags); + + /* VARIATION OF TURBOPAUSE HEIGHT */ + zhf=pdl[1][24]*(1.0+flags->sw[5]*pdl[0][24]*sin(dgtr*input->g_lat)*cos(dr*(input->doy-pt[13]))); + output->t[0]=tinf; + xmm = pdm[2][4]; + z = input->alt; + + + /**** N2 DENSITY ****/ + + /* Diffusive density at Zlb */ + db28 = pdm[2][0]*exp(g28)*pd[2][0]; + /* Diffusive density at Alt */ + output->d[2]=densu(z,db28,tinf,tlb,28.0,alpha[2],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + dd=output->d[2]; + /* Turbopause */ + zh28=pdm[2][2]*zhf; + zhm28=pdm[2][3]*pdl[1][5]; + xmd=28.0-xmm; + /* Mixed density at Zlb */ + b28=densu(zh28,db28,tinf,tlb,xmd,(alpha[2]-1.0),&tz,ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); + if ((flags->sw[15])&&(z<=altl[2])) { + /* Mixed density at Alt */ + dm28=densu(z,b28,tinf,tlb,xmm,alpha[2],&tz,ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Net density at Alt */ + output->d[2]=dnet(output->d[2],dm28,zhm28,xmm,28.0); + } + + + /**** HE DENSITY ****/ + + /* Density variation factor at Zlb */ + g4 = flags->sw[21]*globe7(pd[0], input, flags); + /* Diffusive density at Zlb */ + db04 = pdm[0][0]*exp(g4)*pd[0][0]; + /* Diffusive density at Alt */ + output->d[0]=densu(z,db04,tinf,tlb, 4.,alpha[0],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + dd=output->d[0]; + if ((flags->sw[15]) && (z<altl[0])) { + /* Turbopause */ + zh04=pdm[0][2]; + /* Mixed density at Zlb */ + b04=densu(zh04,db04,tinf,tlb,4.-xmm,alpha[0]-1.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm04=densu(z,b04,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm04=zhm28; + /* Net density at Alt */ + output->d[0]=dnet(output->d[0],dm04,zhm04,xmm,4.); + /* Correction to specified mixing ratio at ground */ + rl=log(b28*pdm[0][1]/b04); + zc04=pdm[0][4]*pdl[1][0]; + hc04=pdm[0][5]*pdl[1][1]; + /* Net density corrected at Alt */ + output->d[0]=output->d[0]*ccor(z,rl,hc04,zc04); + } + + + /**** O DENSITY ****/ + + /* Density variation factor at Zlb */ + g16= flags->sw[21]*globe7(pd[1],input,flags); + /* Diffusive density at Zlb */ + db16 = pdm[1][0]*exp(g16)*pd[1][0]; + /* Diffusive density at Alt */ + output->d[1]=densu(z,db16,tinf,tlb, 16.,alpha[1],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); + dd=output->d[1]; + if ((flags->sw[15]) && (z<=altl[1])) { + /* Turbopause */ + zh16=pdm[1][2]; + /* Mixed density at Zlb */ + b16=densu(zh16,db16,tinf,tlb,16.0-xmm,(alpha[1]-1.0), &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm16=densu(z,b16,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm16=zhm28; + /* Net density at Alt */ + output->d[1]=dnet(output->d[1],dm16,zhm16,xmm,16.); + rl=pdm[1][1]*pdl[1][16]*(1.0+flags->sw[1]*pdl[0][23]*(input->f107A-150.0)); + hc16=pdm[1][5]*pdl[1][3]; + zc16=pdm[1][4]*pdl[1][2]; + hc216=pdm[1][5]*pdl[1][4]; + output->d[1]=output->d[1]*ccor2(z,rl,hc16,zc16,hc216); + /* Chemistry correction */ + hcc16=pdm[1][7]*pdl[1][13]; + zcc16=pdm[1][6]*pdl[1][12]; + rc16=pdm[1][3]*pdl[1][14]; + /* Net density corrected at Alt */ + output->d[1]=output->d[1]*ccor(z,rc16,hcc16,zcc16); + } + + + /**** O2 DENSITY ****/ + + /* Density variation factor at Zlb */ + g32= flags->sw[21]*globe7(pd[4], input, flags); + /* Diffusive density at Zlb */ + db32 = pdm[3][0]*exp(g32)*pd[4][0]; + /* Diffusive density at Alt */ + output->d[3]=densu(z,db32,tinf,tlb, 32.,alpha[3],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); + dd=output->d[3]; + if (flags->sw[15]) { + if (z<=altl[3]) { + /* Turbopause */ + zh32=pdm[3][2]; + /* Mixed density at Zlb */ + b32=densu(zh32,db32,tinf,tlb,32.-xmm,alpha[3]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm32=densu(z,b32,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm32=zhm28; + /* Net density at Alt */ + output->d[3]=dnet(output->d[3],dm32,zhm32,xmm,32.); + /* Correction to specified mixing ratio at ground */ + rl=log(b28*pdm[3][1]/b32); + hc32=pdm[3][5]*pdl[1][7]; + zc32=pdm[3][4]*pdl[1][6]; + output->d[3]=output->d[3]*ccor(z,rl,hc32,zc32); } - - - /**** HE DENSITY ****/ - - /* Density variation factor at Zlb */ - g4 = flags->sw[21]*globe7(pd[0], input, flags); - /* Diffusive density at Zlb */ - db04 = pdm[0][0]*exp(g4)*pd[0][0]; - /* Diffusive density at Alt */ - output->d[0]=densu(z,db04,tinf,tlb, 4.,alpha[0],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - dd=output->d[0]; - if ((flags->sw[15]) && (z<altl[0])) - { - /* Turbopause */ - zh04=pdm[0][2]; - /* Mixed density at Zlb */ - b04=densu(zh04,db04,tinf,tlb,4.-xmm,alpha[0]-1.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - /* Mixed density at Alt */ - dm04=densu(z,b04,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - zhm04=zhm28; - /* Net density at Alt */ - output->d[0]=dnet(output->d[0],dm04,zhm04,xmm,4.); - /* Correction to specified mixing ratio at ground */ - rl=log(b28*pdm[0][1]/b04); - zc04=pdm[0][4]*pdl[1][0]; - hc04=pdm[0][5]*pdl[1][1]; - /* Net density corrected at Alt */ - output->d[0]=output->d[0]*ccor(z,rl,hc04,zc04); - } - - - /**** O DENSITY ****/ - - /* Density variation factor at Zlb */ - g16= flags->sw[21]*globe7(pd[1],input,flags); - /* Diffusive density at Zlb */ - db16 = pdm[1][0]*exp(g16)*pd[1][0]; - /* Diffusive density at Alt */ - output->d[1]=densu(z,db16,tinf,tlb, 16.,alpha[1],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); - dd=output->d[1]; - if ((flags->sw[15]) && (z<=altl[1])) - { - /* Turbopause */ - zh16=pdm[1][2]; - /* Mixed density at Zlb */ - b16=densu(zh16,db16,tinf,tlb,16.0-xmm,(alpha[1]-1.0), &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - /* Mixed density at Alt */ - dm16=densu(z,b16,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - zhm16=zhm28; - /* Net density at Alt */ - output->d[1]=dnet(output->d[1],dm16,zhm16,xmm,16.); - rl=pdm[1][1]*pdl[1][16]*(1.0+flags->sw[1]*pdl[0][23]*(input->f107A-150.0)); - hc16=pdm[1][5]*pdl[1][3]; - zc16=pdm[1][4]*pdl[1][2]; - hc216=pdm[1][5]*pdl[1][4]; - output->d[1]=output->d[1]*ccor2(z,rl,hc16,zc16,hc216); - /* Chemistry correction */ - hcc16=pdm[1][7]*pdl[1][13]; - zcc16=pdm[1][6]*pdl[1][12]; - rc16=pdm[1][3]*pdl[1][14]; - /* Net density corrected at Alt */ - output->d[1]=output->d[1]*ccor(z,rc16,hcc16,zcc16); + /* Correction for general departure from diffusive equilibrium above Zlb */ + hcc32=pdm[3][7]*pdl[1][22]; + hcc232=pdm[3][7]*pdl[0][22]; + zcc32=pdm[3][6]*pdl[1][21]; + rc32=pdm[3][3]*pdl[1][23]*(1.+flags->sw[1]*pdl[0][23]*(input->f107A-150.)); + /* Net density corrected at Alt */ + output->d[3]=output->d[3]*ccor2(z,rc32,hcc32,zcc32,hcc232); + } + + + /**** AR DENSITY ****/ + + /* Density variation factor at Zlb */ + g40= flags->sw[20]*globe7(pd[5],input,flags); + /* Diffusive density at Zlb */ + db40 = pdm[4][0]*exp(g40)*pd[5][0]; + /* Diffusive density at Alt */ + output->d[4]=densu(z,db40,tinf,tlb, 40.,alpha[4],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + dd=output->d[4]; + if ((flags->sw[15]) && (z<=altl[4])) { + /* Turbopause */ + zh40=pdm[4][2]; + /* Mixed density at Zlb */ + b40=densu(zh40,db40,tinf,tlb,40.-xmm,alpha[4]-1.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm40=densu(z,b40,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm40=zhm28; + /* Net density at Alt */ + output->d[4]=dnet(output->d[4],dm40,zhm40,xmm,40.); + /* Correction to specified mixing ratio at ground */ + rl=log(b28*pdm[4][1]/b40); + hc40=pdm[4][5]*pdl[1][9]; + zc40=pdm[4][4]*pdl[1][8]; + /* Net density corrected at Alt */ + output->d[4]=output->d[4]*ccor(z,rl,hc40,zc40); } - /**** O2 DENSITY ****/ - - /* Density variation factor at Zlb */ - g32= flags->sw[21]*globe7(pd[4], input, flags); - /* Diffusive density at Zlb */ - db32 = pdm[3][0]*exp(g32)*pd[4][0]; - /* Diffusive density at Alt */ - output->d[3]=densu(z,db32,tinf,tlb, 32.,alpha[3],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); - dd=output->d[3]; - if (flags->sw[15]) - { - if (z<=altl[3]) - { - /* Turbopause */ - zh32=pdm[3][2]; - /* Mixed density at Zlb */ - b32=densu(zh32,db32,tinf,tlb,32.-xmm,alpha[3]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - /* Mixed density at Alt */ - dm32=densu(z,b32,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - zhm32=zhm28; - /* Net density at Alt */ - output->d[3]=dnet(output->d[3],dm32,zhm32,xmm,32.); - /* Correction to specified mixing ratio at ground */ - rl=log(b28*pdm[3][1]/b32); - hc32=pdm[3][5]*pdl[1][7]; - zc32=pdm[3][4]*pdl[1][6]; - output->d[3]=output->d[3]*ccor(z,rl,hc32,zc32); - } - /* Correction for general departure from diffusive equilibrium above Zlb */ - hcc32=pdm[3][7]*pdl[1][22]; - hcc232=pdm[3][7]*pdl[0][22]; - zcc32=pdm[3][6]*pdl[1][21]; - rc32=pdm[3][3]*pdl[1][23]*(1.+flags->sw[1]*pdl[0][23]*(input->f107A-150.)); - /* Net density corrected at Alt */ - output->d[3]=output->d[3]*ccor2(z,rc32,hcc32,zcc32,hcc232); - } - - - /**** AR DENSITY ****/ - - /* Density variation factor at Zlb */ - g40= flags->sw[20]*globe7(pd[5],input,flags); - /* Diffusive density at Zlb */ - db40 = pdm[4][0]*exp(g40)*pd[5][0]; - /* Diffusive density at Alt */ - output->d[4]=densu(z,db40,tinf,tlb, 40.,alpha[4],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - dd=output->d[4]; - if ((flags->sw[15]) && (z<=altl[4])) - { - /* Turbopause */ - zh40=pdm[4][2]; - /* Mixed density at Zlb */ - b40=densu(zh40,db40,tinf,tlb,40.-xmm,alpha[4]-1.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - /* Mixed density at Alt */ - dm40=densu(z,b40,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - zhm40=zhm28; - /* Net density at Alt */ - output->d[4]=dnet(output->d[4],dm40,zhm40,xmm,40.); - /* Correction to specified mixing ratio at ground */ - rl=log(b28*pdm[4][1]/b40); - hc40=pdm[4][5]*pdl[1][9]; - zc40=pdm[4][4]*pdl[1][8]; - /* Net density corrected at Alt */ - output->d[4]=output->d[4]*ccor(z,rl,hc40,zc40); - } - - - /**** HYDROGEN DENSITY ****/ - - /* Density variation factor at Zlb */ - g1 = flags->sw[21]*globe7(pd[6], input, flags); - /* Diffusive density at Zlb */ - db01 = pdm[5][0]*exp(g1)*pd[6][0]; - /* Diffusive density at Alt */ - output->d[6]=densu(z,db01,tinf,tlb,1.,alpha[6],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - dd=output->d[6]; - if ((flags->sw[15]) && (z<=altl[6])) - { - /* Turbopause */ - zh01=pdm[5][2]; - /* Mixed density at Zlb */ - b01=densu(zh01,db01,tinf,tlb,1.-xmm,alpha[6]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - /* Mixed density at Alt */ - dm01=densu(z,b01,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - zhm01=zhm28; - /* Net density at Alt */ - output->d[6]=dnet(output->d[6],dm01,zhm01,xmm,1.); - /* Correction to specified mixing ratio at ground */ - rl=log(b28*pdm[5][1]*sqrt(pdl[1][17]*pdl[1][17])/b01); - hc01=pdm[5][5]*pdl[1][11]; - zc01=pdm[5][4]*pdl[1][10]; - output->d[6]=output->d[6]*ccor(z,rl,hc01,zc01); - /* Chemistry correction */ - hcc01=pdm[5][7]*pdl[1][19]; - zcc01=pdm[5][6]*pdl[1][18]; - rc01=pdm[5][3]*pdl[1][20]; - /* Net density corrected at Alt */ - output->d[6]=output->d[6]*ccor(z,rc01,hcc01,zcc01); - } - - - /**** ATOMIC NITROGEN DENSITY ****/ - - /* Density variation factor at Zlb */ - g14 = flags->sw[21]*globe7(pd[7],input,flags); - /* Diffusive density at Zlb */ - db14 = pdm[6][0]*exp(g14)*pd[7][0]; - /* Diffusive density at Alt */ - output->d[7]=densu(z,db14,tinf,tlb,14.,alpha[7],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - dd=output->d[7]; - if ((flags->sw[15]) && (z<=altl[7])) - { - /* Turbopause */ - zh14=pdm[6][2]; - /* Mixed density at Zlb */ - b14=densu(zh14,db14,tinf,tlb,14.-xmm,alpha[7]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - /* Mixed density at Alt */ - dm14=densu(z,b14,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); - zhm14=zhm28; - /* Net density at Alt */ - output->d[7]=dnet(output->d[7],dm14,zhm14,xmm,14.); - /* Correction to specified mixing ratio at ground */ - rl=log(b28*pdm[6][1]*sqrt(pdl[0][2]*pdl[0][2])/b14); - hc14=pdm[6][5]*pdl[0][1]; - zc14=pdm[6][4]*pdl[0][0]; - output->d[7]=output->d[7]*ccor(z,rl,hc14,zc14); - /* Chemistry correction */ - hcc14=pdm[6][7]*pdl[0][4]; - zcc14=pdm[6][6]*pdl[0][3]; - rc14=pdm[6][3]*pdl[0][5]; - /* Net density corrected at Alt */ - output->d[7]=output->d[7]*ccor(z,rc14,hcc14,zcc14); - } - - - /**** Anomalous OXYGEN DENSITY ****/ - - g16h = flags->sw[21]*globe7(pd[8],input,flags); - db16h = pdm[7][0]*exp(g16h)*pd[8][0]; - tho = pdm[7][9]*pdl[0][6]; - dd=densu(z,db16h,tho,tho,16.,alpha[8],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); - zsht=pdm[7][5]; - zmho=pdm[7][4]; - zsho=scalh(zmho,16.0,tho); - output->d[8]=dd*exp(-zsht/zsho*(exp(-(z-zmho)/zsht)-1.)); - - - /* total mass density */ - output->d[5] = 1.66E-24*(4.0*output->d[0]+16.0*output->d[1]+28.0*output->d[2]+32.0*output->d[3]+40.0*output->d[4]+ output->d[6]+14.0*output->d[7]); - db48=1.66E-24*(4.0*db04+16.0*db16+28.0*db28+32.0*db32+40.0*db40+db01+14.0*db14); - + /**** HYDROGEN DENSITY ****/ + + /* Density variation factor at Zlb */ + g1 = flags->sw[21]*globe7(pd[6], input, flags); + /* Diffusive density at Zlb */ + db01 = pdm[5][0]*exp(g1)*pd[6][0]; + /* Diffusive density at Alt */ + output->d[6]=densu(z,db01,tinf,tlb,1.,alpha[6],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + dd=output->d[6]; + if ((flags->sw[15]) && (z<=altl[6])) { + /* Turbopause */ + zh01=pdm[5][2]; + /* Mixed density at Zlb */ + b01=densu(zh01,db01,tinf,tlb,1.-xmm,alpha[6]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm01=densu(z,b01,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm01=zhm28; + /* Net density at Alt */ + output->d[6]=dnet(output->d[6],dm01,zhm01,xmm,1.); + /* Correction to specified mixing ratio at ground */ + rl=log(b28*pdm[5][1]*sqrt(pdl[1][17]*pdl[1][17])/b01); + hc01=pdm[5][5]*pdl[1][11]; + zc01=pdm[5][4]*pdl[1][10]; + output->d[6]=output->d[6]*ccor(z,rl,hc01,zc01); + /* Chemistry correction */ + hcc01=pdm[5][7]*pdl[1][19]; + zcc01=pdm[5][6]*pdl[1][18]; + rc01=pdm[5][3]*pdl[1][20]; + /* Net density corrected at Alt */ + output->d[6]=output->d[6]*ccor(z,rc01,hcc01,zcc01); +} - /* temperature */ - z = sqrt(input->alt*input->alt); - ddum = densu(z,1.0, tinf, tlb, 0.0, 0.0, &output->t[1], ptm[5], s, mn1, zn1, meso_tn1, meso_tgn1); - if (flags->sw[0]) - { - for (i=0;i<9;i++) - output->d[i]=output->d[i]*1.0E6; - output->d[5]=output->d[5]/1000; - } + /**** ATOMIC NITROGEN DENSITY ****/ + + /* Density variation factor at Zlb */ + g14 = flags->sw[21]*globe7(pd[7],input,flags); + /* Diffusive density at Zlb */ + db14 = pdm[6][0]*exp(g14)*pd[7][0]; + /* Diffusive density at Alt */ + output->d[7]=densu(z,db14,tinf,tlb,14.,alpha[7],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + dd=output->d[7]; + if ((flags->sw[15]) && (z<=altl[7])) { + /* Turbopause */ + zh14=pdm[6][2]; + /* Mixed density at Zlb */ + b14=densu(zh14,db14,tinf,tlb,14.-xmm,alpha[7]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm14=densu(z,b14,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm14=zhm28; + /* Net density at Alt */ + output->d[7]=dnet(output->d[7],dm14,zhm14,xmm,14.); + /* Correction to specified mixing ratio at ground */ + rl=log(b28*pdm[6][1]*sqrt(pdl[0][2]*pdl[0][2])/b14); + hc14=pdm[6][5]*pdl[0][1]; + zc14=pdm[6][4]*pdl[0][0]; + output->d[7]=output->d[7]*ccor(z,rl,hc14,zc14); + /* Chemistry correction */ + hcc14=pdm[6][7]*pdl[0][4]; + zcc14=pdm[6][6]*pdl[0][3]; + rc14=pdm[6][3]*pdl[0][5]; + /* Net density corrected at Alt */ + output->d[7]=output->d[7]*ccor(z,rc14,hcc14,zcc14); + } + + + /**** Anomalous OXYGEN DENSITY ****/ + + g16h = flags->sw[21]*globe7(pd[8],input,flags); + db16h = pdm[7][0]*exp(g16h)*pd[8][0]; + tho = pdm[7][9]*pdl[0][6]; + dd=densu(z,db16h,tho,tho,16.,alpha[8],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); + zsht=pdm[7][5]; + zmho=pdm[7][4]; + zsho=scalh(zmho,16.0,tho); + output->d[8]=dd*exp(-zsht/zsho*(exp(-(z-zmho)/zsht)-1.)); + + + /* total mass density */ + output->d[5] = 1.66E-24*(4.0*output->d[0]+16.0*output->d[1]+28.0*output->d[2]+32.0*output->d[3]+40.0*output->d[4]+ output->d[6]+14.0*output->d[7]); + db48=1.66E-24*(4.0*db04+16.0*db16+28.0*db28+32.0*db32+40.0*db40+db01+14.0*db14); + + + + /* temperature */ + z = sqrt(input->alt*input->alt); + ddum = densu(z,1.0, tinf, tlb, 0.0, 0.0, &output->t[1], ptm[5], s, mn1, zn1, meso_tn1, meso_tgn1); + if (flags->sw[0]) { + for(i=0;i<9;i++) + output->d[i]=output->d[i]*1.0E6; + output->d[5]=output->d[5]/1000; + } } @@ -1691,51 +1621,40 @@ void MSIS::gts7(struct nrlmsise_input *input, struct nrlmsise_flags *flags, void MSIS::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: MSIS" << endl; - if (from == 1) cout << "Destroyed: MSIS" << endl; + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: MSIS" << endl; + if (from == 1) cout << "Destroyed: MSIS" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 32) { // Turbulence + if (first_pass && from == 2) { + cout << "vTurbulenceNED(X), vTurbulenceNED(Y), vTurbulenceNED(Z), " + << "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), " + << "vDirection(X), vDirection(Y), vDirection(Z), " + << "Magnitude, " + << "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl; } - if (debug_lvl & 8 ) // Runtime state variables - { + if (from == 2) { + cout << vTurbulenceNED << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl; } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 32) // Turbulence - { - if (first_pass && from == 2) - { - cout << "vTurbulenceNED(X), vTurbulenceNED(Y), vTurbulenceNED(Z), " - << "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), " - << "vDirection(X), vDirection(Y), vDirection(Z), " - << "Magnitude, " - << "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl; - } - if (from == 2) - { - cout << vTurbulenceNED << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl; - } - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } diff --git a/src/models/atmosphere/FGMSIS.h b/src/models/atmosphere/FGMSIS.h old mode 100644 new mode 100755 index f7988f18327c302d3ef5f964c37c7d75c4facebb..5761b1921965cfd421778bec430d7bb45b42d16c --- a/src/models/atmosphere/FGMSIS.h +++ b/src/models/atmosphere/FGMSIS.h @@ -1,34 +1,34 @@ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + Header: FGMSIS.h Description: MSIS-00 Atmosphere Author: David Culp Date started: 12/14/03 - + ------------- Copyright (C) 2003 David P. Culp (davidculp2@comcast.net) ------ - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser 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. - + Further information about the GNU Lesser General Public License can also be found on the world wide web at http://www.gnu.org. - + HISTORY -------------------------------------------------------------------------------- 12/14/03 DPC Created 01/11/04 DPC Derive from FGAtmosphere - + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SENTRY %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ @@ -53,8 +53,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -65,12 +64,12 @@ CLASS DOCUMENTATION This C++ format model wraps the NRLMSISE-00 C source code package - release 20020503 - + The NRLMSISE-00 model was developed by Mike Picone, Alan Hedin, and - Doug Drob. They also wrote a NRLMSISE-00 distribution package in + Doug Drob. They also wrote a NRLMSISE-00 distribution package in FORTRAN which is available at http://uap-www.nrl.navy.mil/models_web/msis/msis_home.htm - + Dominik Brodowski implemented and maintains this C version. You can reach him at devel@brodo.de. See the file "DOCUMENTATION" for details, and check http://www.brodo.de/english/pub/nrlmsise/index.html for @@ -83,37 +82,33 @@ CLASS DOCUMENTATION STRUCT DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -struct nrlmsise_flags -{ - int switches[24]; - double sw[24]; - double swc[24]; +struct nrlmsise_flags { + int switches[24]; + double sw[24]; + double swc[24]; }; -struct ap_array -{ - double a[7]; +struct ap_array { + double a[7]; }; -struct nrlmsise_input -{ - int year; /* year, currently ignored */ - int doy; /* day of year */ - double sec; /* seconds in day (UT) */ - double alt; /* altitude in kilometers */ - double g_lat; /* geodetic latitude */ - double g_long; /* geodetic longitude */ - double lst; /* local apparent solar time (hours), see note below */ - double f107A; /* 81 day average of F10.7 flux (centered on DOY) */ - double f107; /* daily F10.7 flux for previous day */ - double ap; /* magnetic index(daily) */ - struct ap_array *ap_a; /* see above */ +struct nrlmsise_input { + int year; /* year, currently ignored */ + int doy; /* day of year */ + double sec; /* seconds in day (UT) */ + double alt; /* altitude in kilometers */ + double g_lat; /* geodetic latitude */ + double g_long; /* geodetic longitude */ + double lst; /* local apparent solar time (hours), see note below */ + double f107A; /* 81 day average of F10.7 flux (centered on DOY) */ + double f107; /* daily F10.7 flux for previous day */ + double ap; /* magnetic index(daily) */ + struct ap_array *ap_a; /* see above */ }; -struct nrlmsise_output -{ - double d[9]; /* densities */ - double t[2]; /* temperatures */ +struct nrlmsise_output { + double d[9]; /* densities */ + double t[2]; /* temperatures */ }; @@ -125,86 +120,86 @@ class MSIS : public FGAtmosphere { public: - /// Constructor - MSIS(FGFDMExec*); - /// Destructor - ~MSIS(); - /** Runs the MSIS-00 atmosphere model; called by the Executive - @return false if no error */ - bool Run(void); + /// Constructor + MSIS(FGFDMExec*); + /// Destructor + ~MSIS(); + /** Runs the MSIS-00 atmosphere model; called by the Executive + @return false if no error */ + bool Run(void); - bool InitModel(void); + bool InitModel(void); - /// Does nothing. External control is not allowed. - void UseExternal(void); + /// Does nothing. External control is not allowed. + void UseExternal(void); private: - void Calculate(int day, // day of year (1 to 366) - double sec, // seconds in day (0.0 to 86400.0) - double alt, // altitude, feet - double lat, // geodetic latitude, degrees - double lon // geodetic longitude, degrees - ); - - void Debug(int from); - - nrlmsise_flags flags; - nrlmsise_input input; - nrlmsise_output output; - ap_array aph; - - /* PARMB */ - double gsurf; - double re; - - /* GTS3C */ - double dd; - - /* DMIX */ - double dm04, dm16, dm28, dm32, dm40, dm01, dm14; - - /* MESO7 */ - double meso_tn1[5]; - double meso_tn2[4]; - double meso_tn3[5]; - double meso_tgn1[2]; - double meso_tgn2[2]; - double meso_tgn3[2]; - - /* LPOLY */ - double dfa; - double plg[4][9]; - double ctloc, stloc; - double c2tloc, s2tloc; - double s3tloc, c3tloc; - double apdf, apt[4]; - - void tselec(struct nrlmsise_flags *flags); - void glatf(double lat, double *gv, double *reff); - double ccor(double alt, double r, double h1, double zh); - double ccor2(double alt, double r, double h1, double zh, double h2); - double scalh(double alt, double xm, double temp); - double dnet(double dd, double dm, double zhm, double xmm, double xm); - void splini(double *xa, double *ya, double *y2a, int n, double x, double *y); - void splint(double *xa, double *ya, double *y2a, int n, double x, double *y); - void spline(double *x, double *y, int n, double yp1, double ypn, double *y2); - double zeta(double zz, double zl); - double densm(double alt, double d0, double xm, double *tz, int mn3, double *zn3, - double *tn3, double *tgn3, int mn2, double *zn2, double *tn2, - double *tgn2); - double densu(double alt, double dlb, double tinf, double tlb, double xm, - double alpha, double *tz, double zlb, double s2, int mn1, - double *zn1, double *tn1, double *tgn1); - double g0(double a, double *p); - double sumex(double ex); - double sg0(double ex, double *p, double *ap); - double globe7(double *p, nrlmsise_input *input, nrlmsise_flags *flags); - double glob7s(double *p, nrlmsise_input *input, nrlmsise_flags *flags); - void gtd7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); - void gtd7d(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); - void ghp7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output, double press); - void gts7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); + void Calculate(int day, // day of year (1 to 366) + double sec, // seconds in day (0.0 to 86400.0) + double alt, // altitude, feet + double lat, // geodetic latitude, degrees + double lon // geodetic longitude, degrees + ); + + void Debug(int from); + + nrlmsise_flags flags; + nrlmsise_input input; + nrlmsise_output output; + ap_array aph; + + /* PARMB */ + double gsurf; + double re; + + /* GTS3C */ + double dd; + + /* DMIX */ + double dm04, dm16, dm28, dm32, dm40, dm01, dm14; + + /* MESO7 */ + double meso_tn1[5]; + double meso_tn2[4]; + double meso_tn3[5]; + double meso_tgn1[2]; + double meso_tgn2[2]; + double meso_tgn3[2]; + + /* LPOLY */ + double dfa; + double plg[4][9]; + double ctloc, stloc; + double c2tloc, s2tloc; + double s3tloc, c3tloc; + double apdf, apt[4]; + + void tselec(struct nrlmsise_flags *flags); + void glatf(double lat, double *gv, double *reff); + double ccor(double alt, double r, double h1, double zh); + double ccor2(double alt, double r, double h1, double zh, double h2); + double scalh(double alt, double xm, double temp); + double dnet(double dd, double dm, double zhm, double xmm, double xm); + void splini(double *xa, double *ya, double *y2a, int n, double x, double *y); + void splint(double *xa, double *ya, double *y2a, int n, double x, double *y); + void spline(double *x, double *y, int n, double yp1, double ypn, double *y2); + double zeta(double zz, double zl); + double densm(double alt, double d0, double xm, double *tz, int mn3, double *zn3, + double *tn3, double *tgn3, int mn2, double *zn2, double *tn2, + double *tgn2); + double densu(double alt, double dlb, double tinf, double tlb, double xm, + double alpha, double *tz, double zlb, double s2, int mn1, + double *zn1, double *tn1, double *tgn1); + double g0(double a, double *p); + double sumex(double ex); + double sg0(double ex, double *p, double *ap); + double globe7(double *p, nrlmsise_input *input, nrlmsise_flags *flags); + double glob7s(double *p, nrlmsise_input *input, nrlmsise_flags *flags); + void gtd7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); + void gtd7d(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); + void ghp7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output, double press); + void gts7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); }; diff --git a/src/models/atmosphere/FGMSISData.cpp b/src/models/atmosphere/FGMSISData.cpp old mode 100644 new mode 100755 index 7c6838eb4c006a28f6646a52a09a83e9ba8d5556..d77e1c51f5546a9f3270dd0bed0f8149b330c8ed --- a/src/models/atmosphere/FGMSISData.cpp +++ b/src/models/atmosphere/FGMSISData.cpp @@ -10,7 +10,7 @@ * 20020503 * * The NRLMSISE-00 model was developed by Mike Picone, Alan Hedin, and - * Doug Drob. They also wrote a NRLMSISE-00 distribution package in + * Doug Drob. They also wrote a NRLMSISE-00 distribution package in * FORTRAN which is available at * http://uap-www.nrl.navy.mil/models_web/msis/msis_home.htm * @@ -26,738 +26,722 @@ /* ------------------------ BLOCK DATA GTD7BK ------------------------ */ /* ------------------------------------------------------------------- */ -namespace JSBSim -{ +namespace JSBSim { /* TEMPERATURE */ -double pt[150] = -{ - 9.86573E-01, 1.62228E-02, 1.55270E-02,-1.04323E-01,-3.75801E-03, +double pt[150] = { + 9.86573E-01, 1.62228E-02, 1.55270E-02,-1.04323E-01,-3.75801E-03, -1.18538E-03,-1.24043E-01, 4.56820E-03, 8.76018E-03,-1.36235E-01, -3.52427E-02, 8.84181E-03,-5.92127E-03,-8.61650E+00, 0.00000E+00, - 1.28492E-02, 0.00000E+00, 1.30096E+02, 1.04567E-02, 1.65686E-03, + 1.28492E-02, 0.00000E+00, 1.30096E+02, 1.04567E-02, 1.65686E-03, -5.53887E-06, 2.97810E-03, 0.00000E+00, 5.13122E-03, 8.66784E-02, - 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.27026E-06, - 0.00000E+00, 6.74494E+00, 4.93933E-03, 2.21656E-03, 2.50802E-03, - 0.00000E+00, 0.00000E+00,-2.08841E-02,-1.79873E+00, 1.45103E-03, - 2.81769E-04,-1.44703E-03,-5.16394E-05, 8.47001E-02, 1.70147E-01, - 5.72562E-03, 5.07493E-05, 4.36148E-03, 1.17863E-04, 4.74364E-03, - 6.61278E-03, 4.34292E-05, 1.44373E-03, 2.41470E-05, 2.84426E-03, - 8.56560E-04, 2.04028E-03, 0.00000E+00,-3.15994E+03,-2.46423E-03, - 1.13843E-03, 4.20512E-04, 0.00000E+00,-9.77214E+01, 6.77794E-03, - 5.27499E-03, 1.14936E-03, 0.00000E+00,-6.61311E-03,-1.84255E-02, + 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.27026E-06, + 0.00000E+00, 6.74494E+00, 4.93933E-03, 2.21656E-03, 2.50802E-03, + 0.00000E+00, 0.00000E+00,-2.08841E-02,-1.79873E+00, 1.45103E-03, + 2.81769E-04,-1.44703E-03,-5.16394E-05, 8.47001E-02, 1.70147E-01, + 5.72562E-03, 5.07493E-05, 4.36148E-03, 1.17863E-04, 4.74364E-03, + 6.61278E-03, 4.34292E-05, 1.44373E-03, 2.41470E-05, 2.84426E-03, + 8.56560E-04, 2.04028E-03, 0.00000E+00,-3.15994E+03,-2.46423E-03, + 1.13843E-03, 4.20512E-04, 0.00000E+00,-9.77214E+01, 6.77794E-03, + 5.27499E-03, 1.14936E-03, 0.00000E+00,-6.61311E-03,-1.84255E-02, -1.96259E-02, 2.98618E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 6.44574E+02, 8.84668E-04, 5.05066E-04, 0.00000E+00, 4.02881E+03, + 6.44574E+02, 8.84668E-04, 5.05066E-04, 0.00000E+00, 4.02881E+03, -1.89503E-03, 0.00000E+00, 0.00000E+00, 8.21407E-04, 2.06780E-03, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, -1.20410E-02,-3.63963E-03, 9.92070E-05,-1.15284E-04,-6.33059E-05, -6.05545E-01, 8.34218E-03,-9.13036E+01, 3.71042E-04, 0.00000E+00, - 4.19000E-04, 2.70928E-03, 3.31507E-03,-4.44508E-03,-4.96334E-03, + 4.19000E-04, 2.70928E-03, 3.31507E-03,-4.44508E-03,-4.96334E-03, -1.60449E-03, 3.95119E-03, 2.48924E-03, 5.09815E-04, 4.05302E-03, - 2.24076E-03, 0.00000E+00, 6.84256E-03, 4.66354E-04, 0.00000E+00, + 2.24076E-03, 0.00000E+00, 6.84256E-03, 4.66354E-04, 0.00000E+00, -3.68328E-04, 0.00000E+00, 0.00000E+00,-1.46870E+02, 0.00000E+00, - 0.00000E+00, 1.09501E-03, 4.65156E-04, 5.62583E-04, 3.21596E+00, - 6.43168E-04, 3.14860E-03, 3.40738E-03, 1.78481E-03, 9.62532E-04, - 5.58171E-04, 3.43731E+00,-2.33195E-01, 5.10289E-04, 0.00000E+00, - 0.00000E+00,-9.25347E+04, 0.00000E+00,-1.99639E-03, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 + 0.00000E+00, 1.09501E-03, 4.65156E-04, 5.62583E-04, 3.21596E+00, + 6.43168E-04, 3.14860E-03, 3.40738E-03, 1.78481E-03, 9.62532E-04, + 5.58171E-04, 3.43731E+00,-2.33195E-01, 5.10289E-04, 0.00000E+00, + 0.00000E+00,-9.25347E+04, 0.00000E+00,-1.99639E-03, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 }; -double pd[9][150] = -{ - /* HE DENSITY */ { - 1.09979E+00,-4.88060E-02,-1.97501E-01,-9.10280E-02,-6.96558E-03, - 2.42136E-02, 3.91333E-01,-7.20068E-03,-3.22718E-02, 1.41508E+00, - 1.68194E-01, 1.85282E-02, 1.09384E-01,-7.24282E+00, 0.00000E+00, - 2.96377E-01,-4.97210E-02, 1.04114E+02,-8.61108E-02,-7.29177E-04, - 1.48998E-06, 1.08629E-03, 0.00000E+00, 0.00000E+00, 8.31090E-02, - 1.12818E-01,-5.75005E-02,-1.29919E-02,-1.78849E-02,-2.86343E-06, - 0.00000E+00,-1.51187E+02,-6.65902E-03, 0.00000E+00,-2.02069E-03, - 0.00000E+00, 0.00000E+00, 4.32264E-02,-2.80444E+01,-3.26789E-03, - 2.47461E-03, 0.00000E+00, 0.00000E+00, 9.82100E-02, 1.22714E-01, - -3.96450E-02, 0.00000E+00,-2.76489E-03, 0.00000E+00, 1.87723E-03, - -8.09813E-03, 4.34428E-05,-7.70932E-03, 0.00000E+00,-2.28894E-03, - -5.69070E-03,-5.22193E-03, 6.00692E-03,-7.80434E+03,-3.48336E-03, - -6.38362E-03,-1.82190E-03, 0.00000E+00,-7.58976E+01,-2.17875E-02, - -1.72524E-02,-9.06287E-03, 0.00000E+00, 2.44725E-02, 8.66040E-02, - 1.05712E-01, 3.02543E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, - -6.01364E+03,-5.64668E-03,-2.54157E-03, 0.00000E+00, 3.15611E+02, - -5.69158E-03, 0.00000E+00, 0.00000E+00,-4.47216E-03,-4.49523E-03, - 4.64428E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 4.51236E-02, 2.46520E-02, 6.17794E-03, 0.00000E+00, 0.00000E+00, - -3.62944E-01,-4.80022E-02,-7.57230E+01,-1.99656E-03, 0.00000E+00, - -5.18780E-03,-1.73990E-02,-9.03485E-03, 7.48465E-03, 1.53267E-02, - 1.06296E-02, 1.18655E-02, 2.55569E-03, 1.69020E-03, 3.51936E-02, - -1.81242E-02, 0.00000E+00,-1.00529E-01,-5.10574E-03, 0.00000E+00, - 2.10228E-03, 0.00000E+00, 0.00000E+00,-1.73255E+02, 5.07833E-01, - -2.41408E-01, 8.75414E-03, 2.77527E-03,-8.90353E-05,-5.25148E+00, - -5.83899E-03,-2.09122E-02,-9.63530E-03, 9.77164E-03, 4.07051E-03, - 2.53555E-04,-5.52875E+00,-3.55993E-01,-2.49231E-03, 0.00000E+00, - 0.00000E+00, 2.86026E+01, 0.00000E+00, 3.42722E-04, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 - }, /* O DENSITY */ { - 1.02315E+00,-1.59710E-01,-1.06630E-01,-1.77074E-02,-4.42726E-03, - 3.44803E-02, 4.45613E-02,-3.33751E-02,-5.73598E-02, 3.50360E-01, - 6.33053E-02, 2.16221E-02, 5.42577E-02,-5.74193E+00, 0.00000E+00, - 1.90891E-01,-1.39194E-02, 1.01102E+02, 8.16363E-02, 1.33717E-04, - 6.54403E-06, 3.10295E-03, 0.00000E+00, 0.00000E+00, 5.38205E-02, - 1.23910E-01,-1.39831E-02, 0.00000E+00, 0.00000E+00,-3.95915E-06, - 0.00000E+00,-7.14651E-01,-5.01027E-03, 0.00000E+00,-3.24756E-03, - 0.00000E+00, 0.00000E+00, 4.42173E-02,-1.31598E+01,-3.15626E-03, - 1.24574E-03,-1.47626E-03,-1.55461E-03, 6.40682E-02, 1.34898E-01, - -2.42415E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 6.13666E-04, - -5.40373E-03, 2.61635E-05,-3.33012E-03, 0.00000E+00,-3.08101E-03, - -2.42679E-03,-3.36086E-03, 0.00000E+00,-1.18979E+03,-5.04738E-02, - -2.61547E-03,-1.03132E-03, 1.91583E-04,-8.38132E+01,-1.40517E-02, - -1.14167E-02,-4.08012E-03, 1.73522E-04,-1.39644E-02,-6.64128E-02, - -6.85152E-02,-1.34414E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 6.07916E+02,-4.12220E-03,-2.20996E-03, 0.00000E+00, 1.70277E+03, - -4.63015E-03, 0.00000E+00, 0.00000E+00,-2.25360E-03,-2.96204E-03, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 3.92786E-02, 1.31186E-02,-1.78086E-03, 0.00000E+00, 0.00000E+00, - -3.90083E-01,-2.84741E-02,-7.78400E+01,-1.02601E-03, 0.00000E+00, - -7.26485E-04,-5.42181E-03,-5.59305E-03, 1.22825E-02, 1.23868E-02, - 6.68835E-03,-1.03303E-02,-9.51903E-03, 2.70021E-04,-2.57084E-02, - -1.32430E-02, 0.00000E+00,-3.81000E-02,-3.16810E-03, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-9.05762E-04,-2.14590E-03,-1.17824E-03, 3.66732E+00, - -3.79729E-04,-6.13966E-03,-5.09082E-03,-1.96332E-03,-3.08280E-03, - -9.75222E-04, 4.03315E+00,-2.52710E-01, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 - }, /* N2 DENSITY */ { - 1.16112E+00, 0.00000E+00, 0.00000E+00, 3.33725E-02, 0.00000E+00, - 3.48637E-02,-5.44368E-03, 0.00000E+00,-6.73940E-02, 1.74754E-01, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00, - 1.26733E-01, 0.00000E+00, 1.03154E+02, 5.52075E-02, 0.00000E+00, - 0.00000E+00, 8.13525E-04, 0.00000E+00, 0.00000E+00, 8.66784E-02, - 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-2.50482E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.48894E-03, - 6.16053E-04,-5.79716E-04, 2.95482E-03, 8.47001E-02, 1.70147E-01, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 - }, /* TLB */ { - 9.44846E-01, 0.00000E+00, 0.00000E+00,-3.08617E-02, 0.00000E+00, - -2.44019E-02, 6.48607E-03, 0.00000E+00, 3.08181E-02, 4.59392E-02, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00, - 2.13260E-02, 0.00000E+00,-3.56958E+02, 0.00000E+00, 1.82278E-04, - 0.00000E+00, 3.07472E-04, 0.00000E+00, 0.00000E+00, 8.66784E-02, - 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 3.83054E-03, 0.00000E+00, 0.00000E+00, - -1.93065E-03,-1.45090E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-1.23493E-03, 1.36736E-03, 8.47001E-02, 1.70147E-01, - 3.71469E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 5.10250E-03, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 3.68756E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 - }, /* O2 DENSITY */ { - 1.35580E+00, 1.44816E-01, 0.00000E+00, 6.07767E-02, 0.00000E+00, - 2.94777E-02, 7.46900E-02, 0.00000E+00,-9.23822E-02, 8.57342E-02, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.38636E+01, 0.00000E+00, - 7.71653E-02, 0.00000E+00, 8.18751E+01, 1.87736E-02, 0.00000E+00, - 0.00000E+00, 1.49667E-02, 0.00000E+00, 0.00000E+00, 8.66784E-02, - 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-3.67874E+02, 5.48158E-03, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, - 1.22631E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 8.17187E-03, 3.71617E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.10826E-03, - -3.13640E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - -7.35742E-02,-5.00266E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 1.94965E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 - }, /* AR DENSITY */ { - 1.04761E+00, 2.00165E-01, 2.37697E-01, 3.68552E-02, 0.00000E+00, - 3.57202E-02,-2.14075E-01, 0.00000E+00,-1.08018E-01,-3.73981E-01, - 0.00000E+00, 3.10022E-02,-1.16305E-03,-2.07596E+01, 0.00000E+00, - 8.64502E-02, 0.00000E+00, 9.74908E+01, 5.16707E-02, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 8.66784E-02, - 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 3.46193E+02, 1.34297E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.48509E-03, - -1.54689E-04, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, - 1.47753E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 1.89320E-02, 3.68181E-05, 1.32570E-02, 0.00000E+00, 0.00000E+00, - 3.59719E-03, 7.44328E-03,-1.00023E-03,-6.50528E+03, 0.00000E+00, - 1.03485E-02,-1.00983E-03,-4.06916E-03,-6.60864E+01,-1.71533E-02, - 1.10605E-02, 1.20300E-02,-5.20034E-03, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - -2.62769E+03, 7.13755E-03, 4.17999E-03, 0.00000E+00, 1.25910E+04, - 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.23595E-03, 4.60217E-03, - 5.71794E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - -3.18353E-02,-2.35526E-02,-1.36189E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 2.03522E-02,-6.67837E+01,-1.09724E-03, 0.00000E+00, - -1.38821E-02, 1.60468E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.51574E-02, - -5.44470E-04, 0.00000E+00, 7.28224E-02, 6.59413E-02, 0.00000E+00, - -5.15692E-03, 0.00000E+00, 0.00000E+00,-3.70367E+03, 0.00000E+00, - 0.00000E+00, 1.36131E-02, 5.38153E-03, 0.00000E+00, 4.76285E+00, - -1.75677E-02, 2.26301E-02, 0.00000E+00, 1.76631E-02, 4.77162E-03, - 0.00000E+00, 5.39354E+00, 0.00000E+00,-7.51710E-03, 0.00000E+00, - 0.00000E+00,-8.82736E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 - }, /* H DENSITY */ { - 1.26376E+00,-2.14304E-01,-1.49984E-01, 2.30404E-01, 2.98237E-02, - 2.68673E-02, 2.96228E-01, 2.21900E-02,-2.07655E-02, 4.52506E-01, - 1.20105E-01, 3.24420E-02, 4.24816E-02,-9.14313E+00, 0.00000E+00, - 2.47178E-02,-2.88229E-02, 8.12805E+01, 5.10380E-02,-5.80611E-03, - 2.51236E-05,-1.24083E-02, 0.00000E+00, 0.00000E+00, 8.66784E-02, - 1.58727E-01,-3.48190E-02, 0.00000E+00, 0.00000E+00, 2.89885E-05, - 0.00000E+00, 1.53595E+02,-1.68604E-02, 0.00000E+00, 1.01015E-02, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.84552E-04, - -1.22181E-03, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, - -1.04927E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.91313E-03, - -2.30501E-02, 3.14758E-05, 0.00000E+00, 0.00000E+00, 1.26956E-02, - 8.35489E-03, 3.10513E-04, 0.00000E+00, 3.42119E+03,-2.45017E-03, - -4.27154E-04, 5.45152E-04, 1.89896E-03, 2.89121E+01,-6.49973E-03, - -1.93855E-02,-1.48492E-02, 0.00000E+00,-5.10576E-02, 7.87306E-02, - 9.51981E-02,-1.49422E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 2.65503E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 6.37110E-03, 3.24789E-04, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 6.14274E-02, 1.00376E-02,-8.41083E-04, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-1.27099E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, - -3.94077E-03,-1.28601E-02,-7.97616E-03, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-6.71465E-03,-1.69799E-03, 1.93772E-03, 3.81140E+00, - -7.79290E-03,-1.82589E-02,-1.25860E-02,-1.04311E-02,-3.02465E-03, - 2.43063E-03, 3.63237E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 - }, /* N DENSITY */ { - 7.09557E+01,-3.26740E-01, 0.00000E+00,-5.16829E-01,-1.71664E-03, - 9.09310E-02,-6.71500E-01,-1.47771E-01,-9.27471E-02,-2.30862E-01, - -1.56410E-01, 1.34455E-02,-1.19717E-01, 2.52151E+00, 0.00000E+00, - -2.41582E-01, 5.92939E-02, 4.39756E+00, 9.15280E-02, 4.41292E-03, - 0.00000E+00, 8.66807E-03, 0.00000E+00, 0.00000E+00, 8.66784E-02, - 1.58727E-01, 9.74701E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 6.70217E+01,-1.31660E-03, 0.00000E+00,-1.65317E-02, - 0.00000E+00, 0.00000E+00, 8.50247E-02, 2.77428E+01, 4.98658E-03, - 6.15115E-03, 9.50156E-03,-2.12723E-02, 8.47001E-02, 1.70147E-01, - -2.38645E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.37380E-03, - -8.41918E-03, 2.80145E-05, 7.12383E-03, 0.00000E+00,-1.66209E-02, - 1.03533E-04,-1.68898E-02, 0.00000E+00, 3.64526E+03, 0.00000E+00, - 6.54077E-03, 3.69130E-04, 9.94419E-04, 8.42803E+01,-1.16124E-02, - -7.74414E-03,-1.68844E-03, 1.42809E-03,-1.92955E-03, 1.17225E-01, - -2.41512E-02, 1.50521E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 1.60261E+03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.54403E-04,-1.87270E-02, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 2.76439E-02, 6.43207E-03,-3.54300E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-2.80221E-02, 8.11228E+01,-6.75255E-04, 0.00000E+00, - -1.05162E-02,-3.48292E-03,-6.97321E-03, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-1.45546E-03,-1.31970E-02,-3.57751E-03,-1.09021E+00, - -1.50181E-02,-7.12841E-03,-6.64590E-03,-3.52610E-03,-1.87773E-02, - -2.22432E-03,-3.93895E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 - }, /* HOT O DENSITY */ { - 6.04050E-02, 1.57034E+00, 2.99387E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.51018E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.61650E+00, 1.26454E-02, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 5.50878E-03, 0.00000E+00, 0.00000E+00, 8.66784E-02, - 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 6.23881E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, - -9.45934E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 - } -}; +double pd[9][150] = { +/* HE DENSITY */ { + 1.09979E+00,-4.88060E-02,-1.97501E-01,-9.10280E-02,-6.96558E-03, + 2.42136E-02, 3.91333E-01,-7.20068E-03,-3.22718E-02, 1.41508E+00, + 1.68194E-01, 1.85282E-02, 1.09384E-01,-7.24282E+00, 0.00000E+00, + 2.96377E-01,-4.97210E-02, 1.04114E+02,-8.61108E-02,-7.29177E-04, + 1.48998E-06, 1.08629E-03, 0.00000E+00, 0.00000E+00, 8.31090E-02, + 1.12818E-01,-5.75005E-02,-1.29919E-02,-1.78849E-02,-2.86343E-06, + 0.00000E+00,-1.51187E+02,-6.65902E-03, 0.00000E+00,-2.02069E-03, + 0.00000E+00, 0.00000E+00, 4.32264E-02,-2.80444E+01,-3.26789E-03, + 2.47461E-03, 0.00000E+00, 0.00000E+00, 9.82100E-02, 1.22714E-01, + -3.96450E-02, 0.00000E+00,-2.76489E-03, 0.00000E+00, 1.87723E-03, + -8.09813E-03, 4.34428E-05,-7.70932E-03, 0.00000E+00,-2.28894E-03, + -5.69070E-03,-5.22193E-03, 6.00692E-03,-7.80434E+03,-3.48336E-03, + -6.38362E-03,-1.82190E-03, 0.00000E+00,-7.58976E+01,-2.17875E-02, + -1.72524E-02,-9.06287E-03, 0.00000E+00, 2.44725E-02, 8.66040E-02, + 1.05712E-01, 3.02543E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, + -6.01364E+03,-5.64668E-03,-2.54157E-03, 0.00000E+00, 3.15611E+02, + -5.69158E-03, 0.00000E+00, 0.00000E+00,-4.47216E-03,-4.49523E-03, + 4.64428E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 4.51236E-02, 2.46520E-02, 6.17794E-03, 0.00000E+00, 0.00000E+00, + -3.62944E-01,-4.80022E-02,-7.57230E+01,-1.99656E-03, 0.00000E+00, + -5.18780E-03,-1.73990E-02,-9.03485E-03, 7.48465E-03, 1.53267E-02, + 1.06296E-02, 1.18655E-02, 2.55569E-03, 1.69020E-03, 3.51936E-02, + -1.81242E-02, 0.00000E+00,-1.00529E-01,-5.10574E-03, 0.00000E+00, + 2.10228E-03, 0.00000E+00, 0.00000E+00,-1.73255E+02, 5.07833E-01, + -2.41408E-01, 8.75414E-03, 2.77527E-03,-8.90353E-05,-5.25148E+00, + -5.83899E-03,-2.09122E-02,-9.63530E-03, 9.77164E-03, 4.07051E-03, + 2.53555E-04,-5.52875E+00,-3.55993E-01,-2.49231E-03, 0.00000E+00, + 0.00000E+00, 2.86026E+01, 0.00000E+00, 3.42722E-04, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 +}, /* O DENSITY */ { + 1.02315E+00,-1.59710E-01,-1.06630E-01,-1.77074E-02,-4.42726E-03, + 3.44803E-02, 4.45613E-02,-3.33751E-02,-5.73598E-02, 3.50360E-01, + 6.33053E-02, 2.16221E-02, 5.42577E-02,-5.74193E+00, 0.00000E+00, + 1.90891E-01,-1.39194E-02, 1.01102E+02, 8.16363E-02, 1.33717E-04, + 6.54403E-06, 3.10295E-03, 0.00000E+00, 0.00000E+00, 5.38205E-02, + 1.23910E-01,-1.39831E-02, 0.00000E+00, 0.00000E+00,-3.95915E-06, + 0.00000E+00,-7.14651E-01,-5.01027E-03, 0.00000E+00,-3.24756E-03, + 0.00000E+00, 0.00000E+00, 4.42173E-02,-1.31598E+01,-3.15626E-03, + 1.24574E-03,-1.47626E-03,-1.55461E-03, 6.40682E-02, 1.34898E-01, + -2.42415E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 6.13666E-04, + -5.40373E-03, 2.61635E-05,-3.33012E-03, 0.00000E+00,-3.08101E-03, + -2.42679E-03,-3.36086E-03, 0.00000E+00,-1.18979E+03,-5.04738E-02, + -2.61547E-03,-1.03132E-03, 1.91583E-04,-8.38132E+01,-1.40517E-02, + -1.14167E-02,-4.08012E-03, 1.73522E-04,-1.39644E-02,-6.64128E-02, + -6.85152E-02,-1.34414E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 6.07916E+02,-4.12220E-03,-2.20996E-03, 0.00000E+00, 1.70277E+03, + -4.63015E-03, 0.00000E+00, 0.00000E+00,-2.25360E-03,-2.96204E-03, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 3.92786E-02, 1.31186E-02,-1.78086E-03, 0.00000E+00, 0.00000E+00, + -3.90083E-01,-2.84741E-02,-7.78400E+01,-1.02601E-03, 0.00000E+00, + -7.26485E-04,-5.42181E-03,-5.59305E-03, 1.22825E-02, 1.23868E-02, + 6.68835E-03,-1.03303E-02,-9.51903E-03, 2.70021E-04,-2.57084E-02, + -1.32430E-02, 0.00000E+00,-3.81000E-02,-3.16810E-03, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-9.05762E-04,-2.14590E-03,-1.17824E-03, 3.66732E+00, + -3.79729E-04,-6.13966E-03,-5.09082E-03,-1.96332E-03,-3.08280E-03, + -9.75222E-04, 4.03315E+00,-2.52710E-01, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 +}, /* N2 DENSITY */ { + 1.16112E+00, 0.00000E+00, 0.00000E+00, 3.33725E-02, 0.00000E+00, + 3.48637E-02,-5.44368E-03, 0.00000E+00,-6.73940E-02, 1.74754E-01, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00, + 1.26733E-01, 0.00000E+00, 1.03154E+02, 5.52075E-02, 0.00000E+00, + 0.00000E+00, 8.13525E-04, 0.00000E+00, 0.00000E+00, 8.66784E-02, + 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-2.50482E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.48894E-03, + 6.16053E-04,-5.79716E-04, 2.95482E-03, 8.47001E-02, 1.70147E-01, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 +}, /* TLB */ { + 9.44846E-01, 0.00000E+00, 0.00000E+00,-3.08617E-02, 0.00000E+00, + -2.44019E-02, 6.48607E-03, 0.00000E+00, 3.08181E-02, 4.59392E-02, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00, + 2.13260E-02, 0.00000E+00,-3.56958E+02, 0.00000E+00, 1.82278E-04, + 0.00000E+00, 3.07472E-04, 0.00000E+00, 0.00000E+00, 8.66784E-02, + 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 3.83054E-03, 0.00000E+00, 0.00000E+00, + -1.93065E-03,-1.45090E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-1.23493E-03, 1.36736E-03, 8.47001E-02, 1.70147E-01, + 3.71469E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 5.10250E-03, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 3.68756E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 +}, /* O2 DENSITY */ { + 1.35580E+00, 1.44816E-01, 0.00000E+00, 6.07767E-02, 0.00000E+00, + 2.94777E-02, 7.46900E-02, 0.00000E+00,-9.23822E-02, 8.57342E-02, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.38636E+01, 0.00000E+00, + 7.71653E-02, 0.00000E+00, 8.18751E+01, 1.87736E-02, 0.00000E+00, + 0.00000E+00, 1.49667E-02, 0.00000E+00, 0.00000E+00, 8.66784E-02, + 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-3.67874E+02, 5.48158E-03, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, + 1.22631E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 8.17187E-03, 3.71617E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.10826E-03, + -3.13640E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + -7.35742E-02,-5.00266E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 1.94965E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 +}, /* AR DENSITY */ { + 1.04761E+00, 2.00165E-01, 2.37697E-01, 3.68552E-02, 0.00000E+00, + 3.57202E-02,-2.14075E-01, 0.00000E+00,-1.08018E-01,-3.73981E-01, + 0.00000E+00, 3.10022E-02,-1.16305E-03,-2.07596E+01, 0.00000E+00, + 8.64502E-02, 0.00000E+00, 9.74908E+01, 5.16707E-02, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 8.66784E-02, + 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 3.46193E+02, 1.34297E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.48509E-03, + -1.54689E-04, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, + 1.47753E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 1.89320E-02, 3.68181E-05, 1.32570E-02, 0.00000E+00, 0.00000E+00, + 3.59719E-03, 7.44328E-03,-1.00023E-03,-6.50528E+03, 0.00000E+00, + 1.03485E-02,-1.00983E-03,-4.06916E-03,-6.60864E+01,-1.71533E-02, + 1.10605E-02, 1.20300E-02,-5.20034E-03, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + -2.62769E+03, 7.13755E-03, 4.17999E-03, 0.00000E+00, 1.25910E+04, + 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.23595E-03, 4.60217E-03, + 5.71794E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + -3.18353E-02,-2.35526E-02,-1.36189E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 2.03522E-02,-6.67837E+01,-1.09724E-03, 0.00000E+00, + -1.38821E-02, 1.60468E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.51574E-02, + -5.44470E-04, 0.00000E+00, 7.28224E-02, 6.59413E-02, 0.00000E+00, + -5.15692E-03, 0.00000E+00, 0.00000E+00,-3.70367E+03, 0.00000E+00, + 0.00000E+00, 1.36131E-02, 5.38153E-03, 0.00000E+00, 4.76285E+00, + -1.75677E-02, 2.26301E-02, 0.00000E+00, 1.76631E-02, 4.77162E-03, + 0.00000E+00, 5.39354E+00, 0.00000E+00,-7.51710E-03, 0.00000E+00, + 0.00000E+00,-8.82736E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 +}, /* H DENSITY */ { + 1.26376E+00,-2.14304E-01,-1.49984E-01, 2.30404E-01, 2.98237E-02, + 2.68673E-02, 2.96228E-01, 2.21900E-02,-2.07655E-02, 4.52506E-01, + 1.20105E-01, 3.24420E-02, 4.24816E-02,-9.14313E+00, 0.00000E+00, + 2.47178E-02,-2.88229E-02, 8.12805E+01, 5.10380E-02,-5.80611E-03, + 2.51236E-05,-1.24083E-02, 0.00000E+00, 0.00000E+00, 8.66784E-02, + 1.58727E-01,-3.48190E-02, 0.00000E+00, 0.00000E+00, 2.89885E-05, + 0.00000E+00, 1.53595E+02,-1.68604E-02, 0.00000E+00, 1.01015E-02, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.84552E-04, + -1.22181E-03, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, + -1.04927E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.91313E-03, + -2.30501E-02, 3.14758E-05, 0.00000E+00, 0.00000E+00, 1.26956E-02, + 8.35489E-03, 3.10513E-04, 0.00000E+00, 3.42119E+03,-2.45017E-03, + -4.27154E-04, 5.45152E-04, 1.89896E-03, 2.89121E+01,-6.49973E-03, + -1.93855E-02,-1.48492E-02, 0.00000E+00,-5.10576E-02, 7.87306E-02, + 9.51981E-02,-1.49422E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 2.65503E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 6.37110E-03, 3.24789E-04, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 6.14274E-02, 1.00376E-02,-8.41083E-04, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-1.27099E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, + -3.94077E-03,-1.28601E-02,-7.97616E-03, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-6.71465E-03,-1.69799E-03, 1.93772E-03, 3.81140E+00, + -7.79290E-03,-1.82589E-02,-1.25860E-02,-1.04311E-02,-3.02465E-03, + 2.43063E-03, 3.63237E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 +}, /* N DENSITY */ { + 7.09557E+01,-3.26740E-01, 0.00000E+00,-5.16829E-01,-1.71664E-03, + 9.09310E-02,-6.71500E-01,-1.47771E-01,-9.27471E-02,-2.30862E-01, + -1.56410E-01, 1.34455E-02,-1.19717E-01, 2.52151E+00, 0.00000E+00, + -2.41582E-01, 5.92939E-02, 4.39756E+00, 9.15280E-02, 4.41292E-03, + 0.00000E+00, 8.66807E-03, 0.00000E+00, 0.00000E+00, 8.66784E-02, + 1.58727E-01, 9.74701E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 6.70217E+01,-1.31660E-03, 0.00000E+00,-1.65317E-02, + 0.00000E+00, 0.00000E+00, 8.50247E-02, 2.77428E+01, 4.98658E-03, + 6.15115E-03, 9.50156E-03,-2.12723E-02, 8.47001E-02, 1.70147E-01, + -2.38645E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.37380E-03, + -8.41918E-03, 2.80145E-05, 7.12383E-03, 0.00000E+00,-1.66209E-02, + 1.03533E-04,-1.68898E-02, 0.00000E+00, 3.64526E+03, 0.00000E+00, + 6.54077E-03, 3.69130E-04, 9.94419E-04, 8.42803E+01,-1.16124E-02, + -7.74414E-03,-1.68844E-03, 1.42809E-03,-1.92955E-03, 1.17225E-01, + -2.41512E-02, 1.50521E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 1.60261E+03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.54403E-04,-1.87270E-02, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 2.76439E-02, 6.43207E-03,-3.54300E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-2.80221E-02, 8.11228E+01,-6.75255E-04, 0.00000E+00, + -1.05162E-02,-3.48292E-03,-6.97321E-03, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-1.45546E-03,-1.31970E-02,-3.57751E-03,-1.09021E+00, + -1.50181E-02,-7.12841E-03,-6.64590E-03,-3.52610E-03,-1.87773E-02, + -2.22432E-03,-3.93895E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 +}, /* HOT O DENSITY */ { + 6.04050E-02, 1.57034E+00, 2.99387E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.51018E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.61650E+00, 1.26454E-02, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 5.50878E-03, 0.00000E+00, 0.00000E+00, 8.66784E-02, + 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 6.23881E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, + -9.45934E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 +}}; /* S PARAM */ -double ps[150] = -{ - 9.56827E-01, 6.20637E-02, 3.18433E-02, 0.00000E+00, 0.00000E+00, - 3.94900E-02, 0.00000E+00, 0.00000E+00,-9.24882E-03,-7.94023E-03, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 2.74677E-03, 0.00000E+00, 1.54951E-02, 8.66784E-02, - 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00,-6.99007E-04, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 1.24362E-02,-5.28756E-03, 8.47001E-02, 1.70147E-01, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 +double ps[150] = { + 9.56827E-01, 6.20637E-02, 3.18433E-02, 0.00000E+00, 0.00000E+00, + 3.94900E-02, 0.00000E+00, 0.00000E+00,-9.24882E-03,-7.94023E-03, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 2.74677E-03, 0.00000E+00, 1.54951E-02, 8.66784E-02, + 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00,-6.99007E-04, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 1.24362E-02,-5.28756E-03, 8.47001E-02, 1.70147E-01, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 }; /* TURBO */ -double pdl[2][25] = -{ - { 1.09930E+00, 3.90631E+00, 3.07165E+00, 9.86161E-01, 1.63536E+01, - 4.63830E+00, 1.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 1.28840E+00, 3.10302E-02, 1.18339E-01 }, - { 1.00000E+00, 7.00000E-01, 1.15020E+00, 3.44689E+00, 1.28840E+00, - 1.00000E+00, 1.08738E+00, 1.22947E+00, 1.10016E+00, 7.34129E-01, - 1.15241E+00, 2.22784E+00, 7.95046E-01, 4.01612E+00, 4.47749E+00, - 1.23435E+02,-7.60535E-02, 1.68986E-06, 7.44294E-01, 1.03604E+00, - 1.72783E+02, 1.15020E+00, 3.44689E+00,-7.46230E-01, 9.49154E-01 } +double pdl[2][25] = { + { 1.09930E+00, 3.90631E+00, 3.07165E+00, 9.86161E-01, 1.63536E+01, + 4.63830E+00, 1.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 1.28840E+00, 3.10302E-02, 1.18339E-01 }, + { 1.00000E+00, 7.00000E-01, 1.15020E+00, 3.44689E+00, 1.28840E+00, + 1.00000E+00, 1.08738E+00, 1.22947E+00, 1.10016E+00, 7.34129E-01, + 1.15241E+00, 2.22784E+00, 7.95046E-01, 4.01612E+00, 4.47749E+00, + 1.23435E+02,-7.60535E-02, 1.68986E-06, 7.44294E-01, 1.03604E+00, + 1.72783E+02, 1.15020E+00, 3.44689E+00,-7.46230E-01, 9.49154E-01 } }; /* LOWER BOUNDARY */ -double ptm[50] = -{ - 1.04130E+03, 3.86000E+02, 1.95000E+02, 1.66728E+01, 2.13000E+02, - 1.20000E+02, 2.40000E+02, 1.87000E+02,-2.00000E+00, 0.00000E+00 -}; -double pdm[8][10] = -{ - { 2.45600E+07, 6.71072E-06, 1.00000E+02, 0.00000E+00, 1.10000E+02, - 1.00000E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 },\ - { 8.59400E+10, 1.00000E+00, 1.05000E+02,-8.00000E+00, 1.10000E+02, - 1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00 },\ - { 2.81000E+11, 0.00000E+00, 1.05000E+02, 2.80000E+01, 2.89500E+01, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 }, - { 3.30000E+10, 2.68270E-01, 1.05000E+02, 1.00000E+00, 1.10000E+02, - 1.00000E+01, 1.10000E+02,-1.00000E+01, 0.00000E+00, 0.00000E+00 }, - { 1.33000E+09, 1.19615E-02, 1.05000E+02, 0.00000E+00, 1.10000E+02, - 1.00000E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 }, - { 1.76100E+05, 1.00000E+00, 9.50000E+01,-8.00000E+00, 1.10000E+02, - 1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00, }, - { 1.00000E+07, 1.00000E+00, 1.05000E+02,-8.00000E+00, 1.10000E+02, - 1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00 }, - { 1.00000E+06, 1.00000E+00, 1.05000E+02,-8.00000E+00, 5.50000E+02, - 7.60000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 4.00000E+03 } +double ptm[50] = { + 1.04130E+03, 3.86000E+02, 1.95000E+02, 1.66728E+01, 2.13000E+02, + 1.20000E+02, 2.40000E+02, 1.87000E+02,-2.00000E+00, 0.00000E+00 }; +double pdm[8][10] = { +{ 2.45600E+07, 6.71072E-06, 1.00000E+02, 0.00000E+00, 1.10000E+02, + 1.00000E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 },\ +{ 8.59400E+10, 1.00000E+00, 1.05000E+02,-8.00000E+00, 1.10000E+02, + 1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00 },\ +{ 2.81000E+11, 0.00000E+00, 1.05000E+02, 2.80000E+01, 2.89500E+01, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 }, +{ 3.30000E+10, 2.68270E-01, 1.05000E+02, 1.00000E+00, 1.10000E+02, + 1.00000E+01, 1.10000E+02,-1.00000E+01, 0.00000E+00, 0.00000E+00 }, +{ 1.33000E+09, 1.19615E-02, 1.05000E+02, 0.00000E+00, 1.10000E+02, + 1.00000E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 }, +{ 1.76100E+05, 1.00000E+00, 9.50000E+01,-8.00000E+00, 1.10000E+02, + 1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00, }, +{ 1.00000E+07, 1.00000E+00, 1.05000E+02,-8.00000E+00, 1.10000E+02, + 1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00 }, +{ 1.00000E+06, 1.00000E+00, 1.05000E+02,-8.00000E+00, 5.50000E+02, + 7.60000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 4.00000E+03 }}; -double ptl[4][100] = -{ - /* TN1(2) */ { - 1.00858E+00, 4.56011E-02,-2.22972E-02,-5.44388E-02, 5.23136E-04, - -1.88849E-02, 5.23707E-02,-9.43646E-03, 6.31707E-03,-7.80460E-02, - -4.88430E-02, 0.00000E+00, 0.00000E+00,-7.60250E+00, 0.00000E+00, - -1.44635E-02,-1.76843E-02,-1.21517E+02, 2.85647E-02, 0.00000E+00, - 0.00000E+00, 6.31792E-04, 0.00000E+00, 5.77197E-03, 8.66784E-02, - 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-8.90272E+03, 3.30611E-03, 3.02172E-03, 0.00000E+00, - -2.13673E-03,-3.20910E-04, 0.00000E+00, 0.00000E+00, 2.76034E-03, - 2.82487E-03,-2.97592E-04,-4.21534E-03, 8.47001E-02, 1.70147E-01, - 8.96456E-03, 0.00000E+00,-1.08596E-02, 0.00000E+00, 0.00000E+00, - 5.57917E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 9.65405E-03, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TN1(3) */ { - 9.39664E-01, 8.56514E-02,-6.79989E-03, 2.65929E-02,-4.74283E-03, - 1.21855E-02,-2.14905E-02, 6.49651E-03,-2.05477E-02,-4.24952E-02, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.19148E+01, 0.00000E+00, - 1.18777E-02,-7.28230E-02,-8.15965E+01, 1.73887E-02, 0.00000E+00, - 0.00000E+00, 0.00000E+00,-1.44691E-02, 2.80259E-04, 8.66784E-02, - 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 2.16584E+02, 3.18713E-03, 7.37479E-03, 0.00000E+00, - -2.55018E-03,-3.92806E-03, 0.00000E+00, 0.00000E+00,-2.89757E-03, - -1.33549E-03, 1.02661E-03, 3.53775E-04, 8.47001E-02, 1.70147E-01, - -9.17497E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 3.56082E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-1.00902E-02, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TN1(4) */ { - 9.85982E-01,-4.55435E-02, 1.21106E-02, 2.04127E-02,-2.40836E-03, - 1.11383E-02,-4.51926E-02, 1.35074E-02,-6.54139E-03, 1.15275E-01, - 1.28247E-01, 0.00000E+00, 0.00000E+00,-5.30705E+00, 0.00000E+00, - -3.79332E-02,-6.24741E-02, 7.71062E-01, 2.96315E-02, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 6.81051E-03,-4.34767E-03, 8.66784E-02, - 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 1.07003E+01,-2.76907E-03, 4.32474E-04, 0.00000E+00, - 1.31497E-03,-6.47517E-04, 0.00000E+00,-2.20621E+01,-1.10804E-03, - -8.09338E-04, 4.18184E-04, 4.29650E-03, 8.47001E-02, 1.70147E-01, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - -4.04337E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-9.52550E-04, - 8.56253E-04, 4.33114E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.21223E-03, - 2.38694E-04, 9.15245E-04, 1.28385E-03, 8.67668E-04,-5.61425E-06, - 1.04445E+00, 3.41112E+01, 0.00000E+00,-8.40704E-01,-2.39639E+02, - 7.06668E-01,-2.05873E+01,-3.63696E-01, 2.39245E+01, 0.00000E+00, - -1.06657E-03,-7.67292E-04, 1.54534E-04, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TN1(5) TN2(1) */ { - 1.00320E+00, 3.83501E-02,-2.38983E-03, 2.83950E-03, 4.20956E-03, - 5.86619E-04, 2.19054E-02,-1.00946E-02,-3.50259E-03, 4.17392E-02, - -8.44404E-03, 0.00000E+00, 0.00000E+00, 4.96949E+00, 0.00000E+00, - -7.06478E-03,-1.46494E-02, 3.13258E+01,-1.86493E-03, 0.00000E+00, - -1.67499E-02, 0.00000E+00, 0.00000E+00, 5.12686E-04, 8.66784E-02, - 1.58727E-01,-4.64167E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 4.37353E-03,-1.99069E+02, 0.00000E+00,-5.34884E-03, 0.00000E+00, - 1.62458E-03, 2.93016E-03, 2.67926E-03, 5.90449E+02, 0.00000E+00, - 0.00000E+00,-1.17266E-03,-3.58890E-04, 8.47001E-02, 1.70147E-01, - 0.00000E+00, 0.00000E+00, 1.38673E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.60571E-03, - 6.28078E-04, 5.05469E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.57829E-03, - -4.00855E-04, 5.04077E-05,-1.39001E-03,-2.33406E-03,-4.81197E-04, - 1.46758E+00, 6.20332E+00, 0.00000E+00, 3.66476E-01,-6.19760E+01, - 3.09198E-01,-1.98999E+01, 0.00000E+00,-3.29933E+02, 0.00000E+00, - -1.10080E-03,-9.39310E-05, 1.39638E-04, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - } -}; - -double pma[10][100] = -{ - /* TN2(2) */ { - 9.81637E-01,-1.41317E-03, 3.87323E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.58707E-02, - -8.63658E-03, 0.00000E+00, 0.00000E+00,-2.02226E+00, 0.00000E+00, - -8.69424E-03,-1.91397E-02, 8.76779E+01, 4.52188E-03, 0.00000E+00, - 2.23760E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-7.07572E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, - -4.11210E-03, 3.50060E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00,-8.36657E-03, 1.61347E+01, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00,-1.45130E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.24152E-03, - 6.43365E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.33255E-03, - 2.42657E-03, 1.60666E-03,-1.85728E-03,-1.46874E-03,-4.79163E-06, - 1.22464E+00, 3.53510E+01, 0.00000E+00, 4.49223E-01,-4.77466E+01, - 4.70681E-01, 8.41861E+00,-2.88198E-01, 1.67854E+02, 0.00000E+00, - 7.11493E-04, 6.05601E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TN2(3) */ { - 1.00422E+00,-7.11212E-03, 5.24480E-03, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.28914E-02, - -2.41301E-02, 0.00000E+00, 0.00000E+00,-2.12219E+01,-1.03830E-02, - -3.28077E-03, 1.65727E-02, 1.68564E+00,-6.68154E-03, 0.00000E+00, - 1.45155E-02, 0.00000E+00, 8.42365E-03, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-4.34645E-03, 0.00000E+00, 0.00000E+00, 2.16780E-02, - 0.00000E+00,-1.38459E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 7.04573E-03,-4.73204E+01, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 1.08767E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.08279E-03, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.21769E-04, - -2.27387E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.26769E-03, - 3.16901E-03, 4.60316E-04,-1.01431E-04, 1.02131E-03, 9.96601E-04, - 1.25707E+00, 2.50114E+01, 0.00000E+00, 4.24472E-01,-2.77655E+01, - 3.44625E-01, 2.75412E+01, 0.00000E+00, 7.94251E+02, 0.00000E+00, - 2.45835E-03, 1.38871E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TN2(4) TN3(1) */ { - 1.01890E+00,-2.46603E-02, 1.00078E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-6.70977E-02, - -4.02286E-02, 0.00000E+00, 0.00000E+00,-2.29466E+01,-7.47019E-03, - 2.26580E-03, 2.63931E-02, 3.72625E+01,-6.39041E-03, 0.00000E+00, - 9.58383E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-1.85291E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 1.39717E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 9.19771E-03,-3.69121E+02, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00,-1.57067E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.07265E-03, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.92953E-03, - -2.77739E-03,-4.40092E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.47280E-03, - 2.95035E-04,-1.81246E-03, 2.81945E-03, 4.27296E-03, 9.78863E-04, - 1.40545E+00,-6.19173E+00, 0.00000E+00, 0.00000E+00,-7.93632E+01, - 4.44643E-01,-4.03085E+02, 0.00000E+00, 1.15603E+01, 0.00000E+00, - 2.25068E-03, 8.48557E-04,-2.98493E-04, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TN3(2) */ { - 9.75801E-01, 3.80680E-02,-3.05198E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.85575E-02, - 5.04057E-02, 0.00000E+00, 0.00000E+00,-1.76046E+02, 1.44594E-02, - -1.48297E-03,-3.68560E-03, 3.02185E+01,-3.23338E-03, 0.00000E+00, - 1.53569E-02, 0.00000E+00,-1.15558E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 4.89620E-03, 0.00000E+00, 0.00000E+00,-1.00616E-02, - -8.21324E-03,-1.57757E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 6.63564E-03, 4.58410E+01, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00,-2.51280E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 9.91215E-03, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.73148E-04, - -1.29648E-03,-7.32026E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.68110E-03, - -4.66003E-03,-1.31567E-03,-7.39390E-04, 6.32499E-04,-4.65588E-04, - -1.29785E+00,-1.57139E+02, 0.00000E+00, 2.58350E-01,-3.69453E+01, - 4.10672E-01, 9.78196E+00,-1.52064E-01,-3.85084E+03, 0.00000E+00, - -8.52706E-04,-1.40945E-03,-7.26786E-04, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TN3(3) */ { - 9.60722E-01, 7.03757E-02,-3.00266E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.22671E-02, - 4.10423E-02, 0.00000E+00, 0.00000E+00,-1.63070E+02, 1.06073E-02, - 5.40747E-04, 7.79481E-03, 1.44908E+02, 1.51484E-04, 0.00000E+00, - 1.97547E-02, 0.00000E+00,-1.41844E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 5.77884E-03, 0.00000E+00, 0.00000E+00, 9.74319E-03, - 0.00000E+00,-2.88015E+03, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00,-4.44902E-03,-2.92760E+01, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 2.34419E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.36685E-03, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.65325E-04, - -5.50628E-04, 3.31465E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.06179E-03, - -3.08575E-03,-7.93589E-04,-1.08629E-04, 5.95511E-04,-9.05050E-04, - 1.18997E+00, 4.15924E+01, 0.00000E+00,-4.72064E-01,-9.47150E+02, - 3.98723E-01, 1.98304E+01, 0.00000E+00, 3.73219E+03, 0.00000E+00, - -1.50040E-03,-1.14933E-03,-1.56769E-04, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TN3(4) */ { - 1.03123E+00,-7.05124E-02, 8.71615E-03, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.82621E-02, - -9.80975E-03, 0.00000E+00, 0.00000E+00, 2.89286E+01, 9.57341E-03, - 0.00000E+00, 0.00000E+00, 8.66153E+01, 7.91938E-04, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 4.68917E-03, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 7.86638E-03, 0.00000E+00, 0.00000E+00, 9.90827E-03, - 0.00000E+00, 6.55573E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.00200E+01, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 7.07457E-03, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.72268E-03, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.04970E-04, - 1.21560E-03,-8.05579E-06, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.49941E-03, - -4.57256E-04,-1.59311E-04, 2.96481E-04,-1.77318E-03,-6.37918E-04, - 1.02395E+00, 1.28172E+01, 0.00000E+00, 1.49903E-01,-2.63818E+01, - 0.00000E+00, 4.70628E+01,-2.22139E-01, 4.82292E-02, 0.00000E+00, - -8.67075E-04,-5.86479E-04, 5.32462E-04, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TN3(5) SURFACE TEMP TSL */ { - 1.00828E+00,-9.10404E-02,-2.26549E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.32420E-02, - -9.08925E-03, 0.00000E+00, 0.00000E+00, 3.36105E+01, 0.00000E+00, - 0.00000E+00, 0.00000E+00,-1.24957E+01,-5.87939E-03, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 2.79765E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.01237E+03, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00,-1.75553E-02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.29699E-03, - 1.26659E-03, 2.68402E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.17894E-03, - 1.48746E-03, 1.06478E-04, 1.34743E-04,-2.20939E-03,-6.23523E-04, - 6.36539E-01, 1.13621E+01, 0.00000E+00,-3.93777E-01, 2.38687E+03, - 0.00000E+00, 6.61865E+02,-1.21434E-01, 9.27608E+00, 0.00000E+00, - 1.68478E-04, 1.24892E-03, 1.71345E-03, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TGN3(2) SURFACE GRAD TSLG */ { - 1.57293E+00,-6.78400E-01, 6.47500E-01, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.62974E-02, - -3.60423E-01, 0.00000E+00, 0.00000E+00, 1.28358E+02, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 4.68038E+01, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-1.67898E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 2.90994E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.15706E+01, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TGN2(1) TGN1(2) */ { - 8.60028E-01, 3.77052E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.17570E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 7.77757E-03, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 1.01024E+02, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 6.54251E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.56959E-02, - 1.91001E-02, 3.15971E-02, 1.00982E-02,-6.71565E-03, 2.57693E-03, - 1.38692E+00, 2.82132E-01, 0.00000E+00, 0.00000E+00, 3.81511E+02, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - }, /* TGN3(1) TGN2(2) */ { - 1.06029E+00,-5.25231E-02, 3.73034E-01, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.31072E-02, - -3.88409E-01, 0.00000E+00, 0.00000E+00,-1.65295E+02,-2.13801E-01, - -4.38916E-02,-3.22716E-01,-8.82393E+01, 1.18458E-01, 0.00000E+00, - -4.35863E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00,-1.19782E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 2.62229E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.37443E+01, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00,-4.55788E-01, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.84009E-02, - 3.96733E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.05494E-02, - 7.39617E-02, 1.92200E-02,-8.46151E-03,-1.34244E-02, 1.96338E-02, - 1.50421E+00, 1.88368E+01, 0.00000E+00, 0.00000E+00,-5.13114E+01, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 5.11923E-02, 3.61225E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 - } -}; +double ptl[4][100] = { +/* TN1(2) */ { + 1.00858E+00, 4.56011E-02,-2.22972E-02,-5.44388E-02, 5.23136E-04, + -1.88849E-02, 5.23707E-02,-9.43646E-03, 6.31707E-03,-7.80460E-02, + -4.88430E-02, 0.00000E+00, 0.00000E+00,-7.60250E+00, 0.00000E+00, + -1.44635E-02,-1.76843E-02,-1.21517E+02, 2.85647E-02, 0.00000E+00, + 0.00000E+00, 6.31792E-04, 0.00000E+00, 5.77197E-03, 8.66784E-02, + 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-8.90272E+03, 3.30611E-03, 3.02172E-03, 0.00000E+00, + -2.13673E-03,-3.20910E-04, 0.00000E+00, 0.00000E+00, 2.76034E-03, + 2.82487E-03,-2.97592E-04,-4.21534E-03, 8.47001E-02, 1.70147E-01, + 8.96456E-03, 0.00000E+00,-1.08596E-02, 0.00000E+00, 0.00000E+00, + 5.57917E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 9.65405E-03, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TN1(3) */ { + 9.39664E-01, 8.56514E-02,-6.79989E-03, 2.65929E-02,-4.74283E-03, + 1.21855E-02,-2.14905E-02, 6.49651E-03,-2.05477E-02,-4.24952E-02, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.19148E+01, 0.00000E+00, + 1.18777E-02,-7.28230E-02,-8.15965E+01, 1.73887E-02, 0.00000E+00, + 0.00000E+00, 0.00000E+00,-1.44691E-02, 2.80259E-04, 8.66784E-02, + 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 2.16584E+02, 3.18713E-03, 7.37479E-03, 0.00000E+00, + -2.55018E-03,-3.92806E-03, 0.00000E+00, 0.00000E+00,-2.89757E-03, + -1.33549E-03, 1.02661E-03, 3.53775E-04, 8.47001E-02, 1.70147E-01, + -9.17497E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 3.56082E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-1.00902E-02, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TN1(4) */ { + 9.85982E-01,-4.55435E-02, 1.21106E-02, 2.04127E-02,-2.40836E-03, + 1.11383E-02,-4.51926E-02, 1.35074E-02,-6.54139E-03, 1.15275E-01, + 1.28247E-01, 0.00000E+00, 0.00000E+00,-5.30705E+00, 0.00000E+00, + -3.79332E-02,-6.24741E-02, 7.71062E-01, 2.96315E-02, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 6.81051E-03,-4.34767E-03, 8.66784E-02, + 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 1.07003E+01,-2.76907E-03, 4.32474E-04, 0.00000E+00, + 1.31497E-03,-6.47517E-04, 0.00000E+00,-2.20621E+01,-1.10804E-03, + -8.09338E-04, 4.18184E-04, 4.29650E-03, 8.47001E-02, 1.70147E-01, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + -4.04337E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-9.52550E-04, + 8.56253E-04, 4.33114E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.21223E-03, + 2.38694E-04, 9.15245E-04, 1.28385E-03, 8.67668E-04,-5.61425E-06, + 1.04445E+00, 3.41112E+01, 0.00000E+00,-8.40704E-01,-2.39639E+02, + 7.06668E-01,-2.05873E+01,-3.63696E-01, 2.39245E+01, 0.00000E+00, + -1.06657E-03,-7.67292E-04, 1.54534E-04, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TN1(5) TN2(1) */ { + 1.00320E+00, 3.83501E-02,-2.38983E-03, 2.83950E-03, 4.20956E-03, + 5.86619E-04, 2.19054E-02,-1.00946E-02,-3.50259E-03, 4.17392E-02, + -8.44404E-03, 0.00000E+00, 0.00000E+00, 4.96949E+00, 0.00000E+00, + -7.06478E-03,-1.46494E-02, 3.13258E+01,-1.86493E-03, 0.00000E+00, + -1.67499E-02, 0.00000E+00, 0.00000E+00, 5.12686E-04, 8.66784E-02, + 1.58727E-01,-4.64167E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 4.37353E-03,-1.99069E+02, 0.00000E+00,-5.34884E-03, 0.00000E+00, + 1.62458E-03, 2.93016E-03, 2.67926E-03, 5.90449E+02, 0.00000E+00, + 0.00000E+00,-1.17266E-03,-3.58890E-04, 8.47001E-02, 1.70147E-01, + 0.00000E+00, 0.00000E+00, 1.38673E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.60571E-03, + 6.28078E-04, 5.05469E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.57829E-03, + -4.00855E-04, 5.04077E-05,-1.39001E-03,-2.33406E-03,-4.81197E-04, + 1.46758E+00, 6.20332E+00, 0.00000E+00, 3.66476E-01,-6.19760E+01, + 3.09198E-01,-1.98999E+01, 0.00000E+00,-3.29933E+02, 0.00000E+00, + -1.10080E-03,-9.39310E-05, 1.39638E-04, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +} }; +double pma[10][100] = { +/* TN2(2) */ { + 9.81637E-01,-1.41317E-03, 3.87323E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.58707E-02, + -8.63658E-03, 0.00000E+00, 0.00000E+00,-2.02226E+00, 0.00000E+00, + -8.69424E-03,-1.91397E-02, 8.76779E+01, 4.52188E-03, 0.00000E+00, + 2.23760E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-7.07572E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, + -4.11210E-03, 3.50060E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00,-8.36657E-03, 1.61347E+01, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00,-1.45130E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.24152E-03, + 6.43365E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.33255E-03, + 2.42657E-03, 1.60666E-03,-1.85728E-03,-1.46874E-03,-4.79163E-06, + 1.22464E+00, 3.53510E+01, 0.00000E+00, 4.49223E-01,-4.77466E+01, + 4.70681E-01, 8.41861E+00,-2.88198E-01, 1.67854E+02, 0.00000E+00, + 7.11493E-04, 6.05601E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TN2(3) */ { + 1.00422E+00,-7.11212E-03, 5.24480E-03, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.28914E-02, + -2.41301E-02, 0.00000E+00, 0.00000E+00,-2.12219E+01,-1.03830E-02, + -3.28077E-03, 1.65727E-02, 1.68564E+00,-6.68154E-03, 0.00000E+00, + 1.45155E-02, 0.00000E+00, 8.42365E-03, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-4.34645E-03, 0.00000E+00, 0.00000E+00, 2.16780E-02, + 0.00000E+00,-1.38459E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 7.04573E-03,-4.73204E+01, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 1.08767E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.08279E-03, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.21769E-04, + -2.27387E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.26769E-03, + 3.16901E-03, 4.60316E-04,-1.01431E-04, 1.02131E-03, 9.96601E-04, + 1.25707E+00, 2.50114E+01, 0.00000E+00, 4.24472E-01,-2.77655E+01, + 3.44625E-01, 2.75412E+01, 0.00000E+00, 7.94251E+02, 0.00000E+00, + 2.45835E-03, 1.38871E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TN2(4) TN3(1) */ { + 1.01890E+00,-2.46603E-02, 1.00078E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-6.70977E-02, + -4.02286E-02, 0.00000E+00, 0.00000E+00,-2.29466E+01,-7.47019E-03, + 2.26580E-03, 2.63931E-02, 3.72625E+01,-6.39041E-03, 0.00000E+00, + 9.58383E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-1.85291E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 1.39717E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 9.19771E-03,-3.69121E+02, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00,-1.57067E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.07265E-03, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.92953E-03, + -2.77739E-03,-4.40092E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.47280E-03, + 2.95035E-04,-1.81246E-03, 2.81945E-03, 4.27296E-03, 9.78863E-04, + 1.40545E+00,-6.19173E+00, 0.00000E+00, 0.00000E+00,-7.93632E+01, + 4.44643E-01,-4.03085E+02, 0.00000E+00, 1.15603E+01, 0.00000E+00, + 2.25068E-03, 8.48557E-04,-2.98493E-04, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TN3(2) */ { + 9.75801E-01, 3.80680E-02,-3.05198E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.85575E-02, + 5.04057E-02, 0.00000E+00, 0.00000E+00,-1.76046E+02, 1.44594E-02, + -1.48297E-03,-3.68560E-03, 3.02185E+01,-3.23338E-03, 0.00000E+00, + 1.53569E-02, 0.00000E+00,-1.15558E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 4.89620E-03, 0.00000E+00, 0.00000E+00,-1.00616E-02, + -8.21324E-03,-1.57757E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 6.63564E-03, 4.58410E+01, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00,-2.51280E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 9.91215E-03, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.73148E-04, + -1.29648E-03,-7.32026E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.68110E-03, + -4.66003E-03,-1.31567E-03,-7.39390E-04, 6.32499E-04,-4.65588E-04, + -1.29785E+00,-1.57139E+02, 0.00000E+00, 2.58350E-01,-3.69453E+01, + 4.10672E-01, 9.78196E+00,-1.52064E-01,-3.85084E+03, 0.00000E+00, + -8.52706E-04,-1.40945E-03,-7.26786E-04, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TN3(3) */ { + 9.60722E-01, 7.03757E-02,-3.00266E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.22671E-02, + 4.10423E-02, 0.00000E+00, 0.00000E+00,-1.63070E+02, 1.06073E-02, + 5.40747E-04, 7.79481E-03, 1.44908E+02, 1.51484E-04, 0.00000E+00, + 1.97547E-02, 0.00000E+00,-1.41844E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 5.77884E-03, 0.00000E+00, 0.00000E+00, 9.74319E-03, + 0.00000E+00,-2.88015E+03, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00,-4.44902E-03,-2.92760E+01, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 2.34419E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.36685E-03, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.65325E-04, + -5.50628E-04, 3.31465E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.06179E-03, + -3.08575E-03,-7.93589E-04,-1.08629E-04, 5.95511E-04,-9.05050E-04, + 1.18997E+00, 4.15924E+01, 0.00000E+00,-4.72064E-01,-9.47150E+02, + 3.98723E-01, 1.98304E+01, 0.00000E+00, 3.73219E+03, 0.00000E+00, + -1.50040E-03,-1.14933E-03,-1.56769E-04, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TN3(4) */ { + 1.03123E+00,-7.05124E-02, 8.71615E-03, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.82621E-02, + -9.80975E-03, 0.00000E+00, 0.00000E+00, 2.89286E+01, 9.57341E-03, + 0.00000E+00, 0.00000E+00, 8.66153E+01, 7.91938E-04, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 4.68917E-03, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 7.86638E-03, 0.00000E+00, 0.00000E+00, 9.90827E-03, + 0.00000E+00, 6.55573E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.00200E+01, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 7.07457E-03, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.72268E-03, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.04970E-04, + 1.21560E-03,-8.05579E-06, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.49941E-03, + -4.57256E-04,-1.59311E-04, 2.96481E-04,-1.77318E-03,-6.37918E-04, + 1.02395E+00, 1.28172E+01, 0.00000E+00, 1.49903E-01,-2.63818E+01, + 0.00000E+00, 4.70628E+01,-2.22139E-01, 4.82292E-02, 0.00000E+00, + -8.67075E-04,-5.86479E-04, 5.32462E-04, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TN3(5) SURFACE TEMP TSL */ { + 1.00828E+00,-9.10404E-02,-2.26549E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.32420E-02, + -9.08925E-03, 0.00000E+00, 0.00000E+00, 3.36105E+01, 0.00000E+00, + 0.00000E+00, 0.00000E+00,-1.24957E+01,-5.87939E-03, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 2.79765E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.01237E+03, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00,-1.75553E-02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.29699E-03, + 1.26659E-03, 2.68402E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.17894E-03, + 1.48746E-03, 1.06478E-04, 1.34743E-04,-2.20939E-03,-6.23523E-04, + 6.36539E-01, 1.13621E+01, 0.00000E+00,-3.93777E-01, 2.38687E+03, + 0.00000E+00, 6.61865E+02,-1.21434E-01, 9.27608E+00, 0.00000E+00, + 1.68478E-04, 1.24892E-03, 1.71345E-03, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TGN3(2) SURFACE GRAD TSLG */ { + 1.57293E+00,-6.78400E-01, 6.47500E-01, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.62974E-02, + -3.60423E-01, 0.00000E+00, 0.00000E+00, 1.28358E+02, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 4.68038E+01, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-1.67898E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 2.90994E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.15706E+01, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TGN2(1) TGN1(2) */ { + 8.60028E-01, 3.77052E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.17570E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 7.77757E-03, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 1.01024E+02, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 6.54251E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.56959E-02, + 1.91001E-02, 3.15971E-02, 1.00982E-02,-6.71565E-03, 2.57693E-03, + 1.38692E+00, 2.82132E-01, 0.00000E+00, 0.00000E+00, 3.81511E+02, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +}, /* TGN3(1) TGN2(2) */ { + 1.06029E+00,-5.25231E-02, 3.73034E-01, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.31072E-02, + -3.88409E-01, 0.00000E+00, 0.00000E+00,-1.65295E+02,-2.13801E-01, + -4.38916E-02,-3.22716E-01,-8.82393E+01, 1.18458E-01, 0.00000E+00, + -4.35863E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00,-1.19782E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 2.62229E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.37443E+01, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00,-4.55788E-01, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.84009E-02, + 3.96733E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.05494E-02, + 7.39617E-02, 1.92200E-02,-8.46151E-03,-1.34244E-02, 1.96338E-02, + 1.50421E+00, 1.88368E+01, 0.00000E+00, 0.00000E+00,-5.13114E+01, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 5.11923E-02, 3.61225E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00 +} }; + /* SEMIANNUAL MULT SAM */ -double sam[100] = -{ - 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, - 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, - 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, - 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, - 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, - 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, - 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, - 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, - 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, - 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, - 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 +double sam[100] = { + 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, + 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, + 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, + 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, + 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, + 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, + 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, + 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, + 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, + 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, + 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 }; - - + + /* MIDDLE ATMOSPHERE AVERAGES */ -double pavgm[10] = -{ - 2.61000E+02, 2.64000E+02, 2.29000E+02, 2.17000E+02, 2.17000E+02, - 2.23000E+02, 2.86760E+02,-2.93940E+00, 2.50000E+00, 0.00000E+00 -}; - +double pavgm[10] = { + 2.61000E+02, 2.64000E+02, 2.29000E+02, 2.17000E+02, 2.17000E+02, + 2.23000E+02, 2.86760E+02,-2.93940E+00, 2.50000E+00, 0.00000E+00 }; + } // namespace diff --git a/src/models/atmosphere/FGMars.cpp b/src/models/atmosphere/FGMars.cpp old mode 100644 new mode 100755 index 8c32f349d8c2bddcfc0f582b28fd547f1933dc2d..93c388f5f60f2b6dddae881660c2a24376d301f5 --- a/src/models/atmosphere/FGMars.cpp +++ b/src/models/atmosphere/FGMars.cpp @@ -46,8 +46,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGMars.cpp,v 1.10 2010/02/25 05:21:36 jberndt Exp $"; static const char *IdHdr = ID_MARS; @@ -59,33 +58,30 @@ CLASS IMPLEMENTATION FGMars::FGMars(FGFDMExec* fdmex) : FGAtmosphere(fdmex) { - Name = "FGMars"; - Reng = 53.5 * 44.01; + Name = "FGMars"; + Reng = 53.5 * 44.01; - bind(); - Debug(0); + bind(); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGMars::Calculate(double altitude) { - //Calculate reftemp, refpress, and density + //Calculate reftemp, refpress, and density - // LIMIT the temperatures so they do not descend below absolute zero. + // LIMIT the temperatures so they do not descend below absolute zero. - if (altitude < 22960.0) - { - intTemperature = -25.68 - 0.000548*altitude; // Deg Fahrenheit - } - else - { - intTemperature = -10.34 - 0.001217*altitude; // Deg Fahrenheit - } - intPressure = 14.62*exp(-0.00003*altitude); // psf - 14.62 psf =~ 7 millibars - intDensity = intPressure/(Reng*intTemperature); // slugs/ft^3 (needs deg R. as input + if (altitude < 22960.0) { + intTemperature = -25.68 - 0.000548*altitude; // Deg Fahrenheit + } else { + intTemperature = -10.34 - 0.001217*altitude; // Deg Fahrenheit + } + intPressure = 14.62*exp(-0.00003*altitude); // psf - 14.62 psf =~ 7 millibars + intDensity = intPressure/(Reng*intTemperature); // slugs/ft^3 (needs deg R. as input - //cout << "Atmosphere: h=" << altitude << " rho= " << intDensity << endl; + //cout << "Atmosphere: h=" << altitude << " rho= " << intDensity << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -109,51 +105,39 @@ void FGMars::Calculate(double altitude) void FGMars::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGMars" << endl; - if (from == 1) cout << "Destroyed: FGMars" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor } - if (debug_lvl & 32) // Turbulence - { - if (first_pass && from == 2) - { - cout << "vTurbulenceNED(X), vTurbulenceNED(Y), vTurbulenceNED(Z), " - << "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), " - << "vDirection(X), vDirection(Y), vDirection(Z), " - << "Magnitude, " - << "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl; - } - else if (from == 2) - { - cout << vTurbulenceNED << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGMars" << endl; + if (from == 1) cout << "Destroyed: FGMars" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 32) { // Turbulence + if (first_pass && from == 2) { + cout << "vTurbulenceNED(X), vTurbulenceNED(Y), vTurbulenceNED(Z), " + << "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), " + << "vDirection(X), vDirection(Y), vDirection(Z), " + << "Magnitude, " + << "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl; + } else if (from == 2) { + cout << vTurbulenceNED << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } // namespace JSBSim diff --git a/src/models/atmosphere/FGMars.h b/src/models/atmosphere/FGMars.h old mode 100644 new mode 100755 index 61bcea900a4eeca44240c0ce29a92332fcc64dff..e98634ecfb7661f707e9067dc689faaa62460d46 --- a/src/models/atmosphere/FGMars.h +++ b/src/models/atmosphere/FGMars.h @@ -1,32 +1,32 @@ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + Header: FGMars.h Author: Jon Berndt Date started: 01/05/2004 - + ------------- Copyright (C) 2004 Jon S. Berndt (jon@jsbsim.org) ------------- - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser 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. - + Further information about the GNU Lesser General Public License can also be found on the world wide web at http://www.gnu.org. - + HISTORY -------------------------------------------------------------------------------- 01/05/2004 JSB Created - + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SENTRY %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ @@ -50,8 +50,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -66,16 +65,15 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGMars : public FGAtmosphere -{ +class FGMars : public FGAtmosphere { public: - /// Constructor - FGMars(FGFDMExec*); + /// Constructor + FGMars(FGFDMExec*); private: - void Calculate(double altitude); + void Calculate(double altitude); - void Debug(int from); + void Debug(int from); }; } // namespace JSBSim diff --git a/src/models/flight_control/FGAccelerometer.cpp b/src/models/flight_control/FGAccelerometer.cpp old mode 100644 new mode 100755 index 044c9ffabc882e4d060fb27bb976afa2334d6156..30c2f2244f0dafd45dbce930af012b4c4f65f42d --- a/src/models/flight_control/FGAccelerometer.cpp +++ b/src/models/flight_control/FGAccelerometer.cpp @@ -43,8 +43,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGAccelerometer.cpp,v 1.8 2009/10/24 22:59:30 jberndt Exp $"; static const char *IdHdr = ID_ACCELEROMETER; @@ -54,57 +53,53 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGAccelerometer::FGAccelerometer(FGFCS* fcs, Element* element) - : FGSensor(fcs, element), - FGSensorOrientation(element) + : FGSensor(fcs, element), + FGSensorOrientation(element) { - Propagate = fcs->GetExec()->GetPropagate(); - MassBalance = fcs->GetExec()->GetMassBalance(); - Inertial = fcs->GetExec()->GetInertial(); - - Element* location_element = element->FindElement("location"); - if (location_element) vLocation = location_element->FindElementTripletConvertTo("IN"); - else - { - cerr << "No location given for accelerometer. " << endl; - exit(-1); - } + Propagate = fcs->GetExec()->GetPropagate(); + MassBalance = fcs->GetExec()->GetMassBalance(); + Inertial = fcs->GetExec()->GetInertial(); + + Element* location_element = element->FindElement("location"); + if (location_element) vLocation = location_element->FindElementTripletConvertTo("IN"); + else {cerr << "No location given for accelerometer. " << endl; exit(-1);} - vRadius = MassBalance->StructuralToBody(vLocation); + vRadius = MassBalance->StructuralToBody(vLocation); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGAccelerometer::~FGAccelerometer() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGAccelerometer::Run(void ) { - // There is no input assumed. This is a dedicated acceleration sensor. + // There is no input assumed. This is a dedicated acceleration sensor. - vRadius = MassBalance->StructuralToBody(vLocation); + vRadius = MassBalance->StructuralToBody(vLocation); + + //gravitational forces + vAccel = Propagate->GetTl2b() * FGColumnVector3(0, 0, Inertial->gravity()); - //gravitational forces - vAccel = Propagate->GetTl2b() * FGColumnVector3(0, 0, Inertial->gravity()); + //aircraft forces + vAccel += (Propagate->GetUVWdot() + + Propagate->GetPQRdot() * vRadius + + Propagate->GetPQR() * (Propagate->GetPQR() * vRadius)); - //aircraft forces - vAccel += (Propagate->GetUVWdot() - + Propagate->GetPQRdot() * vRadius - + Propagate->GetPQR() * (Propagate->GetPQR() * vRadius)); + // transform to the specified orientation + vAccel = mT * vAccel; - // transform to the specified orientation - vAccel = mT * vAccel; + Input = vAccel(axis); - Input = vAccel(axis); + ProcessSensorSignal(); - ProcessSensorSignal(); - - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -128,38 +123,30 @@ bool FGAccelerometer::Run(void ) void FGAccelerometer::Debug(int from) { - string ax[4] = {"none", "X", "Y", "Z"}; + string ax[4] = {"none", "X", "Y", "Z"}; - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " Axis: " << ax[axis] << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGAccelerometer" << endl; - if (from == 1) cout << "Destroyed: FGAccelerometer" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " Axis: " << ax[axis] << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGAccelerometer" << endl; + if (from == 1) cout << "Destroyed: FGAccelerometer" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGAccelerometer.h b/src/models/flight_control/FGAccelerometer.h old mode 100644 new mode 100755 index 0339202eba7254ce9e79ba0f1813e4d003c2f1b6..5616ed55b0cb7029849663a2e31d7708fa453fea --- a/src/models/flight_control/FGAccelerometer.h +++ b/src/models/flight_control/FGAccelerometer.h @@ -56,8 +56,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFCS; @@ -121,20 +120,20 @@ CLASS DECLARATION class FGAccelerometer : public FGSensor, public FGSensorOrientation { public: - FGAccelerometer(FGFCS* fcs, Element* element); - ~FGAccelerometer(); + FGAccelerometer(FGFCS* fcs, Element* element); + ~FGAccelerometer(); - bool Run (void); + bool Run (void); private: - FGPropagate* Propagate; - FGMassBalance* MassBalance; - FGInertial* Inertial; - FGColumnVector3 vLocation; - FGColumnVector3 vRadius; - FGColumnVector3 vAccel; - - void Debug(int from); + FGPropagate* Propagate; + FGMassBalance* MassBalance; + FGInertial* Inertial; + FGColumnVector3 vLocation; + FGColumnVector3 vRadius; + FGColumnVector3 vAccel; + + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGActuator.cpp b/src/models/flight_control/FGActuator.cpp index cbecc6413d1773e222b3c169cf358dc0a39ec04e..417c72fa237cf62d6623b6aba86006ab723222be 100644 --- a/src/models/flight_control/FGActuator.cpp +++ b/src/models/flight_control/FGActuator.cpp @@ -41,10 +41,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGActuator.cpp,v 1.14 2009/10/24 22:59:30 jberndt Exp $"; +static const char *IdSrc = "$Id: FGActuator.cpp,v 1.15 2010/08/21 22:56:11 jberndt Exp $"; static const char *IdHdr = ID_ACTUATOR; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -54,144 +53,134 @@ CLASS IMPLEMENTATION FGActuator::FGActuator(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - double denom; - - // inputs are read from the base class constructor - - PreviousOutput = 0.0; - PreviousHystOutput = 0.0; - PreviousRateLimOutput = 0.0; - PreviousLagInput = PreviousLagOutput = 0.0; - bias = lag = hysteresis_width = deadband_width = 0.0; - rate_limit = 0.0; // no limit - fail_zero = fail_hardover = fail_stuck = false; - ca = cb = 0.0; - - if ( element->FindElement("deadband_width") ) - { - deadband_width = element->FindElementValueAsNumber("deadband_width"); - } - if ( element->FindElement("hysteresis_width") ) - { - hysteresis_width = element->FindElementValueAsNumber("hysteresis_width"); - } - if ( element->FindElement("rate_limit") ) - { - rate_limit = element->FindElementValueAsNumber("rate_limit"); - } - if ( element->FindElement("bias") ) - { - bias = element->FindElementValueAsNumber("bias"); - } - if ( element->FindElement("lag") ) - { - lag = element->FindElementValueAsNumber("lag"); - denom = 2.00 + dt*lag; - ca = dt*lag / denom; - cb = (2.00 - dt*lag) / denom; - } - - FGFCSComponent::bind(); - bind(); - - Debug(0); + double denom; + + // inputs are read from the base class constructor + + PreviousOutput = 0.0; + PreviousHystOutput = 0.0; + PreviousRateLimOutput = 0.0; + PreviousLagInput = PreviousLagOutput = 0.0; + bias = lag = hysteresis_width = deadband_width = 0.0; + rate_limit = 0.0; // no limit + fail_zero = fail_hardover = fail_stuck = false; + ca = cb = 0.0; + + if ( element->FindElement("deadband_width") ) { + deadband_width = element->FindElementValueAsNumber("deadband_width"); + } + if ( element->FindElement("hysteresis_width") ) { + hysteresis_width = element->FindElementValueAsNumber("hysteresis_width"); + } + if ( element->FindElement("rate_limit") ) { + rate_limit = element->FindElementValueAsNumber("rate_limit"); + } + if ( element->FindElement("bias") ) { + bias = element->FindElementValueAsNumber("bias"); + } + if ( element->FindElement("lag") ) { + lag = element->FindElementValueAsNumber("lag"); + denom = 2.00 + dt*lag; + ca = dt*lag / denom; + cb = (2.00 - dt*lag) / denom; + } + + FGFCSComponent::bind(); + bind(); + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGActuator::~FGActuator() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGActuator::Run(void ) { - Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; - if (fail_zero) Input = 0; - if (fail_hardover) Input = clipmax*sign(Input); + if (fail_zero) Input = 0; + if (fail_hardover) Input = clipmax*sign(Input); - Output = Input; // Perfect actuator. At this point, if no failures are present - // and no subsequent lag, limiting, etc. is done, the output - // is simply the input. If any further processing is done - // (below) such as lag, rate limiting, hysteresis, etc., then - // the Input will be further processed and the eventual Output - // will be overwritten from this perfect value. + Output = Input; // Perfect actuator. At this point, if no failures are present + // and no subsequent lag, limiting, etc. is done, the output + // is simply the input. If any further processing is done + // (below) such as lag, rate limiting, hysteresis, etc., then + // the Input will be further processed and the eventual Output + // will be overwritten from this perfect value. - if (lag != 0.0) Lag(); // models actuator lag - if (rate_limit != 0) RateLimit(); // limit the actuator rate - if (deadband_width != 0.0) Deadband(); - if (hysteresis_width != 0.0) Hysteresis(); - if (bias != 0.0) Bias(); // models a finite bias + if (lag != 0.0) Lag(); // models actuator lag + if (rate_limit != 0) RateLimit(); // limit the actuator rate + if (deadband_width != 0.0) Deadband(); + if (hysteresis_width != 0.0) Hysteresis(); + if (bias != 0.0) Bias(); // models a finite bias - if (fail_stuck) Output = PreviousOutput; - PreviousOutput = Output; // previous value needed for "stuck" malfunction + if (fail_stuck) Output = PreviousOutput; + PreviousOutput = Output; // previous value needed for "stuck" malfunction - Clip(); - if (IsOutput) SetOutput(); + Clip(); + if (IsOutput) SetOutput(); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGActuator::Bias(void) { - Output += bias; + Output += bias; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGActuator::Lag(void) { - // "Output" on the right side of the "=" is the current frame input - // for this Lag filter - double input = Output; - Output = ca * (input + PreviousLagInput) + PreviousLagOutput * cb; - PreviousLagInput = input; - PreviousLagOutput = Output; + // "Output" on the right side of the "=" is the current frame input + // for this Lag filter + double input = Output; + Output = ca * (input + PreviousLagInput) + PreviousLagOutput * cb; + PreviousLagInput = input; + PreviousLagOutput = Output; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGActuator::Hysteresis(void) { - // Note: this function acts cumulatively on the "Output" parameter. So, "Output" - // is - for the purposes of this Hysteresis method - really the input to the - // method. - double input = Output; - - if (input > PreviousHystOutput) - { - Output = max(PreviousHystOutput, input-0.5*hysteresis_width); - } - else if (input < PreviousHystOutput) - { - Output = min(PreviousHystOutput, input+0.5*hysteresis_width); - } - - PreviousHystOutput = Output; + // Note: this function acts cumulatively on the "Output" parameter. So, "Output" + // is - for the purposes of this Hysteresis method - really the input to the + // method. + double input = Output; + + if (input > PreviousHystOutput) { + Output = max(PreviousHystOutput, input-0.5*hysteresis_width); + } else if (input < PreviousHystOutput) { + Output = min(PreviousHystOutput, input+0.5*hysteresis_width); + } + + PreviousHystOutput = Output; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGActuator::RateLimit(void) { - // Note: this function acts cumulatively on the "Output" parameter. So, "Output" - // is - for the purposes of this RateLimit method - really the input to the - // method. - double input = Output; - if (dt > 0.0) - { - double rate = (input - PreviousRateLimOutput)/dt; - if (fabs(rate) > rate_limit) - { - Output = PreviousRateLimOutput + (rate_limit*fabs(rate)/rate)*dt; - } + // Note: this function acts cumulatively on the "Output" parameter. So, "Output" + // is - for the purposes of this RateLimit method - really the input to the + // method. + double input = Output; + if (dt > 0.0) { + double rate = (input - PreviousRateLimOutput)/dt; + if (fabs(rate) > rate_limit) { + Output = PreviousRateLimOutput + (rate_limit*fabs(rate)/rate)*dt; } - PreviousRateLimOutput = Output; + } + PreviousRateLimOutput = Output; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -204,18 +193,17 @@ void FGActuator::Deadband(void) void FGActuator::bind(void) { - string tmp = Name; - if (Name.find("/") == string::npos) - { - tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true); - } - const string tmp_zero = tmp + "/malfunction/fail_zero"; - const string tmp_hardover = tmp + "/malfunction/fail_hardover"; - const string tmp_stuck = tmp + "/malfunction/fail_stuck"; - - PropertyManager->Tie( tmp_zero, this, &FGActuator::GetFailZero, &FGActuator::SetFailZero); - PropertyManager->Tie( tmp_hardover, this, &FGActuator::GetFailHardover, &FGActuator::SetFailHardover); - PropertyManager->Tie( tmp_stuck, this, &FGActuator::GetFailStuck, &FGActuator::SetFailStuck); + string tmp = Name; + if (Name.find("/") == string::npos) { + tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true); + } + const string tmp_zero = tmp + "/malfunction/fail_zero"; + const string tmp_hardover = tmp + "/malfunction/fail_hardover"; + const string tmp_stuck = tmp + "/malfunction/fail_stuck"; + + PropertyManager->Tie( tmp_zero, this, &FGActuator::GetFailZero, &FGActuator::SetFailZero); + PropertyManager->Tie( tmp_hardover, this, &FGActuator::GetFailHardover, &FGActuator::SetFailHardover); + PropertyManager->Tie( tmp_stuck, this, &FGActuator::GetFailStuck, &FGActuator::SetFailStuck); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -239,50 +227,41 @@ void FGActuator::bind(void) void FGActuator::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - if (InputSigns[0] < 0) - cout << " INPUT: -" << InputNodes[0]->getName() << endl; - else - cout << " INPUT: " << InputNodes[0]->getName() << endl; - - if (IsOutput) - { - for (unsigned int i=0; i<OutputNodes.size(); i++) - cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; - } - if (bias != 0.0) cout << " Bias: " << bias << endl; - if (rate_limit != 0) cout << " Rate limit: " << rate_limit << endl; - if (lag != 0) cout << " Actuator lag: " << lag << endl; - if (hysteresis_width != 0) cout << " Hysteresis width: " << hysteresis_width << endl; - if (deadband_width != 0) cout << " Deadband width: " << deadband_width << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGActuator" << endl; - if (from == 1) cout << "Destroyed: FGActuator" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + if (InputSigns[0] < 0) + cout << " INPUT: -" << InputNames[0] << endl; + else + cout << " INPUT: " << InputNames[0] << endl; + + if (IsOutput) { + for (unsigned int i=0; i<OutputNodes.size(); i++) + cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; + } + if (bias != 0.0) cout << " Bias: " << bias << endl; + if (rate_limit != 0) cout << " Rate limit: " << rate_limit << endl; + if (lag != 0) cout << " Actuator lag: " << lag << endl; + if (hysteresis_width != 0) cout << " Hysteresis width: " << hysteresis_width << endl; + if (deadband_width != 0) cout << " Deadband width: " << deadband_width << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGActuator" << endl; + if (from == 1) cout << "Destroyed: FGActuator" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGActuator.h b/src/models/flight_control/FGActuator.h index 276a7f6f3604384ec404c15cc499c039152003ab..7a7866e6d580c73201174a2a4865109fd947a094 100644 --- a/src/models/flight_control/FGActuator.h +++ b/src/models/flight_control/FGActuator.h @@ -50,8 +50,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFCS; @@ -65,14 +64,14 @@ CLASS DOCUMENTATION by specifying any/all of the following additional effects that can be applied to the actuator. In order of application to the input signal, these are: - + - System lag (input lag, really) - Rate limiting - Deadband - Hysteresis (mechanical hysteresis) - Bias (mechanical bias) - Position limiting ("hard stops") - + There are also several malfunctions that can be applied to the actuator by setting a property to true or false (or 1 or 0). @@ -122,73 +121,55 @@ CLASS DECLARATION class FGActuator : public FGFCSComponent { public: - /// Constructor - FGActuator(FGFCS* fcs, Element* element); - /// Destructor - ~FGActuator(); - - /** This function processes the input. - It calls private functions if needed to perform the hysteresis, lag, - limiting, etc. functions. */ - bool Run (void); - - // these may need to have the bool argument replaced with a double - /** This function fails the actuator to zero. The motion to zero - will flow through the lag, hysteresis, and rate limiting - functions if those are activated. */ - inline void SetFailZero(bool set) - { - fail_zero = set; - } - inline void SetFailHardover(bool set) - { - fail_hardover = set; - } - inline void SetFailStuck(bool set) - { - fail_stuck = set; - } - - inline bool GetFailZero(void) const - { - return fail_zero; - } - inline bool GetFailHardover(void) const - { - return fail_hardover; - } - inline bool GetFailStuck(void) const - { - return fail_stuck; - } - + /// Constructor + FGActuator(FGFCS* fcs, Element* element); + /// Destructor + ~FGActuator(); + + /** This function processes the input. + It calls private functions if needed to perform the hysteresis, lag, + limiting, etc. functions. */ + bool Run (void); + + // these may need to have the bool argument replaced with a double + /** This function fails the actuator to zero. The motion to zero + will flow through the lag, hysteresis, and rate limiting + functions if those are activated. */ + inline void SetFailZero(bool set) {fail_zero = set;} + inline void SetFailHardover(bool set) {fail_hardover = set;} + inline void SetFailStuck(bool set) {fail_stuck = set;} + + inline bool GetFailZero(void) const {return fail_zero;} + inline bool GetFailHardover(void) const {return fail_hardover;} + inline bool GetFailStuck(void) const {return fail_stuck;} + private: - double span; - double bias; - double rate_limit; - double hysteresis_width; - double deadband_width; - double lag; - double ca; // lag filter coefficient "a" - double cb; // lag filter coefficient "b" - double PreviousOutput; - double PreviousHystOutput; - double PreviousRateLimOutput; - double PreviousLagInput; - double PreviousLagOutput; - bool fail_zero; - bool fail_hardover; - bool fail_stuck; - - void Hysteresis(void); - void Lag(void); - void RateLimit(void); - void Deadband(void); - void Bias(void); - - void bind(void); - - void Debug(int from); + double span; + double bias; + double rate_limit; + double hysteresis_width; + double deadband_width; + double lag; + double ca; // lag filter coefficient "a" + double cb; // lag filter coefficient "b" + double PreviousOutput; + double PreviousHystOutput; + double PreviousRateLimOutput; + double PreviousLagInput; + double PreviousLagOutput; + bool fail_zero; + bool fail_hardover; + bool fail_stuck; + + void Hysteresis(void); + void Lag(void); + void RateLimit(void); + void Deadband(void); + void Bias(void); + + void bind(void); + + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGDeadBand.cpp b/src/models/flight_control/FGDeadBand.cpp index 5aa2e03d64b37887a78c728af01f13d950022b07..354b1d8b99cdf01c998b672dd6912bcf78ab8554 100644 --- a/src/models/flight_control/FGDeadBand.cpp +++ b/src/models/flight_control/FGDeadBand.cpp @@ -44,10 +44,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGDeadBand.cpp,v 1.9 2009/10/24 22:59:30 jberndt Exp $"; +static const char *IdSrc = "$Id: FGDeadBand.cpp,v 1.10 2010/08/21 22:56:11 jberndt Exp $"; static const char *IdHdr = ID_DEADBAND; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -58,76 +57,64 @@ CLASS IMPLEMENTATION FGDeadBand::FGDeadBand(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - string width_string; - - WidthPropertyNode = 0; - WidthPropertySign = 1.0; - gain = 1.0; - width = 0.0; - - if ( element->FindElement("width") ) - { - width_string = element->FindElementValue("width"); - if (!is_number(width_string)) // property - { - if (width_string[0] == '-') - { - WidthPropertySign = -1.0; - width_string.erase(0,1); - } - WidthPropertyNode = PropertyManager->GetNode(width_string); - } - else - { - width = element->FindElementValueAsNumber("width"); - } + string width_string; + + WidthPropertyNode = 0; + WidthPropertySign = 1.0; + gain = 1.0; + width = 0.0; + + if ( element->FindElement("width") ) { + width_string = element->FindElementValue("width"); + if (!is_number(width_string)) { // property + if (width_string[0] == '-') { + WidthPropertySign = -1.0; + width_string.erase(0,1); + } + WidthPropertyNode = PropertyManager->GetNode(width_string); + } else { + width = element->FindElementValueAsNumber("width"); } + } - if (element->FindElement("gain")) - { - gain = element->FindElementValueAsNumber("gain"); - } + if (element->FindElement("gain")) { + gain = element->FindElementValueAsNumber("gain"); + } - FGFCSComponent::bind(); - Debug(0); + FGFCSComponent::bind(); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGDeadBand::~FGDeadBand() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGDeadBand::Run(void ) { - Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; - if (WidthPropertyNode != 0) - { - width = WidthPropertyNode->getDoubleValue() * WidthPropertySign; - } + if (WidthPropertyNode != 0) { + width = WidthPropertyNode->getDoubleValue() * WidthPropertySign; + } - if (Input < -width/2.0) - { - Output = (Input + width/2.0)*gain; - } - else if (Input > width/2.0) - { - Output = (Input - width/2.0)*gain; - } - else - { - Output = 0.0; - } + if (Input < -width/2.0) { + Output = (Input + width/2.0)*gain; + } else if (Input > width/2.0) { + Output = (Input - width/2.0)*gain; + } else { + Output = 0.0; + } - Clip(); + Clip(); - if (IsOutput) SetOutput(); + if (IsOutput) SetOutput(); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -151,50 +138,38 @@ bool FGDeadBand::Run(void ) void FGDeadBand::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " INPUT: " << InputNodes[0]->getName() << endl; - if (WidthPropertyNode != 0) - { - cout << " DEADBAND WIDTH: " << WidthPropertyNode->GetName() << endl; - } - else - { - cout << " DEADBAND WIDTH: " << width << endl; - } - cout << " GAIN: " << gain << endl; - if (IsOutput) - { - for (unsigned int i=0; i<OutputNodes.size(); i++) - cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; - } - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGDeadBand" << endl; - if (from == 1) cout << "Destroyed: FGDeadBand" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " INPUT: " << InputNames[0] << endl; + if (WidthPropertyNode != 0) { + cout << " DEADBAND WIDTH: " << WidthPropertyNode->GetName() << endl; + } else { + cout << " DEADBAND WIDTH: " << width << endl; + } + cout << " GAIN: " << gain << endl; + if (IsOutput) { + for (unsigned int i=0; i<OutputNodes.size(); i++) + cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; + } } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGDeadBand" << endl; + if (from == 1) cout << "Destroyed: FGDeadBand" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGDeadBand.h b/src/models/flight_control/FGDeadBand.h index e2095a853e139e56ec4594131f7af0e038f0c79c..80464769f6ef2618a92fa9a724fffde3ad73dad7 100644 --- a/src/models/flight_control/FGDeadBand.h +++ b/src/models/flight_control/FGDeadBand.h @@ -49,8 +49,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFCS; class Element; @@ -91,18 +90,18 @@ CLASS DECLARATION class FGDeadBand : public FGFCSComponent { public: - FGDeadBand(FGFCS* fcs, Element* element); - ~FGDeadBand(); + FGDeadBand(FGFCS* fcs, Element* element); + ~FGDeadBand(); - bool Run(void); + bool Run(void); private: - double width; - double gain; - FGPropertyManager* WidthPropertyNode; - double WidthPropertySign; + double width; + double gain; + FGPropertyManager* WidthPropertyNode; + double WidthPropertySign; - void Debug(int from); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/flight_control/FGFCSComponent.cpp b/src/models/flight_control/FGFCSComponent.cpp index 42b746e9582196f0518845bb17988c1eaa0be8fa..6cdf9ab8334ab381cb00c91f759369817637b4bb 100644 --- a/src/models/flight_control/FGFCSComponent.cpp +++ b/src/models/flight_control/FGFCSComponent.cpp @@ -45,10 +45,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.27 2009/10/24 22:59:30 jberndt Exp $"; +static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.29 2010/09/07 00:40:03 jberndt Exp $"; static const char *IdHdr = ID_FCSCOMPONENT; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -57,251 +56,204 @@ CLASS IMPLEMENTATION FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs) { - Element *input_element, *clip_el; - Input = Output = clipmin = clipmax = 0.0; - treenode = 0; - delay = index = 0; - ClipMinPropertyNode = ClipMaxPropertyNode = 0; - clipMinSign = clipMaxSign = 1.0; - IsOutput = clip = false; - string input, clip_string; - dt = fcs->GetDt(); - - PropertyManager = fcs->GetPropertyManager(); - if (element->GetName() == string("lag_filter")) - { - Type = "LAG_FILTER"; - } - else if (element->GetName() == string("lead_lag_filter")) - { - Type = "LEAD_LAG_FILTER"; - } - else if (element->GetName() == string("washout_filter")) - { - Type = "WASHOUT_FILTER"; - } - else if (element->GetName() == string("second_order_filter")) - { - Type = "SECOND_ORDER_FILTER"; - } - else if (element->GetName() == string("integrator")) - { - Type = "INTEGRATOR"; - } - else if (element->GetName() == string("summer")) - { - Type = "SUMMER"; - } - else if (element->GetName() == string("pure_gain")) - { - Type = "PURE_GAIN"; - } - else if (element->GetName() == string("scheduled_gain")) - { - Type = "SCHEDULED_GAIN"; - } - else if (element->GetName() == string("aerosurface_scale")) - { - Type = "AEROSURFACE_SCALE"; - } - else if (element->GetName() == string("switch")) - { - Type = "SWITCH"; - } - else if (element->GetName() == string("kinematic")) - { - Type = "KINEMATIC"; - } - else if (element->GetName() == string("deadband")) - { - Type = "DEADBAND"; - } - else if (element->GetName() == string("fcs_function")) - { - Type = "FCS_FUNCTION"; - } - else if (element->GetName() == string("pid")) - { - Type = "PID"; - } - else if (element->GetName() == string("sensor")) - { - Type = "SENSOR"; - } - else if (element->GetName() == string("accelerometer")) - { - Type = "ACCELEROMETER"; - } - else if (element->GetName() == string("magnetometer")) - { - Type = "MAGNETOMETER"; - } - else if (element->GetName() == string("gyro")) - { - Type = "GYRO"; - } - else if (element->GetName() == string("actuator")) - { - Type = "ACTUATOR"; - } - else // illegal component in this channel - { - Type = "UNKNOWN"; - } - - Name = element->GetAttributeValue("name"); - - FGPropertyManager *tmp=0; - - input_element = element->FindElement("input"); - while (input_element) - { - input = input_element->GetDataLine(); - if (input[0] == '-') - { - InputSigns.push_back(-1.0); - input.erase(0,1); - } - else - { - InputSigns.push_back( 1.0); - } - tmp = PropertyManager->GetNode(input); - if (tmp) - { - InputNodes.push_back( tmp ); - } - else - { - cerr << fgred << " In component: " << Name << " unknown property " - << input << " referenced. Aborting" << reset << endl; - exit(-1); - } - input_element = element->FindNextElement("input"); - } - - Element *out_elem = element->FindElement("output"); - while (out_elem) - { - IsOutput = true; - string output_node_name = out_elem->GetDataLine(); - FGPropertyManager* OutputNode = PropertyManager->GetNode( output_node_name, true ); - OutputNodes.push_back(OutputNode); - if (!OutputNode) - { - cerr << endl << " Unable to process property: " << output_node_name << endl; - throw(string("Invalid output property name in flight control definition")); - } - out_elem = element->FindNextElement("output"); - } - - Element* delay_elem = element->FindElement("delay"); - if ( delay_elem ) - { - delay = (unsigned int)delay_elem->GetDataAsNumber(); - string delayType = delay_elem->GetAttributeValue("type"); - if (delayType.length() > 0) - { - if (delayType == "time") - { - delay = (int)(delay / dt); - } - else if (delayType == "frames") - { - // no op. the delay type of "frames" is assumed and is the default. - } - else - { - cerr << "Unallowed delay type" << endl; - } - } - else - { - delay = (int)(delay / dt); - } - output_array.resize(delay); - for (int i=0; i<delay; i++) output_array[i] = 0.0; - } - - clip_el = element->FindElement("clipto"); - if (clip_el) - { - clip_string = clip_el->FindElementValue("min"); - if (!is_number(clip_string)) // it's a property - { - if (clip_string[0] == '-') - { - clipMinSign = -1.0; - clip_string.erase(0,1); - } - ClipMinPropertyNode = PropertyManager->GetNode( clip_string ); - } - else - { - clipmin = clip_el->FindElementValueAsNumber("min"); - } - clip_string = clip_el->FindElementValue("max"); - if (!is_number(clip_string)) // it's a property - { - if (clip_string[0] == '-') - { - clipMaxSign = -1.0; - clip_string.erase(0,1); - } - ClipMaxPropertyNode = PropertyManager->GetNode( clip_string ); - } - else - { - clipmax = clip_el->FindElementValueAsNumber("max"); - } - clip = true; - } - - Debug(0); + Element *input_element, *clip_el; + Input = Output = clipmin = clipmax = 0.0; + treenode = 0; + delay = index = 0; + ClipMinPropertyNode = ClipMaxPropertyNode = 0; + clipMinSign = clipMaxSign = 1.0; + IsOutput = clip = false; + string input, clip_string; + dt = fcs->GetDt(); + + PropertyManager = fcs->GetPropertyManager(); + if (element->GetName() == string("lag_filter")) { + Type = "LAG_FILTER"; + } else if (element->GetName() == string("lead_lag_filter")) { + Type = "LEAD_LAG_FILTER"; + } else if (element->GetName() == string("washout_filter")) { + Type = "WASHOUT_FILTER"; + } else if (element->GetName() == string("second_order_filter")) { + Type = "SECOND_ORDER_FILTER"; + } else if (element->GetName() == string("integrator")) { + Type = "INTEGRATOR"; + } else if (element->GetName() == string("summer")) { + Type = "SUMMER"; + } else if (element->GetName() == string("pure_gain")) { + Type = "PURE_GAIN"; + } else if (element->GetName() == string("scheduled_gain")) { + Type = "SCHEDULED_GAIN"; + } else if (element->GetName() == string("aerosurface_scale")) { + Type = "AEROSURFACE_SCALE"; + } else if (element->GetName() == string("switch")) { + Type = "SWITCH"; + } else if (element->GetName() == string("kinematic")) { + Type = "KINEMATIC"; + } else if (element->GetName() == string("deadband")) { + Type = "DEADBAND"; + } else if (element->GetName() == string("fcs_function")) { + Type = "FCS_FUNCTION"; + } else if (element->GetName() == string("pid")) { + Type = "PID"; + } else if (element->GetName() == string("sensor")) { + Type = "SENSOR"; + } else if (element->GetName() == string("accelerometer")) { + Type = "ACCELEROMETER"; + } else if (element->GetName() == string("magnetometer")) { + Type = "MAGNETOMETER"; + } else if (element->GetName() == string("gyro")) { + Type = "GYRO"; + } else if (element->GetName() == string("actuator")) { + Type = "ACTUATOR"; + } else { // illegal component in this channel + Type = "UNKNOWN"; + } + + Name = element->GetAttributeValue("name"); + + FGPropertyManager *tmp=0; + + input_element = element->FindElement("input"); + while (input_element) { + input = input_element->GetDataLine(); + if (input[0] == '-') { + InputSigns.push_back(-1.0); + input.erase(0,1); + } else { + InputSigns.push_back( 1.0); + } + if (PropertyManager->HasNode(input)) { + tmp = PropertyManager->GetNode(input); + } else { + tmp = 0L; + // cerr << fgcyan << "In component: " + Name + " property " + // + input + " is initially undefined." << reset << endl; + } + InputNodes.push_back( tmp ); + InputNames.push_back( input ); + + input_element = element->FindNextElement("input"); + } + + Element *out_elem = element->FindElement("output"); + while (out_elem) { + IsOutput = true; + string output_node_name = out_elem->GetDataLine(); + FGPropertyManager* OutputNode = PropertyManager->GetNode( output_node_name, true ); + OutputNodes.push_back(OutputNode); + if (!OutputNode) { + cerr << endl << " Unable to process property: " << output_node_name << endl; + throw(string("Invalid output property name in flight control definition")); + } + out_elem = element->FindNextElement("output"); + } + + Element* delay_elem = element->FindElement("delay"); + if ( delay_elem ) { + delay = (unsigned int)delay_elem->GetDataAsNumber(); + string delayType = delay_elem->GetAttributeValue("type"); + if (delayType.length() > 0) { + if (delayType == "time") { + delay = (int)(delay / dt); + } else if (delayType == "frames") { + // no op. the delay type of "frames" is assumed and is the default. + } else { + cerr << "Unallowed delay type" << endl; + } + } else { + delay = (int)(delay / dt); + } + output_array.resize(delay); + for (int i=0; i<delay; i++) output_array[i] = 0.0; + } + + clip_el = element->FindElement("clipto"); + if (clip_el) { + clip_string = clip_el->FindElementValue("min"); + if (!is_number(clip_string)) { // it's a property + if (clip_string[0] == '-') { + clipMinSign = -1.0; + clip_string.erase(0,1); + } + ClipMinPropertyNode = PropertyManager->GetNode( clip_string ); + } else { + clipmin = clip_el->FindElementValueAsNumber("min"); + } + clip_string = clip_el->FindElementValue("max"); + if (!is_number(clip_string)) { // it's a property + if (clip_string[0] == '-') { + clipMaxSign = -1.0; + clip_string.erase(0,1); + } + ClipMaxPropertyNode = PropertyManager->GetNode( clip_string ); + } else { + clipmax = clip_el->FindElementValueAsNumber("max"); + } + clip = true; + } + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGFCSComponent::~FGFCSComponent() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCSComponent::SetOutput(void) { - for (unsigned int i=0; i<OutputNodes.size(); i++) OutputNodes[i]->setDoubleValue(Output); + for (unsigned int i=0; i<OutputNodes.size(); i++) OutputNodes[i]->setDoubleValue(Output); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFCSComponent::Run(void) { - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCSComponent::Delay(void) { - output_array[index] = Output; - if (index == delay-1) index = 0; - else index++; - Output = output_array[index]; + output_array[index] = Output; + if (index == delay-1) index = 0; + else index++; + Output = output_array[index]; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFCSComponent::Clip(void) { - if (clip) - { - if (ClipMinPropertyNode != 0) clipmin = clipMinSign*ClipMinPropertyNode->getDoubleValue(); - if (ClipMaxPropertyNode != 0) clipmax = clipMaxSign*ClipMaxPropertyNode->getDoubleValue(); - if (Output > clipmax) Output = clipmax; - else if (Output < clipmin) Output = clipmin; - } + if (clip) { + if (ClipMinPropertyNode != 0) clipmin = clipMinSign*ClipMinPropertyNode->getDoubleValue(); + if (ClipMaxPropertyNode != 0) clipmax = clipMaxSign*ClipMaxPropertyNode->getDoubleValue(); + if (Output > clipmax) Output = clipmax; + else if (Output < clipmin) Output = clipmin; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGFCSComponent::LateBind(void) +{ + FGPropertyManager* node = 0L; + + for (unsigned int i=0; i<InputNodes.size(); i++) { + if (!InputNodes[i]) { + if (PropertyManager->HasNode(InputNames[i])) { + node = PropertyManager->GetNode(InputNames[i]); + InputNodes[i] = node; + } else { + throw(InputNames[i]); + } + } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -314,16 +266,13 @@ void FGFCSComponent::Clip(void) void FGFCSComponent::bind(void) { - string tmp; - if (Name.find("/") == string::npos) - { - tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true); - } - else - { - tmp = Name; - } - PropertyManager->Tie( tmp, this, &FGFCSComponent::GetOutput); + string tmp; + if (Name.find("/") == string::npos) { + tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true); + } else { + tmp = Name; + } + PropertyManager->Tie( tmp, this, &FGFCSComponent::GetOutput); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -347,65 +296,50 @@ void FGFCSComponent::bind(void) void FGFCSComponent::Debug(int from) { - string propsign=""; - - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) - { - cout << endl << " Loading Component \"" << Name - << "\" of type: " << Type << endl; - - if (clip) - { - if (ClipMinPropertyNode != 0L) - { - if (clipMinSign < 0.0) propsign="-"; - cout << " Minimum limit: " << propsign << ClipMinPropertyNode->GetName() << endl; - propsign=""; - } - else - { - cout << " Minimum limit: " << clipmin << endl; - } - if (ClipMaxPropertyNode != 0L) - { - if (clipMaxSign < 0.0) propsign="-"; - cout << " Maximum limit: " << propsign << ClipMaxPropertyNode->GetName() << endl; - propsign=""; - } - else - { - cout << " Maximum limit: " << clipmax << endl; - } - } - if (delay > 0) cout <<" Frame delay: " << delay - << " frames (" << delay*dt << " sec)" << endl; + string propsign=""; + + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { + cout << endl << " Loading Component \"" << Name + << "\" of type: " << Type << endl; + + if (clip) { + if (ClipMinPropertyNode != 0L) { + if (clipMinSign < 0.0) propsign="-"; + cout << " Minimum limit: " << propsign << ClipMinPropertyNode->GetName() << endl; + propsign=""; + } else { + cout << " Minimum limit: " << clipmin << endl; } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGFCSComponent" << endl; - if (from == 1) cout << "Destroyed: FGFCSComponent" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; + if (ClipMaxPropertyNode != 0L) { + if (clipMaxSign < 0.0) propsign="-"; + cout << " Maximum limit: " << propsign << ClipMaxPropertyNode->GetName() << endl; + propsign=""; + } else { + cout << " Maximum limit: " << clipmax << endl; } - } + } + if (delay > 0) cout <<" Frame delay: " << delay + << " frames (" << delay*dt << " sec)" << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGFCSComponent" << endl; + if (from == 1) cout << "Destroyed: FGFCSComponent" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; + } + } } } diff --git a/src/models/flight_control/FGFCSComponent.h b/src/models/flight_control/FGFCSComponent.h index 950b92c54a45e11fd27f1984e5250af9c068dee1..7889cd948a243b05ca40ee82381aef325bc915b9 100644 --- a/src/models/flight_control/FGFCSComponent.h +++ b/src/models/flight_control/FGFCSComponent.h @@ -45,14 +45,13 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $" +#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.17 2010/08/21 22:56:11 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFCS; class FGPropertyManager; @@ -81,7 +80,7 @@ CLASS DOCUMENTATION - FGActuator @author Jon S. Berndt - @version $Id: FGFCSComponent.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $ + @version $Id: FGFCSComponent.h,v 1.17 2010/08/21 22:56:11 jberndt Exp $ @see Documentation for the FGFCS class, and for the configuration file class */ @@ -92,56 +91,46 @@ CLASS DECLARATION class FGFCSComponent : public FGJSBBase { public: - /// Constructor - FGFCSComponent(FGFCS* fcs, Element* el); - /// Destructor - virtual ~FGFCSComponent(); - - virtual bool Run(void); - virtual void SetOutput(void); - double GetOutput (void) const - { - return Output; - } - std::string GetName(void) const - { - return Name; - } - std::string GetType(void) const - { - return Type; - } - virtual double GetOutputPct(void) const - { - return 0; - } + /// Constructor + FGFCSComponent(FGFCS* fcs, Element* el); + /// Destructor + virtual ~FGFCSComponent(); + + virtual bool Run(void); + virtual void SetOutput(void); + void LateBind(void); + double GetOutput (void) const {return Output;} + std::string GetName(void) const {return Name;} + std::string GetType(void) const { return Type; } + virtual double GetOutputPct(void) const { return 0; } protected: - FGFCS* fcs; - FGPropertyManager* PropertyManager; - FGPropertyManager* treenode; - std::vector <FGPropertyManager*> OutputNodes; - FGPropertyManager* ClipMinPropertyNode; - FGPropertyManager* ClipMaxPropertyNode; - std::vector <FGPropertyManager*> InputNodes; - std::vector <float> InputSigns; - std::vector <double> output_array; - std::string Type; - std::string Name; - double Input; - double Output; - double clipmax, clipmin; - int delay; - int index; - float clipMinSign, clipMaxSign; - double dt; - bool IsOutput; - bool clip; - - void Delay(void); - void Clip(void); - virtual void bind(); - virtual void Debug(int from); + FGFCS* fcs; + FGPropertyManager* PropertyManager; + FGPropertyManager* treenode; + std::vector <FGPropertyManager*> OutputNodes; + FGPropertyManager* ClipMinPropertyNode; + FGPropertyManager* ClipMaxPropertyNode; + std::vector <FGPropertyManager*> InputNodes; + std::vector <std::string> InputNames; + std::vector <float> InputSigns; + std::vector <double> output_array; + std::string Type; + std::string Name; + double Input; + double Output; + double clipmax, clipmin; + int delay; + int index; + float clipMinSign, clipMaxSign; + double dt; + bool IsOutput; + bool clip; + + void Delay(void); + void Clip(void); + virtual void bind(); + virtual void Debug(int from); }; } //namespace JSBSim diff --git a/src/models/flight_control/FGFCSFunction.cpp b/src/models/flight_control/FGFCSFunction.cpp old mode 100644 new mode 100755 index ffc17e2024302b5fa227e66f87751e2edb5e60ff..c2119491719077185199ad67ae33523380994be7 --- a/src/models/flight_control/FGFCSFunction.cpp +++ b/src/models/flight_control/FGFCSFunction.cpp @@ -43,10 +43,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGFCSFunction.cpp,v 1.9 2009/10/24 22:59:30 jberndt Exp $"; +static const char *IdSrc = "$Id: FGFCSFunction.cpp,v 1.10 2010/08/21 22:56:11 jberndt Exp $"; static const char *IdHdr = ID_FCSFUNCTION; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -57,45 +56,43 @@ CLASS IMPLEMENTATION FGFCSFunction::FGFCSFunction(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - Element *function_element = element->FindElement("function"); - - if (function_element) - function = new FGFunction(PropertyManager, function_element); - else - { - cerr << "FCS Function should contain a \"function\" element" << endl; - exit(-1); - } + Element *function_element = element->FindElement("function"); + + if (function_element) + function = new FGFunction(PropertyManager, function_element); + else { + cerr << "FCS Function should contain a \"function\" element" << endl; + exit(-1); + } - FGFCSComponent::bind(); - Debug(0); + FGFCSComponent::bind(); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGFCSFunction::~FGFCSFunction() { - delete function; - Debug(1); + delete function; + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFCSFunction::Run(void ) { - Output = function->GetValue(); + Output = function->GetValue(); - if (InputNodes.size() > 0) - { - Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; - Output*= Input; - } + if (InputNodes.size() > 0) { + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + Output*= Input; + } - Clip(); + Clip(); - if (IsOutput) SetOutput(); + if (IsOutput) SetOutput(); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -119,43 +116,34 @@ bool FGFCSFunction::Run(void ) void FGFCSFunction::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - if (InputNodes.size()>0) - cout << " INPUT: " << InputNodes[0]->getName() << endl; + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + if (InputNodes.size()>0) + cout << " INPUT: " << InputNames[0] << endl; // cout << " Function: " << endl; - if (IsOutput) - { - for (unsigned int i=0; i<OutputNodes.size(); i++) - cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; - } - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGFCSFunction" << endl; - if (from == 1) cout << "Destroyed: FGFCSFunction" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (IsOutput) { + for (unsigned int i=0; i<OutputNodes.size(); i++) + cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; + } } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGFCSFunction" << endl; + if (from == 1) cout << "Destroyed: FGFCSFunction" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGFCSFunction.h b/src/models/flight_control/FGFCSFunction.h old mode 100644 new mode 100755 index bee3093014499a7187a74f5637e15cb38805371a..d6524edf248c195808c555b7aab6be905d869650 --- a/src/models/flight_control/FGFCSFunction.h +++ b/src/models/flight_control/FGFCSFunction.h @@ -51,8 +51,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFCS; @@ -65,7 +64,7 @@ CLASS DOCUMENTATION One of the most recent additions to the FCS component set is the FCS Function component. This component allows a function to be created when no other component -is suitable. Available mathematical operations are described in the FGFunction class. +is suitable. Available mathematical operations are described in the FGFunction class. The function component is defined as follows: @code @@ -116,15 +115,15 @@ CLASS DECLARATION class FGFCSFunction : public FGFCSComponent { public: - FGFCSFunction(FGFCS* fcs, Element* element); - ~FGFCSFunction(); + FGFCSFunction(FGFCS* fcs, Element* element); + ~FGFCSFunction(); - bool Run(void); + bool Run(void); private: - FGFunction* function; + FGFunction* function; - void Debug(int from); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/flight_control/FGFilter.cpp b/src/models/flight_control/FGFilter.cpp index 7f2b902612847ce678e772c9e27fc75c1729d37a..39f4f3e95ffb544d91fb5e10e24dad5c5cf8311c 100644 --- a/src/models/flight_control/FGFilter.cpp +++ b/src/models/flight_control/FGFilter.cpp @@ -46,10 +46,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGFilter.cpp,v 1.15 2009/10/24 22:59:30 jberndt Exp $"; +static const char *IdSrc = "$Id: FGFilter.cpp,v 1.16 2010/08/21 22:56:11 jberndt Exp $"; static const char *IdHdr = ID_FILTER; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -58,131 +57,121 @@ CLASS IMPLEMENTATION FGFilter::FGFilter(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - Trigger = 0; - DynamicFilter = false; - - C[1] = C[2] = C[3] = C[4] = C[5] = C[6] = 0.0; - for (int i=1; i<7; i++) - { - PropertySign[i] = 1.0; - PropertyNode[i] = 0L; - ReadFilterCoefficients(element, i); - } + Trigger = 0; + DynamicFilter = false; - if (Type == "LAG_FILTER") FilterType = eLag ; - else if (Type == "LEAD_LAG_FILTER") FilterType = eLeadLag ; - else if (Type == "SECOND_ORDER_FILTER") FilterType = eOrder2 ; - else if (Type == "WASHOUT_FILTER") FilterType = eWashout ; - else if (Type == "INTEGRATOR") FilterType = eIntegrator ; - else FilterType = eUnknown ; + C[1] = C[2] = C[3] = C[4] = C[5] = C[6] = 0.0; + for (int i=1; i<7; i++) { + PropertySign[i] = 1.0; + PropertyNode[i] = 0L; + ReadFilterCoefficients(element, i); + } - if (element->FindElement("trigger")) - { - Trigger = PropertyManager->GetNode(element->FindElementValue("trigger")); - } + if (Type == "LAG_FILTER") FilterType = eLag ; + else if (Type == "LEAD_LAG_FILTER") FilterType = eLeadLag ; + else if (Type == "SECOND_ORDER_FILTER") FilterType = eOrder2 ; + else if (Type == "WASHOUT_FILTER") FilterType = eWashout ; + else if (Type == "INTEGRATOR") FilterType = eIntegrator ; + else FilterType = eUnknown ; - Initialize = true; + if (element->FindElement("trigger")) { + Trigger = PropertyManager->GetNode(element->FindElementValue("trigger")); + } - CalculateDynamicFilters(); + Initialize = true; - FGFCSComponent::bind(); + CalculateDynamicFilters(); - Debug(0); + FGFCSComponent::bind(); + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGFilter::~FGFilter() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFilter::ReadFilterCoefficients(Element* element, int index) { - // index is known to be 1-7. - // A stringstream would be overkill, but also trying to avoid sprintf - string coefficient = "c0"; - coefficient[1] += index; - - if ( element->FindElement(coefficient) ) - { - string property_string = element->FindElementValue(coefficient); - if (!is_number(property_string)) // property - { - if (property_string[0] == '-') - { - PropertySign[index] = -1.0; - property_string.erase(0,1); - } - else - { - PropertySign[index] = 1.0; - } - PropertyNode[index] = PropertyManager->GetNode(property_string); - DynamicFilter = true; - } - else - { - C[index] = element->FindElementValueAsNumber(coefficient); - } + // index is known to be 1-7. + // A stringstream would be overkill, but also trying to avoid sprintf + string coefficient = "c0"; + coefficient[1] += index; + + if ( element->FindElement(coefficient) ) { + string property_string = element->FindElementValue(coefficient); + if (!is_number(property_string)) { // property + if (property_string[0] == '-') { + PropertySign[index] = -1.0; + property_string.erase(0,1); + } else { + PropertySign[index] = 1.0; + } + PropertyNode[index] = PropertyManager->GetNode(property_string); + DynamicFilter = true; + } else { + C[index] = element->FindElementValueAsNumber(coefficient); } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGFilter::CalculateDynamicFilters(void) { - double denom; + double denom; - switch (FilterType) - { + switch (FilterType) { case eLag: - if (PropertyNode[1] != 0L) C[1] = PropertyNode[1]->getDoubleValue()*PropertySign[1]; - denom = 2.00 + dt*C[1]; - ca = dt*C[1] / denom; - cb = (2.00 - dt*C[1]) / denom; + if (PropertyNode[1] != 0L) C[1] = PropertyNode[1]->getDoubleValue()*PropertySign[1]; + denom = 2.00 + dt*C[1]; + ca = dt*C[1] / denom; + cb = (2.00 - dt*C[1]) / denom; - break; + break; case eLeadLag: - if (PropertyNode[1] != 0L) C[1] = PropertyNode[1]->getDoubleValue()*PropertySign[1]; - if (PropertyNode[2] != 0L) C[2] = PropertyNode[2]->getDoubleValue()*PropertySign[2]; - if (PropertyNode[3] != 0L) C[3] = PropertyNode[3]->getDoubleValue()*PropertySign[3]; - if (PropertyNode[4] != 0L) C[4] = PropertyNode[4]->getDoubleValue()*PropertySign[4]; - denom = 2.00*C[3] + dt*C[4]; - ca = (2.00*C[1] + dt*C[2]) / denom; - cb = (dt*C[2] - 2.00*C[1]) / denom; - cc = (2.00*C[3] - dt*C[4]) / denom; - break; + if (PropertyNode[1] != 0L) C[1] = PropertyNode[1]->getDoubleValue()*PropertySign[1]; + if (PropertyNode[2] != 0L) C[2] = PropertyNode[2]->getDoubleValue()*PropertySign[2]; + if (PropertyNode[3] != 0L) C[3] = PropertyNode[3]->getDoubleValue()*PropertySign[3]; + if (PropertyNode[4] != 0L) C[4] = PropertyNode[4]->getDoubleValue()*PropertySign[4]; + denom = 2.00*C[3] + dt*C[4]; + ca = (2.00*C[1] + dt*C[2]) / denom; + cb = (dt*C[2] - 2.00*C[1]) / denom; + cc = (2.00*C[3] - dt*C[4]) / denom; + break; case eOrder2: - if (PropertyNode[1] != 0L) C[1] = PropertyNode[1]->getDoubleValue()*PropertySign[1]; - if (PropertyNode[2] != 0L) C[2] = PropertyNode[2]->getDoubleValue()*PropertySign[2]; - if (PropertyNode[3] != 0L) C[3] = PropertyNode[3]->getDoubleValue()*PropertySign[3]; - if (PropertyNode[4] != 0L) C[4] = PropertyNode[4]->getDoubleValue()*PropertySign[4]; - if (PropertyNode[5] != 0L) C[5] = PropertyNode[5]->getDoubleValue()*PropertySign[5]; - if (PropertyNode[6] != 0L) C[6] = PropertyNode[6]->getDoubleValue()*PropertySign[6]; - denom = 4.0*C[4] + 2.0*C[5]*dt + C[6]*dt*dt; - ca = (4.0*C[1] + 2.0*C[2]*dt + C[3]*dt*dt) / denom; - cb = (2.0*C[3]*dt*dt - 8.0*C[1]) / denom; - cc = (4.0*C[1] - 2.0*C[2]*dt + C[3]*dt*dt) / denom; - cd = (2.0*C[6]*dt*dt - 8.0*C[4]) / denom; - ce = (4.0*C[4] - 2.0*C[5]*dt + C[6]*dt*dt) / denom; - break; + if (PropertyNode[1] != 0L) C[1] = PropertyNode[1]->getDoubleValue()*PropertySign[1]; + if (PropertyNode[2] != 0L) C[2] = PropertyNode[2]->getDoubleValue()*PropertySign[2]; + if (PropertyNode[3] != 0L) C[3] = PropertyNode[3]->getDoubleValue()*PropertySign[3]; + if (PropertyNode[4] != 0L) C[4] = PropertyNode[4]->getDoubleValue()*PropertySign[4]; + if (PropertyNode[5] != 0L) C[5] = PropertyNode[5]->getDoubleValue()*PropertySign[5]; + if (PropertyNode[6] != 0L) C[6] = PropertyNode[6]->getDoubleValue()*PropertySign[6]; + denom = 4.0*C[4] + 2.0*C[5]*dt + C[6]*dt*dt; + ca = (4.0*C[1] + 2.0*C[2]*dt + C[3]*dt*dt) / denom; + cb = (2.0*C[3]*dt*dt - 8.0*C[1]) / denom; + cc = (4.0*C[1] - 2.0*C[2]*dt + C[3]*dt*dt) / denom; + cd = (2.0*C[6]*dt*dt - 8.0*C[4]) / denom; + ce = (4.0*C[4] - 2.0*C[5]*dt + C[6]*dt*dt) / denom; + break; case eWashout: - if (PropertyNode[1] != 0L) C[1] = PropertyNode[1]->getDoubleValue()*PropertySign[1]; - denom = 2.00 + dt*C[1]; - ca = 2.00 / denom; - cb = (2.00 - dt*C[1]) / denom; - break; + if (PropertyNode[1] != 0L) C[1] = PropertyNode[1]->getDoubleValue()*PropertySign[1]; + denom = 2.00 + dt*C[1]; + ca = 2.00 / denom; + cb = (2.00 - dt*C[1]) / denom; + break; case eIntegrator: - if (PropertyNode[1] != 0L) C[1] = PropertyNode[1]->getDoubleValue()*PropertySign[1]; - ca = dt*C[1] / 2.00; - break; + if (PropertyNode[1] != 0L) C[1] = PropertyNode[1]->getDoubleValue()*PropertySign[1]; + ca = dt*C[1] / 2.00; + break; case eUnknown: - cerr << "Unknown filter type" << endl; - break; - } + cerr << "Unknown filter type" << endl; + break; + } } @@ -190,63 +179,57 @@ void FGFilter::CalculateDynamicFilters(void) bool FGFilter::Run(void) { - double test = 0.0; - - if (Initialize) - { + double test = 0.0; - PreviousOutput1 = PreviousInput1 = Output = Input; - Initialize = false; + if (Initialize) { - } - else - { - - Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + PreviousOutput1 = PreviousInput1 = Output = Input; + Initialize = false; - if (DynamicFilter) CalculateDynamicFilters(); + } else { - switch (FilterType) - { - case eLag: - Output = Input * ca + PreviousInput1 * ca + PreviousOutput1 * cb; - break; - case eLeadLag: - Output = Input * ca + PreviousInput1 * cb + PreviousOutput1 * cc; - break; - case eOrder2: - Output = Input * ca + PreviousInput1 * cb + PreviousInput2 * cc - - PreviousOutput1 * cd - PreviousOutput2 * ce; - break; - case eWashout: - Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb; - break; - case eIntegrator: - if (Trigger != 0) - { - test = Trigger->getDoubleValue(); - if (fabs(test) > 0.000001) - { - Input = PreviousInput1 = PreviousInput2 = 0.0; - } - } - Output = Input * ca + PreviousInput1 * ca + PreviousOutput1; - break; - case eUnknown: - break; + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + + if (DynamicFilter) CalculateDynamicFilters(); + + switch (FilterType) { + case eLag: + Output = Input * ca + PreviousInput1 * ca + PreviousOutput1 * cb; + break; + case eLeadLag: + Output = Input * ca + PreviousInput1 * cb + PreviousOutput1 * cc; + break; + case eOrder2: + Output = Input * ca + PreviousInput1 * cb + PreviousInput2 * cc + - PreviousOutput1 * cd - PreviousOutput2 * ce; + break; + case eWashout: + Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb; + break; + case eIntegrator: + if (Trigger != 0) { + test = Trigger->getDoubleValue(); + if (fabs(test) > 0.000001) { + Input = PreviousInput1 = PreviousInput2 = 0.0; + } } - + Output = Input * ca + PreviousInput1 * ca + PreviousOutput1; + break; + case eUnknown: + break; } - PreviousOutput2 = PreviousOutput1; - PreviousOutput1 = Output; - PreviousInput2 = PreviousInput1; - PreviousInput1 = Input; + } + + PreviousOutput2 = PreviousOutput1; + PreviousOutput1 = Output; + PreviousInput2 = PreviousInput1; + PreviousInput1 = Input; - Clip(); - if (IsOutput) SetOutput(); + Clip(); + if (IsOutput) SetOutput(); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -270,110 +253,100 @@ bool FGFilter::Run(void) void FGFilter::Debug(int from) { - string sgn=""; - - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " INPUT: " << InputNodes[0]->getName() << endl; - switch (FilterType) - { - case eLag: - if (PropertySign[1] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl; - else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl; - break; - case eLeadLag: - if (PropertySign[1] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl; - else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl; - if (PropertySign[2] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[2] == 0L) cout << " C[2]: " << C[2] << endl; - else cout << " C[2] is the value of property: " << sgn << PropertyNode[2]->GetName() << endl; - if (PropertySign[3] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[3] == 0L) cout << " C[3]: " << C[3] << endl; - else cout << " C[3] is the value of property: " << sgn << PropertyNode[3]->GetName() << endl; - if (PropertySign[4] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[4] == 0L) cout << " C[4]: " << C[4] << endl; - else cout << " C[4] is the value of property: " << sgn << PropertyNode[4]->GetName() << endl; - break; - case eOrder2: - if (PropertySign[1] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl; - else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl; - if (PropertySign[2] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[2] == 0L) cout << " C[2]: " << C[2] << endl; - else cout << " C[2] is the value of property: " << sgn << PropertyNode[2]->GetName() << endl; - if (PropertySign[3] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[3] == 0L) cout << " C[3]: " << C[3] << endl; - else cout << " C[3] is the value of property: " << sgn << PropertyNode[3]->GetName() << endl; - if (PropertySign[4] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[4] == 0L) cout << " C[4]: " << C[4] << endl; - else cout << " C[4] is the value of property: " << sgn << PropertyNode[4]->GetName() << endl; - if (PropertySign[5] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[5] == 0L) cout << " C[5]: " << C[5] << endl; - else cout << " C[5] is the value of property: " << sgn << PropertyNode[5]->GetName() << endl; - if (PropertySign[6] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[6] == 0L) cout << " C[6]: " << C[6] << endl; - else cout << " C[6] is the value of property: " << sgn << PropertyNode[6]->GetName() << endl; - break; - case eWashout: - if (PropertySign[1] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl; - else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl; - break; - case eIntegrator: - if (PropertySign[1] < 0.0) sgn="-"; - else sgn = ""; - if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl; - else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl; - break; - case eUnknown: - break; - } - if (IsOutput) - { - for (unsigned int i=0; i<OutputNodes.size(); i++) - cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; - } - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGFilter" << endl; - if (from == 1) cout << "Destroyed: FGFilter" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + string sgn=""; + + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " INPUT: " << InputNames[0] << endl; + switch (FilterType) { + case eLag: + if (PropertySign[1] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl; + else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl; + break; + case eLeadLag: + if (PropertySign[1] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl; + else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl; + if (PropertySign[2] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[2] == 0L) cout << " C[2]: " << C[2] << endl; + else cout << " C[2] is the value of property: " << sgn << PropertyNode[2]->GetName() << endl; + if (PropertySign[3] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[3] == 0L) cout << " C[3]: " << C[3] << endl; + else cout << " C[3] is the value of property: " << sgn << PropertyNode[3]->GetName() << endl; + if (PropertySign[4] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[4] == 0L) cout << " C[4]: " << C[4] << endl; + else cout << " C[4] is the value of property: " << sgn << PropertyNode[4]->GetName() << endl; + break; + case eOrder2: + if (PropertySign[1] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl; + else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl; + if (PropertySign[2] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[2] == 0L) cout << " C[2]: " << C[2] << endl; + else cout << " C[2] is the value of property: " << sgn << PropertyNode[2]->GetName() << endl; + if (PropertySign[3] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[3] == 0L) cout << " C[3]: " << C[3] << endl; + else cout << " C[3] is the value of property: " << sgn << PropertyNode[3]->GetName() << endl; + if (PropertySign[4] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[4] == 0L) cout << " C[4]: " << C[4] << endl; + else cout << " C[4] is the value of property: " << sgn << PropertyNode[4]->GetName() << endl; + if (PropertySign[5] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[5] == 0L) cout << " C[5]: " << C[5] << endl; + else cout << " C[5] is the value of property: " << sgn << PropertyNode[5]->GetName() << endl; + if (PropertySign[6] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[6] == 0L) cout << " C[6]: " << C[6] << endl; + else cout << " C[6] is the value of property: " << sgn << PropertyNode[6]->GetName() << endl; + break; + case eWashout: + if (PropertySign[1] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl; + else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl; + break; + case eIntegrator: + if (PropertySign[1] < 0.0) sgn="-"; + else sgn = ""; + if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl; + else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl; + break; + case eUnknown: + break; + } + if (IsOutput) { + for (unsigned int i=0; i<OutputNodes.size(); i++) + cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; + } } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGFilter" << endl; + if (from == 1) cout << "Destroyed: FGFilter" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGFilter.h b/src/models/flight_control/FGFilter.h index f7784433b80fce4e1341a8549e48948a2cf91632..efb03541cef6cd4f63575456105a6a01ec68aa73 100644 --- a/src/models/flight_control/FGFilter.h +++ b/src/models/flight_control/FGFilter.h @@ -49,8 +49,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class Element; class FGPropertyManager; @@ -240,40 +239,36 @@ CLASS DECLARATION class FGFilter : public FGFCSComponent { public: - FGFilter(FGFCS* fcs, Element* element); - ~FGFilter(); - - bool Run (void); + FGFilter(FGFCS* fcs, Element* element); + ~FGFilter(); - /** When true, causes previous values to be set to current values. This - is particularly useful for first pass. */ - bool Initialize; - void ResetPastStates(void) - { - Input = 0.0; - Initialize = true; - } + bool Run (void); - enum {eLag, eLeadLag, eOrder2, eWashout, eIntegrator, eUnknown} FilterType; + /** When true, causes previous values to be set to current values. This + is particularly useful for first pass. */ + bool Initialize; + void ResetPastStates(void) {Input = 0.0; Initialize = true;} + + enum {eLag, eLeadLag, eOrder2, eWashout, eIntegrator, eUnknown} FilterType; private: - double ca; - double cb; - double cc; - double cd; - double ce; - double C[7]; // There are 6 coefficients, indexing is "1" based. - double PropertySign[7]; - double PreviousInput1; - double PreviousInput2; - double PreviousOutput1; - double PreviousOutput2; - FGPropertyManager* Trigger; - FGPropertyManager* PropertyNode[7]; - void CalculateDynamicFilters(void); - void ReadFilterCoefficients(Element* el, int index); - bool DynamicFilter; - void Debug(int from); + double ca; + double cb; + double cc; + double cd; + double ce; + double C[7]; // There are 6 coefficients, indexing is "1" based. + double PropertySign[7]; + double PreviousInput1; + double PreviousInput2; + double PreviousOutput1; + double PreviousOutput2; + FGPropertyManager* Trigger; + FGPropertyManager* PropertyNode[7]; + void CalculateDynamicFilters(void); + void ReadFilterCoefficients(Element* el, int index); + bool DynamicFilter; + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGGain.cpp b/src/models/flight_control/FGGain.cpp index 978f63c83aa66a5527828b60cb4cc741c2a8a5a1..b7944bd6e2bd34b0695acd51f1c3abcbece4a81f 100644 --- a/src/models/flight_control/FGGain.cpp +++ b/src/models/flight_control/FGGain.cpp @@ -45,10 +45,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGGain.cpp,v 1.20 2009/10/24 22:59:30 jberndt Exp $"; +static const char *IdSrc = "$Id: FGGain.cpp,v 1.22 2010/08/24 10:37:17 jberndt Exp $"; static const char *IdHdr = ID_GAIN; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -57,161 +56,131 @@ CLASS IMPLEMENTATION FGGain::FGGain(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - Element *scale_element, *zero_centered; - string strScheduledBy, gain_string, sZeroCentered; - - GainPropertyNode = 0; - GainPropertySign = 1.0; - Gain = 1.000; - Rows = 0; - Table = 0; - InMin = -1.0; - InMax = 1.0; - OutMin = OutMax = 0.0; - - if (Type == "PURE_GAIN") - { - if ( !element->FindElement("gain") ) - { - cout << highint << " No GAIN specified (default: 1.0)" << normint << endl; - } + Element *scale_element, *zero_centered; + string strScheduledBy, gain_string, sZeroCentered; + + GainPropertyNode = 0; + GainPropertySign = 1.0; + Gain = 1.000; + Rows = 0; + Table = 0; + InMin = -1.0; + InMax = 1.0; + OutMin = OutMax = 0.0; + + if (Type == "PURE_GAIN") { + if ( !element->FindElement("gain") ) { + cerr << highint << " No GAIN specified (default: 1.0)" << normint << endl; } - - if ( element->FindElement("gain") ) - { - gain_string = element->FindElementValue("gain"); - if (!is_number(gain_string)) // property - { - if (gain_string[0] == '-') - { - GainPropertySign = -1.0; - gain_string.erase(0,1); - } - GainPropertyNode = PropertyManager->GetNode(gain_string); - } - else - { - Gain = element->FindElementValueAsNumber("gain"); - } + } + + if ( element->FindElement("gain") ) { + gain_string = element->FindElementValue("gain"); + if (!is_number(gain_string)) { // property + if (gain_string[0] == '-') { + GainPropertySign = -1.0; + gain_string.erase(0,1); + } + GainPropertyNode = PropertyManager->GetNode(gain_string); + } else { + Gain = element->FindElementValueAsNumber("gain"); } - - if (Type == "AEROSURFACE_SCALE") - { - scale_element = element->FindElement("domain"); - if (scale_element) - { - if (scale_element->FindElement("max") && scale_element->FindElement("min") ) - { - InMax = scale_element->FindElementValueAsNumber("max"); - InMin = scale_element->FindElementValueAsNumber("min"); - } - } - scale_element = element->FindElement("range"); - if (!scale_element) throw(string("No range supplied for aerosurface scale component")); - if (scale_element->FindElement("max") && scale_element->FindElement("min") ) - { - OutMax = scale_element->FindElementValueAsNumber("max"); - OutMin = scale_element->FindElementValueAsNumber("min"); - } - else - { - cerr << "Maximum and minimum output values must be supplied for the " - "aerosurface scale component" << endl; - exit(-1); - } - ZeroCentered = true; - zero_centered = element->FindElement("zero_centered"); - //ToDo if zero centered, then mins must be <0 and max's must be >0 - if (zero_centered) - { - sZeroCentered = element->FindElementValue("zero_centered"); - if (sZeroCentered == string("0") || sZeroCentered == string("false")) - { - ZeroCentered = false; - } - } + } + + if (Type == "AEROSURFACE_SCALE") { + scale_element = element->FindElement("domain"); + if (scale_element) { + if (scale_element->FindElement("max") && scale_element->FindElement("min") ) + { + InMax = scale_element->FindElementValueAsNumber("max"); + InMin = scale_element->FindElementValueAsNumber("min"); + } } - - if (Type == "SCHEDULED_GAIN") + scale_element = element->FindElement("range"); + if (!scale_element) throw(string("No range supplied for aerosurface scale component")); + if (scale_element->FindElement("max") && scale_element->FindElement("min") ) { - if (element->FindElement("table")) - { - Table = new FGTable(PropertyManager, element->FindElement("table")); - } - else - { - cerr << "A table must be provided for the scheduled gain component" << endl; - exit(-1); - } + OutMax = scale_element->FindElementValueAsNumber("max"); + OutMin = scale_element->FindElementValueAsNumber("min"); + } else { + cerr << "Maximum and minimum output values must be supplied for the " + "aerosurface scale component" << endl; + exit(-1); } + ZeroCentered = true; + zero_centered = element->FindElement("zero_centered"); + //ToDo if zero centered, then mins must be <0 and max's must be >0 + if (zero_centered) { + sZeroCentered = element->FindElementValue("zero_centered"); + if (sZeroCentered == string("0") || sZeroCentered == string("false")) { + ZeroCentered = false; + } + } + } + + if (Type == "SCHEDULED_GAIN") { + if (element->FindElement("table")) { + Table = new FGTable(PropertyManager, element->FindElement("table")); + } else { + cerr << "A table must be provided for the scheduled gain component" << endl; + exit(-1); + } + } - FGFCSComponent::bind(); + FGFCSComponent::bind(); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGGain::~FGGain() { - delete Table; + delete Table; - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGGain::Run(void ) { - double SchedGain = 1.0; + double SchedGain = 1.0; - Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; - if (GainPropertyNode != 0) Gain = GainPropertyNode->getDoubleValue() * GainPropertySign; + if (GainPropertyNode != 0) Gain = GainPropertyNode->getDoubleValue() * GainPropertySign; - if (Type == "PURE_GAIN") // PURE_GAIN - { + if (Type == "PURE_GAIN") { // PURE_GAIN - Output = Gain * Input; + Output = Gain * Input; - } - else if (Type == "SCHEDULED_GAIN") // SCHEDULED_GAIN - { + } else if (Type == "SCHEDULED_GAIN") { // SCHEDULED_GAIN - SchedGain = Table->GetValue(); - Output = Gain * SchedGain * Input; + SchedGain = Table->GetValue(); + Output = Gain * SchedGain * Input; - } - else if (Type == "AEROSURFACE_SCALE") // AEROSURFACE_SCALE - { + } else if (Type == "AEROSURFACE_SCALE") { // AEROSURFACE_SCALE - if (ZeroCentered) - { - if (Input == 0.0) - { - Output = 0.0; - } - else if (Input > 0) - { - Output = (Input / InMax) * OutMax; - } - else - { - Output = (Input / InMin) * OutMin; - } - } - else - { - Output = OutMin + ((Input - InMin) / (InMax - InMin)) * (OutMax - OutMin); - } - - Output *= Gain; + if (ZeroCentered) { + if (Input == 0.0) { + Output = 0.0; + } else if (Input > 0) { + Output = (Input / InMax) * OutMax; + } else { + Output = (Input / InMin) * OutMin; + } + } else { + Output = OutMin + ((Input - InMin) / (InMax - InMin)) * (OutMax - OutMin); } - Clip(); - if (IsOutput) SetOutput(); + Output *= Gain; + } + + Clip(); + if (IsOutput) SetOutput(); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -235,66 +204,52 @@ bool FGGain::Run(void ) void FGGain::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - if (InputSigns[0] < 0) - cout << " INPUT: -" << InputNodes[0]->getName() << endl; - else - cout << " INPUT: " << InputNodes[0]->getName() << endl; - - if (GainPropertyNode != 0) - { - cout << " GAIN: " << GainPropertyNode->GetName() << endl; - } - else - { - cout << " GAIN: " << Gain << endl; - } - if (IsOutput) - { - for (unsigned int i=0; i<OutputNodes.size(); i++) - cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; - } - if (Type == "AEROSURFACE_SCALE") - { - cout << " In/Out Mapping:" << endl; - cout << " Input MIN: " << InMin << endl; - cout << " Input MAX: " << InMax << endl; - cout << " Output MIN: " << OutMin << endl; - cout << " Output MAX: " << OutMax << endl; - } - if (Table != 0) - { - cout << " Scheduled by table: " << endl; - Table->Print(); - } - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + if (InputSigns[0] < 0) + cout << " INPUT: -" << InputNames[0] << endl; + else + cout << " INPUT: " << InputNames[0] << endl; + + if (GainPropertyNode != 0) { + cout << " GAIN: " << GainPropertyNode->GetName() << endl; + } else { + cout << " GAIN: " << Gain << endl; + } + if (IsOutput) { + for (unsigned int i=0; i<OutputNodes.size(); i++) + cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; + } + if (Type == "AEROSURFACE_SCALE") { + cout << " In/Out Mapping:" << endl; + cout << " Input MIN: " << InMin << endl; + cout << " Input MAX: " << InMax << endl; + cout << " Output MIN: " << OutMin << endl; + cout << " Output MAX: " << OutMax << endl; + } + if (Table != 0) { + cout << " Scheduled by table: " << endl; + Table->Print(); + } } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGGain" << endl; - if (from == 1) cout << "Destroyed: FGGain" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGGain" << endl; + if (from == 1) cout << "Destroyed: FGGain" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGGain.h b/src/models/flight_control/FGGain.h index 7476ef6f9bea358b4003825351659f292184b2cd..5383cab20908080e5a540a9e7725bbf34ecdd666 100644 --- a/src/models/flight_control/FGGain.h +++ b/src/models/flight_control/FGGain.h @@ -50,8 +50,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFCS; class Element; @@ -219,21 +218,21 @@ CLASS DECLARATION class FGGain : public FGFCSComponent { public: - FGGain(FGFCS* fcs, Element* element); - ~FGGain(); + FGGain(FGFCS* fcs, Element* element); + ~FGGain(); - bool Run (void); + bool Run (void); private: - FGTable* Table; - FGPropertyManager* GainPropertyNode; - double GainPropertySign; - double Gain; - double InMin, InMax, OutMin, OutMax; - int Rows; - bool ZeroCentered; - - void Debug(int from); + FGTable* Table; + FGPropertyManager* GainPropertyNode; + double GainPropertySign; + double Gain; + double InMin, InMax, OutMin, OutMax; + int Rows; + bool ZeroCentered; + + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGGradient.cpp b/src/models/flight_control/FGGradient.cpp index 5a7f4f736bafcbc1e4dd34733e48fe195393bc13..9046e4975b00ea1f4a9143990a803f71084d75b9 100644 --- a/src/models/flight_control/FGGradient.cpp +++ b/src/models/flight_control/FGGradient.cpp @@ -42,8 +42,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGGradient.cpp,v 1.4 2009/10/24 22:59:30 jberndt Exp $"; static const char *IdHdr = ID_GRADIENT; @@ -55,23 +54,23 @@ CLASS IMPLEMENTATION FGGradient::FGGradient(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - FGFCSComponent::bind(); + FGFCSComponent::bind(); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGGradient::~FGGradient() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGGradient::Run(void ) { - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -95,36 +94,28 @@ bool FGGradient::Run(void ) void FGGradient::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGGradient" << endl; - if (from == 1) cout << "Destroyed: FGGradient" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGGradient" << endl; + if (from == 1) cout << "Destroyed: FGGradient" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGGradient.h b/src/models/flight_control/FGGradient.h index e8641251350ca142c8f972d5047c2bf803e09d85..06d3e843f936a57abb471b151280d260a0a1233d 100644 --- a/src/models/flight_control/FGGradient.h +++ b/src/models/flight_control/FGGradient.h @@ -1,8 +1,8 @@ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Header: FGGradient.h - Author: - Date started: + Author: + Date started: ------------- Copyright (C) ------------- @@ -50,8 +50,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFCS; @@ -69,13 +68,13 @@ CLASS DECLARATION class FGGradient : public FGFCSComponent { public: - FGGradient(FGFCS* fcs, Element* element); - ~FGGradient(); + FGGradient(FGFCS* fcs, Element* element); + ~FGGradient(); - bool Run (void); + bool Run (void); private: - void Debug(int from); + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGGyro.cpp b/src/models/flight_control/FGGyro.cpp old mode 100644 new mode 100755 index d64907af3f02098811aa9e7a0de6d4f45120ec9d..dffb3c9da3d017a531a80f24c695fdeb8971b69f --- a/src/models/flight_control/FGGyro.cpp +++ b/src/models/flight_control/FGGyro.cpp @@ -42,8 +42,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGGyro.cpp,v 1.5 2009/10/24 22:59:30 jberndt Exp $"; static const char *IdHdr = ID_GYRO; @@ -53,34 +52,34 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGGyro::FGGyro(FGFCS* fcs, Element* element) : FGSensor(fcs, element), - FGSensorOrientation(element) + FGSensorOrientation(element) { - Propagate = fcs->GetExec()->GetPropagate(); - - Debug(0); + Propagate = fcs->GetExec()->GetPropagate(); + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGGyro::~FGGyro() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGGyro::Run(void ) { - // There is no input assumed. This is a dedicated angular acceleration sensor. + // There is no input assumed. This is a dedicated angular acceleration sensor. + + //aircraft rates + vAccel = mT * Propagate->GetPQRdot(); - //aircraft rates - vAccel = mT * Propagate->GetPQRdot(); + Input = vAccel(axis); - Input = vAccel(axis); + ProcessSensorSignal(); - ProcessSensorSignal(); - - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -104,38 +103,30 @@ bool FGGyro::Run(void ) void FGGyro::Debug(int from) { - string ax[4] = {"none", "X", "Y", "Z"}; + string ax[4] = {"none", "X", "Y", "Z"}; - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " Axis: " << ax[axis] << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGGyro" << endl; - if (from == 1) cout << "Destroyed: FGGyro" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " Axis: " << ax[axis] << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGGyro" << endl; + if (from == 1) cout << "Destroyed: FGGyro" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGGyro.h b/src/models/flight_control/FGGyro.h old mode 100644 new mode 100755 index 6aa8cae41364b934448091bf2fa2c71c972fc7ca..2dcc9fb215930ee2ec57e9b991846e92eedb3509 --- a/src/models/flight_control/FGGyro.h +++ b/src/models/flight_control/FGGyro.h @@ -56,8 +56,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFCS; @@ -117,17 +116,17 @@ CLASS DECLARATION class FGGyro : public FGSensor, public FGSensorOrientation { public: - FGGyro(FGFCS* fcs, Element* element); - ~FGGyro(); + FGGyro(FGFCS* fcs, Element* element); + ~FGGyro(); - bool Run (void); + bool Run (void); private: - FGPropagate* Propagate; - FGColumnVector3 vAccel; - void CalculateTransformMatrix(void); - - void Debug(int from); + FGPropagate* Propagate; + FGColumnVector3 vAccel; + void CalculateTransformMatrix(void); + + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGKinemat.cpp b/src/models/flight_control/FGKinemat.cpp index 9e8031c93a1b951e706b93a8be9ba02be1878831..dc81ed1e4adf43763f6d1cc6c10cc24684012f8e 100644 --- a/src/models/flight_control/FGKinemat.cpp +++ b/src/models/flight_control/FGKinemat.cpp @@ -44,10 +44,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGKinemat.cpp,v 1.10 2009/10/24 22:59:30 jberndt Exp $"; +static const char *IdSrc = "$Id: FGKinemat.cpp,v 1.11 2010/08/21 22:56:11 jberndt Exp $"; static const char *IdHdr = ID_FLAPS; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -56,120 +55,112 @@ CLASS IMPLEMENTATION FGKinemat::FGKinemat(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - Element *traverse_element, *setting_element; - double tmpDetent; - double tmpTime; - - Detents.clear(); - TransitionTimes.clear(); - - Output = OutputPct = 0; - DoScale = true; - - if (element->FindElement("noscale")) DoScale = false; - - traverse_element = element->FindElement("traverse"); - setting_element = traverse_element->FindElement("setting"); - while (setting_element) - { - tmpDetent = setting_element->FindElementValueAsNumber("position"); - tmpTime = setting_element->FindElementValueAsNumber("time"); - Detents.push_back(tmpDetent); - TransitionTimes.push_back(tmpTime); - setting_element = traverse_element->FindNextElement("setting"); - } - NumDetents = Detents.size(); - - if (NumDetents <= 1) - { - cerr << "Kinematic component " << Name - << " must have more than 1 setting element" << endl; - exit(-1); - } - - FGFCSComponent::bind(); + Element *traverse_element, *setting_element; + double tmpDetent; + double tmpTime; + + Detents.clear(); + TransitionTimes.clear(); + + Output = OutputPct = 0; + DoScale = true; + + if (element->FindElement("noscale")) DoScale = false; + + traverse_element = element->FindElement("traverse"); + setting_element = traverse_element->FindElement("setting"); + while (setting_element) { + tmpDetent = setting_element->FindElementValueAsNumber("position"); + tmpTime = setting_element->FindElementValueAsNumber("time"); + Detents.push_back(tmpDetent); + TransitionTimes.push_back(tmpTime); + setting_element = traverse_element->FindNextElement("setting"); + } + NumDetents = Detents.size(); + + if (NumDetents <= 1) { + cerr << "Kinematic component " << Name + << " must have more than 1 setting element" << endl; + exit(-1); + } + + FGFCSComponent::bind(); // treenode->Tie("output-norm", this, &FGKinemat::GetOutputPct ); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGKinemat::~FGKinemat() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGKinemat::Run(void ) { - double dt0 = dt; - - Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; - - if (DoScale) Input *= Detents[NumDetents-1]; - - if (IsOutput) Output = OutputNodes[0]->getDoubleValue(); - - if (Input < Detents[0]) - Input = Detents[0]; - else if (Detents[NumDetents-1] < Input) - Input = Detents[NumDetents-1]; - - // Process all detent intervals the movement traverses until either the - // final value is reached or the time interval has finished. - while ( dt0 > 0.0 && !EqualToRoundoff(Input, Output) ) - { - - // Find the area where Output is in - int ind; - for (ind = 1; (Input < Output) ? Detents[ind] < Output : Detents[ind] <= Output ; ++ind) - if (NumDetents <= ind) - break; - - // A transition time of 0.0 means an infinite rate. - // The output is reached in one step - if (TransitionTimes[ind] <= 0.0) - { - Output = Input; - break; - } + double dt0 = dt; + + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + + if (DoScale) Input *= Detents[NumDetents-1]; + + if (IsOutput) Output = OutputNodes[0]->getDoubleValue(); + + if (Input < Detents[0]) + Input = Detents[0]; + else if (Detents[NumDetents-1] < Input) + Input = Detents[NumDetents-1]; + + // Process all detent intervals the movement traverses until either the + // final value is reached or the time interval has finished. + while ( dt0 > 0.0 && !EqualToRoundoff(Input, Output) ) { + + // Find the area where Output is in + int ind; + for (ind = 1; (Input < Output) ? Detents[ind] < Output : Detents[ind] <= Output ; ++ind) + if (NumDetents <= ind) + break; + + // A transition time of 0.0 means an infinite rate. + // The output is reached in one step + if (TransitionTimes[ind] <= 0.0) { + Output = Input; + break; + } else { + // Compute the rate in this area + double Rate = (Detents[ind] - Detents[ind-1])/TransitionTimes[ind]; + // Compute the maximum input value inside this area + double ThisInput = Input; + if (ThisInput < Detents[ind-1]) ThisInput = Detents[ind-1]; + if (Detents[ind] < ThisInput) ThisInput = Detents[ind]; + // Compute the time to reach the value in ThisInput + double ThisDt = fabs((ThisInput-Output)/Rate); + + // and clip to the timestep size + if (dt0 < ThisDt) { + ThisDt = dt0; + if (Output < Input) + Output += ThisDt*Rate; else - { - // Compute the rate in this area - double Rate = (Detents[ind] - Detents[ind-1])/TransitionTimes[ind]; - // Compute the maximum input value inside this area - double ThisInput = Input; - if (ThisInput < Detents[ind-1]) ThisInput = Detents[ind-1]; - if (Detents[ind] < ThisInput) ThisInput = Detents[ind]; - // Compute the time to reach the value in ThisInput - double ThisDt = fabs((ThisInput-Output)/Rate); - - // and clip to the timestep size - if (dt0 < ThisDt) - { - ThisDt = dt0; - if (Output < Input) - Output += ThisDt*Rate; - else - Output -= ThisDt*Rate; - } - else - // Handle this case separate to make shure the termination condition - // is met even in inexact arithmetics ... - Output = ThisInput; - - dt0 -= ThisDt; - } + Output -= ThisDt*Rate; + } else + // Handle this case separate to make shure the termination condition + // is met even in inexact arithmetics ... + Output = ThisInput; + + dt0 -= ThisDt; } + } - OutputPct = (Output-Detents[0])/(Detents[NumDetents-1]-Detents[0]); + OutputPct = (Output-Detents[0])/(Detents[NumDetents-1]-Detents[0]); - Clip(); - if (IsOutput) SetOutput(); + Clip(); + if (IsOutput) SetOutput(); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -193,47 +184,37 @@ bool FGKinemat::Run(void ) void FGKinemat::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " INPUT: " << InputNodes[0]->getName() << endl; - cout << " DETENTS: " << NumDetents << endl; - for (int i=0;i<NumDetents;i++) - { - cout << " " << Detents[i] << " " << TransitionTimes[i] << endl; - } - if (IsOutput) - { - for (unsigned int i=0; i<OutputNodes.size(); i++) - cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; - } - if (!DoScale) cout << " NOSCALE" << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGKinemat" << endl; - if (from == 1) cout << "Destroyed: FGKinemat" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " INPUT: " << InputNames[0] << endl; + cout << " DETENTS: " << NumDetents << endl; + for (int i=0;i<NumDetents;i++) { + cout << " " << Detents[i] << " " << TransitionTimes[i] << endl; + } + if (IsOutput) { + for (unsigned int i=0; i<OutputNodes.size(); i++) + cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; + } + if (!DoScale) cout << " NOSCALE" << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGKinemat" << endl; + if (from == 1) cout << "Destroyed: FGKinemat" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGKinemat.h b/src/models/flight_control/FGKinemat.h index fc89e4979c9fef541d5c8889a8d0e36f2953d5cd..93ae1ce762c9abafe22c2466042a196e3c0a9206 100644 --- a/src/models/flight_control/FGKinemat.h +++ b/src/models/flight_control/FGKinemat.h @@ -50,8 +50,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -109,38 +108,34 @@ mechanization of a servo-actuator, there should be an output specified. CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGKinemat : public FGFCSComponent -{ +class FGKinemat : public FGFCSComponent { public: - /** Constructor. - @param fcs A reference to the current flight control system. - @param element reference to the current configuration file node. - */ - FGKinemat(FGFCS* fcs, Element* element); - - /// Destructor. - ~FGKinemat(); - - /** Kinematic component output value. - @return the current output of the kinematic object on the range of [0,1]. */ - double GetOutputPct() const - { - return OutputPct; - } - - /** Run method, overrides FGModel::Run(). - @return false on success, true on failure. - The routine doing the work. */ - bool Run (void); + /** Constructor. + @param fcs A reference to the current flight control system. + @param element reference to the current configuration file node. + */ + FGKinemat(FGFCS* fcs, Element* element); + + /// Destructor. + ~FGKinemat(); + + /** Kinematic component output value. + @return the current output of the kinematic object on the range of [0,1]. */ + double GetOutputPct() const { return OutputPct; } + + /** Run method, overrides FGModel::Run(). + @return false on success, true on failure. + The routine doing the work. */ + bool Run (void); private: - std::vector<double> Detents; - std::vector<double> TransitionTimes; - int NumDetents; - double OutputPct; - bool DoScale; + std::vector<double> Detents; + std::vector<double> TransitionTimes; + int NumDetents; + double OutputPct; + bool DoScale; - void Debug(int from); + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGMagnetometer.cpp b/src/models/flight_control/FGMagnetometer.cpp old mode 100644 new mode 100755 index ae93c02a6ec386137fb76a6e7bc7bda8a72d3fee..3c04e68fa508203cdca2c4980ae2246736b0c619 --- a/src/models/flight_control/FGMagnetometer.cpp +++ b/src/models/flight_control/FGMagnetometer.cpp @@ -45,8 +45,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGMagnetometer.cpp,v 1.5 2009/10/24 22:59:30 jberndt Exp $"; static const char *IdHdr = ID_MAGNETOMETER; @@ -57,90 +56,86 @@ CLASS IMPLEMENTATION FGMagnetometer::FGMagnetometer(FGFCS* fcs, Element* element) : FGSensor(fcs, element), - FGSensorOrientation(element), - counter(0), - INERTIAL_UPDATE_RATE(1000) + FGSensorOrientation(element), + counter(0), + INERTIAL_UPDATE_RATE(1000) { - Propagate = fcs->GetExec()->GetPropagate(); - MassBalance = fcs->GetExec()->GetMassBalance(); - Inertial = fcs->GetExec()->GetInertial(); - - Element* location_element = element->FindElement("location"); - if (location_element) vLocation = location_element->FindElementTripletConvertTo("IN"); - else - { - cerr << "No location given for magnetometer. " << endl; - exit(-1); - } - - vRadius = MassBalance->StructuralToBody(vLocation); - - //assuming date wont significantly change over a flight to affect mag field - //would be better to get the date from the sim if its simulated... - time_t rawtime; - time( &rawtime ); - tm * ptm = gmtime ( &rawtime ); - - int year = ptm->tm_year; - if (year>100) - { - year-= 100; - } - //the months here are zero based TODO find out if the function expects 1s based - date = (yymmdd_to_julian_days(ptm->tm_year,ptm->tm_mon,ptm->tm_mday));//Julian 1950-2049 yy,mm,dd - updateInertialMag(); - - Debug(0); + Propagate = fcs->GetExec()->GetPropagate(); + MassBalance = fcs->GetExec()->GetMassBalance(); + Inertial = fcs->GetExec()->GetInertial(); + + Element* location_element = element->FindElement("location"); + if (location_element) vLocation = location_element->FindElementTripletConvertTo("IN"); + else {cerr << "No location given for magnetometer. " << endl; exit(-1);} + + vRadius = MassBalance->StructuralToBody(vLocation); + + //assuming date wont significantly change over a flight to affect mag field + //would be better to get the date from the sim if its simulated... + time_t rawtime; + time( &rawtime ); + tm * ptm = gmtime ( &rawtime ); + + int year = ptm->tm_year; + if(year>100) + { + year-= 100; + } + //the months here are zero based TODO find out if the function expects 1s based + date = (yymmdd_to_julian_days(ptm->tm_year,ptm->tm_mon,ptm->tm_mday));//Julian 1950-2049 yy,mm,dd + updateInertialMag(); + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMagnetometer::~FGMagnetometer() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGMagnetometer::updateInertialMag(void) { - counter++; - if (counter > INERTIAL_UPDATE_RATE)//dont need to update every iteration - { - counter = 0; - - usedLat = (Propagate->GetGeodLatitudeRad());//radians, N and E lat and long are positive, S and W negative - usedLon = (Propagate->GetLongitude());//radians - usedAlt = (Propagate->GetGeodeticAltitude()*fttom*0.001);//km - - //this should be done whenever the position changes significantly (in nTesla) - calc_magvar( usedLat, - usedLon, - usedAlt, - date, - field ); - } + counter++; + if (counter > INERTIAL_UPDATE_RATE)//dont need to update every iteration + { + counter = 0; + + usedLat = (Propagate->GetGeodLatitudeRad());//radians, N and E lat and long are positive, S and W negative + usedLon = (Propagate->GetLongitude());//radians + usedAlt = (Propagate->GetGeodeticAltitude()*fttom*0.001);//km + + //this should be done whenever the position changes significantly (in nTesla) + calc_magvar( usedLat, + usedLon, + usedAlt, + date, + field ); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGMagnetometer::Run(void ) { - // There is no input assumed. This is a dedicated magnetic field sensor. - - vRadius = MassBalance->StructuralToBody(vLocation); + // There is no input assumed. This is a dedicated magnetic field sensor. + + vRadius = MassBalance->StructuralToBody(vLocation); - updateInertialMag(); + updateInertialMag(); - // Inertial magnetic field rotated to the body frame - vMag = Propagate->GetTl2b() * FGColumnVector3(field[3], field[4], field[5]); + // Inertial magnetic field rotated to the body frame + vMag = Propagate->GetTl2b() * FGColumnVector3(field[3], field[4], field[5]); - // Allow for sensor orientation - vMag = mT * vMag; + // Allow for sensor orientation + vMag = mT * vMag; + + Input = vMag(axis); - Input = vMag(axis); + ProcessSensorSignal(); - ProcessSensorSignal(); - - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -164,38 +159,30 @@ bool FGMagnetometer::Run(void ) void FGMagnetometer::Debug(int from) { - string ax[4] = {"none", "X", "Y", "Z"}; + string ax[4] = {"none", "X", "Y", "Z"}; - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " Axis: " << ax[axis] << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGMagnetometer" << endl; - if (from == 1) cout << "Destroyed: FGMagnetometer" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " Axis: " << ax[axis] << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGMagnetometer" << endl; + if (from == 1) cout << "Destroyed: FGMagnetometer" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGMagnetometer.h b/src/models/flight_control/FGMagnetometer.h old mode 100644 new mode 100755 index 62ea366537184235672c3838fb45f3480c34e647..c7a850ab31b5a3e1e404f88fa4f594f907d06e68 --- a/src/models/flight_control/FGMagnetometer.h +++ b/src/models/flight_control/FGMagnetometer.h @@ -56,8 +56,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFCS; @@ -129,28 +128,28 @@ CLASS DECLARATION class FGMagnetometer : public FGSensor, public FGSensorOrientation { public: - FGMagnetometer(FGFCS* fcs, Element* element); - ~FGMagnetometer(); + FGMagnetometer(FGFCS* fcs, Element* element); + ~FGMagnetometer(); - bool Run (void); + bool Run (void); private: - FGPropagate* Propagate; - FGMassBalance* MassBalance; - FGInertial* Inertial; - FGColumnVector3 vLocation; - FGColumnVector3 vRadius; - FGColumnVector3 vMag; - void updateInertialMag(void); - double field[6]; - double usedLat; - double usedLon; - double usedAlt; - unsigned long int date; - int counter; - int INERTIAL_UPDATE_RATE; - - void Debug(int from); + FGPropagate* Propagate; + FGMassBalance* MassBalance; + FGInertial* Inertial; + FGColumnVector3 vLocation; + FGColumnVector3 vRadius; + FGColumnVector3 vMag; + void updateInertialMag(void); + double field[6]; + double usedLat; + double usedLon; + double usedAlt; + unsigned long int date; + int counter; + int INERTIAL_UPDATE_RATE; + + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGPID.cpp b/src/models/flight_control/FGPID.cpp old mode 100644 new mode 100755 index d03a58f53c8a27d655c2f2c235e14d6d781458f8..7c50560e9fef6fb72356d535f033cf82555ef51d --- a/src/models/flight_control/FGPID.cpp +++ b/src/models/flight_control/FGPID.cpp @@ -42,10 +42,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGPID.cpp,v 1.16 2009/10/24 22:59:30 jberndt Exp $"; +static const char *IdSrc = "$Id: FGPID.cpp,v 1.17 2010/08/21 22:56:11 jberndt Exp $"; static const char *IdHdr = ID_PID; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -54,133 +53,114 @@ CLASS IMPLEMENTATION FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - string kp_string, ki_string, kd_string; - - Kp = Ki = Kd = 0.0; - KpPropertyNode = 0; - KiPropertyNode = 0; - KdPropertyNode = 0; - KpPropertySign = 1.0; - KiPropertySign = 1.0; - KdPropertySign = 1.0; - I_out_total = 0.0; - Input_prev = Input_prev2 = 0.0; - Trigger = 0; - - if ( element->FindElement("kp") ) - { - kp_string = element->FindElementValue("kp"); - if (!is_number(kp_string)) // property - { - if (kp_string[0] == '-') - { - KpPropertySign = -1.0; - kp_string.erase(0,1); - } - KpPropertyNode = PropertyManager->GetNode(kp_string); - } - else - { - Kp = element->FindElementValueAsNumber("kp"); - } + string kp_string, ki_string, kd_string; + + Kp = Ki = Kd = 0.0; + KpPropertyNode = 0; + KiPropertyNode = 0; + KdPropertyNode = 0; + KpPropertySign = 1.0; + KiPropertySign = 1.0; + KdPropertySign = 1.0; + I_out_total = 0.0; + Input_prev = Input_prev2 = 0.0; + Trigger = 0; + + if ( element->FindElement("kp") ) { + kp_string = element->FindElementValue("kp"); + if (!is_number(kp_string)) { // property + if (kp_string[0] == '-') { + KpPropertySign = -1.0; + kp_string.erase(0,1); + } + KpPropertyNode = PropertyManager->GetNode(kp_string); + } else { + Kp = element->FindElementValueAsNumber("kp"); } - - if ( element->FindElement("ki") ) - { - ki_string = element->FindElementValue("ki"); - if (!is_number(ki_string)) // property - { - if (ki_string[0] == '-') - { - KiPropertySign = -1.0; - ki_string.erase(0,1); - } - KiPropertyNode = PropertyManager->GetNode(ki_string); - } - else - { - Ki = element->FindElementValueAsNumber("ki"); - } + } + + if ( element->FindElement("ki") ) { + ki_string = element->FindElementValue("ki"); + if (!is_number(ki_string)) { // property + if (ki_string[0] == '-') { + KiPropertySign = -1.0; + ki_string.erase(0,1); + } + KiPropertyNode = PropertyManager->GetNode(ki_string); + } else { + Ki = element->FindElementValueAsNumber("ki"); } - - if ( element->FindElement("kd") ) - { - kd_string = element->FindElementValue("kd"); - if (!is_number(kd_string)) // property - { - if (kd_string[0] == '-') - { - KdPropertySign = -1.0; - kd_string.erase(0,1); - } - KdPropertyNode = PropertyManager->GetNode(kd_string); - } - else - { - Kd = element->FindElementValueAsNumber("kd"); - } + } + + if ( element->FindElement("kd") ) { + kd_string = element->FindElementValue("kd"); + if (!is_number(kd_string)) { // property + if (kd_string[0] == '-') { + KdPropertySign = -1.0; + kd_string.erase(0,1); + } + KdPropertyNode = PropertyManager->GetNode(kd_string); + } else { + Kd = element->FindElementValueAsNumber("kd"); } + } - if (element->FindElement("trigger")) - { - Trigger = PropertyManager->GetNode(element->FindElementValue("trigger")); - } + if (element->FindElement("trigger")) { + Trigger = PropertyManager->GetNode(element->FindElementValue("trigger")); + } - FGFCSComponent::bind(); + FGFCSComponent::bind(); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGPID::~FGPID() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGPID::Run(void ) { - double I_out_delta = 0.0; - double P_out, D_out; - - Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; - - if (KpPropertyNode != 0) Kp = KpPropertyNode->getDoubleValue() * KpPropertySign; - if (KiPropertyNode != 0) Ki = KiPropertyNode->getDoubleValue() * KiPropertySign; - if (KdPropertyNode != 0) Kd = KdPropertyNode->getDoubleValue() * KdPropertySign; - - P_out = Kp * Input; - D_out = (Kd / dt) * (Input - Input_prev); - - // Do not continue to integrate the input to the integrator if a wind-up - // condition is sensed - that is, if the property pointed to by the trigger - // element is non-zero. Reset the integrator to 0.0 if the Trigger value - // is negative. - - if (Trigger != 0) - { - double test = Trigger->getDoubleValue(); - if (fabs(test) < 0.000001) I_out_delta = Ki * dt * Input; // Normal - if (test < 0.0) I_out_total = 0.0; // Reset integrator to 0.0 - } - else // no anti-wind-up trigger defined - { - I_out_delta = Ki * dt * Input; - } - - I_out_total += I_out_delta; - - Output = P_out + I_out_total + D_out; - - Input_prev = Input; - Input_prev2 = Input_prev; - - Clip(); - if (IsOutput) SetOutput(); - - return true; + double I_out_delta = 0.0; + double P_out, D_out; + + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + + if (KpPropertyNode != 0) Kp = KpPropertyNode->getDoubleValue() * KpPropertySign; + if (KiPropertyNode != 0) Ki = KiPropertyNode->getDoubleValue() * KiPropertySign; + if (KdPropertyNode != 0) Kd = KdPropertyNode->getDoubleValue() * KdPropertySign; + + P_out = Kp * Input; + D_out = (Kd / dt) * (Input - Input_prev); + + // Do not continue to integrate the input to the integrator if a wind-up + // condition is sensed - that is, if the property pointed to by the trigger + // element is non-zero. Reset the integrator to 0.0 if the Trigger value + // is negative. + + if (Trigger != 0) { + double test = Trigger->getDoubleValue(); + if (fabs(test) < 0.000001) I_out_delta = Ki * dt * Input; // Normal + if (test < 0.0) I_out_total = 0.0; // Reset integrator to 0.0 + } else { // no anti-wind-up trigger defined + I_out_delta = Ki * dt * Input; + } + + I_out_total += I_out_delta; + + Output = P_out + I_out_total + D_out; + + Input_prev = Input; + Input_prev2 = Input_prev; + + Clip(); + if (IsOutput) SetOutput(); + + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -204,45 +184,36 @@ bool FGPID::Run(void ) void FGPID::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - if (InputSigns[0] < 0) - cout << " INPUT: -" << InputNodes[0]->getName() << endl; - else - cout << " INPUT: " << InputNodes[0]->getName() << endl; - - if (IsOutput) - { - for (unsigned int i=0; i<OutputNodes.size(); i++) - cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; - } - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGPID" << endl; - if (from == 1) cout << "Destroyed: FGPID" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + if (InputSigns[0] < 0) + cout << " INPUT: -" << InputNames[0] << endl; + else + cout << " INPUT: " << InputNames[0] << endl; + + if (IsOutput) { + for (unsigned int i=0; i<OutputNodes.size(); i++) + cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; + } } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGPID" << endl; + if (from == 1) cout << "Destroyed: FGPID" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGPID.h b/src/models/flight_control/FGPID.h old mode 100644 new mode 100755 index f8aaa20a9c4bb6e6a20c28f2a0134d091d0ab95b..a573dc3214a28c165b473daa9dbed00e4c22eba0 --- a/src/models/flight_control/FGPID.h +++ b/src/models/flight_control/FGPID.h @@ -50,8 +50,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFCS; class Element; @@ -94,28 +93,25 @@ CLASS DECLARATION class FGPID : public FGFCSComponent { public: - FGPID(FGFCS* fcs, Element* element); - ~FGPID(); + FGPID(FGFCS* fcs, Element* element); + ~FGPID(); - bool Run (void); - void ResetPastStates(void) - { - Input_prev = Input_prev2 = Output = I_out_total = 0.0; - } + bool Run (void); + void ResetPastStates(void) {Input_prev = Input_prev2 = Output = I_out_total = 0.0;} private: - FGPropertyManager *Trigger; - double Kp, Ki, Kd; - double I_out_total; - double Input_prev, Input_prev2; - double KpPropertySign; - double KiPropertySign; - double KdPropertySign; - FGPropertyManager* KpPropertyNode; - FGPropertyManager* KiPropertyNode; - FGPropertyManager* KdPropertyNode; - - void Debug(int from); + FGPropertyManager *Trigger; + double Kp, Ki, Kd; + double I_out_total; + double Input_prev, Input_prev2; + double KpPropertySign; + double KiPropertySign; + double KdPropertySign; + FGPropertyManager* KpPropertyNode; + FGPropertyManager* KiPropertyNode; + FGPropertyManager* KdPropertyNode; + + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGSensor.cpp b/src/models/flight_control/FGSensor.cpp old mode 100644 new mode 100755 index 6db0ed7a2f5811511ceb5c51fc029e75ff63cf95..a7feb746969ad1f66eb7a114d79a049fd3168907 --- a/src/models/flight_control/FGSensor.cpp +++ b/src/models/flight_control/FGSensor.cpp @@ -44,10 +44,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGSensor.cpp,v 1.20 2009/10/24 22:59:30 jberndt Exp $"; +static const char *IdSrc = "$Id: FGSensor.cpp,v 1.21 2010/08/21 22:56:11 jberndt Exp $"; static const char *IdHdr = ID_SENSOR; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -57,242 +56,213 @@ CLASS IMPLEMENTATION FGSensor::FGSensor(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - double denom; - - // inputs are read from the base class constructor - - bits = quantized = divisions = 0; - PreviousInput = PreviousOutput = 0.0; - min = max = bias = gain = noise_variance = lag = drift_rate = drift = span = 0.0; - granularity = 0.0; - noise_type = 0; - fail_low = fail_high = fail_stuck = false; - - Element* quantization_element = element->FindElement("quantization"); - if ( quantization_element) - { - if ( quantization_element->FindElement("bits") ) - { - bits = (int)quantization_element->FindElementValueAsNumber("bits"); - } - divisions = (1<<bits); - if ( quantization_element->FindElement("min") ) - { - min = quantization_element->FindElementValueAsNumber("min"); - } - if ( quantization_element->FindElement("max") ) - { - max = quantization_element->FindElementValueAsNumber("max"); - } - quant_property = quantization_element->GetAttributeValue("name"); - span = max - min; - granularity = span/divisions; - } - if ( element->FindElement("bias") ) - { - bias = element->FindElementValueAsNumber("bias"); + double denom; + + // inputs are read from the base class constructor + + bits = quantized = divisions = 0; + PreviousInput = PreviousOutput = 0.0; + min = max = bias = gain = noise_variance = lag = drift_rate = drift = span = 0.0; + granularity = 0.0; + noise_type = 0; + fail_low = fail_high = fail_stuck = false; + + Element* quantization_element = element->FindElement("quantization"); + if ( quantization_element) { + if ( quantization_element->FindElement("bits") ) { + bits = (int)quantization_element->FindElementValueAsNumber("bits"); } - if ( element->FindElement("gain") ) - { - gain = element->FindElementValueAsNumber("gain"); + divisions = (1<<bits); + if ( quantization_element->FindElement("min") ) { + min = quantization_element->FindElementValueAsNumber("min"); } - if ( element->FindElement("drift_rate") ) - { - drift_rate = element->FindElementValueAsNumber("drift_rate"); + if ( quantization_element->FindElement("max") ) { + max = quantization_element->FindElementValueAsNumber("max"); } - if ( element->FindElement("lag") ) - { - lag = element->FindElementValueAsNumber("lag"); - denom = 2.00 + dt*lag; - ca = dt*lag / denom; - cb = (2.00 - dt*lag) / denom; + quant_property = quantization_element->GetAttributeValue("name"); + span = max - min; + granularity = span/divisions; + } + if ( element->FindElement("bias") ) { + bias = element->FindElementValueAsNumber("bias"); + } + if ( element->FindElement("gain") ) { + gain = element->FindElementValueAsNumber("gain"); + } + if ( element->FindElement("drift_rate") ) { + drift_rate = element->FindElementValueAsNumber("drift_rate"); + } + if ( element->FindElement("lag") ) { + lag = element->FindElementValueAsNumber("lag"); + denom = 2.00 + dt*lag; + ca = dt*lag / denom; + cb = (2.00 - dt*lag) / denom; + } + if ( element->FindElement("noise") ) { + noise_variance = element->FindElementValueAsNumber("noise"); + string variation = element->FindElement("noise")->GetAttributeValue("variation"); + if (variation == "PERCENT") { + NoiseType = ePercent; + } else if (variation == "ABSOLUTE") { + NoiseType = eAbsolute; + } else { + NoiseType = ePercent; + cerr << "Unknown noise type in sensor: " << Name << endl; + cerr << " defaulting to PERCENT." << endl; } - if ( element->FindElement("noise") ) - { - noise_variance = element->FindElementValueAsNumber("noise"); - string variation = element->FindElement("noise")->GetAttributeValue("variation"); - if (variation == "PERCENT") - { - NoiseType = ePercent; - } - else if (variation == "ABSOLUTE") - { - NoiseType = eAbsolute; - } - else - { - NoiseType = ePercent; - cerr << "Unknown noise type in sensor: " << Name << endl; - cerr << " defaulting to PERCENT." << endl; - } - string distribution = element->FindElement("noise")->GetAttributeValue("distribution"); - if (distribution == "UNIFORM") - { - DistributionType = eUniform; - } - else if (distribution == "GAUSSIAN") - { - DistributionType = eGaussian; - } - else - { - DistributionType = eUniform; - cerr << "Unknown random distribution type in sensor: " << Name << endl; - cerr << " defaulting to UNIFORM." << endl; - } + string distribution = element->FindElement("noise")->GetAttributeValue("distribution"); + if (distribution == "UNIFORM") { + DistributionType = eUniform; + } else if (distribution == "GAUSSIAN") { + DistributionType = eGaussian; + } else { + DistributionType = eUniform; + cerr << "Unknown random distribution type in sensor: " << Name << endl; + cerr << " defaulting to UNIFORM." << endl; } + } - FGFCSComponent::bind(); - bind(); + FGFCSComponent::bind(); + bind(); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGSensor::~FGSensor() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGSensor::Run(void) { - Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; - ProcessSensorSignal(); + ProcessSensorSignal(); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGSensor::ProcessSensorSignal(void) { - Output = Input; // perfect sensor + Output = Input; // perfect sensor - // Degrade signal as specified + // Degrade signal as specified - if (fail_stuck) - { - Output = PreviousOutput; - } - else - { - if (lag != 0.0) Lag(); // models sensor lag and filter - if (noise_variance != 0.0) Noise(); // models noise - if (drift_rate != 0.0) Drift(); // models drift over time - if (gain != 0.0) Gain(); // models a finite gain - if (bias != 0.0) Bias(); // models a finite bias + if (fail_stuck) { + Output = PreviousOutput; + } else { + if (lag != 0.0) Lag(); // models sensor lag and filter + if (noise_variance != 0.0) Noise(); // models noise + if (drift_rate != 0.0) Drift(); // models drift over time + if (gain != 0.0) Gain(); // models a finite gain + if (bias != 0.0) Bias(); // models a finite bias - if (delay != 0) Delay(); // models system signal transport latencies + if (delay != 0) Delay(); // models system signal transport latencies - if (fail_low) Output = -HUGE_VAL; - if (fail_high) Output = HUGE_VAL; + if (fail_low) Output = -HUGE_VAL; + if (fail_high) Output = HUGE_VAL; - if (bits != 0) Quantize(); // models quantization degradation + if (bits != 0) Quantize(); // models quantization degradation - Clip(); - } + Clip(); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGSensor::Noise(void) { - double random_value=0.0; - - if (DistributionType == eUniform) - { - random_value = ((double)rand()/(double)RAND_MAX) - 0.5; - } - else - { - random_value = GaussianRandomNumber(); - } - - switch ( NoiseType ) - { - case ePercent: - Output *= (1.0 + noise_variance*random_value); - break; - - case eAbsolute: - Output += noise_variance*random_value; - break; - } + double random_value=0.0; + + if (DistributionType == eUniform) { + random_value = ((double)rand()/(double)RAND_MAX) - 0.5; + } else { + random_value = GaussianRandomNumber(); + } + + switch( NoiseType ) { + case ePercent: + Output *= (1.0 + noise_variance*random_value); + break; + + case eAbsolute: + Output += noise_variance*random_value; + break; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGSensor::Bias(void) { - Output += bias; + Output += bias; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGSensor::Gain(void) { - Output *= gain; + Output *= gain; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGSensor::Drift(void) { - drift += drift_rate*dt; - Output += drift; + drift += drift_rate*dt; + Output += drift; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGSensor::Quantize(void) { - if (Output < min) Output = min; - if (Output > max) Output = max; - double portion = Output - min; - quantized = (int)(portion/granularity); - Output = quantized*granularity + min; + if (Output < min) Output = min; + if (Output > max) Output = max; + double portion = Output - min; + quantized = (int)(portion/granularity); + Output = quantized*granularity + min; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGSensor::Lag(void) { - // "Output" on the right side of the "=" is the current input - Output = ca * (Output + PreviousInput) + PreviousOutput * cb; + // "Output" on the right side of the "=" is the current input + Output = ca * (Output + PreviousInput) + PreviousOutput * cb; - PreviousOutput = Output; - PreviousInput = Input; + PreviousOutput = Output; + PreviousInput = Input; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGSensor::bind(void) { - string tmp = Name; - if (Name.find("/") == string::npos) - { - tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true); - } - const string tmp_low = tmp + "/malfunction/fail_low"; - const string tmp_high = tmp + "/malfunction/fail_high"; - const string tmp_stuck = tmp + "/malfunction/fail_stuck"; - - PropertyManager->Tie( tmp_low, this, &FGSensor::GetFailLow, &FGSensor::SetFailLow); - PropertyManager->Tie( tmp_high, this, &FGSensor::GetFailHigh, &FGSensor::SetFailHigh); - PropertyManager->Tie( tmp_stuck, this, &FGSensor::GetFailStuck, &FGSensor::SetFailStuck); - - if (!quant_property.empty()) - { - if (quant_property.find("/") == string::npos) // not found - { - string qprop = "fcs/" + PropertyManager->mkPropertyName(quant_property, true); - PropertyManager->Tie(qprop, this, &FGSensor::GetQuantized); - } + string tmp = Name; + if (Name.find("/") == string::npos) { + tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true); + } + const string tmp_low = tmp + "/malfunction/fail_low"; + const string tmp_high = tmp + "/malfunction/fail_high"; + const string tmp_stuck = tmp + "/malfunction/fail_stuck"; + + PropertyManager->Tie( tmp_low, this, &FGSensor::GetFailLow, &FGSensor::SetFailLow); + PropertyManager->Tie( tmp_high, this, &FGSensor::GetFailHigh, &FGSensor::SetFailHigh); + PropertyManager->Tie( tmp_stuck, this, &FGSensor::GetFailStuck, &FGSensor::SetFailStuck); + + if (!quant_property.empty()) { + if (quant_property.find("/") == string::npos) { // not found + string qprop = "fcs/" + PropertyManager->mkPropertyName(quant_property, true); + PropertyManager->Tie(qprop, this, &FGSensor::GetQuantized); } + } } @@ -317,86 +287,66 @@ void FGSensor::bind(void) void FGSensor::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - if (InputSigns.size() > 0) - { - if (InputSigns[0] < 0) - cout << " INPUT: -" << InputNodes[0]->getName() << endl; - else - cout << " INPUT: " << InputNodes[0]->getName() << endl; - } - if (bits != 0) - { - if (quant_property.empty()) - cout << " Quantized output" << endl; - else - cout << " Quantized output (property: " << quant_property << ")" << endl; - - cout << " Bits: " << bits << endl; - cout << " Min value: " << min << endl; - cout << " Max value: " << max << endl; - cout << " (span: " << span << ", granularity: " << granularity << ")" << endl; - } - if (bias != 0.0) cout << " Bias: " << bias << endl; - if (gain != 0.0) cout << " Gain: " << gain << endl; - if (drift_rate != 0) cout << " Sensor drift rate: " << drift_rate << endl; - if (lag != 0) cout << " Sensor lag: " << lag << endl; - if (noise_variance != 0) - { - if (NoiseType == eAbsolute) - { - cout << " Noise variance (absolute): " << noise_variance << endl; - } - else if (NoiseType == ePercent) - { - cout << " Noise variance (percent): " << noise_variance << endl; - } - else - { - cout << " Noise variance type is invalid" << endl; - } - if (DistributionType == eUniform) - { - cout << " Random noise is uniformly distributed." << endl; - } - else if (DistributionType == eGaussian) - { - cout << " Random noise is gaussian distributed." << endl; - } - } - if (IsOutput) - { - for (unsigned int i=0; i<OutputNodes.size(); i++) - cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + if (InputSigns.size() > 0) { + if (InputSigns[0] < 0) + cout << " INPUT: -" << InputNames[0] << endl; + else + cout << " INPUT: " << InputNames[0] << endl; + } + if (bits != 0) { + if (quant_property.empty()) + cout << " Quantized output" << endl; + else + cout << " Quantized output (property: " << quant_property << ")" << endl; + + cout << " Bits: " << bits << endl; + cout << " Min value: " << min << endl; + cout << " Max value: " << max << endl; + cout << " (span: " << span << ", granularity: " << granularity << ")" << endl; + } + if (bias != 0.0) cout << " Bias: " << bias << endl; + if (gain != 0.0) cout << " Gain: " << gain << endl; + if (drift_rate != 0) cout << " Sensor drift rate: " << drift_rate << endl; + if (lag != 0) cout << " Sensor lag: " << lag << endl; + if (noise_variance != 0) { + if (NoiseType == eAbsolute) { + cout << " Noise variance (absolute): " << noise_variance << endl; + } else if (NoiseType == ePercent) { + cout << " Noise variance (percent): " << noise_variance << endl; + } else { + cout << " Noise variance type is invalid" << endl; } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGSensor" << endl; - if (from == 1) cout << "Destroyed: FGSensor" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; + if (DistributionType == eUniform) { + cout << " Random noise is uniformly distributed." << endl; + } else if (DistributionType == eGaussian) { + cout << " Random noise is gaussian distributed." << endl; } + } + if (IsOutput) { + for (unsigned int i=0; i<OutputNodes.size(); i++) + cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; + } + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGSensor" << endl; + if (from == 1) cout << "Destroyed: FGSensor" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/flight_control/FGSensor.h b/src/models/flight_control/FGSensor.h old mode 100644 new mode 100755 index 9b2c9e2892c05503d29e41c986f040849487fd60..bcc18dbe51f88534bdac7b6e5d3c8ea26135aef4 --- a/src/models/flight_control/FGSensor.h +++ b/src/models/flight_control/FGSensor.h @@ -50,8 +50,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFCS; class Element; @@ -118,84 +117,57 @@ CLASS DECLARATION class FGSensor : public FGFCSComponent { public: - FGSensor(FGFCS* fcs, Element* element); - virtual ~FGSensor(); - - void SetFailLow(double val) - { - if (val > 0.0) fail_low = true; - else fail_low = false; - } - void SetFailHigh(double val) - { - if (val > 0.0) fail_high = true; - else fail_high = false; - } - void SetFailStuck(double val) - { - if (val > 0.0) fail_stuck = true; - else fail_stuck = false; - } - - double GetFailLow(void) const - { - if (fail_low) return 1.0; - else return 0.0; - } - double GetFailHigh(void) const - { - if (fail_high) return 1.0; - else return 0.0; - } - double GetFailStuck(void) const - { - if (fail_stuck) return 1.0; - else return 0.0; - } - int GetQuantized(void) const - { - return quantized; - } - - virtual bool Run (void); + FGSensor(FGFCS* fcs, Element* element); + virtual ~FGSensor(); + + void SetFailLow(double val) {if (val > 0.0) fail_low = true; else fail_low = false;} + void SetFailHigh(double val) {if (val > 0.0) fail_high = true; else fail_high = false;} + void SetFailStuck(double val) {if (val > 0.0) fail_stuck = true; else fail_stuck = false;} + + double GetFailLow(void) const {if (fail_low) return 1.0; else return 0.0;} + double GetFailHigh(void) const {if (fail_high) return 1.0; else return 0.0;} + double GetFailStuck(void) const {if (fail_stuck) return 1.0; else return 0.0;} + int GetQuantized(void) const {return quantized;} + + virtual bool Run (void); protected: - enum eNoiseType {ePercent=0, eAbsolute} NoiseType; - enum eDistributionType {eUniform=0, eGaussian} DistributionType; - double min, max; - double span; - double bias; - double gain; - double drift_rate; - double drift; - double noise_variance; - double lag; - double granularity; - double ca; /// lag filter coefficient "a" - double cb; /// lag filter coefficient "b" - double PreviousOutput; - double PreviousInput; - int noise_type; - int bits; - int quantized; - int divisions; - bool fail_low; - bool fail_high; - bool fail_stuck; - std::string quant_property; - - void ProcessSensorSignal(void); - void Noise(void); - void Bias(void); - void Drift(void); - void Quantize(void); - void Lag(void); - void Gain(void); - - void bind(void); + enum eNoiseType {ePercent=0, eAbsolute} NoiseType; + enum eDistributionType {eUniform=0, eGaussian} DistributionType; + double min, max; + double span; + double bias; + double gain; + double drift_rate; + double drift; + double noise_variance; + double lag; + double granularity; + double ca; /// lag filter coefficient "a" + double cb; /// lag filter coefficient "b" + double PreviousOutput; + double PreviousInput; + int noise_type; + int bits; + int quantized; + int divisions; + bool fail_low; + bool fail_high; + bool fail_stuck; + std::string quant_property; + + void ProcessSensorSignal(void); + void Noise(void); + void Bias(void); + void Drift(void); + void Quantize(void); + void Lag(void); + void Gain(void); + + void bind(void); private: - void Debug(int from); + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGSensorOrientation.h b/src/models/flight_control/FGSensorOrientation.h old mode 100644 new mode 100755 index d376851139deaf92590ff1b28609bb56235def35..4defe4f7a76451d2fa454e8b79572a125b515dab --- a/src/models/flight_control/FGSensorOrientation.h +++ b/src/models/flight_control/FGSensorOrientation.h @@ -54,8 +54,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -76,78 +75,64 @@ CLASS DECLARATION class FGSensorOrientation : public FGJSBBase { public: - FGSensorOrientation(Element* element) - { - Element* orient_element = element->FindElement("orientation"); - if (orient_element) vOrient = orient_element->FindElementTripletConvertTo("RAD"); - else - { - std::cerr << "No orientation given for this sensor. " << std::endl; - } - - Element* axis_element = element->FindElement("axis"); - if (axis_element) - { - string sAxis = element->FindElementValue("axis"); - if (sAxis == "X" || sAxis == "x") - { - axis = 1; - } - else if (sAxis == "Y" || sAxis == "y") - { - axis = 2; - } - else if (sAxis == "Z" || sAxis == "z") - { - axis = 3; - } - else - { - std::cerr << " Incorrect/no axis specified for this sensor; assuming X axis" << std::endl; - axis = 1; - } - } - - CalculateTransformMatrix(); + FGSensorOrientation(Element* element) + { + Element* orient_element = element->FindElement("orientation"); + if (orient_element) vOrient = orient_element->FindElementTripletConvertTo("RAD"); + else { std::cerr << "No orientation given for this sensor. " << std::endl;} + + Element* axis_element = element->FindElement("axis"); + if (axis_element) { + string sAxis = element->FindElementValue("axis"); + if (sAxis == "X" || sAxis == "x") { + axis = 1; + } else if (sAxis == "Y" || sAxis == "y") { + axis = 2; + } else if (sAxis == "Z" || sAxis == "z") { + axis = 3; + } else { + std::cerr << " Incorrect/no axis specified for this sensor; assuming X axis" << std::endl; + axis = 1; + } } + CalculateTransformMatrix(); + } + // ~FGSensorOrientation(); protected: - FGColumnVector3 vOrient; - FGMatrix33 mT; - int axis; - void CalculateTransformMatrix(void) - { - double cp,sp,cr,sr,cy,sy; - - cp=cos(vOrient(ePitch)); - sp=sin(vOrient(ePitch)); - cr=cos(vOrient(eRoll)); - sr=sin(vOrient(eRoll)); - cy=cos(vOrient(eYaw)); - sy=sin(vOrient(eYaw)); - - mT(1,1) = cp*cy; - mT(1,2) = cp*sy; - mT(1,3) = -sp; - - mT(2,1) = sr*sp*cy - cr*sy; - mT(2,2) = sr*sp*sy + cr*cy; - mT(2,3) = sr*cp; - - mT(3,1) = cr*sp*cy + sr*sy; - mT(3,2) = cr*sp*sy - sr*cy; - mT(3,3) = cr*cp; - - // This transform is different than for FGForce, where we want a native nozzle - // force in body frame. Here we calculate the body frame accel and want it in - // the transformed accelerometer frame. So, the next line is commented out. - // mT = mT.Inverse(); - } + FGColumnVector3 vOrient; + FGMatrix33 mT; + int axis; + void CalculateTransformMatrix(void) + { + double cp,sp,cr,sr,cy,sy; + + cp=cos(vOrient(ePitch)); sp=sin(vOrient(ePitch)); + cr=cos(vOrient(eRoll)); sr=sin(vOrient(eRoll)); + cy=cos(vOrient(eYaw)); sy=sin(vOrient(eYaw)); + + mT(1,1) = cp*cy; + mT(1,2) = cp*sy; + mT(1,3) = -sp; + + mT(2,1) = sr*sp*cy - cr*sy; + mT(2,2) = sr*sp*sy + cr*cy; + mT(2,3) = sr*cp; + + mT(3,1) = cr*sp*cy + sr*sy; + mT(3,2) = cr*sp*sy - sr*cy; + mT(3,3) = cr*cp; + + // This transform is different than for FGForce, where we want a native nozzle + // force in body frame. Here we calculate the body frame accel and want it in + // the transformed accelerometer frame. So, the next line is commented out. + // mT = mT.Inverse(); + } private: - void Debug(int from); + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGSummer.cpp b/src/models/flight_control/FGSummer.cpp index 345c01b28da685ce4ffd3f1270fc54c1af358176..b67cbf70d4ad42678236bed2f808ac897c9641db 100644 --- a/src/models/flight_control/FGSummer.cpp +++ b/src/models/flight_control/FGSummer.cpp @@ -43,10 +43,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGSummer.cpp,v 1.7 2009/10/24 22:59:30 jberndt Exp $"; +static const char *IdSrc = "$Id: FGSummer.cpp,v 1.8 2010/08/21 22:56:11 jberndt Exp $"; static const char *IdHdr = ID_SUMMER; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -55,41 +54,40 @@ CLASS IMPLEMENTATION FGSummer::FGSummer(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - Bias = 0.0; + Bias = 0.0; - if (element->FindElement("bias")) Bias = element->FindElementValueAsNumber("bias"); + if (element->FindElement("bias")) Bias = element->FindElementValueAsNumber("bias"); - FGFCSComponent::bind(); + FGFCSComponent::bind(); - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGSummer::~FGSummer() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGSummer::Run(void ) { - unsigned int idx; + unsigned int idx; - Output = 0.0; + Output = 0.0; - for (idx=0; idx<InputNodes.size(); idx++) - { - Output += InputNodes[idx]->getDoubleValue() * InputSigns[idx]; - } + for (idx=0; idx<InputNodes.size(); idx++) { + Output += InputNodes[idx]->getDoubleValue() * InputSigns[idx]; + } - Output += Bias; + Output += Bias; - Clip(); - if (IsOutput) SetOutput(); + Clip(); + if (IsOutput) SetOutput(); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -113,50 +111,40 @@ bool FGSummer::Run(void ) void FGSummer::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " INPUTS: " << endl; - for (unsigned i=0;i<InputNodes.size();i++) - { - if (InputSigns[i] < 0) - cout << " -" << InputNodes[i]->getName() << endl; - else - cout << " " << InputNodes[i]->getName() << endl; - } - if (Bias != 0.0) cout << " Bias: " << Bias << endl; - if (IsOutput) - { - for (unsigned int i=0; i<OutputNodes.size(); i++) - cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; - } - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGSummer" << endl; - if (from == 1) cout << "Destroyed: FGSummer" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " INPUTS: " << endl; + for (unsigned i=0;i<InputNodes.size();i++) { + if (InputSigns[i] < 0) + cout << " -" << InputNames[i] << endl; + else + cout << " " << InputNames[i] << endl; + } + if (Bias != 0.0) cout << " Bias: " << Bias << endl; + if (IsOutput) { + for (unsigned int i=0; i<OutputNodes.size(); i++) + cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; + } } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGSummer" << endl; + if (from == 1) cout << "Destroyed: FGSummer" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } //namespace JSBSim diff --git a/src/models/flight_control/FGSummer.h b/src/models/flight_control/FGSummer.h index 06891700994fc4ecf73f5b29f6c0762aa060759a..12a198d01bd47bc4f7f0599132111f7e9e70e5b9 100644 --- a/src/models/flight_control/FGSummer.h +++ b/src/models/flight_control/FGSummer.h @@ -49,8 +49,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class Element; @@ -86,7 +85,7 @@ CLASS DOCUMENTATION <input> fcs/roll-ap-error-integrator </input> <clipto> <min> -1 </min> - <max> 1 </max> + <max> 1 </max> </clipto> </summer> @endcode @@ -110,19 +109,19 @@ CLASS DECLARATION class FGSummer : public FGFCSComponent { public: - /** Constructor. - @param fcs a pointer to the parent FGFCS object. - @param element a pointer to the configuration file node. */ - FGSummer(FGFCS* fcs, Element* element); - /// Destructor - ~FGSummer(); + /** Constructor. + @param fcs a pointer to the parent FGFCS object. + @param element a pointer to the configuration file node. */ + FGSummer(FGFCS* fcs, Element* element); + /// Destructor + ~FGSummer(); - /// The execution method for this FCS component. - bool Run(void); + /// The execution method for this FCS component. + bool Run(void); private: - double Bias; - void Debug(int from); + double Bias; + void Debug(int from); }; } #endif diff --git a/src/models/flight_control/FGSwitch.cpp b/src/models/flight_control/FGSwitch.cpp index c077a382bdbba3c49557ce58c4de8e7cfdd1d680..4e68ea7ffc2a5cefe08df67ca1cc5a6ef8b9e7bf 100644 --- a/src/models/flight_control/FGSwitch.cpp +++ b/src/models/flight_control/FGSwitch.cpp @@ -67,8 +67,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGSwitch.cpp,v 1.19 2009/10/24 22:59:30 jberndt Exp $"; static const char *IdHdr = ID_SWITCH; @@ -79,151 +78,121 @@ CLASS IMPLEMENTATION FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - string value, logic; - struct test *current_test; - Element *test_element, *condition_element; - - FGFCSComponent::bind(); // Bind() this component here in case it is used - // in its own definition for a sample-and-hold - - test_element = element->GetElement(); - while (test_element) - { - if (test_element->GetName() == "default") - { - current_test = new struct test; - current_test->Logic = eDefault; - tests.push_back(current_test); - } - else if (test_element->GetName() == "test") // here's a test - { - current_test = new struct test; - logic = test_element->GetAttributeValue("logic"); - if (logic == "OR") current_test->Logic = eOR; - else if (logic == "AND") current_test->Logic = eAND; - else if (logic.size() == 0) current_test->Logic = eAND; // default - else // error - { - cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << Name << endl; - } - for (unsigned int i=0; i<test_element->GetNumDataLines(); i++) - { - string input_data = test_element->GetDataLine(i); - if (input_data.size() <= 1) - { - // Make sure there are no bad data lines that consist solely of whitespace - cerr << fgred << " Bad data line in switch component: " << Name << reset << endl; - continue; - } - current_test->conditions.push_back(new FGCondition(input_data, PropertyManager)); - } - - condition_element = test_element->GetElement(); // retrieve condition groups - while (condition_element) - { - current_test->conditions.push_back(new FGCondition(condition_element, PropertyManager)); - condition_element = test_element->GetNextElement(); - } - - tests.push_back(current_test); + string value, logic; + struct test *current_test; + Element *test_element, *condition_element; + + FGFCSComponent::bind(); // Bind() this component here in case it is used + // in its own definition for a sample-and-hold + + test_element = element->GetElement(); + while (test_element) { + if (test_element->GetName() == "default") { + current_test = new struct test; + current_test->Logic = eDefault; + tests.push_back(current_test); + } else if (test_element->GetName() == "test") { // here's a test + current_test = new struct test; + logic = test_element->GetAttributeValue("logic"); + if (logic == "OR") current_test->Logic = eOR; + else if (logic == "AND") current_test->Logic = eAND; + else if (logic.size() == 0) current_test->Logic = eAND; // default + else { // error + cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << Name << endl; + } + for (unsigned int i=0; i<test_element->GetNumDataLines(); i++) { + string input_data = test_element->GetDataLine(i); + if (input_data.size() <= 1) { + // Make sure there are no bad data lines that consist solely of whitespace + cerr << fgred << " Bad data line in switch component: " << Name << reset << endl; + continue; } + current_test->conditions.push_back(new FGCondition(input_data, PropertyManager)); + } + + condition_element = test_element->GetElement(); // retrieve condition groups + while (condition_element) { + current_test->conditions.push_back(new FGCondition(condition_element, PropertyManager)); + condition_element = test_element->GetNextElement(); + } - if (test_element->GetName() != "output" - && test_element->GetName() != "description") // this is not an output element - { - value = test_element->GetAttributeValue("value"); - if (value.empty()) - { - cerr << "No VALUE supplied for switch component: " << Name << endl; - } - else - { - if (is_number(value)) - { - current_test->OutputVal = atof(value.c_str()); - } - else - { - // "value" must be a property if execution passes to here. - if (value[0] == '-') - { - current_test->sign = -1.0; - value.erase(0,1); - } - else - { - current_test->sign = 1.0; - } - current_test->OutputProp = PropertyManager->GetNode(value); - } - } + tests.push_back(current_test); + } + + if (test_element->GetName() != "output" + && test_element->GetName() != "description") { // this is not an output element + value = test_element->GetAttributeValue("value"); + if (value.empty()) { + cerr << "No VALUE supplied for switch component: " << Name << endl; + } else { + if (is_number(value)) { + current_test->OutputVal = atof(value.c_str()); + } else { + // "value" must be a property if execution passes to here. + if (value[0] == '-') { + current_test->sign = -1.0; + value.erase(0,1); + } else { + current_test->sign = 1.0; + } + current_test->OutputProp = PropertyManager->GetNode(value); } - test_element = element->GetNextElement(); + } } + test_element = element->GetNextElement(); + } - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGSwitch::~FGSwitch() { - for (unsigned int i=0; i<tests.size(); i++) - { - for (unsigned int j=0; j<tests[i]->conditions.size(); j++) delete tests[i]->conditions[j]; - delete tests[i]; - } + for (unsigned int i=0; i<tests.size(); i++) { + for (unsigned int j=0; j<tests[i]->conditions.size(); j++) delete tests[i]->conditions[j]; + delete tests[i]; + } - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGSwitch::Run(void ) { - bool pass = false; - double default_output=0.0; - - for (unsigned int i=0; i<tests.size(); i++) - { - if (tests[i]->Logic == eDefault) - { - default_output = tests[i]->GetValue(); - } - else if (tests[i]->Logic == eAND) - { - pass = true; - for (unsigned int j=0; j<tests[i]->conditions.size(); j++) - { - if (!tests[i]->conditions[j]->Evaluate()) pass = false; - } - } - else if (tests[i]->Logic == eOR) - { - pass = false; - for (unsigned int j=0; j<tests[i]->conditions.size(); j++) - { - if (tests[i]->conditions[j]->Evaluate()) pass = true; - } - } - else - { - cerr << "Invalid logic test" << endl; - } - - if (pass) - { - Output = tests[i]->GetValue(); - break; - } + bool pass = false; + double default_output=0.0; + + for (unsigned int i=0; i<tests.size(); i++) { + if (tests[i]->Logic == eDefault) { + default_output = tests[i]->GetValue(); + } else if (tests[i]->Logic == eAND) { + pass = true; + for (unsigned int j=0; j<tests[i]->conditions.size(); j++) { + if (!tests[i]->conditions[j]->Evaluate()) pass = false; + } + } else if (tests[i]->Logic == eOR) { + pass = false; + for (unsigned int j=0; j<tests[i]->conditions.size(); j++) { + if (tests[i]->conditions[j]->Evaluate()) pass = true; + } + } else { + cerr << "Invalid logic test" << endl; } - if (!pass) Output = default_output; + if (pass) { + Output = tests[i]->GetValue(); + break; + } + } + + if (!pass) Output = default_output; - Clip(); - if (IsOutput) SetOutput(); + Clip(); + if (IsOutput) SetOutput(); - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -247,89 +216,77 @@ bool FGSwitch::Run(void ) void FGSwitch::Debug(int from) { - string comp, scratch; - string indent = " "; - bool first = false; - - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - for (unsigned int i=0; i<tests.size(); i++) - { - - scratch = " if "; - - switch (tests[i]->Logic) - { - case (elUndef): - comp = " UNSET "; - cerr << "Unset logic for test condition" << endl; - break; - case (eAND): - comp = " AND "; - break; - case (eOR): - comp=" OR "; - break; - case (eDefault): - scratch = " by default."; - break; - default: - comp = " UNKNOWN "; - cerr << "Unknown logic for test condition" << endl; - } - - if (tests[i]->OutputProp != 0L) - if (tests[i]->sign < 0) - cout << indent << "Switch VALUE is - " << tests[i]->OutputProp->GetName() << scratch << endl; - else - cout << indent << "Switch VALUE is " << tests[i]->OutputProp->GetName() << scratch << endl; - else - cout << indent << "Switch VALUE is " << tests[i]->OutputVal << scratch << endl; - - first = true; - for (unsigned int j=0; j<tests[i]->conditions.size(); j++) - { - if (!first) cout << indent << comp << " "; - else cout << indent << " "; - first = false; - tests[i]->conditions[j]->PrintCondition(); - cout << endl; - } - cout << endl; - } - if (IsOutput) - { - for (unsigned int i=0; i<OutputNodes.size(); i++) - cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; - } + string comp, scratch; + string indent = " "; + bool first = false; + + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + for (unsigned int i=0; i<tests.size(); i++) { + + scratch = " if "; + + switch(tests[i]->Logic) { + case (elUndef): + comp = " UNSET "; + cerr << "Unset logic for test condition" << endl; + break; + case (eAND): + comp = " AND "; + break; + case (eOR): + comp=" OR "; + break; + case (eDefault): + scratch = " by default."; + break; + default: + comp = " UNKNOWN "; + cerr << "Unknown logic for test condition" << endl; } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGSwitch" << endl; - if (from == 1) cout << "Destroyed: FGSwitch" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; + + if (tests[i]->OutputProp != 0L) + if (tests[i]->sign < 0) + cout << indent << "Switch VALUE is - " << tests[i]->OutputProp->GetName() << scratch << endl; + else + cout << indent << "Switch VALUE is " << tests[i]->OutputProp->GetName() << scratch << endl; + else + cout << indent << "Switch VALUE is " << tests[i]->OutputVal << scratch << endl; + + first = true; + for (unsigned int j=0; j<tests[i]->conditions.size(); j++) { + if (!first) cout << indent << comp << " "; + else cout << indent << " "; + first = false; + tests[i]->conditions[j]->PrintCondition(); + cout << endl; } + cout << endl; + } + if (IsOutput) { + for (unsigned int i=0; i<OutputNodes.size(); i++) + cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; + } + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGSwitch" << endl; + if (from == 1) cout << "Destroyed: FGSwitch" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } //namespace JSBSim diff --git a/src/models/flight_control/FGSwitch.h b/src/models/flight_control/FGSwitch.h index 1b9882d97e9f8be375198f980cdaef00db85d684..a230aef7e5a2fadc1e5bd7ef35cb823e6c0ba4dc 100644 --- a/src/models/flight_control/FGSwitch.h +++ b/src/models/flight_control/FGSwitch.h @@ -51,8 +51,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -135,51 +134,48 @@ CLASS DECLARATION class FGSwitch : public FGFCSComponent { public: - /** Constructor - @param fcs a pointer to the parent FGFCS class - @param element a pointer to the Element (from the config file XML tree) - that represents this switch component */ - FGSwitch(FGFCS* fcs, Element* element); + /** Constructor + @param fcs a pointer to the parent FGFCS class + @param element a pointer to the Element (from the config file XML tree) + that represents this switch component */ + FGSwitch(FGFCS* fcs, Element* element); - /// Destructor - ~FGSwitch(); + /// Destructor + ~FGSwitch(); - /** Executes the switch logic. - @return true - always*/ - bool Run(void); + /** Executes the switch logic. + @return true - always*/ + bool Run(void); - enum eLogic {elUndef=0, eAND, eOR, eDefault}; - enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE}; + enum eLogic {elUndef=0, eAND, eOR, eDefault}; + enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE}; private: - struct test - { - vector <FGCondition*> conditions; - eLogic Logic; - double OutputVal; - FGPropertyManager *OutputProp; - float sign; - - double GetValue(void) - { - if (OutputProp == 0L) return OutputVal; - else return OutputProp->getDoubleValue()*sign; - } - - test(void) // constructor for the test structure - { - Logic = elUndef; - OutputVal = 0.0; - OutputProp = 0L; - sign = 1.0; - } - - }; - - vector <test*> tests; - - void Debug(int from); + struct test { + vector <FGCondition*> conditions; + eLogic Logic; + double OutputVal; + FGPropertyManager *OutputProp; + float sign; + + double GetValue(void) { + if (OutputProp == 0L) return OutputVal; + else return OutputProp->getDoubleValue()*sign; + } + + test(void) { // constructor for the test structure + Logic = elUndef; + OutputVal = 0.0; + OutputProp = 0L; + sign = 1.0; + } + + }; + + vector <test*> tests; + + void Debug(int from); }; } #endif diff --git a/src/models/propulsion/FGElectric.cpp b/src/models/propulsion/FGElectric.cpp index ef23127812c5fa7c2b93b52c9f7ac07ab8d5eb34..1138d820cceed7fe97b849229c8057af6eb1f8d9 100644 --- a/src/models/propulsion/FGElectric.cpp +++ b/src/models/propulsion/FGElectric.cpp @@ -48,10 +48,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGElectric.cpp,v 1.8 2010/02/25 05:21:36 jberndt Exp $"; +static const char *IdSrc = "$Id: FGElectric.cpp,v 1.9 2010/08/21 17:13:48 jberndt Exp $"; static const char *IdHdr = ID_ELECTRIC; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -59,66 +58,70 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGElectric::FGElectric(FGFDMExec* exec, Element *el, int engine_number) - : FGEngine(exec, el, engine_number) + : FGEngine(exec, el, engine_number) { - string token; + string token; - Type = etElectric; - PowerWatts = 745.7; - hptowatts = 745.7; + Type = etElectric; + PowerWatts = 745.7; + hptowatts = 745.7; - dt = FDMExec->GetDeltaT(); + dt = FDMExec->GetDeltaT(); - if (el->FindElement("power")) - PowerWatts = el->FindElementValueAsNumberConvertTo("power","WATTS"); + if (el->FindElement("power")) + PowerWatts = el->FindElementValueAsNumberConvertTo("power","WATTS"); - Debug(0); // Call Debug() routine from constructor if needed + Debug(0); // Call Debug() routine from constructor if needed } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGElectric::~FGElectric() { - Debug(1); // Call Debug() routine from constructor if needed + Debug(1); // Call Debug() routine from constructor if needed } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -double FGElectric::Calculate(void) +void FGElectric::Calculate(void) { - Throttle = FCS->GetThrottlePos(EngineNumber); + RunPreFunctions(); + + Throttle = FCS->GetThrottlePos(EngineNumber); - RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); + RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); - HP = PowerWatts * Throttle / hptowatts; + HP = PowerWatts * Throttle / hptowatts; - PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired(); + PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired(); - return Thruster->Calculate(PowerAvailable); + Thruster->Calculate(PowerAvailable); + + RunPostFunctions(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGElectric::GetEngineLabels(const string& delimiter) { - std::ostringstream buf; + std::ostringstream buf; - buf << Name << " HP (engine " << EngineNumber << ")" << delimiter - << Thruster->GetThrusterLabels(EngineNumber, delimiter); + buf << Name << " HP (engine " << EngineNumber << ")" << delimiter + << Thruster->GetThrusterLabels(EngineNumber, delimiter); - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGElectric::GetEngineValues(const string& delimiter) { - std::ostringstream buf; + std::ostringstream buf; - buf << HP << delimiter - << Thruster->GetThrusterValues(EngineNumber, delimiter); + buf << HP << delimiter + << Thruster->GetThrusterValues(EngineNumber, delimiter); - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -143,46 +146,38 @@ string FGElectric::GetEngineValues(const string& delimiter) void FGElectric::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - cout << "\n Engine Name: " << Name << endl; - cout << " Power Watts: " << PowerWatts << endl; + cout << "\n Engine Name: " << Name << endl; + cout << " Power Watts: " << PowerWatts << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGElectric" << endl; - if (from == 1) cout << "Destroyed: FGElectric" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGElectric" << endl; + if (from == 1) cout << "Destroyed: FGElectric" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } double FGElectric::CalcFuelNeed(void) { - return 0; + return 0; } } // namespace JSBSim diff --git a/src/models/propulsion/FGElectric.h b/src/models/propulsion/FGElectric.h index 63243185571150cff86f600a0228e9614f531dc1..268522956219d2a10302369e58930c184c1cb777 100644 --- a/src/models/propulsion/FGElectric.h +++ b/src/models/propulsion/FGElectric.h @@ -45,14 +45,13 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_ELECTRIC "$Id: FGElectric.h,v 1.8 2009/10/24 22:59:30 jberndt Exp $"; +#define ID_ELECTRIC "$Id: FGElectric.h,v 1.9 2010/08/21 18:07:59 jberndt Exp $"; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -66,7 +65,7 @@ CLASS DOCUMENTATION there is no battery model available, so this motor does not consume any energy. There is no internal friction. @author David Culp - @version "$Id: FGElectric.h,v 1.8 2009/10/24 22:59:30 jberndt Exp $" + @version "$Id: FGElectric.h,v 1.9 2010/08/21 18:07:59 jberndt Exp $" */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -76,41 +75,35 @@ CLASS DECLARATION class FGElectric : public FGEngine { public: - /// Constructor - FGElectric(FGFDMExec* exec, Element *el, int engine_number); - /// Destructor - ~FGElectric(); - - double Calculate(void); - double GetPowerAvailable(void) - { - return PowerAvailable; - } - double getRPM(void) - { - return RPM; - } - std::string GetEngineLabels(const std::string& delimiter); - std::string GetEngineValues(const std::string& delimiter); + /// Constructor + FGElectric(FGFDMExec* exec, Element *el, int engine_number); + /// Destructor + ~FGElectric(); + + void Calculate(void); + double GetPowerAvailable(void) {return PowerAvailable;} + double getRPM(void) {return RPM;} + std::string GetEngineLabels(const std::string& delimiter); + std::string GetEngineValues(const std::string& delimiter); private: - double CalcFuelNeed(void); + double CalcFuelNeed(void); - double BrakeHorsePower; - double PowerAvailable; + double BrakeHorsePower; + double PowerAvailable; - // timestep - double dt; + // timestep + double dt; - // constants - double hptowatts; + // constants + double hptowatts; - double PowerWatts; // maximum engine power - double RPM; // revolutions per minute - double HP; + double PowerWatts; // maximum engine power + double RPM; // revolutions per minute + double HP; - void Debug(int from); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/propulsion/FGEngine.cpp b/src/models/propulsion/FGEngine.cpp index 65f0d916cc6f19152d6f5faf9813517a6183204c..6cc525a5341422ac881444597d39eeaacacf00e7 100644 --- a/src/models/propulsion/FGEngine.cpp +++ b/src/models/propulsion/FGEngine.cpp @@ -52,10 +52,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGEngine.cpp,v 1.38 2010/06/02 04:05:13 jberndt Exp $"; +static const char *IdSrc = "$Id: FGEngine.cpp,v 1.39 2010/08/21 17:13:48 jberndt Exp $"; static const char *IdHdr = ID_ENGINE; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -63,129 +62,122 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number) - : EngineNumber(engine_number) + : EngineNumber(engine_number) { - Element* local_element; - FGColumnVector3 location, orientation; + Element* local_element; + FGColumnVector3 location, orientation; + + Name = ""; + Type = etUnknown; + X = Y = Z = 0.0; + EnginePitch = EngineYaw = 0.0; + SLFuelFlowMax = 0.0; + MaxThrottle = 1.0; + MinThrottle = 0.0; + FuelDensity = 6.0; + unsigned int i; - Name = ""; - Type = etUnknown; - X = Y = Z = 0.0; - EnginePitch = EngineYaw = 0.0; - SLFuelFlowMax = 0.0; - MaxThrottle = 1.0; - MinThrottle = 0.0; - FuelDensity = 6.0; - unsigned int i; + ResetToIC(); // initialize dynamic terms - ResetToIC(); // initialize dynamic terms + FDMExec = exec; + Atmosphere = FDMExec->GetAtmosphere(); + FCS = FDMExec->GetFCS(); + Propulsion = FDMExec->GetPropulsion(); + Aircraft = FDMExec->GetAircraft(); + Propagate = FDMExec->GetPropagate(); + Auxiliary = FDMExec->GetAuxiliary(); - FDMExec = exec; - Atmosphere = FDMExec->GetAtmosphere(); - FCS = FDMExec->GetFCS(); - Propulsion = FDMExec->GetPropulsion(); - Aircraft = FDMExec->GetAircraft(); - Propagate = FDMExec->GetPropagate(); - Auxiliary = FDMExec->GetAuxiliary(); + PropertyManager = FDMExec->GetPropertyManager(); - PropertyManager = FDMExec->GetPropertyManager(); + Name = engine_element->GetAttributeValue("name"); - Name = engine_element->GetAttributeValue("name"); + Load(engine_element, PropertyManager, to_string(EngineNumber)); // Call ModelFunctions loader // Find and set engine location - local_element = engine_element->GetParent()->FindElement("location"); - if (local_element) location = local_element->FindElementTripletConvertTo("IN"); - else cerr << "No engine location found for this engine." << endl; + local_element = engine_element->GetParent()->FindElement("location"); + if (local_element) location = local_element->FindElementTripletConvertTo("IN"); + else cerr << "No engine location found for this engine." << endl; - local_element = engine_element->GetParent()->FindElement("orient"); - if (local_element) orientation = local_element->FindElementTripletConvertTo("RAD"); + local_element = engine_element->GetParent()->FindElement("orient"); + if (local_element) orientation = local_element->FindElementTripletConvertTo("RAD"); // else cerr << "No engine orientation found for this engine." << endl; // Jon: The engine orientation has a default and is not normally used. - SetPlacement(location, orientation); - - // Load thruster - local_element = engine_element->GetParent()->FindElement("thruster"); - if (local_element) - { - if (!LoadThruster(local_element)) exit(-1); - } - else - { - cerr << "No thruster definition supplied with engine definition." << endl; - } - - // Build and initialize the feed tank vector. - for (i=0; i<(Propulsion->GetNumTanks()); i++) - { - SourceTanks.push_back(0); + SetPlacement(location, orientation); + + // Load thruster + local_element = engine_element->GetParent()->FindElement("thruster"); + if (local_element) { + if (!LoadThruster(local_element)) exit(-1); + } else { + cerr << "No thruster definition supplied with engine definition." << endl; + } + + // Build and initialize the feed tank vector. + for (i=0; i<(Propulsion->GetNumTanks()); i++) { + SourceTanks.push_back(0); + } + + // Load feed tank[s] references + local_element = engine_element->GetParent()->FindElement("feed"); + if (local_element) { + while (local_element) { + int tankID = (int)local_element->GetDataAsNumber(); + FGTank* tank = Propulsion->GetTank(tankID); + if (tank) { + AddFeedTank(tankID, tank->GetPriority()); + FuelDensity = tank->GetDensity(); + } else { + cerr << "Feed tank " << tankID << + " specified in engine definition does not exist." << endl; + } + local_element = engine_element->GetParent()->FindNextElement("feed"); } + } else { + cerr << "No feed tank specified in engine definition." << endl; + } - // Load feed tank[s] references - local_element = engine_element->GetParent()->FindElement("feed"); - if (local_element) - { - while (local_element) - { - int tankID = (int)local_element->GetDataAsNumber(); - FGTank* tank = Propulsion->GetTank(tankID); - if (tank) - { - AddFeedTank(tankID, tank->GetPriority()); - FuelDensity = tank->GetDensity(); - } - else - { - cerr << "Feed tank " << tankID << - " specified in engine definition does not exist." << endl; - } - local_element = engine_element->GetParent()->FindNextElement("feed"); - } - } - else - { - cerr << "No feed tank specified in engine definition." << endl; - } + string property_name, base_property_name; + base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); - string property_name, base_property_name; - base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); + property_name = base_property_name + "/set-running"; + PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetRunning, &FGEngine::SetRunning ); + property_name = base_property_name + "/thrust-lbs"; + PropertyManager->Tie( property_name.c_str(), Thruster, &FGThruster::GetThrust); + property_name = base_property_name + "/fuel-flow-rate-pps"; + PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate); - property_name = base_property_name + "/set-running"; - PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetRunning, &FGEngine::SetRunning ); - property_name = base_property_name + "/thrust-lbs"; - PropertyManager->Tie( property_name.c_str(), Thruster, &FGThruster::GetThrust); - property_name = base_property_name + "/fuel-flow-rate-pps"; - PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate); + PostLoad(engine_element, PropertyManager, to_string(EngineNumber)); - //cout << "Engine[" << EngineNumber << "] using fuel density: " << FuelDensity << endl; + //cout << "Engine[" << EngineNumber << "] using fuel density: " << FuelDensity << endl; - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGEngine::~FGEngine() { - delete Thruster; - Debug(1); + delete Thruster; + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGEngine::ResetToIC(void) { - Throttle = 0.0; - Mixture = 1.0; - Starter = false; - FuelExpended = 0.0; - Starved = Running = Cranking = false; - PctPower = 0.0; - TrimMode = false; - FuelFlow_gph = 0.0; - FuelFlow_pph = 0.0; - FuelFlowRate = 0.0; - FuelFreeze = false; + Throttle = 0.0; + Mixture = 1.0; + Starter = false; + FuelExpended = 0.0; + Starved = Running = Cranking = false; + PctPower = 0.0; + TrimMode = false; + FuelFlow_gph = 0.0; + FuelFlow_pph = 0.0; + FuelFlowRate = 0.0; + FuelFreeze = false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -197,62 +189,53 @@ void FGEngine::ResetToIC(void) void FGEngine::ConsumeFuel(void) { - if (FuelFreeze) return; - if (TrimMode) return; - - unsigned int i; - double Fshortage, FuelNeeded; - FGTank* Tank; - unsigned int TanksWithFuel = 0; - Fshortage = FuelNeeded = 0.0; - double FuelToBurn; - unsigned int CurrentPriority = 1; - vector <int> FeedList; - Starved = false; - - FuelToBurn = CalcFuelNeed(); - if (FuelToBurn == 0.0) return; - - // Count how many fuel tanks with the current priority level have fuel. - // If none, then try next lower priority. Build the feed list. - while ((TanksWithFuel == 0) && (CurrentPriority <= Propulsion->GetNumTanks())) - { - for (i=0; i<Propulsion->GetNumTanks(); i++) - { - if (SourceTanks[i] != 0) - { - Tank = Propulsion->GetTank(i); - if (Tank->GetType() == FGTank::ttFUEL) - { - if ((Tank->GetContents() > 0.0) && ((unsigned int)Tank->GetPriority() == CurrentPriority)) - { - ++TanksWithFuel; - FeedList.push_back(i); - } - } - else - { - cerr << "No oxidizer tanks should be used for this engine type." << endl; - } - } + if (FuelFreeze) return; + if (TrimMode) return; + + unsigned int i; + double Fshortage, FuelNeeded; + FGTank* Tank; + unsigned int TanksWithFuel = 0; + Fshortage = FuelNeeded = 0.0; + double FuelToBurn; + unsigned int CurrentPriority = 1; + vector <int> FeedList; + Starved = false; + + FuelToBurn = CalcFuelNeed(); + if (FuelToBurn == 0.0) return; + + // Count how many fuel tanks with the current priority level have fuel. + // If none, then try next lower priority. Build the feed list. + while ((TanksWithFuel == 0) && (CurrentPriority <= Propulsion->GetNumTanks())) { + for (i=0; i<Propulsion->GetNumTanks(); i++) { + if (SourceTanks[i] != 0) { + Tank = Propulsion->GetTank(i); + if (Tank->GetType() == FGTank::ttFUEL) { + if ((Tank->GetContents() > 0.0) && ((unsigned int)Tank->GetPriority() == CurrentPriority)) { + ++TanksWithFuel; + FeedList.push_back(i); + } + } else { + cerr << "No oxidizer tanks should be used for this engine type." << endl; } - if (TanksWithFuel == 0) CurrentPriority++; - } - - // No fuel found at any priority! - if (TanksWithFuel == 0) - { - Starved = true; - return; - } - - // Remove equal amount of fuel from each feed tank. - FuelNeeded = FuelToBurn/TanksWithFuel; - for (i=0; i<FeedList.size(); i++) - { - Tank = Propulsion->GetTank(FeedList[i]); - Tank->Drain(FuelNeeded); + } } + if (TanksWithFuel == 0) CurrentPriority++; + } + + // No fuel found at any priority! + if (TanksWithFuel == 0) { + Starved = true; + return; + } + + // Remove equal amount of fuel from each feed tank. + FuelNeeded = FuelToBurn/TanksWithFuel; + for (i=0; i<FeedList.size(); i++) { + Tank = Propulsion->GetTank(FeedList[i]); + Tank->Drain(FuelNeeded); + } } @@ -260,115 +243,99 @@ void FGEngine::ConsumeFuel(void) double FGEngine::CalcFuelNeed(void) { - double dT = FDMExec->GetDeltaT()*Propulsion->GetRate(); - FuelFlowRate = SLFuelFlowMax*PctPower; - FuelExpended = FuelFlowRate*dT; - return FuelExpended; + double dT = FDMExec->GetDeltaT()*Propulsion->GetRate(); + FuelFlowRate = SLFuelFlowMax*PctPower; + FuelExpended = FuelFlowRate*dT; + return FuelExpended; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGEngine::SetPlacement(FGColumnVector3& location, FGColumnVector3& orientation) { - X = location(eX); - Y = location(eY); - Z = location(eZ); - EnginePitch = orientation(ePitch); - EngineYaw = orientation (eYaw); + X = location(eX); + Y = location(eY); + Z = location(eZ); + EnginePitch = orientation(ePitch); + EngineYaw = orientation (eYaw); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGEngine::AddFeedTank(int tkID, int priority) { - SourceTanks[tkID] = priority; + SourceTanks[tkID] = priority; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3& FGEngine::GetBodyForces(void) { - return Thruster->GetBodyForces(); + return Thruster->GetBodyForces(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3& FGEngine::GetMoments(void) { - return Thruster->GetMoments(); + return Thruster->GetMoments(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGEngine::LoadThruster(Element *thruster_element) { - string token, fullpath, localpath; - string thruster_filename, thruster_fullpathname, thrType; - string enginePath = FDMExec->GetEnginePath(); - string aircraftPath = FDMExec->GetFullAircraftPath(); - ifstream thruster_file; - FGColumnVector3 location, orientation; - string separator = "/"; - - fullpath = enginePath + separator; - localpath = aircraftPath + separator + "Engines" + separator; - - thruster_filename = thruster_element->GetAttributeValue("file"); - if ( !thruster_filename.empty()) - { - thruster_fullpathname = fullpath + thruster_filename + ".xml"; - thruster_file.open(thruster_fullpathname.c_str()); - if ( !thruster_file.is_open()) - { - thruster_fullpathname = localpath + thruster_filename + ".xml"; - thruster_file.open(thruster_fullpathname.c_str()); - if ( !thruster_file.is_open()) - { - cerr << "Could not open thruster file: " << thruster_filename << ".xml" << endl; - return false; - } - else - { - thruster_file.close(); - } - } - else - { - thruster_file.close(); - } - } - else - { - cerr << "No thruster filename given." << endl; + string token, fullpath, localpath; + string thruster_filename, thruster_fullpathname, thrType; + string enginePath = FDMExec->GetEnginePath(); + string aircraftPath = FDMExec->GetFullAircraftPath(); + ifstream thruster_file; + FGColumnVector3 location, orientation; + string separator = "/"; + + fullpath = enginePath + separator; + localpath = aircraftPath + separator + "Engines" + separator; + + thruster_filename = thruster_element->GetAttributeValue("file"); + if ( !thruster_filename.empty()) { + thruster_fullpathname = fullpath + thruster_filename + ".xml"; + thruster_file.open(thruster_fullpathname.c_str()); + if ( !thruster_file.is_open()) { + thruster_fullpathname = localpath + thruster_filename + ".xml"; + thruster_file.open(thruster_fullpathname.c_str()); + if ( !thruster_file.is_open()) { + cerr << "Could not open thruster file: " << thruster_filename << ".xml" << endl; return false; + } else { + thruster_file.close(); + } + } else { + thruster_file.close(); } - - document = LoadXMLDocument(thruster_fullpathname); - document->SetParent(thruster_element); - - thrType = document->GetName(); - - if (thrType == "propeller") - { - Thruster = new FGPropeller(FDMExec, document, EngineNumber); - } - else if (thrType == "nozzle") - { - Thruster = new FGNozzle(FDMExec, document, EngineNumber); - } - else if (thrType == "rotor") - { - Thruster = new FGRotor(FDMExec, document, EngineNumber); - } - else if (thrType == "direct") - { - Thruster = new FGThruster( FDMExec, document, EngineNumber); - } - - Thruster->SetdeltaT(FDMExec->GetDeltaT() * Propulsion->GetRate()); - - Debug(2); - return true; + } else { + cerr << "No thruster filename given." << endl; + return false; + } + + document = LoadXMLDocument(thruster_fullpathname); + document->SetParent(thruster_element); + + thrType = document->GetName(); + + if (thrType == "propeller") { + Thruster = new FGPropeller(FDMExec, document, EngineNumber); + } else if (thrType == "nozzle") { + Thruster = new FGNozzle(FDMExec, document, EngineNumber); + } else if (thrType == "rotor") { + Thruster = new FGRotor(FDMExec, document, EngineNumber); + } else if (thrType == "direct") { + Thruster = new FGThruster( FDMExec, document, EngineNumber); + } + + Thruster->SetdeltaT(FDMExec->GetDeltaT() * Propulsion->GetRate()); + + Debug(2); + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -392,44 +359,35 @@ bool FGEngine::LoadThruster(Element *thruster_element) void FGEngine::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - } - if (from == 2) // After thruster loading - { - cout << " X = " << Thruster->GetLocationX() << endl; - cout << " Y = " << Thruster->GetLocationY() << endl; - cout << " Z = " << Thruster->GetLocationZ() << endl; - cout << " Pitch = " << radtodeg*Thruster->GetAnglesToBody(ePitch) << " degrees" << endl; - cout << " Yaw = " << radtodeg*Thruster->GetAnglesToBody(eYaw) << " degrees" << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGEngine" << endl; - if (from == 1) cout << "Destroyed: FGEngine" << endl; } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { + if (from == 2) { // After thruster loading + cout << " X = " << Thruster->GetLocationX() << endl; + cout << " Y = " << Thruster->GetLocationY() << endl; + cout << " Z = " << Thruster->GetLocationZ() << endl; + cout << " Pitch = " << radtodeg*Thruster->GetAnglesToBody(ePitch) << " degrees" << endl; + cout << " Yaw = " << radtodeg*Thruster->GetAnglesToBody(eYaw) << " degrees" << endl; } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGEngine" << endl; + if (from == 1) cout << "Destroyed: FGEngine" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/propulsion/FGEngine.h b/src/models/propulsion/FGEngine.h index bcde8a91f8b94298890767dc882db97cba730842..c25eebfc0a4abdca19e431987e1ebe11bc49cc8a 100644 --- a/src/models/propulsion/FGEngine.h +++ b/src/models/propulsion/FGEngine.h @@ -43,7 +43,7 @@ SENTRY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include "FGJSBBase.h" +#include "math/FGModelFunctions.h" #include "input_output/FGXMLFileRead.h" #include "input_output/FGXMLElement.h" #include "models/FGFCS.h" @@ -55,14 +55,13 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_ENGINE "$Id: FGEngine.h,v 1.20 2010/02/25 05:21:36 jberndt Exp $" +#define ID_ENGINE "$Id: FGEngine.h,v 1.21 2010/08/21 17:13:48 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class FGFDMExec; class FGAtmosphere; @@ -80,7 +79,7 @@ CLASS DOCUMENTATION /** Base class for all engines. This base class contains methods and members common to all engines, such as - logic to drain fuel from the appropriate tank, etc. + logic to drain fuel from the appropriate tank, etc. <br> <h3>Configuration File Format:</h3> @code @@ -97,7 +96,7 @@ CLASS DOCUMENTATION <yaw> {number} </yaw> </orient> <feed> {integer} </feed> - ... optional more feed tank index numbers ... + ... optional more feed tank index numbers ... <thruster file="{string}"> <location unit="{IN | M}"> <x> {number} </x> @@ -114,206 +113,131 @@ CLASS DOCUMENTATION @endcode <pre> NOTES: - + Not all thruster types can be matched with a given engine type. See the class documentation for engine and thruster classes. -</pre> +</pre> @author Jon S. Berndt - @version $Id: FGEngine.h,v 1.20 2010/02/25 05:21:36 jberndt Exp $ + @version $Id: FGEngine.h,v 1.21 2010/08/21 17:13:48 jberndt Exp $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGEngine : public FGJSBBase, public FGXMLFileRead +class FGEngine : public FGModelFunctions, public FGXMLFileRead { public: - FGEngine(FGFDMExec* exec, Element* el, int engine_number); - virtual ~FGEngine(); - - enum EngineType {etUnknown, etRocket, etPiston, etTurbine, etTurboprop, etElectric}; - - EngineType GetType(void) - { - return Type; - } - virtual string GetName(void) - { - return Name; - } - - // Engine controls - virtual double GetThrottleMin(void) - { - return MinThrottle; - } - virtual double GetThrottleMax(void) - { - return MaxThrottle; - } - virtual double GetThrottle(void) - { - return Throttle; - } - virtual double GetMixture(void) - { - return Mixture; - } - virtual bool GetStarter(void) - { - return Starter; - } - - virtual double getFuelFlow_gph () const - { - return FuelFlow_gph; - } - virtual double getFuelFlow_pph () const - { - return FuelFlow_pph; - } - virtual double GetFuelFlowRate(void) const - { - return FuelFlowRate; - } - virtual bool GetStarved(void) - { - return Starved; - } - virtual bool GetRunning(void) const - { - return Running; - } - virtual bool GetCranking(void) - { - return Cranking; - } - - virtual void SetStarved(bool tt) - { - Starved = tt; - } - virtual void SetStarved(void) - { - Starved = true; - } - - virtual void SetRunning(bool bb) - { - Running=bb; - } - virtual void SetName(string name) - { - Name = name; - } - virtual void AddFeedTank(int tkID, int priority); - virtual void SetFuelFreeze(bool f) - { - FuelFreeze = f; - } - - virtual void SetStarter(bool s) - { - Starter = s; - } - - virtual int InitRunning(void) - { - return 1; - } - - /** Resets the Engine parameters to the initial conditions */ - void ResetToIC(void); - - /** Calculates the thrust of the engine, and other engine functions. - @return Thrust in pounds */ - virtual double Calculate(void) - { - return 0.0; - } - - /// Sets engine placement information - virtual void SetPlacement(FGColumnVector3& location, FGColumnVector3& orientation); - - virtual double GetPowerAvailable(void) - { - return 0.0; - }; - - virtual bool GetTrimMode(void) - { - return TrimMode; - } - virtual void SetTrimMode(bool state) - { - TrimMode = state; - } - - virtual FGColumnVector3& GetBodyForces(void); - virtual FGColumnVector3& GetMoments(void); - - bool LoadThruster(Element *el); - FGThruster* GetThruster(void) - { - return Thruster; - } - - virtual std::string GetEngineLabels(const std::string& delimiter) = 0; - virtual std::string GetEngineValues(const std::string& delimiter) = 0; + FGEngine(FGFDMExec* exec, Element* el, int engine_number); + virtual ~FGEngine(); + + enum EngineType {etUnknown, etRocket, etPiston, etTurbine, etTurboprop, etElectric}; + + EngineType GetType(void) { return Type; } + virtual string GetName(void) { return Name; } + + // Engine controls + virtual double GetThrottleMin(void) { return MinThrottle; } + virtual double GetThrottleMax(void) { return MaxThrottle; } + virtual double GetThrottle(void) { return Throttle; } + virtual double GetMixture(void) { return Mixture; } + virtual bool GetStarter(void) { return Starter; } + + virtual double getFuelFlow_gph () const {return FuelFlow_gph;} + virtual double getFuelFlow_pph () const {return FuelFlow_pph;} + virtual double GetFuelFlowRate(void) const {return FuelFlowRate;} + virtual bool GetStarved(void) { return Starved; } + virtual bool GetRunning(void) const { return Running; } + virtual bool GetCranking(void) { return Cranking; } + + virtual void SetStarved(bool tt) { Starved = tt; } + virtual void SetStarved(void) { Starved = true; } + + virtual void SetRunning(bool bb) { Running=bb; } + virtual void SetName(string name) { Name = name; } + virtual void AddFeedTank(int tkID, int priority); + virtual void SetFuelFreeze(bool f) { FuelFreeze = f; } + + virtual void SetStarter(bool s) { Starter = s; } + + virtual int InitRunning(void){ return 1; } + + /** Resets the Engine parameters to the initial conditions */ + void ResetToIC(void); + + /** Calculates the thrust of the engine, and other engine functions. */ + virtual void Calculate(void) = 0; + + /// Sets engine placement information + virtual void SetPlacement(FGColumnVector3& location, FGColumnVector3& orientation); + + virtual double GetPowerAvailable(void) {return 0.0;}; + + virtual bool GetTrimMode(void) {return TrimMode;} + virtual void SetTrimMode(bool state) {TrimMode = state;} + + virtual FGColumnVector3& GetBodyForces(void); + virtual FGColumnVector3& GetMoments(void); + + bool LoadThruster(Element *el); + FGThruster* GetThruster(void) {return Thruster;} + + virtual std::string GetEngineLabels(const std::string& delimiter) = 0; + virtual std::string GetEngineValues(const std::string& delimiter) = 0; protected: - /** Reduces the fuel in the active tanks by the amount required. - This function should be called from within the - derived class' Calculate() function before any other calculations are - done. This base class method removes fuel from the fuel tanks as - appropriate, and sets the starved flag if necessary. */ - virtual void ConsumeFuel(void); - - /** The fuel need is calculated based on power levels and flow rate for that - power level. It is also turned from a rate into an actual amount (pounds) - by multiplying it by the delta T and the rate. - @return Total fuel requirement for this engine in pounds. */ - virtual double CalcFuelNeed(void); - - FGPropertyManager* PropertyManager; - std::string Name; - const int EngineNumber; - EngineType Type; - double X, Y, Z; - double EnginePitch; - double EngineYaw; - double SLFuelFlowMax; - double MaxThrottle; - double MinThrottle; - - double Throttle; - double Mixture; - double FuelExpended; - double FuelFlowRate; - double PctPower; - bool Starter; - bool Starved; - bool Running; - bool Cranking; - bool TrimMode; - bool FuelFreeze; - - double FuelFlow_gph; - double FuelFlow_pph; - double FuelDensity; - - FGFDMExec* FDMExec; - FGAtmosphere* Atmosphere; - FGFCS* FCS; - FGPropulsion* Propulsion; - FGAircraft* Aircraft; - FGPropagate* Propagate; - FGAuxiliary* Auxiliary; - FGThruster* Thruster; - - std::vector <int> SourceTanks; - void Debug(int from); + /** Reduces the fuel in the active tanks by the amount required. + This function should be called from within the + derived class' Calculate() function before any other calculations are + done. This base class method removes fuel from the fuel tanks as + appropriate, and sets the starved flag if necessary. */ + virtual void ConsumeFuel(void); + + /** The fuel need is calculated based on power levels and flow rate for that + power level. It is also turned from a rate into an actual amount (pounds) + by multiplying it by the delta T and the rate. + @return Total fuel requirement for this engine in pounds. */ + virtual double CalcFuelNeed(void); + + FGPropertyManager* PropertyManager; + std::string Name; + const int EngineNumber; + EngineType Type; + double X, Y, Z; + double EnginePitch; + double EngineYaw; + double SLFuelFlowMax; + double MaxThrottle; + double MinThrottle; + + double Throttle; + double Mixture; + double FuelExpended; + double FuelFlowRate; + double PctPower; + bool Starter; + bool Starved; + bool Running; + bool Cranking; + bool TrimMode; + bool FuelFreeze; + + double FuelFlow_gph; + double FuelFlow_pph; + double FuelDensity; + + FGFDMExec* FDMExec; + FGAtmosphere* Atmosphere; + FGFCS* FCS; + FGPropulsion* Propulsion; + FGAircraft* Aircraft; + FGPropagate* Propagate; + FGAuxiliary* Auxiliary; + FGThruster* Thruster; + + std::vector <int> SourceTanks; + + void Debug(int from); }; } diff --git a/src/models/propulsion/FGForce.cpp b/src/models/propulsion/FGForce.cpp index e74e2d4db0ae708fe88ac7f78ac19712fac2ef71..0180d18e404b15f73aec103a04550d1822ce50c2 100644 --- a/src/models/propulsion/FGForce.cpp +++ b/src/models/propulsion/FGForce.cpp @@ -51,8 +51,7 @@ and the cg. using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGForce.cpp,v 1.14 2009/10/24 22:59:30 jberndt Exp $"; static const char *IdHdr = ID_FORCE; @@ -60,102 +59,97 @@ static const char *IdHdr = ID_FORCE; //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGForce::FGForce(FGFDMExec *FDMExec) : - fdmex(FDMExec), - ttype(tNone) + fdmex(FDMExec), + ttype(tNone) { - mT(1,1) = 1; //identity matrix - mT(2,2) = 1; - mT(3,3) = 1; + mT(1,1) = 1; //identity matrix + mT(2,2) = 1; + mT(3,3) = 1; - Debug(0); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGForce::~FGForce() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3& FGForce::GetBodyForces(void) { - vFb = Transform()*vFn; + vFb = Transform()*vFn; - // Find the distance from this vector's acting location to the cg; this - // needs to be done like this to convert from structural to body coords. - // CG and RP values are in inches + // Find the distance from this vector's acting location to the cg; this + // needs to be done like this to convert from structural to body coords. + // CG and RP values are in inches - vDXYZ = fdmex->GetMassBalance()->StructuralToBody(vActingXYZn); + vDXYZ = fdmex->GetMassBalance()->StructuralToBody(vActingXYZn); - vM = vMn + vDXYZ*vFb; + vM = vMn + vDXYZ*vFb; - return vFb; + return vFb; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGMatrix33 FGForce::Transform(void) { - switch (ttype) - { - case tWindBody: - return fdmex->GetAerodynamics()->GetTw2b(); - case tLocalBody: - return fdmex->GetPropagate()->GetTl2b(); - case tCustom: - case tNone: - return mT; - default: - cout << "Unrecognized tranform requested from FGForce::Transform()" << endl; - exit(1); - } + switch(ttype) { + case tWindBody: + return fdmex->GetAerodynamics()->GetTw2b(); + case tLocalBody: + return fdmex->GetPropagate()->GetTl2b(); + case tCustom: + case tNone: + return mT; + default: + cout << "Unrecognized tranform requested from FGForce::Transform()" << endl; + exit(1); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGForce::UpdateCustomTransformMatrix(void) { - double cp,sp,cr,sr,cy,sy; - double srsp, crcy, crsy; - - cp=cos(vOrient(ePitch)); - sp=sin(vOrient(ePitch)); - cr=cos(vOrient(eRoll)); - sr=sin(vOrient(eRoll)); - cy=cos(vOrient(eYaw)); - sy=sin(vOrient(eYaw)); - - srsp = sr*sp; - crcy = cr*cy; - crsy = cr*sy; - - mT(1,1) = cp*cy; - mT(2,1) = cp*sy; - mT(3,1) = -sp; - - mT(1,2) = srsp*cy - crsy; - mT(2,2) = srsp*sy + crcy; - mT(3,2) = sr*cp; - - mT(1,3) = crcy*sp + sr*sy; - mT(2,3) = crsy*sp - sr*cy; - mT(3,3) = cr*cp; + double cp,sp,cr,sr,cy,sy; + double srsp, crcy, crsy; + + cp=cos(vOrient(ePitch)); sp=sin(vOrient(ePitch)); + cr=cos(vOrient(eRoll)); sr=sin(vOrient(eRoll)); + cy=cos(vOrient(eYaw)); sy=sin(vOrient(eYaw)); + + srsp = sr*sp; + crcy = cr*cy; + crsy = cr*sy; + + mT(1,1) = cp*cy; + mT(2,1) = cp*sy; + mT(3,1) = -sp; + + mT(1,2) = srsp*cy - crsy; + mT(2,2) = srsp*sy + crcy; + mT(3,2) = sr*cp; + + mT(1,3) = crcy*sp + sr*sy; + mT(2,3) = crsy*sp - sr*cy; + mT(3,3) = cr*cp; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGForce::SetAnglesToBody(double broll, double bpitch, double byaw) { - if (ttype == tCustom) - { - vOrient(ePitch) = bpitch; - vOrient(eRoll) = broll; - vOrient(eYaw) = byaw; + if (ttype == tCustom) { + vOrient(ePitch) = bpitch; + vOrient(eRoll) = broll; + vOrient(eYaw) = byaw; - UpdateCustomTransformMatrix(); - } + UpdateCustomTransformMatrix(); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -179,36 +173,28 @@ void FGForce::SetAnglesToBody(double broll, double bpitch, double byaw) void FGForce::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGForce" << endl; - if (from == 1) cout << "Destroyed: FGForce" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGForce" << endl; + if (from == 1) cout << "Destroyed: FGForce" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/propulsion/FGForce.h b/src/models/propulsion/FGForce.h index 49fe1e84f6d63c5ea0afe58c1d885e196dad754e..9ec0d30649ab725e0904bdadaceee545e9e7ea85 100644 --- a/src/models/propulsion/FGForce.h +++ b/src/models/propulsion/FGForce.h @@ -72,8 +72,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -226,208 +225,111 @@ CLASS DECLARATION class FGForce : public FGJSBBase { public: - /// Constructor - FGForce(FGFDMExec *FDMExec); - FGForce(const FGForce& force) - { - vFn = force.vFn; - vXYZn = force.vXYZn; - ttype = force.ttype; - fdmex = force.fdmex; - } - /// Destructor - ~FGForce(); - - enum TransformType { tNone, tWindBody, tLocalBody, tCustom }; - - virtual FGColumnVector3& GetBodyForces(void); - - inline double GetBodyXForce(void) const - { - return vFb(eX); - } - inline double GetBodyYForce(void) const - { - return vFb(eY); - } - inline double GetBodyZForce(void) const - { - return vFb(eZ); - } - inline FGColumnVector3& GetMoments(void) - { - return vM; - } - - // Normal point of application, JSBsim structural coords - // (inches, x +back, y +right, z +up) - inline void SetLocation(double x, double y, double z) - { - vXYZn(eX) = x; - vXYZn(eY) = y; - vXYZn(eZ) = z; - SetActingLocation(x, y, z); - } - - /** Acting point of application. - JSBsim structural coords used (inches, x +back, y +right, z +up). - This function sets the point at which the force acts - this may - not be the same as where the object resides. One area where this - is true is P-Factor modeling. - @param x acting location of force - @param y acting location of force - @param z acting location of force */ - inline void SetActingLocation(double x, double y, double z) - { - vActingXYZn(eX) = x; - vActingXYZn(eY) = y; - vActingXYZn(eZ) = z; - } - inline void SetLocationX(double x) - { - vXYZn(eX) = x; - vActingXYZn(eX) = x; - } - inline void SetLocationY(double y) - { - vXYZn(eY) = y; - vActingXYZn(eY) = y; - } - inline void SetLocationZ(double z) - { - vXYZn(eZ) = z; - vActingXYZn(eZ) = z; - } - inline double SetActingLocationX(double x) - { - vActingXYZn(eX) = x; - return x; - } - inline double SetActingLocationY(double y) - { - vActingXYZn(eY) = y; - return y; - } - inline double SetActingLocationZ(double z) - { - vActingXYZn(eZ) = z; - return z; - } - inline void SetLocation(FGColumnVector3 vv) - { - vXYZn = vv; - SetActingLocation(vv); - } - inline void SetActingLocation(FGColumnVector3 vv) - { - vActingXYZn = vv; - } - - inline double GetLocationX( void ) const - { - return vXYZn(eX); - } - inline double GetLocationY( void ) const - { - return vXYZn(eY); - } - inline double GetLocationZ( void ) const - { - return vXYZn(eZ); - } - inline double GetActingLocationX( void ) const - { - return vActingXYZn(eX); - } - inline double GetActingLocationY( void ) const - { - return vActingXYZn(eY); - } - inline double GetActingLocationZ( void ) const - { - return vActingXYZn(eZ); - } - FGColumnVector3& GetLocation(void) - { - return vXYZn; - } - FGColumnVector3& GetActingLocation(void) - { - return vActingXYZn; - } - - //these angles are relative to body axes, not earth!!!!! - //I'm using these because pitch, roll, and yaw are easy to visualize, - //there's no equivalent to roll in wind axes i.e. alpha, ? , beta - //making up new names or using these is a toss-up: either way people - //are going to get confused. - //They are in radians. - - void SetAnglesToBody(double broll, double bpitch, double byaw); - inline void SetAnglesToBody(FGColumnVector3 vv) - { - SetAnglesToBody(vv(eRoll), vv(ePitch), vv(eYaw)); - } - - void UpdateCustomTransformMatrix(void); - void SetPitch(double pitch) - { - vOrient(ePitch) = pitch; - UpdateCustomTransformMatrix(); - } - void SetYaw(double yaw) - { - vOrient(eYaw) = yaw; - UpdateCustomTransformMatrix(); - } - - double GetPitch(void) const - { - return vOrient(ePitch); - } - double GetYaw(void) const - { - return vOrient(eYaw); - } - - inline FGColumnVector3& GetAnglesToBody(void) - { - return vOrient; - } - inline double GetAnglesToBody(int axis) const - { - return vOrient(axis); - } - - inline void SetTransformType(TransformType ii) - { - ttype=ii; - } - inline TransformType GetTransformType(void) const - { - return ttype; - } - - FGMatrix33 Transform(void); + /// Constructor + FGForce(FGFDMExec *FDMExec); + FGForce(const FGForce& force) { + vFn = force.vFn; + vXYZn = force.vXYZn; + ttype = force.ttype; + fdmex = force.fdmex; + } + /// Destructor + ~FGForce(); + + enum TransformType { tNone, tWindBody, tLocalBody, tCustom }; + + virtual FGColumnVector3& GetBodyForces(void); + + inline double GetBodyXForce(void) const { return vFb(eX); } + inline double GetBodyYForce(void) const { return vFb(eY); } + inline double GetBodyZForce(void) const { return vFb(eZ); } + inline FGColumnVector3& GetMoments(void) { return vM; } + + // Normal point of application, JSBsim structural coords + // (inches, x +back, y +right, z +up) + inline void SetLocation(double x, double y, double z) { + vXYZn(eX) = x; + vXYZn(eY) = y; + vXYZn(eZ) = z; + SetActingLocation(x, y, z); + } + + /** Acting point of application. + JSBsim structural coords used (inches, x +back, y +right, z +up). + This function sets the point at which the force acts - this may + not be the same as where the object resides. One area where this + is true is P-Factor modeling. + @param x acting location of force + @param y acting location of force + @param z acting location of force */ + inline void SetActingLocation(double x, double y, double z) { + vActingXYZn(eX) = x; + vActingXYZn(eY) = y; + vActingXYZn(eZ) = z; + } + inline void SetLocationX(double x) {vXYZn(eX) = x; vActingXYZn(eX) = x;} + inline void SetLocationY(double y) {vXYZn(eY) = y; vActingXYZn(eY) = y;} + inline void SetLocationZ(double z) {vXYZn(eZ) = z; vActingXYZn(eZ) = z;} + inline double SetActingLocationX(double x) {vActingXYZn(eX) = x; return x;} + inline double SetActingLocationY(double y) {vActingXYZn(eY) = y; return y;} + inline double SetActingLocationZ(double z) {vActingXYZn(eZ) = z; return z;} + inline void SetLocation(FGColumnVector3 vv) { vXYZn = vv; SetActingLocation(vv);} + inline void SetActingLocation(FGColumnVector3 vv) { vActingXYZn = vv; } + + inline double GetLocationX( void ) const { return vXYZn(eX);} + inline double GetLocationY( void ) const { return vXYZn(eY);} + inline double GetLocationZ( void ) const { return vXYZn(eZ);} + inline double GetActingLocationX( void ) const { return vActingXYZn(eX);} + inline double GetActingLocationY( void ) const { return vActingXYZn(eY);} + inline double GetActingLocationZ( void ) const { return vActingXYZn(eZ);} + FGColumnVector3& GetLocation(void) { return vXYZn; } + FGColumnVector3& GetActingLocation(void) { return vActingXYZn; } + + //these angles are relative to body axes, not earth!!!!! + //I'm using these because pitch, roll, and yaw are easy to visualize, + //there's no equivalent to roll in wind axes i.e. alpha, ? , beta + //making up new names or using these is a toss-up: either way people + //are going to get confused. + //They are in radians. + + void SetAnglesToBody(double broll, double bpitch, double byaw); + inline void SetAnglesToBody(FGColumnVector3 vv) { + SetAnglesToBody(vv(eRoll), vv(ePitch), vv(eYaw)); + } + + void UpdateCustomTransformMatrix(void); + void SetPitch(double pitch) {vOrient(ePitch) = pitch; UpdateCustomTransformMatrix();} + void SetYaw(double yaw) {vOrient(eYaw) = yaw; UpdateCustomTransformMatrix();} + + double GetPitch(void) const {return vOrient(ePitch);} + double GetYaw(void) const {return vOrient(eYaw);} + + inline FGColumnVector3& GetAnglesToBody(void) {return vOrient;} + inline double GetAnglesToBody(int axis) const {return vOrient(axis);} + + inline void SetTransformType(TransformType ii) { ttype=ii; } + inline TransformType GetTransformType(void) const { return ttype; } + + FGMatrix33 Transform(void); protected: - FGFDMExec *fdmex; - FGColumnVector3 vFn; - FGColumnVector3 vMn; - FGColumnVector3 vH; - FGColumnVector3 vOrient; - TransformType ttype; - FGColumnVector3 vXYZn; - FGColumnVector3 vActingXYZn; + FGFDMExec *fdmex; + FGColumnVector3 vFn; + FGColumnVector3 vMn; + FGColumnVector3 vH; + FGColumnVector3 vOrient; + TransformType ttype; + FGColumnVector3 vXYZn; + FGColumnVector3 vActingXYZn; private: - FGColumnVector3 vFb; - FGColumnVector3 vM; - FGColumnVector3 vDXYZ; + FGColumnVector3 vFb; + FGColumnVector3 vM; + FGColumnVector3 vDXYZ; - FGMatrix33 mT; + FGMatrix33 mT; - void Debug(int from); + void Debug(int from); }; } #endif diff --git a/src/models/propulsion/FGNozzle.cpp b/src/models/propulsion/FGNozzle.cpp index 2fa92df58b3eccc09b5b1cc29467c86d970b89ea..f1d0fb12e1911e07bc223f71fbe70d41656c6bf2 100644 --- a/src/models/propulsion/FGNozzle.cpp +++ b/src/models/propulsion/FGNozzle.cpp @@ -45,8 +45,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGNozzle.cpp,v 1.13 2009/10/26 03:49:58 jberndt Exp $"; static const char *IdHdr = ID_NOZZLE; @@ -57,68 +56,67 @@ CLASS IMPLEMENTATION FGNozzle::FGNozzle(FGFDMExec* FDMExec, Element* nozzle_element, int num) - : FGThruster(FDMExec, nozzle_element, num) + : FGThruster(FDMExec, nozzle_element, num) { - if (nozzle_element->FindElement("area")) - Area = nozzle_element->FindElementValueAsNumberConvertTo("area", "FT2"); - else - { - cerr << "Fatal Error: Nozzle exit area must be given in nozzle config file." << endl; - exit(-1); - } - /* - if (nozzle_element->FindElement("pe")) - PE = nozzle_element->FindElementValueAsNumberConvertTo("pe", "PSF"); - else { - cerr << "Fatal Error: Nozzle exit pressure must be given in nozzle config file." << endl; - exit(-1); - } - */ - Thrust = 0; - Type = ttNozzle; - - Debug(0); + if (nozzle_element->FindElement("area")) + Area = nozzle_element->FindElementValueAsNumberConvertTo("area", "FT2"); + else { + cerr << "Fatal Error: Nozzle exit area must be given in nozzle config file." << endl; + exit(-1); + } +/* + if (nozzle_element->FindElement("pe")) + PE = nozzle_element->FindElementValueAsNumberConvertTo("pe", "PSF"); + else { + cerr << "Fatal Error: Nozzle exit pressure must be given in nozzle config file." << endl; + exit(-1); + } +*/ + Thrust = 0; + Type = ttNozzle; + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGNozzle::~FGNozzle() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGNozzle::Calculate(double vacThrust) { - double pAtm = fdmex->GetAtmosphere()->GetPressure(); - Thrust = max((double)0.0, vacThrust - pAtm*Area); + double pAtm = fdmex->GetAtmosphere()->GetPressure(); + Thrust = max((double)0.0, vacThrust - pAtm*Area); - vFn(1) = Thrust * cos(ReverserAngle); + vFn(1) = Thrust * cos(ReverserAngle); - return Thrust; + return Thrust; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGNozzle::GetThrusterLabels(int id, string delimeter) { - std::ostringstream buf; + std::ostringstream buf; - buf << Name << " Thrust (engine " << id << " in lbs)"; + buf << Name << " Thrust (engine " << id << " in lbs)"; - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGNozzle::GetThrusterValues(int id, string delimeter) { - std::ostringstream buf; + std::ostringstream buf; - buf << Thrust; + buf << Thrust; - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -142,37 +140,29 @@ string FGNozzle::GetThrusterValues(int id, string delimeter) void FGNozzle::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " Nozzle Name: " << Name << endl; - cout << " Nozzle Exit Area = " << Area << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGNozzle" << endl; - if (from == 1) cout << "Destroyed: FGNozzle" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " Nozzle Name: " << Name << endl; + cout << " Nozzle Exit Area = " << Area << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGNozzle" << endl; + if (from == 1) cout << "Destroyed: FGNozzle" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/propulsion/FGNozzle.h b/src/models/propulsion/FGNozzle.h index 5e39e7b99e972dfe5c6e88d7c103d2f8a2db6fb2..d2945ba7b677bf4020d3b9d90fd33850995221c7 100644 --- a/src/models/propulsion/FGNozzle.h +++ b/src/models/propulsion/FGNozzle.h @@ -50,14 +50,13 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -/** Models a rocket nozzle. +/** Models a rocket nozzle. <h3>Configuration File Format:</h3> @@ -74,7 +73,7 @@ CLASS DOCUMENTATION <b>area</b> - Nozzle area at the exit plane. </pre> - All parameters MUST be specified. + All parameters MUST be specified. @author Jon S. Berndt @version $Id: FGNozzle.h,v 1.8 2009/10/26 03:49:58 jberndt Exp $ */ @@ -83,23 +82,22 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGNozzle : public FGThruster -{ +class FGNozzle : public FGThruster { public: - /// Constructor - FGNozzle(FGFDMExec* exec, Element* el, int num = 0); - /// Destructor - ~FGNozzle(); + /// Constructor + FGNozzle(FGFDMExec* exec, Element* el, int num = 0); + /// Destructor + ~FGNozzle(); - double Calculate(double vacThrust); - string GetThrusterLabels(int id, string delimeter); - string GetThrusterValues(int id, string delimeter); + double Calculate(double vacThrust); + string GetThrusterLabels(int id, string delimeter); + string GetThrusterValues(int id, string delimeter); private: // double PE; - double Area; - void Debug(int from); + double Area; + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/propulsion/FGPiston.cpp b/src/models/propulsion/FGPiston.cpp index 60647fa26c8a48ea6fe610e411ae62b8f4348119..b225563c2e0a4516da20e9483e2afdd05eb3d193 100644 --- a/src/models/propulsion/FGPiston.cpp +++ b/src/models/propulsion/FGPiston.cpp @@ -51,10 +51,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGPiston.cpp,v 1.52 2010/06/05 12:12:34 jberndt Exp $"; +static const char *IdSrc = "$Id: FGPiston.cpp,v 1.53 2010/08/21 17:13:48 jberndt Exp $"; static const char *IdHdr = ID_PISTON; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -62,419 +61,405 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number) - : FGEngine(exec, el, engine_number), - R_air(287.3), // Gas constant for air J/Kg/K - rho_fuel(800), // estimate - calorific_value_fuel(47.3e6), - Cp_air(1005), // Specific heat (constant pressure) J/Kg/K - Cp_fuel(1700), - standard_pressure(101320.73) + : FGEngine(exec, el, engine_number), + R_air(287.3), // Gas constant for air J/Kg/K + rho_fuel(800), // estimate + calorific_value_fuel(47.3e6), + Cp_air(1005), // Specific heat (constant pressure) J/Kg/K + Cp_fuel(1700), + standard_pressure(101320.73) { - string token; - - // Defaults and initializations - - Type = etPiston; - dt = FDMExec->GetDeltaT(); - - // These items are read from the configuration file - // Defaults are from a Lycoming O-360, more or less - - Cycles = 4; - IdleRPM = 600; - MaxRPM = 2800; - Displacement = 360; - SparkFailDrop = 1.0; - MaxHP = 200; - MinManifoldPressure_inHg = 6.5; - MaxManifoldPressure_inHg = 28.5; - ISFC = -1; - volumetric_efficiency = 0.85; - Bore = 5.125; - Stroke = 4.375; - Cylinders = 4; - CompressionRatio = 8.5; - Z_airbox = -999; - Ram_Air_Factor = 1; - PeakMeanPistonSpeed_fps = 100; - FMEPDynamic= 18400; - FMEPStatic = 46500; - - - // These are internal program variables - - crank_counter = 0; - Magnetos = 0; - minMAP = 21950; - maxMAP = 96250; + string token; + + // Defaults and initializations + + Type = etPiston; + dt = FDMExec->GetDeltaT(); + + // These items are read from the configuration file + // Defaults are from a Lycoming O-360, more or less + + Cycles = 4; + IdleRPM = 600; + MaxRPM = 2800; + Displacement = 360; + SparkFailDrop = 1.0; + MaxHP = 200; + MinManifoldPressure_inHg = 6.5; + MaxManifoldPressure_inHg = 28.5; + ISFC = -1; + volumetric_efficiency = 0.85; + Bore = 5.125; + Stroke = 4.375; + Cylinders = 4; + CompressionRatio = 8.5; + Z_airbox = -999; + Ram_Air_Factor = 1; + PeakMeanPistonSpeed_fps = 100; + FMEPDynamic= 18400; + FMEPStatic = 46500; + + + // These are internal program variables + + crank_counter = 0; + Magnetos = 0; + minMAP = 21950; + maxMAP = 96250; + + ResetToIC(); + + // Supercharging + BoostSpeeds = 0; // Default to no supercharging + BoostSpeed = 0; + Boosted = false; + BoostOverride = 0; + BoostManual = 0; + bBoostOverride = false; + bTakeoffBoost = false; + TakeoffBoost = 0.0; // Default to no extra takeoff-boost + int i; + for (i=0; i<FG_MAX_BOOST_SPEEDS; i++) { + RatedBoost[i] = 0.0; + RatedPower[i] = 0.0; + RatedAltitude[i] = 0.0; + BoostMul[i] = 1.0; + RatedMAP[i] = 100000; + RatedRPM[i] = 2500; + TakeoffMAP[i] = 100000; + } + for (i=0; i<FG_MAX_BOOST_SPEEDS-1; i++) { + BoostSwitchAltitude[i] = 0.0; + BoostSwitchPressure[i] = 0.0; + } + + // First column is thi, second is neta (combustion efficiency) + Lookup_Combustion_Efficiency = new FGTable(12); + *Lookup_Combustion_Efficiency << 0.00 << 0.980; + *Lookup_Combustion_Efficiency << 0.90 << 0.980; + *Lookup_Combustion_Efficiency << 1.00 << 0.970; + *Lookup_Combustion_Efficiency << 1.05 << 0.950; + *Lookup_Combustion_Efficiency << 1.10 << 0.900; + *Lookup_Combustion_Efficiency << 1.15 << 0.850; + *Lookup_Combustion_Efficiency << 1.20 << 0.790; + *Lookup_Combustion_Efficiency << 1.30 << 0.700; + *Lookup_Combustion_Efficiency << 1.40 << 0.630; + *Lookup_Combustion_Efficiency << 1.50 << 0.570; + *Lookup_Combustion_Efficiency << 1.60 << 0.525; + *Lookup_Combustion_Efficiency << 2.00 << 0.345; + + Mixture_Efficiency_Correlation = new FGTable(15); + *Mixture_Efficiency_Correlation << 0.05000 << 0.00000; + *Mixture_Efficiency_Correlation << 0.05137 << 0.00862; + *Mixture_Efficiency_Correlation << 0.05179 << 0.21552; + *Mixture_Efficiency_Correlation << 0.05430 << 0.48276; + *Mixture_Efficiency_Correlation << 0.05842 << 0.70690; + *Mixture_Efficiency_Correlation << 0.06312 << 0.83621; + *Mixture_Efficiency_Correlation << 0.06942 << 0.93103; + *Mixture_Efficiency_Correlation << 0.07786 << 1.00000; + *Mixture_Efficiency_Correlation << 0.08845 << 1.00000; + *Mixture_Efficiency_Correlation << 0.09270 << 0.98276; + *Mixture_Efficiency_Correlation << 0.10120 << 0.93103; + *Mixture_Efficiency_Correlation << 0.11455 << 0.72414; + *Mixture_Efficiency_Correlation << 0.12158 << 0.45690; + *Mixture_Efficiency_Correlation << 0.12435 << 0.23276; + *Mixture_Efficiency_Correlation << 0.12500 << 0.00000; + + + // Read inputs from engine data file where present. + + if (el->FindElement("minmp")) // Should have ELSE statement telling default value used? + MinManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("minmp","INHG"); + if (el->FindElement("maxmp")) + MaxManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("maxmp","INHG"); + if (el->FindElement("displacement")) + Displacement = el->FindElementValueAsNumberConvertTo("displacement","IN3"); + if (el->FindElement("maxhp")) + MaxHP = el->FindElementValueAsNumberConvertTo("maxhp","HP"); + if (el->FindElement("sparkfaildrop")) + SparkFailDrop = Constrain(0, 1 - el->FindElementValueAsNumber("sparkfaildrop"), 1); + if (el->FindElement("cycles")) + Cycles = el->FindElementValueAsNumber("cycles"); + if (el->FindElement("idlerpm")) + IdleRPM = el->FindElementValueAsNumber("idlerpm"); + if (el->FindElement("maxrpm")) + MaxRPM = el->FindElementValueAsNumber("maxrpm"); + if (el->FindElement("maxthrottle")) + MaxThrottle = el->FindElementValueAsNumber("maxthrottle"); + if (el->FindElement("minthrottle")) + MinThrottle = el->FindElementValueAsNumber("minthrottle"); + if (el->FindElement("bsfc")) + ISFC = el->FindElementValueAsNumberConvertTo("bsfc", "LBS/HP*HR"); + if (el->FindElement("volumetric-efficiency")) + volumetric_efficiency = el->FindElementValueAsNumber("volumetric-efficiency"); + if (el->FindElement("compression-ratio")) + CompressionRatio = el->FindElementValueAsNumber("compression-ratio"); + if (el->FindElement("bore")) + Bore = el->FindElementValueAsNumberConvertTo("bore","IN"); + if (el->FindElement("stroke")) + Stroke = el->FindElementValueAsNumberConvertTo("stroke","IN"); + if (el->FindElement("cylinders")) + Cylinders = el->FindElementValueAsNumber("cylinders"); + if (el->FindElement("air-intake-impedance-factor")) + Z_airbox = el->FindElementValueAsNumber("air-intake-impedance-factor"); + if (el->FindElement("ram-air-factor")) + Ram_Air_Factor = el->FindElementValueAsNumber("ram-air-factor"); + if (el->FindElement("dynamic-fmep")) + FMEPDynamic= el->FindElementValueAsNumberConvertTo("dynamic-fmep","PA"); + if (el->FindElement("static-fmep")) + FMEPStatic = el->FindElementValueAsNumberConvertTo("static-fmep","PA"); + if (el->FindElement("peak-piston-speed")) + PeakMeanPistonSpeed_fps = el->FindElementValueAsNumber("peak-piston-speed"); + if (el->FindElement("numboostspeeds")) { // Turbo- and super-charging parameters + BoostSpeeds = (int)el->FindElementValueAsNumber("numboostspeeds"); + if (el->FindElement("boostoverride")) + BoostOverride = (int)el->FindElementValueAsNumber("boostoverride"); + if (el->FindElement("boostmanual")) + BoostManual = (int)el->FindElementValueAsNumber("boostmanual"); + if (el->FindElement("takeoffboost")) + TakeoffBoost = el->FindElementValueAsNumberConvertTo("takeoffboost", "PSI"); + if (el->FindElement("ratedboost1")) + RatedBoost[0] = el->FindElementValueAsNumberConvertTo("ratedboost1", "PSI"); + if (el->FindElement("ratedboost2")) + RatedBoost[1] = el->FindElementValueAsNumberConvertTo("ratedboost2", "PSI"); + if (el->FindElement("ratedboost3")) + RatedBoost[2] = el->FindElementValueAsNumberConvertTo("ratedboost3", "PSI"); + if (el->FindElement("ratedpower1")) + RatedPower[0] = el->FindElementValueAsNumberConvertTo("ratedpower1", "HP"); + if (el->FindElement("ratedpower2")) + RatedPower[1] = el->FindElementValueAsNumberConvertTo("ratedpower2", "HP"); + if (el->FindElement("ratedpower3")) + RatedPower[2] = el->FindElementValueAsNumberConvertTo("ratedpower3", "HP"); + if (el->FindElement("ratedrpm1")) + RatedRPM[0] = el->FindElementValueAsNumber("ratedrpm1"); + if (el->FindElement("ratedrpm2")) + RatedRPM[1] = el->FindElementValueAsNumber("ratedrpm2"); + if (el->FindElement("ratedrpm3")) + RatedRPM[2] = el->FindElementValueAsNumber("ratedrpm3"); + if (el->FindElement("ratedaltitude1")) + RatedAltitude[0] = el->FindElementValueAsNumberConvertTo("ratedaltitude1", "FT"); + if (el->FindElement("ratedaltitude2")) + RatedAltitude[1] = el->FindElementValueAsNumberConvertTo("ratedaltitude2", "FT"); + if (el->FindElement("ratedaltitude3")) + RatedAltitude[2] = el->FindElementValueAsNumberConvertTo("ratedaltitude3", "FT"); + } + + StarterHP = sqrt(MaxHP) * 0.4; + displacement_SI = Displacement * in3tom3; + RatedMeanPistonSpeed_fps = ( MaxRPM * Stroke) / (360); // AKA 2 * (RPM/60) * ( Stroke / 12) or 2NS + + // Create IFSC to match the engine if not provided + if (ISFC < 0) { + double pmep = 29.92 - MaxManifoldPressure_inHg; + pmep *= inhgtopa * volumetric_efficiency; + double fmep = (FMEPDynamic * RatedMeanPistonSpeed_fps * fttom + FMEPStatic); + double hp_loss = ((pmep + fmep) * displacement_SI * MaxRPM)/(Cycles*22371); + ISFC = ( 1.1*Displacement * MaxRPM * volumetric_efficiency *(MaxManifoldPressure_inHg / 29.92) ) / (9411 * (MaxHP+hp_loss)); +// cout <<"FMEP: "<< fmep <<" PMEP: "<< pmep << " hp_loss: " <<hp_loss <<endl; + } + if ( MaxManifoldPressure_inHg > 29.9 ) { // Don't allow boosting with a bogus number + MaxManifoldPressure_inHg = 29.9; + } + minMAP = MinManifoldPressure_inHg * inhgtopa; // inHg to Pa + maxMAP = MaxManifoldPressure_inHg * inhgtopa; - ResetToIC(); +// For throttle +/* + * Pm = ( Ze / ( Ze + Zi + Zt ) ) * Pa + * Where: + * Pm = Manifold Pressure + * Pa = Ambient Pressre + * Ze = engine impedance, Ze is effectively 1 / Mean Piston Speed + * Zi = airbox impedance + * Zt = throttle impedance + * + * For the calculation below throttle is fully open or Zt = 0 + * + * + * + */ - // Supercharging - BoostSpeeds = 0; // Default to no supercharging - BoostSpeed = 0; - Boosted = false; - BoostOverride = 0; - BoostManual = 0; - bBoostOverride = false; - bTakeoffBoost = false; - TakeoffBoost = 0.0; // Default to no extra takeoff-boost - int i; - for (i=0; i<FG_MAX_BOOST_SPEEDS; i++) - { - RatedBoost[i] = 0.0; - RatedPower[i] = 0.0; - RatedAltitude[i] = 0.0; - BoostMul[i] = 1.0; - RatedMAP[i] = 100000; - RatedRPM[i] = 2500; - TakeoffMAP[i] = 100000; + if(Z_airbox < 0.0){ + double Ze=PeakMeanPistonSpeed_fps/RatedMeanPistonSpeed_fps; // engine impedence + Z_airbox = (standard_pressure *Ze / maxMAP) - Ze; // impedence of airbox + } + // Constant for Throttle impedence + Z_throttle=(PeakMeanPistonSpeed_fps/((IdleRPM * Stroke) / 360))*(standard_pressure/minMAP - 1) - Z_airbox; + // Z_throttle=(MaxRPM/IdleRPM )*(standard_pressure/minMAP+2); // Constant for Throttle impedence + + string property_name, base_property_name; + base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); + property_name = base_property_name + "/power-hp"; + PropertyManager->Tie(property_name, &HP); + property_name = base_property_name + "/bsfc-lbs_hphr"; + PropertyManager->Tie(property_name, &ISFC); + property_name = base_property_name + "/volumetric-efficiency"; + PropertyManager->Tie(property_name, &volumetric_efficiency); + property_name = base_property_name + "/map-pa"; + PropertyManager->Tie(property_name, &MAP); + property_name = base_property_name + "/map-inhg"; + PropertyManager->Tie(property_name, &ManifoldPressure_inHg); + property_name = base_property_name + "/air-intake-impedance-factor"; + PropertyManager->Tie(property_name, &Z_airbox); + property_name = base_property_name + "/ram-air-factor"; + PropertyManager->Tie(property_name, &Ram_Air_Factor); + property_name = base_property_name + "/boost-speed"; + PropertyManager->Tie(property_name, &BoostSpeed); + + // Set up and sanity-check the turbo/supercharging configuration based on the input values. + if (TakeoffBoost > RatedBoost[0]) bTakeoffBoost = true; + for (i=0; i<BoostSpeeds; ++i) { + bool bad = false; + if (RatedBoost[i] <= 0.0) bad = true; + if (RatedPower[i] <= 0.0) bad = true; + if (RatedAltitude[i] < 0.0) bad = true; // 0.0 is deliberately allowed - this corresponds to unregulated supercharging. + if (i > 0 && RatedAltitude[i] < RatedAltitude[i - 1]) bad = true; + if (bad) { + // We can't recover from the above - don't use this supercharger speed. + BoostSpeeds--; + // TODO - put out a massive error message! + break; } - for (i=0; i<FG_MAX_BOOST_SPEEDS-1; i++) - { - BoostSwitchAltitude[i] = 0.0; - BoostSwitchPressure[i] = 0.0; + // Now sanity-check stuff that is recoverable. + if (i < BoostSpeeds - 1) { + if (BoostSwitchAltitude[i] < RatedAltitude[i]) { + // TODO - put out an error message + // But we can also make a reasonable estimate, as below. + BoostSwitchAltitude[i] = RatedAltitude[i] + 1000; + } + BoostSwitchPressure[i] = Atmosphere->GetPressure(BoostSwitchAltitude[i]) * psftopa; + //cout << "BoostSwitchAlt = " << BoostSwitchAltitude[i] << ", pressure = " << BoostSwitchPressure[i] << '\n'; + // Assume there is some hysteresis on the supercharger gear switch, and guess the value for now + BoostSwitchHysteresis = 1000; } - - // First column is thi, second is neta (combustion efficiency) - Lookup_Combustion_Efficiency = new FGTable(12); - *Lookup_Combustion_Efficiency << 0.00 << 0.980; - *Lookup_Combustion_Efficiency << 0.90 << 0.980; - *Lookup_Combustion_Efficiency << 1.00 << 0.970; - *Lookup_Combustion_Efficiency << 1.05 << 0.950; - *Lookup_Combustion_Efficiency << 1.10 << 0.900; - *Lookup_Combustion_Efficiency << 1.15 << 0.850; - *Lookup_Combustion_Efficiency << 1.20 << 0.790; - *Lookup_Combustion_Efficiency << 1.30 << 0.700; - *Lookup_Combustion_Efficiency << 1.40 << 0.630; - *Lookup_Combustion_Efficiency << 1.50 << 0.570; - *Lookup_Combustion_Efficiency << 1.60 << 0.525; - *Lookup_Combustion_Efficiency << 2.00 << 0.345; - - Mixture_Efficiency_Correlation = new FGTable(15); - *Mixture_Efficiency_Correlation << 0.05000 << 0.00000; - *Mixture_Efficiency_Correlation << 0.05137 << 0.00862; - *Mixture_Efficiency_Correlation << 0.05179 << 0.21552; - *Mixture_Efficiency_Correlation << 0.05430 << 0.48276; - *Mixture_Efficiency_Correlation << 0.05842 << 0.70690; - *Mixture_Efficiency_Correlation << 0.06312 << 0.83621; - *Mixture_Efficiency_Correlation << 0.06942 << 0.93103; - *Mixture_Efficiency_Correlation << 0.07786 << 1.00000; - *Mixture_Efficiency_Correlation << 0.08845 << 1.00000; - *Mixture_Efficiency_Correlation << 0.09270 << 0.98276; - *Mixture_Efficiency_Correlation << 0.10120 << 0.93103; - *Mixture_Efficiency_Correlation << 0.11455 << 0.72414; - *Mixture_Efficiency_Correlation << 0.12158 << 0.45690; - *Mixture_Efficiency_Correlation << 0.12435 << 0.23276; - *Mixture_Efficiency_Correlation << 0.12500 << 0.00000; - - - // Read inputs from engine data file where present. - - if (el->FindElement("minmp")) // Should have ELSE statement telling default value used? - MinManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("minmp","INHG"); - if (el->FindElement("maxmp")) - MaxManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("maxmp","INHG"); - if (el->FindElement("displacement")) - Displacement = el->FindElementValueAsNumberConvertTo("displacement","IN3"); - if (el->FindElement("maxhp")) - MaxHP = el->FindElementValueAsNumberConvertTo("maxhp","HP"); - if (el->FindElement("sparkfaildrop")) - SparkFailDrop = Constrain(0, 1 - el->FindElementValueAsNumber("sparkfaildrop"), 1); - if (el->FindElement("cycles")) - Cycles = el->FindElementValueAsNumber("cycles"); - if (el->FindElement("idlerpm")) - IdleRPM = el->FindElementValueAsNumber("idlerpm"); - if (el->FindElement("maxrpm")) - MaxRPM = el->FindElementValueAsNumber("maxrpm"); - if (el->FindElement("maxthrottle")) - MaxThrottle = el->FindElementValueAsNumber("maxthrottle"); - if (el->FindElement("minthrottle")) - MinThrottle = el->FindElementValueAsNumber("minthrottle"); - if (el->FindElement("bsfc")) - ISFC = el->FindElementValueAsNumberConvertTo("bsfc", "LBS/HP*HR"); - if (el->FindElement("volumetric-efficiency")) - volumetric_efficiency = el->FindElementValueAsNumber("volumetric-efficiency"); - if (el->FindElement("compression-ratio")) - CompressionRatio = el->FindElementValueAsNumber("compression-ratio"); - if (el->FindElement("bore")) - Bore = el->FindElementValueAsNumberConvertTo("bore","IN"); - if (el->FindElement("stroke")) - Stroke = el->FindElementValueAsNumberConvertTo("stroke","IN"); - if (el->FindElement("cylinders")) - Cylinders = el->FindElementValueAsNumber("cylinders"); - if (el->FindElement("air-intake-impedance-factor")) - Z_airbox = el->FindElementValueAsNumber("air-intake-impedance-factor"); - if (el->FindElement("ram-air-factor")) - Ram_Air_Factor = el->FindElementValueAsNumber("ram-air-factor"); - if (el->FindElement("dynamic-fmep")) - FMEPDynamic= el->FindElementValueAsNumberConvertTo("dynamic-fmep","PA"); - if (el->FindElement("static-fmep")) - FMEPStatic = el->FindElementValueAsNumberConvertTo("static-fmep","PA"); - if (el->FindElement("peak-piston-speed")) - PeakMeanPistonSpeed_fps = el->FindElementValueAsNumber("peak-piston-speed"); - if (el->FindElement("numboostspeeds")) // Turbo- and super-charging parameters - { - BoostSpeeds = (int)el->FindElementValueAsNumber("numboostspeeds"); - if (el->FindElement("boostoverride")) - BoostOverride = (int)el->FindElementValueAsNumber("boostoverride"); - if (el->FindElement("boostmanual")) - BoostManual = (int)el->FindElementValueAsNumber("boostmanual"); - if (el->FindElement("takeoffboost")) - TakeoffBoost = el->FindElementValueAsNumberConvertTo("takeoffboost", "PSI"); - if (el->FindElement("ratedboost1")) - RatedBoost[0] = el->FindElementValueAsNumberConvertTo("ratedboost1", "PSI"); - if (el->FindElement("ratedboost2")) - RatedBoost[1] = el->FindElementValueAsNumberConvertTo("ratedboost2", "PSI"); - if (el->FindElement("ratedboost3")) - RatedBoost[2] = el->FindElementValueAsNumberConvertTo("ratedboost3", "PSI"); - if (el->FindElement("ratedpower1")) - RatedPower[0] = el->FindElementValueAsNumberConvertTo("ratedpower1", "HP"); - if (el->FindElement("ratedpower2")) - RatedPower[1] = el->FindElementValueAsNumberConvertTo("ratedpower2", "HP"); - if (el->FindElement("ratedpower3")) - RatedPower[2] = el->FindElementValueAsNumberConvertTo("ratedpower3", "HP"); - if (el->FindElement("ratedrpm1")) - RatedRPM[0] = el->FindElementValueAsNumber("ratedrpm1"); - if (el->FindElement("ratedrpm2")) - RatedRPM[1] = el->FindElementValueAsNumber("ratedrpm2"); - if (el->FindElement("ratedrpm3")) - RatedRPM[2] = el->FindElementValueAsNumber("ratedrpm3"); - if (el->FindElement("ratedaltitude1")) - RatedAltitude[0] = el->FindElementValueAsNumberConvertTo("ratedaltitude1", "FT"); - if (el->FindElement("ratedaltitude2")) - RatedAltitude[1] = el->FindElementValueAsNumberConvertTo("ratedaltitude2", "FT"); - if (el->FindElement("ratedaltitude3")) - RatedAltitude[2] = el->FindElementValueAsNumberConvertTo("ratedaltitude3", "FT"); + // Now work out the supercharger pressure multiplier of this speed from the rated boost and altitude. + RatedMAP[i] = Atmosphere->GetPressureSL() * psftopa + RatedBoost[i] * 6895; // psi*6895 = Pa. + // Sometimes a separate BCV setting for takeoff or extra power is fitted. + if (TakeoffBoost > RatedBoost[0]) { + // Assume that the effect on the BCV is the same whichever speed is in use. + TakeoffMAP[i] = RatedMAP[i] + ((TakeoffBoost - RatedBoost[0]) * 6895); + bTakeoffBoost = true; + } else { + TakeoffMAP[i] = RatedMAP[i]; + bTakeoffBoost = false; } + BoostMul[i] = RatedMAP[i] / (Atmosphere->GetPressure(RatedAltitude[i]) * psftopa); - StarterHP = sqrt(MaxHP) * 0.4; - displacement_SI = Displacement * in3tom3; - RatedMeanPistonSpeed_fps = ( MaxRPM * Stroke) / (360); // AKA 2 * (RPM/60) * ( Stroke / 12) or 2NS - - // Create IFSC to match the engine if not provided - if (ISFC < 0) - { - double pmep = 29.92 - MaxManifoldPressure_inHg; - pmep *= inhgtopa * volumetric_efficiency; - double fmep = (FMEPDynamic * RatedMeanPistonSpeed_fps * fttom + FMEPStatic); - double hp_loss = ((pmep + fmep) * displacement_SI * MaxRPM)/(Cycles*22371); - ISFC = ( 1.1*Displacement * MaxRPM * volumetric_efficiency *(MaxManifoldPressure_inHg / 29.92) ) / (9411 * (MaxHP+hp_loss)); -// cout <<"FMEP: "<< fmep <<" PMEP: "<< pmep << " hp_loss: " <<hp_loss <<endl; - } - if ( MaxManifoldPressure_inHg > 29.9 ) // Don't allow boosting with a bogus number - { - MaxManifoldPressure_inHg = 29.9; - } - minMAP = MinManifoldPressure_inHg * inhgtopa; // inHg to Pa - maxMAP = MaxManifoldPressure_inHg * inhgtopa; + } -// For throttle - /* - * Pm = ( Ze / ( Ze + Zi + Zt ) ) * Pa - * Where: - * Pm = Manifold Pressure - * Pa = Ambient Pressre - * Ze = engine impedance, Ze is effectively 1 / Mean Piston Speed - * Zi = airbox impedance - * Zt = throttle impedance - * - * For the calculation below throttle is fully open or Zt = 0 - * - * - * - */ - - if (Z_airbox < 0.0) - { - double Ze=PeakMeanPistonSpeed_fps/RatedMeanPistonSpeed_fps; // engine impedence - Z_airbox = (standard_pressure *Ze / maxMAP) - Ze; // impedence of airbox - } - // Constant for Throttle impedence - Z_throttle=(PeakMeanPistonSpeed_fps/((IdleRPM * Stroke) / 360))*(standard_pressure/minMAP - 1) - Z_airbox; - // Z_throttle=(MaxRPM/IdleRPM )*(standard_pressure/minMAP+2); // Constant for Throttle impedence - - string property_name, base_property_name; - base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); - property_name = base_property_name + "/power-hp"; - PropertyManager->Tie(property_name, &HP); - property_name = base_property_name + "/bsfc-lbs_hphr"; - PropertyManager->Tie(property_name, &ISFC); - property_name = base_property_name + "/volumetric-efficiency"; - PropertyManager->Tie(property_name, &volumetric_efficiency); - property_name = base_property_name + "/map-pa"; - PropertyManager->Tie(property_name, &MAP); - property_name = base_property_name + "/map-inhg"; - PropertyManager->Tie(property_name, &ManifoldPressure_inHg); - property_name = base_property_name + "/air-intake-impedance-factor"; - PropertyManager->Tie(property_name, &Z_airbox); - property_name = base_property_name + "/ram-air-factor"; - PropertyManager->Tie(property_name, &Ram_Air_Factor); - property_name = base_property_name + "/boost-speed"; - PropertyManager->Tie(property_name, &BoostSpeed); - - // Set up and sanity-check the turbo/supercharging configuration based on the input values. - if (TakeoffBoost > RatedBoost[0]) bTakeoffBoost = true; - for (i=0; i<BoostSpeeds; ++i) - { - bool bad = false; - if (RatedBoost[i] <= 0.0) bad = true; - if (RatedPower[i] <= 0.0) bad = true; - if (RatedAltitude[i] < 0.0) bad = true; // 0.0 is deliberately allowed - this corresponds to unregulated supercharging. - if (i > 0 && RatedAltitude[i] < RatedAltitude[i - 1]) bad = true; - if (bad) - { - // We can't recover from the above - don't use this supercharger speed. - BoostSpeeds--; - // TODO - put out a massive error message! - break; - } - // Now sanity-check stuff that is recoverable. - if (i < BoostSpeeds - 1) - { - if (BoostSwitchAltitude[i] < RatedAltitude[i]) - { - // TODO - put out an error message - // But we can also make a reasonable estimate, as below. - BoostSwitchAltitude[i] = RatedAltitude[i] + 1000; - } - BoostSwitchPressure[i] = Atmosphere->GetPressure(BoostSwitchAltitude[i]) * psftopa; - //cout << "BoostSwitchAlt = " << BoostSwitchAltitude[i] << ", pressure = " << BoostSwitchPressure[i] << '\n'; - // Assume there is some hysteresis on the supercharger gear switch, and guess the value for now - BoostSwitchHysteresis = 1000; - } - // Now work out the supercharger pressure multiplier of this speed from the rated boost and altitude. - RatedMAP[i] = Atmosphere->GetPressureSL() * psftopa + RatedBoost[i] * 6895; // psi*6895 = Pa. - // Sometimes a separate BCV setting for takeoff or extra power is fitted. - if (TakeoffBoost > RatedBoost[0]) - { - // Assume that the effect on the BCV is the same whichever speed is in use. - TakeoffMAP[i] = RatedMAP[i] + ((TakeoffBoost - RatedBoost[0]) * 6895); - bTakeoffBoost = true; - } - else - { - TakeoffMAP[i] = RatedMAP[i]; - bTakeoffBoost = false; - } - BoostMul[i] = RatedMAP[i] / (Atmosphere->GetPressure(RatedAltitude[i]) * psftopa); - - } - - if (BoostSpeeds > 0) - { - Boosted = true; - BoostSpeed = 0; - } - bBoostOverride = (BoostOverride == 1 ? true : false); - bBoostManual = (BoostManual == 1 ? true : false); - Debug(0); // Call Debug() routine from constructor if needed + if (BoostSpeeds > 0) { + Boosted = true; + BoostSpeed = 0; + } + bBoostOverride = (BoostOverride == 1 ? true : false); + bBoostManual = (BoostManual == 1 ? true : false); + Debug(0); // Call Debug() routine from constructor if needed } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGPiston::~FGPiston() { - delete Lookup_Combustion_Efficiency; - delete Mixture_Efficiency_Correlation; - Debug(1); // Call Debug() routine from constructor if needed + delete Lookup_Combustion_Efficiency; + delete Mixture_Efficiency_Correlation; + Debug(1); // Call Debug() routine from constructor if needed } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPiston::ResetToIC(void) { - FGEngine::ResetToIC(); - - ManifoldPressure_inHg = Atmosphere->GetPressure() * psftoinhg; // psf to in Hg - MAP = Atmosphere->GetPressure() * psftopa; - TMAP = MAP; - double airTemperature_degK = RankineToKelvin(Atmosphere->GetTemperature()); - OilTemp_degK = airTemperature_degK; - CylinderHeadTemp_degK = airTemperature_degK; - ExhaustGasTemp_degK = airTemperature_degK; - EGT_degC = ExhaustGasTemp_degK - 273; - Thruster->SetRPM(0.0); - RPM = 0.0; - OilPressure_psi = 0.0; + FGEngine::ResetToIC(); + + ManifoldPressure_inHg = Atmosphere->GetPressure() * psftoinhg; // psf to in Hg + MAP = Atmosphere->GetPressure() * psftopa; + TMAP = MAP; + double airTemperature_degK = RankineToKelvin(Atmosphere->GetTemperature()); + OilTemp_degK = airTemperature_degK; + CylinderHeadTemp_degK = airTemperature_degK; + ExhaustGasTemp_degK = airTemperature_degK; + EGT_degC = ExhaustGasTemp_degK - 273; + Thruster->SetRPM(0.0); + RPM = 0.0; + OilPressure_psi = 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -double FGPiston::Calculate(void) +void FGPiston::Calculate(void) { - if (FuelFlow_gph > 0.0) ConsumeFuel(); - - Throttle = FCS->GetThrottlePos(EngineNumber); - Mixture = FCS->GetMixturePos(EngineNumber); - - // - // Input values. - // - - p_amb = Atmosphere->GetPressure() * psftopa; - double p = Auxiliary->GetTotalPressure() * psftopa; - p_ram = (p - p_amb) * Ram_Air_Factor + p_amb; - T_amb = RankineToKelvin(Atmosphere->GetTemperature()); - - RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); - MeanPistonSpeed_fps = ( RPM * Stroke) / (360); // AKA 2 * (RPM/60) * ( Stroke / 12) or 2NS - - IAS = Auxiliary->GetVcalibratedKTS(); - - doEngineStartup(); - if (Boosted) doBoostControl(); - doMAP(); - doAirFlow(); - doFuelFlow(); - - //Now that the fuel flow is done check if the mixture is too lean to run the engine - //Assume lean limit at 22 AFR for now - thats a thi of 0.668 - //This might be a bit generous, but since there's currently no audiable warning of impending - //cutout in the form of misfiring and/or rough running its probably reasonable for now. -// if (equivalence_ratio < 0.668) -// Running = false; - - doEnginePower(); - if (IndicatedHorsePower < 0.1250) Running = false; - - doEGT(); - doCHT(); - doOilTemperature(); - doOilPressure(); - - if (Thruster->GetType() == FGThruster::ttPropeller) - { - ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber)); - ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber)); - } + RunPreFunctions(); + + if (FuelFlow_gph > 0.0) ConsumeFuel(); + + Throttle = FCS->GetThrottlePos(EngineNumber); + Mixture = FCS->GetMixturePos(EngineNumber); + + // Input values. + + p_amb = Atmosphere->GetPressure() * psftopa; + double p = Auxiliary->GetTotalPressure() * psftopa; + p_ram = (p - p_amb) * Ram_Air_Factor + p_amb; + T_amb = RankineToKelvin(Atmosphere->GetTemperature()); + + RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); + MeanPistonSpeed_fps = ( RPM * Stroke) / (360); // AKA 2 * (RPM/60) * ( Stroke / 12) or 2NS + + IAS = Auxiliary->GetVcalibratedKTS(); + + doEngineStartup(); + if (Boosted) doBoostControl(); + doMAP(); + doAirFlow(); + doFuelFlow(); + + //Now that the fuel flow is done check if the mixture is too lean to run the engine + //Assume lean limit at 22 AFR for now - thats a thi of 0.668 + //This might be a bit generous, but since there's currently no audiable warning of impending + //cutout in the form of misfiring and/or rough running its probably reasonable for now. - PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired(); + // if (equivalence_ratio < 0.668) + // Running = false; - return Thruster->Calculate(PowerAvailable); + doEnginePower(); + if (IndicatedHorsePower < 0.1250) Running = false; + + doEGT(); + doCHT(); + doOilTemperature(); + doOilPressure(); + + if (Thruster->GetType() == FGThruster::ttPropeller) { + ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber)); + ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber)); + } + + PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired(); + Thruster->Calculate(PowerAvailable); + + RunPostFunctions(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGPiston::CalcFuelNeed(void) { - double dT = FDMExec->GetDeltaT() * Propulsion->GetRate(); - FuelExpended = FuelFlowRate * dT; - return FuelExpended; + double dT = FDMExec->GetDeltaT() * Propulsion->GetRate(); + FuelExpended = FuelFlowRate * dT; + return FuelExpended; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -int FGPiston::InitRunning(void) -{ - Magnetos=3; - p_amb = Atmosphere->GetPressure() * psftopa; - double mix= p_amb / (101325.0*1.3); - FCS->SetMixturePos(EngineNumber, mix); - Thruster->SetRPM( 2.*IdleRPM/Thruster->GetGearRatio() ); - //Thruster->SetRPM( 1000 ); - Running=true; +int FGPiston::InitRunning(void) { + Magnetos=3; + p_amb = Atmosphere->GetPressure() * psftopa; + double mix= p_amb / (101325.0*1.3); + FCS->SetMixturePos(EngineNumber, mix); + Thruster->SetRPM( 2.*IdleRPM/Thruster->GetGearRatio() ); + //Thruster->SetRPM( 1000 ); + Running=true; // cout <<"Set Running in FGPiston. RPM:" << Thruster->GetRPM()*Thruster->GetGearRatio() <<" Pressure:"<<p_amb<<" Mixture:"<< mix <<endl; - return 1; + return 1; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -484,75 +469,63 @@ int FGPiston::InitRunning(void) void FGPiston::doEngineStartup(void) { - // Check parameters that may alter the operating state of the engine. - // (spark, fuel, starter motor etc) - bool spark; - bool fuel; - // Check for spark - Magneto_Left = false; - Magneto_Right = false; - // Magneto positions: - // 0 -> off - // 1 -> left only - // 2 -> right only - // 3 -> both - if (Magnetos != 0) - { - spark = true; - } - else - { - spark = false; - } // neglects battery voltage, master on switch, etc for now. - - if ((Magnetos == 1) || (Magnetos > 2)) Magneto_Left = true; - if (Magnetos > 1) Magneto_Right = true; - - // Assume we have fuel for now - fuel = !Starved; - - // Check if we are turning the starter motor - if (Cranking != Starter) - { - // This check saves .../cranking from getting updated every loop - they - // only update when changed. - Cranking = Starter; - crank_counter = 0; - } + // Check parameters that may alter the operating state of the engine. + // (spark, fuel, starter motor etc) + bool spark; + bool fuel; + // Check for spark + Magneto_Left = false; + Magneto_Right = false; + // Magneto positions: + // 0 -> off + // 1 -> left only + // 2 -> right only + // 3 -> both + if (Magnetos != 0) { + spark = true; + } else { + spark = false; + } // neglects battery voltage, master on switch, etc for now. + + if ((Magnetos == 1) || (Magnetos > 2)) Magneto_Left = true; + if (Magnetos > 1) Magneto_Right = true; + + // Assume we have fuel for now + fuel = !Starved; + + // Check if we are turning the starter motor + if (Cranking != Starter) { + // This check saves .../cranking from getting updated every loop - they + // only update when changed. + Cranking = Starter; + crank_counter = 0; + } - if (Cranking) crank_counter++; //Check mode of engine operation - - if (!Running && spark && fuel) // start the engine if revs high enough - { - if (Cranking) - { - if ((RPM > IdleRPM*0.8) && (crank_counter > 175)) // Add a little delay to startup - Running = true; // on the starter - } - else - { - if (RPM > IdleRPM*0.8) // This allows us to in-air start - Running = true; // when windmilling - } + if (Cranking) crank_counter++; //Check mode of engine operation + + if (!Running && spark && fuel) { // start the engine if revs high enough + if (Cranking) { + if ((RPM > IdleRPM*0.8) && (crank_counter > 175)) // Add a little delay to startup + Running = true; // on the starter + } else { + if (RPM > IdleRPM*0.8) // This allows us to in-air start + Running = true; // when windmilling } + } + + // Cut the engine *power* - Note: the engine may continue to + // spin if the prop is in a moving airstream - // Cut the engine *power* - Note: the engine may continue to - // spin if the prop is in a moving airstream - - if ( Running && (!spark || !fuel) ) Running = false; - - // Check for stalling (RPM = 0). - if (Running) - { - if (RPM == 0) - { - Running = false; - } - else if ((RPM <= IdleRPM *0.8 ) && (Cranking)) - { - Running = false; - } + if ( Running && (!spark || !fuel) ) Running = false; + + // Check for stalling (RPM = 0). + if (Running) { + if (RPM == 0) { + Running = false; + } else if ((RPM <= IdleRPM *0.8 ) && (Cranking)) { + Running = false; } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -570,30 +543,22 @@ void FGPiston::doEngineStartup(void) void FGPiston::doBoostControl(void) { - if (BoostManual) - { - if (BoostSpeed > BoostSpeeds-1) BoostSpeed = BoostSpeeds-1; - if (BoostSpeed < 0) BoostSpeed = 0; - } - else - { - if (BoostSpeed < BoostSpeeds - 1) - { - // Check if we need to change to a higher boost speed - if (p_amb < BoostSwitchPressure[BoostSpeed] - BoostSwitchHysteresis) - { - BoostSpeed++; - } - } - if (BoostSpeed > 0) - { - // Check if we need to change to a lower boost speed - if (p_amb > BoostSwitchPressure[BoostSpeed - 1] + BoostSwitchHysteresis) - { - BoostSpeed--; - } - } + if(BoostManual) { + if(BoostSpeed > BoostSpeeds-1) BoostSpeed = BoostSpeeds-1; + if(BoostSpeed < 0) BoostSpeed = 0; + } else { + if(BoostSpeed < BoostSpeeds - 1) { + // Check if we need to change to a higher boost speed + if(p_amb < BoostSwitchPressure[BoostSpeed] - BoostSwitchHysteresis) { + BoostSpeed++; + } + } if(BoostSpeed > 0) { + // Check if we need to change to a lower boost speed + if(p_amb > BoostSwitchPressure[BoostSpeed - 1] + BoostSwitchHysteresis) { + BoostSpeed--; + } } + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -613,56 +578,48 @@ void FGPiston::doBoostControl(void) void FGPiston::doMAP(void) { - double Zt = (1-Throttle)*(1-Throttle)*Z_throttle; // throttle impedence - double Ze= MeanPistonSpeed_fps > 0 ? PeakMeanPistonSpeed_fps/MeanPistonSpeed_fps : 999999; // engine impedence - - double map_coefficient = Ze/(Ze+Z_airbox+Zt); - - // Add a one second lag to manifold pressure changes - double dMAP = (TMAP - p_ram * map_coefficient) * dt; - TMAP -=dMAP; - - // Find the mean effective pressure required to achieve this manifold pressure - // Fixme: determine the HP consumed by the supercharger - - PMEP = (TMAP - p_amb) * volumetric_efficiency; // Fixme: p_amb should be exhaust manifold pressure - - if (Boosted) - { - // If takeoff boost is fitted, we currently assume the following throttle map: - // (In throttle % - actual input is 0 -> 1) - // 99 / 100 - Takeoff boost - // In real life, most planes would be fitted with a mechanical 'gate' between - // the rated boost and takeoff boost positions. - - bool bTakeoffPos = false; - if (bTakeoffBoost) - { - if (Throttle > 0.98) - { - bTakeoffPos = true; - } - } - // Boost the manifold pressure. - double boost_factor = (( BoostMul[BoostSpeed] - 1 ) / RatedRPM[BoostSpeed] ) * RPM + 1; - MAP = TMAP * boost_factor; - // Now clip the manifold pressure to BCV or Wastegate setting. - if (bTakeoffPos) - { - if (MAP > TakeoffMAP[BoostSpeed]) MAP = TakeoffMAP[BoostSpeed]; - } - else - { - if (MAP > RatedMAP[BoostSpeed]) MAP = RatedMAP[BoostSpeed]; - } + double Zt = (1-Throttle)*(1-Throttle)*Z_throttle; // throttle impedence + double Ze= MeanPistonSpeed_fps > 0 ? PeakMeanPistonSpeed_fps/MeanPistonSpeed_fps : 999999; // engine impedence + + double map_coefficient = Ze/(Ze+Z_airbox+Zt); + + // Add a one second lag to manifold pressure changes + double dMAP = (TMAP - p_ram * map_coefficient) * dt; + TMAP -=dMAP; + + // Find the mean effective pressure required to achieve this manifold pressure + // Fixme: determine the HP consumed by the supercharger + + PMEP = (TMAP - p_amb) * volumetric_efficiency; // Fixme: p_amb should be exhaust manifold pressure + + if (Boosted) { + // If takeoff boost is fitted, we currently assume the following throttle map: + // (In throttle % - actual input is 0 -> 1) + // 99 / 100 - Takeoff boost + // In real life, most planes would be fitted with a mechanical 'gate' between + // the rated boost and takeoff boost positions. + + bool bTakeoffPos = false; + if (bTakeoffBoost) { + if (Throttle > 0.98) { + bTakeoffPos = true; + } } - else - { - MAP = TMAP; + // Boost the manifold pressure. + double boost_factor = (( BoostMul[BoostSpeed] - 1 ) / RatedRPM[BoostSpeed] ) * RPM + 1; + MAP = TMAP * boost_factor; + // Now clip the manifold pressure to BCV or Wastegate setting. + if (bTakeoffPos) { + if (MAP > TakeoffMAP[BoostSpeed]) MAP = TakeoffMAP[BoostSpeed]; + } else { + if (MAP > RatedMAP[BoostSpeed]) MAP = RatedMAP[BoostSpeed]; } + } else { + MAP = TMAP; + } - // And set the value in American units as well - ManifoldPressure_inHg = MAP / inhgtopa; + // And set the value in American units as well + ManifoldPressure_inHg = MAP / inhgtopa; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -681,17 +638,17 @@ void FGPiston::doMAP(void) void FGPiston::doAirFlow(void) { - double gamma = 1.3; // specific heat constants + double gamma = 1.3; // specific heat constants // loss of volumentric efficiency due to difference between MAP and exhaust pressure // Eq 6-10 from The Internal Combustion Engine - Charles Taylor Vol 1 - double ve =((gamma-1)/gamma) +( CompressionRatio -(p_amb/MAP))/(gamma*( CompressionRatio - 1)); + double ve =((gamma-1)/gamma) +( CompressionRatio -(p_amb/MAP))/(gamma*( CompressionRatio - 1)); - rho_air = p_amb / (R_air * T_amb); - double swept_volume = (displacement_SI * (RPM/60)) / 2; - double v_dot_air = swept_volume * volumetric_efficiency *ve; + rho_air = p_amb / (R_air * T_amb); + double swept_volume = (displacement_SI * (RPM/60)) / 2; + double v_dot_air = swept_volume * volumetric_efficiency *ve; - double rho_air_manifold = MAP / (R_air * T_amb); - m_dot_air = v_dot_air * rho_air_manifold; + double rho_air_manifold = MAP / (R_air * T_amb); + m_dot_air = v_dot_air * rho_air_manifold; } @@ -706,14 +663,14 @@ void FGPiston::doAirFlow(void) void FGPiston::doFuelFlow(void) { - double thi_sea_level = 1.3 * Mixture; // Allows an AFR of infinity:1 to 11.3075:1 - equivalence_ratio = thi_sea_level * 101325.0 / p_amb; + double thi_sea_level = 1.3 * Mixture; // Allows an AFR of infinity:1 to 11.3075:1 + equivalence_ratio = thi_sea_level * 101325.0 / p_amb; // double AFR = 10+(12*(1-Mixture));// mixture 10:1 to 22:1 // m_dot_fuel = m_dot_air / AFR; - m_dot_fuel = (m_dot_air * equivalence_ratio) / 14.7; - FuelFlowRate = m_dot_fuel * 2.2046; // kg to lb - FuelFlow_pph = FuelFlowRate * 3600; // seconds to hours - FuelFlow_gph = FuelFlow_pph / 6.0; // Assumes 6 lbs / gallon + m_dot_fuel = (m_dot_air * equivalence_ratio) / 14.7; + FuelFlowRate = m_dot_fuel * 2.2046; // kg to lb + FuelFlow_pph = FuelFlowRate * 3600; // seconds to hours + FuelFlow_gph = FuelFlow_pph / 6.0; // Assumes 6 lbs / gallon } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -729,54 +686,45 @@ void FGPiston::doFuelFlow(void) void FGPiston::doEnginePower(void) { - IndicatedHorsePower = 0; - FMEP = 0; - if (Running) - { - // FIXME: this needs to be generalized - double ME, percent_RPM, power; // Convienience term for use in the calculations - ME = Mixture_Efficiency_Correlation->GetValue(m_dot_fuel/m_dot_air); - - percent_RPM = RPM/MaxRPM; + IndicatedHorsePower = 0; + FMEP = 0; + if (Running) { + // FIXME: this needs to be generalized + double ME, percent_RPM, power; // Convienience term for use in the calculations + ME = Mixture_Efficiency_Correlation->GetValue(m_dot_fuel/m_dot_air); + + percent_RPM = RPM/MaxRPM; // Guestimate engine friction losses from Figure 4.4 of "Engines: An Introduction", John Lumley - FMEP = (-FMEPDynamic * MeanPistonSpeed_fps * fttom - FMEPStatic); + FMEP = (-FMEPDynamic * MeanPistonSpeed_fps * fttom - FMEPStatic); - power = 1; + power = 1; - if ( Magnetos != 3 ) power *= SparkFailDrop; + if ( Magnetos != 3 ) power *= SparkFailDrop; - IndicatedHorsePower = (FuelFlow_pph / ISFC )* ME * power; + IndicatedHorsePower = (FuelFlow_pph / ISFC )* ME * power; + } else { + // Power output when the engine is not running + if (Cranking) { + if (RPM < 10) { + IndicatedHorsePower = StarterHP; + } else if (RPM < IdleRPM*0.8) { + IndicatedHorsePower = StarterHP + ((IdleRPM*0.8 - RPM) / 8.0); + // This is a guess - would be nice to find a proper starter moter torque curve + } else { + IndicatedHorsePower = StarterHP; + } } - else - { - // Power output when the engine is not running - if (Cranking) - { - if (RPM < 10) - { - IndicatedHorsePower = StarterHP; - } - else if (RPM < IdleRPM*0.8) - { - IndicatedHorsePower = StarterHP + ((IdleRPM*0.8 - RPM) / 8.0); - // This is a guess - would be nice to find a proper starter moter torque curve - } - else - { - IndicatedHorsePower = StarterHP; - } - } - } + } - // Constant is (1/2) * 60 * 745.7 - // (1/2) convert cycles, 60 minutes to seconds, 745.7 watts to hp. - double pumping_hp = ((PMEP + FMEP) * displacement_SI * RPM)/(Cycles*22371); + // Constant is (1/2) * 60 * 745.7 + // (1/2) convert cycles, 60 minutes to seconds, 745.7 watts to hp. + double pumping_hp = ((PMEP + FMEP) * displacement_SI * RPM)/(Cycles*22371); - HP = IndicatedHorsePower + pumping_hp - 1.5; //FIXME 1.5 static friction should depend on oil temp and configuration + HP = IndicatedHorsePower + pumping_hp - 1.5; //FIXME 1.5 static friction should depend on oil temp and configuration // cout << "pumping_hp " <<pumping_hp << FMEP << PMEP <<endl; - PctPower = HP / MaxHP ; + PctPower = HP / MaxHP ; // cout << "Power = " << HP << " RPM = " << RPM << " Running = " << Running << " Cranking = " << Cranking << endl; } @@ -792,28 +740,25 @@ void FGPiston::doEnginePower(void) void FGPiston::doEGT(void) { - double delta_T_exhaust; - double enthalpy_exhaust; - double heat_capacity_exhaust; - double dEGTdt; - - if ((Running) && (m_dot_air > 0.0)) // do the energy balance - { - combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio); - enthalpy_exhaust = m_dot_fuel * calorific_value_fuel * - combustion_efficiency * 0.33; - heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel); - delta_T_exhaust = enthalpy_exhaust / heat_capacity_exhaust; - ExhaustGasTemp_degK = T_amb + delta_T_exhaust; - ExhaustGasTemp_degK *= 0.444 + ((0.544 - 0.444) * PctPower); - } - else // Drop towards ambient - guess an appropriate time constant for now - { - combustion_efficiency = 0; - dEGTdt = (RankineToKelvin(Atmosphere->GetTemperature()) - ExhaustGasTemp_degK) / 100.0; - delta_T_exhaust = dEGTdt * dt; - ExhaustGasTemp_degK += delta_T_exhaust; - } + double delta_T_exhaust; + double enthalpy_exhaust; + double heat_capacity_exhaust; + double dEGTdt; + + if ((Running) && (m_dot_air > 0.0)) { // do the energy balance + combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio); + enthalpy_exhaust = m_dot_fuel * calorific_value_fuel * + combustion_efficiency * 0.33; + heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel); + delta_T_exhaust = enthalpy_exhaust / heat_capacity_exhaust; + ExhaustGasTemp_degK = T_amb + delta_T_exhaust; + ExhaustGasTemp_degK *= 0.444 + ((0.544 - 0.444) * PctPower); + } else { // Drop towards ambient - guess an appropriate time constant for now + combustion_efficiency = 0; + dEGTdt = (RankineToKelvin(Atmosphere->GetTemperature()) - ExhaustGasTemp_degK) / 100.0; + delta_T_exhaust = dEGTdt * dt; + ExhaustGasTemp_degK += delta_T_exhaust; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -828,29 +773,29 @@ void FGPiston::doEGT(void) void FGPiston::doCHT(void) { - double h1 = -95.0; - double h2 = -3.95; - double h3 = -140.0; // -0.05 * 2800 (default maxrpm) - - double arbitary_area = Displacement/360.0; - double CpCylinderHead = 800.0; - double MassCylinderHead = 8.0; - - double temperature_difference = CylinderHeadTemp_degK - T_amb; - double v_apparent = IAS * 0.5144444; - double v_dot_cooling_air = arbitary_area * v_apparent; - double m_dot_cooling_air = v_dot_cooling_air * rho_air; - double dqdt_from_combustion = - m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33; - double dqdt_forced = (h2 * m_dot_cooling_air * temperature_difference) + - (h3 * RPM * temperature_difference / MaxRPM); - double dqdt_free = h1 * temperature_difference; - double dqdt_cylinder_head = dqdt_from_combustion + dqdt_forced + dqdt_free; - - double HeatCapacityCylinderHead = CpCylinderHead * MassCylinderHead; - - CylinderHeadTemp_degK += - (dqdt_cylinder_head / HeatCapacityCylinderHead) * dt; + double h1 = -95.0; + double h2 = -3.95; + double h3 = -140.0; // -0.05 * 2800 (default maxrpm) + + double arbitary_area = Displacement/360.0; + double CpCylinderHead = 800.0; + double MassCylinderHead = 8.0; + + double temperature_difference = CylinderHeadTemp_degK - T_amb; + double v_apparent = IAS * 0.5144444; + double v_dot_cooling_air = arbitary_area * v_apparent; + double m_dot_cooling_air = v_dot_cooling_air * rho_air; + double dqdt_from_combustion = + m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33; + double dqdt_forced = (h2 * m_dot_cooling_air * temperature_difference) + + (h3 * RPM * temperature_difference / MaxRPM); + double dqdt_free = h1 * temperature_difference; + double dqdt_cylinder_head = dqdt_from_combustion + dqdt_forced + dqdt_free; + + double HeatCapacityCylinderHead = CpCylinderHead * MassCylinderHead; + + CylinderHeadTemp_degK += + (dqdt_cylinder_head / HeatCapacityCylinderHead) * dt; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -864,30 +809,27 @@ void FGPiston::doCHT(void) void FGPiston::doOilTemperature(void) { - double target_oil_temp; // Steady state oil temp at the current engine conditions - double time_constant; // The time constant for the differential equation - double efficiency = 0.667; // The aproximate oil cooling system efficiency // FIXME: may vary by engine + double target_oil_temp; // Steady state oil temp at the current engine conditions + double time_constant; // The time constant for the differential equation + double efficiency = 0.667; // The aproximate oil cooling system efficiency // FIXME: may vary by engine // Target oil temp is interpolated between ambient temperature and Cylinder Head Tempurature // target_oil_temp = ( T_amb * efficiency ) + (CylinderHeadTemp_degK *(1-efficiency)) ; - target_oil_temp = CylinderHeadTemp_degK + efficiency * (T_amb - CylinderHeadTemp_degK) ; - - if (OilPressure_psi > 5.0 ) - { - time_constant = 5000 / OilPressure_psi; // Guess at a time constant for circulated oil. - // The higher the pressure the faster it reaches - // target temperature. Oil pressure should be about - // 60 PSI yielding a TC of about 80. - } - else - { - time_constant = 1000; // Time constant for engine-off; reflects the fact - // that oil is no longer getting circulated - } + target_oil_temp = CylinderHeadTemp_degK + efficiency * (T_amb - CylinderHeadTemp_degK) ; - double dOilTempdt = (target_oil_temp - OilTemp_degK) / time_constant; + if (OilPressure_psi > 5.0 ) { + time_constant = 5000 / OilPressure_psi; // Guess at a time constant for circulated oil. + // The higher the pressure the faster it reaches + // target temperature. Oil pressure should be about + // 60 PSI yielding a TC of about 80. + } else { + time_constant = 1000; // Time constant for engine-off; reflects the fact + // that oil is no longer getting circulated + } - OilTemp_degK += (dOilTempdt * dt); + double dOilTempdt = (target_oil_temp - OilTemp_degK) / time_constant; + + OilTemp_degK += (dOilTempdt * dt); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -901,47 +843,46 @@ void FGPiston::doOilTemperature(void) void FGPiston::doOilPressure(void) { - double Oil_Press_Relief_Valve = 60; // FIXME: may vary by engine - double Oil_Press_RPM_Max = MaxRPM * 0.75; // 75% of max rpm FIXME: may vary by engine - double Design_Oil_Temp = 358; // degK; FIXME: may vary by engine - double Oil_Viscosity_Index = 0.25; + double Oil_Press_Relief_Valve = 60; // FIXME: may vary by engine + double Oil_Press_RPM_Max = MaxRPM * 0.75; // 75% of max rpm FIXME: may vary by engine + double Design_Oil_Temp = 358; // degK; FIXME: may vary by engine + double Oil_Viscosity_Index = 0.25; - OilPressure_psi = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * RPM; + OilPressure_psi = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * RPM; - if (OilPressure_psi >= Oil_Press_Relief_Valve) - { - OilPressure_psi = Oil_Press_Relief_Valve; - } + if (OilPressure_psi >= Oil_Press_Relief_Valve) { + OilPressure_psi = Oil_Press_Relief_Valve; + } - OilPressure_psi += (Design_Oil_Temp - OilTemp_degK) * Oil_Viscosity_Index * OilPressure_psi / Oil_Press_Relief_Valve; + OilPressure_psi += (Design_Oil_Temp - OilTemp_degK) * Oil_Viscosity_Index * OilPressure_psi / Oil_Press_Relief_Valve; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGPiston::GetEngineLabels(const string& delimiter) { - std::ostringstream buf; + std::ostringstream buf; - buf << Name << " Power Available (engine " << EngineNumber << " in HP)" << delimiter - << Name << " HP (engine " << EngineNumber << ")" << delimiter - << Name << " equivalent ratio (engine " << EngineNumber << ")" << delimiter - << Name << " MAP (engine " << EngineNumber << " in inHg)" << delimiter - << Thruster->GetThrusterLabels(EngineNumber, delimiter); + buf << Name << " Power Available (engine " << EngineNumber << " in HP)" << delimiter + << Name << " HP (engine " << EngineNumber << ")" << delimiter + << Name << " equivalent ratio (engine " << EngineNumber << ")" << delimiter + << Name << " MAP (engine " << EngineNumber << " in inHg)" << delimiter + << Thruster->GetThrusterLabels(EngineNumber, delimiter); - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGPiston::GetEngineValues(const string& delimiter) { - std::ostringstream buf; + std::ostringstream buf; - buf << PowerAvailable << delimiter << HP << delimiter - << equivalence_ratio << delimiter << ManifoldPressure_inHg << delimiter - << Thruster->GetThrusterValues(EngineNumber, delimiter); + buf << PowerAvailable << delimiter << HP << delimiter + << equivalence_ratio << delimiter << ManifoldPressure_inHg << delimiter + << Thruster->GetThrusterValues(EngineNumber, delimiter); - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -966,68 +907,60 @@ string FGPiston::GetEngineValues(const string& delimiter) void FGPiston::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - - cout << "\n Engine Name: " << Name << endl; - cout << " MinManifoldPressure: " << MinManifoldPressure_inHg << endl; - cout << " MaxManifoldPressure: " << MaxManifoldPressure_inHg << endl; - cout << " MinMaP (Pa): " << minMAP << endl; - cout << " MaxMaP (Pa): " << maxMAP << endl; - cout << " Displacement: " << Displacement << endl; - cout << " Bore: " << Bore << endl; - cout << " Stroke: " << Stroke << endl; - cout << " Cylinders: " << Cylinders << endl; - cout << " Compression Ratio: " << CompressionRatio << endl; - cout << " MaxHP: " << MaxHP << endl; - cout << " Cycles: " << Cycles << endl; - cout << " IdleRPM: " << IdleRPM << endl; - cout << " MaxRPM: " << MaxRPM << endl; - cout << " Throttle Constant: " << Z_throttle << endl; - cout << " ISFC: " << ISFC << endl; - cout << " Volumetric Efficiency: " << volumetric_efficiency << endl; - cout << " PeakMeanPistonSpeed_fps: " << PeakMeanPistonSpeed_fps << endl; - cout << " Intake Impedance Factor: " << Z_airbox << endl; - cout << " Dynamic FMEP Factor: " << FMEPDynamic << endl; - cout << " Static FMEP Factor: " << FMEPStatic << endl; - - cout << endl; - cout << " Combustion Efficiency table:" << endl; - Lookup_Combustion_Efficiency->Print(); - cout << endl; - - cout << endl; - cout << " Mixture Efficiency Correlation table:" << endl; - Mixture_Efficiency_Correlation->Print(); - cout << endl; - - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGPiston" << endl; - if (from == 1) cout << "Destroyed: FGPiston" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + + cout << "\n Engine Name: " << Name << endl; + cout << " MinManifoldPressure: " << MinManifoldPressure_inHg << endl; + cout << " MaxManifoldPressure: " << MaxManifoldPressure_inHg << endl; + cout << " MinMaP (Pa): " << minMAP << endl; + cout << " MaxMaP (Pa): " << maxMAP << endl; + cout << " Displacement: " << Displacement << endl; + cout << " Bore: " << Bore << endl; + cout << " Stroke: " << Stroke << endl; + cout << " Cylinders: " << Cylinders << endl; + cout << " Compression Ratio: " << CompressionRatio << endl; + cout << " MaxHP: " << MaxHP << endl; + cout << " Cycles: " << Cycles << endl; + cout << " IdleRPM: " << IdleRPM << endl; + cout << " MaxRPM: " << MaxRPM << endl; + cout << " Throttle Constant: " << Z_throttle << endl; + cout << " ISFC: " << ISFC << endl; + cout << " Volumetric Efficiency: " << volumetric_efficiency << endl; + cout << " PeakMeanPistonSpeed_fps: " << PeakMeanPistonSpeed_fps << endl; + cout << " Intake Impedance Factor: " << Z_airbox << endl; + cout << " Dynamic FMEP Factor: " << FMEPDynamic << endl; + cout << " Static FMEP Factor: " << FMEPStatic << endl; + + cout << endl; + cout << " Combustion Efficiency table:" << endl; + Lookup_Combustion_Efficiency->Print(); + cout << endl; + + cout << endl; + cout << " Mixture Efficiency Correlation table:" << endl; + Mixture_Efficiency_Correlation->Print(); + cout << endl; + } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGPiston" << endl; + if (from == 1) cout << "Destroyed: FGPiston" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } // namespace JSBSim diff --git a/src/models/propulsion/FGPiston.h b/src/models/propulsion/FGPiston.h index c26a13592602b15b5e6674eb8ac1ee204d212705..13072afac2ef0883897f35aa79e9c9078de022f4 100644 --- a/src/models/propulsion/FGPiston.h +++ b/src/models/propulsion/FGPiston.h @@ -46,15 +46,14 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_PISTON "$Id: FGPiston.h,v 1.23 2010/02/25 05:21:36 jberndt Exp $"; +#define ID_PISTON "$Id: FGPiston.h,v 1.24 2010/08/21 18:08:13 jberndt Exp $"; #define FG_MAX_BOOST_SPEEDS 3 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -182,7 +181,7 @@ CLASS DOCUMENTATION @author Dave Luff (engine operational code) @author David Megginson (initial porting and additional code) @author Ron Jensen (additional engine code) - @version $Id: FGPiston.h,v 1.23 2010/02/25 05:21:36 jberndt Exp $ + @version $Id: FGPiston.h,v 1.24 2010/08/21 18:08:13 jberndt Exp $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -192,190 +191,160 @@ CLASS DECLARATION class FGPiston : public FGEngine { public: - /// Constructor - FGPiston(FGFDMExec* exec, Element* el, int engine_number); - /// Destructor - ~FGPiston(); - - std::string GetEngineLabels(const std::string& delimiter); - std::string GetEngineValues(const std::string& delimiter); - - double Calculate(void); - double GetPowerAvailable(void) - { - return PowerAvailable; - } - double CalcFuelNeed(void); - - void ResetToIC(void); - void SetMagnetos(int magnetos) - { - Magnetos = magnetos; - } - - double GetEGT(void) - { - return EGT_degC; - } - int GetMagnetos(void) - { - return Magnetos; - } - - double getExhaustGasTemp_degF(void) - { - return KelvinToFahrenheit(ExhaustGasTemp_degK); - } - double getManifoldPressure_inHg(void) const - { - return ManifoldPressure_inHg; - } - double getCylinderHeadTemp_degF(void) - { - return KelvinToFahrenheit(CylinderHeadTemp_degK); - } - double getOilPressure_psi(void) const - { - return OilPressure_psi; - } - double getOilTemp_degF (void) - { - return KelvinToFahrenheit(OilTemp_degK); - } - double getRPM(void) - { - return RPM; - } + /// Constructor + FGPiston(FGFDMExec* exec, Element* el, int engine_number); + /// Destructor + ~FGPiston(); + + std::string GetEngineLabels(const std::string& delimiter); + std::string GetEngineValues(const std::string& delimiter); + + void Calculate(void); + double GetPowerAvailable(void) {return PowerAvailable;} + double CalcFuelNeed(void); + + void ResetToIC(void); + void SetMagnetos(int magnetos) {Magnetos = magnetos;} + + double GetEGT(void) { return EGT_degC; } + int GetMagnetos(void) {return Magnetos;} + + double getExhaustGasTemp_degF(void) {return KelvinToFahrenheit(ExhaustGasTemp_degK);} + double getManifoldPressure_inHg(void) const {return ManifoldPressure_inHg;} + double getCylinderHeadTemp_degF(void) {return KelvinToFahrenheit(CylinderHeadTemp_degK);} + double getOilPressure_psi(void) const {return OilPressure_psi;} + double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);} + double getRPM(void) {return RPM;} protected: private: - int crank_counter; - - double IndicatedHorsePower; - double PMEP; - double FMEP; - double FMEPDynamic; - double FMEPStatic; - double PowerAvailable; - - // timestep - double dt; - - void doEngineStartup(void); - void doBoostControl(void); - void doMAP(void); - void doAirFlow(void); - void doFuelFlow(void); - void doEnginePower(void); - void doEGT(void); - void doCHT(void); - void doOilPressure(void); - void doOilTemperature(void); - - int InitRunning(void); - - // - // constants - // - - const double R_air; - const double rho_fuel; // kg/m^3 - const double calorific_value_fuel; // W/Kg (approximate) - const double Cp_air; // J/KgK - const double Cp_fuel; // J/KgK - const double standard_pressure; //Pa - - - FGTable *Lookup_Combustion_Efficiency; - FGTable *Mixture_Efficiency_Correlation; - - // - // Configuration - // - double MinManifoldPressure_inHg; // Inches Hg - double MaxManifoldPressure_inHg; // Inches Hg - double MaxManifoldPressure_Percent; // MaxManifoldPressure / 29.92 - double Displacement; // cubic inches - double displacement_SI; // cubic meters - double MaxHP; // horsepower - double SparkFailDrop; // drop of power due to spark failure - double Cycles; // cycles/power stroke - double IdleRPM; // revolutions per minute - double MaxRPM; // revolutions per minute - double Bore; // inches - double Stroke; // inches - double Cylinders; // number - double CompressionRatio; // number - double Z_airbox; // number representing intake impediance before the throttle - double Z_throttle; // number representing slope of throttle impediance - double PeakMeanPistonSpeed_fps; // ft/sec speed where intake valves begin to choke. Typically 33-50 fps - double RatedMeanPistonSpeed_fps; // ft/sec derived from MaxRPM and stroke. - double Ram_Air_Factor; // number - - double StarterHP; // initial horsepower of starter motor - int BoostSpeeds; // Number of super/turbocharger boost speeds - zero implies no turbo/supercharging. - int BoostSpeed; // The current boost-speed (zero-based). - bool Boosted; // Set true for boosted engine. - int BoostManual; // The raw value read in from the config file - should be 1 or 0 - see description below. - bool bBoostManual; // Set true if pilot must manually control the boost speed. - int BoostOverride; // The raw value read in from the config file - should be 1 or 0 - see description below. - bool bBoostOverride; // Set true if pilot override of the boost regulator was fitted. - // (Typically called 'war emergency power'). - bool bTakeoffBoost; // Set true if extra takeoff / emergency boost above rated boost could be attained. - // (Typically by extra throttle movement past a mechanical 'gate'). - double TakeoffBoost; // Sea-level takeoff boost in psi. (if fitted). - double RatedBoost[FG_MAX_BOOST_SPEEDS]; // Sea-level rated boost in psi. - double RatedAltitude[FG_MAX_BOOST_SPEEDS]; // Altitude at which full boost is reached (boost regulation ends) - // and at which power starts to fall with altitude [ft]. - double RatedRPM[FG_MAX_BOOST_SPEEDS]; // Engine speed at which the rated power for each boost speed is delivered [rpm]. - double RatedPower[FG_MAX_BOOST_SPEEDS]; // Power at rated throttle position at rated altitude [HP]. - double BoostSwitchAltitude[FG_MAX_BOOST_SPEEDS - 1]; // Altitude at which switchover (currently assumed automatic) - // from one boost speed to next occurs [ft]. - double BoostSwitchPressure[FG_MAX_BOOST_SPEEDS - 1]; // Pressure at which boost speed switchover occurs [Pa] - double BoostMul[FG_MAX_BOOST_SPEEDS]; // Pressure multipier of unregulated supercharger - double RatedMAP[FG_MAX_BOOST_SPEEDS]; // Rated manifold absolute pressure [Pa] (BCV clamp) - double TakeoffMAP[FG_MAX_BOOST_SPEEDS]; // Takeoff setting manifold absolute pressure [Pa] (BCV clamp) - double BoostSwitchHysteresis; // Pa. - - double minMAP; // Pa - double maxMAP; // Pa - double MAP; // Pa - double TMAP; // Pa - throttle manifold pressure e.g. before the supercharger boost - double ISFC; // Indicated specific fuel consumption [lbs/horsepower*hour - - // - // Inputs (in addition to those in FGEngine). - // - double p_amb; // Pascals - double p_ram; // Pascals - double T_amb; // degrees Kelvin - double RPM; // revolutions per minute - double IAS; // knots - bool Magneto_Left; - bool Magneto_Right; - int Magnetos; - - // - // Outputs (in addition to those in FGEngine). - // - double rho_air; - double volumetric_efficiency; - double map_coefficient; - double m_dot_air; - double equivalence_ratio; - double m_dot_fuel; - double HP; - double combustion_efficiency; - double ExhaustGasTemp_degK; - double EGT_degC; - double ManifoldPressure_inHg; - double CylinderHeadTemp_degK; - double OilPressure_psi; - double OilTemp_degK; - double MeanPistonSpeed_fps; - - void Debug(int from); + int crank_counter; + + double IndicatedHorsePower; + double PMEP; + double FMEP; + double FMEPDynamic; + double FMEPStatic; + double PowerAvailable; + + // timestep + double dt; + + void doEngineStartup(void); + void doBoostControl(void); + void doMAP(void); + void doAirFlow(void); + void doFuelFlow(void); + void doEnginePower(void); + void doEGT(void); + void doCHT(void); + void doOilPressure(void); + void doOilTemperature(void); + + int InitRunning(void); + + // + // constants + // + + const double R_air; + const double rho_fuel; // kg/m^3 + const double calorific_value_fuel; // W/Kg (approximate) + const double Cp_air; // J/KgK + const double Cp_fuel; // J/KgK + const double standard_pressure; //Pa + + + FGTable *Lookup_Combustion_Efficiency; + FGTable *Mixture_Efficiency_Correlation; + + // + // Configuration + // + double MinManifoldPressure_inHg; // Inches Hg + double MaxManifoldPressure_inHg; // Inches Hg + double MaxManifoldPressure_Percent; // MaxManifoldPressure / 29.92 + double Displacement; // cubic inches + double displacement_SI; // cubic meters + double MaxHP; // horsepower + double SparkFailDrop; // drop of power due to spark failure + double Cycles; // cycles/power stroke + double IdleRPM; // revolutions per minute + double MaxRPM; // revolutions per minute + double Bore; // inches + double Stroke; // inches + double Cylinders; // number + double CompressionRatio; // number + double Z_airbox; // number representing intake impediance before the throttle + double Z_throttle; // number representing slope of throttle impediance + double PeakMeanPistonSpeed_fps; // ft/sec speed where intake valves begin to choke. Typically 33-50 fps + double RatedMeanPistonSpeed_fps; // ft/sec derived from MaxRPM and stroke. + double Ram_Air_Factor; // number + + double StarterHP; // initial horsepower of starter motor + int BoostSpeeds; // Number of super/turbocharger boost speeds - zero implies no turbo/supercharging. + int BoostSpeed; // The current boost-speed (zero-based). + bool Boosted; // Set true for boosted engine. + int BoostManual; // The raw value read in from the config file - should be 1 or 0 - see description below. + bool bBoostManual; // Set true if pilot must manually control the boost speed. + int BoostOverride; // The raw value read in from the config file - should be 1 or 0 - see description below. + bool bBoostOverride; // Set true if pilot override of the boost regulator was fitted. + // (Typically called 'war emergency power'). + bool bTakeoffBoost; // Set true if extra takeoff / emergency boost above rated boost could be attained. + // (Typically by extra throttle movement past a mechanical 'gate'). + double TakeoffBoost; // Sea-level takeoff boost in psi. (if fitted). + double RatedBoost[FG_MAX_BOOST_SPEEDS]; // Sea-level rated boost in psi. + double RatedAltitude[FG_MAX_BOOST_SPEEDS]; // Altitude at which full boost is reached (boost regulation ends) + // and at which power starts to fall with altitude [ft]. + double RatedRPM[FG_MAX_BOOST_SPEEDS]; // Engine speed at which the rated power for each boost speed is delivered [rpm]. + double RatedPower[FG_MAX_BOOST_SPEEDS]; // Power at rated throttle position at rated altitude [HP]. + double BoostSwitchAltitude[FG_MAX_BOOST_SPEEDS - 1]; // Altitude at which switchover (currently assumed automatic) + // from one boost speed to next occurs [ft]. + double BoostSwitchPressure[FG_MAX_BOOST_SPEEDS - 1]; // Pressure at which boost speed switchover occurs [Pa] + double BoostMul[FG_MAX_BOOST_SPEEDS]; // Pressure multipier of unregulated supercharger + double RatedMAP[FG_MAX_BOOST_SPEEDS]; // Rated manifold absolute pressure [Pa] (BCV clamp) + double TakeoffMAP[FG_MAX_BOOST_SPEEDS]; // Takeoff setting manifold absolute pressure [Pa] (BCV clamp) + double BoostSwitchHysteresis; // Pa. + + double minMAP; // Pa + double maxMAP; // Pa + double MAP; // Pa + double TMAP; // Pa - throttle manifold pressure e.g. before the supercharger boost + double ISFC; // Indicated specific fuel consumption [lbs/horsepower*hour + + // + // Inputs (in addition to those in FGEngine). + // + double p_amb; // Pascals + double p_ram; // Pascals + double T_amb; // degrees Kelvin + double RPM; // revolutions per minute + double IAS; // knots + bool Magneto_Left; + bool Magneto_Right; + int Magnetos; + + // + // Outputs (in addition to those in FGEngine). + // + double rho_air; + double volumetric_efficiency; + double map_coefficient; + double m_dot_air; + double equivalence_ratio; + double m_dot_fuel; + double HP; + double combustion_efficiency; + double ExhaustGasTemp_degK; + double EGT_degC; + double ManifoldPressure_inHg; + double CylinderHeadTemp_degK; + double OilPressure_psi; + double OilTemp_degK; + double MeanPistonSpeed_fps; + + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/propulsion/FGPropeller.cpp b/src/models/propulsion/FGPropeller.cpp index a379218bce1f0e3b86a0284925fa5442abd4c48c..8204bb9d21cd88bd127071fee4da1e5eb43a419b 100644 --- a/src/models/propulsion/FGPropeller.cpp +++ b/src/models/propulsion/FGPropeller.cpp @@ -46,8 +46,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGPropeller.cpp,v 1.30 2010/05/02 15:10:07 jberndt Exp $"; static const char *IdHdr = ID_PROPELLER; @@ -62,133 +61,119 @@ CLASS IMPLEMENTATION // helicopter. FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num) - : FGThruster(exec, prop_element, num) + : FGThruster(exec, prop_element, num) { - string token; - Element *table_element, *local_element; - string name=""; - FGPropertyManager* PropertyManager = exec->GetPropertyManager(); - - MaxPitch = MinPitch = P_Factor = Pitch = Advance = MinRPM = MaxRPM = 0.0; - Sense = 1; // default clockwise rotation - ReversePitch = 0.0; - Reversed = false; - Feathered = false; - Reverse_coef = 0.0; - GearRatio = 1.0; - CtFactor = CpFactor = 1.0; - ConstantSpeed = 0; - cThrust = cPower = CtMach = CpMach = 0; - Vinduced = 0.0; - - if (prop_element->FindElement("ixx")) - Ixx = prop_element->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2"); - if (prop_element->FindElement("diameter")) - Diameter = prop_element->FindElementValueAsNumberConvertTo("diameter", "FT"); - if (prop_element->FindElement("numblades")) - numBlades = (int)prop_element->FindElementValueAsNumber("numblades"); - if (prop_element->FindElement("gearratio")) - GearRatio = prop_element->FindElementValueAsNumber("gearratio"); - if (prop_element->FindElement("minpitch")) - MinPitch = prop_element->FindElementValueAsNumber("minpitch"); - if (prop_element->FindElement("maxpitch")) - MaxPitch = prop_element->FindElementValueAsNumber("maxpitch"); - if (prop_element->FindElement("minrpm")) - MinRPM = prop_element->FindElementValueAsNumber("minrpm"); - if (prop_element->FindElement("maxrpm")) - { - MaxRPM = prop_element->FindElementValueAsNumber("maxrpm"); - ConstantSpeed = 1; - } - if (prop_element->FindElement("constspeed")) - ConstantSpeed = (int)prop_element->FindElementValueAsNumber("constspeed"); - if (prop_element->FindElement("reversepitch")) - ReversePitch = prop_element->FindElementValueAsNumber("reversepitch"); - for (int i=0; i<2; i++) - { - table_element = prop_element->FindNextElement("table"); - name = table_element->GetAttributeValue("name"); - if (name == "C_THRUST") - { - cThrust = new FGTable(PropertyManager, table_element); - } - else if (name == "C_POWER") - { - cPower = new FGTable(PropertyManager, table_element); - } - else if (name == "CT_MACH") - { - CtMach = new FGTable(PropertyManager, table_element); - } - else if (name == "CP_MACH") - { - CpMach = new FGTable(PropertyManager, table_element); - } - else - { - cerr << "Unknown table type: " << name << " in propeller definition." << endl; - } - } - - local_element = prop_element->GetParent()->FindElement("sense"); - if (local_element) - { - double Sense = local_element->GetDataAsNumber(); - SetSense(fabs(Sense)/Sense); - } - local_element = prop_element->GetParent()->FindElement("p_factor"); - if (local_element) - { - P_Factor = local_element->GetDataAsNumber(); + string token; + Element *table_element, *local_element; + string name=""; + FGPropertyManager* PropertyManager = exec->GetPropertyManager(); + + MaxPitch = MinPitch = P_Factor = Pitch = Advance = MinRPM = MaxRPM = 0.0; + Sense = 1; // default clockwise rotation + ReversePitch = 0.0; + Reversed = false; + Feathered = false; + Reverse_coef = 0.0; + GearRatio = 1.0; + CtFactor = CpFactor = 1.0; + ConstantSpeed = 0; + cThrust = cPower = CtMach = CpMach = 0; + Vinduced = 0.0; + + if (prop_element->FindElement("ixx")) + Ixx = prop_element->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2"); + if (prop_element->FindElement("diameter")) + Diameter = prop_element->FindElementValueAsNumberConvertTo("diameter", "FT"); + if (prop_element->FindElement("numblades")) + numBlades = (int)prop_element->FindElementValueAsNumber("numblades"); + if (prop_element->FindElement("gearratio")) + GearRatio = prop_element->FindElementValueAsNumber("gearratio"); + if (prop_element->FindElement("minpitch")) + MinPitch = prop_element->FindElementValueAsNumber("minpitch"); + if (prop_element->FindElement("maxpitch")) + MaxPitch = prop_element->FindElementValueAsNumber("maxpitch"); + if (prop_element->FindElement("minrpm")) + MinRPM = prop_element->FindElementValueAsNumber("minrpm"); + if (prop_element->FindElement("maxrpm")) { + MaxRPM = prop_element->FindElementValueAsNumber("maxrpm"); + ConstantSpeed = 1; } - if (P_Factor < 0) - { - cerr << "P-Factor value in config file must be greater than zero" << endl; + if (prop_element->FindElement("constspeed")) + ConstantSpeed = (int)prop_element->FindElementValueAsNumber("constspeed"); + if (prop_element->FindElement("reversepitch")) + ReversePitch = prop_element->FindElementValueAsNumber("reversepitch"); + for (int i=0; i<2; i++) { + table_element = prop_element->FindNextElement("table"); + name = table_element->GetAttributeValue("name"); + if (name == "C_THRUST") { + cThrust = new FGTable(PropertyManager, table_element); + } else if (name == "C_POWER") { + cPower = new FGTable(PropertyManager, table_element); + } else if (name == "CT_MACH") { + CtMach = new FGTable(PropertyManager, table_element); + } else if (name == "CP_MACH") { + CpMach = new FGTable(PropertyManager, table_element); + } else { + cerr << "Unknown table type: " << name << " in propeller definition." << endl; } - if (prop_element->FindElement("ct_factor")) - SetCtFactor( prop_element->FindElementValueAsNumber("ct_factor") ); - if (prop_element->FindElement("cp_factor")) - SetCpFactor( prop_element->FindElementValueAsNumber("cp_factor") ); - - Type = ttPropeller; - RPM = 0; - vTorque.InitMatrix(); - D4 = Diameter*Diameter*Diameter*Diameter; - D5 = D4*Diameter; - Pitch = MinPitch; - - string property_name, base_property_name; - base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum); - property_name = base_property_name + "/advance-ratio"; - PropertyManager->Tie( property_name.c_str(), &J ); - property_name = base_property_name + "/blade-angle"; - PropertyManager->Tie( property_name.c_str(), &Pitch ); - property_name = base_property_name + "/thrust-coefficient"; - PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetThrustCoefficient ); - property_name = base_property_name + "/propeller-rpm"; - PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetRPM ); - property_name = base_property_name + "/helical-tip-Mach"; - PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetHelicalTipMach ); - property_name = base_property_name + "/constant-speed-mode"; - PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetConstantSpeed, - &FGPropeller::SetConstantSpeed ); - property_name = base_property_name + "/prop-induced-velocity_fps"; - PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetInducedVelocity, - &FGPropeller::SetInducedVelocity ); - - Debug(0); + } + + local_element = prop_element->GetParent()->FindElement("sense"); + if (local_element) { + double Sense = local_element->GetDataAsNumber(); + SetSense(fabs(Sense)/Sense); + } + local_element = prop_element->GetParent()->FindElement("p_factor"); + if (local_element) { + P_Factor = local_element->GetDataAsNumber(); + } + if (P_Factor < 0) { + cerr << "P-Factor value in config file must be greater than zero" << endl; + } + if (prop_element->FindElement("ct_factor")) + SetCtFactor( prop_element->FindElementValueAsNumber("ct_factor") ); + if (prop_element->FindElement("cp_factor")) + SetCpFactor( prop_element->FindElementValueAsNumber("cp_factor") ); + + Type = ttPropeller; + RPM = 0; + vTorque.InitMatrix(); + D4 = Diameter*Diameter*Diameter*Diameter; + D5 = D4*Diameter; + Pitch = MinPitch; + + string property_name, base_property_name; + base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum); + property_name = base_property_name + "/advance-ratio"; + PropertyManager->Tie( property_name.c_str(), &J ); + property_name = base_property_name + "/blade-angle"; + PropertyManager->Tie( property_name.c_str(), &Pitch ); + property_name = base_property_name + "/thrust-coefficient"; + PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetThrustCoefficient ); + property_name = base_property_name + "/propeller-rpm"; + PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetRPM ); + property_name = base_property_name + "/helical-tip-Mach"; + PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetHelicalTipMach ); + property_name = base_property_name + "/constant-speed-mode"; + PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetConstantSpeed, + &FGPropeller::SetConstantSpeed ); + property_name = base_property_name + "/prop-induced-velocity_fps"; + PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetInducedVelocity, + &FGPropeller::SetInducedVelocity ); + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGPropeller::~FGPropeller() { - delete cThrust; - delete cPower; - delete CtMach; - delete CpMach; + delete cThrust; + delete cPower; + delete CtMach; + delete CpMach; - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -207,219 +192,199 @@ FGPropeller::~FGPropeller() double FGPropeller::Calculate(double PowerAvailable) { - double omega, alpha, beta; + double omega, alpha, beta; - double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU); - double rho = fdmex->GetAtmosphere()->GetDensity(); - double RPS = RPM/60.0; + double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU); + double rho = fdmex->GetAtmosphere()->GetDensity(); + double RPS = RPM/60.0; - // Calculate helical tip Mach - double Area = 0.25*Diameter*Diameter*M_PI; - double Vtip = RPS * Diameter * M_PI; - HelicalTipMach = sqrt(Vtip*Vtip + Vel*Vel) / - fdmex->GetAtmosphere()->GetSoundSpeed(); + // Calculate helical tip Mach + double Area = 0.25*Diameter*Diameter*M_PI; + double Vtip = RPS * Diameter * M_PI; + HelicalTipMach = sqrt(Vtip*Vtip + Vel*Vel) / + fdmex->GetAtmosphere()->GetSoundSpeed(); - if (RPS > 0.0) J = Vel / (Diameter * RPS); // Calculate J normally - else J = Vel / Diameter; - - if (MaxPitch == MinPitch) // Fixed pitch prop - { - ThrustCoeff = cThrust->GetValue(J); - } - else // Variable pitch prop - { - ThrustCoeff = cThrust->GetValue(J, Pitch); - } + if (RPS > 0.0) J = Vel / (Diameter * RPS); // Calculate J normally + else J = Vel / Diameter; - // Apply optional scaling factor to Ct (default value = 1) - ThrustCoeff *= CtFactor; + if (MaxPitch == MinPitch) { // Fixed pitch prop + ThrustCoeff = cThrust->GetValue(J); + } else { // Variable pitch prop + ThrustCoeff = cThrust->GetValue(J, Pitch); + } + + // Apply optional scaling factor to Ct (default value = 1) + ThrustCoeff *= CtFactor; - // Apply optional Mach effects from CT_MACH table - if (CtMach) ThrustCoeff *= CtMach->GetValue(HelicalTipMach); + // Apply optional Mach effects from CT_MACH table + if (CtMach) ThrustCoeff *= CtMach->GetValue(HelicalTipMach); - if (P_Factor > 0.0001) - { - alpha = fdmex->GetAuxiliary()->Getalpha(); - beta = fdmex->GetAuxiliary()->Getbeta(); - SetActingLocationY( GetLocationY() + P_Factor*alpha*Sense); - SetActingLocationZ( GetLocationZ() + P_Factor*beta*Sense); - } + if (P_Factor > 0.0001) { + alpha = fdmex->GetAuxiliary()->Getalpha(); + beta = fdmex->GetAuxiliary()->Getbeta(); + SetActingLocationY( GetLocationY() + P_Factor*alpha*Sense); + SetActingLocationZ( GetLocationZ() + P_Factor*beta*Sense); + } - Thrust = ThrustCoeff*RPS*RPS*D4*rho; + Thrust = ThrustCoeff*RPS*RPS*D4*rho; - // From B. W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics" - // first edition, eqn. 6.15 (propeller analysis chapter). - Vinduced = 0.5 * (-Vel + sqrt(Vel*Vel + 2.0*Thrust/(rho*Area))); + // From B. W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics" + // first edition, eqn. 6.15 (propeller analysis chapter). + Vinduced = 0.5 * (-Vel + sqrt(Vel*Vel + 2.0*Thrust/(rho*Area))); - omega = RPS*2.0*M_PI; + omega = RPS*2.0*M_PI; - vFn(1) = Thrust; + vFn(1) = Thrust; - // The Ixx value and rotation speed given below are for rotation about the - // natural axis of the engine. The transform takes place in the base class - // FGForce::GetBodyForces() function. + // The Ixx value and rotation speed given below are for rotation about the + // natural axis of the engine. The transform takes place in the base class + // FGForce::GetBodyForces() function. - vH(eX) = Ixx*omega*Sense; - vH(eY) = 0.0; - vH(eZ) = 0.0; + vH(eX) = Ixx*omega*Sense; + vH(eY) = 0.0; + vH(eZ) = 0.0; - if (omega > 0.0) ExcessTorque = PowerAvailable / omega; - else ExcessTorque = PowerAvailable / 1.0; + if (omega > 0.0) ExcessTorque = PowerAvailable / omega; + else ExcessTorque = PowerAvailable / 1.0; - RPM = (RPS + ((ExcessTorque / Ixx) / (2.0 * M_PI)) * deltaT) * 60.0; + RPM = (RPS + ((ExcessTorque / Ixx) / (2.0 * M_PI)) * deltaT) * 60.0; - if (RPM < 0.0) RPM = 0.0; // Engine won't turn backwards + if (RPM < 0.0) RPM = 0.0; // Engine won't turn backwards - // Transform Torque and momentum first, as PQR is used in this - // equation and cannot be transformed itself. - vMn = fdmex->GetPropagate()->GetPQR()*(Transform()*vH) + Transform()*vTorque; + // Transform Torque and momentum first, as PQR is used in this + // equation and cannot be transformed itself. + vMn = fdmex->GetPropagate()->GetPQR()*(Transform()*vH) + Transform()*vTorque; - return Thrust; // return thrust in pounds + return Thrust; // return thrust in pounds } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGPropeller::GetPowerRequired(void) { - double cPReq, J; - double rho = fdmex->GetAtmosphere()->GetDensity(); - double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU); - double RPS = RPM / 60.0; - - if (RPS != 0.0) J = Vel / (Diameter * RPS); - else J = Vel / Diameter; - - if (MaxPitch == MinPitch) // Fixed pitch prop - { - cPReq = cPower->GetValue(J); - - } - else // Variable pitch prop - { - - if (ConstantSpeed != 0) // Constant Speed Mode - { - - // do normal calculation when propeller is neither feathered nor reversed - // Note: This method of feathering and reversing was added to support the - // turboprop model. It's left here for backward compatablity, but - // now feathering and reversing should be done in Manual Pitch Mode. - if (!Feathered) - { - if (!Reversed) - { - - double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance; - double dRPM = rpmReq - RPM; - // The pitch of a variable propeller cannot be changed when the RPMs are - // too low - the oil pump does not work. - if (RPM > 200) Pitch -= dRPM * deltaT; - if (Pitch < MinPitch) Pitch = MinPitch; - else if (Pitch > MaxPitch) Pitch = MaxPitch; - - } - else // Reversed propeller - { - - // when reversed calculate propeller pitch depending on throttle lever position - // (beta range for taxing full reverse for braking) - double PitchReq = MinPitch - ( MinPitch - ReversePitch ) * Reverse_coef; - // The pitch of a variable propeller cannot be changed when the RPMs are - // too low - the oil pump does not work. - if (RPM > 200) Pitch += (PitchReq - Pitch) / 200; - if (RPM > MaxRPM) - { - Pitch += (MaxRPM - RPM) / 50; - if (Pitch < ReversePitch) Pitch = ReversePitch; - else if (Pitch > MaxPitch) Pitch = MaxPitch; - } - } - - } - else // Feathered propeller - { - // ToDo: Make feathered and reverse settings done via FGKinemat - Pitch += (MaxPitch - Pitch) / 300; // just a guess (about 5 sec to fully feathered) - } - - } - else // Manual Pitch Mode, pitch is controlled externally - { - + double cPReq, J; + double rho = fdmex->GetAtmosphere()->GetDensity(); + double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU); + double RPS = RPM / 60.0; + + if (RPS != 0.0) J = Vel / (Diameter * RPS); + else J = Vel / Diameter; + + if (MaxPitch == MinPitch) { // Fixed pitch prop + cPReq = cPower->GetValue(J); + + } else { // Variable pitch prop + + if (ConstantSpeed != 0) { // Constant Speed Mode + + // do normal calculation when propeller is neither feathered nor reversed + // Note: This method of feathering and reversing was added to support the + // turboprop model. It's left here for backward compatablity, but + // now feathering and reversing should be done in Manual Pitch Mode. + if (!Feathered) { + if (!Reversed) { + + double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance; + double dRPM = rpmReq - RPM; + // The pitch of a variable propeller cannot be changed when the RPMs are + // too low - the oil pump does not work. + if (RPM > 200) Pitch -= dRPM * deltaT; + if (Pitch < MinPitch) Pitch = MinPitch; + else if (Pitch > MaxPitch) Pitch = MaxPitch; + + } else { // Reversed propeller + + // when reversed calculate propeller pitch depending on throttle lever position + // (beta range for taxing full reverse for braking) + double PitchReq = MinPitch - ( MinPitch - ReversePitch ) * Reverse_coef; + // The pitch of a variable propeller cannot be changed when the RPMs are + // too low - the oil pump does not work. + if (RPM > 200) Pitch += (PitchReq - Pitch) / 200; + if (RPM > MaxRPM) { + Pitch += (MaxRPM - RPM) / 50; + if (Pitch < ReversePitch) Pitch = ReversePitch; + else if (Pitch > MaxPitch) Pitch = MaxPitch; + } } - cPReq = cPower->GetValue(J, Pitch); - } - - // Apply optional scaling factor to Cp (default value = 1) - cPReq *= CpFactor; + } else { // Feathered propeller + // ToDo: Make feathered and reverse settings done via FGKinemat + Pitch += (MaxPitch - Pitch) / 300; // just a guess (about 5 sec to fully feathered) + } - // Apply optional Mach effects from CP_MACH table - if (CpMach) cPReq *= CpMach->GetValue(HelicalTipMach); + } else { // Manual Pitch Mode, pitch is controlled externally - if (RPS > 0.1) - { - PowerRequired = cPReq*RPS*RPS*RPS*D5*rho; - vTorque(eX) = -Sense*PowerRequired / (RPS*2.0*M_PI); - } - else - { - // For a stationary prop we have to estimate torque first. - double CL = (90.0 - Pitch) / 20.0; - if (CL > 1.5) CL = 1.5; - double BladeArea = Diameter * Diameter / 32.0 * numBlades; - vTorque(eX) = -Sense*BladeArea*Diameter*Vel*Vel*rho*0.19*CL; - PowerRequired = vTorque(eX)*0.2*M_PI; } - - return PowerRequired; + + cPReq = cPower->GetValue(J, Pitch); + } + + // Apply optional scaling factor to Cp (default value = 1) + cPReq *= CpFactor; + + // Apply optional Mach effects from CP_MACH table + if (CpMach) cPReq *= CpMach->GetValue(HelicalTipMach); + + if (RPS > 0.1) { + PowerRequired = cPReq*RPS*RPS*RPS*D5*rho; + vTorque(eX) = -Sense*PowerRequired / (RPS*2.0*M_PI); + } else { + // For a stationary prop we have to estimate torque first. + double CL = (90.0 - Pitch) / 20.0; + if (CL > 1.5) CL = 1.5; + double BladeArea = Diameter * Diameter / 32.0 * numBlades; + vTorque(eX) = -Sense*BladeArea*Diameter*Vel*Vel*rho*0.19*CL; + PowerRequired = vTorque(eX)*0.2*M_PI; + } + + return PowerRequired; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3 FGPropeller::GetPFactor() { - double px=0.0, py, pz; + double px=0.0, py, pz; - py = Thrust * Sense * (GetActingLocationY() - GetLocationY()) / 12.0; - pz = Thrust * Sense * (GetActingLocationZ() - GetLocationZ()) / 12.0; + py = Thrust * Sense * (GetActingLocationY() - GetLocationY()) / 12.0; + pz = Thrust * Sense * (GetActingLocationZ() - GetLocationZ()) / 12.0; - return FGColumnVector3(px, py, pz); + return FGColumnVector3(px, py, pz); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGPropeller::GetThrusterLabels(int id, string delimeter) { - std::ostringstream buf; + std::ostringstream buf; - buf << Name << " Torque (engine " << id << ")" << delimeter - << Name << " PFactor Pitch (engine " << id << ")" << delimeter - << Name << " PFactor Yaw (engine " << id << ")" << delimeter - << Name << " Thrust (engine " << id << " in lbs)" << delimeter; - if (IsVPitch()) - buf << Name << " Pitch (engine " << id << ")" << delimeter; - buf << Name << " RPM (engine " << id << ")"; + buf << Name << " Torque (engine " << id << ")" << delimeter + << Name << " PFactor Pitch (engine " << id << ")" << delimeter + << Name << " PFactor Yaw (engine " << id << ")" << delimeter + << Name << " Thrust (engine " << id << " in lbs)" << delimeter; + if (IsVPitch()) + buf << Name << " Pitch (engine " << id << ")" << delimeter; + buf << Name << " RPM (engine " << id << ")"; - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGPropeller::GetThrusterValues(int id, string delimeter) { - std::ostringstream buf; - - FGColumnVector3 vPFactor = GetPFactor(); - buf << vTorque(eX) << delimeter - << vPFactor(ePitch) << delimeter - << vPFactor(eYaw) << delimeter - << Thrust << delimeter; - if (IsVPitch()) - buf << Pitch << delimeter; - buf << RPM; - - return buf.str(); + std::ostringstream buf; + + FGColumnVector3 vPFactor = GetPFactor(); + buf << vTorque(eX) << delimeter + << vPFactor(ePitch) << delimeter + << vPFactor(eYaw) << delimeter + << Thrust << delimeter; + if (IsVPitch()) + buf << Pitch << delimeter; + buf << RPM; + + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -443,48 +408,40 @@ string FGPropeller::GetThrusterValues(int id, string delimeter) void FGPropeller::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << "\n Propeller Name: " << Name << endl; - cout << " IXX = " << Ixx << endl; - cout << " Diameter = " << Diameter << " ft." << endl; - cout << " Number of Blades = " << numBlades << endl; - cout << " Gear Ratio = " << GearRatio << endl; - cout << " Minimum Pitch = " << MinPitch << endl; - cout << " Maximum Pitch = " << MaxPitch << endl; - cout << " Minimum RPM = " << MinRPM << endl; - cout << " Maximum RPM = " << MaxRPM << endl; + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << "\n Propeller Name: " << Name << endl; + cout << " IXX = " << Ixx << endl; + cout << " Diameter = " << Diameter << " ft." << endl; + cout << " Number of Blades = " << numBlades << endl; + cout << " Gear Ratio = " << GearRatio << endl; + cout << " Minimum Pitch = " << MinPitch << endl; + cout << " Maximum Pitch = " << MaxPitch << endl; + cout << " Minimum RPM = " << MinRPM << endl; + cout << " Maximum RPM = " << MaxRPM << endl; // cout << " Thrust Coefficient: " << endl; // cThrust->Print(); // cout << " Power Coefficient: " << endl; // cPower->Print(); - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGPropeller" << endl; - if (from == 1) cout << "Destroyed: FGPropeller" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGPropeller" << endl; + if (from == 1) cout << "Destroyed: FGPropeller" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/propulsion/FGPropeller.h b/src/models/propulsion/FGPropeller.h index f07c8270598973cd16dfac3b79865b322d67cf08..ea7953e1eabc8eba4c422104b02b3b63e7d3b932 100644 --- a/src/models/propulsion/FGPropeller.h +++ b/src/models/propulsion/FGPropeller.h @@ -51,15 +51,14 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /** FGPropeller models a propeller given the tabular data for Ct and Cp, - indexed by the advance ratio "J". + indexed by the advance ratio "J". <h3>Configuration File Format:</h3> @code @@ -117,7 +116,7 @@ CLASS DOCUMENTATION \<maxpitch> - Maximum blade pitch angle. \<minrpm> - Minimum rpm target for constant speed propeller. \<maxrpm> - Maximum rpm target for constant speed propeller. - \<constspeed> - 1 = constant speed mode, 0 = manual pitch mode. + \<constspeed> - 1 = constant speed mode, 0 = manual pitch mode. \<reversepitch> - Blade pitch angle for reverse. \<sense> - Direction of rotation (1=clockwise as viewed from cockpit, -1=anti-clockwise as viewed from cockpit). @@ -130,7 +129,7 @@ CLASS DOCUMENTATION coefficient of power (Cp). Two tables are optional. They apply a factor to Ct and Cp based on the - helical tip Mach. + helical tip Mach. <br> Several references were helpful, here:<ul> @@ -151,246 +150,152 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGPropeller : public FGThruster -{ +class FGPropeller : public FGThruster { public: - /** Constructor for FGPropeller. - @param exec a pointer to the main executive object - @param el a pointer to the thruster config file XML element - @param num the number of this propeller */ - FGPropeller(FGFDMExec* exec, Element* el, int num = 0); - - /// Destructor for FGPropeller - deletes the FGTable objects - ~FGPropeller(); - - /** Sets the Revolutions Per Minute for the propeller. Normally the propeller - instance will calculate its own rotational velocity, given the Torque - produced by the engine and integrating over time using the standard - equation for rotational acceleration "a": a = Q/I , where Q is Torque and - I is moment of inertia for the propeller. - @param rpm the rotational velocity of the propeller */ - void SetRPM(double rpm) - { - RPM = rpm; - } - - /// Returns true of this propeller is variable pitch - bool IsVPitch(void) - { - return MaxPitch != MinPitch; - } - - /** This commands the pitch of the blade to change to the value supplied. - This call is meant to be issued either from the cockpit or by the flight - control system (perhaps to maintain constant RPM for a constant-speed - propeller). This value will be limited to be within whatever is specified - in the config file for Max and Min pitch. It is also one of the lookup - indices to the power and thrust tables for variable-pitch propellers. - @param pitch the pitch of the blade in degrees. */ - void SetPitch(double pitch) - { - Pitch = pitch; - } - - void SetAdvance(double advance) - { - Advance = advance; - } - - /// Sets the P-Factor constant - void SetPFactor(double pf) - { - P_Factor = pf; - } - - /// Sets propeller into constant speed mode, or manual pitch mode - void SetConstantSpeed(int mode) - { - ConstantSpeed = mode; - } - - /// Sets coefficient of thrust multiplier - void SetCtFactor(double ctf) - { - CtFactor = ctf; - } - - /// Sets coefficient of power multiplier - void SetCpFactor(double cpf) - { - CpFactor = cpf; - } - - /** Sets the rotation sense of the propeller. - @param s this value should be +/- 1 ONLY. +1 indicates clockwise rotation as - viewed by someone standing behind the engine looking forward into - the direction of flight. */ - void SetSense(double s) - { - Sense = s; - } - - /// Retrieves the pitch of the propeller in degrees. - double GetPitch(void) - { - return Pitch; - } - - /// Retrieves the RPMs of the propeller - double GetRPM(void) const - { - return RPM; - } - - /// Retrieves the propeller moment of inertia - double GetIxx(void) - { - return Ixx; - } - - /// Retrieves the coefficient of thrust multiplier - double GetCtFactor(void) - { - return CtFactor; - } - - /// Retrieves the coefficient of power multiplier - double GetCpFactor(void) - { - return CpFactor; - } - - /// Retrieves the propeller diameter - double GetDiameter(void) - { - return Diameter; - } - - /// Retrieves propeller thrust table - FGTable* GetCThrustTable(void) const - { - return cThrust; - } - /// Retrieves propeller power table - FGTable* GetCPowerTable(void) const - { - return cPower; - } - - /// Retrieves propeller thrust Mach effects factor - FGTable* GetCtMachTable(void) const - { - return CtMach; - } - /// Retrieves propeller power Mach effects factor - FGTable* GetCpMachTable(void) const - { - return CpMach; - } - - /// Retrieves the Torque in foot-pounds (Don't you love the English system?) - double GetTorque(void) - { - return vTorque(eX); - } - - /** Retrieves the power required (or "absorbed") by the propeller - - i.e. the power required to keep spinning the propeller at the current - velocity, air density, and rotational rate. */ - double GetPowerRequired(void); - - /** Calculates and returns the thrust produced by this propeller. - Given the excess power available from the engine (in foot-pounds), the thrust is - calculated, as well as the current RPM. The RPM is calculated by integrating - the torque provided by the engine over what the propeller "absorbs" - (essentially the "drag" of the propeller). - @param PowerAvailable this is the excess power provided by the engine to - accelerate the prop. It could be negative, dictating that the propeller - would be slowed. - @return the thrust in pounds */ - double Calculate(double PowerAvailable); - FGColumnVector3 GetPFactor(void); - string GetThrusterLabels(int id, string delimeter); - string GetThrusterValues(int id, string delimeter); - - void SetReverseCoef (double c) - { - Reverse_coef = c; - } - double GetReverseCoef (void) - { - return Reverse_coef; - } - void SetReverse (bool r) - { - Reversed = r; - } - bool GetReverse (void) - { - return Reversed; - } - void SetFeather (bool f) - { - Feathered = f; - } - bool GetFeather (void) - { - return Feathered; - } - double GetThrustCoefficient(void) const - { - return ThrustCoeff; - } - double GetHelicalTipMach(void) const - { - return HelicalTipMach; - } - int GetConstantSpeed(void) const - { - return ConstantSpeed; - } - void SetInducedVelocity(double Vi) - { - Vinduced = Vi; - } - double GetInducedVelocity(void) const - { - return Vinduced; - } + /** Constructor for FGPropeller. + @param exec a pointer to the main executive object + @param el a pointer to the thruster config file XML element + @param num the number of this propeller */ + FGPropeller(FGFDMExec* exec, Element* el, int num = 0); + + /// Destructor for FGPropeller - deletes the FGTable objects + ~FGPropeller(); + + /** Sets the Revolutions Per Minute for the propeller. Normally the propeller + instance will calculate its own rotational velocity, given the Torque + produced by the engine and integrating over time using the standard + equation for rotational acceleration "a": a = Q/I , where Q is Torque and + I is moment of inertia for the propeller. + @param rpm the rotational velocity of the propeller */ + void SetRPM(double rpm) {RPM = rpm;} + + /// Returns true of this propeller is variable pitch + bool IsVPitch(void) {return MaxPitch != MinPitch;} + + /** This commands the pitch of the blade to change to the value supplied. + This call is meant to be issued either from the cockpit or by the flight + control system (perhaps to maintain constant RPM for a constant-speed + propeller). This value will be limited to be within whatever is specified + in the config file for Max and Min pitch. It is also one of the lookup + indices to the power and thrust tables for variable-pitch propellers. + @param pitch the pitch of the blade in degrees. */ + void SetPitch(double pitch) {Pitch = pitch;} + + void SetAdvance(double advance) {Advance = advance;} + + /// Sets the P-Factor constant + void SetPFactor(double pf) {P_Factor = pf;} + + /// Sets propeller into constant speed mode, or manual pitch mode + void SetConstantSpeed(int mode) {ConstantSpeed = mode;} + + /// Sets coefficient of thrust multiplier + void SetCtFactor(double ctf) {CtFactor = ctf;} + + /// Sets coefficient of power multiplier + void SetCpFactor(double cpf) {CpFactor = cpf;} + + /** Sets the rotation sense of the propeller. + @param s this value should be +/- 1 ONLY. +1 indicates clockwise rotation as + viewed by someone standing behind the engine looking forward into + the direction of flight. */ + void SetSense(double s) { Sense = s;} + + /// Retrieves the pitch of the propeller in degrees. + double GetPitch(void) { return Pitch; } + + /// Retrieves the RPMs of the propeller + double GetRPM(void) const { return RPM; } + + /// Retrieves the propeller moment of inertia + double GetIxx(void) { return Ixx; } + + /// Retrieves the coefficient of thrust multiplier + double GetCtFactor(void) { return CtFactor; } + + /// Retrieves the coefficient of power multiplier + double GetCpFactor(void) { return CpFactor; } + + /// Retrieves the propeller diameter + double GetDiameter(void) { return Diameter; } + + /// Retrieves propeller thrust table + FGTable* GetCThrustTable(void) const { return cThrust;} + /// Retrieves propeller power table + FGTable* GetCPowerTable(void) const { return cPower; } + + /// Retrieves propeller thrust Mach effects factor + FGTable* GetCtMachTable(void) const { return CtMach; } + /// Retrieves propeller power Mach effects factor + FGTable* GetCpMachTable(void) const { return CpMach; } + + /// Retrieves the Torque in foot-pounds (Don't you love the English system?) + double GetTorque(void) { return vTorque(eX); } + + /** Retrieves the power required (or "absorbed") by the propeller - + i.e. the power required to keep spinning the propeller at the current + velocity, air density, and rotational rate. */ + double GetPowerRequired(void); + + /** Calculates and returns the thrust produced by this propeller. + Given the excess power available from the engine (in foot-pounds), the thrust is + calculated, as well as the current RPM. The RPM is calculated by integrating + the torque provided by the engine over what the propeller "absorbs" + (essentially the "drag" of the propeller). + @param PowerAvailable this is the excess power provided by the engine to + accelerate the prop. It could be negative, dictating that the propeller + would be slowed. + @return the thrust in pounds */ + double Calculate(double PowerAvailable); + FGColumnVector3 GetPFactor(void); + string GetThrusterLabels(int id, string delimeter); + string GetThrusterValues(int id, string delimeter); + + void SetReverseCoef (double c) { Reverse_coef = c; } + double GetReverseCoef (void) { return Reverse_coef; } + void SetReverse (bool r) { Reversed = r; } + bool GetReverse (void) { return Reversed; } + void SetFeather (bool f) { Feathered = f; } + bool GetFeather (void) { return Feathered; } + double GetThrustCoefficient(void) const {return ThrustCoeff;} + double GetHelicalTipMach(void) const {return HelicalTipMach;} + int GetConstantSpeed(void) const {return ConstantSpeed;} + void SetInducedVelocity(double Vi) {Vinduced = Vi;} + double GetInducedVelocity(void) const {return Vinduced;} private: - int numBlades; - double J; - double RPM; - double Ixx; - double Diameter; - double MaxPitch; - double MinPitch; - double MinRPM; - double MaxRPM; - double Pitch; - double P_Factor; - double Sense; - double Advance; - double ExcessTorque; - double D4; - double D5; - double HelicalTipMach; - double Vinduced; - FGColumnVector3 vTorque; - FGTable *cThrust; - FGTable *cPower; - FGTable *CtMach; - FGTable *CpMach; - double CtFactor; - double CpFactor; - int ConstantSpeed; - void Debug(int from); - double ReversePitch; // Pitch, when fully reversed - bool Reversed; // true, when propeller is reversed - double Reverse_coef; // 0 - 1 defines AdvancePitch (0=MIN_PITCH 1=REVERSE_PITCH) - bool Feathered; // true, if feather command + int numBlades; + double J; + double RPM; + double Ixx; + double Diameter; + double MaxPitch; + double MinPitch; + double MinRPM; + double MaxRPM; + double Pitch; + double P_Factor; + double Sense; + double Advance; + double ExcessTorque; + double D4; + double D5; + double HelicalTipMach; + double Vinduced; + FGColumnVector3 vTorque; + FGTable *cThrust; + FGTable *cPower; + FGTable *CtMach; + FGTable *CpMach; + double CtFactor; + double CpFactor; + int ConstantSpeed; + void Debug(int from); + double ReversePitch; // Pitch, when fully reversed + bool Reversed; // true, when propeller is reversed + double Reverse_coef; // 0 - 1 defines AdvancePitch (0=MIN_PITCH 1=REVERSE_PITCH) + bool Feathered; // true, if feather command }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/propulsion/FGRocket.cpp b/src/models/propulsion/FGRocket.cpp index f893b545e25ee6468cf71c535d936b4f29748b1f..87c76685fc4809eda32724c43b82d5ce55282c84 100644 --- a/src/models/propulsion/FGRocket.cpp +++ b/src/models/propulsion/FGRocket.cpp @@ -47,10 +47,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGRocket.cpp,v 1.19 2010/02/25 05:21:36 jberndt Exp $"; +static const char *IdSrc = "$Id: FGRocket.cpp,v 1.20 2010/08/21 17:13:48 jberndt Exp $"; static const char *IdHdr = ID_ROCKET; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -58,153 +57,135 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number) - : FGEngine(exec, el, engine_number) + : FGEngine(exec, el, engine_number) { - Element* thrust_table_element = 0; - ThrustTable = 0L; - BurnTime = 0.0; - previousFuelNeedPerTank = 0.0; - previousOxiNeedPerTank = 0.0; - PropellantFlowRate = 0.0; - FuelFlowRate = FuelExpended = 0.0; - OxidizerFlowRate = OxidizerExpended = 0.0; - SLOxiFlowMax = SLFuelFlowMax = 0.0; - BuildupTime = 0.0; - It = 0.0; - ThrustVariation = 0.0; - TotalIspVariation = 0.0; - - // Defaults - MinThrottle = 0.0; - MaxThrottle = 1.0; - - if (el->FindElement("isp")) - Isp = el->FindElementValueAsNumber("isp"); - if (el->FindElement("builduptime")) - BuildupTime = el->FindElementValueAsNumber("builduptime"); - if (el->FindElement("maxthrottle")) - MaxThrottle = el->FindElementValueAsNumber("maxthrottle"); - if (el->FindElement("minthrottle")) - MinThrottle = el->FindElementValueAsNumber("minthrottle"); - if (el->FindElement("slfuelflowmax")) - SLFuelFlowMax = el->FindElementValueAsNumberConvertTo("slfuelflowmax", "LBS/SEC"); - if (el->FindElement("sloxiflowmax")) - SLOxiFlowMax = el->FindElementValueAsNumberConvertTo("sloxiflowmax", "LBS/SEC"); - - // If there is a thrust table element, this is a solid propellant engine. - thrust_table_element = el->FindElement("thrust_table"); - if (thrust_table_element) - { - ThrustTable = new FGTable(PropertyManager, thrust_table_element); - Element* variation_element = el->FindElement("variation"); - if (variation_element) - { - if (variation_element->FindElement("thrust")) - { - ThrustVariation = variation_element->FindElementValueAsNumber("thrust"); - } - if (variation_element->FindElement("total_isp")) - { - TotalIspVariation = variation_element->FindElementValueAsNumber("total_isp"); - } - } + Type = etRocket; + Element* thrust_table_element = 0; + ThrustTable = 0L; + BurnTime = 0.0; + previousFuelNeedPerTank = 0.0; + previousOxiNeedPerTank = 0.0; + PropellantFlowRate = 0.0; + FuelFlowRate = FuelExpended = 0.0; + OxidizerFlowRate = OxidizerExpended = 0.0; + SLOxiFlowMax = SLFuelFlowMax = 0.0; + BuildupTime = 0.0; + It = 0.0; + ThrustVariation = 0.0; + TotalIspVariation = 0.0; + Flameout = false; + + // Defaults + MinThrottle = 0.0; + MaxThrottle = 1.0; + + if (el->FindElement("isp")) + Isp = el->FindElementValueAsNumber("isp"); + if (el->FindElement("builduptime")) + BuildupTime = el->FindElementValueAsNumber("builduptime"); + if (el->FindElement("maxthrottle")) + MaxThrottle = el->FindElementValueAsNumber("maxthrottle"); + if (el->FindElement("minthrottle")) + MinThrottle = el->FindElementValueAsNumber("minthrottle"); + if (el->FindElement("slfuelflowmax")) + SLFuelFlowMax = el->FindElementValueAsNumberConvertTo("slfuelflowmax", "LBS/SEC"); + if (el->FindElement("sloxiflowmax")) + SLOxiFlowMax = el->FindElementValueAsNumberConvertTo("sloxiflowmax", "LBS/SEC"); + + // If there is a thrust table element, this is a solid propellant engine. + thrust_table_element = el->FindElement("thrust_table"); + if (thrust_table_element) { + ThrustTable = new FGTable(PropertyManager, thrust_table_element); + Element* variation_element = el->FindElement("variation"); + if (variation_element) { + if (variation_element->FindElement("thrust")) { + ThrustVariation = variation_element->FindElementValueAsNumber("thrust"); + } + if (variation_element->FindElement("total_isp")) { + TotalIspVariation = variation_element->FindElementValueAsNumber("total_isp"); + } } + } - bindmodel(); - - Debug(0); - - Type = etRocket; - Flameout = false; + bindmodel(); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGRocket::~FGRocket(void) { - delete ThrustTable; - Debug(1); + delete ThrustTable; + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -double FGRocket::Calculate(void) +void FGRocket::Calculate(void) { - double dT = FDMExec->GetDeltaT()*Propulsion->GetRate(); - double thrust; - - if (!Flameout && !Starved) ConsumeFuel(); - - PropellantFlowRate = (FuelExpended + OxidizerExpended)/dT; - Throttle = FCS->GetThrottlePos(EngineNumber); - - // If there is a thrust table, it is a function of propellant burned. The - // engine is started when the throttle is advanced to 1.0. After that, it - // burns without regard to throttle setting. - - if (ThrustTable != 0L) // Thrust table given -> Solid fuel used - { - - if ((Throttle == 1 || BurnTime > 0.0 ) && !Starved) - { - double TotalEngineFuelBurned=0.0; - for (int i=0; i<(int)SourceTanks.size(); i++) - { - FGTank* tank = Propulsion->GetTank(i); - if (SourceTanks[i] == 1) - { - TotalEngineFuelBurned += tank->GetCapacity() - tank->GetContents(); - } - } - - VacThrust = ThrustTable->GetValue(TotalEngineFuelBurned) - * (ThrustVariation + 1) - * (TotalIspVariation + 1); - if (BurnTime <= BuildupTime && BuildupTime > 0.0) - { - VacThrust *= sin((BurnTime/BuildupTime)*M_PI/2.0); - // VacThrust *= (1-cos((BurnTime/BuildupTime)*M_PI))/2.0; // 1 - cos approach - } - BurnTime += FDMExec->GetDeltaT(); // Increment burn time - } - else - { - VacThrust = 0.0; - } + double dT = FDMExec->GetDeltaT()*Propulsion->GetRate(); - } - else // liquid fueled rocket assumed - { + RunPreFunctions(); + + if (!Flameout && !Starved) ConsumeFuel(); - if (Throttle < MinThrottle || Starved) // Combustion not supported - { + PropellantFlowRate = (FuelExpended + OxidizerExpended)/dT; + Throttle = FCS->GetThrottlePos(EngineNumber); - PctPower = 0.0; // desired thrust - Flameout = true; - VacThrust = 0.0; + // If there is a thrust table, it is a function of propellant burned. The + // engine is started when the throttle is advanced to 1.0. After that, it + // burns without regard to throttle setting. + if (ThrustTable != 0L) { // Thrust table given -> Solid fuel used + + if ((Throttle == 1 || BurnTime > 0.0 ) && !Starved) { + double TotalEngineFuelBurned=0.0; + for (int i=0; i<(int)SourceTanks.size(); i++) { + FGTank* tank = Propulsion->GetTank(i); + if (SourceTanks[i] == 1) { + TotalEngineFuelBurned += tank->GetCapacity() - tank->GetContents(); } - else // Calculate thrust - { + } + + VacThrust = ThrustTable->GetValue(TotalEngineFuelBurned) + * (ThrustVariation + 1) + * (TotalIspVariation + 1); + if (BurnTime <= BuildupTime && BuildupTime > 0.0) { + VacThrust *= sin((BurnTime/BuildupTime)*M_PI/2.0); + // VacThrust *= (1-cos((BurnTime/BuildupTime)*M_PI))/2.0; // 1 - cos approach + } + BurnTime += FDMExec->GetDeltaT(); // Increment burn time + } else { + VacThrust = 0.0; + } - // This is nonsensical. Max throttle should be assumed to be 1.0. One might - // conceivably have a throttle setting > 1.0 for some rocket engines. But, 1.0 - // should always be the default. - // PctPower = Throttle / MaxThrottle; // Min and MaxThrottle range from 0.0 to 1.0, normally. + } else { // liquid fueled rocket assumed - PctPower = Throttle; - Flameout = false; - VacThrust = Isp * PropellantFlowRate; + if (Throttle < MinThrottle || Starved) { // Combustion not supported - } + PctPower = 0.0; // desired thrust + Flameout = true; + VacThrust = 0.0; + + } else { // Calculate thrust - } // End thrust calculations + // This is nonsensical. Max throttle should be assumed to be 1.0. One might + // conceivably have a throttle setting > 1.0 for some rocket engines. But, 1.0 + // should always be the default. + // PctPower = Throttle / MaxThrottle; // Min and MaxThrottle range from 0.0 to 1.0, normally. + + PctPower = Throttle; + Flameout = false; + VacThrust = Isp * PropellantFlowRate; - thrust = Thruster->Calculate(VacThrust); - It += thrust * dT; + } + + } // End thrust calculations - return thrust; + It += Thruster->Calculate(VacThrust) * dT; + + RunPostFunctions(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -213,76 +194,70 @@ double FGRocket::Calculate(void) void FGRocket::ConsumeFuel(void) { - unsigned int i; - FGTank* Tank; - bool haveOxTanks = false; - double Fshortage=0, Oshortage=0, TanksWithFuel=0, TanksWithOxidizer=0; - - if (FuelFreeze) return; - if (TrimMode) return; - - // Count how many assigned tanks have fuel for this engine at this time. - // If there is/are fuel tanks but no oxidizer tanks, this indicates - // a solid rocket is being modeled. - - for (i=0; i<SourceTanks.size(); i++) - { - Tank = Propulsion->GetTank(i); - switch (Tank->GetType()) - { - case FGTank::ttFUEL: - if (Tank->GetContents() > 0.0 && Tank->GetSelected() && SourceTanks[i] > 0) ++TanksWithFuel; - break; - case FGTank::ttOXIDIZER: - if (Tank->GetContents() > 0.0 && Tank->GetSelected() && SourceTanks[i] > 0) - { - haveOxTanks = true; - ++TanksWithOxidizer; - } - break; + unsigned int i; + FGTank* Tank; + bool haveOxTanks = false; + double Fshortage=0, Oshortage=0, TanksWithFuel=0, TanksWithOxidizer=0; + + if (FuelFreeze) return; + if (TrimMode) return; + + // Count how many assigned tanks have fuel for this engine at this time. + // If there is/are fuel tanks but no oxidizer tanks, this indicates + // a solid rocket is being modeled. + + for (i=0; i<SourceTanks.size(); i++) { + Tank = Propulsion->GetTank(i); + switch(Tank->GetType()) { + case FGTank::ttFUEL: + if (Tank->GetContents() > 0.0 && Tank->GetSelected() && SourceTanks[i] > 0) ++TanksWithFuel; + break; + case FGTank::ttOXIDIZER: + if (Tank->GetContents() > 0.0 && Tank->GetSelected() && SourceTanks[i] > 0) { + haveOxTanks = true; + ++TanksWithOxidizer; } + break; } - - // If this engine has burned out, it is starved. - - if (TanksWithFuel==0 || (haveOxTanks && TanksWithOxidizer==0)) - { - Starved = true; - return; - } - - // Expend fuel from the engine's tanks if the tank is selected as a source - // for this engine. - - double fuelNeedPerTank = 0; - double oxiNeedPerTank = 0; - - if (TanksWithFuel > 0) fuelNeedPerTank = CalcFuelNeed()/TanksWithFuel; - if (TanksWithOxidizer > 0) oxiNeedPerTank = CalcOxidizerNeed()/TanksWithOxidizer; - - for (i=0; i<SourceTanks.size(); i++) - { - Tank = Propulsion->GetTank(i); - if ( ! Tank->GetSelected() || SourceTanks[i] == 0) continue; // If this tank is not selected as a source, skip it. - switch (Tank->GetType()) - { - case FGTank::ttFUEL: - Fshortage += Tank->Drain(2.0*fuelNeedPerTank - previousFuelNeedPerTank); - previousFuelNeedPerTank = fuelNeedPerTank; - break; - case FGTank::ttOXIDIZER: - Oshortage += Tank->Drain(2.0*oxiNeedPerTank - previousOxiNeedPerTank); - previousOxiNeedPerTank = oxiNeedPerTank; - break; - } + } + + // If this engine has burned out, it is starved. + + if (TanksWithFuel==0 || (haveOxTanks && TanksWithOxidizer==0)) { + Starved = true; + return; + } + + // Expend fuel from the engine's tanks if the tank is selected as a source + // for this engine. + + double fuelNeedPerTank = 0; + double oxiNeedPerTank = 0; + + if (TanksWithFuel > 0) fuelNeedPerTank = CalcFuelNeed()/TanksWithFuel; + if (TanksWithOxidizer > 0) oxiNeedPerTank = CalcOxidizerNeed()/TanksWithOxidizer; + + for (i=0; i<SourceTanks.size(); i++) { + Tank = Propulsion->GetTank(i); + if ( ! Tank->GetSelected() || SourceTanks[i] == 0) continue; // If this tank is not selected as a source, skip it. + switch(Tank->GetType()) { + case FGTank::ttFUEL: + Fshortage += Tank->Drain(2.0*fuelNeedPerTank - previousFuelNeedPerTank); + previousFuelNeedPerTank = fuelNeedPerTank; + break; + case FGTank::ttOXIDIZER: + Oshortage += Tank->Drain(2.0*oxiNeedPerTank - previousOxiNeedPerTank); + previousOxiNeedPerTank = oxiNeedPerTank; + break; } + } - if (Fshortage < 0.00 || (haveOxTanks && Oshortage < 0.00)) Starved = true; - else Starved = false; + if (Fshortage < 0.00 || (haveOxTanks && Oshortage < 0.00)) Starved = true; + else Starved = false; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// +// // The FuelFlowRate can be affected by the TotalIspVariation value (settable // in a config file or via properties). The TotalIspVariation parameter affects // thrust, but the thrust determines fuel flow rate, so it must be adjusted @@ -290,53 +265,50 @@ void FGRocket::ConsumeFuel(void) double FGRocket::CalcFuelNeed(void) { - double dT = FDMExec->GetDeltaT()*Propulsion->GetRate(); + double dT = FDMExec->GetDeltaT()*Propulsion->GetRate(); - if (ThrustTable != 0L) // Thrust table given - infers solid fuel - { - FuelFlowRate = VacThrust/Isp; // This calculates wdot (weight flow rate in lbs/sec) - FuelFlowRate /= (1 + TotalIspVariation); - } - else - { - FuelFlowRate = SLFuelFlowMax*PctPower; - } + if (ThrustTable != 0L) { // Thrust table given - infers solid fuel + FuelFlowRate = VacThrust/Isp; // This calculates wdot (weight flow rate in lbs/sec) + FuelFlowRate /= (1 + TotalIspVariation); + } else { + FuelFlowRate = SLFuelFlowMax*PctPower; + } - FuelExpended = FuelFlowRate*dT; // For this time step ... - return FuelExpended; + FuelExpended = FuelFlowRate*dT; // For this time step ... + return FuelExpended; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGRocket::CalcOxidizerNeed(void) { - double dT = FDMExec->GetDeltaT()*Propulsion->GetRate(); - OxidizerFlowRate = SLOxiFlowMax*PctPower; - OxidizerExpended = OxidizerFlowRate*dT; - return OxidizerExpended; + double dT = FDMExec->GetDeltaT()*Propulsion->GetRate(); + OxidizerFlowRate = SLOxiFlowMax*PctPower; + OxidizerExpended = OxidizerFlowRate*dT; + return OxidizerExpended; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGRocket::GetEngineLabels(const string& delimiter) { - std::ostringstream buf; + std::ostringstream buf; - buf << Name << " Total Impulse (engine " << EngineNumber << " in psf)" << delimiter - << Thruster->GetThrusterLabels(EngineNumber, delimiter); + buf << Name << " Total Impulse (engine " << EngineNumber << " in psf)" << delimiter + << Thruster->GetThrusterLabels(EngineNumber, delimiter); - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGRocket::GetEngineValues(const string& delimiter) { - std::ostringstream buf; + std::ostringstream buf; - buf << It << delimiter << Thruster->GetThrusterValues(EngineNumber, delimiter); + buf << It << delimiter << Thruster->GetThrusterValues(EngineNumber, delimiter); - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -345,28 +317,25 @@ string FGRocket::GetEngineValues(const string& delimiter) // void FGRocket::bindmodel() { - string property_name, base_property_name; - base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); - - property_name = base_property_name + "/total-impulse"; - PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalImpulse); - property_name = base_property_name + "/vacuum-thrust_lbs"; - PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetVacThrust); - - if (ThrustTable) // Solid rocket motor - { - property_name = base_property_name + "/thrust-variation_pct"; - PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetThrustVariation, - &FGRocket::SetThrustVariation); - property_name = base_property_name + "/total-isp-variation_pct"; - PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalIspVariation, - &FGRocket::SetTotalIspVariation); - } - else // Liquid rocket motor - { - property_name = base_property_name + "/oxi-flow-rate-pps"; - PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetOxiFlowRate); - } + string property_name, base_property_name; + base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); + + property_name = base_property_name + "/total-impulse"; + PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalImpulse); + property_name = base_property_name + "/vacuum-thrust_lbs"; + PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetVacThrust); + + if (ThrustTable) { // Solid rocket motor + property_name = base_property_name + "/thrust-variation_pct"; + PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetThrustVariation, + &FGRocket::SetThrustVariation); + property_name = base_property_name + "/total-isp-variation_pct"; + PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalIspVariation, + &FGRocket::SetTotalIspVariation); + } else { // Liquid rocket motor + property_name = base_property_name + "/oxi-flow-rate-pps"; + PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetOxiFlowRate); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -390,43 +359,35 @@ void FGRocket::bindmodel() void FGRocket::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " Engine Name: " << Name << endl; - cout << " Vacuum Isp = " << Isp << endl; - cout << " Maximum Throttle = " << MaxThrottle << endl; - cout << " Minimum Throttle = " << MinThrottle << endl; - cout << " Fuel Flow (max) = " << SLFuelFlowMax << endl; - cout << " Oxidizer Flow (max) = " << SLOxiFlowMax << endl; - if (SLFuelFlowMax > 0) - cout << " Mixture ratio = " << SLOxiFlowMax/SLFuelFlowMax << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGRocket" << endl; - if (from == 1) cout << "Destroyed: FGRocket" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " Engine Name: " << Name << endl; + cout << " Vacuum Isp = " << Isp << endl; + cout << " Maximum Throttle = " << MaxThrottle << endl; + cout << " Minimum Throttle = " << MinThrottle << endl; + cout << " Fuel Flow (max) = " << SLFuelFlowMax << endl; + cout << " Oxidizer Flow (max) = " << SLOxiFlowMax << endl; + if (SLFuelFlowMax > 0) + cout << " Mixture ratio = " << SLOxiFlowMax/SLFuelFlowMax << endl; } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGRocket" << endl; + if (from == 1) cout << "Destroyed: FGRocket" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/propulsion/FGRocket.h b/src/models/propulsion/FGRocket.h index 58012a5d47a7402699a468bfe07b0726451b00e6..38e367510645e7f88ef94e907ef7c5de00198ccc 100644 --- a/src/models/propulsion/FGRocket.h +++ b/src/models/propulsion/FGRocket.h @@ -46,14 +46,13 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_ROCKET "$Id: FGRocket.h,v 1.12 2009/11/08 02:24:17 jberndt Exp $" +#define ID_ROCKET "$Id: FGRocket.h,v 1.14 2010/08/21 18:08:25 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -78,12 +77,12 @@ CLASS DOCUMENTATION The nozzle exit pressure (p2) is returned via a call to FGNozzle::GetPowerRequired(). This exit pressure is used to get the at-altitude thrust level. - + One can model the thrust of a solid rocket by providing a normalized thrust table as a function of time. For instance, the space shuttle solid rocket booster normalized thrust value looks roughly like this: -<pre> +<pre> \<thrust_table name="propulsion/thrust_time" type="internal"> \<tableData> 0.0 0.00 @@ -119,7 +118,7 @@ for the rocket engine to be throttle up to 1. At that time, the solid rocket fuel begins burning and thrust is provided. @author Jon S. Berndt - $Id: FGRocket.h,v 1.12 2009/11/08 02:24:17 jberndt Exp $ + $Id: FGRocket.h,v 1.14 2010/08/21 18:08:25 jberndt Exp $ @see FGNozzle, FGThruster, FGForce, @@ -135,128 +134,103 @@ CLASS DECLARATION class FGRocket : public FGEngine { public: - /** Constructor. - @param exec pointer to JSBSim parent object, the FDM Executive. - @param el a pointer to the XML Element instance representing the engine. - @param engine_number engine number */ - FGRocket(FGFDMExec* exec, Element *el, int engine_number); - - /** Destructor */ - ~FGRocket(void); - - /** Determines the thrust. - @return thrust */ - double Calculate(void); - - /** Gets the total impulse of the rocket. - @return The cumulative total impulse of the rocket up to this time.*/ - double GetTotalImpulse(void) const - { - return It; - } - - /** Gets the flame-out status. - The engine will "flame out" if the throttle is set below the minimum - sustainable-thrust setting. - @return true if engine has flamed out. */ - bool GetFlameout(void) - { - return Flameout; - } - - double GetOxiFlowRate(void) const - { - return OxidizerFlowRate; - } - - std::string GetEngineLabels(const std::string& delimiter); - std::string GetEngineValues(const std::string& delimiter); - - /** Sets the thrust variation for a solid rocket engine. - Solid propellant rocket motor thrust characteristics are typically - defined at 70 degrees F temperature. At any other temperature, - performance will be different. Warmer propellant grain will - burn quicker and at higher thrust. Total motor impulse is - not changed for change in thrust. - @param var the variation in percent. That is, a 2 percent - variation would be specified as 0.02. A positive 2% variation - in thrust would increase the thrust by 2%, and shorten the burn time. */ - void SetThrustVariation(double var) - { - ThrustVariation = var; - } - - /** Sets the variation in total motor energy. - The total energy present in a solid rocket motor can be modified - (such as might happen with manufacturing variations) by setting - the total Isp variation. - @param var the variation in percent. That is, a 2 percent - variation would be specified as 0.02. This variation will - affect the total thrust, but not the burn time.*/ - void SetTotalIspVariation(double var) - { - TotalIspVariation = var; - } - - /** Returns the thrust variation, if any. */ - double GetThrustVariation(void) const - { - return ThrustVariation; - } - - /** Returns the Total Isp variation, if any. */ - double GetTotalIspVariation(void) const - { - return TotalIspVariation; - } + /** Constructor. + @param exec pointer to JSBSim parent object, the FDM Executive. + @param el a pointer to the XML Element instance representing the engine. + @param engine_number engine number */ + FGRocket(FGFDMExec* exec, Element *el, int engine_number); + + /** Destructor */ + ~FGRocket(void); + + /** Determines the thrust.*/ + void Calculate(void); + + /** Gets the total impulse of the rocket. + @return The cumulative total impulse of the rocket up to this time.*/ + double GetTotalImpulse(void) const {return It;} + + /** Gets the flame-out status. + The engine will "flame out" if the throttle is set below the minimum + sustainable-thrust setting. + @return true if engine has flamed out. */ + bool GetFlameout(void) {return Flameout;} + + double GetOxiFlowRate(void) const {return OxidizerFlowRate;} + + std::string GetEngineLabels(const std::string& delimiter); + std::string GetEngineValues(const std::string& delimiter); + + /** Sets the thrust variation for a solid rocket engine. + Solid propellant rocket motor thrust characteristics are typically + defined at 70 degrees F temperature. At any other temperature, + performance will be different. Warmer propellant grain will + burn quicker and at higher thrust. Total motor impulse is + not changed for change in thrust. + @param var the variation in percent. That is, a 2 percent + variation would be specified as 0.02. A positive 2% variation + in thrust would increase the thrust by 2%, and shorten the burn time. */ + void SetThrustVariation(double var) {ThrustVariation = var;} + + /** Sets the variation in total motor energy. + The total energy present in a solid rocket motor can be modified + (such as might happen with manufacturing variations) by setting + the total Isp variation. + @param var the variation in percent. That is, a 2 percent + variation would be specified as 0.02. This variation will + affect the total thrust, but not the burn time.*/ + void SetTotalIspVariation(double var) {TotalIspVariation = var;} + + /** Returns the thrust variation, if any. */ + double GetThrustVariation(void) const {return ThrustVariation;} + + /** Returns the Total Isp variation, if any. */ + double GetTotalIspVariation(void) const {return TotalIspVariation;} private: - /** Reduces the fuel in the active tanks by the amount required. - This function should be called from within the - derived class' Calculate() function before any other calculations are - done. This base class method removes fuel from the fuel tanks as - appropriate, and sets the starved flag if necessary. */ - void ConsumeFuel(void); - - /** The fuel need is calculated based on power levels and flow rate for that - power level. It is also turned from a rate into an actual amount (pounds) - by multiplying it by the delta T and the rate. - @return Total fuel requirement for this engine in pounds. */ - double CalcFuelNeed(void); - - /** The oxidizer need is calculated based on power levels and flow rate for that - power level. It is also turned from a rate into an actual amount (pounds) - by multiplying it by the delta T and the rate. - @return Total oxidizer requirement for this engine in pounds. */ - double CalcOxidizerNeed(void); - - /** Returns the vacuum thrust. - @return The vacuum thrust in lbs. */ - double GetVacThrust(void) const - { - return VacThrust; - } - - void bindmodel(void); - - double Isp; // Vacuum Isp - double It; - double MxR; // Mixture Ratio - double BurnTime; - double ThrustVariation; - double TotalIspVariation; - double VacThrust; - double previousFuelNeedPerTank; - double previousOxiNeedPerTank; - double OxidizerExpended; - double SLOxiFlowMax; - double OxidizerFlowRate; - double PropellantFlowRate; - bool Flameout; - double BuildupTime; - FGTable* ThrustTable; - - void Debug(int from); + /** Reduces the fuel in the active tanks by the amount required. + This function should be called from within the + derived class' Calculate() function before any other calculations are + done. This base class method removes fuel from the fuel tanks as + appropriate, and sets the starved flag if necessary. */ + void ConsumeFuel(void); + + /** The fuel need is calculated based on power levels and flow rate for that + power level. It is also turned from a rate into an actual amount (pounds) + by multiplying it by the delta T and the rate. + @return Total fuel requirement for this engine in pounds. */ + double CalcFuelNeed(void); + + /** The oxidizer need is calculated based on power levels and flow rate for that + power level. It is also turned from a rate into an actual amount (pounds) + by multiplying it by the delta T and the rate. + @return Total oxidizer requirement for this engine in pounds. */ + double CalcOxidizerNeed(void); + + /** Returns the vacuum thrust. + @return The vacuum thrust in lbs. */ + double GetVacThrust(void) const {return VacThrust;} + + void bindmodel(void); + + double Isp; // Vacuum Isp + double It; + double MxR; // Mixture Ratio + double BurnTime; + double ThrustVariation; + double TotalIspVariation; + double VacThrust; + double previousFuelNeedPerTank; + double previousOxiNeedPerTank; + double OxidizerExpended; + double SLOxiFlowMax; + double OxidizerFlowRate; + double PropellantFlowRate; + bool Flameout; + double BuildupTime; + FGTable* ThrustTable; + + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/propulsion/FGRotor.cpp b/src/models/propulsion/FGRotor.cpp index ab6334328d14c0c8a80b5a844682fc087d96ddf7..b1c1661d034710fa386b04e1fa1ac537ef65340a 100644 --- a/src/models/propulsion/FGRotor.cpp +++ b/src/models/propulsion/FGRotor.cpp @@ -52,8 +52,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGRotor.cpp,v 1.9 2010/06/05 12:12:34 jberndt Exp $"; static const char *IdHdr = ID_ROTOR; @@ -64,10 +63,7 @@ MISC static int dump_req; // debug schwafel flag -static inline double sqr(double x) -{ - return x*x; -} +static inline double sqr(double x) { return x*x; } /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS IMPLEMENTATION @@ -81,122 +77,113 @@ FGRotor::rotor::~rotor() { } // hmm, not a real alternative to a pretty long initializer list -void FGRotor::rotor::zero() -{ - FGColumnVector3 zero_vec(0.0, 0.0, 0.0); - - flags = 0; - parent = NULL ; - - reports = 0; - - // configuration - Radius = 0.0 ; - BladeNum = 0 ; - RelDistance_xhub = 0.0 ; - RelShift_yhub = 0.0 ; - RelHeight_zhub = 0.0 ; - NominalRPM = 0.0 ; - MinRPM = 0.0 ; - BladeChord = 0.0 ; - LiftCurveSlope = 0.0 ; - BladeFlappingMoment = 0.0 ; - BladeTwist = 0.0 ; - BladeMassMoment = 0.0 ; - TipLossB = 0.0 ; - PolarMoment = 0.0 ; - InflowLag = 0.0 ; - ShaftTilt = 0.0 ; - HingeOffset = 0.0 ; - HingeOffset_hover = 0.0 ; - CantAngleD3 = 0.0 ; - - theta_shaft = 0.0 ; - phi_shaft = 0.0 ; - - // derived parameters - LockNumberByRho = 0.0 ; - solidity = 0.0 ; - RpmRatio = 0.0 ; - - for (int i=0; i<5; i++) R[i] = 0.0; - for (int i=0; i<6; i++) B[i] = 0.0; - - BodyToShaft.InitMatrix(); - ShaftToBody.InitMatrix(); - - // dynamic values - ActualRPM = 0.0 ; - Omega = 0.0 ; - beta_orient = 0.0 ; - a0 = 0.0 ; - a_1 = b_1 = a_dw = 0.0 ; - a1s = b1s = 0.0 ; - H_drag = J_side = 0.0 ; - - Torque = 0.0 ; - Thrust = 0.0 ; - Ct = 0.0 ; - lambda = 0.0 ; - mu = 0.0 ; - nu = 0.0 ; - v_induced = 0.0 ; - - force = zero_vec ; - moment = zero_vec ; +void FGRotor::rotor::zero() { + FGColumnVector3 zero_vec(0.0, 0.0, 0.0); + + flags = 0; + parent = NULL ; + + reports = 0; + + // configuration + Radius = 0.0 ; + BladeNum = 0 ; + RelDistance_xhub = 0.0 ; + RelShift_yhub = 0.0 ; + RelHeight_zhub = 0.0 ; + NominalRPM = 0.0 ; + MinRPM = 0.0 ; + BladeChord = 0.0 ; + LiftCurveSlope = 0.0 ; + BladeFlappingMoment = 0.0 ; + BladeTwist = 0.0 ; + BladeMassMoment = 0.0 ; + TipLossB = 0.0 ; + PolarMoment = 0.0 ; + InflowLag = 0.0 ; + ShaftTilt = 0.0 ; + HingeOffset = 0.0 ; + HingeOffset_hover = 0.0 ; + CantAngleD3 = 0.0 ; + + theta_shaft = 0.0 ; + phi_shaft = 0.0 ; + + // derived parameters + LockNumberByRho = 0.0 ; + solidity = 0.0 ; + RpmRatio = 0.0 ; + + for (int i=0; i<5; i++) R[i] = 0.0; + for (int i=0; i<6; i++) B[i] = 0.0; + + BodyToShaft.InitMatrix(); + ShaftToBody.InitMatrix(); + + // dynamic values + ActualRPM = 0.0 ; + Omega = 0.0 ; + beta_orient = 0.0 ; + a0 = 0.0 ; + a_1 = b_1 = a_dw = 0.0 ; + a1s = b1s = 0.0 ; + H_drag = J_side = 0.0 ; + + Torque = 0.0 ; + Thrust = 0.0 ; + Ct = 0.0 ; + lambda = 0.0 ; + mu = 0.0 ; + nu = 0.0 ; + v_induced = 0.0 ; + + force = zero_vec ; + moment = zero_vec ; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 5in1: value-fetch-convert-default-return function +// 5in1: value-fetch-convert-default-return function -double FGRotor::rotor::cnf_elem( const string& ename, double default_val, +double FGRotor::rotor::cnf_elem( const string& ename, double default_val, const string& unit, bool tell) { - Element *e = NULL; - double val=default_val; - - std::string pname = "*No parent element*"; - - if (parent) - { - e = parent->FindElement(ename); - pname = parent->GetName(); - } - - if (e) - { - if (unit.empty()) - { - // val = e->FindElementValueAsNumber(ename); - // yields to: Attempting to get single data value from multiple lines - val = parent->FindElementValueAsNumber(ename); - } - else - { - // val = e->FindElementValueAsNumberConvertTo(ename,unit); - // yields to: Attempting to get non-existent element diameter + crash, why ? - val = parent->FindElementValueAsNumberConvertTo(ename,unit); - } + Element *e = NULL; + double val=default_val; + + std::string pname = "*No parent element*"; + + if (parent) { + e = parent->FindElement(ename); + pname = parent->GetName(); + } + + if (e) { + if (unit.empty()) { + // val = e->FindElementValueAsNumber(ename); + // yields to: Attempting to get single data value from multiple lines + val = parent->FindElementValueAsNumber(ename); + } else { + // val = e->FindElementValueAsNumberConvertTo(ename,unit); + // yields to: Attempting to get non-existent element diameter + crash, why ? + val = parent->FindElementValueAsNumberConvertTo(ename,unit); } - else - { - if (tell) - { - cerr << pname << ": missing element '" << ename <<"' using estimated value: " << default_val << endl; - } + } else { + if (tell) { + cerr << pname << ": missing element '" << ename <<"' using estimated value: " << default_val << endl; } + } - return val; + return val; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGRotor::rotor::cnf_elem(const string& ename, double default_val, bool tell) { - return cnf_elem(ename, default_val, "", tell); + return cnf_elem(ename, default_val, "", tell); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -206,119 +193,106 @@ double FGRotor::rotor::cnf_elem(const string& ename, double default_val, bool te void FGRotor::rotor::configure(int f, const rotor *xmain) { - double estimate; - const bool yell = true; - const bool silent = false; - - flags = f; - - estimate = (xmain) ? 2.0 * xmain->Radius * 0.2 : 42.0; - Radius = 0.5 * cnf_elem("diameter", estimate, "FT", yell); + double estimate; + const bool yell = true; + const bool silent = false; - estimate = (xmain) ? xmain->BladeNum : 2.0; - estimate = Constrain(1.0,estimate,4.0); - BladeNum = (int) cnf_elem("numblades", estimate, yell); + flags = f; - estimate = (xmain) ? - xmain->Radius * 1.05 - Radius : - 0.025 * Radius ; - RelDistance_xhub = cnf_elem("xhub", estimate, "FT", yell); + estimate = (xmain) ? 2.0 * xmain->Radius * 0.2 : 42.0; + Radius = 0.5 * cnf_elem("diameter", estimate, "FT", yell); - RelShift_yhub = cnf_elem("yhub", 0.0, "FT", silent); + estimate = (xmain) ? xmain->BladeNum : 2.0; + estimate = Constrain(1.0,estimate,4.0); + BladeNum = (int) cnf_elem("numblades", estimate, yell); - estimate = - 0.1 * Radius - 4.0; - RelHeight_zhub = cnf_elem("zhub", estimate, "FT", yell); + estimate = (xmain) ? - xmain->Radius * 1.05 - Radius : - 0.025 * Radius ; + RelDistance_xhub = cnf_elem("xhub", estimate, "FT", yell); - // make sure that v_tip (omega*r) is below 0.7mach ~ 750ft/s - estimate = (750.0/Radius)/(2.0*M_PI) * 60.0; // 7160/Radius - NominalRPM = cnf_elem("nominalrpm", estimate, yell); + RelShift_yhub = cnf_elem("yhub", 0.0, "FT", silent); + + estimate = - 0.1 * Radius - 4.0; + RelHeight_zhub = cnf_elem("zhub", estimate, "FT", yell); + + // make sure that v_tip (omega*r) is below 0.7mach ~ 750ft/s + estimate = (750.0/Radius)/(2.0*M_PI) * 60.0; // 7160/Radius + NominalRPM = cnf_elem("nominalrpm", estimate, yell); - MinRPM = cnf_elem("minrpm", 1.0, silent); - MinRPM = Constrain(1.0, MinRPM, NominalRPM-1.0); + MinRPM = cnf_elem("minrpm", 1.0, silent); + MinRPM = Constrain(1.0, MinRPM, NominalRPM-1.0); - estimate = (xmain) ? 0.12 : 0.07; // guess solidity - estimate = estimate * M_PI*Radius/BladeNum; - BladeChord = cnf_elem("chord", estimate, "FT", yell); + estimate = (xmain) ? 0.12 : 0.07; // guess solidity + estimate = estimate * M_PI*Radius/BladeNum; + BladeChord = cnf_elem("chord", estimate, "FT", yell); - LiftCurveSlope = cnf_elem("liftcurveslope", 6.0, yell); // "1/RAD" + LiftCurveSlope = cnf_elem("liftcurveslope", 6.0, yell); // "1/RAD" - estimate = sqr(BladeChord) * sqr(Radius) * 0.57; - BladeFlappingMoment = cnf_elem("flappingmoment", estimate, "SLUG*FT2", yell); - BladeFlappingMoment = Constrain(0.1, BladeFlappingMoment, 1e9); + estimate = sqr(BladeChord) * sqr(Radius) * 0.57; + BladeFlappingMoment = cnf_elem("flappingmoment", estimate, "SLUG*FT2", yell); + BladeFlappingMoment = Constrain(0.1, BladeFlappingMoment, 1e9); - BladeTwist = cnf_elem("twist", -0.17, "RAD", yell); + BladeTwist = cnf_elem("twist", -0.17, "RAD", yell); - estimate = sqr(BladeChord) * BladeChord * 15.66; // might be really wrong! - BladeMassMoment = cnf_elem("massmoment", estimate, yell); // slug-ft - BladeMassMoment = Constrain(0.1, BladeMassMoment, 1e9); + estimate = sqr(BladeChord) * BladeChord * 15.66; // might be really wrong! + BladeMassMoment = cnf_elem("massmoment", estimate, yell); // slug-ft + BladeMassMoment = Constrain(0.1, BladeMassMoment, 1e9); - TipLossB = cnf_elem("tiplossfactor", 0.98, silent); + TipLossB = cnf_elem("tiplossfactor", 0.98, silent); - estimate = 1.1 * BladeFlappingMoment * BladeNum; - PolarMoment = cnf_elem("polarmoment", estimate, "SLUG*FT2", silent); - PolarMoment = Constrain(0.1, PolarMoment, 1e9); + estimate = 1.1 * BladeFlappingMoment * BladeNum; + PolarMoment = cnf_elem("polarmoment", estimate, "SLUG*FT2", silent); + PolarMoment = Constrain(0.1, PolarMoment, 1e9); - InflowLag = cnf_elem("inflowlag", 0.2, silent); // fixme, depends on size + InflowLag = cnf_elem("inflowlag", 0.2, silent); // fixme, depends on size - estimate = (xmain) ? 0.0 : -0.06; - ShaftTilt = cnf_elem("shafttilt", estimate, "RAD", silent); + estimate = (xmain) ? 0.0 : -0.06; + ShaftTilt = cnf_elem("shafttilt", estimate, "RAD", silent); - // ignore differences between teeter/hingeless/fully-articulated constructions - estimate = 0.05 * Radius; - HingeOffset = cnf_elem("hingeoffset", estimate, "FT", (xmain) ? silent : yell); + // ignore differences between teeter/hingeless/fully-articulated constructions + estimate = 0.05 * Radius; + HingeOffset = cnf_elem("hingeoffset", estimate, "FT", (xmain) ? silent : yell); - CantAngleD3 = cnf_elem("cantangle", 0.0, "RAD", silent); + CantAngleD3 = cnf_elem("cantangle", 0.0, "RAD", silent); - // derived parameters + // derived parameters - // precalc often used powers - R[0]=1.0; - R[1]=Radius; - R[2]=R[1]*R[1]; - R[3]=R[2]*R[1]; - R[4]=R[3]*R[1]; - B[0]=1.0; - B[1]=TipLossB; - B[2]=B[1]*B[1]; - B[3]=B[2]*B[1]; - B[4]=B[3]*B[1]; - B[5]=B[4]*B[1]; + // precalc often used powers + R[0]=1.0; R[1]=Radius; R[2]=R[1]*R[1]; R[3]=R[2]*R[1]; R[4]=R[3]*R[1]; + B[0]=1.0; B[1]=TipLossB; B[2]=B[1]*B[1]; B[3]=B[2]*B[1]; B[4]=B[3]*B[1]; B[5]=B[4]*B[1]; - LockNumberByRho = LiftCurveSlope * BladeChord * R[4] / BladeFlappingMoment; - solidity = BladeNum * BladeChord / (M_PI * Radius); + LockNumberByRho = LiftCurveSlope * BladeChord * R[4] / BladeFlappingMoment; + solidity = BladeNum * BladeChord / (M_PI * Radius); - // use simple orientations at the moment - if (flags & eTail) // axis parallel to Y_body - { - theta_shaft = 0.0; // no tilt - phi_shaft = 0.5*M_PI; + // use simple orientations at the moment + if (flags & eTail) { // axis parallel to Y_body + theta_shaft = 0.0; // no tilt + phi_shaft = 0.5*M_PI; - // opposite direction if main rotor is spinning CW - if (xmain && (xmain->flags & eRotCW) ) - { - phi_shaft = -phi_shaft; - } + // opposite direction if main rotor is spinning CW + if (xmain && (xmain->flags & eRotCW) ) { + phi_shaft = -phi_shaft; } - else // more or less upright - { - theta_shaft = ShaftTilt; - phi_shaft = 0.0; - } - - // setup Shaft-Body transforms, see /SH79/ eqn(17,18) - double st = sin(theta_shaft); - double ct = cos(theta_shaft); - double sp = sin(phi_shaft); - double cp = cos(phi_shaft); - - ShaftToBody.InitMatrix( ct, st*sp, st*cp, - 0.0, cp, -sp, - -st, ct*sp, ct*cp ); - - BodyToShaft = ShaftToBody.Inverse(); - - // misc defaults - nu = 0.001; // help the flow solver by providing some moving molecules - - return; + } else { // more or less upright + theta_shaft = ShaftTilt; + phi_shaft = 0.0; + } + + // setup Shaft-Body transforms, see /SH79/ eqn(17,18) + double st = sin(theta_shaft); + double ct = cos(theta_shaft); + double sp = sin(phi_shaft); + double cp = cos(phi_shaft); + + ShaftToBody.InitMatrix( ct, st*sp, st*cp, + 0.0, cp, -sp, + -st, ct*sp, ct*cp ); + + BodyToShaft = ShaftToBody.Inverse(); + + // misc defaults + nu = 0.001; // help the flow solver by providing some moving molecules + + return; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -326,24 +300,24 @@ void FGRotor::rotor::configure(int f, const rotor *xmain) // calculate control-axes components of total airspeed at the hub. // sets rotor orientation angle (beta) as side effect. /SH79/ eqn(19-22) -FGColumnVector3 FGRotor::rotor::hub_vel_body2ca( const FGColumnVector3 &uvw, - const FGColumnVector3 &pqr, - double a_ic, double b_ic) +FGColumnVector3 FGRotor::rotor::hub_vel_body2ca( const FGColumnVector3 &uvw, + const FGColumnVector3 &pqr, + double a_ic, double b_ic) { - FGColumnVector3 v_r, v_shaft, v_w; - FGColumnVector3 pos(RelDistance_xhub,0.0,RelHeight_zhub); + FGColumnVector3 v_r, v_shaft, v_w; + FGColumnVector3 pos(RelDistance_xhub,0.0,RelHeight_zhub); - v_r = uvw + pqr*pos; - v_shaft = BodyToShaft * v_r; + v_r = uvw + pqr*pos; + v_shaft = BodyToShaft * v_r; - beta_orient = atan2(v_shaft(eV),v_shaft(eU)); + beta_orient = atan2(v_shaft(eV),v_shaft(eU)); - v_w(eU) = v_shaft(eU)*cos(beta_orient) + v_shaft(eV)*sin(beta_orient); - v_w(eV) = 0.0; - v_w(eW) = v_shaft(eW) - b_ic*v_shaft(eU) - a_ic*v_shaft(eV); + v_w(eU) = v_shaft(eU)*cos(beta_orient) + v_shaft(eV)*sin(beta_orient); + v_w(eV) = 0.0; + v_w(eW) = v_shaft(eW) - b_ic*v_shaft(eU) - a_ic*v_shaft(eV); - return v_w; + return v_w; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -352,51 +326,49 @@ FGColumnVector3 FGRotor::rotor::hub_vel_body2ca( const FGColumnVector3 &uvw, FGColumnVector3 FGRotor::rotor::fus_angvel_body2ca( const FGColumnVector3 &pqr) { - FGColumnVector3 av_s_fus, av_w_fus; - - av_s_fus = BodyToShaft * pqr; + FGColumnVector3 av_s_fus, av_w_fus; - av_w_fus(eP)= av_s_fus(eP)*cos(beta_orient) + av_s_fus(eQ)*sin(beta_orient); - av_w_fus(eQ)= - av_s_fus(eP)*sin(beta_orient) + av_s_fus(eQ)*cos(beta_orient); - av_w_fus(eR)= av_s_fus(eR); + av_s_fus = BodyToShaft * pqr; - return av_w_fus; + av_w_fus(eP)= av_s_fus(eP)*cos(beta_orient) + av_s_fus(eQ)*sin(beta_orient); + av_w_fus(eQ)= - av_s_fus(eP)*sin(beta_orient) + av_s_fus(eQ)*cos(beta_orient); + av_w_fus(eR)= av_s_fus(eR); + + return av_w_fus; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // problem function passed to rk solver -double FGRotor::rotor::dnuFunction::pFunc(double x, double nu) -{ + double FGRotor::rotor::dnuFunction::pFunc(double x, double nu) { double d_nu; - d_nu = k_sat * (ct_lambda * (k_wor - nu) + k_theta) / - (2.0 * sqrt( mu2 + sqr(k_wor - nu)) ); + d_nu = k_sat * (ct_lambda * (k_wor - nu) + k_theta) / + (2.0 * sqrt( mu2 + sqr(k_wor - nu)) ); d_nu = d_nu * k_flowscale - nu; - return d_nu; -}; + return d_nu; + }; //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// merge params to keep the equation short -void FGRotor::rotor::dnuFunction::update_params(rotor *r, double ct_t01, double fs, double w) -{ + // merge params to keep the equation short + void FGRotor::rotor::dnuFunction::update_params(rotor *r, double ct_t01, double fs, double w) { k_sat = 0.5* r->solidity * r->LiftCurveSlope; ct_lambda = 1.0/2.0*r->B[2] + 1.0/4.0 * r->mu*r->mu; k_wor = w/(r->Omega*r->Radius); k_theta = ct_t01; mu2 = r->mu * r->mu; k_flowscale = fs; -}; + }; //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Calculate rotor thrust and inflow-ratio (lambda), this is achieved by // approximating a solution for the differential equation: -// +// // dnu/dt = 1/tau ( Ct / (2*sqrt(mu^2+lambda^2)) - nu ) , /SH79/ eqn(26). -// +// // Propper calculation of the inflow-ratio (lambda) is vital for the // following calculations. Simple implementations (i.e. Newton-Raphson w/o // checking) tend to oscillate or overshoot in the low speed region, @@ -407,61 +379,57 @@ void FGRotor::rotor::dnuFunction::update_params(rotor *r, double ct_t01, double // see /TA77/ eqn(10a). Doing the ground effect calculation here seems // more favorable then to code it in the fdm_config. -void FGRotor::rotor::calc_flow_and_thrust( - double dt, double rho, double theta_0, - double Uw, double Ww, double flow_scale) +void FGRotor::rotor::calc_flow_and_thrust( + double dt, double rho, double theta_0, + double Uw, double Ww, double flow_scale) { - double ct_over_sigma = 0.0; - double ct_l, ct_t0, ct_t1; - double nu_ret = 0.0; - - mu = Uw/(Omega*Radius); // /SH79/ eqn(24) - - ct_t0 = (1.0/3.0*B[3] + 1.0/2.0 * TipLossB*mu*mu - 4.0/(9.0*M_PI) * mu*mu*mu )*theta_0; - ct_t1 = (1.0/4.0*B[4] + 1.0/4.0 * B[2]*mu*mu)*BladeTwist; - - // merge params together - flowEquation.update_params(this, ct_t0+ct_t1, flow_scale, Ww); - - nu_ret = rk.evolve(nu, &flowEquation); - - if (rk.getStatus() != FGRungeKutta::eNoError) // never observed so far - { - cerr << "# IEHHHH [" << flags << "]: Solver Error - resetting!" << endl; - rk.clearStatus(); - nu_ret = nu; // use old value and keep fingers crossed. + double ct_over_sigma = 0.0; + double ct_l, ct_t0, ct_t1; + double nu_ret = 0.0; + + mu = Uw/(Omega*Radius); // /SH79/ eqn(24) + + ct_t0 = (1.0/3.0*B[3] + 1.0/2.0 * TipLossB*mu*mu - 4.0/(9.0*M_PI) * mu*mu*mu )*theta_0; + ct_t1 = (1.0/4.0*B[4] + 1.0/4.0 * B[2]*mu*mu)*BladeTwist; + + // merge params together + flowEquation.update_params(this, ct_t0+ct_t1, flow_scale, Ww); + + nu_ret = rk.evolve(nu, &flowEquation); + + if (rk.getStatus() != FGRungeKutta::eNoError) { // never observed so far + cerr << "# IEHHHH [" << flags << "]: Solver Error - resetting!" << endl; + rk.clearStatus(); + nu_ret = nu; // use old value and keep fingers crossed. + } + + // keep an eye on the solver, but be quiet after a hundred messages + if (reports < 100 && rk.getIterations()>6) { + cerr << "# LOOK [" << flags << "]: Solver took " + << rk.getIterations() << " rounds." << endl; + reports++; + if (reports==100) { + cerr << "# stopped babbling after 100 notifications." << endl; } + } - // keep an eye on the solver, but be quiet after a hundred messages - if (reports < 100 && rk.getIterations()>6) - { - cerr << "# LOOK [" << flags << "]: Solver took " - << rk.getIterations() << " rounds." << endl; - reports++; - if (reports==100) - { - cerr << "# stopped babbling after 100 notifications." << endl; - } - } + // now from nu to lambda, Ct, and Thrust - // now from nu to lambda, Ct, and Thrust + nu = nu_ret; + lambda = Ww/(Omega*Radius) - nu; // /SH79/ eqn(25) - nu = nu_ret; - lambda = Ww/(Omega*Radius) - nu; // /SH79/ eqn(25) + ct_l = (1.0/2.0*B[2] + 1.0/4.0 * mu*mu)*lambda; + ct_over_sigma = (LiftCurveSlope/2.0)*(ct_l + ct_t0 + ct_t1); // /SH79/ eqn(27) - ct_l = (1.0/2.0*B[2] + 1.0/4.0 * mu*mu)*lambda; - ct_over_sigma = (LiftCurveSlope/2.0)*(ct_l + ct_t0 + ct_t1); // /SH79/ eqn(27) + Thrust = BladeNum*BladeChord*Radius*rho*sqr(Omega*Radius) * ct_over_sigma; - Thrust = BladeNum*BladeChord*Radius*rho*sqr(Omega*Radius) * ct_over_sigma; + Ct = ct_over_sigma * solidity; + v_induced = nu * (Omega*Radius); - Ct = ct_over_sigma * solidity; - v_induced = nu * (Omega*Radius); - - if (dump_req && (flags & eMain) ) - { - printf("# mu %f : nu %f lambda %f vi %f\n", mu, nu, lambda, v_induced); - } + if (dump_req && (flags & eMain) ) { + printf("# mu %f : nu %f lambda %f vi %f\n", mu, nu, lambda, v_induced); + } } @@ -474,31 +442,31 @@ void FGRotor::rotor::calc_flow_and_thrust( void FGRotor::rotor::calc_torque(double rho, double theta_0) { - double Qa0; - double cq_s_m[5], cq_over_sigma; - double l,m,t075; // shortcuts + double Qa0; + double cq_s_m[5], cq_over_sigma; + double l,m,t075; // shortcuts - t075 = theta_0 + 0.75 * BladeTwist; + t075 = theta_0 + 0.75 * BladeTwist; - m = mu; - l = lambda; + m = mu; + l = lambda; - cq_s_m[0] = 0.00109 - 0.0036*l - 0.0027*t075 - 1.10*sqr(l) - 0.545*l*t075 + 0.122*sqr(t075); - cq_s_m[2] = ( 0.00109 - 0.0027*t075 - 3.13*sqr(l) - 6.35*l*t075 - 1.93*sqr(t075) ) * sqr(m); - cq_s_m[3] = - 0.133*l*t075 * sqr(m)*m; - cq_s_m[4] = ( - 0.976*sqr(l) - 6.38*l*t075 - 5.26*sqr(t075) ) * sqr(m)*sqr(m); + cq_s_m[0] = 0.00109 - 0.0036*l - 0.0027*t075 - 1.10*sqr(l) - 0.545*l*t075 + 0.122*sqr(t075); + cq_s_m[2] = ( 0.00109 - 0.0027*t075 - 3.13*sqr(l) - 6.35*l*t075 - 1.93*sqr(t075) ) * sqr(m); + cq_s_m[3] = - 0.133*l*t075 * sqr(m)*m; + cq_s_m[4] = ( - 0.976*sqr(l) - 6.38*l*t075 - 5.26*sqr(t075) ) * sqr(m)*sqr(m); - cq_over_sigma = cq_s_m[0] + cq_s_m[2] + cq_s_m[3] + cq_s_m[4]; - // guess an a (LiftCurveSlope) is included in eqn above, so check if there is a large - // influence when a_'other-model'/ a_'ch54' diverts from 1.0. + cq_over_sigma = cq_s_m[0] + cq_s_m[2] + cq_s_m[3] + cq_s_m[4]; + // guess an a (LiftCurveSlope) is included in eqn above, so check if there is a large + // influence when a_'other-model'/ a_'ch54' diverts from 1.0. - Qa0 = BladeNum * BladeChord * R[2] * rho * sqr(Omega*Radius); + Qa0 = BladeNum * BladeChord * R[2] * rho * sqr(Omega*Radius); // TODO: figure out how to handle negative cq_over_sigma/torque - Torque = Qa0 * cq_over_sigma; + Torque = Qa0 * cq_over_sigma; - return; + return; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -508,47 +476,47 @@ void FGRotor::rotor::calc_torque(double rho, double theta_0) void FGRotor::rotor::calc_coning_angle(double rho, double theta_0) { - double lock_gamma = LockNumberByRho * rho; + double lock_gamma = LockNumberByRho * rho; - double a0_l = (1.0/6.0 * B[3] + 0.04 * mu*mu*mu) * lambda; - double a0_t0 = (1.0/8.0 * B[4] + 1.0/8.0 * B[2]*mu*mu) * theta_0; - double a0_t1 = (1.0/10.0 * B[5] + 1.0/12.0 * B[3]*mu*mu) * BladeTwist; - a0 = lock_gamma * ( a0_l + a0_t0 + a0_t1); - return; + double a0_l = (1.0/6.0 * B[3] + 0.04 * mu*mu*mu) * lambda; + double a0_t0 = (1.0/8.0 * B[4] + 1.0/8.0 * B[2]*mu*mu) * theta_0; + double a0_t1 = (1.0/10.0 * B[5] + 1.0/12.0 * B[3]*mu*mu) * BladeTwist; + a0 = lock_gamma * ( a0_l + a0_t0 + a0_t1); + return; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Flapping angles relative to control axes /SH79/ eqn(32) -void FGRotor::rotor::calc_flapping_angles( double rho, double theta_0, - const FGColumnVector3 &pqr_fus_w) +void FGRotor::rotor::calc_flapping_angles( double rho, double theta_0, + const FGColumnVector3 &pqr_fus_w) { - double lock_gamma = LockNumberByRho * rho; - - double mu2_2B2 = sqr(mu)/(2.0*B[2]); - double t075 = theta_0 + 0.75 * BladeTwist; // common approximation for rectangular blades - - a_1 = 1.0/(1.0 - mu2_2B2) * ( - (2.0*lambda + (8.0/3.0)*t075)*mu - + pqr_fus_w(eP)/Omega - - 16.0 * pqr_fus_w(eQ)/(B[4]*lock_gamma*Omega) - ); - - b_1 = 1.0/(1.0 + mu2_2B2) * ( - (4.0/3.0)*mu*a0 - - pqr_fus_w(eQ)/Omega - - 16.0 * pqr_fus_w(eP)/(B[4]*lock_gamma*Omega) - ); - - // used in force calc - a_dw = 1.0/(1.0 - mu2_2B2) * ( - (2.0*lambda + (8.0/3.0)*t075)*mu - - 24.0 * pqr_fus_w(eQ)/(B[4]*lock_gamma*Omega) - * ( 1.0 - ( 0.29 * t075 / (Ct/solidity) ) ) - ); - - return; + double lock_gamma = LockNumberByRho * rho; + + double mu2_2B2 = sqr(mu)/(2.0*B[2]); + double t075 = theta_0 + 0.75 * BladeTwist; // common approximation for rectangular blades + + a_1 = 1.0/(1.0 - mu2_2B2) * ( + (2.0*lambda + (8.0/3.0)*t075)*mu + + pqr_fus_w(eP)/Omega + - 16.0 * pqr_fus_w(eQ)/(B[4]*lock_gamma*Omega) + ); + + b_1 = 1.0/(1.0 + mu2_2B2) * ( + (4.0/3.0)*mu*a0 + - pqr_fus_w(eQ)/Omega + - 16.0 * pqr_fus_w(eP)/(B[4]*lock_gamma*Omega) + ); + + // used in force calc + a_dw = 1.0/(1.0 - mu2_2B2) * ( + (2.0*lambda + (8.0/3.0)*t075)*mu + - 24.0 * pqr_fus_w(eQ)/(B[4]*lock_gamma*Omega) + * ( 1.0 - ( 0.29 * t075 / (Ct/solidity) ) ) + ); + + return; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -557,21 +525,21 @@ void FGRotor::rotor::calc_flapping_angles( double rho, double theta_0, void FGRotor::rotor::calc_drag_and_side_forces(double rho, double theta_0) { - double cy_over_sigma ; - double t075 = theta_0 + 0.75 * BladeTwist; - - H_drag = Thrust * a_dw; - - cy_over_sigma = ( - 0.75*b_1*lambda - 1.5*a0*mu*lambda + 0.25*a_1*b_1*mu - - a0*a_1*sqr(mu) + (1.0/6.0)*a0*a_1 - - (0.75*mu*a0 - (1.0/3.0)*b_1 - 0.5*sqr(mu)*b_1)*t075 - ); - cy_over_sigma *= LiftCurveSlope/2.0; - - J_side = BladeNum * BladeChord * Radius * rho * sqr(Omega*Radius) * cy_over_sigma; - - return; + double cy_over_sigma ; + double t075 = theta_0 + 0.75 * BladeTwist; + + H_drag = Thrust * a_dw; + + cy_over_sigma = ( + 0.75*b_1*lambda - 1.5*a0*mu*lambda + 0.25*a_1*b_1*mu + - a0*a_1*sqr(mu) + (1.0/6.0)*a0*a_1 + - (0.75*mu*a0 - (1.0/3.0)*b_1 - 0.5*sqr(mu)*b_1)*t075 + ); + cy_over_sigma *= LiftCurveSlope/2.0; + + J_side = BladeNum * BladeChord * Radius * rho * sqr(Omega*Radius) * cy_over_sigma; + + return; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -582,18 +550,17 @@ void FGRotor::rotor::calc_drag_and_side_forces(double rho, double theta_0) FGColumnVector3 FGRotor::rotor::body_forces(double a_ic, double b_ic) { FGColumnVector3 F_s( - - H_drag*cos(beta_orient) - J_side*sin(beta_orient) + Thrust*b_ic, - - H_drag*sin(beta_orient) + J_side*cos(beta_orient) + Thrust*a_ic, - - Thrust); - - if (dump_req && (flags & eMain) ) - { - printf("# abß: % f % f % f\n", a_ic, b_ic, beta_orient ); - printf("# HJT: % .2f % .2f % .2f\n", H_drag, J_side, Thrust ); - printf("# F_s: % .2f % .2f % .2f\n", F_s(1), F_s(2), F_s(3) ); - FGColumnVector3 F_h; - F_h = ShaftToBody * F_s; - printf("# F_h: % .2f % .2f % .2f\n", F_h(1), F_h(2), F_h(3) ); + - H_drag*cos(beta_orient) - J_side*sin(beta_orient) + Thrust*b_ic, + - H_drag*sin(beta_orient) + J_side*cos(beta_orient) + Thrust*a_ic, + - Thrust); + + if (dump_req && (flags & eMain) ) { + printf("# abß: % f % f % f\n", a_ic, b_ic, beta_orient ); + printf("# HJT: % .2f % .2f % .2f\n", H_drag, J_side, Thrust ); + printf("# F_s: % .2f % .2f % .2f\n", F_s(1), F_s(2), F_s(3) ); + FGColumnVector3 F_h; + F_h = ShaftToBody * F_s; + printf("# F_h: % .2f % .2f % .2f\n", F_h(1), F_h(2), F_h(3) ); } return ShaftToBody * F_s; @@ -607,41 +574,39 @@ FGColumnVector3 FGRotor::rotor::body_forces(double a_ic, double b_ic) FGColumnVector3 FGRotor::rotor::body_moments(FGColumnVector3 F_h, double a_ic, double b_ic) { - FGColumnVector3 M_s, M_hub, M_h; - - FGColumnVector3 h_pos(RelDistance_xhub, 0.0, RelHeight_zhub); - - // vermutlich ein biege moment, bzw.widerstands moment ~ d^3 - double M_w_tilde = 0.0 ; - double mf = 0.0 ; + FGColumnVector3 M_s, M_hub, M_h; + + FGColumnVector3 h_pos(RelDistance_xhub, 0.0, RelHeight_zhub); - M_w_tilde = BladeMassMoment; + // vermutlich ein biege moment, bzw.widerstands moment ~ d^3 + double M_w_tilde = 0.0 ; + double mf = 0.0 ; + + M_w_tilde = BladeMassMoment; - // cyclic flapping relative to shaft axes /SH79/ eqn(43) - a1s = a_1*cos(beta_orient) + b_1*sin(beta_orient) - b_ic; - b1s = b_1*cos(beta_orient) - a_1*sin(beta_orient) + a_ic; + // cyclic flapping relative to shaft axes /SH79/ eqn(43) + a1s = a_1*cos(beta_orient) + b_1*sin(beta_orient) - b_ic; + b1s = b_1*cos(beta_orient) - a_1*sin(beta_orient) + a_ic; - // mind this: no HingeOffset, no additional pitch/roll moments - mf = 0.5 * (HingeOffset+HingeOffset_hover) * BladeNum * Omega*Omega * M_w_tilde; - M_s(eL) = mf*b1s; - M_s(eM) = mf*a1s; - M_s(eN) = Torque; + // mind this: no HingeOffset, no additional pitch/roll moments + mf = 0.5 * (HingeOffset+HingeOffset_hover) * BladeNum * Omega*Omega * M_w_tilde; + M_s(eL) = mf*b1s; + M_s(eM) = mf*a1s; + M_s(eN) = Torque; - if (flags & eRotCW) - { - M_s(eN) = -M_s(eN); - } + if (flags & eRotCW) { + M_s(eN) = -M_s(eN); + } - if (flags & eCoaxial) - { - M_s(eN) = 0.0; - } + if (flags & eCoaxial) { + M_s(eN) = 0.0; + } - M_hub = ShaftToBody * M_s; + M_hub = ShaftToBody * M_s; - M_h = M_hub + (h_pos * F_h); + M_h = M_hub + (h_pos * F_h); - return M_h; + return M_h; } @@ -650,156 +615,145 @@ FGColumnVector3 FGRotor::rotor::body_moments(FGColumnVector3 F_h, double a_ic, d // Constructor FGRotor::FGRotor(FGFDMExec *exec, Element* rotor_element, int num) - : FGThruster(exec, rotor_element, num) + : FGThruster(exec, rotor_element, num) { - FGColumnVector3 location, orientation; - Element *thruster_element; + FGColumnVector3 location, orientation; + Element *thruster_element; - PropertyManager = fdmex->GetPropertyManager(); - dt = fdmex->GetDeltaT(); + PropertyManager = fdmex->GetPropertyManager(); + dt = fdmex->GetDeltaT(); - /* apply defaults */ + /* apply defaults */ - rho = 0.002356; // just a sane value + rho = 0.002356; // just a sane value + + RPM = 0.0; + Sense = 1.0; + tailRotorPresent = false; + + effective_tail_col = 0.001; // just a sane value - RPM = 0.0; - Sense = 1.0; - tailRotorPresent = false; + prop_inflow_ratio_lambda = 0.0; + prop_advance_ratio_mu = 0.0; + prop_inflow_ratio_induced_nu = 0.0; + prop_mr_torque = 0.0; + prop_thrust_coefficient = 0.0; + prop_coning_angle = 0.0; - effective_tail_col = 0.001; // just a sane value + prop_theta_downwash = prop_phi_downwash = 0.0; - prop_inflow_ratio_lambda = 0.0; - prop_advance_ratio_mu = 0.0; - prop_inflow_ratio_induced_nu = 0.0; - prop_mr_torque = 0.0; - prop_thrust_coefficient = 0.0; - prop_coning_angle = 0.0; + hover_threshold = 0.0; + hover_scale = 0.0; - prop_theta_downwash = prop_phi_downwash = 0.0; + mr.zero(); + tr.zero(); - hover_threshold = 0.0; - hover_scale = 0.0; + // debug stuff + prop_DumpFlag = 0; - mr.zero(); - tr.zero(); + /* configure */ - // debug stuff - prop_DumpFlag = 0; + Type = ttRotor; + SetTransformType(FGForce::tCustom); - /* configure */ + // get data from parent and 'mount' the rotor system - Type = ttRotor; - SetTransformType(FGForce::tCustom); + thruster_element = rotor_element->GetParent()->FindElement("sense"); + if (thruster_element) { + Sense = thruster_element->GetDataAsNumber() >= 0.0 ? 1.0: -1.0; + } - // get data from parent and 'mount' the rotor system + thruster_element = rotor_element->GetParent()->FindElement("location"); + if (thruster_element) location = thruster_element->FindElementTripletConvertTo("IN"); + else cerr << "No thruster location found." << endl; - thruster_element = rotor_element->GetParent()->FindElement("sense"); - if (thruster_element) - { - Sense = thruster_element->GetDataAsNumber() >= 0.0 ? 1.0: -1.0; - } + thruster_element = rotor_element->GetParent()->FindElement("orient"); + if (thruster_element) orientation = thruster_element->FindElementTripletConvertTo("RAD"); + else cerr << "No thruster orientation found." << endl; - thruster_element = rotor_element->GetParent()->FindElement("location"); - if (thruster_element) location = thruster_element->FindElementTripletConvertTo("IN"); - else cerr << "No thruster location found." << endl; + SetLocation(location); + SetAnglesToBody(orientation); - thruster_element = rotor_element->GetParent()->FindElement("orient"); - if (thruster_element) orientation = thruster_element->FindElementTripletConvertTo("RAD"); - else cerr << "No thruster orientation found." << endl; + // get main rotor parameters + mr.parent = rotor_element; - SetLocation(location); - SetAnglesToBody(orientation); + int flags = eMain; - // get main rotor parameters - mr.parent = rotor_element; + string a_val=""; + a_val = rotor_element->GetAttributeValue("variant"); + if ( a_val == "coaxial" ) { + flags += eCoaxial; + cerr << "# found 'coaxial' variant" << endl; + } - int flags = eMain; + if (Sense<0.0) { + flags += eRotCW; + } + + mr.configure(flags); - string a_val=""; - a_val = rotor_element->GetAttributeValue("variant"); - if ( a_val == "coaxial" ) - { - flags += eCoaxial; - cerr << "# found 'coaxial' variant" << endl; - } + mr.rk.init(0,dt,6); - if (Sense<0.0) - { - flags += eRotCW; - } - - mr.configure(flags); - - mr.rk.init(0,dt,6); - - // get tail rotor parameters - tr.parent=rotor_element->FindElement("tailrotor"); - if (tr.parent) - { - tailRotorPresent = true; - } - else - { - tailRotorPresent = false; - cerr << "# No tailrotor found, assuming a single rotor." << endl; - } + // get tail rotor parameters + tr.parent=rotor_element->FindElement("tailrotor"); + if (tr.parent) { + tailRotorPresent = true; + } else { + tailRotorPresent = false; + cerr << "# No tailrotor found, assuming a single rotor." << endl; + } - if (tailRotorPresent) - { - int flags = eTail; - if (Sense<0.0) - { - flags += eRotCW; - } - tr.configure(flags, &mr); - tr.rk.init(0,dt,6); - tr.RpmRatio = tr.NominalRPM/mr.NominalRPM; // 'connect' + if (tailRotorPresent) { + int flags = eTail; + if (Sense<0.0) { + flags += eRotCW; } + tr.configure(flags, &mr); + tr.rk.init(0,dt,6); + tr.RpmRatio = tr.NominalRPM/mr.NominalRPM; // 'connect' + } - /* remaining parameters */ + /* remaining parameters */ - // ground effect - double c_ground_effect = 0.0; // uh1 ~ 0.28 , larger values increase the effect - ground_effect_exp = 0.0; - ground_effect_shift = 0.0; + // ground effect + double c_ground_effect = 0.0; // uh1 ~ 0.28 , larger values increase the effect + ground_effect_exp = 0.0; + ground_effect_shift = 0.0; - if (rotor_element->FindElement("cgroundeffect")) - c_ground_effect = rotor_element->FindElementValueAsNumber("cgroundeffect"); + if (rotor_element->FindElement("cgroundeffect")) + c_ground_effect = rotor_element->FindElementValueAsNumber("cgroundeffect"); - if (rotor_element->FindElement("groundeffectshift")) - ground_effect_shift = rotor_element->FindElementValueAsNumberConvertTo("groundeffectshift","FT"); + if (rotor_element->FindElement("groundeffectshift")) + ground_effect_shift = rotor_element->FindElementValueAsNumberConvertTo("groundeffectshift","FT"); - // prepare calculations, see /TA77/ - if (c_ground_effect > 1e-5) - { - ground_effect_exp = 1.0 / ( 2.0*mr.Radius * c_ground_effect ); - } - else - { - ground_effect_exp = 0.0; // disable - } + // prepare calculations, see /TA77/ + if (c_ground_effect > 1e-5) { + ground_effect_exp = 1.0 / ( 2.0*mr.Radius * c_ground_effect ); + } else { + ground_effect_exp = 0.0; // disable + } - // smooth out jumps in hagl reported, otherwise the ground effect - // calculation would cause jumps too. 1Hz seems sufficient. - damp_hagl = Filter(1.0,dt); + // smooth out jumps in hagl reported, otherwise the ground effect + // calculation would cause jumps too. 1Hz seems sufficient. + damp_hagl = Filter(1.0,dt); - // misc, experimental - if (rotor_element->FindElement("hoverthreshold")) - hover_threshold = rotor_element->FindElementValueAsNumberConvertTo("hoverthreshold", "FT/SEC"); + // misc, experimental + if (rotor_element->FindElement("hoverthreshold")) + hover_threshold = rotor_element->FindElementValueAsNumberConvertTo("hoverthreshold", "FT/SEC"); - if (rotor_element->FindElement("hoverscale")) - hover_scale = rotor_element->FindElementValueAsNumber("hoverscale"); + if (rotor_element->FindElement("hoverscale")) + hover_scale = rotor_element->FindElementValueAsNumber("hoverscale"); - // enable import-export - bind(); + // enable import-export + bind(); - // unused right now - prop_rotorbrake->setDoubleValue(0.0); - prop_freewheel_factor->setDoubleValue(1.0); + // unused right now + prop_rotorbrake->setDoubleValue(0.0); + prop_freewheel_factor->setDoubleValue(1.0); - Debug(0); + Debug(0); } // Constructor @@ -807,232 +761,218 @@ FGRotor::FGRotor(FGFDMExec *exec, Element* rotor_element, int num) FGRotor::~FGRotor() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // mea-culpa - the connection to the engine might be wrong, but the calling // convention appears to be 'variable' too. -// piston call: +// piston call: // return Thruster->Calculate((Eng_HP * hptoftlbssec)-Thruster->GetPowerRequired()); -// turbine call: +// turbine call: // Thrust = Thruster->Calculate(Thrust); // allow thruster to modify thrust (i.e. reversing) // // Here 'Calculate' takes thrust and estimates the power provided. double FGRotor::Calculate(double PowerAvailable) { - // controls - double A_IC; // lateral (roll) control in radians - double B_IC; // longitudinal (pitch) control in radians - double theta_col; // main rotor collective pitch in radians - double tail_col; // tail rotor collective in radians + // controls + double A_IC; // lateral (roll) control in radians + double B_IC; // longitudinal (pitch) control in radians + double theta_col; // main rotor collective pitch in radians + double tail_col; // tail rotor collective in radians - // state - double h_agl_ft = 0.0; - double Vt ; + // state + double h_agl_ft = 0.0; + double Vt ; - FGColumnVector3 UVW_h; - FGColumnVector3 PQR_h; + FGColumnVector3 UVW_h; + FGColumnVector3 PQR_h; - /* total vehicle velocity including wind effects in feet per second. */ - Vt = fdmex->GetAuxiliary()->GetVt(); + /* total vehicle velocity including wind effects in feet per second. */ + Vt = fdmex->GetAuxiliary()->GetVt(); - dt = fdmex->GetDeltaT(); // might be variable ? + dt = fdmex->GetDeltaT(); // might be variable ? - dump_req = prop_DumpFlag; - prop_DumpFlag = 0; + dump_req = prop_DumpFlag; + prop_DumpFlag = 0; - // fetch often used values - rho = fdmex->GetAtmosphere()->GetDensity(); // slugs/ft^3. + // fetch often used values + rho = fdmex->GetAtmosphere()->GetDensity(); // slugs/ft^3. - UVW_h = fdmex->GetAuxiliary()->GetAeroUVW(); - PQR_h = fdmex->GetAuxiliary()->GetAeroPQR(); + UVW_h = fdmex->GetAuxiliary()->GetAeroUVW(); + PQR_h = fdmex->GetAuxiliary()->GetAeroPQR(); - // handle present RPM now, calc omega values. + // handle present RPM now, calc omega values. - if (RPM < mr.MinRPM) // kludge, otherwise calculations go bananas - { - RPM = mr.MinRPM; - } + if (RPM < mr.MinRPM) { // kludge, otherwise calculations go bananas + RPM = mr.MinRPM; + } - mr.ActualRPM = RPM; - mr.Omega = (RPM/60.0)*2.0*M_PI; + mr.ActualRPM = RPM; + mr.Omega = (RPM/60.0)*2.0*M_PI; - if (tailRotorPresent) - { - tr.ActualRPM = RPM*tr.RpmRatio; - tr.Omega = (RPM*tr.RpmRatio/60.0)*2.0*M_PI; - } + if (tailRotorPresent) { + tr.ActualRPM = RPM*tr.RpmRatio; + tr.Omega = (RPM*tr.RpmRatio/60.0)*2.0*M_PI; + } - // read control inputs + // read control inputs - A_IC = prop_lateral_ctrl->getDoubleValue(); - B_IC = prop_longitudinal_ctrl->getDoubleValue(); - theta_col = prop_collective_ctrl->getDoubleValue(); - tail_col = 0.0; - if (tailRotorPresent) - { - tail_col = prop_antitorque_ctrl->getDoubleValue(); - } + A_IC = prop_lateral_ctrl->getDoubleValue(); + B_IC = prop_longitudinal_ctrl->getDoubleValue(); + theta_col = prop_collective_ctrl->getDoubleValue(); + tail_col = 0.0; + if (tailRotorPresent) { + tail_col = prop_antitorque_ctrl->getDoubleValue(); + } - FGColumnVector3 vHub_ca = mr.hub_vel_body2ca(UVW_h,PQR_h,A_IC,B_IC); - FGColumnVector3 avFus_ca = mr.fus_angvel_body2ca(PQR_h); + FGColumnVector3 vHub_ca = mr.hub_vel_body2ca(UVW_h,PQR_h,A_IC,B_IC); + FGColumnVector3 avFus_ca = mr.fus_angvel_body2ca(PQR_h); - h_agl_ft = fdmex->GetPropagate()->GetDistanceAGL(); + h_agl_ft = fdmex->GetPropagate()->GetDistanceAGL(); - double filtered_hagl; - filtered_hagl = damp_hagl.execute( h_agl_ft + ground_effect_shift ); + double filtered_hagl; + filtered_hagl = damp_hagl.execute( h_agl_ft + ground_effect_shift ); - // gnuplot> plot [-1:50] 1 - exp((-x/44)/.28) - double ge_factor = 1.0; - if (ground_effect_exp > 1e-5) - { - ge_factor -= exp(-filtered_hagl*ground_effect_exp); - } - // clamp - if (ge_factor<0.5) ge_factor=0.5; + // gnuplot> plot [-1:50] 1 - exp((-x/44)/.28) + double ge_factor = 1.0; + if (ground_effect_exp > 1e-5) { + ge_factor -= exp(-filtered_hagl*ground_effect_exp); + } + // clamp + if (ge_factor<0.5) ge_factor=0.5; - if (dump_req) - { - printf("# GE h: %.3f (%.3f) f: %f\n", filtered_hagl, h_agl_ft + ground_effect_shift, ge_factor); - } + if (dump_req) { + printf("# GE h: %.3f (%.3f) f: %f\n", filtered_hagl, h_agl_ft + ground_effect_shift, ge_factor); + } - // EXPERIMENTAL: modify rotor for hover, see rotor::body_moments for the consequences - if (hover_threshold > 1e-5 && Vt < hover_threshold) - { - double scale = 1.0 - Vt/hover_threshold; - mr.HingeOffset_hover = scale*hover_scale*mr.Radius; - } - else - { - mr.HingeOffset_hover = 0.0; - } + // EXPERIMENTAL: modify rotor for hover, see rotor::body_moments for the consequences + if (hover_threshold > 1e-5 && Vt < hover_threshold) { + double scale = 1.0 - Vt/hover_threshold; + mr.HingeOffset_hover = scale*hover_scale*mr.Radius; + } else { + mr.HingeOffset_hover = 0.0; + } - // all set, start calculations + // all set, start calculations - /* MAIN ROTOR */ + /* MAIN ROTOR */ - mr.calc_flow_and_thrust(dt, rho, theta_col, vHub_ca(eU), vHub_ca(eW), ge_factor); + mr.calc_flow_and_thrust(dt, rho, theta_col, vHub_ca(eU), vHub_ca(eW), ge_factor); - prop_inflow_ratio_lambda = mr.lambda; - prop_advance_ratio_mu = mr.mu; - prop_inflow_ratio_induced_nu = mr.nu; - prop_thrust_coefficient = mr.Ct; + prop_inflow_ratio_lambda = mr.lambda; + prop_advance_ratio_mu = mr.mu; + prop_inflow_ratio_induced_nu = mr.nu; + prop_thrust_coefficient = mr.Ct; - mr.calc_coning_angle(rho, theta_col); - prop_coning_angle = mr.a0; + mr.calc_coning_angle(rho, theta_col); + prop_coning_angle = mr.a0; - mr.calc_torque(rho, theta_col); - prop_mr_torque = mr.Torque; + mr.calc_torque(rho, theta_col); + prop_mr_torque = mr.Torque; - mr.calc_flapping_angles(rho, theta_col, avFus_ca); - mr.calc_drag_and_side_forces(rho, theta_col); + mr.calc_flapping_angles(rho, theta_col, avFus_ca); + mr.calc_drag_and_side_forces(rho, theta_col); - FGColumnVector3 F_h_mr = mr.body_forces(A_IC,B_IC); - FGColumnVector3 M_h_mr = mr.body_moments(F_h_mr, A_IC, B_IC); + FGColumnVector3 F_h_mr = mr.body_forces(A_IC,B_IC); + FGColumnVector3 M_h_mr = mr.body_moments(F_h_mr, A_IC, B_IC); - // export downwash angles - // theta: positive for downwash moving from +z_h towards +x_h - // phi: positive for downwash moving from +z_h towards -y_h + // export downwash angles + // theta: positive for downwash moving from +z_h towards +x_h + // phi: positive for downwash moving from +z_h towards -y_h - prop_theta_downwash = atan2( - UVW_h(eU), mr.v_induced - UVW_h(eW)); - prop_phi_downwash = atan2( UVW_h(eV), mr.v_induced - UVW_h(eW)); + prop_theta_downwash = atan2( - UVW_h(eU), mr.v_induced - UVW_h(eW)); + prop_phi_downwash = atan2( UVW_h(eV), mr.v_induced - UVW_h(eW)); - mr.force(eX) = F_h_mr(1); - mr.force(eY) = F_h_mr(2); - mr.force(eZ) = F_h_mr(3); + mr.force(eX) = F_h_mr(1); + mr.force(eY) = F_h_mr(2); + mr.force(eZ) = F_h_mr(3); - mr.moment(eL) = M_h_mr(1); - mr.moment(eM) = M_h_mr(2); - mr.moment(eN) = M_h_mr(3); + mr.moment(eL) = M_h_mr(1); + mr.moment(eM) = M_h_mr(2); + mr.moment(eN) = M_h_mr(3); - /* TAIL ROTOR */ + /* TAIL ROTOR */ - FGColumnVector3 F_h_tr(0.0, 0.0, 0.0); - FGColumnVector3 M_h_tr(0.0, 0.0, 0.0); + FGColumnVector3 F_h_tr(0.0, 0.0, 0.0); + FGColumnVector3 M_h_tr(0.0, 0.0, 0.0); - if (tailRotorPresent) - { - FGColumnVector3 vHub_ca_tr = tr.hub_vel_body2ca(UVW_h,PQR_h); - FGColumnVector3 avFus_ca_tr = tr.fus_angvel_body2ca(PQR_h); + if (tailRotorPresent) { + FGColumnVector3 vHub_ca_tr = tr.hub_vel_body2ca(UVW_h,PQR_h); + FGColumnVector3 avFus_ca_tr = tr.fus_angvel_body2ca(PQR_h); - tr.calc_flow_and_thrust(dt, rho, tail_col, vHub_ca_tr(eU), vHub_ca_tr(eW)); - tr.calc_coning_angle(rho, tail_col); + tr.calc_flow_and_thrust(dt, rho, tail_col, vHub_ca_tr(eU), vHub_ca_tr(eW)); + tr.calc_coning_angle(rho, tail_col); - // test code for cantered tail rotor, see if it has a notable effect. /SH79/ eqn(47) - if (fabs(tr.CantAngleD3)>1e-5) - { - double tan_d3 = tan(tr.CantAngleD3); - double d_t0t; - double ca_dt = dt/12.0; - for (int i = 0; i<12; i++) - { - d_t0t = 1/0.1*(tail_col - tr.a0 * tan_d3 - effective_tail_col); - effective_tail_col += d_t0t*ca_dt; - } - } - else - { - effective_tail_col = tail_col; - } + // test code for cantered tail rotor, see if it has a notable effect. /SH79/ eqn(47) + if (fabs(tr.CantAngleD3)>1e-5) { + double tan_d3 = tan(tr.CantAngleD3); + double d_t0t; + double ca_dt = dt/12.0; + for (int i = 0; i<12; i++) { + d_t0t = 1/0.1*(tail_col - tr.a0 * tan_d3 - effective_tail_col); + effective_tail_col += d_t0t*ca_dt; + } + } else { + effective_tail_col = tail_col; + } - tr.calc_torque(rho, effective_tail_col); - tr.calc_flapping_angles(rho, effective_tail_col, avFus_ca_tr); - tr.calc_drag_and_side_forces(rho, effective_tail_col); + tr.calc_torque(rho, effective_tail_col); + tr.calc_flapping_angles(rho, effective_tail_col, avFus_ca_tr); + tr.calc_drag_and_side_forces(rho, effective_tail_col); - F_h_tr = tr.body_forces(); - M_h_tr = tr.body_moments(F_h_tr); - } + F_h_tr = tr.body_forces(); + M_h_tr = tr.body_moments(F_h_tr); + } - tr.force(eX) = F_h_tr(1) ; - tr.force(eY) = F_h_tr(2) ; - tr.force(eZ) = F_h_tr(3) ; - tr.moment(eL) = M_h_tr(1) ; - tr.moment(eM) = M_h_tr(2) ; - tr.moment(eN) = M_h_tr(3) ; - - /* - TODO: - check negative mr.Torque conditions - freewheel factor: assure [0..1] just multiply with available power - rotorbrake: just steal from available power - - */ - - // calculate new RPM, assuming a stiff connection between engine and rotor. - - double engine_hp = PowerAvailable/2.24; // 'undo' force via the estimation factor used in aeromatic - double engine_torque = 550.0*engine_hp/mr.Omega; - double Omega_dot = (engine_torque - mr.Torque) / mr.PolarMoment; - - RPM += ( Omega_dot * dt )/(2.0*M_PI) * 60.0; - - if (0 && dump_req) - { - printf("# SENSE : % d % d\n", mr.flags & eRotCW ? -1 : 1, tr.flags & eRotCW ? -1 : 1); - printf("# vi : % f % f\n", mr.v_induced, tr.v_induced); - printf("# a0 a1 b1 : % f % f % f\n", mr.a0, mr.a_1, mr.b_1 ); - printf("# m forces : % f % f % f\n", mr.force(eX), mr.force(eY), mr.force(eZ) ); - printf("# m moments : % f % f % f\n", mr.moment(eL), mr.moment(eM), mr.moment(eN) ); - printf("# t forces : % f % f % f\n", tr.force(eX), tr.force(eY), tr.force(eZ) ); - printf("# t moments : % f % f % f\n", tr.moment(eL), tr.moment(eM), tr.moment(eN) ); - } + tr.force(eX) = F_h_tr(1) ; + tr.force(eY) = F_h_tr(2) ; + tr.force(eZ) = F_h_tr(3) ; + tr.moment(eL) = M_h_tr(1) ; + tr.moment(eM) = M_h_tr(2) ; + tr.moment(eN) = M_h_tr(3) ; + +/* + TODO: + check negative mr.Torque conditions + freewheel factor: assure [0..1] just multiply with available power + rotorbrake: just steal from available power - // finally set vFn & vMn - vFn = mr.force + tr.force; - vMn = mr.moment + tr.moment; +*/ - // and just lie here - Thrust = 0.0; + // calculate new RPM, assuming a stiff connection between engine and rotor. - // return unmodified thrust to the turbine. - // :TK: As far as I can see the return value is unused. - return PowerAvailable; + double engine_hp = PowerAvailable/2.24; // 'undo' force via the estimation factor used in aeromatic + double engine_torque = 550.0*engine_hp/mr.Omega; + double Omega_dot = (engine_torque - mr.Torque) / mr.PolarMoment; + + RPM += ( Omega_dot * dt )/(2.0*M_PI) * 60.0; + + if (0 && dump_req) { + printf("# SENSE : % d % d\n", mr.flags & eRotCW ? -1 : 1, tr.flags & eRotCW ? -1 : 1); + printf("# vi : % f % f\n", mr.v_induced, tr.v_induced); + printf("# a0 a1 b1 : % f % f % f\n", mr.a0, mr.a_1, mr.b_1 ); + printf("# m forces : % f % f % f\n", mr.force(eX), mr.force(eY), mr.force(eZ) ); + printf("# m moments : % f % f % f\n", mr.moment(eL), mr.moment(eM), mr.moment(eN) ); + printf("# t forces : % f % f % f\n", tr.force(eX), tr.force(eY), tr.force(eZ) ); + printf("# t moments : % f % f % f\n", tr.moment(eL), tr.moment(eM), tr.moment(eN) ); + } + + // finally set vFn & vMn + vFn = mr.force + tr.force; + vMn = mr.moment + tr.moment; + + // and just lie here + Thrust = 0.0; + + // return unmodified thrust to the turbine. + // :TK: As far as I can see the return value is unused. + return PowerAvailable; } // Calculate @@ -1043,55 +983,54 @@ double FGRotor::Calculate(double PowerAvailable) double FGRotor::GetPowerRequired(void) { - PowerRequired = 0.0; - return PowerRequired; + PowerRequired = 0.0; + return PowerRequired; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGRotor::bind(void) -{ +bool FGRotor::bind(void) { + + string property_name, base_property_name; + base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum); + + PropertyManager->Tie( base_property_name + "/rotor-rpm", this, &FGRotor::GetRPM ); + PropertyManager->Tie( base_property_name + "/thrust-mr-lbs", &mr.Thrust ); + PropertyManager->Tie( base_property_name + "/vi-mr-fps", &mr.v_induced ); + PropertyManager->Tie( base_property_name + "/a0-mr-rad", &mr.a0 ); + PropertyManager->Tie( base_property_name + "/a1-mr-rad", &mr.a1s ); // s means shaft axes + PropertyManager->Tie( base_property_name + "/b1-mr-rad", &mr.b1s ); + PropertyManager->Tie( base_property_name + "/thrust-tr-lbs", &tr.Thrust ); + PropertyManager->Tie( base_property_name + "/vi-tr-fps", &tr.v_induced ); + + // lambda + PropertyManager->Tie( base_property_name + "/inflow-ratio", &prop_inflow_ratio_lambda ); + // mu + PropertyManager->Tie( base_property_name + "/advance-ratio", &prop_advance_ratio_mu ); + // nu + PropertyManager->Tie( base_property_name + "/induced-inflow-ratio", &prop_inflow_ratio_induced_nu ); + + PropertyManager->Tie( base_property_name + "/torque-mr-lbsft", &prop_mr_torque ); + PropertyManager->Tie( base_property_name + "/thrust-coefficient", &prop_thrust_coefficient ); + PropertyManager->Tie( base_property_name + "/main-rotor-rpm", &mr.ActualRPM ); + PropertyManager->Tie( base_property_name + "/tail-rotor-rpm", &tr.ActualRPM ); - string property_name, base_property_name; - base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum); - - PropertyManager->Tie( base_property_name + "/rotor-rpm", this, &FGRotor::GetRPM ); - PropertyManager->Tie( base_property_name + "/thrust-mr-lbs", &mr.Thrust ); - PropertyManager->Tie( base_property_name + "/vi-mr-fps", &mr.v_induced ); - PropertyManager->Tie( base_property_name + "/a0-mr-rad", &mr.a0 ); - PropertyManager->Tie( base_property_name + "/a1-mr-rad", &mr.a1s ); // s means shaft axes - PropertyManager->Tie( base_property_name + "/b1-mr-rad", &mr.b1s ); - PropertyManager->Tie( base_property_name + "/thrust-tr-lbs", &tr.Thrust ); - PropertyManager->Tie( base_property_name + "/vi-tr-fps", &tr.v_induced ); - - // lambda - PropertyManager->Tie( base_property_name + "/inflow-ratio", &prop_inflow_ratio_lambda ); - // mu - PropertyManager->Tie( base_property_name + "/advance-ratio", &prop_advance_ratio_mu ); - // nu - PropertyManager->Tie( base_property_name + "/induced-inflow-ratio", &prop_inflow_ratio_induced_nu ); - - PropertyManager->Tie( base_property_name + "/torque-mr-lbsft", &prop_mr_torque ); - PropertyManager->Tie( base_property_name + "/thrust-coefficient", &prop_thrust_coefficient ); - PropertyManager->Tie( base_property_name + "/main-rotor-rpm", &mr.ActualRPM ); - PropertyManager->Tie( base_property_name + "/tail-rotor-rpm", &tr.ActualRPM ); - - // position of the downwash - PropertyManager->Tie( base_property_name + "/theta-downwash-rad", &prop_theta_downwash ); - PropertyManager->Tie( base_property_name + "/phi-downwash-rad", &prop_phi_downwash ); - - // nodes to use via get<xyz>Value - prop_collective_ctrl = PropertyManager->GetNode(base_property_name + "/collective-ctrl-rad",true); - prop_lateral_ctrl = PropertyManager->GetNode(base_property_name + "/lateral-ctrl-rad",true); - prop_longitudinal_ctrl = PropertyManager->GetNode(base_property_name + "/longitudinal-ctrl-rad",true); - prop_antitorque_ctrl = PropertyManager->GetNode(base_property_name + "/antitorque-ctrl-rad",true); - - prop_rotorbrake = PropertyManager->GetNode(base_property_name + "/rotorbrake-hp", true); - prop_freewheel_factor = PropertyManager->GetNode(base_property_name + "/freewheel-factor", true); - - PropertyManager->Tie( base_property_name + "/dump-flag", &prop_DumpFlag ); - - return true; + // position of the downwash + PropertyManager->Tie( base_property_name + "/theta-downwash-rad", &prop_theta_downwash ); + PropertyManager->Tie( base_property_name + "/phi-downwash-rad", &prop_phi_downwash ); + + // nodes to use via get<xyz>Value + prop_collective_ctrl = PropertyManager->GetNode(base_property_name + "/collective-ctrl-rad",true); + prop_lateral_ctrl = PropertyManager->GetNode(base_property_name + "/lateral-ctrl-rad",true); + prop_longitudinal_ctrl = PropertyManager->GetNode(base_property_name + "/longitudinal-ctrl-rad",true); + prop_antitorque_ctrl = PropertyManager->GetNode(base_property_name + "/antitorque-ctrl-rad",true); + + prop_rotorbrake = PropertyManager->GetNode(base_property_name + "/rotorbrake-hp", true); + prop_freewheel_factor = PropertyManager->GetNode(base_property_name + "/freewheel-factor", true); + + PropertyManager->Tie( base_property_name + "/dump-flag", &prop_DumpFlag ); + + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1099,11 +1038,11 @@ bool FGRotor::bind(void) string FGRotor::GetThrusterLabels(int id, string delimeter) { - std::ostringstream buf; + std::ostringstream buf; - buf << Name << " RPM (engine " << id << ")"; + buf << Name << " RPM (engine " << id << ")"; - return buf.str(); + return buf.str(); } @@ -1111,11 +1050,11 @@ string FGRotor::GetThrusterLabels(int id, string delimeter) string FGRotor::GetThrusterValues(int id, string delimeter) { - std::ostringstream buf; + std::ostringstream buf; - buf << RPM; + buf << RPM; - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1139,38 +1078,30 @@ string FGRotor::GetThrusterValues(int id, string delimeter) void FGRotor::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << "\n Rotor Name: " << Name << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGRotor" << endl; - if (from == 1) cout << "Destroyed: FGRotor" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << "\n Rotor Name: " << Name << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGRotor" << endl; + if (from == 1) cout << "Destroyed: FGRotor" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } -} // namespace JSBSim +} // namespace JSBSim diff --git a/src/models/propulsion/FGRotor.h b/src/models/propulsion/FGRotor.h index 1077675b6e9af4390371515d2798f796cf51a07a..0663fba46ac474b2584c9f2fa10c025dc74f460b 100644 --- a/src/models/propulsion/FGRotor.h +++ b/src/models/propulsion/FGRotor.h @@ -52,8 +52,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -61,7 +60,7 @@ CLASS DOCUMENTATION /** Models a rotor system. The default configuration consists of main and tail rotor. A practical way to define the positions is to start with an - imaginary gear-box near the cg of the vehicle. + imaginary gear-box near the cg of the vehicle. In this case the location in the thruster definition should be approximately equal to the cg defined in the <tt>fdm_config/mass_balance</tt> @@ -110,7 +109,7 @@ CLASS DOCUMENTATION </rotor> // LENGTH means any of the supported units, same for ANGLE and MOMENT. -// Xunit-attributes are a hint for currently unsupported units, so +// Xunit-attributes are a hint for currently unsupported units, so // values must be provided accordingly. @endcode @@ -123,9 +122,9 @@ CLASS DOCUMENTATION \<diameter> - Rotor disk diameter (R). \<numblades> - Number of blades (b). \<xhub> - Relative height in body coordinate system, thus usually negative. - \<zhub> - Relative distance in body coordinate system, close to zero - for main rotor, and usually negative for the tail rotor. - \<nominalrpm> - RPM at which the rotor usally operates. + \<zhub> - Relative distance in body coordinate system, close to zero + for main rotor, and usually negative for the tail rotor. + \<nominalrpm> - RPM at which the rotor usally operates. \<minrpm> - Lowest RPM generated by the code, optional. \<chord> - Blade chord, (c). \<liftcurveslope> - Slope of curve of section lift against section angle of attack, @@ -140,25 +139,25 @@ CLASS DOCUMENTATION \<shafttilt> - Orientation of the rotor shaft, negative angles define a 'forward' tilt. Used by main rotor, optional. \<hingeoffset> - Rotor flapping-hinge offset (e). - + Experimental properties - + \<cantangle> - Flapping hinge cantangle used by tail rotor, optional. \<cgroundeffect> - Parameter for exponent in ground effect approximation. Value should be in the range 0.2 - 0.35, 0.0 disables, optional. - \<groundeffectshift> - Further adjustment of ground effect. + \<groundeffectshift> - Further adjustment of ground effect. </pre> -<h3>Notes:</h3> +<h3>Notes:</h3> The behavior of the rotor is controlled/influenced by 5 inputs.<ul> <li> The power provided by the engine. This is handled by the regular engine controls.</li> - <li> The collective control input. This is read from the <tt>fdm</tt> property + <li> The collective control input. This is read from the <tt>fdm</tt> property <tt>propulsion/engine[x]/collective-ctrl-rad</tt>.</li> <li> The lateral cyclic input. Read from <tt>propulsion/engine[x]/lateral-ctrl-rad</tt>.</li> - <li> The longitudinal cyclic input. Read from + <li> The longitudinal cyclic input. Read from <tt>propulsion/engine[x]/longitudinal-ctrl-rad</tt>.</li> <li> The tail collective (aka antitorque, aka pedal) control input. Read from <tt>propulsion/engine[x]/antitorque-ctrl-rad</tt>.</li> @@ -172,28 +171,28 @@ CLASS DOCUMENTATION To model a standalone main rotor just omit the <tailrotor/> element. If you provide a plain <tailrotor/> element all tail rotor parameters are estimated. - + The 'sense' parameter from the thruster is interpreted as follows, sense=1 means counter clockwise rotation of the main rotor, as viewed from above. This is as a far as I know more popular than clockwise rotation, which is defined by setting sense to -1 (to be honest, I'm just 99.9% sure that the orientation is handled properly). - + Concerning coaxial designs: By providing the 'variant' attribute with value 'coaxial' a Kamov-style rotor is modeled - i.e. the rotor produces no torque. -<h3>References:</h3> +<h3>References:</h3> - <dl> + <dl> <dt>/SH79/</dt><dd>Shaugnessy, J. D., Deaux, Thomas N., and Yenni, Kenneth R., - "Development and Validation of a Piloted Simulation of a + "Development and Validation of a Piloted Simulation of a Helicopter and External Sling Load", NASA TP-1285, 1979.</dd> <dt>/BA41/</dt><dd>Bailey,F.J.,Jr., "A Simplified Theoretical Method of Determining the Characteristics of a Lifting Rotor in Forward Flight", NACA Rep.716, 1941.</dd> <dt>/AM50/</dt><dd>Amer, Kenneth B.,"Theory of Helicopter Damping in Pitch or Roll and a Comparison With Flight Measurements", NACA TN-2136, 1950.</dd> <dt>/TA77/</dt><dd>Talbot, Peter D., Corliss, Lloyd D., "A Mathematical Force and Moment - Model of a UH-1H Helicopter for Flight Dynamics Simulations", NASA TM-73,254, 1977.</dd> + Model of a UH-1H Helicopter for Flight Dynamics Simulations", NASA TM-73,254, 1977.</dd> </dl> @author Thomas Kreitler @@ -204,213 +203,198 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGRotor : public FGThruster -{ - - enum eRotorFlags {eNone=0, eMain=1, eTail=2, eCoaxial=4, eRotCW=8} ; - struct rotor - { - - virtual ~rotor(); - void zero(); - void configure(int f, const rotor *xmain = NULL); - - // assist in parameter retrieval - double cnf_elem(const string& ename, double default_val=0.0, const string& unit = "", bool tell=false); - double cnf_elem(const string& ename, double default_val=0.0, bool tell=false); - - // rotor dynamics - void calc_flow_and_thrust(double dt, double rho, double theta_0, double Uw, double Ww, double flow_scale = 1.0); - - void calc_torque(double rho, double theta_0); - void calc_coning_angle(double rho, double theta_0); - void calc_flapping_angles(double rho, double theta_0, const FGColumnVector3 &pqr_fus_w); - void calc_drag_and_side_forces(double rho, double theta_0); - - // transformations - FGColumnVector3 hub_vel_body2ca( const FGColumnVector3 &uvw, const FGColumnVector3 &pqr, - double a_ic = 0.0 , double b_ic = 0.0 ); - FGColumnVector3 fus_angvel_body2ca( const FGColumnVector3 &pqr); - - FGColumnVector3 body_forces(double a_ic = 0.0 , double b_ic = 0.0 ); - FGColumnVector3 body_moments(FGColumnVector3 F_h, double a_ic = 0.0 , double b_ic = 0.0 ); - - // bookkeeping - int flags ; - Element *parent ; - - // used in flow calculation - // FGRK4 rk ; // use this after checking - FGRKFehlberg rk ; - int reports ; - - // configuration parameters - double Radius ; - int BladeNum ; - double RelDistance_xhub ; - double RelShift_yhub ; - double RelHeight_zhub ; - double NominalRPM ; - double MinRPM ; - double BladeChord ; - double LiftCurveSlope ; - double BladeFlappingMoment ; - double BladeTwist ; - double BladeMassMoment ; - double TipLossB ; - double PolarMoment ; - double InflowLag ; - double ShaftTilt ; - double HingeOffset ; - double HingeOffset_hover ; - double CantAngleD3 ; - - double theta_shaft ; - double phi_shaft ; - - // derived parameters - double LockNumberByRho ; - double solidity ; // aka sigma - double RpmRatio ; // main_to_tail, hmm - double R[5] ; // Radius powers - double B[6] ; // TipLossB powers - - FGMatrix33 BodyToShaft ; // [S]T, see /SH79/ eqn(17,18) - FGMatrix33 ShaftToBody ; // [S] - - // dynamic values - double ActualRPM ; - double Omega ; // must be > 0 - double beta_orient ; - double a0 ; // coning angle (rad) - double a_1, b_1, a_dw ; - double a1s, b1s ; // cyclic flapping relative to shaft axes, /SH79/ eqn(43) - double H_drag, J_side ; - - double Torque ; - double Thrust ; - double Ct ; - double lambda ; // inflow ratio - double mu ; // tip-speed ratio - double nu ; // induced inflow ratio - double v_induced ; // always positive [ft/s] - - // results - FGColumnVector3 force ; - FGColumnVector3 moment ; - - - // declare the problem function - class dnuFunction : public FGRungeKuttaProblem - { - public: - void update_params(rotor *r, double ct_t01, double fs, double w); - private: - double pFunc(double x, double y); - // some shortcuts - double k_sat, ct_lambda, k_wor, k_theta, mu2, k_flowscale; - } flowEquation; - - - }; +class FGRotor : public FGThruster { + + enum eRotorFlags {eNone=0, eMain=1, eTail=2, eCoaxial=4, eRotCW=8} ; + struct rotor { + + virtual ~rotor(); + void zero(); + void configure(int f, const rotor *xmain = NULL); + + // assist in parameter retrieval + double cnf_elem(const string& ename, double default_val=0.0, const string& unit = "", bool tell=false); + double cnf_elem(const string& ename, double default_val=0.0, bool tell=false); + + // rotor dynamics + void calc_flow_and_thrust(double dt, double rho, double theta_0, double Uw, double Ww, double flow_scale = 1.0); + + void calc_torque(double rho, double theta_0); + void calc_coning_angle(double rho, double theta_0); + void calc_flapping_angles(double rho, double theta_0, const FGColumnVector3 &pqr_fus_w); + void calc_drag_and_side_forces(double rho, double theta_0); + + // transformations + FGColumnVector3 hub_vel_body2ca( const FGColumnVector3 &uvw, const FGColumnVector3 &pqr, + double a_ic = 0.0 , double b_ic = 0.0 ); + FGColumnVector3 fus_angvel_body2ca( const FGColumnVector3 &pqr); + + FGColumnVector3 body_forces(double a_ic = 0.0 , double b_ic = 0.0 ); + FGColumnVector3 body_moments(FGColumnVector3 F_h, double a_ic = 0.0 , double b_ic = 0.0 ); + + // bookkeeping + int flags ; + Element *parent ; + + // used in flow calculation + // FGRK4 rk ; // use this after checking + FGRKFehlberg rk ; + int reports ; + + // configuration parameters + double Radius ; + int BladeNum ; + double RelDistance_xhub ; + double RelShift_yhub ; + double RelHeight_zhub ; + double NominalRPM ; + double MinRPM ; + double BladeChord ; + double LiftCurveSlope ; + double BladeFlappingMoment ; + double BladeTwist ; + double BladeMassMoment ; + double TipLossB ; + double PolarMoment ; + double InflowLag ; + double ShaftTilt ; + double HingeOffset ; + double HingeOffset_hover ; + double CantAngleD3 ; + + double theta_shaft ; + double phi_shaft ; + + // derived parameters + double LockNumberByRho ; + double solidity ; // aka sigma + double RpmRatio ; // main_to_tail, hmm + double R[5] ; // Radius powers + double B[6] ; // TipLossB powers + + FGMatrix33 BodyToShaft ; // [S]T, see /SH79/ eqn(17,18) + FGMatrix33 ShaftToBody ; // [S] + + // dynamic values + double ActualRPM ; + double Omega ; // must be > 0 + double beta_orient ; + double a0 ; // coning angle (rad) + double a_1, b_1, a_dw ; + double a1s, b1s ; // cyclic flapping relative to shaft axes, /SH79/ eqn(43) + double H_drag, J_side ; + + double Torque ; + double Thrust ; + double Ct ; + double lambda ; // inflow ratio + double mu ; // tip-speed ratio + double nu ; // induced inflow ratio + double v_induced ; // always positive [ft/s] + + // results + FGColumnVector3 force ; + FGColumnVector3 moment ; + + + // declare the problem function + class dnuFunction : public FGRungeKuttaProblem { + public: + void update_params(rotor *r, double ct_t01, double fs, double w); + private: + double pFunc(double x, double y); + // some shortcuts + double k_sat, ct_lambda, k_wor, k_theta, mu2, k_flowscale; + } flowEquation; + + + }; public: - /** Constructor - @param exec pointer to executive structure - @param rotor_element pointer to XML element in the config file - @param num the number of this rotor */ - FGRotor(FGFDMExec *exec, Element* rotor_element, int num); - - /// Destructor - ~FGRotor(); - - void SetRPM(double rpm) - { - RPM = rpm; - } - - /** Calculates forces and moments created by the rotor(s) and updates - vFn,vMn state variables. RPM changes are handled inside, too. - The RPM change is based on estimating the torque provided by the engine. - - @param PowerAvailable here this is the thrust (not power) provided by a turbine - @return PowerAvailable */ - double Calculate(double); - - double GetRPM(void) const - { - return RPM; - } - double GetDiameter(void) - { - return mr.Radius*2.0; - } - - // Stubs. Right now this rotor-to-engine interface is just a hack. - double GetTorque(void) - { - return 0.0; /* return mr.Torque;*/ - } - double GetPowerRequired(void); - - // Stubs. Only main rotor RPM is returned - string GetThrusterLabels(int id, string delimeter); - string GetThrusterValues(int id, string delimeter); + /** Constructor + @param exec pointer to executive structure + @param rotor_element pointer to XML element in the config file + @param num the number of this rotor */ + FGRotor(FGFDMExec *exec, Element* rotor_element, int num); -private: + /// Destructor + ~FGRotor(); + + void SetRPM(double rpm) {RPM = rpm;} - bool bind(void); + /** Calculates forces and moments created by the rotor(s) and updates + vFn,vMn state variables. RPM changes are handled inside, too. + The RPM change is based on estimating the torque provided by the engine. + + @param PowerAvailable here this is the thrust (not power) provided by a turbine + @return PowerAvailable */ + double Calculate(double); + + double GetRPM(void) const { return RPM; } + double GetDiameter(void) { return mr.Radius*2.0; } + + // Stubs. Right now this rotor-to-engine interface is just a hack. + double GetTorque(void) { return 0.0; /* return mr.Torque;*/ } + double GetPowerRequired(void); + + // Stubs. Only main rotor RPM is returned + string GetThrusterLabels(int id, string delimeter); + string GetThrusterValues(int id, string delimeter); + +private: - double RPM; - double Sense; // default is counter clockwise rotation of the main rotor (viewed from above) - bool tailRotorPresent; + bool bind(void); - void Debug(int from); + double RPM; + double Sense; // default is counter clockwise rotation of the main rotor (viewed from above) + bool tailRotorPresent; - FGPropertyManager* PropertyManager; + void Debug(int from); - rotor mr; - rotor tr; + FGPropertyManager* PropertyManager; - Filter damp_hagl; + rotor mr; + rotor tr; - double rho; + Filter damp_hagl; - double effective_tail_col; // /SH79/ eqn(47) + double rho; + + double effective_tail_col; // /SH79/ eqn(47) - double ground_effect_exp; - double ground_effect_shift; + double ground_effect_exp; + double ground_effect_shift; - double hover_threshold; - double hover_scale; + double hover_threshold; + double hover_scale; - // fdm imported controls - FGPropertyManager* prop_collective_ctrl; - FGPropertyManager* prop_lateral_ctrl; - FGPropertyManager* prop_longitudinal_ctrl; - FGPropertyManager* prop_antitorque_ctrl; + // fdm imported controls + FGPropertyManager* prop_collective_ctrl; + FGPropertyManager* prop_lateral_ctrl; + FGPropertyManager* prop_longitudinal_ctrl; + FGPropertyManager* prop_antitorque_ctrl; - FGPropertyManager* prop_freewheel_factor; - FGPropertyManager* prop_rotorbrake; + FGPropertyManager* prop_freewheel_factor; + FGPropertyManager* prop_rotorbrake; - // fdm export ... - double prop_inflow_ratio_lambda; - double prop_advance_ratio_mu; - double prop_inflow_ratio_induced_nu; - double prop_mr_torque; - double prop_coning_angle; + // fdm export ... + double prop_inflow_ratio_lambda; + double prop_advance_ratio_mu; + double prop_inflow_ratio_induced_nu; + double prop_mr_torque; + double prop_coning_angle; - double prop_theta_downwash; - double prop_phi_downwash; + double prop_theta_downwash; + double prop_phi_downwash; - double prop_thrust_coefficient; - double prop_lift_coefficient; + double prop_thrust_coefficient; + double prop_lift_coefficient; - double dt; // deltaT doesn't do the thing + double dt; // deltaT doesn't do the thing - // devel/debug stuff - int prop_DumpFlag; // causes 1-time dump on stdout + // devel/debug stuff + int prop_DumpFlag; // causes 1-time dump on stdout }; } diff --git a/src/models/propulsion/FGTank.cpp b/src/models/propulsion/FGTank.cpp index b48e926fc6f3d8215c20b56026a35af973a4c696..c9d38dab871b08c8396143f284d4a122098df3dd 100644 --- a/src/models/propulsion/FGTank.cpp +++ b/src/models/propulsion/FGTank.cpp @@ -46,8 +46,7 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { static const char *IdSrc = "$Id: FGTank.cpp,v 1.28 2010/01/24 19:26:04 jberndt Exp $"; static const char *IdHdr = ID_TANK; @@ -57,226 +56,212 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number) - : TankNumber(tank_number), Exec(exec) + : TankNumber(tank_number), Exec(exec) { - string token, strFuelName; - Element* element; - Element* element_Grain; - Area = 1.0; - Density = 6.6; - InitialTemperature = Temperature = -9999.0; - Ixx = Iyy = Izz = 0.0; - Radius = Contents = Standpipe = Length = InnerRadius = 0.0; - InitialStandpipe = 0.0; + string token, strFuelName; + Element* element; + Element* element_Grain; + Area = 1.0; + Density = 6.6; + InitialTemperature = Temperature = -9999.0; + Ixx = Iyy = Izz = 0.0; + Radius = Contents = Standpipe = Length = InnerRadius = 0.0; + InitialStandpipe = 0.0; + Capacity = 0.00001; + Priority = InitialPriority = 1; + PropertyManager = Exec->GetPropertyManager(); + vXYZ.InitMatrix(); + vXYZ_drain.InitMatrix(); + + type = el->GetAttributeValue("type"); + if (type == "FUEL") Type = ttFUEL; + else if (type == "OXIDIZER") Type = ttOXIDIZER; + else Type = ttUNKNOWN; + + element = el->FindElement("location"); + if (element) vXYZ = element->FindElementTripletConvertTo("IN"); + else cerr << "No location found for this tank." << endl; + + vXYZ_drain = vXYZ; // Set initial drain location to initial tank CG + + element = el->FindElement("drain_location"); + if (element) { + vXYZ_drain = element->FindElementTripletConvertTo("IN"); + } + + if (el->FindElement("radius")) + Radius = el->FindElementValueAsNumberConvertTo("radius", "IN"); + if (el->FindElement("capacity")) + Capacity = el->FindElementValueAsNumberConvertTo("capacity", "LBS"); + if (el->FindElement("contents")) + InitialContents = Contents = el->FindElementValueAsNumberConvertTo("contents", "LBS"); + if (el->FindElement("temperature")) + InitialTemperature = Temperature = el->FindElementValueAsNumber("temperature"); + if (el->FindElement("standpipe")) + InitialStandpipe = Standpipe = el->FindElementValueAsNumberConvertTo("standpipe", "LBS"); + if (el->FindElement("priority")) + InitialPriority = Priority = el->FindElementValueAsNumber("priority"); + if (el->FindElement("density")) + Density = el->FindElementValueAsNumberConvertTo("density", "LBS/GAL"); + if (el->FindElement("type")) + strFuelName = el->FindElementValue("type"); + + + SetPriority( InitialPriority ); // this will also set the Selected flag + + if (Capacity == 0) { + cerr << "Tank capacity must not be zero. Reset to 0.00001 lbs!" << endl; Capacity = 0.00001; - Priority = InitialPriority = 1; - PropertyManager = Exec->GetPropertyManager(); - vXYZ.InitMatrix(); - vXYZ_drain.InitMatrix(); - - type = el->GetAttributeValue("type"); - if (type == "FUEL") Type = ttFUEL; - else if (type == "OXIDIZER") Type = ttOXIDIZER; - else Type = ttUNKNOWN; - - element = el->FindElement("location"); - if (element) vXYZ = element->FindElementTripletConvertTo("IN"); - else cerr << "No location found for this tank." << endl; - - vXYZ_drain = vXYZ; // Set initial drain location to initial tank CG - - element = el->FindElement("drain_location"); - if (element) - { - vXYZ_drain = element->FindElementTripletConvertTo("IN"); - } - - if (el->FindElement("radius")) - Radius = el->FindElementValueAsNumberConvertTo("radius", "IN"); - if (el->FindElement("capacity")) - Capacity = el->FindElementValueAsNumberConvertTo("capacity", "LBS"); - if (el->FindElement("contents")) - InitialContents = Contents = el->FindElementValueAsNumberConvertTo("contents", "LBS"); - if (el->FindElement("temperature")) - InitialTemperature = Temperature = el->FindElementValueAsNumber("temperature"); - if (el->FindElement("standpipe")) - InitialStandpipe = Standpipe = el->FindElementValueAsNumberConvertTo("standpipe", "LBS"); - if (el->FindElement("priority")) - InitialPriority = Priority = el->FindElementValueAsNumber("priority"); - if (el->FindElement("density")) - Density = el->FindElementValueAsNumberConvertTo("density", "LBS/GAL"); - if (el->FindElement("type")) - strFuelName = el->FindElementValue("type"); - - - SetPriority( InitialPriority ); // this will also set the Selected flag - - if (Capacity == 0) - { - cerr << "Tank capacity must not be zero. Reset to 0.00001 lbs!" << endl; - Capacity = 0.00001; - Contents = 0.0; - } - PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0 - - // Check whether this is a solid propellant "tank". Initialize it if true. - - grainType = gtUNKNOWN; // This is the default - - element_Grain = el->FindElement("grain_config"); - if (element_Grain) - { - - strGType = element_Grain->GetAttributeValue("type"); - if (strGType == "CYLINDRICAL") grainType = gtCYLINDRICAL; - else if (strGType == "ENDBURNING") grainType = gtENDBURNING; - else cerr << "Unknown propellant grain type specified" << endl; - - if (element_Grain->FindElement("length")) - Length = element_Grain->FindElementValueAsNumberConvertTo("length", "IN"); - if (element_Grain->FindElement("bore_diameter")) - InnerRadius = element_Grain->FindElementValueAsNumberConvertTo("bore_diameter", "IN")/2.0; - - // Initialize solid propellant values for debug and runtime use. - - switch (grainType) - { - case gtCYLINDRICAL: - if (Radius <= InnerRadius) - { - cerr << "The bore diameter should be smaller than the total grain diameter!" << endl; - exit(-1); - } - Volume = M_PI * Length * (Radius*Radius - InnerRadius*InnerRadius); // cubic inches - break; - case gtENDBURNING: - Volume = M_PI * Length * Radius * Radius; // cubic inches - break; - case gtUNKNOWN: - cerr << "Unknown grain type found in this rocket engine definition." << endl; - exit(-1); + Contents = 0.0; + } + PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0 + + // Check whether this is a solid propellant "tank". Initialize it if true. + + grainType = gtUNKNOWN; // This is the default + + element_Grain = el->FindElement("grain_config"); + if (element_Grain) { + + strGType = element_Grain->GetAttributeValue("type"); + if (strGType == "CYLINDRICAL") grainType = gtCYLINDRICAL; + else if (strGType == "ENDBURNING") grainType = gtENDBURNING; + else cerr << "Unknown propellant grain type specified" << endl; + + if (element_Grain->FindElement("length")) + Length = element_Grain->FindElementValueAsNumberConvertTo("length", "IN"); + if (element_Grain->FindElement("bore_diameter")) + InnerRadius = element_Grain->FindElementValueAsNumberConvertTo("bore_diameter", "IN")/2.0; + + // Initialize solid propellant values for debug and runtime use. + + switch (grainType) { + case gtCYLINDRICAL: + if (Radius <= InnerRadius) { + cerr << "The bore diameter should be smaller than the total grain diameter!" << endl; + exit(-1); } - Density = (Contents*lbtoslug)/Volume; // slugs/in^3 - CalculateInertias(); + Volume = M_PI * Length * (Radius*Radius - InnerRadius*InnerRadius); // cubic inches + break; + case gtENDBURNING: + Volume = M_PI * Length * Radius * Radius; // cubic inches + break; + case gtUNKNOWN: + cerr << "Unknown grain type found in this rocket engine definition." << endl; + exit(-1); } - - string property_name, base_property_name; - base_property_name = CreateIndexedPropertyName("propulsion/tank", TankNumber); - property_name = base_property_name + "/contents-lbs"; - PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents, - &FGTank::SetContents ); - property_name = base_property_name + "/priority"; - PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority, - &FGTank::SetPriority ); - - if (Temperature != -9999.0) InitialTemperature = Temperature = FahrenheitToCelsius(Temperature); - Area = 40.0 * pow(Capacity/1975, 0.666666667); - - // A named fuel type will override a previous density value - if (!strFuelName.empty()) Density = ProcessFuelName(strFuelName); - - Debug(0); + Density = (Contents*lbtoslug)/Volume; // slugs/in^3 + CalculateInertias(); + } + + string property_name, base_property_name; + base_property_name = CreateIndexedPropertyName("propulsion/tank", TankNumber); + property_name = base_property_name + "/contents-lbs"; + PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents, + &FGTank::SetContents ); + property_name = base_property_name + "/priority"; + PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority, + &FGTank::SetPriority ); + + if (Temperature != -9999.0) InitialTemperature = Temperature = FahrenheitToCelsius(Temperature); + Area = 40.0 * pow(Capacity/1975, 0.666666667); + + // A named fuel type will override a previous density value + if (!strFuelName.empty()) Density = ProcessFuelName(strFuelName); + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGTank::~FGTank() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGTank::ResetToIC(void) { - SetTemperature( InitialTemperature ); - SetStandpipe ( InitialStandpipe ); - SetContents ( InitialContents ); - PctFull = 100.0*Contents/Capacity; - SetPriority( InitialPriority ); + SetTemperature( InitialTemperature ); + SetStandpipe ( InitialStandpipe ); + SetContents ( InitialContents ); + PctFull = 100.0*Contents/Capacity; + SetPriority( InitialPriority ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% const FGColumnVector3 FGTank::GetXYZ(void) { - return vXYZ_drain + (Contents/Capacity)*(vXYZ - vXYZ_drain); + return vXYZ_drain + (Contents/Capacity)*(vXYZ - vXYZ_drain); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% const double FGTank::GetXYZ(int idx) { - return vXYZ_drain(idx) + (Contents/Capacity)*(vXYZ(idx)-vXYZ_drain(idx)); + return vXYZ_drain(idx) + (Contents/Capacity)*(vXYZ(idx)-vXYZ_drain(idx)); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTank::Drain(double used) { - double remaining = Contents - used; + double remaining = Contents - used; - if (remaining >= 0) // Reduce contents by amount used. - { + if (remaining >= 0) { // Reduce contents by amount used. - Contents -= used; - PctFull = 100.0*Contents/Capacity; + Contents -= used; + PctFull = 100.0*Contents/Capacity; - } - else // This tank must be empty. - { + } else { // This tank must be empty. - Contents = 0.0; - PctFull = 0.0; - } + Contents = 0.0; + PctFull = 0.0; + } - if (grainType != gtUNKNOWN) CalculateInertias(); + if (grainType != gtUNKNOWN) CalculateInertias(); - return remaining; + return remaining; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTank::Fill(double amount) { - double overage = 0.0; - - Contents += amount; - - if (Contents > Capacity) - { - overage = Contents - Capacity; - Contents = Capacity; - PctFull = 100.0; - } - else - { - PctFull = Contents/Capacity*100.0; - } - return overage; + double overage = 0.0; + + Contents += amount; + + if (Contents > Capacity) { + overage = Contents - Capacity; + Contents = Capacity; + PctFull = 100.0; + } else { + PctFull = Contents/Capacity*100.0; + } + return overage; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGTank::SetContents(double amount) { - Contents = amount; - if (Contents > Capacity) - { - Contents = Capacity; - PctFull = 100.0; - } - else - { - PctFull = Contents/Capacity*100.0; - } + Contents = amount; + if (Contents > Capacity) { + Contents = Capacity; + PctFull = 100.0; + } else { + PctFull = Contents/Capacity*100.0; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGTank::SetContentsGallons(double gallons) { - SetContents(gallons * Density); + SetContents(gallons * Density); } @@ -284,17 +269,16 @@ void FGTank::SetContentsGallons(double gallons) double FGTank::Calculate(double dt) { - if (Temperature == -9999.0) return 0.0; - double HeatCapacity = 900.0; // Joules/lbm/C - double TempFlowFactor = 1.115; // Watts/sqft/C - double TAT = Exec->GetAuxiliary()->GetTAT_C(); - double Tdiff = TAT - Temperature; - double dTemp = 0.0; // Temp change due to one surface - if (fabs(Tdiff) > 0.1) - { - dTemp = (TempFlowFactor * Area * Tdiff * dt) / (Contents * HeatCapacity); - } - return Temperature += (dTemp + dTemp); // For now, assume upper/lower the same + if (Temperature == -9999.0) return 0.0; + double HeatCapacity = 900.0; // Joules/lbm/C + double TempFlowFactor = 1.115; // Watts/sqft/C + double TAT = Exec->GetAuxiliary()->GetTAT_C(); + double Tdiff = TAT - Temperature; + double dTemp = 0.0; // Temp change due to one surface + if (fabs(Tdiff) > 0.1) { + dTemp = (TempFlowFactor * Area * Tdiff * dt) / (Contents * HeatCapacity); + } + return Temperature += (dTemp + dTemp); // For now, assume upper/lower the same } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -304,39 +288,35 @@ double FGTank::Calculate(double dt) void FGTank::CalculateInertias(void) { - double Mass = Contents*lbtoslug; - double RadSumSqr; - double Rad2 = Radius*Radius; - - if (Density > 0.0) - { - Volume = (Contents*lbtoslug)/Density; // in^3 - } - else - { - cerr << endl << " Solid propellant grain density is zero!" << endl << endl; - exit(-1); - } - - switch (grainType) - { + double Mass = Contents*lbtoslug; + double RadSumSqr; + double Rad2 = Radius*Radius; + + if (Density > 0.0) { + Volume = (Contents*lbtoslug)/Density; // in^3 + } else { + cerr << endl << " Solid propellant grain density is zero!" << endl << endl; + exit(-1); + } + + switch (grainType) { case gtCYLINDRICAL: - InnerRadius = sqrt(Rad2 - Volume/(M_PI * Length)); - RadSumSqr = (Rad2 + InnerRadius*InnerRadius)/144.0; - Ixx = 0.5*Mass*RadSumSqr; - Iyy = Mass*(3.0*RadSumSqr + Length*Length/144.0)/12.0; - break; + InnerRadius = sqrt(Rad2 - Volume/(M_PI * Length)); + RadSumSqr = (Rad2 + InnerRadius*InnerRadius)/144.0; + Ixx = 0.5*Mass*RadSumSqr; + Iyy = Mass*(3.0*RadSumSqr + Length*Length/144.0)/12.0; + break; case gtENDBURNING: - Length = Volume/(M_PI*Rad2); - Ixx = 0.5*Mass*Rad2/144.0; - Iyy = Mass*(3.0*Rad2 + Length*Length)/(144.0*12.0); - break; + Length = Volume/(M_PI*Rad2); + Ixx = 0.5*Mass*Rad2/144.0; + Iyy = Mass*(3.0*Rad2 + Length*Length)/(144.0*12.0); + break; case gtUNKNOWN: - cerr << "Unknown grain type found." << endl; - exit(-1); - break; - } - Izz = Iyy; + cerr << "Unknown grain type found." << endl; + exit(-1); + break; + } + Izz = Iyy; } @@ -344,37 +324,36 @@ void FGTank::CalculateInertias(void) double FGTank::ProcessFuelName(std::string const& name) { - if (name == "AVGAS") return 6.02; - else if (name == "JET-A") return 6.74; - else if (name == "JET-A1") return 6.74; - else if (name == "JET-B") return 6.48; - else if (name == "JP-1") return 6.76; - else if (name == "JP-2") return 6.38; - else if (name == "JP-3") return 6.34; - else if (name == "JP-4") return 6.48; - else if (name == "JP-5") return 6.81; - else if (name == "JP-6") return 6.55; - else if (name == "JP-7") return 6.61; - else if (name == "JP-8") return 6.66; - else if (name == "JP-8+100") return 6.66; -//else if (name == "JP-9") return 6.74; -//else if (name == "JPTS") return 6.74; - else if (name == "RP-1") return 6.73; - else if (name == "T-1") return 6.88; - else if (name == "ETHANOL") return 6.58; - else if (name == "HYDRAZINE")return 8.61; - else if (name == "F-34") return 6.66; - else if (name == "F-35") return 6.74; - else if (name == "F-40") return 6.48; - else if (name == "F-44") return 6.81; - else if (name == "AVTAG") return 6.48; - else if (name == "AVCAT") return 6.81; - else - { - cerr << "Unknown fuel type specified: "<< name << endl; - } - - return 6.6; + if (name == "AVGAS") return 6.02; + else if (name == "JET-A") return 6.74; + else if (name == "JET-A1") return 6.74; + else if (name == "JET-B") return 6.48; + else if (name == "JP-1") return 6.76; + else if (name == "JP-2") return 6.38; + else if (name == "JP-3") return 6.34; + else if (name == "JP-4") return 6.48; + else if (name == "JP-5") return 6.81; + else if (name == "JP-6") return 6.55; + else if (name == "JP-7") return 6.61; + else if (name == "JP-8") return 6.66; + else if (name == "JP-8+100") return 6.66; + //else if (name == "JP-9") return 6.74; + //else if (name == "JPTS") return 6.74; + else if (name == "RP-1") return 6.73; + else if (name == "T-1") return 6.88; + else if (name == "ETHANOL") return 6.58; + else if (name == "HYDRAZINE")return 8.61; + else if (name == "F-34") return 6.66; + else if (name == "F-35") return 6.74; + else if (name == "F-40") return 6.48; + else if (name == "F-44") return 6.81; + else if (name == "AVTAG") return 6.48; + else if (name == "AVCAT") return 6.81; + else { + cerr << "Unknown fuel type specified: "<< name << endl; + } + + return 6.6; } @@ -399,41 +378,33 @@ double FGTank::ProcessFuelName(std::string const& name) void FGTank::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - cout << " " << type << " tank holds " << Capacity << " lbs. " << type << endl; - cout << " currently at " << PctFull << "% of maximum capacity" << endl; - cout << " Tank location (X, Y, Z): " << vXYZ(eX) << ", " << vXYZ(eY) << ", " << vXYZ(eZ) << endl; - cout << " Effective radius: " << Radius << " inches" << endl; - cout << " Initial temperature: " << Temperature << " Fahrenheit" << endl; - cout << " Priority: " << Priority << endl; - } + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " " << type << " tank holds " << Capacity << " lbs. " << type << endl; + cout << " currently at " << PctFull << "% of maximum capacity" << endl; + cout << " Tank location (X, Y, Z): " << vXYZ(eX) << ", " << vXYZ(eY) << ", " << vXYZ(eZ) << endl; + cout << " Effective radius: " << Radius << " inches" << endl; + cout << " Initial temperature: " << Temperature << " Fahrenheit" << endl; + cout << " Priority: " << Priority << endl; } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGTank" << endl; - if (from == 1) cout << "Destroyed: FGTank" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { - } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGTank" << endl; + if (from == 1) cout << "Destroyed: FGTank" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/propulsion/FGTank.h b/src/models/propulsion/FGTank.h index c6f5cf13ddeae8d1728d961db5ad31d49bd83689..12e7e5fc9e6b2899399888ea4d9028f1966e45f8 100644 --- a/src/models/propulsion/FGTank.h +++ b/src/models/propulsion/FGTank.h @@ -58,8 +58,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class Element; class FGPropertyManager; @@ -72,7 +71,7 @@ CLASS DOCUMENTATION /** Models a fuel tank. <h3>Fuel Temperature:</h3> - + Fuel temperature is calculated using the following assumptions: Fuel temperature will only be calculated for tanks which have an initial fuel @@ -80,12 +79,12 @@ CLASS DOCUMENTATION The surface area of the tank is estimated from the capacity in pounds. It is assumed that the tank is a wing tank with dimensions h by 4h by 10h. The - volume of the tank is then 40(h)(h)(h). The area of the upper or lower + volume of the tank is then 40(h)(h)(h). The area of the upper or lower surface is then 40(h)(h). The volume is also equal to the capacity divided by 49.368 lbs/cu-ft, for jet fuel. The surface area of one side can then be - derived from the tank's capacity. + derived from the tank's capacity. - The heat capacity of jet fuel is assumed to be 900 Joules/lbm/K, and the + The heat capacity of jet fuel is assumed to be 900 Joules/lbm/K, and the heat transfer factor of the tank is 1.115 Watts/sq-ft/K. <h3>Fuel Dump:</h3> @@ -101,7 +100,7 @@ CLASS DOCUMENTATION tree at <tt>propulsion/tank[i]/contents-lbs</tt>, where i is the tank number (Tanks are automatically numbered, starting at zero, in the order in which they are read in the aircraft configuration file). The latter method allows one to use a system of FCS - components to control tank contents. + components to control tank contents. <h3>Configuration File Format:</h3> @@ -186,200 +185,136 @@ CLASS DECLARATION class FGTank : public FGJSBBase { public: - /** Constructor. - The constructor reads in the defining parameters from a configuration file. - @param exec a pointer to the base FGFDMExec instance. - @param el a pointer to the Tank element. - @param tank_number the tank number (zero based). - */ - FGTank(FGFDMExec* exec, Element* el, int tank_number); - /// Destructor - ~FGTank(); - - enum TankType {ttUNKNOWN, ttFUEL, ttOXIDIZER}; - enum GrainType {gtUNKNOWN, gtCYLINDRICAL, gtENDBURNING}; - - /** Removes fuel from the tank. - This function removes fuel from a tank. If the tank empties, it is - deselected. - @param used the amount of fuel used in lbs. - @return the remaining contents of the tank in lbs. - */ - double Drain(double used); - - /** Performs local, tanks-specific calculations, such as fuel temperature. - This function calculates the temperature of the fuel in the tank. - @param dt the time step for this model. - @return the current temperature in degrees Celsius. - */ - double Calculate(double dt); - - /** Retrieves the type of tank: Fuel or Oxidizer. - @return the tank type, 0 for undefined, 1 for fuel, and 2 for oxidizer. - */ - int GetType(void) - { - return Type; - } - - /** Resets the tank parameters to the initial conditions */ - void ResetToIC(void); - - /** If the tank is set to supply fuel, this function returns true. - @return true if this tank is set to a non-zero priority.*/ - bool GetSelected(void) - { - return Selected; - } - - /** Gets the tank fill level. - @return the fill level in percent, from 0 to 100.*/ - double GetPctFull(void) - { - return PctFull; - } - - /** Gets the capacity of the tank. - @return the capacity of the tank in pounds. */ - double GetCapacity(void) - { - return Capacity; - } - - /** Gets the capacity of the tank. - @return the capacity of the tank in gallons. */ - double GetCapacityGallons(void) - { - return Capacity/Density; - } - - /** Gets the contents of the tank. - @return the contents of the tank in pounds. */ - double GetContents(void) const - { - return Contents; - } - - /** Gets the contents of the tank. - @return the contents of the tank in gallons. */ - double GetContentsGallons(void) const - { - return Contents/Density; - } - - /** Gets the temperature of the fuel. - The temperature of the fuel is calculated if an initial tempearture is - given in the configuration file. - @return the temperature of the fuel in degrees C IF an initial temperature - is given, otherwise 0.0 C is returned. */ - double GetTemperature_degC(void) - { - return Temperature; - } - - /** Gets the temperature of the fuel. - The temperature of the fuel is calculated if an initial tempearture is - given in the configuration file. - @return the temperature of the fuel in degrees F IF an initial temperature - is given, otherwise 32 degrees F is returned. */ - double GetTemperature(void) - { - return CelsiusToFahrenheit(Temperature); - } - - /** Returns the density of a named fuel type. - @return the density, in lbs/gal, or 6.6 if name cannot be resolved. */ - double ProcessFuelName(std::string const& name); - - double GetIxx(void) - { - return Ixx; - } - double GetIyy(void) - { - return Iyy; - } - double GetIzz(void) - { - return Izz; - } - - double GetStandpipe(void) - { - return Standpipe; - } - - int GetPriority(void) const - { - return Priority; - } - void SetPriority(int p) - { - Priority = p; - Selected = p>0 ? true:false; - } - - double GetDensity(void) const - { - return Density; - } - void SetDensity(double d) - { - Density = d; - } - - const FGColumnVector3 GetXYZ(void); - const double GetXYZ(int idx); - - const GrainType GetGrainType(void) - { - return grainType; - } - - double Fill(double amount); - void SetContents(double amount); - void SetContentsGallons(double gallons); - void SetTemperature(double temp) - { - Temperature = temp; - } - void SetStandpipe(double amount) - { - Standpipe = amount; - } - void SetSelected(bool sel) - { - sel==true ? SetPriority(1):SetPriority(0); - } + /** Constructor. + The constructor reads in the defining parameters from a configuration file. + @param exec a pointer to the base FGFDMExec instance. + @param el a pointer to the Tank element. + @param tank_number the tank number (zero based). + */ + FGTank(FGFDMExec* exec, Element* el, int tank_number); + /// Destructor + ~FGTank(); + + enum TankType {ttUNKNOWN, ttFUEL, ttOXIDIZER}; + enum GrainType {gtUNKNOWN, gtCYLINDRICAL, gtENDBURNING}; + + /** Removes fuel from the tank. + This function removes fuel from a tank. If the tank empties, it is + deselected. + @param used the amount of fuel used in lbs. + @return the remaining contents of the tank in lbs. + */ + double Drain(double used); + + /** Performs local, tanks-specific calculations, such as fuel temperature. + This function calculates the temperature of the fuel in the tank. + @param dt the time step for this model. + @return the current temperature in degrees Celsius. + */ + double Calculate(double dt); + + /** Retrieves the type of tank: Fuel or Oxidizer. + @return the tank type, 0 for undefined, 1 for fuel, and 2 for oxidizer. + */ + int GetType(void) {return Type;} + + /** Resets the tank parameters to the initial conditions */ + void ResetToIC(void); + + /** If the tank is set to supply fuel, this function returns true. + @return true if this tank is set to a non-zero priority.*/ + bool GetSelected(void) {return Selected;} + + /** Gets the tank fill level. + @return the fill level in percent, from 0 to 100.*/ + double GetPctFull(void) {return PctFull;} + + /** Gets the capacity of the tank. + @return the capacity of the tank in pounds. */ + double GetCapacity(void) {return Capacity;} + + /** Gets the capacity of the tank. + @return the capacity of the tank in gallons. */ + double GetCapacityGallons(void) {return Capacity/Density;} + + /** Gets the contents of the tank. + @return the contents of the tank in pounds. */ + double GetContents(void) const {return Contents;} + + /** Gets the contents of the tank. + @return the contents of the tank in gallons. */ + double GetContentsGallons(void) const {return Contents/Density;} + + /** Gets the temperature of the fuel. + The temperature of the fuel is calculated if an initial tempearture is + given in the configuration file. + @return the temperature of the fuel in degrees C IF an initial temperature + is given, otherwise 0.0 C is returned. */ + double GetTemperature_degC(void) {return Temperature;} + + /** Gets the temperature of the fuel. + The temperature of the fuel is calculated if an initial tempearture is + given in the configuration file. + @return the temperature of the fuel in degrees F IF an initial temperature + is given, otherwise 32 degrees F is returned. */ + double GetTemperature(void) {return CelsiusToFahrenheit(Temperature);} + + /** Returns the density of a named fuel type. + @return the density, in lbs/gal, or 6.6 if name cannot be resolved. */ + double ProcessFuelName(std::string const& name); + + double GetIxx(void) {return Ixx;} + double GetIyy(void) {return Iyy;} + double GetIzz(void) {return Izz;} + + double GetStandpipe(void) {return Standpipe;} + + int GetPriority(void) const {return Priority;} + void SetPriority(int p) { Priority = p; Selected = p>0 ? true:false; } + + double GetDensity(void) const {return Density;} + void SetDensity(double d) { Density = d; } + + const FGColumnVector3 GetXYZ(void); + const double GetXYZ(int idx); + + const GrainType GetGrainType(void) {return grainType;} + + double Fill(double amount); + void SetContents(double amount); + void SetContentsGallons(double gallons); + void SetTemperature(double temp) { Temperature = temp; } + void SetStandpipe(double amount) { Standpipe = amount; } + void SetSelected(bool sel) { sel==true ? SetPriority(1):SetPriority(0); } private: - TankType Type; - GrainType grainType; - int TankNumber; - std::string type; - std::string strGType; - FGColumnVector3 vXYZ; - FGColumnVector3 vXYZ_drain; - double Capacity; - double Radius; - double InnerRadius; - double Length; - double Volume; - double Density; - double Ixx; - double Iyy; - double Izz; - double PctFull; - double Contents, InitialContents; - double Area; - double Temperature, InitialTemperature; - double Standpipe, InitialStandpipe; - bool Selected; - int Priority, InitialPriority; - FGFDMExec* Exec; - FGPropertyManager* PropertyManager; - void CalculateInertias(void); - void Debug(int from); + TankType Type; + GrainType grainType; + int TankNumber; + std::string type; + std::string strGType; + FGColumnVector3 vXYZ; + FGColumnVector3 vXYZ_drain; + double Capacity; + double Radius; + double InnerRadius; + double Length; + double Volume; + double Density; + double Ixx; + double Iyy; + double Izz; + double PctFull; + double Contents, InitialContents; + double Area; + double Temperature, InitialTemperature; + double Standpipe, InitialStandpipe; + bool Selected; + int Priority, InitialPriority; + FGFDMExec* Exec; + FGPropertyManager* PropertyManager; + void CalculateInertias(void); + void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/propulsion/FGThruster.cpp b/src/models/propulsion/FGThruster.cpp index 130ab59bf77554db7e3b504540c078282721683e..5af8c1ddd50193ceb8b33b4f3a6542249bec4812 100644 --- a/src/models/propulsion/FGThruster.cpp +++ b/src/models/propulsion/FGThruster.cpp @@ -43,10 +43,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGThruster.cpp,v 1.12 2009/10/24 22:59:30 jberndt Exp $"; +static const char *IdSrc = "$Id: FGThruster.cpp,v 1.13 2010/08/21 22:56:11 jberndt Exp $"; static const char *IdHdr = ID_THRUSTER; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -56,79 +55,79 @@ CLASS IMPLEMENTATION FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMExec) { - Element* thruster_element = el->GetParent(); - Element* element; - FGColumnVector3 location, orientation; + Element* thruster_element = el->GetParent(); + Element* element; + FGColumnVector3 location, orientation; - Type = ttDirect; - SetTransformType(FGForce::tCustom); + Type = ttDirect; + SetTransformType(FGForce::tCustom); - Name = el->GetAttributeValue("name"); + Name = el->GetAttributeValue("name"); - GearRatio = 1.0; - ReverserAngle = 0.0; - EngineNum = num; - PropertyManager = FDMExec->GetPropertyManager(); + GearRatio = 1.0; + ReverserAngle = 0.0; + EngineNum = num; + PropertyManager = FDMExec->GetPropertyManager(); // Determine the initial location and orientation of this thruster and load the // thruster with this information. - element = thruster_element->FindElement("location"); - if (element) location = element->FindElementTripletConvertTo("IN"); - else cerr << "No thruster location found." << endl; - - element = thruster_element->FindElement("orient"); - if (element) orientation = element->FindElementTripletConvertTo("RAD"); - else cerr << "No thruster orientation found." << endl; - - SetLocation(location); - SetAnglesToBody(orientation); - - string property_name, base_property_name; - base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum); - property_name = base_property_name + "/pitch-angle-rad"; - PropertyManager->Tie( property_name.c_str(), (FGForce *)this, &FGForce::GetPitch, &FGForce::SetPitch); - property_name = base_property_name + "/yaw-angle-rad"; - PropertyManager->Tie( property_name.c_str(), (FGForce *)this, &FGForce::GetYaw, &FGForce::SetYaw); - - if (el->GetName() == "direct") // this is a direct thruster. At this time - // only a direct thruster can be reversed. - { - property_name = base_property_name + "/reverser-angle-rad"; - PropertyManager->Tie( property_name.c_str(), (FGThruster *)this, &FGThruster::GetReverserAngle, - &FGThruster::SetReverserAngle); - } - - Debug(0); + element = thruster_element->FindElement("location"); + if (element) location = element->FindElementTripletConvertTo("IN"); + else cerr << fgred << " No thruster location found." << reset << endl; + + element = thruster_element->FindElement("orient"); + if (element) orientation = element->FindElementTripletConvertTo("RAD"); + else cerr << " No thruster orientation found." << endl; + + SetLocation(location); + SetAnglesToBody(orientation); + + string property_name, base_property_name; + base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum); + property_name = base_property_name + "/pitch-angle-rad"; + PropertyManager->Tie( property_name.c_str(), (FGForce *)this, &FGForce::GetPitch, &FGForce::SetPitch); + property_name = base_property_name + "/yaw-angle-rad"; + PropertyManager->Tie( property_name.c_str(), (FGForce *)this, &FGForce::GetYaw, &FGForce::SetYaw); + + if (el->GetName() == "direct") // this is a direct thruster. At this time + // only a direct thruster can be reversed. + { + property_name = base_property_name + "/reverser-angle-rad"; + PropertyManager->Tie( property_name.c_str(), (FGThruster *)this, &FGThruster::GetReverserAngle, + &FGThruster::SetReverserAngle); + } + + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGThruster::~FGThruster() { - Debug(1); + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGThruster::GetThrusterLabels(int id, string delimeter) { - std::ostringstream buf; + std::ostringstream buf; - buf << Name << " Thrust (engine " << id << " in lbs)"; + buf << Name << " Thrust (engine " << id << " in lbs)"; - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGThruster::GetThrusterValues(int id, string delimeter) { - std::ostringstream buf; + std::ostringstream buf; - buf << Thrust; + buf << Thrust; - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -152,36 +151,28 @@ string FGThruster::GetThrusterValues(int id, string delimeter) void FGThruster::Debug(int from) { - if (debug_lvl <= 0) return; + if (debug_lvl <= 0) return; - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGThruster" << endl; - if (from == 1) cout << "Destroyed: FGThruster" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { - } - if (debug_lvl & 16) // Sanity checking - { } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGThruster" << endl; + if (from == 1) cout << "Destroyed: FGThruster" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/propulsion/FGThruster.h b/src/models/propulsion/FGThruster.h index 0a566ed6324f662841d73a4523f311400340d3fb..118005f5a408b0498619efcf6c82230cb7197b8d 100644 --- a/src/models/propulsion/FGThruster.h +++ b/src/models/propulsion/FGThruster.h @@ -52,8 +52,7 @@ DEFINITIONS FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class Element; class FGPropertyManager; @@ -69,11 +68,11 @@ CLASS DOCUMENTATION "Reverser angle" as used here is a way to manipulate the thrust vector, along the thrust axis ONLY, during run time. This should not be confused with a thrust vectoring nozzle. The angle is defined in radians, and is - used thus: Final_thrust = cosine( reverser_angle ) * unmodified_thrust. + used thus: Final_thrust = cosine( reverser_angle ) * unmodified_thrust. Therefore a reverser angle of 0 results in no change, and a reverser angle of 3.14 (pi) results in a completely reversed thrust vector. An angle of 1.57 (pi/2) results in no thrust at all. - + @author Jon Berndt @version $Id: FGThruster.h,v 1.15 2009/10/24 22:59:30 jberndt Exp $ */ @@ -82,79 +81,47 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGThruster : public FGForce -{ +class FGThruster : public FGForce { public: - /// Constructor - FGThruster(FGFDMExec *FDMExec, Element *el, int num ); - /// Destructor - virtual ~FGThruster(); - - enum eType {ttNozzle, ttRotor, ttPropeller, ttDirect}; - - virtual double Calculate(double tt) - { - Thrust = cos(ReverserAngle)*tt; - vFn(1) = Thrust; - return Thrust; - } - void SetName(string name) - { - Name = name; - } - virtual void SetRPM(double rpm) {}; - virtual double GetPowerRequired(void) - { - return 0.0; - } - virtual void SetdeltaT(double dt) - { - deltaT = dt; - } - double GetThrust(void) const - { - return Thrust; - } - eType GetType(void) - { - return Type; - } - string GetName(void) - { - return Name; - } - void SetReverserAngle(double angle) - { - ReverserAngle = angle; - } - double GetReverserAngle(void) const - { - return ReverserAngle; - } - virtual double GetRPM(void) const - { - return 0.0; - }; - double GetGearRatio(void) - { - return GearRatio; - } - virtual string GetThrusterLabels(int id, string delimeter); - virtual string GetThrusterValues(int id, string delimeter); + /// Constructor + FGThruster(FGFDMExec *FDMExec, Element *el, int num ); + /// Destructor + virtual ~FGThruster(); + + enum eType {ttNozzle, ttRotor, ttPropeller, ttDirect}; + + virtual double Calculate(double tt) { + Thrust = cos(ReverserAngle)*tt; + vFn(1) = Thrust; + return Thrust; + } + void SetName(string name) {Name = name;} + virtual void SetRPM(double rpm) {}; + virtual double GetPowerRequired(void) {return 0.0;} + virtual void SetdeltaT(double dt) {deltaT = dt;} + double GetThrust(void) const {return Thrust;} + eType GetType(void) {return Type;} + string GetName(void) {return Name;} + void SetReverserAngle(double angle) {ReverserAngle = angle;} + double GetReverserAngle(void) const {return ReverserAngle;} + virtual double GetRPM(void) const { return 0.0; }; + double GetGearRatio(void) {return GearRatio; } + virtual string GetThrusterLabels(int id, string delimeter); + virtual string GetThrusterValues(int id, string delimeter); protected: - eType Type; - string Name; - double Thrust; - double PowerRequired; - double deltaT; - double GearRatio; - double ThrustCoeff; - double ReverserAngle; - int EngineNum; - FGPropertyManager* PropertyManager; - virtual void Debug(int from); + eType Type; + string Name; + double Thrust; + double PowerRequired; + double deltaT; + double GearRatio; + double ThrustCoeff; + double ReverserAngle; + int EngineNum; + FGPropertyManager* PropertyManager; + virtual void Debug(int from); }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/models/propulsion/FGTurbine.cpp b/src/models/propulsion/FGTurbine.cpp index 08b90158f7bb28efc6a54b800b16081936b4a025..485c01c9421533e2ef9e81891888d37e561fc33d 100644 --- a/src/models/propulsion/FGTurbine.cpp +++ b/src/models/propulsion/FGTurbine.cpp @@ -49,10 +49,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.27 2010/05/24 11:26:37 jberndt Exp $"; +static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.29 2010/08/31 04:01:32 jberndt Exp $"; static const char *IdHdr = ID_TURBINE; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -61,326 +60,281 @@ CLASS IMPLEMENTATION FGTurbine::FGTurbine(FGFDMExec* exec, Element *el, int engine_number) - : FGEngine(exec, el, engine_number) + : FGEngine(exec, el, engine_number) { - Type = etTurbine; - - MilThrust = MaxThrust = 10000.0; - TSFC = 0.8; - ATSFC = 1.7; - IdleN1 = 30.0; - IdleN2 = 60.0; - MaxN1 = MaxN2 = 100.0; - Augmented = AugMethod = Injected = 0; - BypassRatio = BleedDemand = 0.0; - IdleThrustLookup = MilThrustLookup = MaxThrustLookup = InjectionLookup = 0; - N1_spinup = 1.0; - N2_spinup = 3.0; - - ResetToIC(); - - Load(exec, el); - Debug(0); + Type = etTurbine; + + MilThrust = MaxThrust = 10000.0; + TSFC = 0.8; + ATSFC = 1.7; + IdleN1 = 30.0; + IdleN2 = 60.0; + MaxN1 = MaxN2 = 100.0; + Augmented = AugMethod = Injected = 0; + BypassRatio = BleedDemand = 0.0; + IdleThrustLookup = MilThrustLookup = MaxThrustLookup = InjectionLookup = 0; + N1_spinup = 1.0; N2_spinup = 3.0; + + ResetToIC(); + + Load(exec, el); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGTurbine::~FGTurbine() { - delete IdleThrustLookup; - delete MilThrustLookup; - delete MaxThrustLookup; - delete InjectionLookup; - Debug(1); + delete IdleThrustLookup; + delete MilThrustLookup; + delete MaxThrustLookup; + delete InjectionLookup; + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGTurbine::ResetToIC(void) { - N1 = N2 = 0.0; - N2norm = 0.0; - correctedTSFC = TSFC; - ThrottlePos = AugmentCmd = 0.0; - InletPosition = NozzlePosition = 1.0; - Stalled = Seized = Overtemp = Fire = Augmentation = Injection = Reversed = false; - Cutoff = true; - phase = tpOff; - TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556; - EGT_degC = TAT; - OilTemp_degK = TAT + 273.0; + N1 = N2 = 0.0; + N2norm = 0.0; + correctedTSFC = TSFC; + ThrottlePos = AugmentCmd = 0.0; + InletPosition = NozzlePosition = 1.0; + Stalled = Seized = Overtemp = Fire = Augmentation = Injection = Reversed = false; + Cutoff = true; + phase = tpOff; + TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556; + EGT_degC = TAT; + OilTemp_degK = TAT + 273.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // The main purpose of Calculate() is to determine what phase the engine should // be in, then call the corresponding function. -double FGTurbine::Calculate(void) +void FGTurbine::Calculate(void) { - double thrust; - - TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556; - double qbar = Auxiliary->Getqbar(); - dt = FDMExec->GetDeltaT() * Propulsion->GetRate(); - ThrottlePos = FCS->GetThrottlePos(EngineNumber); - if (ThrottlePos > 1.0) - { - AugmentCmd = ThrottlePos - 1.0; - ThrottlePos -= AugmentCmd; - } - else - { - AugmentCmd = 0.0; - } - - // When trimming is finished check if user wants engine OFF or RUNNING - if ((phase == tpTrim) && (dt > 0)) - { - if (Running && !Starved) - { - phase = tpRun; - N2 = IdleN2 + ThrottlePos * N2_factor; - N1 = IdleN1 + ThrottlePos * N1_factor; - OilTemp_degK = 366.0; - Cutoff = false; - } - else - { - phase = tpOff; - Cutoff = true; - EGT_degC = TAT; - } + double thrust; + + RunPreFunctions(); + + TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556; + double qbar = Auxiliary->Getqbar(); + dt = FDMExec->GetDeltaT() * Propulsion->GetRate(); + ThrottlePos = FCS->GetThrottlePos(EngineNumber); + if (ThrottlePos > 1.0) { + AugmentCmd = ThrottlePos - 1.0; + ThrottlePos -= AugmentCmd; + } else { + AugmentCmd = 0.0; + } + + // When trimming is finished check if user wants engine OFF or RUNNING + if ((phase == tpTrim) && (dt > 0)) { + if (Running && !Starved) { + phase = tpRun; + N2 = IdleN2 + ThrottlePos * N2_factor; + N1 = IdleN1 + ThrottlePos * N1_factor; + OilTemp_degK = 366.0; + Cutoff = false; + } + else { + phase = tpOff; + Cutoff = true; + EGT_degC = TAT; + } } - if (!Running && Cutoff && Starter) - { - if (phase == tpOff) phase = tpSpinUp; - } - - // start - if ((Starter == true) || (qbar > 30.0)) - { - if (!Running && !Cutoff && (N2 > 15.0)) phase = tpStart; - } - - if (Cutoff && (phase != tpSpinUp)) phase = tpOff; - if (dt == 0) phase = tpTrim; - if (Starved) phase = tpOff; - if (Stalled) phase = tpStall; - if (Seized) phase = tpSeize; - - switch (phase) - { - case tpOff: - thrust = Off(); - break; - case tpRun: - thrust = Run(); - break; - case tpSpinUp: - thrust = SpinUp(); - break; - case tpStart: - thrust = Start(); - break; - case tpStall: - thrust = Stall(); - break; - case tpSeize: - thrust = Seize(); - break; - case tpTrim: - thrust = Trim(); - break; - default: - thrust = Off(); - } - - thrust = Thruster->Calculate(thrust); // allow thruster to modify thrust (i.e. reversing) - - return thrust; + if (!Running && Cutoff && Starter) { + if (phase == tpOff) phase = tpSpinUp; + } + + // start + if ((Starter == true) || (qbar > 30.0)) { + if (!Running && !Cutoff && (N2 > 15.0)) phase = tpStart; + } + + if (Cutoff && (phase != tpSpinUp)) phase = tpOff; + if (dt == 0) phase = tpTrim; + if (Starved) phase = tpOff; + if (Stalled) phase = tpStall; + if (Seized) phase = tpSeize; + + switch (phase) { + case tpOff: thrust = Off(); break; + case tpRun: thrust = Run(); break; + case tpSpinUp: thrust = SpinUp(); break; + case tpStart: thrust = Start(); break; + case tpStall: thrust = Stall(); break; + case tpSeize: thrust = Seize(); break; + case tpTrim: thrust = Trim(); break; + default: thrust = Off(); + } + + Thruster->Calculate(thrust); // allow thruster to modify thrust (i.e. reversing) + + RunPostFunctions(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTurbine::Off(void) { - double qbar = Auxiliary->Getqbar(); - Running = false; - FuelFlow_pph = Seek(&FuelFlow_pph, 0, 1000.0, 10000.0); - N1 = Seek(&N1, qbar/10.0, N1/2.0, N1/2.0); - N2 = Seek(&N2, qbar/15.0, N2/2.0, N2/2.0); - EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3); - OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2); - OilPressure_psi = N2 * 0.62; - NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); - EPR = Seek(&EPR, 1.0, 0.2, 0.2); - Augmentation = false; - ConsumeFuel(); - return 0.0; + double qbar = Auxiliary->Getqbar(); + Running = false; + FuelFlow_pph = Seek(&FuelFlow_pph, 0, 1000.0, 10000.0); + N1 = Seek(&N1, qbar/10.0, N1/2.0, N1/2.0); + N2 = Seek(&N2, qbar/15.0, N2/2.0, N2/2.0); + EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3); + OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2); + OilPressure_psi = N2 * 0.62; + NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); + EPR = Seek(&EPR, 1.0, 0.2, 0.2); + Augmentation = false; + ConsumeFuel(); + return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTurbine::Run() { - double idlethrust, milthrust, thrust; - double spoolup; // acceleration in pct/sec - double sigma = Atmosphere->GetDensityRatio(); - double T = Atmosphere->GetTemperature(); - - idlethrust = MilThrust * IdleThrustLookup->GetValue(); - milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue(); - - Running = true; - Starter = false; - - // adjust acceleration for N2 and atmospheric density - double n = N2norm + 0.1; - if (n > 1) n = 1; - spoolup = delay / (1 + 3 * (1-n)*(1-n)*(1-n) + (1 - sigma)); - - N2 = Seek(&N2, IdleN2 + ThrottlePos * N2_factor, spoolup, spoolup * 3.0); - N1 = Seek(&N1, IdleN1 + ThrottlePos * N1_factor, spoolup, spoolup * 2.4); - N2norm = (N2 - IdleN2) / N2_factor; - thrust = idlethrust + (milthrust * N2norm * N2norm); - EGT_degC = TAT + 363.1 + ThrottlePos * 357.1; - OilPressure_psi = N2 * 0.62; - OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0.1); - - if (!Augmentation) - { - correctedTSFC = TSFC * sqrt(T/389.7) * (0.84 + (1-N2norm)*(1-N2norm)); - FuelFlow_pph = Seek(&FuelFlow_pph, thrust * correctedTSFC, 1000.0, 10000.0); - if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF; - NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8); - thrust = thrust * (1.0 - BleedDemand); - EPR = 1.0 + thrust/MilThrust; - } - - if (AugMethod == 1) - { - if ((ThrottlePos > 0.99) && (N2 > 97.0)) - { - Augmentation = true; - } - else - { - Augmentation = false; - } - } - - if ((Augmented == 1) && Augmentation && (AugMethod < 2)) - { - thrust = MaxThrustLookup->GetValue() * MaxThrust; - FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0); - NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); - } - - if (AugMethod == 2) - { - if (AugmentCmd > 0.0) - { - Augmentation = true; - double tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - thrust; - thrust += (tdiff * AugmentCmd); - FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0); - NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); - } - else - { - Augmentation = false; - } + double idlethrust, milthrust, thrust; + double spoolup; // acceleration in pct/sec + double sigma = Atmosphere->GetDensityRatio(); + double T = Atmosphere->GetTemperature(); + + idlethrust = MilThrust * IdleThrustLookup->GetValue(); + milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue(); + + Running = true; + Starter = false; + + // adjust acceleration for N2 and atmospheric density + double n = N2norm + 0.1; + if (n > 1) n = 1; + spoolup = delay / (1 + 3 * (1-n)*(1-n)*(1-n) + (1 - sigma)); + + N2 = Seek(&N2, IdleN2 + ThrottlePos * N2_factor, spoolup, spoolup * 3.0); + N1 = Seek(&N1, IdleN1 + ThrottlePos * N1_factor, spoolup, spoolup * 2.4); + N2norm = (N2 - IdleN2) / N2_factor; + thrust = idlethrust + (milthrust * N2norm * N2norm); + EGT_degC = TAT + 363.1 + ThrottlePos * 357.1; + OilPressure_psi = N2 * 0.62; + OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0.1); + + if (!Augmentation) { + correctedTSFC = TSFC * sqrt(T/389.7) * (0.84 + (1-N2norm)*(1-N2norm)); + FuelFlow_pph = Seek(&FuelFlow_pph, thrust * correctedTSFC, 1000.0, 10000.0); + if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF; + NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8); + thrust = thrust * (1.0 - BleedDemand); + EPR = 1.0 + thrust/MilThrust; + } + + if (AugMethod == 1) { + if ((ThrottlePos > 0.99) && (N2 > 97.0)) {Augmentation = true;} + else {Augmentation = false;} + } + + if ((Augmented == 1) && Augmentation && (AugMethod < 2)) { + thrust = MaxThrustLookup->GetValue() * MaxThrust; + FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0); + NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); + } + + if (AugMethod == 2) { + if (AugmentCmd > 0.0) { + Augmentation = true; + double tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - thrust; + thrust += (tdiff * AugmentCmd); + FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0); + NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); + } else { + Augmentation = false; } - - if ((Injected == 1) && Injection) - { - InjectionTimer += dt; - if (InjectionTimer < InjectionTime) - { - thrust = thrust * InjectionLookup->GetValue(); - } - else - { - Injection = false; - } + } + + if ((Injected == 1) && Injection) { + InjectionTimer += dt; + if (InjectionTimer < InjectionTime) { + thrust = thrust * InjectionLookup->GetValue(); + } else { + Injection = false; } + } - ConsumeFuel(); - if (Cutoff) phase = tpOff; - if (Starved) phase = tpOff; + ConsumeFuel(); + if (Cutoff) phase = tpOff; + if (Starved) phase = tpOff; - return thrust; + return thrust; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTurbine::SpinUp(void) { - Running = false; - FuelFlow_pph = 0.0; - N2 = Seek(&N2, 25.18, N2_spinup, N2/2.0); - N1 = Seek(&N1, 5.21, N1_spinup, N1/2.0); - EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3); - OilPressure_psi = N2 * 0.62; - OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2); - EPR = 1.0; - NozzlePosition = 1.0; - if (Starter == false) phase = tpOff; - return 0.0; + Running = false; + FuelFlow_pph = 0.0; + N2 = Seek(&N2, 25.18, N2_spinup, N2/2.0); + N1 = Seek(&N1, 5.21, N1_spinup, N1/2.0); + EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3); + OilPressure_psi = N2 * 0.62; + OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2); + EPR = 1.0; + NozzlePosition = 1.0; + if (Starter == false) phase = tpOff; + return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTurbine::Start(void) { - double qbar = Auxiliary->Getqbar(); - if ((N2 > 15.0) && !Starved) // minimum 15% N2 needed for start - { - Cranking = true; // provided for sound effects signal - if (N2 < IdleN2) - { - N2 = Seek(&N2, IdleN2, 2.0, N2/2.0); - N1 = Seek(&N1, IdleN1, 1.4, N1/2.0); - EGT_degC = Seek(&EGT_degC, TAT + 363.1, 21.3, 7.3); - FuelFlow_pph = IdleFF * N2 / IdleN2; - OilPressure_psi = N2 * 0.62; - ConsumeFuel(); - if ((Starter == false) && (qbar < 30.0)) phase = tpOff; // aborted start - } - else - { - phase = tpRun; - Running = true; - Starter = false; - Cranking = false; - } + double qbar = Auxiliary->Getqbar(); + if ((N2 > 15.0) && !Starved) { // minimum 15% N2 needed for start + Cranking = true; // provided for sound effects signal + if (N2 < IdleN2) { + N2 = Seek(&N2, IdleN2, 2.0, N2/2.0); + N1 = Seek(&N1, IdleN1, 1.4, N1/2.0); + EGT_degC = Seek(&EGT_degC, TAT + 363.1, 21.3, 7.3); + FuelFlow_pph = IdleFF * N2 / IdleN2; + OilPressure_psi = N2 * 0.62; + ConsumeFuel(); + if ((Starter == false) && (qbar < 30.0)) phase = tpOff; // aborted start + } + else { + phase = tpRun; + Running = true; + Starter = false; + Cranking = false; + } } - else // no start if N2 < 15% - { - phase = tpOff; - Starter = false; + else { // no start if N2 < 15% + phase = tpOff; + Starter = false; } - return 0.0; + return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTurbine::Stall(void) { - double qbar = Auxiliary->Getqbar(); - EGT_degC = TAT + 903.14; - FuelFlow_pph = IdleFF; - N1 = Seek(&N1, qbar/10.0, 0, N1/10.0); - N2 = Seek(&N2, qbar/15.0, 0, N2/10.0); - ConsumeFuel(); - if (ThrottlePos < 0.01) - { - phase = tpRun; // clear the stall with throttle to idle - Stalled = false; + double qbar = Auxiliary->Getqbar(); + EGT_degC = TAT + 903.14; + FuelFlow_pph = IdleFF; + N1 = Seek(&N1, qbar/10.0, 0, N1/10.0); + N2 = Seek(&N2, qbar/15.0, 0, N2/10.0); + ConsumeFuel(); + if (ThrottlePos < 0.01) { + phase = tpRun; // clear the stall with throttle to idle + Stalled = false; } - return 0.0; + return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -408,37 +362,26 @@ double FGTurbine::Trim() N2 = IdleN2 + ThrottlePos * N2_factor; N2norm = (N2 - IdleN2) / N2_factor; thrust = (idlethrust + (milthrust * N2norm * N2norm)) - * (1.0 - BleedDemand); - - if (AugMethod == 1) - { - if ((ThrottlePos > 0.99) && (N2 > 97.0)) - { - Augmentation = true; - } - else - { - Augmentation = false; - } + * (1.0 - BleedDemand); + + if (AugMethod == 1) { + if ((ThrottlePos > 0.99) && (N2 > 97.0)) {Augmentation = true;} + else {Augmentation = false;} } - if ((Augmented == 1) && Augmentation && (AugMethod < 2)) - { - thrust = MaxThrust * MaxThrustLookup->GetValue(); + if ((Augmented == 1) && Augmentation && (AugMethod < 2)) { + thrust = MaxThrust * MaxThrustLookup->GetValue(); } - if (AugMethod == 2) - { - if (AugmentCmd > 0.0) - { - tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - thrust; - thrust += (tdiff * AugmentCmd); - } + if (AugMethod == 2) { + if (AugmentCmd > 0.0) { + tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - thrust; + thrust += (tdiff * AugmentCmd); + } } - if ((Injected == 1) && Injection) - { - thrust = thrust * InjectionLookup->GetValue(); + if ((Injected == 1) && Injection) { + thrust = thrust * InjectionLookup->GetValue(); } return thrust; @@ -448,180 +391,161 @@ double FGTurbine::Trim() double FGTurbine::CalcFuelNeed(void) { - double dT = FDMExec->GetDeltaT() * Propulsion->GetRate(); - FuelFlowRate = FuelFlow_pph / 3600.0; // Calculates flow in lbs/sec from lbs/hr - FuelExpended = FuelFlowRate * dT; // Calculates fuel expended in this time step - return FuelExpended; + double dT = FDMExec->GetDeltaT() * Propulsion->GetRate(); + FuelFlowRate = FuelFlow_pph / 3600.0; // Calculates flow in lbs/sec from lbs/hr + FuelExpended = FuelFlowRate * dT; // Calculates fuel expended in this time step + return FuelExpended; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -double FGTurbine::GetPowerAvailable(void) -{ - if ( ThrottlePos <= 0.77 ) - return 64.94*ThrottlePos; - else - return 217.38*ThrottlePos - 117.38; +double FGTurbine::GetPowerAvailable(void) { + if( ThrottlePos <= 0.77 ) + return 64.94*ThrottlePos; + else + return 217.38*ThrottlePos - 117.38; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -double FGTurbine::Seek(double *var, double target, double accel, double decel) -{ - double v = *var; - if (v > target) - { - v -= dt * decel; - if (v < target) v = target; - } - else if (v < target) - { - v += dt * accel; - if (v > target) v = target; - } - return v; +double FGTurbine::Seek(double *var, double target, double accel, double decel) { + double v = *var; + if (v > target) { + v -= dt * decel; + if (v < target) v = target; + } else if (v < target) { + v += dt * accel; + if (v > target) v = target; + } + return v; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGTurbine::Load(FGFDMExec* exec, Element *el) { - string property_name, property_prefix; - property_prefix = CreateIndexedPropertyName("propulsion/engine", EngineNumber); - - if (el->FindElement("milthrust")) - MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS"); - if (el->FindElement("maxthrust")) - MaxThrust = el->FindElementValueAsNumberConvertTo("maxthrust","LBS"); - if (el->FindElement("bypassratio")) - BypassRatio = el->FindElementValueAsNumber("bypassratio"); - if (el->FindElement("bleed")) - BleedDemand = el->FindElementValueAsNumber("bleed"); - if (el->FindElement("tsfc")) - TSFC = el->FindElementValueAsNumber("tsfc"); - if (el->FindElement("atsfc")) - ATSFC = el->FindElementValueAsNumber("atsfc"); - if (el->FindElement("idlen1")) - IdleN1 = el->FindElementValueAsNumber("idlen1"); - if (el->FindElement("idlen2")) - IdleN2 = el->FindElementValueAsNumber("idlen2"); - if (el->FindElement("maxn1")) - MaxN1 = el->FindElementValueAsNumber("maxn1"); - if (el->FindElement("maxn2")) - MaxN2 = el->FindElementValueAsNumber("maxn2"); - if (el->FindElement("n1spinup")) - N1_spinup = el->FindElementValueAsNumber("n1spinup"); - if (el->FindElement("n2spinup")) - N2_spinup = el->FindElementValueAsNumber("n2spinup"); - if (el->FindElement("augmented")) - Augmented = (int)el->FindElementValueAsNumber("augmented"); - if (el->FindElement("augmethod")) - AugMethod = (int)el->FindElementValueAsNumber("augmethod"); - if (el->FindElement("injected")) - Injected = (int)el->FindElementValueAsNumber("injected"); - if (el->FindElement("injection-time")) - InjectionTime = el->FindElementValueAsNumber("injection-time"); - - Element *function_element; - string name; - FGPropertyManager* PropertyManager = exec->GetPropertyManager(); - - while (true) - { - function_element = el->FindNextElement("function"); - if (!function_element) break; - name = function_element->GetAttributeValue("name"); - if (name == "IdleThrust") - { - IdleThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); - } - else if (name == "MilThrust") - { - MilThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); - } - else if (name == "AugThrust") - { - MaxThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); - } - else if (name == "Injection") - { - InjectionLookup = new FGFunction(PropertyManager, function_element, property_prefix); - } - else - { - cerr << "Unknown function type: " << name << " in turbine definition." << - endl; - } + string property_name, property_prefix; + property_prefix = CreateIndexedPropertyName("propulsion/engine", EngineNumber); + + if (el->FindElement("milthrust")) + MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS"); + if (el->FindElement("maxthrust")) + MaxThrust = el->FindElementValueAsNumberConvertTo("maxthrust","LBS"); + if (el->FindElement("bypassratio")) + BypassRatio = el->FindElementValueAsNumber("bypassratio"); + if (el->FindElement("bleed")) + BleedDemand = el->FindElementValueAsNumber("bleed"); + if (el->FindElement("tsfc")) + TSFC = el->FindElementValueAsNumber("tsfc"); + if (el->FindElement("atsfc")) + ATSFC = el->FindElementValueAsNumber("atsfc"); + if (el->FindElement("idlen1")) + IdleN1 = el->FindElementValueAsNumber("idlen1"); + if (el->FindElement("idlen2")) + IdleN2 = el->FindElementValueAsNumber("idlen2"); + if (el->FindElement("maxn1")) + MaxN1 = el->FindElementValueAsNumber("maxn1"); + if (el->FindElement("maxn2")) + MaxN2 = el->FindElementValueAsNumber("maxn2"); + if (el->FindElement("n1spinup")) + N1_spinup = el->FindElementValueAsNumber("n1spinup"); + if (el->FindElement("n2spinup")) + N2_spinup = el->FindElementValueAsNumber("n2spinup"); + if (el->FindElement("augmented")) + Augmented = (int)el->FindElementValueAsNumber("augmented"); + if (el->FindElement("augmethod")) + AugMethod = (int)el->FindElementValueAsNumber("augmethod"); + if (el->FindElement("injected")) + Injected = (int)el->FindElementValueAsNumber("injected"); + if (el->FindElement("injection-time")) + InjectionTime = el->FindElementValueAsNumber("injection-time"); + + Element *function_element; + string name; + FGPropertyManager* PropertyManager = exec->GetPropertyManager(); + + while (true) { + function_element = el->FindNextElement("function"); + if (!function_element) break; + name = function_element->GetAttributeValue("name"); + if (name == "IdleThrust") { + IdleThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); + } else if (name == "MilThrust") { + MilThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); + } else if (name == "AugThrust") { + MaxThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); + } else if (name == "Injection") { + InjectionLookup = new FGFunction(PropertyManager, function_element, property_prefix); } + } - // Pre-calculations and initializations + // Pre-calculations and initializations - delay = 90.0 / (BypassRatio + 3.0); - N1_factor = MaxN1 - IdleN1; - N2_factor = MaxN2 - IdleN2; - OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0; - IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate + delay = 90.0 / (BypassRatio + 3.0); + N1_factor = MaxN1 - IdleN1; + N2_factor = MaxN2 - IdleN2; + OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0; + IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate - bindmodel(); - return true; + bindmodel(); + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGTurbine::GetEngineLabels(const string& delimiter) { - std::ostringstream buf; + std::ostringstream buf; - buf << Name << "_N1[" << EngineNumber << "]" << delimiter - << Name << "_N2[" << EngineNumber << "]" << delimiter - << Thruster->GetThrusterLabels(EngineNumber, delimiter); + buf << Name << "_N1[" << EngineNumber << "]" << delimiter + << Name << "_N2[" << EngineNumber << "]" << delimiter + << Thruster->GetThrusterLabels(EngineNumber, delimiter); - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGTurbine::GetEngineValues(const string& delimiter) { - std::ostringstream buf; + std::ostringstream buf; - buf << N1 << delimiter - << N2 << delimiter - << Thruster->GetThrusterValues(EngineNumber, delimiter); + buf << N1 << delimiter + << N2 << delimiter + << Thruster->GetThrusterValues(EngineNumber, delimiter); - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGTurbine::bindmodel() { - string property_name, base_property_name; - base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); - property_name = base_property_name + "/n1"; - PropertyManager->Tie( property_name.c_str(), &N1); - property_name = base_property_name + "/n2"; - PropertyManager->Tie( property_name.c_str(), &N2); - property_name = base_property_name + "/injection_cmd"; - PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this, - &FGTurbine::GetInjection, &FGTurbine::SetInjection); - property_name = base_property_name + "/seized"; - PropertyManager->Tie( property_name.c_str(), &Seized); - property_name = base_property_name + "/stalled"; - PropertyManager->Tie( property_name.c_str(), &Stalled); + string property_name, base_property_name; + base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); + property_name = base_property_name + "/n1"; + PropertyManager->Tie( property_name.c_str(), &N1); + property_name = base_property_name + "/n2"; + PropertyManager->Tie( property_name.c_str(), &N2); + property_name = base_property_name + "/injection_cmd"; + PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this, + &FGTurbine::GetInjection, &FGTurbine::SetInjection); + property_name = base_property_name + "/seized"; + PropertyManager->Tie( property_name.c_str(), &Seized); + property_name = base_property_name + "/stalled"; + PropertyManager->Tie( property_name.c_str(), &Stalled); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -int FGTurbine::InitRunning(void) -{ - FDMExec->SuspendIntegration(); - Cutoff=false; - Running=true; - N2=IdleN2; - Calculate(); - FDMExec->ResumeIntegration(); - return phase==tpRun; +int FGTurbine::InitRunning(void) { + FDMExec->SuspendIntegration(); + Cutoff=false; + Running=true; + N2=IdleN2; + Calculate(); + FDMExec->ResumeIntegration(); + return phase==tpRun; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -645,55 +569,46 @@ int FGTurbine::InitRunning(void) void FGTurbine::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - - } - if (from == 2) // called from Load() - { - cout << "\n Engine Name: " << Name << endl; - cout << " MilThrust: " << MilThrust << endl; - cout << " MaxThrust: " << MaxThrust << endl; - cout << " BypassRatio: " << BypassRatio << endl; - cout << " TSFC: " << TSFC << endl; - cout << " ATSFC: " << ATSFC << endl; - cout << " IdleN1: " << IdleN1 << endl; - cout << " IdleN2: " << IdleN2 << endl; - cout << " MaxN1: " << MaxN1 << endl; - cout << " MaxN2: " << MaxN2 << endl; - cout << " Augmented: " << Augmented << endl; - cout << " AugMethod: " << AugMethod << endl; - cout << " Injected: " << Injected << endl; - cout << " MinThrottle: " << MinThrottle << endl; - - cout << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGTurbine" << endl; - if (from == 1) cout << "Destroyed: FGTurbine" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + } - if (debug_lvl & 16) // Sanity checking - { + if (from == 2) { // called from Load() + cout << "\n Engine Name: " << Name << endl; + cout << " MilThrust: " << MilThrust << endl; + cout << " MaxThrust: " << MaxThrust << endl; + cout << " BypassRatio: " << BypassRatio << endl; + cout << " TSFC: " << TSFC << endl; + cout << " ATSFC: " << ATSFC << endl; + cout << " IdleN1: " << IdleN1 << endl; + cout << " IdleN2: " << IdleN2 << endl; + cout << " MaxN1: " << MaxN1 << endl; + cout << " MaxN2: " << MaxN2 << endl; + cout << " Augmented: " << Augmented << endl; + cout << " AugMethod: " << AugMethod << endl; + cout << " Injected: " << Injected << endl; + cout << " MinThrottle: " << MinThrottle << endl; + + cout << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGTurbine" << endl; + if (from == 1) cout << "Destroyed: FGTurbine" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/propulsion/FGTurbine.h b/src/models/propulsion/FGTurbine.h index d3bde86dc66a719b3c763538a2cd80cfc9f0944f..62c6d321a34680294bd16b3d27b56ec8edf4a5e0 100644 --- a/src/models/propulsion/FGTurbine.h +++ b/src/models/propulsion/FGTurbine.h @@ -42,14 +42,13 @@ INCLUDES #include "FGEngine.h" -#define ID_TURBINE "$Id: FGTurbine.h,v 1.18 2009/10/24 22:59:30 jberndt Exp $" +#define ID_TURBINE "$Id: FGTurbine.h,v 1.19 2010/08/21 18:08:46 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { class Element; class FGFunction; @@ -114,7 +113,7 @@ CLASS DOCUMENTATION atsfc - Afterburning TSFC, lbm/hr/lbf idlen1 - Fan rotor rpm (% of max) at idle idlen2 - Core rotor rpm (% of max) at idle - maxn1 - Fan rotor rpm (% of max) at full throttle + maxn1 - Fan rotor rpm (% of max) at full throttle maxn2 - Core rotor rpm (% of max) at full throttle augmented 0 = afterburner not installed @@ -126,10 +125,10 @@ CLASS DOCUMENTATION injected 0 = Water injection not installed 1 = Water injection installed - injection-time - Time, in seconds, of water injection duration + injection-time - Time, in seconds, of water injection duration </pre> -<h3>NOTES:</h3> +<h3>NOTES:</h3> <pre> Bypass ratio is used only to estimate engine acceleration time. The effect of bypass ratio on engine efficiency is already included in @@ -147,7 +146,7 @@ CLASS DOCUMENTATION /engine/direct.xml </pre> @author David P. Culp - @version "$Id: FGTurbine.h,v 1.18 2009/10/24 22:59:30 jberndt Exp $" + @version "$Id: FGTurbine.h,v 1.19 2010/08/21 18:08:46 jberndt Exp $" */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -157,202 +156,128 @@ CLASS DECLARATION class FGTurbine : public FGEngine { public: - /** Constructor - @param Executive pointer to executive structure - @param el pointer to the XML element representing the turbine engine - @param engine_number engine number */ - FGTurbine(FGFDMExec* Executive, Element *el, int engine_number); - /// Destructor - ~FGTurbine(); - - enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim }; - - double Calculate(void); - double CalcFuelNeed(void); - double GetPowerAvailable(void); - /** A lag filter. - Used to control the rate at which values are allowed to change. - @param var a pointer to a variable of type double - @param target the desired (target) value - @param accel the rate, per second, the value may increase - @param decel the rate, per second, the value may decrease */ - double Seek(double* var, double target, double accel, double decel); - - phaseType GetPhase(void) - { - return phase; - } - - bool GetOvertemp(void) const - { - return Overtemp; - } - bool GetInjection(void) const - { - return Injection; - } - bool GetFire(void) const - { - return Fire; - } - bool GetAugmentation(void) const - { - return Augmentation; - } - bool GetReversed(void) const - { - return Reversed; - } - bool GetCutoff(void) const - { - return Cutoff; - } - int GetIgnition(void) const - { - return Ignition; - } - - double GetInlet(void) const - { - return InletPosition; - } - double GetNozzle(void) const - { - return NozzlePosition; - } - double GetBleedDemand(void) const - { - return BleedDemand; - } - double GetN1(void) const - { - return N1; - } - double GetN2(void) const - { - return N2; - } - double GetEPR(void) const - { - return EPR; - } - double GetEGT(void) const - { - return EGT_degC; - } - - double getOilPressure_psi () const - { - return OilPressure_psi; - } - double getOilTemp_degF (void) - { - return KelvinToFahrenheit(OilTemp_degK); - } - void SetInjection(bool injection) - { - Injection = injection; - } - void SetIgnition(int ignition) - { - Ignition = ignition; - } - void SetAugmentation(bool augmentation) - { - Augmentation = augmentation; - } - void SetPhase( phaseType p ) - { - phase = p; - } - void SetEPR(double epr) - { - EPR = epr; - } - void SetBleedDemand(double bleedDemand) - { - BleedDemand = bleedDemand; - } - void SetReverse(bool reversed) - { - Reversed = reversed; - } - void SetCutoff(bool cutoff) - { - Cutoff = cutoff; - } - int InitRunning(void); - void ResetToIC(void); - - std::string GetEngineLabels(const std::string& delimiter); - std::string GetEngineValues(const std::string& delimiter); + /** Constructor + @param Executive pointer to executive structure + @param el pointer to the XML element representing the turbine engine + @param engine_number engine number */ + FGTurbine(FGFDMExec* Executive, Element *el, int engine_number); + /// Destructor + ~FGTurbine(); + + enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim }; + + void Calculate(void); + double CalcFuelNeed(void); + double GetPowerAvailable(void); + /** A lag filter. + Used to control the rate at which values are allowed to change. + @param var a pointer to a variable of type double + @param target the desired (target) value + @param accel the rate, per second, the value may increase + @param decel the rate, per second, the value may decrease */ + double Seek(double* var, double target, double accel, double decel); + + phaseType GetPhase(void) { return phase; } + + bool GetOvertemp(void) const {return Overtemp; } + bool GetInjection(void) const {return Injection;} + bool GetFire(void) const { return Fire; } + bool GetAugmentation(void) const {return Augmentation;} + bool GetReversed(void) const { return Reversed; } + bool GetCutoff(void) const { return Cutoff; } + int GetIgnition(void) const {return Ignition;} + + double GetInlet(void) const { return InletPosition; } + double GetNozzle(void) const { return NozzlePosition; } + double GetBleedDemand(void) const {return BleedDemand;} + double GetN1(void) const {return N1;} + double GetN2(void) const {return N2;} + double GetEPR(void) const {return EPR;} + double GetEGT(void) const {return EGT_degC;} + + double getOilPressure_psi () const {return OilPressure_psi;} + double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);} + + void SetInjection(bool injection) {Injection = injection;} + void SetIgnition(int ignition) {Ignition = ignition;} + void SetAugmentation(bool augmentation) {Augmentation = augmentation;} + void SetPhase( phaseType p ) { phase = p; } + void SetEPR(double epr) {EPR = epr;} + void SetBleedDemand(double bleedDemand) {BleedDemand = bleedDemand;} + void SetReverse(bool reversed) { Reversed = reversed; } + void SetCutoff(bool cutoff) { Cutoff = cutoff; } + int InitRunning(void); + void ResetToIC(void); + + std::string GetEngineLabels(const std::string& delimiter); + std::string GetEngineValues(const std::string& delimiter); private: - phaseType phase; ///< Operating mode, or "phase" - double MilThrust; ///< Maximum Unaugmented Thrust, static @ S.L. (lbf) - double MaxThrust; ///< Maximum Augmented Thrust, static @ S.L. (lbf) - double BypassRatio; ///< Bypass Ratio - double TSFC; ///< Thrust Specific Fuel Consumption (lbm/hr/lbf) - double ATSFC; ///< Augmented TSFC (lbm/hr/lbf) - double IdleN1; ///< Idle N1 - double IdleN2; ///< Idle N2 - double N1; ///< N1 - double N2; ///< N2 - double N2norm; ///< N2 normalized (0=idle, 1=max) - double MaxN1; ///< N1 at 100% throttle - double MaxN2; ///< N2 at 100% throttle - double IdleFF; ///< Idle Fuel Flow (lbm/hr) - double delay; ///< Inverse spool-up time from idle to 100% (seconds) - double dt; ///< Simulator time slice - double N1_factor; ///< factor to tie N1 and throttle - double N2_factor; ///< factor to tie N2 and throttle - double ThrottlePos; ///< FCS-supplied throttle position - double AugmentCmd; ///< modulated afterburner command (0.0 to 1.0) - double TAT; ///< total air temperature (deg C) - double N1_spinup; ///< N1 spin up rate from starter (per second) - double N2_spinup; ///< N2 spin up rate from starter (per second) - bool Stalled; ///< true if engine is compressor-stalled - bool Seized; ///< true if inner spool is seized - bool Overtemp; ///< true if EGT exceeds limits - bool Fire; ///< true if engine fire detected - bool Injection; - bool Augmentation; - bool Reversed; - bool Cutoff; - int Injected; ///< = 1 if water injection installed - int Ignition; - int Augmented; ///< = 1 if augmentation installed - int AugMethod; ///< = 0 if using property /engine[n]/augmentation - ///< = 1 if using last 1% of throttle movement - ///< = 2 if using FCS-defined throttle - double EGT_degC; - double EPR; - double OilPressure_psi; - double OilTemp_degK; - double BleedDemand; - double InletPosition; - double NozzlePosition; - double correctedTSFC; - double InjectionTimer; - double InjectionTime; - - double Off(void); - double Run(); - double SpinUp(void); - double Start(void); - double Stall(void); - double Seize(void); - double Trim(); - - FGFunction *IdleThrustLookup; - FGFunction *MilThrustLookup; - FGFunction *MaxThrustLookup; - FGFunction *InjectionLookup; - - bool Load(FGFDMExec *exec, Element *el); - void bindmodel(void); - void Debug(int from); + phaseType phase; ///< Operating mode, or "phase" + double MilThrust; ///< Maximum Unaugmented Thrust, static @ S.L. (lbf) + double MaxThrust; ///< Maximum Augmented Thrust, static @ S.L. (lbf) + double BypassRatio; ///< Bypass Ratio + double TSFC; ///< Thrust Specific Fuel Consumption (lbm/hr/lbf) + double ATSFC; ///< Augmented TSFC (lbm/hr/lbf) + double IdleN1; ///< Idle N1 + double IdleN2; ///< Idle N2 + double N1; ///< N1 + double N2; ///< N2 + double N2norm; ///< N2 normalized (0=idle, 1=max) + double MaxN1; ///< N1 at 100% throttle + double MaxN2; ///< N2 at 100% throttle + double IdleFF; ///< Idle Fuel Flow (lbm/hr) + double delay; ///< Inverse spool-up time from idle to 100% (seconds) + double dt; ///< Simulator time slice + double N1_factor; ///< factor to tie N1 and throttle + double N2_factor; ///< factor to tie N2 and throttle + double ThrottlePos; ///< FCS-supplied throttle position + double AugmentCmd; ///< modulated afterburner command (0.0 to 1.0) + double TAT; ///< total air temperature (deg C) + double N1_spinup; ///< N1 spin up rate from starter (per second) + double N2_spinup; ///< N2 spin up rate from starter (per second) + bool Stalled; ///< true if engine is compressor-stalled + bool Seized; ///< true if inner spool is seized + bool Overtemp; ///< true if EGT exceeds limits + bool Fire; ///< true if engine fire detected + bool Injection; + bool Augmentation; + bool Reversed; + bool Cutoff; + int Injected; ///< = 1 if water injection installed + int Ignition; + int Augmented; ///< = 1 if augmentation installed + int AugMethod; ///< = 0 if using property /engine[n]/augmentation + ///< = 1 if using last 1% of throttle movement + ///< = 2 if using FCS-defined throttle + double EGT_degC; + double EPR; + double OilPressure_psi; + double OilTemp_degK; + double BleedDemand; + double InletPosition; + double NozzlePosition; + double correctedTSFC; + double InjectionTimer; + double InjectionTime; + + double Off(void); + double Run(); + double SpinUp(void); + double Start(void); + double Stall(void); + double Seize(void); + double Trim(); + + FGFunction *IdleThrustLookup; + FGFunction *MilThrustLookup; + FGFunction *MaxThrustLookup; + FGFunction *InjectionLookup; + + bool Load(FGFDMExec *exec, Element *el); + void bindmodel(void); + void Debug(int from); }; } diff --git a/src/models/propulsion/FGTurboProp.cpp b/src/models/propulsion/FGTurboProp.cpp old mode 100644 new mode 100755 index 2a5b9ee57e0d08db4df24eae56cf627a4df2c0e9..9813199618d5fb29edb499ab14b597dee065a0ba --- a/src/models/propulsion/FGTurboProp.cpp +++ b/src/models/propulsion/FGTurboProp.cpp @@ -50,10 +50,9 @@ INCLUDES using namespace std; -namespace JSBSim -{ +namespace JSBSim { -static const char *IdSrc = "$Id: FGTurboProp.cpp,v 1.16 2010/02/25 05:21:36 jberndt Exp $"; +static const char *IdSrc = "$Id: FGTurboProp.cpp,v 1.17 2010/08/21 17:13:48 jberndt Exp $"; static const char *IdHdr = ID_TURBOPROP; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -61,398 +60,347 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number) - : FGEngine(exec, el, engine_number), - ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL) + : FGEngine(exec, el, engine_number), + ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL) { - SetDefaults(); + SetDefaults(); - Load(exec, el); - Debug(0); + Load(exec, el); + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGTurboProp::~FGTurboProp() { - delete ITT_N1; - delete EnginePowerRPM_N1; - delete EnginePowerVC; - Debug(1); + delete ITT_N1; + delete EnginePowerRPM_N1; + delete EnginePowerVC; + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGTurboProp::Load(FGFDMExec* exec, Element *el) { - IdleFF=-1; - MaxStartingTime = 999999; //very big timeout -> infinite - Ielu_max_torque=-1; + IdleFF=-1; + MaxStartingTime = 999999; //very big timeout -> infinite + Ielu_max_torque=-1; // ToDo: Need to make sure units are properly accounted for below. - if (el->FindElement("milthrust")) - MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS"); - if (el->FindElement("idlen1")) - IdleN1 = el->FindElementValueAsNumber("idlen1"); - if (el->FindElement("idlen2")) - IdleN2 = el->FindElementValueAsNumber("idlen2"); - if (el->FindElement("maxn1")) - MaxN1 = el->FindElementValueAsNumber("maxn1"); - if (el->FindElement("maxn2")) - MaxN2 = el->FindElementValueAsNumber("maxn2"); - if (el->FindElement("betarangeend")) - BetaRangeThrottleEnd = el->FindElementValueAsNumber("betarangeend")/100.0; - if (el->FindElement("reversemaxpower")) - ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0; - - if (el->FindElement("maxpower")) - MaxPower = el->FindElementValueAsNumber("maxpower"); - if (el->FindElement("idlefuelflow")) - IdleFF = el->FindElementValueAsNumber("idlefuelflow"); - if (el->FindElement("psfc")) - PSFC = el->FindElementValueAsNumber("psfc"); - if (el->FindElement("n1idle_max_delay")) - Idle_Max_Delay = el->FindElementValueAsNumber("n1idle_max_delay"); - if (el->FindElement("maxstartingtime")) - MaxStartingTime = el->FindElementValueAsNumber("maxstartingtime"); - if (el->FindElement("startern1")) - StarterN1 = el->FindElementValueAsNumber("startern1"); - if (el->FindElement("ielumaxtorque")) - Ielu_max_torque = el->FindElementValueAsNumber("ielumaxtorque"); - if (el->FindElement("itt_delay")) - ITT_Delay = el->FindElementValueAsNumber("itt_delay"); - - Element *table_element; - string name; - FGPropertyManager* PropertyManager = exec->GetPropertyManager(); - - while (true) - { - table_element = el->FindNextElement("table"); - if (!table_element) break; - name = table_element->GetAttributeValue("name"); - if (name == "EnginePowerVC") - { - EnginePowerVC = new FGTable(PropertyManager, table_element); - } - else if (name == "EnginePowerRPM_N1") - { - EnginePowerRPM_N1 = new FGTable(PropertyManager, table_element); - } - else if (name == "ITT_N1") - { - ITT_N1 = new FGTable(PropertyManager, table_element); - } - else - { - cerr << "Unknown table type: " << name << " in turbine definition." << - endl; - } + if (el->FindElement("milthrust")) + MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS"); + if (el->FindElement("idlen1")) + IdleN1 = el->FindElementValueAsNumber("idlen1"); + if (el->FindElement("idlen2")) + IdleN2 = el->FindElementValueAsNumber("idlen2"); + if (el->FindElement("maxn1")) + MaxN1 = el->FindElementValueAsNumber("maxn1"); + if (el->FindElement("maxn2")) + MaxN2 = el->FindElementValueAsNumber("maxn2"); + if (el->FindElement("betarangeend")) + BetaRangeThrottleEnd = el->FindElementValueAsNumber("betarangeend")/100.0; + if (el->FindElement("reversemaxpower")) + ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0; + + if (el->FindElement("maxpower")) + MaxPower = el->FindElementValueAsNumber("maxpower"); + if (el->FindElement("idlefuelflow")) + IdleFF = el->FindElementValueAsNumber("idlefuelflow"); + if (el->FindElement("psfc")) + PSFC = el->FindElementValueAsNumber("psfc"); + if (el->FindElement("n1idle_max_delay")) + Idle_Max_Delay = el->FindElementValueAsNumber("n1idle_max_delay"); + if (el->FindElement("maxstartingtime")) + MaxStartingTime = el->FindElementValueAsNumber("maxstartingtime"); + if (el->FindElement("startern1")) + StarterN1 = el->FindElementValueAsNumber("startern1"); + if (el->FindElement("ielumaxtorque")) + Ielu_max_torque = el->FindElementValueAsNumber("ielumaxtorque"); + if (el->FindElement("itt_delay")) + ITT_Delay = el->FindElementValueAsNumber("itt_delay"); + + Element *table_element; + string name; + FGPropertyManager* PropertyManager = exec->GetPropertyManager(); + + while (true) { + table_element = el->FindNextElement("table"); + if (!table_element) break; + name = table_element->GetAttributeValue("name"); + if (name == "EnginePowerVC") { + EnginePowerVC = new FGTable(PropertyManager, table_element); + } else if (name == "EnginePowerRPM_N1") { + EnginePowerRPM_N1 = new FGTable(PropertyManager, table_element); + } else if (name == "ITT_N1") { + ITT_N1 = new FGTable(PropertyManager, table_element); + } else { + cerr << "Unknown table type: " << name << " in turbine definition." << + endl; } + } - // Pre-calculations and initializations + // Pre-calculations and initializations - delay=1; - N1_factor = MaxN1 - IdleN1; - N2_factor = MaxN2 - IdleN2; - OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0; - if (IdleFF==-1) IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate + delay=1; + N1_factor = MaxN1 - IdleN1; + N2_factor = MaxN2 - IdleN2; + OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0; + if (IdleFF==-1) IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate - cout << "ENG POWER:" << EnginePowerRPM_N1->GetValue(1200,90) << "\n"; + cout << "ENG POWER:" << EnginePowerRPM_N1->GetValue(1200,90) << "\n"; - return true; + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // The main purpose of Calculate() is to determine what phase the engine should // be in, then call the corresponding function. -double FGTurboProp::Calculate(void) +void FGTurboProp::Calculate(void) { - TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556; - dt = FDMExec->GetDeltaT() * Propulsion->GetRate(); - - ThrottleCmd = FCS->GetThrottleCmd(EngineNumber); - - Prop_RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); - if (Thruster->GetType() == FGThruster::ttPropeller) - { - ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber)); - ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber)); - ((FGPropeller*)Thruster)->SetReverse(Reversed); - if (Reversed) - { - ((FGPropeller*)Thruster)->SetReverseCoef(ThrottleCmd); - } - else - { - ((FGPropeller*)Thruster)->SetReverseCoef(0.0); - } + RunPreFunctions(); + + TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556; + dt = FDMExec->GetDeltaT() * Propulsion->GetRate(); + + ThrottleCmd = FCS->GetThrottleCmd(EngineNumber); + + Prop_RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); + if (Thruster->GetType() == FGThruster::ttPropeller) { + ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber)); + ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber)); + ((FGPropeller*)Thruster)->SetReverse(Reversed); + if (Reversed) { + ((FGPropeller*)Thruster)->SetReverseCoef(ThrottleCmd); + } else { + ((FGPropeller*)Thruster)->SetReverseCoef(0.0); } - - if (Reversed) - { - if (ThrottleCmd < BetaRangeThrottleEnd) - { - ThrottleCmd = 0.0; // idle when in Beta-range - } - else - { - // when reversed: - ThrottleCmd = (ThrottleCmd-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower; - } + } + + if (Reversed) { + if (ThrottleCmd < BetaRangeThrottleEnd) { + ThrottleCmd = 0.0; // idle when in Beta-range + } else { + // when reversed: + ThrottleCmd = (ThrottleCmd-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower; } - - // When trimming is finished check if user wants engine OFF or RUNNING - if ((phase == tpTrim) && (dt > 0)) - { - if (Running && !Starved) - { - phase = tpRun; - N2 = IdleN2; - N1 = IdleN1; - OilTemp_degK = 366.0; - Cutoff = false; - } - else - { - phase = tpOff; - Cutoff = true; - Eng_ITT_degC = TAT; - Eng_Temperature = TAT; - OilTemp_degK = TAT+273.15; - } + } + + // When trimming is finished check if user wants engine OFF or RUNNING + if ((phase == tpTrim) && (dt > 0)) { + if (Running && !Starved) { + phase = tpRun; + N2 = IdleN2; + N1 = IdleN1; + OilTemp_degK = 366.0; + Cutoff = false; + } else { + phase = tpOff; + Cutoff = true; + Eng_ITT_degC = TAT; + Eng_Temperature = TAT; + OilTemp_degK = TAT+273.15; } + } - if (!Running && Starter) - { - if (phase == tpOff) - { - phase = tpSpinUp; - if (StartTime < 0) StartTime=0; - } - } - if (!Running && !Cutoff && (N1 > 15.0)) - { - phase = tpStart; - StartTime = -1; + if (!Running && Starter) { + if (phase == tpOff) { + phase = tpSpinUp; + if (StartTime < 0) StartTime=0; } - if (Cutoff && (phase != tpSpinUp)) phase = tpOff; - if (dt == 0) phase = tpTrim; - if (Starved) phase = tpOff; - if (Condition >= 10) - { - phase = tpOff; - StartTime=-1; + } + if (!Running && !Cutoff && (N1 > 15.0)) { + phase = tpStart; + StartTime = -1; + } + if (Cutoff && (phase != tpSpinUp)) phase = tpOff; + if (dt == 0) phase = tpTrim; + if (Starved) phase = tpOff; + if (Condition >= 10) { + phase = tpOff; + StartTime=-1; + } + + if (Condition < 1) { + if (Ielu_max_torque > 0 + && -Ielu_max_torque > ((FGPropeller*)(Thruster))->GetTorque() + && ThrottleCmd >= OldThrottle ) { + ThrottleCmd = OldThrottle - 0.1 * dt; //IELU down + Ielu_intervent = true; + } else if (Ielu_max_torque > 0 && Ielu_intervent && ThrottleCmd >= OldThrottle) { + ThrottleCmd = OldThrottle; + ThrottleCmd = OldThrottle + 0.05 * dt; //IELU up + Ielu_intervent = true; + } else { + Ielu_intervent = false; } + } else { + Ielu_intervent = false; + } + OldThrottle = ThrottleCmd; - if (Condition < 1) - { - if (Ielu_max_torque > 0 - && -Ielu_max_torque > ((FGPropeller*)(Thruster))->GetTorque() - && ThrottleCmd >= OldThrottle ) - { - ThrottleCmd = OldThrottle - 0.1 * dt; //IELU down - Ielu_intervent = true; - } - else if (Ielu_max_torque > 0 && Ielu_intervent && ThrottleCmd >= OldThrottle) - { - ThrottleCmd = OldThrottle; - ThrottleCmd = OldThrottle + 0.05 * dt; //IELU up - Ielu_intervent = true; - } - else - { - Ielu_intervent = false; - } - } - else - { - Ielu_intervent = false; - } - OldThrottle = ThrottleCmd; - - switch (phase) - { - case tpOff: - Eng_HP = Off(); - break; - case tpRun: - Eng_HP = Run(); - break; - case tpSpinUp: - Eng_HP = SpinUp(); - break; - case tpStart: - Eng_HP = Start(); - break; - default: - Eng_HP = 0; - } + switch (phase) { + case tpOff: Eng_HP = Off(); break; + case tpRun: Eng_HP = Run(); break; + case tpSpinUp: Eng_HP = SpinUp(); break; + case tpStart: Eng_HP = Start(); break; + default: Eng_HP = 0; + } - //printf ("EngHP: %lf / Requi: %lf\n",Eng_HP,Prop_Required_Power); - PowerAvailable = (Eng_HP * hptoftlbssec) - Thruster->GetPowerRequired(); + //printf ("EngHP: %lf / Requi: %lf\n",Eng_HP,Prop_Required_Power); + PowerAvailable = (Eng_HP * hptoftlbssec) - Thruster->GetPowerRequired(); - return Thruster->Calculate(PowerAvailable); + Thruster->Calculate(PowerAvailable); + RunPostFunctions(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTurboProp::Off(void) { - double qbar = Auxiliary->Getqbar(); - Running = false; - EngStarting = false; + double qbar = Auxiliary->Getqbar(); + Running = false; EngStarting = false; - FuelFlow_pph = Seek(&FuelFlow_pph, 0, 800.0, 800.0); + FuelFlow_pph = Seek(&FuelFlow_pph, 0, 800.0, 800.0); - //allow the air turn with generator - N1 = ExpSeek(&N1, qbar/15.0, Idle_Max_Delay*2.5, Idle_Max_Delay * 5); + //allow the air turn with generator + N1 = ExpSeek(&N1, qbar/15.0, Idle_Max_Delay*2.5, Idle_Max_Delay * 5); - OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + TAT, 400 , 400); + OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + TAT, 400 , 400); - Eng_Temperature = ExpSeek(&Eng_Temperature,TAT,300,400); - double ITT_goal = ITT_N1->GetValue(N1,0.1) + ((N1>20) ? 0.0 : (20-N1)/20.0 * Eng_Temperature); - Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); + Eng_Temperature = ExpSeek(&Eng_Temperature,TAT,300,400); + double ITT_goal = ITT_N1->GetValue(N1,0.1) + ((N1>20) ? 0.0 : (20-N1)/20.0 * Eng_Temperature); + Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); - OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi + OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi - ConsumeFuel(); // for possible setting Starved = false when fuel tank - // is refilled (fuel crossfeed etc.) + ConsumeFuel(); // for possible setting Starved = false when fuel tank + // is refilled (fuel crossfeed etc.) - if (Prop_RPM>5) return -0.012; // friction in engine when propeller spining (estimate) - return 0.0; + if (Prop_RPM>5) return -0.012; // friction in engine when propeller spining (estimate) + return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTurboProp::Run(void) { - double thrust = 0.0, EngPower_HP, eff_coef; - Running = true; - Starter = false; - EngStarting = false; + double thrust = 0.0, EngPower_HP, eff_coef; + Running = true; Starter = false; EngStarting = false; //--- - double old_N1 = N1; - N1 = ExpSeek(&N1, IdleN1 + ThrottleCmd * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4); + double old_N1 = N1; + N1 = ExpSeek(&N1, IdleN1 + ThrottleCmd * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4); - EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1); - EngPower_HP *= EnginePowerVC->GetValue(); - if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; + EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1); + EngPower_HP *= EnginePowerVC->GetValue(); + if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; - eff_coef = 9.333 - (N1)/12; // 430%Fuel at 60%N1 - FuelFlow_pph = PSFC * EngPower_HP * eff_coef; + eff_coef = 9.333 - (N1)/12; // 430%Fuel at 60%N1 + FuelFlow_pph = PSFC * EngPower_HP * eff_coef; - Eng_Temperature = ExpSeek(&Eng_Temperature,Eng_ITT_degC,300,400); - double ITT_goal = ITT_N1->GetValue((N1-old_N1)*300+N1,1); - Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); + Eng_Temperature = ExpSeek(&Eng_Temperature,Eng_ITT_degC,300,400); + double ITT_goal = ITT_N1->GetValue((N1-old_N1)*300+N1,1); + Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); - OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi + OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi //--- - EPR = 1.0 + thrust/MilThrust; + EPR = 1.0 + thrust/MilThrust; - OilTemp_degK = Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04); + OilTemp_degK = Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04); - ConsumeFuel(); + ConsumeFuel(); - if (Cutoff) phase = tpOff; - if (Starved) phase = tpOff; + if (Cutoff) phase = tpOff; + if (Starved) phase = tpOff; - return EngPower_HP; + return EngPower_HP; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTurboProp::SpinUp(void) { - double EngPower_HP; - Running = false; - EngStarting = true; - FuelFlow_pph = 0.0; - - if (!GeneratorPower) - { - EngStarting=false; - phase=tpOff; - StartTime = -1; - return 0.0; - } + double EngPower_HP; + Running = false; EngStarting = true; + FuelFlow_pph = 0.0; + + if (!GeneratorPower) { + EngStarting=false; + phase=tpOff; + StartTime = -1; + return 0.0; + } - N1 = ExpSeek(&N1, StarterN1, Idle_Max_Delay * 6, Idle_Max_Delay * 2.4); + N1 = ExpSeek(&N1, StarterN1, Idle_Max_Delay * 6, Idle_Max_Delay * 2.4); - Eng_Temperature = ExpSeek(&Eng_Temperature,TAT,300,400); - double ITT_goal = ITT_N1->GetValue(N1,0.1) + ((N1>20) ? 0.0 : (20-N1)/20.0 * Eng_Temperature); - Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); + Eng_Temperature = ExpSeek(&Eng_Temperature,TAT,300,400); + double ITT_goal = ITT_N1->GetValue(N1,0.1) + ((N1>20) ? 0.0 : (20-N1)/20.0 * Eng_Temperature); + Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); - OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + TAT, 400 , 400); + OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + TAT, 400 , 400); - OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi - NozzlePosition = 1.0; + OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi + NozzlePosition = 1.0; - EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1); - EngPower_HP *= EnginePowerVC->GetValue(); - if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; + EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1); + EngPower_HP *= EnginePowerVC->GetValue(); + if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; - if (StartTime>=0) StartTime+=dt; - if (StartTime > MaxStartingTime && MaxStartingTime > 0) //start failed due timeout - { - phase = tpOff; - StartTime = -1; - } + if (StartTime>=0) StartTime+=dt; + if (StartTime > MaxStartingTime && MaxStartingTime > 0) { //start failed due timeout + phase = tpOff; + StartTime = -1; + } - ConsumeFuel(); // for possible setting Starved = false when fuel tank - // is refilled (fuel crossfeed etc.) + ConsumeFuel(); // for possible setting Starved = false when fuel tank + // is refilled (fuel crossfeed etc.) - return EngPower_HP; + return EngPower_HP; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTurboProp::Start(void) { - double EngPower_HP,eff_coef; - EngStarting = false; - if ((N1 > 15.0) && !Starved) // minimum 15% N2 needed for start - { - double old_N1 = N1; - Cranking = true; // provided for sound effects signal - if (N1 < IdleN1) - { - EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1); - EngPower_HP *= EnginePowerVC->GetValue(); - if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; - N1 = ExpSeek(&N1, IdleN1*1.1, Idle_Max_Delay*4, Idle_Max_Delay * 2.4); - eff_coef = 9.333 - (N1)/12; // 430%Fuel at 60%N1 - FuelFlow_pph = PSFC * EngPower_HP * eff_coef; - Eng_Temperature = ExpSeek(&Eng_Temperature,Eng_ITT_degC,300,400); - double ITT_goal = ITT_N1->GetValue((N1-old_N1)*300+N1,1); - Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); - - OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi - OilTemp_degK = Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04); - - } - else - { - phase = tpRun; - Running = true; - Starter = false; - Cranking = false; - FuelFlow_pph = 0; - EngPower_HP=0.0; - } - } - else // no start if N2 < 15% or Starved - { - phase = tpOff; - Starter = false; + double EngPower_HP,eff_coef; + EngStarting = false; + if ((N1 > 15.0) && !Starved) { // minimum 15% N2 needed for start + double old_N1 = N1; + Cranking = true; // provided for sound effects signal + if (N1 < IdleN1) { + EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1); + EngPower_HP *= EnginePowerVC->GetValue(); + if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; + N1 = ExpSeek(&N1, IdleN1*1.1, Idle_Max_Delay*4, Idle_Max_Delay * 2.4); + eff_coef = 9.333 - (N1)/12; // 430%Fuel at 60%N1 + FuelFlow_pph = PSFC * EngPower_HP * eff_coef; + Eng_Temperature = ExpSeek(&Eng_Temperature,Eng_ITT_degC,300,400); + double ITT_goal = ITT_N1->GetValue((N1-old_N1)*300+N1,1); + Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); + + OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi + OilTemp_degK = Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04); + + } else { + phase = tpRun; + Running = true; + Starter = false; + Cranking = false; + FuelFlow_pph = 0; + EngPower_HP=0.0; } + } else { // no start if N2 < 15% or Starved + phase = tpOff; + Starter = false; + } - ConsumeFuel(); + ConsumeFuel(); - return EngPower_HP; + return EngPower_HP; } @@ -460,28 +408,25 @@ double FGTurboProp::Start(void) double FGTurboProp::CalcFuelNeed(void) { - double dT = FDMExec->GetDeltaT() * Propulsion->GetRate(); - FuelFlowRate = FuelFlow_pph / 3600.0; - FuelExpended = FuelFlowRate * dT; - return FuelExpended; + double dT = FDMExec->GetDeltaT() * Propulsion->GetRate(); + FuelFlowRate = FuelFlow_pph / 3600.0; + FuelExpended = FuelFlowRate * dT; + return FuelExpended; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGTurboProp::Seek(double *var, double target, double accel, double decel) { - double v = *var; - if (v > target) - { - v -= dt * decel; - if (v < target) v = target; - } - else if (v < target) - { - v += dt * accel; - if (v > target) v = target; - } - return v; + double v = *var; + if (v > target) { + v -= dt * decel; + if (v < target) v = target; + } else if (v < target) { + v += dt * accel; + if (v > target) v = target; + } + return v; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -489,16 +434,13 @@ double FGTurboProp::Seek(double *var, double target, double accel, double decel) double FGTurboProp::ExpSeek(double *var, double target, double accel_tau, double decel_tau) { // exponential delay instead of the linear delay used in Seek - double v = *var; - if (v > target) - { - v = (v - target) * exp ( -dt / decel_tau) + target; - } - else if (v < target) - { - v = (target - v) * (1 - exp ( -dt / accel_tau)) + v; - } - return v; + double v = *var; + if (v > target) { + v = (v - target) * exp ( -dt / decel_tau) + target; + } else if (v < target) { + v = (target - v) * (1 - exp ( -dt / accel_tau)) + v; + } + return v; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -506,30 +448,30 @@ double FGTurboProp::ExpSeek(double *var, double target, double accel_tau, double void FGTurboProp::SetDefaults(void) { // Name = "Not defined"; - N1 = N2 = 0.0; - Type = etTurboprop; - MilThrust = 10000.0; - IdleN1 = 30.0; - IdleN2 = 60.0; - MaxN1 = 100.0; - MaxN2 = 100.0; - ThrottleCmd = 0.0; - InletPosition = 1.0; - NozzlePosition = 1.0; - Reversed = false; - Cutoff = true; - phase = tpOff; - Stalled = false; - Seized = false; - Overtemp = false; - Fire = false; - Eng_ITT_degC = 0.0; - - GeneratorPower=true; - Condition = 0; - Ielu_intervent=false; - - Idle_Max_Delay = 1.0; + N1 = N2 = 0.0; + Type = etTurboprop; + MilThrust = 10000.0; + IdleN1 = 30.0; + IdleN2 = 60.0; + MaxN1 = 100.0; + MaxN2 = 100.0; + ThrottleCmd = 0.0; + InletPosition = 1.0; + NozzlePosition = 1.0; + Reversed = false; + Cutoff = true; + phase = tpOff; + Stalled = false; + Seized = false; + Overtemp = false; + Fire = false; + Eng_ITT_degC = 0.0; + + GeneratorPower=true; + Condition = 0; + Ielu_intervent=false; + + Idle_Max_Delay = 1.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -537,55 +479,55 @@ void FGTurboProp::SetDefaults(void) string FGTurboProp::GetEngineLabels(const string& delimiter) { - std::ostringstream buf; + std::ostringstream buf; - buf << Name << "_N1[" << EngineNumber << "]" << delimiter - << Name << "_N2[" << EngineNumber << "]" << delimiter - << Name << "_PwrAvail[" << EngineNumber << "]" << delimiter - << Thruster->GetThrusterLabels(EngineNumber, delimiter); + buf << Name << "_N1[" << EngineNumber << "]" << delimiter + << Name << "_N2[" << EngineNumber << "]" << delimiter + << Name << "_PwrAvail[" << EngineNumber << "]" << delimiter + << Thruster->GetThrusterLabels(EngineNumber, delimiter); - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string FGTurboProp::GetEngineValues(const string& delimiter) { - std::ostringstream buf; + std::ostringstream buf; - buf << PowerAvailable << delimiter - << N1 << delimiter - << N2 << delimiter - << Thruster->GetThrusterValues(EngineNumber,delimiter); + buf << PowerAvailable << delimiter + << N1 << delimiter + << N2 << delimiter + << Thruster->GetThrusterValues(EngineNumber,delimiter); - return buf.str(); + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% int FGTurboProp::InitRunning(void) { - FDMExec->SuspendIntegration(); - Cutoff=false; - Running=true; - N2=16.0; - Calculate(); - FDMExec->ResumeIntegration(); - return phase==tpRun; + FDMExec->SuspendIntegration(); + Cutoff=false; + Running=true; + N2=16.0; + Calculate(); + FDMExec->ResumeIntegration(); + return phase==tpRun; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGTurboProp::bindmodel() { - string property_name, base_property_name; - base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); - property_name = base_property_name + "/n1"; - PropertyManager->Tie( property_name.c_str(), &N1); - property_name = base_property_name + "/n2"; - PropertyManager->Tie( property_name.c_str(), &N2); - property_name = base_property_name + "/reverser"; - PropertyManager->Tie( property_name.c_str(), &Reversed); + string property_name, base_property_name; + base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); + property_name = base_property_name + "/n1"; + PropertyManager->Tie( property_name.c_str(), &N1); + property_name = base_property_name + "/n2"; + PropertyManager->Tie( property_name.c_str(), &N2); + property_name = base_property_name + "/reverser"; + PropertyManager->Tie( property_name.c_str(), &Reversed); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -609,46 +551,37 @@ void FGTurboProp::bindmodel() void FGTurboProp::Debug(int from) { - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) // Standard console startup message output - { - if (from == 0) // Constructor - { - - } - if (from == 2) // called from Load() - { - cout << "\n ****MUJ MOTOR TURBOPROP****\n"; - cout << "\n Engine Name: " << Name << endl; - cout << " MilThrust: " << MilThrust << endl; - cout << " IdleN1: " << IdleN1 << endl; - cout << " MaxN1: " << MaxN1 << endl; - - cout << endl; - } - } - if (debug_lvl & 2 ) // Instantiation/Destruction notification - { - if (from == 0) cout << "Instantiated: FGTurboProp" << endl; - if (from == 1) cout << "Destroyed: FGTurboProp" << endl; - } - if (debug_lvl & 4 ) // Run() method entry print for FGModel-derived objects - { - } - if (debug_lvl & 8 ) // Runtime state variables - { + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + } - if (debug_lvl & 16) // Sanity checking - { + if (from == 2) { // called from Load() + cout << "\n ****MUJ MOTOR TURBOPROP****\n"; + cout << "\n Engine Name: " << Name << endl; + cout << " MilThrust: " << MilThrust << endl; + cout << " IdleN1: " << IdleN1 << endl; + cout << " MaxN1: " << MaxN1 << endl; + + cout << endl; } - if (debug_lvl & 64) - { - if (from == 0) // Constructor - { - cout << IdSrc << endl; - cout << IdHdr << endl; - } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGTurboProp" << endl; + if (from == 1) cout << "Destroyed: FGTurboProp" << endl; + } + if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + } + if (debug_lvl & 8 ) { // Runtime state variables + } + if (debug_lvl & 16) { // Sanity checking + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; } + } } } diff --git a/src/models/propulsion/FGTurboProp.h b/src/models/propulsion/FGTurboProp.h old mode 100644 new mode 100755 index 9885873b05ccc07d869cab47cdc48924738abbbc..c73c0b76534841090a4eb1c8b3e50f976bcc1c58 --- a/src/models/propulsion/FGTurboProp.h +++ b/src/models/propulsion/FGTurboProp.h @@ -46,14 +46,13 @@ INCLUDES #include "input_output/FGXMLElement.h" #include "math/FGTable.h" -#define ID_TURBOPROP "$Id: FGTurboProp.h,v 1.11 2009/10/26 03:48:42 jberndt Exp $" +#define ID_TURBOPROP "$Id: FGTurboProp.h,v 1.12 2010/08/21 18:08:37 jberndt Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -namespace JSBSim -{ +namespace JSBSim { /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -95,221 +94,135 @@ CLASS DECLARATION class FGTurboProp : public FGEngine { public: - /** Constructor - @param Executive pointer to executive structure - @param el pointer to the XML element representing the turbine engine - @param engine_number engine number*/ - FGTurboProp(FGFDMExec* Executive, Element *el, int engine_number); - /// Destructor - ~FGTurboProp(); - - enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim }; - - double Calculate(void); - double CalcFuelNeed(void); - - inline double GetPowerAvailable(void) const - { - return (Eng_HP * hptoftlbssec); - } - inline double GetPowerAvailable_HP(void) const - { - return (Eng_HP); - } - inline double GetPropRPM(void) const - { - return (Prop_RPM); - } - inline double GetThrottleCmd(void) const - { - return (ThrottleCmd); - } - inline bool GetIeluIntervent(void) const - { - return Ielu_intervent; - } - - double Seek(double* var, double target, double accel, double decel); - double ExpSeek(double* var, double target, double accel, double decel); - - phaseType GetPhase(void) const - { - return phase; - } - - bool GetOvertemp(void) const - { - return Overtemp; - } - bool GetFire(void) const - { - return Fire; - } - bool GetReversed(void) const - { - return Reversed; - } - bool GetCutoff(void) const - { - return Cutoff; - } - int GetIgnition(void) const - { - return Ignition; - } - - double GetInlet(void) const - { - return InletPosition; - } - double GetNozzle(void) const - { - return NozzlePosition; - } - double GetN1(void) const - { - return N1; - } - double GetN2(void) const - { - return N2; - } - double GetEPR(void) const - { - return EPR; - } - double GetITT(void) const - { - return Eng_ITT_degC; - } - double GetEngStarting(void) const - { - return EngStarting; - } - - double getOilPressure_psi () const - { - return OilPressure_psi; - } - double getOilTemp_degF (void) - { - return KelvinToFahrenheit(OilTemp_degK); - } - - inline bool GetGeneratorPower(void) const - { - return GeneratorPower; - } - inline int GetCondition(void) const - { - return Condition; - } - void SetIgnition(int ignition) - { - Ignition = ignition; - } - void SetPhase( phaseType p ) - { - phase = p; - } - void SetEPR(double epr) - { - EPR = epr; - } - void SetReverse(bool reversed) - { - Reversed = reversed; - } - void SetCutoff(bool cutoff) - { - Cutoff = cutoff; - } - - inline void SetGeneratorPower(bool gp) - { - GeneratorPower=gp; - } - inline void SetCondition(bool c) - { - Condition=c; - } - int InitRunning(void); - std::string GetEngineLabels(const std::string& delimiter); - std::string GetEngineValues(const std::string& delimiter); + /** Constructor + @param Executive pointer to executive structure + @param el pointer to the XML element representing the turbine engine + @param engine_number engine number*/ + FGTurboProp(FGFDMExec* Executive, Element *el, int engine_number); + /// Destructor + ~FGTurboProp(); + + enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim }; + + void Calculate(void); + double CalcFuelNeed(void); + + inline double GetPowerAvailable(void) const {return (Eng_HP * hptoftlbssec);} + inline double GetPowerAvailable_HP(void) const {return (Eng_HP);} + inline double GetPropRPM(void) const {return (Prop_RPM);} + inline double GetThrottleCmd(void) const {return (ThrottleCmd);} + inline bool GetIeluIntervent(void) const { return Ielu_intervent; } + + double Seek(double* var, double target, double accel, double decel); + double ExpSeek(double* var, double target, double accel, double decel); + + phaseType GetPhase(void) const { return phase; } + + bool GetOvertemp(void) const {return Overtemp; } + bool GetFire(void) const { return Fire; } + bool GetReversed(void) const { return Reversed; } + bool GetCutoff(void) const { return Cutoff; } + int GetIgnition(void) const {return Ignition;} + + double GetInlet(void) const { return InletPosition; } + double GetNozzle(void) const { return NozzlePosition; } + double GetN1(void) const {return N1;} + double GetN2(void) const {return N2;} + double GetEPR(void) const {return EPR;} + double GetITT(void) const {return Eng_ITT_degC;} + double GetEngStarting(void) const { return EngStarting; } + + double getOilPressure_psi () const {return OilPressure_psi;} + double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);} + + inline bool GetGeneratorPower(void) const { return GeneratorPower; } + inline int GetCondition(void) const { return Condition; } + + void SetIgnition(int ignition) {Ignition = ignition;} + void SetPhase( phaseType p ) { phase = p; } + void SetEPR(double epr) {EPR = epr;} + void SetReverse(bool reversed) { Reversed = reversed; } + void SetCutoff(bool cutoff) { Cutoff = cutoff; } + + inline void SetGeneratorPower(bool gp) { GeneratorPower=gp; } + inline void SetCondition(bool c) { Condition=c; } + int InitRunning(void); + std::string GetEngineLabels(const std::string& delimiter); + std::string GetEngineValues(const std::string& delimiter); private: - phaseType phase; ///< Operating mode, or "phase" - double MilThrust; ///< Maximum Unaugmented Thrust, static @ S.L. (lbf) - double IdleN1; ///< Idle N1 - double IdleN2; ///< Idle N2 - double N1; ///< N1 - double N2; ///< N2 - double MaxN1; ///< N1 at 100% throttle - double MaxN2; ///< N2 at 100% throttle - double IdleFF; ///< Idle Fuel Flow (lbm/hr) - double delay; ///< Inverse spool-up time from idle to 100% (seconds) - double dt; ///< Simulator time slice - double N1_factor; ///< factor to tie N1 and throttle - double N2_factor; ///< factor to tie N2 and throttle - double ThrottleCmd; ///< FCS-supplied throttle position - double TAT; ///< total air temperature (deg C) - double PowerAvailable; - bool Stalled; ///< true if engine is compressor-stalled - bool Seized; ///< true if inner spool is seized - bool Overtemp; ///< true if EGT exceeds limits - bool Fire; ///< true if engine fire detected - bool Reversed; - bool Cutoff; - int Ignition; - - double EPR; - double OilPressure_psi; - double OilTemp_degK; - double InletPosition; - double NozzlePosition; - - double Ielu_max_torque; // max propeller torque (before ielu intervent) - bool Ielu_intervent; - double OldThrottle; - - double BetaRangeThrottleEnd; // coef (0-1) where is end of beta-range - double ReverseMaxPower; // coef (0-1) multiplies max throttle on reverse - - double Idle_Max_Delay; // time delay for exponencial - double MaxPower; // max engine power [HP] - double StarterN1; // rotates of generator maked by starter [%] - double MaxStartingTime; // maximal time for start [s] (-1 means not used) - double Prop_RPM; // propeller RPM - double Velocity; - double rho; - double PSFC; // Power specific fuel comsumption [lb/(HP*hr)] at best efficiency - - double Eng_HP; // current engine power - - double StartTime; // engine strating time [s] (0 when start button pushed) - - double ITT_Delay; // time delay for exponencial grow of ITT - double Eng_ITT_degC; - double Eng_Temperature; // temperature inside engine - - bool EngStarting; // logicaly output - TRUE if engine is starting - bool GeneratorPower; - int Condition; - - double Off(void); - double Run(void); - double SpinUp(void); - double Start(void); - - void SetDefaults(void); - bool Load(FGFDMExec *exec, Element *el); - void bindmodel(void); - void Debug(int from); - - FGTable* ITT_N1; // ITT temperature depending on throttle command - FGTable* EnginePowerRPM_N1; - FGTable* EnginePowerVC; + phaseType phase; ///< Operating mode, or "phase" + double MilThrust; ///< Maximum Unaugmented Thrust, static @ S.L. (lbf) + double IdleN1; ///< Idle N1 + double IdleN2; ///< Idle N2 + double N1; ///< N1 + double N2; ///< N2 + double MaxN1; ///< N1 at 100% throttle + double MaxN2; ///< N2 at 100% throttle + double IdleFF; ///< Idle Fuel Flow (lbm/hr) + double delay; ///< Inverse spool-up time from idle to 100% (seconds) + double dt; ///< Simulator time slice + double N1_factor; ///< factor to tie N1 and throttle + double N2_factor; ///< factor to tie N2 and throttle + double ThrottleCmd; ///< FCS-supplied throttle position + double TAT; ///< total air temperature (deg C) + double PowerAvailable; + bool Stalled; ///< true if engine is compressor-stalled + bool Seized; ///< true if inner spool is seized + bool Overtemp; ///< true if EGT exceeds limits + bool Fire; ///< true if engine fire detected + bool Reversed; + bool Cutoff; + int Ignition; + + double EPR; + double OilPressure_psi; + double OilTemp_degK; + double InletPosition; + double NozzlePosition; + + double Ielu_max_torque; // max propeller torque (before ielu intervent) + bool Ielu_intervent; + double OldThrottle; + + double BetaRangeThrottleEnd; // coef (0-1) where is end of beta-range + double ReverseMaxPower; // coef (0-1) multiplies max throttle on reverse + + double Idle_Max_Delay; // time delay for exponencial + double MaxPower; // max engine power [HP] + double StarterN1; // rotates of generator maked by starter [%] + double MaxStartingTime; // maximal time for start [s] (-1 means not used) + double Prop_RPM; // propeller RPM + double Velocity; + double rho; + double PSFC; // Power specific fuel comsumption [lb/(HP*hr)] at best efficiency + + double Eng_HP; // current engine power + + double StartTime; // engine strating time [s] (0 when start button pushed) + + double ITT_Delay; // time delay for exponencial grow of ITT + double Eng_ITT_degC; + double Eng_Temperature; // temperature inside engine + + bool EngStarting; // logicaly output - TRUE if engine is starting + bool GeneratorPower; + int Condition; + + double Off(void); + double Run(void); + double SpinUp(void); + double Start(void); + + void SetDefaults(void); + bool Load(FGFDMExec *exec, Element *el); + void bindmodel(void); + void Debug(int from); + + FGTable* ITT_N1; // ITT temperature depending on throttle command + FGTable* EnginePowerRPM_N1; + FGTable* EnginePowerVC; }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/simgear/magvar/Makefile.am b/src/simgear/magvar/Makefile.am old mode 100644 new mode 100755 diff --git a/src/simgear/magvar/coremag.cxx b/src/simgear/magvar/coremag.cxx old mode 100644 new mode 100755 diff --git a/src/simgear/magvar/coremag.hxx b/src/simgear/magvar/coremag.hxx old mode 100644 new mode 100755 diff --git a/src/simgear/xml/ascii.h b/src/simgear/xml/ascii.h old mode 100644 new mode 100755 diff --git a/src/simgear/xml/asciitab.h b/src/simgear/xml/asciitab.h old mode 100644 new mode 100755 diff --git a/src/simgear/xml/easyxml.cpp b/src/simgear/xml/easyxml.cpp old mode 100644 new mode 100755 index 12cbb5afe2aa542ded72b2b3fb660e506e96bbaa..38b079f51d31ea1133562176ec6a166e7f6ce2d2 --- a/src/simgear/xml/easyxml.cpp +++ b/src/simgear/xml/easyxml.cpp @@ -46,31 +46,30 @@ XMLAttributes::~XMLAttributes () int XMLAttributes::findAttribute (const char * name) const { - int s = size(); - for (int i = 0; i < s; i++) - { - if (strcmp(name, getName(i)) == 0) - return i; - } - return -1; + int s = size(); + for (int i = 0; i < s; i++) { + if (strcmp(name, getName(i)) == 0) + return i; + } + return -1; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool XMLAttributes::hasAttribute (const char * name) const { - return (findAttribute(name) != -1); + return (findAttribute(name) != -1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% const char *XMLAttributes::getValue (const char * name) const { - int pos = findAttribute(name); - if (pos >= 0) - return getValue(pos); - else - return 0; + int pos = findAttribute(name); + if (pos >= 0) + return getValue(pos); + else + return 0; } //////////////////////////////////////////////////////////////////////// @@ -85,9 +84,9 @@ XMLAttributesDefault::XMLAttributesDefault () XMLAttributesDefault::XMLAttributesDefault (const XMLAttributes &atts) { - int s = atts.size(); - for (int i = 0; i < s; i++) - addAttribute(atts.getName(i), atts.getValue(i)); + int s = atts.size(); + for (int i = 0; i < s; i++) + addAttribute(atts.getName(i), atts.getValue(i)); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -100,59 +99,56 @@ XMLAttributesDefault::~XMLAttributesDefault () int XMLAttributesDefault::size () const { - return _atts.size() / 2; + return _atts.size() / 2; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% const char *XMLAttributesDefault::getName (int i) const { - return _atts[i*2].c_str(); + return _atts[i*2].c_str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% const char *XMLAttributesDefault::getValue (int i) const { - return _atts[i*2+1].c_str(); + return _atts[i*2+1].c_str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void XMLAttributesDefault::addAttribute (const char * name, const char * value) { - _atts.push_back(name); - _atts.push_back(value); + _atts.push_back(name); + _atts.push_back(value); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void XMLAttributesDefault::setName (int i, const char * name) { - _atts[i*2] = name; + _atts[i*2] = name; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void XMLAttributesDefault::setValue (int i, const char * name) { - _atts[i*2+1] = name; + _atts[i*2+1] = name; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void XMLAttributesDefault::setValue (const char * name, const char * value) { - int pos = findAttribute(name); - if (pos >= 0) - { - setName(pos, name); - setValue(pos, value); - } - else - { - addAttribute(name, value); - } + int pos = findAttribute(name); + if (pos >= 0) { + setName(pos, name); + setValue(pos, value); + } else { + addAttribute(name, value); + } } //////////////////////////////////////////////////////////////////////// @@ -162,38 +158,38 @@ void XMLAttributesDefault::setValue (const char * name, const char * value) class ExpatAtts : public XMLAttributes { public: - ExpatAtts (const char ** atts) : _atts(atts) {} + ExpatAtts (const char ** atts) : _atts(atts) {} - virtual int size () const; - virtual const char * getName (int i) const; - virtual const char * getValue (int i) const; + virtual int size () const; + virtual const char * getName (int i) const; + virtual const char * getValue (int i) const; private: - const char ** _atts; + const char ** _atts; }; //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% int ExpatAtts::size () const { - int s = 0; - for (int i = 0; _atts[i] != 0; i += 2) - s++; - return s; + int s = 0; + for (int i = 0; _atts[i] != 0; i += 2) + s++; + return s; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% const char *ExpatAtts::getName (int i) const { - return _atts[i*2]; + return _atts[i*2]; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% const char *ExpatAtts::getValue (int i) const { - return _atts[i*2+1]; + return _atts[i*2+1]; } //////////////////////////////////////////////////////////////////////// @@ -204,30 +200,30 @@ const char *ExpatAtts::getValue (int i) const static void start_element (void * userData, const char * name, const char ** atts) { - VISITOR.startElement(name, ExpatAtts(atts)); + VISITOR.startElement(name, ExpatAtts(atts)); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% static void end_element (void * userData, const char * name) { - VISITOR.endElement(name); + VISITOR.endElement(name); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% static void character_data (void * userData, const char * s, int len) { - VISITOR.data(s, len); + VISITOR.data(s, len); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% static void processing_instruction (void * userData, - const char * target, - const char * data) + const char * target, + const char * data) { - VISITOR.pi(target, data); + VISITOR.pi(target, data); } #undef VISITOR @@ -238,68 +234,58 @@ static void processing_instruction (void * userData, void readXML (istream &input, XMLVisitor &visitor, const string &path) { - XML_Parser parser = XML_ParserCreate(0); - XML_SetUserData(parser, &visitor); - XML_SetElementHandler(parser, start_element, end_element); - XML_SetCharacterDataHandler(parser, character_data); - XML_SetProcessingInstructionHandler(parser, processing_instruction); - - visitor.startXML(); - - char buf[16384]; - while (!input.eof()) - { - - if (!input.good()) - { - cerr << "Problem reading input file" << endl; - XML_ParserFree(parser); - return; - } - - input.read(buf,16384); - if (!XML_Parse(parser, buf, input.gcount(), false)) - { - cerr << "XML parse error: " << XML_ErrorString(XML_GetErrorCode(parser)) << endl; - XML_ParserFree(parser); - return; - } + XML_Parser parser = XML_ParserCreate(0); + XML_SetUserData(parser, &visitor); + XML_SetElementHandler(parser, start_element, end_element); + XML_SetCharacterDataHandler(parser, character_data); + XML_SetProcessingInstructionHandler(parser, processing_instruction); + + visitor.startXML(); + + char buf[16384]; + while (!input.eof()) { + if (!input.good()) { + cerr << "Problem reading input file" << endl; + XML_ParserFree(parser); + return; } -// Verify end of document. - if (!XML_Parse(parser, buf, 0, true)) - { - cerr << "XML parse error: " << XML_ErrorString(XML_GetErrorCode(parser)) << endl; - XML_ParserFree(parser); - return; + input.read(buf,16384); + if (!XML_Parse(parser, buf, input.gcount(), false)) { + cerr << "XML parse error: " << XML_ErrorString(XML_GetErrorCode(parser)) << endl; + XML_ParserFree(parser); + return; } + } + +// Verify end of document. + if (!XML_Parse(parser, buf, 0, true)) { + cerr << "XML parse error: " << XML_ErrorString(XML_GetErrorCode(parser)) << endl; XML_ParserFree(parser); + return; + } + + XML_ParserFree(parser); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void readXML (const string &path, XMLVisitor &visitor) { - ifstream input(path.c_str()); - if (input.good()) - { - try - { - readXML(input, visitor, path); - } - catch (...) - { - input.close(); - cerr << "Failed to open file" << endl; - } - } - else - { - cerr << "Failed to open file" << endl; + ifstream input(path.c_str()); + if (input.good()) { + try { + readXML(input, visitor, path); + } catch (...) { + input.close(); + cerr << "Failed to open file" << endl; } - input.close(); + } else { + cerr << "Failed to open file" << endl; + } + input.close(); } // end of easyxml.cxx diff --git a/src/simgear/xml/easyxml.cxx b/src/simgear/xml/easyxml.cxx old mode 100644 new mode 100755 diff --git a/src/simgear/xml/easyxml.hxx b/src/simgear/xml/easyxml.hxx old mode 100644 new mode 100755 diff --git a/src/simgear/xml/expat.h b/src/simgear/xml/expat.h old mode 100644 new mode 100755 index 229c140bb76a146ac709bde3b0ff5aed7e8639ee..cb07c1c92e8b522eef5173caf56a10d3bb617c37 --- a/src/simgear/xml/expat.h +++ b/src/simgear/xml/expat.h @@ -38,76 +38,72 @@ typedef unsigned char XML_Bool; Otherwise, the #define hackery is quite ugly and would have been dropped. */ -enum XML_Status -{ - XML_STATUS_ERROR = 0, +enum XML_Status { + XML_STATUS_ERROR = 0, #define XML_STATUS_ERROR XML_STATUS_ERROR - XML_STATUS_OK = 1, + XML_STATUS_OK = 1, #define XML_STATUS_OK XML_STATUS_OK - XML_STATUS_SUSPENDED = 2, + XML_STATUS_SUSPENDED = 2, #define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED }; -enum XML_Error -{ - XML_ERROR_NONE, - XML_ERROR_NO_MEMORY, - XML_ERROR_SYNTAX, - XML_ERROR_NO_ELEMENTS, - XML_ERROR_INVALID_TOKEN, - XML_ERROR_UNCLOSED_TOKEN, - XML_ERROR_PARTIAL_CHAR, - XML_ERROR_TAG_MISMATCH, - XML_ERROR_DUPLICATE_ATTRIBUTE, - XML_ERROR_JUNK_AFTER_DOC_ELEMENT, - XML_ERROR_PARAM_ENTITY_REF, - XML_ERROR_UNDEFINED_ENTITY, - XML_ERROR_RECURSIVE_ENTITY_REF, - XML_ERROR_ASYNC_ENTITY, - XML_ERROR_BAD_CHAR_REF, - XML_ERROR_BINARY_ENTITY_REF, - XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, - XML_ERROR_MISPLACED_XML_PI, - XML_ERROR_UNKNOWN_ENCODING, - XML_ERROR_INCORRECT_ENCODING, - XML_ERROR_UNCLOSED_CDATA_SECTION, - XML_ERROR_EXTERNAL_ENTITY_HANDLING, - XML_ERROR_NOT_STANDALONE, - XML_ERROR_UNEXPECTED_STATE, - XML_ERROR_ENTITY_DECLARED_IN_PE, - XML_ERROR_FEATURE_REQUIRES_XML_DTD, - XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING, - /* Added in 1.95.7. */ - XML_ERROR_UNBOUND_PREFIX, - /* Added in 1.95.8. */ - XML_ERROR_UNDECLARING_PREFIX, - XML_ERROR_INCOMPLETE_PE, - XML_ERROR_XML_DECL, - XML_ERROR_TEXT_DECL, - XML_ERROR_PUBLICID, - XML_ERROR_SUSPENDED, - XML_ERROR_NOT_SUSPENDED, - XML_ERROR_ABORTED, - XML_ERROR_FINISHED, - XML_ERROR_SUSPEND_PE +enum XML_Error { + XML_ERROR_NONE, + XML_ERROR_NO_MEMORY, + XML_ERROR_SYNTAX, + XML_ERROR_NO_ELEMENTS, + XML_ERROR_INVALID_TOKEN, + XML_ERROR_UNCLOSED_TOKEN, + XML_ERROR_PARTIAL_CHAR, + XML_ERROR_TAG_MISMATCH, + XML_ERROR_DUPLICATE_ATTRIBUTE, + XML_ERROR_JUNK_AFTER_DOC_ELEMENT, + XML_ERROR_PARAM_ENTITY_REF, + XML_ERROR_UNDEFINED_ENTITY, + XML_ERROR_RECURSIVE_ENTITY_REF, + XML_ERROR_ASYNC_ENTITY, + XML_ERROR_BAD_CHAR_REF, + XML_ERROR_BINARY_ENTITY_REF, + XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, + XML_ERROR_MISPLACED_XML_PI, + XML_ERROR_UNKNOWN_ENCODING, + XML_ERROR_INCORRECT_ENCODING, + XML_ERROR_UNCLOSED_CDATA_SECTION, + XML_ERROR_EXTERNAL_ENTITY_HANDLING, + XML_ERROR_NOT_STANDALONE, + XML_ERROR_UNEXPECTED_STATE, + XML_ERROR_ENTITY_DECLARED_IN_PE, + XML_ERROR_FEATURE_REQUIRES_XML_DTD, + XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING, + /* Added in 1.95.7. */ + XML_ERROR_UNBOUND_PREFIX, + /* Added in 1.95.8. */ + XML_ERROR_UNDECLARING_PREFIX, + XML_ERROR_INCOMPLETE_PE, + XML_ERROR_XML_DECL, + XML_ERROR_TEXT_DECL, + XML_ERROR_PUBLICID, + XML_ERROR_SUSPENDED, + XML_ERROR_NOT_SUSPENDED, + XML_ERROR_ABORTED, + XML_ERROR_FINISHED, + XML_ERROR_SUSPEND_PE }; -enum XML_Content_Type -{ - XML_CTYPE_EMPTY = 1, - XML_CTYPE_ANY, - XML_CTYPE_MIXED, - XML_CTYPE_NAME, - XML_CTYPE_CHOICE, - XML_CTYPE_SEQ +enum XML_Content_Type { + XML_CTYPE_EMPTY = 1, + XML_CTYPE_ANY, + XML_CTYPE_MIXED, + XML_CTYPE_NAME, + XML_CTYPE_CHOICE, + XML_CTYPE_SEQ }; -enum XML_Content_Quant -{ - XML_CQUANT_NONE, - XML_CQUANT_OPT, - XML_CQUANT_REP, - XML_CQUANT_PLUS +enum XML_Content_Quant { + XML_CQUANT_NONE, + XML_CQUANT_OPT, + XML_CQUANT_REP, + XML_CQUANT_PLUS }; /* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be @@ -130,13 +126,12 @@ enum XML_Content_Quant typedef struct XML_cp XML_Content; -struct XML_cp -{ - enum XML_Content_Type type; - enum XML_Content_Quant quant; - XML_Char * name; - unsigned int numchildren; - XML_Content * children; +struct XML_cp { + enum XML_Content_Type type; + enum XML_Content_Quant quant; + XML_Char * name; + unsigned int numchildren; + XML_Content * children; }; @@ -145,8 +140,8 @@ struct XML_cp to free model when finished with it. */ typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData, - const XML_Char *name, - XML_Content *model); + const XML_Char *name, + XML_Content *model); XMLPARSEAPI(void) XML_SetElementDeclHandler(XML_Parser parser, @@ -161,12 +156,12 @@ XML_SetElementDeclHandler(XML_Parser parser, true and default is non-NULL, then this is a "#FIXED" default. */ typedef void (XMLCALL *XML_AttlistDeclHandler) ( - void *userData, - const XML_Char *elname, - const XML_Char *attname, - const XML_Char *att_type, - const XML_Char *dflt, - int isrequired); + void *userData, + const XML_Char *elname, + const XML_Char *attname, + const XML_Char *att_type, + const XML_Char *dflt, + int isrequired); XMLPARSEAPI(void) XML_SetAttlistDeclHandler(XML_Parser parser, @@ -181,20 +176,19 @@ XML_SetAttlistDeclHandler(XML_Parser parser, as no, or that it was given as yes. */ typedef void (XMLCALL *XML_XmlDeclHandler) (void *userData, - const XML_Char *version, - const XML_Char *encoding, - int standalone); + const XML_Char *version, + const XML_Char *encoding, + int standalone); XMLPARSEAPI(void) XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler xmldecl); -typedef struct -{ - void *(*malloc_fcn)(size_t size); - void *(*realloc_fcn)(void *ptr, size_t size); - void (*free_fcn)(void *ptr); +typedef struct { + void *(*malloc_fcn)(size_t size); + void *(*realloc_fcn)(void *ptr, size_t size); + void (*free_fcn)(void *ptr); } XML_Memory_Handling_Suite; /* Constructs a new parser; encoding is the encoding specified by the @@ -248,27 +242,27 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encoding); names and values are 0 terminated. */ typedef void (XMLCALL *XML_StartElementHandler) (void *userData, - const XML_Char *name, - const XML_Char **atts); + const XML_Char *name, + const XML_Char **atts); typedef void (XMLCALL *XML_EndElementHandler) (void *userData, - const XML_Char *name); + const XML_Char *name); /* s is not 0 terminated. */ typedef void (XMLCALL *XML_CharacterDataHandler) (void *userData, - const XML_Char *s, - int len); + const XML_Char *s, + int len); /* target and data are 0 terminated */ typedef void (XMLCALL *XML_ProcessingInstructionHandler) ( - void *userData, - const XML_Char *target, - const XML_Char *data); + void *userData, + const XML_Char *target, + const XML_Char *data); /* data is 0 terminated */ typedef void (XMLCALL *XML_CommentHandler) (void *userData, - const XML_Char *data); + const XML_Char *data); typedef void (XMLCALL *XML_StartCdataSectionHandler) (void *userData); typedef void (XMLCALL *XML_EndCdataSectionHandler) (void *userData); @@ -287,18 +281,18 @@ typedef void (XMLCALL *XML_EndCdataSectionHandler) (void *userData); multiple calls. */ typedef void (XMLCALL *XML_DefaultHandler) (void *userData, - const XML_Char *s, - int len); + const XML_Char *s, + int len); /* This is called for the start of the DOCTYPE declaration, before any DTD or internal subset is parsed. */ typedef void (XMLCALL *XML_StartDoctypeDeclHandler) ( - void *userData, - const XML_Char *doctypeName, - const XML_Char *sysid, - const XML_Char *pubid, - int has_internal_subset); + void *userData, + const XML_Char *doctypeName, + const XML_Char *sysid, + const XML_Char *pubid, + int has_internal_subset); /* This is called for the start of the DOCTYPE declaration when the closing > is encountered, but after processing any external @@ -325,15 +319,15 @@ typedef void (XMLCALL *XML_EndDoctypeDeclHandler)(void *userData); that would break binary compatibility. */ typedef void (XMLCALL *XML_EntityDeclHandler) ( - void *userData, - const XML_Char *entityName, - int is_parameter_entity, - const XML_Char *value, - int value_length, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName); + void *userData, + const XML_Char *entityName, + int is_parameter_entity, + const XML_Char *value, + int value_length, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); XMLPARSEAPI(void) XML_SetEntityDeclHandler(XML_Parser parser, @@ -349,23 +343,23 @@ XML_SetEntityDeclHandler(XML_Parser parser, NULL. The other arguments may be. */ typedef void (XMLCALL *XML_UnparsedEntityDeclHandler) ( - void *userData, - const XML_Char *entityName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName); + void *userData, + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); /* This is called for a declaration of notation. The base argument is whatever was set by XML_SetBase. The notationName will never be NULL. The other arguments can be. */ typedef void (XMLCALL *XML_NotationDeclHandler) ( - void *userData, - const XML_Char *notationName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId); + void *userData, + const XML_Char *notationName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); /* When namespace processing is enabled, these are called once for each namespace declaration. The call to the start and end element @@ -374,13 +368,13 @@ typedef void (XMLCALL *XML_NotationDeclHandler) ( NULL. For an xmlns="" attribute, uri will be NULL. */ typedef void (XMLCALL *XML_StartNamespaceDeclHandler) ( - void *userData, - const XML_Char *prefix, - const XML_Char *uri); + void *userData, + const XML_Char *prefix, + const XML_Char *uri); typedef void (XMLCALL *XML_EndNamespaceDeclHandler) ( - void *userData, - const XML_Char *prefix); + void *userData, + const XML_Char *prefix); /* This is called if the document is not standalone, that is, it has an external subset or a reference to a parameter entity, but does not @@ -428,11 +422,11 @@ typedef int (XMLCALL *XML_NotStandaloneHandler) (void *userData); not userData. */ typedef int (XMLCALL *XML_ExternalEntityRefHandler) ( - XML_Parser parser, - const XML_Char *context, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId); + XML_Parser parser, + const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); /* This is called in two situations: 1) An entity reference is encountered for which no declaration @@ -445,9 +439,9 @@ typedef int (XMLCALL *XML_ExternalEntityRefHandler) ( declarations or attribute values */ typedef void (XMLCALL *XML_SkippedEntityHandler) ( - void *userData, - const XML_Char *entityName, - int is_parameter_entity); + void *userData, + const XML_Char *entityName, + int is_parameter_entity); /* This structure is filled in by the XML_UnknownEncodingHandler to provide information to the parser about encodings that are unknown @@ -501,12 +495,11 @@ typedef void (XMLCALL *XML_SkippedEntityHandler) ( 4. No Unicode character may be encoded by more than one distinct sequence of bytes. */ -typedef struct -{ - int map[256]; - void *data; - int (XMLCALL *convert)(void *data, const char *s); - void (XMLCALL *release)(void *data); +typedef struct { + int map[256]; + void *data; + int (XMLCALL *convert)(void *data, const char *s); + void (XMLCALL *release)(void *data); } XML_Encoding; /* This is called for an encoding that is unknown to the parser. @@ -525,9 +518,9 @@ typedef struct return an XML_UNKNOWN_ENCODING error. */ typedef int (XMLCALL *XML_UnknownEncodingHandler) ( - void *encodingHandlerData, - const XML_Char *name, - XML_Encoding *info); + void *encodingHandlerData, + const XML_Char *name, + XML_Encoding *info); XMLPARSEAPI(void) XML_SetElementHandler(XML_Parser parser, @@ -764,20 +757,20 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal); (resumable = 0) an already suspended parser. Some call-backs may still follow because they would otherwise get lost. Examples: - endElementHandler() for empty elements when stopped in - startElementHandler(), - - endNameSpaceDeclHandler() when stopped in endElementHandler(), + startElementHandler(), + - endNameSpaceDeclHandler() when stopped in endElementHandler(), and possibly others. Can be called from most handlers, including DTD related call-backs, except when parsing an external parameter entity and resumable != 0. Returns XML_STATUS_OK when successful, XML_STATUS_ERROR otherwise. - Possible error codes: + Possible error codes: - XML_ERROR_SUSPENDED: when suspending an already suspended parser. - XML_ERROR_FINISHED: when the parser has already finished. - XML_ERROR_SUSPEND_PE: when suspending while parsing an external PE. - When resumable != 0 (true) then parsing is suspended, that is, - XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED. + When resumable != 0 (true) then parsing is suspended, that is, + XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED. Otherwise, parsing is aborted, that is, XML_Parse() and XML_ParseBuffer() return XML_STATUS_ERROR with error code XML_ERROR_ABORTED. @@ -788,7 +781,7 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal); the externalEntityRefHandler() to call XML_StopParser() on the parent parser (recursively), if one wants to stop parsing altogether. - When suspended, parsing can be resumed by calling XML_ResumeParser(). + When suspended, parsing can be resumed by calling XML_ResumeParser(). */ XMLPARSEAPI(enum XML_Status) XML_StopParser(XML_Parser parser, XML_Bool resumable); @@ -796,7 +789,7 @@ XML_StopParser(XML_Parser parser, XML_Bool resumable); /* Resumes parsing after it has been suspended with XML_StopParser(). Must not be called from within a handler call-back. Returns same status codes as XML_Parse() or XML_ParseBuffer(). - Additional error code XML_ERROR_NOT_SUSPENDED possible. + Additional error code XML_ERROR_NOT_SUSPENDED possible. *Note*: This must be called on the most deeply nested child parser instance @@ -808,18 +801,16 @@ XML_StopParser(XML_Parser parser, XML_Bool resumable); XMLPARSEAPI(enum XML_Status) XML_ResumeParser(XML_Parser parser); -enum XML_Parsing -{ - XML_INITIALIZED, - XML_PARSING, - XML_FINISHED, - XML_SUSPENDED +enum XML_Parsing { + XML_INITIALIZED, + XML_PARSING, + XML_FINISHED, + XML_SUSPENDED }; -typedef struct -{ - enum XML_Parsing parsing; - XML_Bool finalBuffer; +typedef struct { + enum XML_Parsing parsing; + XML_Bool finalBuffer; } XML_ParsingStatus; /* Returns status of parser with respect to being initialized, parsing, @@ -851,11 +842,10 @@ XML_ExternalEntityParserCreate(XML_Parser parser, const XML_Char *context, const XML_Char *encoding); -enum XML_ParamEntityParsing -{ - XML_PARAM_ENTITY_PARSING_NEVER, - XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, - XML_PARAM_ENTITY_PARSING_ALWAYS +enum XML_ParamEntityParsing { + XML_PARAM_ENTITY_PARSING_NEVER, + XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, + XML_PARAM_ENTITY_PARSING_ALWAYS }; /* Controls parsing of parameter entities (including the external DTD @@ -900,7 +890,7 @@ XML_GetErrorCode(XML_Parser parser); be within the relevant markup. When called outside of the callback functions, the position indicated will be just past the last parse event (regardless of whether there was an associated callback). - + They may also be called after returning from a call to XML_Parse or XML_ParseBuffer. If the return value is XML_STATUS_ERROR then the location is the location of the character at which the error @@ -963,11 +953,10 @@ XML_ErrorString(enum XML_Error code); XMLPARSEAPI(const XML_LChar *) XML_ExpatVersion(void); -typedef struct -{ - int major; - int minor; - int micro; +typedef struct { + int major; + int minor; + int micro; } XML_Expat_Version; /* Return an XML_Expat_Version structure containing numeric version @@ -977,24 +966,22 @@ XMLPARSEAPI(XML_Expat_Version) XML_ExpatVersionInfo(void); /* Added in Expat 1.95.5. */ -enum XML_FeatureEnum -{ - XML_FEATURE_END = 0, - XML_FEATURE_UNICODE, - XML_FEATURE_UNICODE_WCHAR_T, - XML_FEATURE_DTD, - XML_FEATURE_CONTEXT_BYTES, - XML_FEATURE_MIN_SIZE, - XML_FEATURE_SIZEOF_XML_CHAR, - XML_FEATURE_SIZEOF_XML_LCHAR - /* Additional features must be added to the end of this enum. */ +enum XML_FeatureEnum { + XML_FEATURE_END = 0, + XML_FEATURE_UNICODE, + XML_FEATURE_UNICODE_WCHAR_T, + XML_FEATURE_DTD, + XML_FEATURE_CONTEXT_BYTES, + XML_FEATURE_MIN_SIZE, + XML_FEATURE_SIZEOF_XML_CHAR, + XML_FEATURE_SIZEOF_XML_LCHAR + /* Additional features must be added to the end of this enum. */ }; -typedef struct -{ - enum XML_FeatureEnum feature; - const XML_LChar *name; - long int value; +typedef struct { + enum XML_FeatureEnum feature; + const XML_LChar *name; + long int value; } XML_Feature; XMLPARSEAPI(const XML_Feature *) diff --git a/src/simgear/xml/expat_config.h b/src/simgear/xml/expat_config.h old mode 100644 new mode 100755 diff --git a/src/simgear/xml/expat_external.h b/src/simgear/xml/expat_external.h old mode 100644 new mode 100755 index 0a263fd14809af0c4348cea2745fbabf0413aa66..4145cacacdfb4fc033e256a9e6f665dbce4ddac3 --- a/src/simgear/xml/expat_external.h +++ b/src/simgear/xml/expat_external.h @@ -71,8 +71,7 @@ #define XMLPARSEAPI(type) XMLIMPORT type XMLCALL #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif #ifdef XML_UNICODE_WCHAR_T @@ -81,13 +80,13 @@ extern "C" #ifdef XML_UNICODE /* Information is UTF-16 encoded. */ #ifdef XML_UNICODE_WCHAR_T - typedef wchar_t XML_Char; - typedef wchar_t XML_LChar; +typedef wchar_t XML_Char; +typedef wchar_t XML_LChar; #else - typedef unsigned short XML_Char; - typedef char XML_LChar; +typedef unsigned short XML_Char; +typedef char XML_LChar; #endif /* XML_UNICODE_WCHAR_T */ #else /* Information is UTF-8 encoded. */ - typedef char XML_Char; - typedef char XML_LChar; +typedef char XML_Char; +typedef char XML_LChar; #endif /* XML_UNICODE */ diff --git a/src/simgear/xml/iasciitab.h b/src/simgear/xml/iasciitab.h old mode 100644 new mode 100755 diff --git a/src/simgear/xml/internal.h b/src/simgear/xml/internal.h old mode 100644 new mode 100755 diff --git a/src/simgear/xml/latin1tab.h b/src/simgear/xml/latin1tab.h old mode 100644 new mode 100755 diff --git a/src/simgear/xml/macconfig.h b/src/simgear/xml/macconfig.h old mode 100644 new mode 100755 diff --git a/src/simgear/xml/nametab.h b/src/simgear/xml/nametab.h old mode 100644 new mode 100755 index 964261c7158ea2dd4e72d389bdacc7aeebe5e2c0..b05e62c77a6c624a6828dd3f4e25ba8fe841e7a0 --- a/src/simgear/xml/nametab.h +++ b/src/simgear/xml/nametab.h @@ -1,153 +1,150 @@ -static const unsigned namingBitmap[] = -{ - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, - 0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, - 0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, - 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, - 0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, - 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, - 0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, - 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, - 0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, - 0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, - 0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, - 0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, - 0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, - 0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, - 0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, - 0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, - 0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, - 0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, - 0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, - 0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, - 0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, - 0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, - 0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, - 0x40000000, 0xF580C900, 0x00000007, 0x02010800, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, - 0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, - 0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, - 0x00000000, 0x00004C40, 0x00000000, 0x00000000, - 0x00000007, 0x00000000, 0x00000000, 0x00000000, - 0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, - 0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, - 0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, - 0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, - 0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, - 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, - 0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, - 0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, - 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, - 0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, - 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, - 0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, - 0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, - 0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, - 0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, - 0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, - 0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, - 0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, - 0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, - 0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, - 0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, - 0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, - 0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, - 0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, - 0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, - 0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, - 0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, - 0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, +static const unsigned namingBitmap[] = { +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, +0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, +0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, +0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, +0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, +0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, +0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, +0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, +0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, +0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, +0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, +0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, +0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, +0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, +0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, +0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, +0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, +0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, +0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, +0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, +0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, +0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, +0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, +0x40000000, 0xF580C900, 0x00000007, 0x02010800, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, +0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, +0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, +0x00000000, 0x00004C40, 0x00000000, 0x00000000, +0x00000007, 0x00000000, 0x00000000, 0x00000000, +0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, +0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, +0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, +0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, +0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, +0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, +0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, +0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, +0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, +0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, +0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, +0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, +0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, +0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, +0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, +0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, +0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, +0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, +0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, +0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, +0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, +0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, +0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, +0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, +0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, +0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, +0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, +0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, }; -static const unsigned char nmstrtPages[] = -{ - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, - 0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, - 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +static const unsigned char nmstrtPages[] = { +0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, +0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, +0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, +0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -static const unsigned char namePages[] = -{ - 0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, - 0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, - 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, - 0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +static const unsigned char namePages[] = { +0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, +0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, +0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, +0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; diff --git a/src/simgear/xml/utf8tab.h b/src/simgear/xml/utf8tab.h old mode 100644 new mode 100755 diff --git a/src/simgear/xml/winconfig.h b/src/simgear/xml/winconfig.h old mode 100644 new mode 100755 diff --git a/src/simgear/xml/xmlparse.c b/src/simgear/xml/xmlparse.c old mode 100644 new mode 100755 index fd065530c9ee6cf47e2772c0c09de48b68375dab..ac1fd774606b24731d739b9eb6236c5dc3a5c582 --- a/src/simgear/xml/xmlparse.c +++ b/src/simgear/xml/xmlparse.c @@ -83,18 +83,16 @@ typedef char ICHAR; typedef const XML_Char *KEY; -typedef struct -{ - KEY name; +typedef struct { + KEY name; } NAMED; -typedef struct -{ - NAMED **v; - unsigned char power; - size_t size; - size_t used; - const XML_Memory_Handling_Suite *mem; +typedef struct { + NAMED **v; + unsigned char power; + size_t size; + size_t used; + const XML_Memory_Handling_Suite *mem; } HASH_TABLE; /* Basic character hash algorithm, taken from Python's string hash: @@ -122,10 +120,9 @@ typedef struct #define PROBE_STEP(hash, mask, power) \ ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1)) -typedef struct -{ - NAMED **p; - NAMED **end; +typedef struct { + NAMED **p; + NAMED **end; } HASH_TABLE_ITER; #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ @@ -137,31 +134,28 @@ typedef struct #define EXPAND_SPARE 24 -typedef struct binding -{ - struct prefix *prefix; - struct binding *nextTagBinding; - struct binding *prevPrefixBinding; - const struct attribute_id *attId; - XML_Char *uri; - int uriLen; - int uriAlloc; +typedef struct binding { + struct prefix *prefix; + struct binding *nextTagBinding; + struct binding *prevPrefixBinding; + const struct attribute_id *attId; + XML_Char *uri; + int uriLen; + int uriAlloc; } BINDING; -typedef struct prefix -{ - const XML_Char *name; - BINDING *binding; +typedef struct prefix { + const XML_Char *name; + BINDING *binding; } PREFIX; -typedef struct -{ - const XML_Char *str; - const XML_Char *localPart; - const XML_Char *prefix; - int strLen; - int uriLen; - int prefixLen; +typedef struct { + const XML_Char *str; + const XML_Char *localPart; + const XML_Char *prefix; + int strLen; + int uriLen; + int prefixLen; } TAG_NAME; /* TAG represents an open element. @@ -177,140 +171,129 @@ typedef struct A parser re-uses these structures, maintaining a list of allocated TAG objects in a free list. */ -typedef struct tag -{ - struct tag *parent; /* parent of this element */ - const char *rawName; /* tagName in the original encoding */ - int rawNameLength; - TAG_NAME name; /* tagName in the API encoding */ - char *buf; /* buffer for name components */ - char *bufEnd; /* end of the buffer */ - BINDING *bindings; +typedef struct tag { + struct tag *parent; /* parent of this element */ + const char *rawName; /* tagName in the original encoding */ + int rawNameLength; + TAG_NAME name; /* tagName in the API encoding */ + char *buf; /* buffer for name components */ + char *bufEnd; /* end of the buffer */ + BINDING *bindings; } TAG; -typedef struct -{ - const XML_Char *name; - const XML_Char *textPtr; - int textLen; /* length in XML_Chars */ - int processed; /* # of processed bytes - when suspended */ - const XML_Char *systemId; - const XML_Char *base; - const XML_Char *publicId; - const XML_Char *notation; - XML_Bool open; - XML_Bool is_param; - XML_Bool is_internal; /* true if declared in internal subset outside PE */ +typedef struct { + const XML_Char *name; + const XML_Char *textPtr; + int textLen; /* length in XML_Chars */ + int processed; /* # of processed bytes - when suspended */ + const XML_Char *systemId; + const XML_Char *base; + const XML_Char *publicId; + const XML_Char *notation; + XML_Bool open; + XML_Bool is_param; + XML_Bool is_internal; /* true if declared in internal subset outside PE */ } ENTITY; -typedef struct -{ - enum XML_Content_Type type; - enum XML_Content_Quant quant; - const XML_Char * name; - int firstchild; - int lastchild; - int childcnt; - int nextsib; +typedef struct { + enum XML_Content_Type type; + enum XML_Content_Quant quant; + const XML_Char * name; + int firstchild; + int lastchild; + int childcnt; + int nextsib; } CONTENT_SCAFFOLD; #define INIT_SCAFFOLD_ELEMENTS 32 -typedef struct block -{ - struct block *next; - int size; - XML_Char s[1]; +typedef struct block { + struct block *next; + int size; + XML_Char s[1]; } BLOCK; -typedef struct -{ - BLOCK *blocks; - BLOCK *freeBlocks; - const XML_Char *end; - XML_Char *ptr; - XML_Char *start; - const XML_Memory_Handling_Suite *mem; +typedef struct { + BLOCK *blocks; + BLOCK *freeBlocks; + const XML_Char *end; + XML_Char *ptr; + XML_Char *start; + const XML_Memory_Handling_Suite *mem; } STRING_POOL; /* The XML_Char before the name is used to determine whether an attribute has been specified. */ -typedef struct attribute_id -{ - XML_Char *name; - PREFIX *prefix; - XML_Bool maybeTokenized; - XML_Bool xmlns; +typedef struct attribute_id { + XML_Char *name; + PREFIX *prefix; + XML_Bool maybeTokenized; + XML_Bool xmlns; } ATTRIBUTE_ID; -typedef struct -{ - const ATTRIBUTE_ID *id; - XML_Bool isCdata; - const XML_Char *value; +typedef struct { + const ATTRIBUTE_ID *id; + XML_Bool isCdata; + const XML_Char *value; } DEFAULT_ATTRIBUTE; -typedef struct -{ - unsigned long version; - unsigned long hash; - const XML_Char *uriName; +typedef struct { + unsigned long version; + unsigned long hash; + const XML_Char *uriName; } NS_ATT; -typedef struct -{ - const XML_Char *name; - PREFIX *prefix; - const ATTRIBUTE_ID *idAtt; - int nDefaultAtts; - int allocDefaultAtts; - DEFAULT_ATTRIBUTE *defaultAtts; +typedef struct { + const XML_Char *name; + PREFIX *prefix; + const ATTRIBUTE_ID *idAtt; + int nDefaultAtts; + int allocDefaultAtts; + DEFAULT_ATTRIBUTE *defaultAtts; } ELEMENT_TYPE; -typedef struct -{ - HASH_TABLE generalEntities; - HASH_TABLE elementTypes; - HASH_TABLE attributeIds; - HASH_TABLE prefixes; - STRING_POOL pool; - STRING_POOL entityValuePool; - /* false once a parameter entity reference has been skipped */ - XML_Bool keepProcessing; - /* true once an internal or external PE reference has been encountered; - this includes the reference to an external subset */ - XML_Bool hasParamEntityRefs; - XML_Bool standalone; +typedef struct { + HASH_TABLE generalEntities; + HASH_TABLE elementTypes; + HASH_TABLE attributeIds; + HASH_TABLE prefixes; + STRING_POOL pool; + STRING_POOL entityValuePool; + /* false once a parameter entity reference has been skipped */ + XML_Bool keepProcessing; + /* true once an internal or external PE reference has been encountered; + this includes the reference to an external subset */ + XML_Bool hasParamEntityRefs; + XML_Bool standalone; #ifdef XML_DTD - /* indicates if external PE has been read */ - XML_Bool paramEntityRead; - HASH_TABLE paramEntities; + /* indicates if external PE has been read */ + XML_Bool paramEntityRead; + HASH_TABLE paramEntities; #endif /* XML_DTD */ - PREFIX defaultPrefix; - /* === scaffolding for building content model === */ - XML_Bool in_eldecl; - CONTENT_SCAFFOLD *scaffold; - unsigned contentStringLen; - unsigned scaffSize; - unsigned scaffCount; - int scaffLevel; - int *scaffIndex; + PREFIX defaultPrefix; + /* === scaffolding for building content model === */ + XML_Bool in_eldecl; + CONTENT_SCAFFOLD *scaffold; + unsigned contentStringLen; + unsigned scaffSize; + unsigned scaffCount; + int scaffLevel; + int *scaffIndex; } DTD; -typedef struct open_internal_entity -{ - const char *internalEventPtr; - const char *internalEventEndPtr; - struct open_internal_entity *next; - ENTITY *entity; - int startTagLevel; - XML_Bool betweenDecl; /* WFC: PE Between Declarations */ +typedef struct open_internal_entity { + const char *internalEventPtr; + const char *internalEventEndPtr; + struct open_internal_entity *next; + ENTITY *entity; + int startTagLevel; + XML_Bool betweenDecl; /* WFC: PE Between Declarations */ } OPEN_INTERNAL_ENTITY; typedef enum XML_Error PTRCALL Processor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr); + const char *start, + const char *end, + const char **endPtr); static Processor prologProcessor; static Processor prologInitProcessor; @@ -461,103 +444,102 @@ parserInit(XML_Parser parser, const XML_Char *encodingName); ? 0 \ : ((*((pool)->ptr)++ = c), 1)) -struct XML_ParserStruct -{ - /* The first member must be userData so that the XML_GetUserData - macro works. */ - void *m_userData; - void *m_handlerArg; - char *m_buffer; - const XML_Memory_Handling_Suite m_mem; - /* first character to be parsed */ - const char *m_bufferPtr; - /* past last character to be parsed */ - char *m_bufferEnd; - /* allocated end of buffer */ - const char *m_bufferLim; - long m_parseEndByteIndex; - const char *m_parseEndPtr; - XML_Char *m_dataBuf; - XML_Char *m_dataBufEnd; - XML_StartElementHandler m_startElementHandler; - XML_EndElementHandler m_endElementHandler; - XML_CharacterDataHandler m_characterDataHandler; - XML_ProcessingInstructionHandler m_processingInstructionHandler; - XML_CommentHandler m_commentHandler; - XML_StartCdataSectionHandler m_startCdataSectionHandler; - XML_EndCdataSectionHandler m_endCdataSectionHandler; - XML_DefaultHandler m_defaultHandler; - XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler; - XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler; - XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; - XML_NotationDeclHandler m_notationDeclHandler; - XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; - XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; - XML_NotStandaloneHandler m_notStandaloneHandler; - XML_ExternalEntityRefHandler m_externalEntityRefHandler; - XML_Parser m_externalEntityRefHandlerArg; - XML_SkippedEntityHandler m_skippedEntityHandler; - XML_UnknownEncodingHandler m_unknownEncodingHandler; - XML_ElementDeclHandler m_elementDeclHandler; - XML_AttlistDeclHandler m_attlistDeclHandler; - XML_EntityDeclHandler m_entityDeclHandler; - XML_XmlDeclHandler m_xmlDeclHandler; - const ENCODING *m_encoding; - INIT_ENCODING m_initEncoding; - const ENCODING *m_internalEncoding; - const XML_Char *m_protocolEncodingName; - XML_Bool m_ns; - XML_Bool m_ns_triplets; - void *m_unknownEncodingMem; - void *m_unknownEncodingData; - void *m_unknownEncodingHandlerData; - void (XMLCALL *m_unknownEncodingRelease)(void *); - PROLOG_STATE m_prologState; - Processor *m_processor; - enum XML_Error m_errorCode; - const char *m_eventPtr; - const char *m_eventEndPtr; - const char *m_positionPtr; - OPEN_INTERNAL_ENTITY *m_openInternalEntities; - OPEN_INTERNAL_ENTITY *m_freeInternalEntities; - XML_Bool m_defaultExpandInternalEntities; - int m_tagLevel; - ENTITY *m_declEntity; - const XML_Char *m_doctypeName; - const XML_Char *m_doctypeSysid; - const XML_Char *m_doctypePubid; - const XML_Char *m_declAttributeType; - const XML_Char *m_declNotationName; - const XML_Char *m_declNotationPublicId; - ELEMENT_TYPE *m_declElementType; - ATTRIBUTE_ID *m_declAttributeId; - XML_Bool m_declAttributeIsCdata; - XML_Bool m_declAttributeIsId; - DTD *m_dtd; - const XML_Char *m_curBase; - TAG *m_tagStack; - TAG *m_freeTagList; - BINDING *m_inheritedBindings; - BINDING *m_freeBindingList; - int m_attsSize; - int m_nSpecifiedAtts; - int m_idAttIndex; - ATTRIBUTE *m_atts; - NS_ATT *m_nsAtts; - unsigned long m_nsAttsVersion; - unsigned char m_nsAttsPower; - POSITION m_position; - STRING_POOL m_tempPool; - STRING_POOL m_temp2Pool; - char *m_groupConnector; - unsigned int m_groupSize; - XML_Char m_namespaceSeparator; - XML_Parser m_parentParser; - XML_ParsingStatus m_parsingStatus; +struct XML_ParserStruct { + /* The first member must be userData so that the XML_GetUserData + macro works. */ + void *m_userData; + void *m_handlerArg; + char *m_buffer; + const XML_Memory_Handling_Suite m_mem; + /* first character to be parsed */ + const char *m_bufferPtr; + /* past last character to be parsed */ + char *m_bufferEnd; + /* allocated end of buffer */ + const char *m_bufferLim; + long m_parseEndByteIndex; + const char *m_parseEndPtr; + XML_Char *m_dataBuf; + XML_Char *m_dataBufEnd; + XML_StartElementHandler m_startElementHandler; + XML_EndElementHandler m_endElementHandler; + XML_CharacterDataHandler m_characterDataHandler; + XML_ProcessingInstructionHandler m_processingInstructionHandler; + XML_CommentHandler m_commentHandler; + XML_StartCdataSectionHandler m_startCdataSectionHandler; + XML_EndCdataSectionHandler m_endCdataSectionHandler; + XML_DefaultHandler m_defaultHandler; + XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler; + XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler; + XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; + XML_NotationDeclHandler m_notationDeclHandler; + XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; + XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; + XML_NotStandaloneHandler m_notStandaloneHandler; + XML_ExternalEntityRefHandler m_externalEntityRefHandler; + XML_Parser m_externalEntityRefHandlerArg; + XML_SkippedEntityHandler m_skippedEntityHandler; + XML_UnknownEncodingHandler m_unknownEncodingHandler; + XML_ElementDeclHandler m_elementDeclHandler; + XML_AttlistDeclHandler m_attlistDeclHandler; + XML_EntityDeclHandler m_entityDeclHandler; + XML_XmlDeclHandler m_xmlDeclHandler; + const ENCODING *m_encoding; + INIT_ENCODING m_initEncoding; + const ENCODING *m_internalEncoding; + const XML_Char *m_protocolEncodingName; + XML_Bool m_ns; + XML_Bool m_ns_triplets; + void *m_unknownEncodingMem; + void *m_unknownEncodingData; + void *m_unknownEncodingHandlerData; + void (XMLCALL *m_unknownEncodingRelease)(void *); + PROLOG_STATE m_prologState; + Processor *m_processor; + enum XML_Error m_errorCode; + const char *m_eventPtr; + const char *m_eventEndPtr; + const char *m_positionPtr; + OPEN_INTERNAL_ENTITY *m_openInternalEntities; + OPEN_INTERNAL_ENTITY *m_freeInternalEntities; + XML_Bool m_defaultExpandInternalEntities; + int m_tagLevel; + ENTITY *m_declEntity; + const XML_Char *m_doctypeName; + const XML_Char *m_doctypeSysid; + const XML_Char *m_doctypePubid; + const XML_Char *m_declAttributeType; + const XML_Char *m_declNotationName; + const XML_Char *m_declNotationPublicId; + ELEMENT_TYPE *m_declElementType; + ATTRIBUTE_ID *m_declAttributeId; + XML_Bool m_declAttributeIsCdata; + XML_Bool m_declAttributeIsId; + DTD *m_dtd; + const XML_Char *m_curBase; + TAG *m_tagStack; + TAG *m_freeTagList; + BINDING *m_inheritedBindings; + BINDING *m_freeBindingList; + int m_attsSize; + int m_nSpecifiedAtts; + int m_idAttIndex; + ATTRIBUTE *m_atts; + NS_ATT *m_nsAtts; + unsigned long m_nsAttsVersion; + unsigned char m_nsAttsPower; + POSITION m_position; + STRING_POOL m_tempPool; + STRING_POOL m_temp2Pool; + char *m_groupConnector; + unsigned int m_groupSize; + XML_Char m_namespaceSeparator; + XML_Parser m_parentParser; + XML_ParsingStatus m_parsingStatus; #ifdef XML_DTD - XML_Bool m_isParamEntity; - XML_Bool m_useForeignDTD; - enum XML_ParamEntityParsing m_paramEntityParsing; + XML_Bool m_isParamEntity; + XML_Bool m_useForeignDTD; + enum XML_ParamEntityParsing m_paramEntityParsing; #endif }; @@ -670,23 +652,22 @@ struct XML_ParserStruct XML_Parser XMLCALL XML_ParserCreate(const XML_Char *encodingName) { - return XML_ParserCreate_MM(encodingName, NULL, NULL); + return XML_ParserCreate_MM(encodingName, NULL, NULL); } XML_Parser XMLCALL XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) { - XML_Char tmp[2]; - *tmp = nsSep; - return XML_ParserCreate_MM(encodingName, NULL, tmp); + XML_Char tmp[2]; + *tmp = nsSep; + return XML_ParserCreate_MM(encodingName, NULL, tmp); } -static const XML_Char implicitContext[] = -{ - 'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/', - 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/', - 'X', 'M', 'L', '/', '1', '9', '9', '8', '/', - 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0' +static const XML_Char implicitContext[] = { + 'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/', + 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/', + 'X', 'M', 'L', '/', '1', '9', '9', '8', '/', + 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0' }; XML_Parser XMLCALL @@ -694,19 +675,17 @@ XML_ParserCreate_MM(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep) { - XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL); - if (parser != NULL && ns) - { - /* implicit context only set for root parser, since child - parsers (i.e. external entity parsers) will inherit it - */ - if (!setContext(parser, implicitContext)) - { - XML_ParserFree(parser); - return NULL; - } + XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL); + if (parser != NULL && ns) { + /* implicit context only set for root parser, since child + parsers (i.e. external entity parsers) will inherit it + */ + if (!setContext(parser, implicitContext)) { + XML_ParserFree(parser); + return NULL; } - return parser; + } + return parser; } static XML_Parser @@ -715,181 +694,170 @@ parserCreate(const XML_Char *encodingName, const XML_Char *nameSep, DTD *dtd) { - XML_Parser parser; - - if (memsuite) - { - XML_Memory_Handling_Suite *mtemp; - parser = (XML_Parser) - memsuite->malloc_fcn(sizeof(struct XML_ParserStruct)); - if (parser != NULL) - { - mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); - mtemp->malloc_fcn = memsuite->malloc_fcn; - mtemp->realloc_fcn = memsuite->realloc_fcn; - mtemp->free_fcn = memsuite->free_fcn; - } - } - else - { - XML_Memory_Handling_Suite *mtemp; - parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct)); - if (parser != NULL) - { - mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); - mtemp->malloc_fcn = malloc; - mtemp->realloc_fcn = realloc; - mtemp->free_fcn = free; - } - } - - if (!parser) - return parser; + XML_Parser parser; + + if (memsuite) { + XML_Memory_Handling_Suite *mtemp; + parser = (XML_Parser) + memsuite->malloc_fcn(sizeof(struct XML_ParserStruct)); + if (parser != NULL) { + mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); + mtemp->malloc_fcn = memsuite->malloc_fcn; + mtemp->realloc_fcn = memsuite->realloc_fcn; + mtemp->free_fcn = memsuite->free_fcn; + } + } + else { + XML_Memory_Handling_Suite *mtemp; + parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct)); + if (parser != NULL) { + mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); + mtemp->malloc_fcn = malloc; + mtemp->realloc_fcn = realloc; + mtemp->free_fcn = free; + } + } + + if (!parser) + return parser; - buffer = NULL; - bufferLim = NULL; + buffer = NULL; + bufferLim = NULL; - attsSize = INIT_ATTS_SIZE; - atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE)); - if (atts == NULL) - { - FREE(parser); - return NULL; - } - dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); - if (dataBuf == NULL) - { - FREE(atts); - FREE(parser); - return NULL; - } - dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; + attsSize = INIT_ATTS_SIZE; + atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE)); + if (atts == NULL) { + FREE(parser); + return NULL; + } + dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); + if (dataBuf == NULL) { + FREE(atts); + FREE(parser); + return NULL; + } + dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; - if (dtd) - _dtd = dtd; - else - { - _dtd = dtdCreate(&parser->m_mem); - if (_dtd == NULL) - { - FREE(dataBuf); - FREE(atts); - FREE(parser); - return NULL; - } + if (dtd) + _dtd = dtd; + else { + _dtd = dtdCreate(&parser->m_mem); + if (_dtd == NULL) { + FREE(dataBuf); + FREE(atts); + FREE(parser); + return NULL; } + } - freeBindingList = NULL; - freeTagList = NULL; - freeInternalEntities = NULL; + freeBindingList = NULL; + freeTagList = NULL; + freeInternalEntities = NULL; - groupSize = 0; - groupConnector = NULL; + groupSize = 0; + groupConnector = NULL; - unknownEncodingHandler = NULL; - unknownEncodingHandlerData = NULL; + unknownEncodingHandler = NULL; + unknownEncodingHandlerData = NULL; - namespaceSeparator = '!'; - ns = XML_FALSE; - ns_triplets = XML_FALSE; + namespaceSeparator = '!'; + ns = XML_FALSE; + ns_triplets = XML_FALSE; - nsAtts = NULL; - nsAttsVersion = 0; - nsAttsPower = 0; + nsAtts = NULL; + nsAttsVersion = 0; + nsAttsPower = 0; - poolInit(&tempPool, &(parser->m_mem)); - poolInit(&temp2Pool, &(parser->m_mem)); - parserInit(parser, encodingName); + poolInit(&tempPool, &(parser->m_mem)); + poolInit(&temp2Pool, &(parser->m_mem)); + parserInit(parser, encodingName); - if (encodingName && !protocolEncodingName) - { - XML_ParserFree(parser); - return NULL; - } + if (encodingName && !protocolEncodingName) { + XML_ParserFree(parser); + return NULL; + } - if (nameSep) - { - ns = XML_TRUE; - internalEncoding = XmlGetInternalEncodingNS(); - namespaceSeparator = *nameSep; - } - else - { - internalEncoding = XmlGetInternalEncoding(); - } + if (nameSep) { + ns = XML_TRUE; + internalEncoding = XmlGetInternalEncodingNS(); + namespaceSeparator = *nameSep; + } + else { + internalEncoding = XmlGetInternalEncoding(); + } - return parser; + return parser; } static void parserInit(XML_Parser parser, const XML_Char *encodingName) { - processor = prologInitProcessor; - XmlPrologStateInit(&prologState); - protocolEncodingName = (encodingName != NULL - ? poolCopyString(&tempPool, encodingName) - : NULL); - curBase = NULL; - XmlInitEncoding(&initEncoding, &encoding, 0); - userData = NULL; - handlerArg = NULL; - startElementHandler = NULL; - endElementHandler = NULL; - characterDataHandler = NULL; - processingInstructionHandler = NULL; - commentHandler = NULL; - startCdataSectionHandler = NULL; - endCdataSectionHandler = NULL; - defaultHandler = NULL; - startDoctypeDeclHandler = NULL; - endDoctypeDeclHandler = NULL; - unparsedEntityDeclHandler = NULL; - notationDeclHandler = NULL; - startNamespaceDeclHandler = NULL; - endNamespaceDeclHandler = NULL; - notStandaloneHandler = NULL; - externalEntityRefHandler = NULL; - externalEntityRefHandlerArg = parser; - skippedEntityHandler = NULL; - elementDeclHandler = NULL; - attlistDeclHandler = NULL; - entityDeclHandler = NULL; - xmlDeclHandler = NULL; - bufferPtr = buffer; - bufferEnd = buffer; - parseEndByteIndex = 0; - parseEndPtr = NULL; - declElementType = NULL; - declAttributeId = NULL; - declEntity = NULL; - doctypeName = NULL; - doctypeSysid = NULL; - doctypePubid = NULL; - declAttributeType = NULL; - declNotationName = NULL; - declNotationPublicId = NULL; - declAttributeIsCdata = XML_FALSE; - declAttributeIsId = XML_FALSE; - memset(&position, 0, sizeof(POSITION)); - errorCode = XML_ERROR_NONE; - eventPtr = NULL; - eventEndPtr = NULL; - positionPtr = NULL; - openInternalEntities = NULL; - defaultExpandInternalEntities = XML_TRUE; - tagLevel = 0; - tagStack = NULL; - inheritedBindings = NULL; - nSpecifiedAtts = 0; - unknownEncodingMem = NULL; - unknownEncodingRelease = NULL; - unknownEncodingData = NULL; - parentParser = NULL; - parsing = XML_INITIALIZED; + processor = prologInitProcessor; + XmlPrologStateInit(&prologState); + protocolEncodingName = (encodingName != NULL + ? poolCopyString(&tempPool, encodingName) + : NULL); + curBase = NULL; + XmlInitEncoding(&initEncoding, &encoding, 0); + userData = NULL; + handlerArg = NULL; + startElementHandler = NULL; + endElementHandler = NULL; + characterDataHandler = NULL; + processingInstructionHandler = NULL; + commentHandler = NULL; + startCdataSectionHandler = NULL; + endCdataSectionHandler = NULL; + defaultHandler = NULL; + startDoctypeDeclHandler = NULL; + endDoctypeDeclHandler = NULL; + unparsedEntityDeclHandler = NULL; + notationDeclHandler = NULL; + startNamespaceDeclHandler = NULL; + endNamespaceDeclHandler = NULL; + notStandaloneHandler = NULL; + externalEntityRefHandler = NULL; + externalEntityRefHandlerArg = parser; + skippedEntityHandler = NULL; + elementDeclHandler = NULL; + attlistDeclHandler = NULL; + entityDeclHandler = NULL; + xmlDeclHandler = NULL; + bufferPtr = buffer; + bufferEnd = buffer; + parseEndByteIndex = 0; + parseEndPtr = NULL; + declElementType = NULL; + declAttributeId = NULL; + declEntity = NULL; + doctypeName = NULL; + doctypeSysid = NULL; + doctypePubid = NULL; + declAttributeType = NULL; + declNotationName = NULL; + declNotationPublicId = NULL; + declAttributeIsCdata = XML_FALSE; + declAttributeIsId = XML_FALSE; + memset(&position, 0, sizeof(POSITION)); + errorCode = XML_ERROR_NONE; + eventPtr = NULL; + eventEndPtr = NULL; + positionPtr = NULL; + openInternalEntities = NULL; + defaultExpandInternalEntities = XML_TRUE; + tagLevel = 0; + tagStack = NULL; + inheritedBindings = NULL; + nSpecifiedAtts = 0; + unknownEncodingMem = NULL; + unknownEncodingRelease = NULL; + unknownEncodingData = NULL; + parentParser = NULL; + parsing = XML_INITIALIZED; #ifdef XML_DTD - isParamEntity = XML_FALSE; - useForeignDTD = XML_FALSE; - paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; + isParamEntity = XML_FALSE; + useForeignDTD = XML_FALSE; + paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; #endif } @@ -897,71 +865,67 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) static void FASTCALL moveToFreeBindingList(XML_Parser parser, BINDING *bindings) { - while (bindings) - { - BINDING *b = bindings; - bindings = bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - } + while (bindings) { + BINDING *b = bindings; + bindings = bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + } } XML_Bool XMLCALL XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) { - TAG *tStk; - OPEN_INTERNAL_ENTITY *openEntityList; - if (parentParser) - return XML_FALSE; - /* move tagStack to freeTagList */ - tStk = tagStack; - while (tStk) - { - TAG *tag = tStk; - tStk = tStk->parent; - tag->parent = freeTagList; - moveToFreeBindingList(parser, tag->bindings); - tag->bindings = NULL; - freeTagList = tag; - } - /* move openInternalEntities to freeInternalEntities */ - openEntityList = openInternalEntities; - while (openEntityList) - { - OPEN_INTERNAL_ENTITY *openEntity = openEntityList; - openEntityList = openEntity->next; - openEntity->next = freeInternalEntities; - freeInternalEntities = openEntity; - } - moveToFreeBindingList(parser, inheritedBindings); - FREE(unknownEncodingMem); - if (unknownEncodingRelease) - unknownEncodingRelease(unknownEncodingData); - poolClear(&tempPool); - poolClear(&temp2Pool); - parserInit(parser, encodingName); - dtdReset(_dtd, &parser->m_mem); - return setContext(parser, implicitContext); + TAG *tStk; + OPEN_INTERNAL_ENTITY *openEntityList; + if (parentParser) + return XML_FALSE; + /* move tagStack to freeTagList */ + tStk = tagStack; + while (tStk) { + TAG *tag = tStk; + tStk = tStk->parent; + tag->parent = freeTagList; + moveToFreeBindingList(parser, tag->bindings); + tag->bindings = NULL; + freeTagList = tag; + } + /* move openInternalEntities to freeInternalEntities */ + openEntityList = openInternalEntities; + while (openEntityList) { + OPEN_INTERNAL_ENTITY *openEntity = openEntityList; + openEntityList = openEntity->next; + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } + moveToFreeBindingList(parser, inheritedBindings); + FREE(unknownEncodingMem); + if (unknownEncodingRelease) + unknownEncodingRelease(unknownEncodingData); + poolClear(&tempPool); + poolClear(&temp2Pool); + parserInit(parser, encodingName); + dtdReset(_dtd, &parser->m_mem); + return setContext(parser, implicitContext); } enum XML_Status XMLCALL XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) { - /* Block after XML_Parse()/XML_ParseBuffer() has been called. - XXX There's no way for the caller to determine which of the - XXX possible error cases caused the XML_STATUS_ERROR return. - */ - if (parsing == XML_PARSING || parsing == XML_SUSPENDED) - return XML_STATUS_ERROR; - if (encodingName == NULL) - protocolEncodingName = NULL; - else - { - protocolEncodingName = poolCopyString(&tempPool, encodingName); - if (!protocolEncodingName) - return XML_STATUS_ERROR; - } - return XML_STATUS_OK; + /* Block after XML_Parse()/XML_ParseBuffer() has been called. + XXX There's no way for the caller to determine which of the + XXX possible error cases caused the XML_STATUS_ERROR return. + */ + if (parsing == XML_PARSING || parsing == XML_SUSPENDED) + return XML_STATUS_ERROR; + if (encodingName == NULL) + protocolEncodingName = NULL; + else { + protocolEncodingName = poolCopyString(&tempPool, encodingName); + if (!protocolEncodingName) + return XML_STATUS_ERROR; + } + return XML_STATUS_OK; } XML_Parser XMLCALL @@ -969,285 +933,274 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, const XML_Char *encodingName) { - XML_Parser parser = oldParser; - DTD *newDtd = NULL; - DTD *oldDtd = _dtd; - XML_StartElementHandler oldStartElementHandler = startElementHandler; - XML_EndElementHandler oldEndElementHandler = endElementHandler; - XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; - XML_ProcessingInstructionHandler oldProcessingInstructionHandler - = processingInstructionHandler; - XML_CommentHandler oldCommentHandler = commentHandler; - XML_StartCdataSectionHandler oldStartCdataSectionHandler - = startCdataSectionHandler; - XML_EndCdataSectionHandler oldEndCdataSectionHandler - = endCdataSectionHandler; - XML_DefaultHandler oldDefaultHandler = defaultHandler; - XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler - = unparsedEntityDeclHandler; - XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; - XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler - = startNamespaceDeclHandler; - XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler - = endNamespaceDeclHandler; - XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; - XML_ExternalEntityRefHandler oldExternalEntityRefHandler - = externalEntityRefHandler; - XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler; - XML_UnknownEncodingHandler oldUnknownEncodingHandler - = unknownEncodingHandler; - XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler; - XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler; - XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler; - XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler; - ELEMENT_TYPE * oldDeclElementType = declElementType; - - void *oldUserData = userData; - void *oldHandlerArg = handlerArg; - XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities; - XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; + XML_Parser parser = oldParser; + DTD *newDtd = NULL; + DTD *oldDtd = _dtd; + XML_StartElementHandler oldStartElementHandler = startElementHandler; + XML_EndElementHandler oldEndElementHandler = endElementHandler; + XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; + XML_ProcessingInstructionHandler oldProcessingInstructionHandler + = processingInstructionHandler; + XML_CommentHandler oldCommentHandler = commentHandler; + XML_StartCdataSectionHandler oldStartCdataSectionHandler + = startCdataSectionHandler; + XML_EndCdataSectionHandler oldEndCdataSectionHandler + = endCdataSectionHandler; + XML_DefaultHandler oldDefaultHandler = defaultHandler; + XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler + = unparsedEntityDeclHandler; + XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; + XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler + = startNamespaceDeclHandler; + XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler + = endNamespaceDeclHandler; + XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; + XML_ExternalEntityRefHandler oldExternalEntityRefHandler + = externalEntityRefHandler; + XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler; + XML_UnknownEncodingHandler oldUnknownEncodingHandler + = unknownEncodingHandler; + XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler; + XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler; + XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler; + XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler; + ELEMENT_TYPE * oldDeclElementType = declElementType; + + void *oldUserData = userData; + void *oldHandlerArg = handlerArg; + XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities; + XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; #ifdef XML_DTD - enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing; - int oldInEntityValue = prologState.inEntityValue; + enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing; + int oldInEntityValue = prologState.inEntityValue; #endif - XML_Bool oldns_triplets = ns_triplets; + XML_Bool oldns_triplets = ns_triplets; #ifdef XML_DTD - if (!context) - newDtd = oldDtd; + if (!context) + newDtd = oldDtd; #endif /* XML_DTD */ - /* Note that the magical uses of the pre-processor to make field - access look more like C++ require that `parser' be overwritten - here. This makes this function more painful to follow than it - would be otherwise. - */ - if (ns) - { - XML_Char tmp[2]; - *tmp = namespaceSeparator; - parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd); - } - else - { - parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd); - } - - if (!parser) - return NULL; + /* Note that the magical uses of the pre-processor to make field + access look more like C++ require that `parser' be overwritten + here. This makes this function more painful to follow than it + would be otherwise. + */ + if (ns) { + XML_Char tmp[2]; + *tmp = namespaceSeparator; + parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd); + } + else { + parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd); + } + + if (!parser) + return NULL; - startElementHandler = oldStartElementHandler; - endElementHandler = oldEndElementHandler; - characterDataHandler = oldCharacterDataHandler; - processingInstructionHandler = oldProcessingInstructionHandler; - commentHandler = oldCommentHandler; - startCdataSectionHandler = oldStartCdataSectionHandler; - endCdataSectionHandler = oldEndCdataSectionHandler; - defaultHandler = oldDefaultHandler; - unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler; - notationDeclHandler = oldNotationDeclHandler; - startNamespaceDeclHandler = oldStartNamespaceDeclHandler; - endNamespaceDeclHandler = oldEndNamespaceDeclHandler; - notStandaloneHandler = oldNotStandaloneHandler; - externalEntityRefHandler = oldExternalEntityRefHandler; - skippedEntityHandler = oldSkippedEntityHandler; - unknownEncodingHandler = oldUnknownEncodingHandler; - elementDeclHandler = oldElementDeclHandler; - attlistDeclHandler = oldAttlistDeclHandler; - entityDeclHandler = oldEntityDeclHandler; - xmlDeclHandler = oldXmlDeclHandler; - declElementType = oldDeclElementType; - userData = oldUserData; - if (oldUserData == oldHandlerArg) - handlerArg = userData; - else - handlerArg = parser; - if (oldExternalEntityRefHandlerArg != oldParser) - externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; - defaultExpandInternalEntities = oldDefaultExpandInternalEntities; - ns_triplets = oldns_triplets; - parentParser = oldParser; + startElementHandler = oldStartElementHandler; + endElementHandler = oldEndElementHandler; + characterDataHandler = oldCharacterDataHandler; + processingInstructionHandler = oldProcessingInstructionHandler; + commentHandler = oldCommentHandler; + startCdataSectionHandler = oldStartCdataSectionHandler; + endCdataSectionHandler = oldEndCdataSectionHandler; + defaultHandler = oldDefaultHandler; + unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler; + notationDeclHandler = oldNotationDeclHandler; + startNamespaceDeclHandler = oldStartNamespaceDeclHandler; + endNamespaceDeclHandler = oldEndNamespaceDeclHandler; + notStandaloneHandler = oldNotStandaloneHandler; + externalEntityRefHandler = oldExternalEntityRefHandler; + skippedEntityHandler = oldSkippedEntityHandler; + unknownEncodingHandler = oldUnknownEncodingHandler; + elementDeclHandler = oldElementDeclHandler; + attlistDeclHandler = oldAttlistDeclHandler; + entityDeclHandler = oldEntityDeclHandler; + xmlDeclHandler = oldXmlDeclHandler; + declElementType = oldDeclElementType; + userData = oldUserData; + if (oldUserData == oldHandlerArg) + handlerArg = userData; + else + handlerArg = parser; + if (oldExternalEntityRefHandlerArg != oldParser) + externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; + defaultExpandInternalEntities = oldDefaultExpandInternalEntities; + ns_triplets = oldns_triplets; + parentParser = oldParser; #ifdef XML_DTD - paramEntityParsing = oldParamEntityParsing; - prologState.inEntityValue = oldInEntityValue; - if (context) - { + paramEntityParsing = oldParamEntityParsing; + prologState.inEntityValue = oldInEntityValue; + if (context) { #endif /* XML_DTD */ - if (!dtdCopy(_dtd, oldDtd, &parser->m_mem) - || !setContext(parser, context)) - { - XML_ParserFree(parser); - return NULL; - } - processor = externalEntityInitProcessor; -#ifdef XML_DTD - } - else - { - /* The DTD instance referenced by _dtd is shared between the document's - root parser and external PE parsers, therefore one does not need to - call setContext. In addition, one also *must* not call setContext, - because this would overwrite existing prefix->binding pointers in - _dtd with ones that get destroyed with the external PE parser. - This would leave those prefixes with dangling pointers. - */ - isParamEntity = XML_TRUE; - XmlPrologStateInitExternalEntity(&prologState); - processor = externalParEntInitProcessor; + if (!dtdCopy(_dtd, oldDtd, &parser->m_mem) + || !setContext(parser, context)) { + XML_ParserFree(parser); + return NULL; } + processor = externalEntityInitProcessor; +#ifdef XML_DTD + } + else { + /* The DTD instance referenced by _dtd is shared between the document's + root parser and external PE parsers, therefore one does not need to + call setContext. In addition, one also *must* not call setContext, + because this would overwrite existing prefix->binding pointers in + _dtd with ones that get destroyed with the external PE parser. + This would leave those prefixes with dangling pointers. + */ + isParamEntity = XML_TRUE; + XmlPrologStateInitExternalEntity(&prologState); + processor = externalParEntInitProcessor; + } #endif /* XML_DTD */ - return parser; + return parser; } static void FASTCALL destroyBindings(BINDING *bindings, XML_Parser parser) { - for (;;) - { - BINDING *b = bindings; - if (!b) - break; - bindings = b->nextTagBinding; - FREE(b->uri); - FREE(b); - } + for (;;) { + BINDING *b = bindings; + if (!b) + break; + bindings = b->nextTagBinding; + FREE(b->uri); + FREE(b); + } } void XMLCALL XML_ParserFree(XML_Parser parser) { - TAG *tagList; - OPEN_INTERNAL_ENTITY *entityList; - if (parser == NULL) - return; - /* free tagStack and freeTagList */ - tagList = tagStack; - for (;;) - { - TAG *p; - if (tagList == NULL) - { - if (freeTagList == NULL) - break; - tagList = freeTagList; - freeTagList = NULL; - } - p = tagList; - tagList = tagList->parent; - FREE(p->buf); - destroyBindings(p->bindings, parser); - FREE(p); - } - /* free openInternalEntities and freeInternalEntities */ - entityList = openInternalEntities; - for (;;) - { - OPEN_INTERNAL_ENTITY *openEntity; - if (entityList == NULL) - { - if (freeInternalEntities == NULL) - break; - entityList = freeInternalEntities; - freeInternalEntities = NULL; - } - openEntity = entityList; - entityList = entityList->next; - FREE(openEntity); - } - - destroyBindings(freeBindingList, parser); - destroyBindings(inheritedBindings, parser); - poolDestroy(&tempPool); - poolDestroy(&temp2Pool); + TAG *tagList; + OPEN_INTERNAL_ENTITY *entityList; + if (parser == NULL) + return; + /* free tagStack and freeTagList */ + tagList = tagStack; + for (;;) { + TAG *p; + if (tagList == NULL) { + if (freeTagList == NULL) + break; + tagList = freeTagList; + freeTagList = NULL; + } + p = tagList; + tagList = tagList->parent; + FREE(p->buf); + destroyBindings(p->bindings, parser); + FREE(p); + } + /* free openInternalEntities and freeInternalEntities */ + entityList = openInternalEntities; + for (;;) { + OPEN_INTERNAL_ENTITY *openEntity; + if (entityList == NULL) { + if (freeInternalEntities == NULL) + break; + entityList = freeInternalEntities; + freeInternalEntities = NULL; + } + openEntity = entityList; + entityList = entityList->next; + FREE(openEntity); + } + + destroyBindings(freeBindingList, parser); + destroyBindings(inheritedBindings, parser); + poolDestroy(&tempPool); + poolDestroy(&temp2Pool); #ifdef XML_DTD - /* external parameter entity parsers share the DTD structure - parser->m_dtd with the root parser, so we must not destroy it - */ - if (!isParamEntity && _dtd) + /* external parameter entity parsers share the DTD structure + parser->m_dtd with the root parser, so we must not destroy it + */ + if (!isParamEntity && _dtd) #else - if (_dtd) + if (_dtd) #endif /* XML_DTD */ - dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem); - FREE((void *)atts); - FREE(groupConnector); - FREE(buffer); - FREE(dataBuf); - FREE(nsAtts); - FREE(unknownEncodingMem); - if (unknownEncodingRelease) - unknownEncodingRelease(unknownEncodingData); - FREE(parser); + dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem); + FREE((void *)atts); + FREE(groupConnector); + FREE(buffer); + FREE(dataBuf); + FREE(nsAtts); + FREE(unknownEncodingMem); + if (unknownEncodingRelease) + unknownEncodingRelease(unknownEncodingData); + FREE(parser); } void XMLCALL XML_UseParserAsHandlerArg(XML_Parser parser) { - handlerArg = parser; + handlerArg = parser; } enum XML_Error XMLCALL XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) { #ifdef XML_DTD - /* block after XML_Parse()/XML_ParseBuffer() has been called */ - if (parsing == XML_PARSING || parsing == XML_SUSPENDED) - return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING; - useForeignDTD = useDTD; - return XML_ERROR_NONE; + /* block after XML_Parse()/XML_ParseBuffer() has been called */ + if (parsing == XML_PARSING || parsing == XML_SUSPENDED) + return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING; + useForeignDTD = useDTD; + return XML_ERROR_NONE; #else - return XML_ERROR_FEATURE_REQUIRES_XML_DTD; + return XML_ERROR_FEATURE_REQUIRES_XML_DTD; #endif } void XMLCALL XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) { - /* block after XML_Parse()/XML_ParseBuffer() has been called */ - if (parsing == XML_PARSING || parsing == XML_SUSPENDED) - return; - ns_triplets = do_nst ? XML_TRUE : XML_FALSE; + /* block after XML_Parse()/XML_ParseBuffer() has been called */ + if (parsing == XML_PARSING || parsing == XML_SUSPENDED) + return; + ns_triplets = do_nst ? XML_TRUE : XML_FALSE; } void XMLCALL XML_SetUserData(XML_Parser parser, void *p) { - if (handlerArg == userData) - handlerArg = userData = p; - else - userData = p; + if (handlerArg == userData) + handlerArg = userData = p; + else + userData = p; } enum XML_Status XMLCALL XML_SetBase(XML_Parser parser, const XML_Char *p) { - if (p) - { - p = poolCopyString(&_dtd->pool, p); - if (!p) - return XML_STATUS_ERROR; - curBase = p; - } - else - curBase = NULL; - return XML_STATUS_OK; + if (p) { + p = poolCopyString(&_dtd->pool, p); + if (!p) + return XML_STATUS_ERROR; + curBase = p; + } + else + curBase = NULL; + return XML_STATUS_OK; } const XML_Char * XMLCALL XML_GetBase(XML_Parser parser) { - return curBase; + return curBase; } int XMLCALL XML_GetSpecifiedAttributeCount(XML_Parser parser) { - return nSpecifiedAtts; + return nSpecifiedAtts; } int XMLCALL XML_GetIdAttributeIndex(XML_Parser parser) { - return idAttIndex; + return idAttIndex; } void XMLCALL @@ -1255,43 +1208,41 @@ XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end) { - startElementHandler = start; - endElementHandler = end; + startElementHandler = start; + endElementHandler = end; } void XMLCALL XML_SetStartElementHandler(XML_Parser parser, - XML_StartElementHandler start) -{ - startElementHandler = start; + XML_StartElementHandler start) { + startElementHandler = start; } void XMLCALL XML_SetEndElementHandler(XML_Parser parser, - XML_EndElementHandler end) -{ - endElementHandler = end; + XML_EndElementHandler end) { + endElementHandler = end; } void XMLCALL XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler) { - characterDataHandler = handler; + characterDataHandler = handler; } void XMLCALL XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler handler) { - processingInstructionHandler = handler; + processingInstructionHandler = handler; } void XMLCALL XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) { - commentHandler = handler; + commentHandler = handler; } void XMLCALL @@ -1299,38 +1250,36 @@ XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end) { - startCdataSectionHandler = start; - endCdataSectionHandler = end; + startCdataSectionHandler = start; + endCdataSectionHandler = end; } void XMLCALL XML_SetStartCdataSectionHandler(XML_Parser parser, - XML_StartCdataSectionHandler start) -{ - startCdataSectionHandler = start; + XML_StartCdataSectionHandler start) { + startCdataSectionHandler = start; } void XMLCALL XML_SetEndCdataSectionHandler(XML_Parser parser, - XML_EndCdataSectionHandler end) -{ - endCdataSectionHandler = end; + XML_EndCdataSectionHandler end) { + endCdataSectionHandler = end; } void XMLCALL XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler) { - defaultHandler = handler; - defaultExpandInternalEntities = XML_FALSE; + defaultHandler = handler; + defaultExpandInternalEntities = XML_FALSE; } void XMLCALL XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler) { - defaultHandler = handler; - defaultExpandInternalEntities = XML_TRUE; + defaultHandler = handler; + defaultExpandInternalEntities = XML_TRUE; } void XMLCALL @@ -1338,36 +1287,34 @@ XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end) { - startDoctypeDeclHandler = start; - endDoctypeDeclHandler = end; + startDoctypeDeclHandler = start; + endDoctypeDeclHandler = end; } void XMLCALL XML_SetStartDoctypeDeclHandler(XML_Parser parser, - XML_StartDoctypeDeclHandler start) -{ - startDoctypeDeclHandler = start; + XML_StartDoctypeDeclHandler start) { + startDoctypeDeclHandler = start; } void XMLCALL XML_SetEndDoctypeDeclHandler(XML_Parser parser, - XML_EndDoctypeDeclHandler end) -{ - endDoctypeDeclHandler = end; + XML_EndDoctypeDeclHandler end) { + endDoctypeDeclHandler = end; } void XMLCALL XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler) { - unparsedEntityDeclHandler = handler; + unparsedEntityDeclHandler = handler; } void XMLCALL XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) { - notationDeclHandler = handler; + notationDeclHandler = handler; } void XMLCALL @@ -1375,52 +1322,50 @@ XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end) { - startNamespaceDeclHandler = start; - endNamespaceDeclHandler = end; + startNamespaceDeclHandler = start; + endNamespaceDeclHandler = end; } void XMLCALL XML_SetStartNamespaceDeclHandler(XML_Parser parser, - XML_StartNamespaceDeclHandler start) -{ - startNamespaceDeclHandler = start; + XML_StartNamespaceDeclHandler start) { + startNamespaceDeclHandler = start; } void XMLCALL XML_SetEndNamespaceDeclHandler(XML_Parser parser, - XML_EndNamespaceDeclHandler end) -{ - endNamespaceDeclHandler = end; + XML_EndNamespaceDeclHandler end) { + endNamespaceDeclHandler = end; } void XMLCALL XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler) { - notStandaloneHandler = handler; + notStandaloneHandler = handler; } void XMLCALL XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler) { - externalEntityRefHandler = handler; + externalEntityRefHandler = handler; } void XMLCALL XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) { - if (arg) - externalEntityRefHandlerArg = (XML_Parser)arg; - else - externalEntityRefHandlerArg = parser; + if (arg) + externalEntityRefHandlerArg = (XML_Parser)arg; + else + externalEntityRefHandlerArg = parser; } void XMLCALL XML_SetSkippedEntityHandler(XML_Parser parser, XML_SkippedEntityHandler handler) { - skippedEntityHandler = handler; + skippedEntityHandler = handler; } void XMLCALL @@ -1428,579 +1373,530 @@ XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *data) { - unknownEncodingHandler = handler; - unknownEncodingHandlerData = data; + unknownEncodingHandler = handler; + unknownEncodingHandlerData = data; } void XMLCALL XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl) { - elementDeclHandler = eldecl; + elementDeclHandler = eldecl; } void XMLCALL XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl) { - attlistDeclHandler = attdecl; + attlistDeclHandler = attdecl; } void XMLCALL XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler) { - entityDeclHandler = handler; + entityDeclHandler = handler; } void XMLCALL XML_SetXmlDeclHandler(XML_Parser parser, - XML_XmlDeclHandler handler) -{ - xmlDeclHandler = handler; + XML_XmlDeclHandler handler) { + xmlDeclHandler = handler; } int XMLCALL XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing peParsing) { - /* block after XML_Parse()/XML_ParseBuffer() has been called */ - if (parsing == XML_PARSING || parsing == XML_SUSPENDED) - return 0; + /* block after XML_Parse()/XML_ParseBuffer() has been called */ + if (parsing == XML_PARSING || parsing == XML_SUSPENDED) + return 0; #ifdef XML_DTD - paramEntityParsing = peParsing; - return 1; + paramEntityParsing = peParsing; + return 1; #else - return peParsing == XML_PARAM_ENTITY_PARSING_NEVER; + return peParsing == XML_PARAM_ENTITY_PARSING_NEVER; #endif } enum XML_Status XMLCALL XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) { - switch (parsing) - { - case XML_SUSPENDED: - errorCode = XML_ERROR_SUSPENDED; - return XML_STATUS_ERROR; - case XML_FINISHED: - errorCode = XML_ERROR_FINISHED; - return XML_STATUS_ERROR; - default: - parsing = XML_PARSING; - } + switch (parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + default: + parsing = XML_PARSING; + } - if (len == 0) - { - finalBuffer = (XML_Bool)isFinal; - if (!isFinal) - return XML_STATUS_OK; - positionPtr = bufferPtr; - parseEndPtr = bufferEnd; + if (len == 0) { + finalBuffer = (XML_Bool)isFinal; + if (!isFinal) + return XML_STATUS_OK; + positionPtr = bufferPtr; + parseEndPtr = bufferEnd; - /* If data are left over from last buffer, and we now know that these - data are the final chunk of input, then we have to check them again - to detect errors based on this information. - */ - errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); + /* If data are left over from last buffer, and we now know that these + data are the final chunk of input, then we have to check them again + to detect errors based on this information. + */ + errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); - if (errorCode == XML_ERROR_NONE) - { - switch (parsing) - { - case XML_SUSPENDED: - XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); - positionPtr = bufferPtr; - return XML_STATUS_SUSPENDED; - case XML_INITIALIZED: - case XML_PARSING: - parsing = XML_FINISHED; - /* fall through */ - default: - return XML_STATUS_OK; - } - } - eventEndPtr = eventPtr; - processor = errorProcessor; - return XML_STATUS_ERROR; - } + if (errorCode == XML_ERROR_NONE) { + switch (parsing) { + case XML_SUSPENDED: + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return XML_STATUS_SUSPENDED; + case XML_INITIALIZED: + case XML_PARSING: + parsing = XML_FINISHED; + /* fall through */ + default: + return XML_STATUS_OK; + } + } + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } #ifndef XML_CONTEXT_BYTES - else if (bufferPtr == bufferEnd) - { - const char *end; - int nLeftOver; - enum XML_Error result; - parseEndByteIndex += len; - positionPtr = s; - finalBuffer = (XML_Bool)isFinal; + else if (bufferPtr == bufferEnd) { + const char *end; + int nLeftOver; + enum XML_Error result; + parseEndByteIndex += len; + positionPtr = s; + finalBuffer = (XML_Bool)isFinal; - errorCode = processor(parser, s, parseEndPtr = s + len, &end); + errorCode = processor(parser, s, parseEndPtr = s + len, &end); - if (errorCode != XML_ERROR_NONE) - { - eventEndPtr = eventPtr; - processor = errorProcessor; - return XML_STATUS_ERROR; - } - else - { - switch (parsing) - { - case XML_SUSPENDED: - result = XML_STATUS_SUSPENDED; - break; - case XML_INITIALIZED: - case XML_PARSING: - result = XML_STATUS_OK; - if (isFinal) - { - parsing = XML_FINISHED; - return result; - } - } + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + else { + switch (parsing) { + case XML_SUSPENDED: + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED: + case XML_PARSING: + result = XML_STATUS_OK; + if (isFinal) { + parsing = XML_FINISHED; + return result; } + } + } - XmlUpdatePosition(encoding, positionPtr, end, &position); - positionPtr = end; - nLeftOver = s + len - end; - if (nLeftOver) - { - if (buffer == NULL || nLeftOver > bufferLim - buffer) - { - /* FIXME avoid integer overflow */ - char *temp; - temp = (buffer == NULL - ? (char *)MALLOC(len * 2) - : (char *)REALLOC(buffer, len * 2)); - if (temp == NULL) - { - errorCode = XML_ERROR_NO_MEMORY; - return XML_STATUS_ERROR; - } - buffer = temp; - if (!buffer) - { - errorCode = XML_ERROR_NO_MEMORY; - eventPtr = eventEndPtr = NULL; - processor = errorProcessor; - return XML_STATUS_ERROR; - } - bufferLim = buffer + len * 2; - } - memcpy(buffer, end, nLeftOver); - bufferPtr = buffer; - bufferEnd = buffer + nLeftOver; + XmlUpdatePosition(encoding, positionPtr, end, &position); + positionPtr = end; + nLeftOver = s + len - end; + if (nLeftOver) { + if (buffer == NULL || nLeftOver > bufferLim - buffer) { + /* FIXME avoid integer overflow */ + char *temp; + temp = (buffer == NULL + ? (char *)MALLOC(len * 2) + : (char *)REALLOC(buffer, len * 2)); + if (temp == NULL) { + errorCode = XML_ERROR_NO_MEMORY; + return XML_STATUS_ERROR; } - return result; + buffer = temp; + if (!buffer) { + errorCode = XML_ERROR_NO_MEMORY; + eventPtr = eventEndPtr = NULL; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + bufferLim = buffer + len * 2; + } + memcpy(buffer, end, nLeftOver); + bufferPtr = buffer; + bufferEnd = buffer + nLeftOver; } + return result; + } #endif /* not defined XML_CONTEXT_BYTES */ - else - { - void *buff = XML_GetBuffer(parser, len); - if (buff == NULL) - return XML_STATUS_ERROR; - else - { - memcpy(buff, s, len); - return XML_ParseBuffer(parser, len, isFinal); - } + else { + void *buff = XML_GetBuffer(parser, len); + if (buff == NULL) + return XML_STATUS_ERROR; + else { + memcpy(buff, s, len); + return XML_ParseBuffer(parser, len, isFinal); } + } } enum XML_Status XMLCALL XML_ParseBuffer(XML_Parser parser, int len, int isFinal) { - const char *start; - enum XML_Error result = XML_STATUS_OK; - - switch (parsing) - { + const char *start; + enum XML_Error result = XML_STATUS_OK; + + switch (parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + default: + parsing = XML_PARSING; + } + + start = bufferPtr; + positionPtr = start; + bufferEnd += len; + parseEndPtr = bufferEnd; + parseEndByteIndex += len; + finalBuffer = (XML_Bool)isFinal; + + errorCode = processor(parser, start, parseEndPtr, &bufferPtr); + + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + else { + switch (parsing) { case XML_SUSPENDED: - errorCode = XML_ERROR_SUSPENDED; - return XML_STATUS_ERROR; - case XML_FINISHED: - errorCode = XML_ERROR_FINISHED; - return XML_STATUS_ERROR; - default: - parsing = XML_PARSING; - } - - start = bufferPtr; - positionPtr = start; - bufferEnd += len; - parseEndPtr = bufferEnd; - parseEndByteIndex += len; - finalBuffer = (XML_Bool)isFinal; - - errorCode = processor(parser, start, parseEndPtr, &bufferPtr); - - if (errorCode != XML_ERROR_NONE) - { - eventEndPtr = eventPtr; - processor = errorProcessor; - return XML_STATUS_ERROR; - } - else - { - switch (parsing) - { - case XML_SUSPENDED: - result = XML_STATUS_SUSPENDED; - break; - case XML_INITIALIZED: - case XML_PARSING: - if (isFinal) - { - parsing = XML_FINISHED; - return result; - } - default: ; /* should not happen */ - } + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED: + case XML_PARSING: + if (isFinal) { + parsing = XML_FINISHED; + return result; + } + default: ; /* should not happen */ } + } - XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); - positionPtr = bufferPtr; - return result; + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return result; } void * XMLCALL XML_GetBuffer(XML_Parser parser, int len) { - switch (parsing) - { - case XML_SUSPENDED: - errorCode = XML_ERROR_SUSPENDED; - return NULL; - case XML_FINISHED: - errorCode = XML_ERROR_FINISHED; - return NULL; - default: - ; - } + switch (parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return NULL; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return NULL; + default: ; + } - if (len > bufferLim - bufferEnd) - { - /* FIXME avoid integer overflow */ - int neededSize = len + (bufferEnd - bufferPtr); + if (len > bufferLim - bufferEnd) { + /* FIXME avoid integer overflow */ + int neededSize = len + (bufferEnd - bufferPtr); #ifdef XML_CONTEXT_BYTES - int keep = bufferPtr - buffer; + int keep = bufferPtr - buffer; - if (keep > XML_CONTEXT_BYTES) - keep = XML_CONTEXT_BYTES; - neededSize += keep; + if (keep > XML_CONTEXT_BYTES) + keep = XML_CONTEXT_BYTES; + neededSize += keep; #endif /* defined XML_CONTEXT_BYTES */ - if (neededSize <= bufferLim - buffer) - { + if (neededSize <= bufferLim - buffer) { #ifdef XML_CONTEXT_BYTES - if (keep < bufferPtr - buffer) - { - int offset = (bufferPtr - buffer) - keep; - memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep); - bufferEnd -= offset; - bufferPtr -= offset; - } + if (keep < bufferPtr - buffer) { + int offset = (bufferPtr - buffer) - keep; + memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep); + bufferEnd -= offset; + bufferPtr -= offset; + } #else - memmove(buffer, bufferPtr, bufferEnd - bufferPtr); - bufferEnd = buffer + (bufferEnd - bufferPtr); - bufferPtr = buffer; + memmove(buffer, bufferPtr, bufferEnd - bufferPtr); + bufferEnd = buffer + (bufferEnd - bufferPtr); + bufferPtr = buffer; #endif /* not defined XML_CONTEXT_BYTES */ - } - else - { - char *newBuf; - int bufferSize = bufferLim - bufferPtr; - if (bufferSize == 0) - bufferSize = INIT_BUFFER_SIZE; - do - { - bufferSize *= 2; - } - while (bufferSize < neededSize); - newBuf = (char *)MALLOC(bufferSize); - if (newBuf == 0) - { - errorCode = XML_ERROR_NO_MEMORY; - return NULL; - } - bufferLim = newBuf + bufferSize; + } + else { + char *newBuf; + int bufferSize = bufferLim - bufferPtr; + if (bufferSize == 0) + bufferSize = INIT_BUFFER_SIZE; + do { + bufferSize *= 2; + } while (bufferSize < neededSize); + newBuf = (char *)MALLOC(bufferSize); + if (newBuf == 0) { + errorCode = XML_ERROR_NO_MEMORY; + return NULL; + } + bufferLim = newBuf + bufferSize; #ifdef XML_CONTEXT_BYTES - if (bufferPtr) - { - int keep = bufferPtr - buffer; - if (keep > XML_CONTEXT_BYTES) - keep = XML_CONTEXT_BYTES; - memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep); - FREE(buffer); - buffer = newBuf; - bufferEnd = buffer + (bufferEnd - bufferPtr) + keep; - bufferPtr = buffer + keep; - } - else - { - bufferEnd = newBuf + (bufferEnd - bufferPtr); - bufferPtr = buffer = newBuf; - } + if (bufferPtr) { + int keep = bufferPtr - buffer; + if (keep > XML_CONTEXT_BYTES) + keep = XML_CONTEXT_BYTES; + memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep); + FREE(buffer); + buffer = newBuf; + bufferEnd = buffer + (bufferEnd - bufferPtr) + keep; + bufferPtr = buffer + keep; + } + else { + bufferEnd = newBuf + (bufferEnd - bufferPtr); + bufferPtr = buffer = newBuf; + } #else - if (bufferPtr) - { - memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); - FREE(buffer); - } - bufferEnd = newBuf + (bufferEnd - bufferPtr); - bufferPtr = buffer = newBuf; + if (bufferPtr) { + memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); + FREE(buffer); + } + bufferEnd = newBuf + (bufferEnd - bufferPtr); + bufferPtr = buffer = newBuf; #endif /* not defined XML_CONTEXT_BYTES */ - } } - return bufferEnd; + } + return bufferEnd; } enum XML_Status XMLCALL XML_StopParser(XML_Parser parser, XML_Bool resumable) { - switch (parsing) - { - case XML_SUSPENDED: - if (resumable) - { - errorCode = XML_ERROR_SUSPENDED; - return XML_STATUS_ERROR; - } - parsing = XML_FINISHED; - break; - case XML_FINISHED: - errorCode = XML_ERROR_FINISHED; - return XML_STATUS_ERROR; - default: - if (resumable) - { + switch (parsing) { + case XML_SUSPENDED: + if (resumable) { + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + } + parsing = XML_FINISHED; + break; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + default: + if (resumable) { #ifdef XML_DTD - if (isParamEntity) - { - errorCode = XML_ERROR_SUSPEND_PE; - return XML_STATUS_ERROR; - } + if (isParamEntity) { + errorCode = XML_ERROR_SUSPEND_PE; + return XML_STATUS_ERROR; + } #endif - parsing = XML_SUSPENDED; - } - else - parsing = XML_FINISHED; + parsing = XML_SUSPENDED; } - return XML_STATUS_OK; + else + parsing = XML_FINISHED; + } + return XML_STATUS_OK; } enum XML_Status XMLCALL XML_ResumeParser(XML_Parser parser) { - enum XML_Error result = XML_STATUS_OK; + enum XML_Error result = XML_STATUS_OK; - if (parsing != XML_SUSPENDED) - { - errorCode = XML_ERROR_NOT_SUSPENDED; - return XML_STATUS_ERROR; - } - parsing = XML_PARSING; + if (parsing != XML_SUSPENDED) { + errorCode = XML_ERROR_NOT_SUSPENDED; + return XML_STATUS_ERROR; + } + parsing = XML_PARSING; - errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); + errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); - if (errorCode != XML_ERROR_NONE) - { - eventEndPtr = eventPtr; - processor = errorProcessor; - return XML_STATUS_ERROR; - } - else - { - switch (parsing) - { - case XML_SUSPENDED: - result = XML_STATUS_SUSPENDED; - break; - case XML_INITIALIZED: - case XML_PARSING: - if (finalBuffer) - { - parsing = XML_FINISHED; - return result; - } - default: - ; - } + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + else { + switch (parsing) { + case XML_SUSPENDED: + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED: + case XML_PARSING: + if (finalBuffer) { + parsing = XML_FINISHED; + return result; + } + default: ; } + } - XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); - positionPtr = bufferPtr; - return result; + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return result; } void XMLCALL XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) { - assert(status != NULL); - *status = parser->m_parsingStatus; + assert(status != NULL); + *status = parser->m_parsingStatus; } enum XML_Error XMLCALL XML_GetErrorCode(XML_Parser parser) { - return errorCode; + return errorCode; } long XMLCALL XML_GetCurrentByteIndex(XML_Parser parser) { - if (eventPtr) - return parseEndByteIndex - (parseEndPtr - eventPtr); - return -1; + if (eventPtr) + return parseEndByteIndex - (parseEndPtr - eventPtr); + return -1; } int XMLCALL XML_GetCurrentByteCount(XML_Parser parser) { - if (eventEndPtr && eventPtr) - return eventEndPtr - eventPtr; - return 0; + if (eventEndPtr && eventPtr) + return eventEndPtr - eventPtr; + return 0; } const char * XMLCALL XML_GetInputContext(XML_Parser parser, int *offset, int *size) { #ifdef XML_CONTEXT_BYTES - if (eventPtr && buffer) - { - *offset = eventPtr - buffer; - *size = bufferEnd - buffer; - return buffer; - } + if (eventPtr && buffer) { + *offset = eventPtr - buffer; + *size = bufferEnd - buffer; + return buffer; + } #endif /* defined XML_CONTEXT_BYTES */ - return (char *) 0; + return (char *) 0; } int XMLCALL XML_GetCurrentLineNumber(XML_Parser parser) { - if (eventPtr && eventPtr >= positionPtr) - { - XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); - positionPtr = eventPtr; - } - return position.lineNumber + 1; + if (eventPtr && eventPtr >= positionPtr) { + XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); + positionPtr = eventPtr; + } + return position.lineNumber + 1; } int XMLCALL XML_GetCurrentColumnNumber(XML_Parser parser) { - if (eventPtr && eventPtr >= positionPtr) - { - XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); - positionPtr = eventPtr; - } - return position.columnNumber; + if (eventPtr && eventPtr >= positionPtr) { + XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); + positionPtr = eventPtr; + } + return position.columnNumber; } void XMLCALL XML_FreeContentModel(XML_Parser parser, XML_Content *model) { - FREE(model); + FREE(model); } void * XMLCALL XML_MemMalloc(XML_Parser parser, size_t size) { - return MALLOC(size); + return MALLOC(size); } void * XMLCALL XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) { - return REALLOC(ptr, size); + return REALLOC(ptr, size); } void XMLCALL XML_MemFree(XML_Parser parser, void *ptr) { - FREE(ptr); + FREE(ptr); } void XMLCALL XML_DefaultCurrent(XML_Parser parser) { - if (defaultHandler) - { - if (openInternalEntities) - reportDefault(parser, - internalEncoding, - openInternalEntities->internalEventPtr, - openInternalEntities->internalEventEndPtr); - else - reportDefault(parser, encoding, eventPtr, eventEndPtr); - } + if (defaultHandler) { + if (openInternalEntities) + reportDefault(parser, + internalEncoding, + openInternalEntities->internalEventPtr, + openInternalEntities->internalEventEndPtr); + else + reportDefault(parser, encoding, eventPtr, eventEndPtr); + } } const XML_LChar * XMLCALL XML_ErrorString(enum XML_Error code) { - static const XML_LChar *message[] = - { - 0, - XML_L("out of memory"), - XML_L("syntax error"), - XML_L("no element found"), - XML_L("not well-formed (invalid token)"), - XML_L("unclosed token"), - XML_L("partial character"), - XML_L("mismatched tag"), - XML_L("duplicate attribute"), - XML_L("junk after document element"), - XML_L("illegal parameter entity reference"), - XML_L("undefined entity"), - XML_L("recursive entity reference"), - XML_L("asynchronous entity"), - XML_L("reference to invalid character number"), - XML_L("reference to binary entity"), - XML_L("reference to external entity in attribute"), - XML_L("xml declaration not at start of external entity"), - XML_L("unknown encoding"), - XML_L("encoding specified in XML declaration is incorrect"), - XML_L("unclosed CDATA section"), - XML_L("error in processing external entity reference"), - XML_L("document is not standalone"), - XML_L("unexpected parser state - please send a bug report"), - XML_L("entity declared in parameter entity"), - XML_L("requested feature requires XML_DTD support in Expat"), - XML_L("cannot change setting once parsing has begun"), - XML_L("unbound prefix"), - XML_L("must not undeclare prefix"), - XML_L("incomplete markup in parameter entity"), - XML_L("XML declaration not well-formed"), - XML_L("text declaration not well-formed"), - XML_L("illegal character(s) in public id"), - XML_L("parser suspended"), - XML_L("parser not suspended"), - XML_L("parsing aborted"), - XML_L("parsing finished"), - XML_L("cannot suspend in external parameter entity") - }; - if (code > 0 && code < sizeof(message)/sizeof(message[0])) - return message[code]; - return NULL; + static const XML_LChar *message[] = { + 0, + XML_L("out of memory"), + XML_L("syntax error"), + XML_L("no element found"), + XML_L("not well-formed (invalid token)"), + XML_L("unclosed token"), + XML_L("partial character"), + XML_L("mismatched tag"), + XML_L("duplicate attribute"), + XML_L("junk after document element"), + XML_L("illegal parameter entity reference"), + XML_L("undefined entity"), + XML_L("recursive entity reference"), + XML_L("asynchronous entity"), + XML_L("reference to invalid character number"), + XML_L("reference to binary entity"), + XML_L("reference to external entity in attribute"), + XML_L("xml declaration not at start of external entity"), + XML_L("unknown encoding"), + XML_L("encoding specified in XML declaration is incorrect"), + XML_L("unclosed CDATA section"), + XML_L("error in processing external entity reference"), + XML_L("document is not standalone"), + XML_L("unexpected parser state - please send a bug report"), + XML_L("entity declared in parameter entity"), + XML_L("requested feature requires XML_DTD support in Expat"), + XML_L("cannot change setting once parsing has begun"), + XML_L("unbound prefix"), + XML_L("must not undeclare prefix"), + XML_L("incomplete markup in parameter entity"), + XML_L("XML declaration not well-formed"), + XML_L("text declaration not well-formed"), + XML_L("illegal character(s) in public id"), + XML_L("parser suspended"), + XML_L("parser not suspended"), + XML_L("parsing aborted"), + XML_L("parsing finished"), + XML_L("cannot suspend in external parameter entity") + }; + if (code > 0 && code < sizeof(message)/sizeof(message[0])) + return message[code]; + return NULL; } const XML_LChar * XMLCALL -XML_ExpatVersion(void) -{ +XML_ExpatVersion(void) { - /* V1 is used to string-ize the version number. However, it would - string-ize the actual version macro *names* unless we get them - substituted before being passed to V1. CPP is defined to expand - a macro, then rescan for more expansions. Thus, we use V2 to expand - the version macros, then CPP will expand the resulting V1() macro - with the correct numerals. */ - /* ### I'm assuming cpp is portable in this respect... */ + /* V1 is used to string-ize the version number. However, it would + string-ize the actual version macro *names* unless we get them + substituted before being passed to V1. CPP is defined to expand + a macro, then rescan for more expansions. Thus, we use V2 to expand + the version macros, then CPP will expand the resulting V1() macro + with the correct numerals. */ + /* ### I'm assuming cpp is portable in this respect... */ #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c) #define V2(a,b,c) XML_L("expat_")V1(a,b,c) - return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION); + return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION); #undef V1 #undef V2 @@ -2009,44 +1905,43 @@ XML_ExpatVersion(void) XML_Expat_Version XMLCALL XML_ExpatVersionInfo(void) { - XML_Expat_Version version; + XML_Expat_Version version; - version.major = XML_MAJOR_VERSION; - version.minor = XML_MINOR_VERSION; - version.micro = XML_MICRO_VERSION; + version.major = XML_MAJOR_VERSION; + version.minor = XML_MINOR_VERSION; + version.micro = XML_MICRO_VERSION; - return version; + return version; } const XML_Feature * XMLCALL XML_GetFeatureList(void) { - static XML_Feature features[] = - { - {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"), 0}, - {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), 0}, + static XML_Feature features[] = { + {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"), 0}, + {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), 0}, #ifdef XML_UNICODE - {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0}, + {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0}, #endif #ifdef XML_UNICODE_WCHAR_T - {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0}, + {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0}, #endif #ifdef XML_DTD - {XML_FEATURE_DTD, XML_L("XML_DTD"), 0}, + {XML_FEATURE_DTD, XML_L("XML_DTD"), 0}, #endif #ifdef XML_CONTEXT_BYTES - {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), - XML_CONTEXT_BYTES}, + {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), + XML_CONTEXT_BYTES}, #endif #ifdef XML_MIN_SIZE - {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0}, + {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0}, #endif - {XML_FEATURE_END, NULL, 0} - }; + {XML_FEATURE_END, NULL, 0} + }; - features[0].value = sizeof(XML_Char); - features[1].value = sizeof(XML_LChar); - return features; + features[0].value = sizeof(XML_Char); + features[1].value = sizeof(XML_LChar); + return features; } /* Initially tag->rawName always points into the parse buffer; @@ -2057,48 +1952,46 @@ XML_GetFeatureList(void) static XML_Bool storeRawNames(XML_Parser parser) { - TAG *tag = tagStack; - while (tag) - { - int bufSize; - int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); - char *rawNameBuf = tag->buf + nameLen; - /* Stop if already stored. Since tagStack is a stack, we can stop - at the first entry that has already been copied; everything - below it in the stack is already been accounted for in a - previous call to this function. - */ - if (tag->rawName == rawNameBuf) - break; - /* For re-use purposes we need to ensure that the - size of tag->buf is a multiple of sizeof(XML_Char). - */ - bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)); - if (bufSize > tag->bufEnd - tag->buf) - { - char *temp = (char *)REALLOC(tag->buf, bufSize); - if (temp == NULL) - return XML_FALSE; - /* if tag->name.str points to tag->buf (only when namespace - processing is off) then we have to update it - */ - if (tag->name.str == (XML_Char *)tag->buf) - tag->name.str = (XML_Char *)temp; - /* if tag->name.localPart is set (when namespace processing is on) - then update it as well, since it will always point into tag->buf - */ - if (tag->name.localPart) - tag->name.localPart = (XML_Char *)temp + (tag->name.localPart - - (XML_Char *)tag->buf); - tag->buf = temp; - tag->bufEnd = temp + bufSize; - rawNameBuf = temp + nameLen; - } - memcpy(rawNameBuf, tag->rawName, tag->rawNameLength); - tag->rawName = rawNameBuf; - tag = tag->parent; - } - return XML_TRUE; + TAG *tag = tagStack; + while (tag) { + int bufSize; + int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); + char *rawNameBuf = tag->buf + nameLen; + /* Stop if already stored. Since tagStack is a stack, we can stop + at the first entry that has already been copied; everything + below it in the stack is already been accounted for in a + previous call to this function. + */ + if (tag->rawName == rawNameBuf) + break; + /* For re-use purposes we need to ensure that the + size of tag->buf is a multiple of sizeof(XML_Char). + */ + bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)); + if (bufSize > tag->bufEnd - tag->buf) { + char *temp = (char *)REALLOC(tag->buf, bufSize); + if (temp == NULL) + return XML_FALSE; + /* if tag->name.str points to tag->buf (only when namespace + processing is off) then we have to update it + */ + if (tag->name.str == (XML_Char *)tag->buf) + tag->name.str = (XML_Char *)temp; + /* if tag->name.localPart is set (when namespace processing is on) + then update it as well, since it will always point into tag->buf + */ + if (tag->name.localPart) + tag->name.localPart = (XML_Char *)temp + (tag->name.localPart - + (XML_Char *)tag->buf); + tag->buf = temp; + tag->bufEnd = temp + bufSize; + rawNameBuf = temp + nameLen; + } + memcpy(rawNameBuf, tag->rawName, tag->rawNameLength); + tag->rawName = rawNameBuf; + tag = tag->parent; + } + return XML_TRUE; } static enum XML_Error PTRCALL @@ -2107,14 +2000,13 @@ contentProcessor(XML_Parser parser, const char *end, const char **endPtr) { - enum XML_Error result = doContent(parser, 0, encoding, start, end, - endPtr, (XML_Bool)!finalBuffer); - if (result == XML_ERROR_NONE) - { - if (!storeRawNames(parser)) - return XML_ERROR_NO_MEMORY; - } - return result; + enum XML_Error result = doContent(parser, 0, encoding, start, end, + endPtr, (XML_Bool)!finalBuffer); + if (result == XML_ERROR_NONE) { + if (!storeRawNames(parser)) + return XML_ERROR_NO_MEMORY; + } + return result; } static enum XML_Error PTRCALL @@ -2123,11 +2015,11 @@ externalEntityInitProcessor(XML_Parser parser, const char *end, const char **endPtr) { - enum XML_Error result = initializeEncoding(parser); - if (result != XML_ERROR_NONE) - return result; - processor = externalEntityInitProcessor2; - return externalEntityInitProcessor2(parser, start, end, endPtr); + enum XML_Error result = initializeEncoding(parser); + if (result != XML_ERROR_NONE) + return result; + processor = externalEntityInitProcessor2; + return externalEntityInitProcessor2(parser, start, end, endPtr); } static enum XML_Error PTRCALL @@ -2136,42 +2028,38 @@ externalEntityInitProcessor2(XML_Parser parser, const char *end, const char **endPtr) { - const char *next = start; /* XmlContentTok doesn't always set the last arg */ - int tok = XmlContentTok(encoding, start, end, &next); - switch (tok) - { - case XML_TOK_BOM: - /* If we are at the end of the buffer, this would cause the next stage, - i.e. externalEntityInitProcessor3, to pass control directly to - doContent (by detecting XML_TOK_NONE) without processing any xml text - declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent. - */ - if (next == end && !finalBuffer) - { - *endPtr = next; - return XML_ERROR_NONE; - } - start = next; - break; - case XML_TOK_PARTIAL: - if (!finalBuffer) - { - *endPtr = start; - return XML_ERROR_NONE; - } - eventPtr = start; - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (!finalBuffer) - { - *endPtr = start; - return XML_ERROR_NONE; - } - eventPtr = start; - return XML_ERROR_PARTIAL_CHAR; + const char *next = start; /* XmlContentTok doesn't always set the last arg */ + int tok = XmlContentTok(encoding, start, end, &next); + switch (tok) { + case XML_TOK_BOM: + /* If we are at the end of the buffer, this would cause the next stage, + i.e. externalEntityInitProcessor3, to pass control directly to + doContent (by detecting XML_TOK_NONE) without processing any xml text + declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent. + */ + if (next == end && !finalBuffer) { + *endPtr = next; + return XML_ERROR_NONE; + } + start = next; + break; + case XML_TOK_PARTIAL: + if (!finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; } - processor = externalEntityInitProcessor3; - return externalEntityInitProcessor3(parser, start, end, endPtr); + eventPtr = start; + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (!finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; + } + eventPtr = start; + return XML_ERROR_PARTIAL_CHAR; + } + processor = externalEntityInitProcessor3; + return externalEntityInitProcessor3(parser, start, end, endPtr); } static enum XML_Error PTRCALL @@ -2180,50 +2068,46 @@ externalEntityInitProcessor3(XML_Parser parser, const char *end, const char **endPtr) { - int tok; - const char *next = start; /* XmlContentTok doesn't always set the last arg */ - eventPtr = start; - tok = XmlContentTok(encoding, start, end, &next); - eventEndPtr = next; + int tok; + const char *next = start; /* XmlContentTok doesn't always set the last arg */ + eventPtr = start; + tok = XmlContentTok(encoding, start, end, &next); + eventEndPtr = next; - switch (tok) - { - case XML_TOK_XML_DECL: + switch (tok) { + case XML_TOK_XML_DECL: { - enum XML_Error result; - result = processXmlDecl(parser, 1, start, next); - if (result != XML_ERROR_NONE) - return result; - switch (parsing) - { - case XML_SUSPENDED: - *endPtr = next; - return XML_ERROR_NONE; - case XML_FINISHED: - return XML_ERROR_ABORTED; - default: - start = next; - } + enum XML_Error result; + result = processXmlDecl(parser, 1, start, next); + if (result != XML_ERROR_NONE) + return result; + switch (parsing) { + case XML_SUSPENDED: + *endPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: + start = next; + } } break; - case XML_TOK_PARTIAL: - if (!finalBuffer) - { - *endPtr = start; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (!finalBuffer) - { - *endPtr = start; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_PARTIAL: + if (!finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; } - processor = externalEntityContentProcessor; - tagLevel = 1; - return externalEntityContentProcessor(parser, start, end, endPtr); + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (!finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + } + processor = externalEntityContentProcessor; + tagLevel = 1; + return externalEntityContentProcessor(parser, start, end, endPtr); } static enum XML_Error PTRCALL @@ -2232,14 +2116,13 @@ externalEntityContentProcessor(XML_Parser parser, const char *end, const char **endPtr) { - enum XML_Error result = doContent(parser, 1, encoding, start, end, - endPtr, (XML_Bool)!finalBuffer); - if (result == XML_ERROR_NONE) - { - if (!storeRawNames(parser)) - return XML_ERROR_NO_MEMORY; - } - return result; + enum XML_Error result = doContent(parser, 1, encoding, start, end, + endPtr, (XML_Bool)!finalBuffer); + if (result == XML_ERROR_NONE) { + if (!storeRawNames(parser)) + return XML_ERROR_NO_MEMORY; + } + return result; } static enum XML_Error @@ -2251,492 +2134,449 @@ doContent(XML_Parser parser, const char **nextPtr, XML_Bool haveMore) { - /* save one level of indirection */ - DTD * const dtd = _dtd; - - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) - { - eventPP = &eventPtr; - eventEndPP = &eventEndPtr; - } - else - { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - *eventPP = s; - - for (;;) - { - const char *next = s; /* XmlContentTok doesn't always set the last arg */ - int tok = XmlContentTok(enc, s, end, &next); - *eventEndPP = next; - switch (tok) - { - case XML_TOK_TRAILING_CR: - if (haveMore) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - *eventEndPP = end; - if (characterDataHandler) - { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, end); - /* We are at the end of the final buffer, should we check for - XML_SUSPENDED, XML_FINISHED? - */ - if (startTagLevel == 0) - return XML_ERROR_NO_ELEMENTS; - if (tagLevel != startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - *nextPtr = end; - return XML_ERROR_NONE; - case XML_TOK_NONE: - if (haveMore) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - if (startTagLevel > 0) - { - if (tagLevel != startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_NO_ELEMENTS; - case XML_TOK_INVALID: - *eventPP = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (haveMore) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (haveMore) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_ENTITY_REF: - { - const XML_Char *name; - ENTITY *entity; - XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (ch) - { - if (characterDataHandler) - characterDataHandler(handlerArg, &ch, 1); - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - name = poolStoreString(&dtd->pool, enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!name) - return XML_ERROR_NO_MEMORY; - entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); - poolDiscard(&dtd->pool); - /* First, determine if a check for an existing declaration is needed; - if yes, check that the entity exists, and that it is internal, - otherwise call the skipped entity or default handler. - */ - if (!dtd->hasParamEntityRefs || dtd->standalone) - { - if (!entity) - return XML_ERROR_UNDEFINED_ENTITY; - else if (!entity->is_internal) - return XML_ERROR_ENTITY_DECLARED_IN_PE; - } - else if (!entity) - { - if (skippedEntityHandler) - skippedEntityHandler(handlerArg, name, 0); - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - if (entity->open) - return XML_ERROR_RECURSIVE_ENTITY_REF; - if (entity->notation) - return XML_ERROR_BINARY_ENTITY_REF; - if (entity->textPtr) - { - enum XML_Error result; - if (!defaultExpandInternalEntities) - { - if (skippedEntityHandler) - skippedEntityHandler(handlerArg, entity->name, 0); - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - result = processInternalEntity(parser, entity, XML_FALSE); - if (result != XML_ERROR_NONE) - return result; - } - else if (externalEntityRefHandler) - { - const XML_Char *context; - entity->open = XML_TRUE; - context = getContext(parser); - entity->open = XML_FALSE; - if (!context) - return XML_ERROR_NO_MEMORY; - if (!externalEntityRefHandler(externalEntityRefHandlerArg, - context, - entity->base, - entity->systemId, - entity->publicId)) - return XML_ERROR_EXTERNAL_ENTITY_HANDLING; - poolDiscard(&tempPool); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; + /* save one level of indirection */ + DTD * const dtd = _dtd; + + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + + for (;;) { + const char *next = s; /* XmlContentTok doesn't always set the last arg */ + int tok = XmlContentTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_TRAILING_CR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + *eventEndPP = end; + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, end); + /* We are at the end of the final buffer, should we check for + XML_SUSPENDED, XML_FINISHED? + */ + if (startTagLevel == 0) + return XML_ERROR_NO_ELEMENTS; + if (tagLevel != startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + *nextPtr = end; + return XML_ERROR_NONE; + case XML_TOK_NONE: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + if (startTagLevel > 0) { + if (tagLevel != startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_NO_ELEMENTS; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_ENTITY_REF: + { + const XML_Char *name; + ENTITY *entity; + XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (ch) { + if (characterDataHandler) + characterDataHandler(handlerArg, &ch, 1); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; } - case XML_TOK_START_TAG_NO_ATTS: - /* fall through */ - case XML_TOK_START_TAG_WITH_ATTS: - { - TAG *tag; - enum XML_Error result; - XML_Char *toPtr; - if (freeTagList) - { - tag = freeTagList; - freeTagList = freeTagList->parent; - } - else - { - tag = (TAG *)MALLOC(sizeof(TAG)); - if (!tag) - return XML_ERROR_NO_MEMORY; - tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE); - if (!tag->buf) - { - FREE(tag); - return XML_ERROR_NO_MEMORY; - } - tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; - } - tag->bindings = NULL; - tag->parent = tagStack; - tagStack = tag; - tag->name.localPart = NULL; - tag->name.prefix = NULL; - tag->rawName = s + enc->minBytesPerChar; - tag->rawNameLength = XmlNameLength(enc, tag->rawName); - ++tagLevel; - { - const char *rawNameEnd = tag->rawName + tag->rawNameLength; - const char *fromPtr = tag->rawName; - toPtr = (XML_Char *)tag->buf; - for (;;) - { - int bufSize; - int convLen; - XmlConvert(enc, - &fromPtr, rawNameEnd, - (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); - convLen = toPtr - (XML_Char *)tag->buf; - if (fromPtr == rawNameEnd) - { - tag->name.strLen = convLen; - break; - } - bufSize = (tag->bufEnd - tag->buf) << 1; - { - char *temp = (char *)REALLOC(tag->buf, bufSize); - if (temp == NULL) - return XML_ERROR_NO_MEMORY; - tag->buf = temp; - tag->bufEnd = temp + bufSize; - toPtr = (XML_Char *)temp + convLen; - } - } - } - tag->name.str = (XML_Char *)tag->buf; - *toPtr = XML_T('\0'); - result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); - if (result) - return result; - if (startElementHandler) - startElementHandler(handlerArg, tag->name.str, - (const XML_Char **)atts); + name = poolStoreString(&dtd->pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); + poolDiscard(&dtd->pool); + /* First, determine if a check for an existing declaration is needed; + if yes, check that the entity exists, and that it is internal, + otherwise call the skipped entity or default handler. + */ + if (!dtd->hasParamEntityRefs || dtd->standalone) { + if (!entity) + return XML_ERROR_UNDEFINED_ENTITY; + else if (!entity->is_internal) + return XML_ERROR_ENTITY_DECLARED_IN_PE; + } + else if (!entity) { + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, name, 0); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + if (entity->open) + return XML_ERROR_RECURSIVE_ENTITY_REF; + if (entity->notation) + return XML_ERROR_BINARY_ENTITY_REF; + if (entity->textPtr) { + enum XML_Error result; + if (!defaultExpandInternalEntities) { + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, entity->name, 0); else if (defaultHandler) - reportDefault(parser, enc, s, next); - poolClear(&tempPool); + reportDefault(parser, enc, s, next); break; + } + result = processInternalEntity(parser, entity, XML_FALSE); + if (result != XML_ERROR_NONE) + return result; } - case XML_TOK_EMPTY_ELEMENT_NO_ATTS: - /* fall through */ - case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: - { - const char *rawName = s + enc->minBytesPerChar; - enum XML_Error result; - BINDING *bindings = NULL; - XML_Bool noElmHandlers = XML_TRUE; - TAG_NAME name; - name.str = poolStoreString(&tempPool, enc, rawName, - rawName + XmlNameLength(enc, rawName)); - if (!name.str) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - result = storeAtts(parser, enc, s, &name, &bindings); - if (result) - return result; - poolFinish(&tempPool); - if (startElementHandler) - { - startElementHandler(handlerArg, name.str, (const XML_Char **)atts); - noElmHandlers = XML_FALSE; - } - if (endElementHandler) - { - if (startElementHandler) - *eventPP = *eventEndPP; - endElementHandler(handlerArg, name.str); - noElmHandlers = XML_FALSE; - } - if (noElmHandlers && defaultHandler) - reportDefault(parser, enc, s, next); - poolClear(&tempPool); - while (bindings) - { - BINDING *b = bindings; - if (endNamespaceDeclHandler) - endNamespaceDeclHandler(handlerArg, b->prefix->name); - bindings = bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - b->prefix->binding = b->prevPrefixBinding; - } + else if (externalEntityRefHandler) { + const XML_Char *context; + entity->open = XML_TRUE; + context = getContext(parser); + entity->open = XML_FALSE; + if (!context) + return XML_ERROR_NO_MEMORY; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + context, + entity->base, + entity->systemId, + entity->publicId)) + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + poolDiscard(&tempPool); } - if (tagLevel == 0) - return epilogProcessor(parser, next, end, nextPtr); + else if (defaultHandler) + reportDefault(parser, enc, s, next); break; - case XML_TOK_END_TAG: - if (tagLevel == startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - else - { - int len; - const char *rawName; - TAG *tag = tagStack; - tagStack = tag->parent; - tag->parent = freeTagList; - freeTagList = tag; - rawName = s + enc->minBytesPerChar*2; - len = XmlNameLength(enc, rawName); - if (len != tag->rawNameLength - || memcmp(tag->rawName, rawName, len) != 0) - { - *eventPP = rawName; - return XML_ERROR_TAG_MISMATCH; - } - --tagLevel; - if (endElementHandler) - { - const XML_Char *localPart; - const XML_Char *prefix; - XML_Char *uri; - localPart = tag->name.localPart; - if (ns && localPart) - { - /* localPart and prefix may have been overwritten in - tag->name.str, since this points to the binding->uri - buffer which gets re-used; so we have to add them again - */ - uri = (XML_Char *)tag->name.str + tag->name.uriLen; - /* don't need to check for space - already done in storeAtts() */ - while (*localPart) *uri++ = *localPart++; - prefix = (XML_Char *)tag->name.prefix; - if (ns_triplets && prefix) - { - *uri++ = namespaceSeparator; - while (*prefix) *uri++ = *prefix++; - } - *uri = XML_T('\0'); - } - endElementHandler(handlerArg, tag->name.str); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - while (tag->bindings) - { - BINDING *b = tag->bindings; - if (endNamespaceDeclHandler) - endNamespaceDeclHandler(handlerArg, b->prefix->name); - tag->bindings = tag->bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - b->prefix->binding = b->prevPrefixBinding; - } - if (tagLevel == 0) - return epilogProcessor(parser, next, end, nextPtr); - } - break; - case XML_TOK_CHAR_REF: - { - int n = XmlCharRefNumber(enc, s); - if (n < 0) - return XML_ERROR_BAD_CHAR_REF; - if (characterDataHandler) - { - XML_Char buf[XML_ENCODE_MAX]; - characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); + } + case XML_TOK_START_TAG_NO_ATTS: + /* fall through */ + case XML_TOK_START_TAG_WITH_ATTS: + { + TAG *tag; + enum XML_Error result; + XML_Char *toPtr; + if (freeTagList) { + tag = freeTagList; + freeTagList = freeTagList->parent; } - break; - case XML_TOK_XML_DECL: - return XML_ERROR_MISPLACED_XML_PI; - case XML_TOK_DATA_NEWLINE: - if (characterDataHandler) - { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_CDATA_SECT_OPEN: + else { + tag = (TAG *)MALLOC(sizeof(TAG)); + if (!tag) + return XML_ERROR_NO_MEMORY; + tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE); + if (!tag->buf) { + FREE(tag); + return XML_ERROR_NO_MEMORY; + } + tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; + } + tag->bindings = NULL; + tag->parent = tagStack; + tagStack = tag; + tag->name.localPart = NULL; + tag->name.prefix = NULL; + tag->rawName = s + enc->minBytesPerChar; + tag->rawNameLength = XmlNameLength(enc, tag->rawName); + ++tagLevel; { - enum XML_Error result; - if (startCdataSectionHandler) - startCdataSectionHandler(handlerArg); -#if 0 - /* Suppose you doing a transformation on a document that involves - changing only the character data. You set up a defaultHandler - and a characterDataHandler. The defaultHandler simply copies - characters through. The characterDataHandler does the - transformation and writes the characters out escaping them as - necessary. This case will fail to work if we leave out the - following two lines (because & and < inside CDATA sections will - be incorrectly escaped). - - However, now we have a start/endCdataSectionHandler, so it seems - easier to let the user deal with this. - */ - else if (characterDataHandler) - characterDataHandler(handlerArg, dataBuf, 0); -#endif - else if (defaultHandler) - reportDefault(parser, enc, s, next); - result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore); - if (result != XML_ERROR_NONE) - return result; - else if (!next) + const char *rawNameEnd = tag->rawName + tag->rawNameLength; + const char *fromPtr = tag->rawName; + toPtr = (XML_Char *)tag->buf; + for (;;) { + int bufSize; + int convLen; + XmlConvert(enc, + &fromPtr, rawNameEnd, + (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); + convLen = toPtr - (XML_Char *)tag->buf; + if (fromPtr == rawNameEnd) { + tag->name.strLen = convLen; + break; + } + bufSize = (tag->bufEnd - tag->buf) << 1; { - processor = cdataSectionProcessor; - return result; + char *temp = (char *)REALLOC(tag->buf, bufSize); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + tag->buf = temp; + tag->bufEnd = temp + bufSize; + toPtr = (XML_Char *)temp + convLen; } + } } + tag->name.str = (XML_Char *)tag->buf; + *toPtr = XML_T('\0'); + result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); + if (result) + return result; + if (startElementHandler) + startElementHandler(handlerArg, tag->name.str, + (const XML_Char **)atts); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + poolClear(&tempPool); break; - case XML_TOK_TRAILING_RSQB: - if (haveMore) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - if (characterDataHandler) - { - if (MUST_CONVERT(enc, s)) - { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); - characterDataHandler(handlerArg, dataBuf, - dataPtr - (ICHAR *)dataBuf); - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)end - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, end); - /* We are at the end of the final buffer, should we check for - XML_SUSPENDED, XML_FINISHED? + } + case XML_TOK_EMPTY_ELEMENT_NO_ATTS: + /* fall through */ + case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: + { + const char *rawName = s + enc->minBytesPerChar; + enum XML_Error result; + BINDING *bindings = NULL; + XML_Bool noElmHandlers = XML_TRUE; + TAG_NAME name; + name.str = poolStoreString(&tempPool, enc, rawName, + rawName + XmlNameLength(enc, rawName)); + if (!name.str) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + result = storeAtts(parser, enc, s, &name, &bindings); + if (result) + return result; + poolFinish(&tempPool); + if (startElementHandler) { + startElementHandler(handlerArg, name.str, (const XML_Char **)atts); + noElmHandlers = XML_FALSE; + } + if (endElementHandler) { + if (startElementHandler) + *eventPP = *eventEndPP; + endElementHandler(handlerArg, name.str); + noElmHandlers = XML_FALSE; + } + if (noElmHandlers && defaultHandler) + reportDefault(parser, enc, s, next); + poolClear(&tempPool); + while (bindings) { + BINDING *b = bindings; + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + bindings = bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } + } + if (tagLevel == 0) + return epilogProcessor(parser, next, end, nextPtr); + break; + case XML_TOK_END_TAG: + if (tagLevel == startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + else { + int len; + const char *rawName; + TAG *tag = tagStack; + tagStack = tag->parent; + tag->parent = freeTagList; + freeTagList = tag; + rawName = s + enc->minBytesPerChar*2; + len = XmlNameLength(enc, rawName); + if (len != tag->rawNameLength + || memcmp(tag->rawName, rawName, len) != 0) { + *eventPP = rawName; + return XML_ERROR_TAG_MISMATCH; + } + --tagLevel; + if (endElementHandler) { + const XML_Char *localPart; + const XML_Char *prefix; + XML_Char *uri; + localPart = tag->name.localPart; + if (ns && localPart) { + /* localPart and prefix may have been overwritten in + tag->name.str, since this points to the binding->uri + buffer which gets re-used; so we have to add them again */ - if (startTagLevel == 0) - { - *eventPP = end; - return XML_ERROR_NO_ELEMENTS; - } - if (tagLevel != startTagLevel) - { - *eventPP = end; - return XML_ERROR_ASYNC_ENTITY; - } - *nextPtr = end; - return XML_ERROR_NONE; - case XML_TOK_DATA_CHARS: - if (characterDataHandler) - { - if (MUST_CONVERT(enc, s)) - { - for (;;) - { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = s; - characterDataHandler(handlerArg, dataBuf, - dataPtr - (ICHAR *)dataBuf); - if (s == next) - break; - *eventPP = s; - } - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)next - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_PI: - if (!reportProcessingInstruction(parser, enc, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_COMMENT: - if (!reportComment(parser, enc, s, next)) - return XML_ERROR_NO_MEMORY; - break; - default: - if (defaultHandler) - reportDefault(parser, enc, s, next); - break; + uri = (XML_Char *)tag->name.str + tag->name.uriLen; + /* don't need to check for space - already done in storeAtts() */ + while (*localPart) *uri++ = *localPart++; + prefix = (XML_Char *)tag->name.prefix; + if (ns_triplets && prefix) { + *uri++ = namespaceSeparator; + while (*prefix) *uri++ = *prefix++; + } + *uri = XML_T('\0'); + } + endElementHandler(handlerArg, tag->name.str); } - *eventPP = s = next; - switch (parsing) - { - case XML_SUSPENDED: - *nextPtr = next; - return XML_ERROR_NONE; - case XML_FINISHED: - return XML_ERROR_ABORTED; - default: - ; + else if (defaultHandler) + reportDefault(parser, enc, s, next); + while (tag->bindings) { + BINDING *b = tag->bindings; + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + tag->bindings = tag->bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; } - } - /* not reached */ + if (tagLevel == 0) + return epilogProcessor(parser, next, end, nextPtr); + } + break; + case XML_TOK_CHAR_REF: + { + int n = XmlCharRefNumber(enc, s); + if (n < 0) + return XML_ERROR_BAD_CHAR_REF; + if (characterDataHandler) { + XML_Char buf[XML_ENCODE_MAX]; + characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + } + break; + case XML_TOK_XML_DECL: + return XML_ERROR_MISPLACED_XML_PI; + case XML_TOK_DATA_NEWLINE: + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_CDATA_SECT_OPEN: + { + enum XML_Error result; + if (startCdataSectionHandler) + startCdataSectionHandler(handlerArg); +#if 0 + /* Suppose you doing a transformation on a document that involves + changing only the character data. You set up a defaultHandler + and a characterDataHandler. The defaultHandler simply copies + characters through. The characterDataHandler does the + transformation and writes the characters out escaping them as + necessary. This case will fail to work if we leave out the + following two lines (because & and < inside CDATA sections will + be incorrectly escaped). + + However, now we have a start/endCdataSectionHandler, so it seems + easier to let the user deal with this. + */ + else if (characterDataHandler) + characterDataHandler(handlerArg, dataBuf, 0); +#endif + else if (defaultHandler) + reportDefault(parser, enc, s, next); + result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore); + if (result != XML_ERROR_NONE) + return result; + else if (!next) { + processor = cdataSectionProcessor; + return result; + } + } + break; + case XML_TOK_TRAILING_RSQB: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); + characterDataHandler(handlerArg, dataBuf, + dataPtr - (ICHAR *)dataBuf); + } + else + characterDataHandler(handlerArg, + (XML_Char *)s, + (XML_Char *)end - (XML_Char *)s); + } + else if (defaultHandler) + reportDefault(parser, enc, s, end); + /* We are at the end of the final buffer, should we check for + XML_SUSPENDED, XML_FINISHED? + */ + if (startTagLevel == 0) { + *eventPP = end; + return XML_ERROR_NO_ELEMENTS; + } + if (tagLevel != startTagLevel) { + *eventPP = end; + return XML_ERROR_ASYNC_ENTITY; + } + *nextPtr = end; + return XML_ERROR_NONE; + case XML_TOK_DATA_CHARS: + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + for (;;) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = s; + characterDataHandler(handlerArg, dataBuf, + dataPtr - (ICHAR *)dataBuf); + if (s == next) + break; + *eventPP = s; + } + } + else + characterDataHandler(handlerArg, + (XML_Char *)s, + (XML_Char *)next - (XML_Char *)s); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_PI: + if (!reportProcessingInstruction(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_COMMENT: + if (!reportComment(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + break; + default: + if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + *eventPP = s = next; + switch (parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: ; + } + } + /* not reached */ } /* Precondition: all arguments must be non-NULL; @@ -2754,362 +2594,324 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, TAG_NAME *tagNamePtr, BINDING **bindingsPtr) { - DTD * const dtd = _dtd; /* save one level of indirection */ - ELEMENT_TYPE *elementType; - int nDefaultAtts; - const XML_Char **appAtts; /* the attribute list for the application */ - int attIndex = 0; - int prefixLen; - int i; - int n; - XML_Char *uri; - int nPrefixes = 0; - BINDING *binding; - const XML_Char *localPart; - - /* lookup the element type name */ - elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0); + DTD * const dtd = _dtd; /* save one level of indirection */ + ELEMENT_TYPE *elementType; + int nDefaultAtts; + const XML_Char **appAtts; /* the attribute list for the application */ + int attIndex = 0; + int prefixLen; + int i; + int n; + XML_Char *uri; + int nPrefixes = 0; + BINDING *binding; + const XML_Char *localPart; + + /* lookup the element type name */ + elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0); + if (!elementType) { + const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str); + if (!name) + return XML_ERROR_NO_MEMORY; + elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name, + sizeof(ELEMENT_TYPE)); if (!elementType) - { - const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str); - if (!name) - return XML_ERROR_NO_MEMORY; - elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name, - sizeof(ELEMENT_TYPE)); - if (!elementType) - return XML_ERROR_NO_MEMORY; - if (ns && !setElementTypePrefix(parser, elementType)) - return XML_ERROR_NO_MEMORY; - } - nDefaultAtts = elementType->nDefaultAtts; - - /* get the attributes from the tokenizer */ - n = XmlGetAttributes(enc, attStr, attsSize, atts); - if (n + nDefaultAtts > attsSize) - { - int oldAttsSize = attsSize; - ATTRIBUTE *temp; - attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; - temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE)); - if (temp == NULL) - return XML_ERROR_NO_MEMORY; - atts = temp; - if (n > oldAttsSize) - XmlGetAttributes(enc, attStr, n, atts); - } - - appAtts = (const XML_Char **)atts; - for (i = 0; i < n; i++) - { - /* add the name and value to the attribute list */ - ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name, - atts[i].name - + XmlNameLength(enc, atts[i].name)); - if (!attId) - return XML_ERROR_NO_MEMORY; - /* Detect duplicate attributes by their QNames. This does not work when - namespace processing is turned on and different prefixes for the same - namespace are used. For this case we have a check further down. - */ - if ((attId->name)[-1]) - { - if (enc == encoding) - eventPtr = atts[i].name; - return XML_ERROR_DUPLICATE_ATTRIBUTE; - } - (attId->name)[-1] = 1; - appAtts[attIndex++] = attId->name; - if (!atts[i].normalized) - { - enum XML_Error result; - XML_Bool isCdata = XML_TRUE; - - /* figure out whether declared as other than CDATA */ - if (attId->maybeTokenized) - { - int j; - for (j = 0; j < nDefaultAtts; j++) - { - if (attId == elementType->defaultAtts[j].id) - { - isCdata = elementType->defaultAtts[j].isCdata; - break; - } - } - } - - /* normalize the attribute value */ - result = storeAttributeValue(parser, enc, isCdata, - atts[i].valuePtr, atts[i].valueEnd, - &tempPool); - if (result) - return result; - appAtts[attIndex] = poolStart(&tempPool); - poolFinish(&tempPool); - } - else - { - /* the value did not need normalizing */ - appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, - atts[i].valueEnd); - if (appAtts[attIndex] == 0) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - } - /* handle prefixed attribute names */ - if (attId->prefix) - { - if (attId->xmlns) - { - /* deal with namespace declarations here */ - enum XML_Error result = addBinding(parser, attId->prefix, attId, - appAtts[attIndex], bindingsPtr); - if (result) - return result; - --attIndex; - } - else - { - /* deal with other prefixed names later */ - attIndex++; - nPrefixes++; - (attId->name)[-1] = 2; - } + return XML_ERROR_NO_MEMORY; + if (ns && !setElementTypePrefix(parser, elementType)) + return XML_ERROR_NO_MEMORY; + } + nDefaultAtts = elementType->nDefaultAtts; + + /* get the attributes from the tokenizer */ + n = XmlGetAttributes(enc, attStr, attsSize, atts); + if (n + nDefaultAtts > attsSize) { + int oldAttsSize = attsSize; + ATTRIBUTE *temp; + attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; + temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE)); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + atts = temp; + if (n > oldAttsSize) + XmlGetAttributes(enc, attStr, n, atts); + } + + appAtts = (const XML_Char **)atts; + for (i = 0; i < n; i++) { + /* add the name and value to the attribute list */ + ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name, + atts[i].name + + XmlNameLength(enc, atts[i].name)); + if (!attId) + return XML_ERROR_NO_MEMORY; + /* Detect duplicate attributes by their QNames. This does not work when + namespace processing is turned on and different prefixes for the same + namespace are used. For this case we have a check further down. + */ + if ((attId->name)[-1]) { + if (enc == encoding) + eventPtr = atts[i].name; + return XML_ERROR_DUPLICATE_ATTRIBUTE; + } + (attId->name)[-1] = 1; + appAtts[attIndex++] = attId->name; + if (!atts[i].normalized) { + enum XML_Error result; + XML_Bool isCdata = XML_TRUE; + + /* figure out whether declared as other than CDATA */ + if (attId->maybeTokenized) { + int j; + for (j = 0; j < nDefaultAtts; j++) { + if (attId == elementType->defaultAtts[j].id) { + isCdata = elementType->defaultAtts[j].isCdata; + break; + } } - else - attIndex++; - } + } - /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */ - nSpecifiedAtts = attIndex; - if (elementType->idAtt && (elementType->idAtt->name)[-1]) - { - for (i = 0; i < attIndex; i += 2) - if (appAtts[i] == elementType->idAtt->name) - { - idAttIndex = i; - break; - } + /* normalize the attribute value */ + result = storeAttributeValue(parser, enc, isCdata, + atts[i].valuePtr, atts[i].valueEnd, + &tempPool); + if (result) + return result; + appAtts[attIndex] = poolStart(&tempPool); + poolFinish(&tempPool); + } + else { + /* the value did not need normalizing */ + appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, + atts[i].valueEnd); + if (appAtts[attIndex] == 0) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + } + /* handle prefixed attribute names */ + if (attId->prefix) { + if (attId->xmlns) { + /* deal with namespace declarations here */ + enum XML_Error result = addBinding(parser, attId->prefix, attId, + appAtts[attIndex], bindingsPtr); + if (result) + return result; + --attIndex; + } + else { + /* deal with other prefixed names later */ + attIndex++; + nPrefixes++; + (attId->name)[-1] = 2; + } } else - idAttIndex = -1; - - /* do attribute defaulting */ - for (i = 0; i < nDefaultAtts; i++) - { - const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i; - if (!(da->id->name)[-1] && da->value) - { - if (da->id->prefix) - { - if (da->id->xmlns) - { - enum XML_Error result = addBinding(parser, da->id->prefix, da->id, - da->value, bindingsPtr); - if (result) - return result; - } - else - { - (da->id->name)[-1] = 2; - nPrefixes++; - appAtts[attIndex++] = da->id->name; - appAtts[attIndex++] = da->value; - } - } - else - { - (da->id->name)[-1] = 1; - appAtts[attIndex++] = da->id->name; - appAtts[attIndex++] = da->value; - } + attIndex++; + } + + /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */ + nSpecifiedAtts = attIndex; + if (elementType->idAtt && (elementType->idAtt->name)[-1]) { + for (i = 0; i < attIndex; i += 2) + if (appAtts[i] == elementType->idAtt->name) { + idAttIndex = i; + break; + } + } + else + idAttIndex = -1; + + /* do attribute defaulting */ + for (i = 0; i < nDefaultAtts; i++) { + const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i; + if (!(da->id->name)[-1] && da->value) { + if (da->id->prefix) { + if (da->id->xmlns) { + enum XML_Error result = addBinding(parser, da->id->prefix, da->id, + da->value, bindingsPtr); + if (result) + return result; } - } - appAtts[attIndex] = 0; - - /* expand prefixed attribute names, check for duplicates, - and clear flags that say whether attributes were specified */ - i = 0; - if (nPrefixes) - { - int j; /* hash table index */ - unsigned long version = nsAttsVersion; - int nsAttsSize = (int)1 << nsAttsPower; - /* size of hash table must be at least 2 * (# of prefixed attributes) */ - if ((nPrefixes << 1) >> nsAttsPower) /* true for nsAttsPower = 0 */ - { - NS_ATT *temp; - /* hash table size must also be a power of 2 and >= 8 */ - while (nPrefixes >> nsAttsPower++); - if (nsAttsPower < 3) - nsAttsPower = 3; - nsAttsSize = (int)1 << nsAttsPower; - temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT)); - if (!temp) - return XML_ERROR_NO_MEMORY; - nsAtts = temp; - version = 0; /* force re-initialization of nsAtts hash table */ + else { + (da->id->name)[-1] = 2; + nPrefixes++; + appAtts[attIndex++] = da->id->name; + appAtts[attIndex++] = da->value; } - /* using a version flag saves us from initializing nsAtts every time */ - if (!version) /* initialize version flags when version wraps around */ - { - version = INIT_ATTS_VERSION; - for (j = nsAttsSize; j != 0; ) - nsAtts[--j].version = version; + } + else { + (da->id->name)[-1] = 1; + appAtts[attIndex++] = da->id->name; + appAtts[attIndex++] = da->value; + } + } + } + appAtts[attIndex] = 0; + + /* expand prefixed attribute names, check for duplicates, + and clear flags that say whether attributes were specified */ + i = 0; + if (nPrefixes) { + int j; /* hash table index */ + unsigned long version = nsAttsVersion; + int nsAttsSize = (int)1 << nsAttsPower; + /* size of hash table must be at least 2 * (# of prefixed attributes) */ + if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */ + NS_ATT *temp; + /* hash table size must also be a power of 2 and >= 8 */ + while (nPrefixes >> nsAttsPower++); + if (nsAttsPower < 3) + nsAttsPower = 3; + nsAttsSize = (int)1 << nsAttsPower; + temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT)); + if (!temp) + return XML_ERROR_NO_MEMORY; + nsAtts = temp; + version = 0; /* force re-initialization of nsAtts hash table */ + } + /* using a version flag saves us from initializing nsAtts every time */ + if (!version) { /* initialize version flags when version wraps around */ + version = INIT_ATTS_VERSION; + for (j = nsAttsSize; j != 0; ) + nsAtts[--j].version = version; + } + nsAttsVersion = --version; + + /* expand prefixed names and check for duplicates */ + for (; i < attIndex; i += 2) { + const XML_Char *s = appAtts[i]; + if (s[-1] == 2) { /* prefixed */ + ATTRIBUTE_ID *id; + const BINDING *b; + unsigned long uriHash = 0; + ((XML_Char *)s)[-1] = 0; /* clear flag */ + id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0); + b = id->prefix->binding; + if (!b) + return XML_ERROR_UNBOUND_PREFIX; + + /* as we expand the name we also calculate its hash value */ + for (j = 0; j < b->uriLen; j++) { + const XML_Char c = b->uri[j]; + if (!poolAppendChar(&tempPool, c)) + return XML_ERROR_NO_MEMORY; + uriHash = CHAR_HASH(uriHash, c); } - nsAttsVersion = --version; + while (*s++ != XML_T(':')) + ; + do { /* copies null terminator */ + const XML_Char c = *s; + if (!poolAppendChar(&tempPool, *s)) + return XML_ERROR_NO_MEMORY; + uriHash = CHAR_HASH(uriHash, c); + } while (*s++); - /* expand prefixed names and check for duplicates */ - for (; i < attIndex; i += 2) - { - const XML_Char *s = appAtts[i]; - if (s[-1] == 2) /* prefixed */ - { - ATTRIBUTE_ID *id; - const BINDING *b; - unsigned long uriHash = 0; - ((XML_Char *)s)[-1] = 0; /* clear flag */ - id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0); - b = id->prefix->binding; - if (!b) - return XML_ERROR_UNBOUND_PREFIX; - - /* as we expand the name we also calculate its hash value */ - for (j = 0; j < b->uriLen; j++) - { - const XML_Char c = b->uri[j]; - if (!poolAppendChar(&tempPool, c)) - return XML_ERROR_NO_MEMORY; - uriHash = CHAR_HASH(uriHash, c); - } - while (*s++ != XML_T(':')) - ; - do /* copies null terminator */ - { - const XML_Char c = *s; - if (!poolAppendChar(&tempPool, *s)) - return XML_ERROR_NO_MEMORY; - uriHash = CHAR_HASH(uriHash, c); - } - while (*s++); - - { /* Check hash table for duplicate of expanded name (uriName). + { /* Check hash table for duplicate of expanded name (uriName). Derived from code in lookup(HASH_TABLE *table, ...). */ - unsigned char step = 0; - unsigned long mask = nsAttsSize - 1; - j = uriHash & mask; /* index into hash table */ - while (nsAtts[j].version == version) - { - /* for speed we compare stored hash values first */ - if (uriHash == nsAtts[j].hash) - { - const XML_Char *s1 = poolStart(&tempPool); - const XML_Char *s2 = nsAtts[j].uriName; - /* s1 is null terminated, but not s2 */ - for (; *s1 == *s2 && *s1 != 0; s1++, s2++); - if (*s1 == 0) - return XML_ERROR_DUPLICATE_ATTRIBUTE; - } - if (!step) - step = PROBE_STEP(uriHash, mask, nsAttsPower); - j < step ? ( j += nsAttsSize - step) : (j -= step); - } - } - - if (ns_triplets) /* append namespace separator and prefix */ - { - tempPool.ptr[-1] = namespaceSeparator; - s = b->prefix->name; - do - { - if (!poolAppendChar(&tempPool, *s)) - return XML_ERROR_NO_MEMORY; - } - while (*s++); - } - - /* store expanded name in attribute list */ - s = poolStart(&tempPool); - poolFinish(&tempPool); - appAtts[i] = s; - - /* fill empty slot with new version, uriName and hash value */ - nsAtts[j].version = version; - nsAtts[j].hash = uriHash; - nsAtts[j].uriName = s; - - if (!--nPrefixes) - break; + unsigned char step = 0; + unsigned long mask = nsAttsSize - 1; + j = uriHash & mask; /* index into hash table */ + while (nsAtts[j].version == version) { + /* for speed we compare stored hash values first */ + if (uriHash == nsAtts[j].hash) { + const XML_Char *s1 = poolStart(&tempPool); + const XML_Char *s2 = nsAtts[j].uriName; + /* s1 is null terminated, but not s2 */ + for (; *s1 == *s2 && *s1 != 0; s1++, s2++); + if (*s1 == 0) + return XML_ERROR_DUPLICATE_ATTRIBUTE; } - else /* not prefixed */ - ((XML_Char *)s)[-1] = 0; /* clear flag */ + if (!step) + step = PROBE_STEP(uriHash, mask, nsAttsPower); + j < step ? ( j += nsAttsSize - step) : (j -= step); + } } - } - /* clear flags for the remaining attributes */ - for (; i < attIndex; i += 2) - ((XML_Char *)(appAtts[i]))[-1] = 0; - for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) - binding->attId->name[-1] = 0; - if (!ns) - return XML_ERROR_NONE; + if (ns_triplets) { /* append namespace separator and prefix */ + tempPool.ptr[-1] = namespaceSeparator; + s = b->prefix->name; + do { + if (!poolAppendChar(&tempPool, *s)) + return XML_ERROR_NO_MEMORY; + } while (*s++); + } - /* expand the element type name */ - if (elementType->prefix) - { - binding = elementType->prefix->binding; - if (!binding) - return XML_ERROR_UNBOUND_PREFIX; - localPart = tagNamePtr->str; - while (*localPart++ != XML_T(':')) - ; - } - else if (dtd->defaultPrefix.binding) - { - binding = dtd->defaultPrefix.binding; - localPart = tagNamePtr->str; - } - else - return XML_ERROR_NONE; - prefixLen = 0; - if (ns_triplets && binding->prefix->name) - { - for (; binding->prefix->name[prefixLen++];) - ; - } - tagNamePtr->localPart = localPart; - tagNamePtr->uriLen = binding->uriLen; - tagNamePtr->prefix = binding->prefix->name; - tagNamePtr->prefixLen = prefixLen; - for (i = 0; localPart[i++];) - ; - n = i + binding->uriLen + prefixLen; - if (n > binding->uriAlloc) - { - TAG *p; - uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char)); - if (!uri) - return XML_ERROR_NO_MEMORY; - binding->uriAlloc = n + EXPAND_SPARE; - memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char)); - for (p = tagStack; p; p = p->parent) - if (p->name.str == binding->uri) - p->name.str = uri; - FREE(binding->uri); - binding->uri = uri; - } - uri = binding->uri + binding->uriLen; - memcpy(uri, localPart, i * sizeof(XML_Char)); - if (prefixLen) - { - uri = uri + (i - 1); - if (namespaceSeparator) - *uri = namespaceSeparator; - memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char)); - } - tagNamePtr->str = binding->uri; + /* store expanded name in attribute list */ + s = poolStart(&tempPool); + poolFinish(&tempPool); + appAtts[i] = s; + + /* fill empty slot with new version, uriName and hash value */ + nsAtts[j].version = version; + nsAtts[j].hash = uriHash; + nsAtts[j].uriName = s; + + if (!--nPrefixes) + break; + } + else /* not prefixed */ + ((XML_Char *)s)[-1] = 0; /* clear flag */ + } + } + /* clear flags for the remaining attributes */ + for (; i < attIndex; i += 2) + ((XML_Char *)(appAtts[i]))[-1] = 0; + for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) + binding->attId->name[-1] = 0; + + if (!ns) + return XML_ERROR_NONE; + + /* expand the element type name */ + if (elementType->prefix) { + binding = elementType->prefix->binding; + if (!binding) + return XML_ERROR_UNBOUND_PREFIX; + localPart = tagNamePtr->str; + while (*localPart++ != XML_T(':')) + ; + } + else if (dtd->defaultPrefix.binding) { + binding = dtd->defaultPrefix.binding; + localPart = tagNamePtr->str; + } + else return XML_ERROR_NONE; + prefixLen = 0; + if (ns_triplets && binding->prefix->name) { + for (; binding->prefix->name[prefixLen++];) + ; + } + tagNamePtr->localPart = localPart; + tagNamePtr->uriLen = binding->uriLen; + tagNamePtr->prefix = binding->prefix->name; + tagNamePtr->prefixLen = prefixLen; + for (i = 0; localPart[i++];) + ; + n = i + binding->uriLen + prefixLen; + if (n > binding->uriAlloc) { + TAG *p; + uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char)); + if (!uri) + return XML_ERROR_NO_MEMORY; + binding->uriAlloc = n + EXPAND_SPARE; + memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char)); + for (p = tagStack; p; p = p->parent) + if (p->name.str == binding->uri) + p->name.str = uri; + FREE(binding->uri); + binding->uri = uri; + } + uri = binding->uri + binding->uriLen; + memcpy(uri, localPart, i * sizeof(XML_Char)); + if (prefixLen) { + uri = uri + (i - 1); + if (namespaceSeparator) + *uri = namespaceSeparator; + memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char)); + } + tagNamePtr->str = binding->uri; + return XML_ERROR_NONE; } /* addBinding() overwrites the value of prefix->binding without checking. @@ -3119,63 +2921,59 @@ static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr) { - BINDING *b; - int len; - - /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */ - if (*uri == XML_T('\0') && prefix->name) - return XML_ERROR_UNDECLARING_PREFIX; - - for (len = 0; uri[len]; len++) - ; - if (namespaceSeparator) - len++; - if (freeBindingList) - { - b = freeBindingList; - if (len > b->uriAlloc) - { - XML_Char *temp = (XML_Char *)REALLOC(b->uri, - sizeof(XML_Char) * (len + EXPAND_SPARE)); - if (temp == NULL) - return XML_ERROR_NO_MEMORY; - b->uri = temp; - b->uriAlloc = len + EXPAND_SPARE; - } - freeBindingList = b->nextTagBinding; - } - else - { - b = (BINDING *)MALLOC(sizeof(BINDING)); - if (!b) - return XML_ERROR_NO_MEMORY; - b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE)); - if (!b->uri) - { - FREE(b); - return XML_ERROR_NO_MEMORY; - } - b->uriAlloc = len + EXPAND_SPARE; - } - b->uriLen = len; - memcpy(b->uri, uri, len * sizeof(XML_Char)); - if (namespaceSeparator) - b->uri[len - 1] = namespaceSeparator; - b->prefix = prefix; - b->attId = attId; - b->prevPrefixBinding = prefix->binding; - /* NULL binding when default namespace undeclared */ - if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix) - prefix->binding = NULL; - else - prefix->binding = b; - b->nextTagBinding = *bindingsPtr; - *bindingsPtr = b; - /* if attId == NULL then we are not starting a namespace scope */ - if (attId && startNamespaceDeclHandler) - startNamespaceDeclHandler(handlerArg, prefix->name, - prefix->binding ? uri : 0); - return XML_ERROR_NONE; + BINDING *b; + int len; + + /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */ + if (*uri == XML_T('\0') && prefix->name) + return XML_ERROR_UNDECLARING_PREFIX; + + for (len = 0; uri[len]; len++) + ; + if (namespaceSeparator) + len++; + if (freeBindingList) { + b = freeBindingList; + if (len > b->uriAlloc) { + XML_Char *temp = (XML_Char *)REALLOC(b->uri, + sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + b->uri = temp; + b->uriAlloc = len + EXPAND_SPARE; + } + freeBindingList = b->nextTagBinding; + } + else { + b = (BINDING *)MALLOC(sizeof(BINDING)); + if (!b) + return XML_ERROR_NO_MEMORY; + b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (!b->uri) { + FREE(b); + return XML_ERROR_NO_MEMORY; + } + b->uriAlloc = len + EXPAND_SPARE; + } + b->uriLen = len; + memcpy(b->uri, uri, len * sizeof(XML_Char)); + if (namespaceSeparator) + b->uri[len - 1] = namespaceSeparator; + b->prefix = prefix; + b->attId = attId; + b->prevPrefixBinding = prefix->binding; + /* NULL binding when default namespace undeclared */ + if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix) + prefix->binding = NULL; + else + prefix->binding = b; + b->nextTagBinding = *bindingsPtr; + *bindingsPtr = b; + /* if attId == NULL then we are not starting a namespace scope */ + if (attId && startNamespaceDeclHandler) + startNamespaceDeclHandler(handlerArg, prefix->name, + prefix->binding ? uri : 0); + return XML_ERROR_NONE; } /* The idea here is to avoid using stack for each CDATA section when @@ -3187,24 +2985,21 @@ cdataSectionProcessor(XML_Parser parser, const char *end, const char **endPtr) { - enum XML_Error result = doCdataSection(parser, encoding, &start, end, - endPtr, (XML_Bool)!finalBuffer); - if (result != XML_ERROR_NONE) - return result; - if (start) - { - if (parentParser) /* we are parsing an external entity */ - { - processor = externalEntityContentProcessor; - return externalEntityContentProcessor(parser, start, end, endPtr); - } - else - { - processor = contentProcessor; - return contentProcessor(parser, start, end, endPtr); - } - } + enum XML_Error result = doCdataSection(parser, encoding, &start, end, + endPtr, (XML_Bool)!finalBuffer); + if (result != XML_ERROR_NONE) return result; + if (start) { + if (parentParser) { /* we are parsing an external entity */ + processor = externalEntityContentProcessor; + return externalEntityContentProcessor(parser, start, end, endPtr); + } + else { + processor = contentProcessor; + return contentProcessor(parser, start, end, endPtr); + } + } + return result; } /* startPtr gets set to non-null if the section is closed, and to null if @@ -3218,116 +3013,104 @@ doCdataSection(XML_Parser parser, const char **nextPtr, XML_Bool haveMore) { - const char *s = *startPtr; - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) - { - eventPP = &eventPtr; - *eventPP = s; - eventEndPP = &eventEndPtr; - } - else - { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } + const char *s = *startPtr; + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; *eventPP = s; - *startPtr = NULL; - - for (;;) - { - const char *next; - int tok = XmlCdataSectionTok(enc, s, end, &next); - *eventEndPP = next; - switch (tok) - { - case XML_TOK_CDATA_SECT_CLOSE: - if (endCdataSectionHandler) - endCdataSectionHandler(handlerArg); + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + *startPtr = NULL; + + for (;;) { + const char *next; + int tok = XmlCdataSectionTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_CDATA_SECT_CLOSE: + if (endCdataSectionHandler) + endCdataSectionHandler(handlerArg); #if 0 - /* see comment under XML_TOK_CDATA_SECT_OPEN */ - else if (characterDataHandler) - characterDataHandler(handlerArg, dataBuf, 0); + /* see comment under XML_TOK_CDATA_SECT_OPEN */ + else if (characterDataHandler) + characterDataHandler(handlerArg, dataBuf, 0); #endif - else if (defaultHandler) - reportDefault(parser, enc, s, next); - *startPtr = next; - *nextPtr = next; - if (parsing == XML_FINISHED) - return XML_ERROR_ABORTED; - else - return XML_ERROR_NONE; - case XML_TOK_DATA_NEWLINE: - if (characterDataHandler) - { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_DATA_CHARS: - if (characterDataHandler) - { - if (MUST_CONVERT(enc, s)) - { - for (;;) - { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = next; - characterDataHandler(handlerArg, dataBuf, - dataPtr - (ICHAR *)dataBuf); - if (s == next) - break; - *eventPP = s; - } - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)next - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_INVALID: - *eventPP = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (haveMore) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_PARTIAL: - case XML_TOK_NONE: - if (haveMore) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_CDATA_SECTION; - default: - *eventPP = next; - return XML_ERROR_UNEXPECTED_STATE; + else if (defaultHandler) + reportDefault(parser, enc, s, next); + *startPtr = next; + *nextPtr = next; + if (parsing == XML_FINISHED) + return XML_ERROR_ABORTED; + else + return XML_ERROR_NONE; + case XML_TOK_DATA_NEWLINE: + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_DATA_CHARS: + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + for (;;) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = next; + characterDataHandler(handlerArg, dataBuf, + dataPtr - (ICHAR *)dataBuf); + if (s == next) + break; + *eventPP = s; + } } + else + characterDataHandler(handlerArg, + (XML_Char *)s, + (XML_Char *)next - (XML_Char *)s); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_PARTIAL: + case XML_TOK_NONE: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_CDATA_SECTION; + default: + *eventPP = next; + return XML_ERROR_UNEXPECTED_STATE; + } - *eventPP = s = next; - switch (parsing) - { - case XML_SUSPENDED: - *nextPtr = next; - return XML_ERROR_NONE; - case XML_FINISHED: - return XML_ERROR_ABORTED; - default: - ; - } + *eventPP = s = next; + switch (parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: ; } - /* not reached */ + } + /* not reached */ } #ifdef XML_DTD @@ -3341,16 +3124,15 @@ ignoreSectionProcessor(XML_Parser parser, const char *end, const char **endPtr) { - enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, - endPtr, (XML_Bool)!finalBuffer); - if (result != XML_ERROR_NONE) - return result; - if (start) - { - processor = prologProcessor; - return prologProcessor(parser, start, end, endPtr); - } + enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, + endPtr, (XML_Bool)!finalBuffer); + if (result != XML_ERROR_NONE) return result; + if (start) { + processor = prologProcessor; + return prologProcessor(parser, start, end, endPtr); + } + return result; } /* startPtr gets set to non-null is the section is closed, and to null @@ -3364,60 +3146,55 @@ doIgnoreSection(XML_Parser parser, const char **nextPtr, XML_Bool haveMore) { - const char *next; - int tok; - const char *s = *startPtr; - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) - { - eventPP = &eventPtr; - *eventPP = s; - eventEndPP = &eventEndPtr; - } - else - { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } + const char *next; + int tok; + const char *s = *startPtr; + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; *eventPP = s; - *startPtr = NULL; - tok = XmlIgnoreSectionTok(enc, s, end, &next); - *eventEndPP = next; - switch (tok) - { - case XML_TOK_IGNORE_SECT: - if (defaultHandler) - reportDefault(parser, enc, s, next); - *startPtr = next; - *nextPtr = next; - if (parsing == XML_FINISHED) - return XML_ERROR_ABORTED; - else - return XML_ERROR_NONE; - case XML_TOK_INVALID: - *eventPP = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (haveMore) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_PARTIAL: - case XML_TOK_NONE: - if (haveMore) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */ - default: - *eventPP = next; - return XML_ERROR_UNEXPECTED_STATE; - } - /* not reached */ + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + *startPtr = NULL; + tok = XmlIgnoreSectionTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_IGNORE_SECT: + if (defaultHandler) + reportDefault(parser, enc, s, next); + *startPtr = next; + *nextPtr = next; + if (parsing == XML_FINISHED) + return XML_ERROR_ABORTED; + else + return XML_ERROR_NONE; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_PARTIAL: + case XML_TOK_NONE: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */ + default: + *eventPP = next; + return XML_ERROR_UNEXPECTED_STATE; + } + /* not reached */ } #endif /* XML_DTD */ @@ -3425,175 +3202,158 @@ doIgnoreSection(XML_Parser parser, static enum XML_Error initializeEncoding(XML_Parser parser) { - const char *s; + const char *s; #ifdef XML_UNICODE - char encodingBuf[128]; - if (!protocolEncodingName) - s = NULL; - else - { - int i; - for (i = 0; protocolEncodingName[i]; i++) - { - if (i == sizeof(encodingBuf) - 1 - || (protocolEncodingName[i] & ~0x7f) != 0) - { - encodingBuf[0] = '\0'; - break; - } - encodingBuf[i] = (char)protocolEncodingName[i]; - } - encodingBuf[i] = '\0'; - s = encodingBuf; + char encodingBuf[128]; + if (!protocolEncodingName) + s = NULL; + else { + int i; + for (i = 0; protocolEncodingName[i]; i++) { + if (i == sizeof(encodingBuf) - 1 + || (protocolEncodingName[i] & ~0x7f) != 0) { + encodingBuf[0] = '\0'; + break; + } + encodingBuf[i] = (char)protocolEncodingName[i]; } + encodingBuf[i] = '\0'; + s = encodingBuf; + } #else - s = protocolEncodingName; + s = protocolEncodingName; #endif - if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s)) - return XML_ERROR_NONE; - return handleUnknownEncoding(parser, protocolEncodingName); + if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s)) + return XML_ERROR_NONE; + return handleUnknownEncoding(parser, protocolEncodingName); } static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s, const char *next) { - const char *encodingName = NULL; - const XML_Char *storedEncName = NULL; - const ENCODING *newEncoding = NULL; - const char *version = NULL; - const char *versionend; - const XML_Char *storedversion = NULL; - int standalone = -1; - if (!(ns - ? XmlParseXmlDeclNS - : XmlParseXmlDecl)(isGeneralTextEntity, - encoding, - s, - next, - &eventPtr, - &version, - &versionend, - &encodingName, - &newEncoding, - &standalone)) - { - if (isGeneralTextEntity) - return XML_ERROR_TEXT_DECL; - else - return XML_ERROR_XML_DECL; - } - if (!isGeneralTextEntity && standalone == 1) - { - _dtd->standalone = XML_TRUE; + const char *encodingName = NULL; + const XML_Char *storedEncName = NULL; + const ENCODING *newEncoding = NULL; + const char *version = NULL; + const char *versionend; + const XML_Char *storedversion = NULL; + int standalone = -1; + if (!(ns + ? XmlParseXmlDeclNS + : XmlParseXmlDecl)(isGeneralTextEntity, + encoding, + s, + next, + &eventPtr, + &version, + &versionend, + &encodingName, + &newEncoding, + &standalone)) { + if (isGeneralTextEntity) + return XML_ERROR_TEXT_DECL; + else + return XML_ERROR_XML_DECL; + } + if (!isGeneralTextEntity && standalone == 1) { + _dtd->standalone = XML_TRUE; #ifdef XML_DTD - if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE) - paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; + if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE) + paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; #endif /* XML_DTD */ + } + if (xmlDeclHandler) { + if (encodingName != NULL) { + storedEncName = poolStoreString(&temp2Pool, + encoding, + encodingName, + encodingName + + XmlNameLength(encoding, encodingName)); + if (!storedEncName) + return XML_ERROR_NO_MEMORY; + poolFinish(&temp2Pool); + } + if (version) { + storedversion = poolStoreString(&temp2Pool, + encoding, + version, + versionend - encoding->minBytesPerChar); + if (!storedversion) + return XML_ERROR_NO_MEMORY; } - if (xmlDeclHandler) - { - if (encodingName != NULL) - { - storedEncName = poolStoreString(&temp2Pool, - encoding, - encodingName, - encodingName - + XmlNameLength(encoding, encodingName)); - if (!storedEncName) - return XML_ERROR_NO_MEMORY; - poolFinish(&temp2Pool); - } - if (version) - { - storedversion = poolStoreString(&temp2Pool, - encoding, - version, - versionend - encoding->minBytesPerChar); - if (!storedversion) - return XML_ERROR_NO_MEMORY; - } - xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone); + xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone); + } + else if (defaultHandler) + reportDefault(parser, encoding, s, next); + if (protocolEncodingName == NULL) { + if (newEncoding) { + if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) { + eventPtr = encodingName; + return XML_ERROR_INCORRECT_ENCODING; + } + encoding = newEncoding; + } + else if (encodingName) { + enum XML_Error result; + if (!storedEncName) { + storedEncName = poolStoreString( + &temp2Pool, encoding, encodingName, + encodingName + XmlNameLength(encoding, encodingName)); + if (!storedEncName) + return XML_ERROR_NO_MEMORY; + } + result = handleUnknownEncoding(parser, storedEncName); + poolClear(&temp2Pool); + if (result == XML_ERROR_UNKNOWN_ENCODING) + eventPtr = encodingName; + return result; + } + } + + if (storedEncName || storedversion) + poolClear(&temp2Pool); + + return XML_ERROR_NONE; +} + +static enum XML_Error +handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) +{ + if (unknownEncodingHandler) { + XML_Encoding info; + int i; + for (i = 0; i < 256; i++) + info.map[i] = -1; + info.convert = NULL; + info.data = NULL; + info.release = NULL; + if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, + &info)) { + ENCODING *enc; + unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding()); + if (!unknownEncodingMem) { + if (info.release) + info.release(info.data); + return XML_ERROR_NO_MEMORY; + } + enc = (ns + ? XmlInitUnknownEncodingNS + : XmlInitUnknownEncoding)(unknownEncodingMem, + info.map, + info.convert, + info.data); + if (enc) { + unknownEncodingData = info.data; + unknownEncodingRelease = info.release; + encoding = enc; + return XML_ERROR_NONE; + } } - else if (defaultHandler) - reportDefault(parser, encoding, s, next); - if (protocolEncodingName == NULL) - { - if (newEncoding) - { - if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) - { - eventPtr = encodingName; - return XML_ERROR_INCORRECT_ENCODING; - } - encoding = newEncoding; - } - else if (encodingName) - { - enum XML_Error result; - if (!storedEncName) - { - storedEncName = poolStoreString( - &temp2Pool, encoding, encodingName, - encodingName + XmlNameLength(encoding, encodingName)); - if (!storedEncName) - return XML_ERROR_NO_MEMORY; - } - result = handleUnknownEncoding(parser, storedEncName); - poolClear(&temp2Pool); - if (result == XML_ERROR_UNKNOWN_ENCODING) - eventPtr = encodingName; - return result; - } - } - - if (storedEncName || storedversion) - poolClear(&temp2Pool); - - return XML_ERROR_NONE; -} - -static enum XML_Error -handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) -{ - if (unknownEncodingHandler) - { - XML_Encoding info; - int i; - for (i = 0; i < 256; i++) - info.map[i] = -1; - info.convert = NULL; - info.data = NULL; - info.release = NULL; - if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, - &info)) - { - ENCODING *enc; - unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding()); - if (!unknownEncodingMem) - { - if (info.release) - info.release(info.data); - return XML_ERROR_NO_MEMORY; - } - enc = (ns - ? XmlInitUnknownEncodingNS - : XmlInitUnknownEncoding)(unknownEncodingMem, - info.map, - info.convert, - info.data); - if (enc) - { - unknownEncodingData = info.data; - unknownEncodingRelease = info.release; - encoding = enc; - return XML_ERROR_NONE; - } - } - if (info.release != NULL) - info.release(info.data); - } - return XML_ERROR_UNKNOWN_ENCODING; + if (info.release != NULL) + info.release(info.data); + } + return XML_ERROR_UNKNOWN_ENCODING; } static enum XML_Error PTRCALL @@ -3602,11 +3362,11 @@ prologInitProcessor(XML_Parser parser, const char *end, const char **nextPtr) { - enum XML_Error result = initializeEncoding(parser); - if (result != XML_ERROR_NONE) - return result; - processor = prologProcessor; - return prologProcessor(parser, s, end, nextPtr); + enum XML_Error result = initializeEncoding(parser); + if (result != XML_ERROR_NONE) + return result; + processor = prologProcessor; + return prologProcessor(parser, s, end, nextPtr); } #ifdef XML_DTD @@ -3617,24 +3377,22 @@ externalParEntInitProcessor(XML_Parser parser, const char *end, const char **nextPtr) { - enum XML_Error result = initializeEncoding(parser); - if (result != XML_ERROR_NONE) - return result; + enum XML_Error result = initializeEncoding(parser); + if (result != XML_ERROR_NONE) + return result; - /* we know now that XML_Parse(Buffer) has been called, - so we consider the external parameter entity read */ - _dtd->paramEntityRead = XML_TRUE; + /* we know now that XML_Parse(Buffer) has been called, + so we consider the external parameter entity read */ + _dtd->paramEntityRead = XML_TRUE; - if (prologState.inEntityValue) - { - processor = entityValueInitProcessor; - return entityValueInitProcessor(parser, s, end, nextPtr); - } - else - { - processor = externalParEntProcessor; - return externalParEntProcessor(parser, s, end, nextPtr); - } + if (prologState.inEntityValue) { + processor = entityValueInitProcessor; + return entityValueInitProcessor(parser, s, end, nextPtr); + } + else { + processor = externalParEntProcessor; + return externalParEntProcessor(parser, s, end, nextPtr); + } } static enum XML_Error PTRCALL @@ -3643,72 +3401,65 @@ entityValueInitProcessor(XML_Parser parser, const char *end, const char **nextPtr) { - int tok; - const char *start = s; - const char *next = start; - eventPtr = start; + int tok; + const char *start = s; + const char *next = start; + eventPtr = start; - for (;;) - { - tok = XmlPrologTok(encoding, start, end, &next); - eventEndPtr = next; - if (tok <= 0) - { - if (!finalBuffer && tok != XML_TOK_INVALID) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - switch (tok) - { - case XML_TOK_INVALID: - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_NONE: /* start == end */ - default: - break; - } - /* found end of entity value - can store it now */ - return storeEntityValue(parser, encoding, s, end); - } - else if (tok == XML_TOK_XML_DECL) - { - enum XML_Error result; - result = processXmlDecl(parser, 0, start, next); - if (result != XML_ERROR_NONE) - return result; - switch (parsing) - { - case XML_SUSPENDED: - *nextPtr = next; - return XML_ERROR_NONE; - case XML_FINISHED: - return XML_ERROR_ABORTED; - default: - *nextPtr = next; - } - /* stop scanning for text declaration - we found one */ - processor = entityValueProcessor; - return entityValueProcessor(parser, next, end, nextPtr); - } - /* If we are at the end of the buffer, this would cause XmlPrologTok to - return XML_TOK_NONE on the next call, which would then cause the - function to exit with *nextPtr set to s - that is what we want for other - tokens, but not for the BOM - we would rather like to skip it; - then, when this routine is entered the next time, XmlPrologTok will - return XML_TOK_INVALID, since the BOM is still in the buffer - */ - else if (tok == XML_TOK_BOM && next == end && !finalBuffer) - { - *nextPtr = next; - return XML_ERROR_NONE; - } - start = next; - eventPtr = start; + for (;;) { + tok = XmlPrologTok(encoding, start, end, &next); + eventEndPtr = next; + if (tok <= 0) { + if (!finalBuffer && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: /* start == end */ + default: + break; + } + /* found end of entity value - can store it now */ + return storeEntityValue(parser, encoding, s, end); + } + else if (tok == XML_TOK_XML_DECL) { + enum XML_Error result; + result = processXmlDecl(parser, 0, start, next); + if (result != XML_ERROR_NONE) + return result; + switch (parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: + *nextPtr = next; + } + /* stop scanning for text declaration - we found one */ + processor = entityValueProcessor; + return entityValueProcessor(parser, next, end, nextPtr); + } + /* If we are at the end of the buffer, this would cause XmlPrologTok to + return XML_TOK_NONE on the next call, which would then cause the + function to exit with *nextPtr set to s - that is what we want for other + tokens, but not for the BOM - we would rather like to skip it; + then, when this routine is entered the next time, XmlPrologTok will + return XML_TOK_INVALID, since the BOM is still in the buffer + */ + else if (tok == XML_TOK_BOM && next == end && !finalBuffer) { + *nextPtr = next; + return XML_ERROR_NONE; } + start = next; + eventPtr = start; + } } static enum XML_Error PTRCALL @@ -3717,43 +3468,39 @@ externalParEntProcessor(XML_Parser parser, const char *end, const char **nextPtr) { - const char *next = s; - int tok; + const char *next = s; + int tok; - tok = XmlPrologTok(encoding, s, end, &next); - if (tok <= 0) - { - if (!finalBuffer && tok != XML_TOK_INVALID) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - switch (tok) - { - case XML_TOK_INVALID: - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_NONE: /* start == end */ - default: - break; - } - } - /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM. - However, when parsing an external subset, doProlog will not accept a BOM - as valid, and report a syntax error, so we have to skip the BOM - */ - else if (tok == XML_TOK_BOM) - { - s = next; - tok = XmlPrologTok(encoding, s, end, &next); + tok = XmlPrologTok(encoding, s, end, &next); + if (tok <= 0) { + if (!finalBuffer && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; } + switch (tok) { + case XML_TOK_INVALID: + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: /* start == end */ + default: + break; + } + } + /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM. + However, when parsing an external subset, doProlog will not accept a BOM + as valid, and report a syntax error, so we have to skip the BOM + */ + else if (tok == XML_TOK_BOM) { + s = next; + tok = XmlPrologTok(encoding, s, end, &next); + } - processor = prologProcessor; - return doProlog(parser, encoding, s, end, tok, next, - nextPtr, (XML_Bool)!finalBuffer); + processor = prologProcessor; + return doProlog(parser, encoding, s, end, tok, next, + nextPtr, (XML_Bool)!finalBuffer); } static enum XML_Error PTRCALL @@ -3762,38 +3509,34 @@ entityValueProcessor(XML_Parser parser, const char *end, const char **nextPtr) { - const char *start = s; - const char *next = s; - const ENCODING *enc = encoding; - int tok; + const char *start = s; + const char *next = s; + const ENCODING *enc = encoding; + int tok; - for (;;) - { - tok = XmlPrologTok(enc, start, end, &next); - if (tok <= 0) - { - if (!finalBuffer && tok != XML_TOK_INVALID) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - switch (tok) - { - case XML_TOK_INVALID: - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_NONE: /* start == end */ - default: - break; - } - /* found end of entity value - can store it now */ - return storeEntityValue(parser, enc, s, end); - } - start = next; + for (;;) { + tok = XmlPrologTok(enc, start, end, &next); + if (tok <= 0) { + if (!finalBuffer && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: /* start == end */ + default: + break; + } + /* found end of entity value - can store it now */ + return storeEntityValue(parser, enc, s, end); } + start = next; + } } #endif /* XML_DTD */ @@ -3804,10 +3547,10 @@ prologProcessor(XML_Parser parser, const char *end, const char **nextPtr) { - const char *next = s; - int tok = XmlPrologTok(encoding, s, end, &next); - return doProlog(parser, encoding, s, end, tok, next, - nextPtr, (XML_Bool)!finalBuffer); + const char *next = s; + int tok = XmlPrologTok(encoding, s, end, &next); + return doProlog(parser, encoding, s, end, tok, next, + nextPtr, (XML_Bool)!finalBuffer); } static enum XML_Error @@ -3821,1172 +3564,1075 @@ doProlog(XML_Parser parser, XML_Bool haveMore) { #ifdef XML_DTD - static const XML_Char externalSubsetName[] = { '#' , '\0' }; + static const XML_Char externalSubsetName[] = { '#' , '\0' }; #endif /* XML_DTD */ - static const XML_Char atypeCDATA[] = { 'C', 'D', 'A', 'T', 'A', '\0' }; - static const XML_Char atypeID[] = { 'I', 'D', '\0' }; - static const XML_Char atypeIDREF[] = { 'I', 'D', 'R', 'E', 'F', '\0' }; - static const XML_Char atypeIDREFS[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' }; - static const XML_Char atypeENTITY[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' }; - static const XML_Char atypeENTITIES[] = - { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' }; - static const XML_Char atypeNMTOKEN[] = - { - 'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' - }; - static const XML_Char atypeNMTOKENS[] = - { - 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' - }; - static const XML_Char notationPrefix[] = - { - 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' - }; - static const XML_Char enumValueSep[] = { '|', '\0' }; - static const XML_Char enumValueStart[] = { '(', '\0' }; - - /* save one level of indirection */ - DTD * const dtd = _dtd; - - const char **eventPP; - const char **eventEndPP; - enum XML_Content_Quant quant; - - if (enc == encoding) - { - eventPP = &eventPtr; - eventEndPP = &eventEndPtr; - } - else - { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - - for (;;) - { - int role; - XML_Bool handleDefault = XML_TRUE; - *eventPP = s; - *eventEndPP = next; - if (tok <= 0) - { - if (haveMore && tok != XML_TOK_INVALID) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - switch (tok) - { - case XML_TOK_INVALID: - *eventPP = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_NONE: + static const XML_Char atypeCDATA[] = { 'C', 'D', 'A', 'T', 'A', '\0' }; + static const XML_Char atypeID[] = { 'I', 'D', '\0' }; + static const XML_Char atypeIDREF[] = { 'I', 'D', 'R', 'E', 'F', '\0' }; + static const XML_Char atypeIDREFS[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' }; + static const XML_Char atypeENTITY[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' }; + static const XML_Char atypeENTITIES[] = + { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' }; + static const XML_Char atypeNMTOKEN[] = { + 'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' }; + static const XML_Char atypeNMTOKENS[] = { + 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' }; + static const XML_Char notationPrefix[] = { + 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' }; + static const XML_Char enumValueSep[] = { '|', '\0' }; + static const XML_Char enumValueStart[] = { '(', '\0' }; + + /* save one level of indirection */ + DTD * const dtd = _dtd; + + const char **eventPP; + const char **eventEndPP; + enum XML_Content_Quant quant; + + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + + for (;;) { + int role; + XML_Bool handleDefault = XML_TRUE; + *eventPP = s; + *eventEndPP = next; + if (tok <= 0) { + if (haveMore && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: #ifdef XML_DTD - /* for internal PE NOT referenced between declarations */ - if (enc != encoding && !openInternalEntities->betweenDecl) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - /* WFC: PE Between Declarations - must check that PE contains - complete markup, not only for external PEs, but also for - internal PEs if the reference occurs between declarations. - */ - if (isParamEntity || enc != encoding) - { - if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc) - == XML_ROLE_ERROR) - return XML_ERROR_INCOMPLETE_PE; - *nextPtr = s; - return XML_ERROR_NONE; - } -#endif /* XML_DTD */ - return XML_ERROR_NO_ELEMENTS; - default: - tok = -tok; - next = end; - break; - } + /* for internal PE NOT referenced between declarations */ + if (enc != encoding && !openInternalEntities->betweenDecl) { + *nextPtr = s; + return XML_ERROR_NONE; } - role = XmlTokenRole(&prologState, tok, s, next, enc); - switch (role) - { - case XML_ROLE_XML_DECL: - { - enum XML_Error result = processXmlDecl(parser, 0, s, next); - if (result != XML_ERROR_NONE) - return result; - enc = encoding; - handleDefault = XML_FALSE; + /* WFC: PE Between Declarations - must check that PE contains + complete markup, not only for external PEs, but also for + internal PEs if the reference occurs between declarations. + */ + if (isParamEntity || enc != encoding) { + if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc) + == XML_ROLE_ERROR) + return XML_ERROR_INCOMPLETE_PE; + *nextPtr = s; + return XML_ERROR_NONE; } +#endif /* XML_DTD */ + return XML_ERROR_NO_ELEMENTS; + default: + tok = -tok; + next = end; break; - case XML_ROLE_DOCTYPE_NAME: - if (startDoctypeDeclHandler) - { - doctypeName = poolStoreString(&tempPool, enc, s, next); - if (!doctypeName) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - doctypePubid = NULL; - handleDefault = XML_FALSE; - } - doctypeSysid = NULL; /* always initialize to NULL */ - break; - case XML_ROLE_DOCTYPE_INTERNAL_SUBSET: - if (startDoctypeDeclHandler) - { - startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid, - doctypePubid, 1); - doctypeName = NULL; - poolClear(&tempPool); - handleDefault = XML_FALSE; - } - break; + } + } + role = XmlTokenRole(&prologState, tok, s, next, enc); + switch (role) { + case XML_ROLE_XML_DECL: + { + enum XML_Error result = processXmlDecl(parser, 0, s, next); + if (result != XML_ERROR_NONE) + return result; + enc = encoding; + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_DOCTYPE_NAME: + if (startDoctypeDeclHandler) { + doctypeName = poolStoreString(&tempPool, enc, s, next); + if (!doctypeName) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + doctypePubid = NULL; + handleDefault = XML_FALSE; + } + doctypeSysid = NULL; /* always initialize to NULL */ + break; + case XML_ROLE_DOCTYPE_INTERNAL_SUBSET: + if (startDoctypeDeclHandler) { + startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid, + doctypePubid, 1); + doctypeName = NULL; + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + break; #ifdef XML_DTD - case XML_ROLE_TEXT_DECL: - { - enum XML_Error result = processXmlDecl(parser, 1, s, next); - if (result != XML_ERROR_NONE) - return result; - enc = encoding; - handleDefault = XML_FALSE; - } - break; + case XML_ROLE_TEXT_DECL: + { + enum XML_Error result = processXmlDecl(parser, 1, s, next); + if (result != XML_ERROR_NONE) + return result; + enc = encoding; + handleDefault = XML_FALSE; + } + break; #endif /* XML_DTD */ - case XML_ROLE_DOCTYPE_PUBLIC_ID: + case XML_ROLE_DOCTYPE_PUBLIC_ID: #ifdef XML_DTD - useForeignDTD = XML_FALSE; - declEntity = (ENTITY *)lookup(&dtd->paramEntities, - externalSubsetName, - sizeof(ENTITY)); - if (!declEntity) - return XML_ERROR_NO_MEMORY; + useForeignDTD = XML_FALSE; + declEntity = (ENTITY *)lookup(&dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; #endif /* XML_DTD */ - dtd->hasParamEntityRefs = XML_TRUE; - if (startDoctypeDeclHandler) - { - if (!XmlIsPublicId(enc, s, next, eventPP)) - return XML_ERROR_PUBLICID; - doctypePubid = poolStoreString(&tempPool, enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!doctypePubid) - return XML_ERROR_NO_MEMORY; - normalizePublicId((XML_Char *)doctypePubid); - poolFinish(&tempPool); - handleDefault = XML_FALSE; - goto alreadyChecked; - } - /* fall through */ - case XML_ROLE_ENTITY_PUBLIC_ID: - if (!XmlIsPublicId(enc, s, next, eventPP)) - return XML_ERROR_PUBLICID; -alreadyChecked: - if (dtd->keepProcessing && declEntity) - { - XML_Char *tem = poolStoreString(&dtd->pool, - enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!tem) - return XML_ERROR_NO_MEMORY; - normalizePublicId(tem); - declEntity->publicId = tem; - poolFinish(&dtd->pool); - if (entityDeclHandler) - handleDefault = XML_FALSE; - } - break; - case XML_ROLE_DOCTYPE_CLOSE: - if (doctypeName) - { - startDoctypeDeclHandler(handlerArg, doctypeName, - doctypeSysid, doctypePubid, 0); - poolClear(&tempPool); - handleDefault = XML_FALSE; - } - /* doctypeSysid will be non-NULL in the case of a previous - XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler - was not set, indicating an external subset - */ + dtd->hasParamEntityRefs = XML_TRUE; + if (startDoctypeDeclHandler) { + if (!XmlIsPublicId(enc, s, next, eventPP)) + return XML_ERROR_PUBLICID; + doctypePubid = poolStoreString(&tempPool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!doctypePubid) + return XML_ERROR_NO_MEMORY; + normalizePublicId((XML_Char *)doctypePubid); + poolFinish(&tempPool); + handleDefault = XML_FALSE; + goto alreadyChecked; + } + /* fall through */ + case XML_ROLE_ENTITY_PUBLIC_ID: + if (!XmlIsPublicId(enc, s, next, eventPP)) + return XML_ERROR_PUBLICID; + alreadyChecked: + if (dtd->keepProcessing && declEntity) { + XML_Char *tem = poolStoreString(&dtd->pool, + enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!tem) + return XML_ERROR_NO_MEMORY; + normalizePublicId(tem); + declEntity->publicId = tem; + poolFinish(&dtd->pool); + if (entityDeclHandler) + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_DOCTYPE_CLOSE: + if (doctypeName) { + startDoctypeDeclHandler(handlerArg, doctypeName, + doctypeSysid, doctypePubid, 0); + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + /* doctypeSysid will be non-NULL in the case of a previous + XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler + was not set, indicating an external subset + */ #ifdef XML_DTD - if (doctypeSysid || useForeignDTD) - { - dtd->hasParamEntityRefs = XML_TRUE; /* when docTypeSysid == NULL */ - if (paramEntityParsing && externalEntityRefHandler) - { - ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, - externalSubsetName, - sizeof(ENTITY)); - if (!entity) - return XML_ERROR_NO_MEMORY; - if (useForeignDTD) - entity->base = curBase; - dtd->paramEntityRead = XML_FALSE; - if (!externalEntityRefHandler(externalEntityRefHandlerArg, - 0, - entity->base, - entity->systemId, - entity->publicId)) - return XML_ERROR_EXTERNAL_ENTITY_HANDLING; - if (dtd->paramEntityRead && - !dtd->standalone && - notStandaloneHandler && - !notStandaloneHandler(handlerArg)) - return XML_ERROR_NOT_STANDALONE; - /* end of DTD - no need to update dtd->keepProcessing */ - } - useForeignDTD = XML_FALSE; - } + if (doctypeSysid || useForeignDTD) { + dtd->hasParamEntityRefs = XML_TRUE; /* when docTypeSysid == NULL */ + if (paramEntityParsing && externalEntityRefHandler) { + ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!entity) + return XML_ERROR_NO_MEMORY; + if (useForeignDTD) + entity->base = curBase; + dtd->paramEntityRead = XML_FALSE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + if (dtd->paramEntityRead && + !dtd->standalone && + notStandaloneHandler && + !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + /* end of DTD - no need to update dtd->keepProcessing */ + } + useForeignDTD = XML_FALSE; + } #endif /* XML_DTD */ - if (endDoctypeDeclHandler) - { - endDoctypeDeclHandler(handlerArg); - handleDefault = XML_FALSE; - } - break; - case XML_ROLE_INSTANCE_START: + if (endDoctypeDeclHandler) { + endDoctypeDeclHandler(handlerArg); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_INSTANCE_START: #ifdef XML_DTD - /* if there is no DOCTYPE declaration then now is the - last chance to read the foreign DTD - */ - if (useForeignDTD) - { - dtd->hasParamEntityRefs = XML_TRUE; - if (paramEntityParsing && externalEntityRefHandler) - { - ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, - externalSubsetName, - sizeof(ENTITY)); - if (!entity) - return XML_ERROR_NO_MEMORY; - entity->base = curBase; - dtd->paramEntityRead = XML_FALSE; - if (!externalEntityRefHandler(externalEntityRefHandlerArg, - 0, - entity->base, - entity->systemId, - entity->publicId)) - return XML_ERROR_EXTERNAL_ENTITY_HANDLING; - if (dtd->paramEntityRead && - !dtd->standalone && - notStandaloneHandler && - !notStandaloneHandler(handlerArg)) - return XML_ERROR_NOT_STANDALONE; - /* end of DTD - no need to update dtd->keepProcessing */ - } - } + /* if there is no DOCTYPE declaration then now is the + last chance to read the foreign DTD + */ + if (useForeignDTD) { + dtd->hasParamEntityRefs = XML_TRUE; + if (paramEntityParsing && externalEntityRefHandler) { + ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!entity) + return XML_ERROR_NO_MEMORY; + entity->base = curBase; + dtd->paramEntityRead = XML_FALSE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + if (dtd->paramEntityRead && + !dtd->standalone && + notStandaloneHandler && + !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + /* end of DTD - no need to update dtd->keepProcessing */ + } + } #endif /* XML_DTD */ - processor = contentProcessor; - return contentProcessor(parser, s, end, nextPtr); - case XML_ROLE_ATTLIST_ELEMENT_NAME: - declElementType = getElementType(parser, enc, s, next); - if (!declElementType) - return XML_ERROR_NO_MEMORY; - goto checkAttListDeclHandler; - case XML_ROLE_ATTRIBUTE_NAME: - declAttributeId = getAttributeId(parser, enc, s, next); - if (!declAttributeId) - return XML_ERROR_NO_MEMORY; - declAttributeIsCdata = XML_FALSE; - declAttributeType = NULL; - declAttributeIsId = XML_FALSE; - goto checkAttListDeclHandler; - case XML_ROLE_ATTRIBUTE_TYPE_CDATA: - declAttributeIsCdata = XML_TRUE; - declAttributeType = atypeCDATA; - goto checkAttListDeclHandler; - case XML_ROLE_ATTRIBUTE_TYPE_ID: - declAttributeIsId = XML_TRUE; - declAttributeType = atypeID; - goto checkAttListDeclHandler; - case XML_ROLE_ATTRIBUTE_TYPE_IDREF: - declAttributeType = atypeIDREF; - goto checkAttListDeclHandler; - case XML_ROLE_ATTRIBUTE_TYPE_IDREFS: - declAttributeType = atypeIDREFS; - goto checkAttListDeclHandler; - case XML_ROLE_ATTRIBUTE_TYPE_ENTITY: - declAttributeType = atypeENTITY; - goto checkAttListDeclHandler; - case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES: - declAttributeType = atypeENTITIES; - goto checkAttListDeclHandler; - case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN: - declAttributeType = atypeNMTOKEN; - goto checkAttListDeclHandler; - case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS: - declAttributeType = atypeNMTOKENS; -checkAttListDeclHandler: - if (dtd->keepProcessing && attlistDeclHandler) - handleDefault = XML_FALSE; - break; - case XML_ROLE_ATTRIBUTE_ENUM_VALUE: - case XML_ROLE_ATTRIBUTE_NOTATION_VALUE: - if (dtd->keepProcessing && attlistDeclHandler) - { - const XML_Char *prefix; - if (declAttributeType) - { - prefix = enumValueSep; - } - else - { - prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE - ? notationPrefix - : enumValueStart); - } - if (!poolAppendString(&tempPool, prefix)) - return XML_ERROR_NO_MEMORY; - if (!poolAppend(&tempPool, enc, s, next)) - return XML_ERROR_NO_MEMORY; - declAttributeType = tempPool.start; - handleDefault = XML_FALSE; - } - break; - case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: - case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: - if (dtd->keepProcessing) - { - if (!defineAttribute(declElementType, declAttributeId, - declAttributeIsCdata, declAttributeIsId, - 0, parser)) - return XML_ERROR_NO_MEMORY; - if (attlistDeclHandler && declAttributeType) - { - if (*declAttributeType == XML_T('(') - || (*declAttributeType == XML_T('N') - && declAttributeType[1] == XML_T('O'))) - { - /* Enumerated or Notation type */ - if (!poolAppendChar(&tempPool, XML_T(')')) - || !poolAppendChar(&tempPool, XML_T('\0'))) - return XML_ERROR_NO_MEMORY; - declAttributeType = tempPool.start; - poolFinish(&tempPool); - } - *eventEndPP = s; - attlistDeclHandler(handlerArg, declElementType->name, - declAttributeId->name, declAttributeType, - 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE); - poolClear(&tempPool); - handleDefault = XML_FALSE; - } - } - break; - case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: - case XML_ROLE_FIXED_ATTRIBUTE_VALUE: - if (dtd->keepProcessing) - { - const XML_Char *attVal; - enum XML_Error result = - storeAttributeValue(parser, enc, declAttributeIsCdata, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar, - &dtd->pool); - if (result) - return result; - attVal = poolStart(&dtd->pool); - poolFinish(&dtd->pool); - /* ID attributes aren't allowed to have a default */ - if (!defineAttribute(declElementType, declAttributeId, - declAttributeIsCdata, XML_FALSE, attVal, parser)) - return XML_ERROR_NO_MEMORY; - if (attlistDeclHandler && declAttributeType) - { - if (*declAttributeType == XML_T('(') - || (*declAttributeType == XML_T('N') - && declAttributeType[1] == XML_T('O'))) - { - /* Enumerated or Notation type */ - if (!poolAppendChar(&tempPool, XML_T(')')) - || !poolAppendChar(&tempPool, XML_T('\0'))) - return XML_ERROR_NO_MEMORY; - declAttributeType = tempPool.start; - poolFinish(&tempPool); - } - *eventEndPP = s; - attlistDeclHandler(handlerArg, declElementType->name, - declAttributeId->name, declAttributeType, - attVal, - role == XML_ROLE_FIXED_ATTRIBUTE_VALUE); - poolClear(&tempPool); - handleDefault = XML_FALSE; - } - } - break; - case XML_ROLE_ENTITY_VALUE: - if (dtd->keepProcessing) - { - enum XML_Error result = storeEntityValue(parser, enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (declEntity) - { - declEntity->textPtr = poolStart(&dtd->entityValuePool); - declEntity->textLen = poolLength(&dtd->entityValuePool); - poolFinish(&dtd->entityValuePool); - if (entityDeclHandler) - { - *eventEndPP = s; - entityDeclHandler(handlerArg, - declEntity->name, - declEntity->is_param, - declEntity->textPtr, - declEntity->textLen, - curBase, 0, 0, 0); - handleDefault = XML_FALSE; - } - } - else - poolDiscard(&dtd->entityValuePool); - if (result != XML_ERROR_NONE) - return result; - } - break; - case XML_ROLE_DOCTYPE_SYSTEM_ID: + processor = contentProcessor; + return contentProcessor(parser, s, end, nextPtr); + case XML_ROLE_ATTLIST_ELEMENT_NAME: + declElementType = getElementType(parser, enc, s, next); + if (!declElementType) + return XML_ERROR_NO_MEMORY; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_NAME: + declAttributeId = getAttributeId(parser, enc, s, next); + if (!declAttributeId) + return XML_ERROR_NO_MEMORY; + declAttributeIsCdata = XML_FALSE; + declAttributeType = NULL; + declAttributeIsId = XML_FALSE; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_CDATA: + declAttributeIsCdata = XML_TRUE; + declAttributeType = atypeCDATA; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_ID: + declAttributeIsId = XML_TRUE; + declAttributeType = atypeID; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_IDREF: + declAttributeType = atypeIDREF; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_IDREFS: + declAttributeType = atypeIDREFS; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_ENTITY: + declAttributeType = atypeENTITY; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES: + declAttributeType = atypeENTITIES; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN: + declAttributeType = atypeNMTOKEN; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS: + declAttributeType = atypeNMTOKENS; + checkAttListDeclHandler: + if (dtd->keepProcessing && attlistDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ATTRIBUTE_ENUM_VALUE: + case XML_ROLE_ATTRIBUTE_NOTATION_VALUE: + if (dtd->keepProcessing && attlistDeclHandler) { + const XML_Char *prefix; + if (declAttributeType) { + prefix = enumValueSep; + } + else { + prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE + ? notationPrefix + : enumValueStart); + } + if (!poolAppendString(&tempPool, prefix)) + return XML_ERROR_NO_MEMORY; + if (!poolAppend(&tempPool, enc, s, next)) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: + case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: + if (dtd->keepProcessing) { + if (!defineAttribute(declElementType, declAttributeId, + declAttributeIsCdata, declAttributeIsId, + 0, parser)) + return XML_ERROR_NO_MEMORY; + if (attlistDeclHandler && declAttributeType) { + if (*declAttributeType == XML_T('(') + || (*declAttributeType == XML_T('N') + && declAttributeType[1] == XML_T('O'))) { + /* Enumerated or Notation type */ + if (!poolAppendChar(&tempPool, XML_T(')')) + || !poolAppendChar(&tempPool, XML_T('\0'))) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + poolFinish(&tempPool); + } + *eventEndPP = s; + attlistDeclHandler(handlerArg, declElementType->name, + declAttributeId->name, declAttributeType, + 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE); + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + } + break; + case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: + case XML_ROLE_FIXED_ATTRIBUTE_VALUE: + if (dtd->keepProcessing) { + const XML_Char *attVal; + enum XML_Error result = + storeAttributeValue(parser, enc, declAttributeIsCdata, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar, + &dtd->pool); + if (result) + return result; + attVal = poolStart(&dtd->pool); + poolFinish(&dtd->pool); + /* ID attributes aren't allowed to have a default */ + if (!defineAttribute(declElementType, declAttributeId, + declAttributeIsCdata, XML_FALSE, attVal, parser)) + return XML_ERROR_NO_MEMORY; + if (attlistDeclHandler && declAttributeType) { + if (*declAttributeType == XML_T('(') + || (*declAttributeType == XML_T('N') + && declAttributeType[1] == XML_T('O'))) { + /* Enumerated or Notation type */ + if (!poolAppendChar(&tempPool, XML_T(')')) + || !poolAppendChar(&tempPool, XML_T('\0'))) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + poolFinish(&tempPool); + } + *eventEndPP = s; + attlistDeclHandler(handlerArg, declElementType->name, + declAttributeId->name, declAttributeType, + attVal, + role == XML_ROLE_FIXED_ATTRIBUTE_VALUE); + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + } + break; + case XML_ROLE_ENTITY_VALUE: + if (dtd->keepProcessing) { + enum XML_Error result = storeEntityValue(parser, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (declEntity) { + declEntity->textPtr = poolStart(&dtd->entityValuePool); + declEntity->textLen = poolLength(&dtd->entityValuePool); + poolFinish(&dtd->entityValuePool); + if (entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + declEntity->is_param, + declEntity->textPtr, + declEntity->textLen, + curBase, 0, 0, 0); + handleDefault = XML_FALSE; + } + } + else + poolDiscard(&dtd->entityValuePool); + if (result != XML_ERROR_NONE) + return result; + } + break; + case XML_ROLE_DOCTYPE_SYSTEM_ID: #ifdef XML_DTD - useForeignDTD = XML_FALSE; + useForeignDTD = XML_FALSE; #endif /* XML_DTD */ - dtd->hasParamEntityRefs = XML_TRUE; - if (startDoctypeDeclHandler) - { - doctypeSysid = poolStoreString(&tempPool, enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (doctypeSysid == NULL) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - handleDefault = XML_FALSE; - } + dtd->hasParamEntityRefs = XML_TRUE; + if (startDoctypeDeclHandler) { + doctypeSysid = poolStoreString(&tempPool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (doctypeSysid == NULL) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + handleDefault = XML_FALSE; + } #ifdef XML_DTD - else - /* use externalSubsetName to make doctypeSysid non-NULL - for the case where no startDoctypeDeclHandler is set */ - doctypeSysid = externalSubsetName; + else + /* use externalSubsetName to make doctypeSysid non-NULL + for the case where no startDoctypeDeclHandler is set */ + doctypeSysid = externalSubsetName; #endif /* XML_DTD */ - if (!dtd->standalone + if (!dtd->standalone #ifdef XML_DTD - && !paramEntityParsing + && !paramEntityParsing #endif /* XML_DTD */ - && notStandaloneHandler - && !notStandaloneHandler(handlerArg)) - return XML_ERROR_NOT_STANDALONE; + && notStandaloneHandler + && !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; #ifndef XML_DTD - break; + break; #else /* XML_DTD */ - if (!declEntity) - { - declEntity = (ENTITY *)lookup(&dtd->paramEntities, - externalSubsetName, - sizeof(ENTITY)); - if (!declEntity) - return XML_ERROR_NO_MEMORY; - declEntity->publicId = NULL; - } - /* fall through */ + if (!declEntity) { + declEntity = (ENTITY *)lookup(&dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; + declEntity->publicId = NULL; + } + /* fall through */ #endif /* XML_DTD */ - case XML_ROLE_ENTITY_SYSTEM_ID: - if (dtd->keepProcessing && declEntity) - { - declEntity->systemId = poolStoreString(&dtd->pool, enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!declEntity->systemId) - return XML_ERROR_NO_MEMORY; - declEntity->base = curBase; - poolFinish(&dtd->pool); - if (entityDeclHandler) - handleDefault = XML_FALSE; - } - break; - case XML_ROLE_ENTITY_COMPLETE: - if (dtd->keepProcessing && declEntity && entityDeclHandler) - { - *eventEndPP = s; - entityDeclHandler(handlerArg, - declEntity->name, - declEntity->is_param, - 0,0, - declEntity->base, - declEntity->systemId, - declEntity->publicId, - 0); - handleDefault = XML_FALSE; - } - break; - case XML_ROLE_ENTITY_NOTATION_NAME: - if (dtd->keepProcessing && declEntity) - { - declEntity->notation = poolStoreString(&dtd->pool, enc, s, next); - if (!declEntity->notation) - return XML_ERROR_NO_MEMORY; - poolFinish(&dtd->pool); - if (unparsedEntityDeclHandler) - { - *eventEndPP = s; - unparsedEntityDeclHandler(handlerArg, - declEntity->name, - declEntity->base, - declEntity->systemId, - declEntity->publicId, - declEntity->notation); - handleDefault = XML_FALSE; - } - else if (entityDeclHandler) - { - *eventEndPP = s; - entityDeclHandler(handlerArg, - declEntity->name, - 0,0,0, - declEntity->base, - declEntity->systemId, - declEntity->publicId, - declEntity->notation); - handleDefault = XML_FALSE; - } - } - break; - case XML_ROLE_GENERAL_ENTITY_NAME: - { - if (XmlPredefinedEntityName(enc, s, next)) - { - declEntity = NULL; - break; - } - if (dtd->keepProcessing) - { - const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); - if (!name) - return XML_ERROR_NO_MEMORY; - declEntity = (ENTITY *)lookup(&dtd->generalEntities, name, - sizeof(ENTITY)); - if (!declEntity) - return XML_ERROR_NO_MEMORY; - if (declEntity->name != name) - { - poolDiscard(&dtd->pool); - declEntity = NULL; - } - else - { - poolFinish(&dtd->pool); - declEntity->publicId = NULL; - declEntity->is_param = XML_FALSE; - /* if we have a parent parser or are reading an internal parameter - entity, then the entity declaration is not considered "internal" - */ - declEntity->is_internal = !(parentParser || openInternalEntities); - if (entityDeclHandler) - handleDefault = XML_FALSE; - } - } - else - { - poolDiscard(&dtd->pool); - declEntity = NULL; - } + case XML_ROLE_ENTITY_SYSTEM_ID: + if (dtd->keepProcessing && declEntity) { + declEntity->systemId = poolStoreString(&dtd->pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!declEntity->systemId) + return XML_ERROR_NO_MEMORY; + declEntity->base = curBase; + poolFinish(&dtd->pool); + if (entityDeclHandler) + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_ENTITY_COMPLETE: + if (dtd->keepProcessing && declEntity && entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + declEntity->is_param, + 0,0, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + 0); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_ENTITY_NOTATION_NAME: + if (dtd->keepProcessing && declEntity) { + declEntity->notation = poolStoreString(&dtd->pool, enc, s, next); + if (!declEntity->notation) + return XML_ERROR_NO_MEMORY; + poolFinish(&dtd->pool); + if (unparsedEntityDeclHandler) { + *eventEndPP = s; + unparsedEntityDeclHandler(handlerArg, + declEntity->name, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + declEntity->notation); + handleDefault = XML_FALSE; } - break; - case XML_ROLE_PARAM_ENTITY_NAME: -#ifdef XML_DTD - if (dtd->keepProcessing) - { - const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); - if (!name) - return XML_ERROR_NO_MEMORY; - declEntity = (ENTITY *)lookup(&dtd->paramEntities, - name, sizeof(ENTITY)); - if (!declEntity) - return XML_ERROR_NO_MEMORY; - if (declEntity->name != name) - { - poolDiscard(&dtd->pool); - declEntity = NULL; - } - else - { - poolFinish(&dtd->pool); - declEntity->publicId = NULL; - declEntity->is_param = XML_TRUE; - /* if we have a parent parser or are reading an internal parameter - entity, then the entity declaration is not considered "internal" - */ - declEntity->is_internal = !(parentParser || openInternalEntities); - if (entityDeclHandler) - handleDefault = XML_FALSE; - } - } - else - { - poolDiscard(&dtd->pool); - declEntity = NULL; - } -#else /* not XML_DTD */ + else if (entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + 0,0,0, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + declEntity->notation); + handleDefault = XML_FALSE; + } + } + break; + case XML_ROLE_GENERAL_ENTITY_NAME: + { + if (XmlPredefinedEntityName(enc, s, next)) { + declEntity = NULL; + break; + } + if (dtd->keepProcessing) { + const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); + if (!name) + return XML_ERROR_NO_MEMORY; + declEntity = (ENTITY *)lookup(&dtd->generalEntities, name, + sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; + if (declEntity->name != name) { + poolDiscard(&dtd->pool); declEntity = NULL; -#endif /* XML_DTD */ - break; - case XML_ROLE_NOTATION_NAME: - declNotationPublicId = NULL; - declNotationName = NULL; - if (notationDeclHandler) - { - declNotationName = poolStoreString(&tempPool, enc, s, next); - if (!declNotationName) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - handleDefault = XML_FALSE; - } - break; - case XML_ROLE_NOTATION_PUBLIC_ID: - if (!XmlIsPublicId(enc, s, next, eventPP)) - return XML_ERROR_PUBLICID; - if (declNotationName) /* means notationDeclHandler != NULL */ - { - XML_Char *tem = poolStoreString(&tempPool, - enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!tem) - return XML_ERROR_NO_MEMORY; - normalizePublicId(tem); - declNotationPublicId = tem; - poolFinish(&tempPool); - handleDefault = XML_FALSE; - } - break; - case XML_ROLE_NOTATION_SYSTEM_ID: - if (declNotationName && notationDeclHandler) - { - const XML_Char *systemId - = poolStoreString(&tempPool, enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!systemId) - return XML_ERROR_NO_MEMORY; - *eventEndPP = s; - notationDeclHandler(handlerArg, - declNotationName, - curBase, - systemId, - declNotationPublicId); - handleDefault = XML_FALSE; - } - poolClear(&tempPool); - break; - case XML_ROLE_NOTATION_NO_SYSTEM_ID: - if (declNotationPublicId && notationDeclHandler) - { - *eventEndPP = s; - notationDeclHandler(handlerArg, - declNotationName, - curBase, - 0, - declNotationPublicId); - handleDefault = XML_FALSE; - } - poolClear(&tempPool); - break; - case XML_ROLE_ERROR: - switch (tok) - { - case XML_TOK_PARAM_ENTITY_REF: - /* PE references in internal subset are - not allowed within declarations. */ - return XML_ERROR_PARAM_ENTITY_REF; - case XML_TOK_XML_DECL: - return XML_ERROR_MISPLACED_XML_PI; - default: - return XML_ERROR_SYNTAX; - } + } + else { + poolFinish(&dtd->pool); + declEntity->publicId = NULL; + declEntity->is_param = XML_FALSE; + /* if we have a parent parser or are reading an internal parameter + entity, then the entity declaration is not considered "internal" + */ + declEntity->is_internal = !(parentParser || openInternalEntities); + if (entityDeclHandler) + handleDefault = XML_FALSE; + } + } + else { + poolDiscard(&dtd->pool); + declEntity = NULL; + } + } + break; + case XML_ROLE_PARAM_ENTITY_NAME: #ifdef XML_DTD - case XML_ROLE_IGNORE_SECT: - { - enum XML_Error result; - if (defaultHandler) - reportDefault(parser, enc, s, next); + if (dtd->keepProcessing) { + const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); + if (!name) + return XML_ERROR_NO_MEMORY; + declEntity = (ENTITY *)lookup(&dtd->paramEntities, + name, sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; + if (declEntity->name != name) { + poolDiscard(&dtd->pool); + declEntity = NULL; + } + else { + poolFinish(&dtd->pool); + declEntity->publicId = NULL; + declEntity->is_param = XML_TRUE; + /* if we have a parent parser or are reading an internal parameter + entity, then the entity declaration is not considered "internal" + */ + declEntity->is_internal = !(parentParser || openInternalEntities); + if (entityDeclHandler) handleDefault = XML_FALSE; - result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore); - if (result != XML_ERROR_NONE) - return result; - else if (!next) - { - processor = ignoreSectionProcessor; - return result; - } } - break; + } + else { + poolDiscard(&dtd->pool); + declEntity = NULL; + } +#else /* not XML_DTD */ + declEntity = NULL; #endif /* XML_DTD */ - case XML_ROLE_GROUP_OPEN: - if (prologState.level >= groupSize) - { - if (groupSize) - { - char *temp = (char *)REALLOC(groupConnector, groupSize *= 2); - if (temp == NULL) - return XML_ERROR_NO_MEMORY; - groupConnector = temp; - if (dtd->scaffIndex) - { - int *temp = (int *)REALLOC(dtd->scaffIndex, - groupSize * sizeof(int)); - if (temp == NULL) - return XML_ERROR_NO_MEMORY; - dtd->scaffIndex = temp; - } - } - else - { - groupConnector = (char *)MALLOC(groupSize = 32); - if (!groupConnector) - return XML_ERROR_NO_MEMORY; - } - } - groupConnector[prologState.level] = 0; - if (dtd->in_eldecl) - { - int myindex = nextScaffoldPart(parser); - if (myindex < 0) - return XML_ERROR_NO_MEMORY; - dtd->scaffIndex[dtd->scaffLevel] = myindex; - dtd->scaffLevel++; - dtd->scaffold[myindex].type = XML_CTYPE_SEQ; - if (elementDeclHandler) - handleDefault = XML_FALSE; - } - break; - case XML_ROLE_GROUP_SEQUENCE: - if (groupConnector[prologState.level] == '|') - return XML_ERROR_SYNTAX; - groupConnector[prologState.level] = ','; - if (dtd->in_eldecl && elementDeclHandler) - handleDefault = XML_FALSE; - break; - case XML_ROLE_GROUP_CHOICE: - if (groupConnector[prologState.level] == ',') - return XML_ERROR_SYNTAX; - if (dtd->in_eldecl - && !groupConnector[prologState.level] - && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type - != XML_CTYPE_MIXED) - ) - { - dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type - = XML_CTYPE_CHOICE; - if (elementDeclHandler) - handleDefault = XML_FALSE; - } - groupConnector[prologState.level] = '|'; - break; - case XML_ROLE_PARAM_ENTITY_REF: + break; + case XML_ROLE_NOTATION_NAME: + declNotationPublicId = NULL; + declNotationName = NULL; + if (notationDeclHandler) { + declNotationName = poolStoreString(&tempPool, enc, s, next); + if (!declNotationName) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_NOTATION_PUBLIC_ID: + if (!XmlIsPublicId(enc, s, next, eventPP)) + return XML_ERROR_PUBLICID; + if (declNotationName) { /* means notationDeclHandler != NULL */ + XML_Char *tem = poolStoreString(&tempPool, + enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!tem) + return XML_ERROR_NO_MEMORY; + normalizePublicId(tem); + declNotationPublicId = tem; + poolFinish(&tempPool); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_NOTATION_SYSTEM_ID: + if (declNotationName && notationDeclHandler) { + const XML_Char *systemId + = poolStoreString(&tempPool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!systemId) + return XML_ERROR_NO_MEMORY; + *eventEndPP = s; + notationDeclHandler(handlerArg, + declNotationName, + curBase, + systemId, + declNotationPublicId); + handleDefault = XML_FALSE; + } + poolClear(&tempPool); + break; + case XML_ROLE_NOTATION_NO_SYSTEM_ID: + if (declNotationPublicId && notationDeclHandler) { + *eventEndPP = s; + notationDeclHandler(handlerArg, + declNotationName, + curBase, + 0, + declNotationPublicId); + handleDefault = XML_FALSE; + } + poolClear(&tempPool); + break; + case XML_ROLE_ERROR: + switch (tok) { + case XML_TOK_PARAM_ENTITY_REF: + /* PE references in internal subset are + not allowed within declarations. */ + return XML_ERROR_PARAM_ENTITY_REF; + case XML_TOK_XML_DECL: + return XML_ERROR_MISPLACED_XML_PI; + default: + return XML_ERROR_SYNTAX; + } #ifdef XML_DTD - case XML_ROLE_INNER_PARAM_ENTITY_REF: - dtd->hasParamEntityRefs = XML_TRUE; - if (!paramEntityParsing) - dtd->keepProcessing = dtd->standalone; - else - { - const XML_Char *name; - ENTITY *entity; - name = poolStoreString(&dtd->pool, enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!name) - return XML_ERROR_NO_MEMORY; - entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); - poolDiscard(&dtd->pool); - /* first, determine if a check for an existing declaration is needed; - if yes, check that the entity exists, and that it is internal, - otherwise call the skipped entity handler - */ - if (prologState.documentEntity && - (dtd->standalone - ? !openInternalEntities - : !dtd->hasParamEntityRefs)) - { - if (!entity) - return XML_ERROR_UNDEFINED_ENTITY; - else if (!entity->is_internal) - return XML_ERROR_ENTITY_DECLARED_IN_PE; - } - else if (!entity) - { - dtd->keepProcessing = dtd->standalone; - /* cannot report skipped entities in declarations */ - if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) - { - skippedEntityHandler(handlerArg, name, 1); - handleDefault = XML_FALSE; - } - break; - } - if (entity->open) - return XML_ERROR_RECURSIVE_ENTITY_REF; - if (entity->textPtr) - { - enum XML_Error result; - XML_Bool betweenDecl = - (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE); - result = processInternalEntity(parser, entity, betweenDecl); - if (result != XML_ERROR_NONE) - return result; - handleDefault = XML_FALSE; - break; - } - if (externalEntityRefHandler) - { - dtd->paramEntityRead = XML_FALSE; - entity->open = XML_TRUE; - if (!externalEntityRefHandler(externalEntityRefHandlerArg, - 0, - entity->base, - entity->systemId, - entity->publicId)) - { - entity->open = XML_FALSE; - return XML_ERROR_EXTERNAL_ENTITY_HANDLING; - } - entity->open = XML_FALSE; - handleDefault = XML_FALSE; - if (!dtd->paramEntityRead) - { - dtd->keepProcessing = dtd->standalone; - break; - } - } - else - { - dtd->keepProcessing = dtd->standalone; - break; - } - } + case XML_ROLE_IGNORE_SECT: + { + enum XML_Error result; + if (defaultHandler) + reportDefault(parser, enc, s, next); + handleDefault = XML_FALSE; + result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore); + if (result != XML_ERROR_NONE) + return result; + else if (!next) { + processor = ignoreSectionProcessor; + return result; + } + } + break; #endif /* XML_DTD */ - if (!dtd->standalone && - notStandaloneHandler && - !notStandaloneHandler(handlerArg)) - return XML_ERROR_NOT_STANDALONE; - break; - - /* Element declaration stuff */ - - case XML_ROLE_ELEMENT_NAME: - if (elementDeclHandler) - { - declElementType = getElementType(parser, enc, s, next); - if (!declElementType) - return XML_ERROR_NO_MEMORY; - dtd->scaffLevel = 0; - dtd->scaffCount = 0; - dtd->in_eldecl = XML_TRUE; - handleDefault = XML_FALSE; - } - break; - - case XML_ROLE_CONTENT_ANY: - case XML_ROLE_CONTENT_EMPTY: - if (dtd->in_eldecl) - { - if (elementDeclHandler) - { - XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content)); - if (!content) - return XML_ERROR_NO_MEMORY; - content->quant = XML_CQUANT_NONE; - content->name = NULL; - content->numchildren = 0; - content->children = NULL; - content->type = ((role == XML_ROLE_CONTENT_ANY) ? - XML_CTYPE_ANY : - XML_CTYPE_EMPTY); - *eventEndPP = s; - elementDeclHandler(handlerArg, declElementType->name, content); - handleDefault = XML_FALSE; - } - dtd->in_eldecl = XML_FALSE; - } - break; - - case XML_ROLE_CONTENT_PCDATA: - if (dtd->in_eldecl) - { - dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type - = XML_CTYPE_MIXED; - if (elementDeclHandler) - handleDefault = XML_FALSE; - } - break; - - case XML_ROLE_CONTENT_ELEMENT: - quant = XML_CQUANT_NONE; - goto elementContent; - case XML_ROLE_CONTENT_ELEMENT_OPT: - quant = XML_CQUANT_OPT; - goto elementContent; - case XML_ROLE_CONTENT_ELEMENT_REP: - quant = XML_CQUANT_REP; - goto elementContent; - case XML_ROLE_CONTENT_ELEMENT_PLUS: - quant = XML_CQUANT_PLUS; -elementContent: - if (dtd->in_eldecl) - { - ELEMENT_TYPE *el; - const XML_Char *name; - int nameLen; - const char *nxt = (quant == XML_CQUANT_NONE - ? next - : next - enc->minBytesPerChar); - int myindex = nextScaffoldPart(parser); - if (myindex < 0) - return XML_ERROR_NO_MEMORY; - dtd->scaffold[myindex].type = XML_CTYPE_NAME; - dtd->scaffold[myindex].quant = quant; - el = getElementType(parser, enc, s, nxt); - if (!el) - return XML_ERROR_NO_MEMORY; - name = el->name; - dtd->scaffold[myindex].name = name; - nameLen = 0; - for (; name[nameLen++]; ); - dtd->contentStringLen += nameLen; - if (elementDeclHandler) - handleDefault = XML_FALSE; - } - break; - - case XML_ROLE_GROUP_CLOSE: - quant = XML_CQUANT_NONE; - goto closeGroup; - case XML_ROLE_GROUP_CLOSE_OPT: - quant = XML_CQUANT_OPT; - goto closeGroup; - case XML_ROLE_GROUP_CLOSE_REP: - quant = XML_CQUANT_REP; - goto closeGroup; - case XML_ROLE_GROUP_CLOSE_PLUS: - quant = XML_CQUANT_PLUS; -closeGroup: - if (dtd->in_eldecl) - { - if (elementDeclHandler) - handleDefault = XML_FALSE; - dtd->scaffLevel--; - dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant; - if (dtd->scaffLevel == 0) - { - if (!handleDefault) - { - XML_Content *model = build_model(parser); - if (!model) - return XML_ERROR_NO_MEMORY; - *eventEndPP = s; - elementDeclHandler(handlerArg, declElementType->name, model); - } - dtd->in_eldecl = XML_FALSE; - dtd->contentStringLen = 0; - } - } - break; - /* End element declaration stuff */ - - case XML_ROLE_PI: - if (!reportProcessingInstruction(parser, enc, s, next)) - return XML_ERROR_NO_MEMORY; - handleDefault = XML_FALSE; - break; - case XML_ROLE_COMMENT: - if (!reportComment(parser, enc, s, next)) - return XML_ERROR_NO_MEMORY; + case XML_ROLE_GROUP_OPEN: + if (prologState.level >= groupSize) { + if (groupSize) { + char *temp = (char *)REALLOC(groupConnector, groupSize *= 2); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + groupConnector = temp; + if (dtd->scaffIndex) { + int *temp = (int *)REALLOC(dtd->scaffIndex, + groupSize * sizeof(int)); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + dtd->scaffIndex = temp; + } + } + else { + groupConnector = (char *)MALLOC(groupSize = 32); + if (!groupConnector) + return XML_ERROR_NO_MEMORY; + } + } + groupConnector[prologState.level] = 0; + if (dtd->in_eldecl) { + int myindex = nextScaffoldPart(parser); + if (myindex < 0) + return XML_ERROR_NO_MEMORY; + dtd->scaffIndex[dtd->scaffLevel] = myindex; + dtd->scaffLevel++; + dtd->scaffold[myindex].type = XML_CTYPE_SEQ; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_GROUP_SEQUENCE: + if (groupConnector[prologState.level] == '|') + return XML_ERROR_SYNTAX; + groupConnector[prologState.level] = ','; + if (dtd->in_eldecl && elementDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_GROUP_CHOICE: + if (groupConnector[prologState.level] == ',') + return XML_ERROR_SYNTAX; + if (dtd->in_eldecl + && !groupConnector[prologState.level] + && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type + != XML_CTYPE_MIXED) + ) { + dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type + = XML_CTYPE_CHOICE; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + groupConnector[prologState.level] = '|'; + break; + case XML_ROLE_PARAM_ENTITY_REF: +#ifdef XML_DTD + case XML_ROLE_INNER_PARAM_ENTITY_REF: + dtd->hasParamEntityRefs = XML_TRUE; + if (!paramEntityParsing) + dtd->keepProcessing = dtd->standalone; + else { + const XML_Char *name; + ENTITY *entity; + name = poolStoreString(&dtd->pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); + poolDiscard(&dtd->pool); + /* first, determine if a check for an existing declaration is needed; + if yes, check that the entity exists, and that it is internal, + otherwise call the skipped entity handler + */ + if (prologState.documentEntity && + (dtd->standalone + ? !openInternalEntities + : !dtd->hasParamEntityRefs)) { + if (!entity) + return XML_ERROR_UNDEFINED_ENTITY; + else if (!entity->is_internal) + return XML_ERROR_ENTITY_DECLARED_IN_PE; + } + else if (!entity) { + dtd->keepProcessing = dtd->standalone; + /* cannot report skipped entities in declarations */ + if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) { + skippedEntityHandler(handlerArg, name, 1); handleDefault = XML_FALSE; + } + break; + } + if (entity->open) + return XML_ERROR_RECURSIVE_ENTITY_REF; + if (entity->textPtr) { + enum XML_Error result; + XML_Bool betweenDecl = + (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE); + result = processInternalEntity(parser, entity, betweenDecl); + if (result != XML_ERROR_NONE) + return result; + handleDefault = XML_FALSE; + break; + } + if (externalEntityRefHandler) { + dtd->paramEntityRead = XML_FALSE; + entity->open = XML_TRUE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) { + entity->open = XML_FALSE; + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + } + entity->open = XML_FALSE; + handleDefault = XML_FALSE; + if (!dtd->paramEntityRead) { + dtd->keepProcessing = dtd->standalone; break; - case XML_ROLE_NONE: - switch (tok) - { - case XML_TOK_BOM: - handleDefault = XML_FALSE; - break; - } - break; - case XML_ROLE_DOCTYPE_NONE: - if (startDoctypeDeclHandler) - handleDefault = XML_FALSE; - break; - case XML_ROLE_ENTITY_NONE: - if (dtd->keepProcessing && entityDeclHandler) - handleDefault = XML_FALSE; - break; - case XML_ROLE_NOTATION_NONE: - if (notationDeclHandler) - handleDefault = XML_FALSE; - break; - case XML_ROLE_ATTLIST_NONE: - if (dtd->keepProcessing && attlistDeclHandler) - handleDefault = XML_FALSE; - break; - case XML_ROLE_ELEMENT_NONE: - if (elementDeclHandler) - handleDefault = XML_FALSE; - break; - } /* end of big switch */ + } + } + else { + dtd->keepProcessing = dtd->standalone; + break; + } + } +#endif /* XML_DTD */ + if (!dtd->standalone && + notStandaloneHandler && + !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + break; + + /* Element declaration stuff */ + + case XML_ROLE_ELEMENT_NAME: + if (elementDeclHandler) { + declElementType = getElementType(parser, enc, s, next); + if (!declElementType) + return XML_ERROR_NO_MEMORY; + dtd->scaffLevel = 0; + dtd->scaffCount = 0; + dtd->in_eldecl = XML_TRUE; + handleDefault = XML_FALSE; + } + break; + + case XML_ROLE_CONTENT_ANY: + case XML_ROLE_CONTENT_EMPTY: + if (dtd->in_eldecl) { + if (elementDeclHandler) { + XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content)); + if (!content) + return XML_ERROR_NO_MEMORY; + content->quant = XML_CQUANT_NONE; + content->name = NULL; + content->numchildren = 0; + content->children = NULL; + content->type = ((role == XML_ROLE_CONTENT_ANY) ? + XML_CTYPE_ANY : + XML_CTYPE_EMPTY); + *eventEndPP = s; + elementDeclHandler(handlerArg, declElementType->name, content); + handleDefault = XML_FALSE; + } + dtd->in_eldecl = XML_FALSE; + } + break; + + case XML_ROLE_CONTENT_PCDATA: + if (dtd->in_eldecl) { + dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type + = XML_CTYPE_MIXED; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + break; + + case XML_ROLE_CONTENT_ELEMENT: + quant = XML_CQUANT_NONE; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_OPT: + quant = XML_CQUANT_OPT; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_REP: + quant = XML_CQUANT_REP; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_PLUS: + quant = XML_CQUANT_PLUS; + elementContent: + if (dtd->in_eldecl) { + ELEMENT_TYPE *el; + const XML_Char *name; + int nameLen; + const char *nxt = (quant == XML_CQUANT_NONE + ? next + : next - enc->minBytesPerChar); + int myindex = nextScaffoldPart(parser); + if (myindex < 0) + return XML_ERROR_NO_MEMORY; + dtd->scaffold[myindex].type = XML_CTYPE_NAME; + dtd->scaffold[myindex].quant = quant; + el = getElementType(parser, enc, s, nxt); + if (!el) + return XML_ERROR_NO_MEMORY; + name = el->name; + dtd->scaffold[myindex].name = name; + nameLen = 0; + for (; name[nameLen++]; ); + dtd->contentStringLen += nameLen; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + break; + + case XML_ROLE_GROUP_CLOSE: + quant = XML_CQUANT_NONE; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_OPT: + quant = XML_CQUANT_OPT; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_REP: + quant = XML_CQUANT_REP; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_PLUS: + quant = XML_CQUANT_PLUS; + closeGroup: + if (dtd->in_eldecl) { + if (elementDeclHandler) + handleDefault = XML_FALSE; + dtd->scaffLevel--; + dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant; + if (dtd->scaffLevel == 0) { + if (!handleDefault) { + XML_Content *model = build_model(parser); + if (!model) + return XML_ERROR_NO_MEMORY; + *eventEndPP = s; + elementDeclHandler(handlerArg, declElementType->name, model); + } + dtd->in_eldecl = XML_FALSE; + dtd->contentStringLen = 0; + } + } + break; + /* End element declaration stuff */ - if (handleDefault && defaultHandler) - reportDefault(parser, enc, s, next); + case XML_ROLE_PI: + if (!reportProcessingInstruction(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + handleDefault = XML_FALSE; + break; + case XML_ROLE_COMMENT: + if (!reportComment(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + handleDefault = XML_FALSE; + break; + case XML_ROLE_NONE: + switch (tok) { + case XML_TOK_BOM: + handleDefault = XML_FALSE; + break; + } + break; + case XML_ROLE_DOCTYPE_NONE: + if (startDoctypeDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ENTITY_NONE: + if (dtd->keepProcessing && entityDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_NOTATION_NONE: + if (notationDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ATTLIST_NONE: + if (dtd->keepProcessing && attlistDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ELEMENT_NONE: + if (elementDeclHandler) + handleDefault = XML_FALSE; + break; + } /* end of big switch */ + + if (handleDefault && defaultHandler) + reportDefault(parser, enc, s, next); + + switch (parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: + s = next; + tok = XmlPrologTok(enc, s, end, &next); + } + } + /* not reached */ +} - switch (parsing) - { - case XML_SUSPENDED: - *nextPtr = next; - return XML_ERROR_NONE; - case XML_FINISHED: - return XML_ERROR_ABORTED; - default: - s = next; - tok = XmlPrologTok(enc, s, end, &next); - } +static enum XML_Error PTRCALL +epilogProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + processor = epilogProcessor; + eventPtr = s; + for (;;) { + const char *next = NULL; + int tok = XmlPrologTok(encoding, s, end, &next); + eventEndPtr = next; + switch (tok) { + /* report partial linebreak - it might be the last token */ + case -XML_TOK_PROLOG_S: + if (defaultHandler) { + reportDefault(parser, encoding, s, next); + if (parsing == XML_FINISHED) + return XML_ERROR_ABORTED; + } + *nextPtr = next; + return XML_ERROR_NONE; + case XML_TOK_NONE: + *nextPtr = s; + return XML_ERROR_NONE; + case XML_TOK_PROLOG_S: + if (defaultHandler) + reportDefault(parser, encoding, s, next); + break; + case XML_TOK_PI: + if (!reportProcessingInstruction(parser, encoding, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_COMMENT: + if (!reportComment(parser, encoding, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_INVALID: + eventPtr = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (!finalBuffer) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (!finalBuffer) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + default: + return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; } - /* not reached */ -} - -static enum XML_Error PTRCALL -epilogProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) -{ - processor = epilogProcessor; - eventPtr = s; - for (;;) - { - const char *next = NULL; - int tok = XmlPrologTok(encoding, s, end, &next); - eventEndPtr = next; - switch (tok) - { - /* report partial linebreak - it might be the last token */ - case -XML_TOK_PROLOG_S: - if (defaultHandler) - { - reportDefault(parser, encoding, s, next); - if (parsing == XML_FINISHED) - return XML_ERROR_ABORTED; - } - *nextPtr = next; - return XML_ERROR_NONE; - case XML_TOK_NONE: - *nextPtr = s; - return XML_ERROR_NONE; - case XML_TOK_PROLOG_S: - if (defaultHandler) - reportDefault(parser, encoding, s, next); - break; - case XML_TOK_PI: - if (!reportProcessingInstruction(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_COMMENT: - if (!reportComment(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_INVALID: - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (!finalBuffer) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (!finalBuffer) - { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - default: - return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; - } - eventPtr = s = next; - switch (parsing) - { - case XML_SUSPENDED: - *nextPtr = next; - return XML_ERROR_NONE; - case XML_FINISHED: - return XML_ERROR_ABORTED; - default: - ; - } + eventPtr = s = next; + switch (parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: ; } + } } static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) { - const char *textStart, *textEnd; - const char *next; - enum XML_Error result; - OPEN_INTERNAL_ENTITY *openEntity; - - if (freeInternalEntities) - { - openEntity = freeInternalEntities; - freeInternalEntities = openEntity->next; - } - else - { - openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY)); - if (!openEntity) - return XML_ERROR_NO_MEMORY; - } - entity->open = XML_TRUE; - entity->processed = 0; - openEntity->next = openInternalEntities; - openInternalEntities = openEntity; - openEntity->entity = entity; - openEntity->startTagLevel = tagLevel; - openEntity->betweenDecl = betweenDecl; - openEntity->internalEventPtr = NULL; - openEntity->internalEventEndPtr = NULL; - textStart = (char *)entity->textPtr; - textEnd = (char *)(entity->textPtr + entity->textLen); + const char *textStart, *textEnd; + const char *next; + enum XML_Error result; + OPEN_INTERNAL_ENTITY *openEntity; + + if (freeInternalEntities) { + openEntity = freeInternalEntities; + freeInternalEntities = openEntity->next; + } + else { + openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY)); + if (!openEntity) + return XML_ERROR_NO_MEMORY; + } + entity->open = XML_TRUE; + entity->processed = 0; + openEntity->next = openInternalEntities; + openInternalEntities = openEntity; + openEntity->entity = entity; + openEntity->startTagLevel = tagLevel; + openEntity->betweenDecl = betweenDecl; + openEntity->internalEventPtr = NULL; + openEntity->internalEventEndPtr = NULL; + textStart = (char *)entity->textPtr; + textEnd = (char *)(entity->textPtr + entity->textLen); #ifdef XML_DTD - if (entity->is_param) - { - int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); - result = doProlog(parser, internalEncoding, textStart, textEnd, tok, - next, &next, XML_FALSE); - } - else + if (entity->is_param) { + int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); + result = doProlog(parser, internalEncoding, textStart, textEnd, tok, + next, &next, XML_FALSE); + } + else #endif /* XML_DTD */ - result = doContent(parser, tagLevel, internalEncoding, textStart, - textEnd, &next, XML_FALSE); + result = doContent(parser, tagLevel, internalEncoding, textStart, + textEnd, &next, XML_FALSE); - if (result == XML_ERROR_NONE) - { - if (textEnd != next && parsing == XML_SUSPENDED) - { - entity->processed = next - textStart; - processor = internalEntityProcessor; - } - else - { - entity->open = XML_FALSE; - openInternalEntities = openEntity->next; - /* put openEntity back in list of free instances */ - openEntity->next = freeInternalEntities; - freeInternalEntities = openEntity; - } + if (result == XML_ERROR_NONE) { + if (textEnd != next && parsing == XML_SUSPENDED) { + entity->processed = next - textStart; + processor = internalEntityProcessor; } - return result; + else { + entity->open = XML_FALSE; + openInternalEntities = openEntity->next; + /* put openEntity back in list of free instances */ + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } + } + return result; } static enum XML_Error PTRCALL @@ -4995,63 +4641,59 @@ internalEntityProcessor(XML_Parser parser, const char *end, const char **nextPtr) { - ENTITY *entity; - const char *textStart, *textEnd; - const char *next; - enum XML_Error result; - OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities; - if (!openEntity) - return XML_ERROR_UNEXPECTED_STATE; + ENTITY *entity; + const char *textStart, *textEnd; + const char *next; + enum XML_Error result; + OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities; + if (!openEntity) + return XML_ERROR_UNEXPECTED_STATE; - entity = openEntity->entity; - textStart = ((char *)entity->textPtr) + entity->processed; - textEnd = (char *)(entity->textPtr + entity->textLen); + entity = openEntity->entity; + textStart = ((char *)entity->textPtr) + entity->processed; + textEnd = (char *)(entity->textPtr + entity->textLen); #ifdef XML_DTD - if (entity->is_param) - { - int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); - result = doProlog(parser, internalEncoding, textStart, textEnd, tok, - next, &next, XML_FALSE); - } - else + if (entity->is_param) { + int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); + result = doProlog(parser, internalEncoding, textStart, textEnd, tok, + next, &next, XML_FALSE); + } + else #endif /* XML_DTD */ - result = doContent(parser, openEntity->startTagLevel, internalEncoding, - textStart, textEnd, &next, XML_FALSE); + result = doContent(parser, openEntity->startTagLevel, internalEncoding, + textStart, textEnd, &next, XML_FALSE); - if (result != XML_ERROR_NONE) - return result; - else if (textEnd != next && parsing == XML_SUSPENDED) - { - entity->processed = next - (char *)entity->textPtr; - return result; - } - else - { - entity->open = XML_FALSE; - openInternalEntities = openEntity->next; - /* put openEntity back in list of free instances */ - openEntity->next = freeInternalEntities; - freeInternalEntities = openEntity; - } + if (result != XML_ERROR_NONE) + return result; + else if (textEnd != next && parsing == XML_SUSPENDED) { + entity->processed = next - (char *)entity->textPtr; + return result; + } + else { + entity->open = XML_FALSE; + openInternalEntities = openEntity->next; + /* put openEntity back in list of free instances */ + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } #ifdef XML_DTD - if (entity->is_param) - { - int tok; - processor = prologProcessor; - tok = XmlPrologTok(encoding, s, end, &next); - return doProlog(parser, encoding, s, end, tok, next, nextPtr, - (XML_Bool)!finalBuffer); - } - else + if (entity->is_param) { + int tok; + processor = prologProcessor; + tok = XmlPrologTok(encoding, s, end, &next); + return doProlog(parser, encoding, s, end, tok, next, nextPtr, + (XML_Bool)!finalBuffer); + } + else #endif /* XML_DTD */ - { - processor = contentProcessor; - /* see externalEntityContentProcessor vs contentProcessor */ - return doContent(parser, parentParser ? 1 : 0, encoding, s, end, - nextPtr, (XML_Bool)!finalBuffer); - } + { + processor = contentProcessor; + /* see externalEntityContentProcessor vs contentProcessor */ + return doContent(parser, parentParser ? 1 : 0, encoding, s, end, + nextPtr, (XML_Bool)!finalBuffer); + } } static enum XML_Error PTRCALL @@ -5060,7 +4702,7 @@ errorProcessor(XML_Parser parser, const char *end, const char **nextPtr) { - return errorCode; + return errorCode; } static enum XML_Error @@ -5068,15 +4710,15 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, const char *ptr, const char *end, STRING_POOL *pool) { - enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, - end, pool); - if (result) - return result; - if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) - poolChop(pool); - if (!poolAppendChar(pool, XML_T('\0'))) - return XML_ERROR_NO_MEMORY; - return XML_ERROR_NONE; + enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, + end, pool); + if (result) + return result; + if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) + poolChop(pool); + if (!poolAppendChar(pool, XML_T('\0'))) + return XML_ERROR_NO_MEMORY; + return XML_ERROR_NONE; } static enum XML_Error @@ -5084,159 +4726,147 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, const char *ptr, const char *end, STRING_POOL *pool) { - DTD * const dtd = _dtd; /* save one level of indirection */ - for (;;) - { - const char *next; - int tok = XmlAttributeValueTok(enc, ptr, end, &next); - switch (tok) - { - case XML_TOK_NONE: - return XML_ERROR_NONE; - case XML_TOK_INVALID: - if (enc == encoding) - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_CHAR_REF: - { - XML_Char buf[XML_ENCODE_MAX]; - int i; - int n = XmlCharRefNumber(enc, ptr); - if (n < 0) - { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BAD_CHAR_REF; - } - if (!isCdata - && n == 0x20 /* space */ - && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) - break; - n = XmlEncode(n, (ICHAR *)buf); - if (!n) - { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BAD_CHAR_REF; - } - for (i = 0; i < n; i++) - { - if (!poolAppendChar(pool, buf[i])) - return XML_ERROR_NO_MEMORY; - } + DTD * const dtd = _dtd; /* save one level of indirection */ + for (;;) { + const char *next; + int tok = XmlAttributeValueTok(enc, ptr, end, &next); + switch (tok) { + case XML_TOK_NONE: + return XML_ERROR_NONE; + case XML_TOK_INVALID: + if (enc == encoding) + eventPtr = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_CHAR_REF: + { + XML_Char buf[XML_ENCODE_MAX]; + int i; + int n = XmlCharRefNumber(enc, ptr); + if (n < 0) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BAD_CHAR_REF; + } + if (!isCdata + && n == 0x20 /* space */ + && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) + break; + n = XmlEncode(n, (ICHAR *)buf); + if (!n) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BAD_CHAR_REF; + } + for (i = 0; i < n; i++) { + if (!poolAppendChar(pool, buf[i])) + return XML_ERROR_NO_MEMORY; } + } + break; + case XML_TOK_DATA_CHARS: + if (!poolAppend(pool, enc, ptr, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_TRAILING_CR: + next = ptr + enc->minBytesPerChar; + /* fall through */ + case XML_TOK_ATTRIBUTE_VALUE_S: + case XML_TOK_DATA_NEWLINE: + if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) break; - case XML_TOK_DATA_CHARS: - if (!poolAppend(pool, enc, ptr, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_TRAILING_CR: - next = ptr + enc->minBytesPerChar; - /* fall through */ - case XML_TOK_ATTRIBUTE_VALUE_S: - case XML_TOK_DATA_NEWLINE: - if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) - break; - if (!poolAppendChar(pool, 0x20)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_ENTITY_REF: - { - const XML_Char *name; - ENTITY *entity; - char checkEntityDecl; - XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, - ptr + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (ch) - { - if (!poolAppendChar(pool, ch)) - return XML_ERROR_NO_MEMORY; - break; - } - name = poolStoreString(&temp2Pool, enc, - ptr + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!name) + if (!poolAppendChar(pool, 0x20)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_ENTITY_REF: + { + const XML_Char *name; + ENTITY *entity; + char checkEntityDecl; + XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, + ptr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (ch) { + if (!poolAppendChar(pool, ch)) return XML_ERROR_NO_MEMORY; - entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); - poolDiscard(&temp2Pool); - /* first, determine if a check for an existing declaration is needed; - if yes, check that the entity exists, and that it is internal, - otherwise call the default handler (if called from content) - */ - if (pool == &dtd->pool) /* are we called from prolog? */ - checkEntityDecl = + break; + } + name = poolStoreString(&temp2Pool, enc, + ptr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); + poolDiscard(&temp2Pool); + /* first, determine if a check for an existing declaration is needed; + if yes, check that the entity exists, and that it is internal, + otherwise call the default handler (if called from content) + */ + if (pool == &dtd->pool) /* are we called from prolog? */ + checkEntityDecl = #ifdef XML_DTD - prologState.documentEntity && + prologState.documentEntity && #endif /* XML_DTD */ - (dtd->standalone - ? !openInternalEntities - : !dtd->hasParamEntityRefs); - else /* if (pool == &tempPool): we are called from content */ - checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone; - if (checkEntityDecl) - { - if (!entity) - return XML_ERROR_UNDEFINED_ENTITY; - else if (!entity->is_internal) - return XML_ERROR_ENTITY_DECLARED_IN_PE; - } - else if (!entity) - { - /* cannot report skipped entity here - see comments on - skippedEntityHandler - if (skippedEntityHandler) - skippedEntityHandler(handlerArg, name, 0); - */ - if ((pool == &tempPool) && defaultHandler) - reportDefault(parser, enc, ptr, next); - break; - } - if (entity->open) - { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_RECURSIVE_ENTITY_REF; - } - if (entity->notation) - { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BINARY_ENTITY_REF; - } - if (!entity->textPtr) - { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; - } - else - { - enum XML_Error result; - const XML_Char *textEnd = entity->textPtr + entity->textLen; - entity->open = XML_TRUE; - result = appendAttributeValue(parser, internalEncoding, isCdata, - (char *)entity->textPtr, - (char *)textEnd, pool); - entity->open = XML_FALSE; - if (result) - return result; - } + (dtd->standalone + ? !openInternalEntities + : !dtd->hasParamEntityRefs); + else /* if (pool == &tempPool): we are called from content */ + checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone; + if (checkEntityDecl) { + if (!entity) + return XML_ERROR_UNDEFINED_ENTITY; + else if (!entity->is_internal) + return XML_ERROR_ENTITY_DECLARED_IN_PE; } - break; - default: - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_UNEXPECTED_STATE; + else if (!entity) { + /* cannot report skipped entity here - see comments on + skippedEntityHandler + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, name, 0); + */ + if ((pool == &tempPool) && defaultHandler) + reportDefault(parser, enc, ptr, next); + break; + } + if (entity->open) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_RECURSIVE_ENTITY_REF; + } + if (entity->notation) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BINARY_ENTITY_REF; + } + if (!entity->textPtr) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; } - ptr = next; + else { + enum XML_Error result; + const XML_Char *textEnd = entity->textPtr + entity->textLen; + entity->open = XML_TRUE; + result = appendAttributeValue(parser, internalEncoding, isCdata, + (char *)entity->textPtr, + (char *)textEnd, pool); + entity->open = XML_FALSE; + if (result) + return result; + } + } + break; + default: + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_UNEXPECTED_STATE; } - /* not reached */ + ptr = next; + } + /* not reached */ } static enum XML_Error @@ -5245,293 +4875,265 @@ storeEntityValue(XML_Parser parser, const char *entityTextPtr, const char *entityTextEnd) { - DTD * const dtd = _dtd; /* save one level of indirection */ - STRING_POOL *pool = &(dtd->entityValuePool); - enum XML_Error result = XML_ERROR_NONE; + DTD * const dtd = _dtd; /* save one level of indirection */ + STRING_POOL *pool = &(dtd->entityValuePool); + enum XML_Error result = XML_ERROR_NONE; #ifdef XML_DTD - int oldInEntityValue = prologState.inEntityValue; - prologState.inEntityValue = 1; + int oldInEntityValue = prologState.inEntityValue; + prologState.inEntityValue = 1; #endif /* XML_DTD */ - /* never return Null for the value argument in EntityDeclHandler, - since this would indicate an external entity; therefore we - have to make sure that entityValuePool.start is not null */ - if (!pool->blocks) - { - if (!poolGrow(pool)) - return XML_ERROR_NO_MEMORY; - } - - for (;;) - { - const char *next; - int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); - switch (tok) - { - case XML_TOK_PARAM_ENTITY_REF: + /* never return Null for the value argument in EntityDeclHandler, + since this would indicate an external entity; therefore we + have to make sure that entityValuePool.start is not null */ + if (!pool->blocks) { + if (!poolGrow(pool)) + return XML_ERROR_NO_MEMORY; + } + + for (;;) { + const char *next; + int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); + switch (tok) { + case XML_TOK_PARAM_ENTITY_REF: #ifdef XML_DTD - if (isParamEntity || enc != encoding) - { - const XML_Char *name; - ENTITY *entity; - name = poolStoreString(&tempPool, enc, - entityTextPtr + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!name) - { - result = XML_ERROR_NO_MEMORY; - goto endEntityValue; - } - entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); - poolDiscard(&tempPool); - if (!entity) - { - /* not a well-formedness error - see XML 1.0: WFC Entity Declared */ - /* cannot report skipped entity here - see comments on - skippedEntityHandler - if (skippedEntityHandler) - skippedEntityHandler(handlerArg, name, 0); - */ - dtd->keepProcessing = dtd->standalone; - goto endEntityValue; - } - if (entity->open) - { - if (enc == encoding) - eventPtr = entityTextPtr; - result = XML_ERROR_RECURSIVE_ENTITY_REF; - goto endEntityValue; - } - if (entity->systemId) - { - if (externalEntityRefHandler) - { - dtd->paramEntityRead = XML_FALSE; - entity->open = XML_TRUE; - if (!externalEntityRefHandler(externalEntityRefHandlerArg, - 0, - entity->base, - entity->systemId, - entity->publicId)) - { - entity->open = XML_FALSE; - result = XML_ERROR_EXTERNAL_ENTITY_HANDLING; - goto endEntityValue; - } - entity->open = XML_FALSE; - if (!dtd->paramEntityRead) - dtd->keepProcessing = dtd->standalone; - } - else - dtd->keepProcessing = dtd->standalone; - } - else - { - entity->open = XML_TRUE; - result = storeEntityValue(parser, - internalEncoding, - (char *)entity->textPtr, - (char *)(entity->textPtr - + entity->textLen)); - entity->open = XML_FALSE; - if (result) - goto endEntityValue; - } - break; - } -#endif /* XML_DTD */ - /* In the internal subset, PE references are not legal - within markup declarations, e.g entity values in this case. */ + if (isParamEntity || enc != encoding) { + const XML_Char *name; + ENTITY *entity; + name = poolStoreString(&tempPool, enc, + entityTextPtr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; + } + entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); + poolDiscard(&tempPool); + if (!entity) { + /* not a well-formedness error - see XML 1.0: WFC Entity Declared */ + /* cannot report skipped entity here - see comments on + skippedEntityHandler + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, name, 0); + */ + dtd->keepProcessing = dtd->standalone; + goto endEntityValue; + } + if (entity->open) { + if (enc == encoding) eventPtr = entityTextPtr; - result = XML_ERROR_PARAM_ENTITY_REF; - goto endEntityValue; - case XML_TOK_NONE: - result = XML_ERROR_NONE; - goto endEntityValue; - case XML_TOK_ENTITY_REF: - case XML_TOK_DATA_CHARS: - if (!poolAppend(pool, enc, entityTextPtr, next)) - { - result = XML_ERROR_NO_MEMORY; - goto endEntityValue; - } - break; - case XML_TOK_TRAILING_CR: - next = entityTextPtr + enc->minBytesPerChar; - /* fall through */ - case XML_TOK_DATA_NEWLINE: - if (pool->end == pool->ptr && !poolGrow(pool)) - { - result = XML_ERROR_NO_MEMORY; - goto endEntityValue; - } - *(pool->ptr)++ = 0xA; - break; - case XML_TOK_CHAR_REF: - { - XML_Char buf[XML_ENCODE_MAX]; - int i; - int n = XmlCharRefNumber(enc, entityTextPtr); - if (n < 0) - { - if (enc == encoding) - eventPtr = entityTextPtr; - result = XML_ERROR_BAD_CHAR_REF; - goto endEntityValue; - } - n = XmlEncode(n, (ICHAR *)buf); - if (!n) - { - if (enc == encoding) - eventPtr = entityTextPtr; - result = XML_ERROR_BAD_CHAR_REF; - goto endEntityValue; - } - for (i = 0; i < n; i++) - { - if (pool->end == pool->ptr && !poolGrow(pool)) - { - result = XML_ERROR_NO_MEMORY; - goto endEntityValue; - } - *(pool->ptr)++ = buf[i]; + result = XML_ERROR_RECURSIVE_ENTITY_REF; + goto endEntityValue; + } + if (entity->systemId) { + if (externalEntityRefHandler) { + dtd->paramEntityRead = XML_FALSE; + entity->open = XML_TRUE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) { + entity->open = XML_FALSE; + result = XML_ERROR_EXTERNAL_ENTITY_HANDLING; + goto endEntityValue; } + entity->open = XML_FALSE; + if (!dtd->paramEntityRead) + dtd->keepProcessing = dtd->standalone; + } + else + dtd->keepProcessing = dtd->standalone; } - break; - case XML_TOK_PARTIAL: - if (enc == encoding) - eventPtr = entityTextPtr; - result = XML_ERROR_INVALID_TOKEN; - goto endEntityValue; - case XML_TOK_INVALID: - if (enc == encoding) - eventPtr = next; - result = XML_ERROR_INVALID_TOKEN; + else { + entity->open = XML_TRUE; + result = storeEntityValue(parser, + internalEncoding, + (char *)entity->textPtr, + (char *)(entity->textPtr + + entity->textLen)); + entity->open = XML_FALSE; + if (result) goto endEntityValue; - default: - if (enc == encoding) - eventPtr = entityTextPtr; - result = XML_ERROR_UNEXPECTED_STATE; + } + break; + } +#endif /* XML_DTD */ + /* In the internal subset, PE references are not legal + within markup declarations, e.g entity values in this case. */ + eventPtr = entityTextPtr; + result = XML_ERROR_PARAM_ENTITY_REF; + goto endEntityValue; + case XML_TOK_NONE: + result = XML_ERROR_NONE; + goto endEntityValue; + case XML_TOK_ENTITY_REF: + case XML_TOK_DATA_CHARS: + if (!poolAppend(pool, enc, entityTextPtr, next)) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; + } + break; + case XML_TOK_TRAILING_CR: + next = entityTextPtr + enc->minBytesPerChar; + /* fall through */ + case XML_TOK_DATA_NEWLINE: + if (pool->end == pool->ptr && !poolGrow(pool)) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; + } + *(pool->ptr)++ = 0xA; + break; + case XML_TOK_CHAR_REF: + { + XML_Char buf[XML_ENCODE_MAX]; + int i; + int n = XmlCharRefNumber(enc, entityTextPtr); + if (n < 0) { + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_BAD_CHAR_REF; + goto endEntityValue; + } + n = XmlEncode(n, (ICHAR *)buf); + if (!n) { + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_BAD_CHAR_REF; + goto endEntityValue; + } + for (i = 0; i < n; i++) { + if (pool->end == pool->ptr && !poolGrow(pool)) { + result = XML_ERROR_NO_MEMORY; goto endEntityValue; + } + *(pool->ptr)++ = buf[i]; } - entityTextPtr = next; + } + break; + case XML_TOK_PARTIAL: + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_INVALID_TOKEN; + goto endEntityValue; + case XML_TOK_INVALID: + if (enc == encoding) + eventPtr = next; + result = XML_ERROR_INVALID_TOKEN; + goto endEntityValue; + default: + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_UNEXPECTED_STATE; + goto endEntityValue; } + entityTextPtr = next; + } endEntityValue: #ifdef XML_DTD - prologState.inEntityValue = oldInEntityValue; + prologState.inEntityValue = oldInEntityValue; #endif /* XML_DTD */ - return result; + return result; } static void FASTCALL normalizeLines(XML_Char *s) { - XML_Char *p; - for (;; s++) - { - if (*s == XML_T('\0')) - return; - if (*s == 0xD) - break; - } - p = s; - do - { - if (*s == 0xD) - { - *p++ = 0xA; - if (*++s == 0xA) - s++; - } - else - *p++ = *s++; + XML_Char *p; + for (;; s++) { + if (*s == XML_T('\0')) + return; + if (*s == 0xD) + break; + } + p = s; + do { + if (*s == 0xD) { + *p++ = 0xA; + if (*++s == 0xA) + s++; } - while (*s); - *p = XML_T('\0'); + else + *p++ = *s++; + } while (*s); + *p = XML_T('\0'); } static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { - const XML_Char *target; - XML_Char *data; - const char *tem; - if (!processingInstructionHandler) - { - if (defaultHandler) - reportDefault(parser, enc, start, end); - return 1; - } - start += enc->minBytesPerChar * 2; - tem = start + XmlNameLength(enc, start); - target = poolStoreString(&tempPool, enc, start, tem); - if (!target) - return 0; - poolFinish(&tempPool); - data = poolStoreString(&tempPool, enc, - XmlSkipS(enc, tem), - end - enc->minBytesPerChar*2); - if (!data) - return 0; - normalizeLines(data); - processingInstructionHandler(handlerArg, target, data); - poolClear(&tempPool); + const XML_Char *target; + XML_Char *data; + const char *tem; + if (!processingInstructionHandler) { + if (defaultHandler) + reportDefault(parser, enc, start, end); return 1; + } + start += enc->minBytesPerChar * 2; + tem = start + XmlNameLength(enc, start); + target = poolStoreString(&tempPool, enc, start, tem); + if (!target) + return 0; + poolFinish(&tempPool); + data = poolStoreString(&tempPool, enc, + XmlSkipS(enc, tem), + end - enc->minBytesPerChar*2); + if (!data) + return 0; + normalizeLines(data); + processingInstructionHandler(handlerArg, target, data); + poolClear(&tempPool); + return 1; } static int reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { - XML_Char *data; - if (!commentHandler) - { - if (defaultHandler) - reportDefault(parser, enc, start, end); - return 1; - } - data = poolStoreString(&tempPool, - enc, - start + enc->minBytesPerChar * 4, - end - enc->minBytesPerChar * 3); - if (!data) - return 0; - normalizeLines(data); - commentHandler(handlerArg, data); - poolClear(&tempPool); + XML_Char *data; + if (!commentHandler) { + if (defaultHandler) + reportDefault(parser, enc, start, end); return 1; + } + data = poolStoreString(&tempPool, + enc, + start + enc->minBytesPerChar * 4, + end - enc->minBytesPerChar * 3); + if (!data) + return 0; + normalizeLines(data); + commentHandler(handlerArg, data); + poolClear(&tempPool); + return 1; } static void reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end) { - if (MUST_CONVERT(enc, s)) - { - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) - { - eventPP = &eventPtr; - eventEndPP = &eventEndPtr; - } - else - { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - do - { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = s; - defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - *eventPP = s; - } - while (s != end); + if (MUST_CONVERT(enc, s)) { + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; } - else - defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s); + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + do { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = s; + defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); + *eventPP = s; + } while (s != end); + } + else + defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s); } @@ -5539,148 +5141,135 @@ static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, XML_Bool isId, const XML_Char *value, XML_Parser parser) { - DEFAULT_ATTRIBUTE *att; - if (value || isId) - { - /* The handling of default attributes gets messed up if we have - a default which duplicates a non-default. */ - int i; - for (i = 0; i < type->nDefaultAtts; i++) - if (attId == type->defaultAtts[i].id) - return 1; - if (isId && !type->idAtt && !attId->xmlns) - type->idAtt = attId; + DEFAULT_ATTRIBUTE *att; + if (value || isId) { + /* The handling of default attributes gets messed up if we have + a default which duplicates a non-default. */ + int i; + for (i = 0; i < type->nDefaultAtts; i++) + if (attId == type->defaultAtts[i].id) + return 1; + if (isId && !type->idAtt && !attId->xmlns) + type->idAtt = attId; + } + if (type->nDefaultAtts == type->allocDefaultAtts) { + if (type->allocDefaultAtts == 0) { + type->allocDefaultAtts = 8; + type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts + * sizeof(DEFAULT_ATTRIBUTE)); + if (!type->defaultAtts) + return 0; } - if (type->nDefaultAtts == type->allocDefaultAtts) - { - if (type->allocDefaultAtts == 0) - { - type->allocDefaultAtts = 8; - type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts - * sizeof(DEFAULT_ATTRIBUTE)); - if (!type->defaultAtts) - return 0; - } - else - { - DEFAULT_ATTRIBUTE *temp; - int count = type->allocDefaultAtts * 2; - temp = (DEFAULT_ATTRIBUTE *) - REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE))); - if (temp == NULL) - return 0; - type->allocDefaultAtts = count; - type->defaultAtts = temp; - } + else { + DEFAULT_ATTRIBUTE *temp; + int count = type->allocDefaultAtts * 2; + temp = (DEFAULT_ATTRIBUTE *) + REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE))); + if (temp == NULL) + return 0; + type->allocDefaultAtts = count; + type->defaultAtts = temp; } - att = type->defaultAtts + type->nDefaultAtts; - att->id = attId; - att->value = value; - att->isCdata = isCdata; - if (!isCdata) - attId->maybeTokenized = XML_TRUE; - type->nDefaultAtts += 1; - return 1; + } + att = type->defaultAtts + type->nDefaultAtts; + att->id = attId; + att->value = value; + att->isCdata = isCdata; + if (!isCdata) + attId->maybeTokenized = XML_TRUE; + type->nDefaultAtts += 1; + return 1; } static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) { - DTD * const dtd = _dtd; /* save one level of indirection */ - const XML_Char *name; - for (name = elementType->name; *name; name++) - { - if (*name == XML_T(':')) - { - PREFIX *prefix; - const XML_Char *s; - for (s = elementType->name; s != name; s++) - { - if (!poolAppendChar(&dtd->pool, *s)) - return 0; - } - if (!poolAppendChar(&dtd->pool, XML_T('\0'))) - return 0; - prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), - sizeof(PREFIX)); - if (!prefix) - return 0; - if (prefix->name == poolStart(&dtd->pool)) - poolFinish(&dtd->pool); - else - poolDiscard(&dtd->pool); - elementType->prefix = prefix; + DTD * const dtd = _dtd; /* save one level of indirection */ + const XML_Char *name; + for (name = elementType->name; *name; name++) { + if (*name == XML_T(':')) { + PREFIX *prefix; + const XML_Char *s; + for (s = elementType->name; s != name; s++) { + if (!poolAppendChar(&dtd->pool, *s)) + return 0; + } + if (!poolAppendChar(&dtd->pool, XML_T('\0'))) + return 0; + prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), + sizeof(PREFIX)); + if (!prefix) + return 0; + if (prefix->name == poolStart(&dtd->pool)) + poolFinish(&dtd->pool); + else + poolDiscard(&dtd->pool); + elementType->prefix = prefix; - } } - return 1; + } + return 1; } static ATTRIBUTE_ID * getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { - DTD * const dtd = _dtd; /* save one level of indirection */ - ATTRIBUTE_ID *id; - const XML_Char *name; - if (!poolAppendChar(&dtd->pool, XML_T('\0'))) - return NULL; - name = poolStoreString(&dtd->pool, enc, start, end); - if (!name) - return NULL; - /* skip quotation mark - its storage will be re-used (like in name[-1]) */ - ++name; - id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID)); - if (!id) - return NULL; - if (id->name != name) - poolDiscard(&dtd->pool); - else - { - poolFinish(&dtd->pool); - if (!ns) - ; - else if (name[0] == XML_T('x') - && name[1] == XML_T('m') - && name[2] == XML_T('l') - && name[3] == XML_T('n') - && name[4] == XML_T('s') - && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) - { - if (name[5] == XML_T('\0')) - id->prefix = &dtd->defaultPrefix; - else - id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX)); - id->xmlns = XML_TRUE; - } - else - { - int i; - for (i = 0; name[i]; i++) - { - /* attributes without prefix are *not* in the default namespace */ - if (name[i] == XML_T(':')) - { - int j; - for (j = 0; j < i; j++) - { - if (!poolAppendChar(&dtd->pool, name[j])) - return NULL; - } - if (!poolAppendChar(&dtd->pool, XML_T('\0'))) - return NULL; - id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), - sizeof(PREFIX)); - if (id->prefix->name == poolStart(&dtd->pool)) - poolFinish(&dtd->pool); - else - poolDiscard(&dtd->pool); - break; - } - } + DTD * const dtd = _dtd; /* save one level of indirection */ + ATTRIBUTE_ID *id; + const XML_Char *name; + if (!poolAppendChar(&dtd->pool, XML_T('\0'))) + return NULL; + name = poolStoreString(&dtd->pool, enc, start, end); + if (!name) + return NULL; + /* skip quotation mark - its storage will be re-used (like in name[-1]) */ + ++name; + id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID)); + if (!id) + return NULL; + if (id->name != name) + poolDiscard(&dtd->pool); + else { + poolFinish(&dtd->pool); + if (!ns) + ; + else if (name[0] == XML_T('x') + && name[1] == XML_T('m') + && name[2] == XML_T('l') + && name[3] == XML_T('n') + && name[4] == XML_T('s') + && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) { + if (name[5] == XML_T('\0')) + id->prefix = &dtd->defaultPrefix; + else + id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX)); + id->xmlns = XML_TRUE; + } + else { + int i; + for (i = 0; name[i]; i++) { + /* attributes without prefix are *not* in the default namespace */ + if (name[i] == XML_T(':')) { + int j; + for (j = 0; j < i; j++) { + if (!poolAppendChar(&dtd->pool, name[j])) + return NULL; + } + if (!poolAppendChar(&dtd->pool, XML_T('\0'))) + return NULL; + id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), + sizeof(PREFIX)); + if (id->prefix->name == poolStart(&dtd->pool)) + poolFinish(&dtd->pool); + else + poolDiscard(&dtd->pool); + break; } + } } - return id; + } + return id; } #define CONTEXT_SEP XML_T('\f') @@ -5688,270 +5277,256 @@ getAttributeId(XML_Parser parser, const ENCODING *enc, static const XML_Char * getContext(XML_Parser parser) { - DTD * const dtd = _dtd; /* save one level of indirection */ - HASH_TABLE_ITER iter; - XML_Bool needSep = XML_FALSE; - - if (dtd->defaultPrefix.binding) - { - int i; - int len; - if (!poolAppendChar(&tempPool, XML_T('='))) - return NULL; - len = dtd->defaultPrefix.binding->uriLen; - if (namespaceSeparator != XML_T('\0')) - len--; - for (i = 0; i < len; i++) - if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i])) - return NULL; - needSep = XML_TRUE; - } - - hashTableIterInit(&iter, &(dtd->prefixes)); - for (;;) - { - int i; - int len; - const XML_Char *s; - PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); - if (!prefix) - break; - if (!prefix->binding) - continue; - if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) - return NULL; - for (s = prefix->name; *s; s++) - if (!poolAppendChar(&tempPool, *s)) - return NULL; - if (!poolAppendChar(&tempPool, XML_T('='))) - return NULL; - len = prefix->binding->uriLen; - if (namespaceSeparator != XML_T('\0')) - len--; - for (i = 0; i < len; i++) - if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) - return NULL; - needSep = XML_TRUE; - } + DTD * const dtd = _dtd; /* save one level of indirection */ + HASH_TABLE_ITER iter; + XML_Bool needSep = XML_FALSE; + if (dtd->defaultPrefix.binding) { + int i; + int len; + if (!poolAppendChar(&tempPool, XML_T('='))) + return NULL; + len = dtd->defaultPrefix.binding->uriLen; + if (namespaceSeparator != XML_T('\0')) + len--; + for (i = 0; i < len; i++) + if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i])) + return NULL; + needSep = XML_TRUE; + } - hashTableIterInit(&iter, &(dtd->generalEntities)); - for (;;) - { - const XML_Char *s; - ENTITY *e = (ENTITY *)hashTableIterNext(&iter); - if (!e) - break; - if (!e->open) - continue; - if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) - return NULL; - for (s = e->name; *s; s++) - if (!poolAppendChar(&tempPool, *s)) - return 0; - needSep = XML_TRUE; - } - - if (!poolAppendChar(&tempPool, XML_T('\0'))) + hashTableIterInit(&iter, &(dtd->prefixes)); + for (;;) { + int i; + int len; + const XML_Char *s; + PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); + if (!prefix) + break; + if (!prefix->binding) + continue; + if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) + return NULL; + for (s = prefix->name; *s; s++) + if (!poolAppendChar(&tempPool, *s)) + return NULL; + if (!poolAppendChar(&tempPool, XML_T('='))) + return NULL; + len = prefix->binding->uriLen; + if (namespaceSeparator != XML_T('\0')) + len--; + for (i = 0; i < len; i++) + if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) return NULL; - return tempPool.start; + needSep = XML_TRUE; + } + + + hashTableIterInit(&iter, &(dtd->generalEntities)); + for (;;) { + const XML_Char *s; + ENTITY *e = (ENTITY *)hashTableIterNext(&iter); + if (!e) + break; + if (!e->open) + continue; + if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) + return NULL; + for (s = e->name; *s; s++) + if (!poolAppendChar(&tempPool, *s)) + return 0; + needSep = XML_TRUE; + } + + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return NULL; + return tempPool.start; } static XML_Bool setContext(XML_Parser parser, const XML_Char *context) { - DTD * const dtd = _dtd; /* save one level of indirection */ - const XML_Char *s = context; + DTD * const dtd = _dtd; /* save one level of indirection */ + const XML_Char *s = context; - while (*context != XML_T('\0')) - { - if (*s == CONTEXT_SEP || *s == XML_T('\0')) - { - ENTITY *e; - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return XML_FALSE; - e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0); - if (e) - e->open = XML_TRUE; - if (*s != XML_T('\0')) - s++; - context = s; - poolDiscard(&tempPool); - } - else if (*s == XML_T('=')) - { - PREFIX *prefix; - if (poolLength(&tempPool) == 0) - prefix = &dtd->defaultPrefix; - else - { - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return XML_FALSE; - prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool), - sizeof(PREFIX)); - if (!prefix) - return XML_FALSE; - if (prefix->name == poolStart(&tempPool)) - { - prefix->name = poolCopyString(&dtd->pool, prefix->name); - if (!prefix->name) - return XML_FALSE; - } - poolDiscard(&tempPool); - } - for (context = s + 1; - *context != CONTEXT_SEP && *context != XML_T('\0'); - context++) - if (!poolAppendChar(&tempPool, *context)) - return XML_FALSE; - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return XML_FALSE; - if (addBinding(parser, prefix, NULL, poolStart(&tempPool), - &inheritedBindings) != XML_ERROR_NONE) - return XML_FALSE; - poolDiscard(&tempPool); - if (*context != XML_T('\0')) - ++context; - s = context; - } - else - { - if (!poolAppendChar(&tempPool, *s)) - return XML_FALSE; - s++; + while (*context != XML_T('\0')) { + if (*s == CONTEXT_SEP || *s == XML_T('\0')) { + ENTITY *e; + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return XML_FALSE; + e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0); + if (e) + e->open = XML_TRUE; + if (*s != XML_T('\0')) + s++; + context = s; + poolDiscard(&tempPool); + } + else if (*s == XML_T('=')) { + PREFIX *prefix; + if (poolLength(&tempPool) == 0) + prefix = &dtd->defaultPrefix; + else { + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return XML_FALSE; + prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool), + sizeof(PREFIX)); + if (!prefix) + return XML_FALSE; + if (prefix->name == poolStart(&tempPool)) { + prefix->name = poolCopyString(&dtd->pool, prefix->name); + if (!prefix->name) + return XML_FALSE; } + poolDiscard(&tempPool); + } + for (context = s + 1; + *context != CONTEXT_SEP && *context != XML_T('\0'); + context++) + if (!poolAppendChar(&tempPool, *context)) + return XML_FALSE; + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return XML_FALSE; + if (addBinding(parser, prefix, NULL, poolStart(&tempPool), + &inheritedBindings) != XML_ERROR_NONE) + return XML_FALSE; + poolDiscard(&tempPool); + if (*context != XML_T('\0')) + ++context; + s = context; + } + else { + if (!poolAppendChar(&tempPool, *s)) + return XML_FALSE; + s++; } - return XML_TRUE; + } + return XML_TRUE; } static void FASTCALL normalizePublicId(XML_Char *publicId) { - XML_Char *p = publicId; - XML_Char *s; - for (s = publicId; *s; s++) - { - switch (*s) - { - case 0x20: - case 0xD: - case 0xA: - if (p != publicId && p[-1] != 0x20) - *p++ = 0x20; - break; - default: - *p++ = *s; - } + XML_Char *p = publicId; + XML_Char *s; + for (s = publicId; *s; s++) { + switch (*s) { + case 0x20: + case 0xD: + case 0xA: + if (p != publicId && p[-1] != 0x20) + *p++ = 0x20; + break; + default: + *p++ = *s; } - if (p != publicId && p[-1] == 0x20) - --p; - *p = XML_T('\0'); + } + if (p != publicId && p[-1] == 0x20) + --p; + *p = XML_T('\0'); } static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms) { - DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD)); - if (p == NULL) - return p; - poolInit(&(p->pool), ms); - poolInit(&(p->entityValuePool), ms); - hashTableInit(&(p->generalEntities), ms); - hashTableInit(&(p->elementTypes), ms); - hashTableInit(&(p->attributeIds), ms); - hashTableInit(&(p->prefixes), ms); + DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD)); + if (p == NULL) + return p; + poolInit(&(p->pool), ms); + poolInit(&(p->entityValuePool), ms); + hashTableInit(&(p->generalEntities), ms); + hashTableInit(&(p->elementTypes), ms); + hashTableInit(&(p->attributeIds), ms); + hashTableInit(&(p->prefixes), ms); #ifdef XML_DTD - p->paramEntityRead = XML_FALSE; - hashTableInit(&(p->paramEntities), ms); + p->paramEntityRead = XML_FALSE; + hashTableInit(&(p->paramEntities), ms); #endif /* XML_DTD */ - p->defaultPrefix.name = NULL; - p->defaultPrefix.binding = NULL; - - p->in_eldecl = XML_FALSE; - p->scaffIndex = NULL; - p->scaffold = NULL; - p->scaffLevel = 0; - p->scaffSize = 0; - p->scaffCount = 0; - p->contentStringLen = 0; - - p->keepProcessing = XML_TRUE; - p->hasParamEntityRefs = XML_FALSE; - p->standalone = XML_FALSE; - return p; + p->defaultPrefix.name = NULL; + p->defaultPrefix.binding = NULL; + + p->in_eldecl = XML_FALSE; + p->scaffIndex = NULL; + p->scaffold = NULL; + p->scaffLevel = 0; + p->scaffSize = 0; + p->scaffCount = 0; + p->contentStringLen = 0; + + p->keepProcessing = XML_TRUE; + p->hasParamEntityRefs = XML_FALSE; + p->standalone = XML_FALSE; + return p; } static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) { - HASH_TABLE_ITER iter; - hashTableIterInit(&iter, &(p->elementTypes)); - for (;;) - { - ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); - if (!e) - break; - if (e->allocDefaultAtts != 0) - ms->free_fcn(e->defaultAtts); - } - hashTableClear(&(p->generalEntities)); + HASH_TABLE_ITER iter; + hashTableIterInit(&iter, &(p->elementTypes)); + for (;;) { + ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!e) + break; + if (e->allocDefaultAtts != 0) + ms->free_fcn(e->defaultAtts); + } + hashTableClear(&(p->generalEntities)); #ifdef XML_DTD - p->paramEntityRead = XML_FALSE; - hashTableClear(&(p->paramEntities)); + p->paramEntityRead = XML_FALSE; + hashTableClear(&(p->paramEntities)); #endif /* XML_DTD */ - hashTableClear(&(p->elementTypes)); - hashTableClear(&(p->attributeIds)); - hashTableClear(&(p->prefixes)); - poolClear(&(p->pool)); - poolClear(&(p->entityValuePool)); - p->defaultPrefix.name = NULL; - p->defaultPrefix.binding = NULL; + hashTableClear(&(p->elementTypes)); + hashTableClear(&(p->attributeIds)); + hashTableClear(&(p->prefixes)); + poolClear(&(p->pool)); + poolClear(&(p->entityValuePool)); + p->defaultPrefix.name = NULL; + p->defaultPrefix.binding = NULL; - p->in_eldecl = XML_FALSE; + p->in_eldecl = XML_FALSE; - ms->free_fcn(p->scaffIndex); - p->scaffIndex = NULL; - ms->free_fcn(p->scaffold); - p->scaffold = NULL; + ms->free_fcn(p->scaffIndex); + p->scaffIndex = NULL; + ms->free_fcn(p->scaffold); + p->scaffold = NULL; - p->scaffLevel = 0; - p->scaffSize = 0; - p->scaffCount = 0; - p->contentStringLen = 0; + p->scaffLevel = 0; + p->scaffSize = 0; + p->scaffCount = 0; + p->contentStringLen = 0; - p->keepProcessing = XML_TRUE; - p->hasParamEntityRefs = XML_FALSE; - p->standalone = XML_FALSE; + p->keepProcessing = XML_TRUE; + p->hasParamEntityRefs = XML_FALSE; + p->standalone = XML_FALSE; } static void dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) { - HASH_TABLE_ITER iter; - hashTableIterInit(&iter, &(p->elementTypes)); - for (;;) - { - ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); - if (!e) - break; - if (e->allocDefaultAtts != 0) - ms->free_fcn(e->defaultAtts); - } - hashTableDestroy(&(p->generalEntities)); + HASH_TABLE_ITER iter; + hashTableIterInit(&iter, &(p->elementTypes)); + for (;;) { + ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!e) + break; + if (e->allocDefaultAtts != 0) + ms->free_fcn(e->defaultAtts); + } + hashTableDestroy(&(p->generalEntities)); #ifdef XML_DTD - hashTableDestroy(&(p->paramEntities)); + hashTableDestroy(&(p->paramEntities)); #endif /* XML_DTD */ - hashTableDestroy(&(p->elementTypes)); - hashTableDestroy(&(p->attributeIds)); - hashTableDestroy(&(p->prefixes)); - poolDestroy(&(p->pool)); - poolDestroy(&(p->entityValuePool)); - if (isDocEntity) - { - ms->free_fcn(p->scaffIndex); - ms->free_fcn(p->scaffold); - } - ms->free_fcn(p); + hashTableDestroy(&(p->elementTypes)); + hashTableDestroy(&(p->attributeIds)); + hashTableDestroy(&(p->prefixes)); + poolDestroy(&(p->pool)); + poolDestroy(&(p->entityValuePool)); + if (isDocEntity) { + ms->free_fcn(p->scaffIndex); + ms->free_fcn(p->scaffold); + } + ms->free_fcn(p); } /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise. @@ -5960,139 +5535,131 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) static int dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms) { - HASH_TABLE_ITER iter; - - /* Copy the prefix table. */ - - hashTableIterInit(&iter, &(oldDtd->prefixes)); - for (;;) - { - const XML_Char *name; - const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); - if (!oldP) - break; - name = poolCopyString(&(newDtd->pool), oldP->name); - if (!name) - return 0; - if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX))) - return 0; - } - - hashTableIterInit(&iter, &(oldDtd->attributeIds)); - - /* Copy the attribute id table. */ - - for (;;) - { - ATTRIBUTE_ID *newA; - const XML_Char *name; - const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); + HASH_TABLE_ITER iter; - if (!oldA) - break; - /* Remember to allocate the scratch byte before the name. */ - if (!poolAppendChar(&(newDtd->pool), XML_T('\0'))) - return 0; - name = poolCopyString(&(newDtd->pool), oldA->name); - if (!name) - return 0; - ++name; - newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, - sizeof(ATTRIBUTE_ID)); - if (!newA) - return 0; - newA->maybeTokenized = oldA->maybeTokenized; - if (oldA->prefix) - { - newA->xmlns = oldA->xmlns; - if (oldA->prefix == &oldDtd->defaultPrefix) - newA->prefix = &newDtd->defaultPrefix; - else - newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), - oldA->prefix->name, 0); - } - } + /* Copy the prefix table. */ - /* Copy the element type table. */ + hashTableIterInit(&iter, &(oldDtd->prefixes)); + for (;;) { + const XML_Char *name; + const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); + if (!oldP) + break; + name = poolCopyString(&(newDtd->pool), oldP->name); + if (!name) + return 0; + if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX))) + return 0; + } - hashTableIterInit(&iter, &(oldDtd->elementTypes)); + hashTableIterInit(&iter, &(oldDtd->attributeIds)); - for (;;) - { - int i; - ELEMENT_TYPE *newE; - const XML_Char *name; - const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); - if (!oldE) - break; - name = poolCopyString(&(newDtd->pool), oldE->name); - if (!name) - return 0; - newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, - sizeof(ELEMENT_TYPE)); - if (!newE) - return 0; - if (oldE->nDefaultAtts) - { - newE->defaultAtts = (DEFAULT_ATTRIBUTE *) - ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); - if (!newE->defaultAtts) - { - ms->free_fcn(newE); - return 0; - } - } - if (oldE->idAtt) - newE->idAtt = (ATTRIBUTE_ID *) - lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0); - newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; - if (oldE->prefix) - newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), - oldE->prefix->name, 0); - for (i = 0; i < newE->nDefaultAtts; i++) - { - newE->defaultAtts[i].id = (ATTRIBUTE_ID *) - lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); - newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; - if (oldE->defaultAtts[i].value) - { - newE->defaultAtts[i].value - = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); - if (!newE->defaultAtts[i].value) - return 0; - } - else - newE->defaultAtts[i].value = NULL; - } - } + /* Copy the attribute id table. */ - /* Copy the entity tables. */ - if (!copyEntityTable(&(newDtd->generalEntities), - &(newDtd->pool), - &(oldDtd->generalEntities))) + for (;;) { + ATTRIBUTE_ID *newA; + const XML_Char *name; + const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); + + if (!oldA) + break; + /* Remember to allocate the scratch byte before the name. */ + if (!poolAppendChar(&(newDtd->pool), XML_T('\0'))) + return 0; + name = poolCopyString(&(newDtd->pool), oldA->name); + if (!name) + return 0; + ++name; + newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, + sizeof(ATTRIBUTE_ID)); + if (!newA) + return 0; + newA->maybeTokenized = oldA->maybeTokenized; + if (oldA->prefix) { + newA->xmlns = oldA->xmlns; + if (oldA->prefix == &oldDtd->defaultPrefix) + newA->prefix = &newDtd->defaultPrefix; + else + newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), + oldA->prefix->name, 0); + } + } + + /* Copy the element type table. */ + + hashTableIterInit(&iter, &(oldDtd->elementTypes)); + + for (;;) { + int i; + ELEMENT_TYPE *newE; + const XML_Char *name; + const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!oldE) + break; + name = poolCopyString(&(newDtd->pool), oldE->name); + if (!name) + return 0; + newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, + sizeof(ELEMENT_TYPE)); + if (!newE) + return 0; + if (oldE->nDefaultAtts) { + newE->defaultAtts = (DEFAULT_ATTRIBUTE *) + ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); + if (!newE->defaultAtts) { + ms->free_fcn(newE); return 0; + } + } + if (oldE->idAtt) + newE->idAtt = (ATTRIBUTE_ID *) + lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0); + newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; + if (oldE->prefix) + newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), + oldE->prefix->name, 0); + for (i = 0; i < newE->nDefaultAtts; i++) { + newE->defaultAtts[i].id = (ATTRIBUTE_ID *) + lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); + newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; + if (oldE->defaultAtts[i].value) { + newE->defaultAtts[i].value + = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); + if (!newE->defaultAtts[i].value) + return 0; + } + else + newE->defaultAtts[i].value = NULL; + } + } + + /* Copy the entity tables. */ + if (!copyEntityTable(&(newDtd->generalEntities), + &(newDtd->pool), + &(oldDtd->generalEntities))) + return 0; #ifdef XML_DTD - if (!copyEntityTable(&(newDtd->paramEntities), - &(newDtd->pool), - &(oldDtd->paramEntities))) - return 0; - newDtd->paramEntityRead = oldDtd->paramEntityRead; + if (!copyEntityTable(&(newDtd->paramEntities), + &(newDtd->pool), + &(oldDtd->paramEntities))) + return 0; + newDtd->paramEntityRead = oldDtd->paramEntityRead; #endif /* XML_DTD */ - newDtd->keepProcessing = oldDtd->keepProcessing; - newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs; - newDtd->standalone = oldDtd->standalone; + newDtd->keepProcessing = oldDtd->keepProcessing; + newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs; + newDtd->standalone = oldDtd->standalone; - /* Don't want deep copying for scaffolding */ - newDtd->in_eldecl = oldDtd->in_eldecl; - newDtd->scaffold = oldDtd->scaffold; - newDtd->contentStringLen = oldDtd->contentStringLen; - newDtd->scaffSize = oldDtd->scaffSize; - newDtd->scaffLevel = oldDtd->scaffLevel; - newDtd->scaffIndex = oldDtd->scaffIndex; + /* Don't want deep copying for scaffolding */ + newDtd->in_eldecl = oldDtd->in_eldecl; + newDtd->scaffold = oldDtd->scaffold; + newDtd->contentStringLen = oldDtd->contentStringLen; + newDtd->scaffSize = oldDtd->scaffSize; + newDtd->scaffLevel = oldDtd->scaffLevel; + newDtd->scaffIndex = oldDtd->scaffIndex; - return 1; + return 1; } /* End dtdCopy */ static int @@ -6100,72 +5667,65 @@ copyEntityTable(HASH_TABLE *newTable, STRING_POOL *newPool, const HASH_TABLE *oldTable) { - HASH_TABLE_ITER iter; - const XML_Char *cachedOldBase = NULL; - const XML_Char *cachedNewBase = NULL; + HASH_TABLE_ITER iter; + const XML_Char *cachedOldBase = NULL; + const XML_Char *cachedNewBase = NULL; - hashTableIterInit(&iter, oldTable); + hashTableIterInit(&iter, oldTable); - for (;;) - { - ENTITY *newE; - const XML_Char *name; - const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); - if (!oldE) - break; - name = poolCopyString(newPool, oldE->name); - if (!name) - return 0; - newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY)); - if (!newE) + for (;;) { + ENTITY *newE; + const XML_Char *name; + const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); + if (!oldE) + break; + name = poolCopyString(newPool, oldE->name); + if (!name) + return 0; + newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY)); + if (!newE) + return 0; + if (oldE->systemId) { + const XML_Char *tem = poolCopyString(newPool, oldE->systemId); + if (!tem) + return 0; + newE->systemId = tem; + if (oldE->base) { + if (oldE->base == cachedOldBase) + newE->base = cachedNewBase; + else { + cachedOldBase = oldE->base; + tem = poolCopyString(newPool, cachedOldBase); + if (!tem) return 0; - if (oldE->systemId) - { - const XML_Char *tem = poolCopyString(newPool, oldE->systemId); - if (!tem) - return 0; - newE->systemId = tem; - if (oldE->base) - { - if (oldE->base == cachedOldBase) - newE->base = cachedNewBase; - else - { - cachedOldBase = oldE->base; - tem = poolCopyString(newPool, cachedOldBase); - if (!tem) - return 0; - cachedNewBase = newE->base = tem; - } - } - if (oldE->publicId) - { - tem = poolCopyString(newPool, oldE->publicId); - if (!tem) - return 0; - newE->publicId = tem; - } - } - else - { - const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, - oldE->textLen); - if (!tem) - return 0; - newE->textPtr = tem; - newE->textLen = oldE->textLen; - } - if (oldE->notation) - { - const XML_Char *tem = poolCopyString(newPool, oldE->notation); - if (!tem) - return 0; - newE->notation = tem; + cachedNewBase = newE->base = tem; } - newE->is_param = oldE->is_param; - newE->is_internal = oldE->is_internal; + } + if (oldE->publicId) { + tem = poolCopyString(newPool, oldE->publicId); + if (!tem) + return 0; + newE->publicId = tem; + } + } + else { + const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, + oldE->textLen); + if (!tem) + return 0; + newE->textPtr = tem; + newE->textLen = oldE->textLen; } - return 1; + if (oldE->notation) { + const XML_Char *tem = poolCopyString(newPool, oldE->notation); + if (!tem) + return 0; + newE->notation = tem; + } + newE->is_param = oldE->is_param; + newE->is_internal = oldE->is_internal; + } + return 1; } #define INIT_POWER 6 @@ -6173,400 +5733,370 @@ copyEntityTable(HASH_TABLE *newTable, static XML_Bool FASTCALL keyeq(KEY s1, KEY s2) { - for (; *s1 == *s2; s1++, s2++) - if (*s1 == 0) - return XML_TRUE; - return XML_FALSE; + for (; *s1 == *s2; s1++, s2++) + if (*s1 == 0) + return XML_TRUE; + return XML_FALSE; } static unsigned long FASTCALL hash(KEY s) { - unsigned long h = 0; - while (*s) - h = CHAR_HASH(h, *s++); - return h; + unsigned long h = 0; + while (*s) + h = CHAR_HASH(h, *s++); + return h; } static NAMED * lookup(HASH_TABLE *table, KEY name, size_t createSize) { - size_t i; - if (table->size == 0) - { - size_t tsize; - if (!createSize) - return NULL; - table->power = INIT_POWER; - /* table->size is a power of 2 */ - table->size = (size_t)1 << INIT_POWER; - tsize = table->size * sizeof(NAMED *); - table->v = (NAMED **)table->mem->malloc_fcn(tsize); - if (!table->v) - { - table->size = 0; - return NULL; - } - memset(table->v, 0, tsize); - i = hash(name) & ((unsigned long)table->size - 1); - } - else - { - unsigned long h = hash(name); - unsigned long mask = (unsigned long)table->size - 1; - unsigned char step = 0; - i = h & mask; - while (table->v[i]) - { - if (keyeq(name, table->v[i]->name)) - return table->v[i]; + size_t i; + if (table->size == 0) { + size_t tsize; + if (!createSize) + return NULL; + table->power = INIT_POWER; + /* table->size is a power of 2 */ + table->size = (size_t)1 << INIT_POWER; + tsize = table->size * sizeof(NAMED *); + table->v = (NAMED **)table->mem->malloc_fcn(tsize); + if (!table->v) { + table->size = 0; + return NULL; + } + memset(table->v, 0, tsize); + i = hash(name) & ((unsigned long)table->size - 1); + } + else { + unsigned long h = hash(name); + unsigned long mask = (unsigned long)table->size - 1; + unsigned char step = 0; + i = h & mask; + while (table->v[i]) { + if (keyeq(name, table->v[i]->name)) + return table->v[i]; + if (!step) + step = PROBE_STEP(h, mask, table->power); + i < step ? (i += table->size - step) : (i -= step); + } + if (!createSize) + return NULL; + + /* check for overflow (table is half full) */ + if (table->used >> (table->power - 1)) { + unsigned char newPower = table->power + 1; + size_t newSize = (size_t)1 << newPower; + unsigned long newMask = (unsigned long)newSize - 1; + size_t tsize = newSize * sizeof(NAMED *); + NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize); + if (!newV) + return NULL; + memset(newV, 0, tsize); + for (i = 0; i < table->size; i++) + if (table->v[i]) { + unsigned long newHash = hash(table->v[i]->name); + size_t j = newHash & newMask; + step = 0; + while (newV[j]) { if (!step) - step = PROBE_STEP(h, mask, table->power); - i < step ? (i += table->size - step) : (i -= step); - } - if (!createSize) - return NULL; - - /* check for overflow (table is half full) */ - if (table->used >> (table->power - 1)) - { - unsigned char newPower = table->power + 1; - size_t newSize = (size_t)1 << newPower; - unsigned long newMask = (unsigned long)newSize - 1; - size_t tsize = newSize * sizeof(NAMED *); - NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize); - if (!newV) - return NULL; - memset(newV, 0, tsize); - for (i = 0; i < table->size; i++) - if (table->v[i]) - { - unsigned long newHash = hash(table->v[i]->name); - size_t j = newHash & newMask; - step = 0; - while (newV[j]) - { - if (!step) - step = PROBE_STEP(newHash, newMask, newPower); - j < step ? (j += newSize - step) : (j -= step); - } - newV[j] = table->v[i]; - } - table->mem->free_fcn(table->v); - table->v = newV; - table->power = newPower; - table->size = newSize; - i = h & newMask; - step = 0; - while (table->v[i]) - { - if (!step) - step = PROBE_STEP(h, newMask, newPower); - i < step ? (i += newSize - step) : (i -= step); - } + step = PROBE_STEP(newHash, newMask, newPower); + j < step ? (j += newSize - step) : (j -= step); + } + newV[j] = table->v[i]; } - } - table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize); - if (!table->v[i]) - return NULL; - memset(table->v[i], 0, createSize); - table->v[i]->name = name; - (table->used)++; - return table->v[i]; + table->mem->free_fcn(table->v); + table->v = newV; + table->power = newPower; + table->size = newSize; + i = h & newMask; + step = 0; + while (table->v[i]) { + if (!step) + step = PROBE_STEP(h, newMask, newPower); + i < step ? (i += newSize - step) : (i -= step); + } + } + } + table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize); + if (!table->v[i]) + return NULL; + memset(table->v[i], 0, createSize); + table->v[i]->name = name; + (table->used)++; + return table->v[i]; } static void FASTCALL hashTableClear(HASH_TABLE *table) { - size_t i; - for (i = 0; i < table->size; i++) - { - table->mem->free_fcn(table->v[i]); - table->v[i] = NULL; - } - table->used = 0; + size_t i; + for (i = 0; i < table->size; i++) { + table->mem->free_fcn(table->v[i]); + table->v[i] = NULL; + } + table->used = 0; } static void FASTCALL hashTableDestroy(HASH_TABLE *table) { - size_t i; - for (i = 0; i < table->size; i++) - table->mem->free_fcn(table->v[i]); - table->mem->free_fcn(table->v); + size_t i; + for (i = 0; i < table->size; i++) + table->mem->free_fcn(table->v[i]); + table->mem->free_fcn(table->v); } static void FASTCALL hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) { - p->power = 0; - p->size = 0; - p->used = 0; - p->v = NULL; - p->mem = ms; + p->power = 0; + p->size = 0; + p->used = 0; + p->v = NULL; + p->mem = ms; } static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) { - iter->p = table->v; - iter->end = iter->p + table->size; + iter->p = table->v; + iter->end = iter->p + table->size; } static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter) { - while (iter->p != iter->end) - { - NAMED *tem = *(iter->p)++; - if (tem) - return tem; - } - return NULL; + while (iter->p != iter->end) { + NAMED *tem = *(iter->p)++; + if (tem) + return tem; + } + return NULL; } static void FASTCALL poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) { - pool->blocks = NULL; - pool->freeBlocks = NULL; - pool->start = NULL; - pool->ptr = NULL; - pool->end = NULL; - pool->mem = ms; + pool->blocks = NULL; + pool->freeBlocks = NULL; + pool->start = NULL; + pool->ptr = NULL; + pool->end = NULL; + pool->mem = ms; } static void FASTCALL poolClear(STRING_POOL *pool) { - if (!pool->freeBlocks) - pool->freeBlocks = pool->blocks; - else - { - BLOCK *p = pool->blocks; - while (p) - { - BLOCK *tem = p->next; - p->next = pool->freeBlocks; - pool->freeBlocks = p; - p = tem; - } + if (!pool->freeBlocks) + pool->freeBlocks = pool->blocks; + else { + BLOCK *p = pool->blocks; + while (p) { + BLOCK *tem = p->next; + p->next = pool->freeBlocks; + pool->freeBlocks = p; + p = tem; } - pool->blocks = NULL; - pool->start = NULL; - pool->ptr = NULL; - pool->end = NULL; + } + pool->blocks = NULL; + pool->start = NULL; + pool->ptr = NULL; + pool->end = NULL; } static void FASTCALL poolDestroy(STRING_POOL *pool) { - BLOCK *p = pool->blocks; - while (p) - { - BLOCK *tem = p->next; - pool->mem->free_fcn(p); - p = tem; - } - p = pool->freeBlocks; - while (p) - { - BLOCK *tem = p->next; - pool->mem->free_fcn(p); - p = tem; - } + BLOCK *p = pool->blocks; + while (p) { + BLOCK *tem = p->next; + pool->mem->free_fcn(p); + p = tem; + } + p = pool->freeBlocks; + while (p) { + BLOCK *tem = p->next; + pool->mem->free_fcn(p); + p = tem; + } } static XML_Char * poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end) { - if (!pool->ptr && !poolGrow(pool)) - return NULL; - for (;;) - { - XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); - if (ptr == end) - break; - if (!poolGrow(pool)) - return NULL; - } - return pool->start; + if (!pool->ptr && !poolGrow(pool)) + return NULL; + for (;;) { + XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); + if (ptr == end) + break; + if (!poolGrow(pool)) + return NULL; + } + return pool->start; } static const XML_Char * FASTCALL poolCopyString(STRING_POOL *pool, const XML_Char *s) { - do - { - if (!poolAppendChar(pool, *s)) - return NULL; - } - while (*s++); - s = pool->start; - poolFinish(pool); - return s; + do { + if (!poolAppendChar(pool, *s)) + return NULL; + } while (*s++); + s = pool->start; + poolFinish(pool); + return s; } static const XML_Char * poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) { - if (!pool->ptr && !poolGrow(pool)) - return NULL; - for (; n > 0; --n, s++) - { - if (!poolAppendChar(pool, *s)) - return NULL; - } - s = pool->start; - poolFinish(pool); - return s; + if (!pool->ptr && !poolGrow(pool)) + return NULL; + for (; n > 0; --n, s++) { + if (!poolAppendChar(pool, *s)) + return NULL; + } + s = pool->start; + poolFinish(pool); + return s; } static const XML_Char * FASTCALL poolAppendString(STRING_POOL *pool, const XML_Char *s) { - while (*s) - { - if (!poolAppendChar(pool, *s)) - return NULL; - s++; - } - return pool->start; + while (*s) { + if (!poolAppendChar(pool, *s)) + return NULL; + s++; + } + return pool->start; } static XML_Char * poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end) { - if (!poolAppend(pool, enc, ptr, end)) - return NULL; - if (pool->ptr == pool->end && !poolGrow(pool)) - return NULL; - *(pool->ptr)++ = 0; - return pool->start; + if (!poolAppend(pool, enc, ptr, end)) + return NULL; + if (pool->ptr == pool->end && !poolGrow(pool)) + return NULL; + *(pool->ptr)++ = 0; + return pool->start; } static XML_Bool FASTCALL poolGrow(STRING_POOL *pool) { - if (pool->freeBlocks) - { - if (pool->start == 0) - { - pool->blocks = pool->freeBlocks; - pool->freeBlocks = pool->freeBlocks->next; - pool->blocks->next = NULL; - pool->start = pool->blocks->s; - pool->end = pool->start + pool->blocks->size; - pool->ptr = pool->start; - return XML_TRUE; - } - if (pool->end - pool->start < pool->freeBlocks->size) - { - BLOCK *tem = pool->freeBlocks->next; - pool->freeBlocks->next = pool->blocks; - pool->blocks = pool->freeBlocks; - pool->freeBlocks = tem; - memcpy(pool->blocks->s, pool->start, - (pool->end - pool->start) * sizeof(XML_Char)); - pool->ptr = pool->blocks->s + (pool->ptr - pool->start); - pool->start = pool->blocks->s; - pool->end = pool->start + pool->blocks->size; - return XML_TRUE; - } - } - if (pool->blocks && pool->start == pool->blocks->s) - { - int blockSize = (pool->end - pool->start)*2; - pool->blocks = (BLOCK *) - pool->mem->realloc_fcn(pool->blocks, - (offsetof(BLOCK, s) - + blockSize * sizeof(XML_Char))); - if (pool->blocks == NULL) - return XML_FALSE; - pool->blocks->size = blockSize; - pool->ptr = pool->blocks->s + (pool->ptr - pool->start); - pool->start = pool->blocks->s; - pool->end = pool->start + blockSize; - } + if (pool->freeBlocks) { + if (pool->start == 0) { + pool->blocks = pool->freeBlocks; + pool->freeBlocks = pool->freeBlocks->next; + pool->blocks->next = NULL; + pool->start = pool->blocks->s; + pool->end = pool->start + pool->blocks->size; + pool->ptr = pool->start; + return XML_TRUE; + } + if (pool->end - pool->start < pool->freeBlocks->size) { + BLOCK *tem = pool->freeBlocks->next; + pool->freeBlocks->next = pool->blocks; + pool->blocks = pool->freeBlocks; + pool->freeBlocks = tem; + memcpy(pool->blocks->s, pool->start, + (pool->end - pool->start) * sizeof(XML_Char)); + pool->ptr = pool->blocks->s + (pool->ptr - pool->start); + pool->start = pool->blocks->s; + pool->end = pool->start + pool->blocks->size; + return XML_TRUE; + } + } + if (pool->blocks && pool->start == pool->blocks->s) { + int blockSize = (pool->end - pool->start)*2; + pool->blocks = (BLOCK *) + pool->mem->realloc_fcn(pool->blocks, + (offsetof(BLOCK, s) + + blockSize * sizeof(XML_Char))); + if (pool->blocks == NULL) + return XML_FALSE; + pool->blocks->size = blockSize; + pool->ptr = pool->blocks->s + (pool->ptr - pool->start); + pool->start = pool->blocks->s; + pool->end = pool->start + blockSize; + } + else { + BLOCK *tem; + int blockSize = pool->end - pool->start; + if (blockSize < INIT_BLOCK_SIZE) + blockSize = INIT_BLOCK_SIZE; else - { - BLOCK *tem; - int blockSize = pool->end - pool->start; - if (blockSize < INIT_BLOCK_SIZE) - blockSize = INIT_BLOCK_SIZE; - else - blockSize *= 2; - tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s) - + blockSize * sizeof(XML_Char)); - if (!tem) - return XML_FALSE; - tem->size = blockSize; - tem->next = pool->blocks; - pool->blocks = tem; - if (pool->ptr != pool->start) - memcpy(tem->s, pool->start, - (pool->ptr - pool->start) * sizeof(XML_Char)); - pool->ptr = tem->s + (pool->ptr - pool->start); - pool->start = tem->s; - pool->end = tem->s + blockSize; - } - return XML_TRUE; + blockSize *= 2; + tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s) + + blockSize * sizeof(XML_Char)); + if (!tem) + return XML_FALSE; + tem->size = blockSize; + tem->next = pool->blocks; + pool->blocks = tem; + if (pool->ptr != pool->start) + memcpy(tem->s, pool->start, + (pool->ptr - pool->start) * sizeof(XML_Char)); + pool->ptr = tem->s + (pool->ptr - pool->start); + pool->start = tem->s; + pool->end = tem->s + blockSize; + } + return XML_TRUE; } static int FASTCALL nextScaffoldPart(XML_Parser parser) { - DTD * const dtd = _dtd; /* save one level of indirection */ - CONTENT_SCAFFOLD * me; - int next; + DTD * const dtd = _dtd; /* save one level of indirection */ + CONTENT_SCAFFOLD * me; + int next; + if (!dtd->scaffIndex) { + dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int)); if (!dtd->scaffIndex) - { - dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int)); - if (!dtd->scaffIndex) - return -1; - dtd->scaffIndex[0] = 0; - } - - if (dtd->scaffCount >= dtd->scaffSize) - { - CONTENT_SCAFFOLD *temp; - if (dtd->scaffold) - { - temp = (CONTENT_SCAFFOLD *) - REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); - if (temp == NULL) - return -1; - dtd->scaffSize *= 2; - } - else - { - temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS - * sizeof(CONTENT_SCAFFOLD)); - if (temp == NULL) - return -1; - dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS; - } - dtd->scaffold = temp; - } - next = dtd->scaffCount++; - me = &dtd->scaffold[next]; - if (dtd->scaffLevel) - { - CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]]; - if (parent->lastchild) - { - dtd->scaffold[parent->lastchild].nextsib = next; - } - if (!parent->childcnt) - parent->firstchild = next; - parent->lastchild = next; - parent->childcnt++; - } - me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0; - return next; + return -1; + dtd->scaffIndex[0] = 0; + } + + if (dtd->scaffCount >= dtd->scaffSize) { + CONTENT_SCAFFOLD *temp; + if (dtd->scaffold) { + temp = (CONTENT_SCAFFOLD *) + REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); + if (temp == NULL) + return -1; + dtd->scaffSize *= 2; + } + else { + temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS + * sizeof(CONTENT_SCAFFOLD)); + if (temp == NULL) + return -1; + dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS; + } + dtd->scaffold = temp; + } + next = dtd->scaffCount++; + me = &dtd->scaffold[next]; + if (dtd->scaffLevel) { + CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]]; + if (parent->lastchild) { + dtd->scaffold[parent->lastchild].nextsib = next; + } + if (!parent->childcnt) + parent->firstchild = next; + parent->lastchild = next; + parent->childcnt++; + } + me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0; + return next; } static void @@ -6576,60 +6106,56 @@ build_node(XML_Parser parser, XML_Content **contpos, XML_Char **strpos) { - DTD * const dtd = _dtd; /* save one level of indirection */ - dest->type = dtd->scaffold[src_node].type; - dest->quant = dtd->scaffold[src_node].quant; - if (dest->type == XML_CTYPE_NAME) - { - const XML_Char *src; - dest->name = *strpos; - src = dtd->scaffold[src_node].name; - for (;;) - { - *(*strpos)++ = *src; - if (!*src) - break; - src++; - } - dest->numchildren = 0; - dest->children = NULL; - } - else - { - unsigned int i; - int cn; - dest->numchildren = dtd->scaffold[src_node].childcnt; - dest->children = *contpos; - *contpos += dest->numchildren; - for (i = 0, cn = dtd->scaffold[src_node].firstchild; - i < dest->numchildren; - i++, cn = dtd->scaffold[cn].nextsib) - { - build_node(parser, cn, &(dest->children[i]), contpos, strpos); - } - dest->name = NULL; - } + DTD * const dtd = _dtd; /* save one level of indirection */ + dest->type = dtd->scaffold[src_node].type; + dest->quant = dtd->scaffold[src_node].quant; + if (dest->type == XML_CTYPE_NAME) { + const XML_Char *src; + dest->name = *strpos; + src = dtd->scaffold[src_node].name; + for (;;) { + *(*strpos)++ = *src; + if (!*src) + break; + src++; + } + dest->numchildren = 0; + dest->children = NULL; + } + else { + unsigned int i; + int cn; + dest->numchildren = dtd->scaffold[src_node].childcnt; + dest->children = *contpos; + *contpos += dest->numchildren; + for (i = 0, cn = dtd->scaffold[src_node].firstchild; + i < dest->numchildren; + i++, cn = dtd->scaffold[cn].nextsib) { + build_node(parser, cn, &(dest->children[i]), contpos, strpos); + } + dest->name = NULL; + } } static XML_Content * build_model (XML_Parser parser) { - DTD * const dtd = _dtd; /* save one level of indirection */ - XML_Content *ret; - XML_Content *cpos; - XML_Char * str; - int allocsize = (dtd->scaffCount * sizeof(XML_Content) - + (dtd->contentStringLen * sizeof(XML_Char))); - - ret = (XML_Content *)MALLOC(allocsize); - if (!ret) - return NULL; + DTD * const dtd = _dtd; /* save one level of indirection */ + XML_Content *ret; + XML_Content *cpos; + XML_Char * str; + int allocsize = (dtd->scaffCount * sizeof(XML_Content) + + (dtd->contentStringLen * sizeof(XML_Char))); + + ret = (XML_Content *)MALLOC(allocsize); + if (!ret) + return NULL; - str = (XML_Char *) (&ret[dtd->scaffCount]); - cpos = &ret[1]; + str = (XML_Char *) (&ret[dtd->scaffCount]); + cpos = &ret[1]; - build_node(parser, 0, ret, &cpos, &str); - return ret; + build_node(parser, 0, ret, &cpos, &str); + return ret; } static ELEMENT_TYPE * @@ -6638,22 +6164,21 @@ getElementType(XML_Parser parser, const char *ptr, const char *end) { - DTD * const dtd = _dtd; /* save one level of indirection */ - const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end); - ELEMENT_TYPE *ret; + DTD * const dtd = _dtd; /* save one level of indirection */ + const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end); + ELEMENT_TYPE *ret; - if (!name) - return NULL; - ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); - if (!ret) - return NULL; - if (ret->name != name) - poolDiscard(&dtd->pool); - else - { - poolFinish(&dtd->pool); - if (!setElementTypePrefix(parser, ret)) - return NULL; - } - return ret; + if (!name) + return NULL; + ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); + if (!ret) + return NULL; + if (ret->name != name) + poolDiscard(&dtd->pool); + else { + poolFinish(&dtd->pool); + if (!setElementTypePrefix(parser, ret)) + return NULL; + } + return ret; } diff --git a/src/simgear/xml/xmlrole.c b/src/simgear/xml/xmlrole.c old mode 100644 new mode 100755 index 6deceb91f94500f5d0af908056504feb7e58e4ec..1924fcb4dbe243ed7d474cdd450de7ca937dba4b --- a/src/simgear/xml/xmlrole.c +++ b/src/simgear/xml/xmlrole.c @@ -26,101 +26,56 @@ */ -static const char KW_ANY[] = -{ - ASCII_A, ASCII_N, ASCII_Y, '\0' -}; -static const char KW_ATTLIST[] = -{ - ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' -}; -static const char KW_CDATA[] = -{ - ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' -}; -static const char KW_DOCTYPE[] = -{ - ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' -}; -static const char KW_ELEMENT[] = -{ - ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' -}; -static const char KW_EMPTY[] = -{ - ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' -}; -static const char KW_ENTITIES[] = -{ +static const char KW_ANY[] = { + ASCII_A, ASCII_N, ASCII_Y, '\0' }; +static const char KW_ATTLIST[] = { + ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' }; +static const char KW_CDATA[] = { + ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_DOCTYPE[] = { + ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' }; +static const char KW_ELEMENT[] = { + ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' }; +static const char KW_EMPTY[] = { + ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' }; +static const char KW_ENTITIES[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, - '\0' -}; -static const char KW_ENTITY[] = -{ - ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' -}; -static const char KW_FIXED[] = -{ - ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' -}; -static const char KW_ID[] = -{ - ASCII_I, ASCII_D, '\0' -}; -static const char KW_IDREF[] = -{ - ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' -}; -static const char KW_IDREFS[] = -{ - ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' -}; -static const char KW_IGNORE[] = -{ - ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' -}; -static const char KW_IMPLIED[] = -{ - ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' -}; -static const char KW_INCLUDE[] = -{ - ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' -}; -static const char KW_NDATA[] = -{ - ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' -}; -static const char KW_NMTOKEN[] = -{ - ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' -}; -static const char KW_NMTOKENS[] = -{ + '\0' }; +static const char KW_ENTITY[] = { + ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' }; +static const char KW_FIXED[] = { + ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' }; +static const char KW_ID[] = { + ASCII_I, ASCII_D, '\0' }; +static const char KW_IDREF[] = { + ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' }; +static const char KW_IDREFS[] = { + ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' }; +static const char KW_IGNORE[] = { + ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' }; +static const char KW_IMPLIED[] = { + ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' }; +static const char KW_INCLUDE[] = { + ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' }; +static const char KW_NDATA[] = { + ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_NMTOKEN[] = { + ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' }; +static const char KW_NMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, - '\0' -}; + '\0' }; static const char KW_NOTATION[] = { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, - '\0' - }; -static const char KW_PCDATA[] = -{ - ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' -}; -static const char KW_PUBLIC[] = -{ - ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' -}; -static const char KW_REQUIRED[] = -{ + '\0' }; +static const char KW_PCDATA[] = { + ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_PUBLIC[] = { + ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' }; +static const char KW_REQUIRED[] = { ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D, - '\0' -}; -static const char KW_SYSTEM[] = -{ - ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' -}; + '\0' }; +static const char KW_SYSTEM[] = { + ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' }; #ifndef MIN_BYTES_PER_CHAR #define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar) @@ -142,22 +97,22 @@ typedef int PTRCALL PROLOG_HANDLER(PROLOG_STATE *state, const ENCODING *enc); static PROLOG_HANDLER -prolog0, prolog1, prolog2, -doctype0, doctype1, doctype2, doctype3, doctype4, doctype5, -internalSubset, -entity0, entity1, entity2, entity3, entity4, entity5, entity6, -entity7, entity8, entity9, entity10, -notation0, notation1, notation2, notation3, notation4, -attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6, -attlist7, attlist8, attlist9, -element0, element1, element2, element3, element4, element5, element6, -element7, + prolog0, prolog1, prolog2, + doctype0, doctype1, doctype2, doctype3, doctype4, doctype5, + internalSubset, + entity0, entity1, entity2, entity3, entity4, entity5, entity6, + entity7, entity8, entity9, entity10, + notation0, notation1, notation2, notation3, notation4, + attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6, + attlist7, attlist8, attlist9, + element0, element1, element2, element3, element4, element5, element6, + element7, #ifdef XML_DTD -externalSubset0, externalSubset1, -condSect0, condSect1, condSect2, + externalSubset0, externalSubset1, + condSect0, condSect1, condSect2, #endif /* XML_DTD */ -declClose, -error; + declClose, + error; static int FASTCALL common(PROLOG_STATE *state, int tok); @@ -168,35 +123,34 @@ prolog0(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - state->handler = prolog1; - return XML_ROLE_NONE; - case XML_TOK_XML_DECL: - state->handler = prolog1; - return XML_ROLE_XML_DECL; - case XML_TOK_PI: - state->handler = prolog1; - return XML_ROLE_PI; - case XML_TOK_COMMENT: - state->handler = prolog1; - return XML_ROLE_COMMENT; - case XML_TOK_BOM: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (!XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - end, - KW_DOCTYPE)) - break; - state->handler = doctype0; - return XML_ROLE_DOCTYPE_NONE; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + state->handler = prolog1; + return XML_ROLE_NONE; + case XML_TOK_XML_DECL: + state->handler = prolog1; + return XML_ROLE_XML_DECL; + case XML_TOK_PI: + state->handler = prolog1; + return XML_ROLE_PI; + case XML_TOK_COMMENT: + state->handler = prolog1; + return XML_ROLE_COMMENT; + case XML_TOK_BOM: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (!XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_DOCTYPE)) + break; + state->handler = doctype0; + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); } static int PTRCALL @@ -206,29 +160,28 @@ prolog1(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_PI: - return XML_ROLE_PI; - case XML_TOK_COMMENT: - return XML_ROLE_COMMENT; - case XML_TOK_BOM: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (!XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - end, - KW_DOCTYPE)) - break; - state->handler = doctype0; - return XML_ROLE_DOCTYPE_NONE; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_PI: + return XML_ROLE_PI; + case XML_TOK_COMMENT: + return XML_ROLE_COMMENT; + case XML_TOK_BOM: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (!XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_DOCTYPE)) + break; + state->handler = doctype0; + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); } static int PTRCALL @@ -238,19 +191,18 @@ prolog2(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_PI: - return XML_ROLE_PI; - case XML_TOK_COMMENT: - return XML_ROLE_COMMENT; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_PI: + return XML_ROLE_PI; + case XML_TOK_COMMENT: + return XML_ROLE_COMMENT; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); } static int PTRCALL @@ -260,16 +212,15 @@ doctype0(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_DOCTYPE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = doctype1; - return XML_ROLE_DOCTYPE_NAME; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = doctype1; + return XML_ROLE_DOCTYPE_NAME; + } + return common(state, tok); } static int PTRCALL @@ -279,30 +230,27 @@ doctype1(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_DOCTYPE_NONE; - case XML_TOK_OPEN_BRACKET: - state->handler = internalSubset; - return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) - { - state->handler = doctype3; - return XML_ROLE_DOCTYPE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) - { - state->handler = doctype2; - return XML_ROLE_DOCTYPE_NONE; - } - break; + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = internalSubset; + return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = doctype3; + return XML_ROLE_DOCTYPE_NONE; } - return common(state, tok); + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = doctype2; + return XML_ROLE_DOCTYPE_NONE; + } + break; + } + return common(state, tok); } static int PTRCALL @@ -312,15 +260,14 @@ doctype2(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_DOCTYPE_NONE; - case XML_TOK_LITERAL: - state->handler = doctype3; - return XML_ROLE_DOCTYPE_PUBLIC_ID; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_LITERAL: + state->handler = doctype3; + return XML_ROLE_DOCTYPE_PUBLIC_ID; + } + return common(state, tok); } static int PTRCALL @@ -330,15 +277,14 @@ doctype3(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_DOCTYPE_NONE; - case XML_TOK_LITERAL: - state->handler = doctype4; - return XML_ROLE_DOCTYPE_SYSTEM_ID; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_LITERAL: + state->handler = doctype4; + return XML_ROLE_DOCTYPE_SYSTEM_ID; + } + return common(state, tok); } static int PTRCALL @@ -348,18 +294,17 @@ doctype4(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_DOCTYPE_NONE; - case XML_TOK_OPEN_BRACKET: - state->handler = internalSubset; - return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = internalSubset; + return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + } + return common(state, tok); } static int PTRCALL @@ -369,15 +314,14 @@ doctype5(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_DOCTYPE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + } + return common(state, tok); } static int PTRCALL @@ -387,57 +331,52 @@ internalSubset(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - end, - KW_ENTITY)) - { - state->handler = entity0; - return XML_ROLE_ENTITY_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - end, - KW_ATTLIST)) - { - state->handler = attlist0; - return XML_ROLE_ATTLIST_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - end, - KW_ELEMENT)) - { - state->handler = element0; - return XML_ROLE_ELEMENT_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - end, - KW_NOTATION)) - { - state->handler = notation0; - return XML_ROLE_NOTATION_NONE; - } - break; - case XML_TOK_PI: - return XML_ROLE_PI; - case XML_TOK_COMMENT: - return XML_ROLE_COMMENT; - case XML_TOK_PARAM_ENTITY_REF: - return XML_ROLE_PARAM_ENTITY_REF; - case XML_TOK_CLOSE_BRACKET: - state->handler = doctype5; - return XML_ROLE_DOCTYPE_NONE; - case XML_TOK_NONE: - return XML_ROLE_NONE; + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ENTITY)) { + state->handler = entity0; + return XML_ROLE_ENTITY_NONE; + } + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ATTLIST)) { + state->handler = attlist0; + return XML_ROLE_ATTLIST_NONE; } - return common(state, tok); + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ELEMENT)) { + state->handler = element0; + return XML_ROLE_ELEMENT_NONE; + } + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_NOTATION)) { + state->handler = notation0; + return XML_ROLE_NOTATION_NONE; + } + break; + case XML_TOK_PI: + return XML_ROLE_PI; + case XML_TOK_COMMENT: + return XML_ROLE_COMMENT; + case XML_TOK_PARAM_ENTITY_REF: + return XML_ROLE_PARAM_ENTITY_REF; + case XML_TOK_CLOSE_BRACKET: + state->handler = doctype5; + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_NONE: + return XML_ROLE_NONE; + } + return common(state, tok); } #ifdef XML_DTD @@ -449,10 +388,10 @@ externalSubset0(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - state->handler = externalSubset1; - if (tok == XML_TOK_XML_DECL) - return XML_ROLE_TEXT_DECL; - return externalSubset1(state, tok, ptr, end, enc); + state->handler = externalSubset1; + if (tok == XML_TOK_XML_DECL) + return XML_ROLE_TEXT_DECL; + return externalSubset1(state, tok, ptr, end, enc); } static int PTRCALL @@ -462,28 +401,27 @@ externalSubset1(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_COND_SECT_OPEN: - state->handler = condSect0; - return XML_ROLE_NONE; - case XML_TOK_COND_SECT_CLOSE: - if (state->includeLevel == 0) - break; - state->includeLevel -= 1; - return XML_ROLE_NONE; - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_BRACKET: - break; - case XML_TOK_NONE: - if (state->includeLevel) - break; - return XML_ROLE_NONE; - default: - return internalSubset(state, tok, ptr, end, enc); - } - return common(state, tok); + switch (tok) { + case XML_TOK_COND_SECT_OPEN: + state->handler = condSect0; + return XML_ROLE_NONE; + case XML_TOK_COND_SECT_CLOSE: + if (state->includeLevel == 0) + break; + state->includeLevel -= 1; + return XML_ROLE_NONE; + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_BRACKET: + break; + case XML_TOK_NONE: + if (state->includeLevel) + break; + return XML_ROLE_NONE; + default: + return internalSubset(state, tok, ptr, end, enc); + } + return common(state, tok); } #endif /* XML_DTD */ @@ -495,18 +433,17 @@ entity0(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ENTITY_NONE; - case XML_TOK_PERCENT: - state->handler = entity1; - return XML_ROLE_ENTITY_NONE; - case XML_TOK_NAME: - state->handler = entity2; - return XML_ROLE_GENERAL_ENTITY_NAME; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_PERCENT: + state->handler = entity1; + return XML_ROLE_ENTITY_NONE; + case XML_TOK_NAME: + state->handler = entity2; + return XML_ROLE_GENERAL_ENTITY_NAME; + } + return common(state, tok); } static int PTRCALL @@ -516,15 +453,14 @@ entity1(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ENTITY_NONE; - case XML_TOK_NAME: - state->handler = entity7; - return XML_ROLE_PARAM_ENTITY_NAME; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_NAME: + state->handler = entity7; + return XML_ROLE_PARAM_ENTITY_NAME; + } + return common(state, tok); } static int PTRCALL @@ -534,28 +470,25 @@ entity2(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ENTITY_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) - { - state->handler = entity4; - return XML_ROLE_ENTITY_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) - { - state->handler = entity3; - return XML_ROLE_ENTITY_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = declClose; - state->role_none = XML_ROLE_ENTITY_NONE; - return XML_ROLE_ENTITY_VALUE; + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = entity4; + return XML_ROLE_ENTITY_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = entity3; + return XML_ROLE_ENTITY_NONE; } - return common(state, tok); + break; + case XML_TOK_LITERAL: + state->handler = declClose; + state->role_none = XML_ROLE_ENTITY_NONE; + return XML_ROLE_ENTITY_VALUE; + } + return common(state, tok); } static int PTRCALL @@ -565,15 +498,14 @@ entity3(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ENTITY_NONE; - case XML_TOK_LITERAL: - state->handler = entity4; - return XML_ROLE_ENTITY_PUBLIC_ID; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_LITERAL: + state->handler = entity4; + return XML_ROLE_ENTITY_PUBLIC_ID; + } + return common(state, tok); } static int PTRCALL @@ -583,15 +515,14 @@ entity4(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ENTITY_NONE; - case XML_TOK_LITERAL: - state->handler = entity5; - return XML_ROLE_ENTITY_SYSTEM_ID; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_LITERAL: + state->handler = entity5; + return XML_ROLE_ENTITY_SYSTEM_ID; + } + return common(state, tok); } static int PTRCALL @@ -601,22 +532,20 @@ entity5(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ENTITY_NONE; - case XML_TOK_DECL_CLOSE: - setTopLevel(state); - return XML_ROLE_ENTITY_COMPLETE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) - { - state->handler = entity6; - return XML_ROLE_ENTITY_NONE; - } - break; + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_ENTITY_COMPLETE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) { + state->handler = entity6; + return XML_ROLE_ENTITY_NONE; } - return common(state, tok); + break; + } + return common(state, tok); } static int PTRCALL @@ -626,16 +555,15 @@ entity6(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ENTITY_NONE; - case XML_TOK_NAME: - state->handler = declClose; - state->role_none = XML_ROLE_ENTITY_NONE; - return XML_ROLE_ENTITY_NOTATION_NAME; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_NAME: + state->handler = declClose; + state->role_none = XML_ROLE_ENTITY_NONE; + return XML_ROLE_ENTITY_NOTATION_NAME; + } + return common(state, tok); } static int PTRCALL @@ -645,28 +573,25 @@ entity7(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ENTITY_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) - { - state->handler = entity9; - return XML_ROLE_ENTITY_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) - { - state->handler = entity8; - return XML_ROLE_ENTITY_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = declClose; - state->role_none = XML_ROLE_ENTITY_NONE; - return XML_ROLE_ENTITY_VALUE; + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = entity9; + return XML_ROLE_ENTITY_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = entity8; + return XML_ROLE_ENTITY_NONE; } - return common(state, tok); + break; + case XML_TOK_LITERAL: + state->handler = declClose; + state->role_none = XML_ROLE_ENTITY_NONE; + return XML_ROLE_ENTITY_VALUE; + } + return common(state, tok); } static int PTRCALL @@ -676,15 +601,14 @@ entity8(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ENTITY_NONE; - case XML_TOK_LITERAL: - state->handler = entity9; - return XML_ROLE_ENTITY_PUBLIC_ID; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_LITERAL: + state->handler = entity9; + return XML_ROLE_ENTITY_PUBLIC_ID; + } + return common(state, tok); } static int PTRCALL @@ -694,15 +618,14 @@ entity9(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ENTITY_NONE; - case XML_TOK_LITERAL: - state->handler = entity10; - return XML_ROLE_ENTITY_SYSTEM_ID; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_LITERAL: + state->handler = entity10; + return XML_ROLE_ENTITY_SYSTEM_ID; + } + return common(state, tok); } static int PTRCALL @@ -712,15 +635,14 @@ entity10(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ENTITY_NONE; - case XML_TOK_DECL_CLOSE: - setTopLevel(state); - return XML_ROLE_ENTITY_COMPLETE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_ENTITY_COMPLETE; + } + return common(state, tok); } static int PTRCALL @@ -730,15 +652,14 @@ notation0(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_NOTATION_NONE; - case XML_TOK_NAME: - state->handler = notation1; - return XML_ROLE_NOTATION_NAME; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NOTATION_NONE; + case XML_TOK_NAME: + state->handler = notation1; + return XML_ROLE_NOTATION_NAME; + } + return common(state, tok); } static int PTRCALL @@ -748,24 +669,21 @@ notation1(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_NOTATION_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) - { - state->handler = notation3; - return XML_ROLE_NOTATION_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) - { - state->handler = notation2; - return XML_ROLE_NOTATION_NONE; - } - break; + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NOTATION_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = notation3; + return XML_ROLE_NOTATION_NONE; } - return common(state, tok); + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = notation2; + return XML_ROLE_NOTATION_NONE; + } + break; + } + return common(state, tok); } static int PTRCALL @@ -775,15 +693,14 @@ notation2(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_NOTATION_NONE; - case XML_TOK_LITERAL: - state->handler = notation4; - return XML_ROLE_NOTATION_PUBLIC_ID; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NOTATION_NONE; + case XML_TOK_LITERAL: + state->handler = notation4; + return XML_ROLE_NOTATION_PUBLIC_ID; + } + return common(state, tok); } static int PTRCALL @@ -793,16 +710,15 @@ notation3(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_NOTATION_NONE; - case XML_TOK_LITERAL: - state->handler = declClose; - state->role_none = XML_ROLE_NOTATION_NONE; - return XML_ROLE_NOTATION_SYSTEM_ID; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NOTATION_NONE; + case XML_TOK_LITERAL: + state->handler = declClose; + state->role_none = XML_ROLE_NOTATION_NONE; + return XML_ROLE_NOTATION_SYSTEM_ID; + } + return common(state, tok); } static int PTRCALL @@ -812,19 +728,18 @@ notation4(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_NOTATION_NONE; - case XML_TOK_LITERAL: - state->handler = declClose; - state->role_none = XML_ROLE_NOTATION_NONE; - return XML_ROLE_NOTATION_SYSTEM_ID; - case XML_TOK_DECL_CLOSE: - setTopLevel(state); - return XML_ROLE_NOTATION_NO_SYSTEM_ID; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NOTATION_NONE; + case XML_TOK_LITERAL: + state->handler = declClose; + state->role_none = XML_ROLE_NOTATION_NONE; + return XML_ROLE_NOTATION_SYSTEM_ID; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_NOTATION_NO_SYSTEM_ID; + } + return common(state, tok); } static int PTRCALL @@ -834,16 +749,15 @@ attlist0(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist1; - return XML_ROLE_ATTLIST_ELEMENT_NAME; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist1; + return XML_ROLE_ATTLIST_ELEMENT_NAME; + } + return common(state, tok); } static int PTRCALL @@ -853,19 +767,18 @@ attlist1(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_DECL_CLOSE: - setTopLevel(state); - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist2; - return XML_ROLE_ATTRIBUTE_NAME; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist2; + return XML_ROLE_ATTRIBUTE_NAME; + } + return common(state, tok); } static int PTRCALL @@ -875,42 +788,38 @@ attlist2(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_NAME: + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_NAME: { - static const char *types[] = - { - KW_CDATA, - KW_ID, - KW_IDREF, - KW_IDREFS, - KW_ENTITY, - KW_ENTITIES, - KW_NMTOKEN, - KW_NMTOKENS, - }; - int i; - for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++) - if (XmlNameMatchesAscii(enc, ptr, end, types[i])) - { - state->handler = attlist8; - return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i; - } + static const char *types[] = { + KW_CDATA, + KW_ID, + KW_IDREF, + KW_IDREFS, + KW_ENTITY, + KW_ENTITIES, + KW_NMTOKEN, + KW_NMTOKENS, + }; + int i; + for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++) + if (XmlNameMatchesAscii(enc, ptr, end, types[i])) { + state->handler = attlist8; + return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i; + } } - if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) - { - state->handler = attlist5; - return XML_ROLE_ATTLIST_NONE; + if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) { + state->handler = attlist5; + return XML_ROLE_ATTLIST_NONE; } break; - case XML_TOK_OPEN_PAREN: - state->handler = attlist3; - return XML_ROLE_ATTLIST_NONE; - } - return common(state, tok); + case XML_TOK_OPEN_PAREN: + state->handler = attlist3; + return XML_ROLE_ATTLIST_NONE; + } + return common(state, tok); } static int PTRCALL @@ -920,17 +829,16 @@ attlist3(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_NMTOKEN: - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist4; - return XML_ROLE_ATTRIBUTE_ENUM_VALUE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_NMTOKEN: + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist4; + return XML_ROLE_ATTRIBUTE_ENUM_VALUE; + } + return common(state, tok); } static int PTRCALL @@ -940,18 +848,17 @@ attlist4(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_CLOSE_PAREN: - state->handler = attlist8; - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_OR: - state->handler = attlist3; - return XML_ROLE_ATTLIST_NONE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_CLOSE_PAREN: + state->handler = attlist8; + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_OR: + state->handler = attlist3; + return XML_ROLE_ATTLIST_NONE; + } + return common(state, tok); } static int PTRCALL @@ -961,15 +868,14 @@ attlist5(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_OPEN_PAREN: - state->handler = attlist6; - return XML_ROLE_ATTLIST_NONE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_OPEN_PAREN: + state->handler = attlist6; + return XML_ROLE_ATTLIST_NONE; + } + return common(state, tok); } static int PTRCALL @@ -979,15 +885,14 @@ attlist6(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_NAME: - state->handler = attlist7; - return XML_ROLE_ATTRIBUTE_NOTATION_VALUE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_NAME: + state->handler = attlist7; + return XML_ROLE_ATTRIBUTE_NOTATION_VALUE; + } + return common(state, tok); } static int PTRCALL @@ -997,18 +902,17 @@ attlist7(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_CLOSE_PAREN: - state->handler = attlist8; - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_OR: - state->handler = attlist6; - return XML_ROLE_ATTLIST_NONE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_CLOSE_PAREN: + state->handler = attlist8; + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_OR: + state->handler = attlist6; + return XML_ROLE_ATTLIST_NONE; + } + return common(state, tok); } /* default value */ @@ -1019,41 +923,37 @@ attlist8(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_POUND_NAME: - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - end, - KW_IMPLIED)) - { - state->handler = attlist1; - return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE; - } - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - end, - KW_REQUIRED)) - { - state->handler = attlist1; - return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE; - } - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - end, - KW_FIXED)) - { - state->handler = attlist9; - return XML_ROLE_ATTLIST_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = attlist1; - return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE; + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_POUND_NAME: + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_IMPLIED)) { + state->handler = attlist1; + return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE; + } + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_REQUIRED)) { + state->handler = attlist1; + return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE; + } + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_FIXED)) { + state->handler = attlist9; + return XML_ROLE_ATTLIST_NONE; } - return common(state, tok); + break; + case XML_TOK_LITERAL: + state->handler = attlist1; + return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE; + } + return common(state, tok); } static int PTRCALL @@ -1063,15 +963,14 @@ attlist9(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ATTLIST_NONE; - case XML_TOK_LITERAL: - state->handler = attlist1; - return XML_ROLE_FIXED_ATTRIBUTE_VALUE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_LITERAL: + state->handler = attlist1; + return XML_ROLE_FIXED_ATTRIBUTE_VALUE; + } + return common(state, tok); } static int PTRCALL @@ -1081,16 +980,15 @@ element0(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ELEMENT_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element1; - return XML_ROLE_ELEMENT_NAME; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element1; + return XML_ROLE_ELEMENT_NAME; + } + return common(state, tok); } static int PTRCALL @@ -1100,30 +998,27 @@ element1(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ELEMENT_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) - { - state->handler = declClose; - state->role_none = XML_ROLE_ELEMENT_NONE; - return XML_ROLE_CONTENT_EMPTY; - } - if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) - { - state->handler = declClose; - state->role_none = XML_ROLE_ELEMENT_NONE; - return XML_ROLE_CONTENT_ANY; - } - break; - case XML_TOK_OPEN_PAREN: - state->handler = element2; - state->level = 1; - return XML_ROLE_GROUP_OPEN; + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + return XML_ROLE_CONTENT_EMPTY; } - return common(state, tok); + if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + return XML_ROLE_CONTENT_ANY; + } + break; + case XML_TOK_OPEN_PAREN: + state->handler = element2; + state->level = 1; + return XML_ROLE_GROUP_OPEN; + } + return common(state, tok); } static int PTRCALL @@ -1133,39 +1028,37 @@ element2(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ELEMENT_NONE; - case XML_TOK_POUND_NAME: - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - end, - KW_PCDATA)) - { - state->handler = element3; - return XML_ROLE_CONTENT_PCDATA; - } - break; - case XML_TOK_OPEN_PAREN: - state->level = 2; - state->handler = element6; - return XML_ROLE_GROUP_OPEN; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT; - case XML_TOK_NAME_QUESTION: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_OPT; - case XML_TOK_NAME_ASTERISK: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_REP; - case XML_TOK_NAME_PLUS: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_PLUS; + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_POUND_NAME: + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_PCDATA)) { + state->handler = element3; + return XML_ROLE_CONTENT_PCDATA; } - return common(state, tok); + break; + case XML_TOK_OPEN_PAREN: + state->level = 2; + state->handler = element6; + return XML_ROLE_GROUP_OPEN; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT; + case XML_TOK_NAME_QUESTION: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_OPT; + case XML_TOK_NAME_ASTERISK: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_REP; + case XML_TOK_NAME_PLUS: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_PLUS; + } + return common(state, tok); } static int PTRCALL @@ -1175,23 +1068,22 @@ element3(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ELEMENT_NONE; - case XML_TOK_CLOSE_PAREN: - state->handler = declClose; - state->role_none = XML_ROLE_ELEMENT_NONE; - return XML_ROLE_GROUP_CLOSE; - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->handler = declClose; - state->role_none = XML_ROLE_ELEMENT_NONE; - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_OR: - state->handler = element4; - return XML_ROLE_ELEMENT_NONE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_CLOSE_PAREN: + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + return XML_ROLE_GROUP_CLOSE; + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_OR: + state->handler = element4; + return XML_ROLE_ELEMENT_NONE; + } + return common(state, tok); } static int PTRCALL @@ -1201,16 +1093,15 @@ element4(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ELEMENT_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element5; - return XML_ROLE_CONTENT_ELEMENT; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element5; + return XML_ROLE_CONTENT_ELEMENT; + } + return common(state, tok); } static int PTRCALL @@ -1220,19 +1111,18 @@ element5(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ELEMENT_NONE; - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->handler = declClose; - state->role_none = XML_ROLE_ELEMENT_NONE; - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_OR: - state->handler = element4; - return XML_ROLE_ELEMENT_NONE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_OR: + state->handler = element4; + return XML_ROLE_ELEMENT_NONE; + } + return common(state, tok); } static int PTRCALL @@ -1242,28 +1132,27 @@ element6(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ELEMENT_NONE; - case XML_TOK_OPEN_PAREN: - state->level += 1; - return XML_ROLE_GROUP_OPEN; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT; - case XML_TOK_NAME_QUESTION: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_OPT; - case XML_TOK_NAME_ASTERISK: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_REP; - case XML_TOK_NAME_PLUS: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_PLUS; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_OPEN_PAREN: + state->level += 1; + return XML_ROLE_GROUP_OPEN; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT; + case XML_TOK_NAME_QUESTION: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_OPT; + case XML_TOK_NAME_ASTERISK: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_REP; + case XML_TOK_NAME_PLUS: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_PLUS; + } + return common(state, tok); } static int PTRCALL @@ -1273,50 +1162,45 @@ element7(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_ELEMENT_NONE; - case XML_TOK_CLOSE_PAREN: - state->level -= 1; - if (state->level == 0) - { - state->handler = declClose; - state->role_none = XML_ROLE_ELEMENT_NONE; - } - return XML_ROLE_GROUP_CLOSE; - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->level -= 1; - if (state->level == 0) - { - state->handler = declClose; - state->role_none = XML_ROLE_ELEMENT_NONE; - } - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_CLOSE_PAREN_QUESTION: - state->level -= 1; - if (state->level == 0) - { - state->handler = declClose; - state->role_none = XML_ROLE_ELEMENT_NONE; - } - return XML_ROLE_GROUP_CLOSE_OPT; - case XML_TOK_CLOSE_PAREN_PLUS: - state->level -= 1; - if (state->level == 0) - { - state->handler = declClose; - state->role_none = XML_ROLE_ELEMENT_NONE; - } - return XML_ROLE_GROUP_CLOSE_PLUS; - case XML_TOK_COMMA: - state->handler = element6; - return XML_ROLE_GROUP_SEQUENCE; - case XML_TOK_OR: - state->handler = element6; - return XML_ROLE_GROUP_CHOICE; + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_CLOSE_PAREN: + state->level -= 1; + if (state->level == 0) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + } + return XML_ROLE_GROUP_CLOSE; + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->level -= 1; + if (state->level == 0) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + } + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_CLOSE_PAREN_QUESTION: + state->level -= 1; + if (state->level == 0) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; } - return common(state, tok); + return XML_ROLE_GROUP_CLOSE_OPT; + case XML_TOK_CLOSE_PAREN_PLUS: + state->level -= 1; + if (state->level == 0) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + } + return XML_ROLE_GROUP_CLOSE_PLUS; + case XML_TOK_COMMA: + state->handler = element6; + return XML_ROLE_GROUP_SEQUENCE; + case XML_TOK_OR: + state->handler = element6; + return XML_ROLE_GROUP_CHOICE; + } + return common(state, tok); } #ifdef XML_DTD @@ -1328,24 +1212,21 @@ condSect0(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) - { - state->handler = condSect1; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) - { - state->handler = condSect2; - return XML_ROLE_NONE; - } - break; + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) { + state->handler = condSect1; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) { + state->handler = condSect2; + return XML_ROLE_NONE; } - return common(state, tok); + break; + } + return common(state, tok); } static int PTRCALL @@ -1355,16 +1236,15 @@ condSect1(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_BRACKET: - state->handler = externalSubset1; - state->includeLevel += 1; - return XML_ROLE_NONE; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = externalSubset1; + state->includeLevel += 1; + return XML_ROLE_NONE; + } + return common(state, tok); } static int PTRCALL @@ -1374,15 +1254,14 @@ condSect2(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_BRACKET: - state->handler = externalSubset1; - return XML_ROLE_IGNORE_SECT; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = externalSubset1; + return XML_ROLE_IGNORE_SECT; + } + return common(state, tok); } #endif /* XML_DTD */ @@ -1394,15 +1273,14 @@ declClose(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - switch (tok) - { - case XML_TOK_PROLOG_S: - return state->role_none; - case XML_TOK_DECL_CLOSE: - setTopLevel(state); - return state->role_none; - } - return common(state, tok); + switch (tok) { + case XML_TOK_PROLOG_S: + return state->role_none; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return state->role_none; + } + return common(state, tok); } static int PTRCALL @@ -1412,28 +1290,28 @@ error(PROLOG_STATE *state, const char *end, const ENCODING *enc) { - return XML_ROLE_NONE; + return XML_ROLE_NONE; } static int FASTCALL common(PROLOG_STATE *state, int tok) { #ifdef XML_DTD - if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF) - return XML_ROLE_INNER_PARAM_ENTITY_REF; + if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF) + return XML_ROLE_INNER_PARAM_ENTITY_REF; #endif - state->handler = error; - return XML_ROLE_ERROR; + state->handler = error; + return XML_ROLE_ERROR; } void XmlPrologStateInit(PROLOG_STATE *state) { - state->handler = prolog0; + state->handler = prolog0; #ifdef XML_DTD - state->documentEntity = 1; - state->includeLevel = 0; - state->inEntityValue = 0; + state->documentEntity = 1; + state->includeLevel = 0; + state->inEntityValue = 0; #endif /* XML_DTD */ } @@ -1442,9 +1320,9 @@ XmlPrologStateInit(PROLOG_STATE *state) void XmlPrologStateInitExternalEntity(PROLOG_STATE *state) { - state->handler = externalSubset0; - state->documentEntity = 0; - state->includeLevel = 0; + state->handler = externalSubset0; + state->documentEntity = 0; + state->includeLevel = 0; } #endif /* XML_DTD */ diff --git a/src/simgear/xml/xmlrole.h b/src/simgear/xml/xmlrole.h old mode 100644 new mode 100755 index 733f6b3c0dc807cfac7cd95469661b2326e4fbeb..4dd9f06f97679e6ce6d6b54e8c4a3ccfc5717bac --- a/src/simgear/xml/xmlrole.h +++ b/src/simgear/xml/xmlrole.h @@ -14,97 +14,94 @@ #include "xmltok.h" #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - enum - { - XML_ROLE_ERROR = -1, - XML_ROLE_NONE = 0, - XML_ROLE_XML_DECL, - XML_ROLE_INSTANCE_START, - XML_ROLE_DOCTYPE_NONE, - XML_ROLE_DOCTYPE_NAME, - XML_ROLE_DOCTYPE_SYSTEM_ID, - XML_ROLE_DOCTYPE_PUBLIC_ID, - XML_ROLE_DOCTYPE_INTERNAL_SUBSET, - XML_ROLE_DOCTYPE_CLOSE, - XML_ROLE_GENERAL_ENTITY_NAME, - XML_ROLE_PARAM_ENTITY_NAME, - XML_ROLE_ENTITY_NONE, - XML_ROLE_ENTITY_VALUE, - XML_ROLE_ENTITY_SYSTEM_ID, - XML_ROLE_ENTITY_PUBLIC_ID, - XML_ROLE_ENTITY_COMPLETE, - XML_ROLE_ENTITY_NOTATION_NAME, - XML_ROLE_NOTATION_NONE, - XML_ROLE_NOTATION_NAME, - XML_ROLE_NOTATION_SYSTEM_ID, - XML_ROLE_NOTATION_NO_SYSTEM_ID, - XML_ROLE_NOTATION_PUBLIC_ID, - XML_ROLE_ATTRIBUTE_NAME, - XML_ROLE_ATTRIBUTE_TYPE_CDATA, - XML_ROLE_ATTRIBUTE_TYPE_ID, - XML_ROLE_ATTRIBUTE_TYPE_IDREF, - XML_ROLE_ATTRIBUTE_TYPE_IDREFS, - XML_ROLE_ATTRIBUTE_TYPE_ENTITY, - XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, - XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, - XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, - XML_ROLE_ATTRIBUTE_ENUM_VALUE, - XML_ROLE_ATTRIBUTE_NOTATION_VALUE, - XML_ROLE_ATTLIST_NONE, - XML_ROLE_ATTLIST_ELEMENT_NAME, - XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, - XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, - XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, - XML_ROLE_FIXED_ATTRIBUTE_VALUE, - XML_ROLE_ELEMENT_NONE, - XML_ROLE_ELEMENT_NAME, - XML_ROLE_CONTENT_ANY, - XML_ROLE_CONTENT_EMPTY, - XML_ROLE_CONTENT_PCDATA, - XML_ROLE_GROUP_OPEN, - XML_ROLE_GROUP_CLOSE, - XML_ROLE_GROUP_CLOSE_REP, - XML_ROLE_GROUP_CLOSE_OPT, - XML_ROLE_GROUP_CLOSE_PLUS, - XML_ROLE_GROUP_CHOICE, - XML_ROLE_GROUP_SEQUENCE, - XML_ROLE_CONTENT_ELEMENT, - XML_ROLE_CONTENT_ELEMENT_REP, - XML_ROLE_CONTENT_ELEMENT_OPT, - XML_ROLE_CONTENT_ELEMENT_PLUS, - XML_ROLE_PI, - XML_ROLE_COMMENT, +enum { + XML_ROLE_ERROR = -1, + XML_ROLE_NONE = 0, + XML_ROLE_XML_DECL, + XML_ROLE_INSTANCE_START, + XML_ROLE_DOCTYPE_NONE, + XML_ROLE_DOCTYPE_NAME, + XML_ROLE_DOCTYPE_SYSTEM_ID, + XML_ROLE_DOCTYPE_PUBLIC_ID, + XML_ROLE_DOCTYPE_INTERNAL_SUBSET, + XML_ROLE_DOCTYPE_CLOSE, + XML_ROLE_GENERAL_ENTITY_NAME, + XML_ROLE_PARAM_ENTITY_NAME, + XML_ROLE_ENTITY_NONE, + XML_ROLE_ENTITY_VALUE, + XML_ROLE_ENTITY_SYSTEM_ID, + XML_ROLE_ENTITY_PUBLIC_ID, + XML_ROLE_ENTITY_COMPLETE, + XML_ROLE_ENTITY_NOTATION_NAME, + XML_ROLE_NOTATION_NONE, + XML_ROLE_NOTATION_NAME, + XML_ROLE_NOTATION_SYSTEM_ID, + XML_ROLE_NOTATION_NO_SYSTEM_ID, + XML_ROLE_NOTATION_PUBLIC_ID, + XML_ROLE_ATTRIBUTE_NAME, + XML_ROLE_ATTRIBUTE_TYPE_CDATA, + XML_ROLE_ATTRIBUTE_TYPE_ID, + XML_ROLE_ATTRIBUTE_TYPE_IDREF, + XML_ROLE_ATTRIBUTE_TYPE_IDREFS, + XML_ROLE_ATTRIBUTE_TYPE_ENTITY, + XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, + XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, + XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, + XML_ROLE_ATTRIBUTE_ENUM_VALUE, + XML_ROLE_ATTRIBUTE_NOTATION_VALUE, + XML_ROLE_ATTLIST_NONE, + XML_ROLE_ATTLIST_ELEMENT_NAME, + XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, + XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, + XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, + XML_ROLE_FIXED_ATTRIBUTE_VALUE, + XML_ROLE_ELEMENT_NONE, + XML_ROLE_ELEMENT_NAME, + XML_ROLE_CONTENT_ANY, + XML_ROLE_CONTENT_EMPTY, + XML_ROLE_CONTENT_PCDATA, + XML_ROLE_GROUP_OPEN, + XML_ROLE_GROUP_CLOSE, + XML_ROLE_GROUP_CLOSE_REP, + XML_ROLE_GROUP_CLOSE_OPT, + XML_ROLE_GROUP_CLOSE_PLUS, + XML_ROLE_GROUP_CHOICE, + XML_ROLE_GROUP_SEQUENCE, + XML_ROLE_CONTENT_ELEMENT, + XML_ROLE_CONTENT_ELEMENT_REP, + XML_ROLE_CONTENT_ELEMENT_OPT, + XML_ROLE_CONTENT_ELEMENT_PLUS, + XML_ROLE_PI, + XML_ROLE_COMMENT, #ifdef XML_DTD - XML_ROLE_TEXT_DECL, - XML_ROLE_IGNORE_SECT, - XML_ROLE_INNER_PARAM_ENTITY_REF, + XML_ROLE_TEXT_DECL, + XML_ROLE_IGNORE_SECT, + XML_ROLE_INNER_PARAM_ENTITY_REF, #endif /* XML_DTD */ - XML_ROLE_PARAM_ENTITY_REF - }; + XML_ROLE_PARAM_ENTITY_REF +}; - typedef struct prolog_state - { - int (PTRCALL *handler) (struct prolog_state *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc); - unsigned level; - int role_none; +typedef struct prolog_state { + int (PTRCALL *handler) (struct prolog_state *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc); + unsigned level; + int role_none; #ifdef XML_DTD - unsigned includeLevel; - int documentEntity; - int inEntityValue; + unsigned includeLevel; + int documentEntity; + int inEntityValue; #endif /* XML_DTD */ - } PROLOG_STATE; +} PROLOG_STATE; - void XmlPrologStateInit(PROLOG_STATE *); +void XmlPrologStateInit(PROLOG_STATE *); #ifdef XML_DTD - void XmlPrologStateInitExternalEntity(PROLOG_STATE *); +void XmlPrologStateInitExternalEntity(PROLOG_STATE *); #endif /* XML_DTD */ #define XmlTokenRole(state, tok, ptr, end, enc) \ diff --git a/src/simgear/xml/xmltok.c b/src/simgear/xml/xmltok.c old mode 100644 new mode 100755 index 945db72d06570ba5e3e19aaea300a9e9b888a733..b09c2cd2a2868fa24684893f74dddef3e4e19cd0 --- a/src/simgear/xml/xmltok.c +++ b/src/simgear/xml/xmltok.c @@ -120,19 +120,19 @@ static int PTRFASTCALL isNever(const ENCODING *enc, const char *p) { - return 0; + return 0; } static int PTRFASTCALL utf8_isName2(const ENCODING *enc, const char *p) { - return UTF8_GET_NAMING2(namePages, (const unsigned char *)p); + return UTF8_GET_NAMING2(namePages, (const unsigned char *)p); } static int PTRFASTCALL utf8_isName3(const ENCODING *enc, const char *p) { - return UTF8_GET_NAMING3(namePages, (const unsigned char *)p); + return UTF8_GET_NAMING3(namePages, (const unsigned char *)p); } #define utf8_isName4 isNever @@ -140,13 +140,13 @@ utf8_isName3(const ENCODING *enc, const char *p) static int PTRFASTCALL utf8_isNmstrt2(const ENCODING *enc, const char *p) { - return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p); + return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p); } static int PTRFASTCALL utf8_isNmstrt3(const ENCODING *enc, const char *p) { - return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p); + return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p); } #define utf8_isNmstrt4 isNever @@ -154,41 +154,40 @@ utf8_isNmstrt3(const ENCODING *enc, const char *p) static int PTRFASTCALL utf8_isInvalid2(const ENCODING *enc, const char *p) { - return UTF8_INVALID2((const unsigned char *)p); + return UTF8_INVALID2((const unsigned char *)p); } static int PTRFASTCALL utf8_isInvalid3(const ENCODING *enc, const char *p) { - return UTF8_INVALID3((const unsigned char *)p); + return UTF8_INVALID3((const unsigned char *)p); } static int PTRFASTCALL utf8_isInvalid4(const ENCODING *enc, const char *p) { - return UTF8_INVALID4((const unsigned char *)p); + return UTF8_INVALID4((const unsigned char *)p); } -struct normal_encoding -{ - ENCODING enc; - unsigned char type[256]; +struct normal_encoding { + ENCODING enc; + unsigned char type[256]; #ifdef XML_MIN_SIZE - int (PTRFASTCALL *byteType)(const ENCODING *, const char *); - int (PTRFASTCALL *isNameMin)(const ENCODING *, const char *); - int (PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *); - int (PTRFASTCALL *byteToAscii)(const ENCODING *, const char *); - int (PTRCALL *charMatches)(const ENCODING *, const char *, int); + int (PTRFASTCALL *byteType)(const ENCODING *, const char *); + int (PTRFASTCALL *isNameMin)(const ENCODING *, const char *); + int (PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *); + int (PTRFASTCALL *byteToAscii)(const ENCODING *, const char *); + int (PTRCALL *charMatches)(const ENCODING *, const char *, int); #endif /* XML_MIN_SIZE */ - int (PTRFASTCALL *isName2)(const ENCODING *, const char *); - int (PTRFASTCALL *isName3)(const ENCODING *, const char *); - int (PTRFASTCALL *isName4)(const ENCODING *, const char *); - int (PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *); - int (PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *); - int (PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *); - int (PTRFASTCALL *isInvalid2)(const ENCODING *, const char *); - int (PTRFASTCALL *isInvalid3)(const ENCODING *, const char *); - int (PTRFASTCALL *isInvalid4)(const ENCODING *, const char *); + int (PTRFASTCALL *isName2)(const ENCODING *, const char *); + int (PTRFASTCALL *isName3)(const ENCODING *, const char *); + int (PTRFASTCALL *isName4)(const ENCODING *, const char *); + int (PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *); + int (PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *); + int (PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *); + int (PTRFASTCALL *isInvalid2)(const ENCODING *, const char *); + int (PTRFASTCALL *isInvalid3)(const ENCODING *, const char *); + int (PTRFASTCALL *isInvalid4)(const ENCODING *, const char *); }; #define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *) (enc)) @@ -243,7 +242,7 @@ static int FASTCALL checkCharRefNumber(int); static int PTRFASTCALL sb_byteType(const ENCODING *enc, const char *p) { - return SB_BYTE_TYPE(enc, p); + return SB_BYTE_TYPE(enc, p); } #define BYTE_TYPE(enc, p) \ (AS_NORMAL_ENCODING(enc)->byteType(enc, p)) @@ -257,7 +256,7 @@ sb_byteType(const ENCODING *enc, const char *p) static int PTRFASTCALL sb_byteToAscii(const ENCODING *enc, const char *p) { - return *p; + return *p; } #else #define BYTE_TO_ASCII(enc, p) (*(p)) @@ -286,7 +285,7 @@ sb_byteToAscii(const ENCODING *enc, const char *p) static int PTRCALL sb_charMatches(const ENCODING *enc, const char *p, int c) { - return *p == c; + return *p == c; } #else /* c is an ASCII character */ @@ -306,12 +305,11 @@ sb_charMatches(const ENCODING *enc, const char *p, int c) #undef IS_NMSTRT_CHAR_MINBPC #undef IS_INVALID_CHAR -enum /* UTF8_cvalN is value of masked first byte of N byte sequence */ -{ - UTF8_cval1 = 0x00, - UTF8_cval2 = 0xc0, - UTF8_cval3 = 0xe0, - UTF8_cval4 = 0xf0 +enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */ + UTF8_cval1 = 0x00, + UTF8_cval2 = 0xc0, + UTF8_cval3 = 0xe0, + UTF8_cval4 = 0xf0 }; static void PTRCALL @@ -319,19 +317,18 @@ utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { - char *to; - const char *from; - if (fromLim - *fromP > toLim - *toP) - { - /* Avoid copying partial characters. */ - for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--) - if (((unsigned char)fromLim[-1] & 0xc0) != 0x80) - break; - } - for (to = *toP, from = *fromP; from != fromLim; from++, to++) - *to = *from; - *fromP = from; - *toP = to; + char *to; + const char *from; + if (fromLim - *fromP > toLim - *toP) { + /* Avoid copying partial characters. */ + for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--) + if (((unsigned char)fromLim[-1] & 0xc0) != 0x80) + break; + } + for (to = *toP, from = *fromP; from != fromLim; from++, to++) + *to = *from; + *fromP = from; + *toP = to; } static void PTRCALL @@ -339,93 +336,87 @@ utf8_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { - unsigned short *to = *toP; - const char *from = *fromP; - while (from != fromLim && to != toLim) - { - switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) - { - case BT_LEAD2: - *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f)); - from += 2; - break; - case BT_LEAD3: - *to++ = (unsigned short)(((from[0] & 0xf) << 12) - | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f)); - from += 3; - break; - case BT_LEAD4: - { - unsigned long n; - if (to + 1 == toLim) - goto after; - n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) - | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f); - n -= 0x10000; - to[0] = (unsigned short)((n >> 10) | 0xD800); - to[1] = (unsigned short)((n & 0x3FF) | 0xDC00); - to += 2; - from += 4; - } - break; - default: - *to++ = *from++; - break; - } + unsigned short *to = *toP; + const char *from = *fromP; + while (from != fromLim && to != toLim) { + switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) { + case BT_LEAD2: + *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f)); + from += 2; + break; + case BT_LEAD3: + *to++ = (unsigned short)(((from[0] & 0xf) << 12) + | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f)); + from += 3; + break; + case BT_LEAD4: + { + unsigned long n; + if (to + 1 == toLim) + goto after; + n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) + | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f); + n -= 0x10000; + to[0] = (unsigned short)((n >> 10) | 0xD800); + to[1] = (unsigned short)((n & 0x3FF) | 0xDC00); + to += 2; + from += 4; + } + break; + default: + *to++ = *from++; + break; } + } after: - *fromP = from; - *toP = to; + *fromP = from; + *toP = to; } #ifdef XML_NS -static const struct normal_encoding utf8_encoding_ns = -{ - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { +static const struct normal_encoding utf8_encoding_ns = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { #include "asciitab.h" #include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; #endif -static const struct normal_encoding utf8_encoding = -{ - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { +static const struct normal_encoding utf8_encoding = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; #ifdef XML_NS -static const struct normal_encoding internal_utf8_encoding_ns = -{ - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { +static const struct normal_encoding internal_utf8_encoding_ns = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { #include "iasciitab.h" #include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; #endif -static const struct normal_encoding internal_utf8_encoding = -{ - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { +static const struct normal_encoding internal_utf8_encoding = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { #define BT_COLON BT_NMSTRT #include "iasciitab.h" #undef BT_COLON #include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; static void PTRCALL @@ -433,27 +424,24 @@ latin1_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { - for (;;) - { - unsigned char c; - if (*fromP == fromLim) - break; - c = (unsigned char)**fromP; - if (c & 0x80) - { - if (toLim - *toP < 2) - break; - *(*toP)++ = (char)((c >> 6) | UTF8_cval2); - *(*toP)++ = (char)((c & 0x3f) | 0x80); - (*fromP)++; - } - else - { - if (*toP == toLim) - break; - *(*toP)++ = *(*fromP)++; - } + for (;;) { + unsigned char c; + if (*fromP == fromLim) + break; + c = (unsigned char)**fromP; + if (c & 0x80) { + if (toLim - *toP < 2) + break; + *(*toP)++ = (char)((c >> 6) | UTF8_cval2); + *(*toP)++ = (char)((c & 0x3f) | 0x80); + (*fromP)++; + } + else { + if (*toP == toLim) + break; + *(*toP)++ = *(*fromP)++; } + } } static void PTRCALL @@ -461,34 +449,32 @@ latin1_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { - while (*fromP != fromLim && *toP != toLim) - *(*toP)++ = (unsigned char)*(*fromP)++; + while (*fromP != fromLim && *toP != toLim) + *(*toP)++ = (unsigned char)*(*fromP)++; } #ifdef XML_NS -static const struct normal_encoding latin1_encoding_ns = -{ - { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, - { +static const struct normal_encoding latin1_encoding_ns = { + { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, + { #include "asciitab.h" #include "latin1tab.h" - }, - STANDARD_VTABLE(sb_) + }, + STANDARD_VTABLE(sb_) }; #endif -static const struct normal_encoding latin1_encoding = -{ - { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, - { +static const struct normal_encoding latin1_encoding = { + { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, + { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" - }, - STANDARD_VTABLE(sb_) + }, + STANDARD_VTABLE(sb_) }; static void PTRCALL @@ -496,61 +482,51 @@ ascii_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { - while (*fromP != fromLim && *toP != toLim) - *(*toP)++ = *(*fromP)++; + while (*fromP != fromLim && *toP != toLim) + *(*toP)++ = *(*fromP)++; } #ifdef XML_NS -static const struct normal_encoding ascii_encoding_ns = -{ - { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, - { +static const struct normal_encoding ascii_encoding_ns = { + { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, + { #include "asciitab.h" - /* BT_NONXML == 0 */ - }, - STANDARD_VTABLE(sb_) +/* BT_NONXML == 0 */ + }, + STANDARD_VTABLE(sb_) }; #endif -static const struct normal_encoding ascii_encoding = -{ - { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, - { +static const struct normal_encoding ascii_encoding = { + { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, + { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON - /* BT_NONXML == 0 */ - }, - STANDARD_VTABLE(sb_) +/* BT_NONXML == 0 */ + }, + STANDARD_VTABLE(sb_) }; static int PTRFASTCALL unicode_byte_type(char hi, char lo) { - switch ((unsigned char)hi) - { - case 0xD8: - case 0xD9: - case 0xDA: - case 0xDB: - return BT_LEAD4; - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: - return BT_TRAIL; + switch ((unsigned char)hi) { + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + return BT_LEAD4; + case 0xDC: case 0xDD: case 0xDE: case 0xDF: + return BT_TRAIL; + case 0xFF: + switch ((unsigned char)lo) { case 0xFF: - switch ((unsigned char)lo) - { - case 0xFF: - case 0xFE: - return BT_NONXML; - } - break; + case 0xFE: + return BT_NONXML; } - return BT_NONASCII; + break; + } + return BT_NONASCII; } #define DEFINE_UTF16_TO_UTF8(E) \ @@ -670,31 +646,31 @@ DEFINE_UTF16_TO_UTF16(big2_) static int PTRFASTCALL little2_byteType(const ENCODING *enc, const char *p) { - return LITTLE2_BYTE_TYPE(enc, p); + return LITTLE2_BYTE_TYPE(enc, p); } static int PTRFASTCALL little2_byteToAscii(const ENCODING *enc, const char *p) { - return LITTLE2_BYTE_TO_ASCII(enc, p); + return LITTLE2_BYTE_TO_ASCII(enc, p); } static int PTRCALL little2_charMatches(const ENCODING *enc, const char *p, int c) { - return LITTLE2_CHAR_MATCHES(enc, p, c); + return LITTLE2_CHAR_MATCHES(enc, p, c); } static int PTRFASTCALL little2_isNameMin(const ENCODING *enc, const char *p) { - return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p); + return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p); } static int PTRFASTCALL little2_isNmstrtMin(const ENCODING *enc, const char *p) { - return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p); + return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p); } #undef VTABLE @@ -730,68 +706,64 @@ little2_isNmstrtMin(const ENCODING *enc, const char *p) #ifdef XML_NS -static const struct normal_encoding little2_encoding_ns = -{ - { VTABLE, 2, 0, +static const struct normal_encoding little2_encoding_ns = { + { VTABLE, 2, 0, #if BYTEORDER == 1234 - 1 + 1 #else - 0 + 0 #endif - }, - { + }, + { #include "asciitab.h" #include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) + }, + STANDARD_VTABLE(little2_) }; #endif -static const struct normal_encoding little2_encoding = -{ - { VTABLE, 2, 0, +static const struct normal_encoding little2_encoding = { + { VTABLE, 2, 0, #if BYTEORDER == 1234 - 1 + 1 #else - 0 + 0 #endif - }, - { + }, + { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) + }, + STANDARD_VTABLE(little2_) }; #if BYTEORDER != 4321 #ifdef XML_NS -static const struct normal_encoding internal_little2_encoding_ns = -{ - { VTABLE, 2, 0, 1 }, - { +static const struct normal_encoding internal_little2_encoding_ns = { + { VTABLE, 2, 0, 1 }, + { #include "iasciitab.h" #include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) + }, + STANDARD_VTABLE(little2_) }; #endif -static const struct normal_encoding internal_little2_encoding = -{ - { VTABLE, 2, 0, 1 }, - { +static const struct normal_encoding internal_little2_encoding = { + { VTABLE, 2, 0, 1 }, + { #define BT_COLON BT_NMSTRT #include "iasciitab.h" #undef BT_COLON #include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) + }, + STANDARD_VTABLE(little2_) }; #endif @@ -813,31 +785,31 @@ static const struct normal_encoding internal_little2_encoding = static int PTRFASTCALL big2_byteType(const ENCODING *enc, const char *p) { - return BIG2_BYTE_TYPE(enc, p); + return BIG2_BYTE_TYPE(enc, p); } static int PTRFASTCALL big2_byteToAscii(const ENCODING *enc, const char *p) { - return BIG2_BYTE_TO_ASCII(enc, p); + return BIG2_BYTE_TO_ASCII(enc, p); } static int PTRCALL big2_charMatches(const ENCODING *enc, const char *p, int c) { - return BIG2_CHAR_MATCHES(enc, p, c); + return BIG2_CHAR_MATCHES(enc, p, c); } static int PTRFASTCALL big2_isNameMin(const ENCODING *enc, const char *p) { - return BIG2_IS_NAME_CHAR_MINBPC(enc, p); + return BIG2_IS_NAME_CHAR_MINBPC(enc, p); } static int PTRFASTCALL big2_isNmstrtMin(const ENCODING *enc, const char *p) { - return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p); + return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p); } #undef VTABLE @@ -873,68 +845,64 @@ big2_isNmstrtMin(const ENCODING *enc, const char *p) #ifdef XML_NS -static const struct normal_encoding big2_encoding_ns = -{ - { VTABLE, 2, 0, +static const struct normal_encoding big2_encoding_ns = { + { VTABLE, 2, 0, #if BYTEORDER == 4321 - 1 + 1 #else - 0 + 0 #endif - }, - { + }, + { #include "asciitab.h" #include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) + }, + STANDARD_VTABLE(big2_) }; #endif -static const struct normal_encoding big2_encoding = -{ - { VTABLE, 2, 0, +static const struct normal_encoding big2_encoding = { + { VTABLE, 2, 0, #if BYTEORDER == 4321 - 1 + 1 #else - 0 + 0 #endif - }, - { + }, + { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) + }, + STANDARD_VTABLE(big2_) }; #if BYTEORDER != 1234 #ifdef XML_NS -static const struct normal_encoding internal_big2_encoding_ns = -{ - { VTABLE, 2, 0, 1 }, - { +static const struct normal_encoding internal_big2_encoding_ns = { + { VTABLE, 2, 0, 1 }, + { #include "iasciitab.h" #include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) + }, + STANDARD_VTABLE(big2_) }; #endif -static const struct normal_encoding internal_big2_encoding = -{ - { VTABLE, 2, 0, 1 }, - { +static const struct normal_encoding internal_big2_encoding = { + { VTABLE, 2, 0, 1 }, + { #define BT_COLON BT_NMSTRT #include "iasciitab.h" #undef BT_COLON #include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) + }, + STANDARD_VTABLE(big2_) }; #endif @@ -944,53 +912,51 @@ static const struct normal_encoding internal_big2_encoding = static int FASTCALL streqci(const char *s1, const char *s2) { - for (;;) - { - char c1 = *s1++; - char c2 = *s2++; - if (ASCII_a <= c1 && c1 <= ASCII_z) - c1 += ASCII_A - ASCII_a; - if (ASCII_a <= c2 && c2 <= ASCII_z) - c2 += ASCII_A - ASCII_a; - if (c1 != c2) - return 0; - if (!c1) - break; - } - return 1; + for (;;) { + char c1 = *s1++; + char c2 = *s2++; + if (ASCII_a <= c1 && c1 <= ASCII_z) + c1 += ASCII_A - ASCII_a; + if (ASCII_a <= c2 && c2 <= ASCII_z) + c2 += ASCII_A - ASCII_a; + if (c1 != c2) + return 0; + if (!c1) + break; + } + return 1; } static void PTRCALL initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end, POSITION *pos) { - normal_updatePosition(&utf8_encoding.enc, ptr, end, pos); + normal_updatePosition(&utf8_encoding.enc, ptr, end, pos); } static int toAscii(const ENCODING *enc, const char *ptr, const char *end) { - char buf[1]; - char *p = buf; - XmlUtf8Convert(enc, &ptr, end, &p, p + 1); - if (p == buf) - return -1; - else - return buf[0]; + char buf[1]; + char *p = buf; + XmlUtf8Convert(enc, &ptr, end, &p, p + 1); + if (p == buf) + return -1; + else + return buf[0]; } static int FASTCALL isSpace(int c) { - switch (c) - { - case 0x20: - case 0xD: - case 0xA: - case 0x9: - return 1; - } - return 0; + switch (c) { + case 0x20: + case 0xD: + case 0xA: + case 0x9: + return 1; + } + return 0; } /* Return 1 if there's just optional white space or there's an S @@ -1005,129 +971,107 @@ parsePseudoAttribute(const ENCODING *enc, const char **valPtr, const char **nextTokPtr) { - int c; - char open; - if (ptr == end) - { - *namePtr = NULL; - return 1; - } - if (!isSpace(toAscii(enc, ptr, end))) - { - *nextTokPtr = ptr; - return 0; - } - do - { - ptr += enc->minBytesPerChar; + int c; + char open; + if (ptr == end) { + *namePtr = NULL; + return 1; + } + if (!isSpace(toAscii(enc, ptr, end))) { + *nextTokPtr = ptr; + return 0; + } + do { + ptr += enc->minBytesPerChar; + } while (isSpace(toAscii(enc, ptr, end))); + if (ptr == end) { + *namePtr = NULL; + return 1; + } + *namePtr = ptr; + for (;;) { + c = toAscii(enc, ptr, end); + if (c == -1) { + *nextTokPtr = ptr; + return 0; } - while (isSpace(toAscii(enc, ptr, end))); - if (ptr == end) - { - *namePtr = NULL; - return 1; + if (c == ASCII_EQUALS) { + *nameEndPtr = ptr; + break; } - *namePtr = ptr; - for (;;) - { - c = toAscii(enc, ptr, end); - if (c == -1) - { - *nextTokPtr = ptr; - return 0; - } - if (c == ASCII_EQUALS) - { - *nameEndPtr = ptr; - break; - } - if (isSpace(c)) - { - *nameEndPtr = ptr; - do - { - ptr += enc->minBytesPerChar; - } - while (isSpace(c = toAscii(enc, ptr, end))); - if (c != ASCII_EQUALS) - { - *nextTokPtr = ptr; - return 0; - } - break; - } + if (isSpace(c)) { + *nameEndPtr = ptr; + do { ptr += enc->minBytesPerChar; - } - if (ptr == *namePtr) - { + } while (isSpace(c = toAscii(enc, ptr, end))); + if (c != ASCII_EQUALS) { *nextTokPtr = ptr; return 0; + } + break; } ptr += enc->minBytesPerChar; - c = toAscii(enc, ptr, end); - while (isSpace(c)) - { - ptr += enc->minBytesPerChar; - c = toAscii(enc, ptr, end); - } - if (c != ASCII_QUOT && c != ASCII_APOS) - { - *nextTokPtr = ptr; - return 0; - } - open = (char)c; + } + if (ptr == *namePtr) { + *nextTokPtr = ptr; + return 0; + } + ptr += enc->minBytesPerChar; + c = toAscii(enc, ptr, end); + while (isSpace(c)) { ptr += enc->minBytesPerChar; - *valPtr = ptr; - for (;; ptr += enc->minBytesPerChar) - { - c = toAscii(enc, ptr, end); - if (c == open) - break; - if (!(ASCII_a <= c && c <= ASCII_z) - && !(ASCII_A <= c && c <= ASCII_Z) - && !(ASCII_0 <= c && c <= ASCII_9) - && c != ASCII_PERIOD - && c != ASCII_MINUS - && c != ASCII_UNDERSCORE) - { - *nextTokPtr = ptr; - return 0; - } + c = toAscii(enc, ptr, end); + } + if (c != ASCII_QUOT && c != ASCII_APOS) { + *nextTokPtr = ptr; + return 0; + } + open = (char)c; + ptr += enc->minBytesPerChar; + *valPtr = ptr; + for (;; ptr += enc->minBytesPerChar) { + c = toAscii(enc, ptr, end); + if (c == open) + break; + if (!(ASCII_a <= c && c <= ASCII_z) + && !(ASCII_A <= c && c <= ASCII_Z) + && !(ASCII_0 <= c && c <= ASCII_9) + && c != ASCII_PERIOD + && c != ASCII_MINUS + && c != ASCII_UNDERSCORE) { + *nextTokPtr = ptr; + return 0; } - *nextTokPtr = ptr + enc->minBytesPerChar; - return 1; + } + *nextTokPtr = ptr + enc->minBytesPerChar; + return 1; } -static const char KW_version[] = -{ - ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0' +static const char KW_version[] = { + ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0' }; -static const char KW_encoding[] = -{ - ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0' +static const char KW_encoding[] = { + ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0' }; -static const char KW_standalone[] = -{ - ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o, - ASCII_n, ASCII_e, '\0' +static const char KW_standalone[] = { + ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o, + ASCII_n, ASCII_e, '\0' }; -static const char KW_yes[] = -{ - ASCII_y, ASCII_e, ASCII_s, '\0' +static const char KW_yes[] = { + ASCII_y, ASCII_e, ASCII_s, '\0' }; -static const char KW_no[] = -{ - ASCII_n, ASCII_o, '\0' +static const char KW_no[] = { + ASCII_n, ASCII_o, '\0' }; static int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, - const char *, - const char *), + const char *, + const char *), int isGeneralTextEntity, const ENCODING *enc, const char *ptr, @@ -1139,193 +1083,163 @@ doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const ENCODING **encoding, int *standalone) { - const char *val = NULL; - const char *name = NULL; - const char *nameEnd = NULL; - ptr += 5 * enc->minBytesPerChar; - end -= 2 * enc->minBytesPerChar; - if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr) - || !name) - { - *badPtr = ptr; - return 0; - } - if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) - { - if (!isGeneralTextEntity) - { - *badPtr = name; - return 0; - } - } - else - { - if (versionPtr) - *versionPtr = val; - if (versionEndPtr) - *versionEndPtr = ptr; - if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) - { - *badPtr = ptr; - return 0; - } - if (!name) - { - if (isGeneralTextEntity) - { - /* a TextDecl must have an EncodingDecl */ - *badPtr = ptr; - return 0; - } - return 1; - } + const char *val = NULL; + const char *name = NULL; + const char *nameEnd = NULL; + ptr += 5 * enc->minBytesPerChar; + end -= 2 * enc->minBytesPerChar; + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr) + || !name) { + *badPtr = ptr; + return 0; + } + if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) { + if (!isGeneralTextEntity) { + *badPtr = name; + return 0; } - if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) - { - int c = toAscii(enc, val, end); - if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) - { - *badPtr = val; - return 0; - } - if (encodingName) - *encodingName = val; - if (encoding) - *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar); - if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) - { - *badPtr = ptr; - return 0; - } - if (!name) - return 1; + } + else { + if (versionPtr) + *versionPtr = val; + if (versionEndPtr) + *versionEndPtr = ptr; + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { + *badPtr = ptr; + return 0; } - if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone) - || isGeneralTextEntity) - { - *badPtr = name; + if (!name) { + if (isGeneralTextEntity) { + /* a TextDecl must have an EncodingDecl */ + *badPtr = ptr; return 0; + } + return 1; } - if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) - { - if (standalone) - *standalone = 1; - } - else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) - { - if (standalone) - *standalone = 0; - } - else - { - *badPtr = val; - return 0; + } + if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) { + int c = toAscii(enc, val, end); + if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) { + *badPtr = val; + return 0; } - while (isSpace(toAscii(enc, ptr, end))) - ptr += enc->minBytesPerChar; - if (ptr != end) - { - *badPtr = ptr; - return 0; + if (encodingName) + *encodingName = val; + if (encoding) + *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar); + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { + *badPtr = ptr; + return 0; } - return 1; + if (!name) + return 1; + } + if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone) + || isGeneralTextEntity) { + *badPtr = name; + return 0; + } + if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) { + if (standalone) + *standalone = 1; + } + else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) { + if (standalone) + *standalone = 0; + } + else { + *badPtr = val; + return 0; + } + while (isSpace(toAscii(enc, ptr, end))) + ptr += enc->minBytesPerChar; + if (ptr != end) { + *badPtr = ptr; + return 0; + } + return 1; } static int FASTCALL checkCharRefNumber(int result) { - switch (result >> 8) - { - case 0xD8: - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: - return -1; - case 0: - if (latin1_encoding.type[result] == BT_NONXML) - return -1; - break; - case 0xFF: - if (result == 0xFFFE || result == 0xFFFF) - return -1; - break; - } - return result; + switch (result >> 8) { + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + case 0xDC: case 0xDD: case 0xDE: case 0xDF: + return -1; + case 0: + if (latin1_encoding.type[result] == BT_NONXML) + return -1; + break; + case 0xFF: + if (result == 0xFFFE || result == 0xFFFF) + return -1; + break; + } + return result; } int FASTCALL XmlUtf8Encode(int c, char *buf) { - enum - { - /* minN is minimum legal resulting value for N byte sequence */ - min2 = 0x80, - min3 = 0x800, - min4 = 0x10000 - }; - - if (c < 0) - return 0; - if (c < min2) - { - buf[0] = (char)(c | UTF8_cval1); - return 1; - } - if (c < min3) - { - buf[0] = (char)((c >> 6) | UTF8_cval2); - buf[1] = (char)((c & 0x3f) | 0x80); - return 2; - } - if (c < min4) - { - buf[0] = (char)((c >> 12) | UTF8_cval3); - buf[1] = (char)(((c >> 6) & 0x3f) | 0x80); - buf[2] = (char)((c & 0x3f) | 0x80); - return 3; - } - if (c < 0x110000) - { - buf[0] = (char)((c >> 18) | UTF8_cval4); - buf[1] = (char)(((c >> 12) & 0x3f) | 0x80); - buf[2] = (char)(((c >> 6) & 0x3f) | 0x80); - buf[3] = (char)((c & 0x3f) | 0x80); - return 4; - } + enum { + /* minN is minimum legal resulting value for N byte sequence */ + min2 = 0x80, + min3 = 0x800, + min4 = 0x10000 + }; + + if (c < 0) return 0; + if (c < min2) { + buf[0] = (char)(c | UTF8_cval1); + return 1; + } + if (c < min3) { + buf[0] = (char)((c >> 6) | UTF8_cval2); + buf[1] = (char)((c & 0x3f) | 0x80); + return 2; + } + if (c < min4) { + buf[0] = (char)((c >> 12) | UTF8_cval3); + buf[1] = (char)(((c >> 6) & 0x3f) | 0x80); + buf[2] = (char)((c & 0x3f) | 0x80); + return 3; + } + if (c < 0x110000) { + buf[0] = (char)((c >> 18) | UTF8_cval4); + buf[1] = (char)(((c >> 12) & 0x3f) | 0x80); + buf[2] = (char)(((c >> 6) & 0x3f) | 0x80); + buf[3] = (char)((c & 0x3f) | 0x80); + return 4; + } + return 0; } int FASTCALL XmlUtf16Encode(int charNum, unsigned short *buf) { - if (charNum < 0) - return 0; - if (charNum < 0x10000) - { - buf[0] = (unsigned short)charNum; - return 1; - } - if (charNum < 0x110000) - { - charNum -= 0x10000; - buf[0] = (unsigned short)((charNum >> 10) + 0xD800); - buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00); - return 2; - } + if (charNum < 0) return 0; + if (charNum < 0x10000) { + buf[0] = (unsigned short)charNum; + return 1; + } + if (charNum < 0x110000) { + charNum -= 0x10000; + buf[0] = (unsigned short)((charNum >> 10) + 0xD800); + buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00); + return 2; + } + return 0; } -struct unknown_encoding -{ - struct normal_encoding normal; - CONVERTER convert; - void *userData; - unsigned short utf16[256]; - char utf8[256][4]; +struct unknown_encoding { + struct normal_encoding normal; + CONVERTER convert; + void *userData; + unsigned short utf16[256]; + char utf8[256][4]; }; #define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *) (enc)) @@ -1333,35 +1247,35 @@ struct unknown_encoding int XmlSizeOfUnknownEncoding(void) { - return sizeof(struct unknown_encoding); + return sizeof(struct unknown_encoding); } static int PTRFASTCALL unknown_isName(const ENCODING *enc, const char *p) { - const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); - int c = uenc->convert(uenc->userData, p); - if (c & ~0xFFFF) - return 0; - return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF); + const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); + int c = uenc->convert(uenc->userData, p); + if (c & ~0xFFFF) + return 0; + return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF); } static int PTRFASTCALL unknown_isNmstrt(const ENCODING *enc, const char *p) { - const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); - int c = uenc->convert(uenc->userData, p); - if (c & ~0xFFFF) - return 0; - return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF); + const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); + int c = uenc->convert(uenc->userData, p); + if (c & ~0xFFFF) + return 0; + return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF); } static int PTRFASTCALL unknown_isInvalid(const ENCODING *enc, const char *p) { - const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); - int c = uenc->convert(uenc->userData, p); - return (c & ~0xFFFF) || checkCharRefNumber(c) < 0; + const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); + int c = uenc->convert(uenc->userData, p); + return (c & ~0xFFFF) || checkCharRefNumber(c) < 0; } static void PTRCALL @@ -1369,38 +1283,33 @@ unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { - const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); - char buf[XML_UTF8_ENCODE_MAX]; - for (;;) - { - const char *utf8; - int n; - if (*fromP == fromLim) - break; - utf8 = uenc->utf8[(unsigned char)**fromP]; - n = *utf8++; - if (n == 0) - { - int c = uenc->convert(uenc->userData, *fromP); - n = XmlUtf8Encode(c, buf); - if (n > toLim - *toP) - break; - utf8 = buf; - *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP] - - (BT_LEAD2 - 2)); - } - else - { - if (n > toLim - *toP) - break; - (*fromP)++; - } - do - { - *(*toP)++ = *utf8++; - } - while (--n != 0); + const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); + char buf[XML_UTF8_ENCODE_MAX]; + for (;;) { + const char *utf8; + int n; + if (*fromP == fromLim) + break; + utf8 = uenc->utf8[(unsigned char)**fromP]; + n = *utf8++; + if (n == 0) { + int c = uenc->convert(uenc->userData, *fromP); + n = XmlUtf8Encode(c, buf); + if (n > toLim - *toP) + break; + utf8 = buf; + *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP] + - (BT_LEAD2 - 2)); + } + else { + if (n > toLim - *toP) + break; + (*fromP)++; } + do { + *(*toP)++ = *utf8++; + } while (--n != 0); + } } static void PTRCALL @@ -1408,21 +1317,19 @@ unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { - const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); - while (*fromP != fromLim && *toP != toLim) - { - unsigned short c = uenc->utf16[(unsigned char)**fromP]; - if (c == 0) - { - c = (unsigned short) - uenc->convert(uenc->userData, *fromP); - *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP] - - (BT_LEAD2 - 2)); - } - else - (*fromP)++; - *(*toP)++ = c; + const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); + while (*fromP != fromLim && *toP != toLim) { + unsigned short c = uenc->utf16[(unsigned char)**fromP]; + if (c == 0) { + c = (unsigned short) + uenc->convert(uenc->userData, *fromP); + *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP] + - (BT_LEAD2 - 2)); } + else + (*fromP)++; + *(*toP)++ = c; + } } ENCODING * @@ -1431,149 +1338,134 @@ XmlInitUnknownEncoding(void *mem, CONVERTER convert, void *userData) { - int i; - struct unknown_encoding *e = (struct unknown_encoding *)mem; - for (i = 0; i < (int)sizeof(struct normal_encoding); i++) - ((char *)mem)[i] = ((char *)&latin1_encoding)[i]; - for (i = 0; i < 128; i++) - if (latin1_encoding.type[i] != BT_OTHER - && latin1_encoding.type[i] != BT_NONXML - && table[i] != i) - return 0; - for (i = 0; i < 256; i++) - { - int c = table[i]; - if (c == -1) - { - e->normal.type[i] = BT_MALFORM; - /* This shouldn't really get used. */ - e->utf16[i] = 0xFFFF; - e->utf8[i][0] = 1; - e->utf8[i][1] = 0; - } - else if (c < 0) - { - if (c < -4) - return 0; - e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2)); - e->utf8[i][0] = 0; - e->utf16[i] = 0; - } - else if (c < 0x80) - { - if (latin1_encoding.type[c] != BT_OTHER - && latin1_encoding.type[c] != BT_NONXML - && c != i) - return 0; - e->normal.type[i] = latin1_encoding.type[c]; - e->utf8[i][0] = 1; - e->utf8[i][1] = (char)c; - e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c); - } - else if (checkCharRefNumber(c) < 0) - { - e->normal.type[i] = BT_NONXML; - /* This shouldn't really get used. */ - e->utf16[i] = 0xFFFF; - e->utf8[i][0] = 1; - e->utf8[i][1] = 0; - } - else - { - if (c > 0xFFFF) - return 0; - if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff)) - e->normal.type[i] = BT_NMSTRT; - else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff)) - e->normal.type[i] = BT_NAME; - else - e->normal.type[i] = BT_OTHER; - e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1); - e->utf16[i] = (unsigned short)c; - } + int i; + struct unknown_encoding *e = (struct unknown_encoding *)mem; + for (i = 0; i < (int)sizeof(struct normal_encoding); i++) + ((char *)mem)[i] = ((char *)&latin1_encoding)[i]; + for (i = 0; i < 128; i++) + if (latin1_encoding.type[i] != BT_OTHER + && latin1_encoding.type[i] != BT_NONXML + && table[i] != i) + return 0; + for (i = 0; i < 256; i++) { + int c = table[i]; + if (c == -1) { + e->normal.type[i] = BT_MALFORM; + /* This shouldn't really get used. */ + e->utf16[i] = 0xFFFF; + e->utf8[i][0] = 1; + e->utf8[i][1] = 0; + } + else if (c < 0) { + if (c < -4) + return 0; + e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2)); + e->utf8[i][0] = 0; + e->utf16[i] = 0; } - e->userData = userData; - e->convert = convert; - if (convert) - { - e->normal.isName2 = unknown_isName; - e->normal.isName3 = unknown_isName; - e->normal.isName4 = unknown_isName; - e->normal.isNmstrt2 = unknown_isNmstrt; - e->normal.isNmstrt3 = unknown_isNmstrt; - e->normal.isNmstrt4 = unknown_isNmstrt; - e->normal.isInvalid2 = unknown_isInvalid; - e->normal.isInvalid3 = unknown_isInvalid; - e->normal.isInvalid4 = unknown_isInvalid; + else if (c < 0x80) { + if (latin1_encoding.type[c] != BT_OTHER + && latin1_encoding.type[c] != BT_NONXML + && c != i) + return 0; + e->normal.type[i] = latin1_encoding.type[c]; + e->utf8[i][0] = 1; + e->utf8[i][1] = (char)c; + e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c); + } + else if (checkCharRefNumber(c) < 0) { + e->normal.type[i] = BT_NONXML; + /* This shouldn't really get used. */ + e->utf16[i] = 0xFFFF; + e->utf8[i][0] = 1; + e->utf8[i][1] = 0; + } + else { + if (c > 0xFFFF) + return 0; + if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff)) + e->normal.type[i] = BT_NMSTRT; + else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff)) + e->normal.type[i] = BT_NAME; + else + e->normal.type[i] = BT_OTHER; + e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1); + e->utf16[i] = (unsigned short)c; } - e->normal.enc.utf8Convert = unknown_toUtf8; - e->normal.enc.utf16Convert = unknown_toUtf16; - return &(e->normal.enc); + } + e->userData = userData; + e->convert = convert; + if (convert) { + e->normal.isName2 = unknown_isName; + e->normal.isName3 = unknown_isName; + e->normal.isName4 = unknown_isName; + e->normal.isNmstrt2 = unknown_isNmstrt; + e->normal.isNmstrt3 = unknown_isNmstrt; + e->normal.isNmstrt4 = unknown_isNmstrt; + e->normal.isInvalid2 = unknown_isInvalid; + e->normal.isInvalid3 = unknown_isInvalid; + e->normal.isInvalid4 = unknown_isInvalid; + } + e->normal.enc.utf8Convert = unknown_toUtf8; + e->normal.enc.utf16Convert = unknown_toUtf16; + return &(e->normal.enc); } /* If this enumeration is changed, getEncodingIndex and encodings must also be changed. */ -enum -{ - UNKNOWN_ENC = -1, - ISO_8859_1_ENC = 0, - US_ASCII_ENC, - UTF_8_ENC, - UTF_16_ENC, - UTF_16BE_ENC, - UTF_16LE_ENC, - /* must match encodingNames up to here */ - NO_ENC +enum { + UNKNOWN_ENC = -1, + ISO_8859_1_ENC = 0, + US_ASCII_ENC, + UTF_8_ENC, + UTF_16_ENC, + UTF_16BE_ENC, + UTF_16LE_ENC, + /* must match encodingNames up to here */ + NO_ENC }; -static const char KW_ISO_8859_1[] = -{ - ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9, - ASCII_MINUS, ASCII_1, '\0' +static const char KW_ISO_8859_1[] = { + ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9, + ASCII_MINUS, ASCII_1, '\0' }; -static const char KW_US_ASCII[] = -{ - ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I, - '\0' +static const char KW_US_ASCII[] = { + ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I, + '\0' }; -static const char KW_UTF_8[] = -{ - ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0' +static const char KW_UTF_8[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0' }; -static const char KW_UTF_16[] = -{ - ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0' +static const char KW_UTF_16[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0' }; -static const char KW_UTF_16BE[] = -{ - ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E, - '\0' +static const char KW_UTF_16BE[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E, + '\0' }; -static const char KW_UTF_16LE[] = -{ - ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E, - '\0' +static const char KW_UTF_16LE[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E, + '\0' }; static int FASTCALL getEncodingIndex(const char *name) { - static const char *encodingNames[] = - { - KW_ISO_8859_1, - KW_US_ASCII, - KW_UTF_8, - KW_UTF_16, - KW_UTF_16BE, - KW_UTF_16LE, - }; - int i; - if (name == NULL) - return NO_ENC; - for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++) - if (streqci(name, encodingNames[i])) - return i; - return UNKNOWN_ENC; + static const char *encodingNames[] = { + KW_ISO_8859_1, + KW_US_ASCII, + KW_UTF_8, + KW_UTF_16, + KW_UTF_16BE, + KW_UTF_16LE, + }; + int i; + if (name == NULL) + return NO_ENC; + for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++) + if (streqci(name, encodingNames[i])) + return i; + return UNKNOWN_ENC; } /* For binary compatibility, we store the index of the encoding @@ -1599,127 +1491,118 @@ initScan(const ENCODING **encodingTable, const char *end, const char **nextTokPtr) { - const ENCODING **encPtr; - - if (ptr == end) - return XML_TOK_NONE; - encPtr = enc->encPtr; - if (ptr + 1 == end) - { - /* only a single byte available for auto-detection */ + const ENCODING **encPtr; + + if (ptr == end) + return XML_TOK_NONE; + encPtr = enc->encPtr; + if (ptr + 1 == end) { + /* only a single byte available for auto-detection */ #ifndef XML_DTD /* FIXME */ - /* a well-formed document entity must have more than one byte */ - if (state != XML_CONTENT_STATE) - return XML_TOK_PARTIAL; + /* a well-formed document entity must have more than one byte */ + if (state != XML_CONTENT_STATE) + return XML_TOK_PARTIAL; #endif - /* so we're parsing an external text entity... */ - /* if UTF-16 was externally specified, then we need at least 2 bytes */ - switch (INIT_ENC_INDEX(enc)) - { - case UTF_16_ENC: - case UTF_16LE_ENC: - case UTF_16BE_ENC: - return XML_TOK_PARTIAL; - } - switch ((unsigned char)*ptr) - { - case 0xFE: - case 0xFF: - case 0xEF: /* possibly first byte of UTF-8 BOM */ - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - /* fall through */ - case 0x00: - case 0x3C: - return XML_TOK_PARTIAL; - } + /* so we're parsing an external text entity... */ + /* if UTF-16 was externally specified, then we need at least 2 bytes */ + switch (INIT_ENC_INDEX(enc)) { + case UTF_16_ENC: + case UTF_16LE_ENC: + case UTF_16BE_ENC: + return XML_TOK_PARTIAL; } - else - { - switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) - { - case 0xFEFF: - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - *nextTokPtr = ptr + 2; - *encPtr = encodingTable[UTF_16BE_ENC]; - return XML_TOK_BOM; - /* 00 3C is handled in the default case */ - case 0x3C00: - if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC - || INIT_ENC_INDEX(enc) == UTF_16_ENC) - && state == XML_CONTENT_STATE) - break; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - case 0xFFFE: - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - *nextTokPtr = ptr + 2; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XML_TOK_BOM; - case 0xEFBB: - /* Maybe a UTF-8 BOM (EF BB BF) */ - /* If there's an explicitly specified (external) encoding - of ISO-8859-1 or some flavour of UTF-16 - and this is an external text entity, - don't look for the BOM, - because it might be a legal data. - */ - if (state == XML_CONTENT_STATE) - { - int e = INIT_ENC_INDEX(enc); - if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC - || e == UTF_16LE_ENC || e == UTF_16_ENC) - break; - } - if (ptr + 2 == end) - return XML_TOK_PARTIAL; - if ((unsigned char)ptr[2] == 0xBF) - { - *nextTokPtr = ptr + 3; - *encPtr = encodingTable[UTF_8_ENC]; - return XML_TOK_BOM; - } - break; - default: - if (ptr[0] == '\0') - { - /* 0 isn't a legal data character. Furthermore a document - entity can only start with ASCII characters. So the only - way this can fail to be big-endian UTF-16 if it it's an - external parsed general entity that's labelled as - UTF-16LE. - */ - if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC) - break; - *encPtr = encodingTable[UTF_16BE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - } - else if (ptr[1] == '\0') - { - /* We could recover here in the case: - - parsing an external entity - - second byte is 0 - - no externally specified encoding - - no encoding declaration - by assuming UTF-16LE. But we don't, because this would mean when - presented just with a single byte, we couldn't reliably determine - whether we needed further bytes. - */ - if (state == XML_CONTENT_STATE) - break; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - } - break; - } + switch ((unsigned char)*ptr) { + case 0xFE: + case 0xFF: + case 0xEF: /* possibly first byte of UTF-8 BOM */ + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + /* fall through */ + case 0x00: + case 0x3C: + return XML_TOK_PARTIAL; + } + } + else { + switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) { + case 0xFEFF: + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + *nextTokPtr = ptr + 2; + *encPtr = encodingTable[UTF_16BE_ENC]; + return XML_TOK_BOM; + /* 00 3C is handled in the default case */ + case 0x3C00: + if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC + || INIT_ENC_INDEX(enc) == UTF_16_ENC) + && state == XML_CONTENT_STATE) + break; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + case 0xFFFE: + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + *nextTokPtr = ptr + 2; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XML_TOK_BOM; + case 0xEFBB: + /* Maybe a UTF-8 BOM (EF BB BF) */ + /* If there's an explicitly specified (external) encoding + of ISO-8859-1 or some flavour of UTF-16 + and this is an external text entity, + don't look for the BOM, + because it might be a legal data. + */ + if (state == XML_CONTENT_STATE) { + int e = INIT_ENC_INDEX(enc); + if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC + || e == UTF_16LE_ENC || e == UTF_16_ENC) + break; + } + if (ptr + 2 == end) + return XML_TOK_PARTIAL; + if ((unsigned char)ptr[2] == 0xBF) { + *nextTokPtr = ptr + 3; + *encPtr = encodingTable[UTF_8_ENC]; + return XML_TOK_BOM; + } + break; + default: + if (ptr[0] == '\0') { + /* 0 isn't a legal data character. Furthermore a document + entity can only start with ASCII characters. So the only + way this can fail to be big-endian UTF-16 if it it's an + external parsed general entity that's labelled as + UTF-16LE. + */ + if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC) + break; + *encPtr = encodingTable[UTF_16BE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + } + else if (ptr[1] == '\0') { + /* We could recover here in the case: + - parsing an external entity + - second byte is 0 + - no externally specified encoding + - no encoding declaration + by assuming UTF-16LE. But we don't, because this would mean when + presented just with a single byte, we couldn't reliably determine + whether we needed further bytes. + */ + if (state == XML_CONTENT_STATE) + break; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + } + break; } - *encPtr = encodingTable[INIT_ENC_INDEX(enc)]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + } + *encPtr = encodingTable[INIT_ENC_INDEX(enc)]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); } @@ -1745,10 +1628,10 @@ XmlInitUnknownEncodingNS(void *mem, CONVERTER convert, void *userData) { - ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); - if (enc) - ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON; - return enc; + ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); + if (enc) + ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON; + return enc; } #endif /* XML_NS */ diff --git a/src/simgear/xml/xmltok.h b/src/simgear/xml/xmltok.h old mode 100644 new mode 100755 index b8aac6dfed716b20691875dd0dfd73c025618a0d..1ecd05f886287bc23dd27e0b7da4bce619837300 --- a/src/simgear/xml/xmltok.h +++ b/src/simgear/xml/xmltok.h @@ -6,26 +6,25 @@ #define XmlTok_INCLUDED 1 #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - /* The following token may be returned by XmlContentTok */ +/* The following token may be returned by XmlContentTok */ #define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be - start of illegal ]]> sequence */ - /* The following tokens may be returned by both XmlPrologTok and - XmlContentTok. - */ + start of illegal ]]> sequence */ +/* The following tokens may be returned by both XmlPrologTok and + XmlContentTok. +*/ #define XML_TOK_NONE -4 /* The string to be scanned is empty */ #define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan; - might be part of CRLF sequence */ + might be part of CRLF sequence */ #define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ #define XML_TOK_PARTIAL -1 /* only part of a token */ #define XML_TOK_INVALID 0 - /* The following tokens are returned by XmlContentTok; some are also - returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok. - */ +/* The following tokens are returned by XmlContentTok; some are also + returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok. +*/ #define XML_TOK_START_TAG_WITH_ATTS 1 #define XML_TOK_START_TAG_NO_ATTS 2 #define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */ @@ -37,15 +36,15 @@ extern "C" #define XML_TOK_ENTITY_REF 9 #define XML_TOK_CHAR_REF 10 /* numeric character reference */ - /* The following tokens may be returned by both XmlPrologTok and - XmlContentTok. - */ +/* The following tokens may be returned by both XmlPrologTok and + XmlContentTok. +*/ #define XML_TOK_PI 11 /* processing instruction */ #define XML_TOK_XML_DECL 12 /* XML decl or text decl */ #define XML_TOK_COMMENT 13 #define XML_TOK_BOM 14 /* Byte order mark */ - /* The following tokens are returned only by XmlPrologTok */ +/* The following tokens are returned only by XmlPrologTok */ #define XML_TOK_PROLOG_S 15 #define XML_TOK_DECL_OPEN 16 /* <!foo */ #define XML_TOK_DECL_CLOSE 17 /* > */ @@ -62,7 +61,7 @@ extern "C" #define XML_TOK_PARAM_ENTITY_REF 28 #define XML_TOK_INSTANCE_START 29 - /* The following occur only in element type declarations */ +/* The following occur only in element type declarations */ #define XML_TOK_NAME_QUESTION 30 /* name? */ #define XML_TOK_NAME_ASTERISK 31 /* name* */ #define XML_TOK_NAME_PLUS 32 /* name+ */ @@ -73,15 +72,15 @@ extern "C" #define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ #define XML_TOK_COMMA 38 - /* The following token is returned only by XmlAttributeValueTok */ +/* The following token is returned only by XmlAttributeValueTok */ #define XML_TOK_ATTRIBUTE_VALUE_S 39 - /* The following token is returned only by XmlCdataSectionTok */ +/* The following token is returned only by XmlCdataSectionTok */ #define XML_TOK_CDATA_SECT_CLOSE 40 - /* With namespace processing this is returned by XmlPrologTok for a - name with a colon. - */ +/* With namespace processing this is returned by XmlPrologTok for a + name with a colon. +*/ #define XML_TOK_PREFIXED_NAME 41 #ifdef XML_DTD @@ -105,98 +104,95 @@ extern "C" #define XML_ATTRIBUTE_VALUE_LITERAL 0 #define XML_ENTITY_VALUE_LITERAL 1 - /* The size of the buffer passed to XmlUtf8Encode must be at least this. */ +/* The size of the buffer passed to XmlUtf8Encode must be at least this. */ #define XML_UTF8_ENCODE_MAX 4 - /* The size of the buffer passed to XmlUtf16Encode must be at least this. */ +/* The size of the buffer passed to XmlUtf16Encode must be at least this. */ #define XML_UTF16_ENCODE_MAX 2 - typedef struct position - { - /* first line and first column are 0 not 1 */ - unsigned long lineNumber; - unsigned long columnNumber; - } POSITION; - - typedef struct - { - const char *name; - const char *valuePtr; - const char *valueEnd; - char normalized; - } ATTRIBUTE; - - struct encoding; - typedef struct encoding ENCODING; - - typedef int (PTRCALL *SCANNER)(const ENCODING *, - const char *, - const char *, - const char **); - - struct encoding - { - SCANNER scanners[XML_N_STATES]; - SCANNER literalScanners[XML_N_LITERAL_TYPES]; - int (PTRCALL *sameName)(const ENCODING *, - const char *, - const char *); - int (PTRCALL *nameMatchesAscii)(const ENCODING *, - const char *, - const char *, - const char *); - int (PTRFASTCALL *nameLength)(const ENCODING *, const char *); - const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *); - int (PTRCALL *getAtts)(const ENCODING *enc, - const char *ptr, - int attsMax, - ATTRIBUTE *atts); - int (PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr); - int (PTRCALL *predefinedEntityName)(const ENCODING *, - const char *, - const char *); - void (PTRCALL *updatePosition)(const ENCODING *, - const char *ptr, - const char *end, - POSITION *); - int (PTRCALL *isPublicId)(const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr); - void (PTRCALL *utf8Convert)(const ENCODING *enc, - const char **fromP, - const char *fromLim, - char **toP, - const char *toLim); - void (PTRCALL *utf16Convert)(const ENCODING *enc, - const char **fromP, - const char *fromLim, - unsigned short **toP, - const unsigned short *toLim); - int minBytesPerChar; - char isUtf8; - char isUtf16; - }; - - /* Scan the string starting at ptr until the end of the next complete - token, but do not scan past eptr. Return an integer giving the - type of token. - - Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. - - Return XML_TOK_PARTIAL when the string does not contain a complete - token; nextTokPtr will not be set. - - Return XML_TOK_INVALID when the string does not start a valid - token; nextTokPtr will be set to point to the character which made - the token invalid. - - Otherwise the string starts with a valid token; nextTokPtr will be - set to point to the character following the end of that token. - - Each data character counts as a single token, but adjacent data - characters may be returned together. Similarly for characters in - the prolog outside literals, comments and processing instructions. - */ +typedef struct position { + /* first line and first column are 0 not 1 */ + unsigned long lineNumber; + unsigned long columnNumber; +} POSITION; + +typedef struct { + const char *name; + const char *valuePtr; + const char *valueEnd; + char normalized; +} ATTRIBUTE; + +struct encoding; +typedef struct encoding ENCODING; + +typedef int (PTRCALL *SCANNER)(const ENCODING *, + const char *, + const char *, + const char **); + +struct encoding { + SCANNER scanners[XML_N_STATES]; + SCANNER literalScanners[XML_N_LITERAL_TYPES]; + int (PTRCALL *sameName)(const ENCODING *, + const char *, + const char *); + int (PTRCALL *nameMatchesAscii)(const ENCODING *, + const char *, + const char *, + const char *); + int (PTRFASTCALL *nameLength)(const ENCODING *, const char *); + const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *); + int (PTRCALL *getAtts)(const ENCODING *enc, + const char *ptr, + int attsMax, + ATTRIBUTE *atts); + int (PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr); + int (PTRCALL *predefinedEntityName)(const ENCODING *, + const char *, + const char *); + void (PTRCALL *updatePosition)(const ENCODING *, + const char *ptr, + const char *end, + POSITION *); + int (PTRCALL *isPublicId)(const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr); + void (PTRCALL *utf8Convert)(const ENCODING *enc, + const char **fromP, + const char *fromLim, + char **toP, + const char *toLim); + void (PTRCALL *utf16Convert)(const ENCODING *enc, + const char **fromP, + const char *fromLim, + unsigned short **toP, + const unsigned short *toLim); + int minBytesPerChar; + char isUtf8; + char isUtf16; +}; + +/* Scan the string starting at ptr until the end of the next complete + token, but do not scan past eptr. Return an integer giving the + type of token. + + Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. + + Return XML_TOK_PARTIAL when the string does not contain a complete + token; nextTokPtr will not be set. + + Return XML_TOK_INVALID when the string does not start a valid + token; nextTokPtr will be set to point to the character which made + the token invalid. + + Otherwise the string starts with a valid token; nextTokPtr will be + set to point to the character following the end of that token. + + Each data character counts as a single token, but adjacent data + characters may be returned together. Similarly for characters in + the prolog outside literals, comments and processing instructions. +*/ #define XmlTok(enc, state, ptr, end, nextTokPtr) \ @@ -218,9 +214,9 @@ extern "C" #endif /* XML_DTD */ - /* This is used for performing a 2nd-level tokenization on the content - of a literal that has already been returned by XmlTok. - */ +/* This is used for performing a 2nd-level tokenization on the content + of a literal that has already been returned by XmlTok. +*/ #define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) @@ -262,58 +258,57 @@ extern "C" #define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) - typedef struct - { - ENCODING initEnc; - const ENCODING **encPtr; - } INIT_ENCODING; - - int XmlParseXmlDecl(int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **versionEndPtr, - const char **encodingNamePtr, - const ENCODING **namedEncodingPtr, - int *standalonePtr); - - int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name); - const ENCODING *XmlGetUtf8InternalEncoding(void); - const ENCODING *XmlGetUtf16InternalEncoding(void); - int FASTCALL XmlUtf8Encode(int charNumber, char *buf); - int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf); - int XmlSizeOfUnknownEncoding(void); - - - typedef int (XMLCALL *CONVERTER) (void *userData, const char *p); - - ENCODING * - XmlInitUnknownEncoding(void *mem, - int *table, - CONVERTER convert, - void *userData); - - int XmlParseXmlDeclNS(int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **versionEndPtr, - const char **encodingNamePtr, - const ENCODING **namedEncodingPtr, - int *standalonePtr); - - int XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name); - const ENCODING *XmlGetUtf8InternalEncodingNS(void); - const ENCODING *XmlGetUtf16InternalEncodingNS(void); - ENCODING * - XmlInitUnknownEncodingNS(void *mem, - int *table, - CONVERTER convert, - void *userData); +typedef struct { + ENCODING initEnc; + const ENCODING **encPtr; +} INIT_ENCODING; + +int XmlParseXmlDecl(int isGeneralTextEntity, + const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr, + const char **versionPtr, + const char **versionEndPtr, + const char **encodingNamePtr, + const ENCODING **namedEncodingPtr, + int *standalonePtr); + +int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name); +const ENCODING *XmlGetUtf8InternalEncoding(void); +const ENCODING *XmlGetUtf16InternalEncoding(void); +int FASTCALL XmlUtf8Encode(int charNumber, char *buf); +int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf); +int XmlSizeOfUnknownEncoding(void); + + +typedef int (XMLCALL *CONVERTER) (void *userData, const char *p); + +ENCODING * +XmlInitUnknownEncoding(void *mem, + int *table, + CONVERTER convert, + void *userData); + +int XmlParseXmlDeclNS(int isGeneralTextEntity, + const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr, + const char **versionPtr, + const char **versionEndPtr, + const char **encodingNamePtr, + const ENCODING **namedEncodingPtr, + int *standalonePtr); + +int XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name); +const ENCODING *XmlGetUtf8InternalEncodingNS(void); +const ENCODING *XmlGetUtf16InternalEncodingNS(void); +ENCODING * +XmlInitUnknownEncodingNS(void *mem, + int *table, + CONVERTER convert, + void *userData); #ifdef __cplusplus } #endif diff --git a/src/simgear/xml/xmltok_impl.c b/src/simgear/xml/xmltok_impl.c old mode 100644 new mode 100755 index f6e067a8d7b28d9a6b23047d7ffc3da8a791f7c1..46569fe38aad148a25f3d83a635d0eecbd42641f --- a/src/simgear/xml/xmltok_impl.c +++ b/src/simgear/xml/xmltok_impl.c @@ -90,42 +90,36 @@ static int PTRCALL PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - if (ptr != end) - { - if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) - { + if (ptr != end) { + if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + ptr += MINBPC(enc); + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + INVALID_CASES(ptr, nextTokPtr) + case BT_MINUS: + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) { + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { *nextTokPtr = ptr; return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_COMMENT; } + break; + default: ptr += MINBPC(enc); - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - INVALID_CASES(ptr, nextTokPtr) - case BT_MINUS: - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) - { - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) - { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_COMMENT; - } - break; - default: - ptr += MINBPC(enc); - break; - } - } + break; + } } - return XML_TOK_PARTIAL; + } + return XML_TOK_PARTIAL; } /* ptr points to character following "<!" */ @@ -134,102 +128,90 @@ static int PTRCALL PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - if (ptr == end) + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + case BT_MINUS: + return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_LSQB: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_COND_SECT_OPEN; + case BT_NMSTRT: + case BT_HEX: + ptr += MINBPC(enc); + break; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_PERCNT: + if (ptr + MINBPC(enc) == end) return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - case BT_MINUS: - return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_LSQB: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_COND_SECT_OPEN; + /* don't allow <!ENTITY% foo "whatever"> */ + switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) { + case BT_S: case BT_CR: case BT_LF: case BT_PERCNT: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + /* fall through */ + case BT_S: case BT_CR: case BT_LF: + *nextTokPtr = ptr; + return XML_TOK_DECL_OPEN; case BT_NMSTRT: case BT_HEX: - ptr += MINBPC(enc); - break; + ptr += MINBPC(enc); + break; default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - case BT_PERCNT: - if (ptr + MINBPC(enc) == end) - return XML_TOK_PARTIAL; - /* don't allow <!ENTITY% foo "whatever"> */ - switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) - { - case BT_S: - case BT_CR: - case BT_LF: - case BT_PERCNT: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - /* fall through */ - case BT_S: - case BT_CR: - case BT_LF: - *nextTokPtr = ptr; - return XML_TOK_DECL_OPEN; - case BT_NMSTRT: - case BT_HEX: - ptr += MINBPC(enc); - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - return XML_TOK_PARTIAL; + } + return XML_TOK_PARTIAL; } static int PTRCALL PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr) { - int upper = 0; - *tokPtr = XML_TOK_PI; - if (end - ptr != MINBPC(enc)*3) - return 1; - switch (BYTE_TO_ASCII(enc, ptr)) - { - case ASCII_x: - break; - case ASCII_X: - upper = 1; - break; - default: - return 1; - } - ptr += MINBPC(enc); - switch (BYTE_TO_ASCII(enc, ptr)) - { - case ASCII_m: - break; - case ASCII_M: - upper = 1; - break; - default: - return 1; - } - ptr += MINBPC(enc); - switch (BYTE_TO_ASCII(enc, ptr)) - { - case ASCII_l: - break; - case ASCII_L: - upper = 1; - break; - default: - return 1; - } - if (upper) - return 0; - *tokPtr = XML_TOK_XML_DECL; + int upper = 0; + *tokPtr = XML_TOK_PI; + if (end - ptr != MINBPC(enc)*3) + return 1; + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_x: + break; + case ASCII_X: + upper = 1; + break; + default: return 1; + } + ptr += MINBPC(enc); + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_m: + break; + case ASCII_M: + upper = 1; + break; + default: + return 1; + } + ptr += MINBPC(enc); + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_l: + break; + case ASCII_L: + upper = 1; + break; + default: + return 1; + } + if (upper) + return 0; + *tokPtr = XML_TOK_XML_DECL; + return 1; } /* ptr points to character following "<?" */ @@ -238,153 +220,133 @@ static int PTRCALL PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - int tok; - const char *target = ptr; - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: + int tok; + const char *target = ptr; + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_S: case BT_CR: case BT_LF: + if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) { *nextTokPtr = ptr; return XML_TOK_INVALID; - } - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - case BT_S: - case BT_CR: - case BT_LF: - if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) - { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - ptr += MINBPC(enc); - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - INVALID_CASES(ptr, nextTokPtr) - case BT_QUEST: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, ASCII_GT)) - { - *nextTokPtr = ptr + MINBPC(enc); - return tok; - } - break; - default: - ptr += MINBPC(enc); - break; - } - } - return XML_TOK_PARTIAL; + } + ptr += MINBPC(enc); + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + INVALID_CASES(ptr, nextTokPtr) case BT_QUEST: - if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) - { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, ASCII_GT)) - { - *nextTokPtr = ptr + MINBPC(enc); - return tok; - } - /* fall through */ + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_GT)) { + *nextTokPtr = ptr + MINBPC(enc); + return tok; + } + break; default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; + ptr += MINBPC(enc); + break; } + } + return XML_TOK_PARTIAL; + case BT_QUEST: + if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_GT)) { + *nextTokPtr = ptr + MINBPC(enc); + return tok; + } + /* fall through */ + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - return XML_TOK_PARTIAL; + } + return XML_TOK_PARTIAL; } static int PTRCALL PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - static const char CDATA_LSQB[] = { ASCII_C, ASCII_D, ASCII_A, - ASCII_T, ASCII_A, ASCII_LSQB - }; - int i; - /* CDATA[ */ - if (end - ptr < 6 * MINBPC(enc)) - return XML_TOK_PARTIAL; - for (i = 0; i < 6; i++, ptr += MINBPC(enc)) - { - if (!CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) - { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } + static const char CDATA_LSQB[] = { ASCII_C, ASCII_D, ASCII_A, + ASCII_T, ASCII_A, ASCII_LSQB }; + int i; + /* CDATA[ */ + if (end - ptr < 6 * MINBPC(enc)) + return XML_TOK_PARTIAL; + for (i = 0; i < 6; i++, ptr += MINBPC(enc)) { + if (!CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - *nextTokPtr = ptr; - return XML_TOK_CDATA_SECT_OPEN; + } + *nextTokPtr = ptr; + return XML_TOK_CDATA_SECT_OPEN; } static int PTRCALL PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) - { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) - { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } + if (ptr == end) + return XML_TOK_NONE; + if (MINBPC(enc) > 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; } - switch (BYTE_TYPE(enc, ptr)) - { - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) - break; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) - { - ptr -= MINBPC(enc); - break; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CDATA_SECT_CLOSE; - case BT_CR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - case BT_LF: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - INVALID_CASES(ptr, nextTokPtr) - default: - ptr += MINBPC(enc); - break; + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) + break; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr -= MINBPC(enc); + break; } - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CDATA_SECT_CLOSE; + case BT_CR: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + case BT_LF: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + INVALID_CASES(ptr, nextTokPtr) + default: + ptr += MINBPC(enc); + break; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ @@ -393,23 +355,23 @@ PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, } \ ptr += n; \ break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE - case BT_NONXML: - case BT_MALFORM: - case BT_TRAIL: - case BT_CR: - case BT_LF: - case BT_RSQB: - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } + case BT_NONXML: + case BT_MALFORM: + case BT_TRAIL: + case BT_CR: + case BT_LF: + case BT_RSQB: + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; } /* ptr points to character following "</" */ @@ -418,56 +380,47 @@ static int PTRCALL PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - case BT_S: - case BT_CR: - case BT_LF: - for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) - { - switch (BYTE_TYPE(enc, ptr)) - { - case BT_S: - case BT_CR: - case BT_LF: - break; - case BT_GT: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_END_TAG; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -#ifdef XML_NS - case BT_COLON: - /* no need to check qname syntax here, - since end-tag must match exactly */ - ptr += MINBPC(enc); - break; -#endif + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_S: case BT_CR: case BT_LF: + for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_S: case BT_CR: case BT_LF: + break; case BT_GT: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_END_TAG; + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_END_TAG; default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; + *nextTokPtr = ptr; + return XML_TOK_INVALID; } + } + return XML_TOK_PARTIAL; +#ifdef XML_NS + case BT_COLON: + /* no need to check qname syntax here, + since end-tag must match exactly */ + ptr += MINBPC(enc); + break; +#endif + case BT_GT: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_END_TAG; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - return XML_TOK_PARTIAL; + } + return XML_TOK_PARTIAL; } /* ptr points to character following "&#X" */ @@ -476,34 +429,30 @@ static int PTRCALL PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - if (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - case BT_DIGIT: - case BT_HEX: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) - { - switch (BYTE_TYPE(enc, ptr)) - { - case BT_DIGIT: - case BT_HEX: - break; - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CHAR_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } + if (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_DIGIT: + case BT_HEX: + break; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - return XML_TOK_PARTIAL; + for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_DIGIT: + case BT_HEX: + break; + case BT_SEMI: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CHAR_REF; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + } + return XML_TOK_PARTIAL; } /* ptr points to character following "&#" */ @@ -512,34 +461,30 @@ static int PTRCALL PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - if (ptr != end) - { - if (CHAR_MATCHES(enc, ptr, ASCII_x)) - return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - switch (BYTE_TYPE(enc, ptr)) - { - case BT_DIGIT: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) - { - switch (BYTE_TYPE(enc, ptr)) - { - case BT_DIGIT: - break; - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CHAR_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } + if (ptr != end) { + if (CHAR_MATCHES(enc, ptr, ASCII_x)) + return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + switch (BYTE_TYPE(enc, ptr)) { + case BT_DIGIT: + break; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - return XML_TOK_PARTIAL; + for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_DIGIT: + break; + case BT_SEMI: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CHAR_REF; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + } + return XML_TOK_PARTIAL; } /* ptr points to character following "&" */ @@ -548,31 +493,28 @@ static int PTRCALL PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_NUM: - return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + case BT_NUM: + return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_SEMI: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_ENTITY_REF; default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_ENTITY_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; + } + return XML_TOK_PARTIAL; } /* ptr points to character following first character of attribute name */ @@ -582,175 +524,156 @@ PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { #ifdef XML_NS - int hadColon = 0; + int hadColon = 0; #endif - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) #ifdef XML_NS - case BT_COLON: - if (hadColon) - { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - hadColon = 1; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - break; + case BT_COLON: + if (hadColon) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + hadColon = 1; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + break; #endif + case BT_S: case BT_CR: case BT_LF: + for (;;) { + int t; + + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + t = BYTE_TYPE(enc, ptr); + if (t == BT_EQUALS) + break; + switch (t) { case BT_S: - case BT_CR: case BT_LF: - for (;;) - { - int t; - - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - t = BYTE_TYPE(enc, ptr); - if (t == BT_EQUALS) - break; - switch (t) - { - case BT_S: - case BT_LF: - case BT_CR: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - /* fall through */ - case BT_EQUALS: - { - int open; + case BT_CR: + break; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + /* fall through */ + case BT_EQUALS: + { + int open; #ifdef XML_NS - hadColon = 0; + hadColon = 0; #endif - for (;;) - { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - open = BYTE_TYPE(enc, ptr); - if (open == BT_QUOT || open == BT_APOS) - break; - switch (open) - { - case BT_S: - case BT_LF: - case BT_CR: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - ptr += MINBPC(enc); - /* in attribute value */ - for (;;) + for (;;) { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + open = BYTE_TYPE(enc, ptr); + if (open == BT_QUOT || open == BT_APOS) + break; + switch (open) { + case BT_S: + case BT_LF: + case BT_CR: + break; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + ptr += MINBPC(enc); + /* in attribute value */ + for (;;) { + int t; + if (ptr == end) + return XML_TOK_PARTIAL; + t = BYTE_TYPE(enc, ptr); + if (t == open) + break; + switch (t) { + INVALID_CASES(ptr, nextTokPtr) + case BT_AMP: { - int t; - if (ptr == end) - return XML_TOK_PARTIAL; - t = BYTE_TYPE(enc, ptr); - if (t == open) - break; - switch (t) - { - INVALID_CASES(ptr, nextTokPtr) - case BT_AMP: - { - int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr); - if (tok <= 0) - { - if (tok == XML_TOK_INVALID) - *nextTokPtr = ptr; - return tok; - } - break; - } - case BT_LT: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - default: - ptr += MINBPC(enc); - break; - } + int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr); + if (tok <= 0) { + if (tok == XML_TOK_INVALID) + *nextTokPtr = ptr; + return tok; + } + break; } + case BT_LT: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + default: ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - case BT_S: - case BT_CR: - case BT_LF: - break; - case BT_SOL: - goto sol; - case BT_GT: - goto gt; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - /* ptr points to closing quote */ - for (;;) - { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_S: - case BT_CR: - case BT_LF: - continue; - case BT_GT: -gt: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_START_TAG_WITH_ATTS; - case BT_SOL: -sol: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) - { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_EMPTY_ELEMENT_WITH_ATTS; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - break; - } break; + } } + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + case BT_S: + case BT_CR: + case BT_LF: + break; + case BT_SOL: + goto sol; + case BT_GT: + goto gt; default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + /* ptr points to closing quote */ + for (;;) { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + case BT_S: case BT_CR: case BT_LF: + continue; + case BT_GT: + gt: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_START_TAG_WITH_ATTS; + case BT_SOL: + sol: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_EMPTY_ELEMENT_WITH_ATTS; + default: *nextTokPtr = ptr; return XML_TOK_INVALID; + } + break; } + break; + } + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - return XML_TOK_PARTIAL; + } + return XML_TOK_PARTIAL; } /* ptr points to character following "<" */ @@ -760,173 +683,154 @@ PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { #ifdef XML_NS - int hadColon; + int hadColon; #endif - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_EXCL: - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - case BT_MINUS: - return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_LSQB: - return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), - end, nextTokPtr); - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_QUEST: - return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_SOL: - return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr); - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + case BT_EXCL: + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + case BT_MINUS: + return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_LSQB: + return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), + end, nextTokPtr); } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + case BT_QUEST: + return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_SOL: + return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr); + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } #ifdef XML_NS - hadColon = 0; + hadColon = 0; #endif - /* we have a start-tag */ - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + /* we have a start-tag */ + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) #ifdef XML_NS - case BT_COLON: - if (hadColon) - { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - hadColon = 1; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - break; + case BT_COLON: + if (hadColon) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + hadColon = 1; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + break; #endif - case BT_S: - case BT_CR: - case BT_LF: - { - ptr += MINBPC(enc); - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_GT: - goto gt; - case BT_SOL: - goto sol; - case BT_S: - case BT_CR: - case BT_LF: - ptr += MINBPC(enc); - continue; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr); - } - return XML_TOK_PARTIAL; - } - case BT_GT: -gt: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_START_TAG_NO_ATTS; - case BT_SOL: -sol: + case BT_S: case BT_CR: case BT_LF: + { + ptr += MINBPC(enc); + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + case BT_GT: + goto gt; + case BT_SOL: + goto sol; + case BT_S: case BT_CR: case BT_LF: ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) - { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_EMPTY_ELEMENT_NO_ATTS; - default: + continue; + default: *nextTokPtr = ptr; return XML_TOK_INVALID; + } + return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr); } + return XML_TOK_PARTIAL; + } + case BT_GT: + gt: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_START_TAG_NO_ATTS; + case BT_SOL: + sol: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_EMPTY_ELEMENT_NO_ATTS; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - return XML_TOK_PARTIAL; + } + return XML_TOK_PARTIAL; } static int PTRCALL PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) - { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) - { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } + if (ptr == end) + return XML_TOK_NONE; + if (MINBPC(enc) > 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; } - switch (BYTE_TYPE(enc, ptr)) - { - case BT_LT: - return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_AMP: - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_CR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - case BT_LF: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_RSQB; - if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) - break; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_RSQB; - if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) - { - ptr -= MINBPC(enc); - break; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - INVALID_CASES(ptr, nextTokPtr) - default: - ptr += MINBPC(enc); - break; + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_LT: + return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_AMP: + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_CR: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + case BT_LF: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_RSQB; + if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) + break; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_RSQB; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr -= MINBPC(enc); + break; } - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + INVALID_CASES(ptr, nextTokPtr) + default: + ptr += MINBPC(enc); + break; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ @@ -935,44 +839,40 @@ PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end, } \ ptr += n; \ break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE - case BT_RSQB: - if (ptr + MINBPC(enc) != end) - { - if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) - { - ptr += MINBPC(enc); - break; - } - if (ptr + 2*MINBPC(enc) != end) - { - if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) - { - ptr += MINBPC(enc); - break; - } - *nextTokPtr = ptr + 2*MINBPC(enc); - return XML_TOK_INVALID; - } - } - /* fall through */ - case BT_AMP: - case BT_LT: - case BT_NONXML: - case BT_MALFORM: - case BT_TRAIL: - case BT_CR: - case BT_LF: - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } + case BT_RSQB: + if (ptr + MINBPC(enc) != end) { + if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) { + ptr += MINBPC(enc); + break; + } + if (ptr + 2*MINBPC(enc) != end) { + if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) { + ptr += MINBPC(enc); + break; + } + *nextTokPtr = ptr + 2*MINBPC(enc); + return XML_TOK_INVALID; + } + } + /* fall through */ + case BT_AMP: + case BT_LT: + case BT_NONXML: + case BT_MALFORM: + case BT_TRAIL: + case BT_CR: + case BT_LF: + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; } /* ptr points to character following "%" */ @@ -981,70 +881,56 @@ static int PTRCALL PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - if (ptr == end) - return -XML_TOK_PERCENT; - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_S: - case BT_LF: - case BT_CR: - case BT_PERCNT: - *nextTokPtr = ptr; - return XML_TOK_PERCENT; + if (ptr == end) + return -XML_TOK_PERCENT; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + case BT_S: case BT_LF: case BT_CR: case BT_PERCNT: + *nextTokPtr = ptr; + return XML_TOK_PERCENT; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_SEMI: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_PARAM_ENTITY_REF; default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_PARAM_ENTITY_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - return XML_TOK_PARTIAL; + } + return XML_TOK_PARTIAL; } static int PTRCALL PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_CR: case BT_LF: case BT_S: + case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR: + *nextTokPtr = ptr; + return XML_TOK_POUND_NAME; default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - case BT_CR: - case BT_LF: - case BT_S: - case BT_RPAR: - case BT_GT: - case BT_PERCNT: - case BT_VERBAR: - *nextTokPtr = ptr; - return XML_TOK_POUND_NAME; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return -XML_TOK_POUND_NAME; + } + return -XML_TOK_POUND_NAME; } static int PTRCALL @@ -1052,181 +938,158 @@ PREFIX(scanLit)(int open, const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - while (ptr != end) - { - int t = BYTE_TYPE(enc, ptr); - switch (t) - { - INVALID_CASES(ptr, nextTokPtr) - case BT_QUOT: - case BT_APOS: - ptr += MINBPC(enc); - if (t != open) - break; - if (ptr == end) - return -XML_TOK_LITERAL; - *nextTokPtr = ptr; - switch (BYTE_TYPE(enc, ptr)) - { - case BT_S: - case BT_CR: - case BT_LF: - case BT_GT: - case BT_PERCNT: - case BT_LSQB: - return XML_TOK_LITERAL; - default: - return XML_TOK_INVALID; - } - default: - ptr += MINBPC(enc); - break; - } + while (ptr != end) { + int t = BYTE_TYPE(enc, ptr); + switch (t) { + INVALID_CASES(ptr, nextTokPtr) + case BT_QUOT: + case BT_APOS: + ptr += MINBPC(enc); + if (t != open) + break; + if (ptr == end) + return -XML_TOK_LITERAL; + *nextTokPtr = ptr; + switch (BYTE_TYPE(enc, ptr)) { + case BT_S: case BT_CR: case BT_LF: + case BT_GT: case BT_PERCNT: case BT_LSQB: + return XML_TOK_LITERAL; + default: + return XML_TOK_INVALID; + } + default: + ptr += MINBPC(enc); + break; } - return XML_TOK_PARTIAL; + } + return XML_TOK_PARTIAL; } static int PTRCALL PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - int tok; - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) - { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) - { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } + int tok; + if (ptr == end) + return XML_TOK_NONE; + if (MINBPC(enc) > 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; } - switch (BYTE_TYPE(enc, ptr)) + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_QUOT: + return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_APOS: + return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_LT: { - case BT_QUOT: - return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_APOS: - return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_LT: - { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) - { - case BT_EXCL: - return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_QUEST: - return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_NMSTRT: - case BT_HEX: - case BT_NONASCII: - case BT_LEAD2: - case BT_LEAD3: - case BT_LEAD4: - *nextTokPtr = ptr - MINBPC(enc); - return XML_TOK_INSTANCE_START; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + case BT_EXCL: + return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_QUEST: + return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_NMSTRT: + case BT_HEX: + case BT_NONASCII: + case BT_LEAD2: + case BT_LEAD3: + case BT_LEAD4: + *nextTokPtr = ptr - MINBPC(enc); + return XML_TOK_INSTANCE_START; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - case BT_CR: - if (ptr + MINBPC(enc) == end) - { - *nextTokPtr = end; - /* indicate that this might be part of a CR/LF pair */ - return -XML_TOK_PROLOG_S; - } + case BT_CR: + if (ptr + MINBPC(enc) == end) { + *nextTokPtr = end; + /* indicate that this might be part of a CR/LF pair */ + return -XML_TOK_PROLOG_S; + } + /* fall through */ + case BT_S: case BT_LF: + for (;;) { + ptr += MINBPC(enc); + if (ptr == end) + break; + switch (BYTE_TYPE(enc, ptr)) { + case BT_S: case BT_LF: + break; + case BT_CR: + /* don't split CR/LF pair */ + if (ptr + MINBPC(enc) != end) + break; /* fall through */ - case BT_S: - case BT_LF: - for (;;) - { - ptr += MINBPC(enc); - if (ptr == end) - break; - switch (BYTE_TYPE(enc, ptr)) - { - case BT_S: - case BT_LF: - break; - case BT_CR: - /* don't split CR/LF pair */ - if (ptr + MINBPC(enc) != end) - break; - /* fall through */ - default: - *nextTokPtr = ptr; - return XML_TOK_PROLOG_S; - } - } + default: *nextTokPtr = ptr; return XML_TOK_PROLOG_S; - case BT_PERCNT: - return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_COMMA: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_COMMA; - case BT_LSQB: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OPEN_BRACKET; - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return -XML_TOK_CLOSE_BRACKET; - if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) - { - if (ptr + MINBPC(enc) == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) - { - *nextTokPtr = ptr + 2*MINBPC(enc); - return XML_TOK_COND_SECT_CLOSE; - } - } - *nextTokPtr = ptr; - return XML_TOK_CLOSE_BRACKET; - case BT_LPAR: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OPEN_PAREN; + } + } + *nextTokPtr = ptr; + return XML_TOK_PROLOG_S; + case BT_PERCNT: + return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_COMMA: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_COMMA; + case BT_LSQB: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OPEN_BRACKET; + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return -XML_TOK_CLOSE_BRACKET; + if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { + if (ptr + MINBPC(enc) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) { + *nextTokPtr = ptr + 2*MINBPC(enc); + return XML_TOK_COND_SECT_CLOSE; + } + } + *nextTokPtr = ptr; + return XML_TOK_CLOSE_BRACKET; + case BT_LPAR: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OPEN_PAREN; + case BT_RPAR: + ptr += MINBPC(enc); + if (ptr == end) + return -XML_TOK_CLOSE_PAREN; + switch (BYTE_TYPE(enc, ptr)) { + case BT_AST: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_ASTERISK; + case BT_QUEST: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_QUESTION; + case BT_PLUS: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_PLUS; + case BT_CR: case BT_LF: case BT_S: + case BT_GT: case BT_COMMA: case BT_VERBAR: case BT_RPAR: - ptr += MINBPC(enc); - if (ptr == end) - return -XML_TOK_CLOSE_PAREN; - switch (BYTE_TYPE(enc, ptr)) - { - case BT_AST: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_ASTERISK; - case BT_QUEST: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_QUESTION; - case BT_PLUS: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_PLUS; - case BT_CR: - case BT_LF: - case BT_S: - case BT_GT: - case BT_COMMA: - case BT_VERBAR: - case BT_RPAR: - *nextTokPtr = ptr; - return XML_TOK_CLOSE_PAREN; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_VERBAR: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OR; - case BT_GT: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DECL_CLOSE; - case BT_NUM: - return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr); + *nextTokPtr = ptr; + return XML_TOK_CLOSE_PAREN; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + case BT_VERBAR: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OR; + case BT_GT: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DECL_CLOSE; + case BT_NUM: + return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr); #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (end - ptr < n) \ @@ -1243,232 +1106,207 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, } \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE - case BT_NMSTRT: - case BT_HEX: - tok = XML_TOK_NAME; - ptr += MINBPC(enc); - break; - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: + case BT_NMSTRT: + case BT_HEX: + tok = XML_TOK_NAME; + ptr += MINBPC(enc); + break; + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: #ifdef XML_NS - case BT_COLON: + case BT_COLON: #endif - tok = XML_TOK_NMTOKEN; - ptr += MINBPC(enc); - break; - case BT_NONASCII: - if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) - { - ptr += MINBPC(enc); - tok = XML_TOK_NAME; - break; - } - if (IS_NAME_CHAR_MINBPC(enc, ptr)) - { - ptr += MINBPC(enc); - tok = XML_TOK_NMTOKEN; - break; - } - /* fall through */ - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; + tok = XML_TOK_NMTOKEN; + ptr += MINBPC(enc); + break; + case BT_NONASCII: + if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { + ptr += MINBPC(enc); + tok = XML_TOK_NAME; + break; } - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - case BT_GT: - case BT_RPAR: - case BT_COMMA: - case BT_VERBAR: - case BT_LSQB: - case BT_PERCNT: - case BT_S: - case BT_CR: - case BT_LF: - *nextTokPtr = ptr; - return tok; + if (IS_NAME_CHAR_MINBPC(enc, ptr)) { + ptr += MINBPC(enc); + tok = XML_TOK_NMTOKEN; + break; + } + /* fall through */ + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_GT: case BT_RPAR: case BT_COMMA: + case BT_VERBAR: case BT_LSQB: case BT_PERCNT: + case BT_S: case BT_CR: case BT_LF: + *nextTokPtr = ptr; + return tok; #ifdef XML_NS - case BT_COLON: - ptr += MINBPC(enc); - switch (tok) - { - case XML_TOK_NAME: - if (ptr == end) - return XML_TOK_PARTIAL; - tok = XML_TOK_PREFIXED_NAME; - switch (BYTE_TYPE(enc, ptr)) - { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - default: - tok = XML_TOK_NMTOKEN; - break; - } - break; - case XML_TOK_PREFIXED_NAME: - tok = XML_TOK_NMTOKEN; - break; - } - break; -#endif - case BT_PLUS: - if (tok == XML_TOK_NMTOKEN) - { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_PLUS; - case BT_AST: - if (tok == XML_TOK_NMTOKEN) - { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_ASTERISK; - case BT_QUEST: - if (tok == XML_TOK_NMTOKEN) - { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_QUESTION; + case BT_COLON: + ptr += MINBPC(enc); + switch (tok) { + case XML_TOK_NAME: + if (ptr == end) + return XML_TOK_PARTIAL; + tok = XML_TOK_PREFIXED_NAME; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; + tok = XML_TOK_NMTOKEN; + break; } + break; + case XML_TOK_PREFIXED_NAME: + tok = XML_TOK_NMTOKEN; + break; + } + break; +#endif + case BT_PLUS: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_PLUS; + case BT_AST: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_ASTERISK; + case BT_QUEST: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_QUESTION; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; } - return -tok; + } + return -tok; } static int PTRCALL PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - const char *start; - if (ptr == end) - return XML_TOK_NONE; - start = ptr; - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { + const char *start; + if (ptr == end) + return XML_TOK_NONE; + start = ptr; + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE - case BT_AMP: - if (ptr == start) - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_LT: - /* this is for inside entity references */ - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_LF: - if (ptr == start) - { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_CR: - if (ptr == start) - { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_S: - if (ptr == start) - { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_ATTRIBUTE_VALUE_S; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } + case BT_AMP: + if (ptr == start) + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_LT: + /* this is for inside entity references */ + *nextTokPtr = ptr; + return XML_TOK_INVALID; + case BT_LF: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_CR: + if (ptr == start) { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_S: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_ATTRIBUTE_VALUE_S; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; } static int PTRCALL PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - const char *start; - if (ptr == end) - return XML_TOK_NONE; - start = ptr; - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_AMP: - if (ptr == start) - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_PERCNT: - if (ptr == start) - { - int tok = PREFIX(scanPercent)(enc, ptr + MINBPC(enc), - end, nextTokPtr); - return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_LF: - if (ptr == start) - { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_CR: - if (ptr == start) - { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } + const char *start; + if (ptr == end) + return XML_TOK_NONE; + start = ptr; + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: ptr += n; break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_AMP: + if (ptr == start) + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_PERCNT: + if (ptr == start) { + int tok = PREFIX(scanPercent)(enc, ptr + MINBPC(enc), + end, nextTokPtr); + return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_LF: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_CR: + if (ptr == start) { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; } #ifdef XML_DTD @@ -1477,60 +1315,51 @@ static int PTRCALL PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - int level = 0; - if (MINBPC(enc) > 1) - { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) - { - n &= ~(MINBPC(enc) - 1); - end = ptr + n; - } + int level = 0; + if (MINBPC(enc) > 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + end = ptr + n; } - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { - INVALID_CASES(ptr, nextTokPtr) - case BT_LT: - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) - { - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) - { - ++level; - ptr += MINBPC(enc); - } - } - break; - case BT_RSQB: - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) - { - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, ASCII_GT)) - { - ptr += MINBPC(enc); - if (level == 0) - { - *nextTokPtr = ptr; - return XML_TOK_IGNORE_SECT; - } - --level; - } - } - break; - default: - ptr += MINBPC(enc); - break; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + INVALID_CASES(ptr, nextTokPtr) + case BT_LT: + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) { + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) { + ++level; + ptr += MINBPC(enc); + } + } + break; + case BT_RSQB: + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr += MINBPC(enc); + if (level == 0) { + *nextTokPtr = ptr; + return XML_TOK_IGNORE_SECT; + } + --level; } + } + break; + default: + ptr += MINBPC(enc); + break; } - return XML_TOK_PARTIAL; + } + return XML_TOK_PARTIAL; } #endif /* XML_DTD */ @@ -1539,59 +1368,55 @@ static int PTRCALL PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end, const char **badPtr) { - ptr += MINBPC(enc); - end -= MINBPC(enc); - for (; ptr != end; ptr += MINBPC(enc)) - { - switch (BYTE_TYPE(enc, ptr)) - { - case BT_DIGIT: - case BT_HEX: - case BT_MINUS: - case BT_APOS: - case BT_LPAR: - case BT_RPAR: - case BT_PLUS: - case BT_COMMA: - case BT_SOL: - case BT_EQUALS: - case BT_QUEST: - case BT_CR: - case BT_LF: - case BT_SEMI: - case BT_EXCL: - case BT_AST: - case BT_PERCNT: - case BT_NUM: + ptr += MINBPC(enc); + end -= MINBPC(enc); + for (; ptr != end; ptr += MINBPC(enc)) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_DIGIT: + case BT_HEX: + case BT_MINUS: + case BT_APOS: + case BT_LPAR: + case BT_RPAR: + case BT_PLUS: + case BT_COMMA: + case BT_SOL: + case BT_EQUALS: + case BT_QUEST: + case BT_CR: + case BT_LF: + case BT_SEMI: + case BT_EXCL: + case BT_AST: + case BT_PERCNT: + case BT_NUM: #ifdef XML_NS - case BT_COLON: + case BT_COLON: #endif - break; - case BT_S: - if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) - { - *badPtr = ptr; - return 0; - } - break; - case BT_NAME: - case BT_NMSTRT: - if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f)) - break; - default: - switch (BYTE_TO_ASCII(enc, ptr)) - { - case 0x24: /* $ */ - case 0x40: /* @ */ - break; - default: - *badPtr = ptr; - return 0; - } - break; - } + break; + case BT_S: + if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) { + *badPtr = ptr; + return 0; + } + break; + case BT_NAME: + case BT_NMSTRT: + if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f)) + break; + default: + switch (BYTE_TO_ASCII(enc, ptr)) { + case 0x24: /* $ */ + case 0x40: /* @ */ + break; + default: + *badPtr = ptr; + return 0; + } + break; } - return 1; + } + return 1; } /* This must only be called for a well-formed start-tag or empty @@ -1603,15 +1428,13 @@ static int PTRCALL PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax, ATTRIBUTE *atts) { - enum { other, inName, inValue } state = inName; - int nAtts = 0; - int open = 0; /* defined when state == inValue; + enum { other, inName, inValue } state = inName; + int nAtts = 0; + int open = 0; /* defined when state == inValue; initialization just to shut up compilers */ - for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) - { - switch (BYTE_TYPE(enc, ptr)) - { + for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) { + switch (BYTE_TYPE(enc, ptr)) { #define START_NAME \ if (state == other) { \ if (nAtts < attsMax) { \ @@ -1622,341 +1445,294 @@ PREFIX(getAtts)(const ENCODING *enc, const char *ptr, } #define LEAD_CASE(n) \ case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE - case BT_NONASCII: - case BT_NMSTRT: - case BT_HEX: - START_NAME - break; + case BT_NONASCII: + case BT_NMSTRT: + case BT_HEX: + START_NAME + break; #undef START_NAME - case BT_QUOT: - if (state != inValue) - { - if (nAtts < attsMax) - atts[nAtts].valuePtr = ptr + MINBPC(enc); - state = inValue; - open = BT_QUOT; - } - else if (open == BT_QUOT) - { - state = other; - if (nAtts < attsMax) - atts[nAtts].valueEnd = ptr; - nAtts++; - } - break; - case BT_APOS: - if (state != inValue) - { - if (nAtts < attsMax) - atts[nAtts].valuePtr = ptr + MINBPC(enc); - state = inValue; - open = BT_APOS; - } - else if (open == BT_APOS) - { - state = other; - if (nAtts < attsMax) - atts[nAtts].valueEnd = ptr; - nAtts++; - } - break; - case BT_AMP: - if (nAtts < attsMax) - atts[nAtts].normalized = 0; - break; - case BT_S: - if (state == inName) - state = other; - else if (state == inValue - && nAtts < attsMax - && atts[nAtts].normalized - && (ptr == atts[nAtts].valuePtr - || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE - || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE - || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open)) - atts[nAtts].normalized = 0; - break; - case BT_CR: - case BT_LF: - /* This case ensures that the first attribute name is counted - Apart from that we could just change state on the quote. */ - if (state == inName) - state = other; - else if (state == inValue && nAtts < attsMax) - atts[nAtts].normalized = 0; - break; - case BT_GT: - case BT_SOL: - if (state != inValue) - return nAtts; - break; - default: - break; - } + case BT_QUOT: + if (state != inValue) { + if (nAtts < attsMax) + atts[nAtts].valuePtr = ptr + MINBPC(enc); + state = inValue; + open = BT_QUOT; + } + else if (open == BT_QUOT) { + state = other; + if (nAtts < attsMax) + atts[nAtts].valueEnd = ptr; + nAtts++; + } + break; + case BT_APOS: + if (state != inValue) { + if (nAtts < attsMax) + atts[nAtts].valuePtr = ptr + MINBPC(enc); + state = inValue; + open = BT_APOS; + } + else if (open == BT_APOS) { + state = other; + if (nAtts < attsMax) + atts[nAtts].valueEnd = ptr; + nAtts++; + } + break; + case BT_AMP: + if (nAtts < attsMax) + atts[nAtts].normalized = 0; + break; + case BT_S: + if (state == inName) + state = other; + else if (state == inValue + && nAtts < attsMax + && atts[nAtts].normalized + && (ptr == atts[nAtts].valuePtr + || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE + || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE + || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open)) + atts[nAtts].normalized = 0; + break; + case BT_CR: case BT_LF: + /* This case ensures that the first attribute name is counted + Apart from that we could just change state on the quote. */ + if (state == inName) + state = other; + else if (state == inValue && nAtts < attsMax) + atts[nAtts].normalized = 0; + break; + case BT_GT: + case BT_SOL: + if (state != inValue) + return nAtts; + break; + default: + break; } - /* not reached */ + } + /* not reached */ } static int PTRFASTCALL PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) { - int result = 0; - /* skip &# */ - ptr += 2*MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, ASCII_x)) - { - for (ptr += MINBPC(enc); - !CHAR_MATCHES(enc, ptr, ASCII_SEMI); - ptr += MINBPC(enc)) - { - int c = BYTE_TO_ASCII(enc, ptr); - switch (c) - { - case ASCII_0: - case ASCII_1: - case ASCII_2: - case ASCII_3: - case ASCII_4: - case ASCII_5: - case ASCII_6: - case ASCII_7: - case ASCII_8: - case ASCII_9: - result <<= 4; - result |= (c - ASCII_0); - break; - case ASCII_A: - case ASCII_B: - case ASCII_C: - case ASCII_D: - case ASCII_E: - case ASCII_F: - result <<= 4; - result += 10 + (c - ASCII_A); - break; - case ASCII_a: - case ASCII_b: - case ASCII_c: - case ASCII_d: - case ASCII_e: - case ASCII_f: - result <<= 4; - result += 10 + (c - ASCII_a); - break; - } - if (result >= 0x110000) - return -1; - } + int result = 0; + /* skip &# */ + ptr += 2*MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_x)) { + for (ptr += MINBPC(enc); + !CHAR_MATCHES(enc, ptr, ASCII_SEMI); + ptr += MINBPC(enc)) { + int c = BYTE_TO_ASCII(enc, ptr); + switch (c) { + case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4: + case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9: + result <<= 4; + result |= (c - ASCII_0); + break; + case ASCII_A: case ASCII_B: case ASCII_C: + case ASCII_D: case ASCII_E: case ASCII_F: + result <<= 4; + result += 10 + (c - ASCII_A); + break; + case ASCII_a: case ASCII_b: case ASCII_c: + case ASCII_d: case ASCII_e: case ASCII_f: + result <<= 4; + result += 10 + (c - ASCII_a); + break; + } + if (result >= 0x110000) + return -1; } - else - { - for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) - { - int c = BYTE_TO_ASCII(enc, ptr); - result *= 10; - result += (c - ASCII_0); - if (result >= 0x110000) - return -1; - } + } + else { + for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { + int c = BYTE_TO_ASCII(enc, ptr); + result *= 10; + result += (c - ASCII_0); + if (result >= 0x110000) + return -1; } - return checkCharRefNumber(result); + } + return checkCharRefNumber(result); } static int PTRCALL PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end) { - switch ((end - ptr)/MINBPC(enc)) - { - case 2: - if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) - { - switch (BYTE_TO_ASCII(enc, ptr)) - { - case ASCII_l: - return ASCII_LT; - case ASCII_g: - return ASCII_GT; - } - } - break; - case 3: - if (CHAR_MATCHES(enc, ptr, ASCII_a)) - { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, ASCII_m)) - { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, ASCII_p)) - return ASCII_AMP; - } + switch ((end - ptr)/MINBPC(enc)) { + case 2: + if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) { + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_l: + return ASCII_LT; + case ASCII_g: + return ASCII_GT; + } + } + break; + case 3: + if (CHAR_MATCHES(enc, ptr, ASCII_a)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_m)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_p)) + return ASCII_AMP; + } + } + break; + case 4: + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_q: + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_u)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_o)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_t)) + return ASCII_QUOT; } - break; - case 4: - switch (BYTE_TO_ASCII(enc, ptr)) - { - case ASCII_q: - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, ASCII_u)) - { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, ASCII_o)) - { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, ASCII_t)) - return ASCII_QUOT; - } - } - break; - case ASCII_a: - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, ASCII_p)) - { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, ASCII_o)) - { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, ASCII_s)) - return ASCII_APOS; - } - } - break; + } + break; + case ASCII_a: + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_p)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_o)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_s)) + return ASCII_APOS; } + } + break; } - return 0; + } + return 0; } static int PTRCALL PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2) { - for (;;) - { - switch (BYTE_TYPE(enc, ptr1)) - { + for (;;) { + switch (BYTE_TYPE(enc, ptr1)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ if (*ptr1++ != *ptr2++) \ return 0; - LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2) + LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2) #undef LEAD_CASE - /* fall through */ - if (*ptr1++ != *ptr2++) - return 0; - break; - case BT_NONASCII: - case BT_NMSTRT: + /* fall through */ + if (*ptr1++ != *ptr2++) + return 0; + break; + case BT_NONASCII: + case BT_NMSTRT: #ifdef XML_NS - case BT_COLON: + case BT_COLON: #endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 1) { + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 2) { + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 3) { if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 1) - { - if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 2) - { - if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 3) - { - if (*ptr2++ != *ptr1++) - return 0; - } - } - } - break; - default: - if (MINBPC(enc) == 1 && *ptr1 == *ptr2) - return 1; - switch (BYTE_TYPE(enc, ptr2)) - { - case BT_LEAD2: - case BT_LEAD3: - case BT_LEAD4: - case BT_NONASCII: - case BT_NMSTRT: + return 0; + } + } + } + break; + default: + if (MINBPC(enc) == 1 && *ptr1 == *ptr2) + return 1; + switch (BYTE_TYPE(enc, ptr2)) { + case BT_LEAD2: + case BT_LEAD3: + case BT_LEAD4: + case BT_NONASCII: + case BT_NMSTRT: #ifdef XML_NS - case BT_COLON: + case BT_COLON: #endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - return 0; - default: - return 1; - } - } + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + return 0; + default: + return 1; + } } - /* not reached */ + } + /* not reached */ } static int PTRCALL PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, const char *end1, const char *ptr2) { - for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) - { - if (ptr1 == end1) - return 0; - if (!CHAR_MATCHES(enc, ptr1, *ptr2)) - return 0; - } - return ptr1 == end1; + for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) { + if (ptr1 == end1) + return 0; + if (!CHAR_MATCHES(enc, ptr1, *ptr2)) + return 0; + } + return ptr1 == end1; } static int PTRFASTCALL PREFIX(nameLength)(const ENCODING *enc, const char *ptr) { - const char *start = ptr; - for (;;) - { - switch (BYTE_TYPE(enc, ptr)) - { + const char *start = ptr; + for (;;) { + switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE - case BT_NONASCII: - case BT_NMSTRT: + case BT_NONASCII: + case BT_NMSTRT: #ifdef XML_NS - case BT_COLON: + case BT_COLON: #endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - ptr += MINBPC(enc); - break; - default: - return ptr - start; - } + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + ptr += MINBPC(enc); + break; + default: + return ptr - start; } + } } static const char * PTRFASTCALL PREFIX(skipS)(const ENCODING *enc, const char *ptr) { - for (;;) - { - switch (BYTE_TYPE(enc, ptr)) - { - case BT_LF: - case BT_CR: - case BT_S: - ptr += MINBPC(enc); - break; - default: - return ptr; - } + for (;;) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_LF: + case BT_CR: + case BT_S: + ptr += MINBPC(enc); + break; + default: + return ptr; } + } } static void PTRCALL @@ -1965,34 +1741,32 @@ PREFIX(updatePosition)(const ENCODING *enc, const char *end, POSITION *pos) { - while (ptr != end) - { - switch (BYTE_TYPE(enc, ptr)) - { + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { #define LEAD_CASE(n) \ case BT_LEAD ## n: \ ptr += n; \ break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) #undef LEAD_CASE - case BT_LF: - pos->columnNumber = (unsigned)-1; - pos->lineNumber++; - ptr += MINBPC(enc); - break; - case BT_CR: - pos->lineNumber++; - ptr += MINBPC(enc); - if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - pos->columnNumber = (unsigned)-1; - break; - default: - ptr += MINBPC(enc); - break; - } - pos->columnNumber++; + case BT_LF: + pos->columnNumber = (unsigned)-1; + pos->lineNumber++; + ptr += MINBPC(enc); + break; + case BT_CR: + pos->lineNumber++; + ptr += MINBPC(enc); + if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + pos->columnNumber = (unsigned)-1; + break; + default: + ptr += MINBPC(enc); + break; } + pos->columnNumber++; + } } #undef DO_LEAD_CASE diff --git a/src/simgear/xml/xmltok_impl.h b/src/simgear/xml/xmltok_impl.h old mode 100644 new mode 100755 index 5bbd0afff92212319f9182ae421d012a47ee67a6..da0ea60a657d660770878804e3962426e84d58ef --- a/src/simgear/xml/xmltok_impl.h +++ b/src/simgear/xml/xmltok_impl.h @@ -3,45 +3,44 @@ Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file COPYING for copying permission. */ -enum -{ - BT_NONXML, - BT_MALFORM, - BT_LT, - BT_AMP, - BT_RSQB, - BT_LEAD2, - BT_LEAD3, - BT_LEAD4, - BT_TRAIL, - BT_CR, - BT_LF, - BT_GT, - BT_QUOT, - BT_APOS, - BT_EQUALS, - BT_QUEST, - BT_EXCL, - BT_SOL, - BT_SEMI, - BT_NUM, - BT_LSQB, - BT_S, - BT_NMSTRT, - BT_COLON, - BT_HEX, - BT_DIGIT, - BT_NAME, - BT_MINUS, - BT_OTHER, /* known not to be a name or name start character */ - BT_NONASCII, /* might be a name or name start character */ - BT_PERCNT, - BT_LPAR, - BT_RPAR, - BT_AST, - BT_PLUS, - BT_COMMA, - BT_VERBAR +enum { + BT_NONXML, + BT_MALFORM, + BT_LT, + BT_AMP, + BT_RSQB, + BT_LEAD2, + BT_LEAD3, + BT_LEAD4, + BT_TRAIL, + BT_CR, + BT_LF, + BT_GT, + BT_QUOT, + BT_APOS, + BT_EQUALS, + BT_QUEST, + BT_EXCL, + BT_SOL, + BT_SEMI, + BT_NUM, + BT_LSQB, + BT_S, + BT_NMSTRT, + BT_COLON, + BT_HEX, + BT_DIGIT, + BT_NAME, + BT_MINUS, + BT_OTHER, /* known not to be a name or name start character */ + BT_NONASCII, /* might be a name or name start character */ + BT_PERCNT, + BT_LPAR, + BT_RPAR, + BT_AST, + BT_PLUS, + BT_COMMA, + BT_VERBAR }; #include <stddef.h> diff --git a/src/simgear/xml/xmltok_ns.c b/src/simgear/xml/xmltok_ns.c old mode 100644 new mode 100755 index 8093473765287fdaade832dcd41fd9c8e51743ca..5610eb95ba73510e861c6c5864c625a732a18100 --- a/src/simgear/xml/xmltok_ns.c +++ b/src/simgear/xml/xmltok_ns.c @@ -1,84 +1,83 @@ const ENCODING * NS(XmlGetUtf8InternalEncoding)(void) { - return &ns(internal_utf8_encoding).enc; + return &ns(internal_utf8_encoding).enc; } const ENCODING * NS(XmlGetUtf16InternalEncoding)(void) { #if BYTEORDER == 1234 - return &ns(internal_little2_encoding).enc; + return &ns(internal_little2_encoding).enc; #elif BYTEORDER == 4321 - return &ns(internal_big2_encoding).enc; + return &ns(internal_big2_encoding).enc; #else - const short n = 1; - return (*(const char *)&n - ? &ns(internal_little2_encoding).enc - : &ns(internal_big2_encoding).enc); + const short n = 1; + return (*(const char *)&n + ? &ns(internal_little2_encoding).enc + : &ns(internal_big2_encoding).enc); #endif } -static const ENCODING *NS(encodings)[] = -{ - &ns(latin1_encoding).enc, - &ns(ascii_encoding).enc, - &ns(utf8_encoding).enc, - &ns(big2_encoding).enc, - &ns(big2_encoding).enc, - &ns(little2_encoding).enc, - &ns(utf8_encoding).enc /* NO_ENC */ +static const ENCODING *NS(encodings)[] = { + &ns(latin1_encoding).enc, + &ns(ascii_encoding).enc, + &ns(utf8_encoding).enc, + &ns(big2_encoding).enc, + &ns(big2_encoding).enc, + &ns(little2_encoding).enc, + &ns(utf8_encoding).enc /* NO_ENC */ }; static int PTRCALL NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - return initScan(NS(encodings), (const INIT_ENCODING *)enc, - XML_PROLOG_STATE, ptr, end, nextTokPtr); + return initScan(NS(encodings), (const INIT_ENCODING *)enc, + XML_PROLOG_STATE, ptr, end, nextTokPtr); } static int PTRCALL NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { - return initScan(NS(encodings), (const INIT_ENCODING *)enc, - XML_CONTENT_STATE, ptr, end, nextTokPtr); + return initScan(NS(encodings), (const INIT_ENCODING *)enc, + XML_CONTENT_STATE, ptr, end, nextTokPtr); } int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name) { - int i = getEncodingIndex(name); - if (i == UNKNOWN_ENC) - return 0; - SET_INIT_ENC_INDEX(p, i); - p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); - p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); - p->initEnc.updatePosition = initUpdatePosition; - p->encPtr = encPtr; - *encPtr = &(p->initEnc); - return 1; + int i = getEncodingIndex(name); + if (i == UNKNOWN_ENC) + return 0; + SET_INIT_ENC_INDEX(p, i); + p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); + p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); + p->initEnc.updatePosition = initUpdatePosition; + p->encPtr = encPtr; + *encPtr = &(p->initEnc); + return 1; } static const ENCODING * NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) { #define ENCODING_MAX 128 - char buf[ENCODING_MAX]; - char *p = buf; - int i; - XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); - if (ptr != end) - return 0; - *p = 0; - if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) - return enc; - i = getEncodingIndex(buf); - if (i == UNKNOWN_ENC) - return 0; - return NS(encodings)[i]; + char buf[ENCODING_MAX]; + char *p = buf; + int i; + XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); + if (ptr != end) + return 0; + *p = 0; + if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) + return enc; + i = getEncodingIndex(buf); + if (i == UNKNOWN_ENC) + return 0; + return NS(encodings)[i]; } int @@ -93,15 +92,15 @@ NS(XmlParseXmlDecl)(int isGeneralTextEntity, const ENCODING **encoding, int *standalone) { - return doParseXmlDecl(NS(findEncoding), - isGeneralTextEntity, - enc, - ptr, - end, - badPtr, - versionPtr, - versionEndPtr, - encodingName, - encoding, - standalone); + return doParseXmlDecl(NS(findEncoding), + isGeneralTextEntity, + enc, + ptr, + end, + badPtr, + versionPtr, + versionEndPtr, + encodingName, + encoding, + standalone); } diff --git a/src/utilities/XMLParseTest.cpp b/src/utilities/XMLParseTest.cpp old mode 100644 new mode 100755 index 5b41727383f584587c037744e0fcdd3bd43fe528..47dfad2fe5041cb6632f0e61b558995b9b208190 --- a/src/utilities/XMLParseTest.cpp +++ b/src/utilities/XMLParseTest.cpp @@ -11,13 +11,12 @@ using namespace JSBSim; int main (int argc, char** argv) { - ifstream inputfile(argv[1]); - if (!inputfile) - { - cerr << "Could not open XML file " << argv[1] << endl << endl; - exit(-1); - } - FGXMLParse myXMLFile; - readXML (inputfile, myXMLFile); - myXMLFile.GetDocument()->Print(); + ifstream inputfile(argv[1]); + if (!inputfile) { + cerr << "Could not open XML file " << argv[1] << endl << endl; + exit(-1); + } + FGXMLParse myXMLFile; + readXML (inputfile, myXMLFile); + myXMLFile.GetDocument()->Print(); } diff --git a/src/utilities/aeromatic/Aeromatic.cpp b/src/utilities/aeromatic/Aeromatic.cpp old mode 100644 new mode 100755 index 599b3acc8a391fdb0001f6c08a5f04d67b6fe91f..b743960458b83f7b4aa61f2177521f7e0b93e518 --- a/src/utilities/aeromatic/Aeromatic.cpp +++ b/src/utilities/aeromatic/Aeromatic.cpp @@ -49,7 +49,7 @@ INCLUDES #include <iomanip> //namespace JSBSim { -//static const char *IdSrc = "$Id: Aeromatic.cpp,v 1.1.1.1 +//static const char *IdSrc = "$Id: Aeromatic.cpp,v 1.1.1.1 //static const char *IdHdr = ID_AEROMATIC; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -57,1756 +57,1155 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -Aeromatic::Aeromatic() -{ - Reset(); +Aeromatic::Aeromatic() { + Reset(); } -Aeromatic::~Aeromatic() -{ +Aeromatic::~Aeromatic() { } -string Aeromatic::PrintEngine() -{ - string filename = EngineName + ".xml"; - ofstream f; - f.open(filename.c_str(), ios::out); - f << fixed << setw(7) << setprecision(2); - f << "<?xml version=\"1.0\"?>\n"; - f << "<!--\n File: " << filename << endl; - f << " Author: Aero-Matic v " << AEROMATIC_VERSION << "\n\n"; - f << " Inputs:\n"; - f << " name: " << EngineName << endl; - switch (eType) - { - case etPiston: - f << " type: piston\n"; - break; - case etTurbine: - f << " type: turbine\n"; - break; - case etTurboprop: - f << " type: turboprop\n"; - break; - case etRocket: - f << " type: rocket\n"; - break; - } - switch (eType) - { - case etPiston: - f << " power: " << enginePower << " hp\n"; - break; - case etTurbine: - f << " thrust: " << engineThrust << " lb\n"; - break; - case etTurboprop: - f << " power: " << enginePower << " hp\n"; - break; - case etRocket: - f << " thrust: " << engineThrust << " lb\n"; - break; - } - if (augmentation) - f << " augmented? yes\n"; - else - f << " augmented? no\n"; - if (injection) - f << " injected? yes\n"; - else - f << " injected? no\n"; - f << "-->\n\n"; +string Aeromatic::PrintEngine() { + string filename = EngineName + ".xml"; + ofstream f; + f.open(filename.c_str(), ios::out); + f << fixed << setw(7) << setprecision(2); + f << "<?xml version=\"1.0\"?>\n"; + f << "<!--\n File: " << filename << endl; + f << " Author: Aero-Matic v " << AEROMATIC_VERSION << "\n\n"; + f << " Inputs:\n"; + f << " name: " << EngineName << endl; + switch(eType) { + case etPiston: f << " type: piston\n"; break; + case etTurbine: f << " type: turbine\n"; break; + case etTurboprop: f << " type: turboprop\n"; break; + case etRocket: f << " type: rocket\n"; break; + } + switch(eType) { + case etPiston: f << " power: " << enginePower << " hp\n"; break; + case etTurbine: f << " thrust: " << engineThrust << " lb\n"; break; + case etTurboprop: f << " power: " << enginePower << " hp\n"; break; + case etRocket: f << " thrust: " << engineThrust << " lb\n"; break; + } + if(augmentation) + f << " augmented? yes\n"; + else + f << " augmented? no\n"; + if(injection) + f << " injected? yes\n"; + else + f << " injected? no\n"; + f << "-->\n\n"; //************************************************ //* MakePiston * //************************************************ - switch (eType) - { - case etPiston: - { - double displacement = enginePower * 1.6; - - f << setw(7) << setprecision(2); - f << "<piston_engine name=\"" << EngineName << "\">\n"; - f << " <minmp unit=\"INHG\"> " << 6.0 << " </minmp>\n"; - f << " <maxmp unit=\"INHG\"> " << 30.0 << " </maxmp>\n"; - f << " <displacement unit=\"IN3\"> " << displacement << " </displacement>\n"; - f << " <maxhp> " << enginePower << " </maxhp>\n"; - f << " <cycles> 2.0 </cycles>\n"; - f << " <idlerpm> 700.0 </idlerpm>\n"; - f << " <maxthrottle> 1.0 </maxthrottle>\n"; - f << " <minthrottle> 0.2 </minthrottle>\n"; - f << "</piston_engine>\n"; - break; - } +switch (eType) { + case etPiston: { + double displacement = enginePower * 1.6; + + f << setw(7) << setprecision(2); + f << "<piston_engine name=\"" << EngineName << "\">\n"; + f << " <minmp unit=\"INHG\"> " << 6.0 << " </minmp>\n"; + f << " <maxmp unit=\"INHG\"> " << 30.0 << " </maxmp>\n"; + f << " <displacement unit=\"IN3\"> " << displacement << " </displacement>\n"; + f << " <maxhp> " << enginePower << " </maxhp>\n"; + f << " <cycles> 2.0 </cycles>\n"; + f << " <idlerpm> 700.0 </idlerpm>\n"; + f << " <maxthrottle> 1.0 </maxthrottle>\n"; + f << " <minthrottle> 0.2 </minthrottle>\n"; + f << "</piston_engine>\n"; + break; + } //************************************************ //* MakeTurbine * //************************************************ - case etTurbine: - { - - double maxthrust = engineThrust * 1.5; - - f << "<turbine_engine name=\"" <<EngineName<< "\">\n"; - f << " <milthrust> " <<engineThrust<< " </milthrust>\n"; - if (augmentation) f << " <maxthrust> " <<maxthrust<< " </maxthrust>\n"; - f << " <bypassratio> 0.0 </bypassratio>\n"; - f << " <tsfc> 0.8 </tsfc>\n"; - f << " <atsfc> 1.7 </atsfc>\n"; - f << " <idlen1> 30.0 </idlen1>\n"; - f << " <idlen2> 60.0 </idlen2>\n"; - f << " <maxn1> 100.0 </maxn1>\n"; - f << " <maxn2> 100.0 </maxn2>\n"; - if (augmentation) - { - f << " <augmented> 1 </augmented>\n"; - f << " <augmethod> 1 </augmethod>\n"; - } - else - { - f << " <augmented> 0 </augmented>\n"; - f << " <augmethod> 1 </augmethod>\n"; - } - if (injection) - { - f << " <injected> 1 </injected>\n"; - } - else - { - f << " <injected> 0 </injected>\n"; - } - f << endl; - - f << " <function name=\"IdleThrust\">\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; - f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; - f << " <tableData>\n"; - f << " -10000 0 10000 20000 30000 40000 50000\n"; - f << " 0.0 0.0430 0.0488 0.0528 0.0694 0.0899 0.1183 0.1467\n"; - f << " 0.2 0.0500 0.0501 0.0335 0.0544 0.0797 0.1049 0.1342\n"; - f << " 0.4 0.0040 0.0047 0.0020 0.0272 0.0595 0.0891 0.1203\n"; - f << " 0.6 0.0 0.0 0.0 0.0 0.0276 0.0718 0.1073\n"; - f << " 0.8 0.0 0.0 0.0 0.0 0.0474 0.0868 0.0900\n"; - f << " 1.0 0.0 0.0 0.0 0.0 0.0 0.0552 0.0800\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </function>\n\n"; - - f << " <function name=\"MilThrust\">\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; - f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; - f << " <tableData>\n"; - f << " -10000 0 10000 20000 30000 40000 50000\n"; - f << " 0.0 1.2600 1.0000 0.7400 0.5340 0.3720 0.2410 0.1490\n"; - f << " 0.2 1.1710 0.9340 0.6970 0.5060 0.3550 0.2310 0.1430\n"; - f << " 0.4 1.1500 0.9210 0.6920 0.5060 0.3570 0.2330 0.1450\n"; - f << " 0.6 1.1810 0.9510 0.7210 0.5320 0.3780 0.2480 0.1540\n"; - f << " 0.8 1.2580 1.0200 0.7820 0.5820 0.4170 0.2750 0.1700\n"; - f << " 1.0 1.3690 1.1200 0.8710 0.6510 0.4750 0.3150 0.1950\n"; - f << " 1.2 1.4850 1.2300 0.9750 0.7440 0.5450 0.3640 0.2250\n"; - f << " 1.4 1.5941 1.3400 1.0860 0.8450 0.6280 0.4240 0.2630\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </function>\n\n"; - - if (augmentation) - { - f << " <function name=\"AugThrust\">\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; - f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; - f << " <tableData>\n"; - f << " -10000 0 10000 20000 30000 40000 50000\n"; - f << " 0.0 1.1816 1.0000 0.8184 0.6627 0.5280 0.3756 0.2327\n"; - f << " 0.2 1.1308 0.9599 0.7890 0.6406 0.5116 0.3645 0.2258\n"; - f << " 0.4 1.1150 0.9474 0.7798 0.6340 0.5070 0.3615 0.2240\n"; - f << " 0.6 1.1284 0.9589 0.7894 0.6420 0.5134 0.3661 0.2268\n"; - f << " 0.8 1.1707 0.9942 0.8177 0.6647 0.5309 0.3784 0.2345\n"; - f << " 1.0 1.2411 1.0529 0.8648 0.7017 0.5596 0.3983 0.2467\n"; - f << " 1.2 1.3287 1.1254 0.9221 0.7462 0.5936 0.4219 0.2614\n"; - f << " 1.4 1.4365 1.2149 0.9933 0.8021 0.6360 0.4509 0.2794\n"; - f << " 1.6 1.5711 1.3260 1.0809 0.8700 0.6874 0.4860 0.3011\n"; - f << " 1.8 1.7301 1.4579 1.1857 0.9512 0.7495 0.5289 0.3277\n"; - f << " 2.0 1.8314 1.5700 1.3086 1.0474 0.8216 0.5786 0.3585\n"; - f << " 2.2 1.9700 1.6900 1.4100 1.2400 0.9100 0.6359 0.3940\n"; - f << " 2.4 2.0700 1.8000 1.5300 1.3400 1.0000 0.7200 0.4600\n"; - f << " 2.6 2.2000 1.9200 1.6400 1.4400 1.1000 0.8000 0.5200\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </function>\n\n"; - } - - if (injection) - { - f << " <function name=\"WaterFactor\">\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; - f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; - f << " <tableData>\n"; - f << " 0 50000\n"; - f << " 0.0 1.2000 1.2000\n"; - f << " 1.0 1.2000 1.2000\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </function>\n\n"; - } - - f << "</turbine_engine>\n"; - break; - } + case etTurbine: { + + double maxthrust = engineThrust * 1.5; + + f << "<turbine_engine name=\"" <<EngineName<< "\">\n"; + f << " <milthrust> " <<engineThrust<< " </milthrust>\n"; + if (augmentation) f << " <maxthrust> " <<maxthrust<< " </maxthrust>\n"; + f << " <bypassratio> 0.0 </bypassratio>\n"; + f << " <tsfc> 0.8 </tsfc>\n"; + f << " <atsfc> 1.7 </atsfc>\n"; + f << " <idlen1> 30.0 </idlen1>\n"; + f << " <idlen2> 60.0 </idlen2>\n"; + f << " <maxn1> 100.0 </maxn1>\n"; + f << " <maxn2> 100.0 </maxn2>\n"; + if (augmentation) { + f << " <augmented> 1 </augmented>\n"; + f << " <augmethod> 1 </augmethod>\n"; + } else { + f << " <augmented> 0 </augmented>\n"; + f << " <augmethod> 1 </augmethod>\n"; + } + if (injection) { + f << " <injected> 1 </injected>\n"; + } else { + f << " <injected> 0 </injected>\n"; + } + f << endl; + + f << " <function name=\"IdleThrust\">\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; + f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; + f << " <tableData>\n"; + f << " -10000 0 10000 20000 30000 40000 50000\n"; + f << " 0.0 0.0430 0.0488 0.0528 0.0694 0.0899 0.1183 0.1467\n"; + f << " 0.2 0.0500 0.0501 0.0335 0.0544 0.0797 0.1049 0.1342\n"; + f << " 0.4 0.0040 0.0047 0.0020 0.0272 0.0595 0.0891 0.1203\n"; + f << " 0.6 0.0 0.0 0.0 0.0 0.0276 0.0718 0.1073\n"; + f << " 0.8 0.0 0.0 0.0 0.0 0.0474 0.0868 0.0900\n"; + f << " 1.0 0.0 0.0 0.0 0.0 0.0 0.0552 0.0800\n"; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </function>\n\n"; + + f << " <function name=\"MilThrust\">\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; + f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; + f << " <tableData>\n"; + f << " -10000 0 10000 20000 30000 40000 50000\n"; + f << " 0.0 1.2600 1.0000 0.7400 0.5340 0.3720 0.2410 0.1490\n"; + f << " 0.2 1.1710 0.9340 0.6970 0.5060 0.3550 0.2310 0.1430\n"; + f << " 0.4 1.1500 0.9210 0.6920 0.5060 0.3570 0.2330 0.1450\n"; + f << " 0.6 1.1810 0.9510 0.7210 0.5320 0.3780 0.2480 0.1540\n"; + f << " 0.8 1.2580 1.0200 0.7820 0.5820 0.4170 0.2750 0.1700\n"; + f << " 1.0 1.3690 1.1200 0.8710 0.6510 0.4750 0.3150 0.1950\n"; + f << " 1.2 1.4850 1.2300 0.9750 0.7440 0.5450 0.3640 0.2250\n"; + f << " 1.4 1.5941 1.3400 1.0860 0.8450 0.6280 0.4240 0.2630\n"; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </function>\n\n"; + + if (augmentation) { + f << " <function name=\"AugThrust\">\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; + f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; + f << " <tableData>\n"; + f << " -10000 0 10000 20000 30000 40000 50000\n"; + f << " 0.0 1.1816 1.0000 0.8184 0.6627 0.5280 0.3756 0.2327\n"; + f << " 0.2 1.1308 0.9599 0.7890 0.6406 0.5116 0.3645 0.2258\n"; + f << " 0.4 1.1150 0.9474 0.7798 0.6340 0.5070 0.3615 0.2240\n"; + f << " 0.6 1.1284 0.9589 0.7894 0.6420 0.5134 0.3661 0.2268\n"; + f << " 0.8 1.1707 0.9942 0.8177 0.6647 0.5309 0.3784 0.2345\n"; + f << " 1.0 1.2411 1.0529 0.8648 0.7017 0.5596 0.3983 0.2467\n"; + f << " 1.2 1.3287 1.1254 0.9221 0.7462 0.5936 0.4219 0.2614\n"; + f << " 1.4 1.4365 1.2149 0.9933 0.8021 0.6360 0.4509 0.2794\n"; + f << " 1.6 1.5711 1.3260 1.0809 0.8700 0.6874 0.4860 0.3011\n"; + f << " 1.8 1.7301 1.4579 1.1857 0.9512 0.7495 0.5289 0.3277\n"; + f << " 2.0 1.8314 1.5700 1.3086 1.0474 0.8216 0.5786 0.3585\n"; + f << " 2.2 1.9700 1.6900 1.4100 1.2400 0.9100 0.6359 0.3940\n"; + f << " 2.4 2.0700 1.8000 1.5300 1.3400 1.0000 0.7200 0.4600\n"; + f << " 2.6 2.2000 1.9200 1.6400 1.4400 1.1000 0.8000 0.5200\n"; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </function>\n\n"; + } + + if (injection) { + f << " <function name=\"WaterFactor\">\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; + f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; + f << " <tableData>\n"; + f << " 0 50000\n"; + f << " 0.0 1.2000 1.2000\n"; + f << " 1.0 1.2000 1.2000\n"; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </function>\n\n"; + } + + f << "</turbine_engine>\n"; + break; + } //************************************************ //* MakeTurboprop * //************************************************ - case etTurboprop: - { - - - // estimate thrust from power - engineThrust = 2.24 * enginePower; - - f << "<turbine_engine name=\"" <<EngineName<< "\">\n"; - f << " <milthrust> " << engineThrust << " </milthrust>\n"; - f << " <bypassratio> 0.0 </bypassratio>\n"; - f << " <tsfc> 0.55 </tsfc>\n"; - f << " <idlen2> 60.0 </idlen2>\n"; - f << " <maxn2> 100.0 </maxn2>\n"; - f << " <augmented> 0 </augmented>\n"; - f << " <injected> 0 </injected>\n\n"; - - f << " <function name=\"IdleThrust\">\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; - f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; - f << " <tableData>\n"; - f << " -10000 0 10000 20000 30000 40000 50000\n"; - f << " 0.0 0.0430 0.0488 0.0528 0.0694 0.0899 0.1183 0.1467\n"; - f << " 0.2 0.0500 0.0501 0.0335 0.0544 0.0797 0.1049 0.1342\n"; - f << " 0.4 0.0040 0.0047 0.0020 0.0272 0.0595 0.0891 0.1203\n"; - f << " 0.6 0.0 0.0 0.0 0.0276 0.0718 0.0430 0.0\n"; - f << " 0.8 0.0 0.0 0.0 0.0 0.0174 0.0086 0.0\n"; - f << " 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </function>\n\n"; - - f << " <function name=\"MilThrust\">\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; - f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; - f << " <tableData>\n"; - f << " -10000 0 10000 20000 30000 40000 50000\n"; - f << " 0.0 1.1260 1.0000 0.7400 0.5340 0.3720 0.2410 0.1490\n"; - f << " 0.2 1.1000 0.9340 0.6970 0.5060 0.3550 0.2310 0.1430\n"; - f << " 0.4 1.0000 0.6410 0.6120 0.4060 0.3570 0.2330 0.1450\n"; - f << " 0.6 0.4430 0.3510 0.2710 0.2020 0.1780 0.1020 0.0640\n"; - f << " 0.8 0.0240 0.0200 0.0160 0.0130 0.0110 0.0100 0.0\n"; - f << " 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </function>\n\n"; - - f << "</turbine_engine>\n"; - break; - } + case etTurboprop: { + + + // estimate thrust from power + engineThrust = 2.24 * enginePower; + + f << "<turbine_engine name=\"" <<EngineName<< "\">\n"; + f << " <milthrust> " << engineThrust << " </milthrust>\n"; + f << " <bypassratio> 0.0 </bypassratio>\n"; + f << " <tsfc> 0.55 </tsfc>\n"; + f << " <idlen2> 60.0 </idlen2>\n"; + f << " <maxn2> 100.0 </maxn2>\n"; + f << " <augmented> 0 </augmented>\n"; + f << " <injected> 0 </injected>\n\n"; + + f << " <function name=\"IdleThrust\">\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; + f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; + f << " <tableData>\n"; + f << " -10000 0 10000 20000 30000 40000 50000\n"; + f << " 0.0 0.0430 0.0488 0.0528 0.0694 0.0899 0.1183 0.1467\n"; + f << " 0.2 0.0500 0.0501 0.0335 0.0544 0.0797 0.1049 0.1342\n"; + f << " 0.4 0.0040 0.0047 0.0020 0.0272 0.0595 0.0891 0.1203\n"; + f << " 0.6 0.0 0.0 0.0 0.0276 0.0718 0.0430 0.0\n"; + f << " 0.8 0.0 0.0 0.0 0.0 0.0174 0.0086 0.0\n"; + f << " 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n"; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </function>\n\n"; + + f << " <function name=\"MilThrust\">\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; + f << " <independentVar lookup=\"column\">atmosphere/density-altitude</independentVar>\n"; + f << " <tableData>\n"; + f << " -10000 0 10000 20000 30000 40000 50000\n"; + f << " 0.0 1.1260 1.0000 0.7400 0.5340 0.3720 0.2410 0.1490\n"; + f << " 0.2 1.1000 0.9340 0.6970 0.5060 0.3550 0.2310 0.1430\n"; + f << " 0.4 1.0000 0.6410 0.6120 0.4060 0.3570 0.2330 0.1450\n"; + f << " 0.6 0.4430 0.3510 0.2710 0.2020 0.1780 0.1020 0.0640\n"; + f << " 0.8 0.0240 0.0200 0.0160 0.0130 0.0110 0.0100 0.0\n"; + f << " 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n"; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </function>\n\n"; + + f << "</turbine_engine>\n"; + break; + } //************************************************ //* MakeRocket * //************************************************ - case etRocket: - { - - f << "<rocket_engine name=\"" << EngineName << "\">\n"; - f << " <shr> 1.23 </shr>\n"; - f << " <max_pc> 86556.00 </max_pc>\n"; - f << " <variance> 0.10 </variance>\n"; - f << " <prop_eff> 0.67 </prop_eff>\n"; - f << " <maxthrottle> 1.00 </maxthrottle>\n"; - f << " <minthrottle> 0.40 </minthrottle>\n"; - f << " <slfuelflowmax> 91.50 </slfuelflowmax>\n"; - f << " <sloxiflowmax> 105.20 </sloxiflowmax>\n"; - f << "</rocket_engine>\n"; - } - }//switch - - f << flush; - f.close(); - return filename; + case etRocket: { + + f << "<rocket_engine name=\"" << EngineName << "\">\n"; + f << " <shr> 1.23 </shr>\n"; + f << " <max_pc> 86556.00 </max_pc>\n"; + f << " <variance> 0.10 </variance>\n"; + f << " <prop_eff> 0.67 </prop_eff>\n"; + f << " <maxthrottle> 1.00 </maxthrottle>\n"; + f << " <minthrottle> 0.40 </minthrottle>\n"; + f << " <slfuelflowmax> 91.50 </slfuelflowmax>\n"; + f << " <sloxiflowmax> 105.20 </sloxiflowmax>\n"; + f << "</rocket_engine>\n"; + } + }//switch + + f << flush; + f.close(); + return filename; } -string Aeromatic::PrintProp() -{ - - // find propeller rpm which gives a tip mach of 0.88 - // (static at sea level) - double maxrpm = 18763.0 / diameter; - - double gearratio = engineRPM / maxrpm; - - double maxrps = maxrpm / 60.0; - double rps2 = maxrps * maxrps; - double rps3 = rps2 * maxrps; - double d4 = diameter * diameter * diameter * diameter; - double d5 = d4 * diameter; - double rho = 0.002378; - - // static power and thrust coefficients - double cp0 = enginePower * 550.0 / rho / rps3 / d5; - double ct0 = cp0 * 0.86; - - double static_thrust = ct0 * rho * rps2 * d4; - - // estimate number of blades - int blades; - if (cp0 < 0.035) - { - blades = 2; - } - else if (cp0 >= 0.06) - { - blades = 4; - } - else - { - blades = 3; - } - - // estimate moment of inertia - double L = diameter / 2; // length each blade (feet) - double M = L * 0.09317; // mass each blade (slugs) - if (L < 1) - { - M = L * 0.003; // mass for tiny props - } - double ixx = blades * (0.33333 * M * L * L); - - //***************************************************** - // * - // Print XML file * - // * - //***************************************************** - string filename = PropName + ".xml"; - ofstream f; - f.open(filename.c_str(), ios::out); - f << fixed << setw(7) << setprecision(2); - f << "<xml version=\"1.0\"?>\n"; - f << "<!-- Generated by Aero-Matic v " <<AEROMATIC_VERSION<< "\n\n"; - f << " Inputs:\n"; - f << " horsepower: " << enginePower << endl; - if (fixedpitch) - f << " pitch: fixed\n"; - else - f << " pitch: variable\n"; - f << " max engine rpm: " << engineRPM << endl; - f << " prop diameter (ft): " << diameter << endl; - f << endl << " Outputs:\n"; - f << " max prop rpm: " << maxrpm << endl; - f << " gear ratio: " << gearratio << endl; - f << fixed << setw(7) << setprecision(4); - f << " Cp0: " << cp0 << endl; - f << " Ct0: " << ct0 << endl; - f << fixed << setw(7) << setprecision(2); - f << " static thrust (lbs): " << static_thrust << endl; - f << "-->\n\n"; - - f << "<propeller name=\"" << PropName << "\">\n"; - f << " <ixx> " << ixx << " </ixx>\n"; - f << " <diameter unit=\"IN\"> " << diameter * 12 << " </diameter>\n"; - f << " <numblades> " << blades << " </numblades>\n"; - f << " <gearratio> " << gearratio << " </gearratio>\n"; - - if (fixedpitch) - { - f << " <minpitch> 20 </minpitch>\n"; - f << " <maxpitch> 20 </maxpitch>\n"; - } - else - { - f << " <minpitch> 10 </minpitch>\n"; - f << " <maxpitch> 45 </maxpitch>\n"; - } - - if (!fixedpitch) - { - f << " <minrpm> " << maxrpm * 0.8 << " </minrpm>\n"; - f << " <maxrpm> " << maxrpm << " </maxrpm>\n"; - } - - f << endl; - f << setprecision(4); - - if (fixedpitch) - { - f << " <function name=\"C_THRUST\">\n"; - f << " <table>\n"; - f << " <independentVar>propulsion/advance-ratio</independentVar>\n"; - f << " <tableData>\n"; - f << " 0.0 " << ct0 * 1.0 << endl; - f << " 0.1 " << ct0 * 0.959 << endl; - f << " 0.2 " << ct0 * 0.917 << endl; - f << " 0.3 " << ct0 * 0.844 << endl; - f << " 0.4 " << ct0 * 0.758 << endl; - f << " 0.5 " << ct0 * 0.668 << endl; - f << " 0.6 " << ct0 * 0.540 << endl; - f << " 0.7 " << ct0 * 0.410 << endl; - f << " 0.8 " << ct0 * 0.222 << endl; - f << " 1.0 " << ct0 * -0.075 << endl; - f << " 1.2 " << ct0 * -0.394 << endl; - f << " 1.4 " << ct0 * -0.708 << endl; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </function>\n"; - } - else // variable pitch - { - f << " <function name=\"C_THRUST\">\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">propulsion/advance-ratio</independentVar>\n"; - f << " <independentVar lookup=\"column\">propulsion/blade-angle</independentVar>\n"; - f << " <tableData>\n"; - f << " 10 15 20 25 30 35 40 45\n"; - f << " 0.0 "<< ct0*1.000 << " " << ct0*1.286 << " " << ct0*1.435 << " " << ct0*1.455 << " " << ct0*1.527 << " " << ct0*1.583 << " " << ct0*1.619 << " " << ct0*1.637 << endl; - - f << " 0.1 "<< ct0*0.882 << " " << ct0*1.182 << " " << ct0*1.419 << " " << ct0*1.436 << " " << ct0*1.509 << " " << ct0*1.573 << " " << ct0*1.610 << " " << ct0*1.637 << endl; - - f << " 0.2 "<< ct0*0.727 << " " << ct0*1.054 << " " << ct0*1.363 << " " << ct0*1.419 << " " << ct0*1.491 << " " << ct0*1.555 << " " << ct0*1.601 << " " << ct0*1.628 << endl; - - f << " 0.3 "<< ct0*0.555 << " " << ct0*0.908 << " " << ct0*1.273 << " " << ct0*1.391 << " " << ct0*1.473 << " " << ct0*1.537 << " " << ct0*1.573 << " " << ct0*1.624 << endl; - - f << " 0.4 "<< ct0*0.373 << " " << ct0*0.754 << " " << ct0*1.155 << " " << ct0*1.373 << " " << ct0*1.455 << " " << ct0*1.519 << " " << ct0*1.555 << " " << ct0*1.619 << endl; - - f << " 0.5 "<< ct0*0.173 << " " << ct0*0.591 << " " << ct0*1.000 << " " << ct0*1.337 << " " << ct0*1.427 << " " << ct0*1.501 << " " << ct0*1.539 << " " << ct0*1.615 << endl; - - f << " 0.6 "<< ct0*0.000 << " " << ct0*0.422 << " " << ct0*0.836 << " " << ct0*1.218 << " " << ct0*1.399 << " " << ct0*1.465 << " " << ct0*1.524 << " " << ct0*1.609 << endl; - - f << " 0.7 "<< ct0*-0.227 << " " << ct0*0.218 << " " << ct0*0.655 << " " << ct0*1.137 << " " << ct0*1.368 << " " << ct0*1.445 << " " << ct0*1.483 << " " << ct0*1.591 << endl; - - f << " 0.8 "<< ct0*-0.373 << " " << ct0*0.028 << " " << ct0*0.463 << " " << ct0*0.908 << " " << ct0*1.296 << " " << ct0*1.427 << " " << ct0*1.455 << " " << ct0*1.568 << endl; - - f << " 0.9 "<< ct0*-0.637 << " " << ct0*-0.033 << " " << ct0*0.264 << " " << ct0*0.727 << " " << ct0*1.173 << " " << ct0*1.391 << " " << ct0*1.437 << " " << ct0*1.563 << endl; - - f << " 1.0 "<< ct0*-0.808 << " " << ct0*-0.363 << " " << ct0*0.064 << " " << ct0*0.545 << " " << ct0*1.000 << " " << ct0*1.337 << " " << ct0*1.401 << " " << ct0*1.545 << endl; - - f << " 1.6 "<< ct0*-1.997 << " " << ct0*-1.545 << " " << ct0*-1.178 << " " << ct0*-0.545 << " " << ct0*-0.092 << " " << ct0*0.399 << " " << ct0*0.890 << " " << ct0*1.381 << endl; - - f << " 2.0 "<< ct0*-2.728 << " " << ct0*-2.438 << " " << ct0*-2.095 << " " << ct0*-1.319 << " " << ct0*-0.864 << " " << ct0*-0.273 << " " << ct0*0.273 << " " << ct0*0.908 << endl; - - f << " 3.0 "<< ct0*-3.764 << " " << ct0*-3.437 << " " << ct0*-3.093 << " " << ct0*-2.307 << " " << ct0*-1.866 << " " << ct0*-1.272 << " " << ct0*-0.709 << " " << ct0*-0.098 << endl; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </function>\n"; - } - - f << endl; - if (fixedpitch) - { - f << " <function name=\"C_POWER\">\n"; - f << " <table>\n"; - f << " <independentVar>propulsion/advance-ratio</independentVar>\n"; - f << " <tableData>\n"; - f << " 0.0 " << cp0 * 1.0 << endl; - f << " 0.1 " << cp0 * 0.990 << endl; - f << " 0.2 " << cp0 * 0.976 << endl; - f << " 0.3 " << cp0 * 0.953 << endl; - f << " 0.4 " << cp0 * 0.898 << endl; - f << " 0.5 " << cp0 * 0.823 << endl; - f << " 0.6 " << cp0 * 0.755 << endl; - f << " 0.7 " << cp0 * 0.634 << endl; - f << " 0.8 " << cp0 * 0.518 << endl; - f << " 1.0 " << cp0 * 0.185 << endl; - f << " 1.2 " << cp0 * -0.296 << endl; - f << " 1.4 " << cp0 * -0.890 << endl; - f << " 1.6 " << cp0 * -1.511 << endl; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </function>\n"; - } - else // variable pitch - { - f << " <function name=\"C_POWER\">\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">propulsion/advance-ratio</independentVar>\n"; - f << " <independentVar lookup=\"column\">propulsion/blade-angle</independentVar>\n"; - f << " <tableData>\n"; - f << " 10 45\n"; - f << " 0.0 " << cp0 * 1.0 << " " << cp0 * 3.0 << endl; - f << " 0.1 " << cp0 * 1.0 << " " << cp0 * 3.0 << endl; - f << " 0.2 " << cp0 * 0.953 << " " << cp0 * 2.859 << endl; - f << " 0.3 " << cp0 * 0.906 << " " << cp0 * 2.718 << endl; - f << " 0.4 " << cp0 * 0.797 << " " << cp0 * 2.391 << endl; - f << " 0.5 " << cp0 * 0.656 << " " << cp0 * 1.968 << endl; - f << " 0.6 " << cp0 * 0.531 << " " << cp0 * 1.593 << endl; - f << " 0.7 " << cp0 * 0.313 << " " << cp0 * 0.939 << endl; - f << " 0.8 " << cp0 * 0.125 << " " << cp0 * 0.375 << endl; - f << " 1.0 " << cp0 * -0.375 << " " << cp0 * 0.144 << endl; - f << " 1.2 " << cp0 * -1.093 << " " << cp0 * 0.000 << endl; - f << " 1.4 " << cp0 * -2.030 << " " << cp0 * 0.250 << endl; - f << " 1.6 " << cp0 * -3.0 << " " << cp0 * -0.022 << endl; - f << " 1.8 " << cp0 * -4.0 << " " << cp0 * -0.610 << endl; - f << " 2.0 " << cp0 * -5.0 << " " << cp0 * -1.220 << endl; - f << " 2.2 " << cp0 * -6.0 << " " << cp0 * -1.830 << endl; - f << " 2.4 " << cp0 * -7.0 << " " << cp0 * -2.440 << endl; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </function>\n"; - } - - f << "\n</propeller>\n"; - f << flush; - f.close(); - return filename; +string Aeromatic::PrintProp() { + + // find propeller rpm which gives a tip mach of 0.88 + // (static at sea level) + double maxrpm = 18763.0 / diameter; + + double gearratio = engineRPM / maxrpm; + + double maxrps = maxrpm / 60.0; + double rps2 = maxrps * maxrps; + double rps3 = rps2 * maxrps; + double d4 = diameter * diameter * diameter * diameter; + double d5 = d4 * diameter; + double rho = 0.002378; + + // static power and thrust coefficients + double cp0 = enginePower * 550.0 / rho / rps3 / d5; + double ct0 = cp0 * 0.86; + + double static_thrust = ct0 * rho * rps2 * d4; + + // estimate number of blades + int blades; + if (cp0 < 0.035) { + blades = 2; + } else if (cp0 >= 0.06) { + blades = 4; + } else { + blades = 3; + } + + // estimate moment of inertia + double L = diameter / 2; // length each blade (feet) + double M = L * 0.09317; // mass each blade (slugs) + if (L < 1) { M = L * 0.003; } // mass for tiny props + double ixx = blades * (0.33333 * M * L * L); + + //***************************************************** + // * + // Print XML file * + // * + //***************************************************** + string filename = PropName + ".xml"; + ofstream f; + f.open(filename.c_str(), ios::out); + f << fixed << setw(7) << setprecision(2); + f << "<xml version=\"1.0\"?>\n"; + f << "<!-- Generated by Aero-Matic v " <<AEROMATIC_VERSION<< "\n\n"; + f << " Inputs:\n"; + f << " horsepower: " << enginePower << endl; + if (fixedpitch) + f << " pitch: fixed\n"; + else + f << " pitch: variable\n"; + f << " max engine rpm: " << engineRPM << endl; + f << " prop diameter (ft): " << diameter << endl; + f << endl << " Outputs:\n"; + f << " max prop rpm: " << maxrpm << endl; + f << " gear ratio: " << gearratio << endl; + f << fixed << setw(7) << setprecision(4); + f << " Cp0: " << cp0 << endl; + f << " Ct0: " << ct0 << endl; + f << fixed << setw(7) << setprecision(2); + f << " static thrust (lbs): " << static_thrust << endl; + f << "-->\n\n"; + + f << "<propeller name=\"" << PropName << "\">\n"; + f << " <ixx> " << ixx << " </ixx>\n"; + f << " <diameter unit=\"IN\"> " << diameter * 12 << " </diameter>\n"; + f << " <numblades> " << blades << " </numblades>\n"; + f << " <gearratio> " << gearratio << " </gearratio>\n"; + + if (fixedpitch) { + f << " <minpitch> 20 </minpitch>\n"; + f << " <maxpitch> 20 </maxpitch>\n"; + } else { + f << " <minpitch> 10 </minpitch>\n"; + f << " <maxpitch> 45 </maxpitch>\n"; + } + + if (!fixedpitch) { + f << " <minrpm> " << maxrpm * 0.8 << " </minrpm>\n"; + f << " <maxrpm> " << maxrpm << " </maxrpm>\n"; + } + + f << endl; + f << setprecision(4); + + if (fixedpitch) { + f << " <function name=\"C_THRUST\">\n"; + f << " <table>\n"; + f << " <independentVar>propulsion/advance-ratio</independentVar>\n"; + f << " <tableData>\n"; + f << " 0.0 " << ct0 * 1.0 << endl; + f << " 0.1 " << ct0 * 0.959 << endl; + f << " 0.2 " << ct0 * 0.917 << endl; + f << " 0.3 " << ct0 * 0.844 << endl; + f << " 0.4 " << ct0 * 0.758 << endl; + f << " 0.5 " << ct0 * 0.668 << endl; + f << " 0.6 " << ct0 * 0.540 << endl; + f << " 0.7 " << ct0 * 0.410 << endl; + f << " 0.8 " << ct0 * 0.222 << endl; + f << " 1.0 " << ct0 * -0.075 << endl; + f << " 1.2 " << ct0 * -0.394 << endl; + f << " 1.4 " << ct0 * -0.708 << endl; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </function>\n"; + } else { // variable pitch + f << " <function name=\"C_THRUST\">\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">propulsion/advance-ratio</independentVar>\n"; + f << " <independentVar lookup=\"column\">propulsion/blade-angle</independentVar>\n"; + f << " <tableData>\n"; + f << " 10 15 20 25 30 35 40 45\n"; + f << " 0.0 "<< ct0*1.000 << " " << ct0*1.286 << " " << ct0*1.435 << " " << ct0*1.455 << " " << ct0*1.527 << " " << ct0*1.583 << " " << ct0*1.619 << " " << ct0*1.637 << endl; + + f << " 0.1 "<< ct0*0.882 << " " << ct0*1.182 << " " << ct0*1.419 << " " << ct0*1.436 << " " << ct0*1.509 << " " << ct0*1.573 << " " << ct0*1.610 << " " << ct0*1.637 << endl; + + f << " 0.2 "<< ct0*0.727 << " " << ct0*1.054 << " " << ct0*1.363 << " " << ct0*1.419 << " " << ct0*1.491 << " " << ct0*1.555 << " " << ct0*1.601 << " " << ct0*1.628 << endl; + + f << " 0.3 "<< ct0*0.555 << " " << ct0*0.908 << " " << ct0*1.273 << " " << ct0*1.391 << " " << ct0*1.473 << " " << ct0*1.537 << " " << ct0*1.573 << " " << ct0*1.624 << endl; + + f << " 0.4 "<< ct0*0.373 << " " << ct0*0.754 << " " << ct0*1.155 << " " << ct0*1.373 << " " << ct0*1.455 << " " << ct0*1.519 << " " << ct0*1.555 << " " << ct0*1.619 << endl; + + f << " 0.5 "<< ct0*0.173 << " " << ct0*0.591 << " " << ct0*1.000 << " " << ct0*1.337 << " " << ct0*1.427 << " " << ct0*1.501 << " " << ct0*1.539 << " " << ct0*1.615 << endl; + + f << " 0.6 "<< ct0*0.000 << " " << ct0*0.422 << " " << ct0*0.836 << " " << ct0*1.218 << " " << ct0*1.399 << " " << ct0*1.465 << " " << ct0*1.524 << " " << ct0*1.609 << endl; + + f << " 0.7 "<< ct0*-0.227 << " " << ct0*0.218 << " " << ct0*0.655 << " " << ct0*1.137 << " " << ct0*1.368 << " " << ct0*1.445 << " " << ct0*1.483 << " " << ct0*1.591 << endl; + + f << " 0.8 "<< ct0*-0.373 << " " << ct0*0.028 << " " << ct0*0.463 << " " << ct0*0.908 << " " << ct0*1.296 << " " << ct0*1.427 << " " << ct0*1.455 << " " << ct0*1.568 << endl; + + f << " 0.9 "<< ct0*-0.637 << " " << ct0*-0.033 << " " << ct0*0.264 << " " << ct0*0.727 << " " << ct0*1.173 << " " << ct0*1.391 << " " << ct0*1.437 << " " << ct0*1.563 << endl; + + f << " 1.0 "<< ct0*-0.808 << " " << ct0*-0.363 << " " << ct0*0.064 << " " << ct0*0.545 << " " << ct0*1.000 << " " << ct0*1.337 << " " << ct0*1.401 << " " << ct0*1.545 << endl; + + f << " 1.6 "<< ct0*-1.997 << " " << ct0*-1.545 << " " << ct0*-1.178 << " " << ct0*-0.545 << " " << ct0*-0.092 << " " << ct0*0.399 << " " << ct0*0.890 << " " << ct0*1.381 << endl; + + f << " 2.0 "<< ct0*-2.728 << " " << ct0*-2.438 << " " << ct0*-2.095 << " " << ct0*-1.319 << " " << ct0*-0.864 << " " << ct0*-0.273 << " " << ct0*0.273 << " " << ct0*0.908 << endl; + + f << " 3.0 "<< ct0*-3.764 << " " << ct0*-3.437 << " " << ct0*-3.093 << " " << ct0*-2.307 << " " << ct0*-1.866 << " " << ct0*-1.272 << " " << ct0*-0.709 << " " << ct0*-0.098 << endl; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </function>\n"; + } + + f << endl; + if (fixedpitch) { + f << " <function name=\"C_POWER\">\n"; + f << " <table>\n"; + f << " <independentVar>propulsion/advance-ratio</independentVar>\n"; + f << " <tableData>\n"; + f << " 0.0 " << cp0 * 1.0 << endl; + f << " 0.1 " << cp0 * 0.990 << endl; + f << " 0.2 " << cp0 * 0.976 << endl; + f << " 0.3 " << cp0 * 0.953 << endl; + f << " 0.4 " << cp0 * 0.898 << endl; + f << " 0.5 " << cp0 * 0.823 << endl; + f << " 0.6 " << cp0 * 0.755 << endl; + f << " 0.7 " << cp0 * 0.634 << endl; + f << " 0.8 " << cp0 * 0.518 << endl; + f << " 1.0 " << cp0 * 0.185 << endl; + f << " 1.2 " << cp0 * -0.296 << endl; + f << " 1.4 " << cp0 * -0.890 << endl; + f << " 1.6 " << cp0 * -1.511 << endl; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </function>\n"; + } else { // variable pitch + f << " <function name=\"C_POWER\">\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">propulsion/advance-ratio</independentVar>\n"; + f << " <independentVar lookup=\"column\">propulsion/blade-angle</independentVar>\n"; + f << " <tableData>\n"; + f << " 10 45\n"; + f << " 0.0 " << cp0 * 1.0 << " " << cp0 * 3.0 << endl; + f << " 0.1 " << cp0 * 1.0 << " " << cp0 * 3.0 << endl; + f << " 0.2 " << cp0 * 0.953 << " " << cp0 * 2.859 << endl; + f << " 0.3 " << cp0 * 0.906 << " " << cp0 * 2.718 << endl; + f << " 0.4 " << cp0 * 0.797 << " " << cp0 * 2.391 << endl; + f << " 0.5 " << cp0 * 0.656 << " " << cp0 * 1.968 << endl; + f << " 0.6 " << cp0 * 0.531 << " " << cp0 * 1.593 << endl; + f << " 0.7 " << cp0 * 0.313 << " " << cp0 * 0.939 << endl; + f << " 0.8 " << cp0 * 0.125 << " " << cp0 * 0.375 << endl; + f << " 1.0 " << cp0 * -0.375 << " " << cp0 * 0.144 << endl; + f << " 1.2 " << cp0 * -1.093 << " " << cp0 * 0.000 << endl; + f << " 1.4 " << cp0 * -2.030 << " " << cp0 * 0.250 << endl; + f << " 1.6 " << cp0 * -3.0 << " " << cp0 * -0.022 << endl; + f << " 1.8 " << cp0 * -4.0 << " " << cp0 * -0.610 << endl; + f << " 2.0 " << cp0 * -5.0 << " " << cp0 * -1.220 << endl; + f << " 2.2 " << cp0 * -6.0 << " " << cp0 * -1.830 << endl; + f << " 2.4 " << cp0 * -7.0 << " " << cp0 * -2.440 << endl; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </function>\n"; + } + + f << "\n</propeller>\n"; + f << flush; + f.close(); + return filename; } -string Aeromatic::PrintAero() -{ - - int i,j,k; - - // first, estimate wing loading in psf - double wingloading; - switch (aType) - { - case atGlider: - wingloading = 7.0; - break; - case atLtSingle: - wingloading = 14.0; - break; - case atLtTwin: - wingloading = 29.0; - break; - case atRacer: - wingloading = 45.0; - break; - case atSEFighter: - wingloading = 95.0; - break; - case at2EFighter: - wingloading = 100.0; - break; - case at2ETransport: - wingloading = 110.0; - break; - case at3ETransport: - wingloading = 110.0; - break; - case at4ETransport: - wingloading = 110.0; - break; - case atMEProp: - wingloading = 57.0; - break; - } - - // if no wing area given, use wing loading to estimate - bool wingarea_input = false; - if (wingarea == 0.0) - { - wingarea = MTOW / wingloading; - } - else - { - wingarea_input = true; - wingloading = MTOW / wingarea; - } - - // calculate wing chord - double wingchord = wingarea / wingspan; - - // calculate aspect ratio - double aspectratio = wingspan / wingchord; - - // calculate half-span - double halfspan = wingspan / 2.0; - - // estimate horizontal tail area - double htailarea = 0.0; - if (htailarea == 0.0) - { - switch (aType) - { - case atGlider: - htailarea = wingarea * 0.12; - break; - case atLtSingle: - htailarea = wingarea * 0.16; - break; - case atLtTwin: - htailarea = wingarea * 0.16; - break; - case atRacer: - htailarea = wingarea * 0.17; - break; - case atSEFighter: - htailarea = wingarea * 0.20; - break; - case at2EFighter: - htailarea = wingarea * 0.20; - break; - case at2ETransport: - htailarea = wingarea * 0.25; - break; - case at3ETransport: - htailarea = wingarea * 0.25; - break; - case at4ETransport: - htailarea = wingarea * 0.25; - break; - case atMEProp: - htailarea = wingarea * 0.16; - break; - } - } - - // estimate distance from CG to horizontal tail aero center - double htailarm = 0.0; - if (htailarm == 0.0) - { - switch (aType) - { - case atGlider: - htailarm = length * 0.60; - break; - case atLtSingle: - htailarm = length * 0.52; - break; - case atLtTwin: - htailarm = length * 0.50; - break; - case atRacer: - htailarm = length * 0.60; - break; - case atSEFighter: - htailarm = length * 0.40; - break; - case at2EFighter: - htailarm = length * 0.40; - break; - case at2ETransport: - htailarm = length * 0.45; - break; - case at3ETransport: - htailarm = length * 0.45; - break; - case at4ETransport: - htailarm = length * 0.45; - break; - case atMEProp: - htailarm = length * 0.50; - break; - } - } - - // estimate vertical tail area - double vtailarea = 0.0; - if (vtailarea == 0.0) - { - switch (aType) - { - case atGlider: - vtailarea = wingarea * 0.10; - break; - case atLtSingle: - vtailarea = wingarea * 0.10; - break; - case atLtTwin: - vtailarea = wingarea * 0.18; - break; - case atRacer: - vtailarea = wingarea * 0.10; - break; - case atSEFighter: - vtailarea = wingarea * 0.12; - break; - case at2EFighter: - vtailarea = wingarea * 0.18; - break; - case at2ETransport: - vtailarea = wingarea * 0.20; - break; - case at3ETransport: - vtailarea = wingarea * 0.20; - break; - case at4ETransport: - vtailarea = wingarea * 0.20; - break; - case atMEProp: - vtailarea = wingarea * 0.18; - break; - } - } - - // estimate distance from CG to vertical tail aero center - double vtailarm = 0.0; - if (vtailarm == 0.0) - { - switch (aType) - { - case atGlider: - vtailarm = length * 0.60; - break; - case atLtSingle: - vtailarm = length * 0.50; - break; - case atLtTwin: - vtailarm = length * 0.50; - break; - case atRacer: - vtailarm = length * 0.60; - break; - case atSEFighter: - vtailarm = length * 0.40; - break; - case at2EFighter: - vtailarm = length * 0.40; - break; - case at2ETransport: - vtailarm = length * 0.45; - break; - case at3ETransport: - vtailarm = length * 0.45; - break; - case at4ETransport: - vtailarm = length * 0.45; - break; - case atMEProp: - vtailarm = length * 0.50; - break; - } - } +string Aeromatic::PrintAero() { + + int i,j,k; + + // first, estimate wing loading in psf + double wingloading; + switch(aType) { + case atGlider: wingloading = 7.0; break; + case atLtSingle: wingloading = 14.0; break; + case atLtTwin: wingloading = 29.0; break; + case atRacer: wingloading = 45.0; break; + case atSEFighter: wingloading = 95.0; break; + case at2EFighter: wingloading = 100.0; break; + case at2ETransport: wingloading = 110.0; break; + case at3ETransport: wingloading = 110.0; break; + case at4ETransport: wingloading = 110.0; break; + case atMEProp: wingloading = 57.0; break; + } + + // if no wing area given, use wing loading to estimate + bool wingarea_input = false; + if (wingarea == 0.0) { + wingarea = MTOW / wingloading; + } + else { + wingarea_input = true; + wingloading = MTOW / wingarea; + } + + // calculate wing chord + double wingchord = wingarea / wingspan; + + // calculate aspect ratio + double aspectratio = wingspan / wingchord; + + // calculate half-span + double halfspan = wingspan / 2.0; + + // estimate horizontal tail area + double htailarea = 0.0; + if (htailarea == 0.0) { + switch(aType) { + case atGlider: htailarea = wingarea * 0.12; break; + case atLtSingle: htailarea = wingarea * 0.16; break; + case atLtTwin: htailarea = wingarea * 0.16; break; + case atRacer: htailarea = wingarea * 0.17; break; + case atSEFighter: htailarea = wingarea * 0.20; break; + case at2EFighter: htailarea = wingarea * 0.20; break; + case at2ETransport: htailarea = wingarea * 0.25; break; + case at3ETransport: htailarea = wingarea * 0.25; break; + case at4ETransport: htailarea = wingarea * 0.25; break; + case atMEProp: htailarea = wingarea * 0.16; break; + } + } + + // estimate distance from CG to horizontal tail aero center + double htailarm = 0.0; + if (htailarm == 0.0) { + switch(aType) { + case atGlider: htailarm = length * 0.60; break; + case atLtSingle: htailarm = length * 0.52; break; + case atLtTwin: htailarm = length * 0.50; break; + case atRacer: htailarm = length * 0.60; break; + case atSEFighter: htailarm = length * 0.40; break; + case at2EFighter: htailarm = length * 0.40; break; + case at2ETransport: htailarm = length * 0.45; break; + case at3ETransport: htailarm = length * 0.45; break; + case at4ETransport: htailarm = length * 0.45; break; + case atMEProp: htailarm = length * 0.50; break; + } + } + + // estimate vertical tail area + double vtailarea = 0.0; + if (vtailarea == 0.0) { + switch(aType) { + case atGlider: vtailarea = wingarea * 0.10; break; + case atLtSingle: vtailarea = wingarea * 0.10; break; + case atLtTwin: vtailarea = wingarea * 0.18; break; + case atRacer: vtailarea = wingarea * 0.10; break; + case atSEFighter: vtailarea = wingarea * 0.12; break; + case at2EFighter: vtailarea = wingarea * 0.18; break; + case at2ETransport: vtailarea = wingarea * 0.20; break; + case at3ETransport: vtailarea = wingarea * 0.20; break; + case at4ETransport: vtailarea = wingarea * 0.20; break; + case atMEProp: vtailarea = wingarea * 0.18; break; + } + } + + // estimate distance from CG to vertical tail aero center + double vtailarm = 0.0; + if (vtailarm == 0.0) { + switch(aType) { + case atGlider: vtailarm = length * 0.60; break; + case atLtSingle: vtailarm = length * 0.50; break; + case atLtTwin: vtailarm = length * 0.50; break; + case atRacer: vtailarm = length * 0.60; break; + case atSEFighter: vtailarm = length * 0.40; break; + case at2EFighter: vtailarm = length * 0.40; break; + case at2ETransport: vtailarm = length * 0.45; break; + case at3ETransport: vtailarm = length * 0.45; break; + case at4ETransport: vtailarm = length * 0.45; break; + case atMEProp: vtailarm = length * 0.50; break; + } + } //***** MOMENTS OF INERTIA ****************************** // use Roskam's formulae to estimate moments of inertia - double Rx, Ry, Rz; - switch (aType) // moment-of-inertia factors - { - case atGlider: - Rx = 0.34; - Ry = 0.33; - Rz = 0.47; - break; - case atLtSingle: - Rx = 0.27; - Ry = 0.36; - Rz = 0.42; - break; - case atLtTwin: - Rx = 0.27; - Ry = 0.35; - Rz = 0.45; - break; - case atRacer: - Rx = 0.27; - Ry = 0.36; - Rz = 0.42; - break; - case atSEFighter: - Rx = 0.27; - Ry = 0.35; - Rz = 0.40; - break; - case at2EFighter: - Rx = 0.29; - Ry = 0.34; - Rz = 0.41; - break; - case at2ETransport: - Rx = 0.25; - Ry = 0.38; - Rz = 0.46; - break; - case at3ETransport: - Rx = 0.25; - Ry = 0.36; - Rz = 0.47; - break; - case at4ETransport: - Rx = 0.32; - Ry = 0.34; - Rz = 0.47; - break; - case atMEProp: - Rx = 0.32; - Ry = 0.35; - Rz = 0.47; - break; - } - - double rawixx = (MTOW / 32.2)* pow((Rx * wingspan / 2.0), 2); - double rawiyy = (MTOW / 32.2)* pow((Ry * length / 2.0), 2); - double rawizz = (MTOW / 32.2)* pow((Rz * ((wingspan + length)/2.0) / 2.0), 2); - // assume 4 degree angle between longitudinal and inertial axes - // double rawixz = abs(rawizz - rawixx) * 0.06975647; - - // originally I increased the raw MOI's to make up for lack of - // joystick feel, but here I'll use the raw values - double ixx = rawixx; - double iyy = rawiyy; - double izz = rawizz; - double ixz = 0; - - - //***** EMPTY WEIGHT ********************************* - - // estimate empty weight - double emptyweight = 0.0; - if (emptyweight == 0.0) - { - switch (aType) - { - case atGlider: - emptyweight = MTOW * .84; - case atLtSingle: - emptyweight = MTOW * .62; - case atLtTwin: - emptyweight = MTOW * .61; - case atRacer: - emptyweight = MTOW * .61; - case atSEFighter: - emptyweight = MTOW * .53; - case at2EFighter: - emptyweight = MTOW * .50; - case at2ETransport: - emptyweight = MTOW * .55; - case at3ETransport: - emptyweight = MTOW * .52; - case at4ETransport: - emptyweight = MTOW * .49; - case atMEProp: - emptyweight = MTOW * .60; - } - } - - //***** CG LOCATION *********************************** - - double cglocx = (length - htailarm) * 12.0; - double cglocy = 0; - double cglocz = -(length / 40.0) * 12; - - //***** AERO REFERENCE POINT ************************** - - double aerorpx = cglocx; - double aerorpy = 0; - double aerorpz = 0; - - //***** PILOT EYEPOINT ********************************* - - // place pilot's eyepoint based on airplane type - double eyeptlocx, eyeptlocy, eyeptlocz; - switch (aType) - { - case atGlider: - { - eyeptlocx = (length * 0.19) * 12.0; - eyeptlocy = 0.0; - eyeptlocz = 9.0; - break; - } - case atLtSingle: - { - eyeptlocx = (length * 0.13) * 12.0; - eyeptlocy = -18.0; - eyeptlocz = 45.0; - break; - } - case atLtTwin: - { - eyeptlocx = (length * 0.17) * 12.0; - eyeptlocy = -18.0; - eyeptlocz = 45.0; - break; - } - case atRacer: - { - eyeptlocx = (length * 0.28) * 12.0; - eyeptlocy = 0.0; - eyeptlocz = 40.0; - break; - } - case atSEFighter: - { - eyeptlocx = (length * 0.20) * 12.0; - eyeptlocy = 0.0; - eyeptlocz = 36.0; - break; - } - case at2EFighter: - { - eyeptlocx = (length * 0.20) * 12.0; - eyeptlocy = 0.0; - eyeptlocz = 38.0; - break; - } - case at2ETransport: - { - eyeptlocx = (length * 0.07) * 12.0; - eyeptlocy = -30.0; - eyeptlocz = 70.0; - break; - } - case at3ETransport: - { - eyeptlocx = (length * 0.07) * 12.0; - eyeptlocy = -30.0; - eyeptlocz = 75.0; - break; - } - case at4ETransport: - { - eyeptlocx = (length * 0.07) * 12.0; - eyeptlocy = -32.0; - eyeptlocz = 80.0; - break; - } - case atMEProp: - { - eyeptlocx = (length * 0.08) * 12.0; - eyeptlocy = -24.0; - eyeptlocz = 65.0; - break; - } - } - - //***** LANDING GEAR ********************************* - - // set main gear longitudinal location relative to CG - double gearlocx_main; - if (tricycle) gearlocx_main = cglocx * 1.04; - else gearlocx_main = cglocx * 0.91; - - - // set main gear lateral location - double gearlocy_main; - switch (aType) - { - case atGlider: - gearlocy_main = wingspan * 0.005* 12; - break; - case atLtSingle: - gearlocy_main = wingspan * 0.09 * 12; - break; - case atLtTwin: - gearlocy_main = wingspan * 0.09 * 12; - break; - case atRacer: - gearlocy_main = wingspan * 0.15 * 12; - break; - case atSEFighter: - gearlocy_main = wingspan * 0.09 * 12; - break; - case at2EFighter: - gearlocy_main = wingspan * 0.09 * 12; - break; - case at2ETransport: - gearlocy_main = wingspan * 0.09 * 12; - break; - case at3ETransport: - gearlocy_main = wingspan * 0.09 * 12; - break; - case at4ETransport: - gearlocy_main = wingspan * 0.09 * 12; - break; - case atMEProp: - gearlocy_main = wingspan * 0.11 * 12; - break; - } - - // set main gear length (from aircraft centerline, extended) - double gearlocz_main; - if (tricycle) gearlocz_main = -(length * 0.12 * 12); - else gearlocz_main = -(length * 0.20 * 12); - - if (aType == atGlider) gearlocz_main = -(length / 10.0 * 12); - - double gearlocx_nose = length * 0.13 * 12; - double gearlocy_nose = 0.0; - double gearlocz_nose = gearlocz_main; - if (aType == atGlider) gearlocz_nose = gearlocz_main * 0.6; - - double gearlocx_tail = length * 0.91 * 12; - double gearlocy_tail = 0.0; - double gearlocz_tail = gearlocz_main * 0.30; - - double gearspring_main = MTOW * 1.0; - double gearspring_nose = MTOW * 0.3; - double gearspring_tail = MTOW * 1.0; - - double geardamp_main = MTOW * 0.2; - double geardamp_nose = MTOW * 0.1; - double geardamp_tail = MTOW * 0.8; - - double geardynamic = 0.5; - double gearstatic = 0.8; - double gearrolling = 0.02; - if (aType == atGlider) gearrolling = 0.5; - - string gearsteerable_nose = "STEERABLE"; - string gearsteerable_main = "FIXED"; - string gearsteerable_tail = "CASTERED"; - double gearmaxsteer = 5.0; - string retract; - if (retractable) retract = "RETRACT"; - else retract = "FIXED"; - - //***** PROPULSION ************************************ - - // spread engines out in reasonable locations - - double englocx[16], englocy[16], englocz[16], leftmost; - double engfeed[16], thrusterlocx[16], thrusterlocy[16], thrusterlocz[16]; - - if (elType == elFwd_Fuselage) - { - leftmost = ((double)engines * -20.0) + 20.0; - for (i=0; i<engines; i++) - { - englocx[i] = 36.0; - englocy[i] = leftmost + (i * 40.0); - englocz[i] = 0.0; - } - } - - if (elType == elMid_Fuselage) - { - leftmost = ((double)engines * -20.0) + 20.0; - for (i=0; i<engines; i++) - { - englocx[i] = cglocx; - englocy[i] = leftmost + (i * 40.0); - englocz[i] = -12.0; - } - } - - if (elType == elAft_Fuselage) - { - leftmost = (engines * -20.0) + 20.0; - for (i=0; i<engines; i++) - { - englocx[i] = (length * 12.0) - 60.0; - englocy[i] = leftmost + (i * 40.0); - englocz[i] = 0.0; - } - } - - // wing engines (odd one goes in middle) - if (elType == elWings) - { - int halfcount = (int)(engines / 2); - for (i=0; i<halfcount; i++) //left wing - { - englocx[i] = cglocx; - englocy[i] = wingspan * -2.0; // span/-2/3*12 - englocz[i] = -40.0; - } - englocx[halfcount] = cglocx; // center - englocy[halfcount] = 0.0; - englocz[halfcount] = -20; - for (k=halfcount+1; k<engines; k++) //right wing - { - englocx[k] = cglocx; - englocy[k] = wingspan * 2.0; // span/2/3*12 - englocz[k] = -40.0; - } - } - - // wing and tail engines (odd one goes in tail) - if (elType == elWings_Tail) - { - int halfcount = (int)(engines / 2); - for (i=0; i<halfcount; i++) //left wing - { - englocx[i] = cglocx; - englocy[i] = wingspan * -2.0; // span/-2/3*12 - englocz[i] = -40.0; - } - englocx[halfcount] = length - 60; // center - englocy[halfcount] = 0.0; - englocz[halfcount] = 60.0; - for (k=halfcount+1; k<engines; k++) //right wing - { - englocx[k] = cglocx; - englocy[k] = wingspan * 2.0; // span/2/3*12 - englocz[k] = -40.0; - } - } - - // wing and nose engines (odd one goes in nose) - if (elType == elWings_Nose) - { - int halfcount = (int)(engines / 2); - for (i=0; i<halfcount; i++) //left wing - { - englocx[i] = cglocx; - englocy[i] = wingspan * -2.0; //span/-2/3*12 - englocz[i] = -40.0; - } - englocx[halfcount] = 36.0; //center - englocy[halfcount] = 0.0; - englocz[halfcount] = 0.0; - for (k=halfcount+1; k<engines; k++) //right wing - { - englocx[k] = cglocx; - englocy[k] = wingspan * 2.0; //span/2/3*12 - englocz[k] = -40.0; - } - } - - // thruster goes where engine is - double engpitch = 0.0; - double engyaw = 0.0; - double thrusterpitch = 0.0; - double thrusteryaw = 0.0; - for (i=0; i<engines; i++) - { - engfeed[i] = i; - thrusterlocx[i] = englocx[i]; - thrusterlocy[i] = englocy[i]; - thrusterlocz[i] = englocz[i]; - } - - // thruster type (note: only piston engine gets a propeller) - string thrustertype; - switch (eType) - { - case etPiston: - thrustertype = "prop"; - break; - case etTurbine: - thrustertype = "direct"; - break; - case etTurboprop: - thrustertype = "direct"; - break; - case etRocket: - thrustertype = "direct"; - break; - } - - //***** FUEL TANKS ********************************** - - // an N-engined airplane will have N+1 fuel tanks - // all tanks located at CG and are half full - double tanklocx = cglocx; - double tanklocy = cglocy; - double tanklocz = cglocz; - double tankcapacity, tankcontents; - double tankradius = 0.0; - switch (aType) - { - case atGlider: - tankcapacity = 0.0; - break; - case atLtSingle: - tankcapacity = 20.0; - break; - case atLtTwin: - tankcapacity = 50.0; - break; - case atRacer: - tankcapacity = 200.0; - break; - case atSEFighter: - tankcapacity = 500.0; - break; - case at2EFighter: - tankcapacity = 700.0; - break; - case at2ETransport: - tankcapacity = MTOW/23.0/(engines + 1); - break; - case at3ETransport: - tankcapacity = MTOW/16.0/(engines + 1); - break; - case at4ETransport: - tankcapacity = MTOW/16.0/(engines + 1); - break; - case atMEProp: - tankcapacity = MTOW/18.0/(engines + 1); - break; - } - tankcontents = tankcapacity/2; - - //***** LIFT **************************************** - - // estimate slope of lift curve based on airplane type - // units: per radian - double CLalpha; - switch (aType) - { - case atGlider: - CLalpha = 5.5; - break; - case atLtSingle: - CLalpha = 5.0; - break; - case atLtTwin: - CLalpha = 4.8; - break; - case atRacer: - CLalpha = 4.5; - break; - case atSEFighter: - CLalpha = 3.5; - break; - case at2EFighter: - CLalpha = 3.6; - break; - case at2ETransport: - CLalpha = 4.4; - break; - case at3ETransport: - CLalpha = 4.4; - break; - case at4ETransport: - CLalpha = 4.4; - break; - case atMEProp: - CLalpha = 4.9; - break; - } - - // estimate CL at zero alpha - double CL0; - switch (aType) - { - case atGlider: - CL0 = 0.25; - break; - case atLtSingle: - CL0 = 0.25; - break; - case atLtTwin: - CL0 = 0.24; - break; - case atRacer: - CL0 = 0.17; - break; - case atSEFighter: - CL0 = 0.08; - break; - case at2EFighter: - CL0 = 0.08; - break; - case at2ETransport: - CL0 = 0.20; - break; - case at3ETransport: - CL0 = 0.20; - break; - case at4ETransport: - CL0 = 0.20; - break; - case atMEProp: - CL0 = 0.24; - break; - } - - // estimate stall CL (no flaps), based on airplane type - double CLmax; - switch (aType) - { - case atGlider: - CLmax = 1.40; - break; - case atLtSingle: - CLmax = 1.40; - break; - case atLtTwin: - CLmax = 1.30; - break; - case atRacer: - CLmax = 1.20; - break; - case atSEFighter: - CLmax = 1.00; - break; - case at2EFighter: - CLmax = 1.00; - break; - case at2ETransport: - CLmax = 1.20; - break; - case at3ETransport: - CLmax = 1.20; - break; - case at4ETransport: - CLmax = 1.20; - break; - case atMEProp: - CLmax = 1.40; - break; - } - - // estimate delta-CL-flaps - double dCLflaps; - switch (aType) - { - case atGlider: - dCLflaps = 0.20; - break; - case atLtSingle: - dCLflaps = 0.40; - break; - case atLtTwin: - dCLflaps = 0.40; - break; - case atRacer: - dCLflaps = 0.30; - break; - case atSEFighter: - dCLflaps = 0.35; - break; - case at2EFighter: - dCLflaps = 0.35; - break; - case at2ETransport: - dCLflaps = 1.50; - break; - case at3ETransport: - dCLflaps = 1.50; - break; - case at4ETransport: - dCLflaps = 1.50; - break; - case atMEProp: - dCLflaps = 0.60; - break; - } - - // some types have speedbrakes in wings, affecting lift - double dCLspeedbrake; - switch (aType) - { - case atGlider: - dCLspeedbrake = -0.05; - break; - case atLtSingle: - dCLspeedbrake = 0.00; - break; - case atLtTwin: - dCLspeedbrake = 0.00; - break; - case atRacer: - dCLspeedbrake = 0.00; - break; - case atSEFighter: - dCLspeedbrake = 0.00; - break; - case at2EFighter: - dCLspeedbrake = 0.00; - break; - case at2ETransport: - dCLspeedbrake = -0.10; - break; - case at3ETransport: - dCLspeedbrake = -0.09; - break; - case at4ETransport: - dCLspeedbrake = -0.08; - break; - case atMEProp: - dCLspeedbrake = 0.00; - break; - } - - // estimate lift due to elevator deflection - double CLde = 0.2; - - //***** DRAG ***************************************** - - // estimate drag at zero lift, based on airplane type - // NOT including landing gear - double CD0; - switch (aType) - { - case atGlider: - CD0 = 0.010; - break; - case atLtSingle: - CD0 = 0.024; - break; - case atLtTwin: - CD0 = 0.025; - break; - case atRacer: - CD0 = 0.020; - break; - case atSEFighter: - CD0 = 0.021; - break; - case at2EFighter: - CD0 = 0.024; - break; - case at2ETransport: - CD0 = 0.020; - break; - case at3ETransport: - CD0 = 0.019; - break; - case at4ETransport: - CD0 = 0.017; - break; - case atMEProp: - CD0 = 0.025; - break; - } - - // add gear drag if fixed gear - if (!retractable) - { - switch (aType) - { - case atGlider: - CD0 += 0.002; - break; - case atLtSingle: - CD0 += 0.004; - break; - case atLtTwin: - CD0 += 0.004; - break; - case atRacer: - CD0 += 0.004; - break; - case atSEFighter: - CD0 += 0.005; - break; - case at2EFighter: - CD0 += 0.005; - break; - case at2ETransport: - CD0 += 0.002; - break; - case at3ETransport: - CD0 += 0.002; - break; - case at4ETransport: - CD0 += 0.002; - break; - case atMEProp: - CD0 += 0.003; - break; - } - } - - // estimate induced drag coefficient K - double K; - switch (aType) - { - case atGlider: - K = 0.023; - break; - case atLtSingle: - K = 0.040; - break; - case atLtTwin: - K = 0.041; - break; - case atRacer: - K = 0.045; - break; - case atSEFighter: - K = 0.090; - break; - case at2EFighter: - K = 0.090; - break; - case at2ETransport: - K = 0.043; - break; - case at3ETransport: - K = 0.042; - break; - case at4ETransport: - K = 0.042; - break; - case atMEProp: - K = 0.039; - break; - } - - // CD flaps - double CDflaps; - switch (aType) - { - case atGlider: - CDflaps = 0.024; - break; - case atLtSingle: - CDflaps = 0.030; - break; - case atLtTwin: - CDflaps = 0.039; - break; - case atRacer: - CDflaps = 0.040; - break; - case atSEFighter: - CDflaps = 0.080; - break; - case at2EFighter: - CDflaps = 0.075; - break; - case at2ETransport: - CDflaps = 0.059; - break; - case at3ETransport: - CDflaps = 0.057; - break; - case at4ETransport: - CDflaps = 0.055; - break; - case atMEProp: - CDflaps = 0.035; - break; - } - - // estimate drag from landing gear down - double CDgear; - switch (aType) - { - case atGlider: - CDgear = 0.012; - break; - case atLtSingle: - CDgear = 0.030; - break; - case atLtTwin: - CDgear = 0.030; - break; - case atRacer: - CDgear = 0.030; - break; - case atSEFighter: - CDgear = 0.020; - break; - case at2EFighter: - CDgear = 0.020; - break; - case at2ETransport: - CDgear = 0.015; - break; - case at3ETransport: - CDgear = 0.013; - break; - case at4ETransport: - CDgear = 0.011; - break; - case atMEProp: - CDgear = 0.023; - break; - } - - double CDde = 0.04; // elevator deflection - double CDbeta = 0.2; // sideslip - double CDspeedbrake = CD0; // speedbrake - - // estimate critical mach - double Mcrit; - switch (aType) - { - case atGlider: - Mcrit = 0.70; - break; - case atLtSingle: - Mcrit = 0.70; - break; - case atLtTwin: - Mcrit = 0.72; - break; - case atRacer: - Mcrit = 0.73; - break; - case atSEFighter: - Mcrit = 0.81; - break; - case at2EFighter: - Mcrit = 0.81; - break; - case at2ETransport: - Mcrit = 0.79; - break; - case at3ETransport: - Mcrit = 0.79; - break; - case at4ETransport: - Mcrit = 0.79; - break; - case atMEProp: - Mcrit = 0.70; - break; - } - - //***** SIDE ************************************* - - // estimate side force due to sideslip (beta) - double CYbeta = -1.0; - - //***** ROLL ************************************* - - // estimate roll coefficients - double Clbeta = -0.1; // sideslip - double Clp = -0.4; // roll rate - double Clr = 0.15; // yaw rate - - // estimate aileron power - double Clda; - switch (aType) - { - case atGlider: - Clda = 0.06; - break; - case atLtSingle: - Clda = 0.17; - break; - case atLtTwin: - Clda = 0.17; - break; - case atRacer: - Clda = 0.18; - break; - case atSEFighter: - Clda = 0.11; - break; - case at2EFighter: - Clda = 0.12; - break; - case at2ETransport: - Clda = 0.10; - break; - case at3ETransport: - Clda = 0.10; - break; - case at4ETransport: - Clda = 0.10; - break; - case atMEProp: - Clda = 0.15; - break; - } - - double Cldr = 0.01; // rudder roll - - //***** PITCH ************************************ - - double Cmalpha, Cmde, Cmq, Cmadot; - - // estimate pitch coefficients - switch (aType) - { - case atGlider: - Cmalpha = -0.5; // per radian alpha - Cmde = -0.8; // elevator deflection - Cmq = -9.0; // pitch rate - Cmadot = -12.0; // alpha-dot - break; - case atLtSingle: - Cmalpha = -0.5; // per radian alpha - Cmde = -1.1; // elevator deflection - Cmq = -12.0; // pitch rate - Cmadot = -7.0; // alpha-dot - break; - case atLtTwin: - Cmalpha = -0.4; // per radian alpha - Cmde = -1.0; // elevator deflection - Cmq = -22.0; // pitch rate - Cmadot = -8.0; // alpha-dot - break; - case atRacer: - Cmalpha = -0.5; // per radian alpha - Cmde = -1.0; // elevator deflection - Cmq = -15.0; // pitch rate - Cmadot = -7.0; // alpha-dot - break; - case atSEFighter: - Cmalpha = -0.3; // per radian alpha - Cmde = -0.8; // elevator deflection - Cmq = -18.0; // pitch rate - Cmadot = -9.0; // alpha-dot - break; - case at2EFighter: - Cmalpha = -0.3; // per radian alpha - Cmde = -0.8; // elevator deflection - Cmq = -18.0; // pitch rate - Cmadot = -9.0; // alpha-dot - break; - case at2ETransport: - Cmalpha = -0.6; // per radian alpha - Cmde = -1.2; // elevator deflection - Cmq = -17.0; // pitch rate - Cmadot = -6.0; // alpha-dot - break; - case at3ETransport: - Cmalpha = -0.6; // per radian alpha - Cmde = -1.2; // elevator deflection - Cmq = -17.0; // pitch rate - Cmadot = -6.0; // alpha-dot - break; - case at4ETransport: - Cmalpha = -0.7; // per radian alpha - Cmde = -1.3; // elevator deflection - Cmq = -21.0; // pitch rate - Cmadot = -4.0; // alpha-dot - break; - case atMEProp: - Cmalpha = -0.4; // per radian alpha - Cmde = -1.0; // elevator deflection - Cmq = -22.0; // pitch rate - Cmadot = -8.0; // alpha-dot - break; - } - - //***** YAW ************************************** - - // estimate yaw coefficients - double Cnbeta = 0.12; // sideslip - double Cnr = -0.15; // yaw rate - double Cndr = -0.10; // rudder deflection - if (aType == atGlider) Cndr = -0.03; - - // estimate adverse yaw - double Cnda; - switch (aType) - { - case atGlider: - Cnda = -0.02; - break; - case atLtSingle: - Cnda = -0.01; - break; - case atLtTwin: - Cnda = -0.01; - break; - case atRacer: - Cnda = -0.003; - break; - case atSEFighter: - Cnda = 0.0; - break; - case at2EFighter: - Cnda = 0.0; - break; - case at2ETransport: - Cnda = 0.0; - break; - case at3ETransport: - Cnda = 0.0; - break; - case at4ETransport: - Cnda = 0.0; - break; - case atMEProp: - Cnda = -0.008; - break; - } + double Rx, Ry, Rz; + switch(aType) { // moment-of-inertia factors + case atGlider: Rx = 0.34; Ry = 0.33; Rz = 0.47; break; + case atLtSingle: Rx = 0.27; Ry = 0.36; Rz = 0.42; break; + case atLtTwin: Rx = 0.27; Ry = 0.35; Rz = 0.45; break; + case atRacer: Rx = 0.27; Ry = 0.36; Rz = 0.42; break; + case atSEFighter: Rx = 0.27; Ry = 0.35; Rz = 0.40; break; + case at2EFighter: Rx = 0.29; Ry = 0.34; Rz = 0.41; break; + case at2ETransport: Rx = 0.25; Ry = 0.38; Rz = 0.46; break; + case at3ETransport: Rx = 0.25; Ry = 0.36; Rz = 0.47; break; + case at4ETransport: Rx = 0.32; Ry = 0.34; Rz = 0.47; break; + case atMEProp: Rx = 0.32; Ry = 0.35; Rz = 0.47; break; + } + + double rawixx = (MTOW / 32.2)* pow((Rx * wingspan / 2.0), 2); + double rawiyy = (MTOW / 32.2)* pow((Ry * length / 2.0), 2); + double rawizz = (MTOW / 32.2)* pow((Rz * ((wingspan + length)/2.0) / 2.0), 2); + // assume 4 degree angle between longitudinal and inertial axes + // double rawixz = abs(rawizz - rawixx) * 0.06975647; + + // originally I increased the raw MOI's to make up for lack of + // joystick feel, but here I'll use the raw values + double ixx = rawixx; + double iyy = rawiyy; + double izz = rawizz; + double ixz = 0; + + + //***** EMPTY WEIGHT ********************************* + + // estimate empty weight + double emptyweight = 0.0; + if (emptyweight == 0.0) { + switch(aType) { + case atGlider: emptyweight = MTOW * .84; + case atLtSingle: emptyweight = MTOW * .62; + case atLtTwin: emptyweight = MTOW * .61; + case atRacer: emptyweight = MTOW * .61; + case atSEFighter: emptyweight = MTOW * .53; + case at2EFighter: emptyweight = MTOW * .50; + case at2ETransport: emptyweight = MTOW * .55; + case at3ETransport: emptyweight = MTOW * .52; + case at4ETransport: emptyweight = MTOW * .49; + case atMEProp: emptyweight = MTOW * .60; + } + } + + //***** CG LOCATION *********************************** + + double cglocx = (length - htailarm) * 12.0; + double cglocy = 0; + double cglocz = -(length / 40.0) * 12; + + //***** AERO REFERENCE POINT ************************** + + double aerorpx = cglocx; + double aerorpy = 0; + double aerorpz = 0; + + //***** PILOT EYEPOINT ********************************* + + // place pilot's eyepoint based on airplane type + double eyeptlocx, eyeptlocy, eyeptlocz; + switch(aType) { + case atGlider: { eyeptlocx = (length * 0.19) * 12.0; + eyeptlocy = 0.0; + eyeptlocz = 9.0; break; } + case atLtSingle: { eyeptlocx = (length * 0.13) * 12.0; + eyeptlocy = -18.0; + eyeptlocz = 45.0; break; } + case atLtTwin: { eyeptlocx = (length * 0.17) * 12.0; + eyeptlocy = -18.0; + eyeptlocz = 45.0; break; } + case atRacer: { eyeptlocx = (length * 0.28) * 12.0; + eyeptlocy = 0.0; + eyeptlocz = 40.0; break; } + case atSEFighter: { eyeptlocx = (length * 0.20) * 12.0; + eyeptlocy = 0.0; + eyeptlocz = 36.0; break; } + case at2EFighter: { eyeptlocx = (length * 0.20) * 12.0; + eyeptlocy = 0.0; + eyeptlocz = 38.0; break; } + case at2ETransport: { eyeptlocx = (length * 0.07) * 12.0; + eyeptlocy = -30.0; + eyeptlocz = 70.0; break; } + case at3ETransport: { eyeptlocx = (length * 0.07) * 12.0; + eyeptlocy = -30.0; + eyeptlocz = 75.0; break; } + case at4ETransport: { eyeptlocx = (length * 0.07) * 12.0; + eyeptlocy = -32.0; + eyeptlocz = 80.0; break; } + case atMEProp: { eyeptlocx = (length * 0.08) * 12.0; + eyeptlocy = -24.0; + eyeptlocz = 65.0; break; } + } + + //***** LANDING GEAR ********************************* + + // set main gear longitudinal location relative to CG + double gearlocx_main; + if (tricycle) gearlocx_main = cglocx * 1.04; + else gearlocx_main = cglocx * 0.91; + + + // set main gear lateral location + double gearlocy_main; + switch(aType) { + case atGlider: gearlocy_main = wingspan * 0.005* 12; break; + case atLtSingle: gearlocy_main = wingspan * 0.09 * 12; break; + case atLtTwin: gearlocy_main = wingspan * 0.09 * 12; break; + case atRacer: gearlocy_main = wingspan * 0.15 * 12; break; + case atSEFighter: gearlocy_main = wingspan * 0.09 * 12; break; + case at2EFighter: gearlocy_main = wingspan * 0.09 * 12; break; + case at2ETransport: gearlocy_main = wingspan * 0.09 * 12; break; + case at3ETransport: gearlocy_main = wingspan * 0.09 * 12; break; + case at4ETransport: gearlocy_main = wingspan * 0.09 * 12; break; + case atMEProp: gearlocy_main = wingspan * 0.11 * 12; break; + } + + // set main gear length (from aircraft centerline, extended) + double gearlocz_main; + if (tricycle) gearlocz_main = -(length * 0.12 * 12); + else gearlocz_main = -(length * 0.20 * 12); + + if (aType == atGlider) gearlocz_main = -(length / 10.0 * 12); + + double gearlocx_nose = length * 0.13 * 12; + double gearlocy_nose = 0.0; + double gearlocz_nose = gearlocz_main; + if (aType == atGlider) gearlocz_nose = gearlocz_main * 0.6; + + double gearlocx_tail = length * 0.91 * 12; + double gearlocy_tail = 0.0; + double gearlocz_tail = gearlocz_main * 0.30; + + double gearspring_main = MTOW * 1.0; + double gearspring_nose = MTOW * 0.3; + double gearspring_tail = MTOW * 1.0; + + double geardamp_main = MTOW * 0.2; + double geardamp_nose = MTOW * 0.1; + double geardamp_tail = MTOW * 0.8; + + double geardynamic = 0.5; + double gearstatic = 0.8; + double gearrolling = 0.02; + if (aType == atGlider) gearrolling = 0.5; + + string gearsteerable_nose = "STEERABLE"; + string gearsteerable_main = "FIXED"; + string gearsteerable_tail = "CASTERED"; + double gearmaxsteer = 5.0; + string retract; + if (retractable) retract = "RETRACT"; + else retract = "FIXED"; + + //***** PROPULSION ************************************ + + // spread engines out in reasonable locations + + double englocx[16], englocy[16], englocz[16], leftmost; + double engfeed[16], thrusterlocx[16], thrusterlocy[16], thrusterlocz[16]; + + if (elType == elFwd_Fuselage) { + leftmost = ((double)engines * -20.0) + 20.0; + for(i=0; i<engines; i++) { + englocx[i] = 36.0; + englocy[i] = leftmost + (i * 40.0); + englocz[i] = 0.0; + } + } + + if (elType == elMid_Fuselage) { + leftmost = ((double)engines * -20.0) + 20.0; + for(i=0; i<engines; i++) { + englocx[i] = cglocx; + englocy[i] = leftmost + (i * 40.0); + englocz[i] = -12.0; + } + } + + if (elType == elAft_Fuselage) { + leftmost = (engines * -20.0) + 20.0; + for(i=0; i<engines; i++) { + englocx[i] = (length * 12.0) - 60.0; + englocy[i] = leftmost + (i * 40.0); + englocz[i] = 0.0; + } + } + + // wing engines (odd one goes in middle) + if (elType == elWings) { + int halfcount = (int)(engines / 2); + for(i=0; i<halfcount; i++) { //left wing + englocx[i] = cglocx; + englocy[i] = wingspan * -2.0; // span/-2/3*12 + englocz[i] = -40.0; + } + englocx[halfcount] = cglocx; // center + englocy[halfcount] = 0.0; + englocz[halfcount] = -20; + for(k=halfcount+1; k<engines; k++) { //right wing + englocx[k] = cglocx; + englocy[k] = wingspan * 2.0; // span/2/3*12 + englocz[k] = -40.0; + } + } + + // wing and tail engines (odd one goes in tail) + if (elType == elWings_Tail) { + int halfcount = (int)(engines / 2); + for(i=0; i<halfcount; i++) { //left wing + englocx[i] = cglocx; + englocy[i] = wingspan * -2.0; // span/-2/3*12 + englocz[i] = -40.0; + } + englocx[halfcount] = length - 60; // center + englocy[halfcount] = 0.0; + englocz[halfcount] = 60.0; + for(k=halfcount+1; k<engines; k++) { //right wing + englocx[k] = cglocx; + englocy[k] = wingspan * 2.0; // span/2/3*12 + englocz[k] = -40.0; + } + } + + // wing and nose engines (odd one goes in nose) + if (elType == elWings_Nose) { + int halfcount = (int)(engines / 2); + for(i=0; i<halfcount; i++) { //left wing + englocx[i] = cglocx; + englocy[i] = wingspan * -2.0; //span/-2/3*12 + englocz[i] = -40.0; + } + englocx[halfcount] = 36.0; //center + englocy[halfcount] = 0.0; + englocz[halfcount] = 0.0; + for(k=halfcount+1; k<engines; k++) { //right wing + englocx[k] = cglocx; + englocy[k] = wingspan * 2.0; //span/2/3*12 + englocz[k] = -40.0; + } + } + + // thruster goes where engine is + double engpitch = 0.0; + double engyaw = 0.0; + double thrusterpitch = 0.0; + double thrusteryaw = 0.0; + for(i=0; i<engines; i++) { + engfeed[i] = i; + thrusterlocx[i] = englocx[i]; + thrusterlocy[i] = englocy[i]; + thrusterlocz[i] = englocz[i]; + } + + // thruster type (note: only piston engine gets a propeller) + string thrustertype; + switch(eType) { + case etPiston: thrustertype = "prop"; break; + case etTurbine: thrustertype = "direct"; break; + case etTurboprop: thrustertype = "direct"; break; + case etRocket: thrustertype = "direct"; break; + } + + //***** FUEL TANKS ********************************** + + // an N-engined airplane will have N+1 fuel tanks + // all tanks located at CG and are half full + double tanklocx = cglocx; + double tanklocy = cglocy; + double tanklocz = cglocz; + double tankcapacity, tankcontents; + double tankradius = 0.0; + switch(aType) { + case atGlider: tankcapacity = 0.0; break; + case atLtSingle: tankcapacity = 20.0; break; + case atLtTwin: tankcapacity = 50.0; break; + case atRacer: tankcapacity = 200.0; break; + case atSEFighter: tankcapacity = 500.0; break; + case at2EFighter: tankcapacity = 700.0; break; + case at2ETransport: tankcapacity = MTOW/23.0/(engines + 1); break; + case at3ETransport: tankcapacity = MTOW/16.0/(engines + 1); break; + case at4ETransport: tankcapacity = MTOW/16.0/(engines + 1); break; + case atMEProp: tankcapacity = MTOW/18.0/(engines + 1); break; + } + tankcontents = tankcapacity/2; + + //***** LIFT **************************************** + + // estimate slope of lift curve based on airplane type + // units: per radian + double CLalpha; + switch(aType) { + case atGlider: CLalpha = 5.5; break; + case atLtSingle: CLalpha = 5.0; break; + case atLtTwin: CLalpha = 4.8; break; + case atRacer: CLalpha = 4.5; break; + case atSEFighter: CLalpha = 3.5; break; + case at2EFighter: CLalpha = 3.6; break; + case at2ETransport: CLalpha = 4.4; break; + case at3ETransport: CLalpha = 4.4; break; + case at4ETransport: CLalpha = 4.4; break; + case atMEProp: CLalpha = 4.9; break; + } + + // estimate CL at zero alpha + double CL0; + switch(aType) { + case atGlider: CL0 = 0.25; break; + case atLtSingle: CL0 = 0.25; break; + case atLtTwin: CL0 = 0.24; break; + case atRacer: CL0 = 0.17; break; + case atSEFighter: CL0 = 0.08; break; + case at2EFighter: CL0 = 0.08; break; + case at2ETransport: CL0 = 0.20; break; + case at3ETransport: CL0 = 0.20; break; + case at4ETransport: CL0 = 0.20; break; + case atMEProp: CL0 = 0.24; break; + } + + // estimate stall CL (no flaps), based on airplane type + double CLmax; + switch(aType) { + case atGlider: CLmax = 1.40; break; + case atLtSingle: CLmax = 1.40; break; + case atLtTwin: CLmax = 1.30; break; + case atRacer: CLmax = 1.20; break; + case atSEFighter: CLmax = 1.00; break; + case at2EFighter: CLmax = 1.00; break; + case at2ETransport: CLmax = 1.20; break; + case at3ETransport: CLmax = 1.20; break; + case at4ETransport: CLmax = 1.20; break; + case atMEProp: CLmax = 1.40; break; + } + + // estimate delta-CL-flaps + double dCLflaps; + switch(aType) { + case atGlider: dCLflaps = 0.20; break; + case atLtSingle: dCLflaps = 0.40; break; + case atLtTwin: dCLflaps = 0.40; break; + case atRacer: dCLflaps = 0.30; break; + case atSEFighter: dCLflaps = 0.35; break; + case at2EFighter: dCLflaps = 0.35; break; + case at2ETransport: dCLflaps = 1.50; break; + case at3ETransport: dCLflaps = 1.50; break; + case at4ETransport: dCLflaps = 1.50; break; + case atMEProp: dCLflaps = 0.60; break; + } + + // some types have speedbrakes in wings, affecting lift + double dCLspeedbrake; + switch(aType) { + case atGlider: dCLspeedbrake = -0.05; break; + case atLtSingle: dCLspeedbrake = 0.00; break; + case atLtTwin: dCLspeedbrake = 0.00; break; + case atRacer: dCLspeedbrake = 0.00; break; + case atSEFighter: dCLspeedbrake = 0.00; break; + case at2EFighter: dCLspeedbrake = 0.00; break; + case at2ETransport: dCLspeedbrake = -0.10; break; + case at3ETransport: dCLspeedbrake = -0.09; break; + case at4ETransport: dCLspeedbrake = -0.08; break; + case atMEProp: dCLspeedbrake = 0.00; break; + } + + // estimate lift due to elevator deflection + double CLde = 0.2; + + //***** DRAG ***************************************** + + // estimate drag at zero lift, based on airplane type + // NOT including landing gear + double CD0; + switch(aType) { + case atGlider: CD0 = 0.010; break; + case atLtSingle: CD0 = 0.024; break; + case atLtTwin: CD0 = 0.025; break; + case atRacer: CD0 = 0.020; break; + case atSEFighter: CD0 = 0.021; break; + case at2EFighter: CD0 = 0.024; break; + case at2ETransport: CD0 = 0.020; break; + case at3ETransport: CD0 = 0.019; break; + case at4ETransport: CD0 = 0.017; break; + case atMEProp: CD0 = 0.025; break; + } + + // add gear drag if fixed gear + if(!retractable) { + switch(aType) { + case atGlider: CD0 += 0.002; break; + case atLtSingle: CD0 += 0.004; break; + case atLtTwin: CD0 += 0.004; break; + case atRacer: CD0 += 0.004; break; + case atSEFighter: CD0 += 0.005; break; + case at2EFighter: CD0 += 0.005; break; + case at2ETransport: CD0 += 0.002; break; + case at3ETransport: CD0 += 0.002; break; + case at4ETransport: CD0 += 0.002; break; + case atMEProp: CD0 += 0.003; break; + } + } + + // estimate induced drag coefficient K + double K; + switch(aType) { + case atGlider: K = 0.023; break; + case atLtSingle: K = 0.040; break; + case atLtTwin: K = 0.041; break; + case atRacer: K = 0.045; break; + case atSEFighter: K = 0.090; break; + case at2EFighter: K = 0.090; break; + case at2ETransport: K = 0.043; break; + case at3ETransport: K = 0.042; break; + case at4ETransport: K = 0.042; break; + case atMEProp: K = 0.039; break; + } + + // CD flaps + double CDflaps; + switch(aType) { + case atGlider: CDflaps = 0.024; break; + case atLtSingle: CDflaps = 0.030; break; + case atLtTwin: CDflaps = 0.039; break; + case atRacer: CDflaps = 0.040; break; + case atSEFighter: CDflaps = 0.080; break; + case at2EFighter: CDflaps = 0.075; break; + case at2ETransport: CDflaps = 0.059; break; + case at3ETransport: CDflaps = 0.057; break; + case at4ETransport: CDflaps = 0.055; break; + case atMEProp: CDflaps = 0.035; break; + } + + // estimate drag from landing gear down + double CDgear; + switch(aType) { + case atGlider: CDgear = 0.012; break; + case atLtSingle: CDgear = 0.030; break; + case atLtTwin: CDgear = 0.030; break; + case atRacer: CDgear = 0.030; break; + case atSEFighter: CDgear = 0.020; break; + case at2EFighter: CDgear = 0.020; break; + case at2ETransport: CDgear = 0.015; break; + case at3ETransport: CDgear = 0.013; break; + case at4ETransport: CDgear = 0.011; break; + case atMEProp: CDgear = 0.023; break; + } + + double CDde = 0.04; // elevator deflection + double CDbeta = 0.2; // sideslip + double CDspeedbrake = CD0; // speedbrake + + // estimate critical mach + double Mcrit; + switch(aType) { + case atGlider: Mcrit = 0.70; break; + case atLtSingle: Mcrit = 0.70; break; + case atLtTwin: Mcrit = 0.72; break; + case atRacer: Mcrit = 0.73; break; + case atSEFighter: Mcrit = 0.81; break; + case at2EFighter: Mcrit = 0.81; break; + case at2ETransport: Mcrit = 0.79; break; + case at3ETransport: Mcrit = 0.79; break; + case at4ETransport: Mcrit = 0.79; break; + case atMEProp: Mcrit = 0.70; break; + } + + //***** SIDE ************************************* + + // estimate side force due to sideslip (beta) + double CYbeta = -1.0; + + //***** ROLL ************************************* + + // estimate roll coefficients + double Clbeta = -0.1; // sideslip + double Clp = -0.4; // roll rate + double Clr = 0.15; // yaw rate + + // estimate aileron power + double Clda; + switch(aType) { + case atGlider: Clda = 0.06; break; + case atLtSingle: Clda = 0.17; break; + case atLtTwin: Clda = 0.17; break; + case atRacer: Clda = 0.18; break; + case atSEFighter: Clda = 0.11; break; + case at2EFighter: Clda = 0.12; break; + case at2ETransport: Clda = 0.10; break; + case at3ETransport: Clda = 0.10; break; + case at4ETransport: Clda = 0.10; break; + case atMEProp: Clda = 0.15; break; + } + + double Cldr = 0.01; // rudder roll + + //***** PITCH ************************************ + + double Cmalpha, Cmde, Cmq, Cmadot; + + // estimate pitch coefficients + switch(aType) { + case atGlider: + Cmalpha = -0.5; // per radian alpha + Cmde = -0.8; // elevator deflection + Cmq = -9.0; // pitch rate + Cmadot = -12.0; // alpha-dot + break; + case atLtSingle: + Cmalpha = -0.5; // per radian alpha + Cmde = -1.1; // elevator deflection + Cmq = -12.0; // pitch rate + Cmadot = -7.0; // alpha-dot + break; + case atLtTwin: + Cmalpha = -0.4; // per radian alpha + Cmde = -1.0; // elevator deflection + Cmq = -22.0; // pitch rate + Cmadot = -8.0; // alpha-dot + break; + case atRacer: + Cmalpha = -0.5; // per radian alpha + Cmde = -1.0; // elevator deflection + Cmq = -15.0; // pitch rate + Cmadot = -7.0; // alpha-dot + break; + case atSEFighter: + Cmalpha = -0.3; // per radian alpha + Cmde = -0.8; // elevator deflection + Cmq = -18.0; // pitch rate + Cmadot = -9.0; // alpha-dot + break; + case at2EFighter: + Cmalpha = -0.3; // per radian alpha + Cmde = -0.8; // elevator deflection + Cmq = -18.0; // pitch rate + Cmadot = -9.0; // alpha-dot + break; + case at2ETransport: + Cmalpha = -0.6; // per radian alpha + Cmde = -1.2; // elevator deflection + Cmq = -17.0; // pitch rate + Cmadot = -6.0; // alpha-dot + break; + case at3ETransport: + Cmalpha = -0.6; // per radian alpha + Cmde = -1.2; // elevator deflection + Cmq = -17.0; // pitch rate + Cmadot = -6.0; // alpha-dot + break; + case at4ETransport: + Cmalpha = -0.7; // per radian alpha + Cmde = -1.3; // elevator deflection + Cmq = -21.0; // pitch rate + Cmadot = -4.0; // alpha-dot + break; + case atMEProp: + Cmalpha = -0.4; // per radian alpha + Cmde = -1.0; // elevator deflection + Cmq = -22.0; // pitch rate + Cmadot = -8.0; // alpha-dot + break; + } + + //***** YAW ************************************** + + // estimate yaw coefficients + double Cnbeta = 0.12; // sideslip + double Cnr = -0.15; // yaw rate + double Cndr = -0.10; // rudder deflection + if(aType == atGlider) Cndr = -0.03; + + // estimate adverse yaw + double Cnda; + switch(aType) { + case atGlider: Cnda = -0.02; break; + case atLtSingle: Cnda = -0.01; break; + case atLtTwin: Cnda = -0.01; break; + case atRacer: Cnda = -0.003; break; + case atSEFighter: Cnda = 0.0; break; + case at2EFighter: Cnda = 0.0; break; + case at2ETransport: Cnda = 0.0; break; + case at3ETransport: Cnda = 0.0; break; + case at4ETransport: Cnda = 0.0; break; + case atMEProp: Cnda = -0.008; break; + } //************************************************ @@ -1815,579 +1214,509 @@ string Aeromatic::PrintAero() //* * //************************************************ - string filename = AircraftName + ".xml"; - ofstream f; - f.open(filename.c_str(), ios::out); - f << fixed << setw(7) << setprecision(2); - - f << "<?xml version=\"1.0\"?>\n"; - f << "<?xml-stylesheet href=\"JSBSim.xsl\" type=\"application/xml\"?>\n"; - f << "<fdm_config name=\"" << AircraftName << "\" version=\"2.0\" release=\"ALPHA\">\n"; - - f << " <fileheader>\n"; - f << " <author>Aeromatic v " << AEROMATIC_VERSION << "</author>\n"; - f << " <filecreationdate>now</filecreationdate>\n"; - f << " <description>Models a " << AircraftName << "</description>\n"; - f << " <reference refID=\"None\" author=\"n/a\" title=\"n/a\" date=\"n/a\" />\n"; - f << " </fileheader>\n\n"; - - f << "<!--\n File: " << filename << endl; - f << " Inputs:\n"; - f << " name: " << AircraftName << endl; - switch (aType) - { - case atGlider: - f << " type: glider\n"; - break; - case atLtSingle: - f << " type: light single\n"; - break; - case atLtTwin: - f << " type: light twin\n"; - break; - case atRacer: - f << " type: WWII fighter, subsonic sport, aerobatic\n"; - break; - case atSEFighter: - f << " type: single-engine transonic/supersonic fighter\n"; - break; - case at2EFighter: - f << " type: two-engine transonic/supersonic fighter\n"; - break; - case at2ETransport: - f << " type: two-engine transonic transport\n"; - break; - case at3ETransport: - f << " type: three-engine transonic transport\n"; - break; - case at4ETransport: - f << " type: four-engine transonic transport\n"; - break; - case atMEProp: - f << " type: multi-engine prop transport\n"; - break; - } - f << " max weight: " << MTOW << " lb\n"; - f << " wing span: " << wingspan << " ft\n"; - f << " length: " << length << " ft\n"; - - if (!wingarea_input) - f << " wing area: unspecified\n"; - else - f << " wing area: " << wingarea << " sq-ft\n"; - - if (tricycle) f << " gear type: tricycle\n"; - else f << " gear type: taildragger\n"; - - if (retractable) f << " retractable?: yes\n"; - else f << " retractable?: no\n"; - - f << " # engines: " << engines << endl; - switch (eType) - { - case etPiston: - f << " engine type: piston\n"; - break; - case etTurbine: - f << " engine type: turbine\n"; - break; - case etTurboprop: - f << " engine type: turboprop\n"; - break; - case etRocket: - f << " engine type: rocket\n"; - break; - } - - switch (elType) - { - case elFwd_Fuselage: - f << " engine layout: forward fuselage\n"; - break; - case elMid_Fuselage: - f << " engine layout: middle fuselage\n"; - break; - case elAft_Fuselage: - f << " engine layout: aft fuselage\n"; - break; - case elWings: - f << " engine layout: wings\n"; - break; - case elWings_Tail: - f << " engine layout: wings and tail\n"; - break; - case elWings_Nose: - f << " engine layout: wings and nose\n"; - break; - } - - if (yawdamper) f << " yaw damper? yes\n"; - else f << " yaw damper? no\n\n"; - - f << fixed << setw(7) << setprecision(4); - f << " Outputs:\n"; - f << " wing loading: " << wingloading << " lb/sq-ft\n"; - f << " CL-alpha: " << CLalpha << " per radian\n"; - f << " CL-0: " << CL0 << endl; - f << " CL-max: " << CLmax << endl; - f << " CD-0: " << CD0 << endl; - f << " K: " << K << endl; - f << "\n-->\n\n"; - f << fixed << setw(7) << setprecision(2); - + string filename = AircraftName + ".xml"; + ofstream f; + f.open(filename.c_str(), ios::out); + f << fixed << setw(7) << setprecision(2); + + f << "<?xml version=\"1.0\"?>\n"; + f << "<?xml-stylesheet href=\"JSBSim.xsl\" type=\"application/xml\"?>\n"; + f << "<fdm_config name=\"" << AircraftName << "\" version=\"2.0\" release=\"ALPHA\">\n"; + + f << " <fileheader>\n"; + f << " <author>Aeromatic v " << AEROMATIC_VERSION << "</author>\n"; + f << " <filecreationdate>now</filecreationdate>\n"; + f << " <description>Models a " << AircraftName << "</description>\n"; + f << " <reference refID=\"None\" author=\"n/a\" title=\"n/a\" date=\"n/a\" />\n"; + f << " </fileheader>\n\n"; + + f << "<!--\n File: " << filename << endl; + f << " Inputs:\n"; + f << " name: " << AircraftName << endl; + switch(aType) { + case atGlider: f << " type: glider\n"; break; + case atLtSingle: f << " type: light single\n"; break; + case atLtTwin: f << " type: light twin\n"; break; + case atRacer: f << " type: WWII fighter, subsonic sport, aerobatic\n"; break; + case atSEFighter: f << " type: single-engine transonic/supersonic fighter\n"; break; + case at2EFighter: f << " type: two-engine transonic/supersonic fighter\n"; break; + case at2ETransport: f << " type: two-engine transonic transport\n"; break; + case at3ETransport: f << " type: three-engine transonic transport\n"; break; + case at4ETransport: f << " type: four-engine transonic transport\n"; break; + case atMEProp: f << " type: multi-engine prop transport\n"; break; + } + f << " max weight: " << MTOW << " lb\n"; + f << " wing span: " << wingspan << " ft\n"; + f << " length: " << length << " ft\n"; + + if(!wingarea_input) + f << " wing area: unspecified\n"; + else + f << " wing area: " << wingarea << " sq-ft\n"; + + if (tricycle) f << " gear type: tricycle\n"; + else f << " gear type: taildragger\n"; + + if (retractable) f << " retractable?: yes\n"; + else f << " retractable?: no\n"; + + f << " # engines: " << engines << endl; + switch(eType) { + case etPiston: f << " engine type: piston\n"; break; + case etTurbine: f << " engine type: turbine\n"; break; + case etTurboprop: f << " engine type: turboprop\n"; break; + case etRocket: f << " engine type: rocket\n"; break; + } + + switch(elType) { + case elFwd_Fuselage: f << " engine layout: forward fuselage\n"; break; + case elMid_Fuselage: f << " engine layout: middle fuselage\n"; break; + case elAft_Fuselage: f << " engine layout: aft fuselage\n"; break; + case elWings: f << " engine layout: wings\n"; break; + case elWings_Tail: f << " engine layout: wings and tail\n"; break; + case elWings_Nose: f << " engine layout: wings and nose\n"; break; + } + + if(yawdamper) f << " yaw damper? yes\n"; + else f << " yaw damper? no\n\n"; + + f << fixed << setw(7) << setprecision(4); + f << " Outputs:\n"; + f << " wing loading: " << wingloading << " lb/sq-ft\n"; + f << " CL-alpha: " << CLalpha << " per radian\n"; + f << " CL-0: " << CL0 << endl; + f << " CL-max: " << CLmax << endl; + f << " CD-0: " << CD0 << endl; + f << " K: " << K << endl; + f << "\n-->\n\n"; + f << fixed << setw(7) << setprecision(2); + //***** METRICS ********************************** - f << " <metrics>\n"; - f << " <wingarea unit=\"FT2\"> " << wingarea << " </wingarea>\n"; - f << " <wingspan unit=\"FT\" > " << wingspan << " </wingspan>\n"; - f << " <chord unit=\"FT\" > " << wingchord << " </chord>\n"; - f << " <htailarea unit=\"FT2\"> " << htailarea << " </htailarea>\n"; - f << " <htailarm unit=\"FT\" > " << htailarm << " </htailarm>\n"; - f << " <vtailarea unit=\"FT2\"> " << vtailarea << " </vtailarea>\n"; - f << " <vtailarm unit=\"FT\" > " << vtailarm << " </vtailarm>\n"; - f << " <location name=\"AERORP\" unit=\"IN\">\n"; - f << " <x> " << aerorpx << " </x>\n"; - f << " <y> " << aerorpy << " </y>\n"; - f << " <z> " << aerorpz << " </z>\n"; + f << " <metrics>\n"; + f << " <wingarea unit=\"FT2\"> " << wingarea << " </wingarea>\n"; + f << " <wingspan unit=\"FT\" > " << wingspan << " </wingspan>\n"; + f << " <chord unit=\"FT\" > " << wingchord << " </chord>\n"; + f << " <htailarea unit=\"FT2\"> " << htailarea << " </htailarea>\n"; + f << " <htailarm unit=\"FT\" > " << htailarm << " </htailarm>\n"; + f << " <vtailarea unit=\"FT2\"> " << vtailarea << " </vtailarea>\n"; + f << " <vtailarm unit=\"FT\" > " << vtailarm << " </vtailarm>\n"; + f << " <location name=\"AERORP\" unit=\"IN\">\n"; + f << " <x> " << aerorpx << " </x>\n"; + f << " <y> " << aerorpy << " </y>\n"; + f << " <z> " << aerorpz << " </z>\n"; + f << " </location>\n"; + f << " <location name=\"EYEPOINT\" unit=\"IN\">\n"; + f << " <x> " << eyeptlocx << " </x>\n"; + f << " <y> " << eyeptlocy << " </y>\n"; + f << " <z> " << eyeptlocz << " </z>\n"; + f << " </location>\n"; + f << " <location name=\"VRP\" unit=\"IN\">\n"; + f << " <x>0</x>\n"; + f << " <y>0</y>\n"; + f << " <z>0</z>\n"; + f << " </location>\n"; + f << " </metrics>\n\n"; + + f << " <mass_balance>\n"; + f << " <ixx unit=\"SLUG*FT2\"> " << ixx << " </ixx>\n"; + f << " <iyy unit=\"SLUG*FT2\"> " << iyy << " </iyy>\n"; + f << " <izz unit=\"SLUG*FT2\"> " << izz << " </izz>\n"; + f << " <ixz unit=\"SLUG*FT2\"> " << ixz << " </ixz>\n"; + f << " <emptywt unit=\"LBS\" > " << emptyweight << " </emptywt>\n"; + f << " <location name=\"CG\" unit=\"IN\">\n"; + f << " <x> " << cglocx << " </x>\n"; + f << " <y> " << cglocy << " </y>\n"; + f << " <z> " << cglocz << " </z>\n"; + f << " </location>\n"; + f << " </mass_balance>\n\n"; + + + //***** LANDING GEAR ****************************** + + f << " <ground_reactions>\n\n"; + + if(aType == atGlider) { + + f << " <contact type=\"BOGEY\" name=\"LEFT_MAIN\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << gearlocx_main << " </x>\n"; + f << " <y> " << -gearlocy_main << " </y>\n"; + f << " <z> " << gearlocz_main << " </z>\n"; + f << " </location>\n"; + f << " <static_friction> " << gearstatic << " </static_friction>\n"; + f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; + f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; + f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; + f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; + f << " <max_steer unit=\"DEG\">0</max_steer>\n"; + f << " <brake_group>NONE</brake_group>\n"; + f << " <retractable>" << retract << "</retractable>\n"; + f << " </contact>\n\n"; + + f << " <contact type=\"BOGEY\" name=\"RIGHT_MAIN\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << gearlocx_main << " </x>\n"; + f << " <y> " << gearlocy_main << " </y>\n"; + f << " <z> " << gearlocz_main << " </z>\n"; f << " </location>\n"; - f << " <location name=\"EYEPOINT\" unit=\"IN\">\n"; - f << " <x> " << eyeptlocx << " </x>\n"; - f << " <y> " << eyeptlocy << " </y>\n"; - f << " <z> " << eyeptlocz << " </z>\n"; + f << " <static_friction> " << gearstatic << " </static_friction>\n"; + f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; + f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; + f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; + f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; + f << " <max_steer unit=\"DEG\">0</max_steer>\n"; + f << " <brake_group>NONE</brake_group>\n"; + f << " <retractable> " << retract << "</retractable>\n"; + f << " </contact>\n\n"; + + f << " <contact type=\"BOGEY\" name=\"NOSE\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << gearlocx_nose << " </x>\n"; + f << " <y> " << gearlocy_nose << " </y>\n"; + f << " <z> " << gearlocz_nose << " </z>\n"; f << " </location>\n"; - f << " <location name=\"VRP\" unit=\"IN\">\n"; - f << " <x>0</x>\n"; - f << " <y>0</y>\n"; - f << " <z>0</z>\n"; + f << " <static_friction> " << gearstatic << " </static_friction>\n"; + f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; + f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; + f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_nose << " </spring_coeff>\n"; + f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_nose << " </damping_coeff>\n"; + f << " <max_steer unit=\"DEG\">0</max_steer>\n"; + f << " <brake_group>NONE</brake_group>\n"; + f << " <retractable>" << retract << "</retractable>\n"; + f << " </contact>\n\n"; + + f << " <contact type=\"STRUCTURE\" name=\"LEFT_WING\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << cglocx << " </x>\n"; + f << " <y> " << -halfspan << " </y>\n"; + f << " <z> " << cglocz << " </z>\n"; f << " </location>\n"; - f << " </metrics>\n\n"; - - f << " <mass_balance>\n"; - f << " <ixx unit=\"SLUG*FT2\"> " << ixx << " </ixx>\n"; - f << " <iyy unit=\"SLUG*FT2\"> " << iyy << " </iyy>\n"; - f << " <izz unit=\"SLUG*FT2\"> " << izz << " </izz>\n"; - f << " <ixz unit=\"SLUG*FT2\"> " << ixz << " </ixz>\n"; - f << " <emptywt unit=\"LBS\" > " << emptyweight << " </emptywt>\n"; - f << " <location name=\"CG\" unit=\"IN\">\n"; + f << " <static_friction> " << gearstatic << " </static_friction>\n"; + f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; + f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; + f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; + f << " </contact>\n\n"; + + f << " <contact type=\"STRUCTURE\" name=\"RIGHT_WING\">\n"; + f << " <location unit=\"IN\">\n"; f << " <x> " << cglocx << " </x>\n"; - f << " <y> " << cglocy << " </y>\n"; + f << " <y> " << halfspan << " </y>\n"; f << " <z> " << cglocz << " </z>\n"; f << " </location>\n"; - f << " </mass_balance>\n\n"; - - - //***** LANDING GEAR ****************************** - - f << " <ground_reactions>\n\n"; - - if (aType == atGlider) - { - - f << " <contact type=\"BOGEY\" name=\"LEFT_MAIN\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << gearlocx_main << " </x>\n"; - f << " <y> " << -gearlocy_main << " </y>\n"; - f << " <z> " << gearlocz_main << " </z>\n"; - f << " </location>\n"; - f << " <static_friction> " << gearstatic << " </static_friction>\n"; - f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; - f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; - f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; - f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; - f << " <max_steer unit=\"DEG\">0</max_steer>\n"; - f << " <brake_group>NONE</brake_group>\n"; - f << " <retractable>" << retract << "</retractable>\n"; - f << " </contact>\n\n"; - - f << " <contact type=\"BOGEY\" name=\"RIGHT_MAIN\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << gearlocx_main << " </x>\n"; - f << " <y> " << gearlocy_main << " </y>\n"; - f << " <z> " << gearlocz_main << " </z>\n"; - f << " </location>\n"; - f << " <static_friction> " << gearstatic << " </static_friction>\n"; - f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; - f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; - f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; - f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; - f << " <max_steer unit=\"DEG\">0</max_steer>\n"; - f << " <brake_group>NONE</brake_group>\n"; - f << " <retractable> " << retract << "</retractable>\n"; - f << " </contact>\n\n"; - - f << " <contact type=\"BOGEY\" name=\"NOSE\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << gearlocx_nose << " </x>\n"; - f << " <y> " << gearlocy_nose << " </y>\n"; - f << " <z> " << gearlocz_nose << " </z>\n"; - f << " </location>\n"; - f << " <static_friction> " << gearstatic << " </static_friction>\n"; - f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; - f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; - f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_nose << " </spring_coeff>\n"; - f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_nose << " </damping_coeff>\n"; - f << " <max_steer unit=\"DEG\">0</max_steer>\n"; - f << " <brake_group>NONE</brake_group>\n"; - f << " <retractable>" << retract << "</retractable>\n"; - f << " </contact>\n\n"; - - f << " <contact type=\"STRUCTURE\" name=\"LEFT_WING\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << cglocx << " </x>\n"; - f << " <y> " << -halfspan << " </y>\n"; - f << " <z> " << cglocz << " </z>\n"; - f << " </location>\n"; - f << " <static_friction> " << gearstatic << " </static_friction>\n"; - f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; - f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; - f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; - f << " </contact>\n\n"; - - f << " <contact type=\"STRUCTURE\" name=\"RIGHT_WING\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << cglocx << " </x>\n"; - f << " <y> " << halfspan << " </y>\n"; - f << " <z> " << cglocz << " </z>\n"; - f << " </location>\n"; - f << " <static_friction> " << gearstatic << " </static_friction>\n"; - f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; - f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; - f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; - f << " </contact>\n\n"; - } - else // not a glider - { - if (tricycle) - { - - f << " <contact type=\"BOGEY\" name=\"NOSE\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << gearlocx_nose << " </x>\n"; - f << " <y> " << gearlocy_nose << " </y>\n"; - f << " <z> " << gearlocz_nose << " </z>\n"; - f << " </location>\n"; - f << " <static_friction> " << gearstatic << " </static_friction>\n"; - f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; - f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; - f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_nose << " </spring_coeff>\n"; - f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_nose << " </damping_coeff>\n"; - f << " <max_steer unit=\"DEG\"> " << gearmaxsteer << " </max_steer>\n"; - f << " <brake_group>NONE</brake_group>\n"; - f << " <retractable>" << retract << "</retractable>\n"; - f << " </contact>\n\n"; - } - - f << " <contact type=\"BOGEY\" name=\"LEFT_MAIN\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << gearlocx_main << " </x>\n"; - f << " <y> " << -gearlocy_main << " </y>\n"; - f << " <z> " << gearlocz_main << " </z>\n"; - f << " </location>\n"; - f << " <static_friction> " << gearstatic << " </static_friction>\n"; - f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; - f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; - f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; - f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; - f << " <max_steer unit=\"DEG\">0</max_steer>\n"; - f << " <brake_group>LEFT</brake_group>\n"; - f << " <retractable>" << retract << "</retractable>\n"; - f << " </contact>\n\n"; - - f << " <contact type=\"BOGEY\" name=\"RIGHT_MAIN\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << gearlocx_main << " </x>\n"; - f << " <y> " << gearlocy_main << " </y>\n"; - f << " <z> " << gearlocz_main << " </z>\n"; - f << " </location>\n"; - f << " <static_friction> " << gearstatic << " </static_friction>\n"; - f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; - f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; - f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; - f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; - f << " <max_steer unit=\"DEG\">0</max_steer>\n"; - f << " <brake_group>RIGHT</brake_group>\n"; - f << " <retractable>" << retract << "</retractable>\n"; - f << " </contact>\n\n"; - - if (!tricycle) - { - - f << " <contact type=\"BOGEY\" name=\"TAIL\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << gearlocx_tail << " </x>\n"; - f << " <y> " << gearlocy_tail << " </y>\n"; - f << " <z> " << gearlocz_tail << " </z>\n"; - f << " </location>\n"; - f << " <static_friction> " << gearstatic << " </static_friction>\n"; - f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; - f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; - f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_tail << " </spring_coeff>\n"; - f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_tail << " </damping_coeff>\n"; - f << " <max_steer unit=\"DEG\"> " << gearmaxsteer << " </max_steer>\n"; - f << " <brake_group>NONE</brake_group>\n"; - f << " <retractable>" << retract << "</retractable>\n"; - f << " </contact>\n\n"; - } - - f << " <contact type=\"STRUCTURE\" name=\"LEFT_WING\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << cglocx << " </x>\n"; - f << " <y> " << -halfspan << " </y>\n"; - f << " <z> " << cglocz << " </z>\n"; - f << " </location>\n"; - f << " <static_friction> " << gearstatic << " </static_friction>\n"; - f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; - f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; - f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; - f << " </contact>\n\n"; - - f << " <contact type=\"STRUCTURE\" name=\"RIGHT_WING\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << cglocx << " </x>\n"; - f << " <y> " << halfspan << " </y>\n"; - f << " <z> " << cglocz << " </z>\n"; - f << " </location>\n"; - f << " <static_friction> " << gearstatic << " </static_friction>\n"; - f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; - f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; - f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; - f << " </contact>\n\n"; + f << " <static_friction> " << gearstatic << " </static_friction>\n"; + f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; + f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; + f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; + f << " </contact>\n\n"; + } + else { // not a glider + if (tricycle) { + + f << " <contact type=\"BOGEY\" name=\"NOSE\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << gearlocx_nose << " </x>\n"; + f << " <y> " << gearlocy_nose << " </y>\n"; + f << " <z> " << gearlocz_nose << " </z>\n"; + f << " </location>\n"; + f << " <static_friction> " << gearstatic << " </static_friction>\n"; + f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; + f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; + f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_nose << " </spring_coeff>\n"; + f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_nose << " </damping_coeff>\n"; + f << " <max_steer unit=\"DEG\"> " << gearmaxsteer << " </max_steer>\n"; + f << " <brake_group>NONE</brake_group>\n"; + f << " <retractable>" << retract << "</retractable>\n"; + f << " </contact>\n\n"; + } + + f << " <contact type=\"BOGEY\" name=\"LEFT_MAIN\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << gearlocx_main << " </x>\n"; + f << " <y> " << -gearlocy_main << " </y>\n"; + f << " <z> " << gearlocz_main << " </z>\n"; + f << " </location>\n"; + f << " <static_friction> " << gearstatic << " </static_friction>\n"; + f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; + f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; + f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; + f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; + f << " <max_steer unit=\"DEG\">0</max_steer>\n"; + f << " <brake_group>LEFT</brake_group>\n"; + f << " <retractable>" << retract << "</retractable>\n"; + f << " </contact>\n\n"; + + f << " <contact type=\"BOGEY\" name=\"RIGHT_MAIN\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << gearlocx_main << " </x>\n"; + f << " <y> " << gearlocy_main << " </y>\n"; + f << " <z> " << gearlocz_main << " </z>\n"; + f << " </location>\n"; + f << " <static_friction> " << gearstatic << " </static_friction>\n"; + f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; + f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; + f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; + f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; + f << " <max_steer unit=\"DEG\">0</max_steer>\n"; + f << " <brake_group>RIGHT</brake_group>\n"; + f << " <retractable>" << retract << "</retractable>\n"; + f << " </contact>\n\n"; + + if (!tricycle) { + + f << " <contact type=\"BOGEY\" name=\"TAIL\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << gearlocx_tail << " </x>\n"; + f << " <y> " << gearlocy_tail << " </y>\n"; + f << " <z> " << gearlocz_tail << " </z>\n"; + f << " </location>\n"; + f << " <static_friction> " << gearstatic << " </static_friction>\n"; + f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; + f << " <rolling_friction> " << gearrolling << " </rolling_friction>\n"; + f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_tail << " </spring_coeff>\n"; + f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_tail << " </damping_coeff>\n"; + f << " <max_steer unit=\"DEG\"> " << gearmaxsteer << " </max_steer>\n"; + f << " <brake_group>NONE</brake_group>\n"; + f << " <retractable>" << retract << "</retractable>\n"; + f << " </contact>\n\n"; + } + + f << " <contact type=\"STRUCTURE\" name=\"LEFT_WING\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << cglocx << " </x>\n"; + f << " <y> " << -halfspan << " </y>\n"; + f << " <z> " << cglocz << " </z>\n"; + f << " </location>\n"; + f << " <static_friction> " << gearstatic << " </static_friction>\n"; + f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; + f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; + f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; + f << " </contact>\n\n"; + + f << " <contact type=\"STRUCTURE\" name=\"RIGHT_WING\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << cglocx << " </x>\n"; + f << " <y> " << halfspan << " </y>\n"; + f << " <z> " << cglocz << " </z>\n"; + f << " </location>\n"; + f << " <static_friction> " << gearstatic << " </static_friction>\n"; + f << " <dynamic_friction> " << geardynamic << " </dynamic_friction>\n"; + f << " <spring_coeff unit=\"LBS/FT\"> " << gearspring_main << " </spring_coeff>\n"; + f << " <damping_coeff unit=\"LBS/FT/SEC\"> " << geardamp_main << " </damping_coeff>\n"; + f << " </contact>\n\n"; - } - f << " </ground_reactions>\n\n"; + } + f << " </ground_reactions>\n\n"; //***** PROPULSION *************************************** - f << " <propulsion>\n\n"; - if (aType == atGlider) // if glider, do nothing here - { - } - else - { - for (i=0; i<engines; i++) - { - - f << " <engine file=\"" << EngineName << "\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << englocx[i] << " </x>\n"; - f << " <y> " << englocy[i] << " </y>\n"; - f << " <z> " << englocz[i] << " </z>\n"; - f << " </location>\n"; - f << " <orient unit=\"DEG\">\n"; - f << " <pitch> " << engpitch << " </pitch>\n"; - f << " <roll> 0.00 </roll>\n"; - f << " <yaw> " << engyaw << " </yaw>\n"; - f << " </orient>\n"; - f << " <feed>" << engfeed[i] << "</feed>\n"; - - if (eType == etPiston) f << " <thruster file=\"" << PropName << "\">\n"; - else f << " <thruster file=\"direct\">\n"; - - f << " <location unit=\"IN\">\n"; - f << " <x> " << thrusterlocx[i] << " </x>\n"; - f << " <y> " << thrusterlocy[i] << " </y>\n"; - f << " <z> " << thrusterlocz[i] << " </z>\n"; - f << " </location>\n"; - f << " <orient unit=\"DEG\">\n"; - f << " <pitch> " << thrusterpitch << " </pitch>\n"; - f << " <roll> 0.00 </roll>\n"; - f << " <yaw> " << thrusteryaw << " </yaw>\n"; - f << " </orient>\n"; - - f << " </thruster>\n"; - f << " </engine>\n\n"; - } - -//***** FUEL TANKS ************************************** - - for (i=0; i<(engines + 1); i++) - { - f << " <tank type=\"FUEL\" number=\"" << i << "\">\n"; - f << " <location unit=\"IN\">\n"; - f << " <x> " << tanklocx << " </x>\n"; - f << " <y> " << tanklocy << " </y>\n"; - f << " <z> " << tanklocz << " </z>\n"; - f << " </location>\n"; - f << " <capacity unit=\"LBS\"> " << tankcapacity << " </capacity>\n"; - f << " <contents unit=\"LBS\"> " << tankcontents << " </contents>\n"; - f << " </tank>\n\n"; - } - } - f << " </propulsion>\n\n"; + f << " <propulsion>\n\n"; + if(aType == atGlider) { // if glider, do nothing here + } + else { + for(i=0; i<engines; i++) { + + f << " <engine file=\"" << EngineName << "\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << englocx[i] << " </x>\n"; + f << " <y> " << englocy[i] << " </y>\n"; + f << " <z> " << englocz[i] << " </z>\n"; + f << " </location>\n"; + f << " <orient unit=\"DEG\">\n"; + f << " <pitch> " << engpitch << " </pitch>\n"; + f << " <roll> 0.00 </roll>\n"; + f << " <yaw> " << engyaw << " </yaw>\n"; + f << " </orient>\n"; + f << " <feed>" << engfeed[i] << "</feed>\n"; + + if (eType == etPiston) f << " <thruster file=\"" << PropName << "\">\n"; + else f << " <thruster file=\"direct\">\n"; + + f << " <location unit=\"IN\">\n"; + f << " <x> " << thrusterlocx[i] << " </x>\n"; + f << " <y> " << thrusterlocy[i] << " </y>\n"; + f << " <z> " << thrusterlocz[i] << " </z>\n"; + f << " </location>\n"; + f << " <orient unit=\"DEG\">\n"; + f << " <pitch> " << thrusterpitch << " </pitch>\n"; + f << " <roll> 0.00 </roll>\n"; + f << " <yaw> " << thrusteryaw << " </yaw>\n"; + f << " </orient>\n"; + + f << " </thruster>\n"; + f << " </engine>\n\n"; + } + + //***** FUEL TANKS ************************************** + + for(i=0; i<(engines + 1); i++) { + f << " <tank type=\"FUEL\" number=\"" << i << "\">\n"; + f << " <location unit=\"IN\">\n"; + f << " <x> " << tanklocx << " </x>\n"; + f << " <y> " << tanklocy << " </y>\n"; + f << " <z> " << tanklocz << " </z>\n"; + f << " </location>\n"; + f << " <capacity unit=\"LBS\"> " << tankcapacity << " </capacity>\n"; + f << " <contents unit=\"LBS\"> " << tankcontents << " </contents>\n"; + f << " </tank>\n\n"; + } +} + f << " </propulsion>\n\n"; //***** FLIGHT CONTROL SYSTEM *************************** - f << " <flight_control name=\"" << AircraftName << "\">\n\n"; + f << " <flight_control name=\"" << AircraftName << "\">\n\n"; + + f << " <component name=\"Pitch Trim Sum\" type=\"SUMMER\">\n"; + f << " <input>fcs/elevator-cmd-norm</input>\n"; + f << " <input>fcs/pitch-trim-cmd-norm</input>\n"; + f << " <clipto>\n"; + f << " <min> -1 </min>\n"; + f << " <max> 1 </max>\n"; + f << " </clipto>\n"; + f << " </component>\n\n"; + + f << " <component name=\"Elevator Control\" type=\"AEROSURFACE_SCALE\">\n"; + f << " <input>fcs/pitch-trim-sum</input>\n"; + f << " <limit>\n"; + f << " <min> -0.35 </min>\n"; + f << " <max> 0.30 </max>\n"; + f << " </limit>\n"; + f << " <output>fcs/elevator-pos-rad</output>\n"; + f << " </component>\n\n"; + + f << " <component name=\"Roll Trim Sum\" type=\"SUMMER\">\n"; + f << " <input>fcs/aileron-cmd-norm</input>\n"; + f << " <input>fcs/roll-trim-cmd-norm</input>\n"; + f << " <clipto>\n"; + f << " <min> -1 </min>\n"; + f << " <max> 1 </max>\n"; + f << " </clipto>\n"; + f << " </component>\n\n"; + + f << " <component name=\"Left Aileron Control\" type=\"AEROSURFACE_SCALE\">\n"; + f << " <input>fcs/roll-trim-sum</input>\n"; + f << " <limit>\n"; + f << " <min> -0.35 </min>\n"; + f << " <max> 0.35 </max>\n"; + f << " </limit>\n"; + f << " <output>fcs/left-aileron-pos-rad</output>\n"; + f << " </component>\n\n"; + + f << " <component name=\"Right Aileron Control\" type=\"AEROSURFACE_SCALE\">\n"; + f << " <input>fcs/roll-trim-sum</input>\n"; + f << " <limit>\n"; + f << " <min> -0.35 </min>\n"; + f << " <max> 0.35 </max>\n"; + f << " </limit>\n"; + f << " <output>fcs/right-aileron-pos-rad</output>\n"; + f << " </component>\n\n"; + + f << " <component name=\"Rudder Command Sum\" type=\"SUMMER\">\n"; + f << " <input>fcs/rudder-cmd-norm</input>\n"; + f << " <input>fcs/yaw-trim-cmd-norm</input>\n"; + f << " <limit>\n"; + f << " <min> -0.35 </min>\n"; + f << " <max> 0.35 </max>\n"; + f << " </limit>\n"; + f << " </component>\n\n"; + + if (yawdamper) { + f << " <component name=\"Yaw Damper Rate\" type=\"SCHEDULED_GAIN\">\n"; + f << " <input>velocities/r-aero-rad_sec</input>\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/ve-kts</independentVar>\n"; + f << " <tableData>\n"; + f << " 30 0.00\n"; + f << " 60 2.00\n"; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </component>\n\n"; - f << " <component name=\"Pitch Trim Sum\" type=\"SUMMER\">\n"; - f << " <input>fcs/elevator-cmd-norm</input>\n"; - f << " <input>fcs/pitch-trim-cmd-norm</input>\n"; - f << " <clipto>\n"; - f << " <min> -1 </min>\n"; - f << " <max> 1 </max>\n"; - f << " </clipto>\n"; + f << " <component name=\"Yaw Damper Beta\" type=\"SCHEDULED_GAIN\">\n"; + f << " <input>aero/beta-rad</input>\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/ve-kts</independentVar>\n"; + f << " <tableData>\n"; + f << " 30 0.00\n"; + f << " 60 0.00\n"; + f << " </tableData>\n"; + f << " </table>\n"; f << " </component>\n\n"; - f << " <component name=\"Elevator Control\" type=\"AEROSURFACE_SCALE\">\n"; - f << " <input>fcs/pitch-trim-sum</input>\n"; + f << " <component name=\"Yaw Damper Sum\" type=\"SUMMER\">\n"; + f << " <input>fcs/yaw-damper-beta</input>\n"; + f << " <input>fcs/yaw-damper-rate</input>\n"; f << " <limit>\n"; - f << " <min> -0.35 </min>\n"; - f << " <max> 0.30 </max>\n"; + f << " <min> -0.1 </min>\n"; + f << " <max> 0.1 </max>\n"; f << " </limit>\n"; - f << " <output>fcs/elevator-pos-rad</output>\n"; f << " </component>\n\n"; - f << " <component name=\"Roll Trim Sum\" type=\"SUMMER\">\n"; - f << " <input>fcs/aileron-cmd-norm</input>\n"; - f << " <input>fcs/roll-trim-cmd-norm</input>\n"; - f << " <clipto>\n"; - f << " <min> -1 </min>\n"; - f << " <max> 1 </max>\n"; - f << " </clipto>\n"; + f << " <component name=\"Yaw Damper Final\" type=\"SCHEDULED_GAIN\">\n"; + f << " <input>fcs/yaw-damper-sum</input>\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/ve-kts</independentVar>\n"; + f << " <tableData>\n"; + f << " 30 0.0\n"; + f << " 31 1.0\n"; + f << " </tableData>\n"; + f << " </table>\n"; f << " </component>\n\n"; - f << " <component name=\"Left Aileron Control\" type=\"AEROSURFACE_SCALE\">\n"; - f << " <input>fcs/roll-trim-sum</input>\n"; + f << " <component name=\"Rudder Sum\" type=\"SUMMER\">\n"; + f << " <input>fcs/rudder-command-sum</input>\n"; + f << " <input>fcs/yaw-damper-final</input>\n"; f << " <limit>\n"; - f << " <min> -0.35 </min>\n"; - f << " <max> 0.35 </max>\n"; - f << " </limit>\n"; - f << " <output>fcs/left-aileron-pos-rad</output>\n"; - f << " </component>\n\n"; - - f << " <component name=\"Right Aileron Control\" type=\"AEROSURFACE_SCALE\">\n"; - f << " <input>fcs/roll-trim-sum</input>\n"; - f << " <limit>\n"; - f << " <min> -0.35 </min>\n"; - f << " <max> 0.35 </max>\n"; + f << " <min> -1 </min>\n"; + f << " <max> 1 </max>\n"; f << " </limit>\n"; - f << " <output>fcs/right-aileron-pos-rad</output>\n"; f << " </component>\n\n"; - f << " <component name=\"Rudder Command Sum\" type=\"SUMMER\">\n"; - f << " <input>fcs/rudder-cmd-norm</input>\n"; - f << " <input>fcs/yaw-trim-cmd-norm</input>\n"; + f << " <component name=\"Rudder Control\" type=\"AEROSURFACE_SCALE\">\n"; + f << " <input>fcs/rudder-sum</input>\n"; f << " <limit>\n"; f << " <min> -0.35 </min>\n"; f << " <max> 0.35 </max>\n"; f << " </limit>\n"; - f << " </component>\n\n"; - - if (yawdamper) - { - f << " <component name=\"Yaw Damper Rate\" type=\"SCHEDULED_GAIN\">\n"; - f << " <input>velocities/r-aero-rad_sec</input>\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/ve-kts</independentVar>\n"; - f << " <tableData>\n"; - f << " 30 0.00\n"; - f << " 60 2.00\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </component>\n\n"; - - f << " <component name=\"Yaw Damper Beta\" type=\"SCHEDULED_GAIN\">\n"; - f << " <input>aero/beta-rad</input>\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/ve-kts</independentVar>\n"; - f << " <tableData>\n"; - f << " 30 0.00\n"; - f << " 60 0.00\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </component>\n\n"; - - f << " <component name=\"Yaw Damper Sum\" type=\"SUMMER\">\n"; - f << " <input>fcs/yaw-damper-beta</input>\n"; - f << " <input>fcs/yaw-damper-rate</input>\n"; - f << " <limit>\n"; - f << " <min> -0.1 </min>\n"; - f << " <max> 0.1 </max>\n"; - f << " </limit>\n"; - f << " </component>\n\n"; - - f << " <component name=\"Yaw Damper Final\" type=\"SCHEDULED_GAIN\">\n"; - f << " <input>fcs/yaw-damper-sum</input>\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/ve-kts</independentVar>\n"; - f << " <tableData>\n"; - f << " 30 0.0\n"; - f << " 31 1.0\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </component>\n\n"; - - f << " <component name=\"Rudder Sum\" type=\"SUMMER\">\n"; - f << " <input>fcs/rudder-command-sum</input>\n"; - f << " <input>fcs/yaw-damper-final</input>\n"; - f << " <limit>\n"; - f << " <min> -1 </min>\n"; - f << " <max> 1 </max>\n"; - f << " </limit>\n"; - f << " </component>\n\n"; - - f << " <component name=\"Rudder Control\" type=\"AEROSURFACE_SCALE\">\n"; - f << " <input>fcs/rudder-sum</input>\n"; - f << " <limit>\n"; - f << " <min> -0.35 </min>\n"; - f << " <max> 0.35 </max>\n"; - f << " </limit>\n"; - f << " <output>fcs/rudder-pos-rad</output>\n"; - f << " </component>\n\n"; - } - else - { - f << " <component name=\"Rudder Control\" type=\"AEROSURFACE_SCALE\">\n"; - f << " <input>fcs/rudder-command-sum</input>\n"; - f << " <limit>\n"; - f << " <min> -0.35 </min>\n"; - f << " <max> 0.35 </max>\n"; - f << " </limit>\n"; - f << " <output>fcs/rudder-pos-rad</output>\n"; - f << " </component>\n\n"; - } - - f << " <component name=\"Flaps Control\" type=\"KINEMAT\">\n"; - f << " <input>fcs/flap-cmd-norm</input>\n"; - f << " <traverse>\n"; - f << " <setting>\n"; - f << " <position> 0 </position>\n"; - f << " <time> 0 </time>\n"; - f << " </setting>\n"; - f << " <setting>\n"; - f << " <position> 15 </position>\n"; - f << " <time> 4 </time>\n"; - f << " </setting>\n"; - f << " <setting>\n"; - f << " <position> 30 </position>\n"; - f << " <time> 3 </time>\n"; - f << " </setting>\n"; - f << " </traverse>\n"; - f << " <output>fcs/flap-pos-deg</output>\n"; - f << " </component>\n\n"; - - if (retractable) - { - f << " <component name=\"Gear Control\" type=\"KINEMAT\">\n"; - f << " <input>gear/gear-cmd-norm</input>\n"; - f << " <traverse>\n"; - f << " <setting>\n"; - f << " <position> 0 </position>\n"; - f << " <time> 0 </time>\n"; - f << " </setting>\n"; - f << " <setting>\n"; - f << " <position> 1 </position>\n"; - f << " <time> 5 </time>\n"; - f << " </setting>\n"; - f << " </traverse>\n"; - f << " <output>gear/gear-pos-norm</output>\n"; - f << " </component>\n\n"; - } - - f << " <component name=\"Speedbrake Control\" type=\"KINEMAT\">\n"; - f << " <input>fcs/speedbrake-cmd-norm</input>\n"; + f << " <output>fcs/rudder-pos-rad</output>\n"; + f << " </component>\n\n"; + } + else { + f << " <component name=\"Rudder Control\" type=\"AEROSURFACE_SCALE\">\n"; + f << " <input>fcs/rudder-command-sum</input>\n"; + f << " <limit>\n"; + f << " <min> -0.35 </min>\n"; + f << " <max> 0.35 </max>\n"; + f << " </limit>\n"; + f << " <output>fcs/rudder-pos-rad</output>\n"; + f << " </component>\n\n"; + } + + f << " <component name=\"Flaps Control\" type=\"KINEMAT\">\n"; + f << " <input>fcs/flap-cmd-norm</input>\n"; + f << " <traverse>\n"; + f << " <setting>\n"; + f << " <position> 0 </position>\n"; + f << " <time> 0 </time>\n"; + f << " </setting>\n"; + f << " <setting>\n"; + f << " <position> 15 </position>\n"; + f << " <time> 4 </time>\n"; + f << " </setting>\n"; + f << " <setting>\n"; + f << " <position> 30 </position>\n"; + f << " <time> 3 </time>\n"; + f << " </setting>\n"; + f << " </traverse>\n"; + f << " <output>fcs/flap-pos-deg</output>\n"; + f << " </component>\n\n"; + + if (retractable) { + f << " <component name=\"Gear Control\" type=\"KINEMAT\">\n"; + f << " <input>gear/gear-cmd-norm</input>\n"; f << " <traverse>\n"; f << " <setting>\n"; f << " <position> 0 </position>\n"; @@ -2395,470 +1724,484 @@ string Aeromatic::PrintAero() f << " </setting>\n"; f << " <setting>\n"; f << " <position> 1 </position>\n"; - f << " <time> 1 </time>\n"; + f << " <time> 5 </time>\n"; f << " </setting>\n"; f << " </traverse>\n"; - f << " <output>fcs/speedbrake-pos-norm</output>\n"; + f << " <output>gear/gear-pos-norm</output>\n"; f << " </component>\n\n"; - - f << " </flight_control>\n\n"; - - //***** AERODYNAMICS ****************************************** - - - f << " <aerodynamics>\n\n"; - f << " <axis name=\"LIFT\">\n\n"; - - // build a simple lift curve with four points - double point; - f << " <coefficient name=\"CLalpha\">\n"; - f << " <description>Lift_due_to_alpha</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">aero/alpha-rad</independentVar>\n"; - f << " <tableData>\n"; - point = -(CLalpha * 0.2) + CL0; - f << " -0.20 " << point << endl; - f << " 0.00 " << CL0 << endl; - double alpha = (CLmax - CL0) / CLalpha; - f << " " << alpha << " " << CLmax << endl; - point = CLmax - (0.6 * alpha * CLalpha); - f << " 0.60 " << point << endl; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - double dCLflap_per_deg = dCLflaps / 30.0; - f << " <coefficient name=\"dCLflap\">\n"; - f << " <description>Delta_Lift_due_to_flaps</description>\n"; + } + + f << " <component name=\"Speedbrake Control\" type=\"KINEMAT\">\n"; + f << " <input>fcs/speedbrake-cmd-norm</input>\n"; + f << " <traverse>\n"; + f << " <setting>\n"; + f << " <position> 0 </position>\n"; + f << " <time> 0 </time>\n"; + f << " </setting>\n"; + f << " <setting>\n"; + f << " <position> 1 </position>\n"; + f << " <time> 1 </time>\n"; + f << " </setting>\n"; + f << " </traverse>\n"; + f << " <output>fcs/speedbrake-pos-norm</output>\n"; + f << " </component>\n\n"; + + f << " </flight_control>\n\n"; + + //***** AERODYNAMICS ****************************************** + + + f << " <aerodynamics>\n\n"; + f << " <axis name=\"LIFT\">\n\n"; + + // build a simple lift curve with four points + double point; + f << " <coefficient name=\"CLalpha\">\n"; + f << " <description>Lift_due_to_alpha</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">aero/alpha-rad</independentVar>\n"; + f << " <tableData>\n"; + point = -(CLalpha * 0.2) + CL0; + f << " -0.20 " << point << endl; + f << " 0.00 " << CL0 << endl; + double alpha = (CLmax - CL0) / CLalpha; + f << " " << alpha << " " << CLmax << endl; + point = CLmax - (0.6 * alpha * CLalpha); + f << " 0.60 " << point << endl; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + double dCLflap_per_deg = dCLflaps / 30.0; + f << " <coefficient name=\"dCLflap\">\n"; + f << " <description>Delta_Lift_due_to_flaps</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>fcs/flap-pos-deg</property>\n"; + f << " <value> " << dCLflap_per_deg << " </value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"dCLsb\">\n"; + f << " <description>Delta_Lift_due_to_speedbrake</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>fcs/speedbrake-pos-norm</property>\n"; + f << " <value>" << dCLspeedbrake << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"CLde\">\n"; + f << " <description>Lift_due_to_Elevator_Deflection</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>fcs/elevator-pos-rad</property>\n"; + f << " <value>" << CLde << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " </axis>\n\n"; + + //***** DRAG ****************************************************** + + f << " <axis name=\"DRAG\">\n\n"; + + f << " <coefficient name=\"CD0\">\n"; + f << " <description>Drag_at_zero_lift</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">aero/alpha-rad</independentVar>\n"; + f << " <tableData>\n"; + f << " -1.57 1.500\n"; + double CD02 = CD0 * 1.3; + f << " -0.26 " << CD02 << endl; + f << " 0.00 " << CD0 << endl; + f << " 0.26 " << CD02 << endl; + f << " 1.57 1.500\n"; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"CDi\">\n"; + f << " <description>Induced_drag</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>aero/cl-squared-norm</property>\n"; + f << " <value>" << K << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"CDmach\">\n"; + f << " <description>Drag_due_to_mach</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; + f << " <tableData>\n"; + f << " 0.00 0.000\n"; + f << " " << Mcrit << " 0.000\n"; + f << " 1.10 0.023\n"; + f << " 1.80 0.015\n"; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + double CDflaps_per_deg = CDflaps / 30.0; + f << " <coefficient name=\"CDflap\">\n"; + f << " <description>Drag_due_to_flaps</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>fcs/flap-pos-deg</property>\n"; + f << " <value> " << CDflaps_per_deg << " </value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + if (retractable) { + f << " <coefficient name=\"CDgear\">\n"; + f << " <description>Drag_due_to_gear</description>\n"; f << " <function>\n"; f << " <product>\n"; f << " <property>aero/qbar-psf</property>\n"; f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>fcs/flap-pos-deg</property>\n"; - f << " <value> " << dCLflap_per_deg << " </value>\n"; + f << " <property>gear/gear-pos-norm</property>\n"; + f << " <value>" << CDgear << "</value>\n"; f << " </product>\n"; f << " </function>\n"; f << " </coefficient>\n\n"; - - f << " <coefficient name=\"dCLsb\">\n"; - f << " <description>Delta_Lift_due_to_speedbrake</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>fcs/speedbrake-pos-norm</property>\n"; - f << " <value>" << dCLspeedbrake << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"CLde\">\n"; - f << " <description>Lift_due_to_Elevator_Deflection</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>fcs/elevator-pos-rad</property>\n"; - f << " <value>" << CLde << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " </axis>\n\n"; - - //***** DRAG ****************************************************** - - f << " <axis name=\"DRAG\">\n\n"; - - f << " <coefficient name=\"CD0\">\n"; - f << " <description>Drag_at_zero_lift</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">aero/alpha-rad</independentVar>\n"; - f << " <tableData>\n"; - f << " -1.57 1.500\n"; - double CD02 = CD0 * 1.3; - f << " -0.26 " << CD02 << endl; - f << " 0.00 " << CD0 << endl; - f << " 0.26 " << CD02 << endl; - f << " 1.57 1.500\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"CDi\">\n"; - f << " <description>Induced_drag</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>aero/cl-squared-norm</property>\n"; - f << " <value>" << K << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"CDmach\">\n"; - f << " <description>Drag_due_to_mach</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; - f << " <tableData>\n"; - f << " 0.00 0.000\n"; - f << " " << Mcrit << " 0.000\n"; - f << " 1.10 0.023\n"; - f << " 1.80 0.015\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - double CDflaps_per_deg = CDflaps / 30.0; - f << " <coefficient name=\"CDflap\">\n"; - f << " <description>Drag_due_to_flaps</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>fcs/flap-pos-deg</property>\n"; - f << " <value> " << CDflaps_per_deg << " </value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - if (retractable) - { - f << " <coefficient name=\"CDgear\">\n"; - f << " <description>Drag_due_to_gear</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>gear/gear-pos-norm</property>\n"; - f << " <value>" << CDgear << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - } - - f << " <coefficient name=\"CDsb\">\n"; - f << " <description>Drag_due_to_speedbrakes</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>fcs/speedbrake-pos-norm</property>\n"; - f << " <value>" << CDspeedbrake << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - double CDb26 = CDbeta * 0.25; // CD at beta of 0.26 radians - f << " <coefficient name=\"CDbeta\">\n"; - f << " <description>Drag_due_to_sideslip</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">aero/beta-rad</independentVar>\n"; - f << " <tableData>\n"; - f << " -1.57 1.230\n"; - f << " -0.26 " << CDb26 << endl; - f << " 0.00 0.000\n"; - f << " 0.26 " << CDb26 << endl; - f << " 1.57 1.230\n"; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"CDde\">\n"; - f << " <description>Drag_due_to_Elevator_Deflection</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>fcs/elevator-pos-norm</property>\n"; - f << " <value>" << CDde << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " </axis>\n\n"; - - //***** SIDE ************************************************* - - f << " <axis name=\"SIDE\">\n\n"; - - f << " <coefficient name=\"CYb\">\n"; - f << " <description>Side_force_due_to_beta</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>aero/beta-rad</property>\n"; - f << " <value>" << CYbeta << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " </axis>\n\n"; - - //***** ROLL ************************************************ - - f << " <axis name=\"ROLL\">\n\n"; - - f << " <coefficient name=\"Clb\">\n"; - f << " <description>Roll_moment_due_to_beta</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/bw-ft</property>\n"; - f << " <property>aero/beta-rad</property>\n"; - f << " <value>" << Clbeta << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"Clp\">\n"; - f << " <description>Roll_moment_due_to_roll_rate</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/bw-ft</property>\n"; - f << " <property>aero/bi2vel</property>\n"; - f << " <property>velocities/p-aero-rad_sec</property>\n"; - f << " <value>" << Clp << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"Clr\">\n"; - f << " <description>Roll_moment_due_to_yaw_rate</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/bw-ft</property>\n"; - f << " <property>aero/bi2vel</property>\n"; - f << " <property>velocities/r-aero-rad_sec</property>\n"; - f << " <value>" << Clr << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - double Clda3 = Clda * 0.333; - f << " <coefficient name=\"Clda\">\n"; - f << " <description>Roll_moment_due_to_aileron</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/bw-ft</property>\n"; - f << " <property>fcs/left-aileron-pos-rad</property>\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; - f << " <tableData>\n"; - f << " 0.0 " << Clda << endl; - f << " 2.0 " << Clda3 << endl; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"Cldr\">\n"; - f << " <description>Roll_moment_due_to_rudder</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/bw-ft</property>\n"; - f << " <property>fcs/rudder-pos-rad</property>\n"; - f << " <value>" << Cldr << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " </axis>\n\n"; - - //***** PITCH ***************************************** - - f << " <axis name=\"PITCH\">\n\n"; - - f << " <coefficient name=\"Cmalpha\">\n"; - f << " <description>Pitch_moment_due_to_alpha</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/cbarw-ft</property>\n"; - f << " <property>aero/alpha-rad</property>\n"; - f << " <value>" << Cmalpha << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - double Cmde4 = Cmde * 0.25; - f << " <coefficient name=\"Cmde\">\n"; - f << " <description>Pitch_moment_due_to_elevator</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/cbarw-ft</property>\n"; - f << " <property>fcs/elevator-pos-rad</property>\n"; - f << " <table>\n"; - f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; - f << " <tableData>\n"; - f << " 0.0 " << Cmde << endl; - f << " 2.0 " << Cmde4 << endl; - f << " </tableData>\n"; - f << " </table>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"Cmq\">\n"; - f << " <description>Pitch_moment_due_to_pitch_rate</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/cbarw-ft</property>\n"; - f << " <property>aero/ci2vel</property>\n"; - f << " <property>velocities/q-aero-rad_sec</property>\n"; - f << " <value>" << Cmq << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"Cmadot\">\n"; - f << " <description>Pitch_moment_due_to_alpha_rate</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/cbarw-ft</property>\n"; - f << " <property>aero/ci2vel</property>\n"; - f << " <property>aero/alphadot-rad_sec</property>\n"; - f << " <value>" << Cmadot << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " </axis>\n\n"; - - //***** YAW *********************************************** - - f << " <axis name=\"YAW\">\n\n"; - - f << " <coefficient name=\"Cnb\">\n"; - f << " <description>Yaw_moment_due_to_beta</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/bw-ft</property>\n"; - f << " <property>aero/beta-rad</property>\n"; - f << " <value>" << Cnbeta << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"Cnr\">\n"; - f << " <description>Yaw_moment_due_to_yaw_rate</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/bw-ft</property>\n"; - f << " <property>aero/bi2vel</property>\n"; - f << " <property>velocities/r-aero-rad_sec</property>\n"; - f << " <value>" << Cnr << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"Cndr\">\n"; - f << " <description>Yaw_moment_due_to_rudder</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/bw-ft</property>\n"; - f << " <property>fcs/rudder-pos-rad</property>\n"; - f << " <value>" << Cndr << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " <coefficient name=\"Cnda\">\n"; - f << " <description>Adverse_yaw</description>\n"; - f << " <function>\n"; - f << " <product>\n"; - f << " <property>aero/qbar-psf</property>\n"; - f << " <property>metrics/Sw-sqft</property>\n"; - f << " <property>metrics/bw-ft</property>\n"; - f << " <property>fcs/left-aileron-pos-rad</property>\n"; - f << " <value>" << Cnda << "</value>\n"; - f << " </product>\n"; - f << " </function>\n"; - f << " </coefficient>\n\n"; - - f << " </axis>\n\n"; - f << " </aerodynamics>\n\n"; - f << "</fdm_config>\n"; - - f << flush; - f.close(); - return filename; + } + + f << " <coefficient name=\"CDsb\">\n"; + f << " <description>Drag_due_to_speedbrakes</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>fcs/speedbrake-pos-norm</property>\n"; + f << " <value>" << CDspeedbrake << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + double CDb26 = CDbeta * 0.25; // CD at beta of 0.26 radians + f << " <coefficient name=\"CDbeta\">\n"; + f << " <description>Drag_due_to_sideslip</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">aero/beta-rad</independentVar>\n"; + f << " <tableData>\n"; + f << " -1.57 1.230\n"; + f << " -0.26 " << CDb26 << endl; + f << " 0.00 0.000\n"; + f << " 0.26 " << CDb26 << endl; + f << " 1.57 1.230\n"; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"CDde\">\n"; + f << " <description>Drag_due_to_Elevator_Deflection</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>fcs/elevator-pos-norm</property>\n"; + f << " <value>" << CDde << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " </axis>\n\n"; + + //***** SIDE ************************************************* + + f << " <axis name=\"SIDE\">\n\n"; + + f << " <coefficient name=\"CYb\">\n"; + f << " <description>Side_force_due_to_beta</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>aero/beta-rad</property>\n"; + f << " <value>" << CYbeta << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " </axis>\n\n"; + + //***** ROLL ************************************************ + + f << " <axis name=\"ROLL\">\n\n"; + + f << " <coefficient name=\"Clb\">\n"; + f << " <description>Roll_moment_due_to_beta</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/bw-ft</property>\n"; + f << " <property>aero/beta-rad</property>\n"; + f << " <value>" << Clbeta << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"Clp\">\n"; + f << " <description>Roll_moment_due_to_roll_rate</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/bw-ft</property>\n"; + f << " <property>aero/bi2vel</property>\n"; + f << " <property>velocities/p-aero-rad_sec</property>\n"; + f << " <value>" << Clp << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"Clr\">\n"; + f << " <description>Roll_moment_due_to_yaw_rate</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/bw-ft</property>\n"; + f << " <property>aero/bi2vel</property>\n"; + f << " <property>velocities/r-aero-rad_sec</property>\n"; + f << " <value>" << Clr << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + double Clda3 = Clda * 0.333; + f << " <coefficient name=\"Clda\">\n"; + f << " <description>Roll_moment_due_to_aileron</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/bw-ft</property>\n"; + f << " <property>fcs/left-aileron-pos-rad</property>\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; + f << " <tableData>\n"; + f << " 0.0 " << Clda << endl; + f << " 2.0 " << Clda3 << endl; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"Cldr\">\n"; + f << " <description>Roll_moment_due_to_rudder</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/bw-ft</property>\n"; + f << " <property>fcs/rudder-pos-rad</property>\n"; + f << " <value>" << Cldr << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " </axis>\n\n"; + + //***** PITCH ***************************************** + + f << " <axis name=\"PITCH\">\n\n"; + + f << " <coefficient name=\"Cmalpha\">\n"; + f << " <description>Pitch_moment_due_to_alpha</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/cbarw-ft</property>\n"; + f << " <property>aero/alpha-rad</property>\n"; + f << " <value>" << Cmalpha << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + double Cmde4 = Cmde * 0.25; + f << " <coefficient name=\"Cmde\">\n"; + f << " <description>Pitch_moment_due_to_elevator</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/cbarw-ft</property>\n"; + f << " <property>fcs/elevator-pos-rad</property>\n"; + f << " <table>\n"; + f << " <independentVar lookup=\"row\">velocities/mach-norm</independentVar>\n"; + f << " <tableData>\n"; + f << " 0.0 " << Cmde << endl; + f << " 2.0 " << Cmde4 << endl; + f << " </tableData>\n"; + f << " </table>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"Cmq\">\n"; + f << " <description>Pitch_moment_due_to_pitch_rate</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/cbarw-ft</property>\n"; + f << " <property>aero/ci2vel</property>\n"; + f << " <property>velocities/q-aero-rad_sec</property>\n"; + f << " <value>" << Cmq << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"Cmadot\">\n"; + f << " <description>Pitch_moment_due_to_alpha_rate</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/cbarw-ft</property>\n"; + f << " <property>aero/ci2vel</property>\n"; + f << " <property>aero/alphadot-rad_sec</property>\n"; + f << " <value>" << Cmadot << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " </axis>\n\n"; + + //***** YAW *********************************************** + + f << " <axis name=\"YAW\">\n\n"; + + f << " <coefficient name=\"Cnb\">\n"; + f << " <description>Yaw_moment_due_to_beta</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/bw-ft</property>\n"; + f << " <property>aero/beta-rad</property>\n"; + f << " <value>" << Cnbeta << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"Cnr\">\n"; + f << " <description>Yaw_moment_due_to_yaw_rate</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/bw-ft</property>\n"; + f << " <property>aero/bi2vel</property>\n"; + f << " <property>velocities/r-aero-rad_sec</property>\n"; + f << " <value>" << Cnr << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"Cndr\">\n"; + f << " <description>Yaw_moment_due_to_rudder</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/bw-ft</property>\n"; + f << " <property>fcs/rudder-pos-rad</property>\n"; + f << " <value>" << Cndr << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " <coefficient name=\"Cnda\">\n"; + f << " <description>Adverse_yaw</description>\n"; + f << " <function>\n"; + f << " <product>\n"; + f << " <property>aero/qbar-psf</property>\n"; + f << " <property>metrics/Sw-sqft</property>\n"; + f << " <property>metrics/bw-ft</property>\n"; + f << " <property>fcs/left-aileron-pos-rad</property>\n"; + f << " <value>" << Cnda << "</value>\n"; + f << " </product>\n"; + f << " </function>\n"; + f << " </coefficient>\n\n"; + + f << " </axis>\n\n"; + f << " </aerodynamics>\n\n"; + f << "</fdm_config>\n"; + + f << flush; + f.close(); + return filename; } -void Aeromatic::Reset() -{ - AircraftName = EngineName = PropName = "unnamed"; - aType = atLtSingle; - MTOW = 5000.0; - wingspan = 30.0; - length = 30.0; - wingarea = 0.0; // this allows aeromatic to estimate wing area - tricycle = true; - retractable = true; - engines = 1; - eType = etPiston; - elType = elFwd_Fuselage; - yawdamper = false; - enginePower = 400.0; - engineRPM = 2700.0; - fixedpitch = false; - diameter = 6.0; - engineThrust = 2000.0; - augmentation = false; - injection = false; +void Aeromatic::Reset() { + AircraftName = EngineName = PropName = "unnamed"; + aType = atLtSingle; + MTOW = 5000.0; + wingspan = 30.0; + length = 30.0; + wingarea = 0.0; // this allows aeromatic to estimate wing area + tricycle = true; + retractable = true; + engines = 1; + eType = etPiston; + elType = elFwd_Fuselage; + yawdamper = false; + enginePower = 400.0; + engineRPM = 2700.0; + fixedpitch = false; + diameter = 6.0; + engineThrust = 2000.0; + augmentation = false; + injection = false; } // } // namespace //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + diff --git a/src/utilities/aeromatic/Aeromatic.h b/src/utilities/aeromatic/Aeromatic.h old mode 100644 new mode 100755 index 2890d8ae138d69c1dbf85e1087a8e2b4421d861c..8797cac304972b8290cacfb896732519843962a3 --- a/src/utilities/aeromatic/Aeromatic.h +++ b/src/utilities/aeromatic/Aeromatic.h @@ -1,33 +1,33 @@ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + Header: Aeromatic.h Author: David Culp Implementation of the Aero-Matic web application Date started: 04/26/05 - + ------------- Copyright (C) 20005 David Culp (davidculp2@comcast.net)--------- - + 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; either version 2 of the License, or (at your option) any later version. - + 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. - + Further information about the GNU General Public License can also be found on the world wide web at http://www.gnu.org. - + HISTORY -------------------------------------------------------------------------------- 04/26/05 DPC Created - + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SENTRY %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ @@ -53,6 +53,7 @@ FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ //namespace JSBSim { +using namespace std; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -60,7 +61,7 @@ CLASS DOCUMENTATION /** This class encapsulates the Aero-Matic web application, which is used to generate plausible JSBSim configuration files based on a few questions - about an aircraft's type and metrics. + about an aircraft's type and metrics. To use this class you must first supply it with useful data, for example, to get an engine configuration file for a CFM-56: @@ -71,7 +72,7 @@ CLASS DOCUMENTATION am->SetEngineThrust(20000.0); string engine_filename = am->PrintEngine(); - + @author David Culp @version $Id: Aeromatic.h */ @@ -80,147 +81,80 @@ CLASS DOCUMENTATION CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class Aeromatic -{ - using namespace std; +class Aeromatic { public: - /// Constructor - Aeromatic(); - /// Destructor - ~Aeromatic(); - - /// Resets all variables to their initial state - void Reset(); - - enum aircraftType { atGlider, atLtSingle, atLtTwin, atRacer, atSEFighter, - at2EFighter, at2ETransport, at3ETransport, at4ETransport, atMEProp - }; - - enum engineType { etPiston, etTurbine, etTurboprop, etRocket }; - - enum engineLayoutType { elFwd_Fuselage, elMid_Fuselage, elAft_Fuselage, elWings, - elWings_Tail, elWings_Nose - }; - - // Setters for user input - void SetAircraftName(string n) - { - AircraftName=n; - } - void SetEngineName(string n) - { - EngineName=n; - } - void SetPropName(string n) - { - PropName=n; - } - void SetAircraftType(aircraftType t) - { - aType=t; - } - void SetMTOW(double mtow) - { - MTOW=mtow; - } - void SetWingspan(double s) - { - wingspan=s; - } - void SetLength(double len) - { - length=len; - } - void SetWingArea(double S) - { - wingarea=S; - } - void SetTricycle(bool t) - { - tricycle=t; - } - void SetRetractable(bool r) - { - retractable=r; - } - void SetNumEngines(int n) - { - engines=n; - } - void SetEngineType(engineType et) - { - eType=et; - } - void SetEngineLayout(engineLayoutType el) - { - elType=el; - } - void SetYawDamper(bool d) - { - yawdamper=d; - } - void SetEnginePower(double p) - { - enginePower=p; - } - void SetEngineRPM(double r) - { - engineRPM=r; - } - void SetFixedPitch(bool f) - { - fixedpitch=f; - } - void SetPropDiameter(double d) - { - diameter=d; - } - void SetEngineThrust(double t) - { - engineThrust=t; - } - void SetAugmented(bool a) - { - augmentation=a; - } - void SetInjected(bool i) - { - injection=i; - } - - // Functions to retrieve Aero-Matic output (print to XML file). - // Return value is file name. - string PrintEngine(); - string PrintProp(); - string PrintAero(); + /// Constructor + Aeromatic(); + /// Destructor + ~Aeromatic(); + + /// Resets all variables to their initial state + void Reset(); + + enum aircraftType { atGlider, atLtSingle, atLtTwin, atRacer, atSEFighter, + at2EFighter, at2ETransport, at3ETransport, at4ETransport, atMEProp }; + + enum engineType { etPiston, etTurbine, etTurboprop, etRocket }; + + enum engineLayoutType { elFwd_Fuselage, elMid_Fuselage, elAft_Fuselage, elWings, + elWings_Tail, elWings_Nose }; + + // Setters for user input + void SetAircraftName(string n) { AircraftName=n; } + void SetEngineName(string n) { EngineName=n; } + void SetPropName(string n) { PropName=n; } + void SetAircraftType(aircraftType t) { aType=t; } + void SetMTOW(double mtow) { MTOW=mtow; } + void SetWingspan(double s) { wingspan=s; } + void SetLength(double len) { length=len; } + void SetWingArea(double S) { wingarea=S; } + void SetTricycle(bool t) { tricycle=t; } + void SetRetractable(bool r) { retractable=r; } + void SetNumEngines(int n) { engines=n; } + void SetEngineType(engineType et) { eType=et; } + void SetEngineLayout(engineLayoutType el) { elType=el; } + void SetYawDamper(bool d) { yawdamper=d; } + void SetEnginePower(double p) { enginePower=p; } + void SetEngineRPM(double r) { engineRPM=r; } + void SetFixedPitch(bool f) { fixedpitch=f; } + void SetPropDiameter(double d) { diameter=d; } + void SetEngineThrust(double t) { engineThrust=t; } + void SetAugmented(bool a) { augmentation=a; } + void SetInjected(bool i) { injection=i; } + + // Functions to retrieve Aero-Matic output (print to XML file). + // Return value is file name. + string PrintEngine(); + string PrintProp(); + string PrintAero(); private: - string AircraftName, EngineName, PropName; - aircraftType aType; - double MTOW; // Maximum Takeoff Weight, in pounds - double wingspan; // Wing span, in feet - double length; // Aircraft length, in feet - double wingarea; // Planform area of wing, in square feet - bool tricycle; // True if aircraft has tricycle landing gear. - // False implies a tail-dragger configuration. - bool retractable; // True if gear is retractable. - int engines; // Number of engines. - engineType eType; // Type of engines. One type for all! - engineLayoutType elType; // Engine locations. - bool yawdamper; // True if yaw damper installed - - double enginePower; // Engine horsepower. Max at sea level. - double engineRPM; // Maximum rated engine rpm. - bool fixedpitch; // True if prop pitch is fixed. - // False implies variable pitch. - double diameter; // Propeller diameter in feet. - - double engineThrust; // Engine thrust in pounds, static at sea level, - // without afterburning. - bool augmentation; // True if augmentation (afterburner) installed. - bool injection; // True if water or nitrous injection installed. + string AircraftName, EngineName, PropName; + aircraftType aType; + double MTOW; // Maximum Takeoff Weight, in pounds + double wingspan; // Wing span, in feet + double length; // Aircraft length, in feet + double wingarea; // Planform area of wing, in square feet + bool tricycle; // True if aircraft has tricycle landing gear. + // False implies a tail-dragger configuration. + bool retractable; // True if gear is retractable. + int engines; // Number of engines. + engineType eType; // Type of engines. One type for all! + engineLayoutType elType; // Engine locations. + bool yawdamper; // True if yaw damper installed + + double enginePower; // Engine horsepower. Max at sea level. + double engineRPM; // Maximum rated engine rpm. + bool fixedpitch; // True if prop pitch is fixed. + // False implies variable pitch. + double diameter; // Propeller diameter in feet. + + double engineThrust; // Engine thrust in pounds, static at sea level, + // without afterburning. + bool augmentation; // True if augmentation (afterburner) installed. + bool injection; // True if water or nitrous injection installed. }; diff --git a/src/utilities/aeromatic/aero.php b/src/utilities/aeromatic/aero.php old mode 100644 new mode 100755 diff --git a/src/utilities/aeromatic/aero2.php b/src/utilities/aeromatic/aero2.php old mode 100644 new mode 100755 diff --git a/src/utilities/aeromatic/aeromatic-doc.html b/src/utilities/aeromatic/aeromatic-doc.html old mode 100644 new mode 100755 diff --git a/src/utilities/aeromatic/aeromatic.html b/src/utilities/aeromatic/aeromatic.html old mode 100644 new mode 100755 diff --git a/src/utilities/aeromatic/aeromatic2.html b/src/utilities/aeromatic/aeromatic2.html old mode 100644 new mode 100755 diff --git a/src/utilities/aeromatic/engine.php b/src/utilities/aeromatic/engine.php old mode 100644 new mode 100755 diff --git a/src/utilities/aeromatic/engine2.php b/src/utilities/aeromatic/engine2.php old mode 100644 new mode 100755 diff --git a/src/utilities/aeromatic/prop.php b/src/utilities/aeromatic/prop.php old mode 100644 new mode 100755 diff --git a/src/utilities/aeromatic/prop2.php b/src/utilities/aeromatic/prop2.php old mode 100644 new mode 100755 diff --git a/src/utilities/aeromatic/readme-aeromatic.html b/src/utilities/aeromatic/readme-aeromatic.html old mode 100644 new mode 100755 diff --git a/src/utilities/datafile.cpp b/src/utilities/datafile.cpp index d4a9caa488a7b5d45128df3939beaeeecbcc3cde..9b6840fef3abf8d3bb8ce922145cfdda0fe335ac 100644 --- a/src/utilities/datafile.cpp +++ b/src/utilities/datafile.cpp @@ -17,163 +17,141 @@ #include "datafile.h" -DataFile::DataFile() -{ +DataFile::DataFile() { } -DataFile::~DataFile() -{ - f.close(); +DataFile::~DataFile() { + f.close(); } /** This overloaded constructor opens the requested file. */ -DataFile::DataFile(string fname) -{ - int count=0; - unsigned short start, end; - string var; - - f.open(fname.c_str()); - f.setf(ios::skipws); - if ( !f ) - { - cout << "fileopen failed for file " << fname << endl << endl; - exit(-1); +DataFile::DataFile(string fname) { + int count=0; + unsigned short start, end; + string var; + + f.open(fname.c_str()); + f.setf(ios::skipws); + if ( !f ) { + cout << "fileopen failed for file " << fname << endl << endl; + exit(-1); + } else { + cout << "File " << fname << " successfully opened." << endl; + } + + getline(f, data_str); + end = 0; + + while (1) { + start = end; + while (data_str[start] == ' ') start++; + end = data_str.find(",", start); + count++; + if (end >= 65535) { + end = data_str.size(); + var = data_str.substr(start, end-start); + names.push_back(var); + break; + } else { + var = data_str.substr(start, end-start); + names.push_back(var); + end++; } - else - { - cout << "File " << fname << " successfully opened." << endl; + } + + cout << "Done parsing names. Reading data ..." << endl; + + int row=0, column=0; + char scratch[10]; + + while (1) { + column = 0; + Data.push_back(*(new Row())); + while (1) { + Data[row].push_back(0.0); + f >> Data[row][column]; + if (f.eof()) { + Data.pop_back(); + break; + } + if (++column == count) break; + else f >> scratch; } - - getline(f, data_str); - end = 0; - - while (1) - { - start = end; - while (data_str[start] == ' ') start++; - end = data_str.find(",", start); - count++; - if (end >= 65535) - { - end = data_str.size(); - var = data_str.substr(start, end-start); - names.push_back(var); - break; - } - else - { - var = data_str.substr(start, end-start); - names.push_back(var); - end++; - } - } - - cout << "Done parsing names. Reading data ..." << endl; - - int row=0, column=0; - char scratch[10]; - - while (1) - { - column = 0; - Data.push_back(*(new Row())); - while (1) - { - Data[row].push_back(0.0); - f >> Data[row][column]; - if (f.eof()) - { - Data.pop_back(); - break; - } - if (++column == count) break; - else f >> scratch; - } - row++; - if (f.eof()) break; - } - - for (int i=0;i<GetNumFields();i++) - { - Max.push_back(0.0); - Min.push_back(0.0); - } - - for (int fld=0; fld<GetNumFields(); fld++) - { - Max[fld] = Data[0][fld]; - Min[fld] = Data[0][fld]; - for (int rec=1;rec<GetNumRecords();rec++) - { - if (Data[rec][fld] > Max[fld]) Max[fld] = Data[rec][fld]; - else if (Data[rec][fld] < Min[fld]) Min[fld] = Data[rec][fld]; - } + row++; + if (f.eof()) break; + } + + for (int i=0;i<GetNumFields();i++) { + Max.push_back(0.0); + Min.push_back(0.0); + } + + for (int fld=0; fld<GetNumFields(); fld++) { + Max[fld] = Data[0][fld]; + Min[fld] = Data[0][fld]; + for (int rec=1;rec<GetNumRecords();rec++) { + if (Data[rec][fld] > Max[fld]) Max[fld] = Data[rec][fld]; + else if (Data[rec][fld] < Min[fld]) Min[fld] = Data[rec][fld]; } + } - StartIdx = 0; - EndIdx = GetNumRecords()-1; + StartIdx = 0; + EndIdx = GetNumRecords()-1; - cout << endl << "Done Reading data ..." << endl; + cout << endl << "Done Reading data ..." << endl; } -float DataFile::GetAutoAxisMax(int item) -{ - double Mx, order, magnitude; - float max = Max[item]; - float min = Min[item]; +float DataFile::GetAutoAxisMax(int item) { + double Mx, order, magnitude; + float max = Max[item]; + float min = Min[item]; - if (max == 0.0 && min == 0.0) return(1.0); + if (max == 0.0 && min == 0.0) return(1.0); - if (StartIdx != 0 || EndIdx != (GetNumRecords()-1)) - { - Mx = Data[StartIdx][item]; - for (int rec=StartIdx+1; rec<=EndIdx; rec++) - { - if (Data[rec][item] > Mx) Mx = Data[rec][item]; - } + if (StartIdx != 0 || EndIdx != (GetNumRecords()-1)) { + Mx = Data[StartIdx][item]; + for (int rec=StartIdx+1; rec<=EndIdx; rec++) { + if (Data[rec][item] > Mx) Mx = Data[rec][item]; } + } - order = (int)(log10(fabs(max))); - magnitude = pow((double)10.0, (double)order); + order = (int)(log10(fabs(max))); + magnitude = pow((double)10.0, (double)order); - if (max > 0.0) Mx = ((int)(max / magnitude) + 1) * magnitude; - else Mx = ((int)(max / magnitude)) * magnitude; + if (max > 0.0) Mx = ((int)(max / magnitude) + 1) * magnitude; + else Mx = ((int)(max / magnitude)) * magnitude; - return Mx; + return Mx; } -float DataFile::GetAutoAxisMin(int item) -{ - float Mn, order, magnitude; - float min = Min[item]; - float max = Max[item]; +float DataFile::GetAutoAxisMin(int item) { + float Mn, order, magnitude; + float min = Min[item]; + float max = Max[item]; - if (max == 0.0 && min == 0.0) return(0.0); + if (max == 0.0 && min == 0.0) return(0.0); - if (StartIdx != 0 || (EndIdx != GetNumRecords()-1)) - { - min = Data[StartIdx][item]; - for (int rec=StartIdx+1; rec<=EndIdx; rec++) - { - if (Data[rec][item] < min) min = Data[rec][item]; - } + if (StartIdx != 0 || (EndIdx != GetNumRecords()-1)) { + min = Data[StartIdx][item]; + for (int rec=StartIdx+1; rec<=EndIdx; rec++) { + if (Data[rec][item] < min) min = Data[rec][item]; } + } - order = (int)(log10(fabs(min))); - magnitude = pow((double)10.0, (double)order); + order = (int)(log10(fabs(min))); + magnitude = pow((double)10.0, (double)order); - if (min > 0.0) Mn = ((int)(min / magnitude)) * magnitude; - else Mn = ((int)(min / magnitude) - 1) * magnitude; + if (min > 0.0) Mn = ((int)(min / magnitude)) * magnitude; + else Mn = ((int)(min / magnitude) - 1) * magnitude; - return Mn; + return Mn; } diff --git a/src/utilities/datafile.h b/src/utilities/datafile.h index e9c02c975107dae53f9554c5c4febbbfb7030e80..d02219ecd40b2466a1ad74cdd6d852c3a4d2e0c9 100644 --- a/src/utilities/datafile.h +++ b/src/utilities/datafile.h @@ -25,81 +25,44 @@ #include <cmath> #include <iostream> +using namespace std; /**This class handles reading a data file and placing user-requested data into arrays for plotting. *@author Jon S. Berndt */ -class DataFile -{ - using namespace std; +class DataFile { public: - DataFile(); - ~DataFile(); - DataFile(string fname); + DataFile(); + ~DataFile(); + DataFile(string fname); - std::vector <string> names; - string data_str; - typedef std::vector <float> Row; - typedef std::vector <Row> DataType; - DataType Data; + std::vector <string> names; + string data_str; + typedef std::vector <float> Row; + typedef std::vector <Row> DataType; + DataType Data; - int GetNumFields(void) - { - if (Data.size() > 0) return(Data[0].size()); - else return(0); - } - int GetNumRecords(void) - { - return(Data.size()); - } - float GetStartTime(void) - { - if (Data.size() >= 2) return(Data[0][0]); - else return(0); - } - float GetEndTime(void) - { - if (Data.size() >= 2) return(Data[Data.size()-1][0]); - else return(0); - } - float GetMax(int column) - { - return(Max[column]); - } - float GetMin(int column) - { - return(Min[column]); - } - float GetRange(int field) - { - return (GetMax(field) - GetMin(field)); - } - float GetAutoAxisMax(int item); - float GetAutoAxisMin(int item); - void SetStartIdx(int sidx) - { - StartIdx = sidx; - } - void SetEndIdx(int eidx) - { - EndIdx = eidx; - } - int GetStartIdx(void) - { - return StartIdx; - } - int GetEndIdx(void) - { - return EndIdx; - } + int GetNumFields(void) {if (Data.size() > 0) return(Data[0].size()); else return(0);} + int GetNumRecords(void) {return(Data.size());} + float GetStartTime(void) {if (Data.size() >= 2) return(Data[0][0]); else return(0);} + float GetEndTime(void) {if (Data.size() >= 2) return(Data[Data.size()-1][0]); else return(0);} + float GetMax(int column) {return(Max[column]);} + float GetMin(int column) {return(Min[column]);} + float GetRange(int field) {return (GetMax(field) - GetMin(field));} + float GetAutoAxisMax(int item); + float GetAutoAxisMin(int item); + void SetStartIdx(int sidx) {StartIdx = sidx;} + void SetEndIdx(int eidx) {EndIdx = eidx;} + int GetStartIdx(void) {return StartIdx;} + int GetEndIdx(void) {return EndIdx;} private: // Private attributes - string buff_str; - ifstream f; - Row Max; - Row Min; - int StartIdx, EndIdx; + string buff_str; + ifstream f; + Row Max; + Row Min; + int StartIdx, EndIdx; }; #endif diff --git a/src/utilities/main.cpp b/src/utilities/main.cpp index 4d5f5c61817e74da757257884528bf63ae82b9d2..369ab9a332fbebc399869d64aed81f9eb2edce3e 100644 --- a/src/utilities/main.cpp +++ b/src/utilities/main.cpp @@ -43,570 +43,502 @@ ofstream outfile; int main(int argc, char *argv[]) { - string commands_str, digits = "0123456789", displaytype="CONS", next, input_arg; - string savefile="", pngFName_str="JSBSim", time_str, float_digits=".0123456789"; - vector <int> commands_vec; - size_t start = 0, end = 0, namelen; - char pngFName[200]="JSBSim"; - float sf, ef; - char scratch; - - if (argc > 3 || argc == 1 ) - { - cout << endl << "Usage: SimPlot <data_file_name.csv> [<autoplot file>]" << endl << endl; - exit(-1); + string commands_str, digits = "0123456789", displaytype="CONS", next, input_arg; + string savefile="", pngFName_str="JSBSim", time_str, float_digits=".0123456789"; + vector <int> commands_vec; + size_t start = 0, end = 0, namelen; + char pngFName[200]="JSBSim"; + float sf, ef; + char scratch; + + if (argc > 3 || argc == 1 ) { + cout << endl << "Usage: SimPlot <data_file_name.csv> [<autoplot file>]" << endl << endl; + exit(-1); + } + + DataFile df(argv[1]); + + if (argc == 3) { + + ifstream inputfile(argv[2]); + if (!inputfile) { + cerr << "Could not open autoplot file " << argv[2] << endl << endl; + exit(-1); } + plotXMLVisitor myVisitor; + readXML (inputfile, myVisitor); - DataFile df(argv[1]); + plotdata(df, &myVisitor); + exit(0); + } - if (argc == 3) - { + cout << endl << endl << "Here are the available parameters which may be plotted: " << endl; + cout << endl; - ifstream inputfile(argv[2]); - if (!inputfile) - { - cerr << "Could not open autoplot file " << argv[2] << endl << endl; - exit(-1); - } - plotXMLVisitor myVisitor; - readXML (inputfile, myVisitor); - - plotdata(df, &myVisitor); - exit(0); - } - - cout << endl << endl << "Here are the available parameters which may be plotted: " << endl; - cout << endl; - - namelen = 0; - for (unsigned int i=0; i<df.names.size();i++) - { - namelen = namelen > df.names[i].size() ? namelen : df.names[i].size(); - } + namelen = 0; + for (unsigned int i=0; i<df.names.size();i++) { + namelen = namelen > df.names[i].size() ? namelen : df.names[i].size(); + } nextplot: - commands_str = ""; - time_str = ""; - start=0; - end=0; - commands_vec.clear(); - - bool col1 = true; - unsigned int i; - for (i=0; i<df.names.size();i++) - { - cout << i << ") " << df.names[i]; - if (col1) - { - for (unsigned int j=0; j<= namelen - df.names[i].size() + 2; j++) cout << " "; - if (i<10) cout << " "; - } - else - { - cout << endl; - } - col1=!col1; + commands_str = ""; + time_str = ""; + start=0; + end=0; + commands_vec.clear(); + + bool col1 = true; + unsigned int i; + for (i=0; i<df.names.size();i++) { + cout << i << ") " << df.names[i]; + if (col1) { + for (unsigned int j=0; j<= namelen - df.names[i].size() + 2; j++) cout << " "; + if (i<10) cout << " "; + } else { + cout << endl; } + col1=!col1; + } - int numvars = df.GetNumFields(); - int numpoints = df.GetNumRecords(); - float starttime = df.GetStartTime(); - float endtime = df.GetEndTime(); + int numvars = df.GetNumFields(); + int numpoints = df.GetNumRecords(); + float starttime = df.GetStartTime(); + float endtime = df.GetEndTime(); - cout << endl; - cout << endl << "Data file contains " << numvars << " independent variables." << endl; - cout << "Number of data points: " << numpoints << endl; - cout << "Time goes from " << starttime << " to " << endtime << " seconds." << endl; + cout << endl; + cout << endl << "Data file contains " << numvars << " independent variables." << endl; + cout << "Number of data points: " << numpoints << endl; + cout << "Time goes from " << starttime << " to " << endtime << " seconds." << endl; entertime: - cout << endl << "Enter new time range [#.#-#.# or -]: "; - cin >> time_str; - - sf = starttime; - ef = endtime; - - if (time_str[0] != '-') - { - sscanf(time_str.c_str(),"%f %c %f",&sf, &scratch, &ef); - - bool redo = true; - if (ef <= sf) - { - cout << "The end time must be greater than the start time" << endl; - } - else if (ef <= 0.0) - { - cout << "The end time must be greater than zero" << endl; - } - else if (sf < 0.000) - { - cout << "The start time must not be less than zero" << endl; + cout << endl << "Enter new time range [#.#-#.# or -]: "; + cin >> time_str; + + sf = starttime; + ef = endtime; + + if (time_str[0] != '-') { + sscanf(time_str.c_str(),"%f %c %f",&sf, &scratch, &ef); + + bool redo = true; + if (ef <= sf) { + cout << "The end time must be greater than the start time" << endl; + } else if (ef <= 0.0) { + cout << "The end time must be greater than zero" << endl; + } else if (sf < 0.000) { + cout << "The start time must not be less than zero" << endl; + } else if (sf < starttime) { + cout << "The start time must not be less than " << starttime << endl; + } else if (ef > endtime) { + cout << "The end time must not be greater than " << endtime << endl; + } else { + for (int pt=0; pt<df.GetNumRecords(); pt++) { + if (df.Data[pt][0] <= sf) df.SetStartIdx(pt); + if (df.Data[pt][0] <= ef) { + df.SetEndIdx(pt); + } else { + break; } - else if (sf < starttime) - { - cout << "The start time must not be less than " << starttime << endl; - } - else if (ef > endtime) - { - cout << "The end time must not be greater than " << endtime << endl; - } - else - { - for (int pt=0; pt<df.GetNumRecords(); pt++) - { - if (df.Data[pt][0] <= sf) df.SetStartIdx(pt); - if (df.Data[pt][0] <= ef) - { - df.SetEndIdx(pt); - } - else - { - break; - } - } - redo = false; - } - if (redo) goto entertime; - } - else - { - df.SetStartIdx(0); - df.SetEndIdx(df.GetNumRecords()-1); + } + redo = false; } + if (redo) goto entertime; + } else { + df.SetStartIdx(0); + df.SetEndIdx(df.GetNumRecords()-1); + } - cout << endl << "Enter a comma-separated list of the items to be plotted (or 'q' to quit): "; - cin >> commands_str; + cout << endl << "Enter a comma-separated list of the items to be plotted (or 'q' to quit): "; + cin >> commands_str; - if (commands_str[0] == 'q') exit(0); + if (commands_str[0] == 'q') exit(0); - while (1) - { - start = commands_str.find_first_of(digits,start); - if (start >= string::npos) break; - end = commands_str.find_first_not_of(digits,start); - commands_vec.push_back(atoi(commands_str.substr(start, end-start).c_str())); - start=end; - } + while (1) { + start = commands_str.find_first_of(digits,start); + if (start >= string::npos) break; + end = commands_str.find_first_not_of(digits,start); + commands_vec.push_back(atoi(commands_str.substr(start, end-start).c_str())); + start=end; + } - cout << "Initializing plot page ..." << endl; + cout << "Initializing plot page ..." << endl; savepng: // Set page format - metafl((char*)displaytype.c_str()); - setpag("da4l"); + metafl((char*)displaytype.c_str()); + setpag("da4l"); // Initialization - disini(); + disini(); // Set Plot Parameters - pagera(); - serif(); - shdcha(); - chncrv("color"); + pagera(); + serif(); + shdcha(); + chncrv("color"); // Set plot axis system - axspos(450,1800); - axslen(2200,1200); + axspos(450,1800); + axslen(2200,1200); // Set plot titles - int thisplot; - int numtraces = commands_vec.size(); + int thisplot; + int numtraces = commands_vec.size(); - name("Time (in seconds)","x"); + name("Time (in seconds)","x"); - string longaxistext; - for (thisplot=0; thisplot < numtraces; thisplot++) - { - longaxistext = longaxistext + " " + df.names[commands_vec[thisplot]]; - } - name((char*)(longaxistext.c_str()),"y"); + string longaxistext; + for (thisplot=0; thisplot < numtraces; thisplot++) { + longaxistext = longaxistext + " " + df.names[commands_vec[thisplot]]; + } + name((char*)(longaxistext.c_str()),"y"); - labdig(3,"xy"); - ticks(10,"xy"); + labdig(3,"xy"); + ticks(10,"xy"); - titlin("JSBSim plot",1); - string subtitle = ""; - for (thisplot=0; thisplot < numtraces; thisplot++) - { - if (thisplot == 0) subtitle = df.names[commands_vec[thisplot]]; - else subtitle = subtitle + ", " + df.names[commands_vec[thisplot]]; - } + titlin("JSBSim plot",1); + string subtitle = ""; + for (thisplot=0; thisplot < numtraces; thisplot++) { + if (thisplot == 0) subtitle = df.names[commands_vec[thisplot]]; + else subtitle = subtitle + ", " + df.names[commands_vec[thisplot]]; + } - subtitle = subtitle + string(" vs. Time"); - titlin((char*)(subtitle.c_str()),3); + subtitle = subtitle + string(" vs. Time"); + titlin((char*)(subtitle.c_str()),3); // Plot data - double *timarray = new double[df.GetEndIdx()-df.GetStartIdx()+1]; // new jsb 11/9 + double *timarray = new double[df.GetEndIdx()-df.GetStartIdx()+1]; // new jsb 11/9 - for (int pt=df.GetStartIdx(), pti=0; pt<=df.GetEndIdx(); pt++, pti++) - { - timarray[pti] = df.Data[pt][0]; - } + for (int pt=df.GetStartIdx(), pti=0; pt<=df.GetEndIdx(); pt++, pti++) { + timarray[pti] = df.Data[pt][0]; + } - float axismax = df.GetAutoAxisMax(commands_vec[0]); - float axismin = df.GetAutoAxisMin(commands_vec[0]); + float axismax = df.GetAutoAxisMax(commands_vec[0]); + float axismin = df.GetAutoAxisMin(commands_vec[0]); - for (thisplot=1; thisplot < numtraces; thisplot++) - { - axismax = axismax > df.GetAutoAxisMax(commands_vec[thisplot]) ? axismax : df.GetAutoAxisMax(commands_vec[thisplot]); - axismin = axismin < df.GetAutoAxisMin(commands_vec[thisplot]) ? axismin : df.GetAutoAxisMin(commands_vec[thisplot]); - } + for (thisplot=1; thisplot < numtraces; thisplot++) { + axismax = axismax > df.GetAutoAxisMax(commands_vec[thisplot]) ? axismax : df.GetAutoAxisMax(commands_vec[thisplot]); + axismin = axismin < df.GetAutoAxisMin(commands_vec[thisplot]) ? axismin : df.GetAutoAxisMin(commands_vec[thisplot]); + } - float spread = axismax - axismin; + float spread = axismax - axismin; - if (spread < 1.0) labdig(3,"y"); - else if (spread < 10.0) labdig(2,"y"); - else if (spread < 100.0) labdig(1,"y"); - else labdig(0,"y"); + if (spread < 1.0) labdig(3,"y"); + else if (spread < 10.0) labdig(2,"y"); + else if (spread < 100.0) labdig(1,"y"); + else labdig(0,"y"); - if (spread > 1000.0) - { - labdig(2,"y"); - labels("fexp","y"); - } - else - { - labels("float","y"); - } + if (spread > 1000.0) { + labdig(2,"y"); + labels("fexp","y"); + } else { + labels("float","y"); + } - spread = df.Data[df.GetEndIdx()][0] - df.Data[df.GetStartIdx()][0]; - - if (spread < 1.0) labdig(3,"x"); - else if (spread < 10.0) labdig(2,"x"); - else if (spread < 100.0) labdig(1,"x"); - else labdig(0,"x"); - - float fac = ((int)(spread + 0.5))/10.00; - - if (spread > 1000.0) labels("fexp","x"); - else labels("float","x"); - - graf( df.Data[df.GetStartIdx()][0], // starttime - df.Data[df.GetEndIdx()][0], // endtime - df.Data[df.GetStartIdx()][0], // starttime - fac, - axismin, - axismax, - axismin, - (axismax - axismin)/10.0); - - title(); - color("blue"); - grid(1,1); - - for (thisplot=0; thisplot < numtraces; thisplot++) - { - double *datarray = new double[df.GetEndIdx()-df.GetStartIdx()+1]; - for (int pt=df.GetStartIdx(), pti=0; pt<=df.GetEndIdx(); pt++, pti++) - { - datarray[pti] = df.Data[pt][commands_vec[thisplot]]; - } - color("red"); - curve(timarray,datarray,df.GetEndIdx()-df.GetStartIdx()+1); - delete[] datarray; - } + spread = df.Data[df.GetEndIdx()][0] - df.Data[df.GetStartIdx()][0]; - char legendtext[numtraces*(namelen)]; + if (spread < 1.0) labdig(3,"x"); + else if (spread < 10.0) labdig(2,"x"); + else if (spread < 100.0) labdig(1,"x"); + else labdig(0,"x"); - color("blue"); - legini(legendtext, numtraces, (namelen)); - legtit("Legend"); - for (thisplot=0; thisplot < numtraces; thisplot++) - { - leglin(legendtext, (char*)df.names[commands_vec[thisplot]].c_str(), thisplot+1); - } - legend(legendtext, 3); + float fac = ((int)(spread + 0.5))/10.00; -// Terminate + if (spread > 1000.0) labels("fexp","x"); + else labels("float","x"); - disfin(); + graf( df.Data[df.GetStartIdx()][0], // starttime + df.Data[df.GetEndIdx()][0], // endtime + df.Data[df.GetStartIdx()][0], // starttime + fac, + axismin, + axismax, + axismin, + (axismax - axismin)/10.0); -// Request to save + title(); + color("blue"); + grid(1,1); - if (displaytype == "CONS") - { - cout << endl << "Save graph as a .png file [y|N]: "; - cin >> savefile; - if (savefile[0] == 'y') - { - displaytype = "PNG"; - pngFName_str = dwgtxt("Enter filename:",pngFName); - if (pngFName_str.find_first_of("png",0) == string::npos) - { - pngFName_str = pngFName_str + ".png"; - } - setfil((char*)pngFName_str.c_str()); - goto savepng; - } - } - else - { - displaytype = "CONS"; + for (thisplot=0; thisplot < numtraces; thisplot++) { + double *datarray = new double[df.GetEndIdx()-df.GetStartIdx()+1]; + for (int pt=df.GetStartIdx(), pti=0; pt<=df.GetEndIdx(); pt++, pti++) { + datarray[pti] = df.Data[pt][commands_vec[thisplot]]; } + color("red"); + curve(timarray,datarray,df.GetEndIdx()-df.GetStartIdx()+1); + delete[] datarray; + } - cout << endl << "Create another plot? [Y|n]: "; - cin >> next; + char legendtext[numtraces*(namelen)]; - if (next[0] == 'n') - { - return EXIT_SUCCESS; - } - else - { - goto nextplot; + color("blue"); + legini(legendtext, numtraces, (namelen)); + legtit("Legend"); + for (thisplot=0; thisplot < numtraces; thisplot++) { + leglin(legendtext, (char*)df.names[commands_vec[thisplot]].c_str(), thisplot+1); + } + legend(legendtext, 3); + +// Terminate + + disfin(); + +// Request to save + + if (displaytype == "CONS") { + cout << endl << "Save graph as a .png file [y|N]: "; + cin >> savefile; + if (savefile[0] == 'y') { + displaytype = "PNG"; + pngFName_str = dwgtxt("Enter filename:",pngFName); + if (pngFName_str.find_first_of("png",0) == string::npos) { + pngFName_str = pngFName_str + ".png"; + } + setfil((char*)pngFName_str.c_str()); + goto savepng; } + } else { + displaytype = "CONS"; + } + + cout << endl << "Create another plot? [Y|n]: "; + cin >> next; + + if (next[0] == 'n') { + return EXIT_SUCCESS; + } else { + goto nextplot; + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% int GetID(DataFile& df, string param) { - for (unsigned int i=0; i<df.names.size(); i++) - { - if (df.names[i] == param) - { - cout << df.names[i] << endl; - return i; - } + for (unsigned int i=0; i<df.names.size(); i++) { + if (df.names[i] == param) { + cout << df.names[i] << endl; + return i; } - return -1; + } + return -1; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void plotdata(DataFile& df, plotXMLVisitor* plotVisitor) { - vector <int> IDs; - int XID; - - outfile.open("JSBSimPlots.html"); - if (!outfile) - { - cerr << "Could not open output file " << "JSBSimPlots.html" << endl; - exit(-1); - } - time_t tm = time(NULL); - - outfile << "<HTML>" << endl; - outfile << "<HEAD>" << endl; - outfile << "<TITLE>JSBSim Test Run Results</TITLE>" << endl; - outfile << "</HEAD>" << endl; - outfile << "<BODY bgColor=gainsboro>" << endl; - outfile << "<P><FONT size=4>" << endl; - outfile << "JSBSim Test Results<BR></FONT>" << endl; - outfile << "<FONT size=2 face=Arial>" << endl; + vector <int> IDs; + int XID; + + outfile.open("JSBSimPlots.html"); + if (!outfile) { + cerr << "Could not open output file " << "JSBSimPlots.html" << endl; + exit(-1); + } + time_t tm = time(NULL); + + outfile << "<HTML>" << endl; + outfile << "<HEAD>" << endl; + outfile << "<TITLE>JSBSim Test Run Results</TITLE>" << endl; + outfile << "</HEAD>" << endl; + outfile << "<BODY bgColor=gainsboro>" << endl; + outfile << "<P><FONT size=4>" << endl; + outfile << "JSBSim Test Results<BR></FONT>" << endl; + outfile << "<FONT size=2 face=Arial>" << endl; // outfile << "Test: <EM>New code for aerosurfaces</EM><BR>" << endl; - outfile << "Date: <EM>" << ctime(&tm) << "</EM>" << endl; - outfile << "</FONT><FONT face=Arial>" << endl; - outfile << "<HR style=""LEFT: 10px; WIDTH: 100%; TOP: 52px; HEIGHT: 4px"" SIZE=4 width=""100%"">" << endl; - outfile << "</FONT>" << endl; - outfile << "<P>" << endl; - outfile << "<TABLE cellSpacing=2 cellPadding=3 width=""95%"" align=center border=0>" << endl; - - for (int j=0; j<plotVisitor->vPlots.size(); j++) - { - - if (plotVisitor->vPlots[j].Autoscale) // autoscaling - { - xmin = xmax = ymin = ymax = 0.00; - autoscale = true; - cout << "Autoscaling ..." << endl; - } - else - { - autoscale = false; - xmin = plotVisitor->vPlots[j].Min[eX]; - ymin = plotVisitor->vPlots[j].Min[eY]; - xmax = plotVisitor->vPlots[j].Max[eX]; - ymax = plotVisitor->vPlots[j].Max[eY]; - } - - XID = GetID(df, plotVisitor->vPlots[j].X_Variable); - if (XID < 0) - { - cout << "ID not found for X axis parameter " << plotVisitor->vPlots[j].X_Variable << endl; - } + outfile << "Date: <EM>" << ctime(&tm) << "</EM>" << endl; + outfile << "</FONT><FONT face=Arial>" << endl; + outfile << "<HR style=""LEFT: 10px; WIDTH: 100%; TOP: 52px; HEIGHT: 4px"" SIZE=4 width=""100%"">" << endl; + outfile << "</FONT>" << endl; + outfile << "<P>" << endl; + outfile << "<TABLE cellSpacing=2 cellPadding=3 width=""95%"" align=center border=0>" << endl; + + for (int j=0; j<plotVisitor->vPlots.size(); j++) { + + if (plotVisitor->vPlots[j].Autoscale) { // autoscaling + xmin = xmax = ymin = ymax = 0.00; + autoscale = true; + cout << "Autoscaling ..." << endl; + } else { + autoscale = false; + xmin = plotVisitor->vPlots[j].Min[eX]; + ymin = plotVisitor->vPlots[j].Min[eY]; + xmax = plotVisitor->vPlots[j].Max[eX]; + ymax = plotVisitor->vPlots[j].Max[eY]; + } - IDs.clear(); - - for (int i=0; i<plotVisitor->vPlots[j].Y_Variables.size(); i++) - { - int id = GetID(df, plotVisitor->vPlots[j].Y_Variables[i]); - if (id < 0) - { - cerr << "Item[" << i << "]: " << plotVisitor->vPlots[j].Y_Variables[i] << - " not found in data file" << endl; - } - else - { - IDs.push_back(id); - plot(df, plotVisitor->vPlots[j].Title, - plotVisitor->vPlots[j].Axis_Caption[eX], - plotVisitor->vPlots[j].Axis_Caption[eY], - XID, IDs); - } - } + XID = GetID(df, plotVisitor->vPlots[j].X_Variable); + if (XID < 0) { + cout << "ID not found for X axis parameter " << plotVisitor->vPlots[j].X_Variable << endl; + } + IDs.clear(); + + for (int i=0; i<plotVisitor->vPlots[j].Y_Variables.size(); i++) { + int id = GetID(df, plotVisitor->vPlots[j].Y_Variables[i]); + if (id < 0) { + cerr << "Item[" << i << "]: " << plotVisitor->vPlots[j].Y_Variables[i] << + " not found in data file" << endl; + } else { + IDs.push_back(id); + plot(df, plotVisitor->vPlots[j].Title, + plotVisitor->vPlots[j].Axis_Caption[eX], + plotVisitor->vPlots[j].Axis_Caption[eY], + XID, IDs); + } } - outfile << " </TABLE></P>" << endl; - outfile << " </BODY>" << endl; - outfile << " </HTML>" << endl; - outfile.close(); + + } + outfile << " </TABLE></P>" << endl; + outfile << " </BODY>" << endl; + outfile << " </HTML>" << endl; + outfile.close(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void plot(DataFile& df, string Title, string xTitle, string yTitle, int XID, vector <int> IDs) { - df.SetStartIdx(0); - df.SetEndIdx(df.GetNumRecords()-1); + df.SetStartIdx(0); + df.SetEndIdx(df.GetNumRecords()-1); - metafl("PNG"); - setpag("da4l"); + metafl("PNG"); + setpag("da4l"); - disini(); // Initialization + disini(); // Initialization - pagera(); // Set Plot Parameters + pagera(); // Set Plot Parameters // hwfont(); - helve(); - shdcha(); - chncrv("color"); - - axspos(450,1800); // Set plot axis system - axslen(2200,1200); - - int thisplot; // Set plot titles - int numtraces = IDs.size(); - - name((char*)xTitle.c_str(),"x"); - name((char*)yTitle.c_str(),"y"); - labdig(3,"xy"); - ticks(10,"xy"); - titlin((char*)Title.c_str(),1); - - string subtitle = ""; - for (thisplot=0; thisplot < numtraces; thisplot++) - { - if (thisplot == 0) subtitle = df.names[IDs[thisplot]]; - else subtitle = subtitle + ", " + df.names[IDs[thisplot]]; - } + helve(); + shdcha(); + chncrv("color"); - subtitle = subtitle + string(" vs. ") + xTitle; - titlin((char*)(subtitle.c_str()),3); + axspos(450,1800); // Set plot axis system + axslen(2200,1200); -// Plot data + int thisplot; // Set plot titles + int numtraces = IDs.size(); - double *timarray = new double[df.GetEndIdx()-df.GetStartIdx()+1]; + name((char*)xTitle.c_str(),"x"); + name((char*)yTitle.c_str(),"y"); + labdig(3,"xy"); + ticks(10,"xy"); + titlin((char*)Title.c_str(),1); - for (int pt=df.GetStartIdx(), pti=0; pt<=df.GetEndIdx(); pt++, pti++) - { - timarray[pti] = df.Data[pt][XID]; - } + string subtitle = ""; + for (thisplot=0; thisplot < numtraces; thisplot++) { + if (thisplot == 0) subtitle = df.names[IDs[thisplot]]; + else subtitle = subtitle + ", " + df.names[IDs[thisplot]]; + } - float axismax = df.GetAutoAxisMax(IDs[0]); - float axismin = df.GetAutoAxisMin(IDs[0]); + subtitle = subtitle + string(" vs. ") + xTitle; + titlin((char*)(subtitle.c_str()),3); - for (thisplot=1; thisplot < numtraces; thisplot++) - { - axismax = axismax > df.GetAutoAxisMax(IDs[thisplot]) ? axismax : df.GetAutoAxisMax(IDs[thisplot]); - axismin = axismin < df.GetAutoAxisMin(IDs[thisplot]) ? axismin : df.GetAutoAxisMin(IDs[thisplot]); - } +// Plot data - float spread = axismax - axismin; + double *timarray = new double[df.GetEndIdx()-df.GetStartIdx()+1]; - if (spread < 1.0) labdig(3,"y"); - else if (spread < 10.0) labdig(2,"y"); - else if (spread < 100.0) labdig(1,"y"); - else labdig(0,"y"); + for (int pt=df.GetStartIdx(), pti=0; pt<=df.GetEndIdx(); pt++, pti++) { + timarray[pti] = df.Data[pt][XID]; + } - if (spread > 1000.0) - { - labdig(2,"y"); - labels("fexp","y"); - } - else - { - labels("float","y"); - } + float axismax = df.GetAutoAxisMax(IDs[0]); + float axismin = df.GetAutoAxisMin(IDs[0]); - if (autoscale) - { - xmin = df.Data[df.GetStartIdx()][XID]; - xmax = df.Data[df.GetEndIdx()][XID]; - ymin = axismin; - ymax = axismax; - } + for (thisplot=1; thisplot < numtraces; thisplot++) { + axismax = axismax > df.GetAutoAxisMax(IDs[thisplot]) ? axismax : df.GetAutoAxisMax(IDs[thisplot]); + axismin = axismin < df.GetAutoAxisMin(IDs[thisplot]) ? axismin : df.GetAutoAxisMin(IDs[thisplot]); + } - spread = xmax - xmin; + float spread = axismax - axismin; - if (spread < 1.0) labdig(3,"x"); - else if (spread < 10.0) labdig(2,"x"); - else if (spread < 100.0) labdig(1,"x"); - else labdig(0,"x"); + if (spread < 1.0) labdig(3,"y"); + else if (spread < 10.0) labdig(2,"y"); + else if (spread < 100.0) labdig(1,"y"); + else labdig(0,"y"); - float fac = ((int)(spread + 0.5))/10.00; + if (spread > 1000.0) { + labdig(2,"y"); + labels("fexp","y"); + } else { + labels("float","y"); + } - if (spread > 1000.0) labels("fexp","x"); - else labels("float","x"); + if (autoscale) { + xmin = df.Data[df.GetStartIdx()][XID]; + xmax = df.Data[df.GetEndIdx()][XID]; + ymin = axismin; + ymax = axismax; + } - graf( xmin, xmax, xmin, fac, ymin, ymax, ymin, (ymax - ymin)/10.0); + spread = xmax - xmin; - title(); - color("blue"); - grid(1,1); + if (spread < 1.0) labdig(3,"x"); + else if (spread < 10.0) labdig(2,"x"); + else if (spread < 100.0) labdig(1,"x"); + else labdig(0,"x"); - for (thisplot=0; thisplot < numtraces; thisplot++) - { - double *datarray = new double[df.GetEndIdx()-df.GetStartIdx()+1]; - for (int pt=df.GetStartIdx(), pti=0; pt<=df.GetEndIdx(); pt++, pti++) - { - datarray[pti] = df.Data[pt][IDs[thisplot]]; - } - color("red"); - curve(timarray,datarray,df.GetEndIdx()-df.GetStartIdx()+1); - delete[] datarray; - } + float fac = ((int)(spread + 0.5))/10.00; - size_t namelen = 0; - for (unsigned int i=0; i<df.names.size();i++) - { - namelen = namelen > df.names[i].size() ? namelen : df.names[i].size(); - } + if (spread > 1000.0) labels("fexp","x"); + else labels("float","x"); + + graf( xmin, xmax, xmin, fac, ymin, ymax, ymin, (ymax - ymin)/10.0); + + title(); + color("blue"); + grid(1,1); - char legendtext[numtraces*(namelen)]; - color("blue"); - legini(legendtext, numtraces, namelen); - legtit("Legend"); - for (thisplot=0; thisplot < numtraces; thisplot++) - { - leglin(legendtext, (char*)df.names[IDs[thisplot]].c_str(), thisplot+1); + for (thisplot=0; thisplot < numtraces; thisplot++) { + double *datarray = new double[df.GetEndIdx()-df.GetStartIdx()+1]; + for (int pt=df.GetStartIdx(), pti=0; pt<=df.GetEndIdx(); pt++, pti++) { + datarray[pti] = df.Data[pt][IDs[thisplot]]; } - legend(legendtext, 3); - - outfile << "<TR>" << endl; - outfile << " <TD style=\"WIDTH: 90px\" vAlign=top align=middle height=90>" << endl; - outfile << " <A href=" << getfil() << "><FONT face=Arial>" << endl; - outfile << " <IMG id=IMG1 style=\"LEFT: 2px; WIDTH: 85px; TOP: 14px; HEIGHT: 60px\" height=60 src=" << getfil() << " width=85 > </FONT>" << endl; - outfile << " </A>" << endl; - outfile << " </TD>" << endl; - outfile << " <TD vAlign=top align=left>" << endl; - outfile << " <FONT face=Arial size=2>" << endl; - outfile << " " << Title << endl; - outfile << " " << yTitle << " vs. " << xTitle << "<BR>" << endl; - outfile << " X Axis Min: " << xmin << " Max: " << xmax << "<BR>" << endl; - outfile << " Y Axis Min: " << ymin << " Max: " << ymax << "</H4>" << endl; - outfile << " </FONT>" << endl; - outfile << " </TD>" << endl; - outfile << "</TR>" << endl; - - disfin(); + color("red"); + curve(timarray,datarray,df.GetEndIdx()-df.GetStartIdx()+1); + delete[] datarray; + } + + size_t namelen = 0; + for (unsigned int i=0; i<df.names.size();i++) { + namelen = namelen > df.names[i].size() ? namelen : df.names[i].size(); + } + + char legendtext[numtraces*(namelen)]; + color("blue"); + legini(legendtext, numtraces, namelen); + legtit("Legend"); + for (thisplot=0; thisplot < numtraces; thisplot++) { + leglin(legendtext, (char*)df.names[IDs[thisplot]].c_str(), thisplot+1); + } + legend(legendtext, 3); + + outfile << "<TR>" << endl; + outfile << " <TD style=\"WIDTH: 90px\" vAlign=top align=middle height=90>" << endl; + outfile << " <A href=" << getfil() << "><FONT face=Arial>" << endl; + outfile << " <IMG id=IMG1 style=\"LEFT: 2px; WIDTH: 85px; TOP: 14px; HEIGHT: 60px\" height=60 src=" << getfil() << " width=85 > </FONT>" << endl; + outfile << " </A>" << endl; + outfile << " </TD>" << endl; + outfile << " <TD vAlign=top align=left>" << endl; + outfile << " <FONT face=Arial size=2>" << endl; + outfile << " " << Title << endl; + outfile << " " << yTitle << " vs. " << xTitle << "<BR>" << endl; + outfile << " X Axis Min: " << xmin << " Max: " << xmax << "<BR>" << endl; + outfile << " Y Axis Min: " << ymin << " Max: " << ymax << "</H4>" << endl; + outfile << " </FONT>" << endl; + outfile << " </TD>" << endl; + outfile << "</TR>" << endl; + + disfin(); } diff --git a/src/utilities/plotXMLVisitor.cpp b/src/utilities/plotXMLVisitor.cpp old mode 100644 new mode 100755 index 116b79f8cbd812bbffe5e75fb3ca317d0fc0759f..ca18487f449e5df7094cb013c250bc842fc976ea --- a/src/utilities/plotXMLVisitor.cpp +++ b/src/utilities/plotXMLVisitor.cpp @@ -6,9 +6,9 @@ using namespace std; plotXMLVisitor::plotXMLVisitor(void) { - first_element_read = false; - inPage = false; - axis = unset; + first_element_read = false; + inPage = false; + axis = unset; } plotXMLVisitor::~plotXMLVisitor(void) @@ -27,161 +27,117 @@ void plotXMLVisitor::endXML(void) void plotXMLVisitor::startElement (const char * name, const XMLAttributes &atts) { - current_element = name; - for (int i=0; i<atts.size();i++) - { - if (string(atts.getName(i)) == string("axis")) - { - if (string(atts.getValue(i)) == string("x")) axis = eX; - else if (string(atts.getValue(i)) == string("y2")) axis = eY2; - else axis = eY; - } - else - { - cerr << "Unknown attribute " << atts.getName(i) << " encountered." << endl; - exit (-1); - } - if (i == 1) - { - cerr << "Too many attributes. Offending attribute (item:" << i << ") is " << atts.getName(i) << endl; - exit (-1); - } + current_element = name; + for (int i=0; i<atts.size();i++) { + if (string(atts.getName(i)) == string("axis")) { + if (string(atts.getValue(i)) == string("x")) axis = eX; + else if (string(atts.getValue(i)) == string("y2")) axis = eY2; + else axis = eY; + } else { + cerr << "Unknown attribute " << atts.getName(i) << " encountered." << endl; + exit (-1); } - - if (!first_element_read) - { - if (current_element != string("plotset")) - { - cerr << endl << " This is not a valid plotset description (" << current_element << ")" << endl; - exit (-1); - } - else - { - first_element_read = true; - } + if (i == 1) { + cerr << "Too many attributes. Offending attribute (item:" << i << ") is " << atts.getName(i) << endl; + exit (-1); } + } - if (current_element == "page") - { - vPages.push_back(Page()); - inPage = true; + if (!first_element_read) { + if (current_element != string("plotset")) { + cerr << endl << " This is not a valid plotset description (" << current_element << ")" << endl; + exit (-1); + } else { + first_element_read = true; } - else if (current_element == "plot") - { - if (!inPage) - { - vPlots.push_back(Plots()); - } - else - { - vPages.back().vPlots.push_back(Plots()); - } + } + + if (current_element == "page") { + vPages.push_back(Page()); + inPage = true; + } else if (current_element == "plot") { + if (!inPage) { + vPlots.push_back(Plots()); + } else { + vPages.back().vPlots.push_back(Plots()); } + } } void plotXMLVisitor::endElement (const char * name) { - if (string(name) == string("title")) - { - if (!inPage) - vPlots.back().Title = trim(data_string); - else - vPages.back().vPlots.back().Title = trim(data_string); - } - else if (string(name) == string("label")) - { - if (axis < 0) - { - cerr << "Axis not chosen." << endl; - exit(-1); - } - if (!inPage) - vPlots.back().Axis_Caption[axis] = trim(data_string); - else - vPages.back().vPlots.back().Axis_Caption[axis] = trim(data_string); - } - else if (string(name) == string("scale")) - { - if (!inPage) - if (trim(data_string) == "auto") vPlots.back().Autoscale = true; - else - if (trim(data_string) == "auto") vPages.back().vPlots.back().Autoscale = true; - } - else if (string(name) == string("min")) - { - if (axis < 0) - { - cerr << "Axis not chosen." << endl; - exit(-1); - } - if (!inPage) - vPlots.back().Min[axis] = atof(data_string.c_str()); - else - vPages.back().vPlots.back().Min[axis] = atof(data_string.c_str()); - } - else if (string(name) == string("max")) - { - if (axis < 0) - { - cerr << "Axis not chosen." << endl; - exit(-1); - } - if (!inPage) - vPlots.back().Max[axis] = atof(data_string.c_str()); - else - vPages.back().vPlots.back().Max[axis] = atof(data_string.c_str()); - } - else if (string(name) == string("parameter")) - { - if (axis == eX) - { - if (!inPage) - vPlots.back().X_Variable = trim(data_string); - else - vPages.back().vPlots.back().X_Variable = trim(data_string); - } - else if (axis == eY) - { - if (!inPage) - vPlots.back().Y_Variables.push_back(trim(data_string)); - else - vPages.back().vPlots.back().Y_Variables.push_back(trim(data_string)); - } - else if (axis == eY2) - { - if (!inPage) - vPlots.back().Y2_Variables.push_back(trim(data_string)); - else - vPages.back().vPlots.back().Y2_Variables.push_back(trim(data_string)); - } - else - { - cerr << "Axis not chosen." << endl; - exit(-1); - } - } - else if (string(name) == string("plotset")) - { + if (string(name) == string("title")) { + if (!inPage) + vPlots.back().Title = trim(data_string); + else + vPages.back().vPlots.back().Title = trim(data_string); + } else if (string(name) == string("label")) { + if (axis < 0) { + cerr << "Axis not chosen." << endl; + exit(-1); } - else if (string(name) == string("plot")) - { + if (!inPage) + vPlots.back().Axis_Caption[axis] = trim(data_string); + else + vPages.back().vPlots.back().Axis_Caption[axis] = trim(data_string); + } else if (string(name) == string("scale")) { + if (!inPage) + if (trim(data_string) == "auto") vPlots.back().Autoscale = true; + else + if (trim(data_string) == "auto") vPages.back().vPlots.back().Autoscale = true; + } else if (string(name) == string("min")) { + if (axis < 0) { + cerr << "Axis not chosen." << endl; + exit(-1); } - else if (string(name) == string("page")) - { - inPage = false; + if (!inPage) + vPlots.back().Min[axis] = atof(data_string.c_str()); + else + vPages.back().vPlots.back().Min[axis] = atof(data_string.c_str()); + } else if (string(name) == string("max")) { + if (axis < 0) { + cerr << "Axis not chosen." << endl; + exit(-1); } + if (!inPage) + vPlots.back().Max[axis] = atof(data_string.c_str()); else - { - cerr << "Unknown data element." << endl; - exit(-1); + vPages.back().vPlots.back().Max[axis] = atof(data_string.c_str()); + } else if (string(name) == string("parameter")) { + if (axis == eX) { + if (!inPage) + vPlots.back().X_Variable = trim(data_string); + else + vPages.back().vPlots.back().X_Variable = trim(data_string); + } else if (axis == eY) { + if (!inPage) + vPlots.back().Y_Variables.push_back(trim(data_string)); + else + vPages.back().vPlots.back().Y_Variables.push_back(trim(data_string)); + } else if (axis == eY2) { + if (!inPage) + vPlots.back().Y2_Variables.push_back(trim(data_string)); + else + vPages.back().vPlots.back().Y2_Variables.push_back(trim(data_string)); + } else { + cerr << "Axis not chosen." << endl; + exit(-1); } + } else if (string(name) == string("plotset")) { + } else if (string(name) == string("plot")) { + } else if (string(name) == string("page")) { + inPage = false; + } else { + cerr << "Unknown data element." << endl; + exit(-1); + } } void plotXMLVisitor::data (const char * s, int length) { // const char *local_string = s; - data_string = s; - data_string.resize(length); + data_string = s; + data_string.resize(length); } void plotXMLVisitor::pi (const char * target, const char * data) diff --git a/src/utilities/plotXMLVisitor.h b/src/utilities/plotXMLVisitor.h old mode 100644 new mode 100755 index ec99cd2e3d9439e2b0cf4cb12c70f39efea348ff..3d61b4f74996c3e52f59818260a67bb1526f472b --- a/src/utilities/plotXMLVisitor.h +++ b/src/utilities/plotXMLVisitor.h @@ -4,29 +4,26 @@ #include <cstdio> #include <cstdlib> -struct Plots -{ - string Title; - string Axis_Caption[3]; - double Min[3], Max[3]; - bool Autoscale; - vector <string> Y_Variables; - vector <string> Y2_Variables; - string X_Variable; - - Plots(void) - { - Autoscale = true; - Min[0] = Min[1] = Min[2] = 0.0; - Max[0] = Max[1] = Max[2] = 0.0; - Title=""; - Axis_Caption[0] = Axis_Caption[1] = Axis_Caption[2] = ""; - } +struct Plots { + string Title; + string Axis_Caption[3]; + double Min[3], Max[3]; + bool Autoscale; + vector <string> Y_Variables; + vector <string> Y2_Variables; + string X_Variable; + + Plots(void) { + Autoscale = true; + Min[0] = Min[1] = Min[2] = 0.0; + Max[0] = Max[1] = Max[2] = 0.0; + Title=""; + Axis_Caption[0] = Axis_Caption[1] = Axis_Caption[2] = ""; + } }; -struct Page -{ - vector <struct Plots> vPlots; +struct Page { + vector <struct Plots> vPlots; }; enum Axis {unset=-1, eX=0, eY, eY2}; @@ -35,26 +32,26 @@ class plotXMLVisitor : public XMLVisitor { public: - plotXMLVisitor(void); - ~plotXMLVisitor(void); - - void startXML(); - void endXML(); - void startElement (const char * name, const XMLAttributes &atts); - void endElement (const char * name); - void data (const char * s, int length); - void pi (const char * target, const char * data); - void warning (const char * message, int line, int column); + plotXMLVisitor(void); + ~plotXMLVisitor(void); - vector <struct Plots> vPlots; - vector <struct Page> vPages; + void startXML(); + void endXML(); + void startElement (const char * name, const XMLAttributes &atts); + void endElement (const char * name); + void data (const char * s, int length); + void pi (const char * target, const char * data); + void warning (const char * message, int line, int column); - bool inPage; + vector <struct Plots> vPlots; + vector <struct Page> vPages; + + bool inPage; private: - bool first_element_read; - string current_element; + bool first_element_read; + string current_element; // const char* data_string; - string data_string; - Axis axis; + string data_string; + Axis axis; }; diff --git a/src/utilities/post_process.sh b/src/utilities/post_process.sh old mode 100644 new mode 100755 diff --git a/src/utilities/prep_plot.cpp b/src/utilities/prep_plot.cpp old mode 100644 new mode 100755 index 596d492487a15b8c24ae7adffe1331115084b035..c56f22d20458f64a5e5289e343425f62e06d8d65 --- a/src/utilities/prep_plot.cpp +++ b/src/utilities/prep_plot.cpp @@ -4,7 +4,7 @@ Author: Jon S. Berndt Date started: 11/24/2006 Purpose: CSV -> gnuplot prepping tool - + ------------- Copyright (C) 2006 Jon S. Berndt (jon@jsbsim.org) ------------- This program is free software; you can redistribute it and/or modify it under @@ -61,7 +61,7 @@ Compiling: g++ prep_plot.cpp plotXMLVisitor.cpp ../simgear/xml/easyxml.cxx -L ../simgear/xml/ -lExpat -o prep_plot.exe These compiler options may produce a faster executable if your machines supports it: --O9 -march=nocona +-O9 -march=nocona Usage: (note that an argument with embedded spaces needs to be surrounded by quotes) @@ -109,518 +109,458 @@ using namespace std; string plot_range; -string HaveTerm(vector <string>&, string); +string HaveTerm(vector <string>&, string); int GetTermIndex(vector <string>&, string); void EmitComparisonPlot(vector <string>&, int, string); void EmitSinglePlot(string, int, string); bool MakeArbitraryPlot( - vector <string>& files, - vector <string>& names, - struct Plots& myPlot, - string Title, - stringstream& plot); + vector <string>& files, + vector <string>& names, + struct Plots& myPlot, + string Title, + stringstream& plot); int main(int argc, char **argv) { - string in_string, var_name, input_arg, supplied_title=""; - vector <string> plotspecfiles; - vector <string> names; - int ctr=1, next_comma=0, len=0, start=0, file_ctr=0; - vector <string> files; - ifstream infile2; - char num[4]; - bool comprehensive=false; - - string start_time="", end_time=""; - - if (argc == 1) - { - cout << endl << "Usage: " << endl << endl; - cout << " prep_plot <datafile.csv> [--plot=<plot_directives.xml>] [--comp[rehensive]] [--start=<time>] [--end=<time.] [--title=<title>]" - << endl << endl; - exit(-1); + string in_string, var_name, input_arg, supplied_title=""; + vector <string> plotspecfiles; + vector <string> names; + int ctr=1, next_comma=0, len=0, start=0, file_ctr=0; + vector <string> files; + ifstream infile2; + char num[4]; + bool comprehensive=false; + + string start_time="", end_time=""; + + if (argc == 1) { + cout << endl << "Usage: " << endl << endl; + cout << " prep_plot <datafile.csv> [--plot=<plot_directives.xml>] [--comp[rehensive]] [--start=<time>] [--end=<time.] [--title=<title>]" + << endl << endl; + exit(-1); + } + + string filename(argv[1]), new_filename, Title; + + if (filename.find("#") != string::npos) { // if plotting multiple files + while (file_ctr<10) { + new_filename=filename; + sprintf(num,"%d",file_ctr); + new_filename.replace(new_filename.find("#"),1,num); + infile2.open(new_filename.c_str()); + if (!infile2.is_open()) break; + infile2.close(); + files.push_back(new_filename); + file_ctr++; } - - string filename(argv[1]), new_filename, Title; - - if (filename.find("#") != string::npos) // if plotting multiple files - { - while (file_ctr<10) - { - new_filename=filename; - sprintf(num,"%d",file_ctr); - new_filename.replace(new_filename.find("#"),1,num); - infile2.open(new_filename.c_str()); - if (!infile2.is_open()) break; - infile2.close(); - files.push_back(new_filename); - file_ctr++; - } - } - else - { - files.push_back(filename); + } else { + files.push_back(filename); + } + + ifstream infile(files[0].c_str()); + if (!infile.is_open()) { + cerr << "Could not open file: " << files[0] << endl; + exit(-1); + } + getline(infile, in_string, '\n'); + names = split(in_string, ','); + unsigned int num_names=names.size(); + + // Read command line args + + for (int i=2; i<argc; i++) { + input_arg = string(argv[i]); + if (input_arg.substr(0,6) == "--plot") { + plotspecfiles.push_back(input_arg.erase(0,7)); + } else if (input_arg.substr(0,6) == "--comp") { + comprehensive=true; + } else if (input_arg.substr(0,7) == "--title") { + supplied_title=input_arg.erase(0,8); + } else if (input_arg.substr(0,7) == "--start") { + start_time=input_arg.erase(0,8); + } else if (input_arg.substr(0,5) == "--end") { + end_time=input_arg.erase(0,6); + } else { + cerr << endl << "Unknown argument " << input_arg << endl; + exit(-1); } + } + + plot_range=""; + if (start_time.size() > 0 || end_time.size() > 0) + plot_range = "["+start_time+":"+end_time+"]"; + + cout << "set terminal postscript enhanced color \""DEFAULT_FONT"\"" << endl; + if (!supplied_title.empty()) { + cout << "set title \"" << supplied_title << "\" font \""TITLE_FONT"\"" << endl; + } + cout << "set output '" << files[0].substr(0,files[0].size()-4) << ".ps'" << endl; + + cout << "set size 1.0,1.0" << endl; + cout << "set origin 0.0,0.0" << endl; + cout << "set lmargin 6" << endl; + cout << "set rmargin 4" << endl; + cout << "set tmargin 1" << endl; + cout << "set bmargin 1" << endl; + + cout << "set datafile separator \",\"" << endl; + cout << "set grid xtics ytics" << endl; + cout << "set xtics font \""TICS_FONT"\"" << endl; + cout << "set ytics font \""TICS_FONT"\"" << endl; + cout << "set timestamp \"%d/%m/%y %H:%M\" 0,0 \""TIMESTAMP_FONT"\"" << endl; + + if (comprehensive) { + + for (unsigned int i=1;i<num_names;i++) { + + if ( i <= num_names-3 + && names[i].find("_X") != string::npos + && names[i+1].find("_Y") != string::npos + && names[i+2].find("_Z") != string::npos ) + + { // XYZ value + + if (!supplied_title.empty()) { + cout << "set title \"" << supplied_title + << "\\n" << names[i] << " vs. Time\" font \""TITLE_FONT"\"" << endl; + } - ifstream infile(files[0].c_str()); - if (!infile.is_open()) - { - cerr << "Could not open file: " << files[0] << endl; - exit(-1); - } - getline(infile, in_string, '\n'); - names = split(in_string, ','); - unsigned int num_names=names.size(); + cout << "set size 1.0,1.0" << endl; + cout << "set origin 0.0,0.0" << endl; + cout << "set multiplot" << endl; + cout << "set size 1.0,0.35" << endl; + if (files.size()==1) { // Single file + cout << "set origin 0.0,0.65" << endl; + cout << "set xlabel \"\"" << endl; + cout << "set ylabel \"" << names[i] << "\" font \""LABEL_FONT"\"" << endl; + cout << "set format x \"\"" << endl; + cout << "set timestamp \"\" 0,0 \""TIMESTAMP_FONT"\"" << endl; + EmitSinglePlot(files[0], i+1, names[i]); + + cout << "set origin 0.0,0.325" << endl; + cout << "set title \"\"" << endl; + cout << "set ylabel \"" << names[i+1] << "\" font \""LABEL_FONT"\"" << endl; + EmitSinglePlot(files[0], i+2, names[i+1]); + + cout << "set origin 0.0,0.0" << endl; + cout << "set xlabel \"Time (sec)\" font \""LABEL_FONT"\"" << endl; + cout << "set ylabel \"" << names[i+2] << "\" font \""LABEL_FONT"\"" << endl; + cout << "set format x" << endl; + cout << "set timestamp \"%d/%m/%y %H:%M\" 0,0 \""TIMESTAMP_FONT"\"" << endl; + EmitSinglePlot(files[0], i+3, names[i+2]); + + } else { // Multiple files, multiple plots per page + + // Plot 1 (top) X + cout << "set origin 0.0,0.65" << endl; + cout << "set xlabel \"\"" << endl; + cout << "set ylabel \"" << names[i] << "\" font \""LABEL_FONT"\"" << endl; + cout << "set format x \"\"" << endl; + cout << "set timestamp \"\" 0,0 \""TIMESTAMP_FONT"\"" << endl; + EmitComparisonPlot(files, i+1, names[i]); + + // Plot 2 (middle) Y + cout << "set origin 0.0,0.325" << endl; + cout << "set title \"\"" << endl; + cout << "set ylabel \"" << names[i+1] << "\" font \""LABEL_FONT"\"" << endl; + EmitComparisonPlot(files, i+2, names[i+1]); + + // Plot 3 (bottom) Z + cout << "set origin 0.0,0.00" << endl; + cout << "set xlabel \"Time (sec)\" font \""LABEL_FONT"\"" << endl; + cout << "set ylabel \"" << names[i+2] << "\" font \""LABEL_FONT"\"" << endl; + cout << "set format x" << endl; + cout << "set timestamp \"%d/%m/%y %H:%M\" 0,0 \""TIMESTAMP_FONT"\"" << endl; + EmitComparisonPlot(files, i+3, names[i+2]); + } + i += 2; + cout << "unset multiplot" << endl; + cout << "set size 1.0,1.0" << endl; + cout << "set origin 0.0,0.0" << endl; - // Read command line args + } else { // Straight single value to plot - for (int i=2; i<argc; i++) - { - input_arg = string(argv[i]); - if (input_arg.substr(0,6) == "--plot") - { - plotspecfiles.push_back(input_arg.erase(0,7)); + if (!supplied_title.empty()) { // title added + cout << "set title \"" << supplied_title + << "\\n" << names[i] << " vs. Time\" font \""TITLE_FONT"\"" << endl; } - else if (input_arg.substr(0,6) == "--comp") - { - comprehensive=true; - } - else if (input_arg.substr(0,7) == "--title") - { - supplied_title=input_arg.erase(0,8); - } - else if (input_arg.substr(0,7) == "--start") - { - start_time=input_arg.erase(0,8); + cout << "set xlabel \"Time (sec)\" font \""LABEL_FONT"\"" << endl; + cout << "set ylabel \"" << names[i] << "\" font \""LABEL_FONT"\"" << endl; + + if (files.size()==1) { // Single file + EmitSinglePlot(files[0], i+1, names[i]); + } else { // Multiple files + EmitComparisonPlot(files, i+1, names[i]); } - else if (input_arg.substr(0,5) == "--end") + } + } + } // end if comprehensive + + // special single plots + + vector <string> LeftYAxisNames; + vector <string> RightYAxisNames; + string title; + stringstream newPlot; + bool result = false; + plotXMLVisitor myVisitor; + + for (int fl=0; fl<plotspecfiles.size(); fl++) { + ifstream plotDirectivesFile(plotspecfiles[fl].c_str()); + if (!plotDirectivesFile) { + cerr << "Could not open autoplot file " << plotspecfiles[fl] << endl << endl; + exit(-1); + } else { + plotXMLVisitor *aVisitor = new plotXMLVisitor(); + myVisitor = *aVisitor; + readXML (plotDirectivesFile, myVisitor); + + for (int i=0; i<myVisitor.vPlots.size();i++) { + newPlot.str(""); + struct Plots& myPlot = myVisitor.vPlots[i]; + Title = ""; + if (!supplied_title.empty()) Title = supplied_title + string("\\n"); + newPlot << "set timestamp \"%d/%m/%y %H:%M\" 0,0 \""TIMESTAMP_FONT"\"" << endl; + result = MakeArbitraryPlot(files, names, myPlot, Title, newPlot); + if (result) cout << newPlot.str(); + } + + // special multiple plots + + for (int page=0; page<myVisitor.vPages.size(); page++) { + int numPlots = myVisitor.vPages[page].vPlots.size(); + newPlot.str(""); + + // Calculate margins smartly + float marginXLabel = 0.0; + for (int plot=1; plot<numPlots; plot++) { - end_time=input_arg.erase(0,6); + if (myVisitor.vPages[page].vPlots[plot].Axis_Caption[eX].size() > 0) { + marginXLabel = 8.0; + break; + } } - else + + float marginTitle = 0.0; + for (int plot=0; plot<numPlots-1; plot++) { - cerr << endl << "Unknown argument " << input_arg << endl; - exit(-1); + if (myVisitor.vPages[page].vPlots[plot].Title.size() > 0) { + marginTitle = 9.0; + break; + } } - } - plot_range=""; - if (start_time.size() > 0 || end_time.size() > 0) - plot_range = "["+start_time+":"+end_time+"]"; - - cout << "set terminal postscript enhanced color \""DEFAULT_FONT"\"" << endl; - if (!supplied_title.empty()) - { - cout << "set title \"" << supplied_title << "\" font \""TITLE_FONT"\"" << endl; - } - cout << "set output '" << files[0].substr(0,files[0].size()-4) << ".ps'" << endl; + float margin = (3. + marginTitle + marginXLabel)/540.; + float plot_margin = (2.*(numPlots-1.))*margin; + float size = (1.0 - plot_margin)/(float)numPlots; - cout << "set size 1.0,1.0" << endl; - cout << "set origin 0.0,0.0" << endl; - cout << "set lmargin 6" << endl; - cout << "set rmargin 4" << endl; - cout << "set tmargin 1" << endl; - cout << "set bmargin 1" << endl; + newPlot << "set size 1.0,1.0" << endl; + newPlot << "set origin 0.0,0.0" << endl; + newPlot << "set timestamp \"%d/%m/%y %H:%M\" 0,0 \""TIMESTAMP_FONT"\"" << endl; + newPlot << "set multiplot" << endl; - cout << "set datafile separator \",\"" << endl; - cout << "set grid xtics ytics" << endl; - cout << "set xtics font \""TICS_FONT"\"" << endl; - cout << "set ytics font \""TICS_FONT"\"" << endl; - cout << "set timestamp \"%d/%m/%y %H:%M\" 0,0 \""TIMESTAMP_FONT"\"" << endl; - - if (comprehensive) - { - - for (unsigned int i=1;i<num_names;i++) + for (int plot=0; plot<numPlots; plot++) { + struct Plots& myPlot = myVisitor.vPages[page].vPlots[plot]; + float position = (float)plot*(size + 2.*margin); + newPlot << "set size 1.0," << size << endl; + newPlot << "set origin 0.0," << position << endl; - if ( i <= num_names-3 - && names[i].find("_X") != string::npos - && names[i+1].find("_Y") != string::npos - && names[i+2].find("_Z") != string::npos ) - - { // XYZ value - - if (!supplied_title.empty()) - { - cout << "set title \"" << supplied_title - << "\\n" << names[i] << " vs. Time\" font \""TITLE_FONT"\"" << endl; - } - - cout << "set size 1.0,1.0" << endl; - cout << "set origin 0.0,0.0" << endl; - cout << "set multiplot" << endl; - cout << "set size 1.0,0.35" << endl; - if (files.size()==1) // Single file - { - cout << "set origin 0.0,0.65" << endl; - cout << "set xlabel \"\"" << endl; - cout << "set ylabel \"" << names[i] << "\" font \""LABEL_FONT"\"" << endl; - cout << "set format x \"\"" << endl; - cout << "set timestamp \"\" 0,0 \""TIMESTAMP_FONT"\"" << endl; - EmitSinglePlot(files[0], i+1, names[i]); - - cout << "set origin 0.0,0.325" << endl; - cout << "set title \"\"" << endl; - cout << "set ylabel \"" << names[i+1] << "\" font \""LABEL_FONT"\"" << endl; - EmitSinglePlot(files[0], i+2, names[i+1]); - - cout << "set origin 0.0,0.0" << endl; - cout << "set xlabel \"Time (sec)\" font \""LABEL_FONT"\"" << endl; - cout << "set ylabel \"" << names[i+2] << "\" font \""LABEL_FONT"\"" << endl; - cout << "set format x" << endl; - cout << "set timestamp \"%d/%m/%y %H:%M\" 0,0 \""TIMESTAMP_FONT"\"" << endl; - EmitSinglePlot(files[0], i+3, names[i+2]); - - } - else // Multiple files, multiple plots per page - { - - // Plot 1 (top) X - cout << "set origin 0.0,0.65" << endl; - cout << "set xlabel \"\"" << endl; - cout << "set ylabel \"" << names[i] << "\" font \""LABEL_FONT"\"" << endl; - cout << "set format x \"\"" << endl; - cout << "set timestamp \"\" 0,0 \""TIMESTAMP_FONT"\"" << endl; - EmitComparisonPlot(files, i+1, names[i]); - - // Plot 2 (middle) Y - cout << "set origin 0.0,0.325" << endl; - cout << "set title \"\"" << endl; - cout << "set ylabel \"" << names[i+1] << "\" font \""LABEL_FONT"\"" << endl; - EmitComparisonPlot(files, i+2, names[i+1]); - - // Plot 3 (bottom) Z - cout << "set origin 0.0,0.00" << endl; - cout << "set xlabel \"Time (sec)\" font \""LABEL_FONT"\"" << endl; - cout << "set ylabel \"" << names[i+2] << "\" font \""LABEL_FONT"\"" << endl; - cout << "set format x" << endl; - cout << "set timestamp \"%d/%m/%y %H:%M\" 0,0 \""TIMESTAMP_FONT"\"" << endl; - EmitComparisonPlot(files, i+3, names[i+2]); - } - i += 2; - cout << "unset multiplot" << endl; - cout << "set size 1.0,1.0" << endl; - cout << "set origin 0.0,0.0" << endl; - - } - else // Straight single value to plot - { - - if (!supplied_title.empty()) // title added - { - cout << "set title \"" << supplied_title - << "\\n" << names[i] << " vs. Time\" font \""TITLE_FONT"\"" << endl; - } - cout << "set xlabel \"Time (sec)\" font \""LABEL_FONT"\"" << endl; - cout << "set ylabel \"" << names[i] << "\" font \""LABEL_FONT"\"" << endl; - - if (files.size()==1) // Single file - { - EmitSinglePlot(files[0], i+1, names[i]); - } - else // Multiple files - { - EmitComparisonPlot(files, i+1, names[i]); - } - } - } - } // end if comprehensive - - // special single plots - - vector <string> LeftYAxisNames; - vector <string> RightYAxisNames; - string title; - stringstream newPlot; - bool result = false; - plotXMLVisitor myVisitor; + Title = ""; + if (!supplied_title.empty()) Title = supplied_title + string("\\n"); - for (int fl=0; fl<plotspecfiles.size(); fl++) - { - ifstream plotDirectivesFile(plotspecfiles[fl].c_str()); - if (!plotDirectivesFile) - { - cerr << "Could not open autoplot file " << plotspecfiles[fl] << endl << endl; - exit(-1); - } - else - { - plotXMLVisitor *aVisitor = new plotXMLVisitor(); - myVisitor = *aVisitor; - readXML (plotDirectivesFile, myVisitor); - - for (int i=0; i<myVisitor.vPlots.size();i++) - { - newPlot.str(""); - struct Plots& myPlot = myVisitor.vPlots[i]; - Title = ""; - if (!supplied_title.empty()) Title = supplied_title + string("\\n"); - newPlot << "set timestamp \"%d/%m/%y %H:%M\" 0,0 \""TIMESTAMP_FONT"\"" << endl; - result = MakeArbitraryPlot(files, names, myPlot, Title, newPlot); - if (result) cout << newPlot.str(); - } - - // special multiple plots - - for (int page=0; page<myVisitor.vPages.size(); page++) - { - int numPlots = myVisitor.vPages[page].vPlots.size(); - newPlot.str(""); - - // Calculate margins smartly - float marginXLabel = 0.0; - for (int plot=1; plot<numPlots; plot++) - { - if (myVisitor.vPages[page].vPlots[plot].Axis_Caption[eX].size() > 0) - { - marginXLabel = 8.0; - break; - } - } - - float marginTitle = 0.0; - for (int plot=0; plot<numPlots-1; plot++) - { - if (myVisitor.vPages[page].vPlots[plot].Title.size() > 0) - { - marginTitle = 9.0; - break; - } - } - - float margin = (3. + marginTitle + marginXLabel)/540.; - float plot_margin = (2.*(numPlots-1.))*margin; - float size = (1.0 - plot_margin)/(float)numPlots; - - newPlot << "set size 1.0,1.0" << endl; - newPlot << "set origin 0.0,0.0" << endl; - newPlot << "set timestamp \"%d/%m/%y %H:%M\" 0,0 \""TIMESTAMP_FONT"\"" << endl; - newPlot << "set multiplot" << endl; - - for (int plot=0; plot<numPlots; plot++) - { - struct Plots& myPlot = myVisitor.vPages[page].vPlots[plot]; - float position = (float)plot*(size + 2.*margin); - newPlot << "set size 1.0," << size << endl; - newPlot << "set origin 0.0," << position << endl; - - Title = ""; - if (!supplied_title.empty()) Title = supplied_title + string("\\n"); - - result = MakeArbitraryPlot(files, names, myPlot, Title, newPlot); - if (!result) break; - newPlot << "unset timestamp" << endl; - } - - newPlot << "unset multiplot" << endl; - newPlot << "set size 1.0,1.0" << endl; - newPlot << "set origin 0.0,0.0" << endl; - - if (result) cout << newPlot.str(); - } + result = MakeArbitraryPlot(files, names, myPlot, Title, newPlot); + if (!result) break; + newPlot << "unset timestamp" << endl; } + + newPlot << "unset multiplot" << endl; + newPlot << "set size 1.0,1.0" << endl; + newPlot << "set origin 0.0,0.0" << endl; + + if (result) cout << newPlot.str(); + } } + } } // ############################################################################ string HaveTerm(vector <string>& names, string parameter) { - for (unsigned int i=0; i<names.size(); i++) - { - if (names[i] == parameter.substr(0,names[i].size())) return names[i]; - } - cerr << "Could not find parameter: _" << parameter << "_" << endl; - return string(""); + for (unsigned int i=0; i<names.size(); i++) { + if (names[i] == parameter.substr(0,names[i].size())) return names[i]; + } + cerr << "Could not find parameter: _" << parameter << "_" << endl; + return string(""); } // ############################################################################ int GetTermIndex(vector <string>& names, string parameter) { - for (unsigned int i=0; i<names.size(); i++) - { - if (names[i] == parameter) return i+1; - } - return -1; + for (unsigned int i=0; i<names.size(); i++) { + if (names[i] == parameter) return i+1; + } + return -1; } // ############################################################################ bool MakeArbitraryPlot( - vector <string>& files, - vector <string>& names, - struct Plots& myPlot, - string Title, - stringstream& newPlot) + vector <string>& files, + vector <string>& names, + struct Plots& myPlot, + string Title, + stringstream& newPlot) { - bool have_all_terms=true; - int i; - vector <string> LeftYAxisNames = myPlot.Y_Variables; - vector <string> RightYAxisNames = myPlot.Y2_Variables; - string XAxisName = myPlot.X_Variable; - int numLeftYAxisNames = LeftYAxisNames.size(); - int numRightYAxisNames = RightYAxisNames.size(); - string time_range=""; - - // This line assumes time is in column 1 - if (GetTermIndex(names, XAxisName) == 1) time_range = plot_range; - - have_all_terms = have_all_terms && !HaveTerm(names, XAxisName).empty(); - for (i=0; i<numLeftYAxisNames; i++) have_all_terms = have_all_terms && !HaveTerm(names, LeftYAxisNames[i]).empty(); - for (i=0; i<numRightYAxisNames; i++) have_all_terms = have_all_terms && !HaveTerm(names, RightYAxisNames[i]).empty(); - - if (have_all_terms) - { - // Title - Title += myPlot.Title; - if (!Title.empty()) - newPlot << "set title \"" << Title << "\" font \""TITLE_FONT"\"" << endl; - else - newPlot << "unset title" << endl; - - // X axis caption - if (myPlot.Axis_Caption[eX].size() > 0) - newPlot << "set xlabel \"" << myPlot.Axis_Caption[eX] << "\" font \""LABEL_FONT"\"" << endl; - else - newPlot << "unset xlabel" << endl; - - // Left Y axis caption - if (myPlot.Axis_Caption[eY].size() > 0) - newPlot << "set ylabel \"" << myPlot.Axis_Caption[eY] << "\" font \""LABEL_FONT"\"" << endl; - else - newPlot << "unset ylabel" << endl; - - // Right Y axis caption - if (myPlot.Axis_Caption[eY2].size() > 0) - newPlot << "set y2label \"" << myPlot.Axis_Caption[eY2] << "\" font \""LABEL_FONT"\"" << endl; - else - newPlot << "unset y2label" << endl; - - if (files.size() == 1) // Single file - { + bool have_all_terms=true; + int i; + vector <string> LeftYAxisNames = myPlot.Y_Variables; + vector <string> RightYAxisNames = myPlot.Y2_Variables; + string XAxisName = myPlot.X_Variable; + int numLeftYAxisNames = LeftYAxisNames.size(); + int numRightYAxisNames = RightYAxisNames.size(); + string time_range=""; + + // This line assumes time is in column 1 + if (GetTermIndex(names, XAxisName) == 1) time_range = plot_range; + + have_all_terms = have_all_terms && !HaveTerm(names, XAxisName).empty(); + for (i=0; i<numLeftYAxisNames; i++) have_all_terms = have_all_terms && !HaveTerm(names, LeftYAxisNames[i]).empty(); + for (i=0; i<numRightYAxisNames; i++) have_all_terms = have_all_terms && !HaveTerm(names, RightYAxisNames[i]).empty(); + + if (have_all_terms) { + // Title + Title += myPlot.Title; + if (!Title.empty()) + newPlot << "set title \"" << Title << "\" font \""TITLE_FONT"\"" << endl; + else + newPlot << "unset title" << endl; + + // X axis caption + if (myPlot.Axis_Caption[eX].size() > 0) + newPlot << "set xlabel \"" << myPlot.Axis_Caption[eX] << "\" font \""LABEL_FONT"\"" << endl; + else + newPlot << "unset xlabel" << endl; - if (numRightYAxisNames > 0) - { - newPlot << "set rmargin 9" << endl; - newPlot << "set y2tics font \""TICS_FONT"\"" << endl; - } - - newPlot << "plot " << time_range << " \"" << files[0] << "\" using " << GetTermIndex(names, XAxisName) - << ":" << GetTermIndex(names, LeftYAxisNames[0]) << " with lines title \"" - << LeftYAxisNames[0] << "\""; - if (numLeftYAxisNames > 1) - { - newPlot << ", \\" << endl; - for (i=1; i<numLeftYAxisNames-1; i++) - { - newPlot << " \"" << files[0] << "\" using " << GetTermIndex(names, XAxisName) - << ":" << GetTermIndex(names, LeftYAxisNames[i]) << " with lines title \"" - << LeftYAxisNames[i] << "\", \\" << endl; - } - newPlot << " \"" << files[0] << "\" using " << GetTermIndex(names, XAxisName)<< ":" - << GetTermIndex(names, LeftYAxisNames[numLeftYAxisNames-1]) << " with lines title \"" - << LeftYAxisNames[numLeftYAxisNames-1] << "\""; - } - if (numRightYAxisNames > 0) - { - newPlot << ", \\" << endl; - for (i=0; i<numRightYAxisNames-1; i++) - { - newPlot << " \"" << files[0] << "\" using " << GetTermIndex(names, XAxisName) - << ":" << GetTermIndex(names, RightYAxisNames[i]) << " with lines axes x1y2 title \"" - << RightYAxisNames[i] << "\", \\" << endl; - } - newPlot << " \"" << files[0] << "\" using " << GetTermIndex(names, XAxisName) - << ":" << GetTermIndex(names, RightYAxisNames[numRightYAxisNames-1]) << " with lines axes x1y2 title \"" - << RightYAxisNames[numRightYAxisNames-1] << "\""; - } - newPlot << endl; - if (numRightYAxisNames > 0) - { - newPlot << "set rmargin 4" << endl; - newPlot << "unset y2tics" << endl; - newPlot << "set y2label" << endl; - } + // Left Y axis caption + if (myPlot.Axis_Caption[eY].size() > 0) + newPlot << "set ylabel \"" << myPlot.Axis_Caption[eY] << "\" font \""LABEL_FONT"\"" << endl; + else + newPlot << "unset ylabel" << endl; + // Right Y axis caption + if (myPlot.Axis_Caption[eY2].size() > 0) + newPlot << "set y2label \"" << myPlot.Axis_Caption[eY2] << "\" font \""LABEL_FONT"\"" << endl; + else + newPlot << "unset y2label" << endl; + + if (files.size() == 1) { // Single file + + if (numRightYAxisNames > 0) { + newPlot << "set rmargin 9" << endl; + newPlot << "set y2tics font \""TICS_FONT"\"" << endl; + } + + newPlot << "plot " << time_range << " \"" << files[0] << "\" using " << GetTermIndex(names, XAxisName) + << ":" << GetTermIndex(names, LeftYAxisNames[0]) << " with lines title \"" + << LeftYAxisNames[0] << "\""; + if (numLeftYAxisNames > 1) { + newPlot << ", \\" << endl; + for (i=1; i<numLeftYAxisNames-1; i++) { + newPlot << " \"" << files[0] << "\" using " << GetTermIndex(names, XAxisName) + << ":" << GetTermIndex(names, LeftYAxisNames[i]) << " with lines title \"" + << LeftYAxisNames[i] << "\", \\" << endl; + } + newPlot << " \"" << files[0] << "\" using " << GetTermIndex(names, XAxisName)<< ":" + << GetTermIndex(names, LeftYAxisNames[numLeftYAxisNames-1]) << " with lines title \"" + << LeftYAxisNames[numLeftYAxisNames-1] << "\""; + } + if (numRightYAxisNames > 0) { + newPlot << ", \\" << endl; + for (i=0; i<numRightYAxisNames-1; i++) { + newPlot << " \"" << files[0] << "\" using " << GetTermIndex(names, XAxisName) + << ":" << GetTermIndex(names, RightYAxisNames[i]) << " with lines axes x1y2 title \"" + << RightYAxisNames[i] << "\", \\" << endl; + } + newPlot << " \"" << files[0] << "\" using " << GetTermIndex(names, XAxisName) + << ":" << GetTermIndex(names, RightYAxisNames[numRightYAxisNames-1]) << " with lines axes x1y2 title \"" + << RightYAxisNames[numRightYAxisNames-1] << "\""; + } + newPlot << endl; + if (numRightYAxisNames > 0) { + newPlot << "set rmargin 4" << endl; + newPlot << "unset y2tics" << endl; + newPlot << "set y2label" << endl; + } + + } else { // Multiple file comparison plot + + if (numRightYAxisNames > 0) { + newPlot << "set rmargin 9" << endl; + newPlot << "set y2tics font \""TICS_FONT"\"" << endl; + } + + for (int f=0;f<files.size();f++) { + + if (f==0) cout << "plot " << time_range << " "; + else { + newPlot << ", \\" << endl; + newPlot << " "; } - else // Multiple file comparison plot - { - if (numRightYAxisNames > 0) - { - newPlot << "set rmargin 9" << endl; - newPlot << "set y2tics font \""TICS_FONT"\"" << endl; - } - - for (int f=0;f<files.size();f++) - { - - if (f==0) cout << "plot " << time_range << " "; - else - { - newPlot << ", \\" << endl; - newPlot << " "; - } - - newPlot << "\"" << files[f] << "\" using " << GetTermIndex(names, XAxisName) - << ":" << GetTermIndex(names, LeftYAxisNames[0]) << " with lines title \"" - << LeftYAxisNames[0] << ": " << f << "\""; - if (numLeftYAxisNames > 1) - { - newPlot << ", \\" << endl; - for (i=1; i<numLeftYAxisNames-1; i++) - { - newPlot << " \"" << files[f] << "\" using " << GetTermIndex(names, XAxisName) - << ":" << GetTermIndex(names, LeftYAxisNames[i]) << " with lines title \"" - << LeftYAxisNames[i] << ": " << f << "\", \\" << endl; - } - newPlot << " \"" << files[f] << "\" using " << GetTermIndex(names, XAxisName)<< ":" - << GetTermIndex(names, LeftYAxisNames[numLeftYAxisNames-1]) << " with lines title \"" - << LeftYAxisNames[numLeftYAxisNames-1] << ": " << f << "\""; - } - if (numRightYAxisNames > 0) - { - newPlot << ", \\" << endl; - for (i=0; i<numRightYAxisNames-2; i++) - { - newPlot << " \"" << files[f] << "\" using " << GetTermIndex(names, XAxisName) - << ":" << GetTermIndex(names, RightYAxisNames[i]) << " with lines axes x1y2 title \"" - << RightYAxisNames[i] << ": " << f << "\", \\" << endl; - } - newPlot << " \"" << files[f] << "\" using " << GetTermIndex(names, XAxisName) - << ":" << GetTermIndex(names, RightYAxisNames[numRightYAxisNames-1]) << " with lines axes x1y2 title \"" - << RightYAxisNames[numRightYAxisNames-1] << ": " << f << "\""; - } - } - newPlot << endl; - if (numRightYAxisNames > 0) - { - newPlot << "set rmargin 4" << endl; - newPlot << "unset y2tics" << endl; - newPlot << "set y2label" << endl; - } + newPlot << "\"" << files[f] << "\" using " << GetTermIndex(names, XAxisName) + << ":" << GetTermIndex(names, LeftYAxisNames[0]) << " with lines title \"" + << LeftYAxisNames[0] << ": " << f << "\""; + if (numLeftYAxisNames > 1) { + newPlot << ", \\" << endl; + for (i=1; i<numLeftYAxisNames-1; i++) { + newPlot << " \"" << files[f] << "\" using " << GetTermIndex(names, XAxisName) + << ":" << GetTermIndex(names, LeftYAxisNames[i]) << " with lines title \"" + << LeftYAxisNames[i] << ": " << f << "\", \\" << endl; + } + newPlot << " \"" << files[f] << "\" using " << GetTermIndex(names, XAxisName)<< ":" + << GetTermIndex(names, LeftYAxisNames[numLeftYAxisNames-1]) << " with lines title \"" + << LeftYAxisNames[numLeftYAxisNames-1] << ": " << f << "\""; } + if (numRightYAxisNames > 0) { + newPlot << ", \\" << endl; + for (i=0; i<numRightYAxisNames-2; i++) { + newPlot << " \"" << files[f] << "\" using " << GetTermIndex(names, XAxisName) + << ":" << GetTermIndex(names, RightYAxisNames[i]) << " with lines axes x1y2 title \"" + << RightYAxisNames[i] << ": " << f << "\", \\" << endl; + } + newPlot << " \"" << files[f] << "\" using " << GetTermIndex(names, XAxisName) + << ":" << GetTermIndex(names, RightYAxisNames[numRightYAxisNames-1]) << " with lines axes x1y2 title \"" + << RightYAxisNames[numRightYAxisNames-1] << ": " << f << "\""; + } + } + newPlot << endl; + if (numRightYAxisNames > 0) { + newPlot << "set rmargin 4" << endl; + newPlot << "unset y2tics" << endl; + newPlot << "set y2label" << endl; + } } - return have_all_terms; + } + return have_all_terms; } // ############################################################################ void EmitSinglePlot(string filename, int index, string linetitle ) { - cout << "plot " << plot_range << " \"" << filename << "\" using 1:" << index << " with lines title \"" << linetitle << "\"" << endl; + cout << "plot " << plot_range << " \"" << filename << "\" using 1:" << index << " with lines title \"" << linetitle << "\"" << endl; } // ############################################################################ void EmitComparisonPlot(vector <string>& filenames, int index, string linetitle) { - cout << "plot " << plot_range << " \"" << filenames[0] << "\" using 1:" << index << " with lines title \"" << linetitle << ": 1" << "\", \\" << endl; - for (unsigned int f=1;f<filenames.size()-1;f++) - { - cout << "\"" << filenames[f] << "\" using 1:" << index << " with lines title \"" << linetitle << ": " << f+1 << "\", \\" << endl; - } - cout << "\"" << filenames[filenames.size()-1] << "\" using 1:" << index << " with lines title \"" << linetitle << ": " << filenames.size() << "\"" << endl; + cout << "plot " << plot_range << " \"" << filenames[0] << "\" using 1:" << index << " with lines title \"" << linetitle << ": 1" << "\", \\" << endl; + for (unsigned int f=1;f<filenames.size()-1;f++){ + cout << "\"" << filenames[f] << "\" using 1:" << index << " with lines title \"" << linetitle << ": " << f+1 << "\", \\" << endl; + } + cout << "\"" << filenames[filenames.size()-1] << "\" using 1:" << index << " with lines title \"" << linetitle << ": " << filenames.size() << "\"" << endl; } diff --git a/src/utilities/prep_plot.vcproj b/src/utilities/prep_plot.vcproj old mode 100644 new mode 100755 diff --git a/systems/GNCUtilities.xml b/systems/GNCUtilities.xml old mode 100644 new mode 100755 diff --git a/templates/template.am b/templates/template.am deleted file mode 100644 index 592af124eb75b8b310a6317c61472ebedacbc6d4..0000000000000000000000000000000000000000 --- a/templates/template.am +++ /dev/null @@ -1,19 +0,0 @@ -# -# @FILE@.am -# Copyright (C) @FIRSTNAME@ @LASTNAME@ @YEAR@ <@EMAIL@> -# -# @FILE@.am 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, either version 2 of the License, or -# (at your option) any later version. -# -# @FILE@.am 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, see <http://www.gnu.org/licenses/>. -# - -# vim:ts=4:sw=4 diff --git a/templates/template.c b/templates/template.c deleted file mode 100644 index 5cde7401b023e7890adc7a88a090301cf4096ccb..0000000000000000000000000000000000000000 --- a/templates/template.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * @FILE@.c - * Copyright (C) @FIRSTNAME@ @LASTNAME@ @YEAR@ <@EMAIL@> - * - * @FILE@.c 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, either version 2 of the License, or - * (at your option) any later version. - * - * @FILE@.c 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, see <http://www.gnu.org/licenses/>. - */ - -// vim:ts=4:sw=4 diff --git a/templates/template.cpp b/templates/template.cpp deleted file mode 100644 index 91b4d22d517b5366a3e1d2f6ef35706095c3ec8a..0000000000000000000000000000000000000000 --- a/templates/template.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * @CLASS@.cpp - * Copyright (C) @FIRSTNAME@ @LASTNAME@ @YEAR@ <@EMAIL@> - * - * @CLASS@.cpp 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, either version 2 of the License, or - * (at your option) any later version. - * - * @CLASS@.cpp 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, see <http://www.gnu.org/licenses/>. - */ - -#include "@CLASS@.h" - -namespace @NAMESPACE@ -{ - -@CLASS@::@CLASS@() -{ -} - -@CLASS@::~@CLASS@() -{ -} - -} // @NAMESPACE@ - - -// vim:ts=4:sw=4 diff --git a/templates/template.h b/templates/template.h deleted file mode 100644 index 148a891f8780e4e7318de840eb61271799f6d403..0000000000000000000000000000000000000000 --- a/templates/template.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * @CLASS@.h - * Copyright (C) @FIRSTNAME@ @LASTNAME@ @YEAR@ <@EMAIL@> - * - * @CLASS@.h 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, either version 2 of the License, or - * (at your option) any later version. - * - * @CLASS@.h 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, see <http://www.gnu.org/licenses/>. - */ - -#ifndef @NAMESPACE@_@CLASS@_H -#define @NAMESPACE@_@CLASS@_H - -namespace @NAMESPACE@ -{ - -class @CLASS@ -{ -public: - @CLASS@(); - virtual ~@CLASS@(); -private: -}; - -} // @NAMESPACE@ - -#endif - -// vim:ts=4:sw=4 diff --git a/templates/template.sh b/templates/template.sh deleted file mode 100755 index a10f74df5dc9dfa8bd6406e8af3aaed581143e41..0000000000000000000000000000000000000000 --- a/templates/template.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -# -# @FILE@.sh -# Copyright (C) @FIRSTNAME@ @LASTNAME@ @YEAR@ <@EMAIL@> -# -# @FILE@.sh 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, either version 2 of the License, or -# (at your option) any later version. -# -# @FILE@.sh 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, see <http://www.gnu.org/licenses/>. -# - -# vim:ts=4:sw=4