9軸センサーICM-42688+MMC5983 6軸&9軸回転ベクトル&3軸オイラー角 MAX1000Hz同時出力 ROS/ROS2対応 USB接続

はじめに

令和3年度発売の旧型機種のhayate_imu v2は多くの企業、学校法人のユーザー様にご利用いただいたことに、厚く御礼申し上げます。ありがとうございます。旧機種はv2.4までとリリースさせていただいておりますが、いまユーザー様のお手元にある旧バージョン製品のファームバージョンアップは、ユーザー様のもとで実施可能なので、詳細については、別途順次ご案内申し上げます。昨今の半導体ショックにより供給不足、価格高騰などの影響を受ける中、後継機種の開発を続けてきた結果、令和5年4月下旬より、9軸IMU/AHRS haya_imu v3.2の発売をお知らせさせていただきます。

製品紹介

Cortex-M4 (クロック周波数120MHz)、新型6軸IMUのICM-42688(ICM-42688-Pまたは、ICM-42688-V)、高精度3軸AMR方式地磁気センサMMC5983MAの実装により、通常出力モード、デモストレーションモード、キャリブレーションモード(初期バイアス測定)、6軸フュージョン回転ベクトルクォータニオン、9軸フュージョン回転ベクトルクォータニオン、3軸オイラー角の同時出力は最大1000Hzまで可能となります。ROS/ROS2とも対応しており、ドライバーはGithubよりダウンロードして製品とセットでご利用いただけます。

主な仕様

・型番 haya_imu v3.x
・内蔵チップ Microchip Cortex-M4(120MHz)、ICM-42688-VまたはICM-42688-P、MMC5983MA実装
・外部接続 USB2.0+ Type-C、USB+5V給電
・最大出力レート
  - 6軸/9軸フュージョン回転ベクトル四元数 1000Hz
  - 3軸オイラー角  1000Hz
  - 3軸加速度(アクセル)データ  1000Hz
  - 3軸角速度(ジャイロ)データ  1000Hz
  - IMU内部温度データ      1000Hz
  - 3軸地磁気(コンパス)データ  500Hz

・測定レンジ
  - 加速度(アクセル)センサ  ±8g
  - 角速度(ジャイロ)センサ  ±2000dps
  - 地磁気(コンパス)センサ  ±800µT

・バイアス測定補正 初期バイアス測定、動作時即時測定、内蔵補正機能あり
・消費電力 150mW以下(環境温度21℃ 実測値)
・寸法 38.0mm × 39.0mm × 4.8mm(突起物含む)
・取付穴 M3x4、隣り合う穴の中心間距離32.0mm

主な特長

・サービスモード 通常出力モード、デモンストレーションモード、キャリブレーションモード
・結果出力 6軸フュージョン回転クォータニオン、9軸フュージョン回転クォータニオン、3軸オイラー角1KHzまで同時出力、結果出力レートに関わらずIMU/地磁気センサのデータサンプリング周波数、フュージョン周波数は常に1000Hz/500Hzに設定済み
・初期バイアス測定 使用環境変化あった際に利用可能なキャリブレーションモードで最短数分程度で初期バイアス測定完了、MCUフラッシュに自動的に保存して、動作時に読み込んで即時バイアス測定&補正あり
・地磁気センサ温度補償 地磁気センサは、計測時間1msにわたるセットリセット計測(温度補償機能)使用済み
・磁気外乱による干渉 受けにくいことが当社実験(磁束密度約2G)にて確認済み
・ROS/ROS2対応 本体にはROS/ROS2ライブラリを実装せず、対向装置にドライバーインストールにより実現

詳細情報

【製品名称】haya_imu v3.x
【開発会社】ROBOT翔(株式会社翔雲)
【発売時期】令和5年4月下旬
【商品情報】9軸センサー6軸&9軸回転ベクトル 3軸オイラー角 MAX1000Hz同時出力 ROS/ROS2対応 USB接続 | ROBOT翔

参考情報

エンコーダ付きDCモータPID制御の実験-haya_imu応用例

