# when told to (at every step). from stonesoup.types.hypothesis import SingleHypothesis from stonesoup.types.track import Track track = Track() for measurement in measurements: prediction = predictor.predict(prior, timestamp=measurement.timestamp) hypothesis = SingleHypothesis(prediction, measurement) post = updater.update(hypothesis) track.append(post) prior = track[-1] # %% # Plot the resulting track with the sample points at each iteration. plotter.plot_tracks(track, [0, 2], particle=True) plotter.fig # sphinx_gallery_thumbnail_number = 3 # %% # Key points # ---------- # 1. Sampling methods offer an attractive alternative to Kalman-based filtering for recursive # state estimation. # 2. The particle filter trades off a more subtle quantification of a non-Gaussian # estimate against increased computational effort. # 3. Very often particle filters encounter sample impoverishment and require a resampling step. # %% # References
# do this. Storing the information is facilitated by the top-level :class:`~.Track` class which # holds a sequence of states. from stonesoup.types.track import Track track = Track() for measurement in measurements: prediction = predictor.predict(prior, timestamp=measurement.timestamp) hypothesis = SingleHypothesis( prediction, measurement) # Group a prediction and measurement post = updater.update(hypothesis) track.append(post) prior = track[-1] # %% # Plot the resulting track, including uncertainty ellipses plotter.plot_tracks(track, [0, 2], uncertainty=True) plotter.fig # sphinx_gallery_thumbnail_number = 3 # %% # Key points # ---------- # 1. Stone Soup is built on a variety of types of :class:`~.State` object. These can be used to # represent hidden states, observations, estimates, ground truth, and more. # 2. Bayesian recursion is undertaken by the successive applications of predict and update methods # using a :class:`~.Predictor` and an :class:`~.Updater`. Explicit association of predicted # states with measurements is necessary. Broadly speaking, predictors apply a # :class:`~.TransitionModel`, data associators use a # :class:`~.Hypothesiser` to associate a prediction with a measurement, and updaters use this # association together with the :class:`~.MeasurementModel` to calculate the posterior state
# Populate the track from stonesoup.types.hypothesis import SingleHypothesis from stonesoup.types.track import Track track = Track() for measurement in measurements: prediction = predictor.predict(prior, timestamp=measurement.timestamp) hypothesis = SingleHypothesis(prediction, measurement) post = unscented_updater.update(hypothesis) track.append(post) prior = track[-1] # %% # And plot plotter.plot_tracks(track, [0, 2], uncertainty=True, color='r') plotter.fig # %% # The UT in slightly more depth # ----------------------------- # Now try and get a sense of what actually happens to the uncertainty when a non-linear combination # of functions happens. Instead of deriving this analytically (and potentially getting bogged-down # in the maths), let's just use a sampling method. # We can start with a prediction, which is Gauss-distributed in state space, that we will use to # make our measurement predictions from. from stonesoup.types.prediction import GaussianStatePrediction prediction = GaussianStatePrediction(state_vector=[[0], [0], [20], [0]], covar=np.diag([1.5, 0.5, 1.5, 0.5]), timestamp=datetime.now())
tracks, all_tracks = set(), set() for n, measurements in enumerate(all_measurements): # Calculate all hypothesis pairs and associate the elements in the best subset to the tracks. hypotheses = data_associator.associate(tracks, measurements, start_time + timedelta(seconds=n)) associated_measurements = set() for track in tracks: hypothesis = hypotheses[track] if hypothesis.measurement: post = updater.update(hypothesis) track.append(post) associated_measurements.add(hypothesis.measurement) else: # When data associator says no detections are good enough, we'll keep the prediction track.append(hypothesis.prediction) # Carry out deletion and initiation tracks -= deleter.delete_tracks(tracks) tracks |= initiator.initiate(measurements - associated_measurements, start_time + timedelta(seconds=n)) all_tracks |= tracks # %% # Plot the resulting tracks. # sphinx_gallery_thumbnail_number = 3 plotter.plot_tracks(all_tracks, [0, 2], uncertainty=True) plotter.fig
for predictor, updater, colour, filter, particle_count \ in zip(predictors, updaters, colours, filters, particle_counts): track = Track() prior = ParticleState(particles[:particle_count], timestamp=start_time) for measurement in measurements: prediction = predictor.predict(prior, timestamp=measurement.timestamp) hypothesis = SingleHypothesis(prediction, measurement) post = updater.update(hypothesis) track.append(post) prior = track[-1] plotter = Plotter() plotter.plot_ground_truths(truth, [0, 2]) plotter.plot_measurements(measurements, [0, 2]) plotter.plot_tracks(track, [0, 2], particle=True, color=colour) plotter.ax.set_title(filter) plotter.ax.set_xlim(0, 30) plotter.ax.set_ylim(0, 30) metric_manager = SimpleManager( [siap_gen], associator=TrackToTruth(association_threshold=np.inf)) metric_manager.add_data(tracks={track}, groundtruth_paths={truth}) pa[filter] = { metric for metric in metric_manager.generate_metrics() if metric.title.startswith('time-based SIAP PA') }.pop() # %%
track2 = Track() print("Capon detections:") for timestep, detections in detector1: for detection in detections: print(detection) prediction = predictor.predict(prior, timestamp=detection.timestamp) hypothesis = SingleHypothesis( prediction, detection) # Group a prediction and measurement post = updater.update(hypothesis) track1.append(post) prior = track1[-1] print("RJMCMC detections:") for timestep, detections in detector2: for detection in detections: print(detection) prediction = predictor.predict(prior, timestamp=detection.timestamp) hypothesis = SingleHypothesis( prediction, detection) # Group a prediction and measurement post = updater.update(hypothesis) track2.append(post) prior = track2[-1] plotter = Plotter() plotter.plot_tracks(set([track1, track2]), [0, 2], uncertainty=True) plotter.fig import matplotlib.pyplot as plt plt.show()