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