0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

反光板導(dǎo)航SLAM:VEnus代碼淺析

3D視覺工坊 ? 來源:古月居 ? 2023-03-14 10:54 ? 次閱讀

通過研究具體的代碼我們可以簡單了解VEnus中對于反光柱定位的具體流程。

1、IntensityExtraction::Extract

IntensityExtraction::IntensityRange2D &cloud,
                 VEnus::IntensityRange2D &candidate_cloud)

Extract函數(shù)的主要作用是從激光點云中提取出高反點,然后存儲到對應(yīng)的容器中。輸入的數(shù)據(jù)類型為

VEnus::IntensityRange2D

IntensityRange2D數(shù)據(jù)類型是定義在sensor/proto/sensor.proto文件內(nèi)

message IntensityRange2D
{
  int64 timestamp = 1;
  string frame_id = 2;
  repeated IntensityPoint2D points = 3;
}

IntensityPoint2D的數(shù)據(jù)格式如下:

message IntensityPoint2D
{
  float x = 1;
  float y = 2;
  float intensity = 3;
}

repeated 類似于std的vector,可以用來存放N個相同類型的內(nèi)容。所以這個函數(shù)的輸入cloud是一系列帶有強(qiáng)度信息的2D坐標(biāo)點。函數(shù)的candidate_cloud代表的是匹配到的可能的反光柱點。所以它們數(shù)據(jù)結(jié)構(gòu)是一樣的。

然后是函數(shù)實現(xiàn),這個函數(shù)其實很簡單,它只是對整個點云進(jìn)行了一次遍歷,取連續(xù)的n個點,這個由一個參數(shù)intensity_median_filter_param決定,如果反光柱粗一點的或者激光分辨率高一點的話可以設(shè)置大一點,否則的話可以設(shè)置小一點,例如3。

然后對這些點進(jìn)行判斷,只要其中有一半的點云強(qiáng)度超過閾值intensity_threshold則認(rèn)為這里存在一個反光柱,將其中的點云強(qiáng)度處于中間值的那個點存入到容器candidate_cloud。這里其實有點隨機(jī)性在里面,因為沒有把所有的點都加入到容器中,所以是存在一定遺漏的。

2、DBscanAssociation::Association

DBscanAssociation::IntensityRange2D& candidate_cloud,
                  VEnus::Feature2DList& feature_list)

前面我們提取出了反光柱的中心點,但是這里的點云中可能會出現(xiàn)很多個點代表同一個反光柱的情況。所以這個函數(shù)即是對剛才的這些點進(jìn)行一次類似于聚類的操作。

candidate_cloud為第一步中選出來的高反點。feature_list為可能的反光柱中心。然后我們具體看一下函數(shù)實現(xiàn):

Association的第一部分主要是遍歷了所有點,通過調(diào)用expand_cluster函數(shù)進(jìn)行一個分類:

 for (; iter < dataset.end(); ++iter) {
 ? ?if (iter->status == UNCLASSIFIED) {
   //聚類,將所有高反點根據(jù)相互之間距離分類,分類完成的點status為CLASSIFIED,同時處于同一類的點ID一致。
   if (expand_cluster(iter, cluster_id)) {
    cluster_id++;
   }
  }
 }

dataset里面存儲的就是當(dāng)前幀的高反點,來自于candidate_cloud,數(shù)據(jù)類型為:

PointDBSCAN(double px, double py) {
   x = px;
   y = py;
   status = UNCLASSIFIED;
   id = 0;
  }

可以看到對于每一個高反點,都有坐標(biāo)x/y、狀態(tài)status以及id等幾個屬性。初始狀態(tài)下狀態(tài)都為UNCLASSIFIED未區(qū)分,id都為0。然后函數(shù)對于每個點調(diào)用expand_cluster函數(shù)。

這個函數(shù)的作用是:對于每一個candidate_cloud,找到所有candidate_cloud中的點與其接近的點(兩者間距離小于一定閾值)這些點的status都會被設(shè)置為CLASSIFIED防止重復(fù)判斷。id都會被設(shè)置為相同代表同一個反光柱。

