The DataIO
class defined in C++ provides a flexible input/output object for interfacing between models, tasks, events, and more. It is templated to work with nearly any data type, provided that type can be passed and returned via function. This guide provides an overview of how to interact with the DataIO
class.
The DataIO
Class
The SIGNAL Macro
The SIGNAL macro which defines parameters, inputs, and outputs for models uses is simply a wrapper for the DataIO object. It is used to simplify DataIO creation for new users, but is not mandatory. Examples using SIGNAL and DataIO are provided here.
The PARAMS, INPUTS, and OUTPUTS sections in each model define signals for interfacing with it.
Use
Because SIGNALs are defined on the interfaces of models, the most common way of constructing large sims is to connect the inputs of one model to the outputs of another. In this way, complex calculations are changed in much the same way as Simulink blocks are tied together.
The most basic use cases
The most basic use cases for signals (and, by extension, the DataIO object) that a user would typically need involve writing, reading, and connecting signals to one another. Writing to a signal involves setting its value, typically from some internal calculation in a model. Reading a signal involves getting its value, often for use inside a model, and connecting signals involves tying a downstream (input) to an upstream (output) to facilitate data flow in the simulation.
WRITE: Writing to a DataIO object involves passing a value to it in parenthesis (using the assignment operator won’t work). Example:
DataIO<double> data(parent, "data", 1.0); // Define a DataIO to hold a double value named data with default 1.0
SIGNAL(data, double, 1.0); // This is the exact equivalent of the above using the SIGNAL macro
data(2.0); // Write value 2.0 to the data signal
READ: Reading from a DataIO object involves passing a value to it in parenthesis (using the assignment operator won’t work). Example:
DataIO<double> data(parent, "data", 1.0); // Define a DataIO to hold a double value named data with default 1.0
SIGNAL(data, double, 1.0); // This is the exact equivalent of the above using the SIGNAL macro
double read_val = data(); // read_val will receive 1.0
CONNECT: Connecting two DataIO object involves pointing a downstream signal (such as a model input) to an upstream signal (such as a model output) such that the downstream signal always returns the exact same value as held by the upstream signal. Example:
DataIO<double> upstream(parent, "upstream", 1.0); // Define a DataIO to hold a double value named upstream with default 1.0
SIGNAL(upstream, double, 1.0); // This is the exact equivalent of the above using the SIGNAL macro
DataIO<double> downstream(parent, "downstream", 3.0); // Define a DataIO to hold a double value named upstream with default 3.0
SIGNAL(downstream, double, 3.0); // This is the exact equivalent of the above using the SIGNAL macro
double read_val = downstream(); // read_val will receive 3.0
// Now connect our downstream signal to our upstream signal
connectSignals(upstream, downstream); // This connects downstream to upstream so downstream returns the value of upstream
downstream.mapTo(upstream); // This does the same as the above -- this is more low level. The above is recommended.
read_val = downstream(); // Now downstream will return 1.0, which is the value held by upstream
// Alternatively, you can connect a DataIO to a pointer for easy integration with non-ModelSpace objects, such as integrated FSW
double x = 4.0; // Create a value x and set to 4.0
double* x_ptr = &x; // Pointer x_ptr points to x
downstream.mapTo(x_ptr); // Map downstream to x_ptr
read_val = downstream(); // Now downstream will return 4.0, which is the value x_ptr points to
Description and Naming
The DataIO
class is a templated class with one template argument - T.
DataIO<T>
produces an input/output object for data of type T. The argument is:
-
T - The type of the data. This should be a type that can be passed and returned via function.
DataIO
operates by abstracting data using a pointer. It holds an internal value of type T and a pointer to the data source to use. By default, that data source is itself, but it may point to another DataIO
object if commanded to do so via the mapToPointer
function. In that case, DataIO
will recursively call DataIO
objects until it finds the root object, then return the value held by the root object.
For a complete guide on interacting with the DataIO
class, refer to the Doxygen documentation:
DataIO Doxygen
Creating a DataIO
Description | C++ Example | Python Example |
---|---|---|
Constructor with Parent, Name, and Initial Value - Creates a |
|
|
Getting and Setting Values
Description | C++ Example | Python Example |
---|---|---|
Getting the Value - Returns the value of the |
|
|
Setting a Value - Sets the value of the |
|
|
Mapping DataIO objects to one another
Description | C++ Example | Python Example |
---|---|---|
Mapping DataIO to another DataIO — This is used to connect inputs and outputs on models. This example maps data1 to return the value held by data2. As data2 is changed, data1 will change as well. |
|
|
Mapping to a Pointer - Maps the |
|
|
Additional Operations
Description | C++ Example | Python Example |
---|---|---|
Resetting the Map - Resets the mapping of the |
|
|