CogniPilot

MODELICA LIBRARY · ENGINEERING REFERENCE

SLAM/Inertial/SLAMCovariancePSDCheck.mo

Download original .moGitHub source

Documentation: SLAM.Inertial.SLAMCovariancePSDCheck

within SLAM.Inertial;
// A correlated, frozen reference pose is a Schmidt state, not pose truth.
// World-additive p/v; right-local body attitude; current state order p,v,theta,ba,bg.
// Registration maps reference optical points to current optical coordinates.
// Compile with RGBDRelativePose.mo, ES15PoseCorrection.mo and SPD6Solve.mo.
// These components are under numerical review; the production preset is unchanged.
// Sequential validation only: tolerance jitter never enters retained covariance.
// The function owns factor ordering instead of a cyclic equation-form factor graph.
function SLAMCovariancePSDCheck
  input Real covariance[:,:];
  input Real relativeTolerance;
  output Real valid;
protected
  Real scale;
  Real pivot;
  Real diagonalScale;
  Real diagonalSum;
  Real offDiagonalSum;
  Real lower[size(covariance,1),size(covariance,1)];
algorithm
  diagonalScale := 0.0;
  diagonalSum := 0.0;
  offDiagonalSum := 0.0;
  for i in 1:size(covariance,1) loop
    diagonalScale := diagonalScale+abs(covariance[i,i]);
  end for;
  scale := max(1.0,diagonalScale);
  lower := zeros(size(covariance,1),size(covariance,1));
  pivot := 0.0;
  valid := if size(covariance,1) == size(covariance,2) then 1.0 else 0.0;
  for i in 1:size(covariance,1) loop
    for j in 1:size(covariance,1) loop
      offDiagonalSum := 0.0;
      diagonalSum := 0.0;
      // Ordered finite accumulation; no array-valued comprehension temporary.
      for k in 1:size(covariance,1) loop
        offDiagonalSum := offDiagonalSum+(if k < j then lower[i,k]*lower[j,k] else 0.0);
        diagonalSum := diagonalSum+(if k < i then lower[i,k]^2 else 0.0);
      end for;
      if not (abs(covariance[i,j]) <= 1e12 and
          abs(covariance[i,j]-covariance[j,i]) <= relativeTolerance*scale) then
        valid := 0.0;
      end if;
      if j < i then
        lower[i,j] := (covariance[i,j]-offDiagonalSum)
          /max(lower[j,j],1e-150);
      elseif j == i then
        pivot := covariance[i,i]+relativeTolerance*scale
          -diagonalSum;
        if not (pivot > 0.0 and pivot <= 1e12) then valid := 0.0; end if;
        lower[i,j] := sqrt(if pivot > 0.0 then pivot else 1.0);
      end if;
    end for;
  end for;
end SLAMCovariancePSDCheck;