导出数据
slam 优化后的enu gnss首帧起点转化的真值的enu gnss的经纬高

是这连个计算均方根误差

运行脚本
#!/bin/sh #延迟5秒执行 sleep 1 echo "1 运行开始 vins_rviz" gnome-terminal -t "1-vins_rviz" -x bash -c "\ cd /home/dongdong/v2_Project/v3_SLAM/v5_VinsFusion/catkin ;\ source devel/setup.bash ;\ roslaunch vins vins_rviz.launch ;\ exit;exec bash;" sleep 3 echo "2 kitti_gps_test_my data" gnome-terminal -t "2-kitti_gps_test_mydata" -x bash -c "\ cd /home/dongdong/v2_Project/v3_SLAM/v5_VinsFusion/catkin;\ source devel/setup.bash;\ rosrun vins kitti_gps_test_my2 /media/dongdong/Elements/fjx/2TestData/2TestData/ehang3/;\ exit;exec bash;" #sleep 1 echo "3 global_fusion" gnome-terminal -t "3-global_fusion" -x bash -c "\ cd /home/dongdong/v2_Project/v3_SLAM/v5_VinsFusion/catkin ;\ source devel/setup.bash ;\ rosrun global_fusion global_fusion_node ;\ exit;exec bash;" sleep 1
相机内参改造

%YAML:1.0
#common parameters
imu: 0
num_of_cam: 2
imu_topic: ""
image0_topic: ""
image1_topic: ""
output_path: "/media/fbz/新加卷/data/EHang2022/v1解压后压缩包备份数据/3_for_testing_return_2022-05-25-17-18-43/vins_out/"
cam0_calib: "cam1.yaml"
cam1_calib: "cam2.yaml"
image_width: 720
image_height: 720
# Extrinsic parameter between IMU and Camera.
estimate_extrinsic: 0 # 0 Have an accurate extrinsic parameters. We will trust the following imu^R_cam, imu^T_cam, don't change it.
# 1 Have an initial guess about extrinsic parameters. We will optimize around your initial guess.
#T_cam_imu
body_T_cam0: !!opencv-matrix
rows: 4
cols: 4
dt: d
data: [0.00348999 ,-0.99999188 , 0.0020138, -0.02343326,
-0.9999876 ,-0.00349711 ,-0.00354508 ,0.01260535,
0.0035521 ,-0.0020014 , -0.99999169 ,-0.01791895,
0, 0, 0, 1]
#T_cam_imu
body_T_cam1: !!opencv-matrix
rows: 4
cols: 4
dt: d
data: [0.00446047, -0.99998687 , 0.00252315 ,-0.02420532,
-0.99996658, -0.00444307 , 0.00686255, -0.10818298,
-0.00685125 ,-0.00255368 ,-0.99997327 ,-0.01824371,
0, 0, 0, 1]
#Multiple thread support
multiple_thread: 0
#feature traker paprameters
max_cnt: 200 # max feature number in feature tracking
min_dist: 30 # min distance between two features
freq: 10 # frequence (Hz) of publish tracking result. At least 10Hz for good estimation. If set 0, the frequence will be same as raw image
F_threshold: 1.0 # ransac threshold (pixel)
show_track: 1 # publish tracking image as topic
flow_back: 1 # perform forward and backward optical flow to improve feature tracking accuracy
#optimization parameters
max_solver_time: 0.08 # max solver itration time (s), to guarantee real time
max_num_iterations: 10 # max solver itrations, to guarantee real time
keyframe_parallax: 15 # keyframe selection threshold (pixel)
#imu parameters The more accurate parameters you provide, the better performance
acc_n: 0.1 # accelerometer measurement noise standard deviation. #0.2 0.04
gyr_n: 0.01 # gyroscope measurement noise standard deviation. #0.05 0.004
acc_w: 0.001 # accelerometer bias random work noise standard deviation. #0.02
gyr_w: 1.0e-4 # gyroscope bias random work noise standard deviation. #4.0e-5
g_norm: 9.81007 # gravity magnitude
#unsynchronization parameters
estimate_td: 0 # online estimate time offset between camera and imu
td: 0.0 # initial value of time offset. unit: s. readed image clock + td = real image clock (IMU clock)
核心 相机双目之间的内参

1 局部状态估计

