C++示例代码
#include
#include
#include
#include
#include
#include
#include
#include
inline Eigen::Vector3d Transform(const Eigen::Vector3d& point,
const Eigen::Vector3d& route,
const Eigen::Vector3d& origin,
double scale = 1)
{
auto [x0, y0, z0] = std::make_tuple(point.x(), point.y(), point.z());
auto [rx, ry, rz] = std::make_tuple(route.x(), route.y(), route.z());
auto [x, y, z] = std::make_tuple(origin.x(), origin.y(), origin.z());
double A[9];
A[0] = cos(ry) * cos(rz);
A[1] = -cos(ry) * sin(rz);
A[2] = sin(ry);
A[3] = sin(rx) * sin(ry) * cos(rz) + cos(rx) * sin(rz);
A[4] = -sin(rx) * sin(ry) * sin(rz) + cos(rx) * cos(rz);
A[5] = -sin(rx) * cos(ry);
A[6] = -cos(rx) * sin(ry) * cos(rz) + sin(rx) * sin(rz);
A[7] = cos(rx) * sin(ry) * sin(rz) + sin(rx) * cos(rz);
A[8] = cos(rx) * cos(ry);
double x1 = (A[0] * x0 + A[1] * y0 + A[2] * z0) / scale + x;
double y1 = (A[3] * x0 + A[4] * y0 + A[5] * z0) / scale + y;
double z1 = (A[6] * x0 + A[7] * y0 + A[8] * z0) / scale + z;
return { x1, y1, z1 };
}
inline Eigen::Vector3d ReTransform(Eigen::Vector3d point,
Eigen::Vector3d route,
Eigen::Vector3d origin,
double scale = 1)
{
auto [x0, y0, z0] = std::make_tuple(point.x(), point.y(), point.z());
auto [rx, ry, rz] = std::make_tuple(route.x(), route.y(), route.z());
auto [x, y, z] = std::make_tuple(origin.x(), origin.y(), origin.z());
double x1 = 0, y1 = 0, z1 = 0;
double A[9];
A[0] = cos(ry) * cos(rz);
A[1] = -cos(ry) * sin(rz);
A[2] = sin(ry);
A[3] = sin(rx) * sin(ry) * cos(rz) + cos(rx) * sin(rz);
A[4] = -sin(rx) * sin(ry) * sin(rz) + cos(rx) * cos(rz);
A[5] = -sin(rx) * cos(ry);
A[6] = -cos(rx) * sin(ry) * cos(rz) + sin(rx) * sin(rz);
A[7] = cos(rx) * sin(ry) * sin(rz) + sin(rx) * cos(rz);
A[8] = cos(rx) * cos(ry);
x1 = (A[0] * (x0 - x) + A[3] * (y0 - y) + A[6] * (z0 - z)) * scale;
y1 = (A[1] * (x0 - x) + A[4] * (y0 - y) + A[7] * (z0 - z)) * scale;
z1 = (A[2] * (x0 - x) + A[5] * (y0 - y) + A[8] * (z0 - z)) * scale;
return { x1, y1, z1 };
}
QVector3D TransformAxis(QVector3D& point, QVector3D axisO, QVector3D axisR)
{
auto v3 = Transform({ point.x(), point.y(), point.z() }, { axisR.x(), axisR.y(), axisR.z() }, { axisO.x(), axisO.y(), axisO.z() });
QVector3D p;
p.setX(v3.x());
p.setY(v3.y());
p.setZ(v3.z());
return p;
}
QVector3D ReTransformAxis(const QVector3D& point, const QVector3D& axisO, const QVector3D& axisR)
{
auto v3 = ReTransform({ point.x(), point.y(), point.z() }, { axisR.x(), axisR.y(), axisR.z() }, { axisO.x(), axisO.y(), axisO.z() });
QVector3D p;
p.setX(v3.x());
p.setY(v3.y());
p.setZ(v3.z());
return p;
}
std::tuple<double, double, double> GetEulerAngles(const Eigen::MatrixXd& R)
{
return { atan2(R(2, 1), R(2, 2)),
atan2(-R(2, 0), sqrt(R(2, 1) * R(2, 1) + R(2, 2) * R(2, 2))),
atan2(R(1, 0), R(0, 0)) };
}
void RodriguesMatrixModel(const Eigen::MatrixXd& src, const Eigen::MatrixXd& dst, Eigen::MatrixXd& R, Eigen::Vector3d& t, float& scale)
{
Eigen::Vector3d src_mean = src.colwise().mean();
Eigen::Vector3d dst_mean = dst.colwise().mean();
Eigen::MatrixXd src_demean = src.rowwise() - src_mean.transpose();
Eigen::MatrixXd dst_demean = dst.rowwise() - dst_mean.transpose();
Eigen::VectorXd src_norm = src_demean.rowwise().norm();
Eigen::VectorXd dst_norm = dst_demean.rowwise().norm();
scale = dst_norm.sum() / src_norm.sum();
Eigen::MatrixXd H = src_demean.transpose() * dst_demean;
Eigen::JacobiSVD<Eigen::MatrixXd> svd(H, Eigen::ComputeFullU | Eigen::ComputeFullV);
R = svd.matrixV() * svd.matrixU().transpose();
t = dst_mean - scale * R * src_mean;
}
int main(int argc, char* argv[])
{
QCoreApplication a(argc, argv);
Eigen::MatrixXd src(4, 3), dst(4, 3);
src << -4.39564,
-3.4181,
-1.35831,
-3.66698,
-4.76856,
-1.36094,
-1.40378,
-4.75369,
-1.35691,
0.469564,
-1.93813,
-1.3715;
dst << -4.489,
-3.42713,
-1.35089,
-3.62411,
-4.67908,
-1.36181,
-1.36258,
-4.41787,
-1.36174,
0.16377,
-1.42107,
-1.36566;
Eigen::MatrixXd R;
Eigen::Vector3d t;
float scale;
RodriguesMatrixModel(src, dst, R, t, scale);
qDebug() << "R:" << R(0, 0) << R(0, 1) << R(0, 2) << '\n'
<< R(1, 0) << R(1, 1) << R(1, 2) << '\n'
<< R(2, 0) << R(2, 1) << R(2, 2) << '\n';
qDebug() << "t:" << t(0) << t(1) << t(2);
qDebug() << "s:" << scale;
auto&& [rx, ry, rz] = GetEulerAngles(R);
qDebug() << "rx:" << rx << "ry:" << ry << "rz:" << rz << '\n';
auto&& p = Transform({
-4.39564,
-3.4181,
-1.35831,
},
{ rx, ry, rz }, { t(0), t(1), t(2) });
qDebug() << "测试:" << p(0) << p(1) << p(2);
return a.exec();
}
结果