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"
62 static const char *IdSrc = "$Id: FGOutputSocket.cpp,v 1.5 2013/01/12 21:14:46 bcoconni Exp $";
63 static const char *IdHdr = ID_OUTPUTSOCKET;
65 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
69 FGOutputSocket::FGOutputSocket(FGFDMExec* fdmex) :
75 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 FGOutputSocket::~FGOutputSocket()
82 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84 void FGOutputSocket::SetOutputName(const string& fname)
86 // tokenize the output name
87 size_t dot_pos = fname.find(':', 0);
88 size_t slash_pos = fname.find('/', 0);
90 string name = fname.substr(0, dot_pos);
93 if(dot_pos + 1 < slash_pos)
94 proto = fname.substr(dot_pos + 1, slash_pos - dot_pos - 1);
97 if(slash_pos < string::npos)
98 port = fname.substr(slash_pos + 1, string::npos);
100 // set the model name
101 Name = name + ":" + port + "/" + proto;
103 // set the socket params
106 SockPort = atoi(port.c_str());
109 SockProtocol = FGfdmSocket::ptUDP;
110 else // Default to TCP
111 SockProtocol = FGfdmSocket::ptTCP;
114 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116 bool FGOutputSocket::Load(Element* el)
118 if (!FGOutputType::Load(el))
121 SetOutputName(el->GetAttributeValue("name") + ":" +
122 el->GetAttributeValue("protocol") + "/" +
123 el->GetAttributeValue("port"));
128 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
130 bool FGOutputSocket::InitModel(void)
132 if (FGOutputType::InitModel()) {
134 socket = new FGfdmSocket(SockName, SockPort, SockProtocol);
136 if (socket == 0) return false;
137 if (!socket->GetConnectStatus()) return false;
147 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 void FGOutputSocket::PrintHeaders(void)
154 socket->Clear("<LABELS>");
155 socket->Append("Time");
157 if (SubSystems & ssAerosurfaces) {
158 socket->Append("Aileron Command");
159 socket->Append("Elevator Command");
160 socket->Append("Rudder Command");
161 socket->Append("Flap Command");
162 socket->Append("Left Aileron Position");
163 socket->Append("Right Aileron Position");
164 socket->Append("Elevator Position");
165 socket->Append("Rudder Position");
166 socket->Append("Flap Position");
169 if (SubSystems & ssRates) {
173 socket->Append("PDot");
174 socket->Append("QDot");
175 socket->Append("RDot");
178 if (SubSystems & ssVelocities) {
179 socket->Append("QBar");
180 socket->Append("Vtotal");
181 socket->Append("UBody");
182 socket->Append("VBody");
183 socket->Append("WBody");
184 socket->Append("UAero");
185 socket->Append("VAero");
186 socket->Append("WAero");
187 socket->Append("Vn");
188 socket->Append("Ve");
189 socket->Append("Vd");
192 if (SubSystems & ssForces) {
193 socket->Append("F_Drag");
194 socket->Append("F_Side");
195 socket->Append("F_Lift");
196 socket->Append("LoD");
197 socket->Append("Fx");
198 socket->Append("Fy");
199 socket->Append("Fz");
202 if (SubSystems & ssMoments) {
208 if (SubSystems & ssAtmosphere) {
209 socket->Append("Rho");
210 socket->Append("SL pressure");
211 socket->Append("Ambient pressure");
212 socket->Append("Turbulence Magnitude");
213 socket->Append("Turbulence Direction X");
214 socket->Append("Turbulence Direction Y");
215 socket->Append("Turbulence Direction Z");
216 socket->Append("NWind");
217 socket->Append("EWind");
218 socket->Append("DWind");
221 if (SubSystems & ssMassProps) {
222 socket->Append("Ixx");
223 socket->Append("Ixy");
224 socket->Append("Ixz");
225 socket->Append("Iyx");
226 socket->Append("Iyy");
227 socket->Append("Iyz");
228 socket->Append("Izx");
229 socket->Append("Izy");
230 socket->Append("Izz");
231 socket->Append("Mass");
232 socket->Append("Xcg");
233 socket->Append("Ycg");
234 socket->Append("Zcg");
237 if (SubSystems & ssPropagate) {
238 socket->Append("Altitude");
239 socket->Append("Phi (deg)");
240 socket->Append("Tht (deg)");
241 socket->Append("Psi (deg)");
242 socket->Append("Alpha (deg)");
243 socket->Append("Beta (deg)");
244 socket->Append("Latitude (deg)");
245 socket->Append("Longitude (deg)");
248 if (SubSystems & ssAeroFunctions) {
249 scratch = Aerodynamics->GetAeroFunctionStrings(",");
250 if (scratch.length() != 0) socket->Append(scratch);
253 if (SubSystems & ssFCS) {
254 scratch = FCS->GetComponentStrings(",");
255 if (scratch.length() != 0) socket->Append(scratch);
258 if (SubSystems & ssGroundReactions)
259 socket->Append(GroundReactions->GetGroundReactionStrings(","));
261 if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0)
262 socket->Append(Propulsion->GetPropulsionStrings(","));
264 if (OutputProperties.size() > 0) {
265 for (unsigned int i=0;i<OutputProperties.size();i++)
266 if (OutputCaptions[i].size() > 0) {
267 socket->Append(OutputCaptions[i]);
269 socket->Append(OutputProperties[i]->GetPrintableName());
276 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278 void FGOutputSocket::Print(void)
280 string asciiData, scratch;
282 if (socket == 0) return;
283 if (!socket->GetConnectStatus()) return;
286 socket->Append(FDMExec->GetSimTime());
288 if (SubSystems & ssAerosurfaces) {
289 socket->Append(FCS->GetDaCmd());
290 socket->Append(FCS->GetDeCmd());
291 socket->Append(FCS->GetDrCmd());
292 socket->Append(FCS->GetDfCmd());
293 socket->Append(FCS->GetDaLPos());
294 socket->Append(FCS->GetDaRPos());
295 socket->Append(FCS->GetDePos());
296 socket->Append(FCS->GetDrPos());
297 socket->Append(FCS->GetDfPos());
299 if (SubSystems & ssRates) {
300 socket->Append(radtodeg*Propagate->GetPQR(eP));
301 socket->Append(radtodeg*Propagate->GetPQR(eQ));
302 socket->Append(radtodeg*Propagate->GetPQR(eR));
303 socket->Append(radtodeg*Accelerations->GetPQRdot(eP));
304 socket->Append(radtodeg*Accelerations->GetPQRdot(eQ));
305 socket->Append(radtodeg*Accelerations->GetPQRdot(eR));
307 if (SubSystems & ssVelocities) {
308 socket->Append(Auxiliary->Getqbar());
309 socket->Append(Auxiliary->GetVt());
310 socket->Append(Propagate->GetUVW(eU));
311 socket->Append(Propagate->GetUVW(eV));
312 socket->Append(Propagate->GetUVW(eW));
313 socket->Append(Auxiliary->GetAeroUVW(eU));
314 socket->Append(Auxiliary->GetAeroUVW(eV));
315 socket->Append(Auxiliary->GetAeroUVW(eW));
316 socket->Append(Propagate->GetVel(eNorth));
317 socket->Append(Propagate->GetVel(eEast));
318 socket->Append(Propagate->GetVel(eDown));
320 if (SubSystems & ssForces) {
321 socket->Append(Aerodynamics->GetvFw()(eDrag));
322 socket->Append(Aerodynamics->GetvFw()(eSide));
323 socket->Append(Aerodynamics->GetvFw()(eLift));
324 socket->Append(Aerodynamics->GetLoD());
325 socket->Append(Aircraft->GetForces(eX));
326 socket->Append(Aircraft->GetForces(eY));
327 socket->Append(Aircraft->GetForces(eZ));
329 if (SubSystems & ssMoments) {
330 socket->Append(Aircraft->GetMoments(eL));
331 socket->Append(Aircraft->GetMoments(eM));
332 socket->Append(Aircraft->GetMoments(eN));
334 if (SubSystems & ssAtmosphere) {
335 socket->Append(Atmosphere->GetDensity());
336 socket->Append(Atmosphere->GetPressureSL());
337 socket->Append(Atmosphere->GetPressure());
338 socket->Append(Winds->GetTurbMagnitude());
339 socket->Append(Winds->GetTurbDirection().Dump(","));
340 socket->Append(Winds->GetTotalWindNED().Dump(","));
342 if (SubSystems & ssMassProps) {
343 socket->Append(MassBalance->GetJ()(1,1));
344 socket->Append(MassBalance->GetJ()(1,2));
345 socket->Append(MassBalance->GetJ()(1,3));
346 socket->Append(MassBalance->GetJ()(2,1));
347 socket->Append(MassBalance->GetJ()(2,2));
348 socket->Append(MassBalance->GetJ()(2,3));
349 socket->Append(MassBalance->GetJ()(3,1));
350 socket->Append(MassBalance->GetJ()(3,2));
351 socket->Append(MassBalance->GetJ()(3,3));
352 socket->Append(MassBalance->GetMass());
353 socket->Append(MassBalance->GetXYZcg()(eX));
354 socket->Append(MassBalance->GetXYZcg()(eY));
355 socket->Append(MassBalance->GetXYZcg()(eZ));
357 if (SubSystems & ssPropagate) {
358 socket->Append(Propagate->GetAltitudeASL());
359 socket->Append(radtodeg*Propagate->GetEuler(ePhi));
360 socket->Append(radtodeg*Propagate->GetEuler(eTht));
361 socket->Append(radtodeg*Propagate->GetEuler(ePsi));
362 socket->Append(Auxiliary->Getalpha(inDegrees));
363 socket->Append(Auxiliary->Getbeta(inDegrees));
364 socket->Append(Propagate->GetLocation().GetLatitudeDeg());
365 socket->Append(Propagate->GetLocation().GetLongitudeDeg());
367 if (SubSystems & ssAeroFunctions) {
368 scratch = Aerodynamics->GetAeroFunctionValues(",");
369 if (scratch.length() != 0) socket->Append(scratch);
371 if (SubSystems & ssFCS) {
372 scratch = FCS->GetComponentValues(",");
373 if (scratch.length() != 0) socket->Append(scratch);
375 if (SubSystems & ssGroundReactions) {
376 socket->Append(GroundReactions->GetGroundReactionValues(","));
378 if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
379 socket->Append(Propulsion->GetPropulsionValues(","));
382 for (unsigned int i=0;i<OutputProperties.size();i++) {
383 socket->Append(OutputProperties[i]->getDoubleValue());
389 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391 void FGOutputSocket::SocketStatusOutput(const string& out_str)
395 if (socket == 0) return;
398 asciiData = string("<STATUS>") + out_str;
399 socket->Append(asciiData.c_str());