Documentation

This is machine translation

Translated by Microsoft
Mouseover text to see original. Click the button below to return to the English verison of the page.

Note: This page has been translated by MathWorks. Please click here
To view all translated materals including this page, select Japan from the country navigator on the bottom of this page.

Create Moving Average System object

Introduction

This example shows how to create a System object™ that implements a moving average filter. The example shows how to use the System object in MATLAB® and Simulink® through the MATLAB System block. MovingAverageFilter is a simple moving average System object filter, which computes the unweighted mean of the previous WindowLength input samples, where WindowLength is the length of the moving average window.

The System object accepts single-precision and double-precision 2-D input matrices. Each column of the input matrix is treated as an independent (1-D) channel. The first dimension of the input defines the length of the channel (or the input frame size). MovingAverageFilter independently computes the moving average of each input channel over time.

System object Usage in MATLAB and System object Usage in Simulink show how to use your System object with data.

Create the Class Definition

In the MATLAB Home tab select New -> System Object -> Simulink Extension to open a System object template. This template includes customizations of the System object for use in the MATLAB System block. You can edit the template file, using it as guideline, to create your own System object.

Replace all occurrences of Untitled in the file with MovingAverageFilter and save the file as MovingAverageFilter.m in a folder where you have write permission. You need to add this folder to the MATLAB path to use the System object. For convenience, the entire System object is provided in the file dspdemo.MovingAverageFilter.m. To view this file enter

edit dspdemo.MovingAverageFilter
at the MATLAB command prompt. The prefix dspdemo on dspdemo.MovingAverageFilter is a package name. Packages are special folders that can contain class folders, function and class definition files, and other packages. Package folders always begin with the + character such as +dspdemo. Packages define the scope of the contents of the package folder (that is, a namespace in which names must be unique). This means function and class names need to be unique only within the package. Using a package provides a means to organize classes and functions and to select names for these components that other packages can reuse. You do not have to use packages when creating your System object. For more information on packages in MATLAB, see Packages Create Namespaces (MATLAB). The remainder of this example shows you how to create the MovingAverageFilter object from the System object template without using a package. However, you can also review and use the completed version, dspdemo.MovingAverageFilter.

Moving Average Filter Properties

The MovingAverageFilter object has one public property that controls the length of the moving average. Because the algorithm depends on this value being constant once data processing begins, the property is defined as nontunable. Additionally, the property only accepts real, positive integers. To ensure correct input, add the PositiveInteger attribute to the property. The default value of this property is 5.

properties (PositiveInteger, Nontunable)
        % WindowLength Moving average filter length
        %   Specify the length of the moving average filter as a
        %   scalar positive integer value. The default value of this
        %   property is 5.
        WindowLength = 5
end

The state of the moving average filter is defined with the DiscreteState attribute. Get the value of the state by calling the getDiscreteState method.

properties (DiscreteState)
        State;
end

A moving average filter is an FIR Filter with numerator coefficients equal to ones(WindowLength,1)/WindowLength. Because the coefficients do not change during the streaming operation, the coefficients are defined in a property for optimization purposes. Additionally, to ensure the coefficients are not accessible to users of the System object, use the private attribute.

properties (Access = private, Nontunable)
        pCoefficients;
end

Finally, the System object operates on a possibly multichannel input and therefore requires a property for the number of channels. This property is not accessible to users and therefore you use the private attribute. The value of this property is determined from the number of columns in the input.

properties (Access = private)
        % pNumChannels Property used to cache the number of input channels
        % (columns). Varying the number of channels during the streaming
        % operation is not allowed (since it modifes the number of required
        % states). The default of -1 means that the streaming operation has
        % not started yet (i.e. the number ofo channels is still unknown).
        pNumChannels = -1;
    end

Moving Average Filter Constructor

The System object constructor is a method that has the same name as the class (MovingAverageFilter in this example). Within that method, use the setProperties method to allow standard name-value pair handling at construction, filt = MovingAverageFilter('WindowLength',10).

methods
        % Constructor
        function obj = MovingAverageFilter(varargin)
            % Support name-value pair arguments when constructing the
            % object.
            setProperties(obj,nargin,varargin{:});
        end
end

Moving Average Filter Setup

The setupImpl method sets up the object and implements one-time initialization tasks. The filter coefficients are computed based on the specified window length. The filter's states are initialized to zero. Note that there are WindowLength-1 states per input channel. If you would like to initialize the states to a custom value, you can create a public InitialConditions property and use the property value to set the object state (obj.State) in setupImpl. Finally, the number of channels is determined from the number of columns in the input.

function setupImpl(obj,x)
            numChannels = size(x,2);
            obj.State = zeros(obj.WindowLength-1,numChannels,'like',x);
            % Cache the number of channels
            obj.pNumChannels = numChannels;
            obj.pCoefficients = ones(1,obj.WindowLength)/obj.WindowLength;
end

Note

You must set Access = protected for this method.

