はじめに
数年ぶりに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日間(実質作業時間)
プロジェクト目標
- Spresense SDK v3.0.0 → v3.4.5へのアップデート
- BMI160 6軸IMUセンサーからのデータ取得
- Madgwick AHRSアルゴリズムによる姿勢推定(Roll/Pitch/Yaw)
- 加速度の二重積分による位置推定
- 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の調査プロセス
- 既存の動作例との比較
# 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やビジョンセンサーなどの外部リファレンスとの統合が必要です。
学んだ重要な教訓
- NuttXビルドシステムの理解
- 二重.config構造: SDK側とNuttX側の両方が存在し、ビルドシステムはNuttX側を参照
- CONFIG命名規則: ディレクトリに応じた標準プレフィックス(EXAMPLES_、SYSTEM_等)が必須
- Make.defsの重要性: CONFIGURED_APPSへの登録がbuiltin化の核心
- MODULE変数は不要: 現代のNuttXではPROGNAME、PRIORITY、STACKSIZEのみで十分
- デバッグ手法(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
- WSL2開発のポイント
- Windows側でのusbipd設定が必須
- シリアルポートの競合に注意(minicom等を事前に終了)
- パーミッション設定(chmod 666 /dev/ttyUSB0)
- 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支援開発のベストプラクティス
- 明確な目標設定: AIに何を実現したいかを具体的に伝える
- 段階的な進行: 大きなタスクを小さなステップに分割
- エラー情報の共有: ログやエラーメッセージを詳細に提供
- 検証と確認: AI提案を盲信せず、必ず動作確認
- 知識の定着: 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関連
- https://developer.sony.com/spresense/development-guides/sdk_set_up_ide_ja
- https://nuttx.apache.org/docs/latest/
- https://www.bosch-sensortec.com/products/motion-sensors/imus/bmi160/
- https://x-io.co.uk/open-source-imu-and-ahrs-algorithms/
AI支援開発
- https://claude.com/claude-code - Anthropic社のAIペアプログラミングツール
- https://www.anthropic.com/api - Claude APIドキュメント
開発環境: 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時間
ステータス: ✅ 完全成功