领域驱动设计(DDD)【3】之事件风暴

文章目录

  • 说明
  • 一 事件风暴理论知识
    • 1.1 事件风暴的核心目标
    • 1.2事件风暴的关键步骤
      • 1.2.1 准备工作
      • 1.2.2 核心流程
      • 1.2.3 事件风暴的输出
    • 1.3 事件风暴的优势
    • 1.4 常见问题
      • Q1:事件风暴适合所有项目吗?
      • Q2:事件风暴后如何落地?
      • Q3:在事件风暴里是否要列出所有的领域事件和命令?
      • Q4:各个领域事件需要体现严格的时间顺序吗?
      • Q5:每个步骤的颗粒度应该有多大?
      • Q6:怎么保存和维护事件风暴的结果?
      • Q7:怎么保存领域规则?
  • 二 事件风暴实践
    • 2.1 事件风暴的第一步:识别领域事件
    • 2.2 识别“项目管理”流程的领域事件
    • 2.3 识别其他流程的领域事件
    • 2.4 关于领域事件的补充说明
    • 2.5 事件风暴第二步:识别命令
    • 2.6 事件风暴第三步:识别领域名词
  • 三 深入理解事件风暴的作用

说明

  • 本文学习自极客时间的《手把手教你落地DDD》,仅供学习和交流使用。

一 事件风暴理论知识

  • 事件风暴(Event Storming)是DDD中一种高效的协作式建模方法,由 Alberto Brandolini 提出。它通过**领域事件(Domain Events)**作为核心,快速探索业务逻辑,识别聚合、限界上下文等关键元素。

1.1 事件风暴的核心目标

  1. 快速理解业务:通过事件流梳理业务流程。
  2. 发现领域模型:识别聚合、实体、值对象等。
  3. 划分限界上下文:明确系统边界和交互方式。
  4. 促进团队协作:业务专家、开发人员、架构师共同参与。

1.2事件风暴的关键步骤

1.2.1 准备工作

  • 参与者:业务专家、开发人员、架构师等(建议 4-8 人)。
  • 工具:白板、便利贴(不同颜色)、马克笔。
  • 时间:通常需要 1-3 天的工作坊。

1.2.2 核心流程

  1. 识别领域事件(Domain Events):表示业务中已发生的事实(过去时态)。示例:订单已创建(OrderCreated)、支付已受理(PaymentReceived)。
  2. 排序事件流:按时间顺序排列事件,形成业务流程的完整链路。 订单已创建 → 支付已受理 → 库存已扣减 → 物流已安排
  3. 识别命令(Commands):触发领域事件的动作(通常由用户或外部系统发起)。示例:创建订单(CreateOrder) → 触发 订单已创建(OrderCreated)
  4. 识别聚合(Aggregates):管理一组相关对象的一致性边界(如 Order 聚合根)。
  • 规则
    • 每个命令必须由一个聚合处理。
    • 每个事件必须由一个聚合发布。
  • 示例:Order 聚合处理 创建订单 命令,发布 OrderCreated 事件。
  1. 识别角色(Actors)与外部系统
  • 角色:谁发起了命令?(如用户、管理员、第三方服务)。
  • 外部系统:哪些系统参与流程?(如支付网关、物流系统)。
  1. 划分限界上下文(Bounded Context):将相关事件、聚合划分到独立的上下文中。
  • 示例
    • 订单上下文:处理订单创建、支付。
    • 库存上下文:处理库存扣减。
  1. 识别策略(Policies)与规则
  • 业务规则:如“支付超时自动取消订单”。
  • 策略:通过领域事件触发后续动作(如 PaymentTimeout 触发 CancelOrder)。

1.2.3 事件风暴的输出

  1. 领域模型:明确的聚合、实体、值对象。
  2. 限界上下文:系统模块划分。
  3. 业务流程:事件流与命令的完整映射。
  4. 协作共识:团队对业务逻辑的统一理解。

1.3 事件风暴的优势

  • 高效:快速梳理复杂业务,避免冗长文档。
  • 可视化:通过便利贴直观展示逻辑。
  • 协作友好:业务与技术人员共同参与。
  • 适应变化:易于调整和迭代模型。

1.4 常见问题

Q1:事件风暴适合所有项目吗?

  • 适合:业务复杂、需深度领域建模的系统(如金融、电商)。
  • 不适合:简单 CRUD 或技术驱动型项目。

