Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 14:47
    sdhiscocks closed #684
  • 11:17
    jwragg-dstl synchronize #667
  • 11:09
    jwragg-dstl synchronize #667
  • 10:44
    jwragg-dstl synchronize #667
  • 10:38
    jwragg-dstl synchronize #667
  • 10:38
    jwragg-dstl synchronize #667
  • 10:38
    jwragg-dstl synchronize #667
  • 10:36
    jwragg-dstl synchronize #667
  • 10:35
    jwragg-dstl synchronize #667
  • 10:35
    jwragg-dstl synchronize #667
  • 10:35
    jwragg-dstl synchronize #667
  • 10:34
    jwragg-dstl synchronize #667
  • Aug 08 15:03
    sdhiscocks closed #677
  • Aug 08 11:36
    sdhiscocks synchronize #687
  • Aug 08 11:12
    sdhiscocks unlabeled #686
  • Aug 08 11:12
    sdhiscocks labeled #686
  • Aug 08 11:11
    sdhiscocks closed #686
  • Aug 08 11:03
    sdhiscocks synchronize #687
  • Aug 08 10:40
    sdhiscocks review_requested #688
  • Aug 08 03:02
    victorzheng1 opened #689
Haoger
@Whaoger
@jswright-dstl ,Hi, I have some questions need your team's help. When I use the infrared passive sensor, the sensor may also detect other information besides azimuth and pitch Angle, such as measured pixel value, brightness value, which is a specific number rather than a category, and then these values will change steadily as the target moves. How do I add these attributes to the target's attributes, like CompositeGroundTruthState([kinematic, category]) in Disjoint Tracking and Classification. Thanks
Jordi Barr
@jmbarr
:point_up: May 12, 2022 11:04 PM - I've finally got round to this. See: https://gist.github.com/jmbarr/92dc83e28c04026136d4f8706a1159c1 and the branch at https://github.com/dstl/Stone-Soup/tree/PDAUpdater. @ktalbot and @sdhiscocks .
ktalbot
@ktalbot
@jmbarr Thank you for writing this up, it's quite a bit clearer than the reference-jumping I alluded to previously. In addition to being more intuitive, the Gaussian mixture viewpoint is nice from a software design perspective because it enables a clear separation of the estimation and association components: the updater is completely ignorant of association probabilities, etc. (as it should be).
ap
@apiszcz
I'm wondering if anyone has run into the following warning and if there is an approach to correcting the input data or estimate?
/usr/lib/python3/dist-packages/scipy/spatial/distance.py:1069: RuntimeWarning: invalid value encountered in sqrt
Haoger
@Whaoger
@sdhiscocks , Hi, we can use BoundingBoxReducer before MultiTargetTrackerto filtering detections. And so it should can filtering detections before MultiMeasurementInitiator, but i find the MultiMeasurementInitiator has no argument detector. So how can i do it.
Steven Hiscocks
@sdhiscocks
@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)
Haoger
@Whaoger
@sdhiscocks ,Ok, I'll test this program. Thank you.
Haoger
@Whaoger
@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
So I would like to ask how to modify CompositeUpdateInitiator
Haoger
@Whaoger

@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)
Steven Hiscocks
@sdhiscocks
:+1:
Haoger
@Whaoger

@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 ?

Steven Hiscocks
@sdhiscocks
This implies sub_hypotheses is empty; which I think occurs the code assumes tracks will be initiated for every detection. Try this
diff --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'],
ybtsdst
@ybtsdst
Hi, is there an example for multi track fusion, or any ideas, thanks
Brad Hards
@bradh
As in multiple tracks for a single target that you want to combine?
ybtsdst
@ybtsdst
yes, tracks from multi radar on a single target
Brad Hards
@bradh
A naive approach would just be to treat them as additional measurements.
Haoger
@Whaoger

@sdhiscocks , When I fixed the laest problem, and I found there were still a lot of mistakes when I tried to rewriteCompositeUpdateInitiatorto 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.

