ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Serial Studio 频谱频率标记(FFT Frequency Markers)设计实现指南:从数据模型到监控渲染的完整链路

Serial Studio 频谱频率标记(FFT Frequency Markers)设计实现指南:从数据模型到监控渲染的完整链路 Serial Studio 频谱频率标记FFT Frequency Markers设计实现指南从数据模型到监控渲染的完整链路【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio导读本文基于 Serial Studio 仓库中的设计规格 spec.md、plan.md 与 tasks.md 编写完整还原了FFT 频率标记与报警频带从动机、需求、数据模型、编辑器、API、渲染到测试验证的全过程。读完本文你将掌握如何在 Serial Studio 中为任意启用 FFT 的数据集添加带标签的频率标记与频带、设置警告/报警阈值并让频谱控件自动监控实时峰值以及这套能力如何通过项目 JSON 持久化并通过远程 API 读写。文中涉及的源码均可在仓库对应路径下查阅。一、背景与动机为频谱中的已知频率建立工程语义振动与声学分析的核心对象往往是已知频率800 Hz 的齿轮啮合线gear-mesh line、1× 转速的不平衡线、轴承缺陷频带、需要避开的共振点。在引入本功能之前Serial Studio 的 FFT 控件只能绘制整条频谱对每个赫兹一视同仁——用户必须肉眼定位自己关心的频率记住800 附近那个鼓包的含义再凭目测判断其电平是否超标。既没有方法为工程上有意义的频率打标签也无法一眼看出被监控的谱线是否越过了警告或报警电平更没有任何东西持久化到项目文件中来承载这些领域知识见 spec.md 的 Problem/Motivation 一节。而数据集在幅度域早已解决了等价问题报警频带alarm bands带严重级别、颜色和标签的彩色 min/max 区域可在 Project Editor 专用对话框中编辑、持久化到项目文件并驱动 Bar/Gauge/Meter/LED 等控件的可视化。频率域理应获得同样的待遇在频谱上提供命名标记与频带风格类似 DAW 均衡器与频谱分析仪——带柔和渐变的半透明彩色区域、带标签的频率线并附带每个标记的电平阈值越限即点亮。这正是本规格Spec 0019的出发点。二、目标与非目标明确边界2.1 目标Goals规格明确了八个可验收的目标spec.md 的 Goals 一节标记编辑用户可在 Project Editor 中为任意启用 FFT 的数据集挂载频率标记列表——每个标记包含频率或频带、标签、颜色以及可选的警告/报警幅度阈值dB。FFT 渲染FFT 控件在线性与对数频率轴、任意主题下都能美观清晰地渲染这些标记点标记为带标签的竖线频带为 DAW-EQ 风格的半透明渐变区域。自动监控每个显示 tick 自动测量标记频率邻域内的实时峰值电平当电平越过配置阈值时标记视觉状态升级正常 → 警告 → 报警并附带实时 dB 读数。持久化标记列表持久化在项目文件中未触碰的项目保存/加载保持字节级一致且可完全通过远程 API 读写。Waterfall 一致渲染Waterfall瀑布图/声谱图控件在同一频率轴上渲染相同标记保证两个频谱视图一致。2.2 非目标Non-Goals不做全局报警系统集成标记报警是控件局部的视觉不接入应用级报警监视器、MQTT 或导出FFT 仅在控件内部可见时才计算无头谱报警引擎是另一个更大的功能。不做自动峰值检测/跟踪标记停留在用户配置的频率上不找峰、不跟踪转速、不移动标记。不做谐波/边带光标1×/2×/3× 族用户可为每个谐波单独添加标记自动生成族是未来工作。不做逐标记历史或日志读数仅实时。不引入新依赖、不引入新文件格式标记搭乘现有项目 JSON schema增量式同 0014/0017 纪律。三、需求与验收标准Requirements Acceptance Criteria规格提出 8 条需求R1–R8每条都有明确的验收标准AC1–AC7需求内容验收标准ACR1 SchemaFFT 数据集可携带零个或多个频率标记起始频率 Hz必填、可选结束频率 Hz缺省或相等点标记否则为频带、标签、颜色hex空则从主题自动取、可选警告 dB、可选报警 dBAC1pytest 往返——带标记点频带含/不含阈值的项目重新加载一致无标记项目与旧构建保存的字节级一致R2 EditorProject Editor 提供与 Alarm Bands 编辑器外观/布局/交互语法一致的Frequency Markers编辑器AC5维护者人工验证——与 Alarm Bands 观感一致、校验阻止越界频率、Cancel 丢弃/Apply 持久化且控件实时更新R3 FFT 渲染点标记为竖线标签芯片频带为半透明垂直区域柔和水平渐变线性/对数轴、缩放平移、明暗主题均正确标记不遮挡频谱曲线区域在曲线之下标签在上AC3维护者在实时 FFT如音频输入上验证R4 监控每个显示 tick 计算标记带内的峰值显示电平 dB越限则升级视觉状态并显示实时峰值 dB无阈值只显示读数AC4阈值低于当前峰值时升级、调回后降级R5 工具栏开关FFT 控件工具栏增加Show Frequency Markers开关按控件持久化AC3/AC4 覆盖R6 API标记列表通过远程 API 往返既走通用 dataset-update 路径也走专用原子 get/set 命令非法输入被拒绝/钳制并告警AC2pytest API 往返 非法负载拒绝/钳制R7 Waterfall 渲染在声谱图上绘制相同标记竖线/半透明频带标签芯片缩放/平移/色图正确升级视觉为可选打磨AC6维护者人工验证R8 零热路径影响所有计算都在控件显示层以 UI 刷新率进行帧摄入/解析路径零改动AC7--benchmark-hotpath门禁不变3.1 关键设计决策Decisions规格在 2026-07-17 以委派授权方式记录了几条决策spec.md 的 Decisions 一节标记存放在数据集的项目 JSON 中同 alarm bands而非 widgetSettings它们是属于项目的工程配置、必须可通过 API 寻址而不是逐控件的外观状态。阈值采用显示 dB 值FFT 控件的原生 Y 单位与用户从图上读到的数值一致不做线性单位阈值。点标记监控窗口是小的固定邻域几个 bin轻微失谐的谱线仍能触发确切宽度是 plan 阶段的常量±2 bin。Waterfall 只保证渲染便宜的读数不强制升级视觉——其 C 绘制的轴层使每 tick 重标签开销过大超越线/带/标签的部分是打磨而非契约。四、数据模型与持久化Data Model Persistence4.1 FrequencyMarker 结构体计划plan.md与已落地的源码 Frame.h 完全对应。DataModel::FrequencyMarker定义如下struct alignas(8) FrequencyMarker { double frequency 0; /// Marker frequency in Hz (band start when endFrequency is set) double endFrequency 0; /// Band end in Hz; frequency means a point marker double warningDb std::numeric_limitsdouble::quiet_NaN(); /// Warning level (NaN unset) double alarmDb std::numeric_limitsdouble::quiet_NaN(); /// Alarm level (NaN unset) QString color; /// Optional hex override; empty - automatic (theme palette) QString label; /// Optional human label shown on the marker chip }; static_assert(sizeof(FrequencyMarker) % alignof(FrequencyMarker) 0, Unaligned FrequencyMarker struct);要点endFrequency frequency即视为点标记阈值默认为 NaN 未设置alignas(8)与 static_assert 维持对齐纪律与AlarmBand一致见 Frame.h。4.2 Dataset 扩展与 Keys数据集新增std::vectorFrequencyMarker fftMarkers;成员Frame.h紧邻既有的alarmBands。新的Keys::常量单一事实来源FFTMarkers(fftMarkers)、Frequency(freq)、EndFrequency(endFreq)、WarningDb(warningDb)、AlarmDb(alarmDb)并复用Keys::Label/Keys::Color。一个标记的 JSON 形态{freq: 800, endFreq: 850, label: Gear mesh, color: #ff5722, warningDb: -40, alarmDb: -25}除freq外所有字段可选写回时省略可选字段NaN 阈值、空字符串、endFreq freq永不序列化。序列化契约与AlarmBand相同数组仅在非空时写出保证未触碰的项目字节级一致读取时校验有限且freq 0endFreq仅在 freq时保留垃圾输入返回 false 并丢弃条目。4.3 无 schema 版本升级本特性为纯增量键旧构建读取时忽略未知键与 0014/0017 相同策略无需遗留别名无 Sessions DB 影响。五、编辑器FrequencyMarkersEditor 对话框5.1 架构复用 Alarm Bands 模式编辑器完全克隆AlarmBandsEditor的语法plan.md 的 Editor 一节。完整链路为DatasetView 功能区的Freq. Markers 按钮Behavior 区当所选数据集设置了DatasetFFT || DatasetWaterfall时启用图标复用fft.svg。触发ProjectEditor::openFrequencyMarkersEditorForSelection()ProjectEditorForms.cpp从m_selectedDataset.fftMarkers构建 QVariantListNyquist fftSamplingRate * 0.5rate 0 时有回退保护。发出openFrequencyMarkersEditor(groupId, datasetId, nyquist, markers)信号 → DatasetView 的Connections显示懒加载对话框。点击 Apply 调用Cpp_JSON_ProjectEditor.commitFrequencyMarkers(list)ProjectEditorCommit.cpp镜像commitAlarmBands→ 重建m_selectedDataset.fftMarkers、pm.updateDataset(...)、buildDatasetModel(...)。仪表盘实时拾取沿用既有的 modified→autosave→syncRuntime()路径与 alarm bands 相同控件在仪表盘重新配置时重新实例化。5.2 对话框形态FrequencyMarkersEditor.qml新建基于Widgets.SmartDialog包含Presets 卡片提供几个诚实可用的静态预设——50 Hz / 60 Hz 市电哼声含 2 次谐波的点标记。1×/2×/3× 转轴阶次按基准频率动态生成脚手架被否决预设保持静态。标记表格Start Hz、End Hz留空 点标记、Label、Color 色板ColorDialog 右键重置、Warn dB、Alarm dB、上移/下移、删除。实时预览条0…Nyquist 刻度上的标记总览频带为半透明区域、点为刻度。底部 Cancel / Apply IconButtons。内联校验编辑时 Hz 钳制到 0…Nyquist收集时归一化warn alarm空/非法数字视为未设置。多选行为与 Alarm Bands 完全一致commitFrequencyMarkers仅作用于m_selectedDataset单选语义按钮使能跟随 Alarm Bands 的同一规则。六、FFT 控件模型层监控与 QML 渲染6.1 C 模型零分配监控FFTPlot.h 中可见完整的 QML 接口面Q_PROPERTY(QVariantList markers READ markers ...) Q_INVOKABLE double markerPeakDb(int index) const; // 实时峰值 dB Q_INVOKABLE int markerState(int index) const; // 0 正常 / 1 警告 / 2 报警 // signal: markerValuesChanged()内部有struct MarkerRuntime解析后的 bin 窗口、阈值、实时读数与预分配的m_markerRt向量。流程为构造时复制数据集的标记钳制到 0…Nyquist将每个标记解析为[binLo, binHi]——点标记取 ±2 bin 邻域轻微失谐的线也能触发钳制到频谱范围。rebuildFftPlan()中重新解析因为 bin 宽度随 FFT 尺寸变化。每个 UI tickupdateData()在computeBinSpectrum之后对每个标记在m_binDb[binLo..binHi]上取峰值 → 存储峰值与状态经 NaN 感知的阈值比较0 正常 / 1 警告 / 2 报警→ 发出markerValuesChanged()。稳态零分配标记/bin/状态向量在构造或rebuildFftPlan时定容per-tick 循环只做浮点比较markersQVariantList 在构造时构建一次配置而非 per-tick 数据。QML 通过markerPeakDb(i)/markerState(i)double/int 返回按需读取——不产生 per-tick 容器。阈值语义采用显示 dBballistics 处理后即所见即所判WYSIWYG——原始 dB 会针对用户看不到的峰值报警。6.2 QML 叠加层DAW-EQ 风格渲染FFTPlot.qml 中的渲染设计频带 delegateRectangle 水平Gradient边缘 0.04 → 核心 0.22 的标记色不透明度 1px 边缘描边。点 delegate2px 竖线 背后 8px 柔和发光矩形。芯片胶囊形Label标记色背景 0.9 不透明度、widget_base文字复用 PlotWidget 的光标标签惯例文本格式label · −42.1 dB警告状态用Cpp_ThemeManager.alarmColorForSeverity(2)重染色/线报警用严重级 3 不透明度闪烁SequentialAnimation。分层频带放在裁剪过的Item中、父级为plot.curveLayer、z: -1在PlotCurve描边之下渲染标签芯片在第二层叠加曲线之上复用 PlotWidget 中_triggerLine的模式。坐标映射Hz→x 用控件自身的 world→pixel 数学logX ? log10(freq) : freq基于plot.xVisibleMin/xVisibleRange与PlotCurve完全相同的变换因此缩放/平移自动跟随。芯片防重叠顶部对齐水平重叠时后到的芯片自动换行JS 对少量标记做简单贪心行分配。工具栏开关labels.svg图标经saveWidgetSetting(widgetId, showFrequencyMarkers, ...)持久化默认开启。主题反应式QML 绑定Cpp_ThemeManager.colors自动适配明暗主题。翻译纪律芯片文本只用编号占位符%1/%2规避%n/.arg()翻译陷阱common-mistakes 要求。七、WaterfallC 绘制的标记渲染WaterfallPro 功能QQuickPaintedItem用 C 的paint()绘制相同标记plan.md 的 Waterfall 一节构造时复制标记updateData()从刚写入的m_smoothed行计算每个标记的峰值/状态少量比较。paint()绘制频带填充/标记线/标签芯片在轴层合成之后用与drawXAxis完全一致的xMinHz/xMaxHz缩放平移数学做 Hz→x 映射在 Waterfall.cpp 内提取一个共享小助手保证两个绘制路径不会漂移。关键决策标记不放进缓存的轴层——升级色调会随行变化而轴缓存只在缩放/主题变化时重建会过期每帧多画几根线相比图像 blit 的开销微不足道。新增markersVisibleQ_PROPERTY默认 trueQML 工具栏开关以同一showFrequencyMarkers设置名持久化。配色刷新通过既有onThemeChanged实现。八、API / SDK 面原子 get/set 增量更新键远程 API 面完整镜像 alarm-bands 模式plan.md 的 API 一节applyDatasetNumericFields新增fftMarkers分支数组经DataModel::read(FrequencyMarker, ...)解析非法条目丢弃镜像 alarmBandstakeParam保持未知字段告警诚实。新命令project.dataset.getFFTMarkers/project.dataset.setFFTMarkers原子数组读/写set 时返回droppedInvalid计数注册在 ProjectHandler.cpp 中 alarm-bands 对旁边。免费特性无BUILD_COMMERCIAL守卫——schema 与 FFT 控件为 GPL仅 Waterfall渲染器属于 Pro 且已在控件层门控。SDK 再生成由scripts/sanitize-commit.pygenerate-sdk 步骤在结束时执行。九、热路径与线程影响Hotpath Threading不触碰热路径FrameReader/CircularBuffer/FrameBuilder/ Dashboard 摄入或 span lane 零改动所有新计算都运行在控件模型的 GUI 线程、UI tick 节奏位于既有fftData()环读的下游。--benchmark-hotpath预期字节级不变AC7。无新跨线程信号/槽markerValuesChanged同线程控件 → QML编辑器/API 路径与今天一样在主线程。无新缓存热路径标志输入。时间戳所有权不变——该特性永不接触帧。稳态分配如上所述per-tick 循环仅比较浮点。十、权衡与备选方案Tradeoffs Alternatives计划文档以决策表形式记录了关键取舍plan.md 的 Tradeoffs 一节决策点选项选择与理由标记存放位置数据集 JSON vs widgetSettings vs 新顶层 map数据集 JSONfftMarkers同alarmBands——工程配置、API 可寻址、天然按数据集监控主体控件局部 vs AlarmMonitor 集中控件局部——FFT 仅存在于可见控件内集中式 无头 FFT 引擎规格非目标FFT 渲染方式QML 叠加 vs C 绘制层 vs QtGraphs 系列QML 叠加进curveLayer——主题/缩放/平移免费匹配 PlotCurve 分层无场景图工作Waterfall 渲染缓存轴层 vs 逐帧绘制逐帧——升级色调逐行变化轴缓存仅在缩放/主题时重建会过期阈值语义显示 dBballistics 后vs 原始 dB显示 dB——与图所见即所得原始 dB 会对用户看不到的峰值报警实时状态到 QMLper-tick QVariantList 属性 vs 信号可调用轮询可调用 markerValuesChanged——无 per-tick 容器抖动点标记窗口精确 bin vs ±2 bin±2 bin——轻微失谐的线仍能触发常量且在 brief 中说明编辑器入口表单模型行 vs 专用对话框专用对话框——结构体列表不适合行语法Alarm Bands 已开创先例十一、风险与缓解Risks Mitigations构造闭包/启动无风险——不触碰任何 ProjectModel 构造可达代码编辑器启动仅在用户点击时运行。字节级序列化回归0014/0017 纪律FFTMarkers仅非空时写出可选子键省略由新 pytest 往返覆盖保存未触碰项目并 diff。%n/.arg()翻译陷阱芯片文本只用编号占位符。QML 叠加在缩放下映射使用xVisibleMin/xVisibleRange与 PlotCurve/光标相同——已对照既有光标数学验证裁剪到图层平移出界标记不会渗出。Waterfall Hz 映射漂移提取一个本地助手供drawXAxis与标记通道共用两者不可能不一致。多选提交commitFrequencyMarkers仅作用于m_selectedDataset与commitAlarmBands相同单选功能区按钮沿用 Alarm Bands 的使能规则多选行为一致。Apply 后仪表盘陈旧依赖与 alarm bands 相同的 updateDataset→autosave→syncRuntime路径AC5 验证实时拾取若 FFT 控件需要轻推修复是既有 reconfigure 信号而非新路径。NaN 处理阈值比较前用std::isnan守卫JSON 写入器省略 NaN绝不输出null。十二、测试与验证计划12.1 自动化测试AC1/AC2新增 test_fft_markers.py维护者运行需应用 API 服务器启动经project.dataset.update与setFFTMarkers设置标记getFFTMarkers回显一致。保存/加载保持完整。非法负载负频率、垃圾类型、反序频带、warn alarm→ 以droppedInvalid丢弃/归一化。无标记项目 → 保存的 JSON 不含fftMarkers键。12.2 维护者人工验证AC3–AC6AC3/AC4音频输入实时 FFT 上800 Hz 点标记与带标签频带在两种轴模式下按要求渲染、跟随缩放/平移、明暗主题下观感自然、芯片显示实时 dB阈值低于当前峰值时升级警告/报警视觉可区分调回后降级。AC5编辑器与 Alarm Bands 并排对照观感一致校验阻止越界频率Cancel 丢弃、Apply 持久化且控件无需重启实时更新。AC6相同标记以正确频率出现在 Waterfall 上缩放/平移下正确。AC7--benchmark-hotpath门禁不变无摄入路径改动CI 确认。12.3 静态验证每个触及文件过python scripts/code-verify.py --fix/--check。C diff 过qt-cpp-review6 个 agent已确认修复的问题包括双域 bin 钳制、spectrumSize0守卫、freq 上限、芯片行加固、hasThresholds接线。结束时运行python scripts/sanitize-commit.py仅 sanitize不提交。十三、任务分解与实施顺序Tasks Overview实施按 9 个任务自上而下进行tasks.md依赖链清晰任务内容依赖T1SchemaFrequencyMarker结构 Keys serialize/read无T2编辑器 C启动信号 提交槽T1T3APIdataset-update 键 原子 get/set 命令T1T4FFT 控件模型标记配置、监控、QML 面T1T5FFT QML叠加渲染 工具栏开关T4T6编辑器 QMLFrequencyMarkersEditor 对话框 DatasetView 接线T2T7Waterfall标记渲染 逐行状态 开关T1T8pytest持久化 API 往返T3T9文档architecture 笔记 规格收尾T1–T8规格状态已标记为done2026-07-17 实现AC1/AC2 测试已写AC3–AC7 运行时检查等待维护者执行。十四、相关代码位置速查数据模型Frame.hFrequencyMarker、Frame.hDataset::fftMarkers、序列化/反序列化声明见 Frame.hFFT 控件模型接口FFTPlot.hmarkers属性、markerPeakDb/markerState可调用、MarkerRuntime、m_markerRtFFT QML 渲染FFTPlot.qml编辑器 QML新app/qml/ProjectEditor/Dialogs/FrequencyMarkersEditor.qml功能区入口DatasetView.qml编辑器 CProjectEditorForms.cpp、ProjectEditorCommit.cppAPI 注册ProjectHandler.cpp、ProjectHandlerEntities.cpp集成测试test_fft_markers.py规格文档spec.md、plan.md、tasks.md结语Spec 0019 为 Serial Studio 的频谱域补齐了与幅度域 alarm bands 对称的工程语义能力命名频率标记与 DAW-EQ 风格频带、显示 dB 阈值的自动监控与视觉升级、项目文件持久化、远程 API 原子读写以及 FFT 与 Waterfall 两个频谱视图的一致渲染——全程零热路径影响、零稳态分配、纯增量 schema。对于振动监测、声学分析、旋转机械故障诊断等典型应用这使盯住已知频率从肉眼劳动变成可配置、可持久化、可编程监控的工程流程。读者可以顺着上文给出的源码路径从 Frame.h 的数据结构一路读到 FFTPlot.h 的运行时监控与 FFTPlot.qml 的渲染层完整复现这条从需求到实现的链路。【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表