1. 程式人生 > >香港科技大學的VINS_MONO初試

香港科技大學的VINS_MONO初試

簡介

VINS-Mono 是香港科技大學開源的一個VIO,我簡單的測試了,發現效果不錯。做個簡單的筆記,詳細的內容等我畢設搞完再弄。

程式碼主要分為前端(feature tracker),後端(sliding window, loop closure),還加了初始化(visual-imu aligment)

Feature tracker

這部分程式碼在feature_tracker包下面,主要是接收影象topic,使用KLT光流演算法跟蹤特徵點,同時保持每一幀影象有最少的(100-300)個特徵點。

根據配置檔案中的freq,確定每隔多久的時候,把檢測到的特徵點打包成/feature_tracker/feature

topic 發出去,

要是沒有達到傳送的時間,這幅影象的feature就作為下一時刻的
KLT追蹤的特徵點,就是不是每一副影象都要處理的,那樣計算時間大了,而且資料感覺冗餘,幀與幀之間影象的差距不會那麼明顯。

這裡的freq配置檔案建議至少設定10,為了保證好的前端。

void img_callback(const sensor_msgs::ImageConstPtr &img_msg)
{
    for (int i = 0; i < NUM_OF_CAM; i++)
    {
        ROS_DEBUG("processing camera %d", i);
        if (i != 1 || !STEREO_TRACK)
        //呼叫FeatureTracker的readImage
            trackerData[i].readImage(ptr->image.rowRange(ROW * i, ROW * (i + 1)));
    }

    for (unsigned int i = 0;; i++)
    {
        bool completed = false;
        for (int j = 0; j < NUM_OF_CAM; j++)
            if (j != 1 || !STEREO_TRACK)
            //更新feature的ID
                completed |= trackerData[j].updateID(i);
        if (!completed)
            break;
    }
    
    //釋出特徵點topic
    if (round(1.0 * pub_count / (img_msg->header.stamp.toSec() - first_image_time)) <= FREQ)
    {
        sensor_msgs::PointCloudPtr feature_points(new sensor_msgs::PointCloud);
        //特徵點的id,影象的(u,v)座標
        sensor_msgs::ChannelFloat32 id_of_point;
        sensor_msgs::ChannelFloat32 u_of_point;
        sensor_msgs::ChannelFloat32 v_of_point;

        pub_img.publish(feature_points);

    }

     if (SHOW_TRACK)
     {
        //根據特徵點被追蹤的次數,顯示他的顏色,越紅表示這個特徵點看到的越久,一幅影象要是大部分特徵點是藍色,前端tracker效果很差了,估計要掛了
        double len = std::min(1.0, 1.0 * trackerData[i].track_cnt[j] / WINDOW_SIZE);
        cv::circle(tmp_img, trackerData[i].cur_pts[j], 2, cv::Scalar(255 * (1 - len), 0, 255 * len), 2);
     }


}
void FeatureTracker::readImage(const cv::Mat &_img)
{
    //直方圖均勻化
    //if image is too dark or light, trun on equalize to find enough features
    if (EQUALIZE)
    {
        cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE(3.0, cv::Size(8, 8));
        TicToc t_c;
        clahe->apply(_img, img);
        ROS_DEBUG("CLAHE costs: %fms", t_c.toc());
    }

    if (cur_pts.size() > 0)
    {
        TicToc t_o;
        vector<uchar> status;
        vector<float> err;
        //根據上一時刻的cur_img,cur_pts,尋找當前時刻的forw_pts,
        cv::calcOpticalFlowPyrLK(cur_img, forw_img, cur_pts, forw_pts, status, err, cv::Size(21, 21), 3);
    }

    if (img_cnt == 0)
    {
        //根據fundamentalMatrix中的ransac去除一些outlier
        rejectWithF();
        //跟新特徵點track的次數
        for (auto &n : track_cnt)
            n++;
        //為下面的goodFeaturesToTrack保證相鄰的特徵點之間要相隔30個畫素,設定mask image
        setMask();

        int n_max_cnt = MAX_CNT - static_cast<int>(forw_pts.size());
        if (n_max_cnt > 0)
        {
            //保證每個image有足夠的特徵點,不夠就新提取
            cv::goodFeaturesToTrack(forw_img, n_pts, MAX_CNT - forw_pts.size(), 0.1, MIN_DIST, mask);
        }


    }
}

Slide Window

