YASIM refactoring of ControlMap
This commit is contained in:
parent
09c60ee40e
commit
5aead123fc
4 changed files with 146 additions and 125 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue