FlightGear next
JSBSim.cxx
Go to the documentation of this file.
1/*
2 * SPDX-FileName: JSBsim.cxx
3 * SPDX-FileComment: interface to the JSBsim flight model
4 * SPDX-FileCopyrightText: Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8#ifdef HAVE_CONFIG_H
9# include <config.h>
10#endif
11
12#include <simgear/compiler.h>
13#include <simgear/sg_inlines.h>
14
15#include <cstdlib> // size_t
16#include <string>
17
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>
24
25#include <FDM/flight.hxx>
27
28#include <Aircraft/controls.hxx>
29#include <Main/globals.hxx>
30#include <Main/fg_props.hxx>
31
32#include "JSBSim.hxx"
63
64using namespace JSBSim;
65
66static inline double
67FMAX (double a, double b)
68{
69 return a > b ? a : b;
70}
71
73public:
74 FGFSGroundCallback(FGJSBsim* ifc) : mInterface(ifc) {}
76
78 virtual double GetAltitude(const FGLocation& l) const {
79 double pt[3] = { SG_FEET_TO_METER*l(FGJSBBase::eX),
80 SG_FEET_TO_METER*l(FGJSBBase::eY),
81 SG_FEET_TO_METER*l(FGJSBBase::eZ) };
82 double lat, lon, alt;
83 sgCartToGeod( pt, &lat, &lon, &alt);
84 return alt * SG_METER_TO_FEET;
85 }
86
88 double GetAGLevel(double t, const FGLocation& l, FGLocation& cont,
90 const override {
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);
94 n = FGColumnVector3( normal[0], normal[1], normal[2] );
95 v = FGColumnVector3( vel[0], vel[1], vel[2] );
96 w = FGColumnVector3( angularVel[0], angularVel[1], angularVel[2] );
97 cont = FGColumnVector3( contact[0], contact[1], contact[2] );
98 return agl;
99 }
100
101private:
102 FGJSBsim* mInterface;
103};
104
105// FG uses a squared normalized magnitude for turbulence
106// this lookup table maps fg's severity levels
107// none(0), light(1/3), moderate(2/3) and severe(3/3)
108// to the POE table indexes 0, 3, 4 and 7
110public:
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;
116 }
117};
118
119/******************************************************************************/
120std::map<std::string,int> FGJSBsim::TURBULENCE_TYPE_NAMES;
121
123
125 : FGInterface(dt)
126{
127 bool result;
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;
134 }
135
136 // Set up the debugging level
137 // FIXME: this will not respond to
138 // runtime changes
139
140 if ((sglog().get_log_classes() & SG_FLIGHT) != 0) {
141
142 // do a rough-and-ready mapping to
143 // the levels documented in FGFDMExec.h
144 switch (sglog().get_log_priority()) {
145 case SG_BULK:
147 break;
148 case SG_DEBUG:
150 case SG_INFO:
151 case SG_WARN:
152 case SG_ALERT:
153 case SG_POPUP:
155 break;
156
157 default:
158 // silence warning about unhandled cases
160 break;
161 }
162 } else {
163 // if flight is excluded, don't bother
165 }
166
167 PropertyManager = new FGPropertyManager( (FGPropertyNode*)globals->get_props() );
168 fdmex = new FGFDMExec( PropertyManager );
169 fdmex->Hold();
170
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();
183
184 // Register ground callback.
185 Inertial->SetGroundCallback( new FGFSGroundCallback(this) );
186
187 fgic=fdmex->GetIC();
188 needTrim=true;
189
190 SGPath aircraft_path( fgGetString("/sim/aircraft-dir") );
191
192 SGPath engine_path( fgGetString("/sim/fg-root") );
193 engine_path.append( "Aircraft/Generic/JSBSim/Engines" );
194
195 SGPath systems_path( fgGetString("/sim/fg-root") );
196 systems_path.append( "Aircraft/Generic/JSBSim/Systems" );
197
198// deprecate sim-time-sec for simulation/sim-time-sec
199// remove alias with increased configuration file version number (2.1 or later)
200 SGPropertyNode * node = fgGetNode("/fdm/jsbsim/simulation/sim-time-sec");
201 fgGetNode("/fdm/jsbsim/sim-time-sec", true)->alias(node, false);
202 // end of sim-time-sec deprecation patch
203
204 _ai_wake_enabled = fgGetNode("fdm/ai-wake/enabled", true);
205
206 terrain = fgGetNode("/sim/fdm/surface", true);
207
208 fdmex->Setdt( dt );
209
210 result = fdmex->LoadModel( aircraft_path, engine_path, systems_path,
211 fgGetString("/sim/aero"), false );
212
213 if (result) {
214 SG_LOG( SG_FLIGHT, SG_INFO, " loaded aero.");
215 } else {
216 SG_LOG( SG_FLIGHT, SG_INFO,
217 " aero does not exist (you may have mis-typed the name).");
218 throw(-1);
219 }
220
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 ..." );
224
225 int Neng = Propulsion->GetNumEngines();
226 SG_LOG( SG_FLIGHT, SG_INFO, "num engines = " << Neng );
227
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!");
234 exit(-1);
235 }
236
237 init_gear();
238
239 // Set initial fuel levels if provided.
240 for (unsigned int i = 0; i < Propulsion->GetNumTanks(); i++) {
241 double d;
242 SGPropertyNode * node = fgGetNode("/consumables/fuel/tank", i, true);
243 FGTank* tank = Propulsion->GetTank(i);
244 SGPropertyNode * prop = node->getNode( "density-ppg", true );
245
246 d = prop->getDoubleValue();
247 if( d > 0.0 ) {
248 tank->SetDensity( d );
249 } else {
250 prop->setDoubleValue( SG_MAX2<double>(tank->GetDensity(), 0.1) );
251 }
252
253 prop = node->getNode( "level-lbs", true );
254 d = prop->getDoubleValue();
255 if( d > 0.0 ) {
256 tank->SetContents( d );
257 } else {
258 prop->setDoubleValue( tank->GetContents() );
259 }
260
261 prop = node->getNode( "unusable-gal_us", true );
262 d = prop->getDoubleValue();
263 if ( d > 0.0 ) {
264 tank->SetUnusableVolume( d );
265 } else {
266 prop->setDoubleValue(tank->GetUnusableVolume());
267 }
268 /* Capacity is read-only in FGTank and can't be overwritten from FlightGear */
269 node->getNode("capacity-gal_us", true )->setDoubleValue( tank->GetCapacityGallons() );
270 }
271 Propulsion->SetFuelFreeze((fgGetNode("/sim/freeze/fuel",true))->getBoolValue());
272
273 fgSetDouble("/fdm/trim/pitch-trim", FCS->GetPitchTrimCmd());
274 fgSetDouble("/fdm/trim/throttle", FCS->GetThrottleCmd(0));
275 fgSetDouble("/fdm/trim/aileron", FCS->GetDaCmd());
276 fgSetDouble("/fdm/trim/rudder", FCS->GetDrCmd());
277
278 startup_trim = fgGetNode("/sim/presets/trim", true);
279
280 trimmed = fgGetNode("/fdm/trim/trimmed", true);
281 trimmed->setBoolValue(false);
282
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 );
287
288 stall_warning = fgGetNode("/sim/alarms/stall-warning",true);
289 stall_warning->setDoubleValue(0);
290
291
292 flap_pos_pct=fgGetNode("/surface-positions/flap-pos-norm",true);
293 elevator_pos_pct=fgGetNode("/surface-positions/elevator-pos-norm",true);
294 left_aileron_pos_pct
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);
299 speedbrake_pos_pct
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);
304
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);
312
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);
318
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);
321
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);
332
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);
336
337 slaved = fgGetNode("/sim/slaved/enabled", true);
338
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());
343 }
344
345 hook_root_struct = FGColumnVector3(
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;
351
352 crashed = false;
353
354 mesh = new AircraftMesh(fgGetDouble("/fdm/jsbsim/metrics/bw-ft"),
355 fgGetDouble("/fdm/jsbsim/metrics/cbarw-ft"),
356 fdmex->GetModelName());
357
358 // Trim once to initialize all output parameters
359 FGTrim *fgtrim = new FGTrim(fdmex,tFull);
360 fgtrim->DoTrim();
361 delete fgtrim;
362
363 std::string directive_file = fgGetString("/sim/jsbsim/output-directive-file");
364 if (!directive_file.empty())
365 fdmex->SetOutputDirectives(directive_file);
366}
367
368/******************************************************************************/
370{
371 delete fdmex;
372 delete PropertyManager;
373}
374
375/******************************************************************************/
376
377// Initialize the JSBsim flight model, dt is the time increment for
378// each subsequent iteration through the EOM
379
381{
382 SG_LOG( SG_FLIGHT, SG_INFO, "Starting and initializing JSBsim" );
383
384 // Explicitly call the superclass's
385 // init method first.
386
387 if (fgGetBool("/environment/params/control-fdm-atmosphere")) {
388 Atmosphere->SetTemperature(temperature->getDoubleValue(), get_Altitude(), FGAtmosphere::eCelsius);
389 Atmosphere->SetPressureSL(FGAtmosphere::eInchesHg, pressureSL->getDoubleValue());
390 // initialize to no turbulence, these values get set in the update loop
391 Winds->SetTurbType(FGWinds::ttNone);
392 Winds->SetTurbGain(0.0);
393 Winds->SetTurbRate(0.0);
394 Winds->SetWindspeed20ft(0.0);
395 Winds->SetProbabilityOfExceedence(0.0);
396 }
397
398 fgic->SetWindNEDFpsIC(0.0, 0.0, 0.0);
399
400 SG_LOG(SG_FLIGHT,SG_INFO,"T,p,rho: " << Atmosphere->GetTemperature()
401 << ", " << Atmosphere->GetPressure()
402 << ", " << Atmosphere->GetDensity() );
403
404 FCS->SetDfPos( ofNorm, globals->get_controls()->get_flaps() );
405
406 needTrim = startup_trim->getBoolValue();
407 common_init();
408
410 fdmex->Resume();
411 fdmex->RunIC(); //loop JSBSim once w/o integrating
412 if (fgGetBool("/sim/presets/running")) {
413 Propulsion->InitRunning(-1);
414 for (unsigned int i = 0; i < Propulsion->GetNumEngines(); i++) {
415 FGPiston* eng = (FGPiston*)Propulsion->GetEngine(i);
416 globals->get_controls()->set_magnetos(i, eng->GetMagnetos());
417 globals->get_controls()->set_mixture(i, FCS->GetMixtureCmd(i));
418 }
419 }
420
421 if ( needTrim ) {
422 const FGLocation& cart = fgic->GetPosition();
423 double contact[3], d[3], vel[3];
424 update_ground_cache(cart, 0.01);
425
426 get_agl_ft(fdmex->GetSimTime(), cart, SG_METER_TO_FEET*2, contact, d, vel,
427 d);
428 double terrain_alt = sqrt(contact[0]*contact[0] + contact[1]*contact[1]
429 + contact[2]*contact[2]) - cart.GetSeaLevelRadius();
430
431 SG_LOG(SG_FLIGHT, SG_INFO, "Ready to trim, terrain elevation is: "
432 << terrain_alt );
433
434 if (fgGetBool("/sim/presets/onground")) {
435 FGColumnVector3 gndVelNED = cart.GetTec2l()
436 * FGColumnVector3(vel[0], vel[1], vel[2]);
437 fgic->SetVNorthFpsIC(gndVelNED(1));
438 fgic->SetVEastFpsIC(gndVelNED(2));
439 fgic->SetVDownFpsIC(gndVelNED(3));
440 }
441 do_trim();
442 needTrim = false;
443 }
444
445 copy_from_JSBsim(); //update the bus
446
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);
455
456 SG_LOG( SG_FLIGHT, SG_INFO, " Initialized JSBSim with:" );
457
458 switch(fgic->GetSpeedSet()) {
459 case setned:
460 SG_LOG(SG_FLIGHT,SG_INFO, " Vn,Ve,Vd= "
461 << Propagate->GetVel(FGJSBBase::eNorth) << ", "
462 << Propagate->GetVel(FGJSBBase::eEast) << ", "
463 << Propagate->GetVel(FGJSBBase::eDown) << " ft/s");
464 break;
465 case setuvw:
466 SG_LOG(SG_FLIGHT,SG_INFO, " U,V,W= "
467 << Propagate->GetUVW(1) << ", "
468 << Propagate->GetUVW(2) << ", "
469 << Propagate->GetUVW(3) << " ft/s");
470 break;
471 case setmach:
472 SG_LOG(SG_FLIGHT,SG_INFO, " Mach: "
473 << Auxiliary->GetMach() );
474 break;
475 case setvc:
476 default:
477 SG_LOG(SG_FLIGHT,SG_INFO, " Indicated Airspeed: "
478 << Auxiliary->GetVcalibratedKTS() << " knots" );
479 break;
480 }
481
482 stall_warning->setDoubleValue(0);
483
484 SG_LOG( SG_FLIGHT, SG_INFO, " Bank Angle: "
485 << Propagate->GetEuler(FGJSBBase::ePhi)*RADTODEG << " deg" );
486 SG_LOG( SG_FLIGHT, SG_INFO, " Pitch Angle: "
487 << Propagate->GetEuler(FGJSBBase::eTht)*RADTODEG << " deg" );
488 SG_LOG( SG_FLIGHT, SG_INFO, " True Heading: "
489 << Propagate->GetEuler(FGJSBBase::ePsi)*RADTODEG << " deg" );
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" );
497
498 SG_LOG( SG_FLIGHT, SG_INFO, " set dt" );
499
500 SG_LOG( SG_FLIGHT, SG_INFO, "Finished initializing JSBSim" );
501
502 SG_LOG( SG_FLIGHT, SG_INFO, "FGControls::get_gear_down()= " <<
503 globals->get_controls()->get_gear_down() );
504}
505
506/******************************************************************************/
507
509{
510 fdmex->Unbind();
512}
513
514/******************************************************************************/
515
516// Run an iteration of the EOM (equations of motion)
517void FGJSBsim::update( double dt )
518{
519 if(crashed) {
520 if(!fgGetBool("/sim/crashed"))
521 fgSetBool("/sim/crashed", true);
522 return;
523 }
524
525 if (is_suspended())
526 return;
527
528 int multiloop = _calc_multiloop(dt);
529 FGLocation cart = Auxiliary->GetLocationVRP();
530
531 update_ground_cache(cart, dt);
532
534
535 trimmed->setBoolValue(false);
536
537 for ( int i=0; i < multiloop; i++ ) {
538 if (!fdmex->Run()) {
539 // The property fdm/jsbsim/simulation/terminate has been set to true
540 // by the user. The sim is considered crashed.
541 crashed = true;
542 break;
543 }
544 update_external_forces(fdmex->GetSimTime() + i * fdmex->GetDeltaT());
545 }
546
548 while ((msg = fdmex->ProcessNextMessage()) != NULL) {
549// msg = fdmex->ProcessNextMessage();
550 switch (msg->type) {
552 if (msg->text == "Crash Detected: Simulation FREEZE.")
553 crashed = true;
554 SG_LOG( SG_FLIGHT, SG_INFO, msg->messageId << ": " << msg->text );
555 break;
557 SG_LOG( SG_FLIGHT, SG_INFO, msg->messageId << ": " << msg->text << " " << msg->bVal );
558 break;
560 SG_LOG( SG_FLIGHT, SG_INFO, msg->messageId << ": " << msg->text << " " << msg->iVal );
561 break;
563 SG_LOG( SG_FLIGHT, SG_INFO, msg->messageId << ": " << msg->text << " " << msg->dVal );
564 break;
565 default:
566 SG_LOG( SG_FLIGHT, SG_INFO, "Unrecognized message type." );
567 break;
568 }
569 }
570
572
573 // translate JSBsim back to FG structure so that the
574 // autopilot (and the rest of the sim can use the updated values
576}
577
578/******************************************************************************/
579
581{
582 fdmex->Hold();
583 SGSubsystem::suspend();
584}
585
586/******************************************************************************/
587
589{
590 fdmex->Resume();
591 SGSubsystem::resume();
592}
593
594/******************************************************************************/
595
596// Convert from the FGInterface struct to the JSBsim generic_ struct
597
599{
600 unsigned int i;
601
602 // copy control positions into the JSBsim structure
603
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() );
614
615 if (!override_fg_brake_prop->getBoolValue()) {
616 // Parking brake sets minimum braking
617 // level for mains.
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();
621
622 if (ab_brake_engaged->getBoolValue()) {
623 left_brake = ab_brake_left_pct->getDoubleValue();
624 right_brake = ab_brake_right_pct->getDoubleValue();
625 }
626
627 FCS->SetLBrake(FMAX(left_brake, parking_brake));
628 FCS->SetRBrake(FMAX(right_brake, parking_brake));
629
630 FCS->SetCBrake( 0.0 );
631 // FCS->SetCBrake( globals->get_controls()->get_brake(2) );
632 }
633
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);
637
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));
642
643 switch (Propulsion->GetEngine(i)->GetType()) {
645 { // FGPiston code block
646 FGPiston* eng = (FGPiston*)Propulsion->GetEngine(i);
647 eng->SetMagnetos( globals->get_controls()->get_magnetos(i) );
648 break;
649 } // end FGPiston code block
651 { // FGTurbine code block
652 FGTurbine* eng = (FGTurbine*)Propulsion->GetEngine(i);
653 eng->SetAugmentation( globals->get_controls()->get_augmentation(i) );
654 eng->SetReverse( globals->get_controls()->get_reverser(i) );
655 //eng->SetInjection( globals->get_controls()->get_water_injection(i) );
656 eng->SetCutoff( globals->get_controls()->get_cutoff(i) );
657 eng->SetIgnition( globals->get_controls()->get_ignition(i) );
658 break;
659 } // end FGTurbine code block
661 { // FGRocket code block
662// FGRocket* eng = (FGRocket*)Propulsion->GetEngine(i);
663 break;
664 } // end FGRocket code block
666 { // FGTurboProp code block
667 FGTurboProp* eng = (FGTurboProp*)Propulsion->GetEngine(i);
668 eng->SetReverse( globals->get_controls()->get_reverser(i) );
669 eng->SetCutoff( globals->get_controls()->get_cutoff(i) );
670 // eng->SetIgnition( globals->get_controls()->get_ignition(i) );
671
672 eng->SetGeneratorPower( globals->get_controls()->get_generator_breaker(i) );
673 eng->SetCondition( globals->get_controls()->get_condition(i) );
674 break;
675 } // end FGTurboProp code block
676 default:
677 break;
678 }
679
680 { // FGEngine code block
681 FGEngine* eng = Propulsion->GetEngine(i);
682
683 eng->SetStarter( globals->get_controls()->get_starter(i) );
684 eng->SetRunning( node->getBoolValue("running") );
685 } // end FGEngine code block
686 }
687
688 Atmosphere->SetTemperature(temperature->getDoubleValue(), get_Altitude(), FGAtmosphere::eCelsius);
689 Atmosphere->SetPressureSL(FGAtmosphere::eInchesHg, pressureSL->getDoubleValue());
690 static_cast<FGStandardAtmosphere*>(Atmosphere)->SetDewPoint(FGAtmosphere::eCelsius,
691 dew_point->getDoubleValue());
692
693 Winds->SetTurbType((FGWinds::tType)TURBULENCE_TYPE_NAMES[turbulence_model->getStringValue()]);
694 switch( Winds->GetTurbType() ) {
696 case FGWinds::ttCulp: {
697 double tmp = turbulence_gain->getDoubleValue();
698 Winds->SetTurbGain(tmp * tmp * 100.0);
699 Winds->SetTurbRate(turbulence_rate->getDoubleValue());
700 break;
701 }
703 case FGWinds::ttTustin: {
704 // milspec turbulence: 3=light, 4=moderate, 6=severe turbulence
705 // turbulence_gain normalized: 0: none, 1/3: light, 2/3: moderate, 3/3: severe
706 double tmp = turbulence_gain->getDoubleValue();
707 Winds->SetProbabilityOfExceedence(
708 SGMiscd::roundToInt(TurbulenceSeverityTable.GetValue( tmp ) )
709 );
710 Winds->SetWindspeed20ft(ground_wind->getDoubleValue());
711 break;
712 }
713
714 default:
715 break;
716 }
717
718 Winds->SetWindNED( -wind_from_north->getDoubleValue(),
719 -wind_from_east->getDoubleValue(),
720 -wind_from_down->getDoubleValue() );
721// SG_LOG(SG_FLIGHT,SG_INFO, "Wind NED: "
722// << get_V_north_airmass() << ", "
723// << get_V_east_airmass() << ", "
724// << get_V_down_airmass() );
725
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");
730
731 if (fuelDensity < 0.1)
732 fuelDensity = 6.0; // Use average fuel value
733
734 tank->SetDensity(fuelDensity);
735 tank->SetContents(node->getDoubleValue("level-lbs"));
736 }
737
738 Propulsion->SetFuelFreeze((fgGetNode("/sim/freeze/fuel",true))->getBoolValue());
739 fdmex->SetChild(slaved->getBoolValue());
740
741 return true;
742}
743
744/******************************************************************************/
745
746// Convert from the JSBsim generic_ struct to the FGInterface struct
747
749{
750 unsigned int i, j;
751/*
752 _set_Inertias( MassBalance->GetMass(),
753 MassBalance->GetIxx(),
754 MassBalance->GetIyy(),
755 MassBalance->GetIzz(),
756 MassBalance->GetIxz() );
757*/
758 _set_CG_Position( MassBalance->GetXYZcg(1),
759 MassBalance->GetXYZcg(2),
760 MassBalance->GetXYZcg(3) );
761
762 _set_Accels_Body( Accelerations->GetBodyAccel(1),
763 Accelerations->GetBodyAccel(2),
764 Accelerations->GetBodyAccel(3) );
765
766 _set_Accels_CG_Body_N ( Auxiliary->GetNcg(1),
767 Auxiliary->GetNcg(2),
768 Auxiliary->GetNcg(3) );
769
770 _set_Accels_Pilot_Body( Auxiliary->GetPilotAccel(1),
771 Auxiliary->GetPilotAccel(2),
772 Auxiliary->GetPilotAccel(3) );
773
774 _set_Nlf( Auxiliary->GetNlf() );
775
776 // Velocities
777
778 _set_Velocities_Local( Propagate->GetVel(FGJSBBase::eNorth),
779 Propagate->GetVel(FGJSBBase::eEast),
780 Propagate->GetVel(FGJSBBase::eDown) );
781
782 _set_Velocities_Body( Propagate->GetUVW(1),
783 Propagate->GetUVW(2),
784 Propagate->GetUVW(3) );
785
786 // Make the HUD work ...
787 _set_Velocities_Ground( Propagate->GetVel(FGJSBBase::eNorth),
788 Propagate->GetVel(FGJSBBase::eEast),
789 -Propagate->GetVel(FGJSBBase::eDown) );
790
791 _set_V_rel_wind( Auxiliary->GetVt() );
792
793 _set_V_equiv_kts( Auxiliary->GetVequivalentKTS() );
794
795 _set_V_calibrated_kts( Auxiliary->GetVcalibratedKTS() );
796
797 _set_V_ground_speed( Auxiliary->GetVground() );
798
799 _set_Omega_Body( Propagate->GetPQR(FGJSBBase::eP),
800 Propagate->GetPQR(FGJSBBase::eQ),
801 Propagate->GetPQR(FGJSBBase::eR) );
802
803 _set_Euler_Rates( Auxiliary->GetEulerRates(FGJSBBase::ePhi),
804 Auxiliary->GetEulerRates(FGJSBBase::eTht),
805 Auxiliary->GetEulerRates(FGJSBBase::ePsi) );
806
807 _set_Mach_number( Auxiliary->GetMach() );
808
809 // Positions of Visual Reference Point
810 FGLocation l = Auxiliary->GetLocationVRP();
811 _updatePosition(SGGeoc::fromRadFt( l.GetLongitude(), l.GetLatitude(),
812 l.GetRadius() ));
813
814 _set_Altitude_AGL( Propagate->GetDistanceAGL() );
815 {
816 double contact[3], d[3], sd, t;
817 is_valid_m(&t, d, &sd);
818 get_agl_ft(t, l, SG_METER_TO_FEET*2, contact, d, d, d);
819 double rwrad
820 = FGColumnVector3( contact[0], contact[1], contact[2] ).Magnitude();
822 }
823
824 _set_Euler_Angles( Propagate->GetEuler(FGJSBBase::ePhi),
825 Propagate->GetEuler(FGJSBBase::eTht),
826 Propagate->GetEuler(FGJSBBase::ePsi) );
827
828 _set_Alpha( Auxiliary->Getalpha() );
829 _set_Beta( Auxiliary->Getbeta() );
830
831
832 _set_Gamma_vert_rad( Auxiliary->GetGamma() );
833
834 _set_Earth_position_angle( Propagate->GetEarthPositionAngle() );
835
836 _set_Climb_Rate( Propagate->Gethdot() );
837
838 const FGMatrix33& Tl2b = Propagate->GetTl2b();
839 for ( i = 1; i <= 3; i++ ) {
840 for ( j = 1; j <= 3; j++ ) {
841 _set_T_Local_to_Body( i, j, Tl2b(i,j) );
842 }
843 }
844
845 // Copy the engine values from JSBSim.
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();
850
851 switch (Propulsion->GetEngine(i)->GetType()) {
853 { // FGPiston code block
854 FGPiston* eng = (FGPiston*)Propulsion->GetEngine(i);
855 node->setDoubleValue("egt-degf", eng->getExhaustGasTemp_degF());
856 node->setDoubleValue("oil-temperature-degf", eng->getOilTemp_degF());
857 node->setDoubleValue("oil-pressure-psi", eng->getOilPressure_psi());
858 node->setDoubleValue("mp-osi", eng->getManifoldPressure_inHg());
859 // NOTE: mp-osi is not in ounces per square inch.
860 // This error is left for reasons of backwards compatibility with
861 // existing FlightGear sound and instrument configurations.
862 node->setDoubleValue("mp-inhg", eng->getManifoldPressure_inHg());
863 node->setDoubleValue("cht-degf", eng->getCylinderHeadTemp_degF());
864 node->setDoubleValue("rpm", eng->getRPM());
865 } // end FGPiston code block
866 break;
868 { // FGRocket code block
869// FGRocket* eng = (FGRocket*)Propulsion->GetEngine(i);
870 } // end FGRocket code block
871 break;
873 { // FGTurbine code block
874 FGTurbine* eng = (FGTurbine*)Propulsion->GetEngine(i);
875 node->setDoubleValue("n1", eng->GetN1());
876 node->setDoubleValue("n2", eng->GetN2());
877 node->setDoubleValue("egt-degf", 32 + eng->GetEGT()*9/5);
878 node->setBoolValue("augmentation", eng->GetAugmentation());
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());
883 node->setDoubleValue("oil-pressure-psi", eng->getOilPressure_psi());
884 node->setBoolValue("reversed", eng->GetReversed());
885 node->setBoolValue("cutoff", eng->GetCutoff());
886 node->setDoubleValue("epr", eng->GetEPR());
887 globals->get_controls()->set_reverser(i, eng->GetReversed() );
888 globals->get_controls()->set_cutoff(i, eng->GetCutoff() );
889 globals->get_controls()->set_water_injection(i, eng->GetInjection() );
890 globals->get_controls()->set_augmentation(i, eng->GetAugmentation() );
891 } // end FGTurbine code block
892 break;
894 { // FGTurboProp code block
895 FGTurboProp* eng = (FGTurboProp*)Propulsion->GetEngine(i);
896 node->setDoubleValue("n1", eng->GetN1());
897 //node->setDoubleValue("n2", eng->GetN2());
898 node->setDoubleValue("itt_degf", 32 + eng->GetITT()*9/5);
899 // node->setBoolValue("ignition", eng->GetIgnition() != 0);
900 // node->setDoubleValue("nozzle-pos-norm", eng->GetNozzle());
901 // node->setDoubleValue("inlet-pos-norm", eng->GetInlet());
902 node->setDoubleValue("oil-pressure-psi", eng->getOilPressure_psi());
903 node->setBoolValue("reversed", eng->GetReversed());
904 node->setBoolValue("cutoff", eng->GetCutoff());
905 node->setBoolValue("starting", eng->GetEngStarting());
906 node->setBoolValue("generator-power", eng->GetGeneratorPower());
907 node->setBoolValue("damaged", eng->GetCondition() != 0);
908 node->setBoolValue("ielu-intervent", eng->GetIeluIntervent());
909 node->setDoubleValue("oil-temperature-degf", eng->getOilTemp_degF());
910// node->setBoolValue("onfire", eng->GetFire());
911 globals->get_controls()->set_reverser(i, eng->GetReversed() );
912 globals->get_controls()->set_cutoff(i, eng->GetCutoff() );
913 } // end FGTurboProp code block
914 break;
916 { // FGElectric code block
917 FGElectric* eng = (FGElectric*)Propulsion->GetEngine(i);
918 node->setDoubleValue("rpm", eng->getRPM());
919 } // end FGElectric code block
920 break;
922 break;
923 }
924
925 { // FGEngine code block
926 FGEngine* eng = Propulsion->GetEngine(i);
927 node->setDoubleValue("fuel-flow-gph", eng->getFuelFlow_gph());
928 node->setDoubleValue("thrust_lb", thruster->GetThrust());
929 node->setDoubleValue("fuel-flow_pph", eng->getFuelFlow_pph());
930 node->setBoolValue("running", eng->GetRunning());
931 node->setBoolValue("starter", eng->GetStarter());
932 node->setBoolValue("cranking", eng->GetCranking());
933 globals->get_controls()->set_starter(i, eng->GetStarter() );
934 } // end FGEngine code block
935
936 switch (thruster->GetType()) {
938 { // FGNozzle code block
939// FGNozzle* noz = (FGNozzle*)thruster;
940 } // end FGNozzle code block
941 break;
943 { // FGPropeller code block
944 FGPropeller* prop = (FGPropeller*)thruster;
945 tnode->setDoubleValue("rpm", thruster->GetRPM());
946 tnode->setDoubleValue("pitch", prop->GetPitch());
947 tnode->setDoubleValue("torque", prop->GetTorque());
948 tnode->setBoolValue("feathered", prop->GetFeather());
949 } // end FGPropeller code block
950 break;
952 { // FGRotor code block
953// FGRotor* rotor = (FGRotor*)thruster;
954 } // end FGRotor code block
955 break;
957 { // Direct code block
958 } // end Direct code block
959 break;
960 }
961
962 }
963
964 // Copy the fuel levels from JSBSim if fuel
965 // freeze not enabled.
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);
970 double contents = tank->GetContents();
971 double temp = tank->GetTemperature_degC();
972 double fuelDensity = tank->GetDensity();
973
974 if (fuelDensity < 0.1)
975 fuelDensity = 6.0; // Use average fuel value
976
977 node->setDoubleValue("density-ppg" , fuelDensity);
978 node->setDoubleValue("level-lbs", contents);
979 if (temp != -9999.0) node->setDoubleValue("temperature_degC", temp);
980
981 node->setDoubleValue("arm-in", tank->GetXYZ(FGJSBBase::eX ) );
982 }
983 }
984
985 update_gear();
986
987 stall_warning->setDoubleValue( Aerodynamics->GetStallWarn() );
988
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() );
998
999 // force a sim crashed if crashed (altitude AGL < 0)
1000 if (get_Altitude_AGL() < -100.0) {
1001 fdmex->SuspendIntegration();
1002 crashed = true;
1003 }
1004
1005 return true;
1006}
1007
1008
1010{
1011 // ToDo: handle this properly
1012 fdmex->DisableOutput();
1013 return false;
1014}
1015
1016
1018{
1019 if (state) {
1020 fdmex->EnableOutput();
1021 return true;
1022 } else {
1023 fdmex->DisableOutput();
1024 return false;
1025 }
1026}
1027
1028
1029//Positions
1031{
1032 double alt = altitude->getDoubleValue();
1033 double sea_level_radius_meters, lat_geoc;
1034
1035 if ( alt < -9990 ) alt = 0.0;
1036
1037 SG_LOG(SG_FLIGHT,SG_INFO,"FGJSBsim::set_Latitude: " << lat );
1038 SG_LOG(SG_FLIGHT,SG_INFO," cur alt (ft) = " << alt );
1039
1040 if (needTrim)
1041 fgic->SetGeodLatitudeRadIC( lat );
1042 else {
1043 sgGeodToGeoc( lat, alt * SG_FEET_TO_METER,
1044 &sea_level_radius_meters, &lat_geoc );
1045
1046 double sea_level_radius_ft = sea_level_radius_meters * SG_METER_TO_FEET;
1047 _set_Sea_level_radius( sea_level_radius_ft );
1048
1049 Propagate->SetLatitude(lat_geoc);
1050 }
1051
1053}
1054
1055
1057{
1058 SG_LOG(SG_FLIGHT,SG_INFO,"FGJSBsim::set_Longitude: " << lon );
1059
1060 if (needTrim)
1061 fgic->SetLongitudeRadIC(lon);
1062 else
1063 Propagate->SetLongitude(lon);
1064
1066}
1067
1068// Sets the altitude above sea level.
1070{
1071 SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Altitude: " << alt );
1072
1073 if (needTrim)
1074 fgic->SetAltitudeASLFtIC(alt);
1075 else
1076 Propagate->SetAltitudeASL(alt);
1077
1079}
1080
1082{
1083 SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_V_calibrated_kts: " << vc );
1084
1085 if (needTrim)
1086 fgic->SetVcalibratedKtsIC(vc);
1087 else {
1088 double p=pressure->getDoubleValue();
1089 double mach = FGJSBBase::MachFromVcalibrated(vc, p);
1090 double temp = 1.8*(temperature->getDoubleValue()+273.15);
1091 double soundSpeed = sqrt(1.4*1716.0*temp);
1092 FGColumnVector3 vUVW = Propagate->GetUVW();
1093 vUVW.Normalize();
1094 vUVW *= mach * soundSpeed;
1095 Propagate->SetUVW(1, vUVW(1));
1096 Propagate->SetUVW(2, vUVW(2));
1097 Propagate->SetUVW(3, vUVW(3));
1098 }
1099
1101}
1102
1104{
1105 SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Mach_number: " << mach );
1106
1107 if (needTrim)
1108 fgic->SetMachIC(mach);
1109 else {
1110 double temp = 1.8*(temperature->getDoubleValue()+273.15);
1111 double soundSpeed = sqrt(1.4*1716.0*temp);
1112 FGColumnVector3 vUVW = Propagate->GetUVW();
1113 vUVW.Normalize();
1114 vUVW *= mach * soundSpeed;
1115 Propagate->SetUVW(1, vUVW(1));
1116 Propagate->SetUVW(2, vUVW(2));
1117 Propagate->SetUVW(3, vUVW(3));
1118 }
1119
1121}
1122
1123void FGJSBsim::set_Velocities_Local( double north, double east, double down )
1124{
1125 SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Velocities_Local: "
1126 << north << ", " << east << ", " << down );
1127
1128 if (needTrim) {
1129 fgic->SetVNorthFpsIC(north);
1130 fgic->SetVEastFpsIC(east);
1131 fgic->SetVDownFpsIC(down);
1132 }
1133 else {
1134 FGColumnVector3 vNED(north, east, down);
1135 FGColumnVector3 vUVW = Propagate->GetTl2b() * vNED;
1136 Propagate->SetUVW(1, vUVW(1));
1137 Propagate->SetUVW(2, vUVW(2));
1138 Propagate->SetUVW(3, vUVW(3));
1139 }
1140
1141 FGInterface::set_Velocities_Local(north, east, down);
1142}
1143
1144void FGJSBsim::set_Velocities_Body( double u, double v, double w)
1145{
1146 SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Velocities_Body: "
1147 << u << ", " << v << ", " << w );
1148
1149 if (needTrim) {
1150 fgic->SetUBodyFpsIC(u);
1151 fgic->SetVBodyFpsIC(v);
1152 fgic->SetWBodyFpsIC(w);
1153 }
1154 else {
1155 Propagate->SetUVW(1, u);
1156 Propagate->SetUVW(2, v);
1157 Propagate->SetUVW(3, w);
1158 }
1159
1161}
1162
1163//Euler angles
1164void FGJSBsim::set_Euler_Angles( double phi, double theta, double psi )
1165{
1166 SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Euler_Angles: "
1167 << phi << ", " << theta << ", " << psi );
1168
1169 if (needTrim) {
1170 fgic->SetThetaRadIC(theta);
1171 fgic->SetPhiRadIC(phi);
1172 fgic->SetPsiRadIC(psi);
1173 }
1174 else {
1175 FGQuaternion quat(phi, theta, psi);
1176 FGMatrix33 Tl2b = quat.GetT();
1177 FGMatrix33 Ti2b = Tl2b*Propagate->GetTi2l();
1178 FGQuaternion Qi = Ti2b.GetQuaternion();
1179 Propagate->SetInertialOrientation(Qi);
1180 }
1181
1182 FGInterface::set_Euler_Angles(phi, theta, psi);
1183}
1184
1185//Flight Path
1187{
1188 SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Climb_Rate: " << roc );
1189
1190 //since both climb rate and flight path angle are set in the FG
1191 //startup sequence, something is needed to keep one from cancelling
1192 //out the other.
1193 if( fabs(roc) > 1 && fabs(fgic->GetFlightPathAngleRadIC()) < 0.01 ) {
1194 if (needTrim)
1195 fgic->SetClimbRateFpsIC(roc);
1196 else {
1197 FGColumnVector3 vNED = Propagate->GetVel();
1198 vNED(FGJSBBase::eDown) = -roc;
1199 FGColumnVector3 vUVW = Propagate->GetTl2b() * vNED;
1200 Propagate->SetUVW(1, vUVW(1));
1201 Propagate->SetUVW(2, vUVW(2));
1202 Propagate->SetUVW(3, vUVW(3));
1203 }
1204
1206 }
1207}
1208
1210{
1211 SG_LOG(SG_FLIGHT,SG_INFO, "FGJSBsim::set_Gamma_vert_rad: " << gamma );
1212
1213 if( !(fabs(gamma) < 0.01 && fabs(fgic->GetClimbRateFpsIC()) > 1) ) {
1214 if (needTrim)
1215 fgic->SetFlightPathAngleRadIC(gamma);
1216 else {
1217 FGColumnVector3 vNED = Propagate->GetVel();
1218 double vt = vNED.Magnitude();
1219 vNED(FGJSBBase::eDown) = -vt * sin(gamma);
1220 FGColumnVector3 vUVW = Propagate->GetTl2b() * vNED;
1221 Propagate->SetUVW(1, vUVW(1));
1222 Propagate->SetUVW(2, vUVW(2));
1223 Propagate->SetUVW(3, vUVW(3));
1224 }
1225
1227 }
1228}
1229
1230void FGJSBsim::init_gear(void )
1231{
1233 int Ngear=GroundReactions->GetNumGearUnits();
1234 double max = 1.0;
1235 for (int i=0;i<Ngear;i++) {
1236 FGLGear *gear = gr->GetGearUnit(i);
1237 SGPropertyNode * node = fgGetNode("gear/gear", i, true);
1238 // coordinates are in feet so convert
1239 node->setDoubleValue("xoffset-in", gear->GetBodyLocation()(1) * 12);
1240 node->setDoubleValue("yoffset-in", gear->GetBodyLocation()(2) * 12);
1241 node->setDoubleValue("zoffset-in", gear->GetBodyLocation()(3) * 12);
1242
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);
1246
1247 node->setBoolValue("wow", gear->GetWOW());
1248 node->setDoubleValue("rollspeed-ms", gear->GetWheelRollVel() * SG_FEET_TO_METER);
1249 node->setBoolValue("has-brake", gear->GetBrakeGroup() > 0);
1250 node->setDoubleValue("position-norm", gear->GetGearUnitPos());
1251// node->setDoubleValue("tire-pressure-norm", gear->GetTirePressure());
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;
1257 }
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());
1261 if ( gear->GetSteerable() )
1262 node->setDoubleValue("steering-norm", gear->GetSteerNorm());
1263 }
1264}
1265
1266void FGJSBsim::update_gear(void)
1267{
1268 FGGroundReactions* gr=fdmex->GetGroundReactions();
1269 int Ngear=GroundReactions->GetNumGearUnits();
1270 double max = 1.0;
1271 for (int i=0;i<Ngear;i++) {
1272 FGLGear *gear = gr->GetGearUnit(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());
1277// gear->SetTirePressure(node->getDoubleValue("tire-pressure-norm"));
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;
1283 }
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());
1287 if ( gear->GetSteerable() )
1288 node->setDoubleValue("steering-norm", gear->GetSteerNorm());
1289 }
1290}
1291
1292void FGJSBsim::do_trim(void)
1293{
1294 FGTrim *fgtrim;
1295
1296 if ( fgGetBool("/sim/presets/onground") )
1297 {
1298 fgtrim = new FGTrim(fdmex,tGround);
1299 } else {
1300 fgtrim = new FGTrim(fdmex,tFull);
1301 }
1302
1303 if ( !fgtrim->DoTrim() ) {
1304 fgtrim->Report();
1305 fgtrim->TrimStats();
1306 } else {
1307 trimmed->setBoolValue(true);
1308 }
1309 delete fgtrim;
1310
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() );
1315
1316 globals->get_controls()->set_elevator_trim(FCS->GetPitchTrimCmd());
1317 globals->get_controls()->set_elevator(FCS->GetDeCmd());
1318 for( unsigned i = 0; i < Propulsion->GetNumEngines(); i++ )
1319 globals->get_controls()->set_throttle(i, FCS->GetThrottleCmd(i));
1320
1321 globals->get_controls()->set_aileron(FCS->GetDaCmd());
1322 globals->get_controls()->set_rudder( -FCS->GetDrCmd());
1323
1324 SG_LOG( SG_FLIGHT, SG_INFO, " Trim complete" );
1325}
1326
1327bool FGJSBsim::update_ground_cache(const FGLocation& cart, double dt)
1328{
1329 // Compute the radius of the aircraft. That is the radius of a ball
1330 // where all gear units are in. At the moment it is at least 10ft ...
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();
1335 double r = bl.Magnitude();
1336 if (acrad < r)
1337 acrad = r;
1338 }
1339
1340 // Compute the potential movement of this aircraft and query for the
1341 // ground in this area.
1342 double groundCacheRadius = acrad + 2*dt*Propagate->GetUVW().Magnitude();
1343
1344 double cart_pos[3] {cart(1), cart(2), cart(3)};
1345 double t0 = fdmex->GetSimTime();
1346 bool cache_ok = prepare_ground_cache_ft( t0, t0 + dt, cart_pos,
1347 groundCacheRadius );
1348 if (!cache_ok) {
1349 //SG_LOG(SG_FLIGHT, SG_WARN,
1350 // "FGInterface is being called without scenery below the aircraft!");
1351
1352 //SG_LOG(SG_FLIGHT, SG_WARN, "altitude = "
1353 // << fgic->GetAltitudeASLFtIC());
1354
1355 //SG_LOG(SG_FLIGHT, SG_WARN, "sea level radius = "
1356 // << get_Sea_level_radius());
1357
1358 //SG_LOG(SG_FLIGHT, SG_WARN, "latitude = "
1359 // << fgic->GetLatitudeRadIC());
1360
1361 //SG_LOG(SG_FLIGHT, SG_WARN, "longitude = "
1362 // << fgic->GetLongitudeRadIC());
1363 }
1364
1365 return cache_ok;
1366}
1367
1368double
1369FGJSBsim::get_agl_ft(double t, const FGColumnVector3& loc, double alt_off,
1370 double contact[3], double normal[3], double vel[3],
1371 double angularVel[3])
1372{
1373 const simgear::BVHMaterial* material = nullptr;
1374 simgear::BVHNode::Id id;
1375 double pt[3] {loc(1), loc(2), loc(3)};
1376
1377 if (!FGInterface::get_agl_ft(t, pt, alt_off, contact, normal, vel,
1378 angularVel, material, id))
1379 material = nullptr; // Discard the material data when FGInterface reports an problem.
1380
1381 SGGeod geodPt = SGGeod::fromCart(SG_FEET_TO_METER*SGVec3d(pt));
1382 SGQuatd hlToEc = SGQuatd::fromLonLat(geodPt);
1383
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);
1388 if (terrain_active)
1389 {
1390 static bool material_valid = false;
1391
1392 if (updateGroundReactions(material)) {
1393 setPosition(pt);
1394 setHeading(Propagate->GetEuler(FGJSBBase::ePsi));
1395 GroundReactions->SetRollingFFactor(getRolingFrictionFactor());
1396 GroundReactions->SetStaticFFactor(getStaticFrictionFactor());
1397 GroundReactions->SetMaximumForce(getPressure()*0.00014503773800721815);
1398 GroundReactions->SetBumpiness(getBumpiness());
1399 GroundReactions->SetSolid(getSolid());
1400 GroundReactions->SetPosition(pt);
1401 material_valid = true;
1402 } else {
1403 if (material_valid) {
1404 GroundReactions->resetValues();
1405 material_valid = false;
1406 }
1407 }
1408 }
1409#else
1410 terrain->setBoolValue("valid", false);
1411#endif
1412 return dot(hlToEc.rotate(SGVec3d(0, 0, 1)), SGVec3d(contact) - SGVec3d(pt)) +
1414}
1415
1416inline static double sqr(double x)
1417{
1418 return x * x;
1419}
1420
1421static double angle_diff(double a, double b)
1422{
1423 double diff = fabs(a - b);
1424 if (diff > 180) diff = 360 - diff;
1425
1426 return diff;
1427}
1428
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)
1430{
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;
1437 (*points)++;
1438 }
1439}
1440
1441
1442static void check_hook_solution(const FGColumnVector3& ground_normal_body, double E, double hook_length, double sin_fi_guess, double* sin_fis, double* cos_fis, double* fis, int* points)
1443{
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);
1449 }
1450 }
1451}
1452
1453void FGJSBsim::update_external_forces(double t_off)
1454{
1455 const FGMatrix33& Tb2l = Propagate->GetTb2l();
1456 const FGMatrix33& Tl2b = Propagate->GetTl2b();
1457 const FGLocation& Location = Propagate->GetLocation();
1458 const FGMatrix33& Tec2l = Location.GetTec2l();
1459
1460 double hook_area[4][3];
1461
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);
1467
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);
1474
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()) {
1479 double contact[3];
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);
1490
1491 // check hook tip agl against same ground plane
1492 double hook_tip_agl_ft = DotProduct(hook_tip_body, ground_normal_body) + D;
1493 if (hook_tip_agl_ft < 0) {
1494
1495 // hook tip: hx - l cos, hy, hz + l sin
1496 // on ground: - n0 l cos + n2 l sin + E = 0
1497
1498 double E = D + DotProduct(hook_root_body, ground_normal_body);
1499
1500 // substitue x = sin fi, cos fi = sqrt(1 - x * x)
1501 // and rearrange to get a quadratic with coeffs:
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);
1505
1506 double disc = sqr(b) - 4 * a * c;
1507 if (disc >= 0) {
1508 double delta = sqrt(disc) / (2 * a);
1509
1510 // allow 4 solutions for safety, should never happen
1511 double sin_fis[4];
1512 double cos_fis[4];
1513 double fis[4];
1514 int points = 0;
1515
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);
1519
1520 if (points == 2) {
1521 double diff1 = angle_diff(fi, fis[0]);
1522 double diff2 = angle_diff(fi, fis[1]);
1523 int point = diff1 < diff2 ? 0 : 1;
1524 fi = fis[point];
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;
1529 }
1530 }
1531 }
1532 }
1533 } else {
1534 if (release_hook->getBoolValue()) {
1535 release_wire();
1536 fgSetDouble("/fdm/jsbsim/external_reactions/hook/magnitude", 0.0);
1537 arrestor_wire_engaged_hook->setBoolValue(false);
1538 release_hook->setBoolValue(false);
1539 } else {
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];
1543 get_wire_ends_ft(t_off, wire_ends_ec, wire_vel_ec);
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;
1547 if (rel_vel.Magnitude() < 3) {
1548 release_wire();
1549 fgSetDouble("/fdm/jsbsim/external_reactions/hook/magnitude", 0.0);
1550 arrestor_wire_engaged_hook->setBoolValue(false);
1551 release_hook->setBoolValue(false);
1552 }
1553 else {
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;
1557 force_plane_normal.Normalize();
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;
1562
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"));
1567 }
1568 }
1569 }
1570
1571 FGColumnVector3 hook_tip = Location.LocalToLocation(Tb2l * hook_tip_body);
1572
1573 hook_area[0][0] = hook_tip(1);
1574 hook_area[0][1] = hook_tip(2);
1575 hook_area[0][2] = hook_tip(3);
1576
1577 if (!arrestor_wire_engaged_hook->getBoolValue()) {
1578 // The previous positions.
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];
1585
1586 // Check if we caught a wire.
1587 // Returns true if we caught one.
1588 if (caught_wire_ft(t_off, hook_area)) {
1589 arrestor_wire_engaged_hook->setBoolValue(true);
1590 }
1591 }
1592
1593 // save actual position as old position ...
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];
1600
1601 fgSetDouble("/fdm/jsbsim/systems/hook/tailhook-pos-deg", fi);
1602
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));
1608 // The scalar component is the first component in FGQuaternion but
1609 // the last component in SGQuat.
1610 SGQuatd orient(ql2b(2), ql2b(3), ql2b(4), ql2b(1));
1611
1612 mesh->setPosition(cartPos * SG_FEET_TO_METER, orient);
1613
1614 SGVec3d f = mesh->GetForce(get_wake_group(),
1615 SGVec3d(uvw(1), uvw(2), uvw(3)),
1616 Atmosphere->GetDensity());
1617 const SGVec3d& m = mesh->GetMoment();
1618
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]);
1623
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]);
1628 }
1629 else {
1630 if (_fmag) _fmag->setDoubleValue(0.0);
1631 if (_mmag) _mmag->setDoubleValue(0.0);
1632 }
1633}
1634
1635
1636// Register the subsystem.
1637#if 0
1638SGSubsystemMgr::Registrant<FGJSBsim> registrantFGJSBsim;
1639#endif
double lat_geoc
Definition ADA.cxx:44
#define p(x)
static FGTurbulenceSeverityTable TurbulenceSeverityTable
Definition JSBSim.cxx:122
static double angle_diff(double a, double b)
Definition JSBSim.cxx:1421
static double sqr(double x)
Definition JSBSim.cxx:1416
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)
Definition JSBSim.cxx:1429
static double FMAX(double a, double b)
Definition JSBSim.cxx:67
#define RADTODEG
Definition JSBSim.hxx:49
#define i(x)
void set_rudder(double pos)
Definition controls.cxx:545
void set_elevator(double pos)
Definition controls.cxx:505
void set_aileron(double pos)
Definition controls.cxx:463
void set_throttle(int engine, double pos)
Definition controls.cxx:676
void set_elevator_trim(double pos)
Definition controls.cxx:525
virtual double GetAltitude(const FGLocation &l) const
Get the altitude above sea level dependent on the location.
Definition JSBSim.cxx:78
virtual ~FGFSGroundCallback()
Definition JSBSim.cxx:75
double GetAGLevel(double t, const FGLocation &l, FGLocation &cont, FGColumnVector3 &n, FGColumnVector3 &v, FGColumnVector3 &w) const override
Compute the altitude above ground.
Definition JSBSim.cxx:88
FGFSGroundCallback(FGJSBsim *ifc)
Definition JSBSim.cxx:74
FGControls * get_controls() const
Definition globals.cxx:971
void _updatePosition(const SGGeod &geod)
Definition flight.cxx:504
void _set_Mach_number(double m)
Definition flight.hxx:382
bool getSolid()
Definition flight.hxx:786
void _set_Velocities_Local(double north, double east, double down)
Definition flight.hxx:281
float getStaticFrictionFactor()
Definition flight.hxx:780
void _set_Accels_Pilot_Body(double x, double y, double z)
Definition flight.hxx:270
float getBumpiness()
Definition flight.hxx:776
virtual void set_Velocities_Body(double u, double v, double w)
Definition flight.cxx:579
void _set_Alpha(double a)
Definition flight.hxx:375
void _set_Velocities_Body(double u, double v, double w)
Definition flight.hxx:298
void _set_Accels_Body(double u, double v, double w)
Definition flight.hxx:260
float getPressure()
Definition flight.hxx:775
void unbind() override
Unbind any properties bound to this FDM.
Definition flight.cxx:442
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)
Definition flight.cxx:769
bool get_wire_ends_ft(double t, double end[2][3], double vel[2][3])
Definition flight.cxx:928
void setHeading(float h)
Definition flight.hxx:771
float getGroundDisplacement()
Definition flight.hxx:777
void _set_Earth_position_angle(double a)
Definition flight.hxx:387
void _set_Climb_Rate(double rate)
Definition flight.hxx:389
void _set_CG_Position(double dx, double dy, double dz)
Definition flight.hxx:250
virtual void set_Latitude(double lat)
Definition flight.cxx:546
virtual void set_Climb_Rate(double roc)
Definition flight.cxx:597
bool updateGroundReactions(simgear::BVHMaterial const *&material)
Definition flight.hxx:768
void common_init()
Initialize the state of the FDM.
Definition flight.cxx:137
bool prepare_ground_cache_ft(double startSimTime, double endSimTime, const double pt[3], double rad)
Definition flight.cxx:669
virtual void set_Mach_number(double mach)
Definition flight.cxx:567
void _set_Accels_CG_Body_N(double x, double y, double z)
Definition flight.hxx:275
void _set_Runway_altitude(double alt)
Definition flight.hxx:388
virtual void set_Gamma_vert_rad(double gamma)
Definition flight.cxx:601
float getRolingFrictionFactor()
Definition flight.hxx:783
const AIWakeGroup & get_wake_group(void)
Definition flight.hxx:792
void _set_Velocities_Ground(double north, double east, double down)
Definition flight.hxx:286
void _set_Omega_Body(double p, double q, double r)
Definition flight.hxx:307
void release_wire(void)
Definition flight.cxx:941
virtual void set_V_calibrated_kts(double vc)
Definition flight.cxx:563
void _set_Beta(double b)
Definition flight.hxx:376
virtual void set_Altitude(double alt)
Definition flight.cxx:554
void _set_Nlf(double n)
Definition flight.hxx:280
bool is_valid_m(double *ref_time, double pt[3], double *rad)
Definition flight.cxx:679
void _set_V_calibrated_kts(double kts)
Definition flight.hxx:306
void _set_Sea_level_radius(double r)
Definition flight.hxx:386
double get_Altitude() const
Definition flight.hxx:634
void _set_V_rel_wind(double vt)
Definition flight.hxx:303
void setPosition(double pt[3])
Definition flight.hxx:772
bool caught_wire_ft(double t, const double pt[4][3])
Definition flight.cxx:905
void _set_Altitude_AGL(double agl)
Definition flight.hxx:356
void _set_T_Local_to_Body(int i, int j, double value)
Definition flight.hxx:374
virtual void set_Euler_Angles(double phi, double theta, double psi)
Definition flight.cxx:588
void _set_Euler_Rates(double phi, double theta, double psi)
Definition flight.hxx:312
void _set_V_equiv_kts(double kts)
Definition flight.hxx:305
int _calc_multiloop(double dt)
Definition flight.cxx:65
double get_Sea_level_radius() const
Definition flight.hxx:674
void reset_wake_group(void)
Definition flight.hxx:791
void _set_V_ground_speed(double v)
Definition flight.hxx:304
void _set_Gamma_vert_rad(double gv)
Definition flight.hxx:380
virtual void set_Longitude(double lon)
Definition flight.cxx:550
virtual void set_Velocities_Local(double north, double east, double down)
Definition flight.cxx:571
double get_Altitude_AGL(void) const
Definition flight.hxx:637
void _set_Euler_Angles(double phi, double theta, double psi)
Definition flight.hxx:368
FGFS / JSBSim interface (aka "The Bus").
Definition JSBSim.hxx:102
void set_Velocities_Local(double north, double east, double down)
Sets velocity in N-E-D coordinates.
Definition JSBSim.cxx:1123
FGJSBsim(double dt)
Constructor.
Definition JSBSim.cxx:124
void set_Longitude(double lon)
Set longitude.
Definition JSBSim.cxx:1056
void set_V_calibrated_kts(double vc)
Sets calibrated airspeed Setting this will trigger a recalc of the other velocity terms.
Definition JSBSim.cxx:1081
void set_Latitude(double lat)
Set geocentric latitude.
Definition JSBSim.cxx:1030
void set_Climb_Rate(double roc)
Sets rate of climb.
Definition JSBSim.cxx:1186
bool copy_to_JSBsim()
copy FDM state to LaRCsim structures
Definition JSBSim.cxx:598
void unbind() override
Definition JSBSim.cxx:508
void update(double dt) override
Definition JSBSim.cxx:517
void set_Altitude(double alt)
Set altitude Note: this triggers a recalculation of AGL altitude.
Definition JSBSim.cxx:1069
void init() override
Definition JSBSim.cxx:380
void set_Mach_number(double mach)
Sets Mach number.
Definition JSBSim.cxx:1103
~FGJSBsim()
Destructor.
Definition JSBSim.cxx:369
void set_Euler_Angles(double phi, double theta, double psi)
Euler Angle Parameter Set.
Definition JSBSim.cxx:1164
bool copy_from_JSBsim()
copy FDM state from LaRCsim structures
Definition JSBSim.cxx:748
void suspend() override
Definition JSBSim.cxx:580
void set_Velocities_Body(double u, double v, double w)
Sets aircraft velocity in stability frame.
Definition JSBSim.cxx:1144
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])
Definition JSBSim.cxx:1369
bool ToggleDataLogging(void)
Definition JSBSim.cxx:1009
void set_Gamma_vert_rad(double gamma)
Sets the flight path angle in radians.
Definition JSBSim.cxx:1209
void resume() override
Definition JSBSim.cxx:588
This class implements a 3 element column vector.
FGColumnVector3 & Normalize(void)
Normalize.
double Magnitude(void) const
Length of the vector.
Models an electric motor.
Definition FGElectric.h:68
double getRPM(void)
Definition FGElectric.h:77
Base class for all engines.
Definition FGEngine.h:104
virtual double getFuelFlow_gph() const
Definition FGEngine.h:146
virtual bool GetCranking(void) const
Definition FGEngine.h:153
virtual bool GetRunning(void) const
Definition FGEngine.h:152
virtual void SetStarter(bool s)
Definition FGEngine.h:163
virtual void SetRunning(bool bb)
Definition FGEngine.h:158
virtual double getFuelFlow_pph() const
Definition FGEngine.h:147
virtual bool GetStarter(void) const
Definition FGEngine.h:144
FGGroundReactions * GetGroundReactions(void)
Returns the FGGroundReactions pointer.
Definition FGFDMExec.h:369
Manages ground reactions modeling.
FGLGear * GetGearUnit(int gear) const
Gets a gear instance.
int GetNumGearUnits(void) const
Gets the number of gears.
static short debug_lvl
Definition FGJSBBase.h:190
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...
Landing gear model.
Definition FGLGear.h:191
double GetCompLen(void) const
Gets the current compressed length of the gear in feet.
Definition FGLGear.h:257
double GetWheelRollVel(void) const
Definition FGLGear.h:306
bool GetSteerable(void) const
Definition FGLGear.h:281
double GetGearUnitPos(void) const
Definition FGLGear.cpp:661
double GetSteerNorm(void) const
Definition FGLGear.h:272
bool GetWOW(void) const
Gets the Weight On Wheels flag value.
Definition FGLGear.h:255
int GetBrakeGroup(void) const
Definition FGLGear.h:278
FGColumnVector3 GetBodyLocation(void) const
Gets the location of the gear in Body axes.
Definition FGLGear.h:241
FGLocation holds an arbitrary location in the Earth centered Earth fixed reference frame (ECEF).
Definition FGLocation.h:152
const FGMatrix33 & GetTec2l(void) const
Transform matrix from the earth centered to local horizontal frame.
Definition FGLocation.h:301
FGLocation LocalToLocation(const FGColumnVector3 &lvec) const
Conversion from Local frame coordinates to a location in the earth centered and fixed frame.
Definition FGLocation.h:326
double GetRadius() const
Get the distance from the center of the earth in feet.
Definition FGLocation.h:291
double GetLongitude() const
Get the longitude.
Definition FGLocation.h:234
FGColumnVector3 LocationToLocal(const FGColumnVector3 &ecvec) const
Conversion from a location in the earth centered and fixed frame to local horizontal frame coordinate...
Definition FGLocation.h:336
double GetLatitude() const
Get the GEOCENTRIC latitude in radians.
Definition FGLocation.h:252
double GetSeaLevelRadius(void) const
Get the sea level radius in feet below the current location.
Handles matrix math operations.
Definition FGMatrix33.h:70
FGQuaternion GetQuaternion(void) const
Returns the quaternion associated with this direction cosine (rotation) matrix.
Models a Supercharged Piston engine.
Definition FGPiston.h:224
double getExhaustGasTemp_degF(void) const
Definition FGPiston.h:244
double getOilPressure_psi(void) const
Definition FGPiston.h:247
double getOilTemp_degF(void) const
Definition FGPiston.h:248
double getRPM(void) const
Definition FGPiston.h:249
int GetMagnetos(void) const
Definition FGPiston.h:242
double getCylinderHeadTemp_degF(void) const
Definition FGPiston.h:246
void SetMagnetos(int magnetos)
Definition FGPiston.h:239
double getManifoldPressure_inHg(void) const
Definition FGPiston.h:245
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.
Definition FGTable.cpp:82
Models a fuel tank.
Definition FGTank.h:202
void SetUnusableVolume(double volume)
Sets the volume of unusable fuel in the tank.
Definition FGTank.h:294
double GetUnusableVolume(void) const
Returns the unusable volume of fuel in the tank.
Definition FGTank.h:290
double GetTemperature_degC(void) const
Gets the temperature of the fuel.
Definition FGTank.h:271
double GetContents(void) const
Gets the contents of the tank.
Definition FGTank.h:260
void SetDensity(double d)
Sets the fuel density.
Definition FGTank.h:317
double GetCapacityGallons(void) const
Gets the capacity of the tank.
Definition FGTank.h:256
FGColumnVector3 GetXYZ(void) const
Definition FGTank.cpp:252
void SetContents(double amount)
Definition FGTank.cpp:308
double GetDensity(void) const
Returns the fuel density.
Definition FGTank.h:314
Base class for specific thrusting devices such as propellers, nozzles, etc.
Definition FGThruster.h:77
eType GetType(void)
Definition FGThruster.h:97
virtual double GetRPM(void) const
Definition FGThruster.h:101
double GetThrust(void) const
Definition FGThruster.h:96
The trimming routine for JSBSim.
Definition FGTrim.h:124
bool DoTrim(void)
Execute the trim.
Definition FGTrim.cpp:186
void Report(void)
Print the results of the trim.
Definition FGTrim.cpp:113
void TrimStats()
Iteration statistics.
Definition FGTrim.cpp:92
This class models a turbine engine.
Definition FGTurbine.h:155
bool GetAugmentation(void) const
Definition FGTurbine.h:189
double GetInlet(void) const
Definition FGTurbine.h:194
bool GetInjection(void) const
Definition FGTurbine.h:187
void SetReverse(bool reversed)
Definition FGTurbine.h:217
double GetNozzle(void) const
Definition FGTurbine.h:195
double GetEPR(void) const
Definition FGTurbine.h:199
void SetAugmentation(bool augmentation)
Definition FGTurbine.h:213
double GetN2(void) const
Definition FGTurbine.h:198
double GetN1(void) const
Definition FGTurbine.h:197
int GetIgnition(void) const
Definition FGTurbine.h:192
bool GetReversed(void) const
Definition FGTurbine.h:190
void SetCutoff(bool cutoff)
Definition FGTurbine.h:218
double GetEGT(void) const
Definition FGTurbine.h:200
void SetIgnition(int ignition)
Definition FGTurbine.h:212
bool GetCutoff(void) const
Definition FGTurbine.h:191
double getOilPressure_psi() const
Definition FGTurbine.h:204
Turboprop engine model.
Definition FGTurboProp.h:93
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 GetN1(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.
Definition fg_props.cxx:556
FGGlobals * globals
Definition globals.cxx:142
@ ofNorm
Definition FGFCS.h:56
@ tFull
Definition FGTrim.h:65
@ tGround
Definition FGTrim.h:65
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.
Definition proptest.cpp:31
bool fgGetBool(char const *name, bool def)
Get a bool value for a property.
Definition proptest.cpp:25
bool fgSetBool(char const *name, bool val)
Set a bool value for a property.
Definition proptest.cpp:24
double fgGetDouble(const char *name, double defaultValue)
Get a double value for a property.
Definition proptest.cpp:30
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
Definition proptest.cpp:27
JSBSim Message structure.
Definition FGJSBBase.h:87
enum JSBSim::FGJSBBase::Message::mType type