4+

ロボット・ドローン部品お探しなら
ROBOT翔・電子部品ストア

rosserialをSTM32F4に対応させてみる

はじめに

rosserialは、ROSノードらをシリアルで繋ぐ役割を果たすROSパッケージとしてよく知られている。但し、ArduinoノードとしてSTM32F4は公式に対応されておらず、今回はROS melodicベースのArduinoノード(STM32F411CEU6搭載の開発ボード、通称Balck pill)にrosserialを立ち上げてみた。ソースコードはGithubに公開済み。ROS melodicにおいて動作確認済み。

ソースコード

https://github.com/soarbear/stm32f4_rosseialリポジトリーとして公開済み。

環境

ターゲットボード(MCU) Black pill(STM32F411CEU6実装)
コンパイル環境 Arduino V1.8.13
テスト環境 Ubuntu 18.04 / ROS melodic

参考文献

rosserial melodic-devel branch@Github

0

ロボット・ドローン部品お探しなら
ROBOT翔・電子部品ストア

外部32.768KHzクリスタルからSAMD21クロック設定まで

はじめに

外部32.768KHz水晶発振子からSAMD21クロックを48MHzに設定する手順、ソースをメモにしておく。

設定手順

1. DFLL48Mリファレンスとして使用されるXOSC32Kクロック(オンボード外部32.768Hzクリスタル)を有効にする。
2. XOSC32Kを汎用クロックジェネレーター1として使用する。
3. 汎用クロックジェネレータ1を汎用クロックマルチプレクサ0(DFLL48Mリファレンス)のソースとして使用する。
4. DFLL48Mクロックを有効にする。
5. 汎用クロックジェネレータ0をDFLL48Mに切り替える。
6. CPUのクロックは48MHzで動作する。

ソースコード

下記参考資料から抜粋したソースは以下のとおり。

/* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */
NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val ;

/* Turn on the digital interface clock */
PM->APBAMASK.reg |= PM_APBAMASK_GCLK ;

/* Enable XOSC32K clock (External on-board 32.768Hz oscillator) */
SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */
                       SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K ;
SYSCTRL->XOSC32K.bit.ENABLE = 1 ; /* separate call, as described in chapter 15.6.3 */
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 )
{
  /* Wait for oscillator stabilization */
}

/* Software reset the module to ensure it is re-initialized correctly */
GCLK->CTRL.reg = GCLK_CTRL_SWRST ;
while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) )
{
  /* Wait for reset to complete */
}

/* Put XOSC32K as source of Generic Clock Generator 1 */
GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) ; // Generic Clock Generator 1
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
  /* Wait for synchronization */
}

/* Write Generic Clock Generator 1 configuration */
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC32K ) | // Generic Clock Generator 1
                    GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
//                  GCLK_GENCTRL_OE | // Output clock to a pin for tests
                    GCLK_GENCTRL_GENEN ;
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
  /* Wait for synchronization */
}

/* Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference) */
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GENERIC_CLOCK_MULTIPLEXER_DFLL48M ) | // Generic Clock Multiplexer 0
                  GCLK_CLKCTRL_GEN_GCLK1 | // Generic Clock Generator 1 is source
                  GCLK_CLKCTRL_CLKEN ;
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
  /* Wait for synchronization */
}

/* Enable DFLL48M clock */  
SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
  /* Wait for synchronization */
}
SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 31 ) | // Coarse step is 31, half of the max value
                       SYSCTRL_DFLLMUL_FSTEP( 511 ) | // Fine step is 511, half of the max value
                       SYSCTRL_DFLLMUL_MUL( (VARIANT_MCK + VARIANT_MAINOSC/2) / VARIANT_MAINOSC ) ; // External 32KHz is the reference
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
  /* Wait for synchronization */
}

/* Write full configuration to DFLL control register */
SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
                         SYSCTRL_DFLLCTRL_WAITLOCK |
                         SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
  /* Wait for synchronization */
}

/* Enable the DFLL */
SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ;
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKC) == 0 ||
        (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKF) == 0 )
{
  /* Wait for locks flags */
}
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
  /* Wait for synchronization */
}

/* Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz. */
GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_MAIN ) ; // Generic Clock Generator 0
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
  /* Wait for synchronization */
}

/* Write Generic Clock Generator 0 configuration */
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock Generator 0
                    GCLK_GENCTRL_SRC_DFLL48M | // Selected source is DFLL 48MHz
//                  GCLK_GENCTRL_OE | // Output clock to a pin for tests
                    GCLK_GENCTRL_IDC | // Set 50/50 duty cycle
                    GCLK_GENCTRL_GENEN ;
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
  /* Wait for synchronization */
}

参考資料

ArduinoCore-samd | Github

0

ロボット・ドローン部品お探しなら
ROBOT翔・電子部品ストア

9軸IMUセンサ 6軸/9軸フュージョン 低遅延 USB出力 補正済み ROS対応

V2.5 NEW主な変更点

【V2.4】令和5年3月にリリース済み
較正モードの追加により、ジャイロスコープ、加速度センサ、地磁気センサの初期バイアスは出荷時の測定のみならず、ユーザー様のもとでも測定することはできる。 ※ ユーザー様のお手元にある旧バージョン製品のファームウェアのバージョンアップは、ユーザー様のもとで実施可能なので、詳細については、別途順次ご案内する。

【V2.5】令和5年12月にリリース済み
TDK Smart Motion DMPコードリビジョンに伴うファームウェアのアップデート、ROSパッケージ更新なし。
※ ユーザー様のお手元にある旧バージョン製品のファームウェアのバージョンアップは、ユーザー様のもとで実施可能なので、令和5年12月末までご案内済み。

はじめに

9軸IMU(型番hayate_imu)は、コロナ禍の中で開発した新商品、令和3年3月まで開発~製造、令和3年4月上旬の出荷と予定して、皆さんの学術研究にお役に立てるようと願って、どうぞご検討ご利用のほど宜しくお願い申し上げます。

製品紹介

9軸センサhayate imu、低消費電力プロセッサーCortexM0+、TDK MPU-9250後継機種である、1.71V低電圧で動作可能なICM-20948使用、6軸/9軸融合クォータニオン(四元数)はFPGA on chip(DMP3)から低遅延出力、別途ソフトでフュージョン必要なし、最大出力レート225Hz、同時に加速度(アクセル)3軸データ225Hz、角速度(ジャイロ)3軸データ225Hz、地磁気(コンパス)3軸データ70Hzまで出力可能、補正済み、ROS対応。ロボット、ドローンなど低遅延が必要とされる科学研究、電子機械の検証試作ヘの活用が期待される。

主な仕様

・ 型番 hayate_imu rev.C 6軸フュージョン or ver.B 9軸フュージョン切替可能
・ 内蔵チップ Cortex-M0+、TDK Invensense ICM-20948(9軸)実装 ※1
・ 外部接続 USB Type-Cコネクタ、USB +5V給電 ※2 ※3
・ 最大出力レート ※4
  - 6軸フュージョン or 9軸フュージョン回転ベクトル四元数 225Hz
  - 加速度(アクセル)3軸センサ  225Hz
  - 角速度(ジャイロ)3軸センサ  225Hz
  - 地磁気(コンパス)3軸センサ  70Hz

・ 測定レンジ
  - 加速度(アクセル)センサ  ±16g
  - 角速度(ジャイロ)センサ  ±2000dps
  - 地磁気(コンパス)センサ  ±4900µT

・ 消費電力 50mW以下(環境温度21℃の実測値)
・ 寸法 30mm × 31.4mm × 4.8mm(突起物含む)
・ 重量 4g以下
・ 取付穴 M3x4、隣り合う穴の中心間距離24.4mm

