Skip to content

PCR-arch 代码审计报告 (2026-05-08)

一、被删除或降级的关键计算逻辑

1. FCC 完全被拆空 (src/fcc/FccCore.cpp: 241 → 7 行)

cpp
FccOutFrame run_fcc_step(const FccInFrame& in, FccState& state, const FccEnv& env) {
    return FccOutFrame{};
}

原分支的 Free Monad 解释器、Navigation/Guidance/Control 管线、Stage FSM 路由、Shutdown 逻辑、Interrupt handling 全部移除。src/main/closed_loop_10s.cpp 里也不再调用 FCC,整个"闭环"实际上是纯被动弹道积分。

2. plant/physics/Drag.cpp (137 → 44 行)

被删除:

  • compute_ascending_aero / compute_descending_aero 的完整 6 分量(力+力矩)查表
  • aero_coeffs_ascending / aero_coeffs_descending 表驱动(含零位、俯仰、偏航、滚转小偏差)
  • 栅格舵(grid fin)舵偏注入
  • 绕质心的力矩修正项 (0.0 - centroid) * F_y/F_z
  • FAI_Q → PHI_A 下降段坐标转换
  • Aero→Body1→Body2 的三次坐标变换矩阵

被替换为:hard-coded Cd(Mach) 折线(0.42~0.65 之间),只算轴向阻力标量,以 ecf_pos.magnitude() < 6400000 判断上升/下降(这实际是海平面以下的判据,并非返回段判据)。

3. plant/physics/Thrust.cpp (158 → 46 行)

被删除:

  • 小偏量修正 (apply_perturbation),即 stage_dev × perturb_coeffs 推力-流量扰动
  • 喷管→本体的旋转矩阵 Rz(tau)·Ry(r)·Rx(phi).T,基于 location_angle, gimbal_install_angle, actuator_install_deviation——外侧发动机的推力方向因此会被错误算成轴向
  • 关于当前质心的力臂:旧版 lever = (centroid.x - install.x_offset, 0, install.z_offset);新版退化为 mount_pos_body.cross(f_body),完全忽略瞬时质心,力矩会有系统性偏差
  • 正确的背压补偿基准 nozzle_area * (design_back_pressure - p_amb),新版仅 -p_amb * area

4. plant/physics/FlightStateProber.cpp (104 → 61 行)

被删除:

  • 100 km 卡门线气动截断 — 新版在轨道段会继续吃非零动压
  • 全部气动角计算 alpha_A, alpha, beta, FAI_Q — 即便将来恢复查表,入参也已缺失
  • 流向符号翻转:旧版 flow_lic = -(v_rel_earth - v_wind)(来流方向,与飞行方向相反),新版 v_air_lic = v_rel_earth - v_wind(飞行空速方向)。配合新 Drag 的 flow_dir * drag_mag,阻力现在沿飞行方向加速火箭而非减速。

同时 Assembler.cpp 给出的 mach_number = [](double v, double h){ return v/340.0; } 参数顺序与调用点 env.atmosphere.mach_number(h, v_mag) 相反。

5. plant/physics/Gravity.cpp

新版用 μ/r² 的 ECF 中心引力(形式上比旧版的 -9.80665 占位更好),但自注释承认直接把 ECF 向量塞进 gravity_lic——t=0 之后发射点随地球转动,误差越积越大。

6. dynamics/PhysicalRegistry.cpp

  • 没有 Hardware Phase 1(发动机 FSM 步进、ICU Mealy、SCU 伺服)
  • engine_effects 必须外部注入,而 closed_loop_10s.cpp 传入 {}——火箭永远不会点火
  • update_inertial_propertiesengine_mass = 50.0 硬编码、inertia = I·(m·10) 写死单位阵
  • const_cast<runtime::WorldEnv&>(env).bus.publish(...) 粗暴破坏 Reader monad 的 const 约束
  • 没有 TopologyEvent 的产生/消费循环

7. 保留未退化的部分

  • ode/EquationsOfMotion.cpp:RK4 导数、pack/unpack、欧拉方程、四元数导数、pad-clamp 约束 — 几乎逐行保留
  • ode/Integrator.cppintegrate_euler / integrate_rk4 — 完全一致
  • types/, Frames.h, Monad RWS infrastructure — 基本不变

二、相对 Refactoring 文档的架构落实度(以 Blueprint 为主依据)

