内核调度器与实时优先级:机器人低延迟优化实战

做了这么多年机器人系统,我越来越觉得,实时性问题的根子往往不在ROS/ROS2应用代码里,而在更底下那层——任务到底由谁调度、以什么策略调度。之前接过一个移动底盘的活儿,现象很典型:ROS2节点的控制指令在低负载时延稳定在3ms左右,一旦建图线程跑起来偶尔飙到20ms+,里程计输出跟着跳。一开始怀疑是驱动代码或者总线通信,排查一圈最后定位到调度器,四个节点的线程全挤在同一个核上,默认CFS调度,关键线程和后台日志线程抢CPU时间片,延迟当然忽高忽低。

这一篇我想把内核调度器这块真正讲透。给正在做ROS/ROS2机器人、自动驾驶域控、工业控制的朋友一个完整的实操路线:从CFS和实时调度策略的原理差异,到chrt和pthread API怎么设置优先级,再到CPU隔离、带宽限制这些配套优化怎么配合。内容偏工程向,偏向“改完立竿见影”的那种经验,但也把原理尽可能说清楚,避免大家只知道命令不知道代价。

1. 为什么ROS/ROS2要跟内核调度器较劲

1.1 ROS节点在Linux里就是一个普通进程

先说一个经常被忽视的事实:ROS节点也好,ROS2的组件也罢,编译完跑起来就是一个用户态进程,跟你在终端启动一个python脚本没有本质区别。Linux内核对它一视同仁,按默认策略CFS(Completely Fair Scheduler,完全公平调度器)来分配CPU。除非你显式改调度策略和优先级,否则你的关键控制循环和一个打印日志的worker在调度器眼里地位是一模一样的。

机器人应用里最典型的强实时任务是什么?我以底盘运动控制举例:读取轮式编码器、做运动学解算、给电机控制器发指令。这个循环按1kHz跑,意味着每次执行要在1ms预算内完成。1ms在Linux上不算短,但问题在于不确定:你可能算完只用了300us,但任务本来该在t=0时刻唤醒,结果醒来的时候已经t=0.9ms,甚至更糟,跑到t=1.2ms才被调度。累积误差一来,速度环自然抖动。CFS的公平调度在这里并不关心你这个循环系统有多急。

1.2 调度器是第一个“隐形延迟”

很多人在应用层优化浪费了大量精力——改DDS配置、调QoS策略、甚至重写回调逻辑——结果发现延迟曲线跟没改差不多,原因就是延迟的根源根本不在应用层,而是任务压根没有被及时调度执行。你的回调代码写得再快,线程不拿到CPU时间片就是白搭。

我遇到过最典型的场景:某台工控机上同时跑着实时控制节点、建图节点、还有某监控脚本每500ms采集一次系统指标。监控脚本看起来无害,但它的线程会周期性地插队到CFS可运行队列偏前的位置,从而挤压真正关键的任务。如果你用perf或者追踪工具去看调度事件,会发现控制线程平均唤醒延迟在几百微秒,但最大延迟经常超过10ms,这种非线性非常难在应用层通过加打印加延时去理解。

所以,做机器人实时系统,第一课就是:先让调度器听你的话,再谈业务代码优化。部分关键节点/线程应脱离CFS,用实时调度策略和明确的优先级来管理。

2. CFS、SCHED_FIFO、SCHED_RR到底差在哪里

2.1 CFS的“公平”和“及时性”是两码事

CFS的设计目标是让所有可运行任务在长时间尺度上获得与各自权重匹配的CPU时间。它用vruntime记录每个任务的虚拟运行时间,每次调度都选择vruntime最小的任务执行。nice值决定权重,nice越低权重越高,比如nice=-10的进程理论上能分到的CPU时间比nice=0的多不少。

这个机制的优点是很公平、吞吐好,适合大量普通任务互相分享CPU的场景。但换成实时场景,缺点就暴露了:CFS不提供硬性的“抢占保证”,一个高权重的进程并不能马上抢占当前正在运行的低权重进程,要等调度周期到点或者当前任务时间片用完。普通任务数量一多,关键线程的调度延迟就不可控。

