首页/新闻资讯/正文详情

SUMO交通仿真入门:从零搭建微观交通场景的核心指南

发布时间:2026/9/25 7:33:20 来源:云帆数科 栏目:资讯中心
SUMO交通仿真入门:从零搭建微观交通场景的核心指南
第一次打开 SUMO 的人多半会和当年的我一样对着一个灰网格、几条绿线段发愣。Simulation of Urban MObility这个德国航空航天中心维护了十几年的开源微观交通仿真器在车路协同、自动驾驶决策验证、城市信号优化这些领域已经被用得很广。它也确实强大但入门门槛真实存在net.xml、rou.xml、netconvert、duarouter、TraCI 这一连串名词砸过来很容易让人在一周内放弃。这篇就想把“从一个完全不认识 SUMO 的状态到能跑通自己的第一个仿真场景”这条路上最关键的节点讲透。适合刚接触 SUMO 的交通专业学生、做自动驾驶仿真的工程师以及所有需要在虚拟路网上验证车流方案的人。1. 先搞懂 SUMO 的底层逻辑路网、需求与仿真器1.1 SUMO 是什么为什么值得花时间SUMO 是微观交通流仿真软件。“微观”意味着它把每一辆车当作独立个体来模拟每辆车有自己的跟驰行为、换道倾向、出发时间和可以感知的信号灯状态。这和一整条车流被压缩成几个流量参数的宏观模型完全不同所以它能回答“某个路口改完相位之后平均排队长度变化多少”“自动驾驶车辆在混行环境下会不会导致上下游交通振荡”这类问题。它免费、开源、跨平台而且不是玩具。SUMO 的文档里能看到几十种跟驰模型、换道模型还有一堆面向研究者的分析工具。更重要的是它提供 TraCI 接口外部程序可以在仿真运行过程中实时读取数据、修改信号灯状态、注入新车辆。做 V2X 仿真或者控制算法验证时这个能力几乎是刚需。当然免费开源的代价是学习曲线比较陡。不是功能难而是信息太分散文档是管用的但你得先知道该查哪一个文件。这篇相当于先把最核心的那几条线索给你捋顺。1.2 路网、需求、仿真器三个概念必须分清SUMO 把一次仿真拆成三个独立部分这是理解一切的基础。路网文件是静态的舞台通常叫 xxx.net.xml。它定义了节点坐标、路段几何、车道数量、限速、交叉口连接关系、信号灯位置。路网不是人画的 CAD 图纸它是机器可读的数据结构。你可以在 netedit 里画路网也可以通过命令行工具从 OpenStreetMap 数据自动转换或者直接手写 XML。需求文件是动态的演员一般是 xxx.rou.xml 或 xxx.trips.xml。它定义哪些车辆出发、从哪到哪、什么时候出发、用什么车型、最大速度多少。注意需求数据和路网数据是分开维护的。同一个路网你可以跑早高峰需求也可以跑平峰需求只需要替换需求文件。仿真器把舞台和演员放到一起逐秒推进这就是 sumo 和 sumo-gui 做的事。sumo 是无界面版本适合批量跑实验sumo-gui 带可视化窗口适合调试路网和观察现象。没有需求和路网中的任何一部分仿真都跑不起来。在实践中我见过不少新人把路线错误地写在路网文件里或者把信号灯配时写进需求文件最后报错。区分这三个角色之后绝大多数配置错误都能一眼定位。1.3 组件工具箱netconvert、netedit、duarouter、sumo 的分工SUMO 装好之后你会得到一堆可执行文件但常用的是四个。netconvert 负责格式转换最常见的用途是把 OpenStreetMap 的 .osm 数据转换成 SUMO 的 .net.xml 路网也可以在文本格式和二进制格式之间转换。netedit 是图形编辑器可以直接画路段、设置信号灯、编辑交通需求适合小范围精细修改。duarouter 负责路径计算输入是一堆只写了起终点的 trip 或 flow输出是每辆车实际走哪条路线的 route 文件。sumo 和 sumo-gui 是运行器一个无头一个带界面。一句话理解netconvert 管转格式netedit 管动手改duarouter 管算路sumo 管跑仿真。后面所有操作基本都在这些工具之间打转。2. 安装与环境准备别在起跑线卡住2.1 Windows / Linux / macOS 三条安装路线如果你用 Ubuntu 或 Debian 系的 Linux可以直接sudo apt install sumo sumo-tools装完版本可能不是最新但足够入门。用 Windows 的话去官网下载 zip 包解压到某个目录比如C:\SUMO然后把C:\SUMO\bin加入 PATH再建一个环境变量SUMO_HOMEC:\SUMO。macOS 用户最简单brew install sumo就能装完。还有一条通用路线是 condaconda install -c conda-forge sumo。好处是你可以在一个隔离环境里装不会污染系统坏处是 conda 的包更新频率有时候滞后。我个人的建议新手阶段哪个顺手用哪个不要为了版本纠结。真正影响你学不学得下去的是习惯养成和概念理解不是版本差那么 0.1。2.2 验证安装和准备 Python 环境装完先别急着画路网确认三件事。sumo --version netconvert --version python --version如果都能正常输出说明基本环境没问题。接下来设置 Python 的PYTHONPATH这一步很多人会漏。SUMO 的 Python 工具集放在 tools 目录下包括 randomTrips.py、netcheck.py 这些脚本以及 TraCI 的 Python 绑定库。如果PYTHONPATH没设置你会在import traci时直接碰到红色报错。Linux 下可以这样写进~/.bashrcexport SUMO_HOME/usr/share/sumo export PATH$PATH:$SUMO_HOME/bin export PYTHONPATH$SUMO_HOME/tools:$PYTHONPATH前提是你的包管理器把 sumo 装到了/usr/share/sumo。不同发行版路径可能有差异可以用dpkg -L sumo | grep tools查一下实际位置。Windows 用户则在环境变量里配置一样的变量名。2.3 一个值得坚持的工作目录习惯SUMO 项目文件多建议从一开始就给每个仿真场景一个独立目录并且按类型分开。比如net放路网相关demand放需求文件config放 sumocfg 配置文件output放仿真结果。听起来很基础但实际项目里一个路网改改弄弄就能产生十几个版本需求文件更多没有目录管理会在三天后彻底混乱。我自己的习惯是把整个场景目录丢进 Git 仓库每次改完路网或配置就提交一次。好处是改崩了可以随时回退而且能清楚地看到某个参数是哪个版本引进来的。SUMO 场景文件都是纯文本Git 做 diff 虽然不如代码文件直观但至少能帮你定位修改时间点。3. 一小时跑通第一个 SUMO 仿真3.1 用手写 XML 的方式快速建一个小路网不要急着导入真实地图先手工写一个三角环线路网。这个路网很小但包含三个节点、两条以上路段和交叉口连接关系足够跑通完整流程。先建node.xml定义节点。SUMO 使用平面直角坐标单位是米。nodes node idA x0 y0 typepriority/ node idB x1000 y0 typepriority/ node idC x500 y500 typepriority/ /nodes再建edge.xml定义路段。这里有个特别容易踩的坑SUMO 里的 edge 是单向的。你要想实现双向通行必须写两条方向相反的 edge。比如 A 到 B 有了ABB 到 A 还得有BA别指望系统自动给你补反向。edges edge idAB fromA toB numLanes2 speed13.89/ edge idBA fromB toA numLanes2 speed13.89/ edge idBC fromB toC numLanes1 speed10/ edge idCB fromC toB numLanes1 speed10/ edge idCA fromC toA numLanes1 speed10/ edge idAC fromA toC numLanes1 speed10/ /edges注意speed的单位是米每秒不是公里每小时。13.89正好是 50 km/h10是 36 km/h。这是新手最容易忽略的细节后面看仿真速度不对先回去查这个。然后用 netconvert 生成路网文件netconvert -n node.xml -e edge.xml -o simple.net.xml生成后可以打开simple.net.xml看内容你会发现里面多了大量细节junction 定义、connection 连接关系、车道编号、内部边 internal lanes 等。这些都是 netconvert 自动算出来的你不需要手写。3.2 定义车辆需求从 flow 到 route路网只是舞台现在加演员。新建routes.rou.xml先定义一个车辆类型再定义一个车流。routes vType idcar accel2.6 decel4.5 sigma0.5 length5 maxSpeed50 minGap2.5 color1,0,0/ flow idflow1 typecar fromA toC begin0 end3600 number600/ /routesbegin和end的单位是秒number600表示这一小时内总共发出 600 辆车车辆会在时间段内比较均匀地分布。maxSpeed单位是米每秒虽然我这里填的 50 实际上是米/秒但真实场景里如果限速 50 km/h记得填 13.89。minGap表示车距单位米。flow指定的是 OD 需求也就是出发地和目的地。具体走哪条路SUMO 运行时内部会调用路径搜索算法算出最短路。你也可以直接给一辆车写死路线方便调试vehicle idv1 depart0 typecar route edgesA AB B BC C/ /vehicle这种写法的好处是你能精确控制车辆经过的每条边适合验证路网连通性和观察单车行为。批量实验时通常用 flow 或 trip然后丢给 duarouter 展开成具体 route。3.3 写配置文件让 sumo 跑起来有了路网和需求还需要一个配置告诉 sumo 加载哪些文件、仿真多长时间。新建simple.sumocfgconfiguration input net-file valuesimple.net.xml/ route-files valueroutes.rou.xml/ /input time begin value0/ end value3600/ step-length value0.1/ /time /configuration注意step-length它决定仿真步长单位秒。默认是 1 秒对大多数宏观信号优化研究已经够用。如果你做的是碰撞、避让这类精细化场景可以把步长调到 0.1 秒但计算开销会高很多。新手统一先跑 1 秒就行。然后执行sumo -c simple.sumocfg如果配置正确你会看到一系列仿真进度日志最后显示仿真完成。没有图形界面跑完就结束但至少证明链路是通的。要看车辆跑起来的样子用带界面的版本sumo-gui -c simple.sumocfg打开之后按左下角的播放按钮车辆就会出现在路网上动起来。3.4 sumo-gui 的基本操作和调试技巧窗口打开后鼠标滚轮是缩放右键拖拽是平移。左侧面板可以列出当前路网中的所有车辆点击车辆能看到它的速度、位置、当前边。想按速度看车流颜色分布可以在工具栏的着色模式里选“Speed”。调整仿真速度有两个变量一个是最上面的 delay 滑块它控制每步之间人为等待的毫秒数调成 0 表示系统尽量快地跑另一个是左下角的步进按钮可以单步推进观察某个瞬间的状态。我建议你第一次跑 GUI 的时候故意把 delay 调大让车速放慢盯着几辆车看它们在交叉口怎么让行、怎么换道。这个过程能帮你建立对“微观仿真”的直观感受也会在之后排查问题时帮上大忙。4. 从演示到实战OSM 真实地图导入与自动化工具4.1 用 netconvert 把 OpenStreetMap 数据变成路网手工路网只能用来练手真项目要的是真实路网。最常用的数据源是 OpenStreetMap你自己在网站上框选一个区域导出.osm文件然后执行netconvert --osm-files map.osm -o city.net.xml这行命令会把 OSM 里的 highway 数据转成 SUMO 路网。但有个常见问题OSM 数据里什么路都有从高速公路到小区内部小路不筛选的话转出来的路网会非常碎。所以一般会加一个类型限制netconvert --osm-files map.osm --osm-type street -o city.net.xml--osm-type street表示只转换街道等级的路网。不同 SUMO 版本支持的 type 可能略有差异用之前可以netconvert --help osm看一下具体选项。转出来的路网通常都是几千个节点起步不可能手工检查每个交叉口。这时你应该打开 sumo-gui 快速浏览一圈重点看有没有奇怪的断头路、飞线、大面积空白区域有的话再回去查原始 OSM 数据。4.2 坐标投影问题绕不过去的坑OSM 原始数据用的是经纬度而 SUMO 内部用的是米制平面坐标。netconvert 默认会自动选一个投影方式把经纬度转成平面坐标大多数情况下它能选对但也经常失灵。失灵的表现有两种一种是一打开 sumo-gui发现路网距离尺度完全不对比如本来几百米的道路变成了几十万米另一种是报错说无法计算投影或者坐标超范围。这时候需要手动指定投影参数。常见做法是显式传一个 PROJ 字符串例如netconvert --proj-string projutm zone49 datumWGS84 unitsm --osm-files map.osm -o city.net.xmlUTM 投影分带号zone 可以根据中心经度计算zone int((lon 180) / 6) 1。这步看似麻烦但它决定了路网坐标是否合理。如果你觉得投影概念很唬人可以暂时理解成“把地图无缝平铺到地面上的一块小区域内”选错区域就等于铺歪了。有个经验不要一上来就导入整个城市。先导一个小片区验证坐标正确再逐步扩大。否则你会面对一个巨大且错位的路网根本无法定位问题。4.3 自动生成交通需求randomTrips 与流量标定真实路网有了需求怎么来如果只是概念验证可以用 SUMO 自带的随机出行生成脚本python $SUMO_HOME/tools/randomTrips.py -n city.net.xml -o trips.trips.xml -r trips.rou.xml -e 3600 -p 2-p 2表示平均每两秒生成一辆车。这个脚本会在路网上随机选取起终点生成一批 trip 数据。trip 只写了出发地、目的地和发车时间还没具体到路线所以要再用 duarouter 算一遍duarouter -n city.net.xml -t trips.trips.xml -o routes.rou.xml跑完的routes.rou.xml就是每辆车带上具体路径的最终需求文件。如果你做的是真实项目光靠 randomTrips 是不够的。正式做法是用卡口数据或调查数据先构建 OD 矩阵再根据路网和路径选择模型生成流量。SUMO 里有不少辅助脚本和工具可以导入 OD 矩阵但那是另一个深度的话题。新手阶段先用 randomTrips 把流程跑通理解需求生成的两步结构后面再谈标定。5. 进阶实操信号灯、公交线与 TraCI 动态控制5.1 信号灯配置从自动生成到自定义相位如果你把路网里某个节点的type从priority改成traffic_lightnetconvert 会自动生成一套默认的信号灯配时。在 sumo-gui 里你会看到红绿灯按周期切换足够应付演示。但真实场景没有这么省心你需要自定义绿信比、相位顺序甚至感应控制。信号灯配置写在 additional 文件里然后在 sumocfg 的additional-files里加载。一个完整的两相位示例大概长这样additional tlLogic idC typestatic programIDmProg offset0 phase duration31 stateGGrr/ phase duration6 stateyyyr/ phase duration31 staterrGG/ phase duration6 staterrrr/ /tlLogic /additional这里的state字符串每一位对应交叉口的一个连接。字母含义不复杂大写G表示绿灯、y表示黄灯、r表示红灯。关键是顺序要和该节点实际连接列表保持一致否则会出现“这方向亮黄灯、那方向也亮黄灯”的对不上号问题。最稳妥的做法是先用 netedit 打开路网在信号灯编辑器里直观地改相位和时长改完之后它帮你生成正确的 XML。手写 state 容易错新手尤其容易在连接顺序上翻车。5.2 公交站、定线公交与多方式仿真SUMO 不只管小汽车公交也很容易加进去。先把公交站定义在附加文件里additional busStop idbs1 laneAB_0 startPos10 endPos60 nameBusA/ /additional注意lane不能只写 edge必须写到具体车道。比如AB_0表示 edge AB 的第 0 条车道SUMO 的车道编号从右往左从 0 开始这是很多人的知识盲区。定义公交车时给它配一个公交类型然后在路线中加入停车动作vehicle idbus1 typebus depart0 lineL1 route edgesA AB B BC C/ stop busStopbs1 duration20/ /vehicleduration是停站时长的秒数。这样这辆公交车在通过bs1时会停车 20 秒然后继续行驶看起来就是一班标准公交。也可以实现行人仿真但复杂度会跃升需要给行人定义独立路网空间比如人行横道、步行通道不能直接让行人走在车行道上。如果项目需求里不涉及行人我建议先跳过等主流程跑稳了再碰。5.3 TraCI用 Python 在仿真运行中实时控制TraCI 是 SUMO 对外提供的实时接口。它允许你启动一个仿真然后在 Python 里一步一步推进每一步之间都可以读写内部状态。先写一个最简例子import libsumo as traci traci.start([sumo, -c, simple.sumocfg]) for step in range(3600): traci.simulationStep() ids traci.vehicle.getIDList() if len(ids) 0: continue speeds [traci.vehicle.getSpeed(v) for v in ids] avg_speed sum(speeds) / len(speeds) if step % 600 0: print(step, len(ids), avg_speed) traci.close()有些较老的 SUMO 版本不支持import libsumo你只需要改成import traci其余 API 基本一样。TraCI 真正厉害的地方是动态干预。你可以在每一仿真步里判断当前某个路口的排队长度如果超过阈值就延长绿灯时间你也可以用traci.vehicle.add()在任意时刻向路网中注入车辆模拟突发车流。这些能力让 SUMO 从“预先设定好的动画”变成了“可以做控制实验的沙盒”也是很多论文实验的基础设施。6. 常见问题与排查技巧实录6.1 车辆不出现或瞬间消失这是新手最常遇到的问题。车不出现先查需求文件和仿真时间有没有重叠。比如 flow 里定的begin0 end3600但 sumocfg 里begin100 end200那前 100 秒车还没开始发后 100 秒发完又结束自然一辆都看不见。还有一种情况是车辆出现了但瞬间就“消失”了。这通常不是真消失而是车辆在仿真结束前已经到达目的地被移出路网。确认办法是开启 tripinfo 输出在 sumocfg 中加入output tripinfo-output valuetripinfo.xml/ /output这样每辆车的出发时间、到达时间、总旅行时间都会写进文件一查就知道车到底跑没跑。6.2 车辆不动或堵死在交叉口如果车卡在某个交叉口一直不动大概率是连接关系有问题或者某条路根本走不通。用 sumo-gui 打开路网切到连接显示模式检查每个节电的 incoming、outgoing 边是否正确。还有一种情况是路网中存在孤岛也就是某些路段和其他路网没有物理连接。SUMO 提供了一个检查工具python $SUMO_HOME/tools/net/netcheck.py -n simple.net.xml -o report.txt报告里如果出现“disconnected subnetwork”之类的提示说明路网内部有断点需要回去修 OSM 数据或用 netedit 补上。6.3 导入 OSM 后地图错位或尺度离谱之前讲过的投影问题是主要元凶。如果出现坐标数量级明显不对比如一条路长达 80 万米别怀疑路网数据本身先怀疑投影。用--proj-string重新指定一次再对比路网的坐标范围问题基本能解决。另外有些 OSM 导出文件包含大量小线段和冗余节点转换出的路网会特别“碎”。常用的清理手段是在 netconvert 命令里加--geometry.remove和--geometry.min-dist去掉过密的多余节点保持几何形状不变。6.4 仿真跑得太慢路网大了、车辆多了仿真速度自然下来。最快的办法是改用无界面的 sumo去掉 GUI 渲染开销。还不够就用多线程选项sumo -c config.sumocfg --threads 4threads参数默认是 1调高之后大路网会明显快一些。另外检查一下是不是把step-length设成了 0.1 秒如果是先改回 1 秒大多数场景其实够用。输出文件也别乱开fcd 输出每步全量记录车辆轨迹写盘压力非常大。6.5 环境变量和 Python 导入报错ModuleNotFoundError: No module named traci大概率是PYTHONPATH没配好或者你换了终端之后没有重新加载配置。先执行echo $PYTHONPATH看是否为空。如果之前能用某次更新系统后突然失灵检查 SUMO 版本和 Python 版本的兼容性。别急着升级 SUMO有时候反而是系统 pip 版本和新版 traci 冲突。还有一个隐藏问题Windows 下路径包含中文或空格时Python 脚本可能找不到文件。别在这种地方浪费时间把场景目录放到纯英文路径下能避开一大批诡异报错。最后分享两个我自己的习惯。第一每个实验场景都用 Git 管理路网文件、需求文件、配置文件全部入库。改坏了就回退实验做完了还能翻出来对照当初到底改了什么参数这在仿真调参时比什么文档都可靠。第二不要一上来就导入整个大区域先手工做一个小三角形路网把最简单的仿真跑通再逐步叠加 OSM、信号灯、公交、TraCI。这个三角形路网就像编程里的 Hello World跑通它你就已经迈过 SUMO 最艰难的那道门槛了。