主要是對imu的資料進行預積分,vision重投影誤差的構造,loop-closure的檢測,slide-window的維護 ,marginzation prior的維護,東西比較多。

loop-closure的檢測是使用視覺詞帶的,這裡的特徵不是feature-tracker的,那樣子太少了。是通過訂閱IMAGE_TOPIC,傳遞到閉環檢測部分,重新檢測的,這個我還沒有認真看(做了很多限制,為了搜尋的速度,詞帶不會很大,做了很多限制,從論文上看優化的方程只是加了幾個vision重投影的限制,速度不會太慢)。

是隻有4個自由度的優化,roll, pitch由於重力對齊的原因是可觀測的,就不去優化。

最主要的還是下面這個最小二乘法方程構建,主要的程式碼我列出來。

void Estimator::processIMU(double dt, const Vector3d &linear_acceleration, const Vector3d &angular_velocity)
{

    if (frame_count != 0)
    {
        pre_integrations[frame_count]->push_back(dt, linear_acceleration, angular_velocity);
        //呼叫imu的預積分,propagation ,計算對應的雅可比矩陣
        //if(solver_flag != NON_LINEAR)
            tmp_pre_integration->push_back(dt, linear_acceleration, angular_velocity);

        dt_buf[frame_count].push_back(dt);
        linear_acceleration_buf[frame_count].push_back(linear_acceleration);
        angular_velocity_buf[frame_count].push_back(angular_velocity);

        //提供imu計算的當前位置,速度,作為優化的初值
        int j = frame_count;         
        Vector3d un_acc_0 = Rs[j] * (acc_0 - Bas[j]) - g;
        Vector3d un_gyr = 0.5 * (gyr_0 + angular_velocity) - Bgs[j];
        Rs[j] *= Utility::deltaQ(un_gyr * dt).toRotationMatrix();
        Vector3d un_acc_1 = Rs[j] * (linear_acceleration - Bas[j]) - g;
        Vector3d un_acc = 0.5 * (un_acc_0 + un_acc_1);
        Ps[j] += dt * Vs[j] + 0.5 * dt * dt * un_acc;
        Vs[j] += dt * un_acc;
    }

}

void Estimator::processImage(const map<int, vector<pair<int, Vector3d>>> &image, const std_msgs::Header &header)
{
    //根據視差判斷是不是關鍵幀,
    if (f_manager.addFeatureCheckParallax(frame_count, image))
        marginalization_flag = MARGIN_OLD;
    else
        marginalization_flag = MARGIN_SECOND_NEW;

    ImageFrame imageframe(image, header.stamp.toSec());
    imageframe.pre_integration = tmp_pre_integration;
    all_image_frame.insert(make_pair(header.stamp.toSec(), imageframe));
    tmp_pre_integration = new IntegrationBase{acc_0, gyr_0, Bas[frame_count], Bgs[frame_count]};

//引數要是設定imu-camera的外引數未知,也可以幫你求解的
    if(ESTIMATE_EXTRINSIC == 2)
    {
    }

//初始化的流程
    if (solver_flag == INITIAL)
    {
        if (frame_count == WINDOW_SIZE)
        {
            bool result = false;
            if( ESTIMATE_EXTRINSIC != 2 && (header.stamp.toSec() - initial_timestamp) > 0.1)
            {
            //構造sfm,優化imu偏差,加速度g,尺度的確定
               result = initialStructure();
               initial_timestamp = header.stamp.toSec();
            }
            if(result)
            {
                solver_flag = NON_LINEAR;
                solveOdometry();
                slideWindow();
                f_manager.removeFailures();
                ROS_INFO("Initialization finish!");
                last_R = Rs[WINDOW_SIZE];
                last_P = Ps[WINDOW_SIZE];
                last_R0 = Rs[0];
                last_P0 = Ps[0];
                
            }
            else
                slideWindow();
        }
    //先湊夠window-size的數量的Frame
        else
            frame_count++;
    }
    else
    {
       
        solveOdometry();

//失敗的檢測
        if (failureDetection())
        {
            clearState();
            setParameter();
            return;
        }

        slideWindow();
        f_manager.removeFailures();
        // prepare output of VINS
        key_poses.clear();
        for (int i = 0; i <= WINDOW_SIZE; i++)
            key_poses.push_back(Ps[i]);

        last_R = Rs[WINDOW_SIZE];
        last_P = Ps[WINDOW_SIZE];
        last_R0 = Rs[0];
        last_P0 = Ps[0];
    }

}
void Estimator::slideWindow()
{
//WINDOW_SIZE中的引數的之間調整,同時FeatureManager進行管理feature,有些點要刪除掉,有些點的深度要在下一frame表示(start frame已經刪除了)


    Headers[frame_count - 1] = Headers[frame_count];
    Ps[frame_count - 1] = Ps[frame_count];
    Vs[frame_count - 1] = Vs[frame_count];
    Rs[frame_count - 1] = Rs[frame_count];
    Bas[frame_count - 1] = Bas[frame_count];
    Bgs[frame_count - 1] = Bgs[frame_count];

    delete pre_integrations[WINDOW_SIZE];
    pre_integrations[WINDOW_SIZE] = new IntegrationBase{acc_0, gyr_0, Bas[WINDOW_SIZE], Bgs[WINDOW_SIZE]};
//清楚資料,給下一副影象提供空間
    dt_buf[WINDOW_SIZE].clear();
    linear_acceleration_buf[WINDOW_SIZE].clear();
    angular_velocity_buf[WINDOW_SIZE].clear();    
}

