• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
MKT-porter
博客园    首页    新随笔    联系   管理    订阅  订阅
vins-fusion(2)改造GNSS

 

 

导出数据

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", &timeshara_c, &lat_c, &lon_c, &alt_c) != EOF)
	////%lf之间应该有逗号,因为没有逗号只能读第一个数。用&是因为要把数存到对应数组元素的地址中去。\n是换行读取
	//while (fscanf(file, "%lf %lf %lf %lf", &timesharap_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;

};

  

 

posted on 2025-05-23 19:23  MKT-porter  阅读(47)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3