LCOV - code coverage report
Current view: top level - models/propulsion - FGEngine.cpp (source / functions) Hit Total Coverage
Test: JSBSim-Coverage-Statistics Lines: 117 174 67.2 %
Date: 2010-08-24 Functions: 10 17 58.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 25 108 23.1 %

           Branch data     Line data    Source code
       1                 :            : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       2                 :            : 
       3                 :            :  Module:       FGEngine.cpp
       4                 :            :  Author:       Jon Berndt
       5                 :            :  Date started: 01/21/99
       6                 :            :  Called by:    FGAircraft
       7                 :            : 
       8                 :            :  ------------- Copyright (C) 1999  Jon S. Berndt (jon@jsbsim.org) -------------
       9                 :            : 
      10                 :            :  This program is free software; you can redistribute it and/or modify it under
      11                 :            :  the terms of the GNU Lesser General Public License as published by the Free Software
      12                 :            :  Foundation; either version 2 of the License, or (at your option) any later
      13                 :            :  version.
      14                 :            : 
      15                 :            :  This program is distributed in the hope that it will be useful, but WITHOUT
      16                 :            :  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      17                 :            :  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
      18                 :            : 
      19                 :            :  You should have received a copy of the GNU Lesser General Public License along with
      20                 :            :  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
      21                 :            :  Place - Suite 330, Boston, MA  02111-1307, USA.
      22                 :            : 
      23                 :            :  Further information about the GNU Lesser General Public License can also be found on
      24                 :            :  the world wide web at http://www.gnu.org.
      25                 :            : 
      26                 :            : FUNCTIONAL DESCRIPTION
      27                 :            : --------------------------------------------------------------------------------
      28                 :            : See header file.
      29                 :            : 
      30                 :            : HISTORY
      31                 :            : --------------------------------------------------------------------------------
      32                 :            : 01/21/99   JSB   Created
      33                 :            : 09/03/99   JSB   Changed Rocket thrust equation to correct -= Thrust instead of
      34                 :            :                  += Thrust (thanks to Tony Peden)
      35                 :            : 
      36                 :            : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      37                 :            : INCLUDES
      38                 :            : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
      39                 :            : 
      40                 :            : #include "FGEngine.h"
      41                 :            : #include "FGTank.h"
      42                 :            : #include "FGPropeller.h"
      43                 :            : #include "FGNozzle.h"
      44                 :            : #include "FGRotor.h"
      45                 :            : #include "models/FGPropulsion.h"
      46                 :            : #include "input_output/FGXMLParse.h"
      47                 :            : #include "math/FGColumnVector3.h"
      48                 :            : 
      49                 :            : #include <iostream>
      50                 :            : #include <fstream>
      51                 :            : #include <cstdlib>
      52                 :            : 
      53                 :            : using namespace std;
      54                 :            : 
      55                 :            : namespace JSBSim {
      56                 :            : 
      57                 :            : static const char *IdSrc = "$Id: FGEngine.cpp,v 1.39 2010/08/21 17:13:48 jberndt Exp $";
      58                 :            : static const char *IdHdr = ID_ENGINE;
      59                 :            : 
      60                 :            : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      61                 :            : CLASS IMPLEMENTATION
      62                 :            : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
      63                 :            : 
      64                 :         12 : FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
      65                 :         12 :                       : EngineNumber(engine_number)
      66                 :            : {
      67                 :            :   Element* local_element;
      68                 :         12 :   FGColumnVector3 location, orientation;
      69                 :            : 
      70                 :         12 :   Name = "";
      71                 :         12 :   Type = etUnknown;
      72                 :         12 :   X = Y = Z = 0.0;
      73                 :         12 :   EnginePitch = EngineYaw = 0.0;
      74                 :         12 :   SLFuelFlowMax = 0.0;
      75                 :         12 :   MaxThrottle = 1.0;
      76                 :         12 :   MinThrottle = 0.0;
      77                 :         12 :   FuelDensity = 6.0;
      78                 :            :   unsigned int i;
      79                 :            : 
      80                 :         12 :   ResetToIC(); // initialize dynamic terms
      81                 :            : 
      82                 :         12 :   FDMExec = exec;
      83                 :         24 :   Atmosphere = FDMExec->GetAtmosphere();
      84                 :         24 :   FCS = FDMExec->GetFCS();
      85                 :         24 :   Propulsion = FDMExec->GetPropulsion();
      86                 :         24 :   Aircraft = FDMExec->GetAircraft();
      87                 :         24 :   Propagate = FDMExec->GetPropagate();
      88                 :         24 :   Auxiliary = FDMExec->GetAuxiliary();
      89                 :            : 
      90                 :         12 :   PropertyManager = FDMExec->GetPropertyManager();
      91                 :            : 
      92                 :         24 :   Name = engine_element->GetAttributeValue("name");
      93                 :            : 
      94                 :         12 :   Load(engine_element, PropertyManager, to_string(EngineNumber)); // Call ModelFunctions loader
      95                 :            : 
      96                 :            : // Find and set engine location
      97                 :            : 
      98                 :         12 :   local_element = engine_element->GetParent()->FindElement("location");
      99 [ #  # ][ +  - ]:         12 :   if (local_element)  location = local_element->FindElementTripletConvertTo("IN");
     100                 :          0 :   else      cerr << "No engine location found for this engine." << endl;
     101                 :            : 
     102                 :         12 :   local_element = engine_element->GetParent()->FindElement("orient");
     103 [ #  # ][ -  + ]:         12 :   if (local_element)  orientation = local_element->FindElementTripletConvertTo("RAD");
     104                 :            : //  else          cerr << "No engine orientation found for this engine." << endl;
     105                 :            : // Jon: The engine orientation has a default and is not normally used.
     106                 :            : 
     107                 :            :   SetPlacement(location, orientation);
     108                 :            : 
     109                 :            :   // Load thruster
     110                 :         12 :   local_element = engine_element->GetParent()->FindElement("thruster");
     111   [ #  #  +  - ]:         12 :   if (local_element) {
     112 [ #  # ][ -  + ]:         12 :     if (!LoadThruster(local_element)) exit(-1);
     113                 :            :   } else {
     114                 :          0 :     cerr << "No thruster definition supplied with engine definition." << endl;
     115                 :            :   }
     116                 :            : 
     117                 :            :   // Build and initialize the feed tank vector.
     118 [ #  # ][ +  + ]:         84 :   for (i=0; i<(Propulsion->GetNumTanks()); i++) {
     119                 :         72 :     SourceTanks.push_back(0);
     120                 :            :   }
     121                 :            : 
     122                 :            :   // Load feed tank[s] references
     123                 :         12 :   local_element = engine_element->GetParent()->FindElement("feed");
     124   [ #  #  +  - ]:         12 :   if (local_element) {
     125 [ #  # ][ +  + ]:         34 :     while (local_element) {
     126                 :         22 :       int tankID = (int)local_element->GetDataAsNumber();
     127                 :         44 :       FGTank* tank = Propulsion->GetTank(tankID); 
     128 [ #  # ][ +  - ]:         22 :       if (tank) {
     129                 :            :         AddFeedTank(tankID, tank->GetPriority());
     130                 :         22 :         FuelDensity = tank->GetDensity();
     131                 :            :       } else {
     132                 :            :         cerr << "Feed tank " << tankID <<
     133                 :          0 :           " specified in engine definition does not exist." << endl;
     134                 :            :       }
     135                 :         22 :       local_element = engine_element->GetParent()->FindNextElement("feed");
     136                 :            :     }
     137                 :            :   } else {
     138                 :          0 :     cerr << "No feed tank specified in engine definition." << endl;
     139                 :            :   }
     140                 :            : 
     141                 :         12 :   string property_name, base_property_name;
     142                 :         24 :   base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
     143                 :            : 
     144                 :         24 :   property_name = base_property_name + "/set-running";
     145                 :         12 :   PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetRunning, &FGEngine::SetRunning );
     146                 :         24 :   property_name = base_property_name + "/thrust-lbs";
     147                 :         12 :   PropertyManager->Tie( property_name.c_str(), Thruster, &FGThruster::GetThrust);
     148                 :         24 :   property_name = base_property_name + "/fuel-flow-rate-pps";
     149                 :         12 :   PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate);
     150                 :            : 
     151                 :         12 :   PostLoad(engine_element, PropertyManager, to_string(EngineNumber));
     152                 :            : 
     153                 :            :   //cout << "Engine[" << EngineNumber << "] using fuel density: " << FuelDensity << endl;
     154                 :            : 
     155                 :         12 :   Debug(0);
     156                 :         12 : }
     157                 :            : 
     158                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     159                 :            : 
     160                 :         12 : FGEngine::~FGEngine()
     161                 :            : {
     162 [ #  # ][ #  # ]:         12 :   delete Thruster;
                 [ +  - ]
     163                 :         12 :   Debug(1);
     164 [ #  # ][ #  # ]:         24 : }
                 [ -  + ]
     165                 :            : 
     166                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     167                 :            : 
     168                 :         12 : void FGEngine::ResetToIC(void)
     169                 :            : {
     170                 :         12 :   Throttle = 0.0;
     171                 :         12 :   Mixture = 1.0;
     172                 :         12 :   Starter = false;
     173                 :         12 :   FuelExpended = 0.0;
     174                 :         12 :   Starved = Running = Cranking = false;
     175                 :         12 :   PctPower = 0.0;
     176                 :         12 :   TrimMode = false;
     177                 :         12 :   FuelFlow_gph = 0.0;
     178                 :         12 :   FuelFlow_pph = 0.0;
     179                 :         12 :   FuelFlowRate = 0.0;
     180                 :         12 :   FuelFreeze = false;
     181                 :         12 : }
     182                 :            : 
     183                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     184                 :            : // This base class function should be called from within the
     185                 :            : // derived class' Calculate() function before any other calculations are done.
     186                 :            : // This base class method removes fuel from the fuel tanks as appropriate,
     187                 :            : // and sets the starved flag if necessary.
     188                 :            : // This version of the fuel consumption code should never see an oxidizer tank.
     189                 :            : 
     190                 :          0 : void FGEngine::ConsumeFuel(void)
     191                 :            : {
     192         [ #  # ]:          0 :   if (FuelFreeze) return;
     193         [ #  # ]:          0 :   if (TrimMode) return;
     194                 :            : 
     195                 :            :   unsigned int i;
     196                 :            :   double Fshortage, FuelNeeded;
     197                 :            :   FGTank* Tank;
     198                 :          0 :   unsigned int TanksWithFuel = 0;
     199                 :          0 :   Fshortage = FuelNeeded = 0.0;
     200                 :            :   double FuelToBurn;
     201                 :          0 :   unsigned int CurrentPriority = 1;
     202                 :            :   vector <int> FeedList;
     203                 :          0 :   Starved = false;
     204                 :            : 
     205                 :          0 :   FuelToBurn = CalcFuelNeed();
     206         [ #  # ]:          0 :   if (FuelToBurn == 0.0) return;
     207                 :            : 
     208                 :            :   // Count how many fuel tanks with the current priority level have fuel.
     209                 :            :   // If none, then try next lower priority.  Build the feed list.
     210 [ #  # ][ #  # ]:          0 :   while ((TanksWithFuel == 0) && (CurrentPriority <= Propulsion->GetNumTanks())) {
                 [ #  # ]
     211         [ #  # ]:          0 :     for (i=0; i<Propulsion->GetNumTanks(); i++) {
     212         [ #  # ]:          0 :       if (SourceTanks[i] != 0) {
     213                 :          0 :         Tank = Propulsion->GetTank(i);
     214         [ #  # ]:          0 :         if (Tank->GetType() == FGTank::ttFUEL) {
     215 [ #  # ][ #  # ]:          0 :           if ((Tank->GetContents() > 0.0) && ((unsigned int)Tank->GetPriority() == CurrentPriority)) {
                 [ #  # ]
     216                 :          0 :              ++TanksWithFuel;
     217                 :          0 :              FeedList.push_back(i);
     218                 :            :            } 
     219                 :            :         } else {
     220                 :          0 :            cerr << "No oxidizer tanks should be used for this engine type." << endl;
     221                 :            :         }
     222                 :            :       }
     223                 :            :     }
     224         [ #  # ]:          0 :     if (TanksWithFuel == 0) CurrentPriority++;
     225                 :            :   }
     226                 :            : 
     227                 :            :   // No fuel found at any priority!
     228         [ #  # ]:          0 :   if (TanksWithFuel == 0) {
     229                 :          0 :     Starved = true;
     230                 :            :     return;
     231                 :            :   }
     232                 :            : 
     233                 :            :   // Remove equal amount of fuel from each feed tank.  
     234                 :          0 :   FuelNeeded = FuelToBurn/TanksWithFuel;
     235         [ #  # ]:          0 :   for (i=0; i<FeedList.size(); i++) {
     236                 :          0 :     Tank = Propulsion->GetTank(FeedList[i]);
     237                 :          0 :     Tank->Drain(FuelNeeded); 
     238                 :          0 :   }
     239                 :            : 
     240                 :            : }
     241                 :            : 
     242                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     243                 :            : 
     244                 :          0 : double FGEngine::CalcFuelNeed(void)
     245                 :            : {
     246                 :          0 :   double dT = FDMExec->GetDeltaT()*Propulsion->GetRate();
     247                 :          0 :   FuelFlowRate = SLFuelFlowMax*PctPower;
     248                 :          0 :   FuelExpended = FuelFlowRate*dT;
     249                 :          0 :   return FuelExpended;
     250                 :            : }
     251                 :            : 
     252                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     253                 :            : 
     254                 :          0 : void FGEngine::SetPlacement(FGColumnVector3& location, FGColumnVector3& orientation)
     255                 :            : {
     256                 :         12 :   X = location(eX);
     257                 :         12 :   Y = location(eY);
     258                 :         12 :   Z = location(eZ);
     259                 :         12 :   EnginePitch = orientation(ePitch);
     260                 :         12 :   EngineYaw = orientation (eYaw);
     261                 :          0 : }
     262                 :            : 
     263                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     264                 :            : 
     265                 :          0 : void FGEngine::AddFeedTank(int tkID, int priority)
     266                 :            : {
     267                 :         44 :   SourceTanks[tkID] = priority;
     268                 :          0 : }
     269                 :            : 
     270                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     271                 :            : 
     272                 :     648060 : FGColumnVector3& FGEngine::GetBodyForces(void)
     273                 :            : {
     274                 :     648060 :   return Thruster->GetBodyForces();
     275                 :            : }
     276                 :            : 
     277                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     278                 :            : 
     279                 :     648060 : FGColumnVector3& FGEngine::GetMoments(void)
     280                 :            : {
     281                 :     648060 :   return Thruster->GetMoments();
     282                 :            : }
     283                 :            : 
     284                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     285                 :            : 
     286                 :         12 : bool FGEngine::LoadThruster(Element *thruster_element)
     287                 :            : {
     288                 :         12 :   string token, fullpath, localpath;
     289                 :         12 :   string thruster_filename, thruster_fullpathname, thrType;
     290                 :         12 :   string enginePath = FDMExec->GetEnginePath();
     291                 :         12 :   string aircraftPath = FDMExec->GetFullAircraftPath();
     292                 :         12 :   ifstream thruster_file;
     293                 :         12 :   FGColumnVector3 location, orientation;
     294                 :         12 :   string separator = "/";
     295                 :            : 
     296                 :         24 :   fullpath = enginePath + separator;
     297                 :         24 :   localpath = aircraftPath + separator + "Engines" + separator;
     298                 :            : 
     299                 :         24 :   thruster_filename = thruster_element->GetAttributeValue("file");
     300         [ +  - ]:         12 :   if ( !thruster_filename.empty()) {
     301                 :         24 :     thruster_fullpathname = fullpath + thruster_filename + ".xml";
     302                 :         12 :     thruster_file.open(thruster_fullpathname.c_str());
     303         [ -  + ]:         12 :     if ( !thruster_file.is_open()) {
     304                 :          0 :       thruster_fullpathname = localpath + thruster_filename + ".xml";
     305                 :          0 :       thruster_file.open(thruster_fullpathname.c_str());
     306         [ #  # ]:          0 :       if ( !thruster_file.is_open()) {
     307                 :          0 :         cerr << "Could not open thruster file: " << thruster_filename << ".xml" << endl;
     308                 :          0 :         return false;
     309                 :            :       } else {
     310                 :          0 :         thruster_file.close();
     311                 :            :       }
     312                 :            :     } else {
     313                 :         12 :       thruster_file.close();
     314                 :            :     }
     315                 :            :   } else {
     316                 :          0 :     cerr << "No thruster filename given." << endl;
     317                 :          0 :     return false;
     318                 :            :   }
     319                 :            : 
     320                 :         24 :   document = LoadXMLDocument(thruster_fullpathname);
     321                 :         12 :   document->SetParent(thruster_element);
     322                 :            : 
     323                 :         12 :   thrType = document->GetName();
     324                 :            : 
     325         [ -  + ]:         12 :   if (thrType == "propeller") {
     326                 :          0 :     Thruster = new FGPropeller(FDMExec, document, EngineNumber);
     327         [ +  - ]:         12 :   } else if (thrType == "nozzle") {
     328                 :         12 :     Thruster = new FGNozzle(FDMExec, document, EngineNumber);
     329         [ #  # ]:          0 :   } else if (thrType == "rotor") {
     330                 :          0 :     Thruster = new FGRotor(FDMExec, document, EngineNumber);
     331         [ #  # ]:          0 :   } else if (thrType == "direct") {
     332                 :          0 :     Thruster = new FGThruster( FDMExec, document, EngineNumber);
     333                 :            :   }
     334                 :            : 
     335                 :         12 :   Thruster->SetdeltaT(FDMExec->GetDeltaT() * Propulsion->GetRate());
     336                 :            : 
     337                 :         12 :   Debug(2);
     338                 :         12 :   return true;
     339                 :            : }
     340                 :            : 
     341                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     342                 :            : //    The bitmasked value choices are as follows:
     343                 :            : //    unset: In this case (the default) JSBSim would only print
     344                 :            : //       out the normally expected messages, essentially echoing
     345                 :            : //       the config files as they are read. If the environment
     346                 :            : //       variable is not set, debug_lvl is set to 1 internally
     347                 :            : //    0: This requests JSBSim not to output any messages
     348                 :            : //       whatsoever.
     349                 :            : //    1: This value explicity requests the normal JSBSim
     350                 :            : //       startup messages
     351                 :            : //    2: This value asks for a message to be printed out when
     352                 :            : //       a class is instantiated
     353                 :            : //    4: When this value is set, a message is displayed when a
     354                 :            : //       FGModel object executes its Run() method
     355                 :            : //    8: When this value is set, various runtime state variables
     356                 :            : //       are printed out periodically
     357                 :            : //    16: When set various parameters are sanity checked and
     358                 :            : //       a message is printed out when they go out of bounds
     359                 :            : 
     360                 :         36 : void FGEngine::Debug(int from)
     361                 :            : {
     362         [ +  - ]:         36 :   if (debug_lvl <= 0) return;
     363                 :            : 
     364         [ +  - ]:         36 :   if (debug_lvl & 1) { // Standard console startup message output
     365                 :            :     if (from == 0) { // Constructor
     366                 :            : 
     367                 :            :     }
     368         [ +  + ]:         36 :     if (from == 2) { // After thruster loading
     369                 :         12 :       cout << "      X = " << Thruster->GetLocationX() << endl;
     370                 :         12 :       cout << "      Y = " << Thruster->GetLocationY() << endl;
     371                 :         12 :       cout << "      Z = " << Thruster->GetLocationZ() << endl;
     372                 :         24 :       cout << "      Pitch = " << radtodeg*Thruster->GetAnglesToBody(ePitch) << " degrees" << endl;
     373                 :         24 :       cout << "      Yaw = " << radtodeg*Thruster->GetAnglesToBody(eYaw) << " degrees" << endl;
     374                 :            :     }
     375                 :            :   }
     376         [ -  + ]:         36 :   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
     377         [ #  # ]:          0 :     if (from == 0) cout << "Instantiated: FGEngine" << endl;
     378         [ #  # ]:          0 :     if (from == 1) cout << "Destroyed:    FGEngine" << endl;
     379                 :            :   }
     380                 :         36 :   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
     381                 :            :   }
     382                 :         36 :   if (debug_lvl & 8 ) { // Runtime state variables
     383                 :            :   }
     384                 :         36 :   if (debug_lvl & 16) { // Sanity checking
     385                 :            :   }
     386         [ -  + ]:         36 :   if (debug_lvl & 64) {
     387         [ #  # ]:          0 :     if (from == 0) { // Constructor
     388                 :          0 :       cout << IdSrc << endl;
     389                 :          0 :       cout << IdHdr << endl;
     390                 :            :     }
     391                 :            :   }
     392                 :            : }
     393 [ +  + ][ +  - ]:         12 : }

Generated by: LCOV version 1.9