JSBSim Flight Dynamics Model  1.0 (02 March 2017)
An Open Source Flight Dynamics and Control Software Library in C++
FGOutputSocket.cpp
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 
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 09/10/11 BC Created
36 
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 INCLUDES
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
40 
41 #include <cstring>
42 #include <cstdlib>
43 
44 #include "FGOutputSocket.h"
45 #include "FGFDMExec.h"
46 #include "models/FGAerodynamics.h"
47 #include "models/FGAccelerations.h"
48 #include "models/FGAircraft.h"
49 #include "models/FGAtmosphere.h"
50 #include "models/FGAuxiliary.h"
51 #include "models/FGPropulsion.h"
52 #include "models/FGMassBalance.h"
53 #include "models/FGPropagate.h"
54 #include "models/FGGroundReactions.h"
55 #include "models/FGFCS.h"
56 #include "models/atmosphere/FGWinds.h"
57 #include "input_output/FGXMLElement.h"
58 
59 using namespace std;
60 
61 namespace JSBSim {
62 
63 IDENT(IdSrc,"$Id: FGOutputSocket.cpp,v 1.9 2014/02/17 05:01:22 jberndt Exp $");
64 IDENT(IdHdr,ID_OUTPUTSOCKET);
65 
66 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67 CLASS IMPLEMENTATION
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
69 
70 FGOutputSocket::FGOutputSocket(FGFDMExec* fdmex) :
71  FGOutputType(fdmex),
72  socket(0)
73 {
74 }
75 
76 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 
79 {
80  delete socket;
81 }
82 
83 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84 
85 void FGOutputSocket::SetOutputName(const string& fname)
86 {
87  // tokenize the output name
88  size_t dot_pos = fname.find(':', 0);
89  size_t slash_pos = fname.find('/', 0);
90 
91  string name = fname.substr(0, dot_pos);
92 
93  string proto = "TCP";
94  if(dot_pos + 1 < slash_pos)
95  proto = fname.substr(dot_pos + 1, slash_pos - dot_pos - 1);
96 
97  string port = "1138";
98  if(slash_pos < string::npos)
99  port = fname.substr(slash_pos + 1, string::npos);
100 
101  // set the model name
102  Name = name + ":" + port + "/" + proto;
103 
104  // set the socket params
105  SockName = name;
106 
107  SockPort = atoi(port.c_str());
108 
109  if (proto == "UDP")
110  SockProtocol = FGfdmSocket::ptUDP;
111  else // Default to TCP
112  SockProtocol = FGfdmSocket::ptTCP;
113 }
114 
115 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116 
118 {
119  if (!FGOutputType::Load(el))
120  return false;
121 
122  SetOutputName(el->GetAttributeValue("name") + ":" +
123  el->GetAttributeValue("protocol") + "/" +
124  el->GetAttributeValue("port"));
125 
126  return true;
127 }
128 
129 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
130 
132 {
133  if (FGOutputType::InitModel()) {
134  delete socket;
135  socket = new FGfdmSocket(SockName, SockPort, SockProtocol);
136 
137  if (socket == 0) return false;
138  if (!socket->GetConnectStatus()) return false;
139 
140  PrintHeaders();
141 
142  return true;
143  }
144 
145  return false;
146 }
147 
148 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 
150 void FGOutputSocket::PrintHeaders(void)
151 {
152  string scratch;
153 
154  socket->Clear();
155  socket->Clear("<LABELS>");
156  socket->Append("Time");
157 
158  if (SubSystems & ssAerosurfaces) {
159  socket->Append("Aileron Command");
160  socket->Append("Elevator Command");
161  socket->Append("Rudder Command");
162  socket->Append("Flap Command");
163  socket->Append("Left Aileron Position");
164  socket->Append("Right Aileron Position");
165  socket->Append("Elevator Position");
166  socket->Append("Rudder Position");
167  socket->Append("Flap Position");
168  }
169 
170  if (SubSystems & ssRates) {
171  socket->Append("P");
172  socket->Append("Q");
173  socket->Append("R");
174  socket->Append("PDot");
175  socket->Append("QDot");
176  socket->Append("RDot");
177  }
178 
179  if (SubSystems & ssVelocities) {
180  socket->Append("QBar");
181  socket->Append("Vtotal");
182  socket->Append("UBody");
183  socket->Append("VBody");
184  socket->Append("WBody");
185  socket->Append("UAero");
186  socket->Append("VAero");
187  socket->Append("WAero");
188  socket->Append("Vn");
189  socket->Append("Ve");
190  socket->Append("Vd");
191  }
192 
193  if (SubSystems & ssForces) {
194  socket->Append("F_Drag");
195  socket->Append("F_Side");
196  socket->Append("F_Lift");
197  socket->Append("LoD");
198  socket->Append("Fx");
199  socket->Append("Fy");
200  socket->Append("Fz");
201  }
202 
203  if (SubSystems & ssMoments) {
204  socket->Append("L");
205  socket->Append("M");
206  socket->Append("N");
207  }
208 
209  if (SubSystems & ssAtmosphere) {
210  socket->Append("Rho");
211  socket->Append("SL pressure");
212  socket->Append("Ambient pressure");
213  socket->Append("Turbulence Magnitude");
214  socket->Append("Turbulence Direction");
215  socket->Append("NWind");
216  socket->Append("EWind");
217  socket->Append("DWind");
218  }
219 
220  if (SubSystems & ssMassProps) {
221  socket->Append("Ixx");
222  socket->Append("Ixy");
223  socket->Append("Ixz");
224  socket->Append("Iyx");
225  socket->Append("Iyy");
226  socket->Append("Iyz");
227  socket->Append("Izx");
228  socket->Append("Izy");
229  socket->Append("Izz");
230  socket->Append("Mass");
231  socket->Append("Xcg");
232  socket->Append("Ycg");
233  socket->Append("Zcg");
234  }
235 
236  if (SubSystems & ssPropagate) {
237  socket->Append("Altitude");
238  socket->Append("Phi (deg)");
239  socket->Append("Tht (deg)");
240  socket->Append("Psi (deg)");
241  socket->Append("Alpha (deg)");
242  socket->Append("Beta (deg)");
243  socket->Append("Latitude (deg)");
244  socket->Append("Longitude (deg)");
245  }
246 
247  if (SubSystems & ssAeroFunctions) {
248  scratch = Aerodynamics->GetAeroFunctionStrings(",");
249  if (scratch.length() != 0) socket->Append(scratch);
250  }
251 
252  if (SubSystems & ssFCS) {
253  scratch = FCS->GetComponentStrings(",");
254  if (scratch.length() != 0) socket->Append(scratch);
255  }
256 
257  if (SubSystems & ssGroundReactions)
258  socket->Append(GroundReactions->GetGroundReactionStrings(","));
259 
260  if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0)
261  socket->Append(Propulsion->GetPropulsionStrings(","));
262 
263  if (OutputProperties.size() > 0) {
264  for (unsigned int i=0;i<OutputProperties.size();i++)
265  if (OutputCaptions[i].size() > 0) {
266  socket->Append(OutputCaptions[i]);
267  } else {
268  socket->Append(OutputProperties[i]->GetPrintableName());
269  }
270  }
271 
272  socket->Send();
273 }
274 
275 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276 
278 {
279  string asciiData, scratch;
280 
281  if (socket == 0) return;
282  if (!socket->GetConnectStatus()) return;
283 
284  socket->Clear();
285  socket->Append(FDMExec->GetSimTime());
286 
287  if (SubSystems & ssAerosurfaces) {
288  socket->Append(FCS->GetDaCmd());
289  socket->Append(FCS->GetDeCmd());
290  socket->Append(FCS->GetDrCmd());
291  socket->Append(FCS->GetDfCmd());
292  socket->Append(FCS->GetDaLPos());
293  socket->Append(FCS->GetDaRPos());
294  socket->Append(FCS->GetDePos());
295  socket->Append(FCS->GetDrPos());
296  socket->Append(FCS->GetDfPos());
297  }
298  if (SubSystems & ssRates) {
299  socket->Append(radtodeg*Propagate->GetPQR(eP));
300  socket->Append(radtodeg*Propagate->GetPQR(eQ));
301  socket->Append(radtodeg*Propagate->GetPQR(eR));
302  socket->Append(radtodeg*Accelerations->GetPQRdot(eP));
303  socket->Append(radtodeg*Accelerations->GetPQRdot(eQ));
304  socket->Append(radtodeg*Accelerations->GetPQRdot(eR));
305  }
306  if (SubSystems & ssVelocities) {
307  socket->Append(Auxiliary->Getqbar());
308  socket->Append(Auxiliary->GetVt());
309  socket->Append(Propagate->GetUVW(eU));
310  socket->Append(Propagate->GetUVW(eV));
311  socket->Append(Propagate->GetUVW(eW));
312  socket->Append(Auxiliary->GetAeroUVW(eU));
313  socket->Append(Auxiliary->GetAeroUVW(eV));
314  socket->Append(Auxiliary->GetAeroUVW(eW));
315  socket->Append(Propagate->GetVel(eNorth));
316  socket->Append(Propagate->GetVel(eEast));
317  socket->Append(Propagate->GetVel(eDown));
318  }
319  if (SubSystems & ssForces) {
320  socket->Append(Aerodynamics->GetvFw()(eDrag));
321  socket->Append(Aerodynamics->GetvFw()(eSide));
322  socket->Append(Aerodynamics->GetvFw()(eLift));
323  socket->Append(Aerodynamics->GetLoD());
324  socket->Append(Aircraft->GetForces(eX));
325  socket->Append(Aircraft->GetForces(eY));
326  socket->Append(Aircraft->GetForces(eZ));
327  }
328  if (SubSystems & ssMoments) {
329  socket->Append(Aircraft->GetMoments(eL));
330  socket->Append(Aircraft->GetMoments(eM));
331  socket->Append(Aircraft->GetMoments(eN));
332  }
333  if (SubSystems & ssAtmosphere) {
334  socket->Append(Atmosphere->GetDensity());
335  socket->Append(Atmosphere->GetPressureSL());
336  socket->Append(Atmosphere->GetPressure());
337  socket->Append(Winds->GetTurbMagnitude());
338  socket->Append(Winds->GetTurbDirection());
339  socket->Append(Winds->GetTotalWindNED().Dump(","));
340  }
341  if (SubSystems & ssMassProps) {
342  socket->Append(MassBalance->GetJ()(1,1));
343  socket->Append(MassBalance->GetJ()(1,2));
344  socket->Append(MassBalance->GetJ()(1,3));
345  socket->Append(MassBalance->GetJ()(2,1));
346  socket->Append(MassBalance->GetJ()(2,2));
347  socket->Append(MassBalance->GetJ()(2,3));
348  socket->Append(MassBalance->GetJ()(3,1));
349  socket->Append(MassBalance->GetJ()(3,2));
350  socket->Append(MassBalance->GetJ()(3,3));
351  socket->Append(MassBalance->GetMass());
352  socket->Append(MassBalance->GetXYZcg()(eX));
353  socket->Append(MassBalance->GetXYZcg()(eY));
354  socket->Append(MassBalance->GetXYZcg()(eZ));
355  }
356  if (SubSystems & ssPropagate) {
357  socket->Append(Propagate->GetAltitudeASL());
358  socket->Append(radtodeg*Propagate->GetEuler(ePhi));
359  socket->Append(radtodeg*Propagate->GetEuler(eTht));
360  socket->Append(radtodeg*Propagate->GetEuler(ePsi));
361  socket->Append(Auxiliary->Getalpha(inDegrees));
362  socket->Append(Auxiliary->Getbeta(inDegrees));
363  socket->Append(Propagate->GetLocation().GetLatitudeDeg());
364  socket->Append(Propagate->GetLocation().GetLongitudeDeg());
365  }
366  if (SubSystems & ssAeroFunctions) {
367  scratch = Aerodynamics->GetAeroFunctionValues(",");
368  if (scratch.length() != 0) socket->Append(scratch);
369  }
370  if (SubSystems & ssFCS) {
371  scratch = FCS->GetComponentValues(",");
372  if (scratch.length() != 0) socket->Append(scratch);
373  }
374  if (SubSystems & ssGroundReactions) {
375  socket->Append(GroundReactions->GetGroundReactionValues(","));
376  }
377  if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
378  socket->Append(Propulsion->GetPropulsionValues(","));
379  }
380 
381  for (unsigned int i=0;i<OutputProperties.size();i++) {
382  socket->Append(OutputProperties[i]->getDoubleValue());
383  }
384 
385  socket->Send();
386 }
387 
388 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 
390 void FGOutputSocket::SocketStatusOutput(const string& out_str)
391 {
392  string asciiData;
393 
394  if (socket == 0) return;
395 
396  socket->Clear();
397  asciiData = string("<STATUS>") + out_str;
398  socket->Append(asciiData.c_str());
399  socket->Send();
400 }
401 }
Subsystem: Propagate (= 512)
Definition: FGOutputType.h:193
double GetLoD(void) const
Retrieves the lift over drag ratio.
double GetDfPos(int form=ofRad) const
Gets the flaps position.
Definition: FGFCS.h:320
double GetDeCmd(void) const
Gets the elevator command.
Definition: FGFCS.h:222
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
double GetDePos(int form=ofRad) const
Gets the elevator position.
Definition: FGFCS.h:300
double GetDfCmd(void) const
Gets the flaps command.
Definition: FGFCS.h:234
virtual bool InitModel(void)
Init the output model according to its configitation.
virtual const FGColumnVector3 & GetTotalWindNED(void) const
Retrieves the total wind components in NED frame.
Definition: FGWinds.h:140
double GetDaLPos(int form=ofRad) const
Gets the left aileron position.
Definition: FGFCS.h:290
std::string GetAeroFunctionValues(const std::string &delimeter) const
Gets the aero function values.
Subsystem: Aerosurfaces (= 2)
Definition: FGOutputType.h:185
STL namespace.
virtual double GetPressure(void) const
Returns the pressure in psf.
Definition: FGAtmosphere.h:152
double GetAltitudeASL(void) const
Returns the current altitude above sea level.
Definition: FGPropagate.h:337
Subsystem: Velocities (= 8)
Definition: FGOutputType.h:187
const FGColumnVector3 & GetvFw(void) const
Retrieves the aerodynamic forces in the wind axes.
const FGColumnVector3 & GetUVW(void) const
Retrieves the body frame vehicle velocity vector.
Definition: FGPropagate.h:204
const FGColumnVector3 & GetPQR(void) const
Retrieves the body angular rates vector, relative to the ECEF frame.
Definition: FGPropagate.h:218
bool InitModel(void)
Initializes the instance.
std::string Dump(const std::string &delimeter) const
Prints the contents of the vector.
Subsystem: Atmosphere (= 64)
Definition: FGOutputType.h:190
std::string GetAeroFunctionStrings(const std::string &delimeter) const
Gets the strings for the current set of aero functions.
std::string GetComponentValues(const std::string &delimiter) const
Retrieves all component outputs for inclusion in output stream.
Definition: FGFCS.cpp:641
virtual bool Load(Element *el)
Init the output directives from an XML file (implement the FGModel interface).
const FGColumnVector3 & GetVel(void) const
Retrieves the velocity vector.
Definition: FGPropagate.h:192
Subsystem: Moments (= 32)
Definition: FGOutputType.h:189
const FGColumnVector3 & GetEuler(void) const
Retrieves the Euler angles that define the vehicle orientation.
Definition: FGPropagate.h:260
std::string GetComponentStrings(const std::string &delimiter) const
Retrieves all component names for inclusion in output stream.
Definition: FGFCS.cpp:618
virtual double GetDensity(void) const
Returns the density in slugs/ft^3.
Definition: FGAtmosphere.h:175
Abstract class to provide functions generic to all the output directives.
Definition: FGOutputType.h:95
double GetDaCmd(void) const
Gets the aileron command.
Definition: FGFCS.h:218
void Print(void)
Generates the output.
double GetLongitudeDeg() const
Get the longitude.
Definition: FGLocation.h:260
double GetSimTime(void) const
Returns the cumulative simulation time in seconds.
Definition: FGFDMExec.h:533
virtual void SetOutputName(const std::string &name)
Overwrites the name identifier under which the output will be logged.
virtual bool Load(Element *el)
Init the output directives from an XML file.
Subsystem: Ground Reactions (= 1024)
Definition: FGOutputType.h:194
Subsystem: FCS (= 2048)
Definition: FGOutputType.h:195
double GetLatitudeDeg() const
Get the latitude.
Definition: FGLocation.h:284
const FGColumnVector3 & GetPQRdot(void) const
Retrieves the body axis angular acceleration vector.
Subsystem: Mass Properties (= 128)
Definition: FGOutputType.h:191
~FGOutputSocket()
Destructor.
void SocketStatusOutput(const std::string &out_str)
Outputs a status thru the socket.
Encapsulates the JSBSim simulation executive.
Definition: FGFDMExec.h:189
Subsystem: Body rates (= 4)
Definition: FGOutputType.h:186
Subsystem: Forces (= 16)
Definition: FGOutputType.h:188
double GetDrCmd(void) const
Gets the rudder command.
Definition: FGFCS.h:226
Subsystem: Coefficients (= 256)
Definition: FGOutputType.h:192
Subsystem: Propulsion (= 4096)
Definition: FGOutputType.h:196
double GetDaRPos(int form=ofRad) const
Gets the right aileron position.
Definition: FGFCS.h:295
double GetVt(void) const
Gets the magnitude of total vehicle velocity including wind effects in feet per second.
Definition: FGAuxiliary.h:211
Encapsulates an object that enables JSBSim to communicate via socket (input and/or output)...
Definition: FGfdmSocket.h:89
double GetDrPos(int form=ofRad) const
Gets the rudder position.
Definition: FGFCS.h:305
unsigned int GetNumEngines(void) const
Retrieves the number of engines defined for the aircraft.
Definition: FGPropulsion.h:134