CogniPilot

MODELICA LIBRARY · ENGINEERING REFERENCE

Estimation/StrapdownINS/magnetometerVectorObservation.mo

Download original .moGitHub source

Documentation: Estimation.StrapdownINS.magnetometerVectorObservation

within Estimation.StrapdownINS;

function magnetometerVectorObservation
  "Scale a magnetic-vector residual and its symmetric SO(3) output linearization"
  input Real quaternionWorldBody[4];
  input Real magneticFieldBodyFlu_T[3];
  input Real covarianceBody_T2[3, 3];
  input Real magneticFieldWorldEnu_T[3];
  output Real residual[3];
  output Real attitudeJacobian[3, 3];
  output Real covariance[3, 3];
  output Boolean accepted;
protected
  Real rotationWorldBody[3, 3];
  Real fieldMagnitudeSquared;
  Real fieldScale;
  Real predictedField[3];
  Real measuredField[3];
  Real inverseCovariance[3, 3];
  Boolean covarianceUsable;
algorithm
  rotationWorldBody := LieGroups.SO3.Quat.to_DCM(quaternionWorldBody);
  fieldMagnitudeSquared := magneticFieldWorldEnu_T * magneticFieldWorldEnu_T;
  fieldScale := sqrt(max(fieldMagnitudeSquared, 1.0e-20));
  predictedField := transpose(rotationWorldBody)
    * magneticFieldWorldEnu_T / fieldScale;
  measuredField := magneticFieldBodyFlu_T / fieldScale;
  residual := measuredField - predictedField;
  attitudeJacobian := LieGroups.SO3.Quat.wedge(
    0.5 * (predictedField + measuredField));
  covariance := covarianceBody_T2 / fieldScale^2;
  (inverseCovariance, covarianceUsable) := LinearAlgebra.solveSPD(
    covariance, identity(3));
  accepted := covarianceUsable and fieldMagnitudeSquared > 1.0e-20
    and fieldMagnitudeSquared < ESKF.FiniteMagnitudeLimit;
  for axis in 1:3 loop
    accepted := accepted
      and abs(magneticFieldBodyFlu_T[axis]) < ESKF.FiniteMagnitudeLimit
      and abs(magneticFieldWorldEnu_T[axis]) < ESKF.FiniteMagnitudeLimit;
  end for;
end magnetometerVectorObservation;