CompositeGroundTruthState([kinematic, category])
in Disjoint Tracking and Classification
. Thanks
BoundingBoxReducer
, but as a wrapper for an initiator.:from typing import Sequence, Tuple
from stonesoup.base import Property
from stonesoup.initiator import Initiator
class BoundingBoxFilter(Initiator):
initiator: Initiator = Property()
limits: Sequence[Tuple[float, float]] = Property()
mapping: Sequence[int] = Property(default=None)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.mapping is None:
self.mapping = tuple(range(len(self.limits)))
def initiate(self, detections, *args, **kwargs):
outlier_data = set()
for state in detections:
state_vector = state.state_vector
for i in range(len(self.limits)):
min = self.limits[i][0]
max = self.limits[i][1]
value = state_vector[self.mapping[i]]
if value < min or value > max:
outlier_data.add(state)
break
return self.initiate(detections - outlier_data, *args, **kwargs)
Traceback (most recent call last):
File "MOInfraredUKFCompositeInitiation.py", line 340, in <module>
for time, ctracks, in tracker:
File "C:\SET\Anaconda3\lib\site-packages\stonesoup\tracker\simple.py", line 222, in __next__
self._tracks |= self.initiator.initiate(
File "D:\WORK\Python_Projects\StoneSoup\ModifiedFunction.py", line 929, in initiate
hypothesis = CompositeHypothesis(prediction=None,
File "C:\SET\Anaconda3\lib\site-packages\stonesoup\types\hypothesis.py", line 233, in __init__
raise ValueError("Cannot create an empty composite hypothesis")
ValueError: Cannot create an empty composite hypothesis
CompositeUpdateInitiator
@Whaoger You'll need an extra component for that. Not tested, but this is based on the
BoundingBoxReducer
, but as a wrapper for an initiator.:from typing import Sequence, Tuple from stonesoup.base import Property from stonesoup.initiator import Initiator class BoundingBoxFilter(Initiator): initiator: Initiator = Property() limits: Sequence[Tuple[float, float]] = Property() mapping: Sequence[int] = Property(default=None) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self.mapping is None: self.mapping = tuple(range(len(self.limits))) def initiate(self, detections, *args, **kwargs): outlier_data = set() for state in detections: state_vector = state.state_vector for i in range(len(self.limits)): min = self.limits[i][0] max = self.limits[i][1] value = state_vector[self.mapping[i]] if value < min or value > max: outlier_data.add(state) break return self.initiate(detections - outlier_data, *args, **kwargs)
The last row shoud be:
return self.initiator.initiate(detections - outlier_data, *args, **kwargs)
@sdhiscocks , I am trying to modify
CompositeUpdateInitiator
to make it possible to use two track initiator based on motion information. But there were some problems .Traceback (most recent call last): File "MOInfraredUKFCompositeInitiation.py", line 340, in <module> for time, ctracks, in tracker: File "C:\SET\Anaconda3\lib\site-packages\stonesoup\tracker\simple.py", line 222, in __next__ self._tracks |= self.initiator.initiate( File "D:\WORK\Python_Projects\StoneSoup\ModifiedFunction.py", line 929, in initiate hypothesis = CompositeHypothesis(prediction=None, File "C:\SET\Anaconda3\lib\site-packages\stonesoup\types\hypothesis.py", line 233, in __init__ raise ValueError("Cannot create an empty composite hypothesis") ValueError: Cannot create an empty composite hypothesis
@sdhiscocks ，Hello, could you help me with this question ?
sub_hypotheses
is empty; which I think occurs the code assumes tracks will be initiated for every detection. Try thisdiff --git a/stonesoup/initiator/composite.py b/stonesoup/initiator/composite.py
index f3ab00d3..4e6651a7 100644
--- a/stonesoup/initiator/composite.py
+++ b/stonesoup/initiator/composite.py
@@ -120,6 +120,9 @@ class CompositeUpdateInitiator(Initiator):
# For each composite detection, create a track from its corresponding sub-hypotheses and
# sub-states
for detection, hyps_states in detection_hyps_states.items():
+ if len(hyps_states['sub-hypotheses']) < len(self.sub_initiators):
+ # No tracks initiated for this detection.
+ continue
# Create composite hypothesis from list of sub-hypotheses
hypothesis = CompositeHypothesis(prediction=None,
sub_hypotheses=hyps_states['sub-hypotheses'],
@sdhiscocks , When I fixed the laest problem, and I found there were still a lot of mistakes when I tried to rewriteCompositeUpdateInitiator
to fit combine two track initiator based on motion information, such as create a fixed platform which mounted with a radar sensor and moves within a 6 dimensional state space [x, v_x, y , v_y, z, v_z] .
initiator_1= PassiveHeuristicInitiator(
prior_state=prior_state,
measurement_model=measurement_model
deleter=deleter_step,
data_associator=init_data_associator,
updater=updater,
min_points=min_points)
filtered_initiator_1 = BoundingBoxFilter(
initiator=initiator_1,
limits=[[np.radians(-180), np.radians(0)]],
mapping=[1]
initiator_2 = ImprovedPassiveHeuristicInitiator(
prior_state=prior_state,
measurement_model=measurement_model,
deleter=deleter_step,
data_associator=init_data_associator,
updater=updater,
min_points=min_points)
filtered_initiator_2 = BoundingBoxFilter(
initiator=initiator_2,
limits=[[np.radians(0), np.radians(180)]],
mapping=[1]
)
initiator = ModifiedCompositeUpdateInitiator(
sub_initiators=[filtered_initiator_1, filtered_initiator_2])
)
So I can limit the initial range of two initiator, and then combine the two track initiator algorithms. But I don't know how to modify the CompositeUpdateInitiator
.
from typing import Union
import numpy as np
from stonesoup.models.measurement import MeasurementModel
from stonesoup.models.base import GaussianModel
from stonesoup.types.array import StateVector, StateVectors, CovarianceMatrix
from stonesoup.types.state import State
class MyNewMeasurementModel(MeasurementModel, GaussianModel):
@property
def ndim_meas(self) -> int:
pass
def covar(self, **kwargs) -> CovarianceMatrix:
pass
def function(self, state: State, noise: Union[bool, np.ndarray] = False, **kwargs) -> Union[
StateVector, StateVectors]:
pass
JPDA Tutorial question
Relevant code section from the JPDA tutorial: https://stonesoup.readthedocs.io/en/v0.1b9/auto_tutorials/08_JPDATutorial.html
for n, measurements in enumerate(all_measurements):
hypotheses = data_associator.associate(tracks,
measurements,
start_time + timedelta(seconds=n))
I have a measurement that consists of a single detection followed by the following stack trace.
Is there some approach to managing a measurement with a single detection?
I'm getting a trace when measurement has one detection due to non iteratable.
File C:\p\test\lib\python\lib\site-packages\stonesoup\hypothesiser\probability.py:120, in PDAHypothesiser.hypothesise(self, track, detections, timestamp, **kwargs)
112 hypotheses.append(
113 SingleProbabilityHypothesis(
114 prediction,
115 MissedDetection(timestamp=timestamp),
116 probability
117 ))
119 # True detection hypotheses
--> 120 for detection in detections:
121 # Re-evaluate prediction
122 prediction = self.predictor.predict(
123 track, timestamp=detection.timestamp, **kwargs)
124 # Compute measurement prediction and probability measure
TypeError: 'Detection' object is not iterable
measurements
in first for loop must be a Detection
rather than set of Detection
instances. If this your intent, need to create set of one (and probably best to rename measurements
to measurement
to avoid confusion.for n, measurement in enumerate(all_measurements):
hypotheses = data_associator.associate(tracks,
{measurement},
start_time + timedelta(seconds=n))
Input In [75], in MOT.jpda_filter(self)
741 post_mean, post_covar = gm_reduce_single(means, covars, weights)
743 # Add a Gaussian state approximation to the track.
744 track.append(GaussianStateUpdate(
745 post_mean, post_covar,
746 hypotheses,
--> 747 hypotheses[0].measurement.timestamp))
track_hypotheses = hypotheses[track]
?
for track in self.kalman_tracks:
track_hypotheses = hypotheses[track]
@kaderkabore There is one example here
A template for a Gaussian based transition model would be:
import datetime
from typing import Union
import numpy as np
from stonesoup.models.transition.nonlinear import GaussianTransitionModel
from stonesoup.models.base import TimeVariantModel
from stonesoup.types.array import StateVector, StateVectors, CovarianceMatrix
from stonesoup.types.state import State
class MyNewTransitionModel(GaussianTransitionModel, TimeVariantModel):
@property
def ndim_state(self) -> int:
pass
def covar(self, time_interval: datetime.timedelta, **kwargs) -> CovarianceMatrix:
pass
def function(self, state: State, time_interval: datetime.timedelta,
noise: Union[bool, np.ndarray] = False, **kwargs) -> Union[StateVector, StateVectors]:
pass
Where ndim_state
is dimensions of the state vector; covar
should return covariance matrix, and function
returns a new state based on state
and time_interval
.