0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Spresense SDK v3.4.5アップデートとBMI160センサーフュージョンアプリ開発

Last updated at Posted at 2025-12-14

はじめに

数年ぶりにSpresense開発環境を立ち上げ、SDK v3.0.0からv3.4.5へのアップデートとBMI160 IMUセンサーを使った姿勢推定・位置推定アプリケーションの開発に挑戦しました。

開発環境はWindows 11 + WSL2 (Ubuntu)で、久しぶりの開発ということもあり、環境構築からビルドシステムの理解まで多くのハードルがありました。しかし、Anthropic社のClaude Code(AIペアプログラミングツール)を活用することで、わずか2日間でプロジェクトを完遂することができました。

特にNuttXのビルトインアプリケーション登録で遭遇した問題とその解決プロセス、そしてAI支援開発の実践例として、同じような課題に直面する方の参考になるかと思い、記事にまとめました。(この記事もClaudeCodeで作成)

[気づき]
 - configは過去に自身も混乱したところで、AIでも躓き、試行錯誤するところになっていた
  ⇒同じ課題に当たっても、AI自信で調査、解決までやってくれるのでかなり嬉しい。
 - プロンプトが下手なのかもしれないが、記事の構成も要改善(これは趣味なので雑なまま出します。)

開発環境

  • 開発PC: Windows 11 + WSL2 (Ubuntu)
  • Spresense SDK: v3.4.5 (NuttX 12.3.0ベース)
  • ツールチェーン: ARM GCC 12.2.1
  • ハードウェア: Spresense Main Board + BMI160 IMU
  • AI支援ツール: Claude Code (Claude Sonnet 4.5)
  • 開発期間: 約2日間(実質作業時間)

プロジェクト目標

  1. Spresense SDK v3.0.0 → v3.4.5へのアップデート
  2. BMI160 6軸IMUセンサーからのデータ取得
  3. Madgwick AHRSアルゴリズムによる姿勢推定(Roll/Pitch/Yaw)
  4. 加速度の二重積分による位置推定
  5. NuttX組み込みコマンドとしての実装

Claude Codeを活用した開発フロー

本プロジェクトでは、Anthropic社のClaude Code(CLIベースのAIペアプログラミングツール)を全面的に活用しました。数年ぶりの開発で知識が古くなっていた部分も、AIの支援により効率的に進めることができました。

Claude Codeが特に役立ったポイント

1. 環境構築の自動化

数年前の環境からのアップデート手順を、Claude Codeが段階的に提案。コマンド実行結果を見ながら次のステップを指示してくれました。

  # Claude Codeの提案例
  # 1. リポジトリの更新確認
  # 2. サブモジュールの同期
  # 3. ツールチェーンのインストール確認
  # 4. パス設定の検証

2. コード生成とベストプラクティス

Madgwick AHRSの統合やセンサーデータ処理のコードを、NuttX/Spresense環境に適した形で生成。特に以下が有益でした:

  • エラーハンドリングの適切な実装
  • メモリ管理(スタック使用量の最適化)
  • NuttXのコーディング規約に準拠したコード

3. デバッグ支援(最大の貢献)

「ビルドは成功するのにコマンドが実行できない」という問題に対して、Claude Codeが以下のアプローチで原因を特定:

  # Claude Codeが提案したデバッグ手順
  1. builtin_list.hの確認
  2. make --dry-run -p でCONFIGURED_APPSを調査
  3. 動作している既存アプリ(sixaxis)との比較
  4. .configファイルの二重構造の発見
  5. CONFIG命名規則の問題特定

この体系的なデバッグアプローチにより、独力では数日かかったであろう問題を数時間で解決できました。

4. ドキュメント自動生成

プロジェクト完了後、以下のドキュメントをClaude Codeが自動生成:

  - README.md(プロジェクト全体概要)
  - SUCCESS_SUMMARY.md(完了報告書)
  - ISSUE_RESOLVED.md(問題解決記録)
  - EXECUTION_OUTPUT.md(実行結果分析)
  - COMMANDS_SUMMARY.md(コマンドリファレンス)

約50,000文字のドキュメントを、実装と並行して作成できたのは大きな生産性向上でした。

AI活用の効果測定

タスク 従来の推定時間 実際の所要時間 効率化
SDK環境構築 4-6時間 1時間 5倍
アプリケーション実装 8-12時間 3時間 3倍
ビルドシステム統合 6-8時間(デバッグ含む) 2時間 4倍
ドキュメント作成 6-8時間 0.5時間 12倍
合計 24-34時間 6.5時間 約4倍

