34 template <concepts::Range TSequenceContainer>
36 TSequenceContainer
const& foo_from_bar_transforms,
int max_num_iterations)
37 -> std::optional<typename TSequenceContainer::value_type> {
38 size_t const k_matrix_dim = std::distance(
39 std::begin(foo_from_bar_transforms), std::end(foo_from_bar_transforms));
42 using Group =
typename TSequenceContainer::value_type;
43 using Scalar =
typename Group::Scalar;
44 using Tangent = Eigen::Vector<Scalar, Group::kDof>;
48 Group foo_from_average = *std::begin(foo_from_bar_transforms);
49 Scalar w = Scalar(1. / k_matrix_dim);
50 for (
int i = 0; i < max_num_iterations; ++i) {
53 for (Group
const& foo_from_bar : foo_from_bar_transforms) {
54 average += w * (foo_from_average.inverse() * foo_from_bar).log();
56 Group foo_from_newaverage = foo_from_average * Group::exp(
average);
57 if (((foo_from_newaverage.inverse() * foo_from_average).log())
58 .squaredNorm() < kEpsilon<Scalar>) {
59 return foo_from_newaverage;
62 foo_from_average = foo_from_newaverage;
69 #ifdef DOXYGEN_SHOULD_SKIP_THIS
71 template <
class SequenceContainer,
class Scalar>
72 optional<typename SequenceContainer::value_type>
average(
73 SequenceContainer
const& foo_Ts_bar);
79 int kPointDim = TSequenceContainer::value_type::kDof,
80 class TScalar =
typename TSequenceContainer::value_type::Scalar>
81 auto average(TSequenceContainer
const& foo_from_bar_transforms)
84 typename TSequenceContainer::value_type,
86 std::optional<typename TSequenceContainer::value_type> > {
87 size_t const k_matrix_dim = std::distance(
88 std::begin(foo_from_bar_transforms), std::end(foo_from_bar_transforms));
91 Eigen::Vector<TScalar, kPointDim>
average;
94 foo_from_bar_transforms) {
95 average += foo_from_bar.params();
98 average / TScalar(k_matrix_dim));
104 int kPointDim = TSequenceContainer::value_type::kDof,
105 class TScalar =
typename TSequenceContainer::value_type::Scalar>
106 auto average(TSequenceContainer
const& foo_from_bar_transforms)
109 typename TSequenceContainer::value_type,
110 Scaling<TScalar, kPointDim> >::value,
111 std::optional<typename TSequenceContainer::value_type> > {
112 size_t const k_matrix_dim = std::distance(
113 std::begin(foo_from_bar_transforms), std::end(foo_from_bar_transforms));
114 SOPHUS_ASSERT(k_matrix_dim >= 1,
"kMatrixDim must be >= 1.");
116 Eigen::Array<TScalar, kPointDim, 1>
average;
118 for (Scaling<TScalar, kPointDim>
const& foo_from_bar :
119 foo_from_bar_transforms) {
120 average += foo_from_bar.params().array().log();
122 return Scaling<TScalar, kPointDim>::fromParams(
123 (
average / TScalar(k_matrix_dim)).exp().matrix());
129 class TScalar =
typename TSequenceContainer::value_type::Scalar>
130 auto average(TSequenceContainer
const& foo_from_bar_transforms)
133 typename TSequenceContainer::value_type,
135 std::optional<typename TSequenceContainer::value_type> > {
138 size_t const k_matrix_dim = std::distance(
139 std::begin(foo_from_bar_transforms), std::end(foo_from_bar_transforms));
140 SOPHUS_ASSERT(k_matrix_dim >= 1,
"kMatrixDim must be >= 1.");
142 TScalar w = TScalar(1. / k_matrix_dim);
144 Eigen::Vector<TScalar, 1>
average;
155 class TScalar =
typename TSequenceContainer::value_type::Scalar>
156 auto average(TSequenceContainer
const& foo_from_bar_transforms)
159 typename TSequenceContainer::value_type,
160 SpiralSimilarity2<TScalar> >::value,
161 std::optional<typename TSequenceContainer::value_type> > {
162 size_t const k_matrix_dim = std::distance(
163 std::begin(foo_from_bar_transforms), std::end(foo_from_bar_transforms));
164 SOPHUS_ASSERT(k_matrix_dim >= 1,
"kMatrixDim must be >= 1.");
165 SpiralSimilarity2<TScalar> foo_from_average =
166 *std::begin(foo_from_bar_transforms);
167 TScalar w = TScalar(1. / k_matrix_dim);
169 Eigen::Vector2<TScalar>
average(TScalar(0), TScalar(0));
170 for (SpiralSimilarity2<TScalar>
const& foo_from_bar :
171 foo_from_bar_transforms) {
172 average += w * (foo_from_average.inverse() * foo_from_bar).log();
174 return foo_from_average * SpiralSimilarity2<TScalar>::exp(
average);
178 template <
class TScalar>
179 void getQuaternion(TScalar
const&);
181 template <
class TScalar>
182 auto getUnitQuaternion(Rotation3<TScalar>
const& r)
183 -> Eigen::Vector<TScalar, 4> {
184 return r.params().template head<4>();
187 template <
class TScalar>
188 auto getUnitQuaternion(SpiralSimilarity3<TScalar>
const& s_r)
189 -> Eigen::Vector<TScalar, 4> {
190 return s_r.params().template head<4>().normalized();
195 class TScalar =
typename TSequenceContainer::value_type::Scalar>
196 auto averageUnitQuaternion(TSequenceContainer
const& foo_from_bar_transforms)
197 -> Eigen::Vector<TScalar, 4> {
199 size_t const k_matrix_dim = std::distance(
200 std::begin(foo_from_bar_transforms), std::end(foo_from_bar_transforms));
201 SOPHUS_ASSERT(k_matrix_dim >= 1,
"kMatrixDim must be >= 1.");
202 Eigen::Matrix<TScalar, 4, Eigen::Dynamic> q(4, k_matrix_dim);
204 TScalar w = TScalar(1. / k_matrix_dim);
205 for (
auto const& foo_from_bar : foo_from_bar_transforms) {
206 q.col(i) = w * details::getUnitQuaternion(foo_from_bar);
210 Eigen::Matrix<TScalar, 4, 4> q_qt = q * q.transpose();
212 Eigen::EigenSolver<Eigen::Matrix<TScalar, 4, 4> > es(q_qt);
214 std::complex<TScalar> max_eigenvalue = es.eigenvalues()[0];
215 Eigen::Matrix<std::complex<TScalar>, 4, 1> max_eigenvector =
216 es.eigenvectors().col(0);
218 for (
int i = 1; i < 4; i++) {
219 if (std::norm(es.eigenvalues()[i]) > std::norm(max_eigenvalue)) {
220 max_eigenvalue = es.eigenvalues()[i];
221 max_eigenvector = es.eigenvectors().col(i);
224 Eigen::Vector<TScalar, 4> quat;
226 max_eigenvector[0].real(),
227 max_eigenvector[1].real(),
228 max_eigenvector[2].real(),
229 max_eigenvector[3].real();
239 class TScalar =
typename TSequenceContainer::value_type::Scalar>
240 auto average(TSequenceContainer
const& foo_from_bar_transforms)
243 typename TSequenceContainer::value_type,
244 Rotation3<TScalar> >::value,
245 std::optional<typename TSequenceContainer::value_type> > {
247 details::averageUnitQuaternion(foo_from_bar_transforms));
253 class TScalar =
typename TSequenceContainer::value_type::Scalar>
254 auto average(TSequenceContainer
const& foo_from_bar_transforms)
257 typename TSequenceContainer::value_type,
258 SpiralSimilarity3<TScalar> >::value,
259 std::optional<typename TSequenceContainer::value_type> > {
260 size_t k_matrix_dim = std::distance(
261 std::begin(foo_from_bar_transforms), std::end(foo_from_bar_transforms));
263 SOPHUS_ASSERT(k_matrix_dim >= 1,
"kMatrixDim must be >= 1.");
264 TScalar scale_sum = TScalar(0);
267 for (SpiralSimilarity3<TScalar>
const& foo_from_bar :
268 foo_from_bar_transforms) {
269 scale_sum += log(foo_from_bar.scale());
271 return SpiralSimilarity3<TScalar>(
273 details::averageUnitQuaternion(foo_from_bar_transforms)),
274 exp(scale_sum / TScalar(k_matrix_dim)));
279 class TScalar =
typename TSequenceContainer::value_type::Scalar>
281 TSequenceContainer
const& foo_from_bar_transforms,
282 int max_num_iterations = 20)
285 typename TSequenceContainer::value_type,
287 std::optional<typename TSequenceContainer::value_type> > {
290 return iterativeMean(foo_from_bar_transforms, max_num_iterations);
295 class TScalar =
typename TSequenceContainer::value_type::Scalar>
297 TSequenceContainer
const& foo_from_bar_transforms,
298 int max_num_iterations = 20)
301 typename TSequenceContainer::value_type,
302 Similarity2<TScalar> >::value,
303 std::optional<typename TSequenceContainer::value_type> > {
304 return iterativeMean(foo_from_bar_transforms, max_num_iterations);
309 class TScalar =
typename TSequenceContainer::value_type::Scalar>
311 TSequenceContainer
const& foo_from_bar_transforms,
312 int max_num_iterations = 20)
315 typename TSequenceContainer::value_type,
316 Isometry3<TScalar> >::value,
317 std::optional<typename TSequenceContainer::value_type> > {
318 return iterativeMean(foo_from_bar_transforms, max_num_iterations);
323 class TScalar =
typename TSequenceContainer::value_type::Scalar>
325 TSequenceContainer
const& foo_from_bar_transforms,
326 int max_num_iterations = 20)
329 typename TSequenceContainer::value_type,
330 Similarity3<TScalar> >::value,
331 std::optional<typename TSequenceContainer::value_type> > {
332 return iterativeMean(foo_from_bar_transforms, max_num_iterations);
337 int kPointDim = TSequenceContainer::value_type::kPointDim,
338 class TScalar =
typename TSequenceContainer::value_type::Scalar>
340 TSequenceContainer
const& foo_from_bar_transforms,
341 int max_num_iterations = 20)
344 typename TSequenceContainer::value_type,
346 std::optional<typename TSequenceContainer::value_type> > {
347 return iterativeMean(foo_from_bar_transforms, max_num_iterations);
350 #endif // DOXYGEN_SHOULD_SKIP_THIS