X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FFDM%2FJSBSim%2Fmodels%2FFGFCS.cpp;h=477890295478671424b026873c20664dfeb362fb;hb=edd83dd7e8fd7162ae49da6113ad797c68769f20;hp=0c106cefa1887505aab3276c5d1292e0447d0421;hpb=932b38a87e2870d23f9be9461b551f1e1fe556ba;p=flightgear.git diff --git a/src/FDM/JSBSim/models/FGFCS.cpp b/src/FDM/JSBSim/models/FGFCS.cpp index 0c106cefa..477890295 100644 --- a/src/FDM/JSBSim/models/FGFCS.cpp +++ b/src/FDM/JSBSim/models/FGFCS.cpp @@ -1,28 +1,28 @@ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - Module: FGFCS.cpp + Module: FGFCS.cpp Author: Jon Berndt Date started: 12/12/98 Purpose: Model the flight controls Called by: FDMExec - ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) ------------- + ------------- Copyright (C) 1999 Jon S. Berndt (jon@jsbsim.org) ------------- This program is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free Software + 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 General Public License for more + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - You should have received a copy of the GNU General Public License along with + 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 General Public License can also be found on + Further information about the GNU Lesser General Public License can also be found on the world wide web at http://www.gnu.org. FUNCTIONAL DESCRIPTION @@ -38,29 +38,34 @@ INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include "FGFCS.h" -#include -#include +#include "FGFDMExec.h" +#include "FGGroundReactions.h" +#include "input_output/FGPropertyManager.h" #include - -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include + +#include "models/flight_control/FGFilter.h" +#include "models/flight_control/FGDeadBand.h" +#include "models/flight_control/FGGain.h" +#include "models/flight_control/FGPID.h" +#include "models/flight_control/FGSwitch.h" +#include "models/flight_control/FGSummer.h" +#include "models/flight_control/FGKinemat.h" +#include "models/flight_control/FGFCSFunction.h" +#include "models/flight_control/FGSensor.h" +#include "models/flight_control/FGActuator.h" +#include "models/flight_control/FGAccelerometer.h" +#include "models/flight_control/FGMagnetometer.h" +#include "models/flight_control/FGGyro.h" + +using namespace std; namespace JSBSim { static const char *IdSrc = "$Id$"; static const char *IdHdr = ID_FCS; -#if defined(WIN32) && !defined(__CYGWIN__) -#define snprintf _snprintf -#endif - /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ @@ -74,9 +79,10 @@ FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex) PTrimCmd = YTrimCmd = RTrimCmd = 0.0; GearCmd = GearPos = 1; // default to gear down LeftBrake = RightBrake = CenterBrake = 0.0; + TailhookPos = WingFoldPos = 0.0; bind(); - for (i=0;i<=NForms;i++) { + for (i=0;iHasNode("fcs")) unbind( PropertyManager->GetNode("fcs") ); - if (PropertyManager->HasNode("ap")) unbind( PropertyManager->GetNode("ap") ); - PropertyManager->Untie( "gear/gear-cmd-norm" ); - PropertyManager->Untie( "gear/gear-pos-norm" ); - ThrottleCmd.clear(); ThrottlePos.clear(); MixtureCmd.clear(); @@ -106,17 +107,82 @@ FGFCS::~FGFCS() unsigned int i; for (i=0;iGetType() == "LAG" || + Systems[i]->GetType() == "LEAD_LAG" || + Systems[i]->GetType() == "WASHOUT" || + Systems[i]->GetType() == "SECOND_ORDER_FILTER" || + Systems[i]->GetType() == "INTEGRATOR") + { + ((FGFilter*)Systems[i])->ResetPastStates(); + } else if (Systems[i]->GetType() == "PID" ) { + ((FGPID*)Systems[i])->ResetPastStates(); + } + } + + for (unsigned int i=0; iGetType() == "LAG" || + FCSComponents[i]->GetType() == "LEAD_LAG" || + FCSComponents[i]->GetType() == "WASHOUT" || + FCSComponents[i]->GetType() == "SECOND_ORDER_FILTER" || + FCSComponents[i]->GetType() == "INTEGRATOR") + { + ((FGFilter*)FCSComponents[i])->ResetPastStates(); + } else if (FCSComponents[i]->GetType() == "PID" ) { + ((FGPID*)FCSComponents[i])->ResetPastStates(); + } + } + + for (unsigned int i=0; iGetType() == "LAG" || + APComponents[i]->GetType() == "LEAD_LAG" || + APComponents[i]->GetType() == "WASHOUT" || + APComponents[i]->GetType() == "SECOND_ORDER_FILTER" || + APComponents[i]->GetType() == "INTEGRATOR") + { + ((FGFilter*)APComponents[i])->ResetPastStates(); + } else if (APComponents[i]->GetType() == "PID" ) { + ((FGPID*)APComponents[i])->ResetPastStates(); + } + } + + return true; +} + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Notes: In this logic the default engine commands are set. This is simply a // sort of safe-mode method in case the user has not defined control laws for @@ -132,23 +198,30 @@ bool FGFCS::Run(void) if (FGModel::Run()) return true; // fast exit if nothing to do if (FDMExec->Holding()) return false; + RunPreFunctions(); + for (i=0; iGetGearUnit(i); SteerPosDeg[i] = gear->GetDefaultSteerAngle( GetDsCmd() ); } - // Cycle through the sensor, autopilot, and flight control components - for (i=0; iRun(); + // Execute Systems in order + for (i=0; iRun(); + + // Execute Autopilot for (i=0; iRun(); + + // Execute Flight Control System for (i=0; iRun(); + RunPostFunctions(); + return false; } @@ -382,7 +455,7 @@ void FGFCS::SetMixturePos(int engineNum, double setting) if (engineNum < (int)ThrottlePos.size()) { if (engineNum < 0) { - for (ctr=0;ctr<=MixtureCmd.size();ctr++) MixturePos[ctr] = MixtureCmd[ctr]; + for (ctr=0;ctr *Components; - Element *FCS_cfg, *document, *component_element, *property_element, *sensor_element; + Element *component_element; Element *channel_element; - ifstream* controls_file = new ifstream(); - FGXMLParse controls_file_parser; Components=0; - // Determine if the FCS/Autopilot is defined inline in the aircraft configuration - // file or in a separate file. Set up the Element pointer as appropriate. string separator = "/"; -#ifdef macintosh - separator = ";"; -#endif + +// ToDo: The handling of name and file attributes could be improved, here, +// considering that a name can be in the external file, as well. name = el->GetAttributeValue("name"); if (name.empty()) { fname = el->GetAttributeValue("file"); - file = FDMExec->GetAircraftPath() + separator + FDMExec->GetModelName() + separator + fname + ".xml"; + if (systype == stSystem) { + file = FindSystemFullPathname(fname); + } else { + file = FDMExec->GetFullAircraftPath() + separator + fname + ".xml"; + } if (fname.empty()) { - cerr << "FCS/Autopilot does not appear to be defined inline nor in a file" << endl; + cerr << "FCS, Autopilot, or system does not appear to be defined inline nor in a file" << endl; return false; } else { - controls_file->open(file.c_str()); - readXML(*controls_file, controls_file_parser); - delete controls_file; - document = controls_file_parser.GetDocument(); + document = LoadXMLDocument(file); + if (!document) { + cerr << "Error loading file " << file << endl; + return false; + } + name = document->GetAttributeValue("name"); } } else { document = el; @@ -494,97 +568,108 @@ bool FGFCS::Load(Element* el) } else if (document->GetName() == "flight_control") { Components = &FCSComponents; Name = "FCS: " + document->GetAttributeValue("name"); + } else if (document->GetName() == "system") { + Components = &Systems; + Name = "System: " + document->GetAttributeValue("name"); } - Debug(2); - // ToDo: How do these get untied? - // ToDo: Consider having INPUT and OUTPUT interface properties. Would then - // have to duplicate this block of code after channel read code. - // Input properties could be write only (nah), and output could be read - // only. - if (document->GetName() == "flight_control") bindModel(); - property_element = document->FindElement("property"); - while (property_element) { - interface_properties.push_back(new double(0)); - interface_property_string = property_element->GetDataLine(); - PropertyManager->Tie(interface_property_string, interface_properties.back()); - property_element = document->FindNextElement("property"); - } - - 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; + FGModel::Load(document); // Load interface properties from document + + // After reading interface properties in a file, read properties in the local + // flight_control, autopilot, or system element. This allows general-purpose + // systems to be defined in a file, with overrides or initial loaded constants + // supplied in the relevant element of the aircraft configuration file. + + Element* property_element = 0; + + if (!fname.empty()) { + property_element = el->FindElement("property"); + if (property_element && debug_lvl > 0) cout << endl << " Overriding properties" << endl << endl; + while (property_element) { + double value=0.0; + if ( ! property_element->GetAttributeValue("value").empty()) + value = property_element->GetAttributeValueAsNumber("value"); + + interface_property_string = property_element->GetDataLine(); + if (PropertyManager->HasNode(interface_property_string)) { + FGPropertyManager* node = PropertyManager->GetNode(interface_property_string); + if (debug_lvl > 0) + cout << " " << "Overriding value for property " << interface_property_string + << " (old value: " << node->getDoubleValue() << " new value: " << value << ")" << endl; + node->setDoubleValue(value); + } else { + 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"); } - sensor_element = document->FindNextElement("sensor"); } channel_element = document->FindElement("channel"); while (channel_element) { - component_element = channel_element->FindElement("component"); - if (component_element) { - cout << "This form of the component specification is being deprecated" << endl; - } else { - component_element = channel_element->GetElement(); - } + + if (debug_lvl > 0) + cout << endl << highint << fgblue << " Channel " + << normint << channel_element->GetAttributeValue("name") << reset << endl; + + component_element = channel_element->GetElement(); while (component_element) { - comp_name = component_element->GetAttributeValue("type"); try { - if ((comp_name == "LAG_FILTER") || - (comp_name == "LEAD_LAG_FILTER") || - (comp_name == "SECOND_ORDER_FILTER") || - (comp_name == "WASHOUT_FILTER") || - (comp_name == "INTEGRATOR") || - (component_element->GetName() == string("lag_filter")) || + if ((component_element->GetName() == string("lag_filter")) || (component_element->GetName() == string("lead_lag_filter")) || (component_element->GetName() == string("washout_filter")) || (component_element->GetName() == string("second_order_filter")) || (component_element->GetName() == string("integrator")) ) { Components->push_back(new FGFilter(this, component_element)); - } else if ((comp_name == "PURE_GAIN") || - (comp_name == "SCHEDULED_GAIN") || - (comp_name == "AEROSURFACE_SCALE") || - (component_element->GetName() == string("pure_gain")) || + } else if ((component_element->GetName() == string("pure_gain")) || (component_element->GetName() == string("scheduled_gain")) || (component_element->GetName() == string("aerosurface_scale"))) { Components->push_back(new FGGain(this, component_element)); - } else if ((comp_name == "SUMMER") || (component_element->GetName() == string("summer"))) { + } else if (component_element->GetName() == string("summer")) { Components->push_back(new FGSummer(this, component_element)); - } else if ((comp_name == "DEADBAND") || (component_element->GetName() == string("deadband"))) { + } else if (component_element->GetName() == string("deadband")) { Components->push_back(new FGDeadBand(this, component_element)); - } else if (comp_name == "GRADIENT") { - Components->push_back(new FGGradient(this, component_element)); - } else if ((comp_name == "SWITCH") || (component_element->GetName() == string("switch"))) { + } else if (component_element->GetName() == string("switch")) { Components->push_back(new FGSwitch(this, component_element)); - } else if ((comp_name == "KINEMAT") || (component_element->GetName() == string("kinematic"))) { + } else if (component_element->GetName() == string("kinematic")) { Components->push_back(new FGKinemat(this, component_element)); - } else if ((comp_name == "FUNCTION") || (component_element->GetName() == string("fcs_function"))) { + } else if (component_element->GetName() == string("fcs_function")) { Components->push_back(new FGFCSFunction(this, component_element)); + } else if (component_element->GetName() == string("pid")) { + Components->push_back(new FGPID(this, component_element)); + } else if (component_element->GetName() == string("actuator")) { + Components->push_back(new FGActuator(this, component_element)); + } else if (component_element->GetName() == string("sensor")) { + Components->push_back(new FGSensor(this, component_element)); + } else if (component_element->GetName() == string("accelerometer")) { + Components->push_back(new FGAccelerometer(this, component_element)); + } else if (component_element->GetName() == string("magnetometer")) { + Components->push_back(new FGMagnetometer(this, component_element)); + } else if (component_element->GetName() == string("gyro")) { + Components->push_back(new FGGyro(this, component_element)); } else { - cerr << "Unknown FCS component: " << comp_name << endl; + cerr << "Unknown FCS component: " << component_element->GetName() << endl; } } catch(string s) { cerr << highint << fgred << endl << " " << s << endl; cerr << reset << endl; return false; } - if (comp_name.empty()) { // comp_name will be empty if using new format - component_element = channel_element->GetNextElement(); - } else { - component_element = channel_element->FindNextElement("component"); - } + component_element = channel_element->GetNextElement(); } channel_element = document->FindNextElement("channel"); } + ResetParser(); + return true; } @@ -607,23 +692,89 @@ double FGFCS::GetBrake(FGLGear::BrakeGroup bg) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -string FGFCS::GetComponentStrings(string delimeter) +string FGFCS::FindSystemFullPathname(const string& system_filename) +{ + string fullpath, localpath; + string systemPath = FDMExec->GetSystemsPath(); + string aircraftPath = FDMExec->GetFullAircraftPath(); + ifstream system_file; + + string separator = "/"; + + fullpath = systemPath + separator; + localpath = aircraftPath + separator + "Systems" + separator; + + system_file.open(string(fullpath + system_filename + ".xml").c_str()); + if ( !system_file.is_open()) { + system_file.open(string(localpath + system_filename + ".xml").c_str()); + if ( !system_file.is_open()) { + cerr << " Could not open system file: " << system_filename << " in path " + << fullpath << " or " << localpath << endl; + return string(""); + } else { + return string(localpath + system_filename + ".xml"); + } + } + return string(fullpath + system_filename + ".xml"); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ifstream* FGFCS::FindSystemFile(const string& system_filename) +{ + string fullpath, localpath; + string systemPath = FDMExec->GetSystemsPath(); + string aircraftPath = FDMExec->GetFullAircraftPath(); + ifstream* system_file = new ifstream(); + + string separator = "/"; + + fullpath = systemPath + separator; + localpath = aircraftPath + separator + "Systems" + separator; + + system_file->open(string(fullpath + system_filename + ".xml").c_str()); + if ( !system_file->is_open()) { + system_file->open(string(localpath + system_filename + ".xml").c_str()); + if ( !system_file->is_open()) { + cerr << " Could not open system file: " << system_filename << " in path " + << fullpath << " or " << localpath << endl; + } + } + return system_file; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGFCS::GetComponentStrings(const string& delimiter) { unsigned int comp; string CompStrings = ""; bool firstime = true; + int total_count=0; - for (comp = 0; comp < FCSComponents.size(); comp++) { + for (unsigned int i=0; iGetName(); + CompStrings += Systems[i]->GetName(); + total_count++; } for (comp = 0; comp < APComponents.size(); comp++) { - CompStrings += delimeter; + if (firstime) firstime = false; + else CompStrings += delimiter; + CompStrings += APComponents[comp]->GetName(); + total_count++; + } + + for (comp = 0; comp < FCSComponents.size(); comp++) { + if (firstime) firstime = false; + else CompStrings += delimiter; + + CompStrings += FCSComponents[comp]->GetName(); + total_count++; } return CompStrings; @@ -631,27 +782,39 @@ string FGFCS::GetComponentStrings(string delimeter) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -string FGFCS::GetComponentValues(string delimeter) +string FGFCS::GetComponentValues(const string& delimiter) { + std::ostringstream buf; + unsigned int comp; - string CompValues = ""; - char buffer[12]; bool firstime = true; + int total_count=0; - for (comp = 0; comp < FCSComponents.size(); comp++) { + for (unsigned int i=0; iGetOutput()); - CompValues += string(buffer); + buf << setprecision(9) << Systems[i]->GetOutput(); + total_count++; } for (comp = 0; comp < APComponents.size(); comp++) { - sprintf(buffer, "%s%9.6f", delimeter.c_str(), APComponents[comp]->GetOutput()); - CompValues += string(buffer); + if (firstime) firstime = false; + else buf << delimiter; + + buf << setprecision(9) << APComponents[comp]->GetOutput(); + total_count++; + } + + for (comp = 0; comp < FCSComponents.size(); comp++) { + if (firstime) firstime = false; + else buf << delimiter; + + buf << setprecision(9) << FCSComponents[comp]->GetOutput(); + total_count++; } - return CompValues; + return buf.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -667,7 +830,7 @@ void FGFCS::AddThrottle(void) PropFeatherCmd.push_back(false); PropFeather.push_back(false); - unsigned int num = ThrottleCmd.size()-1; + unsigned int num = (unsigned int)ThrottleCmd.size()-1; bindThrottle(num); } @@ -680,19 +843,24 @@ void FGFCS::AddGear(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +double FGFCS::GetDt(void) +{ + return FDMExec->GetDeltaT()*rate; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + void FGFCS::bind(void) { PropertyManager->Tie("fcs/aileron-cmd-norm", this, &FGFCS::GetDaCmd, &FGFCS::SetDaCmd); PropertyManager->Tie("fcs/elevator-cmd-norm", this, &FGFCS::GetDeCmd, &FGFCS::SetDeCmd); PropertyManager->Tie("fcs/rudder-cmd-norm", this, &FGFCS::GetDrCmd, &FGFCS::SetDrCmd); - PropertyManager->Tie("fcs/steer-cmd-norm", this, &FGFCS::GetDsCmd, &FGFCS::SetDsCmd); PropertyManager->Tie("fcs/flap-cmd-norm", this, &FGFCS::GetDfCmd, &FGFCS::SetDfCmd); PropertyManager->Tie("fcs/speedbrake-cmd-norm", this, &FGFCS::GetDsbCmd, &FGFCS::SetDsbCmd); PropertyManager->Tie("fcs/spoiler-cmd-norm", this, &FGFCS::GetDspCmd, &FGFCS::SetDspCmd); PropertyManager->Tie("fcs/pitch-trim-cmd-norm", this, &FGFCS::GetPitchTrimCmd, &FGFCS::SetPitchTrimCmd); PropertyManager->Tie("fcs/roll-trim-cmd-norm", this, &FGFCS::GetRollTrimCmd, &FGFCS::SetRollTrimCmd); PropertyManager->Tie("fcs/yaw-trim-cmd-norm", this, &FGFCS::GetYawTrimCmd, &FGFCS::SetYawTrimCmd); - PropertyManager->Tie("gear/gear-cmd-norm", this, &FGFCS::GetGearCmd, &FGFCS::SetGearCmd); PropertyManager->Tie("fcs/left-aileron-pos-rad", this, ofRad, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos); PropertyManager->Tie("fcs/left-aileron-pos-deg", this, ofDeg, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos); @@ -729,40 +897,47 @@ void FGFCS::bind(void) PropertyManager->Tie("fcs/mag-spoiler-pos-rad", this, ofMag, &FGFCS::GetDspPos); PropertyManager->Tie("gear/gear-pos-norm", this, &FGFCS::GetGearPos, &FGFCS::SetGearPos); + PropertyManager->Tie("gear/gear-cmd-norm", this, &FGFCS::GetGearCmd, &FGFCS::SetGearCmd); + PropertyManager->Tie("fcs/left-brake-cmd-norm", this, &FGFCS::GetLBrake, &FGFCS::SetLBrake); + PropertyManager->Tie("fcs/right-brake-cmd-norm", this, &FGFCS::GetRBrake, &FGFCS::SetRBrake); + PropertyManager->Tie("fcs/center-brake-cmd-norm", this, &FGFCS::GetCBrake, &FGFCS::SetCBrake); + PropertyManager->Tie("fcs/steer-cmd-norm", this, &FGFCS::GetDsCmd, &FGFCS::SetDsCmd); + + PropertyManager->Tie("gear/tailhook-pos-norm", this, &FGFCS::GetTailhookPos, &FGFCS::SetTailhookPos); + PropertyManager->Tie("fcs/wing-fold-pos-norm", this, &FGFCS::GetWingFoldPos, &FGFCS::SetWingFoldPos); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Technically, this function should probably bind propulsion type specific controls // rather than mixture and prop-advance. -// void FGFCS::bindThrottle(unsigned int num) { - char tmp[80]; + string tmp; - snprintf(tmp, 80, "fcs/throttle-cmd-norm[%u]",num); - PropertyManager->Tie( tmp, this, num, &FGFCS::GetThrottleCmd, + tmp = CreateIndexedPropertyName("fcs/throttle-cmd-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetThrottleCmd, &FGFCS::SetThrottleCmd); - snprintf(tmp, 80, "fcs/throttle-pos-norm[%u]",num); - PropertyManager->Tie( tmp, this, num, &FGFCS::GetThrottlePos, + tmp = CreateIndexedPropertyName("fcs/throttle-pos-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetThrottlePos, &FGFCS::SetThrottlePos); - snprintf(tmp, 80, "fcs/mixture-cmd-norm[%u]",num); - PropertyManager->Tie( tmp, this, num, &FGFCS::GetMixtureCmd, + tmp = CreateIndexedPropertyName("fcs/mixture-cmd-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetMixtureCmd, &FGFCS::SetMixtureCmd); - snprintf(tmp, 80, "fcs/mixture-pos-norm[%u]",num); - PropertyManager->Tie( tmp, this, num, &FGFCS::GetMixturePos, + tmp = CreateIndexedPropertyName("fcs/mixture-pos-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetMixturePos, &FGFCS::SetMixturePos); - snprintf(tmp, 80, "fcs/advance-cmd-norm[%u]",num); - PropertyManager->Tie( tmp, this, num, &FGFCS::GetPropAdvanceCmd, + tmp = CreateIndexedPropertyName("fcs/advance-cmd-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropAdvanceCmd, &FGFCS::SetPropAdvanceCmd); - snprintf(tmp, 80, "fcs/advance-pos-norm[%u]", num); - PropertyManager->Tie( tmp, this, num, &FGFCS::GetPropAdvance, + tmp = CreateIndexedPropertyName("fcs/advance-pos-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropAdvance, &FGFCS::SetPropAdvance); - snprintf(tmp, 80, "fcs/feather-cmd-norm[%u]", num); - PropertyManager->Tie( tmp, this, num, &FGFCS::GetFeatherCmd, + tmp = CreateIndexedPropertyName("fcs/feather-cmd-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetFeatherCmd, &FGFCS::SetFeatherCmd); - snprintf(tmp, 80, "fcs/feather-pos-norm[%u]", num); - PropertyManager->Tie( tmp, this, num, &FGFCS::GetPropFeather, + tmp = CreateIndexedPropertyName("fcs/feather-pos-norm", num); + PropertyManager->Tie( tmp.c_str(), this, num, &FGFCS::GetPropFeather, &FGFCS::SetPropFeather); } @@ -771,26 +946,12 @@ void FGFCS::bindThrottle(unsigned int num) void FGFCS::bindModel(void) { unsigned int i; - char tmp[80]; + string tmp; for (i=0; iGetGearUnit(i)->GetSteerable()) { - snprintf(tmp,80,"fcs/steer-pos-deg[%u]",i); - PropertyManager->Tie( tmp, this, i, &FGFCS::GetSteerPosDeg, &FGFCS::SetSteerPosDeg); - } - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGFCS::unbind(FGPropertyManager *node) -{ - int N = node->nChildren(); - for (int i=0; igetChild(i)->nChildren() ) { - unbind( (FGPropertyManager*)node->getChild(i) ); - } else if ( node->getChild(i)->isTied() ) { - node->getChild(i)->untie(); + tmp = CreateIndexedPropertyName("fcs/steer-pos-deg", i); + PropertyManager->Tie( tmp.c_str(), this, i, &FGFCS::GetSteerPosDeg, &FGFCS::SetSteerPosDeg); } } } @@ -820,7 +981,7 @@ void FGFCS::Debug(int from) if (debug_lvl & 1) { // Standard console startup message output if (from == 2) { // Loader - cout << endl << " Flight Control (" << Name << ")" << endl; + cout << endl << " " << Name << endl; } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification