智能汽车SOA通信:SOME/IP与DDS混合架构解析与排雷指南
做智能汽车通信的同学这两年绕不开两个缩写SOME/IP和DDS。主机厂智能驾驶域、座舱域、中央网关的方案书上往往两个同时出现项目评审被问得最多的也是“为什么用两套协议”。很多刚接触SOA通信的工程师会纠结这俩到底什么关系能不能只用一个配置时该注意什么这篇文章我就把这些年做车载通信中间件的实践按自己的理解掰开讲一遍。先澄清一个坑DDS这个名字在我身边偶尔会引起歧义。做射频和信号处理的同事看到DDS第一反应是Direct Digital Synthesis直接数字频率合成就是AD9951这类DDS信号发生器的核心思路。而做通信的人说的DDS是Data Distribution Service数据分发服务OMG组织定义的标准。汽车圈语境里的DDS几乎都是后者。搜资料时如果不加“Data Distribution Service”或者“OMG DDS”很容易刷出来一堆信号发生器内容这点建议留意。下面分几块讲先聊为什么车会同时需要这两套通信中间件再分别拆SOME/IP和DDS的核心机制给出配置和选型建议最后是混合架构落地和排雷经验。1. 为什么智能汽车同时需要SOME/IP和DDS先看通信架构的进化1.1 从CAN总线到SOA通信对象变了传统汽车的ECU之间主要靠CAN、LIN和FlexRay通信。CAN跑信号报文每条报文有固定的ID和DBC定义收发关系在车型开发时就锁定网关里配好路由表。这种模式很稳定一个节点醒了就按周期发丢了就下个周期补无状态也不需要发现服务。但它的短板也很明显软件功能一旦要调整CAN矩阵、网关路由、DBC都得跟着改OTA想新增一个服务往往要重新评审硬件兼容性和总线负载。随着软件定义汽车推进车辆上的功能越来越多通过SoC上运行的高算力软件实现常用做法是把功能抽象成“服务”比如“定位服务”“车辆控制服务”“远程诊断服务”。服务之间需要动态发现、调用、订阅这是传统CAN信号协议做不到的。于是SOME/IP和DDS作为车载服务化通信中间件登上主力位置底层都是IP网络上层都提供面向服务的通信抽象。它们解决的核心问题一致让分布在多个ECU或域控上的软件模块能像本地调用一样互相通信。区别在于SOME/IP像“打电话点菜”一次请求一次应答语义清晰DDS像“广播电视台”发布者只管往频道里发订阅者按兴趣自己收重在数据实时分发双方彻底解耦。1.2 出身和生态的差别决定了它们的分工这里补一张对比表信息集中放方便理解两侧思路的来源维度SOME/IPDDS主导组织AUTOSAR宝马早期推动后纳入AUTOSAR标准OMG对象管理组织标准历程2014年左右进入AUTOSAR 4.22004年发布DDS 1.0核心模型服务发现 远程过程调用/事件通知发布/订阅全局数据空间DCPS主要生态AUTOSAR CP/AP、SOA诊断、标准车载工具链ROS2、军工防务、工业控制、智能驾驶底层传输UDP/TCPUDP组播/单播、共享内存SOME/IP的诞生地就是汽车所以它的设计带着“整车开发思维”启动时要服务发现运行时有方法调用和超时控制诊断和安全机制都能跟AUTOSAR体系无缝衔接。做AUTOSAR CP的工程师常用的工具链比如Vector、ETAS基本都有SOME/IP配置项。DDS则是从分布式系统领域“跨界”进车的。它不以调用接口为中心而是以数据为中心谁产生数据谁消费数据中间通过Topic解耦。它支持灵活的QoS能控制数据的可靠性、送达时限、历史缓冲、生命周期。正因如此DDS在ROS2之后成为机器人领域的默认通信基础自动驾驶团队也大量使用。这两种协议并不是单纯的竞争关系更像是两种风格差异明显的协作工具。控制域、智能座舱里做服务调用用SOME/IP顺理成章智驾系统里大量传感器数据在多个模块间流动用DDS更合适。接下来分开拆。2. SOME/IP机制拆解服务发现、报文结构和配置要点2.1 服务发现开局建立连接的关键SOME/IP服务发现默认运行在UDP 30490端口通过组播地址广播自己的服务。服务端上线后发送OfferService报文告诉网络“我有XX服务”客户端如果想找服务先发FindService服务端收到后会回复OfferService。后续客户端可以RequestService请求访问服务或者SubscribeEventgroup订阅某个事件组。服务发现这个环节看起来简单但实际项目里容易踩坑。比如服务端启动慢客户端开机就发FindService结果服务端还没上线客户端以为服务不可用组播地址和端口配置不一致两边不在同一个VLAN或者被防火墙隔离SD报文发送周期太密或太疏过密影响总线负载过疏则发现延迟高。AUTOSAR规范里SD有一个状态机包含initial wait phase、repetition phase、main phase每个阶段报文重发间隔不一样。调试时最有效的方法是抓SD报文看客户端是否发出FindService服务端是否回复OfferService。如果一直只有FindService没有OfferService问题基本锁定在服务端发布配置上。2.2 四种通信方式不同场景不同打法SOME/IP通信有四种模式请求-响应Request/Response一问一答用于读取状态、调用方法。只发不答Fire Forget只发请求不期待应答适合指令类、命令类比如“下发启动编码”。发布订阅Publish/Subscribe客户端订阅服务端的事件组服务端定期推送数据适合周期传感器数据。事件与字段Event/FieldEvent类似事件流Field是带读写属性的值比如“当前车速”支持Getter/Setter和Notifier。SOME/IP报文头有固定格式Message ID32位由Service ID和Method ID组成Length32位Request ID32位Protocol Version8位Interface Version8位Message Type8位Return Code8位。报文头总长16字节。Message Type有REQUEST、RESPONSE、NOTIFICATION等Return Code标志请求是否成功。这里有个容易忽略的问题Length字段虽然单位是字节但它从Request ID开始算不包含Message ID和Length自己。做解析或者写测试工具时Length不匹配会导致对端直接丢包排查起来特别费劲。2.3 AUTOSAR AP下面怎么配置在AUTOSAR Adaptive Platform里SOME/IP通常通过arxml定义服务接口然后生成代码。配置项包括服务ID、实例ID、method ID、event ID、端口、传输协议UDP还是TCP、组播地址等。我的习惯是先用协议栈自带的demo跑通点对点再上实车网络。配置时特别注意service instance ID和interface version版本不一致时SD会显示服务可达但调用返回错误码很多人在这里查了半天。iface version不对表现非常隐蔽业务日志里只会看到一个泛泛的错误。还有一点如果走TCP传输SOME/IP支持长连接和分段传输适合大报文比如OTA升级包。走UDP则要注意MTU报文超过1472字节1500 MTU减去20字节IP头和8字节UDP头会被分片分片乱序会引发重组问题。实操中遇到UDP大包掉包先查IP分片和交换机配置不要急着怀疑协议栈。3. DDS机制拆解全局数据空间与QoS3.1 以数据为中心的发布/订阅模型DDS底层模型叫DCPSData-Centric Publish-Subscribe有一个“全局数据空间”的抽象概念。一个域Domain内所有参与者共享这个数据空间通过设定数据类型和话题Topic来交换数据。一个Topic包含一个名字和一种数据类型比如Topic名是“imu_data”类型是自定义的IMU消息。发布端创建DataWriter下发数据订阅端创建DataReader收数据。收发双方都不需要知道对方的IP、端口DDS的发现机制通过SPDPSimple Participant Discovery Protocol和SEDPSimple Endpoint Discovery Protocol自动完成节点和端点的匹配。这跟SOME/IP的区别就出来了SOME/IP客户端和服务端通过网络上的服务ID明确认识对方DDS则更加匿名靠Topic和QoS决定谁和谁通信。好处是扩展性很强加一个订阅者不需要改动发布者坏处是调试时“看不见”通信关系必须依赖工具和日志才能还原拓扑。3.2 QoS策略每项参数都直接影响收发行为DDS真正厉害的地方是QoS。它通过一组策略精确控制通信行为而不是给几个固定的“可靠”或“不可靠”选项。项目里最常用的QoS策略是这几项QoS策略作用典型配置RELIABILITY数据可靠性RELIABLE保证按序不丢BEST_EFFORT尽力传输控制指令用RELIABLE视频流用BEST_EFFORTDURABILITY晚加入的订阅者能否收到历史数据VOLATILE只收新的TRANSIENT_LOCAL/TRANSIENT可以收缓存的历史数据地图服务用TRANSIENT_LOCAL实时传感用VOLATILEHISTORY历史缓存KEEP_LAST(N)只缓存最新N帧KEEP_ALL缓存所有显示类订阅用KEEP_LAST(1)DEADLINE发布者最长多久必须发一帧用于监测“掉线”控制类2ms感知类20msLIVELINESS节点保活租期判断参与者是否存活5s左右太短会误报QoS匹配有严格规则。发布端和订阅端的策略必须兼容比如发布端是RELIABLE订阅端也是RELIABLE匹配发布端BEST_EFFORT、订阅端RELIABLE会出现不匹配或降级。我在调试时见过最多的问题就是两边QoS没对齐日志显示endpoints匹配失败但在Wireshark里数据明明在组播里不停发排查了很久才明白是协议栈在匹配阶段就直接把数据丢弃了。3.3 DDS在ROS2里的实际用法ROS2把DDS作为底层传输通过RMWROS Middleware Wrapper抽象层支持不同的DDS实现。默认是Fast DDS也可以换Cyclone DDS、RTI Connext等。选型时主要从三方面评估许可证Fast DDS和Cyclone DDS开源、性能延迟抖动、吞吐、功能安全认证情况。在ROS2里写代码时通常不用直接配置DDS全部QoS而是通过rclpy或rclcpp的QoS对象设置。比如传感器数据传输from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy, DurabilityPolicy qos QoSProfile( depth1, historyHistoryPolicy.KEEP_LAST, reliabilityReliabilityPolicy.BEST_EFFORT, durabilityDurabilityPolicy.VOLATILE, )发布端和订阅端都设置一致的QoS通信才稳定。车载DDS场景不一定用ROS2但相同逻辑适用先定Topic再定数据类型最后把QoS匹配好。DDS底层走DDSI-RTPS协议本质是UDP组播加单播。部署时要注意组播地址是否被交换机拦截、网卡是否开启组播、多个DDS参与者是否在同一域ID。没有组播权限的容器或虚拟化环境推荐配置成单播发现或使用共享内存传输。4. 选型与混合架构不要做二选一4.1 功能对比速查表维度SOME/IPDDS通信模型服务调用RPC事件发布/订阅QoS实时能力可配置但依赖SD发现机制QoS可精细控制软实时带宽效率单包开销小适合短报文包头较大适合大数据流动态发现基于SD服务发现显式匹配基于SPDP/SEDP自动发现生态AUTOSAR、诊断、SOA服务ROS2、数据分发、智驾标准组织AUTOSAROMG典型场景整车服务调用、OTA、诊断传感器融合、多域数据共享工具链Vector/DSA、WiresharkWireshark、DDS厂商工具核心结论如果你在车里做“服务调用”比如打开空调、读取电池状态、下发控制指令SOME/IP顺手如果你把车上大量数据比如摄像头预处理结果、激光雷达点云、融合轨迹分发给多个消费者DDS是更合理的。不要指望一套协议通吃所有场景。强行用SOME/IP做大带宽数据分发你得处理大量Event订阅和UDP分片工程量和故障率都难看强行用DDS做整车诊断和AUTOSAR服务调用又会跟原有ECU工具链脱节。两者共存是当前中央计算平台最务实的局面。4.2 混合部署的设计思路现在中央计算架构基本是这样一个局面座舱域、车身域传统功能跑AUTOSAR CP/AP服务接口走SOME/IP智驾域尤其是感知融合、规划控制相关模块跑DDS。两边要互相通信就要在中间某个节点做转换。常见方式有三类网关转换在中央网关或域控制器的服务模块里同时跑两套协议栈一边监听SOME/IP服务调用一边以DDS节点收发相应主题做语义转换。接口隔离对外层统一抽象用中间件适配层封装SOME/IP和DDS的差异业务代码不感知底层协议类型。数据链路划分将高频大流量数据直接走DDS组播低频控制指令走SOME/IP避免把它们混在一个通道里造成QoS互相影响。我比较推荐第三种思路至少控制流和数据流不要耦合。比如紧急刹车控制指令走SOME/IP经过AUTOSAR的确认和诊断链路而摄像头原始特征通过DDS直接分发到多个算法模块互相不干扰。如果强制把大流量DDS数据塞进SOME/IP event在UDP缓冲不够时会导致背压控制面因此受到干扰。4.3 桥接转换时要注意的坑协议转换不是简单“收到一条转发一条”。SOME/IP是请求-响应语义DDS是发布-订阅语义两者的事件和字段语义需要映射。具体说SOME/IP的Event对应DDS的TopicSOME/IP的Field的Getter对应DDS的一个请求响应TopicSetter对应另一个SOME/IP的Request/Response方法需要专门的“服务请求Topic”和“服务响应Topic”或者用DDS的请求-响应模式还有超时和可靠性问题。SOME/IP请求有超时重发机制DDS的RELIABLE是端到端确认两边语义不对齐时容易造成桥上数据重复或者丢失。我的做法是给每个转换点维护一张映射表包含service ID、method ID、topic名、QoS配置、超时时间转换程序只用这张表驱动避免硬编码。另外两边序列化规则不同。SOME/IP用自己的序列化规则DDS用CDRCommon Data Representation。桥上要做两种格式互转字段名相同的话用代码生成工具自动生成转换逻辑能省很多事。但建议保留字段版本号和类型描述信息方便后续扩展。5. 实战排雷SOME/IP和DDS混用项目里踩过的坑5.1 服务发现慢半拍导致首包失败SOME/IP的SD启动阶段不是即时完成的从服务端启动到客户端看到服务可用少说几十毫秒。如果系统开机时序控制不好客户端在服务真正发布前就发送调用请求请求自然失败。我在项目里遇到过服务偶发失败的问题板子上电后头几秒调用报错之后又自动好了。排查思路是抓SD客户端先发FindService服务端再发OfferService并伴随重复周期。只要时序错开首包必失败。解决方案在客户端增加自动重试失败后延迟100ms-500ms重发或者让服务端启动后主动发Offer抢占“告知”时机对启动阶段的关键服务把初次重试间隔加大到2秒避免服务端启动瞬间大量请求涌入5.2 DDS QoS不匹配的假故障DDS里最常见的“假故障”就是两端QoS不一致。我调试过一个接收图像数据的模块发布端设RELIABLE订阅端设BEST_EFFORT数据偶尔能收到但时好时坏日志一直输出“no available endpoints”。这个问题用Wireshark很难直接看出来因为组播里数据是正常发的只是订阅端的协议栈把这条topic判定为不匹配而丢弃。排查建议先把两端QoS全部改成默认值然后再逐步调优。用日志或工具比如Fast DDS的XML配置文件输出当前匹配状态很有帮助。关键点RELIABILITY策略要求发布端的可靠性级别不能低于订阅端如果你想用BEST_EFFORT订阅端也必须是BEST_EFFORT。5.3 组播抓包为什么抓不到DDS数据抓DDS包时最容易出现的困惑是为什么Wireshark看不到数据大概率DDS使用组播地址收发而默认抓包接口不接收组播流量或tshark没有指定组播组。解决方案很简单sudo tcpdump -i eth0 multicast或者在Wireshark的捕获选项里取消勾选“启用组播流量过滤”。另外DDSI-RTPS使用端口映射算法不同域ID会映射到不同的通信端口如果域ID搞错了抓包时也会什么都看不到。5.4 工具链推荐和资源评估思路SOME/IP方面Wireshark自带SOME/IP和SOME/IP-SD的解析器配置好解码选项后能直接看到Message ID、Service ID、Method ID和EventGroup ID。DDS方面Wireshark同样有内置的DDS dissector但只解析RTPS层应用层的序列化数据需要扩展或者手动解码。做性能评估时我建议先在本地回环环境里跑一个简单的发布订阅基准测量端到端延迟和抖动。DDS因为QoS和传输选择差异很大同一个工程用BEST_EFFORT和RELIABLE延迟和CPU占用差距能达到2倍以上。SOME/IP则重点测SD报文对总线的占用尤其当网络上服务数量多时SD的周期性报文会占相当比例带宽。做车载通信这几年我的明显感受是这两套协议没有谁能完全替代谁。项目里与其纠结二选一不如把它们看成一个工具箱里的两把不同工具控制类、服务类走SOME/IP数据流、大带宽走DDS。混合架构只要做好协议映射和故障隔离整体可靠性完全可以做起来。根据我的经验项目刚起步时先把服务发现时序和QoS匹配这两件事盯住能避开一多半的坑其余问题抓包和日志能解决八成。

相关新闻

superpowers技能包实战指南:让AI辅助开发输出稳定可预期

superpowers技能包实战指南:让AI辅助开发输出稳定可预期

这年头做 AI 辅助开发的人,十个里有九个都在跟“提示词质量”较劲。我之前也一样,天天调的 prompt 长了又长,效果却时好时坏。直到我把 superpowers 这套技能体系引进来,才意识到问题根本不是“问得不够细”,而是 AI 缺…

2026/10/14 7:59:46 阅读更多 →
照明灯具标准体系全解析:从安全底线到市场准入

照明灯具标准体系全解析:从安全底线到市场准入

我在照明行业摸爬滚打了十几年,最深的体会是:让一个新人快速崩溃的方法,就是直接让他把照明灯具标准体系完整翻一遍。GB 7000.1、IEC 60598-1、UL 1598、EN 55015、GB/T 31897……一连串代号砸过来,如果只看单个标准,很…

2026/10/14 7:58:46 阅读更多 →
汽修行业变革:技术升级与经营转型的生存之道

汽修行业变革:技术升级与经营转型的生存之道

1. 汽修行业的现状与困境上周路过小区门口那家开了12年的"老张汽修",发现卷帘门已经拉下,玻璃门上贴着"店面转让"的告示。这已经是今年附近第三家关门的汽修店了。作为在汽车后市场摸爬滚打多年的从业者,我不得不思考&am…

