Main Content

trackerPHD

Multi-sensor, multi-object PHD tracker

Description

The trackerPHD System object™ is a tracker capable of processing detections of multiple targets from multiple sensors. The tracker uses a multi-target probability hypothesis density (PHD) filter to estimate the states of point targets and extended objects. PHD is a function defined over the state-space of the tracking system, and its value at a state is defined as the expected number of targets per unit state-space volume. The PHD is represented by a weighted summation (mixture) of probability density functions, and peaks in the PHD correspond to possible targets. For an overview of how the tracker functions, see Algorithms.

By default, the trackerPHD can track extended objects using the ggiwphd filter, which models detections from an extended object as a parse points cloud. You can also use trackerPHD with the gmphd filters, which tracks point targets and extended objects with designated shapes. Inputs to the tracker are detection reports generated by objectDetection, fusionRadarSensor, irSensor, or sonarSensor objects. The tracker outputs all maintained tracks and their analysis information.

To track targets using this object:

  1. Create the trackerPHD object and set its properties.

  2. Call the object with arguments, as if it were a function.

To learn more about how System objects work, see What Are System Objects?

Creation

Description

tracker = trackerPHD creates a trackerPHD System object with default property values.

example

tracker = trackerPHD(Name,Value) sets properties for the tracker using one or more name-value pairs. For example, trackerPHD('MaxNumTracks',100) creates a PHD tracker that allows a maximum of 100 tracks. Enclose each property name in quotes.

Properties

expand all

Unless otherwise indicated, properties are nontunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the release function unlocks them.

If a property is tunable, you can change its value at any time.

For more information on changing property values, see System Design in MATLAB Using System Objects.

Unique tracker identifier, specified as a nonnegative integer. This property is used as the SourceIndex in the tracker outputs, and distinguishes tracks that come from different trackers in a multiple-tracker system. You must specify this property as a positive integer to use the track outputs as inputs to a track fuser.

Example: 1

Configuration of tracking sensors, specified as a trackingSensorConfiguration object, an array of trackingSensorConfiguration objects, or a cell array of array of trackingSensorConfiguration objects. This property provides the tracking sensor configuration information, such as sensor detection limits and sensor resolution, to the tracker. Note that there are no default values for the SensorConfigurations property, and you must specify the SensorConfigurations property before using the tracker. However, you can update the configuration by setting the HasSensorConfigurationsInput property to true and specifying the configuration input, config. If you set the MaxDetsPerObject property of the trackingSensorConfiguration object to 1, the tracker creates only one partition, such that at most one detection can be assigned to each target.

Alternately, you can specify this property using structures with field names same as the property names of the trackingSensorConfiguration object.

Function to partition detections into detection cells, specified as a function handle or as a character vector. When each sensor can report more than one detection per object, a partition function is required. The partition function reports all possible partitions of the detections from a sensor. In each partition, the detections are separated into mutually exclusive detection cells, assuming that each detection cell belongs to one extended object.

You can also specify your own detections partition function. For guidance in writing this function, you can examine the details of the default partitioning function, partitionDetections, using the type command as:

type partitionDetections

Example: @myfunction or 'myfunction'

Data Types: function_handle | char

Birth rate of new targets in the density, specified as a scalar. Birth rate indicates the expected number of targets added in the density per unit time. The birth density is created by using the FilterInitializationFcn of the trackingSensorConfiguration used with the tracker. In general, the tracker adds components to the density function in two ways:

  1. Predictive birth density – density initialized by FilterInitializationFcn function when called with no inputs.

  2. Adaptive birth density – density initialized by FilterInitializationFcn function when called with detections inputs. The detections are chosen by the tracker based on their log-likelihood of association with the current estimates of the targets.

Note that the value for the BirthRate property represents the summation of both predictive birth density and adaptive birth density for each time step.

Example: 0.01

Data Types: single | double

