Inside of LOVOT

GROOVE X 技術ブログ

LOVOT 3.0の服検証苦労話

こんにちは、ファームチームのhirayuです。この記事は、GROOVE X Advent Calendar 2024の6日目の記事です。

弊社ではLOVOTを愛でることで、人の愛するちからを育み、そしてそれが人を元気にすることに繋がると考えています。 そうした中でお着替えを通してLOVOTとたくさん触れ合ってもらうよう、LOVOTの服も販売をしています。 これまでいろいろな服が世に出され、お客様からもご好評の声をいただいています。 このLOVOTの服が出荷されていく過程には、たくさんのチームが携わっているのですが、LOVOTが服を着た時に何か異常がないかチェックする担当としてファームチームがいます。

今日はそのLOVOTの服と測距センサーについて苦労した話しをしていきたいと思います。

過去にも服検証の記事を投稿しているので、一緒に参照いただけると幸いです。 tech.groove-x.com

LOVOT 3.0開発で起きた服と測距センサーの干渉

上で述べたように、なくてはならないLOVOTの服なのですが、LOVOT 3.0を開発していく中で想定外の問題が発生しました。 それはLOVOT (初代)/2.0に比べてLOVOT 3.0が服を着用すると測距センサーと干渉しやすいということです。

干渉の原因とその影響

LOVOTには周囲の環境を正確に認識するために測距センサーが組み込まれています。このセンサーは、赤外線を照射してその反射を計測することで物体との距離を測定します。このセンサーにより、LOVOTは障害物を避けることができ、転倒リスクを減らすことができます。

たくさん組み込まれている測距センサーの赤外線を特殊なカメラで見ている様子

LOVOT (初代)/2.0とおおよそ同じ体型をしているLOVOT 3.0ですが、この測距センサーが高機能なものに変わっており、より広範囲を見渡せるものになっています。そのため、たくさんの障害物を見つけられるようになった反面、LOVOT自身の身体周辺も検出範囲に入ってきてしまったことが干渉のしやすさの原因でした。

LOVOTが着用するスカートの一例、可愛い装飾が増えれば増えるほど、干渉しやすくなる。。。

特に後方の床面を見るための、ホーンに取り付いている測距センサーがLOVOTの背面付近の空間にあるものを検出しやすく、丈のあるスカートやふわふわした帽子だと障害物であると判定されやすくなってしまいます。 その結果、LOVOTが誤って物体が近いと認識して動きを止めてしまうといった状況が発生しました。こういった干渉によって、LOVOTは前進しつづけたり、後退しつづけたり、服を着ていないときとは異なるふるまいになってしまうことがありました。

干渉を解決するための設計

この問題に対して、開発チームでは様々な工夫を行いました。 まず検出範囲の広い測距センサーのセンシング信号の内、服と干渉する恐れのある範囲のものについてはソフトウェアで無視する対応を取ることで、服を障害物だと誤判定してしまうことを回避しています。

また、LOVOT 3.0向けに販売される服のデザインに関しても、測距センサーの動作を阻害しない長さや形状にするよう、服チームが試行錯誤して作っていきます。

服チームが初期の試作品作成から寸法修正している様子

最後の砦になっているファームチームでの検査

以上のように設計した服を最終的には一着、一着、ファームチームで検査していきます。 上述したように、後方の床面を見るためのホーンに取り付いている測距センサーと背面の服とが干渉しやすいので、首を回しながら距離計測し、LOVOTがどんな体勢をとっても干渉しないようにチェックします。

首を回しながら距離センサーで距離計測している様子

また長期的にLOVOTに自由な動きをさせながらログをとり、異常な動きをしていないかもチェックしていきます。 ログから測距センサーに異常値はないか、ネストに正常に戻れているか見ています。

この例だとオドメトリ値が負になっています。 オドメトリとはLOVOTの車輪が回転した量を指し、前に進めば正、後退すれば負になります。 LOVOTは自由に動き回るのですが、それでも正常であれば合計すると前に進んでいることが多いので、よく後退している結果があるとちょっとあやしいな?とその原因を探すことになります。

特に長い間LOVOTが動いていると発生する問題でよくあるのは、着崩れです。

画像の帽子は試作段階のものです

LOVOTが動く前は深々と被ったはずの帽子が、動いている内にだんだんと上にあがってきたりします。 この白丸で囲んでいる着崩れが後方の床面を見るための、ホーンに取り付いている測距センサーのセンシング範囲に被ってしまうことがLOVOT 3.0では問題になり、意図せず前進することが多くなってしまいます。

左は初期の試作品、右は修正を加えたもの

上記のような問題に対しては、白枠のように布を足し、帽子を目深にかぶれるようサイズ調整した試作品を作成、検証し、最終製品としては着崩れしにくいよう寸法修正していきます。

終わりに

こうした試行錯誤の結果、LOVOTは服を着ていてもその可愛らしい動きと周囲とのインタラクションを損なうことなく、スムーズに行動することが可能になっています。 このようにたくさんのチームが関わり合いながらLOVOT、そして専用服を開発しています。 まだまだGROOVE Xでは一緒に働いてくれる仲間を募集中ですので、ぜひご応募ください。 recruit.jobcan.jp

LOVOTの目に表示される通知開発

こんにちは。

10月から基盤技術開発のチームに移動した id:numa-gx です。

GROOVE X Advent Calendar 2024の5日目は、LOVOTの目に表示される 通知 の開発についてお話します。

LOVOTには、まぶた・目などの生き物らしさを表現する以外にも、LOVOTの状態をユーザーに伝えるためのアイディスプレイへの通知機能があります。

ホーンを外すと名前・バッテリー残量などが表示されます