通過這種方式可以將所有點都劃分成一個個點的區(qū)域,每個區(qū)域代表了一個反光柱。

在劃分完成后,當(dāng)然是要對每個區(qū)域做處理:

//按照ID將所有點放到map容器中
 unordered_map > feature_dict;
 iter = dataset.begin();
 for (; iter < dataset.end(); ++iter) {
 ? ?if (iter->status == CLASSIFIED) {
   feature_dict[iter->id].push_back(iter - dataset.begin());
  }
 }
 //找到每一組點的中心點的坐標(biāo),存放到tmp_res里面
 vector > tmp_res;
 for (auto pr : feature_dict) {
  double center_x = 0;
  double center_y = 0;
  for (int idx : pr.second) {
   center_x += dataset.at(idx).x;
   center_y += dataset.at(idx).y;
  }
  int sz = pr.second.size();
  //ROS_INFO("center point,x = %f,y = %f",center_x / double(sz),center_y / double(sz));
  tmp_res.push_back(std::make_pair(center_x / double(sz), center_y / double(sz)));
 }
 //判斷每個中心點之間的距離,將距離過近的中心點視為代表同一個反光柱,更新容器中反光柱中心點坐標(biāo)
 merge_cluster(tmp_res);

首先這里通過map維護(hù)了每一個待選的反光柱信息,所有的同一個反光柱的信息放到一起。

進(jìn)行一個劃分,然后對每一類點集調(diào)用merge_cluster進(jìn)行一個中心點的求取。求取的方式其實很簡單就是簡單相加求平均。這樣子就可以知道了所有反光柱中心點所在的位置。

3、CartoMapping::InsertFeatureList

這個函數(shù)的功能還是挺多的,包括匹配,位姿估計,位姿優(yōu)化等一系列其實都是在這個函數(shù)中實現(xiàn)的。詳細(xì)看一下這個函數(shù)具體情況:

3.1 初始化

InsertFeatureList函數(shù)的第一步判斷了feature_points容器是否為空,這里面存儲的是全局坐標(biāo)下的反光柱。這個容器為空說明目前沒有已經(jīng)確定的反光柱。則進(jìn)行初始化。

if (feature_points.empty())

初始化的方式比較簡單,將第一幀的反光柱坐標(biāo)存儲到feature_points中作為初始狀態(tài)下反光柱的中心坐標(biāo),然后更新FeatureGraph。

注意到這里的函數(shù):InsertToFeatureGraph,這個函數(shù)的意義是對于每一個待插入的點(反光柱),計算它與周圍反光柱之間的距離,然后存儲到feature_graph中。注意到feature_graph的數(shù)據(jù)類型

第一個int為對應(yīng)的feature_points的ID,第二個std::unordered_map中的int為與這個feature_points相互關(guān)聯(lián)的反光柱點的ID,后面的double類型數(shù)據(jù)為兩個點之間的距離。

3.2 特征點匹配

SiftNewFeaturePoints(input_fpts, hit_id_pair, wait_insert);

在確認(rèn)初始化完成的情況下,調(diào)用SiftNewFeaturePoints函數(shù)進(jìn)行反光柱的匹配。這個函數(shù)有三個參數(shù):input_fpts為前面識別出來的反光柱坐標(biāo),hit_id_pair為當(dāng)前幀反光柱與世界坐標(biāo)系下的反光柱匹配上的ID,wait_insert為當(dāng)前幀中沒能跟世界坐標(biāo)系下反光柱所匹配上的點的ID。函數(shù)主要執(zhí)行了以下工作:

首先,對于所有當(dāng)前點,建立一個局部的local_feature_graph,記錄當(dāng)前點與點之間的距離。

然后,對于每一個當(dāng)前幀的點,使用其局部local_feature_graph與全局點進(jìn)行匹配。

