Japanese Stable VLMをローカル環境で使ってみる

 

1. はじめに

Stability AIが2023年11月に発表した、画像に日本語でキャプショニングしてくれるJapanese Stable VLMをローカル環境で試してみました。

VRAM16GBでも一応動きました! ja.stability.ai

 

2. PCのスペック

CPU:i5-13500

GPU:RTX4070TI SUPER (VRAM 16GB)

RAM:32GB

OS:ubuntu 22.04 LTS

 

3. 環境構築

3.1 ライブラリのインストール

transformers, accelerate, sentencepiece, protobuf, pillow, huggingface_hubをインストールしました。

 pip install transformers accelerate sentencepiece protobuf pillow huggingface_hub 

 

int8でモデルを読み込むために必要なbitstandbytesをインストールしました。

 pip install -i https://pypi.org/simple/ bitsandbytes 

 

3.2 作業フォルダの作成

図1のフォルダ構成としました。

python フォルダには、4章で作成するpythonコードを入れます。

pictures フォルダには、推論に用いる画像を入れます。

model フォルダには、3.3節でダウンロードするモデルを入れます。

図1 フォルダ構成

 

3.3 モデルのダウンロード

huggingfaceからモデルをダウンロードし、3.2節で作成したmodelフォルダに保存します。

今回はfp16のモデルをint8で読み込むので、model.fp16-0000x-of-00004.safetensorsをダウンロードします。model-0000x-of-00007.safetensorsはダウンロードしません。

他のサイズが小さいファイルは、どれが必要なのか考えるのが面倒だったので全てダウンロードしました。

huggingface.co

 

4. Pythonコード

公式の使用例とnpakaさんの記事を参考にpythonコードを作成し、3.2節で作成したpythonフォルダに、StableVLM_test.pyとして保存しました。

note.com

 

from transformers import AutoTokenizer, AutoModelForVision2Seq, AutoImageProcessor
from PIL import Image

# モデルとトークナイザーとプロセッサーの準備
model = AutoModelForVision2Seq.from_pretrained("/home/username/StableVLM/model",
 trust_remote_code=True, load_in_8bit=True, variant="fp16", max_memory='15GB', low_cpu_mem_usage=True)
tokenizer = AutoTokenizer.from_pretrained("/home/username/StableVLM/model")
processor = AutoImageProcessor.from_pretrained("/home/username/StableVLM/model")

# 入力画像の準備
image_path = "/home/username/StableVLM/pictures/" + input("画像.拡張子:")
image = Image.open(image_path).convert("RGB")

# プロンプトの準備
instructions = input("指示:")
inputs = input("入力:")

prompt = """
以下は、タスクを説明する指示と、文脈のある入力の組み合わせです。要求を適切に満たす応答を書きなさい。

### 指示: 
"""

prompt = prompt + instructions + "\n\n### 入力:\n" + inputs + "\n\n### 応答:\n"

#確認用にプロンプトをprint
print("\n-----プロンプトは下記です-----" + prompt + "-----プロンプト終わり-----\n") 

# 入力の準備
inputs = processor(images=image, return_tensors="pt")
text_encoding = tokenizer(prompt, add_special_tokens=False, return_tensors="pt")
inputs.update(text_encoding)

# 推論の実行
outputs = model.generate(
    **inputs.to(device=model.device),
    do_sample=False,
    num_beams=5,
    max_new_tokens=128,
    min_length=1,
    repetition_penalty=1.5,
)
generated_text = tokenizer.batch_decode(outputs, skip_special_tokens=True)[0].strip()
print(generated_text)

 

6, 7行目において、fp16のモデルを8bitで読み込むこと、メモリ使用量の最大値は15GBとすることを指定しています。

6, 8, 9, 12においてパスを指定しているので、環境に合わせて適宜書き換えてください。

 

5. 動作確認

5.1 使い方

Terminalを開き、4章で書いたコードを実行します。

 python ~/StableVLM/python/StableVLM_test.py 

 

推論に用いたい画像のファイル名を指定し、エンターキーを押します。

次に、プロンプトの指示を記入し、エンターキーを押します。

最後に、プロンプトの入力を記入し、エンターキーを押します。

プロンプトの応答は、指定しないことにしています。

5.2 使用例

5.2.1 使用例その1

図2に、実行時のTerminal画面例を示します。
画像のファイル名はtrack.jpg, プロンプトの指示は「画像を詳細に述べてください。」, プロンプトの入力はなしとしました。

図3にtrack.jpgを示します。

推論結果は「道路脇に緑色のトラックが停まっている」です。トラックは中央分離帯寄りの写真におり、実際は走行中と思われますが、大体あっているのでヨシ👈

 

図2 実行時のTerminal画面例

 

図3 track.jpg

 

VRAMの使用量は最大15GB程度で、推論にかかった時間は数秒でした。

なお、本記事中で与えた画像は、全てデジカメで撮影したものを1920x1280pxにリサイズした画像です。元の5472x3648pxのまま与えると、書いていないことを答える傾向にある気がしたため、リサイズしました。

 

5.2.2 使用例その2

画像の内容について質問することも可能です。

プロンプトの指示「与えられた画像を下に、質問に答えてください。」

プロンプトの入力「船の色は何色ですか。」

与えた画像は、図4に示すレインボーブリッジ遊歩道から撮影した東海汽船ジェットフォイルです。

推論結果「白とピンクです。」

正解ヨシ👈

図4 レインボーブリッジ遊歩道から撮影した東海汽船ジェットフォイル

 

5.2.3 使用例その3

プロンプトの指示「与えられた画像を下に、質問に答えてください。」

プロンプトの入力「何匹の鳥が写っていますか。」

与えた画像は、図5に示す洗足池で撮影したカルガモです。合計8匹ですね。

推論結果「5匹です。」

残念ながら不正解です。

 

図5 洗足池で撮影したカルガモ

 

6. おわりに

今回は、Japanese Stable VLMをVRAM16GBのローカル環境で試してみました。

触ってみた結果としては、一応それっぽい結果が出ないこともないという感じでした。

今後は、移動ロボットで撮影した画像を推論させ、遊びたいです(テキトー)

ミニPCをモバイルバッテリーからのUSB PD給電で使ってみた (自作移動ロボット用)

はじめに

 最近、図1に示す移動ロボットを自作して遊んでいます。UbuntuとROS 2の環境をミニPC上に構築し、LiDARやオドメトリ情報を入力してごにょごにょしてます。

 ミニPCへの電力供給源としてモバイルバッテリーを使ってみた結果、問題なく使えたかどうかお伝えします。移動ロボットを自作する方の参考になれば幸いです。(同様の構成を試して動かなくても責任は取らないです)

 

図1 自作移動ロボット

 

使用するPC

 minisforumのUN305Cを使用しています。スペックは下記です。ちなみにもう廃版のようです。図2に、UN305CのUSB Type-Cポートを示します。このポートは、USB PD給電を受けることができます。

 i3-N305は、ミニPCに最近よく使われているN100の上位っぽい製品です。i3と名前がついていますが、PコアはなくEコアのみ8個の構成です。消費電力が低く、なおかつそこそこ使えそうなので選びました。

 

CPU:intel i3-N305(8コア8スレッド)

GPU:内臓GPUのみ

RAM:16 GB

SSD:256 GB

OS:購入時のWindows11を削除し、Ubuntu 22.04 LTSをインストールし使用

 

Ubuntu 22.04 LTSのインストール時、グラフィックドライバ周りのトラブルがあり、解決に時間を要しました。現在も、2つあるHDMIポートのうち片方が使えません。このPCにLinuxを入れるのはおすすめできません。
(公式非対応なのでMinisforumが悪いわけではありません)

 

図2 UN305CのUSB Type-C ポート

 

 なお、必要なUSB PD給電の出力は、ホームページに明記がありませんでした。参考として、付属のACアダプター出力は36 W(12 V、3 A)です。なお、最大33 W出力が可能なUSB PD充電器であるAnker 323 Chargerを使用すると、起動はできるものの高負荷時には落ちることがありました。

 カスタマーサポートに質問したところ、通常ならば65 W以上の出力が可能なUSB PD給電を用いると問題なく使えるとの返答がありました。

 

使用するモバイルバッテリー

 カスタマーサポートへの問い合わせ結果を受けて、65 W出力が可能なモバイルバッテリーであるAnker 537 Power Bankを選びました。大きいですが自作移動ロボットに入るサイズなのでヨシ👈

 

サイズ:約160 x 85 x 27 mm

出力:USB Type-C 単ポート使用時に最大65 W

容量:24000 mAh

 

使用テスト

テスト① 起動テスト

 まずは、最低限起動できることを確認しました。

 事前にUbuntu上の電源モードをバランスに設定してシャットダウンし、ACアダプタのケーブルを抜いてモバイルバッテリーを接続しました。電源ボタンを押したところ、正常に起動しました。

テスト② 高負荷テスト

 次に、高負荷時に落ちないことを確認しました。Ubuntu上の電源モードをパフォーマンスに設定した上で、Terminal上で下記のコマンドを打ち、8コア中6コアのCPU使用率が100 %となるように負荷 をかけました。その結果、落ちることなく正常に動作し続けました。

 stress -c 6 

 

テスト③ 使用可能時間テスト

 最後に、何時間程度使用できるかを確認しました。Ubuntu上の電源モードをバランスに設定した上で、ミニPCに自作基板およびLiDARを接続しました。

※自作基板は、車輪の回転数制御、mems 9軸センサ値の読み取り等を行い、消費電力は1 W未満。LiDARは消費電力2 W程度。

 また、自作基板とLiDARそれぞれを制御するROS2 ノードを起動しました。このとき、CPU使用率は全コアが50 %程度でした。満充電状態のモバイルバッテリーを接続し、残量インジケータが3/4になるまでに、約3.5時間かかりました。

※残量が4つのLEDで表示されるので、バッテリー切れのぎりぎりまで使用することはできない。ぎりぎりを攻めたいなら、残量が液晶に数値で表示される機種を買おう。

 

 リチウムイオン電池の電圧を3.7 V、放電時の電力変換効率を80 %としたとき、今回のモバイルバッテリーの利用可能な電力量は約71 Whです。3.5時間でその3/4を消費したと仮定すると、平均消費電力は約15 Wであり、自作基板とLiDAR消費分を引くと、約12 Wです。

 intel i3-N305のTDPは15 Wであること、CPU使用率は約50 %であったこと、CPU以外にもRAM、SSD、冷却FAN等が電力を消費することを考えると、計算は合いますね。

 

おわりに

 今回は、自作移動ロボット用に買ったミニPCを、モバイルバッテリーからのUSB PD給電で動かしてみました。結果として無事に動き、CPU使用率50 %程度ならば3.5時間使用できました。

 みんなもミニPCを使ってロボットをつくろう! いや、Jetsonかラズパイでよくね

MATLABを用いた小型ロケットのロール制御系設計

1. はじめに

1.1 ご挨拶

