X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FFDM%2FJSBSim%2Fmodels%2FFGPropulsion.cpp;h=bb260f09bbafa291e7baad01e3cc64e151cd376b;hb=a302cdc1cbb3c147e7c862b484cdd5d86f30a29c;hp=306126ccac78ad3aa6a11ae47d6ef799b54eb413;hpb=932b38a87e2870d23f9be9461b551f1e1fe556ba;p=flightgear.git diff --git a/src/FDM/JSBSim/models/FGPropulsion.cpp b/src/FDM/JSBSim/models/FGPropulsion.cpp index 306126cca..bb260f09b 100644 --- a/src/FDM/JSBSim/models/FGPropulsion.cpp +++ b/src/FDM/JSBSim/models/FGPropulsion.cpp @@ -6,23 +6,23 @@ Purpose: Encapsulates the set of engines and tanks associated with this aircraft - ------------- Copyright (C) 2000 Jon S. Berndt (jsb@hal-pc.org) ------------- + ------------- Copyright (C) 2000 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 General Public License as published by the Free Software + 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 General Public License for more + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - You should have received a copy of the GNU General Public License along with + 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 General Public License can also be found on + 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 @@ -45,19 +45,27 @@ INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include "FGPropulsion.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "models/FGFCS.h" +#include "models/FGMassBalance.h" +#include "models/propulsion/FGThruster.h" +#include "models/propulsion/FGRocket.h" +#include "models/propulsion/FGTurbine.h" +#include "models/propulsion/FGPiston.h" +#include "models/propulsion/FGElectric.h" +#include "models/propulsion/FGTurboProp.h" +#include "models/propulsion/FGTank.h" +#include "input_output/FGPropertyManager.h" +#include "input_output/FGXMLParse.h" +#include "math/FGColumnVector3.h" +#include #include +#include + +using namespace std; namespace JSBSim { -static const char *IdSrc = "$Id$"; +static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.46 2011/05/20 03:18:36 jberndt Exp $"; static const char *IdHdr = ID_PROPULSION; extern short debug_lvl; @@ -71,12 +79,14 @@ 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 = false; + refuel = dump = false; + DumpRate = 0.0; fuel_freeze = false; TotalFuelQuantity = 0.0; IsBound = @@ -85,6 +95,7 @@ FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec) HaveRocketEngine = HaveTurboPropEngine = HaveElectricEngine = false; + HasInitializedEngines = false; Debug(0); } @@ -95,20 +106,59 @@ FGPropulsion::~FGPropulsion() { for (unsigned int i=0; iResetToIC(); + + for (unsigned int i=0; iGetType()) { + case FGEngine::etPiston: + ((FGPiston*)Engines[i])->ResetToIC(); + try { + if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i); + } catch (string str) { + cerr << str << endl; + result = false; + } + break; + case FGEngine::etTurbine: + ((FGTurbine*)Engines[i])->ResetToIC(); + try { + if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i); + } catch (string str) { + cerr << str << endl; + result = false; + } + break; + default: + break; + } + } + + return result; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropulsion::Run(bool Holding) { unsigned int i; - if (FGModel::Run()) return true; - if (FDMExec->Holding()) return false; + if (FGModel::Run(Holding)) return true; + if (Holding) return false; + + RunPreFunctions(); - double dt = State->Getdt(); + double dt = FDMExec->GetDeltaT(); vForces.InitMatrix(); vMoments.InitMatrix(); @@ -124,10 +174,13 @@ bool FGPropulsion::Run(void) 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 ); + + RunPostFunctions(); return false; } @@ -136,35 +189,46 @@ bool FGPropulsion::Run(void) bool FGPropulsion::GetSteadyState(void) { - double currentThrust = 0, lastThrust=-1; - int steady_count,j=0; - bool steady=false; + double currentThrust = 0, lastThrust = -1; + int steady_count = 0, j = 0; + bool steady = false; + bool TrimMode = FDMExec->GetTrimStatus(); vForces.InitMatrix(); vMoments.InitMatrix(); - if (!FGModel::Run()) { + if (!FGModel::Run(false)) { + FDMExec->SetTrimStatus(true); + for (unsigned int i=0; iSetTrimMode(true); +// cout << " Finding steady state for engine " << i << endl; steady=false; steady_count=0; + j=0; while (!steady && j < 6000) { Engines[i]->Calculate(); lastThrust = currentThrust; - currentThrust = Engines[i]->GetThrust(); + currentThrust = Engines[i]->GetThruster()->GetThrust(); if (fabs(lastThrust-currentThrust) < 0.0001) { steady_count++; - if (steady_count > 120) { steady=true; } + if (steady_count > 120) { + steady=true; +// cout << " Steady state found at thrust: " << currentThrust << " lbs." << endl; + } } 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); } + FDMExec->SetTrimStatus(TrimMode); + return false; } else { return true; @@ -173,25 +237,33 @@ bool FGPropulsion::GetSteadyState(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGPropulsion::ICEngineStart(void) +void FGPropulsion::InitRunning(int n) { - int j; + if (n >= 0) { // A specific engine is supposed to be initialized - vForces.InitMatrix(); - vMoments.InitMatrix(); + if (n >= (int)GetNumEngines() ) { + throw(string("Tried to initialize a non-existent engine!")); + } + FDMExec->GetFCS()->SetThrottleCmd(n,1); + FDMExec->GetFCS()->SetMixtureCmd(n,1); + GetEngine(n)->InitRunning(); + GetSteadyState(); - for (unsigned int i=0; iSetTrimMode(true); - j=0; - while (!Engines[i]->GetRunning() && j < 2000) { - Engines[i]->Calculate(); - j++; + InitializedEngines = 1 << n; + HasInitializedEngines = true; + + } else if (n < 0) { // -1 refers to "All Engines" + + for (unsigned int i=0; iGetFCS()->SetThrottleCmd(i,1); + FDMExec->GetFCS()->SetMixtureCmd(i,1); + GetEngine(i)->InitRunning(); } - vForces += Engines[i]->GetBodyForces(); // sum body frame forces - vMoments += Engines[i]->GetMoments(); // sum body frame moments - Engines[i]->SetTrimMode(false); + GetSteadyState(); + InitializedEngines = -1; + HasInitializedEngines = true; + } - return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -199,14 +271,26 @@ bool FGPropulsion::ICEngineStart(void) bool FGPropulsion::Load(Element* el) { string type, engine_filename; - int Feed; bool ThrottleAdded = false; - Element* document; - FGXMLParse engine_file_parser; - ifstream* engine_file; 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"); @@ -217,86 +301,79 @@ bool FGPropulsion::Load(Element* el) } engine_filename = FindEngineFullPathname(engine_filename); - readXML(engine_filename, engine_file_parser); - document = engine_file_parser.GetDocument(); // document holds the engine description + 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); + try { + 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); + } + } catch (std::string str) { + cerr << endl << fgred << str << reset << endl; + return false; } - FCS->AddThrottle(); + FDMExec->GetFCS()->AddThrottle(); ThrottleAdded = true; numEngines++; engine_element = el->FindNextElement("engine"); - engine_file_parser.reset(); + ResetParser(); } - // Process tank definitions + CalculateTankInertias(); + if (!ThrottleAdded) FDMExec->GetFCS()->AddThrottle(); // need to have at least one throttle - Element* tank_element = el->FindElement("tank"); - while (tank_element) { - Tanks.push_back(new FGTank(FDMExec, tank_element)); - 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; + // Process fuel dump rate + if (el->FindElement("dump-rate")) + DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN"); - CalculateTankInertias(); - if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle + PostLoad(el, PropertyManager); return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -string FGPropulsion::FindEngineFullPathname(string engine_filename) +string FGPropulsion::FindEngineFullPathname(const string& engine_filename) { string fullpath, localpath; string enginePath = FDMExec->GetEnginePath(); - string aircraftPath = FDMExec->GetAircraftPath(); - ifstream* engine_file = new ifstream(); + string aircraftPath = FDMExec->GetFullAircraftPath(); + ifstream engine_file; string separator = "/"; -# ifdef macintosh - separator = ";"; -# endif 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()) { + 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(""); @@ -309,17 +386,14 @@ string FGPropulsion::FindEngineFullPathname(string engine_filename) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -ifstream* FGPropulsion::FindEngineFile(string engine_filename) +ifstream* FGPropulsion::FindEngineFile(const string& engine_filename) { string fullpath, localpath; string enginePath = FDMExec->GetEnginePath(); - string aircraftPath = FDMExec->GetAircraftPath(); + string aircraftPath = FDMExec->GetFullAircraftPath(); ifstream* engine_file = new ifstream(); string separator = "/"; -# ifdef macintosh - separator = ";"; -# endif fullpath = enginePath + separator; localpath = aircraftPath + separator + "Engines" + separator; @@ -337,7 +411,7 @@ ifstream* FGPropulsion::FindEngineFile(string engine_filename) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -string FGPropulsion::GetPropulsionStrings(string delimeter) +string FGPropulsion::GetPropulsionStrings(const string& delimiter) const { unsigned int i; @@ -347,13 +421,13 @@ string FGPropulsion::GetPropulsionStrings(string delimeter) for (i=0; iGetEngineLabels(delimeter); + PropulsionStrings += Engines[i]->GetEngineLabels(delimiter); } for (i=0; iGetType() == FGTank::ttFUEL) buf << delimeter << "Fuel Tank " << i; - else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimeter << "Oxidizer Tank " << 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; @@ -361,7 +435,7 @@ string FGPropulsion::GetPropulsionStrings(string delimeter) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -string FGPropulsion::GetPropulsionValues(string delimeter) +string FGPropulsion::GetPropulsionValues(const string& delimiter) const { unsigned int i; @@ -371,12 +445,12 @@ string FGPropulsion::GetPropulsionValues(string delimeter) for (i=0; iGetEngineValues(delimeter); + PropulsionValues += Engines[i]->GetEngineValues(delimiter); } for (i=0; iGetContents(); } @@ -387,13 +461,11 @@ string FGPropulsion::GetPropulsionValues(string delimeter) FGColumnVector3& FGPropulsion::GetTanksMoment(void) { - iTank = Tanks.begin(); vXYZtank_arm.InitMatrix(); - while (iTank < Tanks.end()) { - vXYZtank_arm(eX) += (*iTank)->GetXYZ(eX)*(*iTank)->GetContents(); - vXYZtank_arm(eY) += (*iTank)->GetXYZ(eY)*(*iTank)->GetContents(); - vXYZtank_arm(eZ) += (*iTank)->GetXYZ(eZ)*(*iTank)->GetContents(); - iTank++; + for (unsigned int i=0; iGetXYZ(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; } @@ -404,11 +476,8 @@ double FGPropulsion::GetTanksWeight(void) { double Tw = 0.0; - iTank = Tanks.begin(); - while (iTank < Tanks.end()) { - Tw += (*iTank)->GetContents(); - iTank++; - } + for (unsigned int i=0; iGetContents(); + return Tw; } @@ -423,9 +492,13 @@ FGMatrix33& FGPropulsion::CalculateTankInertias(void) tankJ = FGMatrix33(); - for (unsigned int i=0; iGetPointmassInertia( lbtoslug * Tanks[i]->GetContents(), + for (unsigned int i=0; iGetMassBalance()->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; } @@ -488,7 +561,7 @@ void FGPropulsion::SetCutoff(int setting) void FGPropulsion::SetActiveEngine(int engine) { - if (engine >= Engines.size() || engine < 0) + if (engine >= (int)Engines.size() || engine < 0) ActiveEngine = -1; else ActiveEngine = engine; @@ -536,6 +609,28 @@ void FGPropulsion::DoRefuel(double time_slice) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +void FGPropulsion::DumpFuel(double time_slice) +{ + unsigned int i; + int TanksDumping = 0; + + for (i=0; iGetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping; + } + + if (TanksDumping == 0) return; + + double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping; + + for (i=0; iGetContents() > Tanks[i]->GetStandpipe()) { + Transfer(i, -1, dump_rate_per_tank); + } + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + void FGPropulsion::SetFuelFreeze(bool f) { fuel_freeze = f; @@ -552,36 +647,37 @@ void FGPropulsion::bind(void) typedef int (FGPropulsion::*iPMF)(void) const; IsBound = true; - + PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, false); if (HaveTurbineEngine) { - PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true); - PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, true); + PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, false); + PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, false); } 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/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, false); + PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, false); } 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); -void FGPropulsion::unbind(void) -{ - if (HaveTurbineEngine) { - PropertyManager->Untie("propulsion/starter_cmd"); - PropertyManager->Untie("propulsion/cutoff_cmd"); - } - if (HavePistonEngine) { - PropertyManager->Untie("propulsion/starter_cmd"); - PropertyManager->Untie("propulsion/magneto_cmd"); - } - PropertyManager->Untie("propulsion/active_engine"); - PropertyManager->Untie("propulsion/total-fuel-lbs"); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%