有个误区要澄清:不是把进程的nice调到-20就能获得实时性。nice只能影响CFS内部的权重分配,它不改变调度策略。你的任务依然属于普通调度类,依然会被其他普通任务抢占,只是相对能多分时间。真正要跨过这个门槛,必须切换到实时调度策略。

2.2 SCHED_FIFO:优先级高的先跑,跑完才算完

SCHED_FIFO属于实时调度策略,配合静态优先级,范围是1到99,数字越大优先级越高。它和CFS是两套并行的调度类,内核会优先保证所有实时任务先于普通任务运行。同一个核上如果有多个实时任务,优先级最高的先运行。

关键规则是:SCHED_FIFO任务不按时间片轮转,除非自己主动让出CPU(比如sleep、等锁、阻塞在I/O上),或者被更高优先级的实时任务抢占,否则它会一直运行下去。打个比方,FIFO任务就像一条单车道上的第一辆车,除非它自己靠边停或者后面来了警车,否则一路开到底。

这个特性既是福音也是陷阱。用于强实时任务效果极好——控制线程醒来后只要优先级足够高,几乎可以做到立刻抢占CPU,延迟通常能降到几十微秒级别。但如果代码里有个死循环,或者调试时忘了先移除FIFO优先级,这个任务会锁死整个核心,连ssh和top都拉不回来,只能物理重启。这是每个玩实时调度的人早晚要踩的坑。

2.3 SCHED_RR:实时任务里的“轮流坐庄”

SCHED_RR同样属于实时调度类,优先级范围和SCHED_FIFO完全一致,区别在于同一优先级的多个RR任务会按时间片轮流执行。如果只有一个实时任务,RR和FIFO几乎没区别;但如果同一优先级放多个任务,RR会按固定时间片轮转,避免某个任务独占CPU。

这个时间片长度与系统配置有关,可以用sched_rr_get_interval()查询。我见过不少平台上默认在100ms左右,也有更短的,不同内核配置差异较大。对于多数机器人场景,我倾向于对强实时任务用FIFO,让关键线程一被唤醒就能跑;对一组同权重的周期任务想互相平分CPU时间,才考虑RR。

2.4 三种策略的适用场景比对

调度策略优先级范围是否受CFS时间片影响典型适用场景
SCHED_OTHER/CFSnice -20~19是日志、可视化、建图、非实时业务
SCHED_FIFO实时优先级 1~99否,按优先级抢占强实时单线程、控制循环、安全逻辑
SCHED_RR实时优先级 1~99否,按优先级+时间片轮转多实时任务同优先级互不饿死

如果你对“优先级”和“nice”之间的关系还不熟,这里再强调一遍:CFS里的nice值只决定普通任务间的相对权重,实时优先级则直接决定调度顺序。实时优先级99永远高于所有nice档位的普通任务,即便后者nice是-20。两者不在同一个维度。

2.5 优先级倒置:实时系统的暗坑

把任务改成高优先级并不代表万事大吉。一个经典问题是优先级倒置:低优先级普通任务持有一把锁,高优先级实时任务想拿同一把锁,反而被低优先级的任务阻塞,导致高优先级任务的延迟被拉高。如果低优先级恰好又被其他普通任务抢占,情况更糟。Linux内核默认启用优先级继承,在一定程度上能缓解实时互斥锁的问题,但如果你用的是用户态的进程间锁或某些不参与优先级继承的同步原语,还是会出现延迟尖刺。

在ROS2的实践中,我通常建议:强实时线程之间不要共用复杂锁,数据交换用无锁队列或多发布者单订阅者模式;锁解决不了的同步问题,用直通绑定的DDS共享内存白名单也能化解大半。

3. 实操:把实时优先级真正跑起来

3.1 先用chrt命令验证调度策略

不管代码怎么改,先学会用chrt查状态。查看某个进程当前调度策略和优先级:

chrt -p <PID>

输出类似:

pid 1234's current scheduling policy: SCHED_OTHER pid 1234's current scheduling priority: 0

随手把某个关键线程切到实时策略:

sudo chrt -f -p 60 1234

-f是SCHED_FIFO,-p后跟优先级,最后是PID。切到RR则用-r。回到普通策略用-o,此时优先级设0即可。

要特别留意权限问题:非root用户默认无权限设置实时优先级,会报Operation not permitted。生产环境要给特定二进制的可执行文件授予实时调度的能力,可以这样:

