深蓝学院《从零开始手写VIO》作业五
深蓝学院《从零开始手写VIO》作业六
1. 证明题
证明 D y = 0 Dy=0 Dy=0的最优解 y y y等于 D T D D^TD DTD的最小奇异值对应的奇异值向量
矩阵
D
T
D
D^TD
DTD的奇异值分解如下:
D
⊤
D
=
∑
i
=
1
4
σ
i
2
u
i
u
j
⊤
\mathbf{D}^{\top} \mathbf{D}=\sum_{i=1}^{4} \sigma_{i}^{2} \mathbf{u}_{i} \mathbf{u}_{j}^{\top}
D⊤D=i=1∑4σi2uiuj⊤
回顾我们的原始问题如下:
求解
D
2
n
×
4
y
4
×
1
=
0
D_{2n×4}y_{4×1}=0
D2n×4y4×1=0,这是一个超定方程,本质上求解得到的是一个最小二乘解,使用如下表示:
min
y
∣
∣
D
y
∣
∣
2
=
(
D
y
)
T
(
D
y
)
=
y
T
D
T
D
y
\min _{y} ||Dy||^2 = (Dy)^T(Dy) = y^TD^TDy
ymin∣∣Dy∣∣2=(Dy)T(Dy)=yTDTDy
其中
∣
∣
y
∣
∣
=
1
||y|| = 1
∣∣y∣∣=1
y
y
y可以由
D
T
D
D^TD
DTD的奇异值向量线性组合得到,也就是可以表示成如下形式
y
=
∑
i
=
1
4
k
i
u
i
=
k
i
u
i
+
v
y = \sum_{i=1}^{4} k_iu_i = k_iu_i+v
y=i=1∑4kiui=kiui+v
其中
v
=
∑
j
=
1
,
j
≠
i
4
k
j
u
j
v=\sum_{j=1,j\not=i}^{4}k_ju_j
v=j=1,j=i∑4kjuj
k
i
,
k
j
∈
R
k_i,k_j \in R
ki,kj∈R
容易知道
u
i
u_i
ui和
v
v
v正交。
将
y
y
y代入
y
T
D
T
D
y
y^TD^TDy
yTDTDy得到
min
y
∣
∣
D
y
∣
∣
2
=
(
k
i
u
i
+
v
)
T
D
T
D
(
k
i
u
i
+
v
)
=
k
i
2
u
i
T
D
T
D
u
i
+
v
T
D
T
D
v
+
k
i
u
i
T
D
T
D
v
+
k
i
v
T
D
T
D
u
i
\min _{y} ||Dy||^2 = (k_iu_i+v)^TD^TD(k_iu_i+v) = k_i^2u_i^TD^TDu_i+ v^TD^TDv + k_iu_i^TD^TDv +k_iv^TD^TDu_i
ymin∣∣Dy∣∣2=(kiui+v)TDTD(kiui+v)=ki2uiTDTDui+vTDTDv+kiuiTDTDv+kivTDTDui
由于
u
i
u_i
ui和
v
v
v正交,所以后两项为0;并且
D
u
i
=
σ
i
u
i
Du_i = \sigma_iu_i
Dui=σiui,带入得到
min
y
∣
∣
D
y
∣
∣
2
=
(
k
i
u
i
+
v
)
T
D
T
D
(
k
i
u
i
+
v
)
=
k
i
2
u
i
T
D
T
D
u
i
+
v
T
D
T
D
v
=
k
i
2
σ
i
2
∣
∣
u
i
∣
∣
2
+
v
T
D
T
D
v
>
=
k
i
2
σ
i
2
∣
∣
u
i
∣
∣
2
\min _{y} ||Dy||^2 = (k_iu_i+v)^TD^TD(k_iu_i+v) = k_i^2u_i^TD^TDu_i+ v^TD^TDv = k_i^2\sigma_i^2||u_i||^2 + v^TD^TDv >= k_i^2\sigma_i^2||u_i||^2
ymin∣∣Dy∣∣2=(kiui+v)TDTD(kiui+v)=ki2uiTDTDui+vTDTDv=ki2σi2∣∣ui∣∣2+vTDTDv>=ki2σi2∣∣ui∣∣2
当且仅当
v
=
0
v=0
v=0的时候等号成立。
如果想取得最小值,则
σ
i
=
σ
4
\sigma_i=\sigma_4
σi=σ4,也就是取得最小奇异值的时候,目标函数取得最小值,此时
y
=
k
4
u
4
+
v
=
k
4
u
4
y = k_4u_4+v=k_4u_4
y=k4u4+v=k4u4
由于
∣
∣
y
∣
∣
=
1
||y||=1
∣∣y∣∣=1,所以
k
4
=
1
k_4=1
k4=1,所以
y
=
u
4
y = u_4
y=u4
证明完毕。
2. 代码题
代码如下:
/// TODO::homework; 请完成三角化估计深度的代码
// 遍历所有的观测数据,并三角化
Eigen::Vector3d P_est; // 结果保存到这个变量
P_est.setZero();
/* your code begin */
Eigen::MatrixXd matD = ConstructMatrixD(camera_pose);
Eigen::BDCSVD<Eigen::MatrixXd> bcdsvd(matD.transpose()*matD, Eigen::ComputeFullV | Eigen::ComputeFullU);
auto singular_values = bcdsvd.singularValues();
auto matU = bcdsvd.matrixU();
auto matV = bcdsvd.matrixV();
// result 1
auto tmp_y = matU.rightCols(1);
auto real_y = tmp_y/tmp_y(3);
// result2
double s = matD.maxCoeff();
Eigen::Matrix4d scale_mat = Eigen::Matrix4d::Identity()/s;
auto matD_new = matD*scale_mat;
Eigen::BDCSVD<Eigen::MatrixXd> bcdsvd_new(matD_new.transpose()*matD_new, Eigen::ComputeFullV | Eigen::ComputeFullU);
auto matU_new = bcdsvd_new.matrixU();
auto tmp_y_new = scale_mat*matU_new.rightCols(1); //结果一样
auto real_y_new = tmp_y_new/tmp_y_new(3);
/* your code end */
结果如下:
ground truth:
-2.9477 -0.330799 8.43792
[normal solve] your result1:
-2.9477 -0.330799 8.43792 1
[using Scale solve] your result2:
-2.9477 -0.330799 8.43792 1