1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use crate::{Bearing, CameraPoint, EssentialMatrix, FeatureWorldMatch, Skew3, WorldPoint};
use derive_more::{AsMut, AsRef, Deref, DerefMut, From, Into};
use nalgebra::{IsometryMatrix3, Matrix3, Matrix3x2, Matrix6x2, Matrix6x3, Rotation3, Vector3};
use sample_consensus::Model;
#[derive(Debug, Clone, Copy, PartialEq, AsMut, AsRef, Deref, DerefMut, From, Into)]
pub struct WorldPose(pub IsometryMatrix3<f64>);
impl<P> Model<FeatureWorldMatch<P>> for WorldPose
where
P: Bearing,
{
fn residual(&self, data: &FeatureWorldMatch<P>) -> f32 {
let WorldPose(iso) = *self;
let FeatureWorldMatch(feature, world) = data;
let new_bearing = (iso * world.coords).normalize();
let bearing_vector = feature.bearing();
(1.0 - bearing_vector.dot(&new_bearing)) as f32
}
}
impl WorldPose {
pub fn transform(&self, WorldPoint(point): WorldPoint) -> CameraPoint {
let WorldPose(iso) = *self;
CameraPoint(iso * point)
}
#[rustfmt::skip]
pub fn projection_pose_jacobian(&self, point: WorldPoint) -> Matrix6x2<f64> {
let pr = (self.0.rotation * point.0).coords;
let pc = (self.0 * point.0).coords;
let dp_dt = Matrix3::<f64>::identity();
let dp_dr = Skew3::jacobian_output_to_self(pr);
let dp_dtq = Matrix6x3::<f64>::from_rows(&[
dp_dt.row(0),
dp_dt.row(1),
dp_dt.row(2),
dp_dr.row(0),
dp_dr.row(1),
dp_dr.row(2),
]);
let pcz = pc.z.recip();
let npcz2 = -(pcz * pcz);
let dk_dp = Matrix3x2::new(
pcz, 0.0,
0.0, pcz,
npcz2, npcz2,
);
dp_dtq * dk_dp
}
}
impl From<CameraPose> for WorldPose {
fn from(camera: CameraPose) -> Self {
Self(camera.inverse())
}
}
#[derive(Debug, Clone, Copy, PartialEq, AsMut, AsRef, Deref, DerefMut, From, Into)]
pub struct CameraPose(pub IsometryMatrix3<f64>);
impl CameraPose {
pub fn identity() -> Self {
Self(IsometryMatrix3::identity())
}
}
impl From<WorldPose> for CameraPose {
fn from(world: WorldPose) -> Self {
Self(world.inverse())
}
}
#[derive(Debug, Clone, Copy, PartialEq, AsMut, AsRef, Deref, DerefMut, From, Into)]
pub struct RelativeCameraPose(pub IsometryMatrix3<f64>);
impl RelativeCameraPose {
pub fn from_parts(rotation: Rotation3<f64>, translation: Vector3<f64>) -> Self {
Self(IsometryMatrix3::from_parts(translation.into(), rotation))
}
pub fn transform(&self, CameraPoint(point): CameraPoint) -> CameraPoint {
let Self(iso) = *self;
CameraPoint(iso * point)
}
pub fn essential_matrix(&self) -> EssentialMatrix {
EssentialMatrix(self.0.translation.vector.cross_matrix() * *self.0.rotation.matrix())
}
}
#[derive(Debug, Clone, Copy, PartialEq, AsMut, AsRef, Deref, DerefMut, From, Into)]
pub struct UnscaledRelativeCameraPose(pub RelativeCameraPose);