sudo setcap cap_sys_nice+ep /usr/local/bin/your_robot_node

这样普通用户起来也能设置实时优先级,不需要整个进程用root跑,安全性更好。我之前一直用root启动所有节点,有次调整权限模型时才发现,实时调度权限用capability收口要干净得多。

3.2 在ROS/ROS2节点代码里设置线程策略

命令行chrt适合调试,真正落生产环境还是在代码里直接设置。ROS2节点通常有多线程执行器,每个线程都是从节点内部创建的。你在节点构造函数里把自己当前这个线程改成实时调度是最直接的方式:

#include <pthread.h> #include <sched.h> void set_realtime_scheduler(int priority) { struct sched_param param; param.sched_priority = priority; int ret = pthread_setschedparam(pthread_self(), SCHED_FIFO, &param); if (ret != 0) { // 错误处理,通常是权限不足 } }

要点是必须在业务循环开始前调用。如果是在某个回调函数里调用,线程可能已经跑普通策略一段时间了,虽然改完也有效,但前面这段窗口期延迟不受控。更推荐的写法是专门给关键线程起一个名字,用pthread_setname_np标记,然后用ps -eLo pid,tid,comm,policy,rtprio或top -H观察,非常直观。

ROS1场景类似:nodelet管理线程的地方有时不一样,最简单的办法是写一个小的辅助函数在节点构造函数里调用pthread_setschedparam。需要注意,ROS1的定时器线程不一定就是调用构造函数的那条线程,rospy.Timer底层会创建单独的线程,你需要给那条具体线程设策略。ROS2的executor线程相对好定位,尤其是用SingleThreadedExecutor时,构造函数里pthread_self()就是唯一执行回调的线程。

3.3 用systemd启动配置来声明实时属性

我最近几个项目都改用systemd管理机器人节点了,unit文件里可以直接声明调度策略,省得在代码里硬编码:

[Service] ExecStart=/usr/local/bin/control_node CPUSchedulingPolicy=fifo CPUSchedulingPriority=60 CPUAffinity=2

CPUSchedulingPolicy支持other、fifo、rr,CPUAffinity支持绑核。这个声明比在代码里设置有个额外好处:service文件本身就是配置文档,换机器部署时看一眼就知道这个节点是什么调度策略、绑了哪个核。这比把参数埋在某处配置中心里要直观得多。

配合systemd还有个好处:可以按依赖关系调整启动顺序。实时节点间如果有启动链路要求,先用Requires=和After=编排好,避免出现A节点已经实时运行、B节点还在初始化的情况。

3.4 小心实时带宽限制:sched_rt_runtime_us

系统默认对实时任务有带宽限制,防止实时任务100%占满CPU导致普通任务完全饿死。相关参数是:

/proc/sys/kernel/sched_rt_period_us /proc/sys/kernel/sched_rt_runtime_us

默认值通常是1000000和950000,意味着每个周期内实时任务最多跑95%,剩下5%留给普通任务。这个保护机制本身是好事,但它会在关键时刻给你添乱:如果你的实时任务在某个时间窗口内运行时间超过95%,内核会强制它进入throttled状态,静默200ms,表现就是你的实时任务周期性休眠,延迟曲线出现一条条等距的尖峰。而且这种节流是全局的,不是按任务算的。

调试排障时可以临时关掉限制:

echo -1 > /proc/sys/kernel/sched_rt_runtime_us

生产环境不建议全局关闭,更合理的做法是用cgroup给特定的实时进程组单独放宽限制。比如把实时节点放到一个专属cgroup,在这个cgroup里关闭带宽限制,而不是影响整个系统。

3.5 CPU隔离:给实时线程一个清净的核

调度策略只是第一层,CPU亲和性是第二层。即使你已经把控制线程改成SCHED_FIFO高优先级,内核中断、定时器tick、RCU回调仍然可能在同一核上打扰它。要让延迟极致稳定,就得做CPU隔离。

内核启动参数里可以加:

isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3

isolcpus代表这些核不进普通调度范围,用户态任务默认不会分到这些核上,必须显式绑定才会用。nohz_full关闭隔离核上的周期性定时器tick,进一步减少噪声。rcu_nocbs把RCU回调挪走,避免隔离核上积累回调任务。