※1 内蔵Cortex-M0+とICM-20948間インターフェースはSPI(4Mbps)使用、加速度センサ(消耗)、角速度センサ(温度、ドリフト)、地磁気センサ(磁気変動)にダイナミック補正。
※2 USB対向装置OS環境 Ubuntu 16.04以降推奨。
※3 USB対向装置ROS環境 Kinetic以降推奨。
※4 最大出力レートはhayate imuの実力値、IMU対向装置(USB接続先)での実効値はその装置のリソース(CPUクロック周波数、メモリ容量・スピード)に関わる。

デモ情報

hayate_imu ROSパッケージ | Githubリポジトリ

9軸IMUセンサ ICM-20948内蔵 6軸/9軸シュージョン 出力レート225Hz 低遅延 USB出力 ROS対応 | YouTube

9dof_hayate_imu_youtube
9dof_hayate_imu_youtube

販売情報

【製品名称】hayate_imu rev.C 6軸フュージョン or ver.B 9軸フュージョン
【開発会社】ROBOT翔(株式会社翔雲)
【発売時期】令和3年4月上旬頃
【取扱店舗】9軸IMUセンサ 6軸/9軸フュージョン 低遅延 USB出力 補正済み ROS対応 | ROBOT翔

後継機種

9軸センサーICM-42688+MMC5983 6軸&9軸回転ベクトル&3軸オイラー角 MAX1000Hz同時出力 ROS/ROS2対応 USB接続

参考資料

Migrating from MPU-9250 to ICM-20948-InvenSense
http://wiki.ros.org/ja/9dof_hayate_imu

関連記事

エンコーダ付きDCモータPID制御の実験-hayate_imu応用例
9軸IMUセンサ ICM-20948をロボットに組み込もう
オイラー角~ジンバルロック~クォータニオン
ROS・Unity・ロボット・ドローン姿勢制御に関わるクォータニオン

2+

ロボット・ドローン部品お探しなら
ROBOT翔・電子部品ストア

カルマンフィルタの導出

はじめに

wiki: 「カルマンフィルタ\((Kalman Filter, KF\)と略す\()\) は、誤差のある観測値を用いて、ある動的システムの状態を推定あるいは制御するための、無限インパルス応答フィルタの一種である」。観測値に観測雑音、状態予測値にシステム雑音があって場合により時間とともに誤差がドンドン蓄積してそのまま使えないので、観測と予測のガウス性を利用した線形センサデータフュージョンがカルマンフィルタの原点である。

キーワード

状態空間モデル、線形システム、ガウス分布、最小二乗法、最小解析誤差(共分散行列)、予測値、観測値、推定値、カルマンフィルタ、拡張カルマンフィルタ

状態空間モデル

時系列解析の中で、予測値と観測値の間何らかの因果関係を見つけて、何らかの方法でそれらのデータを絡んでモデル化して状態を推定していく。ここで汎用的な状態方程式観測方程式は以下の式にする。
$$\begin{eqnarray*}&& x_t = F_{t-1}(x_{t-1} ) + q_{t-1} \space \space * \\&& y_t = H_t(x_t) + r_t\end{eqnarray*} $$
ただし、システム雑音、観測雑音\((q_t, r_t)\)は期待値が\(0\)、分散が\((Q_t, R_t)\)の独立正規分布(ガウス分布)にする。
$$\begin{eqnarray*}&& p(q_t) ~ N(0,Qt)\\&& p(r_t) ~ N(0,Rt)\\&& E[q_t r_t]=0 \end{eqnarray*}$$

基本原理

カルマンフィルタの原理は以下のイメージに示すように、最小解析誤差推定(最小二乗)から予測値、観測値をそれぞれの割合\(I-K_t H_t , K_t\)で線形合成した値を状態推定値にする。

kalman_filter_principle_n
kalman_filter_principle_n

式の導出

ベイズ定理やガウス分布からいくつかの導出方法はあるが、本記事は最もシンプルな最小二乗法を用いて、カルマンフィルタの黄金\(5\)式を誘導してみよう。

線形システム

\(F(⋅)、H(⋅)\)とも線形関数の場合、以下線形カルマンフィルタの誘導となる。例えば\( F(x)=Ax+B\)、\(A、B\)とも実数行列、\(x\)は変数行列とする。