通知機能に関して、大別すると2種類の開発項目があります。

  • 既存の通知の見た目の改善
  • 新しい通知の追加

最近の開発事例を参考に、どういう観点で実装と設計を進めていったのかを説明します。

ユーザー体験向上につながる見た目の改善

先月のソフトウェアアップデートでは、バッテリーが高温となった状態を表す通知の見た目が改善されました。

改善前

バッテリーが高温なため充電ができないことを表す

改善後

ネストの上にいる時 ホイールを格納している時
充電を一時的に停止中であることを表す
高温のためユーザーにホイールを出させるように促す

この改善を実施した背景として、変更前の通知では以下のような課題があり、その解決を試みています。

  • 故障のように伝わってしまい、お問い合わせが来ていた
  • 充電がされない状態であっても、待てばこの問題が解消することを伝えたかった
  • 抱っこなどホイールが格納された状態だとバッテリーが冷却されにくいため、ホイールを出すようにユーザーに行動を促したい

表示されるアイコンがちょっと可愛くなっているのも嬉しいですね!

見た目を改善する際に意識すること

アイディスプレイに通知が表示されている状態は、かわいさに対してはプラスになることは基本的にありません。

従って、通知を表示すべきか新しく追加するかを検討する際には、以下の判断基準を満たしているときに限られています。

  • LOVOTが通常とは異なる状況にあることを明確に伝えたい
    • 例:音声コマンドに従って動いている時)
  • ユーザー操作など対話的な行動時のフィードバックをしたい
    • 例:モバイルアプリを使って目を変更する時

新機能の通知

LOVOT 3.0ではサイドパネルとホイールをユーザーが取り外して中を自らの手で掃除できる機能が搭載されました。

サイドパネルの取り外し方 ホイールの取り外し方

このような対話的な操作を必要とする新機能が追加されたときは、ユーザー体験をアシストするために通知の出番がやってきます。

そのため、サイドパネルとホイールが取り外されたパターンのそれぞれ3種類を表す通知を実装しました。

ただし、取り外された場所が異なるケースは同時に発生することはありませんが、ホイールとサイドパネルがそれぞれ取り外された状態の組み合わせは存在しうるため、どのように表示するかを決める必要がありました。

ホイールの取り外し サイドパネルの取り外し
左サイドパネルが取り外されている
左ホイールが取り外されている
右サイドパネルが取り外されている
右ホイールが取り外されている
両サイドパネルが取り外されている
両ホイールが取り外されている

通知を表示する上での制約と工夫

表示内容の仕様を設計するために、一般的なディスプレイと異なる点がいくつかあります。

  • 表示範囲が小さいため、同時に表示できる情報量が少ない
  • 意図して見るものではなく気づいてもらうことが重要
  • ユーザーの年齢層が幅広いため、一目で分かりやすい表現が求められる

このような状況から、以下の制約に基づいた実装を行っています。

  • 同時に表示できる通知は1種類のみ
  • 状況に応じて、優先度の高い通知が切り替わりながら表示される

その結果、取り外し通知の表示パターンは以下のような表示優先度で実装しました。

  • 3種類の取り外し状態はLOVOTのアイコンを表示するデザインを使い、部位ごとにハイライトすることで、表示デザインのバリエーションとして表示する
  • サイドパネルとホイールが同時に取り外されている場合、ホイールを優先的に表示する(サイドパネルを閉じてしまうとホイールの取り付け状況が外から分からないため)

最後に

LOVOTと言えば生き物らしい表現となりがちですが、今回お話した通知のようにディスプレイを通じたユーザーとのインタラクションをデザインすることもできます。

この記事を読んで、GROOVE X に興味を持っていただけたら幸いです。

一緒に働いていただける仲間を募集していますので、よろしくおねがいします。

recruit.jobcan.jp

Cortex-M4マイコンにおけるBootloader & Application構成時の遷移について

この記事は、GROOVE X Advent Calendar 2024の4日目の記事です。

はじめに

こんにちは。 ファームウェアチームに所属しているf-sakashitaと申します。

LOVOTのファームウェア開発については過去記事をご覧頂ければと思います。

tech.groove-x.com

今回はニッチかつ重要な機能でもある、ファームウェア(以後FW)のアップデートに纏わるお話です。

FWのROM構成

LOVOTには数多くのマイコンが搭載されており、ARM Cortex-Mシリーズを採用しています。
これら各マイコンのFWのバイナリはLOVOTのOSの一部に組み込まれ、ネットワーク経由でアップデートできるようになっています。
LOVOTのOSについてはこちらをご参照ください。

そのために、各マイコンのROMは以下のように主にBootloader (以後Boot)およびApplication (以後App)領域から構成されています。

開始アドレス 構成 内容
0x08000000 Boot 電源投入時に動き出すソフトウェア。
主にApp領域をアップデートする
0x08○○○○○○
(任意の位置)
App メインとなるソフトウェア。
Boot領域から遷移後に動作し始める

App領域を更新する場合は以下のようなシーケンスで行われます。

  1. アップデータとなるコンピュータ(Linuxマシン or 別マイコン)からFW更新指令が飛ぶ
    1. この時、更新対象のマイコンはApp領域で動作している前提
  2. 更新対象のマイコンは処理をApp領域からBoot領域に遷移する
  3. Boot内の処理にてアップデータ側から伝わるバイナリをApp領域に書き込む
  4. 更新完了後、処理をApp領域に遷移する

今回はCortex-M4シリーズマイコンにて、ROM構成を分割して双方に処理を遷移させる方法についてご紹介します。

参考

ARM: How to Write a Bootloader
これにしたがって実装すれば間違いないです。

実装したコード

