アプトポッドのブログ - TECH PLAY

TECH PLAY

アプトポッド

アプトポッド の技術ブログ

全256件

intdashを介してRMF WebとGazeboシミュレーションを実行している様子(詳細な動画は最後の方にあります) 本記事の内容 こんにちは、Aptpodのエンジニアの影山と申します。普段は intdash CONTROL CENTER 関係の開発を担当しています。 昨年のROSCon JPでも基調講演がありましたが、フリートの群制御のためのプラットフォームとして、オープンソースで開発が進められている Open-RMF の名前を聞くことが近頃増えている気がします。 本記事では、話題のOpen-RMFと弊社製品のintdashを使って、クラウドを介してフリートを管理することを目的として、AWS上にOpen-RMF検証のためのシミュレーション環境を構築する手順を紹介したいと思います。 intdashを用いた事例の紹介とはなっていますが、内容はOpen-RMFを試してみたいという方へ向けて、Open-RMFにフォーカスして説明していますので、Open-RMFの使い方の一例として、参考にして頂ければ幸いです。 注:現在も開発が進行中なので、本記事の説明が最新のリポジトリの内容と合っていない場合があります。その点はご了承ください。 本記事の内容 背景 Open-RMFとは クラウド上での環境構築の目的 RMF Webの利用 環境構築 前提条件 システム構成図 AWS EC2インスタンスの準備 Open-RMFサーバの準備 ロボットのシミュレーション環境の準備 シミュレーション環境とOpen-RMFサーバの接続 マップの準備 マップ画像の準備 縮尺の定義 Waypoint、レーン、床、壁の定義 Building MapからGazeboで使用するワールドの生成 シミュレーションを利用したOpen-RMF環境の起動 実際の操作の様子 最後に 弊社ソリューションのご案内 背景 これまで弊社ではROSとintdashを組み合わせて、ROSメッセージの可視化や、インターネットを跨いだリアルタイム遠隔操作を実現してきました。 『intdash x ROS』で実現するROSメッセージの遠隔リアルタイムデータ伝送 - aptpod Tech Blog intdashを使ってROSを遠隔制御できるようにするまでのステップ - aptpod Tech Blog 産業用データ伝送プラットフォームでROSの画像とってみた - aptpod Tech Blog 現在、 intdash CONTROL CENTER の一環として、フリート群管理システムについても研究開発を進めており、その過程でOpen-RMFの利用を検討してきました。 本記事では、検討の過程で得た知見をみなさまと共有できればと思っています。 Open-RMFと連携したintdash CONTROL CENTERの構成 Open-RMFとは Open-RMF とは、異なるベンダーのフリートであっても、統一されたインタフェースで管理できることを目標として、 Open Source Robotics Foundationが開発を進めているプロジェクトです。 " より引用 基本的なことは 公式のドキュメント によくまとまっていますが、 現在も活発に開発が進んでいることもあり、公式のドキュメント以外には、導入に関する情報もまだ多くありません。 まずは公式のドキュメントやrmf-demoのREADME.mdを参考に、デモを試してみるのがよいかと思います。 フリートに対して、タスクを割り当てて、その内容に従ってロボットが動作する様子が確認できるかと思います。 クラウド上での環境構築の目的 しかしデモを試しただけでは、実際どのようにノード群が動作しているのかを理解するのはなかなか大変です。 実環境を想定して、理解を深めるには、独自の評価環境を作って試行錯誤を繰り返すのが近道だと思います。 弊社のintdashサーバと連携させることで、クラウド側からのフリート管理を実現させたい、という目標がありますので、そのためのお試し環境をクラウド上に構築してみました。 RMF Webの利用 Open-RMFの操作方法として、デモではシンプルなWebアプリが容易されています。そのほかにも RMF Web というリポジトリ上では、より充実したUIを持つアプリも開発されています。 RMF WebのフロントエンドはReactで実装されており、APIサーバと連動して、ロボットのモニタリングや、タスクのアサイン、ユーザ管理などの機能を備えています。 APIサーバの機能も充実しており、APIサーバを利用することで、独自のフロントエンドを持つWebアプリも実装可能かと思います。 APIサーバはFastAPIを利用して実装されており、起動した状態で http://127.0.0.1:8000/openapi.json にアクセスすると、OpenAPIのJSONスキーマが取得できます。これを眺めるとAPIを利用してどんなことができるかなんとなく理解できるかと思います。 OpenAPIのスキーマをredocで見やすくしたもの 環境構築 前提条件 利用するクラウド環境: AWS EC2 G4dn OS: Ubuntu22.04 ROSのディストリビューション:ROS2 Humble システム構成図 シミュレーション環境全体の構成図 Open-RMFのROS2ノード群とGazeboのシミュレーション環境は、別々のROSドメインで分かれており、そのドメイン間をintdashで繋いでいます。 シミュレーション環境をDomain A、Open-RMFサーバ環境をDomain Bとしています。 ここでintdashはROSのトピックを双方向で中継する役割を担っています。 今回は手軽に開発環境を準備することが目的なので、シミュレーション環境がOpen-RMFと同じインスタンス上に置いていますが、実際は同じインスタンスに存在している必要はなく、NAT越えについてはintdashがカバーしてくれるのでシミュレーション側は、ローカルのPCで動かすことも可能です。 Open-RMFに含まれる、RMF Webを利用して、ロボットの稼働状態をブラウザ上で確認できます。 また、シミュレーションの状態もVNCサーバを利用することで、Gazeboの画面を確認できます。 intdashが提供する Data Visualizer でintdashを通過するトピックの内容を確認することもできます。 Data Visualizerで/clockと/fleet_statesのトピックをリアルタイムで可視化した例 AWS EC2インスタンスの準備 GPUが搭載されたPCを都度準備するのは大変なため、AWSのEC2を利用しています。 GUIが不要であれば、デスクトップ環境は必須ではありませんが、今回はGazebo clientを利用したいので、GPUが使えるインスタンス上で、Ubuntuデスクトップをインストールします。今回は g4dn.2xlarge を利用しています。ストレージは50GB以上あった方がよいと思います。IPアドレスを固定したい場合は、加えてElastic IPを設定してください。 インターネットを上にも情報が色々あるので詳細は割愛しますが、NVIDIAのドライバとVNCサーバをインストールして、適切に設定をすることで、VNCを使ってデスクトップ環境にアクセスできるようになります。 海外リージョンだとGUI操作のレスポンスが悪いので、インスタンスは日本のリージョンで作成するのがよいです。 VNCのポートを公開するのは危険なので、開発時はSSHでポートフォワードしています。以下にVNC接続向けの .ssh/config のポートフォワード設定例を載せておきます。 こうしておけば、 ssh aws-rmf-simulation で接続したあとに、VNC Viewerのようなツールで、 localhost:5900 にアクセスすればデスクトップ環境に接続できます。 Host aws-rmf-simulation Hostname xxx.amazonaws.com User ubuntu LocalForward 5900 xxx.amazonaws.com:5900 IdentityFile ~/.ssh/aws_rsa_key Open-RMFサーバの準備 Open-RMFの実行に必要なコンテナの作り方は、 rmf_deployment_templateリポジトリ の内容が参考になります。 こちらをベースとして、必要な部分を改造していくことで準備できるかと思います。 ビルド時に必要な変数などは、 CIの設定 を読むことで確認できます。 テンプレートではデモを実行するので、rmf-demosやrmf_simulationを取り込んだrmf-simulationというDockerイメージを作成して利用していますが( 参考 )、rmf-simulationを使わずに、オリジナルのDockerイメージを作成することで、独自の環境で動かすことができます。 テンプレートのREADME.mdにもある通り、rmf-simulationはOpen-RMFの基本的なパッケージを取り込んだrmfというDockerイメージをベースに作られています。オリジナルの環境もrmfをベースにして、自作のパッケージを /opt/rmf/src に追加していく形になります。 どんなノードを起動する必要があるかについては、 rmd-demosのlaunch ファイルが参考になります。 以下にrmf_demoのlaunchをベースとして、オリジナルの環境を作る際の注意点を挙げます。 GazeboやRvizはOpen-RMFサーバ側では不要です dashboardはRMF Webを実行するので不要です デモ用のFleet Adapterの代わりに、Full Control Fleet Adapterを起動します Fleet Adapterの詳細については、 こちら の説明を参照ください 起動の方法については、 こちら のlaunch設定を参照ください 現場環境側とサーバ側でROS Domainを別々にします サーバ側のROSと現場環境側が直接通信せずに、常にintdashを介して通信するようにすることで、遠隔地との接続を模擬します 参考に、主要なノードへの起動時に設定必要なパラメータの情報をまとめた図を載せておきます。以下で説明するBuilding Mapと、をそれから生成するnav graphが環境を定義する重要な情報となっていることが分かるかと思います。 Open-RMFノードへのパラメータ ロボットのシミュレーション環境の準備 ロボットをシミュレーションするために、rmf-demosを参考にGazeboを用います。 Full Control Fleet Adapterと組み合わせて簡単にAGVを試せるように、SlotcarというGazeboプラグインが容易されているので、そちらを利用します。 こちらとロボットのモデルを組み合わせることで、デモのようにロボットを操作することができます。 自己位置推定や自律走行をするわけではないので、その点は留意ください。 Slotcarプラグインは rmf_simulation リポジトリに含まれています。 プラグインをビルドするために次のようなリポジトリをcloneして、colcon buildする必要あります。 https://github.com/open-rmf/rmf_simulation.git https://github.com/open-rmf/rmf_internal_msgs.git https://github.com/open-rmf/rmf_building_map_msgs.git https://github.com/open-rmf/rmf_traffic_editor.git https://github.com/open-rmf/rmf_utils.git ロボットのモデルには、rmf_demoで使われている TinyRobot を利用します。 ロボットの初期位置は、ワールドを生成するときに同時に定義されるので、特にこの時点では気にする必要はありません。 TinyRobot シミュレーション環境とOpen-RMFサーバの接続 シミュレーション環境とOpen-RMFサーバとの接続には、 intdash Edge Agent2 と intdash ROS2Bridge を用いています。 詳細な設定の方法はリンク先のマニュアルの通りですが、ポイントとして以下のトピックをブリッジする必要があります。 シミュレーション環境→Open-RMFサーバ /clock /fleet_states Open-RMFサーバ→シミュレーション環境 /robot_path_requests /robot_mode_requests /robot_destination_requests /map (slotcarを用いたシミュレーションの時のみ必要) /fleet_statesトピックはslotcarプラグインが生成してくれないので、slotcarプラグインから配信される、/robot_stateトピックを配列にまとめて/fleet_statesトピックとして配信するノードが必要になります。 マップの準備 実際に試してみたいマップを作成します。Open-RMFで利用するマップはYAML形式のBuilding Mapファイルで定義されています。Open-RMFでは、Building Mapを編集しやすくするために、Traffic EditorというGUIツールが提供されています。 Open-RMFではロボットが走行する経路をBuilding Mapから変換して作成するYAML形式のnav graphで定義しています。 以下のコマンドで作成できます。 ros2 run rmf_building_map_tools building_map_generator nav <building mapのパス> <出力先ディレクトリ> Traffic Editorでは壁やオブジェクトの位置なども定義できますが、建物の形状に関する情報は主にGazebo用のワールドを生成する際に用いられます。 マップ画像の準備 壁や障害物などが分かる図面の画像を用意します。この画像の上をTraffic Editorでなぞって、レーンなどを定義します。こちらの図は弊社の会議室の形に合わせた画像です。 マップ画像 縮尺の定義 Measurementツールで、地図上で線分が何メートルであるかを定義します。定義した内容に応じて画像ファイルの1ピクセルが何メートルであるかが計算されます。 measurementで引いた線分に実際の長さを設定する 一度保存して、Traffic Editorを再起動する必要あります。 ※Traffic Editorはある程度大きなロボットを想定しているため、小さなロボットの経路を編集するには、画面上のレーンの太さなどがマッチしていません。UI上のレーンの太さなどは設定で変えることができないので、どうしても変えたい場合はソースコードの修正が必要です。 Waypoint、レーン、床、壁の定義 Waypoint ロボットの走行する経路の頂点にあたる点です。名前を付けることで、タスクを作成するときにその名前で参照できます。 レーン WaypointとWaypointを直線で結ぶロボットの走行経路です。 床、壁 Gazebo用のワールド生成時に使用される情報です。設定しないと床が抜けたりしてシミュレーションに支障があります。 Waypoint属性の設定 spawn_robot_typeとspawn_robot_nameでシミュレーション上でのロボットのスポーン位置を指定することができます。 ※注: レーンで接続されたWaypointのうち、一つは is_charger=true である必要があります。 レーンを設定している様子 Building MapからGazeboで使用するワールドの生成 Building Mapの準備ができたら、以下のコマンドを実行することで、Gazeboで利用できるワールド情報を自動生成できます。この際に、Traffic Editor上でWaypointの属性情報で設定した情報を利用して、ロボットの初期スポーン位置がワールドデータに反映されます。初期位置を随時変えたい場合は、毎回Traffic Editorで編集するのが手間なので、building.yamlの内容を直接編集するスクリプト等を用意しておくと作業がはかどります。 ros2 run rmf_building_map_tools building_map_generator gazebo <building.yamlのパス> <ワールドデータの出力先> <モデルデータの出力先> 壁の高さや厚さなどが固定値のため、もし修正したい場合はソースコードの修正が必要です。以下に例を示します。 sed -i 's/self.wall_height = 2.5/self.wall_height = 0.5/g' src/rmf_traffic_editor/rmf_building_map_tools/building_map/wall.py sed -i 's/self.wall_thickness = 0.1/self.wall_thickness = 0.05/g' src/rmf_traffic_editor/rmf_building_map_tools/building_map/wall.py シミュレーションを利用したOpen-RMF環境の起動 準備お疲れさまでした! シミュレーションを利用して、indashと組み合わせたOpen-RMF環境を起動して、Open-RMFから制御できることを確認します。 まずGazeboを起動します。 まず次のように環境変数でモデルやプラグインのパスを設定します。 current_path=`pwd` export GAZEBO_MODEL_PATH=<ロボットのSDFが保存されているディレクトリへのパス>:<生成したワールドのモデルへのパス>:/usr/share/gazebo-11/models:$GAZEBO_MODEL_PATH export GAZEBO_RESOURCE_PATH=/usr/share/gazebo-11:$GAZEBO_RESOURCE_PATH export GAZEBO_PLUGIN_PATH=${current_path}/install/rmf_robot_sim_gz_classic_plugins/lib/rmf_robot_sim_gz_classic_plugins:${current_path}/install/rmf_building_sim_common/lib:/usr/share/gazebo-11:$GAZEBO_PLUGIN_PATH そして、ワールドへのパスを引数に与えてGazeboを起動します。 次に、Open-RMF環境のコンテナを起動します。 こちらは準備したコンテナをそれぞれ起動すれば良いですが、複数のコンテナを扱うことになるので、docker compose用のYAMLファイルにまとめておくと便利です。 実際の操作の様子 操作の様子は動画を参照ください。RMF Webのブラウザのウィンドウと、VNC Viewerで表示しているGazeboのシミュレーションの様子を重ねて撮影しています。 www.youtube.com 動画では、2台のロボットが縦方向に往復しているところに、横方向の往復をするタスクを割り当てています。RMF Webのコンソールからタスクを設定して、それがロボットにアサインされる様子が確認できると思います。 (シミュレーションでは時刻がUNIX時間になってしまうので、1970年1月1日を基準とした時刻で画面上表示されています。) 動画ではRMF Webからタスクをアサインする様子を紹介しています。APIサーバにRESTでコマンドを送ることで、ブラウザや、ROSを利用することなく、外部から操作することも可能です。 停止する際は、docker compose downでコンテナを停止して、Gazeboを起動しているターミナルで、ctrl-cでシミュレーションを停止します。 最後に いかがでしたでしょうか? 自作のマップをベースに環境を構築できれば、色々なパターンの検証などがはかどるかと思います。これをご覧になったみなさまのOpen-RMF導入の参考になれば幸いです。 今回はTinyRobotを利用して環境を構築していますが、リアルな自律走行ロボットを、 Free Fleet とNav2を合わせて利用して制御する方式も今回の内容を拡張することで実現可能です。弊社でもTurtlebot3 Burgerの実機を用いて検証していますので、別の機会に紹介できればと思います。 弊社会議室でTurtlebot3 Burgerを使った検証を行っている様子 最後に、宣伝になってしまいますが、 ROSConJP 2023 で、「Open-RMFを応用したクラウドフリート管理システムの構築」というタイトルで登壇予定です。 弊社アプトポッドもROSConJPスポンサーになり、ブースを出す予定です。 そちらでは、検討の過程で学んだOpen-RMFのより深い部分についても紹介できればと思いますので、ぜひ発表を聞いたりブースに訪れて頂ければ幸いです。 弊社ソリューションのご案内 弊社ではモビリティやロボットのリアルタイムでインタラクティブな管制制御システムの迅速な構築を可能にするintdash CONTROL CENTERを推進しております。 www.aptpod.co.jp スマートシティにおける自動運転車、工場や物流倉庫における搬送ロボット、建設現場における建設機械など、モビリティ群の統合遠隔監視・管理、遠隔制御システムなどでお困りのことがあれば、ぜひお声掛けください。 弊社お問合せフォームはこちらです。 www.aptpod.co.jp
当社製品の EDGEPLANT T1 を開発に活用してくださっているお客様の事例を、インタビュー形式でご紹介します。最新のビジネスの現場で当社製品がどのように活用されているかや、当社製品を実際に使ってみての評価等について、お客様の生の声でお伝えいたします。 今回インタビューをさせていただいたのは、「ハンドルの無い完全自動運転車」の実現を目指して自動運転AIシステムの開発を行う Turing株式会社 様(以下、チューリング社)です。同社は、世界で初めて名人を倒した将棋AI「Ponanza」の開発者である⼭本⼀成氏と、カーネギーメロン⼤学で自動運転を研究しPh.D.を取得した⻘⽊俊介氏によって2021年に共同創業されたスタートアップで、カメラ映像のみを用いたAIによる自動運転技術に強みを持っています。 今回は、チューリング社の車両開発部にてチーフエンジニアをつとめていらっしゃる徳弘賢人氏に、事業の内容から開発の裏側まで、様々なお話を伺いました。 本記事は、インタビューアーをつとめましたアプトポッドVPoPの岩田がお送りいたします。 Turing株式会社 車両開発部 チーフエンジニア 徳弘賢人氏 Turing株式会社について 最初のプロダクトTHE FIRST TURING CARについて EDGEPLANT T1採用のきっかけと選定理由 EDGEPLANT T1を実際に使用した感想 今後の弊社ハードウェアに対する期待 Turing株式会社の今後の展望 インタビューを終えて: EDGEPLANT T1のご紹介 Turing株式会社について アプトポッド岩田(以下、岩田): 本日はよろしくお願い致します。まずは、御社の事業内容について教えていただけますか。 チューリング徳弘様(以下、徳弘): はい、我々チューリングは、「完全自動運転の実現」と「ハンドルのない車の販売」を事業目標としている会社です。完全自動運転システムの開発はもちろんですが、最終的には、量産車メーカーと呼ばれる量産ラインを持っている自動車メーカーになることを目標に事業を進めています。 この目標を実現するためには、大きな2つの超えなければならない課題があります。1つめは「完全自動運転を実現する知能の開発」、2つめは「自動車の車体の開発」です。知能と車両の双方を自社で開発することで、目標としている「ハンドルのない完全自動運転車両」の実現を目指しています。 岩田: 知能だけでなく車体そのものまで自社開発しようとしているのが、御社の特徴ということでしょうか。 徳弘: はい、その通りです。完全自動運転向けの知能の開発だけでもそもそも難しいチャレンジではありますが、そこに加えて我々は車体自体も自社開発しようとしています。この双方をターゲットにしているスタートアップはなかなかありません。 また、我々の目標である「ハンドルのない車の販売」は、既存の完成車メーカーとも異なるポイントです。そういったコンセプトを打ち出しているメーカーもあるにはありますが、既存事業との兼ね合いを考えると、それをメインの事業として推進するのはなかなか難しいだろうと考えています。我々は自動運転AIに強みをもつ会社ですが、ただ待っているだけではそういったコンセプトの車は現れてこないだろうということで、自分たちで車体から開発することにしました。  ちなみに、車体開発のようなハードウェアとAI開発のようなソフトウェアでは、ものづくりに対する考え方やアプローチが全く異なります。弊社代表がチューリングを設立した当時の思いとして「AI開発の経験で培ったソフトウェア開発の考え方を主軸に、ハードウェア開発の考え方の良いところを取り入れてもっと良い車づくりを実現したい」というものがあり、我々社員もそういった考えを魅力的に感じ、実現に向けて現在活動しています。 www.youtube.com 現在、AIを活用したコンセプトカーデザインなどにも取り組まれています 最初のプロダクトTHE FIRST TURING CARについて 岩田: 先日ニュースリリースで、御社最初のプロダクト「THE FIRST TURING CAR」の販売と成約について拝見しました。まずはご成約おめでとうございます。 徳弘: ありがとうございます。 岩田: このTHE FIRST TURING CARの開発において、弊社のEDGEPLANT T1をご活用いただいたと聞いています。まずは、プロジェクトの概要について教えていただけますか。 徳弘: 今回販売したTHE FIRST TURING CARというプロダクトは、自動運転のレベル2に相当するシステムを搭載した車両で、市販車両を改造して我々の自動運転AIを搭載したものになります。レベル2相当のシステムなのでドライバーの監視が必要にはなりますが、高速道路での前方追従、前方車がいない状態での速度や車線の維持、車線変更などのドライバー支援機能を提供しています。特徴的なところとしては、搭載している自動運転AIは我々が得意としているカメラ映像ベースのものであるという点と、その自動運転AIの作動状況をユーザーに提示するユーザーインターフェイスを提供している点です。 市販車をベースとして製作された THE FIRST TURING CAR 岩田: ニュースリリースによると、今回のシステムは完全自動運転ではなくあくまでドライバー支援とのことですが、機能的にはどのような違いがあるのでしょうか。 徳弘: 違いは大きく分けて2つあります。 1つめは自動運転AIへの入力として利用する情報の違いです。今回のシステムで利用している情報は前方カメラの映像のみですが、完全自動で運転するには周囲360度全方位の映像を利用する必要があります。今回のシステムでは、完全自動運転に必要な全情報をAIに入力できているわけではありませんし、仮に必要なすべての情報を取得したとしても、それをさばききれるシステムにはなっていません。 2つめは車体ハードウェアの違いです。今回は市販車を改造して製作していますので、全ての挙動を自由自在に制御するところまでは実現できていません。ハンドルのない完全自動運転の車を実現するには、たとえば車両が自ら自動で起動/停止したり、勝手に目的地まで移動したりといった、人間が操縦する既存の車の延長ではない仕組みが必要になってきます。今回は、市販車をベースにしたことで外部からアクセスできる範囲での制御にとどまっており、我々が目指す完全自動運転車両の実現のためにはやはり自分たちで車両から開発するしかないということを改めて感じました。 岩田: なるほど。市販車に後付けする形での開発としたことで、制約の範囲内での機能実現にとどまっているということですね。ちなみに、今回のこちらのプロジェクトにおいて、弊社のEDGEPLANT T1はどのようにご活用いただいたのでしょうか。 徳弘: 御社のEDGEPLANT T1は、まず開発の工程で数台利用させていただきました。また、最終的にTHE FIRST TURING CARそのものにも1台搭載しています。 岩田: 販売されたあのTHE FIRST TURING CARの中でも、我々のEDGEPLANT T1が稼働しているということですね!なんだか嬉しく思います。 開発中の実験車に EDGEPLANT T1 が搭載されている様子 EDGEPLANT T1採用のきっかけと選定理由 岩田: 弊社のEDGEPLANT T1は、どのように見つけてくださったのでしょうか。 徳弘: 一番最初のきっかけは、AWSのソリューションアーキテクトの方から御社のデバイスをご紹介頂いて、検討用にとりあえず1台購入してみたというところからでした。当時社内では、普通のラップトップPCでソフトウェア開発を行って、それをそのまま車両につなげて検証するという方法で開発を進めていました。なので当初は、購入したものの実はそれほど使用していませんでした。 岩田: そうなんですね。その後どういったきっかけで採用に至ったのでしょうか。 徳弘: その後開発が進み、そろそろ車体へのAIの組込みを検討し始めなければというタイミングで、すでに手元にあった御社のEDGEPLANT T1を含めいくつかのデバイスを比較検討して採用デバイスを絞り込んでいきました。半導体不足による調達難の影響もあり納期の長いデバイスもいくつかありましたが、期間的にもあまり余裕がなかったためそのようなデバイスは候補から外していきました。 一方御社のEDGEPLANT T1は、我々がデバイスに求める最低限のスペックはクリアしていましたし、なにより Amazon.co.jp から簡単に購入できたことで、開発のためにある程度のボリュームで早急に入手したかった我々としては非常に助かる選択肢でした。 岩田: 最低限のスペックはクリアしていたということですが、具体的にはどのような要件が必要だったのでしょうか。 徳弘: 基本的に車両に搭載するデバイスになるので、EMC試験や耐振動試験にパスしている必要があります。一方で、今回のシステムはドライバーの監視のもとで作動するものなので、たとえばAEC規格などの量産車両の部品に求められる厳しい基準までは満たしている必要はありませんでした。EDGEPLANT T1は汎用コンピュータということで、そういった厳しい基準までは満たしていませんでしたが、Eマークを取得していたり電磁特性/環境耐性が備わっていることがスペックから分かったため、問題ないと判断しました。不足する部分については、たとえば車両との間にセーフティーマイコンを挟んだり、他のコントローラと相互監視させるなどの工夫によってカバーしています。 また、他のデバイスとの比較検討の過程で、EDGEPLANT T1が使用しているNVIDIA Jetson TX2よりも新しい世代のSoCを搭載したデバイスなども検討しましたが、あまり性能が高すぎても消費電力が問題となることもあり、むしろ最低限の性能を有しているEDGEPLANT T1に合わせて、AIシステム側をスリム化する方向に向かいました。 全体として御社のEDGEPALNT T1は、電磁特性や環境耐性、消費電力といった観点で難しいことを考えないでパッと自動車に積めるスペックに仕上がっていて、非常に完成度の高いデバイスだなと感じています。 Deep Learningにせよ画面描画や画像変換にせよ、とにかくハードウェアアクセラレータ使うのが大事ということで最近社内ではNPP(Nvidia Performance Primitives)を頑張って使うのが流行っている。 pic.twitter.com/ah0wRkGmy4 — 山本一成🌤️TuringのCEO (@issei_y) 2022年10月24日 山本一成氏のSNSに登場した3台のEDGEPLANT T1 EDGEPLANT T1を実際に使用した感想 岩田: 実際にEDGEPLANT T1を使用していただいての感想はいかがでしたか。 徳弘: 一言で申し上げますと、非常に使いやすいな、というのが率直な感想です。すこし乱暴な言い方になりますが、適当に電源を挿しても動きますし、電源制御の機構が内蔵されていて車のイグニッションに連動してくれるので、電源管理が楽にできました。 I/Oに関しても、デバッグしやすいポートがついていたり、拡張性も高かったりと、全体的に見て、我々にはちょうどよい、使いやすいシステムだったと思います。 岩田: ありがとうございます。逆に、使ってみて不足に思うことはありましたか。 徳弘: 細かい点を挙げるならば、たとえば、システム内に監視用のチップがもう一つ積まれていたほうが良い、I/Oについては汎用的なものだけでなくもっと堅牢な専用設計のものがあると良い、CANのようなI/Oについてはもっとコネクタ数が欲しい、などいろいろとあるにはあります。しかし、こういった要件が満たされているに越したことはないものの、これらはあくまで我々のシステム固有の要望であってEDGEPLANT T1のような汎用的なパッケージングとして不足があるということではないと思います。 基本的な我々の感想としては、汎用的なパッケージングとしての機能性は十分である、というもので、それ以上の細かい不足については、自分たちで実装して外側に付加していけばよいと思っています。I/Oさえ充実していれば、あとはソフトウェアでどうにでもなる話ですしね。 岩田: そうですね。やはりEDGEPLANT T1は汎用的なデバイスということで、個別の用途にしっかり最適化していこうとすると、若干物足りない部分はあるのかもしれません。 チューリング社での開発の様子 今後の弊社ハードウェアに対する期待 岩田: 今回利用していただいたEDGEPLANT T1に限らず、今後の弊社製品への期待としては、なにかご要望はございますか。 徳弘: ここは正直に申し上げるとなかなかコメントが難しいのですが、我々のような車両開発を行うメーカーにとって、システムとして信頼性が高く安全なものに仕上げていくには、今後はやはり専用設計のハードウェアを使用していかざるを得ないのかなと考えています。そういった文脈で、車両開発の領域において御社のEDGEPLANT T1のような汎用製品を使用する期間は、実はもうそれほど長くはないのかなと考えているのが正直なところです。 一方で、我々は車両開発と並行して自動運転AIモデルの開発も行っているわけですが、そのためのデータ収集のプロジェクトが現在社内で進行しています。御社のEDGEPLANT T1のような製品は、そういったデータ収集の領域では確実に需要があると思います。たとえば、データ収集の際にデバイスエッジで整合性チェックなどの前処理をさせれば、データ収集ワークフローの効率が全然変わってきます。弊社でも、今後周囲360度全方位の映像データを利用していくに当たり、16個のカメラから映像データを収集したり前処理をしたりすることが需要として出てきそうですが、その際にはよりハイエンドなデバイスが必要になってくる可能性があります。 車両開発の領域からは外れますが、自動運転AIの研究をしている研究機関や企業にとっては、そういったある程度ハイエンドで車に簡単に積み込んで使用できる汎用デバイスは、需要があるのではないかと思います。 岩田: 確かに、我々のお客様の活用事例を見ていてもやはり圧倒的に多いのはデータ収集のプロジェクトになります。今回ご活用いただいたEDGEPLANT T1についても、もともとはデータ収集デバイスとして開発された製品なので、そういった意味で御社の活用事例は弊社の中ではレアケースに該当しますね。 今回は、開発期間も短くスピード感が求められる中で、入手性や使いやすさを評価いただいて弊社製品を採用いただいたわけですが、たとえば他の研究開発機関などのプロトタイピングフェーズにおいて、同様の点が評価される可能性についてはどう思われますか。 徳弘: これについては、組織によりけりだと思います。我々のように最終的に製品をつくることを目指して開発をしているような組織では、やはり最終量産時に使用するシステムに近いものを使用して開発したいという思いは、どうしてもあると思います。一方、大手のOEMさんのような先行開発部隊を抱えている組織であれば、完全にゼロから新規設計を行う際にまず汎用品を使用するという可能性はあると思います。 Turing株式会社の今後の展望 岩田: 最後に、御社の今後の展望やマイルストーンについて教えていただけますか。 徳弘: はい、弊社チューリングは、やはり冒頭に申し上げたとおり「ハンドルのない完全自動運転車を開発してリリースする」というところを目標に活動しております。ですので、われわれの現在のあらゆる活動はすべてこの最終目標に向けたものになっています。 そこに至るまでのマイルストーンとして直近で目指しているのは、我々自身で開発したEVの自動運転車両を少量生産して2025年にリリースするというところです。これを実現するために、まずは来年2024年末までに自社開発EVのナンバーを取得する計画になっています。ナンバーを取得する車両は、自社開発EVのフレームに、EV用の各種コンポーネントや計算機を我々で組み付けて、我々の自動運転システムの搭載したものになる予定です。 岩田: なるほど。それだけのことを実現しようとすると、2025年も遠いようでそれほど時間は無いのかもしれませんね。 徳弘: そうなんです。実は意外と時間が無いな、というのが現場の感覚です。 岩田: ちなみに、御社は 「We Overtake Tesla」というビジョンを掲げていらっしゃると思いますが、2025年よりも更に先にはどういった方向を見据えていらっしゃるのでしょうか。 徳弘: 2025年よりもさらに先となると不確実性がかなり高くなってしまいますが、やはり「ハンドルのない車を量産する」という目標の達成が目指すところになります。この目標の達成は、現時点では2030年を想定しています。そうなりますと、2026年か2027年ごろにはもう量産ラインの取得に向けて具体的に話が進んでないと間に合いませんし、現在の2025年というマイルストーンもそこから逆算して設定したものになっています。 自動運転EV開発のチューリング、AIをフル活用してデザインした「完全自動運転EV」コンセプトカーを公開 https://t.co/zvzqXsHhve 画像生成AI「Stable Diffusion」をフル活用して本当にクルマを丸ごと完全にデザインしました。たぶん世界初! — 山本一成🌤️TuringのCEO (@issei_y) 2023年3月15日 山本一成氏のSNSでは、同社の幅広な事業活動を覗き見ることができる さらに「ハンドルをなくす」というところは、エンジニアリングだけの問題ではなく、法規的な問題も解決していかなければなりません。また、自動運転で使用する知能についても、まだまだもっと賢いAIを開発していかなければなりません。最近ではChatGPTがかなり賢くなってきているので、このままいけばなんとかなるのではないかという話も出てきていますが、ああいったものがリアルタイムかつ高速に、しかも常に高い精度で動作しなければならないとなってくると、AIとしてだけでなくシステムとしての完成度にもかなり高いレベルが必要になります。 車両開発については先程の通り2025年をひとつのマイルストーンとして設定していますが、他の法規的な問題、自動運転AI知能の開発という点についても、別途マイルストーンを設定して進めています。 岩田: なるほど、最近の御社のニュースリリースで、生産拠点の開設や千葉県知事との意見交換、大規模言語モデルの開発への着手など、様々な話題が上がっているのを拝見していましたが、これらはすべてひとつの目標に連動するものだということが改めてよく分かりました。 本日は、EDGEPLANT T1の採用に関わるエピソードや御社の開発プロジェクトにおける要件、実際にEDGEPLANT T1を採用してみての感想など、広い範囲で質問に回答いただき、大変参考になりました。 御社の自動運転車両が実際に発売されるのを楽しみにしています。本日はどうもありがとうございました! インタビューを終えて: EDGEPLANT T1のご紹介 いかがでしたでしょうか。いまとても勢いのあるスタートアップであるチューリング社が、我々のEDGEPLANT T1について、どのような点を評価しご採用いただいたのか、読者の皆さまにもお伝えできていれば幸いです。 最後に、インタビュー中に何度も登場していた弊社の車載向け汎用コンピュータ、 EDGEPLANT T1 について改めてご紹介させていただきます。 EDGEPLANT T1の外観 EDGEPLANT T1は、NVIDIA Jetson TX2を搭載した車載向けエッジコンピュータです。256基のNVIDIA CUDAコアを実装したGPUによって、デバイスエッジでのAI処理や映像・画像処理を実現します。また、SIMスロットやGPSモジュールを備え、モビリティーのコネクテッド化に必要な機能をオールインワンでご提供いたします。 EDGEPLANT T1の主な特徴 SIMスロット搭載、GPSモジュールを内蔵 EMC規格(Eマーク)、信頼性規格(JASO D014)に準拠 広い電源電圧レンジ(9〜36V)に対応し、大型車・建設機械に利用可能 広い動作温度範囲(-20°C〜+65°C) イグニッション連動による自動起動と自動シャットダウンが可能 Wake on CANに対応し、CAN信号に連動して自動起動が可能 電源管理とフォルト監視の独立MCUを搭載 防塵性能と冷却性能、メンテナンス性を兼ね備えた筐体外付けのファン機構 脱落防止ロック機構付きのUSB 3.0コネクターを装備 より詳細なスペックについては、 こちらのデータシート をご覧ください。 EDGEPLANT T1は、以下の販売パートナー様よりご購入いただけます。 詳しくは、 製品紹介ページ をご確認ください。 株式会社マクニカ 様 菱洋エレクトロ株式会社 様 また、 Amazon.co.jp からもご購入いただけます。 在庫も潤沢にございますので、この機会にぜひ導入をご検討ください。 www.aptpod.co.jp
ROSの画像メッセージを遠隔監視したいと思ったことがあるみなさん、 こんにちは。ソリューションアーキテクトの伊勢です。 以前、当ブログではロボット開発プラットフォームのROSとインターネットをつなぐ技術「intdash Bridge」をご紹介しました。 tech.aptpod.co.jp この intdash Bridge が2023年2月から画像のROSメッセージに対応したので、適用例とともにご紹介します。 その前に おことわり これはあくまで"やってみた"記事です。 正式なインストール手順などは公式ドキュメントをご参照ください。 使われている機能 これからご覧いただく動画の構成要素です。 intdash Bridge ROSメッセージをintdash Serverと双方向通信するためのソフトウェアです。 intdash Bridge MJPEG形式とH.264形式でROSデータを送受信できるようになりました。 ROSを流れる画像 ( /sensor_msgs/Image /sensor_msgs/CompressedImage )をMJPEGで、または動画データ(H.264)に変換してリアルタイムで可視化したり、別のエッジデバイスにPublishしたりできます。 今回はUSBカメラの画像データを確認しています。 なお、ROS2版である intdash ROS2Bridge でも対応しています。 intdash CONTROL CENTER 複数モビリティの運行管制向けソリューションフレームワークです。 以前、一部のコンポーネントをご紹介しました。 tech.aptpod.co.jp 今回は2つのコンポーネントでカメラとロボットに制御コマンドを届けています。 遠隔指示コマンドVisual Parts Data Visualizerからエッジデバイスにコマンドを送信します。 遠隔指示コマンドデバイスコネクタ(ROS) エッジデバイスでサーバーからコマンドを受信してintdash Bridgeに連携します。 intdash CONTROL CENTERコンポーネント(黄色) 本題 お待たせしました。 それでは、動画をご覧ください。9分半ほどです。 www.youtube.com このような構成になっています。 0:48 ROSとは 1:18 ROSの画像表示 1:59 カメラ画像を遠隔監視 3:59 カメラ画像を遠隔制御 5:13 ロボットも遠隔制御 6:12 ロボットも遠隔監視&自動制御 ROSの説明や構成図を飛ばしたい方は 6:44ぐらい からどうぞ。 まとめ 今回は、intdash Bridgeとintdash CONTROL CENTERの組み合わせによるエッジデバイスでのカメラ制御を行いました。 ROSは柔軟にノードを追加してメッセージを再利用できるところがいいですね。 intdashを使ってインターネットと双方向通信ができることでさらに応用の幅が広がります。 なお、Upstreamした画像データは他データと同期したタイムスタンプでクラウドに保存されるため、あとから再生・確認・分析が可能です。 参考 ちなみに今回ROSノードはこのような構成にしました。 ROSノード(rqt_graph) /switcher ノードが カメラの画像メッセージをSubscribe intdash Bridgeからコマンド /intdash/ctl_cmd_string をSubscribe コマンドのカメラ番号に一致する画像メッセージを画像変換 /switcher/image_raw にPublish /intdash/intdash_bridge ノードが /switcher/image_raw をAgentに連携 カメラ番号や /rosbridge_websocket から受けたロボット制御プログラムのセンサーデータもAgentに連携 しています。 予告 intdash CONTROL CENTERでは、複数モビリティへのタスク配分やルート設定など運行管理機能の拡充も予定しています。近々、当ブログでご紹介したいと思います。 www.aptpod.co.jp
こんにちは、アプトポッドVPoPの岩田です。 そろそろコロナ禍も収束に向かい、だんだんと原則出社に戻す会社も出始めている頃合いではありますが、当社はまだまだリモートワーク体制を継続していく予定です。 そんななか当社では、リモートワーク体制でオフィスの稼働率が低下していることをきっかけとして、 オフィスの縮小 を行いました。 その際の物品整理、特に蔵書の処分方法のひとつの選択肢として、当社では「公共図書館への寄贈」という選択肢を取りました ので、皆様にご紹介したいと思います。 これは私個人の個人的な思いではありますが、まだ読める、誰かの役に立てる書籍を「捨てる」という選択肢をとることにどうしても抵抗があり、どうにか救う方法はないかと考えた結果ふと思いついた方法が「寄贈」でした。 コロナ禍が続き、当社のようにオフィスを縮小したり撤廃したりする企業様も出てきていることと思います。そういった中でこの記事が担当者様の目に留まり、 リユースされる書籍が少しでも増えることにつながれば幸いです。 事の発端 - オフィス縮小プロジェクト え、捨てるの?まだ読めるのに? - 廃棄の発覚 なにか手はないものか - 寄贈という選択肢 寄贈時の注意点 寄贈までの社内の流れ いざ、寄贈へ さいごに ついでにお知らせ 事の発端 - オフィス縮小プロジェクト 当社では、 2020年にコロナ禍が発生した直後にリモートワーク体制を導入 し、そこから現在に至るまで、基本的にリモートワークを継続しています。 当社には、ハードウェア/ソフトウェアエンジニアから営業・プリセールス、バックオフィスまで様々な職種のメンバーが在籍していますが、 特にソフトウェア系のエンジニアについては、ほぼ100%がリモートワークを行っている 状況です。 物理的なハードウェアを扱うハードウェアエンジニアや、お客様とお話する機会の多い営業・プリセールス、バックオフィス系のメンバーについては、必要に応じてオフィスへ出社して勤務することもありますが、それでも オフィスの座席稼働率は平均的に10~20%割程度しかない 状況が続いていました。 昨年の座席稼働率の推移 当社オフィスは四谷三丁目駅から徒歩数分の位置にあるオフィスビルの3階と5階を使用していますが、これは全社員が出社しても収容できるだけのスペースを確保した広さになっています。前述の通り、コロナ禍に伴い出社率が大幅に低下した結果、2階分あるうちの1階分にはほとんど人がいないような状況が継続的に発生するようになり、この度、オフィスの縮小に踏み切ることとなりました。 オフィス縮小では、5階を解約し3階に集約する計画となったのですが、ここで問題となったのが十数年の会社運営で溜まりに溜まった様々な物品の整理です。床面積が半分になるので、相当多くの什器や物品を整理(処分)しなければならず、 これまで社員の希望で購入し会社に配置されていた蔵書もその整理対象となりました。 え、捨てるの?まだ読めるのに? - 廃棄の発覚 蔵書のほとんどが技術書だったので、オフィス縮小プロジェクトのメンバーからCTO梶田とVPoPである私の2名に「必要な書籍を選別せよ」との依頼が飛びました。今回のオフィス縮小では、床面積が大幅に縮小することもありスペース確保が最優先とのことでしたので、CTO梶田とも相談した結果、数冊を残してその他は処分するという結論としました。 処分対象となった蔵書は、おおよそ100冊~300冊です。 このとき、個人的によく書籍の中古買取り店を利用していたこともあり、 処分対象の書籍についてはてっきり「売却処分」となるものと思い込んでいた のですが、プロジェクトメンバーに改めて聞いてみたところ、どうやら 売却ではなく廃棄 になってしまうとのでした。 たしかによくよく考え直してみると、いち企業のオフィス解体と、個人の引越しや家財整理では勝手が異なることは理解できます。書籍の中古売却で得られる金額などその他費用と比べるとたかが知れており、全体から見ると書籍が「資産性のないもの」に分類されてしまうのは容易に想像がつきました。 プロジェクトメンバーからは、廃棄対象の書籍について、希望があれば社員に引き取ってもらっても構わない旨は指示がありましたが、それでも引き取り手が見つからなかった場合には、やはり廃棄となってしまうようでした。 なにか手はないものか - 寄贈という選択肢 冒頭にも記載したことですが、個人的には、 まだ読める、誰かの役に立てる書籍を「捨てる」という選択肢にはどうしても抵抗がありました。 今自分たちには必要がないとしても、それはその書籍に価値がないからではなく、我々が今それを必要としていないだけです。それを読んで役に立つと思う人も世の中にはいるはずで、その人たちとその書籍が出会えていないだけなのだという思いが頭の中を回っていました。 そうして考えを巡らせる中で、書籍と人との出会いの場として思い至ったのが「図書館」です。思いついたらすぐ行動、気がついたら Google Map でオフィス周辺の図書館を調べていました。 すると オフィスから歩いていける距離に新宿区立四谷図書館がある ではないですか。また、新宿区立図書館のWebを確認すると、利用案内に「 資料の寄贈について 」というページがありました。これぞまさに探していたものです。 www.library.shinjuku.tokyo.jp すぐに「寄贈」というアイデアについてプロジェクトメンバーに確認して了承をとり、さらに四谷図書館に電話で問い合わせをしてみました。すると、いくつか注意点はあるものの、四谷図書館の担当者様にも快く了承をいただくことができました。 寄贈時の注意点 まず第一に、寄贈に関する注意点は、それぞれの図書館のWebに記載があることが予想されます。 そもそも問い合わせ自体も図書館の通常業務に影響してしまうため、まず自分で集められる情報は極力自力で集めるようにするのが良い と思います。 例として、今回寄贈させていただいた四谷図書館を挙げると、Webにはこのように記載されています。 新宿区立図書館のWebサイト ざっと内容を要約すると、以下の通りとなります。 持ち込みは寄贈者自身で行う 一般の書籍は、汚損破損、書込み等がなく、年数経過が少ないことが条件 参考書、問題集、漫画、自伝等自費出版的資料 については対象外 蔵書するかどうかは図書館の判断であり、希望は受け付けない 蔵書対象外となりリサイクルコーナーで利用者へ提供する場合がある なかでも重要なのは、「汚損破損がないこと」と「寄贈者自身で持ち込むこと」でしょうか。なんでも持っていけばOKというわけではなく、きちんと自社内で品質を確認してから、自分自身で持ち込まなければいけません。「ゴミを処分する代わりに持っていく」のではなく、「価値あるものを次の人に届けるお手伝いをしてもらう」のですから、事前の手間がかかるのは当然です。 また、今回は個人からの寄贈ではなく法人からの寄贈であり、分量が多くなったり、寄贈する書籍の種類にも偏りがある(技術書が多い)ため、念の為四谷図書館にも直接電話で問い合わせをし、寄贈に問題がないか(ご迷惑でないか)事前に確認することにしました。 ちなみに、ここ(問い合わせでの為念確認)はとても重要であると考えます。今回四谷図書館は快く引き受けてくださいましたが、寄贈を受け付けているかどうかや、寄贈に対する考え方は各館ごとに異なると思われます。多くの書籍が一度に寄贈されてしまうと当然通常業務の圧迫にもつながるため、法人からの寄贈は受け付けないという選択肢もあって当然のことと思います。皆様も、寄贈を検討する際には十分にご注意ください。 ちなみに、今回のケースでは、やはり蔵書にするかどうかの判断については図書館側で決める、自分で持ち込む、の2点についてこちらで問題なければ、技術書でも、分量があっても問題ないとのことでした。 寄贈までの社内の流れ ご参考までに、寄贈に至るまでの社内の流れをご紹介します。 2022/08 オフィス縮小プロジェクト発足 2022/11 蔵書整理依頼が飛ぶ、大半の蔵書が残存不要という整理に 2022/12 不要書籍が廃棄処分となることが分かる 2023/01 図書館への寄贈案が浮上、図書館へ問い合わせ 2023/02 社員より希望のあった書籍の引取りを実施 2023/03 残った書籍の寄贈を実施 この間、蔵書として残す書籍の選別、廃棄対象の書籍の引き取り希望アンケート実施、オフィス中の本棚からの蔵書のかき集めなど、色々と面倒な作業がありましたが、なんとかオフィス縮小のタイミングに間に合わせることができました。 いざ、寄贈へ 最後に、寄贈当日の流れをご紹介します。 まずはオフィス中から蔵書をかき集めます。雑誌等も含め一旦すべて集めると、ダンボール6箱分にもなりました。 集められた書籍を入れたダンボール(6箱!) 次に、集めた書籍を一冊ずつ蔵書の管理リストと照らし合わせつつ、ついでに汚れ具合をチェックしていきます。(この過程で、集められた書籍のなかに個人所有のものもかなり混ざっていたことが発覚しました、危ない危ない) リストチェックと仕分けの様子 選別の結果、最終的にはダンボール3箱分の書籍が品質チェックをクリアし、寄贈対象となりました。 品質チェックをクリアした書籍たち 運搬の様子。四谷図書館はきれいなビルの中に入っていて、さすが都会の図書館といった感じでした。 四谷図書館が入っている建物のロビー。きれいなビルでした さいごに 個人的には、図書館への書籍の寄贈という体験自体が始めてだったこともあり、本当に受け取ってくれるのか、ご迷惑にならないのかなど、色々と気を揉んで進めたミッションでしたが、推進する側もよく分かっていない手探りでの進行のなか、 こういった話題にも手を挙げて快く手伝いを引き受けてくれるメンバーがいるというのは幸せなことだなぁと改めて感じました。 今回のこの活動が、本当に世の中のためになったのか、ただ図書館の方々の業務を圧迫しただけの自己満足でしかないのか、実際のところは正直分かりません。ただ、何もしなければただ廃棄されるだけだった書籍に、少なくとも一度は新しい持ち主に出会うチャンスを与えられたのは確かです。寄贈した書籍が新しい持ち主に有効活用されることを願って、今回のミッションはコンプリートということにしたいと思います。 ちなみに、本業であるソフトウェア開発に精進していくのはもちろんですが、たまにはこういった、ちょっと一風変わった活動も、いろいろな人のいろいろな側面が垣間見られて面白いなと感じました。 毎日のリモートワークで煮詰まってきたら、息抜きがてら社会貢献というのもアリかもしれません。 それでは今回はこの辺で。最後までお読みいただきありがとうございました。 ついでにお知らせ アプトポッドでは産業用IoTプラットフォームミドルウェアintdashの開発・販売および、intdashを活用したシステム開発を行っております。弊社のプロダクトやビジネスにご興味をお持ちいただけましたら、弊社のコーポレートサイトをご覧ください。 「IoTシステムを構築したいがどんなアーキテクチャがよいのかわからない」「MQTTで構築した既存のIoTシステムがあるが限界を感じている」など、IoTシステム構築に関する一般的なご相談につきましても、お問い合わせいただければお力添えいたします。 www.aptpod.co.jp また、本記事をお読みいただき、アプトポッドに興味を持ってくださったエンジニアの方々からの連絡もお待ちしております。 まずはカジュアルな情報交換からでも構いません。会話をさせていただくなかで、募集中の職種をご紹介させていただきます。( 採用ページはこちら ) www.wantedly.com
モビリティを少しの手間で遠隔制御できるようにしたいと思ったことがあるみなさんに話しかけています。 こんにちは。ソリューションアーキテクトの伊勢です。 以前、当ブログで「intdash CONTROL CENTER」をご紹介しました。 tech.aptpod.co.jp tech.aptpod.co.jp intdash CONTROL CENTERはモビリティ管制制御システム向けソリューションです。 今回は適用例として、遠隔地からコマンドを送信するビジュアルパーツなどのコンポーネントを使って市販のロボットを制御してみます。 その前に おことわり これはあくまで"やってみた"記事です。 intdash CONTROL CENTERは鋭意開発中のソリューションです。 正式なインストール手順などは公式ドキュメントをご参照ください。 本題 気軽に見ていただけるように8分ほどの動画にしてみました。どうぞご覧ください。 www.youtube.com ロボットやコンポーネントの説明を飛ばしたい方は 5:30ぐらいから どうぞ。 まとめ 今回はシンプルなモビリティの例としてロボットトイを取りあげました。 同じ仕組みにより、ビル内の巡回ロボットや工場内の搬送ロボット、公道を走るデリバリーロボットなどに適用が可能です。 intdash CONTROL CENTERは、他にも自律運転車、建設機械、ドローンなどのインテグレーションも想定しています。 www.aptpod.co.jp intdash CONTROL CENTERは、今回ご紹介した遠隔指示コマンドパーツをはじめとして、管制制御向けのコンポーネントを複数備えています。 また、より高度なフリート管理のため、モビリティへのタスク配分やルート設定などの機能も追加していきます。また別の機会でご紹介したいと思います。
こんにちは。コーポレートマーケティング室の白崎です。 aptpodのマーケティング全般を担当しています。 2023年1月25日(水)〜1月27日(金)に東京ビッグサイトで開催された第7回ロボデックスに出展し、モビリティ/ロボット群管理・遠隔制御ソリューションフレームワーク「 intdash CONTROL CENTER (以下、CONTROL CENTER)」を展示しました。 連日、多くの方々にご来場いただき、感謝申し上げます。 大盛況のアプトポッドブース 今回の記事では、ご来場いただいた方はもちろん、ご来場できなかった方もいらっしゃると思いますので、改めて展示内容についてご紹介させていただきます。 CONTROL CETNERとは? CONTROL CENTERの構成 CONTROL CENTERが実現する機能 展示内容 おわりに CONTROL CETNERとは? CONTROL CENTER はアプトポッドが2022年12月にベータリリースした、モビリティやロボット向けのリアルタイムかつインタラクティブな管制制御システムを迅速に構築するためのソリューションフレームワークです。 本ソリューションを活用頂くことで、ロボットや自動車、建機・重機といった複数のモビリティを対象に、遠隔からモビリティ群を監視・管理することができ、必要に応じて人の手による遠隔指示・操作の介入を行うことができるようになります。 CONTROL CENTER適用シナリオ例 CONTROL CENTERの構成 CONTROL CENTERはモビリティ/ロボットなどの機体との送受信処理を行うエッジソフトウェアコンポーネントとデータストリーミング中継処理やデータ保存を行うサーバ・ソフトウェア、及びリアルタイムな群管理や個別機体の状態モニタを行うことができるWebアプリケーションコンポーネントで構成されます。 CONTROL CENTERが実現する機能 主な機能を6点ご紹介します。 ①リアルタイムなフリートマップマッピング  機体群の位置情報、映像などをマップマッピングし、Webベースの統合監視環境 ② 機体群の管理UI  機体群のステータス一覧や、SoC・稼働率の管理 ③ 個別機体の様々なリアルタイムデータ確認が可能なダッシュボード  リアルタイムな機体詳細データをダッシュボード表示 ④ 遠隔操作、操縦  遠隔制御コントローラー向けのコンポーネントを提供 ⑤ ロボット、モビリティ、センサーからカメラまで様々なデバイスの接続  様々なデバイスが接続するための接続コンポーネントを提供 ⑥データの収集と活用  運用時のすべてのデータを過去データとしてサーバに永続化 ※より詳しい機能の説明、デモ動画は下記のテックブログ記事をご覧ください。 tech.aptpod.co.jp 展示内容 ロボデックスではCONTROL CENTERを利用した、2つのユースケースにおけるデモを紹介しました。1つ目はロボット群のフリート管理、2つ目はロボットの遠隔操作です。 ①ロボット群フリート管理 CONTROL CENTERのリファレンスアプリケーションであるフリートマップアプリケーションを使用して、各機体の位置や状態をリアルタイムに可視化することができます。 各ロボットの詳細なデータを確認したい場合には、フリートマップアプリケーションからデータ可視化ダッシュボード( Visual M2M Data Visualizer )に遷移して、機体データの詳細をダッシュボード上で確認することができます。 フリートマップアプリケーション上に複数のロボットの位置情報を表示(画面下部には選択しているロボットの名称や状態、カメラ映像を表示) 遷移先のデータ可視化ダッシュボード画面 モビリティ毎の状態(ステータス)、速度、稼働率などの稼働状況や、バッテリー稼働のモビリティのSoC(State Of Charge)やSoH(State of Health)など、モビリティ管理に必要な詳細なデータを遠隔から監視できるようになります。 ダッシュボード上のVisual Partsを変更することで、対象となるデータの値を表示するだけでなく、時間変化に伴う稼働率状況の変化などをグラフ表示することもできます。また、ノンプログラミングでユーザによる自由なダッシュボードの構成変更が可能です。 6台のロボットそれぞれの詳細データ(速度,SoC,SoHなど)をダッシュボード上に表示 稼働率状況の変化などをグラフ表示 ②ロボットの遠隔操作 オープンソースの移動ロボットプラットフォームである「Turtlebot3」(実機のロボット)を使用した遠隔操作のデモです。ロボットに搭載されたカメラ、センサ情報をリアルタイムにVisual M2M Data Visualizerで監視を行いながら、コントローラを使って遠隔操作を行うことが可能です。 ロボデックスでは会場である東京ビッグサイトから監視を行いながら、コントローラを使って弊社の四谷オフィスにあるTurtlebot3を遠隔操作しました 弊社の四谷オフィスにあるTurtlebot3を遠隔操作 弊社四谷オフィスで遠隔操作されたTurtlebot3 実際にお客様がコントローラで遠隔操作を試すことができるデモとなっており、「スムーズに遠隔操作できて驚いた」等の感想をいただき好評でした! おわりに 今回はモビリティやロボットのリアルタイムかつインタラクティブな管制制御システムを迅速に構築するためのソリューションフレームワークであるCONTROL CENTERを紹介しました。 ロボット管制・管理、遠隔操縦、フリート管理などに課題をお持ちの方は、下記リンクより是非お気軽にお問合せください。 aptpodお問合せフォーム 今後も積極的に展示会への出展を予定しており、決定次第、 コーポレートサイト 等で告知します。 様々なデモをご覧いただける機会ですので、ぜひお立ち寄りください! アプトポッドは豊富な実績と高い技術力で、これからもお客様の課題解決に貢献していきます。
intdashは、2022年11月からプロジェクト別のアクセス権限管理機能の提供を開始しました。 これにより、ユーザーが他のユーザー・エッジ・計測を見る権限をコントロールできるようになっています。 手順を確認してみましょう。 こんにちは。ソリューションアーキテクトの伊勢です。 以前のintdashでは、1ドメイン内の全ユーザーがすべてのユーザー、エッジ、計測(以下、リソース)を参照できました。 企業や組織の利用シーンでは、部署やチーム間で見えるリソースを制限したいケースがあります。 その仕組みを提供するのがプロジェクト機能です。 今回はその紹介の前編です。 まだすべてのアプリケーションが対応できているわけではないため *1 、どのような考え方で参照をコントロールするのかを中心に、画面を見ながら機能を確認していきます。 プロジェクト機能 その前に おことわり ドメイン、ユーザー、エッジとは 今までと何が変わったのか 今までとの互換性 確認ポイント 確認用の構成 確認 ユーザー・エッジの作成 ユーザー・エッジの参照 ユーザー・エッジの参照:Global Projectの場合 グループ・プロジェクトの作成 ユーザー・エッジの割り当て ユーザー・エッジの参照:project1、project2の場合 計測 計測の参照:Global Projectの場合 計測の参照:project1の場合 プロジェクト・サブグループへのメンバー追加 プロジェクトへのメンバー追加 サブグループへのメンバー追加 ロールの追加 ロールの追加:プロジェクト ロールの追加:サブグループ 利用中の権限削除 利用中の権限削除:画面表示中のユーザー 利用中の権限削除:ストリーム中のエッジ マルチテナントとの違い まとめ その前に おことわり これはあくまで"やってみた"記事です。 正式な手順はユーザーガイドやデベロッパーガイドをご参照ください。 ドメイン、ユーザー、エッジとは ユーザーガイド によると以下のとおりです。 intdashサーバーを中心とする、1つのintdash使用環境をドメイン(またはintdashドメイン)と呼びます。 intdashサーバーに接続できるのは、そのドメインで発行されたアカウントを持つユーザーとエッジ(データを送受信するデバイス)のみです。 ドメイン、ユーザー、エッジ エッジは、デバイス1台を指します。 ユーザーは、intdashにアクセスする利用者です。1人のユーザーが複数のエッジを所有することができます。 ユーザーには権限としてロールを割り当てます。 他のユーザーを作成できる管理者には admin ロール、一般ユーザーには member ロールを割り当てます。 今までと何が変わったのか プロジェクト機能が導入される前は、1ドメイン内の全ユーザーがそのドメインにあるすべてのリソースを参照できました。 最新のintdashでは、リソースを プロジェクト という単位で管理し、プロジェクトごとに、アクセス可能なユーザーやエッジを設定するこができます。これにより、他部署や他チームからリソースを参照/削除できないようにすることができます。 プロジェクト機能 今までとの互換性 アクセス権を細かく管理する必要がない場合も、今までどおり利用できるように互換性を設けています。 それがGlobal Projectというデフォルトのプロジェクトです。 最新のintdashでは、ユーザー、エッジを作成すると自動的にGlobal Projectに登録されます。 これにより、Global Projectを通じて1ドメイン内のすべてのリソースを参照できるようになっています。 *2 Global Project 確認ポイント 以下では、段階的にプロジェクトやユーザーの設定を行いながら、各ユーザーからのリソースの見え方を確認していきます。 ユーザー・エッジの参照 計測の参照 プロジェクト・サブグループへのメンバー追加 ロールの追加 利用中の権限削除 マルチテナントとの違い 確認用の構成 はじめに設定の全体構成を掲載しておきます。 ユーザーとエッジ グループとプロジェクト プロジェクト機能の導入により、管理リソースは3階層に分かれることになりました。 グローバルレベル:プロジェクトに関わらず共通 ユーザー エッジ グループ プロジェクト グループレベル:複数のプロジェクトに共通 メンバー割り当て プロジェクトレベル:1プロジェクトに固有 メンバー割り当て エッジ割り当て 計測 確認 では上記のリソースを作成しながら、確認していきましょう。 ユーザー・エッジの作成 まずはユーザーとエッジを作成します。 ユーザとエッジの構成はこのようになります。 ユーザーとエッジ グループとプロジェクトはこうなります。 グループとプロジェクト(Global Project) 既存の管理者ユーザー( *3 )を user1 として手順を始めます。 ユーザーガイド 9. (管理者向け)ユーザーとエッジを管理する - Admin Console にしたがい、 member ロールを持つ一般ユーザ user2 と user3 を作成します。 ユーザーの作成 作成したユーザーをユーザー一覧で確認できます。 ユーザー一覧 次にエッジを作成するため、 user2 でサインインしなおします。 ちなみに admin ロールを持っていない user2 はAdmin Consoleを表示できません。 一般ユーザーのAdmin Console ユーザーガイド 4.4. エッジアカウントを作成する にしたがい、My Pageでエッジ edge1 と edge2 を作成します。エッジの所有者は user2 になります。 エッジの作成(My Page) user3 でサインインしなおし、同じく edge3 と edge4 を作成します。エッジの所有者は user3 になります。 続いて user1 でサインインしなおし、所有者なしエッジを作成します。ユーザーガイド 9.9. エッジアカウントを作成する(管理者向け) にしたがい、Admin Consoleでエッジ edge5 を作成します。 エッジの作成(Admin Console) 作成したエッジをエッジ一覧で確認できます。 エッジ一覧 ユーザー・エッジの参照 まず、ユーザとエッジがGlobal Projectでどう見えるか確認します。 ユーザー・エッジの参照:Global Projectの場合 作成したユーザーのいずれかでProject Consoleを開くと Projects に Global Project のみが表示されています。 Project Console Global Project を選択し、メニューのEdges、MembersでGlobal Projectの管理リソースを確認します。 さきほど作成したユーザーがGlobal Projectのメンバーとして自動的に割り当てられています。 メンバーにはユーザーの member ロールが引き継がれています。 Global ProjectのMembers また、さきほど作成したすべてのエッジがGlobal Projectに自動的に割り当てられており、参照できます。 Global ProjectのEdges このように、Global Projectではすべてのユーザーからすべてのリソースを参照できました。 グループ・プロジェクトの作成 では、いよいよプロジェクトを作成していきましょう。 Global Projectとは別にプロジェクトを作成します。このような構成を作成します。 グループとプロジェクトの作成 まずは user1 でサインインし、Admin Consoleで group1 グループを作成します。 グループの作成 続けて group1 の配下に project1 を作成します。 プロジェクトの作成 同じく、 group1 の配下にプロジェクト project2 を作成します。 Project Consoleで group1 を選択すると Projects でプロジェクトの一覧を確認できます。 Projects なお、Admin Consoleのグループ一覧に表示されている Global Group は、Global Projectが属する特別なグループです。削除や新たなプロジェクト作成、メンバー割り当てはできません。 Global Group ユーザー・エッジの割り当て 作成したグループとプロジェクトにユーザーとエッジを割り当てます。 ユーザーとエッジの割り当て user1 でサインインし、Project Consoleでグループ group1 に user2 をメンバーとして追加します。 Admin Consoleでユーザーを作成したときのロールとは関係なく、プロジェクトごとにロールを付与できます。 今回は member ロールを付与します。 group1のメンバー一覧 続いて、エッジを割り当てます。 まずは、エッジの所有者として、エッジの割り当てを行ってみます。 user2 でサインインし、所有エッジ edge1 を project1 に登録します。 エッジの割り当て 次に、プロジェクトの管理者としてエッジの割り当てを行ってみます。所有者なしのエッジを登録するにはそのプロジェクトの admin ロールが必要なため、 user1 としてサインインし、所有者なしエッジ edge5 を登録します。 project1のEdges 同じく project2 にもエッジを割り当てます。 edge3 は user1 としてサインインした状態で登録します。 ユーザー・エッジの参照:project1、project2の場合 では、ユーザーごとに参照できる範囲を確認します。 まず、 user2 が参照できる範囲です。 Project Consoleで user2 が所属するプロジェクト project1 でMembersを確認します。 所属する user1 と user2 を参照できます。所属しない user3 は表示されません。 なお、 user2 は上位グループ group1 のメンバーであるため、ロールが継承されて Inherited Member として表示されます。プロジェクトを作成した user1 は Owner と表示されます。 project1のMembers Edgesで先ほど登録したエッジ edge1 、 edge5 を確認できます。 次に、作成したプロジェクトに属していない user3 でも確認してみます。 Project Consoleの Projects を見ると、 project1 、 project2 が表示されておらず、プロジェクトのリソースを確認することができません。 割り当てられてないとプロジェクトは見えない 割り当てられていないプロジェクトのURLに直接アクセスしても、リソースは表示されません。 URL直指定(自分が割り当てられていないプロジェクト) 以上の通り、プロジェクト機能により、プロジェクトに所属するユーザー・エッジがプロジェクト外から参照できないことを確認できました。 なお、当記事では比較のため、Global Projectにリソースを登録したままにしています。実際の運用ではGlobal Projectからユーザー・エッジの割り当てを削除してください。 計測 続いて、エッジによる計測の作成を確認してみます。 まずはGlobal Project向けにUpstreamします。 エッジをセットアップします。今回はMJPEGとStringを送信します。 *4 edge1 ではMJPEG、 edge3 と edge5 ではStringをUpstreamします。 計測の参照:Global Projectの場合 まずはGlobal Projectでリアルタイム再生を確認します。 Agentで接続先のプロジェクトUUIDとしてGlobal Projectを指定します。 intdash Edge Agent 2 では intdash-agentctl config で、 project_uuid として 00000000-0000-0000-0000-000000000000 を指定します。 intdash Edge Agent では設定ファイルの project_uuid に空を設定します。 Terminal System では 接続先と認証 で プロジェクトUUID に空を設定します。 intdash Edge Agent 2での接続先プロジェクトの指定(Global Project) Upstreamを開始します。 user2 でサインインしてGlobal ProjectでData Visualizerで確認します。すべてのUpstreamデータが確認できます。 Data Visualizer(Global Project) 計測の参照:project1の場合 続いて、各エッジの接続先を project1 に変更してUpstreamします。 AgentのプロジェクトUUID設定を変更します。 プロジェクトUUIDの取得 intdash Edge Agent 2での接続先プロジェクトの指定(project1) 変更した設定でUpstreamを開始します。 なお、 edge3 は project1 に所属していないため、Agentを起動すると認証エラーとなります。 プロジェクトに所属していないエッジは認証エラー Project Consoleで project1 を選択し、さきほどと同じスクリーンを表示します。 project1 に属するエッジ edge1 と edge5 のUpstreamデータだけが表示されています。 edge3 は project1 には所属していないため、パネルにエッジ名が NO EDGE で表示されます。 Data Visualizer(project1) エッジの接続先プロジェクトを変更したため、Global ProjectのスクリーンにはUpstreamデータが表示されません。 Data Visualizer(Global Project)(データはproject1に送信されているためGlobal Projectでは参照できない) 同じく、Agentの接続先を project2 に変更して project2 のData Visualizerを確認すると edge1 と edge3 のUpstreamデータのみが表示されます。 edge5 はAgent起動時に接続エラーとなります。 Data Visualizer(project2) Data Visualizer(project1)(データはproject2に送信されているためproject1では参照できない) プロジェクト機能により、プロジェクト外のユーザーから計測を参照できないこと、プロジェクト外のエッジからプロジェクトに計測を作成できないことを確認できました。 ここまでで、ユーザー・エッジ・計測の参照制御というプロジェクト機能の基本的な効果が確認できました。 プロジェクト・サブグループへのメンバー追加 では、次に少し使い方をレベルアップしていきたいと思います。 ここまでは、プロジェクトのメンバーは、プロジェクトの上位のグループで設定されたロールを継承していました。 運用上は、細かい範囲に限ってメンバーやロールを追加したいケースがあります。 まずはメンバー追加について確認します。 プロジェクトに直接メンバーを追加する方法、上位グループの下にサブグループを作成してメンバーを追加する方法をご紹介します。 user1 としてサインインした状態で、 group2 配下のグループ・プロジェクトを作成し、エッジを割り当てます。 プロジェクト・サブグループへのメンバ追加準備 サブグループの作成 Subgroups 新たに作成した2つのプロジェクトに2通りの方法でメンバーを追加します。 プロジェクト・サブグループへのメンバー追加 プロジェクトへのメンバー追加 まず、プロジェクトにメンバーを追加します。 user3 を project3 に追加します。(操作は user1 として行ってください。) プロジェクトへのメンバー追加 user3 でサインインするとProject Consoleで project3 を参照できます。 プロジェクトに追加されたメンバー プロジェクトに追加されたメンバーから見えるエッジ サブグループへのメンバー追加 続いて、サブグループにメンバーを追加します。 user3 を group2-1 に追加します。(操作は user1 として行ってください。) サブグループへのメンバー追加 user3 でサインインするとProject Consoleで subgroup2-1 、 project4 を参照できます。 サブグループに追加されたメンバー サブグループに追加されたメンバーから見えるエッジ ロールの追加 次に追加したメンバーにロールを追加してみます。 ロールの追加:プロジェクト まずはプロジェクトに追加したメンバーにロールを追加します。 user3 に、 project3 における admin ロールを追加します。(操作は user1 として行ってください。) プロジェクトでのロール追加 プロジェクトでadminロール追加 user3 は project3 でメンバーを追加・削除できるようになったため、Project ConsoleのMembersに Add Member ボタンが表示されます。 user3は、このプロジェクトにおいてadminロールを追加された ロールの追加:サブグループ 続いて、サブグループに追加したメンバーにロールを追加します。 user3 に、 group2-1 における admin ロールを追加します。(操作は user1 として行ってください。) サブグループでのロール追加 サブグループでadminロール追加 user3 は group2-1 でメンバーを追加・削除できるようになったため、 Add Member ボタンが表示されます。 user3は、このサブグループにおいてadminロールを追加された ここまで説明してきた基本的な考え方を応用して、より複雑な権限制御も簡単に実現することができました。 利用中の権限削除 だいぶ長くなってきて読み手の方はお疲れだと思います。 実は書き手も疲れてきているのですが、もう少しだけおつきあいください。 運用中に権限を変更する上でどうしても気になる点を確認したいと思います。 intdashを利用中にユーザーやエッジの権限を削除するとどうなるのでしょうか。 データを送信中の edge1 と、それをリアルタイムにData Visualizerで見ている user2 を、プロジェクトから削除してみます。 利用中のユーザー・エッジの割り当て削除 Data Visualizerでリアルタイム再生します。 再びproject1のData Visualizer 利用中の権限削除:画面表示中のユーザー まず、Data Visualizerを見ているユーザーの削除です。 user1 で group1 からメンバー user2 を削除します。 adminとしてuser2をグループから削除 ユーザーが削除されてもData Visualizerは問題なく表示され続けます。 利用にはすぐに影響が出ないようになっていますね。 削除されたユーザーで参照を継続 利用中の権限削除:ストリーム中のエッジ 続いて、 project1 からエッジ edge1 を削除してみます。 エッジも削除 削除したエッジのUpstreamデータが表示され続けます。 こちらも権限変更が作成中の計測に影響を与えないようになっています。 削除されたエッジの参照を継続 では、削除した権限はいつ反映されるのでしょうか。 ユーザーは次の画面アクセスです。 Data Visualizerの画面をリロードすると、メッセージが表示されて project1 にアクセスできなくなったことがわかります。 403 Forbidden エッジは次の計測開始です。 Upstreamを一度停止し、再度開始すると認証エラーで接続できなくなったことがわかります。 "Unauthorized" いずれも新たな接続でアクセスが拒否されることがわかりました。 マルチテナントとの違い プロジェクト機能と混同しやすい機能としてマルチテナントがあります。 最後にマルチテナントとの違いを説明します。 マルチテナントは複数ドメインを同時利用する場合に、インフラ・プラットフォームを共有して運用コストを低減するオプションです。 主に、intdashを使ったサービスの提供者が複数のお客様に環境を提供する場合を想定しています。 お客様ごとに環境を設けるよりも低コスト化されます。 なお、テナントの管理リソースはグローバルレベルにおいても完全に分離されており、他のテナントからは参照・変更できません。 マルチテナント 一方、プロジェクト機能はここまで見てきたように、1ドメインの中での権限制御機能です。 グローバルレベルの管理リソースはプロジェクト間で共有されます。 また、マルチテナントのドメインでプロジェクト機能を利用する場合は、1テナントの中での権限を制御することになります。 マルチテナントでプロジェクト機能 まとめ お疲れ様でした。これにて前半はおしまいです。 プロジェクト機能により、組織でintdashを利用するときの柔軟な権限制御ができるようになったことがわかりました。 マルチテナントもそうですが、プロジェクト機能はintdashをより大規模にご利用いただくことを想定して追加された機能です。 お客様のビジネスの発展・拡大に貢献すべく、aptpodのプロダクトは進化を繰り返していきます。 後編では、プロジェクト機能によるData Visualizer以外のアプリケーションの変更をご紹介したいと考えています。 *1 : アプリケーションのEdge Finder、Meas Hub、Media Explorerは現時点でGlobal Projectの計測のみ対応しています。今後のアップデートで対応予定です。 *2 : 自動的にGlobal Projectに登録するかどうかはドメインの設定によって異なります。 この設定はサーバー側の構築・運用担当者によって変更が可能です。 設定の詳細については、現在ドキュメントを準備中です。公開までお待ちください。 *3 : 通常、システム管理者から利用者に提供されます。 *4 : セットアップ手順は割愛します。 intdash Edge Agent 2 デベロッパーガイド をご参照ください。
2022年12月に intdash Edge Agent 2 デベロッパーガイド が公開されました。 これまでの intdash Edge Agent (以降、Agent 1)と設定手順を比較してみましょう。 はじめまして。ソリューションアーキテクトの伊勢です。 普段はお客様への提案を担当していて開発作業は行わないので、intdash Edge Agent 2(以降、Agent 2)にまだ直接触れられていません。どうやら、Agent 1の課題だった機能群の関係性のわかりやすさが改善されたことにより、設定方法が変わっているようです。 今回はAgent 2のご紹介がてら、具体的に設定作業がどう変わったのか確認していきたいと思います。 docs.intdash.jp 目次 目次 その前に おことわり Agent 2とは Agent 1と何が変わったのか 確認ポイント 確認用の構成 比較 Upstream:Agent導入とデバイスコネクター設定 Upstream:Agent導入とデバイスコネクター設定 - Agent 1 Upstream:Agent導入とデバイスコネクター設定 - Agent 2 Upstream:フィルタリング設定 Upstream:フィルタリング設定 - Agent 1 Upstream:フィルタリング設定 - Agent 2 Downstreamのセットアップ 遠隔指示:Agent 1 → Agent 1 遠隔指示:Agent 2 → Agent 2 遠隔指示:Agent 2 → Agent 1 遠隔指示:Agent 1 → Agent 2 まとめ Appendix:設定情報 コンテナ agent1up /root/manager.conf /root/logger.conf.mjpeg コンテナ agent2up intdash-agentd config show /etc/dc_conf/jpeg-up.yml /etc/dc_conf/h264-up.yml コンテナ agent1down /root/manager.conf コンテナ agent2down intdash-agentd config show その前に おことわり これはあくまで"やってみた"記事です。 正式な手順は各デベロッパーガイドをご参照ください。 Agent 2とは デベロッパーガイド によれば、以下のとおりです。 intdash Edge Agent 2は、intdashサーバーとの間で時系列データの送受信を行うエージェントソフトウェアです。 エッジデバイス(Linux PC)にインストールして使用します。 intdash Edge Agent 2 エッジデバイスは、カメラやセンサから取得したデータをデバイスコネクター経由でAgentプロセスに流し込みます。 AgentはサーバーのAPIとストリームを張って、データをサーバーにUpstreamします。 また、エッジデバイスへの制御信号をサーバーからDownstreamしてデバイスコネクターに渡します。 Agent 1と何が変わったのか デバイスコネクターとのインタフェースはこれまでの通り、名前付きパイプである FIFOファイル です。 また、サーバーとの通信は iSCP v1 の後継であるiSCP v2を採用していますが、Agentで隠蔽されるため、利用者が違いを意識することはあまりありません。 なお、実装は開発効率のためにRustとGoを採用しています。 利用者目線で変わった点は機能の再編(分割・追加・名称変更)です。 intdash提供開始から増え続けてきた各種機能の位置付けをゼロベースで見直し、定義しなおしています。 intdash Edge Agent 顕著な変更点はこのようなところです。 設定管理はデーモンが行うようになった 設定情報の形式がJSONからYAMLに変わった(オプションでJSONも指定可能) 設定情報の項目立てが一新した デバイスコネクターをパイプラインとして定義するようになった UpstreamとDownstreamの区別が明確になった 設定周りが多いですね。Agent 1の設定ファイルはAgent 2ではそのまま使えません。 では、どのような設定手順になったのか、Agent 1とAgent 2で比較しながら見ていきましょう。 確認ポイント 典型的な利用ケース、またAgent 1→Agent 2の過渡期にあり得そうなパターンを想定して段階的にセットアップしていきます。 Upstreamのセットアップ Agent導入とデバイスコネクター設定 フィルタリング設定 Downstreamのセットアップ 遠隔指示:Agent 1 → Agent 1 遠隔指示:Agent 2 → Agent 2 遠隔指示:Agent 2 → Agent 1 遠隔指示:Agent 1 → Agent 2 確認用の構成 今回はAgent 1/2とUpstream/Downstreamそれぞれの手順を確認したいため、1台のホストコンピュータに4つのDockerコンテナを立てています。 エッジを4つ用意 比較 Upstream:Agent導入とデバイスコネクター設定 外部デバイスのわかりやすい例としてUSBカメラのUpstreamを設定します。 USBカメラはLogicoolのC920s Upstream:Agent導入とデバイスコネクター設定 - Agent 1 まずはAgent 1での設定方法のおさらいです。 構成はこのようになります。 Agent 1で映像をUpstream Dockerコンテナを作成します。 コンテナでデバイスを利用するため --privileged を指定 intdash Edge Agent デベロッパーガイドの 2.1 インストール を参考にインストールしていきます。 rootユーザーなのでsudoなしで エディタとカメラデバイスユーティリティもインストール Admin Console でエッジを作成します。 UUIDとクライアントシークレットをコピー intdash-edge-manager を起動するときの環境変数が多いので起動用シェルスクリプトを作っておきます。 FQDN・UUID・クライアントシークレットを設定 デフォルト設定で起動すると Edge Finder でUpstreamを確認できます。 Status情報がUpstreamされている 一旦Agentを停止し、カメラ映像のUpstream設定を追加していきます。 ユーティリティでカメラデバイスの設定を確認します。 15FPS・640x480になっている 対応しているカメラなら 、プリインストールされたデバイスコネクター(intdash-edge-logger)でAgentへのデータ連携が可能です。 デベロッパーガイドの 3.2.1 マネージャーの設定ファイル例(manager.conf) を参考にmanager.confとmjpeg設定ファイルを編集します。 mjpeg設定ファイルパス・チャンネル・解像度を設定 再度、起動用シェルスクリプトで起動。 引数の設定ファイルパスを変更 Edge FinderでJPEGのUpsteramが確認できました。 1秒に15枚受信 このあと別のコンテナでカメラデバイスを使うため、Agentを停止しておきます。 Upstream:Agent導入とデバイスコネクター設定 - Agent 2 では、いよいよAgent 2を導入してみます。 構成はこのようになります。 Agent 2で映像をUpstream Dockerコンテナを作成し、 intdash Edge Agent 2 デベロッパーガイド を参考に進めていきます。 Agent 1と同じよう流れ Agent 1と違ってデフォルトの設定ファイルがあるわけではありません。 実際にやって覚えるにはデベロッパーガイドの チュートリアル を進めるのがいいのですが、ここは比較のために映像のアップストリームを設定してみましょう。 なお、Dockerではsystemdでデーモンが自動起動しないため、 デーモンを手動で起動 します。 デーモン(intdash-agentd)を起動 Upstreamを設定します。カメラデバイスは設定レシピ集の 7.2. カメラからV4L2経由で取得したJPEGデータを送信する にそのままの手順があります。これを参考にします。 アップストリーム と デバイスコネクター を設定します。 Agent 1の manager.conf の loggers (mjpeg設定ファイルパス・チャンネル・解像度を設定したセクション)にあたる部分ですね。 iSCP v2にはチャンネル channel という概念はありません。しかしここでは、 互換ルール に沿ってiSCP v2のデータをiSCP v1のチャンネル 1 として扱えるようにするため、データ名称プリフィックス data_name_prefix に v1/1/ を指定します。また、Agent 1と同じくカメラデバイスにあわせて解像度・FPSを設定します。 解像度・FPSは環境変数でデバイスコネクターに渡る 続いてデバイスコネクターの パイプライン を設定します。Agent 1のmjpeg設定ファイルの部分にあたります。 Agent1では /opt/vm2m/sbin/intdash-edge-logger の中に隠蔽されていた、デバイス入力〜フォーマット変換〜FIFO出力の流れを定義します。Agent 2の付属デバイスコネクターの特長としてこのパイプラインの仕組みによりタスクの柔軟な定義が可能になっています。 入力→中間処理→出力 環境変数から解像度・FPSを取得 接続設定 を行います。Agent 1では intdash-edge-manager 起動時に環境変数で指定した部分です。このコンテナ用のUUIDとクライアントシークレットをAdmin Consoleで払い出し、設定します。 FQDN・UUID・クライアントシークレットを設定 最後に ストリーマーを起動 します。 パイプラインに含まれる print-log-filter のログが出力されます。 ログレベル は起動時に設定することができます。 デバイスコネクターへの入力データ量がわかる こちらもEdge Finderで確認 Agent 2の intdash-agentctl コマンドだと設定時にフォーマットエラーに気づくことができるため、セットアップ作業の効率が上がりそうです。 Upstream:フィルタリング設定 送信データ量を間引くフィルタリングの代表例として、一定時間に1データポイントに絞るサンプリングの違いを見てみます。 Agent 1/2ともにデバイスコネクターの出力に対して定義します。 Upstream:フィルタリング設定 - Agent 1 Agent 1では sampling フィルター で設定します。 サンプリング間隔の最初のデータポイントをパス manager.conf の manager.filters セクションを編集します。 1000ミリ秒間に1データポイントに絞る 起動用シェルスクリプトを実行すると間引きされているのを確認できます。 1秒に1枚受信 Upstream:フィルタリング設定 - Agent 2 Agent 2では samplingタイプのフィルター を設定します。 考え方は同じ はじめに、デバイスコネクターからのデータの行先を、 recoverable ではなく src_jpeg に変更します。ただし src_jpeg というストリームは存在しせんので、このあとサンプリングフィルターを経ても行先が src_jpeg のままになっているデータは破棄されることになります。 デバイスコネクターの入力元IDを変更 フィルターを定義します。 src_jpeg に対してサンプリングした結果を recoverable に出力します。 targetがフィルターの入力・change_toが出力 ストリーマーを起動すると間引きされているのを確認できます。 1秒に1枚受信 Agent 2のサンプリングはH.264形式に対応しています。確認してみましょう。 H.264は前フレームとの差分データによる動画圧縮規格のため、サンプリングするとリアルタイム再生はできません。JPEG以外にもサンプリングが効くことを確認するために実施しています。(遅延アップロードにより、全データポイントが回収されたあとは動画として再生が可能です。) まずはカメラデバイスの設定を変更します。FPSは15のままです。 解像度・フォーマットを変更 デバイスコネクターの設定を新たに設定します。 カメラデバイス設定を反映 H.264用のパイプライン設定ファイルを作成します。 MJPEGのときに5つだったエレメントが4つになっています。 id: 2 の h264-split-filter の出力は iscp-v2-compat-msg なので、 iscp-v2-compat-filter が不要なためです。 前処理の出力形式により必要なエレメントは異なる デバイスコネクターにあわせて、フィルターの入力元IDとデータ型名も変更します。 jpegをh264に変更 ストリーマーを起動するとEdge Finderで1秒間に1回の受信を確認できます。 H.264は画面下部がバイト表示 Downstreamのセットアップ ダウンストリームの典型例として、別のエッジの送信データをサーバー経由で受信します。 Agent 2同士のほか、Agent 1/2間での送受信の設定方法も確認してみたいと思います。 遠隔指示:Agent 1 → Agent 1 では、まずこれもAgent 1同士の手順を確認しておきます。 構成はこのようになります。 Agent 1からAgent 1にStringを送信 送信側の設定として先ほど作成したコンテナ agent1up にチャンネルを追加します。 デベロッパーガイド 4.1 独自のデバイスコネクターを使用するための設定 を参考に進めます。 デバイスコネクター起動なし 起動用シェルスクリプトでAgentを起動します。 手っ取り早く送信するため、別ターミナルで同コンテナに入り、FIFOファイルにpython3の struct.pack の結果をリダイレクトします。 python3 -c "import struct, sys, time; s, n = divmod(time.clock_gettime(time.CLOCK_MONOTONIC_RAW), 1); sys.stdout.buffer.write(struct.pack('<BBBBLLBBB7s8s', 1, 26, 0, 0, int(s), int(n * 1_000_000_000), 0x1d, 0, 7, b'command', b'message1'))" > /var/run/intdash/logger_002.tx フォーマットは 6.5 Agent とデバイスコネクターの間で使われる FIFO のデータフォーマット 、の6.5.1 共通ヘッダー、6.5.2 データタイプごとの固有部分に従っています。 タイムスタンプ(Time Sec、Time nano)は基準時刻以前だとAgentで受け付けないため、 time.clock_gettime(time.CLOCK_MONOTONIC_RAW) で現在時刻を取得・計算しています。 Time Sec以降のデータサイズであるLength(第3引数 26 )の計算が結構面倒ですね。 任意のメッセージをFIFOにリダイレクト Edge Finderでサーバーでの受信を確認します。 リダイレクトのたびに受信 次に受信側のエッジを構築します。Dockerでコンテナを作成して、送信側と同様にAgentをインストールします。 受信側では --privileged 不要 エディタもインストール 4.3 FIFO からの読み出し を参考にして manager.conf にDownstream設定を追加します。 "clients" の "type": "control" でこれがDownstreamであることを定義しています。 Downstreamの場合、送信元 EdgeのUUIDの設定が必要です。複数のエッジ(2つまで)を設定できる ctlr_ids が利用できます。 clientsとloggersに設定を追加 Admin Consoleで受信側エッジのUUIDを新たに払い出し、起動用シェルスクリプトを作成しておきます。 FQDN・UUID・クライアントシークレットを設定 送信側・受信側それぞれで起動用シェルスクリプトを起動し、別ターミナルで受信側に入り、FIFOファイルを cat コマンドで監視しておきます。送信側でさきほどのリダイレクトを再度実行します。 cat コマンドの結果で、送信側でリダイレクトしたアスキー文字項目(データID、データ)を確認できます。 od コマンドなどでバイトデータとして確認してもいいでしょう。 送信側のリダイレクトとほぼ同時に出力される 遠隔指示:Agent 2 → Agent 2 では、続いてAgent 2で同様の構成を設定してみます。 構成はこうです。 Agent 2からAgent 2にStringを送信 送信側の設定をコンテナ agent2up に追加します。 デベロッパーガイド 4.1. アップストリームの設定を作成/変更する を参考に進めます。 フィルタリングが適用されているカメラ映像とは別にストリームを新規作成します。また、デバイスコネクター設定も作成しますが、Agent 1と同様にリダイレクトでFIFOファイルに書き込むため、パイプラインは作成しません。 新ストリームとデバイスコネクター設定を作成 Agent 1では送信・受信のFIFO( logger_XXX.tx 、 logger_XXX.rx )をセットで定義していましたが、Agent 2では必要なデバイスコネクター設定に対して1つずつFIFOファイルを設定しています。 intdash-agentctl run でストリーマーを起動します。 別ターミナルでコンテナ agent2up に入り、FIFOファイルにpython3の struct.pack の結果をリダイレクトします。 python3 -c "import struct, sys, time; s, n = divmod(time.clock_gettime(time.CLOCK_MONOTONIC_RAW), 1); sys.stdout.buffer.write(struct.pack('<LLHHL6s7s8s', int(s), int(n * 1_000_000_000), 6, 7, 8, b'string', b'command', b'message1'))" > /var/run/intdash/uplink-command.fifo Agent 2ではフォーマットがAgent 1とは異なります。 5. intdash Edge Agent 2とデバイスコネクターの間で使われるFIFO用データフォーマット を参考にしています。複数項目のデータ長の合計項目がなくなったため、Agent 1よりバイト数指定が楽になりました。 リダイレクトのたびに受信 では、Agent 2でも受信側のエッジを構築します。Dockerでコンテナを作成して、送信側と同様にAgentをインストールします。 このくだりはもう慣れたもの Downstreamとデバイスコネクターを設定していきます。 Downstreamとデバイスコネクター設定 受信側エッジ agent2down をAdmin Consoleで払い出し、接続を設定します。 こちらも慣れたもの /etc/init.d/intdash-agentd start でストリーマーを起動します。 起動直後 送信側でもストリーマーを起動します。別ターミナルで受信側に入り、FIFOファイルを cat コマンドで監視しておきます。 送信側でさきほどのリダイレクトを再度実行します。 送信側のリダイレクトとほぼ同時に出力される Agent 2用のフォーマットで出力されているのがわかります。 遠隔指示:Agent 2 → Agent 1 次はAgent 1/2併用を想定した遠隔指示の設定を確認してみます。 Agent 1/2双方のデータを受け取れるように受信側に設定を追加します。まずはAgent 1から。 どこからどこに送信しているのかこんがらがってきますが構成はこちらです。 Agent 2からAgent 1にStringを送信 Agent 2には 4.3. iSCP v1と互換性を持たせるためのデータ名称 が用意されています。実は本記事はこれに則り、データ名称を v1/<チャンネル> で始めていますので、設定は最低限で済みます。 コンテナ agent1down の manager.conf の ctlr_ids に、コンテナ agent2up のUUIDを追加します。チャンネル/データ名称接頭辞、データID、データタイプは今回あわせてあるため、修正不要です。 送信側のUUIDを追加 コンテナ agent2up のストリーマー、コンテナ agent1down の起動用シェルスクリプトを起動し、 agent1down のFIFOを cat しておきます。 agent2up でFIFOにメッセージをリダイレクトします。 Agent 2から送られたデータが、Agent 1→Agent 1のときと同じく、Agent 1形式で出力されているのがわかります。 Agent 2のメッセージをAgent 1形式で出力 遠隔指示:Agent 1 → Agent 2 最後は、Agent 2の受信側にAgent 1の設定を追加します。 構成はこちらです。 Agent 1からAgent 2にStringを送信 コンテナ agent2down にDownstream設定を追加します。 Downstreamの src_edge_uuid として agent1up のUUIDを追加しています。 filters 配下に複数の送信側エッジを設定可能 コンテナ agent1up の起動用シェルスクリプト、コンテナ agent2down のストリーマーを起動し、 agent2down のFIFOを cat しておきます。 agent1up でFIFOにメッセージをリダイレクトします。 Agent 1のメッセージをAgent 2形式で出力 このように、Agent 2はフォーマットが違うAgent 1とも送受信ができるよう、互換性を備えています。 まとめ 長々とお付き合いありがとうございました。 Agent 1では、Agent起動とストリーム開始、UpstreamとDownstream、それにデバイスコネクター内の各処理が、一緒くたになっていて構築・運用しづらい面がありました。 Agent 2では、これらがきちんと意味合いごとに整理・分離され、個別の管理項目として再定義されたことで構造が理解しやすく、取り回ししやすくなりました。 今回はご紹介しきれませんでしたが、Agent 2には遅延アップロード(Agent 1の再送)などの機能があります。ぜひ実際にお使いいただき、intdashの低遅延性・操作性を体感いただければと思います。 また、Agent以外にもaptpodのプロダクトはブラッシュアップしていきますので、今後もお伝えしていきたいと思っています。 Appendix:設定情報 参考までに最終的な設定情報を掲載します。 Agent 2設定はデベロッパーガイド 12. 設定を書き出す/読み込む の出力結果です。 全体像を再掲 コンテナ agent1up /root/manager.conf { "manager": { "meas_root": "$APPDIR/intdash/meas", "meas_root_volatile": "$RUNDIR/intdash/meas", "rawdir": "$APPDIR/intdash/raw", "basetime": "$RUNDIR/intdash/basetime", "stat": "$RUNDIR/intdash/manager.stat", "logger_stat": "$RUNDIR/intdash/logger_%03hhu.stat", "process_stat": "$RUNDIR/intdash/process.stat", "intdash_stat": "$RUNDIR/intdash/intdash.stat", "network_stat": "$RUNDIR/intdash/network.stat", "system_stat": "$RUNDIR/intdash/system.stat", "wwan_stat": "$RUNDIR/intdash/wwan.stat", "workdirs": [ "$APPDIR/intdash/meas", "$RUNDIR/intdash" ], "filters": [ { "name": "sampling", "channel": "1", "target": "realtime", "setting": [ { "key": "rate", "value": "1000" } ] } ] }, "clients": [ { "protocol": "mod_websocket.v2", "type": "realtime", "my_token": "$TOKEN", "my_id": "$UUID", "my_secret": "$SECRET", "auth_path": "$APPDIR/intdash/.auth", "project_uuid": "", "connection": { "host": "$SERVER", "path": "/api/v1/ws/measurements" }, "fifo_rx": "$RUNDIR/intdash/client_%s.rx", "fifo_tx": "$RUNDIR/intdash/client_%s.tx", "path": "$SBINDIR/intdash-edge-client", "stat": "$RUNDIR/intdash/client_%s.stat", "fast_net_check_cmd":"$BINDIR/intdash-edge-networkd.sh -q -t" }, { "protocol": "mod_http", "type": "resend", "my_token": "$TOKEN", "my_id": "$UUID", "my_secret": "$SECRET", "project_uuid": "", "auth_path": "$APPDIR/intdash/.auth", "connection": { "host": "$SERVER", "path": "/api/v1/measurements" }, "fifo_rx": "$RUNDIR/intdash/client_%s.rx", "fifo_tx": "$RUNDIR/intdash/client_%s.tx", "path": "$SBINDIR/intdash-edge-client", "stat": "$RUNDIR/intdash/client_%s.stat", "fast_net_check_cmd":"$BINDIR/intdash-edge-networkd.sh -q -t" } ], "loggers": [ { "path": "", "connections": [ { "channel": 255, "fifo_rx": "$RUNDIR/intdash/logger_XXX.rx", "fifo_tx": "$RUNDIR/intdash/logger_XXX.tx" } ], "details": { "plugin": "status", "plugin_dir": "$LIBDIR/plugins", "plugin_arg": { "stintd": { "meas_root": "$RUNDIR/intdash/meas" }, "stsys": { "storage_dir": "/" } } } }, { "path": "/opt/vm2m/sbin/intdash-edge-logger", "conf": "/root/logger.conf.mjpeg", "connections": [ { "channel": 1, "fifo_rx": "$RUNDIR/intdash/logger_001.rx", "fifo_tx": "$RUNDIR/intdash/logger_001.tx" } ] }, { "connections": [ { "channel": 2, "fifo_rx": "$RUNDIR/intdash/logger_002.rx", "fifo_tx": "$RUNDIR/intdash/logger_002.tx" } ], "details": { "plugin": "fifo" } } ] } /root/logger.conf.mjpeg { "type": "mjpeg", "data_handler": { "path": "/dev/video0", "baudrate": 15, "camera_width": 640, "camera_height": 480, "camera_hwencodedelay_msec": 100 }, "manager_client": { "tx_path": "/var/run/intdash/logger_001.tx", "rx_path": "/var/run/intdash/logger_001.rx" }, "status": "/var/run/intdash/logger_001.stat", "basetime": "/var/run/intdash/basetime" } コンテナ agent2up intdash-agentd config show connection: server_url: https://xxx.intdash.jp project_uuid: 00000000-0000-0000-0000-000000000000 edge_uuid: 84db287d-d763-4b40-a9a2-2d2824a8b803 client_secret: xxx transport: protocol: websocket upstream: - id: recoverable enabled: true recover: true persist: true qos: unreliable flush_policy: interval flush_interval: 5 - id: recoverable2 enabled: true recover: true persist: true qos: unreliable flush_policy: interval flush_interval: 5 downstream: [] device_connectors_upstream: - id: h264 data_name_prefix: v1/1/ dest_ids: - src_h264 enabled: true format: iscp-v2-compat ipc: type: fifo path: /var/run/intdash/h264.fifo launch: cmd: device-connector-intdash args: - --config - /etc/dc_conf/h264-up.yml environment: - DC_V4L2_SRC_CONF_PATH=/dev/video0 - DC_V4L2_SRC_WIDTH=1920 - DC_V4L2_SRC_HEIGHT=1080 - DC_V4L2_SRC_FPS=15 - DC_PRINT_LOG_FILTER_CONF_TAG=h264 - DC_FILE_SINK_CONF_PATH=/var/run/intdash/h264.fifo - id: command data_name_prefix: v1/2 dest_ids: - recoverable2 enabled: true format: iscp-v2-compat ipc: type: fifo path: /var/run/intdash/uplink-command.fifo device_connectors_downstream: [] filters_upstream: - id: sampling enabled: true type: sampling target: dest_ids: - src_h264 interval_ms: 1000 name: "" src_id: "" type: h264 change_to: dest_id: recoverable filters_downstream: [] deferred_upload: priority: same_as_realtime limit_data_storage: true data_storage_capacity: 102400 /etc/dc_conf/jpeg-up.yml tasks: - id: 1 element: v4l2-src conf: path: $(DC_V4L2_SRC_CONF_PATH) type: jpeg width: $(DC_V4L2_SRC_WIDTH) height: $(DC_V4L2_SRC_HEIGHT) fps: $(DC_V4L2_SRC_FPS) - id: 2 element: jpeg-split-filter from: [ [1] ] - id: 3 element: iscp-v2-compat-filter from: [ [2] ] conf: timestamp: stamp: clock_id: CLOCK_MONOTONIC convert_rule: jpeg - id: 4 element: print-log-filter from: [ [3] ] conf: interval_ms: 10000 tag: $(DC_PRINT_LOG_FILTER_CONF_TAG) output: stderr - id: 5 element: file-sink from: [ [4] ] conf: flush_size: 100 path: $(DC_FILE_SINK_CONF_PATH) /etc/dc_conf/h264-up.yml tasks: - id: 1 element: v4l2-src conf: path: $(DC_V4L2_SRC_CONF_PATH) type: h264 width: $(DC_V4L2_SRC_WIDTH) height: $(DC_V4L2_SRC_HEIGHT) fps: $(DC_V4L2_SRC_FPS) - id: 2 element: h264-split-filter from: [ [1] ] conf: clock_id: CLOCK_MONOTONIC - id: 3 element: print-log-filter from: [ [2] ] conf: interval_ms: 10000 tag: $(DC_PRINT_LOG_FILTER_CONF_TAG) output: stderr - id: 4 element: file-sink from: [ [3] ] conf: flush_size: 100 path: $(DC_FILE_SINK_CONF_PATH) コンテナ agent1down /root/manager.conf { "manager": { "meas_root": "$APPDIR/intdash/meas", "meas_root_volatile": "$RUNDIR/intdash/meas", "rawdir": "$APPDIR/intdash/raw", "basetime": "$RUNDIR/intdash/basetime", "stat": "$RUNDIR/intdash/manager.stat", "logger_stat": "$RUNDIR/intdash/logger_%03hhu.stat", "process_stat": "$RUNDIR/intdash/process.stat", "intdash_stat": "$RUNDIR/intdash/intdash.stat", "network_stat": "$RUNDIR/intdash/network.stat", "system_stat": "$RUNDIR/intdash/system.stat", "wwan_stat": "$RUNDIR/intdash/wwan.stat", "workdirs": [ "$APPDIR/intdash/meas", "$RUNDIR/intdash" ], "filters": [] }, "clients": [ { "protocol": "mod_websocket.v2", "type": "realtime", "my_token": "$TOKEN", "my_id": "$UUID", "my_secret": "$SECRET", "auth_path": "$APPDIR/intdash/.auth", "project_uuid": "", "connection": { "host": "$SERVER", "path": "/api/v1/ws/measurements" }, "fifo_rx": "$RUNDIR/intdash/client_%s.rx", "fifo_tx": "$RUNDIR/intdash/client_%s.tx", "path": "$SBINDIR/intdash-edge-client", "stat": "$RUNDIR/intdash/client_%s.stat", "fast_net_check_cmd":"$BINDIR/intdash-edge-networkd.sh -q -t" }, { "protocol": "mod_http", "type": "resend", "my_token": "$TOKEN", "my_id": "$UUID", "my_secret": "$SECRET", "project_uuid": "", "auth_path": "$APPDIR/intdash/.auth", "connection": { "host": "$SERVER", "path": "/api/v1/measurements" }, "fifo_rx": "$RUNDIR/intdash/client_%s.rx", "fifo_tx": "$RUNDIR/intdash/client_%s.tx", "path": "$SBINDIR/intdash-edge-client", "stat": "$RUNDIR/intdash/client_%s.stat", "fast_net_check_cmd":"$BINDIR/intdash-edge-networkd.sh -q -t" }, { "protocol": "mod_websocket.v2", "type": "control", "my_id": "$UUID", "my_secret": "$SECRET", "project_uuid": "", "auth_path": "$APPDIR/intdash/.auth", "connection": { "host": "$SERVER", "path": "/api/v1/ws/measurements" }, "fifo_rx": "$RUNDIR/intdash/client_%s.rx", "fifo_tx": "$RUNDIR/intdash/client_%s.tx", "path": "$SBINDIR/intdash-edge-client", "stat": "$RUNDIR/intdash/client_%s.stat", "down_dst_id": "00000000-0000-0000-0000-000000000000", "ctlr_ids": [ "e5e156b5-35f3-40ec-9993-8d6d812428c9", "84db287d-d763-4b40-a9a2-2d2824a8b803" ], "ctlr_flts":[ { "channel": 2, "dtype": 10, "ids": ["command"] } ] } ], "loggers": [ { "path": "", "connections": [ { "channel": 255, "fifo_rx": "$RUNDIR/intdash/logger_XXX.rx", "fifo_tx": "$RUNDIR/intdash/logger_XXX.tx" } ], "details": { "plugin": "status", "plugin_dir": "$LIBDIR/plugins", "plugin_arg": { "stintd": { "meas_root": "$RUNDIR/intdash/meas" }, "stsys": { "storage_dir": "/" } } } }, { "path": "", "connections": [ { "channel": 2, "channel_rx": -1, "receive_basetime": true, "fifo_rx": "$RUNDIR/intdash/logger_002.rx", "fifo_tx": "$RUNDIR/intdash/logger_002.tx" } ], "details": { "plugin": "fifo" } } ] } コンテナ agent2down intdash-agentd config show connection: server_url: https://xxx.intdash.jp project_uuid: 00000000-0000-0000-0000-000000000000 edge_uuid: 7e340e6a-ad9f-49d7-8e20-0694d906bbd8 client_secret: xxx transport: protocol: websocket upstream: [] downstream: - id: down enabled: true dest_ids: - src_command filters: - src_edge_uuid: 84db287d-d763-4b40-a9a2-2d2824a8b803 data_filters: - type: string name: v1/2/command - src_edge_uuid: e5e156b5-35f3-40ec-9993-8d6d812428c9 data_filters: - type: string name: v1/2/command device_connectors_upstream: [] device_connectors_downstream: - id: src_command enabled: true format: iscp-v2-compat ipc: type: fifo path: /var/run/intdash/downlink-command.fifo filters_upstream: [] filters_downstream: [] deferred_upload: priority: same_as_realtime limit_data_storage: true data_storage_capacity: 102400
Aptpod Advent Calendar 2022 23日目の記事です。(※土日休みにしているので最終日です) CTOの梶田です。 今年もまたあっという間(いつも言ってますね💦)でAdvent Calendar もなんとか走りきれそうです。 (昨年に引き続き継続するのは大変だなーと痛感していますが、なんとかみんな頑張った💪) 今年はAdvent Calendar も5年目となり、なんか新しいカタチにしようかどうか悩んだのですが、今年も例年通り、 1日目の神前の記事 でも触れられていますが。。。 1日目の記事抜粋 12月ですし、年末ネタとして(勝手に)定着させようとしているので2022年も 昨年 と同様に振り返ろうと思います! ではでは始めます。 (ちょっとタイトルの "また" が多いなw) はじめに MVV パートナー活動 Amazon販売 ソリューションパッケージ 2023年に向けて はじめに 2022年も昨年に引き続き、COVID-19は終息することなく、新しい働き方が標準になりつつあります。 (といってもTwitter社のようにリモートワークは終焉し、出社が強制みたいなところも出てきつつありますね💦) 2022年は、ロシアのウクライナ侵攻と関連する材料/資源不足、物価高(まだまだ高くなりそうですが。。)、為替変動、円安。。。と(他にもいろんなことありましたが) 社会の不安定感が増すなか、弊社としてもなかなか難しい局面は続き、攻めというよりはさらなる守り(投資の抑制、財務の健全化等々)へのシフト。。。 となかなか痺れる1年だったのですが、 5月、6月ぐらいにスタートアップに冬の時代がやってきたというのがちらほら出始めていたころ、、 SmartHR創業者の宮田さんの記事 blog.shojimiyata.com には、特に走り続けるチカラをもらいました💪 (社内でも "全員必読" みたいなかたちで少しだけ広まりましたw 😅) 中でも 変化に適応し続ける奴が一番強い というところと スタートアップがキーを打っている最中に死ぬことはめったにないのだ。だからキーを打ち続けよう! というところは、特に自分の中では心に留めています。 といったところで、 今年のトピックをいくつかピックアップして書いていきます。 MVV パートナー活動 Amazon販売 ソリューションパッケージ MVV 会社として、いわゆるMVV(ミッション・ビジョン・バリュー)を今年公開し、HP(ホームページ)を刷新しました。 youtu.be もともと内部的にはうっすらしてたものですが、言語化され公開されたことで意識しやすくなり、 また、バリューの浸透も含めての施策もいくつかされて、意識することも増えたのかなと感じてはいます。 (なかなか策定や公開までも紆余曲折ありつつ、まつわる施策についても試行錯誤の連続で。。。これだけの言葉だけで終わるのもなんともですが😓) パートナー活動 今年は特にこのパートナー各社様との協業、共創活動へのシフトを意識しました。 リリースとしても、 2022.05.30 アプトポッド、様々な分野のパートナーとの協業で産業DX支援を加速 を中心に各社様との活動をリリースさせていただきました。 2022.01.11 ax株式会社のAIソリューション「ailia」がintdashに対応 2022.02.02 アプトポッドとアクロクエストテクノロジー マルチモーダルデータによるAI/IoTソリューション提供で協業 2022.09.07 アプトポッドとオルフェ 動作分析ソリューション提供で協業 2022.10.20 アプトポッド、NECと5Gを活用したユースケースの創出に向けて連携 また、技術面においては、NTTコミュニケーションズ様やマクニカ様とも技術的な共創活動も今年から始めており、来年以降のどこかでお知らせできることを楽しみにしています。 マクニカ様においては、今回のAdvent Calendar2022の岩田の記事 tech.aptpod.co.jp でも触れられています MET2022(Macnica Exponential Technology 2022) というオンラインイベントにおいても弊社との取り組みをご紹介させていただいています。 内容は下記をご覧ください。 met.macnica.co.jp Amazon販売 ちょっと毛色の違うところで軽いものを。 新しい試みとして、こちらのリリースの通り、 2022.05.09 アプトポッド、推論や機械学習の実行環境に最適なエッジコンピュータ EDGEPLANT T1 を、Amazon で販売開始 昨年販売開始をした EDGEPLANT T1 を今年Amazonのプラットフォームで買えるようにしました。 www.amazon.co.jp こういうかたちで見えるとより身近な感じがしてよいですね! 買う敷居が下がり、こちらをきっかけに使っていただく機会が広がってきつつあるのは嬉しい限りです。 ソリューションパッケージ 今年の試みとして大きなもので最近発表しています 2022.12.06 アプトポッド、モビリティやロボットの群管理・遠隔制御の ソリューションフレームワークをベータリリース にありますようにintdashをバックエンドに使用したソリューションとして、最近新しいプロダクトをいくつか発表しました。 よりワークフローやユースケースに寄り添ったソリューションでお客様やパートナー様へ活用しやすくする狙いで進めています。 今回のAdvent Calendar 2022でも記事となっておりますので是非ご覧ください。 13日目:【intdash AUTOMOTIVE PRO REMOTE CAL】ECU遠隔適合システムのご紹介 tech.aptpod.co.jp 15日目:モビリティ管制制御システム向けソリューション「intdash CONTROL CENTER」を紹介します tech.aptpod.co.jp 2023年に向けて 2022年もまた期待の通りというわけではなく、むしろ大きな変化の荒波に対してどう対峙していくかといったところが試されたような気がしています。 やることすべてが必ずしもうまくいかず、パートナー様との共創活動も含め、なかなか難しいことも多かった年ではありましたが、少しづつ芽となっているものもあり、また製品としては進化しているところもたくさんあります。 2023年はさらなる広がりに向けて、お客様およびパートナー様との共創をさらに深く、広げていきたいと思っております。 何か自社の製品と連携できそうとかこんな困りごとがあるといったお客様やパートナー様は以下からお問い合わせいただけると幸いです。 aptpod,Inc. Contact aptpod,Inc. Contact for Partners 再掲になりますが、上記の宮田さんの記事の 変化に適応し続ける奴が一番強い というところと スタートアップがキーを打っている最中に死ぬことはめったにないのだ。だからキーを打ち続けよう! というところを意識しつつ2023年も走り続けていきたいと思っています💪 来年もまたアプトポッドにご期待ください!! メリークリスマス!🎄
aptpod Advent Calendar 2022 も、22日目になりました。本日は、ドキュメント担当の篠崎がお届けします。 私は、社内で1人だけの「ドキュメント担当」 *1 として、社外に公開するマニュアルや技術ドキュメントの制作を行っています。 ドキュメントは新製品・新機能のリリースに合わせて制作しますので、私は、新製品・新機能の開発担当者 *2 と常にコミュニケーションをとりながらリリースまでの作業を進めています。 そこで、この記事では、テクニカルコミュニケーターとしてのドキュメント担当が、製品開発担当者とどのようにコミュニケーションをとりながら仕事を進めているか、書いてみたいと思います。 *3 (なお、ここでご紹介するやり方は、弊社内で「このようなドキュメントだったらこのようなやり方をする」といういくつかのパターンのうちの1つです。すべてのドキュメントを同じ方法で制作しているわけではありません。) この記事で例にするドキュメント 制作の体制と流れ ドキュメントのキックオフミーティング 目次を作成して提案 開発担当者によるレビュー ライターはどこまで自分で悩むべきか 疑問点解決のためのミーティング おわりに この記事で例にするドキュメント この記事では実際の例として、最近公開した「intdash Edge Agent 2 デベロッパーガイド」( PDF版 および HTML版 )の制作を振り返りながら書いてみたいと思います。 「intdash Edge Agent 2 デベロッパーガイド」は、弊社ソフトウェア製品である「intdash Edge Agent 2」を活用いただくための、開発者向けガイドです。 本製品をLinux PCにインストールすると、そのPCはデータ伝送プラットフォーム intdash のクライアント(エッジ)として動作するようになります。 本製品は、従来からある同等の製品「intdash Edge Agent(末尾に2が付かない)」を使いやすくリニューアルしたものであるため、デベロッパーガイドも完全にリニューアルし、一から作ることにしました。 なお、ドキュメント制作に使用しているツールは Sphinx です。また、原稿データは社内GitLabリポジトリで管理しています。 制作の体制と流れ このドキュメントの制作には、主に以下の3名が携わりました。 ライター1名(私) 当該製品の開発担当者1名(ただし、これ以外の開発メンバーにも要所要所で助けてもらっています) プロダクト開発責任者(かつライターの上司でもある) また、スケジュールは、開発日程との関係、また、ライターの他の作業との関係から、以下のようになりました。 7月中旬:ドキュメントのキックオフミーティング 8月上旬:開発担当者の原案をもとにライターが作業開始 8月下旬:原案を整理し、ライターにて新しい目次を提案、OKをもらう 9月下旬:第1回レビュー(開発担当者およびプロダクト開発責任者がレビューする。以降、レビューを重ね、その都度修正する。) 12月上旬:第5回(最終)レビュー 12月中旬:公開 ライターは7月から12月までずっとこの作業をしているわけではなく、他のドキュメントの制作も同時に進めています。 レビュー日程は作業の進捗に応じてその都度設定する形としました。 ドキュメントのキックオフミーティング まず、7月中旬に今回のドキュメント制作に関するキックオフミーティングを行いました。 ここでは、開発担当者から「このようなドキュメントをつくってほしい」という要望をもらい、以下のことについて説明を受けました。 intdash Edge Agent 2とは何か(特に、既存製品との違い、ユーザー像) 開発スケジュールとドキュメント制作スケジュール ユーザーに説明しなければならないことの一覧 社内にある関連資料(設計関連のドキュメント、インストール用パッケージなど)のありか 今回の場合、このキックオフミーティングを受けて、上記の「ユーザーに説明しなければならないこと」は、開発担当者にて原案を書いてもらうよう依頼しました。 「誰が執筆工程を担当するか」については以下のように役割分担をしているのですが *4 、今回は、上から2番目の「開発者向け製品マニュアル」の方法を採用したということになります。 開発担当者とライターの役割分担 目次を作成して提案 8月上旬、予定通り、十分な情報がしっかりとつまった原案を開発担当者からもらいました。 原案を読み込み、以下のように大きく3部に分けて整理することにしました。 まず動かしてみるためのチュートリアル 目的に応じてやり方を参照するためのガイド 網羅的リファレンス(ここに、設定レシピ集も入れる) これは、これまでの別ドキュメントでの反省をふまえ、また、Divio Technologies社の The Documentation System などのベストプラクティスを参考にしたものです。 目次案 新しい目次について開発担当者やプロダクト開発責任者から承認を得られたら、実際にリライトおよび執筆に入っていきます。 開発担当者によるレビュー 8月下旬以降、説明対象のソフトウェアを実際に操作し、調査や実験をしながら、文章を書いていきます。今回は開発担当者が書いた原案があるので、原案を利用できるところは利用しながらリライト、原案がない部分は自分で一から書きます。 ある程度形になったら、開発担当者やプロダクト開発責任者にレビューしてもらいます。 このレビューは、技術的側面から正しい記述になっているかを確認してもらうのが主な目的です。 レビュー結果を書き込んでもらう方法としては以下の2つを使いました。 機能追加等により、まとまった修正が必要な時は社内GitLab上のマージリクエスト 細かい指摘はGoogleドライブ上のPDFにコメント テキストが主体のドキュメントであれば、細かい指摘もマージリクエストでやり取りをしますが、今回のドキュメントは図や表がたくさんあることから、PDFをGoogleドライブで共有し、そこにコメントをつけてもらう方法を使用しました。 基本的に、レビューコメントを付けてくれるのは開発担当者とプロダクト開発責任者ですが、必要に応じて関連する人がメンションされて呼び出され、議論に加わってくれるという形で進みました。 PDFでのレビュー(開発者がメンションされて呼ばれてきたところ) ライターはどこまで自分で悩むべきか 説明を書いていると、たびたび仕様についての疑問が生じるのですが、どのくらい悩んでから開発担当者に質問すべきか迷います。 私はだいたい、「もう行き詰まった」と思うところまで頑張って一人で悩むようにしています。同時に、「行き詰まった」と感じるところまでできるだけ早く行くように心がけています。 これは、社内のライターとして、自分で答えを探すために必要な材料が十分に与えられているためです。 今回の場合は、手元のDocker環境で、説明対象のソフトウェアを動作させ、実験をすることができました。 実験用のintdashサーバーも自由に使えるため、設定を変えて好きなだけデータの送受信を試してみることができます。 また、社内WikiやGoogleドライブに保存されている設計段階の多くの資料も見ることができます。 (逆に言うと、自分で実験できない場合や資料へのアクセスがない場合は、早く聞くしかないということになります。) 実験環境や社内資料など、情報へのアクセスが十分にあるところでしっかり一人で悩んでおくことは、無駄にはなりません。 一人で考えて行き詰まったとしても、開発担当者に質問するときには、最終的に行き詰まった地点を示し、なぜその道筋をたどったのかを添えて質問すると、開発担当者は返答をしやすくなる(はず)。 自分が行き詰まったということは、これからドキュメントを読むユーザーも同様に行き詰まる可能性が高い。その道筋を自分で体験していれば、それを避けるように説明ができる。 例を挙げてみます。以下は、なんらかの設定項目(ここでは設定項目Xとします)の機能について説明を書こうとして疑問が生じたケースです。ここでは、「このまま考えたら矛盾することが分かった」というのが「行き詰まり」であり、それをもとに質問しました: 設定項目Xの機能はAということであると考えました。 しかし、他に設定項目Yがあるので、Xの機能がAとするとXとYの設定が矛盾することになります。 もしかして、Xの機能はBでしょうか。 開発担当者の返答は、だいたい以下のいずれかになります: (例1)Xの機能はAという理解で正しいです。Yの機能は特別なケースのための設定で、... Aという理解で正しかったということで安心です。でも、悩んだ甲斐がありました。Xについて悩むことでXについて正確に理解しているので、「Xとは異なるY」をどのように説明すればよいか、見えてくるからです。 あるいは以下のような返答もありえます。 (例2)そうです、Xの機能は実はBなんです。ちょっと分かりにくいかもしれませんね、そもそもXがなぜ存在するかというと.... うーむ、Xの機能はAだと予想したのは間違いだったようです。でも、悩んだ甲斐がありました。自分がこのように予想したということは、ユーザーもそのように予想する可能性が高いからです。なぜ自分がそう予想したかを念頭に入れて、Xの「そもそも」のところを説明する必要がありそうです。それにより、Xの位置づけがスムーズに説明できるとよいです。 さらには、以下のような返答もあるかもしれません。 (例3)いいえ、Xの機能は、AでもBでもなく、Cです。どういうことかというと... 予想していなかった第3の答えでした。でも、悩んだ甲斐がありました。これまでAとBを念頭に置いて悩んできたわけですが、ここでも、「Aはでなく、Bでもない」ということがCを理解するための支えになります。 例2や例3のように理解や予想がしにくい機能は、説明を書くと長く複雑なものになってしまうことがあります。そんなとき、場合によっては、「こんなに説明が難しくなってしまうということは、この仕様は見直したほうがよいかも」「設定項目の名前を変えたほうがよいかも」という話になり、ドキュメント化がきっかけで仕様の見直しにまで進むことがあります。 こういうことができるのは、製品開発とドキュメントの制作が社内で緊密に連携しながら進んでいるからこそだと思います。 なかなか複雑なやりとりになってきました。PDFやマージリクエスト上のコメント上で会話を続けて解決すればよいですが、例2や例3のようなケースでは、詳細なコミュニケーションが必要になります。 そんなときは、ライターが主催して、疑問点を解決するためのミーティングをします。 疑問点解決のためのミーティング 疑問点解決のためのミーティングでは、ライターは聞きたいこと(時によって1個から20個ぐらい)を書いた資料を用意しておいて、ひとつひとつ開発担当者に聞きながら解決していきます。 今回のドキュメントでは、開発担当者と7~8回のミーティング(各回1時間ぐらい)をおこなったと思います。 通常、もっと小さなドキュメントや、既存ドキュメントの改版の場合はこんなに多くのミーティングはおこないませんが、前述のとおり、今回は一から新しく制作したため、頻繁におこないました。 *5 ちなみに、普段私はリモートワークをしているのですが、たまたまオフィスに出社した日に開発担当者も出社していて、「せっかくなのでマニュアルの疑問点を解決しましょう」ということになって、オフィスの片隅でミーティングをおこなったこともありました。 対面でミーティングをすると、マウスポインターではなく自分の指を使って「ここの説明が...」と指し示したり、手元の紙に簡単な絵を描いたりしながら話ができ、やはりはかどります。 以上のような工程を経て、最終レビューを通過したら、公開することができます。 ひと段落、ではありますが、ここから先も、「このことが書かれていない」「こう書いてほしい」といった要望をもらうことになると思います。終わりはありません。 おわりに どんなふうにドキュメントを作っているのか、今回は社内での開発者とのコミュニケーションに焦点をあてて、一端をご紹介してみました。 ドキュメントを作るテクニカルライターは、ドキュメントをただ「きれいに」してくれる人というわけではなくて *6 、もっといろんなところで役に立つことができるはず、と思っています。 テクニカルライティングはテクニカルコミュニケーションの一分野であり、今回は、社外の方々に対して「コミュニケーション」をするためのドキュメントを作ったわけですが、そのために社内でも、いわば仕込みの段階で、開発担当者と「テクニカルなコミュニケーション」を繰り返しています。 このような社内コミュニケーションの成果が、例えば上記のような「仕様自体を見直そう」という動きになったり、「ここのところは詳しく説明しよう」という話になったりして、社外にお届けする製品およびドキュメントの改善につながります。そのようなことをめざして、働いています。 *1 : 弊社のドキュメント担当の仕事については、以前 「ひとりドキュメント担当」の仕事 でもご紹介しました。 *2 : テクニカルライティング業界だと、ドキュメント制作におけるこの立ち位置はSME (Subject Matter Expert)と呼ばれます。 *3 : 実は、「私と同じようにドキュメントを内製されている方はどうされているのかな、どのようなやり方がよいのかな」といつも気になっています。「知りたいことがあるときは、まず自分のことを書いてみよう」と思ったのでした。 *4 : この表は以前LINE Technical Writing Meetup vol. 11で発表させていただいたときの スライド から流用しました。 *5 : 弊社内のコミュニケーションガイドラインでは、「翌営業日以降なら事前確認なしに空いているところにミーティングを入れてもよい」となっているので、「うーん、これは聞かないといけないな」となったら、翌日のGoogleカレンダーにポンとミーティングスケジュールを入れます。 *6 : テクニカルライターはドキュメントをきれいにしてくれるだけの人と思われてしまう件については こちら に興味深い記事があります。
本記事のタイトルはいわゆる「釣り」です。MQTTは、最近ではMQTT5がリリースされるなど現在でも進化を続けている、とても洗練された使いやすいプロトコルです(本記事にMQTTを貶める意図は一切ありません)。 弊社アプトポッドでは、 MQTTよりもターゲットを絞ったニッチな領域に向けた独自プロトコル “iSCP” を開発しております。本記事では、せっかく釣られてくださった皆様に、その “iSCP” の魅力について少しばかりご紹介できればと思います。 なお、本記事は aptpod Advent Calender 2022 の 21日目としてお送りします。 はじめに お久しぶりです。VPoPの岩田です。昨年1月末に QUIC DATAGRAMに関する記事 を書いてから、忙しさにかまけてテックブログ投稿をサボっていたら、なんと2年弱もの長い年月が過ぎ去っていました。これはイカンということで、重い腰を上げて久しぶりに記事を書いてみることにします。 肝心の記事の内容についてですが、実は先日12月5日、弊社の業務提携先で出資元でもある株式会社マクニカ様が開催された MET2022(Macnica Exponential Technology 2022) というオンラインイベントに、弊社CTOの梶田と一緒に登壇しましたので、そのときにお話しした内容を再構成してご紹介したいと思います。 met2022.macnica.co.jp 内容はズバリ 「弊社の独自開発プロトコル iSCP(intdash Stream Control Protocol)とはナニモノか」 になります。MET2022では、マクニカ様が企画・開発されているFMS(Fleet Management System、遠隔運行管理システム)についてのご紹介がメイントピックで、そのFMSを裏側から支えるテクノロジーという位置づけで弊社のiSCPについてもご紹介させていただきました。本記事ではその登壇のなかから、iSCPに関する部分のみを抜粋してご紹介いたします。 本記事では、以下の内容をご紹介します。 弊社ユースケースにおいてMQTTに不足していたポイント 弊社の独自プロトコルiSCP開発の経緯 弊社の独自プロトコルiSCPの特長 以下のような方には、なにかヒントになるかもしれません。 メッセージ配送ミドルウェアをどう選定したらよいのかわからない 大量・高頻度なデータの伝送がうまくいかなくて困っている MQTTが苦手とするユースケースについて知りたい はじめに そもそもintdashとは iSCPが必要とされる背景 intdash / iSCPの適用先 なぜMQTTを使わなかったのか 高頻度メッセージに対して低遅延性を実現できなかった 伝送効率化のために、結局 X over MQTT が必要になった データの確実な永続化に対応できなかった iSCPの特長 さいごに 2024/01/18 追記 MQTT5に関する連載始めました。ご興味お持ちいただけましたら、こちらも併せて覧ください。 tech.aptpod.co.jp そもそもintdashとは iSCPをご紹介する前に、まずはiSCP(intdash Stream Control Protocol)が頭に冠しているintdashがそもそも何者かについてご説明しなくてはなりません。 intdashは、弊社が開発している産業用IoTプラットフォームです (プラットフォームの名称であり、プラットフォームを構築するためのミドルウェア製品の名称でもあります)。 自動車や自律ロボットなどの高機能マシンを主にターゲットとして 、それらが吐き出す大量かつ高頻度なIoTデータを、インターネットやLTE網などを利用してクラウドに集めたり、遠隔地に中継したりすることができます。intdashを用いることで、様々なIoTデバイスや高機能マシンをコネクテッド化し、相互に通信させることが可能になります。 産業用IoTプラットフォームintdash intdashが持つ主な特徴は以下の3つです。 【データの伝送】IoTデバイス間をリアルタイム伝送でつなぐ 【データの保存】伝送されたデータはクラウドに蓄積する 【データの活用】蓄積されたデータにアクセスするAPIを提供する 1つめのintdashのリアルタイム伝送機能の実現のために、 intdashのサーバーとクライアントの間で使用されるプロトコルが、本記事のメイントピックであるiSCP(intdash Stream Control Protocol) になります。 iSCPが必要とされる背景 前述のとおり intdash / iSCPは自動車や自律ロボットなどの “高機能マシン” のコネクテッド化を主にターゲットとしています 。このようなマシンでは、高機能であるが故に内部のバス上で大量のデータが飛び交っていますが、 大量のデータに対してはデバイス側で集約・抽出処理を行い、サマリデータのみをクラウドに送信するアプローチを取ることが一般的です 。 これは、大量のローデータ(生データ)をそのまま送信する方法では、消費帯域が多く回線費用がかさんだり、そもそもLTE回線では帯域が足りなかったり、デバイスの性能が送信処理に耐えきれなかったりと、様々な問題が発生するためです。 一方で、弊社が長らく支援させていただいている自動車の研究開発分野など、 ニッチではあるものの一部のケースにおいて、このような事前処理のアプローチが取りづらい領域があることも分かっています 。intdashは、試作車両のテストや各種車両からのデータ取りなどでご利用いただくことが多くありますが、 これらのお客様にとっては、ローデータこそが取得したいデータであって、集約されてしまったサマリデータでは意味が無いからです 。 それでもやっぱりローデータがほしい ものづくり大国日本における ”ものをつくる側” の皆様のデジタルトランスフォーメーションをお手伝いするため、ものづくりにおいて不可欠な "計測器"をそのままクラウド上に移動させてしまうもの だと捉えていただくのが最もイメージに近いでしょうか。このようなユースケースにおいて、大量・高頻度なローデータの収集や伝送を実現するため、以下のような目的を持って開発されたプロトコルがiSCPになります。 伝送の低遅延化 : すばやいトライアンドエラーを実現するため、リアルタイムに状態が把握できることは大きなメリットとなります 伝送効率の向上 : 大量のデータからなるべく冗長性を排することで、モバイル回線の細い帯域を有効活用します 保存データの高信頼化 : データ欠損なく保存しきることをプロトコルレベルで保証することで、安心して収集データを活用できます 多様なデータへの対応 : 多様なデータを統一的に扱える仕組みとすることで、様々な試行錯誤に柔軟に対応できます 弊社の主力商品であるWebベースの可視化ダッシュボード 「Visual M2M Data Visualizer」 も、iSCPを使用して実現しているプロダクトのひとつです。 自動車などのマシン側から打ち上げられた大量データをWebアプリケーションで受け取り、ブラウザ上のダッシュボードで可視化するツールですが、 マシンからブラウザまでデータを届ける際のプロトコルとしてiSCPを使用しており、打ち上げられるデータが大量になってもブラウザでしっかり可視化することができます。 www.youtube.com intdash / iSCPの適用先 ちなみに、intdashの適用領域は前述した研究開発領域のみにとどまりません。たとえば最近では、デリバリーロボットをはじめとするAGV/UGVの監視などにおいて、 「普段はサマリデータだけで良いけれども、事故などの問題事象が発生した場合にはすべてのローデータをかき集めてすばやく状況把握や原因解析を行いたい」 といった要望をいただくケースが出てきています。 このように、IoTのコモディティ化に伴って、ニッチな研究開発領域だけでなく一般のIoTサービスにおいても 「いざというときのために」すべてのローデータをリアルタイム伝送できるケイパビリティを備えておきたい、という志向が生まれつつある ように感じています。 また、AGV/UGVなどのユースケースでは、ロボットが自律的に対処できない場面に直面した場合のために遠隔操縦機能を備えておくと安心ですが、 遠隔操縦などを行う場合にも高頻度データの低遅延伝送は効果を発揮します 。現状、遠隔操縦はまだそこまで広く社会実装されている状況ではありませんが、今後自律ロボットの普及に伴って、ロボット管理プラットフォームやそれに付随する遠隔操縦機能の需要も高まってくるのではないかと考えており、intdashはそのような領域にも適用可能です。 その他、intdashをバックエンドに使用したソリューションとして、最近新しいプロダクトをいくつか発表しておりますので、よろしければこちらもご覧ください。 自動車業界向け ECU遠隔適合ソリューション「Automotive Pro Remote CAL」 tech.aptpod.co.jp モビリティ・ロボットの管制制御ソリューション「intdash Control Center」 tech.aptpod.co.jp もちろんintdash自体は、データを伝送・蓄積・活用するための汎用的なプラットフォームになりますので、 これらの活用例に限らず、様々なサービスやソリューションのバックエンドとしてご活用いただけます 。 なぜMQTTを使わなかったのか ここからやっと本題に入ります。ここまで読み進めてくださった皆様がおそらくお持ちであろう 「IoTのリアルタイム伝送ならばMQTTがあるじゃないか、なぜそれを使わなかったんだ?」 という疑問にお答えします。 実は以前、弊社でもMQTTを使用してリアルタイム伝送機能を実現しようとしていたことがありました。しかしながら、MQTTでは、研究開発領域で求められる要件(リアルタイム性と確実なデータ永続化の両立)を実現することができず、泣く泣く使用を諦めたという過去があります。では、MQTTの何がいけなかったのか。 高頻度メッセージに対して低遅延性を実現できなかった MQTTは一般的に、エンドツーエンドで低遅延にデータを転送できるプロトコルとして知られています。これは、PubSub型のメッセージングパターンの採用と、軽量でシンプルなプロトコル仕様により実現されています。MQTTは確かに、 「あるクライアントから送出されたデータが別のクライアントに到達するまでの時間が短い」 という意味で、低遅延伝送を実現可能なプロトコルです。 しかしながら、このプロトコルを "高機能マシン" が吐き出す大量データの伝送に適用するとどうなるでしょうか。一般的に自動車が吐き出す車両データ(CANデータ)は、秒間数千フレーム〜1万フレームにもなります。例えば、この大量フレームをMQTTのメッセージにそれぞれ詰め込んで送信したとすると、 少なくとも開発当時のMQTTブローカーでは、すべてのメッセージを送りきれる程のスループットが出ませんでした 。 メッセージを送りきれないということは、各メッセージはその分滞留することになり、結果としてメッセージ配送に要する時間は増大します。要するに、メッセージ一つ一つの転送自体は低遅延に実現できるものの、大量のメッセージを送りつけるようなケースではメッセージの滞留によりリアルタイム性が損なわれてしまう、ということになります。さらに悲しいことに、 スループットの上限値は、QoS(メッセージの転送品質)の設定を上げるとさらに低下します 。 世の中には、MQTTブローカーのスループットを調査したベンチマーク結果も多くありますが、その多くは、 複数のクライアントから同時にデータ送信を試行することで、クライアント全体として数万メッセージのスループットが出ることを確認するもの です。クライアント数が増えるケースについては、サーバーをクラスタリングして水平スケールにより対応することもできますが、我々が対峙している1台単体で数千〜数万のメッセージを生成してしまうようなケースでは、単にサーバー台数を増やせば解決というわけにはいきません。 このようなケースに耐えうるMQTTブローカーは、少なくとも企画当初は世の中に存在せず、intdash / iSCP開発の大きなきっかけとなりました。 ※ MQTTの名誉のために若干のエクスキューズを入れておくと、 これはMQTTの性能が悪いと言っているわけではありません 。 MQTTは、1クライアントから受け取れるメッセージ数については弊社の要件を満たしませんでしたが、その代わりに水平スケールさせやすい仕様になっていると思っています。 一方で弊社のiSCPでは、1クライアントから受け取る大量メッセージを捌き切るためにステートフルなデータ保持の仕組みを敢えて導入したり、とにかく大量のデータを捌き切ることに仕様を全振りしています。 これは、あくまで対象とするユースケースの違い・プロダクトの思想の違いであって、どちらが良い悪いというものではありません 。 ユースケースによっては、よりMQTTが適している場合もあれば、iSCPが適している場合もあり、適材適所でプロダクトを選択していけばよいだけのことです。 それぞれ向いているユースケースが違う 伝送効率化のために、結局 X over MQTT が必要になった 前のセクションを読まれた皆様の中には、 「1データずつ1メッセージで送信するからメッセージ数が膨大になるのであって、複数メッセージをまとめて送ればよいのではないか」 と気づいた方もいらっしゃると思います。そのとおりです。あくまでメッセージ数が多すぎることが原因なので、複数データをまとめて大きめなメッセージにしてからバルク送信すれば、スループット不足の問題はある程度回避することができます。一見、この方法で問題は解決できるように思えますが、これはまた別の問題を引き起こします。 バルク送信を採用するということは、MQTTのペイロードへのデータの格納方法として所定のフォーマットを定義するということです。これは、 MQTTの上層にさらに別のプロトコルを定義することに相当します(X over MQTT) 。このアプローチを取った場合、 各クライアントは MQTT のプロトコルに準拠しつつ、MQTT上に想定されているフォーマットに合わせた形式でMQTTのペイロードを構築して送信しなければなりません 。すなわち、そのプロトコルは下層にMQTTを採用してはいるものの、MQTTで定義されている仕様に従っただけのクライアントからは通信ができないことになります。 これはたとえば、HTTPは主にTCP上のプロトコル(= HTTP over TCP)ですが、HTTPサーバーとただのTCPクライアントで通信するには、クライアント側にさらにHTTPを解釈するための自前実装が必要になることと同じだと考えていただければ、分かりやすいでしょうか。 MQTTを下層に使用したとして、結局その上層に独自のプロトコルを定義するのであれば、下層はわざわざMQTTに縛られる必要はありません 。幸い、MQTTのプロトコル仕様は極めてシンプルで、MQTTブローカーにより提供される機能性の実装はそこまで複雑なものではないため、 MQTTに依存することによって課せられる制約と、独自にプロトコルを定義するコスト とを天秤にかけた結果、弊社では独自のプロトコルを開発することを選択しました。 どうせ作るするならすべて自前で作ってしまえ データの確実な永続化に対応できなかった 主にデータ収集用途で使用されることが多かったintdashでは、集めたデータの信頼性についても高い要件を課せられていました。 サーバーに送信されたデータは、取りこぼすこと無く確実にデータストアに保存しなければなりません 。しかしながら、この機能性を既存のMQTTブローカーを用いて実現しようとすると、アーキテクチャが複雑化してしまうという問題がありました。 もちろん、MQTTにもQoS(メッセージの転送品質)という考え方があり、 "伝送経路での欠損については" 検出することができます。一般的に言われていることですが、この "伝送経路での欠損については" の部分が注意を要するところで、 MQTTのQoS設定を上げたとしても、エンドツーエンドでの欠損については検出することができません 。 どういうことかというと、例えばパブリッシャーとサブスクライバーが存在した場合、検出ができるのはあくまで パブリッシャー〜ブローカー間 と ブローカー〜サブスクライバー間 それぞれの経路についてのみであって、例えば極端なケースでは、パブリッシャーからブローカーへ転送されたあと何らかのエラーによってデータが消失してしまうと、それをパブリッシャーは検出することができない、ということになります。 既存のMQTTブローカーを用いてリアルタイム機能およびデータの確実な永続化機能を実現しようとすると、データを永続化するクライアントをサブスクライバーとしてブローカーにぶら下げ、永続化サブスクライバーがデータストアへデータを保存することになりますが、このような形式では 送信クライアントからデータストアまでのエンドツーエンド経路におけるデータ欠損の可能性を排除することができず、結局MQTT上で独自のプロトコルを定義しなければならなくなります (前のセクションでも登場した X over MQTT という形になります)。 片道伝送経路での到達確認しかできない 前のセクションでも言及したとおり、MQTTのプロトコル仕様自体は極めてシンプルで、同様のものをイチから考案することもできなくはありません。 MQTT上に独自プロトコルをスタッキングするくらいなら、はじめから独自のプロトコルを作ってしまったほうが柔軟でシンプルなものができあがるだろう ということで、さらに独自プロトコルの開発に踏み切る機運が高まりました。 もちろん世の中には、「プロトコル自体はMQTTを採用し、MQTTの標準仕様には無い機能性を追加した独自ブローカーを作る」というアプローチを取っている商用MQTTブローカーも存在します(このようなブローカーは、intdashの競合ということになります)。このようなアプローチを取るメリットは、一般のMQTTのライブラリやツール群を流用できることにあります。しかし、それと引き換えに、 MQTT標準仕様の範囲から逸脱しない範囲でしか機能を拡張できない、MQTTの仕様改訂への追従など自社でコントロールできない仕様変更リスクを抱える、などのデメリットもプロダクトに内包させる ことになります。 弊社としては、MQTT標準仕様の範囲だけでは実現できない機能性を追加したかったこと、テックベンチャーとしてMQTTに競合するような新しいプロトコルの確立に挑戦してみたかったことなども含め、メリット・デメリットだけでなく開発メンバーの思いやビジネス的な思惑等、様々なことを考慮して総合的に判断した結果、iSCPという独自プロトコルを開発することを選びました。 iSCPの特長 ここまで説明したMQTTを採用するにあたっての課題に対して、X over MQTT から派生して、MQTT部分も含めてすべてオリジナルなプロトコルスタックにより定義したものがiSCPです。 さらに、MQTTのようなPubSub部分も含めて独自で定義したため、MQTTにはない機能性もいくつか追加することができました。 iSCPの特長には様々なものがありますが、特徴的なものだけを拾い上げると、まずは大量・高頻度なデータを効率よく伝送できるように以下の特長を持っています。 これらの特長により、MQTTでは難しかった大量・高頻度なデータの伝送処理を実現しています。 複数データをまとめてバルク送信(もちろんバルクサイズは調整可能) メタ情報をあえてステートフルに保持することで、通信オーバーヘッドを削減 WebSocketを参考にしたメッセージ圧縮方式の採用 また、主に研究開発にて要求されるリアルタイム性と確実な永続化の両立のため、以下の特長も備えています。 ブローカーはデータを受信したら最優先で転送(永続化処理はあと回し) クライアントへのAckは永続化処理が完了してから返却 Ackにより永続化確認ができないデータは別途あとから永続化 クライアントへのAck返却タイミングが永続化処理完了後となっている点がiSCPの特徴的な部分です 。多くのプロトコルではAckは通信経路での到達確認や順序保証に使われるため、ある程度のAckが返却されない場合にはAck待ちにより送信が停止してしまいますが、iSCPにおいてはサーバーへデータが永続化されたかどうかの確認に用いられるものであるため、Ackの返却は必ずしも待つ必要がありません。 大量にデータを送りつけ、欠損があった場合には検出だけしておき、帯域に余裕があるときに改めて欠損部分だけを永続化処理する、というのが iSCP の基本の考え方になります 。 intdash / iSCPでの処理の流れ このような仕様により、 伝送時にはリアルタイム性を最優先に転送を行いつつ、後からではあるものの取りこぼすことなくデータを回収できる ようになっています。 このような機能性は、弊社でも実績の多い研究開発におけるデータ収集のユースケース(データを可視化しながらトライアンドエラーを行い、最終的にはすべてのデータを収集し切りたい)と極めて相性がよいものです 。もちろんそれだけでなく、たとえば遠隔管制・フリート監視のようなユースケースでは監視時にはリアルタイム性が、事故発生時の解析等でにはデータの信頼性が重要なファクターとなるなど、研究開発以外のユースケースにおいても効果を発揮します。 また、最近では遠隔管制に関連して、ロボットに対する遠隔操縦に対する要望もいただくようになってきています。 このようなケースでは、データの詰まりによってリアルタイム性の失われやすいストリームベースの通信方式よりも、データグラムベースの通信方式が好まれる傾向があります。 このような要求にも応えられるようiSCPは現在も日々進化を続けており、iSCPのメジャーバージョンアップに向けて現在準備を進行しております。 メジャーバージョンアップ前の現行バージョンでは、下層に使用するトランスポートプロトコルとしてWebSocketしか選択できませんでしたが、 メジャーバージョンアップ後のバージョンでは、 データグラムベースの通信方式に対するサポートが追加され、 WebSocketに加えて最新のトランスポートプロトコルであるQUICやWebTransportも使用可能となる予定です 。 さいごに いかがでしたでしょうか。 弊社がなぜMQTTを捨て独自プロトコルの開発に踏み切ったのか、また、その結果生まれたiSCPがどのようなプロトコルなのか 、この記事でお伝えできていれば幸いです。また、前述のMET2022にてご一緒させていただいたマクニカ様のFMS(Fleet Management System)のように、intdashやiSCPが持つ特長に少しでも興味や魅力を感じていただけましたら、ぜひとも皆様ご担当のシステムへの導入をご検討ください。 iSCP のクライアントライブラリ はオープンソース化していますので、どなたでも自由にご利用いただけます。また、 プロトコル仕様書 も公開可能なものを用意しておりますので、プロトコル仕様をよく精査して導入をご検討いただけます。 サーバーソフトウェア や弊社が運用する マネージドサービス は有償でのご提供となりますが、 フリートライアルのプラン もご用意しております。その他些細なことでも構いませんので、プロダクトに関するお問い合わせについては、 弊社営業までご連絡ください 。(私自身も、弊社プロダクトの開発責任者として全力でサポートさせていただきます) 結びとなりますが、アプトポッドではintdashやそれを取り巻く周辺プロダクトの販売だけでなく、intdashを活用したシステムインテグレーションや受託開発も行っております。当社が直接お手伝いをするだけでなく、当社が認定した信頼と実績のあるパートナー企業様にて、ご対応させていただくことも可能です。本記事でご紹介できなかった弊社のプロダクトやビジネス全般につきましては、弊社のコーポレートサイトをご覧ください。 「IoTシステムを構築したいがどんなアーキテクチャがよいのかわからない」「MQTTで構築した既存のIoTシステムがあるが限界を感じている」など、IoTシステム構築に関する一般的なご相談につきましても、お問い合わせいただければお力添えいたします。 www.aptpod.co.jp ※ 本記事をお読みいただき、アプトポッドのプロダクトやエンジニアリングに興味を持ってくださったエンジニアの方々からの連絡もお待ちしております。 まずはカジュアルな情報交換からでも構いません。会話をさせていただくなかで、募集中の職種をご紹介させていただきます。( 採用ページはこちら ) www.wantedly.com 最後までお読みいただき、ありがとうございました。 皆様よいクリスマスと年末をお過ごしください! 🎄🎍
aptpod Advent Calendar 2022 の20日目を担当します、intdash グループ フロントエンドエンジニアの佐藤です。 早速ですが、弊社では認可制御にOAuth 2.0 を採用しています。 tech.aptpod.co.jp ブラウザのアプリケーションでこの認可制御をする際、Express 等を使ったバックエンドがある場合が多いかと思います。 弊社でもNext.js を用いて、認証を管理するバックエンドサービス (BFF) のある構成をとっています。 このバックエンドがある場合のパターンは、Node.js のクライアント・ライブラリやExmaple も多く、それに従えばおおよその実装はできるのではないでしょうか。( oauth2-proxy が有名でしょうか。) バックエンドがある場合の方がセキュリティレベルは高く、一般的にこちらが採用されることが多いように思えます。 一方、バックエンドが無いアプリケーション、つまりブラウザ側 のみ で認証管理する方法は調べてもあまり有用な情報が出てこないことが多いです。 業務の中でブラウザ側のみで認証管理をする場合の実装が必要になり、実装方法について色々と調べましたので、その内容をご紹介します。 前提条件 実装方法 実装する処理の流れ 環境構築 code_verifier とstate を保存する 認可リクエスト先のURL を作成する 認証コードをアクセストークンへ交換する アクセストークンを保存する アクセストークンを利用してリソースを取得する 実装してみて 前提条件 Implicit Flow はセキュリティ上の懸念が伴うために使用しない PKCE に対応した Authorization Code Flow で認可リクエストを行う 実装方法 完成したコードの内容は以下のようになりました。 import { v4 as uuidv4 } from "uuid" ; import pkceChallenge , { generateChallenge } from "pkce-challenge" ; import Cookies from "js-cookie" ; import axios from "axios" ; import { AuthMeApi , MeasDataPointsApi , AuthOAuth2Api } from "../../intdash" ; // クライアント ID const CLIENT_ID = "XXXX-XXXX-XXXX-XXXX" ; // 認可先のホスト const AUTHORIZATION_HOST = "https://example.intdash.jp" ; // リダイレクトURI const REDIRECT_URI = "https://localhost:8443" ; // PKCE の設定 const { code_verifier } = pkceChallenge (); // state の作成 const state = uuidv4 (); (async () => { // アクセス時のURL の検証 const code = new URL ( window .location.href ) .searchParams. get( "code" ) ?? "" ; try { const authOAuth2Api = new AuthOAuth2Api ( { isJsonMime: () => true , basePath: ` ${ AUTHORIZATION_HOST } /api` , } ); const { data: { access_token , expires_in } , } = await authOAuth2Api.issueToken ( { grantType: "authorization_code" , code , clientId: CLIENT_ID , redirectUri: REDIRECT_URI , codeVerifier: Cookies. get( "code_verifier" ) ?? "" , } ); // アクセストークンを取得できた場合、PKCE とstate の値を削除する Cookies.remove ( "code_verifier" ); Cookies.remove ( "state" ); if (typeof access_token !== "undefined" ) { Cookies. set( "_bearer_token" , access_token , { ...options , expires: expires_in , } ); } const authMeApi = new AuthMeApi ( { isJsonMime: () => true , basePath: ` ${ AUTHORIZATION_HOST } /api` , } ); const { data: { name } , } = await authMeApi.getMe ( { withCredentials: true , } ); document .querySelector < HTMLDivElement > ( "#app" ) ! .innerHTML = `<p>Hello ${ name } </p>` ; } catch ( error ) { Cookies. set( "code_verifier" , code_verifier , options ); Cookies. set( "state" , state , options ); const requestURL = new URL ( ` ${ AUTHORIZATION_HOST } /api/auth/oauth2/authorization` ); requestURL.searchParams. set( "client_id" , CLIENT_ID ); requestURL.searchParams. set( "response_type" , "code" ); requestURL.searchParams. set( "redirect_uri" , REDIRECT_URI ); requestURL.searchParams. set( "state" , Cookies. get( "state" ) ?? "" ); requestURL.searchParams. set( "code_challenge" , generateChallenge ( Cookies. get( "code_verifier" ) ?? "" ) ); requestURL.searchParams. set( "code_challenge_method" , "S256" ); document .querySelector < HTMLDivElement > ( "#app" ) ! .innerHTML = `<a href= ${ requestURL.href } >Connect Your Account</a>` ; } } )(); 各エンドポイントは OpenAPI Generator でドキュメントから生成したクライアントを通して、リソースを取得しています 実装する処理の流れ 以下のようなフローで認可を行い、エンドポイントから自分の名前を取得するSPA を実装していきます。 なお、薄灰色の箇所は認可サーバーの役割になるので本記事では触れません。 https://localhost:8443 にブラウザからアクセス 「Connect Your Account」のリンクをクリック https://example.intdash.jp へ認可リクエストを行う https://example.intdash.jp 上でユーザー名とパスワードを入れて認証 https://localhost:8443 へcode を発行 (URL のクエリパラメーターにセット) しリダイレクト https://localhost:8443 上でトークン交換をリクエストする 問題なくトークンが発行できたらCookie に_bearer_token として値をセット Axios で自分の名前を取得するエンドポイントからデータを取得 UI フロー図 環境構築 さくっと作りたかったので Vite を使ってみました。 HTTPS でlocalhost を起動したいのと、API のエンドポイントのホスト ( https://example.intdash.jp ) に対してProxy をしたいので vite.config.js を編集します。 import { defineConfig } from "vite" ; import fs from "fs" ; export default defineConfig( { server: { port: 8443, https: { key: fs.readFileSync( "./.key.pem" ), cert: fs.readFileSync( "./.cert.pem" ), } , proxy: { "/api" : { target: "https://example.intdash.jp" , changeOrigin: true , configure: (proxy, options) => {} , } , } , } , } ); 以下のコマンドを入力すると、 https://localhost:8443 でローカルサーバーが立ち上がります。 yarn dev これで、環境準備が整いました。 code_verifier とstate を保存する 認可リクエストをする前に code_verifier と state を適切なブラウザ API を使用して任意の場所に保存します。 以下の例では js-cookie を利用して Cookie に保存しています。 import { v4 as uuidv4 } from "uuid" ; import pkceChallenge , { generateChallenge } from "pkce-challenge" ; import Cookies from "js-cookie" ; // PKCE の設定 const { code_verifier } = pkceChallenge (); // state の作成 const state = uuidv4 (); Cookies. set( "code_verifier" , code_verifier , options ); Cookies. set( "state" , state , options ); 認可リクエスト先のURL を作成する 次に、認可リクエスト先の URL に以下をクエリパラメータとして追加します。 生成したURL をhref 属性に追加したa タグ を実装します。 ユーザーはこのa タグ をクリックすることで認可フローを開始します。 const requestURL = new URL ( ` ${ AUTHORIZATION_HOST } /api/auth/oauth2/authorization` ); requestURL.searchParams. set( "client_id" , CLIENT_ID ); requestURL.searchParams. set( "response_type" , "code" ); requestURL.searchParams. set( "redirect_uri" , REDIRECT_URI ); requestURL.searchParams. set( "state" , Cookies. get( "state" ) ?? "" ); requestURL.searchParams. set( "code_challenge" , generateChallenge ( Cookies. get( "code_verifier" ) ?? "" ) ); requestURL.searchParams. set( "code_challenge_method" , "S256" ); document .querySelector < HTMLDivElement > ( "#app" ) ! .innerHTML = `<a href= ${ requestURL.href } >Connect Your Account</a>` ; 認証コードをアクセストークンへ交換する 認可先で認証が承認されたら認証コードとともに指定されたリダイレクト URL にリダイレクトされます。 https://localhost:8443/?code=UeE7Adf6QxGDiKuKOngG0Gc9Nee3XhnxMnKYsNTqQ60.OJouZMWIrYDm6EYIpt7xbBMSYC6u7UouTCo30Yk-Uyk&remember_me=true&scope=add_any_edge_to_project%20admin%20anonymous%20authz%20config%3Ar%20config%3Arw%20edge%3Ar%20edge%3Arw%20group%3Ac%20group%3Al%20group%3Arw%20me%3Ar%20me%3Arw%20meas%3Ar%20meas%3Arw%20media%3Ar%20media%3Arw%20offline%20passwordpolicy%3Arw%20project%3Al%20project%3Arw%20projectedge%3Arw%20role%3Ar%20role%3Arw%20scope%3Arw%20screen%3Ar%20screen%3Arw%20sig%3Ar%20sig%3Arw%20stats%3Ar%20stream%3Ar%20stream%3Arw%20system%3Ar%20temporary%20user%3Ar%20user%3Arw%20v1_admin&state=0ebdee45-7178-4d86-8978-560bf49fa6e4 アクセストークンの認証コードを交換するために、トークンエンドポイントに対して POST リクエストを行います。 リクエストには次のパラメータが含まれます。 grant_type 値は authorization_code で固定されています code URL のクエリパラメータに含まれている code を使用します client_id redirect_uri 認可フローを開始したときと同じ値を使用します code_verifier 任意の場所に保存した code_verifier を使用します import { AuthOAuth2Api } from "./intdash" ; const authOAuth2Api = new AuthOAuth2Api ( { basePath: `https://example.intdash.jp/api` , } ); const { data: { access_token , expires_in } , } = await authOAuth2Api.issueToken ( { grantType: "authorization_code" , code , clientId: CLIENT_ID , redirectUri: "https://localhost:8443" , codeVerifier: Cookies. get( "code_verifier" ) ?? "" , } ); アクセストークンを取得した場合のサンプルデータです。 { " access_token ": " eyJhbGciOiJSUzI1NiIsImtpZCI6ImIyYjNkNTIwNzY0MDQ3MTAwMmY0ZWY4MjhjZjJlN2YyZmYwNDhkMzc0YzUwNGYyNTJiYmQ0ZTgwZWE4YzJhZGUiLCJ0eXAiOiJKV1QifQ.eyJzY3AiOlsiYWRkX2FueV9lZGdlX3RvX3Byb2plY3QiLCJhZG1pbiIsImFub255bW91cyIsImF1dGh6IiwiY29uZmlnOnIiLCJjb25maWc6cnciLCJlZGdlOnIiLCJlZGdlOnJ3IiwiZ3JvdXA6YyIsImdyb3VwOmwiLCJncm91cDpydyIsIm1lOnIiLCJtZTpydyIsIm1lYXM6ciIsIm1lYXM6cnciLCJtZWRpYTpyIiwibWVkaWE6cnciLCJvZmZsaW5lIiwicGFzc3dvcmRwb2xpY3k6cnciLCJwcm9qZWN0OmwiLCJwcm9qZWN0OnJ3IiwicHJvamVjdGVkZ2U6cnciLCJyb2xlOnIiLCJyb2xlOnJ3Iiwic2NvcGU6cnciLCJzY3JlZW46ciIsInNjcmVlbjpydyIsInNpZzpyIiwic2lnOnJ3Iiwic3RhdHM6ciIsInN0cmVhbTpyIiwic3RyZWFtOnJ3Iiwic3lzdGVtOnIiLCJ0ZW1wb3JhcnkiLCJ1c2VyOnIiLCJ1c2VyOnJ3IiwidjFfYWRtaW4iXSwidGVuIjowLCJleHAiOjE2NjY1OTAwOTAsImp0aSI6ImE3MjQ4ZTBjLTZjYzUtNDkyNS1hZTEyLTU0Mjk3ZDYyNjNiYiIsImlhdCI6MTY2NjU4NjQ5MCwiaXNzIjoiaHR0cHM6Ly9kZXYuaW50ZGFzaC5qcCIsInN1YiI6IjIwMGU0NTBlLTE4YzMtNGI1MS1hMzk2LWM4NmM5NjYxNjYxMiJ9.F6Obt776U0EupdVqKnCSN0fVX1xKzDXZNTOVVpTinWvwF60r4rooKA_X60N7Bu4y3p1V6g95DJFE25BFAsOZBNM0Pjv8yEFEevLP34kgCoydT80l5ODdgYK0M0k5O03-Cdnjd4_yKk2stoSmF2TMNEjWm47ho6XDVDapi41RddfYu7YUn5_NwQVKBUDHL1i5U1a5-wvcOD_42A9rw2_kxoExuYq3UWOg692ZcfaDdaTDNU_OxagjWSZ8_Lx44kQKdNLZu9tLJZI0DUtYSD43eTy1GusVnxVmKASNigYByPuYaXZU6rkEZV9NlHeTjchh73lvpUhOozjpTXfaaoLpcQ ", " expires_in ": 3599 , " refresh_token ": " EIe7ZiGH_USAAs-21En0NzbnxN3WTFPgmMX9UMDSCtE.jTW1O7yEypG_qkmPY1OT3l1mcsSntdZ9c5YwmFZd9RY ", " refresh_token_expires_in ": 2591999 , " scope ": " add_any_edge_to_project admin anonymous authz config:r config:rw edge:r edge:rw group:c group:l group:rw me:r me:rw meas:r meas:rw media:r media:rw offline passwordpolicy:rw project:l project:rw projectedge:rw role:r role:rw scope:rw screen:r screen:rw sig:r sig:rw stats:r stream:r stream:rw system:r temporary user:r user:rw v1_admin ", " token_type ": " bearer " } アクセストークンを保存する 適切なブラウザ API を使用して、アクセストークン(と、ある場合はリフレッシュトークン)を可能な限り安全に保存します。 以下の例では Cookie に保存しています。 Cookies. set( "_bearer_token" , access_token , { ...options , expires: expires_in , } ); アクセストークンを利用してリソースを取得する import { AuthMeApi } from "./intdash" ; const authMeApi = new AuthMeApi ( { basePath: `https://example.intdash.jp/api` , } ); const { data: { name } , } = await authMeApi.getMe ( { withCredentials: true , } ); document .querySelector < HTMLDivElement > ( "#app" ) ! .innerHTML = `<p>Hello ${ name } </p>` ; OAuth 2.0 で認証したのち、発行されたアクセストークンを使用してリソースが取得できました。 実装してみて アクセス時のURL の検証や、Cookie に格納した値の適切なタイミングでの削除などバックエンドがあるときとは異なる点が多くありました。 リクエストURL の生成やトークン交換はNode.js 上で動くクライアントライブラリ (PKCE に対応している client-oauth2 )があるので、そちらを使ったほうがコードがスッキリします。 例えば初回アクセス時やアクセストークンが交換できなかった際、認証先にリダイレクトをしたい場合はバックエンドだと以下のようなコードになります。 // 認証のためのインスタンスの作成 import ClientOAuth2 from "client-oauth2" ; const intdashAuth = new ClientOAuth2 ( { clientId: CLIENT_ID , accessTokenUri: ` ${ AUTHORIZATION_HOST } /api/auth/oauth2/token` , authorizationUri: ` ${ AUTHORIZATION_HOST } /api/auth/oauth2/authorization` , redirectUri: REDIRECT_URI , state , } ); const uri = intdashAuth.code.getUri ( { state , query: { code_challenge , code_challenge_method: "S256" , } , } ); res.redirect ( uri ); 結局、メリットはとくになかったですね。。。 バックエンドがどうしても用意できないときに、最終手段として使うくらいに考えたほうが良さそうです。
aptpod Advent Calendar 2022 の19日目を担当します、ソリューションアーキテクトの渡辺です。 ところで皆さん。 海外旅行に行くために航空機を利用したことがありますか。 その航空機の中でインターネットが当たり前のように利用できます。 それは何故でしょう? 海外旅行に行くために豪華客船を利用したことがありますか。 その豪華客船の中でもインターネットが当たり前のように利用できます。 それは何故でしょう? これらには「宇宙通信」という技術が用いられています。 この宇宙通信を intdash で試す機会がありましたので、宇宙通信の概要説明と共にその様子をレポートします。 宇宙通信とは 2種類の衛星通信 静止衛星を利用する 低軌道衛星を利用する intdash による宇宙通信 宇宙通信とは 宇宙空間を飛行する機体は正式には「宇宙機」と呼ばれます。 人工衛星、探査機、宇宙ステーションこれらすべて宇宙機です。 この宇宙機が行う電波通信のことを宇宙通信と呼び、特に人工衛星に搭載した中継器を用いて地上の2地点間の通信を行うことを「衛星通信」と呼びます。 2種類の衛星通信 衛星通信では人工衛星を通信の中継器として用いますが、利用する衛星によって大きく2種類に分類できます。 静止衛星を利用する 身近なものとしては、BS放送があります。 地上から静止衛星に対してTV映像を送信し、それを受信した静止衛星はそのTV映像を地上の広い範囲に向けて送信します。 静止衛星は高度36,000Kmにあり、地表の広い範囲をカバーします。 また、地上から見ると上空の固定した位置に静止しているため、常に通信を行えます。 【静止衛星のカバー範囲】 静止衛星は1機で地上の30%~40%をカバーできることから、静止衛星を4機使うと理論的には全世界をカバーする通信網を構築することが出来ます。 この方式でTDRS (Tracking and Data Relay Satellite)がNASAにより運用されており、8機の静止衛星が稼働しています。 【静止衛星による全世界カバー】 静止衛星通信のメリット 静止衛星には大出力の中継装置を搭載できるためブロードバンド通信が可能 広範囲に同報配信が出来るため放送用途に向いている 静止衛星通信のデメリット 衛星を赤道上空にしか配置できないため、北極・南極では利用出来ない 地上からの送信に大出力が必要となるため地上の送信装置を小型化できない 低軌道衛星を利用する 近年、本格的に利用出来る様になってきました。 主に大型の航空機や、外航船舶で利用されています。 衛星の高度が静止衛星の36,000Kmに対して800Km前後とかなり低く地上に近いところを飛んでいるため、カバーできる通信範囲が狭いです。 また、地上に対して秒速7Km(音速の20倍)以上という極超音速で移動しているため、1機の衛星は10分足らずで上空を通り過ぎてしまいます。 【低軌道衛星のカバー範囲】 このような低軌道衛星と1対1ではまともな通信は行えないので、多数の衛星を打ち上げて、上空を衛星で一杯にしてしまおう、というのが低軌道衛星を利用する場合の考え方です。 移動中にスマートフォンで通話をしているような場合、一つの基地局のカバー範囲から次の基地局のカバー範囲に人が移動しても通話を続けることが出来ます。 これをローミングと言いますが、低軌道衛星を利用する場合は基地局の方が超高速で移動していて次々とローミングを行っている状態、という訳です。 スペースX社の「スターリンク」サービスは何と2,000機を超える小型衛星を打ち上げて運用しています。 【低軌道衛星による全世界カバー】 低軌道衛星通信のメリット 地上の送受信装置を小型化できるため携帯電話としての利用も出来る 極軌道衛星を用いれば北極・南極も含めて地球上全てのエリアで利用できる 低軌道衛星通信のデメリット 低軌道衛星には大出力の中継装置を搭載出来ないため通信帯域が限られてしまう 多数の衛星が必要で低軌道衛星は運用寿命も短いためコストが高い intdash による宇宙通信 さて、話は変わって intdash による宇宙通信を行ってきた様子のレポートです。 冒頭で航空機で宇宙通信が利用されていることを書きましたが、今回の機会も将来、航空機で intdash を利用して頂くことを想定したものです。 そのためなんと当社製品 「EDGEPLANT T1」 を航空機に搭載して空に飛ばし、上空で宇宙通信(衛星通信)を行ってきました。 利用させて頂いたのは「イリジウム」という低軌道衛星を用いた衛星通信サービスです。 www.n-aviation.com イリジウムは66機の低軌道衛星を運用しています。 このイリジウムが計画された当初は77個の衛星を用いる事になっていたため、原子番号77の元素であるイリジウムがサービスの名称になっています。 このイリジウムという名前にピンときた方はかなりの宇宙マニアですね。 1991年に計画された後 衛星に反射する強い太陽光がUFO騒ぎを起こしたり 人類史上初の人工衛星同士の衝突事故を起こしたり で世を騒がしたあのイリジウムです。 一度は経営破綻して計画がとん挫しましたが、いつの間にか復活して当初計画していたサービスを見事に実現させていたのです。 この度、ナビコムアビエーション様のご協力で、同社が保有する小型飛行機にイリジウム地上局と 「EDGEPLANT T1」 を搭載して飛行試験を行って頂きました。 www.n-aviation.com 今回の飛行試験ではこの小型飛行機が飛びました。 ナビコムアビエーション様が所有している機体です。 二人乗りのシートの後ろに諸々の機材を搭載しました。 もちろん 「EDGEPLANT T1」 もここに搭載します。 そして無事に離陸。 周辺を飛行して地上をカメラで撮影し、撮影データをイリジウム回線で地上に送信する、というのが今回の飛行試験の目的です。 当社営業担当社員のK氏が撮影(カメラ持ち)係として搭乗し、2回飛行したのですが、とっても楽しかったらしいです(笑) こんな感じで無事に宇宙通信を intdash で試すことが出来ました。 このような小型航空機(モーターグライダー)で宇宙通信ができる技術が既にあります。 近い未来「空飛ぶ車」などもっと小型な航空機に intdash が導入されたら、世界中の空を intdash が飛ぶ日も近い???
aptpod Advent Calendar 2022 の16日目の担当は、開発本部ソリューションプロフェショナルGrの影山です。普段は組み込みソフト周辺の開発やインテグレーションを担当しています。 今日は、aptpodで取り組んでいる、ROSをインターネットに接続する技術について、これまでテックブログやデベロッパーズガイドで公開してきた情報だけでは分かりにくかった、導入の大まかなイメージをご紹介したいと思います。 本記事で思ったよりもROSxインターネットが簡単に実現できそう!と思って頂ければと思っています。 想定読者:ROSをインターネット経由で利用したい方、ロボットの遠隔管理、制御に興味のある方 ROSをインターネットにつなぐ技術 TurtleBot3をインターネット経由で制御してみる ステップ1 構成の検討 ステップ2 intdashの環境を導入 ステップ3 Edgeの作成 ステップ4 設定ファイルの書き換え intdash Edge(コントローラ側) intdash Edge(TurtleBot3側) intdash Bridge(コントローラ側) intdash Bridge(TurtleBot3側) ROS launch(コントローラ側、TurtleBot3側共通) ステップ5 動作確認 終わりに 参考情報 ROSをインターネットにつなぐ技術 実際の導入の紹介の前に、前提となる弊社のプロダクトについて簡単にご紹介します。 aptpodではリアルタイム時系列データの可視化、蓄積を実現するintdashをこれまで開発して、様々なお客様に提供してきました。intdashにROSを接続することで、二つのROS空間があたかも同じローカルネットワーク上に存在するように扱えるようにすることを目的として、intdashへの接続のためのintdash Bridgeとノードを開発しました。 intdashを利用したROSのインターネット接続 詳細は以下のエントリを見て頂くのが分かりやすいかと思います。 tech.aptpod.co.jp tech.aptpod.co.jp TurtleBot3をインターネット経由で制御してみる 本記事の細かい部分はそれぞれの弊社の デベロッパーズガイドやマニュアル を参照して頂くとして、作業全体の大きな流れをつかんでいただくことを第一の目標として説明していきたいと思います。 良くチュートリアルやデモで用いられる TurtleBot3 とTurtleBot3が対応しているROS1を例にとって説明していますが、弊社の製品は ROS2にも対応 しております。 ステップ1 構成の検討 TurtleBot3では、Raspberry Piを制御用のコンピュータとして利用しています。TurtleBot3のマニュアルに従ってセットアップすると、開発元で提供されているTurtleBot3制御関連のROSノードがインストールされて、ゲームコントローラなどを接続して走行を制御できるようになります。 コントローラの入力は標準のパッケージのjoyをインストールできていれば、joy_nodeからコントローラの操作像情報を含んだjoyトピックがpublishされ、それをTurtleBot3のノードが受信して動作します。 元となる構成 遠隔制御を実現しようとする場合、上記のような構成を以下のように2つに分解して、遠隔制御を実現するのが一番シンプルかと思います。 intdash bridge nodeとintdash Edgeをセットで対象のデバイスにインストールすることで、ROSをintdash Serverに接続できるようになります。 intdash bridgeではROSのトピックをintdashの通信仕様に合わせて変換して、intdash Edgeを経由して、intdash Serverと送受信できるような機能を提供しています。 intdash bridgeを用いることで、joy_nodeとTurtleBot3関連ノード観点では、2つのROSの空間が透過的に繋がっているように見えるようになります。 目標とする構成 以降のステップではこの構成を実現するために必要なステップを説明していきます。 ステップ2 intdashの環境を導入 intdash Edge *1 とintdash Bridgeはそれぞれパッケージが公開されているのでLinux環境 *2 であれば簡単にインストールできます。 intdash Edge(intdash Edge Agent)のインストール( 詳細 ) sudo apt-get install intdash-edge intdash Bridgeのインストール( 詳細 ) sudo apt-get install ros-noetic-intdash-bridge  (ROS1:Noeticの場合) ステップ3 Edgeの作成 intdashではEdgeの管理や、アップロードされたデータの管理、可視化のために、 各種Webアプリケーション も提供しています。 Edge Admin Console画面のGUI操作で、intdashサーバ上で仮想的なEdgeを簡単に生成できます。 Edgeをサーバ上で作成したときの画面 Edgeの生成時には、各々のEdgeを識別するためのUUIDと、サーバ接続時に利用するシークレットIDのペアが発行されるので、それらのIDを手元に控えます ステップ4 設定ファイルの書き換え 作成したEdge情報を踏まえて、関連する設定ファイルを書き換えていきます。 設定ファイルの全体ではなく、ポイントとなる部分を抜粋して例を記載しています。 設定対象ファイルのパスは代表的なものを示していますが、運用環境に応じて自由に変更可能です。 intdash Edge(コントローラ側) 編集対象: /etc/opt/intdash/manager.conf 空欄の部分に接続先のintdashサーバのアドレス、EdgeのUUIDとシークレットIDを記入します。 以下のようなloggersにintdash Bridgeで使用するFIFOの設定を追記します。 "connections": [ { "fifo_tx": "/var/run/intdash/logger_001.tx", 注:intdash Edgeとintdash Bridgeの間の通信で使うFIFOを指定しています "fifo_rx": "/var/run/intdash/logger_001.rx", "channel": 1 } ], "details": { "plugin":"fifo", "plugin_dir": "$LIBDIR/plugins" } clientsのtype:realtimeに "dst_id": ["<TurtleBot3のEdge UUID>"] を記載する。 intdash Edge(TurtleBot3側) 編集対象: /etc/opt/intdash/manager.conf 空欄の部分に接続先のintdashサーバのアドレス、EdgeのUUIDとシークレットIDを記入します。 loggersにintdash Bridgeで使用するFIFOの設定を追記します(コントローラと同じく)。 clientsのtype:controlを追加して、以下のようなコントローラEdgeからサーバにアップロードされたデータを受信する設定を行います。 "ctlr_id": "<コントローラのEdge UUID>", "ctlr_flt_ids": [ "/joy"    注:joyトピックを受け取るという意味 ], "ctlr_ch": 1, "ctlr_dtype": 14 注:バイナリデータを受け取るという意味の設定 intdash Bridge(コントローラ側) 編集対象: /etc/opt/intdash/params.yaml サーバへ送信して他のEdgeと共有したいトピック名をここで指定します。 incoming: enabled: false # サーバからのデータは受信しない queue_size: 100 suffix: "" outgoing: enabled: true # サーバへデータを送信する max_array_size: 500 topics: - topic_name: "/joy" # アップロードしたいトピック名 send_mode: "raw" queue_size: 500 intdash Bridge(TurtleBot3側) 編集対象: /etc/opt/intdash/params.yaml サーバからの受信を有効にします。 incoming: enabled: true # サーバから来るデータをROSに送り出す queue_size: 100 suffix: "" outgoing: enabled: false # サーバにデータは送らない ROS launch(コントローラ側、TurtleBot3側共通) 既存のノードの起動設定に加えて、intdash Bridge のノードを起動する設定をlaunchファイルに追記します。 launchファイルの編集例 <arg name="paramsfile" default="/etc/opt/intdash/params.yaml" /> 注:前ステップで編集した設定ファイルをここで指定します <node pkg="intdash_bridge" name="intdash_bridge" type="intdash_bridge_node" output="screen" clear_params="true"> <param name="fifo_tx_raw" value="/var/run/intdash/logger_001.tx" /> 注:intdash Edgeの設定と合わせて、intdash Edgeとintdash Bridgeの間の通信で使うFIFOを指定しています <param name="fifo_rx_raw" value="/var/run/intdash/logger_001.rx" /> <rosparam command="load" file="$(arg paramsfile)" /> </node> ステップ5 動作確認 次のようなステップで起動させることで、動作を確認できます。 intdash Edgeの起動 パッケージと共にインストールされている /etc/systemd/system/intdash-edge.service をsystemctlで起動させます *3 。 ROS launchの実行 インターネットに接続した環境で、roslaunchコマンドを使い前のステップで設定した環境を起動させます。設定に問題なければ以下の動画のようにコントローラでの遠隔操作ができようになっているはずです。 youtu.be 終わりに 今日はaptpodのROSに関する取り組みをご紹介しました。いかがだったでしょうか? ネットワーク越えの設定は難しいように思われますが、intdashと組み合わせてステップを踏んで設定していくとで、意外と簡単にROSのネットワーク接続ができることが伝わっていると幸いです。 現在、aptpodでは、今日紹介したROSやその他の環境も想定してリアルタイムでインタラクティブな管制制御システムの迅速な構築を可能にするintdash CONTROL CENTERというソリューションフレームワークを開発しています。 昨日の記事 に詳細が書かれていますので、気になった方はそちらも合わせてご覧ください。 参考情報 aptpod,Inc CONTROL CENTER aptpod,Inc. Docs *1 : intdash Edgeの基本機能はintdash Edge Agentとして提供されています。今回は実績のあるバージョンを紹介していますが、最近新しいintdash Edge Agent2がリリースされたので、今後はそちらを利用していくようになる予定です *2 : AMD64アーキテクチャー上のLinux、Raspberry Pi 上のRaspbianなどをサポートしています *3 : manager.confの配置や、その他のパス設定を変えたい場合はserviceファイルを編集してください。
aptpod Advent Calendar 2022 の15日目を担当します、ソリューションアーキテクトの岩坪です。 今回の記事では当社が2022年12月にベータリリースしました、モビリティ・ロボットのフリート管理や遠隔監視、遠隔制御を実現するための 管制制御システム向けのソリューションフレームワークである「 intdash CONTROL CENTER 」 を紹介させて頂きます。intdash CONTROL CENTERを利用すると 低コスト・短期で、データ利活用が可能な、拡張性のあるシステム を構築することができます。 記事の後半にはintdash CONTROL CENTERを利用した管制制御システムを想定したユースケースのデモ動画も載せていますので、「何はともあれまずはどういうことができるの」という方は先に デモ動画 を見てみて下さい。 はじめに intdash CONTROL CENTER とは何? intdashを利用したデータ伝送プラットフォームの特長 intdash CONTROL CENTERで実現できること intdash CONTROL CENTERを使ったデモ紹介 おわりに はじめに aptpodのソリューションアーキテクトという役割は、お客様のデータ収集やデータ利活用における課題解決や、お客様業務のDX(デジタルトランスフォーメーション)実現に向けて、当社コアプロダクトである IoTデータ伝送プラットフォーム intdash をベースにソリューション提案を行い、お客様と共にプロジェクトを推進、発展させていくことをミッションとしています。 ソリューションアーキテクトってどんな仕事? - aptpod Tech Blog ここ数年は、様々なモビリティ・ロボット向けにintdashを活用頂き、 建設機械・重機・農機、配送ロボットや警備ロボットといったサービスロボット、工場や物流倉庫内のAGV(Automatic Guided Vehicle)・AMR(Autonomous Mobile Robot)等において、 遠隔監視、遠隔制御、フリート管理 を実現したいお客様も増えてきています。 そういった背景もあり、aptpodは様々なモビリティ・ロボットにおける遠隔監視・遠隔管理/フリート管理・遠隔制御向けのプロダクト企画、開発を進めており、 この度、2022年12月に管制制御システム向けのソリューションフレームワーク「intdash CONTROL CENTER」をベータリリースすることができました。 intdash CONTROL CENTER とは何? 今回紹介するintdash CONTROL CENTERは、 モビリティやロボット向けのリアルタイムかつインタラクティブな管制制御システムを迅速に構築 できるようにするための、ソリューションフレームワークです。 本ソリューションを活用頂くことで、ロボットや自動車、建機・重機といった複数のモビリティを対象に、遠隔からモビリティ群を監視・管理することができ、必要に応じて人の手による遠隔指示・操作の介入を行うことができるようになります。 こういった管制制御システムを構築し、運用していく為には、そこに至るまでに 要件定義や機能開発、検証(PoC)のために多大な開発コスト、期間が必要 になるため、システムを導入したいと考えていても、なかなか立ち上げに進められない方々が多いのが現実です。導入検討の初期段階からいきなり本番運用を見据えた全ての要件定義や運用方法を定めるということも現実的ではないため、小さなPoCのフェーズからはじめて徐々に要件を定めつつ、開発、検証のサイクルを回していく必要もあります。 intdash CONTROL CENTERはまさにこういった「管制制御システムを作っていきたいが、何からどう手を付けてよいのか、いきなり膨大な予算を取るのは難しい…。」と考えられている方にも適したソリューションです。本ソリューションの、 データ収集・データ保存・データ管理・データ可視化、といった基本機能をまずは活用頂くことで短期・低コストで初期フェーズのシステム構築を実現 します。検証を繰り返す中で、必要となった機能はあとから拡張開発することも可能なので、段階的に運用に向けたシステム構築を進めることができます。 intdash CONTROL CENTERの適用シナリオとしては、下記のようなものがあげられます。 工場や物流倉庫におけるAGVの運用監視・遠隔制御介入 建設現場における建設機械の運用監視・遠隔指示 スマートシティにおける自動運転モビリティの運用監視・遠隔指示 intdash CONTROL CENTERの適用シナリオ intdash CONTROL CENTERを利用頂くことで、個別開発の要素を減らし、ベースとなる機能の検証も減らすことができるので、 お客様の実現したいことに対して、お客様自身が注力すべき領域のみに集中 してシステム構築を進めることができるようになります。 intdashを利用したデータ伝送プラットフォームの特長 intdash CONTROL CENTERの説明の前に、まずは本ソリューションのベースとなる、当社のコアプロダクト intdash に関して概要を説明します。 intdashに関する詳細は、下記を参照下さい。 aptpod,Inc About intdash intdashでは自動車やロボット・産業機械や制御・可視化アプリケーションなど、短期間に大量のデータを発生させるデバイスをモバイル網やインターネット網を経由して相互にライブ接続することができます。intdashを流れるストリーミングデータはそのまま時系列データストアに保存され、Visual M2Mでの可視化やAnalytics Servicesでの計算処理や機械学習に利用することができます。 各種デバイスからのリアルタイムなデータ伝送と、時系列データとして様々なデータをサーバへ保存し、可視化をするといったデータ伝送プラットフォームの実現のために、当社からは以下のミドルウェアおよびアプリケーションを提供します。 サーバサイドミドルウェア: intdash Server エッジサイドミドルウェア: intdash Edge 時系列データの可視化アプリケーション: Visual M2M Data Visualizer 管理ユーティリティ: Edge Admin Console、Edge Finder、Meas Hub intdashを利用頂くことで、下記の特長を持つIoTデータ伝送プラットフォームを構築することができます。 短期間に大量のデータが発生するような 高頻度のデータ を扱うことができる 高いリアルタイム性 でデータ伝送ができる 伝送時にパケロスした データの完全回収 ができる 多種多様なデータに対して 時刻を同期してデータ管理 が行える サーバに保存された データを後から利活用 できる 上記の通り、intdashはクラウドなどのサーバに構築したintdash Serverにモビリティのデータをリアルタイムに保存し、データを管理・活用することができるものです。モビリティの機体やデータを管理するための、管制制御システムのようなモビリティ管理プラットフォームをサーバをハブとしたデータ伝送システムとして構築するのが望ましい理由としては、いくつかあげられます。 管理対象のモビリティに問題が発生した際に、問題発生時のモビリティのデータをエビデンスとしてあとから確認したい( 過去データの再生 ) 管理対象のモビリティのデータは様々な拠点から、複数の利用者が確認したい( 複数拠点からのアクセス ) 収集したモビリティのデータをただ貯めておく、可視化するだけでなく、データを利活用してDXを推進したい( データの利活用 ) こういったニーズがある場合は、 限定された拠点や環境においてのみ利用可能なデータとして管理するのではなく、intdashのようにクラウドなどのサーバをハブとしたシステムとして、モビリティのデータを伝送し、保存、管理 する必要が出てきます。intdashを利用頂くことで、これらのニーズに応える管制制御システムの構築が可能となり、これが本記事で紹介するintdash CONTROL CENTERで構築したシステムの特長にもなります。 intdash CONTROL CENTERで実現できること 改めて説明すると、intdash CONTROL CENTERはモビリティやロボットのリアルタイムかつインタラクティブな管制制御システムを迅速に構築できるようにするための、ソリューションフレームワークです。 intdash CONTROL CENTERは下記のコンポーネントで構成されます。 モビリティの機体データの送受信処理を行うエッジ側のソフトウェア データストリーミング中継処理やデータ保存を行うサーバ側のソフトウェア リアルタイムな群管理や個別機体の状態モニタを行えるWEBアプリケーション intdash CONTROL CENTERを構成するコンポーネント それぞれのソフトウェアコンポーネントを活用することで実現できるintdash CONTROL CENTERの機能と特長について説明します。 (1)リアルタイムなフリートマップマッピング 複数モビリティの位置情報や、モビリティに搭載されたカメラの映像などのデータをマップマッピングして可視化できる、WEBベースの統合監視環境をリファレンスアプリケーションとして提供します。 本アプリケーションを利用することで、離れたところから現場で稼働する複数のモビリティの稼働位置、稼働状況を確認することができます。 本アプリケーションは、以下のような開発に活用頂くことができます。 屋内シナリオにおける対象となるエリアのマップなどを画像データとして背景に表示したUI開発 屋外シナリオにおけるOpenStreetMapやGoogle Mapsなどを利用したUI開発 モビリティ個別やモビリティ群全体に対するコマンド送信による遠隔指示機能の実装 (2)モビリティの様々なリアルタイムデータを確認可能なダッシュボード モビリティの詳細データをリアルタイムにダッシュボードに表示して確認することができます。 制御データや映像データなど様々なデータをリアルタイムに表示することが可能であり、ノンプログラミングでユーザによる自由なダッシュボードの構成変更が可能です。 モビリティ毎の状態(ステータス)、速度、稼働率などの稼働状況や、バッテリー稼働のモビリティのSoC(State Of Charge)やSoH(State of Health)など、モビリティ管理に必要な詳細なデータを遠隔から監視できるようになります。 ダッシュボード上のVisual Partsを変更することで、対象となるデータの値を表示するだけでなく、時間変化に伴う稼働率状況の変化などをグラフ表示することもできます。 (3)モビリティを遠隔操縦するためのコントローラ接続と操作データ伝送 ゲームコントローラなどの様々な操作デバイスを接続するためのエッジデバイス用のコンポーネントを提供します。本コンポーネントを利用頂くことで、エッジデバイスに接続されたコントローラの操作情報を操作対象であるモビリティへ遠隔からリアルタイムにデータ伝送し、リアルタイムな遠隔操作・操縦を実現します。 倉庫や工場内などのモビリティはAMRのような自律走行やAGVのような磁気テープ上を無人走行するケースが多いですが、予期しない障害物が置かれてしまうなどして動作不能となるケースがあります。その場合に、モビリティの異常状態(動作不能)を検知して、一時的に遠隔からの人の手による操縦を介して復帰可能な位置まで移動させるような場合に、遠隔操縦が活用できます。 (4)ロボット/モビリティ、センサーからカメラまで様々なデバイスの接続 ロボットや自動車などのモビリティ、またモビリティ上に搭載されるセンサーなどの様々なデバイスを接続して、モビリティのデータ収集するための、エッジデバイス用のコンポーネントを提供します。本コンポーネントは、エッジデバイス側のソフトウェアコンポーネントである「Device Connector」として提供します。 Device Connectorはターゲットとなるデータデバイス(モビリティ自体、センサー、カメラなど)からデータを取得して、intdash Serverにデータ送信を行う「intdash Edge Agent」にデータを受け渡す機能を持ちます。 Device Connectorを利用することで、下記のような様々な形式のデータをフュージョンストリーミングでintdash Serverへ送信することが可能です。 ロボットにおけるROS1/ROS2のメッセージ モビリティにおけるCAN(Control Area Network) 汎用センサー、ビデオなどのセンサーデバイス (5)データの収集・保存と利活用 モビリティから収集されたすべてのデータはサーバに永続化されるため、運用時のデータは過去データを再生することで当時の状況を詳細まで確認することが可能です。 これにより、異常発生時には、関係者によるデータレビューもすぐに行うことができます。これは国内外など関係者が様々な拠点にいる場合でも同様で、同じデータに各拠点からアクセスしてデータ内容を確認することができます。 また、サーバに保存されたデータを活用することで、詳細なデータ解析フローを実現することもできます。運用時に複数のモビリティのデータを都度、人の手により確認して、解析することは現実的ではないので自動化された解析フローを構築することで、効率的な管制制御システムの運用を行うことができます。 (6)豊富なSDK・APIを利用した拡張開発 intdash CONTROL CENTERでは、用意されたSDK、APIを利用することでリアルタイムデータ処理アプリケーションの開発が可能です。お客様ごとの、利用されるモビリティや、運用シーンに合わせて下記のような拡張開発を行うことができます。 アラート機能 詳細データを活用した異常検知 リアルタイム分析による異常検知 AIを利用したリアルタイム映像分析 モビリティ個別の稼働率計算 SDKなど拡張開発に必要となる情報は下記リンクにも置いてありますので、ご興味ある方は参照下さい。 aptpod,Inc Development aptpod,Inc. Docs intdash CONTROL CENTERは上記の機能を実現するソフトウェアコンポーネントを提供します。これをベースにユースケースに応じた、拡張性を持ったシステム開発が可能になります。 前述の通り、ゼロから開発を進めると費用、期間ともに大きく掛かってしまう、モビリティ/ロボット向けの管制制御システム、遠隔操縦システムですが、本ソリューションを導入し、全ての機能または一部の機能を活用頂くことで、 低コスト、短期での本番運用に向けたシステム構築 ができるようになります。 上記にあげた機能のいずれかの実現を目ざしている、または、上記のような機能実現に課題があるといったお客様は是非、当社へご連絡頂き、intdash CONTROL CENTERの活用について一緒に検討させて下さい。 intdash CONTROL CENTERを使ったデモ紹介 これまで説明してきたintdash CONTROL CENTERを利用した、2つのユースケースにおけるデモを紹介します。1つ目は 自律走行ロボット群のフリート管理 、2つ目は 移動ロボットの遠隔操縦・コマンド指示 のユースケースです。 (1)自動走行ロボット群のフリート管理 ROS(Robot Operation System)のシミュレータである Gazebo 上で、屋内工場内に6台の自動走行ロボットを稼働させています。ロボット内はROS1で構築しています。 それぞれのロボットにはintdash Serverとデータ送受信を行うための、intdash EdgeとDevice Connectorを搭載しており、各機体の位置情報、カメラ映像などをリアルタイムにintdash Serverに送信しています。 intdash Serverに送信された位置情報をもとに、intdash CONTROL CENTERのリファレンスアプリケーションであるフリートマップアプリケーションを使用して、 各機体の位置や状態、カメラ映像をリアルタイムに可視化 することができます。 各ロボットの詳細なデータを確認したい場合には、フリートマップアプリケーションからVisual M2M Data Visualizerに遷移して、 機体データの詳細をダッシュボード上で確認 することができます。 今回のデモではVisual M2M Data Visualizerで、各ロボットのSoC, SoHや稼働率をダッシュボード上に値表示、グラフ表示を行っています。 本デモのように遠隔監視室から、稼働しているロボットのマップ上の位置や、SoC/SoH、稼働率といった稼働状況を監視することで、 管理対象のロボットが安全かつ効率的な作業が実施できているかを確認 することができます。 システム構成 youtu.be 【動画説明】 3:30頃まではフリートマップアプリケーション上に複数のロボットの位置情報を表示しています。画面下部には選択しているロボットの名称や状態、カメラ映像を表示しています。 3:30頃からVisual M2M Data Visualizerで6台のロボットそれぞれの詳細データをダッシュボード上に表示しています。速度、角速度、SoC/SoH、稼働率などを値で表示しています。 4:30頃からは同じくVisual M2M Data Vizualizerで6台のロボットのSoCや稼働率の推移をダッシュボード上でグラフ表示しています。 本動画では同じディスプレイでそれぞれのアプリケーションを順番に表示していますが、実際の遠隔監視室では複数のディスプレイを配置して、それぞれのアプリケーションを並べて同時に確認することもできます。 (2)移動ロボットの遠隔操縦・コマンド指示 オープンソースの移動ロボットプラットフォームである「 Turtlebot3 」(実機のロボット)とGazebo上のロボット(シミュレータ上のロボット)を使用した遠隔操縦のデモです。 制御対象のロボット(Turtlebot3)はROS1で構築しており、ロボットに搭載したRaspberry Piにintdash Severとデータ送受信するためのintdash EdgeとDevice Connectorを搭載しています。 同じく、Gazebo上のロボットにもintdash EdgeとDevice Connectorを搭載しています。 遠隔操縦用のコントローラとしては「 DualSense 」を使用しています。操作情報をintdash Serverに送信するために、Raspberry Piを用意し、intdash EdgeとDevice Connectorを搭載しています。DualSenseとRaspberry PiはBluetoothで接続して、コントローラのボタン、ジョイスティックの情報をリアルタイムにRaspberry Pi上のintdash Edgeを介して、intdash Serverに送信します。 intdash Serverに送信された操作情報は、ロボット上のRaspberry Piが受信して、操作情報に従い、ロボットの車輪やアームを動作させます。 本デモの構成では、ロボットに搭載されたカメラ、センサ情報をリアルタイムにVisual M2M Data Visualizerで監視を行いながら、 必要な場合には、人の手を介して遠隔操縦を行うことが可能 となります。 また、Visual M2M Data Visualizer上のボタンを操作することで、ロボットに対するコマンド送信を行うこともできるので、 遠隔監視室からロボットへ指示を行うことが可能 です。 システム構成 www.youtube.com 【動画説明】 0:30頃までは、画面右下に表示されているカメラ映像のDualSenseを操作して、Gazebo上のロボットを遠隔操縦しています。Gazebo上のロボットの動きは画面左下のGazebo上のカメラ映像と、LiDAR情報から確認できます。 0:40頃に掛けて、遠隔操縦の制御対象をGazebo上のロボットから、Turtlebot3に切り替えています。 1:15頃までは、DualSenseを操作して、Turtlebot3を遠隔操縦しています。Turtlebot3の動きは、画面右下のカメラ映像と、画面左上のTurtlebot3に搭載したカメラの映像、LiDAR情報から確認できます。 1:25頃からは、Visual M2M Data Visualizer上の、画面右上の青いボタンを押すことで、Turtlebot3に「アーム位置をリセットする」コマンドを送信しています。青いボタンを押すと、画面右下のTurtlebot3のアーム位置が初期位置に移動する様子が確認できます。 おわりに 今回は当社が提供する、 モビリティやロボットのリアルタイムかつインタラクティブな管制制御システムを迅速に構築するためのソリューションフレームワークである「intdash CONTROL CENTER」 を紹介させて頂きました。 intdash CONTROL CENTERを導入して管制制御システムを構築することで、下記の特長を持つシステムが実現できます。 低コスト、短期でシステムを構築 拡張性のあるシステムを実現 クラウドに保存されたデータを利活用可能 ロボット管制・管理、遠隔操縦、フリート管理などに課題をお持ちの方は、是非当社にご連絡下さい。 intdash CONTROL CENTERを活用頂くことで、課題解決を行い、本番運用に向けた管制制御システムを迅速に実現できるようお手伝いできればと思います。 また、当社ではロボティクス分野向けのソリューションの他にも、自動車分野向けのパッケージプロダクトも開発を進めています。 aptpod,Inc REMOTE CAL 【intdash AUTOMOTIVE PRO REMOTE CAL】ECU遠隔適合システムのご紹介 - aptpod Tech Blog intdash CONTROL CENTER、intdash AUTOMOTIVE PRO REMOTE CALともにパイロットユーザーを募集中です! aptpodは今後も、各産業のDXを進めるためのプロダクトを企画、開発を進めていきます。intdash及び、当社プロダクトで解決できる課題があれば、是非、お気軽に下記リンクからご連絡下さい。 aptpod,Inc. Contact
aptpod Advent Calendar 2022の14日目、担当はコーポレート・マーケティング室、デザインチームの「チェン ・ルイ」です。普段は社内製品のアプリケーションのUIデザイン業務を行なっています。 今年8月から弊社デザイン業務が少しずつSketchからFigmaに移行しています。 弊社のデザイナー高森の8月の記事 では俯瞰的にデザインツール変更や導入するときに確認したポイントを紹介しました。 今回は実際にFigmaを使ってデザインファイルを制作、管理するときに実用的なTipsをいくつか紹介します。 グリッドの整理機能 Selection Colorsで色変数の一括適用 Sectionの活用 PageやSectionを利用してコンポーネントをグルーピングする 最後に グリッドの整理機能 複数のオブジェクトを選択して配列したあと、隅にあるグリッドアイコンをクリックすると、配置を整理できます。 オブジェクトはドラッグして再配置したり、直接画面で間隔を調整したり、プロパティパネルで数値を調整することも可能です。 Sketchではグリットを作る場合、1行、1列ずつ整列する必要があります。Figmaのグリッド整理機能があると時短になります。 グリッドレイアウトを制作するときに試してみましょう。 Selection Colorsで色変数の一括適用 デザインコンポーネントを整理するとき、色を一括で色変数に適用したい場合、 Selection Colors の設定を利用すると便利です。 Selection Colors はFills、Strokes、Solid colorsなどを跨いで一括で色を表示しています。 特に複数のレイヤーを含むコンポーネントは、レイヤーを1つ1つ選択しなくても大丈夫なので、かなり時間が節約できます 。 以下の例はボタンのテキストに色変数を適用する例になります。 【 テキストレイヤーを選択して適用する場合 】 コンポーネントのテキストレイヤーを1つ1つ選択するとかなり手間がかかります。 【 Selection Colorsを利用する場合 】 ボタンを一括で選択して、まとめて変換できます。 コンポーネントに色変数の一括適用したいときに、 Selection Colors を使ってみてください。 Sectionの活用 Sectionは最近追加された機能であり、Sketchには無い、上位のレイヤータイプです。複数のFrame(Sketch のart board相当)をまとめて管理することが可能です。 コンポーネントやデザインガイドを整理するとき、グルーピングして管理したい場合もあります。コンテンツの増減によって、全体の背景の大きさを調整する場合もあります。この場合、Sectionをおすすめします。 【 Frame 】 【 Section 】 上記動画の通り、Frameを使用する場合Contraintsの設定はデフォルトで Scale になり、そのまま広げるとUI要素のサイズも変わってしまうため、まずはLeft、Topに設定する必要があります。 一方、Sectionを利用するとContraintsの設定が関係なく自由に広げてもUI要素のサイズが変わりません。細かいところですがかなり作業時間を節約できます。 現状、SectionとFrameの使い分けは主にこのようになります。 Section→ コンポーネントのグルーピング Frame → UI画面のベース UIコンポーネントを整理するときに、Sectionを活用してみてください。 PageやSectionを利用してコンポーネントをグルーピングする Sketchと同じく、コンポーネントの「/」命名規則が適用されます。 過去SketchでComponentの名前をつける際、「/」で分割を多用するとコンポーネント名が長くなりすぎます。グループ名の漏れやタイポが原因でグルーピングできず、後程編集し直すこともたまに発生しました。 Figmaでは、PageやSection、Frameを使用してカテゴリを作成することができます。コンポーネントをフレームに追加すると「/」と同じように整理されます。コンポーネントを新しいフレームにドラッグするだけで、すぐにコンポーネントを再編成できます。 PageとSectionの活用によって、あらかじめSectionやページに配置と最初からグルーピングでき、コンポーネントの名前が短くなり、二度整理する手間をなくすことができます。 現状iconの画面や目次の階層はこのような関係になります。 階層の順番はこのようになります: ページ > Section > Frame > Component名 UIコンポーネントを整理するときに、是非活用してみてください。 最後に Figmaを活用するTipsは他にもたくさんありますが、今後アップデートがあればまた紹介していきたいと思います。
aptpod Advent Calendar 2022 の13日目を担当します、ECUソリューショングループの村松です。 自動車産業は、100年に一度の大変革の時代といわれており、CASE Connected(コネクティッド)、Autonomous/Automated(自動化)、Shared(シェアリング)、Electric(電動化)、クルマを介した様々なサービス化が進んでおります。 排ガス規制をクリアする為に導入されたECU(Engine Control Unit)は、いつのまにかECU( Electronic Control Unit)となり、電気が流れる車載機能のほぼ全てにECUが存在すると言われております。 昨今、安全性や快適性が追求され複数のECUにまたがるロジックの開発、グローバル開発車両に伴う各国での検証は、実走行試験の複雑化や長期化が課題となっております。 aptpodでは、低遅延、ハイスループットのIoTソリューションintdashの利点と汎用計測適合プロトコルXCP(eXtended Calibration Protocol)による遠隔適合ソリューションintdash AUTOMOTIVE PRO REMOTE CAL(CALibration)で、皆様の課題解決へお力になりたいと考えております。 今回は、β版のリリースを予定しております intdash AUTOMOTIVE PRO REMOTE CAL をご紹介したいと思います。 2021年にご紹介しました CCP(CAN Calibration Protocol) DAQ(Data AcQuisition)サービスについてのtech Blog もご参照ください。 tech.aptpod.co.jp REMOTE CAL システム構成 REMOTE CALの機能 遠隔適合 ユースケース 適合試験者 現地作業者 最後に REMOTE CAL システム構成 REMOTE CALは高速で確実な遠隔データパイプライン環境を実現するサーバーシステム、及び車両計測適合用に制定されたマークアップラングエッジA2L(ASAM MCD-2 MC Language)に対応したWebアプリケーションで構成されます。それにより、計測機器メーカー各社のツールと連携し遠隔よりリアルタイムでの計測適合環境を構築します。 REMOTE CAL UI ECU内部情報が記載されたA2Lの登録、リモート先のEdgeの設定、データ可視化 ECU内部パラメータ(定数・変数値)の表示と変更 REMOTE CAL Server EdgeからのECU内部情報を変換、時系列に整列と格納 REMOTE CAL UIからのECUパラメータ変更をEdgeへ伝達 REMOTE CAL Edge 各社ECU計測器・インターフェースと連携し、ECU内部情報をserverへ転送 UIで設定されたECUパラメータを測定器I/F経由にてECUへ書き込み REMOTE CALの機能 ECU内部構造を記載したA2Lファイルの統合的に管理 XCP接続可能なECUに対しRAM値の計測及び、修正や変更など適合が可能 リアルタイムでのECUの計測・適合と合わせ、映像、位置情報、CANなど様々な情報をノンプログラムのダッシュボード上に配置し可視化 遠隔適合 ユースケース 適合試験者 試験車両をリアルタイムでECU内部実測値、画像、位置情報、CANなどを同時にモニタ可能 遠隔にある複数台の試験車両の情報を同時にダッシュボード上に表示 トラブル時の状況をモニタでき、遠隔地にある試験者へ迅速なサポートが可能 現地作業者 ダッシュボードにより、車両の状況の確認可能 適合作業に必要な車両の操作、確認可能 トラブル時の現地対応はもとより、開発拠点からのリモートサポート可能 最後に intdash AUTOMOTIVE PRO REMOTE CALは、製品版リリースへ向けて順次機能を拡充していく予定です。β版入手方法、製品のご質問や追加機能のご希望などございましたら、お気軽に こちらのリンク までご連絡ください。 www.aptpod.co.jp
本日は aptpod Advent Calendar 2022 の12日目、担当は開発本部のやべです。普段は EDGEPLANT 関係の開発業務をやっています。 さて、皆さん、スプラトゥーン3やってますか?12月から新シーズンが始まってますます楽しくなってきましたね。 aptpod には circle_switch なる slack のチャンネルがあるのですが、最近はもっぱらスプラトゥーンの話題です。先日も 8人集めてプライベートマッチやってました。 当初は最近調査していた Multipath TCP に関するきっちりした技術記事を書こうと考えていましたが、業務以外での社内の雰囲気も伝わるかと思い、このネタにしてみました。 概要 環境構築編 入力側の準備 制御(ゲーム操作)側の準備 調整編 実戦編 おわりに 目次はこんな感じです。イカ、よろしく~ ※本記事ではところどころスプラトゥーン3のプレイ画像が挟まりますが、任天堂のガイドラインを考慮してモザイク処理を施しております。見づらいですがご容赦ください。 概要 今回の目標は、キーボード入力を サーバーを経由 して、Switchにコントローラーの情報として送り、 実際に操作する ところまでになります。 まずはおおまかな構成について説明しておきます。 データの流れ 今回は手元にあった機材を流用して、よくある制御のパターンに近い構成にしています。 入力側:開発試作機( こちら で紹介しています)にキーボードを接続 制御側:Raspberry Pi 4B を Bluetoothコントローラーとして動作するように設定し、Switch からHDMI映像を入力する 実際の機材の接続は、こんな感じでした。 入力側環境 制御側環境 当初制御側のエッジでは Raspberry Pi 4B のUSBポートを直接利用していたのですが、それだと Bluetooth 接続時にHDMI入力が切れる問題が発生したため、セルフパワー給電ができるUSBハブを介することで動作を安定させています。写真に写っているのは StarTech 社のハブですが、同社の製品は信頼性が高く、aptpod でもよく採用しています。 www.startech.com 環境構築編 データのやり取りには、aptpod の製品である intdash Edge を利用しています。利用方法などを知りたい方は、 こちら をご覧ください。 入力側の準備 入力側では、以下のデータを取得してサーバーに送ります。 キーボード入力 カメラ映像(キーボードを映すもの) カメラについてはデフォルトで intdash Edge がサポートしているため、取得設定を行うのみです。キーボード入力については、実装スピード重視で、Python のライブラリを利用しました。 github.com キーボードの入力は、それぞれコントローラーの何らかのボタンに割り当てます。入力内容を変換する処理をどこでやるかは全体のシステム設計にもよりますが、データサイズを均一にするため整形を行ってサーバーに送りたいので、今回は入力エッジ側で変換するようにします。 CONTROLS = { "l" : "BA" , "k" : "BB" , "i" : "BX" , "j" : "BY" , ... } このような形で、入力データを2文字のコントローラー用のコードに変換しました(例:BA = Button A)。このデータを、ループして push/release のタイミングで送っていきます。 while True : event = keyboard.read_event() if event.name == "esc" : print ( "escape was pressed" ) break if not event.name in CONTROLS: continue ctrl = CONTROLS[event.name] if event.event_type == keyboard.KEY_DOWN: on_push(ctrl) else : on_release(ctrl) on_push 、 on_release では、FIFO経由で、データ送信処理を管理しているモジュール(Edge Agent)に対してデータを送っています。 制御(ゲーム操作)側の準備 制御側では、以下のことを行います。 キーボード入力をサーバーから受け取って、コントローラーとして動作する HDMI映像をサーバーへ送信する HDMI入力は、安価なキャプチャデバイスを使ってUSB経由で入力します。設定自体は一般的なUSBカメラと同じもので動作します。コントローラーとしての動作については、こちらの Python のライブラリを利用しました。 github.com 入力側からは、コントローラーの入力に対応したコードが送られてくるため、制御側では実際の定義に置き換えるようにします。 BUTTONS = { "BA" : nxbt.Buttons.A, "BB" : nxbt.Buttons.B, "BX" : nxbt.Buttons.X, "BY" : nxbt.Buttons.Y, ... } これらのデータが届いたタイミングで、対応するボタン入力(もしくはスティック入力)が動作するようにします。 while True : recv = fifo.read( 18 ) if len (recv) != 18 : continue d = decode(recv) if d[ "status" ] == 0 : # release button continue ctrl = d[ "ctrl" ] if ctrl in BUTTONS: nx.press_buttons(controller_index, [BUTTONS[ctrl]]) ... 調整編 とりあえず作っては見たものの、入力に対して反応が悪くなイカ? 初期バージョン 操作情報と一緒にCPU負荷を送っているのでそれを見てみると、制御側の負荷がかなり高くなっています。 制御側の負荷状況 おそらく入力を処理しきれていないため、かなり遅延が発生しているようです。そこでライブラリのコードを参考に、使うAPIの変更やキーボード入力の間引き、押し込み時間の調整など、いくつかの対策を行ったところ、かなり改善しました。 負荷軽減バージョン 赤枠のCPU使用率を見てみると、負荷が40%程度軽減されています。 スペシャル(必殺技的なやつ)もしっかり打てるぞ! スペースキーを押して 発動! 精度はさておき、ここまででキーボード入力を受け取って操作を行うというタスクについては完了しました。 実戦編 というわけで、いざ実戦投入! といっても、見知らぬ方々にご迷惑をおかけするわけにはいかないので、冒頭で話した社内プライベートマッチで一戦だけ行いました。 おろおろしているところを撃ち抜かれる図 結果、瞬殺。 映像の遅延やボタン入力の反応はさほど悪くないものの、スティック側の入力反映が微妙で思ったように動きません。また、移動しながらの視点変更など、同時入力を必要とするケースを考慮していなかったのも、けっこう辛いポイント。実際に社内で制御を扱っているプロジェクトでは色々と考慮して設計されているわけで、遠隔制御は1日にしてならず、と痛感いたしました(みんなすごい!)。 おわりに イカがだったでしょうか?intdash を利用した遠隔制御の雰囲気が伝わっていれば幸いです。 実際に自分でやってみた感想としては、単なる疎通まではたいして時間はかからないものの、その後の操作感の向上や安定性などを詰めていく作業が大変でした。ボードゲームのようなものならこれでも十分ですが、今回扱ったスプラトゥーンのように複雑な操作が必要なゲームに実戦レベルで対応するためには、更なる改善検討が必要になります。操作データの送信方法の見直しや処理の非同期化、Python以外の言語への置き換えなど、やれることはまだまだあります。 こんな記事もあるように、世の中的には遠隔制御とゲームの親和性も注目されていたりするので、今回やった取り組みは案外エントリーとしてはいいお題なのかな?とも思いました。 automaton-media.com ほな カイサン!!!
はじめに aptpod Advent Calendar 2022 9日目の記事を担当する、開発本部の加藤と申します。 aptpodでは自社製のハードウェアも提供しております。現在、コンピュータ製品には EDGEPLANT T1 がありますが、異なるニーズやユースケースにも対応できるような、測定用のペリフェラルを内蔵したコンピュータの試作機開発を行っています。この試作機の特長等についてご紹介させていただきます。こちらの試作機にご興味をお持ちいただけましたら、当社までお問い合わせください。製品化に向けたロードマップや、試作機の試用等についてご案内させていただきます。 はじめに 開発の背景 インターフェイスが少なくUSB周辺機器とセットで利用する必要がある 物理的なサイズが大きい 仕様概略 仕様詳細 外観および入出力 SOM 通信機能・GNSS機能 USB CAN 加速度・角速度センサ アナログ入力 電源ON/OFFの仕方 ストレージ 防水機能 社内テスト 動作温度範囲 静電気放電試験 ファスト・トランジェント/バースト試験 放射エミッション試験 自由落下試験 未実施の試験 実際のデータ収集での使用例 横浜ロボットワールド2022 最後に 開発の背景 aptpodでは、 intdash という双方向データ伝送プラットフォームを使用したデータ収集および遠隔制御サービスをご提供しております。 冒頭申し上げました通り、自社製のコンピュータには EDGEPLANT T1 があり多くのケースでご提供しております。このコンピュータはエッジ側でGPUを活用したAI処理を行う意図をもって開発しましたが、自社サービス専用ということではなく汎用的にも使用できるように設計されています。実際に アマゾンで単体販売 もしております。自社のサービスの全てでこの EDGEPLANT T1 を使おうとする場合には、以下の課題があります。 インターフェイスが少なくUSB周辺機器とセットで利用する必要がある 汎用的に使用できるようにUSBのポートを多く持たせ、インターフェイスの種類は少なく設計している為、USB周辺機器とセット利用が必要となります。その結果USB機器の製造も別途必要となります。製造する製品の種類が増えてしまうのは、生産管理が難しい、価格も高くなるなどのデメリットがあります。 物理的なサイズが大きい 処理能力が高くその際の放熱なども考慮されている為、それを必要としないケースではコンピュータ単体のサイズが必要以上に大きくなっていることになります。また、USBポートやそこからの供給電力を多く用意し多様な組み合わせに対応可能な汎用性を持たせており、用途が限定されるCANインターフェースやアナログ/デジタルインターフェースは内蔵しておりません。多くの場合、 EDGEPLANT CAN-USB Interface と組み合わせて構成しているのですが、測定対象が一定数以下の場合には、物量が必要以上に大きくなってしまいます。 課題解決の方法として、下記の条件を満たすエッジコンピュータを準備することを考えました。 弊社のデータ収集サービスでよく使われる測定用の機能を内蔵している。 内蔵している機能は全て同時に使用できる。 小型・軽量 より詳細な条件は、以下の通りとなります。 LTE通信機能を有する。 弊社のデータ収集サービス(データ完全回収)で使用できるCANやデジタル入力、アナログ入力機能を内蔵している。 内蔵している測定機能を全て同時に使用できる性能を有する。 自動車のデータ収集に必要十分な品質を備える。 動作電圧  9V~36V、動作温度範囲 -20℃~65℃。 長期間継続して購入可能であることが期待できる。 上記条件を満たすコンピュータが市販されていないか探してみましたが、全ての条件に合致するものは見つかりませんでした。その為、自社で開発・試作を行いました。 仕様概略 仕様概略につきましては、横浜ロボットワールド2022の参考出展時に配布させていただいたリーフレットをご覧いただければと存じます。 仕様詳細 仕様の意図や工夫した点などご説明させていただきます。 外観および入出力 サイズは幅88mm×奥行き94mm×高さ32mm(取付板を含まない)、質量は250gとなっております。自動車のダッシュボードの収納スペースやオートバイのシート下収納スペースにも収まるようにコンパクトにまとめました。 自動車に搭載する場合のサイズ感 入出力端子の配置は以下のとおりとなっております。 正面 背面 SOM SOMは、Raspberry Pi CM4を採用しました。コストパフォーマンスが高いこと、Raspberry Piは世に多く出ているハードウェアであり既にそこで動作するソフトウェアも多く作られていると考えられること、Linuxが動作すること、動作温度範囲が広いこと等が選定の理由です。Raspberry Piは弊社でも活用事例は多いです。以下は、Raspberry Piを使用した過去の記事のリンクです。 "リアルタイム"デジタルツインデモを展示しました IoTボタンによる回数記録基盤をAWSとRaspberry Piで構築する Bluetooth Low EnergyのclientアプリをBlueZとpythonで作ってみた intdashを活用したシステム開発 5Gのネットワークを計測してみた 通信遅延発生時にTurtlebot3を安全に遠隔制御する技術 ラズパイでCAN通信をして、車両の診断データを送受信してみた 通信機能・GNSS機能 内蔵の通信機能はLTEを採用しました。aptpod のユースケースではLTE通信が欠かせない為、必須要件であるからです。通信モジュールは、SIERRA WIRELESS社のEM7431にしました。これまで弊社で使用していたEM7430と比較して安価であること、GNSS機能も内蔵しておりコストパフォーマンスが高くなることが理由です。有線LANやWi-Fiが必要な場合には、USBから拡張していただく想定です。 USB USBポートは2ポートとしました。想定したのは、 EDGEPLANT USB Camera と CAN-USB Interface で2ポート、あるいは EDGEPLANT USB Camera とマイクで2ポートという使い方です。 データ収集ではカメラは使用頻度の高いデバイスなのですが内蔵してしまうと取付位置の自由度が下がってしまう為、USBによる外付けとしました。 マイクのインターフェースは、3.5㎜ミニジャックのものとUSBのものがあるのですが、データ収集サービスではマイクの需要はそこまで高くない為、汎用的に使えるUSBを使用することを考えました。 USBのコネクタはネジ止めができません。振動・衝撃でコネクタが外れないようにする為の高保持力(15N)のコネクタを採用しました。 CAN 接続したCANバス上のデータを取得する為のインターフェースです。測定用のサービスに使用する場合、CANに流れるデータ全てを記録する必要があります。CANのデータは高頻度で発生する可能性があり取りこぼしを起こさないようにする為に、専用のマイコンで受け取る仕組みにしました。内部回路は弊社の製品のCAN USB-Interfaceと同じにしました。 加速度・角速度センサ 筐体中心部に加速度・角速度センサICを実装しています。移動体の測定に使用することを想定している本製品にはあるべき機能と考えました。フルスケールが加速度は±2/±4/±8/±16g、角速度は±125/±250/±500/±1000/±2000dps、分解能はそれぞれ16bitです。 アナログ入力 下記の様な入力を想定して汎用的なアナログ入力ポートを4ポート設けました。入力回路は、インピーダンスを高くして接続先の動作の影響が少なくなる様意識しました。 各種状態検知:測定対象が出すエラー信号やLED制御信号の検出を行うケース センサ入力:測定対象に内蔵されているセンサーの電圧を測定するケース 各所電圧・電流検知:電圧や電流の測定を行うケース 外部スイッチ:自動車等の測定で運転者が任意のタイミングでスイッチを押し、後で検索しやすくするケース 電源ON/OFFの仕方 自動車に接続する場合を想定して、バッテリーが接続された状態でイグニッションキー(ボタン)の電圧を検出して電源ONする仕組みにしています。専用の入力端子があり、そこに9V以上の電圧印加で電源ONということです。入力がオープンかGNDレベルになると終了処理してからOFFになります。イグニッションキー(ボタン)は監視用のマイコンで常にチェックしています。このマイコンはCANバス信号もチェックすることが可能で、その内容によって電源ON/OFFする仕組み(Wake on CAN)も準備しています。電源OFF時の待機電流は、バッテリー電圧12V・周囲温度25℃の条件で約5mAでした。 ストレージ Raspberry Piシリーズと同様、ストレージはmicroSDカードを採用しました。データの信頼性の高い産業用のSLCモード64GB品を使用しました。また、意図しないバッテリー断でデータ破損しないように電断保護機能有りのものを選びました。 防水機能 防水機能について検討したのですがどうしても小型化と相反する為、外付けの防水ケースを別に設計・試作しました。ケーブルを通す防水ゴムは、ケーブルを先に通してからケーブル端を加工するものが多いのですが、この方式ですとUSBケーブルやアンテナケーブルの接続が困難になる為、コネクタ付のケーブルに取付けできるタイプを採用しました。 防水ケース 社内テスト 試作機で行った社内試験について簡単にご紹介させていただきます。国際規格の試験も行っておりますが、試験を行った試験場は認証試験場ではないことにご注意ください。 動作温度範囲 -20℃および65℃で起動及び24時間の連続動作を確認しました。 静電気放電試験 試験方法はIEC61000-4-2で、接触放電±8KV、気中放電±8KVで、動作停止しない・故障しないことを確認しました。 ファスト・トランジェント/バースト試験 試験方法はIEC61000-4-4で、電源ラインにノイズを印加する試験を行いました。テストレベル1(500V)にて、自己回復不可能な機能障害が無いことを確認しました。接続するディスプレイやUSBデバイスによって結果が大きく異なり、苦労しました。 放射エミッション試験 試験方法は、FCC Part15 Subpart Bで3m法で行いました。これも接続するディスプレイやUSBデバイスによって結果が大きく異なり苦労しました。本試作機単体(接続デバイスを選べば)では、ClassBで合格できそうなことを確認しました。 自由落下試験 試作機単体で1mの高さからコンクリートに自由落下させる試験を行いました。故障・変更・動作異常などなく問題ないことを確認しました。 未実施の試験 製品化を行う場合には最終の仕様にて下記についても試験を行いたいと考えております。 振動・衝撃試験 過渡伝導エミッション/イミュニティ(ISO7637-2) 放射イミュニティ(IEC61000-4-3) 伝導イミュニティ(IEC61000-4-6) 実際のデータ収集での使用例 本試作機を使用したデータ収集の例をご説明させていただきます。 試作機にソフトウェア( intdash Edge )を実装し、実運用に近い自動車での動作を確認しました。 構成図 搭載物一式 下記のデータ全て取得できることを確認できました。 カメラ:1台、解像度はHD、15fps GNSS:1台、位置検出、1秒に1回更新 CAN:内蔵CAN1ch+ EDGEPLANT CAN-USB Interface を1台追加=合計3ch 角速度センサ:3軸、各分解能16bit、104sps 加速度センサ:3軸、各分解能16bit、104sps 測定データは Visual M2M Data Visualizer で確認しました。各種データを様々な方法で可視化可能なツールで、測定中にリアルタイムで確認することも測定後に確認することも可能です。実際の表示画面を添付します。 Visual M2M Data Visualizerでの確認 横浜ロボットワールド2022 横浜ロボットワールド2022の弊社ブースでこの試作機の展示をさせていただきました。私も説明員として立ち会わせていただきました。 展示品 充電式電池(単3×8本)で駆動してワイヤレスにして、回転台の上に載せました。 EDGEPLANT CAN-USB Interface を接続。アナログ入力には測距センサも接続しました。回転させるとカメラ画像、内蔵の角速度センサのデータ、測距センサのデータが、リアルタイムに滑らかに表示される気持ち良い仕上がりになりました。 Visual M2M Data Visualizer画面 動作をみて頂いたお客様にも「センサーの状態がリアルタイムで確認できるのは良い」「電池駆動できるのは面白い」などご意見いただき大変好評でした。ご来場いただきありがとうございました。 最後に 試作したコンピュータを使用した弊社のデータ収集サービスについてご理解いただけたかと思います。もし、 intdash や本試作機にご興味いただけましたら、是非ご連絡をお願いします。また、本記事では記載できませんでしたが試作機(ハードウェア)は遠隔操作または自律移動ロボットのECUとしても利用可能ではないかと考えております。もし、Raspberry Piベースの堅牢なコンピュータにご興味あれば是非お声がけをお願いします。仮に本試作機(ハードウェア)をご評価いただけるということであればすぐにご提供致します。ご連絡をお待ちしております。最後まで読んでいただきありがとうございました。
はじめに こんにちは。 aptpod Advent Calendar 2022 8 日目を担当する、SRE チームの柏崎です。 SRE チームは、 intdash のインフラ関連の業務はもちろんですが、自社のコーポレートサイトやオフィスのネットワーク等の運用など、いわゆる「社内 SE」的な業務も担当しています。 今回は、社内 SE 業務のうちの 1 つで、私がアプトポッドに入社して以来 8 年ほど面倒を見ている、GitLab の運用についてご紹介しようと思います。 はじめに GitLab 運用ノウハウ 利用するバージョンは 1 つ前 ドキュメントをよく読む Ruby と Node.js Ruby のメモリアロケータ CI 環境 実行基盤 Docker Hub のミラーリング おわりに GitLab 運用ノウハウ ここでは、これまで長く運用してきた GitLab 運用の知見の一部をご紹介します。 ※ 現在 GitLab は、Omnibus と呼ばれる deb/rpm パッケージでのインストールや、Helm chart での k8s へのインストールなど、様々なインストール方式が提供されていますが、アプトポッドでは当初からソースインストール方式を使い続けています。 利用するバージョンは 1 つ前 GitLab は、年 1 回のメジャーリリース、月 1 回のマイナーリリースがあり、都度様々な新機能が追加されています。 私は、「1 つ前のマイナーリリース」の最新を追いかけるようにしています。 GitLab は、バグフィックスやセキュリティフィックスが含まれるパッチリリースが頻繁に行われています。 最新リリースでは、不具合やアップグレードドキュメントの不備があることが多く、そういったものは後追いのパッチリリースで修正されていきます。 当初は最新リリースを追いかけていましたが、前述のような不具合等で切り戻す事も多く苦労しました。 1 つ前のマイナーリリースを使うことで、これにアップグレードする頃には大きな不具合は修正されていて、切り戻しはほとんど発生しなくなりました。 ( こんな 1 行修正 MR を出したこともあります。) ドキュメントをよく読む アップグレード時に注意すべき点を把握するため、アップグレード手順だけではなく、インストール手順も含めてドキュメントをよく読むようにしています。 具体的には下記です。 Installation from source Ruby, Go, Git, Node.js, Yarn などの必要バージョンに更新が無いか、インストール手順に更新が無いか、重点的に確認します。 Installation system requirements Redis, PostgreSQL などの必要バージョンに更新が無いか確認します。 Version-specific upgrading instructions バージョン毎に、アップグレード時の注意点が書かれています。 Ruby と Node.js Ruby は rbenv、Node.js は nodenv を利用してインストールしています。 env 系を利用することで複数のバージョンを手軽に同居させられるので、Ruby や Node.js の必要バージョンが変わった際に、アップグレード作業時間外に事前に準備することができるようにしています。 Ruby のメモリアロケータ GitLab のような Ruby on Rails なアプリケーションを長く稼働していると、メモリ断片化によるメモリ使用量の逼迫に悩まされると思います。 当初は定期的に Puma ワーカーや Sidekiq プロセスを立ち上げ直すことで対処していました。 メモリアロケータを jemalloc にした Ruby を利用するようにしてから、メモリ使用量の上昇がゆるやかになり、このような対処が不要になりました。 jemalloc な Ruby に差し替えてからメモリ使用量が改善した様子 CI 環境 ついでに、CI 環境についても触れておきます。 GitLab は早くから CI サービスが統合されていて、私が GitLab 運用を担当するようになってからは、CI 環境の整備に力を入れてきました。 現在では、製品のアプリはもちろんのこと、プロジェクト独自のアプリも含めて、ほとんどのリポジトリで CI が実行されています。 実行基盤 Docker Machine で、GCP でプリエンプティブル VM インスタンスを利用し、低コストで運用しています。 CI は、ジョブ毎に n1-highcpu-4 (4 vCPU, 3.6 GB) のマシン上で実行され、最大 20 並列で動きます。 プリエンプティブル VM インスタンスを利用していることで、このような「つよつよ環境」を利用しても、月額 1 万強で済んでいます。 月額 1 万強 結構な数の CI が実行されている様子 Docker Hub のミラーリング CI は、ジョブごとに新規の環境で実行されるので、Docker Hub からのイメージの取得が都度行われます。 CI 実行基盤と同じネットワーク内に レジストリのキャッシュ を用意し、イメージ取得の高速化・トラフィックの抑制を行っています。 おわりに いかがでしたでしょうか。 GitLab や CI 環境の運用は、「みんなの業務は俺が支えてるんだ」感を味わえるので、実は結構好きな業務です。 だいぶまとまりが無い内容になってしまいましたが、アプトポッドの GitLab・CI についてのご紹介でした。