lox_frames/transformations/
rotations.rs1use std::ops::Mul;
6
7use glam::{DMat3, DVec3};
8use lox_core::coords::Cartesian;
9
10pub fn rotation_matrix_derivative(m: DMat3, v: DVec3) -> DMat3 {
11 let sx = DVec3::new(0.0, v.z, v.y);
12 let sy = DVec3::new(-v.z, 0.0, v.x);
13 let sz = DVec3::new(v.y, -v.x, 0.0);
14 let s = DMat3::from_cols(sx, sy, sz);
15 -s * m
16}
17
18pub struct Rotation {
19 m: DMat3,
21 dm: DMat3,
23}
24
25impl Rotation {
26 pub const IDENTITY: Self = Self {
27 m: DMat3::IDENTITY,
28 dm: DMat3::ZERO,
29 };
30
31 pub fn new(m: DMat3) -> Self {
32 Self { m, dm: DMat3::ZERO }
33 }
34
35 pub fn with_derivative(mut self, dm: DMat3) -> Self {
36 self.dm = dm;
37 self
38 }
39
40 pub fn with_angular_velocity(mut self, v: DVec3) -> Self {
41 self.dm = rotation_matrix_derivative(self.m, v);
42 self
43 }
44
45 pub fn position_matrix(&self) -> DMat3 {
46 self.m
47 }
48
49 pub fn velocity_matrix(&self) -> DMat3 {
50 self.dm
51 }
52
53 pub fn compose(self, other: Self) -> Self {
54 Self {
55 m: other.m * self.m,
56 dm: other.dm * self.m + other.m * self.dm,
57 }
58 }
59
60 pub fn transpose(&self) -> Self {
61 let m = self.m.transpose();
62 let dm = self.dm.transpose();
63 Self { m, dm }
64 }
65
66 pub fn rotate_position(&self, pos: DVec3) -> DVec3 {
67 self.m * pos
68 }
69
70 pub fn rotate_velocity(&self, pos: DVec3, vel: DVec3) -> DVec3 {
71 self.dm * pos + self.m * vel
72 }
73
74 pub fn rotate_state(&self, pos: DVec3, vel: DVec3) -> (DVec3, DVec3) {
75 (self.rotate_position(pos), self.rotate_velocity(pos, vel))
76 }
77}
78
79impl Mul<DVec3> for Rotation {
80 type Output = DVec3;
81
82 fn mul(self, rhs: DVec3) -> Self::Output {
83 self.m * rhs
84 }
85}
86
87impl Mul<Cartesian> for Rotation {
88 type Output = Cartesian;
89
90 fn mul(self, rhs: Cartesian) -> Self::Output {
91 let pos = self.m * rhs.position();
92 let vel = self.dm * rhs.position() + self.m * rhs.velocity();
93 Cartesian::from_vecs(pos, vel)
94 }
95}