<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何將每個框架插入到SLAM框架中

新機器視覺 ? 來源:古月居 ? 2024-04-30 12:55 ? 次閱讀

0. 簡介

LinK3D、CSF、BALM這幾個都是非常方便去插入到激光SLAM框架的。這里我們會分別從多個角度來介紹如何將每個框架插入到SLAM框架中

1. LinK3D:三維LiDAR點云的

線性關鍵點表示

LinK3D的核心思想和基于我們的LinK3D的兩個LiDAR掃描的匹配結果。綠色線是有效匹配。當前關鍵點(黑色,CK)的描述符用其相鄰關鍵點來表示。描述符的每個維度對應于扇區區域。第一維度對應于當前關鍵點的最近關鍵點所在的扇區區域(藍色和紅色、CK的最近關鍵點),并且其他維度對應于以逆時針順序布置的區域。如果在扇區區域中存在關鍵點,則搜索扇區區域中最近的關鍵點(紫色和橙色,扇區中CK的最近關鍵點)并將其用于表示描述符的對應維度。

a735674c-063c-11ef-a297-92fbcf53809c.png

2. Link3D數據植入

這里的Link3D數據植入其實在外圍調用就這些內容,當中AggregationKeypoints_LinK3D存儲的是存當前點云中的聚類后的關鍵點。而pCurrentFrame_LinK3D對應的則是點云幀。該函數中利用LinK3D仿函數執行了提取邊緣點,聚類,計算描述子的操作。其實主要實現的都是LinK3D提取器。

    //在這里植入LinK3D,把接收到的點云數據用LinK3D提取邊緣點和描述子,發布關鍵點數據,打印輸出描述子
    //LinK3D提取器
    BoW3D::LinK3D_Extractor* pLinK3dExtractor(new BoW3D::LinK3D_Extractor(nScans, scanPeriod_LinK3D, minimumRange, distanceTh, matchTh)); 
    //創建點云幀,該函數中利用LinK3D仿函數執行了提取邊緣點,聚類,計算描述子的操作
    Frame* pCurrentFrame_LinK3D(new Frame(pLinK3dExtractor, plaserCloudIn_LinK3D));
    //此時pCurrentFrame_LinK3D這個類指針中包含了邊緣點,聚類,描述子的信息
//測試 輸出關鍵點數量和第一個關鍵點信息 正常輸出 
// cout << "------------------------" << endl << "關鍵點數量:" << pCurrentFrame_LinK3D->mvAggregationKeypoints.size();
// cout << "第一個關鍵點信息x坐標" << pCurrentFrame_LinK3D->mvAggregationKeypoints[0].x;
    //存當前點云中的聚類后的關鍵點
    AggregationKeypoints_LinK3D->points.insert(AggregationKeypoints_LinK3D->points.end(), pCurrentFrame_LinK3D->mvAggregationKeypoints.begin(), pCurrentFrame_LinK3D->mvAggregationKeypoints.end());
//測試 輸出點云中信息 也能正常輸出
// cout << "------------------------" << endl << "關鍵點數量:" << AggregationKeypoints_LinK3D->points.size();
// cout << "第一個關鍵點信息x坐標" << AggregationKeypoints_LinK3D->points[0].x;
    // 2.對描述子進行匹配 3.使用匹配對進行幀間icp配準 pPreviousFrame是上一個link3d Frame幀 pCurrentFrame_LinK3D是當前link3d Frame幀
    // 獲取上一幀和當前幀之間的匹配索引
     vector> vMatchedIndex; 
    pLinK3dExtractor->match(pCurrentFrame_LinK3D->mvAggregationKeypoints, pPreviousFrame->mvAggregationKeypoints, pCurrentFrame_LinK3D->mDescriptors, pPreviousFrame->mDescriptors, vMatchedIndex);
    //仿照BoW3D函數寫一個幀間ICP匹配函數求出R,t
    int returnValue = 0;
    // 進行幀間ICP匹配 求當前幀到上一幀的位姿變換
    // 這里求的R t是當前幀點云到上一幀點云的位姿變換
    returnValue = pose_estimation_3d3d(pCurrentFrame_LinK3D, pPreviousFrame, vMatchedIndex, RelativeR, Relativet, pLinK3dExtractor);
    //至此獲得了當前幀點云到上一幀點云的位姿變換


    //當前幀Frame用完以后,賦值給上一幀Frame,賦值前先把要丟掉的幀內存釋放
    //這里Frame里有成員指針,析構函數里delete成員指針
    delete pPreviousFrame;
    pPreviousFrame = pCurrentFrame_LinK3D;
    //LinK3D 植入結束

