9#include "PropEngine.hpp"
10#include "PistonEngine.hpp"
11#include "TurbineEngine.hpp"
14#include "Launchbar.hpp"
18#include "Propeller.hpp"
21#include "ControlMap.hpp"
60 "ROTORENGINEMAXRELTORQUE",
71ControlMap::~ControlMap()
73 for(
int i=0;
i<_inputs.size();
i++) {
74 Vector* v = (Vector*)_inputs.get(
i);
75 for(
int j=0; j<v->size(); j++)
76 delete (MapRec*)v->get(j);
80 for(
int i=0;
i<_outputs.size();
i++)
81 delete (OutRec*)_outputs.get(
i);
83 for(
int i=0;
i<_properties.size();
i++) {
84 PropHandle*
p = (PropHandle*)_properties.get(
i);
96void ControlMap::addMapping(
const char* inputProp, ControlType control, ObjectID
id,
int options,
float src0,
float src1,
float dst0,
float dst1)
98 OutRec* out = getOutRec(
id, control);
101 MapRec* map =
new MapRec();
103 map->id = out->maps.add(map);
106 map->src1 = map->dst1 = rangeMax(control);
107 map->src0 = map->dst0 = rangeMin(control);
110 Vector* maps = (Vector*)_inputs.get(getInputPropertyHandle(inputProp));
119ControlMap::OutRec* ControlMap::getOutRec(ObjectID
id, ControlType control)
121 OutRec* out {
nullptr};
122 for(
int i = 0;
i < _outputs.size();
i++) {
123 OutRec* o = (OutRec*)_outputs.get(
i);
124 if(o->oid.object ==
id.object && o->oid.subObj ==
id.subObj
125 && o->control == control)
135 out->control = control;
137 out->id = _outputs.add(out);
142void ControlMap::reset()
145 for(
int i = 0;
i < _outputs.size();
i++) {
146 OutRec* o = (OutRec*)_outputs.get(
i);
147 for(
int j = 0; j < o->maps.size(); j++) {
148 ((MapRec*)(o->maps.get(j)))->val = 0;
153void ControlMap::setInput(
int propHandle,
float val)
155 Vector* maps = (Vector*)_inputs.get(propHandle);
156 for(
int i = 0;
i < maps->size();
i++) {
157 MapRec* m = (MapRec*)maps->get(
i);
161 val2 = Math::clamp(val2, m->src0, m->src1);
162 val2 = (val2 - m->src0) / (m->src1 - m->src0);
163 m->val = m->dst0 + val2 * (m->dst1 - m->dst0);
167int ControlMap::getOutputHandle(ObjectID
id, ControlType control)
169 return getOutRec(
id, control)->id;
172void ControlMap::setTransitionTime(
int handle,
float time)
174 ((OutRec*)_outputs.get(handle))->transitionTime = time;
177float ControlMap::getOutput(
int handle)
179 return ((OutRec*)_outputs.get(handle))->oldValueLeft;
182float ControlMap::getOutputR(
int handle)
184 return ((OutRec*)_outputs.get(handle))->oldValueRight;
187void ControlMap::applyControls(
float dt)
189 for(
int outrec=0; outrec<_outputs.size(); outrec++)
191 OutRec* o = (OutRec*)_outputs.get(outrec);
195 float lval = 0, rval = 0;
196 for(
int i = 0;
i < o->maps.size();
i++) {
197 MapRec* m = (MapRec*)o->maps.get(
i);
200 if(m->opt & OPT_SQUARE) { val = val * Math::abs(val); }
201 if(m->opt & OPT_INVERT) { val = -val; }
203 if(m->opt & OPT_SPLIT) { rval -= val; }
204 else { rval += val; }
209 if(o->transitionTime > 0) {
210 float dl = lval - o->oldValueLeft;
211 float dr = rval - o->oldValueRight;
212 float adl = Math::abs(dl);
213 float adr = Math::abs(dr);
215 float maxDelta = (dt/o->transitionTime) * (rangeMax(o->control) - rangeMin(o->control));
217 dl = dl*maxDelta/adl;
218 lval = o->oldValueLeft + dl;
221 dr = dr*maxDelta/adr;
222 rval = o->oldValueRight + dr;
226 o->oldValueLeft = lval;
227 o->oldValueRight = rval;
229 void* obj = o->oid.object;
232 ((Thruster*)obj)->setThrottle(lval);
235 ((Thruster*)obj)->setMixture(lval);
238 ((TurbineEngine*)((PropEngine*)obj)->getEngine())->setCondLever(lval);
241 ((Thruster*)obj)->setStarter(lval != 0.0);
244 ((PropEngine*)obj)->setMagnetos((
int)lval);
247 ((PropEngine*)obj)->setAdvance(lval);
250 ((PropEngine*)obj)->setPropPitch(lval);
253 ((PropEngine*)obj)->setPropFeather((
int)lval);
256 ((Jet*)obj)->setReheat(lval);
259 ((Jet*)obj)->setRotation(lval);
262 ((Gear*)obj)->setBrake(lval);
265 ((Gear*)obj)->setRotation(lval);
268 ((Gear*)obj)->setExtension(lval);
271 ((Hook*)obj)->setExtension(lval);
274 ((Launchbar*)obj)->setExtension(lval);
277 ((Launchbar*)obj)->setAcceleration(lval);
280 ((Gear*)obj)->setCastering(lval != 0);
283 ((Wing*)obj)->setFlapPos(WING_SLAT,lval);
286 ((Wing*)obj)->setFlapPos(WING_FLAP0, lval, rval);
288 case FLAP0EFFECTIVENESS:
289 ((Wing*)obj)->setFlapEffectiveness(WING_FLAP0,lval);
292 ((Wing*)obj)->setFlapPos(WING_FLAP1,lval, rval);
294 case FLAP1EFFECTIVENESS:
295 ((Wing*)obj)->setFlapEffectiveness(WING_FLAP1,lval);
298 ((Wing*)obj)->setFlapPos(WING_SPOILER, lval, rval);
301 ((Rotor*)obj)->setCollective(lval);
304 ((Rotor*)obj)->setCyclicail(lval,rval);
307 ((Rotor*)obj)->setCyclicele(lval,rval);
310 ((Rotor*)obj)->setTiltPitch(lval);
313 ((Rotor*)obj)->setTiltYaw(lval);
316 ((Rotor*)obj)->setTiltRoll(lval);
319 ((Rotor*)obj)->setRotorBalance(lval);
322 ((Rotorgear*)obj)->setRotorBrake(lval);
324 case ROTORGEARENGINEON:
325 ((Rotorgear*)obj)->setEngineOn((
int)lval);
327 case ROTORENGINEMAXRELTORQUE:
328 ((Rotorgear*)obj)->setRotorEngineMaxRelTorque(lval);
331 ((Rotorgear*)obj)->setRotorRelTarget(lval);
334 ((Jet*)obj)->setReverse(lval != 0);
337 ((PistonEngine*)((Thruster*)obj)->getEngine())->setBoost(lval);
340 ((PistonEngine*)((Thruster*)obj)->getEngine())->setWastegate(lval);
343 ((Hitch*)obj)->setWinchRelSpeed(lval);
346 ((Hitch*)obj)->setOpen(lval!=0);
349 ((Hitch*)obj)->setWinchPositionAuto(lval!=0);
352 ((Hitch*)obj)->findBestAIObject(lval!=0);
357 ((Wing*)obj)->setIncidence(lval);
363float ControlMap::rangeMin(ControlType control)
367 case INCIDENCE:
return INCIDENCE_MIN;
368 case FLAP0:
return -1;
369 case FLAP1:
return -1;
370 case STEER:
return -1;
371 case CYCLICELE:
return -1;
372 case CYCLICAIL:
return -1;
373 case COLLECTIVE:
return -1;
374 case WINCHRELSPEED:
return -1;
375 case MAGNETOS:
return 0;
376 case FLAP0EFFECTIVENESS:
return 1;
377 case FLAP1EFFECTIVENESS:
return 1;
382float ControlMap::rangeMax(ControlType control)
386 case INCIDENCE:
return INCIDENCE_MAX;
387 case FLAP0:
return 1;
388 case FLAP1:
return 1;
389 case STEER:
return 1;
390 case MAGNETOS:
return 3;
391 case FLAP0EFFECTIVENESS:
return 10;
392 case FLAP1EFFECTIVENESS:
return 10;
398int ControlMap::getInputPropertyHandle(
const char*
name)
401 for(
int i=0;
i < _properties.size();
i++) {
402 PropHandle*
p = (PropHandle*)_properties.get(
i);
408 PropHandle*
p =
new PropHandle();
413 Vector* v =
new Vector();
414 p->handle = _inputs.add(v);
420ControlMap::ControlType ControlMap::getControlByName(
const std::string&
name)
424 SG_LOG(SG_FLIGHT,SG_ALERT,
"Unrecognized control type '" <<
name
425 <<
"' in YASim aircraft description.");
428 return static_cast<ControlType
>(std::distance(
ControlNames.begin(), it));
431std::string ControlMap::getControlName(ControlType c)
436ControlMap::ControlType ControlMap::parseControl(
const char*
name)
439 return getControlByName(n);
442ControlMap::ObjectID ControlMap::getObjectID(
void*
object,
int subObj)
444 assert(
object !=
nullptr);
452ControlMap::PropHandle* ControlMap::getProperty(
const int i) {
453 assert((
i >= 0) && (
i < _properties.size()));
454 return ((PropHandle*)_properties.get(
i));
bool options(int, char **)
static const std::vector< std::string > ControlNames
keep this list in sync with the enum ControlType in ControlMap.hpp !
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.