JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
FGUDPInputSocket.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Module: FGUDPInputSocket.cpp
4  Author: Dave Culp
5  Date started: 02/19/15
6  Purpose: Manage input of data from a UDP socket
7  Called by: FGInput
8 
9  ------------- Copyright (C) 2015 Dave Culp --------------
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 class establishes a UDP socket and reads data from it.
31 
32 HISTORY
33 --------------------------------------------------------------------------------
34 02/19/15 DC Created
35 
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 INCLUDES
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39 
40 #include <cstring>
41 #include <cstdlib>
42 #include <sstream>
43 
44 #include "FGUDPInputSocket.h"
45 #include "FGFDMExec.h"
46 #include "input_output/FGXMLElement.h"
47 
48 using namespace std;
49 
50 namespace JSBSim {
51 
52 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 CLASS IMPLEMENTATION
54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
55 
56 FGUDPInputSocket::FGUDPInputSocket(FGFDMExec* fdmex) :
57  FGInputSocket(fdmex), rate(20), oldTimeStamp(0.0)
58 {
59  SockPort = 5139;
60  SockProtocol = FGfdmSocket::ptUDP;
61 }
62 
63 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
64 
66 {
67  if (!FGInputSocket::Load(el))
68  return false;
69 
70  rate = atoi(el->GetAttributeValue("rate").c_str());
71  SetRate(0.5 + 1.0/(FDMExec->GetDeltaT()*rate));
72 
73  Element *property_element = el->FindElement("property");
74 
75  while (property_element) {
76  string property_str = property_element->GetDataLine();
77  FGPropertyNode* node = PropertyManager->GetNode(property_str);
78  if (!node) {
79  cerr << fgred << highint << endl << " No property by the name "
80  << property_str << " can be found." << reset << endl;
81  } else {
82  InputProperties.push_back(node);
83  }
84  property_element = el->FindNextElement("property");
85  }
86 
87  return true;
88 }
89 
90 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91 
92 void FGUDPInputSocket::Read(bool Holding)
93 {
94  if (socket == 0) return;
95 
96  data = socket->Receive();
97 
98  if (data.size() > 0) {
99 
100  vector<string> tokens;
101  stringstream ss(data);
102  string temp;
103  while (getline(ss, temp, ',')) {
104  tokens.push_back(temp);
105  }
106 
107  vector<double> values;
108 
109  for (unsigned int i=0; i<tokens.size(); i++) {
110  values.push_back( atof(tokens[i].c_str()) );
111  }
112 
113  if (values[0] < oldTimeStamp) {
114  return;
115  } else {
116  oldTimeStamp = values[0];
117  }
118 
119  // the zeroeth value is the time stamp
120  if ((values.size() - 1) != InputProperties.size()) {
121  cerr << endl << "Mismatch between UDP input property and value counts." << endl;
122  return;
123  }
124 
125  for (unsigned int i=1; i<values.size(); i++) {
126  InputProperties[i-1]->setDoubleValue(values[i]);
127  }
128  }
129 }
130 
131 }
JSBSim::FGFDMExec
Encapsulates the JSBSim simulation executive.
Definition: FGFDMExec.h:185
JSBSim::Element::GetAttributeValue
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
Definition: FGXMLElement.cpp:260
JSBSim::Element::FindElement
Element * FindElement(const std::string &el="")
Searches for a specified element.
Definition: FGXMLElement.cpp:389
JSBSim::FGPropertyNode
Class wrapper for property handling.
Definition: FGPropertyManager.h:70
JSBSim::FGUDPInputSocket::Read
void Read(bool Holding) override
Reads the socket and updates properties accordingly.
Definition: FGUDPInputSocket.cpp:92
JSBSim::FGJSBBase::fgred
static char fgred[6]
red text
Definition: FGJSBBase.h:139
JSBSim::FGJSBBase::reset
static char reset[5]
resets text properties
Definition: FGJSBBase.h:129
JSBSim::FGFDMExec::GetDeltaT
double GetDeltaT(void) const
Returns the simulation delta T.
Definition: FGFDMExec.h:545
JSBSim::FGModel::SetRate
void SetRate(unsigned int tt)
Set the ouput rate for the model in frames.
Definition: FGModel.h:90
JSBSim::Element::GetDataLine
std::string GetDataLine(unsigned int i=0)
Gets a line of data belonging to an element.
Definition: FGXMLElement.cpp:333
JSBSim::FGInputSocket
Implements the input from a socket.
Definition: FGInputSocket.h:62
JSBSim::FGJSBBase::highint
static char highint[5]
highlights text
Definition: FGJSBBase.h:123
JSBSim::Element::FindNextElement
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
Definition: FGXMLElement.cpp:407
JSBSim::FGUDPInputSocket::Load
bool Load(Element *el) override
Reads the property names from an XML file.
Definition: FGUDPInputSocket.cpp:65
JSBSim::Element
Definition: FGXMLElement.h:143
JSBSim::FGInputSocket::Load
bool Load(Element *el) override
Init the input directives from an XML file.
Definition: FGInputSocket.cpp:74