1
0
Fork 0

latest changes for JSBSim (1.0 prerelease)

This commit is contained in:
ehofman 2009-06-13 07:55:25 +00:00 committed by Tim Moore
parent 21a8522160
commit cb435814c1
31 changed files with 332 additions and 176 deletions

View file

@ -35,6 +35,8 @@ HISTORY
INCLUDES INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define BASE
#include "FGJSBBase.h" #include "FGJSBBase.h"
namespace JSBSim { namespace JSBSim {

View file

@ -45,6 +45,8 @@ INCLUDES
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
#include "input_output/string_utilities.h"
using std::fabs; using std::fabs;
using std::string; using std::string;

View file

@ -184,7 +184,7 @@ bool FGTrim::RemoveState( State state ) {
ta=*iAxes; ta=*iAxes;
if( ta->GetStateType() == state ) { if( ta->GetStateType() == state ) {
delete ta; delete ta;
TrimAxes.erase(iAxes); iAxes = TrimAxes.erase(iAxes);
result=true; result=true;
continue; continue;
} }

View file

@ -31,6 +31,7 @@ INCLUDES
#include "FGXMLParse.h" #include "FGXMLParse.h"
#include <cstdlib> #include <cstdlib>
#include "input_output/string_utilities.h"
namespace JSBSim { namespace JSBSim {
@ -114,26 +115,9 @@ void FGXMLParse::startElement (const char * name, const XMLAttributes &atts)
void FGXMLParse::endElement (const char * name) void FGXMLParse::endElement (const char * name)
{ {
string local_work_string; if (!working_string.empty()) {
vector <string> work_strings = split(working_string, '\n');
while (!working_string.empty()) { for (int i=0; i<work_strings.size(); i++) current_element->AddData(work_strings[i]);
// clear leading newlines and spaces
string::size_type pos = working_string.find_first_not_of( " \n");
if (pos > 0)
working_string.erase(0, pos);
// remove spaces (only) from end of string
pos = working_string.find_last_not_of( " ");
if (pos != string::npos)
working_string.erase( ++pos);
if (!working_string.empty()) {
pos = working_string.find("\n");
if (pos != string::npos) local_work_string = working_string.substr(0,pos);
else local_work_string = working_string;
current_element->AddData(local_work_string);
working_string.erase(0, pos);
}
} }
current_element = current_element->GetParent(); current_element = current_element->GetParent();

View file

@ -63,7 +63,7 @@ FGfdmSocket::FGfdmSocket(string address, int port, int protocol)
else cout << "Winsock DLL not initialized ..." << endl; else cout << "Winsock DLL not initialized ..." << endl;
#endif #endif
if (address.find_first_not_of("0123456789.",0) != address.npos) { if (!is_number(address)) {
if ((host = gethostbyname(address.c_str())) == NULL) { if ((host = gethostbyname(address.c_str())) == NULL) {
cout << "Could not get host net address by name..." << endl; cout << "Could not get host net address by name..." << endl;
} }
@ -121,7 +121,7 @@ FGfdmSocket::FGfdmSocket(string address, int port)
cout << "Host name... " << address << ", Port... " << port << "." << endl; cout << "Host name... " << address << ", Port... " << port << "." << endl;
cout << "Host name... (char) " << address.c_str() << "." << endl; cout << "Host name... (char) " << address.c_str() << "." << endl;
if (address.find_first_not_of("0123456789.",0) != address.npos) { if (!is_number(address)) {
if ((host = gethostbyname(address.c_str())) == NULL) { if ((host = gethostbyname(address.c_str())) == NULL) {
cout << "Could not get host net address by name..." << endl; cout << "Could not get host net address by name..." << endl;
} }

View file

@ -0,0 +1,144 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: string_utilities.h
Author: Jon S. Berndt
Date started: 06/01/09
------------- Copyright (C) 2009 Jon S. Berndt (jsb@hal-pc.org) -------------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA.
Further information about the GNU Lesser General Public License can also be found on
the world wide web at http://www.gnu.org.
HISTORY
--------------------------------------------------------------------------------
06/01/09 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef STRINGUTILS_H
#define STRINGUTILS_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <vector>
#include <ctype.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_STRINGUTILS "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
using namespace std;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#if !defined(BASE)
extern string& trim_left(string& str);
extern string& trim_right(string& str);
extern string& trim(string& str);
extern string& to_upper(string& str);
extern string& to_lower(string& str);
extern bool is_number(string& str);
vector <string> split(string str, char d);
#else
string& trim_left(string& str)
{
while ( !isgraph(str[0]) ) {
str = str.erase(0,1);
if (str.size() == 0) break;
}
return str;
}
string& trim_right(string& str)
{
while (!isgraph(str[str.size()-1])) {
str = str.erase(str.size()-1,1);
if (str.size() == 0) break;
}
return str;
}
string& trim(string& str)
{
if (str.size() == 0) return str;
string temp_str = trim_right(str);
return str = trim_left(temp_str);
}
string& to_upper(string& str)
{
for (int i=0; i<str.size(); i++) str[i] = toupper(str[i]);
return str;
}
string& to_lower(string& str)
{
for (int i=0; i<str.size(); i++) str[i] = tolower(str[i]);
return str;
}
bool is_number(string& str)
{
return (str.find_first_not_of("+-.0123456789Ee") == string::npos);
}
vector <string> split(string str, char d)
{
vector <string> str_array;
int index=0;
string temp = "";
trim(str);
index = str.find(d);
while (index != string::npos) {
temp = str.substr(0,index);
trim(temp);
if (temp.size() > 0) str_array.push_back(temp);
str = str.erase(0,index+1);
index = str.find(d);
}
if (str.size() > 0) {
temp = trim(str);
if (temp.size() > 0) str_array.push_back(temp);
}
return str_array;
}
#endif
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -35,6 +35,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGCondition.h" #include "FGCondition.h"
#include <vector>
namespace JSBSim { namespace JSBSim {
@ -87,13 +88,14 @@ FGCondition::FGCondition(Element* element, FGPropertyManager* PropertyManager) :
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//This constructor is called when there are no nested test groups inside the // This constructor is called when there are no nested test groups inside the
// condition // condition
FGCondition::FGCondition(string test, FGPropertyManager* PropertyManager) : FGCondition::FGCondition(string test, FGPropertyManager* PropertyManager) :
PropertyManager(PropertyManager), isGroup(false) PropertyManager(PropertyManager), isGroup(false)
{ {
string property1, property2, compare_string; string property1, property2, compare_string;
vector <string> test_strings;
InitializeConditionals(); InitializeConditionals();
@ -103,20 +105,21 @@ FGCondition::FGCondition(string test, FGPropertyManager* PropertyManager) :
Logic = elUndef; Logic = elUndef;
conditions.clear(); conditions.clear();
unsigned int start = 0, end = 0; test_strings = split(test, ' ');
start = test.find_first_not_of(" "); if (test_strings.size() == 3) {
end = test.find_first_of(" ", start+1); property1 = test_strings[0];
property1 = test.substr(start,end-start); conditional = test_strings[1];
start = test.find_first_not_of(" ",end); property2 = test_strings[2];
end = test.find_first_of(" ",start+1); } else {
conditional = test.substr(start,end-start); cerr << endl << " Conditional test is invalid: \"" << test
start = test.find_first_not_of(" ",end); << "\" has " << test_strings.size() << " elements in the "
end = test.find_first_of(" ",start+1); << "test condition." << endl;
property2 = test.substr(start,end-start); exit(-1);
}
TestParam1 = PropertyManager->GetNode(property1, true); TestParam1 = PropertyManager->GetNode(property1, true);
Comparison = mComparison[conditional]; Comparison = mComparison[conditional];
if (property2.find_first_not_of("-.0123456789eE") == string::npos) { if (is_number(property2)) {
TestValue = atof(property2.c_str()); TestValue = atof(property2.c_str());
} else { } else {
TestParam2 = PropertyManager->GetNode(property2, true); TestParam2 = PropertyManager->GetNode(property2, true);

View file

@ -168,6 +168,26 @@ void FGLocation::SetPosition(double lon, double lat, double radius)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLocation::SetPositionGeodetic(double lon, double lat, double height)
{
mCacheValid = false;
mGeodLat = lat;
mLon = lon;
GeodeticAltitude = height;
initial_longitude = mLon;
double RN = a / sqrt(1.0 - e2*sin(mGeodLat)*sin(mGeodLat));
mECLoc(eX) = (RN + GeodeticAltitude)*cos(mGeodLat)*cos(mLon);
mECLoc(eY) = (RN + GeodeticAltitude)*cos(mGeodLat)*sin(mLon);
mECLoc(eZ) = ((1 - e2)*RN + GeodeticAltitude)*sin(mGeodLat);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLocation::SetEllipse(double semimajor, double semiminor) void FGLocation::SetEllipse(double semimajor, double semiminor)
{ {
mCacheValid = false; mCacheValid = false;

View file

@ -233,6 +233,12 @@ public:
@param radius distance from center of earth to vehicle in feet*/ @param radius distance from center of earth to vehicle in feet*/
void SetPosition(double lon, double lat, double radius); void SetPosition(double lon, double lat, double radius);
/** Sets the longitude, latitude and the distance above the reference ellipsoid.
@param lon longitude in radians
@param lat GEODETIC latitude in radians
@param height distance above the reference ellipsoid to vehicle in feet*/
void SetPositionGeodetic(double lon, double lat, double height);
/** Sets the semimajor and semiminor axis lengths for this planet. /** Sets the semimajor and semiminor axis lengths for this planet.
The eccentricity and flattening are calculated from the semimajor The eccentricity and flattening are calculated from the semimajor
and semiminor axis lengths */ and semiminor axis lengths */

View file

@ -318,6 +318,8 @@ bool FGAerodynamics::Load(Element *element)
document = element; document = element;
} }
FGModel::Load(element); // Perform base class Load
DetermineAxisSystem(); // Detemine if Lift/Side/Drag, etc. is used. DetermineAxisSystem(); // Detemine if Lift/Side/Drag, etc. is used.
Debug(2); Debug(2);

View file

@ -152,6 +152,8 @@ bool FGAircraft::Load(Element* el)
string element_name; string element_name;
Element* element; Element* element;
FGModel::Load(el);
if (el->FindElement("wingarea")) if (el->FindElement("wingarea"))
WingArea = el->FindElementValueAsNumberConvertTo("wingarea", "FT2"); WingArea = el->FindElementValueAsNumberConvertTo("wingarea", "FT2");
if (el->FindElement("wingspan")) if (el->FindElement("wingspan"))

View file

@ -72,10 +72,6 @@ FGBuoyantForces::~FGBuoyantForces()
for (unsigned int i=0; i<Cells.size(); i++) delete Cells[i]; for (unsigned int i=0; i<Cells.size(); i++) delete Cells[i];
Cells.clear(); Cells.clear();
for (unsigned int i=0; i<interface_properties.size(); i++)
delete interface_properties[i];
interface_properties.clear();
Debug(1); Debug(1);
} }
@ -127,28 +123,7 @@ bool FGBuoyantForces::Load(Element *element)
document = element; document = element;
} }
Element *property_element = document->FindElement("property"); FGModel::Load(element); // Perform base class Load
if (property_element)
cout << endl << " Declared properties" << endl << endl;
while (property_element) {
string interface_property_string = property_element->GetDataLine();
if (PropertyManager->HasNode(interface_property_string)) {
cout << " Property " << interface_property_string <<
" is already defined." << endl;
} else {
double value=0.0;
if ( ! property_element->GetAttributeValue("value").empty())
value = property_element->GetAttributeValueAsNumber("value");
interface_properties.push_back(new double(value));
interface_property_string = property_element->GetDataLine();
PropertyManager->Tie(interface_property_string,
interface_properties.back());
cout << " " << interface_property_string <<
" (initial value: " << value << ")" << endl;
}
property_element = document->FindNextElement("property");
}
gas_cell_element = document->FindElement("gas_cell"); gas_cell_element = document->FindElement("gas_cell");
while (gas_cell_element) { while (gas_cell_element) {

View file

@ -169,8 +169,6 @@ private:
FGColumnVector3 vGasCellXYZ; FGColumnVector3 vGasCellXYZ;
FGColumnVector3 vXYZgasCell_arm; FGColumnVector3 vXYZgasCell_arm;
vector <double*> interface_properties;
bool NoneDefined; bool NoneDefined;
void bind(void); void bind(void);

View file

@ -66,27 +66,10 @@ FGExternalReactions::FGExternalReactions(FGFDMExec* fdmex) : FGModel(fdmex)
bool FGExternalReactions::Load(Element* el) bool FGExternalReactions::Load(Element* el)
{ {
FGModel::Load(el); // Call the base class Load() function to load interface properties.
Debug(2); Debug(2);
// Interface properties are all stored in the interface properties array.
// ToDo: Interface properties should not be created if they already exist.
// A check should be done prior to creation. This ought to make it easier
// to work with FlightGear, where some properties used in definitions may
// already have been created, but would not be seen when JSBSim is run
// in standalone mode.
Element* property_element;
property_element = el->FindElement("property");
while (property_element) {
double value=0.0;
if ( ! property_element->GetAttributeValue("value").empty())
value = property_element->GetAttributeValueAsNumber("value");
interface_properties.push_back(new double(value));
string interface_property_string = property_element->GetDataLine();
PropertyManager->Tie(interface_property_string, interface_properties.back());
property_element = el->FindNextElement("property");
}
// Parse force elements // Parse force elements
int index=0; int index=0;
@ -107,8 +90,7 @@ FGExternalReactions::~FGExternalReactions()
{ {
for (unsigned int i=0; i<Forces.size(); i++) delete Forces[i]; for (unsigned int i=0; i<Forces.size(); i++) delete Forces[i];
Forces.clear(); Forces.clear();
for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i];
interface_properties.clear();
Debug(1); Debug(1);
} }

View file

@ -158,7 +158,6 @@ private:
unsigned int numForces; unsigned int numForces;
FGColumnVector3 vTotalForces; FGColumnVector3 vTotalForces;
FGColumnVector3 vTotalMoments; FGColumnVector3 vTotalMoments;
vector <double*> interface_properties;
bool NoneDefined; bool NoneDefined;

View file

@ -101,8 +101,6 @@ FGFCS::~FGFCS()
unsigned int i; unsigned int i;
for (i=0;i<sensors.size();i++) delete sensors[i];
sensors.clear();
for (i=0;i<APComponents.size();i++) delete APComponents[i]; for (i=0;i<APComponents.size();i++) delete APComponents[i];
APComponents.clear(); APComponents.clear();
for (i=0;i<FCSComponents.size();i++) delete FCSComponents[i]; for (i=0;i<FCSComponents.size();i++) delete FCSComponents[i];
@ -110,8 +108,6 @@ FGFCS::~FGFCS()
for (i=0;i<Systems.size();i++) delete Systems[i]; for (i=0;i<Systems.size();i++) delete Systems[i];
Systems.clear(); Systems.clear();
for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i];
interface_properties.clear();
Debug(1); Debug(1);
} }
@ -208,10 +204,6 @@ bool FGFCS::Run(void)
SteerPosDeg[i] = gear->GetDefaultSteerAngle( GetDsCmd() ); SteerPosDeg[i] = gear->GetDefaultSteerAngle( GetDsCmd() );
} }
// Cycle through the sensor, systems, autopilot, and flight control components
// Execute Sensors
for (i=0; i<sensors.size(); i++) sensors[i]->Run();
// Execute Systems in order // Execute Systems in order
for (i=0; i<Systems.size(); i++) Systems[i]->Run(); for (i=0; i<Systems.size(); i++) Systems[i]->Run();
@ -527,7 +519,7 @@ bool FGFCS::Load(Element* el, SystemType systype)
{ {
string name, file, fname="", interface_property_string, parent_name; string name, file, fname="", interface_property_string, parent_name;
vector <FGFCSComponent*> *Components; vector <FGFCSComponent*> *Components;
Element *component_element, *property_element, *sensor_element; Element *component_element, *sensor_element;
Element *channel_element; Element *channel_element;
Components=0; Components=0;
@ -575,33 +567,15 @@ bool FGFCS::Load(Element* el, SystemType systype)
if (document->GetName() == "flight_control") bindModel(); if (document->GetName() == "flight_control") bindModel();
// Interface properties from any autopilot, flight control, or other system are FGModel::Load(document); // Load interface properties from document
// all stored in the interface properties array.
property_element = document->FindElement("property");
if (property_element && debug_lvl > 0) cout << endl << " Declared properties" << endl << endl;
while (property_element) {
interface_property_string = property_element->GetDataLine();
if (PropertyManager->HasNode(interface_property_string)) {
cerr << " Property " << interface_property_string << " is already defined." << endl;
} else {
double value=0.0;
if ( ! property_element->GetAttributeValue("value").empty())
value = property_element->GetAttributeValueAsNumber("value");
interface_properties.push_back(new double(value));
interface_property_string = property_element->GetDataLine();
PropertyManager->Tie(interface_property_string, interface_properties.back());
if (debug_lvl > 0)
cout << " " << interface_property_string << " (initial value: " << value << ")" << endl;
}
property_element = document->FindNextElement("property");
}
// After reading interface properties in a file, read properties in the local // After reading interface properties in a file, read properties in the local
// flight_control, autopilot, or system element. This allows general-purpose // flight_control, autopilot, or system element. This allows general-purpose
// systems to be defined in a file, with overrides or initial loaded constants // systems to be defined in a file, with overrides or initial loaded constants
// supplied in the relevant element of the aircraft configuration file. // supplied in the relevant element of the aircraft configuration file.
Element* property_element = 0;
if (!fname.empty()) { if (!fname.empty()) {
property_element = el->FindElement("property"); property_element = el->FindElement("property");
if (property_element && debug_lvl > 0) cout << endl << " Overriding properties" << endl << endl; if (property_element && debug_lvl > 0) cout << endl << " Overriding properties" << endl << endl;
@ -628,22 +602,6 @@ bool FGFCS::Load(Element* el, SystemType systype)
} }
} }
// Any sensor elements that are outside of a channel (in either the autopilot
// or the flight_control, or even any possible "system") are placed into the global
// "sensors" array, and are executed prior to any autopilot, flight control, or
// system.
sensor_element = document->FindElement("sensor");
while (sensor_element) {
try {
sensors.push_back(new FGSensor(this, sensor_element));
} catch (string s) {
cerr << highint << fgred << endl << " " << s << endl;
return false;
}
sensor_element = document->FindNextElement("sensor");
}
channel_element = document->FindElement("channel"); channel_element = document->FindElement("channel");
while (channel_element) { while (channel_element) {

View file

@ -568,8 +568,6 @@ private:
FCSCompVec Systems; FCSCompVec Systems;
FCSCompVec FCSComponents; FCSCompVec FCSComponents;
FCSCompVec APComponents; FCSCompVec APComponents;
FCSCompVec sensors;
vector <double*> interface_properties;
void bind(void); void bind(void);
void bindModel(void); void bindModel(void);
void bindThrottle(unsigned int); void bindThrottle(unsigned int);

View file

@ -130,6 +130,8 @@ bool FGGroundReactions::Load(Element* el)
FCS->AddGear(); // make the FCS aware of the landing gear FCS->AddGear(); // make the FCS aware of the landing gear
contact_element = el->FindNextElement("contact"); contact_element = el->FindNextElement("contact");
} }
FGModel::Load(el); // Perform base class Load
for (unsigned int i=0; i<lGear.size();i++) lGear[i]->bind(); for (unsigned int i=0; i<lGear.size();i++) lGear[i]->bind();

View file

@ -114,67 +114,71 @@ bool FGInput::Run(void)
if (line.size() == 0) break; if (line.size() == 0) break;
// now parse individual line // now parse individual line
token_start = line.find_first_not_of(" ", 0); vector <string> tokens = split(line,' ');
token_end = line.find_first_of(" ", token_start);
token = line.substr(token_start, token_end - token_start); string command="", argument="", str_value="";
if (tokens.size() > 0) {
command = to_lower(tokens[0]);
if (tokens.size() > 1) {
argument = trim(tokens[1]);
if (tokens.size() > 2) {
str_value = trim(tokens[2]);
}
}
}
if (token == "set" || token == "SET" ) { // SET PROPERTY if (command == "set") { // SET PROPERTY
token_start = line.find_first_not_of(" ", token_end); node = PropertyManager->GetNode(argument);
token_end = line.find_first_of(" ", token_start); if (node == 0)
token = line.substr(token_start, token_end-token_start); socket->Reply("Unknown property\n");
node = PropertyManager->GetNode(token);
if (node == 0) socket->Reply("Unknown property\n");
else { else {
token_start = line.find_first_not_of(" ", token_end); value = atof(str_value.c_str());
token_end = line.find_first_of(" ", token_start);
token = line.substr(token_start, token_end-token_start);
value = atof(token.c_str());
node->setDoubleValue(value); node->setDoubleValue(value);
} }
socket->Reply("");
} else if (token == "get" || token == "GET") { // GET PROPERTY } else if (command == "get") { // GET PROPERTY
token_start = line.find_first_not_of(" ", token_end); if (argument.size() == 0) {
if (token_start == string::npos) {
socket->Reply("No property argument supplied.\n"); socket->Reply("No property argument supplied.\n");
break; break;
} else {
token = line.substr(token_start, line.size()-token_start);
} }
try { try {
node = PropertyManager->GetNode(token); node = PropertyManager->GetNode(argument);
} catch(...) { } catch(...) {
socket->Reply("Badly formed property query\n"); socket->Reply("Badly formed property query\n");
break; break;
} }
if (node == 0) { if (node == 0) {
if (FDMExec->Holding()) { // if holding can query property list if (FDMExec->Holding()) { // if holding can query property list
string query = FDMExec->QueryPropertyCatalog(token); string query = FDMExec->QueryPropertyCatalog(argument);
socket->Reply(query); socket->Reply(query);
} else { } else {
socket->Reply("Must be in HOLD to search properties\n"); socket->Reply("Must be in HOLD to search properties\n");
} }
} else if (node > 0) { } else if (node > 0) {
sprintf(buf, "%s = %12.6f\n", token.c_str(), node->getDoubleValue()); sprintf(buf, "%s = %12.6f\n", argument.c_str(), node->getDoubleValue());
socket->Reply(buf); socket->Reply(buf);
} }
} else if (token == "hold" || token == "HOLD") { // PAUSE } else if (command == "hold") { // PAUSE
FDMExec->Hold(); FDMExec->Hold();
socket->Reply("");
} else if (token == "resume" || token == "RESUME") { // RESUME } else if (command == "resume") { // RESUME
FDMExec->Resume(); FDMExec->Resume();
socket->Reply("");
} else if (token == "quit" || token == "QUIT") { // QUIT } else if (command == "quit") { // QUIT
// close the socket connection // close the socket connection
socket->Reply(""); socket->Reply("");
socket->Close(); socket->Close();
} else if (token == "info" || token == "INFO") { // INFO } else if (command == "info") { // INFO
// get info about the sim run and/or aircraft, etc. // get info about the sim run and/or aircraft, etc.
sprintf(buf, "%8.3f\0", State->Getsim_time()); sprintf(buf, "%8.3f\0", State->Getsim_time());
@ -184,7 +188,7 @@ bool FGInput::Run(void)
info_string += "Simulation time: " + string(buf) + "\n"; info_string += "Simulation time: " + string(buf) + "\n";
socket->Reply(info_string); socket->Reply(info_string);
} else if (token == "help" || token == "HELP") { // HELP } else if (command == "help") { // HELP
socket->Reply( socket->Reply(
" JSBSim Server commands:\n\n" " JSBSim Server commands:\n\n"

View file

@ -96,6 +96,8 @@ bool FGMassBalance::Load(Element* el)
string element_name = ""; string element_name = "";
double bixx, biyy, bizz, bixy, bixz, biyz; double bixx, biyy, bizz, bixy, bixz, biyz;
FGModel::Load(el); // Perform base class Load.
bixx = biyy = bizz = bixy = bixz = biyz = 0.0; bixx = biyy = bizz = bixy = bixz = biyz = 0.0;
if (el->FindElement("ixx")) if (el->FindElement("ixx"))
bixx = el->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2"); bixx = el->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2");

View file

@ -99,6 +99,9 @@ FGModel::FGModel(FGFDMExec* fdmex)
FGModel::~FGModel() FGModel::~FGModel()
{ {
for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i];
interface_properties.clear();
if (debug_lvl & 2) cout << "Destroyed: FGModel" << endl; if (debug_lvl & 2) cout << "Destroyed: FGModel" << endl;
} }
@ -137,6 +140,35 @@ bool FGModel::InitModel(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGModel::Load(Element* el)
{
// Interface properties are all stored in the interface properties array.
string interface_property_string = "";
Element *property_element = el->FindElement("property");
if (property_element && debug_lvl > 0) cout << endl << " Declared properties" << endl << endl;
while (property_element) {
interface_property_string = property_element->GetDataLine();
if (PropertyManager->HasNode(interface_property_string)) {
cerr << " Property " << interface_property_string << " is already defined." << endl;
} else {
double value=0.0;
if ( ! property_element->GetAttributeValue("value").empty())
value = property_element->GetAttributeValueAsNumber("value");
interface_properties.push_back(new double(value));
PropertyManager->Tie(interface_property_string, interface_properties.back());
if (debug_lvl > 0)
cout << " " << interface_property_string << " (initial value: " << value << ")" << endl;
}
property_element = el->FindNextElement("property");
}
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGModel::Run() bool FGModel::Run()
{ {
if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl; if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl;

View file

@ -44,6 +44,7 @@ INCLUDES
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
@ -93,12 +94,12 @@ public:
/// Constructor /// Constructor
FGModel(FGFDMExec*); FGModel(FGFDMExec*);
/// Destructor /// Destructor
virtual ~FGModel(); ~FGModel();
/** Loads this model. /** Loads this model.
@param el a pointer to the element @param el a pointer to the element
@return true if model is successfully loaded*/ @return true if model is successfully loaded*/
virtual bool Load(Element* el) {return true;} virtual bool Load(Element* el);
FGModel* NextModel; FGModel* NextModel;
string Name; string Name;
@ -135,6 +136,8 @@ protected:
FGPropagate* Propagate; FGPropagate* Propagate;
FGAuxiliary* Auxiliary; FGAuxiliary* Auxiliary;
FGPropertyManager* PropertyManager; FGPropertyManager* PropertyManager;
vector <double*> interface_properties;
}; };
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -253,6 +253,8 @@ bool FGPropulsion::Load(Element* el)
Debug(2); Debug(2);
FGModel::Load(el); // Perform base class Load.
Element* engine_element = el->FindElement("engine"); Element* engine_element = el->FindElement("engine");
while (engine_element) { while (engine_element) {
engine_filename = engine_element->GetAttributeValue("file"); engine_filename = engine_element->GetAttributeValue("file");

View file

@ -52,11 +52,24 @@ CLASS IMPLEMENTATION
FGDeadBand::FGDeadBand(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) FGDeadBand::FGDeadBand(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
{ {
string width_string;
WidthPropertyNode = 0;
WidthPropertySign = 1.0;
gain = 1.0; gain = 1.0;
width = 0.0; width = 0.0;
if (element->FindElement("width")) { if ( element->FindElement("width") ) {
width = element->FindElementValueAsNumber("width"); width_string = element->FindElementValue("width");
if (!is_number(width_string)) { // property
if (width_string[0] == '-') {
WidthPropertySign = -1.0;
width_string.erase(0,1);
}
WidthPropertyNode = PropertyManager->GetNode(width_string);
} else {
width = element->FindElementValueAsNumber("width");
}
} }
if (element->FindElement("gain")) { if (element->FindElement("gain")) {
@ -80,6 +93,10 @@ bool FGDeadBand::Run(void )
{ {
Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
if (WidthPropertyNode != 0) {
width = WidthPropertyNode->getDoubleValue() * WidthPropertySign;
}
if (Input < -width/2.0) { if (Input < -width/2.0) {
Output = (Input + width/2.0)*gain; Output = (Input + width/2.0)*gain;
} else if (Input > width/2.0) { } else if (Input > width/2.0) {
@ -121,7 +138,11 @@ void FGDeadBand::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor if (from == 0) { // Constructor
cout << " INPUT: " << InputNodes[0]->getName() << endl; cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " DEADBAND WIDTH: " << width << endl; if (WidthPropertyNode != 0) {
cout << " DEADBAND WIDTH: " << WidthPropertyNode->GetName() << endl;
} else {
cout << " DEADBAND WIDTH: " << width << endl;
}
cout << " GAIN: " << gain << endl; cout << " GAIN: " << gain << endl;
if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl; if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
} }

View file

@ -97,6 +97,8 @@ public:
private: private:
double width; double width;
double gain; double gain;
FGPropertyManager* WidthPropertyNode;
double WidthPropertySign;
void Debug(int from); void Debug(int from);
}; };

View file

@ -133,7 +133,7 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
clip_el = element->FindElement("clipto"); clip_el = element->FindElement("clipto");
if (clip_el) { if (clip_el) {
clip_string = clip_el->FindElementValue("min"); clip_string = clip_el->FindElementValue("min");
if (clip_string.find_first_not_of("+-.0123456789") != string::npos) { // it's a property if (!is_number(clip_string)) { // it's a property
if (clip_string[0] == '-') { if (clip_string[0] == '-') {
clipMinSign = -1.0; clipMinSign = -1.0;
clip_string.erase(0,1); clip_string.erase(0,1);
@ -143,7 +143,7 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
clipmin = clip_el->FindElementValueAsNumber("min"); clipmin = clip_el->FindElementValueAsNumber("min");
} }
clip_string = clip_el->FindElementValue("max"); clip_string = clip_el->FindElementValue("max");
if (clip_string.find_first_not_of("+-.0123456789") != string::npos) { // it's a property if (!is_number(clip_string)) { // it's a property
if (clip_string[0] == '-') { if (clip_string[0] == '-') {
clipMaxSign = -1.0; clipMaxSign = -1.0;
clip_string.erase(0,1); clip_string.erase(0,1);

View file

@ -105,7 +105,7 @@ void FGFilter::ReadFilterCoefficients(Element* element, int index)
if ( element->FindElement(coefficient) ) { if ( element->FindElement(coefficient) ) {
property_string = element->FindElementValue(coefficient); property_string = element->FindElementValue(coefficient);
if (property_string.find_first_not_of("+-.0123456789Ee") != string::npos) { // property if (!is_number(property_string)) { // property
if (property_string[0] == '-') { if (property_string[0] == '-') {
PropertySign[index] = -1.0; PropertySign[index] = -1.0;
property_string.erase(0,1); property_string.erase(0,1);

View file

@ -70,7 +70,7 @@ FGGain::FGGain(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
if ( element->FindElement("gain") ) { if ( element->FindElement("gain") ) {
gain_string = element->FindElementValue("gain"); gain_string = element->FindElementValue("gain");
if (gain_string.find_first_not_of("+-.0123456789Ee") != string::npos) { // property if (!is_number(gain_string)) { // property
if (gain_string[0] == '-') { if (gain_string[0] == '-') {
GainPropertySign = -1.0; GainPropertySign = -1.0;
gain_string.erase(0,1); gain_string.erase(0,1);
@ -207,7 +207,11 @@ void FGGain::Debug(int from)
else else
cout << " INPUT: " << InputNodes[0]->getName() << endl; cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " GAIN: " << Gain << endl; if (GainPropertyNode != 0) {
cout << " GAIN: " << GainPropertyNode->GetName() << endl;
} else {
cout << " GAIN: " << Gain << endl;
}
if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl; if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
if (Type == "AEROSURFACE_SCALE") { if (Type == "AEROSURFACE_SCALE") {
cout << " In/Out Mapping:" << endl; cout << " In/Out Mapping:" << endl;

View file

@ -64,7 +64,7 @@ FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
if ( element->FindElement("kp") ) { if ( element->FindElement("kp") ) {
kp_string = element->FindElementValue("kp"); kp_string = element->FindElementValue("kp");
if (kp_string.find_first_not_of("+-.0123456789Ee") != string::npos) { // property if (!is_number(kp_string)) { // property
if (kp_string[0] == '-') { if (kp_string[0] == '-') {
KpPropertySign = -1.0; KpPropertySign = -1.0;
kp_string.erase(0,1); kp_string.erase(0,1);
@ -77,7 +77,7 @@ FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
if ( element->FindElement("ki") ) { if ( element->FindElement("ki") ) {
ki_string = element->FindElementValue("ki"); ki_string = element->FindElementValue("ki");
if (ki_string.find_first_not_of("+-.0123456789Ee") != string::npos) { // property if (!is_number(ki_string)) { // property
if (ki_string[0] == '-') { if (ki_string[0] == '-') {
KiPropertySign = -1.0; KiPropertySign = -1.0;
ki_string.erase(0,1); ki_string.erase(0,1);
@ -90,7 +90,7 @@ FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
if ( element->FindElement("kd") ) { if ( element->FindElement("kd") ) {
kd_string = element->FindElementValue("kd"); kd_string = element->FindElementValue("kd");
if (kd_string.find_first_not_of("+-.0123456789Ee") != string::npos) { // property if (!is_number(kd_string)) { // property
if (kd_string[0] == '-') { if (kd_string[0] == '-') {
KdPropertySign = -1.0; KdPropertySign = -1.0;
kd_string.erase(0,1); kd_string.erase(0,1);

View file

@ -119,7 +119,7 @@ class FGSensor : public FGFCSComponent
{ {
public: public:
FGSensor(FGFCS* fcs, Element* element); FGSensor(FGFCS* fcs, Element* element);
~FGSensor(); virtual ~FGSensor();
void SetFailLow(double val) {if (val > 0.0) fail_low = true; else fail_low = false;} void SetFailLow(double val) {if (val > 0.0) fail_low = true; else fail_low = false;}
void SetFailHigh(double val) {if (val > 0.0) fail_high = true; else fail_high = false;} void SetFailHigh(double val) {if (val > 0.0) fail_high = true; else fail_high = false;}

View file

@ -97,7 +97,17 @@ FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << Name << endl; cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << Name << endl;
} }
for (unsigned int i=0; i<test_element->GetNumDataLines(); i++) { for (unsigned int i=0; i<test_element->GetNumDataLines(); i++) {
current_test->conditions.push_back(new FGCondition(test_element->GetDataLine(i), PropertyManager)); string input_data = test_element->GetDataLine(i);
while (input_data[0] <= 32) {
input_data = input_data.erase(0,1);
if (input_data.size() <= 1) break;
}
if (input_data.size() <= 1) {
// Make sure there are no bad data lines that consist solely of whitespace
cerr << fgred << " Bad data line in switch component: " << Name << reset << endl;
continue;
}
current_test->conditions.push_back(new FGCondition(input_data, PropertyManager));
} }
condition_element = test_element->GetElement(); // retrieve condition groups condition_element = test_element->GetElement(); // retrieve condition groups
@ -115,8 +125,7 @@ FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
if (value.empty()) { if (value.empty()) {
cerr << "No VALUE supplied for switch component: " << Name << endl; cerr << "No VALUE supplied for switch component: " << Name << endl;
} else { } else {
if (value.find_first_not_of("-.0123456789eE") == string::npos) { if (is_number(value)) {
// if true (and execution falls into this block), "value" is a number.
current_test->OutputVal = atof(value.c_str()); current_test->OutputVal = atof(value.c_str());
} else { } else {
// "value" must be a property if execution passes to here. // "value" must be a property if execution passes to here.