## Allan Variance
(圖來源自[kalibr, imu noise model](https://github.com/ethz-asl/kalibr/wiki/IMU-Noise-Model)、[IMU 知識筆記](https://mapostech.com/imu/))
具時間序列的資料其隨機誤差一般用 Allan Variance 分析, 概念是將資料依特定時間長度分段,各段分別取平均,再求相鄰段平均值的差值序列,最後計算差值序列的標準差。
<center>
<image width=35% src=https://hackmd.io/_uploads/S1Wwc9zike.png>
</center>
當用較短的時間長度分段時,對應至資料的高頻變化也就是高頻雜訊,用較長的時間長度分段時,對應至資料的低頻變化也就是低頻雜訊。
下圖典型 Allan Variance 分析圖(log-log AD plot) 用不同斜率來判斷是哪種類型的雜訊,下圖的縱軸:對差值序列的標準差取 log; 橫軸 : 對特定時間長度取 log.
<center>
<image width=70% src=https://hackmd.io/_uploads/Hy-r7jGo1x.png>
</center>
查找方式 : 按照下方圖表, 先尋找數據上有多少斜率種類的擬合直線, 再依哪個特定時間段$\tau$ 求交點, 那就會是該雜訊的deviation. 如果想要找 ```Random Walk``` 雜訊種類的標準差, 需要找到 ```-1/2```斜率的擬合直線與 $\tau=1$ 求交點,對應出的 deviation.
<center>
<image width=70% src=https://hackmd.io/_uploads/BJPWfifjkg.png>
</center>
在 kalibr 中, 會考慮 :
1. 量測雜訊
高頻雜訊, 標準差為 $\tau=1$ 與```1/2```斜率 random walk 的交點
2. bias雜訊
低頻雜訊, 標準差為 $\tau=3$ 與```-1/2```斜率 rate random walk 的交點
如下圖所示:
<center>
<image width=70% src=https://hackmd.io/_uploads/SyUuyTzjyg.png>
</center>
### Reference
1. [kalibr, imu noise model](https://github.com/ethz-asl/kalibr/wiki/IMU-Noise-Model)
2. [IMU 知識筆記](https://mapostech.com/imu/)
## IMU Intrinsic Calibration Pipline
我們使用 [yahboom imu device](http://www.yahboom.net/study/IMU) + kalibr 推薦的 [allan_variance_ros](https://github.com/ori-drs/allan_variance_ros) 於 ROS1-noetic from kalibr docker.
### 環境建置 2025.03.03
#### yahboom imu device
<center>
<image width=55% src=https://hackmd.io/_uploads/BJ5552Go1l.png>
</center>
首先按照 [yahboom imu device ](http://www.yahboom.net/study/IMU) 文件說明進行, 務必全部看完.
安裝檔只會用到 ```ros1_imu_ws.zip```, ```IMU standard PC software(V6.2.60)```.
以下只會提及重點~~~
1. 設定 imu device 的採樣率至 200HZ
需要調整 baudrate .
<center>
<image width=75% src=https://hackmd.io/_uploads/HJhMooGi1e.png>
</center>
ros1 確認 imu 200hz 的方式 :
<center>
<image width=45% src=https://hackmd.io/_uploads/BJG4aozsJe.png>
</center>
2. 關閉陀螺儀的自動校正(for 靜止狀態)
為了做 instric calibration, 所以需要進行調整
<center>
<image width=75% src=https://hackmd.io/_uploads/Hk03jjziJl.png>
</center>
#### ROS1-noetic from kalibr docker
<center>
<image width=55% src=https://hackmd.io/_uploads/Hyd0q3Gjyl.png>
</center>
首先先去 [kalibr installation](https://github.com/ethz-asl/kalibr/wiki/installation) 下載 ROS1-noetic from kalibr docker :
<center>
<image width=75% src=https://hackmd.io/_uploads/B1W6vofsyg.png>
</center>
確認 docker images 名稱 by ```$docker images```, 因為接下來要以映像檔為主額外下載其他套件(包含 yahboom imu device deserializer).
<center>
<image width=75% src=https://hackmd.io/_uploads/ByfcuoMj1g.png>
</center>
下載 yahboom imu device 的壓縮檔(python code) : ```ros1_imu_ws.zip``` .
安裝 docker by dockerfile :
::: spoiler 撰寫 dockerfile.
```shell=
# Use ros1 + Ubuntu 20.04 as the base image from https://github.com/ethz-asl/kalibr/wiki/installation
FROM kalibr
MAINTAINER <your name>
LABEL maintainer="<your email>"
# Avoid interactive prompts during installation
ARG DEBIAN_FRONTEND=noninteractive
# Install development tools and dependencies
RUN apt-get update && apt-get install -y \
vim \
git \
meld \
unzip \
python3-pip \
python3-tk \
udev \
lsof \
ros-$ROS_DISTRO-usb-cam \
ros-$ROS_DISTRO-imu-tools
RUN pip install pyserial
RUN git config --global diff.external meld
# [kalibr]
RUN echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
SHELL ["/bin/bash", "-c"]
# [IMU] refer to http://www.yahboom.net/study/IMU
# [IMU] 1-1. unzip ros1_imu_ws.zip [Retronix version]
COPY ros1_imu_ws.zip /root/
RUN unzip /root/ros1_imu_ws.zip -d /root/
# [IMU] 1-2. Compile feature pack and add into enviroment path
RUN source /opt/ros/noetic/setup.bash && \
cd /root/ros_imu_ws/ && \
catkin_make -j && \
cd src/scripts/ && \
sudo chmod 777 *.py && \
echo "source ~/ros_imu_ws/devel/setup.sh" >> ~/.bashrc && \
source ~/.bashrc
# [alan variance] https://github.com/ori-drs/allan_variance_ros
RUN cd /catkin_ws/src && \
git clone https://github.com/ori-drs/allan_variance_ros.git
RUN cd /catkin_ws/ && \
source /opt/ros/noetic/setup.bash && catkin build allan_variance_ros && source devel/setup.bash
# Set the default command to run when the container starts
CMD ["bash"]
```
:::
#### 指令集
- 建置 dokcer 指令 for dockerfile:
```shell=
docker build -t kalibr_ros1 .
```
下指令的資料夾結構 :
<image width=35% src=https://hackmd.io/_uploads/rJ5o0oMjJg.png>
- 啟動 docker 的指令 :
```shell=
docker run -it \
-e DISPLAY=$DISPLAY \
-e XAUTHORITY=/run/user/1000/gdm/Xauthority \
-v /run/user/1000/gdm/Xauthority:/run/user/1000/gdm/Xauthority \
-v /tmp/.X11-unix:/tmp/.X11-unix \
--device=/dev/video0:/dev/video0 \
--net=host \
--privileged \
kalibr_ros1
```
- 啟動 yahboom imu 指令集 :
```
# 1. 啟動 imu 的環境
cd ~/WitImu_ws
colcon build
source ~/WitImu_ws/install/setup.bash
# 2. 啟動 imu device
roslaunch wit_ros_imu rviz_and_imu.launch
# 3. 播放 imu
roslaunch wit_ros_imu rviz_and_imu.launch & rostopic echo /wit/imu
# 4. 錄製 imu
roslaunch wit_ros_imu rviz_and_imu.launch & rosbag record -O imu_data.bag /wit/imu
# 5. 查看 錄製.bag 的簡易資訊
rosbag info imu_data.bag
```
ros1 的 imu 通用格式 by ```rostopic echo /wit/imu```
<center>
<image width=75% src=https://hackmd.io/_uploads/S1MUx2Giyx.png>
</center>
### allan_variance_ros tool
1. 錄製靜置的 imu 長達 8hr~24hr
需先確認 imu 採樣頻率!!!
```shell=
# 啟動 imu 的環境
cd ~/WitImu_ws
colcon build
source ~/WitImu_ws/install/setup.bash
# 錄製 imu
roslaunch wit_ros_imu rviz_and_imu.launch & rosbag record -O imu_data.bag /wit/imu
```
2. [allan_variance_ros command](https://github.com/ori-drs/allan_variance_ros)
```shell=
# 啟動 allan_variance_ros 環境
cd /catkin_ws
source devel/setup.bash
rosrun allan_variance_ros cookbag.py --input imu_data.bag --output cooked_rosbag.bag
rosrun allan_variance_ros allan_variance . imu_config.yaml
rosrun allan_variance_ros analysis.py --data allan_variance.csv
```
Note : imu_config.yaml 是自己配置的, 如下所述:
<image width=55% src=https://hackmd.io/_uploads/By2Oz3fj1l.png>
squence_time 可以藉由 ```rosbag info imu_data.bag``` 查看.
3. 輸出結果圖
量測雜訊的標準差為 ```t=1s``` 與 white noise fit line (slope is ```1/2```) 的交點.
Bias雜訊的標準差為 ```t=3s``` 與 random rate fit line (slope is ```-1/2```) 的交點.
- 加速度器
<image width=85% src=https://hackmd.io/_uploads/BkL5b6Giye.png>
- 陀螺儀
<image width=85% src=https://hackmd.io/_uploads/BycsZ6fikg.png>
- 三種雜訊種類
該工具會分析三種雜訊種類於imu上 : 分別是斜率 ```-1/2```的 random walk, 斜率```0```的 bias instability, 斜率 ```1/2```的 rate random walk.
- 量測雜訊就是斜率 ```-1/2```的 random walk, 高頻雜訊, (對應至$\tau = 1$)
- 零偏雜訊就是斜率```1/2```的 rate random walk, 低頻雜訊, (對應至$\tau = 3$)

- 擬合雜訊模型 for kalibr 外參校正使用
allan_variance_ros tool 可輸出 kalibr 所需格式. ```noise_density```就是量測雜訊的標準差.

<image width=65% src=https://hackmd.io/_uploads/SJfRbpzoke.png>
- 需要注意的是 : ==通常會對雜訊標準差乘上10倍==, 再給 slam 使用以及外參標定流程喔 !!!
## Camera-IMU Extrinsic pipline
流程參考 [link](https://www.youtube.com/watch?v=rBT5O5TEOV4)
1. 執行 Docker 並共用資料夾
```shell=
FOLDER=/home/andrew/Documents/Code/SLAM/Calibration/data
sudo docker run -it \
-e DISPLAY=$DISPLAY \
-e XAUTHORITY=/run/user/1000/gdm/Xauthority \
-v /run/user/1000/gdm/Xauthority:/run/user/1000/gdm/Xauthority \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v "$FOLDER:/data" \
--net=host \
kalibr_allan
```
2. (optional) 產生 apriltag 標定板
```shell=
# generate target.pdf
cd kalibr/aslam_offline_calibration/kalibr/python
python3 kalibr_create_target_pdf --type apriltag --nx 6 --ny 6 --tsize 0.02 --tspace 0.3
```
3. 拍攝錄製成 bag
```shell=
rosbag record -O imu_april.bag /camera/color/image_raw /oak/right/image_rectified /camera/depth/image_raw /imu/data
```
<center>
<image width=55% src=https://hackmd.io/_uploads/HJr6dz-sll.png>
</center>
4. (optional) 雙目標定
```shell=
rosrun kalibr kalibr_calibrate_cameras --bag imu_stereo.bag --topics /camera/color/image_raw /oak/right/image_rectified --models pinhole-radtan pinhole-radtan --target april_6x6.yaml
```
5. camera + imu 標定
```shell=
rosrun kalibr kalibr_calibrate_imu_camera --target april_6x6.yaml --imu imu_bmi270.yaml --imu-models calibrated --cam cam_april-camchain.yaml --bag imu_april.bag
```
:::spoiler 參數檔
- april_6x6.yaml
<center>
<image width=80% src=https://hackmd.io/_uploads/BJ17AG-iee.png>
</center>
- imu_bmi270.yaml
直接取自 allan_ros_tool, 記得對雜訊乘上倍數. i.g. 白雜訊 * 5, 隨機遊走 * 10
<center>
<image width=50% src=https://hackmd.io/_uploads/rySdpf-jgx.png>
</center>
- (雙目) cam_april-camchain.yaml
```cam_overlaps``` 指的是哪些相機與當前相機共視.
<center>
<image width=100% src=https://hackmd.io/_uploads/SkLnAG-sxx.png>
</center>
- (單目) cam_april-camchain.yaml
<center>
<image width=100% src=https://hackmd.io/_uploads/BkbS1QWixl.png>
</center>
:::
### 校正工程的細節
- 相機內參標定
盡量降低曝光時間, 減少 motion blur
- IMU 內參標定
透過 allan variance ros 校正出來的雜訊變異量, 需要放大. 白雜訊 * 5, 隨機遊走 * 10.
- 聯合標定
- 設定 sigma 為 1 進行校正
- 標定手法 : 三軸都要旋轉到, 不能 constant 角速度
- 驗證
- 相機
- projection error 是否在 1 pixel.
- 投影點是否遵從高斯分布(橢圓形)
如果不遵從, 代表相機模型可能是錯的. 以下方圖示為例, 遵從高斯分佈.
<center>
<image width=55% src=https://hackmd.io/_uploads/rkRDjzWsxe.png>
</center>
- IMU
- 採樣點是否是 unitform
如果採樣點不規則, 可能是 bandwidth 開不夠大. 以下方圖為例, imu 200 hz 正常運作.
<center>
<image width=45% src=https://hackmd.io/_uploads/ByDsizbole.png>
</center>
- 確認加速度與陀螺儀是否都在紅框內(3 sigma)
如果沒有, 代表imu內參沒有求好. 以下方圖示為例, 在紅框內代表正常.
<center>
<image width=65% src=https://hackmd.io/_uploads/SJoeoG-jgg.png>
</center>
- 檢查變化量是否夠低
以下方紅框為例, 變化量是低的.
<center>
<image width=85% src=https://hackmd.io/_uploads/ryQq9MWsge.png>
</center>
- IMU 內參的單位

### Reference
1. https://blog.csdn.net/kanhao100/article/details/130073156
2. https://tomas789.medium.com/iphone-calibration-camera-imu-and-kalibr-33b8645fb0aa
3. https://hackmd.io/@PFABrcAkRWSshatDzBNr9w/rJvgZ91rE
4. https://blog.csdn.net/qq_41694024/article/details/130598248