void Estimator::solveOdometry()
{
    if (frame_count < WINDOW_SIZE)
        return;
    if (solver_flag == NON_LINEAR)
    {
        //三角化點
        f_manager.triangulate(Ps, tic, ric);
        ROS_DEBUG("triangulation costs %f", t_tri.toc());
        optimization();
    }
}
void Estimator::optimization()
{
    //新增frame的state,(p,v,q,b_a,b_g),就是ceres要優化的引數
    for (int i = 0; i < WINDOW_SIZE + 1; i++)
    {
        ceres::LocalParameterization *local_parameterization = new PoseLocalParameterization();
        problem.AddParameterBlock(para_Pose[i], SIZE_POSE, local_parameterization);
        problem.AddParameterBlock(para_SpeedBias[i], SIZE_SPEEDBIAS);
    }
    //新增camera-imu的外引數
    for (int i = 0; i < NUM_OF_CAM; i++)
    {
        ceres::LocalParameterization *local_parameterization = new PoseLocalParameterization();
        problem.AddParameterBlock(para_Ex_Pose[i], SIZE_POSE, local_parameterization);
    }

    //為ceres引數賦予初值
    vector2double();

    //新增margination residual, 先驗知識
    //他的Evaluate函式看好,固定了線性化的點,First Jacobian Estimate
    if (last_marginalization_info)
    {
        // construct new marginlization_factor
        MarginalizationFactor *marginalization_factor = new MarginalizationFactor(last_marginalization_info);
        problem.AddResidualBlock(marginalization_factor, NULL,
                                 last_marginalization_parameter_blocks);
    } 

    //新增imu的residual
    for (int i = 0; i < WINDOW_SIZE; i++)
    {
        int j = i + 1;
        if (pre_integrations[j]->sum_dt > 10.0)
            continue;
        IMUFactor* imu_factor = new IMUFactor(pre_integrations[j]);
        problem.AddResidualBlock(imu_factor, NULL, para_Pose[i], para_SpeedBias[i], para_Pose[j], para_SpeedBias[j]);
    }

    //新增vision的residual
    for (auto &it_per_id : f_manager.feature)
    {
        for (auto &it_per_frame : it_per_id.feature_per_frame)
        {
            imu_j++;
            if (imu_i == imu_j)
            {
                continue;
            }
            Vector3d pts_j = it_per_frame.point;
            ProjectionFactor *f = new ProjectionFactor(pts_i, pts_j);
            problem.AddResidualBlock(f, loss_function, para_Pose[imu_i], para_Pose[imu_j], para_Ex_Pose[0], para_Feature[feature_index]);
            f_m_cnt++;
        }
    }

    //新增閉環的引數和residual
    if(LOOP_CLOSURE)
    {
        ceres::LocalParameterization *local_parameterization = new PoseLocalParameterization();
        problem.AddParameterBlock(front_pose.loop_pose, SIZE_POSE, local_parameterization);
        
        if(front_pose.features_ids[retrive_feature_index] == it_per_id.feature_id)
        {
            Vector3d pts_j = Vector3d(front_pose.measurements[retrive_feature_index].x, front_pose.measurements[retrive_feature_index].y, 1.0);
            Vector3d pts_i = it_per_id.feature_per_frame[0].point;
            
            ProjectionFactor *f = new ProjectionFactor(pts_i, pts_j);
            problem.AddResidualBlock(f, loss_function, para_Pose[start], front_pose.loop_pose, para_Ex_Pose[0], para_Feature[feature_index]);
        
            retrive_feature_index++;
            loop_factor_cnt++;
        }
    }


    //設定了優化的最長時間,保證實時性
    if (marginalization_flag == MARGIN_OLD)
        options.max_solver_time_in_seconds = SOLVER_TIME * 4.0 / 5.0;
    else
        options.max_solver_time_in_seconds = SOLVER_TIME;

    // 求解
    ceres::Solve(options, &problem, &summary);

// http://blog.csdn.net/heyijia0327/article/details/53707261#comments
// http://blog.csdn.net/heyijia0327/article/details/52822104
    if (marginalization_flag == MARGIN_OLD)
    {
        //如果當前幀是關鍵幀的,把oldest的frame所有的資訊margination,作為下一時刻的先驗知識,參考上面的兩個網址,大神的解釋很明白

    }
    else{
        //如果當前幀不是關鍵幀的,把second newest的frame所有的視覺資訊丟棄掉,imu資訊不丟棄,記住不是做margination,是為了保持矩陣的稀疏性
    }
    
}

