FlightGear next
FGOutputSocket.cpp
Go to the documentation of this file.
1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3 Module: FGOutputSocket.cpp
4 Author: Bertrand Coconnier
5 Date started: 09/10/11
6 Purpose: Manage output of sim parameters to a socket
7 Called by: FGOutput
8
9 ------------- Copyright (C) 2011 Bertrand Coconnier -------------
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 Software
13 Foundation; either version 2 of the License, or (at your option) any later
14 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 with
22 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23 Place - Suite 330, Boston, MA 02111-1307, USA.
24
25 Further information about the GNU Lesser General Public License can also be found on
26 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--------------------------------------------------------------------------------
3509/10/11 BC Created
36
37%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38INCLUDES
39%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
40
41#include <cstring>
42#include <cstdlib>
43
44#include "FGOutputSocket.h"
45#include "FGFDMExec.h"
48#include "models/FGAircraft.h"
49#include "models/FGAtmosphere.h"
50#include "models/FGAuxiliary.h"
51#include "models/FGPropulsion.h"
53#include "models/FGPropagate.h"
55#include "models/FGFCS.h"
59
60using namespace std;
61
62namespace JSBSim {
63
64/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65CLASS IMPLEMENTATION
66%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
67
73
74//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75
80
81//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82
83void FGOutputSocket::SetOutputName(const string& fname)
84{
85 // tokenize the output name
86 size_t dot_pos = fname.find(':', 0);
87 size_t slash_pos = fname.find('/', 0);
88
89 string name = fname.substr(0, dot_pos);
90
91 string proto = "TCP";
92 if(dot_pos + 1 < slash_pos)
93 proto = fname.substr(dot_pos + 1, slash_pos - dot_pos - 1);
94
95 string port = "1138";
96 if(slash_pos < string::npos)
97 port = fname.substr(slash_pos + 1, string::npos);
98
99 // set the model name
100 Name = name + ":" + port + "/" + proto;
101
102 // set the socket params
103 SockName = name;
104
105 SockPort = atoi(port.c_str());
106
107 if (to_upper(proto) == "UDP")
109 else // Default to TCP
111}
112
113//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114
116{
117 if (!FGOutputType::Load(el))
118 return false;
119
120 SetOutputName(el->GetAttributeValue("name") + ":" +
121 el->GetAttributeValue("protocol") + "/" +
122 el->GetAttributeValue("port"));
123
124 // Check if output precision for doubles has been specified, default to 7 if not
125 if(el->HasAttribute("precision"))
126 precision = (int)el->GetAttributeValueAsNumber("precision");
127 else
128 precision = 7;
129
130 return true;
131}
132
133//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134
136{
138 delete socket;
140
141 if (socket == 0) return false;
142 if (!socket->GetConnectStatus()) return false;
143
144 PrintHeaders();
145
146 return true;
147 }
148
149 return false;
150}
151
152//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153
155{
156 string scratch;
157
158 socket->Clear();
159 socket->Clear("<LABELS>");
160 socket->Append("Time");
161
163 socket->Append("Aileron Command");
164 socket->Append("Elevator Command");
165 socket->Append("Rudder Command");
166 socket->Append("Flap Command");
167 socket->Append("Left Aileron Position");
168 socket->Append("Right Aileron Position");
169 socket->Append("Elevator Position");
170 socket->Append("Rudder Position");
171 socket->Append("Flap Position");
172 }
173
174 if (SubSystems & ssRates) {
175 socket->Append("P");
176 socket->Append("Q");
177 socket->Append("R");
178 socket->Append("PDot");
179 socket->Append("QDot");
180 socket->Append("RDot");
181 }
182
183 if (SubSystems & ssVelocities) {
184 socket->Append("QBar");
185 socket->Append("Vtotal");
186 socket->Append("UBody");
187 socket->Append("VBody");
188 socket->Append("WBody");
189 socket->Append("UAero");
190 socket->Append("VAero");
191 socket->Append("WAero");
192 socket->Append("Vn");
193 socket->Append("Ve");
194 socket->Append("Vd");
195 }
196
197 if (SubSystems & ssForces) {
198 socket->Append("F_Drag");
199 socket->Append("F_Side");
200 socket->Append("F_Lift");
201 socket->Append("LoD");
202 socket->Append("Fx");
203 socket->Append("Fy");
204 socket->Append("Fz");
205 }
206
207 if (SubSystems & ssMoments) {
208 socket->Append("L");
209 socket->Append("M");
210 socket->Append("N");
211 }
212
213 if (SubSystems & ssAtmosphere) {
214 socket->Append("Rho");
215 socket->Append("SL pressure");
216 socket->Append("Ambient pressure");
217 socket->Append("Turbulence Magnitude");
218 socket->Append("Turbulence Direction");
219 socket->Append("NWind");
220 socket->Append("EWind");
221 socket->Append("DWind");
222 }
223
224 if (SubSystems & ssMassProps) {
225 socket->Append("Ixx");
226 socket->Append("Ixy");
227 socket->Append("Ixz");
228 socket->Append("Iyx");
229 socket->Append("Iyy");
230 socket->Append("Iyz");
231 socket->Append("Izx");
232 socket->Append("Izy");
233 socket->Append("Izz");
234 socket->Append("Mass");
235 socket->Append("Xcg");
236 socket->Append("Ycg");
237 socket->Append("Zcg");
238 }
239
240 if (SubSystems & ssPropagate) {
241 socket->Append("Altitude");
242 socket->Append("Phi (deg)");
243 socket->Append("Tht (deg)");
244 socket->Append("Psi (deg)");
245 socket->Append("Alpha (deg)");
246 socket->Append("Beta (deg)");
247 socket->Append("Latitude (deg)");
248 socket->Append("Longitude (deg)");
249 }
250
252 scratch = Aerodynamics->GetAeroFunctionStrings(",");
253 if (scratch.length() != 0) socket->Append(scratch);
254 }
255
256 if (SubSystems & ssFCS) {
257 scratch = FCS->GetComponentStrings(",");
258 if (scratch.length() != 0) socket->Append(scratch);
259 }
260
262 socket->Append(GroundReactions->GetGroundReactionStrings(","));
263
264 if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0)
265 socket->Append(Propulsion->GetPropulsionStrings(","));
266
267 for (unsigned int i=0;i<OutputParameters.size();++i) {
268 if (!OutputCaptions[i].empty())
269 socket->Append(OutputCaptions[i]);
270 else
271 socket->Append(OutputParameters[i]->GetPrintableName());
272 }
273
274 socket->Send();
275}
276
277//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278
280{
281 string asciiData, scratch;
282
283 if (socket == 0) return;
284 if (!socket->GetConnectStatus()) return;
285
286 socket->Clear();
287 socket->Append(FDMExec->GetSimTime());
288
290 socket->Append(FCS->GetDaCmd());
291 socket->Append(FCS->GetDeCmd());
292 socket->Append(FCS->GetDrCmd());
293 socket->Append(FCS->GetDfCmd());
294 socket->Append(FCS->GetDaLPos());
295 socket->Append(FCS->GetDaRPos());
296 socket->Append(FCS->GetDePos());
297 socket->Append(FCS->GetDrPos());
298 socket->Append(FCS->GetDfPos());
299 }
300 if (SubSystems & ssRates) {
301 socket->Append(radtodeg*Propagate->GetPQR(eP));
302 socket->Append(radtodeg*Propagate->GetPQR(eQ));
303 socket->Append(radtodeg*Propagate->GetPQR(eR));
304 socket->Append(radtodeg*Accelerations->GetPQRdot(eP));
305 socket->Append(radtodeg*Accelerations->GetPQRdot(eQ));
306 socket->Append(radtodeg*Accelerations->GetPQRdot(eR));
307 }
308 if (SubSystems & ssVelocities) {
309 socket->Append(Auxiliary->Getqbar());
310 socket->Append(Auxiliary->GetVt());
311 socket->Append(Propagate->GetUVW(eU));
312 socket->Append(Propagate->GetUVW(eV));
313 socket->Append(Propagate->GetUVW(eW));
314 socket->Append(Auxiliary->GetAeroUVW(eU));
315 socket->Append(Auxiliary->GetAeroUVW(eV));
316 socket->Append(Auxiliary->GetAeroUVW(eW));
317 socket->Append(Propagate->GetVel(eNorth));
318 socket->Append(Propagate->GetVel(eEast));
319 socket->Append(Propagate->GetVel(eDown));
320 }
321 if (SubSystems & ssForces) {
322 socket->Append(Aerodynamics->GetvFw()(eDrag));
323 socket->Append(Aerodynamics->GetvFw()(eSide));
324 socket->Append(Aerodynamics->GetvFw()(eLift));
325 socket->Append(Aerodynamics->GetLoD());
326 socket->Append(Aircraft->GetForces(eX));
327 socket->Append(Aircraft->GetForces(eY));
328 socket->Append(Aircraft->GetForces(eZ));
329 }
330 if (SubSystems & ssMoments) {
331 socket->Append(Aircraft->GetMoments(eL));
332 socket->Append(Aircraft->GetMoments(eM));
333 socket->Append(Aircraft->GetMoments(eN));
334 }
335 if (SubSystems & ssAtmosphere) {
336 socket->Append(Atmosphere->GetDensity());
337 socket->Append(Atmosphere->GetPressureSL());
338 socket->Append(Atmosphere->GetPressure());
339 socket->Append(Winds->GetTurbMagnitude());
340 socket->Append(Winds->GetTurbDirection());
341 socket->Append(Winds->GetTotalWindNED().Dump(","));
342 }
343 if (SubSystems & ssMassProps) {
344 socket->Append(MassBalance->GetJ()(1,1));
345 socket->Append(MassBalance->GetJ()(1,2));
346 socket->Append(MassBalance->GetJ()(1,3));
347 socket->Append(MassBalance->GetJ()(2,1));
348 socket->Append(MassBalance->GetJ()(2,2));
349 socket->Append(MassBalance->GetJ()(2,3));
350 socket->Append(MassBalance->GetJ()(3,1));
351 socket->Append(MassBalance->GetJ()(3,2));
352 socket->Append(MassBalance->GetJ()(3,3));
353 socket->Append(MassBalance->GetMass());
354 socket->Append(MassBalance->GetXYZcg()(eX));
355 socket->Append(MassBalance->GetXYZcg()(eY));
356 socket->Append(MassBalance->GetXYZcg()(eZ));
357 }
358 if (SubSystems & ssPropagate) {
359 socket->Append(Propagate->GetAltitudeASL());
360 socket->Append(radtodeg*Propagate->GetEuler(ePhi));
361 socket->Append(radtodeg*Propagate->GetEuler(eTht));
362 socket->Append(radtodeg*Propagate->GetEuler(ePsi));
363 socket->Append(Auxiliary->Getalpha(inDegrees));
364 socket->Append(Auxiliary->Getbeta(inDegrees));
365 socket->Append(Propagate->GetLocation().GetLatitudeDeg());
366 socket->Append(Propagate->GetLocation().GetLongitudeDeg());
367 }
369 scratch = Aerodynamics->GetAeroFunctionValues(",");
370 if (scratch.length() != 0) socket->Append(scratch);
371 }
372 if (SubSystems & ssFCS) {
373 scratch = FCS->GetComponentValues(",");
374 if (scratch.length() != 0) socket->Append(scratch);
375 }
377 socket->Append(GroundReactions->GetGroundReactionValues(","));
378 }
379 if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
380 socket->Append(Propulsion->GetPropulsionValues(","));
381 }
382
383 for (unsigned int i=0;i<OutputParameters.size();++i) {
384 socket->Append(OutputParameters[i]->GetValue());
385 }
386
387 socket->Send();
388}
389
390//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391
392void FGOutputSocket::SocketStatusOutput(const string& out_str)
393{
394 string asciiData;
395
396 if (socket == 0) return;
397
398 socket->Clear();
399 asciiData = string("<STATUS>") + out_str;
400 socket->Append(asciiData.c_str());
401 socket->Send();
402}
403}
#define i(x)
double GetAttributeValueAsNumber(const std::string &key)
Retrieves an attribute value as a double precision real number.
bool HasAttribute(const std::string &key)
Determines if an element has the supplied attribute.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
static constexpr double radtodeg
Definition FGJSBBase.h:348
FGFDMExec * FDMExec
Definition FGModel.h:116
std::string Name
Definition FGModel.h:103
void SocketStatusOutput(const std::string &out_str)
Outputs a status thru the socket.
void Print(void) override
Generates the output.
FGfdmSocket::ProtocolType SockProtocol
~FGOutputSocket() override
Destructor.
bool InitModel(void) override
Initializes the instance.
void SetOutputName(const std::string &name) override
Overwrites the name identifier under which the output will be logged.
virtual void PrintHeaders(void)
FGOutputSocket(FGFDMExec *fdmex)
Constructor.
bool Load(Element *el) override
Init the output directives from an XML file.
@ ssGroundReactions
Subsystem: Ground Reactions (= 1024)
@ ssMoments
Subsystem: Moments (= 32)
@ ssPropagate
Subsystem: Propagate (= 512)
@ ssPropulsion
Subsystem: Propulsion (= 4096)
@ ssForces
Subsystem: Forces (= 16)
@ ssAerosurfaces
Subsystem: Aerosurfaces (= 2)
@ ssMassProps
Subsystem: Mass Properties (= 128)
@ ssFCS
Subsystem: FCS (= 2048)
@ ssRates
Subsystem: Body rates (= 4)
@ ssAtmosphere
Subsystem: Atmosphere (= 64)
@ ssAeroFunctions
Subsystem: Coefficients (= 256)
@ ssVelocities
Subsystem: Velocities (= 8)
FGGroundReactions * GroundReactions
FGAircraft * Aircraft
std::vector< FGPropertyValue * > OutputParameters
FGAccelerations * Accelerations
FGPropulsion * Propulsion
FGAuxiliary * Auxiliary
FGOutputType(FGFDMExec *fdmex)
Constructor (implement the FGModel interface).
FGPropagate * Propagate
FGAtmosphere * Atmosphere
FGMassBalance * MassBalance
std::vector< std::string > OutputCaptions
bool Load(Element *el) override
Init the output directives from an XML file (implement the FGModel interface).
FGAerodynamics * Aerodynamics
bool InitModel(void) override
Init the output model according to its configitation.
Encapsulates an object that enables JSBSim to communicate via socket (input and/or output).
Definition FGfdmSocket.h:71
const char * name
static int atoi(const string &str)
Definition options.cxx:113
std::string & to_upper(std::string &str)