FGAircraft::FGAircraft(FGFDMExec* fdmex) : FGModel(fdmex),
vMoments(3),
vForces(3),
+ vFs(3),
vXYZrp(3),
vbaseXYZcg(3),
vXYZcg(3),
vXYZep(3),
- vEuler(3),
- vFs(3)
+ vEuler(3)
+
{
Name = "FGAircraft";
for (int i = 1; i <= 3; i++) vForces(i) = vMoments(i) = 0.0;
MassChange();
-
FMProp();
FMAero();
FMGear();
static FGColumnVector vXYZtank(3);
float Tw;
float IXXt, IYYt, IZZt, IXZt;
- int t;
+ unsigned int t;
unsigned int axis_ctr;
for (axis_ctr=1; axis_ctr<=3; axis_ctr++) vXYZtank(axis_ctr) = 0.0;
float Oshortage, Fshortage;
- for (int e=0; e<numEngines; e++) {
+ for (unsigned int e=0; e<numEngines; e++) {
Fshortage = Oshortage = 0.0;
for (t=0; t<numTanks; t++) {
switch(Engine[e]->GetType()) {
void FGAircraft::FMAero(void) {
static FGColumnVector vDXYZcg(3);
+ static FGColumnVector vAeroBodyForces(3);
unsigned int axis_ctr,ctr;
for (axis_ctr=1; axis_ctr<=3; axis_ctr++) vFs(axis_ctr) = 0.0;
}
}
- vForces += State->GetTs2b(alpha, beta)*vFs;
-
+ vAeroBodyForces = State->GetTs2b(alpha, beta)*vFs;
+ vForces += vAeroBodyForces;
// The d*cg distances below, given in inches, are the distances FROM the c.g.
// TO the reference point. Since the c.g. and ref point are given in inches in
// the structural system (X positive rearwards) and the body coordinate system
vDXYZcg(eY) = (vXYZrp(eY) - vXYZcg(eY))/12.0;
vDXYZcg(eZ) = -(vXYZrp(eZ) - vXYZcg(eZ))/12.0;
- vMoments(eL) += vForces(eZ)*vDXYZcg(eY) - vForces(eY)*vDXYZcg(eZ); // rolling moment
- vMoments(eM) += vForces(eX)*vDXYZcg(eZ) - vForces(eZ)*vDXYZcg(eX); // pitching moment
- vMoments(eN) += vForces(eY)*vDXYZcg(eX) - vForces(eX)*vDXYZcg(eY); // yawing moment
-
+ vMoments(eL) += vAeroBodyForces(eZ)*vDXYZcg(eY) - vAeroBodyForces(eY)*vDXYZcg(eZ); // rolling moment
+ vMoments(eM) += vAeroBodyForces(eX)*vDXYZcg(eZ) - vAeroBodyForces(eZ)*vDXYZcg(eX); // pitching moment
+ vMoments(eN) += vAeroBodyForces(eY)*vDXYZcg(eX) - vAeroBodyForces(eX)*vDXYZcg(eY); // yawing moment
+
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].TotalValue();
/******************************************************************************/
void FGAircraft::FMProp(void) {
- for (int i=0;i<numEngines;i++) {
+ for (unsigned int i=0;i<numEngines;i++) {
+
+ // Changes required here for new engine placement parameters (i.e. location and direction)
+
vForces(eX) += Engine[i]->CalcThrust();
}
+
}
/******************************************************************************/
while ((token = AC_cfg->GetValue()) != "/METRICS") {
*AC_cfg >> parameter;
- if (parameter == "AC_WINGAREA") *AC_cfg >> WingArea;
- else if (parameter == "AC_WINGSPAN") *AC_cfg >> WingSpan;
- else if (parameter == "AC_CHORD") *AC_cfg >> cbar;
- else if (parameter == "AC_IXX") *AC_cfg >> baseIxx;
- else if (parameter == "AC_IYY") *AC_cfg >> baseIyy;
- else if (parameter == "AC_IZZ") *AC_cfg >> baseIzz;
- else if (parameter == "AC_IXZ") *AC_cfg >> baseIxz;
- else if (parameter == "AC_EMPTYWT") *AC_cfg >> EmptyWeight;
- else if (parameter == "AC_CGLOC") *AC_cfg >> vbaseXYZcg(eX) >> vbaseXYZcg(eY) >> vbaseXYZcg(eZ);
- else if (parameter == "AC_EYEPTLOC") *AC_cfg >> vXYZep(eX) >> vXYZep(eY) >> vXYZep(eZ);
- else if (parameter == "AC_AERORP") *AC_cfg >> vXYZrp(eX) >> vXYZrp(eY) >> vXYZrp(eZ);
- else if (parameter == "AC_ALPHALIMITS") *AC_cfg >> alphaclmin >> alphaclmax;
+ if (parameter == "AC_WINGAREA") {
+ *AC_cfg >> WingArea;
+ cout << " WingArea: " << WingArea << endl;
+ } else if (parameter == "AC_WINGSPAN") {
+ *AC_cfg >> WingSpan;
+ cout << " WingSpan: " << WingSpan << endl;
+ } else if (parameter == "AC_CHORD") {
+ *AC_cfg >> cbar;
+ cout << " Chord: " << cbar << endl;
+ } else if (parameter == "AC_IXX") {
+ *AC_cfg >> baseIxx;
+ cout << " baseIxx: " << baseIxx << endl;
+ } else if (parameter == "AC_IYY") {
+ *AC_cfg >> baseIyy;
+ cout << " baseIyy: " << baseIyy << endl;
+ } else if (parameter == "AC_IZZ") {
+ *AC_cfg >> baseIzz;
+ cout << " baseIzz: " << baseIzz << endl;
+ } else if (parameter == "AC_IXZ") {
+ *AC_cfg >> baseIxz;
+ cout << " baseIxz: " << baseIxz << endl;
+ } else if (parameter == "AC_EMPTYWT") {
+ *AC_cfg >> EmptyWeight;
+ cout << " EmptyWeight: " << EmptyWeight << endl;
+ } else if (parameter == "AC_CGLOC") {
+ *AC_cfg >> vbaseXYZcg(eX) >> vbaseXYZcg(eY) >> vbaseXYZcg(eZ);
+ cout << " Xcg: " << vbaseXYZcg(eX)
+ << " Ycg: " << vbaseXYZcg(eY)
+ << " Zcg: " << vbaseXYZcg(eZ)
+ << endl;
+ } else if (parameter == "AC_EYEPTLOC") {
+ *AC_cfg >> vXYZep(eX) >> vXYZep(eY) >> vXYZep(eZ);
+ cout << " Xep: " << vXYZep(eX)
+ << " Yep: " << vXYZep(eY)
+ << " Zep: " << vXYZep(eZ)
+ << endl;
+ } else if (parameter == "AC_AERORP") {
+ *AC_cfg >> vXYZrp(eX) >> vXYZrp(eY) >> vXYZrp(eZ);
+ cout << " Xrp: " << vXYZrp(eX)
+ << " Yrp: " << vXYZrp(eY)
+ << " Zrp: " << vXYZrp(eZ)
+ << endl;
+ } else if (parameter == "AC_ALPHALIMITS") {
+ *AC_cfg >> alphaclmin >> alphaclmax;
+ cout << " Maximum Alpha: " << alphaclmax
+ << " Minimum Alpha: " << alphaclmin
+ << endl;
+ }
}
}
inline float GetIyy(void) { return Iyy; }
inline float GetIzz(void) { return Izz; }
inline float GetIxz(void) { return Ixz; }
- inline int GetNumEngines(void) { return numEngines; }
+ inline unsigned int GetNumEngines(void) { return numEngines; }
inline FGColumnVector GetXYZcg(void) { return vXYZcg; }
+ inline FGColumnVector GetXYZrp(void) { return vXYZrp; }
inline float GetNlf(void) { return nlf; }
inline float GetAlphaCLMax(void) { return alphaclmax; }
inline float GetAlphaCLMin(void) { return alphaclmin; }
FGColumnVector vEuler;
float baseIxx, baseIyy, baseIzz, baseIxz, EmptyMass, Mass;
float Ixx, Iyy, Izz, Ixz;
- float rho, qbar, Vt;
float alpha, beta;
float WingArea, WingSpan, cbar;
float Weight, EmptyWeight;
if (type == TABLE) {
*AC_cfg >> multparms;
if (multparms.substr(0,1) == "F") {
- LookupR = State->GetParameterIndex(multparms);
+ LookupC = State->GetParameterIndex(multparms);
cout << " Column indexing parameter: " << multparms << endl;
} else {
LookupC = atoi(multparms.c_str());
n = multparms.find("|");
start = mult_count = multipliers = 0;
- while(n < end && n >= 0) {
+ while (n < end && n >= 0) {
n -= start;
mult_idx[mult_count] = State->GetParameterIndex(multparms.substr(start,n));
multipliers += mult_idx[mult_count];
DEFINES
*******************************************************************************/
-#ifndef FGFS
using std::string;
using std::ifstream;
-#endif
/*******************************************************************************
CLASS DECLARATION
// $Log$
-// Revision 1.12 2000/05/30 14:48:53 curt
-// 05/30/2000 updates from Jon Berdnt. Landing gear code now is beginning to
-// work.
+// Revision 1.13 2000/07/06 19:02:46 curt
+// Updates from Jon's official CVS tree.
//
// Revision 1.3 2000/04/26 10:55:57 jsb
// Made changes as required by Curt to install JSBSim into FGFS
public:
- static const int ALL_ENGINES = -1;
- static const int MAX_ENGINES = 10;
+ enum {
+ ALL_ENGINES = -1,
+ MAX_ENGINES = 10,
- static const int ALL_WHEELS = -1;
- static const int MAX_WHEELS = 3;
+ ALL_WHEELS = -1,
+ MAX_WHEELS = 3
+ };
private:
// $Log$
-// Revision 1.11 2000/05/30 14:48:53 curt
-// 05/30/2000 updates from Jon Berdnt. Landing gear code now is beginning to
-// work.
+// Revision 1.12 2000/07/06 19:02:46 curt
+// Updates from Jon's official CVS tree.
+//
+// Revision 1.6 2000/06/03 13:59:52 jsb
+// Changes for compatibility with MSVC
//
// Revision 1.5 2000/05/12 22:45:35 jsb
// Removed extraneous namespace identifiers and header files
enginefile >> X;
enginefile >> Y;
enginefile >> Z;
+ enginefile >> EnginePitch;
+ enginefile >> EngineYaw;
enginefile >> BrakeHorsePower;
enginefile >> MaxThrottle;
enginefile >> MinThrottle;
enginefile >> X;
enginefile >> Y;
enginefile >> Z;
+ enginefile >> EnginePitch;
+ enginefile >> EngineYaw;
enginefile >> SLThrustMax;
enginefile >> VacThrustMax;
enginefile >> MaxThrottle;
string Name;
EngineType Type;
float X, Y, Z;
+ float EnginePitch;
+ float EngineYaw;
float SLThrustMax;
float VacThrustMax;
float SLFuelFlowMax;
void FGFCS::SetThrottleCmd(int engineNum, float setting) {
if (engineNum < 0) {
- for (int ctr=0;ctr<Aircraft->GetNumEngines();ctr++) ThrottleCmd[ctr] = setting;
+ for (unsigned int ctr=0;ctr<Aircraft->GetNumEngines();ctr++) ThrottleCmd[ctr] = setting;
} else {
ThrottleCmd[engineNum] = setting;
}
void FGFCS::SetThrottlePos(int engineNum, float setting) {
if (engineNum < 0) {
- for (int ctr=0;ctr<=Aircraft->GetNumEngines();ctr++) ThrottlePos[ctr] = ThrottleCmd[ctr];
+ for (unsigned int ctr=0;ctr<=Aircraft->GetNumEngines();ctr++) ThrottlePos[ctr] = ThrottleCmd[ctr];
} else {
ThrottlePos[engineNum] = setting;
}
return Components[idx]->GetName();
}
-#pragma warn .8030
-
FGInitialCondition::~FGInitialCondition(void) {}
-;
void FGInitialCondition::SetVcalibratedKtsIC(float tt) {
Rotation = Exec->GetRotation();
WOW = false;
+ FirstContact = false;
+ Reported = false;
+ DistanceTraveled = 0.0;
+ MaximumStrutForce = MaximumStrutTravel = 0.0;
}
if (compressLength > 0.00) {
WOW = true;
-
vWhlVelVec = State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec);
vWhlVelVec += Position->GetVel();
+
compressSpeed = vWhlVelVec(eZ);
+ if (!FirstContact) {
+ FirstContact = true;
+ SinkRate = compressSpeed;
+ GroundSpeed = Position->GetVel().Magnitude();
+ }
+
vWhlVelVec = -1.0 * vWhlVelVec.Normalize();
vWhlVelVec(eZ) = 0.00;
vLocalForce(eX) = fabs(vLocalForce(eZ) * statFCoeff) * vWhlVelVec(eX);
vLocalForce(eY) = fabs(vLocalForce(eZ) * statFCoeff) * vWhlVelVec(eY);
+ MaximumStrutForce = max(MaximumStrutForce, fabs(vLocalForce(eZ)));
+ MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength));
+
vForce = State->GetTl2b() * vLocalForce ;
vMoment = vWhlBodyVec * vForce;
} else {
WOW = false;
+
+ if (Position->GetDistanceAGL() > 200.0) {
+ FirstContact = false;
+ Reported = false;
+ DistanceTraveled = 0.0;
+ MaximumStrutForce = MaximumStrutTravel = 0.0;
+ }
+
vForce.InitMatrix();
vMoment.InitMatrix();
}
+ if (FirstContact) {
+ DistanceTraveled += Position->GetVel().Magnitude()*State->Getdt()*Aircraft->GetRate();
+ }
+
+ if (Position->GetVel().Magnitude() <= 0.05 && !Reported) {
+ Report();
+ }
return vForce;
}
/******************************************************************************/
+void FGLGear::Report(void)
+{
+ cout << endl << "Touchdown report for " << name << endl;
+ cout << " Sink rate at contact: " << SinkRate << " fps, "
+ << SinkRate*0.3408 << " mps" << endl;
+ cout << " Contact ground speed: " << GroundSpeed*.5925 << " knots, "
+ << GroundSpeed*0.3408 << " 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: " << DistanceTraveled << " ft, "
+ << DistanceTraveled*0.3408 << " meters" << endl;
+ Reported = true;
+}
+
float statFCoeff, rollFCoeff, skidFCoeff;
float frictionForce, compForce;
float brakePct, brakeForce, brakeCoeff;
+ double SinkRate;
+ double GroundSpeed;
+ double DistanceTraveled;
+ double MaximumStrutForce;
+ double MaximumStrutTravel;
bool WOW;
+ bool FirstContact;
+ bool Reported;
string name;
FGFDMExec* Exec;
FGAircraft* Aircraft;
FGPosition* Position;
FGRotation* Rotation;
+
+ void Report(void);
};
#include "FGAircraft.h"
/******************************************************************************/
+FGColumnVector FGColumnVector::multElementWise(const FGColumnVector& V)
+{
+ if (Rows() != 3 || V.Rows() != 3) {
+ MatrixException mE;
+ mE.Message = "Invalid row count in vector cross product function";
+ throw mE;
+ }
+
+ FGColumnVector Product(3);
+
+ Product(1) = data[1][1] * V(1);
+ Product(2) = data[2][1] * V(2);
+ Product(3) = data[3][1] * V(3);
+
+ return Product;
+}
+
+/******************************************************************************/
# include <simgear/compiler.h>
# ifdef FG_HAVE_STD_INCLUDES
# include <fstream>
+# include <cmath>
# else
# include <fstream.h>
+# include <math.h>
# endif
#else
# include <fstream>
+# include <cmath>
#endif
#include <string>
friend FGColumnVector operator*(const FGMatrix& M, const FGColumnVector& V);
double& operator()(int m) const;
+
+ FGColumnVector multElementWise(const FGColumnVector& V);
};
/******************************************************************************/
string Name;
virtual bool Run(void);
virtual bool InitModel(void);
- virtual void SetRate(int tt) {rate = tt;};
+ virtual void SetRate(int tt) {rate = tt;}
+ virtual int GetRate(void) {return rate;}
protected:
enum {eU=1, eV, eW};
LongitudeDot = LatitudeDot = RadiusDot = 0.0;
lastLongitudeDot = lastLatitudeDot = lastRadiusDot = 0.0;
Longitude = Latitude = 0.0;
- h = gamma = Vt = 0.0;
+ gamma = Vt = 0.0;
+ h = 3.0; // Est. height of aircraft cg off runway
SeaLevelRadius = EARTHRAD; // For initialization ONLY
Radius = SeaLevelRadius + h;
RunwayRadius = SeaLevelRadius;
#include "FGAuxiliary.h"
#include "FGOutput.h"
-#ifndef M_PI
-/* get a definition for pi */
-#include <Include/fg_constants.h>
-#define M_PI FG_PI
-#endif
-
/*******************************************************************************
************************************ CODE **************************************
*******************************************************************************/
# include <cmath>
#endif
+#ifndef M_PI
+# include <simgear/constants.h>
+# define M_PI FG_PI
+#endif
+
#include "FGModel.h"
#include "FGMatrix.h"
CLASS DECLARATION
*******************************************************************************/
-#pragma warn -8026
-
class FGRotation : public FGModel
{
FGColumnVector vPQR;
inline float Gettht(void) {return vEuler(2);}
inline float Getpsi(void) {return vEuler(3);}
};
-#pragma warn .8026
/******************************************************************************/
#endif
# include <cmath>
#endif
+#ifndef M_PI // support for silly Microsoft compiler
+# include <simgear/constants.h>
+# define M_PI FG_PI
+#endif
+
#include "FGState.h"
#include "FGFDMExec.h"
#include "FGAtmosphere.h"
FGColumnVector FGState::CalcEuler(void) {
static FGColumnVector vEuler(3);
- if (mTl2b(3,3) == 0) vEuler(ePhi) = 0.0;
- else vEuler(ePhi) = atan2(mTl2b(2,3), mTl2b(3,3));
+ if (mTl2b(3,3) == 0.0) mTl2b(3,3) = 0.0000001;
+ if (mTl2b(1,1) == 0.0) mTl2b(1,1) = 0.0000001;
+ vEuler(ePhi) = atan2(mTl2b(2,3), mTl2b(3,3));
vEuler(eTht) = asin(-mTl2b(1,3));
-
- if (mTl2b(1,1) == 0.0) vEuler(ePsi) = 0.0;
- else vEuler(ePsi) = atan2(mTl2b(1,2), mTl2b(1,1));
+ vEuler(ePsi) = atan2(mTl2b(1,2), mTl2b(1,1));
if (vEuler(ePsi) < 0.0) vEuler(ePsi) += 2*M_PI;
inline float Getadot(void) { return adot; }
inline float Getbdot(void) { return bdot; }
- inline float GetLocalAltitudeOverRunway(void) { return LocalAltitudeOverRunway; }
inline float Geta(void) { return a; }
inline float Getsim_time(void) { return sim_time; }
inline void Setadot(float tt) { adot = tt; }
inline void Setbdot(float tt) { bdot = tt; }
- inline void SetLocalAltitudeOverRunway(float tt) { LocalAltitudeOverRunway = tt; }
inline void Seta(float tt) { a = tt; }
inline float Setsim_time(float tt) {
float sim_time, dt;
FGFDMExec* FDMExec;
- float LocalAltitudeOverRunway;
FGMatrix mTb2l;
FGMatrix mTl2b;
FGMatrix mTs2b;
CLASS DECLARATION
*******************************************************************************/
-#pragma warn -8026
-
class FGTranslation : public FGModel {
public:
FGTranslation(FGFDMExec*);
void GetState(void);
};
-#pragma warn .8026
/******************************************************************************/
#endif
#include "FGState.h"
#include "FGFDMExec.h"
-#ifndef M_PI_2
-/* get a definition for pi */
-#include <Include/fg_constants.h>
-#define M_PI_2 FG_PI_2
-#endif
-
/*******************************************************************************
************************************ CODE **************************************
*******************************************************************************/
float cmd = 0.0;
- while (FDMExec->GetState()->Getsim_time() <= 5.0)
+ while (FDMExec->GetState()->Getsim_time() <= 145.0)
{
// Fake an elevator ramp here after 1 second, hold for one second, ramp down
-
+ /*
if (FDMExec->GetState()->Getsim_time() >= 1.00 &&
FDMExec->GetState()->Getsim_time() < 2.0)
{
cmd = 0.00;
}
FDMExec->GetFCS()->SetDeCmd(cmd); // input between -1 and 1
-
+ */
FDMExec->Run();
}