Use angular momentum so that the compass can overshoot and oscillate
before settling.
This commit is contained in:
parent
079bc3196e
commit
2f13bafff5
1 changed files with 33 additions and 19 deletions
|
@ -11,6 +11,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <plib/sg.h>
|
#include <plib/sg.h>
|
||||||
|
#include <simgear/sg_inlines.h>
|
||||||
|
|
||||||
#include "mag_compass.hxx"
|
#include "mag_compass.hxx"
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
|
@ -76,8 +77,6 @@ MagCompass::init ()
|
||||||
_z_accel_node =
|
_z_accel_node =
|
||||||
fgGetNode("/accelerations/pilot/z-accel-fps_sec", true);
|
fgGetNode("/accelerations/pilot/z-accel-fps_sec", true);
|
||||||
_out_node = node->getChild("indicated-heading-deg", 0, true);
|
_out_node = node->getChild("indicated-heading-deg", 0, true);
|
||||||
|
|
||||||
_serviceable_node->setBoolValue(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,18 +84,17 @@ void
|
||||||
MagCompass::update (double delta_time_sec)
|
MagCompass::update (double delta_time_sec)
|
||||||
{
|
{
|
||||||
// This is the real magnetic
|
// This is the real magnetic
|
||||||
// heading, which will almost
|
// which would be displayed
|
||||||
// never appear.
|
// if the compass had no errors.
|
||||||
double heading_mag_deg = _heading_node->getDoubleValue();
|
double heading_mag_deg = _heading_node->getDoubleValue();
|
||||||
|
|
||||||
|
|
||||||
// don't update if it's broken
|
// don't update if the compass
|
||||||
|
// is broken
|
||||||
if (!_serviceable_node->getBoolValue())
|
if (!_serviceable_node->getBoolValue())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
// jam on excessive sideslip
|
||||||
Jam on an excessive sideslip.
|
|
||||||
*/
|
|
||||||
if (fabs(_beta_node->getDoubleValue()) > 12.0) {
|
if (fabs(_beta_node->getDoubleValue()) > 12.0) {
|
||||||
_rate_degps = 0.0;
|
_rate_degps = 0.0;
|
||||||
return;
|
return;
|
||||||
|
@ -114,10 +112,11 @@ MagCompass::update (double delta_time_sec)
|
||||||
|
|
||||||
Hc = atan2(sin(Hm)cos(theta)-tan(mu)sin(theta), cos(Hm))
|
Hc = atan2(sin(Hm)cos(theta)-tan(mu)sin(theta), cos(Hm))
|
||||||
|
|
||||||
This function changes the variable names to the more common
|
This function changes the variable names to the more common psi
|
||||||
psi for the heading, theta for the pitch, and phi for the
|
for the heading, theta for the pitch, and phi for the roll (and
|
||||||
roll. It also modifies the equation to incorporate pitch
|
target_deg for Hc). It also modifies the equation to
|
||||||
as well as roll, as suggested by Chris Metzler.
|
incorporate pitch as well as roll, as suggested by Chris
|
||||||
|
Metzler.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// bank angle (radians)
|
// bank angle (radians)
|
||||||
|
@ -153,7 +152,7 @@ MagCompass::update (double delta_time_sec)
|
||||||
phi -= 0.07 * y_accel_g;
|
phi -= 0.07 * y_accel_g;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// calculate target compass heading Hc in degrees
|
// calculate target compass heading degrees
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// these are expensive: don't repeat
|
// these are expensive: don't repeat
|
||||||
|
@ -172,13 +171,28 @@ MagCompass::update (double delta_time_sec)
|
||||||
- sin_theta * sin_mu;
|
- sin_theta * sin_mu;
|
||||||
|
|
||||||
// This is the value that the compass
|
// This is the value that the compass
|
||||||
// is *trying* to display, but it
|
// is *trying* to display.
|
||||||
// takes time to move there, and because
|
double target_deg = atan2(a, b) * SGD_RADIANS_TO_DEGREES;
|
||||||
// of momentum, the compass will often
|
double old_deg = _out_node->getDoubleValue();
|
||||||
// overshoot.
|
|
||||||
double Hc = atan2(a, b) * SGD_RADIANS_TO_DEGREES;
|
|
||||||
|
|
||||||
_out_node->setDoubleValue(Hc);
|
while ((target_deg - old_deg) > 180.0)
|
||||||
|
target_deg -= 360.0;
|
||||||
|
while ((target_deg - old_deg) < -180.0)
|
||||||
|
target_deg += 360.0;
|
||||||
|
|
||||||
|
// The compass has a current rate of
|
||||||
|
// rotation -- move the rate of rotation
|
||||||
|
// towards one that will turn the compass
|
||||||
|
// to the correct heading, but lag a bit.
|
||||||
|
// (so that the compass can keep overshooting
|
||||||
|
// and coming back).
|
||||||
|
double error = target_deg - old_deg;
|
||||||
|
_rate_degps = fgGetLowPass(_rate_degps, error, delta_time_sec / 5.0);
|
||||||
|
double indicated_deg = old_deg + _rate_degps * delta_time_sec;
|
||||||
|
SG_NORMALIZE_RANGE(indicated_deg, 0.0, 360.0);
|
||||||
|
|
||||||
|
// That's it -- set the messed-up heading.
|
||||||
|
_out_node->setDoubleValue(indicated_deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// end of altimeter.cxx
|
// end of altimeter.cxx
|
||||||
|
|
Loading…
Reference in a new issue