ROS2数据手套遥操作:用滑动窗口滤波消除机械手舵机抖动

第一次在 ROS2 里把数据手套的读数直接转发给机械手,我发现了一个有点尴尬的现象:我戴着手套慢慢张开手,机械手指却在那里高频哆嗦。屏幕上显示的弯曲角度曲线粗看还行,放大一看每一帧都在 ±5° 上下跳动,这个噪声落到舵机上,被忠实执行成了肉眼可见的抖动。后来我在这条链路中间插入了一个滑动窗口滤波节点,效果立竿见影。这篇东西就把完整过程整理出来:为什么抖、滑动窗口为什么够用、ROS2 节点怎么写、参数怎么调,以及我在真实硬件上踩过的几个坑。

1. 为什么给舵机下指令前要先过一遍滑动窗口

1.1 数据手套的噪声到底长什么样

数据手套这类设备,最常见的方案是柔性弯曲传感器配合分压电路。柔性传感器弯曲时电阻变化,经过 ADC 采集得到一个角度值。听起来很简单,但实际拿到的信号远没那么干净。

第一层噪声来自传感器本身。柔性传感器弯折时电阻并不是平滑变化的,内部导电材料的微观接触会有起伏,到了 ADC 上就表现为几毫伏到几十毫伏的随机跳动。第二层噪声来自 ADC 采样,不同板子的供电纹波、参考电压稳定性都会造成读数抖动。第三层则是物理层面的:人手本身就不是绝对静止的,肌肉微颤会直接叠加在手套读数上,这一点在手指悬空时尤其明显。

我在项目里用示波器视角看过整条数据流,静置时单通道读数能跳 ±2°,弯曲到 60° 左右时跳动扩大到 ±5°,如果再赶上采样周期偶尔丢一拍,个别帧能直接跳到 +8°。这个水平的数据,如果直接推到舵机,机械手的分辨率又比较高,那每一帧抖动都会变成真实位移。

1.2 把噪声直接丢给舵机的后果

很多初学者觉得舵机本身有“死区”,小范围抖动会被舵机吃掉。这个观点对模拟舵机可能成立,对现在常用的数字舵机基本不成立。数字舵机控制频率更高、响应更快,输入角度每帧变化,它都会尽力去追。结果是舵机在目标角度附近来回小幅振荡,表现出来就是机械手指“点头”“哆嗦”,声音上也能听到高频的“滋滋”声。

这个现象不只是难看的问题。长期高频振荡会带来三个实际后果:舵机持续堵转过流发热,齿轮组反复换向加剧磨损,机械手姿态不稳定导致无法完成抓取动作。我做抓取测试的时候,滤波之前常有“手指碰到物体就被抖开”的情况,因为指尖位置每秒都在小幅摆动,接触时的摩擦力方向也在变。

所以说,手套读取端和机械手执行端之间,必须有信号处理环节。它不是让机械手变得“迟钝”,而是把传感器噪声从控制链路里摘出去,保留真实的手势意图。

1.3 滑动窗口正是用来拆“平滑 vs 响应”这个矛盾的

控制链路里一直有个矛盾:想要动作平滑,就得容忍一定延迟;想要响应快,噪声就会漏进来。滑动窗口滤波站在一个很讨巧的位置——它不做任何复杂的模型假设,只保证一件事:连续 N 个采样的均值输出,天然比单点采样稳定。因为传感器噪声在时间轴上基本是零均值的随机扰动,平均之后会被抵消大部分。

后面会详细展开计算,这里先给结论:手指的动作频率通常在几赫兹以内,而手套采样往往在 50~100Hz,滑动窗口取 5~10 个样本平均,引入的延迟只有几十毫秒,人基本感知不到,但噪声幅度能压下去一个量级。这个性价比,在工程上很难被拒绝。

2. 滑动窗口滤波的数学细节与方案取舍

2.1 平均窗口的计算逻辑与O(1)递推写法

滑动窗口平均的原理很好理解。维护一个固定长度 N 的队列,每来一个新样本,把它加入队尾,同时把最早的样本挤出去,然后对整个队列求平均,把平均值作为当前输出。

