From 5aead123fc7f9caabb2e02dfecabfd5e3b6b9c30 Mon Sep 17 00:00:00 2001 From: Henning Stahlke Date: Wed, 29 Nov 2017 09:17:51 +0100 Subject: [PATCH] YASIM refactoring of ControlMap --- src/FDM/YASim/ControlMap.cpp | 134 ++++++++++++++++++++++++----------- src/FDM/YASim/ControlMap.hpp | 53 +++++++++----- src/FDM/YASim/FGFDM.cpp | 74 +++---------------- src/FDM/YASim/FGFDM.hpp | 10 ++- 4 files changed, 146 insertions(+), 125 deletions(-) diff --git a/src/FDM/YASim/ControlMap.cpp b/src/FDM/YASim/ControlMap.cpp index 4beef0fe0..e2560193a 100644 --- a/src/FDM/YASim/ControlMap.cpp +++ b/src/FDM/YASim/ControlMap.cpp @@ -44,10 +44,10 @@ ControlMap::~ControlMap() input : index to _inputs type: identifier (see enum OutputType) */ -void ControlMap::addMapping(int input, int type, void* object, int options, +void ControlMap::addMapping(int input, Control control, void* object, int options, float src0, float src1, float dst0, float dst1) { - addMapping(input, type, object, options); + addMapping(input, control, object, options); // The one we just added is last in the list (ugly, awful hack!) Vector* maps = (Vector*)_inputs.get(input); @@ -63,26 +63,25 @@ void ControlMap::addMapping(int input, int type, void* object, int options, input : index to _inputs type: identifier (see enum OutputType) */ -void ControlMap::addMapping(int input, int type, void* object, int options) +void ControlMap::addMapping(int input, Control control, void* object, int options) { // See if the output object already exists OutRec* out = 0; int i; for(i=0; i<_outputs.size(); i++) { - OutRec* o = (OutRec*)_outputs.get(i); - if(o->object == object && o->type == type) { - out = o; - break; - } + OutRec* o = (OutRec*)_outputs.get(i); + if(o->object == object && o->control == control) { + out = o; + break; + } } // Create one if it doesn't if(out == 0) { - out = new OutRec(); - out->type = type; - out->object = object; - out->oldL = out->oldR = out->time = 0; - _outputs.add(out); + out = new OutRec(); + out->control = control; + out->object = object; + _outputs.add(out); } // Make a new input record @@ -92,8 +91,8 @@ void ControlMap::addMapping(int input, int type, void* object, int options) map->idx = out->maps.add(map); // The default ranges differ depending on type! - map->src1 = map->dst1 = rangeMax(type); - map->src0 = map->dst0 = rangeMin(type); + map->src1 = map->dst1 = rangeMax(control); + map->src0 = map->dst0 = rangeMin(control); // And add it to the approproate vectors. Vector* maps = (Vector*)_inputs.get(input); @@ -129,14 +128,14 @@ void ControlMap::setInput(int input, float val) } } -int ControlMap::getOutputHandle(void* obj, int type) +int ControlMap::getOutputHandle(void* obj, Control control) { for(int i=0; i<_outputs.size(); i++) { OutRec* o = (OutRec*)_outputs.get(i); - if(o->object == obj && o->type == type) + if(o->object == obj && o->control == control) return i; } - fprintf(stderr, "ControlMap::getOutputHandle cannot find *%d, type %d \n", obj, type); + fprintf(stderr, "ControlMap::getOutputHandle cannot find *%d, control %d \n", obj, control); return -1; } @@ -188,7 +187,7 @@ void ControlMap::applyControls(float dt) float adl = Math::abs(dl); float adr = Math::abs(dr); - float max = (dt/o->time) * (rangeMax(o->type) - rangeMin(o->type)); + float max = (dt/o->time) * (rangeMax(o->control) - rangeMin(o->control)); if(adl > max) dl = dl*max/adl; if(adr > max) dr = dr*max/adr; @@ -200,7 +199,7 @@ void ControlMap::applyControls(float dt) o->oldR = rval; void* obj = o->object; - switch(o->type) { + switch(o->control) { case THROTTLE: ((Thruster*)obj)->setThrottle(lval); break; case MIXTURE: ((Thruster*)obj)->setMixture(lval); break; case CONDLEVER: ((TurbineEngine*)((PropEngine*) @@ -255,35 +254,35 @@ void ControlMap::applyControls(float dt) } } -float ControlMap::rangeMin(int type) +float ControlMap::rangeMin(Control control) { // The minimum of the range for each type of control - switch(type) { - case FLAP0: return -1; // [-1:1] - case FLAP1: return -1; - case STEER: return -1; - case CYCLICELE: return -1; - case CYCLICAIL: return -1; - case COLLECTIVE: return -1; - case WINCHRELSPEED: return -1; - case MAGNETOS: return 0; // [0:3] - case FLAP0EFFECTIVENESS: return 1; // [0:10] - case FLAP1EFFECTIVENESS: return 1; // [0:10] - default: return 0; // [0:1] + switch(control) { + case FLAP0: return -1; // [-1:1] + case FLAP1: return -1; + case STEER: return -1; + case CYCLICELE: return -1; + case CYCLICAIL: return -1; + case COLLECTIVE: return -1; + case WINCHRELSPEED: return -1; + case MAGNETOS: return 0; // [0:3] + case FLAP0EFFECTIVENESS: return 1; // [0:10] + case FLAP1EFFECTIVENESS: return 1; // [0:10] + default: return 0; // [0:1] } } -float ControlMap::rangeMax(int type) +float ControlMap::rangeMax(Control control) { // The maximum of the range for each type of control - switch(type) { - case FLAP0: return 1; // [-1:1] - case FLAP1: return 1; - case STEER: return 1; - case MAGNETOS: return 3; // [0:3] - case FLAP0EFFECTIVENESS: return 10;// [0:10] - case FLAP1EFFECTIVENESS: return 10;// [0:10] - default: return 1; // [0:1] + switch(control) { + case FLAP0: return 1; // [-1:1] + case FLAP1: return 1; + case STEER: return 1; + case MAGNETOS: return 3; // [0:3] + case FLAP0EFFECTIVENESS: return 10;// [0:10] + case FLAP1EFFECTIVENESS: return 10;// [0:10] + default: return 1; // [0:1] } } @@ -328,4 +327,55 @@ int ControlMap::propertyHandle(const char* name) return p->handle; } + +ControlMap::Control ControlMap::parseControl(const char* name) +{ + if(eq(name, "THROTTLE")) return THROTTLE; + if(eq(name, "MIXTURE")) return MIXTURE; + if(eq(name, "CONDLEVER")) return CONDLEVER; + if(eq(name, "STARTER")) return STARTER; + if(eq(name, "MAGNETOS")) return MAGNETOS; + if(eq(name, "ADVANCE")) return ADVANCE; + if(eq(name, "REHEAT")) return REHEAT; + if(eq(name, "BOOST")) return BOOST; + if(eq(name, "VECTOR")) return VECTOR; + if(eq(name, "PROP")) return PROP; + if(eq(name, "BRAKE")) return BRAKE; + if(eq(name, "STEER")) return STEER; + if(eq(name, "EXTEND")) return EXTEND; + if(eq(name, "HEXTEND")) return HEXTEND; + if(eq(name, "LEXTEND")) return LEXTEND; + if(eq(name, "LACCEL")) return LACCEL; + if(eq(name, "INCIDENCE")) return INCIDENCE; + if(eq(name, "FLAP0")) return FLAP0; + if(eq(name, "FLAP0EFFECTIVENESS")) return FLAP0EFFECTIVENESS; + if(eq(name, "FLAP1")) return FLAP1; + if(eq(name, "FLAP1EFFECTIVENESS")) return FLAP1EFFECTIVENESS; + if(eq(name, "SLAT")) return SLAT; + if(eq(name, "SPOILER")) return SPOILER; + if(eq(name, "CASTERING")) return CASTERING; + if(eq(name, "PROPPITCH")) return PROPPITCH; + if(eq(name, "PROPFEATHER")) return PROPFEATHER; + if(eq(name, "COLLECTIVE")) return COLLECTIVE; + if(eq(name, "CYCLICAIL")) return CYCLICAIL; + if(eq(name, "CYCLICELE")) return CYCLICELE; + if(eq(name, "TILTROLL")) return TILTROLL; + if(eq(name, "TILTPITCH")) return TILTPITCH; + if(eq(name, "TILTYAW")) return TILTYAW; + if(eq(name, "ROTORGEARENGINEON")) return ROTORENGINEON; + if(eq(name, "ROTORBRAKE")) return ROTORBRAKE; + if(eq(name, "ROTORENGINEMAXRELTORQUE")) return ROTORENGINEMAXRELTORQUE; + if(eq(name, "ROTORRELTARGET")) return ROTORRELTARGET; + if(eq(name, "ROTORBALANCE")) return ROTORBALANCE; + if(eq(name, "REVERSE_THRUST")) return REVERSE_THRUST; + if(eq(name, "WASTEGATE")) return WASTEGATE; + if(eq(name, "WINCHRELSPEED")) return WINCHRELSPEED; + if(eq(name, "HITCHOPEN")) return HITCHOPEN; + if(eq(name, "PLACEWINCH")) return PLACEWINCH; + if(eq(name, "FINDAITOW")) return FINDAITOW; + SG_LOG(SG_FLIGHT,SG_ALERT,"Unrecognized control type '" << name + << "' in YASim aircraft description."); + exit(1); +} + } // namespace yasim diff --git a/src/FDM/YASim/ControlMap.hpp b/src/FDM/YASim/ControlMap.hpp index 41342f450..3c135fa6d 100644 --- a/src/FDM/YASim/ControlMap.hpp +++ b/src/FDM/YASim/ControlMap.hpp @@ -10,7 +10,7 @@ class ControlMap { public: ~ControlMap(); - enum OutputType { + enum Control { THROTTLE, MIXTURE, CONDLEVER, @@ -56,22 +56,25 @@ public: FINDAITOW }; - enum { OPT_SPLIT = 0x01, - OPT_INVERT = 0x02, - OPT_SQUARE = 0x04 + enum { + OPT_SPLIT = 0x01, + OPT_INVERT = 0x02, + OPT_SQUARE = 0x04 }; struct PropHandle { char* name; int handle; }; - + + // map control name to int (enum) + Control parseControl(const char* name); // Adds a mapping to between input handle and a particular setting // on an output object. The value of output MUST match the type // of object! - void addMapping(int input, int output, void* object, int options=0); + void addMapping(int input, Control control, void* object, int options=0); // An additional form to specify a mapping range. Input values // outside of [src0:src1] are clamped, and are then mapped to // [dst0:dst1] before being set on the object. - void addMapping(int input, int output, void* object, int options, + void addMapping(int input, Control control, void* object, int options, float src0, float src1, float dst0, float dst1); // Resets our accumulated input values. Call before any @@ -89,12 +92,12 @@ public: // Returns the input/output range appropriate for the given // control. Ailerons go from -1 to 1, while throttles are never // lower than zero, etc... - static float rangeMin(int type); - static float rangeMax(int type); + static float rangeMin(Control control); + static float rangeMax(Control control); // Each output record is identified by both an object/type tuple // and a numeric handle. - int getOutputHandle(void* obj, int type); + int getOutputHandle(void* obj, Control control); // Sets the transition time for the control output to swing // through its full range. @@ -111,15 +114,25 @@ public: 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; }; - struct MapRec { OutRec* out; int idx; int opt; float val; - float src0; float src1; float dst0; float dst1; }; + struct OutRec { + Control control; + void* object; + Vector maps; + float oldL {0}; + float oldR {0}; + float time {0}; + }; + struct MapRec { + OutRec* out; + int idx {0}; + int opt {0}; + float val {0}; + float src0 {0}; + float src1 {0}; + float dst0 {0}; + float dst1 {0}; + }; // A list of (sub)Vectors containing a bunch of MapRec objects for // each input handle. @@ -129,6 +142,10 @@ private: Vector _outputs; // control properties Vector _properties; + + // helper + char* dup(const char* s); + bool eq(const char* a, const char* b); }; }; // namespace yasim diff --git a/src/FDM/YASim/FGFDM.cpp b/src/FDM/YASim/FGFDM.cpp index e93ed0354..ee13427a4 100644 --- a/src/FDM/YASim/FGFDM.cpp +++ b/src/FDM/YASim/FGFDM.cpp @@ -587,7 +587,7 @@ void FGFDM::startElement(const char* name, const XMLAttributes &atts) 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")); + ControlMap::Control control = cm->parseControl(a->getValue("control")); int opt = 0; opt |= a->hasAttribute("split") ? ControlMap::OPT_SPLIT : 0; opt |= a->hasAttribute("invert") ? ControlMap::OPT_INVERT : 0; @@ -602,23 +602,24 @@ void FGFDM::startElement(const char* name, const XMLAttributes &atts) } 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")); - int handle = cm->getOutputHandle(_currObj, type); + ControlMap::Control control = cm->parseControl(a->getValue("control")); + + int handle = cm->getOutputHandle(_currObj, control); PropOut* p = new PropOut(); p->prop = fgGetNode(a->getValue("prop"), true); p->handle = handle; - p->type = type; + p->control = control; p->left = !(a->hasAttribute("side") && eq("right", a->getValue("side"))); - p->min = attrf(a, "min", cm->rangeMin(type)); - p->max = attrf(a, "max", cm->rangeMax(type)); + p->min = attrf(a, "min", cm->rangeMin(control)); + p->max = attrf(a, "max", cm->rangeMax(control)); _controlProps.add(p); } else if(eq(name, "control-speed")) { ControlMap* cm = _airplane.getControlMap(); - int type = parseOutput(a->getValue("control")); - int handle = cm->getOutputHandle(_currObj, type); + ControlMap::Control control = cm->parseControl(a->getValue("control")); + int handle = cm->getOutputHandle(_currObj, control); float time = attrf(a, "transition-time", 0); cm->setTransitionTime(handle, time); @@ -715,8 +716,8 @@ void FGFDM::setOutputProperties(float dt) float val = (p->left ? cm->getOutput(p->handle) : cm->getOutputR(p->handle)); - float rmin = cm->rangeMin(p->type); - float rmax = cm->rangeMax(p->type); + float rmin = cm->rangeMin(p->control); + float rmax = cm->rangeMax(p->control); float frac = (val - rmin) / (rmax - rmin); val = frac*(p->max - p->min) + p->min; p->prop->setFloatValue(val); @@ -1104,59 +1105,6 @@ void FGFDM::parsePropeller(XMLAttributes* a) _currObj = thruster; } -/// map identifier (string) to int (enum in ControlMap) -int FGFDM::parseOutput(const char* name) -{ - if(eq(name, "THROTTLE")) return ControlMap::THROTTLE; - if(eq(name, "MIXTURE")) return ControlMap::MIXTURE; - if(eq(name, "CONDLEVER")) return ControlMap::CONDLEVER; - if(eq(name, "STARTER")) return ControlMap::STARTER; - if(eq(name, "MAGNETOS")) return ControlMap::MAGNETOS; - if(eq(name, "ADVANCE")) return ControlMap::ADVANCE; - if(eq(name, "REHEAT")) return ControlMap::REHEAT; - if(eq(name, "BOOST")) return ControlMap::BOOST; - if(eq(name, "VECTOR")) return ControlMap::VECTOR; - if(eq(name, "PROP")) return ControlMap::PROP; - if(eq(name, "BRAKE")) return ControlMap::BRAKE; - if(eq(name, "STEER")) return ControlMap::STEER; - if(eq(name, "EXTEND")) return ControlMap::EXTEND; - if(eq(name, "HEXTEND")) return ControlMap::HEXTEND; - if(eq(name, "LEXTEND")) return ControlMap::LEXTEND; - if(eq(name, "LACCEL")) return ControlMap::LACCEL; - if(eq(name, "INCIDENCE")) return ControlMap::INCIDENCE; - if(eq(name, "FLAP0")) return ControlMap::FLAP0; - if(eq(name, "FLAP0EFFECTIVENESS")) return ControlMap::FLAP0EFFECTIVENESS; - if(eq(name, "FLAP1")) return ControlMap::FLAP1; - if(eq(name, "FLAP1EFFECTIVENESS")) return ControlMap::FLAP1EFFECTIVENESS; - if(eq(name, "SLAT")) return ControlMap::SLAT; - if(eq(name, "SPOILER")) return ControlMap::SPOILER; - if(eq(name, "CASTERING")) return ControlMap::CASTERING; - if(eq(name, "PROPPITCH")) return ControlMap::PROPPITCH; - if(eq(name, "PROPFEATHER")) return ControlMap::PROPFEATHER; - if(eq(name, "COLLECTIVE")) return ControlMap::COLLECTIVE; - if(eq(name, "CYCLICAIL")) return ControlMap::CYCLICAIL; - if(eq(name, "CYCLICELE")) return ControlMap::CYCLICELE; - if(eq(name, "TILTROLL")) return ControlMap::TILTROLL; - if(eq(name, "TILTPITCH")) return ControlMap::TILTPITCH; - 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")) - return ControlMap::ROTORENGINEMAXRELTORQUE; - if(eq(name, "ROTORRELTARGET")) return ControlMap::ROTORRELTARGET; - if(eq(name, "ROTORBALANCE")) return ControlMap::ROTORBALANCE; - if(eq(name, "REVERSE_THRUST")) return ControlMap::REVERSE_THRUST; - if(eq(name, "WASTEGATE")) return ControlMap::WASTEGATE; - if(eq(name, "WINCHRELSPEED")) return ControlMap::WINCHRELSPEED; - if(eq(name, "HITCHOPEN")) return ControlMap::HITCHOPEN; - if(eq(name, "PLACEWINCH")) return ControlMap::PLACEWINCH; - if(eq(name, "FINDAITOW")) return ControlMap::FINDAITOW; - - SG_LOG(SG_FLIGHT,SG_ALERT,"Unrecognized control type '" - << name << "' in YASim aircraft description."); - exit(1); - -} void FGFDM::parseWeight(XMLAttributes* a) { diff --git a/src/FDM/YASim/FGFDM.hpp b/src/FDM/YASim/FGFDM.hpp index 28eabba21..2d57090ac 100644 --- a/src/FDM/YASim/FGFDM.hpp +++ b/src/FDM/YASim/FGFDM.hpp @@ -34,8 +34,14 @@ public: private: struct EngRec { char* prefix; Thruster* eng; }; struct WeightRec { char* prop; float size; int handle; }; - struct PropOut { SGPropertyNode* prop; int handle, type; bool left; - float min, max; }; + struct PropOut { + SGPropertyNode* prop; + int handle {0}; + ControlMap::Control control; + bool left {false}; + float min {0}; + float max {0}; + }; void setOutputProperties(float dt);