Moving Average Filter Step

The object's algorithm is defined in the stepImpl method. The algorithm in stepImpl is executed when the user of the System object calls step at the command line. In this example, stepImpl calculates the output and updates the object's state values using the filter function.

function Y = stepImpl(obj,X)
    % Compute output and update state
   [Y,obj.State] = filter(obj.pCoefficients,1,X,obj.State);
end

Note

You must set Access = protected for this method.

Moving Average Filter Reset

The state reset equations are defined in the resetImpl method. In this example, the states are reset to zero. If you want to reset the states to a custom value, you can create a public InitialConditions property and use the property value to reset state in resetImpl.

function resetImpl(obj)
    obj.State(:) = 0;
end

Note

You must set methods(Access = protected) for this method.

Input Validation

validateInputsImpl validates inputs to the step method at initialization and at each subsequent call to step where the input attributes (such as dimensions, data type or complexity) change. In this example, validattributes ensures that the input is a 2-D matrix with floating-point data.

function validateInputsImpl(obj, u)
            validateattributes(u,{'double','single'}, {'2d',...
                'nonsparse'},'','input');
            % The number of input channels is not allowed to change. If
            % pNumChannels = -1. This means that the streaming operation
            % has not started yet (i.e. setupImpl has not been invoked
            % yet). Do not perform the check in that case.
            coder.internal.errorIf(obj.pNumChannels~=-1 && obj.pNumChannels ~= size(u,2),...
 'dsp:system:varSizeChannelsNotSupported');
end

Note

You must set methods(Access = protected) for this method.

Object Saving and Loading

saveObjectImpl defines what property and state values are saved in a MAT-file when you call save on that object. If you do not define a saveObjectImpl method for your System object class, only public properties and properties with the DiscreteState attribute are saved. Save the state of an object only if the object is locked. When you load the saved object, the object loads in that locked state. In this System object, the filter coefficients are saved if the object is locked.

function s = saveObjectImpl(obj)
            s = saveObjectImpl@matlab.System(obj);
            if isLocked(obj)
                s.pCoefficients  =  obj.pCoefficients;
                s.pNumChannels  =  obj.pNumChannels;
            end
end

loadObjectImpl defines what System object property and state values are loaded when you load a MAT-file. loadObjectImpl should correspond to your saveObjectImpl to ensure that all saved properties and data are loaded.

function loadObjectImpl(obj,s,wasLocked)
            if wasLocked
                obj.pCoefficients = s.pCoefficients;
                obj.pNumChannels = s.pNumChannels;
            end
            loadObjectImpl@matlab.System(obj,s,wasLocked);
end

Note

You must set Access = protected for this method.

System object Usage in MATLAB

This example uses the System object to remove noise from a noisy pulse sequence. The length of the moving average filter is 30 samples. If you are using the predefined dspdemo.MovingAverageFilter, substitute that name for MovingAverageFilter in the class constructor, for example movingAverageFilter = dspdemo.MovingAverageFilter('WindowLength',30);.

movingAverageFilter = MovingAverageFilter('WindowLength',30);
scope = dsp.TimeScope('SampleRate',1e3,...
    'TimeSpan',256 * .01,...
    'ShowGrid',true,...
    'NumInputPorts',2,...
    'LayoutDimensions',[2 1]);
for i=1:100
    input =  (1-2*randi([0 1],1)) * ones(256,1) + 0.5 * randn(256,1);
    output = movingAverageFilter(input);
    scope(input,output)
end

Simulink Customization Methods

You need to define a few more methods to be able to use the System object in a Simulink MATLAB System block. These methods are not required if you use the System object only in MATLAB. getOutputSizeImpl returns the sizes of each output port. For System objects with one input and one output and where you want the input and output sizes to be the same, you do not need to implement this method. In the case of MovingAverageFilter, there is one input and output and the size of each is the same. Therefore, remove this method from the class definition of MovingAverageFilter.

getDiscreteStateSpecificationImpl returns the size, data type, and complexity of a property. This property must be a discrete-state property. You must define this method if your System object has discrete-state properties and is used in the MATLAB System block. In this example, the method is used to define the State property.

function [sz,dt,cp] = getDiscreteStateSpecificationImpl(obj,~)
    inputSize = propagatedInputSize(obj,1);
    sz = [obj.WindowLength-1 inputSize(2)];
    dt =  propagatedInputDataType(obj,1);
    cp =  propagatedInputComplexity(obj,1);
end

Note

You must set Access = protected for this method.

System object Usage in Simulink

To use your System object in a Simulink model, drag a MATLAB System block from the User-Defined Functions library in Simulink to your model.

Open the block dialog box and set the System object name to MovingAverageFilter. The model ex_movingaverage_filter illustrates the use of the System object in Simulink to filter a noisy pulse sequence.

model = 'ex_movingaverage_filter';
open_system(model);

Run the model by clicking the Run button in the model or entering:

sim(model)

Was this topic helpful?