ObjectSquare [ 2004 年 7 月号 ]

[技術講座]


動くもの主義! オブジェクト工房

第 1 弾 ライントレーサ・シミュレータ

〜 前編 分析モデルと動くものはこれだ! 〜

株式会社 オージス総研
技術部
黒田 洋介
Kuroda_Yousuke@ogis-ri.co.jp


忙中閑あり・・・とは言いますが、忙しい毎日の息抜きがわりに、ちょっと面白いアプリをネタにしてオブジェクト指向をしてみませんか? 今回のお題はライントレーサのシミュレータです。ライントレーサとは、ラインに沿って走るロボットのことですが、ライントレーサをネタに、「カナリマジメ」にオブジェクト指向してみました。


目次

1. はじめに
2. どんなシミュレータにするか
3. 分析
4. 動くソフトウェアはこれだ!
5. 参考文献


1. はじめに

「動くもの主義! オブジェクト工房」の第一弾は、ライントレーサのシミュレータです。 「なんで、ライントレーサ・シミュレータ???」と思われた方も多いかと思います。 最初の記事なので、何か面白いネタで、なおかつオブジェクト指向が生きてくるものが良いと考えました。

まず、頭に浮かんだのは、視覚に訴えるようなソフトです。美しい/面白いスクリーンセーバーなどは良いですね。 しかし、視覚に訴えるものは面白いとは思いますが、オブジェクト指向でやるメリットが出てくるか、判断がつきません。 次に浮かんだのは、機械を制御するソフトです。 モーターなんかがついていて動き回るようなものはさわっていて面白いです。 機械を構成する部品をオブジェクトに見立てることもできるので、オブジェクト指向の威力も存分に発揮されることでしょう。 しかし、機械を準備することはなかなか大変で、本職の仕事としてでもない限り、なかなか難しいものです。

そこで、オブジェクト指向の威力が発揮できる「機械をシミュレートするソフトウェア」・・・それもリアルタイムに目で確認できるものが良いと考えたわけです。 機械を制御する組み込み系開発において、シミュレータにはいくつかのメリットがあります。 まず、実機を準備するコストを下げることができます。次に、プログラムを実機に載せるという作業を行わずにすみます。 他にも、機械をいじる手間が必要ないなど、シミュレータのメリットはさまざまです。

シミュレートする対象として、ライントレーサを選んだきっかけは、UML ロボコン*1にありました。 UML ロボコンとは、レゴ*2で作ったロボットに、ライントレース(つまり、ラインに沿って走ること)が可能となるようなソフトウェアを載せて、その設計(UML モデル)の美しさとライントレーサの速さを競う大会です。

レゴには RCX というコンピュータ部品があるので、これにソフトウェアを載せるのですが、PC から RCX へのプログラム転送時間の長いこと長いこと・・・。ちょっとソフトウェアを変更するだけで何分間もかかるので、ちょっとしたアイディアを試したいと思っても、転送時間に苦しめられます。また、ハードウェアを取り扱うわずらわしさ(レゴいじりなので基本的に楽しいですが)もあります。

「手ごろなシミュレータがあればいろいろ試せるのになぁ・・・」とは、思っていたのですがロボコンの準備期間中にそんなソフトを書く余裕があるはずも無く、気が付くと大会は終わってしまいました。考えてみると、これほど「動くもの主義!」にふさわしい題材もなかなか無いのです。現実世界をベースにするため、オブジェクトに落とし込みやすく、ソフトウェアのみなので、環境さえそろえれば誰でも実行できます。また、視覚に訴えやすいメリットもあります。

というわけで、「動くもの主義! オブジェクト工房」の第一弾は、ライントレーサのシミュレータとなりました。 本記事はシミュレータを作ってみたい方はもちろん、開発の流れを明確にしているので、オブジェクト指向開発をなぞってみたい方も楽しめると思います。 また、シミュレータが表現する世界とシミュレータそのものという二重の関心事からモデリングを行うため、多重の関心事を表現するモデルはどういうものかという点にも触れられると思います。 「シミュレータを作成する」という狭い枠にはまらないよう、オブジェクト指向やモデリングに興味があればそれなりに楽しめるものを心がけました。 どうぞ、ごゆっくりと「動くもの主義!」をお楽しみください。

