最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言lidar_align雷達里程計校準功能詳解

 更新時間:2023年03月02日 16:42:35   作者:月照銀海似蛟龍  
這篇文章主要為大家介紹了C語言lidar_align雷達里程計校準功能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

功能介紹

功能包名稱:lidar_align git網址:鏈接

一種 校準 3D 激光雷達和 6 自由度位姿傳感器 外參 的 方法

適配的ROS版本有 Indigo、Kinect、Melodic

準確的結果需要 大量 非平面的運動,這使得該方法不適合 校準 安裝在汽車上的傳感器 以為只有在那個方向上有數(shù)據(jù)的變化才能計算出最終的結果。

整個功能包大體上實現(xiàn)了下面的功能

1、讀取lidar和位姿傳感器的數(shù)據(jù)

2、通過時間戳匹配lidar每幀里面的每個點和位姿傳感器的坐標變換

3、通過上面的變換矩陣將 利用位姿信息將lidar的每幀拼接成點云

4、每個點和它最近鄰點的距離總和求出,在優(yōu)化中就是不斷的迭代找到坐標變換使這個距離最小

功能包算法的整體思想

1、為每幀lidar的每個點通過時間戳去匹配一個位姿數(shù)據(jù),并通過插值的方式得到更準確的位姿值,每個點的時間偏移也是優(yōu)化因素之一

2、利用NLopt的庫的非線性優(yōu)化方法

3、目標函數(shù):讓拼接后的點云的每個點的最近鄰點最小

4、優(yōu)化向量:x、y 、z、roll、pitch、yaw、time_offset 總體來說就是不斷的迭代,找到一個合適的優(yōu)化向量(也就是lidar到里程計的坐標變換)使得拼在一起的點云每個點的最近鄰點距離最小。這個功能包的優(yōu)點就是可以離線計算,錄一個rosbag,然后跑一下就可以求的外參 它只會讀取一個bag ,所以 lidar和位姿都要在里面

最終的結果: 在運行的時候,功能包會輸出當前的估計變化 優(yōu)化結束的時候 坐標變換的參數(shù)會打印在終端上 也會在路徑下面保存一個txt文件和ply文件。

可以查看ply文件,就是拼接后的點云和場景是否一致

編譯

從git上下載后需要 下載 nlopt的庫

sudo apt-get install libnlopt-dev

然后編譯還是會報錯

Could not find a package configuration file provided by "NLOPT"

解決辦法 將 lidar_align 文件夾下的 NLOPTConfig.cmake 復制到 你ROS工作空間的src路徑下面

相關參數(shù)

這些都沒有在配置文件里面 想要修改的話需要改源碼然后再編譯

在每個類里面有個 Config的結構體, 初始化了相關參數(shù)

和lidar相關的在 Scan類里面設置的

class Scan {
 public:
  struct Config {
    float min_point_distance = 80;//lidar數(shù)據(jù)里面點的距離的最小值 大于此值被使用 0.0;
    float max_point_distance = 200;// lidar數(shù)據(jù)里面點的距離的最大值 小于此值被使用  默認100.0;
    float keep_points_ratio = 0.01;// 用于優(yōu)化點的比例 (此值越大會極大增加運行時間) 默認0.01
    float min_return_intensity = -1.0;//lidar數(shù)據(jù)里面點的強度的最小值  大于此值被使用  默認 -1.0
    bool estimate_point_times = false;//是否估計lidar每個點的時間 用下面那倆變量   默認 false
    bool clockwise_lidar = false;//lidar旋轉的方向  順時針還是逆時針              默認  false(逆時針)
    bool motion_compensation = true;//是不是需要運行補償    默認 true
    float lidar_rpm = 600.0;// lidar的轉速  僅用于  estimate_point_times   默認 600
  };

輸入輸出的相關參數(shù)在launch里面設置的

