---
# System prepended metadata

title: SLAM Notes
tags: [SLAM]

---


# SLAM Notes

###### tags: `SLAM`




## 特徵點(Feature points) vs 角點(Corner points) vs 關鍵點(Key points)

定義些微不同，但皆可被稱為「關鍵點」或「特徵點」，某些地方亦會被稱為"landmark"，例如：
「人臉特徵檢測」 > "facial landmark detection"

* **特徵點(Feature points)**：
    指在圖像中具有顯著性和獨特性的點，這些點通常具有較強的灰度變化、紋理結構或局部結構，並且與相鄰區域的其他點不同。特徵點可以是圖像的明顯邊緣、紋理區域或是斑點等。
    
* **角點(Corner points)**：
    是特徵點的一種特殊類型，指的是圖像中具有明顯角度變化的點，角點通常為兩條邊或曲線相交的位置，這些位置的灰階度在多個方向上都有顯著變化。由於角點在不同方向上的梯度變化較大，它們在圖像中去有獨特性和區分性，常常被視為圖像特徵的重要組成部分，用於自動識別和定位上。
    
    其餘具體描述
    * 角點的一階導數最大，二階導數為零，指為物體邊緣變化不連續的方向
    * 圖像中梯度值和梯度方向變化速率都很高的點

* **關鍵點(Key points)**：
    更加抽象的概念，一般來說為分析問題中較為重的點。

## 機器視覺－相機標定
在影像測量過程以及機器視覺應用中，為確定空間物體表面某點的三維幾何位置與其在影像中對應點之間的相互關係，須建立攝影機成像的幾何模型，幾何模型參數就是攝影機參數，求解參數的過程就稱為相機標定
* **相機內參數**：例如透鏡的焦距、光學中心和徑向畸變係數。
    為什麼叫內參呢，這個是因為這些參數是只有相機決定的，可以認為相機的內參在出廠之後是固定的，不會在使用過程中改變。
    相機的內參分別有：1/dx、1/dy、r、u0、v0、f
    opencv中的內參是4個，分別為fx、fy、u0、v0。其實opencv中的fx也就是F*Sx，其中F是焦距上面的f，Sx是像素/每毫米也就是上面的1/dx。
    dx和dy表示x方向和y方向的一個像素分別佔多少個單位，是反映現實中的影像物理座標關係與像素座標系轉換的關鍵（可以理解成反映像元密度？）。
    u0，v0代表影像的中心像素座標和影像原點像素座標之間相差的橫向和縱向像素數。

* **相機外參數**
    相機的外參是6個(3個用於旋轉、3個用於平移)，三個軸的旋轉參數分別是（w、δ、θ），把每個軸的33旋轉矩陣進行組合（矩陣之間相乘），得到集合三個軸旋轉資訊的R，其大小仍是33；T的三個軸的平移參數（Tx、Ty、Tz）。 R、T組合成3*4的矩陣，其是轉換到標定紙座標的關鍵。

* **畸變參數**
    畸變參數是：k1，k2，k3徑向畸變，p1，p2是切向畸變係數。徑向畸變發生在相機座標系轉像物理座標系的過程。
## 三大 3D 感測原理比較
* **Stereo Vision－立體視覺**
    Stereo Vision 是基於人眼視差的原理，在自然光源下，透過兩個或兩個以上相機模組從不同的角度對同一物體拍攝影像，再進行三角測量法等運算來取得與物體之間的距離資訊。
    
* **Structured Light－結構光**
    Structured Light 是一種主動式深度感測技術，基本零組件包含 IR 發射器、IR 相機模組、RGB 相機模組等。其原理是先對物體發射特定圖案的光斑（Pattern），再經由攝影機來接收物體表面上的光斑圖案編碼（Light Coding），進而比對與原始投射光斑的異同，並利用三角原理計算出物體的三維座標。
    
* **ToF(Time of Flight)－飛時測距**
    ToF 也是一種主動式深度感測技術，其原理為透過紅外線折返的時間去計算跟物體之間的距離，以得出 3D 景深圖。基本零組件包括 IR 發射器、IR 接收器、RGB 相機模組和感光元件或感應陣列。