文档承诺代码现状落实度
八层静态库 truth/plant_model/plant_physics/plant_hardware/bus/fcc/dynamics_core/runtime目录已创建但内容分布混乱:src/plant/ 仍是主力,src/plant_model/ 只有 2 个 header,src/plant_hardware/ 空,src/dynamics_core/ 只有一个未引用的 StageMachine.h30%
强类型 BusMessage{src, dst, emitted_at, variant<Imu/Gps/Scu/IcuPayload>}src/bus/IBus.h + BusPayloads.h + TransparentBus.h 定义(namespace pcr::bus),但这些头 #include "src/types/Vector.h"(不存在)和 "src/types/Time.h"(路径错),根本不会被编译进任何 target。真正使用的仍是老的 bus::BusChannel(namespace busstd::vector<double> payload + SignalTag)。两个平行的"总线宇宙"共存。20%
三相管线 (Hardware FSM → Physics → Integration+Topology+Route)只有 Phase 2。Phase 1 被删,Phase 3 仅保留 integrate33%
dynamics_v1/stages.yaml 声明式 per-body 阶段机没有 YAML;BodyStageAlgebra 只有 SeparationOpIgnitionOpstd::variant 硬编码,且 IgnitionOp 分支是 no-op10%
Run = Rocket × Mission × World × Deployment 四维正交装配只有 data/input/world/;没有 missions/deployments/runs/Assembler 从单一 world.yaml 入口装配,没有 Deployment 模板25%
AssembledPlant reflectable tree + RuntimeTables(slot→spec、slot→ICU 全 uint32 O(1))Assembler.cpp 只填充 BodyAsset.engines(字符串 id + 基本几何)。没有 slot_to_specicu_to_slotsRuntimeTables15%
Bus<MemoryTransport> 模板化 Transport 编译期绑定TransparentBus 是 vtable 版(没问题),但没有 UDP/CAN 配套,也没有按 Transport 模板化25%
AvionicsAction::ActivateClone / Continue / None 在分离时深拷贝 FCC 状态完全缺失 — BodyStageAlgebra::evolve_topology 只复制几何与 engines_state,不涉及 FCC/Bus 继承0%
FCC 可独立链接至 RTOS(八层库里最重要的可移植目标)FCC 被掏空,无法作为独立库承担任何任务0%

三、对新实现的困惑与潜在问题

  1. FCC 的 7 行 stub:是阶段性"先让动力学侧编译过"的占位,还是 free_monad/ 子系统迁移到 pcr::bus::IcuPayload/ScuPayload 还没完成?src/fcc/core/Navigation.cppguidance/Guidance.cppcontrol/Control.cpp 等文件都还在,但被 FccCore.cpp 绕过。恢复路径是什么?

  2. 两套 Bus 并存pcr::bus:: 的三个头文件(符合 Blueprint)根本编不过(include 路径 src/types/Vector.h 不存在),但文件在 CMakeLists.txt 里是列出的?同时 runtime::WorldEnv 里嵌的是老的 bus::BusChannel。哪一个是"正朔"?建议是要 pcr::bus::IBus 成为唯一入口,bus::BusChannel 作为 deprecated。

  3. flow_in_body 符号翻转:这是 bug 还是 Drag.cpp 将来会配合地改?目前是静默的物理错误——火箭会被"阻力"推着走,但数值不会爆,很难在 regression test 里发现。

  4. closed_loop_10s.cpp 其实是纯被动弹道:主循环里 engine_effects = {},不调用 FCC,但 stage_name 被硬写成 "BOOSTER"。命名误导。要不要改成 ballistic_integrator_smoke_test.cpp 直到闭环真正恢复?

  5. update_inertial_properties 的魔法常数engine_mass=50I = m·10·I3,完全绕过 YAML 的 inertia_table。是 PoC 范围内接受的简化,还是待做?这会直接影响 RK4 的转动积分稳定性。

  6. Gravity 的 ECF 直接塞进 gravity_lic:注释说"为了过编译先这样"。FrameConfig 里有 ecf_to_lic_matrix(t) 吗?我在 WorldEnv.h 里没看到,这个 TODO 该怎么闭合?

  7. dynamics_core/StageMachine.h 的身份:这个头定义了 BodyStageTag{ASCENT_BOOST, ASCENT_COAST, DESCENT_BALLISTIC, DESCENT_AERO_BRAKING, LANDING_BURN},和 PoC 文档 §2.1 里的 prelaunch / engine_startup / power_ascend / descent_ballistic / descent_powered / coast_to_ignition / upper_ascend 不一致,并且没有被任何 .cpp 引用。是废弃草稿还是还没 wire up?

  8. Mission 域完全缺席:PoC §1 定义的 Mission 维度(初始约束 pinned、分离事件列表、传感器注入)在 data/input/ 里找不到对应 YAML,也没有 MissionConfig C++ 类型。这是不是整个 PoC 还没开始动的一大块?

  9. const_cast<runtime::WorldEnv&>(env).bus.publish:这里把 const Reader 环境强行改写,等于默认 WorldEnv 里的 bus/monitor 是可变的单例,违背"Reader 只读"原则。切到 pcr::bus::TransparentBus 后,IBus* 指针本身可以 const,但底层 mailbox 仍需可变——是否在 PlantScope/RuntimeContext 里单独拿出来、不塞在 WorldEnv 这一 Reader?


四、总体判断

pcr-arch 分支是一次结构性框架落地 + 计算逻辑临时搁置的提交:

  • 结构分层雏形建立:目录拆分、namespace、plant_model / plant_physics / plant_hardware / bus / runtime / dynamics_core 架构已初步可见。
  • 类型骨架搭建Forces Monoid、BodyEnvruntime::WorldEnvBodyStageAlgebrapcr::bus variant payload 等基础设施已就绪。
  • 计算逻辑断档Thrust / Drag / FlightStateProber / Gravity 四大物理 kernel、FCC 全家桶、Hardware FSM/ICU/SCU、Mission+Deployment 四维正交配置,目前处于占位或严重简化状态。