Q2:事件风暴后如何落地?

  • 转换为 DDD 战术设计(实体、聚合、仓储等)。
  • 结合 CQRS事件溯源(Event Sourcing) 等模式实现。

Q3:在事件风暴里是否要列出所有的领域事件和命令?

  • 列出所有领域事件和命令并没有原则上的错误,但这样做会让结果变得繁琐,反而让人抓不住重点。
  • 建议:在事件风暴里只列出主要的、足以用于表达和交流领域知识的步骤,如签订合同、生效合同等等。而像修改合同和删除合同这样的步骤是显而易见的,在讨论过程中可以提一下,但不必列出。

Q4:各个领域事件需要体现严格的时间顺序吗?

  • 只需要按照大致的顺序,贴出领域事件即可。如果要体现严格的时间顺序,需要用到更复杂的符号,例如条件判断,还有要画更多的连线,会使事件风暴变得非常繁琐。

Q5:每个步骤的颗粒度应该有多大?

  1. 事务完整性准则

    • 当一组操作需要作为原子单元成功/失败时,应合并为单一领域事件
    • 示例:合同签订包含「基本信息录入→明细填写→附件上传」三个步骤,若业务要求三者全部完成才算有效合同,则应聚合为「合同已签订」单个事件
  2. 业务价值导向

    • 领域事件应反映对业务状态产生实质影响的关键节点
    • 反例:合同草稿自动保存(无业务价值) vs 合同最终提交(触发法务审核)
  3. 事件消费意义检验

    • 每个事件至少应有1个明确的下游消费者(如报表生成、风控系统等)
    • 决策树
      步骤变更是否影响其他限界上下文
      拆分为独立事件
      合并到父事件

  • 合同签订案例
步骤独立事件必要性决策依据最终方案
1. 录入基础信息中间状态无业务价值合并到「合同已签订」
2. 填写付款条款✔️触发财务系统预审计「合同条款已确定」
3. 上传签字扫描件仅作为合同完成的附属条件合并到主事件

Q6:怎么保存和维护事件风暴的结果?

  • 如果事件风暴的内容最终会反映到用户故事、用例、功能列表等产出物中,而这些产出物会进行维护,那我们就不必专门更新事件风暴的产出物了,只在需要的时候作为一种沟通工具,将电子化的结果作为一种中间产物保存就可以了。但是,如果你的团队并没有用户故事和用例等保存行为需求的方式,那么我建议你对事件风暴进行维护和更新。
  • 除了绘图之外,事件风暴也可以用表格的形式来保存
业务流程命令领域事件执行者查询数据领域对象
租户管理添加租户租户已添加管理者
组织管理添加开发中心开发中心已添加人事人员企业
组织管理添加开发组开发组已添加人事人员开发中心
组织管理添加直属部门直属部门已添加人事人员企业
员工管理添加员工员工已添加人事人员所属部门
员工管理转移员工员工已转移部门人事人员目标部门

Q7:怎么保存领域规则?

  • 领域规则是重要的领域知识,必须妥善保存。在事件风暴的过程里我们已经识别出了一些领域规则,在后续的领域建模阶段,可能还会识别出更多。
  • 编辑一个领域规则表,把所有的领域规则都汇总在里面,然后再把领域规则表和领域模型放在一起,作为领域知识的重要组成部分。
规则编号模块规则描述举例影响的主要功能
R001项目管理任一时刻,一个员工在各个项目上累计的预计投入工作量不能超过 100%小王在项目 A 上预计投入 60%,如果现在要把他同时分配到项目 B 上,那么项目 B 上的预计投入工作量不能超过 40%为项目分配员工
R002工时管理员工只能在被分配的项目上报工时小王被分配到项目 A 上,但没有分配到项目 B,则小王周一可以在项目 A 上报 4 小时,但不能在项目 B 上报工时报工时
R003工时管理一个员工一天累计工时不能超过 24 小时小王被分配到项目 A 和 B 上,在周一,在 A 上报了 12 小时,在 B 上报了 13 小时,由于超过 24 小时所以不能通过报工时
R004工时管理员工只有在项目有效期内才能报工时小王被分配到项目 A,项目 A 在 8 月 1 日结束,小王想在 8 月 5 日为项目 A 报工时则不能通过报工时
R005工时管理工时单位为小时,最小颗粒度为 0.5 小时小王为项目 A 报 4.5 小时,可以通过,但报 4.6 小时,则不能通过报工时

