7#include "Atmosphere.hpp"
10#include "RigidBody.hpp"
11#include "Integrator.hpp"
12#include "Propeller.hpp"
13#include "PistonEngine.hpp"
16#include "Launchbar.hpp"
19#include "Rotorpart.hpp"
28void printState(State* s)
31 Math::vmul33(tmp.orient, tmp.v, tmp.v);
32 Math::vmul33(tmp.orient, tmp.acc, tmp.acc);
33 Math::vmul33(tmp.orient, tmp.rot, tmp.rot);
34 Math::vmul33(tmp.orient, tmp.racc, tmp.racc);
36 printf(
"\nNEW STATE (LOCAL COORDS)\n");
37 printf(
"pos: %10.2f %10.2f %10.2f\n", tmp.pos[0], tmp.pos[1], tmp.pos[2]);
41 if(
i != 0) printf(
" ");
42 printf(
"%6.2f %6.2f %6.2f\n",
43 tmp.orient[3*
i+0], tmp.orient[3*
i+1], tmp.orient[3*
i+2]);
45 printf(
"v: %6.2f %6.2f %6.2f\n", tmp.v[0], tmp.v[1], tmp.v[2]);
46 printf(
"acc: %6.2f %6.2f %6.2f\n", tmp.acc[0], tmp.acc[1], tmp.acc[2]);
47 printf(
"rot: %6.2f %6.2f %6.2f\n", tmp.rot[0], tmp.rot[1], tmp.rot[2]);
48 printf(
"rac: %6.2f %6.2f %6.2f\n", tmp.racc[0], tmp.racc[1], tmp.racc[2]);
52Model::Model(Airplane* parent) : _parent(parent)
54 _integrator.setBody(&_body);
55 _integrator.setEnvironment(
this);
57 _integrator.setInterval(1.0f/30.0f);
59 _ground_cb =
new Ground();
61 _modelN =
fgGetNode(
"/fdm/yasim/forces",
true);
62 _fAeroXN = _modelN->getNode(
"f-x-drag",
true);
63 _fAeroYN = _modelN->getNode(
"f-y-side",
true);
64 _fAeroZN = _modelN->getNode(
"f-z-lift",
true);
65 _fGravXN = _modelN->getNode(
"gravity-x",
true);
66 _fGravYN = _modelN->getNode(
"gravity-y",
true);
67 _fGravZN = _modelN->getNode(
"gravity-z",
true);
68 _fSumXN = _modelN->getNode(
"f-sum-x",
true);
69 _fSumYN = _modelN->getNode(
"f-sum-y",
true);
70 _fSumZN = _modelN->getNode(
"f-sum-z",
true);
72 _gefxN =
fgGetNode(
"/fdm/yasim/debug/ground-effect/ge-f-x",
true);
73 _gefyN =
fgGetNode(
"/fdm/yasim/debug/ground-effect/ge-f-y",
true);
74 _gefzN =
fgGetNode(
"/fdm/yasim/debug/ground-effect/ge-f-z",
true);
75 _wgdistN =
fgGetNode(
"/fdm/yasim/debug/ground-effect/wing-gnd-dist",
true);
84 for(
int i=0;
i<_hitches.size();
i++)
85 delete (Hitch*)_hitches.get(
i);
89void Model::getThrust(
float* out)
const
92 out[0] = out[1] = out[2] = 0;
93 for(
int i=0;
i<_thrusters.size();
i++) {
94 Thruster* t = (Thruster*)_thrusters.get(
i);
96 Math::add3(tmp, out, out);
100void Model::initIteration()
103 Math::zero3(_torque);
108 _s->planeGlobalToLocal(_global_ground, lground);
109 float alt = Math::abs(lground[3]);
111 for(
int i=0;
i<_thrusters.size();
i++) {
112 Thruster* t = (Thruster*)_thrusters.get(
i);
116 localWind(pos, _s, v, alt);
119 t->setAtmosphere(_atmo);
120 t->integrate(_integrator.getInterval());
123 Math::add3(v, _torque, _torque);
126 Math::add3(v, _gyro, _gyro);
132 Math::mul3(_integrator.getInterval(), _wind, toff);
136 for(
int i=0;
i<_gears.size();
i++) {
137 Gear*
g = (Gear*)_gears.get(
i);
138 g->integrate(_integrator.getInterval());
141 for(
int i=0;
i<_hitches.size();
i++) {
142 Hitch* h = (Hitch*)_hitches.get(
i);
143 h->integrate(_integrator.getInterval());
155void Model::initRotorIteration()
157 float dt = _integrator.getInterval();
159 if (!_rotorgear.isInUse())
return;
160 Math::vmul33(_s->orient, _s->rot, lrot);
161 Math::mul3(dt,lrot,lrot);
162 _rotorgear.initRotorIteration(lrot,dt);
168 initRotorIteration();
170 _integrator.calcNewInterval();
173void Model::setState(State* s)
175 _integrator.setState(s);
176 _s = _integrator.getState();
180void Model::setGroundCallback(Ground* ground_cb)
183 _ground_cb = ground_cb;
186void Model::setGroundEffect(
const float* pos,
float span,
float mul)
188 Math::set3(pos, _geRefPoint);
193void Model::updateGround(State* s)
197 _ground_cb->getGroundPlane(s->pos, _global_ground, dummy, body);
201 for(
i=0;
i<_gears.size();
i++) {
202 Gear*
g = (Gear*)_gears.get(
i);
211 s->posLocalToGlobal(pos, pt);
214 double global_ground[4];
216 const simgear::BVHMaterial* material;
217 _ground_cb->getGroundPlane(pt, global_ground, global_vel, &material, body);
218 g->setGlobalGround(global_ground, global_vel, pt[0], pt[1], material, body);
221 for(
i=0;
i<_hitches.size();
i++) {
222 Hitch* h = (Hitch*)_hitches.get(
i);
231 s->posLocalToGlobal(pos, pt);
234 double global_ground[4];
236 _ground_cb->getGroundPlane(pt, global_ground, global_vel, body);
237 h->setGlobalGround(global_ground, global_vel);
240 for(
i=0;
i<_rotorgear.getRotors()->size();
i++) {
241 Rotor* r = (Rotor*)_rotorgear.getRotors()->get(
i);
242 r->findGroundEffectAltitude(_ground_cb,s);
248 _hook->getTipGlobalPosition(s, pt);
249 double global_ground[4];
250 _ground_cb->getGroundPlane(pt, global_ground, dummy, body);
251 _hook->setGlobalGround(global_ground);
257 _launchbar->getTipGlobalPosition(s, pt);
258 double global_ground[4];
259 _ground_cb->getGroundPlane(pt, global_ground, dummy, body);
260 _launchbar->setGlobalGround(global_ground);
264void Model::calcForces(State* s)
271 _body.setGyro(_gyro);
272 _body.setTorque(_torque);
274 for(
i=0;
i<_thrusters.size();
i++) {
275 Thruster* t = (Thruster*)_thrusters.get(
i);
276 float thrust[3], pos[3];
277 t->getThrust(thrust);
279 _body.addForce(pos, thrust);
287 s->planeGlobalToLocal(_global_ground, ground);
288 float alt = Math::abs(ground[3]);
292 Glue::geodUp(s->pos, grav);
293 Math::mul3(-9.8f * _body.getTotalMass(), grav, grav);
294 Math::vmul33(s->orient, grav, grav);
295 _body.addForce(grav);
299 float faero[3] {0,0,0};
300 if (!_surfaces.empty()) {
302 float vs[3] {0,0,0}, pos[3] {0,0,0};
303 localWind(pos, s, vs, alt);
304 float mach = _atmo.machFromSpeed(Math::mag3(vs));
305 for (
i=0;
i<_surfaces.size();
i++) {
306 Surface* sf = (Surface*)_surfaces.get(
i);
308 sf->getPosition(pos);
309 localWind(pos, s, vs, alt);
311 float force[3], torque[3];
312 sf->calcForce(vs, _atmo.getDensity(), mach, force, torque);
313 Math::add3(faero, force, faero);
315 _body.addForce(pos, force);
316 _body.addTorque(torque);
319 for (j=0; j<_rotorgear.getRotors()->size();j++)
321 Rotor* r = (Rotor *)_rotorgear.getRotors()->get(j);
324 localWind(pos, s, vs, alt);
325 r->calcLiftFactor(vs, _atmo.getDensity(), s);
329 for(
i=0;
i<r->_rotorparts.size();
i++) {
330 float torque_scalar=0;
331 Rotorpart* rp = (Rotorpart*)r->_rotorparts.get(
i);
335 rp->getPosition(pos);
336 localWind(pos, s, vs, alt,
true);
338 float force[3], torque[3];
339 rp->calcForce(vs, _atmo.getDensity(), force, torque, &torque_scalar);
341 rp->getPositionForceAttac(pos);
343 _body.addForce(pos, force);
344 _body.addTorque(torque);
348 if (_rotorgear.isInUse())
351 _rotorgear.calcForces(torque);
352 _body.addTorque(torque);
358 if ((_wingSpan != 0) && (_groundEffect != 0 ))
361 float dist = ground[3] - Math::dot3(ground, _geRefPoint);
363 float geForce[3] = {0, 0, 0};
364 if(dist > 0 && dist < _wingSpan) {
365 fz = Math::dot3(faero, ground);
366 fz *= (_wingSpan - dist) / _wingSpan;
368 Math::mul3(fz, ground, geForce);
369 _body.addForce(geForce);
372 _gefxN->setFloatValue(geForce[0]);
373 _gefyN->setFloatValue(geForce[1]);
374 _gefzN->setFloatValue(geForce[2]);
375 _wgdistN->setFloatValue(dist);
379 _fAeroXN->setFloatValue(faero[0]);
380 _fAeroYN->setFloatValue(faero[1]);
381 _fAeroZN->setFloatValue(faero[2]);
382 _fGravXN->setFloatValue(grav[0]);
383 _fGravYN->setFloatValue(grav[1]);
384 _fGravZN->setFloatValue(grav[2]);
385 _fSumXN->setFloatValue(faero[0]+grav[0]);
386 _fSumYN->setFloatValue(faero[1]+grav[1]);
387 _fSumZN->setFloatValue(faero[2]+grav[2]);
390 float lrot[3], lv[3];
391 Math::vmul33(s->orient, s->rot, lrot);
392 Math::vmul33(s->orient, s->v, lv);
395 for(
i=0;
i<_gears.size();
i++) {
396 float force[3], contact[3];
397 Gear*
g = (Gear*)_gears.get(
i);
399 g->calcForce(_ground_cb, &_body, s, lv, lrot);
400 g->getForce(force, contact);
401 _body.addForce(contact, force);
406 _hook->calcForce(_ground_cb, &_body, s, lv, lrot);
407 float force[3], contact[3];
408 _hook->getForce(force, contact);
409 _body.addForce(contact, force);
414 _launchbar->calcForce(_ground_cb, &_body, s, lv, lrot);
415 float forcelb[3], contactlb[3], forcehb[3], contacthb[3];
416 _launchbar->getForce(forcelb, contactlb, forcehb, contacthb);
417 _body.addForce(contactlb, forcelb);
418 _body.addForce(contacthb, forcehb);
422 for(
i=0;
i<_hitches.size();
i++) {
423 float force[3], contact[3];
424 Hitch* h = (Hitch*)_hitches.get(
i);
425 h->calcForce(_ground_cb,&_body, s);
426 h->getForce(force, contact);
427 _body.addForce(contact, force);
430void Model::newState(State* s)
437 for(
i=0;
i<_gears.size();
i++) {
438 Gear*
g = (Gear*)_gears.get(
i);
440 if (!
g->getSubmergable())
447 double global_ground[4];
448 g->getGlobalGround(global_ground);
450 s->planeGlobalToLocal(global_ground, ground);
451 float dist = ground[3] - Math::dot3(pos, ground);
457 g->updateStuckPoint(s);
466void Model::localWind(
const float* pos,
const yasim::State* s,
float* out,
float alt,
bool is_rotor)
468 float tmp[3], lwind[3], lrot[3], lv[3];
473 double gpos[3];
float up[3];
474 Math::tmul33(s->orient, pos, tmp);
475 for(
int i=0;
i<3;
i++) {
476 gpos[
i] = s->pos[
i] + tmp[
i];
478 Glue::geodUp(gpos, up);
479 _turb->getTurbulence(gpos, alt, up, lwind);
480 Math::add3(_wind, lwind, lwind);
482 Math::set3(_wind, lwind);
486 Math::vmul33(s->orient, lwind, lwind);
487 Math::vmul33(s->orient, s->rot, lrot);
488 Math::vmul33(s->orient, s->v, lv);
490 _body.pointVelocity(pos, lrot, out);
491 Math::mul3(-1, out, out);
492 Math::add3(lwind, out, out);
493 Math::sub3(out, lv, out);
496 if (_rotorgear.isInUse()&&!is_rotor)
498 _rotorgear.getDownWash(pos,lv,tmp);
499 Math::add3(out,tmp, out);
503bool Model::isVersion(YASIM_VERSION version)
const
505 return _parent->isVersion(version);
508bool Model::isVersionOrNewer(YASIM_VERSION version)
const
510 return _parent->isVersionOrNewer(version);
State
Models an aircraft axis for purposes of trimming.
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.