Control Systems Architecture

ControlDeck is designed for real-time control systems and utilizes the concepts of timers and events. It's very important to note that ControlDeck does not run code unless some module is responding to an event or a timer. Therefore, it is generally necessary that at least one module have installed a timer; otherwise no code will ever run. The exception to this is when modules utilize the background processing functions.


Individual modules can request that ControlDeck notify them after a certain time period has passed. This allows them to go to sleep, waking up only on a pre-defined schedule to perform work. For instance, a module might request to be notified every half-second to perform some particular control work. Timers can be set on a per-module basis, and the only limitation is based on the hardware's timer granularity. This is typically at the millisecond level. It is quite possible for module A to request a timer every 300 milliseconds, and module B to request a separate timer at a 5 second interval. An individual module can even have multiple timers active at once, if different jobs require different sequencing; the module will be woken up separately for each job, and a unique code is provided so that the module knows what timer has been fired. For more information on timers, see cd_control_module::request_timer()


Modules can also request to be notified when events are triggered. An event is uniquely identified by a group and name, just as with a variable; also like a variable, the group defaults to the name of the module's system. A particular module triggers the event by specifying the group and name of the event to trigger; all other modules that have requested notification for that event are then woken up to respond to it. It is important to note that the module triggering the event will block (not continue working) until all other interested modules have responded to the event. It is also important to note that if multiple modules have requested notification of a single event, the order in which they will respond to that event is nondeterministic and cannot be relied upon. If modules must act in a specific order, there are two options:

Either option is acceptable, but the second is generally easier to maintain and can be slightly more performant.

ControlDeck provides only one built-in event: the simulation update event (accessible using the group name CD_SYSTEM_GROUP and event name CD_SIMULATION_STEP_EVENT; no quotes as these are macros). This event is triggered after each timestep when ControlDeck is running a DSim simulation for providing data. If the control system will be migrating to working with real hardware, consider using a timer instead, so that no changes will need to be made later on. Note especially that this event will never be sent if no simulation is associated with the control deck.

Background processing

Modules will only run when a timer or event triggers them, unless they have initiated a background process. Background threads may be running even if no main module threads are actively responding to timers or events, and main modules may be woken up when a background thread completes. See start_background_task(), run_background_task(), handle_intermediate_data(), and complete_background_task().