Skip to content.

Sections
Personal tools
You are here: Home » 技術文書 » UML » UML超入門_第3章

Document Actions
UML超入門

(株)永和システムマネジメント    平鍋健児・梅田 政利
作成:初出 技術評論社刊『UML PRESS Vol.1』

3章では,組み込み分野に近いちょっと面白い例として, LEGOMINDSTORMS(TM)(*)を使ったロボット制御を例題にして,実際の開発の流れを追ってみたいと思います.

   第3章 UMLを使ってみよう (LEGO MINDSTORMS(TM)を動かす)


第2章ではUMLの基礎について勉強しました。 ここでは、UMLを実際のアプリケーション開発に取り入れるためのステップとして、 UMLを利用した分析/設計/実装に取り組んでみましょう。 LEGO MINDSTORMS(TM)が実際に動くので面白いと思いますよ。とても小さいシステムなので、気楽に読んでみて下さい。

LEGO MINDSTORMS(TM)

LEGO MINDSTORMS(TM)(レゴ・マインドストーム)は, LEGO 社(デンマーク)とMIT(マサチューセッツ工科大学)が共同開発した, レゴブロックを使ったロボット作成キットです. これを教材にしたロボット作成教室やロボット大会,さらには組み込みオブジェクト指向のトレーニングなども, 近年多く開催されています.(*)


脚注 (*) LEGO MINDSTORMS(TM)に関して詳しくは,

http://mindstorms.lego.com/japan/
http://with.esm.co.jp/
http://www.ogis-ri.co.jp/otc/training/kumikomi-start.html

などを参照してください.


LEGO MINDSTORMS(TM)を制御

UML開発の題材として、LEGO MINDSTORMS(TM)で作成した黒線に沿って走行する ロボットを制御するアプリケーションを作成しましょう。ロボットはトレーサーと名付けました。 RCX(LEGOを制御するユニット)上で動くアプリケーションの開発環境としては、 Java言語のleJOSやC++言語のlegOSなどがあります。 今回は、実際にleJOSを使用して、Windows上で開発します。 また、leJOSでは、赤外線通信にシリアルのIRタワーが必要となっていますので、 LEGO MINDSTORMS ROBOTICS INVENTION SYSTEM(TM) 1.5 をターゲットとします。 2.0には、USBのIRタワーが付属しています。

要求仕様

RCXには3つの入力ポートと3つの出力ポートが用意されていて、 トレーサーでは1つの入力ポートと2つの出力ポートを使用します。 1つの入力ポートに光センサーが接続されているトレーサーは、光センサーによって黒線を検出し、 2つの出力ポートに接続されたモーターを制御することによって、黒線の左縁に沿って走行します。 ユーザがRUNボタンを押すと動き始め、ポート2に接続した光センサーの値が、黒を示す値であれば左ターン、 黒以外の値であれば右ターンを行い、それらを繰り返すことでガクガクしながら走行します。 モーターは、左タイヤ用をポートAに、右タイヤ用をポートCに接続します。 左ターンは左タイヤの停止と右タイヤの前進で行い、右ターンは逆の操作となります。 停止は、ON/OFFボタンで強制的に行います。 ロボットの製作については、LEGO MINDSTORMS ROBOTICS INVENTION SYSTEM(TM) 1.5に 付属のCONSTRUCTOPEDIAを参照して下さい。初めてでも40分くらいで完成するでしょう。

要求分析

ユースケース図を中心に、ユースケース記述と状態図を用いて、要求を分析します。 要求が単純なため今回はこれらで十分でしょう。 ユースケース記述は、例外処理がある場合にはイベントフローで作成すると良いと思いますし、 同期を取る処理がある場合にはアクティビティー図を作成すると分析に役立つでしょう。

ユースケース図
トレーサーは、線の左縁に沿って走る機能しか持っていないため、ユースケースは1つだけです。 この機能は、ユーザによって起動され、光センサー、モーターといったハードウェアを使用して実現されます。 これら全てがアクターとなるので、ユースケース図は、図1のようになります。

図1: ユースケース図

ユースケース記述
図2のように、ユースケースを文章で説明します。 「線の左縁に沿って走る」ユースケースは、 「白に向かって走る(左ターン)」と「黒に向かって走る(右ターン)」の繰り返しによって実現されます。 黒線の上から動き始めても、黒線以外の部分から動き始めてもかまわないことも明記します。 このユースケース記述は2章で取り上げた形式とは異なりますが、 コミュニケーションが十分にとれるものであれば、フォーマットにこだわる必要はありません。 このようにシンプルに記述しても良いでしょう。

