resectionsolver.cpp
Go to the documentation of this file.
1 
19 #include <math.h>
21 #include <vector>
22 #include <iostream>
23 #ifndef Q_MOC_RUN
24 #include <ros/ros.h>
25 #endif
26 
28 {
29  this->calibrationObject = calibrationObject;
30  this->feasibilityChecker = feasibilityChecker;
31 }
32 
33 unsigned int ResectionSolver::solve(const Eigen::Vector2d& base_A, const Eigen::Vector2d& base_B, const Eigen::Vector2d& base_C)
34 {
35  solutions_a.clear();
36  solutions_b.clear();
37  solutions_c.clear();
38  solve_for_lengths((base_A-base_B).norm(), (base_B-base_C).norm(), (base_C-base_A).norm());
39  solutions.clear();
40 
41  for (int i = (int)solutions_a.size()-1; i >= 0; i--)
42  {
43  if (feasibilityChecker->checkFeasibility_sideLengths(solutions_a[i],solutions_c[i],solutions_b[i]))
44  {
45  Eigen::Vector3d top;
46  top = solve_for_top(base_A, base_B, base_C, solutions_b[i], solutions_c[i],solutions_a[i]);
47  solutions.push_back(top);
48  }
49  else
50  {
51  ROS_INFO_STREAM(solutions_a[i] << ", " << solutions_b[i] << ", " << solutions_c[i] << " erased");
52  solutions_a.erase(solutions_a.begin()+i);
53  solutions_b.erase(solutions_b.begin()+i);
54  solutions_c.erase(solutions_c.begin()+i);
55  }
56 
57  }
58  return solutions.size() ;
59 }
60 
61 //Formel aus "New Non-iterative Solution of the Perspective 3-Point Problem" / Huaien ZENG
62 Eigen::Vector3d ResectionSolver::solve_for_top(const Eigen::Vector2d& base_A, const Eigen::Vector2d& base_B, const Eigen::Vector2d& base_C, double length_AS, double length_BS, double length_CS)
63 {
64  Eigen::Vector2d base_B_new, base_C_new;
65  base_B_new = base_B - base_A;
66  base_C_new = base_C - base_A;
67  double alpha, beta;
68  alpha = (pow(base_B_new[0],2.0) + pow(base_B_new[1],2.0) + pow(length_AS,2.0) - pow(length_BS,2.0)) / 2.0;
69  // Hinweis: für die Formel von beta steht an dieser Stelle x*x - y*y, sollte aber x*x - z*z heißen
70  beta = (pow(base_C_new[0],2.0) + pow(base_C_new[1],2.0) + pow(length_AS,2.0) - pow(length_CS,2.0)) / 2.0;
71  double X, Y, Z;
72  Y = (alpha*base_C_new[0]-beta*base_B_new[0])/(base_B_new[1]*base_C_new[0]-base_C_new[1]*base_B_new[0]);
73  if (base_B_new[0] != 0.0)
74  {
75  X = (alpha - Y*base_B_new[1])/base_B_new[0];
76  }
77  else
78  {
79  X = (beta - Y*base_C_new[1])/base_C_new[0];
80  }
81  // da die Höhe Z als positiver Wert definiert ist kann hier von einer eindeutigen Lösung für Z ausgegangen werden
82  Z = sqrt(pow(length_CS, 2.0) - pow(X - base_C_new[0], 2.0) - pow(Y - base_C_new[1], 2.0));
83  return Eigen::Vector3d(X + base_A[0], Y + base_A[1], Z);
84 }
85 
86 
87 //Code from https://github.com/Itseez/opencv/blob/master/modules/calib3d/src/p3p.cpp
88 //http://iplimage.com/blog/p3p-perspective-point-overview/
89 int ResectionSolver::solve_for_lengths(double side_A, double side_B, double side_C)
90 {
91  ROS_DEBUG_STREAM("Sides: " << side_A << ", " << side_B << ", " << side_C);
92 
93  double p = cos(calibrationObject->top_angle_ab) * 2;
94  double q = cos(calibrationObject->top_angle_bc) * 2;
95  double r = cos(calibrationObject->top_angle_ca) * 2;
96 
97  double inv_d22 = 1. / (side_C * side_C);
98  double a = inv_d22 * (side_A * side_A);
99  double b = inv_d22 * (side_B * side_B);
100 
101  double a2 = a * a, b2 = b * b, p2 = p * p, q2 = q * q, r2 = r * r;
102  double pr = p * r, pqr = q * pr;
103 
104  // Check reality condition (the four points should not be coplanar)
105  if (p2 + q2 + r2 - pqr - 1 == 0)
106  return 0;
107 
108  double ab = a * b, a_2 = 2*a;
109 
110  double A = -2 * b + b2 + a2 + 1 + ab*(2 - r2) - a_2;
111 
112  // Check reality condition
113  if (A == 0) return 0;
114 
115  double a_4 = 4*a;
116 
117  double B = q*(-2*(ab + a2 + 1 - b) + r2*ab + a_4) + pr*(b - b2 + ab);
118  double C = q2 + b2*(r2 + p2 - 2) - b*(p2 + pqr) - ab*(r2 + pqr) + (a2 - a_2)*(2 + q2) + 2;
119  double D = pr*(ab-b2+b) + q*((p2-2)*b + 2 * (ab - a2) + a_4 - 2);
120  double E = 1 + 2*(b - a - ab) + b2 - b*p2 + a2;
121 
122  double temp = (p2*(a-1+b) + r2*(a-1-b) + pqr - a*pqr);
123  double b0 = b * temp * temp;
124  // Check reality condition
125  if (b0 == 0)
126  return 0;
127 
128  double real_roots[4];
129  int n = SolveP4(real_roots, B/A, C/A,D/A, E/A);
130 
131  if (n == 0)
132  return 0;
133 
134  int nb_solutions = 0;
135  double r3 = r2*r, pr2 = p*r2, r3q = r3 * q;
136  double inv_b0 = 1. / b0;
137 
138  // For each solution of x
139  for(int i = 0; i < n; i++) {
140  double x = real_roots[i];
141 
142  // Check reality condition
143  if (x <= 0)
144  continue;
145 
146  double x2 = x*x;
147 
148  double b1 =
149  ((1-a-b)*x2 + (q*a-q)*x + 1 - a + b) *
150  (((r3*(a2 + ab*(2 - r2) - a_2 + b2 - 2*b + 1)) * x +
151 
152  (r3q*(2*(b-a2) + a_4 + ab*(r2 - 2) - 2) + pr2*(1 + a2 + 2*(ab-a-b) + r2*(b - b2) + b2))) * x2 +
153 
154  (r3*(q2*(1-2*a+a2) + r2*(b2-ab) - a_4 + 2*(a2 - b2) + 2) + r*p2*(b2 + 2*(ab - b - a) + 1 + a2) + pr2*q*(a_4 + 2*(b - ab - a2) - 2 - r2*b)) * x +
155 
156  2*r3q*(a_2 - b - a2 + ab - 1) + pr2*(q2 - a_4 + 2*(a2 - b2) + r2*b + q2*(a2 - a_2) + 2) +
157  p2*(p*(2*(ab - a - b) + a2 + b2 + 1) + 2*q*r*(b + a_2 - a2 - ab - 1)));
158 
159  // Check reality condition
160  if (b1 <= 0)
161  continue;
162 
163  double y = inv_b0 * b1;
164  double v = x2 + y*y - x*y*r;
165 
166  if (v <= 0)
167  continue;
168 
169  double Z = side_C / sqrt(v);
170  double X = x * Z;
171  double Y = y * Z;
172 
173  solutions_a.push_back(X);
174  solutions_b.push_back(Y);
175  solutions_c.push_back(Z);
176 
177  nb_solutions++;
178  }
179 
180  return nb_solutions;
181 }
182 
183 
184 Eigen::Matrix4d ResectionSolver::calculateTransformationMatrix(const Eigen::Vector2d& base_A, const Eigen::Vector2d& base_B, const Eigen::Vector2d& base_C, const Eigen::Vector3d& solution)
185 {
186  Eigen::Matrix4d *transformation = new Eigen::Matrix4d();
187  //Transformationsmatrix berechnen
188  Eigen::Vector3d x_axis, y_axis, z_axis;
189  //Z-Achse entspricht dem Vektor vom Schnitt-Punkt 2 bis zu Spitze des Tetraeders
190  z_axis = Eigen::Vector3d(solution[0] - base_B[0], solution[1] - base_B[1], solution[2]);
191  z_axis.normalize();
192 
193  Eigen::Vector3d basePoint = solution - z_axis * calibrationObject->side_b;
194  //X- und Y-Achse entsprechen den beiden vorderen Seiten an der Basis des Tetraeders
195  //Die Basispunkte können durch die Vektoren zur Spitze hin und den Kantenlängen des Tetraeders bestimmt werden
196  x_axis = Eigen::Vector3d(base_A[0] - solution[0], base_A[1] - solution[1], -solution[2]);
197  y_axis = Eigen::Vector3d(base_C[0] - solution[0], base_C[1] - solution[1], -solution[2]);
198  x_axis.normalize();
199  y_axis.normalize();
200  x_axis = solution + x_axis * calibrationObject->side_a - basePoint;
201  y_axis = solution + y_axis * calibrationObject->side_c - basePoint;
202  //Orthonormalisierunsgverfahren um sicherzustellen, dass die Vektoren tatsächlich eine orthonormale Basis bilden
203  x_axis = x_axis - x_axis.dot(z_axis)*z_axis;
204  x_axis.normalize();
205  y_axis = y_axis - y_axis.dot(z_axis)*z_axis - y_axis.dot(x_axis)*x_axis;
206  y_axis.normalize();
207 
208  (*transformation)(0,0) = x_axis[0];
209  (*transformation)(1,0) = x_axis[1];
210  (*transformation)(2,0) = x_axis[2];
211  (*transformation)(3,0) = 0.0;
212  (*transformation)(0,1) = y_axis[0];
213  (*transformation)(1,1) = y_axis[1];
214  (*transformation)(2,1) = y_axis[2];
215  (*transformation)(3,1) = 0.0;
216  (*transformation)(0,2) = z_axis[0];
217  (*transformation)(1,2) = z_axis[1];
218  (*transformation)(2,2) = z_axis[2];
219  (*transformation)(3,2) = 0.0;
220  (*transformation)(0,3) = solution[0];
221  (*transformation)(1,3) = solution[1];
222  (*transformation)(2,3) = solution[2];
223  (*transformation)(3,3) = 1.0;
224 
225  return *transformation;
226 }
227 
228 
229 
boost::shared_ptr< Calibration_Object > calibrationObject
int SolveP4(double *x, double a, double b, double c, double d)
Definition: poly34.cpp:201
int solve_for_lengths(double side_A, double side_B, double side_C)
std::vector< Eigen::Vector3d, Eigen::aligned_allocator< Eigen::Vector3d > > solutions
Eigen::Matrix4d calculateTransformationMatrix(const Eigen::Vector2d &base_A, const Eigen::Vector2d &base_B, const Eigen::Vector2d &base_C, const Eigen::Vector3d &solution)
boost::shared_ptr< FeasibilityChecker > feasibilityChecker
unsigned int solve(const Eigen::Vector2d &base_A, const Eigen::Vector2d &base_B, const Eigen::Vector2d &base_C)
ResectionSolver(boost::shared_ptr< Calibration_Object > calibrationObject, boost::shared_ptr< FeasibilityChecker > feasibilityChecker)
std::vector< double > solutions_a
std::vector< double > solutions_b
#define ROS_DEBUG_STREAM(args)
#define ROS_INFO_STREAM(args)
Eigen::Vector3d solve_for_top(const Eigen::Vector2d &base_A, const Eigen::Vector2d &base_B, const Eigen::Vector2d &base_C, double length_AS, double length_BS, double length_CS)
std::vector< double > solutions_c


asr_mild_calibration_tool
Author(s): Aumann Florian, Heller Florian, Meißner Pascal
autogenerated on Mon Dec 2 2019 03:11:43