モデルベース開発入門_モデルベース開発実例_ライントレースロボットを作ってみた

# はじめに
こんにちは。
[前々回(そもそもモデルベース開発とは)](https://qiita.com/LetsMBD/items/a217444a89696c4bfc61)
[前回(モデルベース開発工程)](https://qiita.com/LetsMBD/items/99496567137355a2dc83)
に引き続き入門者(新入社員や転職者)向けモデルベース開発解説記事第三弾です。

今回はモデルベース開発実例を紹介したいと思います。
基礎知識である前回・前々回投稿に今回の開発実例を合わせることによりモデルベース開発の理解を深めていただければ幸いです。

モデルベース開発を中心に組み込み系の情報をまとめたホームページを作成中です。よければ覗いてみてください。
[モデルベース開発入門](http://lets-mbd.com/)

# 開発テーマ ライントレースロボットの制御ソフト開発
ライントレースロボットの制御ソフト開発を題材にモデルベース開発工程を解説したいと思います。
## ライントレースロボットとは

ライントレースロボットとは、線をなぞるように自動走行するロボットです。
白色の床に黒線(または黒色の床に白線)を引き、線をセンシングしながら車輪の回転を制御します。
簡単そうに見えますが奥が深く、制御開発の教材として取り上げられることが多いです。

<iframe width="560" height="315" src="https://www.youtube.com/embed/MAFbO70le4w" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

マイクロマウス大会という名前の全国大会もあります。
目にもとまらぬ速さで駆け抜けるロボットが印象的です。
<iframe width="560" height="315" src="https://www.youtube.com/embed/wva4PzjTc-Y" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

今回はこのライントレースロボットの制御ソフトをモデルベース開発を用いて作成していきたいと思います。

# 要件定義工程
まずは要件定義工程を進めましょう。
①システム構成図作成
②要件一覧表作成の2ステップで進めていきたいと思います。

## ①システム構成図作成
最初に開発対象のシステム構成図を作成します。システム構成図とは、制御対象に搭載されている物の一覧とそれぞれの関係が一目見てわかる図のことです。ソフトウェア開発用の図なので、制御に関係する物が登場します。

今回開発するライントレースロボットは下記の構成で作成したいと思います。
・制御用のマイコン(Arduino UNO)1つ
・ライン検出センサ(フォトリフレクタ)1つ ※複数個使用する場合もありますが、今回は1つ使用。
・走行開始・停止のスイッチ
・システムの状態を表すLED
・走行用モーター2つ(ギアボックス内にモーターが入っている)
下図のようなイメージです。
![20220417_ロボットイメージ図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/70a76fb4-2a62-426f-c72b-1d8ba99e78df.png)
システム構成図は下記のように作成しました。
![システム図2-768x262.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/86dc301c-ba9b-41da-9d76-1357e7d1e284.png)
## ②要件一覧表作成
開発対象が満たすべき要件を一覧にまとめます。
ライントレースロボットを実際に使用する時のことを考えながら検討を進めましょう。

一旦箇条書きで書き出してみます。
・電源を入れた瞬間に走り出すと使いづらいので、電源を入れてもすぐには走り出さないようにします
・電源が入っているのかどうかわかるように、電源が入っているときはLEDを点灯させます
・スイッチを押し下げるとライントレース走行を開始します
・ライントレース走行中であることがわかるように、走行中はLEDを点滅させます
・スイッチを押し下げると走行を停止する
・脱線時に走り続けてしまうことを防止するため、走行中に一定時間ラインを検知しない場合は異常状態と判定し、異常モードとする。
・異常モードに入った時はLEDを高速で点滅させる
・異常モードに一度入ると電源を切るまで解除されない

抜け漏れがないように表形式にまとめ、番号を振って管理します。
|要件ID|要件|
|---|---|
|1|制御システムは3状態(待ち状態、走行状態、異常状態)を持つ。<br>それぞれの状態の意味は下記の通り<br>待ち状態: 走行開始を待っている状態。モーターは停止状態。<br>走行状態: ライントレース走行中。<br>異常状態: 異常が発生した状態。モーターは停止状態。|
|2|電源を入れると待ち状態から開始する|
|3|待ち状態の時にスイッチを押し下げると走行状態に遷移し、ライントレース走行を開始する。|
|4|走行状態中にスイッチを押し下げると待ち状態に遷移する|
|5|走行状態中に一定時間ラインを検知しない場合、脱線したと判定し異常状態に遷移する。|
|6|異常状態に遷移した場合は電源を切るまで他のモードに遷移できない。|
|7|状態に応じてLEDを点灯させる。点灯パターンは下記の通り。<br>待ち状態: LED点灯<br>走行状態: LED点滅(0.5秒点灯、0.5秒消灯の繰り返し)<br>異常状態: LED高速点滅(0.2秒点灯、0.2秒消灯の繰り返し)|

以上で要件定義工程完了です。

# 基本設計工程
基本設計工程では、各要件をどのように実現するか設計します。
①入出力信号の定義
②機能分割
③スケルトンモデル(内部が空のサブシステム)作成
の順番で進めます。

## ①入出力信号の定義
開発対象ソフトの入出力信号を整理します。
### 入力信号
入力信号を下表のように定義しました。
|No|信号名|データ型|最小値|最大値|備考|
|---|---|---|---|---|---|
|1|PhotoRef|uint16|0|1023|ライン検出センサ(フォトリフレクタ)の電圧AD値。反射光が大きい(白色を検出する場合)ほど電流が流れるのでマイコンが検出する電圧は小さくなる。逆に反射光が少ない(黒色を検出する場合)は電流があまり流れないので、マイコンが検出する電圧は高くなる。|
|2|Switch|boolean|0|1|スイッチ状態<br>0: 押されていない<br>1: 押されている|

### 出力信号
出力信号を下表のように定義しました。
|No|信号名|データ型|最小値|最大値|備考|
|---|---|---|---|---|---|
|1|MotorSpeed_R|uint8|0|255|右側モーターPWM出力<br>0:停止, 255:最速|
|2|MotorSpeed_L|uint8|0|255|左側モーターPWM出力<br>0:停止, 255:最速|
|2|LED_ON|boolean|0|1|LED状態<br>0: 消灯, 1: 点灯|

## ②機能分割
要件に基づきソフトの機能分割を検討します。適切に分割を行うことにより「ソフト構造の可読性が高まる」、「複数人で分担しやすくなる」など効果があります。
今回は状態管理機能、LED制御機能、異常検知機能、ライントレース走行機能の4機能に分けて開発を進めます。それぞれの機能の概要と仕様は下記の通りです。

#### 状態管理機能(サブシステム名:StateManagement)
概要: システムの状態(待ち状態、走行状態、異常状態)を管理する機能。
仕様: 起動時は待ち状態から開始する。待ち状態と走行状態はスイッチのONエッジに応じて行き来する。走行状態中に異常が発生すると異常状態に遷移し、一度異常状態に遷移するとシステムを再起動するまで異常状態を維持する。

#### LED制御機能(サブシステム名:LED)
概要: システム状態に応じてLEDの点灯、消灯を制御する機能。
仕様: システムが待ち状態の時はLEDを点灯させる。走行状態の時は0.5秒間隔でLEDの点灯消灯を繰り返す。異常状態の時は0.2秒間隔でLEDの点灯消灯を繰り返す。

#### 異常検知機能(サブシステム名:ErrDetection)
概要: システムの異常を検出する機能。
仕様: システム状態が走行状態の時に一定時間(3秒とする)黒線を認識できなかった場合に異常と判定する。

#### モーター制御機能(サブシステム名:MotorControl)
概要: ラインをトレースしながら走行するように、左右のモーター回転数を制御する機能。
仕様: システム状態が走行状態の場合、ライントレースするように左右のモーター回転数を制御する。システム状態が待ち状態、異常状態の時はモーター回転数を0にする。

## ③スケルトンモデルの作成
機能分割検討結果に基づきスケルトンモデル(内部が空のサブシステム)を作成します。基本設計工程ではソフトの入出力、スケルトンモデル、モデル間の配線のみを行います。

下図のようにスケルトンモデルを作成しました。
![スケルトンモデル-1536x546.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/9dac4cd4-3fe7-9b19-a121-1381ccd530a5.png)
以上で基本設計は完了です。

# 詳細設計工程
詳細設計工程では、基本設計工程で検討した各サブシステム(機能分割したそれぞれの機能)の作り込みと検証を行います。
① 各サブシステムの中身の作成
② 制御モデルの検証(モデリングガイドラインチェック、設計エラー検証、動的解析)
③ MILSによるシステム検証

※具体的なタスクは各社様々だと思いますのでご参考まで。
## ① 各サブシステムの中身の作成
各サブシステムの中身を作り込んでいきます。
### ①-1 状態管理機能(サブシステム名:StateManagement)
![モデル作成_StateManagement.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/b081a7c5-fecf-d2ed-01b7-1f88686741c9.png)

状態遷移部
![モデル作成_StateManagement状態遷移.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/8a18c9cc-a551-efe9-e052-fd6002b0042a.png)

チャタリング処理(ChatteringProcessサブシステム)
![モデル作成_StateManagementチャタリング処理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/625e9e0c-7f2c-12a1-f5d8-8e4fee9c5d38.png)
オンエッジ検出(OnEdgeサブシステム)
![モデル作成_StateManagementエッジ検出.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/aae46d03-f73a-728e-f05f-e643055d0550.png)

### ①-2 LED制御機能(サブシステム名:LED)
![モデル作成_LED2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/69323905-78cd-c91f-f373-fcc3a96f35d0.png)

### ①-3 異常検知機能(サブシステム名:ErrDetection)
![モデル作成_異常検知.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/9bf75215-4eb0-015b-faaf-b591ffb84670.png)

### ①-4 モーター制御機能(サブシステム名:MotorControl)
![モデル作成_モーター制御.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/13602bcd-53ca-1dba-812c-55b3c4e4cf83.png)

## ②制御モデルの検証(モデリングガイドラインチェック、設計エラー検証、動的解析)
次に作成したモデルの検証を行います。
### ②-1 モデリングガイドラインチェック
概要: 作成した制御モデルがモデリングガイドラインに準拠しているかどうかを検証します。モデリングガイドラインとはモデルを作成する際に守るべきルール一覧のことで、ルールを守ってモデルを作成することで可読性の向上やコード生成効率の向上などの効果があります。チームで分担して制御モデルを作成する場合でも、全員のモデル品質を合わせることができます。
　採用するルールに正解はなく、各社独自のルールや各団体(例 JMAAB)が提唱するルールなどから必要なものを取捨選択します。
　
モデリングガイドラインチェック方法
　デフォルトで用意されているチェッカー、または自作のスクリプト、またはSimulink Checkツールボックスを用意することによりモデリングガイドラインに準拠しているかどうかを自動判定することができます。目視による確認もできますが、工数がかかる割にミスや漏れの温床なので、なるべく自動チェック可能な環境を整えるべきだと思います。今回はデフォルトで使用可能なチェックのみを実施します。

#### 手順1 チェッカー(モデルアドバイザー)の起動
モデル化タブを開き、左上のモデルアドバイザーをクリックしてモデルアドバイザーを起動します。
![モデルアドバイザー_01-1536x776.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/67d49e63-34c1-76a0-1422-ee565ca1f803.png)
#### 手順2 モデリングガイドラインチェック対象の選択
モデリングガイドラインチェックを行う階層(どのサブシステムをチェックするかどうか)を選択します。モデルの規模が大きい場合は一度にチェックを行うと時間がかかったり、Simulinkがクラッシュしてしまったりするのである程度の規模で分割してチェックを行います。今回は規模が小さいモデルなので、モデル全体をチェックします。
![モデルアドバイザー_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/8f744fbf-3cbd-7422-1e6b-6840cde7ab9b.png)
#### 手順3 対象ルールの選択
どのルールを採用するかどうか選択します。今回はデフォルトで入っているSimulink機能に関するルールをチェックします。チェックしたい項目のチェックボックスにチェック入れた後、選択したチェックを実行ボタンを押すと自動チェックが始まります。チェックが完了するとチェック結果が格納されたレポートが生成されます。すべてパスするようにモデルの修正を繰り返します。最終的なレポートはエビデンス(証拠)として保存しておきましょう。
![モデルアドバイザー_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/8f0089d0-a84c-72ed-d188-5880000874be.png)
![モデルアドバイザー_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/a9cce138-211e-06db-9169-bb9373cb5fef.png)

### ②-2 設計エラー検証
次に設計エラー検証を行います(Simulink Design Verifierツールボックスが必要)。設計エラー検証とは、制御モデルに構造的な問題が無いかどうかを確認する工程です。仕様通り(例: スイッチを押すと動き出す)に動くかどうかといった観点の検証ではないことがポイントです。具体的にはオーバーフローがないか。デッドロジックがないか。配列アクセスに違反がないか。ゼロ除算がないかを検証します。

設計エラー検証の手順を記載していきます。(バージョンによってインターフェースが変わります)
#### 手順1 SimulinkのアプリタブからDesign Verifierを選択する
![DV_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/544a85ad-a966-caf7-50a0-ace4dcdbdaee.png)

#### 手順2 モードを設計エラー検出モードに設定
画面左上のモードから設計エラー検出を選択します。(Simulink Design Verifierは設計エラー検出だけでなく、自動でテストケースを作ったりプロパティ証明する機能も持っています。それらはまた別の機会に解説します。)
![DV_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/13533bd3-44c7-86d8-db29-f499a52401eb.png)

#### 手順3 設計エラー検出内容の設定
エラー検出の設定をクリックし、設計エラー検出内容を選択します。今回はデッドロジック、範囲外配列アクセス、ゼロ除算、整数オーバーフローの4項目を選択します。選択内容はプロジェクト全体で統一するようにしましょう。
![DV_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/66716759-cd15-363c-07e1-60f35bbbd289.png)

#### 手順4 設計エラー検出の実行
設計エラーの検出ボタンをクリックして検出を実行します。検出が完了するとレポートが生成されるので、エビデンスとして保存しておきましょう。
![DV_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/2bf0ba88-da29-9261-d315-9152beccf637.png)

### ②-3 動的解析
次に動的解析を行います。動的解析とは解析対処の入力信号と出力信号(期待値)の時系列情報(テストパターン)を用意し、実際にモデルをシミュレーションして期待通り(仕様通り)の動きをするかどうかを確認する工程です。シミュレーション時にはカバレッジ(モデル全体のうち何%の確認ができたのかどうか)を計測(Simulink Coverageツールボックスが必要)することにより解析の抜け漏れを防止します。Simulink Testツールボックスがあれば、解析を自動化することができます。
![動的1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/1beea304-3460-13ee-ec75-2dfd0156254a.png)

例としてStateManagement内のChatteringProcessサブシステムの動的解析例を記載します。
#### 手順① テストパターンの作成
解析対象のテストパターンを用意します。テストパターンは下図のようにエクセルで作成します。
![動的2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/ff01e18e-8ca9-2320-7425-1799c4883fc4.png)

#### 手順② 解析の実行
Simulink Testツールボックスの機能であるTestManager(テストを一元管理、自動実行できるツール)の設定を行い、解析を実行します(詳細手順は別ページで解析予定)。解析が完了すると下図のように解析結果やカバレッジの結果を確認することができます。今回の場合、作成したモデルが期待値通りの動きをしており、条件カバレッジと実行カバレッジが両方とも100%達成できていることがわかります。エビデンスとしてレポートを出力し、保存します。
![動的3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/5bf189f3-c892-f897-94ab-eb47c0e8cd1b.png)

以上で制御モデルの検証が完了です。

### ③MILSによるシステム検証
次にMILS(Model In the Simulation)を利用してシステム検証を行います。MILSの詳細は[リンク先](http://lets-mbd.com/4_mils%e3%81%a8%e3%81%af/)をご覧ください。MILSを一言でいうと制御モデルとプラント(実機)モデルを接続しての動作シミュレーションです。実機の代わりにモデルを使うので実機レスで試験可能です。

　ライントレースロボットの場合、タイムを縮めるために走行→ログ取り出し→ログ解析→パラメータチューニングを何度も繰りかえす必要があり時間を要します。MILSであればそれらの工程をPC上で済ますことができます。制御ロジックの確認やパラメーターの当たりづけをMILSで行い、最後の調整を実機を用いて行うことにより大幅に工数を削減することができます。
　また、大会に使われるコースはかなり大きく、そもそも試験スペースを確保することが困難な場合も多くぶっつけ本番になってしまうこともあると思います。MILSであれば試験スペースは自由に作成できるので、色々なコースパターンで制御ロジックが正しく動作するかどうか検証することができます。
![MILSとは-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/fff0c2f4-adba-b432-f905-686a30a039c8.png)
#### 手順① プラント(実機)モデルの作成
制御対象をモデル化します。いくつかのプラントモデリングツールを使ってきましたが、個人的にはSimscape推しです。(使いやすい、制御モデルと接続しやすい)。Simscape Multibodyツールボックスを使うと下図のように物理モデリングをすることができます。具体的な使用方法について後日まとめたいと思います。

#### 手順② シミュレーションによる動作確認
　制御モデルとプランとモデルを接続し、動作確認を行います。要件定義で定義した仕様をすべて満たしていることを確認できたら詳細設計工程完了です。もし仕様と異なった動作をした場合はモデルを修正します。
　MILSをしていると、「このパターンの検討が漏れていた！」、「なんか動作おかしくない？」などいろいろな発見があります。これこそがMILSの効果です。従来開発の場合、実機とECUを接続しての確認は最終工程である実機評価工程で行っていました。最終工程で不具合が出てしまった場合は大きな手戻り(※1)に繋がってしまい、プロジェクト日程に致命的な影響を与えてしまいます。MILSを活用することにより早期に動作確認を行えるので、大きな手戻りを防止して開発効率向上に繋がります。
<iframe width="560" height="315" src="https://www.youtube.com/embed/0rB3RJcSU4c" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

※1 大きな手戻りの例
例① そもそもの要件を修正必要がある
　→要件を修正するということは制御モデルの修正～検証をすべてやり直す必要があり工数がかかります。エンジニアの士気もかなり低下します。(せっかくここまで来たのにやり直しか。。。という心境)

例② 機械・機構を変更する必要がある
　→実現したかった機能が現状の機械・機構では実現できないことが実機試験ではじめてわかる場合があります。機械設計をやり直す場合、数ヶ月単位で日程遅延が発生することがあります。(もっと長い場合も。。。)

以上で詳細設計工程は完了です。

# コーディング工程
コーディング工程では制御モデルからコードを生成し、その他のコードと合わせてコンパイルしてソフトを作成する工程です。モデルから生成したコードはPolyspaceツールボックスを用いて問題が無いことを検証します。
![コーディング.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/a825f076-ead4-de43-6966-2e18800780f6.png)
今回はArduinoマイコンを使用します。ArduinoマイコンはMathWorks社公式のサポートパッケージが存在します。サポートパッケージを使用すると、モデルをソースコードに変換することなく、直接Arduinoマイコンに書き込むことができます。開発実例ではこの方法をもってコーディング工程とします。
![サポートパッケージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/4fc96136-4128-6e52-8207-c351b055b162.png)

# 評価工程
MBD工程上は　単体評価(ECU単体での机上確認)、結合評価(複数ECUを接続した状態での机上確認)、実機評価(全ECUを実機に搭載した状態での評価)と3ステップありますが、今回の開発実例ではECUが1だけ かつ 実機試験のリスクが少ないので、単体評価と結合評価は実施せずに実機評価のみを行います。自動車の制御開発など、ソフトのバグが事故につながる可能性がある場合は入念に単体評価・結合評価を行い、十分にソフトの品質を高めてから実機評価に入る必要があることに注意してください。
## 手順① 実機の用意
下図のようなライントレースロボットを作成しました。
マイコンはArduino Unoを使用。
ライン検出センサとしてフォトリフレクタ(LBR-127HLD)を使用。
タイヤ、キャスター、ギアボックス、ボディーはタミヤのパーツを使用。
![ロボット本体.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643741/63954cb7-61ef-a1f3-79d3-f6fed7298793.png)
## 手順② ソフトの書き込み
SimulinkとArduinoマイコンを接続して制御モデルを書き込みます。
SimulinkとArduinoマイコンの接続にはSimulink Support Package for Arduino HardwareというMathWorks社公式のアドオンを使用します。
(https://jp.mathworks.com/help/supportpkg/arduino/index.html)

## 手順③ 動作確認
要件定義工程で定義した各要件をすべて満たしたソフトが完成しているかどうかを実機を使って確認します。MILSで制御ロジックの確認が済んでいるのでライントレース制御のパラメーターを微調整するだけで完成しました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/ULD6AHRHa7w" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
以上で全要件の動作確認が完了です。
評価工程が完了したので開発プロジェクト完了とします。

# おわりに
　ライントレースロボットを題材にモデルベース開発を実践してみました。開発の流れを大まかに理解していたくことができれば幸いです。
　実際の開発業務は規模が大きく、関連するメンバーも多岐に渡ります。評価工程に入ってから不具合や認識の齟齬が発生してしまうと大きな手戻りとなってしまいます。モデルベース開発を活用して効率的に開発を行えるようになっていきましょう。

モデルベース開発を中心に組み込み系の情報をまとめたホームページを作成中です。よければ覗いてみてください。
[モデルベース開発入門](http://lets-mbd.com/)