1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 Module: FGOutputSocket.cpp
4 Author: Bertrand Coconnier
6 Purpose: Manage output of sim parameters to a socket
9 ------------- Copyright (C) 2011 Bertrand Coconnier -------------
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
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
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.
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.
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 This is the place where you create output routines to dump data for perusal
34 --------------------------------------------------------------------------------
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
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"
63 static const char *IdSrc = "$Id: FGOutputSocket.cpp,v 1.6 2013/11/24 11:40:55 bcoconni Exp $";
64 static const char *IdHdr = ID_OUTPUTSOCKET;
66 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
70 FGOutputSocket::FGOutputSocket(FGFDMExec* fdmex) :
76 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 FGOutputSocket::~FGOutputSocket()
83 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85 void FGOutputSocket::SetOutputName(const string& fname)
87 // tokenize the output name
88 size_t dot_pos = fname.find(':', 0);
89 size_t slash_pos = fname.find('/', 0);
91 string name = fname.substr(0, dot_pos);
94 if(dot_pos + 1 < slash_pos)
95 proto = fname.substr(dot_pos + 1, slash_pos - dot_pos - 1);
98 if(slash_pos < string::npos)
99 port = fname.substr(slash_pos + 1, string::npos);
101 // set the model name
102 Name = name + ":" + port + "/" + proto;
104 // set the socket params
107 SockPort = atoi(port.c_str());
110 SockProtocol = FGfdmSocket::ptUDP;
111 else // Default to TCP
112 SockProtocol = FGfdmSocket::ptTCP;
115 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117 bool FGOutputSocket::Load(Element* el)
119 if (!FGOutputType::Load(el))
122 SetOutputName(el->GetAttributeValue("name") + ":" +
123 el->GetAttributeValue("protocol") + "/" +
124 el->GetAttributeValue("port"));
129 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131 bool FGOutputSocket::InitModel(void)
133 if (FGOutputType::InitModel()) {
135 socket = new FGfdmSocket(SockName, SockPort, SockProtocol);
137 if (socket == 0) return false;
138 if (!socket->GetConnectStatus()) return false;
148 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150 void FGOutputSocket::PrintHeaders(void)
155 socket->Clear("<LABELS>");
156 socket->Append("Time");
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");
170 if (SubSystems & ssRates) {
174 socket->Append("PDot");
175 socket->Append("QDot");
176 socket->Append("RDot");
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");
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");
203 if (SubSystems & ssMoments) {
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 X");
215 socket->Append("Turbulence Direction Y");
216 socket->Append("Turbulence Direction Z");
217 socket->Append("NWind");
218 socket->Append("EWind");
219 socket->Append("DWind");
222 if (SubSystems & ssMassProps) {
223 socket->Append("Ixx");
224 socket->Append("Ixy");
225 socket->Append("Ixz");
226 socket->Append("Iyx");
227 socket->Append("Iyy");
228 socket->Append("Iyz");
229 socket->Append("Izx");
230 socket->Append("Izy");
231 socket->Append("Izz");
232 socket->Append("Mass");
233 socket->Append("Xcg");
234 socket->Append("Ycg");
235 socket->Append("Zcg");
238 if (SubSystems & ssPropagate) {
239 socket->Append("Altitude");
240 socket->Append("Phi (deg)");
241 socket->Append("Tht (deg)");
242 socket->Append("Psi (deg)");
243 socket->Append("Alpha (deg)");
244 socket->Append("Beta (deg)");
245 socket->Append("Latitude (deg)");
246 socket->Append("Longitude (deg)");
249 if (SubSystems & ssAeroFunctions) {
250 scratch = Aerodynamics->GetAeroFunctionStrings(",");
251 if (scratch.length() != 0) socket->Append(scratch);
254 if (SubSystems & ssFCS) {
255 scratch = FCS->GetComponentStrings(",");
256 if (scratch.length() != 0) socket->Append(scratch);
259 if (SubSystems & ssGroundReactions)
260 socket->Append(GroundReactions->GetGroundReactionStrings(","));
262 if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0)
263 socket->Append(Propulsion->GetPropulsionStrings(","));
265 if (OutputProperties.size() > 0) {
266 for (unsigned int i=0;i<OutputProperties.size();i++)
267 if (OutputCaptions[i].size() > 0) {
268 socket->Append(OutputCaptions[i]);
270 socket->Append(OutputProperties[i]->GetPrintableName());
277 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279 void FGOutputSocket::Print(void)
281 string asciiData, scratch;
283 if (socket == 0) return;
284 if (!socket->GetConnectStatus()) return;
287 socket->Append(FDMExec->GetSimTime());
289 if (SubSystems & ssAerosurfaces) {
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());
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));
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));
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));
330 if (SubSystems & ssMoments) {
331 socket->Append(Aircraft->GetMoments(eL));
332 socket->Append(Aircraft->GetMoments(eM));
333 socket->Append(Aircraft->GetMoments(eN));
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().Dump(","));
341 socket->Append(Winds->GetTotalWindNED().Dump(","));
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));
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());
368 if (SubSystems & ssAeroFunctions) {
369 scratch = Aerodynamics->GetAeroFunctionValues(",");
370 if (scratch.length() != 0) socket->Append(scratch);
372 if (SubSystems & ssFCS) {
373 scratch = FCS->GetComponentValues(",");
374 if (scratch.length() != 0) socket->Append(scratch);
376 if (SubSystems & ssGroundReactions) {
377 socket->Append(GroundReactions->GetGroundReactionValues(","));
379 if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
380 socket->Append(Propulsion->GetPropulsionValues(","));
383 for (unsigned int i=0;i<OutputProperties.size();i++) {
384 socket->Append(OutputProperties[i]->getDoubleValue());
390 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
392 void FGOutputSocket::SocketStatusOutput(const string& out_str)
396 if (socket == 0) return;
399 asciiData = string("<STATUS>") + out_str;
400 socket->Append(asciiData.c_str());