CogniPilot

MODELICA LIBRARY · ENGINEERING REFERENCE

LieGroups/SO3/EulerB321/from_Quat.mo

Download original .moGitHub source

Documentation: LieGroups.SO3.EulerB321.from_Quat

within LieGroups.SO3.EulerB321;
function from_Quat "Convert quaternion to Euler B321 angles {yaw, pitch, roll}"
  input Real q[4] "Unit quaternion {w,x,y,z}";
  output Real euler[3] "{yaw (psi), pitch (theta), roll (phi)} [rad]";
protected
  Real a, b, c, d;
  Real sinp;
algorithm
  a := q[1]; b := q[2]; c := q[3]; d := q[4];

  // Pitch: theta = asin(2*(ac - bd))
  sinp := 2.0*(a*c - d*b);
  sinp := min(max(sinp, -1.0), 1.0);

  // Each branch assembles the whole {yaw, pitch, roll} triple with one vector
  // assignment. The galec production lowering keeps only the last per-element
  // write inside a conditional branch, so writing euler[1..3] separately would
  // drop yaw and pitch; the single vector form emits all three components.
  if sinp * sinp > 0.9999 * 0.9999 then
    // Gimbal lock: pitch near +/- 90 deg
    euler := {atan2(2.0*(b*c + a*d), 1.0 - 2.0*(c*c + d*d)),
              asin(sinp),
              0.0};
  else
    euler := {atan2(2.0*(a*d + b*c), 1.0 - 2.0*(c*c + d*d)),
              asin(sinp),
              atan2(2.0*(a*b + c*d), 1.0 - 2.0*(b*b + c*c))};
  end if;
end from_Quat;