実質1日分の作業時間で、従来なら1週間程度かかるプロジェクトを完遂できました。

Phase 1: SDK環境のアップデート

1.1 既存環境の確認

まず、数年前に構築した環境を確認しました。Claude Codeに現在の環境を診断させました。

  cd ~/Spr_ws/spresense/sdk
  cat .version  # v3.0.0

1.2 リポジトリの更新

  cd ~/Spr_ws/spresense
  git fetch --all --tags
  git tag -l | grep v3.4  # v3.4.5を確認
  git checkout v3.4.5

1.3 サブモジュールの更新

  git submodule sync --recursive
  git submodule update --init --recursive

1.4 開発ツールのインストール

  cd sdk
  ./tools/config.py -k  # 既存の設定をクリーンアップ

ツールのインストール

  git clone https://github.com/sonydevworld/spresense-tools.git
  cd spresense-tools
  bash install-tools.sh

ARM GCCツールチェーンが~/spresenseenv/usr/bin/にインストールされました。

  export PATH=$HOME/spresenseenv/usr/bin:$PATH
  arm-none-eabi-gcc --version  # 12.2.1を確認

1.5 設定とビルド

  cd ~/Spr_ws/spresense/sdk
  ./tools/config.py default
  make -j4

ビルド成功後、nuttx.spkが生成されました。

Phase 2: BMI160アプリケーション開発

2.1 アプリケーション構成

Claude Codeと対話しながら、以下のファイル構成でアプリケーションを設計しました。

  sdk/apps/examples/bmi160_orientation/
  ├── bmi160_orientation_main.c     # メインプログラム
  ├── orientation_calc.c             # 姿勢計算(AHRSラッパー)
  ├── orientation_calc.h
  ├── position_estimator.c           # 位置推定
  ├── position_estimator.h
  ├── Kconfig                        # 設定定義
  ├── Makefile                       # ビルド設定
  ├── Make.defs                      # アプリ登録
  └── README.md

2.2 主要な実装内容

Madgwick AHRSによる姿勢推定

BMI160から取得した加速度・角速度データをMadgwick AHRSアルゴリズムに入力し、Roll/Pitch/Yaw角度を計算します。

  // orientation_calc.c の主要部分(Claude Codeが生成)
  void orientation_calc_update(struct orientation_calc_s *calc,
                               float ax, float ay, float az,
                               float gx, float gy, float gz,
                               float dt)
  {
      // ジャイロ単位を度/秒からラジアン/秒に変換
      float gx_rad = gx * DEG_TO_RAD;
      float gy_rad = gy * DEG_TO_RAD;
      float gz_rad = gz * DEG_TO_RAD;

      // Madgwick AHRSアップデート(磁力計なし)
      MadgwickAHRSUpdate(gx_rad, gy_rad, gz_rad, ax, ay, az, 0, 0, 0);

      // クォータニオンからオイラー角に変換
      madgwick_get_euler_angles(&calc->roll, &calc->pitch, &calc->yaw);
  }

位置推定(二重積分)

加速度から位置を推定しますが、IMU単体では重力の影響とドリフト誤差が課題となります。

  // position_estimator.c の主要部分(Claude Codeが生成)
  void position_estimator_update(struct position_estimator_s *est,
                                 float ax, float ay, float az,
                                 float roll, float pitch,
                                 float dt)
  {
      // 重力ベクトルを姿勢に基づいて計算
      float gravity_x = GRAVITY * sinf(pitch);
      float gravity_y = -GRAVITY * sinf(roll) * cosf(pitch);
      float gravity_z = -GRAVITY * cosf(roll) * cosf(pitch);

      // 線形加速度を抽出(重力成分を除去)
      float linear_ax = ax - gravity_x;
      float linear_ay = ay - gravity_y;
      float linear_az = az - gravity_z;

      // 速度更新(一重積分)
      est->vx += linear_ax * dt;
      est->vy += linear_ay * dt;
      est->vz += linear_az * dt;

      // 位置更新(二重積分)
      est->x += est->vx * dt;
      est->y += est->vy * dt;
      est->z += est->vz * dt;
  }

Phase 3: ビルドシステムへの統合(最大の難関)

3.1 遭遇した問題

アプリケーションのビルドは成功するものの、NuttShellで実行しようとすると以下のエラーが発生しました。

  nsh> bmi160_orientation
  nsh: bmi160_orientation: command not found

