Eigen模板结构体调用cast()方法编译报错求助
编译包含Eigen库的C++代码时遇到模板相关编译错误,同时代码存在main函数拼写错误、ring_rot_offset类型不匹配问题,目标是通过自定义模板结构体的cast方法转换Eigen容器数值类型。
源码(mag_models.cpp)
#include <iostream> #include "Eigen/Core" #include "Eigen/Geometry" using namespace std; using namespace Eigen; template <typename T> struct CoilCalibrationModel { double global_gain; Eigen::Vector3<T> noise; Eigen::Vector3<T> bias; Eigen::Vector3<T> gain; Eigen::Vector3<T> per_channel_gain; Eigen::Vector3<T> sensor_offset; Eigen::Quaternion<T> sensor_rot_offset; Eigen::Vector3<T> ring_offset; Eigen::Quaternion<T> ring_rot_offset; Eigen::Quaternion<double> base_sensor_offset; Eigen::Quaternion<double> base_sensor_rot_offset; array<double, 3> crosstalk; template<typename U> CoilCalibrationModel<U> cast() const { CoilCalibrationModel<U> model; model.global_gain = U(global_gain); model.noise = noise.cast<U>(); model.bias = bias.cast<U>(); model.gain = gain.cast<U>(); model.per_channel_gain = per_channel_gain.cast<U>(); model.sensor_offset = sensor_offset.cast<U>(); model.sensor_rot_offset = sensor_rot_offset.cast<U>(); model.ring_offset = ring_offset.cast<U>(); model.ring_rot_offset = ring_rot_offset.cast<U>(); model.base_sensor_offset = base_sensor_offset.cast<U>();; model.base_sensor_rot_offset = base_sensor_rot_offset.cast<U>();; model.crosstalk = {T(crosstalk[0]), T(crosstalk[1]), T(crosstalk[2])}; return model; } }; int mian(){ CoilCalibrationModel<double> fram; fram.global_gain= 0.5; fram.noise = Eigen::Vector3<double>(1,2,3); fram.bias = Eigen::Vector3<double>(1,2,3); fram.gain = Eigen::Vector3<double>(1,2,3); fram.per_channel_gain = Eigen::Vector3<double>(1,2,3); fram.sensor_offset = Eigen::Vector3<double>(1,2,3); fram.sensor_rot_offset = Eigen::Quaternion<double>(1,2,3,4); fram.ring_offset = Eigen::Vector3<double>(1,2,3); fram.ring_rot_offset = Eigen::Vector3<double>(1,2,3); fram.base_sensor_offset = Eigen::Quaternion<double>(1,2,3,4); fram.base_sensor_rot_offset = Eigen::Quaternion<double>(1,2,3,4); fram.crosstalk ={1.0,2.0,3.0}; cout<<" before cast :"<<fram.global_gain<<endl; CoilCalibrationModel<int> framcast = fram.cast<int>(); cout<<" after cast :"<<framcast.global_gain<<endl; }
CMake配置文件
cmake_minimum_required (VERSION 3.8) project ("mag-inverse") set(CMAKE_BUILD_TYPE RelWithDebInfo) Find_Package(Eigen3 REQUIRED) Find_Package(Ceres REQUIRED COMPONENTS SuiteSparse EigenSparse Multithreading LAPACK) include_directories(${CERES_INCLUDE_DIRS}) include_directories(${EIGEN3_INCLUDE_DIRS}) find_package(gflags REQUIRED) include_directories(.) add_executable(magtest mag_models.cpp) target_link_libraries(magtest ${CERES_LIBRARIES}) target_link_libraries(magtest gflags)
编译错误信息
error: expected primary-expression before ‘>’ token 31 | model.noise = noise.cast<U>(); | ^ /home/xx/AuraTest/mag_models.cpp:31:31: error: expected primary-expression before ‘)’ token 31 | model.noise = noise.cast<U>(); | ^ /home/xx/AuraTest/mag_models.cpp:32:27: error: expected primary-expression before ‘>’ token 32 | model.bias = bias.cast<U>(); | ^ /home/xx/AuraTest/mag_models.cpp:32:29: error: expected primary-expression before ‘)’ token 32 | model.bias = bias.cast<U>();
环境信息
- gcc/g++ 版本:9.4
- Eigen版本:3.4
问题修复方案
模板成员函数调用需显式声明
template
在模板类的成员函数中调用Eigen的cast<U>()模板方法时,编译器无法自动推导cast是模板函数,必须在调用前添加template关键字,例如将noise.cast<U>()修改为noise.template cast<U>(),所有Eigen容器的cast调用都需要做此修改。修正main函数拼写错误
将int mian()改为int main()。修正
ring_rot_offset类型不匹配
结构体中ring_rot_offset的类型是Eigen::Quaternion<T>,但main函数中用Eigen::Vector3<double>赋值,需改为Eigen::Quaternion<double>类型赋值:fram.ring_rot_offset = Eigen::Quaternion<double>(1,2,3,4);。移除多余分号
删除model.base_sensor_offset = base_sensor_offset.cast<U>();;和model.base_sensor_rot_offset = base_sensor_rot_offset.cast<U>();;中的多余分号。补充缺失的头文件
代码中使用了array但未包含<array>头文件,需添加#include <array>。
修复后的完整代码
#include <iostream> #include <array> #include "Eigen/Core" #include "Eigen/Geometry" using namespace std; using namespace Eigen; template <typename T> struct CoilCalibrationModel { double global_gain; Eigen::Vector3<T> noise; Eigen::Vector3<T> bias; Eigen::Vector3<T> gain; Eigen::Vector3<T> per_channel_gain; Eigen::Vector3<T> sensor_offset; Eigen::Quaternion<T> sensor_rot_offset; Eigen::Vector3<T> ring_offset; Eigen::Quaternion<T> ring_rot_offset; Eigen::Quaternion<double> base_sensor_offset; Eigen::Quaternion<double> base_sensor_rot_offset; array<double, 3> crosstalk; template<typename U> CoilCalibrationModel<U> cast() const { CoilCalibrationModel<U> model; model.global_gain = U(global_gain); model.noise = noise.template cast<U>(); model.bias = bias.template cast<U>(); model.gain = gain.template cast<U>(); model.per_channel_gain = per_channel_gain.template cast<U>(); model.sensor_offset = sensor_offset.template cast<U>(); model.sensor_rot_offset = sensor_rot_offset.template cast<U>(); model.ring_offset = ring_offset.template cast<U>(); model.ring_rot_offset = ring_rot_offset.template cast<U>(); model.base_sensor_offset = base_sensor_offset.template cast<U>(); model.base_sensor_rot_offset = base_sensor_rot_offset.template cast<U>(); model.crosstalk = {U(crosstalk[0]), U(crosstalk[1]), U(crosstalk[2])}; return model; } }; int main(){ CoilCalibrationModel<double> fram; fram.global_gain= 0.5; fram.noise = Eigen::Vector3<double>(1,2,3); fram.bias = Eigen::Vector3<double>(1,2,3); fram.gain = Eigen::Vector3<double>(1,2,3); fram.per_channel_gain = Eigen::Vector3<double>(1,2,3); fram.sensor_offset = Eigen::Vector3<double>(1,2,3); fram.sensor_rot_offset = Eigen::Quaternion<double>(1,2,3,4); fram.ring_offset = Eigen::Vector3<double>(1,2,3); fram.ring_rot_offset = Eigen::Quaternion<double>(1,2,3,4); fram.base_sensor_offset = Eigen::Quaternion<double>(1,2,3,4); fram.base_sensor_rot_offset = Eigen::Quaternion<double>(1,2,3,4); fram.crosstalk ={1.0,2.0,3.0}; cout<<" before cast :"<<fram.global_gain<<endl; CoilCalibrationModel<int> framcast = fram.cast<int>(); cout<<" after cast :"<<framcast.global_gain<<endl; }
内容的提问来源于stack exchange,提问作者Soar