然后实时线程绑到隔离核上:

taskset -c 2 /usr/local/bin/control_node

做完这一步,控制线程在隔离核上运行,几乎只跟自己任务打交道,延迟可以降到个位数十微秒级别。这套配置在极端抖动场景效果非常明显,我实测过对比:非隔离非实时策略最大延迟8ms+,改成隔离核+FIFO策略后最大延迟60~80us,下降了两个数量级。代价是这两个核不能干其他活,等于空出来给关键任务专用。

4. 机器人场景怎么分配调度策略优先级

4.1 先给任务分好类再动手

在动手改调度策略前,建议先画一张任务清单,把节点或线程按实时性需求分档:

任务类型代表任务推荐策略推荐优先级是否建议绑核
强实时电机控制、里程计解算、安全监测SCHED_FIFO50~65是,绑隔离核
准实时激光雷达回调、路径跟踪、TF发布SCHED_FIFO30~45可选
普通业务建图、定位、日志、可视化SCHED_OTHERnice 0否
系统守护看门狗、心跳SCHED_FIFO80+是

这只是一个参考模板,实际按项目来调。趋势上,底层控制任务的优先级要明显高于建图定位这类计算密集型任务,因为路径规划晚算几毫秒问题不大,控制循环晚几毫秒底盘可能就抖了。

4.2 具体优先级数值的选择经验

这是我个人反复实验后的经验区间:

  • 优先级1~10:留给不太紧急但需要实时调度的任务,比如数据录像触发、状态发布。
  • 优先级30~45:准实时任务。主要给需要维持低延迟但不希望压过控制环的线程。
  • 优先级50~65:主控制循环、传感器核心驱动线程。这个区间是绝大多数机器人实时任务的黄金档位。
  • 优先级80以上:看门狗、心跳、安全逻辑这类“宁可自己卡死也不许机器失控”的任务。
  • 优先级99:尽量留给Kernel内部或极其关键的安全线程,普通项目不建议用最高档。

把优先级设太高并不总是好事。优先级数字只在你需要比别的实时任务抢先时才重要。设成99意味着任何其他实时任务都不能打断你,如果你这个任务本身出了问题,系统就彻底没有自救窗口了。优先级不是越高越光荣,它实际上是在排“谁先死”的顺序。

4.3 量化验证:用cyclictest看调度延迟

所有调度优化都要用数据说话。机器人圈子最常用的测试工具是cyclictest,来自实时测试套件:

sudo cyclictest -t1 -p 80 -i 1000 -l100000

参数含义:-t1单线程、-p80优先级、-i1000间隔1000us、-l100000跑10万次。它会统计每次唤醒的实际时间与目标时间差,输出最小值、平均值、最大延迟。

在一个干净的普通系统上跑,最大延迟几百微秒很正常;做了实时优化后应该能降到几十微秒。如果把隔离核+FIFO都配好,多数机器能达到20~50us以内。我在X86工控机上的经验是:

配置状态平均延迟最大延迟
默认CFS无绑核150us左右5ms~20ms,不稳定
SCHED_FIFO,未绑核30~50us200us~800us,受中断影响
SCHED_FIFO + 隔离核10~20us30~60us,稳定

每次修改调度策略后,建议跑几轮cyclictest对比再做决定,不要只看一两次的偶然现象。数据对不上,那多半是还有中断没挪走,或者带宽限制在起作用。

5. 常见问题与排查技巧实录

5.1 设置实时优先级总是Operation not permitted

这个问题出现频次排第一。原因基本三选一:当前用户没有CAP_SYS_NICE权限、容器里未开放对应capability、或者ulimit -r设为0限制了实时优先级上限。排查顺序建议先看ulimit -r,默认是0,需要调大:

ulimit -r unlimited

容器场景注意在docker或podman启动参数里加上--cap-add=sys_nice。如果进程是systemd管理的,加上LimitRTPRIO=99。

如果跑在受管容器里,还要确认该容器确实允许操作scheduler设置。我踩过一次坑:在宿主机上怎么调都行,容器里死活设置失败,查到最后就是容器的capability白名单没加。把sys_nice加进去就好了。

5.2 设完FIFO优先级,系统直接卡死

