Add errors for pitch, based on a modified equation contributed by
Chris Metzler.
This commit is contained in:
parent
956823b161
commit
04842a0f5b
2 changed files with 51 additions and 30 deletions
|
@ -59,14 +59,14 @@ MagCompass::init ()
|
||||||
|
|
||||||
SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
|
SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
|
||||||
_serviceable_node = node->getChild("serviceable", 0, true);
|
_serviceable_node = node->getChild("serviceable", 0, true);
|
||||||
_heading_node =
|
|
||||||
fgGetNode("/orientation/heading-deg", true);
|
|
||||||
_roll_node =
|
_roll_node =
|
||||||
fgGetNode("/orientation/roll-deg", true);
|
fgGetNode("/orientation/roll-deg", true);
|
||||||
|
_pitch_node =
|
||||||
|
fgGetNode("/orientation/pitch-deg", true);
|
||||||
|
_heading_node =
|
||||||
|
fgGetNode("/orientation/heading-magnetic-deg", true);
|
||||||
_beta_node =
|
_beta_node =
|
||||||
fgGetNode("/orientation/side-slip-deg", true);
|
fgGetNode("/orientation/side-slip-deg", true);
|
||||||
_variation_node =
|
|
||||||
fgGetNode("/environment/magnetic-variation-deg", true);
|
|
||||||
_dip_node =
|
_dip_node =
|
||||||
fgGetNode("/environment/magnetic-dip-deg", true);
|
fgGetNode("/environment/magnetic-dip-deg", true);
|
||||||
_north_accel_node =
|
_north_accel_node =
|
||||||
|
@ -84,47 +84,69 @@ MagCompass::init ()
|
||||||
void
|
void
|
||||||
MagCompass::update (double delta_time_sec)
|
MagCompass::update (double delta_time_sec)
|
||||||
{
|
{
|
||||||
|
// don't update if it's broken
|
||||||
|
if (!_serviceable_node->getBoolValue())
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Formula for northernly turning error from
|
Formula for northernly turning error from
|
||||||
http://williams.best.vwh.net/compass/node4.html:
|
http://williams.best.vwh.net/compass/node4.html:
|
||||||
|
|
||||||
Hc: compass heading
|
Hc: compass heading
|
||||||
Hm: magnetic heading
|
psi: magnetic heading
|
||||||
theta: bank angle (right positive; should be phi here)
|
theta: bank angle (right positive; should be phi here)
|
||||||
mu: dip angle (down positive)
|
mu: dip angle (down positive)
|
||||||
|
|
||||||
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
|
||||||
|
psi for the heading, theta for the pitch, and phi for the
|
||||||
|
roll. It also modifies the equation to incorporate pitch
|
||||||
|
as well as roll, as suggested by Chris Metzler.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// don't update if it's broken
|
// bank angle (radians)
|
||||||
if (!_serviceable_node->getBoolValue())
|
double phi = _roll_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
|
||||||
return;
|
|
||||||
|
|
||||||
// TODO use cached nodes
|
// pitch angle (radians)
|
||||||
|
double theta = _pitch_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
|
||||||
|
|
||||||
// magnetic heading (radians)
|
// magnetic heading (radians)
|
||||||
double Hm =
|
double psi = _heading_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
|
||||||
fgGetDouble("/orientation/heading-magnetic-deg")
|
|
||||||
* SGD_DEGREES_TO_RADIANS;
|
|
||||||
|
|
||||||
// bank angle (radians)
|
// magnetic dip (radians)
|
||||||
double phi =
|
double mu = _dip_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
|
||||||
fgGetDouble("/orientation/roll-deg") * SGD_DEGREES_TO_RADIANS;
|
|
||||||
|
|
||||||
// magnetic dip (radians)
|
|
||||||
double mu =
|
|
||||||
fgGetDouble("/environment/magnetic-dip-deg") * SGD_DEGREES_TO_RADIANS;
|
|
||||||
|
|
||||||
// target compass heading (radians)
|
////////////////////////////////////////////////////////////////////
|
||||||
double Hc =
|
// calculate target compass heading Hc in degrees
|
||||||
atan2(sin(Hm) * cos(phi) - tan(mu) * sin(phi), cos(Hm));
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// these are expensive: don't repeat
|
||||||
|
double sin_phi = sin(phi);
|
||||||
|
double sin_theta = sin(theta);
|
||||||
|
double sin_mu = sin(mu);
|
||||||
|
double cos_theta = cos(theta);
|
||||||
|
double cos_psi = cos(psi);
|
||||||
|
double cos_mu = cos(mu);
|
||||||
|
|
||||||
|
double a = cos(phi) * sin(psi) * cos_mu
|
||||||
|
- sin_phi * cos_theta * sin_mu
|
||||||
|
- sin_phi* sin_theta * cos_mu * cos_psi;
|
||||||
|
|
||||||
|
double b = cos_theta * cos_psi * cos(mu)
|
||||||
|
- sin_theta * sin_mu;
|
||||||
|
|
||||||
|
double Hc = atan2(a, b) * SGD_RADIANS_TO_DEGREES;
|
||||||
|
|
||||||
Hc *= SGD_RADIANS_TO_DEGREES;
|
|
||||||
while (Hc < 0)
|
while (Hc < 0)
|
||||||
Hc += 360;
|
Hc += 360;
|
||||||
while (Hc >= 360)
|
while (Hc >= 360)
|
||||||
Hc =- 360;
|
Hc =- 360;
|
||||||
|
|
||||||
|
// TODO add acceleration error
|
||||||
|
// TODO allow binding with excessive dip/sideslip
|
||||||
|
|
||||||
_out_node->setDoubleValue(Hc);
|
_out_node->setDoubleValue(Hc);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,10 @@
|
||||||
* Input properties:
|
* Input properties:
|
||||||
*
|
*
|
||||||
* /instrumentation/"name"/serviceable
|
* /instrumentation/"name"/serviceable
|
||||||
* /orientation/heading-deg
|
* /orientation/roll-deg
|
||||||
* /orientation/beta-deg
|
* /orientation/pitch-deg
|
||||||
* /environment/magnetic-variation-deg
|
* /orientation/heading-magnetic-deg
|
||||||
|
* /orientation/side-slip-deg
|
||||||
* /environment/magnetic-dip-deg
|
* /environment/magnetic-dip-deg
|
||||||
* /accelerations/ned/north-accel-fps_sec
|
* /accelerations/ned/north-accel-fps_sec
|
||||||
* /accelerations/ned/east-accel-fps_sec
|
* /accelerations/ned/east-accel-fps_sec
|
||||||
|
@ -54,13 +55,11 @@ private:
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
SGPropertyNode_ptr _serviceable_node;
|
SGPropertyNode_ptr _serviceable_node;
|
||||||
SGPropertyNode_ptr _heading_node;
|
|
||||||
SGPropertyNode_ptr _roll_node;
|
SGPropertyNode_ptr _roll_node;
|
||||||
|
SGPropertyNode_ptr _pitch_node;
|
||||||
|
SGPropertyNode_ptr _heading_node;
|
||||||
SGPropertyNode_ptr _beta_node;
|
SGPropertyNode_ptr _beta_node;
|
||||||
SGPropertyNode_ptr _variation_node;
|
|
||||||
SGPropertyNode_ptr _dip_node;
|
SGPropertyNode_ptr _dip_node;
|
||||||
SGPropertyNode_ptr _y_accel_node;
|
|
||||||
SGPropertyNode_ptr _z_accel_node;
|
|
||||||
SGPropertyNode_ptr _north_accel_node;
|
SGPropertyNode_ptr _north_accel_node;
|
||||||
SGPropertyNode_ptr _east_accel_node;
|
SGPropertyNode_ptr _east_accel_node;
|
||||||
SGPropertyNode_ptr _down_accel_node;
|
SGPropertyNode_ptr _down_accel_node;
|
||||||
|
|
Loading…
Reference in a new issue