2026/10/14 7:58:46 阅读更多 →

最新新闻

Claude 看板与动画工具实战:对话式办公套件搭建指南

Claude 看板与动画工具实战:对话式办公套件搭建指南

1. 从单点对话到办公套件:这次更新到底改了什么Claude 最早给人的印象就是一个“会聊天的模型”,你问它答,顶多帮你改改文案、写写代码。但最近这一波更新,方向明显变了——它开始往“办公套件”的路子上走。所谓看板工具和动画工…

2026/10/14 9:47:26 阅读更多 →
小白程序员转行AI必看:Agent开发与大模型开发的区别与学习路径

小白程序员转行AI必看:Agent开发与大模型开发的区别与学习路径

本文对比了大模型算法工程师和Agent开发工程师的薪资、工作内容、学习门槛及发展前景。指出大模型算法岗薪资高但门槛极高,适合深入研究AI模型;而Agent开发岗入门门槛低,适合将AI应用于实际业务场景,是当前及未来的热门方向。建议…

2026/10/14 9:47:26 阅读更多 →
Claude 办公套件更新:看板与动画工具实战指南

Claude 办公套件更新:看板与动画工具实战指南

1. 从单点对话到办公套件:这次更新到底改了什么Claude 最早给人的印象就是一个"能聊天的模型",你问它答,偶尔帮你改改文案、写写代码。但最近这一波更新,方向明显变了——它不再满足于做一个对话框里的助手,…