図2: ユースケース記述

┌────────────────────────────┐
│「線の左縁に沿って走る」ユースケース          │
├────────────────────────────┤
│1.黒線の上にいる場合、左ターンしながら黒線の外を目指す│
│2.黒線から外れた場合、右ターンしながら黒線を目指す  │
│3.1-2を繰り返す                  │
│*.2から始まっても良い                │
└────────────────────────────┘
状態図
システムをひとつのオブジェクトと見なして、状態遷移を表現します。 今回はユースケース記述を読むことによって、システムの動作がイメージできてしまいますので、 冗長に感じるかもしれませんが、図で見るとより直感的なので作成しておきましょう。特に通常の開発では、 動作イメージをつかむのに役に立つでしょう。図3のように、「白検出」と「黒検出」イベントにより、 「白に向かって走る(左ターン)」と「黒に向かって走る(右ターン)」の状態を遷移します。

図3: 要求分析状態図

システム分析

クラス図、状態図、相互作用図を用いて、システムの概要をイメージできるようにブレークダウンします。 この段階では、実装する言語に依存しないので、わかりやすいように日本語で分析しています。

クラス図
全体のクラス構成のイメージを図にします。ここでは、言語に依存したスレッドやイベント通知の構造には触れません。

図4: システム分析クラス図


図4のように、ライン監視部クラスと行動制御部クラスでは、activeステレオタイプを付けることで、 それぞれを別スレッドで動かすことを明示していますが、どのようにスレッド化するかについては明示していません。 ライン監視部クラスが行動制御部クラスにライン状態を通知し、通知された状態によって、 行動制御部クラスから駆動制御部クラスに指示を出します。ライン監視部クラス、駆動制御部クラスは、 それぞれのハードウェアを操作するクラスを集約で保持します。単方向で表現できる関連は、 それが明確になった時点で単方向にしてしまいましょう。


状態図
ライン監視部では、ライン状態の変化を検出した時のみ通知したいため、それを状態遷移によって実現します。 他のクラスでは、状態が必要無いため、ライン監視部の状態図のみ作成します。

図5: システム分析ライン監視分状態図


図5のように、ライン監視分の状態図は、システム全体の状態図と似たものになります。 しかし、最初のライン状態を通知しないことには、行動制御部では動作することができませんので、 初期状態として、ライン上状態でもライン外状態でもないアイドル状態を作成しましょう。 起動時はアイドル状態となり、最初に検出した状態により、ライン上状態かライン外状態のどちらかに遷移することにします。 その後は、ライン上状態とライン外状態の間で、状態遷移を続けます。ある状態に遷移した時には、 その状態のエントリーを実行します。ライン上状態とライン外状態のエントリーでは、 自分の状態を聞き手(行動制御部)に通知しています。

相互作用図
線の状態を3度問い合わせた結果、「ライン上→ライン上→ライン外」であったというストーリーで、 図6にシーケンス図を、図7にコラボレーション図を示します。時系列に沿った処理の流れや、 システム構成がイメージできると思います。ここで、メッセージへの番号の振り方について説明します。 メッセージは、1から順に振られていきますが、操作呼び出しが階層化した場合には、ピリオドで区切って表現します。 階層ですので、非同期呼び出しの後では、トップレベルの階層(ピリオドのない状態)となります。

図6: システム分析シーケンス図


図7: システム分析コラボレーション図
/td>

設計

クラス図、状態図、シーケンス図、コラボレーション図を、実装レベルにブレークダウンし、 パッケージ分割についても、パッケージ図で明確にします。このフェーズの成果物を見ることで、 誰が実装作業を行っても、全体の構成やインターフェースに違いが生じないレベルで作成しましょう。

パッケージ図
今回利用するjava(Java固有)とjosx(RCX関連)パッケージも含めて、図8のようなパッケージ構成にしました。 再利用性を考えて、Commo(通信)、Mechanism(メカニズム)、Control(トレーサーのコントロール)に分け、 Commo、Mechanismが再利用を目的としたパッケージになっています。分類によってパッケージ分割することは当然ですが、 できるだけ双方向の依存関係にならないように心掛けましょう。

図8: 設計パッケージ図


