00001
00018 #include "MathHelpers/Resectionsolver/resectionsolver.h"
00019 #include <math.h>
00020 #include "MathHelpers/Resectionsolver/poly34.h"
00021 #include <vector>
00022 #include <iostream>
00023 #ifndef Q_MOC_RUN
00024 #include <ros/ros.h>
00025 #endif
00026
00027 ResectionSolver::ResectionSolver(boost::shared_ptr<Calibration_Object> calibrationObject, boost::shared_ptr<FeasibilityChecker> feasibilityChecker)
00028 {
00029 this->calibrationObject = calibrationObject;
00030 this->feasibilityChecker = feasibilityChecker;
00031 }
00032
00033 unsigned int ResectionSolver::solve(const Eigen::Vector2d& base_A, const Eigen::Vector2d& base_B, const Eigen::Vector2d& base_C)
00034 {
00035 solutions_a.clear();
00036 solutions_b.clear();
00037 solutions_c.clear();
00038 solve_for_lengths((base_A-base_B).norm(), (base_B-base_C).norm(), (base_C-base_A).norm());
00039 solutions.clear();
00040
00041 for (int i = (int)solutions_a.size()-1; i >= 0; i--)
00042 {
00043 if (feasibilityChecker->checkFeasibility_sideLengths(solutions_a[i],solutions_c[i],solutions_b[i]))
00044 {
00045 Eigen::Vector3d top;
00046 top = solve_for_top(base_A, base_B, base_C, solutions_b[i], solutions_c[i],solutions_a[i]);
00047 solutions.push_back(top);
00048 }
00049 else
00050 {
00051 ROS_INFO_STREAM(solutions_a[i] << ", " << solutions_b[i] << ", " << solutions_c[i] << " erased");
00052 solutions_a.erase(solutions_a.begin()+i);
00053 solutions_b.erase(solutions_b.begin()+i);
00054 solutions_c.erase(solutions_c.begin()+i);
00055 }
00056
00057 }
00058 return solutions.size() ;
00059 }
00060
00061
00062 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)
00063 {
00064 Eigen::Vector2d base_B_new, base_C_new;
00065 base_B_new = base_B - base_A;
00066 base_C_new = base_C - base_A;
00067 double alpha, beta;
00068 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;
00069
00070 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;
00071 double X, Y, Z;
00072 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]);
00073 if (base_B_new[0] != 0.0)
00074 {
00075 X = (alpha - Y*base_B_new[1])/base_B_new[0];
00076 }
00077 else
00078 {
00079 X = (beta - Y*base_C_new[1])/base_C_new[0];
00080 }
00081
00082 Z = sqrt(pow(length_CS, 2.0) - pow(X - base_C_new[0], 2.0) - pow(Y - base_C_new[1], 2.0));
00083 return Eigen::Vector3d(X + base_A[0], Y + base_A[1], Z);
00084 }
00085
00086
00087
00088
00089 int ResectionSolver::solve_for_lengths(double side_A, double side_B, double side_C)
00090 {
00091 ROS_DEBUG_STREAM("Sides: " << side_A << ", " << side_B << ", " << side_C);
00092
00093 double p = cos(calibrationObject->top_angle_ab) * 2;
00094 double q = cos(calibrationObject->top_angle_bc) * 2;
00095 double r = cos(calibrationObject->top_angle_ca) * 2;
00096
00097 double inv_d22 = 1. / (side_C * side_C);
00098 double a = inv_d22 * (side_A * side_A);
00099 double b = inv_d22 * (side_B * side_B);
00100
00101 double a2 = a * a, b2 = b * b, p2 = p * p, q2 = q * q, r2 = r * r;
00102 double pr = p * r, pqr = q * pr;
00103
00104
00105 if (p2 + q2 + r2 - pqr - 1 == 0)
00106 return 0;
00107
00108 double ab = a * b, a_2 = 2*a;
00109
00110 double A = -2 * b + b2 + a2 + 1 + ab*(2 - r2) - a_2;
00111
00112
00113 if (A == 0) return 0;
00114
00115 double a_4 = 4*a;
00116
00117 double B = q*(-2*(ab + a2 + 1 - b) + r2*ab + a_4) + pr*(b - b2 + ab);
00118 double C = q2 + b2*(r2 + p2 - 2) - b*(p2 + pqr) - ab*(r2 + pqr) + (a2 - a_2)*(2 + q2) + 2;
00119 double D = pr*(ab-b2+b) + q*((p2-2)*b + 2 * (ab - a2) + a_4 - 2);
00120 double E = 1 + 2*(b - a - ab) + b2 - b*p2 + a2;
00121
00122 double temp = (p2*(a-1+b) + r2*(a-1-b) + pqr - a*pqr);
00123 double b0 = b * temp * temp;
00124
00125 if (b0 == 0)
00126 return 0;
00127
00128 double real_roots[4];
00129 int n = SolveP4(real_roots, B/A, C/A,D/A, E/A);
00130
00131 if (n == 0)
00132 return 0;
00133
00134 int nb_solutions = 0;
00135 double r3 = r2*r, pr2 = p*r2, r3q = r3 * q;
00136 double inv_b0 = 1. / b0;
00137
00138
00139 for(int i = 0; i < n; i++) {
00140 double x = real_roots[i];
00141
00142
00143 if (x <= 0)
00144 continue;
00145
00146 double x2 = x*x;
00147
00148 double b1 =
00149 ((1-a-b)*x2 + (q*a-q)*x + 1 - a + b) *
00150 (((r3*(a2 + ab*(2 - r2) - a_2 + b2 - 2*b + 1)) * x +
00151
00152 (r3q*(2*(b-a2) + a_4 + ab*(r2 - 2) - 2) + pr2*(1 + a2 + 2*(ab-a-b) + r2*(b - b2) + b2))) * x2 +
00153
00154 (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 +
00155
00156 2*r3q*(a_2 - b - a2 + ab - 1) + pr2*(q2 - a_4 + 2*(a2 - b2) + r2*b + q2*(a2 - a_2) + 2) +
00157 p2*(p*(2*(ab - a - b) + a2 + b2 + 1) + 2*q*r*(b + a_2 - a2 - ab - 1)));
00158
00159
00160 if (b1 <= 0)
00161 continue;
00162
00163 double y = inv_b0 * b1;
00164 double v = x2 + y*y - x*y*r;
00165
00166 if (v <= 0)
00167 continue;
00168
00169 double Z = side_C / sqrt(v);
00170 double X = x * Z;
00171 double Y = y * Z;
00172
00173 solutions_a.push_back(X);
00174 solutions_b.push_back(Y);
00175 solutions_c.push_back(Z);
00176
00177 nb_solutions++;
00178 }
00179
00180 return nb_solutions;
00181 }
00182
00183
00184 Eigen::Matrix4d ResectionSolver::calculateTransformationMatrix(const Eigen::Vector2d& base_A, const Eigen::Vector2d& base_B, const Eigen::Vector2d& base_C, const Eigen::Vector3d& solution)
00185 {
00186 Eigen::Matrix4d *transformation = new Eigen::Matrix4d();
00187
00188 Eigen::Vector3d x_axis, y_axis, z_axis;
00189
00190 z_axis = Eigen::Vector3d(solution[0] - base_B[0], solution[1] - base_B[1], solution[2]);
00191 z_axis.normalize();
00192
00193 Eigen::Vector3d basePoint = solution - z_axis * calibrationObject->side_b;
00194
00195
00196 x_axis = Eigen::Vector3d(base_A[0] - solution[0], base_A[1] - solution[1], -solution[2]);
00197 y_axis = Eigen::Vector3d(base_C[0] - solution[0], base_C[1] - solution[1], -solution[2]);
00198 x_axis.normalize();
00199 y_axis.normalize();
00200 x_axis = solution + x_axis * calibrationObject->side_a - basePoint;
00201 y_axis = solution + y_axis * calibrationObject->side_c - basePoint;
00202
00203 x_axis = x_axis - x_axis.dot(z_axis)*z_axis;
00204 x_axis.normalize();
00205 y_axis = y_axis - y_axis.dot(z_axis)*z_axis - y_axis.dot(x_axis)*x_axis;
00206 y_axis.normalize();
00207
00208 (*transformation)(0,0) = x_axis[0];
00209 (*transformation)(1,0) = x_axis[1];
00210 (*transformation)(2,0) = x_axis[2];
00211 (*transformation)(3,0) = 0.0;
00212 (*transformation)(0,1) = y_axis[0];
00213 (*transformation)(1,1) = y_axis[1];
00214 (*transformation)(2,1) = y_axis[2];
00215 (*transformation)(3,1) = 0.0;
00216 (*transformation)(0,2) = z_axis[0];
00217 (*transformation)(1,2) = z_axis[1];
00218 (*transformation)(2,2) = z_axis[2];
00219 (*transformation)(3,2) = 0.0;
00220 (*transformation)(0,3) = solution[0];
00221 (*transformation)(1,3) = solution[1];
00222 (*transformation)(2,3) = solution[2];
00223 (*transformation)(3,3) = 1.0;
00224
00225 return *transformation;
00226 }
00227
00228
00229