    <param name="input_bag_path" value="$(arg bag_file)" />
    <param name="input_csv_path" value="$(arg csv_file)" />
    <param name="output_pointcloud_path" value="$(find lidar_align)/results/$(anon lidar_points).ply" />
    <param name="output_calibration_path" value="$(find lidar_align)/results/$(anon calibration).txt" />
    <param name="transforms_from_csv" value="$(arg transforms_from_csv)"/>

use_n_scans 執(zhí)行優(yōu)化開始的 lidar的幀數(shù) 默認 2147483647 input_bag_path ros bag 的路徑
transforms_from_csv 是否通過 csv文件 讀取位置 默認 false input_csv_path csv路徑 output_pointcloud_path ply文件輸出路徑 output_calibration_path 校準結果輸出路徑

校正相關參數(shù) 在Aligner類里面設置的

class Aligner {
 public:
  struct Config {
    bool local = false;//執(zhí)行局部優(yōu)化還是全局優(yōu)化 初始化為false, 執(zhí)行全局的優(yōu)化,并且結果用于初始估計 然后執(zhí)行局部優(yōu)化
    std::vector<double> inital_guess{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};//校準的初始估計   僅用于運行 local 模式  
    double max_time_offset = 0.1;//最大的時間對準偏差  x[6]的上下浮動范圍
    double angular_range = 0.5;    //  在初始估計位置的搜索范圍 (弧度)  角度偏移上下限 +-0.5弧度
    double translation_range = 1.0;//在初始估計位置的搜索范圍 (位置)  位置偏移上下限 +-1米
    double max_evals = 200;// 最大的評估次數(shù)
    double xtol = 0.0001;//x的容差
    int knn_batch_size = 1000;//點的偏移數(shù)量 被用于  尋找最近鄰點時
    int knn_k = 1;//尋找最近鄰點的個數(shù) , 程序了 自加1了  因為在一個點云里面找其中一個點的最近鄰一個是自己一個才是真的最近鄰
    float local_knn_max_dist = 0.1;//局部優(yōu)化的時候 最近鄰點的最大距離
    float global_knn_max_dist = 1.0;//全局優(yōu)化的時候 最近鄰點的最大距離
    bool time_cal = true;   //是否執(zhí)行時間補充計算  就是在找每個點的位姿時根據(jù)時間對里程計插值
    std::string output_pointcloud_path = "";  //點云文件保存路徑
    std::string output_calibration_path = ""; // 校準信息文件保存路徑
  };

代碼文件結構

頭文件四個:

  • aligner.h : Lidar 和 Odom 校正(外參計算)時用到的類
  • **loader.h :**從ROS的Bag或CSV格式載入數(shù)據(jù)的相關函數(shù)
  • **sensor.h :**主要包括Odom以及LIdar相關接口
  • transform.h : 一些SO3變化的計算及轉換,在插值、優(yōu)化時使用

cpp文件四個:

  • aligner.cpp : Lidar 和 Odom 校正(外參計算) 時 的實現(xiàn)函數(shù)
  • lidar_align_node.cpp : main的啟動地方 實例各個類
  • loader.cpp : 加載數(shù)據(jù)
  • sensors.cpp : 處理lidar和里程計的數(shù)據(jù)

核心代碼

前面的數(shù)據(jù)讀取處理啥的就不整了,下面分析下主要的代碼部分

在面函數(shù)里面 調用了 下面的 函數(shù) 前面就是數(shù)據(jù)讀取和處理,從這個函數(shù)里面開啟了校準的過程

aligner.lidarOdomTransform(&amp;lidar, &amp;odom);//執(zhí)行校準

這個函數(shù)里面

  /*根據(jù) 是否使用 時間補償  來確定 優(yōu)化參數(shù)的 個數(shù)*/
  size_t num_params = 6;//初始化優(yōu)化參數(shù)的個數(shù)
  if (config_.time_cal) {
    ++num_params;//使用時間補償計算   優(yōu)化參數(shù)個數(shù)為7
  }

根據(jù) 是否使用 時間補償 來確定 優(yōu)化參數(shù)的 個數(shù)

 /*根據(jù)配置參數(shù)(是否執(zhí)行全局優(yōu)化)  執(zhí)行 初始角度的賦值 ,如果執(zhí)行全局優(yōu)化則先進行一個 估計,得到角度 否則 直接附設置的初始值    */
  if (!config_.local) {  //默認  執(zhí)行 全局優(yōu)化  并用于初始估計
    //打印 正在 執(zhí)行 全局 優(yōu)化
    ROS_INFO("Performing Global Optimization...                             ");
    std::vector<double> lb = {-M_PI, -M_PI, -M_PI};//設置下限
    std::vector<double> ub = {M_PI, M_PI, M_PI};//設置上限
    std::vector<double> global_x(3, 0.0);//設置 執(zhí)行全局優(yōu)化的  x參數(shù)向量 設置為3 個,初始值為0.0
    optimize(lb, ub, &opt_data, &global_x);//執(zhí)行優(yōu)化(全局優(yōu)化)  只求 角度的  優(yōu)化結果
    config_.local = true;//將全局優(yōu)化的flag關閉  下次則執(zhí)行 局部優(yōu)化
    //賦值 角度  優(yōu)化 的結果
    x[3] = global_x[0];
    x[4] = global_x[1];
    x[5] = global_x[2];
  } else {//local 為 true的 話  則 為 默認的 初始值 
    x = config_.inital_guess;//初始值 全為0    局部優(yōu)化則初始認為 lidar和imu的坐標軸一致對齊  其它情況最好按實際情況粗略配置 初始值 
  }

根據(jù)配置參數(shù)(是否執(zhí)行全局優(yōu)化) 執(zhí)行 初始角度的賦值 ,如果執(zhí)行全局優(yōu)化則先進行一個 估計,得到角度 否則 直接附設置的初始值