Death rate of components in the density, specified as a scalar. Death rate indicates the rate at which a component vanishes in the density after one time step. Death rate (Pd) relates to the survival probability (Ps) of a component between successive time steps by

Ps=(1Pd)ΔT

where ΔT is the time step.

Example: 1e-4

Data Types: single | double

Threshold of selecting detections for component initialization, specified as a positive scalar. During correction, the tracker calculates the likelihood of association between existing tracks and detection cells. If the association likelihood (given by negative log-likelihood) of a detection cell to all existing tracks is higher than the threshold (which means the detection cell has low likelihood of association to existing tracks), the detection cell is used to initialize new components in the adaptive birth density.

Example: 18.1

Data Types: single | double

Threshold for initializing a tentative track, specified as a scalar. If the weight of a component is higher than the threshold specified by the ExtractionThreshold property, the component is labeled as a 'Tentative' track and given a TrackID.

Example: 0.45

Data Types: single | double

Threshold for track confirmation, specified as a scalar. In a trackerPHD object, a track can have multiple components sharing the same TrackID. If the weight summation of a tentative track's components is higher than the threshold specified by the ConfirmationThreshold property, the track's status is marked as 'Confirmed'.

Example: 0.85

Data Types: single | double

Threshold for component deletion, specified as a scalar. In the PHD tracker, if the weight of a component is lower than the value specified by the DeletionThreshold property, the component is deleted.

Example: 0.01

Data Types: single | double

Threshold for components merging, specified as a real positive scalar. In the PHD tracker, if the Kullback-Leibler distance between components with the same TrackID is smaller than the value specified by the MergingThreshold property, then these components are merged into one component. The merged weight of the new component is equal to the summation of the weights of the pre-merged components. Moreover, if the merged weight is higher than the first threshold specified in the LabelingThresholds property, the merged weight is truncated to the first threshold. Note that components with TrackID equal to 0 can also be merged with each other.

Example: 30

Data Types: single | double

Labeling thresholds, specified as an 1-by-3 vector of decreasing positive values, [C1, C2, C3]. Based on the LabelingThresholds property, the tracker manages components in the density using these rules:

  1. The weight of any component that is higher than the first threshold C1 is reduced to C1.

  2. For all components with the same TrackID, if the largest weight among these components is greater than C2, then the component with the largest weight is preserved to retain the TrackID, while all other components are deleted.

  3. For all components with the same TrackID, if the ratio of the largest weight to the weight summation of all these components is greater than C3, then the component with the largest weight is preserved to retain the TrackID, while all other components are deleted.

  4. If neither condition 2 nor condition 3 is satisfied, then the component with the largest weight retains the TrackID, while the labels of all other components are set to 0. When this occurs, it essentially means that some components may represent other objects. This treatment keeps the possibility for these unreserved components to be extracted again in the future.

Data Types: single | double

Enable updating sensor configurations with time, specified as false or true. Set this property to true if you want the configurations of the sensor updated with time. Also, when this property is set to true, the tracker must be called with the configuration input, config, as shown in the usage syntax.

Data Types: logical

Parameters of the track state reference frame, specified as a structure or a structure array. The tracker passes its StateParameters property values to the StateParameters property of the generated tracks. You can use these parameters to define the reference frame in which the track is reported or other desirable attributes of the generated tracks.

For example, you can use the following structure to define a rectangular reference frame whose origin position is at [10 10 0] meters and whose origin velocity is [2 -2 0] meters per second with respect to the scenario frame.

Field NameValue
Frame"Rectangular"
Position[10 10 0]
Velocity[2 -2 0]

Tunable: Yes

Data Types: struct

This property is read-only.

Number of tracks maintained by the tracker, returned as a nonnegative integer.

Data Types: double

This property is read-only.

Number of confirmed tracks, returned as a nonnegative integer. If the IsConfirmed field of an output track structure is true, the track is confirmed.

Data Types: double

