94 const std::string& name,
const std::list<CartesianPose>& points,
const std::string& reference_frame,
98 Eigen::SparseMatrix<double> constraint_matrix(6, 6);
99 constraint_matrix.insert(1, 1) = -1;
100 constraint_matrix.insert(0, 2) = 2;
101 constraint_matrix.insert(2, 0) = 2;
104 size_t nb_points = points.size();
105 Eigen::VectorXd x_value(nb_points);
106 Eigen::VectorXd y_value(nb_points);
110 std::vector<double> coefficients(6);
111 Eigen::GeneralizedEigenSolver<Eigen::Matrix<double, 6, 6>> solver;
113 std::default_random_engine generator;
114 std::normal_distribution<double>
dist(0., noise_level);
117 for (
const auto& p: points) {
118 x_value[i] = p.get_position()(0) +
dist(generator);
119 y_value[i] = p.get_position()(1) +
dist(generator);
123 double xm = x_value.mean();
124 double ym = y_value.mean();
125 double sx = 0.5 * (x_value.maxCoeff() - x_value.minCoeff());
126 double sy = 0.5 * (y_value.maxCoeff() - y_value.minCoeff());
127 Eigen::VectorXd x_value_centered = (x_value.array() - xm) / sx;
128 Eigen::VectorXd y_value_centered = (y_value.array() - ym) / sy;
131 Eigen::MatrixXd design_matrix(nb_points, 6);
132 design_matrix.col(0) = x_value_centered.array() * x_value_centered.array();
133 design_matrix.col(1) = x_value_centered.array() * y_value_centered.array();
134 design_matrix.col(2) = y_value_centered.array() * y_value_centered.array();
135 design_matrix.col(3) = x_value_centered;
136 design_matrix.col(4) = y_value_centered;
137 design_matrix.col(5) = Eigen::VectorXd::Ones(nb_points);
140 Eigen::Matrix<double, 6, 6> scatter_matrix = design_matrix.transpose() * design_matrix;
143 solver.compute(scatter_matrix, constraint_matrix);
146 unsigned int solution_index;
147 double eigenvalue = solver.betas().maxCoeff(&solution_index);
150 if (eigenvalue < 0) {
155 Eigen::VectorXd solution = solver.eigenvectors().col(solution_index).real();
160 double sx2 = sx * sx;
161 double sy2 = sy * sy;
163 coefficients[0] = solution(0) * sy2;
164 coefficients[1] = solution(1) * sx * sy;
165 coefficients[2] = solution(2) * sx2;
166 coefficients[3] = -2 * solution(0) * sy2 * kx - solution(1) * sx * sy * ky + solution(3) * sx * sy2;
167 coefficients[4] = -solution(1) * sx * sy * kx - 2 * solution(2) * sx2 * ky + solution(4) * sx2 * sy;
168 coefficients[5] = solution(0) * sy2 * kx * kx + solution(1) * sx * sy * kx * ky + solution(2) * sx2 * ky * ky
169 - solution(3) * sx * sy2 * kx - solution(4) * sx2 * sy * ky + solution(5) * sx2 * sy2;
171 delta = coefficients[1] * coefficients[1] - 4 * coefficients[0] * coefficients[2];
177 const std::string& name,
const std::vector<double>& coefficients,
const std::string& reference_frame
180 double b2 = coefficients[1] * coefficients[1];
181 double delta = b2 - 4 * coefficients[0] * coefficients[2];
184 double tmp1 = coefficients[0] * coefficients[4] * coefficients[4]
185 + coefficients[2] * coefficients[3] * coefficients[3]
186 - coefficients[1] * coefficients[3] * coefficients[4]
187 + delta * coefficients[5];
188 double tmp2 = coefficients[2] - coefficients[0];
189 double tmp3 = sqrt(tmp2 * tmp2 + b2);
193 std::vector<double> axis_lengths(2);
196 double r1 = -sqrt(2 * tmp1 * (coefficients[0] + coefficients[2] + tmp3)) / delta;
197 double r2 = -sqrt(2 * tmp1 * (coefficients[0] + coefficients[2] - tmp3)) / delta;
198 axis_lengths[0] = (r1 >= r2) ? r1 : r2;
199 axis_lengths[1] = (r1 >= r2) ? r2 : r1;
203 double cx = (2 * coefficients[2] * coefficients[3] - coefficients[1] * coefficients[4]) / delta;
204 double cy = (2 * coefficients[0] * coefficients[4] - coefficients[1] * coefficients[3]) / delta;
209 if (abs(coefficients[1]) > 1e-4) {
210 phi = atan2(tmp2 - tmp3, coefficients[1]);
211 }
else if (coefficients[0] < coefficients[2]) {
216 if (r1 < r2) { phi += M_PI_2; }
static const Ellipsoid fit(const std::string &name, const std::list< CartesianPose > &points, const std::string &reference_frame="world", double noise_level=0.01)
Fit an Ellipsoid on a set of points This method uses direct least square fitting from Fitzgibbon,...