-
Notifications
You must be signed in to change notification settings - Fork 171
Add measure property to PDAHypothesiser #1204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
rohatgunes
commented
Aug 4, 2025
- Allows for an implementable measure class.
- Defaults to SquaredMahalanobis, so no impact on legacy.
- Defaults to SquaredMahalanobis, so no impact on legacy.
- Defaults to SquaredMahalanobis, so no impact on legacy.
412d172 to
b797797
Compare
| if self.measure(measurement_prediction, detection) \ | ||
| <= self._gate_threshold(self.prob_gate, measurement_prediction.ndim): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering about what measures you are thinking of using, as here you can see the gate threshold it's compared to is designed to be in the same units as the measure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering about what measures you are thinking of using, as here you can see the gate threshold it's compared to is designed to be in the same units as the measure?
The gate threshold is using the gating-probability value to generate a N-dimensional Chi-square scalar distance value as threshold.
We think this can be compared to N-dimensional distance measurements like Mahalanobis, Euclidean or Weighted Euclidean. Also, during Extended Kalman operation, the innovation covariance can slightly deviate from positive semi-definite form which leads to Mahalanobis measure giving misleading output because of square-root of negative number. Having a customizable measure function can help to experiment with others methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sdhiscocks , was that a clear answer? Please let me know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for delay @rohatgunes.
I'm still not clear how Euclidean for example would work in comparison with Chi-square distance. But I can see that other gating approaches may be useful.
Maybe it would also be useful to be able to modify the _gate_threshold function in some way? Or replace the entire if line with a call to a function which returns true or false if it is inside or outside the gate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is worth mentioning here that we also have the Gater class, and more specifically the DistanceGater that should allow users to specify a custom measure for gating with any Hypothesiser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, DistanceGater does not seem to be compatible with PDAHypothesiser as is, where the gating affects probability of a particular hypothesis. It would be possible to keep PDAHypothesiser legacy behaviour intact and let PDAHypothesiser still be used standalone, and only treat detections as gated if a ProbabilityGater is to be used as a wrapper. Maybe this is too defensive/lazy of a programming but otherwise the cake does not seem to be worth the candle? Considering all references to be updated in docs etc. as well as keeping standalone option intact.
So I thought of something like below, to further allow _validation_region_volume() take its course within PDAHypothesiser. What do you think @sglvladi ? Would this be a desired approach @sdhiscocks ? Or would you prefer a different overhaul to override gating calculation within or keep _gate_threshold and wrapper threshold as 2-layer gating like in DistanceHypothesiser where missed_distance is the 1st layer and Gater adds 2nd?
class ProbabilityGater(Gater):
""" PDA based gater
Uses a measure to calculate the distance between a track's post state prediction and the
detection, then removes any detection whose calculated distance exceeds the
specified gate threshold.
"""
measure: Measure = Property(
doc="Measure class used to calculate the distance between the measurement "
"prediction and the hypothesised measurement.")
gate_threshold: float = Property(
doc="The gate threshold. Hypotheses whose calculated distance "
"exceeds this threshold will be filtered out.")
def hypothesise(self, track, detections, timestamp, *args, **kwargs):
# Predict once for gating
prediction = self.hypothesiser.predictor.predict(track, timestamp=timestamp, **kwargs)
gated_detections = [
detection for detection in detections
if self.measure(
self.hypothesiser.updater.predict_measurement(
prediction, detection.measurement_model, **kwargs
),
detection
) <= self.gate_threshold
]
# Pass the prediction to the hypothesiser for re-use and to indicate detections as already gated
return self.hypothesiser.hypothesise(
track, gated_detections, timestamp, prediction=prediction, **kwargs) #There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tl;dr:
Options:
Gaterimplementation, complex to respect legacy but followsGaterclass.measureand_gate_thresholdasPropertywith defaults to respect legacy, simple, straightforward.
Which one will it be?