Suppose it mainly rotates around a certain coordinate axis(A person stands in front of the camera and rotates around to get the rotation matrix), try the following code:
float calc_angle(Eigen::Matrix3f &R_, int axis_)
{
//! the coordinate system is consistent with "vedo"
//! suppose it mainly rotates around a certain coordinate axis(X/Y/Z)
Eigen::Vector3f aX_(1.0f, 0.0f, 0.0f);
Eigen::Vector3f aY_(0.0f, 1.0f, 0.0f);
Eigen::Vector3f aZ_(0.0f, 0.0f, 1.0f);
Eigen::Vector3f v0_, v1_;
int axis_contrary_[2];
switch (axis_)
{
case 0 /* x */:
axis_contrary_[0] = 1;
axis_contrary_[1] = 2;
v0_ = aY_;
v1_ = aZ_;
break;
case 1 /* y */:
axis_contrary_[0] = 0;
axis_contrary_[1] = 2;
v0_ = aX_;
v1_ = aZ_;
break;
case 2 /* z */:
axis_contrary_[0] = 0;
axis_contrary_[1] = 1;
v0_ = aX_;
v1_ = aY_;
break;
}
Eigen::Vector3f v0_new_ = R_ * v0_; //R_.col(axis_contrary_[0]);
v0_new_(axis_) = 0.0f;
v0_new_.normalize();
Eigen::Vector3f v1_new_ = R_ * v1_; //R_.col(axis_contrary_[1]);
v1_new_(axis_) = 0.0f;
v1_new_.normalize();
Eigen::Vector3f v2_new_0_ = v0_.cross(v0_new_);
Eigen::Vector3f v2_new_1_ = v1_.cross(v1_new_);
bool is_reverse = ((v2_new_0_[axis_] + v2_new_1_[axis_]) / 2.0f < 0.0f);
float cos_theta_0_ = v0_new_(axis_contrary_[0]);
float cos_theta_1_ = v1_new_(axis_contrary_[1]);
float theta_0_ = std::acos(cos_theta_0_) / 3.14f * 180.0f;
float theta_1_ = std::acos(cos_theta_1_) / 3.14f * 180.0f;
// std::cout << "theta_0_: " << theta_0_ << std::endl;
// std::cout << "theta_1_: " << theta_1_ << std::endl;
float theta_ = (theta_0_ + theta_1_) / 2.0f;
float deg_;
if (!is_reverse)
{
deg_ = theta_;
}
else
{
deg_ = 360.0f - theta_;
}
return deg_;
}
and you can visualize with the following code:
import numpy as np
from glob import glob
from vedo import *
path_folder = ".../data/20210203_175550/res_R"
path_R_ALL = sorted(glob(path_folder + "/*_R.txt"))
path_t_ALL = sorted(glob(path_folder + "/*_t.txt"))
o = np.array([0, 0, 0])
x = np.mat([1, 0, 0]).T
y = np.mat([0, 1, 0]).T
z = np.mat([0, 0, 1]).T
vp = Plotter(axes=4)
vp += Box((0, 0, 0), 3, 3, 3, alpha=0.1)
for i, (path_R, path_t) in enumerate(zip(path_R_ALL, path_t_ALL)):
R = np.loadtxt(path_R)
R = np.mat(R.reshape(3, 3)).T
# t = np.loadtxt(path_t)
# t = np.mat(t).T
Ax = Line(o, R*x, c="r")
Ay = Line(o, R*y, c="g")
Az = Line(o, R*z, c="b")
vp += Ax
vp += Ay
vp += Az
vp.show(interactive=1)
vp -= Ax
vp -= Ay
vp -= Az
x_new = R*x
x_new[1] = 0
x_new = x_new / np.linalg.norm(x_new)
# print("x_new:", x_new)
z_new = R*z
z_new[1] = 0
z_new = z_new / np.linalg.norm(z_new)
# print("z_new:", z_new)
cos_thetaX = x.T * x_new
thetaX = np.arccos(cos_thetaX) / 3.14 * 180
cos_thetaZ = z.T * z_new
thetaZ = np.arccos(cos_thetaZ) / 3.14 * 180
# print(x, x_new)
tmpX = np.cross(x.T, x_new.T)
# print("tmpX:", tmpX)
if tmpX[0][1] < 0:
thetaX = 360 - thetaX
tmpZ = np.cross(z.T, z_new.T)
# print("tmpZ:", tmpZ)
if tmpZ[0][1] < 0:
thetaZ = 360 - thetaZ
# print(i, tmpX, tmpZ)
print(i, thetaX, thetaZ)