2026/10/14 9:47:26 阅读更多 →
菲律宾客服外包不是四选一:把服务模式做成阶段性组合

菲律宾客服外包不是四选一:把服务模式做成阶段性组合

菲律宾客服模式怎么选?一个直接的判断可以作为起点:工单少、波动大且问题标准化时,先评估共享坐席;业务稳定并需要持续沉淀产品知识时,倾向专属团队;智能硬件等复杂产品需要菲律宾英语一线与中国技术团队形…

2026/10/14 9:47:26 阅读更多 →
CSS阴影效果深度解析与性能优化指南

CSS阴影效果深度解析与性能优化指南

1. 为什么CSS阴影效果总是让人头疼?作为前端开发中最常用的视觉增强手段之一,CSS阴影效果看似简单,实则暗藏玄机。新手常遇到的典型问题包括:阴影效果不自然、性能消耗大、浏览器兼容性差、多层阴影叠加混乱等。这些问题的根源在于…

2026/10/14 9:47:26 阅读更多 →
模型量化:4bit、8bit量化原理与实践

模型量化:4bit、8bit量化原理与实践

📝 本章学习目标:通过本章学习,你将全面掌握"模型量化:4bit、8bit量化原理与实践"这一核心主题,建立系统性认知。一、引言:为什么这个话题如此重要 在人工智能快速发展的今天,模型量化…

2026/10/14 9:46:26 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/14 7:53:34 阅读更多 →