ごめんなさい。全然書き終わりませんでした...

途中までですが、ぜひご覧ください。

 

本記事は、MATLAB/Simulink Advent Calendar 2023の12日目です。

東工大ロケットサークルCREATEが2022年11月に打ち上げました、小型ロケットC-59Jのロール制御系について紹介します。

MATLABを用いて設計したロール制御系について、主に次の3つの観点から記述しました。

  • 制御対象のモデル化とパラメータ推定
  • 制御ゲインの決定
  • 安定性評価

ロケットの機体構造については、ぜひこちらの記事をご覧ください。

tgkhtknk.hatenablog.com

 

1.2 背景

全国にはいくつもの学生ロケットサークルがあり、東京都大島町秋田県能代市和歌山県和歌山市などにて、共同打上実験を年に数回実施しています。

規模としましては、全長1~2m程度のロケットを、高度数百~数千mへ打ち上げています。

これまで、ロール制御 (機軸方向まわりの回転角制御) に挑戦したサークルは複数ありますが、制御系の設計法と制御結果について詳しく紹介した例は見当たりません。

ロケットの製作には半年~1年程度を要し、本番は1発勝負であるため、制御ゲインの試行錯誤的な調整ができない難しい環境にあります。

そこで本記事では、成功裡に終えたC-59Jのロール制御系に焦点を当てその詳細を紹介することで、今後ロール制御に挑戦する方々にとって有益な情報になればと思います。

さらに、MATLAB/Simunik界隈の皆様に向け、MATLABを使用して達成した成果を共有したいと思います。

 

2. ロール制御用ハードウェアの構成

図1に、小型ロケットC-59Jのうち、ロール制御に関連するハードウェアの模式図を示します。

ロールモーメントは、2枚の動翼が発生させる揚力により得ます。

2枚の動翼は、傘歯車を介して1個のMAXON社製エンコーダ付きギアモータにより駆動します。エンコーダには512pulse/countの2相インクリメンタルエンコーダを用い、ギアボックスのギア比は29.16です。

この構成により、四逓倍を用いることで出力軸の角度は約0.006度の分解能で計測されます。

 

MCUにはESP32を用います。

ピトー管により計測した対気速度、MEMS 9軸センサにより計測した機体系角速度、エンコーダにより計測した動翼角度などから、適切なモータ電圧指令値を生成し、モータドライバへPWM信号を送信します。

同時に、各センサ値の計測および計測値と制御値の保存を行います。

さらに、機体内から外の景色および動翼の動きを撮影し、ロール制御の成否を定性的に確認するために、2台の小型カメラを搭載します。

 

図1 ハードウェア構成

 

3. 制御対象および制御系のモデル化

3.1 概要

図2に制御対象および制御系を簡易に表したブロック線図を示します。

ただし、目標ロール角は、固定値が与えられるものと仮定します。

与えられた目標ロール角と、姿勢推定器が推定したロール角推定値、およびピトー管を用いて求めた対気速度推定値をもとに、目標動翼角度決定器が目標動翼角度を決定します。

 

次に、目標動翼角度と、エンコーダを用いて計測した動翼角度計測値から、動翼角度制御器がモータに電圧を印加します。

モータ・ギアボックス・傘歯車・動翼から構成されるモータ-動翼系は、印加された電圧に応じて回転します。

このとき、動翼角度および対気速度に応じて発生するロールモーメントが、機体のロール角を変化させます。

 

図2 ブロック線図

3.2 動翼角度制御のモデル化

3.2.1 モータ・動翼系のモデル化とシステム同定

図2において、ロール角のフィードバックループ内に、動翼角度のフィードバックループが存在します。まずは、この部分をモデル化してみましょう。

 

DCモータにおいて、電圧V (s) から角速度Ω (s)までの伝達関数は、式(1)のように二次系で表せることが知られています。今回は、モータ-動翼系のモデル化にこの式を用いることとします。

 \displaystyle \frac{\Omega \rm{(s)}}{V \rm{(s)}}=\frac{c}{s^2+as+b}  (1)
 
ここで、  a, b, c はモータ-動翼系の機械的・電気的特性から決まる固定値です。
  a, b, c は、こちらの記事を参考にしたシステム同定実験により求めました。

sbasami-tech.hatenablog.com

 

図3に、システム同定実験における入力 (電圧) および出力 (角速度) の時間変化を示します。入力は正弦波とし、3 Hzから徐々に100 Hzまで周波数を上げています。

入力の周波数が上がるにつれ、出力の周波数が徐々に小さくなっていることが分かります。

 

図3 モータ-動翼系システム同定実験における入出力の時間変化

 

下記のMATLABコードを用いて、システム同定をしました。MATLABを使えば簡単だなあ...(中身を知らなすぎると危ないけど)

システム同定実験で得られた、1列目がduty比、2列目が角度計測値、3列目が前サンプリングとの時刻差であるcsvファイルを読み込んでいます。

----------------------------------------------------------------------------------------------

dt = 0.002; %サンプリング周期(規定)
data = readmatrix('data.csv'); %csvファイルを読み取る
length = size(data(:, 1), 1); %データの長さ
 
V = data(:, 1) * 9.97; %電圧指令値 duty比にバッテリー電圧を乗算することで計算
theta = data(:, 2); %角度計測値
dt_measured = data(:, 3)/1000/1000; %サンプリング周期(計測値)[μs]から[s]に変換
 
dtheta = zeros(length, 1); %角速度
for loop = 1:length %角度とサンプリング周期から角速度を計算
if loop == 1
dtheta(loop, 1) = 0;
else
dtheta(loop, 1) = (theta(loop, 1) - theta(loop-1, 1)) / dt_measured(loop, 1);
end
end
 