*1 筆者は 第 3 回 UML ロボコンに参加していました。

*2 レゴとはブロック玩具です。さまざまな形のブロックを積んで好きな形(車など)を作って遊ぶためのおもちゃです。 最近は、モーター・光センサーやそれらを制御する小型のコンピュータを搭載したブロック(RCX という部品)も登場しました。 これによって、モーターの動きなどを記述したプログラムを転送することで、レゴブロックを思い通りに動かすことも可能です。

2. どのようなシミュレータにするか

■ シミュレータの概要

以下のようなシミュレータを作ることを目標としたいと思います。

シミュレータの役割としては、大きく分けると次の二つのものが思い浮かびます。一つは、ある特定の環境を再現するもの。もう一つは、ある問題を解くための環境を整えることです。本シミュレータは、後者により多くの重点を置くことにしました。ラインをトレースするアルゴリズムはどのようなものが良いのか、という問題を解くためのシミュレータであるということです。

なぜ「ある特定の環境を再現するもの」に重点を置かなかったのかを書きたいと思います。ある特定の環境を再現する・・・つまり、一種のエミュレータのような機能があると、このシミュレータであるアルゴリズムを試して、アルゴリズムの部分だけ実際のハードウェアに載せるなんてことも可能になります。これは大変なメリットです。しかし、これがライントレーサのような種類のシステムでは非現実的です。ある特定の環境が提供する API をそろえるだけであれば簡単ですが、ハードウェアの動きをソフトウェア上で再現するとなると、それだけで力尽きてしまいます。

それよりも、今回のシミュレータでは、ラインをトレースする機械のアルゴリズムはどのようなものか検証できるという点に、集中することにしました。

ライントレーサのシミュレータということで、線に沿って動きつづける物体を画面上で表現できればよいと思っています。実機ではないので、細かなチューニングを行うのは無理がありますので、あくまで基本的なアルゴリズムを確認するためのものにします。まずはシミュレータの仕様を起こしたいと思います。

■ アプリケーション(シミュレータ)の仕様

シミュレータの仕様の中に「シミュレーションの時間間隔は 0.2 秒」という記述があります。 これは、0.2 秒おきにシミュレータの世界を更新するということです。 つまり、ライントレーサの思考やライントレーサの位置情報の更新が 0.2 秒ごとに行われるということです。


図 2.1 ライントレーサが攻略するコース

■ シミュレータが表現するハードウェア(ライントレーサ)

※ 実際の車のように前輪や後輪の向きを変えることで方向転換するものではありません。停止して回転することで、方向転換する機体だと思ってください。詳しくは図 2.2 を見てください。実際の車のようにすると、ライントレーサの動きが難しくなると判断しました。


図 2.2 車体の動き

次に、車体の構成です。センサー一つのライントレーサと書きましたが、具体的には図 2.3 のような構成となっています。先端にセンサーがついていて、このセンサーで地面の色を調べながらコース上かどうかをライントレーサは判断します。その判断を元に直進もしくは回転して進行方向を変更してラインに沿って走ることになります。


図 2.3 ライントレーサの車体の構成

ライントレーサの制御方式は、0.2 秒おきにセンサーの値を調べて、進むか方向転換するか決定するシンプルな動作にしたいと思います。シングルタスク(シングルスレッド)のポーリング方式を想定しています。シミュレータが複雑になりすぎないように、マルチタスク方式やイベントドリブン方式は採用しませんでした。

3. 分析

■ 開発の流れ

さて、いよいよ開発に取り掛かりたいと思います。下図(図 3.1)に開発の流れをまとめてみました。 開発プロセスは eUML(参考文献[3])を参考に作成しました。 ポイントとしては、「シミュレーション世界内の動的構造の分析」という段階を作っていることです。 なぜ「動的構造の分析」と段階を分けたのかというと、シミュレーション世界の内外を区別して考えることで、整理して作業が進められると考えたからです。


図 3.1 開発の流れ

■ 概念モデルの作成