二 事件风暴实践

  • 准备工作:准备场地、人员、工具,场地可以是较大的会议室或者有一面足够长的墙,人员包括技术人员(架构师、技术经理、测试人员)和业务人员(产品经理)。工具可以使用便利贴或其他电子形式的绘图工具。

2.1 事件风暴的第一步:识别领域事件

  1. 假设我是产品经理(具有较丰富的DDD经验),你是架构师。我开头和你讲了一遍需求,然后我们开始识别事件风暴的第一步:识别领域事件。
  • 领域事件表示的是,业务流程中每个步骤引发的结果。事件风暴的作者认为,从结果入手来梳理需求,比从操作入手,更容易把业务想清楚。事件风暴中的“事件”两个字就来源于领域事件。
  • 领域事件的命名,一般是完成时 + 被动语态。比如说,订单已提交。

2.2 识别“项目管理”流程的领域事件

  • 首先进行项目管理流程的领域事件。我们各自按照自己的理解,把项目管理中发生的各个领域事件,分别梳理绘制,然后进行讨论,得出最终一致的结果。绘制结果如下:
    在这里插入图片描述

  • 首先,第一个区别,你写的是“客户已创建”,我写的是“客户已添加”。
    在这里插入图片描述
  • 你问我:“业务人员一般会说客户已创建还是客户已添加呢?”
  • 我回答你:“一般是说客户已添加,因为从业务的角度,客户本来就是存在的 ,不需要创建,只是把客户资料添加到我们的系统而已”。
  • 你表示同意。
    在这里插入图片描述

  • 然后,第二个区别,你写的是“签订合同”,我写的是“合同已签订”。
    在这里插入图片描述
  • “签订合同”是个动作,不是事件。所以达成一致后。
    在这里插入图片描述

  • 接着,第三个区别,你写的是“项目已创建”,我写的是“合同已生效”。我后面还有一步“立项”,应该和你的“项目已创建”是一回事,所以说明我比你多了一步“合同已生效”。
  • 你又问:“合同签订以后不是马上就生效了吗,还要有一个额外的生效步骤吗?”
  • 我解释说:“合同签订的时候未必马上生效,比如 1 月 1 日签了合同,但合同中可以约定,真正生效是在 2 月 1 日,所以需要一个单独的步骤让合同生效。”
  • 然后你又问:“我写了项目已创建,但是你写的是已立项,你这种写法好像和其他的不太一致呀。”
  • 我解释说:“虽然我们为领域事件命名的时候,常常用‘什么什么已什么什么’的形式,不过如果业务上已经有约定俗成的术语,我们就直接使用术语,这样更容易和业务沟通。现在业务觉得已立项是一个通用的术语,写成项目已创建反而显得生硬。”
  • 在 DDD 中的各种命名,一般都优先使用约定俗成的业务术语。
  • 目前讨论统一后的内容:
    在这里插入图片描述

  • 其次,第四个区别,我发现自己漏写了“项目已启动”。然后我们再比较了一下“项目已终止”和“项目已结束”两个说法,觉得“项目已结束”更符合业务术语。而“合同已结束”这一步,咱们俩是一样的。不过我在“项目已结束”前面还多了一个“员工已分配”。
    在这里插入图片描述
  • 于是你又问我:“刚才你讲需求的时候,好像是把员工分配作为一块单独的需求来讲的,不属于项目管理这个流程吧?”
  • 我想了想,说:“员工分配背后的业务逻辑有点复杂,所以之前单独拿出来讲,其实员工分配是项目运作中的一个重要环节,放在项目管理中也没毛病。”
  • 你对此表示认可。
  • 我又补充了一点:“员工分配到项目的时候,要填入预计的投入工作量的百分比,一个人可以同时上多个项目,但预计的投入百分比总和不能超过 100%。这种逻辑一般叫业务规则,为了避免忘记,咱们也写上吧。”
    在这里插入图片描述

  • 再下一步,你多了一个“客户已终止”。

  • 我解释说:“客户可以在系统中长期存在,以便不断挖掘商机,一般不必专门进行终止。理论上说,万一客户破产了,是应该终止,不过目前业务上还没有这个需求,这一点可以以后再考虑。”。 于是,我们把“客户已终止”拿掉了。
    在这里插入图片描述

  • 然后你又发现,我的流程中最后还多了一个“客户经理已更换”。
    在这里插入图片描述

  • 你有点惊讶地问:“可以更换客户经理吗?你刚才好像没说呀。”

  • 我说:“可以更换,我刚才忘记说了。”

  • 你紧跟着追问:“那么负责合同的销售人员,还有项目经理是不是也可以换呢?”

  • 我说:“也可以。”
    在这里插入图片描述


  • 最后,我们把整个流程又仔细检查了一遍。又发现了一个遗漏的领域事件。员工分配到项目上以后,还可以下项目,所以应该有一个“员工已退出”事件。
    在这里插入图片描述

