arm_dev
|
bb6f792922
|
复位命令必须带 timeout:实测它自己会永久挂住,还留下占着 USB 的僵尸进程
上一版把触觉 wedged 的处置改成「首选 `sudo -n orisys-usb-reset`(免密,无人值守
可直接跑)」。真跑了一次,发现这句话是错的:
sudo -n /usr/local/bin/orisys-usb-reset 1-3.4.1
跑了 **155s 都没返回**,进程停在 `S` 状态(卡在写
`/sys/bus/usb/drivers/usb/unbind`),`timeout 90` 都收不掉它 —— 现场留下了三个
残留进程。对无人值守来说这是最坏的结果:那一轮在这里永久卡死,而且这个进程还
占着 USB,后面重试触觉只会继续失败。
复位之后 `1-3.4.1` 直接从 sysfs **消失**了(复位前它还在总线上、只是没有
/dev/video*)—— 也就是设备比复位前掉得更彻底。所以这条命令**不是**"跑一下试试"
那种安全操作,必须当有副作用的操作对待。
改动:
· 两处给现场的命令一律写成 `timeout 15 sudo -n /usr/local/bin/orisys-usb-reset
<devpath>`,并把「不加 timeout 会永久卡住 + 留僵尸进程」写进提示原文。
这与 `orisys_tactile.py` 的自动自愈口径一致(那里本来就是 `timeout=15.0`,
所以自动路径不受影响,只有手工执行的建议是错的)。
· 复位后设备仍不在总线上(或消失)→ 明确归到**物理**处置:拔插该相机 /
给这个 Hub 断电重启。
测试:test_v4l_health 新增两条 —— 断言给出的复位命令里含 `timeout 15`,
以及提示里必须写出"会挂住"这件事(只给命令不说风险,人就会裸跑它)。
全仓库 1119 passed / 1 skipped。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-09-28 10:46:06 +08:00 |
|
arm_dev
|
0fadd26ca2
|
体检判据硬化:sysfs 读取带超时、复位命令不再写成"要密码"
两处都是「体检工具自己失效」——本仓库最贵的那类坑:判据看起来在跑,其实
结论是假的或者干脆没有结论。
scripts/lib/usb_health.py
Hub 在内核里卡死时,读它的 sysfs 属性会**永久阻塞**(实测
/sys/bus/usb/devices/1-3.4/product 读 20 秒不返回)。于是体检脚本自己挂住:
本该报出故障的那一次,恰恰什么都不输出。新增 SysfsReader —— 所有 sysfs 读取
带 1s 超时,卡死的路径只尝试一次并记入 blocked(Python 杀不掉阻塞在系统调用
里的线程,不记就会在 --watch 反复采样时攒出几十个),blocked 映射回父设备
并按 error 报出「给这个 Hub 断电重启 / 改插主板直连」。
scripts/lib/v4l_health.py
· 提示语写「到真终端里带密码跑 orisys-usb-reset」,与实际不符:sudoers 对这个
脚本本来就是 NOPASSWD 白名单(`sudo -n -l` 可见;orisys_tactile.py 的自动
复位用的也是 sudo -n)。现场按这句会以为无人值守时做不了这件事。
改成 `sudo -n /usr/local/bin/orisys-usb-reset <devpath>` 并说明免密来源。
· wedged 的处置写反了:以前是「物理重插;reset 只在没完全卡死时有效」,
而设备还在 sysfs 里正是 unbind/bind 能生效的前提,先说 reset。
· main() 增加可注入的 v4l_root/usb_root,用例不再读真机 sysfs。
测试:test_main_exit_code_is_nonzero_on_error 以前直接读真 sysfs,本机这只
相机没插(unplugged)时会变红 —— 它本该只在 wedged 下断言复位提示。改为注入
临时 sysfs(设备在总线上、无 /dev/video*),用例变成确定性的。
test_usb_health + test_v4l_health 共 28 项通过。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-09-28 10:42:37 +08:00 |
|
arm_dev
|
98f4277849
|
真机开工体检四件套:USB 链路 / V4L 设备 / RDK 状态 / 手眼几何
这四个都是「现场看着正常、结果不对」的故障源,共同特征是**不报错**,所以要把它们
从流程里拎出来单独判,并且给出可执行的下一步,而不是只报一个失败。
scripts/lib/usb_health.py
RealSense 协商到 480Mbps(USB 2.0)时能出图、不报错,只是帧率掉到 1/2 且
深度不稳定。这里解析 sysfs 拓扑,把「速率对不对」独立于「有没有图」来判,
并在 --watch 下统计掉线/重连次数(线/口/供电 Hub 的问题会表现为反复抖)。
scripts/lib/v4l_health.py
触觉相机有两类完全不同的坏法,处置方式相反,以前都只表现为「没有 /dev/video*」:
· unplugged —— sysfs 里也没有,是没插/线坏
· wedged —— sysfs 里在、/dev/video* 没有,是 USB 端点了卡死(要复位或重插)
2026-09-28 现场左指就是 wedged(1-3.4.1 在 uvcvideo 下,video 节点缺失)。
scripts/lib/rdk_status.py
ros2_control 卡在 wait_for_operational 时,现象是「栈起来了但关节全是 0、
流程一直等」。原因全在 OperationalStatus 上,而它只有 RDK 读得到。
这里把状态翻成人话 + 处置(Auto(Remote) / 松急停 / 清故障)。
判据取自厂商头文件原话:IN_MANUAL_MODE = "need to switch to Auto (Remote) mode"。
scripts/lib/real_geometry_check.py
手眼矩阵与悬停几何。手眼写坏不会报错,只会让位姿整体偏几毫米到几厘米;
判据:R 正交(|RᵀR−I| ≤ 2e-3)、det(R)=+1、平移量级在 10–500mm。
悬停几何直接复用 gauge_fsm.hover_z_guard(流程里唯一判定处,不另写一套);
工件面未标定(site.yaml 写 0.0 = 未知)时**明确报 FAIL 并说明判不了**,
而不是按 0.0 算出一个假的「已修正」结论。
测试:test_usb_health / test_v4l_health / test_real_geometry_check 共 33 例,
全部钉在「判据要能报错」上(故意弄坏的输入必须被抓到)。
顺带 .gitignore 补 log_real/:真机各终端日志是运行产物,与 log_sim/ 对称。
|
2026-09-28 10:17:32 +08:00 |
|