概念モデルは、2 つの観点から作成することにしました。 1 つはライントレーサの構造はどのようなものかという観点であり、もう 1 つはシミュレータに必要な情報は何かという観点です。

まずはライントレーサの構造の概念モデル図(図3.2)を作成してみました。 概念モデル図を作成したのは、シミュレータ上で表現する機体の構成を把握しておかないと、シミュレータとして何を作成すればよいか判断がつかなかったからです。


図 3.2 ライントレーサの構造の概念モデル

図 3.2 では、「ロボット」(ライントレーサ)は「光センサー」の値(明度)を見てコース上かどうかを判断して、「駆動部」(車体の動きを制御する部分)に進むか止まって方向転換するのか命令を下すという動作を想定しました。 「モーター」(というか推進力を作り出す部分)は、現実世界では「駆動部」を実現するのに必要です。 しかし、「モーター」というものをシミュレータ上で表現すると、自由度が高すぎる問題があります。 なぜなら、「モーター」は前に進むだけに使われるとは限らないからです。(扇風機だってモーターで作れます。) この場合、自由度を上げると実現コストが膨らむと判断しました。 「駆動部」を作ることで、車体の前進や回転を実現するということがはっきりします。

以上のことから、シミュレータが「ロボット」に対して提供しなくてはいけないものは、「駆動部」と「光センサー」であることがわかりました。 なぜなら、この二つを制御するインターフェースが提供されていれば、「ロボット」にとって、制御する先が現実世界であるか、シミュレータの世界であるかは関係がないからです。

図 3.3 はシミュレータに必要な情報の概念モデルです。


図 3.3 シミュレータに必要な情報の概念モデル

図 3.3 は、センサーが感知する対象の情報をシミュレータで準備する必要があることを示しています。 つまり、現実世界で線を引いたコースを作成するように、シミュレータ上でも現実のコースに相当する情報を準備する必要があるということです。 これで、シミュレーションを行うには何が必要かという情報を収集することができました。

■ 要求分析

概念モデルが仕上がったので、ユースケース図(図 3.4)を書きます。 ユーザーの目的としては、シミュレーションの結果をリアルタイムに目で見て確認できることが挙げられます。


図 3.4 ライントレーサ・シミュレータのユースケース図

ユーザーの目的達成を補助するためのユースケースということで、「シミュレータの設定をする」ユースケースなども必要かもしれません。シミュレータの時間間隔やライントレーサの仕様など、シミュレーションに影響のある変更設定を行う部分の要求が出てくるかもしれないからです。ただし、今回はユースケースとしては挙げません。

ユースケース名 ライントレーサをシミュレートする
ユースケースの目的 ライントレーサの動きをシミュレートし、その結果をリアルタイムに画面上で確認すること
シナリオ ユーザーがシミュレータを起動したら、ユーザーがシミュレータ終了するまでシミュレーションが実行されます。ユーザーはシミュレータが実行されている間、ライントレーサの動きをリアルタイムに視覚的に確認することができます。また、シミュレータを実行している間、ユーザーは視点を変更することで、さまざまな角度からライントレーサの動作を確認することができます。

「ライントレーサをシミュレートする」ユースケースの内容としては、以上の点が確認できれば現段階では十分です。シミュレータを考えるにあたって一つ重要になるのは、どこからどこまでがシミュレートする対象(つまりライントレーサ)の問題領域(ドメイン)で、どこからどこまでがシミュレータのソフトウェアとしてのドメインかを明らかにしておくことです。これを怠るととんでもない混乱に突き落とされてしまう恐れがあります。少しユーザーの視点から離れ、何を解決しなくてはならないのかを整理します。

■ ドメイン分割

ドメインを分割する前に、これからの分析作業で何を明らかにしていかなくてはならないのか、列挙してみました。

少なくとも、上記に列挙した項目を明確にしないと動作するシミュレータにはなりません。掘り下げ方次第では、非常に複雑な問題になる可能性があるので、できるだけ上記は分けて考えたいです。ここまでをふまえて、どのようなドメインがあるのかを記したドメインチャート(図 3.5)を作成しました。


図 3.5 ドメインチャート

図 3.5 で色分けしているのは理由があります。黄色の部分はライントレーサに関する部分です。他のアプリケーションには再利用性が低い部分です。水色の部分は描画に関する部分です。この部分は逆に他のアプリケーションに適応しやすい再利用性の高い部分といえます。緑色の部分はシミュレータに固有の部分です。「LineTracer」ドメインや「Mechanism」ドメインを取り替えれば別のシミュレータとして動かすことも期待できます。フレームワークっぽいところです。今のところ、依存関係の問題で取り替えられるようにはなっていません。しかし、少し変更すれば取替え可能になります。

ドメイン名 説明
「LineTracer」ドメイン ライントレーサをどのように実現するかというドメインです。
「Mechanism」ドメイン 「LineTracer」ドメインに機体の動き(具体的にはモーターやセンサー)を制御するためのインターフェースを提供し、機体を動かすための実装方法に関心を持つドメインです。
「Environment」ドメイン コースの状態など、シミュレータ世界の中の「環境」をどうやって表現するかというドメインです。「Mechanism」ドメインに地面の色などを知るためのインターフェースを提供します。どのようなコースであるかなどの情報もここにあります。ライントレーサがコースに関する知識を持って攻略しようというアルゴリズムをとる場合は、「Linetracer」ドメインの中で再度コースをモデル化しなおす必要があります。
「Rendering」ドメイン 「Mechanism」や「Environment」に描画するためのインターフェースを提供し、どのように描画するかというドメインです。前述の通り再利用性が高く資産化しやすい部分です。
「Simulator」ドメイン シミュレーションの進め方に関するドメインです。ユーザーに対しては見た目を変化させ、ライントレーサに対しては思考をさせることで、シミュレーションを進めていかなくてはなりません。
「UI」ドメイン ユーザーとのやり取りに関するドメインです。 ユースケース記述には、ユーザーとのやり取りがそれほど多くないので、今回はほとんど内容がないドメインかもしれません。

図 3.6 にて、ドメイン間のコラボレーションをシーケンス図で表現してみました。流れを追っていくと、UI(※)は 0.2 秒間隔で「Simulator」ドメインにシミュレータを進める命令を出します。「Simulator」ドメインは「Mechanism」ドメインに車体を動かすことを命じた後、「Rendering」ドメインに命じて描画を行います。そして、「Linetracer」ドメインに思考をさせて、次に車体がどう動くのかを決定させます。

※ UI が時間間隔に応じてシミュレーションを進めるというのは妙に感じる方もいるかもしれません。ここでは、方式はどうあれ、UI がシミュレーションを進めるメッセージを飛ばす責務を持っていることを確認しました。実は、こういう構造にすると、ユーザーが手動でシミュレーション中の時間を進めたい場合(「進む」ボタンを押すと 1 単位時間(0.02 秒)進むような場合)などにも対応できるのではないか、という下心がありました。これによって、「Simulator」ドメインの責務がやや小さくなって、独立したドメインとして存在する意味が減ったかなという懸念はあるのですが。


図 3.6 「ライントレーサをシミュレートする」ユースケースにおけるドメイン間のコラボレーション

シミュレータ自体が大きなシステムというわけではないのに、ドメインを細かく分割しすぎと思われる方が多いかと思います。一例として、「Environment」ドメインについて考えてみたいと思います。「Environment」ドメインの責務を見ても「地面の色を取得する」という一見すると単純な責務しか持っていません。ただし、地面の色を決定するにはさまざまな方法があります。以下に地面の色を決定する方法をいくつか挙げてみました。

上記に挙げたのは一例に過ぎませんが、「Environment」ドメインの実現はさまざまな方法があります。それぞれの方法は組み合わせ可能であり、多くの方法を組み合わせて実装するとすればかなりの大きさになります。UML ロボコンに参加された方はわかるかと思いますが、環境の変化によってライントレーサの動きはかなり変わってきます。光源の近くでは、コースを表す黒いラインも白く見えてしまうかもしれません。こうした環境の微妙な変化を実現するには、複雑なモデルが必要になるかもしれません。

考え始めるときりが無いので、「Environment」ドメインを掘り下げるのはこの辺でやめておきたいと思います。ドメインとして独立させた背景としては、以上のような事情がありました。シミュレータは、どれだけ精密にシミュレーションするかによって、同じ題材でも複雑さが変わってきます。後々、複雑さを表現する余地を残すには、ドメイン分析をしっかりと行う必要があります。

さて、ドメインの分割が完了しました。これをもとにクラスを抽出して、分析レベルのクラス図を作成したいと思います。

■ 静的構造の分析(分析レベルのクラス図)

クラスの抽出は、ドメインごとに行います。

抽出したクラス一覧
ドメイン名 抽出したクラス
「LineTracer」ドメイン Robot
「Mechanism」ドメイン Body(ロボットの車体), Sensor
「Rendering」ドメイン Frame, FrameObject(描画物体), Landscape(地面を描画するクラス), Mesh(物体の形状)
「Environment」ドメイン Land(地面の情報をもつ)
「Simulator」ドメイン Simulator
「UI」ドメイン SimulatorWindow

下図(図 3.7)は分析レベルのクラス図です。「Simulator」クラスは、「Robot」クラスや「Body」クラスの時間を進める役割を持っています。また、「FrameObject」クラスに描画命令を出す役割も担っています。「Sensor」クラスの役割は、「Land」クラスから地面の色(明度)情報を取得することです。「Robot」クラスは、「Sensor」クラスから取得した地面の色情報を元に、「Body」クラスに動作命令を出します。「Body」クラスは「Simulator」クラスによって時間が進められたときに、「Robot」クラスからの命令を元に車体の位置を動かす役割を持っています。

ちなみに、ロール名が動詞になっているのは、Executable UML という本で紹介されている記述方法です。詳しくは参考文献[2]をご参照ください。


図 3.7 分析クラス図(UI 以外の全ドメインを対象にしたクラス図)

少しわかりにくい「Rendering」ドメインについて説明します。今回描画対象となるのは、地面(Land)とライントレーサです。ライントレーサは本体(Body)とセンサー(Sensor)から構成されています。FrameObject クラスは画面上で物体の描画を受け持つクラスであり、本体とセンサーの描画を担当します。Landscape クラスは地面の描画を担当します。両クラスの親クラスとして、Frame クラスも作成します。

さて、描画を行うには元となる情報が必要です。必要となるのは、画像ファイルや座標情報です。 ここでいう座標とは、ライントレーサの見た目を直線で表現する場合、直線の始点と終点に使うような座標という意味です。 ここではこうした描画用の情報を形状(Mesh)と呼びます。

Mesh を描画するのは Frame クラスのサブクラスです。仮にライントレーサの本体(Body)がサイコロ形だったら、サイコロのような立方体の形状情報は Mesh が持ち、FrameObject はその情報を元に描画を行います。地面は今回は凹凸の無い平らな地面を想定していますが、凹凸情報もまた Mesh に蓄えられ、Landscape によって描画されます。地面も FrameObject で書いても良いのですが、地面にコースを描かないといけません。そのため、FrameObject とは別のクラス Landscape を作成することにしました。ここまでの分析を元に、「Rendering」ドメインのクラス図を書きました。(図 3.8)


図 3.8 「Rendering」ドメインに関するクラス図

ただ、Body や Sensor の形状情報は、シミュレーション中に利用するかもしれません。Sensor の形によっては、光源の光を遮って影を作るなんてことがあるかもしれないのです。シミュレーションに影響を与える情報を「Rendering」ドメインのみが持つのは不適切であることが予想されます。今回は、シミュレーション世界内で光源を考慮するつもりは無いので、問題は発生しないと考えています。

描画対象物に必要なもの一覧
描画対象物 必要なもの
地面 (板のような)形状データ、(板に貼り付ける)コース画像
本体(Body) 形状データ
センサー(Sensor) 形状データ

静的構造が明らかになったので、動的構造の分析を開始したいと思います。

■ 動的構造の分析

これまでの分析を元に、シーケンス図(図 3.9)を作成しました。0.2 秒ごとに「SimulatorWindow」クラスが「Simulator」クラスに時間を進めるように指令を出します。すると、「Simulator」クラスは「Body」に動くよう命令を出します。「Body」は自身が動くことによって変わった座標情報を、自身を描画する「FrameObject」に渡します。次に、感知を行い、「Sensor」はコース上かどうかの判定を行います。感知が完了すると、「Robot」が思考を行い、次の「Body」の動き(直進か回転)を決定します。「Robot」の思考が完了すると、描画が行われます。


図 3.9 分析レベルのシーケンス図(シミュレータの動作を記述)

これで、どのようにシミュレーションが進められていくのかを理解することができました。これで、シミュレータが作れそうですが、「Robot」クラスの思考に関するアルゴリズムが定まっていないので、決定する必要があります。

■ シミュレーション世界内の動的構造の分析(ロボットクラスの状態遷移)

下図(図 3.10)はライントレースのためのアルゴリズムを表したステートチャート図です。今回はアルゴリズムを掘り下げる気はないので、簡単なアルゴリズムをとります。ライン上にあるときは直進し、ラインから外れると回転してラインを探します。簡単なアルゴリズムですが、よほど難しいコースでない限り走破することができます。


図 3.10 ロボットクラスの状態図

さて、ここまで分析を確認してきました。分析が終わったということは、パフォーマンス等はともかく最低限動作はする状態になっていないといけません。分析でどの段階までやるかは、いろいろと意見が出てくるかと思いますが、この記事では分析が終わったということは、「最低限実装するための情報が揃った」ということにしました。

4. 動くソフトウェアはこれだ!

さて、ここまで開発の流れということで、分析を見てきました。次回に設計と実装の話に入るとして、先に動くソフトウェアの紹介をします。

ファイルのダウンロード

■ 動作環境(※)

OS: Windows2000(要日本語 .NET Framework 1.1 以降, 要 DirectX9 以降)
CPU: PentiumV 700MHz 以上
VideoCard: 16MB 以上のビデオメモリ
※ 動作環境を満たしても、性能の関係で動作が鈍くなることはあります。
※※ ソフトウェアの操作については同梱の「readme.txt」をご参照ください。

■ スクリーンショット


斜め上から見た図


真上から見た図

次回はいよいよ設計とソースコードの解説に入りたいと思います。ソースコードは次回までお預けということで、焦らすようで申し訳ないですが、その間に筆者はせっせとソースコードのリファクタリング・コメント追加を行って、読むに耐えるソースコードにしたいと思います。余力があれば没になった考え方や設計案も紹介できたらと考えています。

5. 参考文献と Web ページ

[1] ブルース・ダグラス著 渡辺博之監訳 株式会社オージス総研訳 「リアルタイムUML 第2版」(翔泳社、2001 年)
[2] スティーブ・J・メラー、マーク・J・バルサー著 二上 貴夫、長瀬 嘉秀監訳 Executable UML 研究会翻訳 株式会社テクノロジックアート編集「Executable UML」(翔泳社、2003 年)
[3] 渡辺博之、渡辺政彦、堀松和人、渡守武和記著「組み込みUML 〜 eUMLによるオブジェクト指向組み込みシステム開発」(翔泳社、2002 年)
[4] アリスター・コーバーン著 ウルシステムズ株式会社監訳 山岸 耕二、水谷 雅宏、矢崎 博英、篠原 明子訳 「ユースケース実践ガイド―効果的なユースケースの書き方」(翔泳社、2001 年)

レゴ社の公式ホームページ
https://www.lego.com/

第3回 UML ロボットコンテスト
https://with.esm.co.jp/2004/uml-robocon2004/toppage.htm

UML Forum2004 の UML ロボットコンテスト告知ページ
https://www.otij.org/umlforum2004/robocon/

[広場の関連記事] 組込みトレーニング向け実習教材の開発記録 〜マインドストームはオブジェクト指向の夢を見るか?〜
https://www.ogis-ri.co.jp/otc/hiroba/technical/lego/index.html

[広場の関連記事] 第 3 回 UML ロボットコンテスト参戦記
https://www.ogis-ri.co.jp/otc/hiroba/Report/UML_Forum2004/robot/index.html



© 2004 OGIS-RI Co., Ltd.
Index Next
Index Next