This guide gets you oriented with the Core Engine: what it is, what you need to run it, and how its frame loop, scheduler, states, and threading model fit together.
1. Understand What the Core Engine Does
The Core Engine is a modular real-time execution system that runs simulations in fixed-rate frames. It lets you:
- Execute logic at a precise refresh rate (e.g., 1 kHz)
- Handle real-time data recording and playback
- Schedule frame-based tasks deterministically
- Integrate external models, hardware, or I/O systems
- Guarantee low-jitter and strict timing control
It is used for embedded simulation, signal generation, hardware-in-the-loop (HIL), control-loop testing, and high-frequency data processing.
2. Check System Requirements
- Windows or Linux
- Recommended: CPU with stable TSC, real-time priority enabled, high-resolution timers, PREEMPT_RT kernel (Linux) or MMCSS (Windows)
- C++ compiler with CMake support
- C++14 or newer
3. Learn the Frame Loop
At the heart of the Core Engine is the Frame Loop, a high-precision, fixed-period execution cycle. Every frame is one "tick" of simulation time, and each tick:
- Sleeps/spins until the next frame start.
- Executes all tasks registered for this frame.
- Processes recording/IO operations.
- Reports timing information.
- Returns to waiting for the next frame boundary.
This produces a stable "heartbeat" for your simulation, giving time-critical algorithms stable sampling intervals, keeping hardware interfaces consistent, and enabling repeatable, debuggable simulations.
4. Write Correct Work Section Code
Each frame is composed of these sections:
- Work Section – all simulation logic divided into models and states components
- Interface Section – I/O send/receive from external interfaces
- Recording / Data Exchange
- Timing Control – busy wait or sleep to maintain exact frame rate
Treat the Work Section like a real-time ISR: fast, predictable, and isolated. Follow these rules:
- Keep it short and deterministic.
- No dynamic memory allocations (
new,malloc,vector push_back). - No disk access.
- Avoid locks unless absolutely necessary.
- Avoid slow/logging functions (
printf,std::cout). - Pre-allocate buffers and reuse them.
- Avoid unpredictable branching and large loops; use the built-in state machine instead.
5. Understand the Scheduler
The Scheduler manages and executes tasks during each simulation frame. It:
- Keeps a list of registered tasks/functions
- Calls them in a deterministic order
- Passes the current frame ID to every task
- Allows tasks to be dynamically enabled/disabled
- Ensures modular separation of simulation components
The Scheduler typically manages these task types: core tasks (system internal), user tasks (defined by the simulation developer), I/O tasks (network or device interactions), and recording tasks (data capture).
6. Know the Engine States
The Core Engine uses a simple state machine to control execution:
| State | Meaning |
|---|---|
| Run | Continuous real-time execution |
| Step | Execute exactly one frame and then pause |
| Stop | Terminate simulation immediately |
| Init | Send Init signal to all the Drivers and the Models |
| Reset | Reset all IO drivers and send Reset signal to all Models |
7. Understand the Multi-Threading Model
Although the Frame Loop is single-threaded for determinism, the engine internally uses additional threads so high-frequency execution is not blocked by slower tasks like disk I/O:
- Frame Loop Thread
- Recording Thread
- Reflection Thread
- Network commands Thread
- Stream I/O Threads
- User-defined long async tasks
8. Review an Example Setup
See the reference documentation for a worked example of an AH-60 device development setup, illustrating how the pieces above come together in a real project.