FR.u = V; %電圧が入力
FR.y = dtheta; %角速度が出力
FRdata = iddata(FR.y, FR.u, dt); %IDDATAオブジェクトの作成
FRdata.InputName = 'Voltage';
FRdata.OutputName = 'AngularVelocity';
figure(1), plot(FRdata);
FRdata_det = detrend(FRdata);%データの平均値を0にする
G2 = tfest(FRdata, 2, 0)%極が2、零が0のモデルを同定
figure(2), compare(FRdata, G2, 'r');%モデルの応答比較の表示
----------------------------------------------------------------------------------------------

図4に、同定実験における角速度の測定値 (図3の下段と同じ) 、およびシステム同定結果を用いたシミュレーション結果の角速度の時間変化を示します。(上記コードで得られるfigure(1)です。)

赤色の線は、システム同定実験における入力電圧(図3の上段)を、システム同定結果に基づくモデルに入力したときの応答をシミュレーションしたものです。

いい感じに同定できてそうですね。

  a=1462, b=53850, c=218100と求まりました。

 

図4 システム同定実験および同定結果を用いたシミュレーションの角速度

3.2.2 動翼角度制御器のモデル化

今回は、PD制御を用いて動翼の角度制御を行います。
比例ゲインと微分ゲインをそれぞれ  K_{Pm}, K_{Dm}とおきます。

簡単のために下記の仮定をおくと、動翼角度のフィードバックループは、図5のように表されます。

・動翼角度は誤差なく計測できる

・モータドライバの電圧制御は正確かつ時定数が小さく、モータ電圧指令値とモータ電圧は等しいとみなせる

 

図5 動翼角度フィードバック系のブロック線図


3.2.3伝達関数の導出とボード線図

図5の動翼角度フィードバック系について、伝達関数とボード線図を確認します。

開ループ伝達関数 G_{om}(s)は、式(2)で表されます。

 \displaystyle G_{om}(s)=\frac{csK_{Dm}+cK_{Pm}}{s^3+as^2+bs} (2)

一方、閉ループ伝達関数 G_{cm}(s)は、式(3)で表されます。

 \displaystyle G_{cm}(s)=\frac{csK_{Dm}+cK_{Pm}}{s^3+as^2+(b+cK_{Dm})s+cK_{Pm}} (3)

 

MATLABを使えば、簡単にボード線図が書けて、位相余裕とゲイン余裕も分かっちゃいます。ボード線図で位相余裕とゲイン余裕を確認しつつ、後述(まだ書けてません)する時系列シミュレーションで応答を確認して、PDゲインを決めました。

----------------------------------------------------------------------------------------------

a = 1462; b = 53850; c = 218100; %モータ-動翼系のシステム同定結果
Kpm = 240; %Pゲイン
Kdm = 1.5; %Dゲイン
 
%開ループ伝達関数のボード線図
[A, B, C, D] = tf2ss([c*Kdm c*Kpm], [1 a b 0]); %伝達関数状態方程式に変換
sys_o = ss(A,B,C,D); %状態空間モデルの作成
figure(1),margin(sys_o) %ボード線図を表示, 位相余裕とゲイン余裕も表示
grid on %グリッドを入れる
 
%閉ループ伝達関数のボード線図
[A, B, C, D] = tf2ss([c*Kdm c*Kpm], [1 a b+c*Kdm c*Kpm]); %伝達関数状態方程式に変換
sys_c = ss(A, B, C, D);%状態空間モデルの作成
figure(2),bode(sys_c) %ボード線図を表示
grid on %グリッドを入れる
----------------------------------------------------------------------------------------------
上記のコードを実行すると、図6および図7が得られます。
 
まず図6の開ループ伝達関数を見てみましょう。
margin関数を用いると、ボード線図と同時にゲイン余裕と位相余裕も得られちゃいます。
位相余裕は56.4度、位相が-180度以下にならないためにゲイン余裕は無限大となっています。
位相余裕、ゲイン余裕ともに充分でしょう。

図6 動翼角度フィードバック系の開ループ伝達関数のボード線図
 
次に、図7の閉ループ伝達関数を見てみましょう。
ある程度の周波数まで振幅・位相ともに0付近であり、その後どちらも下がっていく理想的な形ですね。
振幅が-3 dBになる周波数は395 rad/s ≒ 63 Hzです。このくらい高い周波数まで追従可能なら、安いPWMサーボモータを買うのではなく、MAXONモータを使って制御した意味があると言えるのでは(テキトー)

図7 動翼角度フィードバック系の閉ループ伝達関数のボード線図

3.3 全体のモデル化

3.3.1 機体系のモデル化とパラメータ推定
3.3.2 目標動翼角度決定器のモデル化
3.3.3 伝達関数の導出とボード線図

4. シミュレーションと事前調整

4.1 動翼角度制御のシミュレーションおよび実験

4.2 ロール制御のシミュレーション

4.3 計測誤差の考慮

5. ロール制御実験

5.1 実験条件

5.1.1 飛行プロファイル

図8に飛行プロファイルを示します。横軸は離床を基準とした時刻、縦軸は気圧センサのデータから算出した高度です。

C-59Jは、エンジン燃焼開始の直後に離床し、離床後約2.7秒で燃焼終了しました。

その後は約7秒間の弾道飛行の後、最高高度の約1秒後にパラシュートを開放し、減速落下しました。

 