公式写出来就是:

[ y[k] = \frac{1}{N} \sum_{i=0}^{N-1} x[k - i] ]

如果每次都重新遍历队列求和,复杂度是 O(N)。我这边每帧要处理 5 个通道,窗口取 15,单帧也就 75 次加法,其实算不上性能瓶颈。但 ROS2 节点回调用 Python 写的话,能省一点是一点,所以我用了递推写法:维护一个窗口总和total,新数据进来时加进去,被挤出的旧数据从总和里减掉,均值就是total / N。这样每帧每个通道只要加减各一次,复杂度变成 O(1),窗口再大也无所谓。

Python 里配合collections.deque(maxlen=N)用这个方案非常顺手。deque 满员后 append 会自动把最左边的旧元素挤掉,我只需要在 append 前把旧值从总和里减掉就行。具体代码在后面 ROS2 节点实现里给了完整版。

2.2 为什么是滑动窗口而不是低通、中值或卡尔曼

很多人会问,平滑信号不是有一堆现成方法吗,一阶低通、中值滤波、卡尔曼滤波,为什么非选滑动窗口?我逐个说下实际试出来的感受。

一阶低通(指数移动平均)实现最简单,一个公式y = alpha * x + (1-alpha) * y_prev就完了。但它有个特性:对阶跃变化的响应是渐近逼近的,会有明显的“指数拖尾”。手指快速张开时,机械手会慢半拍然后慢慢追上来,体感上像隔了一层棉花。滑动窗口平均不一样,新数据在窗口内的权重是均匀的,窗口滑过去之后输出能更干净利落地跟上目标值变化。

中值滤波擅长剔掉单个野值,比如偶发性的通信毛刺。但它是非线性滤波,对连续缓慢变化的信号平滑效果一般,而且输出曲线上会有平台状的阶梯感,机械手动作会显得一顿一顿的。

卡尔曼滤波理论最漂亮,只要噪声方差建模准确,它既能平滑又能维持较低延迟。但问题恰恰在“建模准确”这四个字上。传感器噪声方差会随弯曲角度变化,手指运动模型也不好写,调参调不对,整条曲线要么滞后严重要么直接发散。为了一个桌面级机械手 Demo 去投入这种调参成本,性价比不高。

滑动窗口平均的好处是零额外参数、行为可预期、调试直观。你设 N=5,心里就知道最多带来 20ms 左右的群延迟,数据录下来怎么检查都符合预期。在动手做系统之前,先把最简单可靠的方案用上,这是工程上的正路。

2.3 窗口大小N与延迟的量化关系

滑动窗口平均不是没有代价,代价就是延迟。平均滤波对信号的群延迟大约是(N-1) / (2 * f),其中 f 是采样频率。

举个例子,手套以 100Hz 发布数据,采样周期 10ms。窗口 N=5 时,理论延迟约(5-1)/(2*100) = 20ms。N=10 时约 45ms,N=20 时约 95ms。

这个延迟落到人机交互上是多少体感?手指快速点按动作的频段大概在 1~5Hz,对应周期 200~1000ms。20ms 的延迟只占一个动作周期的 2%~10%,人基本无感;95ms 就能感觉到“粘手”了,会觉得机械手总在慢动作回放。所以常规操作窗口取 5~10,追求精细稳定再往 15 以上走。

窗口 N100Hz采样下的理论延迟适合场景
10ms不滤波,纯裸数据测试
310ms对响应要求极高的演示
520ms日常遥操作,推荐起步值
1045ms慢速精确控制、抓取摆放
2095ms极精细动作,愿意牺牲响应

3. ROS2节点实现:从手套话题到机械手目标话题

3.1 话题与节点架构设计

整个链路我拆成三个节点:手套采集节点负责读取传感器并发布原始角度,平滑节点做滑动窗口滤波,机械手驱动节点订阅滤波后的角度并转换成舵机 PWM。

话题设计上,原始数据走/glove_angles,滤波后走/hand_target。消息类型直接用std_msgs/Float32MultiArray,数组里放 5 个浮点数,分别对应拇指到小指的弯曲角度。自定义消息当然更规范,但 Demo 阶段用标准消息最省事,少写一堆接口定义和编译步骤。