典型场景:一个线程设成SCHED_FIFO,代码里恰好有个异常分支导致它疯狂循环,没有任何sleep或阻塞。优先级高意味着它不会被普通的任务抢走CPU,连top都调度不过来,整个核被它锁死。如果你把该线程绑到了唯一的核上,那整个系统就瘫痪了。

应对策略很朴素:所有实时线程必须保证路径上必有阻塞点。即使任务逻辑上是纯计算,也建议在循环末尾加一个极短睡眠或条件等待,给其他任务喘息。另外至少保留一个核不纳入实时高优先级范围,留给登录交互和应急排查。我在所有项目里都保留了这个规矩:隔离核只做实时任务,系统管理核永远保持普通调度。

5.3 实时任务周期莫名变长:被带宽节流了

前文提到sched_rt_runtime_us的全局限制。遇到这个坑时你会觉得程序逻辑没问题,但实时任务每隔一段时间就卡一下,周期从1ms变成约200ms间隔的“周期性停顿”。排查方法很简单,直接看:

cat /proc/stat | grep rt_

rt_throttled数值如果在持续增长,说明节流正在发生。对策是按3.4节的方式给这个任务专属的cgroup放行,而不是全局关闭保护功能。

5.4 优先级设了但延迟没有变化

检查一下是不是根本没有设置成功。有几种可能:线程设置的是SCHED_FIFO,但实际并不是你预期的那条线程在执行业务回调;或者ROS2用默认线程池,多个回调挤在几条线程里,实时只覆盖了其中一条;还有一种情况是设置了FIFO,但没有绑核,中断仍然频繁打断执行。

我通常用两步排查:先看线程名与PID,用ps -eLo pid,tid,comm,policy,rtprio确认目标线程;再用perf sched或者trace-cmd看看关键线程的唤醒延迟分布。确认策略落实了,再谈进一步优化。

5.5 偶发抖动,难以复现

这类问题最容易让人头疼,延迟尖峰几百微秒到几毫秒不等,发生概率很低,但偶尔出现一次就足以让控制环路出问题。经验上优先怀疑三个方向:中断干扰未隔离、实时带宽节流偶发触发、某些低优先级任务持有锁后又被rt任务抢占导致连锁。先用/proc/interrupts看目标核上的中断频率;再把隔离核配齐;最后才考虑代码内锁和优先级倒置问题。

我遇到过一次非常隐蔽的抖动,最终定位到是某网卡驱动的中断一股脑涌到隔离核上,网卡本身优先级比任何用户态实时线程都高,所以FIFO再高也挡不住它。用irqaffinity把中断全部挪到管理核后,最大延迟立刻降了一个量级。

6. 最后分享一点个人心得

回到开头那个移动底盘项目。最终配置是:控制线程放在隔离核2上,SCHED_FIFO优先级60,里程计线程优先级55,建图节点放到核0和核1的CFS默认区,日志和监控全部留在核3。之前那个动不动十几毫秒的延迟彻底消失,控制指令稳定在几百微秒内完成。后来我把这套参数整理成systemd模板,所有新项目只要按任务清单填优先级就行。

实时调度优化这东西,真正难的不是理解某个命令或者某个策略,而是要形成一个稳定的整体框架:先给任务分类,再配合chrt实测,然后用内核参数把噪声隔绝在外,最后用cyclictest持续监控作为回归依据。这个过程没有一次性的银弹,但只要你把调度器这个底层环节控制住,上层应用优化才会真正落到实处。

相关新闻

对齐的幻觉:AI模型对齐中的认知陷阱与实操避坑指南

对齐的幻觉:AI模型对齐中的认知陷阱与实操避坑指南

1. 从“对齐的幻觉”说起&#xff1a;一个被过度简化的复杂命题“对齐”这个词&#xff0c;在过去两年里被提及的频率高得离谱。不管是大模型训练、产品设计&#xff0c;还是团队协作&#xff0c;似乎只要挂上“对齐”两个字&#xff0c;问题就解决了一半。但实际情况是&#x…

2026/10/20 6:50:43 阅读更多 →
农业害虫检测数据集构建与CNN识别模型实战解析

农业害虫检测数据集构建与CNN识别模型实战解析