安全性に配慮した自主的な規制により、ロール制御はエンジン燃焼終了後に開始することとしました。また、パラシュート開放後は大きな対気速度が得られず、動翼がロールモーメントを発揮できないため、ロール制御が成り立ちません。

よって、ロール制御は弾道飛行中にのみ、約7秒間実施しました。

 

図8 飛行プロファイル

5.1.2 パラメータ設定

動翼角度制御における制御ゲインは、  K_{Pm}=240, K_{Dm}=1.5 とし、

目標ロールモーメント生成における制御ゲインは  K_{Pa}=0.8, K_{Da}=0.07 としました。

 

また、ESP32への実装にあたっては、ノイズの影響を低減するため、制御に用いる計測値の一部にデジタルローパスフィルタを施しました。

ピトー管から算出した対気速度には、カットオフ周波数20 Hzの1次のデジタルローパスフィルタを施しました。

MEMS角速度センサから算出したロール角速度には、カットオフ周波数50 Hzの1次のデジタルローパスフィルタを施しました。

5.1.3 初期値

5.2 実験結果

5.2.1 動画による確認

実験結果を、まずは動画で定性的に確認しましょう。

右側が機体に搭載した小型カメラを用いて撮影した映像です。映っている黒い板が動翼です。

中央上が、MEMSジャイロセンサを用いて計測した機体姿勢を、CGで再現した映像です。中央下が、ロール角のグラフです。

左側上が、エンコーダで計測した動翼角度を、CGで再現した映像です。左側下が動翼角度のグラフです。

 

離床すると、C-59Jはロールしています。これは、機体後端にある固定翼のミスアラインメント、ノーズ形状の非対称性等により発生した、外乱ロールモーメントの影響と考えられます。

離床の約2.7秒後にロール制御が開始され、動翼が動き始めます。その後すぐに、ロールがほぼ停止していることが分かりますね!

 

5.2.2 計測データによる確認

図9に、ロール角の時間変化を示します。

青色で示したロール制御開始前は、ロール角が変化していることが分かります。

一方、ロール制御開始後は、素早く目標ロール角に収束しています。

図9 ロール角の時間変化。ロール制御開始前を青色、開始後を赤色で示す。

 

図10に、ロール制御開始直後の、ロール角の時間変化を示します。

整定時のロール角を90度とみなすと、整定時間 (95%) はたったの0.27秒でした!

 

図10 ロール制御開始直後におけるロール角の時間変化

 

図11に、ロール制御開始からパラシュート開放付近までの、ロール角の時間変化を示します。

制御開始直後を除き、目標ロール角からの偏差が±4度以内に抑えられていることが分かります。

図11 ロール制御開始からパラシュート開放付近までのロール角の時間変化

 

図12に、動翼角度および目標動翼角度の時間変化を示します。
動翼角度は目標値に精度よく追従していることが分かります。

モータ軸に取り付けたエンコーダで計測しているので、ギアボックスおよび傘歯車のバックラッシが計測できない誤差として存在はしていますが。

図12 動翼角度および目標動翼角度の時間変化。動翼角度は、ロール制御開始前を青 
色、開始後を赤色で示す。目標動翼角度は黒色で示す。

 

6. おわりに

肝心なMATLABをこんな感じに使ったよ~の部分が書きおわっておらず、ロケットのロール制御できたよ~状態で申し訳ないです。

2023年中には絶対書き終えます。

BUFFALOのUSB WifiアダプタをUbuntu22.04で使えるように設定した話

タイトル通り。自分用にメモしておく。

 

環境

OS:Ubuntu 22.04

 

マザーボードGIGABYTE B660M DS3H DDR4(B660 1700 MicroATX)

1万円くらいで買った安物で、Wifiがついてない。

 

Wifiアダプタ (USB接続):WI-U2-433DHP

Windowsでは刺しただけで使えたが、Ubuntuでは認識しなかった。

中身のチップはRTL8821AUらしい。

 

ドライバをGithubで拾った

色々な方がGithubでドライバを公開しているが、Wifiアダプタ中身のチップと、Ubuntuのバージョンで適切なものを選ばないと動かないらしい (それはそう)

 

私の環境では、下記の手順で動いた。

 

git clone https://github.com/aircrack-ng/rtl8812au.git

cd rtl8812au

sudo make dkms_install

この手順を終えて、Wifiアダプタを刺すと、それまで光っていなかったLEDが点滅。
画面右上からWifiルータのSSIDとパスワードを設定したら、インターネットにつながった。
めでたしめでたし。

小型ロケットのロール制御 ①概要

はじめに

本稿の内容

2022年11月、東工大ロケットサークルCREATEはC-59Jを打ち上げ、団体初となるロール制御を行い成功しました。

本稿では、C-59Jの概要とロール制御の結果を説明します。

CREATEとは

CREATEは、全長1〜2m程度の小型ロケットを製作し打ち上げているサークルです。

図1および図2に過去に打ち上げたロケットの例を示します。

半年ほどかけ1機のロケットを完成させ、伊豆大島裏砂漠または秋田県能代市にて打ち上げています。

 

図1 打ち上がりランチャーを離脱するC-59J (2022年11月打ち上げ)

 

図2 ランチャーに挿入されたC-31J (2017年11月打上)

 

C-59Jの概要

C-59Jは、2022年11月、伊豆大島裏砂漠にて打ち上げられました。

動翼を用いたロール制御 (機軸回りの角度制御) および機体先端に設置したピトー管による対気速度の計測をミッションとしました。

機体姿勢の能動的な制御に挑戦するのは、CREATEとして初めての試みでしたが、成功することができました。

 