1 输入畸变矫正
2 双目飞机容易丢失 只开启前90帧初始化
/*******************************************************
* Copyright (C) 2019, Aerial Robotics Group, Hong Kong University of Science and Technology
*
* This file is part of VINS.
*
* Licensed under the GNU General Public License v3.0;
* you may not use this file except in compliance with the License.
*
* Author: Qin Tong (qintonguav@gmail.com)
*******************************************************/
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <ros/ros.h>
#include <sensor_msgs/NavSatFix.h>
#include "estimator/estimator.h"
#include "utility/visualization.h"
using namespace std;
using namespace Eigen;
Estimator estimator;
ros::Publisher pubGPS;
void SetImage(cv::Mat &source_img,cv::Mat &dst_img,cv::Mat &cameraMatrix,cv::Mat &distCoeffs){
// double fx= 355.0974745605948;
// double fy= 355.47832693317105;
// double cx= 357.7074039567714;
// double cy= 351.0244037313849;
// double k1= -0.023790306606729556;
// double k2= -0.0007571494794293715;
// double p1= 0.00016452517056601848;
// double p2= -0.0005743824914513448;
// cv::Mat cameraMatrix = (cv::Mat_<double>(3, 3) << fx, 0, cx, 0, fy, cy, 0, 0, 1);
// cv::Mat distCoeffs = (cv::Mat_<float>(4, 1) << k1, k2, p1, p2);
cv::Mat dst_Left;
// 普通图像畸变矫正
//undistort(imLeft, dst_Left, cameraMatrix, distCoeffs);
cv::Size corrected_size(source_img.cols,source_img.rows);
cv::Mat mapx, mapy;
// 鱼眼图像畸变矫正
cv::fisheye::initUndistortRectifyMap(cameraMatrix, distCoeffs, cv::Matx33d::eye(), cameraMatrix, corrected_size, CV_16SC2, mapx, mapy);
remap(source_img, dst_img, mapx, mapy, cv::INTER_LINEAR, cv::BORDER_TRANSPARENT);
// cv::imshow("leftImage", imLeft);
// cv::imshow("dst_Left", dst_Left);
// cv::waitKey(2);
//imLeft=dst_Left;
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "vins_estimator");
ros::NodeHandle n("~");
ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Info);
pubGPS = n.advertise<sensor_msgs::NavSatFix>("/gps", 1000);
// if(argc != 2)
// {
// printf("please intput: rosrun vins kitti_gps_test [config file] [data folder] \n"
// "for example: rosrun vins kitti_gps_test "
// "~/catkin_ws/src/VINS-Fusion/config/kitti_raw/kitti_10_03_config.yaml "
// "/media/tony-ws1/disk_D/kitti/2011_10_03/2011_10_03_drive_0027_sync/ \n");
// return 1;
// }
string data_path = argv[1];
printf("data rource: %s\n", data_path.c_str());
string config_file = data_path+"/Vins_Fusion_Config/config.yaml";
printf("config_file: %s\n", config_file.c_str());
string imgpath = data_path+"/FHY_img/";
printf("imgpath file: %s\n",imgpath.c_str());
// 我们的数据 图像和GPS时间戳采集阶段对应好了
string img_timesharp_gps=data_path + "/FHY_config/FHY_gps.txt";
printf("img_timesharp_gps file: %s\n",img_timesharp_gps.c_str());
string dataPath=data_path;
// load image list
FILE* file;
file = std::fopen(img_timesharp_gps.c_str() , "r"); //.c_str()
if(file == NULL){
printf("cannot find file: %s \n", img_timesharp_gps.c_str());
ROS_BREAK();
return 0;
}
vector<string> imageTimeList;
vector<string> GPSTimeList;
vector<vector<string>> GPSDataList;
char timeshara_c[30];
char lat_c[30], lon_c[30], alt_c[30];
string timesharap_s;
string lat_s, lon_s, alt_s;
double timesharap_l;
double lat_l, lon_l, alt_l;
// 相机内参 畸变矫正用
// 左相机
double fx= 355.0974745605948;
double fy= 355.47832693317105;
double cx= 357.7074039567714;
double cy= 351.0244037313849;
double k1= -0.023790306606729556;
double k2= -0.0007571494794293715;
double p1= 0.00016452517056601848;
double p2= -0.0005743824914513448;
cv::Mat cameraMatrix1 = (cv::Mat_<double>(3, 3) << fx, 0, cx, 0, fy, cy, 0, 0, 1);
cv::Mat distCoeffs1 = (cv::Mat_<float>(4, 1) << k1, k2, p1, p2);
//右相机
fx= 354.57110572187014;
fy= 354.97464271252375;
cx= 384.86917126604794;
cy= 350.73170222126146;
k1= -0.025645869860201013;
k2= 0.0021983043217292503;
p1= -0.001180406728702895;
p2= -0.00021669642909000813;
cv::Mat cameraMatrix2 = (cv::Mat_<double>(3, 3) << fx, 0, cx, 0, fy, cy, 0, 0, 1);
cv::Mat distCoeffs2 = (cv::Mat_<float>(4, 1) << k1, k2, p1, p2);
// 按照string 读取出来 容易保存超高精度
while (fscanf(file, "%s %s %s %s", ×hara_c, &lat_c, &lon_c, &alt_c) != EOF)
////%lf之间应该有逗号,因为没有逗号只能读第一个数。用&是因为要把数存到对应数组元素的地址中去。\n是换行读取
//while (fscanf(file, "%lf %lf %lf %lf", ×harap_l, &lat_l, &lon_l, &alt_l) != EOF)
{
std::cout<< timeshara_c << " "<<lat_c<< " " << lon_c <<" "<<alt_c<<std::endl;
//std::cout<< timesharap_l << " "<<lat_l<< " " << lon_l <<" "<< alt_l<<std::endl;
timesharap_s=(string(timeshara_c)); //stod
lat_s=(string(lat_c));
lon_s=(string(lon_c));
alt_s=(string(alt_c));
imageTimeList.push_back(timesharap_s);
GPSTimeList.push_back(timesharap_s);
vector<string> gpsdata_i;
gpsdata_i.push_back(timesharap_s);
gpsdata_i.push_back(lat_s);
gpsdata_i.push_back(lon_s);
gpsdata_i.push_back(alt_s);
GPSDataList.push_back(gpsdata_i);
std::cout<< fixed << setprecision(10) <<timesharap_s << ' '<<lat_s<< " " << lon_s <<" "<<alt_s<<std::endl;
}
std::fclose(file);
readParameters(config_file);
estimator.setParameter();
registerPub(n);
FILE* outFile;
outFile = fopen((OUTPUT_FOLDER + "/vio.txt").c_str(),"w");
if(outFile == NULL)
printf("Output path dosen't exist: %s\n", OUTPUT_FOLDER.c_str());
string leftImagePath, rightImagePath;
cv::Mat imLeft, imRight;
double baseTime;
if(stod(imageTimeList[0]) < stod(GPSTimeList[0]))
baseTime = stod(imageTimeList[0]);
else
baseTime = stod(GPSTimeList[0]);
for (size_t i = 0; i < imageTimeList.size(); i++)
{
if(ros::ok())
{
//printf("base time is %f\n", baseTime);
printf("process image %d\n", (int)i);
// stringstream ss;
// ss << setfill('0') << setw(10) << i;
int begin_id=0;
if(i<begin_id){
continue;
}
leftImagePath = data_path+"/left/" + imageTimeList[i] + ".png";
rightImagePath = data_path+"/right/" + imageTimeList[i] + ".png";
printf("%s\n", leftImagePath.c_str() );
printf("%s\n", rightImagePath.c_str() );
imLeft = cv::imread(leftImagePath, cv::ImreadModes::IMREAD_GRAYSCALE);
if(imLeft.empty() )
//if(imLeft.empty() && imRight.empty()) //判断是否有数据
{
cout<<"Can not read this image !"<<endl;
continue;
}
if( i>begin_id+0 && i<begin_id+90 ){// 保证初始化
imRight = cv::imread(rightImagePath, cv::ImreadModes::IMREAD_GRAYSCALE);
if(imRight.empty() )
//if(imLeft.empty() && imRight.empty()) //判断是否有数据
{
cout<<"Can not read this image !"<<endl;
continue;
}
SetImage(imRight,imRight,cameraMatrix2,distCoeffs2); //右侧相机畸变矫正
}
else{
cv::Mat imRight_;
imRight=imRight_;
}
//=========================对原始图像畸变矫正==========================
cv::Mat dst_Left;
cv::Mat dst_Right;
SetImage(imLeft,imLeft,cameraMatrix1,distCoeffs1); //左相机畸变矫正
//SetImage(imRight,imRight,cameraMatrix2,distCoeffs2); //右侧相机畸变矫正
//imLeft=dst_Left;
//imRight=dst_Right;
//=========================对原始图像畸变矫正==========================
double imgTime = stod(imageTimeList[i]) - (baseTime);
// // load gps
// FILE* GPSFile;
// string GPSFilePath = dataPath + "oxts/data/" + ss.str() + ".txt";
// GPSFile = std::fopen(GPSFilePath.c_str() , "r");
// if(GPSFile == NULL){
// printf("cannot find file: %s\n", GPSFilePath.c_str());
// ROS_BREAK();
// return 0;
// }
double lat, lon, alt, roll, pitch, yaw;
double vn, ve, vf, vl, vu;
double ax, ay, az, af, al, au;
double wx, wy, wz, wf, wl, wu;
double pos_accuracy, vel_accuracy;
double navstat, numsats;
double velmode, orimode;
double gpstime=atof(GPSDataList[i][0].c_str()) ;
lat= atof(GPSDataList[i][1].c_str()) ;
lon= atof(GPSDataList[i][2].c_str()) ;
alt= atof(GPSDataList[i][3].c_str()) ;
// fscanf(GPSFile, "%lf %lf %lf %lf %lf %lf ", &lat, &lon, &alt, &roll, &pitch, &yaw);
// //printf("lat:%lf lon:%lf alt:%lf roll:%lf pitch:%lf yaw:%lf \n", lat, lon, alt, roll, pitch, yaw);
// fscanf(GPSFile, "%lf %lf %lf %lf %lf ", &vn, &ve, &vf, &vl, &vu);
// //printf("vn:%lf ve:%lf vf:%lf vl:%lf vu:%lf \n", vn, ve, vf, vl, vu);
// fscanf(GPSFile, "%lf %lf %lf %lf %lf %lf ", &ax, &ay, &az, &af, &al, &au);
// //printf("ax:%lf ay:%lf az:%lf af:%lf al:%lf au:%lf\n", ax, ay, az, af, al, au);
// fscanf(GPSFile, "%lf %lf %lf %lf %lf %lf ", &wx, &wy, &wz, &wf, &wl, &wu);
// //printf("wx:%lf wy:%lf wz:%lf wf:%lf wl:%lf wu:%lf\n", wx, wy, wz, wf, wl, wu);
// fscanf(GPSFile, "%lf %lf %lf %lf %lf %lf ", &pos_accuracy, &vel_accuracy, &navstat, &numsats, &velmode, &orimode);
// //printf("pos_accuracy:%lf vel_accuracy:%lf navstat:%lf numsats:%lf velmode:%lf orimode:%lf\n",
// // pos_accuracy, vel_accuracy, navstat, numsats, velmode, orimode);
// std::fclose(GPSFile);
// sensor_msgs::NavSatFix gps_position;
// gps_position.header.frame_id = "NED";
// gps_position.header.stamp = ros::Time(imgTime);
// gps_position.status.status = navstat;
// gps_position.status.service = numsats;
// gps_position.latitude = lat;
// gps_position.longitude = lon;
// gps_position.altitude = alt;
// gps_position.position_covariance[0] = pos_accuracy;
sensor_msgs::NavSatFix gps_position;
gps_position.header.frame_id = "NED";
gps_position.header.stamp = ros::Time(imgTime);
gps_position.status.status = 4; //工作状态 kkt正常时候是4
gps_position.status.service = 8; //卫星数目
gps_position.latitude = lat;
gps_position.longitude = lon;
gps_position.altitude = alt;
gps_position.position_covariance[0] = 0.138013155617496; // 速度误差因子 kkt正常数据找的一个 实际应该跟随gps改变 cereas 优化过程中判断条件是否终止
cout<<fixed << setprecision(7) <<"==="<<i << "=== "<<gps_position.header.stamp <<" "<< lat<<" "<<lon << " "<< alt<<endl;
//printf("pos_accuracy %f \n", pos_accuracy);
pubGPS.publish(gps_position);
estimator.inputImage(imgTime, imLeft, imRight);
Eigen::Matrix<double, 4, 4> pose;
estimator.getPoseInWorldFrame(pose);
if(outFile != NULL)
fprintf (outFile, "%f %f %f %f %f %f %f %f %f %f %f %f \n",pose(0,0), pose(0,1), pose(0,2),pose(0,3),
pose(1,0), pose(1,1), pose(1,2),pose(1,3),
pose(2,0), pose(2,1), pose(2,2),pose(2,3));
// cv::imshow("leftImage", imLeft);
// cv::imshow("rightImage", imRight);
// cv::waitKey(2);
}
else
break;
}
if(outFile != NULL)
fclose (outFile);
return 0;
}
2 全局优化进程

