fix(slv): wire dashboard memory slider to SLV backend#7
Closed
Love4yzp wants to merge 25 commits into
Closed
Conversation
Exhibition-tuning batch for the SLV Reachy deploy: - audio: selectable mic input channel (audio_input_channel / CLAWD_AUDIO_INPUT_CHANNEL), lower client-VAD silero threshold (0.3) for the Reachy Mini mic, TTS service URL. - vad: v2v_client_vad_threshold defaults to None (backend default) instead of 0.5. - vision: stop driving head pitch/roll from the exhibition camera (bbox/landmark coords are too noisy) — publish base body_yaw only, head stays neutral. - vision: stop queueing emotion motion from the vision stream (log-only now). - emotions: listening/thinking become antenna-only (no head pose). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make the head a single-writer resource so expression layers compose instead
of stomping each other (the root cause of head jitter / 'pulling the wrong
way' was three controllers writing the Stewart platform independently).
The head_tracking loop now computes the gaze anchor (face/DOA + body yaw) and
sums additive layers on top — emotion accents, speech wobble, idle micro —
clamps into a safe envelope, and emits ONE velocity-limited target:
- Emotion tags inject a transient _HeadAccent (relative offset with
attack/hold/release smoothstep envelope) that rides on top of gaze and
decays back to it, instead of commanding an absolute pose via goto_target.
- Speech wobble folded into the same per-tick sum (unchanged feel).
- Idle micro-motion layer (off by default: motion_head_idle_micro).
- Tunable: motion_emotion_accent_gain (0.6), motion_head_{yaw,pitch,roll}_limit.
- Preserves daemon-compat split + deadbands; legacy body tracking still
never re-anchors the head.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Promote the compositor getattr defaults to first-class Config fields with a
`motion:` yaml section, so accent strength / idle micro can be tuned on the
robot without code edits:
- motion_emotion_accent_gain (0.6), motion_head_idle_micro (false),
motion_head_{yaw,pitch,roll}_limit (25/18/18).
- slv deploy yaml gains a motion: section (accent_gain + idle_micro set;
limits commented to defaults).
motion_plugin reads these via getattr, so behavior is unchanged at defaults.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Audio capture intermittently bound the wrong device on Jetson: PortAudio in-container sometimes drops the USB card from enumeration, so _find_device returned None and capture fell back to the onboard Tegra audio (default device) — which has no real mic, so ASR only ever saw noise/silence and returned empty transcriptions. The duplex/bg-reader candidate lists also hardcoded hw:0,0 / plughw:0,0, but the Reachy Mini USB Audio is on ALSA card 2 here (cards 0/1 are the Jetson HDA/APE), so those never matched. Discover the ALSA card index from /proc/asound/cards (the kernel's authoritative view, unaffected by the PortAudio race) and target plughw:<card>,0 / hw:<card>,0 as the primary capture candidates, falling back to the resolved PortAudio index then the default. Device-agnostic: no card number is hardcoded. Verified on the Jetson (192.168.1.113): logs now show "resolved ALSA card 2" and the duplex stream opening on hw:2,0 instead of the onboard fallback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… trigger _visual_attention_active() gated on _last_face_trigger_time being within the attention window, but that timestamp is the sparse face-GREETING trigger: it fires once per visitor arrival and then sits on _face_trigger_cooldown_s. A visitor standing in front of the robot longer than the window (but silent since the greeting) read as inattentive, so their short utterances were dropped by the meaningful-text gate even while clearly engaging the robot — the wake-word-free flow felt dead. Key attention off continuous presence instead: _last_face_time / _last_face_count, which the vision plugin refreshes every frame a face is seen. Keeps the face soft-gate (still needs a face present to accept short unattended speech) but makes it actually track who is in front of the robot. Both existing attention tests still pass (face present → short text accepted; no vision plugin → dropped). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixes intermittent empty ASR: audio capture bound the wrong device (PortAudio enumeration race → onboard Tegra instead of USB mic) and the voice attention gate keyed off the sparse face-greeting trigger so short utterances were dropped while a face was present. Verified live on the Jetson — real ambient speech now transcribes correctly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…gated) Ports the reachy-mini SDK upgrade onto master (the original work lived on the disjoint feat/head-compositor line). Same logical changes, re-applied to master's current files. - pyproject: reachy-mini>=1.8.0, websockets>=15,<16 (SDK WS transport ceiling), numpy>=2.2.5 (SDK requirement), httpx>=0.28.0. - tests/test_sdk_contract.py (new): introspects the *real installed* SDK (not the MagicMock, which auto-stubs anything) to pin the motion/media/pose/ app-base API surface — the post-upgrade verification gate. - Daemon data-loop fix: the Zenoh->WebSocket migration (SDK 1.5.0) left _ensure_daemon probing the dead Zenoh port 7447, and spawning the daemon without --fastapi-port (so it bound 8000 while the client dialed reachy_daemon_port=38001). Now spawn/probe/connect all use reachy_daemon_port and the spawn passes --fastapi-port — matching the Jetson docker deploy. Covered by tests/test_daemon_readiness.py (new). - conftest: add enable_motors/disable_motors to the mock (real call sites that were silently auto-stubbed). - Stale Zenoh references corrected in README and face-tracker log labels. Verified: full suite 646 passed, 58 skipped, 0 failed on reachy-mini 1.8.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ned vision-cm4 Tidy-up pass to make the runtime architecture legible and align versions: - docs/ARCHITECTURE.md: live component/version/port map (mermaid), the three data loops (conversation / vision-attention / control), a deploy-layout matrix (live vs legacy parallel tree vs alternative-hw vs removed), a code-layout matrix (active SLV backend vs legacy conversation_plugin vs clientloop runtime), the "claw" naming origin, and a retirement checklist. - deploy/jetson/reachy/Dockerfile.daemon: pin reachy-mini>=1.8.0 (was unpinned, which is why the live daemon floated to 1.5.1 while the client built at 1.8.0). - scripts/: verify_reachy_sdk.sh (read-only diagnostic + optional motion test), backup_robot_reachy.sh (non-destructive image/state backup), rebuild_deploy_reachy.sh (Jetson-native rebuild+redeploy), hotpatch_reachy_sdk.sh. - Remove orphaned deploy/vision-cm4 (0 references; recoverable from git history). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ax_history) The "记忆/Memory" slider was dead under the SLV backend: get_history/set_history reached into `conv._client._config.max_history` / `conv._client._history`, which only exist on the legacy plugin (guarded by hasattr → silent no-op). Worse, SLV builds a bare Session() with no max_input_tokens and the runner only appends to it, so conversation history grew UNBOUNDED — the documented `ollama_max_history` (default 3, 0 = stateless) was never honored. SLV plugin now implements the contract the dashboard expects: - get_history_turns() / set_history_turns(n): read/persist ollama_max_history. - _cap_history_turns(): trim self._session.history to the last N user-anchored turns (matching ovs_agent's own turn grouping; tool turns counted as one; 0 = drop all prior history). Applied at the start of each turn (before the new user message) and live when the slider changes. dashboard_plugin get_history/set_history made backend-agnostic: prefer the SLV methods, fall back to the legacy _client path, else read config. Legacy backend behavior unchanged. Trim logic unit-tested for: N<count, N>=count, N=0 (stateless), empty history, tool turns, and leading-orphan rollback. py_compile clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
「通用/General」的记忆滑块在 SLV 下是死的:get_history/set_history 读写 legacy 才有的
conv._client._config.max_history(hasattr 守卫→静默跳过)。且 SLV 用裸 Session()、没设 max_input_tokens,runner 只 add_assistant→历史无上限增长,文档里的ollama_max_history(默认3, 0=无记忆) 从未被遵守。改:SLV 加 get_history_turns()/set_history_turns()/_cap_history_turns(),把 session.history 裁到最近 N 个 user 锚定回合(工具回合算1个,0=清空),每回合开始+滑块改动即时生效。dashboard 两个 handler 改为 backend 无关(优先 SLV 方法→回退 legacy→回退 config)。legacy 行为不变。
裁剪逻辑单测覆盖 N<总数/N≥总数/N=0/空/工具回合/头部orphan 全过;py_compile 通过。⚠️ 机器人离线,尚未设备实测。
🤖 Generated with Claude Code