點云幀配置如下,其實可以看到這里面沒有太多的內容,主要還是調用Link3D中的void LinK3D_Extractor::Ptr pLaserCloudIn, vector &keyPoints, cv::Mat &descriptors, ScanEdgePoints &validCluster)函數。并獲取關鍵點、描述子還有聚類信息。具體的實現與具體論文保持一致,可以看Github內容

  //靜態(全局?)變量要在這里初始化
  long unsigned int Frame::nNextId = 0;


  Frame::Frame(LinK3D_Extractor* pLink3dExtractor, pcl::PointCloud::Ptr pLaserCloudIn):mpLink3dExtractor(pLink3dExtractor)
  {
    mnId = nNextId++; 


    (*mpLink3dExtractor)(pLaserCloudIn, mvAggregationKeypoints, mDescriptors, mClusterEdgeKeypoints);
  }

2. CSF“布料”濾波算法

然后下面就是CSF的處理,這里其實可以將內容加在BALM當中,Github。因為CSF其實作用是區分地面點的作用

a75834b6-063c-11ef-a297-92fbcf53809c.png

 // 
 CSF csf;
 csf.params.iterations = 600;
 csf.params.time_step = 0.95;
 csf.params.cloth_resolution = 3;
 csf.params.bSloopSmooth = false;


 csf.setPointCloud(*laserCloudSurfLast);
 // pcl::savePCDFileBinary(map_save_directory, *SurfFrame);


 std::vector groundIndexes, offGroundIndexes;
 // 輸出的是vector類型的地面點和非地面點索引
 pcl::PointCloud::Ptr groundFrame(new pcl::PointCloud);
 pcl::PointCloud::Ptr offGroundFrame(new pcl::PointCloud);
 csf.do_filtering(groundIndexes, offGroundIndexes);
 pcl::copyPointCloud(*laserCloudSurfLast, groundIndexes, *groundFrame);
 pcl::copyPointCloud(*laserCloudSurfLast, offGroundIndexes, *offGroundFrame);

實際用一句話:把點云翻過來,罩上一塊不同材質的布料,就可以得到地面了。參考實際物理的布,布料上的點之間存在不同的作用力,詳細可以參考這篇文章:https://www.guyuehome.com/40977

3. BALM

對于BALM其實主要分為三塊,balm_front、scan2map、balm_back這三個流程。我們一開始使用的是ALOAM的前端來提取激光里程計信息,然后scan2map中加入CSF來進一步區分地面點。最后分成三類傳入到BA約束當中https://blog.csdn.net/lovely_yoshino/article/details/133940976。

a7677ad4-063c-11ef-a297-92fbcf53809c.png