做农业害虫识别&#xff0c;最让人头疼的往往不是算法选型&#xff0c;而是数据本身。我在这个方向上折腾了快两年&#xff0c;踩过的坑比写过的代码还多。这套关于农业害虫检测数据集与CNN识别模型的项目&#xff0c;本质上解决的核心问题就一个&#xff1a;怎么让模型在田间地…

2026/10/20 6:50:43 阅读更多 →
pascal-5i数据集小样本分割实战:fold划分、episodic采样与避坑指南

pascal-5i数据集小样本分割实战:fold划分、episodic采样与避坑指南

简介&#xff1a;Pascal-5i 数据集面向小样本学习方向的研究者与算法工程师&#xff0c;基于经典 PASCAL VOC 的 20 个类别&#xff0c;通过采样策略划分基础类别与新类别&#xff0c;支持 5-way 1-shot 与 5-way 5-shot 场景&#xff0c;用于评估模型在极少样本下的泛化与适应…

2026/10/20 6:50:43 阅读更多 →

最新新闻

纯.NET自绘打印模板设计器:拖拽式可视化与动态渲染

纯.NET自绘打印模板设计器:拖拽式可视化与动态渲染

简介&#xff1a;这是一套面向.NET开发者的C#可视化打印模板设计源码&#xff0c;纯.NET实现、不依赖任何第三方控件&#xff0c;适合需要为发票、报告、证书、标签及单据类业务快速搭建打印能力的初中级工程师。资源提供模板编辑器、图形设计工具与布局管理器等组件&#xff0…

2026/10/20 7:37:06 阅读更多 →
token预算与分块预填充:大模型推理调度的核心引擎

token预算与分块预填充:大模型推理调度的核心引擎

1. 为什么“token预算”不是个玄学概念&#xff0c;而是调度器的血压计你有没有遇到过这样的情况&#xff1a;模型明明还有算力余量&#xff0c;推理请求却开始排队&#xff1b;或者刚压测完吞吐量&#xff0c;一上真实业务流量就卡在预填充阶段&#xff0c;GPU利用率掉到30%以…

2026/10/20 7:37:06 阅读更多 →
许愿机:下一代开发者协作范式的本质跃迁

许愿机:下一代开发者协作范式的本质跃迁

1. 这不是命名迭代&#xff0c;是人机关系的临界点突破“Coding Agent”这个词我第一次听到是在2022年底&#xff0c;当时某开源社区里几个开发者用PythonLangChain搭了个能读GitHub PR描述、自动生成review comment的小工具&#xff0c;大家笑着叫它“coding agent”——像给程…

2026/10/20 7:37:06 阅读更多 →
低质量图像增强实战:从传统算法到深度学习的完整链路解析

低质量图像增强实战:从传统算法到深度学习的完整链路解析

做低质量图像增强这个课题&#xff0c;是我在调研了好几个月的传统算法之后才真正意识到方向应该怎么选的。那时候我手上有一批夜间监控画面和手机随手拍的暗光照片&#xff0c;第一反应是去试各种老牌图像处理方案&#xff1a;直方图均衡化、伽马校正、维纳滤波、BM3D&#xf…

2026/10/20 7:37:06 阅读更多 →
PIDNet实时语义分割模型:原理、环境配置与训练实战

PIDNet实时语义分割模型:原理、环境配置与训练实战

1. 为什么PIDNet能在语义分割里杀出一条路&#xff1a;先搞清楚它在解决什么问题在做环境配置和代跑训练之前&#xff0c;我建议你先花十分钟想明白一件事&#xff1a;PIDNet到底比之前的实时语义分割模型强在哪。如果你只是照着README把环境装好、把权重下下来、跑两张图就收工…

2026/10/20 7:37:06 阅读更多 →
2003-2025美国每日野火烟雾数据:PM2.5暴露评估与健康影响研究指南

2003-2025美国每日野火烟雾数据:PM2.5暴露评估与健康影响研究指南

这两年做环境健康方向的数据分析&#xff0c;我有一个很深的感触&#xff1a;野火烟雾数据的价值&#xff0c;被严重低估了。以前大家做野火研究&#xff0c;最关心的是火点本身——哪儿烧了、烧了多大、过火面积多少。但真正影响几千万人口健康的&#xff0c;其实是烟雾。烟雾…

2026/10/20 7:36:06 阅读更多 →

日新闻

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实现详解

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

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

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

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

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

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

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →