オドメトリフレーム（/odom）とは何か

# この記事の要約

- 位置推定やSLAMを行う際に出てくるオドメトリフレーム（以下，/odom）の役割，必要性を述べる
- /odomは自律移動を行うために必ずしも必要なものではない
- マップフレーム（以下，/map）上での位置推定の結果がジャンプする可能性がある際（大局的位置推定やループクローズの実行）に，連続する時系列データを蓄積した情報（局所地図など）を保持するために/odomは必要



# はじめに

昨今，自律移動をやろうとなったら，おおよその方はROSを用いるところからスタートし，gmappingやamclなどのSLAMや自己位置推定の機能を使うことになると思います．それで，この際にほとんど多くの方が疑問に思うことは「/odomって何？」だと思います．もちろん，他にも詰まる部分があると思いますが，私の感覚では「初学者で/odomをすんなり理解できた人はいない」という感じです．なので，何度も/odomの説明はしてきたのですが，その度に「説明が難しいし，理解してもらうのも難しい」と思わされるものでした．本記事では，/odomが存在する意味を簡単に説明します．逆に，/odomは無くても良いという理由も説明します．



# フレームの定義

ROSを用いて位置推定を行うと，フレーム（座標系）の構成は以下の様になります（SLAMを用いる場合も同様ですが，説明は位置推定に限定します）．

- /map -> /odom -> /base_link -> /sensor

上記はそれぞれ「マップフレーム（/map）」，「ロボットフレーム（/base_link）」，「センサフレーム（/sensor）」になります（2D LiDARを用いてamclなど実行すると，/sensorは/lidarや/laserになるかと思います）．

ここでまず，**位置推定モジュールの機能は何か**ということを考えてみます．「位置推定の機能を説明してください」と言うと，おそらく多くの方は「与えられた地図上での自身の位置を認識すること」と言うと思います．実際私もそう説明することが多いです．

ですが位置推定の機能をこう説明してしまうと，位置推定モジュールは/mapから/base_linkの変換を求めるものになるはずです．つまり上記のフレームは，

- /map -> /base_link -> /sensor

という構成になるはずです．しかし実際には「/map -> /odom -> /base_link」となっているわけです．つまり位置推定の機能とは，「/mapから/odomの変換を求めていること」になっているわけです．つまり，/odomとは何かを理解しない限り，真に位置推定モジュールが何をしているかは理解できないことになります．

なお後にも述べますが，「/map -> /base_link」の構成で自律移動ができないことはありません．ただ，一部の機能が使えなくなるだけというものになります．



# /odomとは

## オドメトリとは

/odomの解説を始める前に，まずオドメトリ（odometry）の解説をします．オドメトリとは，**センサから計測される移動量を積算して位置を求める手法**になります（昔とある先生から本来の定義はもっと違うと言われたことがあるのですが，現状のロボティクス分野ではこの理解で問題ないと思っています）.

オドメトリの例を上げると，車輪型移動ロボットの車輪の回転量をエンコーダを用いて計測して移動量を計算し，そこから位置を求める「ホイールオドメトリ」があります．ホイールオドメトリの特徴は以下になります．

- 車輪の回転量から計算できる移動量を積算するだけで位置が計算できるため，周囲の外乱に影響を受けない
- 積算により求められた位置は（基本的に）ジャンプ（急激に値が変化）することがないため，位置推定の結果は連続的に変化する

/odomを理解する上で大切なことは，2つ目の**積算により求められた位置はジャンプすることがない**という性質になります．つまり，オドメトリにより求められた位置の軌跡は連続的な経路になります．

ただし，オドメトリにより求められた位置は**積算（積分）誤差**を含みます．これは移動量計算における誤差が時間とともに増大していくという問題です．そのため，オドメトリのみで正しく位置を求めることはできません．



## /odom

前述の通りオドメトリとは，移動量の積算により位置を求めるものになります．そして/odomとは，**オドメトリにより計算された位置を表す座標**になります．つまり位置推定の実施にあたってはまずオドメトリモジュールが存在し，そのモジュールが/odom上で移動量を積算して位置を求めることになります．


## 位置推定によるオドメトリの補正

オドメトリモジュールが/odom上で位置を求めても，その位置には積算誤差が含まれます．そのため，この誤差を修正しないと，本来ロボットが走行するべき環境を示した/map上での正しい位置を求めることができません．そのため，オドメトリの情報を基にして，/map上での正しいロボットの位置を求める必要があります．

ただしここで大切なことは，**/odom上での連続的な経路情報を保持しておきたい**ということです（理由は後述）．これを実現するために位置推定モジュールは，**/map上のロボットの現在位置と，/odom上のロボットの現在位置が同じになるように/mapから/odomへの変換を求める**という動作を実行します．これにより，/map上から見ればロボットの正しい位置がわかる，/odom上では連続的なデータが保持される，ということが達成されるようになります．


## 図解

ここまでの説明を下図にまとめます．オドメトリモジュールの機能は(a)に説明されているように，/odom上での移動量の積算のみになります．そして位置推定の機能は(b)に説明されているように，/mapから/odomへの変換を求めていることになります．ここで注目して欲しいのは上述の通り，/odom上でのロボットの移動軌跡が保持されていることです．

![odometry.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329950/7ca581bf-a886-7830-59cb-08bda4e25ffa.png)



# /odomの必要性

上述の通り/odom上では，ロボットの連続的な移動データが保持されています．この記事では最後に/odomの必要性，同時に不必要性も解説します．

## ジャンプの発生

位置推定は常に連続的に変化するロボットの位置を求めるわけではありません．例えば大域的位置推定が実行されると，ロボットの推定位置は急激にジャンプすることになります．しかし大域的位置推定の結果位置推定の結果がジャンプしたとしても，実際にロボットの位置は変化していないこともあります．

このとき，ロボットが移動中にセンサデータを蓄積し，局所的な地図を作成していたとします．もしフレームの構成が「/map -> /base_link」となっていると，連続的な移動データが保持できないため，この局所地図は不連続なものとなってしまいます．しかしここでフレーム構成を「/map -> /odom -> /base_link」として，局所地図は/odom上の位置情報を基に作成することにすると，局所地図も連続性を保持することが可能になります．

つまり，位置推定結果がジャンプする様なことが想定される場合に，連続する時系列データを活用したい場合には，/odomを用いることが有効となります．

なおSLAMを実行するにあたっては，移動量推定を行うために局所地図を作成することがあります．そしてループ検知などを行い，大域的な地図の補正を行います．この地図補正を行うと，/map上での推定位置がジャンプすることになります．このような場合でも，/odom上で局所地図の構築を行っていれば，連続性を保持した推定を実行することができます．

## /odomがいらない場合

もし位置推定結果がジャンプしない前提であれば，/odomは必要ないことになります．これは例えば，常い位置追跡に成功するようなナビゲーションを前提としていれば十分に達成できます．またこの場合は，/map上での位置を基にデータの蓄積を行っても，特段問題になることはないといえます．実際に私が学生の頃につくばチャレンジンに参加していたときは，そのようなシステムで自律移動を行っていました（というか/odomの必要性を理解していなかった）．

ただし，移動ロボット関連の研究や業務をやるにあたっては，/odomの知識はないと色々と問題になると思います．そのため，/odomを使わないことは良しとしても，/odomに関する知識はあった方が良いかと思います．



# おわりに

ROSで位置推定やSLAMを実行した際に現れるオドメトリフレーム（/odom）に関する解説を行いました．/odom上ではロボットの連続した移動経路データが保持されます．また位置推定やSLAMは，/mapから/odomへの変換を求めます．この記事が少しでも役に立てば幸いです．