while(n.ok())
  {
    ros::spinOnce();
    if(corn_buf.empty() || ground_buf.empty() || odom_buf.empty() || offground_buf.empty())
    {
      continue;
    }


    mBuf.lock();
    uint64_t time_corn = corn_buf.front()->header.stamp.toNSec();
    uint64_t time_ground = ground_buf.front()->header.stamp.toNSec();
    uint64_t time_odom = odom_buf.front()->header.stamp.toNSec();
    uint64_t time_offground = offground_buf.front()->header.stamp.toNSec();
    if(time_odom != time_corn)
    {
      time_odom < time_corn ? odom_buf.pop() : corn_buf.pop();
 ? ? ? ? ? ?mBuf.unlock();
 ? ? ? ? ? ?continue;
 ? ? ? ?}


 ? ? ? ?if(time_odom != time_ground)
 ? ? ? ?{
 ? ? ? ? ? ?time_odom < time_ground ? odom_buf.pop() : ground_buf.pop();
 ? ? ? ? ? ?mBuf.unlock();
 ? ? ? ? ? ?continue;
 ? ? ? ?}


 ? ? ? ?if(time_odom != time_offground)
 ? ? ? ?{
 ? ? ? ? ? ?time_odom < time_ground ? odom_buf.pop() : ground_buf.pop();
 ? ? ? ? ? ?mBuf.unlock();
 ? ? ? ? ? ?continue;
 ? ? ? ?}


 ? ? ? ?ros::Time ct(ground_buf.front()->header.stamp);
    pcl::PointCloud::Ptr pl_ground_temp(new pcl::PointCloud);
    pcl::PointCloud::Ptr pl_edge_temp(new pcl::PointCloud);
    pcl::PointCloud::Ptr pl_offground_temp(new pcl::PointCloud);


    rosmsg2ptype(*ground_buf.front(), *pl_ground);
    rosmsg2ptype(*corn_buf.front(), *pl_corn);
    rosmsg2ptype(*offground_buf.front(), *pl_offground);


    //pcl::savePCDFileBinary("/home/wb/FALOAMBA_WS/wb/Map/map.pcd", *pl_ground);


    //pl_ground還有用,所以這里復制出一個新點云
    *pl_ground_temp = *pl_ground;
    *pl_edge_temp = *pl_corn;
    *pl_offground_temp = *pl_offground;
    corn_buf.pop(); ground_buf.pop(); offground_buf.pop();


    q_odom.w() = odom_buf.front()->pose.pose.orientation.w;
    q_odom.x() = odom_buf.front()->pose.pose.orientation.x;
    q_odom.y() = odom_buf.front()->pose.pose.orientation.y;
    q_odom.z() = odom_buf.front()->pose.pose.orientation.z;
    t_odom.x() = odom_buf.front()->pose.pose.position.x;
    t_odom.y() = odom_buf.front()->pose.pose.position.y;
    t_odom.z() = odom_buf.front()->pose.pose.position.z;
    odom_buf.pop();
    mBuf.unlock();


    // T_curr2last = T_curr2w * T_last2wˉ1
    Eigen::Vector3d delta_t(q_last.matrix().transpose()*(t_odom-t_last));
    Eigen::Quaterniond delta_q(q_last.matrix().transpose() * q_odom.matrix());
    q_last = q_odom;
    t_last = t_odom;


    // T_curr2last * I
    t_gather_pose = t_gather_pose + q_gather_pose * delta_t;
    q_gather_pose = q_gather_pose * delta_q;
    if(jump_flag < skip_num)
 ? ? ? ?{
 ? ? ? ? ? ?jump_flag++;
 ? ? ? ? ? ?continue;
 ? ? ? ?}
 ? ? ? ?jump_flag = 0;


 ? ? ? ?if(plcount == 0)// 第一幀
 ? ? ? ?{
 ? ? ? ? ? ?// 第一幀:T_curr2w = T_curr2last
 ? ? ? ? ? ?q_poses.push_back(q_gather_pose);
 ? ? ? ? ? ?t_poses.push_back(t_gather_pose);
 ? ? ? ?}
 ? ? ? ?else// 第二幀
 ? ? ? ?{
 ? ? ? ? ? ?// T_1_2_0 * T_2_2_1 = T_2_2_0
 ? ? ? ? ? ?// T_2_2_0 * T_3_2_2 = T_3_2_0
 ? ? ? ? ? ?q_poses.push_back(q_poses[plcount-1]*q_gather_pose);
 ? ? ? ? ? ?t_poses.push_back(t_poses[plcount-1] + q_poses[plcount-1] * t_gather_pose);
 ? ? ? ?}


 ? ? ? ?parray.header.stamp = ct;
 ? ? ? ?geometry_msgs::Pose apose;
 ? ? ? ?apose.orientation.w = q_poses[plcount].w();
 ? ? ? ?apose.orientation.x = q_poses[plcount].x();
 ? ? ? ?apose.orientation.y = q_poses[plcount].y();
 ? ? ? ?apose.orientation.z = q_poses[plcount].z();
 ? ? ? ?apose.position.x = t_poses[plcount].x();
 ? ? ? ?apose.position.y = t_poses[plcount].y();
 ? ? ? ?apose.position.z = t_poses[plcount].z();


 ? ? ? ?// ---------------------------- 當前幀位姿(優化前的)--------------------------------
 ? ? ? ?nav_msgs::Odometry laser_odom;
 ? ? ? ?laser_odom.header.frame_id = "camera_init";
 ? ? ? ?laser_odom.child_frame_id = "aft_BA";
 ? ? ? ?laser_odom.header.stamp = ct;
 ? ? ? ?laser_odom.pose.pose.orientation.x = apose.orientation.x;
 ? ? ? ?laser_odom.pose.pose.orientation.y = apose.orientation.y;
 ? ? ? ?laser_odom.pose.pose.orientation.z = apose.orientation.z;
 ? ? ? ?laser_odom.pose.pose.orientation.w = apose.orientation.w;
 ? ? ? ?laser_odom.pose.pose.position.x = apose.position.x;
 ? ? ? ?laser_odom.pose.pose.position.y = apose.position.y;
 ? ? ? ?laser_odom.pose.pose.position.z = apose.position.z;
 ? ? ? ?//發布優化前的位姿
 ? ? ? ?pub_odom.publish(laser_odom);
 ? ? ? ?//發布坐標關系
 ? ? ? ?static tf::TransformBroadcaster br;
 ? ? ? ?tf::Transform transform;
 ? ? ? ?tf::Quaternion q;
 ? ? ? ?transform.setOrigin(tf::Vector3(apose.position.x, apose.position.y, apose.position.z));
 ? ? ? ?q.setW(apose.orientation.w);
 ? ? ? ?q.setX(apose.orientation.x);
 ? ? ? ?q.setY(apose.orientation.y);
 ? ? ? ?q.setZ(apose.orientation.z);
 ? ? ? ?transform.setRotation(q);
 ? ? ? ?br.sendTransform(tf::StampedTransform(transform, laser_odom.header.stamp, "camera_init", "aft_BA"));
 ? ? ? ?parray.poses.push_back(apose);


 ? ? ? ?// 發布優化前的位姿
 ? ? ? ?pub_pose.publish(parray);


 ? ? ? ?pl_ground_buf.push_back(pl_ground_temp);
 ? ? ? ?pl_edge_buf.push_back(pl_edge_temp);
 ? ? ? ?pl_offground_buf.push_back(pl_offground_temp);

審核編輯:黃飛

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • SLAM
    +關注

    關注

    22

    文章

    391

    瀏覽量

    31592
  • 濾波算法
    +關注

    關注

    2

    文章

    83

    瀏覽量

    13661

原文標題:如何插入LinK3D、CSF、BALM來直接插入各個SLAM框架中

文章出處:【微信號:vision263com,微信公眾號:新機器視覺】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    GSLAM:一套通用的SLAM框架與基準

    其中,SLAM算法插件提供了SLAM領域流行的優秀算法,包括DSO,ORBSLAM,SVO和TheiaSFM等,這些插件可以直接集成到自己的代碼中,研究人員也可以基于這些插件進行進一步研究或者貢獻自己的插件。此外Rviz也被集成到了這一
    的頭像 發表于 03-07 09:42 ?7973次閱讀
    GSLAM:一套通用的<b class='flag-5'>SLAM</b><b class='flag-5'>框架</b>與基準

    基于多模態語義SLAM框架

    本文提出了一個魯棒且快速的多模態語義 SLAM 框架,旨在解決復雜和動態環境中的 SLAM 問題。具體來說,將僅幾何聚類和視覺語義信息相結合,以減少由于小尺度對象、遮擋和運動模糊導致的分割誤差的影響。
    的頭像 發表于 08-31 09:39 ?1353次閱讀

    主流web前端技術框架

    Web架構是為解決Web開發開放性問題而設計的具有一定約束性的支撐結構,使用框架可以幫助快速實現Web開發,并解決開發過程遇到的常規問題!以下是2018年常用的Web框架:1.
    發表于 03-28 16:56

    Hadoop的整體框架組成

    。Hadoop旨在從單個服務器擴展數千個機器,每個都提供本地計算和存儲。Hadoop框架包括以下四個模塊:HadoopCommon: 這些是其他Hadoop模塊所需的Java庫和實用程序。這些庫提供文件系統
    發表于 05-11 16:00

    框架設計的常用模式有哪些

    1. 模板方法模式模板方法模式是框架中最常用的設計模式。其根本的思路是算法由框架固定,而將算法具體的操作交給二次開發者實現。例如一個設備初始化的邏輯,
    發表于 12-17 16:44

    目前流行的前端開發框架是什么

    防止落后,但是我們不可能做到每個框架都有學習的時間,我們只需要掌握流行的,坑少的即可。從以下三個方面了解目前流行的前端開發框架。02. 跨多平臺開發框架(1).uni-app--開發一
    發表于 11-08 06:52

    什么是框架?為什么要有框架

    代碼結構體邏輯是一樣的,同時有大量相似或者共同的地方。我們可以這些共同的地方抽出來形成一個固定的程序框架,那么我們再開發新的同一種類型的程序時就可以套用這套框架。這樣會大大提高我們的開發效率,同時由于這個
    發表于 11-09 07:38

    HOOFR-SLAM的系統框架及其特征提取

    Intelligent Vehicles Applications1. 介紹2. HOOFR-SLAM2.1 系統框架2.2 HOOFR特征提取2.3 映射線程2.3.1 特征匹配1. 介紹提出一種HOOFR-...
    發表于 12-21 06:35

    一文總結ACE代碼框架

    都在此文件。如圖:二、ACE_Engine框架模塊劃分對于類Web開發范式組件,根據組件從前端后端的過程,可以整個框架劃分為JsFra
    發表于 01-10 11:09

    如何將CubeMX生成的程序框架與BSP驅動程序快速集成?

    一些經驗如何將 CubeMX 生成的程序框架與 BSP 驅動程序快速集成。目標是擁有無編譯/鏈接錯誤的應用程序框架。x-nucleo 板的入門文檔側重于 HAL 和 BSP 層的一般概念。我正在尋找
    發表于 01-30 08:48

    ACE代碼框架總結

    .ACE_Engine框架模塊劃分對于類Web開發范式組件,根據組件從前端后端的過程,可以整個框架劃分為JsFrameWork,DomNode, ComPonent, Render
    發表于 03-22 09:11

    如何將應用程序移植運行在基于Arm的設備上的Windows?

    本指南介紹如何將應用程序移植運行在基于Arm的設備上的Windows。該指南首先回顧了一般指南,然后展示了不同框架的示例:Tweeten應用程序的Electron移植、StaffPad應用程序
    發表于 08-02 06:06

    spring mvc框架介紹

    。使用 Spring 可插入的 MVC 架構,可以選擇是使用內置的 Spring Web 框架還是 Struts 這樣的 Web 框架。通過策略接口,Spring 框架是高度可配置的,
    發表于 11-17 16:28 ?2159次閱讀
    spring mvc<b class='flag-5'>框架</b>介紹

    LINS算法的框架與代碼分析

    LINS是以濾波為主的IMU、激光雷達緊耦合的激光SLAM算法。該算法的主要創新點就是用以 IESKF(即迭代誤差卡爾曼)為框架,融合 IMU 與激光雷達。該算法于發表于 2020 年 ICRA
    的頭像 發表于 10-09 14:57 ?2437次閱讀

    視覺SLAM開源方案匯總 視覺SLAM設備選型

    SLAM至今已歷經三十多年的研究,這里給出經典視覺SLAM框架,這個框架本身及其包含的算法已經基本定型,并且已經在許多視覺程序庫和機器人程序庫中提供。
    發表于 08-10 14:15 ?468次閱讀
    視覺<b class='flag-5'>SLAM</b>開源方案匯總 視覺<b class='flag-5'>SLAM</b>設備選型
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>