1
0
Fork 0

YASim: Move variables and methods for input properties from FGFDM to ControlMap.

This commit is contained in:
Henning Stahlke 2017-02-06 17:47:45 +01:00
parent f14cc3be33
commit 2cac4e4671
4 changed files with 124 additions and 97 deletions

View file

@ -21,25 +21,29 @@ namespace yasim {
ControlMap::~ControlMap() ControlMap::~ControlMap()
{ {
int i; int i;
for(i=0; i<_inputs.size(); i++) { for(i=0; i<_inputs.size(); i++) {
Vector* v = (Vector*)_inputs.get(i); Vector* v = (Vector*)_inputs.get(i);
int j; int j;
for(j=0; j<v->size(); j++) for(j=0; j<v->size(); j++)
delete (MapRec*)v->get(j); delete (MapRec*)v->get(j);
delete v; delete v;
} }
for(i=0; i<_outputs.size(); i++) for(i=0; i<_outputs.size(); i++)
delete (OutRec*)_outputs.get(i); delete (OutRec*)_outputs.get(i);
}
for(i=0; i<_properties.size(); i++) {
int ControlMap::newInput() PropHandle* p = (PropHandle*)_properties.get(i);
{ delete[] p->name;
Vector* v = new Vector(); delete p;
return _inputs.add(v); }
} }
/**
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, int type, void* object, int options,
float src0, float src1, float dst0, float dst1) 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; m->dst1 = dst1;
} }
/**
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, int type, void* object, int options)
{ {
// See if the output object already exists // 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 } // namespace yasim

View file

@ -1,6 +1,7 @@
#ifndef _CONTROL_MAP_HPP #ifndef _CONTROL_MAP_HPP
#define _CONTROL_MAP_HPP #define _CONTROL_MAP_HPP
#include <simgear/props/props.hxx>
#include "Vector.hpp" #include "Vector.hpp"
namespace yasim { namespace yasim {
@ -26,9 +27,7 @@ public:
OPT_INVERT = 0x02, OPT_INVERT = 0x02,
OPT_SQUARE = 0x04 }; OPT_SQUARE = 0x04 };
// Returns a new, not-yet-used "input handle" for addMapping and struct PropHandle { char* name; int handle; };
// setInput. This typically corresponds to one user axis.
int newInput();
// Adds a mapping to between input handle and a particular setting // Adds a mapping to between input handle and a particular setting
// on an output object. The value of output MUST match the type // on an output object. The value of output MUST match the type
@ -45,9 +44,9 @@ public:
// setInput() invokations. // setInput() invokations.
void reset(); void reset();
// Sets the specified input (as returned by newInput) to the // Sets the specified input (as returned by propertyHandle) to the
// specified value. // specified value.
void setInput(int input, float value); void setInput(int propHandle, float value);
/// Calculates and applies the settings received since the last reset(). /// Calculates and applies the settings received since the last reset().
/// dt defaults to a large value used at solve time. /// dt defaults to a large value used at solve time.
@ -73,6 +72,15 @@ public:
float getOutput(int handle); float getOutput(int handle);
float getOutputR(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: private:
struct OutRec { int type; void* object; Vector maps; struct OutRec { int type; void* object; Vector maps;
float oldL, oldR, time; }; float oldL, oldR, time; };
@ -85,6 +93,8 @@ private:
// An unordered list of output settings. // An unordered list of output settings.
Vector _outputs; Vector _outputs;
// control properties
Vector _properties;
}; };
}; // namespace yasim }; // namespace yasim

View file

@ -59,7 +59,7 @@ FGFDM::FGFDM()
// Map /controls/flight/elevator to the approach elevator control. This // Map /controls/flight/elevator to the approach elevator control. This
// should probably be settable, but there are very few aircraft // should probably be settable, but there are very few aircraft
// who trim their approaches using things other than elevator. // 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? // FIXME: read seed from somewhere?
int seed = 0; int seed = 0;
@ -68,12 +68,6 @@ FGFDM::FGFDM()
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++) { for(int i=0; i<_thrusters.size(); i++) {
EngRec* er = (EngRec*)_thrusters.get(i); EngRec* er = (EngRec*)_thrusters.get(i);
delete[] er->prefix; delete[] er->prefix;
@ -508,33 +502,32 @@ void FGFDM::startElement(const char* name, const XMLAttributes &atts)
v[1] = attrf(a, "y"); v[1] = attrf(a, "y");
v[2] = attrf(a, "z"); v[2] = attrf(a, "z");
((Thruster*)_currObj)->setDirection(v); ((Thruster*)_currObj)->setDirection(v);
} else if(eq(name, "control-setting")) { } else if(eq(name, "control-setting")) {
// A cruise or approach control setting // A cruise or approach control setting
const char* axis = a->getValue("axis"); const char* axis = a->getValue("axis");
float value = attrf(a, "value", 0); float value = attrf(a, "value", 0);
if(_cruiseCurr) ControlMap* cm = _airplane.getControlMap();
_airplane.addCruiseControl(parseAxis(axis), value); if(_cruiseCurr)
else _airplane.addCruiseControl(cm->propertyHandle(axis), value);
_airplane.addApproachControl(parseAxis(axis), value); else
} else if(eq(name, "control-input")) { _airplane.addApproachControl(cm->propertyHandle(axis), value);
} else if(eq(name, "control-input")) {
// A mapping of input property to a control ControlMap* cm = _airplane.getControlMap();
int axis = parseAxis(a->getValue("axis")); // A mapping of input property to a control
int control = parseOutput(a->getValue("control")); int axis = cm->propertyHandle(a->getValue("axis"));
int opt = 0; int control = parseOutput(a->getValue("control"));
opt |= a->hasAttribute("split") ? ControlMap::OPT_SPLIT : 0; int opt = 0;
opt |= a->hasAttribute("invert") ? ControlMap::OPT_INVERT : 0; opt |= a->hasAttribute("split") ? ControlMap::OPT_SPLIT : 0;
opt |= a->hasAttribute("square") ? ControlMap::OPT_SQUARE : 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")) {
if(a->hasAttribute("src0")) { cm->addMapping(axis, control, _currObj, opt,
cm->addMapping(axis, control, _currObj, opt,
attrf(a, "src0"), attrf(a, "src1"), attrf(a, "src0"), attrf(a, "src1"),
attrf(a, "dst0"), attrf(a, "dst1")); attrf(a, "dst0"), attrf(a, "dst1"));
} else { } else {
cm->addMapping(axis, control, _currObj, opt); cm->addMapping(axis, control, _currObj, opt);
} }
} else if(eq(name, "control-output")) { } else if(eq(name, "control-output")) {
// A property output for a control on the current object // A property output for a control on the current object
ControlMap* cm = _airplane.getControlMap(); ControlMap* cm = _airplane.getControlMap();
int type = parseOutput(a->getValue("control")); int type = parseOutput(a->getValue("control"));
@ -575,10 +568,10 @@ void FGFDM::getExternalInput(float dt)
ControlMap* cm = _airplane.getControlMap(); ControlMap* cm = _airplane.getControlMap();
cm->reset(); cm->reset();
for(int i=0; i<_axes.size(); i++) { for(int i=0; i < cm->numProperties(); i++) {
AxisRec* a = (AxisRec*)_axes.get(i); ControlMap::PropHandle *p = cm->getProperty(i);
float val = fgGetFloat(a->name, 0); float val = fgGetFloat(p->name, 0);
cm->setInput(a->handle, val); cm->setInput(p->handle, val);
} }
cm->applyControls(dt); cm->applyControls(dt);
@ -1005,26 +998,7 @@ void FGFDM::parsePropeller(XMLAttributes* a)
_currObj = thruster; _currObj = thruster;
} }
// Turns a string axis name into an integer for use by the /// map identifier (string) to int (enum in ControlMap)
// 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;
}
int FGFDM::parseOutput(const char* name) int FGFDM::parseOutput(const char* name)
{ {
if(eq(name, "THROTTLE")) return ControlMap::THROTTLE; if(eq(name, "THROTTLE")) return ControlMap::THROTTLE;

View file

@ -31,7 +31,6 @@ public:
float getVehicleRadius(void) const { return _vehicle_radius; } float getVehicleRadius(void) const { return _vehicle_radius; }
private: private:
struct AxisRec { char* name; int handle; };
struct EngRec { char* prefix; Thruster* eng; }; struct EngRec { char* prefix; Thruster* eng; };
struct WeightRec { char* prop; float size; int handle; }; struct WeightRec { char* prop; float size; int handle; };
struct PropOut { SGPropertyNode* prop; int handle, type; bool left; struct PropOut { SGPropertyNode* prop; int handle, type; bool left;
@ -41,7 +40,6 @@ private:
Rotor* parseRotor(XMLAttributes* a, const char* name); Rotor* parseRotor(XMLAttributes* a, const char* name);
Wing* parseWing(XMLAttributes* a, const char* name, Version * version); Wing* parseWing(XMLAttributes* a, const char* name, Version * version);
int parseAxis(const char* name);
int parseOutput(const char* name); int parseOutput(const char* name);
void parseWeight(XMLAttributes* a); void parseWeight(XMLAttributes* a);
void parseTurbineEngine(XMLAttributes* a); void parseTurbineEngine(XMLAttributes* a);
@ -64,10 +62,6 @@ private:
// Aerodynamic turbulence model // Aerodynamic turbulence model
Turbulence* _turb; Turbulence* _turb;
// The list of "axes" that we expect to find as input. These are
// typically property names.
Vector _axes;
// Settable weights // Settable weights
Vector _weights; Vector _weights;