1
0
Fork 0

Sync'ed JSBSim

- Trim reports, FGOutputFG and sockets messages now respond to the debug level
- Channels : fix for incorrect time steps caused by execrate
- Improved configuration error detection in FGSwitch with respect to late bound
- Fixed the ordre in which the components of the p-factor moment are reported in CSV output files.
This commit is contained in:
Bertrand Coconnier 2018-07-20 23:38:33 +02:00
parent af380e0d8c
commit ec004d8c6b
13 changed files with 134 additions and 144 deletions

View file

@ -1142,7 +1142,9 @@ void FGFDMExec::DoTrim(int mode)
FGTrim trim(this, (JSBSim::TrimMode)mode); FGTrim trim(this, (JSBSim::TrimMode)mode);
bool success = trim.DoTrim(); bool success = trim.DoTrim();
trim.Report();
if (debug_lvl > 0)
trim.Report();
if (!success) if (!success)
throw("Trim Failed"); throw("Trim Failed");

View file

@ -122,6 +122,26 @@ FGOutputFG::FGOutputFG(FGFDMExec* fdmex) :
FGOutputSocket(fdmex) FGOutputSocket(fdmex)
{ {
memset(&fgSockBuf, 0x0, sizeof(fgSockBuf)); memset(&fgSockBuf, 0x0, sizeof(fgSockBuf));
if (fdmex->GetDebugLevel() > 0) {
// Engine status
if (Propulsion->GetNumEngines() > FGNetFDM::FG_MAX_ENGINES)
cerr << "This vehicle has " << Propulsion->GetNumEngines() << " engines, but the current " << endl
<< "version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_ENGINES << " engines." << endl
<< "Only the first " << FGNetFDM::FG_MAX_ENGINES << " engines will be used." << endl;
// Consumables
if (Propulsion->GetNumTanks() > FGNetFDM::FG_MAX_TANKS)
cerr << "This vehicle has " << Propulsion->GetNumTanks() << " tanks, but the current " << endl
<< "version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_TANKS << " tanks." << endl
<< "Only the first " << FGNetFDM::FG_MAX_TANKS << " tanks will be used." << endl;
// Gear status
if (GroundReactions->GetNumGearUnits() > FGNetFDM::FG_MAX_WHEELS)
cerr << "This vehicle has " << GroundReactions->GetNumGearUnits() << " bogeys, but the current " << endl
<< "version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_WHEELS << " bogeys." << endl
<< "Only the first " << FGNetFDM::FG_MAX_WHEELS << " bogeys will be used." << endl;
}
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -169,12 +189,6 @@ void FGOutputFG::SocketDataFill(FGNetFDM* net)
net->stall_warning = 0.0; // 0.0 - 1.0 indicating the amount of stall net->stall_warning = 0.0; // 0.0 - 1.0 indicating the amount of stall
net->slip_deg = (float)(Auxiliary->Getbeta(inDegrees)); // slip ball deflection, deg net->slip_deg = (float)(Auxiliary->Getbeta(inDegrees)); // slip ball deflection, deg
// Engine status
if (Propulsion->GetNumEngines() > FGNetFDM::FG_MAX_ENGINES && FDMExec->GetSimTime() == 0.0)
cerr << "This vehicle has " << Propulsion->GetNumEngines() << " engines, but the current " << endl
<< "version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_ENGINES << " engines." << endl
<< "Only the first " << FGNetFDM::FG_MAX_ENGINES << " engines will be used." << endl;
net->num_engines = min(FGNetFDM::FG_MAX_ENGINES,Propulsion->GetNumEngines()); // Number of valid engines net->num_engines = min(FGNetFDM::FG_MAX_ENGINES,Propulsion->GetNumEngines()); // Number of valid engines
for (i=0; i<net->num_engines; i++) { for (i=0; i<net->num_engines; i++) {
@ -210,24 +224,12 @@ void FGOutputFG::SocketDataFill(FGNetFDM* net)
} }
} }
// Consumables
if (Propulsion->GetNumTanks() > FGNetFDM::FG_MAX_TANKS && FDMExec->GetSimTime() == 0.0)
cerr << "This vehicle has " << Propulsion->GetNumTanks() << " tanks, but the current " << endl
<< "version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_TANKS << " tanks." << endl
<< "Only the first " << FGNetFDM::FG_MAX_TANKS << " tanks will be used." << endl;
net->num_tanks = min(FGNetFDM::FG_MAX_TANKS, Propulsion->GetNumTanks()); // Max number of fuel tanks net->num_tanks = min(FGNetFDM::FG_MAX_TANKS, Propulsion->GetNumTanks()); // Max number of fuel tanks
for (i=0; i<net->num_tanks; i++) { for (i=0; i<net->num_tanks; i++) {
net->fuel_quantity[i] = (float)(((FGTank *)Propulsion->GetTank(i))->GetContents()); net->fuel_quantity[i] = (float)(((FGTank *)Propulsion->GetTank(i))->GetContents());
} }
// Gear status
if (GroundReactions->GetNumGearUnits() > FGNetFDM::FG_MAX_WHEELS && FDMExec->GetSimTime() == 0.0)
cerr << "This vehicle has " << GroundReactions->GetNumGearUnits() << " bogeys, but the current " << endl
<< "version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_WHEELS << " bogeys." << endl
<< "Only the first " << FGNetFDM::FG_MAX_WHEELS << " bogeys will be used." << endl;
net->num_wheels = min(FGNetFDM::FG_MAX_WHEELS, GroundReactions->GetNumGearUnits()); net->num_wheels = min(FGNetFDM::FG_MAX_WHEELS, GroundReactions->GetNumGearUnits());
for (i=0; i<net->num_wheels; i++) { for (i=0; i<net->num_wheels; i++) {

View file

@ -62,15 +62,17 @@ CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
static bool LoadWinSockDLL(void) static bool LoadWinSockDLL(int debug_lvl)
{ {
WSADATA wsaData; WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData)) { if (WSAStartup(MAKEWORD(1, 1), &wsaData)) {
cout << "Winsock DLL not initialized ..." << endl; cerr << "Winsock DLL not initialized ..." << endl;
return false; return false;
} }
cout << "Winsock DLL loaded ..." << endl; if (debug_lvl > 0)
cout << "Winsock DLL loaded ..." << endl;
return true; return true;
} }
#endif #endif
@ -82,48 +84,53 @@ FGfdmSocket::FGfdmSocket(const string& address, int port, int protocol)
connected = false; connected = false;
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
if (!LoadWinSockDLL()) return; if (!LoadWinSockDLL(debug_lvl)) return;
#endif #endif
if (!is_number(address)) { if (!is_number(address)) {
if ((host = gethostbyname(address.c_str())) == NULL) { host = gethostbyname(address.c_str());
cout << "Could not get host net address by name..." << endl; if (host == NULL) {
cerr << "Could not get host net address by name..." << endl;
return;
} }
} else { } else {
unsigned long ip; unsigned long ip = inet_addr(address.c_str());
ip = inet_addr(address.c_str()); host = gethostbyaddr((char*)&ip, sizeof(ip), PF_INET);
if ((host = gethostbyaddr((char*)&ip, sizeof(ip), PF_INET)) == NULL) { if (host == NULL) {
cout << "Could not get host net address by number..." << endl; cerr << "Could not get host net address by number..." << endl;
return;
} }
} }
if (host != NULL) { if (protocol == ptUDP) { //use udp protocol
if (protocol == ptUDP) { //use udp protocol sckt = socket(AF_INET, SOCK_DGRAM, 0);
sckt = socket(AF_INET, SOCK_DGRAM, 0);
cout << "Creating UDP socket on port " << port << endl;
}
else { //use tcp protocol
sckt = socket(AF_INET, SOCK_STREAM, 0);
cout << "Creating TCP socket on port " << port << endl;
}
if (sckt >= 0) { // successful if (debug_lvl > 0)
memset(&scktName, 0, sizeof(struct sockaddr_in)); cout << "Creating UDP socket on port " << port << endl;
scktName.sin_family = AF_INET; }
scktName.sin_port = htons(port); else { //use tcp protocol
memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length); sckt = socket(AF_INET, SOCK_STREAM, 0);
int len = sizeof(struct sockaddr_in);
if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) { // successful if (debug_lvl > 0)
cout << "Creating TCP socket on port " << port << endl;
}
if (sckt >= 0) { // successful
memset(&scktName, 0, sizeof(struct sockaddr_in));
scktName.sin_family = AF_INET;
scktName.sin_port = htons(port);
memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length);
int len = sizeof(struct sockaddr_in);
if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) { // successful
if (debug_lvl > 0)
cout << "Successfully connected to socket for output ..." << endl; cout << "Successfully connected to socket for output ..." << endl;
connected = true; connected = true;
} else { // unsuccessful } else // unsuccessful
cout << "Could not connect to socket for output ..." << endl; cerr << "Could not connect to socket for output ..." << endl;
} } else // unsuccessful
} else { // unsuccessful cerr << "Could not create socket for FDM output, error = " << errno << endl;
cout << "Could not create socket for FDM output, error = " << errno << endl;
}
}
Debug(0); Debug(0);
} }
@ -137,7 +144,7 @@ FGfdmSocket::FGfdmSocket(int port, int protocol)
string ProtocolName; string ProtocolName;
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
if (!LoadWinSockDLL()) return; if (!LoadWinSockDLL(debug_lvl)) return;
#endif #endif
if (Protocol == ptUDP) { //use udp protocol if (Protocol == ptUDP) { //use udp protocol
@ -154,18 +161,25 @@ FGfdmSocket::FGfdmSocket(int port, int protocol)
ProtocolName = "TCP"; ProtocolName = "TCP";
sckt = socket(AF_INET, SOCK_STREAM, 0); sckt = socket(AF_INET, SOCK_STREAM, 0);
} }
cout << "Creating input " << ProtocolName << " socket on port " << port << endl;
if (debug_lvl > 0)
cout << "Creating input " << ProtocolName << " socket on port " << port
<< endl;
if (sckt != -1) { if (sckt != -1) {
memset(&scktName, 0, sizeof(struct sockaddr_in)); memset(&scktName, 0, sizeof(struct sockaddr_in));
scktName.sin_family = AF_INET; scktName.sin_family = AF_INET;
scktName.sin_port = htons(port); scktName.sin_port = htons(port);
if (Protocol == ptUDP) if (Protocol == ptUDP)
scktName.sin_addr.s_addr = htonl(INADDR_ANY); scktName.sin_addr.s_addr = htonl(INADDR_ANY);
int len = sizeof(struct sockaddr_in); int len = sizeof(struct sockaddr_in);
if (bind(sckt, (struct sockaddr*)&scktName, len) != -1) { if (bind(sckt, (struct sockaddr*)&scktName, len) != -1) {
cout << "Successfully bound to " << ProtocolName << " input socket on port " if (debug_lvl > 0)
<< port << endl <<endl; cout << "Successfully bound to " << ProtocolName
<< " input socket on port " << port << endl << endl;
if (Protocol == ptTCP) { if (Protocol == ptTCP) {
unsigned long NoBlock = true; unsigned long NoBlock = true;
if (listen(sckt, 5) >= 0) { // successful listen() if (listen(sckt, 5) >= 0) { // successful listen()
@ -177,74 +191,22 @@ FGfdmSocket::FGfdmSocket(int port, int protocol)
sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len); sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len);
#endif #endif
connected = true; connected = true;
} else { } else
cerr << "Could not listen ..." << endl; cerr << "Could not listen ..." << endl;
}
} else } else
connected = true; connected = true;
} else { // unsuccessful } else // unsuccessful
cout << "Could not bind to " << ProtocolName << " input socket, error = " cerr << "Could not bind to " << ProtocolName << " input socket, error = "
<< errno << endl; << errno << endl;
} } else // unsuccessful
} else { // unsuccessful cerr << "Could not create " << ProtocolName << " socket for input, error = "
cout << "Could not create " << ProtocolName << " socket for input, error = "
<< errno << endl; << errno << endl;
}
Debug(0); Debug(0);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGfdmSocket::FGfdmSocket(const string& address, int port) // assumes TCP
{
sckt = sckt_in = 0;
connected = false;
Protocol = ptTCP;
#if defined(_MSC_VER) || defined(__MINGW32__)
if (!LoadWinSockDLL()) return;
#endif
cout << "... Socket Configuration Sanity Check ..." << endl;
cout << "Host name... " << address << ", Port... " << port << "." << endl;
cout << "Host name... (char) " << address.c_str() << "." << endl;
if (!is_number(address)) {
if ((host = gethostbyname(address.c_str())) == NULL) {
cout << "Could not get host net address by name..." << endl;
}
} else {
if ((host = gethostbyaddr(address.c_str(), address.size(), PF_INET)) == NULL) {
cout << "Could not get host net address by number..." << endl;
}
}
if (host != NULL) {
cout << "Got host net address..." << endl;
sckt = socket(AF_INET, SOCK_STREAM, 0);
if (sckt >= 0) { // successful
memset(&scktName, 0, sizeof(struct sockaddr_in));
scktName.sin_family = AF_INET;
scktName.sin_port = htons(port);
memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length);
int len = sizeof(struct sockaddr_in);
if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) { // successful
cout << "Successfully connected to socket for output ..." << endl;
connected = true;
} else { // unsuccessful
cout << "Could not connect to socket for output ..." << endl;
}
} else { // unsuccessful
cout << "Could not create socket for FDM output, error = " << errno << endl;
}
}
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGfdmSocket::~FGfdmSocket() FGfdmSocket::~FGfdmSocket()
{ {
if (sckt) shutdown(sckt,2); if (sckt) shutdown(sckt,2);
@ -391,6 +353,16 @@ void FGfdmSocket::Send(const char *data, int length)
} }
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGfdmSocket::WaitUntilReadable(void)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(sckt_in, &fds);
select(sckt_in+1, &fds, NULL, NULL, NULL);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows: // The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print // unset: In this case (the default) JSBSim would only print

