要知道我們相對於起點的位置,最簡單的方式就是時刻知道自己朝什麼方向前進了多少--然後把這些數值加總起來。然而對人類來說,可以依靠羅盤等方式來累計,但對於機器人來說要怎麼做呢?
我們以最常見的雙輪驅動速差小車為例(包含許多常見平台以及我們的智慧機器人),一個比較簡單的方式是在馬達上加上編碼器,透過計算編碼器的數值來知道車子左右輪轉動的圈數,接著只需要知道輪幅就可以計算出移動的距離了。
計算看似美好,但存在一些缺點--比方說,輪子在光滑平面上利用速差轉彎時,容易有滑動的狀況。在這種情況發生後,里程計的數值就不能直接代表移動距離。
這時候我們就會嘗試加入IMU(Inertial measurement unit,慣性測量單元)來輔助。IMU量測的是三軸(XYZ)上的重力加速度以及三軸的角速度--很顯然的,加速度這種數值就是有變化的瞬間量測。因此IMU擅長的是短時間的變化,剛好可以跟前面的編碼器相輔相成,結合兩者的資料就可以得到相對準確的里程計。
而具體這些數值的計算是一個不短的數學過程,發送的ROS訊息格式要填的東西也很多。幸好,大部分的底盤供應商都會把這些東西打包完成,我們只需要使用廠商提供的package就可以了。
而里程計的訊息則會以nav_msgs/odometry的格式發送到odom這個頻道去。這個訊息的格式具體如下:
```python
std_msgs/Header header
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist
```
把底下兩個msg的格式再拆開:
```python
std_msgs/Header header
string child_frame_id
#geometry_msgs/PoseWithCovariance pose
#Point position
float64 x
float64 y
float64 z
#Quaternion orientation
float64 x
float64 y
float64 z
float64 w
float64[36] covariance
###############################
#geometry_msgs/TwistWithCovariance twist
#Vector3 linear
float64 x
float64 y
float64 z
#Vector3 angular
float64 x
float64 y
float64 z
float64[36] covariance
```
......恩,幸好通常供應商會幫忙弄好。
但我們還是要學會看懂資料內容,其中比較沒看過的恐怕會是pose中的Quaternion這個資料了--於是,下一篇我們就來科普一下Quaternion是什麼。