機体の全体構造

図3にC-59J全体のCAD図を示します。図3の左から大きく分けてノーズ区画、電装区画、動翼区画、エンジン区画があります。

 

図3 C-59J全体のCAD図

①ノーズ区画

上空で開放するパラシュートが搭載されています。また、先端に対気速度を計測するためのピトー管が搭載されています。

 

②電装区画

基板および電池が搭載されています。基板は、下記の3つが搭載されています。

 

ミッション基板:ロール制御ミッション用の基板

開放基板:上空でパラシュートを開放し、機体を安全に着陸させるための基板

GPS基板:GPSセンサを用いて計測した座標を、地上へ無線送信するための基板

 

③動翼区画

ロール制御ミッションの鍵を握る部分です。図4にCAD図を示します。

1台のエンコーダ付きギアモータを用いて動かす、2枚の動翼が搭載されています。これらの動翼は、ミッション基板が制御します。

また、円筒型の機体の内側から外側方向を撮影する小型カメラが、2台搭載されています。

これらのカメラは、景色と動翼を映すことで、ロール制御の成否を視覚的に確認するために搭載しました。

 

図4 動翼区画のCAD図

 

④エンジン区画

ロケットを飛ばすために最も重要な、エンジンが搭載されています。

また、機体の姿勢を受動的に安定させるための、4枚の固定翼が搭載されています。

 

機体外観

図5、6に機体外観を示します。

 

図5 機体組み立て後、射点搬入まで待機中のC-59J

 

図6 打上直前、ランチャー挿入状態のC-59J

 

打上結果

飛行プロファイル

図7に飛行プロファイルを示します。横軸は離床を基準とした時刻、縦軸は気圧センサの値から算出した高度です。

C-59Jは、エンジン燃焼開始の直後に離床し、約0.4秒でランチクリアしました。

離床後約2.7秒で燃焼終了し、加えてロール制御を開始しました。

その後、7秒程度ロール制御を実施し、離床後約10.2秒でパラシュートを開放しました。

パラシュート開放後はロール制御を終了し、離床後約36.8秒で着地しました。

図6において、着地時点の高度が0mを下回っているのは、着地点の標高が射点の標高よりも低いことに因ります。

 

図7 飛行プロファイル

動画で確認

ロール制御の様子を、まず動画で確認してみましょう。

右側が、搭載したカメラで撮影した映像です。映っている黒い板は、動翼です。

中央上が、MEMSジャイロセンサを用いて計測した機体姿勢を、CGで再現した映像です。

中央下が、ロール角のグラフです。

左上が、エンコーダで計測した動翼角度を、CGで再現した映像です。

左下が、動翼角度のグラフです。

youtu.be

 

離床すると、C-59Jはロールしています。これは、固定翼のミスアラインメント、ノーズ形状の非対称性等により、ロールモーメントが発生したことに因ると考えられます。

その後、ロール制御が開始され、動翼が動くと、すぐにロールが止まっていますね!

データで確認

図8に、ロール角の時間変化を示します。

青色で示したロール制御開始前は、ロール角が変化していることが分かります。

一方、ロール制御開始後は、素早く目標ロール角に収束しています。

図8 ロール角の時間変化。ロール制御開始前を青色、開始後を赤色で示す。

 

 

図9に、ロール制御開始直後の、ロール角の時間変化を示します。

整定時のロール角を90度とみなすと、整定時間 (95%) はたったの0.27秒でした!

 

図9 ロール制御開始直後におけるロール角の時間変化

 

 

図10に、ロール制御開始からパラシュート開放付近までの、ロール角の時間変化を示します。

制御開始直後を除き、目標ロール角からの偏差が±4度以内に抑えられていることが分かります。

図10 ロール制御開始からパラシュート開放付近までのロール角の時間変化

 

図11に、動翼角度および目標動翼角度の時間変化を示します。
動翼角度は目標値に精度よく追従していることが分かります。

モータ軸に取り付けたエンコーダで計測しているので、ギアボックスおよび傘歯車のバックラッシが計測できない誤差として存在はしていますが。

図11 動翼角度および目標動翼角度の時間変化。動翼角度は、ロール制御開始前を青 
色、開始後を赤色で示す。目標動翼角度は黒色で示す。

 

おわりに

今回は、2022年11月に打ち上げたC-59Jと、ロール制御結果の概要を紹介しました。

次回は、動翼区画とミッション基板のハードウェアについて、選定理由等を紹介する予定です。

次々回は、ロール制御系設計の詳細として、モデリング方法や制御ゲイン決定方法について紹介したいですねます。

ロケットのロール制御に適したオイラー角を検討してみた

先日、2022年11月に、ロケットのロール制御に挑戦して成功しました。そのときに用いたオイラー角についてまとめたPDFを公開します。

 

内容はざっと

・制御機構は機軸まわりのモーメントを発生させるので、機軸を再度に回すオイラー角を選んだ
・飛行中に特異点近傍に陥りにくいオイラー角を選んだ
クォータニオンと選んだオイラー角の変換方法を導出した
・選んだオイラー角が実際に特異点近傍に陥りにくいことを、過去の飛行データを使用して確認した
オイラー角速度の算出方法も確認した

という感じです。

 

2023/02/14追記

参考文献としている松永先生のホームページ上の資料にアクセスできなくなっています。とりあえずインターネットアーカイブのURLを貼っておきます。

https://web.archive.org/web/20210407025007/http://lss.mes.titech.ac.jp/~matunaga/Attitude.pdf

 

