7 #include <Eigen/Geometry>
8 #include <Eigen/src/Geometry/AngleAxis.h>
10 #include <SimoxUtility/math/periodic/periodic_clamp.h>
11 #include <VirtualRobot/math/Helpers.h>
32 const std::vector<float> vec(
v.data(),
v.data() +
v.rows() *
v.cols());
33 return std::distance(std::begin(vec), std::max_element(vec.begin(), vec.end()));
44 EnclosingEllipsoid::compute(
const Points& points)
46 const float tolerance = 0.01;
48 const int N =
static_cast<int>(points.size());
51 Eigen::MatrixXf P(N, d);
53 for (
int i = 0; i < N; i++)
55 P.row(i) = points.at(i);
58 Eigen::MatrixXf Q(d + 1, N);
59 Q.topRows(d) = P.transpose();
60 Q.bottomRows(1).setOnes();
62 Eigen::MatrixXf Qt = Q.transpose();
64 float err = 1.F + tolerance;
65 Eigen::VectorXf u = (1.F / N) * Eigen::VectorXf::Ones(N);
68 while (err > tolerance)
70 const Eigen::MatrixXf V = Q * (u.asDiagonal() * Qt);
71 const Eigen::VectorXf M = (Qt * (V.inverse() * Q)).diagonal();
73 const int j =
static_cast<int>(
argmin(M));
74 const float maximum = M(j);
76 const float stepSize = (maximum - d - 1.0) / ((d + 1.0) * (maximum - 1.0));
78 Eigen::VectorXf uNew = (1.0 - stepSize) * u;
81 err = (uNew - u).
norm();
85 const Eigen::VectorXf center = P.transpose() * u;
87 Eigen::MatrixXf K(d, d);
88 for (
int i = 0; i < d; i++)
90 for (
int j = 0; j < d; j++)
92 K(i, j) = center(i) * center(j);
96 const Eigen::MatrixXf H = (P.transpose() * (u.asDiagonal() * P)) - K;
97 const Eigen::MatrixXf
A = H.inverse() / d;
99 const Eigen::JacobiSVD svd(
A, Eigen::ComputeThinV);
102 const Eigen::VectorXf v0 = svd.matrixV().col(0);
103 const float angle = math::Helpers::Angle(v0);
106 const Eigen::Vector2f
radii = svd.singularValues().cwiseSqrt().cwiseInverse();
110 this->radii =
radii.reverse();
113 const float angle1 = simox::math::periodic_clamp(
angle + M_PI_2, -
M_PI,
M_PI);
115 this->
pose.setIdentity();
116 this->
pose.translation().head<2>() = center;
117 this->
pose.linear() =
118 Eigen::AngleAxisf(angle1, Eigen::Vector3f::UnitZ()).toRotationMatrix();