FlightGear next
FGOutput.cpp
Go to the documentation of this file.
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"
47
48using namespace std;
49
50namespace JSBSim {
51
52/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53CLASS IMPLEMENTATION
54%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
55
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
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
94bool 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
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
125bool 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
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
151bool 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
161string 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
172bool 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
191bool 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
238bool 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
284SGPath 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
314void 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}
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
static short debug_lvl
Definition FGJSBBase.h:190
void PostLoad(Element *el, FGFDMExec *fdmex, std::string prefix="")
void PreLoad(Element *el, FGFDMExec *fdmex, std::string prefix="")
unsigned int rate
Definition FGModel.h:102
FGPropertyManager * PropertyManager
Definition FGModel.h:117
bool InitModel(void) override
Definition FGModel.cpp:81
FGFDMExec * FDMExec
Definition FGModel.h:116
FGModel(FGFDMExec *)
Constructor.
Definition FGModel.cpp:57
virtual SGPath FindFullPathName(const SGPath &path) const
Definition FGModel.cpp:103
bool Upload(Element *el, bool preLoad)
Uploads this model in memory.
Definition FGModel.cpp:110
std::string Name
Definition FGModel.h:103
virtual bool Run(bool Holding)
Runs the model; called by the Executive.
Definition FGModel.cpp:89
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.
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.
void SetOutputProperties(std::vector< FGPropertyNode_ptr > &outputProperties)
Set the list of properties that should be output for this output instance.
void SetIdx(unsigned int idx)
Set the idx for this output instance.
void SetRateHz(double rtHz)
Set the output rate for this output instances.
bool Load(Element *el) override
Init the output directives from an XML file (implement the FGModel interface).
~FGOutput() override
Definition FGOutput.cpp:70
bool SetOutputName(unsigned int idx, const std::string &name)
Overwrites the name identifier under which the output will be logged.
Definition FGOutput.cpp:151
bool Run(bool Holding) override
Runs the Output model; called by the Executive.
Definition FGOutput.cpp:94
bool Toggle(int idx)
Toggles the output generation of each ouput instance.
Definition FGOutput.cpp:125
void Print(void)
Makes all the output instances to generate their ouput.
Definition FGOutput.cpp:109
void SetStartNewOutput(void)
Reset the output prior to a restart of the simulation.
Definition FGOutput.cpp:117
FGOutput(FGFDMExec *)
Definition FGOutput.cpp:56
bool InitModel(void) override
Initializes the instance.
Definition FGOutput.cpp:80
void SetRateHz(double rate)
Modifies the output rate for all output instances.
Definition FGOutput.cpp:135
std::string GetOutputName(unsigned int idx) const
Get the name identifier to which the output will be directed.
Definition FGOutput.cpp:161
SGPath FindFullPathName(const SGPath &path) const override
Definition FGOutput.cpp:284
bool SetDirectivesFile(const SGPath &fname)
Adds a new output instance to the Output Manager.
Definition FGOutput.cpp:172
void ForceOutput(int idx)
Force an output instance to generate its output.
Definition FGOutput.cpp:143
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
Element * LoadXMLDocument(const SGPath &XML_filename, bool verbose=true)
This class is solely for the purpose of determining what type of file is given on the command line.
Definition JSBSim.cpp:146
const char * name
SGPath CheckPathName(const SGPath &path, const SGPath &filename)
short debug_lvl
std::string & to_upper(std::string &str)