这里有一个容易踩的点:传感器数据应该用BEST_EFFORT的 QoS 订阅。手套数据是高频周期发布的,偶尔丢一两帧没关系,平滑窗口本身就能吸收这种丢帧。如果强行用RELIABLE,DDS 层可能为了重传丢掉的旧消息而阻塞回调,反而把实时性拖垮。滤波后的控制输出则建议用默认的RELIABLE传输,保证驱动节点拿到的指令是完整连续的。发布端和订阅端的 QoS 要保证兼容,不然ros2 topic echo都看不到数据。

3.2 平滑节点的完整Python实现

我用ament_python创建包,依赖只需要rclpy和std_msgs。创建命令是:

ros2 pkg create glove_smoother --build-type ament_python --dependencies rclpy std_msgs

核心节点代码我放在glove_smoother/smoother.py里:

import rclpy from rclpy.node import Node from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy from std_msgs.msg import Float32MultiArray from collections import deque import numpy as np class GloveSmoother(Node): def __init__(self): super().__init__('glove_smoother') # 可调参数 self.declare_parameter('window_size', 5) self.declare_parameter('num_channels', 5) self.declare_parameter('input_topic', '/glove_angles') self.declare_parameter('output_topic', '/hand_target') self.window_size = self.get_parameter('window_size').value self.num_channels = self.get_parameter('num_channels').value # 每个通道一个独立窗口 self.buffers = [deque(maxlen=self.window_size) for _ in range(self.num_channels)] self.sums = [0.0] * self.num_channels # 用于 O(1) 递推 sensor_qos = QoSProfile( depth=10, reliability=ReliabilityPolicy.BEST_EFFORT, history=HistoryPolicy.KEEP_LAST, ) self.sub = self.create_subscription( Float32MultiArray, self.get_parameter('input_topic').value, self.callback, sensor_qos, ) self.pub = self.create_publisher( Float32MultiArray, self.get_parameter('output_topic').value, QoSProfile( depth=10, reliability=ReliabilityPolicy.RELIABLE, history=HistoryPolicy.KEEP_LAST, ), ) self.get_logger().info('glove_smoother started') def callback(self, msg): data = list(msg.data) if len(data) != self.num_channels: self.get_logger().warn( f'通道数不匹配: 收到 {len(data)}, 期望 {self.num_channels}') return out = [] for i, value in enumerate(data): # 防御脏数据:非有限值直接沿用当前窗口均值 if not np.isfinite(value): value = self.sums[i] / len(self.buffers[i]) if self.buffers[i] else 0.0 # O(1) 递推:先加新值,再减被挤出的旧值 self.sums[i] += value if len(self.buffers[i]) == self.window_size: self.sums[i] -= self.buffers[i][0] self.buffers[i].append(value) # 窗口未填满时直接平均已有样本,避免启动跳变 smoothed = self.sums[i] / len(self.buffers[i]) out.append(smoothed) msg_out = Float32MultiArray() msg_out.data = [round(v, 2) for v in out] self.pub.publish(msg_out) def main(args=None): rclpy.init(args=args) node = GloveSmoother() try: rclpy.spin(node) except KeyboardInterrupt: pass finally: node.destroy_node() rclpy.shutdown() if __name__ == '__main__': main()

运行方式很简单,可直接传参调窗口大小:

ros2 run glove_smoother glove_smoother --ros-args \ -p window_size:=7 \ -p input_topic:=/glove_angles \ -p output_topic:=/hand_target

启动后用ros2 topic echo看两边数据对比,用rqt_plot同时订阅/glove_angles和/hand_target,滤波前后的曲线差异一眼就能看出来。

3.3 冷启动、丢包与脏数据的边界处理

我在写这个节点时,最先踩的坑是冷启动。节点刚启动时窗口是空的,如果代码上来就取sum / window_size,要么除零报错,要么输出 0。输出 0 的后果很吓人:机械手收到 0 度指令会瞬间把手指全部收紧,看起来就像机器手抽风。所以我这里特意写成“窗口未填满时直接平均已有样本”,前几帧输出虽然标准差大一点,但至少不会出现 0 到真实角度的跳变。