2.3 识别其他流程的领域事件

  • 用上述同样的方法,识别其他流程的领域事件。
    在这里插入图片描述

2.4 关于领域事件的补充说明

  1. 不要把技术事件当成领域事件。领域事件一定要是领域专家所关注的,用的是业务术语。像数据库事务已回滚、缓存已命中之类的技术术语,不是领域事件,不在这个阶段讨论。
  2. 查询功能不算领域事件。领域事件应该是对某样事物产生了影响,并被记录的事情。一般是某个事物的创建、修改和删除。还有一种情况是向其他人或者系统发消息,例如“通知邮件已发送”也算领域事件,因为接收方可能会通过进一步处理来影响某些事物。而像“客户信息已查询”这些就不算领域事件,因为还没有对事物产生实际影响。不过,这并不代表查询功能不重要,查询功能也要以某种方式体现。

2.5 事件风暴第二步:识别命令

  • 命令(command)是引发领域事件的操作,可以通过分析领域事件获得。除了识别出命令本身以外,我们通常还要识别出执行命令的角色,以及执行命令要查询的数据。比如说,对于“合同已签订”这个事件,对应的命令就是“签订合同”。这里,在水蓝色的便利贴上写出命令,然后贴在对应的领域事件上方。“签订合同”的操作者是“销售人员”。售人员术语上叫做“执行者”,英文是 actor。把执行者写在小一点的粉色便利贴上,贴在命令上方,如下图:

在这里插入图片描述

  • 在执行“签订合同”操作时,执行者要先从系统里查出客户信息,才能和这个客户签订合同。这里,“客户”是一种“查询数据”。我们把查询数据写在小一点的绿色便利贴上,也贴在命令上方。
    在这里插入图片描述

  • 按照前面的方法一边讨论,一边识别出所有的命令。
    在这里插入图片描述

2.6 事件风暴第三步:识别领域名词

  • 领域名词是从命令、领域事件、执行者、查询数据里找到的名词性概念。例如,对于签订合同这个命令而言,受到影响的名词性概念是“合同”;类似地,对于合同已签订这个领域事件,是由于“合同”这个名词性概念的状态变化所导致的。
  • 识别领域名词的操作步骤可以分成两小步。
  1. 第一步,挪动上一步的便利贴,把围绕同一个名词的命令、事件、执行者、查询数据摆在一起,分成好几“堆”,贴在墙上。
  2. 第二步,把领域名词写在大一点的黄色便利贴上,贴在每堆便利贴的中间。
    在这里插入图片描述
    在这里插入图片描述
  • 所有领域名词识别结果
    在这里插入图片描述
    在这里插入图片描述
  • 为项目分配员工”和“员工已分配”出现了两次,一次是关于“员工”的,另一次是关于“项目”的。因为这对命令和事件是关于两个名词的,所以抄写了两遍。关于项目的那次,在命令和事件后面加了一个 “2” ,就是同一个概念在图中出现了第二次的意思,这是我们画图时的一个常用技巧,其他有 “2” 的命令和事件也是同理。

三 深入理解事件风暴的作用

  • 从整机视角来看,事件风暴是业务人员和技术人员一起协作,捕获行为需求、消化领域知识、形成统一语言的一种方法。
  • 领域事件的作用:从代码实现的角度来看,领域事件一般会对应一段代码逻辑,这段逻辑可能会最终改变数据库中的数据。另外,在事件驱动的架构中,一个领域事件可能会表现为一个向外部发送的异步消息。
  • 命令的作用:领域建模时,可以通过对命令的走查(walkthrough),细化和验证领域模型。在实现层面,一个命令可能对应前端的一个操作,例如按下按钮;对于后端而言,一个命令可能对应一个 API。
  • 命令的执行者:在领域建模时,执行者可能本身就是一个领域对象,也可能是领域对象充当的角色,或者是权限管理中的一个角色。

