- 哲学对齐:Core vs Plant vs Environment 在数值仿真中,系统的本质可以被抽象为:State(t+dt) = Integrator( State(t), RHS_Forces(State(t), Environment, Assets) )
dynamics_core(普遍的推演引擎 / Calculus & Topology):
角色:它是“时间的主宰”和“拓扑的容器”。它只关心:如何积分(RK4)、欧拉方程如何运作、多体系统如何分裂(拓扑代数)、以及如何用 RWS 单子编排流水线。
无知性:dynamics_core 根本不知道“长征火箭”或“猎鹰火箭”的存在,也不知道“马赫数”是如何计算阻力的。它只知道“如果有力,就会产生加速度”。 2. plant(特定的对象法则 / Specific RHS & Boundary Conditions):
角色:它是被评估的“右端项(Right-Hand Side)”。它包含特定硬件的静态规格(Asset Specs)、特定几何体的气动公式(Drag / Lift计算)、特定发动机的推力曲线(Thrust计算)。 3. environment(外部物理场 / The Universal Stage):
角色:装载风场、引力场、大气密度场。它是所有 plant 评估自身受力时的绝对物理背景。它不属于火箭(Plant),它是宇宙的常量与场。 2. RWS 双层架构与状态/环境的精确映射 基于上述哲学,RWS(Reader-Writer-State)模式的数据结构归属必须严格遵从“谁流转、谁持有;谁使用、谁只读”的原则: Layer 1: WorldRWS (全局拓扑与推演)
State (可变状态):WorldState(包含 std::vector<RocketBody>)。这是推演引擎的最高抽象,必须放在 src/dynamics_core/state/。
Reader (只读环境):WorldEnv。它是 Environment(引力场/风场) 与 Plant Assets(所有火箭型号的蓝图/Specs) 的大集合。它是运行时装配的产物,属于 src/runtime/。 Layer 2: BodyRWS (单体动力学评估)
State (局部可变状态):RocketBody(含 SpatialState, InertialState)。它是 ODE 积分的具体容器,必须放在 src/dynamics_core/state/。
Reader (局部只读上下文):BodyEnv。它是从 WorldEnv 中针对当前 Body 此时此地的状态“探测(Probe)”出来的局部边界条件(如当前的动压 AeroCtx、当前的惯量 MassPropsCtx)。它负责切断 plant 对全局 WorldEnv 的依赖。属于 src/dynamics_core/state/。 3. 重构后的严谨文件结构方案 基于上述推演,我提出以下摒弃历史包袱、严格对齐语义的文件结构: src/ ├── types/ # 纯数学与基础数据类型 │ ├── frames/ # 坐标系 Phantom Types (LIC, ECF, BODY) │ └── monad/ # 纯 FP 基础设施 (RWS, Free, Writer) │ ├── contracts/ # 子系统之间的中立跨域数据包 (DynInFrame, BusMessage) │ ├── environment/ # [新增] 普遍物理场 (解耦自 plant) │ ├── Atmosphere.h # 标准大气模型 (USSA1976) │ ├── GravityField.h # WGS84 引力场 │ └── WindModel.h │ ├── plant/ # 特定的被控对象法则 (Right-Hand Side) │ ├── model/ # 静态资产规格 (EngineSpec, AeroConfig) │ ├── physics/ # 纯函数力学计算 (Thrust.cpp, Drag.cpp, 只依赖 BodyEnv) │ └── hardware/ # 物理实体的机械演化与定义 (Mech.h) │ ├── avionics/ # 电子/电气系统 (基于 Mealy 状态机) │ └── devices/ # 传感器与执行器数字面 (Imu.cpp, Ecu.cpp) │ ├── fcc/ # 飞控计算机 (GNC 算法与 Free Monad 解释器) │ ├── dynamics_core/ # [重命名与净化] 普遍推演引擎 │ ├── ode/ # 运动学方程与积分器 (EquationsOfMotion, RK4) │ ├── algebra/ # 拓扑与阶段代数 (StageOp, evolve_topology) │ ├── state/ # 状态容器与上下文 (WorldState, RocketBody, BodyEnv) │ └── pipeline/ # RWS 流水线编排 (PhysicalRegistry) │ ├── bus/ # 物理/内存总线基础设施 (IBus) │ └── runtime/ # 程序的生命周期管理 ├── loader/ # YAML 解析 ├── Assembler.cpp # 依赖注入:组装 WorldEnv └── WorldEnv.h # 包含 Environment + Plant::Model 4. 方案的核心论点(供与 Claude 讨论) 1. 废弃 dynamics,确立 dynamics_core:这不仅仅是名字的改变,这是宣告该目录只做引擎,不写具体的物理法则。旧的 dynamics/pipeline/Thrust.cpp 是越权行为,必须下放到 plant/physics/。 2. RocketBody 的归属之争:RocketBody 曾放在 plant/model,这是混淆了“设计图纸(Spec)”和“运行时实例(State)”。RocketBody 装着微分方程随时间积分的结果(位置、速度、推进剂余量),所以它必须是 dynamics_core/state/ 的一等公民。 3. Environment 与 Plant 的分离:蓝图中将气动环境和质量配置混在 plant 中,这在语义上是瑕疵。大气层不属于火箭。将 environment 独立,并在运行时一并打包进 WorldEnv,能更完美地诠释“背景场”与“对象”的关系。 4. BodyEnv 是解耦的终极武器:dynamics_core 中的探测器(Prober)结合 WorldEnv 和当前状态,生成局部的 BodyEnv(即当前的边界条件)。然后 dynamics_core 把这个边界条件喂给 plant/physics,算出受力,再拿回来交给 ode/ 积分。这个闭环完美实现了你所说的“微分方程与边界条件的解耦”。 这个方案彻底解决了原来 dynamics 和 dynamics_core 并立的混乱,也解决了具体物理公式到处乱塞的问题。你和 Claude 可以就这种“引擎驱动边界条件计算右端项”的目录映射进行进一步的探讨。