classdef objectTrack
%objectTrack  Contains a report for a single object track
%  objectTrack captures the information reported by a tracker for a single
%  object. You can use the objectTrack output as an input to a
%  track-to-track fuser.
%
%  track = objectTrack creates a track object with default properties.
%  track = objectTrack('Name',value) lets you specify properties as
%  name-value pair arguments that define properties described below:
%
% objectTrack properties:
%   TrackID                   - Integer that identifies the track
%   BranchID                  - Integer that identifies the track branch
%   SourceIndex               - Identification of the system reporting the track
%   UpdateTime                - Time the track was updated by the tracker
%   Age                       - Number of times the track was updated
%   State                     - The current state estimate
%   StateCovariance           - Current track state uncertainty covariance
%   StateParameters           - Parameters about the track state reference frame
%   ObjectClassID             - Object classification
%   ObjectClassProbabilities  - Object classification probabilities
%   TrackLogic                - Track logic type
%   TrackLogicState           - State of the track logic
%   IsConfirmed               - Indication if the track is confirmed
%   IsCoasted                 - Indication if the track is coasted
%   IsSelfReported            - Indication if the track was updated by the sensor system
%   ObjectAttributes          - Additional track attributes
%
% objectTrack methods:
%   toStruct         - Convert the objectTrack to a struct
%
% Class Support:
% --------------
%   TrackID, BranchID, Age, and ObjectClassID must be integer scalar values.
%   UpdateTime must be a real finite scalar value.
%   State and StateCovariance must be real, finite, double or single.
%   StateCovariance must be the same type as State.
%   IsConfirmed, IsCoasted, and IsSelfReported must be logical scalars.
%   StateParameters and ObjectAttributes must be a struct.
%   ObjectClassProbabilities must be positive, less or equal to 1, double
%   or single.
%
% Examples:
% ---------
% % Create a report of a track.
% x = (1:6)';
% P = diag(1:6);
% track = objectTrack(State = x, StateCovariance = P);
% disp(track)
%
% % Create a report of a classified track. There are 3 possibles classes,
% % the probabilities that the track belongs to each class are: 50%, 25%, and
% % 25% respectively.
% track = objectTrack(ObjectClassID = 1, ObjectClassProbabilities = [0.50 0.25 0.25]);
% disp(track)
%
% See also: objectDetection

% Copyright 2019-2022 The MathWorks, Inc.

