9#include <simgear/debug/logstream.hxx>
10#include <simgear/math/sg_geodesy.hxx>
11#include <simgear/misc/sg_path.hxx>
12#include <simgear/scene/model/placement.hxx>
13#include <simgear/xml/easyxml.hxx>
18#include "yasim-common.hpp"
20#include "Atmosphere.hpp"
22#include "Airplane.hpp"
24#include "Integrator.hpp"
28#include "Launchbar.hpp"
29#include "FGGround.hpp"
30#include "PropEngine.hpp"
31#include "PistonEngine.hpp"
46 _fdm->getAirplane()->getModel()->setGroundCallback(
new FGGround(
this) );
47 _fdm->getAirplane()->getModel()->getIntegrator()->setInterval(_dt);
58 std::function<
void(
const std::string& from,
const std::string& to)> fn
61 return _fdm->property_associations(fn);
66 Airplane* a = _fdm->getAirplane();
68 float aoa = a->getCruiseAoA() * RAD2DEG;
69 float tail = -1 * a->getTailIncidence() * RAD2DEG;
70 float drag = 1000 * a->getDragCoefficient();
72 SG_LOG(SG_FLIGHT,SG_INFO,
"YASim solution results:");
73 SG_LOG(SG_FLIGHT,SG_INFO,
" Iterations: "<<a->getSolutionIterations());
74 SG_LOG(SG_FLIGHT,SG_INFO,
" Drag Coefficient: "<< drag);
75 SG_LOG(SG_FLIGHT,SG_INFO,
" Lift Ratio: "<<a->getLiftRatio());
76 SG_LOG(SG_FLIGHT,SG_INFO,
" Cruise AoA: "<< aoa);
77 SG_LOG(SG_FLIGHT,SG_INFO,
" Tail Incidence: "<< tail);
78 SG_LOG(SG_FLIGHT,SG_INFO,
"Approach Elevator: "<<a->getApproachElevator());
82 a->getModel()->getBody()->getCG(cg);
83 snprintf(buf, 256,
" CG: %.3f, %.3f, %.3f", cg[0], cg[1], cg[2]);
84 SG_LOG(SG_FLIGHT, SG_INFO, buf);
86 if(a->getFailureMsg()) {
87 SG_LOG(SG_FLIGHT, SG_POPUP, std::string(
"YASim flight dynamics problem:") + a->getFailureMsg()+
"\nThe aircraft may not fly correctly");
103 for(
int i=0;
i<_fdm->getAirplane()->getModel()->numThrusters();
i++) {
104 snprintf(buf, 256,
"/engines/engine[%d]/fuel-flow-gph",
i);
106 snprintf(buf, 256,
"/engines/engine[%d]/rpm",
i);
108 snprintf(buf, 256,
"/engines/engine[%d]/mp-osi",
i);
110 snprintf(buf, 256,
"/engines/engine[%d]/egt-degf",
i);
112 snprintf(buf, 256,
"/engines/engine[%d]/oil-temperature-degf",
i);
117YASim::GearProps::GearProps(SGPropertyNode_ptr gear_root) :
118 has_brake(gear_root->getNode(
"has-brake", true)),
119 wow(gear_root->getNode(
"wow", true)),
120 compression_norm(gear_root->getNode(
"compression-norm", true)),
121 compression_m(gear_root->getNode(
"compression-m", true)),
122 caster_angle_deg(gear_root->getNode(
"caster-angle-deg", true)),
123 rollspeed_ms(gear_root->getNode(
"rollspeed-ms", true)),
124 ground_is_solid(gear_root->getNode(
"ground-is-solid", true)),
125 ground_friction_factor(gear_root->getNode(
"ground-friction-factor", true))
131 Airplane* airplane = _fdm->getAirplane();
132 Model* model = airplane->getModel();
134 _crashed =
fgGetNode(
"/sim/crashed",
true);
135 _pressure_inhg =
fgGetNode(
"/environment/pressure-inhg",
true);
136 _temp_degc =
fgGetNode(
"/environment/temperature-degc",
true);
137 _density_slugft3 =
fgGetNode(
"/environment/density-slugft3",
true);
138 _gear_agl_m =
fgGetNode(
"/position/gear-agl-m",
true);
139 _gear_agl_ft =
fgGetNode(
"/position/gear-agl-ft",
true);
140 _pilot_g =
fgGetNode(
"/accelerations/pilot-g",
true);
141 _speed_setprop =
fgGetNode(
"/sim/presets/speed-set",
true);
146 model->setCrashed(
false);
147 _crashed->setBoolValue(
false);
150 string speed_set = _speed_setprop->getStringValue();
151 if ((speed_set ==
"") || (speed_set ==
"UVW"))
153 else if (speed_set ==
"NED")
155 else if (speed_set ==
"knots")
157 else if (speed_set ==
"mach")
161 SG_LOG(SG_FLIGHT, SG_ALERT,
"Unknown speed type " << speed_set);
170 }
catch (
const sg_exception &e) {
171 SG_LOG(SG_FLIGHT, SG_ALERT,
172 "Error reading YASim FDM: '" << f <<
"'" << std::endl
173 << e.getFormattedMessage());
183 if (model->getLaunchbar())
185 _catapult_launch_cmd =
fgGetNode(
"/controls/gear/catapult-launch-cmd",
true);
186 _launchbar_position_norm =
fgGetNode(
"/gear/launchbar/position-norm",
true);
187 _launchbar_holdback_pos_norm =
fgGetNode(
"/gear/launchbar/holdback-position-norm",
true);
188 _launchbar_state =
fgGetNode(
"/gear/launchbar/state",
true);
189 _launchbar_strop =
fgGetNode(
"/gear/launchbar/strop",
true);
191 if (airplane->getHook())
193 _tailhook_position_norm =
fgGetNode(
"/gear/tailhook/position-norm", 0,
true);
197 for(
int i=0;
i<airplane->numGear();
i++) {
198 Gear* g = airplane->getGear(
i);
199 SGPropertyNode * node =
fgGetNode(
"gear/gear",
i,
true);
202 node->setDoubleValue(
"xoffset-in", pos[0] * M2FT * 12);
203 node->setDoubleValue(
"yoffset-in", pos[1] * M2FT * 12);
204 node->setDoubleValue(
"zoffset-in", pos[2] * M2FT * 12);
206 node->setDoubleValue(
"xoffset-m", pos[0]);
207 node->setDoubleValue(
"yoffset-m", pos[1]);
208 node->setDoubleValue(
"zoffset-m", pos[2]);
210 node->setDoubleValue(
"wheel-radius-m", g->getWheelRadius());
211 node->setDoubleValue(
"tyre-radius-m", g->getTyreRadius());
213 node->setDoubleValue(
"spring", g->getSpring());
214 node->setDoubleValue(
"damping", g->getDamping());
216 _gearProps.push_back(GearProps(node));
221 bool respect_external_gear_state =
fgGetBool(
"/fdm/yasim/respect-external-gear-state");
224 bool gear_state =
fgGetBool(
"/controls/gear/gear-down");
225 fgSetBool(
"/controls/gear/gear-down",
false);
226 float minGearZ = 1e18;
227 for(
int i=0;
i<airplane->numGear();
i++) {
228 Gear* g = airplane->getGear(
i);
231 pos[2] -= (g->getWheelRadius() + g->getTyreRadius());
232 if(pos[2] < minGearZ)
237 fgSetBool(
"/controls/gear/gear-down", respect_external_gear_state ? gear_state :
true);
239 else if (! respect_external_gear_state)
242 fgSetBool(
"/controls/gear/gear-down",
false);
250 _fdm->getExternalInput();
251 _fdm->getAirplane()->initEngines();
264 if(_crashed->getBoolValue() || _fdm->getAirplane()->getModel()->isCrashed()) {
265 if(!_crashed->getBoolValue())
266 _crashed->setBoolValue(
true);
267 _fdm->getAirplane()->getModel()->setCrashed(
false);
281 sgGeodToCart(lat, lon, alt, xyz);
283 float vr = _fdm->getVehicleRadius();
284 vr += 2.0*FT2M*dt*Math::mag3(v);
289 = (FGGround*)_fdm->getAirplane()->getModel()->getGroundCallback();
292 for(
i=0;
i<iterations;
i++) {
293 gr->setTimeOffset(_simTime +
i*_dt);
301 gr->setTimeOffset(_simTime);
304void YASim::copyToYASim(
bool copyState)
320 float pressure = _pressure_inhg->getFloatValue() * INHG2PA;
321 float temp = _temp_degc->getFloatValue() + 273.15;
322 float dens = _density_slugft3->getFloatValue() *
323 SLUG2KG * M2FT*M2FT*M2FT;
325 atmo.setDensity(dens);
326 atmo.setTemperature(temp);
327 atmo.setPressure(pressure);
330 Model* model = _fdm->getAirplane()->getModel();
333 Glue::xyz2nedMat(lat, lon, xyz2ned);
336 sgGeodToCart(lat, lon, alt, s.pos);
339 double * dp = &model->getState()->pos[0];
340 dp[0] = s.pos[0]; dp[1] = s.pos[1]; dp[2] = s.pos[2];
344 Glue::euler2orient(roll, pitch, hdg, s.orient);
345 Math::mmul33(s.orient, xyz2ned, s.orient);
348 float v[3] {0, 0, 0};
349 bool needCopy =
false;
350 switch (_speed_set) {
360 Math::tmul33(s.orient, v, v);
366 Math::tmul33(s.orient, v, v);
373 Math::tmul33(s.orient, v, v);
386 if(copyState || needCopy)
389 Math::tmul33(xyz2ned, wind, wind);
390 model->setWind(wind);
391 model->setAtmosphere(atmo);
395 _fdm->getAirplane()->getModel()->updateGround(&s);
397 Launchbar* l = model->getLaunchbar();
399 l->setLaunchCmd(0.0 < _catapult_launch_cmd->getFloatValue());
448void YASim::copyFromYASim()
450 Airplane* airplane = _fdm->getAirplane();
451 Model* model = airplane->getModel();
452 yasim::State* s = model->getState();
455 double lat, lon, alt;
456 sgCartToGeod(s->pos, &lat, &lon, &alt);
463 _gear_agl_m->setFloatValue(model->getAGL());
464 _gear_agl_ft->setFloatValue(model->getAGL()*M2FT);
471 Glue::xyz2nedMat(lat, lon, xyz2ned);
475 Math::vmul33(xyz2ned, s->v, v);
478 M2FT*v[1]*M2FT*v[1]));
487 Math::vmul33(s->orient, s->v, v);
495 Math::tmul33(xyz2ned, wind, wind);
496 Math::sub3(s->v, wind, v);
497 Math::vmul33(s->orient, v, v);
500 float P = _pressure_inhg->getFloatValue() * INHG2PA;
501 float T = _temp_degc->getFloatValue() + 273.15;
502 float D = _density_slugft3->getFloatValue()
503 *SLUG2KG * M2FT*M2FT*M2FT;
509 Math::vmul33(xyz2ned, s->acc, v);
512 Math::vmul33(s->orient, s->acc, v);
516 _fdm->getAirplane()->getPilotAccel(v);
522 _pilot_g->setFloatValue(-v[2]/9.8);
526 Math::mul3(1.0/9.8, v, v);
531 Glue::calcAlphaBeta(s, wind, &alpha, &beta);
536 Math::trans33(xyz2ned, tmp);
537 Math::mmul33(s->orient, tmp, tmp);
538 float roll, pitch, hdg;
539 Glue::orient2euler(tmp, &roll, &pitch, &hdg);
541 if(hdg < 0.0) hdg += PI2;
545 Math::vmul33(s->orient, s->rot, v);
548 Glue::calcEulerRates(s, &roll, &pitch, &hdg);
552 for(
int i=0;
i<airplane->numGear();
i++) {
553 Gear*
g = airplane->getGear(
i);
554 GearProps& gearProps = _gearProps[
i];
555 gearProps.has_brake->setBoolValue(
557 gearProps.wow->setBoolValue(
558 g->getCompressFraction() != 0);
559 gearProps.compression_norm->setFloatValue(
560 g->getCompressFraction());
561 gearProps.compression_m->setFloatValue(
562 g->getCompressDist());
563 gearProps.caster_angle_deg->setFloatValue(
564 g->getCasterAngle() * RAD2DEG);
565 gearProps.rollspeed_ms->setFloatValue(
567 gearProps.ground_is_solid->setBoolValue(
568 g->getGroundIsSolid()!=0);
569 gearProps.ground_friction_factor->setFloatValue(
570 g->getGroundFrictionFactor());
573 Hook* h = airplane->getHook();
575 _tailhook_position_norm->setFloatValue(h->getCompressFraction());
578 Launchbar* l = airplane->getLaunchbar();
580 _launchbar_position_norm->setFloatValue(l->getCompressFraction());
581 _launchbar_holdback_pos_norm->setFloatValue(l->getHoldbackCompressFraction());
582 _launchbar_state->setStringValue(l->getState());
583 _launchbar_strop->setBoolValue(l->getStrop());
597 _fdm->getExternalInput(1000);
606SGSubsystemMgr::Registrant<YASim> registrantYASim;
void _set_Altitude(double altitude)
void _set_Mach_number(double m)
double get_V_east_airmass() const
void _set_Geodetic_Position(double lat, double lon)
double get_V_north_airmass() const
double get_Longitude() const
double get_V_east() const
double get_Latitude() const
void _set_Velocities_Local(double north, double east, double down)
void _set_Accels_Pilot_Body(double x, double y, double z)
double get_V_down() const
void _set_Alpha(double a)
void _set_Velocities_Body(double u, double v, double w)
void _set_Accels_Body(double u, double v, double w)
double get_V_calibrated_kts() const
void set_inited(bool value)
void _set_Climb_Rate(double rate)
void bind() override
Bind getters and setters to properties.
void _set_Accels_Local(double north, double east, double down)
void common_init()
Initialize the state of the FDM.
void _set_Accels_CG_Body_N(double x, double y, double z)
void _set_Runway_altitude(double alt)
void _set_Velocities_Ground(double north, double east, double down)
double get_Mach_number() const
void _set_Omega_Body(double p, double q, double r)
bool prepare_ground_cache_m(double startSimTime, double endSimTime, const double pt[3], double rad)
double get_Runway_altitude() const
void _set_Accels_CG_Body(double x, double y, double z)
void _set_V_calibrated_kts(double kts)
double get_V_north() const
double get_Altitude() const
void _set_V_rel_wind(double vt)
void _set_Altitude_AGL(double agl)
void _set_Euler_Rates(double phi, double theta, double psi)
void _set_V_equiv_kts(double kts)
int _calc_multiloop(double dt)
void _set_V_ground_speed(double v)
double get_groundlevel_m(double lat, double lon, double alt)
void _set_Euler_Angles(double phi, double theta, double psi)
double get_V_down_airmass() const
void property_associations(std::function< void(const std::string &from, const std::string &to)> fn) override
void reinit() override
Reinit the FDM.
void update(double dt) override
void fgUntieIfDefined(const std::string &name)
@brfief variant of the above which doesn't warn if the property does not exist
std::string fgGetString(const char *name, const char *defaultValue)
Get a string value for a property.
bool fgGetBool(char const *name, bool def)
Get a bool value for a property.
bool fgSetBool(char const *name, bool val)
Set a bool value for a property.
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.