JSBSim Flight Dynamics Model 1.0 (23 February 2013)
An Open Source Flight Dynamics and Control Software Library in C++

JSBSim.cpp

00001 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00002 
00003  Module:       JSBSim.cpp
00004  Author:       Jon S. Berndt
00005  Date started: 08/17/99
00006  Purpose:      Standalone version of JSBSim.
00007  Called by:    The USER.
00008 
00009  ------------- Copyright (C) 1999  Jon S. Berndt (jon@jsbsim.org) -------------
00010 
00011  This program is free software; you can redistribute it and/or modify it under
00012  the terms of the GNU Lesser General Public License as published by the Free Software
00013  Foundation; either version 2 of the License, or (at your option) any later
00014  version.
00015 
00016  This program is distributed in the hope that it will be useful, but WITHOUT
00017  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00019  details.
00020 
00021  You should have received a copy of the GNU Lesser General Public License along with
00022  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00023  Place - Suite 330, Boston, MA  02111-1307, USA.
00024 
00025  Further information about the GNU Lesser General Public License can also be found on
00026  the world wide web at http://www.gnu.org.
00027 
00028 FUNCTIONAL DESCRIPTION
00029 --------------------------------------------------------------------------------
00030 
00031 This class implements the JSBSim standalone application. It is set up for compilation
00032 under gnu C++, MSVC++, or other compiler.
00033 
00034 HISTORY
00035 --------------------------------------------------------------------------------
00036 08/17/99   JSB   Created
00037 
00038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00039 INCLUDES
00040 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00041 
00042 #include "FGFDMExec.h"
00043 #include "input_output/FGXMLFileRead.h"
00044 
00045 #if !defined(__GNUC__) && !defined(sgi) && !defined(_MSC_VER)
00046 #  include <time>
00047 #else
00048 #  include <time.h>
00049 #endif
00050 
00051 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
00052 #  define WIN32_LEAN_AND_MEAN
00053 #  include <windows.h>
00054 #  include <mmsystem.h>
00055 #  include <regstr.h>
00056 #  include <sys/types.h>
00057 #  include <sys/timeb.h>
00058 #else
00059 #  include <sys/time.h>
00060 #endif
00061 
00062 #include <iostream>
00063 #include <cstdlib>
00064 
00065 using namespace std;
00066 using JSBSim::FGXMLFileRead;
00067 
00068 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00069 DEFINITIONS
00070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00071 
00072 static const char *IdSrc = "$Id: JSBSim.cpp,v 1.78 2012/09/18 12:42:29 jberndt Exp $";
00073 
00074 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00075 GLOBAL DATA
00076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00077 
00078 string RootDir = "";
00079 string ScriptName;
00080 string AircraftName;
00081 string ResetName;
00082 string LogOutputName;
00083 vector <string> LogDirectiveName;
00084 vector <string> CommandLineProperties;
00085 vector <double> CommandLinePropertyValues;
00086 JSBSim::FGFDMExec* FDMExec;
00087 bool realtime;
00088 bool play_nice;
00089 bool suspend;
00090 bool catalog;
00091 bool nohighlight;
00092 
00093 double end_time = 1e99;
00094 double simulation_rate = 1./120.;
00095 bool override_sim_rate = false;
00096 double sleep_period=0.01;
00097 
00098 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00099 FORWARD DECLARATIONS
00100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00101 
00102 bool options(int, char**);
00103 int real_main(int argc, char* argv[]);
00104 void PrintHelp(void);
00105 
00106 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
00107   double getcurrentseconds(void)
00108   {
00109     struct timeb tm_ptr;
00110     ftime(&tm_ptr);
00111     return tm_ptr.time + tm_ptr.millitm*0.001;
00112   }
00113 #else
00114   double getcurrentseconds(void)
00115   {
00116     struct timeval tval;
00117     struct timezone tz;
00118 
00119     gettimeofday(&tval, &tz);
00120     return (tval.tv_sec + tval.tv_usec*1e-6);
00121   }
00122 #endif
00123 
00124 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
00125   void sim_nsleep(long nanosec)
00126   {
00127     Sleep((DWORD)(nanosec*1e-6)); // convert nanoseconds (passed in) to milliseconds for Win32.
00128   }
00129 #else
00130   void sim_nsleep(long nanosec)
00131   {
00132     struct timespec ts, ts1;
00133 
00134     ts.tv_sec = 0;
00135     ts.tv_nsec = nanosec;
00136     nanosleep(&ts, &ts1);
00137   }
00138 #endif
00139 
00142 class XMLFile : public FGXMLFileRead {
00143 public:
00144   bool IsScriptFile(std::string filename) {
00145     bool result=false;
00146     document = LoadXMLDocument(filename, false);
00147     if (document) if (document->GetName() == "runscript") result = true;
00148     ResetParser();
00149     return result;
00150   }
00151   bool IsLogDirectiveFile(std::string filename) {
00152     bool result=false;
00153     document = LoadXMLDocument(filename, false);
00154     if (document) if (document->GetName() == "output") result = true;
00155     ResetParser();
00156     return result;
00157   }
00158   bool IsAircraftFile(std::string filename) {
00159     bool result=false;
00160     document = LoadXMLDocument(filename, false);
00161     if (document) if (document->GetName() == "fdm_config") result = true;
00162     ResetParser();
00163     return result;
00164   }
00165   bool IsInitFile(std::string filename) {
00166     bool result=false;
00167     document = LoadXMLDocument(filename, false);
00168     if (document) if (document->GetName() == "initialize") result = true;
00169     ResetParser();
00170     return result;
00171   }
00172 };
00173 
00174 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00175 CLASS DOCUMENTATION
00176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00177 
00270 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00271 IMPLEMENTATION
00272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00273 
00274 int main(int argc, char* argv[])
00275 {
00276   try {
00277     real_main(argc, argv);
00278   } catch (string msg) {
00279     std::cerr << "FATAL ERROR: JSBSim terminated with an exception."
00280               << std::endl << "The message was: " << msg << std::endl;
00281   } catch (...) {
00282     std::cerr << "FATAL ERROR: JSBSim terminated with an unknown exception."
00283               << std::endl;
00284     throw;
00285   }
00286 }
00287 
00288 int real_main(int argc, char* argv[])
00289 {
00290   // *** INITIALIZATIONS *** //
00291 
00292   ScriptName = "";
00293   AircraftName = "";
00294   ResetName = "";
00295   LogOutputName = "";
00296   LogDirectiveName.clear();
00297   bool result = false, success;
00298   bool was_paused = false;
00299   
00300   double frame_duration;
00301 
00302   double new_five_second_value = 0.0;
00303   double actual_elapsed_time = 0;
00304   double initial_seconds = 0;
00305   double current_seconds = 0.0;
00306   double paused_seconds = 0.0;
00307   double sim_lag_time = 0;
00308   double cycle_duration = 0.0;
00309   double override_sim_rate_value = 0.0;
00310   long sleep_nseconds = 0;
00311 
00312   realtime = false;
00313   play_nice = false;
00314   suspend = false;
00315   catalog = false;
00316   nohighlight = false;
00317 
00318   // *** PARSE OPTIONS PASSED INTO THIS SPECIFIC APPLICATION: JSBSim *** //
00319   success = options(argc, argv);
00320   if (!success) {
00321     PrintHelp();
00322     exit(-1);
00323   }
00324 
00325   // *** SET UP JSBSIM *** //
00326   FDMExec = new JSBSim::FGFDMExec();
00327   FDMExec->SetRootDir(RootDir);
00328   FDMExec->SetAircraftPath("aircraft");
00329   FDMExec->SetEnginePath("engine");
00330   FDMExec->SetSystemsPath("systems");
00331   FDMExec->GetPropertyManager()->Tie("simulation/frame_start_time", &actual_elapsed_time);
00332   FDMExec->GetPropertyManager()->Tie("simulation/cycle_duration", &cycle_duration);
00333 
00334   if (nohighlight) FDMExec->disableHighLighting();
00335 
00336   if (simulation_rate < 1.0 )
00337     FDMExec->Setdt(simulation_rate);
00338   else
00339     FDMExec->Setdt(1.0/simulation_rate);
00340 
00341   if (override_sim_rate) override_sim_rate_value = FDMExec->GetDeltaT();
00342 
00343   // SET PROPERTY VALUES THAT ARE GIVEN ON THE COMMAND LINE and which are for the simulation only.
00344 
00345   for (unsigned int i=0; i<CommandLineProperties.size(); i++) {
00346 
00347     if (CommandLineProperties[i].find("simulation") != std::string::npos) {
00348       if (FDMExec->GetPropertyManager()->GetNode(CommandLineProperties[i])) {
00349         FDMExec->SetPropertyValue(CommandLineProperties[i], CommandLinePropertyValues[i]);
00350       }
00351     }
00352   }
00353 
00354   // *** OPTION A: LOAD A SCRIPT, WHICH LOADS EVERYTHING ELSE *** //
00355   if (!ScriptName.empty()) {
00356 
00357     result = FDMExec->LoadScript(ScriptName, override_sim_rate_value, ResetName);
00358 
00359     if (!result) {
00360       cerr << "Script file " << ScriptName << " was not successfully loaded" << endl;
00361       delete FDMExec;
00362       exit(-1);
00363     }
00364 
00365   // *** OPTION B: LOAD AN AIRCRAFT AND A SET OF INITIAL CONDITIONS *** //
00366   } else if (!AircraftName.empty() || !ResetName.empty()) {
00367 
00368     if (catalog) FDMExec->SetDebugLevel(0);
00369 
00370     if ( ! FDMExec->LoadModel( "aircraft",
00371                                "engine",
00372                                "systems",
00373                                AircraftName)) {
00374       cerr << "  JSBSim could not be started" << endl << endl;
00375       delete FDMExec;
00376       exit(-1);
00377     }
00378 
00379     if (catalog) {
00380       FDMExec->PrintPropertyCatalog();
00381       delete FDMExec;
00382       return 0;
00383     }
00384 
00385     JSBSim::FGInitialCondition *IC = FDMExec->GetIC();
00386     if ( ! IC->Load(ResetName)) {
00387       delete FDMExec;
00388       cerr << "Initialization unsuccessful" << endl;
00389       exit(-1);
00390     }
00391 
00392   } else {
00393     cout << "  No Aircraft, Script, or Reset information given" << endl << endl;
00394     delete FDMExec;
00395     exit(-1);
00396   }
00397 
00398   // Load output directives file[s], if given
00399   for (unsigned int i=0; i<LogDirectiveName.size(); i++) {
00400     if (!LogDirectiveName[i].empty()) {
00401       if (!FDMExec->SetOutputDirectives(LogDirectiveName[i])) {
00402         cout << "Output directives not properly set in file " << LogDirectiveName[i] << endl;
00403         delete FDMExec;
00404         exit(-1);
00405       }
00406     }
00407   }
00408 
00409   // OVERRIDE OUTPUT FILE NAME. THIS IS USEFUL FOR CASES WHERE MULTIPLE
00410   // RUNS ARE BEING MADE (SUCH AS IN A MONTE CARLO STUDY) AND THE OUTPUT FILE
00411   // NAME MUST BE SET EACH TIME TO AVOID THE PREVIOUS RUN DATA FROM BEING OVER-
00412   // WRITTEN. THIS OVERRIDES ONLY THE FILENAME FOR THE FIRST FILE.
00413   if (!LogOutputName.empty()) {
00414     string old_filename = FDMExec->GetOutputFileName();
00415     if (!FDMExec->SetOutputFileName(LogOutputName)) {
00416       cout << "Output filename could not be set" << endl;
00417     } else {
00418       cout << "Output filename change from " << old_filename << " from aircraft"
00419               " configuration file to " << LogOutputName << " specified on"
00420               " command line" << endl;
00421     }
00422   }
00423 
00424   // SET PROPERTY VALUES THAT ARE GIVEN ON THE COMMAND LINE
00425 
00426   for (unsigned int i=0; i<CommandLineProperties.size(); i++) {
00427 
00428     if (!FDMExec->GetPropertyManager()->GetNode(CommandLineProperties[i])) {
00429       cerr << endl << "  No property by the name " << CommandLineProperties[i] << endl;
00430       goto quit;
00431     } else {
00432       FDMExec->SetPropertyValue(CommandLineProperties[i], CommandLinePropertyValues[i]);
00433     }
00434   }
00435 
00436   FDMExec->RunIC();
00437   FDMExec->GetPropagate()->DumpState();
00438 
00439   cout << endl << JSBSim::FGFDMExec::fggreen << JSBSim::FGFDMExec::highint
00440        << "---- JSBSim Execution beginning ... --------------------------------------------"
00441        << JSBSim::FGFDMExec::reset << endl << endl;
00442 
00443   result = FDMExec->Run();  // MAKE AN INITIAL RUN
00444 
00445   if (suspend) FDMExec->Hold();
00446 
00447   // Print actual time at start
00448   char s[100];
00449   time_t tod;
00450   time(&tod);
00451   strftime(s, 99, "%A %B %d %Y %X", localtime(&tod));
00452   cout << "Start: " << s << " (HH:MM:SS)" << endl;
00453 
00454   frame_duration = FDMExec->GetDeltaT();
00455   if (realtime) sleep_nseconds = (long)(frame_duration*1e9);
00456   else          sleep_nseconds = (sleep_period )*1e9;           // 0.01 seconds
00457 
00458   tzset(); 
00459   current_seconds = initial_seconds = getcurrentseconds();
00460 
00461   // *** CYCLIC EXECUTION LOOP, AND MESSAGE READING *** //
00462   while (result && FDMExec->GetSimTime() <= end_time) {
00463 
00464     FDMExec->ProcessMessage(); // Process messages, if any.
00465     
00466     // Check if increment then hold is on and take appropriate actions if it is
00467     // Iterate is not supported in realtime - only in batch and playnice modes
00468     FDMExec->CheckIncrementalHold();
00469     
00470     // if running realtime, throttle the execution, else just run flat-out fast
00471     // unless "playing nice", in which case sleep for a while (0.01 seconds) each frame.
00472     // If suspended, then don't increment cumulative realtime "stopwatch".
00473 
00474     if ( ! FDMExec->Holding()) {
00475       if ( ! realtime ) {         // ------------ RUNNING IN BATCH MODE
00476 
00477         result = FDMExec->Run();
00478 
00479         if (play_nice) sim_nsleep(sleep_nseconds);
00480 
00481       } else {                    // ------------ RUNNING IN REALTIME MODE
00482 
00483         // "was_paused" will be true if entering this "run" loop from a paused state.
00484         if (was_paused) {
00485           initial_seconds += paused_seconds;
00486           was_paused = false;
00487         }
00488         current_seconds = getcurrentseconds();                      // Seconds since 1 Jan 1970
00489         actual_elapsed_time = current_seconds - initial_seconds;    // Real world elapsed seconds since start
00490         sim_lag_time = actual_elapsed_time - FDMExec->GetSimTime(); // How far behind sim-time is from actual
00491                                                                     // elapsed time.
00492         for (int i=0; i<(int)(sim_lag_time/frame_duration); i++) {  // catch up sim time to actual elapsed time.
00493           result = FDMExec->Run();
00494           cycle_duration = getcurrentseconds() - current_seconds;   // Calculate cycle duration
00495           current_seconds = getcurrentseconds();                    // Get new current_seconds
00496           if (FDMExec->Holding()) break;
00497         }
00498 
00499         if (play_nice) sim_nsleep(sleep_nseconds);
00500 
00501         if (FDMExec->GetSimTime() >= new_five_second_value) { // Print out elapsed time every five seconds.
00502           cout << "Simulation elapsed time: " << FDMExec->GetSimTime() << endl;
00503           new_five_second_value += 5.0;
00504         }
00505       }
00506     } else { // Suspended
00507       was_paused = true;
00508       paused_seconds = getcurrentseconds() - current_seconds;
00509       sim_nsleep(sleep_nseconds);
00510       result = FDMExec->Run();
00511     }
00512 
00513   }
00514 
00515 quit:
00516 
00517   // PRINT ENDING CLOCK TIME
00518   time(&tod);
00519   strftime(s, 99, "%A %B %d %Y %X", localtime(&tod));
00520   cout << "End: " << s << " (HH:MM:SS)" << endl;
00521 
00522   // CLEAN UP
00523   delete FDMExec;
00524 
00525   return 0;
00526 }
00527 
00528 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00529 
00530 #define gripe cerr << "Option '" << keyword     \
00531     << "' requires a value, as in '"    \
00532     << keyword << "=something'" << endl << endl;
00533 
00534 bool options(int count, char **arg)
00535 {
00536   int i;
00537   bool result = true;
00538 
00539   if (count == 1) {
00540     PrintHelp();
00541     exit(0);
00542   }
00543 
00544   cout.setf(ios_base::fixed);
00545 
00546   for (i=1; i<count; i++) {
00547     string argument = string(arg[i]);
00548     string keyword(argument);
00549     string value("");
00550     string::size_type n=argument.find("=");
00551 
00552     if (n != string::npos && n > 0) {
00553       keyword = argument.substr(0, n);
00554       value = argument.substr(n+1);
00555     }
00556 
00557     if (keyword == "--help") {
00558       PrintHelp();
00559       exit(0);
00560     } else if (keyword == "--version") {
00561       cout << endl << "  JSBSim Version: " << FDMExec->GetVersion() << endl << endl;
00562       exit (0);
00563     } else if (keyword == "--realtime") {
00564       realtime = true;
00565     } else if (keyword == "--nice") {
00566       play_nice = true;
00567       if (n != string::npos) {
00568         try {
00569           sleep_period = atof( value.c_str() );
00570         } catch (...) {
00571           cerr << endl << "  Invalid sleep period given!" << endl << endl;
00572           result = false;
00573         }
00574       } else {
00575         sleep_period = 0.01;
00576       }
00577     } else if (keyword == "--suspend") {
00578       suspend = true;
00579     } else if (keyword == "--nohighlight") {
00580         nohighlight = true;
00581     } else if (keyword == "--outputlogfile") {
00582       if (n != string::npos) {
00583         LogOutputName = value;
00584       } else {
00585         LogOutputName = "JSBout.csv";
00586         cerr << "  Output log file name must be specified with an = sign. Using JSBout.csv as default";
00587       }
00588     } else if (keyword == "--logdirectivefile") {
00589       if (n != string::npos) {
00590         LogDirectiveName.push_back(value);
00591       } else {
00592         gripe;
00593         exit(1);
00594       }
00595     } else if (keyword == "--root") {
00596       if (n != string::npos) {
00597         RootDir = value;
00598         if (RootDir[RootDir.length()-1] != '/') {
00599           RootDir += '/';
00600         }
00601       } else {
00602         gripe;
00603         exit(1);
00604       }
00605     } else if (keyword == "--aircraft") {
00606       if (n != string::npos) {
00607         AircraftName = value;
00608       } else {
00609         gripe;
00610         exit(1);
00611       }
00612     } else if (keyword == "--script") {
00613       if (n != string::npos) {
00614         ScriptName = value;
00615       } else {
00616         gripe;
00617         exit(1);
00618       }
00619     } else if (keyword == "--initfile") {
00620       if (n != string::npos) {
00621         ResetName = value;
00622       } else {
00623         gripe;
00624         exit(1);
00625       }
00626 
00627     } else if (keyword == "--property") {
00628       if (n != string::npos) {
00629          string propName = value.substr(0,value.find("="));
00630          string propValueString = value.substr(value.find("=")+1);
00631          double propValue = atof(propValueString.c_str());
00632          CommandLineProperties.push_back(propName);
00633          CommandLinePropertyValues.push_back(propValue);
00634       } else {
00635         gripe;
00636         exit(1);
00637       }
00638 
00639     } else if (keyword == "--end-time") {
00640       if (n != string::npos) {
00641         try {
00642         end_time = atof( value.c_str() );
00643         } catch (...) {
00644           cerr << endl << "  Invalid end time given!" << endl << endl;
00645           result = false;
00646         }
00647       } else {
00648         gripe;
00649         exit(1);
00650       }
00651 
00652     } else if (keyword == "--simulation-rate") {
00653       if (n != string::npos) {
00654         try {
00655           simulation_rate = atof( value.c_str() );
00656           override_sim_rate = true;
00657         } catch (...) {
00658           cerr << endl << "  Invalid simulation rate given!" << endl << endl;
00659           result = false;
00660         }
00661       } else {
00662         gripe;
00663         exit(1);
00664       }
00665 
00666     } else if (keyword == "--catalog") {
00667         catalog = true;
00668         if (value.size() > 0) AircraftName=value;
00669     } else if (keyword.substr(0,2) != "--" && value.empty() ) {
00670       // See what kind of files we are specifying on the command line
00671 
00672       XMLFile xmlFile;
00673       
00674       if (xmlFile.IsScriptFile(keyword)) ScriptName = keyword;
00675       else if (xmlFile.IsLogDirectiveFile(keyword))  LogDirectiveName.push_back(keyword);
00676       else if (xmlFile.IsAircraftFile("aircraft/" + keyword + "/" + keyword)) AircraftName = keyword;
00677       else if (xmlFile.IsInitFile(keyword)) ResetName = keyword;
00678       else if (xmlFile.IsInitFile("aircraft/" + AircraftName + "/" + keyword)) ResetName = keyword;
00679       else {
00680         cerr << "The argument \"" << keyword << "\" cannot be interpreted as a file name or option." << endl;
00681         exit(1);
00682       }
00683 
00684     }
00685     else //Unknown keyword so print the help file, the bad keyword and abort
00686     {
00687           PrintHelp();
00688           cerr << "The argument \"" << keyword << "\" cannot be interpreted as a file name or option." << endl;
00689           exit(1);
00690     }
00691 
00692   }
00693 
00694   // Post-processing for script options. check for incompatible options.
00695 
00696   if (catalog && !ScriptName.empty()) {
00697     cerr << "Cannot specify catalog with script option" << endl << endl;
00698     result = false;
00699   }
00700   if (AircraftName.size() > 0 && ResetName.size() == 0 && !catalog) {
00701     cerr << "You must specify an initialization file with the aircraft name." << endl << endl;
00702     result = false;
00703   }
00704   if (ScriptName.size() > 0 && AircraftName.size() > 0) {
00705     cerr << "You cannot specify an aircraft file with a script." << endl;
00706     result = false;
00707   }
00708 
00709   return result;
00710 
00711 }
00712 
00713 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00714 
00715 void PrintHelp(void)
00716 {
00717   cout << endl << "  JSBSim version " << FDMExec->GetVersion() << endl << endl;
00718   cout << "  Usage: jsbsim [script file name] [output file names] <options>" << endl << endl;
00719   cout << "  options:" << endl;
00720     cout << "    --help  returns this message" << endl;
00721     cout << "    --version  returns the version number" << endl;
00722     cout << "    --outputlogfile=<filename>  sets (overrides) the name of the first data output file" << endl;
00723     cout << "    --logdirectivefile=<filename>  specifies the name of a data logging directives file" << endl;
00724     cout << "                                   (can appear multiple times)" << endl;
00725     cout << "    --root=<path>  specifies the JSBSim root directory (where aircraft/, engine/, etc. reside)" << endl;
00726     cout << "    --aircraft=<filename>  specifies the name of the aircraft to be modeled" << endl;
00727     cout << "    --script=<filename>  specifies a script to run" << endl;
00728     cout << "    --realtime  specifies to run in actual real world time" << endl;
00729     cout << "    --nice  specifies to run at lower CPU usage" << endl;
00730     cout << "    --nohighlight  specifies that console output should be pure text only (no color)" << endl;
00731     cout << "    --suspend  specifies to suspend the simulation after initialization" << endl;
00732     cout << "    --initfile=<filename>  specifies an initilization file" << endl;
00733     cout << "    --catalog specifies that all properties for this aircraft model should be printed" << endl;
00734     cout << "              (catalog=aircraftname is an optional format)" << endl;
00735     cout << "    --property=<name=value> e.g. --property=simulation/integrator/rate/rotational=1" << endl;
00736     cout << "    --simulation-rate=<rate (double)> specifies the sim dT time or frequency" << endl;
00737     cout << "                      If rate specified is less than 1, it is interpreted as" << endl;
00738     cout << "                      a time step size, otherwise it is assumed to be a rate in Hertz." << endl;
00739     cout << "    --end-time=<time (double)> specifies the sim end time" << endl << endl;
00740 
00741     cout << "  NOTE: There can be no spaces around the = sign when" << endl;
00742     cout << "        an option is followed by a filename" << endl << endl;
00743 }
00744