第二个坑是通道数不匹配。接入不同手套时,有的发布 5 通道,有的发布 6 通道甚至带一个 IMU 数据。如果不管不顾直接按固定索引取,轻则取值错位,重则数组越界。我在回调开头做了长度校验,不匹配就丢弃整帧并打日志。这个校验看起来多余,但实际接入新硬件时能帮你快速定位到底是节点问题还是数据格式问题。

第三个坑是脏数据。手套线缆接触不良或屏蔽层破损时,偶尔会读到 NaN 或 inf。如果这类值进入窗口,会导致接下来 N 帧的平均值全部被污染,输出一个剧烈的毛刺。我在代码里做了防御:遇到非有限值就用当前窗口均值顶替,不让脏值进入缓冲区。

4. 参数调优:窗口大小、采样频率与指令响应的三角关系

4.1 先录数据再定窗口:一种靠谱的调参顺序

很多人的调参方式是先设一个 N,跑一跑觉得不顺,再加或减。这样也能调出来,但效率太低。我更推荐先录数据,再做离线分析。

用ros2 bag record把手套原始话题录两分钟,期间覆盖几种典型动作:缓慢握拳、快速张合、悬停保持。录完之后直接把 bag 里的数据导出来画曲线,统计噪声的幅度和频率。噪声到底是高频小抖动还是偶发大毛刺,直接决定你选滑动窗口还是需要额外叠一层中值滤波。

以我实际经验,柔性弯曲传感器的噪声频率通常在 5~20Hz 量级,幅度在 ±3°~±5°。想让机械手看起来“稳”,需要把输出曲线的抖动压到 ±1° 以内。窗口 N=5 时可以把 ±5° 的随机抖动压到 ±1° 左右,但噪声更凶的话就要上 N=10。先去数据里找答案,比自己拍脑袋设参数靠谱得多。

4.2 采样频率不一致时会发生什么、怎么处理

滑动窗口平均有一个隐含前提:窗口内的 N 个样本在时间轴上近似等间隔。实际系统里这个前提经常不成立。

手套采集节点如果用的是简单的while True + sleep循环,发布频率会受系统调度影响波动;机械手驱动节点如果订阅的是RELIABLE消息,DDS 队列里旧消息没有及时被读走,回调触发时拿到的可能是几帧前积压的数据。这两种情况叠加,会让窗口里的样本时间跨度忽长忽短,滤波效果时好时坏。

我的处理经验是两条。第一,给手套话题的订阅端设置较小的KEEP_LAST depth,比如 5~10,让 DDS 队列不要积压太多旧消息。第二,滤波节点只负责输出平滑后的目标值,驱动节点的控制循环每次刷新时“取最新的滤波结果”,而不是把可读到的旧消息排队一个个处理。后者会让指令延迟被不断累积放大。

4.3 滤波放在角度映射前还是映射后

手套角度到机械手舵机角度之间通常要过一层映射。柔性传感器两端灵敏度不一样,弯曲 30° 之前和 60° 之后的读数变化率差很多,所以映射关系往往不是纯线性的,还可能要加死区补偿。

这个映射放在滤波前还是滤波后,结论是:一定放在滤波之后,或者说,先滤波原始角度,再做映射。

原因也很直接。如果先做非线性映射再做滤波,映射会把某些区间的噪声放大,比如灵敏度高的区域 1° 输入变化变成 3° 输出变化,滤波窗口前脚刚压完噪声,后脚映射又把噪声幅度拉回来一部分。更麻烦的是,映射里如果有死区或限幅,先映射后滤波会让处理过的信号越过限幅边界又被拉回,形成一种周期性的“撞墙”抖动。先滤波再映射,输入给映射函数的是一条平滑曲线,输出自然平滑,各环节职责也清晰:滤波负责去噪声,映射负责标定转换。

5. 机械手实测效果与踩坑记录

5.1 滤波前后的一组直接对比数据

我在同一台机械手上分别跑了裸数据和 N=7 的滑动窗口,记录了几组直观数据。