  //設置 參數(shù)向量 的下限   ,默認參數(shù) -1,-1,-1,-0.5,-0.5,-0.5
  std::vector<double> lb = {
      -config_.translation_range, -config_.translation_range,
      -config_.translation_range, -config_.angular_range,
      -config_.angular_range,     -config_.angular_range};
  //設置 參數(shù)向量 的上限    默認參數(shù) 1,1,1,0.5,0.5,0.5
  std::vector<double> ub = {
      config_.translation_range, config_.translation_range,
      config_.translation_range, config_.angular_range,
      config_.angular_range,     config_.angular_range};
  //將  全局優(yōu)化得到的 角度的 初始估計值  疊加到 上下限中   也就是說  初始估計 roll 為0.1弧度,則 優(yōu)化的范圍是 0.1 +- 0.5 弧度  
  for (size_t i = 0; i < 6; ++i) {
    lb[i] += x[i];//疊加下限
    ub[i] += x[i];//疊加上限
  }
    //將時間補償?shù)?優(yōu)化 范圍 加 到 上下限中
  if (config_.time_cal) {
    ub.push_back(config_.max_time_offset);
    lb.push_back(-config_.max_time_offset);
  }

設置 優(yōu)化因素的 上限和下限

 /*執(zhí)行局部優(yōu)化*/
  optimize(lb, ub, &opt_data, &x);

執(zhí)行局部優(yōu)化

下面看下執(zhí)行局部優(yōu)化的主要內容

也就是 optimize()函數(shù) 里面就是用的nlopt的方法進行的非線性優(yōu)化

  if (config_.local) {//看是執(zhí)行全局優(yōu)化還是局部優(yōu)化   用的算法不同  x的個數(shù)在前面配置的也不同, 全局優(yōu)化為3個,只求角度 局部優(yōu)化為7個
    opt = nlopt::opt(nlopt::LN_BOBYQA, x->size());
  } else {
    opt = nlopt::opt(nlopt::GN_DIRECT_L, x->size());//選用 全局優(yōu)化函數(shù)  不需要求導的  算法 DIRECT_L   x的個數(shù)在前面配置的是三個 
  }

根據(jù)執(zhí)行全局優(yōu)化還是局部優(yōu)化 選擇不同的算法 并生成了 nlopt 對象實例

  //設置下限
  opt.set_lower_bounds(lb);
  //設置上限
  opt.set_upper_bounds(ub);
  opt.set_maxeval(config_.max_evals);//設置最大估計次數(shù)
  opt.set_xtol_abs(config_.xtol);//設置x容差停止值
  opt.set_min_objective(LidarOdomMinimizer, opt_data);//設置目標函數(shù)  LidarOdomMinimizer函數(shù)名 opt_data外部數(shù)據(jù)

nlopt的相關設置 其中 LidarOdomMinimizer 是目標函數(shù)需要重點看的

目標函數(shù)里面

  //通過 kdtree 的 方法 求的 每個點的 最近鄰距離 總和
  double error = d->aligner->lidarOdomKNNError(*(d->lidar));

在這里 通過 kdtree 的 方法 求的 每個點的 最近鄰距離 總和

然后不斷的迭代讓這個距離最小,得到的優(yōu)化向量就是 校準信息了

主要的核心就是這些了,當然這個里面的小細節(jié)太多了,有問題的童鞋可以私信我。

結果

最后上一個測試時的結果把

Active Transformation Vector (x,y,z,rx,ry,rz) from the Pose Sensor Frame to the Lidar Frame: [0.770924, -0.25834, 0.105557, 1.67974, -1.88141, -1.40085]

Active Transformation Matrix from the Pose Sensor Frame to the Lidar Frame: -0.300413 -0.623731 -0.721603 0.770924 -0.870125 -0.130671 0.475193 -0.25834 -0.390685 0.770639 -0.503468 0.105557 0 0 0 1

Active Translation Vector (x,y,z) from the Pose Sensor Frame to the Lidar Frame: [0.770924, -0.25834, 0.105557]

Active Hamiltonen Quaternion (w,x,y,z) the Pose Sensor Frame to the Lidar Frame: [-0.127913, -0.577435, 0.646763, 0.481564]

Time offset that must be added to lidar timestamps in seconds: -0.00263505

ROS Static TF Publisher:

在txt里面功能包輸出的結果就是這樣的。

以上就是C語言lidar_align雷達里程計校準功能詳解的詳細內容,更多關于C語言lidar_align雷達里程計校準的資料請關注腳本之家其它相關文章!

相關文章