查询功能不产生领域事件,因此也不会有相应的命令。那么如何保证查询功能不被遗漏呢?

  • 实际上,每个查询数据对应着一个查询功能。查询数据是为某个命令服务。系统中可能还有一些单纯的查询功能,并不与某个特定的命令绑定。这些查询功能不会通过事件风暴识别出来,需要单独进行分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/85766.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/85766.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3中监听 Ref 类型的数字数组

在 Vue 3 中&#xff0c;监听一个 Ref 类型的数字数组&#xff08;如 ref<number[]>([])&#xff09;时&#xff0c;根据需求的不同&#xff0c;有几种监听方式&#xff1a; 1. 监听整个数组的引用变化 当整个数组被重新赋值时触发&#xff1a; typescript 复制 下载…

PoolThreadCache 类的结构和源码实现

PoolThreadCache 在 Netty 的内存池中扮演着线程本地缓存的角色。它的主要目的是减少线程在分配内存时对全局 PoolArena 的竞争&#xff0c;通过缓存一部分最近释放的内存块&#xff0c;使得同一线程后续申请相同规格的内存时能够快速获取&#xff0c;从而提高分配效率。 下面…

Linux中的阻塞信号与信号原理

在Linux操作系统中&#xff0c;信号&#xff08;Signal&#xff09;是进程间通信和进程控制的核心机制之一。信号是一种异步通知机制&#xff0c;可以向进程发送异步事件通知&#xff0c;以便进程能够处理系统级别的事件。本文将详细探讨Linux中的信号原理&#xff0c;重点讲解…

QT学习教程(三十五)

事件处理&#xff08;- Event Processingn&#xff09; 事件是视窗系统或者Qt 本身在各种不同的情况下产生的。当用户点击或者释放鼠标&#xff0c;键盘时&#xff0c;一个鼠标事件或者键盘事件就产生了。当窗口第一次显示时&#xff0c;一个绘制事件会产生告诉新可见的窗口绘…

【Dify 案例】【MCP实战】【三】【超级美食家】

接上次的超级助理,我们这一期给出一个超级美食家 首先:我的MCP要申请一个key ` 我们来看看这个MCP服务怎么使用呢。`https://modelscope.cn/mcp/servers/@worryzyy/howtocook-mcp插件里面需要配置 {"mcpServers":{"amap-amap-sse":{"url":&qu…

4.文件管理(文本、日志、Excel表)