![](https://hackmd.io/_uploads/rkE1bLdlp.png)



## Fast特徵點


## BRIEF描述子 vs rBRIEF描述子



## SFM (Structured-From-Motion)－運動估計

* 從運動中不同角度拍攝物體，利用多張物體不同時間的照來恢復物體的3D結構。跟SLAM裡的Visual odometry一樣樣需要估算出每幀圓片到世界座標的 R,t，然後根據圓片重建點雲 °
* 算法關鍵就在於特徵匹配，求兩張圖片之間的R,t，然後反投影得到物體的3D點，最後將多個稀疏點雲融合在一起。
* BA (Bundle Adjustment)－光束調整
  SFM常使用的一種算法

## ORB_SLAM3 調適
前人採坑筆記
https://blog.csdn.net/qq_39533374/article/details/123709139

* Eigen
```shell=
## Eigen Install

##github 有个mirror,版本3.3.4 from 2017
git clone https://github.com/eigenteam/eigen-git-mirror
 
##安装
cd eigen-git-mirror
mkdir build
cd build
cmake ..
sudo make install
 
##安装后,头文件安装在/usr/local/include/eigen3/
```
* Pangolin
```shell=
##安裝Pangolin所需相依套件

sudo apt install libgl1-mesa-dev
sudo apt install libglew-dev
##sudo apt install cmake //注意以前装了就不需要安装了
sudo apt install libpython2.7-dev
##sudo apt install python-pip
##sudo python -mpip install numpy pyopengl Pillow pybind11
sudo apt install pkg-config
sudo apt install libegl1-mesa-dev libwayland-dev libxkbcommon-dev wayland-protocols
##sudo apt install ffmpeg libavcodec-dev libavutil-dev libavformat-dev libswscale-dev libavdevice-dev
##sudo apt install libdc1394-22-dev libraw1394-dev
##sudo apt install libjpeg-dev libpng-dev libtiff5-dev libopenexr-dev
```

```shell=
## Pangolin Install

##預設 git 版本為 0.6
##git clone https://github.com/stevenlovegrove/Pangolin.git 

##坑呀！太坑了！不能安装 Pangolin master 版本
git clone https://github.com/stevenlovegrove/Pangolin/tree/v0.6.git 

cd Pangolin
mkdir build && cd build
cmake ..
make -j4
sudo make install

##檢查
cd examples/HelloPangolin
./HelloPangolin
```

* opencv
```shell=
## Opencv Install

sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
sudo apt update
sudo apt install libjasper1 libjasper-dev

sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg.dev libtiff4.dev libswscale-dev libjasper-dev
```

* Issues
    * 載點位置：
    ```https://github.com/UZ-SLAMLab/ORB_SLAM3.git```
    * C++版本設定
    ```sed -i 's/++11/++14/g' CMakeLists.txt```
    or CMakeLists.txt add_compile_options(-std=c++)
    * 執行時沒有畫面： 
    check ORB_SLAM3/Examples/Monocular/mono_euroc.cc
    第83行，將 false 改成 true
    * RGB-D 執行 timestamp associates tools
    https://cvg.cit.tum.de/data/datasets/rgbd-dataset/tools
        * associate.py 執行錯誤，python2 && python3 語法差異
        ```python=
        # 改
        # first_keys = first_list.keys()
        # second_keys = second_list.keys()
            ↓
        first_keys = list(first_list.keys())
        second_keys = list(second_list.keys())
        ```
        * evaluate 執行錯誤
        ```python=
        # 改
        # first_keys = first_list.keys()
        # second_keys = second_list.keys()
            ↓
        first_keys = list(first_list.keys())
        second_keys = list(second_list.keys())
        
        AttributeError: 'dict_keys' object has no attribute 'sort'
        # 改
        # stamps.sort()
            ↓
        sorted(stamps)
        
        TypeError: 'dict_keys' object is not subscriptable
        # 增
        stamps=list(stamps)
        ```
    * 執行資料集程式碼：
    EuRoc EXEC code : ./Examples/Monocular/mono_euroc ./Vocabulary/ORBvoc.txt ./Examples/Monocular/EuRoC.yaml ./dataset/MH_01 ./Examples/Monocular/EuRoC_TimeStamps/MH01.txt
    * 修改 System.cc 問題：在保存地圖時，經常會出現**Segmentation fault**，導致地圖無法保存目前可能的原因： 在UI界面點擊stop後，stereo_realsense_D435i.cc中的while ( !SLAM.isShutDown())會回傳mbShutDown這個flag的狀態，而這個flag是在System::shutdown()中進行修改的．
    ```cpp=
    void System::Shutdown()
    {
        {
            unique_lock<mutex> lock(mMutexReset);
            mbShutDown = true;
        }

        cout << "Shutdown" << endl;

        mpLocalMapper->RequestFinish();
        mpLoopCloser->RequestFinish();
        …
    ```
    a. shutdown()是註冊在介面端的函數．在介面點選stop()後， mbShutDown 立刻會被設定為 true; b. 同時在./Examples/Stereo/stereo_realsense_D435i.cc中的while (!SLAM.isShutDown())會檢查mbShutDown的值．當mbShutDown==true時，退出while循環. 推出while循環後，後面已無可執行的命令，整個程式退出，SLAM物件銷毀． c. 但是當地圖檔案很大時，註冊在介面端的函數依舊在執行，最後在SaveAtlas()時，會存取SLAM物件中的一些成員，如mStrVocabularyFilePath變數,但此時SLAM已經被銷毀，最後存取變數出錯，導致Segmentation fault.
    修改
    ```cpp=
    void System::Shutdown()
    {
        {
            unique_lock<mutex> lock(mMutexReset);
        }
        cout << "Shutdown" << endl;
        mpLocalMapper->RequestFinish();
        mpLoopCloser->RequestFinish();
        
        …
            
        if(!mStrSaveAtlasToFile.empty())
        {
            Verbose::PrintMess("Atlas saving to file " + mStrSaveAtlasToFile, Verbose::VERBOSITY_NORMAL);
            SaveAtlas(FileType::BINARY_FILE);
        }
        /*if(mpViewer)
            pangolin::BindToContext("ORB-SLAM2: Map Viewer");*/
    #ifdef REGISTER_TIMES
        mpTracker->PrintTimeStats();
    #endif
         mbShutDown = true;
    }
    ```
    將mbShutDown = true;放在程式的最後，執行完地圖儲存後，再修改flag.

    * 

* 進階步驟：
    1. 輸出轉換成 .pcd(point cloud)
https://blog.csdn.net/qq_45848817/article/details/126024785
(另解) 轉換成 .osa
https://blog.csdn.net/qq_43591054/article/details/125693886
    pcl_viewer 可查看 .pcd file
    
    2. .pcd → .ot or .bt
    https://blog.csdn.net/heirenlop/article/details/112133737
    octovis 可查看 .ot .bt file)(.ot 為普通文件、.bt 為二進制文件)
    3. otovis can show octree structure