%#codegen
    
    % Public properties:
    properties (Access=public)
        % TrackID  Integer that identifies the track
        %   Use TrackID to identify a unique tracked object.
        %   An integer scalar value.
        %
        % Default: uint32(1)
        TrackID
        
        % Integer that identifies the track branch
        %   Use BranchID to identify a unique hypothesis of a tracked
        %   object. An integer scalar value.
        %
        % Default: uint32(0)
        BranchID
        
        % SourceIndex Identification of the system reporting the track
        %   Use SourceIndex to identify the tracker or track fuser
        %   that reports this track.
        %   An integer scalar value.
        %
        % Default: uint32(1)
        SourceIndex
    end
    
    properties(Access=public,Dependent)
        % UpdateTime  Time the track was updated by the tracker
        %   A nonnegative real scalar for the time the track was updated by
        %   the tracker.
        %
        % Default: 0
        UpdateTime
    end
       
    properties(Access=public)
        % Age Number of times the track was updated
        %   A positive scalar value. When a track is initialized, its Age
        %   is set to 1. Any subsequent update with a hit or a miss
        %   increments the track Age by 1.
        %
        % Default: 1
        Age
    end
    properties (Access=public, Dependent)
        % State The current state estimate
        %   Provide the track estimated state at the time instance
        %   specified by UpdateTime. A track state depends on the model
        %   used to track the object. For example, if a 3-D constant
        %   velocity model is used to track the object based on the
        %   constvel model, the state vector is [x;vx;y;vy;z;vz].
        %
        % Default: zeros(6,1), representing a constant velocity model
        State
        
        % StateCovariance The track current state uncertainty covariance
        %   Provide the track state uncertainty at the time instance
        %   specified by UpdateTime. The track covariance must be a square,
        %   positive-definite, symmetric matrix with dimensions N-by-N,
        %   where N is the number of elements in the State property.
        %
        % Default: eye(6,6)
        StateCovariance

    end

    properties (Access=public)
        % StateParameters  Parameters about the track state reference frame
        %   Use this property to define the track state reference frame and
        %   how to transform the track from the source coordinate system to
        %   the fuser coordinate system.
        %
        % Default: an empty struct
        StateParameters

        % ObjectClassID  Object classification
        %   Use this property to identify an object class.
        %   For example, use 1 for objects of type 'Car', 2 for objects of
        %   type 'Pedestrian', etc.
        %   Note: 0 is reserved for unknown classification.
        %   An integer scalar.
        %
        % Default: 0
        ObjectClassID

        % ObjectClassProbabilities Object classification probabilities
        %  Use this property to specify the classification probability of
        %  the track as a vector of N elements, where N is the number of
        %  classes. The ith element corresponds to the probability that the
        %  track belongs to class i. Each element must be a scalar between
        %  0 and 1, and the sum of all elements must be equal to 1.
        %
        % Default: 1
        ObjectClassProbabilities
    end
       
    properties(Dependent)
        % TrackLogic  Type of track logic
        %   The name or enumeration of the track logic type. Use one of the
        %   following:
        %     'History'
        %     'Score'
        %     'Integrated'
        %
        % Default: 'History'
        TrackLogic
        
        % TrackLogicState  State of the track logic
        %   The current state of the track logic. The track logic state
        %   depends on the track logic type. It is one of the following:
        %     Logic Type  | Logic State                              | Default
        %   --------------+------------------------------------------+---------
        %    'History'    | A 1xM logical array: M last hits/misses  | [true]
        %   --------------+------------------------------------------+---------
        %    'Score'      | A real 1x2 array: [current,max]          | [0, 0]
        %   --------------+------------------------------------------+---------
        %    'Integrated' | A scalar: probability of track existence | 0.5
        TrackLogicState
    end
       
    properties
        % IsConfirmed  Indicate if the track is confirmed
        %   A logical flag. A value of true means that the track is
        %   confirmed.
        %
        % Default: true
        IsConfirmed
        
        % IsCoasted  Indicate if the track is coasted
        %   A logical flag. A value of true means that the track is
        %   coasted: updated based on prediction.
        %
        % Default: false
        IsCoasted
        
        % IsSelfReported Indicate if the track is self reported
        %   A logical flag. A value of true means that the track is
        %   reported by internal sources (sensors, trackers or fusers). To
        %   limit the propagation of rumors in the system, use the value
        %   false to indicate if the track was updated by an external
        %   source.
        %
        % Default: true
        IsSelfReported
        
        % ObjectAttributes  Attributes passed by the tracker
        %   Use ObjectAttributes to provide additional information about
        %   the object.
        %   Use a struct to provide the additional attributes.
        %
        % Default: an empty struct
        ObjectAttributes
    end
    
    properties (Constant, Access = {?objectTrack, ?matlab.unittest.TestCase})
        pConstantTrackID          = uint32(1);
        pConstantBranchID         = uint32(0);
        pConstantSourceIndex      = uint32(1);
        pConstantUpdateTime       = 0;
        pConstantAge              = uint32(1);
        pConstantState            = zeros(6,1);
        pConstantStateCovariance  = eye(6,6);
        pConstantIsConfirmed      = true;
        pConstantIsCoasted        = false;
        pConstantIsSelfReported   = true;
        pConstantObjectClassID    = 0;
        pConstantObjectClassProbabilities = 1;
        pConstantStateParameters  = struct();
        pConstantObjectAttributes = struct();
        pConstantTrackLogic       = 1;
        pConstantTrackLogicState  = -1;
    end
    
    properties (Access = protected)
        pState           % Stores the state vector
        pStateCovariance % Stores the state covariance matrix
        pUpdateTime      % Stores the update time
        pDataType        % Data type of state vector
        pTrackLogicType  % Type of track logic
        pTrackLogicState % Stores the track logic state
    end
    methods
        % -----------------------------------------------------------------
        % Constructor 
        % -----------------------------------------------------------------
        function track = objectTrack(varargin)
            % Construct a single track object. 
            %   detection = objectTrack creates a default object track.
            %
            %   detection = objectTrack('Name', value) allows the
            %   definition of optional values. Name-value pairs can be
            %   added in any order.
            
            track = setProperties(track, varargin{:});            
        end
        
        %------------------------------------------------------------------
        % Setters, Getters, and validation
        %------------------------------------------------------------------
        function obj = set.TrackID(obj,value)
            validateattributes(value,{'numeric'},{'real','nonnegative','integer',...
                'nonsparse','scalar'},mfilename,'TrackID');
            obj.TrackID = cast(value,'uint32');
        end
        function obj = set.BranchID(obj,value)
            validateattributes(value,{'numeric'},{'real','nonnegative','integer',...
                'nonsparse','scalar'},mfilename,'BranchID');
            obj.BranchID = cast(value,'uint32');
        end
        function obj = set.SourceIndex(obj,value)
            validateattributes(value,{'numeric'},{'real','nonnegative','integer',...
                'nonsparse','scalar'},mfilename,'SourceIndex');
            obj.SourceIndex = cast(value,'uint32');
        end
        function obj = set.UpdateTime(obj,value)
            validateattributes(value,{'numeric'},{'real','nonnegative',...
                'nonsparse','finite','scalar'},mfilename,'UpdateTime');
            obj.pUpdateTime = cast(value,obj.pDataType);
        end
        function obj = set.Age(obj,value)
            validateattributes(value,{'numeric'},{'real','nonnegative','integer',...
                'nonsparse','scalar'},mfilename,'Age');
            obj.Age = cast(value,'uint32');
        end
        function obj = set.State(obj,value)
            validateattributes(value,{obj.pDataType},{'real','finite',...
                'nonsparse','vector'},mfilename,'State');
            obj.pState = value(:);
        end
        function obj = set.StateCovariance(obj,value)
            n = numel(obj.pState);
            validateattributes(value,{'single','double'},{'real','finite',...
                'nonsparse','2d','square','size',[n,n]},mfilename,'StateCovariance');
            matlabshared.tracking.internal.isSymmetricPositiveSemiDefinite('StateCovariance',value);
            obj.pStateCovariance = cast(value,obj.pDataType);
        end
        function value = get.UpdateTime(obj)
            value = obj.pUpdateTime;
        end
        function value = get.State(obj)
            value = obj.pState;
        end
        function value = get.StateCovariance(obj)
            value = obj.pStateCovariance;
        end
        function value = get.TrackLogic(obj)
            value = char(obj.pTrackLogicType);
        end
        function obj = set.TrackLogic(obj,value)
            coder.internal.errorIf(~coder.target('MATLAB'),...
                'shared_tracking:objectTrack:nontunableProp','TrackLogic');
            if isenum(value)
                val = char(value);
                v = validatestring(val,{'History','Score','Integrated'},...
                    mfilename, 'TrackLogic');
            else
                v = validatestring(value,{'History','Score','Integrated'},...
                    mfilename, 'TrackLogic');
            end
            obj = setTrackLogicType(obj,v);
        end
        function obj = set.TrackLogicState(obj,value)
            validateTrackLogicState(obj,value)
            switch obj.pTrackLogicType
                case 1 % History
                    obj.pTrackLogicState = cast(value(:)','logical');
                case 2 % Score
                    obj.pTrackLogicState = cast(value(:)',obj.pDataType);
                case 3 % Integrated
                    obj.pTrackLogicState = cast(value,obj.pDataType);
            end
        end
        function value = get.TrackLogicState(obj)
            value = obj.pTrackLogicState;
        end
        function obj = set.IsConfirmed(obj,value)
            validateFlag(obj,value,'IsConfirmed');
            obj.IsConfirmed = value;
        end
        function obj = set.IsCoasted(obj,value)
            validateFlag(obj,value,'IsCoasted');
            obj.IsCoasted = value;
        end
        function obj = set.IsSelfReported(obj,value)
            validateFlag(obj,value,'IsSelfReported');
            obj.IsSelfReported = value;
        end 
        function obj = set.ObjectClassID(obj,value)
            validateattributes(value,{'numeric'},{'real','nonnegative','integer',...
                'nonsparse','scalar'},mfilename,'ObjectClassID');
            obj.ObjectClassID = value; % Don't cast to uint32 as it may come from customer data
        end
        function obj = set.ObjectClassProbabilities(obj, value)
            validateattributes(value, {'numeric'},{'vector','nonempty','nonsparse',...
                'finite','real', 'nonnegative', '<=',1},...
                mfilename, 'ObjectClassProbabilities');
            coder.internal.errorIf(abs(sum(value)-1)>sqrt(eps(obj.pDataType)),...
                'shared_tracking:objectTrack:invalidClassProbabilityVector',...
                'ObjectClassProbabilities'); %#ok<MCSUP> 
            obj.ObjectClassProbabilities = cast(value(:)', obj.pDataType); %#ok<MCSUP> 
        end
        function obj = set.StateParameters(obj,value)
            validateattributes(value,{'struct'},{},mfilename,'StateParameters');
            obj.StateParameters = value;
        end
        function obj = set.ObjectAttributes(obj,value)
            validateattributes(value,{'struct','cell'},{},mfilename,'ObjectAttributes');
            if iscell(value)
                if isempty(value)
                    obj.ObjectAttributes = struct;
                else
                    obj.ObjectAttributes = value;
                end
            else
                obj.ObjectAttributes = value;
            end
        end
        
        function s = toStruct(obj, keepProb)
            %TOSTRUCT  Convert an objectTrack to a struct
            %   s = TOSTRUCT(OBJ) converts the objectTrack, OBJ, to a struct
            %   whose fields are equivalent to the object properties.
            validateattributes(obj,{'objectTrack'},{},mfilename,'toStruct')
            if nargin <2
                keepProb = true;
            end
            if isempty(obj) % For example, a 0x1 objectTrack output
                s = repmat(toStruct(objectTrack, keepProb),size(obj));
                return
            end

            n = numel(obj);
            s1 = protectedToStruct(obj(1),keepProb);
            if n == 1
                s = s1;
            else
                s = repmat(s1,size(obj));
                for i = 2:n
                    s(i) = protectedToStruct(obj(i),keepProb);
                end
            end
        end
    end
    
    methods (Access = {?objectTrack, ?fusion.simulink.trackFuser, ...
            ?fusion.simulink.trackerGridRFS})
        function s = protectedToStruct(obj,keepProbabilities, fuserTrackLogicSize)
            if nargin==1
                logicType = obj.TrackLogic;
                tls = obj.TrackLogicState;
                addClassProb = true;
            elseif nargin ==2
                logicType = obj.TrackLogic;
                tls = obj.TrackLogicState;
                addClassProb = keepProbabilities;
            else
                logicType = obj.pTrackLogicType;
                tls = obj.TrackLogicState(1:fuserTrackLogicSize);
                addClassProb = keepProbabilities;
            end

            if addClassProb
                s = struct(...
                    'TrackID',          obj.TrackID,...
                    'BranchID',         obj.BranchID,...
                    'SourceIndex',      obj.SourceIndex,...
                    'UpdateTime',       obj.UpdateTime,...
                    'Age',              obj.Age,...
                    'State',            obj.State,...
                    'StateCovariance',  obj.StateCovariance,...
                    'StateParameters',  obj.StateParameters,...
                    'ObjectClassID',    obj.ObjectClassID,...
                    'ObjectClassProbabilities', obj.ObjectClassProbabilities,...
                    'TrackLogic',       logicType,...
                    'TrackLogicState',  tls,...
                    'IsConfirmed',      obj.IsConfirmed,...
                    'IsCoasted',        obj.IsCoasted,...
                    'IsSelfReported',   obj.IsSelfReported,...
                    'ObjectAttributes', obj.ObjectAttributes...
                    );
            else
                s = struct(...
                    'TrackID',          obj.TrackID,...
                    'BranchID',         obj.BranchID,...
                    'SourceIndex',      obj.SourceIndex,...
                    'UpdateTime',       obj.UpdateTime,...
                    'Age',              obj.Age,...
                    'State',            obj.State,...
                    'StateCovariance',  obj.StateCovariance,...
                    'StateParameters',  obj.StateParameters,...
                    'ObjectClassID',    obj.ObjectClassID,...
                    'TrackLogic',       logicType,...
                    'TrackLogicState',  tls,...
                    'IsConfirmed',      obj.IsConfirmed,...
                    'IsCoasted',        obj.IsCoasted,...
                    'IsSelfReported',   obj.IsSelfReported,...
                    'ObjectAttributes', obj.ObjectAttributes...
                    );
            end

            

        end

    end
    
    %----------------------------------------------------------------------
    % Protected methods for assigning properties and defaults
    %----------------------------------------------------------------------
    methods (Access = protected)
        function track = setProperties(track, varargin)
            % Set the properties of the track object
            [trkID, brnID, sysID, updTime,age,state,stateCov,conf,coast,self,...
                clsID, clsProb, trprm, objAttr, tl, tls] = parseInputs(track, varargin{:});

            validateattributes(state,{'double','single'},{},mfilename,'State');
            
            % Number of states and data type are set once
            track.pDataType  = class(state);
            
            track.TrackID          = trkID;
            track.BranchID         = brnID;
            track.SourceIndex      = sysID;
            track.UpdateTime       = updTime;
            track.Age              = age;
            track.State            = state;
            track.StateCovariance  = stateCov;
            track.IsConfirmed      = conf;
            track.IsCoasted        = coast;
            track.IsSelfReported   = self;
            track.ObjectClassProbabilities = clsProb;
            track.ObjectClassID    = clsID;
            track.StateParameters  = trprm;
            track.ObjectAttributes = objAttr;
            
            if coder.target('MATLAB')
                if ischar(tl) || isstring(tl)
                    validatestring(tl,{'History','Score','Integrated'},...
                        mfilename, 'TrackLogic');
                end
            end
            
            % Track logic and track logic state are related
            if (isnumeric(tl) && tl==1) || strcmpi(char(tl),'History') 
                track.pTrackLogicType = trackLogicType.History;
                if tls == track.pConstantTrackLogicState
                    track.TrackLogicState = true;
                else
                    track.TrackLogicState = tls;
                end
            elseif (isnumeric(tl) && tl==2) || strcmpi(char(tl),'Score')
                track.pTrackLogicType = trackLogicType.Score;
                if tls == track.pConstantTrackLogicState
                    track.TrackLogicState = [0,0];
                else
                    track.TrackLogicState = tls;
                end
            elseif (isnumeric(tl) && tl==3) || strcmpi(char(tl),'Integrated')
                track.pTrackLogicType = trackLogicType.Integrated;
                if tls == track.pConstantTrackLogicState
                    track.TrackLogicState = 0.5;
                else
                    track.TrackLogicState = tls;
                end
            else
                coder.internal.error('shared_tracking:objectTrack:invalidTrackLogicType','TrackLogic')
            end
        end
        %------------------------------------------------------------------
        
        function [trkID, brnID, sysID, updTime,age,state,stateCov,conf,coast,self,...
                clsID, clsProb, trprm, objAttr, tl, tls] = parseInputs(track, varargin)
            % Parse inputs to objectDetection in MATLAB

            % Prepare parser
            NVPairNames = {'TrackID',...
                'BranchID',...
                'SourceIndex',...
                'UpdateTime',...
                'Age',...
                'State',...
                'StateCovariance',...
                'TrackLogic',...
                'TrackLogicState',...
                'IsConfirmed',...
                'IsCoasted',...
                'IsSelfReported',...
                'ObjectClassID',...
                'ObjectClassProbabilities',...
                'StateParameters',...
                'ObjectAttributes',...
                'Extent',...
                'MeasurementRate'}; %needed for extended track conversion

            poptions = struct( ...
                'CaseSensitivity',false, ...
                'PartialMatching','unique', ...
                'IgnoreNulls',true, ...
                'SupportOverrides',true);

            pstruct = coder.internal.parseInputs({},NVPairNames,poptions,varargin{:});

            % Retrieve input values.
            trkID = coder.internal.getParameterValue(pstruct.TrackID, track.pConstantTrackID,varargin{:});
            brnID = coder.internal.getParameterValue(pstruct.BranchID, track.pConstantBranchID,varargin{:});
            sysID = coder.internal.getParameterValue(pstruct.SourceIndex,track.pConstantSourceIndex,varargin{:});
            updTime = coder.internal.getParameterValue(pstruct.UpdateTime, track.pConstantUpdateTime,varargin{:});
            age = coder.internal.getParameterValue(pstruct.Age, track.pConstantAge,varargin{:});
            state = coder.internal.getParameterValue(pstruct.State, track.pConstantState,varargin{:});
            stateCov = coder.internal.getParameterValue(pstruct.StateCovariance, track.pConstantStateCovariance, varargin{:});
            conf = coder.internal.getParameterValue(pstruct.IsConfirmed, track.pConstantIsConfirmed, varargin{:});
            coast = coder.internal.getParameterValue(pstruct.IsCoasted, track.pConstantIsCoasted, varargin{:});
            self = coder.internal.getParameterValue(pstruct.IsSelfReported, track.pConstantIsSelfReported, varargin{:});
            clsID = coder.internal.getParameterValue(pstruct.ObjectClassID, track.pConstantObjectClassID,varargin{:});
            clsProb = coder.internal.getParameterValue(pstruct.ObjectClassProbabilities, track.pConstantObjectClassProbabilities,varargin{:});
            trprm = coder.internal.getParameterValue(pstruct.StateParameters, track.pConstantStateParameters,varargin{:});
            objAttr = coder.internal.getParameterValue(pstruct.ObjectAttributes, track.pConstantObjectAttributes,varargin{:});
            tl = coder.internal.getParameterValue(pstruct.TrackLogic, track.pConstantTrackLogic,varargin{:});
            tls = coder.internal.getParameterValue(pstruct.TrackLogicState, track.pConstantTrackLogicState,varargin{:});

        end
        %------------------------------------------------------------------
        
        function validateFlag(~,value,name)
            validateattributes(value,{'logical','numeric'},{'real','nonsparse','scalar','binary'},...
                mfilename,name);
        end
        
        function validateTrackLogicState(obj,value)
            switch obj.pTrackLogicType
                case 1 % History
                    validateattributes(value,{'numeric','logical'},{'binary','vector'},...
                        mfilename,'TrackLogicState');
                case 2 % Score
                    validateattributes(value,{'numeric'},{'real','finite',...
                        'nonsparse','nondecreasing','vector','numel',2},mfilename,...
                        'TrackLogicState');
                case 3 % Integrated
                    validateattributes(value,{'numeric'},{'real','finite',...
                        'nonsparse','nonnegative','scalar','<=',1},mfilename,...
                        'TrackLogicState');
            end
        end
        
        function obj = setTrackLogicType(obj,v)
            if coder.internal.is_defined(obj.pTrackLogicType)
                oldType = obj.pTrackLogicType;
            else
                oldType = 0;
            end
            obj.pTrackLogicType = trackLogicType.(v);
            newType = obj.pTrackLogicType;
            if oldType > 0 && oldType ~= newType
                switch newType
                    case 1
                        obj.TrackLogicState = true;
                    case 2
                        obj.TrackLogicState = [0 0];
                    case 3
                        obj.TrackLogicState = 0.5;
                end
            end
        end
    end
    methods(Static, Hidden)
        function props = matlabCodegenNontunableProperties(~)
            % Let the coder know about non-tunable parameters so that it
            % can generate more efficient code.
            props = {'pDataType', 'pTrackLogicType'};
        end
    end

    methods(Static)
        function obj = loadobj(s)
            if isstruct(s)
                obj = objectTrack;
                

                if isfield(s, 'ObjectClassProbabilities')
                    obj.ObjectClassProbabilities  = s.ObjectClassProbabilities; 
                else
                    obj.ObjectClassProbabilities  = 1;
                end

                obj.ObjectClassID             = s.ObjectClassID;
                obj.Age                       = s.Age;
                obj.BranchID                  = s.BranchID;
                obj.IsCoasted                 = s.IsCoasted;
                obj.IsConfirmed               = s.IsConfirmed;
                obj.IsSelfReported            = s.IsSelfReported;
                obj.ObjectAttributes          = s.ObjectAttributes;

                obj.SourceIndex               = s.SourceIndex;
                obj.StateParameters           = s.StateParameters;
                obj.TrackID                   = s.TrackID;
                if isfield(s, 'pUpdateTime')
                    obj.pUpdateTime      = s.pUpdateTime;
                else
                    obj.UpdateTime                = s.UpdateTime;
                end

                % Dependent properties
                obj.pState                    = s.pState;
                obj.pStateCovariance          = s.pStateCovariance;
                
                obj.pTrackLogicState          = s.pTrackLogicState;
                obj.pTrackLogicType           = s.pTrackLogicType;
                

                % Protected properties
                obj.pDataType                 = s.pDataType;
            else
                obj = s;
            end
            if isempty(obj.ObjectClassProbabilities)
                obj.ObjectClassProbabilities = 1;
            end
        end
    end
end