Eigen四元数 初始化的坑!!!一天的教训!

四元数初始化有多种形式,容易出错的是:由于Eigen中四元数存储顺序(从打印可知)是xyzw,导致赋值出现的错误:

方式一:4个标量

Quaterniond q1(1, 2, 3, 4);                               // 第一种方式  实部为1 ,虚部234

方式二:Vector4d

Quaterniond q2(Vector4d(1, 2, 3, 4));             // 第二种方式  实部为4 ,虚部123

方式三:数组

Quaterniond q2(tmp_q);                                  // 第三种方式,double tmp_q[4];   实部为4 ,虚部123

大坑:方式三不能用!解决方案:我在使用的时候改成了Eigen::Quaternion<T> q_map_vinsWorld(tmp_q[0], tmp_q[1], tmp_q[2], tmp_q[3])因为ceres::RotationMatrixToQuaternion(tmp_R_transposed, tmp_q)得到了wxyz顺序的T tmp_q[4]

 

最终结论:推荐方式一。

1、通过向量初始化时,要注意Eigen四元数的存储顺序,从cout << q.coeffs() << endl;  打印可知,其内部存储是:xyzw。

2、第二种第三种怀疑是 构造初始化时  直接把q.coeffs() = Vector4d / double*  ,而第一种方式,构建初始化时自动调整了顺序给coeffs。

3、本人出错记录:

(1)通过ceres::RotationMatrixToQuaternion(R_map_vinsWorld, tmp_q)得到了wxyz顺序的T tmp_q[4]

(2)Eigen::Quaternion<T> q_map_vinsWorld(tmp_q)直接赋值,结果出错!!!

T tmp_q[4];
T R_map_vinsWorld[9];
YawPitchRollToRotationMatrix(extri_yaw_baselink_IMU[0], T(0), T(0), R_map_vinsWorld);//建图程序中R_map_vinsWorld和R_baselink_IMU的yaw角相同
ceres::RotationMatrixToQuaternion(R_map_vinsWorld, tmp_q); 
cout<<"extri_yaw_baselink_IMU[0]="<<extri_yaw_baselink_IMU[0]<<endl;
cout<<"tmp_q="<<tmp_q[0]<<" "<<tmp_q[1]<<" "<<tmp_q[2]<<" "<<tmp_q[3]<<endl;
Eigen::Quaternion<T> q_map_vinsWorld(tmp_q);
cout<<"q_map_vinsWorld="<<q_map_vinsWorld.w()<<" "<<q_map_vinsWorld.x()<<" "<<q_map_vinsWorld.y()<<" "<<q_map_vinsWorld.z()<<endl;

输出如下:

extri_yaw_baselink_IMU[0]=-90
tmp_q                   =0.707107 -0 -0 0.707107
q_map_vinsWorld=0.707107 0.707107 -0 -0

3、注意ceres中有专门的EigenQuaternionParameterization来 针对解决 Eigen四元数中通过q.coeffs.data()得到double * 时xyzw的情况。如果通过 4个double标量赋值,就可以wxyz赋值,避免EigenQuaternionParameterization,而直接用QuaternionParameterization

好比6DOF优化时

                q_array[i][0] = tmp_q.w();
                q_array[i][1] = tmp_q.x();
                q_array[i][2] = tmp_q.y();
                q_array[i][3] = tmp_q.z();

                sequence_array[i] = (*it)->sequence;

                problem.AddParameterBlock(q_array[i], 4, local_parameterization);

但在CameraFatory中

        ceres::LocalParameterization* quaternionParameterization = 
            new EigenQuaternionParameterization;

        problem.SetParameterization(transformVec.at(i).rotationData(),
                                    quaternionParameterization);
其原因在于他自己写的rotationData函数,用的Eigen::Quaternion.coeffs().data()中内部的存储形式:
double*
Transform::rotationData(void)
{
    return m_q.coeffs().data();
}

 

 

 

int main() {
        cout << "Quaternion from vector4d(1, 2, 3, 4) is:\n"        
                << Quaterniond(Vector4d(1, 2, 3, 4)).coeffs().transpose() << endl;   
        cout << "Quaternion from (1, 2, 3, 4) is:\n"        
                << Quaterniond(1, 2, 3, 4).coeffs().transpose() << endl;   
        return 0;
}

// 输出:

Quaternion from vector4d(1, 2, 3, 4) is:
1 2 3 4
Quaternion from (1, 2, 3, 4) is:
2 3 4 1

 

 

 

 

  • 23
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
EIGEN库中,可以使用不同的方式初始化四元数Quaterniond。 第一种方式是使用四个实数w、x、y、z来初始化Quaterniond对象,例如: Eigen::Quaterniond q1(w, x, y, z) [1。 第二种方式是使用一个四维向量Vector4d来初始化Quaterniond对象,向量的顺序是x、y、z、w,例如: Eigen::Quaterniond q2(Vector4d(x, y, z, w)) [1。 第三种方式是使用一个旋转矩阵Matrix3d来初始化Quaterniond对象,例如: Eigen::Quaterniond q3(Matrix3d(R)) [1。 另外,在引用中,简单地声明一个Quaterniond对象,而未进行初始化。在需要时,可以通过赋值操作来初始化Quaterniond对象,例如: Eigen::Quaterniond quaternion; quaternion = rotation_vector; [3。 总结起来,EIGEN库中的Quaterniond对象可以通过四个实数、四维向量或旋转矩阵来进行初始化。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Eigen四元数Quaterniond的初始](https://blog.csdn.net/hjwang1/article/details/106752766)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [eigen 中旋转向量、旋转矩阵、欧拉角、四元数初始化及相互转换](https://blog.csdn.net/xiaojinger_123/article/details/124376199)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值