diff --git a/src/FDM/JSBSim.cxx b/src/FDM/JSBSim.cxx index 7f4c37610..a481c7dc1 100644 --- a/src/FDM/JSBSim.cxx +++ b/src/FDM/JSBSim.cxx @@ -54,6 +54,7 @@ #include #include #include +#include #include "JSBSim.hxx" /******************************************************************************/ @@ -218,6 +219,9 @@ void FGJSBsim::init() { SG_LOG( SG_FLIGHT, SG_INFO, "Finished initializing JSBSim" ); + SG_LOG( SG_FLIGHT, SG_INFO, "FGControls::get_gear_down()= " << + globals->get_controls()->get_gear_down() ); + } @@ -264,20 +268,20 @@ bool FGJSBsim::update( int multiloop ) { msg = fdmex->ProcessMessage(); switch (msg->type) { case FGJSBBase::Message::eText: - cout << msg->messageId << ": " << msg->text << endl; + SG_LOG( SG_FLIGHT, SG_INFO, msg->messageId << ": " << msg->text ); break; case FGJSBBase::Message::eBool: - cout << msg->messageId << ": " << msg->text << " " << msg->bVal << endl; + SG_LOG( SG_FLIGHT, SG_INFO, msg->messageId << ": " << msg->text << " " << msg->bVal ); break; case FGJSBBase::Message::eInteger: - cout << msg->messageId << ": " << msg->text << " " << msg->iVal << endl; + SG_LOG( SG_FLIGHT, SG_INFO, msg->messageId << ": " << msg->text << " " << msg->iVal ); break; case FGJSBBase::Message::eDouble: - cout << msg->messageId << ": " << msg->text << " " << msg->dVal << endl; + SG_LOG( SG_FLIGHT, SG_INFO, msg->messageId << ": " << msg->text << " " << msg->dVal ); break; default: - cerr << "Unrecognized message type." << endl; - break; + SG_LOG( SG_FLIGHT, SG_INFO, "Unrecognized message type." ); + break; } } @@ -322,9 +326,11 @@ bool FGJSBsim::copy_to_JSBsim() { FCS->SetLBrake( globals->get_controls()->get_brake( 0 ) ); FCS->SetRBrake( globals->get_controls()->get_brake( 1 ) ); FCS->SetCBrake( globals->get_controls()->get_brake( 2 ) ); + FCS->SetGearCmd( globals->get_controls()->get_gear_down()); for (int i = 0; i < get_num_engines(); i++) { FCS->SetThrottleCmd(i, globals->get_controls()->get_throttle(i)); FCS->SetMixtureCmd(i, globals->get_controls()->get_mixture(i)); + FCS->SetPropPitchCmd(i, globals->get_controls()->get_prop_advance(i)); } Position->SetSeaLevelRadius( get_Sea_level_radius() ); @@ -644,9 +650,11 @@ void FGJSBsim::init_gear(void ) { if ( gr->GetGearUnit(i)->GetBrakeGroup() > 0 ) { gear->SetBrake(true); } - if ( gr->GetGearUp() ) { - gear->SetPosition( 0.0 ); - } + if ( gr->GetGearUnit(i)->GetRetractable() ) { + gear->SetPosition( FCS->GetGearPos() ); + } else { + gear->SetPosition( 1.0 ); + } } } @@ -658,9 +666,9 @@ void FGJSBsim::update_gear(void) { for (int i=0;iSetWoW( gr->GetGearUnit(i)->GetWOW() ); - if ( gr->GetGearUp() ) { - gear->SetPosition( 0.0 ); - } + if ( gr->GetGearUnit(i)->GetRetractable() ) { + gear->SetPosition( FCS->GetGearPos() ); + } } } diff --git a/src/FDM/JSBSim/FGAerodynamics.cpp b/src/FDM/JSBSim/FGAerodynamics.cpp index 2b62a7d37..523c73fc2 100644 --- a/src/FDM/JSBSim/FGAerodynamics.cpp +++ b/src/FDM/JSBSim/FGAerodynamics.cpp @@ -49,9 +49,9 @@ CLASS IMPLEMENTATION FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec), - vMoments(3), - vForces(3), vFs(3), + vForces(3), + vMoments(3), vLastFs(3), vDXYZcg(3) { @@ -182,7 +182,6 @@ string FGAerodynamics::GetCoefficientStrings(void) string FGAerodynamics::GetCoefficientValues(void) { string SDValues = ""; - char buffer[10]; bool firstime = true; for (unsigned int axis = 0; axis < 6; axis++) { @@ -203,8 +202,6 @@ string FGAerodynamics::GetCoefficientValues(void) double FGAerodynamics::GetLoD(void) { - double LoD; - if (vFs(1) != 0.00) return vFs(3)/vFs(1); else return 0.00; } diff --git a/src/FDM/JSBSim/FGAtmosphere.cpp b/src/FDM/JSBSim/FGAtmosphere.cpp index 2a19dd91d..9d677b55e 100644 --- a/src/FDM/JSBSim/FGAtmosphere.cpp +++ b/src/FDM/JSBSim/FGAtmosphere.cpp @@ -69,14 +69,14 @@ CLASS IMPLEMENTATION FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex), - vWindNED(3), vDirectiondAccelDt(3), vDirectionAccel(3), vDirection(3), vTurbulence(3), vTurbulenceGrad(3), vBodyTurbGrad(3), - vTurbPQR(3) + vTurbPQR(3), + vWindNED(3) { Name = "FGAtmosphere"; lastIndex=0; @@ -169,7 +169,6 @@ void FGAtmosphere::Calculate(double altitude) { double slope, reftemp, refpress; int i = 0; - bool lookup = false; i = lastIndex; if (altitude < htab[lastIndex]) { @@ -191,12 +190,6 @@ void FGAtmosphere::Calculate(double altitude) } switch(i) { - case 0: // sea level - slope = -0.00356616; // R/ft. - reftemp = 518.67; // R - refpress = 2116.22; // psf - //refdens = 0.00237767; // slugs/cubic ft. - break; case 1: // 36089 ft. slope = 0; reftemp = 389.97; @@ -239,6 +232,14 @@ void FGAtmosphere::Calculate(double altitude) refpress = 0.000122276; //refdens = 2.19541e-10; break; + case 0: + default: // sea level + slope = -0.00356616; // R/ft. + reftemp = 518.67; // R + refpress = 2116.22; // psf + //refdens = 0.00237767; // slugs/cubic ft. + break; + } if (slope == 0) { diff --git a/src/FDM/JSBSim/FGConfigFile.cpp b/src/FDM/JSBSim/FGConfigFile.cpp index 33efd37ec..13948a8f8 100644 --- a/src/FDM/JSBSim/FGConfigFile.cpp +++ b/src/FDM/JSBSim/FGConfigFile.cpp @@ -60,7 +60,7 @@ FGConfigFile::~FGConfigFile() string FGConfigFile::GetNextConfigLine(void) { - int deblank, not_found = string::npos; + int comment_starts_at; int comment_ends_at; int comment_length; diff --git a/src/FDM/JSBSim/FGFCS.cpp b/src/FDM/JSBSim/FGFCS.cpp index a1434dcb9..7535589a9 100644 --- a/src/FDM/JSBSim/FGFCS.cpp +++ b/src/FDM/JSBSim/FGFCS.cpp @@ -54,7 +54,7 @@ INCLUDES #include "filtersjb/FGGradient.h" #include "filtersjb/FGSwitch.h" #include "filtersjb/FGSummer.h" -#include "filtersjb/FGFlaps.h" +#include "filtersjb/FGKinemat.h" static const char *IdSrc = "$Id$"; static const char *IdHdr = ID_FCS; @@ -69,6 +69,7 @@ FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex) DaCmd = DeCmd = DrCmd = DfCmd = DsbCmd = DspCmd = PTrimCmd = 0.0; DaPos = DePos = DrPos = DfPos = DsbPos = DspPos = 0.0; + GearCmd = GearPos = 1; // default to gear down LeftBrake = RightBrake = CenterBrake = 0.0; if (debug_lvl & 2) cout << "Instantiated: " << Name << endl; @@ -82,6 +83,8 @@ FGFCS::~FGFCS() ThrottlePos.clear(); MixtureCmd.clear(); MixturePos.clear(); + PropPitchCmd.clear(); + PropPitchPos.clear(); unsigned int i; @@ -98,6 +101,7 @@ bool FGFCS::Run(void) if (!FGModel::Run()) { for (i=0; iRun(); } else { } @@ -158,6 +162,7 @@ double FGFCS::GetThrottleCmd(int engineNum) << " engines exist, but throttle setting for engine " << engineNum << " is selected" << endl; } + return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -175,6 +180,7 @@ double FGFCS::GetThrottlePos(int engineNum) << " engines exist, but attempted throttle position setting is for engine " << engineNum << endl; } + return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -209,6 +215,36 @@ void FGFCS::SetMixturePos(int engineNum, double setting) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +void FGFCS::SetPropPitchCmd(int engineNum, double setting) +{ + unsigned int ctr; + + if (engineNum < (int)ThrottlePos.size()) { + if (engineNum < 0) { + for (ctr=0;ctr ThrottlePos; vector MixtureCmd; vector MixturePos; + vector PropPitchCmd; + vector PropPitchPos; double LeftBrake, RightBrake, CenterBrake; // Brake settings + double GearCmd,GearPos; vector Components; void Debug(void); diff --git a/src/FDM/JSBSim/FGFDMExec.cpp b/src/FDM/JSBSim/FGFDMExec.cpp index b191a901c..a2fdd683e 100644 --- a/src/FDM/JSBSim/FGFDMExec.cpp +++ b/src/FDM/JSBSim/FGFDMExec.cpp @@ -415,7 +415,7 @@ bool FGFDMExec::LoadScript(string script) string initialize=""; bool result=false; double dt=0.0; - int i; + unsigned i; struct condition *newCondition; if (!Script.IsOpen()) return false; @@ -594,14 +594,12 @@ bool FGFDMExec::LoadScript(string script) void FGFDMExec::RunScript(void) { vector ::iterator iC = Conditions.begin(); - bool truth; - bool WholeTruth; - int i; - - int count=0; + bool truth = false; + bool WholeTruth = false; + unsigned i; double currentTime = State->Getsim_time(); - double newSetValue; + double newSetValue = 0; while (iC < Conditions.end()) { // determine whether the set of conditional tests for this condition equate diff --git a/src/FDM/JSBSim/FGFactorGroup.cpp b/src/FDM/JSBSim/FGFactorGroup.cpp index aee046833..37ef3d921 100644 --- a/src/FDM/JSBSim/FGFactorGroup.cpp +++ b/src/FDM/JSBSim/FGFactorGroup.cpp @@ -77,7 +77,7 @@ FGFactorGroup::FGFactorGroup( FGFDMExec* fdmex ) : FGCoefficient( fdmex) FGFactorGroup::~FGFactorGroup() { - int i; + unsigned i; for (i=0; iGetDistanceAGL() < 300.0 ) { + if ( Position->GetDistanceAGL() < 300.0 ) { vector ::iterator iGear = lGear.begin(); // Sum forces and moments for all gear, here. // Some optimizations may be made here - or rather in the gear code itself. diff --git a/src/FDM/JSBSim/FGGroundReactions.h b/src/FDM/JSBSim/FGGroundReactions.h index 5a7685ea9..7c0ffdcf3 100644 --- a/src/FDM/JSBSim/FGGroundReactions.h +++ b/src/FDM/JSBSim/FGGroundReactions.h @@ -77,24 +77,17 @@ public: FGColumnVector3& GetMoments(void) {return vMoments;} string GetGroundReactionStrings(void); string GetGroundReactionValues(void); - - /** Gets the gear status - @return true if gear is not deployed */ - inline bool GetGearUp(void) { return GearUp; } - /** Gets the number of gear units defined for the aircraft - @return number of gear units defined */ + inline int GetNumGearUnits(void) { return 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]); } - inline void SetGear(bool tt) { GearUp = tt; } - inline void SetGearUp(void) { GearUp = true; } - inline void SetGearDown(bool tt) { GearUp = false; } private: vector lGear; - bool GearUp; FGColumnVector3 vForces; FGColumnVector3 vMoments; FGColumnVector3 vMaxStaticGrip; diff --git a/src/FDM/JSBSim/FGInertial.cpp b/src/FDM/JSBSim/FGInertial.cpp index c7c60c542..c2632e3d5 100644 --- a/src/FDM/JSBSim/FGInertial.cpp +++ b/src/FDM/JSBSim/FGInertial.cpp @@ -48,8 +48,8 @@ CLASS IMPLEMENTATION FGInertial::FGInertial(FGFDMExec* fgex) : FGModel(fgex), - vForces(3), vOmegaLocal(3), + vForces(3), vRadius(3), vGravity(3) { diff --git a/src/FDM/JSBSim/FGInitialCondition.cpp b/src/FDM/JSBSim/FGInitialCondition.cpp index 92346f863..e641fa86c 100644 --- a/src/FDM/JSBSim/FGInitialCondition.cpp +++ b/src/FDM/JSBSim/FGInitialCondition.cpp @@ -536,7 +536,7 @@ bool FGInitialCondition::getTheta(void) { //****************************************************************************** double FGInitialCondition::GammaEqOfTheta(double Theta) { - double a,b,c,d; + double a,b,c; double sTheta,cTheta; //theta=Theta; stheta=sin(theta); ctheta=cos(theta); @@ -551,7 +551,7 @@ double FGInitialCondition::GammaEqOfTheta(double Theta) { //****************************************************************************** double FGInitialCondition::GammaEqOfAlpha(double Alpha) { - double a,b,c,d; + double a,b,c; double sAlpha,cAlpha; sAlpha=sin(Alpha); cAlpha=cos(Alpha); @@ -654,7 +654,7 @@ bool FGInitialCondition::solve(double *y,double x) //initializations d=1; - + x2 = 0; x1=xlo;x3=xhi; f1=(this->*sfunc)(x1)-x; f3=(this->*sfunc)(x3)-x; diff --git a/src/FDM/JSBSim/FGJSBBase.cpp b/src/FDM/JSBSim/FGJSBBase.cpp index d04fdfd1f..acbe17167 100644 --- a/src/FDM/JSBSim/FGJSBBase.cpp +++ b/src/FDM/JSBSim/FGJSBBase.cpp @@ -64,7 +64,7 @@ const double FGJSBBase::ktstofps = 1.68781; const double FGJSBBase::inchtoft = 0.08333333; const double FGJSBBase::Reng = 1716.0; const double FGJSBBase::SHRatio = 1.40; -const string FGJSBBase::needed_cfg_version = "1.56"; +const string FGJSBBase::needed_cfg_version = "1.57"; const string FGJSBBase::JSBSim_version = "0.9.1"; queue FGJSBBase::Messages; diff --git a/src/FDM/JSBSim/FGJSBBase.h b/src/FDM/JSBSim/FGJSBBase.h index 92f71096f..b805f056b 100644 --- a/src/FDM/JSBSim/FGJSBBase.h +++ b/src/FDM/JSBSim/FGJSBBase.h @@ -136,7 +136,9 @@ enum eParam { FG_HTAILAREA, FG_VTAILAREA, FG_VBARH, //horizontal tail volume - FG_VBARV //vertical tail volume + FG_VBARV, //vertical tail volume + FG_GEAR_CMD, + FG_GEAR_POS }; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/FGLGear.cpp b/src/FDM/JSBSim/FGLGear.cpp index 2fe798e60..4826990de 100644 --- a/src/FDM/JSBSim/FGLGear.cpp +++ b/src/FDM/JSBSim/FGLGear.cpp @@ -66,9 +66,12 @@ FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : vXYZ(3), Exec(fdmex) { string tmp; + string Retractable; + *AC_cfg >> tmp >> name >> vXYZ(1) >> vXYZ(2) >> vXYZ(3) >> kSpring >> bDamp>> dynamicFCoeff >> staticFCoeff - >> rollingFCoeff >> sSteerType >> sBrakeGroup >> maxSteerAngle; + >> rollingFCoeff >> sSteerType >> sBrakeGroup + >> maxSteerAngle >> Retractable; if (debug_lvl > 0) { cout << " Name: " << name << endl; @@ -81,6 +84,7 @@ FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : vXYZ(3), cout << " Steering Type: " << sSteerType << endl; cout << " Grouping: " << sBrakeGroup << endl; cout << " Max Steer Angle: " << maxSteerAngle << endl; + cout << " Retractable: " << Retractable << endl; } if (sBrakeGroup == "LEFT" ) eBrakeGrp = bgLeft; @@ -101,6 +105,14 @@ FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : vXYZ(3), cerr << "Improper steering type specification in config file: " << sSteerType << " is undefined." << endl; } + + if( Retractable == "RETRACT" ) { + isRetractable=true; + } else { + isRetractable=false; + } + + GearUp=false; GearDown=true; // Add some AI here to determine if gear is located properly according to its // brake group type ?? @@ -172,6 +184,9 @@ FGLGear::FGLGear(const FGLGear& lgear) sBrakeGroup = lgear.sBrakeGroup; eBrakeGrp = lgear.eBrakeGrp; maxSteerAngle = lgear.maxSteerAngle; + isRetractable = lgear.isRetractable; + GearUp = lgear.GearUp; + GearDown = lgear.GearDown; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -185,31 +200,46 @@ FGLGear::~FGLGear() FGColumnVector3& FGLGear::Force(void) { - double SteerGain; - double SinWheel, CosWheel, SideWhlVel, RollingWhlVel; - double RudderPedal, RollingForce, SideForce, FCoeff; - double WheelSlip; + vForce.InitMatrix(); + vMoment.InitMatrix(); + if(isRetractable ) { + if( FCS->GetGearPos() < 0.01 ) { + GearUp=true;GearDown=false; + } else if(FCS->GetGearPos() > 0.99) { + GearDown=true;GearUp=false; + } else { + GearUp=false; GearDown=false; + } + } else { + GearUp=false; GearDown=true; + } + + if( GearDown ) { + double SteerGain = 0; + double SinWheel, CosWheel, SideWhlVel, RollingWhlVel; + double RollingForce, SideForce, FCoeff; + double WheelSlip; - vWhlBodyVec = (vXYZ - MassBalance->GetXYZcg()) / 12.0; - vWhlBodyVec(eX) = -vWhlBodyVec(eX); - vWhlBodyVec(eZ) = -vWhlBodyVec(eZ); + vWhlBodyVec = (vXYZ - MassBalance->GetXYZcg()) / 12.0; + vWhlBodyVec(eX) = -vWhlBodyVec(eX); + vWhlBodyVec(eZ) = -vWhlBodyVec(eZ); // vWhlBodyVec now stores the vector from the cg to this wheel - vLocalGear = State->GetTb2l() * vWhlBodyVec; + vLocalGear = State->GetTb2l() * vWhlBodyVec; // vLocalGear now stores the vector from the cg to the wheel in local coords. - compressLength = vLocalGear(eZ) - Position->GetDistanceAGL(); + compressLength = vLocalGear(eZ) - Position->GetDistanceAGL(); // The compression length is currently measured in the Z-axis, only, at this time. // It should be measured along the strut axis. If the local-frame gear position // "hangs down" below the CG greater than the altitude, then the compressLength // will be positive - i.e. the gear will have made contact. - if (compressLength > 0.00) { + if (compressLength > 0.00) { - WOW = true; // Weight-On-Wheels is true + WOW = true;// Weight-On-Wheels is true // The next equation should really use the vector to the contact patch of the tire // including the strut compression and not vWhlBodyVec. Will fix this later. @@ -222,20 +252,20 @@ FGColumnVector3& FGLGear::Force(void) // (used for calculating damping force) is found by taking the Z-component of the // wheel velocity. - vWhlVelVec = State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec); + vWhlVelVec = State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec); - vWhlVelVec += Position->GetVel(); + vWhlVelVec += Position->GetVel(); - compressSpeed = vWhlVelVec(eZ); + compressSpeed = vWhlVelVec(eZ); // If this is the first time the wheel has made contact, remember some values // for later printout. - if (!FirstContact) { - FirstContact = true; - SinkRate = compressSpeed; - GroundSpeed = Position->GetVel().Magnitude(); - } + if (!FirstContact) { + FirstContact = true; + SinkRate = compressSpeed; + GroundSpeed = Position->GetVel().Magnitude(); + } // The following needs work regarding friction coefficients and braking and // steering The BrakeFCoeff formula assumes that an anti-skid system is used. @@ -244,71 +274,71 @@ FGColumnVector3& FGLGear::Force(void) // [JSB] The braking force coefficients include normal rolling coefficient + // a percentage of the static friction coefficient based on braking applied. - switch (eBrakeGrp) { - case bgLeft: - SteerGain = -0.10; - BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) + - staticFCoeff*FCS->GetBrake(bgLeft); - break; - case bgRight: - SteerGain = -0.10; - BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) + - staticFCoeff*FCS->GetBrake(bgRight); - break; - case bgCenter: - SteerGain = -0.10; - BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + - staticFCoeff*FCS->GetBrake(bgCenter); - break; - case bgNose: - SteerGain = 0.10; - BrakeFCoeff = rollingFCoeff; - break; - case bgTail: - SteerGain = -0.10; - BrakeFCoeff = rollingFCoeff; - break; - case bgNone: - SteerGain = -0.10; - BrakeFCoeff = rollingFCoeff; - break; - default: - cerr << "Improper brake group membership detected for this gear." << endl; - break; - } + switch (eBrakeGrp) { + case bgLeft: + SteerGain = -0.10; + BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) + + staticFCoeff*FCS->GetBrake(bgLeft); + break; + case bgRight: + SteerGain = -0.10; + BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) + + staticFCoeff*FCS->GetBrake(bgRight); + break; + case bgCenter: + SteerGain = -0.10; + BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + + staticFCoeff*FCS->GetBrake(bgCenter); + break; + case bgNose: + SteerGain = 0.10; + BrakeFCoeff = rollingFCoeff; + break; + case bgTail: + SteerGain = -0.10; + BrakeFCoeff = rollingFCoeff; + break; + case bgNone: + SteerGain = -0.10; + BrakeFCoeff = rollingFCoeff; + break; + default: + cerr << "Improper brake group membership detected for this gear." << endl; + break; + } - switch (eSteerType) { - case stSteer: - SteerAngle = SteerGain*FCS->GetDrPos(); - break; - case stFixed: - SteerAngle = 0.0; - break; - case stCaster: - // Note to Jon: This is not correct for castering gear. I'll fix it later. - SteerAngle = 0.0; - break; - default: - cerr << "Improper steering type membership detected for this gear." << endl; - break; - } + switch (eSteerType) { + case stSteer: + SteerAngle = SteerGain*FCS->GetDrPos(); + break; + case stFixed: + SteerAngle = 0.0; + break; + case stCaster: +// Note to Jon: This is not correct for castering gear. I'll fix it later. + SteerAngle = 0.0; + break; + default: + cerr << "Improper steering type membership detected for this gear." << endl; + break; + } // Transform the wheel velocities from the local axis system to the wheel axis system. // For now, steering angle is assumed to happen in the Local Z axis, // not the strut axis as it should be. Will fix this later. - SinWheel = sin(Rotation->Getpsi() + SteerAngle); - CosWheel = cos(Rotation->Getpsi() + SteerAngle); - RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel; - SideWhlVel = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel; + SinWheel = sin(Rotation->Getpsi() + SteerAngle); + CosWheel = cos(Rotation->Getpsi() + SteerAngle); + RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel; + SideWhlVel = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel; // Calculate tire slip angle. - if (RollingWhlVel == 0.0 && SideWhlVel == 0.0) { - WheelSlip = 0.0; - } else { - WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel); - } + if (RollingWhlVel == 0.0 && SideWhlVel == 0.0) { + WheelSlip = 0.0; + } else { + WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel); + } // The following code normalizes the wheel velocity vector, reverses it, and zeroes out // the z component of the velocity. The question is, should the Z axis velocity be zeroed @@ -325,11 +355,11 @@ FGColumnVector3& FGLGear::Force(void) // transition from static to dynamic friction. There are more complicated formulations // of this that avoid the discrete jump. Will fix this later. - if (fabs(WheelSlip) <= 10.0) { - FCoeff = staticFCoeff*WheelSlip/10.0; - } else { - FCoeff = dynamicFCoeff*fabs(WheelSlip)/WheelSlip; - } + if (fabs(WheelSlip) <= 10.0) { + FCoeff = staticFCoeff*WheelSlip/10.0; + } else { + FCoeff = dynamicFCoeff*fabs(WheelSlip)/WheelSlip; + } // Compute the vertical force on the wheel using square-law damping (per comment // in paper AIAA-2000-4303 - see header prologue comments). We might consider @@ -337,24 +367,24 @@ FGColumnVector3& FGLGear::Force(void) // possibly give a "rebound damping factor" that differs from the compression // case. NOTE: SQUARE LAW DAMPING NO GOOD! - vLocalForce(eZ) = min(-compressLength * kSpring - - compressSpeed * bDamp, (double)0.0); + vLocalForce(eZ) = min(-compressLength * kSpring + - compressSpeed * bDamp, (double)0.0); - MaximumStrutForce = max(MaximumStrutForce, fabs(vLocalForce(eZ))); - MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength)); + MaximumStrutForce = max(MaximumStrutForce, fabs(vLocalForce(eZ))); + MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength)); // Compute the forces in the wheel ground plane. - RollingForce = 0; - if (fabs(RollingWhlVel) > 1E-3) { - RollingForce = vLocalForce(eZ) * BrakeFCoeff * fabs(RollingWhlVel)/RollingWhlVel; - } - SideForce = vLocalForce(eZ) * FCoeff; + RollingForce = 0; + if (fabs(RollingWhlVel) > 1E-3) { + RollingForce = vLocalForce(eZ) * BrakeFCoeff * fabs(RollingWhlVel)/RollingWhlVel; + } + SideForce = vLocalForce(eZ) * FCoeff; // Transform these forces back to the local reference frame. - vLocalForce(eX) = RollingForce*CosWheel - SideForce*SinWheel; - vLocalForce(eY) = SideForce*CosWheel + RollingForce*SinWheel; + vLocalForce(eX) = RollingForce*CosWheel - SideForce*SinWheel; + vLocalForce(eY) = SideForce*CosWheel + RollingForce*SinWheel; // Note to Jon: At this point the forces will be too big when the airplane is // stopped or rolling to a stop. We need to make sure that the gear forces just @@ -370,52 +400,53 @@ FGColumnVector3& FGLGear::Force(void) // Transform the forces back to the body frame and compute the moment. - vForce = State->GetTl2b() * vLocalForce; - vMoment = vWhlBodyVec * vForce; + vForce = State->GetTl2b() * vLocalForce; + vMoment = vWhlBodyVec * vForce; - } else { + } else { - WOW = false; + WOW = false; - if (Position->GetDistanceAGL() > 200.0) { - FirstContact = false; - Reported = false; - DistanceTraveled = 0.0; - MaximumStrutForce = MaximumStrutTravel = 0.0; + if (Position->GetDistanceAGL() > 200.0) { + FirstContact = false; + Reported = false; + DistanceTraveled = 0.0; + MaximumStrutForce = MaximumStrutTravel = 0.0; + } + + compressLength = 0.0;// reset compressLength to zero for data output validity + + } - compressLength = 0.0; // reset compressLength to zero for data output validity - - vForce.InitMatrix(); - vMoment.InitMatrix(); - } - - if (FirstContact) { - DistanceTraveled += Position->GetVel().Magnitude()*State->Getdt()*Aircraft->GetRate(); - } - - if (ReportEnable && Position->GetVel().Magnitude() <= 0.05 && !Reported) { - if (debug_lvl > 0) Report(); - } - - if (lastWOW != WOW) { - PutMessage("GEAR_CONTACT", WOW); - } - - lastWOW = WOW; - - // Crash detection logic (really out-of-bounds detection) + if (FirstContact) { + DistanceTraveled += Position->GetVel().Magnitude()*State->Getdt()*Aircraft->GetRate(); + } - if (compressLength > 500.0 || - vForce.Magnitude() > 100000000.0 || - vMoment.Magnitude() > 5000000000.0 || - SinkRate > 1.4666*30) - { - PutMessage("Crash Detected"); - Exec->Freeze(); - } + if (ReportEnable && Position->GetVel().Magnitude() <= 0.05 && !Reported) { + if (debug_lvl > 0) Report(); + } - return vForce; + if (lastWOW != WOW) { + PutMessage("GEAR_CONTACT", WOW); + } + + lastWOW = WOW; + +// Crash detection logic (really out-of-bounds detection) + + if (compressLength > 500.0 || + vForce.Magnitude() > 100000000.0 || + vMoment.Magnitude() > 5000000000.0 || + SinkRate > 1.4666*30) + { + PutMessage("Crash Detected"); + Exec->Freeze(); + } + + + } + return vForce; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/FGLGear.h b/src/FDM/JSBSim/FGLGear.h index 96261dc30..fe2aff02b 100644 --- a/src/FDM/JSBSim/FGLGear.h +++ b/src/FDM/JSBSim/FGLGear.h @@ -231,7 +231,11 @@ public: inline int GetBrakeGroup(void) { return (int)eBrakeGrp; } inline int GetSteerType(void) { return (int)eSteerType; } - + + inline bool GetRetractable(void) { return isRetractable; } + inline bool GetGearUnitUp(void) { return GearUp; } + inline bool GetGearUnitDown(void) { return GearDown; } + private: FGColumnVector3 vXYZ; FGColumnVector3 vMoment; @@ -259,9 +263,12 @@ private: bool FirstContact; bool Reported; bool ReportEnable; + bool isRetractable; + bool GearUp, GearDown; string name; string sSteerType; string sBrakeGroup; + BrakeGroup eBrakeGrp; SteerType eSteerType; double maxSteerAngle; diff --git a/src/FDM/JSBSim/FGPiston.cpp b/src/FDM/JSBSim/FGPiston.cpp index 1a6a62bc3..58485a2e4 100644 --- a/src/FDM/JSBSim/FGPiston.cpp +++ b/src/FDM/JSBSim/FGPiston.cpp @@ -50,22 +50,27 @@ CLASS IMPLEMENTATION FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg) : FGEngine(exec), - MinManifoldPressure_inHg(6.5), - MaxManifoldPressure_inHg(28.5), - Displacement(360), - MaxHP(200), - Cycles(2), - IdleRPM(600), - // Set constants - CONVERT_CUBIC_INCHES_TO_METERS_CUBED(1.638706e-5), - R_air(287.3), - rho_fuel(800), // estimate - calorific_value_fuel(47.3e6), - Cp_air(1005), - Cp_fuel(1700) + //these must be initialized this way as they are declared const + CONVERT_CUBIC_INCHES_TO_METERS_CUBED(1.638706e-5), + R_air(287.3), + rho_fuel(800), // estimate + calorific_value_fuel(47.3e6), + Cp_air(1005), + Cp_fuel(1700) { + string token; + MinManifoldPressure_inHg=6.5; + MaxManifoldPressure_inHg=28.5; + Displacement=360; + MaxHP=200; + Cycles=2; + IdleRPM=600; + // Set constants + + + Name = Eng_cfg->GetValue("NAME"); Eng_cfg->GetNextConfigLine(); while (Eng_cfg->GetValue() != string("/FG_PISTON")) { @@ -159,7 +164,6 @@ FGPiston::~FGPiston() double FGPiston::Calculate(double PowerRequired) { - double h,EngineMaxPower; // FIXME: calculate from actual fuel flow ConsumeFuel(); diff --git a/src/FDM/JSBSim/FGRocket.cpp b/src/FDM/JSBSim/FGRocket.cpp index e805849ff..9a2e7bba5 100644 --- a/src/FDM/JSBSim/FGRocket.cpp +++ b/src/FDM/JSBSim/FGRocket.cpp @@ -99,7 +99,7 @@ FGRocket::~FGRocket() double FGRocket::Calculate(double pe) { - double Cf; + double Cf=0; ConsumeFuel(); diff --git a/src/FDM/JSBSim/FGRotation.cpp b/src/FDM/JSBSim/FGRotation.cpp index bb6f24363..bd6c8d2c7 100644 --- a/src/FDM/JSBSim/FGRotation.cpp +++ b/src/FDM/JSBSim/FGRotation.cpp @@ -77,12 +77,12 @@ CLASS IMPLEMENTATION FGRotation::FGRotation(FGFDMExec* fdmex) : FGModel(fdmex), vPQR(3), + vAeroPQR(3), vPQRdot(3), vMoments(3), vEuler(3), vEulerRates(3), - vlastPQRdot(3), - vAeroPQR(3) + vlastPQRdot(3) { Name = "FGRotation"; cTht=cPhi=cPsi=1.0; diff --git a/src/FDM/JSBSim/FGState.cpp b/src/FDM/JSBSim/FGState.cpp index e0f535e7e..5adfb8757 100644 --- a/src/FDM/JSBSim/FGState.cpp +++ b/src/FDM/JSBSim/FGState.cpp @@ -73,18 +73,19 @@ CLASS IMPLEMENTATION // entry in the enum eParam definition in FGJSBBase.h. The ID is what must be used // in any config file entry which references that item. -FGState::FGState(FGFDMExec* fdex) : mTb2l(3,3), +FGState::FGState(FGFDMExec* fdex) : + mTb2l(3,3), mTl2b(3,3), mTs2b(3,3), mTb2s(3,3), vQtrn(4), vlastQdot(4), vQdot(4), - vTmp(4), - vEuler(3), vUVW(3), vLocalVelNED(3), - vLocalEuler(3) + vLocalEuler(3), + vTmp(4), + vEuler(3) { FDMExec = fdex; @@ -134,6 +135,7 @@ FGState::FGState(FGFDMExec* fdex) : mTb2l(3,3), RegisterVariable(FG_SPDBRAKE_POS, " speedbrake_pos " ); RegisterVariable(FG_SPOILERS_POS, " spoiler_pos " ); RegisterVariable(FG_FLAPS_POS, " flaps_pos " ); + RegisterVariable(FG_GEAR_POS, " gear_pos " ); RegisterVariable(FG_ELEVATOR_CMD, " elevator_cmd " ); RegisterVariable(FG_AILERON_CMD, " aileron_cmd " ); RegisterVariable(FG_RUDDER_CMD, " rudder_cmd " ); @@ -141,11 +143,12 @@ FGState::FGState(FGFDMExec* fdex) : mTb2l(3,3), RegisterVariable(FG_SPOILERS_CMD, " spoiler_cmd " ); RegisterVariable(FG_FLAPS_CMD, " flaps_cmd " ); RegisterVariable(FG_THROTTLE_CMD, " throttle_cmd " ); + RegisterVariable(FG_GEAR_CMD, " gear_cmd " ); RegisterVariable(FG_THROTTLE_POS, " throttle_pos " ); - RegisterVariable(FG_MIXTURE_CMD, " mixture_cmd " ); - RegisterVariable(FG_MIXTURE_POS, " mixture_pos " ); - RegisterVariable(FG_MAGNETO_CMD, " magneto_cmd " ); - RegisterVariable(FG_STARTER_CMD, " starter_cmd " ); + RegisterVariable(FG_MIXTURE_CMD, " mixture_cmd " ); + RegisterVariable(FG_MIXTURE_POS, " mixture_pos " ); + RegisterVariable(FG_MAGNETO_CMD, " magneto_cmd " ); + RegisterVariable(FG_STARTER_CMD, " starter_cmd " ); RegisterVariable(FG_ACTIVE_ENGINE, " active_engine " ); RegisterVariable(FG_HOVERB, " height/span " ); RegisterVariable(FG_PITCH_TRIM_CMD, " pitch_trim_cmd " ); @@ -301,6 +304,10 @@ double FGState::GetParameter(eParam val_idx) { return Position->GetHOverBMAC(); case FG_PITCH_TRIM_CMD: return FCS->GetPitchTrimCmd(); + case FG_GEAR_CMD: + return FCS->GetGearCmd(); + case FG_GEAR_POS: + return FCS->GetGearPos(); default: cerr << "FGState::GetParameter() - No handler for parameter " << paramdef[val_idx] << endl; return 0.0; @@ -374,7 +381,7 @@ void FGState::SetParameter(eParam val_idx, double val) { FCS->SetMixtureCmd(ActiveEngine,val); break; case FG_MAGNETO_CMD: - Propulsion->GetEngine(ActiveEngine)->SetMagnetos(val); // need to account for -1 + Propulsion->GetEngine(ActiveEngine)->SetMagnetos((int)val); // need to account for -1 break; case FG_STARTER_CMD: if (val < 0.001) @@ -395,7 +402,12 @@ void FGState::SetParameter(eParam val_idx, double val) { case FG_RIGHT_BRAKE_CMD: FCS->SetRBrake(val); break; - + case FG_GEAR_CMD: + FCS->SetGearCmd(val); + break; + case FG_GEAR_POS: + FCS->SetGearPos(val); + break; case FG_SET_LOGGING: if (val < -0.01) Output->Disable(); else if (val > 0.01) Output->Enable(); @@ -734,7 +746,7 @@ FGMatrix33& FGState::GetTb2s(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGState::ReportState(void) { - char out[80], flap[10], gear[10]; + char out[80], flap[10], gear[12]; cout << endl << " JSBSim State" << endl; snprintf(out,80," Weight: %7.0f lbs. CG: %5.1f, %5.1f, %5.1f inches\n", @@ -747,11 +759,13 @@ void FGState::ReportState(void) { snprintf(flap,10,"Up"); else snprintf(flap,10,"%2.0f",FCS->GetDfPos()); - if(GroundReactions->GetGearUp() == true) - snprintf(gear,10,"Up"); + if(FCS->GetGearPos() < 0.01) + snprintf(gear,12,"Up"); + else if(FCS->GetGearPos() > 0.99) + snprintf(gear,12,"Down"); else - snprintf(gear,10,"Down"); - snprintf(out,80, " Flaps: %3s Gear: %4s\n",flap,gear); + snprintf(gear,12,"In Transit"); + snprintf(out,80, " Flaps: %3s Gear: %12s\n",flap,gear); cout << out; snprintf(out,80, " Speed: %4.0f KCAS Mach: %5.2f\n", FDMExec->GetAuxiliary()->GetVcalibratedKTS(), diff --git a/src/FDM/JSBSim/FGState.h b/src/FDM/JSBSim/FGState.h index 8bb298ab4..a60abaea1 100644 --- a/src/FDM/JSBSim/FGState.h +++ b/src/FDM/JSBSim/FGState.h @@ -319,10 +319,11 @@ private: FGMatrix33 mTb2s; FGColumnVector4 vQtrn; FGColumnVector4 vlastQdot; + FGColumnVector4 vQdot; FGColumnVector3 vUVW; FGColumnVector3 vLocalVelNED; FGColumnVector3 vLocalEuler; - FGColumnVector4 vQdot; + FGColumnVector4 vTmp; FGColumnVector3 vEuler; diff --git a/src/FDM/JSBSim/FGTable.h b/src/FDM/JSBSim/FGTable.h index 20201b83a..4a20d688a 100644 --- a/src/FDM/JSBSim/FGTable.h +++ b/src/FDM/JSBSim/FGTable.h @@ -102,8 +102,8 @@ private: enum type {tt1D, tt2D} Type; double** Data; int nRows, nCols; - unsigned int colCounter; - unsigned int rowCounter; + int colCounter; + int rowCounter; double** Allocate(void); void Debug(void); }; diff --git a/src/FDM/JSBSim/FGTrim.h b/src/FDM/JSBSim/FGTrim.h index 6f08de0af..ec53d57a6 100644 --- a/src/FDM/JSBSim/FGTrim.h +++ b/src/FDM/JSBSim/FGTrim.h @@ -147,7 +147,7 @@ class FGTrim : public FGJSBBase private: vector TrimAxes; - int current_axis; + unsigned int current_axis; int N, Nsub; TrimMode mode; int DebugLevel, Debug; @@ -163,7 +163,7 @@ private: bool trimudot; bool gamma_fallback; bool trim_failed; - int axis_count; + unsigned int axis_count; int solutionDomain; double xlo,xhi,alo,ahi; double targetNlf; diff --git a/src/FDM/JSBSim/JSBSim.cpp b/src/FDM/JSBSim/JSBSim.cpp index a5ffaab04..59d8672e0 100644 --- a/src/FDM/JSBSim/JSBSim.cpp +++ b/src/FDM/JSBSim/JSBSim.cpp @@ -1,182 +1,182 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: JSBSim.cpp - Author: Jon S. Berndt - Date started: 08/17/99 - Purpose: Standalone version of JSBSim. - Called by: The USER. - - ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.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 - 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. - -FUNCTIONAL DESCRIPTION --------------------------------------------------------------------------------- - -This class Handles calling JSBSim standalone. It is set up for compilation under -Borland C+Builder or other compiler. - -HISTORY --------------------------------------------------------------------------------- -08/17/99 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGFDMExec.h" -#include "FGRotation.h" -#include "FGAtmosphere.h" -#include "FGState.h" -#include "FGFCS.h" -#include "FGAircraft.h" -#include "FGTranslation.h" -#include "FGPosition.h" -#include "FGAuxiliary.h" -#include "FGOutput.h" -#include "FGConfigFile.h" - -#ifdef FGFS -#include -#include STL_IOSTREAM -# ifdef SG_HAVE_STD_INCLUDES -# include -# else -# include -# endif -#else -# if defined(sgi) && !defined(__GNUC__) -# include -# include -# else -# include -# include -# endif -#endif - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -GLOBAL DATA -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -static const char *IdSrc = "$Id$"; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs] -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Standalone JSBSim main program - This is the wrapper program used to instantiate the JSBSim system and control - it. Use this program to build a version of JSBSim that can be run from the - command line. To get any use out of this, you will have to create a script - to run a test case and specify what kind of output you would like. - @author Jon S. Berndt - @version $Id$ - @see - -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -int main(int argc, char** argv) -{ - FGFDMExec* FDMExec; - float cmd = 0.0; - bool result = false; - bool scripted = false; - - if (argc == 2) { - FGConfigFile testFile(argv[1]); - - if (!testFile.IsOpen()) { - cout << "Script file not opened" << endl; - exit(-1); - } - - testFile.GetNextConfigLine(); - if (testFile.GetValue("runscript").length() <= 0) { - cout << "File: " << argv[1] << " is not a script file" << endl; - exit(-1); - } - scripted = true; - } else if (argc != 3) { - cout << endl - << " You must enter the name of a registered aircraft and reset point:" - << endl << endl << " FDM " << endl; - cout << endl << " Alternatively, you may specify only the name of a script file:" - << endl << endl << " FDM