Sync. with JSBSim CVS
This commit is contained in:
parent
0c5e9f46e7
commit
3cb45f4989
31 changed files with 352 additions and 317 deletions
src/FDM/JSBSim
FGFDMExec.cppJSBSim.cxx
initialization
input_output
math
models
|
@ -572,6 +572,9 @@ void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
|
||||||
sprintf(int_buf, "[%d]", node_idx);
|
sprintf(int_buf, "[%d]", node_idx);
|
||||||
if (node_idx != 0) pcsNew->base_string += string(int_buf);
|
if (node_idx != 0) pcsNew->base_string += string(int_buf);
|
||||||
if (pcs->node->getChild(i)->nChildren() == 0) {
|
if (pcs->node->getChild(i)->nChildren() == 0) {
|
||||||
|
if (pcsNew->base_string.substr(0,11) == string("/fdm/jsbsim")) {
|
||||||
|
pcsNew->base_string = pcsNew->base_string.erase(0,12);
|
||||||
|
}
|
||||||
PropertyCatalog.push_back(pcsNew->base_string);
|
PropertyCatalog.push_back(pcsNew->base_string);
|
||||||
} else {
|
} else {
|
||||||
pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i);
|
pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i);
|
||||||
|
|
|
@ -282,6 +282,10 @@ FGJSBsim::FGJSBsim( double dt )
|
||||||
fgGetDouble("/fdm/jsbsim/systems/hook/tailhook-offset-y-in", 0),
|
fgGetDouble("/fdm/jsbsim/systems/hook/tailhook-offset-y-in", 0),
|
||||||
fgGetDouble("/fdm/jsbsim/systems/hook/tailhook-offset-z-in", -16));
|
fgGetDouble("/fdm/jsbsim/systems/hook/tailhook-offset-z-in", -16));
|
||||||
|
|
||||||
|
// Untie the write-state-file property to avoid creating an initfile.xml
|
||||||
|
// file on each reset.
|
||||||
|
fgGetNode("/fdm/jsbsim/simulation/write-state-file")->untie();
|
||||||
|
|
||||||
crashed = false;
|
crashed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,13 @@ void FGInitialCondition::InitializeIC(void)
|
||||||
|
|
||||||
void FGInitialCondition::WriteStateFile(int num)
|
void FGInitialCondition::WriteStateFile(int num)
|
||||||
{
|
{
|
||||||
string filename = fdmex->GetFullAircraftPath() + "/" + "initfile.xml";
|
string filename = fdmex->GetFullAircraftPath();
|
||||||
|
|
||||||
|
if (filename.empty())
|
||||||
|
filename = "initfile.xml";
|
||||||
|
else
|
||||||
|
filename.append("/initfile.xml");
|
||||||
|
|
||||||
ofstream outfile(filename.c_str());
|
ofstream outfile(filename.c_str());
|
||||||
FGPropagate* Propagate = fdmex->GetPropagate();
|
FGPropagate* Propagate = fdmex->GetPropagate();
|
||||||
|
|
||||||
|
@ -173,11 +179,10 @@ void FGInitialCondition::WriteStateFile(int num)
|
||||||
outfile << " <latitude unit=\"DEG\"> " << Propagate->GetLatitudeDeg() << " </latitude>" << endl;
|
outfile << " <latitude unit=\"DEG\"> " << Propagate->GetLatitudeDeg() << " </latitude>" << endl;
|
||||||
outfile << " <altitude unit=\"FT\"> " << Propagate->Geth() << " </altitude>" << endl;
|
outfile << " <altitude unit=\"FT\"> " << Propagate->Geth() << " </altitude>" << endl;
|
||||||
outfile << "</initialize>" << endl;
|
outfile << "</initialize>" << endl;
|
||||||
|
outfile.close();
|
||||||
} else {
|
} else {
|
||||||
cerr << "Could not open and/or write the state to the initial conditions file." << endl;
|
cerr << "Could not open and/or write the state to the initial conditions file: " << filename << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
outfile.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
|
|
|
@ -46,7 +46,6 @@ INCLUDES
|
||||||
#include <initialization/FGTrim.h>
|
#include <initialization/FGTrim.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
namespace JSBSim {
|
namespace JSBSim {
|
||||||
|
|
||||||
|
@ -204,12 +203,17 @@ bool FGScript::LoadScript( string script )
|
||||||
// Retrieve the event name if given
|
// Retrieve the event name if given
|
||||||
newEvent->Name = event_element->GetAttributeValue("name");
|
newEvent->Name = event_element->GetAttributeValue("name");
|
||||||
|
|
||||||
// Is this event persistent? That is, does it execute repeatedly as long as the
|
// Is this event persistent? That is, does it execute every time the
|
||||||
// condition is true, or does it execute as a one-shot event, only?
|
// condition triggers to true, or does it execute as a one-shot event, only?
|
||||||
if (event_element->GetAttributeValue("persistent") == string("true")) {
|
if (event_element->GetAttributeValue("persistent") == string("true")) {
|
||||||
newEvent->Persistent = true;
|
newEvent->Persistent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Does this event execute continuously when triggered to true?
|
||||||
|
if (event_element->GetAttributeValue("continuous") == string("true")) {
|
||||||
|
newEvent->Continuous = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Process the conditions
|
// Process the conditions
|
||||||
condition_element = event_element->FindElement("condition");
|
condition_element = event_element->FindElement("condition");
|
||||||
if (condition_element != 0) {
|
if (condition_element != 0) {
|
||||||
|
@ -304,7 +308,6 @@ bool FGScript::LoadScript( string script )
|
||||||
|
|
||||||
bool FGScript::RunScript(void)
|
bool FGScript::RunScript(void)
|
||||||
{
|
{
|
||||||
vector <struct event>::iterator iEvent = Events.begin();
|
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
unsigned event_ctr = 0;
|
unsigned event_ctr = 0;
|
||||||
|
|
||||||
|
@ -314,90 +317,98 @@ bool FGScript::RunScript(void)
|
||||||
if (currentTime > EndTime) return false; //Script done!
|
if (currentTime > EndTime) return false; //Script done!
|
||||||
|
|
||||||
// Iterate over all events.
|
// Iterate over all events.
|
||||||
while (iEvent < Events.end()) {
|
for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) {
|
||||||
iEvent->PrevTriggered = iEvent->Triggered;
|
|
||||||
// Determine whether the set of conditional tests for this condition equate
|
// Determine whether the set of conditional tests for this condition equate
|
||||||
// to true and should cause the event to execute.
|
// to true and should cause the event to execute. If the conditions evaluate
|
||||||
if (iEvent->Condition->Evaluate()) {
|
// to true, then the event is triggered. If the event is not persistent,
|
||||||
if (!iEvent->Triggered) {
|
// then this trigger will remain set true. If the event is persistent,
|
||||||
|
// the trigger will reset to false when the condition evaluates to false.
|
||||||
|
if (Events[ev_ctr].Condition->Evaluate()) {
|
||||||
|
if (!Events[ev_ctr].Triggered) {
|
||||||
|
|
||||||
// The conditions are true, do the setting of the desired Event parameters
|
// The conditions are true, do the setting of the desired Event parameters
|
||||||
for (i=0; i<iEvent->SetValue.size(); i++) {
|
for (i=0; i<Events[ev_ctr].SetValue.size(); i++) {
|
||||||
iEvent->OriginalValue[i] = iEvent->SetParam[i]->getDoubleValue();
|
Events[ev_ctr].OriginalValue[i] = Events[ev_ctr].SetParam[i]->getDoubleValue();
|
||||||
if (iEvent->Functions[i] != 0) { // Parameter should be set to a function value
|
if (Events[ev_ctr].Functions[i] != 0) { // Parameter should be set to a function value
|
||||||
iEvent->SetValue[i] = iEvent->Functions[i]->GetValue();
|
Events[ev_ctr].SetValue[i] = Events[ev_ctr].Functions[i]->GetValue();
|
||||||
}
|
}
|
||||||
switch (iEvent->Type[i]) {
|
switch (Events[ev_ctr].Type[i]) {
|
||||||
case FG_VALUE:
|
case FG_VALUE:
|
||||||
case FG_BOOL:
|
case FG_BOOL:
|
||||||
iEvent->newValue[i] = iEvent->SetValue[i];
|
Events[ev_ctr].newValue[i] = Events[ev_ctr].SetValue[i];
|
||||||
break;
|
break;
|
||||||
case FG_DELTA:
|
case FG_DELTA:
|
||||||
iEvent->newValue[i] = iEvent->OriginalValue[i] + iEvent->SetValue[i];
|
Events[ev_ctr].newValue[i] = Events[ev_ctr].OriginalValue[i] + Events[ev_ctr].SetValue[i];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cerr << "Invalid Type specified" << endl;
|
cerr << "Invalid Type specified" << endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
iEvent->StartTime = currentTime + iEvent->Delay;
|
Events[ev_ctr].StartTime = currentTime + Events[ev_ctr].Delay;
|
||||||
iEvent->ValueSpan[i] = iEvent->newValue[i] - iEvent->OriginalValue[i];
|
Events[ev_ctr].ValueSpan[i] = Events[ev_ctr].newValue[i] - Events[ev_ctr].OriginalValue[i];
|
||||||
iEvent->Transiting[i] = true;
|
Events[ev_ctr].Transiting[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iEvent->Triggered = true;
|
Events[ev_ctr].Triggered = true;
|
||||||
} else if (iEvent->Persistent) {
|
|
||||||
iEvent->Triggered = false; // Reset the trigger for persistent events
|
} else if (Events[ev_ctr].Persistent) { // If the event is persistent, reset the trigger.
|
||||||
iEvent->Notified = false; // Also reset the notification flag
|
|
||||||
|
Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events
|
||||||
|
Events[ev_ctr].Notified = false; // Also reset the notification flag
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((currentTime >= iEvent->StartTime) && iEvent->Triggered) {
|
if ((currentTime >= Events[ev_ctr].StartTime) && Events[ev_ctr].Triggered) {
|
||||||
|
|
||||||
for (i=0; i<iEvent->SetValue.size(); i++) {
|
for (i=0; i<Events[ev_ctr].SetValue.size(); i++) {
|
||||||
if (iEvent->Transiting[i]) {
|
if (Events[ev_ctr].Transiting[i]) {
|
||||||
iEvent->TimeSpan = currentTime - iEvent->StartTime;
|
Events[ev_ctr].TimeSpan = currentTime - Events[ev_ctr].StartTime;
|
||||||
if (iEvent->Functions[i] == 0) {
|
switch (Events[ev_ctr].Action[i]) {
|
||||||
switch (iEvent->Action[i]) {
|
case FG_RAMP:
|
||||||
case FG_RAMP:
|
if (Events[ev_ctr].TimeSpan <= Events[ev_ctr].TC[i]) {
|
||||||
if (iEvent->TimeSpan <= iEvent->TC[i]) {
|
newSetValue = Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i];
|
||||||
newSetValue = iEvent->TimeSpan/iEvent->TC[i] * iEvent->ValueSpan[i] + iEvent->OriginalValue[i];
|
} else {
|
||||||
} else {
|
newSetValue = Events[ev_ctr].newValue[i];
|
||||||
newSetValue = iEvent->newValue[i];
|
if (Events[ev_ctr].Continuous != true) Events[ev_ctr].Transiting[i] = false;
|
||||||
iEvent->Transiting[i] = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FG_STEP:
|
|
||||||
newSetValue = iEvent->newValue[i];
|
|
||||||
iEvent->Transiting[i] = false;
|
|
||||||
break;
|
|
||||||
case FG_EXP:
|
|
||||||
newSetValue = (1 - exp( -iEvent->TimeSpan/iEvent->TC[i] )) * iEvent->ValueSpan[i] + iEvent->OriginalValue[i];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cerr << "Invalid Action specified" << endl;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else { // Set the new value based on a function
|
break;
|
||||||
newSetValue = iEvent->Functions[i]->GetValue();
|
case FG_STEP:
|
||||||
|
newSetValue = Events[ev_ctr].newValue[i];
|
||||||
|
|
||||||
|
// If this is not a continuous event, reset the transiting flag.
|
||||||
|
// Otherwise, it is known that the event is a continuous event.
|
||||||
|
// Furthermore, if the event is to be determined by a function,
|
||||||
|
// then the function will be continuously calculated.
|
||||||
|
if (Events[ev_ctr].Continuous != true)
|
||||||
|
Events[ev_ctr].Transiting[i] = false;
|
||||||
|
else if (Events[ev_ctr].Functions[i] != 0)
|
||||||
|
newSetValue = Events[ev_ctr].Functions[i]->GetValue();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case FG_EXP:
|
||||||
|
newSetValue = (1 - exp( -Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] )) * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cerr << "Invalid Action specified" << endl;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
iEvent->SetParam[i]->setDoubleValue(newSetValue);
|
Events[ev_ctr].SetParam[i]->setDoubleValue(newSetValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print notification values after setting them
|
// Print notification values after setting them
|
||||||
if (iEvent->Notify && !iEvent->Notified) {
|
if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) {
|
||||||
cout << endl << " Event " << event_ctr << " (" << iEvent->Name << ")"
|
cout << endl << " Event " << event_ctr << " (" << Events[ev_ctr].Name << ")"
|
||||||
<< " executed at time: " << currentTime << endl;
|
<< " executed at time: " << currentTime << endl;
|
||||||
for (j=0; j<iEvent->NotifyProperties.size();j++) {
|
for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) {
|
||||||
cout << " " << iEvent->NotifyProperties[j]->GetName()
|
cout << " " << Events[ev_ctr].NotifyProperties[j]->GetName()
|
||||||
<< " = " << iEvent->NotifyProperties[j]->getDoubleValue() << endl;
|
<< " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl;
|
||||||
}
|
}
|
||||||
cout << endl;
|
cout << endl;
|
||||||
iEvent->Notified = true;
|
Events[ev_ctr].Notified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iEvent++;
|
|
||||||
event_ctr++;
|
event_ctr++;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -70,13 +70,14 @@ CLASS DOCUMENTATION
|
||||||
format. A test condition (or conditions) can be set up in an event in a
|
format. A test condition (or conditions) can be set up in an event in a
|
||||||
script and when the condition evaluates to true, the specified
|
script and when the condition evaluates to true, the specified
|
||||||
action[s] is/are taken. An event can be <em>persistent</em>,
|
action[s] is/are taken. An event can be <em>persistent</em>,
|
||||||
meaning that at all times when the test condition evaluates to true
|
meaning that at every time the test condition first evaluates to true
|
||||||
the specified <em>set</em> actions take place. When the set of
|
(toggling from false to true) then the specified <em>set</em> actions take
|
||||||
tests evaluates to true for a given
|
place. An event can also be defined to execute or evaluate continuously
|
||||||
|
while the condition is true. When the set of tests evaluates to true for a given
|
||||||
condition, an item may be set to another value. This value may
|
condition, an item may be set to another value. This value may
|
||||||
be a value, or a delta value, and the change from the
|
be a value, or a delta value, and the change from the
|
||||||
current value to the new value can be either via a step function,
|
current value to the new value can be either via a step action,
|
||||||
a ramp, or an exponential approach. The speed of a ramp or
|
a ramp, or an exponential approach. The speed of a ramp or exponential
|
||||||
approach is specified via the time constant. Here is an example
|
approach is specified via the time constant. Here is an example
|
||||||
illustrating the format of the script file:
|
illustrating the format of the script file:
|
||||||
|
|
||||||
|
@ -204,8 +205,8 @@ private:
|
||||||
struct event {
|
struct event {
|
||||||
FGCondition *Condition;
|
FGCondition *Condition;
|
||||||
bool Persistent;
|
bool Persistent;
|
||||||
|
bool Continuous;
|
||||||
bool Triggered;
|
bool Triggered;
|
||||||
bool PrevTriggered;
|
|
||||||
bool Notify;
|
bool Notify;
|
||||||
bool Notified;
|
bool Notified;
|
||||||
double Delay;
|
double Delay;
|
||||||
|
@ -226,8 +227,8 @@ private:
|
||||||
|
|
||||||
event() {
|
event() {
|
||||||
Triggered = false;
|
Triggered = false;
|
||||||
PrevTriggered = false;
|
|
||||||
Persistent = false;
|
Persistent = false;
|
||||||
|
Continuous = false;
|
||||||
Delay = 0.0;
|
Delay = 0.0;
|
||||||
Notify = Notified = false;
|
Notify = Notified = false;
|
||||||
Name = "";
|
Name = "";
|
||||||
|
@ -237,7 +238,6 @@ private:
|
||||||
|
|
||||||
void reset(void) {
|
void reset(void) {
|
||||||
Triggered = false;
|
Triggered = false;
|
||||||
PrevTriggered = false;
|
|
||||||
Notified = false;
|
Notified = false;
|
||||||
StartTime = 0.0;
|
StartTime = 0.0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ CLASS IMPLEMENTATION
|
||||||
FGColumnVector3::FGColumnVector3(void)
|
FGColumnVector3::FGColumnVector3(void)
|
||||||
{
|
{
|
||||||
data[0] = data[1] = data[2] = 0.0;
|
data[0] = data[1] = data[2] = 0.0;
|
||||||
Debug(0);
|
// Debug(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
@ -60,7 +60,7 @@ FGColumnVector3::FGColumnVector3(void)
|
||||||
string FGColumnVector3::Dump(string delimeter) const
|
string FGColumnVector3::Dump(string delimeter) const
|
||||||
{
|
{
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
sprintf(buffer, "%10.3e%s%10.3e%s%10.3e", Entry(1), delimeter.c_str(), Entry(2), delimeter.c_str(), Entry(3));
|
sprintf(buffer, "%13.6e%s%13.6e%s%13.6e", Entry(1), delimeter.c_str(), Entry(2), delimeter.c_str(), Entry(3));
|
||||||
return string(buffer);
|
return string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ FGMatrix33::FGMatrix33(void)
|
||||||
data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
|
data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
|
||||||
data[6] = data[7] = data[8] = 0.0;
|
data[6] = data[7] = data[8] = 0.0;
|
||||||
|
|
||||||
Debug(0);
|
// Debug(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
|
@ -140,7 +140,7 @@ bool FGAircraft::Run(void)
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
double FGAircraft::GetNlf(void)
|
double FGAircraft::GetNlf(void) const
|
||||||
{
|
{
|
||||||
return -1*Aerodynamics->GetvFw(3)/MassBalance->GetWeight();
|
return -1*Aerodynamics->GetvFw(3)/MassBalance->GetWeight();
|
||||||
}
|
}
|
||||||
|
@ -216,13 +216,6 @@ void FGAircraft::bind(void)
|
||||||
PropertyManager->Tie("metrics/lv-norm", this, &FGAircraft::Getlbarv);
|
PropertyManager->Tie("metrics/lv-norm", this, &FGAircraft::Getlbarv);
|
||||||
PropertyManager->Tie("metrics/vbarh-norm", this, &FGAircraft::Getvbarh);
|
PropertyManager->Tie("metrics/vbarh-norm", this, &FGAircraft::Getvbarh);
|
||||||
PropertyManager->Tie("metrics/vbarv-norm", this, &FGAircraft::Getvbarv);
|
PropertyManager->Tie("metrics/vbarv-norm", this, &FGAircraft::Getvbarv);
|
||||||
PropertyManager->Tie("forces/hold-down", this, &FGAircraft::GetHoldDown, &FGAircraft::SetHoldDown);
|
|
||||||
PropertyManager->Tie("moments/l-total-lbsft", this, eL, (PMF)&FGAircraft::GetMoments);
|
|
||||||
PropertyManager->Tie("moments/m-total-lbsft", this, eM, (PMF)&FGAircraft::GetMoments);
|
|
||||||
PropertyManager->Tie("moments/n-total-lbsft", this, eN, (PMF)&FGAircraft::GetMoments);
|
|
||||||
PropertyManager->Tie("forces/fbx-total-lbs", this, eX, (PMF)&FGAircraft::GetForces);
|
|
||||||
PropertyManager->Tie("forces/fby-total-lbs", this, eY, (PMF)&FGAircraft::GetForces);
|
|
||||||
PropertyManager->Tie("forces/fbz-total-lbs", this, eZ, (PMF)&FGAircraft::GetForces);
|
|
||||||
PropertyManager->Tie("metrics/aero-rp-x-in", this, eX, (PMF)&FGAircraft::GetXYZrp);
|
PropertyManager->Tie("metrics/aero-rp-x-in", this, eX, (PMF)&FGAircraft::GetXYZrp);
|
||||||
PropertyManager->Tie("metrics/aero-rp-y-in", this, eY, (PMF)&FGAircraft::GetXYZrp);
|
PropertyManager->Tie("metrics/aero-rp-y-in", this, eY, (PMF)&FGAircraft::GetXYZrp);
|
||||||
PropertyManager->Tie("metrics/aero-rp-z-in", this, eZ, (PMF)&FGAircraft::GetXYZrp);
|
PropertyManager->Tie("metrics/aero-rp-z-in", this, eZ, (PMF)&FGAircraft::GetXYZrp);
|
||||||
|
@ -232,6 +225,14 @@ void FGAircraft::bind(void)
|
||||||
PropertyManager->Tie("metrics/visualrefpoint-x-in", this, eX, (PMF)&FGAircraft::GetXYZvrp);
|
PropertyManager->Tie("metrics/visualrefpoint-x-in", this, eX, (PMF)&FGAircraft::GetXYZvrp);
|
||||||
PropertyManager->Tie("metrics/visualrefpoint-y-in", this, eY, (PMF)&FGAircraft::GetXYZvrp);
|
PropertyManager->Tie("metrics/visualrefpoint-y-in", this, eY, (PMF)&FGAircraft::GetXYZvrp);
|
||||||
PropertyManager->Tie("metrics/visualrefpoint-z-in", this, eZ, (PMF)&FGAircraft::GetXYZvrp);
|
PropertyManager->Tie("metrics/visualrefpoint-z-in", this, eZ, (PMF)&FGAircraft::GetXYZvrp);
|
||||||
|
PropertyManager->Tie("forces/fbx-total-lbs", this, eX, (PMF)&FGAircraft::GetForces);
|
||||||
|
PropertyManager->Tie("forces/fby-total-lbs", this, eY, (PMF)&FGAircraft::GetForces);
|
||||||
|
PropertyManager->Tie("forces/fbz-total-lbs", this, eZ, (PMF)&FGAircraft::GetForces);
|
||||||
|
PropertyManager->Tie("forces/load-factor", this, &FGAircraft::GetNlf);
|
||||||
|
PropertyManager->Tie("forces/hold-down", this, &FGAircraft::GetHoldDown, &FGAircraft::SetHoldDown);
|
||||||
|
PropertyManager->Tie("moments/l-total-lbsft", this, eL, (PMF)&FGAircraft::GetMoments);
|
||||||
|
PropertyManager->Tie("moments/m-total-lbsft", this, eM, (PMF)&FGAircraft::GetMoments);
|
||||||
|
PropertyManager->Tie("moments/n-total-lbsft", this, eN, (PMF)&FGAircraft::GetMoments);
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
|
@ -171,7 +171,7 @@ public:
|
||||||
|
|
||||||
void SetWingArea(double S) {WingArea = S;}
|
void SetWingArea(double S) {WingArea = S;}
|
||||||
|
|
||||||
double GetNlf(void);
|
double GetNlf(void) const;
|
||||||
|
|
||||||
inline FGColumnVector3& GetNwcg(void) { return vNwcg; }
|
inline FGColumnVector3& GetNwcg(void) { return vNwcg; }
|
||||||
|
|
||||||
|
|
|
@ -71,13 +71,13 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
|
||||||
h = 0.0;
|
h = 0.0;
|
||||||
psiw = 0.0;
|
psiw = 0.0;
|
||||||
htab[0]=0;
|
htab[0]=0;
|
||||||
htab[1]=36089.239;
|
htab[1]= 36089.0;
|
||||||
htab[2]=65616.798;
|
htab[2]= 65617.0;
|
||||||
htab[3]=104986.878;
|
htab[3]=104987.0;
|
||||||
htab[4]=154199.475;
|
htab[4]=154199.0;
|
||||||
htab[5]=170603.675;
|
htab[5]=167322.0;
|
||||||
htab[6]=200131.234;
|
htab[6]=232940.0;
|
||||||
htab[7]=259186.352; //ft.
|
htab[7]=278385.0; //ft.
|
||||||
|
|
||||||
MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
|
MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
|
||||||
SetTurbType( ttCulp );
|
SetTurbType( ttCulp );
|
||||||
|
@ -86,6 +86,8 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
|
||||||
Rhythmicity = 0.1;
|
Rhythmicity = 0.1;
|
||||||
spike = target_time = strength = 0.0;
|
spike = target_time = strength = 0.0;
|
||||||
wind_from_clockwise = 0.0;
|
wind_from_clockwise = 0.0;
|
||||||
|
SutherlandConstant = 198.72; // deg Rankine
|
||||||
|
Beta = 2.269690E-08; // slug/(sec ft R^0.5)
|
||||||
|
|
||||||
T_dev_sl = T_dev = delta_T = 0.0;
|
T_dev_sl = T_dev = delta_T = 0.0;
|
||||||
StandardTempOnly = false;
|
StandardTempOnly = false;
|
||||||
|
@ -174,52 +176,57 @@ void FGAtmosphere::Calculate(double altitude)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(i) {
|
switch(i) {
|
||||||
case 1: // 36089 ft.
|
case 0: // Sea level
|
||||||
|
slope = -0.00356616; // R/ft.
|
||||||
|
reftemp = 518.67; // in degrees Rankine, 288.15 Kelvin
|
||||||
|
refpress = 2116.22; // psf
|
||||||
|
//refdens = 0.00237767; // slugs/cubic ft.
|
||||||
|
break;
|
||||||
|
case 1: // 36089 ft. or 11 km
|
||||||
slope = 0;
|
slope = 0;
|
||||||
reftemp = 389.97;
|
reftemp = 389.97; // in degrees Rankine, 216.65 Kelvin
|
||||||
refpress = 472.452;
|
refpress = 472.763;
|
||||||
//refdens = 0.000706032;
|
//refdens = 0.000706032;
|
||||||
break;
|
break;
|
||||||
case 2: // 65616 ft.
|
case 2: // 65616 ft. or 20 km
|
||||||
slope = 0.00054864;
|
slope = 0.00054864;
|
||||||
reftemp = 389.97;
|
reftemp = 389.97; // in degrees Rankine, 216.65 Kelvin
|
||||||
refpress = 114.636;
|
refpress = 114.636;
|
||||||
//refdens = 0.000171306;
|
//refdens = 0.000171306;
|
||||||
break;
|
break;
|
||||||
case 3: // 104986 ft.
|
case 3: // 104986 ft. or 32 km
|
||||||
slope = 0.00153619;
|
slope = 0.001536192;
|
||||||
reftemp = 411.57;
|
reftemp = 411.57; // in degrees Rankine, 228.65 Kelvin
|
||||||
refpress = 8.36364;
|
refpress = 18.128;
|
||||||
//refdens = 1.18422e-05;
|
//refdens = 1.18422e-05;
|
||||||
break;
|
break;
|
||||||
case 4: // 154199 ft.
|
case 4: // 154199 ft. 47 km
|
||||||
slope = 0;
|
slope = 0;
|
||||||
reftemp = 487.17;
|
reftemp = 487.17; // in degrees Rankine, 270.65 Kelvin
|
||||||
refpress = 0.334882;
|
refpress = 2.316;
|
||||||
//refdens = 4.00585e-7;
|
//refdens = 4.00585e-7;
|
||||||
break;
|
break;
|
||||||
case 5: // 170603 ft.
|
case 5: // 167322 ft. or 51 km
|
||||||
slope = -0.00109728;
|
slope = -0.001536192;
|
||||||
reftemp = 487.17;
|
reftemp = 487.17; // in degrees Rankine, 270.65 Kelvin
|
||||||
refpress = 0.683084;
|
refpress = 1.398;
|
||||||
//refdens = 8.17102e-7;
|
//refdens = 8.17102e-7;
|
||||||
break;
|
break;
|
||||||
case 6: // 200131 ft.
|
case 6: // 232940 ft. or 71 km
|
||||||
slope = -0.00219456;
|
slope = -0.00109728;
|
||||||
reftemp = 454.17;
|
reftemp = 386.368; // in degrees Rankine, 214.649 Kelvin
|
||||||
refpress = 0.00684986;
|
refpress = 0.0826;
|
||||||
//refdens = 8.77702e-9;
|
//refdens = 8.77702e-9;
|
||||||
break;
|
break;
|
||||||
case 7: // 259186 ft.
|
case 7: // 278385 ft. or 84.8520 km
|
||||||
slope = 0;
|
slope = 0;
|
||||||
reftemp = 325.17;
|
reftemp = 336.5; // in degrees Rankine, 186.94 Kelvin
|
||||||
refpress = 0.000122276;
|
refpress = 0.00831;
|
||||||
//refdens = 2.19541e-10;
|
//refdens = 2.19541e-10;
|
||||||
break;
|
break;
|
||||||
case 0:
|
|
||||||
default: // sea level
|
default: // sea level
|
||||||
slope = -0.00356616; // R/ft.
|
slope = -0.00356616; // R/ft.
|
||||||
reftemp = 518.67; // R
|
reftemp = 518.67; // in degrees Rankine, 288.15 Kelvin
|
||||||
refpress = 2116.22; // psf
|
refpress = 2116.22; // psf
|
||||||
//refdens = 0.00237767; // slugs/cubic ft.
|
//refdens = 0.00237767; // slugs/cubic ft.
|
||||||
break;
|
break;
|
||||||
|
@ -263,7 +270,7 @@ void FGAtmosphere::CalculateDerived(void)
|
||||||
T_dev = (*temperature) - GetTemperature(h);
|
T_dev = (*temperature) - GetTemperature(h);
|
||||||
density_altitude = h + T_dev * 66.7;
|
density_altitude = h + T_dev * 66.7;
|
||||||
|
|
||||||
if (turbType == ttStandard || ttCulp) Turbulence();
|
if (turbType != ttNone) Turbulence();
|
||||||
|
|
||||||
vTotalWindNED = vWindNED + vGustNED + vTurbulenceNED;
|
vTotalWindNED = vWindNED + vGustNED + vTurbulenceNED;
|
||||||
|
|
||||||
|
@ -271,6 +278,9 @@ void FGAtmosphere::CalculateDerived(void)
|
||||||
if (psiw < 0) psiw += 2*M_PI;
|
if (psiw < 0) psiw += 2*M_PI;
|
||||||
|
|
||||||
soundspeed = sqrt(SHRatio*Reng*(*temperature));
|
soundspeed = sqrt(SHRatio*Reng*(*temperature));
|
||||||
|
|
||||||
|
intViscosity = Beta * pow(intTemperature, 1.5) / (SutherlandConstant + intTemperature);
|
||||||
|
intKinematicViscosity = intViscosity / intDensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,10 @@ public:
|
||||||
double GetDensity(double altitude);
|
double GetDensity(double altitude);
|
||||||
/// Returns the speed of sound in ft/sec.
|
/// Returns the speed of sound in ft/sec.
|
||||||
double GetSoundSpeed(void) const {return soundspeed;}
|
double GetSoundSpeed(void) const {return soundspeed;}
|
||||||
|
/// Returns the absolute viscosity.
|
||||||
|
double GetAbsoluteViscosity(void) const {return intViscosity;}
|
||||||
|
/// Returns the kinematic viscosity.
|
||||||
|
double GetKinematicViscosity(void) const {return intKinematicViscosity;}
|
||||||
|
|
||||||
/// Returns the sea level temperature in degrees Rankine.
|
/// Returns the sea level temperature in degrees Rankine.
|
||||||
double GetTemperatureSL(void) const { return SLtemperature; }
|
double GetTemperatureSL(void) const { return SLtemperature; }
|
||||||
|
@ -237,6 +241,7 @@ protected:
|
||||||
bool useExternal;
|
bool useExternal;
|
||||||
double exTemperature,exDensity,exPressure;
|
double exTemperature,exDensity,exPressure;
|
||||||
double intTemperature, intDensity, intPressure;
|
double intTemperature, intDensity, intPressure;
|
||||||
|
double SutherlandConstant, Beta, intViscosity, intKinematicViscosity;
|
||||||
double T_dev_sl, T_dev, delta_T, density_altitude;
|
double T_dev_sl, T_dev, delta_T, density_altitude;
|
||||||
atmType atmosphere;
|
atmType atmosphere;
|
||||||
bool StandardTempOnly;
|
bool StandardTempOnly;
|
||||||
|
|
|
@ -71,6 +71,7 @@ FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex)
|
||||||
qbar = 0;
|
qbar = 0;
|
||||||
qbarUW = 0.0;
|
qbarUW = 0.0;
|
||||||
qbarUV = 0.0;
|
qbarUV = 0.0;
|
||||||
|
Re = 0.0;
|
||||||
Mach = 0.0;
|
Mach = 0.0;
|
||||||
alpha = beta = 0.0;
|
alpha = beta = 0.0;
|
||||||
adot = bdot = 0.0;
|
adot = bdot = 0.0;
|
||||||
|
@ -79,6 +80,7 @@ FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex)
|
||||||
day_of_year = 1;
|
day_of_year = 1;
|
||||||
seconds_in_day = 0.0;
|
seconds_in_day = 0.0;
|
||||||
hoverbmac = hoverbcg = 0.0;
|
hoverbmac = hoverbcg = 0.0;
|
||||||
|
tatc = RankineToCelsius(tat);
|
||||||
|
|
||||||
vPilotAccel.InitMatrix();
|
vPilotAccel.InitMatrix();
|
||||||
vPilotAccelN.InitMatrix();
|
vPilotAccelN.InitMatrix();
|
||||||
|
@ -200,6 +202,8 @@ bool FGAuxiliary::Run()
|
||||||
alpha = beta = adot = bdot = 0;
|
alpha = beta = adot = bdot = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Re = Vt * Aircraft->Getcbar() / Atmosphere->GetKinematicViscosity();
|
||||||
|
|
||||||
qbar = 0.5*Atmosphere->GetDensity()*Vt*Vt;
|
qbar = 0.5*Atmosphere->GetDensity()*Vt*Vt;
|
||||||
qbarUW = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
|
qbarUW = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
|
||||||
qbarUV = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV));
|
qbarUV = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV));
|
||||||
|
@ -349,6 +353,7 @@ void FGAuxiliary::bind(void)
|
||||||
PropertyManager->Tie("aero/alpha-deg", this, inDegrees, (PMF)&FGAuxiliary::Getalpha);
|
PropertyManager->Tie("aero/alpha-deg", this, inDegrees, (PMF)&FGAuxiliary::Getalpha);
|
||||||
PropertyManager->Tie("aero/beta-deg", this, inDegrees, (PMF)&FGAuxiliary::Getbeta);
|
PropertyManager->Tie("aero/beta-deg", this, inDegrees, (PMF)&FGAuxiliary::Getbeta);
|
||||||
PropertyManager->Tie("aero/mag-beta-deg", this, inDegrees, (PMF)&FGAuxiliary::GetMagBeta);
|
PropertyManager->Tie("aero/mag-beta-deg", this, inDegrees, (PMF)&FGAuxiliary::GetMagBeta);
|
||||||
|
PropertyManager->Tie("aero/Re", this, &FGAuxiliary::GetReynoldsNumber);
|
||||||
PropertyManager->Tie("aero/qbar-psf", this, &FGAuxiliary::Getqbar, &FGAuxiliary::Setqbar, true);
|
PropertyManager->Tie("aero/qbar-psf", this, &FGAuxiliary::Getqbar, &FGAuxiliary::Setqbar, true);
|
||||||
PropertyManager->Tie("aero/qbarUW-psf", this, &FGAuxiliary::GetqbarUW, &FGAuxiliary::SetqbarUW, true);
|
PropertyManager->Tie("aero/qbarUW-psf", this, &FGAuxiliary::GetqbarUW, &FGAuxiliary::SetqbarUW, true);
|
||||||
PropertyManager->Tie("aero/qbarUV-psf", this, &FGAuxiliary::GetqbarUV, &FGAuxiliary::SetqbarUV, true);
|
PropertyManager->Tie("aero/qbarUV-psf", this, &FGAuxiliary::GetqbarUV, &FGAuxiliary::SetqbarUV, true);
|
||||||
|
|
|
@ -181,14 +181,15 @@ public:
|
||||||
double GetMagBeta (int unit) const { if (unit == inDegrees) return fabs(beta)*radtodeg;
|
double GetMagBeta (int unit) const { if (unit == inDegrees) return fabs(beta)*radtodeg;
|
||||||
else cerr << "Bad units" << endl; return 0.0;}
|
else cerr << "Bad units" << endl; return 0.0;}
|
||||||
|
|
||||||
double Getqbar (void) const { return qbar; }
|
double Getqbar (void) const { return qbar; }
|
||||||
double GetqbarUW (void) const { return qbarUW; }
|
double GetqbarUW (void) const { return qbarUW; }
|
||||||
double GetqbarUV (void) const { return qbarUV; }
|
double GetqbarUV (void) const { return qbarUV; }
|
||||||
double GetVt (void) const { return Vt; }
|
double GetReynoldsNumber(void) const { return Re; }
|
||||||
double GetVground (void) const { return Vground; }
|
double GetVt (void) const { return Vt; }
|
||||||
double GetMach (void) const { return Mach; }
|
double GetVground (void) const { return Vground; }
|
||||||
double GetMachU (void) const { return MachU; }
|
double GetMach (void) const { return Mach; }
|
||||||
double GetNz (void) const { return Nz; }
|
double GetMachU (void) const { return MachU; }
|
||||||
|
double GetNz (void) const { return Nz; }
|
||||||
|
|
||||||
double GetHOverBCG(void) const { return hoverbcg; }
|
double GetHOverBCG(void) const { return hoverbcg; }
|
||||||
double GetHOverBMAC(void) const { return hoverbmac; }
|
double GetHOverBMAC(void) const { return hoverbmac; }
|
||||||
|
@ -247,6 +248,7 @@ private:
|
||||||
|
|
||||||
double Vt, Vground, Mach, MachU;
|
double Vt, Vground, Mach, MachU;
|
||||||
double qbar, qbarUW, qbarUV;
|
double qbar, qbarUW, qbarUV;
|
||||||
|
double Re; // Reynolds Number = V*c/mu
|
||||||
double alpha, beta;
|
double alpha, beta;
|
||||||
double adot,bdot;
|
double adot,bdot;
|
||||||
double psigt, gamma;
|
double psigt, gamma;
|
||||||
|
|
|
@ -46,7 +46,6 @@ INCLUDES
|
||||||
#include <models/flight_control/FGDeadBand.h>
|
#include <models/flight_control/FGDeadBand.h>
|
||||||
#include <models/flight_control/FGGain.h>
|
#include <models/flight_control/FGGain.h>
|
||||||
#include <models/flight_control/FGPID.h>
|
#include <models/flight_control/FGPID.h>
|
||||||
#include <models/flight_control/FGGradient.h>
|
|
||||||
#include <models/flight_control/FGSwitch.h>
|
#include <models/flight_control/FGSwitch.h>
|
||||||
#include <models/flight_control/FGSummer.h>
|
#include <models/flight_control/FGSummer.h>
|
||||||
#include <models/flight_control/FGKinemat.h>
|
#include <models/flight_control/FGKinemat.h>
|
||||||
|
@ -514,6 +513,10 @@ bool FGFCS::Load(Element* el, SystemType systype)
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
document = LoadXMLDocument(file);
|
document = LoadXMLDocument(file);
|
||||||
|
if (!document) {
|
||||||
|
cerr << "Error loading file " << file << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
name = document->GetAttributeValue("name");
|
name = document->GetAttributeValue("name");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -551,7 +554,7 @@ bool FGFCS::Load(Element* el, SystemType systype)
|
||||||
}
|
}
|
||||||
|
|
||||||
// After reading interface properties in a file, read properties in the local
|
// After reading interface properties in a file, read properties in the local
|
||||||
// flight_control, autopiot, or system element. This allows general-purpose
|
// flight_control, autopilot, or system element. This allows general-purpose
|
||||||
// systems to be defined in a file, with overrides or initial loaded constants
|
// systems to be defined in a file, with overrides or initial loaded constants
|
||||||
// supplied in the relevant element of the aircraft configuration file.
|
// supplied in the relevant element of the aircraft configuration file.
|
||||||
|
|
||||||
|
@ -967,7 +970,7 @@ void FGFCS::Debug(int from)
|
||||||
|
|
||||||
if (debug_lvl & 1) { // Standard console startup message output
|
if (debug_lvl & 1) { // Standard console startup message output
|
||||||
if (from == 2) { // Loader
|
if (from == 2) { // Loader
|
||||||
cout << endl << " Flight Control (" << Name << ")" << endl;
|
cout << endl << " " << Name << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
|
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
|
||||||
|
|
|
@ -89,17 +89,14 @@ bool FGGroundReactions::Run(void)
|
||||||
vForces.InitMatrix();
|
vForces.InitMatrix();
|
||||||
vMoments.InitMatrix();
|
vMoments.InitMatrix();
|
||||||
|
|
||||||
// Sum forces and moments for all gear, here.
|
// Sum forces and moments for all gear, here.
|
||||||
// Some optimizations may be made here - or rather in the gear code itself.
|
// Some optimizations may be made here - or rather in the gear code itself.
|
||||||
// The gear ::Run() method is called several times - once for each gear.
|
// The gear ::Run() method is called several times - once for each gear.
|
||||||
// Perhaps there is some commonality for things which only need to be
|
// Perhaps there is some commonality for things which only need to be
|
||||||
// calculated once.
|
// calculated once.
|
||||||
if ( Propagate->GetDistanceAGL() < 300.0 ) { // Only execute gear code below 300 feet
|
for (unsigned int i=0; i<lGear.size(); i++) {
|
||||||
for (unsigned int i=0; i<lGear.size(); i++) {
|
vForces += lGear[i]->Force();
|
||||||
vForces += lGear[i]->Force();
|
vMoments += lGear[i]->Moment();
|
||||||
vMoments += lGear[i]->Moment();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -54,7 +54,7 @@ FGInertial::FGInertial(FGFDMExec* fgex) : FGModel(fgex)
|
||||||
{
|
{
|
||||||
Name = "FGInertial";
|
Name = "FGInertial";
|
||||||
|
|
||||||
// Defaults
|
// Earth defaults
|
||||||
RotationRate = 0.00007292115;
|
RotationRate = 0.00007292115;
|
||||||
GM = 14.07644180E15; // WGS84 value
|
GM = 14.07644180E15; // WGS84 value
|
||||||
RadiusReference = 20925650.00; // Equatorial radius (WGS84)
|
RadiusReference = 20925650.00; // Equatorial radius (WGS84)
|
||||||
|
@ -64,6 +64,18 @@ FGInertial::FGInertial(FGFDMExec* fgex) : FGModel(fgex)
|
||||||
b = 20855486.5951; // WGS84 semiminor axis length in feet
|
b = 20855486.5951; // WGS84 semiminor axis length in feet
|
||||||
earthPosAngle = 0.0;
|
earthPosAngle = 0.0;
|
||||||
|
|
||||||
|
// Lunar defaults
|
||||||
|
/*
|
||||||
|
RotationRate = 0.0000026617;
|
||||||
|
GM = 1.7314079E14; // Lunar GM
|
||||||
|
RadiusReference = 5702559.05; // Equatorial radius
|
||||||
|
C2_0 = 0; // value for the C2,0 coefficient
|
||||||
|
J2 = 2.033542482111609E-4; // value for J2
|
||||||
|
a = 5702559.05; // semimajor axis length in feet
|
||||||
|
b = 5695439.63; // semiminor axis length in feet
|
||||||
|
earthPosAngle = 0.0;
|
||||||
|
*/
|
||||||
|
|
||||||
gAccelReference = GM/(RadiusReference*RadiusReference);
|
gAccelReference = GM/(RadiusReference*RadiusReference);
|
||||||
gAccel = GM/(RadiusReference*RadiusReference);
|
gAccel = GM/(RadiusReference*RadiusReference);
|
||||||
|
|
||||||
|
|
|
@ -57,8 +57,9 @@ static const char *IdHdr = ID_LGEAR;
|
||||||
CLASS IMPLEMENTATION
|
CLASS IMPLEMENTATION
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||||
|
|
||||||
FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) : Exec(fdmex),
|
FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) :
|
||||||
GearNumber(number)
|
GearNumber(number),
|
||||||
|
Exec(fdmex)
|
||||||
{
|
{
|
||||||
Element *force_table=0;
|
Element *force_table=0;
|
||||||
Element *dampCoeff=0;
|
Element *dampCoeff=0;
|
||||||
|
@ -341,97 +342,96 @@ FGColumnVector3& FGLGear::Force(void)
|
||||||
|
|
||||||
if (isRetractable) ComputeRetractionState();
|
if (isRetractable) ComputeRetractionState();
|
||||||
|
|
||||||
if (!GearDown) return vForce; // return the null vForce column vector
|
if (GearDown) {
|
||||||
|
|
||||||
vWhlBodyVec = MassBalance->StructuralToBody(vXYZ); // Get wheel in body frame
|
vWhlBodyVec = MassBalance->StructuralToBody(vXYZ); // Get wheel in body frame
|
||||||
vLocalGear = Propagate->GetTb2l() * vWhlBodyVec; // Get local frame wheel location
|
vLocalGear = Propagate->GetTb2l() * vWhlBodyVec; // Get local frame wheel location
|
||||||
|
|
||||||
gearLoc = Propagate->GetLocation().LocalToLocation(vLocalGear);
|
gearLoc = Propagate->GetLocation().LocalToLocation(vLocalGear);
|
||||||
compressLength = -Exec->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel);
|
compressLength = -Exec->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel);
|
||||||
|
|
||||||
// The compression length is measured in the Z-axis, only, at this time.
|
// The compression length is measured in the Z-axis, only, at this time.
|
||||||
|
|
||||||
if (compressLength > 0.00) {
|
if (compressLength > 0.00) {
|
||||||
|
|
||||||
WOW = true;
|
WOW = true;
|
||||||
|
|
||||||
// [The next equation should really use the vector to the contact patch of
|
// [The next equation should really use the vector to the contact patch of
|
||||||
// the tire including the strut compression and not the original vWhlBodyVec.]
|
// the tire including the strut compression and not the original vWhlBodyVec.]
|
||||||
|
|
||||||
vWhlVelVec = Propagate->GetTb2l() * (Propagate->GetPQR() * vWhlBodyVec);
|
vWhlVelVec = Propagate->GetTb2l() * (Propagate->GetPQR() * vWhlBodyVec);
|
||||||
vWhlVelVec += Propagate->GetVel() - cvel;
|
vWhlVelVec += Propagate->GetVel() - cvel;
|
||||||
compressSpeed = vWhlVelVec(eZ);
|
compressSpeed = vWhlVelVec(eZ);
|
||||||
|
|
||||||
InitializeReporting();
|
InitializeReporting();
|
||||||
ComputeBrakeForceCoefficient();
|
ComputeBrakeForceCoefficient();
|
||||||
ComputeSteeringAngle();
|
ComputeSteeringAngle();
|
||||||
ComputeSlipAngle();
|
ComputeSlipAngle();
|
||||||
ComputeSideForceCoefficient();
|
ComputeSideForceCoefficient();
|
||||||
ComputeVerticalStrutForce();
|
ComputeVerticalStrutForce();
|
||||||
|
|
||||||
// Compute the forces in the wheel ground plane.
|
// Compute the forces in the wheel ground plane.
|
||||||
|
|
||||||
double sign = RollingWhlVel>0?1.0:(RollingWhlVel<0?-1.0:0.0);
|
double sign = RollingWhlVel>0?1.0:(RollingWhlVel<0?-1.0:0.0);
|
||||||
RollingForce = ((1.0 - TirePressureNorm) * 30 + vLocalForce(eZ) * BrakeFCoeff) * sign;
|
RollingForce = ((1.0 - TirePressureNorm) * 30 + vLocalForce(eZ) * BrakeFCoeff) * sign;
|
||||||
SideForce = vLocalForce(eZ) * FCoeff;
|
SideForce = vLocalForce(eZ) * FCoeff;
|
||||||
|
|
||||||
// Transform these forces back to the local reference frame.
|
// Transform these forces back to the local reference frame.
|
||||||
|
|
||||||
vLocalForce(eX) = RollingForce*CosWheel - SideForce*SinWheel;
|
vLocalForce(eX) = RollingForce*CosWheel - SideForce*SinWheel;
|
||||||
vLocalForce(eY) = SideForce*CosWheel + RollingForce*SinWheel;
|
vLocalForce(eY) = SideForce*CosWheel + RollingForce*SinWheel;
|
||||||
|
|
||||||
// Transform the forces back to the body frame and compute the moment.
|
// Transform the forces back to the body frame and compute the moment.
|
||||||
|
|
||||||
vForce = Propagate->GetTl2b() * vLocalForce;
|
vForce = Propagate->GetTl2b() * vLocalForce;
|
||||||
|
|
||||||
// Start experimental section for gear jitter reduction
|
// Lag and attenuate the XY-plane forces dependent on velocity
|
||||||
//
|
|
||||||
// Lag and attenuate the XY-plane forces dependent on velocity
|
|
||||||
|
|
||||||
double ca, cb, denom;
|
double ca, cb, denom;
|
||||||
FGColumnVector3 Output;
|
FGColumnVector3 Output;
|
||||||
|
|
||||||
// This code implements a lag filter, C/(s + C) where
|
// This code implements a lag filter, C/(s + C) where
|
||||||
// "C" is the filter coefficient. When "C" is chosen at the
|
// "C" is the filter coefficient. When "C" is chosen at the
|
||||||
// frame rate (in Hz), the jittering is significantly reduced. This is because
|
// frame rate (in Hz), the jittering is significantly reduced. This is because
|
||||||
// the jitter is present *at* the execution rate.
|
// the jitter is present *at* the execution rate.
|
||||||
// If a coefficient is set to something equal to or less than zero, the filter
|
// If a coefficient is set to something equal to or less than zero, the filter
|
||||||
// is bypassed.
|
// is bypassed.
|
||||||
|
|
||||||
if (LongForceLagFilterCoeff > 0) {
|
if (LongForceLagFilterCoeff > 0) {
|
||||||
denom = 2.00 + dT*LongForceLagFilterCoeff;
|
denom = 2.00 + dT*LongForceLagFilterCoeff;
|
||||||
ca = dT*LongForceLagFilterCoeff / denom;
|
ca = dT*LongForceLagFilterCoeff / denom;
|
||||||
cb = (2.00 - dT*LongForceLagFilterCoeff) / denom;
|
cb = (2.00 - dT*LongForceLagFilterCoeff) / denom;
|
||||||
Output(eX) = vForce(eX) * ca + prevIn(eX) * ca + prevOut(eX) * cb;
|
Output(eX) = vForce(eX) * ca + prevIn(eX) * ca + prevOut(eX) * cb;
|
||||||
vForce(eX) = Output(eX);
|
vForce(eX) = Output(eX);
|
||||||
|
}
|
||||||
|
if (LatForceLagFilterCoeff > 0) {
|
||||||
|
denom = 2.00 + dT*LatForceLagFilterCoeff;
|
||||||
|
ca = dT*LatForceLagFilterCoeff / denom;
|
||||||
|
cb = (2.00 - dT*LatForceLagFilterCoeff) / denom;
|
||||||
|
Output(eY) = vForce(eY) * ca + prevIn(eY) * ca + prevOut(eY) * cb;
|
||||||
|
vForce(eY) = Output(eY);
|
||||||
|
}
|
||||||
|
|
||||||
|
prevIn = vForce;
|
||||||
|
prevOut = Output;
|
||||||
|
|
||||||
|
if ((fabs(RollingWhlVel) <= RFRV) && RFRV > 0) vForce(eX) *= fabs(RollingWhlVel)/RFRV;
|
||||||
|
if ((fabs(SideWhlVel) <= SFRV) && SFRV > 0) vForce(eY) *= fabs(SideWhlVel)/SFRV;
|
||||||
|
|
||||||
|
// End section for attentuating gear jitter
|
||||||
|
|
||||||
|
vMoment = vWhlBodyVec * vForce;
|
||||||
|
|
||||||
|
} else { // Gear is NOT compressed
|
||||||
|
|
||||||
|
WOW = false;
|
||||||
|
compressLength = 0.0;
|
||||||
|
|
||||||
|
// Return to neutral position between 1.0 and 0.8 gear pos.
|
||||||
|
SteerAngle *= max(GetGearUnitPos()-0.8, 0.0)/0.2;
|
||||||
|
|
||||||
|
ResetReporting();
|
||||||
}
|
}
|
||||||
if (LatForceLagFilterCoeff > 0) {
|
|
||||||
denom = 2.00 + dT*LatForceLagFilterCoeff;
|
|
||||||
ca = dT*LatForceLagFilterCoeff / denom;
|
|
||||||
cb = (2.00 - dT*LatForceLagFilterCoeff) / denom;
|
|
||||||
Output(eY) = vForce(eY) * ca + prevIn(eY) * ca + prevOut(eY) * cb;
|
|
||||||
vForce(eY) = Output(eY);
|
|
||||||
}
|
|
||||||
|
|
||||||
prevIn = vForce;
|
|
||||||
prevOut = Output;
|
|
||||||
|
|
||||||
if ((fabs(RollingWhlVel) <= RFRV) && RFRV > 0) vForce(eX) *= fabs(RollingWhlVel)/RFRV;
|
|
||||||
if ((fabs(SideWhlVel) <= SFRV) && SFRV > 0) vForce(eY) *= fabs(SideWhlVel)/SFRV;
|
|
||||||
|
|
||||||
// End section for attentuating gear jitter
|
|
||||||
|
|
||||||
vMoment = vWhlBodyVec * vForce;
|
|
||||||
|
|
||||||
} else { // Gear is NOT compressed
|
|
||||||
|
|
||||||
WOW = false;
|
|
||||||
compressLength = 0.0;
|
|
||||||
|
|
||||||
// Return to neutral position between 1.0 and 0.8 gear pos.
|
|
||||||
SteerAngle *= max(GetGearUnitPos()-0.8, 0.0)/0.2;
|
|
||||||
|
|
||||||
ResetReporting();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReportTakeoffOrLanding();
|
ReportTakeoffOrLanding();
|
||||||
|
@ -452,6 +452,7 @@ void FGLGear::ComputeRetractionState(void)
|
||||||
double gearPos = GetGearUnitPos();
|
double gearPos = GetGearUnitPos();
|
||||||
if (gearPos < 0.01) {
|
if (gearPos < 0.01) {
|
||||||
GearUp = true;
|
GearUp = true;
|
||||||
|
WOW = false;
|
||||||
GearDown = false;
|
GearDown = false;
|
||||||
} else if (gearPos > 0.99) {
|
} else if (gearPos > 0.99) {
|
||||||
GearDown = true;
|
GearDown = true;
|
||||||
|
@ -575,7 +576,7 @@ void FGLGear::ReportTakeoffOrLanding(void)
|
||||||
LandingDistanceTraveled += Auxiliary->GetVground()*deltaT;
|
LandingDistanceTraveled += Auxiliary->GetVground()*deltaT;
|
||||||
|
|
||||||
if (StartedGroundRun) {
|
if (StartedGroundRun) {
|
||||||
TakeoffDistanceTraveled50ft += Auxiliary->GetVground()*deltaT;
|
TakeoffDistanceTraveled50ft += Auxiliary->GetVground()*deltaT;
|
||||||
if (WOW) TakeoffDistanceTraveled += Auxiliary->GetVground()*deltaT;
|
if (WOW) TakeoffDistanceTraveled += Auxiliary->GetVground()*deltaT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,6 +740,8 @@ void FGLGear::bind(void)
|
||||||
snprintf(property_name, 80, "gear/unit[%d]/z-position", GearNumber);
|
snprintf(property_name, 80, "gear/unit[%d]/z-position", GearNumber);
|
||||||
Exec->GetPropertyManager()->Tie( property_name, (FGLGear*)this,
|
Exec->GetPropertyManager()->Tie( property_name, (FGLGear*)this,
|
||||||
&FGLGear::GetZPosition, &FGLGear::SetZPosition);
|
&FGLGear::GetZPosition, &FGLGear::SetZPosition);
|
||||||
|
snprintf(property_name, 80, "gear/unit[%d]/compression-ft", GearNumber);
|
||||||
|
Exec->GetPropertyManager()->Tie( property_name, &compressLength );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( isRetractable ) {
|
if( isRetractable ) {
|
||||||
|
@ -752,6 +755,8 @@ void FGLGear::bind(void)
|
||||||
|
|
||||||
void FGLGear::Report(ReportType repType)
|
void FGLGear::Report(ReportType repType)
|
||||||
{
|
{
|
||||||
|
if (fabs(TakeoffDistanceTraveled) < 0.001) return; // Don't print superfluous reports
|
||||||
|
|
||||||
switch(repType) {
|
switch(repType) {
|
||||||
case erLand:
|
case erLand:
|
||||||
cout << endl << "Touchdown report for " << name << endl;
|
cout << endl << "Touchdown report for " << name << endl;
|
||||||
|
|
|
@ -257,6 +257,9 @@ public:
|
||||||
/// Sets the brake value in percent (0 - 100)
|
/// Sets the brake value in percent (0 - 100)
|
||||||
inline void SetBrake(double bp) {brakePct = bp;}
|
inline void SetBrake(double bp) {brakePct = bp;}
|
||||||
|
|
||||||
|
/// Sets the weight-on-wheels flag.
|
||||||
|
void SetWOW(bool wow) {WOW = wow;}
|
||||||
|
|
||||||
/** Set the console touchdown reporting feature
|
/** Set the console touchdown reporting feature
|
||||||
@param flag true turns on touchdown reporting, false turns it off */
|
@param flag true turns on touchdown reporting, false turns it off */
|
||||||
inline void SetReport(bool flag) { ReportEnable = flag; }
|
inline void SetReport(bool flag) { ReportEnable = flag; }
|
||||||
|
|
|
@ -247,6 +247,7 @@ void FGOutput::DelimitedOutput(string fname)
|
||||||
if (SubSystems & ssVelocities) {
|
if (SubSystems & ssVelocities) {
|
||||||
outstream << delimeter;
|
outstream << delimeter;
|
||||||
outstream << "q bar (psf)" + delimeter;
|
outstream << "q bar (psf)" + delimeter;
|
||||||
|
outstream << "Reynolds Number" + delimeter;
|
||||||
outstream << "V_{Total} (ft/s)" + delimeter;
|
outstream << "V_{Total} (ft/s)" + delimeter;
|
||||||
outstream << "V_{Inertial} (ft/s)" + delimeter;
|
outstream << "V_{Inertial} (ft/s)" + delimeter;
|
||||||
outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter;
|
outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter;
|
||||||
|
@ -266,6 +267,9 @@ void FGOutput::DelimitedOutput(string fname)
|
||||||
if (SubSystems & ssAtmosphere) {
|
if (SubSystems & ssAtmosphere) {
|
||||||
outstream << delimeter;
|
outstream << delimeter;
|
||||||
outstream << "Rho (slugs/ft^3)" + delimeter;
|
outstream << "Rho (slugs/ft^3)" + delimeter;
|
||||||
|
outstream << "Absolute Viscosity" + delimeter;
|
||||||
|
outstream << "Kinematic Viscosity" + delimeter;
|
||||||
|
outstream << "Temperature (R)" + delimeter;
|
||||||
outstream << "P_{SL} (psf)" + delimeter;
|
outstream << "P_{SL} (psf)" + delimeter;
|
||||||
outstream << "P_{Ambient} (psf)" + delimeter;
|
outstream << "P_{Ambient} (psf)" + delimeter;
|
||||||
outstream << "Turbulence Magnitude (ft/sec)" + delimeter;
|
outstream << "Turbulence Magnitude (ft/sec)" + delimeter;
|
||||||
|
@ -274,17 +278,17 @@ void FGOutput::DelimitedOutput(string fname)
|
||||||
}
|
}
|
||||||
if (SubSystems & ssMassProps) {
|
if (SubSystems & ssMassProps) {
|
||||||
outstream << delimeter;
|
outstream << delimeter;
|
||||||
outstream << "I_xx" + delimeter;
|
outstream << "I_{xx}" + delimeter;
|
||||||
outstream << "I_xy" + delimeter;
|
outstream << "I_{xy}" + delimeter;
|
||||||
outstream << "I_xz" + delimeter;
|
outstream << "I_{xz}" + delimeter;
|
||||||
outstream << "I_yx" + delimeter;
|
outstream << "I_{yx}" + delimeter;
|
||||||
outstream << "I_yy" + delimeter;
|
outstream << "I_{yy}" + delimeter;
|
||||||
outstream << "I_yz" + delimeter;
|
outstream << "I_{yz}" + delimeter;
|
||||||
outstream << "I_zx" + delimeter;
|
outstream << "I_{zx}" + delimeter;
|
||||||
outstream << "I_zy" + delimeter;
|
outstream << "I_{zy}" + delimeter;
|
||||||
outstream << "I_zz" + delimeter;
|
outstream << "I_{zz}" + delimeter;
|
||||||
outstream << "Mass" + delimeter;
|
outstream << "Mass" + delimeter;
|
||||||
outstream << "X_cg" + delimeter + "Y_cg" + delimeter + "Z_cg";
|
outstream << "X_{cg}" + delimeter + "Y_{cg}" + delimeter + "Z_{cg}";
|
||||||
}
|
}
|
||||||
if (SubSystems & ssPropagate) {
|
if (SubSystems & ssPropagate) {
|
||||||
outstream << delimeter;
|
outstream << delimeter;
|
||||||
|
@ -348,6 +352,7 @@ void FGOutput::DelimitedOutput(string fname)
|
||||||
if (SubSystems & ssVelocities) {
|
if (SubSystems & ssVelocities) {
|
||||||
outstream << delimeter;
|
outstream << delimeter;
|
||||||
outstream << Auxiliary->Getqbar() << delimeter;
|
outstream << Auxiliary->Getqbar() << delimeter;
|
||||||
|
outstream << Auxiliary->GetReynoldsNumber() << delimeter;
|
||||||
outstream << setprecision(12) << Auxiliary->GetVt() << delimeter;
|
outstream << setprecision(12) << Auxiliary->GetVt() << delimeter;
|
||||||
outstream << Propagate->GetInertialVelocityMagnitude() << delimeter;
|
outstream << Propagate->GetInertialVelocityMagnitude() << delimeter;
|
||||||
outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter;
|
outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter;
|
||||||
|
@ -367,6 +372,9 @@ void FGOutput::DelimitedOutput(string fname)
|
||||||
if (SubSystems & ssAtmosphere) {
|
if (SubSystems & ssAtmosphere) {
|
||||||
outstream << delimeter;
|
outstream << delimeter;
|
||||||
outstream << Atmosphere->GetDensity() << delimeter;
|
outstream << Atmosphere->GetDensity() << delimeter;
|
||||||
|
outstream << Atmosphere->GetAbsoluteViscosity() << delimeter;
|
||||||
|
outstream << Atmosphere->GetKinematicViscosity() << delimeter;
|
||||||
|
outstream << Atmosphere->GetTemperature() << delimeter;
|
||||||
outstream << Atmosphere->GetPressureSL() << delimeter;
|
outstream << Atmosphere->GetPressureSL() << delimeter;
|
||||||
outstream << Atmosphere->GetPressure() << delimeter;
|
outstream << Atmosphere->GetPressure() << delimeter;
|
||||||
outstream << Atmosphere->GetTurbMagnitude() << delimeter;
|
outstream << Atmosphere->GetTurbMagnitude() << delimeter;
|
||||||
|
|
|
@ -184,7 +184,7 @@ bool FGPropulsion::GetSteadyState(void)
|
||||||
while (!steady && j < 6000) {
|
while (!steady && j < 6000) {
|
||||||
Engines[i]->Calculate();
|
Engines[i]->Calculate();
|
||||||
lastThrust = currentThrust;
|
lastThrust = currentThrust;
|
||||||
currentThrust = Engines[i]->GetThrust();
|
currentThrust = Engines[i]->GetThruster()->GetThrust();
|
||||||
if (fabs(lastThrust-currentThrust) < 0.0001) {
|
if (fabs(lastThrust-currentThrust) < 0.0001) {
|
||||||
steady_count++;
|
steady_count++;
|
||||||
if (steady_count > 120) {
|
if (steady_count > 120) {
|
||||||
|
|
|
@ -136,7 +136,7 @@ bool MSIS::InitModel(void)
|
||||||
pressure = &intPressure;
|
pressure = &intPressure;
|
||||||
density = &intDensity;
|
density = &intDensity;
|
||||||
|
|
||||||
useExternal=false;
|
UseInternal();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -174,19 +174,11 @@ bool MSIS::Run(void)
|
||||||
intTemperature = output.t[1] * 1.8;
|
intTemperature = output.t[1] * 1.8;
|
||||||
intDensity = output.d[5] * 1.940321;
|
intDensity = output.d[5] * 1.940321;
|
||||||
intPressure = 1716.488 * intDensity * intTemperature;
|
intPressure = 1716.488 * intDensity * intTemperature;
|
||||||
soundspeed = sqrt(2403.0832 * intTemperature);
|
|
||||||
//cout << "T=" << intTemperature << " D=" << intDensity << " P=";
|
//cout << "T=" << intTemperature << " D=" << intDensity << " P=";
|
||||||
//cout << intPressure << " a=" << soundspeed << endl;
|
//cout << intPressure << " a=" << soundspeed << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (turbType != ttNone) {
|
CalculateDerived();
|
||||||
Turbulence();
|
|
||||||
vWindNED += vTurbulenceNED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vWindNED(1) != 0.0) psiw = atan2( vWindNED(2), vWindNED(1) );
|
|
||||||
|
|
||||||
if (psiw < 0) psiw += 2*M_PI;
|
|
||||||
|
|
||||||
Debug(2);
|
Debug(2);
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
|
||||||
snprintf(property_name, 80, "propulsion/engine[%d]/set-running", EngineNumber);
|
snprintf(property_name, 80, "propulsion/engine[%d]/set-running", EngineNumber);
|
||||||
PropertyManager->Tie( property_name, this, &FGEngine::GetRunning, &FGEngine::SetRunning );
|
PropertyManager->Tie( property_name, this, &FGEngine::GetRunning, &FGEngine::SetRunning );
|
||||||
snprintf(property_name, 80, "propulsion/engine[%u]/thrust-lbs", EngineNumber);
|
snprintf(property_name, 80, "propulsion/engine[%u]/thrust-lbs", EngineNumber);
|
||||||
PropertyManager->Tie( property_name, this, &FGEngine::GetThrust);
|
PropertyManager->Tie( property_name, Thruster, &FGThruster::GetThrust);
|
||||||
snprintf(property_name, 80, "propulsion/engine[%u]/fuel-flow-rate-pps", EngineNumber);
|
snprintf(property_name, 80, "propulsion/engine[%u]/fuel-flow-rate-pps", EngineNumber);
|
||||||
PropertyManager->Tie( property_name, this, &FGEngine::GetFuelFlowRate);
|
PropertyManager->Tie( property_name, this, &FGEngine::GetFuelFlowRate);
|
||||||
|
|
||||||
|
@ -138,7 +138,6 @@ FGEngine::~FGEngine()
|
||||||
|
|
||||||
void FGEngine::ResetToIC(void)
|
void FGEngine::ResetToIC(void)
|
||||||
{
|
{
|
||||||
Thrust = 0.0;
|
|
||||||
Throttle = 0.0;
|
Throttle = 0.0;
|
||||||
Mixture = 1.0;
|
Mixture = 1.0;
|
||||||
Starter = false;
|
Starter = false;
|
||||||
|
|
|
@ -150,7 +150,6 @@ public:
|
||||||
virtual double getFuelFlow_gph () const {return FuelFlow_gph;}
|
virtual double getFuelFlow_gph () const {return FuelFlow_gph;}
|
||||||
virtual double getFuelFlow_pph () const {return FuelFlow_pph;}
|
virtual double getFuelFlow_pph () const {return FuelFlow_pph;}
|
||||||
virtual double GetFuelFlowRate(void) const {return FuelFlowRate;}
|
virtual double GetFuelFlowRate(void) const {return FuelFlowRate;}
|
||||||
virtual double GetThrust(void) const { return Thrust; }
|
|
||||||
virtual bool GetStarved(void) { return Starved; }
|
virtual bool GetStarved(void) { return Starved; }
|
||||||
virtual bool GetRunning(void) const { return Running; }
|
virtual bool GetRunning(void) const { return Running; }
|
||||||
virtual bool GetCranking(void) { return Cranking; }
|
virtual bool GetCranking(void) { return Cranking; }
|
||||||
|
@ -216,7 +215,6 @@ protected:
|
||||||
double MaxThrottle;
|
double MaxThrottle;
|
||||||
double MinThrottle;
|
double MinThrottle;
|
||||||
|
|
||||||
double Thrust;
|
|
||||||
double Throttle;
|
double Throttle;
|
||||||
double Mixture;
|
double Mixture;
|
||||||
double FuelExpended;
|
double FuelExpended;
|
||||||
|
|
|
@ -132,21 +132,6 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
|
||||||
*Lookup_Combustion_Efficiency << 1.60 << 0.525;
|
*Lookup_Combustion_Efficiency << 1.60 << 0.525;
|
||||||
*Lookup_Combustion_Efficiency << 2.00 << 0.345;
|
*Lookup_Combustion_Efficiency << 2.00 << 0.345;
|
||||||
|
|
||||||
Power_Mixture_Correlation = new FGTable(13);
|
|
||||||
*Power_Mixture_Correlation << (14.7/1.6) << 0.780;
|
|
||||||
*Power_Mixture_Correlation << 10 << 0.860;
|
|
||||||
*Power_Mixture_Correlation << 11 << 0.935;
|
|
||||||
*Power_Mixture_Correlation << 12 << 0.980;
|
|
||||||
*Power_Mixture_Correlation << 13 << 1.000;
|
|
||||||
*Power_Mixture_Correlation << 14 << 0.990;
|
|
||||||
*Power_Mixture_Correlation << 15 << 0.964;
|
|
||||||
*Power_Mixture_Correlation << 16 << 0.925;
|
|
||||||
*Power_Mixture_Correlation << 17 << 0.880;
|
|
||||||
*Power_Mixture_Correlation << 18 << 0.830;
|
|
||||||
*Power_Mixture_Correlation << 19 << 0.785;
|
|
||||||
*Power_Mixture_Correlation << 20 << 0.740;
|
|
||||||
*Power_Mixture_Correlation << (14.7/0.6) << 0.58;
|
|
||||||
|
|
||||||
Mixture_Efficiency_Correlation = new FGTable(15);
|
Mixture_Efficiency_Correlation = new FGTable(15);
|
||||||
*Mixture_Efficiency_Correlation << 0.05000 << 0.00000;
|
*Mixture_Efficiency_Correlation << 0.05000 << 0.00000;
|
||||||
*Mixture_Efficiency_Correlation << 0.05137 << 0.00862;
|
*Mixture_Efficiency_Correlation << 0.05137 << 0.00862;
|
||||||
|
@ -165,21 +150,6 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
|
||||||
*Mixture_Efficiency_Correlation << 0.12500 << 0.00000;
|
*Mixture_Efficiency_Correlation << 0.12500 << 0.00000;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Manifold_Pressure_Lookup = new
|
|
||||||
|
|
||||||
0 0.2 0.4 0.6 0.8 1
|
|
||||||
0 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000
|
|
||||||
1000 0.7778 0.8212 0.8647 0.9081 0.9516 0.9950
|
|
||||||
2000 0.5556 0.6424 0.7293 0.8162 0.9031 0.9900
|
|
||||||
3000 0.3333 0.4637 0.5940 0.7243 0.8547 0.9850
|
|
||||||
4000 0.2000 0.2849 0.4587 0.6324 0.8062 0.9800
|
|
||||||
5000 0.2000 0.2000 0.3233 0.5406 0.7578 0.9750
|
|
||||||
6000 0.2000 0.2000 0.2000 0.4487 0.7093 0.9700
|
|
||||||
7000 0.2000 0.2000 0.2000 0.2000 0.4570 0.7611
|
|
||||||
8000 0.2000 0.2000 0.2000 0.2000 0.2047 0.5522
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Read inputs from engine data file where present.
|
// Read inputs from engine data file where present.
|
||||||
|
|
||||||
if (el->FindElement("minmp")) // Should have ELSE statement telling default value used?
|
if (el->FindElement("minmp")) // Should have ELSE statement telling default value used?
|
||||||
|
@ -238,10 +208,17 @@ Manifold_Pressure_Lookup = new
|
||||||
RatedAltitude[2] = el->FindElementValueAsNumberConvertTo("ratedaltitude3", "FT");
|
RatedAltitude[2] = el->FindElementValueAsNumberConvertTo("ratedaltitude3", "FT");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaxManifoldPressure_Percent = MaxManifoldPressure_inHg / 29.92;
|
||||||
// Create a BSFC to match the engine if not provided
|
// Create a BSFC to match the engine if not provided
|
||||||
if (BSFC < 0) {
|
if (BSFC < 0) {
|
||||||
BSFC = ( Displacement * MaxRPM * volumetric_efficiency ) / (9411 * MaxHP);
|
BSFC = ( Displacement * MaxRPM * volumetric_efficiency ) / (9411 * MaxHP);
|
||||||
|
BSFC *= (MaxManifoldPressure_Percent * MaxManifoldPressure_Percent * MaxManifoldPressure_Percent);
|
||||||
}
|
}
|
||||||
|
if ( MaxManifoldPressure_inHg > 29.9 ) { // Don't allow boosting with a bogus number
|
||||||
|
MaxManifoldPressure_inHg = 29.9;
|
||||||
|
MaxManifoldPressure_Percent = MaxManifoldPressure_inHg / 29.92;
|
||||||
|
}
|
||||||
|
|
||||||
char property_name[80];
|
char property_name[80];
|
||||||
snprintf(property_name, 80, "propulsion/engine[%d]/power-hp", EngineNumber);
|
snprintf(property_name, 80, "propulsion/engine[%d]/power-hp", EngineNumber);
|
||||||
PropertyManager->Tie(property_name, &HP);
|
PropertyManager->Tie(property_name, &HP);
|
||||||
|
@ -299,7 +276,9 @@ Manifold_Pressure_Lookup = new
|
||||||
BoostSpeed = 0;
|
BoostSpeed = 0;
|
||||||
}
|
}
|
||||||
bBoostOverride = (BoostOverride == 1 ? true : false);
|
bBoostOverride = (BoostOverride == 1 ? true : false);
|
||||||
if (MinThrottle < 0.001) MinThrottle = 0.001; //MinThrottle is a denominator in a power equation so it can't be zero
|
if (MinThrottle < 0.12) MinThrottle = 0.12; //MinThrottle is limited to 0.12 to prevent the
|
||||||
|
// throttle area equation from going negative
|
||||||
|
// 0.12 is 1% of maximum area
|
||||||
Debug(0); // Call Debug() routine from constructor if needed
|
Debug(0); // Call Debug() routine from constructor if needed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +287,6 @@ Manifold_Pressure_Lookup = new
|
||||||
FGPiston::~FGPiston()
|
FGPiston::~FGPiston()
|
||||||
{
|
{
|
||||||
delete Lookup_Combustion_Efficiency;
|
delete Lookup_Combustion_Efficiency;
|
||||||
delete Power_Mixture_Correlation;
|
|
||||||
delete Mixture_Efficiency_Correlation;
|
delete Mixture_Efficiency_Correlation;
|
||||||
Debug(1); // Call Debug() routine from constructor if needed
|
Debug(1); // Call Debug() routine from constructor if needed
|
||||||
}
|
}
|
||||||
|
@ -338,7 +316,8 @@ double FGPiston::Calculate(void)
|
||||||
if (FuelFlow_gph > 0.0) ConsumeFuel();
|
if (FuelFlow_gph > 0.0) ConsumeFuel();
|
||||||
|
|
||||||
Throttle = FCS->GetThrottlePos(EngineNumber);
|
Throttle = FCS->GetThrottlePos(EngineNumber);
|
||||||
ThrottlePos = MinThrottle+((MaxThrottle-MinThrottle)*Throttle );
|
// calculate the throttle plate angle. 1 unit is pi/2 radians.
|
||||||
|
ThrottleAngle = MinThrottle+((MaxThrottle-MinThrottle)*Throttle );
|
||||||
Mixture = FCS->GetMixturePos(EngineNumber);
|
Mixture = FCS->GetMixturePos(EngineNumber);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -367,8 +346,7 @@ double FGPiston::Calculate(void)
|
||||||
// Running = false;
|
// Running = false;
|
||||||
|
|
||||||
doEnginePower();
|
doEnginePower();
|
||||||
if(HP<0.1250)
|
if (HP < 0.1250) Running = false;
|
||||||
Running = false;
|
|
||||||
|
|
||||||
doEGT();
|
doEGT();
|
||||||
doCHT();
|
doCHT();
|
||||||
|
@ -390,8 +368,6 @@ if(HP<0.1250)
|
||||||
double FGPiston::CalcFuelNeed(void)
|
double FGPiston::CalcFuelNeed(void)
|
||||||
{
|
{
|
||||||
double dT = State->Getdt() * Propulsion->GetRate();
|
double dT = State->Getdt() * Propulsion->GetRate();
|
||||||
FuelFlow_pph = FuelFlow_gph * 6.0; // Assumes 6 lbs / gallon
|
|
||||||
FuelFlowRate = FuelFlow_pph / 3600.0;
|
|
||||||
FuelExpended = FuelFlowRate * dT;
|
FuelExpended = FuelFlowRate * dT;
|
||||||
return FuelExpended;
|
return FuelExpended;
|
||||||
}
|
}
|
||||||
|
@ -510,20 +486,18 @@ void FGPiston::doBoostControl(void)
|
||||||
* from the throttle position, turbo/supercharger boost control
|
* from the throttle position, turbo/supercharger boost control
|
||||||
* system, engine speed and local ambient air density.
|
* system, engine speed and local ambient air density.
|
||||||
*
|
*
|
||||||
* TODO: changes in MP should not be instantaneous -- introduce
|
* Inputs: p_amb, Throttle, MaxManifoldPressure_Percent, ThrottleAngle
|
||||||
* a lag between throttle changes and MP changes, to allow pressure
|
* RPM, MaxRPM
|
||||||
* to build up or disperse.
|
|
||||||
*
|
|
||||||
* Inputs: minMAP, maxMAP, p_amb, Throttle
|
|
||||||
*
|
*
|
||||||
* Outputs: MAP, ManifoldPressure_inHg
|
* Outputs: MAP, ManifoldPressure_inHg
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void FGPiston::doMAP(void)
|
void FGPiston::doMAP(void)
|
||||||
{
|
{
|
||||||
suction_loss = RPM > 0.0 ? ThrottlePos * MaxRPM / RPM : 1.0;
|
// estimate throttle plate area. This maps 0.2 -> 0.1 for historical performance reasons
|
||||||
if (suction_loss > 1.0) suction_loss = 1.0;
|
double throttle_area = ThrottleAngle * 1.125 - 0.125;
|
||||||
MAP = p_amb * suction_loss;
|
map_coefficient = pow ((throttle_area * MaxManifoldPressure_Percent),RPM/MaxRPM);
|
||||||
|
MAP = p_amb * map_coefficient;
|
||||||
|
|
||||||
if(Boosted) {
|
if(Boosted) {
|
||||||
// If takeoff boost is fitted, we currently assume the following throttle map:
|
// If takeoff boost is fitted, we currently assume the following throttle map:
|
||||||
|
@ -549,7 +523,7 @@ void FGPiston::doMAP(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Boost the manifold pressure.
|
// Boost the manifold pressure.
|
||||||
double boost_factor = BoostMul[BoostSpeed] * suction_loss * RPM/RatedRPM[BoostSpeed];
|
double boost_factor = BoostMul[BoostSpeed] * map_coefficient * RPM/RatedRPM[BoostSpeed];
|
||||||
if (boost_factor < 1.0) boost_factor = 1.0; // boost will never reduce the MAP
|
if (boost_factor < 1.0) boost_factor = 1.0; // boost will never reduce the MAP
|
||||||
MAP *= boost_factor;
|
MAP *= boost_factor;
|
||||||
// Now clip the manifold pressure to BCV or Wastegate setting.
|
// Now clip the manifold pressure to BCV or Wastegate setting.
|
||||||
|
@ -575,7 +549,7 @@ void FGPiston::doMAP(void)
|
||||||
* (used in CHT calculation for air-cooled engines).
|
* (used in CHT calculation for air-cooled engines).
|
||||||
*
|
*
|
||||||
* Inputs: p_amb, R_air, T_amb, MAP, Displacement,
|
* Inputs: p_amb, R_air, T_amb, MAP, Displacement,
|
||||||
* RPM, volumetric_efficiency, ThrottlePos
|
* RPM, volumetric_efficiency, ThrottleAngle
|
||||||
*
|
*
|
||||||
* TODO: Model inlet manifold air temperature.
|
* TODO: Model inlet manifold air temperature.
|
||||||
*
|
*
|
||||||
|
@ -587,7 +561,7 @@ void FGPiston::doAirFlow(void)
|
||||||
rho_air = p_amb / (R_air * T_amb);
|
rho_air = p_amb / (R_air * T_amb);
|
||||||
double displacement_SI = Displacement * in3tom3;
|
double displacement_SI = Displacement * in3tom3;
|
||||||
double swept_volume = (displacement_SI * (RPM/60)) / 2;
|
double swept_volume = (displacement_SI * (RPM/60)) / 2;
|
||||||
double v_dot_air = swept_volume * volumetric_efficiency * suction_loss;
|
double v_dot_air = swept_volume * volumetric_efficiency * map_coefficient;
|
||||||
|
|
||||||
double rho_air_manifold = MAP / (R_air * T_amb);
|
double rho_air_manifold = MAP / (R_air * T_amb);
|
||||||
m_dot_air = v_dot_air * rho_air_manifold;
|
m_dot_air = v_dot_air * rho_air_manifold;
|
||||||
|
@ -609,11 +583,9 @@ void FGPiston::doFuelFlow(void)
|
||||||
// double AFR = 10+(12*(1-Mixture));// mixture 10:1 to 22:1
|
// double AFR = 10+(12*(1-Mixture));// mixture 10:1 to 22:1
|
||||||
// m_dot_fuel = m_dot_air / AFR;
|
// m_dot_fuel = m_dot_air / AFR;
|
||||||
m_dot_fuel = (m_dot_air * equivalence_ratio) / 14.7;
|
m_dot_fuel = (m_dot_air * equivalence_ratio) / 14.7;
|
||||||
FuelFlow_gph = m_dot_fuel
|
FuelFlowRate = m_dot_fuel * 2.2046; // kg to lb
|
||||||
* 3600 // seconds to hours
|
FuelFlow_pph = FuelFlowRate * 3600; // seconds to hours
|
||||||
* 2.2046 // kg to lb
|
FuelFlow_gph = FuelFlow_pph / 6.0; // Assumes 6 lbs / gallon
|
||||||
/ 6.0; // lb to gal_us of gasoline
|
|
||||||
// / 6.6; // lb to gal_us of kerosene
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
@ -649,7 +621,7 @@ void FGPiston::doEnginePower(void)
|
||||||
if ( Magnetos != 3 ) power *= SparkFailDrop;
|
if ( Magnetos != 3 ) power *= SparkFailDrop;
|
||||||
|
|
||||||
|
|
||||||
HP = (FuelFlow_gph * 6.0 / BSFC )* ME * suction_loss * power;
|
HP = (FuelFlow_gph * 6.0 / BSFC )* ME * map_coefficient * power;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -871,17 +843,13 @@ void FGPiston::Debug(int from)
|
||||||
cout << " IdleRPM: " << IdleRPM << endl;
|
cout << " IdleRPM: " << IdleRPM << endl;
|
||||||
cout << " MaxThrottle: " << MaxThrottle << endl;
|
cout << " MaxThrottle: " << MaxThrottle << endl;
|
||||||
cout << " MinThrottle: " << MinThrottle << endl;
|
cout << " MinThrottle: " << MinThrottle << endl;
|
||||||
|
cout << " BSFC: " << BSFC << endl;
|
||||||
|
|
||||||
cout << endl;
|
cout << endl;
|
||||||
cout << " Combustion Efficiency table:" << endl;
|
cout << " Combustion Efficiency table:" << endl;
|
||||||
Lookup_Combustion_Efficiency->Print();
|
Lookup_Combustion_Efficiency->Print();
|
||||||
cout << endl;
|
cout << endl;
|
||||||
|
|
||||||
cout << endl;
|
|
||||||
cout << " Power Mixture Correlation table:" << endl;
|
|
||||||
Power_Mixture_Correlation->Print();
|
|
||||||
cout << endl;
|
|
||||||
|
|
||||||
cout << endl;
|
cout << endl;
|
||||||
cout << " Mixture Efficiency Correlation table:" << endl;
|
cout << " Mixture Efficiency Correlation table:" << endl;
|
||||||
Mixture_Efficiency_Correlation->Print();
|
Mixture_Efficiency_Correlation->Print();
|
||||||
|
|
|
@ -205,8 +205,7 @@ public:
|
||||||
double getRPM(void) {return RPM;}
|
double getRPM(void) {return RPM;}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
double ThrottlePos;
|
double ThrottleAngle;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int crank_counter;
|
int crank_counter;
|
||||||
|
@ -252,6 +251,7 @@ private:
|
||||||
//
|
//
|
||||||
double MinManifoldPressure_inHg; // Inches Hg
|
double MinManifoldPressure_inHg; // Inches Hg
|
||||||
double MaxManifoldPressure_inHg; // Inches Hg
|
double MaxManifoldPressure_inHg; // Inches Hg
|
||||||
|
double MaxManifoldPressure_Percent; // MaxManifoldPressure / 29.92
|
||||||
double Displacement; // cubic inches
|
double Displacement; // cubic inches
|
||||||
double MaxHP; // horsepower
|
double MaxHP; // horsepower
|
||||||
double SparkFailDrop; // drop of power due to spark failure
|
double SparkFailDrop; // drop of power due to spark failure
|
||||||
|
@ -304,7 +304,7 @@ private:
|
||||||
//
|
//
|
||||||
double rho_air;
|
double rho_air;
|
||||||
double volumetric_efficiency;
|
double volumetric_efficiency;
|
||||||
double suction_loss;
|
double map_coefficient;
|
||||||
double m_dot_air;
|
double m_dot_air;
|
||||||
double equivalence_ratio;
|
double equivalence_ratio;
|
||||||
double m_dot_fuel;
|
double m_dot_fuel;
|
||||||
|
|
|
@ -106,6 +106,7 @@ FGRocket::~FGRocket(void)
|
||||||
double FGRocket::Calculate(void)
|
double FGRocket::Calculate(void)
|
||||||
{
|
{
|
||||||
double dT = State->Getdt()*Propulsion->GetRate();
|
double dT = State->Getdt()*Propulsion->GetRate();
|
||||||
|
double thrust;
|
||||||
|
|
||||||
if (!Flameout && !Starved) ConsumeFuel();
|
if (!Flameout && !Starved) ConsumeFuel();
|
||||||
|
|
||||||
|
@ -135,7 +136,7 @@ double FGRocket::Calculate(void)
|
||||||
|
|
||||||
if (Throttle < MinThrottle || Starved) { // Combustion not supported
|
if (Throttle < MinThrottle || Starved) { // Combustion not supported
|
||||||
|
|
||||||
PctPower = Thrust = 0.0; // desired thrust
|
PctPower = 0.0; // desired thrust
|
||||||
Flameout = true;
|
Flameout = true;
|
||||||
VacThrust = 0.0;
|
VacThrust = 0.0;
|
||||||
|
|
||||||
|
@ -149,10 +150,10 @@ double FGRocket::Calculate(void)
|
||||||
|
|
||||||
} // End thrust calculations
|
} // End thrust calculations
|
||||||
|
|
||||||
Thrust = Thruster->Calculate(VacThrust);
|
thrust = Thruster->Calculate(VacThrust);
|
||||||
It += Thrust * dT;
|
It += thrust * dT;
|
||||||
|
|
||||||
return Thrust;
|
return thrust;
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
|
@ -148,6 +148,8 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
|
||||||
if (Temperature != -9999.0) InitialTemperature = Temperature = FahrenheitToCelsius(Temperature);
|
if (Temperature != -9999.0) InitialTemperature = Temperature = FahrenheitToCelsius(Temperature);
|
||||||
Area = 40.0 * pow(Capacity/1975, 0.666666667);
|
Area = 40.0 * pow(Capacity/1975, 0.666666667);
|
||||||
|
|
||||||
|
CalculateInertias();
|
||||||
|
|
||||||
Debug(0);
|
Debug(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMEx
|
||||||
PropertyManager->Tie( property_name, (FGForce *)this, &FGForce::GetYaw, &FGForce::SetYaw);
|
PropertyManager->Tie( property_name, (FGForce *)this, &FGForce::GetYaw, &FGForce::SetYaw);
|
||||||
|
|
||||||
if (el->GetName() == "direct") // this is a direct thruster. At this time
|
if (el->GetName() == "direct") // this is a direct thruster. At this time
|
||||||
// only a direct thruster can be reversed.
|
// only a direct thruster can be reversed.
|
||||||
{
|
{
|
||||||
snprintf(property_name, 80, "propulsion/engine[%d]/reverser-angle-rad", EngineNum);
|
snprintf(property_name, 80, "propulsion/engine[%d]/reverser-angle-rad", EngineNum);
|
||||||
PropertyManager->Tie( property_name, (FGThruster *)this, &FGThruster::GetReverserAngle,
|
PropertyManager->Tie( property_name, (FGThruster *)this, &FGThruster::GetReverserAngle,
|
||||||
|
|
|
@ -99,7 +99,7 @@ public:
|
||||||
virtual void SetRPM(double rpm) {};
|
virtual void SetRPM(double rpm) {};
|
||||||
virtual double GetPowerRequired(void) {return 0.0;}
|
virtual double GetPowerRequired(void) {return 0.0;}
|
||||||
virtual void SetdeltaT(double dt) {deltaT = dt;}
|
virtual void SetdeltaT(double dt) {deltaT = dt;}
|
||||||
double GetThrust(void) {return Thrust;}
|
double GetThrust(void) const {return Thrust;}
|
||||||
eType GetType(void) {return Type;}
|
eType GetType(void) {return Type;}
|
||||||
string GetName(void) {return Name;}
|
string GetName(void) {return Name;}
|
||||||
void SetReverserAngle(double angle) {ReverserAngle = angle;}
|
void SetReverserAngle(double angle) {ReverserAngle = angle;}
|
||||||
|
|
|
@ -107,6 +107,8 @@ void FGTurbine::ResetToIC(void)
|
||||||
|
|
||||||
double FGTurbine::Calculate(void)
|
double FGTurbine::Calculate(void)
|
||||||
{
|
{
|
||||||
|
double thrust;
|
||||||
|
|
||||||
TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
|
TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
|
||||||
dt = State->Getdt() * Propulsion->GetRate();
|
dt = State->Getdt() * Propulsion->GetRate();
|
||||||
ThrottlePos = FCS->GetThrottlePos(EngineNumber);
|
ThrottlePos = FCS->GetThrottlePos(EngineNumber);
|
||||||
|
@ -144,19 +146,19 @@ double FGTurbine::Calculate(void)
|
||||||
if (Seized) phase = tpSeize;
|
if (Seized) phase = tpSeize;
|
||||||
|
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case tpOff: Thrust = Off(); break;
|
case tpOff: thrust = Off(); break;
|
||||||
case tpRun: Thrust = Run(); break;
|
case tpRun: thrust = Run(); break;
|
||||||
case tpSpinUp: Thrust = SpinUp(); break;
|
case tpSpinUp: thrust = SpinUp(); break;
|
||||||
case tpStart: Thrust = Start(); break;
|
case tpStart: thrust = Start(); break;
|
||||||
case tpStall: Thrust = Stall(); break;
|
case tpStall: thrust = Stall(); break;
|
||||||
case tpSeize: Thrust = Seize(); break;
|
case tpSeize: thrust = Seize(); break;
|
||||||
case tpTrim: Thrust = Trim(); break;
|
case tpTrim: thrust = Trim(); break;
|
||||||
default: Thrust = Off();
|
default: thrust = Off();
|
||||||
}
|
}
|
||||||
|
|
||||||
Thrust = Thruster->Calculate(Thrust); // allow thruster to modify thrust (i.e. reversing)
|
thrust = Thruster->Calculate(thrust); // allow thruster to modify thrust (i.e. reversing)
|
||||||
|
|
||||||
return Thrust;
|
return thrust;
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
|
@ -169,7 +169,6 @@ public:
|
||||||
double Calculate(void);
|
double Calculate(void);
|
||||||
double CalcFuelNeed(void);
|
double CalcFuelNeed(void);
|
||||||
double GetPowerAvailable(void);
|
double GetPowerAvailable(void);
|
||||||
// double GetThrust(void) const {return Thrust;}
|
|
||||||
/** A lag filter.
|
/** A lag filter.
|
||||||
Used to control the rate at which values are allowed to change.
|
Used to control the rate at which values are allowed to change.
|
||||||
@param var a pointer to a variable of type double
|
@param var a pointer to a variable of type double
|
||||||
|
|
Loading…
Add table
Reference in a new issue