Probabilistic Robotics - Chap.3 Gaussian Filters
3.2 The Kalman Filter
カルマンフィルタは線形ガウスシステムでフィルタリング(つまり余計なものを省くプロセス[1])と予測を行うために開発された。カルマンフィルタは、連続状態空間でのbeliefを実装する。離散状態空間やハイブリッドな空間には対応しない。
時刻でのbeliefは、ベイズフィルタがマルコフ過程に加えて下記3点を満たす時、平均と共分散のガウス分布で表せる。
【1点目】
状態遷移確率が線形関数で表わせ、状態がガウスノイズを加味した下記の式で表せる。
ここで、は状態ベクトル、は制御ベクトルを、それぞれ表す。またはの正方行列で、は状態ベクトルの次元を示す。そしてはの行列で、は制御ベクトルの次元を示す。このように行列を導入することで、カルマンフィルタは入力である状態と制御の線形関数として状態遷移を表現する。
なおは、状態遷移の不確かさを表現するためのガウスノイズで、平均は、共分散は、次元は状態ベクトルと同じとする。
式を多変量ガウス分布の式に当てはめると、平均で共分散である
として表せる。
【2点目】
計測確率も、状態遷移確率と同様で入力に対して線形とする。また計測データは、ガウスノイズを加味した下記の式で表せる。
ここではの行列で、は計測ベクトルの次元とする。は、平均で共分散の計測ノイズである。計測確率は、と同様に多変量ガウス分布の形で、
として表せる。
【3点目】
最後に、初期belief は、平均で共分散のガウス分布
として表せる。
これら3つの仮定は、がガウス分布で表せることを確認するのに十分である。
3.2.2 The Kalman Filter Algorithm
カルマンフィルタの入力と出力は
入力:と制御ベクトル、観測ベクトル
出力:
である。アルゴリズムは下記の数式で表せる。
Table3.1 対象が線形な場合のカルマンフィルタアルゴリズム
なおはカルマンゲインと呼ばれ、状態遷移時に観測結果をどの程度考慮するかを調節する値である。
Table3.1の2,3行目は制御を加えた結果の予測過程を、4~6行目は観測結果を元に状態を更新する過程を、それぞれ示している。
それぞれの行に対する私の解釈は、
- 2行目:制御を加えたことによる平均の変化を予測
- 3行目:共分散は分散の2乗であるから、に対する二次形式になっている
- 5行目:予測した平均に対し、予測からどれだけずれたか、を考慮して平均を更新
- 6行目:共分散を求める式なので、の部分は必ず正になる。よってとわかる。このことから、共分散を抑えにかかっていると言える。
下記に私がPythonで書いたカルマンフィルタのコードを載せました。参考になれば。
3.3 The Extended Kalman Filter
3.4 The Unscented Kalman Filter(UKF)
UKFも非線形なシステムに対応するカルマンフィルタの1手法。線形回帰を使うことで、統計的に線形化する。回帰に使うサンプル点として、Sigma Point[3]を設定する。Sigma Pointは、平均を中心とし、かつ共分散行列の主軸に対して線対称になるように配置する。平均・共分散な次元のガウス分布については、個のSigma Pointを配置する。配置時のルールは下記の通り。
ここで、で、とはからどの程度離れるかを決めるスケールパラメータである。
また、各は2種類の重みとを持つ。は平均を、はガウス分布の共分散を、それぞれ計算する際に用いる。なおとは下記の式で求める。
ここでは、分布に関する追加情報をエンコードするためのパラメータであり、分布がガウス分布であればが最良となる。
Sigma Pointは、関数を使って写像される。写像後の平均と共分散はそれぞれ、
として表せる。
3.4.2 The UKF Alogorithm
UKFとEKFの入出力は同じだが、計算負荷はUFKの方が少し高い。また線形システムでは、UFKとLKFは同じ結果を示す。UKFの利点は、ヤコビアンの計算が不要な点である。ヤコビアンの計算には微分が必要であり、時には計算が難しい。そのためヤコビアンの計算を回避できることは計算上好ましい。なおUKFはパーティクルフィルタに似ているが、パーティクルフィルタはサンプル点をランダムに取るのに対し、UKFではサンプル点の取り方が固定という違いがある。
3.5 The Information Filter(IF)
LKFと同様に線形なシステムを仮定している。LKFとの主な違いは、ガウス分布の表現方法である。LKFとその派生は、ガウス分布をモーメント(平均と共分散)を使って表している。それに対しIFは、カノニカルな表現方法を使用する(*注意:僕、カノニカルとはどういうことかよくわかっていません!調べている途中です。。)。
IFとLKFは、状態遷移確率と観測確率それぞれを、LKFと同じ式で求める。またLKFと同様に、予測と更新の2ステップで構成される。IFの入力は、カノニカルなパラメータである。そして出力はである。なおの定義は下記の通り。
IFとLKF・その派生を比較した時、下記のようなメリット・デメリットがある。
- メリット
LKF・その派生よりも数値的に安定している(安定が曖昧だが、他のことばへの言い換えがわからない。。)
LKF・その派生よりもロボットの実問題へ当てはめやすい
- デメリット
更新時に状態推定をリカバーする必要がある
状態空間の次元が大きくなると計算コストが膨大になる
参考
[0]Probabilistic Robotics
[1]Filter (signal processing) - Wikipedia
[2]テイラー展開 - Wikipedia
[3]http://lab.cntl.kyutech.ac.jp/~nishida/lecture/psc/no8.pdf
Numpyでの行列の扱い方
Numpyで行列を作る場合、下記の3種類の方法がある。
①numpy.array([1, 2], [3, 4])
②numpy.matrix(numpy.array([1, 2], [3, 4]))
③numpy.mat(numpy.array([1, 2], [3, 4]))
上記の挙動について調べたことを下記に示す。
足し算・引き算
import numpy as np a = np.array([2, 2]) a.shape -> (2, ) b = np.array([[1, 2], [3, 4]]) b.shape -> (2, 2) a - b -> array([[1 , 0], [-1, -2]]) # なんと計算できちゃいます。aの1行目が2行目にもコピーされ、 # 2行2列の行列として扱われます。 c = np.matrix([[1, 2, 3], [4, 5, 6]]) c.shape -> (2, 3) a - c -> error! # 相手のデータタイプがmatrixだと、aとcのデータタイプが異なるからなのか、aは2行2列とは扱わないです。
掛け算
①の方法を採用する時、行列aとbの掛け算はnumpy.dot(a, b)とする必要がある。もしもa * bとすると、それは各要素毎に掛け算を行うことを意味する。②、③の時は、a * bでもnumpy.dot(a, b)のどちらでもよい。以上をコードで表すと下記の様になる。
import numpy as np a = np.array([[1, 2], [3, 4]]) b = np.array([[4, 3], [2, 1]]) a * b -> array([[4 , 6] [6 , 4]]) # a * b[0][0] = a[0] * b[0] となっている np.dot(a, b) -> array([[8 , 5], [20, 13]]) c = np.matrix(np.array([[1, 2], [3, 4]])) d = np.matrix(np.array([[4, 3], [2, 1]])) c * d -> matrix([[8 , 5], [20, 13]]) np.dot(c * d)-> matrix([[8 , 5], [20, 13]]) e = np.mat(np.array([[1, 2], [3, 4]])) f = np.mat(np.array([[4, 3], [2, 1]])) e * f -> matrix([[8 , 5], [20, 13]]) np.dot(e * f)-> matrix([[8 , 5], [20, 13]]) g = np.array([1, 2]) g * a -> error! np.dot(a, a) -> error! # 掛け算の場合、足し算・引き算と異なり、1行目は2行目にコピーされない
RTAB-Mapについてのメモ
最近3DSLAMに興味があり、ROSにも対応したRTAB-Mapをいじってみました。その過程でわかったことなどをメモします。ある程度纏まった量が出てくるまでは箇条書きになりますのでご容赦を(笑)
・Eigen3.3.3には対応せず。3.2.0はOK(RTAB-Map 0.12.5で)
Huawei P9 Liteでアプリによる通知を有効化する方法
先日Huawei P9 Liteに機種変しました。その後Wuderlist等のアプリをインストール・使ったところ、リマインダーの通知が一向に上がってこないという事態に陥りました。調べたところ、P9 Liteのバッテリーマネージャが原因だということがわかりました。本記事では、どうやって通知を有効化すればよいか、設定方法を記載します。
(少なくともP9 Liteでは)、一部のアプリを除き、画面オフ状態やそのアプリが表示されていない時(バックグラウンドでの実行状態)になるとアプリの動作が無効化されるみたいです。そのため、通知を有効化するためには、アプリの動作有効化が必要となります。有効化の方法は単純で、
「設定」→「詳細設定」→「バッテリーマネージャ」→「保護されたアプリ」
で有効/無効を、タップで切り替えるだけです。
上記「保護されたアプリ」の一覧でwunderlistを有効化することで、リマインダの通知が上がってくるようになりました。参考になれば幸いです。
apt-getとaptitude
はじめに
Linuxでは、コンパイラやエディタ、ライブラリ等のパッケージのインストールを、コマンドを使ってできます。そのコマンドは、apt-getとaptitudeというコマンドがあります。下記ではそれぞれの違いについて簡単に説明します。
apt-getとaptitudeの違い
2つのコマンドの違いは、簡単に言えば推奨パッケージを自動的にインストールするかどうかです。推奨パッケージとは、あるパッケージをインストールした時に、必ずしもインストールする必要はないものの、同時にインストールすることを推奨されるパッケージのことです。
apt-get
apt-getはパッケージのインストールをするためのコマンドです。インストール可能なパッケージの検索はできません。別のコマンドapt-cacheを使います。推奨パッケージは手動でインストール必要があります。
update-alternativesの使い方
update-alternativesとは
Linuxを使う時、シンボリックリンクを使う時があります。例えばgccでは、生成したバイナリを動かす環境に応じて、バージョンを使い分ける必要があります。この時、毎回必要なバージョン以外のgccを削除することもできますが、シンボリックリンクを使ってバージョン管理をするのが便利です。lnコマンドを使ってシンボリックリンクを張ることもできますが、管理対象が別のパッケージに依存しており、かつそのパッケージのバージョンも変更しないといけないときは面倒です。update-alternativesコマンドはそうした時に使う、目的とするパッケージとそれに従属するパッケージのシンボリックリンクを、一括で切り替えることができるコマンドです。
Fig.1 update-alternativesコマンドのイメージ
update-alternativesコマンドの使い方
update-alternativesの主要なオプションは、
・--install
シンボリックリンクの作成・登録
・--slave
installオプションで作成したシンボリックリンクに従属するシンボリックリンクの作成・登録
・--set
使用するシンボリックリンクの設定(コマンド)
・--config
使用するシンボリックリンクの設定(一覧から選択)
・--display
現在選択されているシンボリックリンクの内容を表示
の5つがあります。下記ではそれぞれのオプションについて説明します。
--install
installオプションを使う時は下記の様に記載します。
sudo update-alternatives --install <作成するシンボリックのパス> <グループ名> <実体へのパス> <優先度>
例えばgccの管理を行う時は、
作成するシンボリックのパス = /usr/bin/gcc
グループ名 = gcc
実体へのパス = /usr/bin/gcc-4.8(管理したいバージョンのパスを設定)
優先度 = 10(任意の数字)
とします。
--slave
slaveオプションを使う時は、下記の様にinstallオプションを登録する時に、関連するシンボリックリンクを全て記載して使います。
sudo update-alternatives --install <作成するシンボリックのパス> <グループ名> <実体へのパス> <優先度>\
--slave <作成するシンボリックのパス> <グループ名> <実体へのパス>\
・・・・・・・・
--slave <作成するシンボリックのパス> <グループ名> <実体へのパス>
例えばgccと連動してg++のバージョンを変更したい場合は、
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 10\
--slave /usr/bin/gcc g++ /usr/bin/g++-4.8
として実行する。
--set
コマンドライン上でグループ名をタイプした時、呼び出される実体が、グループの中のどれを指すか、下記の様にコマンドラインで指定する。
sudo update-alternatives --install <グループ名> <実体へのパス>
例えばgccとタイプした時、gccの4.8を使いたい場合、
sudo update-alternatives --install gcc /usr/bin/gcc-4.8
として実行する。
メモリバンクとメモリインターリーブ
メモリにアクセスする時、メモリはRead / Writeされるための準備時間が必要になります。準備時間中はメモリへのアクセスが止まっている状況なので、処理時間においてこの時間は無駄な時間です。この無駄時間を短縮し、プロセッサのメモリアクセス時間を高速化する技術がメモリインターリーブです。
メモリインターリーブでは、アドレスマッピングとメモリアクセスの方法に、それぞれ下記の様な特徴があります。
・アドレスマッピング:複数のメモリバンクにまたがってアドレスをマッピングする。
・メモリアクセス :複数のメモリバンクに対して連続してアクセス要求を出す。
メモリインターリーブでのアドレスマッピング[1]
メモリインターリーブを使うとき、複数のバンクを1つのバンクのようにして扱います。下図のように、通常1つのバンクにおいてマッピングされる番地は連続です。しかし、メモリインターリーブを使うときは下図の様に、複数のバンクを使うことで連続にマッピングします(1バンクだけみると不連続)。
図1. メモリインターリーブでのメモリアドレスマッピング方法