Create Moving Average System Object
This example shows how to create a System object™ that implements a moving average filter.
Introduction
System objects are MATLAB® classes that derive from matlab.System
. As a result, System objects all inherit a common public interface, which includes standard methods:
setup
— Initialize the object, typically at the beginning of a simulationreset
— Clear the internal state of the object, bringing it back to its default post-initialization statusrelease
— Release any resources (memory, hardware, or OS-specific resources) used internally by the object
When you create new kinds of System objects, you provide specific implementations for all the preceding methods to determine its behavior.
In this example, you create and use the movingAverageFilter
System object. movingAverageFilter
is a System object that computes the unweighted mean of the previous WindowLength
input samples. WindowLength
is the length of the moving average window. movingAverageFilter
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.
Create the System Object File
In the MATLAB Home tab, create a new System object class by selecting New > System Object > Basic. The basic template for a System object opens in the MATLAB editor to guide you as you create the movingAverageFilter
System object.
Rename the class movingAverageFilter
and save the file as movingAverageFilter.m
. To ensure you can use the System object, make sure you save the System object in a folder that is on the MATLAB path.
For your convenience, a complete movingAverageFilter
System object file is available with this example. To open the completed class, enter:
edit movingAverageFilter.m
Add Properties
This System object needs four properties. First, add a public property WindowLength
to control the length of the moving average window. 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 input satisfies these conditions, add property validators (see Validate Property Values). Set the default value of this property to 5.
properties(Nontunable)
WindowLength (1,1){mustBeInteger,mustBePositive} = 5
end
Second, add two properties called State
and pNumChannels
. Users should not access either property, so use the Access = private
attribute. State
saves the state of the moving average filter. pNumChannels
stores the number of channels in your input. The value of this property is determined from the number of columns in the input.
properties(Access = private)
State;
pNumChannels = -1;
end
Finally, you need a property to store the FIR numerator coefficients. Add a property called pCoefficients
. Because the coefficients do not change during data processing and you do not want users of the System object to access the coefficients, set the property attributes as Nontunable, Access = private
.
properties(Access = private, Nontunable)
pCoefficients
end
Add Constructor for Easy Creation
The System object constructor is a method that has the same name as the class (movingAverageFilter
in this example). You implement a System object constructor to allow name-value pair inputs to the System object with the setProperties
method. For example, with the constructor, users can use this syntax to create an instance of the System object: filter = movingAverageFilter('WindowLength',10)
. Do not use the constructor for anything else. All other setup tasks should be written in the setupImpl
method.
methods function obj = movingAverageFilter(varargin) % Support name-value pair arguments when constructing object setProperties(obj,nargin,varargin{:}) end end
Set Up and Initialization in setupImpl
The setupImpl
method sets up the object and implements one-time initialization tasks. For this System object, modify the default setupImpl
method to calculate the filter coefficients, the state, and the number of channels. The filter coefficients are computed based on the specified WindowLength
. The filter state is initialized to zero. (Note that there are WindowLength-1
states per input channel.) Finally, the number of channels is determined from the number of columns in the input.
For setupImpl
and all Impl
methods, you must set the method attribute Access = protected
because users of the System object do not call these methods directly. Instead the back-end of the System object calls these methods through other user-facing functions.
function setupImpl(obj,x) % Perform one-time calculations, such as computing constants obj.pNumChannels = size(x,2); obj.pCoefficients = ones(1,obj.WindowLength)/obj.WindowLength; obj.State = zeros(obj.WindowLength-1,obj.pNumChannels,'like',x); end
Define the Algorithm in stepImpl
The object's algorithm is defined in the stepImpl
method. The algorithm in stepImpl
is executed when the user of the System object calls the object at the command line. In this example, modify stepImpl
to calculate the output and update the object's state values using the filter
function.
function y = stepImpl(obj,u) [y,obj.State] = filter(obj.pCoefficients,1,u,obj.State); end
Reset and Release
The state reset equations are defined in the resetImpl
method. In this example, reset states to zero. Additionally, you need to add a releaseImpl
method. From the Editor toolstrip, select Insert Method > Release resources. The releaseImpl
method is added to your System object. Modify releaseImpl
to set the number of channels to -1
, which allows new input to be used with the filter.
function resetImpl(obj) % Initialize / reset discrete-state properties obj.State(:) = 0; end function releaseImpl(obj) obj.pNumChannels = -1; end
Validate Input
To validate inputs to your System object, you must implement a validateInputsImpl
method. This method validates inputs at initialization and at each subsequent call where the input attributes (such as dimensions, data type, or complexity) change. From the toolstrip, select Insert Method > Validate inputs. In the newly inserted validateInputsImpl
method, call validateattributes
to ensure that the input is a 2-D matrix with floating-point data.
function validateInputsImpl(~, u) validateattributes(u,{'double','single'}, {'2d',... 'nonsparse'},'','input'); end
Object Saving and Loading
When you save an instance of a System object, saveObjectImpl
defines what property and state values are saved in a MAT-file. If you do not define a saveObjectImpl
method for your System object class, only public properties and properties with the DiscreteState
attribute are saved. Select Insert Method > Save in MAT-file. Modify saveObjectImpl
so that if the object is locked, the coefficients and number of channels is saved.
function s = saveObjectImpl(obj) s = saveObjectImpl@matlab.System(obj); if isLocked(obj) s.pCoefficients = obj.pCoefficients; s.pNumChannels = obj.pNumChannels; end end
loadObjectImpl
is the companion to saveObjectImpl
because it defines how a saved object loads. When you load the saved object, the object loads in the same locked state. Select Insert Method > Load from MAT-file. Modify loadObjectImpl
so that if the object is locked, the coefficients and number of channels 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
Use movingAverageFilter
in MATLAB
Now that you have defined the System object, you can use the object in MATLAB. For example, use movingAverageFilter
to remove noise from a noisy pulse sequence.
movingAverageFilter = movingAverageFilter('WindowLength',10); t = (1:250)'; signal = randn(250,1); smoothedSignal = movingAverageFilter(signal); plot(t,signal,t,smoothedSignal); legend(["Input","Smoothed Signal"])
Extend Your System Object for Simulink
To use your System object in Simulink®, see Create Moving Average Filter Block with System Object (Simulink).