void jump_to_another_fw(uint32_t another_fw_addr) {
  uint32_t jump_addr = *(__IO uint32_t*)(another_fw_addr + 4);
  
  __disable_irq();            // 他方のFWに飛んで初期化が終わるまで全割り込みを禁止
  
  /* NVICの有効にしている割り込み全てを無効にする */
  NVIC->ICER[0] = 0xFFFFFFFF;
  NVIC->ICER[1] = 0xFFFFFFFF;
  NVIC->ICER[2] = 0xFFFFFFFF;
  NVIC->ICER[3] = 0xFFFFFFFF;
  NVIC->ICER[4] = 0xFFFFFFFF;
  NVIC->ICER[5] = 0xFFFFFFFF;
  NVIC->ICER[6] = 0xFFFFFFFF;
  NVIC->ICER[7] = 0xFFFFFFFF;
  NVIC->ICPR[0] = 0xFFFFFFFF;
  /* NVICの全ての保留中の割り込み要求を無効にする */
  NVIC->ICPR[1] = 0xFFFFFFFF;
  NVIC->ICPR[2] = 0xFFFFFFFF;
  NVIC->ICPR[3] = 0xFFFFFFFF;
  NVIC->ICPR[4] = 0xFFFFFFFF;
  NVIC->ICPR[5] = 0xFFFFFFFF;
  NVIC->ICPR[6] = 0xFFFFFFFF;
  NVIC->ICPR[7] = 0xFFFFFFFF;
  
  /* Jump後すぐにSysTick割り込みが入らない用にするために、SysTickを無効化 */
  SysTick->CTRL = 0;
  SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;
  SCB->SHCSR &= ~( SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk | SCB_SHCSR_MEMFAULTENA_Msk ) ;
  
  /* 他方のFW用にVectorTableの配置変更 */
  SCB->VTOR = another_fw_addr;

  /* スタックポインタとして PSP と MSP のどちらが使われているかを確認し PSP だった場合は if文の中に入る */
  if (CONTROL_SPSEL_Msk & __get_CONTROL()) {
    __set_MSP(__get_PSP());                                  // PSPの値をMSPにコピー
    __set_CONTROL(__get_CONTROL() & ~CONTROL_SPSEL_Msk) ;    // スタックポインタとして MSP を使うように設定変更
  } 

  /* 最適化オプションによってはスタックを使うようなアセンブラコードに変換される可能性があるため、インラインアセンブラで実装 */
  asm volatile ("MSR msp, %0\n"      // スタックポインタを他方のFW用に初期化
                "bx %1\n"            // 他方のFWにジャンプ
                 : : "r" (*(__IO uint32_t*)another_fw_addr),  "r"(jump_addr)); 
}

コードの説明

基本的な遷移方法