目录 1.文本 2.日志 3.Excel表 1.文本 using System.Text;namespace (自己创建的一个类) {/// <summary>/// 配置文件*.ini读写器。/// </summary>public class IniFile{[System.Runtime.InteropServices.DllImport("kernel32")]private static ex…

Java 包装类详解

什么是包装类 Java包装类&#xff08;Wrapper Classes&#xff09;是将8种基本数据类型封装成对象的类&#xff0c;位于java.lang包中。每个基本数据类型都有对应的包装类&#xff1a; byte → Byteshort → Shortint → Integerlong → Longfloat → Floatdouble → Doublec…

阿里云ACP认证-数据仓库

数据仓库 Kappa架构&#xff1a;将实时和离线代码统一&#xff08;优化lambda架构&#xff09;&#xff0c;但是不好修正数据&#xff0c;开发周期长&#xff0c;成本浪费&#xff0c;对于历史数据的高吞吐量力不从心 原一代数据仓库&#xff1a; 离线&#xff1a;hivemaxcom…

WebRTC(五):TURN协议

TURN&#xff08;Traversal Using Relays around NAT&#xff09;协议是一个网络协议&#xff0c;旨在解决 NAT&#xff08;网络地址转换&#xff09;和防火墙 环境下的 UDP/TCP通信问题。它通常与 STUN 和 ICE 协议一起使用&#xff0c;广泛应用于 WebRTC、SIP 和视频会议等实…

Python 的内置函数 hasattr

Python 内建函数列表 > Python 的内置函数 hasattr Python 的内置函数 hasattr() 用于检查一个对象是否具有指定的属性或方法。该函数的语法为&#xff1a; hasattr(object, name)参数说明&#xff1a; object&#xff1a;要检查的对象&#xff0c;可以是任何 Python 对象…

docker使用技巧之把扩展卷命名变成有意义

背景 之前使用别人的镜像之后&#xff0c;启动docker后发出现了一堆看不懂名称的扩展卷 eg&#xff1a;集群查看 扩展卷查看 这个时候如果有很多集群需要清理扩展卷就很麻烦&#xff0c;不知道是哪个集群的 操作步骤 可以实现的分析&#xff1a;这个扩展卷的信息应该是和…

《博物通书》《博物新编》与满清历史篡改

《博物新编》作为近代西方科技输入中国的首部著作&#xff0c;其问世犹如一颗投入平静湖面的巨石&#xff0c;在 19 世纪中期的中国激起层层涟漪&#xff0c;对中国近代科学发展产生了多维度、深层次的影响。它不仅是知识传播的载体&#xff0c;更是推动中国科学从传统走向近代…

【入门】【例18.1】 睡眠

| 时间限制&#xff1a;C/C 1000MS&#xff0c;其他语言 2000MS 内存限制&#xff1a;C/C 64MB&#xff0c;其他语言 128MB 难度&#xff1a;中等 分数&#xff1a;100 OI排行榜得分&#xff1a;12(0.1分数2难度) 出题人&#xff1a;root | 描述 一个人只有每天睡眠时间到达 8…

DAY 38 Dataset和Dataloader类

知识点回顾&#xff1a; Dataset类的__getitem__和__len__方法&#xff08;本质是python的特殊方法&#xff09;Dataloader类minist手写数据集的了解 作业&#xff1a;了解下cifar数据集&#xff0c;尝试获取其中一张图片 import torch import torch.nn as nn import torch.o…

【Kubernetes】以LOL的视角打开K8s

前言 对于大部分后端程序员乃至于非后端程序员来说&#xff0c;在当前的云原生时代&#xff0c;Kubernetes&#xff08;后称K8s&#xff09;都是绕不开的一项技术&#xff1b;同时&#xff0c;对于这个时代的程序员来说&#xff0c;“英雄联盟”&#xff08;后称LOL&#xff0…

UE5 游戏模板 —— FirstShootGame

UE5 游戏模板 —— FirstShootGame 前言一、GameMode二、组件1.ShooterPickUpComponent单播多播 2.ShooterWeaponComponent附着武器开火 3.小结4.ShooterProjectile初始化碰撞受击检测 三、Character初始化输入移动 总结 前言 有了前两个俯视角游戏的基础让我们来看看相对复杂…

国家级与省级(不含港澳台)标准地图服务网站汇总

在先前的文章中&#xff0c;介绍了部分省级的标准地图服务网站可以下载各个区县近几年、不同要素的标准地图&#xff08;链接&#xff1a;国家与省市县 标准地图服务网站 审图号地图下载&#xff09;&#xff0c;但是当时只汇总了部分省级的标准地图服务网站。 这两天看到了一个…

前端开发面试题总结-vue3框架篇(一)

文章目录 Vue3高频问答一、vue2/vue3中常用的构建工具和脚手架分别是什么? 有什么区别?二、请说一说vue2和vue3的区别&#xff1f;三、请说一说vue2和vue3响应式原理的区别&#xff1f;四、vue3 如何定义响应式数据?五、说一说你对vue3中的setup函数?六、说一说vue3中的路由…

【LLM06---相对位置编码】

文章目录 相对位置编码经典式XLNET式T5式DeBERTa式 相对位置编码 上一节我们介绍了绝对位置编码&#xff0c;这一节我们来看相对位置编码&#xff0c;也就是用相对位置信息来表示&#xff0c;之前每一个token的位置式通过一个绝对的位置向量来表示的&#xff0c;现在我们在计算…

纯跟踪算法本质解密:航向角偏差=预瞄角?数学证明与工程实践

定义关键问题 在深入纯跟踪算法核心前&#xff0c;必须澄清一对容易被混淆但至关重要的概念&#xff1a; 概念坐标系物理意义计算方式航向角偏差(α_global)全局坐标系车辆航向与预瞄点方向的夹角预瞄点方位角 - 车辆航向角预瞄角(α_body)车身坐标系预瞄点相对于车辆纵轴的夹…