JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
FGOutput.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Module: FGOutput.cpp
4  Author: Jon Berndt
5  Date started: 12/02/98
6  Purpose: Manage output of sim parameters to file, stdout or socket
7  Called by: FGSimExec
8 
9  ------------- Copyright (C) 1999 Jon S. Berndt (jon@jsbsim.org) -------------
10 
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU Lesser General Public License as published by the Free
13  Software Foundation; either version 2 of the License, or (at your option) any
14  later version.
15 
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19  details.
20 
21  You should have received a copy of the GNU Lesser General Public License along
22  with this program; if not, write to the Free Software Foundation, Inc., 59
23  Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25  Further information about the GNU Lesser General Public License can also be
26  found on the world wide web at http://www.gnu.org.
27 
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 This is the place where you create output routines to dump data for perusal
31 later.
32 
33 HISTORY
34 --------------------------------------------------------------------------------
35 12/02/98 JSB Created
36 11/09/07 HDW Added FlightGear Socket Interface
37 
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39 INCLUDES
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
41 
42 #include "FGOutput.h"
43 #include "input_output/FGOutputTextFile.h"
44 #include "input_output/FGOutputFG.h"
45 #include "input_output/FGXMLFileRead.h"
46 #include "input_output/FGModelLoader.h"
47 
48 using namespace std;
49 
50 namespace JSBSim {
51 
52 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 CLASS IMPLEMENTATION
54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
55 
56 FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex)
57 {
58  typedef int (FGOutput::*iOPV)(void) const;
59 
60  Name = "FGOutput";
61  enabled = true;
62 
63  PropertyManager->Tie("simulation/force-output", this, (iOPV)0, &FGOutput::ForceOutput);
64 
65  Debug(0);
66 }
67 
68 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 
70 FGOutput::~FGOutput()
71 {
72  for (auto output: OutputTypes)
73  delete output;
74 
75  Debug(1);
76 }
77 
78 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 
81 {
82  bool ret = false;
83 
84  if (!FGModel::InitModel()) return false;
85 
86  for (auto output: OutputTypes)
87  ret &= output->InitModel();
88 
89  return ret;
90 }
91 
92 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93 
94 bool FGOutput::Run(bool Holding)
95 {
96  if (FDMExec->GetTrimStatus()) return true;
97  if (FGModel::Run(Holding)) return true;
98  if (Holding) return false;
99  if (!enabled) return true;
100 
101  for (auto output: OutputTypes)
102  output->Run();
103 
104  return false;
105 }
106 
107 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108 
109 void FGOutput::Print(void)
110 {
111  for (auto output: OutputTypes)
112  output->Print();
113 }
114 
115 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116 
118 {
119  for (auto output: OutputTypes)
120  output->SetStartNewOutput();
121 }
122 
123 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
124 
125 bool FGOutput::Toggle(int idx)
126 {
127  if (idx >= (int)0 && idx < (int)OutputTypes.size())
128  return OutputTypes[idx]->Toggle();
129 
130  return false;
131 }
132 
133 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134 
135 void FGOutput::SetRateHz(double rate)
136 {
137  for (auto output: OutputTypes)
138  output->SetRateHz(rate);
139 }
140 
141 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 
144 {
145  if (idx >= (int)0 && idx < (int)OutputTypes.size())
146  OutputTypes[idx]->Print();
147 }
148 
149 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150 
151 bool FGOutput::SetOutputName(unsigned int idx, const std::string& name)
152 {
153  if (idx >= OutputTypes.size()) return false;
154 
155  OutputTypes[idx]->SetOutputName(name);
156  return true;
157 }
158 
159 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
160 
161 string FGOutput::GetOutputName(unsigned int idx) const
162 {
163  string name;
164 
165  if (idx < OutputTypes.size())
166  name = OutputTypes[idx]->GetOutputName();
167  return name;
168 }
169 
170 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171 
172 bool FGOutput::SetDirectivesFile(const SGPath& fname)
173 {
175  Element* document = XMLFile.LoadXMLDocument(fname);
176  if (!document) {
177  stringstream s;
178  s << "Could not read directive file: " << fname;
179  throw BaseException(s.str());
180  }
181 
182  bool result = Load(document);
183  if (!result)
184  cerr << endl << "Aircraft output element has problems in file " << fname << endl;
185 
186  return result;
187 }
188 
189 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190 
191 bool FGOutput::Load(int subSystems, std::string protocol, std::string type,
192  std::string port, std::string name, double outRate,
193  std::vector<FGPropertyNode_ptr> & outputProperties)
194 {
195  size_t idx = OutputTypes.size();
196  FGOutputType* Output = 0;
197 
198  if (debug_lvl > 0) cout << endl << " Output data set: " << idx << endl;
199 
200  type = to_upper(type);
201 
202  if (type == "CSV") {
203  FGOutputTextFile* OutputTextFile = new FGOutputTextFile(FDMExec);
204  OutputTextFile->SetDelimiter(",");
205  Output = OutputTextFile;
206  } else if (type == "TABULAR") {
207  FGOutputTextFile* OutputTextFile = new FGOutputTextFile(FDMExec);
208  OutputTextFile->SetDelimiter("\t");
209  Output = OutputTextFile;
210  } else if (type == "SOCKET") {
211  Output = new FGOutputSocket(FDMExec);
212  name += ":" + port + "/" + protocol;
213  } else if (type == "FLIGHTGEAR") {
214  Output = new FGOutputFG(FDMExec);
215  name += ":" + port + "/" + protocol;
216  } else if (type == "TERMINAL") {
217  // Not done yet
218  } else if (type != string("NONE")) {
219  cerr << "Unknown type of output specified in config file" << endl;
220  }
221 
222  if (!Output) return false;
223 
224  Output->SetIdx(idx);
225  Output->SetOutputName(name);
226  Output->SetRateHz(outRate);
227  Output->SetSubSystems(subSystems);
228  Output->SetOutputProperties(outputProperties);
229 
230  OutputTypes.push_back(Output);
231 
232  Debug(2);
233  return true;
234 }
235 
236 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237 
238 bool FGOutput::Load(Element* document, const SGPath& dir)
239 {
240  // Optional path to use for included files
241  includePath = dir;
242 
243  // Perform base class Pre-Load
244  if (!FGModel::Upload(document, false))
245  return false;
246 
247  size_t idx = OutputTypes.size();
248  string type = document->GetAttributeValue("type");
249  FGOutputType* Output = 0;
250 
251  if (debug_lvl > 0) cout << endl << " Output data set: " << idx << " " << endl;
252 
253  type = to_upper(type);
254 
255  if (type == "CSV") {
256  Output = new FGOutputTextFile(FDMExec);
257  } else if (type == "TABULAR") {
258  Output = new FGOutputTextFile(FDMExec);
259  } else if (type == "SOCKET") {
260  Output = new FGOutputSocket(FDMExec);
261  } else if (type == "FLIGHTGEAR") {
262  Output = new FGOutputFG(FDMExec);
263  } else if (type == "TERMINAL") {
264  // Not done yet
265  } else if (type != string("NONE")) {
266  cerr << "Unknown type of output specified in config file" << endl;
267  }
268 
269  if (!Output) return false;
270 
271  Output->SetIdx(idx);
272  Output->PreLoad(document, FDMExec);
273  Output->Load(document);
274  Output->PostLoad(document, FDMExec);
275 
276  OutputTypes.push_back(Output);
277 
278  Debug(2);
279  return true;
280 }
281 
282 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
283 
284 SGPath FGOutput::FindFullPathName(const SGPath& path) const
285 {
286  // Check optional include path if set
287  if (!includePath.isNull()) {
288  SGPath name = CheckPathName(includePath, path);
289  if (!name.isNull()) return name;
290  }
291 
292  return FGModel::FindFullPathName(path);
293 }
294 
295 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 // The bitmasked value choices are as follows:
297 // unset: In this case (the default) JSBSim would only print
298 // out the normally expected messages, essentially echoing
299 // the config files as they are read. If the environment
300 // variable is not set, debug_lvl is set to 1 internally
301 // 0: This requests JSBSim not to output any messages
302 // whatsoever.
303 // 1: This value explicity requests the normal JSBSim
304 // startup messages
305 // 2: This value asks for a message to be printed out when
306 // a class is instantiated
307 // 4: When this value is set, a message is displayed when a
308 // FGModel object executes its Run() method
309 // 8: When this value is set, various runtime state variables
310 // are printed out periodically
311 // 16: When set various parameters are sanity checked and
312 // a message is printed out when they go out of bounds
313 
314 void FGOutput::Debug(int from)
315 {
316  if (debug_lvl <= 0) return;
317 
318  if (debug_lvl & 1) { // Standard console startup message output
319  if (from == 0) { // Constructor
320 
321  }
322  if (from == 2) {
323  }
324  }
325  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
326  if (from == 0) cout << "Instantiated: FGOutput" << endl;
327  if (from == 1) cout << "Destroyed: FGOutput" << endl;
328  }
329  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
330  }
331  if (debug_lvl & 8 ) { // Runtime state variables
332  }
333  if (debug_lvl & 16) { // Sanity checking
334  }
335  if (debug_lvl & 64) {
336  if (from == 0) { // Constructor
337  }
338  }
339 }
340 }
JSBSim::FGOutputType
Abstract class to provide functions generic to all the output directives.
Definition: FGOutputType.h:90
JSBSim::FGModel::Upload
bool Upload(Element *el, bool preLoad)
Uploads this model in memory.
Definition: FGModel.cpp:110
JSBSim::Element::GetAttributeValue
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
Definition: FGXMLElement.cpp:260
JSBSim::FGOutput::Print
void Print(void)
Makes all the output instances to generate their ouput.
Definition: FGOutput.cpp:109
JSBSim::FGOutput::ForceOutput
void ForceOutput(int idx)
Force an output instance to generate its output.
Definition: FGOutput.cpp:143
JSBSim::FGOutput::Load
bool Load(Element *el, const SGPath &dir=SGPath())
Load the output directives and adds a new output instance to the Output Manager list.
Definition: FGOutput.cpp:238
JSBSim::BaseException
Definition: FGJSBBase.h:59
JSBSim::FGOutput::SetDirectivesFile
bool SetDirectivesFile(const SGPath &fname)
Adds a new output instance to the Output Manager.
Definition: FGOutput.cpp:172
JSBSim::FGOutputType::SetIdx
void SetIdx(unsigned int idx)
Set the idx for this output instance.
Definition: FGOutputType.cpp:91
JSBSim::FGOutputType::SetSubSystems
void SetSubSystems(int subSystems)
Set the activated subsystems for this output instance.
Definition: FGOutputType.h:117
JSBSim::FGOutput::GetOutputName
std::string GetOutputName(unsigned int idx) const
Get the name identifier to which the output will be directed.
Definition: FGOutput.cpp:161
JSBSim::FGOutputType::SetOutputProperties
void SetOutputProperties(std::vector< FGPropertyNode_ptr > &outputProperties)
Set the list of properties that should be output for this output instance.
Definition: FGOutputType.cpp:225
JSBSim::FGOutput::SetStartNewOutput
void SetStartNewOutput(void)
Reset the output prior to a restart of the simulation.
Definition: FGOutput.cpp:117
JSBSim::FGOutput::InitModel
bool InitModel(void) override
Initializes the instance.
Definition: FGOutput.cpp:80
JSBSim::FGXMLFileRead
Definition: FGXMLFileRead.h:51
JSBSim::FGModel::Run
virtual bool Run(bool Holding)
Runs the model; called by the Executive.
Definition: FGModel.cpp:89
JSBSim::FGOutputFG
Implements the output to a FlightGear socket.
Definition: FGOutputFG.h:63
JSBSim::FGOutput::SetOutputName
bool SetOutputName(unsigned int idx, const std::string &name)
Overwrites the name identifier under which the output will be logged.
Definition: FGOutput.cpp:151
JSBSim::FGOutputType::SetOutputName
virtual void SetOutputName(const std::string &name)
Overwrites the name identifier under which the output will be logged.
Definition: FGOutputType.h:129
XMLFile
This class is solely for the purpose of determining what type of file is given on the command line.
Definition: JSBSim.cpp:147
JSBSim::FGOutputType::SetRateHz
void SetRateHz(double rtHz)
Set the output rate for this output instances.
Definition: FGOutputType.cpp:204
JSBSim::FGOutputTextFile
Implements the output to a human readable text file.
Definition: FGOutputTextFile.h:65
JSBSim::FGOutputTextFile::SetDelimiter
void SetDelimiter(const std::string &delim)
Set the delimiter.
Definition: FGOutputTextFile.h:75
JSBSim::FGOutput::SetRateHz
void SetRateHz(double rate)
Modifies the output rate for all output instances.
Definition: FGOutput.cpp:135
JSBSim::FGOutputType::Load
bool Load(Element *el) override
Init the output directives from an XML file (implement the FGModel interface).
Definition: FGOutputType.cpp:102
JSBSim::FGOutput::Run
bool Run(bool Holding) override
Runs the Output model; called by the Executive.
Definition: FGOutput.cpp:94
JSBSim::FGOutput::Toggle
bool Toggle(int idx)
Toggles the output generation of each ouput instance.
Definition: FGOutput.cpp:125
JSBSim::Element
Definition: FGXMLElement.h:143
JSBSim::FGOutputSocket
Implements the output to a socket.
Definition: FGOutputSocket.h:66