静置测试时,手套固定在手托上不动,滤波前角度在 48°~54° 之间来回跳,峰值抖动约 ±3°;滤波后同时间段稳定在 49.8°~50.4°,波动压到 ±0.3°。动态测试时,以大约每秒一次的频率做握拳-张开循环,滤波前机械手动作带有明显的高频颤振,滤波后整体平顺,跟随延迟体感上基本无感,用高速录像回放才能看出慢了几帧。

指标滤波前滤波后(N=7)
静置抖动幅度±3°~±5°±0.3°~±0.8°
舵机声音高频“滋滋”声明显基本安静
跟随延迟0约30ms
抓取成功率碰物即弹开稳定抓住

这个结果说明,滑动窗口在这个场景下并不是“牺牲响应换平滑”,它的延迟代价换来的是执行质量的大幅提升。

5.2 与舵机更新频率的配合:限幅必须跟上

滑动窗口解决的是噪声导致的抖动,但还有一个问题它处理不了:指令的“一步到位”。如果手从 0° 猛挥到 90°,滤波后角度曲线虽然平滑了,但每一帧输出依然可能在短时间内跨过很大的角度增量。舵机收到这种大位移指令,会全力冲过去,产生“甩手”效果。

解决办法是在滤波之后再叠一层速度限幅。控制周期内的最大角度变化量这样算:假设舵机最大允许角速度 120°/s,控制周期 20ms,单周期最大增量就是120 * 0.02 = 2.4°。驱动节点每次收到的目标角度,只朝目标方向移动最多max_delta,多出来的部分留到下一周期继续追。

我把滑动窗口和限幅一起用之后,机械手的动作才有了“人手感”:快速挥动时手会快速但柔和地跟上,不会甩,也不会抖。滑动窗口管高频噪声,限幅管大动态变化,二者互补,缺一个都不够完整。

5.3 我连续踩过的三个坑,都写在里面

第一个坑是窗口初始化方式。最早我在启动时把窗口预填为 0,结果每次节点启动,机械手指都会先猛收一下再慢慢打开,因为前 N 帧的输出是从 0 逐渐逼近真实角度的。后来改成窗口未填满时按已有数据平均,问题直接消失。

第二个坑是零漂。滑动窗口对零均值随机噪声有效,但对缓慢漂移无能为力。我的手套在连续工作十分钟后,手指自然张开的读数会从初始的 5° 漂到 12°,机械手也跟着慢慢“握紧”。后来我加了一个简易基线校准逻辑:发布端检测到所有通道在一秒内变化小于阈值时,就把当前读数当作新的零点,做差之后再进入后面的链路。这套逻辑虽然朴素,但实测几十次运行没有再出现明显漂移。

第三个坑是消息频率波动导致滤波效果不稳定。前面提过,手套节点的发布频率在 30~100Hz 之间波动时,固定 N 的窗口平均会掺入不均匀的时间间隔,输出曲线的平滑度忽好忽坏。我最后采取的办法是给订阅端配了深度较小的队列,并保证驱动节点每次只读最新目标值。如果项目要求更高,可以改成基于时间戳的加权平均,但我在这个 Demo 里没有走到那一步。

整体做下来,这条“手套→滑动窗口滤波→机械手”链路在 ROS2 里跑得很稳,逻辑简单、可复现、调试直观。数据手套的噪声是这类遥操作系统绕不开的问题,而滑动窗口滤波用最少的参数换来了最明显的体验提升。如果你也在做类似的机械手控制项目,建议先把原始数据录下来看清楚噪声长相,再决定窗口大小——这一步值得多花十分钟。

相关新闻

客服机器人主动发券唤醒沉睡客户:购买意图识别与实战拆解

客服机器人主动发券唤醒沉睡客户:购买意图识别与实战拆解

我接手这个需求的时候,第一反应是:客服机器人不是用来回答问题的吗?怎么还要主动发券?但实际业务场景里,这种“看似越权”的需求往往是增长团队最后捞人的一根稻草。电商平台积压了大量沉睡客户——买过几次、加过购物…

2026/10/20 17:09:34 阅读更多 →
从码农到扫地机器人掌门:跨界创业的底层系统思维