相关推荐

Foobar2000 FlatLite整合版:界面美化、中文包与DSD源码输出全攻略
Foobar2000 FlatLite整合版:界面美化、中文包与DSD源码输出全攻略

Foobar2000这个东西,在音频圈里属于"说了一万次还能说出新花样"的常青树。前阵子我重新整理自己用了多年的播放器配置,发现身边好几个朋友都卡在同一个地方:装好Foobar2000之后,想要一个扁平化的现代界面、想要中文菜单… · 2026/9/25 7:33:20

ERROR #134 致命错误全解析:从报错机制到排查修复实战
ERROR #134 致命错误全解析:从报错机制到排查修复实战

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

工业PDA死机与扫码失败的根因排查与实操修复
工业PDA死机与扫码失败的根因排查与实操修复

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

Atlas 300V 24G NPU上部署YOLO:从环境配置到性能优化
Atlas 300V 24G NPU上部署YOLO:从环境配置到性能优化

最近有人问我“Atlas”是什么,说实话第一反应是数据库中间件那头大象,结果他后面跟了一句“部署YOLO”,又补了个“300V 24G”,我立马就明白他说的其实是昇腾Atlas系列的AI加速卡。这名字在AI领域有点被说烂了,因为它既… · 2026/9/25 7:53:33