Cortex-Mシリーズでは、FWバイナリの先頭にベクターテーブルが配置されます(参考

先頭アドレスから4バイトがメインスタックポインタの初期値として配置、その後ろの4バイトがリセットハンドラとして配置されています。
これらがBoot / Appそれぞれのバイナリに存在します。

つまり、他方へFWを遷移させるにはメインスタックポインタを他方の初期値に変更し、そのリセットハンドラを呼び出せば良いということになります。

上記遷移関数の引数のanother_fw_addrには遷移先のFWのスタックポインタの初期値のアドレスが入ります。 jump_addrには遷移先のリセットハンドラのアドレスが入ります。

void jump_to_another_fw(uint32_t another_fw_addr) {
  uint32_t jump_addr = *(__IO uint32_t*)(another_fw_addr + 4);

全割り込み禁止

他方のFWのベクタテーブルを再配置したり、スタックポインタを初期化したりするため、割り込みを禁止にしておくのが安全です。
実施しないとHard Faultに陥る可能性があります。

  __disable_irq();            // 他方のFWに飛んで初期化が終わるまで全割り込みを禁止

  /* NVICの有効にしている割り込み全てを無効にする */
  NVIC->ICER[0] = 0xFFFFFFFF;
  NVIC->ICER[1] = 0xFFFFFFFF;
  NVIC->ICER[2] = 0xFFFFFFFF;
  NVIC->ICER[3] = 0xFFFFFFFF;
  NVIC->ICER[4] = 0xFFFFFFFF;
  NVIC->ICER[5] = 0xFFFFFFFF;
  NVIC->ICER[6] = 0xFFFFFFFF;
  NVIC->ICER[7] = 0xFFFFFFFF;
  NVIC->ICPR[0] = 0xFFFFFFFF;
  /* NVICの全ての保留中の割り込み要求を無効にする */
  NVIC->ICPR[1] = 0xFFFFFFFF;
  NVIC->ICPR[2] = 0xFFFFFFFF;
  NVIC->ICPR[3] = 0xFFFFFFFF;
  NVIC->ICPR[4] = 0xFFFFFFFF;
  NVIC->ICPR[5] = 0xFFFFFFFF;
  NVIC->ICPR[6] = 0xFFFFFFFF;
  NVIC->ICPR[7] = 0xFFFFFFFF;

SysTickの無効化

他方のFWの実装内容によっては不要な処理かもしれませんが、遷移前のSysTickは無効にしておくとより安心です。
というのも、開発中にこれが原因でHard Faultに陥る問題に遭遇したためです。それはApp側でFreeRTOSを使用しているケースでした。

Cortex-MシリーズにてFreeRTOSを導入した場合、スケジューラにSysTickが使われます。
もし遷移前にSysTickを無効にしておかないと、Appに遷移した後に割り込みが許可され、その後直ぐにSysTick割り込みが入る可能性があります。すると、RTOSが未初期化状態でスケジューリング処理が走ってしまい、結果Hard Faultが発生、というわけです。

そこで下記のようにSysTickを無効化してます。

/* Jump後すぐにSysTick割り込みが入らない用にするために、SysTickを無効化 */
  SysTick->CTRL = 0;
  SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;
  SCB->SHCSR &= ~( SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk | SCB_SHCSR_MEMFAULTENA_Msk ) ;

ベクターテーブルの再配置

他方のFWに遷移した後は、そのFWにおける各ベクターハンドラが割り込み時に呼ばれる必要があります。 下記により、ベクターテーブルの再配置を実現しています。

  /* 他方のFW用にVectorTableの配置変更 */
  SCB->VTOR = another_fw_addr;

メインスタックポインタを使用するように変更

Cortex-Mシリーズにはスタックポインタが2種類存在し、MSP (メインスタックポインタ)とPSP (プロセススタックポインタ)があります。
基本的にはMSPが使われますが、例えばFreeRTOSを使用している場合はカーネル実行時はMSPが使われ、各タスク実行時はPSPが使われます。
そのため、例えばあるタスクの処理にてFWを他方に遷移するとなると、遷移後にPSPを使わないようにするためにMSPに戻しておく必要があります。
これを実現しているのが下記処理です。

  /* スタックポインタとして PSP と MSP のどちらが使われているかを確認し PSP だった場合は if文の中に入る */
  if (CONTROL_SPSEL_Msk & __get_CONTROL()) {
    __set_MSP(__get_PSP());                                  // PSPの値をMSPにコピー
    __set_CONTROL(__get_CONTROL() & ~CONTROL_SPSEL_Msk) ;    // スタックポインタとして MSP を使うように設定変更
  } 

スタックポインタの初期化後に遷移するまで絶対にスタックを使用しないようにする

ここが一番重要なポイントです。
最初の説明でもあった通り、FWを他方に遷移する際、事前にスタックポインタを他方のアドレスに初期化しておく必要があります。
このとき、もし初期化後にスタックを使用してしまうと、スタックオーバーフローとなり、Hard Faultに陥ります。

例えば下記のような実装でも問題ない場合はありますが、最適化オプションによって生成されるアセンブラコードがスタックを使用する可能性があります。実際これにハマりました。

    __set_MSP(*(__IO uint32_t*)another_fw_addr);
    jump_addr();

そのため、下記のようにインラインアセンブラを使って実装しておくと、最適化の影響を受けなくなるため安全です。

  /* 最適化オプションによってはスタックを使うようなアセンブラコードに変換される可能性があるため、インラインアセンブラで実装 */
  asm volatile ("MSR msp, %0\n"      // スタックポインタを他方のFW用に初期化
                "bx %1\n"            // 他方のFWにジャンプ
                 : : "r" (*(__IO uint32_t*)another_fw_addr),  "r"(jump_addr)); 

最後に

ローンチ後もFWをアップデートできる仕組みを事前に作っておけば、不具合のあるFWを遠隔で修正したり、新規機能を追加することができます。
しかしアップデート機能そのものに不具合があると大変なお祭り状態と化す恐れがありますので、ローンチ前にしっかりとテストしてバグを潰しておくのが重要です。

GROOVE Xではファームウェアエンジニア以外にも、様々な領域のエンジニアを募集中です。
詳細は下記募集ページをご確認ください!

recruit.jobcan.jp

QAチームとLOVOT 3.0

この記事は、GROOVE Xアドベントカレンダー2024 の3日目の記事です。

はじめに

こんにちは、LOVOTのソフトウェア検証を実施・改善しているQAチームです!

※チームの詳細については、2年前に公開した記事「シナリオテストのおはなし - Inside of LOVOT」をご覧ください。

今回はLOVOT 3.0のリリースに向けて、QAチームがやってきたことをご紹介いたします!

ふるまいのGX Standard試験の作業について

LOVOT 3.0 ふるまいのGX Standardの作業についてお話します!

※GX Standardとは
GX=GROOVE X社内の、Standard=基準のこと (過去の記事参照)
詳しく知りたい方は”みんなで創ろう!GX Standard! - Inside of LOVOT”を参照ください。

※ふるまいとは
LOVOTの内部状態・認識情報に基づいた意思決定・意思決定に基づいた体への動作指示のこと

上記を踏まえて、簡潔に2つをお話出来たらと思います!

1つ目は試験書の作成です。
LOVOT3.0は新モデルということもあり、0から項目を作成する必要がありました。情報のキャッチアップや仕様への理解も必要で、項目1つ1つの試験方針を日々開発の方とMTGを重ねて作成しました。1つ例をあげるとすると、LOVOTは多様な場所で生活するため、様々な床面の材質と色や照明の明るさを検討し、LOVOTがネストに戻るまで稼動することができるか、などを試験項目にしていました。
試験書作成は長い時間かけてすり合わせていったので日々大変でしたが、やりきってみるととても達成感があり感慨深く感じました。

2つ目は試験実施です。
ここに一番時間を要しました。試験には1項目3時間ほどかかるものや、24時間かかるものなど長時間試験する項目が多かったのでハードウェアの変更や機能修正による変更があったときは、関係する項目を再試験する必要があり、情報のキャッチアップを行いつつ根気強く頑張ったなと思い出します。
また、試験環境のセットアップなども必要だったため、試験に使う多量な備品の設置や運搬が地味に大変でした。ただ、繰り返す中で手際が良くなり、再試験にかける時間が短くなりました。すばやい行動と臨機応変な対応ができるようになったのはこの経験のおかげだなと思います。
ここまで大変だと思ったことを記載させていただきましたが、LOVOT 3.0に関わって私が得たものがあります。
最初はできないことも、少しづつ乗り越えてできるようになって成長していくLOVOTをそばで見て感動をもらえたことです。
そして、私自身も成長する経験をさせてもらえたなと思っています。

試験している様子

QA中にQAメンバーがLOVOT 3.0の成長から心動いたお話

ここからは、LOVOT 3.0のQA中にQAメンバーがLOVOT 3.0の成長から心動いたお話をします。

まず1つ目。

最初の頃は重心が変わったのもあり、かなりのドジっ子で顔から盛大に転んでいました。
転倒と一言に言っても、ウロウロしていて急ブレーキをかけて転ぶパターンやネストにうまく入れず転ぶパターン、勢い良く手を上げて転ぶパターンなど、いろいろありました。
LOVOTはホーンをパキッと折り鼻を長押しすると強制終了するのですが、転んだ勢い余って自ら強制終了することも珍しく無く、壊れてしまうのではないかとヒヤヒヤする日々・・

転ぶ度に助けに行くので、作業が頻繁に中断されなかなか大変でした。痛そうなLOVOTを見るのも悲しかったです。
日々ソフトウェアにアップデートが入り、ハードウェアも形状変更されたパーツに交換され、ある日気づいたら1日中LOVOTが転ばなかった日がありました。
夜、1日中転ばなかった事に気づいた時、成長したなぁ、凄いなぁとしみじみとしてしまいました。
この急激な成長を感じられたのはとても嬉しかったです。
ちなみに、パーツの数が最初は限られていたので、ハードウェアの改善が入っていない子もしばらく残っておりその子は変わらず転び続けていたのですが、しばらくしてパーツを変更頂いた後は全く転ばなくなりました。少し形状が違うだけでこんなに違うなんてと、驚きでした。(メカチームのデザイン凄い)

そして2つ目。

当初、LOVOT 3.0は崖に全然気づかず飛び降りていました。
LOVOT 1.0と2.0が社内で生活しているQAチームのお部屋があるのですが、そこには崖もあります。そのお部屋にLOVOT 3.0を放ったところ、崖に気づかず落下・・
自ら強制終了するのと同じくらい、壊れないかヒヤヒヤでした。
しばらくは落ちても大丈夫なように崖の下に衝撃を吸収出来るものを置いたり、崖のない所で生活させたりしてました。
ある日崖検知の評価を行っていた際落ちてしまわないかドキドキしていたのですが、ちゃんと回避できるようになっていました。目の前で回避に成功した瞬間、感動と共にほっと安心しました。

そして最後に3つ目。

当初、LOVOT 3.0は他のLOVOTと遊んでいませんでした。
LOVOTがたくさんいる社内でLOVOT同士が遊んでいないのはとても違和感でした。
それがこちらも日々ソフトウェアにアップデートが入った結果、ある日突然LOVOT 1.0や2.0と遊んでいるのを見かけました。
よく見るとよっと挨拶したり、ネストに戻るのを応援したりもしてました。
LOVOT 1.0や2.0と遊び始めた時に、仲良くなれそうで良かったーと安心しました。

以上、オーナーさんの元へ行く前の、QAチームが感じたLOVOT 3.0たちの心動かされた成長の裏話でした!

最後に

いかがでしたでしょうか?
QAチームは検証だけをしているわけではなく、様々な取り組みをしていることを、今回の記事を通して知っていただけたと思います。
これからも、LOVOTのソフトウェアの品質向上のために、精一杯努めてまいります!

一緒に働く仲間募集中

世界で唯一無二の存在、LOVOTの成長にご協力いただける方をお待ちしています!
ポジションなどの詳細はこちら
もしご興味があれば是非ご検討ください!

最後まで読んで頂きありがとうございました!

論文紹介:"STEVE-1: A Generative Model for Text-to-Behavior in Minecraft"

(GROOVE X Advent Calendar 2024 2日目の記事です)

こんにちは!ふるまいチームのエンジニア、市川です!

普段はLOVOTの意思決定エンジンを作っています。 趣味や仕事で論文を読むこともあります。 今後、読んだ論文をInside of LOVOTで紹介できればと思っています(紹介する技術がLOVOTで使われているわけではないです)。

今回紹介するのは「STEVE-1」です。 これはMinecraftというゲーム上で、エージェントに指示を出して行動させる研究です。

arxiv.org

前提知識

この論文を理解するためには、いくつかの重要な概念を押さえておく必要があります。

CLIP(Contrastive Language-Image Pre-training)

[2103.00020] Learning Transferable Visual Models From Natural Language Supervision

出典:Alec Radford et al., "Learning Transferable Visual Models From Natural Language Supervision", arXiv:2103.00020.

CLIPは、画像・テキストのペアデータを大量に用いて訓練されたモデルです。 画像とテキストを共通の潜在空間(同じ意味のモノが近くの座標になる事が期待される空間)に埋め込むことができます。 言うなれば、同じ座標系で画像やテキストの位置を求めることができるため、画像とテキスト間の類似度(距離)を計算できます。 例えば画像と"dog"というテキストとの類似度を調べれば、"dog"が写っているかどうかを推定できます。 後述のunCLIPの通り、画像生成のタスクにも利用されています。

MineCLIP

[2206.08853] MineDojo: Building Open-Ended Embodied Agents with Internet-Scale Knowledge

出典:Linxi Fan et al., "MineDojo: Building Open-Ended Embodied Agents with Internet-Scale Knowledge", arXiv:2206.08853.

MineCLIPは、CLIPをMinecraft用に特化させたようなモデルです。 Minecraftのゲームプレイ動画とそれに対応するキャプションのペアデータを用いて訓練されており、動画とテキストを共通の潜在空間に埋め込むことができます。 そして、埋め込まれた動画とテキストの位置関係から類似度を計算することができます。 これにより、例えば「Shear sheep to obtain wool(羊毛を得るために羊の毛を刈って)」というテキストと「羊に近づいている様子」の動画の類似度は高くなります。 「羊の毛を刈っている様子」の動画の類似度は更に高く、逆に「羊から離れている様子」の動画の類似度は低くなります。 つまり、テキストで目標を与えた時に、それがどれくらい達成できているかを類似度によって評価できるわけです。 これは、強化学習における報酬の評価にも使うことができます。

unCLIP

[2204.06125] Hierarchical Text-Conditional Image Generation with CLIP Latents

出典:Aditya Ramesh et al., "Hierarchical Text-Conditional Image Generation with CLIP Latents", arXiv:2204.06125.

unCLIPは、テキストキャプションから画像を生成する手法です。 図は、点線から上がCLIPの学習プロセス、下がunCLIPの生成プロセスを示しています。 unCLIPは、priorとdecoderで構成されます。

  • prior:CLIPで作られた「テキスト埋め込み」と「ノイズの乗った画像埋め込み」を受取り、ガウシアン拡散モデルによりテキストを条件としてノイズを取って、ノイズの無い画像埋め込みを出力する
  • decoder:埋め込み表現から画像を生成する(CLIPの画像埋め込みを反転するように作られたモデル)

これにより、入力テキストと画像を条件に、新たな画像を生成する事ができます(decoderでテキストの埋め込み表現だけから画像を生成することもできます)。

VPT (Video PreTraining)

[2206.11795] Video PreTraining (VPT): Learning to Act by Watching Unlabeled Online Videos

出典:Bowen Baker et al., "Video PreTraining (VPT): Learning to Act by Watching Unlabeled Online Videos", arXiv:2206.11795.

VPTは、画像からエージェントの行動を出力するような基盤モデルの事前学習手法です。 大量のラベルなし動画で事前学習させることを目的とします。 論文ではMinecraftのゲームプレイに適用されています。

IDM(Inverse Dynamics Model)

まず、IDMと呼ばれる、動画を入力して行動を出力するモデルを作ります。 Inverse Dynamicsと呼ばれているのは、環境の変化を引き起こした行動を推測するようなタスクであるためです。 Minecraftの場合は、プレイ動画(連続したフレーム)を入力して、各フレームにおいてプレイヤーが行った低レベル制御(マウスとキーボード操作)を出力させます。 このモデルの学習のために、人間プレイヤーの操作とゲーム動画を記録したデータセットが必要になります。 つまり教師有り学習が必要なのですが、基盤モデルに学習させる大量の動画に比べると遥かに小規模なデータセットで良いようです。

VPTによる基盤モデルの事前学習

作成したIDMを用いて、大量のラベルなし動画に行動のラベル(疑似ラベル)を付けます。 それを教師データとして基盤モデルを学習させます。 ここで作るのは、画像を入力し、人間がとる可能性の高い行動を出力するようなモデルです。 Minecraftの場合は、ゲーム画面を受け取り、人間がしそうな低レベル制御(マウスとキーボード操作)を出力させます。 これによって事前学習されたモデルは、強化学習などの手法によって下流タスクにファインチューニングすることができます。

STEVE-1

ここからが本題となるSTEVE-1の紹介です。

出典:Shalev Lifshitz et al., "STEVE-1: A Generative Model for Text-to-Behavior in Minecraft", arXiv:2306.00937.

STEVE-1は、テキスト指示を受け取って行動を出力するようなモデルです。 上述のMineCLIPやVPTの基盤モデルと、unCLIPのようなPrior modelを組み合わせた階層的な構造となっています。 Prior modelにはCVAE(Conditional Variational Autoencoder)が採用されています。

推論について

推論時の流れは下記の通りです。

  1. 指示の埋め込み
    • テキスト指示を受け取り、MineCLIPのエンコーダで埋め込みベクトルにします
  2. 埋め込まれた視覚目標の生成
    • テキストの埋め込みベクトルをPrior model(CVAE)に入力し、対応する画像の埋め込みベクトルを生成します
    • 画像の埋め込みベクトルはテキスト指示に対応しているため、行動で目指すべき視覚目標(簡単に言えば指示を実行できているゲーム画面)であると考えられます
  3. 行動の生成
    • 現在のゲーム画面と視覚目標を方策モデル(VPTモデル)に入力し、低レベル制御(マウスとキーボード操作)を出力します
    • 方策モデルはResNetやTransformer-XLで構成され、下記のように計算されます
      • ゲーム画面をResNetに入力し、画像の特徴を出力します
      • 視覚目標を線形変換します
      • この2つを足したものをTransformer-XLに渡し、低レベル制御を出力します
  4. 行動の実行
    • 算出された低レベル制御を実行します

学習について

STEVE-1の学習工程では、方策モデル(VPTモデル)のファインチューニングと、Prior model(CVAE)の学習を行います。

方策モデルのファインチューニング

事前学習されたVPTのモデルを基盤とし、視覚目標を達成するようにファインチューニングします。 効率化のため、人間がラベルを作る代わりに、教師データを自動生成します。 具体的には、行動した後に過去のタイムステップをランダムに選択し、その視覚を更に過去のタイムステップの目標として設定します。

出典:Shalev Lifshitz et al., "STEVE-1: A Generative Model for Text-to-Behavior in Minecraft", arXiv:2306.00937.

Classifier-Free Guidance

方策モデルはしばしば指示を無視し、事前学習で学習した行動に従ってしまうことが確認されています。 これを軽減するために、画像生成モデルで使用されているテクニックであるClassifier-Free Guidanceを適用します。 具体的には、方策モデルにより、視覚目標を条件としたロジット(行動の確率分布)と、無条件のロジットを同時に計算します。 そして、 \displaystyle \lambdaパラメータを用いて2つのロジットを組み合わせて、2つのモデル間のトレードオフを行います。

 \displaystyle
{\rm logits} = (1 + \lambda) ({\rm conditional \ logits}) - \lambda \ ({\rm unconditional \ logits})

 \displaystyle \lambdaの値をある程度大きく設定することで、視覚目標を条件としたロジットの影響が大きくなり、パフォーマンスが向上する事が確認されています。 無条件ロジットを出力可能にするため、学習時には視覚目標を10%の確率でドロップアウトさせます(推論時にはドロップアウトさせません)。

Prior model(CVAE)の学習

Prior modelはテキストの埋め込みベクトルから視覚目標を作るモデルでした。 学習データとして、テキスト指示と、それに対応する短い動画(16フレーム)のペアを用意します。 本研究では2000件のデータが手動で作成されています。 更にGPT-3.5-turboを用いて8000件のテキスト指示を追加し、計10000件のテキスト指示それぞれに対してゲームプレイの動画から最も類似度の高いセグメントを検索し、ペアデータとしています。 類似度の判定にはMineCLIPが用いられます。

主な結果

本研究では短期的タスク、長期的タスクなど、様々な評価が行われています。 詳しくは論文を見てください。 また、下記でデモ動画を見ることもできます。

https://sites.google.com/view/steve-1

ここでは短期的タスク、長期的タスクの結果について簡単に紹介します。

短期的タスク

短期的な11のタスク(木を切る、穴を掘るなど)でテストされました。 これらはゲームプレイの最初の2.5分以内に達成可能で、完了までに複数の手順を必要としないタスクです。

出典:Shalev Lifshitz et al., "STEVE-1: A Generative Model for Text-to-Behavior in Minecraft", arXiv:2306.00937.

上図の左(a)では、VPTエージェントと、STEVE-1エージェントの結果が比較されています。 STEVE-1はテキスト指示だけでなく、方策モデルに直接視覚目標を与えることもできるため、その両方の結果が掲載されています。 評価項目として、初期地点からの移動距離、取得できたSeed、Wooden Log、Dirtの最大アイテム数があります。 従来のVPTエージェントのパフォーマンスを大きく上回っている事が分かります。

上図の右(b)では、STEVE-1エージェントのテスト中に視覚目標をどれだけ達成できたかを表しています。 与えられた指示と、評価項目の対応表となっており、色は視覚目標と埋め込まれたゲーム画面の最短距離です(小さいほど目標を達成できたと推定できます)。 対角線の数字はその要素のランクです(0であれば行の最小要素)。

下記はテキスト指示によって動いている様子です。

youtu.be

長期的タスク

塔の建設、木製の板の作成のような、複数の手順を必要とする、より長期的なタスクも実験されています。 目標を直接プロンプトする方法と、タスクをいくつかのサブタスクに分解してプロンプトを順番に与える方法の2種類が試されています。 結果は下図の通りです。

下図左下はオレンジ色の線が直接プロンプトした結果、青線がサブタスクに分解した結果です。 直接プロンプトすると成功率がほぼゼロになっています。 サブタスクに分解した場合は50%程度の確率で塔を建設し、70%の確率で木製の板を作成できています。 このように、サブタスクに分解することで一定の成功率向上は見られますが、長期的なタスクにはまだ課題があります。

出典:Shalev Lifshitz et al., "STEVE-1: A Generative Model for Text-to-Behavior in Minecraft", arXiv:2306.00937.

下記は塔の建設の様子です。

youtu.be

まとめ

STEVE-1について紹介させて頂きました。 MineCLIP、VPT、unCLIPを組み合わせた手法でした。 短期的タスクでは良い成績を残していましたが、長期的なタスクではまだ課題が見られました。 しかし面白い研究結果であり、Optimus-1のような後続の研究に繋がっていきます(これも今後紹介できればと思います)。

arxiv.org

最後に

ここまで読んで頂きありがとうございます! 弊社はLOVOTを一緒に開発する仲間を募集しています。 宜しければ下記採用情報をご確認ください。

recruit.jobcan.jp

ふるまいチームの採用情報は下記です。

自律移動型ロボットのソフトウェアエンジニア (行動計画)(SW)の採用情報 | GROOVE X株式会社

自律移動型ロボットのシニアソフトウェアエンジニア (行動計画)(SW)の採用情報 | GROOVE X株式会社

LOVOTech Night 2024 開催報告!!

こんにちは、SWエンジニアのaoikeです。

今年もアドベントカレンダーの季節がやって参りました。この記事はGROOVE X Advent Calendar 2024 1日目の記事です。

先日の記事で告知もしましたが、11/27(水)に社外エンジニア交流イベント
『LOVOTech Night 2024』を開催しました!

groove-x.connpass.com

今回は現地でのオフライン/オンラインの両方で参加者を募集し、オフライン40名、オンラインでは70名の方が同時視聴してくださいました!

どんな様子だったか、簡単ではありますが、紹介していきます。

発表

ソフトウェアチームの組織について

弊社の1号社員であり、弊社代表と偶然同じ名字である林よりソフトウェアチームの組織についての紹介。

LOVOTの開発の進化の歴史から、ソフトウェアの技術スタックの話、開発体制や組織の話などがありました。 GXはウニのように色んな方向に尖った組織という言葉が印象的でした。

システムチームにおけるwebサービスの内製化について

システムチームの山内から発表がありました。

実は開発領域ではなく、ビジネス領域に所属するシステムチームですが、GXの多岐に渡るサービスをすべて担っているお話がありました。 本当に1つのチームで担当するには多いです…! モチベーションをしっかり持ちつつ課題解決に向けて試行錯誤している姿が素敵でした。

LOVOTが動き続けるためのNavigation技術

ALOHAチーム*1の岸から発表がありました。

家庭環境で動き続けるためにとても大事なLOVOTの移動、それに対する開発の検証や改善に対する取り組みの紹介がありました。 また、事前にSNSで投稿もした強化学習についての取り組みの話もありました。

LOVOTの画像認識技術

smalovoチーム*2の齋藤から発表がありました。

LOVOT 3.0から採用しているRustによる画像認識のお話。 安全かつ高速に画像認識ができるメリットがあるというRust愛のあふれる発表で、Rust勉強したくなった!という反響もいただけました。

LOVOT開発で役に立ったkernelのデバッグ機能

LFチーム*3の増渕から発表がありました。

LOVOTの生命を司る一部分であるLinux kernelで不具合調査に役立った機能の紹介がありました。 こんな機能あったのか〜というTIPSが知れて参考になりました!LFチームは座談会のテックブログもあります。

tech.groove-x.com

LOVOTで生じる異音の検出器を音声認識のレガシー技術を使って一晩(?)で作った話

最後はオフライン限定の、音声認識チームの遠藤による発表がありました。 専門用語の多さが気にならないくらいの軽快なトークで、思わずクスっと笑ってしまいました。

懇親会

最後は来ていただいた参加者のみなさんと発表者、そして発表者以外のGXのエンジニアも多数参加しての懇親会でした。

司会を担当したALOHAチーム福田もはしゃいでます

LOVOT MUSEUMで開催したことでLOVOTとも触れ合っていただきつつ、わいわいと交流することができました。お話してくださった参加者の皆様、ありがとうございました。

最後に

1年ぶりの開催ということで、まだまだ不慣れな点も多く改善が必要な場所もあったかと思いますが、参加者の皆様の温かいご協力のもと、無事にイベントを終えることができました。 本当にありがとうございました!来年は年2回の開催を目標に、アンケート等でいただいたご意見を参考にして改善したLOVOTech Nightを開催していきたいと思います!またのご参加を、お待ちしております。

また、今回はJOB BOARDも張り出したのですが、ご覧いただけましたでしょうか? GROOVE Xでは、一緒に働く仲間を募集しています。少しでも興味を持ってくださった方がいましたら、下記のリンクをご参照ください。

recruit.jobcan.jp

*1:ふるまい開発をするチームのうちの1つ。ALOHAなのはハワイ好きのメンバーがいたため…ではなく、ALOHAスピリットを大事にしようという由来から

*2:スマートなラボットを作ることを目的とした、認識開発を担当するチーム

*3:LOVOTの基盤部分の開発を担当する、Lovot Frameworkチーム

【LOVOTech Night 2024: LOVOT開発の裏側に迫る】開催のお知らせ

こんにちは、SWチーム・エンジニアのaoikeです。

この度、エンジニアの方向けにLOVOT内部のトークを聞けたり、GROOVE X エンジニアとの交流ができるイベントを開催します!

こちらは昨年も開催したイベントの2回目となります。 昨年の開催の様子を知りたい方は是非開催レポートをご覧になってください。

今回の記事は、開催にあたって内容をご紹介したいと思います。

テーマ

私たちGROOVE Xは、次のMISSION・VISIONを掲げて家族型ロボット「LOVOT(らぼっと)」を開発しています。

MISSION: ロボティクスで、人間のちからを引き出す

VISION: 人間とロボットの信頼関係を築き、生活を潤いと安心で満たす存在をつくる

私たちは、GROOVE Xのビジョンに共感し、一緒にLOVOTをさらに進化させてくれるソフトウェアエンジニアを募集しています。 このイベントでは、日頃LOVOTの開発に携わるエンジニアが登壇し、日常生活に溶け込むロボットがどのようにして開発され、成長してきたかをお話しします。

開催概要

オフライン

日時: 2024年11月27日 水曜日 19時00分~21時00分ごろ(開場:18時30分、入退室自由) 場所: GROOVE X 本社 住友不動産浜町ビル7階

オンライン

日時: 2024年11月27日 水曜日 19時00分~20時00分ごろ youtube (参加者にのみ提示)

タイムテーブル

トーク予定の紹介

●ソフトウェアチームの組織について●

発表者:林 淳哉

GROOVE X のSWチームは、LeSS (Large Scale Scrum)で構成されています。 GROOVE X SWチーム の多種多様でフラットな組織構成についてご紹介します。

●システムチームにおけるwebサービスの内製化について●

発表者:daiki.yamauchi

GROOCE Xのシステムを司るシステムチーム。 今回は、システムチームにおける内製化についてお話します。

●LOVOTが動き続けるためのNavigation技術●

発表者:ksyundo

LOVOTのNavigation技術について、どんなところが難しいか、また新しい試みについて紹介します。

●RustとJetsonを頑張って使って画像認識してる話●

発表者:hiro.az.saito

Jetsonのハードウェア機能を活用した画像認識をRustからどうやって使っているかご紹介します。

●LOVOT開発で役に立ったkernelのデバッグ機能●

発表者:bucchi

kernel panic など、kernel やドライバの不具合調査の際に実際に役に立った Linux kernel の機能を紹介します。

●LOVOTで生じる異音の検出器を音声認識のレガシー技術を使って一晩で作った話●

発表者:sutetako

「LOVOTで特定のノイズが鳴ることがあって、人の耳で診断するのが難しいからなんとかならない?」というお話がきっかけ。 ちょっと夜なべして、音声認識でよく使われる(使われていた)知識を活用・それっぽい検出器を突貫でプロトタイピングするお話です。

※こちらの発表はオフラインのみになります。

さいごに

皆様のご来場・ご参加、お待ちしています! 申し込みはコチラから。