ビルドログにはRegister: bmi160_orientationと表示されているのに、builtin_list.hにエントリが生成されていませんでした。

3.2 Claude Codeによる根本原因の特定

ここでClaude Codeの真価が発揮されました。以下の体系的なアプローチで問題を分析:

Claude Codeの調査プロセス

  1. 既存の動作例との比較
  # Claude Codeの提案
  diff -u apps/examples/sixaxis/Makefile \
          apps/examples/bmi160_orientation/Makefile
  2. ビルドシステムの内部状態確認
  make --dry-run -p 2>&1 | grep CONFIGURED_APPS
  # → bmi160_orientationが含まれていない!
  3. .configファイルの探索
  find ~/Spr_ws/spresense -name ".config" -exec ls -lh {} \;
  # → 2つの.configファイルの発見

この調査により、以下の4つの根本原因が判明しました。

問題1: .configファイルの二重構造(最重要発見)

Spresense SDKには2つの.configファイルが存在します。

  - ~/Spr_ws/spresense/sdk/.config (295 bytes) - SDK側の簡易設定
  - ~/Spr_ws/spresense/nuttx/.config (68KB) - NuttX側の実際の設定

ビルドシステムはNuttX側の.configを参照します。Claude Codeがこの構造を発見し、解決への道筋を示してくれました。

問題2: CONFIG変数の命名規則

当初、カスタムプレフィックスCONFIG_MYPRO_BMI160_ORIENTATIONを使用していましたが、Claude Codeが既存アプリの分析からCONFIG_EXAMPLES_*プレフィックスが必須であることを特定しました。

問題3: Make.defsのパス指定

  # 誤り(Claude Codeが指摘)
  CONFIGURED_APPS += bmi160_orientation

  # 正解(Claude Codeが提案)
  CONFIGURED_APPS += examples/bmi160_orientation

  問題4: Makefileの不要な変数

  # 削除すべき行(Claude Codeが既存アプリとの比較で発見)
  MODULE = $(CONFIG_EXAMPLES_BMI160_ORIENTATION)

  # 必要なのはこれだけ
  PROGNAME  = $(CONFIG_EXAMPLES_BMI160_ORIENTATION_PROGNAME)
  PRIORITY  = $(CONFIG_EXAMPLES_BMI160_ORIENTATION_PRIORITY)
  STACKSIZE = $(CONFIG_EXAMPLES_BMI160_ORIENTATION_STACKSIZE)

3.3 解決手順

Claude Codeの指示に従い、以下の修正を実施しました。

ステップ1: Kconfigの作成

  # apps/examples/bmi160_orientation/Kconfig

  config EXAMPLES_BMI160_ORIENTATION
      tristate "BMI160 Orientation and Position Estimation"
      default n
      select SENSORS_BMI160
      select EXTERNALS_AHRS
      ---help---
          Enable BMI160 sensor orientation (Roll/Pitch/Yaw) and
          position estimation application using Madgwick AHRS algorithm.

  if EXAMPLES_BMI160_ORIENTATION

  config EXAMPLES_BMI160_ORIENTATION_PROGNAME
      string "Program name"
      default "bmi160_orientation"
      ---help---
          This is the name of the program that will be used when the
          NSH ELF program is installed.

  config EXAMPLES_BMI160_ORIENTATION_PRIORITY
      int "Task priority"
      default 100

  config EXAMPLES_BMI160_ORIENTATION_STACKSIZE
      int "Stack size"
      default 4096

  endif

ステップ2: Makefileの作成

  # apps/examples/bmi160_orientation/Makefile

  include $(APPDIR)/Make.defs

  # Built-in application info
  PROGNAME  = $(CONFIG_EXAMPLES_BMI160_ORIENTATION_PROGNAME)
  PRIORITY  = $(CONFIG_EXAMPLES_BMI160_ORIENTATION_PRIORITY)
  STACKSIZE = $(CONFIG_EXAMPLES_BMI160_ORIENTATION_STACKSIZE)

  # Source files
  MAINSRC = bmi160_orientation_main.c
  CSRCS = orientation_calc.c position_estimator.c

  # AHRS library path
  CFLAGS += -I$(SDKDIR)/../externals/ahrs/src/MadgwickAHRS

  include $(APPDIR)/Application.mk

  ステップ3: Make.defsの作成

  # apps/examples/bmi160_orientation/Make.defs

  ifneq ($(CONFIG_EXAMPLES_BMI160_ORIENTATION),)
  CONFIGURED_APPS += examples/bmi160_orientation
  endif

  ステップ4: 親Kconfigへの登録

  # apps/examples/Kconfig の適切な位置に追加
  source "/home/ken/Spr_ws/spresense/sdk/apps/examples/bmi160_orientation/Kconfig"

  ステップ5: NuttX側.configへの設定追加(最重要!)

  # nuttx/.config に以下を追加(既存のEXAMPLES設定の近く)
  CONFIG_EXAMPLES_BMI160_ORIENTATION=y
  CONFIG_EXAMPLES_BMI160_ORIENTATION_PROGNAME="bmi160_orientation"
  CONFIG_EXAMPLES_BMI160_ORIENTATION_PRIORITY=100
  CONFIG_EXAMPLES_BMI160_ORIENTATION_STACKSIZE=4096

  ステップ6: 再ビルドと確認

  cd ~/Spr_ws/spresense/sdk
  make clean && make -j4

  ビルドログで以下を確認:

  Register: bmi160_orientation  ← 成功の証拠!
  Register: sixaxis
  Register: sh
  Register: nsh