注意這里不是點與點的匹配而是類似于線與線的匹配,如果一個點到其他點的距離與全局點中某個點到其周圍點的距離基本一致,則認(rèn)為這兩個點是匹配上了的,這時候會把這一對ID存放到hit_id_pair中。這個方式其實應(yīng)該是有問題的,如果兩個點到周圍點的距離都很接近,就可能發(fā)生誤匹配。

最后,對于input_fpts中剩下沒有匹配到的點,則會將其存放到wait_insert中,這個數(shù)據(jù)代表這里檢測出一個反光柱但是在全局中沒有,后面需要另外處理。

3.3 初始位姿估計

ComputeCurrentPose(localization_hit, pose)

這個函數(shù)emmm其實我沒看,因為似乎它基本就沒有正確計算出來過。不過也不要緊,直接看下一步

3.4 位姿優(yōu)化

OptimizeCurrentPose(localization_hit, pose);

OptimizeCurrentPose中需要輸入兩個變量:localization_hit里面存放的是當(dāng)前幀下匹配點全局點之間的坐標(biāo)。

pose是機(jī)器人當(dāng)前初步估計下的位姿,按照邏輯它應(yīng)該會來自于步驟3,但是由于3總是出問題所以大部分情況下它來自于上一次估計出來的位姿。

然后根據(jù)輸入的約束關(guān)系localization_hit以及初始位姿pose,調(diào)用ceres優(yōu)化得到一個新的位姿:

 ceres::Problem problem;
 double pose[3] = {robot_pose.x(), robot_pose.y(), robot_pose.theta()};


 for (auto fpt_pair : match_result) {
  problem.AddResidualBlock(new ceres::AutoDiffCostFunction(
                 new FeaturePairCost(fpt_pair.second, fpt_pair.first)),
               new ceres::CauchyLoss(0.2), pose);
 }


 ceres::Options options;
 options.linear_solver_type = ceres::DENSE_QR;
 options.minimizer_progress_to_stdout = false;


 ceres::Summary summary;
 ceres::Solve(options, &problem, &summary);

最后這里輸出得到的是一個新的優(yōu)化后的位姿pose

3.5 更新反光柱信息

注意到前面3.2中還有一個東西沒有處理,就是返回的wait_insert容器。

這個里面存放的是當(dāng)時檢測到的反光柱但是這個反光柱沒能與地圖上其他地方的反光柱相匹配上,說明它可能是一個新的反光柱,對于這些信息我們要將其更新到最新的反光柱信息中:

 Eigen::Isometry2d matrixT = Eigen::Identity();
 matrixT.pretranslate(Eigen::Vector2d(pose.x(), pose.y()));
 matrixT.rotate(pose.theta());
 //  Eigen::Isometry2d matrixTinv = matrixT.inverse();


 vector > new_fpt_wait_insert;
 vector new_fpt_assigned_id;
 for (auto unhit : wait_insert) {
  Eigen::Vector3d local_fpt(unhit.first, unhit.second, 1.0);
  auto global_fpt = matrixT * local_fpt;


  auto new_fpt = make_pair(global_fpt[0], global_fpt[1]);
  feature_points[feature_point_cnt] = new_fpt;
  new_fpt_wait_insert.push_back(new_fpt);
  new_fpt_assigned_id.push_back(feature_point_cnt);
  feature_point_cnt++;
 }

首先是通過矩陣matrixT將這些反光柱點轉(zhuǎn)到世界坐標(biāo)系下,然后再根據(jù)初始化時候的方式一樣更新feature_points容器,存儲新的反光柱信息。當(dāng)然最后還要調(diào)用:

InsertToFeatureGraph(new_fpt_wait_insert, new_fpt_assigned_id);

來更新feature_graph,也就是反光柱之間的距離信息。

通過以上一系列步驟我們就可以得到一個連續(xù)的基于反光柱匹配的位姿估計算法。當(dāng)然這個算法還有一點小問題,比如線匹配意味著每一個反光柱到周圍反光柱之間的距離都要獨一無二,否則就可能出現(xiàn)誤匹配的問題。

