1use nalgebra::{Matrix3, Matrix4, Matrix6, Vector3, Vector6};
9
10use super::jacobian::{inverse_left_jacobian_so3, left_jacobian_so3};
11use super::so3::{So3, hat};
12
13#[derive(Debug, Clone, Copy, PartialEq)]
15pub struct Se3 {
16 rotation: So3,
17 translation: Vector3<f64>,
18}
19
20impl Se3 {
21 pub fn identity() -> Self {
23 Self {
24 rotation: So3::identity(),
25 translation: Vector3::zeros(),
26 }
27 }
28
29 pub fn from_parts(rotation: So3, translation: Vector3<f64>) -> Self {
31 Self {
32 rotation,
33 translation,
34 }
35 }
36
37 pub fn from_matrix_unchecked(matrix: Matrix4<f64>) -> Self {
43 Self {
44 rotation: So3::from_matrix_unchecked(matrix.fixed_view::<3, 3>(0, 0).into()),
45 translation: Vector3::new(matrix[(0, 3)], matrix[(1, 3)], matrix[(2, 3)]),
46 }
47 }
48
49 pub fn rotation(&self) -> &So3 {
51 &self.rotation
52 }
53
54 pub fn translation(&self) -> &Vector3<f64> {
56 &self.translation
57 }
58
59 pub fn matrix(&self) -> Matrix4<f64> {
61 let mut m = Matrix4::identity();
62 m.fixed_view_mut::<3, 3>(0, 0)
63 .copy_from(self.rotation.matrix());
64 m.fixed_view_mut::<3, 1>(0, 3).copy_from(&self.translation);
65 m
66 }
67
68 pub fn exp(xi: &Vector6<f64>) -> Self {
73 let rho = Vector3::new(xi[0], xi[1], xi[2]);
74 let phi = Vector3::new(xi[3], xi[4], xi[5]);
75 Self {
76 rotation: So3::exp(&phi),
77 translation: left_jacobian_so3(&phi) * rho,
78 }
79 }
80
81 pub fn log(&self) -> Vector6<f64> {
83 let phi = self.rotation.log();
84 let rho = inverse_left_jacobian_so3(&phi) * self.translation;
85 Vector6::new(rho[0], rho[1], rho[2], phi[0], phi[1], phi[2])
86 }
87
88 pub fn inverse(&self) -> Self {
90 let inv_rotation = self.rotation.inverse();
91 Self {
92 rotation: inv_rotation,
93 translation: -(inv_rotation * self.translation),
94 }
95 }
96
97 pub fn adjoint(&self) -> Matrix6<f64> {
102 let r = *self.rotation.matrix();
103 let t_hat = hat(&self.translation);
104 let mut adj = Matrix6::zeros();
105 adj.fixed_view_mut::<3, 3>(0, 0).copy_from(&r);
106 adj.fixed_view_mut::<3, 3>(0, 3).copy_from(&(t_hat * r));
107 adj.fixed_view_mut::<3, 3>(3, 3).copy_from(&r);
108 adj
109 }
110
111 pub fn transform_point(&self, p: &Vector3<f64>) -> Vector3<f64> {
113 self.rotation * *p + self.translation
114 }
115}
116
117impl std::ops::Mul for Se3 {
118 type Output = Se3;
119 fn mul(self, rhs: Se3) -> Se3 {
120 Se3 {
121 rotation: self.rotation * rhs.rotation,
122 translation: self.rotation * rhs.translation + self.translation,
123 }
124 }
125}
126
127impl Default for Se3 {
128 fn default() -> Self {
129 Self::identity()
130 }
131}
132
133pub fn hat_se3(xi: &Vector6<f64>) -> Matrix4<f64> {
135 let phi = Vector3::new(xi[3], xi[4], xi[5]);
136 let mut m = Matrix4::zeros();
137 m.fixed_view_mut::<3, 3>(0, 0).copy_from(&hat(&phi));
138 m[(0, 3)] = xi[0];
139 m[(1, 3)] = xi[1];
140 m[(2, 3)] = xi[2];
141 m
142}
143
144pub fn vee_se3(m: &Matrix4<f64>) -> Vector6<f64> {
146 let rot: Matrix3<f64> = m.fixed_view::<3, 3>(0, 0).into();
147 Vector6::new(
148 m[(0, 3)],
149 m[(1, 3)],
150 m[(2, 3)],
151 rot[(2, 1)],
152 rot[(0, 2)],
153 rot[(1, 0)],
154 )
155}