Sync'ed with JSBSim v1.1.11
- Output files are now written in the current directory instead of being written in the aircraft folder (issue GH#337) - A new exception TrimFailureException is now thrown when trim fails. This eases the detection of the trim failure (previously the exception message needed to be checked). - An exception is thrown when a latitude higher than 90 degrees is supplied to a <waypoint> control element (PR GH#536) - Fix the sign of the initial NED climb rate (property ic/gamma-deg) (PR #545) - JSBSim now checks malformed data in <table> elements. Anything different than numbers and spaces/tabs will be rejected. - Usage of <location> and <orientation> in engines is now officially dropped (PR #559, #561 and #563). These elements were deprecated long ago in favor of the corresponding elements <location> and <orientation> in thrusters. Therefore the code removed is no-op. - The computation of the initial rotation rates has been fixed (Issue GH#553). Previously, the rotation rates could be initialized with extremely high values when the vehicle was spawned over the Poles. And for a given set of initial conditions, the initial rotation rates could have different values depending on the initial latitude at which the vehicle was initialized. This now fixed. - The precision with which values are transmitted thru a socket can now be set via the attribute precision such as <output precision="8"> (PR GH#579) - Added 2 new methods to FGFDMExec: SetOutputPath and GetOutputPath to specify the path to which the output files will be written. - All JSBSim exceptions now inherit from JSBSim::BaseException. There still exist std::* exceptions thrown by JSBSim. Cleanup is still in progress. - JSBSim no longer calls exit() or abort(). Exceptions are thrown instead. This gives the calling application an opportunity to gracefully recover.
This commit is contained in:
parent
06063ed82a
commit
60ce826874
34 changed files with 424 additions and 364 deletions
src/FDM/JSBSim
|
@ -144,9 +144,14 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr)
|
|||
// this is to catch errors in binding member functions to the property tree.
|
||||
try {
|
||||
Allocate();
|
||||
} catch (const string& msg ) {
|
||||
cout << "Caught error: " << msg << endl;
|
||||
exit(1);
|
||||
}
|
||||
catch (const string& msg) {
|
||||
cerr << endl << "Caught error: " << msg << endl;
|
||||
throw;
|
||||
}
|
||||
catch (const BaseException& e) {
|
||||
cout << endl << "Caught error: " << e.what() << endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
trim_status = false;
|
||||
|
@ -1093,8 +1098,10 @@ bool FGFDMExec::ReadChild(Element* el)
|
|||
if (location) {
|
||||
child->Loc = location->FindElementTripletConvertTo("IN");
|
||||
} else {
|
||||
cerr << endl << highint << fgred << " No location was found for this child object!" << reset << endl;
|
||||
exit(-1);
|
||||
const string s(" No location was found for this child object!");
|
||||
cerr << el->ReadFrom() << endl << highint << fgred
|
||||
<< s << reset << endl;
|
||||
throw BaseException(s);
|
||||
}
|
||||
|
||||
Element* orientation = el->FindElement("orient");
|
||||
|
@ -1165,7 +1172,7 @@ void FGFDMExec::DoTrim(int mode)
|
|||
trim.Report();
|
||||
|
||||
if (!success)
|
||||
throw("Trim Failed");
|
||||
throw TrimFailureException("Trim Failed");
|
||||
|
||||
trim_completed = 1;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,11 @@ class FGPropulsion;
|
|||
class FGMassBalance;
|
||||
class FGTrim;
|
||||
|
||||
class TrimFailureException : public BaseException {
|
||||
public:
|
||||
TrimFailureException(const std::string& msg) : BaseException(msg) {}
|
||||
};
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
CLASS DOCUMENTATION
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
@ -283,44 +288,65 @@ public:
|
|||
@return true if successful*/
|
||||
bool LoadModel(const std::string& model, bool addModelToPath = true);
|
||||
|
||||
/** Loads a script
|
||||
/** Load a script
|
||||
@param Script The full path name and file name for the script to be loaded.
|
||||
@param deltaT The simulation integration step size, if given. If no value is supplied
|
||||
then 0.0 is used and the value is expected to be supplied in
|
||||
the script file itself.
|
||||
@param initfile The initialization file that will override the initialization file
|
||||
specified in the script file. If no file name is given on the command line,
|
||||
the file specified in the script will be used. If an initialization file
|
||||
is not given in either place, an error will result.
|
||||
@param deltaT The simulation integration step size, if given. If no value
|
||||
is supplied then 0.0 is used and the value is expected to be
|
||||
supplied in the script file itself.
|
||||
@param initfile The initialization file that will override the
|
||||
initialization file specified in the script file. If no
|
||||
file name is given on the command line, the file specified
|
||||
in the script will be used. If an initialization file is
|
||||
not given in either place, an error will result.
|
||||
@return true if successfully loads; false otherwise. */
|
||||
bool LoadScript(const SGPath& Script, double deltaT=0.0,
|
||||
const SGPath& initfile=SGPath());
|
||||
|
||||
/** Sets the path to the engine config file directories.
|
||||
@param path path to the directory under which engine config
|
||||
files are kept, for instance "engine" */
|
||||
/** Set the path to the engine config file directories.
|
||||
Relative paths are taken from the root directory.
|
||||
@param path path to the directory under which engine config files are
|
||||
kept, for instance "engine".
|
||||
@see SetRootDir
|
||||
@see GetEnginePath */
|
||||
bool SetEnginePath(const SGPath& path) {
|
||||
EnginePath = GetFullPath(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Sets the path to the aircraft config file directories.
|
||||
@param path path to the aircraft directory. For instance:
|
||||
"aircraft". Under aircraft, then, would be directories for various
|
||||
modeled aircraft such as C172/, x15/, etc. */
|
||||
/** Set the path to the aircraft config file directories.
|
||||
Under this path, then, would be directories for various modeled aircraft
|
||||
such as C172/, x15/, etc.
|
||||
Relative paths are taken from the root directory.
|
||||
@param path path to the aircraft directory, for instance "aircraft".
|
||||
@see SetRootDir
|
||||
@see GetAircraftPath */
|
||||
bool SetAircraftPath(const SGPath& path) {
|
||||
AircraftPath = GetFullPath(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Sets the path to the systems config file directories.
|
||||
@param path path to the directory under which systems config
|
||||
files are kept, for instance "systems" */
|
||||
/** Set the path to the systems config file directories.
|
||||
Relative paths are taken from the root directory.
|
||||
@param path path to the directory under which systems config files are
|
||||
kept, for instance "systems"
|
||||
@see SetRootDir
|
||||
@see GetSystemsPath */
|
||||
bool SetSystemsPath(const SGPath& path) {
|
||||
SystemsPath = GetFullPath(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Set the directory where the output files will be written.
|
||||
Relative paths are taken from the root directory.
|
||||
@param path path to the directory under which the output files will be
|
||||
written.
|
||||
@see SetRootDir
|
||||
@see GetOutputPath */
|
||||
bool SetOutputPath(const SGPath& path) {
|
||||
OutputPath = GetFullPath(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @name Top-level executive State and Model retrieval mechanism
|
||||
///@{
|
||||
/// Returns the FGAtmosphere pointer.
|
||||
|
@ -371,6 +397,8 @@ public:
|
|||
const SGPath& GetSystemsPath(void) { return SystemsPath; }
|
||||
/// Retrieves the full aircraft path name.
|
||||
const SGPath& GetFullAircraftPath(void) { return FullAircraftPath; }
|
||||
/// Retrieves the path to the output files.
|
||||
const SGPath& GetOutputPath(void) { return OutputPath; }
|
||||
|
||||
/** Retrieves the value of a property.
|
||||
@param property the name of the property
|
||||
|
@ -535,13 +563,23 @@ public:
|
|||
@param delta_t the time step in seconds. */
|
||||
void Setdt(double delta_t) { dT = delta_t; }
|
||||
|
||||
/** Sets the root directory where JSBSim starts looking for its system
|
||||
directories.
|
||||
@param rootDir the string containing the root directory. */
|
||||
/** Set the root directory that is used to obtain absolute paths from
|
||||
relative paths.
|
||||
Aircraft, engine, systems and output paths are not updated by this
|
||||
method. You must call each methods (SetAircraftPath(), SetEnginePath(),
|
||||
etc.) individually if you need to update these paths as well.
|
||||
@param rootDir the path to the root directory.
|
||||
@see GetRootDir
|
||||
@see SetAircraftPath
|
||||
@see SetEnginePath
|
||||
@see SetSystemsPath
|
||||
@see SetOutputPath
|
||||
*/
|
||||
void SetRootDir(const SGPath& rootDir) {RootDir = rootDir;}
|
||||
|
||||
/** Retrieves the Root Directory.
|
||||
@return the string representing the root (base) JSBSim directory. */
|
||||
/** Retrieve the Root Directory.
|
||||
@return the path to the root (base) JSBSim directory.
|
||||
@see SetRootDir */
|
||||
const SGPath& GetRootDir(void) const {return RootDir;}
|
||||
|
||||
/** Increments the simulation time if not in Holding mode. The Frame counter
|
||||
|
@ -600,6 +638,7 @@ private:
|
|||
SGPath FullAircraftPath;
|
||||
SGPath EnginePath;
|
||||
SGPath SystemsPath;
|
||||
SGPath OutputPath;
|
||||
std::string CFGVersion;
|
||||
std::string Release;
|
||||
SGPath RootDir;
|
||||
|
|
|
@ -42,6 +42,7 @@ INCLUDES
|
|||
#include <queue>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "input_output/string_utilities.h"
|
||||
|
||||
|
@ -55,6 +56,11 @@ FORWARD DECLARATIONS
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
class BaseException : public std::runtime_error {
|
||||
public:
|
||||
BaseException(const std::string& msg) : std::runtime_error(msg) {}
|
||||
};
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
CLASS DOCUMENTATION
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
|
|
@ -1013,13 +1013,17 @@ bool FGInitialCondition::Load(const SGPath& rstfile, bool useStoredPath)
|
|||
|
||||
// Make sure that the document is valid
|
||||
if (!document) {
|
||||
cerr << "File: " << init_file_name << " could not be read." << endl;
|
||||
exit(-1);
|
||||
stringstream s;
|
||||
s << "File: " << init_file_name << " could not be read.";
|
||||
cerr << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
|
||||
if (document->GetName() != string("initialize")) {
|
||||
cerr << "File: " << init_file_name << " is not a reset file." << endl;
|
||||
exit(-1);
|
||||
stringstream s;
|
||||
s << "File: " << init_file_name << " is not a reset file.";
|
||||
cerr << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
|
||||
double version = HUGE_VAL;
|
||||
|
@ -1031,8 +1035,9 @@ bool FGInitialCondition::Load(const SGPath& rstfile, bool useStoredPath)
|
|||
if (version == HUGE_VAL) {
|
||||
result = Load_v1(document); // Default to the old version
|
||||
} else if (version >= 3.0) {
|
||||
cerr << "Only initialization file formats 1 and 2 are currently supported" << endl;
|
||||
exit (-1);
|
||||
const string s("Only initialization file formats 1 and 2 are currently supported");
|
||||
cerr << document->ReadFrom() << endl << s << endl;
|
||||
throw BaseException(s);
|
||||
} else if (version >= 2.0) {
|
||||
result = Load_v2(document);
|
||||
} else if (version >= 1.0) {
|
||||
|
@ -1182,15 +1187,7 @@ bool FGInitialCondition::Load_v1(Element* document)
|
|||
if (document->FindElement("trim"))
|
||||
SetTrimRequest(document->FindElementValue("trim"));
|
||||
|
||||
// Refer to Stevens and Lewis, 1.5-14a, pg. 49.
|
||||
// This is the rotation rate of the "Local" frame, expressed in the local frame.
|
||||
const FGMatrix33& Tl2b = orientation.GetT();
|
||||
double radInv = 1.0 / position.GetRadius();
|
||||
FGColumnVector3 vOmegaLocal = {radInv*vUVW_NED(eEast),
|
||||
-radInv*vUVW_NED(eNorth),
|
||||
-radInv*vUVW_NED(eEast)*tan(position.GetLatitude())};
|
||||
|
||||
vPQR_body = Tl2b * vOmegaLocal;
|
||||
vPQR_body.InitMatrix();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1403,19 +1400,12 @@ bool FGInitialCondition::Load_v2(Element* document)
|
|||
// - Body
|
||||
|
||||
Element* attrate_el = document->FindElement("attitude_rate");
|
||||
const FGMatrix33& Tl2b = orientation.GetT();
|
||||
|
||||
// Refer to Stevens and Lewis, 1.5-14a, pg. 49.
|
||||
// This is the rotation rate of the "Local" frame, expressed in the local frame.
|
||||
double radInv = 1.0 / position.GetRadius();
|
||||
FGColumnVector3 vOmegaLocal = { radInv*vUVW_NED(eEast),
|
||||
-radInv*vUVW_NED(eNorth),
|
||||
-radInv*vUVW_NED(eEast)*tan(position.GetLatitude())};
|
||||
|
||||
if (attrate_el) {
|
||||
|
||||
string frame = attrate_el->GetAttributeValue("frame");
|
||||
frame = to_lower(frame);
|
||||
const FGMatrix33& Tl2b = orientation.GetT();
|
||||
FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo("RAD/SEC");
|
||||
|
||||
if (frame == "eci") {
|
||||
|
@ -1424,6 +1414,12 @@ bool FGInitialCondition::Load_v2(Element* document)
|
|||
} else if (frame == "ecef") {
|
||||
vPQR_body = Tl2b * position.GetTec2l() * vAttRate;
|
||||
} else if (frame == "local") {
|
||||
// Refer to Stevens and Lewis, 1.5-14a, pg. 49.
|
||||
// This is the rotation rate of the "Local" frame, expressed in the local frame.
|
||||
double radInv = 1.0 / position.GetRadius();
|
||||
FGColumnVector3 vOmegaLocal = {radInv*vUVW_NED(eEast),
|
||||
-radInv*vUVW_NED(eNorth),
|
||||
-radInv*vUVW_NED(eEast)*tan(position.GetLatitude())};
|
||||
vPQR_body = Tl2b * (vAttRate + vOmegaLocal);
|
||||
} else if (frame == "body") {
|
||||
vPQR_body = vAttRate;
|
||||
|
@ -1434,11 +1430,11 @@ bool FGInitialCondition::Load_v2(Element* document)
|
|||
result = false;
|
||||
|
||||
} else if (frame.empty()) {
|
||||
vPQR_body = Tl2b * vOmegaLocal;
|
||||
vPQR_body.InitMatrix();
|
||||
}
|
||||
|
||||
} else { // Body frame attitude rate assumed 0 relative to local.
|
||||
vPQR_body = Tl2b * vOmegaLocal;
|
||||
vPQR_body.InitMatrix();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -519,7 +519,7 @@ public:
|
|||
{
|
||||
const FGMatrix33& Tb2l = orientation.GetTInv();
|
||||
FGColumnVector3 _vt_NED = Tb2l * Tw2b * FGColumnVector3(vt, 0., 0.);
|
||||
return _vt_NED(eW);
|
||||
return -_vt_NED(eW);
|
||||
}
|
||||
|
||||
/** Gets the initial body velocity
|
||||
|
|
|
@ -214,7 +214,7 @@ void FGOutputFG::SocketDataFill(FGNetFDM* net)
|
|||
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->num_engines = min((unsigned) 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++) {
|
||||
FGEngine* engine = Propulsion->GetEngine(i);
|
||||
|
@ -254,7 +254,7 @@ void FGOutputFG::SocketDataFill(FGNetFDM* net)
|
|||
}
|
||||
}
|
||||
|
||||
net->num_tanks = min((unsigned) 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++) {
|
||||
net->fuel_quantity[i] = (float)(((FGTank *)Propulsion->GetTank(i))->GetContents());
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
the next call to SetStartNewOutput().
|
||||
@param name new name */
|
||||
void SetOutputName(const std::string& fname) override {
|
||||
Name = (FDMExec->GetRootDir()/fname).utf8Str();
|
||||
Name = (FDMExec->GetOutputPath()/fname).utf8Str();
|
||||
runID_postfix = -1;
|
||||
Filename = SGPath();
|
||||
}
|
||||
|
|
|
@ -121,6 +121,12 @@ bool FGOutputSocket::Load(Element* el)
|
|||
el->GetAttributeValue("protocol") + "/" +
|
||||
el->GetAttributeValue("port"));
|
||||
|
||||
// Check if output precision for doubles has been specified, default to 7 if not
|
||||
if(el->HasAttribute("precision"))
|
||||
precision = (int)el->GetAttributeValueAsNumber("precision");
|
||||
else
|
||||
precision = 7;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -130,7 +136,7 @@ bool FGOutputSocket::InitModel(void)
|
|||
{
|
||||
if (FGOutputType::InitModel()) {
|
||||
delete socket;
|
||||
socket = new FGfdmSocket(SockName, SockPort, SockProtocol);
|
||||
socket = new FGfdmSocket(SockName, SockPort, SockProtocol, precision);
|
||||
|
||||
if (socket == 0) return false;
|
||||
if (!socket->GetConnectStatus()) return false;
|
||||
|
|
|
@ -108,6 +108,7 @@ protected:
|
|||
unsigned int SockPort;
|
||||
FGfdmSocket::ProtocolType SockProtocol;
|
||||
FGfdmSocket* socket;
|
||||
int precision;
|
||||
};
|
||||
}
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
INCLUDES
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "FGPropertyManager.h"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -110,13 +111,6 @@ bool FGPropertyNode::HasNode (const string &path)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
string FGPropertyNode::GetName( void ) const
|
||||
{
|
||||
return getNameString();
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
string FGPropertyNode::GetPrintableName( void ) const
|
||||
{
|
||||
string temp_string(getNameString());
|
||||
|
@ -309,8 +303,18 @@ void FGPropertyManager::Untie (const string &name)
|
|||
return;
|
||||
}
|
||||
|
||||
vector <SGPropertyNode_ptr>::iterator it;
|
||||
for (it = tied_properties.begin(); it != tied_properties.end(); ++it) {
|
||||
Untie(property);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGPropertyManager::Untie(SGPropertyNode *property)
|
||||
{
|
||||
const string& name = property->getNameString();
|
||||
|
||||
assert(property->isTied());
|
||||
|
||||
for (auto it = tied_properties.begin(); it != tied_properties.end(); ++it) {
|
||||
if (*it == property) {
|
||||
property->untie();
|
||||
tied_properties.erase(it);
|
||||
|
|
|
@ -97,7 +97,7 @@ class FGPropertyNode : public SGPropertyNode
|
|||
/**
|
||||
* Get the name of a node
|
||||
*/
|
||||
std::string GetName( void ) const;
|
||||
const std::string& GetName( void ) const { return getNameString(); }
|
||||
|
||||
/**
|
||||
* Get the name of a node without underscores, etc.
|
||||
|
@ -413,9 +413,21 @@ class FGPropertyManager
|
|||
*
|
||||
* Classes should use this function to release control of any
|
||||
* properties they are managing.
|
||||
*
|
||||
* @param name The property name to untie (full path).
|
||||
*/
|
||||
void Untie (const std::string &name);
|
||||
|
||||
/**
|
||||
* Untie a property from an external data source.
|
||||
*
|
||||
* Classes should use this function to release control of any
|
||||
* properties they are managing.
|
||||
*
|
||||
* @param property A pointer to the property to untie.
|
||||
*/
|
||||
void Untie (SGPropertyNode* property);
|
||||
|
||||
/**
|
||||
* Unbind all properties bound by this manager to an external data source.
|
||||
*
|
||||
|
|
|
@ -597,12 +597,12 @@ void FGScript::Debug(int from)
|
|||
for (unsigned j=0; j<Events[i].SetValue.size(); j++) {
|
||||
if (Events[i].SetValue[j] == 0.0 && Events[i].Functions[j] != 0L) {
|
||||
if (Events[i].SetParam[j] == 0) {
|
||||
if (Events[i].SetParamName[j].size() == 0) {
|
||||
cerr << fgred << highint << endl
|
||||
<< " An attempt has been made to access a non-existent property" << endl
|
||||
<< " in this event. Please check the property names used, spelling, etc."
|
||||
<< reset << endl;
|
||||
exit(-1);
|
||||
if (Events[i].SetParamName[j].empty()) {
|
||||
stringstream s;
|
||||
s << " An attempt has been made to access a non-existent property" << endl
|
||||
<< " in this event. Please check the property names used, spelling, etc.";
|
||||
cerr << fgred << highint << endl << s.str() << reset << endl;
|
||||
throw BaseException(s.str());
|
||||
} else {
|
||||
cout << endl << " set " << Events[i].SetParamName[j]
|
||||
<< " to function value (Late Bound)";
|
||||
|
@ -614,12 +614,12 @@ void FGScript::Debug(int from)
|
|||
}
|
||||
} else {
|
||||
if (Events[i].SetParam[j] == 0) {
|
||||
if (Events[i].SetParamName[j].size() == 0) {
|
||||
cerr << fgred << highint << endl
|
||||
<< " An attempt has been made to access a non-existent property" << endl
|
||||
<< " in this event. Please check the property names used, spelling, etc."
|
||||
<< reset << endl;
|
||||
exit(-1);
|
||||
if (Events[i].SetParamName[j].empty()) {
|
||||
stringstream s;
|
||||
s << " An attempt has been made to access a non-existent property" << endl
|
||||
<< " in this event. Please check the property names used, spelling, etc.";
|
||||
cerr << fgred << highint << endl << s.str() << reset << endl;
|
||||
throw BaseException(s.str());
|
||||
} else {
|
||||
cout << endl << " set " << Events[i].SetParamName[j]
|
||||
<< " to function value (Late Bound)";
|
||||
|
|
|
@ -81,12 +81,13 @@ static bool LoadWinSockDLL(int debug_lvl)
|
|||
}
|
||||
#endif
|
||||
|
||||
FGfdmSocket::FGfdmSocket(const string& address, int port, int protocol)
|
||||
FGfdmSocket::FGfdmSocket(const string& address, int port, int protocol, int precision)
|
||||
{
|
||||
sckt = sckt_in = 0;
|
||||
Protocol = (ProtocolType)protocol;
|
||||
connected = false;
|
||||
struct addrinfo *addr = nullptr;
|
||||
this->precision = precision;
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
if (!LoadWinSockDLL(debug_lvl)) return;
|
||||
|
@ -150,12 +151,13 @@ FGfdmSocket::FGfdmSocket(const string& address, int port, int protocol)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// assumes TCP or UDP socket on localhost, for inbound datagrams
|
||||
FGfdmSocket::FGfdmSocket(int port, int protocol)
|
||||
FGfdmSocket::FGfdmSocket(int port, int protocol, int precision)
|
||||
{
|
||||
sckt = -1;
|
||||
connected = false;
|
||||
Protocol = (ProtocolType)protocol;
|
||||
string ProtocolName;
|
||||
this->precision = precision;
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
if (!LoadWinSockDLL(debug_lvl)) return;
|
||||
|
@ -338,7 +340,7 @@ void FGfdmSocket::Append(const char* item)
|
|||
void FGfdmSocket::Append(double item)
|
||||
{
|
||||
if (buffer.tellp() > 0) buffer << ',';
|
||||
buffer << std::setw(12) << std::setprecision(7) << item;
|
||||
buffer << std::setw(12) << std::setprecision(precision) << item;
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
|
|
@ -70,10 +70,8 @@ CLASS DECLARATION
|
|||
class FGfdmSocket : public FGJSBBase
|
||||
{
|
||||
public:
|
||||
FGfdmSocket(const std::string& address, int port)
|
||||
: FGfdmSocket(address, port, ptTCP) {}
|
||||
FGfdmSocket(const std::string&, int, int);
|
||||
FGfdmSocket(int, int);
|
||||
FGfdmSocket(const std::string& address, int port, int protocol, int precision = 7);
|
||||
FGfdmSocket(int port, int protocol, int precision = 7);
|
||||
~FGfdmSocket();
|
||||
void Send(void);
|
||||
void Send(const char *data, int length);
|
||||
|
@ -104,6 +102,7 @@ private:
|
|||
struct sockaddr_in scktName;
|
||||
struct hostent *host;
|
||||
std::ostringstream buffer;
|
||||
int precision;
|
||||
bool connected;
|
||||
void Debug(int from);
|
||||
};
|
||||
|
|
|
@ -124,7 +124,7 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager,
|
|||
|
||||
Comparison = mComparison[conditional];
|
||||
if (Comparison == ecUndef) {
|
||||
std::invalid_argument("JSBSim FGCondition: Comparison operator: \""+conditional
|
||||
throw std::invalid_argument("JSBSim FGCondition: Comparison operator: \""+conditional
|
||||
+"\" does not exist. Please check the conditional.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -890,10 +890,8 @@ void FGFunction::Load(Element* el, FGPropertyValue* var, FGFDMExec* fdmex,
|
|||
|
||||
FGFunction::~FGFunction()
|
||||
{
|
||||
if (pNode && pNode->isTied()) {
|
||||
string pName = pNode->GetFullyQualifiedName();
|
||||
PropertyManager->Untie(pName);
|
||||
}
|
||||
if (pNode && pNode->isTied())
|
||||
PropertyManager->Untie(pNode);
|
||||
|
||||
Debug(1);
|
||||
}
|
||||
|
|
|
@ -425,7 +425,6 @@ FGMatrix33 FGMatrix33::operator/(const double scalar) const
|
|||
{
|
||||
FGMatrix33 Quot;
|
||||
|
||||
if ( scalar != 0 ) {
|
||||
double tmp = 1.0/scalar;
|
||||
Quot.data[0] = data[0] * tmp;
|
||||
Quot.data[3] = data[3] * tmp;
|
||||
|
@ -436,8 +435,6 @@ 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)"};
|
||||
|
||||
return Quot;
|
||||
}
|
||||
|
@ -446,7 +443,6 @@ FGMatrix33 FGMatrix33::operator/(const double scalar) const
|
|||
|
||||
FGMatrix33& FGMatrix33::operator/=(const double scalar)
|
||||
{
|
||||
if ( scalar != 0 ) {
|
||||
double tmp = 1.0/scalar;
|
||||
data[0] *= tmp;
|
||||
data[3] *= tmp;
|
||||
|
@ -457,8 +453,6 @@ 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)"};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ INCLUDES
|
|||
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "FGJSBBase.h"
|
||||
#include "FGColumnVector3.h"
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -54,23 +54,6 @@ namespace JSBSim {
|
|||
|
||||
class FGQuaternion;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
CLASS DOCUMENTATION
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
/** Exception convenience class.
|
||||
*/
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
DECLARATION: MatrixException
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
class MatrixException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
MatrixException(const std::string& msg) : std::runtime_error{msg} { }
|
||||
};
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
CLASS DOCUMENTATION
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
|
|
@ -158,7 +158,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el,
|
|||
std::cerr << el->ReadFrom()
|
||||
<<" An unknown table type attribute is listed: " << call_type
|
||||
<< endl;
|
||||
throw TableException("Unknown table type.");
|
||||
throw BaseException("Unknown table type.");
|
||||
}
|
||||
|
||||
// Determine and store the lookup properties for this table unless this table
|
||||
|
@ -199,7 +199,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el,
|
|||
} else if (lookup_axis == string("table")) {
|
||||
lookupProperty[eTable] = node;
|
||||
} else if (!lookup_axis.empty()) {
|
||||
throw TableException("Lookup table axis specification not understood: " + lookup_axis);
|
||||
throw BaseException("Lookup table axis specification not understood: " + lookup_axis);
|
||||
} else { // assumed single dimension table; row lookup
|
||||
lookupProperty[eRow] = node;
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el,
|
|||
std::cerr << el->ReadFrom()
|
||||
<< "No independentVars found, and table is not marked as internal,"
|
||||
<< " nor is it a 3D table." << endl;
|
||||
throw TableException("No independent variable found for table.");
|
||||
throw BaseException("No independent variable found for table.");
|
||||
}
|
||||
}
|
||||
// end lookup property code
|
||||
|
@ -245,8 +245,16 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el,
|
|||
}
|
||||
|
||||
for (i=0; i<tableData->GetNumDataLines(); i++) {
|
||||
buf << tableData->GetDataLine(i) << string(" ");
|
||||
string line = tableData->GetDataLine(i);
|
||||
if (line.find_first_not_of("0123456789.-+eE \t\n") != string::npos) {
|
||||
cerr << " In file " << tableData->GetFileName() << endl
|
||||
<< " Illegal character found in line "
|
||||
<< tableData->GetLineNumber() + i + 1 << ": " << endl << line << endl;
|
||||
throw BaseException("Illegal character");
|
||||
}
|
||||
buf << line << " ";
|
||||
}
|
||||
|
||||
switch (dimension) {
|
||||
case 1:
|
||||
nRows = tableData->GetNumDataLines();
|
||||
|
@ -267,12 +275,12 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el,
|
|||
if (nCols < 2) {
|
||||
std::cerr << tableData->ReadFrom()
|
||||
<< "Not enough columns in table data" << endl;
|
||||
throw TableException("Not enough columns in table data.");
|
||||
throw BaseException("Not enough columns in table data.");
|
||||
}
|
||||
} else {
|
||||
std::cerr << tableData->ReadFrom()
|
||||
<< "Not enough rows in table data" << endl;
|
||||
throw TableException("Not enough rows in the table data.");
|
||||
throw BaseException("Not enough rows in the table data.");
|
||||
}
|
||||
|
||||
Type = tt2D;
|
||||
|
@ -330,7 +338,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el,
|
|||
if (nameel != 0) std::cerr << " of table in " << nameel->GetAttributeValue("name");
|
||||
std::cerr << ":" << reset << endl
|
||||
<< " " << Data[b][1] << "<=" << Data[b-1][1] << endl;
|
||||
throw TableException("Breakpoint lookup is not monotonically increasing");
|
||||
throw BaseException("Breakpoint lookup is not monotonically increasing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -346,7 +354,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el,
|
|||
if (nameel != 0) std::cerr << " of table in " << nameel->GetAttributeValue("name");
|
||||
std::cerr << ":" << reset << endl
|
||||
<< " " << Data[0][c] << "<=" << Data[0][c-1] << endl;
|
||||
throw TableException("FGTable: column lookup is not monotonically increasing");
|
||||
throw BaseException("FGTable: column lookup is not monotonically increasing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -362,7 +370,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el,
|
|||
if (nameel != 0) std::cerr << " of table in " << nameel->GetAttributeValue("name");
|
||||
std::cerr << ":" << reset << endl
|
||||
<< " " << Data[r][0] << "<=" << Data[r-1][0] << endl;
|
||||
throw TableException("FGTable: row lookup is not monotonically increasing");
|
||||
throw BaseException("FGTable: row lookup is not monotonically increasing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -393,10 +401,10 @@ FGTable::~FGTable()
|
|||
// Untie the bound property so that it makes no further reference to this
|
||||
// instance of FGTable after the destruction is completed.
|
||||
if (!Name.empty() && !internal) {
|
||||
string tmp = mkPropertyName(nullptr, "");
|
||||
string tmp = PropertyManager->mkPropertyName(Name, false);
|
||||
FGPropertyNode* node = PropertyManager->GetNode(tmp);
|
||||
if (node->isTied())
|
||||
PropertyManager->Untie(tmp);
|
||||
if (node && node->isTied())
|
||||
PropertyManager->Untie(node);
|
||||
}
|
||||
|
||||
if (nTables > 0) {
|
||||
|
@ -653,8 +661,11 @@ void FGTable::Print(void)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
string FGTable::mkPropertyName(Element* el, const std::string& Prefix)
|
||||
void FGTable::bind(Element* el, const string& Prefix)
|
||||
{
|
||||
typedef double (FGTable::*PMF)(void) const;
|
||||
|
||||
if ( !Name.empty() && !internal) {
|
||||
if (!Prefix.empty()) {
|
||||
if (is_number(Prefix)) {
|
||||
if (Name.find("#") != string::npos) { // if "#" is found
|
||||
|
@ -669,17 +680,7 @@ string FGTable::mkPropertyName(Element* el, const std::string& Prefix)
|
|||
Name = Prefix + "/" + Name;
|
||||
}
|
||||
}
|
||||
|
||||
return PropertyManager->mkPropertyName(Name, false);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGTable::bind(Element* el, const string& Prefix)
|
||||
{
|
||||
typedef double (FGTable::*PMF)(void) const;
|
||||
if ( !Name.empty() && !internal) {
|
||||
string tmp = mkPropertyName(el, Prefix);
|
||||
string tmp = PropertyManager->mkPropertyName(Name, false);
|
||||
|
||||
if (PropertyManager->HasNode(tmp)) {
|
||||
FGPropertyNode* _property = PropertyManager->GetNode(tmp);
|
||||
|
@ -689,6 +690,7 @@ void FGTable::bind(Element* el, const string& Prefix)
|
|||
throw("Failed to bind the property to an existing already tied node.");
|
||||
}
|
||||
}
|
||||
|
||||
PropertyManager->Tie(tmp, this, (PMF)&FGTable::GetValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -226,19 +226,6 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio
|
|||
@author Jon S. Berndt
|
||||
*/
|
||||
|
||||
/** Exception convenience class.
|
||||
*/
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
DECLARATION: TableException
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
class TableException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
TableException(const std::string& msg) : std::runtime_error{msg} { }
|
||||
};
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
CLASS DECLARATION
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
@ -317,8 +304,6 @@ private:
|
|||
FGPropertyManager* const PropertyManager;
|
||||
std::string Name;
|
||||
void bind(Element* el, const std::string& Prefix);
|
||||
|
||||
std::string mkPropertyName(Element* el, const std::string& Prefix);
|
||||
void Debug(int from);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -229,9 +229,13 @@ bool FGAerodynamics::Run(bool Holding)
|
|||
vForcesAtCG = Ts2b*vFnativeAtCG;
|
||||
break;
|
||||
default:
|
||||
cerr << endl << " A proper axis type has NOT been selected. Check "
|
||||
<< "your aerodynamics definition." << endl;
|
||||
exit(-1);
|
||||
{
|
||||
stringstream s;
|
||||
s << " A proper axis type has NOT been selected. Check "
|
||||
<< "your aerodynamics definition.";
|
||||
cerr << endl << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
}
|
||||
// Calculate aerodynamic reference point shift, if any. The shift takes place
|
||||
// in the structual axis. That is, if the shift is positive, it is towards the
|
||||
|
@ -272,9 +276,13 @@ bool FGAerodynamics::Run(bool Holding)
|
|||
vMomentsMRCBodyXYZ = in.Tw2b*vMomentsMRC;
|
||||
break;
|
||||
default:
|
||||
cerr << endl << " A proper axis type has NOT been selected. Check "
|
||||
<< "your aerodynamics definition." << endl;
|
||||
exit(-1);
|
||||
{
|
||||
stringstream s;
|
||||
s << " A proper axis type has NOT been selected. Check "
|
||||
<< "your aerodynamics definition.";
|
||||
cerr << endl << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
}
|
||||
|
||||
vMoments = vMomentsMRCBodyXYZ + vDXYZcg*vForces; // M = r X F
|
||||
|
@ -447,10 +455,12 @@ void FGAerodynamics::DetermineAxisSystem(Element* document)
|
|||
<< " aircraft config file. (NORMAL AXIAL)" << endl;
|
||||
}
|
||||
} else { // error
|
||||
cerr << endl << axis_element->ReadFrom()
|
||||
stringstream s;
|
||||
s << axis_element->ReadFrom()
|
||||
<< endl << " An unknown axis type, " << axis << " has been specified"
|
||||
<< " in the aircraft configuration file." << endl;
|
||||
exit(-1);
|
||||
<< " in the aircraft configuration file.";
|
||||
cerr << endl << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
axis_element = document->FindNextElement("axis");
|
||||
}
|
||||
|
@ -495,8 +505,10 @@ void FGAerodynamics::ProcessAxesNameAndFrame(eAxisType& axisType, const string&
|
|||
<< " aircraft config file." << validNames << " - WIND" << endl;
|
||||
}
|
||||
else {
|
||||
cerr << endl << " Unknown axis frame type of - " << frame << endl;
|
||||
exit(-1);
|
||||
stringstream s;
|
||||
s << " Unknown axis frame type of - " << frame;
|
||||
cerr << endl << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,8 +86,9 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, unsigned int num,
|
|||
if (element) {
|
||||
vXYZ = element->FindElementTripletConvertTo("IN");
|
||||
} else {
|
||||
cerr << "Fatal Error: No location found for this gas cell." << endl;
|
||||
exit(-1);
|
||||
const string s("Fatal Error: No location found for this gas cell.");
|
||||
cerr << el->ReadFrom() << endl << s << endl;
|
||||
throw BaseException(s);
|
||||
}
|
||||
if ((el->FindElement("x_radius") || el->FindElement("x_width")) &&
|
||||
(el->FindElement("y_radius") || el->FindElement("y_width")) &&
|
||||
|
@ -137,8 +138,9 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, unsigned int num,
|
|||
Xwidth * Ywidth * Zwidth);
|
||||
}
|
||||
} else {
|
||||
cerr << "Fatal Error: Gas cell shape must be given." << endl;
|
||||
exit(-1);
|
||||
const string s("Fatal Error: Gas cell shape must be given.");
|
||||
cerr << el->ReadFrom() << endl << s << endl;
|
||||
throw BaseException(s);
|
||||
}
|
||||
if (el->FindElement("max_overpressure")) {
|
||||
MaxOverpressure = el->FindElementValueAsNumberConvertTo("max_overpressure",
|
||||
|
@ -517,8 +519,9 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, unsigned int num,
|
|||
if (element) {
|
||||
vXYZ = element->FindElementTripletConvertTo("IN");
|
||||
} else {
|
||||
cerr << "Fatal Error: No location found for this ballonet." << endl;
|
||||
exit(-1);
|
||||
const string s("Fatal Error: No location found for this ballonet.");
|
||||
cerr << el->ReadFrom() << endl << s << endl;
|
||||
throw BaseException(s);
|
||||
}
|
||||
if ((el->FindElement("x_radius") || el->FindElement("x_width")) &&
|
||||
(el->FindElement("y_radius") || el->FindElement("y_width")) &&
|
||||
|
@ -568,8 +571,9 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, unsigned int num,
|
|||
Xwidth * Ywidth * Zwidth);
|
||||
}
|
||||
} else {
|
||||
cerr << "Fatal Error: Ballonet shape must be given." << endl;
|
||||
exit(-1);
|
||||
const string s("Fatal Error: Ballonet shape must be given.");
|
||||
cerr << el->ReadFrom() << endl << s << endl;
|
||||
throw BaseException(s);
|
||||
}
|
||||
if (el->FindElement("max_overpressure")) {
|
||||
MaxOverpressure = el->FindElementValueAsNumberConvertTo("max_overpressure",
|
||||
|
|
|
@ -152,6 +152,11 @@ bool FGInput::SetDirectivesFile(const SGPath& fname)
|
|||
{
|
||||
FGXMLFileRead XMLFile;
|
||||
Element* document = XMLFile.LoadXMLDocument(fname);
|
||||
if (!document) {
|
||||
stringstream s;
|
||||
s << "Could not read directive file: " << fname;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
bool result = Load(document);
|
||||
|
||||
if (!result)
|
||||
|
|
|
@ -180,7 +180,12 @@ FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number, const struct Inputs&
|
|||
|
||||
Element* element = el->FindElement("location");
|
||||
if (element) vXYZn = element->FindElementTripletConvertTo("IN");
|
||||
else {cerr << "No location given for contact " << name << endl; exit(-1);}
|
||||
else {
|
||||
stringstream s;
|
||||
s << "No location given for contact " << name;
|
||||
cerr << endl << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
SetTransformType(FGForce::tCustom);
|
||||
|
||||
element = el->FindElement("orientation");
|
||||
|
|
|
@ -268,9 +268,11 @@ void FGMassBalance::AddPointMass(Element* el)
|
|||
Element* loc_element = el->FindElement("location");
|
||||
string pointmass_name = el->GetAttributeValue("name");
|
||||
if (!loc_element) {
|
||||
cerr << el->ReadFrom() << "Pointmass " << pointmass_name
|
||||
<< " has no location." << endl;
|
||||
exit(-1);
|
||||
stringstream s;
|
||||
s << el->ReadFrom() << "Pointmass " << pointmass_name
|
||||
<< " has no location.";
|
||||
cerr << endl << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
|
||||
double w = el->FindElementValueAsNumberConvertTo("weight", "LBS");
|
||||
|
|
|
@ -173,8 +173,13 @@ bool FGOutput::SetDirectivesFile(const SGPath& fname)
|
|||
{
|
||||
FGXMLFileRead XMLFile;
|
||||
Element* document = XMLFile.LoadXMLDocument(fname);
|
||||
bool result = Load(document);
|
||||
if (!document) {
|
||||
stringstream s;
|
||||
s << "Could not read directive file: " << fname;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
|
||||
bool result = Load(document);
|
||||
if (!result)
|
||||
cerr << endl << "Aircraft output element has problems in file " << fname << endl;
|
||||
|
||||
|
|
|
@ -688,7 +688,7 @@ void FGPropagate::WriteStateFile(int num)
|
|||
|
||||
if (num == 0) return;
|
||||
|
||||
SGPath path = FDMExec->GetFullAircraftPath();
|
||||
SGPath path = FDMExec->GetOutputPath();
|
||||
|
||||
if (path.isNull()) path = SGPath("initfile.");
|
||||
else path.append("initfile.");
|
||||
|
@ -968,16 +968,22 @@ void FGPropagate::Debug(int from)
|
|||
if (debug_lvl & 16) { // Sanity checking
|
||||
if (from == 2) { // State sanity checking
|
||||
if (fabs(VState.vPQR.Magnitude()) > 1000.0) {
|
||||
cerr << endl << "Vehicle rotation rate is excessive (>1000 rad/sec): " << VState.vPQR.Magnitude() << endl;
|
||||
exit(-1);
|
||||
stringstream s;
|
||||
s << "Vehicle rotation rate is excessive (>1000 rad/sec): " << VState.vPQR.Magnitude();
|
||||
cerr << endl << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
if (fabs(VState.vUVW.Magnitude()) > 1.0e10) {
|
||||
cerr << endl << "Vehicle velocity is excessive (>1e10 ft/sec): " << VState.vUVW.Magnitude() << endl;
|
||||
exit(-1);
|
||||
stringstream s;
|
||||
s << "Vehicle velocity is excessive (>1e10 ft/sec): " << VState.vUVW.Magnitude();
|
||||
cerr << endl << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
if (fabs(GetDistanceAGL()) > 1e10) {
|
||||
cerr << endl << "Vehicle altitude is excessive (>1e10 ft): " << GetDistanceAGL() << endl;
|
||||
exit(-1);
|
||||
stringstream s;
|
||||
s << "Vehicle altitude is excessive (>1e10 ft): " << GetDistanceAGL();
|
||||
cerr << endl << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,34 +52,29 @@ CLASS IMPLEMENTATION
|
|||
FGKinemat::FGKinemat(FGFCS* fcs, Element* element)
|
||||
: FGFCSComponent(fcs, element)
|
||||
{
|
||||
Element *traverse_element, *setting_element;
|
||||
double tmpDetent;
|
||||
double tmpTime;
|
||||
|
||||
CheckInputNodes(1, 1, element);
|
||||
|
||||
Detents.clear();
|
||||
TransitionTimes.clear();
|
||||
|
||||
Output = 0;
|
||||
DoScale = true;
|
||||
|
||||
if (element->FindElement("noscale")) DoScale = false;
|
||||
|
||||
traverse_element = element->FindElement("traverse");
|
||||
setting_element = traverse_element->FindElement("setting");
|
||||
Element* traverse_element = element->FindElement("traverse");
|
||||
Element* setting_element = traverse_element->FindElement("setting");
|
||||
while (setting_element) {
|
||||
tmpDetent = setting_element->FindElementValueAsNumber("position");
|
||||
tmpTime = setting_element->FindElementValueAsNumber("time");
|
||||
double tmpDetent = setting_element->FindElementValueAsNumber("position");
|
||||
double tmpTime = setting_element->FindElementValueAsNumber("time");
|
||||
Detents.push_back(tmpDetent);
|
||||
TransitionTimes.push_back(tmpTime);
|
||||
setting_element = traverse_element->FindNextElement("setting");
|
||||
}
|
||||
|
||||
if (Detents.size() <= 1) {
|
||||
cerr << "Kinematic component " << Name
|
||||
<< " must have more than 1 setting element" << endl;
|
||||
exit(-1);
|
||||
stringstream s;
|
||||
s << "Kinematic component " << Name
|
||||
<< " must have more than 1 setting element";
|
||||
cerr << element->ReadFrom() << endl << s.str() << endl;
|
||||
throw BaseException(s.str());
|
||||
}
|
||||
|
||||
bind(element);
|
||||
|
|
|
@ -182,7 +182,24 @@ bool FGWaypoint::Run(void )
|
|||
double target_longitude_rad = target_longitude->GetValue() * target_longitude_unit;
|
||||
source.SetPosition(source_longitude_rad, source_latitude_rad, radius);
|
||||
|
||||
if (fabs(target_latitude_rad) > M_PI/2.0) {
|
||||
cerr << endl;
|
||||
cerr << "Target latitude in waypoint \"" << Name << "\" must be less than or equal to 90 degrees." << endl;
|
||||
cerr << "(is longitude being mistakenly supplied?)" << endl;
|
||||
cerr << endl;
|
||||
throw("Waypoint target latitude exceeded 90 degrees.");
|
||||
}
|
||||
|
||||
if (fabs(source_latitude_rad) > M_PI/2.0) {
|
||||
cerr << endl;
|
||||
cerr << "Source latitude in waypoint \"" << Name << "\" must be less than or equal to 90 degrees." << endl;
|
||||
cerr << "(is longitude being mistakenly supplied?)" << endl;
|
||||
cerr << endl;
|
||||
throw("Source latitude exceeded 90 degrees.");
|
||||
}
|
||||
|
||||
if (WaypointType == eHeading) { // Calculate Heading
|
||||
|
||||
double heading_to_waypoint_rad = source.GetHeadingTo(target_longitude_rad,
|
||||
target_latitude_rad);
|
||||
|
||||
|
@ -190,11 +207,12 @@ bool FGWaypoint::Run(void )
|
|||
else Output = heading_to_waypoint_rad;
|
||||
|
||||
} else { // Calculate Distance
|
||||
|
||||
double wp_distance = source.GetDistanceTo(target_longitude_rad,
|
||||
target_latitude_rad);
|
||||
|
||||
if (eUnit == eMeters) Output = FeetToMeters(wp_distance);
|
||||
else Output = wp_distance;
|
||||
|
||||
}
|
||||
|
||||
Clip();
|
||||
|
|
|
@ -56,8 +56,6 @@ FGEngine::FGEngine(int engine_number, struct Inputs& input)
|
|||
: in(input), EngineNumber(engine_number)
|
||||
{
|
||||
Type = etUnknown;
|
||||
X = Y = Z = 0.0;
|
||||
EnginePitch = EngineYaw = 0.0;
|
||||
SLFuelFlowMax = 0.0;
|
||||
FuelExpended = 0.0;
|
||||
MaxThrottle = 1.0;
|
||||
|
@ -113,18 +111,6 @@ unsigned int FGEngine::GetSourceTank(unsigned int i) const
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGEngine::SetPlacement(const FGColumnVector3& location,
|
||||
const FGColumnVector3& orientation)
|
||||
{
|
||||
X = location(eX);
|
||||
Y = location(eY);
|
||||
Z = location(eZ);
|
||||
EnginePitch = orientation(ePitch);
|
||||
EngineYaw = orientation (eYaw);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
double FGEngine::GetThrust(void) const
|
||||
{
|
||||
return Thruster->GetThrust();
|
||||
|
@ -200,19 +186,17 @@ bool FGEngine::Load(FGFDMExec *exec, Element *engine_element)
|
|||
// Call ModelFunctions loader
|
||||
FGModelFunctions::Load(engine_element, exec, to_string((int)EngineNumber));
|
||||
|
||||
// Find and set engine location
|
||||
|
||||
// If engine location and/or orientation is supplied issue a warning since they
|
||||
// are ignored. What counts is the location and orientation of the thruster.
|
||||
local_element = parent_element->FindElement("location");
|
||||
if (local_element) location = local_element->FindElementTripletConvertTo("IN");
|
||||
// else cerr << "No engine location found for this engine." << endl;
|
||||
// Jon: The engine location is not important - the nozzle location is.
|
||||
if (local_element)
|
||||
cerr << local_element->ReadFrom()
|
||||
<< "Engine location ignored, only thruster location is used." << endl;
|
||||
|
||||
local_element = parent_element->FindElement("orient");
|
||||
if (local_element) orientation = local_element->FindElementTripletConvertTo("RAD");
|
||||
// else cerr << "No engine orientation found for this engine." << endl;
|
||||
// Jon: The engine orientation has a default and is not normally used.
|
||||
|
||||
SetPlacement(location, orientation);
|
||||
if (local_element)
|
||||
cerr << local_element->ReadFrom()
|
||||
<< "Engine orientation ignored, only thruster orientation is used." << endl;
|
||||
|
||||
// Load thruster
|
||||
local_element = parent_element->FindElement("thruster");
|
||||
|
|
|
@ -71,17 +71,6 @@ CLASS DOCUMENTATION
|
|||
<h3>Configuration File Format:</h3>
|
||||
@code
|
||||
<engine file="{string}">
|
||||
<location unit="{IN | M}">
|
||||
<x> {number} </x>
|
||||
<y> {number} </y>
|
||||
<z> {number} </z>
|
||||
</location>
|
||||
<!-- optional orientation definition -->
|
||||
<orient unit="{RAD | DEG}">
|
||||
<roll> {number} </roll>
|
||||
<pitch> {number} </pitch>
|
||||
<yaw> {number} </yaw>
|
||||
</orient>
|
||||
<feed> {integer} </feed>
|
||||
... optional more feed tank index numbers ...
|
||||
<thruster file="{string}">
|
||||
|
@ -183,9 +172,6 @@ public:
|
|||
|
||||
virtual double GetThrust(void) const;
|
||||
|
||||
/// Sets engine placement information
|
||||
virtual void SetPlacement(const FGColumnVector3& location, const FGColumnVector3& orientation);
|
||||
|
||||
/** The fuel need is calculated based on power levels and flow rate for that
|
||||
power level. It is also turned from a rate into an actual amount (pounds)
|
||||
by multiplying it by the delta T and the rate.
|
||||
|
@ -216,9 +202,6 @@ protected:
|
|||
std::string Name;
|
||||
const int EngineNumber;
|
||||
EngineType Type;
|
||||
double X, Y, Z;
|
||||
double EnginePitch;
|
||||
double EngineYaw;
|
||||
double SLFuelFlowMax;
|
||||
double MaxThrottle;
|
||||
double MinThrottle;
|
||||
|
|
|
@ -106,8 +106,11 @@ const FGMatrix33& FGForce::Transform(void) const
|
|||
case tNone:
|
||||
return mT;
|
||||
default:
|
||||
cout << "Unrecognized tranform requested from FGForce::Transform()" << endl;
|
||||
exit(1);
|
||||
{
|
||||
const string s("Unrecognized tranform requested from FGForce::Transform()");
|
||||
cout << s << endl;
|
||||
throw BaseException(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,8 +57,9 @@ FGNozzle::FGNozzle(FGFDMExec* FDMExec, Element* nozzle_element, int num)
|
|||
if (nozzle_element->FindElement("area"))
|
||||
Area = nozzle_element->FindElementValueAsNumberConvertTo("area", "FT2");
|
||||
else {
|
||||
cerr << "Fatal Error: Nozzle exit area must be given in nozzle config file." << endl;
|
||||
exit(-1);
|
||||
const string s("Fatal Error: Nozzle exit area must be given in nozzle config file.");
|
||||
cerr << s << endl;
|
||||
throw BaseException(s);
|
||||
}
|
||||
|
||||
Thrust = 0;
|
||||
|
|
|
@ -193,10 +193,9 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
|
|||
switch (grainType) {
|
||||
case gtCYLINDRICAL:
|
||||
if (Radius <= InnerRadius) {
|
||||
cerr << element_Grain->ReadFrom()
|
||||
<< "The bore diameter should be smaller than the total grain diameter!"
|
||||
<< endl;
|
||||
exit(-1);
|
||||
const string s("The bore diameter should be smaller than the total grain diameter!");
|
||||
cerr << element_Grain->ReadFrom() << endl << s << endl;
|
||||
throw BaseException(s);
|
||||
}
|
||||
Volume = M_PI * Length * (Radius*Radius - InnerRadius*InnerRadius); // cubic inches
|
||||
break;
|
||||
|
@ -207,10 +206,11 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
|
|||
Volume = 1; // Volume is irrelevant for the FUNCTION type, but it can't be zero!
|
||||
break;
|
||||
case gtUNKNOWN:
|
||||
cerr << el->ReadFrom()
|
||||
<< "Unknown grain type found in this rocket engine definition."
|
||||
<< endl;
|
||||
exit(-1);
|
||||
{
|
||||
const string s("Unknown grain type found in this rocket engine definition.");
|
||||
cerr << el->ReadFrom() << endl << s << endl;
|
||||
throw BaseException(s);
|
||||
}
|
||||
}
|
||||
Density = (Capacity*lbtoslug)/Volume; // slugs/in^3
|
||||
}
|
||||
|
@ -375,8 +375,9 @@ void FGTank::CalculateInertias(void)
|
|||
} else if (Contents <= 0.0) {
|
||||
Volume = 0;
|
||||
} else {
|
||||
cerr << endl << " Solid propellant grain density is zero!" << endl << endl;
|
||||
exit(-1);
|
||||
const string s(" Solid propellant grain density is zero!");
|
||||
cerr << endl << s << endl;
|
||||
throw BaseException(s);
|
||||
}
|
||||
|
||||
switch (grainType) {
|
||||
|
@ -399,9 +400,11 @@ void FGTank::CalculateInertias(void)
|
|||
Izz = function_izz->GetValue()*izz_unit;
|
||||
break;
|
||||
default:
|
||||
cerr << "Unknown grain type found." << endl;
|
||||
exit(-1);
|
||||
break;
|
||||
{
|
||||
const string s("Unknown grain type found.");
|
||||
cerr << s << endl;
|
||||
throw BaseException(s);
|
||||
}
|
||||
}
|
||||
|
||||
} else { // assume liquid propellant: shrinking snowball
|
||||
|
|
Loading…
Add table
Reference in a new issue