View file

@ -83,7 +83,8 @@ CLASS DECLARATION
class FGfdmSocket : public FGJSBBase class FGfdmSocket : public FGJSBBase
{ {
public: public:
FGfdmSocket(const std::string&, int); FGfdmSocket(const std::string& address, int port)
: FGfdmSocket(address, port, ptTCP) {}
FGfdmSocket(const std::string&, int, int); FGfdmSocket(const std::string&, int, int);
FGfdmSocket(int, int); FGfdmSocket(int, int);
~FGfdmSocket(); ~FGfdmSocket();
@ -100,6 +101,7 @@ public:
void Clear(const std::string& s); void Clear(const std::string& s);
void Close(void); void Close(void);
bool GetConnectStatus(void) {return connected;} bool GetConnectStatus(void) {return connected;}
void WaitUntilReadable(void);
enum ProtocolType {ptUDP, ptTCP}; enum ProtocolType {ptUDP, ptTCP};

View file

@ -149,14 +149,14 @@ bool FGAuxiliary::Run(bool Holding)
vAeroPQR = in.vPQR - in.TurbPQR; vAeroPQR = in.vPQR - in.TurbPQR;
vAeroUVW = in.vUVW - in.Tl2b * in.TotalWindNED; vAeroUVW = in.vUVW - in.Tl2b * in.TotalWindNED;
Vt = vAeroUVW.Magnitude();
alpha = beta = adot = bdot = 0; alpha = beta = adot = bdot = 0;
double AeroU2 = vAeroUVW(eU)*vAeroUVW(eU); double AeroU2 = vAeroUVW(eU)*vAeroUVW(eU);
double AeroV2 = vAeroUVW(eV)*vAeroUVW(eV); double AeroV2 = vAeroUVW(eV)*vAeroUVW(eV);
double AeroW2 = vAeroUVW(eW)*vAeroUVW(eW); double AeroW2 = vAeroUVW(eW)*vAeroUVW(eW);
double mUW = AeroU2 + AeroW2; double mUW = AeroU2 + AeroW2;
double Vt2 = Vt*Vt; double Vt2 = mUW + AeroV2;
Vt = sqrt(Vt2);
if ( Vt > 0.001 ) { if ( Vt > 0.001 ) {
if (vAeroUVW(eW) != 0.0) if (vAeroUVW(eW) != 0.0)
@ -206,11 +206,9 @@ bool FGAuxiliary::Run(bool Holding)
if (abs(Mach) > 0.0) { if (abs(Mach) > 0.0) {
vcas = VcalibratedFromMach(Mach, in.Pressure, in.PressureSL, in.DensitySL); vcas = VcalibratedFromMach(Mach, in.Pressure, in.PressureSL, in.DensitySL);
veas = sqrt(2 * qbar / in.DensitySL); veas = sqrt(2 * qbar / in.DensitySL);
vtrue = 1116.43559 * Mach * sqrt(in.Temperature / 518.67);
}
else {
vcas = veas = vtrue = 0.0;
} }
else
vcas = veas = 0.0;
vPilotAccel.InitMatrix(); vPilotAccel.InitMatrix();
vNcg = in.vBodyAccel/in.SLGravity; vNcg = in.vBodyAccel/in.SLGravity;

View file

@ -131,9 +131,9 @@ public:
/** Returns equivalent airspeed in knots. */ /** Returns equivalent airspeed in knots. */
double GetVequivalentKTS(void) const { return veas*fpstokts; } double GetVequivalentKTS(void) const { return veas*fpstokts; }
/** Returns the true airspeed in feet per second. */ /** Returns the true airspeed in feet per second. */
double GetVtrueFPS() const { return vtrue; } double GetVtrueFPS() const { return Vt; }
/** Returns the true airspeed in knots. */ /** Returns the true airspeed in knots. */
double GetVtrueKTS() const { return vtrue * fpstokts; } double GetVtrueKTS() const { return Vt * fpstokts; }
/** Returns the total pressure. /** Returns the total pressure.
Total pressure is freestream total pressure for Total pressure is freestream total pressure for
@ -290,7 +290,7 @@ public:
} in; } in;
private: private:
double vcas, veas, vtrue; double vcas, veas;
double pt, tat, tatc; // Don't add a getter for pt! double pt, tat, tatc; // Don't add a getter for pt!
FGMatrix33 mTw2b; FGMatrix33 mTw2b;

View file

@ -503,9 +503,10 @@ bool FGFCS::Load(Element* document)
string sOnOffProperty = channel_element->GetAttributeValue("execute"); string sOnOffProperty = channel_element->GetAttributeValue("execute");
string sChannelName = channel_element->GetAttributeValue("name"); string sChannelName = channel_element->GetAttributeValue("name");
int Rate = 0;
if (!channel_element->GetAttributeValue("execrate").empty()) if (!channel_element->GetAttributeValue("execrate").empty())
Rate = channel_element->GetAttributeValueAsNumber("execrate"); ChannelRate = channel_element->GetAttributeValueAsNumber("execrate");
else
ChannelRate = 1;
if (sOnOffProperty.length() > 0) { if (sOnOffProperty.length() > 0) {
FGPropertyNode* OnOffPropertyNode = PropertyManager->GetNode(sOnOffProperty); FGPropertyNode* OnOffPropertyNode = PropertyManager->GetNode(sOnOffProperty);
@ -516,10 +517,10 @@ bool FGFCS::Load(Element* document)
<< "understood. The simulation will abort" << reset << endl; << "understood. The simulation will abort" << reset << endl;
throw("Bad system definition"); throw("Bad system definition");
} else } else
newChannel = new FGFCSChannel(this, sChannelName, Rate, newChannel = new FGFCSChannel(this, sChannelName, ChannelRate,
OnOffPropertyNode); OnOffPropertyNode);
} else } else
newChannel = new FGFCSChannel(this, sChannelName, Rate); newChannel = new FGFCSChannel(this, sChannelName, ChannelRate);
SystemChannels.push_back(newChannel); SystemChannels.push_back(newChannel);

View file

@ -92,7 +92,6 @@ public:
/// Adds a component to a channel /// Adds a component to a channel
void Add(FGFCSComponent* comp) { void Add(FGFCSComponent* comp) {
FCSComponents.push_back(comp); FCSComponents.push_back(comp);
comp->SetDtForFrameCount(ExecRate);
} }
/// Returns the number of components in the channel. /// Returns the number of components in the channel.
size_t GetNumComponents() {return FCSComponents.size();} size_t GetNumComponents() {return FCSComponents.size();}

View file

@ -63,7 +63,7 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
clipMinSign = clipMaxSign = 1.0; clipMinSign = clipMaxSign = 1.0;
IsOutput = clip = false; IsOutput = clip = false;
string input,init, clip_string; string input,init, clip_string;
dt = fcs->GetDt(); dt = fcs->GetChannelDeltaT();
PropertyManager = fcs->GetPropertyManager(); PropertyManager = fcs->GetPropertyManager();
if (element->GetName() == string("lag_filter")) { if (element->GetName() == string("lag_filter")) {
@ -250,13 +250,6 @@ void FGFCSComponent::SetOutput(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCSComponent::SetDtForFrameCount(int FrameCount)
{
dt = fcs->GetDt() * FrameCount;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCSComponent::Delay(void) void FGFCSComponent::Delay(void)
{ {
output_array[index] = Output; output_array[index] = Output;

View file

@ -94,7 +94,6 @@ public:
virtual bool Run(void) { return true; } virtual bool Run(void) { return true; }
virtual void SetOutput(void); virtual void SetOutput(void);
void SetDtForFrameCount(int FrameCount);
double GetOutput (void) const {return Output;} double GetOutput (void) const {return Output;}
std::string GetName(void) const {return Name;} std::string GetName(void) const {return Name;}
std::string GetType(void) const { return Type; } std::string GetType(void) const { return Type; }

View file

@ -135,6 +135,13 @@ bool FGSwitch::Run(void )
bool pass = false; bool pass = false;
double default_output=0.0; double default_output=0.0;
// To detect errors early, make sure all conditions and values can be
// evaluated in the first time step.
if (!initialized) {
initialized = true;
VerifyProperties();
}
for (unsigned int i=0; i<tests.size(); i++) { for (unsigned int i=0; i<tests.size(); i++) {
if (tests[i]->Default) { if (tests[i]->Default) {
default_output = tests[i]->GetValue(); default_output = tests[i]->GetValue();
@ -157,6 +164,18 @@ bool FGSwitch::Run(void )
return true; return true;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGSwitch::VerifyProperties(void)
{
for (unsigned int i=0; i<tests.size(); i++) {
if (!tests[i]->Default) {
tests[i]->condition->Evaluate();
}
tests[i]->GetValue();
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows: // The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print // unset: In this case (the default) JSBSim would only print

View file

@ -193,7 +193,9 @@ private:
}; };
std::vector <test*> tests; std::vector <test*> tests;
bool initialized = false;
void VerifyProperties(void);
void Debug(int from); void Debug(int from);
}; };
} }

View file

@ -363,12 +363,13 @@ double FGPropeller::GetPowerRequired(void)
FGColumnVector3 FGPropeller::GetPFactor() const FGColumnVector3 FGPropeller::GetPFactor() const
{ {
double px=0.0, py, pz; // These are moments in lbf per ft : the lever arm along Z generates a moment
// along the pitch direction.
double p_pitch = Thrust * Sense * (GetActingLocationZ() - GetLocationZ()) / 12.0;
// The lever arm along Y generates a moment along the yaw direction.
double p_yaw = Thrust * Sense * (GetActingLocationY() - GetLocationY()) / 12.0;
py = Thrust * Sense * (GetActingLocationY() - GetLocationY()) / 12.0; return FGColumnVector3(0.0, p_pitch, p_yaw);
pz = Thrust * Sense * (GetActingLocationZ() - GetLocationZ()) / 12.0;
return FGColumnVector3(px, py, pz);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%