火箭推力计算流程详解 (Thrust Calculation Pipeline)
概述 (Overview)
推力系统遵循 5 阶段数据流:YAML 配置 → CSV 表格加载 → 发动机状态机 → 真空推力查表 → 动力学力管线。它跨越了三个命名空间(io, rocket, dynamics),并使用单子化(Monadic)的 BodyRWS 架构进行纯函数式组合。
阶段 1:配置加载 (Configuration Loading: YAML → Structs)
入口点 (Entry Point): data/input/rocket_v1/rocket.yaml:19-20
devices: "devices.yaml"火箭配置引用外部的 devices.yaml 文件。
设备配置 (Device Config): data/input/rocket_v1/devices.yaml:1-55
在 COMPOSITE 键下定义发动机组。每台发动机包含:
id— 例如"center_engine","peripheral_engine_1"rated_thrust— 标称真空推力 (牛顿),中心发动机为 679700.0,周向为 693357.143。install— 物理安装几何(万向节限位、方位角、安装角、执行器偏差、轴向/径向偏移)。tables— 6 个用于插值曲线的 CSV 文件路径。
加载链 (Loading Chain):
BodyAsset::load_from_yaml()(src/dynamics/config/BodyAsset.cpp:48-52) 检测到devices键,解析路径并委托给:EngineConfig::load_from_yaml()(src/rocket/device/actuator/EngineConfig.cpp:31-106)- 递归处理标量节点(文件引用)(35-39 行)。
- 解析顶层常量:
rated_thrust_center,rated_thrust_peripheral,skip_liftoff_time_calculation,real_liftoff_time。 - 迭代映射键作为阶段组名(48 行)。
- 为每个组解析可选的
deviations(4 元素数组,56-62 行)和engines列表。 - 为每个发动机节点构建
EngineUnitConfig(70-101 行):- 解析
InstallParams(75-81 行)。 - 通过
CSVReader::load_table_1d()加载 6 个 CSV 表到shared_ptr<InterpTable1D>(93-98 行)。
- 解析
- 填充
engine_groups[key](分组)和engines(平铺列表)。
核心结构体 (Key Structs):
InstallParams (src/rocket/device/actuator/EngineConfig.h:19-26):
struct InstallParams {
double gimbal_limit; // rad
double location_angle; // 喷管方位角 (rad)
double gimbal_install_angle; // 喷管安装角 (rad)
double actuator_install_deviation; // 舵机扭转偏差 (rad)
double x_offset; // 距离头部的轴向偏移 (m)
double z_offset; // 径向偏移 (m), 中心发动机为 0
};EngineUnitConfig (src/rocket/device/actuator/EngineConfig.h:31-43):
struct EngineUnitConfig {
std::string id;
InstallParams install;
double rated_thrust;
shared_ptr<InterpTable1D> thrust_start; // 起动推力曲线
shared_ptr<InterpTable1D> thrust_stop; // 关机推力曲线
shared_ptr<InterpTable1D> mass_flux_start; // 起动质量流
shared_ptr<InterpTable1D> mass_flux_stop; // 关机质量流
shared_ptr<InterpTable1D> perturb; // 摄动系数
shared_ptr<InterpTable1D> params; // 运行参数 vs 推力
};EngineConfig (class) (src/rocket/device/actuator/EngineConfig.h:51-75):
class EngineConfig {
map<string, vector<EngineUnitConfig>> engine_groups; // 按阶段分组
map<string, array<double,4>> stage_deviations; // 摄动种子
vector<EngineUnitConfig> engines; // 平铺列表
bool skip_liftoff_time_calculation = false;
double real_liftoff_time = 0.0;
double rated_thrust_center = 0.0;
double rated_thrust_peripheral = 0.0;
};阶段 2:CSV 表格加载与插值 (CSV Table Loading & Interpolation)
CSV 读取器 (CSV Reader): src/io/reader/CSVReader.h:26-68
CSVReader::load_table_1d() 读取 CSV 文件,其中第 0 列是自变量 (x),第 1..N 列是因变量 (y)。跳过以 # 开头或为空的行。
InterpTable1D: src/io/types/InterpTable1D.h:23-157
核心插值表功能:
x_values— 断点。y_columns— 多个输出列。interpolator(col_index)— 返回单列查找的std::function<double(double)>闭包。all_interpolator()— 返回一次性查找所有列的std::function<vector<double>(double)>闭包。- 使用 线性插值 并在边界处钳位(139-156 行):
- 低于最小 x → 返回第一个 y。
- 高于最大 x → 返回最后一个 y。
- 否则 →
y0 + t * (y1 - y0),其中t = (x - x0) / (x1 - x0)。
每个发动机的 6 张 CSV 表:
| 表名 (Table) | X 轴 (X-axis) | Y 列 (Y-columns) | 用途 (Purpose) |
|---|---|---|---|
thrust_start | 时间 (s) | 推力 (N) | 起动爬升过程 (0→3s,随后稳定) |
thrust_stop | 时间 (s) | 推力 (N) | 关机衰减过程 (0→1s) |
mass_flux_start | 时间 (s) | 燃料 (kg/s), 氧化剂 (kg/s) | 起动过程质量流 |
mass_flux_stop | 时间 (s) | 燃料 (kg/s), 氧化剂 (kg/s) | 关机过程质量流 |
params | 推力 (N) | 参考推力, Isp, 燃料流量, 氧化剂流量 | 以推力水平索引的运行参数 |
perturb | 油门比 (throttle ratio) | 12 个摄动系数 | 小偏差修正矩阵 |
示例: center_thrust_start.csv 显示推力从 t=0.7s 时的 0N 爬升至 t=3.0s 时的 679723N。
阶段 3:发动机状态机与真空输出 (Engine State Machine & Vacuum Output)
发动机状态 (Engine States): src/rocket/device/actuator/EngineState.h:11-16
OFF → STARTING → RUNNING → SHUTTING_DOWN → OFF状态机 (State Machine): EngineModel::evaluate_phase() (src/rocket/device/actuator/EngineModel.h:14-60)
- 处理
BusMessage命令以触发状态转换。 OFF + cmd_active→STARTING(elapsed_time = 0 或real_liftoff_time)。STARTING + !cmd_active→OFF。RUNNING + !cmd_active→SHUTTING_DOWN。- 自动转换:
STARTING3.0s 后 →RUNNING;SHUTTING_DOWN1.0s 后 →OFF。
真空输出 (Vacuum Output): EngineModel::evaluate_vacuum_output() (src/rocket/device/actuator/EngineModel.h:63-110)
这是核心推力查表逻辑,根据发动机相位分支:
- STARTING:
vacuum_thrust = throttle * thrust_start.interpolate(elapsed_time),质量流从mass_flux_start按base_t索引。 - RUNNING:
vacuum_thrust = throttle * rated_thrust,质量流从params第 2, 3 列按base_t索引。 - SHUTTING_DOWN:
vacuum_thrust = throttle * thrust_stop.interpolate(elapsed_time),质量流从mass_flux_stop按base_t索引。 - OFF: 全部为 0。
返回一个 EngineEffect 结构体。
EngineEffect: src/rocket/interface/PhysicalEffect.h:13-25
struct EngineEffect {
uint32_t engine_id;
double vacuum_thrust;
double mass_flow_fuel;
double mass_flow_ox;
double current_throttle;
Angle nozzle_pitch;
Angle nozzle_yaw;
};阶段 4:动力学推力管线 (Dynamics Thrust Pipeline: BodyRWS)
EngineEffect 向量跨越火箭→动力学边界并进入 compute_thrust_pipeline()。
管线 (Pipeline): src/dynamics/pipeline/Thrust.cpp:145-153
apply_perturbation → compensate_ambient_pressure → resolve_thrust_vectors三个单子化阶段使用 >> (bind) 链式调用:
4a. 摄动修正 (Perturbation Correction): Thrust.cpp:40-85
- 通过
body.body_id从EngineConfig查找stage_deviations(4 元素数组:[δφ, δψ, δγ, δx])。 - 对于每个
vacuum_thrust > 0且具有有效perturb/params表的发动机:- 通过
perturb->all_interpolator()在current_throttle处插值所有 12 个摄动系数。 - 使用 4 个偏差参数与系数子集的点积计算 3 个修正量:
dF= Σ(stage_dev[i] * coeffs[0..3]) — 推力修正。dMf_f= Σ(stage_dev[i] * coeffs[4..7]) — 燃料流量修正。dMf_ox= Σ(stage_dev[i] * coeffs[8..11]) — 氧化剂流量修正。
- 从
params表获取参考推力。 - 应用:
vacuum_thrust = vacuum_thrust + dF - ref_thrust。
- 通过
4b. 环境压力补偿 (Ambient Pressure Compensation): Thrust.cpp:88-105
- 从
AeroCtx读取static_pressure。 - 对于每个发动机:
actual_thrust = vacuum_thrust + Sa * (101325.0 - pressure)Sa = 0.6578(喷管出口面积 m²,目前硬编码 — 95 行标记为 TODO)。- 这是标准的喷管出口面积压力修正:在海平面 (101325 Pa) 补偿值为 0;在真空下增加
Sa * 101325N。
4c. 矢量分解与力矩 (Vector Resolution & Torque): Thrust.cpp:108-141
对于每台发动机:
- 喷管坐标系推力矢量 (
Thrust.cpp:11-16):F_nozzle = magnitude * [cos(gz)*cos(gy), sin(gz)*cos(gy), -sin(gy)]其中gy= 万向节偏航 (yaw),gz= 万向节俯仰 (pitch)(来自舵机)。 - 喷管到体轴旋转 (
Thrust.cpp:18-21):R = transpose(Rz(τ) * Ry(r) * Rx(φ))其中φ=location_angle,r=gimbal_install_angle,τ=actuator_install_deviation。 - 体轴系作用力:
F_body = R * F_nozzle - 力臂 (
Thrust.cpp:23-25):lever = [centroid_x - x_offset, 0, z_offset]其中centroid_x是来自body.inertial_state.centroid的当前质心位置。 - 力矩:
torque = lever × F_body - 累加: 将所有发动机的
F_body和torque累加到ThrustAndMassFlux.ft,并求和所有质量流。
输出类型 (Output Types): src/dynamics/interface/PhysicalTypes.h:1-64
struct ThrustAndMassFlux {
vector<EngineForceState> engine_states; // 单个发动机结果
ForceAndTorque ft; // 体轴系总力和力矩
MassFluxResult mf; // 总/燃料/氧化剂质量流
};阶段 5:整合至物理注册表 (Integration into PhysicalRegistry)
src/dynamics/pipeline/PhysicalRegistry.cpp:13-97
WorldRWS 编排器逻辑:
- 并行分发 (Parallel dispatch) (30-78 行): 为每个物体启动
std::async:- 探测上下文:
TrajectoryCtx,AeroCtx,MassPropsCtx。 - 注入包含资产(包含
EngineConfig)、探测到的上下文和时间的BodyEnv。 - 构建管线:
Forces::zero() >> compute_thrust_pipeline >> compute_aero_forces >> compute_gravity_forces。 - 推力结果累加至
Forces:cppnext_f.total_force_b += res.ft.force; next_f.total_moment_b += res.ft.torque; next_f.d_mass_dt += res.mf.total; next_f.d_fuel_dt += res.mf.fuel; next_f.d_oxidizer_dt += res.mf.oxidizer;
- 探测上下文:
- 合并 (Merge) (80-94 行): 收集 futures,更新
WorldState.bodies,通过单子加法合并DynLog。
环境注入路径 (Environment Injection Path):
WorldEnv.body_assets["COMPOSITE"].engines (EngineConfig) → BodyEnv.asset.engines → 动力学内核通过 body_ask() → env.asset.engines.engines[i] 访问。
数据流简图 (Summary Data Flow Diagram)
YAML (devices.yaml)
└→ EngineConfig::load_from_yaml()
└→ CSVReader::load_table_1d() × 每台发动机 6 张表
└→ InterpTable1D (带边界钳位的线性插值)
BusMessage (点火命令)
└→ EngineModel::evaluate_phase() [状态机: OFF→STARTING→RUNNING→SHUTTING_DOWN]
└→ EngineModel::evaluate_vacuum_output() [基于相位和油门的查表]
└→ EngineEffect {真空推力, 质量流, 喷管角度}
EngineEffect[]
└→ compute_thrust_pipeline() [BodyRWS 单子链]
├→ apply_perturbation() [基于摄动表的小偏差修正]
├→ compensate_ambient_pressure() [F = F_vac + Sa*(P0 - P_atm)]
└→ resolve_thrust_vectors() [喷管→体轴旋转, 力臂, 力矩]
└→ ThrustAndMassFlux {体轴力, 体轴力矩, 质量流}
PhysicalRegistry (WorldRWS)
└→ 累加至 Forces → 馈送给 ODE 积分器