aptpod Advent Calendar 2025 12月11日の記事です。 こんにちは、開発本部 Visual M2M グループでフロントエンドエンジニアをしている遠藤です。 昨今、AI の勢いは目覚ましく、弊社でも日々の開発プロセスや自社プロダクトにどのように取り入れていくか検討を重ねています。その中でも、個人的に注目しているのがブラウザ組み込みの AI です。 本記事では、 Google Chrome が現在取り組んでいるブラウザ組み込み AI の動向に触れつつ、この記事の公開時点(2025年12月11日)で実際に利用できる機能を中心に紹介していきます。 Google Chrome の組み込み AI 提供されている API 動作要件 ブラウザ組み込み AI の API を試してみる TypeScript 型定義 可用性の確認 各 API の使い方 Language Detector API 基本的な使い方 Translator API 基本的な使い方 ストリーミング翻訳 Summarizer API 基本的な使い方 ストリーミング要約 おわりに 参考リンク Google Chrome の組み込み AI Google Chrome の組み込み AI は、ブラウザに組み込まれた AI モデルを、ブラウザ API を通して利用できる仕組みです。モデルのデプロイや管理、セルフホスティングを開発者が行わずに、アプリケーションに AI を組み込むことができます。 クライアントサイド(ブラウザ)で処理が完結するため、オフライン利用や機密データのローカル処理などのメリットがあります。また、従来のサーバーサイド AI よりも実装が簡潔になる可能性があり、AI 機能を手軽に取り込める点も魅力の一つです。 提供されている API 本記事公開時点(2025年12月11日)で Google Chrome が公開している組み込み AI の API は以下の通りです。最新のステータスは 公式ドキュメント を確認してください。 API 機能概要 Web 拡張機能 Translator API 言語翻訳 Chrome 138 Chrome 138 Language Detector API 言語自動判定 Chrome 138 Chrome 138 Summarizer API テキスト要約 Chrome 138 Chrome 138 Prompt API 汎用的なプロンプト Origin Trial Chrome 138 Writer API 特定のタスクに応じた文章生成 Origin Trial Origin Trial Rewriter API テキストのリライト Origin Trial Origin Trial Proofreader API テキストの校正 Origin Trial Origin Trial 本記事では、このうち現時点で利用できる Translator / Language Detector / Summarizer の 3 つについて使い方を紹介します。 なお、本記事は Google Chrome での利用を前提にしていますが、 Web Machine Learning Community Group にて標準化の取り組みが行われており、今後は他ブラウザでも利用可能になることが期待されています。 動作要件 Google Chrome の組み込み AI を利用するためには、モデルとハードウェアに関する要件があります。これらは今後更新される可能性があるため、最新の情報は 公式ドキュメント を参照してください。 ブラウザ組み込み AI の API を試してみる TypeScript 型定義 TypeScript を利用する場合は、次のパッケージを追加することで型補完とエラーチェックが有効になります。 npm install --save-dev @types/dom-chromium-ai 可用性の確認 各 API を利用する前に、非同期の availability() 関数を呼び出すことで、利用可能かどうかを確認できます。 // LanguageDetector API の可用性を確認する例 const availability = await LanguageDetector . availability () ; console . log ( availability ) ; availability() は以下の値を Promise で返します。 値 意味 available 利用可能 downloadable モデルのダウンロードが必要 downloading モデルのダウンロードを進行中 unavailable 利用不可(ブラウザがサポートしていない・動作要件を満たしていないなど) 各 API の使い方 現時点で Google Chrome で利用可能な Translator / Language Detector / Summarizer の API について、それぞれ使い方を確認していきます。 Language Detector API 入力テキストの言語を自動判定する API です。入力されたテキストに対して、使用されている言語を確率順にランク付けして返します。多言語フォームにおける入力言語判定や、後述する Translator API と組み合わせた自動翻訳などに活用できます。 基本的な使い方 if ( ! ( "LanguageDetector" in self )) return; // LanguageDetector API の可用性確認 const availability = await LanguageDetector . availability () ; if ( availability === "unavailable" ) return; if ( navigator . userActivation . isActive ) { // アプトポッド公式サイト(https://www.aptpod.co.jp/)より紹介文を抜粋 const input = "アプトポッドは高速双方向なデータストリーミング技術をベースに、産業向けの高速IoTプラットフォームミドルウェア、及びクライアントアプリケーションからエッジハードウェアまでワンストップに開発・提供しています。自動車、ロボット、建機、農機など、様々なモビリティや産業機器をクラウドへ接続し、高精細な遠隔データ収集と分析、リアルタイム監視、遠隔制御、およびデジタルツインの実現など、革新的な産業DXに貢献します。" ; // LanguageDetector インスタンスの作成 const detector = await LanguageDetector . create ({ monitor ( m ) { // モデルのダウンロード進捗を監視 m . addEventListener ( "downloadprogress" , ( e ) => { console . log ( `Downloaded ${ e . loaded * 100 } %` ) ; }) ; } , }) ; // 言語判定の実行 const results = await detector . detect ( input ) ; console . log ( JSON . stringify ( results , null , 2 )) ; /* [ { "confidence": 0.9980313777923584, "detectedLanguage": "ja" }, { "confidence": 0.0000766943849157542, "detectedLanguage": "und" } ] */ } detect() は、 { detectedLanguage, confidence } オブジェクトの配列を Promise で返します。 confidence は 0.0(信頼度が最も低い)から 1.0(信頼度が最も高い)までの値で表されます。 上記の例では、期待通り ja (日本語)が最も高い信頼度で検出されているのがわかります。 Translator API テキストを別の言語に翻訳する API です。アプリケーションの多言語化はもちろん、チャットやユーザー投稿コンテンツのオンデマンド翻訳などに活用できます。 基本的な使い方 if ( ! ( "Translator" in self )) return; // Translator API の可用性確認 const availability = await Translator . availability ({ sourceLanguage : "ja" , targetLanguage : "en" , }) ; if ( availability === "unavailable" ) return; if ( navigator . userActivation . isActive ) { // アプトポッド公式サイト(https://www.aptpod.co.jp/)より紹介文を抜粋 const input = "アプトポッドは高速双方向なデータストリーミング技術をベースに、産業向けの高速IoTプラットフォームミドルウェア、及びクライアントアプリケーションからエッジハードウェアまでワンストップに開発・提供しています。自動車、ロボット、建機、農機など、様々なモビリティや産業機器をクラウドへ接続し、高精細な遠隔データ収集と分析、リアルタイム監視、遠隔制御、およびデジタルツインの実現など、革新的な産業DXに貢献します。" ; // Translator インスタンスの生成 const translator = await Translator . create ({ sourceLanguage : "ja" , // BCP-47 言語コード targetLanguage : "en" , // BCP-47 言語コード monitor ( m ) { // モデルのダウンロード進捗を監視 m . addEventListener ( "downloadprogress" , ( e ) => { console . log ( `Downloaded ${ e . loaded * 100 } %` ) ; }) ; } , }) ; // 翻訳の実行 const result = await translator . translate ( input ) ; console . log ( result ) ; /* Based on high-speed, bidirectional data streaming technology, Aptpod develops and provides one-stop development and delivery of high-speed IoT platform middleware for industrial use, as well as client applications to edge hardware. Connect a variety of mobility and industrial equipment, including automobiles, robots, construction machinery and agricultural machinery to the cloud, and contribute to innovative industrial DX, including high-definition remote data collection and analysis, real-time monitoring, remote control, and realizing digital twins. */ } translate() は翻訳されたテキストを Promise で返します。 上記での例では、 create() 関数の引数で sourceLanguage と targetLanguage で指定した日本語から英語への翻訳が実行されているのがわかります。 ストリーミング翻訳 より長いテキストを翻訳する場合、ReadableStream を返す translateStreaming() を利用することもできます。 // 翻訳の実行 const stream = translator . translateStreaming ( input ) ; for await ( const chunk of stream ) { console . log ( chunk ) ; } Summarizer API 長いテキスト(記事、ドキュメント、チャット履歴など)を簡潔に要約する API です。長い記事の見出し表示や、会議議事録のサマリー作成などに活用できます。 基本的な使い方 if ( ! ( "Summarizer" in self )) return; // Summarizer API の可用性確認 const availability = await Summarizer . availability ({ type : "key-points" , // "tldr" / "teaser" / "key-points" / "headline" format : "markdown" , // "markdown" / "plain-text" length : "short" , // "short" / "medium" / "long" expectedInputLanguages : [ "ja" ] , // BCP-47 言語コード expectedContextLanguages : [ "ja" ] , // BCP-47 言語コード outputLanguage : "ja" , // BCP-47 言語コード }) ; if ( availability === "unavailable" ) return; if ( navigator . userActivation . isActive ) { // アプトポッド公式サイト - 代表挨拶(https://www.aptpod.co.jp/company/ceo/)より文章を抜粋 const input = `アプトポッドは「つなぐ」プロフェッショナルです 現在、自動車、建設、ロボティクスを中心とした様々な分野において、製造業の開発プロセスDX化やイノベーション創出といった数々のプロジェクトを、強みのIoT技術を駆使して、お客様とともに推進しています。当社の基幹製品である「intdash」は、あらゆる種類の産業データを超低遅延で伝送し、欠損なく時系列をそろえてサーバーに永続化するストリーミング技術を特徴としており、現在の多様なプロジェクトの中核を担っています。 数々のプロジェクトを進めるなかで多くのお客様に当社製品の実力を認めていただき、2018年の「intdash」リリース以来、大手製造業のお客様を中心として約50社100プロジェクトの実績を積み上げることができました。 「intdash」は、多種多様でマルチモーダルな産業データを、インターネットを介して、限りなくリアルタイムに、かつ、もとのデータに忠実に伝送するデータストリーミング技術の実現を目指しています。 当社のプリミティブなアプローチとしてはこれを実現するためにデータストリーミングのプロトコル開発から入り、製品の垂直水平統合を行っています。 インターネットが台頭して以降、現代社会を形成し、社会課題を解決していくには、データネットワークの活用が必要不可欠になってきています。 IoTの世界は、IT(人が情報を取得・発信する)だけで良かった時代から、OT(よりフィジカルなモノが通信する)の融合が必須となる時代に変貌しつつあります。今後さらに発展していくメタバース社会、つまりバーチャルワールドが現実世界に融合された社会においては、デジタルツインの社会実装も進行していきます。 そうしたある意味パラレルワールドを融合した社会を形成していくには、現実/仮想といった様々なレイヤやデータの種類を超えた、神経網や血管のようなマルチモーダルなデータネットワークが必要です。アプトポッドは産業シーンを主戦場として、未来志向のマルチモーダルデータネットワークを形成するための技術開発と、インフラプロダクト提供を目指しています。` ; // Summarizer インスタンスの生成 const summarizer = await Summarizer . create ({ type : "key-points" , // "tldr" / "teaser" / "key-points" / "headline" format : "markdown" , // "markdown" / "plain-text" length : "short" , // "short" / "medium" / "long" expectedInputLanguages : [ "ja" ] , // BCP-47 言語コード expectedContextLanguages : [ "ja" ] , // BCP-47 言語コード outputLanguage : "ja" , // BCP-47 言語コード sharedContext : "アプトポッドを知らない人に向けたわかりやすい説明" , // 要約の共有コンテキスト monitor ( m ) { // モデルのダウンロード進捗を監視 m . addEventListener ( "downloadprogress" , ( e ) => { console . log ( `Downloaded ${ e . loaded * 100 } %` ) ; }) ; } , }) ; // 要約の実行 const results = await summarizer . summarize ( input ) ; console . log ( results ) ; /* * アプトポッドは、自動車、建設、ロボティクスなど、様々な分野でIoT技術を活用し、製造業の開発プロセスDX化やイノベーション創出を支援しています。「intdash」という基幹製品は、産業データを低遅延でサーバーに永続化するデータストリーミング技術を特徴としています。 * 「intdash」は、インターネットを介して多様な産業データをリアルタイムに伝送するデータストリーミング技術を実現するために、データストリーミングプロトコルの開発から製品の垂直水平統合を行っています。これにより、大手製造業を中心とした約50社100プロジェクトの実績を積み上げてきました。 * 今後、メタバース社会やデジタルツインの社会実装が進む中で、アプトポッドは現実と仮想を超えたマルチモーダルなデータネットワークを形成するための技術開発とインフラプロダクト提供を目指しており、産業シーンを主戦場としています。 */ } summarizer.summarize() は要約テキストを Promise で返します。 create() 関数の引数で要約の言語や種類、長さ、出力形式などを指定できます。 上記の例では、 type に key-points 、 length に short を指定しているため、3 つの箇条書き形式の短い要約が生成されているのがわかります。 create() が引数として受け取れるパラメータには主に以下があります。 sharedContext : 要約に関する追加のコンテキスト type : 要約のタイプ(デフォルトは key-points ) tldr : 忙しい読者のために要約として作成された短く簡潔な概要 teaser : 最も興味深い点や魅力的な点を要約 key-points : 主要なポイントの箇条書き headline : 要点をとらえた記事の見出し format : 出力形式(デフォルトは markdown ) markdown : マークダウン形式 plain-text : プレーンテキスト形式 length : 要約の長さ(デフォルトは medium ) short : 短い要約 medium : 中程度の要約 long : 長い要約 ストリーミング要約 summarizeStreaming() を利用することで、ReadableStream を返すストリーミング要約も可能です。結果がリアルタイムで提供されるため、逐次的に要約を処理したい場合に便利です。 const stream = summarizer . summarizeStreaming ( input ) ; for await ( const chunk of stream ) { console . log ( chunk ) ; } おわりに ブラウザ組み込み AI によってクライアントサイドで処理が完結することは、プライバシー保護やオフラインでの利用、加えて実装面でも大きな魅力があると感じました。ユーザーの入力データを外部に送信せずに AI を利用できるため、従来のサーバーサイド AI とは異なる利点を得られます。 一方で、動作要件が通常よりもシビアであったり、ブラウザごとにサポート状況に違いが見られたりと、現時点では利用できる場面が限られます。また、Origin Trial 段階の API も多く、今後の仕様変更が発生する可能性もあります。 それでも、こうした機能が標準化され、より広く利用されるようになれば、フロントエンドの体験設計は大きく変わっていくと感じました。必ずしもクライアントサイド AI がサーバーサイド AI を置き換えるわけではなく、双方を併用するハイブリッドな構成を検討することで、より柔軟なアプリケーション設計が可能になるはずです。 intdash や Visual M2M Data Visualizer といったアプトポッドのプロダクトにおいても、活用できる余地は大きいと考えています。今後のアップデートを追いかけながら、具体的な活用方法を検討していきたいと思います。 参考リンク https://developer.chrome.com/docs/ai/built-in https://github.com/webmachinelearning
aptpod Advent Calendar 2025 12月10日の記事です。 intdashグループの呉羽です。普段はintdashサーバーの開発やintdashを利用したアプリケーションの開発を担当しています。主にGo言語を利用しています。 弊社では業務にAIを活用しており、その中でもエンジニアとして Claude Code を積極的に活用しております。そこで今回は、Claude Codeで実際の業務がどう楽になったかをご紹介します。 ※Claude Codeとは、プロンプトを元に自動でコーディングを行ってくれるAIエージェントです。具体的なチュートリアルや使い方は世に多く存在するので、ここでは割愛します。 Claude Code導入の背景 Claude Codeで楽になった4つの開発業務 1. 既存アプリケーションの改修が楽になった 2. ライブラリの調査を任せられるようになった 3. リファクタリングの敷居が下がった 4. 新規アプリケーション開発も楽になったが準備は必要 終わりに Claude Code導入の背景 Claude Code に生成してもらった ASCII Art 2025年6月以前、Claude Codeを利用するためには従量課金か月100ドルの定額プランが必要でしたが、月20ドルの定額プランでも利用できるようになりました。それがきっかけでエンジニア界隈で話題になり、私も試したところ好感触だったため、実務で利用し始めました。 Claude Code以前はGithubCopilotのような単純なコード補完だけを利用することが多く、いわゆるAIエージェントを前提とした開発手法ではありませんでした。しかしAIエージェントの便利さを覚えた現在では、それらを前提とした開発手法に切り替えています。 Claude Codeで楽になった4つの開発業務 1. 既存アプリケーションの改修が楽になった 普段の開発画面の例 まず既存アプリケーションの機能追加や改修が楽になりました。特に触れるのが初めてだったり久しぶりだったりするアプリケーションは、全体像の把握と改修箇所の特定に労力が必要です。そのような場面は、Claude Codeに指示して調査結果をまとめさせることで手間が省けるようになりました。 大規模な既存アプリケーションの改修の場合、 /init コマンドで生成したCLAUDE.md(AIエージェントが参照するアプリケーションの概要書)だけではなく、機能別にドキュメント化することが大切だと感じています。 アプリケーション全体にどのような機能があるか調査してもらう。 調査で得た大まかな機能ごとに、どのようなアーキテクチャやデータフローになっているかを調べさせ、Markdownとして保存してもらう。 CLAUDE.mdに保存したMarkdownのリンクを記載する。 こうしておくことで、AIエージェントが毎回大規模なコードリーディングを行うことなく効率的にアプリケーションの構造を把握してくれるようになり、時間やコンテキストの節約にもなります。 2. ライブラリの調査を任せられるようになった アプリケーションの開発で、何らかのサードパーティのライブラリを利用することはよくあります。しかし時折、望んでいる機能の実現可能性や、具体的な使い方を調べたいときがあります。その際は、ライブラリをgit cloneしてClaude Codeに調査を指示することで、手間を掛けずに調べられるようになりました。 また具体的なサンプルコードを書いてもらい、それを実装の際にAIエージェントに渡すことで、ライブラリを利用した実装を正確に行ってくれます。 3. リファクタリングの敷居が下がった 次にリファクタリングです。特にリファクタリングは、AIエージェントを利用する際に重要度が高まったと感じています。例えばAIエージェントが、既存のよくないコードに影響されたかのような実装をする場面を何度か体験しました。 その際はリファクタリングを検討しますが、このリファクタリング作業も楽になります。既存アプリケーションの改修と同様、リファクタリング前にはコードの意図やテストケースをClaude Codeに調査してまとめさせます。その上で人間の慎重なコードレビューは必要ですが、以前と比べると敷居が下がったのは間違いありません。 4. 新規アプリケーション開発も楽になったが準備は必要 いくつかの新規アプリケーションの開発でもClaude Codeを活用しました。ただ新規開発は既存アプリケーションの改修とは違い、AIが参照できる土台がありません。そのためClaude Codeにとっては判断材料が少なく、意図しない設計方針になることが多々あります。 それらを防ぐために、ガードレールとしていくつかの実装やドキュメントを予め書いておくことが大切です。また弊社では、社内で統一化されたログ構造やCLI構造にする必要があるため、社内ライブラリなどの説明も欠かせませんでした。逆にそれらを準備さえしておけば、後は既存アプリケーションと同様に効率的な開発が可能です。 終わりに 以上がAIエージェントを実務で活用した話です。半年間ほぼ毎日のように向き合ってきましたが、AIエージェントは自分の思い通りだけ動いてくれる銀の弾丸ではありませんでした。例えば、曖昧な仕様の理解のままに適切な指示を出すことは出来ませんし、指示を出したとしても望んだ通りのものは出来上がりません。人間が成果物の責任を持つ以上、どうしても人間側の理解や判断がボトルネックとして残ります。 それでも、AIエージェントが開発効率を良い方向に変えたことは間違いありません。人間がより本質的な部分に集中するための土台として、今後も適切な距離感で活用していきたいと考えています。
こんにちは、ソリューションアーキテクトの尾澤です。 この記事は 「aptpod Advent Calendar 2025」 の12月9日の記事です。 皆さんは ChatGPT や Gemini のような「LLMチャットツール」をどのように活用していますか?PDF資料を分析するためにNotebook LMのような「RAGツール」を活用する場面もあるでしょう。とても便利で、すでに仕事道具として手放せないという人も多いのではないでしょうか? 本記事では、これらのツールをSaaSに頼らずオンデバイスで動かせるように、必要な構成と手順を紹介していきます。 なぜオンデバイスなのか 情報漏洩リスクの回避 外部依存の回避 オフライン・エッジ用途への転用 デメリット 動作環境 本記事で使用した環境 LLMチャットを動かす モデルエンジン Ollamaとは LLMのモデル入手 動作確認 チャットUI Open WebUIとは 実際に使ってみる 違うモデルを使ってみる 検索機能をつける コンテナを終了する RAGツールを動かす RAGツールとは Open Notebookとは 初期設定 埋め込みモデルとは 埋め込みモデルの入手 モデルの設定 実際に使ってみる Macユーザの場合 Apple Siliconの方向性 まとめ なぜオンデバイスなのか オンデバイスでAIを動かすメリットは、大きく以下の3つが考えられます。 情報漏洩リスクの回避 SaaSは手軽で便利である一方、データが外部に送信されることが前提です。顧客資料・非公開の内部資料・個人情報などの機密データを「外部に出せない」という要件は珍しくありません。 また、今年2025年7月には、OpenAIのサム・アルトマンCEOが「ChatGPTには守秘義務がなく法的請求があれば会話内容が開示されるため、心の闇や秘密をすべてさらけ出すのはやめたほうがいい」と警告しています。 オンデバイスであれば、そもそもデータが外部に送信されることがないため、安心してAIを使えます。 外部依存の回避 SaaSを利用することは、サービス提供者によるモデル変更・料金改定・レートリミットなどに依存することにもなります。 オンデバイスであれば、そういった外部要因に影響されることなく、UIやツールチェーンを変更せずにモデルを入れ替えながらワークフローを維持できます。 オフライン・エッジ用途への転用 レイテンシ要件が厳しいユースケースや、ネットワーク帯域が弱い環境など、システム構成にSaaSを組み込めないことがあります。 オンデバイスであれば、場所を選ばずにAIを持ち込めます。 デメリット 最大のデメリットとして「SaaS独自のプロプライエタリなモデル」が使えないという点があります。 しかしその一方で、オープンなモデルが豊富なバリエーションで公開されています。 例えば、今年2025年8月にOpenAIが公開した「GPT-OSS」は、SaaSで提供していた「o3-mini」と同等の推論能力をベンチマークで示しており、こうした優れたモデルも次々と現れています。 このようなモデルを用途に応じて選定し、場合によっては追加でチューニングを行うことで、目的を実現することが十分に可能です。 オンデバイスAIの分野では、モデルの選択が重要なテーマになってきます。 動作環境 この記事では GPU を搭載した Windows 環境を前提に手順を紹介します。GPUの有無によって処理速度とユーザ体験が大きく変わるため、実用的な体験ができる環境で解説を進めます。 また、拡張性や可搬性を考慮して、すべてのコンポーネントをDockerコンテナで実行します。後述する docker-compose.yml はそのまま使えるようになっています。 本記事で使用した環境 Windows 11 CPU: Intel Core i7-14700F (2.10 GHz) GPU: NVIDIA GeForce RTX4070 Ti SUPER (16GB) RAM: 16GB Docker Desktop + NVIDIA Container Toolkit 実は、このGPU環境は、小学生の息子がマイクラのMODやらコマンドやらに興味を持ち始めたのをいいことに、それを口実にして家庭内稟議を通して購入したゲーミングPCです。 本当は私自身が、都市開発シミュレーションゲーム「Cities Skylines II」をやりたくて、虎視眈々と狙っていたのです。 この度、このマシンがゲーム以外の分野で活躍できることに興奮しております。 LLMチャットを動かす それでは早速、LLMチャットを動かしていきましょう。 以下のGitリポジトリをダウンロードしてください。 https://github.com/shumaijp/local-llm-chat-docker-compose services : ollama : # image: ollama/ollama:latest image : ollama/ollama:0.13.1 container_name : ollama-chat ports : - "11434:11434" volumes : - ollama-data:/root/.ollama deploy : resources : reservations : devices : - driver : nvidia count : 1 capabilities : [ gpu ] open-webui : # image: ghcr.io/open-webui/open-webui:main image : ghcr.io/open-webui/open-webui:v0.6.41 container_name : open-webui ports : - "3030:8080" environment : - OLLAMA_BASE_URL=http://ollama:11434 volumes : - open-webui-data:/app/backend/data depends_on : - ollama searxng : # image: searxng/searxng:latest image : searxng/searxng:2025.12.7-9d3ec9a2a container_name : searxng ports : - "8080:8080" volumes : - ./config/searxng:/etc/searxng:rw volumes : ollama-data : name : shared-ollama-data open-webui-data : モデルエンジン まずは、LLMの実行環境について説明します。 Ollamaとは Ollamaは「LLM版のDocker」と表現すると分かりやすいかもしれません。Dockerがコンテナを対象とするように、OllamaはLLMを対象として、実行エンジン・CLIツール・公開リポジトリを提供します。 LLMのモデル入手 OllamaのリポジトリにあるLLMは以下のURLで確認できます。 https://ollama.com/library Ollama Library それぞれのモデルには「8b」「20b」のようなタグが表記されています。タグにある数字はパラメータの数を示しており、AIモデルの脳細胞の数のようなものです。パラメータが多いほど賢く知識が豊富でアウトプットの質が高い反面、メモリやGPUなどのリソースをより多く消費します。 使用するときは「モデル名:タグ名」という形式で指定します。 今回はまず、軽量でポピュラーな「gemma2:2b」を使ってみます。コンテナを起動してCLIツールを使ってダウンロードしてみましょう。 docker compose up -d docker exec ollama-chat ollama pull gemma2:2b 動作確認 Ollamaコンテナが正しく動いているかCLIでAPIを叩いて確認してみましょう。 curl http://localhost:11434/api/generate \ -d '{"model": "gemma2:2b", "prompt": "Hello"}' 以下のように、レスポンスが返ってくれば正常に動いています。 {"model":"gemma2:2b","created_at":"2025-12-06T06:52:59.907909427Z","response":"Hello","done":false} {"model":"gemma2:2b","created_at":"2025-12-06T06:52:59.980637427Z","response":"!","done":false} {"model":"gemma2:2b","created_at":"2025-12-06T06:53:00.07509926Z","response":" 👋","done":false} .... チャットUI つぎに、UIについて説明します。 Open WebUIとは Open WebUIは、LLMを「ChatGPTっぽい快適なUIで使えるようにする」ためのWebアプリです。 LLMが「バックエンド」、Open WebUIが「フロントエンド」という役割分担になっています。 Open WebUIの環境変数(OLLAMA_BASE_URL)でOllamaをバックエンドに指定することで、チャット画面の裏側でLLMへのAPIリクエストが走る仕組みになっています。 実際に使ってみる コンテナが起動している状態で、 http://localhost:3030 にブラウザでアクセスしてみてください。 初回アクセス時は、ユーザ登録画面が表示されます。アカウントを作成してログインすると、下図のような ChatGPT ライクな画面が表示されます。 使用モデルが「gemma2:2b」になっていることを確認して、チャットを開始してみましょう。 gemma2:2bの結果 違うモデルを使ってみる 動作確認のために軽量な「gemma」を使いましたが、他にもMicrosoftの「phi」、Metaの「llama」、Alibabaの「Qwen」など多くのLLMが公開されており、GGUF(GPT-Generated Unified Format)というファイルフォーマット規格によって、これらを同じプラットフォーム上で切り替えて使えるようになっています。 試しにOpenAIの「gpt-oss:20b」をダウンロードして使ってみましょう。 docker exec ollama-chat ollama pull gpt-oss:20b ダウンロード済みのモデルは以下のコマンドで確認できます。 % docker exec ollama-chat ollama list NAME ID SIZE MODIFIED gpt-oss:20b 17052f91a42e 13 GB 3 minutes ago gemma2:2b 8ccf136fdd52 1.6 GB 4 hours ago モデルを「gpt-oss:20b」に切り替えて、先ほどと同じプロンプトを投げてみましょう。 gpt-oss:20bの結果 このように、モデルによって推論結果が大きく変わってきます。 検索機能をつける ChatGPTなどのLLMチャットが、もともと学習していない情報をウェブ検索で補って回答してくれるようになってから、利便性がグッとあがりましたよね。 オンデバイスでも、インターネットに出られる環境であれば同じことが可能です。 ユーザアイコンをクリックしたメニューから「設定」→「管理者設定」に進んで「ウェブ検索」を有効にし、「ウェブ検索エンジン」を指定します。APIキーを用意すれば、GoogleやPerplexityなどのSaaSも使えますが、今回は情報漏洩リスクの回避もひとつのテーマなので、メタ検索エンジンである「SearXNG」を使ってみましょう。すでに docker-compose.yml に定義してあるコンテナのそのエンドポイント「 http://searxng:8080 」を指定して、設定を保存してください。 ウェブ検索の設定 設定が終わったらプロンプトに戻ります。プロンプトの「Integration」のアイコンから「ウェブ検索」を有効にして、インターネットを参照しないとわからないようなことを尋ねてみましょう。 ウェブ検索ありの結果 ウェブから情報を取得して回答してくれました。メタ検索エンジンの SearXNG を介しているので、Google等に直接ユーザのIPアドレスやクエリが送信されることはありません。 コンテナを終了する 使い終わったらコンテナを終了させておいてください。 docker compose down 本記事では、ユースケースごとの分かりやすさと学習のしやすさのため、LLMチャット用とRAGツール用でDocker Compose環境をそれぞれ分けて紹介しています。 このあと説明するRAGツールでもOllamaコンテナを使用しますが、両方のユースケースを同時に起動するとポートが衝突するため、それぞれ別タイミングで起動する前提としています。 RAGツールを動かす チャットの次は、Notebook LMのようなRAGツールを動かしてみましょう。 RAGツールとは ChatGPTやGeminiは使ったことあるけど、Notebook LMは使ったことないという人もいるかもしれません。 RAGツールは、特定のウェブページやファイルを読み込ませることで、LLMに対象ドメインを与えて使う仕組みです。 LLMチャットツールが「世界中の知識をもとに答えるAI」であるのに対して、RAGツールは「渡された資料を読んで答えるAI」です。 Googleの「Notebook LM」は、この代表的なツールです。 Open Notebookとは Notebook LMのようなRAG体験をオンデバイスで再現できるのが 今回使用する「Open Notebook」です。 https://www.open-notebook.ai/ Open WebUIと同じように、裏側でLLMへのAPIリクエストが走る仕組みになっています。 以下のGitリポジトリをダウンロードしてください。 https://github.com/shumaijp/local-opennotebook-docker-compose services : ollama : # image: ollama/ollama:latest image : ollama/ollama:0.13.1 container_name : ollama-rag ports : - "11434:11434" volumes : - ollama-data:/root/.ollama deploy : resources : reservations : devices : - driver : nvidia count : 1 capabilities : [ gpu ] open_notebook : # image: lfnovo/open_notebook:v1-latest-single image : lfnovo/open_notebook:1.2.3-single container_name : open-notebook ports : - "8502:8502" # Web UI - "5055:5055" # API environment : - API_URL=http://127.0.0.1:5055 - OLLAMA_API_BASE=http://ollama:11434 # Database connection (required) - SURREAL_URL=ws://localhost:8000/rpc - SURREAL_USER=root - SURREAL_PASSWORD=root - SURREAL_NAMESPACE=open_notebook - SURREAL_DATABASE=production volumes : - notebook-data:/app/data - surreal-data:/mydata depends_on : - ollama volumes : ollama-data : name : shared-ollama-data notebook-data : surreal-data : なお、上記で使用しているイメージ(lfnovo/open_notebook:1.2.3-single)は、Open Notebookを構成するコンポーネントがすべて入っているオールインワン・イメージです。 中身は「フロントエンド」と「バックエンド(RAG)」と「データベース(SurrealDB)」で構成されており、バックエンドとデータベースだけ立ててAPI経由で活用する、という使い方も可能です。 初期設定 RAGを実現するためには、LLMの他に「埋め込みモデル(Embedding Model)」という別の役割のモデルが必要です。 埋め込みモデルとは 埋め込みモデルとは、テキストや画像などのデータを数値のベクトルに変換するモデルのことで、RAGが与えられた情報を解釈するために必要なものです。 意味的に近いデータがベクトル空間上でも近くに配置されることによって、データの類似性を理解できるようになるというものです。 埋め込みモデルの入手 それでは、コンテナを起動して埋め込みモデルをダウンロードしていきましょう。 今回は速度や精度のバランスが最も優れていると言われている「mxbai-embed-large」を使用します。 docker compose up -d docker exec ollama-rag ollama pull mxbai-embed-large なお、今回のコンテナ構成では、Ollama用にダウンロードしたモデルは「ollama-data」という名前付きボリュームに格納されるようになっています。これにより、RAGツール用の「ollama-rag」コンテナと、先ほどのチャット用の「ollama-chat」コンテナは、ダウンロードしたモデルを共有できるようになっています。 それでは、 http://localhost:8502 にブラウザでアクセスしてみてください。 Open Notebook モデルの設定 Open WebUIと違ってモデルを使うための初期設定が必要です。 左ペインの「MANAGE」→「Models」から「Model Management」の画面を開きます。 まず、「API Providers」のセクションで「Ollama」が有効になっていることを確認してください。 Open Notebookの設定画面 「Default Model Assignments」のセクションで、Open Notebookが使用する様々なモデルを指定しますが、そのためにモデルをあらかじめ登録しておく必要があります。 「Language Models」のセクションで、ダウンロード済みの「gpt-oss:20b」を言語モデルに登録しましょう。「+ Add Model」をクリックし、Providerを「Ollama」、Model Nameに「gpt-oss:20b」を入力して「Add Model」してください。 Language Modelの登録 「Embedding Models」のセクションで、ダウンロード済みの「mxbai-embed-large」を埋め込みモデルに登録しましょう。同じく画面下の「+ Add Model」をクリックし、Providerを「Ollama」、Model Nameに「mxbai-embed-large」を入力して「Add Model」してください。 Embedding Modelの登録 「Default Model Assignments」のセクションに戻ると、登録したモデルを指定できるようになっているので、必須マークがついている Chat Model と Transformation Model に「gpt-oss:20b」を、Embedding Model に「mxbai-embed-large」を設定してください。 モデル設定 実際に使ってみる それでは使ってみましょう。 本記事ではデモとして、MQTTのRFCドキュメントを分析対象にしてみます。 まず「+ New Notebook」からNotebookを作ります。 Notebookの作成 つぎに「+ Add Source」→「+ Add New Source」から、参照する資料をURL・ファイル・プレーンテキストのいずれかで追加します。 今回は、RFCのURL「 https://www.rfc-editor.org/rfc/rfc9431.html 」を指定します。 ソースの追加 登録したSourceのベクトル解析が終わったら質問してみましょう。 あえて「MQTTの」とは言わずに「QoS 0/1/2 の違いを要約して」と入力してみると、ちゃんとRFCを読んで「MQTTのQoS」について回答してくれました。 RAGの結果 一見あいまいな質問ですが、ChatGPTのように話題がズレることなく、与えられた情報の範囲内で答えを探してくれます。 このように、推論の前提となる情報源が「指定した資料」に限定されるため、一般的なLLMチャットにありがちなハルシネーションが起こりにくいのが、RAGの特徴です。 Macユーザの場合 本記事で解説したツールは、Apple Silicon Mac でも問題なく動作します。 手順もほぼ同じで、docker-compose.yml をGitリポジトリに用意した docker-compose-cpu.yml に読み替えるだけで動きます。 # GPU環境の場合 docker compose up -d # 非GPU環境の場合 docker compose -f docker-compose-cpu.yml up -d ただし、macOSではApple SiliconのGPUをDockerから使えないため、同じモデルでも推論速度は大きく低下します。 OllamaをDockerではなくシステム上で動かすことで、Apple SiliconのGPUが活かされある程度のパフォーマンスは期待できます。 brew install ollama ollama serve しかし、実際に普段業務で使用している M4 MacBook Pro でも試してみましたが、Metalサポートが進んでいるとはいえ、CUDA対応GPUに最適化されたモデルではやはり性能差は歴然です。 「まず手元の環境でLLMに触ってみたい」場合にはMacでも十分ですが、「日常的に生産性ツールとして使いたい」場合は、GPU環境のほうが圧倒的に快適です。 以下は「GPU Windows + Ollama on Docker」と「M4 Mac + Ollama on Docker」と「M4 Mac + Ollama on System」の3つの環境で同じプロンプトの性能を比較した表です。 環境 gemma2:2b gpt-oss:20b 推論リソース GPU Windows + Ollama on Docker 6.24 tokens/sec 2.11 tokens/sec CUDA/GPU M4 Mac + Ollama on System 1.60 tokens/sec 0.68 tokens/sec Metal/GPU M4 Mac + Ollama on Docker 0.45 tokens/sec 0.13 tokens/sec CPU Apple Siliconの方向性 ただし、この結果は決して「Applie Siliconが遅い」という話ではありません。 Apple Siliconはそもそも「AIをオンデバイスで高速かつ省電力で動かすこと」をターゲットに設計されています。 そのため、Macユーザが本来とるべきアプローチは、NVIDIAスタックで学習したモデルをそのまま動かすことではなく、それをCore ML 形式に最適化して macOS / iOS / visionOS などで動かすことです。 ですので、前述の比較表は優劣を比較するためのものではなく、あくまで参考値として見ていただけると幸いです。 すでに、Meta・Mistral・Alibaba などの主要モデルが Core ML 版を公開しており、Apple Silicon 上での AI 活用は来年以降もさらに実用化が進んでいきそうだと感じています。 本記事では「NVIDIAスタックで学習されたモデルを動かす」という前提のため Core ML 最適化には触れていませんが、こちらの動向も把握しておくと良いと思います。 まとめ LLMやRAGをオンデバイスで動かすことで、機密データをクラウドに出さずにAIの恩恵を受けられるだけでなく、それをそのままエッジに持ち込めるというメリットがあります。 これは産業IoTにおいても重要なテーマで、エッジ環境における「セキュリティ」「レイテンシ」「ネットワーク」などの要件を、AIにも適用できるということになります。 今回紹介した構成はデスクトップでの検証用途ですが、アプリケーション層とモデル層がAPI分離されているため、ゲートウェイやMEC環境への移植も可能です。 もし「こんなことをAIでできないか?」というアイデアが浮かんだ時、今回構築した環境がその入口になれば嬉しいです。
aptpod Advent Calendar 2025 12月8日の記事です。 こんにちは、デザインチームの上野です。 はじめに QGISをつかってGEO TIFFファイルを書き出す QGISとは QGISのインストール 地図の領域を設定しGEO TIFFファイルを書き出す XYZタイルを用意し、レイヤーに追加する 測地系を変更する 書き出ししたい領域を矩形レイヤとして定義する GEO TIFF画像を書き出す [おまけ]領域の緯度経度を抽出する BlenderでGEO TIFFを読み込んで3Dマップ加工する Blenderとは Blenderのインストール Blender GISをつかう プラグインをインストールする 画像のインポート 建物の追加 モデルの調整 道路のトレースとモデルの追加 マテリアルの変更 完成 まとめ はじめに 近年、自動運転、都市計画、拡張現実(AR)、ゲーム開発といった様々な分野で デジタルツイン の需要が高まっています。 2Dマップや平面図では表現しきれなかった奥行きや構造物などを立体的に見ることができる 3Dマップ はこれらの先端技術を実用化するための鍵となっています。 しかし、本格的な3Dマップを作るとなれば制作の工程は複雑になりコストも高価になりがちです。 そこで本記事では、地理空間データの処理・分析に特化した無償のオープンソースGISソフトウェア 「QGIS」 と、無料の3Dモデリングツール 「Blender」 を連携させ、効率的かつ低コストで3D地図を作成する手法を紹介します。 以下の画像はQGISとBlenderをつかって作ったオフィス周辺のエリアの3Dマップ画像です。 本記事の手順を実施すると、下図のような3Dマップが作成できます。 作成した3Dマップは地形や建物の立体モデルとしてAR/ゲーム/都市計画/ロボティクス/自動運転の背景などに活用できます。 例えば走行中の車両のGPSデータと連携することで空間を視覚的に捉えることができるなど2Dのみではできなかった体験が可能となります。 作り方ですが QGISをつかってGEO TIFFファイルを書き出す BlenderでGEO TIFFを読み込んで3Dマップ加工する と、とてもシンプルな手法で作成しています。 QGISをつかってGEO TIFFファイルを書き出す QGISとは QGISは無料で使えるオープンソースのデスクトップ型地理情報システムソフトウェアで、地図データの表示、作成、編集、そして分析などが行えるアプリケーションです。 qgis.org QGISのインストール まずはQGISをインストールします。 QGISの公式サイト( https://www.qgis.org/download/ )にアクセスします。 寄付をしない場合は「Skip it and go to download」ボタンをクリックします。 ダウンロードページで、「長期リリース版(LTR)」の「QGIS Standalone Installer (64 bit)」などのインストーラーをクリックしてダウンロードを開始します。 ダウンロード後、インストーラーにしたがってインストールを行います。 地図の領域を設定しGEO TIFFファイルを書き出す インストールが完了したらQGISを起動させます。 ここでQGISで書き出したGEO TIFFは、後述するBlender側で「地形を生成する元データ」として使用します。 XYZタイルを用意し、レイヤーに追加する XYZタイルは、Web地図を高速に表示するために、地図画像を一定の大きさのタイルに分割し、それをサーバーが提供する仕組みです。 QGISでは、「XYZ Tiles」接続を利用することで、インターネット経由で配信されているタイル地図を簡単にプロジェクトに追加し、背景地図として活用できます。 まず、XYZタイルを右クリックし、接続を追加します。 ここではGoogle Mapの衛星写真を使用したいと思います。 名称を入力後、URLに https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z} と入力し[OK]を押します。 他のタイル情報に接続したい場合は XYZ Tiles(地図タイル)のURL一覧 を参考にしてください。 追加した接続をレイヤーにドラッグすれば地図が表示されます。 測地系を変更する 地図やGISで測地系が異なると、同じ緯度・経度を指していても、地球上の実際の位置が数メートルから数百メートルずれて表示されてしまいます。 そのため、異なるデータソースを重ね合わせて使う際は、必ず同じ測地系に統一する必要があります。 まずはプロジェクトで使用される座標系の変更を行います。 画面右下の [EPSG:〜]と書かれている箇所をクリックします。 設定画面がでたら測地系を選択します。 日本では平面直角座標系が全国で使用されています。 各都道府県で割り当てられている系統がことなるので こちら を参考に変更してください。 今回作るモデルは東京エリアにあるので該当する JGD2000 Japan Plane Rectangle CS IX を指定し、OKを押します。 座標系が変更されました。 書き出ししたい領域を矩形レイヤとして定義する 座標系が変更できたら書き出したい領域を設定していきます。 左上にある[新規シェープファイルレイヤ]をクリックし、以下の画像のように編集してレイヤを追加します。 レイヤ追加後は編集できるようになります。 [編集モード切り替え]を行えばいつでも地物の追加や削除など再編集することができます。 地図上の2箇所をクリックすることで矩形が生成されます。 またレイヤのスタイルは細かく設定することができます。 GEO TIFF画像を書き出す 書き出したい矩形を作成できたらGEO TIFFとして書き出します。 [OK]を押したら自動的に設定されたディレクトリにGEO TIFF画像が書き出されます。 次はBlenderの作業に入ります。 [おまけ]領域の緯度経度を抽出する QGISを使うメリットの一つとして、座標データを取得できることが挙げられます。 先ほど作成した矩形の四隅の平面直角座標を取得してみます。 矩形レイヤを選択し[ベクタ]→[ジオメトリツール]→[頂点を抽出]を選択します。 入力レイヤが合っているか確認し[実行]を押します。 そうすると矩形の四隅が抽出された 出力レイヤ が追加されます。 出力レイヤを選択した状態で[フィールド計算機]を押します。 属性テーブルに追加するフィールド名や計算式を以下のように設定します。 フィールドの名前を入力(任意の文字列) フィールド型を[小数点付き数値]にし、フィールド長の小数点以下の桁数を調整 式に $x と入力 (Y座標の場合は $y ) X座標とY座標でそれぞれ行います。 出力レイヤを右クリックし、メニューから[属性テーブル]を押します。 別ウィンドウが立ち上がり、先ほど計算したX座標、Y座標がテーブルで表示されます。 このとき、出力レイヤのスタイルでラベルをつけておくとどこの座標がどの位置にあるか視覚的にわかりやすくなります。 取得した値は平面直角座標系をベースにしたものでメートル単位の値になっています。 国土地理院のツール などを使用し変換することで緯度経度の値を取得することができます。 今回は外部ツールを使いましたが、もしかしたらQGIS内で変換できるかもしれません。 今後まだまだ機能含めてQGIS周りを調査していきたいと思います。 以上のようにして領域の矩形の四隅の緯度経度を抽出することができました。 BlenderでGEO TIFFを読み込んで3Dマップ加工する ちょっとしたおまけを挟みましたが、改めてBlenderでの作業にはいります。 Blenderとは Blenderは、オープンソースで無料の統合型3Dコンテンツ制作ソフトウェアです。 幅広い機能により、Blenderは映画制作、ゲーム開発、建築ビジュアライゼーション、プロダクトデザイン、3Dマップの作成など、様々な分野で世界的に利用されています。 www.blender.jp Blenderのインストール Blenderをインストールします。 Blenderの公式サイト( https://www.blender.org/ )にアクセスします。 トップページにある「Download Blender」ボタンをクリックします。ダウンロードページで、ご自身のOS(Windows、macOS、Linux)に対応した最新版の「Blender x.xx」のボタンをクリックし、インストーラーをダウンロードします。 ダウンロード後インストーラー起動し、インストールを完了します。 Blenderをインストールできたら起動し、 Blender GIS というアドオンを使用して画像をインポートします。 Blender GISをつかう プラグインをインストールする まずはBlender GISを使うためにプラグインをローカルにダウンロードします。 Blender GIS を開き、Clone or DownloadからDownload ZIPを選びダウンロードしてください。 BlenderでBelnder GISが使えるようにインポートします。 [編集]→[プリファレンス]を開きます。 [アドオン]を開き、右上のメニューから[ディスクからインストール]を選び、先ほどダウンロードしたZIPファイルを直接指定します。 追加されたあとチェックボックスにチェックを入れることでBlender GISが使用できるようになります。 BlenderのUIにGISのメニューが追加されます。 画像のインポート プラグインが使えるようになったらQGISから書き出したGEO TIFFをインポートします。 [GIS]→[インポート]→[Georeferenced raster(.tif .jpeg .jp2 .png)]をクリックし、書き出したGEO TIFF画像を読み込みます。 画像がインポートされ地図のモデルが生成されました。 建物の追加 Blender GISにはOSMを取得して該当エリア内のオブジェクトを生成する機能があります。 その機能を使って今回は建物を追加します。 [GIS]→[Web geodata]→[Get OSM]をクリックします。 どのOSMを取得するのかON/OFFできるので[Bulidng]をONにします。 建物のメッシュが生成されました。 モデルの調整 あとは3Dマップを使用するケースに合わせてモデリングを調整していきます。 道路のトレースとモデルの追加 例えばGPSで道路を走行するケースの場合、道路を強調したいといった目的がでてくるかと思います。 Blender GISのOSMで生成される道路は以下の画像のように生成されます。 これだと車線や道路の幅といった道路の正確性の表現がわかりにくいので、Adobe Illustratorを使って衛星写真からトレースしSVG形式で書き出します。 BlenderでSVG画像を読み込みスケールや位置などを調整するとこのようになります。 今回は大雑把にトレースしましたが白線なども同様に追加することでより詳細度を高めることができます。 マテリアルの変更 あとはお好みに合わせて各オブジェクトのマテリアルを調整します。 完成 まとめ いかがでしたでしょうか? 3Dマップを作るにあたって、最初はどうやって領域の緯度経度など値の正確性をだすのか、建物などのメッシュを一つ一つ作らないといけないのか、などとても難しいものだと考えていましたが、QGISとBlenderを使うことで十分なクオリティでデータの正確性も担保でき、かなりコストを抑えて作成できることがわかりました。 どちらも無料のソフトウェアで、使っているユーザーも多く、ネット上に有識者によるドキュメントもたくさんあるので是非調べながら手元で色々と試してみてはいかがでしょうか。
aptpod Advent Calendar 2025 12月5日の記事です。 こんにちは、QAグループのKurahashiです。 突然ですが、リグレッションテストを毎回手作業でやるの大変じゃないですか? 画面遷移を一つずつ確認して、スプレッドシートにチェック入れて...正直もっと効率化できないかなと思いますよね。 ふと「AI に任せられないかな?」と思って Claude に相談してみたら、Claude 上で直接 Playwright が動いて、自動でテストを実行できるとのこと!! まだ、お試し段階ですが「これいけるな」という感触があったので記事にしました。 やってみたこと 実際の手順 やってみてわかったこと 今後の展開 まとめ おまけ やってみたこと 今回お試しで弊社製品の「Edge Finder」で画面遷移テストを、Claude と Playwright で自動化してみました。 Edge Finder とは intdashに接続しているデバイスが送信しているリアルタイムデータをブラウザから確認するためのWebアプリケーションです。 www.aptpod.co.jp 従来のやり方 手作業で画面を一個ずつクリック スプレッドシートにチェック 今回試した方法 テストケース(CSV)を Claude に渡す Claude が Playwright で自動実行 その前に、「どうやって Claude が Playwright 動かしてるの?」って疑問に思いますよね。 答えは MCP (Model Context Protocol) です。 簡単に言うと、Claude がローカルのツールを直接操作できる仕組みです。 ┌─────────────┐ │ Claude │ ← チャットで指示 └──────┬──────┘ │ MCP ┌──────┴──────┐ │ Playwright │ ← Claude が直接実行 └─────────────┘ なので先ずは、MCP の設定です。 ただ、これがくせ者で...私は苦労しました😅 環境は人それぞれなので、ここでは私が特にハマった3つのポイントを記載しておきます。 JSON構文の末尾コンマ抜けや括弧の閉じ忘れ。 @playwright/mcpとは別に npx playwright install が必須。 設定後のClaude App完全再起動を忘れずに! 実際の手順 「ここからが本番」と意気込みましたが、環境整備が終わった時点でほぼゴールでした。 試しに今まで使っていたテストケースを投げると自動でブラウザが起動しテストをサクッとこなしていきました。(あまりの早さに呆然と眺めているだけで終わってました...) 1.テストケースを CSV で用意 普段使ってる Googleスプレッドシートをそのまま CSV でダウンロード。 特別なフォーマットは不要です。 2.Claude に投げる Claude Desktop に CSV をアップロードして、こんな感じで頼みました。 このCSVのテストケースをPlaywrightで実行してください。 対象URL: https://*****.*****.jp/console/edges/ 3.Claude が自動実行 Claude が自動で以下の作業を進めてくれます。 CSV を読んで理解 Playwright のコードを生成(裏側で) 実際にブラウザ起動してテスト実行 結果をレポートにまとめてくれる(一部抜粋ですがこのような形で結果を出力してくれます) やってみてわかったこと ✅ とにかく楽 CSV 渡すだけで自動テスト完了 コード書く必要なし ✅ 試行錯誤しやすい エラーが出ても、その場で Claude に相談 会話しながら直せる ✅ プログラミング知識不要 コマンド打たなくていい エディタも不要 ✅ テストケースを詳しく書いていたのが正解だった 今まで「細かすぎかな?」って思っていましたが、これが Claude には助かるらしい。 前提条件がある → どの画面から始めればいいかわかる ボタン名が具体的 → どのボタンを押せばいいかわかる 期待値が明確 → 検証条件をそのまま実装できる 人間が読んでわかりやすいテストケースは、AI にもわかりやすい ってことですね。 今後の展開 今回はお試しで Edge Finder の画面遷移テストだけやってみました。 予想以上にうまくいったので、今後は 他製品の画面遷移テストにも適用 より複雑なテストにも挑戦 チーム全体で使えるように このあたりを進めていきたいと思います。 まとめ やってみた感想 思ってたより簡単だった CSV 渡すだけで自動化できた コード書かなくていいの、楽すぎる 「AI でテスト自動化とか難しそう」っと思っていましたが、実際やってみると全然そんなことなかったです。 特に「プログラミングはちょっと...」って人こそ、試してみる価値あると思います。 おまけ Claude に頼めば、こんなこともできます。 スクリーンショット撮影 テスト実行時に各画面のスクリーンショットも撮ってください レポート生成 結果をHTMLレポートにして保存してください 全部、会話で頼めます。便利。
aptpod Advent Calendar 2025 – 12 月 4 日の記事です。 この記事は、コーポレートマーケティング室デザイナーの tetsu が担当しています。 当チームでは、製品・案件向けアプリケーションの UI デザインをはじめ、マーケティングクリエイティブ、WEB サイトや当テックブログのデザイン・運用などを担当しています。 テック業界の師走といえばアドベントカレンダー。アプトポッドのテックブログでも毎年多くの記事が公開されます *1 が、その運用の中で地味に負荷が大きかったのが OGP(サムネイル画像)の作成 でした。 これまでは、デザイナーが毎回書き出し・設置を行っており、急ぎの差し替えや連携の手間が小さなストレスとして積み重なっていました。 そこで今年は Figma の新機能「Figma Make」 を活用し、OGP 作成から進捗管理までを自動化・アプリ化しました。この記事では、その構築プロセスを紹介します。 *2 www.figma.com これまでの OGP 制作フロー 作成ステップ 1. Figma Make の設定 2. デザインと基本機能の実装 ベースデザインの作成 画像生成機能の実装 テキスト配置の調整 3. 管理アプリとしての UI 拡張 4. Supabase 連携によるステータス管理 5. 書き出し画質の最適化 まとめ これまでの OGP 制作フロー 通常時のテックブログでは、記事内容に合わせて毎回サムネイルを手作業で制作しています。 コンテキストに合わせたイメージを作るため、記事を読む時間と画作りで1記事に1〜2時間までの工数を目標に制作しています。 普段のOGP しかしアドベントカレンダー期間中は、 毎日更新(時間制約) 全体の統一感(デザイン要件) という理由から、昨年までテンプレートを使用していました。 テンプレートの活用をした場合でも、執筆者とのやりとりや設置確認などで15分程度はかかります。 15分×20記事で300分程度は工数をかけていたことになります。 また、工数以上に急ぎの差し込み対応である場合が多く、常に他のタスクの手をとめる必要がありました。 2022〜2024年のアドベントカレンダーOGP 上記の課題を解決するために、今年はさらに一歩進め、テンプレートから“アプリ化”へと発展させた形です。 作成ステップ 1. Figma Make の設定 Figma Make の設定から 「実験モデル > Gemini 3 Pro」 を有効化します。 これにより、プロトタイプ上で高度な AI モデルを利用できるようになります。 Figma Make 設定画面 2. デザインと基本機能の実装 ベースデザインの作成 まず、アドベントカレンダー向けにクリスマスらしいベースデザインをラフで作ります。 この段階で 編集可能エリア(タイトル・著者名) をあらかじめ定義しておきます。 ベースデザイン 画像生成機能の実装 プロンプトで以下を指定します: サイズは 1200 × 630px(OGP 標準) プレビュー内容を JPG としてダウンロード可能 にする 日替わり感を出すため、アイコンや小物を可変にする 画像生成UI テキスト配置の調整 テキストの級数やフォントは UI から調整できますが、 位置・マージン調整は精度を高めるため数値指定 が必要でした。 Figma Make と数度やりとりし、うまくいかない箇所はコードを確認しながら値を指定しました。 3. 管理アプリとしての UI 拡張 ここまでは「デザインチームが書き出し、Figma に一覧化」という想定でした。しかしアドベントカレンダー期間中は、執筆者の編集待ちや掲載タイミングの調整が発生し、お互いに小さな負荷が生まれがちです。 そこで、執筆者自身が “自分の担当日を選び、その場で OGP を生成できる” 管理 UI を追加しました。 担当日を選択して OGP を作成 入力完了ステータスを一覧で可視化 一覧性のある管理UI 画像を生成する側のUIにも、管理UIとの導線や、現在編集している日付をわかりやすくするために右側に日付バーなどを追加しました。 最終的な画像生成UI これにより、執筆者は進捗を自分で管理でき、デザイナー側も状況を一目で把握できるようになりました。 4. Supabase 連携によるステータス管理 プロトタイプ段階ではステータスがブラウザローカルに保存されるだけで、実運用には不十分でした。 そこで、オープンソースの BaaS (Backend as a Service)である Supabase を採用し、進捗ステータスをクラウドで管理できるようにしました。 supabase.com Figma Make は API 連携まわりの操作性が良く、デザイン畑の人間でもほぼノーコードで扱える点が特に便利でした。 5. 書き出し画質の最適化 最終的にデザインの細部を調整し、出力処理を整えます。 普段はデザイナーが毎回 JPG 圧縮の度合いを調整していますが、今回は 設置作業を執筆者に委ねるため、品質設定をシステム側で固定 しています。 書き出し時に自動で Quality 0.8 の JPG に変換 画質とファイルサイズのバランスを安定化 これにより、誰が生成しても品質が揃い、運用負荷を最小化できます。 まとめ 今回の取り組みによって、師走の忙しい時期に細切れで発生していたデザイナーのタスクが大幅に軽減されました。執筆者も、自分のタイミングで OGP を生成・設置でき、全体の流れがスムーズになりました。 「運用フロー自体をデザインする」 ことで、チーム全体のコンテキストスイッチを減らせたことが最大の成果だと感じています。 Figma Make のようなツールを活用すれば、デザイナーでもアプリライクな課題解決を手軽に実装できます。ぜひ試してみてください。 *1 : アプトポッドのアドベントカレンダーは、12 月の平日毎日更新 *2 : この記事の内容は 2025 年 11 月現在の情報です
intdashグループの大久保です。 aptpod Advent Calendar 2025 の12月3日の記事を担当します。 Linuxでアプリケーションを開発するとき、その依存ライブラリ含めどう配布するかは悩ましい問題です。debのようなパッケージであれば、対応するディストリビューションごとにビルドしなければなりません。muslであれば単体で動作する実行バイナリを作れますが、依存するライブラリが多ければビルドが難しかったり、対応不可であったりします。 ここでは、Linuxのアプリケーション配布をするときに有用と思われるAppImageを紹介します。 AppImageとは テスト用アプリケーションの作成 debパッケージからAppImageへの変換 AppImageの動作 カスタムのAppRun まとめ AppImageとは AppImageは、1つの実行ファイルに依存するファイルを内包するようにし、ディストリビューションに関わらず単体で動作するようにしたパッケージフォーマットです。 https://appimage.org/ 今回は、debパッケージからAppImageを作成できる pkg2appimage を使用します。 テスト用アプリケーションの作成 開発言語は特に制約はありませんが、今回はAppImageパッケージを生成する途中でdebパッケージを経由する方法をとるので、debパッケージを簡単に作れるRustを今回は例に使います。他の方法でdebパッケージを作成してもらっても問題ありません。 ここではGTKを使用して画像を表示するシンプルなGUIアプリケーションを作成します。 Cargo.tomlは以下のように準備します。 [ package ] name = "appimage-test" authors = [ "Test <test@example.com>" ] version = "0.1.0" edition = "2024" license = "MIT" [ dependencies ] gtk4 = "0.10" # cargo-deb の設定 [ package.metadata.deb ] maintainer = "Test <test@example.com>" depends = "$auto" section = "misc" priority = "optional" assets = [ # コンパイルされたバイナリを /usr/bin に配置 [ "target/release/appimage-test" , "usr/bin/" , "755" ] , # desktopファイルを /usr/share/applications に配置 [ "appimage-test.desktop" , "usr/share/applications/" , "644" ] , # アイコンファイル (logo.png) を /usr/share/pixmaps/appimage-test.png として配置 [ "logo.png" , "usr/share/pixmaps/appimage-test.png" , "644" ] , ] main.rsは以下になります。注意点としては、画像ファイルにアクセスするとき /usr/share/pixmaps/appimage-test.png と絶対パスを指定するのではなく、実行ファイルのある場所 usr/bin からの相対パスで指定していることです。AppImageは実行時に一時的なパスにファイルを配置するため、絶対パスが機能しなくなります。 use gtk4 :: {Application, ApplicationWindow, Image, gdk_pixbuf :: Pixbuf, prelude :: * }; use std :: env; fn main () { let application = Application :: new ( Some ( "com.example.appimage-test" ), Default :: default ()); application. connect_activate (build_ui); application. run (); } fn build_ui (app: & Application) { let exe_path = env :: current_exe (). expect ( "Failed to get executable path" ); // 実行ファイルからの相対パスから usr/share/pixmaps/appimage-test.png を取得 let exe_dir = exe_path . parent () . expect ( "Failed to get executable directory" ); let image_path = exe_dir. join ( "../share/pixmaps/appimage-test.png" ); let pixbuf = Pixbuf :: from_file ( & image_path). unwrap_or_else ( | e | { panic! ( "Failed to load image file from path {:?}. Error: {}" , image_path, e ); }); let image = Image :: from_pixbuf ( Some ( & pixbuf)); let window = ApplicationWindow :: new (app); window. set_title ( Some ( "AppImage Test (GTK4)" )); window. set_default_size (pixbuf. width (), pixbuf. height ()); window. set_child ( Some ( & image)); window. present (); } Linuxのdesktopファイルを適当に用意し、appimage-test.desktopと名前をつけて保存しておきます。 [Desktop Entry] Version=1.0 Type=Application Name=AppImage Test GenericName=Test Application Comment=A simple GTK4 test application Exec=appimage-test Icon=appimage-test Terminal=false Categories=Utility;Development; StartupNotify=true 他に適当な画像を用意して logo.png として保存しておきます。 以上のものを用意すれば、 cargo-deb でdebパッケージを生成しましょう。target/debian以下にdebファイルが生成されているはずです。 $ cargo deb debパッケージからAppImageへの変換 debパッケージが用意できたら、以下のようなレシピファイルをyamlで作成します。レシピ内にUbuntuのバージョンが含まれますが、UbuntuのバージョンはdebパッケージのビルドとAppImageへの変換の実行するホスト環境、そしてレシピ内で統一しておいたほうが無難です。 app : appimage-test ingredients : dist : noble sources : - deb http://archive.ubuntu.com/ubuntu/ noble main universe debs : - /path/to/appimage-test_0.1.0-1_amd64.deb レシピファイルを作成したら変換用スクリプトをダウンロードしてきましょう。 Releases · AppImageCommunity/pkg2appimage · GitHub ここからダウンロードした実行バイナリで変換に失敗した場合は、GitHubにある 生のスクリプト を実行してやるとうまく行く場合があるようです。 $ wget https://raw.githubusercontent.com/AppImage/pkg2appimage/master/pkg2appimage $ chmod +x pkg2appimage $ ./pkg2appimage testrecipe.yml 変換に成功すれば、outディレクトリ内にAppImageファイルが作成されているはずです。 $ ls out/ AppImage_Test-0.1.0.glibc2.39-x86_64.AppImage これを実行すれば用意した画像を表示するシンプルなウィンドウが表示されます。 AppImageの動作 AppImageの特徴は、実行時に FUSE を用いて、動作に必要なファイル群を一時的にマウントして展開することです。その動作を見るためには、作成された実行ファイルに --appimage-mount オプションを付けて実行します。 $ ./AppImage_Test-0.1.0.glibc2.39-x86_64.AppImage --appimage-mount これを実行すると /tmp/.mount_XXXXX のようなディレクトリ内に、実行中そのAppImageが使うファイルがマウントされていることが確認できます。今回の例として作成したアプリケーションで、画像が /usr/share/pixmaps/appimage-test.png にあるのにソースコード上は相対パスを使ってアクセスしているのは、実行時欲しい画像が実際には /tmp/.mount_XXXXX に展開されているので、それにアクセスできるようにするためです。ここはアプリケーションの実装時に気を付けないといけない点です。また、デフォルトでは一部の基本的なライブラリ(libcなど)はパッケージに含まれず、実行OS側に存在しなければなりません。libfuseもインストールされている必要があります。 カスタムのAppRun AppImageパッケージを起動するとき、まずAppRunというファイルが実行されます。対象となるアプリケーションによっては、カスタムのAppRunを用意してやる必要があります。その場合は、レシピの script にAppRunを作成する処理を記述します。元のdebパッケージがdesktopやアイコンファイルを含んでいない場合、ここで作成処理を追加することもできます。 app : appimage-test ingredients : dist : noble sources : - deb http://archive.ubuntu.com/ubuntu/ noble main universe debs : - /path/to/appimage-test_0.1.0-1_amd64.deb script : - cat > AppRun <<\EOF - # !/bin/sh - HERE="$(dirname "$(readlink -f " ${ 0 }")")" - export LD_LIBRARY_PATH="${HERE}/usr/lib:${HERE}/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}" - exec "${HERE}/usr/bin/appimage-test" "$@" - EOF - chmod a+x AppRun スクリプト内で LD_LIBRARY_PATH などの環境変数を設定し、最後に配置した実行ファイルを呼び出します。アプリケーションに合わせて設定する環境変数を変えましょう。また、デフォルトのAppRunに任せると、カレントディレクトリを変更されてしまうので、相対パスを引数に受け付けるCLIツールをAppImage化する場合はカスタムのAppRunを用意する方が無難です。 まとめ AppImageはLinuxで開発していると興味深い技術なのですが、パッケージ化するとなると日本語の情報がほとんど無いので今回取り上げてみました。いろいろ苦労させられることの多いLinuxでのアプリケーション配布における1つの選択肢として覚えておくのは良いかと思います。
計測データを動画プレイヤーで再生したいみなさん、 こんにちは。ソリューションアーキテクトの伊勢です。 こちらは aptpod Advent Calendar 2025 12月2日の記事です。 今回はintdashの計測データをMP4ファイルとして出力する方法をご紹介します。 はじめに 複数データの出力 MP4ファイルとは やってみた 出力パターン①:音声 出力パターン②:音声 + 映像 出力パターン③:音声 + 映像 + 字幕 起動オプション データ取得オプション 出力オプション 多重化オプション サンプルプログラム データ取得 データ変換 データ出力 MP4多重化 おわりに リンク はじめに intdashのMedia Explorerでは、計測の映像をMP4ファイルでダウンロードできます。 1 Media Explorer また、Meas Converterでは、車両データ解析で利用されるMDFファイルでダウンロードも可能です。 tech.aptpod.co.jp 複数データの出力 利用用途によっては複数データを統合してファイル出力したいケースもあります。 今回は、より複雑な構成のMP4ファイルを出力してみます。 MP4ファイルとは 動画や音声をひとつのファイルにまとめて扱える形式です。 再生時には内部の映像や音声を取り出し、タイムスタンプに基づいて同期再生します。 おおまかな構成は以下のようになっています。 今回はこれらのトラックを統合(多重化)します。 trak (video) : ビデオトラック trak (audio) : オーディオトラック trak (subtitle) : 字幕トラック MP4 File ├─ ftyp # ファイルタイプ情報 (ブランド識別) ├─ moov # メタ情報(再生に必要な情報の塊) │ ├─ mvhd # ムービーヘッダ(全体の時間情報など) │ ├─ trak (video) # ビデオトラック │ │ ├─ tkhd # トラックヘッダ │ │ ├─ mdia # メディア情報 │ │ │ ├─ mdhd # メディアヘッダ(時間単位など) │ │ │ ├─ hdlr # ハンドラ(映像/音声の区別) │ │ │ ├─ minf # メディア情報 │ │ │ │ ├─ stbl # サンプルテーブル │ │ │ │ │ ├─ stsd # サンプル記述子(コーデック情報) │ │ │ │ │ │ ├─ avc1 (AVC/H.264 codec box) │ │ │ │ │ │ │ ├─ avcC (AVCDecoderConfigurationRecord) │ │ │ │ │ │ │ │ ├─ SPS (Sequence Parameter Set) │ │ │ │ │ │ │ │ └─ PPS (Picture Parameter Set) │ │ │ │ │ ├─ stts # 時間情報(各サンプルのduration) │ │ │ │ │ ├─ stsc # チャンク構造 │ │ │ │ │ ├─ stsz # サンプルサイズ │ │ │ │ │ └─ stco # チャンクオフセット │ ├─ trak (audio) # オーディオトラック │ │ ├─ tkhd │ │ ├─ mdia │ │ │ ├─ mdhd │ │ │ ├─ hdlr │ │ │ ├─ minf │ │ │ │ ├─ stbl │ │ │ │ │ ├─ stsd # サンプル記述子(例: mp4a) │ │ │ │ │ ├─ stts │ │ │ │ │ ├─ stsc │ │ │ │ │ ├─ stsz │ │ │ │ │ └─ stco │ └─ trak (subtitle / others) # 他トラック (例: 字幕) │ ├─ mdat # メディアデータ本体(映像フレームや音声サンプル) │ ├─ [Video Sample 1] → H.264フレーム (AVCC形式: length-prefixed NALU) │ ├─ [Video Sample 2] → H.264フレーム │ ├─ ... │ ├─ [Audio Sample 1] → AACフレーム │ ├─ [Audio Sample 2] │ └─ ... └─ free / udta / meta # 追加のメタデータ(オプション) やってみた おおまかな構成です。 iPhoneアプリ intdash Motion で取得した計測データをもとにします。 データ種類ごとにファイルを出力し、最後にMP4ファイルに多重化します。 2 音声:PCMデータ → WAVファイル 映像:H.264データ → バイナリファイル 字幕:GNSSデータ(高度・速度・緯度経度) → SRTファイル 多重化後:MP4ファイル データフロー 出力パターン①:音声 シンプルな例として、音声ファイルをWAVファイルに出力します。 3 対象のエッジと開始時刻〜終了時刻を指定して実行します。 実行:音声 youtu.be 出力パターン②:音声 + 映像 続いて、複数トラックを多重化します。音声 + 映像を出力するパターンです。 実行:音声 + 映像 多重化で警告が出ています。 これは、開始時刻〜終了時刻を直接指定したためで、動画の基準点であるIDRフレームが最初に現れるまで映像フレームが生成されず、黒一色で表示されます。 4 [ h264 @ 0x157704b90 ] no frame! [ h264 @ 0x157704b90 ] non-existing PPS 0 referenced youtu.be 出力パターン③:音声 + 映像 + 字幕 最後に音声 + 映像 + 字幕を出力・多重化する例です。 計測を指定して、計測の開始〜終了時刻のデータを対象とします。 字幕の緯度経度を逆ジオコーディングで住所に変換するため、Google Geocoding APIのAPIキーを指定しています。 実行:音声 + 映像 + 字幕 youtu.be 起動オプション データ取得オプション --api_url required :サーバーURL --api_token required :APIトークン --project_uuid :プロジェクトUUID(省略時は Global Project) いずれか required 計測指定 --meas_uuid :計測UUID エッジ+時間範囲指定 --edge_uuid :エッジUUID --start :開始時刻、RFC3339形式 --end :終了時刻、RFC3339形式 出力オプション --outdir :出力先ディレクトリ(省略時は ./out ) --tracks :出力するトラック audio , video , subtitle を指定(複数可、省略時はすべて) --fps :映像の入力フレームレート(映像出力時、省略時は15) --gmap-api-key :Google Maps API Key(字幕出力時、逆ジオコーディングに使用、省略時は緯度経度を出力) 多重化オプション --mux :WAV / H.264 / SRT を MP4 に多重化(省略時は多重化なし) サンプルプログラム 多重化には SDK入門③ でインストールしたffmpegを利用しています。 クラスアーキテクチャ データ取得 intdash REST APIからのデータ取得はメモリ消費を抑えるため、 チャンク転送エンコーディング でリクエストしています。 api = measurement_service_data_points_api.MeasurementServiceDataPointsApi( self.client ) params: dict [ str , object ] = { "project_uuid" : self.project_uuid, "name" : self.meas_uuid if self.meas_uuid else self.edge_uuid, "time_format" : "ns" , "_preload_content" : False , # 全データロードの抑止 } if self.start: params[ "start" ] = self.start if self.end: params[ "end" ] = self.end if self.data_id_filter: params[ "data_id_filter" ] = self.data_id_filter stream = api.list_project_data_points(**params) データ変換 Motionで収集した音声を単純に繋げるだけだと、zzzzやppppと聞こえるジッタノイズが入っているため、除去します。 PCMデータサンプル間の時間揺らぎを等間隔サンプリングします。 f32 = decode_pcm_s16le(data_bytes) # bytes -> float32 f32_out = self.resampler.push_block(t_rel, f32) if f32_out.size: i16 = encode_pcm_s16le(f32_out) # float32 -> bytes データ出力 映像と音声はメモリに溜め込まず、1件ずつ出力しています。 if data_name == "1/pcm" : ... self._wav.write(i16) ... elif data_name == "1/h264" : ... self._h264.write(data_bytes) また、字幕はGNSSの複数項目を統合して生成します。 高度・速度・緯度経度・住所の字幕セグメントに集約します。 elif data_name == "1/gnss_speed" ... aggregator.update_speed(v) ... elif data_name == "1/gnss_altitude" : ... aggregator.update_altitude(alt) ... elif data_name == "1/gnss_coordinates" : ... changed, lat_q, lon_q = aggregator.update_latlon(lat, lon) ... aggregator.update_address(addr) 集約した字幕は高度が更新されたタイミング、約1秒に1回出力します。 seg = aggregator.on_tick(t_rel) # 高度は約1Hz if seg: self._write_segment(seg) 今回は1回だけREST APIへのリクエストして、データ名で処理を分岐しています。 5 for t_ns, _, data_name, data_bytes in self.reader.get_datapoints(): ... if data_name == "1/pcm" : ... elif data_name == "1/h264" : ... elif data_name == "1/gnss_speed" : ... elif data_name == "1/gnss_altitude" : ... elif data_name == "1/gnss_coordinates" : MP4多重化 音声・映像・字幕それぞれで最初のデータポイントの相対時刻が異なるため、計測開始からのオフセット(ffmpegの -itsoffset オプション)を与えて調整しています。 cmd += [ ... "-itsoffset" , f "{opts.v_offset:.6f}" , "-i" , str (inputs.video), ... cmd += [ "-itsoffset" , f "{opts.a_offset:.6f}" , "-i" , str (inputs.audio)] ... cmd += [ "-itsoffset" , f "{opts.s_offset:.6f}" , "-i" , str (inputs.subtitle)] おわりに 今回は、複数データを一般的な動画ファイルに多重化する例を紹介しました。 マルチモーダルデータも、SDKを使えば、自由に整形が可能です。 intdashはデータの時系列が管理されているため、出力時にもデータが同期されます。 なお、今回は海外eSIMを使ったiPhoneで計測を行いました。 海外での計測は以下の記事でも検証しています。 tech.aptpod.co.jp リンク 本シリーズの過去記事はこちらからご覧ください。 SDK入門①〜社用車で走ったとこ全部見せます〜 :REST APIでデータ取得 SDK入門②〜データ移行ツールの作り方〜 :REST APIでデータ送信 SDK入門③〜RTSPで映像配信するぞ〜 :リアルタイムAPIでデータ取得 SDK入門④〜YOLOで物体検知しちゃう〜 :リアルタイムAPIでデータ送信 SDK入門⑤〜iPadでData Visualizerを見る会〜 :リアルタイムAPIでキャプチャデータ送信 SDK入門⑥〜最速最高度で計測する日〜 : AWS LambdaでREST APIデータ送信 SDK入門⑦〜計測リプレイツールの作り方〜 : REST APIでデータ取得、リアルタイムAPIでデータ送信 SDK入門⑧〜動画アップロードツールの作り方〜 :REST APIで映像データ送信 Media ExplorerでのMP4ダウンロードについては、 SDK入門⑧ で解説しています。 ↩ サンプルプログラムを GitHub にて公開しています。Motionの計測データのみで動作確認しています。未回収データポイントがあると映像と音声がずれるなどの問題が起こりえます。 ↩ サンプリングレートを48kHzにしています。元計測の音声データにあわせる必要があります。 ↩ H.264のIDRフレームについては、 SDK入門⑧ で解説しています。 ↩ 字幕集約がなければ、音声、映像ごとにリクエストする方がシンプルかもしれません。 ↩
aptpod Advent Calendar 2025 12月1日の記事です。 みなさまお久しぶりです。アプトポッドで営業企画をしている神前(こうさき)と申します。 前回 から1年ぶり、5年連続でAdvent Calendarのトップバッターです。甲子園でいったらそこそこ強豪ですね。 今年も懲りずにSalesforceネタで書いていきたいと思います。メインの業務がそれだから仕方ないね。 今年やったこと エンドユーザー向けマイページ作成の経緯 設計 ちょっとしたポイント 補足 見せ方について 作ってみてよかったこと まとめ 今年やったこと この1年間でやったことのうち、大きなトピックとしては、「エンドユーザー向けマイページ」の公開でしょうか。 サンプルページ これまでも内部的には弊社の一部パートナー企業様向けのポータルサイトは公開して使ってもらっていたのですが、エンドユーザー様向けのものは今回が初となります。 Salesforceには「 Experience Cloud 」という機能があり、社内で利用しているSalesforce環境と連携した外部ユーザー向けWebサイトをつくる事が可能です。 使い方は様々で、 セールスパートナー企業向けのサイトをつくり、商談情報を直接パートナーに入力してもらう エンドユーザー向けのサイトをつくる、FAQやお問い合わせ機能をもたせ、エンドユーザーに直接ケースを起票してもらう 会員専用ページをつくり、いわゆるコミュニティを形成する 他 といったことが利用法として想定できます。 今回のケースは「エンドユーザーが当社製品の契約状況や、具体的な利用状況を(当社の営業等を介さずに)直接確認することができるサイト」となります。 そんな機能(ツール)があるのを知らなかった!知ってたけどどう使っていいかわからない!みたいな方がいたら本記事は少しは役に立てるかもしれません。 エンドユーザー向けマイページ作成の経緯 当社の主力製品である「 intdash 」をご利用いただくにあたり、いくつかのプランからお客様の用途に合ったものを提供しています。これまでも提供プランそのものについては何度か変更があったのですが、現時点での最新バージョンからは「瞬間的なデータ流量の最大値」から「1ヶ月間でのトータルのデータ流量」を元に提供をする形になっています。 必然的に、お客様からすると「月にどれだけ使えるプランにしたのか」と「今月はあとどれだけ使えるのか」を確認できないといけません。 そうした情報をどこでみれるようにするのかについてはいくつか候補はあったのですが、最終的にSalesforce上(=Experience Cloudで作成したサイト)でみれるようにすることとなりました。 ちょうど弊社が利用しているMVNO事業者の各SIMの利用状況を確認するサイトがSalesforceで作られていることがわかっていたので、そちらをベンチマークとして作成をすすめていきました。 設計 当社はBtoB企業ですので、エンドユーザーといっても一般消費者ではなく企業が対象となります。 どういった項目を見れるようにするのか、どういう風に見せるのか、といった内容については営業側、開発側と何度か打ち合わせをしながら詰めていきました。 特に、そもそものデータ(A社が◯月◯日に◯Gデータを消費した)の大元がSalesforce内にあるわけではないので、当社の場合は大元のデータがあるAWSからAPIでSalesforceへデータを流し込む部分については開発側におんぶにだっこの状態でした。 AWS側でどういう風にデータを持っているのか、どんなデータを持っているのか(逆に、どんなデータは持っていないのか)によってSalesforce側で追加で何をすることが必要なのかが変わってくるのでこのあたりは特に大変だったように記憶しています。 ただ、一回決まってしまえばやることは明確なので、AWS側からデータを流し込む先(=各項目)を用意して、AWS側では持っていないデータ(そのデータがどのエンドユーザーなのか、どういう契約なのか、等)についてはSalesforceで持っているデータと組み合わせて補完するためのフローを構築する形となります。そこの領域については自分の領域なのであーでもないこーでもないと頭を使いながら設計していきました。 さて、そういった「データをどこからもってくるのか」、「何を見せるのか」といった部分については割と大変というか、営業側(データを見るお客様に一番近い立場)と開発側(データを持っているシステムに一番近い立場)の両方と関わりながらすすめていくので結構おおがかりになるのですが、サイト自体はそれほど複雑だったり、特別なことをしているわけではありません。 サイト内に各種タブがあり、各タブ内で表示する情報や表現方法に違いはあるものの、基本は 「ダッシュボード」 と 「レポート」 を埋め込んでいるだけです。 つまり、日常的にこの2つを利用しているのであれば多少の工夫は必要なものの、おおよそ同様のものはつくれるものと思います。 ちょっとしたポイント どんなデータをどう見せるのか、どこからデータを持ってくるのかといった点は各社さんが持っているデータやどういう目的でどういう属性の人に見せるのかでケースバイケースなのであまり参考になるお話は書けないのですが、どう見せるのかの部分についてはちょっとしたポイントが参考になると思うので書きたいと思います。 使っているのはダッシュボードとレポートの2種類とすでに記載していますが、普段から使っている方はご存知の通り、これらをそのまま使うだけでは「見る人によって見せるものを変える(=動的に見せる)」というのはできません。ですが、実はユーザー側にちょっとしたことをすると実現できるのです。 言葉だけで説明をすると複雑になるので、図をいれていきます。 以下のようなケースを想定します。 ■レポートで、とあるレコードa(にある情報)をXさんにのみ見せるようにしたい 各レコードとオブジェクト、項目の関係を表したのが下記の図です。わかりやすくするためYさんも図にいれています(XさんとYさんは別の企業)。XさんとYさんは別々の企業なのでXさんに見せたいものはYさんには見えてはいけないですし、その逆も然りです。 関係図 さて、レポートを作成するときに、普通にオブジェクトAを使うだけではXさんにもYさんにもレコードaの情報は見えてしまいます。 そこで、オブジェクトAとユーザーにそれぞれ項目αと項目Zを作成します(ここでのユーザーは、設定画面から見る方のユーザーです)。 ※ユーザーXやYにアカウントの払い出しをしているという想定です。 当社の事例。「累積データ流量」がオブジェクトA、「マイページ管理No.」が項目αに該当。 こちらはユーザー側の画面。下部にある「マイページ管理No.」が項目Zに該当。 これらの項目のデータ型はなんでもよいのですが、テキストが無難です(一意にできるのであれば数値とかでも可)。 その後に、オブジェクトAにのみ項目βを作成し、データ型を「数式」、数式の戻り値のデータ型を「チェックボックス」にして以下のような数式を設定します。 [項目α] = $User.[項目Z] 当社の項目βの設定画面。戻り値がチェックボックス。数式のうち、左の「MypageNo」が項目α、「$User」の後ろの「MypageNo」が項目Z。 あとはそれぞれ項目αと項目Zに一意になるような値を入力すればOKです(もちろんαとユーザーXの項目Zは同じ値にするようにする)。 最後にレポート側の「検索条件」に「項目β=true」としてあげれば全て完了です。 レポートの検索条件画面。赤い枠の箇所が「項目β=true」に該当する箇所。 仮に、レコードaの項目αに「AAA」という値をいれ、ユーザーXの項目Zに同様に「AAA」、ユーザーYの項目Zには「BBB」という値をいれます。 ※項目α、項目Zには管理者側からしか値をいれることができないようにしてあります。 ユーザーXがサイトにログインをすると項目βに入力した数式が成立し、チェックボックスがはいるためレポートを閲覧した時にレコードaの情報を閲覧できます。一方で、ユーザーYがサイトにログインしても項目βの数式は成立しないのでチェックボックスは入らずレポートでレコードaの情報を閲覧することはできません(そもそもでてこない)。 項目Zに「AAA」とはいっているマイページ太郎さんには同様に項目αに「AAA」とはいっている項目が表示される。 項目Zに「BBB」とはいっているマイページ次郎さんにはマイページ太郎さんに見えていた項目は表示されない。 これで、同じサイトに同じレポート、同じダッシュボードを貼り付けたとしてもユーザーによって見せたいデータを変えるという動的な見せ方が可能になります。 補足 上記のやり方で動的にレポートをみせることはできるのですが、当社の場合は運用面を考慮して少しゆるくしています。 例えば、今回ユーザーXとユーザーYは別々の会社という設定にしていますが、同じ会社に所属していて、XとY両方に同じ情報をみせる必要がある場合を考えてみましょう。その場合、ユーザー側の項目Zが完全に一意であってはXかYのどちらかにしか情報をみせられません。こうした状況を想定しなくてよい場合(レコードaは常に一人のユーザーにしか見せる必要がない)であればもっと機械的にシンプルにすることも可能でしょう。 また、当社の場合、オブジェクトA内のレコードは毎日毎日増えていきます(毎日のデータ使用量のデータなので当然ですね)。レコードが増えるたびに項目αに手作業で値をいれていくことはできないのでフローを活用しています。詳細は省きますが、さらに大元となるデータをもっておいて、オブジェクトAにレコードが作成された際に、キーとなる値を使って大元から項目αにいれるべき値をもってきて上書きする、という感じです(テキストだとわかりにくいですが・・・)。これもオブジェクトA内のレコードそのものがそんなに増えないような運用であればそこまでしなくてもよいので、どこまでやるか、というのは運用次第という感じですね。 見せ方について ここまでできたらあとは事前に決めていた通りにダッシュボードやレポートを調整していけば完成です。 どの情報をどのように見せるのか、グラフにするのか、グラフでも棒グラフなのか円グラフなのか、あるいは表形式にするのかといった点は見せたいデータによって変わるので最適と思われる表現方法にしてもらえればよいと思います。 当社の場合は日々のデータ使用量の推移を見せたいので、棒グラフとしています。 サンプルページ 上記の図では、青を使用量、赤が残りの使用量を表しています。 期間やそれ以外の項目である程度絞り込んだり、グラフの表現形式をある程度ユーザー側で調整できるのはよいですね。 それとは別に、トップページでは表形式にすることで複数のデータを網羅的に見れるようにしたり、トップページなのでお知らせの枠や当ページの操作マニュアルへのリンクを掲載しています。 サンプルページ 使っているデータ自体は同じでも表現方法でいかようにも見せれるので色々試してみてもよいかもしれませんね。 作ってみてよかったこと 今年の4月に本サイトをオープンし、徐々にお客様にも使っていただいています。まだまだ改善の余地はありますし、実際に社内からも改善要望もあったのでそこは対応をしつつ、もっと便利に、もっと使いやすくしていければと考えています。 個人的にやってよかったなと思った点を最後に記載したいと思います。 当社では年に数回イベントに出展をしています。 【参考】 メンテナンス・レジリエンス TOKYO 2025 見学レポート 片手サイズ × 高速起動 ── EDGEPLANT R1 & CAN FD USB Interface[人とくるま展2025展示レポート] ブース内でデモを展示することもあるわけですが、その際に、どれだけ実際に通信量を消費するのかを本サイトの社内向けのものを使ってその場で営業メンバーが確認していました。デモとはいえ、こういう風にintdashを使って、これぐらいの時間使うとこれぐらいの使用量になるのか、というのを開発側の手を煩わせることなくその場ですぐに確認できるというのは、地味ではあるものの自分がなにがしかに貢献できたのではないかと感じました。 普段の仕事柄、あまり派手な何かをするというよりも、こうした地味な改善の積み重ねが業務の大半なので、実際に使ってもらってるシーンを見れてよい経験でした。 まとめ 長くなってきたのでそろそろ締めたいと思います。 昨年とは違いTips寄りの記事を今年は書いてみました。細かい注意点(項目ごとのアクセス権限の設定とか)は書ききれないほどあるのですが、マニアックになるので今回は省きました。 そういった点よりも、Salesforceで普段使っているレポートやダッシュボードとExperience Cloudを組み合わせればこんなこともできるんだ、ということをおわかりいただければ幸いです。 現在は何をしているかと言うと、Salesforceの提供している自立型AIエージェント「 Agentforce 」の活用を試みています。 とはいえ、いきなり使えるというとそういうわけでもないので、まずはSalesforceに社内のいろんな情報を集約できるように地ならしをやっています。 来年にはAgentforceを活用してこんなことができるようになったよ!みたいな記事を書けるようにやっていきたいと思います。 本記事が少しでも参考になっていると幸いです。 それではまた1年後にお会いしましょう!
気軽に計測データを分析したいみなさん、 こんにちは、ソリューションアーキテクトの伊勢です。 せっかくデータ収集しても、こんな悩みはないですか。 収集したデータをどう利活用したらいいかわからない 分析ツールを導入したけどどう分析したいかわからない 分析結果をどう考察したらいいかわからない IoTあるあるですね。 今回は専門的な分析知識を使わず、 intdashの収集データをノーコードで分析したいと思います。 生成AIはChatGPTの最新版GPT-5を利用します。 1 はじめに データ分析とは GPT-5とは VM2M Data Visualizerとは やってみた CSVダウンロード センサーデータで体感を定量化 行動データから安全性を客観評価 現場運用を解決 おわりに はじめに データ分析とは 数値や記録などのデータを収集・整理・可視化・解釈し、有用な知見(インサイト)を得る一連の活動です。 データ分析の流れ DXを推進するAIポータルメディア「AIsmiley」 データ分析とは?基礎から分かる手法と流れ、仕事でのメリットも解説 このうち、前処理(クレンジング)〜結果の解釈、また報告のためのレポート作成を ChatGPTにまるっとお願いできますし、 なんなら、問題の発見や定義への助言も得られます。 2 GPT-5とは OpenAIが2025年に発表した最新の大規模言語モデルで、マルチモーダル処理(テキスト・画像などを併用可能)や高いコーディング能力を備えています。 また、CSVファイルなどのデータを読み込んで「要約・可視化・パターン検出」といった分析支援を行えます。 今回はこのGPT-5を活用して、intdashの計測データをノーコードで分析してみます。 VM2M Data Visualizerとは 時系列データを可視化するダッシュボードアプリケーションです。 エッジからintdashサーバーに送られているリアルタイムデータをサーバー経由で受信して表示したり、intdashサーバーに保存された過去のデータを表示したりします。 www.aptpod.co.jp 分析対象データは、このダッシュボードからCSVファイルでダウンロードします。 やってみた 3つ課題を設定してデータ分析によって結論を導きます。 まずはデータの準備方法の説明です。 CSVダウンロード intdashのビューアーであるVM2M Data Visualizerで分析対象データを作成します。 任意の計測を選択してから、CSVダウンロードします。 CSVダウンロード項目の指定 注意点です。 適度にサンプリングする データが100万行を超えるとChatGPTの分析処理が重くなってくるため、必要な精度にサンプリングします。 Sampling Interval で 1 / 10 / 100 / 1,000 ms のいずれかを選択します。 必要項目に限定する 余計な項目があると、ChatGPTが勘違いしたり、分析が重くなったります。 必要な項目のチェックボックスだけを選択します。 自然言語形式のタイムスタンプを付与する 分析しやすいように「年月日 時分秒」形式の時刻を最初の列に追加します。 Add human-readable timestamps (yyyy/mm/dd HH:MM:SS). をチェックします。 それでは、最初の分析課題です。 センサーデータで体感を定量化 課題 船酔いしなかったのはなぜか。 こちらの記事でご紹介したカーフェリーのGNSSデータを使います。 tech.aptpod.co.jp 私は元々船酔いしやすいタイプなのですが、この出張時には幸い大丈夫でした。 これは当日の船揺れが穏やかだったからなのか、私が船酔いを克服したからなのか、収集データから分析してみます。 茨城県大洗港〜北海道苫小牧港 Data VisualizerからダウンロードしたCSVファイルはこのようになります。 "#timestring","#timestamp","UBX-HNR-ATT_roll@0/UBX-HNR-ATT[BD-67]","UBX-HNR-ATT_pitch@0/UBX-HNR-ATT[BD-67]","UBX-HNR-PVT_lon@0/UBX-HNR-PVT[BD-67]","UBX-HNR-PVT_lat@0/UBX-HNR-PVT[BD-67]","UBX-HNR-PVT_speed@0/UBX-HNR-PVT[BD-67]","UBX-HNR-PVT_headVeh@0/UBX-HNR-PVT[BD-67]" "'2025/03/20 05:21:58.000000'","1742415718.000000","0","24.45279","140.5754456","36.308563","0.1476","102.80244" "'2025/03/20 05:21:59.000000'","1742415719.000000","0","24.45279","140.5754431","36.3085641","0.3456","102.80244" "'2025/03/20 05:22:00.000000'","1742415720.000000","1.31278","8.01281","140.5754409","36.3085642","0.9359999999999999","121.40534000000001" "'2025/03/20 05:22:01.000000'","1742415721.000000","0","8.11894","140.5754397","36.308563899999996","0.3564","112.06946" ... ChatGPTでCSVファイルを選んでアップロードします。 最初にこういったプロンプトを与えます。 フェリー航行のCSVデータをアップロードします。 タイムスタンプ、緯度経度、方位角、速度、姿勢角が含まれます。 課題:船酔いしなかったのはなぜか のためにデータ分析を行います。 以下を確認してください。 - 項目の一覧 - データ行数 - タイムスタンプ範囲 アップロードファイルの内容確認 必要に応じてデータをクレンジングします。 3 データを整えてください。 - 見やすさのため、項目名のUBX-HNR-PVT_部分と"@"以降を削除してください。 - 空の値が含まれます。直前の値を使用して穴埋め(forward fill)してください。 結果表示についても指示しておきます。 4 また、 - 分析結果のグラフは英語で、本文は日本語で表記してください。 分析準備 早速、効果的な分析方法をおすすめしてくれます。 次に進めるとしたら、まず「ロール角・ピッチ角の変動」を時系列グラフで描いて、船の揺れが小さかったかどうかを確認しますか? そのまま実行してもらいます。 姿勢角のグラフ化 Data Visualizerの roll/pitch のグラフ描画ともあっているようです。 修正して欲しいところは追加で依頼します。 修正後のグラフ 分析結果をどう理解したらいいかも質問できます。 評価指標のアドバイス 気になる部分を他項目を絡めて分析します。 特定時間帯への質問 船揺れに対する知見 最後にレポートとしてまとめてもらいます。 レポート指示 レポートまとめ 結論はこのようになりそうです。 結論 船酔いしなかったのは、当日の船の揺れが小さかったためである。 体質改善や慣れによる克服ではない。 続いての分析課題です。 行動データから安全性を客観評価 課題 弊社営業は安全運転か。 こちらの記事でご紹介した社用車の計測データを使います。 tech.aptpod.co.jp この日、社用車は出張で弊社の営業担当が運転していました。 関西への長距離ドライブで危険運転がなかったか、分析してみます。 社用車の走行計測データ 複数計測に跨って1つのCSVファイルを生成するため、 Data Visualizerを開始時刻と終了時刻をブラウザのアドレスバーで指定します。 エンジン始動で計測が区切れているためです。 https://example.jp/vm2m/?playMode=storedData&startTime=2024-11-13T15:42:01.389%2B09:00&endTime=2024-11-13T19:53:20.124%2B09:00 ダウンロードしたCSVファイルをアップしてプロンプトを与えます。 社用車走行のCSVデータをアップロードします。 タイムスタンプ、緯度経度、方位角、速度、アクセル、ブレーキ、ステアリングが含まれます。 課題:ドライバーは安全運転していたか のためにデータ分析を行います。 以下を確認してください。 - 項目の一覧 - データ行数 - タイムスタンプ範囲 CSVファイルのアップロード データをクレンジングします。 データを整えてください。 - 見やすさのため、項目名の0_RMC_部分と"@"以降を削除してください。 - 空の値が含まれます。直前の値を使用して穴埋め(forward fill)してください。 また、 - 分析結果のグラフは英語で、本文は日本語で表記してください。 データクレンジング 複数のデータ項目をクロス分析してグラフ描画して、考察させてみます。 特にステアリング(ハンドル操作)は高速になるほど操作が少なくなっていることがわかります。 車速 vs 各操作 わかりやすいように閾値を設定して再分析してもらいます。 閾値設定 ハンドル操作は低速時のみのようです。 具体的にどういうときに発生しているのか、地図に可視化してみます。 5 地図ファイルのダウンロードリンク 出力されたHTML ハンドル操作は曲がり角と駐車時に集中 ハンドル操作は停車・低速走行に集中しているという分析結果が、視覚的にも確認できました。 では、まとめてもらいます。 レポートまとめ 結論 データが示す限り、弊社営業は模範的なドライバーでした。 少なくともアクセルとブレーキは疑う余地なしです。 最後の課題は少し難しめです。 現場運用を解決 課題 モーター発熱の要因はなにか。 こちらの記事で紹介した、2025年7月の展示会での計測データを使います。 tech.aptpod.co.jp Unitree Go2-Wは研究開発モデルのため、稼働を続けるとモーターが過熱して、基板保護のために自ら脱力します。 6 分析には複数エッジの計測を利用します。 展示会でのData Visualizerスクリーン マルチモーダル環境センシング(俯瞰カメラ) 検出人物数 7 四足ロボット Unitree Go2-W ロボット脚関節モーターの温度 ロボット脚関節モーターの角度・加速度 8 ロボットの消費電流 カメラ画角が限られて不正確ながら、検出人物数は会場の人出の推移とします。 CSVをアップして、データをクレンジングします。 展示会中の計測データをアップロードします。 タイムスタンプ、俯瞰カメラによる検出人物数、四足ロボットの脚関節モーターの温度・角度・加速度、ロボットの消費電流が含まれます。 課題:モーター発熱の要因はなにか。 のためにデータ分析を行います。 以下を確認してください。 - 項目の一覧 - データ行数 - タイムスタンプ範囲 データを整えてください。 - 見やすさのため、項目名のimu.、motor_state.部分と"@"以降を削除してください。 また、 - 分析結果のグラフは英語で、本文は日本語で表記してください。 CSVファイルアップロード まずは各データの日にち・時間帯ごとのヒートマップを表示してもらいます。 会期3日間、開催時間10〜17時の時間帯別のヒートマップを示してください。 - 人出の多寡:検出人物数で推測してください。 - ロボットの稼働負荷:加速度XYZで代替してください。 - ロボットのモーター温度 各平均値のヒートマップ ぱっと見では相関関係はよくわかりません。 もう少し細かく判定条件を検討します。 脚関節角より、ロボットの状態を分類してください。 - 電源OFF:ロボットデータの行なし。 - 直立:関節角が以下の値近辺、姿勢を保つためにモーター負荷が発生。 0.angle: 0 1.angle: 42 2.angle: -85 3.angle: 0 - 歩行・階段:加速度・関節角の揺れが激しい。 - 伏せ:関節角が以下の値近辺、脱力状態でモーター負荷がかからない。 0.angle: -29 1.angle: 75 2.angle: -145 3.angle: 29 ロボット状態の判定 条件ごとに他項目との関係性を分析してもらいます。 状態ごとのモーター温度と消費電流) 状態ごとのモーター温度と消費電流(テキスト) よく知らない要素は別の要素に置き換えて説明してもらいます。 分析結果の解釈質問 具体的な運用対処も確認してみます。 運用対処の助言 これは実用上の経験とも合致します。 9 まとめです。 まとめ(依頼) まとめ(結論) 他データとの関連性を見出せたかも報告してもらいます。 まとめ(人出との関連) 結論 モーターの発熱は「酷使」の証拠である。 ただし、それが必ずしも来場者への貢献量を意味するわけではない。 おわりに 本記事では、簡単にCSVと生成AIだけでここまで分析できることを紹介しました。 intdashは複数データのタイムスタンプが揃うため、分析の正確さが向上します。 今回は最も基本的な形式として数値データを分析しました。 他の形式の計測データも分析にトライしてみようと思います。 有償サブスクリプションのChatGPT Plusを利用しています。 ↩ 生成AIの回答には 意図しない嘘:ハルシネーション が含まれます。常に分析結果の妥当性を確認しながら使うことが重要です。 ↩ GNSSとCANのように複数ソースからデータを収集している場合、1つのソースから発生タイミングでは他のソースの項目は空であるためです。 ↩ 確認したバージョンだとグラフ中の日本語が文字化けします。 ↩ 過去の記事 で利用したPythonのfoliumライブラリを指定しています。 ↩ 上位モデル は長時間の稼働ができるようになっています。 ↩ 人物検出: SDK入門④〜YOLOで物体検知しちゃう〜 を動かしています。 ↩ 実際はモーターは5つ以上あります。稼働中はどのモーターも動いているため、一部で分析しました。 ↩ 同じ質問でも毎回回答が異なります。複雑な課題ほど、データの与え方やプロンプトの微妙なニュアンスでも分析結果が変わりやすいかもしれません。 ↩
関連ニュース IoT・通信の最前線と「intdash」が拓く新たな共創のかたち イベントの目的 会場の印象:共創を前提にした展示構成 アプトポッド/intdashの展示 intdash の特徴 注目技術と共創の視点 技術トレンド・気づき(BE creation視点) 技術者視点での総括 個人的に興味を持った展示 まとめ 関連ニュース ニュース - トヨタ自動車様「第2回 スタートアップ企業 新事業・新技術展示会」出展のお知らせ(2025年9月26日) - トヨタ自動車様のYoutubeチャンネル「トヨタイムズ」での紹介記事 IoT・通信の最前線と「intdash」が拓く新たな共創のかたち こんにちは、ソリューションアーキテクトの村松です。自動車分野のお客様の業務課題に対して「intdash」の技術を用いた解決方法を検討、システム構築等の提案業務に携わっています。 2025年10月9日、愛知県豊田市のトヨタ自動車 本社で開催された 「第2回 スタートアップ企業 新事業・新技術展示会」 に、技術者視点で参加してきました。 本記事では、展示会の印象や気づき、特に データ収集・通信基盤技術「intdash」 に焦点を当て、製造業のお客様との共創の視点で、IoTプラットフォームとはどうあるべきかを整理します。 www.aptpod.co.jp イベントの目的 本展示会参加の主な目的は以下の2点です。 AI・IoT技術の最新トレンドを把握すること intdash (アプトポッド)の活用拡大可能性を探ること 加えて、トヨタ自動車様が掲げる BE creation(新事業創出スキーム) において、技術者としてどのように共創に関われるかを考察する場ともなりました。 https://global.toyota/newbiz/becre/about/ 会場の印象:共創を前提にした展示構成 会場の最初に目に入ったのは、トヨタ自動車様が外部技術との接点づくりを意識した BE creation ブース です。 4つの展示区画に分かれ、トヨタ自動車様の技術・プラットフォームを開放し、スタートアップやアカデミア、産業界と共創する姿勢が強く印象に残りました。 展示構成は「共創」を前提とし、 “自社技術を囲う”のではなく、“他社技術とつなげる”ための空間設計 がされていました。 来場者同士の会話を促す配置や、リアルタイム連携デモが複数同時に展開されるなど、単なるプレゼンテーションではなく 「共に作る場」 としての意図が明確に感じられました。 アプトポッド/intdashの展示 アプトポッドのブースでは、基盤技術 intdash と TOYOTA GAZOO Racing 様における「intdash」によるリアルタイム遠隔計測システムの公式採用について紹介。 世界中を転戦するレース車両に弊社ハードウェア「EDGEPLANT T1」が搭載され、過酷な使用環境の中、高精度/大容量な計測データがクラウドに集約されレース車両の日々の性能改善や車両開発に活用されています。 ブース風景 先日、トヨタ自動車様のYouTubeチャンネル「トヨタイムズ」において、ニュルブルクリンク24時間レースでの利用シーンが公開されています。 こちらも合わせてぜひご覧ください。 トヨタイムズ公式チャンネル(該当動画はこちら) ※「intdash」利用シーンは 3:40頃 / 17:13頃 / 19:58頃 に登場します。 www.aptpod.co.jp intdash の特徴 製品ページへ 高スループット・低遅延のストリーミング通信基盤 複数のデバイス・拠点間でリアルタイムにデータをやり取り可能 展示では、センサーや車載機器から取得したデータをクラウドで統合・可視化・解析するデモが連続して行われ、多くの来場者が訪れていました。 技術者視点では、intdash は単なるスタンドアロン技術ではなく、 共創を支える基盤 として価値を持っています。 BE creation におけるプラットフォーム提供者としての立ち位置 共創エコシステムへのデータ基盤技術の供給 出展企業・スタートアップとのインターフェース技術としての拡張性 モビリティ、製造、建設、エネルギーなど異分野融合領域での利用接点 つまり、intdash は「データをつなぐ技術」であると同時に、 "共創インフラとしての可能性" を秘めています。 www.aptpod.co.jp 注目技術と共創の視点 技術 特徴 共創ポテンシャル スカイディスク(最適ワークス) AIによる生産計画最適化 プラットフォームと連携し、リアルデータを活用したクロス企業製造最適化が可能 LOZI(SmartBarcode) 製造~物流可視化ソリューション リアルタイムタグ情報をプラットフォームに流し込み、他モジュールと連携可能 ALGO ARTIS 複雑スケジュール最適化エンジン intdash のストリーミングデータで動的スケジューリング実現の連携可能性 Preferred Networks 自社完結型 AI基盤 通信最適化・分散AI・プラットフォーム連携で戦略的立ち位置を模索 技術力だけでなく、「共創に開くか閉じるか」が技術の将来性を決める という点が非常に印象的でした。 技術トレンド・気づき(BE creation視点) 通信基盤の価値向上 : 裏方のインフラから、共創の土台への期待 インターフェース性・拡張性 : API公開やモジュール接続、他社技術との共存性が重要 共創組織文化と技術アプローチの融合 : 制度設計と接続性設計の両立が不可欠 リアルタイム制御×生成AI : ストリーミングデータとリアルタイムAIによる制御・最適化が進行中 技術者視点での総括 intdash は単なるデータ基盤ではなく、 "BE creation の文脈で意味を持つ共創インフラ" として成長可能です。 現代の技術価値は、「良いものを作ること」だけでなく、 "誰と、どう使われるか" によって決まります。 今後のアクションプランとしては: BE creation を考慮しつつ具体的な技術提供先を探索 他出展企業との共同PoC(概念実証)を企画 intdash の機能を共創・拡張性・プラットフォーム性に合わせて強化 これにより、intdash は "「つなぐ技術」から「共創を支える基盤」へ" さらなる進化をしていく。 個人的に興味を持った展示 浮体式洋上風車を開発するベンチャー、 アルバトロス・テクノロジー の展示も印象的でした。 https://www.albatross-technology.com AI普及によるCPU/GPU消費電力の増加に対して、 安定した再生可能エネルギーの一分野として注目される浮体式洋上発電 。 従来型の洋上風力発電とは異なり、低フットプリント・折りたたみ可搬可能な設計 発電時は、携帯電話基地局のような形状で、空間の有効利用が可能 低コストで安定した電力供給が可能 日本の国土は38万km²ですが、EEZ(排他的経済水域)を含めた海洋面積は世界第6位。 洋上領域の利用は、新たな技術・エネルギーパラダイムの鍵 になると感じました。 まとめ intdash は共創を支えるデータ基盤として大きな可能性を秘めてる。 技術の未来は、単なる性能より「共創への開放度」が重要となる。 組み合わせから生まれる新たな価値創出が期待される。
動画ファイルをintdashに取り込みたいみなさん、 こんにちは。ソリューションアーキテクトの伊勢です。 今回はMP4ファイルをintdashの計測データとして登録する方法をご紹介します。 はじめに データフロー H.264とは MP4ファイルとは H.264の格納形式とは Gstreamerとは インストール やってみた 実施手順 MP4ファイルダウンロード 映像編集 アップロード実行 計測再生 サンプルプログラム Convertor MeasurementWriter UploadService エントリーポイント おわりに リンク はじめに すでに保有している計測データファイルをintdashで可視化したいケースがあります。 例えば、システム構想段階でUXを試したいときなどです。 MP4ファイルの計測データ化 通常、intdashの計測データはエッジコンピューターからサーバーに送信されますが、サーバーにファイルの計測データを登録する機能もあります。 intdashのMeas Hubでは、タイプスタンプとデータ値が格納されたCSVファイルをアップロードして計測を作成できます。 Meas Hub 計測アップロード一覧 time,DATA_1,DATA_2,DATA_3 2024-01-01T00:00:00.123456789Z,1,0.1,str1 2024-01-01T00:00:01.123456789Z,2,0.2,str2 2024-01-01T00:00:02.123456789Z,3,0.3,str3 2024-01-01T00:00:03.123456789Z,4,0.4,"str4,example" 2024-01-01T00:00:04.123456789Z,5,0.5,"str5 ""last data""" この方法ではデータは数値または文字列の形式である必要があります。 今回は映像データを登録するため、SDKを使ってツールを実装します。 1 データフロー 今回は、取り込んだ映像を他の計測と同期再生させてみます。 既存の計測からMP4としてダウンロード 映像編集ソフトで加工 ツールでMP4ファイル(編集後)をアップロード Data Visualizerで可視化・同期再生 データフロー H.264とは 今回扱う映像データはH.264で圧縮されています。 前のフレームから変化した部分だけを扱い、データ量を低減する仕組みです。 IDRフレーム/キーフレーム:すべての画素を持ち、単独でデコードできます。動画の基準点として定期的に差し込まれます。 Non IDRフレーム/デルタフレーム:変化した部分だけを持ち、単独では表示できません。IDRフレームと組み合わせて利用されます。 www.idknet.co.jp H.264フレームは、1〜複数のNAL Unit(Network Abstraction Layer Unit)というバイナリ列で構成されます。 MP4ファイルとは 動画や音声をひとつのファイルにまとめて扱える形式です。 再生時には内部の映像や音声を取り出し、タイムスタンプに基づいて同期再生します。 H.264の格納形式とは バイナリデータである映像フレームを区切る方法です。 AVCC形式:保存向き。フレームの先頭にフレームサイズを記録します。最新のMP4で利用されます。 2 Annex B形式:ストリーム向き。フレームの先頭に境界を示すスタートコードを付与します。intdashなど伝送処理で利用されます。 Gstreamerとは 動画・音声を変換できるオープンソースのメディアフレームワークです。 3 今回はMP4ファイルのAVCC形式からAnnex B形式へ変換するのに利用します インストール SDK入門② でインストールしたREST APIのクライアントライブリと、 SDK入門④ でインストールしたGstreamerとPyGObjectライブラリを利用します。 やってみた 実施手順 それでは、前述の流れでMP4ファイルを取り込みます。 H.264フレームのタイムスタンプが各段階でどうなるかを示します。 タイムスタンプ対応 MP4ファイルはAVCC形式のタイプスタンプ項目に1フレーム目起点の相対時刻を持ちますが、絶対時刻はありません。 そのため、ツールで改めて計測の基準時刻を与える必要があります。 MP4ファイルダウンロード intdashのMedia Explorerで元計測の映像をMP4ファイルとしてダウンロードします。 4 このとき、映像1フレーム目の時刻を覚えておきます。 MP4ファイル作成画面 MP4ファイルをダウンロードします。 MP4ファイルダウンロード 映像編集 MP4ファイルを映像編集ソフトで編集します。 今回は文字をオーバーレイしてみます。 MP4ファイルを出力します。解像度・FPSは映像編集ソフトに依存します。 アップロード実行 対象エッジと基準時刻を指定してアップロードします。 今回は元の計測とは別のエッジとして作成します。 基準時刻は元計測の映像1フレーム目の時刻にします。 5 ツール起動 全ての映像フレームがアップロードされ、計測が完了します。 アップロード完了 作成された計測 計測再生 intdashのData Visualizerで元の計測を指定してプレイバック再生します。 映像(左)・GNSS・IMU:元の計測です。 映像(右):編集したMP4ファイルから取り込んだ計測です。 www.youtube.com 映像は元の計測がHD・15FPS、編集後がFullHD・30FPSですが、 計測データのタイムスタンプにより、問題なく同期再生されます。 サンプルプログラム Gstreamerとデータ送信を非同期で実行しています。 クラスアーキテクチャ Gstreamer:H.264フレームをAVCC形式からAnnex B形式に変換します。 Fetchステージ:GsteamerからAnnex B形式のフレームを取り出します。 Convertor Gstreamerをラップします。 入力はMP4ファイルから呼ばれるため、特にメソッドはありません。 出力では、映像フレームを size ごとに取得します。 while len (frames) < size: sample = await asyncio.to_thread(self.sink.emit, "pull-sample" ) MeasurementWriter 計測の作成・完了、シーケンスの作成・置き換え、チャンク送信を行います。 6 intdashのH.264フレームは以下のNAL Unit順で扱うため、Gstreamerから出力されるAUD NALU Type:9 をスキップしています。 IDRフレーム:SPS NALU Type:7 →PPS NALU Type:8 →IDR NALU Type:5 non-IDRフレーム:non-IDR NALU Type:1 payload = MeasurementWriter.skip_aud(frame) IDR/non-IDRを判定し、送信時のデータ型を指定してデータポイント、チャンクを生成しています。 is_idr = self.is_idr_frame(payload) type_name = "h264_frame/idr_frame" if is_idr else "h264_frame/non_idr_frame" store_data_point_group = StoreDataPointGroup( data_id=StoreDataID( type =type_name, name=data_name), data_points=[store_data_point], ) store_data_chunk = StoreDataChunk( sequence_number=self.sequence_number, data_point_groups=[store_data_point_group], ) UploadService GstreamerパイプラインとFetchステージを並列起動しています。 self.convertor.start() fetch_task = asyncio.create_task(self.fetch()) # H.264フレーム取得 エントリーポイント MP4ファイルを読んでH.264(Annex B形式)に変換するGstreamerパイプラインを定義しています。 PIPELINE = """ filesrc location="{path}" ! qtdemux name=demux demux.video_0 ! h264parse config-interval=-1 ! video/x-h264,stream-format=byte-stream,alignment=au ! appsink name=sink sync=false emit-signals=true """ 計測の基準時刻をRFC3339形式で指定します。 指定がないときは現在時刻を基準時刻にしています。 datetime.fromisoformat(basetime) if basetime else datetime.now(tz=timezone.utc), おわりに 今回はintdash外のデータを取り込む一例を紹介しました。 MP4ファイルのタイムスタンプを利用して、intdashの時系列管理に統合できました。 既存の計測データでintdashへの格納や可視化を試せると、システム運用を具体的にイメージしやすくなります。 リンク 本シリーズの過去記事はこちらからご覧ください。 SDK入門①〜社用車で走ったとこ全部見せます〜 :REST APIでデータ取得 SDK入門②〜データ移行ツールの作り方〜 :REST APIでデータ送信 SDK入門③〜RTSPで映像配信するぞ〜 :リアルタイムAPIでデータ取得 SDK入門④〜YOLOで物体検知しちゃう〜 :リアルタイムAPIでデータ送信 SDK入門⑤〜iPadでData Visualizerを見る会〜 :リアルタイムAPIでキャプチャデータ送信 SDK入門⑥〜最速最高度で計測する日〜 : AWS LambdaでREST APIデータ送信 SDK入門⑦〜計測リプレイツールの作り方〜 : REST APIでデータ取得、リアルタイムAPIでデータ送信 コードは GitHub で公開しています。 ↩ MPEG-4 Part 10です。本ツールはこの形式のMP4を前提としています。 ↩ 入門④ でも利用しました。 ↩ 2025年4月のバージョンから時間範囲を指定できるようになりました。 ↩ 計測の開始時刻≦映像の1フレーム目の時刻のためです。 ↩ 計測シーケンス、チャンク送信は 入門② を参照ください。 ↩
IoTデータの通信量にお困りのみなさん、 こんにちは、ソリューションアーキテクトの伊勢です。 車両やロボットがデータ伝送するには無線通信が必要ですが、SIM 1枚では安定しないという課題があります。 山間部や遮蔽物が多いなど電波が弱いエリア 4K画質映像やLiDAR点群などの大容量データ 今回は、SIMやWifiなど複数の回線を束ねるボンディングという技術を実現するマルチ回線ルーターをご紹介します。 はじめに ボンディングとは peplinkルーターとは ボンディングの効果 実測してみた MAX BR2 Pro MAX BR2 Micro おわりに はじめに ボンディングとは 複数の物理的な回線やインターフェースを束ね、仮想的に単一の高速・大容量・高信頼性の通信チャネルとして利用する技術です。 専用のルーターがパケットレベルでデータを複数の回線に分散して送信します。 これにより、1本の帯域を超える大容量データでもスムーズに伝送できます。 通信回線ボンディング peplinkルーターとは 当社ではpeplink社のマルチ回線ルーターをご提供しています。 1 サーバーに配置した仮想ルーター〜物理ルーター間にVPNを構成する仕組みです。 ポイント VPNで伝送したデータは終端ルーターで統合を行う仕組みのため、束ねた複数回線の帯域を単純に足し合わせたより少し低くなります。 tech.aptpod.co.jp ボンディングの効果 車載したエッジコンピューターからカメラ2台分の映像を送信・可視化しました。 www.youtube.com SIM 1枚構成では伝送遅延によりブロックノイズが発生しますが、 SIM 2枚構成ではスムーズに表示できていることがわかります。 2 当社でも、お客様への提案のほか、展示会デモで活用しています。 展示会で多くの方にご来場いただくとLTE回線が混雑する場合、複数SIMの利用でロボットのカメラ・LiDARデータ伝送や遠隔操縦の安定化を感じられます。 tech.aptpod.co.jp 実測してみた ボンディングで通信速度が数値的にどのぐらい上がるのか、色々と回線を組み合わせて検証してみました。 物理ルーターコンソール ポイント 今回はモビリティではなく、オフィスの机上定点で測定しています。 2機種で帯域を計測しました。束ねられる回線数が異なります。 5G マルチ回線モバイルルーター:MAX BR2 Pro インタフェース 回線数 5G/LTE SIM 2 USB 1 Wi-Fi 2 有線WAN 2 マルチ回線モバイルルーター:MAX BR2 Micro インタフェース 回線数 LTE SIM 2 有線WAN x1(LANと共用) 1 計測にはGoogleスピードテストを使用しました。 ポイント 数回実施してみていますが、エリア・時間帯で変動する要素が大きく、結果を保証するものではありません。 MAX BR2 Pro 計測タイミングでブレが大きいのですが、 SIM 1枚よりSIM 2枚の方が、 SIM 2枚よりSIM 2枚 + USB/Wifiの方が 概ね帯域が増加していることが確認できました。 MAX BR2 Pro測定結果 ボンディングの分散具合をintdashへのデータ伝送で確認しました。 アップリンクを多く発生させるため、iPhoneアプリ Motion でMJPEGを送信します。 これで上り40Mbpsほどになります。 MJPEGを送信 FullHD/5FPS 以下のパターンを確認しました。 有線WAN x1 SIM x1 docomo SIM x2 docomo/Softbank SIM x2 docomo/Softbank + Wifi x1 Throughput Tx が複数回線で分散されていることがわかります。 ポイント どのように分散されるかは回線品質の状態によります。 3本まとめたのにほとんど2本しか使われないパターンもありました。 ボンディングによる通信の分散 MAX BR2 Micro SIM 2枚では、ダウンリンク・アップリンクともに15Mbps出ています。 3 MAX BR2 Micro測定結果 おわりに peplinkルーターで回線ボンディング後の帯域を確認しました。 DX化が進むと収集データは多様化・多数化・大容量化されていきます。 ネットワーク帯域の確保は、intdashの安定運用に必要不可欠になっていきます。 当社では、4機種のpeplinkルーターをご提供しています。 大容量データを扱うモビリティの通信安定性に課題を感じている方は、ぜひお問い合わせください。 www.aptpod.co.jp 専用VPN(SpeedFusion VPN)を用いたルーターを利用します。peplinkルーターの日本代理店である CASO様 にご提供いただいています。 ↩ SpeedFusion Engineはすでに販売終了で、現在は後継機をご提供しています。 ↩ 有線WANはEthernetポートが埋まってしまい、PCから接続・スピードテストできないため割愛しています。 ↩
はじめに こんにちは、エンジニアの上野です。 この度、株式会社アプトポッドは2025年7月23日(水)~7月25日(金)に東京ビッグサイトにて開催された「メンテナンス・レジリエンス TOKYO 2025」にNTTドコモビジネス株式会社様と共同で出展いたしました。 mente.jma.or.jp 昨年度のレポート に続きまして、今年は私が弊社の展示や関連技術の見学をしてきましたので、その内容の一部をご紹介したいと思います。 はじめに 会場の様子 展示内容 リアルタイムデジタルツインデモ ロボット点検・設備 マルチモーダル環境センシング 広帯域モバイル伝送 他社様のブースを見学した感想 おわりに 会場の様子 私が見学した日は、快晴かつ真夏の陽気で、非常に暑い一日でした。 それにも関わらず展示会場は多くの来場者で賑わっており、ありがたいことにアプトポッドのブースも盛況で、弊社の技術やサービスに対して高い関心をお寄せいただきました。 展示内容 リアルタイムデジタルツインデモ 昨年に引き続き、日立建機株式会社様のご協力のもと、弊社が開発した リアルタイムデジタルツイン基盤 のデモを展示しました。 youtu.be 今回のデモでは、遠隔地のオペレーターがホイールローダーの搭乗者に対して作業エリアの切り替えを指示し、移動完了後にエリアのステータスが変化する様子を展示しました。私はこのアプリケーションの開発を担当しています。 昨年は点群と重機の可視化が中心でしたが、今年は事前に計測した数千万点クラスの点群を用いて、よりリアルな現場再現と遠隔操作の連携によるインタラクティブな体験を提供するなど、デジタルツインの完成度が一層向上しています。 ロボット点検・設備 今年もUnitree Go2による遠隔操作デモを展示しました。加えて、今回は各足の先端にゴムタイヤを搭載したUnitree Go2-Wも展示されており、階段のような段差も軽々と乗り越える様子が印象的でした。 youtu.be Go2-Wには酸素センサーとアルコールセンサーが搭載されており、会場内に用意されたアルコールスプレーによって、リアルタイムに数値が変化する様子が確認できました。 ロボットによる点検業務への応用が期待されており、異常検知や設備状況の可視化など、実運用を見据えた展示となっていました。 マルチモーダル環境センシング アプトポッドでは、LiDAR・カメラ・温湿度センサーなど、複数のセンサーデータを統合して多面的な環境把握を行う「マルチモーダル環境センシング」にも取り組んでいます。 本展示では、カメラ映像による人体検知、LiDARスキャナによる空間のメッシュ化および人体検出、さらにはサーモグラフィカメラを活用した温度センシングを組み合わせたデモを実施しました。 熱分布の可視化により、異常発熱や熱中症の兆候、設備の異常を早期に発見することが可能です。取得した温度データはintdash上でリアルタイムに可視化され、時系列での分析にも対応しています。 なお、LiDARスキャナによる空間のメッシュ化および人体検出については、株式会社東海林ファジィロボット研究所様 の技術を利用させていただきました。 LiDARスキャナから取得した点群をリアルタイムにメッシュ化することにより、人体検出や詳細な空間形状の把握が可能となります。 広帯域モバイル伝送 アプトポッドでは、複数のモバイル回線を束ねて広帯域なデータ伝送を実現する「intdash Multi Mobile Network」というソリューションを提供しています。 www.aptpod.co.jp youtu.be 今回の展示でも、Unitree Go2に本ソリューションを適用。複数のSIMを用いることで、1枚のSIMでは処理しきれない広帯域の点群・映像データも安定して送信できている様子を確認できました。 UnitreeGoに搭載されたマルチSIMルーター、SIMが2枚刺さっている様子。 一方、昨年と同じ構成(MID-360 LiDAR × SIM1枚)では、データ伝送がギリギリという印象であり、実際のユースケースではマルチSIMの重要性がより高まっていることを実感しました。 他社様のブースを見学した感想 今回、他社様の展示を見学して特に印象的だったのは、「現場の3D化」がより一般化・多様化してきているという点です。 私もかつてiPhone搭載LiDARを用いた3Dスキャン記事を書いたことがありますが、今回の展示ではiPhoneを使ったスキャン、ハンディ型LiDAR、据え置き型レーザースキャナ、ドローン搭載型など、実に多様なスキャン手法が紹介されていました。 特に、法律上ドローンが使いづらい場所ではハンディタイプが有効であり、iPhoneの弱点である位置精度を補うGNSS連携型デバイスなども見られ、各社の工夫と進化が垣間見えました。 炎天下でのiPhoneスキャンに苦しんだ経験がある私としては、代行スキャンサービスの展示も非常に魅力的に感じられ、3D計測の市場が着実に広がっていることを実感しました。 おわりに 昨年に続き出展させていただいた「メンテナンス・レジリエンス TOKYO 2025」は、弊社にとっても技術の発信と学びの両面で非常に有意義な機会となりました。 ご来場いただいた皆様、誠にありがとうございました。 人手で行っていた業務をロボットで行いたい ロボットの遠隔操作を行いたい 大量データを扱えるハイパフォーマンスな可視化アプリケーションを開発したい アプトポッドでは、IoT・ロボティクス・リアルタイム通信の分野で培った技術を活かし、皆さまの課題解決を全力でサポートいたします。お気軽にご相談ください。 お問合せフォームはこちら。 www.aptpod.co.jp
はじめに IoTシステムのデータ伝送には、MQTTが一般的に広く採用されています。AWS IoT、Azure IoT Hubなど、主要クラウドプラットフォームでもMQTTブローカーを内蔵したマネージドサービスが提供されており、ここ数年でIoTシステムの構築は劇的に楽になりました。 しかしながら、MQTTで伝送したリアルタイムデータを実際に活用するための 可視化や分析ツール に関しては、現在も様々なサービスが登場し発展の途上にあります。 MQTTデータ可視化ツールの現状と課題 代表的なMQTTデータの可視化ツールとして、以下のようなものが挙げられます。 MQTT Explorer Node-RED Dashboard ThingsBoard Grafana Live + MQTT Data Source InfluxDB + Chronograf これらのツールにはそれぞれ特徴がありますが、高頻度なセンサーデータ(数百~数千Hz)のリアルタイム表示には十分に対応できず、パフォーマンスに問題が生じるものも多くあります。また、センサーデータに動画や音声といったマルチモーダルデータを統合的かつ同期的に扱うことは難しく、多くのツールでは同期再生ができません。 高頻度マルチモーダルデータの可視化を実現するintdash/Visual M2M 当社は、高頻度でリアルタイム性を求められるIoTデータの伝送と可視化に特化したintdash(伝送ブローカー)およびVisual M2M(可視化ダッシュボードツール)を自社開発しています。intdashとVisual M2Mは、以下のような特徴を持ちます。 ハイパフォーマンス : 数千Hzを超える超高頻度データでもスムーズに描画 マルチモーダル : センサー値に加え、動画や音声なども統合的に同期再生 本記事では、可視化ダッシュボードツールであるVisual M2Mを用いて、MQTTで伝送された高頻度リアルタイムデータを、ハイパフォーマンスに可視化する方法についてご紹介します。 www.aptpod.co.jp 従来Visual M2M(可視化ダッシュボード)を利用するにはバックエンドの伝送基盤としてintdash(伝送ブローカー)を導入し、送信デバイス側もintdashへの対応が必要でしたが、既存のMQTT環境からもintdashの高性能な可視化環境を利用してみたいとのお声をいただき、このたび、後段でご紹介する「MQTT-intdashリレープログラム」を実験的に開発しました。本記事ではこのリレープログラムを用いたMQTTとVisual M2Mの連携方法をご紹介します。 本プロジェクトは現在 Experimental なステータスにあり製品化を模索している状況ですが、ご要望をいただければ本番システムにて稼働できる品質のソフトウェアをご提供可能です。ご興味をお持ちいただけましたら、お問い合わせ等の詳細情報についてはブログ末尾をご確認ください。 MQTTからintdashへのリレー構成 本来、最適なパフォーマンスを実現するには、伝送基盤のintdashと可視化ツールのVisual M2Mをセットで導入していただき、デバイス側も含めてすべてintdashに置き換えていただくのが理想です。 しかし、デバイス側の置き換えには大きな移行コストがかかることも踏まえ、今回は既存システムを活用しながらリレーによってMQTTとintdashを接続する構成をご紹介します。こちらの構成では、まずはintdashとVisual M2Mの性能を気軽に体感していただくことを目的としています。 本構成のメリット: 既存のMQTT環境を変更することなく試験的にVisual M2Mを導入可能 Visual M2Mの優れたパフォーマンスと高機能な可視化を手軽に体験 デメリットとしては、MQTTとintdashの二重構造による冗長性が挙げられますが、まずはVisual M2Mの利便性を体感し、最終的にintdashへの全体移行を検討するためのきっかけとしてご活用いただければ幸いです。 構築ハンズオン 本記事では、既存のMQTTベースのIoTシステムにintdashおよびVisual M2Mを追加導入する構成を前提としたハンズオンを行います。具体的には、OSSのMQTTブローカー(Mosquitto)とRaspberry Piを用いたセンサーデバイスで既存システムを模倣し、そのシステムにintdash/Visual M2Mをリレープログラム経由で追加して、データの可視化までを行います。 ※ 記事執筆当初はハンズオンも含む記事とする予定でしたが、想定外に分量が多くなってしまったため、ハンズオン部分は別途別記事に切り出すこととしました。後日公開予定です。以降のセクションは、ハンズオンの結果についてスクリーンショット付きで解説していきます。 実際の可視化の様子 まずは一般的なMQTTダッシュボードを使用してデータを可視化してみましょう。Raspberry Piからデータ送信を開始しMQTTダッシュボードを確認すると、データが流れている様子が確認できます。 今回は冒頭でも触れた MQTT ExplorerとNode-RED Dashboardをサンプルとしてご紹介します。 MQTT Explorer MQTT Explorer は構築しやすい反面、可視化の表現が限定的です。1トピックあたり1パネルとなり、それぞれのデータの相関具合を確認したりするには少し工夫が必要です。 Node-RED Dashboard 次に、Node-RED Dashboardで可視化する方法も試してみます。 こちらは重ね合わせでの表現も可能ですが、一方でパフォーマンス面で問題が生じました。パフォーマンスの問題については後続のセクションでVisual M2Mと比較します。 Visual M2M 同じデータをintdashにリレーし、Visual M2Mで可視化してみます。 Visual M2Mでは、様々な可視化パーツとグリッドで構成された柔軟なダッシュボードにより、流れているデータを自由に可視化することができます。 ダッシュボードの自由度も高く、描画パフォーマンスも良好で、高頻度なセンサーデータをリアルタイムに描画できました。 描画パフォーマンスの比較 今度は、ダッシュボードの描画パフォーマンスについて、Visual M2Mとその他のツールを比較してみましょう。 今回は比較対象として、Node-RED Dashboardを取り上げます。以下に、Node-RED Dashboard と Visual M2M を並べて再生した動画を示します。 youtu.be Node-RED Dashboardは、静止画では一見問題なく描画されているようにも見えましたが、連続再生していると徐々に描画がリアルタイムから遅れていき、最終的には何秒も遅れたデータが画面上に描画されるようになってしまいました。一方、Visual M2Mは、高頻度データでも滑らかかつ遅延なく表示できています。 低遅延なIoTデータの伝送や可視化については、MQTTなどの "伝送プロトコル" の部分が注目されがちではありますが、最終的にエンドツーエンドで低遅延にデータを届けるには描画側のパフォーマンスも重要な要素であることをおわかりいただけたかと思います。 Grafana との比較と Visual M2M の強み MQTTに少し詳しい方であれば、広く使われている Grafana が比較対象として出てきていないことにお気づきかもしれません。 Grafana は、ダッシュボードの柔軟性やリアルタイム描画のパフォーマンスに関して評価する場合、OSSにおいては最も魅力的かつデファクトスタンダードとなりつつある選択肢の一つです。 このセクションでは、この Grafana について個別に枠を設けて特に掘り下げて、 Visual M2M との違いを明らかにしていきます。 grafana.com Grafana におけるリアルタイム再生の仕組み Grafana は、もともとサーバー監視などで利用されることが多く、単体のままではリアルタイム描画には対応していませんでした。 しかし、v8 で追加された Grafana Live というメッセージングエンジン(Grafana専用のブローカー)を有効化することによって、リアルタイム描画が可能になります。 Grafana Live では、Grafana が稼働しているサーバーのプロセス内に可視化専用の Pub/Sub ブローカーを起動するようです。 Grafana と MQTT とをつなぐ MQTT Data Source は、この仕組みを使用してMQTTブローカーからのデータを専用ブローカーに中継し、Webブラウザまで送り届けます。 Grafana Liveの可視化専用ブローカーは可視化に特化した簡易的なものではあるものの、MQTTブローカーから別のブローカーに中継するという意味で、intdash/Visual M2Mの構成と近しい構成といえます。 Grafana vs Visual M2M それでは、比較のために Grafana での描画の様子をみてみましょう。 UIのデザインに関にしては、これまでに比較した MQTT Explorer や Node-RED Dashboard からは一歩抜きん出ていることが分かります。 黒を基調としたダークなデザインである点がVisual M2Mと良く似ていますが、Visual M2Mのほうが若干ビビッドではっきりした色合い、Grafana のほうがすこし落ち着いた色合いをしています。 youtu.be ここからは、Visual M2Mとの違いを一つずつ見ていきます。 Visual M2Mとの違い① : ブローカーの違い 違いの1つ目は、ブローカーの違いです。 Grafana Live の可視化専用ブローカーは可視化専用の簡易的なもので、通常構成ではサーバーのプロセス内でしか通信ができません。複数のプロセス間で通信するには v8.1 で追加された Redis-based Live HA の構成が必要ですが、これはまだ Experimental 扱いのようです。また、メッセージサイズやフレーム頻度にも限界があり、今回のケースのようなIMUセンサー1台程度であれば問題ありませんでしたが、大量のデバイスからのデータや大量データの可視化ではパフォーマンスが追いつかなくなることが予想されます。 一方、intdash/Visual M2Mでは、そもそも大量のデータを中継するために作られたデータ伝送用のブローカーintdashがデータを中継する構成をとるため、デバイスやデータ量が増えても問題は生じにくくなっています。 Visual M2Mとの違い② : マルチモーダル対応の違い 違いの2つ目は、マルチモーダルデータへの対応方法の違いです。 IoTデータを収集するフィジカルな現場では、数値データだけでなく映像や音声などマルチモーダルなデータを取り扱うことがよくあります。 たとえばリアルタイムな映像データをGrafanaで再生しようと考えた場合、どうなるでしょうか? そもそもMQTTでの映像伝送はあまり一般的ではないのでWebRTCなどを併用することになりますが、WebRTC用のプラグインはコミュニティにより提供されたものしか存在しないようです。 さらにWebRTC用をはじめとする映像再生系のプラグインは、いずれもGrafana Live を使用する仕組みではなく、直接映像データを映像ソースから受け取る仕組みになっているようでした。 このようにデータがそれぞれ別の経路を辿って伝送され、さらに別々の開発元によって作られた別のパネルで再生されるような構成では、 一見同時に再生されているように見えても、各瞬間瞬間で本当に同時刻のデータが画面上に描画されているかは担保できません。 一方、intdashでは、共通のブローカー(intdash)により、センサー値から映像・音声、点群データまで大小様々なデータを、単一のコネクションにより転送することができます。 可視化ツールである Visual M2M も、データの同期を正しく取って再生するように作り込まれているので、マルチモーダルな様々なデータがその瞬間どの様に関連していたのかを正確に把握することができます。 今後の拡張性と推奨構成 今回は、既存システムを活かすことを重視し、intdash/Visual M2Mを横付けする構成としました。しかし、この構成はintdash/Visual M2Mの持つパフォーマンスを最大限に生かせるものではなく、構成上の冗長性もあります。 intdashの性能を最大限に活かすには、バックエンドのMQTTブローカーもintdashに移行し、よりシンプルで効率的な構成とすることがおすすめです。 Visual M2Mはマルチモーダルデータを同一のダッシュボードで再生できるため、従来のMQTTベースのダッシュボードツールでは対応していなかった製造や音声などのデータも、センサーデータとあわせて同期再生できるようになります。 intdashをベースとすることで、マルチモーダルなデータを含む高度なリアルタイム監視や分析環境をシンプルな構成で実現することができるようになり、複数のOSSを組み合わせて構築する場合に比べて運用や保守の負担が大きく軽減されます。 おわりに 本記事では、既存のMQTT環境を維持しながら、intdashおよびVisual M2Mを導入し、その強力なパフォーマンスやマルチモーダルデータの統合表示機能を体感いただける構成をご紹介しました。本記事をきっかけに、まずはVisual M2Mの優れた性能をお試しいただき、そのメリットを実感していただければ幸いです。 ぜひ、この機会にintdash/Visual M2Mのトライアルをお試しください。ご質問や導入に関するご相談は、以下のリンクからお気軽にお問い合わせください。 www.aptpod.co.jp www.aptpod.co.jp
ソリューションアーキテクトの奥山です。 人とくるまのテクノロジー展 2025 YOKOHAMA(5/21–23、パシフィコ横浜) には617 社が出展、約8万人に迫る大型イベントとなりました。弊社アプトポッド も新製品を携えて出展しましたので、レポートをお届けします。 アプトポッドブース(No. 206)では “ 小型 × 即時データ活用 ” を掲げ、 EDGEPLANT R1 と EDGEPLANT CAN FD USB Interface を初披露しました。さらに、自動車業界で長年実績を持つ計測機器メーカー様でも intdash を核にした連携サービスの採用が広がっています。 展示会概要と弊社ブースのご紹介 新製品 EDGEPLANT R1 ―片手サイズエッジコンピュータ 特徴 ユースケース EDGEPLANT CAN FD USB Interface — 高速起動CANロガー 特徴 ユースケース ご要望をお寄せください 関連ブースのご紹介 共和電業様 KYOWA CLOUD STREAM IMV様コネクタ評価試験 まとめ デモ機貸与・PoC のお申し込みはこちら↓ 製品に関するお問い合わせはこちら↓ 展示会概要と弊社ブースのご紹介 会期:2025-05-21(水)– 23(金) 会場:パシフィコ横浜・展示ホール/ノース 規模:出展 617 社・約1,470 小間、総面積 26,500 ㎡、来場者数 79,808 名 アプトポッド は Testing ゾーンに出展しました。来場者の約 7 割が車両開発・研究エンジニアという環境で、 リアルタイム計測と省スペース を両立した新製品と intdash 活用事例を中心に展示しました。 以下が営業チーム渾身のブースです! 狭いながらも目線・動線を計算し、intdash を知っていただくためレイアウトにこだわりました。こだわりすぎて展示コンテンツがギリギリまで仕上がらなかったのはここだけの話です。 www.aptpod.co.jp 弊社ブース 中央 2 台が今回リリースした EDGEPLANT R1 と EDGEPLANT CAN FD USB Interface 。両脇は参考展示の 4K 防塵防水カメラと電源制御ユニットです(鋭意製品化中!)。 新製品 自動車遠隔データ収集ソリューションでは、 intdash Multi Network のデモ映像に足を止める方が多く、「導入したい」とのお声もいただきました。 自動車遠隔データ収集ソリューション 展示会に来れなかった方も intdash Multi Network のデモ映像で体感してみてください。 www.youtube.com 大型ディスプレイでは弊社クラウド活用事例を上映し、「コスト改善につながった」といったお客さまの声を掲示しました。 クラウドによるデータ収集と自動化を支援 映像をYoutubeに公開しましたので、ご覧ください。 www.youtube.com 当日、お客様から様々な業務課題や製品FAQをいただきました。最近の傾向として、遠隔計測にとどまらず計測対象となるデータの種類や容量が爆増するなかで、どのようにデータ処理や管理を効率的に進めるのか、データ収集後の利用活用について課題をお持ちのお客様が多くいらっしゃる印象をもちました。弊社エキスパートによる提案事例紹介や商談裏話などを共有させていただき、お客様との対話を深めることができました。会期を通じて、展示会ならではな熱気を感じとることができ、より良い製品をめざして開発に取組むための活力をいただくことができました。 intdash AutomotivePro おかげさまで 3 日間とも大盛況。最終日はブース内が身動きできないほどでした。ご来場いただいた皆さま、誠にありがとうございました! 大盛況のブース その他、人とくるまのテクノロジー展で展示させていただいた動画は以下リンクからご覧いただけます。 youtu.be youtu.be テックブログらしく技術ネタを一つ。写真のモザイクは YOLOv8-face を使った自作 Python スクリプトで自動処理しています。Haar Cascade ではなく Transformer ベースの最新モデルを採用し、高精度に顔を検出して OpenCV でモザイクを適用。 プライバシー保護もモダンな AI 技術で解決 しています。 新製品 EDGEPLANT R1 ―片手サイズエッジコンピュータ 特徴 機能 概要 通信一体型 LTE / GNSS / Wi-Fi(オプション) をオンボード 計測 I/O CAN 2 ch・アナログ 4 ch・USB × 3・IMU (416 Hz) 車載適合 −20 ~ +65 °C・耐振動 / 耐衝撃・CAN ウェイク対応 OS Terminal System OS 2+intdash SDK 筐体 84 × 95 × 28 mm・285 g(片手サイズ) 詳細はプレスリリースをご覧ください。 www.aptpod.co.jp ユースケース 二輪走行テスト — シート下やカウル内に収まるサイズ&軽量で操縦安定性評価に最適 搬送ロボ/AGV 監視 — 小型モビリティへの搭載性に優れ、遠隔テレメトリが容易 ユーザー車両フリート調査 — 目立たない場所に設置でき、市場品質データを長期取得 EDGEPLANT CAN FD USB Interface — 高速起動CANロガー 特徴 機能 概要 CAN / CAN FD 2 ch データレート ~ 8 Mbps 高速ブート 電源投入後すぐにロギング開始(SD 40 GB) 自己給電 USB / 外部 9–36 V。イグニッション連動&低スタンバイ電流 筐体 57 × 64 × 24 mm・約110 g(従来比 −30 %) 詳細はプレスリリースをご覧ください。 www.aptpod.co.jp ユースケース ECU 起動シーケンス検証 — イグニッション直後の CAN FD を取りこぼしゼロで取得 短サイクル配送車の運行ログ — STOP&GO 数分でもロギング欠落なし EV 常時電源ログ — イグニッション OFF 中も CAN 通信を検知・記録 ご要望をお寄せください 開発中機能の優先順位はユーザーの声を基に決定しています。ぜひお気軽にフィードバックをお寄せください! 関連ブースのご紹介 共和電業様 KYOWA CLOUD STREAM 共和電業様のブースでは、多チャネルロガー CTRS‑100 シリーズ と intdash を連携したクラウド計測サービス KYOWA CLOUD STREAM を展示。センサデータをリアルタイムでクラウド可視化し、取得データは MF4 形式で自動エクスポートできるため、後段の FFT など二次解析ツールへスムーズに受け渡せます。現場とオフィスをシームレスにし、業務効率を大幅に向上させます。 共和電業様ブース KYOWA CLOUD STREAM kyowacloud.kyowa-ei.com IMV様コネクタ評価試験 IMV様のブースでは、長期連続運転を想定した耐久試験業務の一つである「コネクタ評価試験」における intdash 活用デモをご紹介いただきました。振動と通電ストレスを同時に与えながら、接触抵抗・電圧降下・温度・加速度 をリアルタイムで送信し、試験中のグラフ化や異常監視を自動化。これにより、自動車や航空宇宙分野で求められる高度な品質試験において、データ収集・管理の負荷を大幅に軽減し、試験設備の稼働率向上が期待できます。 IMV様ブース まとめ 「片手サイズ × 高速起動」 の EDGEPLANT 新製品は、車載開発の “あと少し足りない” を埋める存在になると実感。 共和電業様・IMV 様の共同デモでは intdash のクラウドネイティブ計測 が試験現場の省力化に寄与できることを再確認しました。 会期 3 日間で 450 枚超 の名刺/バーコードを頂戴し、具体的な PoC ご相談も多数。ご来場ありがとうございました! デモ機貸与・PoC のお申し込みはこちら↓ www.aptpod.co.jp 製品に関するお問い合わせはこちら↓ www.aptpod.co.jp
intdashグループの落合です。普段はIoTデバイス側の製品開発を担当しています。 弊社が アプライアンス 製品として提供しているゲートウェイデバイスには、独自のLinuxディストリビューションである intdash Terminal System [1] (以降、Terminal System OSと呼びます)が搭載されており、 Mender を利用したOTAアップデート機能を備えています。 一方、お客様から intdash Edge Agent 2 [2] を個別インストールした場合でも同じようにOTAアップデートを行いたいという要望をいただくことがあります。 本記事では、個別インストールしたintdash Edge Agent 2をアップデートするために使えるOTAソリューションを選定し、どのようにリモートからアップデートできるか、実際の実装例も含めて解説していきます。 正確には intdash Terminal System 2 OSといいます。このOSは、Yocto Projectをベースに開発された独自のLinuxディストリビューションで、ゲートウェイデバイスに搭載されています。Menderを利用したOTAアップデート機能を備え、電源を入れるだけでintdashに接続し、データ送受信が行えます。 ゲートウェイデバイスからintdashサーバーへ時系列データを送受信するソフトウェアです。ゲートウェイデバイスにインストールすることで、センサーやカメラから取得したデータをクラウドにアップロードし、遠隔監視や制御を可能にします。 組み込みデバイスのOTAソリューション比較 intdash Edge Agent 2 の OTAに適したソリューション選定 OTAアップデート機能の実現方法 準備: Raspberry Pi に intdash Edge Agent 2をインストールする 実装例:AWS IoT Device Management 編 ステップ1: Thing の作成とAWS IoT Device Client の設定 ステップ2 : AWS IoT Job の作成と送信 ③ OTAアップデート用のJobの作成 実装例:Mender 編 ステップ1: Hosted Menderアカウントの作成と mender-client のインストール ステップ2 : Mender Artifact の作成とデプロイ ④ Mender Artifactの作成と登録 ⑤ アプリケーションアップデート まとめ 付録:AWS IoT Device Management編 ステップ1: Thing の作成と AWS IoT Device Client の設定 ① AWS IoT CoreでThingを作成する ② AWS IoT Device Clientのインストール 付録:Mender編 ステップ1: Hosted Menderアカウントの作成と mender-client のインストール ① hosted Mender accountの作成 ② Mender Clientのインストール ③ hosted Menderでの認証 組み込みデバイスのOTAソリューション比較 OTAソリューションには、OSレベルでのアップデートが可能なものと、OS上のミドルウェア/ソフトウェアのアップデートのみが可能なものがあります。 ソリューション OSアップデート ソフトウェアアップデート ライセンス/コスト AWS IoT Device Management △ ※ FreeRTOSがインストールされたデバイスのみが対象 ○ ※ 所定のソフトウェア(AWS IoT SDK)がインストールされたデバイス 従量課金制 Mender ○ ※ Yocto Project等で必要要件を満たしてビルドされたLinux OSが対象 ○ ※ 所定のソフトウェア(mender-client)がインストールされたデバイス 商用版:有償 OSS版:無償(機能制限あり) RAUC ○ ※ Yocto Project等で必要要件を満たしてビルドされたLinux OSが対象 △ ※ Yocto Project等でビルドされたLinux OS上であれば可能 オープンソース:無償 SWUpdate ○ ※ Yocto Project等で必要要件を満たしてビルドされたLinux OSが対象 △ ※ Yocto Project等でビルドされたLinux OS上であれば可能 オープンソース:無償 Balena × △ ※ BalenaOSがインストールされたデバイスが対象 商用版:有償 開発用:無償(台数制限あり) 比較表を見ると、ソフトウェアアップデートする場合については、RAUC や SWUpdate、Balena のように専用のOSを必要とするものと、AWS IoT Device Management や Mender のように、クライアントソフトウェアをインストールすればよいだけのものとに分かれることが分かります。 ちなみに、前述の Terminal System OS の場合は、Yocto Project によるカーネルレベルでのカスタマイズを行っていたことと、コンテナ技術によるアプリケーションのデプロイにも対応させたかったことからMenderでのOSアップデートを採用しています。以下の記事にて詳しく解説されていますので、よろしければご覧ください。 tech.aptpod.co.jp intdash Edge Agent 2 の OTAに適したソリューション選定 intdash Edge Agent 2を個別にインストールする場合、既存のOSに追加でインストールするケースがほとんどです。 このため、選定基準として次の点を重視しました: 既存OSに手を加えずに導入できること クライアントソフトウェアのインストールのみで利用できること これらの基準から、AWS IoT Device ManagementとMenderが候補として残りました。どちらも既存OSに必要なソフトウェアをインストールするだけで、アップデートが実現可能です。 以降では、この2つのソリューションについて、実現方法を検討していきます。 OTAアップデート機能の実現方法 intdash Edge Agent 2は、専用の公開リポジトリを登録することで、aptコマンドによってインストール・アップデートをすることができます。よって、OTAアップデートの際にも、OTAソリューションによって apt コマンドを実行することさえできれば、実際のアップデート自体は aptコマンドがよしなにやってくれることになります。 OTAソリューションとaptコマンドの役割分担を整理すると、以下のようになります。 ソリューション / プログラム 役割 OTAソリューション 遠隔からのユーザーの指示に従いaptコマンドを実行 Apt リポジトリからパッケージをダウンロードしてアップデート AWS IoT Device ManagementではJob機能を使用して、Menderではアプリケーションアップデート機能を使用して、それぞれリモートからコマンドを実行できます。 準備: Raspberry Pi に intdash Edge Agent 2をインストールする 今回はRaspberry Pi 4B に Ubuntu 22.04 LTS(Raspberry Pi Generic preinstalled server image)をインストールしたデバイスを用いて、AWS IoT Device Management と Mender における具体的なOTAアップデートの実現方法を確認していきます。 intdash Edge Agent 2をaptコマンドでインストールするには、公開リポジトリの登録が必要です。登録した後に古いバージョンの intdash Edge Agent 2もバージョン指定でインストールしておきます。 $ sudo apt-get update $ sudo apt-get install -y \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent $ sudo mkdir -p /etc/apt/keyrings $ curl -fsSL https://repository.aptpod.jp/intdash-edge/linux/ubuntu/gpg | \ sudo gpg --dearmor -o /etc/apt/keyrings/intdash-edge.gpg $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/intdash-edge.gpg] \ https://repository.aptpod.jp/intdash-edge/linux/ubuntu \ jammy \ stable" \ | sudo tee /etc/apt/sources.list.d/intdash-edge.list $ sudo apt-get update $ sudo apt-get install --no-install-recommends -y intdash-edge-agent2=1.2.0 インストールされている、バージョンも確認しておきます。 $ apt list -a --installed intdash-edge-agent2 Listing... Done intdash-edge-agent2/unknown 1.3.0 arm64 [upgradable from: 1.2.0] intdash-edge-agent2/unknown 1.2.3 arm64 intdash-edge-agent2/unknown 1.2.1 arm64 intdash-edge-agent2/unknown,now 1.2.0 arm64 [installed,upgradable to: 1.3.0] intdash-edge-agent2/unknown 1.1.5 arm64 intdash-edge-agent2/unknown 1.1.4 arm64 intdash-edge-agent2/unknown 1.1.2 arm64 intdash-edge-agent2/unknown 1.1.1 arm64 intdash-edge-agent2/unknown 1.1.0 arm64 intdash-edge-agent2/unknown 1.0.9 arm64 intdash-edge-agent2/unknown 1.0.8 arm64 intdash-edge-agent2/unknown 1.0.7 arm64 intdash-edge-agent2/unknown 1.0.6 arm64 intdash-edge-agent2/unknown 1.0.5 arm64 intdash-edge-agent2/unknown 1.0.4 arm64 intdash-edge-agent2/unknown 1.0.3 arm64 インストールされたバージョンは 1.2.0 になっていて、最新のアップデートは 1.3.0 、 1.2.0 に対するパッチアップデートでは 1.2.3 が存在することが分かります。 ちなみに、以下のように設定をしておくことで、インストールされるバージョンを固定することができます。 $ cat << EOF | sudo tee /etc/apt/preferences.d/intdash-edge-agent2.pref Package: intdash-edge-agent2 Pin: version 1.2.* Pin-Priority: 999 EOF この設定ファイルでは、インストールされるバージョンを 1.2.x系のパッチバージョンに限定しています。 実装例:AWS IoT Device Management 編 今回やりたいことに適したドキュメントが こちら にあるので、これを参考にしました。概要をまとめると以下のようになります。 ステップ1: Thing の作成と AWS IoT Device Client の設定 ① AWS IoT CoreでThingを作成する ② AWS IoT Device Clientのインストール ステップ2 : AWS IoT Job の作成と送信 ③ OTAアップデート用のJobの作成 ステップ1: Thing の作成とAWS IoT Device Client の設定 ステップ1に関しては、本編上に記載すると煩雑になりすぎるため、巻末に付録として添付しました。詳細な手順を知りたい方は、リンク先の巻末を御覧ください。 ステップ2 : AWS IoT Job の作成と送信 ③ OTAアップデート用のJobの作成 AWS IoT Job を作成することで、アップデートを行いましょう。 準備編 でAptの設定が事前に完了しているため、以下のコマンドを実行すると、「特定のマイナーバージョンに対してパッチバージョンの更新のみ行う」作業が実行されます。 $ apt-get install -y intdash-edge-agent2 このため、アップデートをするには、テンプレートの AWS-Install-Application を使用すれば問題ありません。 AWS IoT CoreのコンソールでJobを作成する手順は以下の通りです。 左側メニューから Manage > Remote actions > Jobs を選択し、 Create job をクリックします。 Create custom job を選択し、 Next をクリックします。 Name に名前(ここでは Update_intdashEdgeAgent2 )を入力し、 Next をクリックします。 Things to run this job に対象のThing(ここでは UpdateTestPilot )を選択し、 Job document は From template を選択し、 Template type に AWS managed templates を選択し、 Template に AWS-Install-Application を選択し、 packages にアップデートするパッケージ名(ここでは intdash-edge-agent2 )を入力し、 runAsUser に root を入力し、 Next をクリックします。 Job run typeにSnapshot を選択し、 Submit をクリックします。 Jobが完了するまで待ちます。 完了したので、Raspberry Pi 側でログを確認してみます。 $ journalctl -u aws-iot-device-client -f Jun 24 03:01:07 update-test-pilot aws-iot-device-client[7133]: 2024-06-24T03:01:07.772Z [ERROR] {8435}: debconf: falling back to frontend: Readline Jun 24 03:01:07 update-test-pilot aws-iot-device-client[7133]: 2024-06-24T03:01:07.772Z [ERROR] {8435}: debconf: unable to initialize frontend: Readline Jun 24 03:01:07 update-test-pilot aws-iot-device-client[7133]: 2024-06-24T03:01:07.772Z [ERROR] {8435}: debconf: (This frontend requires a controlling tty.) Jun 24 03:01:07 update-test-pilot aws-iot-device-client[7133]: 2024-06-24T03:01:07.772Z [ERROR] {8435}: debconf: falling back to frontend: Teletype Jun 24 03:01:07 update-test-pilot aws-iot-device-client[7133]: 2024-06-24T03:01:07.772Z [ERROR] {8435}: dpkg-preconfigure: unable to re-open stdin: Jun 24 03:01:07 update-test-pilot aws-iot-device-client[7133]: 2024-06-24T03:01:07.772Z [WARN] {JobEngine.cpp}: While executing action Install-Application, JobEngine reported receiving errors from STDERR Jun 24 03:01:07 update-test-pilot aws-iot-device-client[7133]: 2024-06-24T03:01:07.772Z [INFO] {JobsFeature.cpp}: Job exited with status: 0 Jun 24 03:01:07 update-test-pilot aws-iot-device-client[7133]: 2024-06-24T03:01:07.772Z [WARN] {JobsFeature.cpp}: JobEngine reported receiving errors from STDERR Jun 24 03:01:07 update-test-pilot aws-iot-device-client[7133]: 2024-06-24T03:01:07.772Z [INFO] {JobsFeature.cpp}: Job executed successfully! Jun 24 03:01:08 update-test-pilot aws-iot-device-client[7133]: 2024-06-24T03:01:08.195Z [INFO] {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job Install-Application が status: 0 で終了しているため、成功したようです。 現在のパッケージバージョンを確認してみます。 $ apt list --installed intdash-edge-agent2 Listing... Done intdash-edge-agent2/unknown,now 1.2.3 arm64 [installed] N: There are 14 additional versions. Please use the '-a' switch to see them. ✅ 期待通りに、マイナーバージョンは変わらずに、パッチバージョンの更新がされました! 実装例:Mender 編 Menderを使用して、アプリケーションのアップデートを行う方法は、 こちら に記載されているように、 Mender Clientがインストールされたイメージ を使用することもできますが、本記事の趣旨に沿って、今回は 準備編 で構築済みのRaspberry Piに対して、追加でmender-clientをインストールしてみます。 手順をまとめると以下のようになります。 ステップ1: Hosted Menderアカウントの作成と mender-client のインストール ① hosted Mender accountの作成 ② Mender Clientのインストール ③ hosted Menderでの認証 ステップ2 : Mender Artifact の作成とデプロイ ④ Mender Artifactの作成と登録 ⑤ アプリケーションアップデート ステップ1: Hosted Menderアカウントの作成と mender-client のインストール ステップ1に関しては、本編上に記載すると煩雑になりすぎるため、巻末に付録として添付しました。詳細な手順を知りたい方は、リンク先の巻末を御覧ください。 ステップ2 : Mender Artifact の作成とデプロイ ④ Mender Artifactの作成と登録 アプリケーションアップデートのために必要なMender Artifactの作成をして、アップデートを行なってみましょう。 準備編 でAptの設定が事前に完了しているため、以下のコマンドを実行すると、「特定のマイナーバージョンに対してパッチバージョンの更新のみ行う」作業が実行されます。 $ apt-get install -y intdash-edge-agent2 このため、上記コマンドを実行するMender Artifactを作成すれば問題ありません。 Mender Artifact は、 ファイルフォーマット に準拠して作成する必要があります。ただし、今回はスクリプトを実行するだけなので、 mender-clientのインストール によって使用できるようになる scriptアップデートモジュール を利用することで簡単に作ることができます。 作成に必要なmender-artifactツールはdockerイメージが提供されているため、そちらを使用して以下のコマンドで作成します。 まず、アップデートを行うコマンドを実行するスクリプトを記載します。 $ cat > update-script.sh << EOF #!/bin/bash apt-get install -y intdash-edge-agent2 EOF 次にdockerでmender-artifactを実行します。 $ docker run -v $(pwd):/work -w /work \ --rm mendersoftware/mender-ci-tools:1.0.0 \ mender-artifact write module-image -T script \ -n intdash-edge-agent2-update-1.0 \ -t raspberrypi4 \ -o intdash-edge-agent2-update-1.0.mender \ -f update-script.sh ホストのカレントディレクトリに intdash-edge-agent2-update-1.0.mender というファイルが出来上がっているので、これでMender Artifactは完成です。 次に intdash-edge-agent2-update-1.0.mender を hosted Mender に登録します。手順は以下の通りです。 hosted Mender にログインし、 RELEASES をクリックし、 UPLOAD をクリックします。 アップロードするファイル intdash-edge-agent2-update-1.0.mender のファイルを選択します。 UPLOAD ARTIFACT をクリックします。 ⑤ アプリケーションアップデート 作成したMender ArtifactをRaspberry Piにデプロイしてアップデートをしてみます。手順は以下の通りです。 hosted Mender にログインし、 DEVICES > All devices をクリックし、 Status: accepted で認証済みのデバイスをフィルターします。対象のデバイスにチェックを入れ、右下の + ボタンをクリックします。 表示されたメニュから Create deployment for this device をクリックします。 Select a Release to deploy に intdash-edge-agent2-update-1.0 を選択し、 CREATE DEPLOYMENT をクリックします。 deploymentが完了するまで待ちます。 deploymentが完了すると、 DEPLOYMENTS > Finished の中にリストされます。 成功しているようです。 詳細を確認すると以下のようになっています。 Raspberry Piにログインして、現在のパッケージバージョンを確認してみます。 $ apt list --installed intdash-edge-agent2 Listing... Done intdash-edge-agent2/unknown,now 1.2.3 arm64 [installed] N: There are 14 additional versions. Please use the '-a' switch to see them. ✅ 期待通りに、マイナーバージョンは変わらずに、パッチバージョンの更新がされました! まとめ OTAソリューションとして使える、AWS IoT Device Management、Mender、RAUC、SWUpdate、Balenaを比較し、シンプルなOTAアップデートのシナリオをAWS IoT Device ManagementとMenderで試してみました。 今回のようにソフトウェアアップデートだけを考えると、AWS IoT Device ManagementはJobのテンプレートが準備されているため、学習コストや手間が少なと導入しやすかったです。ですが、将来的にOSのアップデートも視野に入れるのであればMenderを選択するケースもあると思います。 OTAアップデートを検討中の方にとって、この記事が参考になったら幸いです! 付録:AWS IoT Device Management編 ステップ1: Thing の作成と AWS IoT Device Client の設定 ① AWS IoT CoreでThingを作成する ⚠️ 「 ② AWS IoT Device Clientのインストール 」の作業にあるビルドが約20分かかります。まずはそちらを先に進めていただいてから、この作業をする方が効率的かもしれません。 AWSマネジメントコンソールからIoT Coreを開きます。 左側メニューから Manage > All devices > Things を選び Create things をクリックします。 Create Single Thing を選び Next をクリックします。 Thing name に名前(ここでは UpdateTestPilot )を入力しNextをクリックします。 Auto-generate a new certificate (recommended) を選択し Next をクリックします。 Create plicy をクリックします。 Policy name に名前(ここでは AllActions )を入力して、 Policy action に * を選択し、 Policy resource に * を選択し、 Create をクリックします。 ☑️ AWS IoT Core での Thing と Certificates と Policy の関係性は以下の図のように、Policyは直接Thingに紐付いている訳ではなく、Certificatesを経由して紐付いています。 +--------------+ +---------------+ +---------------+ | Thing | 1----1..* | Certificate | 1----0..* | Policy | +--------------+ +---------------+ +---------------+ `- アクティブなCertificateは1つだけ Policies の画面は閉じて Create single thing の画面に戻り、作成したポリシーを有効にして Create thing をクリックします。 証明書と鍵のダウンロードのためのダイアログが出るので、ファイル全てをダウンロードして Done をクリックします。 ダウンロードした証明書や鍵はデバイス側で使うので、Raspberry Piにコピーし、PCからは削除しておきます。 ② AWS IoT Device Clientのインストール AWS IoT Device Client の GitHub リポジトリ にREADMEがあるので、そちらの手順に従いインストールしてみます。 まずは、Raspberry Pi の Ubuntu にログインし、必要なパッケージをインストールします。 $ sudo apt install build-essential cmake git libssl-dev 使用するAWS IoT Device Clientのソースは v1.9.2 にします。 $ git clone -b v1.9.2 https://github.com/awslabs/aws-iot-device-client プロジェクトディレクトリ内に移動します。 $ cd aws-iot-device-client ソースをそのままビルドすると、ワーニングが出る箇所があり、ビルドエラーとして扱わられるようになっているためビルドできないので、対象のワーニングは許容するパッチをあてます。 $ sed -i -e 's/target_compile_options(${DC_PROJECT_NAME} PRIVATE -Wall -Wno-long-long -pedantic -Werror)/target_compile_options(${DC_PROJECT_NAME} PRIVATE -Wall -Wno-long-long -pedantic -Werror -Wno-error=ignored-attributes)/' CMakeLists.txt ビルドします。 ⚠️ 今回の環境では20分程度かかります。 $ bash << BUILD_SCRIPT #!/usr/bin/env bash set -e mkdir build cd build cmake ../ cmake --build . --target aws-iot-device-client BUILD_SCRIPT 次にセットアップのための準備を行います。 セットアップでは以下の情報が必要になります。 AWS IoT endpoint 作成済みの証明書など一式 各ファイルのパーミッションはAWS IoT Device Clientの期待にあったパーミッションになっている必要がある そのため、まず AWS IoT endpoint を以下のAWS CLIを実行して取得します。AWS CLIの認証情報は IoT Coreにアクセスできる認証情報を使用して実行してください。 aws iot describe-endpoint --endpoint-type iot:Data-ATS 証明書など一式はディレクトリに移動し、適したパーミッションに変更をします。 sudo install -m 0700 -d /root/certs sudo mv ~/*-certificate.pem.crt ~/*-private.pem.key ~/*-public.pem.key ~/AmazonRootCA?.pem /root/certs/ sudo find /root/certs/ -type f -exec chown root:root {} \; sudo find /root/certs/ -type f -exec chmod 0644 {} \; sudo find /root/certs/ -type f -name "*-private.pem.key" -exec chmod 0600 {} \; 準備した情報を用いてセットアップを行うために、setup.shを実行します。 $ sudo ./setup.sh WARNING: Only run this setup script as root if you plan to run the AWS IoT Device Client as root, or if you plan to run the AWS IoT Device Client as a service. Otherwise, you should run this script as the user that will execute the client. Do you want to interactively generate a configuration file for the AWS IoT Device Client? y/n y Specify AWS IoT endpoint to use: あらかじめ取得したAWS IoT endpoint。 e.g. xxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com Specify path to public PEM certificate: /root/certs/*.pem.crt Specify path to private key: /root/certs/*-private.pem.key Specify path to ROOT CA certificate: /root/certs/*.pem Specify thing name (Also used as Client ID): UpdateTestPilot Would you like to configure the logger? y/n y Specify desired log level: DEBUG/INFO/WARN/ERROR INFO Specify log type: STDOUT for standard output, FILE for file STDOUT Specify path to desired log file (if no path is provided, will default to /var/log/aws-iot-device-client/aws-iot-device-client.log: Creating default log directory... Would you like to configure the SDK logging? y/n n Enable Jobs feature? y/n y Specify absolute path to Job handler directory (if no path is provided, will default to /etc/.aws-iot-device-client/jobs): Enable Secure Tunneling feature? y/n y Enable Device Defender feature? y/n y Specify an interval for Device Defender in seconds (default is 300): Enable Fleet Provisioning feature? y/n n Enable Pub Sub sample feature? y/n n Enable Config Shadow feature? y/n n Enable Sample Shadow feature? y/n n { "endpoint": "xxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com", "cert": "/root/certs/*.pem.crt", "key": "/root/certs/*-private.pem.key", "root-ca": "/root/certs/*.pem", "thing-name": "UpdateTestPilot", "logging": { "level": "INFO", "type": "", "file": "/var/log/aws-iot-device-client/aws-iot-device-client.log", "enable-sdk-logging": false, "sdk-log-level": "TRACE", "sdk-log-file": "/var/log/aws-iot-device-client/sdk.log" }, "jobs": { "enabled": true, "handler-directory": "/etc/.aws-iot-device-client/jobs" }, "tunneling": { "enabled": true }, "device-defender": { "enabled": true, "interval": 300 }, "fleet-provisioning": { "enabled": false, "template-name": "", "template-parameters": "", "csr-file": "", "device-key": "" }, "samples": { "pub-sub": { "enabled": false, "publish-topic": "", "publish-file": "/etc/.aws-iot-device-client/pubsub/publish-file.txt", "subscribe-topic": "", "subscribe-file": "/etc/.aws-iot-device-client/pubsub/subscribe-file.txt" } }, "config-shadow": { "enabled": false }, "sample-shadow": { "enabled": false, "shadow-name": "", "shadow-input-file": "", "shadow-output-file": "" } } Does the following configuration appear correct? If yes, configuration will be written to /etc/.aws-iot-device-client/aws-iot-device-client.conf: y/n y Configuration has been successfully written to /etc/.aws-iot-device-client/aws-iot-device-client.conf Creating default pubsub directory... Do you want to copy the sample job handlers to the specified handler directory (/etc/.aws-iot-device-client/jobs)? y/n y Do you want to install AWS IoT Device Client as a service? y/n y Enter the complete directory path for the aws-iot-device-client. (Empty for default: ./build/aws-iot-device-client) Enter the complete directory path for the aws-iot-device-client service file. (Empty for default: ./setup/aws-iot-device-client.service) Do you want to run the AWS IoT Device Client service via Valgrind for debugging? y/n n Installing AWS IoT Device Client... /usr/bin/systemctl Created symlink /etc/systemd/system/multi-user.target.wants/aws-iot-device-client.service → /etc/systemd/system/aws-iot-device-client.service. ● aws-iot-device-client.service - AWS IoT Device Client Loaded: loaded (/etc/systemd/system/aws-iot-device-client.service; enabled; preset: enabled) Active: active (running) since Sat 2024-06-22 06:34:09 UTC; 69ms ago Main PID: 41844 (aws-iot-device-) Tasks: 1 (limit: 3864) Memory: 844.0K (peak: 1.5M) CPU: 38ms CGroup: /system.slice/aws-iot-device-client.service └─41844 /sbin/aws-iot-device-client --config-file /etc/.aws-iot-device-client/aws-iot-device-client.conf Jun 22 06:34:09 mptcp-proxy systemd[1]: Started aws-iot-device-client.service - AWS IoT Device Client. q AWS IoT Device Client is now running! Check /var/log/aws-iot-device-client/aws-iot-device-client.log for log output. 付録:Mender編 ステップ1: Hosted Menderアカウントの作成と mender-client のインストール ① hosted Mender accountの作成 アカウントがない場合は hosted Menderにサインアップ します。 ② Mender Clientのインストール こちら の手順に従ってインストールの準備をします。 $ sudo apt-get update $ sudo apt-get install --assume-yes \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common $ curl -fsSL https://downloads.mender.io/repos/debian/gpg | sudo tee /etc/apt/trusted.gpg.d/mender.asc $ gpg --show-keys --with-fingerprint /etc/apt/trusted.gpg.d/mender.asc $ echo "deb [arch=$(dpkg --print-architecture)] https://downloads.mender.io/repos/debian ubuntu/jammy/stable main" \ | sudo tee /etc/apt/sources.list.d/mender.list > /dev/null $ sudo apt-get update インストーラーを起動 $ sudo apt-get install mender-client4 インストーラーを起動するとコンソールに以下のように、hosted Menderに接続するための情報を訪ねられるので、入力していきます。 Mender Client Setup =================== Setting up the Mender client: The client will regularly poll the server to check for updates and report its inventory data. Get started by first configuring the device type and settings for communicating with the server. The device type property is used to determine which Mender Artifact are compatible with this device. Enter a name for the device type (e.g. raspberrypi3): [update-test-pilot] raspberrypi4 Are you connecting this device to hosted.mender.io? [Y/n] Y Enter your credentials for hosted.mender.io Email: あらかじめMenderサーバーに登録しておいたEメール Password: あらかじめMenderサーバーに登録しておいたパスワード Demo intervals uses short poll and retry intervals (Recommended for testing.) Do you want to run the client in demo mode? [Y/n] Y Mender setup successfully. ③ hosted Menderでの認証 Menderでの認証方法には さまざまな方法 がありますが、ここでは Authorize-on-request Flow で認証します。 hosted Mender にログインし、 DEVICES > All devices をクリックし、 Status: pending で認証待ちのデバイスをフィルターします。対象のデバイスのMACアドレスが表示されているのでこのデバイスをクリックします。 Accept をクリックして認証します。
既存の計測データをアップストリームしたいみなさん、 こんにちは。ソリューションアーキテクトの伊勢です。 システム開発の現場では、一度取得した計測データを再利用して送信したい場面があります。 今回はintdashの計測データを "リプレイ" する方法をご紹介します。 はじめに 再び、intdash API/SDKとは チャンク転送エンコーディング List Data Points のレスポンス確認 やってみた インストール 全体構成 対象計測 リプレイ開始 起動オプション データ取得元オプション データ送信先オプション 再生オプション サンプルプログラム説明 データポイント取得 時刻変換 再生スピード調整 メモリ使用量表示 サンプルプログラム修正 エクスポート インポート おわりに リンク はじめに 開発中にエッジの載っているモビリティをいつでも自由に動かせるとは限りません。 他の作業と利用が重なる 計測には複数名体制の準備が必要 利用施設の申請が必要 偶然得られたデータが再現できない また、本番データを検証環境でデバッグしたいケースもあります。 そんなときに、取り溜めた計測データを手軽にリアルタイム送信できれば、開発効率が高まります。 再び、intdash API/SDKとは 本シリーズではこれまで、intdash APIを REST API と リアルタイムAPI に分けて説明してきました。 このうち、REST APIは一般的なHTTPリクエスト・レスポンス形式の通信方式です。 intdash SDK REST APIで唯一、大容量データ取得に特化した List Data Points エンドポイントは、チャンク転送エンコーディングをサポートしています。 これは、大きなデータを効率よく転送し、クライアント側のメモリ消費を抑えるための設計です。 List Data Pontsエンドポイントのレスポンス定義 チャンク転送エンコーディング サーバーがコンテンツの全体のサイズを事前に決定できない場合や、大容量データ転送の効率化に使用されるデータ転送方式です。 通常、HTTPレスポンスの Content-Length ヘッダには、クライアントが受信すべきデータの総バイト数が記載されます。 しかし、動的に生成されるコンテンツや巨大データのようにデータサイズが事前に不明な場合、 Content-Length を指定するのが難しくなります。 そこで Transfer-Encoding: chunked ヘッダを指定して、データをチャンク(塊)に分けて順次送信する方式が使われます。 これには以下の利点があります。 サーバーは全データを用意する前にレスポンスを開始できる クライアントはメモリを節約しつつデータを逐次処理できる この方式は、ストリーミングや大容量データのダウンロードに適しています。 1 List Data Points のレスポンス確認 レスポンスヘッダを確認してみます。 curlコマンドで List Data Points エンドポイントを叩きます。 HTTP1.1を明示的に指定しています。 2 export API_URL = < YOUR_API_URL > export API_TOKEN = < YOUR_API_TOKEN > export PROJECT_UUID = < YOUR_PROJECT_UUID > export MEAS_UUID = < YOUR_MEAS_UUID > curl -I -X GET " ${API_URL} /api/v1/projects/ ${PROJECT_UUID} /data?name= ${MEAS_UUID} " -H " X-Intdash-Token: ${API_TOKEN} " --http1.1 レスポンスヘッダに Transfer-Encoding: chunked が含まれていることが確認できます。 List Data PointsのHTTPレスポンス 一方、他のエンドポイントでは Content-Length が使用されています。 curl -I -X GET " ${API_URL} /api/v1/projects/ ${PROJECT_UUID} /measurements/ ${MEAS_UUID} " -H " X-Intdash-Token: ${API_TOKEN} " --http1.1 List Data Points以外のHTTPレスポンス 今回紹介するサンプルプログラム 3 では、このチャンク転送エンコーディングを活用して、大容量の計測データ取得時にメモリを節約します。 やってみた インストール SDK入門③ まででインストールしたパッケージを利用します。 加えて、メモリ使用量を表示するため、システム監視ライブラリを導入します。 pip install psutil 全体構成 A環境に保存された計測データをB環境に再度アップストリームします。 全体構成図 対象計測 データ収集に労力のかかる例として長時間の計測を使います。 荷物搬送のためカーフェリー移動した北海道出張 さんふらわあ しれとこ は2025年に引退が決まっているベテラン船で、客室はすべて年季が入ったベット4つの相部屋です。 www.sunflower.co.jp 当社製 EDGEPLANT T1 でGPSデータを収集しました。 客室ベッドでT1と添い寝 茨城県大洗港〜北海道苫小牧港は約302海里 乗船〜下船の20時間26分32秒 リプレイ開始 20時間超の計測を等倍で再生するのは辛いので早送りします。 再生スピード調整機能を使って60倍速でアップストリームします。 起動すると、A環境からREST APIからの計測データ取得と、B環境へのアップストリームが始まります。 リプレイ開始 VM2M Data Visualizer のLIVE再生で位置情報が60倍速で更新されていきます。 津軽海峡冬景色 Edge Finderでリアルタイムデータを確認 再生が完了すると、ちょうど時間が1/60の計測が作成されています。 20分26秒に短縮 起動オプション 今回は、データ取得元を計測UUIDで指定して、別サーバー環境に、再生スピード指定でアップストリームしました。 他にも以下のオプションがあります。 データ取得元オプション 取得元の時間範囲として、計測、またはエッジ・開始時刻・終了時刻を指定します。 --api_url requried :サーバーURL --api_token requried : APIトークン --project_uuid :プロジェクト、省略時はGlobal Project いずれか requried 計測指定: --meas_uuid :計測 エッジ指定: --edge_uuid :エッジ --start :開始時刻、RFC3339形式 --end :終了時刻、RFC3339形式 --data_id_filter :データIDフィルター、カンマ区切りで複数指定 <データ型名>:<データ名>, <データ型名>:<データ名>, ... データ送信先オプション プロジェクト以外は、省略時はデータ取得元と同じになります。 --dst_api_url :サーバーURL --dst_api_token : APIトークン --dst_project_uuid :プロジェクト、省略時はGlobal Project --dst_edge_uuid :エッジ 再生オプション --speed :再生スピード、省略時は等倍(1.0) サンプルプログラム説明 APIアクセス部分を中心に説明します。 クラスアーキテクチャ 2つの処理を非同期で実行しています。 Feed:REST APIから受け取ったデータポイントをキューに登録します。 メモリ消費量を抑えるため、キューが一杯だったら、空くまで待機します。 Fetch:キューからデータポイントを取り出して、アップストリームします。 元の計測と同じ頻度でデータ送信するため、経過時間分スリープします。 再生スピードを指定すると スリープ時間をその分調整します。 データポイント取得 メモリ消費低減のため、 _preload_content を False にして随時読み込みます。 api = measurement_service_data_points_api.MeasurementServiceDataPointsApi( self.client ) params = { "project_uuid" : self.project_uuid, "name" : self.meas_uuid if self.meas_uuid else self.edge_uuid, "time_format" : "ns" , "_preload_content" : False , # 全データロードの抑止 } if self.start: params[ "start" ] = self.start if self.end: params[ "end" ] = self.end if self.data_id_filter: params[ "data_id_filter" ] = self.data_id_filter stream = api.list_project_data_points(**params) 時刻変換 データ送信を待機するため、取得したデータポイントの絶対時刻から経過時間を算出します。 basetime_ns = int (basetime.timestamp() * 1_000_000) * 1_000 ... elapsed_time = tuple [ 0 ] - basetime_ns 再生スピード調整 算出した経過時間分スリープします。 elapsed_time_speed = int (elapsed_time / self.speed) sleep_time = ( basetime_ns + elapsed_time_speed - iscp.DateTime.utcnow().unix_nano() ) / 1_000_000_000 if sleep_time > 0 : await asyncio.sleep(sleep_time) 送信するデータポイントの経過時間は、現在時刻と新たな計測の基準時間との差分です。 elapsed_time_replay = ( iscp.DateTime.utcnow().unix_nano() - start_time.unix_nano() ) await self.upstreamer.send(elapsed_time_replay, type , name, data) メモリ使用量表示 チャンク転送エンコーディングによりメモリ消費が抑えられることを確認するため、使用量をログ表示しています。 process = psutil.Process() mem_info = process.memory_info() logging.info(f "Memory Usage: {mem_info.rss / 1024 / 1024:.2f} MB" ) メモリ使用量ログ おおよそ55MBで推移しています。 試しに _preload_content オプションを外して(デフォルト True で)実行すると、ストリーム開始まで10秒ほどかかり、600〜700MBほど消費します。 一括取得で実行 サンプルプログラム修正 本シリーズで以前、REST APIで計測データをエクスポート/インポートするサンプルプログラムを紹介しました。 tech.aptpod.co.jp こちらは、計測データ量に依存してメモリ消費が増えてしまうため、長時間計測には不向きでした。 今回、同じように _preload_content オプションを指定して、メモリ消費量を抑えるようした修正版を追加しました。 4 エクスポート List Data Pointのオプション指定を変更しました。 api = measurement_service_data_points_api.MeasurementServiceDataPointsApi(client) params = { "project_uuid" : project_uuid, "name" : meas_uuid, "time_format" : "ns" , "_preload_content" : False , } stream = api.list_project_data_points(**params) 一定量ずつ取得した計測データをバッファに取っておいて、1行ずつ順次返すように変更しました。 # バッファ格納 buffer = b "" while True : chunk = stream.read(chunk_size) if not chunk: break buffer += chunk # JSON Line切り出し while b " \n " in buffer : line, buffer = buffer .split(b " \n " , 1 ) line_json = json.loads(line.decode()) if "data" not in line_json: continue if "d" not in line_json[ "data" ]: continue yield line_json 出力ファイルがJSONだとインデント処理が煩雑になるため、JSON Linesに変更しました。 修正前フォーマット:JSON { " measurement ": <計測オブジェクト>, " basetimes ": [ <基準時刻>, <基準時刻>, .. ] , " datapoints ": [ <データポイント>, <データポイント>, .. ] } 修正後フォーマット:JSON Lines {"measurement": <計測オブジェクト>} {"basetime": <基準時刻>} {"basetime": <基準時刻>} ... {"datapoint": <データポイント>} {"datapoint": <データポイント>} ... さきほどのGPS計測をエクスポートすると以下のようになります。 修正前は1.4GBほどメモリを消費しました。 5 python lesson2/migrate/src/meas_export.py --api_url <YOUR_API_URL> --api_token <YOUR_API_TOKEN> --project_uuid <YOUR_PROJECT_UUID> --meas_uuid <YOUR_MEAS_UUID> エクスポート修正前:一括取得版 修正後は46MBほどになりました。 python lesson2/migrate/src/meas_export_mem.py --api_url <YOUR_API_URL> --api_token <YOUR_API_TOKEN> --project_uuid <YOUR_PROJECT_UUID> --meas_uuid <YOUR_MEAS_UUID> エクスポート修正後:随時取得版 インポート あわせて、JSON Linesファイルを随時読み出すようにインポートを修正しました。 with open (file_path, "r" , encoding= "utf-8" ) as f: for line in f: try : yield json.loads(line, object_hook=measurement_decoder) except json.JSONDecodeError as e: logging.warning(f "JSON decode error: {e}" ) CHUNK_SIZE ずつ送信するよう制御しています。 buffer .append(entry[ "datapoint" ]) if len ( buffer ) >= CHUNK_SIZE: sequence_number = send_chunks( client, project_uuid, measurement_obj.uuid, measurement[ "basetime" ], sequence_uuid, buffer , sequence_number, ) buffer .clear() エクスポートしたファイルのインポート結果です。 修正前は2.5GBほどメモリを消費して途中で止まりました。 python lesson2/migrate/src/meas_import.py --api_url <YOUR_API_URL> --api_token <YOUR_API_TOKEN> --project_uuid <YOUR_PROJECT_UUID> --edge_uuid <YOUR_EDGE_UUID> --src_file <YOUR_JSON_FILE> インポート修正前:一括読み出し版 修正後は50MB未満に収まりました。 python lesson2/migrate/src/meas_import_mem.py --api_url <YOUR_API_URL> --api_token <YOUR_API_TOKEN> --project_uuid <YOUR_PROJECT_UUID> --edge_uuid <YOUR_EDGE_UUID> --src_file <YOUR_JSONL_FILE> インポート修正後:随時み出し版 おわりに 今回は開発で利用できるツールの一例を紹介しました。 実データを元に繰り返し送信したり、別環境で再現できると検証の質が向上します。 このようにREST/リアルタイムAPIを組みあわせると自由度の高い制御も可能です。 リンク 本シリーズの過去記事はこちらからご覧ください。 SDK入門①〜社用車で走ったとこ全部見せます〜 :REST APIでデータ取得 SDK入門②〜データ移行ツールの作り方〜 :REST APIでデータ送信 SDK入門③〜RTSPで映像配信するぞ〜 :リアルタイムAPIでデータ取得 SDK入門④〜YOLOで物体検知しちゃう〜 :リアルタイムAPIでデータ送信 SDK入門⑤〜iPadでData Visualizerを見る会〜 :リアルタイムAPIでキャプチャデータ送信 SDK入門⑥〜最速最高度で計測する日〜 : AWS LambdaでREST APIデータ送信 同じ"ストリーミング"と呼んでいますが、チャンク転送エンコーディングとintdashのリアルタイムAPI(iSCP)は別のプロトコルです。 ↩ HTTP2以降では Transfer-Encoding は省略されうるためです。 ↩ GitHub で公開しています。 ↩ GitHub のlesson2に反映してあります。 ↩ JSONフォーマットを一時保持するメモリ消費が大半です。 ↩
intdash SDKを使って開発したプログラムを自動で実行したいみなさん、 こんにちは、ソリューションアーキテクトの伊勢です。 これまで本シリーズではプログラムをコマンドで手動起動してきましたが、検証や運用では自動で起動したい場面が多いはずです。 今回はWebhookとLambdaを組み合わせて、計測完了直後にプログラムを起動する方法を紹介します。 はじめに 全体構成 Webhookとは AWS Lambdaとは Lambdaレイヤーとは API Gatewayとは やってみた AWS構築 距離算出Lambda カスタムLambdaレイヤー作成 Lambda関数作成 レスポンス返却Lambda Lambda関数作成 API Gateway作成 Webhook設定 設定登録 設定確認 計測 計測対象 計測開始 計測完了 サンプルプログラム説明 Webhook設定ツール 一覧 取得 登録 テスト 距離算出 距離算出プログラム レスポンス返却プログラム おわりに リンク はじめに 全体構成 SDK入門② の距離算出プログラムが計測完了直後に起動されるようにします。 距離算出 計測イベントをWebhookリクエストとしてAPI Gatewayに送信します。 Webhookリクエストを受けたAPI GatewayがLambdaを起動します。 レスポンス返却Lambdaは、リクエストが計測完了のときに距離算出Lambdaを起動します。 1 距離算出Lambdaは、プログラムの完了をSlackで通知します。 Webhookとは システム内イベントをシステム外にHTTPで通知する仕組みです。 これでintdash内の変化をintdash外からリアルタイムに知ることができます。 イベントドリブンなシステム連携により、効率的なワークフローを実現できます。 tech.aptpod.co.jp 今回はよりシンプルな使い方を紹介します。 Lambda関数をインラインコードで作成 intdash SDKのLambdaレイヤーを作成 ローカルPCでテストコードによる動作確認 2 AWS Lambdaとは 言わずと知れたサーバレスでコードを実行できるコンピューティングサービスです。 aws.amazon.com 従量課金で手軽であり、作成した関数をイベントで起動できます。 今回はWebhookリクエストをAPI Gatewayで受けてLambdaを起動します。 Lambdaレイヤーとは Lambda関数の実行環境に共有ライブラリや依存ファイルを追加する仕組みです。 これにより、Lambda関数が軽量化され、コードの再利用性が向上します。 今回はintdash SDKや依存するPythonパッケージを登録します。 docs.aws.amazon.com API Gatewayとは APIエンドポイントへのアクセス仲介サービスです。 WebリクエストをバックエンドのLambdaやEC2などにルーティングします。 やってみた AWS構築 起動される側(全体構成の右側)から順に構築していきます。 距離算出Lambda カスタムLambdaレイヤー作成 Lambdaレイヤーとして登録するためのZIPファイルを作成します。 ローカルPCでLambdaレイヤーのディレクトリ構造に SDK入門① 、 SDK入門② のPython依存パッケージをインストールします。 3 mkdir -p path/to/workdir/python/lib/python3. 12 /site-packages pip3. 12 install pydantic python-dateutil urllib3 -t path/to/workdir/python/lib/python3. 12 /site-packages pip3. 12 install protobuf -t path/to/workdir/python/lib/python3. 12 /site-packages 依存パッケージインストール 以下をZIPにまとめます。 SDK入門① で生成したintdash SDKパッケージ intdash SDK入門② で生成したProtocol Buffersエンコーダー gen インストールしたPython依存パッケージ cp -r intdash gen path/to/workdir/python/lib/python3. 12 /site-packages cd path/to/workdir find . -name " *.pyc " -delete find . -name " __pycache__ " -type d -exec rm -r {} + zip -r intdash_sdk.zip python ls -l intdash_sdk.zip python LambdaレイヤーZIP作成 ZIPファイルをアップロードしてレイヤーを作成します。 Lambdaレイヤーの作成 Lambda関数作成 サンプルプログラムからLambda関数のZIPファイルを作成します。 今回のサンプルプログラムはLambdaで実行されることを想定しています。 4 cd lesson6/intdash-distance/src find . -name " *.pyc " -delete find . -name " __pycache__ " -type d -exec rm -r {} + zip -r ../deployment_package.zip . 距離算出Lambda ZIPファイル作成 Lambda関数を作成します。 作成したZIPファイルをアップロードします。 距離算出Lambda関数作成 タイムアウト設定がデフォルト3秒だと途中終了してしまうため、5分に延長します。 距離算出Lambda タイムアウト設定 プログラムに渡す環境変数を設定します。 API_TOKEN : サーバー環境にアクセスするAPIトークン API_URL : サーバー環境のURL FETCH_SIZE : データポイントを何件ずつ処理するか ORIGIN_LAT : 基準点(緯度) ORIGIN_LON : 基準点(経度) SLACK_URL : 通知先Slack 距離算出Lambda 環境変数設定 Lambdaレイヤーを追加します。 intdash SDK: 作成したカスタムLambdaレイヤー requests : 公開ARNを指定 Lambdaレイヤーの追加 レスポンス返却Lambda Lambda関数作成 intdashにレスポンスを返却するためのLambda関数を作成します。 lesson6/invoke-distance/src/lambda_function.py の内容を貼り付けます。 レスポンス返却Lambda作成 プログラムに渡す環境変数を設定します。 SECRET_KEY : あとでWebhook設定に登録する任意の文字列 レスポンス返却Lambda 環境変数設定 API Gateway作成 POSTリクエストを受けるAPI Gatewayを作成します。 レスポンス返却Lambdaと統合します。 API Gateway作成 Webhook設定 設定はintdash APIで管理され、SDKでも参照・更新メソッドが提供されます。 ラップするCLIツールも作ってみました。 このツールを使って今回使う設定を登録・確認します。 5 Webhook設定ツール 設定登録 API GatewayにWebhookリクストを送信する設定を追加します。 リクエストボディはこのようなJSONです。 6 { " url ": " https://example.execute-api.ap-northeast-1.amazonaws.com/webhook ", " secret ": " stringstringstringstringstringst ", " edges_event ": false , " measurements_event ": true , " users_event ": false , " edge_connections_event ": false , " project_edges_event ": false , " project_members_event ": false } secret にはレスポンス返却Lambdaの環境変数 SECRET_KEY を設定します。 7 計測イベントを送信するように measurements_event のみ true にします。 8 JSONファイルを src_path に指定します。 python lesson6/cli/src/hook_cli.py --api_url https://example.intdash.jp --api_token < YOUR_API_TOKEN > --project_uuid < YOUR_PROJECT_UUID > import --src_path =< YOUR_SRC_PATH > 設定確認 登録結果を一覧で確認します。 python lesson6/cli/src/hook_cli.py --api_url https://example.intdash.jp --api_token < YOUR_API_TOKEN > --project_uuid < YOUR_PROJECT_UUID > list Webhook設定登録 計測 計測対象 せっかくなので、その場でプログラムを手動実行できない環境で試しました。 iOSアプリ intdash Motion で飛行中のGPSを計測します。 福岡出張の帰路 エアバスA320 の最大巡航速度はマッハ0.82、国内線の高度はおよそ1万mです。 当社がこれまで計測した環境としては最速かつ最高度ではないかと思います。 1回の計測距離として最長かもしれません。 計測開始 iPhoneはフライトモードにしてあるため、計測がオフラインで開始されます。 オフライン計測を開始 機内Wifiが使える機体なら、リアルタイム計測も可能かもしれません。 離陸 計測完了 着陸後、Motionから計測を遅延アップロードします。 遅延アップロード 数十秒ほどでSlackに通知がありました。 Slack通知 PCからData Visualizerにリンクするとプレイバック再生が始まります。 成田空港を基準点とした算出距離が計測とあわせて表示されます。 9 最高時速1,126km、最高高度9,597m、移動距離575km サンプルプログラム説明 Webhook設定ツール 一覧 List Project Hookの結果の items 配列を返します。 return self.api.list_project_webhooks( self.project_uuid, per_page=per_page ).items 取得 List Project Hookで hook_uuid を指定しています。 10 hooks = self.api.list_project_webhooks( self.project_uuid, hook_uuid=[hook_uuid], ) return hooks.items[ 0 ] 登録 引数 hook_uuid の指定有無でCreate/Update Project Hookを使い分けます。 if hook_uuid: hook = self.api.update_project_webhook( self.project_uuid, hook_uuid, hook_project_update_request=hook_src ) else : hook = self.api.create_project_webhook( self.project_uuid, hook_project_create_request=hook_src ) テスト 指定した resource_type 、 action をHookリクエストとして送信します。 11 return self.api.test_project_webhook( self.project_uuid, hook_uuid, hook_test_request={ "resource_type" : resource_type, "action" : action}, ) 距離算出 距離算出プログラム APIアクセス部は SDK入門② と同じです。 Lambdaにあわせてメイン関数を lambda_hander に変更してあります。 定数は環境変数としてLambda設定から与えられるようにしてあります。 api_url = os.getenv( "API_URL" , "https://example.intdash.jp" ) api_token = os.getenv( "API_TOKEN" , "<YOUR_API_TOKEN>" ) fetch_size = int (os.getenv( "FETCH_SIZE" , 100 )) origin_lat = float (os.getenv( "ORIGIN_LAT" , 35.6878973 )) origin_lon = float (os.getenv( "ORIGIN_LON" , 139.7170926 )) origin = (origin_lat, origin_lon) # 会社 slack_url = os.getenv( "SLACK_URL" , "<YOUR_SLACK_WEBHOOK_URL>" ) テストコードから環境変数を与えて起動しています。 12 os.environ[ "API_URL" ] = "https://example.intdash.jp" os.environ[ "API_TOKEN" ] = "<YOUR_API_TOKEN>" os.environ[ "FETCH_SIZE" ] = "100" os.environ[ "ORIGIN_LAT" ] = "35.6878973" os.environ[ "ORIGIN_LON" ] = "139.7170926" os.environ[ "SLACK_URL" ] = "<YOUR_SLACK_WEBHOOK_URL>" なお、距離算出Lambaが計測を完了するときにもWebhookリクエストが送信されます。これにより、距離算出Lambdaがもう一度起動されるため、無限ループの防止が必要です。 位置情報を含むデータポイントだけを取得します。 stream = api.list_project_data_points( project_uuid=self.project_uuid, name=self.meas_uuid, data_id_filter=[ "#:1/gnss_coordinates" ], start=self.start, limit=fetch_size, time_format= "ns" , ) データポイントが0件の場合は作成した計測を削除します。 # 計測削除(GPSデータなし) if not count: self.writer.delete_measurement() logging.info(f "Deleted measurement: {measurement_dst.uuid}" ) return レスポンス返却プログラム intdash APIとは直接関わりません。 距離算出Lambdaを起動します。 response = lambda_client.invoke( FunctionName= "intdash-distance" , InvocationType= "Event" , Payload=json.dumps(body_dict), ) 起動は0.1秒程度で終わり、すぐにレスポンスを返却します。 return { "statusCode" : 200 , "body" : json.dumps({ "message" : "Webhook received and Distance Lambda invoked" }), } おわりに 今回は起動方法を実際の利用シーンに近づけてみました。 intdash SDKのLambdaレイヤーに登録しておけば、複数のLambda関数に適用できて便利です。 なお、Lambdaは最大実行時間が15分のため、もっと長い処理はFargateやEC2インスタンスを利用することになります。 リンク 本シリーズの過去記事はこちらからご覧ください。 SDK入門①〜社用車で走ったとこ全部見せます〜 :REST APIでデータ取得 SDK入門②〜データ移行ツールの作り方〜 :REST APIでデータ送信 SDK入門③〜RTSPで映像配信するぞ〜 :リアルタイムAPIでデータ取得 SDK入門④〜YOLOで物体検知しちゃう〜 :リアルタイムAPIでデータ送信 SDK入門⑤〜iPadでData Visualizerを見る会〜 :リアルタイムAPIでキャプチャデータ送信 10秒以内にレスポンスを返すため、Lambdaを二段構成にしています。intdashはWebhookリクエストのステータスを管理しており、10秒以内に通知先からレスポンスが返るとステータスを成功 succeeded に移行します。 ↩ テストコードは GitHub で公開しています。 ↩ 前回 までにインストールしたパッケージをすべてZIP化すると、Lambdaレイヤーの上限10MBを超えてしまうためです。 ↩ サンプルプログラムは GitHub で公開しています。 ↩ CLIの使い方は GitHub で解説します。 ↩ サンプルプログラム内にテンプレート lesson6/cli/config/hook.json を用意しています。 ↩ HMAC検証 でWebhookリクエストの改ざんを防止します。 ↩ 間違えやすいですが、各項目名は xxx_events ではなく xxx_event です。 ↩ 計測は1時間ほどで終了しています。Motionログイン時にサーバーで払い出すアクセストークンの有効期限によるものです。 ↩ 設定を1件取得する get_project_webhook は現行バージョンでは動作しません。次バージョンにて改修予定です。 ↩ SDK入門① で紹介しているintdash SDK for Python生成の手順では created / updated / deleted 以外の action がエラーになるようです。その場合は、curlコマンドで直接Test Hook APIを叩いて確認します。 ↩ テストコードの使い方は GitHub で解説します。 ↩
aptpod Advent Calendar 2024 12月25日(最終日)の記事です。 CTOの梶田です。 いつもの通り、今年もまたまたあっという間(いつも言ってますね💦)でAdvent Calendar もなんとか走りきれそうです。(今年は7年目にもなりました!) はじめに デジタルツインソリューションでの進展・協業 自動車業界のSDV化と新たな挑戦 2025年に向けて はじめに 2024年、アプトポッドは多岐にわたる取り組みを通じて、タイトルの通り、新たなつながりと共創を推進してきました。 ここ1年、迫る 2025年問題 (労働人口の減少や熟練者の引退による人手不足、技能伝承の難しさ)や、IT業界で言われる 2025年の崖 など、さまざまな課題が浮き彫りになっています。このような背景の中、多くの企業がDX(デジタルトランスフォーメーション)の推進に迫られている状況が感じられる一年でもありました。 こうした時代の変化の中で、アプトポッドの取り組みも進化を続けています。主力である自動車開発向けのソリューション展開に加え、他分野への活用も着実に広がりを見せています。たとえば、 intdash をミドルウェアとして基盤活用いただく事例や、ソリューション連携の事例が増加し、多岐にわたる分野での貢献が進みました。 <2024年初頭のリリース> www.aptpod.co.jp 今回は、こうした進展や取り組みを中心に、この一年を振り返っていきたいと思います! また、今回の AdventCalendar 2024 でも活用事例について以下でいくつか触れられておりますので是非ご覧ください。 11日目: Unity x ROS をこれから始める方へ、開発Tips書いてみた 13日目: intdashの計測データ分析ボードを作成してみた 17日目: EPS32でリアルタイム映像アップストリーム 20日目: SDK入門⑤〜iPadでData Visualizerを見る会〜 デジタルツインソリューションでの進展・協業 昨年(2023年)の振り返りでも触れた日立建機様との取り組みでは、さらなる進展がありました。 アプトポッド、日立建機と第三者割当増資による資本業務提携を実施 この協業の一環として、建設施工リアルタイムデジタルツイン基盤を開発し、第6回建設・測量生産性向上展「CSPI-EXPO」(2024年5月22日~24日)の日立建機ブースにて展示を行いました。 www.aptpod.co.jp この基盤は、建設施工における「人・機械・現場環境」をデジタルツインで統合・管理する技術であり、リアルタイムデータを活用して仮想空間上で現実世界を再現します。これにより、遠隔地からでも建設プロジェクトの進捗状況や安全性を詳細に監視・管理することが可能となります。さらに、少人数での現場運営を実現し、作業効率の大幅な向上が期待されています。 また、新たな取り組みとして、株式会社Liberaware様との協業により、建設施工管理や設備メンテナンス向けのデジタルツインソリューションを発表しました。 www.aptpod.co.jp このソリューションは、 360°動画ストリーミングから3Dデータを自動生成する技術 を活用しており、建設業界における人手不足の解消に向けたロボット化や自動化の推進に貢献します。業界全体が抱える課題解決に向けた重要な一歩と言えるでしょう。 <デモンストレーション動画> www.youtube.com (おまけ)関連情報 デジタルツインに関連する製品の新機能については、以下の技術ブログでも紹介しています。 tech.aptpod.co.jp さらに 「デジタルツイン」 というキーワードは業界内でも注目を集めており、メンテナンス系のイベントでは新たなつながりや協業のきっかけが生まれました。 tech.aptpod.co.jp 自動車業界のSDV化と新たな挑戦 自動車業界では、車両の機能をソフトウェアで定義・制御する SDV(Software-Defined Vehicle) が急速に進展しています。 ハードウェア中心の設計から脱却し、ソフトウェアを中核とした車両開発へのシフトが求められる中、アプトポッドは2024年に以下の取り組みを発表しました。この取り組みを通じ、SDV時代の加速に貢献していきたいと考えています。 <自動車ソリューションパッケージの最新バージョン> www.aptpod.co.jp この発表に記載された「MDF4形式でのデータダウンロード(予定)」については、Advent Calendarの記事でも取り上げています。ぜひご覧ください。 tech.aptpod.co.jp SDV化が進む中、アプトポッドのプラットフォーム intdashは、車両から取得される大量のデータをリアルタイムで収集・解析する機能を提供します。これにより、ドライビングデータやセンサーデータを活用した高速なソフトウェア開発・テストが可能になり、車両開発プロセスの効率化を実現します。 さらに、2024年7月には、株式会社共和電業様と共同で、自動車開発における試験プロセスの遠隔化やデジタルツイン対応を実現するクラウド計測ソリューションを発表しました。これは、SDV時代のニーズに応える重要なステップと位置づけられます。 www.aptpod.co.jp SDVでは、車両機能がソフトウェアによって定義され、開発プロセスは従来のハードウェア主体から、ソフトウェア中心のアプローチへと移行しています。これに伴い、車両開発においても、より柔軟で効率的なデータ活用が求められています。 共和電業様との協業によるソリューションは、クラウドを活用して同社の高品質なセンサーおよびデータロガーを用い、高精度なデータ収集とモデルベース開発環境を実現します。これにより、SDV時代にふさわしい新たな価値を創出し、自動車開発の未来を切り拓く基盤として貢献していきたいと考えています。 2025年に向けて 2024年は、これまで培ってきた基盤をさらに発展させ、新たなパートナーシップや技術革新を通じて、共創の輪を広げる一年となりました。 建設業界、自動車業界、そしてその他の分野におけるDXやデジタルツインの取り組みを推進し、多くの新しいつながりを生み出すことができました。 もちろん、これまで同様に課題もありましたが、その一つひとつに向き合い、チーム全体で成長を続けることができました。振り返ると、人数も少ない中、多くの成果が形になりつつあり、まだお伝えしきれていない事例も含め、まだまだたくさんの可能性を感じています。 改めて、一緒に挑戦を支えてくださったパートナー様、お客様、そしてチームメンバーに心から感謝しています。(今年もお疲れ様でした!) 2025年は、さらに重要な節目の年になると確信しています。 「2025年問題」や「SDVの進展」など、業界が大きな変革を迎える中で、私たちアプトポッドは引き続き、技術で未来を切り拓き、社会課題の解決に貢献していきたいと思います。お客様やパートナー様との共創をさらに深め、新しい価値を生み出す挑戦を続けていきます。 来年も、アプトポッドにどうぞご期待ください! メリークリスマス!🎄 それでは皆様、良いお年をお迎えください!