/*******************************************************
* Copyright (C) 2019, Aerial Robotics Group, Hong Kong University of Science and Technology
*
* This file is part of VINS.
*
* Licensed under the GNU General Public License v3.0;
* you may not use this file except in compliance with the License.
*
* Author: Qin Tong (qintonguav@gmail.com)
*******************************************************/
#include "ros/ros.h"
#include "globalOpt.h"
#include <sensor_msgs/NavSatFix.h>
#include <nav_msgs/Odometry.h>
#include <nav_msgs/Path.h>
#include <eigen3/Eigen/Dense>
#include <eigen3/Eigen/Geometry>
#include <iostream>
#include <stdio.h>
#include <visualization_msgs/Marker.h>
#include <visualization_msgs/MarkerArray.h>
#include <fstream>
#include <queue>
#include <mutex>
GlobalOptimization globalEstimator;
ros::Publisher pub_global_odometry, pub_global_path, pub_car;
nav_msgs::Path *global_path;
double last_vio_t = -1;
std::queue<sensor_msgs::NavSatFixConstPtr> gpsQueue;
std::mutex m_buf;
void publish_car_model(double t, Eigen::Vector3d t_w_car, Eigen::Quaterniond q_w_car)
{
visualization_msgs::MarkerArray markerArray_msg;
visualization_msgs::Marker car_mesh;
car_mesh.header.stamp = ros::Time(t);
car_mesh.header.frame_id = "world";
car_mesh.type = visualization_msgs::Marker::MESH_RESOURCE;
car_mesh.action = visualization_msgs::Marker::ADD;
car_mesh.id = 0;
car_mesh.mesh_resource = "package://global_fusion/models/car.dae";
Eigen::Matrix3d rot;
rot << 0, 0, -1, 0, -1, 0, -1, 0, 0;
Eigen::Quaterniond Q;
Q = q_w_car * rot;
car_mesh.pose.position.x = t_w_car.x();
car_mesh.pose.position.y = t_w_car.y();
car_mesh.pose.position.z = t_w_car.z();
car_mesh.pose.orientation.w = Q.w();
car_mesh.pose.orientation.x = Q.x();
car_mesh.pose.orientation.y = Q.y();
car_mesh.pose.orientation.z = Q.z();
car_mesh.color.a = 1.0;
car_mesh.color.r = 1.0;
car_mesh.color.g = 0.0;
car_mesh.color.b = 0.0;
float major_scale = 2.0;
car_mesh.scale.x = major_scale;
car_mesh.scale.y = major_scale;
car_mesh.scale.z = major_scale;
markerArray_msg.markers.push_back(car_mesh);
pub_car.publish(markerArray_msg);
}
//GPS 消息订阅
//理解:GPS回调函数,简单,只是把GPS消息存储到了全局变量 gpsQueue 队列里面
void GPS_callback(const sensor_msgs::NavSatFixConstPtr &GPS_msg)
{
//printf("gps_callback! \n");
m_buf.lock();
gpsQueue.push(GPS_msg);
m_buf.unlock();
}
//订阅VIO信息
//(1) 获取 VIO位姿 localPoseMap[t] 和 世界坐标系下的globalPoseMap[t]
void vio_callback(const nav_msgs::Odometry::ConstPtr &pose_msg)
{
//printf("vio_callback! \n");
double t = pose_msg->header.stamp.toSec();
last_vio_t = t;
Eigen::Vector3d vio_t(pose_msg->pose.pose.position.x, pose_msg->pose.pose.position.y, pose_msg->pose.pose.position.z);
Eigen::Quaterniond vio_q;
vio_q.w() = pose_msg->pose.pose.orientation.w;
vio_q.x() = pose_msg->pose.pose.orientation.x;
vio_q.y() = pose_msg->pose.pose.orientation.y;
vio_q.z() = pose_msg->pose.pose.orientation.z;
globalEstimator.inputOdom(t, vio_t, vio_q);
m_buf.lock();
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 GPS with timestamp %f\n", GPS_msg->header.stamp.toSec());
double latitude = GPS_msg->latitude;
double longitude = GPS_msg->longitude;
double altitude = GPS_msg->altitude;
//int numSats = GPS_msg->status.service;
double pos_accuracy = GPS_msg->position_covariance[0];
if(pos_accuracy <= 0)
pos_accuracy = 1;
//printf("receive covariance %lf \n", pos_accuracy);
//if(GPS_msg->status.status > 8)
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;
}
m_buf.unlock();
Eigen::Vector3d global_t;
Eigen:: Quaterniond global_q;
globalEstimator.getGlobalOdom(global_t, global_q);
nav_msgs::Odometry odometry;
odometry.header = pose_msg->header;
odometry.header.frame_id = "world";
odometry.child_frame_id = "world";
odometry.pose.pose.position.x = global_t.x();
odometry.pose.pose.position.y = global_t.y();
odometry.pose.pose.position.z = global_t.z();
odometry.pose.pose.orientation.x = global_q.x();
odometry.pose.pose.orientation.y = global_q.y();
odometry.pose.pose.orientation.z = global_q.z();
odometry.pose.pose.orientation.w = global_q.w();
pub_global_odometry.publish(odometry);
pub_global_path.publish(*global_path);
publish_car_model(t, global_t, global_q);
/*******************
// write result to file
std::ofstream foutC(gpssavename, ios::app);
foutC.setf(ios::fixed, ios::floatfield);
foutC.precision(0);
foutC << pose_msg->header.stamp.toSec() * 1e9 << ",";
foutC.precision(5);
foutC << global_t.x() << ","
<< global_t.y() << ","
<< global_t.z() << ","
<< global_q.w() << ","
<< global_q.x() << ","
<< global_q.y() << ","
<< global_q.z() << endl;
foutC.close();
******************/
//###########################修改 #############################
// write result to file
std::string gpssavename="/home/dongdong/v2_Project/v3_SLAM/v5_VinsFusion/catkin/src/VINS-Fusion/outdata/vio_global.csv";
std::ofstream foutC(gpssavename, ios::app);
foutC.setf(ios::fixed, ios::floatfield);
foutC.precision(0);
foutC << pose_msg->header.stamp.toSec() << " ";
foutC.precision(5);
foutC << global_t.x() << " "
<< global_t.y() << " "
<< global_t.z() << " "
<< global_q.w() << " "
<< global_q.x() << " "
<< global_q.y() << " "
<< global_q.z() << endl;
foutC.close();
//###########################修改 #############################
}
int main(int argc, char **argv)
{
//初始化
ros::init(argc, argv, "globalEstimator");
ros::NodeHandle n("~");
//全局优化
global_path = &globalEstimator.global_path;
//订阅GPS信息
ros::Subscriber sub_GPS = n.subscribe("/gps", 100, GPS_callback);
//订阅VIO信息
ros::Subscriber sub_vio = n.subscribe("/vins_estimator/odometry", 100, vio_callback);
//发布信息, //这些发布的数据,rviz 订阅然后显示,看一下 rviz的配置文件就知道了!
//配置文件在config里面的 vins_rviz_config.rviz
pub_global_path = n.advertise<nav_msgs::Path>("global_path", 100);
pub_global_odometry = n.advertise<nav_msgs::Odometry>("global_odometry", 100);
pub_car = n.advertise<visualization_msgs::MarkerArray>("car_model", 1000);
ros::spin();
return 0;
}
全局优化节点保存数据
这里只能保存时间戳没有名字




