TECH PLAY

アプトポッド

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

248

aptpod Advent Calendar 2023 の12月5日を担当するintdashグループの大久保です。 弊社の製品のうち、エッジ上で動くものはRustを採用しているものが複数あります。例えば、 intdashに接続可能なデバイスを簡単に開発するためデバイス開発キットの基盤 である Device Connector Framework においてもRustを採用しています。 これらのソフトウェアでは大量のバイナリデータを高速に捌く必要があるため、その実装にはRustが適していると考え採用しています。とはいえ、Rustを使えば無条件で効率的な実装になるとは限りません。Rustでバイト列を表現する方法は複数あり、最適化のためにはそれらを使い分ける必要があります。今回は、Rustでのバイト列を扱う方法をまとめてみようと思います。 バイト列を表現する型 まず、一言でバイト列といってもRustでは様々な型を使って表現します。それらの型をここで紹介します。 Vec<u8> Vec<u8> はヒープ領域上に確保されたバイト列です。 mut であれば中身を変更することができ、ライフタイムもついてこないので扱いやすい型です。ただし、 clone() を行う場合は新たにヒープ領域への確保と中身のコピーが行われます。中身が同じバイト列をプログラムのあちこちで扱う場合に、 clone を行うたび高コストの操作が行われてしまいます。 &[u8] 別のオブジェクトが所有するバイト列を参照するスライスです。 Vec<u8> と異なり、 clone は低コストです。しかしライフタイムが付いてくるため、 'static なライフタイムが必要な場合など使えない場面も多いです。 Cow<[u8]> Cow は、所有権を持つ型と参照のenumであり、書き換えが必要になったら所有権を持つ型にcloneするという動作をします。バイト列を扱う場合にも使えます。 Bytes Bytes は、bytesクレートが提供するバイト列を扱うための型です。参照カウンタを用いてメモリを管理するため、効率的な clone() が可能です。 SmallVec SmallVec は、smallvecクレートが提供する、与えたサイズを超えるデータを保持するときだけヒープ領域を使用する Vec に似た型です。その性質上、たいていは短いデータしか扱わないけれども、時々長いデータがやってくる可能性がある場合に効果があります。短いデータはスタックに置くことができ、 clone() でヒープ領域の確保が起こらなくなるため高速になります。スタックに収まらないデータが大半ならば他の型を使うべきでしょう。 ArrayVec ArrayVec は、arrayvecクレートが提供する、ヒープ領域を使わずデータを保持する Vec に似た型です。その容量はコンパイル時に決め、容量を超えるデータをpushしようとするとpanicになります。あらかじめ決まった長さ以下の短いデータしか扱わない場合に使えます。 TinyVec TinyVec は、tinyvecクレートが提供する SmallVec とほぼ同様の型です。このクレートは ArrayVec と同等の型も提供します。異なる点は、このクレートはunsafeなコードを含まないためより安全であることが期待できること、その代わり初期化のため配列に入れる型が Default を実装している必要があり、パフォーマンスは若干劣ると思われることです。 Bytes の使い方 以前、 Rustでバイナリを読み書きするのに必要なクレート3選 という記事でbytesクレートについては少し取り上げています。ここでは、バイト列の効率的な表現方法として、 Byte 型に注目します。 作成とクローン use bytes :: Bytes; let a = Bytes :: copy_from_slice ( & [ 1 , 2 , 3 ]); let b = a. clone (); let c = a. slice (.. 2 ); assert_eq! ( &* a, & [ 1 , 2 , 3 ]); assert_eq! ( &* b, & [ 1 , 2 , 3 ]); assert_eq! ( &* c, & [ 1 , 2 ]); この例では [1, 2, 3] が中身となる Bytes を作り出し、 clone と slice を呼び出しています。 Bytes の clone は参照カウンタを増やすだけで、 Vec<u8> のように新規のヒープ領域確保と中身のコピーが行われません。そのため低コストで呼び出せます。また、 slice(..2) はバイト列の一部分を取り出しますが、これは参照カウンタを増やして元のバイト列の一部を指す Bytes を返します。配列のスライス &a[..2] と異なり、ライフタイムを気にする必要が無くなります。 BytesMut との組み合わせ Bytes の中身は編集できないので、これだけだと使い勝手が悪いです。中身の変更を伴う処理には BytesMut を使います。 use bytes :: {BufMut, BytesMut}; let mut bytes = BytesMut :: new (); bytes. extend_from_slice ( & [ 1 , 2 , 3 ]); let a = bytes. split (). freeze (); // 先頭を`split`で切り出し、`freeze`で`Bytes`に変換する bytes. put_u8 ( 4 ); // `BufMut`トレイトで定義されたメソッドで書き込み let b = bytes. split (). freeze (); assert_eq! ( &* a, & [ 1 , 2 , 3 ]); assert_eq! ( &* b, & [ 4 ]); assert_eq! ( &* bytes, & []); BytesMut は、 BufMut トレイトが提供するメソッドで編集することができ、その結果を split 系のメソッドで切り分け、それらを freeze で Bytes 型に変換できます。この切り分けは低コストでできるため、ストリームで流れてきたデータをパースして分割する場合などに効果を発揮できるでしょう。 並行処理 bytesクレートはtokioの下で開発されており、それゆえ並行処理に適するよう実装されています。 Bytes は Send を実装しているため、スレッド間での共有が容易であり、その共有も参照カウンタによるものなので低コストです。tokioのAPIでもbytesクレートの型は多用されているため、tokioで並行処理を行う場合はこれらの型を使いこなせると便利です。 構造体でのバイト列の持たせ方 構造体にバイト列を持たせる場合、 Vec<u8> を使うことが一般的でしょう。 struct MyData { id: u32 , data: Vec < u8 > , } impl MyData { // `data`を使うなにかのメソッド fn do_something ( & self ) { let data: & [ u8 ] = self .data. as_ref (); } } let data = & [ 1 , 2 , 3 ]; let my_data = MyData { id: 0 , data: data. to_vec (), }; my_data. do_something (); しかし、構造体のメソッドが全て Vec<u8> が必要とは限らず、参照 &[u8] で良い場合も多いでしょう。そのような場合、構造体に定義されたメソッドを使うために、 Vec<u8> を作るためのヒープ領域の確保が行われてしまいます。 そのような場合、バイト列をジェネリクスで扱うと良いでしょう。 struct MyData < T > { id: u32 , data: T, } impl< T: AsRef < [ u8 ] >> MyData < T > { // `data`を使うなにかのメソッド fn do_something ( & self ) { let data: & [ u8 ] = self .data. as_ref (); } } let data = & [ 1 , 2 , 3 ]; let my_data = MyData { id: 0 , data }; my_data. do_something (); 文字列の扱い バイト列と同様によく扱われるデータとして文字列(UTF-8)があります。これまで紹介したバイト列を表現する型に対応する、文字列の型も存在するのでこちらで紹介します。 バイト列 文字列 Vec<u8> String &[u8] &str Cow<[u8]> Cow<str> Bytes ByteString SmallVec<u8> SmallString ArrayVec<u8> ArrayString その他、 SmartString もここであげておきます。これは、 String 型と同じサイズで、そのサイズ内に収まる文字列(64bit環境なら23バイトまで)ならヒープ領域を確保せずその場に記憶してくれます。短い文字列が多数で時々長い文字列を格納するときに効果があり、定義されているメソッドやトレイトが通常の String と同様のものにしてあるので置き換えも容易でしょう。 最後に 以上、Rustにおける様々なバイト列の扱いを紹介しました。バイト列1つでこれだけ選択肢があるのはややこしいですが、うまく使えば安全で高速な実装を行うことができます。これらの知識は実際の製品開発にも活かすようにしています。ここまで読んでくださった方にも本記事の内容がご参考になれば幸いです。
アバター
はじめに aptpod Advent Calendar 2023 12月4日の記事です。 パートナー&サポート推進Grの松下です。弊社では、様々なパートナー様との連携を強化し、新規事業創出・支援を行っています。 弊社のパートナーシップに関するニュースはこちら 先日、パートナーのNTTコミュニケーションズ株式会社様より、超小型受信端末を活用した高精度位置情報測位サービス「Mobile GNSS」の提供がアナウンスされました。 NTTコミュニケーションズ様のプレスリリースはこちら 今回、この Mobile GNSS を実際にintdashにつなぐ事でレビューしたいと思います。 Mobile GNSS こちらのサービスは、超小型のGNSS受信端末、通信サービス、GNSS位置補正情報サービスをワンパッケージで提供しています。これにより、従来のGNSS受信端末の使用開始時と比べ、煩雑な設定を必要とせず、すぐに利用開始することができます。 プレスリリース からポイントをまとめると、RTK測位を用いたcm級の高精度な位置測位が、小型で軽量な端末で行える点にあります。 通常、RTK測位を行う場合は基準点(固定局)を設置する必要がありますが、国土地理院が提供する電子基準点に加えてドコモが独自で設置する基準点(固定局)が設置されているため、利用者はこの受信端末だけで、LTE(インターネット)経由でRTK測位に利用する補正情報を受け取る事ができます。(※ネットワークやオープンスカイ条件による) このRTK測位の恩恵を受けられる小型で軽量なGNSS受信端末はヘルメットなどにも装着可能です。 詳細な仕様に目を向けると、以下の機能を備えています: GNSSチップには、高精度2周波に対応しているubloxの ZED-F9P を搭載 LTE-CAT Cat.1のモバイル通信に対応しており、eSIMも内蔵しているため、すぐに通信が可能です LTEの代わりにWi-Fiで通信することで、モバイル通信環境が悪い環境にも対応できそうです BluetoothのSPP (Serial Port Profile)に対応しているので、無線で位置情報等を取得できます 電池を内蔵しており、USB Type-C または無線充電にも対応しています 防塵防水にも対応しています(IPx6相当) これほどの機能が、この小型筐体に収められていることには驚きますね! この製品自体は端末単体で利用する事を想定しており、測定結果はクラウドを経由して、Webブラウザ上で位置情報を確認する事ができます。また、CSVやNMEA形式でのダウンロードも可能です。 Linux につないでみる 端末単体で利用する想定の製品ですが、USBケーブルで直接接続する事でより高精度なデータにアクセスできます。 実際に受信端末とWindow PCを接続して、 u-center 等のアプリケーションでより詳細な計測データにアクセスする事が可能です。 一方で、Aptpodのintdashで使われる Edge コンピュータは Linux を使用しています。デバイスドライバの仕様を見ると CDC-ACM 形式との事なので、デバイスドライバのインストール無しに接続できそうです。 試しに、 Raspbian OS に接続したところ、 /dev/ttyACM0 のシリアルデバイスとして認識されました。 [ 801.743542] usb 1-1.2: new full-speed USB device number 7 using xhci_hcd [ 801.882330] usb 1-1.2: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00 [ 801.882349] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 801.882365] usb 1-1.2: Product: STM32 Virtual ComPort [ 801.882380] usb 1-1.2: Manufacturer: STMicroelectronics [ 801.882394] usb 1-1.2: SerialNumber: 205A336F3130 [ 801.897274] cdc_acm 1-1.2:1.0: ttyACM0: USB ACM device デバイスファイルの出力を確認すると、NMEA のデータが出力されています。 $ sudo cat /dev/ttyACM0 | head $GNRMC,044500.30,A,3542.74010540,N,13954.78959519,E,000.0,000.0,301123,000.0,,R*77 $GNGGA,044500.30,3542.74010540,N,13954.78959519,E,4,12,1.0,0,M,1.0,M,1.3,0000*7E $GNGSA,A,3,27,16,04,09,08,31,,,,,,,2.16,1.13,1.85,1*0E $GNGSA,A,3,,,,,,,,,,,,,2.16,1.13,1.85,2*08 $GNGSA,A,3,24,26,,,,,,,,,,,2.16,1.13,1.85,3*0B 一般的なNMEAデバイスとして扱えそうなので、intdash Edge Agentに接続できそうです。 intdash に接続する 今回は、Raspbian OS上に intdash Edge Agent 2 をインストールし、Mobile GNSS の位置情報をintdash Serverにアップロードしようと思います。 確認環境 Raspberry Pi 4B+ Raspbian GNU/Linux 10 (buster) LTE通信は Green HouseのLTE USBドングル ( GH-UDG-MCLTEC ) モバイルバッテリーで Raspberry Piに給電 インストールと設定 インストールは こちらの手順 で簡単にできました。 ${DISTRIBUTION} は debian を選択しています。 NMEAデータの送信は、 こちらのレシピ がそのまま使えました。ただし、デバイスパスは /dev/ttyACM0 に変更しています。 sudo intdash-agentctl config up --create ' id: recoverable ' sudo intdash-agentctl config device-connector up --create ' id: up-nmea data_name_prefix: v1/0/ dest_ids: - recoverable format: iscp-v2-compat ipc: type: fifo path: /var/run/intdash/nmea.fifo launch: cmd: device-connector-intdash args: - --config - /etc/dc_conf/nmea.yml environment: - DC_NMEA_PACKET_SRC_CONF_PATH=/dev/ttyACM0 - DC_NMEA_PACKET_SRC_CONF_BAUDRATE=57600 - DC_PRINT_LOG_FILTER_CONF_TAG=nmea - DC_FILE_SINK_CONF_PATH=/var/run/intdash/nmea.fifo ' 検証 RTK測位を行うには、オープンエアな環境が必要です。今回は、江戸川の河川敷で実験してみました。 試験経路 位置情報の評価の場合、基準となる地点が無いと難しいのですが、今回の河川敷には排水溝が設置されていたので、この上を歩いてみました。 また、水飲み場があったので、その周りを円形に一周してみます。 最後に、垣根を越えて川沿いを歩くルートとします。 試験結果 Mobile GNSS単体での動作と、Raspberry Piに繋いで intdashサーバーに送った結果を紹介します。 Mobine GNSS 単体 まずは、Mobile GNSS が LTE Cat.1 を使ってサーバーに送信しているデータを、端末デモ・検証用として運用しているクラウドシステムで確認しました。 結果を見ると、捕捉状態が Fixed になっていることから、RTCM を受信して 正確な位置情報が得られている事がわかります。 また、排水溝の上を綺麗にトレースできている事がわかります。通常のGNSSチップだと結構位置がずれるのですが、これはなかなかいい結果です。 ただし、水飲み場を周りを一周した軌跡は綺麗な円形になっていません。これは、クラウドにアップロードされたデータのサンプリングレートが低く設定されている為です。 intdash と連携 次に、Raspberry Piの LTE ドングルを使って、intdsah サーバーに送信しているデータを、 Data Visualizer で位置情報を可視化した図がこちらになります。 位置情報は 100 ms (10 Hz) 周期で取れていました。 水飲み場のまわりを一周できている様子もトレースできています。 考察 実際に使ってみて、よかった点と、intdash と連携する場合の課題について考察します。 Good Point RTKの基地局を用意せずに、RTK測位の恩恵を受けられます 位置情報の取得周期も標準で10Hzという点も評価できます(他社製品だと、1Hzや、よくても5Hzが多い印象です) 軽量・小型でUSB接続するだけで、面倒な設定も不要で、簡単に位置情報を取得できます intdash 連携時の課題 一般的なGNSS受信端末はUSB給電のものが多いのですが、本製品は電池を内蔵しているため、電源のON/OFFのためにスイッチを手動で押す必要があります。例えば人ではなく建築機器等に常設する場合は、運用等を考える必要がありそうです。 防塵防水加工されていますが、これは単体利用での想定です。USB端子にキャップを付ける形になります。USB接続する場合はコネクタ部分の防水加工が追加で必要そうです。データ量が少なくても問題ないのであれば、Bluetoothを使った無線接続を検討したいところです。 他の類似製品も同じですが、基本的に屋内では使えません。屋外でも、周辺に高いマンションやビルがある場合は、周辺環境の影響を受けRTK測位が難しいことがあります。基本的に、屋外での利用を前提とした製品となります。 まとめ 小型・軽量な端末で、簡単にRTK測位による高精度な位置情報を計測できるMobile GNSSは、単体でも十分な機能を提供する製品だと感じました。 更に話を発展させると、例えば制御情報(CAN等)や生体情報(心拍数等)と高精度な位置情報を同時に取りたい、といった要望になった場合は、intdashをデータハブにした方式も提案できそうだと感じました。
アバター
aptpod Advent Calendar 2023 12月1日の記事です。 みなさまお久しぶりです。アプトポッドで営業企画をしている神前(こうさき)と申します。 前回の登場 からちょうど1年ですね。 これで3年連続でAdvent Calendarのトップバッターを飾ることと相成りました。 3年連続でCTOから依頼を受けるの図 去年の記事でも触れてますが、昨年12月に事業部に異動となり、今日でちょうど1年でもあります。 その1年の中でもメインの業務がタイトルにもあるSalesforceの導入だったのでそのことについて書いていきたいと思います。 「これから自社でSalesforceを導入しようかな」、「色んなサービスを使っているけど一つにまとめたいな」という人がもしいたら参考になるかもしれません。 当時の状況 導入プロジェクトの立ち上げ 主にやったこと 苦労したこと フロー(と役に立ちそうな事例) 売上を把握するためのフロー Salesforceを導入してみて 今後の課題 参考にした記事等 当時の状況 さて、ではそもそもの始まりあたりから書いていきたいと思います。 実は、というほどでもないのですが、Salesforceを導入しようという話自体はいまから約2年前くらいからあがってはいました。 その当時は何かしらSFAを導入しよう、であればSalesforceも候補の一つだね、という感じでしたが、あくまでSFAの導入という文脈であったことや、金額面やその他の事情も重なり、他のSFAを導入することとなったのです。 しかし、実際にSFAを導入して運用を開始すると、もちろんそれでよくなった面も大幅にあった一方で、今度は他のシステム周りとの連携面が課題としてあがってきました。そして、それを皮切りに、「そもそもうちは色んなシステムを入れてるけども、連携してるものもあればそうでないものもあって、結構不便なことが多いよね」となっていきます。 弊社も15年以上の歴史があるため、その長い時間の中で様々なシステムが導入されるものの、それは局所最適化や金額面といったミクロな理由からの導入が多く、全体最適にはほど遠い状態だったのです。 事業部に関連した話で行くと、例えばこんな不便な事案が発生していました。 SFAを導入し、案件の管理は楽になったが、見積書や請求書はERPで作成する、かつ、SFAとERPが連携していないためそれぞれに案件や商品のデータを毎回いれないといけない(データの二重入力)。 案件の議事録は別の社内wikiに記録していたため、詳細を知りたければそちらに飛ぶ必要がある(データの分散) 勤怠入力のシステムと工数を登録するシステムが別で、かつ、連携していないため、目検で月の稼働時間がちゃんとあってるか確認する必要がある(データの整合性) この他にも様々な、「一つ一つは小さいけども、積み重なるととてつもない無駄」が各所で発生している状況でした。 こうした背景に加えて、「各種数値をレポート化できるのはいいけども、小回りがきかないからcsvで吐き出してスプレッドシートで加工する必要がある」、「各種項目に小回りが利かない」といったSFAそのものへの不便さも加わり、さらにカスタマーサクセス部門の立ち上げと、それに伴う顧客管理や問い合わせへの対応の実現をきっかけに、「だったらいっそのこと前々からリプレイスしたかったERPも含めて全体最適ができるようにしよう」となっていったのでした。 導入プロジェクトの立ち上げ といっても立ち上げ自体に私は参加しておらず(そういうプロジェクトを立ち上げるよー、とは事前に聞いてはいましたが)、途中から参加した形になります(立ち上げのわりとすぐ後ではあるけど)。 (自分に関連するところを中心に)時系列でいうと 3月:管理部を中心にツールの選定と各企業からヒアリング 4月:社内での稟議承認。プロジェクトに神前参加。 5月:正式にプロジェクトがスタート。 6月:パートナーさんも含めてSFA、CRM構築のキックオフ 6~9月:SFA、CRMの構築 9月:事業部内でのSalesforceプレ運用開始 10月:旧SFAからSalesforceにSFAを完全移行。全社で運用開始。 という感じです。 私以外のメンバーもそれぞれの部分(勤怠周りとか会計周りとか)を担当していた形です。 主にやったこと といってもそんなに大げさなことはやってはいません。 まずはこれまで使っていたSFAの使用感と似たようなものにするため項目を再現。その中で、「作ったものの、もう使われていない項目」を削除したり「今後のことを考えるとあったほうがいい項目」を追加したり、というのを現場からヒアリングしつつ構築。 その後にデータの流し込みを実施。 標準機能にないものをフローで作成。 SFA移行に伴う案内や、操作マニュアルの作成。 といった具合です。 他にも細々としたことはやっていますが、大きく言うとこんな感じです。 ただし、それは今だから言えること(今だから簡単にできること)であって、当初はだいぶ苦労しました。 以下にいくつかピックアップしてみます。 苦労したこと ここから書くことはSalesforceの導入を体験した方であれば「あるある」でしょうし、これからの人にとっても役に立つ情報かなと思います(というか、そうであってほしい)。 苦労したことでいうといくつかあるのですが、とにかくまず苦労する部分であり、それでいてそこを乗り越えれば楽しくなってくる部分というのが「Salesforceのデータ構造の理解(という表現が正しいかはわかりませんが)」かなと思います。 Salesforceでは、商談(弊社では「案件」と名前を変えてますが)、取引先、担当者、商品、etc.といった具合に、それぞれが「オブジェクト」という箱にデータとしては収まっています。そのため、商談(案件)を登録するのにも色々なところからデータをひっぱってきています。 それまで使っていたSFAでももちろん「案件」、「取引先」といったように分かれてはいたのですが、Salesforceの場合はより細く、より複雑に色々なデータが絡んでいるため、どこにどのデータが収まっているのかがわからず、最初はほんとに手探りでだいぶ苦労をしました。 特に商品については複雑で、商品の一覧としての「商品」、商品の価格のリストである「価格表」、商品と価格表を結ぶ「価格表エントリ」に分かれていますし、さらに商談に紐づくものは「商談商品」となっています。慣れてくれば別ですが、「この項目を変えたい」、「この項目を増やしたい」といったときに、どのオブジェクトをいじれば自分のやりたいことが実現できるのか、というのはとにかく色々触って慣れるまで大変な部分です。 逆に、慣れてくると、「ここを変えようと思ったらここをいじればよさそうだな」とアタリがついてくるので、すぐにやりたいことができるようになってだいぶ楽しくなってきます。 これから導入や構築をするぞ、という人にとってはここが大変でしょうけども、ここの苦労は最初にしておいたほうがよいポイントです。構築に際してはSalesforceのパートナーさんがお手伝いをしてくることがほとんどだと思いますが、丸投げにせずに、自分でやれるようにしておくほうが後々のカスタマイズを考えると確実によいでしょう。 他にもフローもだいぶ苦労をしたのですが、それは次項にて。 フロー(と役に立ちそうな事例) Salesforceにおけるフローとは、例えば画面上のとあるボタンを押下すると何かしらの自動処理が走る、なにかデータを登録するとそれをトリガーに処理が走る、といった「処理の自動化」のことを指します。 かなり自由度が高く、色々なことを自動化することができるのですが、ノーコードとはいえすぐに習熟できるものではなく、特に私のようなプログラミングの経験がない人間からするとだいぶハードルが高く感じる機能ではあります(その分、プログラミング経験者からすると操作しやすく、自由になんでもできる便利な機能だと思います)。 いまでは簡単なものであればすぐにフローを作れるようになりましたが、ここもマスターしようと思うとだいぶ苦労するポイントだと思います。 折角なのでサンプル事例をのせておきたいと思います。ネットで探してもほぼ情報がなかったのですが、わりとニーズ自体はあるフローではないかな、と思います。 売上を把握するためのフロー 商談を管理していれば、当然ですが契約金額、契約予定日も把握できていると思います。商談Aは2023年の12月末に受注(契約)予定で、金額は1,000万円、という感じですね。 一方で、「売上」となるとこれはSalesforceの標準機能では管理できません。つまり、この商談Aの1,000万円がいつ入金されるのか、会計上はどう処理するのか、という観点ですね(商談Aの受注は12月だけど、納品は翌年の3月なので、売上は3月に1,000万、といった具合)。 営業組織であればあまりこの「売上」を意識することはなく、受注金額と契約時期を意識することのほうがほとんどだと思います。逆に、経営層は「売上」を意識し、受注金額や契約時期を意識しない場合がほとんどではないかと思います。 弊社では、この「受注金額」と「売上」の両方をSalesforce上で管理、レポートで可視化をできるようにする必要があったためそこの対応をすすめました。 Salesforceでは、売上を標準では管理できず、「スケジュール」という機能を使う必要があります。 スケジュール機能については以下のページを参照ください。 商品スケジュールの設定方法 – Salesforce大技林 sfblog.markhammer.net このスケジュールを活用することで、たとえばサブスク系の商品の売上を管理できるようになります(仮に、100,000円/月のサブスク商品があり、1年分を2023年12月に契約すると、受注金額は12月に1,200,000円だけど、売上的には12月に100,000円、1月に100,000円、2月に100,000円・・・となる)。 しかし、このままでは商談に紐づく商品一つ一つに手動でスケジュールを設定しなければならず、実際に商談を登録する営業メンバーからするととても手間がかかるため現実的ではないですし、漏れも確実にでて、しかもそれに気付くのも難しいです。 そこで、商談にスケジュールが必要な商品が登録されたら自動でスケジュールを設定するフローを作成しました。また、商談は日々変化をし、商談に紐づく商品が変わったり、同じ商品でも金額や数量、納期がかわることも多々あるため、特定の条件を満たした場合、既に設定されていたスケジュールを削除し、再度スケジュールを設定する、というフローも合わせて作成しています。これで営業のメンバーはスケジュールをほぼ意識することなく、それでいて売上データも管理することが可能になりました。 フローの一部 細かい説明はここではしませんが、このフローは小さなフローを3つと大きなフロー2つを組み合わせています(まとめて全体の数を減らすこともできると思います)。ざっくり説明すると、商談に特定の商品を追加した場合、もしくはすでに登録されている商品の特定の項目(数量や価格等)が変更された際に隠し項目にチェックをいれ(小フローの①と②)、そのチェックをトリガーに商談の中にある隠し項目にチェックをいれます(小フロー③)。このチェックをさらにトリガーとして、商談に紐づく商品のスケジュールをすべて削除し(大フロー①)、そのあとにスケジュールを設定する(大フロー②)、という構造です。 レポートで集計をする際は受注金額と売上金額とでそれぞれ別のレポートタイプを使う必要がありますが、営業メンバー向けの受注金額をベースとしたレポートと経営層向けの売上を中心としたレポートをそれぞれ作成することができるのでとても便利です。 ※本フローの作成にはパートナーさんにもお手伝いいただきました。 Salesforceを導入してみて そろそろまとめに入りますが、Salesforceを導入してみてよかったのは、とにかく自由度が高い(その分使いこなせないとだめですが・・・)ため、ちょっとしたことを自動化したり、各種データを様々に集計したりということがかなり楽になりました。 また、当初の目的でもあった各種システムとの連携も実現できているため、データの二重入力や、csvに吐き出してからスプレッドシートで加工する、といった手間も大幅に削除できています(完全に、とはいきませんが)。 まだ本格運用を始めてから2ヶ月程度なので実際にどれだけの工数を削減できたのか、といったところまではデータとしてはとれていませんが、体感値でいえば以前に比べると様々な業務が楽になったと感じています。 今後の課題 便利さの反面として、Salesforceに詳しい人間が弊社社内にまだまだ少ないのが現状です。また、まだまだ使い倒せる機能が多くあり、改善の余地がかなり残されています。 加えてですが、システムそのものが便利にはなったものの、一方で、(管理側とは別に)使いこなせる人が少ないことも課題の一つです。便利なツールがあっても、使いこなせる人がいなければ宝の持ち腐れです。まだまだ現状では「こういうレポートがほしいんだけど作ってくれない?」という依頼がちょこちょこ来るのが現状で、それでは本質的にはあまり意味がありません。だれでも自分のほしいデータにアクセスし、レポートとして作成し、自身の業務に活用する、というところまでいって初めてSalesforce導入の真価が発揮されるのだと思います。 システム管理者としては、使い勝手や機能の改善と同時に、使いこなせる人を社内に増やしていく、というこれからの方がむしろ本番とさえいえそうです。 それではみなさまよいSalesforceライフをお楽しみください。 参考にした記事等 successjp.salesforce.com まずは公式のものを見るのがよいです。 blog.logical.co.jp スケジュールを設定するフローはこのフローをベースとして作成しています。 blog.logical.co.jp こちらもあると結構便利なフローです。 sf.forum.circlace.com slackとの連携も便利です。
アバター
はじめに アプトポッド 開発本部の影山です。 2023年11月8日(水),11月9日(木)にパシフィコ横浜で開催された、 横浜ロボットワールド2023 に出展しました。 連日、多くの方々にご来場いただき、感謝申し上げます。 www.srobo.jp 弊社ブースの外観 この記事では展示したデモの1つである 四足歩行ロボット Unitree Go1 を使った遠隔操縦デモ について、紹介をしたいと思います。 techshare.co.jp デモの概要 弊社では、 intdash をコアとした、モビリティやロボットのリアルタイムでインタラクティブな管制制御システムを実現する intdash CONTROL CENTER を提案しており、その中に遠隔操作の機能も含まれております。 今回は、弊社のintdashサーバを経由して、遠隔でUnitree Go1を操作するデモを展示しました。 www.aptpod.co.jp www.aptpod.co.jp 利用シーンの例として、工場やプラントにおける警備、点検等があります。 サーバ間で連携し、AI処理をすることによって、例えば人物を検出したり、メーターの読み取り自動化を実現します。 Unitree Go1 デモ デモ構成 簡単に今回のデモの内容を説明します。 今回のデモでは、intdashを経由してUnitree Go1をDualSenseコントローラを使って遠隔で操作できることを主体にお見せしています。 例えばロボットが監視巡回している最中に、何か問題に遭遇した際、オペレータが管制室から手動の遠隔操作で周囲を見て回るようなケースを想像していただければと思います。 会場ではその場で操作していたので、直接UnitreeGo1と通信しているように見えるかもしれませんが、実際は制御の信号をintdashサーバにインターネットを経由して送信して、その信号をUnitreeGo1もまたインターネットを経由して受信して動作しています。 そのため、オペレータはインターネットに接続できる環境であれば、どこにいても操作が可能になります。 UnitreeGo1の状態や、主観カメラの様子も、弊社のダッシュボード画面をブラウザから開けば、リアルタイムに確認しつつ操作可能です。 では、具体的にどのようにして環境を構築したのかは、下の構成図を参照ください。 デモのシステム構成図 現地には、UnitreeGo1を主体に、コントローラからの信号を送信するRaspberry Piと、会場を様子を撮影するRaspberry Piを設置しています。UnitreeGo1にもintdashに接続するエージェントソフトをインストールして、ROSで取得したステータス情報や、カメラの映像をintdashに送信しつつ、コントローラからの制御信号を受信して、機体の制御に反映させています。 またより具体的なユースケースを想定して、共同出展しておりましたNTTコミュニケーションズ様が提供しているAI顔認証ソフトウェアのSAFR®による人物認識も同時に連携しています。SAFRに対して、リアルタイムでintdashから取得したUnitreeGo1のカメラ映像を入力して、検知した結果を画面上に枠線でアノテーションして、intdashに送り返しています。 これらすべての情報は、ダッシュボード上でリアルタイムに確認できます。また過去の記録も履歴から遡ってリプレイも可能になっています。 デモを構築してみて 今回のデモ構築を経験して、以下のような気付きがありました。 UnitreeGo1が想像以上に柔軟に操作できた ROSを利用して、簡単に制御ができました。Jetsonが複数搭載されているので、色々開発の余地も大きいです。 遅延もあまり気にならない 操作に対するUnitreeGo1のレスポンスも素早く感じました。intdashを利用した遠隔制御はもともと遅延が少ないことが特徴の一つなので、UnitreeGo1と組み合わせても、十分実用的と感じました。 技術的には以下のような点も今後深堀りできればと考えています。 自律走行 当日のお客様の声でも自律走行と組み合わせた運用を想定されているケースが多く感じました。UnitreeGo1はLiDARを搭載することも可能なので、そのようなユースケースでもROSなどを活用して自律走行と組み合わせたシナリオもお見せできれば、より利用シーンをイメージしてもらいやすくなるかと考えています。 ネットワーク環境に合わせた制御 UnitreeGo1は自由にどこにでも行ける性能を持っているので、遠隔制御時に通信に問題があった際のケアもきちんとしてあげないと、勝手に変な挙動をして思わぬトラブルが発生することもありえることを実際に開発して理解できました。 そのようなケースに対する対応もより検討を深めたいです。 まとめ 横浜ロボットワールド2023でご紹介した四足歩行ロボット Unitree Go1 を使った 遠隔操縦デモについて紹介しました。 「操作に対するロボットのレスポンスがはやい!」などご意見いただき、大変好評でした。 人手で行っていた業務をロボットで行いたい ロボットの遠隔操作を行いたい 大量データを扱えるハイパフォーマンスな可視化アプリケーションを開発したい などなど、アプトポッドではIoTに関する豊富な実績と高い技術力で、お客様の課題解決にご協力いたします! お気軽にお問合せください。 お問合せフォームはこちら https://www.aptpod.co.jp/contact/
アバター
ネイティブアプリケーション開発を担当している上野です。 前回の記事 で弊社サービスである intdash を用いたデータ伝送がUnityで扱えるようになったとお伝えしましたが今回はAndroidアプリ開発などで利用されている開発言語である Kotlin でも利用可能になりましたのでそのご紹介になります。 今回公開したもの iSCP 2.0 Client Library for Kotlin について intdash REST API クライアント について THETA iSCP Plugin について 開発したサンプルを動かしてみた レイテンシ比較 ミラーリング(scrcpy) iSCP+Visual M2M Data Visualizer RTSP+ffplay 最終結果 最後に 弊社ビジネスのご紹介 今回公開したもの 今回公開したものは、以下の3つです。 iSCP 2.0 Client Library for Kotlin Kotlin向け intdash REST API クライアント THETA iSCP Plugin iSCP 2.0 Client Library for Kotlin について iSCP 2.0 Client Library for Kotlin (※以下iscp-kt) は弊社の独自プロトコル iSCP(intdash Stream Control Protocol) を用いてintdashサーバーへデータ伝送が可能になるクライアントライブラリの Kotlin版 です。 Kotlin版といいつつもKotlinはJavaへの互換性をもっており、Javaコードからもこのライブラリを利用する事も可能です。ライブラリはJARファイルで生成されており、Mavenリポジトリ形式でGithub Pagesに設置しました。ですので依存関係さえクリアできればAndroid以外のJavaプラットフォームでも利用可能です。 ライブラリの参照方法はAndroidの場合、以下の様に .gradle ファイルにMavenリポジトリのパスと参照するライブラリを設定すれば利用可能です。 // settings.gradle ... dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() // Library references for iSCP maven { url "https://aptpod.github.io/iscp-kt" } // <- 追加 } } // app/build.gradle ... dependencies { ... // Install iSCP implementation ' com.aptpod.github:iscp:0.11.0 ' // <- 追加 } iscp-ktの最低Kotlinバージョンは 1.8.20 です。プロジェクトで利用するKotlinバージョンがそれ以上かどうか確認する必要があります。 // build.gradle plugins { id 'com.android.application' version '8.0.2' apply false id 'com.android.library' version '8.0.2' apply false id 'org.jetbrains.kotlin.android' version '1.8.20' apply false // <- 確認 id 'org.jetbrains.kotlin.jvm' version '1.8.20' apply false // <- 確認 } 実装方法に関しては ドキュメント を参照して頂くか、同じく公開したTHETA iSCP Pluginプロジェクト内のテストコードに RealtimeApiTest.kt が実装されています。 // RealtimeApiTest.kt ... @RunWith (AndroidJUnit4 :: class ) class RealtimeApiTest { companion object { const val URL_API = "https://example.intdash.jp" const val ADDRESS = "example.intdash.jp" const val NODE_ID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" const val NODE_SECRET = "xxxxxxxxxx" } ... ソースコードの定数にintdashサーバーと送信するノードの情報を入力する所があるのでそれらを修正して実行するだけでデータの送信を試すことも可能です。 intdash REST API クライアント について Kotlin向け intdash REST API クライアント は intdashサーバーとのデータ伝送には認証情報の発行等が必要な為、それらを行うことができるREST APIクライアントの生成方法やその他のAPIの使用例が記載してあります。 THETA iSCP Pluginでは既にAPI クライアントをJavaプロジェクトとして生成した物を含めています。注意点としては現状 OpenAPI Generator からAPI クライアントを生成する際にKotlinとしては出力していません。現状Kotlinのみのコードで出力ができず、Javaとして出力してもKotlinコードから呼び出すことが出来るからです。 openapi-generator-cli generate -i openapi_public.yaml -g java -o intdash --additional-properties=library=okhttp-gson,apiPackage=com.aptpod.intdash,groupId=com.aptpod,artifactId=intdash,sourceFolder=src/main/java,disallowAdditionalPropertiesIfNotPresent=false,dateLibrary=legacy また、生成コマンドも ドキュメント に書かれているコマンドと若干変えており、 dateLibrary=legacy を追加しています。こちらは検証に利用したTHETA VのAndroid APIバージョンが25で若干古く、日付管理系のクラスが一部利用できなかった為です。APIを利用する際、日時として利用するクラスが java.time.ZonedDateTime から java.util.Date となり、マイクロ秒以下の時間指定が出来なくなってしまうので注意が必要です。 THETA iSCP Plugin について THETA iSCP Plugin はタイトルにもある通りAndroidOSでintdash対応アプリケーション開発が可能になったのでその1例として開発した物になります。 RICHO THETA はAndroidOSで動いている360°カメラデバイスで開発したアプリをプラグインとしてインストールする事が可能です。 プラグイン l RICOH360 Blog 今回は会社にTHETA Vがあったので開発したiscp-ktをプラグインとして組み込みintdashサーバーへ360°画像(H.264形式)をストリーミングするサンプルを公開する事にしました。 ※THETA V以外のTHETAでもプラグインを動作させる事ができる可能性はありますがTHETA Vのみしか検証できていません。 以下は、セットアップ方法になります。詳細は README に記載してあります。 THETAにプラグインをインストールするにはTHETAを開発者モードする必要があります。また開発者モードにするには RICOH THETA プラグイン パートナープログラム に登録する必要があります。 qiita.com 上記を参考にパートナープログラムへの登録は こちら より行いました。 THETAが開発者モードになり、プラグインをインストールできるようになりましたらプロジェクトをリポジトリよりクローンしてAndroid Studioで実行して頂くか、 Releases よりプラグインのapkファイルと設定ファイルをダウンロードしてセットアップが可能です。 { " intdash " : { " server_url " : " https://example.com ", " server_path " : " /api ", " node_client_id " : " 00000000-0000-0000-0000-000000000000 ", " node_client_secret " : " XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ", " save_to_server " : false } , " video " : { " enabled " : true , " resolution " : { // THETA V supported resolutions: [ 3840x1920, 1920x960, 1024x512, 640x320 ] " width " : 1920 , " height " : 960 } , " sample_rate " : 29.97 , // THETA V's frame rate is fixed at 29.97 fps. " encode_rate " : 15 , // Frame rate to be encoded and transmitted. " bit_rate " : 2000000 , " i_frame_interval " : 2 } } 設定ファイルである iscp_plugin_settings.json にはintdashサーバーへデータをストリーミングする設定と送信する360°画像の解像度やビットレート、送信するレート( encode_rate ) などの設定が可能です。 公開したソースコードで一部 TODO としている部分があります。THETAはマイクが内臓されており、音声の収集が可能です。さらに最近のスマートフォンでは無くなってきているイヤホンジャックもついているのでお手持ちのマイクなどを利用しても収音できるかなと考えていましたが、一般的なAndroidアプリでPCMなどの生データを拾うことが可能な android.media.AudioRecord であったりOpenSL ESを利用している Oboe などのライブラリを使用してみたりしましたが、指定したサンプリングレート通りに音声データが集まらなかったり、ノイズがひどかったので今回の公開内容には混ぜておりません。手持ちのTHETA Vの調子が悪かったのかもしくはTHETA Vは現在は製造中止となっているようで新しい機種のTHETAであればもしかすると対応可能なのかもしれません。 ※2023/09検証時THETA Vのファームウェアバージョンは 3.82.1 。 開発したサンプルを動かしてみた 電源を入れたら側面のモードボタンを長押しすることでプラグインが起動します。THETA iSCP Pluginのデータの送信開始・停止の方法は端末中央のシャッターボタンを押すだけです。 youtu.be 設定さえ行えてしまえば簡単にデータの送信ができることがお分かりいただけるかと思います。そして体感ですが遅延も大きくは感じられません。 また、私が開発を担当している VM2M Stream Video では360°画像の可視化が標準サポートされているので手元にiPhoneやiPadがある方限定にはなりますが可視化までお手軽にお試しいただけます。 構成は図で表すと以下のようになっております。 THETA iSCP Plugin 可視化例 ネットワーク環境さえ用意できればTHETA単体で簡単に360°動画のストリーミングができるので便利だなと思っています。 レイテンシ比較 参考までにどの程度レイテンシがあるか計測してみます。スマートフォンにミリ秒単位で表示できる時計アプリを起動しTHETA Vで撮影しつつ、いくつかの可視化方法で可視化されるまでの時間を確認してみました。 ミラーリング(scrcpy) 初めにTHETAを scrcpy というAndroidのミラーリングアプリでWindowsパソコンにミラーリングしたものをカメラで撮影してみました。ミラーリングはUSBケーブル経由で行っています。 現実世界とミラーリング画面との差 時計が表示されたスマートフォンの画面とWindowsパソコンに表示されたミラーリング画面を見比べてみると大体 200ミリ秒 程度のレイテンシであることが分かります。 構成は以下の通りです。 ミラーリング構成図 iSCP+Visual M2M Data Visualizer youtu.be 続いて上の動画のリンクではWindowsパソコンの画面をキャプチャしたもので左側の画面が弊社の製品である Visual M2M Data Visualizer を表示したもので、右側がミラーリング画面になります。 Visual M2M Data Visualizerとミラーリング画面との差 秒のカウントは同じでミラーリングしている画面との差はおおよそ 50~60ミリ秒 程度でしょうか、Visual M2M Data Visualizer はインターネット経由で映像を可視化しているにも関わらず有線接続して可視化している画面と大差がありません。 構成は以下の通りです。 iSCP+Visual M2M Data Visualizer 構成図 RTSP+ffplay youtu.be 最後に比較対象として同じくWindowsパソコンの画面をキャプチャしたものですが、THETAで起動しているプラグインを THETA RTSP Streaming というTHETAの映像をRTSP経由で配信できるプラグインで確認してみました。左側で可視化しているアプリは ffplay で可視化しています。 ffplayとミラーリング画面との差 ミリ秒以下だけみると同じく60ミリ秒程度の遅延かと思いきや 1秒 遅れています。 参考までに THETA RTSP Streaming はGithubに開発プロジェクトが公開されており、今回開発したプラグインの画像のエンコードまでの処理とほとんど同じとなっており、違いとしては伝送プロトコルと可視化ツールの違いのみとなります。 構成は以下の通りです。 RTSP + ffplay 構成図 最終結果 最終的な結果は以下のグラフの通りとなっております。 レイテンシ比較結果 ミラーリング画面のレイテンシを加味して、撮影をした実時間とVisual M2M Data Visualizerで可視化されるまでの差は 250~260ミリ秒 程度のレイテンシで可視化できていそうです。 撮影場所はWiFiの電波の入りが若干悪い会社のエントランスで検証したのですが、自宅のWiFi環境ではもう少し早く 220~230ミリ秒 程度のレイテンシで可視化できていたのでWiFiルーターの性能やネットワーク環境にも依存しそうです。 最後に ここまででintdashのを使うことでリアルタイム性はご理解いただけたと思いますがintdashは単にデータストリーミングするプロトコルで終わらず、ストリーミングしたデータをクラウドへ保存することも可能です。また、保存したデータは時系列データとして処理しており1つ1つのデータに時間情報を持たせている為、後から送信した通りにデータをリプレイ再生したり、集計を行うことも可能です。 今回は会社で既に所持していたTHETA Vを利用しての実験的な実装にはなりましたが、通常のAndroidスマートフォンなどで実装してもよいですし、 最新機種のTHETA Xでは端末に液晶が付いたことにより設定や操作が楽になったり、GPSも搭載されたようでより収集可能なデータも増える可能性がありそうです。 www.ricoh360.com 弊社ビジネスのご紹介 アプトポッドでは、IoTミドルウェア intdash の開発と、intdsahを活用したIoTシステムの構築を事業としています。 intdashは、あらゆるIoTデータを収集、伝送、管理、活用することができ、IoTデータを活用するさまざまなサービスのバックエンドとしてご活用頂いております。 www.aptpod.co.jp IoTデータを利用したプラットフォーム、IoTサービスの開発や、リアルタイムデジタルツイン、製造現場のDX化など、IoTシステムの開発でお困りのことがあれば、ぜひ弊社までお声がけください。 弊社の問い合わせフォームは こちら です。 www.aptpod.co.jp
アバター
はじめに アプトポッドVPoPの岩田です。 昨日、浅草の都立産業技術センター台東館にて行われた ROSConJP 2023 にて、シルバースポンサーとしてブース出展をしてまいりました。ブースでは、当社の主力製品であるIoTプラットフォームミドルウェアintdashをROS開発に応用した、ROS開発ワークフローの効率化パッケージについてご紹介しました。 YouTubeのリアルタイム配信をご覧になられた方は見ていただけたかもしれませんが、当社エンジニアの影山により「Open-RMFを応用したクラウドフリート管理システムの構築」の登壇を行ったり、私自身もライトニングトークでお時間をいただき掲題の「ROS開発の効率化パッケージ」についてご紹介したり、情報発信としても有意義な機会とすることができたと思います。 本投稿では、当日の出展ブースの内容や情報発信の内容について、ご報告させていただきます。 当日の弊社ブースの様子 会場の様子 会場では、自社デバイスのROS対応を検討されているデバイスメーカー様から、ロボットを開発されているロボットメーカー様、ロボットを活用したサービスを探しに来られたユーザー企業様まで、様々な方々とお話させていただくことができました。全体の司会進行をされていた東京大学 高瀬先生をはじめ大学の先生も何名か参加されており、まさにここが日本のROSコミュニティの中心なのだなと実感することができました。 また、ROSConというだけあって皆様当然のようにROSについてはよくご存知で参加されている方もエンジニアの方が多かったので、技術にかなりディープダイブしてお話させていただくことができ、普段の展示会とはまた違った雰囲気となりました。 出展ブースの内容 ブースでは、当社の主力製品である IoTプラットフォームミドルウェア intdash をROS開発に応用した、ROS開発ワークフローの効率化パッケージについてご紹介しました。こちらは、これまでもご提供していたintdashにROS開発に便利なツール群を追加したROS開発者向けのDXソリューションです。 当日掲示したポスター「ROS開発を効率化するクラウドソリューション」 こちらのソリューションについては、ライトニングトークでもご紹介させていただきました。当日のライトニングトークの動画やプレゼン資料は、ROSConJP 公式サイトでも公開されていますが、こちらにも掲載しておきます。 資料左下に画像がありますが、こちらのソリューションの公開に合わせて Visual M2M Data Visualizer についてもROSデータの可視化、特に「2D/3D点群の可視化」に対応するなど、機能強化を予定しております。 また資料中にも記載しております通り、本ソリューションのリリースは11月ごろを予定しております。 リリースの際には無償のトライアルプログラムも予定しておりますので、ご興味お持ちいただけましたら、こちらの登録フォームより是非事前のご登録をお願い致します。 forms.gle ライトニングトークの様子 登壇の内容 登壇では、当社の組み込みエンジニアの影山がOpen-RMFを実際に使用したフリート管理システムの構築にトライした経験談をご紹介させていただきました。(当日のプログラムは ROSConJP 2023 公式から 確認できます) Open-RMFを応用したクラウドフリート管理システムの構築 弊社、株式会社アプトポッドでは、独自のリアルタイム伝送プロトコルをベースにクラウドから利用できるフリート等の遠隔制御、情報収集のシステムを開発してきましたが、単体のみならず複数のフリート管理機能に対応しようとしたときに、独自にゼロから関連する機能を開発することは容易ではありません。弊社ではOpen-RMFを利用してその課題に対処しようとしました。本発表ではOpen-RMFを利用して試作したモビリティ/ロボット群管理システムについて紹介します。 Open-RMFに関する登壇の様子 直前の登壇で Panasonic Asia Pacific Pte. Ltd. の方が、Open-RMF の使い方に関する基礎的な内容についてかなり詳しく説明してくださったため、それに続く登壇として、実際に使ってみた弊社の体験談が、オーディエンスの皆様にはより伝わりやすかったのではないでしょうか。後ほど資料や動画公開されましたら、是非2つセットで見ていただければと思います。 ★★ 後日更新 ★★ ROSConJP 2023公式に、スライドの内容とビデオが公開されました! 自律移動ロボット(AMR)のOpen-RMFへの対応方法( スライド / ビデオ ) Open-RMFを応用したクラウドフリート管理システムの構築( スライド / ビデオ ) また、弊社資料は SpeakerDeck にもアップロードしてあります。 speakerdeck.com おわりに 都立産業技術センター台東館にて行われた ROSConJP 2023 にて、シルバースポンサーとしてブースを出展しました。ブースでは、当社の主力製品であるIoTプラットフォームミドルウェアintdashをROS開発に応用した、ROS開発ワークフローの効率化パッケージについてご紹介しました。 本ソリューションのリリースは11月ごろを予定しておりますが、リリースの際に改めてご案内をさせていただきますので、 事前申込フォーム より是非ご登録ください。 ROSConJP 公式からも、当日の中継動画や資料は公開される予定のようですので、公開されましたら適宜こちらの投稿にもリンク掲載いたします。 ROS関連 Tips 連載のご紹介 現在、こちらの記事にて、ROS関連Tipsの連載を行っています。 ご興味ございましたら、是非ご覧ください。 tech.aptpod.co.jp 投稿済み & 投稿予定コンテンツ そもそもROSとは? ROS開発におけるDocker活用テクニック ROSのDockerコンテナからNVIDIA GPUを利用するには 大量伝送シナリオにおけるROS/DDSのチューニング
アバター
アプトポッド組み込みエンジニアの久保田です。 近年、ロボットやモビリティを動作させるためのプラットフォームとしてROSを採用することが多くなってきています。 通常、ROSは特定のUbuntuバージョンに対応したディストリビューションとしてリリースされていますので、ROSのディストリビューションを変更したい場合は、ホストOSも変更する必要があります。この制約を回避する方法として、Dockerというコンテナ技術を使う方法があります。Dockerを使えば、ホストOSを変更せず様々なROSディストリビューションを動かすことができるようになります。 また、Dockerの利用はホストOSのアップデートが難しいプラットフォームでROSを利用する際にも効果的です。例えば、当社で販売している車載向けエッジコンピュータEDGEPLANT T1はNVIDIA Jetson TX2を搭載していますが、JetsonシリーズはホストOSのアップデートが難しいため、使用可能なROSのディストリビューションを自由に選択することができません。Dockerコンテナを利用することにより様々なROSディストリビューションを動作させることができます。 連載ROS Tips第2回目となる今回は、ROS開発に便利なDockerコンテナの活用テクニックを紹介します。 なお、連載の予定として、以下のようなコンテンツを予定しております。(連載内容は、変更・追加の可能性があります。ご了承ください) そもそもROSとは? ROS開発におけるDocker活用テクニック (本記事) ROSのDockerコンテナからNVIDIA GPUを利用するには 大量伝送シナリオにおけるROS/DDSのチューニング 本連載の投稿済みの記事はこちらからご覧いただけます。 tech.aptpod.co.jp tech.aptpod.co.jp Dockerとは ROS Dockerコンテナイメージ DockerコンテナでROSを実行する Docker活用テクニック① コンテナ間ネットワークの設定 ホスト内通信 (同一筐体内通信) ホスト間通信 (別筐体間通信) Docker活用テクニック② Docker Composeで複数コンテナを起動する Docker活用テクニック③ コンテナでGUIを利用する Docker活用テクニック④ コンテナ内からWebカメラの映像を取得する まとめ 当社プロダクトのご案内 Dockerとは Dockerは、アプリケーションとその動作に必要なすべてのファイルを「コンテナ」というパッケージにまとめる技術です。このコンテナは「仮想化」を利用して、異なる環境でも一貫した動作を実現します。つまり、Dockerは「どこでも同じ動きをするアプリケーション」を作るためのツールであり、その背後には仮想化技術が活用されています。 What is a Container? | Docker より ROSをDockerで利用する際のメリットとデメリットは次の通りです。 メリット: 環境の統一 : Dockerを使用すると、ROSの環境をコンテナ内に構築できるため、開発者間での環境の差異を気にすることなく、一貫した環境で作業することができます。 移植性 : Dockerコンテナは、異なるマシンやクラウド環境でも動作します。これにより、ROSのアプリケーションを簡単に移植やデプロイが可能となります。 バージョン管理 : 異なるROSのバージョンを同時に実行することが容易になります。これは、特定のバージョンに依存するプロジェクトを管理する際に便利です。 隔離 : Dockerコンテナはホストシステムから隔離されているため、システムの設定や依存関係を変更してもホストシステムに影響を与えません。 セキュリティ : コンテナの隔離性により、潜在的なセキュリティリスクからホストシステムを保護することができます。 デメリット: オーバーヘッド : Dockerを使用すると、一部のリソースオーバーヘッドが発生する可能性があります。特に、高いリアルタイム性を要求するアプリケーションには影響が出ることがあります。 ハードウェアアクセス : Dockerコンテナはホストのハードウェアに直接アクセスするのが難しい場合があります。これは、特定のロボットハードウェアやセンサーとの連携に制約をもたらすことがあります。 学習コスト : Docker自体の学習や設定が必要です。ROSのみならず、Dockerの知識も必要となります。 ストレージサイズ : コンテナイメージのサイズが大きくなることがあり、ストレージの使用量が増加する可能性があります。 ROS Dockerコンテナイメージ ROSが動作するDockerコンテナイメージは、Open Source Robotics Foundation (OSRF) が公式イメージを提供しています。イメージはROSディストリビューションの配布方法に準じて、core・base・desktopのイメージとして配布されています。 core : ROSメッセージをpub/subできる最低限のパッケージ base : core + ロボットを動かすための最低限のパッケージ desktop : base + GUIを含むパッケージ 詳細については以下のリンク先の情報からご確認いただけます REP 150 -- ROS Melodic and Newer Metapackages (ROS.org) REP 2001 -- ROS 2 Variants (ROS.org) 公式イメージは以下のサイトにて公開されています イメージ提供サイト: Docker Containers for ROS ros - Official Image | Docker Hub 最新の安定版(LTS)ディストリビューションのイメージ一覧 公式イメージとして、各ROSディストリビューションのイメージが公開されています。ここでは、代表的な最新安定版 (LTS) のイメージを紹介します。 ROSディストリビューション イメージ名 イメージに付けられたタグ ROS Noetic ros-core ros:noetic-ros-core ros-base ros:noetic ros-desktop osrf/ros:noetic-desktop ROS 2 Humble ros-core ros:humble-ros-core ros-base ros:humble ros-desktop osrf/ros:humble-desktop (desktopは amd64のみ, arm64の場合、ros-baseイメージにて apt install ros-<distribution name>-desktop を実行することにより同等のイメージとなります ) DockerコンテナでROSを実行する 提供されているDockerコンテナイメージをダウンロードすることにより、簡単にROSを試すことができます。ここでは、簡単なStringのpublish/subscribeを試してみます。 docker/Tutorials/Docker - ROS Wiki ROS Dockerコンテナイメージをダウンロード pullコマンドにて、イメージをダウンロードします。 $ docker pull ros:noetic ROSマスターを起動 runコマンドにて、ROSマスターとなるコンテナ (コンテナ名: rosmaster) を起動します $ docker run -it --rm --name=rosmaster \ --net=host \ ros:noetic \ roscore ... logging to /root/.ros/log/7f4ee758-512e-11ee-862e-00155d66fab1/roslaunch-localhost-1.log Checking log directory for disk usage. This may take a while. Press Ctrl -C to interrupt Done checking log file disk usage. Usage is < 1GB. started roslaunch server http://localhost:40991/ ros_comm version 1 . 16 . 0 SUMMARY ======== PARAMETERS * /rosdistro: noetic * /rosversion: 1 . 16 . 0 NODES auto-starting new master process [ master ] : started with pid [ 32 ] ROS_MASTER_URI =http://localhost:11311/ setting /run_id to 7f4ee758-512e-11ee-862e-00155d66fab1 process [ rosout -1] : started with pid [ 42 ] started core service [ /rosout ] ROSメッセージをpublish runコマンドにて、ROSメッセージをpublishするコンテナ (コンテナ名: rospub) を起動します $ docker run -it --rm --name rospub \ --net=host \ ros:noetic \ rostopic pub -r 1 /my_topic std_msgs/String ' {data: "hello"} ' ROSメッセージをsubscribe runコマンドにて、ROSメッセージをsubscribeするコンテナ (コンテナ名: rossub) を起動します $ docker run -it --rm --name rossub \ --net=host \ ros:noetic \ rostopic echo /my_topic data: " hello " --- data: " hello " --- data: " hello " --- ROS 2 Dockerコンテナイメージをダウンロード pullコマンドにて、イメージをダウンロードします。 $ docker pull ros:humble ROSメッセージをpublish runコマンドにて、ROSメッセージをpublishするコンテナ (コンテナ名: rospub) を起動します $ docker run -it --rm --name rospub \ --net=host \ --ipc=host \ ros:humble \ ros2 topic pub /my_topic std_msgs/msg/String ' {data: "hello"} ' publisher: beginning loop publishing #1: std_msgs.msg.String(data='hello') publishing #2: std_msgs.msg.String(data='hello') publishing #3: std_msgs.msg.String(data='hello') ROSメッセージをsubscribe runコマンドにて、ROSメッセージをsubscribeするコンテナ (コンテナ名: rossub) を起動します $ docker run -it --rm --name rossub \ --net=host \ --ipc=host \ ros:humble \ ros2 topic echo /my_topic data: hello --- data: hello --- data: hello --- Docker活用テクニック① コンテナ間ネットワークの設定 Dockerコンテナはデフォルトでブリッジネットワークを使用します。これはホストOSとは独立したプライベートなネットワーク空間です。コンテナ間では、コンテナの動作している筐体に合わせてネットワーク設定します。 ホスト内通信 (同一筐体内通信) ホスト内通信 ROS ROSマスター用のコンテナを立てて、アプリ側からはブリッジネットワーク内通信によってROSマスターに接続します。各コンテナはコンテナ名で名前解決できますのでROSマスターの指定にはコンテナ名を使用できます。環境変数にて、ROSホスト名(ROS_HOSTNAME)とROSマスターURI(ROS_MASTER_URI)を指定します。 ブリッジネットワーク作成 (ネットワーク名: rosnet) $ docker network create rosnet ROSマスターコンテナ (コンテナ名: rosmaster) コンテナ名がネットワークホスト名となります。ブリッジネットワーク内のROSマスターURIは http://rosmaster:11311 です。 $ docker run -it --rm \ --net=rosnet \ --name rosmaster \ ros:noetic \ roscore ROSアプリケーションコンテナ (コンテナ名: rosapp) コンテナ名がネットワークホスト名となります。ROSホスト名(ROS_HOSTNAME)とコンテナ名を一致させてください。 $ docker run -it --rm \ --net=rosnet \ --env ROS_HOSTNAME =rosapp \ --env ROS_MASTER_URI =http://rosmaster:11311 \ --name rosapp \ ros:noetic \ rostopic pub -r 1 /my_topic std_msgs/String ' {data: "hello"} ' ROS 2 ROS 2通信には、マスターは不要となっています。ホスト内通信ではプロセス間通信を利用するため、IPCの設定 (--ipc=host) をします。 1.1. Leveraging Fast DDS SHM in Docker deployments — Fast DDS 2.13.0 documentation $ docker run -it --rm --name rospub \ --net=host \ --ipc=host \ ros:humble \ ros2 topic pub /my_topic std_msgs/msg/String ' {data: "hello"} ' ホスト間通信 (別筐体間通信) ホスト間通信 ROS ホストのネットワークインターフェースを共有するように設定 ( --net=host ) します。 ROSマスターコンテナ (コンテナ名: rosmaster) ROSマスターが動作している筐体のIPアドレスまたはホスト名を使用します。ここでは、ROSマスターが動作している筐体のIPアドレスを 192.168.0.1 とします。ROSマスターURIは http://192.168.0.1:11311 です。 $ docker run -it --rm \ --net=host \ --name rosmaster \ ros:noetic \ roscore ROSアプリケーションコンテナ (コンテナ名: rosapp) ROSホスト名(ROS_HOSTNAME)にROSアプリケーションが動作している筐体のIPアドレスを設定します。ここでは ROSアプリケーションが動作している筐体のIPアドレスを 192.168.0.2 とします。 $ docker run -it --rm \ --net=host \ --env ROS_HOSTNAME = 192 . 168 . 0 . 2 \ --env ROS_MASTER_URI =http:// 192 . 168 . 0 .1:11311 \ --name rosapp \ ros:noetic \ rostopic pub -r 1 /my_topic std_msgs/String ' {data: "hello"} ' ROS 2 UDP通信の設定をします。コンテナ外との通信となるため、ホストのネットワークインターフェースを共有するように設定 ( --net=host ) します。 ROS 2は通信ミドルウェアに DDS(Data Distribution Service)を採用しており、UDP通信をするためにはDDSヘの設定が必要です。ここでは、DDSが Fast DDS の場合の設定を紹介します。Fast DDSの設定は、設定ファイルfastrtps-profile.xmlを作成し、環境変数 (FASTRTPS_DEFAULT_PROFILES_FILE) で指定します。 6.2. UDP Transport — Fast DDS 2.13.0 documentation 設定ファイル (fastrtps-profile.xml) <? xml version = "1.0" encoding = "UTF-8" ?> <profiles xmlns = "http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles" > <transport_descriptors> <transport_descriptor> <transport_id> CustomUdpTransport </transport_id> <type> UDPv4 </type> </transport_descriptor> </transport_descriptors> <participant profile_name = "participant_profile" is_default_profile = "true" > <rtps> <userTransports> <transport_id> CustomUdpTransport </transport_id> </userTransports> <useBuiltinTransports> false </useBuiltinTransports> </rtps> </participant> </profiles> 設定ファイル反映 & コンテナ起動 $ docker run -it --rm --name rospub \ --net=host \ -e FASTRTPS_DEFAULT_PROFILES_FILE =/tmp/fastrtps-profile.xml \ -v ./fastrtps-profile.xml:/tmp/fastrtps-profile.xml \ ros:humble \ ros2 topic pub /my_topic std_msgs/msg/String ' {data: "hello"} ' Docker活用テクニック② Docker Composeで複数コンテナを起動する Docker Composeとは Docker Composeは、複数のDockerコンテナを定義し、連携させて実行するためのツールです。設定ファイル (docker-compose.yml) に、使用するコンテナの設定やネットワーク、ボリュームの情報などを記述することで、一つのコマンドで複数のコンテナを同時に起動・停止することができます。特に、複数のサービスが連携するアプリケーションの開発やテストにおいて、環境の構築や管理を簡単にするために利用されます。 ここでは、Dockerコンテナ実行で紹介したコマンドをDocker Compose で実行してみます。 docker/Tutorials/Compose - ROS Wiki ROS 設定ファイル (docker-compose.yml) version : '3' networks : rosnet : driver : bridge services : ros-master : container_name : rosmaster image : ros:noetic command : stdbuf -o L roscore networks : - rosnet restart : always ros-pub : container_name : rospub image : ros:noetic depends_on : - ros-master networks : - rosnet restart : always environment : - ROS_HOSTNAME=rospub - ROS_MASTER_URI=http://rosmaster:11311 command : rostopic pub -r 1 /my_topic std_msgs/String "hello" ros-sub : container_name : rossub image : ros:noetic depends_on : - ros-master networks : - rosnet restart : always environment : - ROS_HOSTNAME=rossub - ROS_MASTER_URI=http://rosmaster:11311 command : rostopic echo /my_topic Dockerコンテナ起動 $ docker-compose -f ./docker-compose.yml up [ + ] Building 0 .0s ( 0 / 0 ) [ + ] Running 4 / 4 ✔ Network tmp_rosnet Created 0 .1s ✔ Container rosmaster Created 0 .1s ✔ Container rossub Created 0 .1s ✔ Container rospub Created 0 .1s Attaching to rosmaster, rospub, rossub rossub | data: " hello " rossub | --- rossub | data: " hello " rossub | --- rossub | data: " hello " rossub | --- (※) 停止はCtrl-C Dockerコンテナ削除 $ docker-compose -f ./docker-compose.yml down [ + ] Running 4 / 4 ✔ Container rossub Removed 0 .0s ✔ Container rospub Removed 0 .0s ✔ Container rosmaster Removed 0 .0s ✔ Network tmp_rosnet Removed ROS 2 設定ファイル (docker-compose.yml) version : '3' services : ros-pub : container_name : rospub image : ros:humble network_mode : "host" ipc : host command : > ros2 topic pub /my_topic std_msgs/msg/String '{data: "hello"}' ros-sub : container_name : rossub image : ros:humble network_mode : "host" ipc : host depends_on : - ros-pub command : ros2 topic echo /my_topic Dockerコンテナ起動 $ docker compose -f docker-compose.yml up [ + ] Building 0 .0s ( 0 / 0 ) [ + ] Running 2 / 2 ✔ Container rospub Created 0 .1s ✔ Container rossub Created 0 .0s Attaching to rospub, rossub rospub | publisher: beginning loop rospub | publishing #1: std_msgs.msg.String(data='hello') rospub | rossub | data: hello rossub | --- rospub | publishing #2: std_msgs.msg.String(data='hello') rospub | rossub | data: hello rossub | --- (※) 停止はCtrl-C Dockerコンテナ削除 $ docker compose -f docker-compose.yml down [ + ] Running 2 / 0 ✔ Container rossub Removed 0 .0s ✔ Container rospub Removed Docker活用テクニック③ コンテナでGUIを利用する Docker with GUI Dockerコンテナ内でGUIアプリケーションを利用するには、ホストでX Serverが必要となります。X ServerはLinuxデスクトップアプリケーションで利用されているWindowシステムです。 事前準備 ホストで X Server が動作していることを確認してください。多くの Linux ディストリビューションでは、デフォルトで X Server がインストールされています。 X Server のアクセス権をコンテナからの接続を許可するように設定します。 $ xhost +local : GUIアプリケーション起動 Dockerコンテナを起動します。コンテナでGUIが利用できるように起動オプション (-e DISPLAY -e QT_X11_NO_MITSHM=1 -v /tmp/.X11-unix:/tmp/.X11-unix) を付加してください。 ここでは、ROS 2のための3D可視化ツールである rviz2 を起動します。 $ docker run -it --rm --name guitest \ -e DISPLAY \ -e QT_X11_NO_MITSHM = 1 \ -v /tmp/.X11-unix:/tmp/.X11-unix \ osrf/ros:humble-desktop \ rviz2 起動後、ホスト上にrviz2が表示されます。 Dockerコンテナ rviz2 Docker活用テクニック④ コンテナ内からWebカメラの映像を取得する Docker with Web Camera ROSでWebカメラ画像を取得するにはV4L2(Video4Linux version 2)を利用します。V4L2は、Linuxカーネル内のAPIであり、ビデオキャプチャと出力デバイスのサポートを提供します。 事前準備 WebカメラがV4L2でサポートされているかを確認してください。UVC(USB Video Class)規格のWebカメラは対応しています。 Webカメラ画像取得ノード ROS ノード提供サイト: ROS Camera driver for GStreamer-based video streams - branch: master GitHub - ros-drivers/gscam: ROS Camera driver for GStreamer-based video streams. ROS 2 ノード提供サイト: ROS Camera driver for GStreamer-based video streams - branch: ros2 GitHub - ros-drivers/gscam at ros2 Webカメラ画像取得 ここでは、 ROS 2 で取得してみます。 Dockerコンテナを起動します。コンテナでWebカメラデバイスが利用できるように起動オプション (--privileged --device=/dev/video0:/dev/video0) を付加してください。 $ docker run -it --rm --name cameratest \ --net=host \ --privileged \ --device=/dev/video0:/dev/video0 \ osrf/ros:humble-desktop \ /bin/bash 起動したDockerコンテナにログイン後、Webカメラ画像取得ノードをビルドします。ビルドが完了後、Webカメラ画像取得ノードを起動します。起動設定ファイルは次の通りです。 Webカメラ画像取得ノード設定ファイル (v4l.launch.xml) <launch> <!-- This launchfile should bring up a node that broadcasts a ros image transport on /webcam/image_raw --> <arg name = "DEVICE" default = "/dev/video0" /> <!-- The GStreamer framerate needs to be an integral fraction --> <arg name = "FPS" default = "10/1" /> <arg name = "PUBLISH_FRAME" default = "false" /> <node namespace = "v4l" name = "gscam_driver_v4l" pkg = "gscam" exec = "gscam_node" output = "screen" > <param name = "camera_name" value = "default" /> <param name = "camera_info_url" value = "package://gscam/examples/uncalibrated_parameters.ini" /> <param name = "gscam_config" value = "v4l2src device=$(var DEVICE) ! video/x-raw,framerate=$(var FPS) ! videoconvert" /> <param name = "frame_id" value = "/v4l_frame" /> <param name = "sync_sink" value = "true" /> </node> <node if = "$(var PUBLISH_FRAME)" name = "v4l_transform" pkg = "tf2_ros" exec = "static_transform_publisher" args = "1 2 3 0 -3.141 0 /world /v4l_frame" /> </launch> Webカメラ画像取得ノード起動後、トピック名が /v4l/camera/image_raw のROSメッセージが送信されます。 # ros2 launch ./v4l.launch.xml [ INFO ] [ launch ] : All log files can be found below /root/.ros/log/2023-09-13-07-37-40-455157-feb5b5ceb79d-2335 [ INFO ] [ launch ] : Default logging verbosity is set to INFO [ INFO ] [ gscam_node -1] : process started with pid [ 2336 ] [ gscam_node -1] [ INFO ] [ 1694590661 . 146771024 ] [ v4l.gscam_driver_v4l ] : Using gstreamer config from rosparam: " v4l2src device=/dev/video0 ! video/x-raw,framerate=10/1 ! videoconvert " [ gscam_node -1] [ INFO ] [ 1694590661 . 147929610 ] [ v4l.gscam_driver_v4l ] : camera calibration URL: package://gscam/examples/uncalibrated_parameters.ini [ gscam_node -1] [ INFO ] [ 1694590661 . 148746118 ] [ v4l.gscam_driver_v4l ] : Loaded camera calibration from package://gscam/examples/uncalibrated_parameters.ini [ gscam_node -1] [ INFO ] [ 1694590663 . 558110687 ] [ v4l.gscam_driver_v4l ] : Time offset: 1694587415 . 451620 [ gscam_node -1] [ INFO ] [ 1694590663 . 572234037 ] [ v4l.gscam_driver_v4l ] : Publishing stream... [ gscam_node -1] [ INFO ] [ 1694590663 . 572646995 ] [ v4l.gscam_driver_v4l ] : Started stream. Webカメラ画像のROSメッセージを確認する場合、「Docker活用テクニック④ コンテナでGUIを利用する」で起動した rviz2 で表示します。 GSCam in Dockerコンテナ まとめ 今回は、ROS開発に便利なDockerコンテナの活用テクニックを紹介しました。紹介した活用テクニックにより、ホストで使用する場合と同様の扱いができますので、ご活用ください。 冒頭にもご紹介した通り、当社は車載向けエッジコンピューターEDGEPLANT T1を販売しています。 aptpod,Inc. EDGEPLANT T1 EDGEPLANT T1はNVIDIA® Jetson™ TX2を搭載したエッジコンピュータで、映像のエンコードやデコードなどGPUを使用する処理や、デバイスエッジでのAIモデルの実行用途にお使いいただけます。また、SIMスロット、GPSモジュールなど、IoT端末として必要な様々な機能を備えています。車載機器に求められるEMC規格(Eマーク)、信頼性規格(JASO D014)などにも準拠しており、ROSを使用したロボット開発、自動運転システムの開発にもおすすめです。 EDGEPLANT T1は、当社の販売パートナー様または、 Amazon.co.jp からご購入いただけます。詳しくは、製品ページをご覧ください。 www.aptpod.co.jp AI自動運転での活用例もございます。ご興味がございましたらこちらの記事もご覧ください。 tech.aptpod.co.jp 次回以降は DockerでROSを利用する際に、GPUを使用する方法についての紹介 ROS 2を利用する上での大容量データ転送シナリオにおけるチューニングについての紹介 を予定しています。 当社プロダクトのご案内 先日行われた ROSConJP 2023 では、ROSの開発ワークフローを効率化するDXソリューションとして、新たなソリューションを発表いたしました。詳細については、ROSConJP 2023の参加報告記事をご覧ください。 tech.aptpod.co.jp また、ROS開発において、当社プロダクトをどの様にご活用いただけるかは、連載1日目にて当社のVPoPがより詳しく紹介しておりますので、こちらもご覧ください。 tech.aptpod.co.jp さらに、当社では、モビリティ・ロボットのフリート管理や遠隔監視、遠隔制御を実現するための管制制御システム向けのソリューションフレームワーク「intdash CONTROL CENTER」を提供しています。 tech.aptpod.co.jp スマートシティにおける自動運転車、工場や物流倉庫における搬送ロボット、建設現場における建設機械など、モビリティ群の統合遠隔監視・管理、遠隔制御システムな どでお困りのことがあれば、ぜひお声掛けください。 お問合せフォームは こちら です。
アバター
はじめに: ROS Tipsの連載投稿はじめます アプトポッドVPoPの岩田です。 近年、ロボット技術が急速に進化していますが、その背景にはROS(Robot Operating System)というミドルウェアの存在が大きく影響しています。特に、ROSの新しいバージョンである「ROS 2」がリリースされて以来、ロボット開発の現場でもますます注目度が高まっています。ROSは元々、研究や学術用途で広く使われていましたが、ROS 2の登場によって商用ロボットや組み込みシステムにも容易に適用できるようになりました。この進化により、より多くの企業や研究機関がROSを採用し、ロボット開発が加速しています。 当社では、主力製品である データ伝送・管理ミドルウェア「intdash」 とROSとの連携プロダクトとして、以下のような製品を提供しています。 intdash Bridge (intdashとROSをつなぐブリッジソフトウェア) intdash ROS2Bridge (intdashとROS 2をつなぐブリッジソフトウェア) ※ これらはLinuxパッケージとして公開してあり、どなたでも使用いただけます。ただし、利用にはintdashのサーバー環境のご契約が必要です。ご興味のある方は、 問い合わせフォーム よりお問い合わせください。 当社では、 ROSと「intdash」を組み合わせたロボットの遠隔化 など、これらの製品を活用したロボットシステムの開発依頼も承っております。こういった製品開発や個別システム開発を繰り返していくなかで、ROSを用いた開発に関するノウハウも徐々に蓄積してきています。 本連載では、 当社がこれまで蓄積してきたTipsやノウハウを、複数回に渡って連載形式でご紹介していきます 。連載第1回目は、最も基本的なところから「そもそもROSとは何なのか」についてご紹介します。 なお、連載の予定として、以下のようなコンテンツを予定しております。(連載内容は、変更・追加の可能性があります。ご了承ください) そもそもROSとは? (本記事) ROS開発におけるDocker活用テクニック ROSのDockerコンテナからNVIDIA GPUを利用するには 大量伝送シナリオにおけるROS/DDSのチューニング 本連載の投稿済みの記事はこちらからご覧いただけます。 tech.aptpod.co.jp tech.aptpod.co.jp はじめに: ROS Tipsの連載投稿はじめます ROSとは ROSの種類: ROSとROS 2 ROSのディストリビューション 当社のソリューションについてのご紹介 おわりに ROSとは What is ROS ROS(Robot Operating System)はオープンソースで提供されるロボット向けのメタ・オペレーティングシステムです。OSと銘打ってはいますが、実際は分散コンピューティングのための通信ミドルウェアが中心のエコシステムとなっています。通信にはPub/Subモデルを採用し、ノード(Node)と呼ばれるプロセス間でメッセージを送受信し合ってソフトウェアを構築します。OSにはUbuntu(Linux)を使用します。 ROSの種類: ROSとROS 2 現在主流になりつつあるのは、ROSの新しいバージョンであるROS 2です。ROS 2がリリースされる以前、ROS(以降、ROS全般についての言及と区別するためにROS 1と表記します)は多くのロボット研究者や開発者に採用されましたが、産業界での採用にはいくつかの課題がありました。特に、リアルタイム性、セキュリティ、モジュラリティなどの面において、不足を指摘する声が多く聞かれました。これらの課題を解決するために、新たに開発されたのがROS 2です。 ROS 2は、新しい通信ミドルウェアDDS(Data Distribution Service)を採用し、リアルタイム性やセキュリティの向上を実現しました 。ROS 2は、ROS 1とは異なる設計思想を持ちながらも、既存のROSユーザーが移行しやすいように設計されています。 .mytable tbody tr { line-height: 1.2; } .mytable tbody th { vertical-align: top; text-align: left; padding-top: 10px; padding-bottom: 20px; white-space: nowrap; } .mytable tbody td { vertical-align: top; text-align: left; padding-top: 10px; padding-bottom: 20px; } 引用: Why ROS 2? ROS 1 ROS 2 想定ロボット 台数 単体ロボットでの使用 複数台のロボットへの対応 想定する プラットフォーム ワークステーション級の 高性能計算機 組み込みプラットフォーム にも対応 OS 基本的にUbuntuのみ マルチプラットフォーム リアルタイム 制御 特別な仕組みにより実現 OSやハードウェアで 標準サポート 想定 ネットワーク 安定した通信環境 (有線・広帯域無線通信) 不安定な通信環境に対応 (遅延や損失にも対応可) 適用分野 研究、学術用途 実製品での利用 通信方式 XMLRPC + TCPROS DDS 送信ノード の検出方法 単一障害点となりうる ROSマスターへ問い合わせ ピア・ツー・ピアで相互検出 ROSのディストリビューション ROSディストリビューションとは、ROSの特定のバージョンに対応したソフトウェアパッケージのまとまりです。これは、Linuxディストリビューション(例: Ubuntu)などと似たようなものと考えることができます。一度新しいディストリビューションがリリースされると、 コアパッケージ(ros-desktop-full以下のすべて)に対する変更は、なるべくバグ修正と非破壊的な改善(non-breaking improvements)に限定されるように運用されます 。一方で、より "高度な" パッケージについての更新ルールは若干緩和されており、破壊的変更(breaking changes)の可否判断はパッケージのメンテナーに任されているようです。 すなわちROSディストリビューションとは、開発者が安心して長期間、ROSを使えるようにするための仕組みです。 このようなディストリビューションの考え方があるおかげで、開発者は安定した環境で作業ができます 。ちなみに、ディストリビューションは Distro などと省略して表記される場合があります。 2023年09月の時点で、LTSサポートされているROSのディストリビューションは以下の通りです。 ROS 1 Distro リリース日 EOL サポートOS Noetic 2020/05/23 2025/05 (Focal EOL) Ubuntu 20.04 Focal (amd64, arm64) Melodic 2018/05/23 2023/06 (Bionic EOL) Ubuntu 18.04 Bionic (amd64, arm64) Kinetic 2016/05/23 2021/04 (Xenial EOL) Ubuntu 16.04 Xenial (amd64) 表中の情報は、以下のリンクからもご確認いただけます。 Distributions - ROS Wiki REP 3 -- Target Platforms (ROS.org) ROS 2 Distro リリース日 EOL サポートOS Humble 2022/05/23 2027/05 (Jammy EOL) Ubuntu 22.04 Jammy (amd64, arm64) Windows 10 V.S. 2019 (amd64) Foxy 2020/06/05 2023/06 (Focal EOL) Ubuntu 20.04 Focal (amd64, arm64) Mac macOS 10.14 Mojave Windows 10 Visual Studio 2019 Dashing 2019/05/31 2021/05 (Bionic EOL) Ubuntu 18.04 Bionic (amd64, arm64) Mac macOS 10.12 Sierra Windows 10 Visual Studio 2019 表中の情報は、以下のリンクからもご確認いただけます。 Distributions — ROS 2 Documentation: Humble documentation REP 2000 -- ROS 2 Releases and Target Platforms (ROS.org) Ubuntu 上記表中に記載したUbuntuのサポート状況 ( LTS : 安定版 ) は以下のようになっています。 バージョン ディストリビューション リリース日 EOL Ubuntu 22.04 Jammy 2022/04/21 2027/04 Ubuntu 20.04 Focal 2020/04/23 2025/04 Ubuntu 18.04 Bionic 2018/04/26 2023/06 Ubuntu 16.04 Xenial 2016/04/21 2021/04 表中の情報は、以下のリンクからもご確認いただけます。 Releases - Ubuntu Wiki 当社のソリューションについてのご紹介 当社では、 IoTデータの伝送・管理を得意とするミドルウェア「intdash」 の開発と、これを用いたシステム開発サービスをご提供しております。 IoTデータの伝送・管理ミドルウェア「intdash」 冒頭でもご紹介した以下のソフトウェア等を利用してROSと「intdash」を連携することにより、インターネットを越えてROSのデータを遠隔地へ連携する いわゆる「NAT越え」 を簡単に実現することが可能です。 intdash Bridge (intdashとROS 1をつなぐブリッジソフトウェア) intdash ROS2Bridge (intdashとROS 2をつなぐブリッジソフトウェア) このような製品により、ひとたびROSロボットを intdash に接続してしまいさえすれば、あとは「intdash」の様々な機能性を利用して、 ロボットのクラウド管理、遠隔監視・遠隔操縦の実現 など、高度なロボットシステムの開発を実現できます。 「intdash」の具体的な特長や機能性については、以下のリンクをご覧ください。 www.aptpod.co.jp また「intdash」は、IoTデータの 「伝送」だけでなく、「可視化」や「データ管理」についても対象とした製品 です。 「intdash」に付属する「Visual M2M Data Visualizer」という可視化ダッシュボードツールを利用すれば、ROSデータを始めとする様々なIoTデータを、ダッシュボード上で一元的に可視化することができます。 以下は「Visual M2M Data Visualizer」により実現可能なダッシュボードの一例です。 「Visual M2M Data Visualizer」のダッシュボード作成例 「Visual M2M Data Visualizer」に対するより詳細な情報は、以下のリンクからご確認いただけます。(上記のダッシュボード例についても、より拡大したものを以下のページでご覧いただけます) www.aptpod.co.jp さらに、「intdash」はミドルウェアを経由して伝送したデータをサーバー上に自動的に保存する機能性を持っています。保存されたデータはWebブラウザからいつでも確認できますので、 ロボット開発の際のデータ管理プラットフォームとしてもご活用いただけます 。 intdashに付属するブラウザアプリケーションや各種APIの詳細については、 当社サイトの製品紹介ページ からご確認ください。 また、ご興味をお持ちいただけた方向けに、「intdash」を14日間無料でをお試しいただける 無償トライアルプログラム もご用意しております。この機会に是非お試しいただき、「intdash」の実力を実感していただければと思います。自社ロボットをお持ちのロボットベンダー様向けには、お持ちのロボットを「intdash」に対応させるための開発環境を無償でご提供させていただく デベロッパープログラム のご用意もございます。詳しい内容について、当社担当者に聞いてみたいという方は、 お問い合わせフォーム よりお気軽にご連絡ください。 おわりに いかがでしたでしょうか。今回はまず基本中の基本「ROSとはなにか」についてご説明し、ROSに関わる当社の製品についても併せてご紹介ました。 冒頭でもご紹介した通り、次回は、 ROS開発におけるDocker活用テクニック です! ROS 2が登場して以来、ROSの開発は徐々にコンテナイメージを前提としたものに移り変わってきている状況があります。次回の投稿では、こういった背景のもと、 そもそもコンテナ技術とはなんなのか、ROSの開発においてどのようにコンテナ技術を活用していけばよいのか 等についてご紹介いたします。次回もお楽しみに! ちなみに、来週 2023年9月26日に開催される ROSConJP 2023 @浅草 にて、シルバースポンサーとしてブースを出展します。 また、当日の講演にて、当社のエンジニアが当社の Open-RMF に関する取り組みについてプレゼンいたします。 tech.aptpod.co.jp ご興味をお持ちいただけた方は、ぜひこの機会に当社ブースにお立ち寄りください。 私も当日ブースに立ちますので、当社製品に関する技術的な内容や様々な疑問にお答えしたいと思います。 最後までお読みいただきありがとうございました!
アバター
 Aptpodのハードウェアエンジニアの平野と申します。Aptpodでは、当社の製品を使って海外で計測をするお客様もいます。海外の計測は少し複雑の様で、時には様々な問題に直面する事があります。今年の夏、私が、28日間の長い休暇を取って、コートジボワールとベナンの家族を訪問する予定でした。そこで、アフリカへの旅行中に当社の製品を使って計測してみようと思いました。私の体験を、同僚、そしてここを読んでいる皆さんにも共有したいと思います。  私は日本語不得意なものでこのブログは先に英語で書いてから日本語に翻訳しています。原文も載せていますので英語で読みたい方は こちら からお願いいたします。 準備 システムの要求 計測したいデータとエッジコンピュータの選定 電波法による通信の制限 デバイスの構成 旅のドライブレポート アビジャンプラトーのドライブ コートジボワールからベナンの旅 ベナンからコートジボワールの復路 振り返り 準備 システムの要求 計測したいデータとエッジコンピュータの選定  今回の計測で、ビデオ、オーディオ、CAN、GPS、周辺の温度と湿度のデータを供したいと思います。 現在、当社で販売しているハードウェアは EDGEPLANT T1 ですが、 今回の旅に、 Raspberry Piをベースにした産業用小型エッジコンピュータ の試作機を使う事に決めました。 このエッジはT1ほど強力でありませんがより小さく、軽く、持ち運びやすいです。GPS付きLTE通信モジュール、加速度計・角速度計、CANバスやUSBポート等が含まれていて、今回の要求に十分対応できます。 使用したいデバイス 電波法による通信の制限  計画で最初に直面した問題は電波法の規制でした。実際、日本で無線を利用するすべての製品が日本の電波法に準拠する必要があると同様、今回の旅に使用するLTEモジュールとアンテナが訪問する各国の電波法に準拠する必要があります。そのため、コートジボワールのARTCI、ガーナのNCA、トーゴとベナンのARCEPで、デバイスを認証する必要があります。私たちは、ポケット Wi-Fi を使用してネットワークに接続し、エッジ内の LTE モジュールを取り除くというアイデアに辿り着きました。  コートジボワールには、Orange と MTN という 2 つの大手通信会社があります( 引用:総務省 )。地元住民によると、Orangeは顧客サポートサービスや田舎での通信カバーが優れています。一方、MTN はベニン、トーゴ、ガーナでも利用できます。 同じポケット Wi-Fi ZLT M30S (LTE 最大 50Mbps、CDMA 5.76Mbps) を使用できるので、コートジボワール国内の旅行とコートジボワールからベニンへの地域間旅行をカバーするために MTN を使用することにしました。 MTN の 4G SIM を 1 枚挿入するだけでインターネットに接続できます。ポケット Wi-Fi の USB ポートを介してエッジ コンピューターを接続してデータを送信することもできます。 Pocket Wifi ZLT M30S  当初の GPS は LTE モジュールに組み込まれているため、GPS 用の別のソリューションを見つける必要があり、USB to GPS レシーバーを使うことになりました。しかし、全てのUSBデバイスは自動的にLinuxに動作する確証はありません。カーネルを介して Linux オペレーティング システムでドライバーを利用できない可能性があります。EDGEPLANT T1 で使用経験があった複数デバイスをテストし、最終的に USB-GNSS レシーバー GU-902-MGG を選択しました。通信の問題が解決したので、エッジに接続したいデバイスの検討に入ります。 デバイスの構成  上で書いたように、エッジ コンピューターは IMU (加速度計とジャイロメーター)、1 つの CAN チャネル、ADC 用の 4 チャネル、および 2 つの USB ポートを有します。 ADC に接続するには、アナログ センサー ボードを使用して、エッジに供給する電圧と電流、周辺の温度と湿度を測定したいと思います。USB ポートについては、カメラとマイクに加えて、USB-Wifi と USB-GNSS も処理する必要があります。したがって、追加のデバイスを接続するために USB ハブ ST7200USBM (USB2.0 7 ポート) を追加しました。システムは次のようになりました。 デバイス構成 旅のドライブレポート アビジャンプラトーのドライブ アビジャン中心区でドライブ アビジャンの幹線道路、ラペ大通り、ゴール大通り、北オートルート・デュ・ノードを使って、アビジャンの中心区であるプラトーの周辺をドライブしました。テストに1999 年式のフォード フォーカスを使いました。日本でホンダ・フリードを使って同じデバイス構成を確認しました。 システムへの電源供給と CAN データの収集はOBDコネクタ経由、USBハブへの電源供給はシガーソケットにて行いました。 フォードフォーカスに実装 ドライブ中のデータ  このドライブからは、ネットワークが安定しており、GPS 結果が正確であることがわかりました。東京近郊での試乗と何ら変わりはありません。東京の同僚はデータを確認し、リアルタイムで運転を追跡することができました。唯一のマイナス点は、CAN データを車から取り出せなかったことです。車を運転していると雨が降り始めたので、窓を閉めてエアコンを作動させました。写真を見ると、温度が 42 度から約 26 度まで下がっていることがわかります。以下に公開していますので、良かったら見て下さい。 youtu.be コートジボワールからベナンの旅 アビジャンからウイダまで、830kmの道のり  旅の後半では、ベナンのウィダーに行くことになりました。 10年毎の一族の大集会に、世界中から家族の一員がウィダーに集まろうとします。今年、コートジボワールからの代表団のほとんどはベナンへの移動に高速バスを利用しました。旅行中にシステムに12V 供給して計測を行うために、電源入力をパワーバンクのモバイルバッテリーと USB PD トリガーに変更しました。バスの真ん中の席に座っていましたが、その後、カメラにより良いスポットビューのため窓席に移動しました。 12V 供給するためパワーバンクを接続 高速バスに実装  システムはうまく機能し、さまざまなコンポーネントから有用なデータを取得することができました。首都からコートジボワール/ガーナ国境までの全道でネットワークがカバーされると期待していましたが、アボワッソ付近(首都から約100km)で3G接続が失われました。接続が失われた後でも、データはエッジ コンピューターの内部ストレージに記録され、その後ベナンでサーバーにアップロードされました。  バス内の気温に関する逸話。どうやら温度の微調整はできないバスでした。そのため、ドライバーはエアコンを定期的に手動でオン/オフする必要がありました。停止中ドアを開けると車内温度が40 度に上昇し、夜間には 15 度ほどまでに低下していました。これは、計測結果で温度データが”波を打つ”理由です。 アボワッソ、首都から100km ロメ港周辺(トーゴ) ベナンからコートジボワールの復路  復路も往路と同じシステムを利用しました。座席の下に USB ポートがあることがわかり、パワーバンクを充電しながら、帰りの旅行中に録画を続けることができました。車の最前列の座席を確保することができたので、映像を期待しました。一方、停車中には他の乗客は全員私たちの座席の前を通り過ぎたので、安全のために他のすべてのコンポーネントをバッグの中に入れておかなければなりませんでした。その結果、一部の GPS 信号が失われ、音声信号にLTE ノイズが入ってしまいました。しかし、20 時間以上の詳細なデータを取得できたため、計測は概ね成功しました。 ウイダー出発 ガーナ国境、SIMカード購入、通信再開 データの興味深い点の 1 つとしては、次の図でわかるように、道路状況がIMUデータに確実に投影されています。 バンパーのある道路 穴だらけの道 状態の良い道路 振り返り  海外での計測として。現地のネットワークを利用し、ライブデータも日本に送信することができました。テストは成功し、GPS、ADC、IMU からの非常に有用で詳細なデータが得られました。アビジャンで使用した車両から CAN データを取得できなかったため、CAN BUS についてはまだ残念な気持ちが残っています。正確な原因をまだ特定する必要がありますが、1999 年のフォードは古すぎて、SAE J1850 PWM プロトコルしか搭載していないようです。もう一つの失望は、通信環境でした。アビジャンやアクラのような大都市周辺では、ネットワークは安定していて高速でしたが、田舎ではネットワークが遅いか、ほとんど存在しませんでした。このような状況では、ビデオやオーディオ チャンネルなどのオンサイト データを確認して修正することは困難でした。  この旅行での発見の 1 つは、IMU と GPS データを使用して、バリケード、バンパー、ポットホールなどの道路状況をリアルタイムでレポートできることです。本記事が弊社システムをご利用いただく際の一助となれば幸いです。最後まで読んで頂いてありがとうございました。