Maximum number of sensors that can be connected to the tracker, specified as a positive integer. MaxNumSensors must be greater than or equal to the largest value of SensorIndex found in all the detections used to update the tracker. SensorIndex is a property of an objectDetection object.

Data Types: single | double

Maximum number of tracks that the tracker can maintain, specified as a positive integer.

Data Types: single | double

Maximum number of components that the tracker can maintain, specified as a positive integer.

Note

The tracker always uses this property to set the maximum number of components that the tracker can maintain and ignores the MaxNumComponents property set in the tracking filter object (ggiwphd or gmphd), which you specify through the SensorConfigurations property.

Data Types: single | double

Usage

To process detections and update tracks, call the tracker with arguments, as if it were a function (described here).

Note

You must specify the SensorConfigurations property before using the tracker.

Description

confirmedTracks = tracker(detections,time) returns a list of confirmed tracks that are updated from a list of detections, detections, at the update time, time. Confirmed tracks are corrected and predicted to the update time.

example

confirmedTracks = tracker(detections,config,time) also specifies a sensor configuration input, config. Use this syntax when the configurations of sensors are changing with time. To enable this syntax, set the HasSensorConfigurationsInput property to true.

[confirmedTracks,tentativeTracks,allTracks] = tracker(___) also returns a list of tentative tracks, tentativeTracks, and a list of all tracks, allTracks. You can use this output syntax with any of the previous input syntaxes.

[confirmedTracks,tentativeTracks,allTracks,analysisInformation] = tracker(___) also returns the analysis information, analysisInformation, which can be used for track analysis. You can use this output syntax with any of the previous input syntaxes.

Input Arguments

expand all

Detection list, specified as a cell array of objectDetection objects. The Time property value of each objectDetection object must be less than or equal to the current update time, time, and greater than the previous time value used to update the tracker. Also, the Time differences between different objectDetection objects in the cell array do not need to be equal.

Time of update, specified as a scalar. The tracker updates all tracks to this time. Units are in seconds.

time must be greater than or equal to the largest Time property value of the objectDetection objects in the input detections list. time must increase in value with each update to the tracker.

Data Types: single | double

Sensor configurations, specified as an array of structures, a cell array of structures, or a cell array of trackingSensorConfiguration objects. If you specify the value using an array of structures or a cell array of structures, you must include SensorIndex as a field for each structure. Other fields are optional, but each field in a structure must have the same name as one of the properties of the trackingSensorConfiguration object. Note that you only need to specify sensor configurations that need to be updated. For example, if you only want to update the IsValidTime property of the fifth sensor, specify config as struct('SensorIndex',5,'IsValidTime',false).

Tip

If you have a fusionRadarSensor sensor object in the tracking system, you can directly use the configuration structure output of the sensor object as this input.

Dependencies

To enable this argument, set the HasSensorConfigurationsInput property to true.

Output Arguments

expand all

Confirmed tracks updated to the current time, returned as a structure or an array of structures. Each structure corresponds to a track. A track is confirmed if the weight summation of its components is above the threshold specified by the ConfirmationThreshold property. If a track is confirmed, the IsConfirmed field of the structure is true. The fields of the confirmed tracks structure are defined in Track Structure.

Data Types: struct

Tentative tracks, returned as a structure or an array of structures. Each structure corresponds to a track. A track is tentative if the weight summation of its components is above the threshold specified by the ExtractionThreshold property, but below the threshold specified by the ConfirmationThreshold property. In that case, the IsConfirmed field of the structure is false. The fields of the structure are defined in Track Structure.

Data Types: struct

All tracks, returned as a structure or an array of structures. Each structure corresponds to a track. The set of all tracks consists of confirmed and tentative tracks. The fields of the structure are defined in Track Structure.

Data Types: struct

Additional information for analyzing track updates, returned as a structure. The fields of this structure are:

FieldDescription
CorrectionOrder

The order in which sensors are used for state estimate correction, returned as a row vector of SensorIndex. For example, [1 3 2 4].

