JSBSim Flight Dynamics Model 1.3.0 (09 Apr 2026)
An Open Source Flight Dynamics and Control Software Library in C++
Loading...
Searching...
No Matches
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
28FUNCTIONAL DESCRIPTION
29--------------------------------------------------------------------------------
30This is the place where you create output routines to dump data for perusal
31later.
32
33HISTORY
34--------------------------------------------------------------------------------
3512/02/98 JSB Created
3611/09/07 HDW Added FlightGear Socket Interface
37
38%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39INCLUDES
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#include "input_output/FGLog.h"
48#include "input_output/string_utilities.h"
49
50using namespace std;
51
52namespace JSBSim {
53
54/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55CLASS IMPLEMENTATION
56%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
57
58FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex)
59{
60 Name = "FGOutput";
61 enabled = true;
62
63 PropertyManager->Tie<FGOutput, int>("simulation/force-output", this, nullptr,
64 &FGOutput::ForceOutput);
65
66 Debug(0);
67}
68
69//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70
71FGOutput::~FGOutput()
72{
73 for (auto output: OutputTypes)
74 delete output;
75
76 Debug(1);
77}
78
79//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80
81bool FGOutput::InitModel(void)
82{
83 bool ret = false;
84
85 if (!FGModel::InitModel()) return false;
86
87 for (auto output: OutputTypes)
88 ret &= output->InitModel();
89
90 return ret;
91}
92
93//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94
95bool FGOutput::Run(bool Holding)
96{
97 if (FDMExec->GetTrimStatus()) return true;
98 if (FGModel::Run(Holding)) return true;
99 if (Holding) return false;
100 if (!enabled) return true;
101
102 for (auto output: OutputTypes)
103 output->Run(Holding);
104
105 return false;
106}
107
108//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109
110void FGOutput::Print(void)
111{
112 for (auto output: OutputTypes)
113 output->Print();
114}
115
116//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117
118void FGOutput::SetStartNewOutput(void)
119{
120 for (auto output: OutputTypes)
121 output->SetStartNewOutput();
122}
123
124//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125
126bool FGOutput::Toggle(int idx)
127{
128 if (idx >= (int)0 && idx < (int)OutputTypes.size())
129 return OutputTypes[idx]->Toggle();
130
131 return false;
132}
133
134//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135
136void FGOutput::SetRateHz(double rate)
137{
138 for (auto output: OutputTypes)
139 output->SetRateHz(rate);
140}
141
142//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143
144void FGOutput::ForceOutput(int idx)
145{
146 if (idx >= (int)0 && idx < (int)OutputTypes.size())
147 OutputTypes[idx]->Print();
148}
149
150//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
151
152bool FGOutput::SetOutputName(unsigned int idx, const std::string& name)
153{
154 if (idx >= OutputTypes.size()) return false;
155
156 OutputTypes[idx]->SetOutputName(name);
157 return true;
158}
159
160//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
161
162string FGOutput::GetOutputName(unsigned int idx) const
163{
164 string name;
165
166 if (idx < OutputTypes.size())
167 name = OutputTypes[idx]->GetOutputName();
168 return name;
169}
170
171//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172
173bool FGOutput::SetDirectivesFile(const SGPath& fname)
174{
176 Element* document = XMLFile.LoadXMLDocument(fname);
177 if (!document) {
178 LogException err;
179 err << "Could not read directive file: " << fname;
180 throw err;
181 }
182
183 bool result = Load(document);
184 if (!result) {
185 FGLogging log(LogLevel::ERROR);
186 log << "\nAircraft output element has problems in file " << fname << "\n";
187 }
188
189 return result;
190}
191
192//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193
194bool FGOutput::Load(int subSystems, std::string protocol, std::string type,
195 std::string port, std::string name, double outRate,
196 std::vector<SGPropertyNode_ptr> & outputProperties)
197{
198 size_t idx = OutputTypes.size();
199 FGOutputType* Output = 0;
200
201 if (debug_lvl > 0) {
202 FGLogging log(LogLevel::DEBUG);
203 log << "\n Output data set: " << idx << "\n";
204 }
205
206 type = to_upper(type);
207
208 if (type == "CSV") {
209 FGOutputTextFile* OutputTextFile = new FGOutputTextFile(FDMExec);
210 OutputTextFile->SetDelimiter(",");
211 Output = OutputTextFile;
212 } else if (type == "TABULAR") {
213 FGOutputTextFile* OutputTextFile = new FGOutputTextFile(FDMExec);
214 OutputTextFile->SetDelimiter("\t");
215 Output = OutputTextFile;
216 } else if (type == "SOCKET") {
217 Output = new FGOutputSocket(FDMExec);
218 name += ":" + port + "/" + protocol;
219 } else if (type == "FLIGHTGEAR") {
220 Output = new FGOutputFG(FDMExec);
221 name += ":" + port + "/" + protocol;
222 } else if (type == "TERMINAL") {
223 // Not done yet
224 } else if (type != string("NONE")) {
225 FGLogging log(LogLevel::ERROR);
226 log << "Unknown type of output specified in config file\n";
227 }
228
229 if (!Output) return false;
230
231 Output->SetIdx(idx);
232 Output->SetOutputName(name);
233 Output->SetRateHz(outRate);
234 Output->SetSubSystems(subSystems);
235 Output->SetOutputProperties(outputProperties);
236
237 OutputTypes.push_back(Output);
238
239 Debug(2);
240 return true;
241}
242
243//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244
245bool FGOutput::Load(Element* document, const SGPath& dir)
246{
247 // Optional path to use for included files
248 includePath = dir;
249
250 // Perform base class Pre-Load
251 if (!FGModel::Upload(document, false))
252 return false;
253
254 size_t idx = OutputTypes.size();
255 string type = document->GetAttributeValue("type");
256 FGOutputType* Output = 0;
257
258 if (debug_lvl > 0) {
259 FGLogging log(LogLevel::DEBUG);
260 log << "\n Output data set: " << idx << " \n";
261 }
262
263 type = to_upper(type);
264
265 if (type == "CSV") {
266 Output = new FGOutputTextFile(FDMExec);
267 } else if (type == "TABULAR") {
268 Output = new FGOutputTextFile(FDMExec);
269 } else if (type == "SOCKET") {
270 Output = new FGOutputSocket(FDMExec);
271 } else if (type == "FLIGHTGEAR") {
272 Output = new FGOutputFG(FDMExec);
273 } else if (type == "TERMINAL") {
274 // Not done yet
275 } else if (type != string("NONE")) {
276 FGLogging log(LogLevel::ERROR);
277 log << "Unknown type of output specified in config file\n";
278 }
279
280 if (!Output) return false;
281
282 Output->SetIdx(idx);
283 Output->PreLoad(document, FDMExec);
284 Output->Load(document);
285 Output->PostLoad(document, FDMExec);
286
287 OutputTypes.push_back(Output);
288
289 Debug(2);
290 return true;
291}
292
293//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294
295SGPath FGOutput::FindFullPathName(const SGPath& path) const
296{
297 // Check optional include path if set
298 if (!includePath.isNull()) {
299 SGPath name = CheckPathName(includePath, path);
300 if (!name.isNull()) return name;
301 }
302
303 return FGModel::FindFullPathName(path);
304}
305
306//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307// The bitmasked value choices are as follows:
308// unset: In this case (the default) JSBSim would only print
309// out the normally expected messages, essentially echoing
310// the config files as they are read. If the environment
311// variable is not set, debug_lvl is set to 1 internally
312// 0: This requests JSBSim not to output any messages
313// whatsoever.
314// 1: This value explicity requests the normal JSBSim
315// startup messages
316// 2: This value asks for a message to be printed out when
317// a class is instantiated
318// 4: When this value is set, a message is displayed when a
319// FGModel object executes its Run() method
320// 8: When this value is set, various runtime state variables
321// are printed out periodically
322// 16: When set various parameters are sanity checked and
323// a message is printed out when they go out of bounds
324
325void FGOutput::Debug(int from)
326{
327 if (debug_lvl <= 0) return;
328
329 if (debug_lvl & 1) { // Standard console startup message output
330 if (from == 0) { // Constructor
331
332 }
333 if (from == 2) {
334 }
335 }
336 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
337 FGLogging log(LogLevel::DEBUG);
338 if (from == 0) log << "Instantiated: FGOutput\n";
339 if (from == 1) log << "Destroyed: FGOutput\n";
340 }
341 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
342 }
343 if (debug_lvl & 8 ) { // Runtime state variables
344 }
345 if (debug_lvl & 16) { // Sanity checking
346 }
347 if (debug_lvl & 64) {
348 if (from == 0) { // Constructor
349 }
350 }
351}
352}
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
Implements the output to a FlightGear socket.
Definition FGOutputFG.h:64
Implements the output to a socket.
Implements the output to a human readable text file.
void SetDelimiter(const std::string &delim)
Set the delimiter.
Abstract class to provide functions generic to all the output directives.
bool Load(Element *el) override
Init the output directives from an XML file (implement the FGModel interface).
void SetOutputProperties(std::vector< SGPropertyNode_ptr > &outputProperties)
Set the list of properties that should be output for this output instance.
void SetRateHz(double rtHz)
Set the output rate for this output instances.
void SetIdx(unsigned int idx)
Set the idx for this output instance.
virtual void SetOutputName(const std::string &name)
Overwrites the name identifier under which the output will be logged.
void SetSubSystems(int subSystems)
Set the activated subsystems for this output instance.
This class is solely for the purpose of determining what type of file is given on the command line.
Definition JSBSim.cpp:155
Main namespace for the JSBSim Flight Dynamics Model.
Definition FGFDMExec.cpp:71