# %% # Creating data associators # ------------------------- # To associate our detections to track objects generate hypotheses using a hypothesiser. In this # case we are using a :class:`~.Mahalanobis` distance measure. In addition, we are exploiting the # fact that the detections should have the same |MMSI|_ for a single vessel, by "gating" out # detections that don't match the tracks |MMSI|_ (this being populated by detections used to create # the track). from stonesoup.gater.filtered import FilteredDetectionsGater from stonesoup.hypothesiser.distance import DistanceHypothesiser from stonesoup.measures import Mahalanobis measure = Mahalanobis() hypothesiser = FilteredDetectionsGater(DistanceHypothesiser(predictor, updater, measure, missed_distance=3), metadata_filter="MMSI") # %% # We will use a nearest-neighbour association algorithm, passing in the Mahalanobis distance # hypothesiser built in the previous step. from stonesoup.dataassociator.neighbour import NearestNeighbour data_associator = NearestNeighbour(hypothesiser) # %% # Creating track initiators and deleters # -------------------------------------- # We need a method to initiate tracks. For this we will create an initiator component # and have it generate a :class:`~.GaussianState`. In this case, we'll use a measurement initiator
) detection_sim = SimpleDetectionSimulator( groundtruth=groundtruth_sim, measurement_model=measurement_model, meas_range=np.array([[-1, 1], [-1, 1]]) * 5000, # Area to generate clutter detection_probability=0.9, clutter_rate=1, seed=4 ) # Filter predictor = KalmanPredictor(transition_model) updater = KalmanUpdater(measurement_model) # Data Associator hypothesiser = DistanceHypothesiser(predictor, updater, Mahalanobis(), missed_distance=3) data_associator = GNNWith2DAssignment(hypothesiser) # Initiator & Deleter deleter = CovarianceBasedDeleter(covar_trace_thresh=1E3) initiator = MultiMeasurementInitiator( GaussianState(np.array([[0], [0], [0], [0]]), np.diag([0, 100, 0, 1000])), measurement_model=measurement_model, deleter=deleter, data_associator=data_associator, updater=updater, min_points=3, ) # Tracker tracker = MultiTargetTracker(
# The GM-PHD filter quantifies the predicted-measurement distance, just as in previous # tutorials. The metric for this is the Mahalanobis distance. We also require two # objects which together form the predictor and to generate hypotheses (or predictions) # based on the previous state. Recall that the GM-PHD propagates the first-order # statistical moment which is a Gaussian mixture. The predicted state at the next time # step is also a Gaussian mixture and can be determined solely by the propagated prior. # Determining this predicted Gaussian mixture is the job for the # :class:`~.GaussianMixtureHypothesiser` class. We must also generate a prediction for each track # in the simulation, and so use the :class:`~.DistanceHypothesiser` object as before. from stonesoup.predictor.kalman import KalmanPredictor kalman_predictor = KalmanPredictor(transition_model) from stonesoup.hypothesiser.distance import DistanceHypothesiser from stonesoup.measures import Mahalanobis base_hypothesiser = DistanceHypothesiser(kalman_predictor, kalman_updater, Mahalanobis(), missed_distance=3) from stonesoup.hypothesiser.gaussianmixture import GaussianMixtureHypothesiser hypothesiser = GaussianMixtureHypothesiser(base_hypothesiser, order_by_detection=True) # %% # The updater takes a list of hypotheses from the hypothesiser and transforms them into # potential new states for our tracks. Each state is a :class:`~.TaggedWeightedGaussianState` # object and has a state vector, covariance, weight, tag, and timestamp. Some of the # updated states have a very low weight, indicating that they do not contribute much to # the Gaussian mixture. To ease the computational complexity, a :class:`~.GaussianMixtureReducer` # is used to merge and prune many of the states based on provided thresholds. States whose # distance is less than the merging threshold will be combined, and states whose weight # is less than the pruning threshold will be removed.
# Now create a resampler and particle updater resampler = SystematicResampler() updater = ParticleUpdater(measurement_model=None, resampler=resampler) # Create a particle initiator from stonesoup.initiator.simple import GaussianParticleInitiator, SinglePointInitiator single_point_initiator = SinglePointInitiator( GaussianState([[0], [-40], [2000], [0], [8000], [0]], np.diag([10000, 1000, 10000, 1000, 10000, 1000])), None) initiator = GaussianParticleInitiator(number_particles=500, initiator=single_point_initiator) hypothesiser = DistanceHypothesiser(predictor, updater, measure=Mahalanobis(), missed_distance=np.inf) data_associator = GNNWith2DAssignment(hypothesiser) from stonesoup.deleter.time import UpdateTimeStepsDeleter deleter = UpdateTimeStepsDeleter(time_steps_since_update=10) # Create a Kalman single-target tracker tracker = SingleTargetTracker( initiator=initiator, deleter=deleter, detector=sim, data_associator=data_associator, updater=updater ) # %%
updater = KalmanUpdater(measurement_model) # %% # Creating data associators # ------------------------- # To associate our detections to track objects generate hypotheses using a hypothesiser. In this # case we are using a :class:`~.Mahalanobis` distance measure. In addition, we are exploiting the # fact that the detections should have the same |MMSI|_ for a single vessel, by gating out # detections that don't match the tracks |MMSI|_ (this being populated by detections used to create # the track). from stonesoup.gater.filtered import FilteredDetectionsGater from stonesoup.hypothesiser.distance import DistanceHypothesiser from stonesoup.measures import Mahalanobis measure = Mahalanobis() hypothesiser = FilteredDetectionsGater( DistanceHypothesiser(predictor, updater, measure, missed_distance=3), metadata_filter="MMSI" ) # %% # We will use a nearest-neighbour association algorithm, passing in the Mahalanobis distance # hypothesiser built in the previous step. from stonesoup.dataassociator.neighbour import NearestNeighbour data_associator = NearestNeighbour(hypothesiser) # %% # Creating track initiators and deleters # -------------------------------------- # We need a method to initiate tracks. For this we will create an initiator component # and have it generate a :class:`~.GaussianState`. In this case, we'll use a measurement initiator # which uses the measurement's value and model covariance where possible. In this case, as we are
from stonesoup.updater.kalman import KalmanUpdater updater = KalmanUpdater(measurement_model) #%% # .. note:: # # For more information on the above classes and how they operate you can refer to the Stone # Soup tutorial on # `using the Kalman Filter <https://stonesoup.readthedocs.io/en/latest/auto_tutorials/01_KalmanFilterTutorial.html>`_. # # Data Association # **************** # We utilise a :class:`~.DistanceHypothesiser` to generate hypotheses between tracks and # measurements, where :class:`~.Mahalanobis` distance is used as a measure of quality: from stonesoup.hypothesiser.distance import DistanceHypothesiser from stonesoup.measures import Mahalanobis hypothesiser = DistanceHypothesiser(predictor, updater, Mahalanobis(), 10) # %% # Continuing the :class:`~.GNNWith2DAssigment` class is used to perform fast joint data association, # based on the Global Nearest Neighbour (GNN) algorithm: from stonesoup.dataassociator.neighbour import GNNWith2DAssignment data_associator = GNNWith2DAssignment(hypothesiser) #%% # .. note:: # For more information on the above classes and how they operate you can refer to the # `Data Association - clutter <https://stonesoup.readthedocs.io/en/latest/auto_tutorials/05_DataAssociation-Clutter.html>`_ # and `Data Association - Multi-Target Tracking <https://stonesoup.readthedocs.io/en/latest/auto_tutorials/06_DataAssociation-MultiTargetTutorial.html>`_ # tutorials. # %% # Track Initiation # ****************
return set() deleter = MyDeleter() # %% # Setup Hypothesiser and Associator # --------------------------------- # Since we know there is only one measurement per scan, we can just use the # :class:`~.NearestNeighbour` associator to achieve our desired result. from stonesoup.measures import Euclidean from stonesoup.dataassociator.neighbour import NearestNeighbour from stonesoup.hypothesiser.distance import DistanceHypothesiser from stonesoup.tracker.simple import SingleTargetTracker meas = Euclidean() hypothesiser = DistanceHypothesiser(predictor, updater, meas) associator = NearestNeighbour(hypothesiser) tracker = SingleTargetTracker(initiator, deleter, detector, associator, updater) # %% # Run the Tracker # --------------------------------- # We extract the ground truth from the detector and then run the tracker. # While running the tracker we: # # - Extract the measurement that is associated with it. # - Extract the position components of the estimated state vector. # # This allows us to plot the measurements, ground truth, and state estimates.