I have wrong result of inverse matrix, using Eigen library. Here's my part of code:
Hessian_matrix = matrix.transpose() * matrix;
std::cout << "Hessian matrix:" << Hessian_matrix << std::endl;
std::cout << "inverse Hessian matrix" << std::endl << Hessian_matrix.inverse() << std::endl;
std::cout << "identity:" << std::endl << Hessian_matrix*Hessian_matrix.inverse() << std::endl << std::endl;
Here, matrix is a 6x6 matrix of type Eigen::MatrixXd, it's Jacobian matrix (1000 x 6). The function, that generated Jacobian matrix:
Eigen::MatrixXd tracking_module::Jacobian_matrix_of_residuals() {
const auto start = std::chrono::system_clock::now();
Eigen::MatrixXd Jacobian_matrix;
unsigned int number_of_landmark = 0;
for (auto& lm_curr_fr : curr_frm_.landmarks_) {
if (!lm_curr_fr){
continue;
}
if (lm_curr_fr->will_be_erased()){
continue;
}
for (auto& lm_prev_fr : last_frm_.landmarks_) {
if (!lm_prev_fr){
continue;
}
if (lm_prev_fr->will_be_erased()){
continue;
}
if (lm_curr_fr->id_ == lm_prev_fr->id_) {
auto pose_1 = last_frm_.cam_pose_cw_.inverse();
auto pose_2 = curr_frm_.cam_pose_cw_.inverse();
Eigen::Matrix3d X1_rot = pose_1.block<3,3>(0,0);
Eigen::Matrix3d X2_rot = pose_2.block<3,3>(0,0);
Eigen::Vector3d roll_pitch_yaw1 = X1_rot.eulerAngles(0, 1, 2);
Eigen::Vector3d roll_pitch_yaw2 = X2_rot.eulerAngles(0, 1, 2);
double x1 = pose_1(0,3);
double y1 = pose_1(1,3);
double z1 = pose_1(2,3);
double x2 = pose_2(0,3);
double y2 = pose_2(1,3);
double z2 = pose_2(2,3);
double yaw1 = roll_pitch_yaw1(2);
double pitch1 = roll_pitch_yaw1(1);
double roll1 = roll_pitch_yaw1(0);
double yaw2 = roll_pitch_yaw2(2);
double pitch2 = roll_pitch_yaw2(1);
double roll2 = roll_pitch_yaw2(0);
Jacobian_matrix.conservativeResize(number_of_landmark+1,6);
Jacobian_matrix(number_of_landmark, 0) = abs(lm_curr_fr->residual_error_from_optimization_)/(x2-x1);
Jacobian_matrix(number_of_landmark, 1) = abs(lm_curr_fr->residual_error_from_optimization_)/(y2-y1);
Jacobian_matrix(number_of_landmark, 2) = abs(lm_curr_fr->residual_error_from_optimization_)/(z2-z1);
Jacobian_matrix(number_of_landmark, 3) = abs(lm_curr_fr->residual_error_from_optimization_)/(yaw2-yaw1);
Jacobian_matrix(number_of_landmark, 4) = abs(lm_curr_fr->residual_error_from_optimization_)/(pitch2-pitch1);
Jacobian_matrix(number_of_landmark, 5) = abs(lm_curr_fr->residual_error_from_optimization_)/(roll2-roll1);
number_of_landmark++;
}
}
}
const auto end = std::chrono::system_clock::now();
elapsed_ms_ = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
// std::cout << "time for Jacobian computing = " << elapsed_ms_ << std::endl;
return Jacobian_matrix;
}
Here's output:
Hessian matrix: 4.26369e+15 -3.8184e+13 -5.26596e+14 -6.92714e+14 -2.29145e+14 -2.96259e+14
-3.8184e+13 3.41962e+11 4.71599e+12 6.20369e+12 2.05214e+12 2.65318e+12
-5.26596e+14 4.71599e+12 6.50382e+13 8.5555e+13 2.83011e+13 3.659e+13
-6.92714e+14 6.20369e+12 8.5555e+13 1.12544e+14 3.72288e+13 4.81326e+13
-2.29145e+14 2.05214e+12 2.83011e+13 3.72288e+13 1.23151e+13 1.59219e+13
-2.96259e+14 2.65318e+12 3.659e+13 4.81326e+13 1.59219e+13 2.05852e+13
inverse Hessian matrix
0.84104 33.9674 -3.73255 1.02025 -0.993682 12.7437
122.317 23835.5 -1591.36 675.752 -4342.53 3295.63
-10.0169 -2080.49 91.1274 -57.0409 407.123 -219.511
5.80446 851.824 -39.0675 37.1296 -144.223 67.9237
4.67209 210.571 4.27676 -33.7183 176.976 -25.5461
-3.04185 -1039.82 77.451 -31.7602 22.0809 9.75697
identity:
0.684563 -9.97159 1.56548 -0.85569 2.44585 2.93436
-0.000541409 1.07273 0.0069068 -0.00905051 0.0821457 -0.0551281
-0.0207974 -0.494565 1.19223 -0.123652 1.03656 -1.45191
-0.0516072 9.20116 -0.429967 1.31109 -1.10355 -2.08863
0.0222311 3.14692 -0.354085 0.188195 0.516471 -0.29575
0.00806517 -4.08476 0.280319 0.15838 -1.06946 0.0306264
As you can see product Hessian * Hessian^(-1) is not even close to the identity matrix. I thought, that I got some kind of singilar matrix or anything like that, and that's why Eigen didn't manage. Then I decided to check inverse matrix in python. Here's code:
a = np.array([[4.26369e+15, -3.8184e+13, -5.26596e+14, -6.92714e+14, -2.29145e+14, -2.96259e+14],
[-3.8184e+13, 3.41962e+11, 4.71599e+12, 6.20369e+12, 2.05214e+12, 2.65318e+12],
[-5.26596e+14, 4.71599e+12, 6.50382e+13, 8.5555e+13, 2.83011e+13, 3.659e+13],
[-6.92714e+14, 6.20369e+12, 8.5555e+13, 1.12544e+14, 3.72288e+13, 4.81326e+13],
[-2.29145e+14, 2.05214e+12, 2.83011e+13, 3.72288e+13, 1.23151e+13, 1.59219e+13],
[-2.96259e+14, 2.65318e+12, 3.659e+13, 4.81326e+13, 1.59219e+13, 2.05852e+13]])
np.linalg.inv(a)
And the output is:
array([[-9.50157030e-11, 2.42050992e-08, -4.09485425e-10,
-1.51298368e-09, 1.44172809e-10, -3.33168349e-10],
[ 2.42050992e-08, -4.13924685e-06, -8.24132506e-08,
4.50069824e-07, 6.55282742e-08, -7.47002292e-08],
[-4.09485425e-10, -8.24132506e-08, -2.73532375e-09,
1.42546534e-09, 6.50633717e-09, 1.22536282e-09],
[-1.51298368e-09, 4.50069824e-07, 1.42546535e-09,
-3.58572413e-08, -6.40345760e-09, 6.47787736e-09],
[ 1.44172809e-10, 6.55282742e-08, 6.50633717e-09,
-6.40345760e-09, 2.88168850e-09, -5.19205954e-09],
[-3.33168349e-10, -7.47002292e-08, 1.22536282e-09,
6.47787736e-09, -5.19205954e-09, -8.47577970e-09]])
If I execute this code in python:
a @ np.linalg.inv(a)
Then the output is:
array([[ 1.00000000e+00, -1.49011612e-08, -2.32830644e-10,
-1.86264515e-09, 0.00000000e+00, -1.16415322e-10],
[-6.82121026e-13, 1.00000000e+00, 5.45696821e-12,
2.91038305e-11, 7.27595761e-12, 9.09494702e-13],
[ 0.00000000e+00, 7.45058060e-09, 1.00000000e+00,
5.82076609e-10, 5.82076609e-11, 4.36557457e-11],
[-2.91038305e-11, 0.00000000e+00, 5.82076609e-11,
1.00000000e+00, 0.00000000e+00, 2.91038305e-11],
[-3.63797881e-12, 9.31322575e-10, 1.45519152e-11,
2.32830644e-10, 1.00000000e+00, 2.91038305e-11],
[-1.81898940e-12, 0.00000000e+00, 1.45519152e-11,
1.16415322e-10, 0.00000000e+00, 1.00000000e+00]])
What's wrong with matrix Eigen function inverse()
?
I used VSCode. My tasks.json is:
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "build_OpenVSLAM",
"command": "cd /home/cds-s/workspace/openvslam/build && cmake -DBUILD_WITH_MARCH_NATIVE=ON \
-DCMAKE_BUILD_TYPE=Release \
-DUSE_PANGOLIN_VIEWER=ON \
-DUSE_SOCKET_PUBLISHER=OFF \
-DUSE_STACK_TRACE_LOGGER=ON \
-DBOW_FRAMEWORK=DBoW2 \
-DBUILD_TESTS=ON \
.. && make -j4",
"args": [],
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [
"$gcc"
],
"group": "build"
}
]
}
My launch.json file is:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Build and debug OpenVSLAM",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/run_tum_rgbd_slam",
"args": [
"-v", "/media/cds-s/data/Vocab/orb_vocab/orb_vocab.dbow2",
"-c", "/media/cds-s/data/Datasets/NKBVS_calib_17_03_2020_rgbd_1200_600.yaml",
"-d", "/media/cds-s/data/Datasets/Husky-NKBVS/00_map_half_2020-03-17-14-21-57/RGBD"
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "build_OpenVSLAM",
"miDebuggerPath": "/usr/bin/gdb",
"default": true
}
]
}
While looking for problem, I decided to define Hessian matrix plicitly with the following code:
Eigen::MatrixXd mat(6,6);
mat << 4.26369e+15, -3.8184e+13, -5.26596e+14, -6.92714e+14, -2.29145e+14, -2.96259e+14,
-3.8184e+13, 3.41962e+11, 4.71599e+12, 6.20369e+12, 2.05214e+12, 2.65318e+12,
-5.26596e+14, 4.71599e+12, 6.50382e+13, 8.5555e+13, 2.83011e+13, 3.659e+13,
-6.92714e+14, 6.20369e+12, 8.5555e+13, 1.12544e+14, 3.72288e+13, 4.81326e+13,
-2.29145e+14, 2.05214e+12, 2.83011e+13, 3.72288e+13, 1.23151e+13, 1.59219e+13,
-2.96259e+14, 2.65318e+12, 3.659e+13, 4.81326e+13, 1.59219e+13, 2.05852e+13;
Then the inverse matrix is correct after building in VScode and running. It seems that I put values into Jacobian or Hessian incorrectly ?