後續

imu的引數很重要,還有就是硬體同步,global shutter的攝像頭很重要。我要是動作快的話,效果就不行了。但人家的視訊感覺效果很不錯。

這個還要繼續弄硬體和程式碼原理,程式碼中最小二乘法優化中的FOCAL_LENGTH感覺要根據自己的攝像頭設定,還沒有具體看,視覺資訊矩陣的設定還沒有看。

工程中具體的情況還是要自己解決,

相關推薦

香港科技大學VINS_MONO初試

簡介 VINS-Mono 是香港科技大學開源的一個VIO,我簡單的測試了,發現效果不錯。做個簡單的筆記,詳細的內容等我畢設搞完再弄。 程式碼主要分為前端(feature tracker),後端(sliding window, loop closure),還加了初始化(visual-imu aligment)

香港科技大學之旅

上班 nbsp 人生 .com 櫃子 缺點 style 問題 app 簡介 在港科大兩周的airship課程已經完結了,從去年看到同學老曹在港科大發的朋友圈,就覺得這門課程應該挺有趣的。於是便報了名,學完了網上的課程,通過了篩選,來到了港科大,期間差點因為簽註延誤,無法來

CCAI 2017 | 香港科技大學計算機系主任楊強:論深度學習的遷移模型

作者 | 賈維娣 7月23日,由中國人工智慧學會、阿里巴巴集團 & 螞蟻金服主辦,CSDN、中國科學院自動化研究所承辦的第三屆中國人工智慧大會(CCAI 2017)在杭州國際會議中心盛大開幕。大會第一天上午,香港科技大學計算機與工程系主任、AAAI Fellow楊強教授發表了《深度學習的遷移

劉慶強大傻逼,杭州電子科技大學 大傻逼

大禮堂 感想 就是 raft acc 真的 大學生 width badge 劉慶強大傻逼,杭州電子科技大學 大傻逼 作者:欲加以乘鏈接:https://www.zhihu.com/question/265351267/answer/292925014來源:知乎著作權歸作

華中科技大學數學專業考研試題參考解答

blog 3年 需要 解答 pos 1年 如果 gpo class 華中科技大學2000年數學分析考研試題參考解答 華中科技大學2001年數學分析考研試題參考解答 華中科技大學2002年數學分析考研試題參考解答 華中科技大學2003年數學分析考研試題參考解答 華

莫言香港公開大學演講

get embed .com div idt gpo ebo body src http://v.youku.com/v_show/id_XNDYwODc5NTYw==.html 莫言香港公開大學演講

畢業真實的版本_↑[昆士蘭科技大學畢業證書]_QUT原件一模一樣證書

was 最新 log 而且 學生 埃默裏大學 clas bus 行業 AI【昆士蘭科技大學畢業證書】【微/Q:865121257——weChat:CC6669834】聯系人Jessie查看點擊網頁快照查看]【學歷認證、文憑、學位證、成績單等】 國外(海外)澳洲英國 加拿大

澳洲悉尼科技大學UTS文憑文憑制作修改成績,GPA修改微信:13166038657

密碼破解 AC 十年 渠道 manage 取數 服務項目 大學 tom 澳洲悉尼科技大學UTS文憑文憑制作修改成績,GPA修改微信:13166038657 【谷歌推薦】劍客滲透聯盟打造最頂尖最專業的黑客滲透技術團隊,專註國內外主流安全系統滲透技術多年來一直潛心研究互聯網安全

