VINS - Fusion GPS/VIO 融合 二、数据融合

https://zhuanlan.zhihu.com/p/75492883

 

一、简介

源代码:VINS - Fusion

数据集:KITTI 数据

程序入口:globalOptNode.cpp

 

二、程序解读

2.1 主函数

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;
}

理解:

代码很简单,订阅 topic(/gps)在GPS_callback回调函数中接收并处理gps数据,订阅topic(/vins_estimator/odometry)

在vio_callback回调函数中接收并处理vio的定位数据,并且生成了三个发布器,用于将结果展示在rviz上。

 

2.2 GPS 消息订阅

ros::Subscriber sub_GPS  =  n.subscribe("/gps", 100, GPS_callback)

void GPS_callback(const sensor_msgs::NavSatFixConstPtr &GPS_msg)
{
    m_buf.lock();
    gpsQueue.push(GPS_msg);
    m_buf.unlock();
}

理解:GPS回调函数,简单,只是把GPS消息存储到了全局变量 gpsQueue 队列里面

 

 

2.3 订阅VIO信息

ros::Subscriber sub_vio = n.subscribe("/vins_estimator/odometry", 100, vio_callback);

(1) 获取 VIO位姿 localPoseMap[t] 和 世界坐标系下的globalPoseMap[t]

void vio_callback(const nav_msgs::Odometry::ConstPtr &pose_msg)
{
    double t = pose_msg->header.stamp.toSec();
    last_vio_t = t;
    
    // 获取VIO输出的位置(三维向量),姿态(四元数)
    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;
    
    //位姿传入global Estimator中
    globalEstimator.inputOdom(t, vio_t, vio_q);
    m_buf.lock();

globalEstimator.inputOdom(t, vio_t, vio_q)  程序如下:

void GlobalOptimization::inputOdom(double t, Eigen::Vector3d OdomP, Eigen::Quaterniond OdomQ)
{
	mPoseMap.lock();
     // 把vio直接输出的位姿存入 localPoseMap 中
    vector<double> localPose{OdomP.x(), OdomP.y(), OdomP.z(), 
    		             OdomQ.w(), OdomQ.x(), OdomQ.y(), OdomQ.z()};
    localPoseMap[t] = localPose;
    Eigen::Quaterniond globalQ;
    
    // 把VIO转换到GPS坐标系下,准确的说是转换到以第一帧GPS为原点的坐标系下
    // 转换之后的位姿插入到globalPoseMap 中
    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                          
    globalPoseMap[t] = globalPose;
    lastP = globalP;//更新
    lastQ = globalQ;
    
    //把最新的全局姿态插入轨迹当中(第一个VIO数据当作第一个全局位姿)
    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();
}

理解:

localPoseMap[t] : VIO 的位姿

globalPoseMap[t] :VIO 的位姿 经过 坐标变换 转到 世界坐标系下的 位姿,也是GPS和VIO融合后的位姿!

这个函数把vio的结果存储在 localPoseMap 中,然后使用外参  WGPS_T_WVIO 把VIO的结果

### VINS-Fusion 视觉惯性融合技术原理及应用 #### 技术原理 VINS-Fusion 是一种基于优化的多传感器融合解决方案,主要用于视觉惯性里程计(VIO)系统。其核心思想是通过融合来自相机和惯性测量单元(IMU)的数据,实现对设备位姿的高精度估计。系统首先进行测量预处理,包括特征提取与跟踪,以及IMU测量的预积分。接着通过初始化过程获取必要的初始值,如位姿、速度、重力向量、陀螺仪偏置等,为后续的非线性优化提供支持。 在VIO模块中,预积分的IMU测量与特征观测紧密融合,以提高估计的精度和鲁棒性。此外,重定位模块帮助系统在丢失跟踪后重新找回位置,而位姿图优化模块则负责全局优化,减少漂移[^3]。 #### 数据融合 VINS-Fusion 支持多种传感器数据的融合,包括但不限于GPS。通过ROS订阅器获取VIO输出的位置和姿态信息,并将其输入到全局估计器中,实现与GPS数据的松耦合融合。这种方法允许系统在不同环境下保持较高的定位精度[^5]。 #### 应用 VINS-Fusion 在机器人导航、自动驾驶汽车、无人机等领域有着广泛的应用前景。它能够提供比单一传感器更可靠、更精确的位置估计,特别是在GNSS信号不可用或受限的环境中。例如,在室内导航、地下勘探、森林穿越等场景中,VINS-Fusion 可以作为主要的定位手段。 #### 代码示例 以下是一个简化的VIO回调函数示例,展示了如何从ROS消息中提取VIO数据并输入到全局估计器中: ```cpp void vio_callback(const nav_msgs::Odometry::ConstPtr &pose_msg) { double t = pose_msg->header.stamp.toSec(); last_vio_t = t; // 获取VIO输出的位置(三维向量),姿态(四元数) 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; // 位姿传入global Estimator中 globalEstimator.inputOdom(t, vio_t, vio_q); m_buf.lock(); // 其他操作... } ```
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

他人是一面镜子,保持谦虚的态度

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值