まずは、予測値(数学期待)を求めるのは出発点なので、すべては以下の式(再掲)から始まる。
$$ x_t = F_{t-1}(x_{t-1} ) + q_{t-1} \space \space * $$
推定値\(\hat{x}_t\)は、重み\(K_t\)の調整で予測値\(x_t\)と観測値\(y_t\)の間にあろうとして、以下線形表現とされる。
$$ \hat{x}_t = x_t + K_t(y_t-H_t x_t) \\
{\small = F_{t-1}(x_{t-1}^{true}+p_{t-1}) + q_{t-1}+ K_t\{(H_t x_t^{true}+r_t) }\\
{\small – H_t(F_{t-1}(x_t^{true}+p_{t-1})+q_{t-1})\} }\\
{\scriptsize = x_t^{true}+F_{t-1}p_{t-1}+q_{t-1}+K_t(r_t-H_t F_{t-1}p_{t-1}-H_t q_{t-1}) }$$
この重み\(K_t\)は、またカルマン係数、カルマンゲインと呼ばれる。

解析誤差(共分散行列)は以下の式より求める。
$$ P_t = E[(\hat{x}_t-x_t^{true})^2] \space \space \\
{\scriptsize = E[(F_{t-1}p_{t-1} + q_{t-1} + K_tr_t-K_t H_t F_{t-1}p_{t-1}-K_t H_t q_{t-1})^2] }\\
{\scriptsize = F_{t-1}P_{t-1}F_{t-1}^T-2F_{t-1}P_t F_{t-1}^TH_t^T K_t^T+Q_{t-1}-2Q_{t-1}H_t^T K_t^T }\\
{\scriptsize + K_t R_t K_t^T+K_t H_t F_{t-1}P_{t-1}F_{t-1}^TH_t^T K_t^T+K_t H_t Q_{t-1}H_t^T K_t^T \space \space \star } $$

ここから二乗の最小化より解析誤差(共分散\(P_t\))を最小値に至る\(K_t\)を求める。
$$ \frac {\partial P_t } {\partial K_t } = 0 \\
{\small \frac {\partial P_t } {\partial K_t } = -2F_{t-1} P_{t-1} F_{t-1}^T H_t^T -2Q_{t-1}H_t^T +} \\
{\scriptsize 2K_t R_t + 2K_t H_t F_{t-1} P_{t-1} F_{t-1}^T H_t^T +2K_tH_tQ_{t-1}H_t^T = 0 \space \space \star \star } $$
上式の最初の二項目までを等式の右に移して、残りの項らから\(K_t\)を抽出しておくと、下式のように\(K_t\)は求められる。
$${\small K_t = (F_{t-1}P_{t-1}F_{t-1}^T + Q_{t-1}) H_t^T \{R_t + }\\
{\small H_t(F_{t-1}P_{t-1}F_{t-1}^T+Q_{t-1})H_t^T\}^{-1}} $$

これで、状態予測時、式\(\star\)及び式\(\star\star\)から得られる\({\small P_t = F_{t-1}P_{t-1}F_{t-1}^T + Q_{t-1} \space ** }\)を上式に代入して、\( K_t\)は以下のように簡略化される。
$$ K_t = P_t H_t^T (R_t + H_t P_t H_t^T)^{-1} \space \space ** \space * $$
これから観測値を入れて、\(K_t\) を使って予測値を更新する(推定値を求める)。
$$ \hat{x} = x_t + K_t(y_t – H_t x_t) \space \space **** $$
推定値を求めたら、続いて\(P_t\)を更新する。前述の\(\star\)式の展開項らに類似して、最後の式は誘導される。
$$ \hat{P}_t = (I – K_t H_t)P_t \space \space **** \space * $$
\(\hat{P}_t\)は、\(P_t\)より\(K_t H_t P_t\)だけ\(0\)に近づいて、つまり\(x_t\)より\(\hat{x}_t\)は知られかねる「真値」に接近になって、\(K_t\)の効果が現れることに違いない。\(\hat{P}_t\)は\((t+1)\)時刻の\(P_t\)として利用される。また、式\(* \space ~ \space **** \space *\)はカルマン黄金\(5\)式とされる。