アバター
Hi All, I’m Hirano working as a Hardware engineer in the Development Division. At Aptpod, we have some clients who are using our products for measurements abroad. And sometimes they face different kinds of problems and taking measurements abroad seems to be a bit complicated. This year, I planned to take a long 28-day vacation to visit my family in Ivory Coast and Benin. So, I wonder how it would be to use one of our products during my trip to Africa and share my experience with my colleagues and (why not) with you too reader here... Preparation System Construction Data I would like to Measure and Choice of the edge computer Telecommunication Restrictions Due to Radio Law Regulation Devices Structure Drive report of the trip Drive around Abidjan Plateau Trip Abidjan(CI) to Ouidah(Benin) Trip Ouidah to Abidjan Introspection Points Preparation System Construction Data I would like to Measure and Choice of the edge computer Here are the kind of data I would like to share: Video, Audio, CAN, GPS, Environment temperature and humidity, etc… Our hardware available to customers now is the EDGEPLANT T1 . But for this trip, I decided to test our currently on-developing edge computer based on Raspberry Pi . This edge is less powerful than the T1 but it is smaller, lighter, and easier to carry around. The hardware is enough to fit better our demand by providing an LTE module with a GPS incorporated, a 3D accelerometer and 3D gyrometer, 1 channel of CAN Bus, 4 entries for ADC, and 2 USB ports that could serve for the Video and Audio Data… Device we would like to use Telecommunication Restrictions Due to Radio Law Regulation The first problem we encountered in our design was the Radio Law Regulation. Indeed, as in Japan where all products utilizing radio spectrum are to conform with the Japan Radio Law, we would need to use LTE modules and antennas to conform to the Radio Law and certificate our device with the ARTCI (Ivory Coast), the NCA(Ghana) and the ARCEP(Togo / Benin) to use a radio communication in these countries. Certification of a device can be costly and time-consuming. It is a necessity if we want to enter our product in a market. But in this kind of “one-time measurement”, we need a non-costly and easier way. We came up with the idea of using pocket Wi-Fi to connect to the network and get rid of the LTE module inside the edge. In Ivory Coast, we have two major Telecom companies, Orange and MTN (World Information and Communication Circumstances from Ministry of Internal Affairs and Communications). According to locals, Orange has the best rural coverage and helpful customer service while MTN is also available in Benin, Togo, and Ghana. We decided to use MTN to cover the trip inside Ivory Coast and the inter-regional one from Ivory Coast to Benin because we would be able to use the same pocket-wifi ZLT M30S (LTE up 50Mbps, CDMA 5.76Mbps). We just need to insert one 4G SIM from MTN to connect to the internet. Theoretically, we can also send out data by connecting our edge computer through the USB port of the pocket-wifi. Pocket Wifi ZLT M30S Our GPS being incorporated with the LTE module, we need now to find another solution for the GPS and end up choosing a USB to GPS receiver. Some USB devices don’t work automatically on Raspi because the driver may not be available in our Linux Operating system via the kernel. We tested different devices that we had experienced with the EDGEPLANT T1 and ended up choosing the USB-GNSS receiver GU-902-MGG. Now that we have resolved our problem of telecommunication, we can work on the different devices we would like to connect to the edge. Devices Structure As we wrote above, the edge computer can handle an IMU (accelerometer and gyrometer), one CAN channel, 4 channels for ADC, and 2 USB ports. To connect to the ADC, we will use an analog sensor board where we measure the supplied voltage and the current in the edge, the temperature, and the humidity. For the USB ports, in addition to the camera and the microphone, we now have to handle also the USB-Wifi and the USB-GNSS. We therefore add a USB Hub ST7200USBM ( USB2.0 7 Ports) to connect the extra devices. The system looks now as follows. Device Structure Devices Details Drive report of the trip Drive around Abidjan Plateau Drive on Freeway around Abidjan Plateau We drove around Plateau , the central business district of Abidjan, using the Boulevard de la Paix, the Boulevard de Gaulle and the Autoroute du Nord. These roads can be considered as the Metropolitan Expressway in Tokyo. The car used for the test is a 1999 year Ford Focus. We used the same system as in my test with Honda Freed in Japan. The system was connected to the OBD connector to collect power supply and CAN data. We also used the cigar socket to supply power to the USB Hub. Installation in Ford Focus Drive around Abidjan Plateau Out of this drive, we found that the network was stable and the GPS result accurate. There is no difference with a test drive around Tokyo. A colleague in Tokyo was able to check the data and follow the drive in real-time. The only negative point is that we couldn’t get CAN Data out of the car. As we were driving, it started to rain and we closed the windows and started the air conditioner in the car. We can see in the picture that the temperature drops from 42 degrees to around 26 degrees. You can watch the video to have a better idea of the road traffic and conditions in Ivory Coast. youtu.be Trip Abidjan(CI) to Ouidah(Benin) 830 km Road trip from Abidjan(CI) to Ouidah(Benin) On our second trip, we had to go to Ouidah in Benin. Every ten years, all family members around the world try to gather in Ouidah. This year, most of the delegation from Cote d'Ivoire used an Inter-regional Highway Bus to travel to Benin. To make the measurements during the trip, we modified the power input of the system to use a power bank mobile battery and a USB PD trigger to provide a 12V voltage supply. We had a seat in the middle of the bus and later moved to a widow to get a better spot view for the camera. PowerPank connected to Supply 12V to the system Installation in Highway Bus The system worked well and we were able to retrieve useful data from the different components. We were expecting to have network coverage all along the way from the capital to the Cote d'Ivoire/Ghana Frontier but lost the 3G connection around Aboisso (about 100km from the capital). Even after the loss of the connection, the data was recorded in the internal storage of the edge computer and later in Benin uploaded to the server. One anecdote about the temperature in the bus. The temperature could not be regulated. So the drivers had to switch on/off the A/C manually periodically. If not, the temperature in the car can rise up to 40 degrees during stops when the doors are open or drop to 15 degrees at night. This explains the wavy form of the temperature data in our measurements. Data Visualizer, Aboisso,100km from Abidjan Lome (Togo), around the port Trip Ouidah to Abidjan On the return trip, we used the same system as in the outbound journey. We found that a USB port was available under the seat so we were able to recharge our power bank and keep recording during the return trip. We were able to get the first-row seat of the car which gives us a better spot for the camera. On the other hand, since all the other passengers were passing by our seats during the stops, we had to keep all the other components inside the bag for safety. We end up losing sometimes the GPS signal and having the Audio signal filled with LTE noise. But the measurement in general was successful as we were able to retrieve more than 20 hours of detailed data. Ouidah Departure LTE Comm started with prepaid SIM card purchased at Ghana Frontier One interesting point of these data is that the IMU renders reliably the different road conditions, as we can see in the following pictures. Road with Bumpers Road with Potholes Road in good conditions Introspection Points For our overseas measurements, we were able to use the local networks and send even live data to Japan. The test was successful with very useful and detailed data from the GPS, ADC, and IMU. We still have some disappointments with the CAN BUS because we couldn’t retrieve CAN data from the vehicle we used in Abidjan. We still have to determine the exact causes but it looks like the 1999 year Ford was too old and had only the SAE J1850 PWM protocol. One another disappointment was with the Telecommunication environment. Around big cities like Abidjan and Accra, the network was stable and fast while in the countryside, it was almost slow or nonexistent. In these conditions, it was difficult to check and fix on-site data like the video or the audio channel. One discovery in this trip is that we could use the IMU and the GPS data to report in live time road conditions like barricades, bumpers, or potholes. We hope that this report will be useful to you when you use our system. Thanks for reading.
アバター
aptpod Hardwareグループ所属、組込みソフトウェアエンジニアの矢部です。 aptpodで取り扱っているサービスでは、通信機能は重要な要素の一つです。LTE通信網を利用して計測を行うことが多いですが、時間帯や地域によって通信性能が低下することがあります。皆さんも普段スマホを利用していて、昼時は遅い、山間部だと繋がりにくい、などと感じることがあるかもしれません。 今回は通信性能を向上させるための一つの案として、Multipath TCPというものを紹介します。なお、現時点(2023年)ではaptpod内でソリューションとして確立できていないので、あくまで実験的な要素となります。 Multipath TCP (MPTCP) て何? MPTCP概要 MPTCPの接続方法 ネットワークスタックについて v0 と v1 の互換性 MP_CAPABLE オプション Linux カーネルの対応状況 MPTCP 検証結果 Raspberry Pi によるMPTCP v1検証 MPTCPの有効化 mptcpdの利用 有線LANと無線LANの同時利用の場合 LTE2回線利用の場合 MPTCPを利用したintdash通信 通信性能向上に関する調査 耐障害性に関する調査 発生した問題と対処法について さいごに Multipath TCP (MPTCP) て何? MPTCP概要 Multipath TCPは、TCP接続が同時に複数のパスを利用できるようにすることで、通信のスループットを最大化し、冗長性を高めることを目的としたものです。 公式サイトは こちら にありますが、最新のカーネルで採用されているMPTCP v1についてはGithub上で公開されている情報のほうが詳しいです。 github.com もっと詳細を知りたい方は、各バージョンごとのRFCはご覧ください。 MPTCP v0: RFC6824 / 日本語版 (こちらは廃止されており、RFC8684 が現行版) MPTCP v1: RFC8684 / 日本語版 まず、これらから抜粋したMPTCPの仕組みを簡単に説明します。 MPTCPの接続方法 MPTCPでは、ピア間の接続パスを一つではなく、複数パス(サブフロー)を同時に利用できるようにするためのTCP拡張を定義しています。 MPTCP利用シナリオの例 MPTCPの接続は、通常のTCP接続と同じ形で開始されます。 まず最初にMPTCPの接続はホストAのアドレスA1と、ホストBのアドレスB1との間で確立する 追加パス(上の例だと A2 と B1 間)が利用可能な場合、MPCTPサブフローと呼ばれる追加のTCPセッションが作成される サブフローは既存のセッションと結合され、ホストAとB上のアプリケーション間の単一の接続として見えるようになる 追加サブフローの検出方法はパス管理の設定方法に依存しますが、上の例でいえば、A2 ↔︎ B2と A1 ↔︎ B1も追加可能なパスになります。 ネットワークスタックについて MPTCPはトランスポート層で動作するため、既存のアプリケーションでも変更なしで利用可能となっています。実際利用してみると、これがかなりの強みであることがわかります。 データシーケンス信号(DSS)オプション これを利用することで、あるサブフローでのデータ送信で障害が発生した場合に、同じDSNのデータを異なるサブフローで再送信が可能となっています。 v0 と v1 の互換性 RFC上では、v1の仕様はv0とは下位互換性がないと記述されています。そのため、v1のみに対応しているカーネルでは、v0での通信を行うことができませんし、逆もまた然りです。 ただ、仕様上はMP_CAPABLEオプションという、パケット内でバージョンを判別する方法は存在しています。ですので、ホストが複数のMPTCPバージョンをサポートすることでどちらでも動作できるようにすることは可能かとは思いますが、今回検証した限りLinuxカーネルはそのような実装になっていないようでした。 MP_CAPABLE オプション 各パケットには、マルチパス対応(MP_CAPABLE)オプションが含まれています。 MP_CAPABLE(v1) この部分の仕様が、v0とv1では異なっています。 MP_CAPABLE(v0) ホスト側が複数のバージョンをサポートする場合、オプションを送信する側がサポート可能な最大のバージョンを送り、受信側がそれを見て利用したいバージョンを通知する形となります。 Linux カーネルの対応状況 MPTCP v1 が公式にLinuxカーネルに採用されたのは、v5.6からです。現行の最新ディストリビューションであれば、ほぼ対応していると言って問題ないかと思います。対応状況については、 公式のChangelog に記載があります。 この後に記載している今回の検証では、カーネルバージョンをv5.15.32利用しています。なお、aptpodが現在販売しているEDGEPLANT T1はカーネルバージョンがv4.9となっているため、残念ながらMPTCP v1を利用することができません。 MPTCP 検証結果 Raspberry Pi によるMPTCP v1検証 現在のメインストリームはv1なので、こちらを使います。以前テックブログでも紹介しましたRaspberry Piベースの小型コンピュータを使って検証してみました。 tech.aptpod.co.jp なお、T1でもMPTCP v0であれば利用可能であることは検証していますが、性能的な差はないので記載は割愛しています。 MPTCPの有効化 RaspberryPi OSの場合、カーネルコンフィグで設定を有効にすればMPTCP v1が利用できるようになります。 コンフィグ設定したもので確認すると、MPTCP設定が有効になっていることがわかります。 apt@raspberrypi:~ $ sysctl net.mptcp.enabled net.mptcp.enabled = 1 mptcpdの利用 MPTCP v1を利用する場合、 mptcpd という非常に便利なツールがあります。 github.com これを利用することで、アプリケーションに何ら手を加えることなく、MPTCPに対応した通信ができるようになります。例えば iperf3 をMPTCPに対応した形で通信させる場合、以下のコマンドを実行するだけです。 $ mptcpize run iperf3 -s 有線LANと無線LANの同時利用の場合 まずは室内でLANを2系統(eth0,wlan0)使うケースで試験してみます。速度の検証には iperf3 を用いました。 MPTCPの設定を行った状態で iperf3 で通信している状況を tcpdump してみると、それぞれのNICからMPTCPのオプションが付いたパケットが送信されていることがわかります。 apt@raspberrypi:~ $ sudo tcpdump -i wlan0 dst port 5201 -n -nn tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on wlan0, link-type EN10MB (Ethernet), snapshot length 262144 bytes 17:11:22.004375 IP 192.168.11.22.38851 > 192.168.11.19.5201: Flags [S], seq 399502012, win 64240, options [mss 1460,sackOK,TS val 1740192247 ecr 0,nop,wscale 7,mptcp join id 7 token 0xa808d87f nonce 0x251cca21], length 0 17:11:22.008050 IP 192.168.11.22.38851 > 192.168.11.19.5201: Flags [.], ack 2143962676, win 502, options [nop,nop,TS val 1740192251 ecr 667182969,mptcp join hmac 0xf686d1acd242cf317cf5c1f9c3b61230a75cf74e], length 0 17:11:22.047919 IP 192.168.11.22.60827 > 192.168.11.19.5201: Flags [S], seq 2712815829, win 64240, options [mss 1460,sackOK,TS val 1740192291 ecr 0,nop,wscale 7,mptcp join id 7 token 0xd7358f3e nonce 0xfd3c2dbd], length 0 17:11:22.049973 IP 192.168.11.22.60827 > 192.168.11.19.5201: Flags [.], ack 1616183346, win 502, options [nop,nop,TS val 1740192293 ecr 667183011,mptcp join hmac 0xd54c9ad8aa6276037996de49cf98d78062709e4a], length 0 apt@raspberrypi:~ $ sudo tcpdump -i eth1 dst port 5201 -n -nn tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes 17:11:20.350554 IP 192.168.11.24.56846 > 192.168.11.19.5201: Flags [.], seq 3439394281:3439395705, ack 307584348, win 502, options [nop,nop,TS val 3397519411 ecr 3244345261,mptcp dss ack 1465887935 seq 2403971799896915964 subseq 19174102 len 9936,nop,nop], length 1424 17:11:20.350579 IP 192.168.11.24.56846 > 192.168.11.19.5201: Flags [.], seq 1424:2848, ack 1, win 502, options [nop,nop,TS val 3397519411 ecr 3244345261,mptcp dss ack 1465887935 seq 2403971799896915964 subseq 19174102 len 9936,nop,nop], length 1424 17:11:20.350592 IP 192.168.11.24.56846 > 192.168.11.19.5201: Flags [.], seq 2848:4272, ack 1, win 502, options [nop,nop,TS val 3397519411 ecr 3244345261,mptcp dss ack 1465887935 seq 2403971799896915964 subseq 19174102 len 9936,nop,nop], length 1424 17:11:20.350604 IP 192.168.11.24.56846 > 192.168.11.19.5201: Flags [.], seq 4272:5696, ack 1, win 502, options [nop,nop,TS val 3397519411 ecr 3244345261,mptcp dss ack 1465887935 seq 2403971799896915964 subseq 19174102 len 9936,nop,nop], length 1424 17:11:20.350628 IP 192.168.11.24.56846 > 192.168.11.19.5201: Flags [.], seq 5696:7120, ack 1, win 502, options [nop,nop,TS val 3397519411 ecr 3244345261,mptcp dss ack 1465887935 seq 2403971799896915964 subseq 19174102 len 9936,nop,nop], length 1424 速度については、以下の結果となりました。 構成 速度(avg) eth + wlan 53.3 Mbits/s eth only 82.6 Mbits/s wlan only 6.46 Mbits/s 実験した場所(私の自室)が電波の入りが悪かったのかWLAN単体での通信がかなり遅かったため、同時に利用した際に有線単体と比べると通信が遅くなってしまったようです。 LTE2回線利用の場合 内蔵しているLTEモジュール EM7431 と、LTEドングル GH-UDG-MLCTE を利用した、LTE2回線利用による通信性能の測定を行います。同一キャリアを利用すると通信帯域が重なる恐れがあるため、キャリアは分けました。 実際に通信速度を測ってみた結果は、以下の通りです。 通信速度計測結果 構成 速度(avg) 内蔵LTEモジュール + LTE ドングル 9.39 Mbits/s 内蔵LTEモジュール のみ 5.98 Mbits/s LTEドングルのみ 6.93 Mbits/s 同じタイミングで何度か通信速度を測ってみましたが、おおむね同じような値となっています。 複数回の通信性能計測結果 こちらの結果からは、LTE通信で単一の通信経路だと5~6 Mbpsくらいしか出せないところでも、Mulitpath TCPを使えば 9~10 Mbps程度の速度を安定して出せることがわかりました。 MPTCPを利用したintdash通信 通信性能向上に関する調査 実際にMPTCPをaptpodの製品であるintdashに適用した場合にどの程度通信性能が向上するかを見てみます。分かりやすく比較できるよう、16Mbpsという高いビットレートでカメラ映像を利用する設定にしてみました。 まずは、内蔵LTEモジュールのみの1回線利用での測定結果から。 内蔵LTEモジュールのみでの計測 こちらのグラフは、青が送信データ量、赤が送信できずに内部に溜まったデータ量を示しています。一定量のデータは送れてはいるものの、間に合わずにデータが溜まっているのがわかります。 続いて、内蔵LTEモジュールとLTEドングルの2回線利用での結果がこちら。 2回線利用した場合の計測 先ほどと比べて送信データ量が大きく改善しており、データもほとんど溜まっていません。 この結果から、MPTCPを利用することで、1回線では難しいデータ量の計測が実現できそうだ、ということがわかりました。ただ、実際に運用に乗せるためには、時間や場所などを変えてもっと試行回数を増やす必要はありそうです。 耐障害性に関する調査 MPTCPのメリットとして冗長性を高めるというものあるので、こちらの検証も行いました。 有線LANとLTE通信の2回線を利用した状態で、途中で有線LANを抜いた際の挙動がこちらになります。 途中で1回線を途絶させるデモ 有線LANを抜いた瞬間に1秒程度動画が止まるものの、すぐに復帰しているのがわかります。MPTCP使っていない状態で同じことを実施すると、復帰までにかなり時間がかかるため、冗長性という点でかなりの改善が見られます。 発生した問題と対処法について LTE通信で検証を行っていた際、うまくMPTCPとして動作しないという問題が発生しました。調査を行った結果、送っているパケットには mptcp capable オプションが付いているが、サーバー側に到達したパケットには同オプションが付いていないことがわかりました。 今まで未検証だった技術ということもあり、まずはMPTCP周りから洗っていたのですが、結果としてはSIMに固定グローバルIPを割り当てることで解決することができました。あまり使う機会はないかもしれませんが、各キャリアで有料の固定グローバルIPオプションというものが用意されており、弊社ではお客様からの要望で利用することがあります。 この現象について、今回の検証でサーバー側を担当してくれたSREエンジニアに相談したところ、キャリアグレードNATが原因かも、という見解でした。 ja.wikipedia.org 名前は伏せますが通信キャリア2社を利用し、両方とも同様の現象が発生しています。自宅のネットワーク環境から利用した場合は問題なかったため、LTE通信網のどこかに原因があるのかもしれません。 さいごに 上手な使い方があるのかもしれませんが、MPTCP自体はNICの状況に応じた通信速度の細かい調整などはやってくれないため、今回の検証例でもあったように速度の速いNICの足を引っ張るような結果が起こり得ます。このあたりはPeplink社のSpeedFusionといったサービスはうまくできそうです。国内だとCASO社がサービス提供をしており、aptpodでも連携した実績があります。 www.caso.co.jp youtu.be また、TIER Ⅳ社も多回線通信について高度な技術を開発されているようで、参考になります。 medium.com ただ、当然ながら商用サービスを利用する場合はそれなりにいいお値段するため、Linuxの機能を用いて実行できるのは大きなアドバンテージであると感じています。このあたりは実運用での要求に応じて、何を選択すべきかを考えるところかと思います。 aptpodでは多種多様な通信環境で安定的な計測ソリューションを提供できるよう、日々研究開発を行っていますので、ご興味ある方、困りごとがある方など気軽にご相談ください! www.aptpod.co.jp
アバター
ネイティブアプリケーション開発を担当している上野です。 この度、弊社サービスの intdash と、ゲームエンジン Unity との連携を容易に実現するモジュールを公開することになりました。モジュールの公開に合わせて、その利用サンプルも公開しています。今回は、それらの使い方をご紹介いたします。 Unityで開発したアプリケーションからデータをリアルタイムに取り出して可視化したり、クラウドへ保存して活用したりしてみたいという方や、デジタルツイン開発を始めてみたいという方の第1歩として、このサンプルを活用いただければと思います。 今回公開したもの intdash SDK Samples for Unity について シミュレーターのサンプル 操縦アプリケーションのサンプル 可視化アプリケーションのサンプル intdash SDK for Unity について モジュールの導入と準備 データを生成する仮想デバイスの作成 取得したデータのintdashによる送信 intdashを流れるデータの受信 SDKで実現できること 弊社ビジネスのご紹介 今回公開したもの 今回公開したのは、以下2つです。Unity用のSDKと、そのサンプルの2つのリポジトリになります。 intdash SDK for Unity intdash SDK Samples for Unity intdash SDK for Unity は、UnityのIDEにインポートして利用するSDKで、intdashサーバーのリアルタイム伝送のためのAPIに接続するモジュールや、REST APIにアクセスするためのモジュールが含まれています。 intdash SDK Samples for Unity は、intdash SDK for Unity の使い方を理解していただくためのサンプルです。詳しくはこれ以降で解説します。 ※ 本記事は intdash-unity v1.0.0 、 intdash-unity-samples v1.0.0 を想定しています。将来的に仕様が変更される可能性もありますのでご注意ください。 intdash SDK Samples for Unity について youtu.be ここからは、SDKのサンプルである intdash SDK Samples for Unity をとりあえず試してみたい方向けの内容になります。 今回のサンプルには、ビジュアライザー、コントローラー、シミュレーターが含まれます。 ビジュアライザーは、intdashを流れるデータをUnityを使用して可視化するアプリケーションのサンプルです。今回のサンプルは簡易的なものですが、Unityを使用することで点群データなど3D空間上での可視化表現を用意に実装することができます。 コントローラーは、intdashを介して制御データを送信する操縦アプリケーションのサンプルです。こちらもサンプルは簡易的なものですが、Unityを使用することで、VRゴーグルを活用したバーチャル操縦コックピットの開発など、高度なアプリケーションを開発することができます。 最後にシミュレーターは、Unityで実装した物理シュミレーションのサンプルです。ビジュアライザーやコントローラーは現実世界のデバイスの可視化、操縦のためにも使用できますが、実際のデバイスを用意するのが難しい場合には、こちらのシミュレーターサンプルのようにシミュレーション空間をUnityで作成して代替することも可能です。 ビジュアライザー、コントローラー、シミュレーターと、弊社サービスであるintdashとの間のデータの流れは以下のようになります。 すべてのサンプルプロジェクトがintdashサーバーを介してデータをやり取りしており、お互いのデータを相互に活用して動作します。 今回公開したサンプルでは、シミュレーター内にレース場を作成し、その上で走行する自動車のモデルを、コントローラーで操縦したりビジュアライザーで可視化したりするシナリオをご用意しました。 ※ intdashサーバーとのデータ伝送を行うにはご契約が必要になります、無償のトライアルプログラムもございますのでぜひご活用ください。 intdash Free Trial シミュレーターのサンプル intdash Simulator Sample シミュレータを作成する場合には、まずシミュレーションしたいシナリオを考えて、3D空間内に構築します。 このサンプルでは車の前方にカメラ配置し取得した映像をJPEG形式に圧縮した物と車体の位置、回転情報も収集しデータ伝送を行います。 また、遠隔制御を受け付ける為の操作データの受信方法も実装されています。 操縦アプリケーションのサンプル intdash Controller Sample 操縦アプリケーションでは、操縦対象から取得したデータを可視化しつつ、逆に操作情報を送信することで操縦を実現します。 サンプルでは、コントローラーとは別のアプリケーションであるシミュレーターに配置された車を操縦していますが、intdashによるデータ伝送を用いれば、シミュレーターのかわりに現実世界の車や機械を制御することも可能です。サンプルでは2種類のデータしか扱っていませんが、可視化するデータの種類を増やしたり、Unityの3D空間上での表現力を活かして点群データなどを可視化すれば、より安全で効率のよい操作アプリケーションを実現することも可能になります。 可視化アプリケーションのサンプル intdash Visualizer Sample こちらは遠隔制御目的ではなく監視用途のアプリケーションです。 コントローラーのサンプルと見た目が似ているため違いが分かりにくくなっていますが、こちらは操縦ではなく可視化や監視を目的としたビジュアライザーのサンプルです。 シミュレーターから取得したデータを表示しているのはコントローラーと同様ですが、コントローラーが送信している操作情報もintdashから受け取って可視化している点が、ビジュアライザーのコントローラと異なるポイントです。 intdashには、データの伝送だけでなく、伝送したデータがクラウドに自動的に保存されるという機能にも対応しています。このサンプルでは、intdashに保存された過去のデータを取得してプレイバックする機能も含まれています。 データストアされたデータのプレイバック プレイバックでの可視化では、リアルタイムの可視化とは異なり、右下の俯瞰マップに走行ルートが表示されます。プレイバック機能は、アプリケーションを開始する際に再生日時を指定することで利用できます intdash SDK for Unity について intdash SDK for Unity ここからは、SDK自体を使用して、サンプルで解説したようなアプリケーションを作ってみたい方向けの内容になります。実際のコードも踏まえつつ、モジュールの使い方を解説します。 モジュールの導入と準備 UnityEditorのHierarchyに含まれるintdashとの認証情報入力する場所 上記はSimulatorSampleに含まれるSampleScene.unityをUnityEditorで開きHierarchyとInspectorを表示した状態です。 サンプルでは intdash/ApiManager というGameObjectにIntdashApiManagerスクリプトがアタッチされています。こちらにintdashサーバーとのアクセス情報を入力するだけでサーバーとの接続準備は完了です。 コネクションの設定 intdashサーバーへデータを送信する際はエッジのUUIDの設定が必要です。サンプルでは intdash/Connections 配下のGameObjectにIscpConnectionスクリプトがアタッチされ、そちらでエッジUUIDの設定が可能です。 IntdashApiManagerに含まれる Type の項目が Client Secret(Edge UUID) である場合は、認証情報を発行したエッジのUUIDがIscpConnectionのエッジUUIDとして自動で設定されるため、入力は不要です。他の認証方法を利用する場合や、複数のコネクションを設定し、複数のエッジを利用してデータを送信したいケースではエッジUUIDの設定を行ってください。 ※ 複数のコネクションを利用したい場合は Is Shared にチェックをいれない、もしくは1つのコンポーネントのみにチェックする様にしてください。 データを生成する仮想デバイスの作成 シミュレーターなどにおいて、データを生成する仮想デバイスを作成する方法は、以下の通りになります。 using System.Collections; using System.Collections.Generic; using UnityEngine; public class SampleDevice : MonoBehaviour { public float SamplingRate = 10f ; private float ? _SamplingRate; public struct OutputData { // ToDo: 出力したいデータ } public delegate void OnOutputDataDelegate(OutputData outputData); public OnOutputDataDelegate OnOutputData; private float elapsedTime = 0 ; private float targetTime = 0 ; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { if (SamplingRate != _SamplingRate) { _SamplingRate = SamplingRate; this .targetTime = 1f / SamplingRate; this .elapsedTime = 0f ; } if (SamplingRate <= 0 ) return ; elapsedTime += Time.deltaTime; if ( this .elapsedTime > this .targetTime) { this .elapsedTime -= this .targetTime; // ToDo: 指定した出力時間が来たので値取得 or 計算を行い利用先にデータを流す var data = new OutputData(出力したいデータ); OnOutputData ? .Invoke(data); } } } Unityでは、Update() という関数が各フレームごとに呼び出されるので、SamplingRateで指定した分の時間間隔が経過するごとにデータの取得処理や生成処理を行うことで、必要な周期ごとにデータの生成が可能です。 ※ データが大きすぎたり、PCのスペックが低すぎたりする場合には、ほかの処理に影響が出る場合もあります。その場合には、別スレッドで処理させたり、GPUを使用するなどのチューニングが必要になる場合もあります。 取得したデータのintdashによる送信 取得したデータを、intdashサーバーに送信する方法は、以下の通りになります。 using UnityEngine; using iSCP.Model; public class Iscp_SampleDataPublisher : MonoBehaviour, IIscpUpstreamCallbacks { [SerializeField] private string dataType = "string/json" ; [SerializeField] private string dataName = "sampleData" ; [SerializeField] private bool persist; public DeviceSample InputDevice; // MEMO: Basically, IscpConnection attachment from Inspector is not required, but can be specified. [SerializeField] private IscpConnection iscp; private IscpUpstream upstream; // Called when the script is first activated. private void Awake() { // Setup iSCP. if (iscp == null ) { this .iscp = IscpConnection.GetOrCreateSharedInstance(); } // Register upstream. upstream = iscp.RegisterUpstream(persist); upstream.Callbacks = this ; } private void OnEnable() { if (InputDevice != null ) InputDevice.OnOutputData += OnOutputData; } private void OnDisable() { if (InputDevice != null ) InputDevice.OnOutputData -= OnOutputData; } void OnOutputData(DeviceSample.OutputData data) { // Generation in accordance with data format. var json = "" ; json += "{" ; json += "" ; // ToDo: 送信したいデータ json += " }" ; var payload = System.Text.Encoding.UTF8.GetBytes(json); // Send data points to upstream. upstream.SendDataPoint(dataName, dataType, payload); } } 「仮想デバイスの作成」で作成したデバイスが定期的にコールバックで値を出力するので、事前に開いておいたintdashのアップストリームへデータ を書き込むだけでデータを伝送できます。 書き込むデータに対しては、事前にデータ名とデータタイプ、ペイロードのフォーマットを決めておく必要があります。今回、データの中身を理解しやすくするためにペイロードフォーマットにはJSONを使用しています。これはあくまで一例で、場合によってはロボット開発で使用されるROSデータや、よりデータサイズを小さくするためにバイナリフォーマットを使用することもできます。 また、ストリームを開く際に、送信したデータをクラウドへ保存するかどうかの設定もでき、データ伝送だけを行う設定とすることも可能です。 intdashを流れるデータの受信 コントローラーやシミュレーターから送信されたデータを、intdashサーバーから受信する方法は、以下の通りになります。 using System; using UnityEngine; using Newtonsoft.Json.Linq; public class Iscp_SampleDataSubscriber : MonoBehaviour { [SerializeField] private string dataType = "string/json" ; [SerializeField] private string dataName = "sampleData" ; [SerializeField] [IntdashLabel( "Node ID(Edge UUID)" )] private string nodeId = "" ; public SampleComponent TargetComponent; [SerializeField] private string receivedTime; public string ReceivedTime => receivedTime; [SerializeField] private string receivedData; public string ReceivedData => receivedData; // MEMO: Basically, IscpConnection attachment from Inspector is not required, but can be specified. [SerializeField] private IscpConnection iscp; private IscpDownstream downstream; // Called when the script is first activated. private void Awake() { // Setup iSCP. if ( this .iscp == null ) { this .iscp = IscpConnection.GetOrCreateSharedInstance(); } // Register downstream. downstream = this .iscp.RegisterDownstream(nodeId, dataName, dataType, OnReceiveDataPoints); } // Received data points events. private void OnReceiveDataPoints(DateTime baseTime, iSCP.Model.DataPointGroup group ) { Dispatcher.RunOnMainThread(() => { if ( this == null ) return ; if ( !this .enabled) return ; try { foreach ( var d in group .DataPoints) { receivedTime = DateTime.UtcNow.ToLocalTime().ToString( "HH:mm:ss.ffffff" ); // Extract the necessary data from the data format. receivedData = System.Text.Encoding.UTF8.GetString(d.Payload); 抽出する型 抽出したデータ; // Json Parse { JObject json = JObject.Parse(receivedData); // ToDo: 送られてくるデータフォーマットに沿って必要なデータを抽出する。 抽出したデータ = json[ "抽出したいデータ" ]ToObject<抽出する型>(); } if (TargetComponent != null ) { if (TargetComponent.enabled) { // ToDo: 動かしたり、可視化したいコンポーネントへデータを伝える。 Debug.Log( "Received data: " + 抽出したデータ); } } } } catch (Exception e) { Debug.LogError( "Failed to deserialize control message. " + e.Message); } }); } } 受信したいデータに合わせて、dataTypeやdataName、nodeId を設定することで、intdashサーバーからダウンストリームを開くことができます。サンプルでは、シミュレーターやコントローラーで使用しているエッジのUUIDをnodeIdとして指定しています。 データが受信されるとコールバックが呼び出されるので、ペイロードのフォーマットに合わせてデータをパースし、可視化などの必要な処理を行います。 SDKで実現できること 今回のサンプルでは、あくまでSDKの使い方を示す目的にフォーカスして、最小限の構成を使用しています。最小限の構成のため、できることは限られていますが、intdashを使えば簡単にUnityからデータを伝送できることをご理解いただけたと思います。 サンプルと同様に、intdashを活用してデジタルツインシステムを実現した例として、以下のような事例もございます。 openhub.ntt.com 上記記事の中では、 建設現場の遠隔化/リアルタイムデジタルツイン というテーマで、今回のサンプルをさらにグレードアップしたようなアプリケーションが紹介されています。 今回のサンプルでは映像のみを用いた遠隔操縦を題材としていますが、3D LiDARを使用して点群データを取得するなどすれば、より詳細な情報を利用して安全かつ正確な操作が可能になります。 また、たとえば高額なセンサーの購入が必要となる実証実験の際にも、現実世界でのシステム構築の前にUnityでシミュレーションを構築すれば、実際に近いデータの流れを低コストに再現することができます。 弊社ビジネスのご紹介 アプトポッドでは、IoTミドルウェア intdash の開発と、intdsahを活用したIoTシステムの構築を事業としています。 intdashは、あらゆるIoTデータを収集、伝送、管理、活用することができ、IoTデータを活用するさまざまなサービスのバックエンドとしてご活用頂いております。 www.aptpod.co.jp 今回ご紹介したSDKは、デジタルツインやAR/VRで活用されているUnityとintdashの連携性を更に強め、intdashで集めたデータの活用の幅を広げていくための強力なツールです。 IoTデータを利用したプラットフォーム、IoTサービスの開発や、リアルタイムデジタルツイン、製造現場のDX化など、IoTシステムの開発でお困りのことがあれば、ぜひ弊社までお声がけください。 弊社の問い合わせフォームはこちらです。 www.aptpod.co.jp
アバター
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
アバター