42 #include "initialization/FGTrim.h" 43 #include "FGFDMExec.h" 44 #include "input_output/FGXMLFileRead.h" 46 #if !defined(__GNUC__) && !defined(sgi) && !defined(_MSC_VER) 54 #elif defined(__GNUC__) && !defined(sgi) 58 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__) 59 # define WIN32_LEAN_AND_MEAN 61 # include <mmsystem.h> 63 # include <sys/types.h> 64 # include <sys/timeb.h> 66 # include <sys/time.h> 80 IDENT(IdSrc,
"$Id: JSBSim.cpp,v 1.91 2017/02/25 15:50:02 bcoconni Exp $");
90 vector <string> LogOutputName;
91 vector <SGPath> LogDirectiveName;
92 vector <string> CommandLineProperties;
93 vector <double> CommandLinePropertyValues;
103 double end_time = 1e99;
104 double simulation_rate = 1./120.;
105 bool override_sim_rate =
false;
106 double sleep_period=0.01;
112 bool options(
int,
char**);
113 int real_main(
int argc,
char* argv[]);
114 void PrintHelp(
void);
116 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__) 117 double getcurrentseconds(
void)
121 return tm_ptr.time + tm_ptr.millitm*0.001;
124 double getcurrentseconds(
void)
129 gettimeofday(&tval, &tz);
130 return (tval.tv_sec + tval.tv_usec*1e-6);
134 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__) 135 void sim_nsleep(
long nanosec)
137 Sleep((DWORD)(nanosec*1e-6));
140 void sim_nsleep(
long nanosec)
142 struct timespec ts, ts1;
145 ts.tv_nsec = nanosec;
146 nanosleep(&ts, &ts1);
154 bool IsScriptFile(
const SGPath& filename) {
156 Element *document = LoadXMLDocument(filename,
false);
157 if (document && document->
GetName() ==
"runscript") result =
true;
161 bool IsLogDirectiveFile(
const SGPath& filename) {
163 Element *document = LoadXMLDocument(filename,
false);
164 if (document && document->
GetName() ==
"output") result =
true;
168 bool IsAircraftFile(
const SGPath& filename) {
170 Element* document = LoadXMLDocument(filename,
false);
171 if (document && document->
GetName() ==
"fdm_config") result =
true;
175 bool IsInitFile(
const SGPath& filename) {
177 Element *document = LoadXMLDocument(filename,
false);
178 if (document && document->
GetName() ==
"initialize") result =
true;
284 int main(
int argc,
char* argv[])
286 #if defined(_MSC_VER) 288 _controlfp(_controlfp(0, 0) & ~(_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW),
290 #elif defined(__GNUC__) && !defined(sgi) && !defined(__APPLE__) 291 feenableexcept(FE_DIVBYZERO | FE_INVALID);
295 real_main(argc, argv);
296 }
catch (
string& msg) {
297 std::cerr <<
"FATAL ERROR: JSBSim terminated with an exception." 298 << std::endl <<
"The message was: " << msg << std::endl;
301 std::cerr <<
"FATAL ERROR: JSBSim terminated with an unknown exception." 308 int real_main(
int argc,
char* argv[])
315 LogOutputName.clear();
316 LogDirectiveName.clear();
317 bool result =
false, success;
318 bool was_paused =
false;
320 double frame_duration;
322 double new_five_second_value = 0.0;
323 double actual_elapsed_time = 0;
324 double initial_seconds = 0;
325 double current_seconds = 0.0;
326 double paused_seconds = 0.0;
327 double sim_lag_time = 0;
328 double cycle_duration = 0.0;
329 double override_sim_rate_value = 0.0;
330 long sleep_nseconds = 0;
339 success = options(argc, argv);
356 if (simulation_rate < 1.0 )
357 FDMExec->
Setdt(simulation_rate);
359 FDMExec->
Setdt(1.0/simulation_rate);
361 if (override_sim_rate) override_sim_rate_value = FDMExec->
GetDeltaT();
365 for (
unsigned int i=0; i<CommandLineProperties.size(); i++) {
367 if (CommandLineProperties[i].find(
"simulation") != std::string::npos) {
369 FDMExec->
SetPropertyValue(CommandLineProperties[i], CommandLinePropertyValues[i]);
375 if (!ScriptName.isNull()) {
377 result = FDMExec->
LoadScript(ScriptName, override_sim_rate_value, ResetName);
380 cerr <<
"Script file " << ScriptName <<
" was not successfully loaded" << endl;
386 }
else if (!AircraftName.empty() || !ResetName.isNull()) {
390 if ( ! FDMExec->
LoadModel(SGPath(
"aircraft"),
394 cerr <<
" JSBSim could not be started" << endl << endl;
400 FDMExec->PrintPropertyCatalog();
406 if ( ! IC->
Load(ResetName)) {
408 cerr <<
"Initialization unsuccessful" << endl;
413 cout <<
" No Aircraft, Script, or Reset information given" << endl << endl;
419 for (
unsigned int i=0; i<LogDirectiveName.size(); i++) {
420 if (!LogDirectiveName[i].isNull()) {
422 cout <<
"Output directives not properly set in file " << LogDirectiveName[i] << endl;
433 for (
unsigned int i=0; i<LogOutputName.size(); i++) {
436 cout <<
"Output filename could not be set" << endl;
438 cout <<
"Output filename change from " << old_filename <<
" from aircraft" 439 " configuration file to " << LogOutputName[i] <<
" specified on" 440 " command line" << endl;
446 for (
unsigned int i=0; i<CommandLineProperties.size(); i++) {
449 cerr << endl <<
" No property by the name " << CommandLineProperties[i] << endl;
452 FDMExec->
SetPropertyValue(CommandLineProperties[i], CommandLinePropertyValues[i]);
459 FDMExec->PrintSimulationConfiguration();
469 }
catch (
string& msg) {
470 cerr << endl << msg << endl << endl;
476 <<
"---- JSBSim Execution beginning ... --------------------------------------------" 479 result = FDMExec->
Run();
481 if (suspend) FDMExec->
Hold();
487 strftime(s, 99,
"%A %B %d %Y %X", localtime(&tod));
488 cout <<
"Start: " << s <<
" (HH:MM:SS)" << endl;
491 if (realtime) sleep_nseconds = (long)(frame_duration*1e9);
492 else sleep_nseconds = (sleep_period )*1e9;
495 current_seconds = initial_seconds = getcurrentseconds();
498 while (result && FDMExec->
GetSimTime() <= end_time) {
513 result = FDMExec->
Run();
515 if (play_nice) sim_nsleep(sleep_nseconds);
521 initial_seconds += paused_seconds;
524 current_seconds = getcurrentseconds();
525 actual_elapsed_time = current_seconds - initial_seconds;
526 sim_lag_time = actual_elapsed_time - FDMExec->
GetSimTime();
528 for (
int i=0; i<(int)(sim_lag_time/frame_duration); i++) {
529 result = FDMExec->
Run();
530 cycle_duration = getcurrentseconds() - current_seconds;
531 current_seconds = getcurrentseconds();
535 if (play_nice) sim_nsleep(sleep_nseconds);
537 if (FDMExec->
GetSimTime() >= new_five_second_value) {
538 cout <<
"Simulation elapsed time: " << FDMExec->
GetSimTime() << endl;
539 new_five_second_value += 5.0;
544 paused_seconds = getcurrentseconds() - current_seconds;
545 sim_nsleep(sleep_nseconds);
546 result = FDMExec->
Run();
556 strftime(s, 99,
"%A %B %d %Y %X", localtime(&tod));
557 cout <<
"End: " << s <<
" (HH:MM:SS)" << endl;
567 #define gripe cerr << "Option '" << keyword \ 568 << "' requires a value, as in '" \ 569 << keyword << "=something'" << endl << endl; 571 bool options(
int count,
char **arg)
581 cout.setf(ios_base::fixed);
583 for (i=1; i<count; i++) {
584 string argument = string(arg[i]);
585 string keyword(argument);
587 string::size_type n=argument.find(
"=");
589 if (n != string::npos && n > 0) {
590 keyword = argument.substr(0, n);
591 value = argument.substr(n+1);
594 if (keyword ==
"--help") {
597 }
else if (keyword ==
"--version") {
598 cout << endl <<
" JSBSim Version: " << FDMExec->
GetVersion() << endl << endl;
600 }
else if (keyword ==
"--realtime") {
602 }
else if (keyword ==
"--nice") {
604 if (n != string::npos) {
606 sleep_period = atof( value.c_str() );
608 cerr << endl <<
" Invalid sleep period given!" << endl << endl;
614 }
else if (keyword ==
"--suspend") {
616 }
else if (keyword ==
"--nohighlight") {
618 }
else if (keyword ==
"--outputlogfile") {
619 if (n != string::npos) {
620 LogOutputName.push_back(value);
622 }
else if (keyword ==
"--logdirectivefile") {
623 if (n != string::npos) {
624 LogDirectiveName.push_back(SGPath::fromLocal8Bit(value.c_str()));
629 }
else if (keyword ==
"--root") {
630 if (n != string::npos) {
631 RootDir = SGPath::fromLocal8Bit(value.c_str());
636 }
else if (keyword ==
"--aircraft") {
637 if (n != string::npos) {
638 AircraftName = value;
643 }
else if (keyword ==
"--script") {
644 if (n != string::npos) {
645 ScriptName = SGPath::fromLocal8Bit(value.c_str());
650 }
else if (keyword ==
"--initfile") {
651 if (n != string::npos) {
652 ResetName = SGPath::fromLocal8Bit(value.c_str());
658 }
else if (keyword ==
"--property") {
659 if (n != string::npos) {
660 string propName = value.substr(0,value.find(
"="));
661 string propValueString = value.substr(value.find(
"=")+1);
662 double propValue = atof(propValueString.c_str());
663 CommandLineProperties.push_back(propName);
664 CommandLinePropertyValues.push_back(propValue);
670 }
else if (keyword.substr(0,5) ==
"--end") {
671 if (n != string::npos) {
673 end_time = atof( value.c_str() );
675 cerr << endl <<
" Invalid end time given!" << endl << endl;
683 }
else if (keyword ==
"--simulation-rate") {
684 if (n != string::npos) {
686 simulation_rate = atof( value.c_str() );
687 override_sim_rate =
true;
689 cerr << endl <<
" Invalid simulation rate given!" << endl << endl;
697 }
else if (keyword ==
"--catalog") {
699 if (value.size() > 0) AircraftName=value;
700 }
else if (keyword.substr(0,2) !=
"--" && value.empty() ) {
704 SGPath path = SGPath::fromLocal8Bit(keyword.c_str());
706 if (xmlFile.IsScriptFile(path)) ScriptName = path;
707 else if (xmlFile.IsLogDirectiveFile(path)) LogDirectiveName.push_back(path);
708 else if (xmlFile.IsAircraftFile(SGPath(
"aircraft")/keyword/keyword)) AircraftName = keyword;
709 else if (xmlFile.IsInitFile(path)) ResetName = path;
710 else if (xmlFile.IsInitFile(SGPath(
"aircraft")/AircraftName/keyword)) ResetName = SGPath(
"aircraft")/AircraftName/keyword;
712 cerr <<
"The argument \"" << keyword <<
"\" cannot be interpreted as a file name or option." << endl;
720 cerr <<
"The argument \"" << keyword <<
"\" cannot be interpreted as a file name or option." << endl;
728 if (catalog && !ScriptName.isNull()) {
729 cerr <<
"Cannot specify catalog with script option" << endl << endl;
732 if (!AircraftName.empty() && ResetName.isNull() && !catalog) {
733 cerr <<
"You must specify an initialization file with the aircraft name." << endl << endl;
736 if (!ScriptName.isNull() && !AircraftName.empty()) {
737 cerr <<
"You cannot specify an aircraft file with a script." << endl;
749 cout << endl <<
" JSBSim version " << FDMExec->
GetVersion() << endl << endl;
750 cout <<
" Usage: jsbsim [script file name] [output file names] <options>" << endl << endl;
751 cout <<
" options:" << endl;
752 cout <<
" --help returns this message" << endl;
753 cout <<
" --version returns the version number" << endl;
754 cout <<
" --outputlogfile=<filename> sets (overrides) the name of a data output file" << endl;
755 cout <<
" --logdirectivefile=<filename> specifies the name of a data logging directives file" << endl;
756 cout <<
" (can appear multiple times)" << endl;
757 cout <<
" --root=<path> specifies the JSBSim root directory (where aircraft/, engine/, etc. reside)" << endl;
758 cout <<
" --aircraft=<filename> specifies the name of the aircraft to be modeled" << endl;
759 cout <<
" --script=<filename> specifies a script to run" << endl;
760 cout <<
" --realtime specifies to run in actual real world time" << endl;
761 cout <<
" --nice specifies to run at lower CPU usage" << endl;
762 cout <<
" --nohighlight specifies that console output should be pure text only (no color)" << endl;
763 cout <<
" --suspend specifies to suspend the simulation after initialization" << endl;
764 cout <<
" --initfile=<filename> specifies an initilization file" << endl;
765 cout <<
" --catalog specifies that all properties for this aircraft model should be printed" << endl;
766 cout <<
" (catalog=aircraftname is an optional format)" << endl;
767 cout <<
" --property=<name=value> e.g. --property=simulation/integrator/rate/rotational=1" << endl;
768 cout <<
" --simulation-rate=<rate (double)> specifies the sim dT time or frequency" << endl;
769 cout <<
" If rate specified is less than 1, it is interpreted as" << endl;
770 cout <<
" a time step size, otherwise it is assumed to be a rate in Hertz." << endl;
771 cout <<
" --end=<time (double)> specifies the sim end time" << endl << endl;
773 cout <<
" NOTE: There can be no spaces around the = sign when" << endl;
774 cout <<
" an option is followed by a filename" << endl << endl;
FGInitialCondition * GetIC(void)
Returns a pointer to the FGInitialCondition object.
bool LoadScript(const SGPath &Script, double deltaT=0.0, const SGPath &initfile=SGPath())
Loads a script.
bool RunIC(void)
Initializes the sim from the initial condition object and executes each scheduled model without integ...
static char reset[5]
resets text properties
void SetPropertyValue(const std::string &property, double value)
Sets a property value.
std::string GetVersion(void)
Returns the version number of JSBSim.
void disableHighLighting(void)
Disables highlighting in the console output.
bool SetOutputFileName(const int n, const std::string &fname)
Sets (or overrides) the output filename.
FGPropertyManager * GetPropertyManager(void)
Returns a pointer to the property manager object.
void SetRootDir(const SGPath &rootDir)
Sets the root directory where JSBSim starts looking for its system directories.
void SetDebugLevel(int level)
Sets the debug level.
void Setdt(double delta_t)
Sets the integration time step for the simulation executive.
void Tie(const std::string &name, bool *pointer, bool useDefault=true)
Tie a property to an external bool variable.
bool NeedTrim(void) const
Does initialization file call for trim ?
void ProcessMessage(void)
Reads the message on the queue and removes it from the queue.
void Hold(void)
Pauses execution by preventing time from incrementing.
const std::string & GetName(void) const
Retrieves the element name.
static char fggreen[6]
green text
std::string GetOutputFileName(int n) const
Retrieves the current output filename.
bool Load(const SGPath &rstname, bool useStoredPath=true)
Loads the initial conditions.
bool SetOutputDirectives(const SGPath &fname)
Sets the output (logging) mechanism for this run.
The trimming routine for JSBSim.
This class is solely for the purpose of determining what type of file is given on the command line...
bool Holding(void)
Returns true if the simulation is Holding (i.e. simulation time is not moving).
Initializes the simulation run.
bool SetSystemsPath(const SGPath &path)
Sets the path to the systems config file directories.
bool SetEnginePath(const SGPath &path)
Sets the path to the engine config file directories.
double GetSimTime(void) const
Returns the cumulative simulation time in seconds.
static char highint[5]
highlights text
double GetDeltaT(void) const
Returns the simulation delta T.
void CheckIncrementalHold(void)
Checks if required to hold afer increment.
bool Run(void)
This function executes each scheduled model in succession.
Encapsulates the JSBSim simulation executive.
bool LoadModel(const SGPath &AircraftPath, const SGPath &EnginePath, const SGPath &SystemsPath, const std::string &model, bool addModelToPath=true)
Loads an aircraft model.
bool SetAircraftPath(const SGPath &path)
Sets the path to the aircraft config file directories.
bool DoTrim(void)
Execute the trim.
FGPropagate * GetPropagate(void)
Returns the FGPropagate pointer.