classdef trackingABF < matlabshared.tracking.internal.AbstractAlphaBetaFilter ...
    & matlabshared.tracking.internal.fusion.CustomDisplay ...
    & matlabshared.smoothers.internal.ABFSmoother
%trackingABF   Alpha-beta filter for object tracking
%   The alpha-beta filter is designed for tracking an object that follows a
%   linear motion model and has a linear measurement model. Examples of
%   linear motion are constant velocity and constant acceleration. You can
%   use the filter to predict an object's future location, to reduce noise
%   in the detected location, or to help associate multiple objects with
%   their tracks.
%
%   ABF = trackingABF returns an alpha-beta filter for a discrete time,
%   2D constant velocity system. The motion model is '2D Constant Velocity'
%   with the state defined as [x;vx;y;vy].
%
%   ABF = trackingABF(Name,Value) creates an alpha-beta filter object, ABF,
%   with the specified property Name set to the specified Value. You can
%   specify additional name-value pair arguments in any order as
%   (Name1,Value1,...,NameN,ValueN).
%
%   trackingABF properties:
%
%   MotionModel          - Model of target motion
%   State                - Alpha-beta filter states
%   StateCovariance      - State estimation error covariance
%   ProcessNoise         - Process noise covariance
%   MeasurementNoise     - Measurement noise covariance
%   Coefficients         - Alpha-beta filter coefficients
%   EnableSmoothing      - Enable backward smoothing for the filter
%   MaxNumSmoothingSteps - Maximum number of backward smoothing steps allowed
%                          for smoothing
%
%   trackingABF methods:
%
%   predict     - Perform state prediction using alpha-beta filter
%   correct     - Perform state correction using alpha-beta filter
%   correctjpda - Correct the filter using joint probabilistic detection assignment
%   smooth      - Smooth the filter estimate using backward recursion
%   distance    - Distances between measurements and filter prediction
%   likelihood  - Calculate the likelihood of a measurement
%   clone       - Create alpha-beta filter object with same property values
%
%   Notes:
%   ------
%   * If the measurement exists, e.g., the object has been detected, you
%     can call the predict method and the correct method together. If the
%     measurement is missing, you can call the predict method but not the
%     correct method.
%   * You can use the distance method to compute distances that describe
%     how a set of measurements matches the filter. You can thus find a
%     measurement that best fits the filter. This strategy can be used for
%     matching object detections against object tracks in a multi-object
%     tracking problem.
%
%   % Example 1: Create a trackingABF for a 2D constant velocity model
%   % ----------------------------------------------------------------
%   %   Use the pre-packaged constant velocity motion model, constvel, and
%   %   the associated measurement model, cvmeas. These models assume that
%   %   the state is [x;vx;y;vy] and a position measurement is [x;y].
%   ABF = trackingABF
%
%   % Example 2: Create a trackingABF with an additional name-value pair
%   % ------------------------------------------------------------------
%   %   Use an additional name-value pair to define the State
%   state = [1;2;3;4];
%   ABF = trackingABF('State', state)
%
%   % Example 3: Running the filter
%   % -----------------------------
%   %   After constructing a filter, use the following steps to call
%   %   predict and correct. You may call predict and correct in any order
%   %   and as many times you would like to call each.
%   state = [1;2;3;4];
%   ABF = trackingABF('State', state);
%   meas = [1;1];
%   [x_pred, P_pred] = predict(ABF, 0.5)    % Predict over 0.5 seconds
%   [x_corr, P_corr] = correct(ABF, meas)   % Correct using the measurement
%   [x_pred, P_pred] = predict(ABF)         % Predict over 1 second
%   [x_pred, P_pred] = predict(ABF, 2)      % Predict over 2 seconds
%
%   % Modify the filter coefficients and correct again.
%   ABF.Coefficients = [0.4 0.2];
%   [x_corr, P_corr] = correct(ABF, [8;14])
%
%   % Example 4: Using the distance method
%   % ------------------------------------
%   %   You can measure the distance between the filter and a set of
%   %   measurements, z_matrix, by calling the distance method.
%   state = [1;2;3;4;0;0]; % A 3-D model
%   ABF = trackingABF('MotionModel','3D Constant Velocity', 'State', state);
%   [x_pred, P_pred] = predict(ABF);
%   z_matrix = [0, 0, 0; 1, 1, 0; 2, 2, 0];
%   d = distance(ABF, z_matrix)
%
%  See also: trackingKF, trackingEKF, trackingUKF