从码农到扫地机器人掌门:跨界创业的底层系统思维

很多人看到“从码农到扫地茅掌门,再到越野追梦人”这个标题,第一反应都是问同一句:你到底是写代码的、造机器人的,还是玩越野车的? 我的回答是:三个都做过,但没有任何一个是靠“换工作”换来的…

2026/10/20 17:08:33 阅读更多 →
PostgreSQL安装报错Requires: llvm-toolset-7-clang的排查与解决

PostgreSQL安装报错Requires: llvm-toolset-7-clang的排查与解决

碰到Requires: llvm-toolset-7-clang > 4.0.1这种报错,很多人第一反应是“装个数据库怎么还跟编译器扯上关系了”。我当年第一次在 CentOS 7 上装 PostgreSQL 11 也愣了半天,后来把 RPM 依赖链和 PostgreSQL 的 JIT 机制都翻了一遍才彻底搞明白。这篇…

2026/10/20 17:08:33 阅读更多 →

最新新闻

Qt课程进度导航栏G03:从数据模型到自绘渲染的完整实践

Qt课程进度导航栏G03:从数据模型到自绘渲染的完整实践

做教育类桌面客户端的时候,课程导航一直是个绕不开的活儿。用户要在一个窗口里看到章、节、课时的层级关系,要清楚自己学到哪了,还得能一键跳回上次退出的位置。市面上的现成组件大多只解决“展示目录”这一层,进度状态、学习记忆…

2026/10/20 17:53:47 阅读更多 →
软件设计师上午题解题切片:真题陷阱、能力断点与命题逻辑拆解

软件设计师上午题解题切片:真题陷阱、能力断点与命题逻辑拆解

简介:本资源为2025年下半年全国计算机技术与软件专业技术资格(水平)考试——软件设计师科目上午卷的真题解析与标准答案全集,专为备考该认证的计算机专业技术人员设计,聚焦基础知识巩固、解题逻辑训练与应试策略提升。…

2026/10/20 17:53:47 阅读更多 →
卫星姿态轨道控制Simulink仿真实践:从翻滚到对地定向的完整闭环

卫星姿态轨道控制Simulink仿真实践:从翻滚到对地定向的完整闭环

想真正弄明白卫星姿态轨道控制,光看资料是不够的。我见过不少人手里攒着好几份讲义和开源工程,每个模块单独看都能讲出头头是道,但要自己在Simulink里搭一条“从翻滚状态到对地定向稳定”的完整闭环,就卡住了。这篇博文就是一次卫…

2026/10/20 17:53:47 阅读更多 →
Microsoft Agent Framework迁移指南:从Semantic Kernel到自治AI代理

Microsoft Agent Framework迁移指南:从Semantic Kernel到自治AI代理

1. 项目概述:这不是一次简单的工具替换,而是一场底层思维的迁移“.NET AI 生态系统的重构与演进:Microsoft Agent Framework 对 Semantic Kernel 的继承、超越与战略整合”——这个标题里藏着一个被很多人忽略的关键事实:它不是在…

2026/10/20 17:53:47 阅读更多 →
每瓦Token成AI工厂新KPI,NVIDIA全栈升级如何提升能效

每瓦Token成AI工厂新KPI,NVIDIA全栈升级如何提升能效

AI算力圈最近都在聊一个新词:每瓦Token。这玩意儿不是厂商营销造出来的概念,而是实实在在成了衡量AI数据中心“生产效率”的硬指标。过去大家比的是峰值算力,也就是FP16、FP8下的TOPS数值,现在风向明显变了,大家开始盯…

2026/10/20 17:53:47 阅读更多 →
JMeter接口测试进阶:从参数化、断言到结果分析的核心能力

JMeter接口测试进阶:从参数化、断言到结果分析的核心能力

做接口测试这行,接触JMeter是早晚的事。早年我还在手工点接口文档、拿浏览器调试工具一个个试请求的时候,第一次用JMeter跑通一个几十线程的并发场景,那感觉确实挺新鲜。但说句实在话,从“会用JMeter”到“能把接口测试做出价值”…

2026/10/20 17:52:45 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →