From 2cac4e4671e252f04f87f5be5cd0c8608cfcfbf5 Mon Sep 17 00:00:00 2001 From: Henning Stahlke Date: Mon, 6 Feb 2017 17:47:45 +0100 Subject: [PATCH] YASim: Move variables and methods for input properties from FGFDM to ControlMap. --- src/FDM/YASim/ControlMap.cpp | 79 +++++++++++++++++++----- src/FDM/YASim/ControlMap.hpp | 20 ++++-- src/FDM/YASim/FGFDM.cpp | 116 ++++++++++++++--------------------- src/FDM/YASim/FGFDM.hpp | 6 -- 4 files changed, 124 insertions(+), 97 deletions(-) diff --git a/src/FDM/YASim/ControlMap.cpp b/src/FDM/YASim/ControlMap.cpp index 6a51650f1..bf56615f9 100644 --- a/src/FDM/YASim/ControlMap.cpp +++ b/src/FDM/YASim/ControlMap.cpp @@ -21,25 +21,29 @@ namespace yasim { ControlMap::~ControlMap() { - int i; - for(i=0; i<_inputs.size(); i++) { - Vector* v = (Vector*)_inputs.get(i); - int j; - for(j=0; jsize(); j++) + int i; + for(i=0; i<_inputs.size(); i++) { + Vector* v = (Vector*)_inputs.get(i); + int j; + for(j=0; jsize(); j++) delete (MapRec*)v->get(j); - delete v; - } + delete v; + } - for(i=0; i<_outputs.size(); i++) - delete (OutRec*)_outputs.get(i); -} - -int ControlMap::newInput() -{ - Vector* v = new Vector(); - return _inputs.add(v); + for(i=0; i<_outputs.size(); i++) + delete (OutRec*)_outputs.get(i); + + for(i=0; i<_properties.size(); i++) { + PropHandle* p = (PropHandle*)_properties.get(i); + delete[] p->name; + delete p; + } } +/** + input : index to _inputs + type: identifier (see enum OutputType) +*/ void ControlMap::addMapping(int input, int type, void* object, int options, float src0, float src1, float dst0, float dst1) { @@ -55,6 +59,10 @@ void ControlMap::addMapping(int input, int type, void* object, int options, m->dst1 = dst1; } +/** + input : index to _inputs + type: identifier (see enum OutputType) +*/ void ControlMap::addMapping(int input, int type, void* object, int options) { // See if the output object already exists @@ -278,4 +286,45 @@ float ControlMap::rangeMax(int type) } } +/// duplicate null-terminated string +char* ControlMap::dup(const char* s) +{ + int len=0; + while(s[len++]); + char* s2 = new char[len+1]; + char* p = s2; + while((*p++ = *s++)); + s2[len] = 0; + return s2; +} + +/// compare null-terminated strings +bool ControlMap::eq(const char* a, const char* b) +{ + while(*a && *b && *a == *b) { a++; b++; } + // equal if both a and b points to null chars + return !(*a || *b); +} + +/// register property name, return ID (int) +int ControlMap::propertyHandle(const char* name) +{ + for(int i=0; i < _properties.size(); i++) { + PropHandle* p = (PropHandle*)_properties.get(i); + if(eq(p->name, name)) + return p->handle; + } + + // create new + PropHandle* p = new PropHandle(); + p->name = dup(name); + + fgGetNode(p->name, true); + + Vector* v = new Vector(); + p->handle = _inputs.add(v); + _properties.add(p); + return p->handle; +} + } // namespace yasim diff --git a/src/FDM/YASim/ControlMap.hpp b/src/FDM/YASim/ControlMap.hpp index 4741f5df0..dc7f75f79 100644 --- a/src/FDM/YASim/ControlMap.hpp +++ b/src/FDM/YASim/ControlMap.hpp @@ -1,6 +1,7 @@ #ifndef _CONTROL_MAP_HPP #define _CONTROL_MAP_HPP +#include #include "Vector.hpp" namespace yasim { @@ -26,9 +27,7 @@ public: OPT_INVERT = 0x02, OPT_SQUARE = 0x04 }; - // Returns a new, not-yet-used "input handle" for addMapping and - // setInput. This typically corresponds to one user axis. - int newInput(); + struct PropHandle { char* name; int handle; }; // Adds a mapping to between input handle and a particular setting // on an output object. The value of output MUST match the type @@ -45,9 +44,9 @@ public: // setInput() invokations. void reset(); - // Sets the specified input (as returned by newInput) to the + // Sets the specified input (as returned by propertyHandle) to the // specified value. - void setInput(int input, float value); + void setInput(int propHandle, float value); /// Calculates and applies the settings received since the last reset(). /// dt defaults to a large value used at solve time. @@ -73,6 +72,15 @@ public: float getOutput(int handle); float getOutputR(int handle); + // register property name, return handle + int propertyHandle(const char* name); + int numProperties() { return _properties.size(); } + PropHandle* getProperty(const int i) { return ((PropHandle*)_properties.get(i)); } + + // helper + char* dup(const char* s); + bool eq(const char* a, const char* b); + private: struct OutRec { int type; void* object; Vector maps; float oldL, oldR, time; }; @@ -85,6 +93,8 @@ private: // An unordered list of output settings. Vector _outputs; + // control properties + Vector _properties; }; }; // namespace yasim diff --git a/src/FDM/YASim/FGFDM.cpp b/src/FDM/YASim/FGFDM.cpp index 480376b67..659cfe550 100644 --- a/src/FDM/YASim/FGFDM.cpp +++ b/src/FDM/YASim/FGFDM.cpp @@ -59,7 +59,7 @@ FGFDM::FGFDM() // Map /controls/flight/elevator to the approach elevator control. This // should probably be settable, but there are very few aircraft // who trim their approaches using things other than elevator. - _airplane.setElevatorControl(parseAxis("/controls/flight/elevator-trim")); + _airplane.setElevatorControl(_airplane.getControlMap()->propertyHandle("/controls/flight/elevator-trim")); // FIXME: read seed from somewhere? int seed = 0; @@ -68,12 +68,6 @@ FGFDM::FGFDM() FGFDM::~FGFDM() { - for(int i=0; i<_axes.size(); i++) { - AxisRec* a = (AxisRec*)_axes.get(i); - delete[] a->name; - delete a; - } - for(int i=0; i<_thrusters.size(); i++) { EngRec* er = (EngRec*)_thrusters.get(i); delete[] er->prefix; @@ -113,7 +107,7 @@ void FGFDM::iterate(float dt) _airplane.setFuel(i, LBS2KG * _tank_level_lbs[i]->getFloatValue()); } _airplane.calcFuelWeights(); - + setOutputProperties(dt); } @@ -320,7 +314,7 @@ void FGFDM::startElement(const char* name, const XMLAttributes &atts) j->setVMax(attrf(a, "exhaust-speed") * KTS2MPS); if(a->hasAttribute("spool-time")) j->setSpooling(attrf(a, "spool-time")); - + j->setPosition(v); _airplane.addThruster(j, mass, v); sprintf(buf, "/engines/engine[%d]", _nextEngine++); @@ -459,14 +453,14 @@ void FGFDM::startElement(const char* name, const XMLAttributes &atts) float cy = attrf(a, "cy", 1); float cz = attrf(a, "cz", 1); float idrag = attrf(a, "idrag", 1); - _airplane.addFuselage(v, b, attrf(a, "width"), taper, mid, + _airplane.addFuselage(v, b, attrf(a, "width"), taper, mid, cx, cy, cz, idrag); } else if(eq(name, "tank")) { v[0] = attrf(a, "x"); v[1] = attrf(a, "y"); v[2] = attrf(a, "z"); float density = 6.0; // gasoline, in lbs/gal - if(a->hasAttribute("jet")) density = 6.72; + if(a->hasAttribute("jet")) density = 6.72; density *= LBS2KG*CM2GALS; _airplane.addTank(v, attrf(a, "capacity") * LBS2KG, density); } else if(eq(name, "ballast")) { @@ -497,7 +491,7 @@ void FGFDM::startElement(const char* name, const XMLAttributes &atts) ((Rotor*)_currObj)->setcollective(attrf(a, "min"), attrf(a, "max")); } else if(eq(name, "cyclic")) { ((Rotor*)_currObj)->setcyclic(attrf(a, "ail"), attrf(a, "ele")); - */ + */ } else if(eq(name, "actionpt")) { v[0] = attrf(a, "x"); v[1] = attrf(a, "y"); @@ -508,33 +502,32 @@ void FGFDM::startElement(const char* name, const XMLAttributes &atts) v[1] = attrf(a, "y"); v[2] = attrf(a, "z"); ((Thruster*)_currObj)->setDirection(v); - } else if(eq(name, "control-setting")) { - // A cruise or approach control setting - const char* axis = a->getValue("axis"); - float value = attrf(a, "value", 0); - if(_cruiseCurr) - _airplane.addCruiseControl(parseAxis(axis), value); - else - _airplane.addApproachControl(parseAxis(axis), value); - } else if(eq(name, "control-input")) { - - // A mapping of input property to a control - int axis = parseAxis(a->getValue("axis")); - int control = parseOutput(a->getValue("control")); - int opt = 0; - opt |= a->hasAttribute("split") ? ControlMap::OPT_SPLIT : 0; - opt |= a->hasAttribute("invert") ? ControlMap::OPT_INVERT : 0; - opt |= a->hasAttribute("square") ? ControlMap::OPT_SQUARE : 0; - - ControlMap* cm = _airplane.getControlMap(); - if(a->hasAttribute("src0")) { - cm->addMapping(axis, control, _currObj, opt, - attrf(a, "src0"), attrf(a, "src1"), + } else if(eq(name, "control-setting")) { + // A cruise or approach control setting + const char* axis = a->getValue("axis"); + float value = attrf(a, "value", 0); + ControlMap* cm = _airplane.getControlMap(); + if(_cruiseCurr) + _airplane.addCruiseControl(cm->propertyHandle(axis), value); + else + _airplane.addApproachControl(cm->propertyHandle(axis), value); + } else if(eq(name, "control-input")) { + ControlMap* cm = _airplane.getControlMap(); + // A mapping of input property to a control + int axis = cm->propertyHandle(a->getValue("axis")); + int control = parseOutput(a->getValue("control")); + int opt = 0; + opt |= a->hasAttribute("split") ? ControlMap::OPT_SPLIT : 0; + opt |= a->hasAttribute("invert") ? ControlMap::OPT_INVERT : 0; + opt |= a->hasAttribute("square") ? ControlMap::OPT_SQUARE : 0; + if(a->hasAttribute("src0")) { + cm->addMapping(axis, control, _currObj, opt, + attrf(a, "src0"), attrf(a, "src1"), attrf(a, "dst0"), attrf(a, "dst1")); - } else { - cm->addMapping(axis, control, _currObj, opt); - } - } else if(eq(name, "control-output")) { + } else { + cm->addMapping(axis, control, _currObj, opt); + } + } else if(eq(name, "control-output")) { // A property output for a control on the current object ControlMap* cm = _airplane.getControlMap(); int type = parseOutput(a->getValue("control")); @@ -555,7 +548,7 @@ void FGFDM::startElement(const char* name, const XMLAttributes &atts) int type = parseOutput(a->getValue("control")); int handle = cm->getOutputHandle(_currObj, type); float time = attrf(a, "transition-time", 0); - + cm->setTransitionTime(handle, time); } else { SG_LOG(SG_FLIGHT,SG_ALERT,"Unexpected tag '" @@ -575,10 +568,10 @@ void FGFDM::getExternalInput(float dt) ControlMap* cm = _airplane.getControlMap(); cm->reset(); - for(int i=0; i<_axes.size(); i++) { - AxisRec* a = (AxisRec*)_axes.get(i); - float val = fgGetFloat(a->name, 0); - cm->setInput(a->handle, val); + for(int i=0; i < cm->numProperties(); i++) { + ControlMap::PropHandle *p = cm->getProperty(i); + float val = fgGetFloat(p->name, 0); + cm->setInput(p->handle, val); } cm->applyControls(dt); @@ -716,7 +709,7 @@ void FGFDM::setOutputProperties(float dt) // cockpit code can scale them to the right values. float pnorm = j->getPerfNorm(); moveprop(node, "oilp-norm", pnorm, dt/3); // 3s seek time - moveprop(node, "oilt-norm", pnorm, dt/30); // 30s + moveprop(node, "oilt-norm", pnorm, dt/30); // 30s moveprop(node, "itt-norm", pnorm, dt/1); // 1s } } @@ -824,9 +817,9 @@ Rotor* FGFDM::parseRotor(XMLAttributes* a, const char* type) w->setTiltCenterZ(attrf(a,"tiltcenterz",0.0)); w->setDownwashFactor(attrf(a, "downwashfactor", 1)); if(attrb(a,"ccw")) - w->setCcw(1); + w->setCcw(1); if(attrb(a,"sharedflaphinge")) - w->setSharedFlapHinge(true); + w->setSharedFlapHinge(true); if(a->hasAttribute("name")) w->setName(a->getValue("name") ); @@ -845,7 +838,7 @@ Rotor* FGFDM::parseRotor(XMLAttributes* a, const char* type) w->setPowerAtPitch0(attrf(a, "poweratpitch-0", 300)); w->setPowerAtPitchB(attrf(a, "poweratpitch-b", 3000)); if(attrb(a,"notorque")) - w->setNotorque(1); + w->setNotorque(1); #define p(x) if (a->hasAttribute(#x)) w->setParameter((char *)#x,attrf(a,#x) ); #define p2(x,y) if (a->hasAttribute(y)) w->setParameter((char *)#x,attrf(a,y) ); @@ -893,7 +886,7 @@ void FGFDM::parsePistonEngine(XMLAttributes* a) eng->setDisplacement(attrf(a, "displacement") * CIN2CM); if(a->hasAttribute("compression")) - eng->setCompression(attrf(a, "compression")); + eng->setCompression(attrf(a, "compression")); if(a->hasAttribute("min-throttle")) eng->setMinThrottle(attrf(a, "min-throttle")); @@ -944,7 +937,7 @@ void FGFDM::parsePropeller(XMLAttributes* a) if(a->hasAttribute("displacement")) eng->setDisplacement(attrf(a, "displacement") * CIN2CM); if(a->hasAttribute("compression")) - eng->setCompression(attrf(a, "compression")); + eng->setCompression(attrf(a, "compression")); if(a->hasAttribute("turbo-mul")) { float mul = attrf(a, "turbo-mul"); float mp = attrf(a, "wastegate-mp", 1e6) * INHG2PA; @@ -1005,26 +998,7 @@ void FGFDM::parsePropeller(XMLAttributes* a) _currObj = thruster; } -// Turns a string axis name into an integer for use by the -// ControlMap. Creates a new axis if this one hasn't been defined -// yet. -int FGFDM::parseAxis(const char* name) -{ - for(int i=0; i<_axes.size(); i++) { - AxisRec* a = (AxisRec*)_axes.get(i); - if(eq(a->name, name)) - return a->handle; - } - - // Not there, make a new one. - AxisRec* a = new AxisRec(); - a->name = dup(name); - fgGetNode( a->name, true ); // make sure the property name exists - a->handle = _airplane.getControlMap()->newInput(); - _axes.add(a); - return a->handle; -} - +/// map identifier (string) to int (enum in ControlMap) int FGFDM::parseOutput(const char* name) { if(eq(name, "THROTTLE")) return ControlMap::THROTTLE; @@ -1061,7 +1035,7 @@ int FGFDM::parseOutput(const char* name) if(eq(name, "TILTYAW")) return ControlMap::TILTYAW; if(eq(name, "ROTORGEARENGINEON")) return ControlMap::ROTORENGINEON; if(eq(name, "ROTORBRAKE")) return ControlMap::ROTORBRAKE; - if(eq(name, "ROTORENGINEMAXRELTORQUE")) + if(eq(name, "ROTORENGINEMAXRELTORQUE")) return ControlMap::ROTORENGINEMAXRELTORQUE; if(eq(name, "ROTORRELTARGET")) return ControlMap::ROTORRELTARGET; if(eq(name, "ROTORBALANCE")) return ControlMap::ROTORBALANCE; @@ -1143,7 +1117,7 @@ float FGFDM::attrf(XMLAttributes* atts, const char* attr, float def) { const char* val = atts->getValue(attr); if(val == 0) return def; - else return (float)atof(val); + else return (float)atof(val); } double FGFDM::attrd(XMLAttributes* atts, const char* attr) diff --git a/src/FDM/YASim/FGFDM.hpp b/src/FDM/YASim/FGFDM.hpp index b8fb8ca18..0b7c48daa 100644 --- a/src/FDM/YASim/FGFDM.hpp +++ b/src/FDM/YASim/FGFDM.hpp @@ -31,7 +31,6 @@ public: float getVehicleRadius(void) const { return _vehicle_radius; } private: - struct AxisRec { char* name; int handle; }; struct EngRec { char* prefix; Thruster* eng; }; struct WeightRec { char* prop; float size; int handle; }; struct PropOut { SGPropertyNode* prop; int handle, type; bool left; @@ -41,7 +40,6 @@ private: Rotor* parseRotor(XMLAttributes* a, const char* name); Wing* parseWing(XMLAttributes* a, const char* name, Version * version); - int parseAxis(const char* name); int parseOutput(const char* name); void parseWeight(XMLAttributes* a); void parseTurbineEngine(XMLAttributes* a); @@ -64,10 +62,6 @@ private: // Aerodynamic turbulence model Turbulence* _turb; - // The list of "axes" that we expect to find as input. These are - // typically property names. - Vector _axes; - // Settable weights Vector _weights;