Branch data Line data Source code
1 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 : :
3 : : Module: FGInput.cpp
4 : : Author: Jon Berndt
5 : : Date started: 12/02/98
6 : : Purpose: Manage output of sim parameters to file or stdout
7 : : Called by: FGSimExec
8 : :
9 : : ------------- Copyright (C) 1999 Jon S. Berndt (jon@jsbsim.org) -------------
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 : : 12/02/98 JSB Created
36 : :
37 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 : : INCLUDES
39 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
40 : :
41 : : #include "FGInput.h"
42 : : #include "FGAircraft.h"
43 : : #include "FGFDMExec.h"
44 : :
45 : : #include "input_output/FGfdmSocket.h"
46 : : #include "input_output/FGXMLElement.h"
47 : :
48 : : #include <sstream>
49 : : #include <iomanip>
50 : : #include <cstdlib>
51 : :
52 : : using namespace std;
53 : :
54 : : namespace JSBSim {
55 : :
56 : : static const char *IdSrc = "$Id: FGInput.cpp,v 1.19 2010/02/25 05:21:36 jberndt Exp $";
57 : : static const char *IdHdr = ID_INPUT;
58 : :
59 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60 : : CLASS IMPLEMENTATION
61 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
62 : :
63 : 1 : FGInput::FGInput(FGFDMExec* fdmex) : FGModel(fdmex)
64 : : {
65 : 1 : Name = "FGInput";
66 : 1 : sFirstPass = dFirstPass = true;
67 : 1 : socket = 0;
68 : 1 : port = 0;
69 : 1 : enabled = true;
70 : :
71 : 1 : Debug(0);
72 : 1 : }
73 : :
74 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75 : :
76 : 1 : FGInput::~FGInput()
77 : : {
78 [ - + ][ # # ]: 1 : delete socket;
79 : 1 : Debug(1);
80 : 1 : }
81 : :
82 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 : :
84 : 1 : bool FGInput::InitModel(void)
85 : : {
86 [ - + ]: 1 : if (!FGModel::InitModel()) return false;
87 : :
88 : 1 : return true;
89 : : }
90 : :
91 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
92 : : //
93 : : // This function handles accepting input commands from the socket interface.
94 : : //
95 : :
96 : 54005 : bool FGInput::Run(void)
97 : : {
98 : 54005 : string line, token;
99 : 54005 : size_t start=0, string_start=0, string_end=0;
100 : 54005 : double value=0;
101 : 54005 : FGPropertyManager* node=0;
102 : :
103 [ - + ]: 54005 : if (FGModel::Run()) return true; // fast exit if nothing to do
104 [ + - ]: 54005 : if (port == 0) return false; // Do nothing here if port not defined
105 : : // return false if no error
106 : : // This model DOES execute if "Exec->Holding"
107 : :
108 : 0 : RunPreFunctions();
109 : :
110 : 0 : data = socket->Receive(); // get socket transmission if present
111 : :
112 [ # # ]: 0 : if (data.size() > 0) {
113 : : // parse lines
114 : 0 : while (1) {
115 : 0 : string_start = data.find_first_not_of("\r\n", start);
116 [ # # ]: 0 : if (string_start == string::npos) break;
117 : 0 : string_end = data.find_first_of("\r\n", string_start);
118 [ # # ]: 0 : if (string_end == string::npos) break;
119 : 0 : line = data.substr(string_start, string_end-string_start);
120 [ # # ]: 0 : if (line.size() == 0) break;
121 : :
122 : : // now parse individual line
123 : 0 : vector <string> tokens = split(line,' ');
124 : :
125 : 0 : string command="", argument="", str_value="";
126 [ # # ]: 0 : if (tokens.size() > 0) {
127 : 0 : command = to_lower(tokens[0]);
128 [ # # ]: 0 : if (tokens.size() > 1) {
129 : 0 : argument = trim(tokens[1]);
130 [ # # ]: 0 : if (tokens.size() > 2) {
131 : 0 : str_value = trim(tokens[2]);
132 : : }
133 : : }
134 : : }
135 : :
136 [ # # ]: 0 : if (command == "set") { // SET PROPERTY
137 : :
138 : 0 : node = PropertyManager->GetNode(argument);
139 [ # # ]: 0 : if (node == 0)
140 : 0 : socket->Reply("Unknown property\n");
141 : : else {
142 : 0 : value = atof(str_value.c_str());
143 : 0 : node->setDoubleValue(value);
144 : : }
145 : 0 : socket->Reply("");
146 : :
147 [ # # ]: 0 : } else if (command == "get") { // GET PROPERTY
148 : :
149 [ # # ]: 0 : if (argument.size() == 0) {
150 : 0 : socket->Reply("No property argument supplied.\n");
151 : : break;
152 : : }
153 : : try {
154 : 0 : node = PropertyManager->GetNode(argument);
155 : 0 : } catch(...) {
156 : 0 : socket->Reply("Badly formed property query\n");
157 : : break;
158 : : }
159 [ # # ]: 0 : if (node == 0) {
160 [ # # ]: 0 : if (FDMExec->Holding()) { // if holding can query property list
161 : 0 : string query = FDMExec->QueryPropertyCatalog(argument);
162 : 0 : socket->Reply(query);
163 : : } else {
164 : 0 : socket->Reply("Must be in HOLD to search properties\n");
165 : : }
166 [ # # ]: 0 : } else if (node > 0) {
167 : 0 : ostringstream buf;
168 : 0 : buf << argument << " = " << setw(12) << setprecision(6) << node->getDoubleValue() << endl;
169 : 0 : socket->Reply(buf.str());
170 : : }
171 : :
172 [ # # ]: 0 : } else if (command == "hold") { // PAUSE
173 : :
174 : 0 : FDMExec->Hold();
175 : 0 : socket->Reply("");
176 : :
177 [ # # ]: 0 : } else if (command == "resume") { // RESUME
178 : :
179 : 0 : FDMExec->Resume();
180 : 0 : socket->Reply("");
181 : :
182 [ # # ]: 0 : } else if (command == "quit") { // QUIT
183 : :
184 : : // close the socket connection
185 : 0 : socket->Reply("");
186 : 0 : socket->Close();
187 : :
188 [ # # ]: 0 : } else if (command == "info") { // INFO
189 : :
190 : : // get info about the sim run and/or aircraft, etc.
191 : 0 : ostringstream info;
192 : 0 : info << "JSBSim version: " << JSBSim_version << endl;
193 : 0 : info << "Config File version: " << needed_cfg_version << endl;
194 : 0 : info << "Aircraft simulated: " << Aircraft->GetAircraftName() << endl;
195 : 0 : info << "Simulation time: " << setw(8) << setprecision(3) << FDMExec->GetSimTime() << endl;
196 : 0 : socket->Reply(info.str());
197 : :
198 [ # # ]: 0 : } else if (command == "help") { // HELP
199 : :
200 : : socket->Reply(
201 : : " JSBSim Server commands:\n\n"
202 : : " get {property name}\n"
203 : : " set {property name} {value}\n"
204 : : " hold\n"
205 : : " resume\n"
206 : : " help\n"
207 : : " quit\n"
208 : 0 : " info\n\n");
209 : :
210 : : } else {
211 : 0 : socket->Reply(string("Unknown command: ") + token + string("\n"));
212 : : }
213 : :
214 : 0 : start = string_end;
215 : : }
216 : : }
217 : :
218 : 0 : RunPostFunctions();
219 : :
220 : 54005 : return false;
221 : : }
222 : :
223 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224 : :
225 : 0 : bool FGInput::Load(Element* element)
226 : : {
227 : 0 : string type="", parameter="";
228 : 0 : string name="", fname="";
229 : 0 : string property;
230 : :
231 : : // if the input has already been set up, print a warning message and return
232 [ # # ]: 0 : if (port > 0) {
233 : 0 : cerr << "An input port has already been assigned for this run" << endl;
234 : 0 : return false;
235 : : }
236 : :
237 : 0 : port = int(element->GetAttributeValueAsNumber("port"));
238 [ # # ]: 0 : if (port == 0) {
239 : 0 : cerr << endl << "No port assigned in input element" << endl;
240 : : } else {
241 : 0 : socket = new FGfdmSocket(port);
242 : : }
243 : :
244 : 0 : Debug(2);
245 : :
246 : 0 : return true;
247 : : }
248 : :
249 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 : : // The bitmasked value choices are as follows:
251 : : // unset: In this case (the default) JSBSim would only print
252 : : // out the normally expected messages, essentially echoing
253 : : // the config files as they are read. If the environment
254 : : // variable is not set, debug_lvl is set to 1 internally
255 : : // 0: This requests JSBSim not to output any messages
256 : : // whatsoever.
257 : : // 1: This value explicity requests the normal JSBSim
258 : : // startup messages
259 : : // 2: This value asks for a message to be printed out when
260 : : // a class is instantiated
261 : : // 4: When this value is set, a message is displayed when a
262 : : // FGModel object executes its Run() method
263 : : // 8: When this value is set, various runtime state variables
264 : : // are printed out periodically
265 : : // 16: When set various parameters are sanity checked and
266 : : // a message is printed out when they go out of bounds
267 : :
268 : 2 : void FGInput::Debug(int from)
269 : : {
270 : 2 : string scratch="";
271 : :
272 [ + - ]: 2 : if (debug_lvl <= 0) return;
273 : :
274 : 2 : if (debug_lvl & 1) { // Standard console startup message output
275 : : if (from == 0) { // Constructor
276 : : }
277 : : if (from == 2) {
278 : : }
279 : : }
280 [ - + ]: 2 : if (debug_lvl & 2 ) { // Instantiation/Destruction notification
281 [ # # ]: 0 : if (from == 0) cout << "Instantiated: FGInput" << endl;
282 [ # # ]: 0 : if (from == 1) cout << "Destroyed: FGInput" << endl;
283 : : }
284 : 2 : if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
285 : : }
286 : 2 : if (debug_lvl & 8 ) { // Runtime state variables
287 : : }
288 : 2 : if (debug_lvl & 16) { // Sanity checking
289 : : }
290 [ - + ]: 2 : if (debug_lvl & 64) {
291 [ # # ]: 0 : if (from == 0) { // Constructor
292 : 0 : cout << IdSrc << endl;
293 : 0 : cout << IdHdr << endl;
294 : : }
295 : 2 : }
296 : : }
297 [ + + ][ + - ]: 12 : }
|