行为树与py_trees:从状态机到模块化AI决策的Python实践
1. 从状态机到行为树为什么我们需要更优雅的决策逻辑如果你做过游戏AI、机器人控制或者任何需要复杂决策逻辑的系统大概率都跟状态机打过交道。状态机FSM是个好东西直观、简单画几个圈圈和箭头就能把逻辑理清楚。但项目稍微复杂一点状态数量开始指数级增长箭头多到能织成一张蜘蛛网的时候噩梦就开始了。添加一个新行为你可能需要修改三四个状态小心翼翼地连接新的转换条件生怕碰断了哪根线导致整个系统崩溃。调试更是痛苦你很难一眼看出当前决策的完整上下文只能跟着日志在状态之间跳来跳去。行为树Behavior Tree就是为了解决这种“面条式逻辑”而生的。我第一次接触行为树是在一个机器人导航项目里当时的状态机已经臃肿不堪。行为树给我的第一印象是它把“做什么”行为和“什么时候做”决策逻辑清晰地分开了。整个树形结构就像公司的组织架构图根节点是CEO下面有各个部门分支部门里又有具体的执行员工叶子节点。CEO不关心具体怎么扫地、怎么写代码他只关心市场部这个季度的目标一个子任务完成了没有。没完成那就换策略部试试。这种“职责分离”的思想让代码的模块化、可读性和可复用性上了好几个台阶。py_trees就是一个用 Python 实现的行为树库。选择它一方面是因为 Python 的快速原型能力在算法验证和逻辑调试阶段效率极高另一方面py_trees的设计非常干净提供了丰富的内置节点类型和实用的可视化、日志工具能让开发者聚焦于行为逻辑本身而不是框架的细枝末节。无论是做学术研究、机器人仿真如ROS2中的导航栈大量使用行为树还是游戏原型开发它都是一个得力的工具。接下来我会结合自己的踩坑经验带你拆解py_trees的核心并重点聊聊那个最容易让人困惑的Fallback节点。2. 行为树核心架构与py_trees设计哲学2.1 行为树的基本组成单元节点行为树的所有魔力都源于几种基础类型的节点。在py_trees中所有节点都继承自Behaviour这个基类。理解每个节点的生命周期和返回值是写好行为树的关键。1. 控制流节点Composite决策的大脑这是树的枝干负责控制执行流程。py_trees提供了几种最经典的类型Sequence序列按顺序执行子节点。当前一个子节点返回SUCCESS时才执行下一个如果某个子节点返回RUNNING则下次tick会从它继续如果某个子节点返回FAILURE则整个Sequence立即返回FAILURE。你可以把它理解为“必须全部成功”的逻辑与AND。# 例如走到冰箱前 - 打开冰箱门 - 拿出可乐 drink_seq py_trees.composites.Sequence(name“拿饮料”, memoryTrue) # memoryTrue 表示记住正在运行的子节点下次tick从中断处继续Selector选择器 / Fallback后备这是重点我们后面会详细展开。它按顺序执行子节点直到有一个返回SUCCESS或RUNNING则停止。它体现了“尝试多个方案直到一个可行”的逻辑。Parallel并行同时执行所有子节点并根据设定的成功/失败阈值如“全部成功”、“多数成功”来决定自身返回状态。常用于需要同时监控多个条件或执行多个动作的场景。2. 装饰器节点Decorator功能的增强器它只有一个子节点用于修改或增强该子节点的行为。比如Inverter将子节点的结果取反SUCCESS变FAILURE反之亦然。Timeout为子节点的执行设置时间限制。Repeat重复执行子节点指定次数或直到满足条件。Condition等待某个条件变为真然后再执行子节点。这常用于将“等待事件”这个动作优雅地嵌入到树中。3. 执行节点Leaf实际干活的叶子这是树的末端包含具体的业务逻辑。主要分两种Action动作执行一个具体的操作如“移动”、“抓取”。它通常需要多个tick才能完成期间返回RUNNING完成后根据结果返回SUCCESS或FAILURE。Condition条件检查某个布尔条件是否成立如“电池电量是否大于20%”、“目标是否在视野内”。它应该在一个tick内完成立刻返回SUCCESS或FAILURE不应该返回RUNNING。注意py_trees中Condition既是一种装饰器节点类型也是叶子节点的一种。作为叶子节点时它是一个瞬时检查作为装饰器时它是一个阻塞式的等待节点。要根据上下文区分。2.2py_trees的运行时Tick 机制行为树不是一次性执行的函数它需要在游戏循环或机器人控制循环中不断被“驱动”。这个驱动过程叫做tick。一次tick的流程可以简化为从根节点开始tick。根据当前节点的类型和状态决定下一个要tick的子节点。该子节点执行自己的逻辑可能是瞬间的条件检查也可能是一个耗时的动作的一小步并返回状态SUCCESS/FAILURE/RUNNING。状态沿着树向上传递影响父节点如Sequence,Selector的决策。本次tick结束。下一次tick到来时树会从上次中断的地方RUNNING的节点或根据新的决策逻辑继续执行。这种机制使得行为树能很好地处理需要长时间运行的任务如“巡逻”同时又能即时响应更高优先级的任务如“被攻击时躲避”。2.3 可视化与调试让逻辑“看得见”py_trees最棒的特性之一就是内置了强大的可视化工具。你可以通过py_trees.display.render_dot_tree将行为树导出为.dot文件然后用 Graphviz 生成图片。更强大的是py_trees.visitors.DisplaySnapshotVisitor它可以在每次tick后在终端用彩色字符和缩进实时打印出树的快照哪个节点正在运行、哪个成功、哪个失败一目了然。这对于调试复杂的行为逻辑至关重要能让你直观地看到决策流是如何在树中流动的。3. 深度解析Selector 与 Fallback 节点的异同与陷阱这是行为树概念中最容易混淆也是py_trees里需要特别注意的一点。网络上很多资料对这两个词混用但在py_trees的语境下它们有明确的、有时甚至是反直觉的区别。3.1 定义与标准行为首先记住它们的核心逻辑按顺序执行子节点直到有一个子节点成功。Selector这是更广义、更常见的名称。它的行为如上所述从左到右执行子节点遇到第一个返回SUCCESS或RUNNING的子节点就停止并返回该状态。如果所有子节点都返回FAILURE则它返回FAILURE。Fallback在py_trees中Fallback是Selector的一个别名。也就是说py_trees.composites.Selector和py_trees.composites.Fallback指向的是同一个类。它们的行为是完全一致的。那么问题来了既然一样为什么要有两个名字这源于历史和行为树理论的发展。在一些文献和早期实现中Selector和Fallback可能被赋予细微不同的语义例如对RUNNING状态的处理记忆策略。但py_trees的作者 Daniel Stonier 在设计和文档中明确将它们统一了。使用Fallback更多是一种语义上的强调提醒读代码的人这个选择器节点是用来实现“后备计划”或“故障恢复”逻辑的。3.2 经典用例故障恢复链这是Fallback节点最闪耀的地方。假设我们有一个机器人抓取物体的任务grasp_fallback py_trees.composites.Fallback(name“抓取策略” memoryFalse) grasp_fallback.add_children([ py_trees.behaviours.Success(name“尝试精准抓取”), # 条件目标静止且清晰 py_trees.behaviours.Success(name“尝试区域扫掠”), # 条件目标大致位置已知 py_trees.behaviours.Success(name“移动到目标前手动干预”) # 最终后备 ])这棵小树表达的逻辑是首先尝试“精准抓取”比如用视觉伺服。如果成功了SUCCESS整个Fallback成功任务结束。如果精准抓取失败了FAILURE比如视觉丢失则尝试下一个方案“区域扫掠”比如让机械臂在目标区域做一次网格化搜索。如果成功任务结束。如果区域扫掠也失败了则执行最终方案“移动到目标前手动干预”。这个方案必须被设计为尽可能总能成功比如只是移动到某个安全位置并报警。如果连最后一个子节点都失败了那整个Fallback才宣告失败。这种结构将不同的恢复策略清晰地分层优先级从高到低代码的可读性和可维护性极佳。添加一个新的恢复策略只需要在合适的位置插入一个新的子节点即可。3.3 关键参数memory的作用与抉择Selector/Fallback节点有一个至关重要的布尔参数memory它决定了节点如何记住子节点的RUNNING状态。memoryFalse默认失忆模式。每次tick都从第一个子节点重新开始评估。即使上次tick时第二个子节点返回了RUNNING这次tick也会先检查第一个子节点是否已经可以成功了。这适用于条件随时可能变化的场景。例如一个“反应式”选择器reactive_selector py_trees.composites.Selector(name“反应式选择” memoryFalse) reactive_selector.add_children([ IsEnemyVisible(), # 条件看见敌人吗 PatrolRoute() # 动作执行巡逻 ])这里我们希望机器人持续监控“是否看见敌人”。即使上一帧在巡逻PatrolRoute返回RUNNING这一帧如果敌人突然出现IsEnemyVisible返回SUCCESS选择器应该立即切换到第一个子节点可能触发“攻击”行为。如果memoryTrue选择器会“卡”在巡逻动作上无法及时响应敌人出现的瞬间。memoryTrue记忆模式。一旦某个子节点返回RUNNING选择器就会“锁定”它后续的tick会直接继续执行这个RUNNING的子节点跳过前面所有子节点的重新评估。这适用于执行一个需要时间完成、且不应被高优先级条件打断的动作链。通常用于Sequence节点内嵌的Fallback。# 一个需要连续完成、且有后备方案的任务序列 task_seq py_trees.composites.Sequence(name“复杂任务” memoryTrue) recover_fallback py_trees.composites.Fallback(name“带恢复的步骤” memoryTrue) recover_fallback.add_children([ PrimaryApproach(), # 主要方法 RecoveryAction() # 恢复方法 ]) task_seq.add_children([MoveToLocation(), recover_fallback, FinalAction()])在这个例子里recover_fallback的memoryTrue确保了一旦开始执行PrimaryApproach并进入RUNNING状态就会一直执行它直到结束成功或失败而不会在每次tick时都重新去尝试PrimaryApproach可能因为瞬时条件变化而失败。只有它彻底失败后才会切换到RecoveryAction。选择建议对于条件检查Condition节点居多的Fallback通常用memoryFalse保持响应性。对于动作Action节点居多的Fallback尤其是在Sequence内部时使用memoryTrue来保证动作的连续执行。这是一个非常容易出错的地方需要根据具体业务逻辑仔细斟酌。4. 构建一棵健壮的行为树从设计到实现4.1 设计模式与最佳实践保持树的扁平化尽量避免过深的嵌套。如果一棵子树过于复杂考虑将其封装成一个新的、具有更高层级语义的复合节点或者拆分成多个并行树。条件与动作分离尽量使用装饰器节点或独立的Condition叶子节点来检查条件而不是把条件判断硬编码在Action节点内部。这使得条件可以被多个行为共享和复用。使用黑板Blackboard进行数据共享py_trees提供了Blackboard这是一个全局的键值存储。节点之间可以通过读写黑板来传递信息而不是通过紧耦合的函数参数。例如一个“检测目标”的节点将目标坐标写入黑板后续的“移动至目标”节点再从黑板中读取。这极大地降低了节点间的耦合度。为节点起好名字节点的name参数在调试和可视化时至关重要。使用像“IsBatteryLow?”、“NavigateTo(Kitchen)”这样具有明确行为描述的名字而不是“check1”、“actionA”。4.2 一个完整的机器人巡逻与反应示例假设我们设计一个简单的室内服务机器人它的行为包括日常巡逻、电量低时自动回充电站、遇到障碍物时绕行。import py_trees import time class CheckBattery(py_trees.behaviour.Behaviour): 检查电量是否低于20% def __init__(self, name): super().__init__(name) self.blackboard self.attach_blackboard_client() self.blackboard.register_key(key“battery_level”, accesspy_trees.common.Access.READ) def update(self): if self.blackboard.battery_level 20: return py_trees.common.Status.SUCCESS else: return py_trees.common.Status.FAILURE class PatrolAction(py_trees.behaviour.Behaviour): 执行巡逻动作 def __init__(self, name): super().__init__(name) self._patrol_complete False def initialise(self): # 开始巡逻重置状态 print(f“[{self.name}]开始巡逻路线...”) self._patrol_complete False def update(self): # 模拟巡逻进行中 time.sleep(0.1) # 模拟耗时 if not self._patrol_complete: print(f“[{self.name}]巡逻中...”) # 这里应该是控制机器人移动的真实代码 # 假设5次tick后巡逻完成 self._counter getattr(self, ‘_counter’, 0) 1 if self._counter 5: self._patrol_complete True self._counter 0 return py_trees.common.Status.RUNNING else: print(f“[{self.name}]巡逻完成”) return py_trees.common.Status.SUCCESS def terminate(self, new_status): # 清理工作 if new_status py_trees.common.Status.INTERRUPTED: print(f“[{self.name}]巡逻被中断”) # 构建行为树 root py_trees.composites.Parallel(name“Root”, policypy_trees.common.ParallelPolicy.SuccessOnAll()) # 分支1高优先级 - 电量管理 power_management py_trees.composites.Sequence(name“电源管理” memoryFalse) power_management.add_children([ CheckBattery(“电量低于20%”), py_trees.behaviours.Success(name“执行回充”) # 简化实际是复杂动作 ]) # 分支2主行为 - 巡逻但遇到障碍能绕行 main_behavior py_trees.composites.Sequence(name“主行为” memoryTrue) # 巡逻动作本身可能失败如遇到永久障碍因此用Fallback包装 patrol_with_recovery py_trees.composites.Fallback(name“巡逻与恢复” memoryTrue) patrol_with_recovery.add_children([ PatrolAction(“沿A路线巡逻”), py_trees.behaviours.Success(name“执行绕行”) # 简化实际是绕行动作 ]) main_behavior.add_child(patrol_with_recovery) root.add_children([power_management, main_behavior]) # 初始化黑板 blackboard py_trees.blackboard.Blackboard() blackboard.battery_level 50 # 初始电量50% # 创建并运行树 tree py_trees.trees.BehaviourTree(root) tree.setup(timeout15) for i in range(20): tree.tick() # 每次tick模拟一帧 # 模拟电量随时间下降 blackboard.battery_level - 2 if blackboard.battery_level 0: blackboard.battery_level 0 time.sleep(0.5)在这棵树中Parallel根节点允许“电源管理”和“主行为”两个分支同时进行。SuccessOnAll策略要求两者都成功但通常其中一个会是常驻的监控循环。“电源管理”是一个Sequence只有电量检查成功才会执行回充。“主行为”是一个Sequence里面包含一个Fallback。Fallback首先尝试巡逻如果巡逻彻底失败比如路线被堵死则启动绕行方案。这里Fallback的memoryTrue保证了巡逻动作的连续性。4.3 调试技巧使用 Snapshot Visitor在开发时强烈建议将DisplaySnapshotVisitor添加到你的行为树中tree py_trees.trees.BehaviourTree(root) tree.add_visitor(py_trees.visitors.DisplaySnapshotVisitor()) tree.setup(timeout15) for i in range(10): tree.tick() time.sleep(1)这会在控制台输出彩色化的树状态让你清晰地看到每一帧哪个节点是RUNNING绿色、SUCCESS蓝色、FAILURE红色。这是定位逻辑错误最快的方法。5. 常见问题、性能考量与进阶方向5.1 典型问题排查表问题现象可能原因排查步骤与解决方案行为树“卡住”不再响应某个Action节点永远返回RUNNING或陷入死循环。Selector/Fallback的memoryTrue导致无法跳出。1. 使用DisplaySnapshotVisitor查看哪个节点常绿RUNNING。2. 检查该Action节点的update逻辑确保在完成或失败时正确返回SUCCESS/FAILURE。3. 检查包裹该节点的Selector/Fallback的memory参数是否合理。对于需要被中断的动作其父选择器应使用memoryFalse。高优先级行为无法打断低优先级行为Selector/Fallback使用了memoryTrue且当前RUNNING的子节点是低优先级行为。将高优先级行为所在的Selector/Fallback设为memoryFalse。确保高优先级行为是选择器中的第一个子节点。考虑使用Parallel节点配合SuccessOnOne策略来实现真正的抢占。条件检查不稳定行为频繁切换条件节点检查的传感器数据有噪声导致结果在SUCCESS和FAILURE间抖动。1. 为条件节点添加滞后作用Hysteresis。例如“电量低”条件在低于18%时触发但“电量充足”条件要等到高于25%时才触发避免在20%附近震荡。2. 使用装饰器节点如py_trees.decorators.RunningIsFailure将RUNNING状态视为失败可以强制选择器继续尝试后续节点但需谨慎使用。行为树变得臃肿难以维护节点和层级过多逻辑耦合紧密。1.封装子树将功能相关的节点组封装成一个新的自定义Behaviour类对外提供简洁的接口。2.利用黑板减少节点间直接的参数传递通过黑板共享状态。3.考虑分层或并行的多棵树将完全不相关的功能模块拆分成独立的行为树由一个更顶层的调度器管理。5.2 性能考量行为树每一帧都要从根节点tick一次虽然节点逻辑通常很简单状态判断和函数调用但在节点数量极大成千上万或tick频率极高如1000Hz时仍需注意性能。避免在update()中进行繁重计算尤其是Condition节点应快速检查状态。复杂的感知或规划算法结果应提前计算好存入黑板供条件节点读取。谨慎使用memoryFalse这会导致每次tick都重新评估选择器前面的所有子节点即使它们之前失败了。如果这些子节点包含昂贵的条件检查会成为性能瓶颈。在这种情况下可以考虑调整树的结构或者将昂贵的检查结果缓存一段时间。节点的初始化和终止initialise()和terminate()方法可能包含资源分配和释放操作。确保它们被高效调用避免不必要的开销。5.3 进阶方向当你熟悉了基础可以探索以下方向让行为树更强大自定义装饰器与复合节点py_trees的框架允许你轻松扩展。例如你可以创建一个Cooldown装饰器让子节点执行成功后在一段时间内不再被触发或者创建一个RandomSelector复合节点随机选择一个子节点执行。与ROS2等机器人框架深度集成py_trees_ros是py_trees的ROS2扩展它提供了与ROS2生命周期、话题、服务、动作客户端无缝对接的节点类型是构建ROS2机器人复杂行为系统的标准工具。行为树与规划结合行为树擅长反应式控制和任务编排但不擅长长序列规划。可以将行为树与规划器如用于导航的MoveBase、用于抓取的MoveIt结合。行为树负责高层任务调度和故障恢复规划器负责生成具体的运动轨迹。可视化编辑工具虽然py_trees的代码定义很清晰但对于大型树图形化编辑更有优势。可以探索像Groot需要配合支持py_trees的中间件或基于Web的自研编辑器实现拖拽式构建行为树并导出为py_trees代码。从我自己的项目经验来看行为树不是一个“银弹”它最适合的场景是那些具有清晰层次化决策逻辑、且需要良好模块化和可观测性的系统。它不能替代状态机在简单流程控制上的简洁也不能替代规划算法在复杂解空间搜索上的能力。但它作为连接高层任务规划与底层动作执行的“粘合剂”在构建可靠、易调试、易扩展的自主系统时其价值是无可替代的。理解Selector/Fallback的微妙之处善用memory参数是能否用好py_trees的关键一步。

