use crate::data_messages::*;
impl From<RotationMatrixMessage> for QuaternionMessage {
fn from(message: RotationMatrixMessage) -> Self {
let xx = message.xx;
let xy = message.xy;
let xz = message.xz;
let yx = message.yx;
let yy = message.yy;
let yz = message.yz;
let zx = message.zx;
let zy = message.zy;
let zz = message.zz;
let tr = xx + yy + zz;
if tr > 0.0 {
let s = f32::sqrt(tr + 1.0) * 2.0; QuaternionMessage {
timestamp: message.timestamp,
w: 0.25 * s,
x: (zy - yz) / s,
y: (xz - zx) / s,
z: (yx - xy) / s,
}
} else if (xx > yy) && (xx > zz) {
let s = f32::sqrt(1.0 + xx - yy - zz) * 2.0; QuaternionMessage {
timestamp: message.timestamp,
w: (zy - yz) / s,
x: 0.25 * s,
y: (xy + yx) / s,
z: (xz + zx) / s,
}
} else if yy > zz {
let s = f32::sqrt(1.0 + yy - xx - zz) * 2.0; QuaternionMessage {
timestamp: message.timestamp,
w: (xz - zx) / s,
x: (xy + yx) / s,
y: 0.25 * s,
z: (yz + zy) / s,
}
} else {
let s = f32::sqrt(1.0 + zz - xx - yy) * 2.0; QuaternionMessage {
timestamp: message.timestamp,
w: (yx - xy) / s,
x: (xz + zx) / s,
y: (yz + zy) / s,
z: 0.25 * s,
}
}
}
}
impl From<EulerAnglesMessage> for QuaternionMessage {
fn from(message: EulerAnglesMessage) -> Self {
let psi = f32::to_radians(message.yaw);
let theta = f32::to_radians(message.pitch);
let phi = f32::to_radians(message.roll);
let cos_half_psi = f32::cos(psi * 0.5);
let sin_half_psi = f32::sin(psi * 0.5);
let cos_half_theta = f32::cos(theta * 0.5);
let sin_half_theta = f32::sin(theta * 0.5);
let cos_half_phi = f32::cos(phi * 0.5);
let sin_half_phi = f32::sin(phi * 0.5);
QuaternionMessage {
timestamp: message.timestamp,
w: cos_half_psi * cos_half_theta * cos_half_phi + sin_half_psi * sin_half_theta * sin_half_phi,
x: cos_half_psi * cos_half_theta * sin_half_phi - sin_half_psi * sin_half_theta * cos_half_phi,
y: cos_half_psi * sin_half_theta * cos_half_phi + sin_half_psi * cos_half_theta * sin_half_phi,
z: sin_half_psi * cos_half_theta * cos_half_phi - cos_half_psi * sin_half_theta * sin_half_phi,
}
}
}
impl From<QuaternionMessage> for EulerAnglesMessage {
fn from(message: QuaternionMessage) -> Self {
let w = message.w;
let x = message.x;
let y = message.y;
let z = message.z;
EulerAnglesMessage {
timestamp: message.timestamp,
roll: f32::to_degrees(f32::atan2(2.0 * (y * z + w * x), 2.0 * (w * w - 0.5 + z * z))),
pitch: f32::to_degrees(-1.0 * f32::asin(f32::clamp(2.0 * (x * z - w * y), -1.0, 1.0))),
yaw: f32::to_degrees(f32::atan2(2.0 * (x * y + w * z), 2.0 * (w * w - 0.5 + x * x))),
}
}
}
impl From<RotationMatrixMessage> for EulerAnglesMessage {
fn from(message: RotationMatrixMessage) -> Self {
QuaternionMessage::from(message).into()
}
}