Find_RT.h
Go to the documentation of this file.
1 #include <cstdlib>
2 #include <cstdio>
3 #include <math.h>
4 #include <fstream>
5 #include <iostream>
6 #include <string>
7 #include <sstream>
8 #include <utility>
9 
10 #include <Eigen/Dense>
11 #include <Eigen/SVD>
12 #include <Eigen/Geometry>
13 #include <unsupported/Eigen/MatrixFunctions>
14 
15 using namespace Eigen;
16 
17 std::string pkg_loc = ros::package::getPath("lidar_camera_calibration");
18 
19 Eigen::Vector3d translation_sum;
20 Eigen::Quaterniond rotation_sum;
21 
22 Eigen::Matrix3d rotation_avg_by_mult;
23 float rmse_avg;
24 
26 
27 Eigen::Quaterniond addQ(Eigen::Quaterniond a, Eigen::Quaterniond b) {
28  Eigen::Quaterniond retval;
29  if (a.x() * b.x() + a.y() * b.y() + a.z() * b.z() + a.w() * b.w() < 0.0) {
30  b.x() = -b.x();
31  b.y() = -b.y();
32  b.z() = -b.z();
33  b.w() = -b.w();
34  }
35  retval.x() = a.x() + b.x();
36  retval.y() = a.y() + b.y();
37  retval.z() = a.z() + b.z();
38  retval.w() = a.w() + b.w();
39  return retval;
40 }
41 
42 std::pair <MatrixXd, MatrixXd> readArray() {
43  std::ifstream infile(pkg_loc + "/conf/points.txt");
44  int num_points = 0;
45 
46  infile >> num_points;
47 
48  ROS_ASSERT(num_points > 0);
49 
50  MatrixXd lidar(3, num_points), camera(3, num_points);
51 
52  std::cout << "Num points is:" << num_points << std::endl;
53 
54  for (int i = 0; i < num_points; i++) {
55  infile >> lidar(0, i) >> lidar(1, i) >> lidar(2, i);
56  }
57  for (int i = 0; i < num_points; i++) {
58  infile >> camera(0, i) >> camera(1, i) >> camera(2, i);
59  }
60  infile.close();
61 
62  // camera values are stored in variable 'lidar' and vice-versa
63  // need to change this
64  return std::pair<MatrixXd, MatrixXd>(lidar, camera);
65  //return std::pair<MatrixXd, MatrixXd>(camera, lidar);
66 }
67 
68 // calculates rotation and translation that transforms points in the lidar frame to the camera frame
69 Matrix4d calc_RT(MatrixXd lidar, MatrixXd camera, int MAX_ITERS, Eigen::Matrix3d lidarToCamera) {
70  if (iteration_counter == 0) {
71  std::ofstream clean_file(pkg_loc + "/log/avg_values.txt", std::ios_base::trunc);
72  clean_file.close();
73 
74  translation_sum << 0.0, 0.0, 0.0;
75  rotation_sum = Quaterniond(0.0, 0.0, 0.0, 0.0);
76  rotation_avg_by_mult << 1.0, 0.0, 0.0,
77  0.0, 1.0, 0.0,
78  0.0, 0.0, 1.0;
79  rmse_avg = 0.0;
80  }
81  int num_points = lidar.cols();
82  std::cout << "Number of points: " << num_points << std::endl;
83  Vector3d mu_lidar, mu_camera;
84 
85  mu_lidar << 0.0, 0.0, 0.0;
86  mu_camera << 0.0, 0.0, 0.0;
87 
88  for (int i = 0; i < num_points; i++) {
89  mu_lidar(0) += lidar(0, i);
90  mu_lidar(1) += lidar(1, i);
91  mu_lidar(2) += lidar(2, i);
92  }
93  for (int i = 0; i < num_points; i++) {
94  mu_camera(0) += camera(0, i);
95  mu_camera(1) += camera(1, i);
96  mu_camera(2) += camera(2, i);
97  }
98 
99  mu_lidar = mu_lidar / num_points;
100  mu_camera = mu_camera / num_points;
101 
102  if (iteration_counter == 0) {
103  std::cout << "mu_lidar: \n" << mu_lidar << std::endl;
104  std::cout << "mu_camera: \n" << mu_camera << std::endl;
105  }
106 
107  MatrixXd lidar_centered = lidar.colwise() - mu_lidar;
108  MatrixXd camera_centered = camera.colwise() - mu_camera;
109 
110  if (iteration_counter == 0) {
111  std::cout << "lidar_centered: \n" << lidar_centered << std::endl;
112  std::cout << "camera_centered: \n" << camera_centered << std::endl;
113  }
114 
115  Matrix3d cov = camera_centered * lidar_centered.transpose();
116 
117  std::cout << cov << std::endl;
118 
119  JacobiSVD <MatrixXd> svd(cov, ComputeFullU | ComputeFullV);
120 
121  Matrix3d rotation;
122  rotation = svd.matrixU() * svd.matrixV().transpose();
123  if (rotation.determinant() < 0) {
124  Vector3d diag_correct;
125  diag_correct << 1.0, 1.0, -1.0;
126 
127  rotation = svd.matrixU() * diag_correct.asDiagonal() * svd.matrixV().transpose();
128  }
129 
130  Vector3d translation = mu_camera - rotation * mu_lidar;
131 
132  // averaging translation and rotation
133  translation_sum += translation;
134  Quaterniond temp_q(rotation);
135  rotation_sum = addQ(rotation_sum, temp_q);
136 
137  // averaging rotations by multiplication
139  rotation.pow(1.0 / (iteration_counter + 1));
140 
141  Vector3d ea = rotation.eulerAngles(2, 1, 0);
142 
143  std::cout << "Rotation matrix: \n" << rotation << std::endl;
144  std::cout << "Rotation in Euler angles: \n" << ea * 57.3 << std::endl;
145  std::cout << "Translation: \n" << translation << std::endl;
146 
147  MatrixXd eltwise_error = (camera - ((rotation * lidar).colwise() + translation)).array().square().colwise().sum();
148  double error = sqrt(eltwise_error.sum() / num_points);
149  std::cout << "RMSE: " << error << std::endl;
150 
151  rmse_avg = rmse_avg + error;
152 
153  Matrix4d T;
154  T.setIdentity(4, 4);
155  T.topLeftCorner(3, 3) = rotation;
156  T.col(3).head(3) = translation;
157 
158  std::cout << "Rigid-body transformation: \n" << T << std::endl;
159 
161 
162  if (iteration_counter % 1 == 0) {
163  std::ofstream log_avg_values(pkg_loc + "/log/avg_values.txt", std::ios_base::app);
164 
165  std::cout << "--------------------------------------------------------------------\n";
166  std::cout << "After " << iteration_counter << " iterations\n";
167  std::cout << "--------------------------------------------------------------------\n";
168 
169  std::cout << "Average translation is:" << "\n" << translation_sum / iteration_counter << "\n";
170  log_avg_values << iteration_counter << "\n";
171  log_avg_values << translation_sum / iteration_counter << "\n";
172 
173 
178  double mag = sqrt(rotation_sum.x() * rotation_sum.x() +
179  rotation_sum.y() * rotation_sum.y() +
180  rotation_sum.z() * rotation_sum.z() +
181  rotation_sum.w() * rotation_sum.w());
182  rotation_sum.x() = rotation_sum.x() / mag;
183  rotation_sum.y() = rotation_sum.y() / mag;
184  rotation_sum.z() = rotation_sum.z() / mag;
185  rotation_sum.w() = rotation_sum.w() / mag;
186 
187  Eigen::Matrix3d rotation_avg = rotation_sum.toRotationMatrix();
188  std::cout << "Average rotation is:" << "\n" << rotation_avg << "\n";
189  Eigen::Matrix3d final_rotation = rotation_avg * lidarToCamera;
190  Eigen::Vector3d final_angles = final_rotation.eulerAngles(2, 1, 0);
191 
192  log_avg_values << std::fixed << std::setprecision(8)
193  << rotation_avg(0, 0) << " " << rotation_avg(0, 1) << " " << rotation_avg(0, 2) << "\n"
194  << rotation_avg(1, 0) << " " << rotation_avg(1, 1) << " " << rotation_avg(1, 2) << "\n"
195  << rotation_avg(2, 0) << " " << rotation_avg(2, 1) << " " << rotation_avg(2, 2) << "\n";
196 
197  Matrix4d T;
198  T.setIdentity(4, 4);
199  T.topLeftCorner(3, 3) = rotation_avg;
200  T.col(3).head(3) = translation_sum / iteration_counter;
201  std::cout << "Average transformation is: \n" << T << "\n";
202  std::cout << "Final rotation is:" << "\n" << final_rotation << "\n";
203  std::cout << "Final ypr is:" << "\n" << final_angles << "\n";
204 
205  std::cout << "Average RMSE is: " << rmse_avg * 1.0 / iteration_counter << "\n";
206 
207  MatrixXd eltwise_error_temp = (camera - ((rotation_avg * lidar).colwise() + (translation_sum /
208  iteration_counter))).array().square().colwise().sum();
209  double error_temp = sqrt(eltwise_error_temp.sum() / num_points);
210 
211  std::cout << "RMSE on average transformation is: " << error_temp << std::endl;
212  log_avg_values << std::fixed << std::setprecision(8) << error_temp << "\n";
213 
214  }
215 
216  return T;
217 }
218 
219 
220 void readArucoPose(std::vector<float> marker_info, int num_of_marker_in_config) {
221  std::vector <Matrix4d> marker_pose;
222 
223  ROS_ASSERT(marker_info.size() / 7 == num_of_marker_in_config);
224 
225  int j = 0;
226  for (int i = 0; i < marker_info.size() / 7; i++) {
227 
228  Vector3d trans, rot;
229  int marker_id = marker_info[j++];
230  trans(0) = marker_info[j++];
231  trans(1) = marker_info[j++];
232  trans(2) = marker_info[j++];
233  rot(0) = marker_info[j++];
234  rot(1) = marker_info[j++];
235  rot(2) = marker_info[j++];
236 
237  Transform<double, 3, Affine> aa;
238  aa = AngleAxis<double>(rot.norm(), rot / rot.norm());
239 
240  Matrix4d g;
241  g.setIdentity(4, 4);
242  g = aa * g;
243 
244  Matrix4d T;
245  T.setIdentity(4, 4);
246  T.topLeftCorner(3, 3) = g.topLeftCorner(3, 3);//.transpose();
247  T.col(3).head(3) = trans;
248 
249  marker_pose.push_back(T);
250 
251  }
252 
253 
254  std::ifstream infile(pkg_loc + "/conf/marker_coordinates.txt");
255  std::ofstream outfile(pkg_loc + "/conf/points.txt", std::ios_base::app);
256 
257  int num_of_markers;
258  infile >> num_of_markers;
259 
260  for (int i = 0; i < num_of_markers; i++) {
261  float temp;
262  std::vector<float> board;
263  for (int j = 0; j < 5; j++) {
264  infile >> temp;
265  board.push_back(temp / 100.0);
266  }
267  float la, ba;
268  la = board[4] / 2 + board[2];
269  ba = board[4] / 2 + board[3];
270 
271  Matrix4d points_board;
272  points_board << ba, 0, board[0] - la, 1,
273  ba - board[1], 0, board[0] - la, 1,
274  ba - board[1], 0, -la, 1,
275  ba, 0, -la, 1;
276 
277  points_board = marker_pose[i] * (points_board.transpose());
278 
279  for (int k = 0; k < 4; k++) {
280  outfile << points_board(0, k) << " " << points_board(1, k) << " " << points_board(2, k) << "\n";
281  }
282 
283  }
284  outfile.close();
285  infile.close();
286 }
287 
288 
289 void find_transformation(std::vector<float> marker_info, int num_of_marker_in_config, int MAX_ITERS,
290  Eigen::Matrix3d lidarToCamera) {
291  readArucoPose(marker_info, num_of_marker_in_config);
292  std::pair <MatrixXd, MatrixXd> point_clouds = readArray();
293  Matrix4d T = calc_RT(point_clouds.first, point_clouds.second, MAX_ITERS, lidarToCamera);
294 }
void readArucoPose(std::vector< float > marker_info, int num_of_marker_in_config)
Definition: Find_RT.h:220
Eigen::Matrix3d rotation_avg_by_mult
Definition: Find_RT.h:22
Eigen::Quaterniond rotation_sum
Definition: Find_RT.h:20
Matrix4d calc_RT(MatrixXd lidar, MatrixXd camera, int MAX_ITERS, Eigen::Matrix3d lidarToCamera)
Definition: Find_RT.h:69
ROSLIB_DECL std::string getPath(const std::string &package_name)
float rmse_avg
Definition: Find_RT.h:23
Eigen::Matrix3d lidarToCamera
Eigen::Vector3d translation_sum
Definition: Find_RT.h:19
std::pair< MatrixXd, MatrixXd > readArray()
Definition: Find_RT.h:42
#define ROS_ASSERT(cond)
void find_transformation(std::vector< float > marker_info, int num_of_marker_in_config, int MAX_ITERS, Eigen::Matrix3d lidarToCamera)
Definition: Find_RT.h:289
int iteration_counter
Definition: Find_RT.h:25
Eigen::Quaterniond addQ(Eigen::Quaterniond a, Eigen::Quaterniond b)
Definition: Find_RT.h:27
std::string pkg_loc
Definition: Find_RT.h:17


lidar_camera_calibration
Author(s):
autogenerated on Sat Feb 6 2021 03:39:37