Nonconvex constrained optimization
Loading...
Searching...
No Matches
indicator-so3.hpp
Go to the documentation of this file.
1#pragma once
2
5#include <Eigen/LU>
6#include <Eigen/SVD>
7#include <cassert>
8
10
11/// Indicator function of SO(3), the group of 3D rotation matrices.
12/// @ingroup grp_Functions
13template <Config Conf>
16
17 /// Project a 3x3 matrix onto SO(3). Accepts both 3x3 matrices and
18 /// 9-vectors as input and output (using column-major storage order).
19 /// @p in and @p out may alias.
20 real_t prox(crmat in, rmat out, [[maybe_unused]] real_t gamma = 1) {
21 assert(in.rows() == out.rows());
22 assert(in.cols() == out.cols());
23 [[maybe_unused]] const bool is_3x3_matrix =
24 in.rows() == 3 && in.cols() == 3;
25 [[maybe_unused]] const bool is_9_vector =
26 in.size() == 9 && (in.rows() == 9 || in.cols() == 9);
27 assert(is_3x3_matrix || is_9_vector);
28
29 using so3_mat = Eigen::Matrix<real_t, 3, 3>;
30 Eigen::JacobiSVD<so3_mat> svd{
31 in.reshaped(3, 3), Eigen::ComputeFullU | Eigen::ComputeFullV};
32 so3_mat U = svd.matrixU();
33 auto &&V = svd.matrixV();
34 // Ensure a proper rotation (det = +1) by flipping the smallest singular axis.
35 if (U.determinant() * V.determinant() < 0)
36 U.col(2) *= real_t{-1};
37 out.reshaped(3, 3).noalias() = U * V.transpose();
38 return 0;
39 }
40
41 friend real_t guanaqo_tag_invoke(tag_t<alpaqa::prox>, IndicatorSO3 &self,
42 crmat in, rmat out, real_t gamma) {
43 return self.prox(std::move(in), std::move(out), gamma);
44 }
45};
46
47} // namespace alpaqa::functions
#define USING_ALPAQA_CONFIG(Conf)
Definition config.hpp:77
typename Conf::crmat crmat
Definition config.hpp:97
typename Conf::rmat rmat
Definition config.hpp:96
typename Conf::real_t real_t
Definition config.hpp:86
Indicator function of SO(3), the group of 3D rotation matrices.
real_t prox(crmat in, rmat out, real_t gamma=1)
Project a 3x3 matrix onto SO(3).
friend real_t guanaqo_tag_invoke(tag_t< alpaqa::prox >, IndicatorSO3 &self, crmat in, rmat out, real_t gamma)