1
0
Fork 0

Sync'ed with JSBSim v1.1.8

- Always set useDefault to false when calling SGPropertyNode::tie()
- Mass flows can now be specified using SI unit (kg/s)
- Add a new property propulsion/fuel_freeze to freeze fuel consumption.
- Add a new flag DONT_EXECUTE_RUN_IC that can be specified to FGFDMExec::ResetToInitialConditions. When specified, this flag avoid calling FGFDMExec::RunIC when executing FGFDMExec::ResetToInitialConditions.
- Fix a bug in <linear_actuator> that resulted in erroneous output values when the input was oscillating around the zero value.
- Add an assert that forbids to set the value of FGPropertyValue when the property was specified with a minus sign.
- Fix the compatibility with recent versions of MinGW64
- Fix ws2tcpip.h casing for compilation on case sensitive OS.
- Improve the templating of FGPropertyManager::Tie().
- Expand FGParameterValue exception message (James Turner)
- TurboProp: Filters out negative powers when the propeller is not rotating
This commit is contained in:
Bertrand Coconnier 2021-07-24 19:19:14 +02:00
parent 364be50967
commit 81313f4aa2
19 changed files with 124 additions and 282 deletions

View file

@ -604,7 +604,9 @@ void FGFDMExec::ResetToInitialConditions(int mode)
{
if (Constructing) return;
if (mode == 1) Output->SetStartNewOutput();
// mode flags
if (mode & START_NEW_OUTPUT) Output->SetStartNewOutput();
InitializeModels();
@ -613,7 +615,8 @@ void FGFDMExec::ResetToInitialConditions(int mode)
else
Setsim_time(0.0);
RunIC();
if (!(mode & DONT_EXECUTE_RUN_IC))
RunIC();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -460,10 +460,15 @@ public:
void Resume(void) {holding = false;}
/// Returns true if the simulation is Holding (i.e. simulation time is not moving).
bool Holding(void) {return holding;}
/// Mode flags for ResetToInitialConditions
static const int START_NEW_OUTPUT = 0x1;
static const int DONT_EXECUTE_RUN_IC = 0x2;
/** Resets the initial conditions object and prepares the simulation to run
again. If mode is set to 1 the output instances will take special actions
such as closing the current output file and open a new one with a
different name.
again. If the mode's first bit is set the output instances will take special actions
such as closing the current output file and open a new one with a different name.
If the second bit is set then RunIC() won't be executed, leaving it to the caller
to call RunIC(), e.g. in case the caller wants to set some other state like control
surface deflections which would've been reset.
@param mode Sets the reset mode.*/
void ResetToInitialConditions(int mode);
/// Sets the debug level.

View file

@ -52,12 +52,10 @@ namespace JSBSim {
void FGPropertyManager::Unbind(void)
{
vector<SGPropertyNode_ptr>::iterator it;
for(auto& prop: tied_properties)
prop->untie();
for (it = tied_properties.begin();it < tied_properties.end();it++)
(*it)->untie();
tied_properties.clear();
tied_properties.clear();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -73,7 +71,7 @@ string FGPropertyManager::mkPropertyName(string name, bool lowercase) {
else if( isspace(name[i]) )
name[i]='-';
}
return name;
}
@ -324,95 +322,4 @@ void FGPropertyManager::Untie (const string &name)
cerr << "Failed to untie property " << name << endl
<< "JSBSim is not the owner of this property." << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::Tie (const string &name, bool *pointer)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}
if (!property->tie(SGRawValuePointer<bool>(pointer), false))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::Tie (const string &name, int *pointer)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}
if (!property->tie(SGRawValuePointer<int>(pointer), false))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::Tie (const string &name, long *pointer)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}
if (!property->tie(SGRawValuePointer<long>(pointer), false))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::Tie (const string &name, float *pointer)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}
if (!property->tie(SGRawValuePointer<float>(pointer), false))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::Tie (const string &name, double *pointer)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}
if (!property->tie(SGRawValuePointer<double>(pointer), false))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}
} // namespace JSBSim

