Skip to content

Time and Clock System

> Status: PATCH · 已对齐 PCR Master Blueprint v1.0 > 范畴: src/types/Time.h > 依赖: 无(POD value type)

The foundation of the entire architecture. This system guarantees deterministic physics and zero time-drift errors.

Core Philosophy

  1. No Floats for Time: Floating-point addition is non-associative (a + b) + c != a + (b + c). Accumulating small dt over a long simulation will drift. We use int64_t ticks.
  2. Fixed Precision: The base unit is 1 tick = 0.1ms (100μs). This is sufficient for both high-frequency dynamics (1kHz+) and long-duration missions.
  3. Adaptive Clock: The simulation clock must support variable steps to align perfectly with critical events (e.g., IMU sampling, engine cutoff).
  4. No std::chrono: 仿真的 wall clock 与 OS 时钟无关。std::chrono::steady_clock 漂移、跨进程不可序列化。我们的 Time 是仿真域专属类型。

1. The Time Class

A value type representing a point in time or a duration.

cpp
// src/types/Time.h
#include <cstdint>
#include <compare>
#include <ostream>

class Time {
    // The only data member: 0.1ms ticks
    int64_t ticks_;

    // Private constructor to force usage of static factories
    constexpr explicit Time(int64_t t) : ticks_(t) {}

public:
    // --- Factories ---
    static constexpr Time zero() { return Time(0); }
    static constexpr Time from_ticks(int64_t t) { return Time(t); }
    static constexpr Time from_sec(double s) { 
        return Time(static_cast<int64_t>(s * 10000.0 + 0.5)); 
    }
    static constexpr Time from_ms(double ms) { 
        return Time(static_cast<int64_t>(ms * 10.0 + 0.5)); 
    }
    static constexpr Time from_hz(int hz) {     // 50 Hz → 0.02s = 200 ticks
        return Time(10000 / hz);
    }

    // --- Accessors ---
    constexpr int64_t ticks() const { return ticks_; }
    constexpr double to_sec() const { return ticks_ * 0.0001; }
    constexpr double to_ms() const { return ticks_ * 0.1; }

    // --- Arithmetic ---
    constexpr Time operator+(Time other) const { return Time(ticks_ + other.ticks_); }
    constexpr Time operator-(Time other) const { return Time(ticks_ - other.ticks_); }
    constexpr Time operator*(int64_t s) const { return Time(ticks_ * s); }
    constexpr Time operator/(int64_t s) const { return Time(ticks_ / s); }
    
    // --- Comparison (C++20 spaceship) ---
    constexpr auto operator<=>(const Time&) const = default;

    // --- Output ---
    friend std::ostream& operator<<(std::ostream& os, Time t) {
        return os << t.to_sec() << "s";
    }
};

// User-defined literals for convenience
constexpr Time operator""_s(long double s) { return Time::from_sec(static_cast<double>(s)); }
constexpr Time operator""_ms(long double ms) { return Time::from_ms(static_cast<double>(ms)); }

> v1.0 增补from_hz(int) 是必须的;调度器 sim::MultiRateScheduler 用它构造 fcc_period = Time::from_hz(50) / phys_period = Time::from_hz(1000)(详见 06_Simulation/Body_World_Tick.md §6)。

2. Clock — 仿真主时钟(在 WorldState 内)

仿真主时钟存在于 sim::WorldState.current_time,由 WorldTick 阶段 A 推进(详见 06_Simulation/Body_World_Tick.md §3.2)。没有独立的 Clock 对象——之前 v0 的 Clock 结构已废弃,因为:

  1. 自适应步长由 sim::MultiRateScheduler 统一管理(不再 per-state)
  2. target_time 概念由 mission_config.end_time 提供
  3. IMU sampling alignment 由设备 FSM 内部完成(不再主循环对齐)
cpp
// simulation/state/WorldState.h(节选)
namespace sim {

struct WorldState {
    Time current_time;
    std::vector<RocketBody> bodies;
    // ... 拓扑事件历史等
};

} // namespace sim

3. MultiRateScheduler

详见 06_Simulation/Body_World_Tick.md §6 与 04_FCC/Static_Compilation_FSM.md。简要:

cpp
namespace sim {

struct MultiRateScheduler {
    Time fcc_period    { Time::from_hz(50)   };  // FCC 50 Hz
    Time phys_period   { Time::from_hz(1000) };  // 物理 1 kHz
    Time last_fcc_tick { Time::zero() };

    bool should_fcc_tick(Time now);   // O(1) 整数比较,决定本 phys tick 是否驱动 FCC
};

} // namespace sim

> 强约束phys_period.ticks() 必须整除 fcc_period.ticks(),否则会出现"漂移"。详见 06_Simulation/Body_World_Tick.md §6.4 频率匹配表。

4. Usage Example

cpp
// 1. Define times naturally
Time t_start      = 0_s;
Time phys_dt      = 1_ms;
Time mission_end  = 300.5_s;

// 2. Runner main loop
sim::WorldState ws;
ws.current_time = t_start;
sim::MultiRateScheduler scheduler;

while (ws.current_time < mission_end) {
    auto [wout, new_ws, log] = sim::world_tick(phys_dt).run(world_env, std::move(ws));
    ws = std::move(new_ws);
    // ws.current_time 已经在 world_tick 内推进了 phys_dt
}

详见 07_Runtime/Assembler_and_Runner.md §4.3。

5. C-Distillation 路径

C++C
class Time { int64_t ticks_; }typedef int64_t Time;struct Time { int64_t ticks; };
operator+/-static inline Time time_add(Time a, Time b);
user-defined literals _s_ms编译期 #define MS(x) ((Time){(x) * 10})
from_hz(int)static inline Time time_from_hz(int hz)

详见 08_Cross_Cutting/Implementation_Roadmap.md §7。

6. 引用

  • Blueprint §0("无浮点时间" 是基础约束)、§2.7(Runtime 持有主循环)、§2.6.4(多速率调度)
  • 06_Simulation/Body_World_Tick.md §6(MultiRateScheduler)
  • 07_Runtime/Assembler_and_Runner.md §4.3(Runner main loop 使用 Time)
  • 06_Simulation/Dual_Layer_RWS.md(BodyEnv.current_time 是 Time 类型)