Raspberry Piでジャイロを使ってみる:ソフトウェア(Python)
前回Adafruit製のジャイロ基板をラズパイに接続してみました:
今回はPythonから基板にアクセスして姿勢情報などを取得してみましょう。
各種ライブラリをインストール
この基板を扱う専用のPython APIである「adafruit-circuitpython-lsm9ds1」がAdafruit社から提供されています。そのライブラリは「CircuitPython」というライブラリに依存しています。CircuitPythonは組み込み系のlinux基板で外部機器を使う汎用のライブラリです。これをラズパイで使うには「adafruit-blinka」という仲介レイヤーのライブラリを通す必要があります:

この3つともインストールする必要がありますが、adafruit-blinkaをインストールするとCurcuitPythonも一緒にインストールされます。順を追って入れてみましょう。
Adafruit-Blinkaをインストール
まずはラズパイのターミナルを起動して、
pip3 install --upgrade setuptools
Python3のsetuptoolsをアップグレードします。続いてadafruitのPythonシェルをアップグレードします:
sudo pip3 install --upgrade adafruit-python-shell
これはsudoをつけてroot権限にして下さい。ローカルユーザ権限にするとblinkaのインストールで失敗してしまいます。
次にadafruit-blinkaをインストールするのですが、これはpipではなくてインストール用のPythonコードが提供されています。wgetでそれをネットからダウンロードしましょう。適当なダウンロード先ディレクトリにcdコマンドで移動してから以下のコマンドでraspi-blinka.pyをダウンロードします:
wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/raspi-blinka.py
長いのでコピペでどうぞ。最後にダウンロードしたraspi-blinka.pyを実行します。これもroot権限です:
sudo python3 raspi-blinka.py
ここですんなりインストールが始まる人はそのまま最後まで進めて下さい。僕はインストール開始後に以下の警告が出ました:

「システムデフォルトのPythonが2.7.18だけどVersion 3にしないといかんよ~」と言われています。なるほど、これは一旦「n」でインストールを中止し、デフォルトのPythonバージョンをチェックしてみましょう。
ラズパイのデフォルトをPython3に変更
ラズパイのシステムデフォルトのPythonバージョンは以下のコマンドでチェックできます:
python --version
僕の場合は…

確かに2.7.18ですね。
実はラズパイ(Bullseye)にはPython2.7とPython3.7の両方が入っていまして、デフォルトではPython2.7が使われるようになっています。そのため「python」とコマンドした時にはPython2.7が実行されるんです。
「python」とコマンドした時に「python3」として扱ってもらうには、シンボリックリンクをpython3に切り替える必要があります。
まず現在のシンボリックリンクを確認してみましょう。実行ファイル関連は/usr/binというディレクトリ下にざーっと並んでいます。その実行ファイルリスト一覧の中で「python」が含まれる物だけ列挙してみます:
cd /usr/bin
ls -l | grep python
2行目のgrepでファイルリストの中でpythonが含まれる行を列挙してくれます。僕の場合以下のようになりました:

注目は真ん中上辺りにある「python -> python2」という一行です。これはコマンドで「python」と打った場合に「python2」と読み替えますよ、という事を表しています。これがシンボリックリンクです。ちなみにpython2はさらにpython2.7に読み替えるようにもなっているみたいですね。
これをpython3と読み替える(上の場合だと実際はpython3.9を実行する)には、既存のシンボリックリンクを一度削除(アンリンク)する必要があります:
sudo unlink python
unlinkコマンドで「python」に紐づいたシンボリックリンクを削除する事が出来ます。この段階でもう一度リストアップしてみると、

python -> python2という一行が無くなりました。この状態だと「python sample.py」のようにコマンドを叩いてもPythonコードを実行できなくなります。
新しくpython -> python3のシンボリックリンクを作成します:
sudo ln -s python3 python
lnコマンドにsオプションを付けるとシンボリックリンクを作成できます。引数のpython3 pythonの順番に気を付けて下さい。逆にすると面倒臭い事になりますので…。
これでpythonと打つとpython3が実行されるように変更出来ました:

リストにもちゃんと変更したシンボリックリンクが追加されていますね。
Adafruit-Blinkaを再度インストール
では再度Adafruit-Blinkaをインストールすべく、raspi-blinka.pyを保存したディレクトリに移動し、
sudo python3 raspi-blinka.py
でインストールしましょう。今度は警告は出ず、つらつらとインストール作業が進みました。最後にリブート確認が出るので「Y」でリブートすればBlinkaのインストールは完了です:

adafruit-circuitpython-lsm9ds1のインストール
続いて今回の基板にアクセスするLSM9DS1ライブラリをインストールします:
pip3 install adafruit-circuitpython-lsm9ds1
これでPythonからジャイロ基板にアクセスする準備が整いました!
Pythonから姿勢情報を取ってみよう
ここまででお膳立てが揃っていますので、ジャイロ等の情報はもう簡単に得る事が出来ます。適当なエディタで以下のPythonコードを作成してみましょう:
import board
import adafruit_lsm9ds1
i2c = board.I2C()
sensor = adafruit_lsm9ds1.LSM9DS1_I2C( i2c )
while True:
print( "Gyro: {0:0.3f}, {1:0.3f}, {2:0.3f}".format( *sensor.gyro ))
このコードを実行すると、ターミナルにジャイロの姿勢情報(XYZ軸回転の角速度(deg/s))が流れ続けます。基板をぐにぐに動かすと値がリアルタイムに変わるのを確認できると思います:

この基板はジャイロだけでなく加速度センサーと磁力計も付いています。また単位は粗いですが温度計もあります。それらの値も以下のように簡単に取得できます:
import board
import adafruit_lsm9ds1
i2c = board.I2C()
sensor = adafruit_lsm9ds1.LSM9DS1_I2C( i2c )
while True:
print( "Acc: {0:0.3f}, {1:0.3f}, {2:0.3f}".format( *sensor.acceleration ))
print( "Mag: {0:0.3f}, {1:0.3f}, {2:0.3f}".format( *sensor.magnetic ))
print( "Tmp: {0:0.3f}".format( sensor.temperature ))
加速度は基板を移動した方向ベクトルに対応した加速度ベクトル、磁力は…ゴメンナサイ、この辺り詳しく無くて良く分かりません(^-^;。温度は0.5度単位のようです。
ここからが本番
基板が返してくれるジャイロと加速度の情報を見ると、そのまま使うに難しい事がすぐに分かります。
ジャイロの姿勢は軸回転速度(rad/s)なので、基板に触れていない時はゼロになるはずですが、実際は、

このようにXYZ軸それぞれ微妙に値が入って来ます。これはセンサーの誤差なので取り除く必要があります。
また加速度(m/s²)に至っては、

動いていないはずなのに良く分からない値が飛び込んできます。これ実は地球の重力加速度を各軸別で検知しているんです。実際一番上の行を各軸のベクトルの大きさとして3軸の合成ベクトルの大きさを求めると、

地球の重力加速度9.8m/s²に近い値になっています。ただ、今センサーは静止させているのでその方向に実際に動いているわけではないです。加速度センサーから搭載している機器の動きによる加速度を得るには、この重力加速度を取り除く必要があるわけです。
そう、ジャイロ・加速度センサーを使う時には細かなキャリブレーションが必須なんです。
という事で次回はキャリブレーションについて見ていく事にします。ではまた(^-^)/