TrackIDsAtStepBeginning

Track IDs when step began.

DeletedTrackIDs

IDs of tracks deleted during the step.

TrackIDsAtStepEnd

Track IDs when the step ended.

SensorAnalysisInfo

Cell array of sensor analysis information.

The SensorAnalysisInfo field can include multiple sensor information reports. Each report is a structure containing:

FieldDescription
SensorIndex

Sensor index.

DetectionCells

Detection cells, returned as a logical matrix. Each column of the matrix denotes a detection cell. In each column, if the ith element is 1, then the ith detection belongs to the detection cell denoted by that column.

DetectionLikelihoods

The association likelihoods between components in the density function and detection cells, returned as an N-by-P matrix. N is the number of components in the density function, and P is the number of detection cells.

IsBirthCells

Indicates if the detection cells listed in DetectionCells give birth to new tracks, returned as a 1-by-P logical vector, where P is the number of detection cells.

NumPartitions

Number of partitions.

DetectionProbability

Probability of existing tracks being detected by the sensor, specified as a 1-by-N row vector, where N is the number of components in the density function.

LabelsBeforeCorrection

Labels of components in the density function before correction, return as a 1-by-Mb row vector. Mb is the number of components maintained in the tracker before correction. Each element of the vector is a TrackID. For example, [1 1 2 0 0]. Note that multiple components can share the same TrackID.

LabelsAfterCorrection

Labels of components in the density function after correction, returned as a 1-by-Ma row vector. Ma is the number of components maintained in the tracker after correction. Each element of the vector is a TrackID. For example, [1 1 1 2 2 0 0]. Note that multiple components can share the same TrackID.

WeightsBeforeCorrection

Weights of components in the density function before correction, returned as a 1-by-Mb row vector. Mb is the number of components maintained in the tracker before correction. Each element of the vector is the weight of the corresponding component given in LabelsBeforeCorrection. For example, [0.1 0.5 0.7 0.3 0.2].

WeightsAfterCorrection

Weights of components in the density function after correction, returned as a 1-by-Ma row vector. Ma is the number of components maintained in the tracker after correction. Each element of the vector is the weight of the corresponding component given in LabelsAfterCorrection. For example, [0.1 0.4 0.2 0.6 0.3 0.2 0.2].

Data Types: struct

Object Functions

To use an object function, specify the System object as the first input argument. For example, to release system resources of a System object named obj, use this syntax:

release(obj)

expand all

predictTracksToTimePredict track state
deleteTrackDelete existing track
initializeTrackInitialize new track
sensorIndicesList of sensor indices
exportToSimulinkExport tracker or track fuser to Simulink model
getPHDFilterGet copy of PHD filter
generateCodeGenerate code for tracker object and object functions
stepRun System object algorithm
releaseRelease resources and allow changes to System object property values and input characteristics
isLockedDetermine if System object is in use
cloneCreate duplicate System object
resetReset internal states of System object

Examples

collapse all

Set up the sensor configuration, create a PHD tracker, and feed the tracker with detections.

    % Create sensor configuration. Specify clutter density of the sensor and
    % set the IsValidTime property to true.
    configuration = trackingSensorConfiguration(1);
    configuration.ClutterDensity = 1e-7;   
    configuration.IsValidTime = true;
    
    % Create a PHD tracker.
    tracker = trackerPHD('SensorConfigurations',configuration);
    
    % Create detections near points [5;-5;0] and [-5;5;0] at t=0, and 
    % update the tracker with these detections.
    detections = cell(20,1);
    for i = 1:10
        detections{i} = objectDetection(0,[5;-5;0] + 0.2*randn(3,1));
    end
    for j = 11:20
        detections{j} = objectDetection(0,[-5;5;0] + 0.2*randn(3,1));
    end

    tracker(detections,0);