View file

@ -424,109 +424,31 @@ class FGPropertyManager
*/
void Unbind (void);
// Templates cause ambiguity here
/**
* Tie a property to an external bool variable.
* Tie a property to an external variable.
*
* The property's value will automatically mirror the variable's
* value, and vice-versa, until the property is untied.
*
* @param name The property name to tie (full path).
* @param pointer A pointer to the variable.
* @param useDefault true if any existing property value should be
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
void
Tie (const std::string &name, bool *pointer);
template <typename T> void
Tie (const std::string &name, T *pointer)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}
/**
* Tie a property to an external int variable.
*
* The property's value will automatically mirror the variable's
* value, and vice-versa, until the property is untied.
*
* @param name The property name to tie (full path).
* @param pointer A pointer to the variable.
* @param useDefault true if any existing property value should be
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
void
Tie (const std::string &name, int *pointer);
/**
* Tie a property to an external long variable.
*
* The property's value will automatically mirror the variable's
* value, and vice-versa, until the property is untied.
*
* @param name The property name to tie (full path).
* @param pointer A pointer to the variable.
* @param useDefault true if any existing property value should be
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
void
Tie (const std::string &name, long *pointer);
/**
* Tie a property to an external float variable.
*
* The property's value will automatically mirror the variable's
* value, and vice-versa, until the property is untied.
*
* @param name The property name to tie (full path).
* @param pointer A pointer to the variable.
* @param useDefault true if any existing property value should be
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
void
Tie (const std::string &name, float *pointer);
/**
* Tie a property to an external double variable.
*
* The property's value will automatically mirror the variable's
* value, and vice-versa, until the property is untied.
*
* @param name The property name to tie (full path).
* @param pointer A pointer to the variable.
* @param useDefault true if any existing property value should be
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
void
Tie (const std::string &name, double *pointer);
//============================================================================
//
// All of the following functions *must* be inlined, otherwise linker
// errors will result
//
//============================================================================
/* template <class V> void
Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0,
bool useDefault = true);
template <class V> void
Tie (const std::string &name, int index, V (*getter)(int),
void (*setter)(int, V) = 0, bool useDefault = true);
template <class T, class V> void
Tie (const std::string &name, T * obj, V (T::*getter)() const,
void (T::*setter)(V) = 0, bool useDefault = true);
template <class T, class V> void
Tie (const std::string &name, T * obj, int index,
V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
bool useDefault = true); */
if (!property->tie(SGRawValuePointer<T>(pointer), false))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
}
}
/**
* Tie a property to a pair of simple functions.
@ -542,8 +464,8 @@ class FGPropertyManager
* @param setter The setter function, or 0 if the value is unmodifiable.
*/
template <class V> inline void
Tie (const std::string &name, V (*getter)(), void (*setter)(V) = nullptr)
template <typename T> void
Tie (const std::string &name, T (*getter)(), void (*setter)(T) = nullptr)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
@ -551,17 +473,17 @@ class FGPropertyManager
return;
}
if (!property->tie(SGRawValueFunctions<V>(getter, setter), false))
std::cerr << "Failed to tie property " << name << " to functions" << std::endl;
if (!property->tie(SGRawValueFunctions<T>(getter, setter), false))
std::cerr << "Failed to tie property " << name << " to functions"
<< std::endl;
else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
if (!getter) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
}
}
/**
* Tie a property to a pair of indexed functions.
*
@ -577,8 +499,9 @@ class FGPropertyManager
* @param getter The getter function, or 0 if the value is unreadable.
* @param setter The setter function, or 0 if the value is unmodifiable.
*/
template <class V> inline void Tie (const std::string &name, int index, V (*getter)(int),
void (*setter)(int, V) = nullptr)
template <typename T> void
Tie (const std::string &name, int index, T (*getter)(int),
void (*setter)(int, T) = nullptr)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
@ -586,17 +509,18 @@ class FGPropertyManager
return;
}
if (!property->tie(SGRawValueFunctionsIndexed<V>(index, getter, setter), false))
std::cerr << "Failed to tie property " << name << " to indexed functions" << std::endl;
if (!property->tie(SGRawValueFunctionsIndexed<T>(index, getter, setter),
false))
std::cerr << "Failed to tie property " << name << " to indexed functions"
<< std::endl;
else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
if (!getter) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
}
}
/**
* Tie a property to a pair of object methods.
*
@ -613,9 +537,9 @@ class FGPropertyManager
* @param setter The object's setter method, or 0 if the value is
* unmodifiable.
*/
template <class T, class V> inline void
template <class T, class V> void
Tie (const std::string &name, T * obj, V (T::*getter)() const,
void (T::*setter)(V) = nullptr)
void (T::*setter)(V) = nullptr)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
@ -624,10 +548,11 @@ class FGPropertyManager
}
if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), false))
std::cerr << "Failed to tie property " << name << " to object methods" << std::endl;
std::cerr << "Failed to tie property " << name << " to object methods"
<< std::endl;
else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
if (!getter) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
}
@ -649,9 +574,9 @@ class FGPropertyManager
* @param getter The getter method, or 0 if the value is unreadable.
* @param setter The setter method, or 0 if the value is unmodifiable.
*/
template <class T, class V> inline void
template <class T, class V> void
Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
void (T::*setter)(int, V) = nullptr)
void (T::*setter)(int, V) = nullptr)
{
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
@ -659,15 +584,17 @@ class FGPropertyManager
return;
}
if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), false))
std::cerr << "Failed to tie property " << name << " to indexed object methods" << std::endl;
if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter),
false))
std::cerr << "Failed to tie property " << name
<< " to indexed object methods" << std::endl;
else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
if (!getter) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
}
}
}
template <class T> simgear::PropertyObject<T>
CreatePropertyObject(const std::string &path)

