while (!gpsQueue.empty())
{
sensor_msgs::NavSatFixConstPtr GPS_msg = gpsQueue.front();
double gps_t = GPS_msg->header.stamp.toSec();
printf("vio t: %f, gps t: %f \n", t, gps_t);
// 10ms sync tolerance
if (gps_t >= t - 0.01 && gps_t <= t + 0.01)
{
...
printf("receive covariance %lf \n", pos_accuracy);
globalEstimator.inputGPS(t, latitude, longitude, altitude, pos_accuracy);
gpsQueue.pop();
break;
}
else if (gps_t < t - 0.01)
gpsQueue.pop();
else if (gps_t > t + 0.01)
break;
}
void GlobalOptimization::inputGPS(double t, double latitude, double longitude, double altitude, double posAccuracy)
{
double xyz[3];
GPS2XYZ(latitude, longitude, altitude, xyz);
vector<double> tmp{xyz[0], xyz[1], xyz[2], posAccuracy};
//printf("new gps: t: %f x: %f y: %f z:%f \n", t, tmp[0], tmp[1], tmp[2]);
GPSPositionMap[t] = tmp;
newGPS = true;
}
void GlobalOptimization::inputOdom(double t, Eigen::Vector3d OdomP, Eigen::Quaterniond OdomQ)
{
mPoseMap.lock();
vector<double> localPose{OdomP.x(), OdomP.y(), OdomP.z(),
OdomQ.w(), OdomQ.x(), OdomQ.y(), OdomQ.z()};
localPoseMap[t] = localPose;
Eigen::Quaterniond globalQ;
globalQ = WGPS_T_WVIO.block<3, 3>(0, 0) * OdomQ;
Eigen::Vector3d globalP = WGPS_T_WVIO.block<3, 3>(0, 0) * OdomP + WGPS_T_WVIO.block<3, 1>(0, 3);
vector<double> globalPose{globalP.x(), globalP.y(), globalP.z(),
globalQ.w(), globalQ.x(), globalQ.y(), globalQ.z()};
globalPoseMap[t] = globalPose;
lastP = globalP;
lastQ = globalQ;
...
mPoseMap.unlock();
}
void GlobalOptimization::optimize() {
while (true) {
if (newGPS) {
newGPS = false;
...
//...ceres
ceres::LocalParameterization *local_parameterization =
new ceres::QuaternionParameterization();
// add param
mPoseMap.lock();
int length = localPoseMap.size();
// w^t_i w^q_i
double t_array[length][3];
double q_array[length][4];
map<double, vector<double>>::iterator iter;
iter = globalPoseMap.begin();
for (int i = 0; i < length; i++, iter++) {
...
//初始添加的是gps坐标系下的参数
problem.AddParameterBlock(q_array[i], 4, local_parameterization);
problem.AddParameterBlock(t_array[i], 3);
}
...
for (iterVIO = localPoseMap.begin(); iterVIO != localPoseMap.end();
iterVIO++, i++) {
// vio factor
iterVIONext = iterVIO;
iterVIONext++;
if (iterVIONext != localPoseMap.end()) {
...
//添加i帧和j帧vio(VIO坐标系下)
wTi.block<3, 3>(0, 0) =...
wTi.block<3, 1>(0, 3) =...
wTj.block<3, 3>(0, 0) =...
wTj.block<3, 1>(0, 3) =...
// 第j帧到第i帧的变换矩阵
Eigen::Matrix4d iTj = wTi.inverse() * wTj;
...
iQj = iTj.block<3, 3>(0, 0);
iPj = iTj.block<3, 1>(0, 3);
ceres::CostFunction *vio_function =
RelativeRTError::Create(iPj.x(), iPj.y(), iPj.z(), iQj.w(),
iQj.x(), iQj.y(), iQj.z(), 0.1, 0.01);
problem.AddResidualBlock(vio_function, NULL, q_array[i], t_array[i],
q_array[i + 1], t_array[i + 1]);
}
// gps factor
double t = iterVIO->first;
iterGPS = GPSPositionMap.find(t);
if (iterGPS != GPSPositionMap.end()) {
ceres::CostFunction *gps_function =
TError::Create(iterGPS->second[0], iterGPS->second[1],
iterGPS->second[2], iterGPS->second[3]);
// printf("inverse weight %f \n", iterGPS->second[3]);
problem.AddResidualBlock(gps_function, loss_function, t_array[i]);
}
}
...
//求解最小二乘
iter = globalPoseMap.begin();
for (int i = 0; i < length; i++, iter++) {
//取出优化参数
vector<double> globalPose{t_array[i][0], t_array[i][1], t_array[i][2],
q_array[i][0], q_array[i][1], q_array[i][2],
q_array[i][3]};
iter->second = globalPose;
if (i == length - 1) {
Eigen::Matrix4d WVIO_T_body = Eigen::Matrix4d::Identity();
Eigen::Matrix4d WGPS_T_body = Eigen::Matrix4d::Identity();
double t = iter->first;
//VIO到body坐标系的q
WVIO_T_body.block<3, 3>(0, 0) =...localPose_q
//VIO到body坐标系的t
WVIO_T_body.block<3, 1>(0, 3) =...localPose_t
//GPS到body坐标系的q
WGPS_T_body.block<3, 3>(0, 0) =...globalPose_q
//GPS到body坐标系的t
WGPS_T_body.block<3, 1>(0, 3) =...globalPose_t
//GPS到VIO坐标系的变换矩阵
WGPS_T_WVIO = WGPS_T_body * WVIO_T_body.inverse();
}
}
//更新全局路径
updateGlobalPath();
mPoseMap.unlock();
}
...
}
return;
}
A General Optimization-based Framework for Global Pose Estimation with Multiple Sensors
VINS Fusion算法解读