1
0
Fork 0
flightgear/src/FDM/YASim/YASim.cxx

502 lines
15 KiB
C++
Raw Normal View History

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/scene/model/placement.hxx>
#include <simgear/xml/easyxml.hxx>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include "FGFDM.hpp"
#include "Atmosphere.hpp"
#include "Math.hpp"
#include "Airplane.hpp"
#include "Model.hpp"
#include "Integrator.hpp"
#include "Glue.hpp"
#include "Gear.hpp"
#include "Hook.hpp"
#include "Launchbar.hpp"
#include "FGGround.hpp"
#include "PropEngine.hpp"
2001-12-07 20:00:59 +00:00
#include "PistonEngine.hpp"
#include "YASim.hxx"
using namespace yasim;
static const float YASIM_PI = 3.14159265358979323846;
static const float RAD2DEG = 180/YASIM_PI;
static const float PI2 = YASIM_PI*2;
2001-12-07 20:00:59 +00:00
static const float RAD2RPM = 9.54929658551;
static const float M2FT = 3.2808399;
static const float FT2M = 0.3048;
static const float MPS2KTS = 3600.0/1852.0;
static const float CM2GALS = 264.172037284; // gallons/cubic meter
2001-12-07 20:00:59 +00:00
static const float KG2LBS = 2.20462262185;
static const float W2HP = 1.3416e-3;
static const float INHG2PA = 3386.389;
static const float SLUG2KG = 14.59390;
YASim::YASim(double dt) :
_simTime(0)
{
// set_delta_t(dt);
_fdm = new FGFDM();
2001-12-24 13:54:03 +00:00
_dt = dt;
_fdm->getAirplane()->getModel()->setGroundCallback( new FGGround(this) );
_fdm->getAirplane()->getModel()->getIntegrator()->setInterval(_dt);
}
YASim::~YASim()
{
delete _fdm;
}
void YASim::report()
{
Airplane* a = _fdm->getAirplane();
float aoa = a->getCruiseAoA() * RAD2DEG;
float tail = -1 * a->getTailIncidence() * RAD2DEG;
float drag = 1000 * a->getDragCoefficient();
SG_LOG(SG_FLIGHT,SG_INFO,"YASim solution results:");
SG_LOG(SG_FLIGHT,SG_INFO," Iterations: "<<a->getSolutionIterations());
SG_LOG(SG_FLIGHT,SG_INFO," Drag Coefficient: "<< drag);
SG_LOG(SG_FLIGHT,SG_INFO," Lift Ratio: "<<a->getLiftRatio());
SG_LOG(SG_FLIGHT,SG_INFO," Cruise AoA: "<< aoa);
SG_LOG(SG_FLIGHT,SG_INFO," Tail Incidence: "<< tail);
SG_LOG(SG_FLIGHT,SG_INFO,"Approach Elevator: "<<a->getApproachElevator());
float cg[3];
char buf[256];
a->getModel()->getBody()->getCG(cg);
sprintf(buf, " CG: %.3f, %.3f, %.3f", cg[0], cg[1], cg[2]);
SG_LOG(SG_FLIGHT, SG_INFO, buf);
if(a->getFailureMsg()) {
SG_LOG(SG_FLIGHT, SG_ALERT, "YASim SOLUTION FAILURE:");
SG_LOG(SG_FLIGHT, SG_ALERT, a->getFailureMsg());
exit(1);
}
}
2001-12-24 13:54:03 +00:00
void YASim::bind()
{
// Run the superclass bind to set up a bunch of property ties
FGInterface::bind();
// Now UNtie the ones that we are going to set ourselves.
fgUntie("/consumables/fuel/tank[0]/level-gal_us");
fgUntie("/consumables/fuel/tank[1]/level-gal_us");
char buf[256];
for(int i=0; i<_fdm->getAirplane()->getModel()->numThrusters(); i++) {
sprintf(buf, "/engines/engine[%d]/fuel-flow-gph", i); fgUntie(buf);
sprintf(buf, "/engines/engine[%d]/rpm", i); fgUntie(buf);
sprintf(buf, "/engines/engine[%d]/mp-osi", i); fgUntie(buf);
sprintf(buf, "/engines/engine[%d]/egt-degf", i); fgUntie(buf);
sprintf(buf, "/engines/engine[%d]/oil-temperature-degf", i); fgUntie(buf);
2001-12-24 13:54:03 +00:00
}
}
void YASim::init()
{
Airplane* a = _fdm->getAirplane();
Model* m = a->getModel();
// Superclass hook
common_init();
2001-12-10 23:13:54 +00:00
m->setCrashed(false);
// Figure out the initial speed type
string speed_set = fgGetString("/sim/presets/speed-set", "UVW");
if (speed_set == "NED")
_speed_set = NED;
else if (speed_set == "UVW")
_speed_set = UVW;
else if (speed_set == "knots")
_speed_set = KNOTS;
else if (speed_set == "mach")
_speed_set = MACH;
else {
_speed_set = UVW;
SG_LOG(SG_FLIGHT, SG_ALERT, "Unknown speed type " << speed_set);
}
// Build a filename and parse it
SGPath f(fgGetString("/sim/aircraft-dir"));
f.append(fgGetString("/sim/aero"));
f.concat(".xml");
readXML(f.str(), *_fdm);
// Compile it into a real airplane, and tell the user what they got
a->compile();
report();
_fdm->init();
2001-12-07 20:00:59 +00:00
// Create some FG{Eng|Gear}Interface objects
int i;
for(i=0; i<a->numGear(); i++) {
Gear* g = a->getGear(i);
SGPropertyNode * node = fgGetNode("gear/gear", i, true);
2001-12-07 20:00:59 +00:00
float pos[3];
g->getPosition(pos);
node->setDoubleValue("xoffset-in", pos[0] * M2FT * 12);
node->setDoubleValue("yoffset-in", pos[1] * M2FT * 12);
node->setDoubleValue("zoffset-in", pos[2] * M2FT * 12);
2001-12-07 20:00:59 +00:00
}
2001-12-10 23:13:54 +00:00
// Are we at ground level? If so, lift the plane up so the gear
// clear the ground.
From: "Jim Wilson" <jimw@kelcomaine.com> This is a new improved patch for the previous tile manager fixes. Rather than building dependencies between FGlocation or the viewer or fdm with tilemgr what I ended up doing was linking the pieces together in the Mainloop in main.cxx. You'll see what I mean...it's been commented fairly well. More than likely we should move that chunk somewhere...just not sure where yet. The changes seem clean now. As I get more ideas there could be some further improvement in organizing the update in tilemgr. You'll note that I left an override in there for the tilemgr::update() function to preserve earlier functionality if someone needs it (e.g. usage independent of an fdm or viewer), not to mention there are a few places in flightgear that call it directly that have not been changed to the new interface (and may not need to be). The code has been optimized to avoid duplicate traversals and seems to run generally quite well. Note that there can be a short delay reloading tiles that have been dropped from static views. We could call the tile scheduler on a view switch, but it's not a big deal and at the moment I'd like to get this in so people can try it and comment on it as it is. Everything has been resycned with CVS tonight and I've included the description submitted earlier (below). Best, Jim Changes synced with CVS approx 20:30EDT 2002-05-09 (after this evenings updates). Files: http://www.spiderbark.com/fgfs/viewer-update-20020516.tar.gz or http://www.spiderbark.com/fgfs/viewer-update-20020516.diffs.gz Description: In a nutshell, these patches begin to take what was one value for ground elevation and calculate ground elevation values seperately for the FDM and the viewer (eye position). Several outstanding view related bugs have been fixed. With the introduction of the new viewer code a lot of that Flight Gear code broke related to use of a global variable called "scenery.cur_elev". Therefore the ground_elevation and other associated items (like the current tile bucket) is maintained per FDM instance and per View. Each of these has a "point" or location that can be identified. See changes to FGLocation class and main.cxx. Most of the problems related to the new viewer in terms of sky, ground and runway lights, and tower views are fixed. There are four minor problems remaining. 1) The sun/moon spins when you pan the "lookat" tower view only (view #3). 2) Under stress (esp. magic carpet full speed with max visibility), there is a memory leak in the tile caching that was not introduced with these changes. 3) I have not tested these changes or made corrections to the ADA or External FDM interfaces. 4) The change view function doesn't call the time/light update (not a problem unless a tower is very far away). Details: FDM/flight.cxx, flight.hxx - FGInterface ties to FGAircraftModel so that it's location data can be accessed for runway (ground elevation under aircraft) elevation. FDM/larsim.cxx, larcsim.hxx - gets runway elevation from FGInterface now. Commented out function that is causing a namespace conflict, hasn't been called with recent code anyway. FDM/JSBSim/JSBSim.cxx, YASim/YASim.cxx - gets runway elevation from FGInterface now. Scenery/newcache.cxx, newcache.hxx - changed caching scheme to time based (oldest tiles discard). Scenery/tileentry.cxx, tileentry.hxx - added place to record time, changed rendering to reference viewer altitude in order to fix a problem with ground and runway lights. Scenery/tilemgr.cxx, tilemgr.hxx - Modified update() to accept values for multiple locations. Refresh function added in order to periodically make the tiles current for a non-moving view (like a tower). Main/fg_init.cxx - register event for making tiles current in a non-moving view (like a tower). Main/location.hxx - added support for current ground elevation data. Main/main.cxx - added second tilemgr call for fdm, fixed places where viewer position data was required for correct sky rendering. Main/options.cxx - fixed segfault reported by Curtis when using --view-offset command line parameter. Main/viewer.cxx, viewer.hxx - removed fudging of view position. Fixed numerous bugs that were causing eye and target values to get mixed up.
2002-05-17 17:25:28 +00:00
double runway_altitude = get_Runway_altitude();
if(get_Altitude() - runway_altitude < 50) {
fgSetBool("/controls/gear/gear-down", false);
2001-12-10 23:13:54 +00:00
float minGearZ = 1e18;
for(i=0; i<a->numGear(); i++) {
Gear* g = a->getGear(i);
float pos[3];
g->getPosition(pos);
if(pos[2] < minGearZ)
minGearZ = pos[2];
}
_set_Altitude(runway_altitude - minGearZ*M2FT);
fgSetBool("/controls/gear/gear-down", true);
}
// Blank the state, and copy in ours
State s;
m->setState(&s);
copyToYASim(true);
2001-12-24 13:54:03 +00:00
_fdm->getExternalInput();
_fdm->getAirplane()->initEngines();
2001-12-24 13:54:03 +00:00
set_inited(true);
}
void YASim::update(double dt)
{
if (is_suspended())
return;
int iterations = _calc_multiloop(dt);
2001-12-10 23:13:54 +00:00
// If we're crashed, then we don't care
if(_fdm->getAirplane()->getModel()->isCrashed()) {
if(!fgGetBool("/sim/crashed"))
fgSetBool("/sim/crashed", true);
return;
}
2001-12-10 23:13:54 +00:00
// ground. Calculate a cartesian coordinate for the ground under
// us, find the (geodetic) up vector normal to the ground, then
// use that to find the final (radius) term of the plane equation.
Mathias Fr�hlich: 2. I made YASim query the the ground cache at the wrong place. This one fixed this, one can now land the bo105 on top of the oracle buildings :) 3. Is a followup of the scenery center update code: Register the scenery center transform at the time it is put into the scene graph not at creation time. 4. I held that part back from the past hitlist patch, because I hoped that it will be sufficient (and the last one was in fact the biggest part) without. As some test cases from Melchior showed me, it is not. We have additionally to the wrong computed transform from the prevous patch some roundoff problems. This patch adds some small tolerance to for the point in triangle test. ... may be one even needs to increase the eps value further if starting at some tile boundaries still fails. 5. That is a big chunk. Tested now for two days while hunting the second patch :) . That is a partial rewrite of the groundcache to use its own datastructures for that flat scenegraph in the cache. The basic advantage is, what Erik suggested, to precompute some often used values of these triangles. Also allmost all computations are now in double precision which should decrease (hopefully fix), together with a similar tolerance for some point in triangle tests, the problems with 'no ground below aircraft'. I am playing with octrees for the groundcache, that will finally solve the performance problem when high triangular count models end up in the groundcache. This patch is also some prework for those octrees ...
2005-05-30 08:48:27 +00:00
float v[3] = { get_uBody(), get_vBody(), get_wBody() };
float lat = get_Latitude(); float lon = get_Longitude();
Mathias Fr�hlich: 2. I made YASim query the the ground cache at the wrong place. This one fixed this, one can now land the bo105 on top of the oracle buildings :) 3. Is a followup of the scenery center update code: Register the scenery center transform at the time it is put into the scene graph not at creation time. 4. I held that part back from the past hitlist patch, because I hoped that it will be sufficient (and the last one was in fact the biggest part) without. As some test cases from Melchior showed me, it is not. We have additionally to the wrong computed transform from the prevous patch some roundoff problems. This patch adds some small tolerance to for the point in triangle test. ... may be one even needs to increase the eps value further if starting at some tile boundaries still fails. 5. That is a big chunk. Tested now for two days while hunting the second patch :) . That is a partial rewrite of the groundcache to use its own datastructures for that flat scenegraph in the cache. The basic advantage is, what Erik suggested, to precompute some often used values of these triangles. Also allmost all computations are now in double precision which should decrease (hopefully fix), together with a similar tolerance for some point in triangle tests, the problems with 'no ground below aircraft'. I am playing with octrees for the groundcache, that will finally solve the performance problem when high triangular count models end up in the groundcache. This patch is also some prework for those octrees ...
2005-05-30 08:48:27 +00:00
float alt = get_Altitude() * FT2M; double xyz[3];
sgGeodToCart(lat, lon, alt, xyz);
// build the environment cache.
float vr = _fdm->getVehicleRadius();
Mathias Fr�hlich: 2. I made YASim query the the ground cache at the wrong place. This one fixed this, one can now land the bo105 on top of the oracle buildings :) 3. Is a followup of the scenery center update code: Register the scenery center transform at the time it is put into the scene graph not at creation time. 4. I held that part back from the past hitlist patch, because I hoped that it will be sufficient (and the last one was in fact the biggest part) without. As some test cases from Melchior showed me, it is not. We have additionally to the wrong computed transform from the prevous patch some roundoff problems. This patch adds some small tolerance to for the point in triangle test. ... may be one even needs to increase the eps value further if starting at some tile boundaries still fails. 5. That is a big chunk. Tested now for two days while hunting the second patch :) . That is a partial rewrite of the groundcache to use its own datastructures for that flat scenegraph in the cache. The basic advantage is, what Erik suggested, to precompute some often used values of these triangles. Also allmost all computations are now in double precision which should decrease (hopefully fix), together with a similar tolerance for some point in triangle tests, the problems with 'no ground below aircraft'. I am playing with octrees for the groundcache, that will finally solve the performance problem when high triangular count models end up in the groundcache. This patch is also some prework for those octrees ...
2005-05-30 08:48:27 +00:00
vr += 2.0*FT2M*dt*Math::mag3(v);
prepare_ground_cache_m( _simTime, _simTime + dt, xyz, vr );
// Track time increments.
FGGround* gr
= (FGGround*)_fdm->getAirplane()->getModel()->getGroundCallback();
2001-12-07 20:00:59 +00:00
int i;
for(i=0; i<iterations; i++) {
gr->setTimeOffset(_simTime + i*_dt);
copyToYASim(false);
_fdm->iterate(_dt);
copyFromYASim();
}
// Increment the local sim time
_simTime += dt;
gr->setTimeOffset(_simTime);
}
void YASim::copyToYASim(bool copyState)
{
// Physical state
double lat = get_Latitude();
double lon = get_Longitude();
float alt = get_Altitude() * FT2M;
float roll = get_Phi();
float pitch = get_Theta();
float hdg = get_Psi();
// Environment
float wind[3];
wind[0] = get_V_north_airmass() * FT2M * -1.0;
wind[1] = get_V_east_airmass() * FT2M * -1.0;
wind[2] = get_V_down_airmass() * FT2M * -1.0;
float pressure = fgGetFloat("/environment/pressure-inhg") * INHG2PA;
float temp = fgGetFloat("/environment/temperature-degc") + 273.15;
float dens = fgGetFloat("/environment/density-slugft3")
* SLUG2KG * M2FT*M2FT*M2FT;
// Convert and set:
Model* model = _fdm->getAirplane()->getModel();
State s;
float xyz2ned[9];
Glue::xyz2nedMat(lat, lon, xyz2ned);
// position
sgGeodToCart(lat, lon, alt, s.pos);
// orientation
Glue::euler2orient(roll, pitch, hdg, s.orient);
Math::mmul33(s.orient, xyz2ned, s.orient);
// Velocity
string speed_set = fgGetString("/sim/presets/speed-set", "UVW");
float v[3];
bool needCopy = false;
switch (_speed_set) {
case NED:
v[0] = get_V_north() * FT2M * -1.0;
v[1] = get_V_east() * FT2M * -1.0;
v[2] = get_V_down() * FT2M * -1.0;
break;
case UVW:
v[0] = get_uBody() * FT2M;
v[1] = get_vBody() * FT2M;
v[2] = get_wBody() * FT2M;
Math::tmul33(s.orient, v, v);
break;
case KNOTS:
v[0] = Atmosphere::spdFromVCAS(get_V_calibrated_kts()/MPS2KTS,
pressure, temp);
v[1] = 0;
v[2] = 0;
Math::tmul33(s.orient, v, v);
needCopy = true;
break;
case MACH:
v[0] = Atmosphere::spdFromMach(get_Mach_number(), temp);
v[1] = 0;
v[2] = 0;
Math::tmul33(s.orient, v, v);
needCopy = true;
break;
default:
v[0] = 0;
v[1] = 0;
v[2] = 0;
break;
}
if (!copyState)
_speed_set = UVW; // change to this after initial setting
Math::set3(v, s.v);
if(copyState || needCopy)
model->setState(&s);
// wind
Math::tmul33(xyz2ned, wind, wind);
model->setWind(wind);
// air
model->setAir(pressure, temp, dens);
// Query a ground plane for each gear/hook/launchbar and
// write that value into the corresponding class.
_fdm->getAirplane()->getModel()->updateGround(&s);
Launchbar* l = model->getLaunchbar();
if (l)
l->setLaunchCmd(0.0<fgGetFloat("/controls/gear/catapult-launch-cmd"));
}
// All the settables:
//
// These are set below:
// _set_Accels_Local
// _set_Accels_Body
// _set_Accels_CG_Body
// _set_Accels_Pilot_Body
// _set_Accels_CG_Body_N
// _set_Velocities_Local
// _set_Velocities_Ground
// _set_Velocities_Wind_Body
// _set_Omega_Body
// _set_Euler_Rates
// _set_Euler_Angles
// _set_V_rel_wind
// _set_V_ground_speed
// _set_V_equiv_kts
// _set_V_calibrated_kts
// _set_Alpha
// _set_Beta
// _set_Mach_number
// _set_Climb_Rate
// _set_Tank1Fuel
// _set_Tank2Fuel
// _set_Altitude_AGL
// _set_Geodetic_Position
// _set_Runway_altitude
// Ignoring these, because they're unused:
// _set_Geocentric_Position
// _set_Geocentric_Rates
// _set_Cos_phi
// _set_Cos_theta
// _set_Earth_position_angle (WTF?)
// _set_Gamma_vert_rad
// _set_Inertias
// _set_T_Local_to_Body
// _set_CG_Position
// _set_Sea_Level_Radius
// Externally set via the weather code:
// _set_Velocities_Local_Airmass
// _set_Density
// _set_Static_pressure
// _set_Static_temperature
void YASim::copyFromYASim()
{
2001-12-07 20:00:59 +00:00
Airplane* airplane = _fdm->getAirplane();
Model* model = airplane->getModel();
State* s = model->getState();
// position
double lat, lon, alt;
sgCartToGeod(s->pos, &lat, &lon, &alt);
_set_Geodetic_Position(lat, lon, alt*M2FT);
double groundlevel_m = get_groundlevel_m(lat, lon, alt);
_set_Runway_altitude(groundlevel_m*SG_METER_TO_FEET);
_set_Altitude_AGL((alt-groundlevel_m)*SG_METER_TO_FEET);
// the smallest agl of all gears
fgSetFloat("/position/gear-agl-m", model->getAGL());
fgSetFloat("/position/gear-agl-ft", model->getAGL()*M2FT);
// UNUSED
//_set_Geocentric_Position(Glue::geod2geocLat(lat), lon, alt*M2FT);
// useful conversion matrix
float xyz2ned[9];
Glue::xyz2nedMat(lat, lon, xyz2ned);
// velocity
float v[3];
Math::vmul33(xyz2ned, s->v, v);
_set_Velocities_Local(M2FT*v[0], M2FT*v[1], M2FT*v[2]);
_set_V_ground_speed(Math::sqrt(M2FT*v[0]*M2FT*v[0] +
M2FT*v[1]*M2FT*v[1]));
_set_Climb_Rate(-M2FT*v[2]);
// The HUD uses this, but inverts down (?!)
_set_Velocities_Ground(M2FT*v[0], M2FT*v[1], -M2FT*v[2]);
// _set_Geocentric_Rates(M2FT*v[0], M2FT*v[1], M2FT*v[2]); // UNUSED
// Airflow velocity.
float wind[3];
wind[0] = get_V_north_airmass() * FT2M * -1.0; // Wind in NED
wind[1] = get_V_east_airmass() * FT2M * -1.0;
wind[2] = get_V_down_airmass() * FT2M * -1.0;
Math::tmul33(xyz2ned, wind, wind); // Wind in global
Math::sub3(s->v, wind, v); // V - wind in global
Math::vmul33(s->orient, v, v); // to body coordinates
_set_Velocities_Wind_Body(v[0]*M2FT, -v[1]*M2FT, -v[2]*M2FT);
_set_V_rel_wind(Math::mag3(v)*M2FT); // units?
float P = fgGetDouble("/environment/pressure-inhg") * INHG2PA;
2008-12-05 17:33:57 +00:00
float T = fgGetDouble("/environment/temperature-degc") + 273.15;
float D = fgGetFloat("/environment/density-slugft3")
*SLUG2KG * M2FT*M2FT*M2FT;
_set_V_equiv_kts(Atmosphere::calcVEAS(v[0], P, T, D)*MPS2KTS);
_set_V_calibrated_kts(Atmosphere::calcVCAS(v[0], P, T)*MPS2KTS);
_set_Mach_number(Atmosphere::calcMach(v[0], T));
// acceleration
Math::vmul33(xyz2ned, s->acc, v);
_set_Accels_Local(M2FT*v[0], M2FT*v[1], M2FT*v[2]);
Math::vmul33(s->orient, s->acc, v);
_set_Accels_Body(M2FT*v[0], -M2FT*v[1], -M2FT*v[2]);
_set_Accels_CG_Body(M2FT*v[0], -M2FT*v[1], -M2FT*v[2]);
_fdm->getAirplane()->getPilotAccel(v);
_set_Accels_Pilot_Body(-M2FT*v[0], M2FT*v[1], M2FT*v[2]);
// There is no property for pilot G's, but I need it for a panel
// instrument. Hack this in here, and REMOVE IT WHEN IT FINDS A
// REAL HOME!
fgSetFloat("/accelerations/pilot-g", -v[2]/9.8);
// The one appears (!) to want inverted pilot acceleration
// numbers, in G's...
Math::mul3(1.0/9.8, v, v);
_set_Accels_CG_Body_N(v[0], -v[1], -v[2]);
// orientation
float alpha, beta;
Glue::calcAlphaBeta(s, wind, &alpha, &beta);
_set_Alpha(alpha);
_set_Beta(beta);
float tmp[9];
Math::trans33(xyz2ned, tmp);
Math::mmul33(s->orient, tmp, tmp);
float roll, pitch, hdg;
Glue::orient2euler(tmp, &roll, &pitch, &hdg);
// make heading positive value
if(hdg < 0.0) hdg += PI2;
_set_Euler_Angles(roll, pitch, hdg);
// rotation
Math::vmul33(s->orient, s->rot, v);
_set_Omega_Body(v[0], -v[1], -v[2]);
Glue::calcEulerRates(s, &roll, &pitch, &hdg);
_set_Euler_Rates(roll, pitch, hdg);
2001-12-07 20:00:59 +00:00
// Fill out our engine and gear objects
int i;
for(i=0; i<airplane->numGear(); i++) {
2001-12-07 20:00:59 +00:00
Gear* g = airplane->getGear(i);
SGPropertyNode * node = fgGetNode("gear/gear", i, true);
node->setBoolValue("has-brake", g->getBrake() != 0);
node->setBoolValue("wow", g->getCompressFraction() != 0);
node->setFloatValue("compression-norm", g->getCompressFraction());
node->setFloatValue("compression-m", g->getCompressDist());
node->setFloatValue("caster-angle-deg", g->getCasterAngle() * RAD2DEG);
node->setFloatValue("rollspeed-ms", g->getRollSpeed());
node->setBoolValue("ground-is-solid", g->getGroundIsSolid()!=0);
node->setFloatValue("ground-friction-factor", g->getGroundFrictionFactor());
2001-12-07 20:00:59 +00:00
}
Hook* h = airplane->getHook();
if(h) {
SGPropertyNode * node = fgGetNode("gear/tailhook", 0, true);
node->setFloatValue("position-norm", h->getCompressFraction());
}
Launchbar* l = airplane->getLaunchbar();
if(l) {
SGPropertyNode * node = fgGetNode("gear/launchbar", 0, true);
node->setFloatValue("position-norm", l->getCompressFraction());
node->setFloatValue("holdback-position-norm", l->getHoldbackCompressFraction());
node->setStringValue("state", l->getState());
node->setBoolValue("strop", l->getStrop());
}
}