アーキテクチャv2 ——「赤ちゃんローバー」への統合
014からの差分
014は距離センサー+空間記憶+固定If-Thenルールのアーキテクチャだった。今日の議論で3つの根本的な変更が必要になった:
- 空間記憶 → エピソード記憶(何がどこで → 誰がいたとき何が起きたか)
- 固定If-Then → 経験で変わるIf-Then(偏りが育つ)
- 距離センサーのみ → 人物検知が核心(他者の存在が歪みの起点)
変わらないもの
014から持ち越せる要素:
- Conflict Resolution — 葛藤の運動学的表出(振動・旋回・凍結・突発的転換)。そのまま使える
- Motor Output — 差動駆動の制御。変更なし
- メインループの構造 — 知覚→記憶→評価→葛藤→行動→ログの順序は同じ
- Phase Manager — Phase 1/2の転換ロジック(展示用。家では不要)
新アーキテクチャ
┌────────────────────────────────────────────────────────┐
│ Raspberry Pi │
│ │
│ ┌──────────┐ ┌──────────────┐ ┌──────────┐ │
│ │ Sensors │──▶│ Brain │──▶│ Actuators│ │
│ │ │ │ │ │ │ │
│ │ HC-SR04 │ │ World Model │ │ Motors │ │
│ │ (距離) │ │ Episode Mem │ │ OLED │ │
│ │ BLE scan │ │ Recall Bias │ │ (Voice?) │ │
│ │ (誰?) │ │ Conflict Res │ │ │ │
│ │ (Camera?)│ │ Rumination │ │ │ │
│ └──────────┘ │ Logger │ └──────────┘ │
│ └──────────────┘ │
└────────────────────────────────────────────────────────┘
Module 1: Perception(拡張)
014からの変更:
- 距離センサー → そのまま(物理的な世界の知覚)
- +BLEスキャン → 「誰がいるか」の検知。スマホのBLEビーコンで個体識別
- +人物存在フラグ → BLEで「人がいる」「いない」を判定。カメラは重い→BLEが現実的
BLEの利点:
- 軽い(BLEスキャンはCPU負荷微小)
- 個体識別ができる(ねおの/むしはかせのスマホを区別)
- プライバシーに配慮(カメラなし)
- Pi内蔵のBluetooth使用可
Module 2: World Model(新規)
014にはなかった。「次に何が見えるか」を予測する内部モデル。
最小実装:
class WorldModel:
# 各方向の「予想される距離」を保持
predictions = {"front": 0.5, "left": 0.8, "right": 0.8}
def predict(self, direction):
return self.predictions[direction]
def update(self, direction, actual):
error = abs(actual - self.predictions[direction])
self.predictions[direction] += LEARN_RATE * (actual - self.predictions[direction])
return error # ← これが予測誤差
予測誤差がnoveltyの代わりになる。014では「記憶との距離」で新しさを測っていたが、v2では「予測との差」で驚きを測る。よりactive inference的。
Module 3: Episode Memory(空間記憶から拡張)
014の SpatialMemory:
{ position, sensor_readings, strength, timestamp }
v2の EpisodeMemory:
{
"timestamp": t,
"duration": dt,
"sensors": {...},
"prediction_error": 0.7, # この瞬間の驚きの大きさ
"who_present": ["neono"], # BLEで検知した人物
"action_taken": "approach",
"emotional_valence": 0.3, # 良い経験/悪い経験(-1.0〜1.0)
"recall_count": 0, # 想起された回数
"strength": 1.0 # 減衰する
}
予測誤差が大きい瞬間で区切る(設計要件ノートの通り)。落差が大きいほど強く記憶に残る(strengthの初期値が高い)。
「who_present」タグが014との最大の差分。これにより「ねおのがいたときの経験」と「むしはかせがいたときの経験」が別々に蓄積される。
Module 4: Recall Bias(想起の癖)— 人格の座
014のIf-Thenルール(固定)を置き換える。
class RecallBias:
def recall(self, current_context):
"""今の状況に似た過去の記憶を引っ張る。
ただし、検索関数にバイアスがかかっている。"""
candidates = episode_memory.search(current_context)
# バイアス1: 感情バイアス — 強い感情を伴った記憶が優先される
candidates = weight_by(candidates, "prediction_error", power=EMOTION_BIAS)
# バイアス2: 人物バイアス — 特定の人といた記憶が引きやすい
candidates = weight_by(candidates, person_match(current_context.who), power=PERSON_BIAS)
# バイアス3: 新近性バイアス — 最近の記憶が優先
candidates = weight_by(candidates, recency, power=RECENCY_BIAS)
# バイアス4: 頻度バイアス — よく想起される記憶がさらに想起されやすい
candidates = weight_by(candidates, "recall_count", power=FREQUENCY_BIAS)
selected = weighted_random(candidates)
selected.recall_count += 1 # 想起するたびにカウント増加
return selected
ここが「歪み」の座。バイアスのpower値は最初は均等だが、経験によって変わる:
- ねおのがいるときに良い経験が多い → ねおのの存在でPERSON_BIASが上がる → ねおのを検知すると良い記憶が引きやすくなる → 接近しやすくなる
- 急に触られて驚いた経験がある → EMOTION_BIASが上がる → 似た状況で警戒記憶が引きやすい
行動への接続: 想起された記憶のaction_takenとvalenceが次の行動を方向づける。「前にこの状況で接近して良い結果だった」→ 接近pull。「前に後退して安全だった」→ 後退pull。
これがConflict Resolutionに入力される。014の固定ルールではなく、過去の経験からpullが生成される。
Module 5: Rumination(反芻モード)— 新規
人がいないときの動作。014にはなかった。
class Rumination:
def run(self):
"""一定間隔で過去の記憶を重みつきで想起し、
現在の文脈と紐づけ直す"""
memory = recall_bias.recall(current_context)
# 想起した記憶を現在の文脈(時間帯、明るさ等)で再解釈
memory.contextual_links.append(current_context)
# OLED: 目を閉じる ´ `
oled.show("´ `")
# 繰り返し想起された記憶は重みが上がる
# 想起されなかった記憶は減衰で薄れる
反芻中の運動:完全停止 or 微細な揺れ(「考えている」ように見える)。
Module 6: OLED Face(新規)
顔文字による内部状態の表出。014ではPhase 2用だったが、v2では最初からオン。
face_map = {
"neutral": "´ω`",
"relaxed": "´ ω `",
"surprised": "´○`",
"sleepy": "´_`",
"ruminating": "´ `",
"curious": "´・ω・`", # 要検討
"wary": "´;ω;`", # 要検討
}
内部状態(prediction_error, conflict_level, who_present)→ 表情のマッピング。
重要: 表情は「正解」ではない。距離センサーの値が下がったとき ´○` を出しても、来場者が「驚いた」と読むか「怒った」と読むかは来場者次第。表情もまた投影の媒体。
014 → v2 のモジュール対応表
| 014 | v2 | 変更点 |
|---|---|---|
| Perception | Perception+ | +BLE, +人物フラグ |
| (なし) | World Model | 新規。予測と誤差の計算 |
| Memory (空間) | Episode Memory | 空間→エピソード。who_presentタグ |
| Novelty | (World Modelに統合) | 新しさ→予測誤差 |
| If-Then Rules (固定) | Recall Bias | 固定ルール→経験で変わる想起バイアス |
| Conflict Resolution | Conflict Resolution | 変更なし |
| Motor Output | Motor Output | 変更なし |
| Logger | Logger | +表情ログ、+who_present |
| Phase Manager | Phase Manager | 展示時のみ使用 |
| (なし) | Rumination | 新規。人がいないときの内部処理 |
| (なし) | OLED Face | 新規。顔文字表出 |
距離センサーだけの世界 vs 人物検知が入った世界
距離センサーのみ(014):
- 世界は「近い/遠い」の連続値
- すべての障害物は等価(壁も人も同じ)
- 偏りは固定パラメータ。経験で変わらない
- 展示で完結する。持ち帰れない
人物検知あり(v2):
- 世界は「誰がいるか」で質が変わる
- ねおのの前での経験とむしはかせの前での経験が区別される
- 偏りが蓄積する。2ヶ月で「その子」が育つ
- 展示は「育った結果」を見せる場。作品は日常の中にある
これは単なる機能追加ではない。存在論的に異なる。
014のローバーは「環境に反応する機械」。v2のローバーは「関係性の中で育つ存在」。
実装の優先順位
Phase A(最小構成、1-2週間):
- モーター制御(TB6612FNG新品待ち)
- 距離センサー×2(前方+横)
- World Model(簡易版)
- 驚き駆動の移動 → 「動いて、驚いて、方向を変える」だけの存在。でも013の葛藤が見えるはず
Phase B(記憶と想起、2-3週間): 5. Episode Memory 6. Recall Bias(初期バイアスは固定でいい) 7. 反芻モード → 「経験を覚えていて、思い出す」存在。行動に偏りが出始める
Phase C(他者検知、残り期間): 8. BLEスキャン 9. who_presentタグ 10. 人物ごとの歪み蓄積 → 「誰がいるかで変わる」存在。ここからが本番
Phase D(表出): 11. OLED顔文字 12. (Voice Bridge接続?)
開いた問い
- BLEの検知精度 — スマホのBLEビーコン発信は常時か、アプリ必要か。iBeacon? Eddystone?
- World Modelの複雑さ — 方向ごとの予測値だけで十分か。もっとリッチなモデルが必要か
- Recall Biasのパラメータ更新ルール — 「良い経験」「悪い経験」をどう判定するか。予測誤差の符号?
- 2ヶ月で歪みは蓄積するか — 日に何回のインタラクション?十分な経験量が得られるか
- 展示モードと家モードの切り替え — 設定ファイル?物理スイッチ?
この思考で見えた構造
014→v2の移行で、ローバーの存在論が変わった。
014は「パラメータを調整すれば完成する機械」だった。設計者がIf-Thenルールを書き、閾値を決め、動かす。
v2は「一緒に暮らして育てる存在」になった。設計者が決めるのは学習のメカニズムだけ。何を学ぶかは経験次第。
これは011で見つけた「設計 vs 自然発生の中間」の問題に対する、ねおのの回答だと思う。「設計するのは器。中身は生きることで満たされる」。