[http://:title]

Blender+Pythonを用いてクォータニオンから姿勢表示しよう

はじめに

 3次元の姿勢を表現する方法の1つに, クォータニオン(四元数)があります. オイラー角と比較して, 特異点が存在しない, 計算量が少なくすむことが多いなどのメリットが存在しますが, 直感的に理解しづらいのが難点です. 

 そこで今回は, クォータニオンの時系列データを記したCSVデータを読み込んで, 3D CGソフトのBlenderでぐるぐる回す方法を説明します. 本記事で用いているBlenderのバージョンは2.92であり, PCのOSはWindows10です.

Blenderをダウンロード&インストールする

 Blenderの公式サイトからダウンロードし, その後インストールします. 特に迷う部分はないと思います.
https://www.blender.org/

Blenderを起動し, さわってみる

 Bldenderを起動すると, 図1のような画面が表示されます. 中央に立方体が配置され, 選択状態にあります. この画面の右下に, 立方体の位置や姿勢の設定が表示されています. 

f:id:tgkhtknk:20211215235858p:plain

図1 Blenderの起動時の画面

 右下を拡大したのが図2です. 初期設定では原点に配置され, 姿勢はxyzオイラー角の[0° 0° 0°]^Tになっています. そこのプルダウン部分をクリックすると, Quaternion(WXYZ)を選択することができます.

(ところで, Bldnerでxyzオイラー角とされているのは一般的な表記ではzyxオイラー角であり, 同様に例えばzxyオイラー角とされているのはyxzオイラー角が一般的な表記だと思うのですが, 本題ではないので深入りしないことにします.) 

f:id:tgkhtknk:20211215235902p:plain

図2 立方体オブジェクトの設定(初期値)

クォータニオンの定義を確認する

 Blenderのおけるクォータニオンは, WXYZと書かれていることから分かる通り, 1つ目が実部で2~4つ目が虚部です. つまり, ノルムが1のベクトル[x y z]^Tを軸にθ [rad]回転させるときのクォータニオン

f:id:tgkhtknk:20211216002002p:plain,

と表されます. よって, x軸回りにπ/4回転させるときは, 

f:id:tgkhtknk:20211216002938p:plain

です. これを試しにBlenderに入力してみます. 図3の赤枠部分のように入力すると, x軸(赤色の線)を軸に45°回転します. 

f:id:tgkhtknk:20211216120401p:plain

図3 クォータニオンの確認

Pythonコードを書く準備をする

図4のように, 画面上部のタブから赤枠内の"scripting"をクリックし, Pythonコードを書くための画面に移ります. その後, 緑色枠内の"New"をクリックすると, コードを書けるようになります. 

f:id:tgkhtknk:20211216135213p:plain

図4 scripting画面の初期状態

 次に, 必要なライブラリをインストールします. 今回は, osとbpyとpandasを用います.  osとbpyBlender内蔵Pythonには標準で入っているはずですので, pandasのインストールを行います. こちらのサイトを参考にインストールしてください. Blender内蔵Pythonへインストールする必要があるため, Pythonに慣れてる方もこのサイトを見た方がいいです. 

Blender内蔵Pythonにライブラリを追加する方法 | suemura's portfolio

 その後, きちんとインストールできたか確認します. 図5のように, Blenderテキストエディタ領域に

import os, bpy

import pandas as pd

と入力して, 赤枠で囲った実行ボタンを押します. 左下の緑枠で囲った領域に, 緑色のチェックボックスの後に"bpy.ops.text.run_script()"と表示されていれば成功です. 

f:id:tgkhtknk:20211218211440p:plain

図5 スクリプト実行

一方でエラーが発生した場合は, 図6のように赤いバツ印が表示されます. エラーメッセージの詳細はToggle System Consoleというのを開かないと見られません. 図7のようにBlender左上のWindowからToggle System Consoleをクリックしてください. 

f:id:tgkhtknk:20211218175458p:plain

図6 エラー発生時

f:id:tgkhtknk:20211218175527p:plain

図7 Toggle System Consoleの場所

f:id:tgkhtknk:20211218180407p:plain

図8 Toggle System Console

図8がToggle System Consoleです. 今回はBlender内蔵Pythonにインストールしていないsimplekmlをわざとimportさせようとしたため, simplekmlがないぞとメッセージが出ています.

クォータニオンのデータを用意する

図9のような時間間隔が同一のCSV形式のデータを用意します. 図9では, 見やすいようにエクセルで開いています. 1列目が実部, 2~4列目が虚部です. 行と列が逆だとPythonコードが読み取ってくれなくなります. 今回は時間間隔が0.001 sの1000 Hzのデータを用意しました. 

f:id:tgkhtknk:20211218181838p:plain

図9 CSVデータ

余談ですが, エクセルでデータを作成してCSV形式で保存する際には注意が必要です. 図10のように, CSV (コンマ区切り)をクリックしてください. 上の方にあるCSV UTF-8 (コンマ区切り)を選択して保存すると, Pythonコードが読み取ってくれなくなります.

f:id:tgkhtknk:20211218181918p:plain

図10 CSV形式での保存

Pythonコードを書き実行する

 図11が私が用いたコードです. 内容を解説します.

・5, 6行目でライブラリをimport

・8行目でCSVファイルがあるディレクトリを指定(バックスラッシュを二重にすることに注意)

・9行目でCSVファイルのファイル名を指定

・11~13行目で現在ある全てのオブジェクトを消去(消去しないと面倒が発生する可能性あり)

・15~17行目で, 原点に大きさ(1, 1, 3)の直方体を配置

・18行目でその直方体の角度表現をクォータニオンに設定(11~13行目で消去を行わないと, 作成した直方体の名称が Cube ではない可能性がある)

・20行目で現在アクティブなオブジェクト=Cubeをobjに設定

 

・22行目から1フレームごとに繰り返すfor文に入る

・今回は1000 Hzのクォータニオンデータを用いる. 20個に1つのデータを使用し, 50 Hzにする. 

・23行目でk+1フレーム目を指定

・24~27行目でCSVファイルから読み取ったデータをq0~q3に代入

・28行目でCubeを回転させ, 29行目でキーフレームを挿入する. 

・31行目では, old_typeに現在の編集エリアのタイプ(テキストエディタ)を代入

・32行目で編集エリアをグラフエディタに移動し, 33行目でキーフレーム間に補完をリニアに設定(今回は1フレームごとに設定しているので, 31~34行目はなくてもよい)

・34行目でテキストエディタに戻る

f:id:tgkhtknk:20211218192113p:plain

図11 コード

ディレクトリ, ファイル名, CSVデータのサンプリング周期と作成する動画のフレームレートにより適宜8, 9, 22, 24~27行目を書き換え, Pythonコードを実行します. ただし, Blenderを日本語化していると18行目でエラーを吐くことに注意してください. 対処法はある気がするのですが, このコードは英語でないと動きません.

 Scripting画面からLayout画面に戻ると, 図12のように直方体ができています. また, 赤枠で囲ったCubeの角度を表す部分が黄色になっています. これがキーフレームが挿入された状態です.

 さらに, 画面下の緑色で囲ったタイムラインにオレンジ色の四角形がたくさんあります. これは1つ1つがその時刻ごとにキーフレームが挿入されていることを表します. 

 今回用いたデータでは404フレーム目までキーフレームが挿入されましたが, デフォルトの設定ではタイムラインが250で最後になっています. そこで, 青枠で囲った250を404に変更します. 

f:id:tgkhtknk:20211218195453p:plain

図12 スクリプト実行後のLayout画面

⑦ロケットっぽい形のオブジェクトを入れる

 直方体がぐるぐる回ってもいまいちなので, ロケットっぽい形のオブジェクトを導入します. 今回は, 事前に作成しておいたSTLファイルをimortします. 図13のように, File→Import→Stl をクリックします.

f:id:tgkhtknk:20211218200411p:plain

図13 STLファイルのimoport

そうすると, 図14のように原点にimportしたオブジェクト(以下Rocketと呼ぶ)が配置されます. Rocketの角度が意図した初期姿勢と異なる場合は, 初期姿勢に変更してください. なお, 図12では404フレーム目でしたが, 図14では1フレーム目に移動しています. ここから, RocketがCubeと一緒に回転してくれるように設定を行います. 

f:id:tgkhtknk:20211218200905p:plain

図14 STLファイルのimport後

 まず, Cubeをクリックします. その後, 図15のようにCubeの角度と大きさを変更します. 角度は初期姿勢(Rocketと同じ姿勢)にします. RocketがCubeと一緒に回転するようにするための作業上の都合で一時的にするだけなので, キーフレームの挿入(iキーを押す)はしないでください.

 次に, CubeがRocketの中に収まるようにCubeの大きさを変更します. これは動画を作成するときに見栄えをよくするための作業です.

f:id:tgkhtknk:20211218201425p:plain

図15 Cubeの大きさと角度の変更

 次に, 親子関係を設定します. まずRocketをクリックします. そのまま, Shiftキーを押しながらCubeをクリックします. (Rocketの中に隠れてしまっていますが, あるはずのところをクリックすれば問題なくできます) 必ずRocketを先, Cubeを後にクリックします. その後, Ctrlキーをおしながらpを押すと, 図16のようになるのでObject (Keep Transform)をクリックします. こうすることでCubeが親, Rocketが子となり, RocketはCubeと一緒に回るようになります. 

f:id:tgkhtknk:20211218202139p:plain

図16 親子関係の設定

⑧フレームレートの設定

 今回はフレームレートが50 fps (50 Hz)になるようにCSVデータのサンプリングレートとPythonコードでのダウンサンプリングを定めたので, Blender上でも50 fpsに設定します. 図17のように, 画面右側にある赤枠で囲ったプリンターが画像を出しているアイコンをクリックします. その後, 緑色枠で囲った部分のデフォルトで24になっているFrame Rateを50に変更します. 

f:id:tgkhtknk:20211218203923p:plain

図17 フレームレートの設定

⑨映像を見てみる

 図18の赤枠で囲った, タイムラインの上部にある再生ボタンをクリックすれば, Rocketが回る様子を映像で見ることができます. ただし, リアルタイムに描画してるので50fpsで表示してくれるとは限りません.

 きちんと動画に出力する方法は下2つの記事を参考にしてください. 他にもググればいくらでも出てくるので説明しません. (記事終盤になり疲れてきたし) 

【Blender2.9】カメラの使い方と機能:レンダリングには必要技術! | Vtuberの解剖学

Blender2.8で【静止画】【動画】をレンダリングして保存する方法

f:id:tgkhtknk:20211218204558p:plain

図18 再生ボタン

⑩実際のロケットの動画と見比べてみる

この動画は, 2019年11月に打ち上げたC-43Jの動画と, それに搭載した基板のデータからBlenderで作成した動画の比較動画です. いい感じですね!!(最後の方ちょっとずれてるけど, ドリフト・基板とカメラ間の時刻誤差・撮影地点から見てロケットが移動しているの複合によるものかな)

youtu.be