非線形システム

前述線形カルマンフィルタの\(F(⋅),H(⋅)\)は非線形関数になった場合、\(f(⋅),h(⋅)\)と記す。ティラー展開の最初の\(2\)項のみを使って、如何なる非線形関数とも線形化されるが、\(3\)項目以降は切り捨てられるので誤差を招くことにもなる。例えば、\(f(x)=Ax^2+B\)、\(A,B\)とも実数行列、\(x\)は変数行列として、ティラー展開の最初の\(2\)項のみを使って、即ち\( f(a)+\frac {\partial {f(x)}} {\partial {x}}|_{x=a}(x-a) \) のように\(f(x)\)を、\(Aa^2+B+2Aa(x-a)\)に線形化される。状態予測の際、線形カルマンフィルタの\(F\)を\(f\)、観測値の取り入れる際、線形カルマンフィルタの\(H\)を\(h\)に、共分散行列の計算の際、\(F,H\)を\( \frac {\partial {f(x)}} {\partial {x}}|_{x=x_{t-1}}, \frac {\partial {h(x)}} {\partial {x}}|_{x=x_t}\)に置き換えて済む。

これまでカルマンフィルタの誘導で、逐次状態値推定の手順を以下のとおり整理しておく。

逐次状態推定の手順

時系列の状態推定に応用して、以下状態予測\(Predict\)→測定更新 \(Measurement \space Update\)→状態更新\(Correct, Update\)→時間更新\(Time \space Update\)→次の状態予測\(Predict\)→\(…\)の繰り返すことによって、時系列とともに状態の数学期待最小解析誤差(共分散)を求める手順となる。

Step0=パラメータ初期化(t=0)

状態推定(数学期待)、解析誤差共分散の初期化
$$\begin{eqnarray*}&& \hat{x}_0 = E[x_0]\\&& \hat{P_0} = E[(x_0-\hat{x}_0)(x_0-\hat{x}_0)^T]\end{eqnarray*}$$

Step1=状態値、共分散行列予測(t>0)

$$\begin{eqnarray*}&& x_t = F_{t-1}(\hat{x}_{t-1})\\&& P_t = F_{t-1}\hat{P}_{t-1}F_{t-1}^T + Q_{t-1}\end{eqnarray*}$$
ただし、\(x_t\)は予測値、\(P_t\)は事前共分散行列、\(Q_{t-1}=E[q_{t-1}q^T_{t-1}]\)

Step2=カルマンゲイン、状態値、共分散行列更新

$$\begin{eqnarray*}&& K_t = P_t H_t^T (H_t P_t H_t^T + R_t)^{-1}\\
&& \hat{x_t} = x_t + K_t(y_t – H_t x_t)\\&&\hat{P}_t = (I-K_t H_t) P_t \end {eqnarray*}$$
ただし、\(K_t\)はカルマンゲイン、\(\hat{x}_t\)は状態推定値、\(\hat{P}_t\)は事後共分散行列、\(R_{t}=E[r_{t}r^T_{t}]\)

KFフローチャート

Kalman_Filter_Flowchart_2
Kalman_Filter_Flowchart_2

拡張カルマンフィルタ

拡張カルマンフィルタ\((Extended Kalman Filter, EKF\)と略す\()\)は、非線形フィルタリングである。前述した状態方程式、観測方程式より、以下の状態空間モデルの\(f(⋅)\)または\(h(⋅)\)が非線形関数であり、拡張カルマンフィルタが適用される。テイラー展開より、2次微分以降の項目を省略して、非線形である\(f(⋅), h(⋅)\)の1次微分を線形化とし、前述したカルマンフィルタのアルゴリズムが適用可能となる。しかし、\(f(⋅), h(⋅)\)の微分では\(f(⋅), h(⋅)\)の一部しか表現できず、この線形化処理(1次微分)が誤差を招くことになる。
$$\begin{eqnarray*}&& F_{t-1} =\frac{\partial f_{t-1}(x)}{\partial x}|_{x=\hat{x}_{t-1}}\\&& H_{t} =\frac{\partial h_{t}(x)}{\partial x}|_{x=\hat{x}_{t}}\end{eqnarray*}$$

