1
0
Fork 0

YASIM refactoring of ControlMap

This commit is contained in:
Henning Stahlke 2017-11-29 09:17:51 +01:00
parent 09c60ee40e
commit 5aead123fc
4 changed files with 146 additions and 125 deletions

View file

@ -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

View file

@ -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

View file

@ -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)
{

View file

@ -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);