%   References:
%   [1] Blackman, Multiple-Target Tracking with Radar Applications, Artech
%   House, 1986
%   [2] Bar-Shalom et al., Estimation with Applications to Tracking and
%   Navigation, Theory, Algorithms, and Software. John Wiley & Sons, 2001
%   Copyright 2018 The MathWorks, Inc.

%#codegen
%#ok<*EMCLS>
%#ok<*EMCA>
%#ok<*MCSUP>

    methods
        function obj = trackingABF(varargin)
            [smoothArgs,idx1,idx2] = trackingEKF.parseSmoothingNVPairs(varargin{:});
            filterArgs = {varargin{1:idx1-1},varargin{idx1 + 2:idx2 - 1},varargin{idx2 + 2:end}};
            defaultMotionModel = '2D Constant Velocity';
            obj@matlabshared.smoothers.internal.ABFSmoother(smoothArgs{:});
            obj@matlabshared.tracking.internal.AbstractAlphaBetaFilter(defaultMotionModel,filterArgs{:});
        end
        
        function varargout = predict(obj,varargin)
            %
           
           % The above line is intentionally left empty to divert the help
           % text to superclass.
            
           % Call setup on smoother, the smoother knows when to return
           % safely without doing setup multiple times. 
           setupInitialDistributions(obj);
           
           % Predict using the superclass 
           [varargout{1:nargout}] = predict@matlabshared.tracking.internal.AbstractAlphaBetaFilter(obj,varargin{:});
           
           % Update the data for the smoother
           obj.LastJacobian = obj.pStateTransitionMatrix;
           updatePredictionData(obj);
        end
        
        function varargout = correct(obj,varargin)
           %
           
           % The above line is intentionally left empty to divert the help
           % text to superclass.
           
           % Correct using the superclass
           [varargout{1:nargout}] = correct@matlabshared.tracking.internal.AbstractAlphaBetaFilter(obj,varargin{:});
           
           % Update the data for the smoother
           updateCorrectionData(obj);
        end
        
        function varargout = correctjpda(obj,varargin)
            %
           
           % The above line is intentionally left empty to divert the help
           % text to superclass.
           
           % Correctjpda using the superclass
           [varargout{1:nargout}] = correctjpda@matlabshared.tracking.internal.AbstractAlphaBetaFilter(obj,varargin{:});
           
           % Update the data for the smoother
           updateCorrectionData(obj);
        end
        
        function newObj = clone(obj)
            newObj = clone@matlabshared.tracking.internal.AbstractAlphaBetaFilter(obj);
            copySmootherProperties(obj,newObj);
        end
    end
    
    methods (Access = protected)
        function propGroups = getPropertyGroups(obj)                        
            filterGroups = matlab.mixin.util.PropertyGroup({'MotionModel','State','StateCovariance','ProcessNoise','MeasurementNoise','Coefficients'});
            smoothGroups = getPropertyGroups@matlabshared.smoothers.internal.ABFSmoother(obj);
            propGroups = [filterGroups;smoothGroups];
        end
    end
    
    methods (Access = protected)
        % saveobj to make sure the filter is saved correctly. The
        % method is overridden to save smoother properties in addition
        % to filter properties. 
        function s = saveobj(obj)
            sABF = saveobj@matlabshared.tracking.internal.AbstractAlphaBetaFilter(obj);
            s = saveSmootherProperties(obj, sABF);
        end
    end
    
    methods (Static, Hidden)
      %--------------------------------------------------------------------
      % loadobj to make sure that the filter is loaded correctly.
      % This method cannot be inherited from the superclass because the
      % correct object type has to be created. 
      %--------------------------------------------------------------------
      function obj = loadobj(sobj)
          obj = trackingABF();
          loadPrivateProps(obj,sobj);
          loadSmootherProperties(obj,sobj);
      end
      
      function props = matlabCodegenNontunableProperties(~)
          p1 = matlabshared.tracking.internal.AbstractAlphaBetaFilter.matlabCodegenNontunableProperties;
          p2 = matlabshared.smoothers.internal.ABFSmoother.matlabCodegenNontunableProperties;
          props = {p1{:}, p2{:}};
      end
    end
end