匹配閾值也不能設(shè)計的太大,否則也會發(fā)生匹配錯誤,但是設(shè)計的太小就可能導(dǎo)致本來是一個地方的反光柱沒有成功匹配上,最后該位置會生成出很多個反光柱,類似于這樣:

06b9ee62-c003-11ed-bfe3-dac502259ad0.png

這里先介紹完代碼思路,具體的代碼實現(xiàn)以及優(yōu)化過程下一章單獨展開介紹。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 導(dǎo)航
    +關(guān)注

    關(guān)注

    7

    文章

    517

    瀏覽量

    42333
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4284

    瀏覽量

    62325
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4723

    瀏覽量

    68236
  • SLAM
    +關(guān)注

    關(guān)注

    23

    文章

    415

    瀏覽量

    31758
  • Venus
    +關(guān)注

    關(guān)注

    0

    文章

    7

    瀏覽量

    2660

原文標(biāo)題:反光板導(dǎo)航SLAM:VEnus代碼淺析

文章出處:【微信號:3D視覺工坊,微信公眾號:3D視覺工坊】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    反光板的選用

    推薦一款用在智能小車上紅外測距傳感器的反光板吧{:19:}
    發(fā)表于 07-19 12:57

    激光導(dǎo)航AGV控制系統(tǒng)解決方案(無反光板非工控機(jī))

    LNM-v1.0(工業(yè)級)無軌導(dǎo)航無軌導(dǎo)航LNM-v1.0激光導(dǎo)航模塊是一款基于室內(nèi)復(fù)雜壞境的導(dǎo)航模塊,該模塊通過激光雷達(dá)對室內(nèi)環(huán)境進(jìn)行掃描,自主構(gòu)建地圖并自主規(guī)劃路徑行走。LNM模塊
    發(fā)表于 06-10 14:07

    AGV激光雷達(dá)SLAM定位導(dǎo)航技術(shù)

    agv自由行走的問題?! 《ㄎ缓?b class='flag-5'>導(dǎo)航一般是相輔相成,傳統(tǒng)的定位導(dǎo)航方式(電磁導(dǎo)航、磁條導(dǎo)航)的優(yōu)缺點如下方圖表所示,這些方案的優(yōu)點和局限性都很明顯。稍微靈活點的
    發(fā)表于 11-09 15:59

    SLAM技術(shù)的應(yīng)用及發(fā)展現(xiàn)狀

    結(jié)合激光雷達(dá)或者攝像頭的方法,讓掃地機(jī)可以高效繪制室內(nèi)地圖,智能分析和規(guī)劃掃地環(huán)境,成功讓自己步入了智能導(dǎo)航的陣列。除了掃地機(jī)之外,SLAM技術(shù)在其他服務(wù)機(jī)器人(例如商場導(dǎo)購機(jī)器人、銀行機(jī)器人
    發(fā)表于 12-06 10:25

    激光SLAM與視覺SLAM有什么區(qū)別?

    機(jī)器人定位導(dǎo)航中,目前主要涉及到激光SLAM與視覺SLAM,激光SLAM在理論、技術(shù)和產(chǎn)品落地上都較為成熟,因而成為現(xiàn)下最為主流的定位導(dǎo)航
    發(fā)表于 07-05 06:41

    怎么利用51單片機(jī)去實現(xiàn)風(fēng)扇轉(zhuǎn)速測量的源程序+電路圖呢

    項目功能:將被測風(fēng)扇葉片(三葉風(fēng)扇)置于紅外光電傳感器和其反光板之間,當(dāng)光電傳感器接收到對面的反光板反射回來的信號時(即葉片間的空隙通過時)輸出低電平,當(dāng)光電傳感器沒收到反光板反射回的信號時(即葉片
    發(fā)表于 09-08 06:59

    有沒有辦法用VL53L0X 區(qū)分反光板和其他反光材料?

    如您所知,無論反光片表面角度如何,反光片都非常明亮。然而,其他反光材料,如鏡子,只有在表面角度垂直于 VL53L0X 時才會亮。在這種情況下,僅憑亮度的差異是很難區(qū)分的。 有沒有辦法用 VL53L0X 區(qū)分
    發(fā)表于 12-27 06:24

    SLAM算法在AGV小車中的使用

    導(dǎo)航一般是相輔相成,傳統(tǒng)的定位導(dǎo)航方式(電磁導(dǎo)航、磁條導(dǎo)航)的優(yōu)缺點如下方圖表所示,這些方案的優(yōu)點和局限性都很明顯。稍微靈活點的導(dǎo)航定位方
    發(fā)表于 09-11 16:01 ?1262次閱讀

    艾吉威:智慧物流“剛需”下的推陳出新

    艾吉威成功將無反光板激光自主導(dǎo)航叉車AGV運(yùn)用于輪胎制造領(lǐng)域,成為全球首例大規(guī)模運(yùn)用無標(biāo)識導(dǎo)航AGV的案例。
    的頭像 發(fā)表于 06-19 17:47 ?2754次閱讀

    無人叉車的種類有哪些,關(guān)于它的選擇方法的介紹

    的無人叉車也成為目前廣大用戶所關(guān)心的問題。 我們在選擇無人叉車的時候,要了解它們的性能和結(jié)構(gòu),其中激光導(dǎo)航叉車可分為分為有反光板和無反光板兩種: 我們在選擇有反光板激光
    發(fā)表于 10-20 12:06 ?2327次閱讀

    關(guān)于SEER SRC核心控制器的八問八答

    。 問:SEER 機(jī)器人支持哪些導(dǎo)航呢? 答:激光 SLAM 導(dǎo)航,激光反光板導(dǎo)航,二維碼導(dǎo)航,
    的頭像 發(fā)表于 11-03 18:18 ?2164次閱讀

    激光SLAM搬運(yùn)式叉車SFL-CBD20-S

    SFL-CBD20-S采用了目前最穩(wěn)定最主流的導(dǎo)航方式——激光SLAM導(dǎo)航,無反光板,部署方便,內(nèi)置仙工智能(SEER)SRC核心控制器,可提供地圖構(gòu)建、定位、
    的頭像 發(fā)表于 02-04 16:43 ?2408次閱讀

    反光導(dǎo)航開發(fā)與實驗

    VEnus算法對于反光導(dǎo)航的基本思路,其主要分為了高反點提取、高反點聚類查找中心、高反點與已知反光柱位姿匹配以及調(diào)用ceres庫進(jìn)行位姿優(yōu)化等步驟。
    的頭像 發(fā)表于 07-14 15:37 ?580次閱讀
    <b class='flag-5'>反光</b>柱<b class='flag-5'>導(dǎo)航</b>開發(fā)與實驗

    淺析基于SLAM的機(jī)器人自主定位導(dǎo)航

    正如圖中所示,機(jī)器人自主定位導(dǎo)航技術(shù)中包括:定位和地圖創(chuàng)建(SLAM)與路徑規(guī)劃和運(yùn)動控制兩個部分,而SLAM本身只是完成機(jī)器人的定位和地圖創(chuàng)建,二者有所區(qū)別。
    發(fā)表于 08-03 11:12 ?915次閱讀
    <b class='flag-5'>淺析</b>基于<b class='flag-5'>SLAM</b>的機(jī)器人自主定位<b class='flag-5'>導(dǎo)航</b>

    光電傳感器反光板能否用鏡子替代?

    反光板是所有回歸反射型光電傳感器必不可少的配套元件,它的使命是將光電傳感器中的發(fā)射器發(fā)出去的光反射回來,以便傳感器接收器能夠接收到光信號。那么一定有不少工程師想過這個問題鏡子也可以反光可以用鏡子
    的頭像 發(fā)表于 07-02 08:24 ?460次閱讀
    光電傳感器<b class='flag-5'>反光板</b>能否用鏡子替代?