View file

@ -156,6 +156,7 @@ Element::Element(const string& nm)
convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"];
// Mass flow
convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"];
convert["KG/SEC"]["LBS/SEC"] = convert["KG"]["LBS"];
convert ["N/SEC"]["LBS/SEC"] = 0.224808943;
convert ["LBS/SEC"]["N/SEC"] = 1.0/convert ["N/SEC"]["LBS/SEC"];
// Fuel Consumption

View file

@ -39,7 +39,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <WS2tcpip.h>
#include <ws2tcpip.h>
#elif defined(__OpenBSD__)
#include <sys/types.h>
#include <sys/socket.h>
@ -156,7 +156,7 @@ FGfdmSocket::FGfdmSocket(int port, int protocol)
connected = false;
Protocol = (ProtocolType)protocol;
string ProtocolName;
#if defined(_MSC_VER) || defined(__MINGW32__)
if (!LoadWinSockDLL(debug_lvl)) return;
#endif
@ -179,7 +179,7 @@ FGfdmSocket::FGfdmSocket(int port, int protocol)
if (debug_lvl > 0)
cout << "Creating input " << ProtocolName << " socket on port " << port
<< endl;
if (sckt != -1) {
memset(&scktName, 0, sizeof(struct sockaddr_in));
scktName.sin_family = AF_INET;
@ -275,15 +275,15 @@ string FGfdmSocket::Receive(void)
}
#endif
}
// this is for FGUDPInputSocket
if (sckt >= 0 && Protocol == ptUDP) {
struct sockaddr addr;
socklen_t fromlen = sizeof addr;
num_chars = recvfrom(sckt, buf, sizeof buf, 0, (struct sockaddr*)&addr, &fromlen);
if (num_chars != -1) data.append(buf, num_chars);
if (num_chars != -1) data.append(buf, num_chars);
}
return data;
}

View file

@ -826,7 +826,7 @@ protected:
void CheckMinArguments(Element* el, unsigned int _min);
void CheckMaxArguments(Element* el, unsigned int _max);
void CheckOddOrEvenArguments(Element* el, OddEven odd_even);
std::string CreateOutputNode(Element* el, const string& Prefix);
std::string CreateOutputNode(Element* el, const std::string& Prefix);
private:
std::string Name;