Update the tracker again after 0.1 seconds by assuming that targets move at a constant velocity of [1;2;0] unit per second.

    dT = 0.1;
    for i = 1:20
        detections{i}.Time = detections{i}.Time + dT;
        detections{i}.Measurement = detections{i}.Measurement + [1;2;0]*dT;
    end
    [confTracks,tentTracks,allTracks] = tracker(detections,dT);

Visualize detections and confirmed tracks.

    % Obtain measurements from detections.
    d = [detections{:}];
    measurements = [d.Measurement];
    
    % Extract positions of confirmed tracking using getTrackPositions function.
    % Note that we used the default sensor configuration
    % FilterInitializationFcn, initcvggiwphd, which uses a constant velocity
    % model and defines the states as [x;vx;y;vy;z;vy].
    positionSelector = [1 0 0 0 0 0;0 0 1 0 0 0;0 0 0 0 1 0];
    positions = getTrackPositions(confTracks,positionSelector);
    
    figure()
    plot(measurements(1,:),measurements(2,:),'x','MarkerSize',5,'MarkerEdgeColor','b');
    hold on;
    plot(positions(1,1),positions(1,2),'v','MarkerSize',5,'MarkerEdgeColor','r' );
    hold on;
    plot(positions(2,1),positions(2,2),'^','MarkerSize',5,'MarkerEdgeColor','r' );
    legend('Detections','Track 1','Track 2')
    xlabel('x')
    ylabel('y')

Create a tracking scenario and specify its StopTime and UpdateRate properties.

scenario = trackingScenario;
scenario.StopTime = Inf;
scenario.UpdateRate = 0;

Add a tower platform in the scenario and specify its dimensions.

Tower = platform(scenario,'ClassID',3);

Tower.Dimensions = struct( ...
    'Length',10, ...
    'Width',10, ...
    'Height',60, ...
    'OriginOffset',[0 0 30]);

Add a car platform in the scenario. Specify its dimensions and trajectory.

Car = platform(scenario,'ClassID',2);

Car.Dimensions = struct( ...
    'Length',4.7, ...
    'Width',1.8, ...
    'Height',1.4, ...
    'OriginOffset',[-0.6 0 0.7]);

Car.Trajectory = waypointTrajectory( ...
    [0 -15 -0.23;0.3 -29.5 -0.23; 0.3 -42 -0.39;0.3 -56.5 -0.23; ...
    -0.3 -78.2 -0.23;4.4 -96.4 -0.23], ...
    [0; 1.4 ; 2.7;  4.1; 6.3; 8.2], ...
    'Course',[-88; -89; -89; -92; -84; -71], ...
    'GroundSpeed',[10; 10; 10; 10; 10; 10], ...
    'ClimbRate',[0; 0; 0; 0; 0; 0], ...
    'AutoPitch',true, ...
    'AutoBank',true);

Create a non-scanning radar, specify its properties, and mount the sensor on the tower.

NoScanning = fusionRadarSensor('SensorIndex',1, ...
    'UpdateRate',10, ...
    'MountingAngles',[-90 0 0], ...
    'FieldOfView',[20 10], ...
    'ScanMode','No scanning', ...
    'HasINS',true, ...
    'DetectionCoordinates','Scenario', ...
    'TargetReportFormat','Detections', ...
    'HasElevation',true);

Tower.Sensors = NoScanning;

Create a theater plot to visualize sensor coverage, tracks, and detections.

tp = theaterPlot('XLim',[-58 58],'YLim',[-104 12],'ZLim',[-109 8]);
set(tp.Parent,'YDir','reverse','ZDir','reverse');
view(tp.Parent,-37.5,30);
% Platform plotter for the car.
platp = platformPlotter(tp,'DisplayName','Targets','MarkerFaceColor','k');
% Detection plotter for sensor detections.
detp = detectionPlotter(tp,'DisplayName','Detections','MarkerSize',6, ...
    'MarkerFaceColor',[0.85 0.325 0.098],'MarkerEdgeColor','k','History',10000);