昇腾Atlas 300V 24G加速卡部署YOLO全流程实战
昇腾Atlas 300V 24G加速卡部署YOLO全流程实战

1. 先搞清楚Atlas 300V 24G的定位:是加速卡,但不是你以为的那种加速卡1.1 一张卡解决什么问题看到热搜里连续出现“atlas部署yolo”和“atlas 300v 24g 是运算加速卡吗”这两条,我就知道又有一批做边缘AI或服务器推理的同学被这张卡吸引过来了… · 2026/9/25 7:53:27

ExternalDNS 与 AWS Load Balancer Controller 集成实战:ALB/NLB Ingress 的 DNS 自动化管理
ExternalDNS 与 AWS Load Balancer Controller 集成实战:ALB/NLB Ingress 的 DNS 自动化管理

云原生 【免费下载链接】external-dns Configure external DNS servers dynamically from Kubernetes resources 项目地址: https://gitcode.com/gh_mirrors/ex/external-dns 点击查看 免费下载 ExternalDNS 与 AWS Load Balancer Controller(原 ALB In… · 2026/9/25 7:53:20

Apache Flink Checkpoint 监控指南:读懂 Web UI 四大标签页与每项指标
Apache Flink Checkpoint 监控指南:读懂 Web UI 四大标签页与每项指标

