人間のあるべき姿の探索

思索・人形・エンジニアリング

ロボットのプログラムをレイヤードアーキテクチャで考える

少し前にドメイン駆動設計の本を読んだり勉強したのですが、手元のロボットのプログラムをリファクタリングしているとき、突然「似ている…!」と思ったので、書いていきます。

レイヤードアーキテクチャとは

詳細は省きます。ドメイン駆動設計というソフトウェアの設計手法では、ドメインモデリング(業務知識をモデルとして表現)に着目し、それをコードに落とし込んでいきます。業務知識を一か所にまとめることでコンポーネントごとの責務が明確になりコードの保守性が上がったりするのですが、そのコンポーネントの依存関係を階層構造にしたのがレイヤードアーキテクチャです。

レイヤードアーキテクチャは4つの層からなっており、外部からのrequest/responseを担当するInterface層、アプリケーションレイヤでユースケースを表現するusecase層、業務ドメインに関する値及び振舞いを集約したdomain層、DBへのデータの永続化などの外部との接続方式を担うinfrastructure層からなります。*1

一般的にリクエストを受け付けて何かデータやページなどのコンテンツを返す…と考えるとWebAPIやブラウザーアプリケーションの実装に使えるイメージがあるんですが、ロボットにも使えそうです。ちなみに、依存性の逆転でInfrastructure層がDomain層を見ていますが、今回はそういったDDD的な関係性は置いておいて、層ごとの責務の分離に着目します。

マーの計算レベル

ロボットの話に進む前に、少し遠回りして、人間の話をします。計算論的神経科学者のデビッド・マー神経科学の理論的理解の枠組みとして、計算理論、表現とアルゴリズム、実装の3つのレベルを提唱しました。生化学的に脳を物理的な観点で扱っていた神経科学を数学的な構造によるモデル化などの手法を通じて、理論的に理解する試み…と言えばよいでしょうか。そして、3つのレベルは順番に、「脳が果たすべき目的は何か、それを果たすためにどのような計算が必要か」「計算理論のレベルで定められた計算を遂行するための表現や、具体的なアルゴリズム」「それらの目的・具体的な計算をハードウェアで実現するためにどうすればよいか」と分けられます。

ロボットを作る…と考えたときに、人間を同じ枠組みとして捉えると結構似ていることが分かります。僕は顔のロボットのコードをリファクタリングしながら気づいたのですが、まずモータを動かす為のコードを書いていて、PWMで電気的信号を送る実装とソフトウェア的な可動域の制約や動きの制御を分離するべきだと考えました。これが、それぞれ実装レベルと表現とアルゴリズムレベルに対応づきます。そして、モータが動くことの意味付けとして、ロボットがある場所を見るという行動目的があります。これが計算理論レベルに対応付けられるのではないかと考えました。

ちょっとコードをべた書きすると、以下のイメージです。

Robot.Look(yaw, pitch, roll); // 計算理論レベル

void Look(yaw, pitch, roll){ servoYaw.MoveTo(angleYaw), servoPitch.MoveTo() ...// 表現とアルゴリズムレベル

void MoveTo(angle){PWM.setPWM(150, 600, pulse(angle * rate))} // 実装レベル

レイヤードアーキテクチャを振り返る

具体的なコード片を書いたところで、レイヤードアーキテクチャと先ほどの計算レベルが似ていることに気づきます。以下の図のようなイメージになります。

もう少しイメージを膨らませてみます、ロボットといえば定義的には入力、制御、出力が揃っていることが条件となります*2。これを図にすると、こうです。

これは完全な自律ロボットが外界とコミュニケーションする様子です、ロボットの具体的なイメージは何でもよいですが、例えば監視カメラもカメラ映像がセンサとして入って、人を見つけたらその方向に動く為の制御を計算して、モータが動いてカメラが人の方を向きます。
そして、これを人間が遠隔操作するロボットに置き換えるとどうなるでしょうか。こうなります。

ロボットと操作者の人間の構造が同じ話はまた別の機会にしますが*3、ロボットの制御系は人から命令を受けてモータを動かし、そして代わりに動いた先の映像を操作者に送り返しています。…Request/Responseですね?埋まりました。

ロボットのプログラムでもレイヤードアーキテクチャができてうれしい!ちなみに自律ロボットでも同じ仕組みで作れて、Interface層に人間によるリクエストだけではなく自動操作アルゴリズムによるリクエストを受ける窓口を作ればOKです。そういう意味では、フロントUI→バックエンドWebAPI→DBの構造と(経路計画等のレベルの)制御アルゴリズム→遠隔操作ロボットの仕組み→アクチュエータの構造はかなり似通ったものになりますね。
DDDの例を見るとIntarface層がUIとして存在しInfrastructure層にDBやその他外部APIが接続されるイメージからWebAPIやブラウザーアプリケーションの例を見かけることが多いと感じていたのですが、Infraはハードウェアにつながるし、UIは別に自律操縦プログラムの受け口として存在していてもよいわけで、応用先は結構広いんじゃあないかと思います。

終わりに

DDDについては、「DDDが必要になるくらい業務ドメインが複雑な場合、そのための要件定義や言葉のすり合わせが大変だよね」といった趣旨のTweetを以前みたことがあり、そうだね…という気持ちになったことがあります。社会人経験が浅く業務とは…?という人間からするとそのレイヤーの気持ちはわからないので、まずは自分が知っている領域で何か書いてみるのも面白いかもしれないですね。

少し前に読んでいた構造主義の入門本*4で人類学者のレヴィ=ストロースが見つけた部族内のコミュニケーションでのルール(婚姻クラス)がクラインの四元群と似ているのを発見した記述があったのですが、僕も「ロボットが人間のモデル化故にマーの計算レベルに当てはまるところがあり、さらにはレイヤードアーキテクチャの層の分け方にも通ずるところがある」と気づいた時は数学の発見的な喜びがありました。

触れていきたいですね、様々な物事に隠された「構造」に…

*1:かなり参考になりました

【Go】DDD + レイヤードアーキテクチャでREST APIを実装する | みんたく

*2:諸説ありますが、伝統的にはそう

*3:元々遠隔操作のモデル化のために作っていた図なので、その背景を強めに入れたブログを書きます

*4:不勉強ゆえに、構造主義を知らずにポスト構造主義の思想が登場する書籍を読んで、この本には意☆味☆不☆明な思想!と泣いていたので、こうすればよかったんだ~!と叫びながら構造主義の本を買いました