% Coverage plotter for sensor.
covp = coveragePlotter(tp,'DisplayName','Sensor Coverage');
% Track plotter for tracks.
tPlotter = trackPlotter(tp,'DisplayName','Tracks');

Extract the sensor configuration of the sensor and use it to specify a PHD tracker.

sensorConfig = trackingSensorConfiguration(scenario.Platforms{1}.Sensors{1}, ...
    'SensorTransformFcn',@cvmeas,'FilterInitializationFcn',@initcvggiwphd);

tracker = trackerPHD('SensorConfigurations',sensorConfig, ...
    'PartitioningFcn',@(x)partitionDetections(x,1,4.7),...
    'AssignmentThreshold',20,'ExtractionThreshold',0.8,...
    'ConfirmationThreshold',1.5,'MergingThreshold',20,...
    'DeletionThreshold',2e-1,'BirthRate',1e-3,... 
    'HasSensorConfigurationsInput',true);

Simulate the scenario, generate detections, and use the detections to track the car. Update the theater plot during simulation.

while advance(scenario) && ishghandle(tp.Parent)

    % Generate sensor data.
    [dets,configs,sensorConfigPIDs] = detect(scenario);

    % Read sensor data.
    allDets = [dets{:}];
    if ~isempty(allDets)
        % Extract measurement positions.
        meas = cat(2,allDets.Measurement)';
        % Extract measurement noise.
        measCov = cat(3,allDets.MeasurementNoise);
    else
        meas = zeros(0,3);
        measCov = zeros(3,3,0);
    end

    % Obtain true positions.
    truePoses = platformPoses(scenario);
    truePosition = vertcat(truePoses(:).Position);

    % Update tracker with the detections and sensor configuration.
    [cTracks,tTracks,allTracks] = tracker(dets,configs,scenario.SimulationTime);

    % Update the theater plot.
    plotPlatform(platp,truePosition);
    plotDetection(detp,meas,measCov);
    plotCoverage(covp,coverageConfig(scenario));
    % Update the track plotter. Extract track positions.
    positionSelector = [1 0 0 0 0 0; 0 0 1 0 0 0; 0 0 0 0 1 0];
    positions = getTrackPositions(cTracks,positionSelector);
    % Label and plot the tracks.
    if ~isempty(cTracks)
        labels = cell(numel(cTracks),1);
        for i =1:numel(cTracks)
            labels{i} = {['T',num2str(cTracks(i).TrackID)]};
        end
        plotTrack(tPlotter,positions,labels);
    end
    drawnow
end

More About

expand all

Algorithms

expand all

References

[1] Granstorm, K., C. Lundquiest, and O. Orguner. " Extended target tracking using a Gaussian-mixture PHD filter." IEEE Transactions on Aerospace and Electronic Systems. Vol. 48, Number 4, 2012, pp. 3268-3286.

[2] Granstorm, K., and O. Orguner." A PHD filter for tracking multiple extended targets using random matrices." IEEE Transactions on Signal Processing. Vol. 60, Number 11, 2012, pp. 5657-5671.

[3] Granstorm, K., and A. Natale, P. Braca, G. Ludeno, and F. Serafino."Gamma Gaussian inverse Wishart probability hypothesis density for extended target tracking using X-band marine radar data." IEEE Transactions on Geoscience and Remote Sensing. Vol. 53, Number 12, 2015, pp. 6617-6631.

[4] Panta, Kusha, et al. “Data Association and Track Management for the Gaussian Mixture Probability Hypothesis Density Filter.” IEEE Transactions on Aerospace and Electronic Systems, vol. 45, no. 3, July 2009, pp. 1003–16.

[5] Ristic, B., et al. “Adaptive Target Birth Intensity for PHD and CPHD Filters.” IEEE Transactions on Aerospace and Electronic Systems, vol. 48, no. 2, 2012, pp. 1656–68.

Extended Capabilities

Version History

Introduced in R2019a

expand all