「Python×Simulinkで自動設計!TOFから距離を求める最小例」

皆さんこんにちは。この記事をご覧いただきありがとうございます。私は、設計は「手作業で積み上げるもの」ではなく、仕様・構成・検証まで含めて再現可能な形で残せるものであるべきだと考えています。
本記事では、その最小例として Python から Simulink モデルを自動生成し、TOF(飛翔時間)から距離を求めるサブシステムを作成・検証する流れを紹介します。
なお、実装の一部(スクリプトの骨格生成など)には ChatGPT を活用していますが、入出力定義・数式の妥当性・検証条件は筆者が設計しています。

🧩 この記事の目的

  • Python から Simulink を操作できる仕組みを体験する
  • 手作業(GUI)の負担を減らし、仕様変更に強い形にする
  • 生成物を“検証可能”な形で残す流れを掴む
  • AIを使う場合でも、誤解を潰す確認手順(スモールステップ)を含めて紹介する

🧩 背景

Simulinkでモデルを構築する場合、GUIでブロックを配置・接続するのが一般的です。
しかし、仕様変更が入るたびに手作業で修正するのは効率的とは言えません。

そこで今回は、
Pythonからモデルを生成することで、設計を「再現可能な形」にすることを目指します。

本記事ではステップ1〜5を通して、環境構築からモデル自動生成、そして簡単な検証 までを体験できる内容になっています。

※なお、この記事の内容は ChatGPT とのディスカッションを元に編集したものであり、筆者の環境で動作確認済みです。

🧩 ステップ1|MATLAB Engine API for Python の構築

PythonからMATLABを呼び出せるようにするためには、MATLAB Engine API for Python をインストールする必要があります。下記のステップを踏んでインストールしていきましょう。

✅ ステップ1のゴール

PythonからMATLABを呼び出せるようにする。


🔧 前提条件チェック

項目内容
Python環境すでにインストール済み or これから入れる(AnacondaでもOK)
バージョンPython 3.7〜3.10 が推奨(2025aでは公式対応範囲)
それ以外のバージョンでも動作する可能性はあるが非推奨
MATLABのバージョンR2025a(他バージョンは未検証)

✅ 手順(Windows前提)

① Pythonがまだならインストール

公式:https://www.python.org/downloads/