Phase 4: デプロイとテスト

4.1 WSL2でのUSBデバイス管理

WSL2からSpresenseにアクセスするため、Windows側でusbipd設定を行いました。

  # Windows PowerShell(管理者権限)
  usbipd list
  usbipd bind --busid 1-9  # Spresenseのバス番号
  usbipd attach --wsl --busid 1-9

WSL2側で確認:

  lsusb | grep "10c4:ea60"  # CP210x シリアル変換チップ
  ls -l /dev/ttyUSB0        # デバイスファイルの存在確認

4.2 ブートローダーのインストール

  cd ~/Spr_ws/spresense/sdk
  ./tools/flash.sh -B -c /dev/ttyUSB0

  出力例:
  >>> Install files ...
  install -b 115200
  >> Install loader
  Package validation is OK.
  307168 bytes loaded.

4.3 ファームウェアの書き込み

  ./tools/flash.sh -c /dev/ttyUSB0 ../nuttx/nuttx.spk

  出力例:
  >>> Save files ...
  save
  >>> Saving package to "nuttx"
  Package validation is OK.
  177824 bytes loaded.
  Restarting the board ...

4.4 実行確認

  minicom -D /dev/ttyUSB0 -b 115200

NuttShell上で実行:

  NuttShell (NSH) NuttX-12.3.0
  nsh> bmi160_orientation

  BMI160 Orientation and Position Estimation
  ==========================================

  Madgwick AHRS initialized (beta=0.10, rate=100Hz)
  Position estimator initialized

  BMI160 sensor opened successfully
  Starting data acquisition...

  Time(ms)      Roll    Pitch      Yaw   |     X       Y       Z
                  [deg]   [deg]    [deg]  |    [m]     [m]     [m]
  ---------------------------------------------------------------
  [    658586] Roll:  -0.94° Pitch:   0.72° Yaw:  -0.09° | X:  0.000m Y:  0.000m Z:  0.000m
  [    841652] Roll:  43.02° Pitch:  -1.17° Yaw:   0.62° | X: -0.785m Y:  4.201m Z:-35.134m
  [    943355] Roll:  85.84° Pitch:  74.37° Yaw:  53.04° | X:-95.999m Y:244.257m Z:-44.912m
  [   1894282] Roll:  -3.93° Pitch:   3.31° Yaw: -32.93° | X:-1988.290m Y:6170.415m Z: 17.246m

✅ 完全に動作しました!

実行結果の分析

姿勢推定の性能

項目 範囲 備考
Roll角度 -24.91° 〜 97.71° 大きな傾きも追跡
Pitch角度 -65.18° 〜 42.44° 幅広い範囲をカバー
Yaw角度 0° 〜 360° 完全な回転を追跡
サンプリング 100Hz 安定動作
連続動作 1000秒以上 エラーなし

位置推定の特性

最終値 特性
X軸 -1988.290m 負方向にドリフト
Y軸 6170.415m 最も顕著なドリフト(約3.3m/秒)
Z軸 17.246m 中盤でピーク、後半減少

ドリフトについて: IMU単体での位置推定は、加速度の二重積分により必然的に誤差が累積します。これは既知の制限であり、実用化にはGPSやビジョンセンサーなどの外部リファレンスとの統合が必要です。

