相对变换的迭代乘法导致快速不稳定
Iterative multiplication of relative transforms leads to fast instability
我正在编写一个程序,它接收 Eigen 变换并在应用一些噪声后将它们存储在容器中。特别是,在时间 k,我接收到变换 Tk。我从容器中获取转换 Tk-1,创建 delta = Tk-1-1 · Tk,对delta应用一些噪声,将Tk-1 · delta作为容器的新元素存储。
我注意到,在 50 次迭代之后,值完全错误,并且在每次迭代中,我都看到容器的最后一个元素在预乘以它的倒数时,甚至不等于标识。
我已经检查过容器是否遵循 Eigen 指定的分配规则。
我觉得这个问题和我做的操作不稳定有关。
下面的简单代码在 max = 35
时产生非零值,并在 max
大于 60 时产生无穷大。
Eigen::Isometry3d my_pose = Eigen::Isometry3d::Identity();
my_pose.translate(Eigen::Vector3d::Random());
my_pose.rotate(Eigen::Quaterniond::UnitRandom());
Eigen::Isometry3d my_other_pose = my_pose;
int max = 35;
for(int i=0; i < max; i++)
{
my_pose = my_pose * my_pose.inverse() * my_pose;
}
std::cerr << my_pose.matrix() - my_other_pose.matrix() << std::endl;
我很惊讶分歧发生的速度。由于我的真实程序预计会迭代数百次以上,有没有办法创建更稳定的相对转换?
是的,使用 Quaterniond
进行旋转:
Eigen::Isometry3d my_pose = Eigen::Isometry3d::Identity();
my_pose.translate(Eigen::Vector3d::Random());
my_pose.rotate(Eigen::Quaterniond::UnitRandom());
Eigen::Isometry3d my_other_pose = my_pose;
Eigen::Quaterniond q(my_pose.rotation());
int max = 35;
for (int i = 0; i < max; i++) {
std::cerr << q.matrix() << "\n\n";
std::cerr << my_pose.matrix() << "\n\n";
q = q * q.inverse() * q;
my_pose = my_pose * my_pose.inverse() * my_pose;
}
std::cerr << q.matrix() - Eigen::Quaterniond(my_other_pose.rotation()).matrix() << "\n";
std::cerr << my_pose.matrix() - my_other_pose.matrix() << std::endl;
如果您检查打印出的差异,矩阵的旋转部分会出现巨大误差,而平移部分是可以容忍的。旋转矩阵的逆会很快遇到稳定性问题,所以通常不建议直接使用它。
我正在编写一个程序,它接收 Eigen 变换并在应用一些噪声后将它们存储在容器中。特别是,在时间 k,我接收到变换 Tk。我从容器中获取转换 Tk-1,创建 delta = Tk-1-1 · Tk,对delta应用一些噪声,将Tk-1 · delta作为容器的新元素存储。
我注意到,在 50 次迭代之后,值完全错误,并且在每次迭代中,我都看到容器的最后一个元素在预乘以它的倒数时,甚至不等于标识。
我已经检查过容器是否遵循 Eigen 指定的分配规则。 我觉得这个问题和我做的操作不稳定有关。
下面的简单代码在 max = 35
时产生非零值,并在 max
大于 60 时产生无穷大。
Eigen::Isometry3d my_pose = Eigen::Isometry3d::Identity();
my_pose.translate(Eigen::Vector3d::Random());
my_pose.rotate(Eigen::Quaterniond::UnitRandom());
Eigen::Isometry3d my_other_pose = my_pose;
int max = 35;
for(int i=0; i < max; i++)
{
my_pose = my_pose * my_pose.inverse() * my_pose;
}
std::cerr << my_pose.matrix() - my_other_pose.matrix() << std::endl;
我很惊讶分歧发生的速度。由于我的真实程序预计会迭代数百次以上,有没有办法创建更稳定的相对转换?
是的,使用 Quaterniond
进行旋转:
Eigen::Isometry3d my_pose = Eigen::Isometry3d::Identity();
my_pose.translate(Eigen::Vector3d::Random());
my_pose.rotate(Eigen::Quaterniond::UnitRandom());
Eigen::Isometry3d my_other_pose = my_pose;
Eigen::Quaterniond q(my_pose.rotation());
int max = 35;
for (int i = 0; i < max; i++) {
std::cerr << q.matrix() << "\n\n";
std::cerr << my_pose.matrix() << "\n\n";
q = q * q.inverse() * q;
my_pose = my_pose * my_pose.inverse() * my_pose;
}
std::cerr << q.matrix() - Eigen::Quaterniond(my_other_pose.rotation()).matrix() << "\n";
std::cerr << my_pose.matrix() - my_other_pose.matrix() << std::endl;
如果您检查打印出的差异,矩阵的旋转部分会出现巨大误差,而平移部分是可以容忍的。旋转矩阵的逆会很快遇到稳定性问题,所以通常不建议直接使用它。