View file

@ -160,7 +160,7 @@ FGColumnVector3 FGMatrix33::GetEuler(void) const
{
FGColumnVector3 mEulerAngles;
bool GimbalLock = false;
if (data[6] <= -1.0) {
mEulerAngles(2) = 0.5*M_PI;
GimbalLock = true;
@ -176,7 +176,7 @@ FGColumnVector3 FGMatrix33::GetEuler(void) const
mEulerAngles(1) = atan2(-data[5], data[4]);
else
mEulerAngles(1) = atan2(data[7], data[8]);
if (GimbalLock)
mEulerAngles(3) = 0.0;
else {
@ -436,9 +436,9 @@ FGMatrix33 FGMatrix33::operator/(const double scalar) const
Quot.data[2] = data[2] * tmp;
Quot.data[5] = data[5] * tmp;
Quot.data[8] = data[8] * tmp;
} else {
throw MatrixException{"Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)"};
}
} else
throw MatrixException{"Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)"};
return Quot;
}
@ -457,9 +457,9 @@ FGMatrix33& FGMatrix33::operator/=(const double scalar)
data[2] *= tmp;
data[5] *= tmp;
data[8] *= tmp;
} else {
throw MatrixException{"Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)"};
}
} else
throw MatrixException{"Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)"};
return *this;
}

View file

@ -65,12 +65,10 @@ CLASS DOCUMENTATION
DECLARATION: MatrixException
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
// changed by James to inherit std::runtime_error, so that if this
// gets thrown, we can actually catch it.
class MatrixException : public std::runtime_error
{
public:
MatrixException(const std::string& msg) : std::runtime_error{msg} { }
MatrixException(const std::string& msg) : std::runtime_error{msg} { }
};
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -71,7 +71,7 @@ public:
<< "The element <" << el->GetName()
<< "> must either contain a value number or a property name."
<< endl;
throw invalid_argument("Illegal argument");
throw invalid_argument("FGParameterValue: Illegal argument defining: " + el->GetName());
}
Construct(value, pm);

View file

@ -29,8 +29,9 @@ Purpose: Stores property values
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <assert.h>
#include "FGPropertyValue.h"
#include "input_output/FGPropertyManager.h"
namespace JSBSim {
@ -80,6 +81,9 @@ double FGPropertyValue::GetValue(void) const
void FGPropertyValue::SetValue(double value)
{
// SetValue() ignores the Sign flag. So make sure it is never called with a
// negative sign.
assert(Sign == 1);
GetNode()->setDoubleValue(value);
}

View file

@ -241,20 +241,19 @@ string FGBuoyantForces::GetBuoyancyValues(const string& delimeter)
void FGBuoyantForces::bind(void)
{
typedef double (FGBuoyantForces::*PGF)(int) const;
typedef void (FGBuoyantForces::*PSF)(int, double);
using PSF = void (FGBuoyantForces::*)(int, double);
PropertyManager->Tie("moments/l-buoyancy-lbsft", this, eL,
(PGF)&FGBuoyantForces::GetMoments, (PSF)nullptr);
&FGBuoyantForces::GetMoments, (PSF)nullptr);
PropertyManager->Tie("moments/m-buoyancy-lbsft", this, eM,
(PGF)&FGBuoyantForces::GetMoments, (PSF)nullptr);
&FGBuoyantForces::GetMoments, (PSF)nullptr);
PropertyManager->Tie("moments/n-buoyancy-lbsft", this, eN,
(PGF)&FGBuoyantForces::GetMoments, (PSF)nullptr);
&FGBuoyantForces::GetMoments, (PSF)nullptr);
PropertyManager->Tie("forces/fbx-buoyancy-lbs", this, eX,
(PGF)&FGBuoyantForces::GetForces, (PSF)nullptr);
&FGBuoyantForces::GetForces, (PSF)nullptr);
PropertyManager->Tie("forces/fby-buoyancy-lbs", this, eY,
(PGF)&FGBuoyantForces::GetForces, (PSF)nullptr);
&FGBuoyantForces::GetForces, (PSF)nullptr);
PropertyManager->Tie("forces/fbz-buoyancy-lbs", this, eZ,
(PGF)&FGBuoyantForces::GetForces, (PSF)nullptr);
&FGBuoyantForces::GetForces, (PSF)nullptr);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -195,7 +195,7 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, unsigned int num,
property_name = base_property_name + "/max_volume-ft3";
PropertyManager->Tie( property_name.c_str(), &MaxVolume);
PropertyManager->GetNode()->SetWritable( property_name);
PropertyManager->GetNode()->SetWritable( property_name, false );
property_name = base_property_name + "/temp-R";
PropertyManager->Tie( property_name.c_str(), &Temperature);
property_name = base_property_name + "/pressure-psf";
@ -623,7 +623,7 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, unsigned int num,
property_name = base_property_name + "/max_volume-ft3";
PropertyManager->Tie( property_name, &MaxVolume);
PropertyManager->GetNode()->SetWritable( property_name);
PropertyManager->GetNode()->SetWritable( property_name, false );
property_name = base_property_name + "/temp-R";
PropertyManager->Tie( property_name, &Temperature);

