如何获取Eigen::Matrix的行地址?实现向Ceres代价函数逐行传参
正确获取Eigen矩阵行引用并传入Ceres的方法
首先要明确Eigen默认矩阵是列主序存储,这意味着一行的元素在内存中并不是连续的,直接传行的指针会导致Ceres读取错误数据,这是很多人踩坑的点。下面分两种场景给出解决方案:
场景1:改为行主序矩阵(推荐,无拷贝开销)
如果可以修改矩阵的存储顺序,定义时指定行主序:
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> intensityEigenMat;
此时每一行的内存是连续的,你可以通过以下方式获取行的引用或指针:
- 获取行的常量引用(适合Ceres代价函数接受
const Eigen::Ref<const Eigen::RowVectorXd>&参数):Eigen::Ref<const Eigen::RowVectorXd> row_ref = intensityEigenMat.row(i); - 获取行的原始指针(适合Ceres接受
const double*参数):const double* row_ptr = intensityEigenMat.row(i).data();
场景2:保持默认列主序矩阵(需拷贝)
如果不能修改矩阵存储顺序,需要先将行拷贝到连续内存的向量中:
Eigen::RowVectorXd row_vec = intensityEigenMat.row(i);
之后直接传递row_vec(引用)或row_vec.data()(指针)给Ceres即可,缺点是会产生一次数据拷贝,大矩阵场景下有性能开销。
你之前写法的问题
intensityEigenMat.row(0):返回的是Eigen的行表达式对象(不是直接的向量类型),如果Ceres代价函数的参数不支持Eigen的表达式类型,会编译失败。&intensityEigenMat.row(0):取的是临时表达式对象的地址,属于未定义行为,编译器可能直接报错或运行时崩溃。&intensityEigenMat.row(0).data():data()返回的是double*,取它的地址得到double**,完全不符合Ceres需要的参数类型。
内容的提问来源于stack exchange,提问作者user22132012
相关产品推荐
相关产品推荐

