1
0
Fork 0

Sync with latest JSBSim changes.

This commit is contained in:
curt 2001-11-30 17:49:37 +00:00
parent c167c60de9
commit 71a562b695
31 changed files with 774 additions and 475 deletions

View file

@ -198,7 +198,7 @@ void FGJSBsim::init() {
break; break;
} }
stall_warning->setBoolValue(false); stall_warning->setDoubleValue(0);
SG_LOG( SG_FLIGHT, SG_INFO, " Bank Angle: " SG_LOG( SG_FLIGHT, SG_INFO, " Bank Angle: "
<< Rotation->Getphi()*RADTODEG << " deg" ); << Rotation->Getphi()*RADTODEG << " deg" );
@ -382,7 +382,7 @@ bool FGJSBsim::copy_from_JSBsim() {
// Auxiliary->GetNpilot(2)/32.1739, // Auxiliary->GetNpilot(2)/32.1739,
// Auxiliary->GetNpilot(3)/32.1739 ); // Auxiliary->GetNpilot(3)/32.1739 );
_set_Nlf( Aerodynamics->GetNlf() ); _set_Nlf( Aircraft->GetNlf() );
// Velocities // Velocities

56
src/FDM/JSBSim/AUTHORS Normal file
View file

@ -0,0 +1,56 @@
AUTHORS
-------
Jon S. Berndt
primary architect and coordinator
jsb@hal-pc.org
CVS access as developer (r/w)
Tony Peden
additional architecture support
trimming and aerodynamics
interface with flightgear
apeden@earthlink.net
CVS access as developer (r/w)
Additional support (programming, bug fixes, aircraft models)
by the FlightGear team and others as listed:
Curt Olson
wrote initial interface with flightgear
works flightgear/jsbsim issues
curt@flightgear.org
Norman Vine
matrix math class optimization support
general C++ suggestions, debugging, and support
nhv@cape.com
Christian Mayer
JSBSim compatibility with MSVC
mail@ChristianMayer.de
Erik Hofman
JSBSim compatibility with IRIX
erik@ehofman.com
David Megginson
ported Dave Luff's piston engine model initially to JSBSim
creation of multi-engine C-310 model and testing/debugging
general C++ suggestions, debugging, and support
david@megginson.com
Ross Golder
improvements to the build process and auto* files
ross@golder.org
Dave Luff
wrote the piston engine model used by LaRCSim and is ported to JSBSim
eazdluf@nottingham.ac.uk
Norman Princen
provided an improved gear model
nprincen@hotmail.com

View file

@ -100,7 +100,10 @@ bool FGAerodynamics::Run(void)
vFs(axis_ctr+1) += Coeff[axis_ctr][ctr]->TotalValue(); vFs(axis_ctr+1) += Coeff[axis_ctr][ctr]->TotalValue();
} }
} }
//correct signs of drag and lift to wind axes convention
//positive forward, right, down
vFs(1)*=-1; vFs(3)*=-1;
//cout << "Aircraft::vFs: " << vFs << endl;
vForces = State->GetTs2b()*vFs; vForces = State->GetTs2b()*vFs;
vDXYZcg(eX) = -(Aircraft->GetXYZrp(eX) vDXYZcg(eX) = -(Aircraft->GetXYZrp(eX)
@ -198,17 +201,6 @@ string FGAerodynamics::GetCoefficientValues(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGAerodynamics::GetNlf(void)
{
if (fabs(Position->GetGamma()) < 1.57) {
return (vFs(eZ)/(MassBalance->GetWeight()*cos(Position->GetGamma())));
} else {
return 0.0;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGAerodynamics::GetLoD(void) double FGAerodynamics::GetLoD(void)
{ {
double LoD; double LoD;

View file

@ -134,8 +134,6 @@ public:
coefficients */ coefficients */
string GetCoefficientValues(void); string GetCoefficientValues(void);
/// Gets the Normal Load Factor
double GetNlf(void);
private: private:
typedef map<string,int> AxisIndex; typedef map<string,int> AxisIndex;

View file

@ -105,7 +105,8 @@ FGAircraft::FGAircraft(FGFDMExec* fdmex) : FGModel(fdmex),
vXYZep(3), vXYZep(3),
vDXYZcg(3), vDXYZcg(3),
vBodyAccel(3), vBodyAccel(3),
vNcg(3) vNcg(3),
vNwcg(3)
{ {
Name = "FGAircraft"; Name = "FGAircraft";
alphaclmin = alphaclmax = 0; alphaclmin = alphaclmax = 0;
@ -180,6 +181,9 @@ bool FGAircraft::Run(void)
vNcg = vBodyAccel/Inertial->gravity(); vNcg = vBodyAccel/Inertial->gravity();
vNwcg = State->GetTb2s() * vNcg;
vNwcg(3) = -1*vNwcg(3) + 1;
if (alphaclmax != 0) { if (alphaclmax != 0) {
if (Translation->Getalpha() > 0.85*alphaclmax) { if (Translation->Getalpha() > 0.85*alphaclmax) {
impending_stall = 10*(Translation->Getalpha()/alphaclmax - 0.85); impending_stall = 10*(Translation->Getalpha()/alphaclmax - 0.85);
@ -196,6 +200,13 @@ bool FGAircraft::Run(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
float FGAircraft::GetNlf(void)
{
return vNwcg(3);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::ReadPrologue(FGConfigFile* AC_cfg) void FGAircraft::ReadPrologue(FGConfigFile* AC_cfg)
{ {
string token = AC_cfg->GetValue(); string token = AC_cfg->GetValue();

View file

@ -200,7 +200,11 @@ public:
inline void SetAlphaCLMax(double tt) { alphaclmax=tt; } inline void SetAlphaCLMax(double tt) { alphaclmax=tt; }
inline void SetAlphaCLMin(double tt) { alphaclmin=tt; } inline void SetAlphaCLMin(double tt) { alphaclmin=tt; }
inline bool GetStallWarn(void) { return impending_stall; } inline double GetStallWarn(void) { return impending_stall; }
float GetNlf(void);
inline FGColumnVector3& GetNwcg(void) { return vNwcg; }
private: private:
FGColumnVector3 vMoments; FGColumnVector3 vMoments;
@ -211,6 +215,7 @@ private:
FGColumnVector3 vDXYZcg; FGColumnVector3 vDXYZcg;
FGColumnVector3 vBodyAccel; FGColumnVector3 vBodyAccel;
FGColumnVector3 vNcg; FGColumnVector3 vNcg;
FGColumnVector3 vNwcg;
double WingArea, WingSpan, cbar, WingIncidence; double WingArea, WingSpan, cbar, WingIncidence;
double HTailArea, VTailArea, HTailArm, VTailArm; double HTailArea, VTailArea, HTailArm, VTailArm;

View file

@ -145,6 +145,7 @@ public:
inline void SetTurbGain(double tt) {TurbGain = tt;} inline void SetTurbGain(double tt) {TurbGain = tt;}
inline double GetTurbPQR(int idx) {return vTurbPQR(idx);} inline double GetTurbPQR(int idx) {return vTurbPQR(idx);}
inline FGColumnVector3& GetTurbPQR(void) {return vTurbPQR;}
private: private:
double rho; double rho;

View file

@ -64,7 +64,8 @@ CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGEngine::FGEngine(FGFDMExec* exec) { FGEngine::FGEngine(FGFDMExec* exec)
{
FDMExec = exec; FDMExec = exec;
State = FDMExec->GetState(); State = FDMExec->GetState();
Atmosphere = FDMExec->GetAtmosphere(); Atmosphere = FDMExec->GetAtmosphere();
@ -101,7 +102,8 @@ FGEngine::~FGEngine()
// This base class method removes fuel from the fuel tanks as appropriate, // This base class method removes fuel from the fuel tanks as appropriate,
// and sets the starved flag if necessary. // and sets the starved flag if necessary.
void FGEngine::ConsumeFuel(void) { void FGEngine::ConsumeFuel(void)
{
double Fshortage, Oshortage; double Fshortage, Oshortage;
FGTank* Tank; FGTank* Tank;

View file

@ -182,6 +182,9 @@ public:
/// Sets engine placement information /// Sets engine placement information
void SetPlacement(double x, double y, double z, double pitch, double yaw); void SetPlacement(double x, double y, double z, double pitch, double yaw);
/// Sets the engine number
void SetEngineNumber(int nn) {EngineNumber = nn;}
virtual double GetPowerAvailable(void) {return 0.0;}; virtual double GetPowerAvailable(void) {return 0.0;};
bool GetTrimMode(void) {return TrimMode;} bool GetTrimMode(void) {return TrimMode;}

View file

@ -67,8 +67,8 @@ const double FGJSBBase::SHRatio = 1.40;
const string FGJSBBase::needed_cfg_version = "1.55"; const string FGJSBBase::needed_cfg_version = "1.55";
const string FGJSBBase::JSBSim_version = "0.9.1"; const string FGJSBBase::JSBSim_version = "0.9.1";
queue <struct FGJSBBase::Message*> FGJSBBase::Messages; queue <FGJSBBase::Message*> FGJSBBase::Messages;
struct FGJSBBase::Message FGJSBBase::localMsg; FGJSBBase::Message FGJSBBase::localMsg;
unsigned int FGJSBBase::messageId = 0; unsigned int FGJSBBase::messageId = 0;
unsigned int FGJSBBase::frame = 0; unsigned int FGJSBBase::frame = 0;
@ -82,7 +82,7 @@ FGJSBBase::FGJSBBase()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
struct FGJSBBase::Message* FGJSBBase::PutMessage(struct Message* msg) FGJSBBase::Message* FGJSBBase::PutMessage(Message* msg)
{ {
Messages.push(msg); Messages.push(msg);
return msg; return msg;
@ -90,9 +90,9 @@ struct FGJSBBase::Message* FGJSBBase::PutMessage(struct Message* msg)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
struct FGJSBBase::Message* FGJSBBase::PutMessage(string text) FGJSBBase::Message* FGJSBBase::PutMessage(string text)
{ {
struct Message *msg = new Message(); Message *msg = new Message();
msg->text = text; msg->text = text;
msg->messageId = messageId++; msg->messageId = messageId++;
msg->subsystem = "FDM"; msg->subsystem = "FDM";
@ -103,9 +103,9 @@ struct FGJSBBase::Message* FGJSBBase::PutMessage(string text)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
struct FGJSBBase::Message* FGJSBBase::PutMessage(string text, bool bVal) FGJSBBase::Message* FGJSBBase::PutMessage(string text, bool bVal)
{ {
struct Message *msg = new Message(); Message *msg = new Message();
msg->text = text; msg->text = text;
msg->messageId = messageId++; msg->messageId = messageId++;
msg->subsystem = "FDM"; msg->subsystem = "FDM";
@ -117,9 +117,9 @@ struct FGJSBBase::Message* FGJSBBase::PutMessage(string text, bool bVal)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
struct FGJSBBase::Message* FGJSBBase::PutMessage(string text, int iVal) FGJSBBase::Message* FGJSBBase::PutMessage(string text, int iVal)
{ {
struct Message *msg = new Message(); Message *msg = new Message();
msg->text = text; msg->text = text;
msg->messageId = messageId++; msg->messageId = messageId++;
msg->subsystem = "FDM"; msg->subsystem = "FDM";
@ -131,9 +131,9 @@ struct FGJSBBase::Message* FGJSBBase::PutMessage(string text, int iVal)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
struct FGJSBBase::Message* FGJSBBase::PutMessage(string text, double dVal) FGJSBBase::Message* FGJSBBase::PutMessage(string text, double dVal)
{ {
struct Message *msg = new Message(); Message *msg = new Message();
msg->text = text; msg->text = text;
msg->messageId = messageId++; msg->messageId = messageId++;
msg->subsystem = "FDM"; msg->subsystem = "FDM";
@ -145,7 +145,7 @@ struct FGJSBBase::Message* FGJSBBase::PutMessage(string text, double dVal)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
struct FGJSBBase::Message* FGJSBBase::ReadMessage(void) FGJSBBase::Message* FGJSBBase::ReadMessage(void)
{ {
if (!Messages.empty()) return Messages.front(); if (!Messages.empty()) return Messages.front();
else return NULL; else return NULL;
@ -153,7 +153,7 @@ struct FGJSBBase::Message* FGJSBBase::ReadMessage(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
struct FGJSBBase::Message* FGJSBBase::ProcessMessage(void) FGJSBBase::Message* FGJSBBase::ProcessMessage(void)
{ {
if (!Messages.empty()) if (!Messages.empty())
localMsg = *(Messages.front()); localMsg = *(Messages.front());

View file

@ -165,7 +165,7 @@ public:
virtual ~FGJSBBase() {}; virtual ~FGJSBBase() {};
/// JSBSim Message structure /// JSBSim Message structure
struct Message { typedef struct Msg {
unsigned int fdmId; unsigned int fdmId;
unsigned int messageId; unsigned int messageId;
string text; string text;
@ -174,7 +174,7 @@ public:
bool bVal; bool bVal;
int iVal; int iVal;
double dVal; double dVal;
}; } Message;
///@name JSBSim Enums. ///@name JSBSim Enums.
//@{ //@{
@ -227,38 +227,38 @@ public:
/** Places a Message structure on the Message queue. /** Places a Message structure on the Message queue.
@param msg pointer to a Message structure @param msg pointer to a Message structure
@return pointer to a Message structure */ @return pointer to a Message structure */
struct Message* PutMessage(struct Message* msg); Message* PutMessage(Message* msg);
/** Creates a message with the given text and places it on the queue. /** Creates a message with the given text and places it on the queue.
@param text message text @param text message text
@return pointer to a Message structure */ @return pointer to a Message structure */
struct Message* PutMessage(string text); Message* PutMessage(string text);
/** Creates a message with the given text and boolean value and places it on the queue. /** Creates a message with the given text and boolean value and places it on the queue.
@param text message text @param text message text
@param bVal boolean value associated with the message @param bVal boolean value associated with the message
@return pointer to a Message structure */ @return pointer to a Message structure */
struct Message* PutMessage(string text, bool bVal); Message* PutMessage(string text, bool bVal);
/** Creates a message with the given text and integer value and places it on the queue. /** Creates a message with the given text and integer value and places it on the queue.
@param text message text @param text message text
@param iVal integer value associated with the message @param iVal integer value associated with the message
@return pointer to a Message structure */ @return pointer to a Message structure */
struct Message* PutMessage(string text, int iVal); Message* PutMessage(string text, int iVal);
/** Creates a message with the given text and double value and places it on the queue. /** Creates a message with the given text and double value and places it on the queue.
@param text message text @param text message text
@param dVal double value associated with the message @param dVal double value associated with the message
@return pointer to a Message structure */ @return pointer to a Message structure */
struct Message* PutMessage(string text, double dVal); Message* PutMessage(string text, double dVal);
/** Reads the message on the queue (but does not delete it). /** Reads the message on the queue (but does not delete it).
@return pointer to a Message structure (or NULL if no mesage) */ @return pointer to a Message structure (or NULL if no mesage) */
struct Message* ReadMessage(void); Message* ReadMessage(void);
/** Reads the message on the queue and removes it from the queue. /** Reads the message on the queue and removes it from the queue.
@return pointer to a Message structure (or NULL if no mesage) */ @return pointer to a Message structure (or NULL if no mesage) */
struct Message* ProcessMessage(void); Message* ProcessMessage(void);
//@} //@}
protected: protected:
static struct Message localMsg; static Message localMsg;
static queue <struct Message*> Messages; static queue <Message*> Messages;
virtual void Debug(void) {}; virtual void Debug(void) {};

View file

@ -148,8 +148,6 @@ void FGOutput::DelimitedOutput(string fname)
} }
if (SubSystems & ssAerosurfaces) { if (SubSystems & ssAerosurfaces) {
outstream << ", "; outstream << ", ";
outstream << "Throttle, ";
outstream << "Mixture, ";
outstream << "Aileron Cmd, "; outstream << "Aileron Cmd, ";
outstream << "Elevator Cmd, "; outstream << "Elevator Cmd, ";
outstream << "Rudder Cmd, "; outstream << "Rudder Cmd, ";
@ -224,8 +222,6 @@ void FGOutput::DelimitedOutput(string fname)
} }
if (SubSystems & ssAerosurfaces) { if (SubSystems & ssAerosurfaces) {
outstream << ", "; outstream << ", ";
outstream << FCS->GetThrottlePos(0) << ", ";
outstream << FCS->GetMixturePos(0) << ", ";
outstream << FCS->GetDaCmd() << ", "; outstream << FCS->GetDaCmd() << ", ";
outstream << FCS->GetDeCmd() << ", "; outstream << FCS->GetDeCmd() << ", ";
outstream << FCS->GetDrCmd() << ", "; outstream << FCS->GetDrCmd() << ", ";
@ -242,7 +238,7 @@ void FGOutput::DelimitedOutput(string fname)
outstream << Translation->Getqbar() << ", "; outstream << Translation->Getqbar() << ", ";
outstream << Translation->GetVt() << ", "; outstream << Translation->GetVt() << ", ";
outstream << Translation->GetUVW() << ", "; outstream << Translation->GetUVW() << ", ";
outstream << Translation->GetvAero() << ", "; outstream << Translation->GetvAeroUVW() << ", ";
outstream << Position->GetVel(); outstream << Position->GetVel();
} }
if (SubSystems & ssForces) { if (SubSystems & ssForces) {
@ -360,9 +356,9 @@ void FGOutput::SocketOutput(void)
socket->Append(Translation->GetUVW(eU)); socket->Append(Translation->GetUVW(eU));
socket->Append(Translation->GetUVW(eV)); socket->Append(Translation->GetUVW(eV));
socket->Append(Translation->GetUVW(eW)); socket->Append(Translation->GetUVW(eW));
socket->Append(Translation->GetvAero(eU)); socket->Append(Translation->GetvAeroUVW(eU));
socket->Append(Translation->GetvAero(eV)); socket->Append(Translation->GetvAeroUVW(eV));
socket->Append(Translation->GetvAero(eW)); socket->Append(Translation->GetvAeroUVW(eW));
socket->Append(Position->GetVn()); socket->Append(Position->GetVn());
socket->Append(Position->GetVe()); socket->Append(Position->GetVe());
socket->Append(Position->GetVd()); socket->Append(Position->GetVd());

View file

@ -144,6 +144,7 @@ Notes: [TP] Make sure that -Vt <= hdot <= Vt, which, of course, should always
bool FGPosition::Run(void) { bool FGPosition::Run(void) {
double cosLat; double cosLat;
double hdot_Vt; double hdot_Vt;
FGColumnVector3 vMac;
if (!FGModel::Run()) { if (!FGModel::Run()) {
GetState(); GetState();
@ -171,7 +172,13 @@ bool FGPosition::Run(void) {
DistanceAGL = Radius - RunwayRadius; // Geocentric DistanceAGL = Radius - RunwayRadius; // Geocentric
hoverb = DistanceAGL/b;
hoverbcg = DistanceAGL/b;
vMac=State->GetTb2l()*Aircraft->GetXYZrp();
vMac *= inchtoft;
hoverbmac = (DistanceAGL + vMac(3))/b;
if (Vt > 0) { if (Vt > 0) {
hdot_Vt = RadiusDot/Vt; hdot_Vt = RadiusDot/Vt;
@ -209,7 +216,7 @@ void FGPosition::Seth(double tt) {
h = tt; h = tt;
Radius = h + SeaLevelRadius; Radius = h + SeaLevelRadius;
DistanceAGL = Radius - RunwayRadius; // Geocentric DistanceAGL = Radius - RunwayRadius; // Geocentric
hoverb = DistanceAGL/b; hoverbcg = DistanceAGL/b;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -218,7 +225,7 @@ void FGPosition::SetDistanceAGL(double tt) {
DistanceAGL=tt; DistanceAGL=tt;
Radius = RunwayRadius + DistanceAGL; Radius = RunwayRadius + DistanceAGL;
h = Radius - SeaLevelRadius; h = Radius - SeaLevelRadius;
hoverb = DistanceAGL/b; hoverbcg = DistanceAGL/b;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -105,7 +105,8 @@ public:
inline double GetGamma(void) { return gamma; } inline double GetGamma(void) { return gamma; }
inline void SetGamma(double tt) { gamma = tt; } inline void SetGamma(double tt) { gamma = tt; }
inline double GetHOverB(void) { return hoverb; } inline double GetHOverBCG(void) { return hoverbcg; }
inline double GetHOverBMAC(void){ return hoverbmac; }
void SetvVel(const FGColumnVector3& v) { vVel = v; } void SetvVel(const FGColumnVector3& v) { vVel = v; }
void SetLatitude(double tt) { Latitude = tt; } void SetLatitude(double tt) { Latitude = tt; }
void SetLongitude(double tt) { Longitude = tt; } void SetLongitude(double tt) { Longitude = tt; }
@ -133,7 +134,7 @@ private:
double SeaLevelRadius; double SeaLevelRadius;
double gamma; double gamma;
double Vt, Vground; double Vt, Vground;
double hoverb,b; double hoverbcg,hoverbmac,b;
double psigt; double psigt;

View file

@ -50,7 +50,7 @@ FGPropeller::FGPropeller(FGFDMExec* exec, FGConfigFile* Prop_cfg) : FGThruster(e
string token; string token;
int rows, cols; int rows, cols;
MaxPitch = MinPitch = P_Factor = Sense = 0.0; MaxPitch = MinPitch = P_Factor = Sense = Pitch = 0.0;
Name = Prop_cfg->GetValue("NAME"); Name = Prop_cfg->GetValue("NAME");
Prop_cfg->GetNextConfigLine(); Prop_cfg->GetNextConfigLine();
@ -138,7 +138,7 @@ FGPropeller::~FGPropeller()
double FGPropeller::Calculate(double PowerAvailable) double FGPropeller::Calculate(double PowerAvailable)
{ {
double J, C_Thrust, omega; double J, C_Thrust, omega;
double Vel = (fdmex->GetTranslation()->GetvAero())(1); double Vel = fdmex->GetTranslation()->GetvAeroUVW(eU);
double rho = fdmex->GetAtmosphere()->GetDensity(); double rho = fdmex->GetAtmosphere()->GetDensity();
double RPS = RPM/60.0; double RPS = RPM/60.0;
double alpha, beta; double alpha, beta;
@ -194,7 +194,7 @@ double FGPropeller::GetPowerRequired(void)
double cPReq, RPS = RPM / 60.0; double cPReq, RPS = RPM / 60.0;
double J = (fdmex->GetTranslation()->GetvAero())(1) / (Diameter * RPS); double J = fdmex->GetTranslation()->GetvAeroUVW(eU) / (Diameter * RPS);
double rho = fdmex->GetAtmosphere()->GetDensity(); double rho = fdmex->GetAtmosphere()->GetDensity();
if (MaxPitch == MinPitch) { // Fixed pitch prop if (MaxPitch == MinPitch) { // Fixed pitch prop

View file

@ -62,14 +62,14 @@ CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec) FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec),
Forces(3),
Moments(3)
{ {
Name = "FGPropulsion"; Name = "FGPropulsion";
numSelectedFuelTanks = numSelectedOxiTanks = 0; numSelectedFuelTanks = numSelectedOxiTanks = 0;
numTanks = numEngines = numThrusters = 0; numTanks = numEngines = numThrusters = 0;
numOxiTanks = numFuelTanks = 0; numOxiTanks = numFuelTanks = 0;
Forces = new FGColumnVector3(3);
Moments = new FGColumnVector3(3);
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl; if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
} }
@ -80,8 +80,6 @@ FGPropulsion::~FGPropulsion()
{ {
for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i]; for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
Engines.clear(); Engines.clear();
if (Forces) delete Forces;
if (Moments) delete Moments;
if (debug_lvl & 2) cout << "Destroyed: FGPropulsion" << endl; if (debug_lvl & 2) cout << "Destroyed: FGPropulsion" << endl;
} }
@ -92,16 +90,16 @@ bool FGPropulsion::Run(void)
double PowerAvailable; double PowerAvailable;
dt = State->Getdt(); dt = State->Getdt();
Forces->InitMatrix(); Forces.InitMatrix();
Moments->InitMatrix(); Moments.InitMatrix();
if (!FGModel::Run()) { if (!FGModel::Run()) {
for (unsigned int i=0; i<numEngines; i++) { for (unsigned int i=0; i<numEngines; i++) {
Thrusters[i]->SetdeltaT(dt*rate); Thrusters[i]->SetdeltaT(dt*rate);
PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired()); PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
Thrusters[i]->Calculate(PowerAvailable); Thrusters[i]->Calculate(PowerAvailable);
*Forces += Thrusters[i]->GetBodyForces(); // sum body frame forces Forces += Thrusters[i]->GetBodyForces(); // sum body frame forces
*Moments += Thrusters[i]->GetMoments(); // sum body frame moments Moments += Thrusters[i]->GetMoments(); // sum body frame moments
} }
return false; return false;
} else { } else {
@ -111,15 +109,16 @@ bool FGPropulsion::Run(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropulsion::GetSteadyState(void) { bool FGPropulsion::GetSteadyState(void)
{
double PowerAvailable; double PowerAvailable;
double currentThrust = 0, lastThrust=-1; double currentThrust = 0, lastThrust=-1;
dt = State->Getdt(); dt = State->Getdt();
int steady_count,j=0; int steady_count,j=0;
bool steady=false; bool steady=false;
Forces->InitMatrix(); Forces.InitMatrix();
Moments->InitMatrix(); Moments.InitMatrix();
if (!FGModel::Run()) { if (!FGModel::Run()) {
for (unsigned int i=0; i<numEngines; i++) { for (unsigned int i=0; i<numEngines; i++) {
@ -138,8 +137,8 @@ bool FGPropulsion::GetSteadyState(void) {
} }
j++; j++;
} }
*Forces += Thrusters[i]->GetBodyForces(); // sum body frame forces Forces += Thrusters[i]->GetBodyForces(); // sum body frame forces
*Moments += Thrusters[i]->GetMoments(); // sum body frame moments Moments += Thrusters[i]->GetMoments(); // sum body frame moments
Engines[i]->SetTrimMode(false); Engines[i]->SetTrimMode(false);
} }
@ -152,13 +151,14 @@ bool FGPropulsion::GetSteadyState(void) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropulsion::ICEngineStart(void) { bool FGPropulsion::ICEngineStart(void)
{
double PowerAvailable; double PowerAvailable;
int j; int j;
dt = State->Getdt(); dt = State->Getdt();
Forces->InitMatrix(); Forces.InitMatrix();
Moments->InitMatrix(); Moments.InitMatrix();
for (unsigned int i=0; i<numEngines; i++) { for (unsigned int i=0; i<numEngines; i++) {
Engines[i]->SetTrimMode(true); Engines[i]->SetTrimMode(true);
@ -169,8 +169,8 @@ bool FGPropulsion::ICEngineStart(void) {
Thrusters[i]->Calculate(PowerAvailable); Thrusters[i]->Calculate(PowerAvailable);
j++; j++;
} }
*Forces += Thrusters[i]->GetBodyForces(); // sum body frame forces Forces += Thrusters[i]->GetBodyForces(); // sum body frame forces
*Moments += Thrusters[i]->GetMoments(); // sum body frame moments Moments += Thrusters[i]->GetMoments(); // sum body frame moments
Engines[i]->SetTrimMode(false); Engines[i]->SetTrimMode(false);
} }
return true; return true;
@ -254,6 +254,7 @@ bool FGPropulsion::Load(FGConfigFile* AC_cfg)
} }
Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw); Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
Engines[numEngines]->SetEngineNumber(numEngines);
numEngines++; numEngines++;
} else { } else {
@ -406,7 +407,7 @@ string FGPropulsion::GetPropulsionValues(void)
switch(Engines[i]->GetType()) { switch(Engines[i]->GetType()) {
case FGEngine::etPiston: case FGEngine::etPiston:
PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetPowerAvailable(), 10, buff))); PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
break; break;
case FGEngine::etRocket: case FGEngine::etRocket:
PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff))); PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));

View file

@ -168,10 +168,10 @@ public:
string GetPropulsionStrings(void); string GetPropulsionStrings(void);
string GetPropulsionValues(void); string GetPropulsionValues(void);
inline FGColumnVector3& GetForces(void) {return *Forces; } inline FGColumnVector3& GetForces(void) {return Forces; }
inline double GetForces(int n) { return (*Forces)(n);} inline double GetForces(int n) { return Forces(n);}
inline FGColumnVector3& GetMoments(void) {return *Moments;} inline FGColumnVector3& GetMoments(void) {return Moments;}
inline double GetMoments(int n) {return (*Moments)(n);} inline double GetMoments(int n) {return Moments(n);}
FGColumnVector3& GetTanksCG(void); FGColumnVector3& GetTanksCG(void);
double GetTanksWeight(void); double GetTanksWeight(void);
@ -195,8 +195,8 @@ private:
unsigned int numTanks; unsigned int numTanks;
unsigned int numThrusters; unsigned int numThrusters;
double dt; double dt;
FGColumnVector3 *Forces; FGColumnVector3 Forces;
FGColumnVector3 *Moments; FGColumnVector3 Moments;
FGColumnVector3 vXYZtank; FGColumnVector3 vXYZtank;
void Debug(void); void Debug(void);
}; };

View file

@ -81,7 +81,8 @@ FGRotation::FGRotation(FGFDMExec* fdmex) : FGModel(fdmex),
vMoments(3), vMoments(3),
vEuler(3), vEuler(3),
vEulerRates(3), vEulerRates(3),
vlastPQRdot(3) vlastPQRdot(3),
vAeroPQR(3)
{ {
Name = "FGRotation"; Name = "FGRotation";
cTht=cPhi=cPsi=1.0; cTht=cPhi=cPsi=1.0;
@ -115,6 +116,7 @@ bool FGRotation::Run(void)
vPQRdot(eR) = (N1*Ixx + L2*Ixz) / (Ixx*Izz - Ixz*Ixz); vPQRdot(eR) = (N1*Ixx + L2*Ixz) / (Ixx*Izz - Ixz*Ixz);
vPQR += dt*rate*(vlastPQRdot + vPQRdot)/2.0; vPQR += dt*rate*(vlastPQRdot + vPQRdot)/2.0;
vAeroPQR = vPQR + Atmosphere->GetTurbPQR();
State->IntegrateQuat(vPQR, rate); State->IntegrateQuat(vPQR, rate);
State->CalcMatrices(); State->CalcMatrices();

View file

@ -88,6 +88,8 @@ public:
inline FGColumnVector3& GetPQR(void) {return vPQR;} inline FGColumnVector3& GetPQR(void) {return vPQR;}
inline double GetPQR(int axis) {return vPQR(axis);} inline double GetPQR(int axis) {return vPQR(axis);}
inline FGColumnVector3& GetAeroPQR(void) {return vAeroPQR;}
inline double GetAeroPQR(int axis) {return vAeroPQR(axis);}
inline FGColumnVector3& GetPQRdot(void) {return vPQRdot;} inline FGColumnVector3& GetPQRdot(void) {return vPQRdot;}
inline double GetPQRdot(int idx) {return vPQRdot(idx);} inline double GetPQRdot(int idx) {return vPQRdot(idx);}
inline FGColumnVector3& GetEuler(void) {return vEuler;} inline FGColumnVector3& GetEuler(void) {return vEuler;}
@ -111,6 +113,7 @@ public:
private: private:
FGColumnVector3 vPQR; FGColumnVector3 vPQR;
FGColumnVector3 vAeroPQR;
FGColumnVector3 vPQRdot; FGColumnVector3 vPQRdot;
FGColumnVector3 vMoments; FGColumnVector3 vMoments;
FGColumnVector3 vEuler; FGColumnVector3 vEuler;

View file

@ -76,6 +76,7 @@ CLASS IMPLEMENTATION
FGState::FGState(FGFDMExec* fdex) : mTb2l(3,3), FGState::FGState(FGFDMExec* fdex) : mTb2l(3,3),
mTl2b(3,3), mTl2b(3,3),
mTs2b(3,3), mTs2b(3,3),
mTb2s(3,3),
vQtrn(4), vQtrn(4),
vlastQdot(4), vlastQdot(4),
vQdot(4), vQdot(4),
@ -223,12 +224,12 @@ double FGState::GetParameter(eParam val_idx) {
return Rotation->GetPQR(eP); return Rotation->GetPQR(eP);
case FG_YAWRATE: case FG_YAWRATE:
return Rotation->GetPQR(eR); return Rotation->GetPQR(eR);
case FG_AEROQ:
return Rotation->GetPQR(eQ) + Atmosphere->GetTurbPQR(eQ); // add aero turbulence effects
case FG_AEROP: case FG_AEROP:
return Rotation->GetPQR(eP) + Atmosphere->GetTurbPQR(eP); // add aero turbulence effects return Rotation->GetAeroPQR(eP);
case FG_AEROQ:
return Rotation->GetAeroPQR(eQ);
case FG_AEROR: case FG_AEROR:
return Rotation->GetPQR(eR) + Atmosphere->GetTurbPQR(eR); // add aero turbulence effects return Rotation->GetAeroPQR(eR);
case FG_CL_SQRD: case FG_CL_SQRD:
if (Translation->Getqbar() > 0.00) if (Translation->Getqbar() > 0.00)
scratch = Aerodynamics->GetvLastFs(eLift)/(Aircraft->GetWingArea()*Translation->Getqbar()); scratch = Aerodynamics->GetvLastFs(eLift)/(Aircraft->GetWingArea()*Translation->Getqbar());
@ -297,7 +298,7 @@ double FGState::GetParameter(eParam val_idx) {
if (ActiveEngine < 0) return FCS->GetMixturePos(0); if (ActiveEngine < 0) return FCS->GetMixturePos(0);
else return FCS->GetMixturePos(ActiveEngine); else return FCS->GetMixturePos(ActiveEngine);
case FG_HOVERB: case FG_HOVERB:
return Position->GetHOverB(); return Position->GetHOverBMAC();
case FG_PITCH_TRIM_CMD: case FG_PITCH_TRIM_CMD:
return FCS->GetPitchTrimCmd(); return FCS->GetPitchTrimCmd();
default: default:
@ -432,7 +433,7 @@ bool FGState::Reset(string path, string acname, string fname)
resetfile.GetNextConfigLine(); resetfile.GetNextConfigLine();
token = resetfile.GetValue(); token = resetfile.GetValue();
if (token != "initialize") { if (token != string("initialize")) {
cerr << "The reset file " << resetDef cerr << "The reset file " << resetDef
<< " does not appear to be a reset file" << endl; << " does not appear to be a reset file" << endl;
return false; return false;
@ -440,7 +441,7 @@ bool FGState::Reset(string path, string acname, string fname)
resetfile.GetNextConfigLine(); resetfile.GetNextConfigLine();
resetfile >> token; resetfile >> token;
while (token != "/initialize" && token != "EOF") { while (token != string("/initialize") && token != string("EOF")) {
if (token == "UBODY") resetfile >> U; if (token == "UBODY") resetfile >> U;
if (token == "VBODY") resetfile >> V; if (token == "VBODY") resetfile >> V;
if (token == "WBODY") resetfile >> W; if (token == "WBODY") resetfile >> W;
@ -482,7 +483,7 @@ void FGState::Initialize(double U, double V, double W,
{ {
double alpha, beta; double alpha, beta;
double qbar, Vt; double qbar, Vt;
FGColumnVector3 vAero; FGColumnVector3 vAeroUVW;
Position->SetLatitude(Latitude); Position->SetLatitude(Latitude);
Position->SetLongitude(Longitude); Position->SetLongitude(Longitude);
@ -500,14 +501,14 @@ void FGState::Initialize(double U, double V, double W,
Atmosphere->SetWindNED(wnorth, weast, wdown); Atmosphere->SetWindNED(wnorth, weast, wdown);
vAero = vUVW + mTl2b*Atmosphere->GetWindNED(); vAeroUVW = vUVW + mTl2b*Atmosphere->GetWindNED();
if (vAero(eW) != 0.0) if (vAeroUVW(eW) != 0.0)
alpha = vAero(eU)*vAero(eU) > 0.0 ? atan2(vAero(eW), vAero(eU)) : 0.0; alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
else else
alpha = 0.0; alpha = 0.0;
if (vAero(eV) != 0.0) if (vAeroUVW(eV) != 0.0)
beta = vAero(eU)*vAero(eU)+vAero(eW)*vAero(eW) > 0.0 ? atan2(vAero(eV), (fabs(vAero(eU))/vAero(eU))*sqrt(vAero(eU)*vAero(eU) + vAero(eW)*vAero(eW))) : 0.0; beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), (fabs(vAeroUVW(eU))/vAeroUVW(eU))*sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0;
else else
beta = 0.0; beta = 0.0;
@ -689,19 +690,46 @@ FGMatrix33& FGState::GetTs2b(void)
cb = cos(beta); cb = cos(beta);
sb = sin(beta); sb = sin(beta);
mTs2b(1,1) = -ca*cb; mTs2b(1,1) = ca*cb;
mTs2b(1,2) = -ca*sb; mTs2b(1,2) = -ca*sb;
mTs2b(1,3) = sa; mTs2b(1,3) = -sa;
mTs2b(2,1) = -sb; mTs2b(2,1) = sb;
mTs2b(2,2) = cb; mTs2b(2,2) = cb;
mTs2b(2,3) = 0.0; mTs2b(2,3) = 0.0;
mTs2b(3,1) = -sa*cb; mTs2b(3,1) = sa*cb;
mTs2b(3,2) = -sa*sb; mTs2b(3,2) = -sa*sb;
mTs2b(3,3) = -ca; mTs2b(3,3) = ca;
return mTs2b; return mTs2b;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGMatrix33& FGState::GetTb2s(void)
{
float alpha,beta;
float ca, cb, sa, sb;
alpha = Translation->Getalpha();
beta = Translation->Getbeta();
ca = cos(alpha);
sa = sin(alpha);
cb = cos(beta);
sb = sin(beta);
mTb2s(1,1) = ca*cb;
mTb2s(1,2) = sb;
mTb2s(1,3) = sa*cb;
mTb2s(2,1) = -ca*sb;
mTb2s(2,2) = cb;
mTb2s(2,3) = -sa*sb;
mTb2s(3,1) = -sa;
mTb2s(3,2) = 0.0;
mTb2s(3,3) = ca;
return mTb2s;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -742,7 +770,7 @@ void FGState::ReportState(void) {
Position->Gethdot()*60 ); Position->Gethdot()*60 );
cout << out; cout << out;
snprintf(out,80, " Normal Load Factor: %4.2f g's Pitch Rate: %5.2f deg/s\n", snprintf(out,80, " Normal Load Factor: %4.2f g's Pitch Rate: %5.2f deg/s\n",
Aerodynamics->GetNlf(), Aircraft->GetNlf(),
GetParameter(FG_PITCHRATE)*radtodeg ); GetParameter(FG_PITCHRATE)*radtodeg );
cout << out; cout << out;
snprintf(out,80, " Heading: %3.0f deg true Sideslip: %5.2f deg\n", snprintf(out,80, " Heading: %3.0f deg true Sideslip: %5.2f deg\n",

View file

@ -269,6 +269,11 @@ public:
*/ */
FGMatrix33& GetTs2b(void); FGMatrix33& GetTs2b(void);
/** Calculates and returns the body-to-stability axis transformation matrix.
@return a reference to the stability-to-body transformation matrix.
*/
FGMatrix33& GetTb2s(void);
/** Retrieves the local-to-body transformation matrix. /** Retrieves the local-to-body transformation matrix.
@return a reference to the local-to-body transformation matrix. @return a reference to the local-to-body transformation matrix.
*/ */
@ -311,6 +316,7 @@ private:
FGMatrix33 mTb2l; FGMatrix33 mTb2l;
FGMatrix33 mTl2b; FGMatrix33 mTl2b;
FGMatrix33 mTs2b; FGMatrix33 mTs2b;
FGMatrix33 mTb2s;
FGColumnVector4 vQtrn; FGColumnVector4 vQtrn;
FGColumnVector4 vlastQdot; FGColumnVector4 vlastQdot;
FGColumnVector3 vUVW; FGColumnVector3 vUVW;

View file

@ -82,7 +82,7 @@ FGTranslation::FGTranslation(FGFDMExec* fdmex) : FGModel(fdmex),
vUVWdot(3), vUVWdot(3),
vlastUVWdot(3), vlastUVWdot(3),
mVel(3,3), mVel(3,3),
vAero(3) vAeroUVW(3)
{ {
Name = "FGTranslation"; Name = "FGTranslation";
qbar = 0; qbar = 0;
@ -122,29 +122,29 @@ bool FGTranslation::Run(void)
vUVWdot = mVel*Rotation->GetPQR() + Aircraft->GetBodyAccel(); vUVWdot = mVel*Rotation->GetPQR() + Aircraft->GetBodyAccel();
vUVW += Tc * (vlastUVWdot + vUVWdot); vUVW += Tc * (vlastUVWdot + vUVWdot);
vAero = vUVW + State->GetTl2b()*Atmosphere->GetWindNED(); vAeroUVW = vUVW + State->GetTl2b()*Atmosphere->GetWindNED();
Vt = vAero.Magnitude(); Vt = vAeroUVW.Magnitude();
if ( Vt > 1) { if ( Vt > 1) {
if (vAero(eW) != 0.0) if (vAeroUVW(eW) != 0.0)
alpha = vAero(eU)*vAero(eU) > 0.0 ? atan2(vAero(eW), vAero(eU)) : 0.0; alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
if (vAero(eV) != 0.0) if (vAeroUVW(eV) != 0.0)
beta = vAero(eU)*vAero(eU)+vAero(eW)*vAero(eW) > 0.0 ? atan2(vAero(eV), beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV),
sqrt(vAero(eU)*vAero(eU) + vAero(eW)*vAero(eW))) : 0.0; sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0;
// stolen, quite shamelessly, from LaRCsim // stolen, quite shamelessly, from LaRCsim
double mUW = (vAero(eU)*vAero(eU) + vAero(eW)*vAero(eW)); double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
double signU=1; double signU=1;
if (vAero(eU) != 0.0) if (vAeroUVW(eU) != 0.0)
signU = vAero(eU)/fabs(vAero(eU)); signU = vAeroUVW(eU)/fabs(vAeroUVW(eU));
if ( (mUW == 0.0) || (Vt == 0.0) ) { if ( (mUW == 0.0) || (Vt == 0.0) ) {
adot = 0.0; adot = 0.0;
bdot = 0.0; bdot = 0.0;
} else { } else {
adot = (vAero(eU)*vAero(eW) - vAero(eW)*vUVWdot(eU))/mUW; adot = (vAeroUVW(eU)*vAeroUVW(eW) - vAeroUVW(eW)*vUVWdot(eU))/mUW;
bdot = (signU*mUW*vUVWdot(eV) - vAero(eV)*(vAero(eU)*vUVWdot(eU) bdot = (signU*mUW*vUVWdot(eV) - vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU)
+ vAero(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW)); + vAeroUVW(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW));
} }
} else { } else {
alpha = beta = adot = bdot = 0; alpha = beta = adot = bdot = 0;

View file

@ -91,8 +91,8 @@ public:
inline double GetUVW (int idx) { return vUVW(idx); } inline double GetUVW (int idx) { return vUVW(idx); }
inline FGColumnVector3& GetUVWdot(void) { return vUVWdot; } inline FGColumnVector3& GetUVWdot(void) { return vUVWdot; }
inline double GetUVWdot(int idx) { return vUVWdot(idx); } inline double GetUVWdot(int idx) { return vUVWdot(idx); }
inline FGColumnVector3& GetvAero (void) { return vAero; } inline FGColumnVector3& GetvAeroUVW (void) { return vAeroUVW; }
inline double GetvAero (int idx) { return vAero(idx); } inline double GetvAeroUVW (int idx) { return vAeroUVW(idx); }
inline double Getalpha(void) { return alpha; } inline double Getalpha(void) { return alpha; }
inline double Getbeta (void) { return beta; } inline double Getbeta (void) { return beta; }
@ -121,7 +121,7 @@ private:
FGColumnVector3 vUVWdot; FGColumnVector3 vUVWdot;
FGColumnVector3 vlastUVWdot; FGColumnVector3 vlastUVWdot;
FGMatrix33 mVel; FGMatrix33 mVel;
FGColumnVector3 vAero; FGColumnVector3 vAeroUVW;
double Vt, qbar, Mach; double Vt, qbar, Mach;
double dt; double dt;

View file

@ -53,6 +53,7 @@ INCLUDES
#include "FGAircraft.h" #include "FGAircraft.h"
#include "FGMassBalance.h" #include "FGMassBalance.h"
#include "FGAerodynamics.h" #include "FGAerodynamics.h"
#include "FGColumnVector3.h"
#if _MSC_VER #if _MSC_VER
#pragma warning (disable : 4786 4788) #pragma warning (disable : 4786 4788)
#endif #endif
@ -70,7 +71,7 @@ FGTrim::FGTrim(FGFDMExec *FDMExec,FGInitialCondition *FGIC, TrimMode tt ) {
Tolerance=1E-3; Tolerance=1E-3;
A_Tolerance = Tolerance / 10; A_Tolerance = Tolerance / 10;
Debug=0; Debug=0;DebugLevel=0;
fdmex=FDMExec; fdmex=FDMExec;
fgic=FGIC; fgic=FGIC;
total_its=0; total_its=0;
@ -79,6 +80,8 @@ FGTrim::FGTrim(FGFDMExec *FDMExec,FGInitialCondition *FGIC, TrimMode tt ) {
axis_count=0; axis_count=0;
mode=tt; mode=tt;
xlo=xhi=alo=ahi; xlo=xhi=alo=ahi;
targetNlf=1.0;
debug_axis=tAll;
switch(mode) { switch(mode) {
case tFull: case tFull:
cout << " Full Trim" << endl; cout << " Full Trim" << endl;
@ -102,6 +105,24 @@ FGTrim::FGTrim(FGFDMExec *FDMExec,FGInitialCondition *FGIC, TrimMode tt ) {
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tTheta )); TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tTheta ));
//TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tPhi )); //TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tPhi ));
break; break;
case tPullup:
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tNlf,tAlpha ));
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta ));
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi ));
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
break;
case tTurn:
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tNlf,tAlpha ));
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tBeta ));
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
break;
} }
//cout << "TrimAxes.size(): " << TrimAxes.size() << endl; //cout << "TrimAxes.size(): " << TrimAxes.size() << endl;
sub_iterations=new double[TrimAxes.size()]; sub_iterations=new double[TrimAxes.size()];
@ -281,9 +302,24 @@ bool FGTrim::DoTrim(void) {
successful[current_axis]=0; successful[current_axis]=0;
solution[current_axis]=false; solution[current_axis]=false;
} }
if(mode == tPullup ) {
cout << "Setting pitch rate and nlf... " << endl;
setupPullup();
cout << "pitch rate done ... " << endl;
TrimAxes[0]->SetStateTarget(targetNlf);
cout << "nlf done" << endl;
} else if (mode == tTurn) {
setupTurn();
TrimAxes[0]->SetStateTarget(targetNlf);
}
do { do {
axis_count=0; axis_count=0;
for(current_axis=0;current_axis<TrimAxes.size();current_axis++) { for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
setDebug();
Nsub=0; Nsub=0;
if(!solution[current_axis]) { if(!solution[current_axis]) {
if(checkLimits()) { if(checkLimits()) {
@ -550,5 +586,50 @@ bool FGTrim::checkLimits(void) {
return solutionExists; return solutionExists;
} }
void FGTrim::setupPullup() {
float g,q,cgamma;
FGColumnVector3 vPQR;
g=fdmex->GetInertial()->gravity();
cgamma=cos(fgic->GetFlightPathAngleRadIC());
cout << "setPitchRateInPullup(): " << g << ", " << cgamma << ", "
<< fgic->GetVtrueFpsIC() << endl;
q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC();
cout << targetNlf << ", " << q << endl;
vPQR.InitMatrix();
vPQR(2)=q;
cout << vPQR << endl;
fdmex->GetRotation()->SetPQR(vPQR);
cout << "setPitchRateInPullup() complete" << endl;
}
void FGTrim::setupTurn(void){
FGColumnVector3 vPQR;
float g,q,r,phi, psidot;
phi = fgic->GetRollAngleRadIC();
if( fabs(phi) > 0.01 && fabs(phi) < 1.56 ) {
targetNlf = 1 / cos(phi);
g = fdmex->GetInertial()->gravity();
psidot = g*tan(phi) / fgic->GetVtrueFpsIC();
q = psidot*sin(phi);
r = psidot*cos(phi);
vPQR(1)=0;vPQR(2)=q;vPQR(3)=r;
fdmex->GetRotation()->SetPQR(vPQR);
cout << targetNlf << ", " << vPQR*57.29577 << endl;
}
}
void FGTrim::setDebug(void) {
if(debug_axis == tAll ||
TrimAxes[current_axis]->GetStateType() == debug_axis ) {
Debug=DebugLevel;
return;
} else {
Debug=0;
return;
}
}
//YOU WERE WARNED, BUT YOU DID IT ANYWAY. //YOU WERE WARNED, BUT YOU DID IT ANYWAY.

View file

@ -70,7 +70,9 @@ DEFINITIONS
#define ID_TRIM "$Id$" #define ID_TRIM "$Id$"
typedef enum { tLongitudinal, tFull, tGround, tCustom, tNone } TrimMode; typedef enum { tLongitudinal, tFull, tGround, tPullup,
tCustom, tNone, tTurn
} TrimMode;
#ifdef _MSC_VER #ifdef _MSC_VER
#define snprintf _snprintf #define snprintf _snprintf
@ -148,7 +150,7 @@ private:
int current_axis; int current_axis;
int N, Nsub; int N, Nsub;
TrimMode mode; TrimMode mode;
int Debug; int DebugLevel, Debug;
double Tolerance, A_Tolerance; double Tolerance, A_Tolerance;
double wdot,udot,qdot; double wdot,udot,qdot;
double dth; double dth;
@ -164,6 +166,8 @@ private:
int axis_count; int axis_count;
int solutionDomain; int solutionDomain;
double xlo,xhi,alo,ahi; double xlo,xhi,alo,ahi;
double targetNlf;
int debug_axis;
FGFDMExec* fdmex; FGFDMExec* fdmex;
FGInitialCondition* fgic; FGInitialCondition* fgic;
@ -181,6 +185,11 @@ private:
bool checkLimits(void); bool checkLimits(void);
void setupPullup(void);
void setupTurn(void);
void setDebug(void);
public: public:
/** Initializes the trimming class /** Initializes the trimming class
@param FDMExec pointer to a JSBSim executive object. @param FDMExec pointer to a JSBSim executive object.
@ -270,10 +279,21 @@ public:
A_Tolerance = tt / 10; A_Tolerance = tt / 10;
} }
//Debug level 1 shows results of each top-level iteration /**
//Debug level 2 shows level 1 & results of each per-axis iteration Debug level 1 shows results of each top-level iteration
inline void SetDebug(int level) { Debug = level; } Debug level 2 shows level 1 & results of each per-axis iteration
inline void ClearDebug(void) { Debug = 0; } */
inline void SetDebug(int level) { DebugLevel = level; }
inline void ClearDebug(void) { DebugLevel = 0; }
/**
Output debug data for one of the axes
The State enum is defined in FGTrimAxis.h
*/
inline void DebugState(State state) { debug_axis=state; }
inline void SetTargetNlf(float nlf) { targetNlf=nlf; }
inline double GetTargetNlf(void) { return targetNlf; }
}; };

View file

@ -62,6 +62,7 @@ FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st,
state_convert=1.0; state_convert=1.0;
control_convert=1.0; control_convert=1.0;
state_value=0; state_value=0;
state_target=0;
switch(state) { switch(state) {
case tUdot: tolerance = DEFAULT_TOLERANCE; break; case tUdot: tolerance = DEFAULT_TOLERANCE; break;
case tVdot: tolerance = DEFAULT_TOLERANCE; break; case tVdot: tolerance = DEFAULT_TOLERANCE; break;
@ -70,6 +71,7 @@ FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st,
case tPdot: tolerance = DEFAULT_TOLERANCE / 10; break; case tPdot: tolerance = DEFAULT_TOLERANCE / 10; break;
case tRdot: tolerance = DEFAULT_TOLERANCE / 10; break; case tRdot: tolerance = DEFAULT_TOLERANCE / 10; break;
case tHmgt: tolerance = 0.01; break; case tHmgt: tolerance = 0.01; break;
case tNlf: state_target=1.0; tolerance = 1E-5; break;
} }
solver_eps=tolerance; solver_eps=tolerance;
@ -151,13 +153,14 @@ FGTrimAxis::~FGTrimAxis()
void FGTrimAxis::getState(void) { void FGTrimAxis::getState(void) {
switch(state) { switch(state) {
case tUdot: state_value=fdmex->GetAircraft()->GetBodyAccel()(1); break; case tUdot: state_value=fdmex->GetTranslation()->GetUVWdot()(1)-state_target; break;
case tVdot: state_value=fdmex->GetAircraft()->GetBodyAccel()(2); break; case tVdot: state_value=fdmex->GetTranslation()->GetUVWdot()(2)-state_target; break;
case tWdot: state_value=fdmex->GetAircraft()->GetBodyAccel()(3); break; case tWdot: state_value=fdmex->GetTranslation()->GetUVWdot()(3)-state_target; break;
case tQdot: state_value=fdmex->GetRotation()->GetPQRdot(2);break; case tQdot: state_value=fdmex->GetRotation()->GetPQRdot(2)-state_target;break;
case tPdot: state_value=fdmex->GetRotation()->GetPQRdot(1); break; case tPdot: state_value=fdmex->GetRotation()->GetPQRdot(1)-state_target; break;
case tRdot: state_value=fdmex->GetRotation()->GetPQRdot(3); break; case tRdot: state_value=fdmex->GetRotation()->GetPQRdot(3)-state_target; break;
case tHmgt: state_value=computeHmgt(); break; case tHmgt: state_value=computeHmgt()-state_target; break;
case tNlf: state_value=fdmex->GetAircraft()->GetNlf()-state_target; break;
} }
} }
@ -412,7 +415,7 @@ void FGTrimAxis::AxisReport(void) {
char out[80]; char out[80];
sprintf(out," %20s: %6.2f %5s: %9.2e Tolerance: %3.0e\n", sprintf(out," %20s: %6.2f %5s: %9.2e Tolerance: %3.0e\n",
GetControlName().c_str(), GetControl()*control_convert, GetControlName().c_str(), GetControl()*control_convert,
GetStateName().c_str(), GetState(), GetTolerance()); GetStateName().c_str(), GetState()+state_target, GetTolerance());
cout << out; cout << out;
} }

View file

@ -56,7 +56,9 @@ INCLUDES
#define DEFAULT_TOLERANCE 0.001 #define DEFAULT_TOLERANCE 0.001
const string StateNames[7]= { "udot","vdot","wdot","qdot","pdot","rdot","hmgt" }; const string StateNames[10]= { "all","udot","vdot","wdot","qdot","pdot","rdot",
"hmgt","nlf"
};
const string ControlNames[14]= { "Throttle","Sideslip","Angle of Attack", const string ControlNames[14]= { "Throttle","Sideslip","Angle of Attack",
"Elevator","Ailerons","Rudder", "Elevator","Ailerons","Rudder",
"Altitude AGL", "Pitch Angle", "Altitude AGL", "Pitch Angle",
@ -69,7 +71,7 @@ const string ControlNames[14]= { "Throttle","Sideslip","Angle of Attack",
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
enum State { tUdot,tVdot,tWdot,tQdot,tPdot,tRdot,tHmgt }; enum State { tAll,tUdot,tVdot,tWdot,tQdot,tPdot,tRdot,tHmgt,tNlf };
enum Control { tThrottle, tBeta, tAlpha, tElevator, tAileron, tRudder, tAltAGL, enum Control { tThrottle, tBeta, tAlpha, tElevator, tAileron, tRudder, tAltAGL,
tTheta, tPhi, tGamma, tPitchTrim, tRollTrim, tYawTrim, tHeading }; tTheta, tPhi, tGamma, tPitchTrim, tRollTrim, tYawTrim, tHeading };
@ -120,6 +122,9 @@ public:
void SetThetaOnGround(double ff); void SetThetaOnGround(double ff);
void SetPhiOnGround(double ff); void SetPhiOnGround(double ff);
inline void SetStateTarget(float target) { state_target=target; }
inline float GetStateTarget(void) { return state_target; }
bool initTheta(void); bool initTheta(void);
void AxisReport(void); void AxisReport(void);
@ -133,8 +138,10 @@ private:
State state; State state;
Control control; Control control;
double state_value; float state_target;
double control_value;
float state_value;
float control_value;
double control_min; double control_min;
double control_max; double control_max;

View file

@ -152,7 +152,7 @@ int main(int argc, char** argv)
} }
} }
struct FGJSBBase::Message* msg; FGJSBBase::Message* msg;
while (FDMExec->Run()) { while (FDMExec->Run()) {
while (FDMExec->ReadMessage()) { while (FDMExec->ReadMessage()) {
msg = FDMExec->ProcessMessage(); msg = FDMExec->ProcessMessage();

76
src/FDM/JSBSim/README Normal file
View file

@ -0,0 +1,76 @@
Contents
--------
1) Introduction
2) Building with autoconf/automake
3) Contact
1) Introduction
---------------
JSBSim is a multi-platform, general purpose object-oriented Flight
Dynamics Model (FDM) written in C++. Jon Berndt and Tony Peden began
about mid-1998 writing JSBSim. As of this writing it is the default
FDM for FlightGear. JSBSim can also be run in a standalone batch mode
for testing and study. More information on JSBSim can be found at the
JSBSim home page here:
http://jsbsim.sourceforge.net
The standalone version of JSBSim can be easily built from the command
line of a unix or unix-like (CygWin/Linux/Unix/IRIX, etc.) system like
this:
make -fMakefile.solo
If you are on an IRIX machine you can use the Makefile.irix makefile.
Directions are also provided below for using traditional auto* utilities
also provided with JSBSim.
2) Building with autoconf/automake
----------------------------------
Unpack the distribution tarball (if needed - CVS users will have
downloaded the code directly) using your preferred method, and change
to the working directory. For example :
$ tar xvfz JSBSim-0.1.2.tar.gz
$ cd JSBSim-0.1.2
NOTE for CVS users: If you are using JSBSim from a CVS checkout, or
snapshot, you will need to create the initial configure script. The
commands to do this have been included in the 'autogen.sh' script, so
just :
$ ./autogen.sh
If you wish to customise your version of JSBSim, use the following to
determine any build-time options you may be interested in.
$ ./configure --help
Then :
$ ./configure
This will check your system platform, compiler and other local
configuration variables needed to build JSBSim, and generates the
necessary Makefiles. Next :
$ make
Will compile the various classes, and link the library. Finally :
$ make install
Unless specified otherwise (with --prefix configure option), this will
install 'JSBSim.a' into '/usr/local/lib'.
3) Contact
----------
For more information on JSBSim contact Jon Berndt at jsbsim@hal-pc.org.