globalOpt.cpp
/*******************************************************
* Copyright (C) 2019, Aerial Robotics Group, Hong Kong University of Science and Technology
*
* This file is part of VINS.
*
* Licensed under the GNU General Public License v3.0;
* you may not use this file except in compliance with the License.
*
* Author: Qin Tong (qintonguav@gmail.com)
*******************************************************/
#include "globalOpt.h"
#include "Factors.h"
#include <fstream>
GlobalOptimization::GlobalOptimization()
{
initGPS = false;
newGPS = false;
WGPS_T_WVIO = Eigen::Matrix4d::Identity();
threadOpt = std::thread(&GlobalOptimization::optimize, this);
}
GlobalOptimization::~GlobalOptimization()
{
threadOpt.detach();
}
void GlobalOptimization::GPS2XYZ(double latitude, double longitude, double altitude, double* xyz)
{
if(!initGPS)
{
geoConverter.Reset(latitude, longitude, altitude);
initGPS = true;
}
geoConverter.Forward(latitude, longitude, altitude, xyz[0], xyz[1], xyz[2]);
//printf("la: %f lo: %f al: %f\n", latitude, longitude, altitude);
//printf("gps x: %f y: %f z: %f\n", xyz[0], xyz[1], xyz[2]);
}
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;
geometry_msgs::PoseStamped pose_stamped;
pose_stamped.header.stamp = ros::Time(t);
pose_stamped.header.frame_id = "world";
pose_stamped.pose.position.x = lastP.x();
pose_stamped.pose.position.y = lastP.y();
pose_stamped.pose.position.z = lastP.z();
pose_stamped.pose.orientation.x = lastQ.x();
pose_stamped.pose.orientation.y = lastQ.y();
pose_stamped.pose.orientation.z = lastQ.z();
pose_stamped.pose.orientation.w = lastQ.w();
global_path.header = pose_stamped.header;
global_path.poses.push_back(pose_stamped);
mPoseMap.unlock();
}
void GlobalOptimization::getGlobalOdom(Eigen::Vector3d &odomP, Eigen::Quaterniond &odomQ)
{
odomP = lastP;
odomQ = lastQ;
}
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,latitude, longitude, altitude};
//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::optimize()
{
while(true)
{
if(newGPS)
{
newGPS = false;
printf("global optimization\n");
TicToc globalOptimizationTime;
ceres::Problem problem;
ceres::Solver::Options options;
options.linear_solver_type = ceres::SPARSE_NORMAL_CHOLESKY;
//options.minimizer_progress_to_stdout = true;
//options.max_solver_time_in_seconds = SOLVER_TIME * 3;
options.max_num_iterations = 5;
ceres::Solver::Summary summary;
ceres::LossFunction *loss_function;
loss_function = new ceres::HuberLoss(1.0);
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++)
{
t_array[i][0] = iter->second[0];
t_array[i][1] = iter->second[1];
t_array[i][2] = iter->second[2];
q_array[i][0] = iter->second[3];
q_array[i][1] = iter->second[4];
q_array[i][2] = iter->second[5];
q_array[i][3] = iter->second[6];
problem.AddParameterBlock(q_array[i], 4, local_parameterization);
problem.AddParameterBlock(t_array[i], 3);
}
map<double, vector<double>>::iterator iterVIO, iterVIONext, iterGPS;
int i = 0;
for (iterVIO = localPoseMap.begin(); iterVIO != localPoseMap.end(); iterVIO++, i++)
{
//vio factor
iterVIONext = iterVIO;
iterVIONext++;
if(iterVIONext != localPoseMap.end())
{
Eigen::Matrix4d wTi = Eigen::Matrix4d::Identity();
Eigen::Matrix4d wTj = Eigen::Matrix4d::Identity();
wTi.block<3, 3>(0, 0) = Eigen::Quaterniond(iterVIO->second[3], iterVIO->second[4],
iterVIO->second[5], iterVIO->second[6]).toRotationMatrix();
wTi.block<3, 1>(0, 3) = Eigen::Vector3d(iterVIO->second[0], iterVIO->second[1], iterVIO->second[2]);
wTj.block<3, 3>(0, 0) = Eigen::Quaterniond(iterVIONext->second[3], iterVIONext->second[4],
iterVIONext->second[5], iterVIONext->second[6]).toRotationMatrix();
wTj.block<3, 1>(0, 3) = Eigen::Vector3d(iterVIONext->second[0], iterVIONext->second[1], iterVIONext->second[2]);
Eigen::Matrix4d iTj = wTi.inverse() * wTj;
Eigen::Quaterniond iQj;
iQj = iTj.block<3, 3>(0, 0);
Eigen::Vector3d 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]);
/*
double **para = new double *[4];
para[0] = q_array[i];
para[1] = t_array[i];
para[3] = q_array[i+1];
para[4] = t_array[i+1];
double *tmp_r = new double[6];
double **jaco = new double *[4];
jaco[0] = new double[6 * 4];
jaco[1] = new double[6 * 3];
jaco[2] = new double[6 * 4];
jaco[3] = new double[6 * 3];
vio_function->Evaluate(para, tmp_r, jaco);
std::cout << Eigen::Map<Eigen::Matrix<double, 6, 1>>(tmp_r).transpose() << std::endl
<< std::endl;
std::cout << Eigen::Map<Eigen::Matrix<double, 6, 4, Eigen::RowMajor>>(jaco[0]) << std::endl
<< std::endl;
std::cout << Eigen::Map<Eigen::Matrix<double, 6, 3, Eigen::RowMajor>>(jaco[1]) << std::endl
<< std::endl;
std::cout << Eigen::Map<Eigen::Matrix<double, 6, 4, Eigen::RowMajor>>(jaco[2]) << std::endl
<< std::endl;
std::cout << Eigen::Map<Eigen::Matrix<double, 6, 3, Eigen::RowMajor>>(jaco[3]) << std::endl
<< std::endl;
*/
}
//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]);
//vector<double> tmp{xyz[0], xyz[1], xyz[2], posAccuracy,latitude, longitude, altitude};
// float latitude=iterGPS->second[4];
// float longitude=iterGPS->second[5];
// float altitude=iterGPS->second[6];
//printf("inverse weight %f \n", iterGPS->second[3]);
problem.AddResidualBlock(gps_function, loss_function, t_array[i]);
/*
double **para = new double *[1];
para[0] = t_array[i];
double *tmp_r = new double[3];
double **jaco = new double *[1];
jaco[0] = new double[3 * 3];
gps_function->Evaluate(para, tmp_r, jaco);
std::cout << Eigen::Map<Eigen::Matrix<double, 3, 1>>(tmp_r).transpose() << std::endl
<< std::endl;
std::cout << Eigen::Map<Eigen::Matrix<double, 3, 3, Eigen::RowMajor>>(jaco[0]) << std::endl
<< std::endl;
*/
}
}
//mPoseMap.unlock();
ceres::Solve(options, &problem, &summary);
//std::cout << summary.BriefReport() << "\n";
// update global pose
//mPoseMap.lock();
// save
iter = globalPoseMap.begin();
map<double, vector<double>> globalPoseMap_gps;
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;
WVIO_T_body.block<3, 3>(0, 0) = Eigen::Quaterniond(localPoseMap[t][3], localPoseMap[t][4],
localPoseMap[t][5], localPoseMap[t][6]).toRotationMatrix();
WVIO_T_body.block<3, 1>(0, 3) = Eigen::Vector3d(localPoseMap[t][0], localPoseMap[t][1], localPoseMap[t][2]);
WGPS_T_body.block<3, 3>(0, 0) = Eigen::Quaterniond(globalPose[3], globalPose[4],
globalPose[5], globalPose[6]).toRotationMatrix();
WGPS_T_body.block<3, 1>(0, 3) = Eigen::Vector3d(globalPose[0], globalPose[1], globalPose[2]);
WGPS_T_WVIO = WGPS_T_body * WVIO_T_body.inverse();
//vector<double> tmp{xyz[0], xyz[1], xyz[2], posAccuracy,latitude, longitude, altitude};
iterGPS = GPSPositionMap.find(t);
if (iterGPS != GPSPositionMap.end()){
//vector<double> globalPose_t{t_array[i][0], t_array[i][1], t_array[i][2]}; // 优化后的全局坐标xyz
//vector<double> globalPose_gps{iterGPS->second[0],iterGPS->second[1],iterGPS->second[2]}; //// 优化后的全局坐标xyz 优化前的坐标xyz
//vector<double> real_gps{iterGPS->second[4],iterGPS->second[5],iterGPS->second[6]}; //// 优化后的全局坐标xyz 优化前的坐标xyz
//vector<double> tmp{xyz[0], xyz[1], xyz[2], posAccuracy,latitude, longitude, altitude};
vector<double> globalPose_xyz_gps{t_array[i][0], t_array[i][1], t_array[i][2], iterGPS->second[0], iterGPS->second[1], iterGPS->second[2],iterGPS->second[4],iterGPS->second[5],iterGPS->second[6]};
globalPoseMap_gps.insert(pair<double, vector<double>>(t,globalPose_xyz_gps));
}
}
}
std::string gpssavename1="/home/dongdong/v2_Project/v3_SLAM/v5_VinsFusion/catkin/src/VINS-Fusion/outdata/vio_gps_global.csv";
std::ofstream fout_XYZGPS(gpssavename1, ios::app);
fout_XYZGPS.setf(ios::fixed, ios::floatfield);
fout_XYZGPS.precision(6);
map<double, vector<double>>::iterator iter_xyz_gps;
for (iter_xyz_gps = globalPoseMap_gps.begin(); iter_xyz_gps != globalPoseMap_gps.end(); iter_xyz_gps++)
{
double timesharp_=iter_xyz_gps->first;
vector<double> data_xyz_gps=iter_xyz_gps->second;
fout_XYZGPS << timesharp_ << " "
<< data_xyz_gps[0] << " "
<< data_xyz_gps[1] << " "
<< data_xyz_gps[2] << " "
<< data_xyz_gps[3] << " "
<< data_xyz_gps[4] << " "
<< data_xyz_gps[5] << " "
<< data_xyz_gps[6] << " "
<< data_xyz_gps[7] << " "
<< data_xyz_gps[8] << endl;
}
fout_XYZGPS.close();
updateGlobalPath();
//printf("global time %f \n", globalOptimizationTime.toc());
mPoseMap.unlock();
}
std::chrono::milliseconds dura(20);
std::this_thread::sleep_for(dura);
}
return;
}
void GlobalOptimization::updateGlobalPath()
{
global_path.poses.clear();
map<double, vector<double>>::iterator iter;
for (iter = globalPoseMap.begin(); iter != globalPoseMap.end(); iter++)
{
geometry_msgs::PoseStamped pose_stamped;
pose_stamped.header.stamp = ros::Time(iter->first);
pose_stamped.header.frame_id = "world";
pose_stamped.pose.position.x = iter->second[0];
pose_stamped.pose.position.y = iter->second[1];
pose_stamped.pose.position.z = iter->second[2];
pose_stamped.pose.orientation.w = iter->second[3];
pose_stamped.pose.orientation.x = iter->second[4];
pose_stamped.pose.orientation.y = iter->second[5];
pose_stamped.pose.orientation.z = iter->second[6];
global_path.poses.push_back(pose_stamped);
}
}
globalOpt.h
/*******************************************************
* Copyright (C) 2019, Aerial Robotics Group, Hong Kong University of Science and Technology
*
* This file is part of VINS.
*
* Licensed under the GNU General Public License v3.0;
* you may not use this file except in compliance with the License.
*
* Author: Qin Tong (qintonguav@gmail.com)
*******************************************************/
#pragma once
#include <vector>
#include <map>
#include <iostream>
#include <mutex>
#include <thread>
#include <eigen3/Eigen/Dense>
#include <eigen3/Eigen/Geometry>
#include <ceres/ceres.h>
#include <nav_msgs/Odometry.h>
#include <nav_msgs/Path.h>
#include "LocalCartesian.hpp"
#include "tic_toc.h"
using namespace std;
class GlobalOptimization
{
public:
GlobalOptimization();
~GlobalOptimization();
void inputGPS(double t, double latitude, double longitude, double altitude, double posAccuracy);
void inputOdom(double t, Eigen::Vector3d OdomP, Eigen::Quaterniond OdomQ);
void getGlobalOdom(Eigen::Vector3d &odomP, Eigen::Quaterniond &odomQ);
nav_msgs::Path global_path;
private:
void GPS2XYZ(double latitude, double longitude, double altitude, double* xyz);
void optimize();
void updateGlobalPath();
// format t, tx,ty,tz,qw,qx,qy,qz
map<double, vector<double>> localPoseMap;
map<double, vector<double>> globalPoseMap;
map<double, vector<double>> GPSPositionMap;
bool initGPS;
bool newGPS;
GeographicLib::LocalCartesian geoConverter;
std::mutex mPoseMap;
Eigen::Matrix4d WGPS_T_WVIO;
Eigen::Vector3d lastP;
Eigen::Quaterniond lastQ;
std::thread threadOpt;
};
浙公网安备 33010602011771号