}
// Process the output element[s]. This element is OPTIONAL, and there may be more than one.
+ unsigned int idx=0;
+ typedef int (FGOutput::*iOPMF)(void) const;
element = document->FindElement("output");
while (element) {
+ if (debug_lvl > 0) cout << endl << " Output data set: " << idx << " ";
FGOutput* Output = new FGOutput(this);
Output->InitModel();
Schedule(Output, 1);
result = Output->Load(element);
- Outputs.push_back(Output);
if (!result) {
cerr << endl << "Aircraft output element has problems in file " << aircraftCfgFileName << endl;
return result;
+ } else {
+ Outputs.push_back(Output);
+ string outputProp = CreateIndexedPropertyName("simulation/output",idx);
+ instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate);
+ idx++;
}
element = document->FindNextElement("output");
}
result = Output->Load(0);
Outputs.push_back(Output);
+ typedef int (FGOutput::*iOPMF)(void) const;
+ string outputProp = CreateIndexedPropertyName("simulation/output",Outputs.size()-1);
+ instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate);
+
return result;
}
#define BASE
#include "FGJSBBase.h"
+#include <iostream>
namespace JSBSim {
short FGJSBBase::debug_lvl = 1;
+using std::cerr;
+using std::cout;
+using std::endl;
+
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGJSBBase::PutMessage(const Message& msg)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGJSBBase::Message* FGJSBBase::ProcessMessage(void)
+void FGJSBBase::ProcessMessage(void)
+{
+ if (Messages.empty()) return;
+ localMsg = Messages.front();
+
+ while (Messages.size() > 0) {
+ switch (localMsg.type) {
+ case JSBSim::FGJSBBase::Message::eText:
+ cout << localMsg.messageId << ": " << localMsg.text << endl;
+ break;
+ case JSBSim::FGJSBBase::Message::eBool:
+ cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.bVal << endl;
+ break;
+ case JSBSim::FGJSBBase::Message::eInteger:
+ cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.iVal << endl;
+ break;
+ case JSBSim::FGJSBBase::Message::eDouble:
+ cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.dVal << endl;
+ break;
+ default:
+ cerr << "Unrecognized message type." << endl;
+ break;
+ }
+ Messages.pop();
+ if (Messages.size() > 0) localMsg = Messages.front();
+ else break;
+ }
+
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGJSBBase::Message* FGJSBBase::ProcessNextMessage(void)
{
if (Messages.empty()) return NULL;
localMsg = Messages.front();
+
Messages.pop();
return &localMsg;
}
@return 1 if some messages */
int SomeMessages(void);
/** Reads the message on the queue and removes it from the queue.
- @return pointer to a Message structure (or NULL if no mesage) */
- Message* ProcessMessage(void);
+ This function also prints out the message.*/
+ void ProcessMessage(void);
+ /** Reads the next message on the queue and removes it from the queue.
+ This function also prints out the message.
+ @return a pointer to the message, or NULL if there are no messages.*/
+ Message* ProcessNextMessage(void);
//@}
/** Returns the version number of JSBSim.
}
FGJSBBase::Message* msg;
- while (fdmex->SomeMessages()) {
- msg = fdmex->ProcessMessage();
+ while (msg = fdmex->ProcessNextMessage()) {
+// msg = fdmex->ProcessNextMessage();
switch (msg->type) {
case FGJSBBase::Message::eText:
if (msg->text == "Crash Detected: Simulation FREEZE.")
SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG"));
if (document->FindElement("elevation"))
SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT"));
+
if (document->FindElement("altitude")) // This is feet above ground level
SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT"));
+ else if (document->FindElement("altitudeAGL")) // This is feet above ground level
+ SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitudeAGL", "FT"));
+ else if (document->FindElement("altitudeMSL")) // This is feet above sea level
+ SetAltitudeASLFtIC(document->FindElementValueAsNumberConvertTo("altitudeMSL", "FT"));
+
if (document->FindElement("ubody"))
SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC"));
if (document->FindElement("vbody"))
- beta (angle, degrees)
- gamma (angle, degrees)
- roc (vertical velocity, ft/sec)
+ - elevation (local terrain elevation, ft)
- altitude (altitude AGL, ft)
+ - altitudeAGL (altitude AGL, ft)
+ - altitudeMSL (altitude MSL, ft)
- winddir (wind from-angle, degrees)
- vwind (magnitude wind speed, ft/sec)
- hwind (headwind speed, knots)
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
#include <string>
#include <iostream>
#include <simgear/props/props.hxx>
-#include <simgear/math/SGMath.hxx>
#include "FGJSBBase.h"
{
string name, file, fname="", interface_property_string, parent_name;
vector <FGFCSComponent*> *Components;
- Element *component_element, *sensor_element;
+ Element *component_element;
Element *channel_element;
Components=0;
Exec->GetPropertyManager()->Tie( property_name.c_str(), &compressLength );
property_name = base_property_name + "/side_friction_coeff";
Exec->GetPropertyManager()->Tie( property_name.c_str(), &FCoeff );
+
+ property_name = base_property_name + "/static_friction_coeff";
+ Exec->GetPropertyManager()->Tie( property_name.c_str(), &staticFCoeff );
+
}
if( isRetractable ) {
Weight = EmptyWeight = Mass = 0.0;
vbaseXYZcg.InitMatrix(0.0);
+ vXYZcg.InitMatrix(0.0);
+ vLastXYZcg.InitMatrix(0.0);
+ vDeltaXYZcg.InitMatrix(0.0);
baseJ.InitMatrix();
mJ.InitMatrix();
mJinv.InitMatrix();
{
if (!FGModel::InitModel()) return false;
+ vLastXYZcg.InitMatrix(0.0);
+ vDeltaXYZcg.InitMatrix(0.0);
+
return true;
}
+ GetPointMassMoment()
+ BuoyantForces->GetGasMassMoment()) / Weight;
+ // Track frame-by-frame delta CG, and move the EOM-tracked location
+ // by this amount.
+ if (vLastXYZcg.Magnitude() == 0.0) vLastXYZcg = vXYZcg;
+ vDeltaXYZcg = vXYZcg - vLastXYZcg;
+ vDeltaXYZcgBody = StructuralToBody(vLastXYZcg) - StructuralToBody(vXYZcg);
+ vLastXYZcg = vXYZcg;
+ Propagate->NudgeBodyLocation(vDeltaXYZcgBody);
+
// Calculate new total moments of inertia
// At first it is the base configuration inertia matrix ...
bool InitModel(void);
bool Run(void);
- inline double GetMass(void) const {return Mass;}
- inline double GetWeight(void) const {return Weight;}
- inline FGColumnVector3& GetXYZcg(void) {return vXYZcg;}
- inline double GetXYZcg(int axis) const {return vXYZcg(axis);}
+ double GetMass(void) const {return Mass;}
+ double GetWeight(void) const {return Weight;}
+ FGColumnVector3& GetXYZcg(void) {return vXYZcg;}
+ double GetXYZcg(int axis) const {return vXYZcg(axis);}
+ FGColumnVector3& GetDeltaXYZcg(void) {return vDeltaXYZcg;}
+ double GetDeltaXYZcg(int axis) const {return vDeltaXYZcg(axis);}
/** Computes the inertia contribution of a pointmass.
Computes and returns the inertia matrix of a pointmass of mass
FGMatrix33 pmJ;
FGMatrix33 baseJ;
FGColumnVector3 vXYZcg;
+ FGColumnVector3 vLastXYZcg;
+ FGColumnVector3 vDeltaXYZcg;
+ FGColumnVector3 vDeltaXYZcgBody;
FGColumnVector3 vXYZtank;
FGColumnVector3 vbaseXYZcg;
FGColumnVector3 vPMxyz;
outstream << Propulsion->GetPropulsionValues(delimeter);
}
+ outstream.precision(18);
for (unsigned int i=0;i<OutputProperties.size();i++) {
outstream << delimeter << OutputProperties[i]->getDoubleValue();
}
+ outstream.precision(10);
outstream << endl;
outstream.flush();
property_element = document->FindNextElement("property");
}
- OutRate = OutRate>1000?1000:(OutRate<0?0:OutRate);
- rate = (int)(0.5 + 1.0/(State->Getdt()*OutRate));
+ SetRate(OutRate);
Debug(2);
return true;
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGOutput::SetRate(int rtHz)
+{
+ rtHz = rtHz>1000?1000:(rtHz<0?0:rtHz);
+ if (rtHz > 0) {
+ rate = (int)(0.5 + 1.0/(State->Getdt()*rtHz));
+ Enable();
+ } else {
+ rate = 1;
+ Disable();
+ }
+}
+
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
void SetType(string);
void SetStartNewFile(bool tt) {StartNewFile = tt;}
void SetSubsystems(int tt) {SubSystems = tt;}
- inline void Enable(void) { enabled = true; }
- inline void Disable(void) { enabled = false; }
- inline bool Toggle(void) {enabled = !enabled; return enabled;}
+ void Enable(void) { enabled = true; }
+ void Disable(void) { enabled = false; }
+ bool Toggle(void) {enabled = !enabled; return enabled;}
bool Load(Element* el);
void SetOutputFileName(string fname) {Filename = fname;}
void SetDirectivesFile(string fname) {DirectivesFile = fname;}
+ void SetRate(int rt);
string GetOutputFileName(void) const {return Filename;}
/// Subsystem types for specifying which will be output in the FDM data logging
void SetInitialState(const FGInitialCondition *);
void RecomputeLocalTerrainRadius(void);
+ void NudgeBodyLocation(FGColumnVector3 deltaLoc) {
+ vDeltaXYZEC = GetTb2ec()*deltaLoc;
+ VState.vLocation -= vDeltaXYZEC;
+ }
+
void CalculatePQRdot(void);
void CalculateQuatdot(void);
void CalculateLocationdot(void);
FGColumnVector3 vUVWdot, last_vUVWdot, last2_vUVWdot;
FGColumnVector3 vLocationDot, last_vLocationDot, last2_vLocationDot;
FGColumnVector3 vLocation;
+ FGColumnVector3 vDeltaXYZEC;
FGColumnVector3 vPQRi; // Inertial frame angular velocity
FGColumnVector3 vOmega; // The Earth angular velocity vector
FGColumnVector3 vOmegaLocal; // The local frame angular velocity vector
vH(eY) = 0.0;
vH(eZ) = 0.0;
- vH = Transform()*vH; // Transform rotational momentum to rotated frame (if any)
-
if (omega > 0.0) ExcessTorque = GearRatio * PowerAvailable / omega;
else ExcessTorque = GearRatio * PowerAvailable / 1.0;
if (RPM < 1.0) RPM = 0; // Engine friction stops rotation arbitrarily at 1 RPM.
- // Transform Torque and momentum prior to this equation, as PQR is used in this
+ // Transform Torque and momentum first, as PQR is used in this
// equation and cannot be transformed itself.
- vMn = fdmex->GetPropagate()->GetPQR()*vH + Transform()*vTorque;
+ vMn = fdmex->GetPropagate()->GetPQR()*(Transform()*vH) + Transform()*vTorque;
return Thrust; // return thrust in pounds
}