状態空間モデル

$$\begin{eqnarray*}&& x_t = f_{t-1}(x_{t-1}) + q_{t-1}\\&& y_t = h_t(x_t) + r_t\end{eqnarray*}$$

Step0=パラメータ初期化(t=0)

$$\begin{eqnarray*}&& \hat{x}_0 = E[x_0]\\&& \hat{P}_0 = E[(x_0-\hat{x_0})(x_0-\hat{x_0})^T]\end{eqnarray*}$$

Step1=状態値、共分散行列予測(t>0)

$$\begin{eqnarray*} && x_t = f_{t-1}(\hat{x}_{t-1})\\&& P_t = F_{t-1}\hat{P}_{t-1}F_{t-1}^T + Q_{t-1}\end{eqnarray*}$$
ただし、\(x_t\)は予測値、\(P_t\)は事前共分散行列、\(Q_{t-1}=E[q_{t-1}q^T_{t-1}]\)

Step2=カルマンゲイン、状態値、共分散行列更新

$$\begin{eqnarray*}&& K_t = P_t H_t^T(H_t P_t H_t^T + R_t)^{-1}\\
&& \hat{x_t} = x_t + K_t(y_t – h_t x_t)\\&&\hat{P_t} = (I-K_tH_t) P_t \end{eqnarray*}$$
ただし、\(K_t\)はカルマンゲイン、\(\hat{x_t}\)は状態推定値、\(\hat{P_t}\)は事後共分散行列、\(R_t=E[r_t r^T_t]\)

EKFフローチャート

Extended_Kalman_Filter_Flowchart_2
Extended_Kalman_Filter_Flowchart_2

拡張カルマンフィルタを6軸IMUへの適用

6軸IMUへの適用例として、本サイトの記事 6軸IMU~拡張カルマンフィルタ に載ってある。

カルマンフィルタの再考

カルマンフィルタでは、状態推定値を予測結果\(x_t\)(実装例ではジャイロセンサーデータ)と観測データ\(y_t\)(実装例では加速度センサデータ)の線形結合でデータ同化とし,その解析誤差(共分散)を最小にする推定法だと分かる。これは、状態方程式、観測方程式とも線形関数(非線形関数の場合、線形化する)、システム誤差、観測誤差の数学期待が\(0\)の正規分布との前提条件から由来した推定法である。しかし、カルマンフィルタをかけることで、状態推定値は予測結果と観測データの間にあるのは、真値からかなり乖離してしまう場合にあるのか。これはシステム誤差と観測誤差が無相関かつ直交という前提から、勿論推定値が真値と観測値の間にある、実環境の真値は分からないので推定値は真値と見なす結論に至る考えである。パーフォーマンスの検証は、比較的精確な実験環境(比較用の高精度ジャイロセンサ、加速度センサ、エンコーダ、モータ)がないと、実は容易ではない。というよりも、シミュレーションをかけてカルマンフィルタのアルゴリズムを検証するのが、確実に可能である。

参考文献

1-wikipedia: カルマンフィルタオイラー角
2-Greg Welch氏、Gary Bishop氏: An Introduction to the Kalman Filter
3-田島洋氏: マルチボディダイナミクスの基礎―3次元運動方程式の立て方

関連記事

オイラー角~ジンバルロック~クォータニオン
SLAM~拡張カルマンフィルタ
SLAM~Unscentedカルマンフィルタ
9軸IMUセンサ 6軸/9軸フュージョン 低遅延 USB出力 補正済み ROS対応
9軸IMU ICM-20948をロボットに組み込もう
YDLIDAR G4=16m 薄型 ROS対応SLAM LIDAR
研究開発用 台車型ロボット キット

4+

ロボット・ドローン部品お探しなら
ROBOT翔・電子部品ストア