第十四屆華中科技大學程序設計競賽 K Walking in the Forest【二分答案/最小化最大值】

ica ride int lib namespace coder 浪費 first efi 鏈接:https://www.nowcoder.com/acm/contest/106/K 來源:牛客網 題目描述 It’s universally acknowledged t

第十四屆華中科技大學程序設計競賽 J Various Tree【數值型一維BFS/最小步數】

hust there ini amp rep targe ati 數值 set 鏈接:https://www.nowcoder.com/acm/contest/106/J 來源:牛客網 題目描述 It’s universally acknowledged that th

5月3日,坐標華中科技大學,跟E課網金牌講師面對面,Are you ready?

IC行業 集成電路 你是否想充分了解集成電路行業?是否想了解集成電路行業的崗位分布?臨近畢業要做哪些準備能更好地完成學校到職場的切換?臨近畢業是否有太多的疑問想向老司機咨詢?......答案在這裏?當然不是,約好時間和地點,做好小板凳,金牌講師現場一一講解,詳情點擊鏈接:https://mp.weix

2018年北京信息科技大學第十屆程序設計競賽暨ACM選拔賽-B-precise math function

AI 計算 ac代碼 AS esc lag .com load des 題目描述 喜愛ACM的PBY同學遇到了一道數學難題,已知底數n,請你幫他準確的計算出結果a = nπ(n的π次方),結果保留小數點後x位。 輸入描述: 第一行是一個整數t,表示測試實例的

第十四屆華中科技大學程序設計競賽決賽同步賽

祖先 思維 simple HR .cn 題意 競賽 並查集 正整數 第十四屆華中科技大學程序設計競賽決賽同步賽 A Beauty of Trees 思維,帶權並查集 題意: 長度為 n 的序列,沒告訴你具體數是多少。只給出 m 個查詢,表示區間 [l,r] 的異或和為 k

華中科技大學 計算機組成原理 上機實驗1 2018

image 可能 ive debug 區號 分析 pan open 實驗目的 實驗目的 GB2312 區位碼 字模碼 奇偶校驗校 驗位 檢錯 海明碼編解碼電路基本原理 流水數據傳輸機制,流水暫停原理 實驗環境 (以下文字僅

牛客網 中南林業科技大學第十一屆程序設計大賽J題 二分+線段樹

main build query 。。 eof its include pan ID https://www.nowcoder.com/acm/contest/124#question 題意 找第一個不小於K的數的下標,然後對它前一個數加一 解析 我們可以維護一個最大

關於電子科技大學內共享單車使用的調查報告

** 關於電子科技大學內共享單車使用的調查報告 ** 時間:十月二十六號 地點:電子科技大學 調研人員:施啟銳,薛倍騁,陶嘉禕,劉詩源,劉宇傑。 本次有效的填寫人次為72人 男女分佈為 雖然調查人數不多,但是也可以明顯的看出男生使用共享單車比女生更頻繁。 (還有一個原因

電子科技大學生物資訊學 重點

一: 簡答:研究內容: n  資料管理層面上:開發、設計一系列相關的工具,能夠方便有效的獲取、管理以及使用各種型別的資料和資訊。 n  演算法開發層面上:開發新的演算法及統計學的方法來揭示大規模資料之間的聯絡。 n  研究物件層面上:分析和解釋各種型別的生物學資料,包括核

世界一流大學和一流學科(雙一流建設)——西安電子科技大學

部分轉自:https://www.dxsbb.com/news/43529.html   1、雙一流大學簡介 雙一流,即世界一流大學和世界一流學科,是繼985工程(39所)、211工程(112所+4所學校有兩個校區=116所)之後又一國家戰略,其中世界一流大學42所,名單由

南方科技大學環境學院夏雨教授博士後一名(環境微生物方向)

南方科技大學環境學院夏雨教授誠聘博士後一名(環境微生物方向) 團隊介紹 夏雨,香港大學博士,南方科技大學環境科學與工程學院助理教授。 研究方向集中於:利用新一代測序技術與生物資訊學大資料分析相結合的手段研究環境微生物群落組成和協同作用關係對(1)致病菌的環境分佈以及抗生

【杭州電子科技大學2018新生編程大賽題解】

大學 vector using tor space 新車 algo 最小 科技 01: 1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include&l