JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
JSBSim.cpp
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
13  Software Foundation; either version 2 of the License, or (at your option) any
14  later 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
22  with this program; if not, write to the Free Software Foundation, Inc., 59
23  Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25  Further information about the GNU Lesser General Public License can also be
26  found on the world wide web at http://www.gnu.org.
27 
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 
31 This class implements the JSBSim standalone application. It is set up for
32 compilation under gnu C++, MSVC++, or other compiler.
33 
34 HISTORY
35 --------------------------------------------------------------------------------
36 08/17/99 JSB Created
37 
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39 INCLUDES
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
41 
42 #include "initialization/FGTrim.h"
43 #include "FGFDMExec.h"
44 #include "input_output/FGXMLFileRead.h"
45 
46 #if !defined(__GNUC__) && !defined(sgi) && !defined(_MSC_VER)
47 # include <time>
48 #else
49 # include <time.h>
50 #endif
51 
52 #if defined(_MSC_VER)
53 # include <float.h>
54 #elif defined(__GNUC__) && !defined(sgi)
55 # define __GNU_VISIBLE 1
56 # include <fenv.h>
57 #endif
58 
59 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
60 # define WIN32_LEAN_AND_MEAN
61 # include <windows.h>
62 # include <mmsystem.h>
63 # include <regstr.h>
64 # include <sys/types.h>
65 # include <sys/timeb.h>
66 #else
67 # include <sys/time.h>
68 #endif
69 
70 #include <iostream>
71 #include <cstdlib>
72 
73 using namespace std;
75 using JSBSim::Element;
76 
77 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 GLOBAL DATA
79 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
80 
81 SGPath RootDir;
82 SGPath ScriptName;
83 string AircraftName;
84 SGPath ResetName;
85 vector <string> LogOutputName;
86 vector <SGPath> LogDirectiveName;
87 vector <string> CommandLineProperties;
88 vector <double> CommandLinePropertyValues;
89 JSBSim::FGFDMExec* FDMExec;
90 JSBSim::FGTrim* trimmer;
91 
92 bool realtime;
93 bool play_nice;
94 bool suspend;
95 bool catalog;
96 bool nohighlight;
97 
98 double end_time = 1e99;
99 double simulation_rate = 1./120.;
100 bool override_sim_rate = false;
101 double sleep_period=0.01;
102 
103 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 FORWARD DECLARATIONS
105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
106 
107 bool options(int, char**);
108 int real_main(int argc, char* argv[]);
109 void PrintHelp(void);
110 
111 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
112  double getcurrentseconds(void)
113  {
114  struct timeb tm_ptr;
115  ftime(&tm_ptr);
116  return tm_ptr.time + tm_ptr.millitm*0.001;
117  }
118 #else
119  double getcurrentseconds(void)
120  {
121  struct timeval tval;
122  struct timezone tz;
123 
124  gettimeofday(&tval, &tz);
125  return (tval.tv_sec + tval.tv_usec*1e-6);
126  }
127 #endif
128 
129 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
130  void sim_nsleep(long nanosec)
131  {
132  Sleep((DWORD)(nanosec*1e-6)); // convert nanoseconds (passed in) to milliseconds for Win32.
133  }
134 #else
135  void sim_nsleep(long nanosec)
136  {
137  struct timespec ts, ts1;
138 
139  ts.tv_sec = 0;
140  ts.tv_nsec = nanosec;
141  nanosleep(&ts, &ts1);
142  }
143 #endif
144 
147 class XMLFile : public FGXMLFileRead {
148 public:
149  bool IsScriptFile(const SGPath& filename) {
150  bool result=false;
151  Element *document = LoadXMLDocument(filename, false);
152  if (document && document->GetName() == "runscript") result = true;
153  ResetParser();
154  return result;
155  }
156  bool IsLogDirectiveFile(const SGPath& filename) {
157  bool result=false;
158  Element *document = LoadXMLDocument(filename, false);
159  if (document && document->GetName() == "output") result = true;
160  ResetParser();
161  return result;
162  }
163  bool IsAircraftFile(const SGPath& filename) {
164  bool result=false;
165  Element* document = LoadXMLDocument(filename, false);
166  if (document && document->GetName() == "fdm_config") result = true;
167  ResetParser();
168  return result;
169  }
170  bool IsInitFile(const SGPath& filename) {
171  bool result=false;
172  Element *document = LoadXMLDocument(filename, false);
173  if (document && document->GetName() == "initialize") result = true;
174  ResetParser();
175  return result;
176  }
177 };
178 
179 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180 CLASS DOCUMENTATION
181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
182 
277 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278 IMPLEMENTATION
279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
280 
281 int main(int argc, char* argv[])
282 {
283 #if defined(_MSC_VER) || defined(__MINGW32__)
284  _clearfp();
285  _controlfp(_controlfp(0, 0) & ~(_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW),
286  _MCW_EM);
287 #elif defined(__GNUC__) && !defined(sgi) && !defined(__APPLE__)
288  feenableexcept(FE_DIVBYZERO | FE_INVALID);
289 #endif
290 
291  try {
292  real_main(argc, argv);
293  } catch (string& msg) {
294  std::cerr << "FATAL ERROR: JSBSim terminated with an exception."
295  << std::endl << "The message was: " << msg << std::endl;
296  return 1;
297  } catch (const char* msg) {
298  std::cerr << "FATAL ERROR: JSBSim terminated with an exception."
299  << std::endl << "The message was: " << msg << std::endl;
300  return 1;
301  } catch (...) {
302  std::cerr << "FATAL ERROR: JSBSim terminated with an unknown exception."
303  << std::endl;
304  return 1;
305  }
306  return 0;
307 }
308 
309 int real_main(int argc, char* argv[])
310 {
311  // *** INITIALIZATIONS *** //
312 
313  ScriptName = "";
314  AircraftName = "";
315  ResetName = "";
316  LogOutputName.clear();
317  LogDirectiveName.clear();
318  bool result = false, success;
319  bool was_paused = false;
320 
321  double frame_duration;
322 
323  double new_five_second_value = 0.0;
324  double actual_elapsed_time = 0;
325  double initial_seconds = 0;
326  double current_seconds = 0.0;
327  double paused_seconds = 0.0;
328  double sim_lag_time = 0;
329  double cycle_duration = 0.0;
330  double override_sim_rate_value = 0.0;
331  long sleep_nseconds = 0;
332 
333  realtime = false;
334  play_nice = false;
335  suspend = false;
336  catalog = false;
337  nohighlight = false;
338 
339  // *** PARSE OPTIONS PASSED INTO THIS SPECIFIC APPLICATION: JSBSim *** //
340  success = options(argc, argv);
341  if (!success) {
342  PrintHelp();
343  exit(-1);
344  }
345 
346  // *** SET UP JSBSIM *** //
347  FDMExec = new JSBSim::FGFDMExec();
348  FDMExec->SetRootDir(RootDir);
349  FDMExec->SetAircraftPath(SGPath("aircraft"));
350  FDMExec->SetEnginePath(SGPath("engine"));
351  FDMExec->SetSystemsPath(SGPath("systems"));
352  FDMExec->SetOutputPath(SGPath("."));
353  FDMExec->GetPropertyManager()->Tie("simulation/frame_start_time", &actual_elapsed_time);
354  FDMExec->GetPropertyManager()->Tie("simulation/cycle_duration", &cycle_duration);
355 
356  if (nohighlight) FDMExec->disableHighLighting();
357 
358  if (simulation_rate < 1.0 )
359  FDMExec->Setdt(simulation_rate);
360  else
361  FDMExec->Setdt(1.0/simulation_rate);
362 
363  if (override_sim_rate) override_sim_rate_value = FDMExec->GetDeltaT();
364 
365  // SET PROPERTY VALUES THAT ARE GIVEN ON THE COMMAND LINE and which are for the simulation only.
366 
367  for (unsigned int i=0; i<CommandLineProperties.size(); i++) {
368 
369  if (CommandLineProperties[i].find("simulation") != std::string::npos) {
370  if (FDMExec->GetPropertyManager()->GetNode(CommandLineProperties[i])) {
371  FDMExec->SetPropertyValue(CommandLineProperties[i], CommandLinePropertyValues[i]);
372  }
373  }
374  }
375 
376  // *** OPTION A: LOAD A SCRIPT, WHICH LOADS EVERYTHING ELSE *** //
377  if (!ScriptName.isNull()) {
378 
379  result = FDMExec->LoadScript(ScriptName, override_sim_rate_value, ResetName);
380 
381  if (!result) {
382  cerr << "Script file " << ScriptName << " was not successfully loaded" << endl;
383  delete FDMExec;
384  exit(-1);
385  }
386 
387  // *** OPTION B: LOAD AN AIRCRAFT AND A SET OF INITIAL CONDITIONS *** //
388  } else if (!AircraftName.empty() || !ResetName.isNull()) {
389 
390  if (catalog) FDMExec->SetDebugLevel(0);
391 
392  if ( ! FDMExec->LoadModel(SGPath("aircraft"),
393  SGPath("engine"),
394  SGPath("systems"),
395  AircraftName)) {
396  cerr << " JSBSim could not be started" << endl << endl;
397  delete FDMExec;
398  exit(-1);
399  }
400 
401  if (catalog) {
402  FDMExec->PrintPropertyCatalog();
403  delete FDMExec;
404  return 0;
405  }
406 
407  JSBSim::FGInitialCondition *IC = FDMExec->GetIC();
408  if ( ! IC->Load(ResetName)) {
409  delete FDMExec;
410  cerr << "Initialization unsuccessful" << endl;
411  exit(-1);
412  }
413 
414  } else {
415  cout << " No Aircraft, Script, or Reset information given" << endl << endl;
416  delete FDMExec;
417  exit(-1);
418  }
419 
420  // Load output directives file[s], if given
421  for (unsigned int i=0; i<LogDirectiveName.size(); i++) {
422  if (!LogDirectiveName[i].isNull()) {
423  if (!FDMExec->SetOutputDirectives(LogDirectiveName[i])) {
424  cout << "Output directives not properly set in file " << LogDirectiveName[i] << endl;
425  delete FDMExec;
426  exit(-1);
427  }
428  }
429  }
430 
431  // OVERRIDE OUTPUT FILE NAME. THIS IS USEFUL FOR CASES WHERE MULTIPLE
432  // RUNS ARE BEING MADE (SUCH AS IN A MONTE CARLO STUDY) AND THE OUTPUT FILE
433  // NAME MUST BE SET EACH TIME TO AVOID THE PREVIOUS RUN DATA FROM BEING OVER-
434  // WRITTEN.
435  for (unsigned int i=0; i<LogOutputName.size(); i++) {
436  string old_filename = FDMExec->GetOutputFileName(i);
437  if (!FDMExec->SetOutputFileName(i, LogOutputName[i])) {
438  cout << "Output filename could not be set" << endl;
439  } else {
440  cout << "Output filename change from " << old_filename << " from aircraft"
441  " configuration file to " << LogOutputName[i] << " specified on"
442  " command line" << endl;
443  }
444  }
445 
446  // SET PROPERTY VALUES THAT ARE GIVEN ON THE COMMAND LINE
447 
448  for (unsigned int i=0; i<CommandLineProperties.size(); i++) {
449 
450  if (!FDMExec->GetPropertyManager()->GetNode(CommandLineProperties[i])) {
451  cerr << endl << " No property by the name " << CommandLineProperties[i] << endl;
452  delete FDMExec;
453  exit(-1);
454  } else {
455  FDMExec->SetPropertyValue(CommandLineProperties[i], CommandLinePropertyValues[i]);
456  }
457  }
458 
459  FDMExec->RunIC();
460 
461  // PRINT SIMULATION CONFIGURATION
462  FDMExec->PrintSimulationConfiguration();
463 
464  // Dump the simulation state (position, orientation, etc.)
465  FDMExec->GetPropagate()->DumpState();
466 
467  // Perform trim if requested via the initialization file
468  JSBSim::TrimMode icTrimRequested = (JSBSim::TrimMode)FDMExec->GetIC()->TrimRequested();
469  if (icTrimRequested != JSBSim::TrimMode::tNone) {
470  trimmer = new JSBSim::FGTrim( FDMExec, icTrimRequested );
471  try {
472  trimmer->DoTrim();
473 
474  if (FDMExec->GetDebugLevel() > 0)
475  trimmer->Report();
476 
477  delete trimmer;
478  } catch (string& msg) {
479  cerr << endl << msg << endl << endl;
480  exit(1);
481  }
482  }
483 
485  << "---- JSBSim Execution beginning ... --------------------------------------------"
486  << JSBSim::FGFDMExec::reset << endl << endl;
487 
488  result = FDMExec->Run(); // MAKE AN INITIAL RUN
489 
490  if (suspend) FDMExec->Hold();
491 
492  // Print actual time at start
493  char s[100];
494  time_t tod;
495  time(&tod);
496  struct tm local;
497 #if defined(_MSC_VER) || defined(__MINGW32__)
498  localtime_s(&local, &tod);
499 #else
500  localtime_r(&tod, &local);
501 #endif
502  strftime(s, 99, "%A %B %d %Y %X", &local);
503  cout << "Start: " << s << " (HH:MM:SS)" << endl;
504 
505  frame_duration = FDMExec->GetDeltaT();
506  if (realtime) sleep_nseconds = (long)(frame_duration*1e9);
507  else sleep_nseconds = (sleep_period )*1e9; // 0.01 seconds
508 
509  tzset();
510  current_seconds = initial_seconds = getcurrentseconds();
511 
512  // *** CYCLIC EXECUTION LOOP, AND MESSAGE READING *** //
513  while (result && FDMExec->GetSimTime() <= end_time) {
514 
515  FDMExec->ProcessMessage(); // Process messages, if any.
516 
517  // Check if increment then hold is on and take appropriate actions if it is
518  // Iterate is not supported in realtime - only in batch and playnice modes
519  FDMExec->CheckIncrementalHold();
520 
521  // if running realtime, throttle the execution, else just run flat-out fast
522  // unless "playing nice", in which case sleep for a while (0.01 seconds) each frame.
523  // If suspended, then don't increment cumulative realtime "stopwatch".
524 
525  if ( ! FDMExec->Holding()) {
526  if ( ! realtime ) { // ------------ RUNNING IN BATCH MODE
527 
528  result = FDMExec->Run();
529 
530  if (play_nice) sim_nsleep(sleep_nseconds);
531 
532  } else { // ------------ RUNNING IN REALTIME MODE
533 
534  // "was_paused" will be true if entering this "run" loop from a paused state.
535  if (was_paused) {
536  initial_seconds += paused_seconds;
537  was_paused = false;
538  }
539  current_seconds = getcurrentseconds(); // Seconds since 1 Jan 1970
540  actual_elapsed_time = current_seconds - initial_seconds; // Real world elapsed seconds since start
541  sim_lag_time = actual_elapsed_time - FDMExec->GetSimTime(); // How far behind sim-time is from actual
542  // elapsed time.
543  for (int i=0; i<(int)(sim_lag_time/frame_duration); i++) { // catch up sim time to actual elapsed time.
544  result = FDMExec->Run();
545  cycle_duration = getcurrentseconds() - current_seconds; // Calculate cycle duration
546  current_seconds = getcurrentseconds(); // Get new current_seconds
547  if (FDMExec->Holding()) break;
548  }
549 
550  if (play_nice) sim_nsleep(sleep_nseconds);
551 
552  if (FDMExec->GetSimTime() >= new_five_second_value) { // Print out elapsed time every five seconds.
553  cout << "Simulation elapsed time: " << FDMExec->GetSimTime() << endl;
554  new_five_second_value += 5.0;
555  }
556  }
557  } else { // Suspended
558  was_paused = true;
559  paused_seconds = getcurrentseconds() - current_seconds;
560  sim_nsleep(sleep_nseconds);
561  result = FDMExec->Run();
562  }
563 
564  }
565 
566  // PRINT ENDING CLOCK TIME
567  time(&tod);
568 #if defined(_MSC_VER) || defined(__MINGW32__)
569  localtime_s(&local, &tod);
570 #else
571  localtime_r(&tod, &local);
572 #endif
573  strftime(s, 99, "%A %B %d %Y %X", &local);
574  cout << "End: " << s << " (HH:MM:SS)" << endl;
575 
576  // CLEAN UP
577  delete FDMExec;
578 
579  return 0;
580 }
581 
582 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583 
584 #define gripe cerr << "Option '" << keyword \
585  << "' requires a value, as in '" \
586  << keyword << "=something'" << endl << endl;
587 
588 bool options(int count, char **arg)
589 {
590  int i;
591  bool result = true;
592 
593  if (count == 1) {
594  PrintHelp();
595  exit(0);
596  }
597 
598  cout.setf(ios_base::fixed);
599 
600  for (i=1; i<count; i++) {
601  string argument = string(arg[i]);
602  string keyword(argument);
603  string value("");
604  string::size_type n=argument.find("=");
605 
606  if (n != string::npos && n > 0) {
607  keyword = argument.substr(0, n);
608  value = argument.substr(n+1);
609  }
610 
611  if (keyword == "--help") {
612  PrintHelp();
613  exit(0);
614  } else if (keyword == "--version") {
615  cout << endl << " JSBSim Version: " << FDMExec->GetVersion() << endl << endl;
616  exit (0);
617  } else if (keyword == "--realtime") {
618  realtime = true;
619  } else if (keyword == "--nice") {
620  play_nice = true;
621  if (n != string::npos) {
622  try {
623  sleep_period = atof( value.c_str() );
624  } catch (...) {
625  cerr << endl << " Invalid sleep period given!" << endl << endl;
626  result = false;
627  }
628  } else {
629  sleep_period = 0.01;
630  }
631  } else if (keyword == "--suspend") {
632  suspend = true;
633  } else if (keyword == "--nohighlight") {
634  nohighlight = true;
635  } else if (keyword == "--outputlogfile") {
636  if (n != string::npos) {
637  LogOutputName.push_back(value);
638  }
639  } else if (keyword == "--logdirectivefile") {
640  if (n != string::npos) {
641  LogDirectiveName.push_back(SGPath::fromLocal8Bit(value.c_str()));
642  } else {
643  gripe;
644  exit(1);
645  }
646  } else if (keyword == "--root") {
647  if (n != string::npos) {
648  RootDir = SGPath::fromLocal8Bit(value.c_str());
649  } else {
650  gripe;
651  exit(1);
652  }
653  } else if (keyword == "--aircraft") {
654  if (n != string::npos) {
655  AircraftName = value;
656  } else {
657  gripe;
658  exit(1);
659  }
660  } else if (keyword == "--script") {
661  if (n != string::npos) {
662  ScriptName = SGPath::fromLocal8Bit(value.c_str());
663  } else {
664  gripe;
665  exit(1);
666  }
667  } else if (keyword == "--initfile") {
668  if (n != string::npos) {
669  ResetName = SGPath::fromLocal8Bit(value.c_str());
670  } else {
671  gripe;
672  exit(1);
673  }
674 
675  } else if (keyword == "--property") {
676  if (n != string::npos) {
677  string propName = value.substr(0,value.find("="));
678  string propValueString = value.substr(value.find("=")+1);
679  double propValue = atof(propValueString.c_str());
680  CommandLineProperties.push_back(propName);
681  CommandLinePropertyValues.push_back(propValue);
682  } else {
683  gripe;
684  exit(1);
685  }
686 
687  } else if (keyword.substr(0,5) == "--end") {
688  if (n != string::npos) {
689  try {
690  end_time = atof( value.c_str() );
691  } catch (...) {
692  cerr << endl << " Invalid end time given!" << endl << endl;
693  result = false;
694  }
695  } else {
696  gripe;
697  exit(1);
698  }
699 
700  } else if (keyword == "--simulation-rate") {
701  if (n != string::npos) {
702  try {
703  simulation_rate = atof( value.c_str() );
704  override_sim_rate = true;
705  } catch (...) {
706  cerr << endl << " Invalid simulation rate given!" << endl << endl;
707  result = false;
708  }
709  } else {
710  gripe;
711  exit(1);
712  }
713 
714  } else if (keyword == "--catalog") {
715  catalog = true;
716  if (value.size() > 0) AircraftName=value;
717  } else if (keyword.substr(0,2) != "--" && value.empty() ) {
718  // See what kind of files we are specifying on the command line
719 
720  XMLFile xmlFile;
721  SGPath path = SGPath::fromLocal8Bit(keyword.c_str());
722 
723  if (xmlFile.IsScriptFile(path)) ScriptName = path;
724  else if (xmlFile.IsLogDirectiveFile(path)) LogDirectiveName.push_back(path);
725  else if (xmlFile.IsAircraftFile(SGPath("aircraft")/keyword/keyword)) AircraftName = keyword;
726  else if (xmlFile.IsInitFile(path)) ResetName = path;
727  else if (xmlFile.IsInitFile(SGPath("aircraft")/AircraftName/keyword)) ResetName = SGPath("aircraft")/AircraftName/keyword;
728  else {
729  cerr << "The argument \"" << keyword << "\" cannot be interpreted as a file name or option." << endl;
730  exit(1);
731  }
732 
733  }
734  else //Unknown keyword so print the help file, the bad keyword and abort
735  {
736  PrintHelp();
737  cerr << "The argument \"" << keyword << "\" cannot be interpreted as a file name or option." << endl;
738  exit(1);
739  }
740 
741  }
742 
743  // Post-processing for script options. check for incompatible options.
744 
745  if (catalog && !ScriptName.isNull()) {
746  cerr << "Cannot specify catalog with script option" << endl << endl;
747  result = false;
748  }
749  if (!AircraftName.empty() && ResetName.isNull() && !catalog) {
750  cerr << "You must specify an initialization file with the aircraft name." << endl << endl;
751  result = false;
752  }
753  if (!ScriptName.isNull() && !AircraftName.empty()) {
754  cerr << "You cannot specify an aircraft file with a script." << endl;
755  result = false;
756  }
757 
758  return result;
759 
760 }
761 
762 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
763 
764 void PrintHelp(void)
765 {
766  cout << endl << " JSBSim version " << FDMExec->GetVersion() << endl << endl;
767  cout << " Usage: jsbsim [script file name] [output file names] <options>" << endl << endl;
768  cout << " options:" << endl;
769  cout << " --help returns this message" << endl;
770  cout << " --version returns the version number" << endl;
771  cout << " --outputlogfile=<filename> sets (overrides) the name of a data output file" << endl;
772  cout << " --logdirectivefile=<filename> specifies the name of a data logging directives file" << endl;
773  cout << " (can appear multiple times)" << endl;
774  cout << " --root=<path> specifies the JSBSim root directory (where aircraft/, engine/, etc. reside)" << endl;
775  cout << " --aircraft=<filename> specifies the name of the aircraft to be modeled" << endl;
776  cout << " --script=<filename> specifies a script to run" << endl;
777  cout << " --realtime specifies to run in actual real world time" << endl;
778  cout << " --nice specifies to run at lower CPU usage" << endl;
779  cout << " --nohighlight specifies that console output should be pure text only (no color)" << endl;
780  cout << " --suspend specifies to suspend the simulation after initialization" << endl;
781  cout << " --initfile=<filename> specifies an initilization file" << endl;
782  cout << " --catalog specifies that all properties for this aircraft model should be printed" << endl;
783  cout << " (catalog=aircraftname is an optional format)" << endl;
784  cout << " --property=<name=value> e.g. --property=simulation/integrator/rate/rotational=1" << endl;
785  cout << " --simulation-rate=<rate (double)> specifies the sim dT time or frequency" << endl;
786  cout << " If rate specified is less than 1, it is interpreted as" << endl;
787  cout << " a time step size, otherwise it is assumed to be a rate in Hertz." << endl;
788  cout << " --end=<time (double)> specifies the sim end time" << endl << endl;
789 
790  cout << " NOTE: There can be no spaces around the = sign when" << endl;
791  cout << " an option is followed by a filename" << endl << endl;
792 }
JSBSim::FGFDMExec::LoadScript
bool LoadScript(const SGPath &Script, double deltaT=0.0, const SGPath &initfile=SGPath())
Load a script.
Definition: FGFDMExec.cpp:658
JSBSim::FGFDMExec
Encapsulates the JSBSim simulation executive.
Definition: FGFDMExec.h:185
JSBSim::FGInitialCondition::Load
bool Load(const SGPath &rstname, bool useStoredPath=true)
Loads the initial conditions.
Definition: FGInitialCondition.cpp:1002
JSBSim::FGFDMExec::GetIC
FGInitialCondition * GetIC(void)
Returns a pointer to the FGInitialCondition object.
Definition: FGFDMExec.h:387
JSBSim::FGFDMExec::SetRootDir
void SetRootDir(const SGPath &rootDir)
Set the root directory that is used to obtain absolute paths from relative paths.
Definition: FGFDMExec.h:578
JSBSim::FGFDMExec::GetSimTime
double GetSimTime(void) const
Returns the cumulative simulation time in seconds.
Definition: FGFDMExec.h:542
JSBSim::FGFDMExec::GetPropertyManager
FGPropertyManager * GetPropertyManager(void)
Returns a pointer to the property manager object.
Definition: FGFDMExec.cpp:1121
JSBSim::FGFDMExec::SetOutputFileName
bool SetOutputFileName(const int n, const std::string &fname)
Sets (or overrides) the output filename.
Definition: FGFDMExec.h:458
JSBSim::FGFDMExec::SetPropertyValue
void SetPropertyValue(const std::string &property, double value)
Sets a property value.
Definition: FGFDMExec.h:412
JSBSim::FGJSBBase::ProcessMessage
void ProcessMessage(void)
Reads the message on the queue and removes it from the queue.
Definition: FGJSBBase.cpp:148
JSBSim::FGFDMExec::SetDebugLevel
void SetDebugLevel(int level)
Sets the debug level.
Definition: FGFDMExec.h:503
JSBSim::FGTrim::DoTrim
bool DoTrim(void)
Execute the trim.
Definition: FGTrim.cpp:186
JSBSim::FGFDMExec::SetOutputDirectives
bool SetOutputDirectives(const SGPath &fname)
Sets the output (logging) mechanism for this run.
Definition: FGFDMExec.h:445
JSBSim::FGJSBBase::GetVersion
static const std::string & GetVersion(void)
Returns the version number of JSBSim.
Definition: FGJSBBase.h:185
JSBSim::FGFDMExec::Holding
bool Holding(void)
Returns true if the simulation is Holding (i.e. simulation time is not moving).
Definition: FGFDMExec.h:490
JSBSim::FGFDMExec::GetPropagate
FGPropagate * GetPropagate(void)
Returns the FGPropagate pointer.
Definition: FGFDMExec.h:377
JSBSim::FGInitialCondition::TrimRequested
int TrimRequested(void) const
Does initialization file call for trim ?
Definition: FGInitialCondition.h:683
JSBSim::FGFDMExec::GetOutputFileName
std::string GetOutputFileName(int n) const
Retrieves the current output filename.
Definition: FGFDMExec.h:464
JSBSim::FGJSBBase::fggreen
static char fggreen[6]
green text
Definition: FGJSBBase.h:141
JSBSim::FGJSBBase::reset
static char reset[5]
resets text properties
Definition: FGJSBBase.h:129
JSBSim::FGTrim
The trimming routine for JSBSim.
Definition: FGTrim.h:123
JSBSim::FGInitialCondition
Initializes the simulation run.
Definition: FGInitialCondition.h:224
JSBSim::FGFDMExec::CheckIncrementalHold
void CheckIncrementalHold(void)
Checks if required to hold afer increment.
Definition: FGFDMExec.cpp:1137
JSBSim::FGFDMExec::GetDeltaT
double GetDeltaT(void) const
Returns the simulation delta T.
Definition: FGFDMExec.h:545
JSBSim::FGXMLFileRead
Definition: FGXMLFileRead.h:51
JSBSim::FGFDMExec::Hold
void Hold(void)
Pauses execution by preventing time from incrementing.
Definition: FGFDMExec.h:482
JSBSim::Element::GetName
const std::string & GetName(void) const
Retrieves the element name.
Definition: FGXMLElement.h:179
JSBSim::FGFDMExec::SetEnginePath
bool SetEnginePath(const SGPath &path)
Set the path to the engine config file directories.
Definition: FGFDMExec.h:311
JSBSim::FGFDMExec::SetAircraftPath
bool SetAircraftPath(const SGPath &path)
Set the path to the aircraft config file directories.
Definition: FGFDMExec.h:323
JSBSim::FGFDMExec::RunIC
bool RunIC(void)
Initializes the sim from the initial condition object and executes each scheduled model without integ...
Definition: FGFDMExec.cpp:560
XMLFile
This class is solely for the purpose of determining what type of file is given on the command line.
Definition: JSBSim.cpp:147
JSBSim::FGFDMExec::GetDebugLevel
int GetDebugLevel(void) const
Retrieves the current debug level setting.
Definition: FGFDMExec.h:594
JSBSim::FGFDMExec::Setdt
void Setdt(double delta_t)
Sets the integration time step for the simulation executive.
Definition: FGFDMExec.h:564
JSBSim::FGTrim::Report
void Report(void)
Print the results of the trim.
Definition: FGTrim.cpp:113
JSBSim::FGFDMExec::SetSystemsPath
bool SetSystemsPath(const SGPath &path)
Set the path to the systems config file directories.
Definition: FGFDMExec.h:334
JSBSim::FGJSBBase::highint
static char highint[5]
highlights text
Definition: FGJSBBase.h:123
JSBSim::FGFDMExec::LoadModel
bool LoadModel(const SGPath &AircraftPath, const SGPath &EnginePath, const SGPath &SystemsPath, const std::string &model, bool addModelToPath=true)
Loads an aircraft model.
Definition: FGFDMExec.cpp:671
JSBSim::FGJSBBase::disableHighLighting
void disableHighLighting(void)
Disables highlighting in the console output.
Definition: FGJSBBase.cpp:191
JSBSim::FGFDMExec::Run
bool Run(void)
This function executes each scheduled model in succession.
Definition: FGFDMExec.cpp:325
JSBSim::Element
Definition: FGXMLElement.h:143
JSBSim::FGPropertyManager::Tie
void Tie(const std::string &name, T *pointer)
Tie a property to an external variable.
Definition: FGPropertyManager.h:449
JSBSim::FGFDMExec::SetOutputPath
bool SetOutputPath(const SGPath &path)
Set the directory where the output files will be written.
Definition: FGFDMExec.h:345