From 6cd02910972870292f055095336144bccd32711f Mon Sep 17 00:00:00 2001 From: Bertrand Coconnier Date: Sun, 11 Aug 2024 13:40:35 +0200 Subject: [PATCH] Logging redesign (cont'd) (#1136) --- src/input_output/FGLog.cpp | 22 +- src/input_output/FGLog.h | 19 +- src/input_output/FGModelLoader.cpp | 9 +- src/input_output/FGfdmSocket.h | 1 + src/models/FGAtmosphere.cpp | 16 +- src/models/FGAuxiliary.cpp | 15 +- src/models/FGFCS.cpp | 96 +++--- src/models/FGInertial.cpp | 30 +- src/models/FGInput.cpp | 27 +- src/models/FGMassBalance.cpp | 107 +++---- src/models/FGModel.cpp | 22 +- src/models/FGModel.h | 6 +- src/models/FGPropagate.cpp | 278 +++++++++--------- .../atmosphere/FGStandardAtmosphere.cpp | 74 +++-- src/models/atmosphere/FGWinds.cpp | 6 +- 15 files changed, 409 insertions(+), 319 deletions(-) diff --git a/src/input_output/FGLog.cpp b/src/input_output/FGLog.cpp index 2c7912eff2..347a5a86ff 100644 --- a/src/input_output/FGLog.cpp +++ b/src/input_output/FGLog.cpp @@ -48,18 +48,28 @@ CLASS IMPLEMENTATION void FGLogging::Flush(void) { - logger->Message(buffer.str()); - buffer.str(""); - logger->Format(LogFormat::RESET); - logger->Flush(); + std::string message = buffer.str(); + + if (!message.empty()) { + logger->Message(message); + buffer.str(""); + logger->Format(LogFormat::RESET); + logger->Flush(); + } + buffer.clear(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGLogging& FGLogging::operator<<(LogFormat format) { - logger->Message(buffer.str()); - buffer.str(""); + std::string message = buffer.str(); + + if (!message.empty()) { + logger->Message(message); + buffer.str(""); + } + logger->Format(format); return *this; } diff --git a/src/input_output/FGLog.h b/src/input_output/FGLog.h index 41622f1c1e..7b12fbaf80 100644 --- a/src/input_output/FGLog.h +++ b/src/input_output/FGLog.h @@ -46,6 +46,7 @@ INCLUDES #include "simgear/misc/sg_path.hxx" #include "FGJSBBase.h" +#include "math/FGColumnVector3.h" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -55,9 +56,13 @@ namespace JSBSim { class Element; -// The return type of std::setprecision is unspecified by the C++ standard so we -// need some C++ magic to be able to overload the operator<< for std::setprecision +// The return type of these functions is unspecified by the C++ standard so we +// need some C++ magic to be able to overload the operator<< for these functions. using setprecision_t = decltype(std::setprecision(0)); +// For MSVC set_precision_t and setw_t are the same type +#ifndef _MSC_VER +using setw_t = decltype(std::setw(0)); +#endif enum class LogLevel { BULK, // For frequent messages @@ -114,10 +119,18 @@ class JSBSIM_API FGLogging virtual ~FGLogging() { Flush(); } FGLogging& operator<<(const char* message) { buffer << message ; return *this; } FGLogging& operator<<(const std::string& message) { buffer << message ; return *this; } - FGLogging& operator<<(unsigned int value) { buffer << value; return *this; } + template::value>> + FGLogging& operator<<(T value) { buffer << value; return *this; } FGLogging& operator<<(std::ostream& (*manipulator)(std::ostream&)) { buffer << manipulator; return *this; } + FGLogging& operator<<(std::ios_base& (*manipulator)(std::ios_base&)) { buffer << manipulator; return *this; } FGLogging& operator<<(setprecision_t value) { buffer << value; return *this; } + // Avoid duplicate definition for MSVC for which set_precision_t and setw_t + // are the same type +#ifndef _MSC_VER + FGLogging& operator<<(setw_t value) { buffer << value; return *this; } +#endif FGLogging& operator<<(const SGPath& path) { buffer << path; return *this; } + FGLogging& operator<<(const FGColumnVector3& vec) { buffer << vec; return *this; } FGLogging& operator<<(LogFormat format); std::string str(void) const { return buffer.str(); } void Flush(void); diff --git a/src/input_output/FGModelLoader.cpp b/src/input_output/FGModelLoader.cpp index 5aaa55d550..6c0a85d76b 100644 --- a/src/input_output/FGModelLoader.cpp +++ b/src/input_output/FGModelLoader.cpp @@ -37,10 +37,11 @@ HISTORY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include "FGJSBBase.h" +#include "FGFDMExec.h" #include "FGModelLoader.h" #include "FGXMLFileRead.h" #include "models/FGModel.h" +#include "input_output/FGLog.h" using namespace std; @@ -67,8 +68,8 @@ Element_ptr FGModelLoader::Open(Element *el) else { document = XMLFileRead.LoadXMLDocument(path); if (document == 0L) { - cerr << endl << el->ReadFrom() - << "Could not open file: " << fname << endl; + FGXMLLogging log(model->GetExec()->GetLogger(), el, LogLevel::ERROR); + log << "Could not open file: " << fname << endl; return NULL; } CachedFiles[path.utf8Str()] = document; @@ -83,6 +84,8 @@ Element_ptr FGModelLoader::Open(Element *el) return document; } +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + SGPath CheckPathName(const SGPath& path, const SGPath& filename) { SGPath fullName = path/filename.utf8Str(); diff --git a/src/input_output/FGfdmSocket.h b/src/input_output/FGfdmSocket.h index d2c0717d81..8b61bf13b4 100644 --- a/src/input_output/FGfdmSocket.h +++ b/src/input_output/FGfdmSocket.h @@ -44,6 +44,7 @@ INCLUDES #if defined(_MSC_VER) || defined(__MINGW32__) #include #include + #undef ERROR #else #include #endif diff --git a/src/models/FGAtmosphere.cpp b/src/models/FGAtmosphere.cpp index b5aa81cd8d..4ce21592bd 100644 --- a/src/models/FGAtmosphere.cpp +++ b/src/models/FGAtmosphere.cpp @@ -44,6 +44,7 @@ INCLUDES #include "FGFDMExec.h" #include "FGAtmosphere.h" +#include "input_output/FGLog.h" namespace JSBSim { @@ -104,8 +105,9 @@ double FGAtmosphere::ValidatePressure(double p, const string& msg, bool quiet) c const double MinPressure = ConvertToPSF(1E-15, ePascals); if (p < MinPressure) { if (!quiet) { - cerr << msg << " " << p << " is too low." << endl - << msg << " is capped to " << MinPressure << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); + log << msg << " " << p << " is too low." << endl + << msg << " will be capped to " << MinPressure << endl; } return MinPressure; } @@ -124,8 +126,9 @@ double FGAtmosphere::ValidateTemperature(double t, const string& msg, bool quiet if (t < minUniverseTemperature) { if (!quiet) { - cerr << msg << " " << t << " is too low." << endl - << msg << " is capped to " << minUniverseTemperature << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); + log << msg << " " << t << " is too low." << endl + << msg << " will be capped to " << minUniverseTemperature << endl; } return minUniverseTemperature; } @@ -354,8 +357,9 @@ void FGAtmosphere::Debug(int from) } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) std::cout << "Instantiated: FGAtmosphere" << std::endl; - if (from == 1) std::cout << "Destroyed: FGAtmosphere" << std::endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + if (from == 0) log << "Instantiated: FGAtmosphere" << std::endl; + if (from == 1) log << "Destroyed: FGAtmosphere" << std::endl; } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects } diff --git a/src/models/FGAuxiliary.cpp b/src/models/FGAuxiliary.cpp index 118456498b..335433c7a5 100644 --- a/src/models/FGAuxiliary.cpp +++ b/src/models/FGAuxiliary.cpp @@ -48,6 +48,7 @@ INCLUDES #include "input_output/FGPropertyManager.h" #include "FGInertial.h" #include "FGAtmosphere.h" +#include "input_output/FGLog.h" using namespace std; @@ -444,7 +445,9 @@ void FGAuxiliary::bind(void) double FGAuxiliary::BadUnits(void) const { - cerr << "Bad units" << endl; return 0.0; + FGLogging log(FDMExec->GetLogger(), LogLevel::ERROR); + log << "Bad units" << endl; + return 0.0; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -476,18 +479,20 @@ void FGAuxiliary::Debug(int from) } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGAuxiliary" << endl; - if (from == 1) cout << "Destroyed: FGAuxiliary" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + if (from == 0) log << "Instantiated: FGAuxiliary" << endl; + if (from == 1) log << "Destroyed: FGAuxiliary" << endl; } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects } if (debug_lvl & 8 ) { // Runtime state variables } if (debug_lvl & 16) { // Sanity checking + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); if (Mach > 100 || Mach < 0.00) - cout << "FGPropagate::Mach is out of bounds: " << Mach << endl; + log << "FGPropagate::Mach is out of bounds: " << Mach << endl; if (qbar > 1e6 || qbar < 0.00) - cout << "FGPropagate::qbar is out of bounds: " << qbar << endl; + log << "FGPropagate::qbar is out of bounds: " << qbar << endl; } if (debug_lvl & 64) { if (from == 0) { // Constructor diff --git a/src/models/FGFCS.cpp b/src/models/FGFCS.cpp index a5ffadfaa2..09d172642d 100644 --- a/src/models/FGFCS.cpp +++ b/src/models/FGFCS.cpp @@ -1,6 +1,6 @@ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - Module: FGFCS.cpp + Module: FGFCS.cpp Author: Jon Berndt Date started: 12/12/98 Purpose: Model the flight controls @@ -42,6 +42,7 @@ INCLUDES #include "FGFCS.h" #include "input_output/FGModelLoader.h" +#include "input_output/FGLog.h" #include "models/flight_control/FGFilter.h" #include "models/flight_control/FGDeadBand.h" @@ -81,7 +82,7 @@ FGFCS::FGFCS(FGFDMExec* fdm) : FGModel(fdm), ChannelRate(1) PTrimCmd = YTrimCmd = RTrimCmd = 0.0; GearCmd = GearPos = 1; // default to gear down BrakePos.resize(FGLGear::bgNumBrakeGroups); - TailhookPos = WingFoldPos = 0.0; + TailhookPos = WingFoldPos = 0.0; bind(); for (i=0;iGetName() << endl; + if (debug_lvl & 4) { + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + log << " Executing System Channel: " << SystemChannels[i]->GetName() << endl; + } ChannelRate = SystemChannels[i]->GetRate(); SystemChannels[i]->Execute(); } @@ -323,9 +327,10 @@ void FGFCS::SetThrottleCmd(int engineNum, double setting) ThrottleCmd[engineNum] = setting; } } else { - cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size() - << " engines exist, but attempted throttle command is for engine " - << engineNum << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::ERROR); + log << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size() + << " engines exist, but attempted throttle command is for engine " + << engineNum << endl; } } @@ -341,9 +346,10 @@ void FGFCS::SetThrottlePos(int engineNum, double setting) ThrottlePos[engineNum] = setting; } } else { - cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size() - << " engines exist, but attempted throttle position setting is for engine " - << engineNum << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::ERROR); + log << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size() + << " engines exist, but attempted throttle position setting is for engine " + << engineNum << endl; } } @@ -353,14 +359,16 @@ double FGFCS::GetThrottleCmd(int engineNum) const { if (engineNum < (int)ThrottlePos.size()) { if (engineNum < 0) { - cerr << "Cannot get throttle value for ALL engines" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::ERROR); + log << "Cannot get throttle value for ALL engines" << endl; } else { return ThrottleCmd[engineNum]; } } else { - cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size() - << " engines exist, but throttle setting for engine " << engineNum - << " is selected" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::ERROR); + log << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size() + << " engines exist, but throttle setting for engine " << engineNum + << " is selected" << endl; } return 0.0; } @@ -371,14 +379,16 @@ double FGFCS::GetThrottlePos(int engineNum) const { if (engineNum < (int)ThrottlePos.size()) { if (engineNum < 0) { - cerr << "Cannot get throttle value for ALL engines" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::ERROR); + log << "Cannot get throttle value for ALL engines" << endl; } else { return ThrottlePos[engineNum]; } } else { - cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size() - << " engines exist, but attempted throttle position setting is for engine " - << engineNum << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::ERROR); + log << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size() + << " engines exist, but attempted throttle position setting is for engine " + << engineNum << endl; } return 0.0; } @@ -491,14 +501,14 @@ bool FGFCS::Load(Element* document) Debug(2); Element* channel_element = document->FindElement("channel"); - + while (channel_element) { - + FGFCSChannel* newChannel = 0; string sOnOffProperty = channel_element->GetAttributeValue("execute"); string sChannelName = channel_element->GetAttributeValue("name"); - + if (!channel_element->GetAttributeValue("execrate").empty()) ChannelRate = channel_element->GetAttributeValueAsNumber("execrate"); else @@ -506,12 +516,13 @@ bool FGFCS::Load(Element* document) if (sOnOffProperty.length() > 0) { FGPropertyNode* OnOffPropertyNode = PropertyManager->GetNode(sOnOffProperty); - if (OnOffPropertyNode == 0) { - cerr << channel_element->ReadFrom() << highint << fgred - << "The On/Off property, " << sOnOffProperty << " specified for channel " - << channel_element->GetAttributeValue("name") << " is undefined or not " - << "understood. The simulation will abort" << reset << endl; - throw("Bad system definition"); + if (OnOffPropertyNode == nullptr) { + FGXMLLogging log(FDMExec->GetLogger(), channel_element, LogLevel::FATAL); + log << LogFormat::BOLD << LogFormat::RED + << "The On/Off property, " << sOnOffProperty << " specified for channel " + << channel_element->GetAttributeValue("name") << " is undefined or not " + << "understood. The simulation will abort" << LogFormat::RESET << endl; + throw BaseException(log.str()); } else newChannel = new FGFCSChannel(this, sChannelName, ChannelRate, OnOffPropertyNode); @@ -520,10 +531,12 @@ bool FGFCS::Load(Element* document) SystemChannels.push_back(newChannel); - if (debug_lvl > 0) - cout << endl << highint << fgblue << " Channel " - << normint << channel_element->GetAttributeValue("name") << reset << endl; - + if (debug_lvl > 0) { + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + log << endl << LogFormat::BOLD << LogFormat::BLUE << " Channel " + << LogFormat::NORMAL << channel_element->GetAttributeValue("name") << LogFormat::RESET << endl; + } + Element* component_element = channel_element->GetElement(); while (component_element) { try { @@ -554,9 +567,10 @@ bool FGFCS::Load(Element* document) // is equivalent to Element* c1_el = component_element->FindElement("c1"); if (!c1_el) { - cerr << component_element->ReadFrom(); - throw("INTEGRATOR component " + component_element->GetAttributeValue("name") - + " does not provide the parameter "); + FGXMLLogging log(FDMExec->GetLogger(), component_element, LogLevel::FATAL); + log << "INTEGRATOR component " << component_element->GetAttributeValue("name") + << " does not provide the parameter " << endl; + throw BaseException(log.str()); } c1_el->ChangeName("ki"); if (!c1_el->HasAttribute("type")) @@ -583,11 +597,13 @@ bool FGFCS::Load(Element* document) } else if (component_element->GetName() == string("linear_actuator")) { newChannel->Add(new FGLinearActuator(this, component_element)); } else { - cerr << "Unknown FCS component: " << component_element->GetName() << endl; + FGXMLLogging log(FDMExec->GetLogger(), component_element, LogLevel::ERROR); + log << "Unknown FCS component: " << component_element->GetName() << endl; } } catch(string& s) { - cerr << highint << fgred << endl << " " << s << endl; - cerr << reset << endl; + FGXMLLogging log(FDMExec->GetLogger(), component_element, LogLevel::ERROR); + log << LogFormat::BOLD << LogFormat::RED << endl << " " << s << endl; + log << LogFormat::RESET << endl; return false; } component_element = channel_element->GetNextElement(); @@ -817,13 +833,15 @@ void FGFCS::Debug(int from) if (debug_lvl <= 0) return; if (debug_lvl & 1) { // Standard console startup message output + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); if (from == 2) { // Loader - cout << endl << " " << Name << endl; + log << endl << " " << Name << endl; } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGFCS" << endl; - if (from == 1) cout << "Destroyed: FGFCS" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + if (from == 0) log << "Instantiated: FGFCS" << endl; + if (from == 1) log << "Destroyed: FGFCS" << endl; } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects } diff --git a/src/models/FGInertial.cpp b/src/models/FGInertial.cpp index 7ba20b3e13..d8dabe4e27 100644 --- a/src/models/FGInertial.cpp +++ b/src/models/FGInertial.cpp @@ -35,8 +35,10 @@ HISTORY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ +#include "FGFDMExec.h" #include "FGInertial.h" #include "input_output/FGXMLElement.h" +#include "input_output/FGLog.h" #include "GeographicLib/Geodesic.hpp" using namespace std; @@ -119,10 +121,11 @@ bool FGInertial::Load(Element* el) // Messages to warn the user about possible inconsistencies. if (debug_lvl > 0) { + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); if (a != b && J2 == 0.0) - cout << "Gravitational constant J2 is null for a non-spherical planet." << endl; + log << "Gravitational constant J2 is null for a non-spherical planet." << endl; if (a == b && J2 != 0.0) - cout << "Gravitational constant J2 is non-zero for a spherical planet." << endl; + log << "Gravitational constant J2 is non-zero for a spherical planet." << endl; } Debug(2); @@ -239,15 +242,16 @@ void FGInertial::SetAltitudeAGL(FGLocation& location, double altitudeAGL) void FGInertial::SetGravityType(int gt) { // Messages to warn the user about possible inconsistencies. + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); switch (gt) { case eGravType::gtStandard: if (a != b) - cout << "Warning: Standard gravity model has been set for a non-spherical planet" << endl; + log << "Standard gravity model has been set for a non-spherical planet" << endl; break; case eGravType::gtWGS84: if (J2 == 0.0) - cout << "Warning: WGS84 gravity model has been set without specifying the J2 gravitational constant." << endl; + log << "WGS84 gravity model has been set without specifying the J2 gravitational constant." << endl; } gravType = gt; @@ -287,19 +291,21 @@ void FGInertial::Debug(int from) if (debug_lvl <= 0) return; if (debug_lvl & 1) { // Standard console startup message output + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); if (from == 0) {} // Constructor if (from == 2) { // Loading - cout << endl << " Planet " << Name << endl; - cout << " Semi major axis: " << a << endl; - cout << " Semi minor axis: " << b << endl; - cout << " Rotation rate : " << scientific << vOmegaPlanet(eZ) << endl; - cout << " GM : " << GM << endl; - cout << " J2 : " << J2 << endl << defaultfloat << endl; + log << endl << " Planet " << Name << endl + << " Semi major axis: " << a << endl + << " Semi minor axis: " << b << endl + << " Rotation rate : " << scientific << vOmegaPlanet(eZ) << endl + << " GM : " << GM << endl + << " J2 : " << J2 << endl << defaultfloat << endl; } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGInertial" << endl; - if (from == 1) cout << "Destroyed: FGInertial" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + if (from == 0) log << "Instantiated: FGInertial" << endl; + if (from == 1) log << "Destroyed: FGInertial" << endl; } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects } diff --git a/src/models/FGInput.cpp b/src/models/FGInput.cpp index 1fe66c76e0..d8555aed24 100644 --- a/src/models/FGInput.cpp +++ b/src/models/FGInput.cpp @@ -43,6 +43,7 @@ INCLUDES #include "input_output/FGUDPInputSocket.h" #include "input_output/FGXMLFileRead.h" #include "input_output/FGModelLoader.h" +#include "input_output/FGLog.h" using namespace std; @@ -91,7 +92,10 @@ bool FGInput::Load(Element* el) string type = element->GetAttributeValue("type"); FGInputType* Input = 0; - if (debug_lvl > 0) cout << endl << " Input data set: " << idx << " " << endl; + if (debug_lvl > 0) { + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + log << endl << " Input data set: " << idx << " " << endl; + } type = to_upper(type); @@ -100,8 +104,8 @@ bool FGInput::Load(Element* el) } else if (type == "QTJSBSIM") { Input = new FGUDPInputSocket(FDMExec); } else if (type != string("NONE")) { - cerr << element->ReadFrom() - << "Unknown type of input specified in config file" << endl; + FGXMLLogging log(FDMExec->GetLogger(), element, LogLevel::ERROR); + log << "Unknown type of input specified in config file" << endl; } if (!Input) return false; @@ -153,14 +157,16 @@ 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()); + FGLogging log(FDMExec->GetLogger(), LogLevel::FATAL); + log << "Could not read directive file: " << fname << endl; + throw BaseException(log.str()); } bool result = Load(document); - if (!result) - cerr << endl << "Aircraft input element has problems in file " << fname << endl; + if (!result) { + FGLogging log(FDMExec->GetLogger(), LogLevel::ERROR); + log << endl << "Aircraft input element has problems in file " << fname << endl; + } return result; } @@ -229,8 +235,9 @@ void FGInput::Debug(int from) } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGInput" << endl; - if (from == 1) cout << "Destroyed: FGInput" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + if (from == 0) log << "Instantiated: FGInput" << endl; + if (from == 1) log << "Destroyed: FGInput" << endl; } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects } diff --git a/src/models/FGMassBalance.cpp b/src/models/FGMassBalance.cpp index bc30c6457a..e5a1ad9dba 100644 --- a/src/models/FGMassBalance.cpp +++ b/src/models/FGMassBalance.cpp @@ -43,6 +43,7 @@ INCLUDES #include "FGMassBalance.h" #include "FGFDMExec.h" #include "input_output/FGXMLElement.h" +#include "input_output/FGLog.h" using namespace std; @@ -268,11 +269,9 @@ void FGMassBalance::AddPointMass(Element* el) Element* loc_element = el->FindElement("location"); string pointmass_name = el->GetAttributeValue("name"); if (!loc_element) { - stringstream s; - s << el->ReadFrom() << "Pointmass " << pointmass_name - << " has no location."; - cerr << endl << s.str() << endl; - throw BaseException(s.str()); + FGXMLLogging log(FDMExec->GetLogger(), el, LogLevel::FATAL); + log << "Pointmass " << pointmass_name << " has no location." << endl; + throw BaseException(log.str()); } double w = el->FindElementValueAsNumberConvertTo("weight", "LBS"); @@ -451,45 +450,44 @@ void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager, void FGMassBalance::GetMassPropertiesReport(int i) { - cout << endl << fgblue << highint - << " Mass Properties Report (English units: lbf, in, slug-ft^2)" - << reset << endl; - cout << " " << underon << " Weight CG-X CG-Y" - << " CG-Z Ixx Iyy Izz" - << " Ixy Ixz Iyz" << underoff << endl; - cout.precision(1); - cout << highint << setw(34) << left << " Base Vehicle " << normint - << right << setw(12) << EmptyWeight - << setw(8) << vbaseXYZcg(eX) << setw(8) << vbaseXYZcg(eY) << setw(8) << vbaseXYZcg(eZ) - << setw(12) << baseJ(1,1) << setw(12) << baseJ(2,2) << setw(12) << baseJ(3,3) - << setw(12) << baseJ(1,2) << setw(12) << baseJ(1,3) << setw(12) << baseJ(2,3) << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::INFO); + log << endl << LogFormat::BLUE << LogFormat::BOLD + << " Mass Properties Report (English units: lbf, in, slug-ft^2)" + << LogFormat::RESET << endl; + log << " " << LogFormat::UNDERLINE_ON << " Weight CG-X CG-Y" + << " CG-Z Ixx Iyy Izz" + << " Ixy Ixz Iyz" << LogFormat::UNDERLINE_OFF << endl; + log << setprecision(1); + log << LogFormat::BOLD << setw(34) << left << " Base Vehicle " << normint + << right << setw(12) << EmptyWeight + << setw(8) << vbaseXYZcg(eX) << setw(8) << vbaseXYZcg(eY) << setw(8) << vbaseXYZcg(eZ) + << setw(12) << baseJ(1,1) << setw(12) << baseJ(2,2) << setw(12) << baseJ(3,3) + << setw(12) << baseJ(1,2) << setw(12) << baseJ(1,3) << setw(12) << baseJ(2,3) << endl; for (unsigned int i=0;iGetPointMassWeight(); - cout << highint << left << setw(4) << i << setw(30) << pm->GetName() << normint - << right << setw(12) << pmweight << setw(8) << pm->GetLocation()(eX) - << setw(8) << pm->GetLocation()(eY) << setw(8) << pm->GetLocation()(eZ) - << setw(12) << pm->GetPointMassMoI(1,1) << setw(12) << pm->GetPointMassMoI(2,2) << setw(12) << pm->GetPointMassMoI(3,3) - << setw(12) << pm->GetPointMassMoI(1,2) << setw(12) << pm->GetPointMassMoI(1,3) << setw(12) << pm->GetPointMassMoI(2,3) << endl; + log << LogFormat::BOLD << left << setw(4) << i << setw(30) << pm->GetName() << normint + << right << setw(12) << pmweight << setw(8) << pm->GetLocation()(eX) + << setw(8) << pm->GetLocation()(eY) << setw(8) << pm->GetLocation()(eZ) + << setw(12) << pm->GetPointMassMoI(1,1) << setw(12) << pm->GetPointMassMoI(2,2) << setw(12) << pm->GetPointMassMoI(3,3) + << setw(12) << pm->GetPointMassMoI(1,2) << setw(12) << pm->GetPointMassMoI(1,3) << setw(12) << pm->GetPointMassMoI(2,3) << endl; } - cout << FDMExec->GetPropulsionTankReport(); - - cout << " " << underon << setw(136) << " " << underoff << endl; - cout << highint << left << setw(30) << " Total: " << right << setw(14) << Weight - << setw(8) << vXYZcg(eX) - << setw(8) << vXYZcg(eY) - << setw(8) << vXYZcg(eZ) - << setw(12) << mJ(1,1) - << setw(12) << mJ(2,2) - << setw(12) << mJ(3,3) - << setw(12) << mJ(1,2) - << setw(12) << mJ(1,3) - << setw(12) << mJ(2,3) - << normint << endl; - - cout.setf(ios_base::fixed); + log << FDMExec->GetPropulsionTankReport(); + + log << " " << LogFormat::UNDERLINE_ON << setw(136) << " " << LogFormat::UNDERLINE_OFF << endl; + log << LogFormat::BOLD << left << setw(30) << " Total: " << right << setw(14) << Weight + << setw(8) << vXYZcg(eX) + << setw(8) << vXYZcg(eY) + << setw(8) << vXYZcg(eZ) + << setw(12) << mJ(1,1) + << setw(12) << mJ(2,2) + << setw(12) << mJ(3,3) + << setw(12) << mJ(1,2) + << setw(12) << mJ(1,3) + << setw(12) << mJ(2,3) + << LogFormat::NORMAL << endl; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -517,18 +515,19 @@ void FGMassBalance::Debug(int from) if (debug_lvl & 1) { // Standard console startup message output if (from == 2) { // Loading - cout << endl << " Mass and Balance:" << endl; - cout << " baseIxx: " << baseJ(1,1) << " slug-ft2" << endl; - cout << " baseIyy: " << baseJ(2,2) << " slug-ft2" << endl; - cout << " baseIzz: " << baseJ(3,3) << " slug-ft2" << endl; - cout << " baseIxy: " << baseJ(1,2) << " slug-ft2" << endl; - cout << " baseIxz: " << baseJ(1,3) << " slug-ft2" << endl; - cout << " baseIyz: " << baseJ(2,3) << " slug-ft2" << endl; - cout << " Empty Weight: " << EmptyWeight << " lbm" << endl; - cout << " CG (x, y, z): " << vbaseXYZcg << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + log << endl << " Mass and Balance:" << endl; + log << " baseIxx: " << baseJ(1,1) << " slug-ft2" << endl; + log << " baseIyy: " << baseJ(2,2) << " slug-ft2" << endl; + log << " baseIzz: " << baseJ(3,3) << " slug-ft2" << endl; + log << " baseIxy: " << baseJ(1,2) << " slug-ft2" << endl; + log << " baseIxz: " << baseJ(1,3) << " slug-ft2" << endl; + log << " baseIyz: " << baseJ(2,3) << " slug-ft2" << endl; + log << " Empty Weight: " << EmptyWeight << " lbm" << endl; + log << " CG (x, y, z): " << vbaseXYZcg << endl; // ToDo: Need to add point mass outputs here for (unsigned int i=0; iWeight << " lbs. at " + log << " Point Mass Object: " << PointMasses[i]->Weight << " lbs. at " << "X, Y, Z (in.): " << PointMasses[i]->Location(eX) << " " << PointMasses[i]->Location(eY) << " " << PointMasses[i]->Location(eZ) << endl; @@ -536,8 +535,9 @@ void FGMassBalance::Debug(int from) } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGMassBalance" << endl; - if (from == 1) cout << "Destroyed: FGMassBalance" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + if (from == 0) log << "Instantiated: FGMassBalance" << endl; + if (from == 1) log << "Destroyed: FGMassBalance" << endl; } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects } @@ -545,12 +545,13 @@ void FGMassBalance::Debug(int from) } if (debug_lvl & 16) { // Sanity checking if (from == 2) { + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); if (EmptyWeight <= 0.0 || EmptyWeight > 1e9) - cout << "MassBalance::EmptyWeight out of bounds: " << EmptyWeight << endl; + log << "MassBalance::EmptyWeight out of bounds: " << EmptyWeight << endl; if (Weight <= 0.0 || Weight > 1e9) - cout << "MassBalance::Weight out of bounds: " << Weight << endl; + log << "MassBalance::Weight out of bounds: " << Weight << endl; if (Mass <= 0.0 || Mass > 1e9) - cout << "MassBalance::Mass out of bounds: " << Mass << endl; + log << "MassBalance::Mass out of bounds: " << Mass << endl; } } if (debug_lvl & 64) { diff --git a/src/models/FGModel.cpp b/src/models/FGModel.cpp index 93e804481e..acdec8dab5 100644 --- a/src/models/FGModel.cpp +++ b/src/models/FGModel.cpp @@ -41,6 +41,7 @@ INCLUDES #include "FGModel.h" #include "FGFDMExec.h" #include "input_output/FGModelLoader.h" +#include "input_output/FGLog.h" using namespace std; @@ -66,14 +67,14 @@ FGModel::FGModel(FGFDMExec* fdmex) exe_ctr = 1; rate = 1; - if (debug_lvl & 2) cout << " FGModel Base Class" << endl; + Debug(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGModel::~FGModel() { - if (debug_lvl & 2) cout << "Destroyed: FGModel" << endl; + Debug(1); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -88,14 +89,14 @@ bool FGModel::InitModel(void) bool FGModel::Run(bool Holding) { - if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl; - if (rate == 1) return false; // Fast exit if nothing to do if (exe_ctr >= rate) exe_ctr = 0; if (exe_ctr++ == 1) return false; else return true; + + Debug(2); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -115,9 +116,9 @@ bool FGModel::Upload(Element* el, bool preLoad) if (!document) return false; if (document->GetName() != el->GetName()) { - cerr << el->ReadFrom() - << " Read model '" << document->GetName() - << "' while expecting model '" << el->GetName() << "'" << endl; + FGXMLLogging log(FDMExec->GetLogger(), el, LogLevel::ERROR); + log << " Read model '" << document->GetName() + << "' while expecting model '" << el->GetName() << "'" << endl; return false; } @@ -177,10 +178,13 @@ void FGModel::Debug(int from) } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGModel" << endl; - if (from == 1) cout << "Destroyed: FGModel" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + if (from == 0) log << "Instantiated: FGModel" << endl; + if (from == 1) log << "Destroyed: FGModel" << endl; } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + log << "Entering Run() for model " << Name << endl; } if (debug_lvl & 8 ) { // Runtime state variables } diff --git a/src/models/FGModel.h b/src/models/FGModel.h index ac0840ade2..752ef4f35b 100644 --- a/src/models/FGModel.h +++ b/src/models/FGModel.h @@ -90,12 +90,12 @@ class JSBSIM_API FGModel : public FGModelFunctions /// Set the ouput rate for the model in frames void SetRate(unsigned int tt) {rate = tt;} /// Get the output rate for the model in frames - unsigned int GetRate(void) {return rate;} - FGFDMExec* GetExec(void) {return FDMExec;} + unsigned int GetRate(void) const { return rate; } + FGFDMExec* GetExec(void) const { return FDMExec; } void SetPropertyManager(std::shared_ptr fgpm) { PropertyManager=fgpm;} virtual SGPath FindFullPathName(const SGPath& path) const; - const std::string& GetName(void) { return Name; } + const std::string& GetName(void) const { return Name; } virtual bool Load(Element* el) { return true; } protected: diff --git a/src/models/FGPropagate.cpp b/src/models/FGPropagate.cpp index bd41fa311e..c307b5c9f2 100644 --- a/src/models/FGPropagate.cpp +++ b/src/models/FGPropagate.cpp @@ -70,6 +70,7 @@ INCLUDES #include "FGFDMExec.h" #include "simgear/io/iostreams/sgstream.hxx" #include "FGInertial.h" +#include "input_output/FGLog.h" using namespace std; @@ -702,35 +703,36 @@ FGColumnVector3 FGPropagate::GetEulerDeg(void) const void FGPropagate::DumpState(void) { - cout << endl; - cout << fgblue - << "------------------------------------------------------------------" << reset << endl; - cout << highint - << "State Report at sim time: " << FDMExec->GetSimTime() << " seconds" << reset << endl; - cout << " " << underon - << "Position" << underoff << endl; - cout << " ECI: " << VState.vInertialPosition.Dump(", ") << " (x,y,z, in ft)" << endl; - cout << " ECEF: " << VState.vLocation << " (x,y,z, in ft)" << endl; - cout << " Local: " << VState.vLocation.GetGeodLatitudeDeg() - << ", " << VState.vLocation.GetLongitudeDeg() - << ", " << GetAltitudeASL() << " (geodetic lat, lon, alt ASL in deg and ft)" << endl; - - cout << endl << " " << underon - << "Orientation" << underoff << endl; - cout << " ECI: " << VState.qAttitudeECI.GetEulerDeg().Dump(", ") << " (phi, theta, psi in deg)" << endl; - cout << " Local: " << VState.qAttitudeLocal.GetEulerDeg().Dump(", ") << " (phi, theta, psi in deg)" << endl; - - cout << endl << " " << underon - << "Velocity" << underoff << endl; - cout << " ECI: " << VState.vInertialVelocity.Dump(", ") << " (x,y,z in ft/s)" << endl; - cout << " ECEF: " << (Tb2ec * VState.vUVW).Dump(", ") << " (x,y,z in ft/s)" << endl; - cout << " Local: " << GetVel() << " (n,e,d in ft/sec)" << endl; - cout << " Body: " << GetUVW() << " (u,v,w in ft/sec)" << endl; - - cout << endl << " " << underon - << "Body Rates (relative to given frame, expressed in body frame)" << underoff << endl; - cout << " ECI: " << (VState.vPQRi*radtodeg).Dump(", ") << " (p,q,r in deg/s)" << endl; - cout << " ECEF: " << (VState.vPQR*radtodeg).Dump(", ") << " (p,q,r in deg/s)" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::INFO); + log << endl; + log << LogFormat::BLUE + << "------------------------------------------------------------------" << LogFormat::RESET << endl; + log << LogFormat::BOLD + << "State Report at sim time: " << FDMExec->GetSimTime() << " seconds" << LogFormat::RESET << endl; + log << " " << LogFormat::UNDERLINE_ON + << "Position" << LogFormat::UNDERLINE_OFF << endl; + log << " ECI: " << VState.vInertialPosition.Dump(", ") << " (x,y,z, in ft)" << endl; + log << " ECEF: " << VState.vLocation << " (x,y,z, in ft)" << endl; + log << " Local: " << VState.vLocation.GetGeodLatitudeDeg() + << ", " << VState.vLocation.GetLongitudeDeg() + << ", " << GetAltitudeASL() << " (geodetic lat, lon, alt ASL in deg and ft)" << endl; + + log << endl << " " << LogFormat::UNDERLINE_ON + << "Orientation" << LogFormat::UNDERLINE_OFF << endl; + log << " ECI: " << VState.qAttitudeECI.GetEulerDeg().Dump(", ") << " (phi, theta, psi in deg)" << endl; + log << " Local: " << VState.qAttitudeLocal.GetEulerDeg().Dump(", ") << " (phi, theta, psi in deg)" << endl; + + log << endl << " " << LogFormat::UNDERLINE_ON + << "Velocity" << LogFormat::UNDERLINE_OFF << endl; + log << " ECI: " << VState.vInertialVelocity.Dump(", ") << " (x,y,z in ft/s)" << endl; + log << " ECEF: " << (Tb2ec * VState.vUVW).Dump(", ") << " (x,y,z in ft/s)" << endl; + log << " Local: " << GetVel() << " (n,e,d in ft/sec)" << endl; + log << " Body: " << GetUVW() << " (u,v,w in ft/sec)" << endl; + + log << endl << " " << LogFormat::UNDERLINE_ON + << "Body Rates (relative to given frame, expressed in body frame)" << LogFormat::UNDERLINE_OFF << endl; + log << " ECI: " << (VState.vPQRi * radtodeg).Dump(", ") << " (p,q,r in deg/s)" << endl; + log << " ECEF: " << (VState.vPQR * radtodeg).Dump(", ") << " (p,q,r in deg/s)" << endl; } //****************************************************************************** @@ -767,8 +769,9 @@ void FGPropagate::WriteStateFile(int num) outfile << "" << endl; outfile.close(); } else { - cerr << "Could not open and/or write the state to the initial conditions file: " - << path << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::ERROR); + log << "Could not open and/or write the state to the initial conditions file: " + << path << endl; } break; case 2: @@ -804,12 +807,14 @@ void FGPropagate::WriteStateFile(int num) outfile << "" << endl; outfile.close(); } else { - cerr << "Could not open and/or write the state to the initial conditions file: " - << path << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::ERROR); + log << "Could not open and/or write the state to the initial conditions file: " + << path << endl; } break; default: - cerr << "When writing a state file, the supplied value must be 1 or 2 for the version number of the resulting IC file" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::ERROR); + log << "When writing a state file, the supplied value must be 1 or 2 for the version number of the resulting IC file" << endl; } } @@ -932,121 +937,120 @@ void FGPropagate::Debug(int from) } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGPropagate" << endl; - if (from == 1) cout << "Destroyed: FGPropagate" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + if (from == 0) log << "Instantiated: FGPropagate" << endl; + if (from == 1) log << "Destroyed: FGPropagate" << endl; } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects } if (debug_lvl & 8 && from == 2) { // Runtime state variables - cout << endl << fgblue << highint << left - << " Propagation Report (English units: ft, degrees) at simulation time " << FDMExec->GetSimTime() << " seconds" - << reset << endl; - cout << endl; - cout << highint << " Earth Position Angle (deg): " << setw(8) << setprecision(3) << reset - << GetEarthPositionAngleDeg() << endl; - cout << endl; - cout << highint << " Body velocity (ft/sec): " << setw(8) << setprecision(3) << reset << VState.vUVW << endl; - cout << highint << " Local velocity (ft/sec): " << setw(8) << setprecision(3) << reset << vVel << endl; - cout << highint << " Inertial velocity (ft/sec): " << setw(8) << setprecision(3) << reset << VState.vInertialVelocity << endl; - cout << highint << " Inertial Position (ft): " << setw(10) << setprecision(3) << reset << VState.vInertialPosition << endl; - cout << highint << " Latitude (deg): " << setw(8) << setprecision(3) << reset << VState.vLocation.GetLatitudeDeg() << endl; - cout << highint << " Longitude (deg): " << setw(8) << setprecision(3) << reset << VState.vLocation.GetLongitudeDeg() << endl; - cout << highint << " Altitude ASL (ft): " << setw(8) << setprecision(3) << reset << GetAltitudeASL() << endl; -// cout << highint << " Acceleration (NED, ft/sec^2): " << setw(8) << setprecision(3) << reset << Tb2l*GetUVWdot() << endl; - cout << endl; - cout << highint << " Matrix ECEF to Body (Orientation of Body with respect to ECEF): " - << reset << endl << Tec2b.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tec2b.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Body to ECEF (Orientation of ECEF with respect to Body):" - << reset << endl << Tb2ec.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tb2ec.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Local to Body (Orientation of Body with respect to Local):" - << reset << endl << Tl2b.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tl2b.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Body to Local (Orientation of Local with respect to Body):" - << reset << endl << Tb2l.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tb2l.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Local to ECEF (Orientation of ECEF with respect to Local):" - << reset << endl << Tl2ec.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tl2ec.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix ECEF to Local (Orientation of Local with respect to ECEF):" - << reset << endl << Tec2l.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tec2l.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix ECEF to Inertial (Orientation of Inertial with respect to ECEF):" - << reset << endl << Tec2i.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tec2i.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Inertial to ECEF (Orientation of ECEF with respect to Inertial):" - << reset << endl << Ti2ec.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Ti2ec.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Inertial to Body (Orientation of Body with respect to Inertial):" - << reset << endl << Ti2b.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Ti2b.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Body to Inertial (Orientation of Inertial with respect to Body):" - << reset << endl << Tb2i.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tb2i.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Inertial to Local (Orientation of Local with respect to Inertial):" - << reset << endl << Ti2l.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Ti2l.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << highint << " Matrix Local to Inertial (Orientation of Inertial with respect to Local):" - << reset << endl << Tl2i.Dump("\t", " ") << endl; - cout << highint << " Associated Euler angles (deg): " << setw(8) - << setprecision(3) << reset << (Tl2i.GetQuaternion().GetEuler()*radtodeg) - << endl << endl; - - cout << setprecision(6); // reset the output stream + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + log << endl << LogFormat::BLUE << LogFormat::BOLD << left + << " Propagation Report (English units: ft, degrees) at simulation time " << FDMExec->GetSimTime() << " seconds" + << LogFormat::RESET << endl; + log << endl; + log << LogFormat::BOLD << " Earth Position Angle (deg): " << setw(8) << setprecision(3) << LogFormat::RESET + << GetEarthPositionAngleDeg() << endl; + log << endl; + log << LogFormat::BOLD << " Body velocity (ft/sec): " << setw(8) << setprecision(3) << LogFormat::RESET << VState.vUVW << endl; + log << LogFormat::BOLD << " Local velocity (ft/sec): " << setw(8) << setprecision(3) << LogFormat::RESET << vVel << endl; + log << LogFormat::BOLD << " Inertial velocity (ft/sec): " << setw(8) << setprecision(3) << LogFormat::RESET << VState.vInertialVelocity << endl; + log << LogFormat::BOLD << " Inertial Position (ft): " << setw(10) << setprecision(3) << LogFormat::RESET << VState.vInertialPosition << endl; + log << LogFormat::BOLD << " Latitude (deg): " << setw(8) << setprecision(3) << LogFormat::RESET << VState.vLocation.GetLatitudeDeg() << endl; + log << LogFormat::BOLD << " Longitude (deg): " << setw(8) << setprecision(3) << LogFormat::RESET << VState.vLocation.GetLongitudeDeg() << endl; + log << LogFormat::BOLD << " Altitude ASL (ft): " << setw(8) << setprecision(3) << LogFormat::RESET << GetAltitudeASL() << endl; + // log << LogFormat::BOLD << " Acceleration (NED, ft/sec^2): " << setw(8) << setprecision(3) << LogFormat::RESET << Tb2l*GetUVWdot() << endl; + log << endl; + log << LogFormat::BOLD << " Matrix ECEF to Body (Orientation of Body with respect to ECEF): " + << LogFormat::RESET << endl << Tec2b.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Tec2b.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << LogFormat::BOLD << " Matrix Body to ECEF (Orientation of ECEF with respect to Body):" + << LogFormat::RESET << endl << Tb2ec.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Tb2ec.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << LogFormat::BOLD << " Matrix Local to Body (Orientation of Body with respect to Local):" + << LogFormat::RESET << endl << Tl2b.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Tl2b.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << LogFormat::BOLD << " Matrix Body to Local (Orientation of Local with respect to Body):" + << LogFormat::RESET << endl << Tb2l.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Tb2l.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << LogFormat::BOLD << " Matrix Local to ECEF (Orientation of ECEF with respect to Local):" + << LogFormat::RESET << endl << Tl2ec.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Tl2ec.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << LogFormat::BOLD << " Matrix ECEF to Local (Orientation of Local with respect to ECEF):" + << LogFormat::RESET << endl << Tec2l.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Tec2l.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << LogFormat::BOLD << " Matrix ECEF to Inertial (Orientation of Inertial with respect to ECEF):" + << LogFormat::RESET << endl << Tec2i.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Tec2i.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << LogFormat::BOLD << " Matrix Inertial to ECEF (Orientation of ECEF with respect to Inertial):" + << LogFormat::RESET << endl << Ti2ec.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Ti2ec.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << LogFormat::BOLD << " Matrix Inertial to Body (Orientation of Body with respect to Inertial):" + << LogFormat::RESET << endl << Ti2b.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Ti2b.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << LogFormat::BOLD << " Matrix Body to Inertial (Orientation of Inertial with respect to Body):" + << LogFormat::RESET << endl << Tb2i.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Tb2i.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << LogFormat::BOLD << " Matrix Inertial to Local (Orientation of Local with respect to Inertial):" + << LogFormat::RESET << endl << Ti2l.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Ti2l.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << LogFormat::BOLD << " Matrix Local to Inertial (Orientation of Inertial with respect to Local):" + << LogFormat::RESET << endl << Tl2i.Dump("\t", " ") << endl; + log << LogFormat::BOLD << " Associated Euler angles (deg): " << setw(8) + << setprecision(3) << LogFormat::RESET << (Tl2i.GetQuaternion().GetEuler()*radtodeg) + << endl << endl; + + log << setprecision(6); // reset the output stream } if (debug_lvl & 16) { // Sanity checking if (from == 2) { // State sanity checking if (fabs(VState.vPQR.Magnitude()) > 1000.0) { - stringstream s; - s << "Vehicle rotation rate is excessive (>1000 rad/sec): " << VState.vPQR.Magnitude(); - cerr << endl << s.str() << endl; - throw BaseException(s.str()); + FGLogging log(FDMExec->GetLogger(), LogLevel::FATAL); + log << "Vehicle rotation rate is excessive (>1000 rad/sec): " << VState.vPQR.Magnitude() << endl; + throw BaseException(log.str()); } if (fabs(VState.vUVW.Magnitude()) > 1.0e10) { - stringstream s; - s << "Vehicle velocity is excessive (>1e10 ft/sec): " << VState.vUVW.Magnitude(); - cerr << endl << s.str() << endl; - throw BaseException(s.str()); + FGLogging log(FDMExec->GetLogger(), LogLevel::FATAL); + log << "Vehicle velocity is excessive (>1e10 ft/sec): " << VState.vUVW.Magnitude() << endl; + throw BaseException(log.str()); } if (fabs(GetDistanceAGL()) > 1e10) { - stringstream s; - s << "Vehicle altitude is excessive (>1e10 ft): " << GetDistanceAGL(); - cerr << endl << s.str() << endl; - throw BaseException(s.str()); + FGLogging log(FDMExec->GetLogger(), LogLevel::FATAL); + log << "Vehicle altitude is excessive (>1e10 ft): " << GetDistanceAGL() << endl; + throw BaseException(log.str()); } } } diff --git a/src/models/atmosphere/FGStandardAtmosphere.cpp b/src/models/atmosphere/FGStandardAtmosphere.cpp index d9e812d610..f2c4f395ec 100644 --- a/src/models/atmosphere/FGStandardAtmosphere.cpp +++ b/src/models/atmosphere/FGStandardAtmosphere.cpp @@ -49,6 +49,7 @@ INCLUDES #include "FGFDMExec.h" #include "FGStandardAtmosphere.h" +#include "input_output/FGLog.h" namespace JSBSim { @@ -361,9 +362,10 @@ void FGStandardAtmosphere::SetTemperatureBias(eTemperature unit, double t) // temperature lower than the lowest known temperature in the universe if (minStdAtmosphereTemp + TemperatureBias < minUniverseTemperature) { double minBias = minUniverseTemperature - minStdAtmosphereTemp; - cerr << "The temperature bias " << TemperatureBias << " R is too low. " - << "It could result in temperatures below the absolute zero." << endl - << "Temperature bias is therefore capped to " << minBias << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); + log << "The temperature bias " << TemperatureBias << " R is too low. " + << "It could result in temperatures below the absolute zero." << endl + << "Temperature bias is therefore capped to " << minBias << endl; TemperatureBias = minBias; } @@ -411,9 +413,10 @@ void FGStandardAtmosphere::SetTemperatureGradedDelta(double deltemp, double h, e deltemp *= 1.80; // If temp delta "t" is given in metric, scale up to English if (deltemp <= minDeltaTemperature) { - cerr << "The temperature delta " << deltemp << " R is too low. " - << "It could result in temperatures below the absolute zero." << endl - << "Temperature delta is therefore capped to " << minDeltaTemperature << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); + log << "The temperature delta " << deltemp << " R is too low. " + << "It could result in temperatures below the absolute zero." << endl + << "Temperature delta is therefore capped to " << minDeltaTemperature << endl; deltemp = minDeltaTemperature; } @@ -429,15 +432,16 @@ void FGStandardAtmosphere::SetTemperatureGradedDelta(double deltemp, double h, e void FGStandardAtmosphere::PrintStandardAtmosphereTable() { - std::cout << "Altitude (ft) Temp (F) Pressure (psf) Density (sl/ft3)" << std::endl; - std::cout << "------------- -------- -------------- ----------------" << std::endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::INFO); + log << "Altitude (ft) Temp (F) Pressure (psf) Density (sl/ft3)" << std::endl; + log << "------------- -------- -------------- ----------------" << std::endl; for (int i=0; i<280000; i+=1000) { Calculate(i); - std::cout << std::setw(12) << std::setprecision(2) << i - << " " << std::setw(9) << std::setprecision(2) << Temperature - 459.67 - << " " << std::setw(13) << std::setprecision(4) << Pressure - << " " << std::setw(18) << std::setprecision(8) << Density - << std::endl; + log << std::setw(12) << std::setprecision(2) << i + << " " << std::setw(9) << std::setprecision(2) << Temperature - 459.67 + << " " << std::setw(13) << std::setprecision(4) << Pressure + << " " << std::setw(18) << std::setprecision(8) << Density + << std::endl; } // Re-execute the Run() method to reset the calculated values @@ -620,9 +624,10 @@ void FGStandardAtmosphere::SetDewPoint(eTemperature unit, double dewpoint) constexpr double minDewPoint = -CelsiusToRankine(c) + 1.0; if (dewPoint_R <= minDewPoint) { - cerr << "The dew point temperature " << dewPoint_R << " is lower than " - << minDewPoint << " R." << endl - << "Dew point is therefore capped to " << minDewPoint << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); + log << "The dew point temperature " << dewPoint_R << " is lower than " + << minDewPoint << " R." << endl + << "Dew point is therefore capped to " << minDewPoint << endl; dewPoint_R = minDewPoint; } @@ -631,8 +636,9 @@ void FGStandardAtmosphere::SetDewPoint(eTemperature unit, double dewpoint) double finalizedDewPoint = GetDewPoint(eRankine); if (finalizedDewPoint < dewPoint_R) { - cerr << "Dew point temperature has been capped to " << finalizedDewPoint - << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); + log << "Dew point temperature has been capped to " << finalizedDewPoint + << endl; } } @@ -660,13 +666,15 @@ void FGStandardAtmosphere::SetVaporPressure(ePressure unit, double Pa) double altitude = CalculatePressureAltitude(Pressure, 0.0); double VaporPressure = ConvertToPSF(Pa, unit); if (VaporPressure < 0.0) { - cerr << "The vapor pressure cannot be negative." << endl - << "Vapor pressure is set to 0.0" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); + log << "The vapor pressure cannot be negative." << endl + << "Vapor pressure is set to 0.0" << endl; VaporPressure = 0.0; } else if (VaporPressure >= Pressure) { - cerr << "The vapor pressure " << VaporPressure - << " PSF is higher than the ambient pressure." << endl - << "Vapor pressure is therefore capped to " << Pressure-1.0 << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); + log << "The vapor pressure " << VaporPressure + << " PSF is higher than the ambient pressure." << endl + << "Vapor pressure is therefore capped to " << Pressure-1.0 << endl; VaporPressure = Pressure - 1.0; } VaporMassFraction = Rdry * VaporPressure / (Rwater * (Pressure - VaporPressure)); @@ -701,12 +709,14 @@ double FGStandardAtmosphere::GetRelativeHumidity(void) const void FGStandardAtmosphere::SetRelativeHumidity(double RH) { if (RH < 0.0) { - cerr << "The relative humidity cannot be negative." << endl - << "Relative humidity is set to 0%" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); + log << "The relative humidity cannot be negative." << endl + << "Relative humidity is set to 0%" << endl; RH = 0.0; } else if (RH > 100.0) { - cerr << "The relative humidity cannot be higher than 100%." << endl - << "Relative humidity is set to 100%" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); + log << "The relative humidity cannot be higher than 100%." << endl + << "Relative humidity is set to 100%" << endl; RH = 100.0; } @@ -730,8 +740,9 @@ void FGStandardAtmosphere::SetVaporMassFractionPPM(double frac) ValidateVaporMassFraction(altitude); if (fabs(VaporMassFraction*1E6-frac)>1E-2) { - cerr << "The vapor mass fraction " << frac << " has been capped to " - << VaporMassFraction*1E6 << "PPM." << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::WARN); + log << "The vapor mass fraction " << frac << " has been capped to " + << VaporMassFraction*1E6 << "PPM." << endl; } } @@ -794,8 +805,9 @@ void FGStandardAtmosphere::Debug(int from) } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) std::cout << "Instantiated: FGStandardAtmosphere" << std::endl; - if (from == 1) std::cout << "Destroyed: FGStandardAtmosphere" << std::endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + if (from == 0) log << "Instantiated: FGStandardAtmosphere" << std::endl; + if (from == 1) log << "Destroyed: FGStandardAtmosphere" << std::endl; } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects } diff --git a/src/models/atmosphere/FGWinds.cpp b/src/models/atmosphere/FGWinds.cpp index 62f18bcc23..0efdc3357c 100644 --- a/src/models/atmosphere/FGWinds.cpp +++ b/src/models/atmosphere/FGWinds.cpp @@ -46,6 +46,7 @@ INCLUDES #include "FGWinds.h" #include "FGFDMExec.h" #include "math/FGTable.h" +#include "input_output/FGLog.h" using namespace std; @@ -594,8 +595,9 @@ void FGWinds::Debug(int from) } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGWinds" << endl; - if (from == 1) cout << "Destroyed: FGWinds" << endl; + FGLogging log(FDMExec->GetLogger(), LogLevel::DEBUG); + if (from == 0) log << "Instantiated: FGWinds" << endl; + if (from == 1) log << "Destroyed: FGWinds" << endl; } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects }