sophus_sensor/distortions/
enhanced_unified.rs1use core::{
2 borrow::Borrow,
3 marker::PhantomData,
4};
5
6use sophus_autodiff::{
7 params::IsParamsImpl,
8 prelude::{
9 IsMatrix,
10 IsScalar,
11 IsVector,
12 },
13};
14
15use crate::{
16 prelude::*,
17 traits::IsCameraDistortionImpl,
18};
19
20extern crate alloc;
21
22#[derive(Debug, Clone, Copy)]
24pub struct EnhancedUnifiedDistortionImpl<
25 S: IsScalar<BATCH, DM, DN>,
26 const BATCH: usize,
27 const DM: usize,
28 const DN: usize,
29> {
30 phantom: PhantomData<S>,
31}
32
33impl<S: IsScalar<BATCH, DM, DN>, const BATCH: usize, const DM: usize, const DN: usize>
34 IsParamsImpl<S, 6, BATCH, DM, DN> for EnhancedUnifiedDistortionImpl<S, BATCH, DM, DN>
35{
36 fn are_params_valid(_params: S::Vector<6>) -> S::Mask {
37 S::Mask::all_true()
38 }
39
40 fn params_examples() -> alloc::vec::Vec<S::Vector<6>> {
41 alloc::vec![S::Vector::<6>::from_f64_array([
42 1.0, 1.0, 0.0, 0.0, 0.0, 0.0,
43 ])]
44 }
45
46 fn invalid_params_examples() -> alloc::vec::Vec<S::Vector<6>> {
47 alloc::vec![
48 S::Vector::<6>::from_f64_array([0.0, 1.0, 0.0, 0.0, 0.0, 0.0]),
49 S::Vector::<6>::from_f64_array([1.0, 0.0, 0.0, 0.0, 0.0, 0.0]),
50 ]
51 }
52}
53
54impl<S: IsScalar<BATCH, DM, DN>, const BATCH: usize, const DM: usize, const DN: usize>
56 IsCameraDistortionImpl<S, 2, 6, BATCH, DM, DN>
57 for EnhancedUnifiedDistortionImpl<S, BATCH, DM, DN>
58{
59 fn distort<PA, PO>(params: PA, proj_point_in_camera_z1_plane: PO) -> S::Vector<2>
60 where
61 PA: Borrow<S::Vector<6>>,
62 PO: Borrow<S::Vector<2>>,
63 {
64 let params = params.borrow();
65 let proj_point_in_camera_z1_plane = proj_point_in_camera_z1_plane.borrow();
66
67 let fx = params.elem(0);
69 let fy = params.elem(1);
70 let cx = params.elem(2);
71 let cy = params.elem(3);
72 let alpha = params.elem(4);
73 let beta = params.elem(5);
74
75 let x = proj_point_in_camera_z1_plane.elem(0);
76 let y = proj_point_in_camera_z1_plane.elem(1);
77
78 let r2 = x * x + y * y;
79 let rho2 = beta * r2 + S::from_f64(1.0);
80 let rho = rho2.sqrt();
81
82 let norm = alpha * rho + (S::from_f64(1.0) - alpha);
83
84 let mx = x / norm;
85 let my = y / norm;
86
87 S::Vector::<2>::from_array([fx * mx + cx, fy * my + cy])
88 }
89
90 fn undistort<PA, PO>(params: PA, distorted_point: PO) -> S::Vector<2>
91 where
92 PA: Borrow<S::Vector<6>>,
93 PO: Borrow<S::Vector<2>>,
94 {
95 let params = params.borrow();
96 let distorted_point = distorted_point.borrow();
97 let fx = params.elem(0);
98 let fy = params.elem(1);
99 let cx = params.elem(2);
100 let cy = params.elem(3);
101 let alpha = params.elem(4);
102 let beta = params.elem(5);
103
104 let mx = (distorted_point.elem(0) - cx) / fx;
105 let my = (distorted_point.elem(1) - cy) / fy;
106
107 let r2 = mx * mx + my * my;
108 let gamma = S::from_f64(1.0) - alpha;
109
110 let nominator = S::from_f64(1.0) - alpha * alpha * beta * r2;
111 let denominator = alpha * (S::from_f64(1.0) - (alpha - gamma) * beta * r2).sqrt() + gamma;
112
113 let k = nominator / denominator;
114
115 S::Vector::<2>::from_array([mx / k, my / k])
116 }
117 fn dx_distort_x<PA, PO>(params: PA, proj_point_in_camera_z1_plane: PO) -> S::Matrix<2, 2>
118 where
119 PA: Borrow<S::Vector<6>>,
120 PO: Borrow<S::Vector<2>>,
121 {
122 let params = params.borrow();
123 let proj_point_in_camera_z1_plane = proj_point_in_camera_z1_plane.borrow();
124
125 let fx = params.elem(0);
126 let fy = params.elem(1);
127 let alpha = params.elem(4);
128 let beta = params.elem(5);
129
130 let x = proj_point_in_camera_z1_plane.elem(0);
131 let y = proj_point_in_camera_z1_plane.elem(1);
132
133 let r2 = x * x + y * y;
134 let rho2 = beta * r2 + S::from_f64(1.0);
135 let rho = rho2.sqrt();
136
137 let norm = alpha * rho + (S::from_f64(1.0) - alpha);
138
139 let drho2_dx = S::from_f64(2.0) * beta * x;
141 let drho2_dy = S::from_f64(2.0) * beta * y;
142
143 let drho_dx = drho2_dx / (S::from_f64(2.0) * rho);
144 let drho_dy = drho2_dy / (S::from_f64(2.0) * rho);
145
146 let dnorm_dx = alpha * drho_dx;
147 let dnorm_dy = alpha * drho_dy;
148
149 let dmx_dx = (norm - x * dnorm_dx) / (norm * norm);
150 let dmx_dy = -x * dnorm_dy / (norm * norm);
151
152 let dmy_dx = -y * dnorm_dx / (norm * norm);
153 let dmy_dy = (norm - y * dnorm_dy) / (norm * norm);
154
155 S::Matrix::<2, 2>::from_array2([[fx * dmx_dx, fx * dmx_dy], [fy * dmy_dx, fy * dmy_dy]])
156 }
157
158 fn dx_distort_params<PA, PO>(params: PA, proj_point_in_camera_z1_plane: PO) -> S::Matrix<2, 6>
159 where
160 PA: Borrow<S::Vector<6>>,
161 PO: Borrow<S::Vector<2>>,
162 {
163 let params = params.borrow();
164 let proj_point_in_camera_z1_plane = proj_point_in_camera_z1_plane.borrow();
165
166 let fx = params.elem(0);
167 let fy = params.elem(1);
168 let alpha = params.elem(4);
169 let beta = params.elem(5);
170
171 let x = proj_point_in_camera_z1_plane.elem(0);
172 let y = proj_point_in_camera_z1_plane.elem(1);
173
174 let r2 = x * x + y * y;
175 let rho2 = beta * r2 + S::from_f64(1.0);
176 let rho = rho2.sqrt();
177
178 let norm = alpha * rho + (S::from_f64(1.0) - alpha);
179
180 let drho2_dbeta = r2;
182 let drho_dbeta = drho2_dbeta / (S::from_f64(2.0) * rho);
183
184 let dnorm_dalpha = rho - S::from_f64(1.0);
185 let dnorm_dbeta = alpha * drho_dbeta;
186
187 let mx = x / norm;
188 let my = y / norm;
189
190 let dmx_dalpha = -x * dnorm_dalpha / (norm * norm);
191 let dmy_dalpha = -y * dnorm_dalpha / (norm * norm);
192
193 let dmx_dbeta = -x * dnorm_dbeta / (norm * norm);
194 let dmy_dbeta = -y * dnorm_dbeta / (norm * norm);
195
196 S::Matrix::<2, 6>::from_array2([
197 [
198 mx,
199 S::zero(),
200 S::ones(),
201 S::zero(),
202 fx * dmx_dalpha,
203 fx * dmx_dbeta,
204 ],
205 [
206 S::zero(),
207 my,
208 S::zero(),
209 S::ones(),
210 fy * dmy_dalpha,
211 fy * dmy_dbeta,
212 ],
213 ])
214 }
215
216 fn identity_params() -> S::Vector<6> {
217 let mut params = S::Vector::<6>::zeros();
218 *params.elem_mut(0) = <S>::ones();
219 *params.elem_mut(1) = <S>::ones();
220 params
221 }
222}