相关新闻

Pandas DataFrame.append()弃用:性能陷阱与高效数据合并方案详解

Pandas DataFrame.append()弃用:性能陷阱与高效数据合并方案详解

1. 问题缘起:一个“过时”的错误如何成为数据处理的拦路虎 如果你最近在升级了pandas版本后,运行一段曾经完美工作的数据处理脚本,突然遇到了 AttributeError: ‘DataFrame‘ object has no attribute ‘append‘ 这个报错,先别…

2026/10/5 14:02:29 阅读更多 →
Claude Cowork重塑AI办公:从Copilot到协同工作的范式转移

Claude Cowork重塑AI办公:从Copilot到协同工作的范式转移

1. 从“Copilot”到“Cowork”:AI办公的范式转移最近,如果你关注AI和办公软件,一定被“Claude杀入Office全家桶”这样的标题刷屏了。这背后,是Anthropic公司推出的Claude for Microsoft 365(内部代号“Cowork”&#x…

2026/10/5 6:59:20 阅读更多 →
腾讯鹅虾平台:零代码构建AI Agent,无缝集成QQ飞书钉钉

腾讯鹅虾平台:零代码构建AI Agent,无缝集成QQ飞书钉钉

1. 项目概述:当“养虾”不再是技术活 最近,腾讯悄悄上线了一个叫「鹅虾」的新玩意儿,在圈子里小火了一把。这名字乍一听有点摸不着头脑,但如果你最近关注过AI Agent(智能体)或者企业办公自动化,…

2026/9/29 6:11:57 阅读更多 →

最新新闻

医疗微调DeepSeek全流程:LoRA训练、验证与部署避坑指南

医疗微调DeepSeek全流程:LoRA训练、验证与部署避坑指南

简介:一份23页的PDF实操教程,面向算法工程师、医学信息化从业者及对大模型应用感兴趣的读者,围绕如何将DeepSeek微调成‘资深医生’辅助诊断模型展开。内容从医疗行业与大模型结合背景切入,介绍DeepSeek架构特点(多头注…

2026/10/5 14:02:23 阅读更多 →
从测试驱动到质量内建:一条通往持久质量的路

从测试驱动到质量内建:一条通往持久质量的路

做了这么多年软件质量相关的工作,我越来越觉得“测试驱动开发”和“质量内建”这两个词放在一起看特别有意思。TDD从十多年前开始流行,很多团队都认认真真地练过“红-绿-重构”循环,但真正坚持下来并且尝到甜头的并不多。这不是TDD本身的问题…

2026/10/5 14:02:23 阅读更多 →
DMR数字对讲机核心技术解析:从TDMA双时隙到系统落地

DMR数字对讲机核心技术解析:从TDMA双时隙到系统落地

在物流仓储、安保巡更、工地调度这些场景里待过的人,大概率已经见过DMR对讲机——机身印着大写的DMR字样,顶部带一块小液晶屏,按键比传统模拟机多出一倍。很多人第一次拿到这种机器,第一反应是“应该更高级”,但高级在…

2026/10/5 14:02:23 阅读更多 →
Ubuntu下FSL神经影像分析套件完整安装与避坑指南

Ubuntu下FSL神经影像分析套件完整安装与避坑指南

开学第二周,实验室新到的Ubuntu工作站总算登录进去了,导师甩给我一句话:“把FSL装上,下午组会用。”如果你是神经影像方向的学生,这个场面八成不陌生。FSL,全称FMRIB Software Library,是牛津大…

2026/10/5 14:02:23 阅读更多 →
ARC-AGI-3里程碑2:混合架构实现零样本抽象推理

ARC-AGI-3里程碑2:混合架构实现零样本抽象推理

1. 项目概述:这不是又一个AI玩具,而是一次对“真正智能”边界的硬核试探ARC-AGI-3 里程碑2,这个名字乍看像一串技术编号,但如果你在AGI(通用人工智能)社区泡过几天,就会知道它背后压着的分量——…

2026/10/5 14:02:23 阅读更多 →
遥感生态指数RSEI模型原理与GEE实现全解析

遥感生态指数RSEI模型原理与GEE实现全解析

这些年做生态环境遥感评估,我周围很多同行一开始都习惯用NDVI单指标来看一个区域的生态状况,但说实话,单看绿度太片面了。一个城市周边可能有大量农田,NDVI很高,但地表温度、建筑裸土占比这些生态压力因素完全没体现出…

2026/10/5 14:01:23 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

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

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

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

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/5 5:06:42 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/5 3:06:17 阅读更多 →

月新闻

我发现了一个新思路:用 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/4 11:40:45 阅读更多 →
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/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练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/4 20:14:29 阅读更多 →