キャディでエンジニア採用を担当しております片渕です。
今回は、エンジニアの社内勉強会「STUDDi」にてプレゼンがありました一部の情報(3ネタほど)を、レポート形式でお伝えしたいと思います。
STUDDIは、エンジニア全員が持ち回りで発表機会があるものですが、入社してくる方も増えてきたこともあり
- まだ一度もスピーカーになっていない方(新しく入られた方)の発表する場として優先する
- 好きな技術について思う存分語ってOK
という方針でやっておりまして、今回は
- Clean Architecture
- 自律移動ロボット
- 3D CADのデモンストレーション
の3つをご紹介していきます。
[toc]
Clean Architecture for UI
今回はまず2021年12月13日に開催された社内勉強会、濱口からのプレゼン内容をまとめております。
なじみがないマイクロサービスのチケットが取れない理由は何か?
濱口:
生産管理プロダクトチームでは、複数のマイクロサービスで構成されたプロダクトを開発しています。
開発優先順位が流動的に変化していく中で、自分のなじみがないとか、得意でない分野(フロント / バック、言語、フレームワークなど)のマイクロサービスのチケットをすぐとりたいと思うものの、なかなか手が出せない状況がありました。
実際に前期の Klein の開発では、フロントエンドが得意なエンジニアが少なかったため、UI のチケットがしばしば滞留してしまう状態がありました。
上記のボトルネックが発生した理由のひとつに、ひとつのマイクロサービスの中でどこに何が書いてあるのかが分かりづらいかった、という点が挙げられるかと思います。
コードの中で迷子になってしまう状態ですね。
よって、言語やフレームワークが違っていてもどこに何が書いてあるのかがわかるようにするためには、どうしたら良いかと考えました。
その答えのひとつとしては、レイヤー分けの仕方を統一すればいい、というのがあるのではないかと考えています。
UIもBEもClean Architectureで作ればいいのではという仮説
濱口:
私が実装してきた、レイヤー分け( Clean Arthitecture )は以下のようなイメージです。
Clean Architecture考えにのっとりレイヤー分けを行うと、抽象と詳細を分離でき、変化に強くなります。
ここで言う抽象とは純粋なビジネスロジックを指し、変わりにくいものを示しています。
ここを守るために usecase の外側を分離します。
具体的には REST インタフェースなど外から入ってきたリクエストを controller が受け付け、usecase が起動されます。 usecase では domain が駆使され、ビジネスロジックが完遂されます。
さらに永続化するとなると domain が gateway を介して、reposigory 層で永続化を実行することになるのですが、これを上記手続き通りに実装すると usecase がgateway に依存してしまいます。
そこは依存性の逆転を使って、インタフェースに依存させることで外部の詳細がビジネスロジックの世界に漏れ出すのを防いでいます。
上記のようにレイヤーで責務を明確に分けることにより何がどこに書いてあるかがあたりがつくようになります。
Clean Architectureで作ってみた
濱口:
上記の例はじめ自分の経験では主にバックエンド API で Clean Architecture を実装してきたきたのですが、これを UI に当てはめたとき、UI にとって domain や usecase はどんな概念になるかと考えてみると、例えば通貨と値の組み合わせを持つ金額というドメインがあるとして、金額をフォーマットにして通過単位やカンマをつけることがドメインの責務になると考えました。
この仮説をもって、実際に React で TODO アプリを作り試してみました。
https://github.com/yujihamaguchi/todo-app
まず Done / Undone の状態によってTODO文言の表示を変える、というような責務を持つ Item という domain が考えられます。
usecase はどこに相当するかというと、ドメインのロジックを使うところ、と考えると、コンポーネントととらえました。
port は、コンポーネントのルートがインターフェースをさらしていて、ここに相当すると思っています。
gateway は、実際にさらしたインターフェースに対して実装をうっていく hooks 以下の実装に相当します。
ファイルにアクセスして TODO を保存したり消したりするところですが、driver を集約してインターフェースを実装するという意味では、gateway といえるのではないでしょうか。
このように UI においても Clean Architecture の考え方を当てはめてディレクトリ構成やファイル名を寄せていくなどすると、どこに何が実装してあるかがすぐわかるように構成することも可能かなと考えています。
ロボット掃除機から学ぶ自律移動ロボットを支える技術
続いて2022年1月4日に開催された社内勉強会、上野からのプレゼン内容をまとめております。
上野:
今回はロボット掃除機を題材として、自律移動ロボットを構成する要素技術についてお話したいと思います。
ロボット掃除機の主な機能は、部屋を掃除しながら、障害物があればそれらを回避しつつ、掃除が終わったら充電ドックに戻ることです。
これらを達成するための、ロボットが必要とする要素技術としては主に以下の5つがあります。
【1】経路生成 【2】自己位置推定 【3】動作計画 【4】制御 【5】地図の更新
今回は、これらを1つずつ説明していきます。
【1】経路生成
上野:
まずは、部屋全体を掃除するために、ロボットが経由すべき点をいくつか作り、そこを経由しながら掃除をしていきます。
このように、指定されたエリアを網羅するような経路を生成する技術はCoverage Path Planningと呼ばれる分野です。
部屋の掃除ロボットだけではなく、芝刈りロボットや、巨大な航空写真を作る(飛行機から写真を撮って画像をつなぎ合わせる)時にも使われます。
ここで生成された経路に従って移動していくのですが、そのためにまず必要となるのが、ロボット自身が今どこにいるのか?という自己位置の推定となります。
【2】自己位置推定
上野:
これは、ロボット自身が部屋(環境)のどこにいるか?をセンサの情報から推定するものです。
例えばGPSであれば、その信号を受信していくものになりますし、車輪の回転数センサや車体の大きさから、どのくらい移動しているかを計算するホイールオドメトリと呼ばれるものもあります。
ただし、タイヤが回ってはいるもののスリップして実際には進んでいないケースもあったりするので、IMUなどカメラなどを併用するケースもあります。
他にも自己位置推定の手法には、LiDARというセンサによって得られた点群のスキャンマッチングなどがあります。
これは自動運転車などで用いられているものですが、レーザーによって計測した3次元の点群同士のスキャンマッチングを行い、ロボットがどう移動したかを計算するものです。
これらを用いて、自己位置の推定ができたら、次に必要なのは移動に必要となる速度などの目標値の計算になります。
【3】動作計画
上野:
具体的には動作計画と呼ばれるもので、ロボットが経路間を移動する時の、制御目標値を計算します。
上述した経路計画(ロボットの移動経路を計算するもの)とは異なります。
というのも、ロボットには物理的な制約があるため、経路計画通りの経路をそのまま移動できないことがあります。
例えば車の場合は、スライドp10にあるようなStartとGoalを一直線なPathで移動することができません。
実際にはTrajectoryを移動することになるため、そのためにタイヤをどう動かすか?などを計算するものが動作計画とよばれるもの。
ルンバはその場で旋回して真っ直ぐ進むことができるので、車よりはシンプルに考えることができます。
【4】制御
上野:
その上で、与えられた目標値を実際に実現させるために、制御情報の入力が必要となります。
制御情報とは、例えばモータであれば電圧や電流を変化させることで回転速度を制御できるので、右の車輪を1秒間あたり60回転させたいのであれば、こうしようという数値を決めることができます。
上の図にある式をご覧ください。
第2項は例えば進行方向から迎い風がふくことで生じるような定常的な誤差を打ち消す働きをします。
第3項は、急に追い風がふいてくるような、急激な外乱を打ち消す働きをします。
【5】地図の更新
最後は、環境に変化があった場合のお地図の更新についてお話します。
ここでは、カメラや超音波センサーやLiDARなどの観測データをもとに、障害物があった理、部屋のレイアウトに変更があったりした場合に地図をリアルタイムで更新をしていきます。
具体的には、ロボットが認識できるような地図をセルやグリッドを使って表現し、新しい地図を生成することになります。
このことと、【2】の自己位置推定を同時に行うことをSLAM(Simultaneous Localization ans Mapping)というのですが、わりと挫折する人が多かったりもします。
地図が更新された場合には、新しい情報を用いて再度経路生成を行うことで障害物を回避する経路を生成できます。
こうした経路計画の手法は、グラフ探索アルゴリズムを用いるものや、ランダムサンプリングを利用した方法、仮想的なポテンシャル場を想定し、そこに障害物の影響を考慮することで経路を計算するポテンシャル法など、多岐にわたります。
実際にサービスロボットを作る場合には、孔子た自律移動の技術に加えて、音声認識やタスク計画、ロボットアームの動作計画など、幅広い分野の知識が必要になります。
3D CADをライブストリーミングしてみた
最後になりますが、2022年1月11日にCTO小橋より、フュージョン360というオートデスク社が作っているもので、3D CADとはどんな感じなのか?を体験すべく、ライブストリーミングを行いましたので、概要をまとめております。
どのように3次元の図面が出来上がっていくのか?
小橋:
例えば立方体を作るとした時に、まずは2次限で絵を書いていくことになります。
XYZ軸のうち、どの平面に長方形を作るかということですね。
X-Yを選びましたが、ここで描くことができた平面をどちらの方向に伸ばすか指定をすると立方体を作ることができます。
さらに、穴を開けたい場合は、あけたい面を選択して穴をスケッチします。
ただし、穴の場所が固定されていないので、解が複数(無数)にありますよという状態になっています。
そこで、端から50mmの位置などと固定することで、はじめて解が1つ定まったと表現されていきます。
位置が定まった穴に対しても、深さをどのくらいにするかを設定することで図面に表現されるようになります。
それから立方体の端の面取り、ここを丸くしていく加工をフィレットというのですが、例えば1mmのフィレットをかけたいとしたとき、どの辺にかけたいかを選択すると、かけることができます。
コンポーネント設計はCADの世界だとどうなるのか?
小橋:
続いてコンポーネント設計についてですが、ソフトウェアの世界ではこうすべきだ、などという流派がいくつかあったりもしますよね。
これが、CADの世界だとどうなるかというと、例えば似たような形状をパラメーターを使ってたくさん作りたいニーズがあったとします。
下記の図にあるような形状の、アルミフレームを設計するとして、これは長さのパラメーターだけを変化させられるようにしています。
例えば1250mmにすると一気に長くなるわけですが、ディスタンスの所にパラメーターを入れているわけですね。
こうすることで同じ断面のアルミフレームをたくさん作りたい時に使えたりするのですが、残念ながら外から関数を入れてやってもらう、というのはできません。
それから、複数の物体を合体させる場合、ジョイントという機能があります。
2つの物体の端と端どうしを、座標空間の中で合わせにいくような感じでやると、接続できるのです。
どことどこをアンカリングしてきたのかを注意しておかないど、設計変更がおきた時に大変になってきます。
ヒストリーベースで、どんな操作をやってきたのか?など時間軸でスクロールできるのはフュージョンの特徴の1つですね。
CAM(コンピューター支援製造)ソフトでのシミュレーション
小橋:
設計者はモデリングをどうするかを考えるのですが、実際にどう製造できるよう作るかを考えるのは別の思考回路になります。
そのため、例えば立方体に溝を作るときに、エンドミルで削るのですが、どういう工具で加工するかというシミュレーションが難しい。
このとき、CAMを使うことになるのですが、ジグで固定し、どのように削っていくのかをよしなに考えてくれるアダプティブクリアリングというツールパスがあります。
実際に加工する時に選ぶ工具を選択し、上記の図にもあるように、渦をまくような感じで工具が動き、加工していく様子をシミュレートできるものです。
どのくらいの速度で削ることができるのか?加工する時に熱が発生するので、どのように調整していくのか?
加工する材質や、工具の材質に応じて、モノの動きなどを設定しながら動かさないといけないのですが、これをCAMがプログラミングで判断してくれるのです。
一定のインプットをしてあげることで、こうした加工パスを作ってくれるので便利ですよね。
ということで以上、2次元の平面図形から形状をおこし、最後はCAMソフトでシミュレーションしていくデモンストレーションを今回は行ってみました。
おわりに
今回は、3回分の社内勉強会の内容をまとめてみたのですが、いかがでしたでしょうか。
記事内容をご覧いただいて、興味持った方はこちらにて、お話する機会をご用意しておりますので、ぜひご活用ください。
また社外向けに一般公開するイベントに関する情報は、キャディのCONNPASSをご用意しておりますので、こちらもご登録いただけますと幸いです。
最後までお読みいただきまして、ありがとうございます。