Skip to content

PCR 重构:装配根、Plant Scope 与总线抽象实现细节


1. 配置层:Runner 是唯一的装配根(Composition Root)

Runner 是链接“编译能力”与“运行配置”的终点。配置层划分为:

text
data/input/sim/
├── deployments/
│   ├── sil_monolithic.yaml      # 所有组件在本机
│   ├── dyn_node.yaml            # 只装 Plant + Dynamics,FCC 在远端
│   └── fcc_node.yaml            # 只装 FCC,Plant 在远端
├── missions/                     # 任务脚本(见第 4 点)
│   ├── nominal_ascent.yaml
│   ├── static_fire_test.yaml
│   └── sit_ground_test.yaml
├── worlds/                       # 环境真相(风场、大气、发射场)
│   ├── standard_atmosphere.yaml
│   ├── gale_wind.yaml
│   └── launch_site_wenchang.yaml
└── runs/                         # 具体运行的装配清单
    └── run_001.yaml              # 引用 deployment + mission + world + rocket_version

关键洞察:链接决定“能力上限”,配置决定“能力用多少”

同一个 SIL 二进制可以通过切换 run_xxx.yaml 来模拟不同部署。启动流程:

cpp
// runtime/runner.cpp
int main(int argc, char** argv) {
    auto run = load_run_yaml(argv[1]);        // run_001.yaml
    auto depl = load_deployment(run.deployment);   // sil_monolithic.yaml
    
    RunContext ctx;
    if (depl.has_plant)    ctx.plant    = load_plant(run.rocket_version);
    if (depl.has_dynamics) ctx.dynamics = load_mission(run.mission);
    if (depl.has_fcc)      ctx.fcc      = load_fcc_config(run.rocket_version);
    if (depl.has_world)    ctx.world    = load_world(run.world);
    apply_overrides(ctx, run.overrides);

    // 编译期已选定模板,运行期选择 Transport 参数
    auto bus = make_bus(depl.transport);
    
    // 装配
    auto assembled = assemble(ctx);
    run_simulation(assembled, bus);
}

2. Plant Scope 概念:一套真相,三种视图

Plant 物理真相始终唯一,但不同部署下实例化的子集不同:

cpp
// plant_model 层
struct PlantScope {
    bool include_physics_bodies;    // 气动、推力、质量 → 要积分的
    bool include_hardware_engines;  // 发动机状态机
    bool include_hardware_sensors;  // IMU/GPS 状态演化
    bool include_hardware_icus;     // ICU 状态机
    bool include_bus_endpoints;     // 本机驻留的总线节点集合
    std::vector<uint32_t> local_bus_addresses;  // 本机承载的地址
    std::vector<uint32_t> remote_bus_addresses; // 需要通过 Transport 代理的
};

在 HIL 部署中,远端地址会被装配为 BusProxy(如 UdpBusProxy),使得本地 ICU 无法区分 FCC 是本地还是远端——这就是 Transport 抽象的价值。


3. Assembler 输出:可反射的装配树(前端数据模型)

AssembledPlant 既是热路径数据,又是自省式树(introspectable tree):

cpp
// plant_model 层
struct AssembledNode {
    std::string kind;                         // "EngineGroup", "Icu", "ImuUnit"
    std::string display_name;                 // "一级助推器发动机组"
    std::string path;                         // "/rocket/propulsion/stage_1_group"
    
    std::map<std::string, Value> parameters;  // YAML 原始参数
    std::vector<AssetRef> assets;             // 曲线/表格引用
    std::vector<std::string> controlled_by;   // 拓扑关联:控制者
    std::vector<std::string> controls;        // 拓扑关联:被控对象
    
    std::map<std::string, Value> mutable_initial_state; // 加注量、惯组误差等
};

struct AssembledPlant {
    std::vector<AssembledNode> nodes;
    std::unordered_map<std::string, size_t> path_index;
    RuntimeTables runtime;                    // O(1) uint32 索引热路径视图
};

4. Mission × Rocket × World 三正交维度

stages.yaml 属于 Mission 属性而非 Rocket 属性。

  • Mission:定义初始状态、动力学约束(如 pinned)、事件机、传感器数据注入。
  • 正交组合Run = Rocket × Mission × World × Deployment

例如:同一枚火箭,在“名义飞行”任务中包含分离事件,在“静态点火”任务中则是固定在架位上(约束自由度),无分离事件。


5. 代数效应与 BodyStageAlgebra

BodyStageAlgebra 是声明式的操作集合,YAML 驱动,C++ 解释。

cpp
enum class StageOp {
    IgniteEngines { slots: [...] },
    ShutdownEngines { slots: [...] },
    TransitionAerodynamicModel { from: ascending, to: descending },
    SplitBody { into: [...], sep_plane: ... },
};

struct StageTransition {
    StageTag from;
    EventMatcher trigger;
    std::vector<StageOp> ops;
    StageTag to;
};

6. HardwareState 与 HardwareOutput 的单子链演化

硬件层遵循 Mealy 机模式:

cpp
// 长期存在的内部状态(跨 tick 累积)
struct HardwareState {
    std::map<uint32_t, EngineFsm> engine_fsms;
    std::map<uint32_t, double> icu_delay_timers; // 处理如 1s 延时分离
    std::map<uint32_t, ImuBias> imu_biases;
};

// 本 tick 的瞬时产出
struct HardwareOutput {
    std::vector<EngineEffect> engine_effects;
    std::vector<BusMessage> emitted_bus_messages;
    std::vector<TopologyEvent> topology_events; // 由状态机演化产生(如延时到期)
};

// 演化规则
std::pair<HardwareState, HardwareOutput>
step_hardware(const HardwareState& prev, const std::vector<BusMessage>& incoming, const BodyPhysicalState& phys, Time dt);

三相管线单子链(Monad Chain):

  1. Phase 1: Hardware:硬件状态演化 -> 产出 HardwareOutput
  2. Phase 2: Physics:通过 Reader 注入 HardwareOutput 计算力 -> 积分导数。
  3. Phase 3: Topology & Bus:消费 topology_events 改变 body 集合,路由消息。

7. Bus 在不同部署下的角色

Bus 是跨场景的枢纽,所有节点只对 Bus 地址可见。

模式Transport 实现消息特征用途
SILMemoryTransport原生 C++ 结构体,零拷贝验证算法,回归测试
Dyn-HILUdpTransportUDP 序列化,跨机通信FCC 实时机联调
FCC-HILCanTransportCAN 帧编码,硬件总线飞控软件压力测试

代码通过模板 Transport 保持完全一致:Bus<MemoryTransport> vs Bus<UdpTransport>