10 #include <Eigen/Geometry>
12 #include <SimoxUtility/math/periodic/periodic_clamp.h>
13 #include <VirtualRobot/math/Helpers.h>
33 const std::vector<float> vec(
v.data(),
v.data() +
v.rows() *
v.cols());
34 return std::distance(std::begin(vec), std::max_element(vec.begin(), vec.end()));
45 EnclosingEllipsoid::compute(
const Points& points)
47 const float tolerance = 0.01;
49 const int N =
static_cast<int>(points.size());
52 Eigen::MatrixXf P(N, d);
54 for (
int i = 0; i < N; i++)
56 P.row(i) = points.at(i);
59 Eigen::MatrixXf Q(d + 1, N);
60 Q.topRows(d) = P.transpose();
61 Q.bottomRows(1).setOnes();
63 Eigen::MatrixXf Qt = Q.transpose();
65 float err = 1.F + tolerance;
66 Eigen::VectorXf u = (1.F / N) * Eigen::VectorXf::Ones(N);
69 while (err > tolerance)
71 const Eigen::MatrixXf V = Q * (u.asDiagonal() * Qt);
72 const Eigen::VectorXf M = (Qt * (V.inverse() * Q)).diagonal();
74 const int j =
static_cast<int>(
argmin(M));
75 const float maximum = M(j);
77 const float stepSize = (maximum - d - 1.0) / ((d + 1.0) * (maximum - 1.0));
79 Eigen::VectorXf uNew = (1.0 - stepSize) * u;
82 err = (uNew - u).
norm();
86 const Eigen::VectorXf center = P.transpose() * u;
88 Eigen::MatrixXf K(d, d);
89 for (
int i = 0; i < d; i++)
91 for (
int j = 0; j < d; j++)
93 K(i, j) = center(i) * center(j);
97 const Eigen::MatrixXf H = (P.transpose() * (u.asDiagonal() * P)) - K;
98 const Eigen::MatrixXf
A = H.inverse() / d;
100 const Eigen::JacobiSVD svd(
A, Eigen::ComputeThinV);
103 const Eigen::VectorXf v0 = svd.matrixV().col(0);
104 const float angle = math::Helpers::Angle(v0);
107 const Eigen::Vector2f
radii = svd.singularValues().cwiseSqrt().cwiseInverse();
111 this->radii =
radii.reverse();
114 const float angle1 = simox::math::periodic_clamp(
angle + M_PI_2, -
M_PI,
M_PI);
116 this->
pose.setIdentity();
117 this->
pose.translation().head<2>() = center;
118 this->
pose.linear() =
119 Eigen::AngleAxisf(angle1, Eigen::Vector3f::UnitZ()).toRotationMatrix();