クラス図
前フェーズで作成したクラス図を、leJOSのパッケージを利用して実装レベルにブレークダウンしたものが、 図9のクラス図です。クラスがどのパッケージに属すかも明確にしています。 josxのSensorクラスにリスナー登録することで、変化を検出するスレッドがスタートします。そのため、 前フェーズでは、LineMonitor(ライン監視部)クラスがSensor(センサー)クラスを集約で保持していましたが、 LineMonitorはSensorListenerクラスをインターフェースにして、Sensorクラスにリスナー登録する形になりました。 Tracer(行動制御部)クラスはThreadクラスを継承してスレッド化しました。 LineMonitorクラスからTracerクラスへの状態通知には、EventFlagクラスを用います。 前フェーズでは、DriveUnit(駆動制御部)クラスは2つのMotor(モーター)クラスを持っていましたが、 ここではMotorクラスに依存する形になりました。これは、Motorクラスが静的属性A/B/Cとして、 全てのポートに接続されたモーターを管理するとともに、操作も全て静的メンバ関数としているためです。 例えば、モーターAに前進命令を出すときは、"Motor.A.forward()"となります。DriveUnitクラス自身も、 静的メンバ関数の集まりとなるため、Tracerクラスが依存する関係となっています。
図9: 設計クラス図
状態図
前フェーズで作成したライン監視部クラスの状態図を、実装レベルにブレークダウンすると図10のようになります。 エントリーには、実際のコーディングと同じレベルで記述しています。
/td>
図10: 設計LineMonitor状態図
相互作用図
ここでは図11のように、ライン外からライン上に移動するストーリーについてのシーケンス図を作成します。 ライン上からライン外に移動するストーリーについては、先のストーリーのシーケンスとほとんど変化が無いため、省略します。 同じストーリーをコラボレーション図にすると、図12のようになります。対象が簡単なこともあり、 すでに実装そのままという感じになりましたね。もっと大きなシステムでは、 コーディングと1対1になるような図を作成することは大変ですので、要点を押さえた図を作成すれば良いでしょう。
図11: 設計シーケンス図


図12: 設計コラボレーション図

実装

設計モデルを見て実装しましょう。 コンパイルの方法やRCXへのソフトの転送は、この後のコラムに書いてありますので、そちらをご覧下さい。

この章のソースコードはこちらからダウンロードできます.→tracer.lzh

まとめ

今回は対象物が簡単だったこともあり、全ての図を作成していませんが、 実際の開発でも必要な図だけを作成すれば良いでしょう。 また、要求分析→システム分析→設計の3フェーズで開発しましたが、 対象物がより複雑である場合には、システム分析フェーズと設計フェーズの間に、 アーキテクチャ設計フェーズを加えてみると良いでしょう。 反対に、熟知した問題領域である場合には、設計レベルから入っても良いでしょう。 どちらにせよ、まずはUMLを取れ入れてみることが大事だと思います。 参考までに、この記事よりもさらに賢いトレーサーロボットを題材に、 「組込み・リアルタイム向オブジェクト指向 分析・設計トレーニング」が開催されています (*)。 実開発にUMLを取り入れることを考えている方には特に有用かもしれません. この記事が、みなさんが開発にUMLを取り入れる助けになれば嬉しく思います。


脚注(*)

http://www.ogis-ri.co.jp/otc/training/kumikomi-start.html


謝辞

UMLでの分析/設計についてご教授くださっただけでなく、 この記事を書くにあたってアドバイスをくださった(株)オージス総研の渡辺博之さんに心から感謝します。

leJOSでLEGOを動かそう

Windows版を例に、インストールから実行までの手順を説明します。 作業は本当に簡単なので、LEGOを持っている方は、是非試してみることをお薦めします。 まずは、以下のサイトで、leJOS(2001.9.3現在の最新バージョンは1.0.2です)を入手しましょう。


http://lejos.sourceforge.net/


leJOSを任意のディレクトリに解凍したら、以下の設定を行います。

  • leJOSのbinディレクトリを環境変数PATHに含める
  • javaのbinディレクトリを環境変数PATHに含める(JDK1.1, 1.2, 1.3のいずれか)
  • 環境変数CLASSPATH=.を設定する
  • 環境変数RCXTTYを設定する(RS232Cがcom1の場合は不要)

これらの設定が終わったら、leJOSのファームウェアをRCXに転送します。 シリアルポートに接続されたIRタワーの前にRCXを置いて、コマンドを実行しましょう。


% lejosfirmdl -f

続いて、クラスファイルを作成しましょう。


% lejosc */*.java


コンパイルが全て通ったら、クラスファイルをRCXに転送しましょう。 転送コマンドの引数には、main関数のあるクラスを指定します。


% lejos Control/Tracer


あとは、RCXのRUNボタンを押すと動き始めます。止めるときはOn/Offボタンを押してください

≫第4章





この記事への評価にご協力をお願いします。

良かった 普通 イマイチ