View file

@ -802,6 +802,7 @@ void FGPropulsion::bind(void)
{
typedef double (FGPropulsion::*PMF)(int) const;
typedef int (FGPropulsion::*iPMF)(void) const;
typedef bool (FGPropulsion::*bPMF)(void) const;
IsBound = true;
PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning);
@ -827,6 +828,7 @@ void FGPropulsion::bind(void)
TotalOxidizerQuantity = PropertyManager->CreatePropertyObject<double>("propulsion/total-oxidizer-lbs");
refuel = PropertyManager->CreatePropertyObject<bool>("propulsion/refuel");
dump = PropertyManager->CreatePropertyObject<bool>("propulsion/fuel_dump");
PropertyManager->Tie("propulsion/fuel_freeze", this, (bPMF)nullptr, &FGPropulsion::SetFuelFreeze);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -1,5 +1,5 @@
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
*
Module: FGLinearActuator.cpp
Author: Adriano Bassignana
Date started: 2019-01-03
@ -43,11 +43,11 @@ INCLUDES
using namespace std;
namespace JSBSim {
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGLinearActuator::FGLinearActuator(FGFCS* fcs, Element* element)
: FGFCSComponent(fcs, element)
{
@ -141,7 +141,7 @@ FGLinearActuator::FGLinearActuator(FGFCS* fcs, Element* element)
Debug(0);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGLinearActuator::~FGLinearActuator()
@ -184,16 +184,11 @@ bool FGLinearActuator::Run(void )
}
if ((versus == 0) || (versus == direction)) {
inputMem = Input;
if (direction != 0) {
if (abs(inputDelta) >= (module*rate)) {
if (direction > 0) {
countSpin++;
direction = 0;
} else if (direction < 0) {
countSpin--;
direction = 0;
}
}
if (abs(inputDelta) >= (module*rate)) {
if (inputDelta < 0)
countSpin++;
else
countSpin--;
}
} else if ((versus != 0) && (direction != 0) && (versus != direction)) {
inputLast += inputDelta;
@ -207,7 +202,7 @@ bool FGLinearActuator::Run(void )
}
if (lag > 0.0) {
double input = Output;
double input = Output;
Output = ca * (input + previousLagInput) + previousLagOutput * cb;
previousLagInput = input;
previousLagOutput = Output;

View file

@ -75,7 +75,7 @@ FGMagnetometer::FGMagnetometer(FGFCS* fcs, Element* element)
time_t rawtime;
time( &rawtime );
struct tm ptm;
#ifdef _MSC_VER
#if defined(_MSC_VER) || defined(__MINGW32__)
gmtime_s(&ptm, &rawtime);
#else
gmtime_r(&rawtime, &ptm);

View file

@ -90,12 +90,12 @@ void FGElectric::Calculate(void)
if (Thruster->GetType() == FGThruster::ttPropeller) {
((FGPropeller*)Thruster)->SetAdvance(in.PropAdvance[EngineNumber]);
((FGPropeller*)Thruster)->SetFeather(in.PropFeather[EngineNumber]);
}
}
RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
HP = PowerWatts * in.ThrottlePos[EngineNumber] / hptowatts;
LoadThrusterInputs();
// Filters out negative powers when the propeller is not rotating.
double power = HP * hptoftlbssec;

View file

@ -124,7 +124,7 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Input
bTakeoffBoost = false;
TakeoffBoost = 0.0; // Default to no extra takeoff-boost
BoostLossFactor = 0.0; // Default to free boost
int i;
for (i=0; i<FG_MAX_BOOST_SPEEDS; i++) {
RatedBoost[i] = 0.0;
@ -142,7 +142,7 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Input
// Read inputs from engine data file where present.
if (el->FindElement("minmp"))
if (el->FindElement("minmp"))
MinManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("minmp","INHG");
if (el->FindElement("maxmp"))
MaxManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("maxmp","INHG");
@ -309,7 +309,7 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Input
Z_airbox = (standard_pressure *Ze / maxMAP) - Ze; // impedence of airbox
}
// Constant for Throttle impedence
Z_throttle=(PeakMeanPistonSpeed_fps/((IdleRPM * Stroke) / 360))*(standard_pressure/minMAP - 1) - Z_airbox;
Z_throttle=(PeakMeanPistonSpeed_fps/((IdleRPM * Stroke) / 360))*(standard_pressure/minMAP - 1) - Z_airbox;
// Z_throttle=(MaxRPM/IdleRPM )*(standard_pressure/minMAP+2); // Constant for Throttle impedence
// Default tables if not provided in the configuration file
@ -518,9 +518,7 @@ void FGPiston::Calculate(void)
}
LoadThrusterInputs();
// Filters out negative powers.
// TODO: static_friction_HP should not be taken into account while the engine
// is not started.
// Filters out negative powers when the propeller is not rotating.
double power = HP * hptoftlbssec;
if (RPM <= 0.1) power = max(power, 0.0);
Thruster->Calculate(power);
@ -533,7 +531,7 @@ void FGPiston::Calculate(void)
double FGPiston::CalcFuelNeed(void)
{
FuelExpended = FuelFlowRate * in.TotalDeltaT;
if (!Starved) FuelUsedLbs += FuelExpended;
if (!Starved) FuelUsedLbs += FuelExpended;
return FuelExpended;
}
@ -594,7 +592,7 @@ void FGPiston::doEngineStartup(void)
if ( Running ) {
if (!spark || !fuel) Running = false;
if (RPM < IdleRPM*0.8 ) Running = false;
} else { // !Running
} else { // !Running
if ( spark && fuel) { // start the engine if revs high enough
if (RPM > IdleRPM*0.8) // This allows us to in-air start
Running = true; // when windmilling
@ -705,7 +703,7 @@ void FGPiston::doMAP(void)
} else {
BoostLossHP = 0;
}
// And set the value in American units as well
ManifoldPressure_inHg = MAP / inhgtopa;
}
@ -800,14 +798,14 @@ void FGPiston::doEnginePower(void)
} else {
// Power output when the engine is not running
double torque, k_torque, rpm; // Convienience term for use in the calculations
rpm = RPM < 1.0 ? 1.0 : RPM;
if (Cranking) {
if(RPM<StarterRPM) k_torque = 1.0-RPM/(StarterRPM);
else k_torque = 0;
torque = StarterTorque*k_torque*StarterGain;
IndicatedHorsePower = torque * rpm / 5252;
}
}
}
// Constant is (1/2) * 60 * 745.7

View file

@ -291,7 +291,10 @@ void FGTurboProp::Calculate(void)
}
LoadThrusterInputs();
Thruster->Calculate(HP * hptoftlbssec);
// Filters out negative powers when the propeller is not rotating.
double power = HP * hptoftlbssec;
if (RPM <= 0.1) power = max(power, 0.0);
Thruster->Calculate(power);
RunPostFunctions();
}