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.

HistogramGAM configuration.
 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

  1. Edit the file ../Configurations/MassSpring/RTApp-MassSpring-6.cfg and add a StatisticsGAM to compute information about the Force signal.

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.

PIDGAM output signal requirements.
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.

GAM to convert between scalar and single-element vector signals.
 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.

Updated configuration with the Force statistics.
 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.

  1. Edit the file ../Configurations/MassSpring/RTApp-MassSpring-7.cfg and add a signal to the HistogramGAM to compute a histogram of the GAMTimer_ReadTime signal.

  2. Rename the signal in the output as Thread1FreeTimeHistogram.

  3. Use as MinLim the value 2600 and as MaxLim the value 9800.

  1. Why are the Min and Max limits of the histogram set to these values? What is the expected range of values for the GAMTimer_ReadTime signal?

  2. Why were these two exact numbers chosen (and not e.g. 2000 and 10000)? 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.

Updated configuration with the Force statistics.
 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        }