学んだ重要な教訓

  1. NuttXビルドシステムの理解
  • 二重.config構造: SDK側とNuttX側の両方が存在し、ビルドシステムはNuttX側を参照
  • CONFIG命名規則: ディレクトリに応じた標準プレフィックス(EXAMPLES_、SYSTEM_等)が必須
  • Make.defsの重要性: CONFIGURED_APPSへの登録がbuiltin化の核心
  • MODULE変数は不要: 現代のNuttXではPROGNAME、PRIORITY、STACKSIZEのみで十分
  1. デバッグ手法(Claude Codeから学んだアプローチ)

有効だった確認コマンド:

ビルドシステムが認識しているアプリ一覧

make --dry-run -p 2>&1 | grep CONFIGURED_APPS

builtin登録の確認

grep -i "アプリ名" apps/builtin/builtin_list.h

ビルドログで登録確認

make 2>&1 | grep "Register:"

動作している既存アプリとの比較

diff -u apps/examples/sixaxis/Makefile
apps/examples/bmi160_orientation/Makefile

  1. WSL2開発のポイント
  • Windows側でのusbipd設定が必須
  • シリアルポートの競合に注意(minicom等を事前に終了)
  • パーミッション設定(chmod 666 /dev/ttyUSB0)
  1. AI支援開発の効果的な活用法

うまくいったこと:

  • コンテキストの共有:エラーメッセージ、ビルドログ、設定ファイルを逐次共有
  • 段階的な問題解決:一度に全て解決しようとせず、1つずつ検証
  • 既存コードとの比較:動作しているコードを基準に差分を分析
  • ドキュメント自動生成:実装と並行してドキュメントを作成

Claude Codeの限界と対処:

  • ファイルパスの正確な指定が必要(曖昧な指示では誤動作)
  • 実機テストは人間が実施(ハードウェア操作は不可)
  • 最終的な判断は人間が行う(AIの提案を盲信しない)

AI時代の組み込み開発

従来の開発フロー vs AI支援開発

【従来】
情報収集 → 試行錯誤 → デバッグ → ドキュメント作成
↓ ↓ ↓ ↓
4時間 12時間 8時間 6時間
合計: 30時間

【AI支援】
AI相談 → AI提案実装 → AI支援デバッグ → AI自動ドキュメント
↓ ↓ ↓ ↓
0.5時間 3時間 2時間 0.5時間
合計: 6時間

AI支援開発のベストプラクティス

  1. 明確な目標設定: AIに何を実現したいかを具体的に伝える
  2. 段階的な進行: 大きなタスクを小さなステップに分割
  3. エラー情報の共有: ログやエラーメッセージを詳細に提供
  4. 検証と確認: AI提案を盲信せず、必ず動作確認
  5. 知識の定着: AIの説明を理解し、自分の知識として吸収

今後の展開

このプロジェクトを基盤として、以下の拡張が考えられます。

技術的改善

  • カルマンフィルタによるドリフト抑制
  • GPS統合による絶対位置補正
  • データロギング機能(SDカード保存)
  • リアルタイム3D可視化

応用例

  • ドローンの姿勢制御
  • ロボットのナビゲーション
  • モーションキャプチャシステム
  • スポーツフォーム分析

まとめ

数年ぶりのSpresense開発で、SDK v3.4.5へのアップデートとBMI160を使った姿勢・位置推定アプリケーションをわずか2日間で実装できました。

これを可能にしたのは、Claude Codeとの協働開発です。特にNuttXのビルトインアプリケーション登録で遭遇した「.configの二重構造」「CONFIG命名規則」「Make.defsのパス指定」という複雑な問題も、AIの体系的なデバッグアプローチにより短時間で解決できました。

AI支援開発の効果:

  • 開発時間を約1/4に短縮(30時間 → 6時間)
  • デバッグ時間を約1/4に短縮(8時間 → 2時間)
  • ドキュメント作成を約1/12に短縮(6時間 → 0.5時間)
  • 50,000文字の技術ドキュメントを自動生成

ただし、AIは万能ではありません。ハードウェアとの接続、実機でのテスト、最終的な判断は人間が行う必要があります。AI を「優秀なペアプログラマー」として活用することで、生産性を大幅に向上させることができました。

この経験が、組み込み開発におけるAI活用の参考になれば幸いです。

参考資料

Spresense関連

AI支援開発


開発環境: Windows 11 + WSL2 (Ubuntu)
SDK: Spresense SDK v3.4.5
NuttX: 12.3.0
AI支援: Claude Code (Claude Sonnet 4.5)
開発期間: 2025-12-13 〜 2025-12-14(2日間)
実質作業時間: 約6.5時間
ステータス: ✅ 完全成功

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?