  • C語言實現(xiàn)五子棋小游戲

    C語言實現(xiàn)五子棋小游戲

    五子棋游戲是一款很經典的智力游戲,只有學過編程語言的人,把五子棋的編程原理弄懂了,就能用自己熟悉的語言實現(xiàn)出來,在這里給大家分享,c語言五子棋源碼,僅供大家參考借鑒。
    2016-03-03
  • C語言版的三子棋游戲

    C語言版的三子棋游戲

    這篇文章主要為大家詳細介紹了C語言版的三子棋游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C++深入探究類與對象之對象模型與this指針使用方法

    C++深入探究類與對象之對象模型與this指針使用方法

    C++對象模型中只有類的非static成員以及一個指向虛函數(shù)表的指針被配置于類對象內,其他都在類對象外,在 C++ 中,每一個對象都能通過 this 指針來訪問自己的地址。this 指針是所有成員函數(shù)的隱含參數(shù)。因此,在成員函數(shù)內部,它可以用來指向調用對象
    2022-04-04
  • 在Visual Studio使用C++開發(fā)Metro應用

    在Visual Studio使用C++開發(fā)Metro應用

    這篇文章主要介紹了在Visual Studio使用C++開發(fā)Metro應用的示例,盡管只是一個Hello world,但可以體現(xiàn)出VS下為開發(fā)者提供的方便,需要的朋友可以參考下
    2015-07-07
  • C語言實現(xiàn)數(shù)獨程序的示例代碼

    C語言實現(xiàn)數(shù)獨程序的示例代碼

    數(shù)獨是源自瑞士的一種數(shù)學游戲。是一種運用紙、筆進行演算的邏輯游戲。本文將利用C語言實現(xiàn)數(shù)獨程序,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-03-03
  • C++簡明講解類型轉換的使用與作用

    C++簡明講解類型轉換的使用與作用

    類型轉換(type?cast),是高級語言的一個基本語法。它被實現(xiàn)為一個特殊的運算符,以小括號內加上類型名來表示,接下來讓我們一起來詳細了解
    2022-04-04
  • 詳解C++實現(xiàn)拓撲排序算法

    詳解C++實現(xiàn)拓撲排序算法

    拓撲排序是對一個有向無環(huán)圖(Directed Acyclic Graph簡稱DAG)G進行拓撲排序,是將G中所有頂點排成一個線性序列,使得圖中任意一對頂點u和v,若邊(u,v)∈E(G),則u在線性序列中出現(xiàn)在v之前。本文將對其原理進行講解,并且用C++進行實現(xiàn)
    2021-06-06
  • 詳解C++字符串常用操作函數(shù)(查找、插入、截取、刪除等)

    詳解C++字符串常用操作函數(shù)(查找、插入、截取、刪除等)

    這篇文章主要介紹了C++字符串常用操作函數(shù)(查找、插入、截取、刪除等),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • C語言實現(xiàn)三子棋的示例代碼

    C語言實現(xiàn)三子棋的示例代碼

    所謂三子棋,就是三行三列的棋盤,玩家可以和電腦下棋,率先連成三個的獲勝。這篇文章主要為大家詳細介紹了如何通過C語言實現(xiàn)三子棋小游戲,感興趣的小伙伴可以嘗試一下
    2023-01-01
  • Qt鍵盤事件實現(xiàn)圖片在窗口上下左右移動

    Qt鍵盤事件實現(xiàn)圖片在窗口上下左右移動

    這篇文章主要為大家詳細介紹了Qt鍵盤事件實現(xiàn)圖片在窗口上下左右移動,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08

最新評論

洛阳市| 高州市| 克东县| 武威市| 嘉荫县| 南江县| 锡林郭勒盟| 阿勒泰市| 克什克腾旗| 汾西县| 固安县| 临清市| 都昌县| 广水市| 六盘水市| 酒泉市| 中江县| 宜都市| 密云县| 黑水县| 宝丰县| 历史| 民乐县| 木里| 余庆县| 东丰县| 永德县| 嘉兴市| 明星| 吴旗县| 宿迁市| 余庆县| 藁城市| 龙川县| 行唐县| 株洲市| 阿克| 确山县| 沾益县| 门头沟区| 铜山县|