(Anaconda派なら https://www.anaconda.com/)


② MATLAB Engine API for Python のセットアップ

  1. MATLABのインストール先に移動:
cd "C:\\Program Files\\MATLAB\\R2025a\\extern\\engines\\python"

※上記パスはインストール状況により異なる。R2025aの部分確認すること。

  1. setup.py を使ってインストール:
python setup.py install


✅ 成功確認

Pythonで以下を実行:

import matlab.engine
eng = matlab.engine.start_matlab()
eng.sqrt(16.0)

出力が 4.0 になれば成功!


🧩 ステップ2|Simulinkモデル自動生成テスト

Pythonで空のSimulinkモデルを生成するスクリプト実行してみます。
Pythonで以下を実行してください:

🧪 シンプルな空モデルを生成&保存するスクリプト

※注意:下記の”save_dir”はご自身のローカルpath(フルpath)に変更してください!

import matlab.engine
import os

# MATLABエンジン起動
eng = matlab.engine.start_matlab()

# モデル名と保存パス
model_name = 'test_model'
save_dir = r'**{ご自身のローカルpath(フルpath)}**'
save_path = os.path.join(save_dir, model_name + '.slx')

# モデル新規作成
eng.new_system(model_name, nargout=0)
eng.open_system(model_name, nargout=0)  # モデルを表示(MATLAB上で開く)

# 保存(指定ディレクトリへ)
eng.save_system(model_name, save_path, nargout=0)

# モデルを閉じる(任意)
# eng.close_system(model_name, save=False)

print(f"モデルを保存しました → {save_path}")


✅ 実行結果の確認ポイント

  • MATLABが起動し、test_model という空のモデルウィンドウが開く
  • 指定したフォルダに test_model.slx が作成される
  • エラーがなければコンソールに保存完了メッセージ

🧩 ステップ3|仕様定義(IN/OUT整理、ロジック定義)

次に、今回作るサブシステム「TOF2DIST」の仕様を整理します。
まずは「どんな入力を受け取り、どんな出力を返すのか」を明確にします。
今回は、ソナー制御システムで用いられるTOFから距離への変換を例にします。

入力信号

  • TOF_A … ソナーAの飛翔時間 [s]
  • TOF_B … ソナーBの飛翔時間 [s]
  • Temp … 温度 [℃]

出力信号

  • dA … 距離A [m]
  • dB … 距離B [m]
  • c … 音速 [m/s]

使用する式

  • 音速: $$ c=331.5+0.6×Temp $$
  • 距離: $$ dA = \frac{c \times TOF\_A}{2}, \quad dB = \frac{c \times TOF\_B}{2} $$

このシンプルな仕様をブロックとして自動生成していきます。


🧩 ステップ4|Simulinkモデル自動生成

ここではPythonスクリプトを使って、上記仕様をSimulinkのサブシステムとして自動生成します。

今回のスクリプト(make_tof2dist.py)は、骨格や記述パターンの作成に ChatGPT を活用しました。
一方で、入出力と仕様(論理)は設計者側で固定し、数式やフローチャートで合意を取ってから生成に進めています。

スクリプトのポイント抜粋

# --- サブシステム作成 ---
SUBSYS = f'{MODEL_NAME}/TOF2DIST'
eng.add_block('built-in/Subsystem', SUBSYS,
              'Position', md([100, 100, 300, 250]), nargout=0)

# --- 入出力ポート ---
add(eng, 'built-in/Inport',  f'{SUBSYS}/TOF_A', 30,  50)
add(eng, 'built-in/Inport',  f'{SUBSYS}/TOF_B', 30, 120)
add(eng, 'built-in/Inport',  f'{SUBSYS}/Temp',  30, 190)

add(eng, 'built-in/Outport', f'{SUBSYS}/dA',  600, 50)
add(eng, 'built-in/Outport', f'{SUBSYS}/dB',  600, 120)
add(eng, 'built-in/Outport', f'{SUBSYS}/c',   600, 190)

# --- 音速の計算 (c = 331.5 + 0.6*Temp) ---
add(eng, 'built-in/Constant', f'{SUBSYS}/c331_5', 100, 200, Value=331.5)
add(eng, 'built-in/Gain',     f'{SUBSYS}/k0p6',   100, 150, Gain=0.6)
add(eng, 'built-in/Sum',      f'{SUBSYS}/c_sum',  200, 150, Inputs='++')

# --- 距離の計算 (dA = c*TOF_A/2) ---
add(eng, 'built-in/Product', f'{SUBSYS}/mulA', 300,  50)
add(eng, 'built-in/Gain',    f'{SUBSYS}/halfA', 400,  50, Gain=0.5)

# (dBも同様に作成)

すべてのブロックを組み合わせ、最後に eng.save_system(...) で保存すればOKです。 ※全文は後日、GitHubで公開予定

実行コマンド

python C:\\Users\\...\\make_tof2dist.py

実行結果

Simulink上に TOF2DIST サブシステム が自動生成されます。

1.Simulinkモデルを開いて確認すると、配線は下記のようにごちゃごちゃしてしまっています。
  目視チェックを容易にするため、配線をきれいにします。

2.モデルを全て選択した状態で「Ctrl+Shift+a」※を押すと、自動で配線がきれいにできます。
(※MATLAB R2025aの場合。他のバージョンではショートカットキーが変わることがあります)
この状態であれば、目視チェックが容易になり、正しさの一時確認ができます。


🧩 ステップ5|Simulinkモデル検証

モデルが生成できたら、正しく計算できるか検証します。

そのために「固定値を入力 → 出力をDisplayで確認」するハーネスを自動生成します。

スクリプト例(make_dist_harness.py

# --- 定数入力 ---
add(eng, 'built-in/Constant', f'{MODEL_NAME}/Const_TOF_A', 30,  50, Value=0.010)
add(eng, 'built-in/Constant', f'{MODEL_NAME}/Const_TOF_B', 30, 120, Value=0.012)
add(eng, 'built-in/Constant', f'{MODEL_NAME}/Const_Temp',  30, 190, Value=20)

# --- 出力をDisplayで可視化 ---
add(eng, 'built-in/Display', f'{MODEL_NAME}/Disp_dA', 600,  50)
add(eng, 'built-in/Display', f'{MODEL_NAME}/Disp_dB', 600, 120)
add(eng, 'built-in/Display', f'{MODEL_NAME}/Disp_c',  600, 190)

# --- サブシステムと接続 ---
eng.add_line(MODEL_NAME, 'Const_TOF_A/1', 'TOF2DIST/1', nargout=0)
eng.add_line(MODEL_NAME, 'TOF2DIST/1',   'Disp_dA/1',   nargout=0)

# (TOF_B, Temp も同様に接続)

※全文は後日、GitHubで公開予定

入力条件

  • TOF_A = 0.010 [s]
  • TOF_B = 0.012 [s]
  • Temp = 20 [℃]

理論値

理論値は、今回のロジックの場合、電卓レベルで算出できますので、ここは人の手で算出することが大事です。(理論値までChatGPTに出してもらっては、期待値と出力値に共通の間違いが入り込む可能性があるからです)

$$
dA=343.5×0.010/2=1.718 [m]
$$

$$
dB=343.5×0.012/2=2.061 [m]
$$

実行結果

SimulinkのDisplayブロックに以下が表示され、一致することを確認できます。

  • dA ≈ 1.718
  • dB ≈ 2.061
  • c = 343.5

👉 これで「Pythonスクリプトからモデルを作る → Simulinkで検証する」一連の流れが完成しました!

次の記事では「CSV入力によるログ検証」や「座標変換(TOF2XY)」にも挑戦してみたいと思ってます。

補足:AIは「コードを書く速度」を上げられますが、仕様の確定と検証は設計者の責務です。
本記事は、その境界を保ったまま“再現可能な設計”に落とし込む最小例としてまとめました。


🧩 ハマりどころメモ

  • set_param は kwargs では通らないケースがある(リスト形式が無難)
  • ブロック名は built-in/ or simulink/ で指定する
  • Positionmatlab.double([x1 y1 x2 y2])
  • PythonからMATLAB Engineを扱う際、型の扱いやパラメータ指定方法でつまずきやすい。こうした細部の調整は、AIとの対話を通して効率的に解決できた。

🧩 今後の展望

  • CSV入力にしてログ検証まで拡張
  • 座標変換(TOF2XY)の実装へ
  • 検証を自動化して記事化第2弾へ
  • 「もし他にも“こんな変換を自動化したい”というアイデアがあれば、ぜひコメントなどで教えてください。」

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です