12#include <simgear/compiler.h>
13#include <simgear/sg_inlines.h>
18#include <simgear/constants.h>
19#include <simgear/debug/logstream.hxx>
20#include <simgear/math/sg_geodesy.hxx>
21#include <simgear/misc/sg_path.hxx>
22#include <simgear/structure/commands.hxx>
23#include <simgear/bvh/BVHMaterial.hxx>
83 sgCartToGeod( pt, &lat, &lon, &alt);
84 return alt * SG_METER_TO_FEET;
91 double contact[3], normal[3], vel[3], angularVel[3];
92 double agl = mInterface->get_agl_ft(t, l, SG_METER_TO_FEET*2, contact,
93 normal, vel, angularVel);
112 *
this << (0.0/9.0) << 0.0;
113 *
this << (1.0/9.0) << 3.0;
114 *
this << (4.0/9.0) << 4.0;
115 *
this << (9.0/9.0) << 7.0;
120std::map<std::string,int> FGJSBsim::TURBULENCE_TYPE_NAMES;
128 if( TURBULENCE_TYPE_NAMES.empty() ) {
129 TURBULENCE_TYPE_NAMES[
"ttNone"] = FGWinds::ttNone;
130 TURBULENCE_TYPE_NAMES[
"ttStandard"] = FGWinds::ttStandard;
131 TURBULENCE_TYPE_NAMES[
"ttCulp"] = FGWinds::ttCulp;
132 TURBULENCE_TYPE_NAMES[
"ttMilspec"] = FGWinds::ttMilspec;
133 TURBULENCE_TYPE_NAMES[
"ttTustin"] = FGWinds::ttTustin;
140 if ((sglog().get_log_classes() & SG_FLIGHT) != 0) {
144 switch (sglog().get_log_priority()) {
168 fdmex =
new FGFDMExec( PropertyManager );
171 Atmosphere = fdmex->GetAtmosphere();
172 Winds = fdmex->GetWinds();
173 FCS = fdmex->GetFCS();
174 MassBalance = fdmex->GetMassBalance();
175 Propulsion = fdmex->GetPropulsion();
176 Aircraft = fdmex->GetAircraft();
177 Propagate = fdmex->GetPropagate();
178 Auxiliary = fdmex->GetAuxiliary();
179 Inertial = fdmex->GetInertial();
180 Aerodynamics = fdmex->GetAerodynamics();
181 GroundReactions = fdmex->GetGroundReactions();
182 Accelerations = fdmex->GetAccelerations();
190 SGPath aircraft_path(
fgGetString(
"/sim/aircraft-dir") );
193 engine_path.append(
"Aircraft/Generic/JSBSim/Engines" );
195 SGPath systems_path(
fgGetString(
"/sim/fg-root") );
196 systems_path.append(
"Aircraft/Generic/JSBSim/Systems" );
200 SGPropertyNode * node =
fgGetNode(
"/fdm/jsbsim/simulation/sim-time-sec");
201 fgGetNode(
"/fdm/jsbsim/sim-time-sec",
true)->alias(node,
false);
204 _ai_wake_enabled =
fgGetNode(
"fdm/ai-wake/enabled",
true);
206 terrain =
fgGetNode(
"/sim/fdm/surface",
true);
210 result = fdmex->LoadModel( aircraft_path, engine_path, systems_path,
214 SG_LOG( SG_FLIGHT, SG_INFO,
" loaded aero.");
216 SG_LOG( SG_FLIGHT, SG_INFO,
217 " aero does not exist (you may have mis-typed the name).");
221 SG_LOG( SG_FLIGHT, SG_INFO,
"" );
222 SG_LOG( SG_FLIGHT, SG_INFO,
"" );
223 SG_LOG( SG_FLIGHT, SG_INFO,
"After loading aero definition file ..." );
225 int Neng = Propulsion->GetNumEngines();
226 SG_LOG( SG_FLIGHT, SG_INFO,
"num engines = " << Neng );
228 if ( GroundReactions->GetNumGearUnits() <= 0 ) {
229 SG_LOG( SG_FLIGHT, SG_ALERT,
"num gear units = "
230 << GroundReactions->GetNumGearUnits() );
231 SG_LOG( SG_FLIGHT, SG_ALERT,
"This is a very bad thing because with 0 gear units, the ground trimming");
232 SG_LOG( SG_FLIGHT, SG_ALERT,
"routine (coming up later in the code) will core dump.");
233 SG_LOG( SG_FLIGHT, SG_ALERT,
"Halting the sim now, and hoping a solution will present itself soon!");
240 for (
unsigned int i = 0;
i < Propulsion->GetNumTanks();
i++) {
242 SGPropertyNode * node =
fgGetNode(
"/consumables/fuel/tank",
i,
true);
243 FGTank* tank = Propulsion->GetTank(
i);
244 SGPropertyNode * prop = node->getNode(
"density-ppg",
true );
246 d = prop->getDoubleValue();
250 prop->setDoubleValue( SG_MAX2<double>(tank->
GetDensity(), 0.1) );
253 prop = node->getNode(
"level-lbs",
true );
254 d = prop->getDoubleValue();
261 prop = node->getNode(
"unusable-gal_us",
true );
262 d = prop->getDoubleValue();
269 node->getNode(
"capacity-gal_us",
true )->setDoubleValue( tank->
GetCapacityGallons() );
271 Propulsion->SetFuelFreeze((
fgGetNode(
"/sim/freeze/fuel",
true))->getBoolValue());
273 fgSetDouble(
"/fdm/trim/pitch-trim", FCS->GetPitchTrimCmd());
274 fgSetDouble(
"/fdm/trim/throttle", FCS->GetThrottleCmd(0));
278 startup_trim =
fgGetNode(
"/sim/presets/trim",
true);
280 trimmed =
fgGetNode(
"/fdm/trim/trimmed",
true);
281 trimmed->setBoolValue(
false);
283 pitch_trim =
fgGetNode(
"/fdm/trim/pitch-trim",
true );
284 throttle_trim =
fgGetNode(
"/fdm/trim/throttle",
true );
285 aileron_trim =
fgGetNode(
"/fdm/trim/aileron",
true );
286 rudder_trim =
fgGetNode(
"/fdm/trim/rudder",
true );
288 stall_warning =
fgGetNode(
"/sim/alarms/stall-warning",
true);
289 stall_warning->setDoubleValue(0);
292 flap_pos_pct=
fgGetNode(
"/surface-positions/flap-pos-norm",
true);
293 elevator_pos_pct=
fgGetNode(
"/surface-positions/elevator-pos-norm",
true);
295 =
fgGetNode(
"/surface-positions/left-aileron-pos-norm",
true);
296 right_aileron_pos_pct
297 =
fgGetNode(
"/surface-positions/right-aileron-pos-norm",
true);
298 rudder_pos_pct=
fgGetNode(
"/surface-positions/rudder-pos-norm",
true);
300 =
fgGetNode(
"/surface-positions/speedbrake-pos-norm",
true);
301 spoilers_pos_pct=
fgGetNode(
"/surface-positions/spoilers-pos-norm",
true);
302 tailhook_pos_pct=
fgGetNode(
"/gear/tailhook/position-norm",
true);
303 wing_fold_pos_pct=
fgGetNode(
"surface-positions/wing-fold-pos-norm",
true);
305 elevator_pos_pct->setDoubleValue(0);
306 left_aileron_pos_pct->setDoubleValue(0);
307 right_aileron_pos_pct->setDoubleValue(0);
308 rudder_pos_pct->setDoubleValue(0);
309 flap_pos_pct->setDoubleValue(0);
310 speedbrake_pos_pct->setDoubleValue(0);
311 spoilers_pos_pct->setDoubleValue(0);
313 override_fg_brake_prop =
fgGetNode(
"/fdm/jsbsim/systems/override-fg-brake-properties",
true);
314 override_fg_brake_prop->setBoolValue(
false);
315 ab_brake_engaged =
fgGetNode(
"/autopilot/autobrake/engaged",
true);
316 ab_brake_left_pct =
fgGetNode(
"/autopilot/autobrake/brake-left-output",
true);
317 ab_brake_right_pct =
fgGetNode(
"/autopilot/autobrake/brake-right-output",
true);
319 arrestor_wire_engaged_hook =
fgGetNode(
"/fdm/jsbsim/systems/hook/arrestor-wire-engaged-hook",
true);
320 release_hook =
fgGetNode(
"/fdm/jsbsim/systems/hook/tailhook-release-cmd",
true);
322 altitude =
fgGetNode(
"/position/altitude-ft");
323 precipitation =
fgGetNode(
"/environment/rain-norm",
true);
324 temperature =
fgGetNode(
"/environment/temperature-degc",
true);
325 pressure =
fgGetNode(
"/environment/pressure-inhg",
true);
326 pressureSL =
fgGetNode(
"/environment/pressure-sea-level-inhg",
true);
327 dew_point =
fgGetNode(
"/environment/dewpoint-degc",
true);
328 ground_wind =
fgGetNode(
"/environment/config/boundary/entry[0]/wind-speed-kt",
true);
329 turbulence_gain =
fgGetNode(
"/environment/turbulence/magnitude-norm",
true);
330 turbulence_rate =
fgGetNode(
"/environment/turbulence/rate-hz",
true);
331 turbulence_model =
fgGetNode(
"/environment/params/jsbsim-turbulence-model",
true);
333 wind_from_north=
fgGetNode(
"/environment/wind-from-north-fps",
true);
334 wind_from_east =
fgGetNode(
"/environment/wind-from-east-fps" ,
true);
335 wind_from_down =
fgGetNode(
"/environment/wind-from-down-fps" ,
true);
337 slaved =
fgGetNode(
"/sim/slaved/enabled",
true);
339 for (
unsigned int i = 0;
i < Propulsion->GetNumEngines();
i++) {
340 SGPropertyNode * node =
fgGetNode(
"engines/engine",
i,
true);
341 Propulsion->GetEngine(
i)->GetThruster()->SetRPM(node->getDoubleValue(
"rpm") /
342 Propulsion->GetEngine(
i)->GetThruster()->GetGearRatio());
346 fgGetDouble(
"/fdm/jsbsim/systems/hook/tailhook-offset-x-in", 196),
347 fgGetDouble(
"/fdm/jsbsim/systems/hook/tailhook-offset-y-in", 0),
348 fgGetDouble(
"/fdm/jsbsim/systems/hook/tailhook-offset-z-in", -16));
349 last_hook_tip[0] = 0; last_hook_tip[1] = 0; last_hook_tip[2] = 0;
350 last_hook_root[0] = 0; last_hook_root[1] = 0; last_hook_root[2] = 0;
356 fdmex->GetModelName());
363 std::string directive_file =
fgGetString(
"/sim/jsbsim/output-directive-file");
364 if (!directive_file.empty())
365 fdmex->SetOutputDirectives(directive_file);
372 delete PropertyManager;
382 SG_LOG( SG_FLIGHT, SG_INFO,
"Starting and initializing JSBsim" );
387 if (
fgGetBool(
"/environment/params/control-fdm-atmosphere")) {
392 Winds->SetTurbGain(0.0);
393 Winds->SetTurbRate(0.0);
394 Winds->SetWindspeed20ft(0.0);
395 Winds->SetProbabilityOfExceedence(0.0);
398 fgic->SetWindNEDFpsIC(0.0, 0.0, 0.0);
400 SG_LOG(SG_FLIGHT,SG_INFO,
"T,p,rho: " << Atmosphere->GetTemperature()
401 <<
", " << Atmosphere->GetPressure()
402 <<
", " << Atmosphere->GetDensity() );
404 FCS->SetDfPos(
ofNorm,
globals->get_controls()->get_flaps() );
406 needTrim = startup_trim->getBoolValue();
413 Propulsion->InitRunning(-1);
414 for (
unsigned int i = 0;
i < Propulsion->GetNumEngines();
i++) {
417 globals->get_controls()->set_mixture(
i, FCS->GetMixtureCmd(
i));
423 double contact[3], d[3], vel[3];
424 update_ground_cache(cart, 0.01);
426 get_agl_ft(fdmex->GetSimTime(), cart, SG_METER_TO_FEET*2, contact, d, vel,
428 double terrain_alt = sqrt(contact[0]*contact[0] + contact[1]*contact[1]
431 SG_LOG(SG_FLIGHT, SG_INFO,
"Ready to trim, terrain elevation is: "
434 if (
fgGetBool(
"/sim/presets/onground")) {
437 fgic->SetVNorthFpsIC(gndVelNED(1));
438 fgic->SetVEastFpsIC(gndVelNED(2));
439 fgic->SetVDownFpsIC(gndVelNED(3));
447 _fmag =
fgGetNode(
"/fdm/jsbsim/external_reactions/ai-wake/magnitude",
false);
448 _fbx =
fgGetNode(
"/fdm/jsbsim/external_reactions/ai-wake/x",
false);
449 _fby =
fgGetNode(
"/fdm/jsbsim/external_reactions/ai-wake/y",
false);
450 _fbz =
fgGetNode(
"/fdm/jsbsim/external_reactions/ai-wake/z",
false);
451 _mmag =
fgGetNode(
"/fdm/jsbsim/external_reactions/ai-wake/magnitude-lbsft",
false);
452 _mbx =
fgGetNode(
"/fdm/jsbsim/external_reactions/ai-wake/l",
false);
453 _mby =
fgGetNode(
"/fdm/jsbsim/external_reactions/ai-wake/m",
false);
454 _mbz =
fgGetNode(
"/fdm/jsbsim/external_reactions/ai-wake/n",
false);
456 SG_LOG( SG_FLIGHT, SG_INFO,
" Initialized JSBSim with:" );
458 switch(fgic->GetSpeedSet()) {
460 SG_LOG(SG_FLIGHT,SG_INFO,
" Vn,Ve,Vd= "
466 SG_LOG(SG_FLIGHT,SG_INFO,
" U,V,W= "
467 << Propagate->GetUVW(1) <<
", "
468 << Propagate->GetUVW(2) <<
", "
469 << Propagate->GetUVW(3) <<
" ft/s");
472 SG_LOG(SG_FLIGHT,SG_INFO,
" Mach: "
473 << Auxiliary->GetMach() );
477 SG_LOG(SG_FLIGHT,SG_INFO,
" Indicated Airspeed: "
478 << Auxiliary->GetVcalibratedKTS() <<
" knots" );
482 stall_warning->setDoubleValue(0);
484 SG_LOG( SG_FLIGHT, SG_INFO,
" Bank Angle: "
486 SG_LOG( SG_FLIGHT, SG_INFO,
" Pitch Angle: "
488 SG_LOG( SG_FLIGHT, SG_INFO,
" True Heading: "
490 SG_LOG( SG_FLIGHT, SG_INFO,
" Latitude: "
491 << Propagate->GetLocation().GetLatitudeDeg() <<
" deg" );
492 SG_LOG( SG_FLIGHT, SG_INFO,
" Longitude: "
493 << Propagate->GetLocation().GetLongitudeDeg() <<
" deg" );
494 SG_LOG( SG_FLIGHT, SG_INFO,
" Altitude: "
495 << Propagate->GetAltitudeASL() <<
" feet" );
496 SG_LOG( SG_FLIGHT, SG_INFO,
" loaded initial conditions" );
498 SG_LOG( SG_FLIGHT, SG_INFO,
" set dt" );
500 SG_LOG( SG_FLIGHT, SG_INFO,
"Finished initializing JSBSim" );
502 SG_LOG( SG_FLIGHT, SG_INFO,
"FGControls::get_gear_down()= " <<
503 globals->get_controls()->get_gear_down() );
529 FGLocation cart = Auxiliary->GetLocationVRP();
531 update_ground_cache(cart, dt);
535 trimmed->setBoolValue(
false);
537 for (
int i=0;
i < multiloop;
i++ ) {
544 update_external_forces(fdmex->GetSimTime() +
i * fdmex->GetDeltaT());
548 while ((msg = fdmex->ProcessNextMessage()) != NULL) {
552 if (msg->
text ==
"Crash Detected: Simulation FREEZE.")
554 SG_LOG( SG_FLIGHT, SG_INFO, msg->
messageId <<
": " << msg->
text );
557 SG_LOG( SG_FLIGHT, SG_INFO, msg->
messageId <<
": " << msg->
text <<
" " << msg->
bVal );
560 SG_LOG( SG_FLIGHT, SG_INFO, msg->
messageId <<
": " << msg->
text <<
" " << msg->
iVal );
563 SG_LOG( SG_FLIGHT, SG_INFO, msg->
messageId <<
": " << msg->
text <<
" " << msg->
dVal );
566 SG_LOG( SG_FLIGHT, SG_INFO,
"Unrecognized message type." );
583 SGSubsystem::suspend();
591 SGSubsystem::resume();
604 FCS->SetDaCmd(
globals->get_controls()->get_aileron());
605 FCS->SetRollTrimCmd(
globals->get_controls()->get_aileron_trim() );
606 FCS->SetDeCmd(
globals->get_controls()->get_elevator());
607 FCS->SetPitchTrimCmd(
globals->get_controls()->get_elevator_trim() );
608 FCS->SetDrCmd( -
globals->get_controls()->get_rudder() );
609 FCS->SetDsCmd(
globals->get_controls()->get_rudder() );
610 FCS->SetYawTrimCmd( -
globals->get_controls()->get_rudder_trim() );
611 FCS->SetDfCmd(
globals->get_controls()->get_flaps() );
612 FCS->SetDsbCmd(
globals->get_controls()->get_speedbrake() );
613 FCS->SetDspCmd(
globals->get_controls()->get_spoilers() );
615 if (!override_fg_brake_prop->getBoolValue()) {
618 double parking_brake =
globals->get_controls()->get_brake_parking();
619 double left_brake =
globals->get_controls()->get_brake_left();
620 double right_brake =
globals->get_controls()->get_brake_right();
622 if (ab_brake_engaged->getBoolValue()) {
623 left_brake = ab_brake_left_pct->getDoubleValue();
624 right_brake = ab_brake_right_pct->getDoubleValue();
627 FCS->SetLBrake(
FMAX(left_brake, parking_brake));
628 FCS->SetRBrake(
FMAX(right_brake, parking_brake));
630 FCS->SetCBrake( 0.0 );
634 FCS->SetGearCmd(
globals->get_controls()->get_gear_down());
635 for (
i = 0;
i < Propulsion->GetNumEngines();
i++) {
636 SGPropertyNode * node =
fgGetNode(
"engines/engine",
i,
true);
638 FCS->SetThrottleCmd(
i,
globals->get_controls()->get_throttle(
i));
639 FCS->SetMixtureCmd(
i,
globals->get_controls()->get_mixture(
i));
640 FCS->SetPropAdvanceCmd(
i,
globals->get_controls()->get_prop_advance(
i));
641 FCS->SetFeatherCmd(
i,
globals->get_controls()->get_feather(
i));
643 switch (Propulsion->GetEngine(
i)->GetType()) {
681 FGEngine* eng = Propulsion->GetEngine(
i);
684 eng->
SetRunning( node->getBoolValue(
"running") );
691 dew_point->getDoubleValue());
693 Winds->SetTurbType((
FGWinds::tType)TURBULENCE_TYPE_NAMES[turbulence_model->getStringValue()]);
694 switch( Winds->GetTurbType() ) {
697 double tmp = turbulence_gain->getDoubleValue();
698 Winds->SetTurbGain(tmp * tmp * 100.0);
699 Winds->SetTurbRate(turbulence_rate->getDoubleValue());
706 double tmp = turbulence_gain->getDoubleValue();
707 Winds->SetProbabilityOfExceedence(
710 Winds->SetWindspeed20ft(ground_wind->getDoubleValue());
718 Winds->SetWindNED( -wind_from_north->getDoubleValue(),
719 -wind_from_east->getDoubleValue(),
720 -wind_from_down->getDoubleValue() );
726 for (
i = 0;
i < Propulsion->GetNumTanks();
i++) {
727 SGPropertyNode * node =
fgGetNode(
"/consumables/fuel/tank",
i,
true);
728 FGTank * tank = Propulsion->GetTank(
i);
729 double fuelDensity = node->getDoubleValue(
"density-ppg");
731 if (fuelDensity < 0.1)
735 tank->
SetContents(node->getDoubleValue(
"level-lbs"));
738 Propulsion->SetFuelFreeze((
fgGetNode(
"/sim/freeze/fuel",
true))->getBoolValue());
739 fdmex->SetChild(slaved->getBoolValue());
759 MassBalance->GetXYZcg(2),
760 MassBalance->GetXYZcg(3) );
763 Accelerations->GetBodyAccel(2),
764 Accelerations->GetBodyAccel(3) );
767 Auxiliary->GetNcg(2),
768 Auxiliary->GetNcg(3) );
771 Auxiliary->GetPilotAccel(2),
772 Auxiliary->GetPilotAccel(3) );
783 Propagate->GetUVW(2),
784 Propagate->GetUVW(3) );
816 double contact[3], d[3], sd, t;
818 get_agl_ft(t, l, SG_METER_TO_FEET*2, contact, d, d, d);
838 const FGMatrix33& Tl2b = Propagate->GetTl2b();
839 for (
i = 1;
i <= 3;
i++ ) {
840 for ( j = 1; j <= 3; j++ ) {
846 for (
i=0;
i < Propulsion->GetNumEngines();
i++ ) {
847 SGPropertyNode * node =
fgGetNode(
"engines/engine",
i,
true);
848 SGPropertyNode * tnode = node->getChild(
"thruster", 0,
true);
849 FGThruster * thruster = Propulsion->GetEngine(
i)->GetThruster();
851 switch (Propulsion->GetEngine(
i)->GetType()) {
864 node->setDoubleValue(
"rpm", eng->
getRPM());
875 node->setDoubleValue(
"n1", eng->
GetN1());
876 node->setDoubleValue(
"n2", eng->
GetN2());
877 node->setDoubleValue(
"egt-degf", 32 + eng->
GetEGT()*9/5);
879 node->setBoolValue(
"water-injection", eng->
GetInjection());
880 node->setBoolValue(
"ignition", eng->
GetIgnition() != 0);
881 node->setDoubleValue(
"nozzle-pos-norm", eng->
GetNozzle());
882 node->setDoubleValue(
"inlet-pos-norm", eng->
GetInlet());
884 node->setBoolValue(
"reversed", eng->
GetReversed());
885 node->setBoolValue(
"cutoff", eng->
GetCutoff());
886 node->setDoubleValue(
"epr", eng->
GetEPR());
896 node->setDoubleValue(
"n1", eng->
GetN1());
898 node->setDoubleValue(
"itt_degf", 32 + eng->
GetITT()*9/5);
903 node->setBoolValue(
"reversed", eng->
GetReversed());
904 node->setBoolValue(
"cutoff", eng->
GetCutoff());
907 node->setBoolValue(
"damaged", eng->
GetCondition() != 0);
918 node->setDoubleValue(
"rpm", eng->
getRPM());
926 FGEngine* eng = Propulsion->GetEngine(
i);
928 node->setDoubleValue(
"thrust_lb", thruster->
GetThrust());
930 node->setBoolValue(
"running", eng->
GetRunning());
931 node->setBoolValue(
"starter", eng->
GetStarter());
932 node->setBoolValue(
"cranking", eng->
GetCranking());
945 tnode->setDoubleValue(
"rpm", thruster->
GetRPM());
946 tnode->setDoubleValue(
"pitch", prop->
GetPitch());
947 tnode->setDoubleValue(
"torque", prop->
GetTorque());
948 tnode->setBoolValue(
"feathered", prop->
GetFeather());
966 if ( ! Propulsion->GetFuelFreeze() ) {
967 for (
i = 0;
i < Propulsion->GetNumTanks();
i++) {
968 SGPropertyNode * node =
fgGetNode(
"/consumables/fuel/tank",
i,
true);
969 FGTank* tank = Propulsion->GetTank(
i);
974 if (fuelDensity < 0.1)
977 node->setDoubleValue(
"density-ppg" , fuelDensity);
978 node->setDoubleValue(
"level-lbs", contents);
979 if (temp != -9999.0) node->setDoubleValue(
"temperature_degC", temp);
987 stall_warning->setDoubleValue( Aerodynamics->GetStallWarn() );
989 elevator_pos_pct->setDoubleValue( FCS->GetDePos(
ofNorm) );
990 left_aileron_pos_pct->setDoubleValue( FCS->GetDaLPos(
ofNorm) );
991 right_aileron_pos_pct->setDoubleValue( FCS->GetDaRPos(
ofNorm) );
992 rudder_pos_pct->setDoubleValue( -1*FCS->GetDrPos(
ofNorm) );
993 flap_pos_pct->setDoubleValue( FCS->GetDfPos(
ofNorm) );
994 speedbrake_pos_pct->setDoubleValue( FCS->GetDsbPos(
ofNorm) );
995 spoilers_pos_pct->setDoubleValue( FCS->GetDspPos(
ofNorm) );
996 tailhook_pos_pct->setDoubleValue( FCS->GetTailhookPos() );
997 wing_fold_pos_pct->setDoubleValue( FCS->GetWingFoldPos() );
1001 fdmex->SuspendIntegration();
1012 fdmex->DisableOutput();
1020 fdmex->EnableOutput();
1023 fdmex->DisableOutput();
1032 double alt = altitude->getDoubleValue();
1033 double sea_level_radius_meters,
lat_geoc;
1035 if ( alt < -9990 ) alt = 0.0;
1037 SG_LOG(SG_FLIGHT,SG_INFO,
"FGJSBsim::set_Latitude: " << lat );
1038 SG_LOG(SG_FLIGHT,SG_INFO,
" cur alt (ft) = " << alt );
1041 fgic->SetGeodLatitudeRadIC( lat );
1043 sgGeodToGeoc( lat, alt * SG_FEET_TO_METER,
1044 &sea_level_radius_meters, &
lat_geoc );
1046 double sea_level_radius_ft = sea_level_radius_meters * SG_METER_TO_FEET;
1058 SG_LOG(SG_FLIGHT,SG_INFO,
"FGJSBsim::set_Longitude: " << lon );
1061 fgic->SetLongitudeRadIC(lon);
1063 Propagate->SetLongitude(lon);
1071 SG_LOG(SG_FLIGHT,SG_INFO,
"FGJSBsim::set_Altitude: " << alt );
1074 fgic->SetAltitudeASLFtIC(alt);
1076 Propagate->SetAltitudeASL(alt);
1083 SG_LOG(SG_FLIGHT,SG_INFO,
"FGJSBsim::set_V_calibrated_kts: " << vc );
1086 fgic->SetVcalibratedKtsIC(vc);
1088 double p=pressure->getDoubleValue();
1090 double temp = 1.8*(temperature->getDoubleValue()+273.15);
1091 double soundSpeed = sqrt(1.4*1716.0*temp);
1094 vUVW *= mach * soundSpeed;
1095 Propagate->SetUVW(1, vUVW(1));
1096 Propagate->SetUVW(2, vUVW(2));
1097 Propagate->SetUVW(3, vUVW(3));
1105 SG_LOG(SG_FLIGHT,SG_INFO,
"FGJSBsim::set_Mach_number: " << mach );
1108 fgic->SetMachIC(mach);
1110 double temp = 1.8*(temperature->getDoubleValue()+273.15);
1111 double soundSpeed = sqrt(1.4*1716.0*temp);
1114 vUVW *= mach * soundSpeed;
1115 Propagate->SetUVW(1, vUVW(1));
1116 Propagate->SetUVW(2, vUVW(2));
1117 Propagate->SetUVW(3, vUVW(3));
1125 SG_LOG(SG_FLIGHT,SG_INFO,
"FGJSBsim::set_Velocities_Local: "
1126 << north <<
", " << east <<
", " << down );
1129 fgic->SetVNorthFpsIC(north);
1130 fgic->SetVEastFpsIC(east);
1131 fgic->SetVDownFpsIC(down);
1136 Propagate->SetUVW(1, vUVW(1));
1137 Propagate->SetUVW(2, vUVW(2));
1138 Propagate->SetUVW(3, vUVW(3));
1146 SG_LOG(SG_FLIGHT,SG_INFO,
"FGJSBsim::set_Velocities_Body: "
1147 << u <<
", " << v <<
", " << w );
1150 fgic->SetUBodyFpsIC(u);
1151 fgic->SetVBodyFpsIC(v);
1152 fgic->SetWBodyFpsIC(w);
1155 Propagate->SetUVW(1, u);
1156 Propagate->SetUVW(2, v);
1157 Propagate->SetUVW(3, w);
1166 SG_LOG(SG_FLIGHT,SG_INFO,
"FGJSBsim::set_Euler_Angles: "
1167 << phi <<
", " << theta <<
", " << psi );
1170 fgic->SetThetaRadIC(theta);
1171 fgic->SetPhiRadIC(phi);
1172 fgic->SetPsiRadIC(psi);
1179 Propagate->SetInertialOrientation(Qi);
1188 SG_LOG(SG_FLIGHT,SG_INFO,
"FGJSBsim::set_Climb_Rate: " << roc );
1193 if( fabs(roc) > 1 && fabs(fgic->GetFlightPathAngleRadIC()) < 0.01 ) {
1195 fgic->SetClimbRateFpsIC(roc);
1200 Propagate->SetUVW(1, vUVW(1));
1201 Propagate->SetUVW(2, vUVW(2));
1202 Propagate->SetUVW(3, vUVW(3));
1211 SG_LOG(SG_FLIGHT,SG_INFO,
"FGJSBsim::set_Gamma_vert_rad: " << gamma );
1213 if( !(fabs(gamma) < 0.01 && fabs(fgic->GetClimbRateFpsIC()) > 1) ) {
1215 fgic->SetFlightPathAngleRadIC(gamma);
1221 Propagate->SetUVW(1, vUVW(1));
1222 Propagate->SetUVW(2, vUVW(2));
1223 Propagate->SetUVW(3, vUVW(3));
1230void FGJSBsim::init_gear(
void )
1235 for (
int i=0;
i<Ngear;
i++) {
1237 SGPropertyNode * node =
fgGetNode(
"gear/gear",
i,
true);
1243 node->setDoubleValue(
"xoffset-m", gear->
GetBodyLocation()(1) * SG_FEET_TO_METER);
1244 node->setDoubleValue(
"yoffset-m", gear->
GetBodyLocation()(2) * SG_FEET_TO_METER);
1245 node->setDoubleValue(
"zoffset-m", gear->
GetBodyLocation()(3) * SG_FEET_TO_METER);
1247 node->setBoolValue(
"wow", gear->
GetWOW());
1248 node->setDoubleValue(
"rollspeed-ms", gear->
GetWheelRollVel() * SG_FEET_TO_METER);
1252 max = node->getDoubleValue(
"max-compression-ft");
1253 if (max < 0.00001) {
1254 max = node->getDoubleValue(
"max-compression-m");
1255 if (max < 0.00001) max = 1.0;
1256 else max /= SG_FEET_TO_METER;
1258 node->setDoubleValue(
"compression-norm", gear->
GetCompLen() / max);
1259 node->setDoubleValue(
"compression-m", gear->
GetCompLen() * SG_FEET_TO_METER);
1260 node->setDoubleValue(
"compression-ft", gear->
GetCompLen());
1262 node->setDoubleValue(
"steering-norm", gear->
GetSteerNorm());
1266void FGJSBsim::update_gear(
void)
1268 FGGroundReactions* gr=fdmex->GetGroundReactions();
1271 for (
int i=0;
i<Ngear;
i++) {
1273 SGPropertyNode * node =
fgGetNode(
"gear/gear",
i,
true);
1274 node->getChild(
"wow", 0,
true)->setBoolValue( gear->
GetWOW());
1275 node->getChild(
"rollspeed-ms", 0,
true)->setDoubleValue(gear->
GetWheelRollVel() * SG_FEET_TO_METER);
1276 node->getChild(
"position-norm", 0,
true)->setDoubleValue(gear->
GetGearUnitPos());
1278 max = node->getDoubleValue(
"max-compression-ft");
1279 if (max < 0.00001) {
1280 max = node->getDoubleValue(
"max-compression-m");
1281 if (max < 0.00001) max = 1.0;
1282 else max /= SG_FEET_TO_METER;
1284 node->setDoubleValue(
"compression-norm", gear->
GetCompLen() / max);
1285 node->setDoubleValue(
"compression-m", gear->
GetCompLen() * SG_FEET_TO_METER);
1286 node->setDoubleValue(
"compression-ft", gear->
GetCompLen());
1288 node->setDoubleValue(
"steering-norm", gear->
GetSteerNorm());
1292void FGJSBsim::do_trim(
void)
1296 if (
fgGetBool(
"/sim/presets/onground") )
1298 fgtrim =
new FGTrim(fdmex,
tGround);
1300 fgtrim =
new FGTrim(fdmex,
tFull);
1303 if ( !fgtrim->
DoTrim() ) {
1307 trimmed->setBoolValue(
true);
1311 pitch_trim->setDoubleValue( FCS->GetPitchTrimCmd() );
1312 throttle_trim->setDoubleValue( FCS->GetThrottleCmd(0) );
1313 aileron_trim->setDoubleValue( FCS->GetDaCmd() );
1314 rudder_trim->setDoubleValue( -FCS->GetDrCmd() );
1318 for(
unsigned i = 0;
i < Propulsion->GetNumEngines();
i++ )
1324 SG_LOG( SG_FLIGHT, SG_INFO,
" Trim complete" );
1327bool FGJSBsim::update_ground_cache(
const FGLocation& cart,
double dt)
1331 double acrad = 10.0;
1332 int n_gears = GroundReactions->GetNumGearUnits();
1333 for (
int i=0;
i<n_gears; ++
i) {
1334 FGColumnVector3 bl = GroundReactions->GetGearUnit(
i)->GetBodyLocation();
1342 double groundCacheRadius = acrad + 2*dt*Propagate->GetUVW().Magnitude();
1344 double cart_pos[3] {cart(1), cart(2), cart(3)};
1345 double t0 = fdmex->GetSimTime();
1347 groundCacheRadius );
1370 double contact[3],
double normal[3],
double vel[3],
1371 double angularVel[3])
1373 const simgear::BVHMaterial* material =
nullptr;
1374 simgear::BVHNode::Id id;
1375 double pt[3] {loc(1), loc(2), loc(3)};
1378 angularVel, material,
id))
1381 SGGeod geodPt = SGGeod::fromCart(SG_FEET_TO_METER*SGVec3d(pt));
1382 SGQuatd hlToEc = SGQuatd::fromLonLat(geodPt);
1384#ifdef JSBSIM_USE_GROUNDREACTIONS
1385 bool terrain_active = (terrain->getIntValue(
"override-level", -1) > 0) ? false :
true;
1386 terrain->setBoolValue(
"active", terrain_active);
1387 terrain->setBoolValue(
"valid", (material && terrain_active) ?
true :
false);
1390 static bool material_valid =
false;
1397 GroundReactions->SetMaximumForce(
getPressure()*0.00014503773800721815);
1399 GroundReactions->SetSolid(
getSolid());
1400 GroundReactions->SetPosition(pt);
1401 material_valid =
true;
1403 if (material_valid) {
1404 GroundReactions->resetValues();
1405 material_valid =
false;
1410 terrain->setBoolValue(
"valid",
false);
1412 return dot(hlToEc.rotate(SGVec3d(0, 0, 1)), SGVec3d(contact) - SGVec3d(pt)) +
1416inline static double sqr(
double x)
1423 double diff = fabs(a - b);
1424 if (diff > 180) diff = 360 - diff;
1429static void check_hook_solution(
const FGColumnVector3& ground_normal_body,
double E,
double hook_length,
double sin_fi_guess,
double cos_fi_guess,
double* sin_fis,
double* cos_fis,
double* fis,
int* points)
1431 FGColumnVector3 tip(-hook_length * cos_fi_guess, 0, hook_length * sin_fi_guess);
1432 double dist =
DotProduct(tip, ground_normal_body);
1433 if (fabs(dist + E) < 0.0001) {
1434 sin_fis[*points] = sin_fi_guess;
1435 cos_fis[*points] = cos_fi_guess;
1436 fis[*points] = atan2(sin_fi_guess, cos_fi_guess) * SG_RADIANS_TO_DEGREES;
1444 if (sin_fi_guess >= -1 && sin_fi_guess <= 1) {
1445 double cos_fi_guess = sqrt(1 -
sqr(sin_fi_guess));
1446 check_hook_solution(ground_normal_body, E, hook_length, sin_fi_guess, cos_fi_guess, sin_fis, cos_fis, fis, points);
1447 if (fabs(cos_fi_guess) > SG_EPSILON) {
1448 check_hook_solution(ground_normal_body, E, hook_length, sin_fi_guess, -cos_fi_guess, sin_fis, cos_fis, fis, points);
1453void FGJSBsim::update_external_forces(
double t_off)
1455 const FGMatrix33& Tb2l = Propagate->GetTb2l();
1456 const FGMatrix33& Tl2b = Propagate->GetTl2b();
1457 const FGLocation& Location = Propagate->GetLocation();
1458 const FGMatrix33& Tec2l = Location.
GetTec2l();
1460 double hook_area[4][3];
1462 FGColumnVector3 hook_root_body = MassBalance->StructuralToBody(hook_root_struct);
1463 FGColumnVector3 hook_root = Location.
LocalToLocation(Tb2l * hook_root_body);
1464 hook_area[1][0] = hook_root(1);
1465 hook_area[1][1] = hook_root(2);
1466 hook_area[1][2] = hook_root(3);
1468 hook_length =
fgGetDouble(
"/fdm/jsbsim/systems/hook/tailhook-length-ft", 6.75);
1469 double fi_min =
fgGetDouble(
"/fdm/jsbsim/systems/hook/tailhook-pos-min-deg", -18);
1470 double fi_max =
fgGetDouble(
"/fdm/jsbsim/systems/hook/tailhook-pos-max-deg", 30);
1471 double fi =
fgGetDouble(
"/fdm/jsbsim/systems/hook/tailhook-pos-norm") * (fi_max - fi_min) + fi_min;
1472 double cos_fi = cos(fi * SG_DEGREES_TO_RADIANS);
1473 double sin_fi = sin(fi * SG_DEGREES_TO_RADIANS);
1475 FGColumnVector3 hook_tip_body = hook_root_body;
1476 hook_tip_body(1) -= hook_length * cos_fi;
1477 hook_tip_body(3) += hook_length * sin_fi;
1478 if (!arrestor_wire_engaged_hook->getBoolValue()) {
1480 double ground_normal[3];
1481 double ground_vel[3];
1482 double ground_angular_vel[3];
1483 double root_agl_ft =
get_agl_ft(t_off, hook_root, 0, contact,
1484 ground_normal, ground_vel,
1485 ground_angular_vel);
1486 if (root_agl_ft > 0 && root_agl_ft < hook_length) {
1487 FGColumnVector3 ground_normal_body = Tl2b * (Tec2l * FGColumnVector3(ground_normal[0], ground_normal[1], ground_normal[2]));
1488 FGColumnVector3 contact_body = Tl2b * Location.
LocationToLocal(FGColumnVector3(contact[0], contact[1], contact[2]));
1489 double D = -
DotProduct(contact_body, ground_normal_body);
1492 double hook_tip_agl_ft =
DotProduct(hook_tip_body, ground_normal_body) + D;
1493 if (hook_tip_agl_ft < 0) {
1498 double E = D +
DotProduct(hook_root_body, ground_normal_body);
1502 double a =
sqr(hook_length) * (
sqr(ground_normal_body(1)) +
sqr(ground_normal_body(3)));
1503 double b = 2 * E * ground_normal_body(3) * hook_length;
1504 double c =
sqr(E) -
sqr(ground_normal_body(1) * hook_length);
1506 double disc =
sqr(b) - 4 * a * c;
1508 double delta = sqrt(disc) / (2 * a);
1516 double sin_fi_guess = -b / (2 * a) - delta;
1517 check_hook_solution(ground_normal_body, E, hook_length, sin_fi_guess, sin_fis, cos_fis, fis, &points);
1518 check_hook_solution(ground_normal_body, E, hook_length, sin_fi_guess + 2 * delta, sin_fis, cos_fis, fis, &points);
1523 int point = diff1 < diff2 ? 0 : 1;
1525 sin_fi = sin_fis[point];
1526 cos_fi = cos_fis[point];
1527 hook_tip_body(1) = hook_root_body(1) - hook_length * cos_fi;
1528 hook_tip_body(3) = hook_root_body(3) + hook_length * sin_fi;
1534 if (release_hook->getBoolValue()) {
1536 fgSetDouble(
"/fdm/jsbsim/external_reactions/hook/magnitude", 0.0);
1537 arrestor_wire_engaged_hook->setBoolValue(
false);
1538 release_hook->setBoolValue(
false);
1540 FGColumnVector3 hook_root_vel = Propagate->GetVel() + (Tb2l * (Propagate->GetPQR() * hook_root_body));
1541 double wire_ends_ec[2][3];
1542 double wire_vel_ec[2][3];
1544 FGColumnVector3 wire_vel_1 = Tec2l * FGColumnVector3(wire_vel_ec[0][0], wire_vel_ec[0][1], wire_vel_ec[0][2]);
1545 FGColumnVector3 wire_vel_2 = Tec2l * FGColumnVector3(wire_vel_ec[1][0], wire_vel_ec[1][1], wire_vel_ec[1][2]);
1546 FGColumnVector3 rel_vel = hook_root_vel - (wire_vel_1 + wire_vel_2) / 2;
1549 fgSetDouble(
"/fdm/jsbsim/external_reactions/hook/magnitude", 0.0);
1550 arrestor_wire_engaged_hook->setBoolValue(
false);
1551 release_hook->setBoolValue(
false);
1554 FGColumnVector3 wire_end1_body = Tl2b * Location.
LocationToLocal(FGColumnVector3(wire_ends_ec[0][0], wire_ends_ec[0][1], wire_ends_ec[0][2])) - hook_root_body;
1555 FGColumnVector3 wire_end2_body = Tl2b * Location.
LocationToLocal(FGColumnVector3(wire_ends_ec[1][0], wire_ends_ec[1][1], wire_ends_ec[1][2])) - hook_root_body;
1556 FGColumnVector3 force_plane_normal = wire_end1_body * wire_end2_body;
1558 cos_fi =
DotProduct(force_plane_normal, FGColumnVector3(0, 0, 1));
1559 if (cos_fi < 0) cos_fi = -cos_fi;
1560 sin_fi = sqrt(1 -
sqr(cos_fi));
1561 fi = atan2(sin_fi, cos_fi) * SG_RADIANS_TO_DEGREES;
1563 fgSetDouble(
"/fdm/jsbsim/external_reactions/hook/x", -cos_fi);
1564 fgSetDouble(
"/fdm/jsbsim/external_reactions/hook/y", 0);
1565 fgSetDouble(
"/fdm/jsbsim/external_reactions/hook/z", sin_fi);
1566 fgSetDouble(
"/fdm/jsbsim/external_reactions/hook/magnitude",
fgGetDouble(
"/fdm/jsbsim/systems/hook/force"));
1571 FGColumnVector3 hook_tip = Location.
LocalToLocation(Tb2l * hook_tip_body);
1573 hook_area[0][0] = hook_tip(1);
1574 hook_area[0][1] = hook_tip(2);
1575 hook_area[0][2] = hook_tip(3);
1577 if (!arrestor_wire_engaged_hook->getBoolValue()) {
1579 hook_area[2][0] = last_hook_root[0];
1580 hook_area[2][1] = last_hook_root[1];
1581 hook_area[2][2] = last_hook_root[2];
1582 hook_area[3][0] = last_hook_tip[0];
1583 hook_area[3][1] = last_hook_tip[1];
1584 hook_area[3][2] = last_hook_tip[2];
1589 arrestor_wire_engaged_hook->setBoolValue(
true);
1594 last_hook_tip[0] = hook_area[0][0];
1595 last_hook_tip[1] = hook_area[0][1];
1596 last_hook_tip[2] = hook_area[0][2];
1597 last_hook_root[0] = hook_area[1][0];
1598 last_hook_root[1] = hook_area[1][1];
1599 last_hook_root[2] = hook_area[1][2];
1601 fgSetDouble(
"/fdm/jsbsim/systems/hook/tailhook-pos-deg", fi);
1603 if (_ai_wake_enabled->getBoolValue()) {
1604 FGColumnVector3 uvw = Propagate->GetUVW();
1605 FGQuaternion ql2b = Propagate->GetQuaternion();
1606 FGLocation l = Auxiliary->GetLocationVRP();
1607 SGVec3d cartPos(l(1), l(2), l(3));
1610 SGQuatd orient(ql2b(2), ql2b(3), ql2b(4), ql2b(1));
1612 mesh->setPosition(cartPos * SG_FEET_TO_METER, orient);
1615 SGVec3d(uvw(1), uvw(2), uvw(3)),
1616 Atmosphere->GetDensity());
1617 const SGVec3d& m = mesh->GetMoment();
1619 if (_fmag) _fmag->setDoubleValue(1.0);
1620 if (_fbx) _fbx->setDoubleValue(f[0]);
1621 if (_fby) _fby->setDoubleValue(f[1]);
1622 if (_fbz) _fbz->setDoubleValue(f[2]);
1624 if (_mmag) _mmag->setDoubleValue(1.0);
1625 if (_mbx) _mbx->setDoubleValue(m[0]);
1626 if (_mby) _mby->setDoubleValue(m[1]);
1627 if (_mbz) _mbz->setDoubleValue(m[2]);
1630 if (_fmag) _fmag->setDoubleValue(0.0);
1631 if (_mmag) _mmag->setDoubleValue(0.0);
1638SGSubsystemMgr::Registrant<FGJSBsim> registrantFGJSBsim;
static FGTurbulenceSeverityTable TurbulenceSeverityTable
static double angle_diff(double a, double b)
static double sqr(double x)
static void check_hook_solution(const FGColumnVector3 &ground_normal_body, double E, double hook_length, double sin_fi_guess, double cos_fi_guess, double *sin_fis, double *cos_fis, double *fis, int *points)
static double FMAX(double a, double b)
void set_rudder(double pos)
void set_elevator(double pos)
void set_aileron(double pos)
void set_throttle(int engine, double pos)
void set_elevator_trim(double pos)
virtual double GetAltitude(const FGLocation &l) const
Get the altitude above sea level dependent on the location.
virtual ~FGFSGroundCallback()
double GetAGLevel(double t, const FGLocation &l, FGLocation &cont, FGColumnVector3 &n, FGColumnVector3 &v, FGColumnVector3 &w) const override
Compute the altitude above ground.
FGFSGroundCallback(FGJSBsim *ifc)
FGControls * get_controls() const
void _updatePosition(const SGGeod &geod)
void _set_Mach_number(double m)
void _set_Velocities_Local(double north, double east, double down)
float getStaticFrictionFactor()
void _set_Accels_Pilot_Body(double x, double y, double z)
virtual void set_Velocities_Body(double u, double v, double w)
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)
void unbind() override
Unbind any properties bound to this FDM.
bool get_agl_ft(double t, const double pt[3], double max_altoff, double contact[3], double normal[3], double linearVel[3], double angularVel[3], simgear::BVHMaterial const *&material, simgear::BVHNode::Id &id)
bool get_wire_ends_ft(double t, double end[2][3], double vel[2][3])
float getGroundDisplacement()
void _set_Earth_position_angle(double a)
void _set_Climb_Rate(double rate)
void _set_CG_Position(double dx, double dy, double dz)
virtual void set_Latitude(double lat)
virtual void set_Climb_Rate(double roc)
bool updateGroundReactions(simgear::BVHMaterial const *&material)
void common_init()
Initialize the state of the FDM.
bool prepare_ground_cache_ft(double startSimTime, double endSimTime, const double pt[3], double rad)
virtual void set_Mach_number(double mach)
void _set_Accels_CG_Body_N(double x, double y, double z)
void _set_Runway_altitude(double alt)
virtual void set_Gamma_vert_rad(double gamma)
float getRolingFrictionFactor()
const AIWakeGroup & get_wake_group(void)
void _set_Velocities_Ground(double north, double east, double down)
void _set_Omega_Body(double p, double q, double r)
virtual void set_V_calibrated_kts(double vc)
virtual void set_Altitude(double alt)
bool is_valid_m(double *ref_time, double pt[3], double *rad)
void _set_V_calibrated_kts(double kts)
void _set_Sea_level_radius(double r)
double get_Altitude() const
void _set_V_rel_wind(double vt)
void setPosition(double pt[3])
bool caught_wire_ft(double t, const double pt[4][3])
void _set_Altitude_AGL(double agl)
void _set_T_Local_to_Body(int i, int j, double value)
virtual void set_Euler_Angles(double phi, double theta, double psi)
void _set_Euler_Rates(double phi, double theta, double psi)
void _set_V_equiv_kts(double kts)
int _calc_multiloop(double dt)
double get_Sea_level_radius() const
void reset_wake_group(void)
void _set_V_ground_speed(double v)
void _set_Gamma_vert_rad(double gv)
virtual void set_Longitude(double lon)
virtual void set_Velocities_Local(double north, double east, double down)
double get_Altitude_AGL(void) const
void _set_Euler_Angles(double phi, double theta, double psi)
FGFS / JSBSim interface (aka "The Bus").
void set_Velocities_Local(double north, double east, double down)
Sets velocity in N-E-D coordinates.
FGJSBsim(double dt)
Constructor.
void set_Longitude(double lon)
Set longitude.
void set_V_calibrated_kts(double vc)
Sets calibrated airspeed Setting this will trigger a recalc of the other velocity terms.
void set_Latitude(double lat)
Set geocentric latitude.
void set_Climb_Rate(double roc)
Sets rate of climb.
bool copy_to_JSBsim()
copy FDM state to LaRCsim structures
void update(double dt) override
void set_Altitude(double alt)
Set altitude Note: this triggers a recalculation of AGL altitude.
void set_Mach_number(double mach)
Sets Mach number.
void set_Euler_Angles(double phi, double theta, double psi)
Euler Angle Parameter Set.
bool copy_from_JSBsim()
copy FDM state from LaRCsim structures
void set_Velocities_Body(double u, double v, double w)
Sets aircraft velocity in stability frame.
double get_agl_ft(double t, const JSBSim::FGColumnVector3 &loc, double alt_off, double contact[3], double normal[3], double vel[3], double angularVel[3])
bool ToggleDataLogging(void)
void set_Gamma_vert_rad(double gamma)
Sets the flight path angle in radians.
FGTurbulenceSeverityTable()
This class implements a 3 element column vector.
FGColumnVector3 & Normalize(void)
Normalize.
double Magnitude(void) const
Length of the vector.
Models an electric motor.
Base class for all engines.
virtual double getFuelFlow_gph() const
virtual bool GetCranking(void) const
virtual bool GetRunning(void) const
virtual void SetStarter(bool s)
virtual void SetRunning(bool bb)
virtual double getFuelFlow_pph() const
virtual bool GetStarter(void) const
FGGroundReactions * GetGroundReactions(void)
Returns the FGGroundReactions pointer.
Manages ground reactions modeling.
FGLGear * GetGearUnit(int gear) const
Gets a gear instance.
int GetNumGearUnits(void) const
Gets the number of gears.
static double MachFromVcalibrated(double vcas, double p)
Calculate the Mach number from the calibrated airspeed.Based on the formulas in the US Air Force Airc...
double GetCompLen(void) const
Gets the current compressed length of the gear in feet.
double GetWheelRollVel(void) const
bool GetSteerable(void) const
double GetGearUnitPos(void) const
double GetSteerNorm(void) const
bool GetWOW(void) const
Gets the Weight On Wheels flag value.
int GetBrakeGroup(void) const
FGColumnVector3 GetBodyLocation(void) const
Gets the location of the gear in Body axes.
FGLocation holds an arbitrary location in the Earth centered Earth fixed reference frame (ECEF).
const FGMatrix33 & GetTec2l(void) const
Transform matrix from the earth centered to local horizontal frame.
FGLocation LocalToLocation(const FGColumnVector3 &lvec) const
Conversion from Local frame coordinates to a location in the earth centered and fixed frame.
double GetRadius() const
Get the distance from the center of the earth in feet.
double GetLongitude() const
Get the longitude.
FGColumnVector3 LocationToLocal(const FGColumnVector3 &ecvec) const
Conversion from a location in the earth centered and fixed frame to local horizontal frame coordinate...
double GetLatitude() const
Get the GEOCENTRIC latitude in radians.
double GetSeaLevelRadius(void) const
Get the sea level radius in feet below the current location.
Handles matrix math operations.
FGQuaternion GetQuaternion(void) const
Returns the quaternion associated with this direction cosine (rotation) matrix.
Models a Supercharged Piston engine.
double getExhaustGasTemp_degF(void) const
double getOilPressure_psi(void) const
double getOilTemp_degF(void) const
double getRPM(void) const
int GetMagnetos(void) const
double getCylinderHeadTemp_degF(void) const
void SetMagnetos(int magnetos)
double getManifoldPressure_inHg(void) const
FGPropeller models a propeller given the tabular data for Ct (thrust) and Cp (power),...
bool GetFeather(void) const
Returns true if the propeller is in feathered position.
double GetTorque(void) const
Retrieves the Torque in foot-pounds (Don't you love the English system?)
double GetPitch(void) const
Retrieves the pitch of the propeller in degrees.
Class wrapper for property handling.
Models the Quaternion representation of rotations.
const FGMatrix33 & GetT(void) const
Transformation matrix.
FGTable(const FGTable &table)
This is the very important copy constructor.
void SetUnusableVolume(double volume)
Sets the volume of unusable fuel in the tank.
double GetUnusableVolume(void) const
Returns the unusable volume of fuel in the tank.
double GetTemperature_degC(void) const
Gets the temperature of the fuel.
double GetContents(void) const
Gets the contents of the tank.
void SetDensity(double d)
Sets the fuel density.
double GetCapacityGallons(void) const
Gets the capacity of the tank.
FGColumnVector3 GetXYZ(void) const
void SetContents(double amount)
double GetDensity(void) const
Returns the fuel density.
Base class for specific thrusting devices such as propellers, nozzles, etc.
virtual double GetRPM(void) const
double GetThrust(void) const
The trimming routine for JSBSim.
bool DoTrim(void)
Execute the trim.
void Report(void)
Print the results of the trim.
void TrimStats()
Iteration statistics.
This class models a turbine engine.
bool GetAugmentation(void) const
double GetInlet(void) const
bool GetInjection(void) const
void SetReverse(bool reversed)
double GetNozzle(void) const
double GetEPR(void) const
void SetAugmentation(bool augmentation)
int GetIgnition(void) const
bool GetReversed(void) const
void SetCutoff(bool cutoff)
double GetEGT(void) const
void SetIgnition(int ignition)
bool GetCutoff(void) const
double getOilPressure_psi() const
void SetCondition(bool c)
double getOilPressure_psi() const
double GetEngStarting(void) const
int GetCondition(void) const
bool GetReversed(void) const
bool GetIeluIntervent(void) const
double getOilTemp_degF(void)
void SetGeneratorPower(bool gp)
bool GetGeneratorPower(void) const
bool GetCutoff(void) const
void SetReverse(bool reversed)
void SetCutoff(bool cutoff)
double GetITT(void) const
std::string fgGetString(const char *name, const char *defaultValue)
Get a string value for a property.
double DotProduct(const FGColumnVector3 &v1, const FGColumnVector3 &v2)
Dot product of two vectors Compute and return the euclidean dot (or scalar) product of two vectors v1...
bool fgSetDouble(const char *name, double defaultValue)
Set a double 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.
double fgGetDouble(const char *name, double defaultValue)
Get a double value for a property.
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
JSBSim Message structure.
enum JSBSim::FGJSBBase::Message::mType type