Branch data Line data Source code
1 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 : :
3 : : Module: JSBSim.cpp
4 : : Author: Jon S. Berndt
5 : : Date started: 08/17/99
6 : : Purpose: Standalone version of JSBSim.
7 : : Called by: The USER.
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 : :
31 : : This class Handles calling JSBSim standalone. It is set up for compilation under
32 : : Borland C+Builder or other compiler.
33 : :
34 : : HISTORY
35 : : --------------------------------------------------------------------------------
36 : : 08/17/99 JSB Created
37 : :
38 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39 : : INCLUDES
40 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
41 : :
42 : : #include "FGFDMExec.h"
43 : : //#include <initialization/FGTrimAnalysis.h>
44 : :
45 : : #if !defined(__GNUC__) && !defined(sgi) && !defined(_MSC_VER)
46 : : # include <time>
47 : : #else
48 : : # include <time.h>
49 : : #endif
50 : :
51 : : #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
52 : : # define WIN32_LEAN_AND_MEAN
53 : : # include <windows.h>
54 : : # include <mmsystem.h>
55 : : # include <regstr.h>
56 : : # include <sys/types.h>
57 : : # include <sys/timeb.h>
58 : : #else
59 : : # include <sys/time.h>
60 : : #endif
61 : :
62 : : #include <iostream>
63 : : #include <cstdlib>
64 : :
65 : : using namespace std;
66 : :
67 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
68 : : DEFINITIONS
69 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
70 : :
71 : : static const char *IdSrc = "$Id: JSBSim.cpp,v 1.60 2010/08/11 11:49:44 jberndt Exp $";
72 : :
73 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74 : : GLOBAL DATA
75 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
76 : :
77 : 4 : string RootDir = "";
78 : 4 : string ScriptName;
79 : 4 : string AircraftName;
80 : 4 : string ResetName;
81 : 4 : string LogOutputName;
82 : 2 : vector <string> LogDirectiveName;
83 : 2 : vector <string> CommandLineProperties;
84 [ + + ][ + - ]: 4 : vector <double> CommandLinePropertyValues;
85 : : JSBSim::FGFDMExec* FDMExec;
86 : : bool realtime;
87 : : bool play_nice;
88 : : bool suspend;
89 : : bool catalog;
90 : :
91 : : double end_time = 1e99;
92 : : double simulation_rate = 1./120.;
93 : : bool override_sim_rate = false;
94 : :
95 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
96 : : FORWARD DECLARATIONS
97 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
98 : :
99 : : bool options(int, char**);
100 : : void PrintHelp(void);
101 : :
102 : : #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
103 : : double getcurrentseconds(void)
104 : : {
105 : : struct timeb tm_ptr;
106 : : ftime(&tm_ptr);
107 : : return tm_ptr.time + tm_ptr.millitm*0.001;
108 : : }
109 : : #else
110 : 1 : double getcurrentseconds(void)
111 : : {
112 : : struct timeval tval;
113 : : struct timezone tz;
114 : :
115 : 1 : gettimeofday(&tval, &tz);
116 : 1 : return (tval.tv_sec + tval.tv_usec*1e-6);
117 : : }
118 : : #endif
119 : :
120 : : #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
121 : : void sim_nsleep(long nanosec)
122 : : {
123 : : Sleep(nanosec*1e-6); // convert nanoseconds (passed in) to milliseconds for Win32.
124 : : }
125 : : #else
126 : 0 : void sim_nsleep(long nanosec)
127 : : {
128 : : struct timespec ts, ts1;
129 : :
130 : 0 : ts.tv_sec = 0;
131 : 0 : ts.tv_nsec = nanosec;
132 : 0 : nanosleep(&ts, &ts1);
133 : 0 : }
134 : : #endif
135 : :
136 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137 : : CLASS DOCUMENTATION
138 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
139 : :
140 : : /** \mainpage JSBSim
141 : : * An Open Source, Object-Oriented, Cross-Platform Flight Dynamics Model in C++
142 : :
143 : : * \section intro Introduction
144 : : *
145 : : * JSBSim is an open source, multi-platform, object-oriented flight dynamics
146 : : * model (FDM) framework written in the C++ programming language. It is
147 : : * designed to support simulation modeling of any aerospace craft without the
148 : : * need for specific compiled and linked program code, instead relying on a
149 : : * relatively simple model specification written in a XML format. The format is
150 : : * formally known as JSBSim-ML (JSBSim Markup Language).
151 : : *
152 : : * JSBSim (www.jsbsim.org) was created initially for the open source FlightGear
153 : : * flight simulator (www.flightgear.org), where it replaced LaRCSim (Langley
154 : : * Research Center Simulation) as the default FDM. JSBSim also maintains the
155 : : * ability to run in a standalone, batch mode. This is useful for running tests
156 : : * or sets of tests automatically using the internal scripting capability.
157 : : *
158 : : * Differently from LaRCSim, JSBSim does not model specific aircraft in program
159 : : * code. The aircraft itself is defined in a file written in an XML-based format
160 : : * where the aircraft mass and geometric properties are specified. Additional
161 : : * statements define:
162 : : *
163 : : * - Landing gear location and properties.
164 : : * - Pilot eyepoint
165 : : * - Additional point masses (passengers, cargo, etc.)
166 : : * - Propulsion system (engines, fuel tanks, and "thrusters")
167 : : * - Flight control system
168 : : * - Autopilot
169 : : * - Aerodynamic stability derivatives and coefficients
170 : : *
171 : : * The configuration file format is set up to be easily comprehensible, for
172 : : * instance featuring textbook-like coefficients, which enables newcomers to
173 : : * become immediately fluent in describing vehicles, and requiring only prior
174 : : * basic theoretical aero knowledge.
175 : : *
176 : : * One of the more unique features of JSBSim is its method of modeling flight
177 : : * control systems and an autopilot. These are modeled by assembling strings
178 : : * of components that represent filters, switches, summers, gains, sensors, etc.
179 : : *
180 : : * Another unique feature is displayed in the use of "properties". Properties
181 : : * essentially expose chosen variables as nodes in a tree, in a directory-like
182 : : * hierarchy. This approach facilitates plugging in different FDMs into
183 : : * FlightGear, but it also is a fundamental tool in allowing a wide range of
184 : : * aircraft to be modeled, each having its own unique control system,
185 : : * aerosurfaces, and flight deck instrument panel. The use of properties allows
186 : : * all these items for a craft to be modeled and integrated without the need for
187 : : * specific and unique program source code.
188 : : *
189 : : * The equations of motion are modeled essentially as they are presented in
190 : : * aerospace textbooks for the benefit of student users, but quaternions are
191 : : * used to track orientation, avoiding "gimbal lock". While JSBSim is
192 : : * designed to model primarily atmospheric flight at lower speeds, coriolis and
193 : : * centripetal accelerations are incorporated into the EOM to
194 : : * permit a wider range of vehicles to be simulated.
195 : : *
196 : : * Currently under development is an expansion of the atmospheric modeling for
197 : : * JSBSim. The existing model approximates the standard atmosphere of 1976.
198 : : * Recently, source code for the NRLMSISE-00 model was obtained and this is
199 : : * being implemented as a C++ class that can optionally be used. Also, a simple
200 : : * Mars atmosphere is being implemented.
201 : : *
202 : : * JSBSim can output (log) data in a configurable way. Sets of data that are
203 : : * logically related can be selected to be output at a chosen rate, and
204 : : * individual properties can be selected for output. The output can be streamed
205 : : * to the console, or to a file, and can also be transmitted through a socket.
206 : : *
207 : : * JSBSim has been used in a variety of ways:
208 : : *
209 : : * - For developing control laws for a sounding rocket
210 : : * - For crafting an aircraft autopilot as part of a thesis project
211 : : * - As a flight model for FlightGear
212 : : * - As an FDM that drives motion base simulators for some
213 : : * commercial/entertainment simulators
214 : : *
215 : : * \section Supported Platforms:
216 : : * JSBSim has been built on the following platforms:
217 : : *
218 : : * - Linux (x86)
219 : : * - Windows (MSVC, Cygwin, Mingwin)
220 : : * - SGI (native compilers)
221 : : * - Mac OS X
222 : : * - FreeBSD
223 : : *
224 : : * \section depends Dependencies
225 : : *
226 : : * JSBSim has no dependencies at present.
227 : : *
228 : : * \section license Licensing
229 : : *
230 : : * JSBSim is licensed under the terms of the Lesser GPL (LGPL)
231 : : *
232 : : * \section website Website
233 : : *
234 : : * For more information, see the JSBSim web site: www.jsbsim.org.
235 : : */
236 : :
237 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 : : IMPLEMENTATION
239 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
240 : :
241 : 2 : int main(int argc, char* argv[])
242 : : {
243 : : // *** INITIALIZATIONS *** //
244 : :
245 : : ScriptName = "";
246 : : AircraftName = "";
247 : : ResetName = "";
248 : : LogOutputName = "";
249 : : LogDirectiveName.clear();
250 : 2 : bool result = false, success;
251 : 2 : bool was_paused = false;
252 : :
253 : : double frame_duration;
254 : :
255 : 2 : double new_five_second_value = 0.0;
256 : 2 : double actual_elapsed_time = 0;
257 : 2 : double initial_seconds = 0;
258 : 2 : double current_seconds = 0.0;
259 : 2 : double paused_seconds = 0.0;
260 : 2 : double sim_lag_time = 0;
261 : 2 : double cycle_duration = 0.0;
262 : 2 : double override_sim_rate_value = 0.0;
263 : 2 : long sleep_nseconds = 0;
264 : :
265 : 2 : realtime = false;
266 : 2 : play_nice = false;
267 : 2 : suspend = false;
268 : 2 : catalog=false;
269 : :
270 : : // *** PARSE OPTIONS PASSED INTO THIS SPECIFIC APPLICATION: JSBSim *** //
271 : 2 : success = options(argc, argv);
272 [ + + ]: 2 : if (!success) {
273 : 1 : PrintHelp();
274 : 1 : exit(-1);
275 : : }
276 : :
277 : : // *** SET UP JSBSIM *** //
278 : 1 : FDMExec = new JSBSim::FGFDMExec();
279 : 2 : FDMExec->SetRootDir(RootDir);
280 : 2 : FDMExec->SetAircraftPath("aircraft");
281 : 2 : FDMExec->SetEnginePath("engine");
282 : 2 : FDMExec->SetSystemsPath("systems");
283 : 1 : FDMExec->GetPropertyManager()->Tie("simulation/frame_start_time", &actual_elapsed_time);
284 : 1 : FDMExec->GetPropertyManager()->Tie("simulation/cycle_duration", &cycle_duration);
285 : :
286 [ + - ]: 1 : if (simulation_rate < 1.0 )
287 : 1 : FDMExec->Setdt(simulation_rate);
288 : : else
289 : 0 : FDMExec->Setdt(1.0/simulation_rate);
290 : :
291 [ - + ]: 1 : if (override_sim_rate) override_sim_rate_value = FDMExec->GetDeltaT();
292 : :
293 : : // *** OPTION A: LOAD A SCRIPT, WHICH LOADS EVERYTHING ELSE *** //
294 [ + - ]: 1 : if (!ScriptName.empty()) {
295 : :
296 : 1 : result = FDMExec->LoadScript(ScriptName, override_sim_rate_value);
297 : :
298 [ - + ]: 1 : if (!result) {
299 : 0 : cerr << "Script file " << ScriptName << " was not successfully loaded" << endl;
300 [ # # ]: 0 : delete FDMExec;
301 : 0 : exit(-1);
302 : : }
303 : :
304 : : // *** OPTION B: LOAD AN AIRCRAFT AND A SET OF INITIAL CONDITIONS *** //
305 [ # # ][ # # ]: 0 : } else if (!AircraftName.empty() || !ResetName.empty()) {
[ # # ]
306 : :
307 [ # # ]: 0 : if (catalog) FDMExec->SetDebugLevel(0);
308 : :
309 [ # # ]: 0 : if ( ! FDMExec->LoadModel( "aircraft",
310 : : "engine",
311 : : "systems",
312 : : AircraftName)) {
313 : 0 : cerr << " JSBSim could not be started" << endl << endl;
314 [ # # ]: 0 : delete FDMExec;
315 : 0 : exit(-1);
316 : : }
317 : :
318 [ # # ]: 0 : if (catalog) {
319 : 0 : FDMExec->PrintPropertyCatalog();
320 [ # # ]: 0 : delete FDMExec;
321 : 0 : return 0;
322 : : }
323 : :
324 : 0 : JSBSim::FGInitialCondition *IC = FDMExec->GetIC();
325 [ # # ]: 0 : if ( ! IC->Load(ResetName)) {
326 [ # # ]: 0 : delete FDMExec;
327 : 0 : cerr << "Initialization unsuccessful" << endl;
328 : 0 : exit(-1);
329 : : }
330 : :
331 : : } else {
332 : 0 : cout << " No Aircraft, Script, or Reset information given" << endl << endl;
333 [ # # ]: 0 : delete FDMExec;
334 : 0 : exit(-1);
335 : : }
336 : :
337 : : // Load output directives file, if given
338 [ - + ]: 1 : for (unsigned int i=0; i<LogDirectiveName.size(); i++) {
339 [ # # ]: 0 : if (!LogDirectiveName[i].empty()) {
340 [ # # ]: 0 : if (!FDMExec->SetOutputDirectives(LogDirectiveName[i])) {
341 : 0 : cout << "Output directives not properly set in file " << LogDirectiveName[i] << endl;
342 [ # # ]: 0 : delete FDMExec;
343 : 0 : exit(-1);
344 : : }
345 : : }
346 : : }
347 : :
348 : : // OVERRIDE OUTPUT FILE NAME. THIS IS USEFUL FOR CASES WHERE MULTIPLE
349 : : // RUNS ARE BEING MADE (SUCH AS IN A MONTE CARLO STUDY) AND THE OUTPUT FILE
350 : : // NAME MUST BE SET EACH TIME TO AVOID THE PREVIOUS RUN DATA FROM BEING OVER-
351 : : // WRITTEN. THIS OVERRIDES ONLY THE FILENAME FOR THE FIRST FILE.
352 [ - + ]: 1 : if (!LogOutputName.empty()) {
353 : 0 : string old_filename = FDMExec->GetOutputFileName();
354 [ # # ]: 0 : if (!FDMExec->SetOutputFileName(LogOutputName)) {
355 : 0 : cout << "Output filename could not be set" << endl;
356 : : } else {
357 : : cout << "Output filename change from " << old_filename << " from aircraft"
358 : : " configuration file to " << LogOutputName << " specified on"
359 : 0 : " command line" << endl;
360 : 0 : }
361 : : }
362 : :
363 : : // SET PROPERTY VALUES THAT ARE GIVEN ON THE COMMAND LINE
364 : :
365 [ - + ]: 1 : for (unsigned int i=0; i<CommandLineProperties.size(); i++) {
366 : :
367 [ # # ]: 0 : if (!FDMExec->GetPropertyManager()->GetNode(CommandLineProperties[i])) {
368 : 0 : cerr << endl << " No property by the name " << CommandLineProperties[i] << endl;
369 : : goto quit;
370 : : } else {
371 : 0 : FDMExec->SetPropertyValue(CommandLineProperties[i], CommandLinePropertyValues[i]);
372 : : }
373 : : }
374 : :
375 : : cout << endl << JSBSim::FGFDMExec::fggreen << JSBSim::FGFDMExec::highint
376 : : << "---- JSBSim Execution beginning ... --------------------------------------------"
377 : 1 : << JSBSim::FGFDMExec::reset << endl << endl;
378 : :
379 : 1 : result = FDMExec->Run(); // MAKE AN INITIAL RUN
380 : :
381 [ - + ]: 1 : if (suspend) FDMExec->Hold();
382 : :
383 : : // Print actual time at start
384 : : char s[100];
385 : : time_t tod;
386 : 1 : time(&tod);
387 : 1 : strftime(s, 99, "%A %B %d %Y %X", localtime(&tod));
388 : 1 : cout << "Start: " << s << " (HH:MM:SS)" << endl;
389 : :
390 : 2 : frame_duration = FDMExec->GetDeltaT();
391 [ - + ]: 1 : if (realtime) sleep_nseconds = (long)(frame_duration*1e9);
392 : 1 : else sleep_nseconds = (10000000); // 0.01 seconds
393 : :
394 : 1 : tzset();
395 : 1 : current_seconds = initial_seconds = getcurrentseconds();
396 : :
397 : : // *** CYCLIC EXECUTION LOOP, AND MESSAGE READING *** //
398 [ + + ][ + - ]: 54004 : while (result && FDMExec->GetSimTime() <= end_time) {
[ + + ]
399 : :
400 : 54003 : FDMExec->ProcessMessage(); // Process messages, if any.
401 : :
402 : : // if running realtime, throttle the execution, else just run flat-out fast
403 : : // unless "playing nice", in which case sleep for a while (0.01 seconds) each frame.
404 : : // If suspended, then don't increment cumulative realtime "stopwatch".
405 : :
406 [ + - ]: 54003 : if ( ! FDMExec->Holding()) {
407 [ + - ]: 54003 : if ( ! realtime ) { // ------------ RUNNING IN BATCH MODE
408 : :
409 : 54003 : result = FDMExec->Run();
410 : :
411 [ - + ]: 54003 : if (play_nice) sim_nsleep(sleep_nseconds);
412 : :
413 : : } else { // ------------ RUNNING IN REALTIME MODE
414 : :
415 : : // "was_paused" will be true if entering this "run" loop from a paused state.
416 [ # # ]: 0 : if (was_paused) {
417 : 0 : initial_seconds += paused_seconds;
418 : 0 : was_paused = false;
419 : : }
420 : 0 : current_seconds = getcurrentseconds(); // Seconds since 1 Jan 1970
421 : 0 : actual_elapsed_time = current_seconds - initial_seconds; // Real world elapsed seconds since start
422 : 0 : sim_lag_time = actual_elapsed_time - FDMExec->GetSimTime(); // How far behind sim-time is from actual
423 : : // elapsed time.
424 [ # # ]: 0 : for (int i=0; i<(int)(sim_lag_time/frame_duration); i++) { // catch up sim time to actual elapsed time.
425 : 0 : result = FDMExec->Run();
426 : 0 : cycle_duration = getcurrentseconds() - current_seconds; // Calculate cycle duration
427 : 0 : current_seconds = getcurrentseconds(); // Get new current_seconds
428 [ # # ]: 0 : if (FDMExec->Holding()) break;
429 : : }
430 : :
431 [ # # ]: 0 : if (play_nice) sim_nsleep(sleep_nseconds);
432 : :
433 [ # # ]: 0 : if (FDMExec->GetSimTime() >= new_five_second_value) { // Print out elapsed time every five seconds.
434 : 0 : cout << "Simulation elapsed time: " << FDMExec->GetSimTime() << endl;
435 : 0 : new_five_second_value += 5.0;
436 : : }
437 : : }
438 : : } else { // Suspended
439 : 0 : was_paused = true;
440 : 0 : paused_seconds = getcurrentseconds() - current_seconds;
441 : 0 : sim_nsleep(sleep_nseconds);
442 : 0 : result = FDMExec->Run();
443 : : }
444 : :
445 : : }
446 : :
447 : 1 : quit:
448 : :
449 : : // PRINT ENDING CLOCK TIME
450 : 1 : time(&tod);
451 : 1 : strftime(s, 99, "%A %B %d %Y %X", localtime(&tod));
452 : 1 : cout << "End: " << s << " (HH:MM:SS)" << endl;
453 : :
454 : : // CLEAN UP
455 [ + - ]: 1 : delete FDMExec;
456 : :
457 : 1 : return 0;
458 : : }
459 : :
460 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461 : :
462 : 2 : bool options(int count, char **arg)
463 : : {
464 : : int i;
465 : 2 : bool result = true;
466 : :
467 [ - + ]: 2 : if (count == 1) {
468 : 0 : PrintHelp();
469 : 0 : exit(0);
470 : : }
471 : :
472 : : cout.setf(ios_base::fixed);
473 : :
474 : : #define gripe cerr << "Option '" << keyword \
475 : : << "' requires a value, as in '" \
476 : : << keyword << "=something'" << endl << endl;/**/
477 : :
478 [ + + ]: 4 : for (i=1; i<count; i++) {
479 : 2 : string argument = string(arg[i]);
480 : 2 : string keyword(argument);
481 : 2 : string value("");
482 : 2 : string::size_type n=argument.find("=");
483 [ + - ]: 2 : if (n != string::npos && n > 0) {
484 : 4 : keyword = argument.substr(0, n);
485 : 4 : value = argument.substr(n+1);
486 : : }
487 : :
488 [ - + ]: 2 : if (keyword == "--help") {
489 : 0 : PrintHelp();
490 : 0 : exit(0);
491 [ - + ]: 2 : } else if (keyword == "--version") {
492 : 0 : cout << endl << " JSBSim Version: " << FDMExec->GetVersion() << endl << endl;
493 : 0 : exit (0);
494 [ - + ]: 2 : } else if (keyword == "--realtime") {
495 : 0 : realtime = true;
496 [ - + ]: 2 : } else if (keyword == "--nice") {
497 : 0 : play_nice = true;
498 [ - + ]: 2 : } else if (keyword == "--suspend") {
499 : 0 : suspend = true;
500 [ - + ]: 2 : } else if (keyword == "--outputlogfile") {
501 [ # # ]: 0 : if (n != string::npos) {
502 : : LogOutputName = value;
503 : : } else {
504 : : LogOutputName = "JSBout.csv";
505 : 0 : cerr << " Output log file name must be specified with an = sign. Using JSBout.csv as default";
506 : : }
507 [ - + ]: 2 : } else if (keyword == "--logdirectivefile") {
508 [ # # ]: 0 : if (n != string::npos) {
509 : 0 : LogDirectiveName.push_back(value);
510 : : } else {
511 : 0 : gripe;
512 : 0 : exit(1);
513 : : }
514 [ - + ]: 2 : } else if (keyword == "--root") {
515 [ # # ]: 0 : if (n != string::npos) {
516 : : RootDir = value;
517 [ # # ]: 0 : if (RootDir[RootDir.length()-1] != '/') {
518 : : RootDir += '/';
519 : : }
520 : : } else {
521 : 0 : gripe;
522 : 0 : exit(1);
523 : : }
524 [ - + ]: 2 : } else if (keyword == "--aircraft") {
525 [ # # ]: 0 : if (n != string::npos) {
526 : : AircraftName = value;
527 : : } else {
528 : 0 : gripe;
529 : 0 : exit(1);
530 : : }
531 [ + + ]: 2 : } else if (keyword == "--script") {
532 [ + - ]: 1 : if (n != string::npos) {
533 : : ScriptName = value;
534 : : } else {
535 : 0 : gripe;
536 : 0 : exit(1);
537 : : }
538 [ - + ]: 1 : } else if (keyword == "--initfile") {
539 [ # # ]: 0 : if (n != string::npos) {
540 : : ResetName = value;
541 : : } else {
542 : 0 : gripe;
543 : 0 : exit(1);
544 : : }
545 : :
546 [ - + ]: 1 : } else if (keyword == "--property") {
547 [ # # ]: 0 : if (n != string::npos) {
548 : 0 : string propName = value.substr(0,value.find("="));
549 : 0 : string propValueString = value.substr(value.find("=")+1);
550 : 0 : double propValue = atof(propValueString.c_str());
551 : 0 : CommandLineProperties.push_back(propName);
552 : 0 : CommandLinePropertyValues.push_back(propValue);
553 : : } else {
554 : 0 : gripe;
555 : 0 : exit(1);
556 : : }
557 : :
558 [ - + ]: 1 : } else if (keyword == "--end-time") {
559 [ # # ]: 0 : if (n != string::npos) {
560 : : try {
561 : 0 : end_time = atof( value.c_str() );
562 : : } catch (...) {
563 : : cerr << endl << " Invalid end time given!" << endl << endl;
564 : : result = false;
565 : : }
566 : : } else {
567 : 0 : gripe;
568 : 0 : exit(1);
569 : : }
570 : :
571 [ - + ]: 1 : } else if (keyword == "--simulation-rate") {
572 [ # # ]: 0 : if (n != string::npos) {
573 : : try {
574 : 0 : simulation_rate = atof( value.c_str() );
575 : 0 : override_sim_rate = true;
576 : : } catch (...) {
577 : : cerr << endl << " Invalid simulation rate given!" << endl << endl;
578 : : result = false;
579 : : }
580 : : } else {
581 : 0 : gripe;
582 : 0 : exit(1);
583 : : }
584 : :
585 [ - + ]: 1 : } else if (keyword == "--catalog") {
586 : 0 : catalog = true;
587 [ # # ]: 0 : if (value.size() > 0) AircraftName=value;
588 : : } else {
589 : 1 : cerr << endl << " Parameter: " << argument << " not understood" << endl;
590 : 1 : result = false;
591 : : }
592 : : }
593 : :
594 : : // Post-processing for script options. check for incompatible options.
595 : :
596 [ - + ][ # # ]: 2 : if (catalog && !ScriptName.empty()) {
[ - + ]
597 : 0 : cerr << "Cannot specify catalog with script option" << endl << endl;
598 : 0 : result = false;
599 : : }
600 : : if (AircraftName.size() > 0 && ResetName.size() == 0 && !catalog) {
601 : 0 : cerr << "You must specify an initialization file with the aircraft name." << endl << endl;
602 : 0 : result = false;
603 : : }
604 [ + + ][ + - ]: 2 : if ((ScriptName.size() > 0 && AircraftName.size() > 0) || (ScriptName.size() > 0 && ResetName.size() > 0)) {
[ + + ][ - + ]
[ - + ]
605 : 0 : cerr << "You cannot specify an aircraft or initialization file with a script." << endl;
606 : 0 : result = false;
607 : : }
608 : :
609 : 2 : return result;
610 : :
611 : : }
612 : :
613 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
614 : :
615 : 1 : void PrintHelp(void)
616 : : {
617 : 2 : cout << endl << " JSBSim version " << FDMExec->GetVersion() << endl << endl;
618 : 1 : cout << " Usage: jsbsim <options>" << endl << endl;
619 : 1 : cout << " options:" << endl;
620 : 1 : cout << " --help returns this message" << endl;
621 : 1 : cout << " --version returns the version number" << endl;
622 : 1 : cout << " --outputlogfile=<filename> sets (overrides) the name of the first data output file" << endl;
623 : 1 : cout << " --logdirectivefile=<filename> specifies the name of a data logging directives file" << endl;
624 : 1 : cout << " (can appear multiple times)" << endl;
625 : 1 : cout << " --root=<path> specifies the JSBSim root directory (where aircraft/, engine/, etc. reside)" << endl;
626 : 1 : cout << " --aircraft=<filename> specifies the name of the aircraft to be modeled" << endl;
627 : 1 : cout << " --script=<filename> specifies a script to run" << endl;
628 : 1 : cout << " --realtime specifies to run in actual real world time" << endl;
629 : 1 : cout << " --nice specifies to run at lower CPU usage" << endl;
630 : 1 : cout << " --suspend specifies to suspend the simulation after initialization" << endl;
631 : 1 : cout << " --initfile=<filename> specifies an initilization file" << endl;
632 : 1 : cout << " --catalog specifies that all properties for this aircraft model should be printed" << endl;
633 : 1 : cout << " (catalog=aircraftname is an optional format)" << endl;
634 : 1 : cout << " --property=<name=value> e.g. --property=simulation/integrator/rate/rotational=1" << endl;
635 : 1 : cout << " --simulation-rate=<rate (double)> specifies the sim dT time or frequency" << endl;
636 : 1 : cout << " --end-time=<time (double)> specifies the sim end time" << endl << endl;
637 : :
638 : 1 : cout << " NOTE: There can be no spaces around the = sign when" << endl;
639 : 1 : cout << " an option is followed by a filename" << endl << endl;
640 [ + + ][ + - ]: 13 : }
641 : :
|