ap
@apiszcz
Is there an approach/method/function to translate a track data structure into a row type record for a pandas data frame? Tx
Amani
@Amanigence_twitter
Can I use the same measurement model for all the Filters( LKF,EKF,UKF,PF). In the first tutorial in stone soup, they used measurement_model = LinearGaussian() but in the other filters they used measurement_model = CartesianToBearingRange()...The question is, can I use this code [measurement_model = LinearGaussian()]for all types of filters?
Steven Hiscocks
@sdhiscocks
@apiszcz Not currently. Some of the nested components make it a little tricky, but should be able to create dataframe for base track elements (time, state vector elements, etc.). Would be interested if you develop something you could share.
@Amanigence_twitter - Yes, you can generally. There are some constraints, for example the Kalman kilter only works for linear models, but wouldn't work for non-linear model (e.g. Bearing Range); where as EKF and UKF from Kalman filter family are versions designed to handle the non-linear models.
Steven Hiscocks
@sdhiscocks
@Whaoger The CompositeUpdateInitiator in Stone Soup is designed where you are trying to combine for example categorical with kinematic states. Is this what your trying to do? Or just want to use multiple detections from multiple sensors for initiation?
ap
@apiszcz
Thanks, I have my own approach, did not want to keep it going if something better was in the framework.
Haoger
@Whaoger
@sdhiscocks , I want to divide the monitoring area into two, using heuristic and logical track initiation algorithms respectively.
ybtsdst
@ybtsdst
hi, is there any guide about adding a new measurement model
ap
@apiszcz
There is a QGIS Time Data Controller plugin that enables interactive visualization of vector data. https://github.com/mitre/QgisTDC the compiled plugin is available in the 'build' directory.
Steven Hiscocks
@sdhiscocks
@ybtsdst You can create a measurement model by creating a subclass that implements the required abstract methods. Many IDEs will create a template for you based on the abstract methods. Here's an example for a Gaussian Measurement Model:
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
ap
@apiszcz
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
Steven Hiscocks
@sdhiscocks
@apiszcz Looks like 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))
ap
@apiszcz
Thanks, it seems like the approach expects multiple detections for a track so the single case needs to be ignored. Here is what happens next.
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))
Steven Hiscocks
@sdhiscocks
@apiszcz What error message did you get?
Steven Hiscocks
@sdhiscocks
Suspect this should be hypotheses[0].prediction.timestamp similar to the tracker implementation.
ap
@apiszcz
sorry, error is
KeyError: 0
Steven Hiscocks
@sdhiscocks
ap
@apiszcz
Yes, I think it may be better if I create a modified note with a single point track and submit a ticket
        for track in self.kalman_tracks:

                track_hypotheses = hypotheses[track]
Haoger
@Whaoger
@sdhiscocks , Hello,PDA is to calculate the weighted sum of the probability values of the valid measurements in the associated gate, but the parameters of the associated gate are not set in the PDAHypothesis ?
So the probability of what measurement is being calculated?
Haoger
@Whaoger
Because I want to avoid the influence of multiple target measurements on trajectories by attenuating the probability values measured in the intersection area of the associated gate with different trajectories, it is necessary to first judge whether there is measurement in the intersection area of the associated gate .
Steven Hiscocks
@sdhiscocks
@Whaoger You can use a DistanceGater with Mahalanobis distance, but this is awkward as you need to calculate gate threshold yourself. We've resolved this in #636 which includes probability gate as standard, and also can use non parametric PDA.
Haoger
@Whaoger
Ok, Thank you, Regarding the track association of PDA algorithm under multi-target and multi-clutter background, is there any improvement measures? Because of the high real-time requirement, JPDA related algorithm is not considered at present.
kader kabore
@kaderkabore
Hey, the framework has great transitions model for linear motions but missing on non-Linear motion such as polar agent or UAV motion models. Can you give me tips to include custom non-Linear models?
Steven Hiscocks
@sdhiscocks

@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.

kader kabore
@kaderkabore
Thanks @sdhiscocks
Steven Hiscocks
@sdhiscocks
@kaderkabore If you do implement any new models, they'd be welcome additions if you were able to contribute them.