DEEP 12 · 第一辑 · 运动控制核心 · LEARN NOTES

收进学习手册 · 2026-09-11 · duck.whatled.com

解读 12 · robotd/soc.rs + sound.rs + theremin.rs + chorale.rs:电池、声音与彩蛋

解读对象:robotd/src/soc.rs(84 行)、sound.rs(947 行)、theremin.rs(489 行)、chorale.rs(1320 行)
需要的前置:意图槽见解读 10;ToF 驱动见解读 17

1. soc.rs:板温是 sysfs 的事,不是总线的事

soc.rs 开头就划界(soc.rs:3-6):它不碰 Dynamixel 总线,所以不属于 duck-control、不走 RobotIo——这是读 /sys/class/thermal 的 sysfs(内核向用户空间暴露文件的接口),归跑在 Linux 板上的守护进程管。核心函数 hottest_zone_c(soc.rs:29)取所有热区的最大值而非单看 CPU:按名字挑一个区,换块板子就漏掉真正在升温的那区。读数 ≤0 视为传感器故障跳过;没有热区的机器(如 macOS)返回 None——靠"找不到文件"降级,不用 cfg 条件编译。

电池侧只做采样:每 1 秒(RATE_WINDOW,main.rs:85)补采一次慢传感器,BATTERY_EMA_ALPHA = 0.1(main.rs:99)做指数平滑——约 10 秒时间常数,压住随步态起伏的电压摆动(main.rs:3039-3046)。百分比映射见 model.rs 的 battery_percent(解读 07)。

2. sound.rs:独占 PCM 决定一切结构

声卡 PCM 是独占单客户端的,sound.rs 的形状由此而来(sound.rs:5-15):只有一个播放子进程,新声音杀死旧的;所有播放走一个被控制循环拥有的 Sound(play,sound.rs:281)。PCM 归谁是五态枚举 Ride(sound.rs:90-104):Off/Riding/Landing/Theremin/Singing。滑行(wheee,按住就循环的"骑乘",源码称 ride)有两种退场:明说松开 → 杀子进程;信号停了 → 写完 end 段落地——只有后者会播放 wheee_end_*,这正是解读 10里 WheeeHold 三态的原因。

两个硬边界:关机前的告别 peck 是唯一阻塞调用,上界 BLOCKING_PLAY_MAX = 1500 ms(sound.rs:42);block_sigpipe(sound.rs:77)屏蔽写线程的 SIGPIPE,否则写死掉的 aplay 会杀掉守护进程。两个实测数:扬声器 300 Hz 以下就没法了(SPEAKER_ROLLOFF_HZ,sound.rs:70);合唱每声部音量 0.55(CHORALE_LEVEL,sound.rs:63)——四只鸭是声学叠加,真机没人替你除。

3. theremin.rs:三种采样率在一处会合

ToF 特雷门(手在喙前的距离变音高)的模块注释把三个速率摆开(theremin.rs:1-9):深度帧 15 Hz 来自 tofd 的 socket、控制循环 50 Hz 独占嘴、音频 48 kHz 在写线程。reader 线程把最新帧放进 ArcSwapOption 槽(theremin.rs:88);Theremin::tick(theremin.rs:153)由循环调用、永不阻塞,产出 Note(theremin.rs:73):嘴张度 + 状态块 + closeness(0 远 1 近)。它刻意不是频率——音域跟着嗓音库走;同一份 closeness 同时驱动音高、音量和嘴,两条曲线不一致就是"嘴型动画贴在声音上"。帧停了是"淡出不是闸门":超过 FRAME_STALE = 500 ms(theremin.rs:46)电平归零,帧回来乐器自己续上。

4. chorale.rs:没有指挥棒的多机合唱

chorale.rs 是鸭子合唱的行为层(chorale.rs:1-5):btd 管无线电不思考,这里思考不碰无线电,两者之间只有信标。机制三条:低 id 指挥(chorale.rs:9-12)——两只愿意唱的鸭子确定性选出指挥,没有可丢的选票;指挥掌握座位表(chorale.rs:14-22)——座位按加入顺序排,各自推座位会和别鸭不一致,所以指挥广播 roster,所有人重放 seat_all;拍号即时间(chorale.rs:24-30)——没有共同时钟,指挥的拍计数器就是时间基。曲子表 PIECES = [1, 2, 3](chorale.rs:60-66):wistful、duck_strut,和标注"TEST ONLY — remove before release"的 outer_wilds(chorale.rs:62-63)——彩蛋如实交代在注释里。安全阀:[chorale] accept 默认 false(robotd-params lib.rs:437-443),不该有鸭子因为别人走进房间就自己动起来。

你带走的收获

延伸

什么鸭 WHATDUCK · 复刻学习笔记 ← 全部手册 · 首页