Statistics
This section continues to build upon the previous example and adds features that allow computing runtime statistics on the MARTe2 signals.
The MARTe2-components repository offers two GAMs that can be used to implement statistics:
StatisticsGAM, provides average, standard deviation, minimum and maximum of its input signal over a moving time window.
HistogramGAM, computes histograms from the input signal values.
In this example, the StatisticsGAM is used to compute the average and standard deviation of the cycle time, while the HistogramGAM is used to compute a histogram of the cycle time values.
Note
The number of bins of the HistogramGAM is computed using the output signal number of elements. The size of the bin is automatically computed as \((MaxValue - MinValue) / (NumberOfElements - 2)\). This size is cast to the input signal type and thus may lead to rounding errors.
In case the input signal is an integer, it is recommended to satisfy the equation above such that the size of the bin is also an exact integer.
1 +GAMHist = {
2 Class = HistogramGAM
3 BeginCycleNumber = 200
4 InputSignals = {
5 Thread1CycleTime = {
6 DataSource = DDB1
7 Type = uint32
8 MinLim = 7750
9 MaxLim = 12250
10 }
11 }
12 OutputSignals = {
13 Thread1CycleTimeHistogram = {
14 DataSource = DDB1
15 Type = uint32
16 NumberOfElements = 11
17 }
18 }
19 }
Running the application
Start the application with:
./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-5.cfg -l RealTimeLoader -s State1
Once the application is running, inspect the screen output and verify that the log shows the cycle time average, maximum, and minimum values, as well as the standard deviation and the histogram values. The log should show entries similar to the following:
$ [Information - LoggerBroker.cpp:152]: Thread1CycleTimeAverage [0:0]:10002
$ [Information - LoggerBroker.cpp:152]: Thread1CycleTimeStdDev [0:0]:61
$ [Information - LoggerBroker.cpp:152]: Thread1CycleTimeMax [0:0]:9859
$ [Information - LoggerBroker.cpp:152]: Thread1CycleTimeMin [0:0]:10131
$ [Information - LoggerBroker.cpp:152]: Thread1CycleTimeHistogram [0:10]:{ 5 0 0 0 2 888 1 0 0 1 4 }
Exercises
Ex. 1: Add the force statistics
Edit the file
../Configurations/MassSpring/RTApp-MassSpring-6.cfgand add aStatisticsGAMto compute information about theForcesignal.
Warning
MARTe2 does not distinguish between a scalar signal (NumberOfDimensions = 0, NumberOfElements = 1) and a single-element vector signal (NumberOfDimensions = 1, NumberOfElements = 1).
However, some components impose specific requirements. For example, the PIDGAM requires its output to be a single-element vector, while the StatisticsGAM requires its input to be a scalar.
1 +GAMController = {
2 OutputSignals = {
3 Force = {
4 DataSource = DDB1
5 Type = float64
6 NumberOfDimensions = 1
7 NumberOfElements = 1
8 }
9 }
Consequently, connecting the output of the PIDGAM to the input of the StatisticsGAM requires an intermediate GAM to convert between these definitions. Otherwise, the application will report conflicting signal requirements.
1 +GAMPatchForceDims = {
2 Class = IOGAM
3 InputSignals = {
4 Force = {
5 DataSource = DDB1
6 Type = float64
7 NumberOfDimensions = 1
8 NumberOfElements = 1
9 }
10 }
11 OutputSignals = {
12 ForceP = {
13 DataSource = DDB1
14 Type = float64
15 NumberOfDimensions = 0
16 NumberOfElements = 1
17 }
18 }
19 }
Note that the IOGAM performs a memcpy of all the input signals memory into the output signals memory, only requiring size compatibility between the input and output signals. This allows the IOGAM to be used as a simple pass-through GAM to convert between different signal definitions, without the need to implement a custom GAM for this purpose.
Warning
Because the IOGAM performs a memcpy of the input signal memory into the output signal memory, it does not perform any transformation of the signal values and will copy the signals in the same order as they are defined in the configuration file.
This means that if the order is not maintained consistently, the output signals will not match the expected input signal order and/or be cast to the incorrect type.
For example:
+MyIOGAM = {
Class = IOGAM
InputSignals = {
InputReference = {
DataSource = Driver1
Type = float64
}
Measurement = {
DataSource = Driver2
Type = float64
}
}
OutputSignals = {
Measurement = {
DataSource = DDB1
Type = float64
}
InputReference = {
DataSource = DDB1
Type = float64
}
}
}
Would swap the InputReference and Measurement signals.
./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-6.cfg -l RealTimeLoader -s State1
Solution
The solution is to add a new GAM and connect all the signals to the GAMDisplay.
1 +GAMForceStats = {
2 Class = StatisticsGAM
3 WindowSize = 200
4 InfiniteMaxMin = 0
5 InputSignals = {
6 ForceP = {
7 DataSource = DDB1
8 Type = float64
9 }
10 }
11 OutputSignals = {
12 ForceAverage = {
13 DataSource = DDB1
14 Type = float64
15 }
16 ForceStdDev = {
17 DataSource = DDB1
18 Type = float64
19 }
20 ForceMin = {
21 DataSource = DDB1
22 Type = float64
23 }
24 ForceMax = {
25 DataSource = DDB1
26 Type = float64
27 }
28 }
29 }
Ex. 2: Add an additional histogram for the GAMTimer read signal
The GAMTimer Read signal provides a good indication of the amount of free time in the thread and thus of the system load. Adding a histogram of this signal can help to identify if the system is overloaded and whether the cycle time is sufficient for the application.
Edit the file
../Configurations/MassSpring/RTApp-MassSpring-7.cfgand add a signal to the HistogramGAM to compute a histogram of theGAMTimer_ReadTimesignal.Rename the signal in the output as
Thread1FreeTimeHistogram.Use as
MinLimthe value2600and asMaxLimthe value9800.
Why are the Min and Max limits of the histogram set to these values? What is the expected range of values for the
GAMTimer_ReadTimesignal?Why were these two exact numbers chosen (and not e.g.
2000and10000)? What is the bin size of the histogram?
Solution
The solution is to add the signal to the HistogramGAM and connect it to the GAMDisplay.
1 +GAMHist = {
2 Class = HistogramGAM
3 BeginCycleNumber = 200
4 InputSignals = {
5 Thread1CycleTime = {
6 DataSource = DDB1
7 Type = uint32
8 MinLim = 7750
9 MaxLim = 12250
10 }
11 GAMTimer_ReadTime = {
12 DataSource = DDB1
13 Type = uint32
14 MinLim = 2600
15 MaxLim = 9800
16 }
17 }
18 OutputSignals = {
19 Thread1CycleTimeHistogram = {
20 DataSource = DDB1
21 Type = uint32
22 NumberOfElements = 11
23 }
24 Thread1FreeTimeHistogram = {
25 DataSource = DDB1
26 Type = uint32
27 NumberOfElements = 11
28 }
29 }
30 }