大数据流处理批处理数据工程 【免费下载链接】flink 项目地址: https://gitcode.com/gh_mirrors/fli/flink 点击查看 免费下载 Flink 的 Web 界面提供了专门监控作业 Checkpoint 的入口,且作业终止后这些统计依然可查。本文围绕官方文档 docs/content/d… · 2026/9/25 7:53:08

AIO Sandbox:桌面级开发环境的原子化容器封装
AIO Sandbox:桌面级开发环境的原子化容器封装

1. 这不是沙箱,是“桌面级开发环境”的原子化封装你有没有过这种体验:调试一个前端页面,得开着 Chrome DevTools 查 DOM,同时切到终端敲curl测试 API,再切回 VSCode 改代码,顺手还要用chmod修个文件权限&am… · 2026/9/25 7:52:50

运算符与条件分支的底层逻辑:从优先级到if/switch的高效写法
运算符与条件分支的底层逻辑:从优先级到if/switch的高效写法

1. 把运算符当成"决策细胞"来理解1.1 运算符的本质:从一次计算到一次判断很多人学编程时,运算符是被一笔带过的基础章节。但我一直觉得,运算符才是整个程序流程控制里最核心的"细胞"。为什么这么说?因为不管你… · 2026/9/25 7:52:50

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

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

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

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

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

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

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码