Skip to content

Commit

Permalink
Pass measurement_model to is_detectable is SimpleSensor
Browse files Browse the repository at this point in the history
By passing a measurement mode to is_detectable, this avoids unnecessary
recreation of a model for every truth. Where a different model is
needed, still try to use the parameters of the sensor model in order to
minimise calculations.
  • Loading branch information
sdhiscocks committed Sep 30, 2024
1 parent 6c94fb4 commit 25a1697
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 36 deletions.
2 changes: 1 addition & 1 deletion stonesoup/sensor/passive.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def measurement_model(self):
translation_offset=self.position,
rotation_offset=self.orientation)

def is_detectable(self, state: GroundTruthState) -> bool:
def is_detectable(self, state: GroundTruthState, measurement_model=None) -> bool:
return True

def is_clutter_detectable(self, state: Detection) -> bool:
Expand Down
94 changes: 61 additions & 33 deletions stonesoup/sensor/radar/radar.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ def measurement_model(self):
translation_offset=self.position,
rotation_offset=self.orientation)

def is_detectable(self, state: GroundTruthState) -> bool:
measurement_vector = self.measurement_model.function(state, noise=False)
def is_detectable(self, state: GroundTruthState, measurement_model=None) -> bool:
if measurement_model is None:
measurement_model = self.measurement_model
measurement_vector = measurement_model.function(state, noise=False)
true_range = measurement_vector[1, 0] # Bearing(0), Range(1)
return true_range <= self.max_range

Expand Down Expand Up @@ -102,14 +104,23 @@ def measurement_model(self):
translation_offset=self.position,
rotation_offset=self.orientation)

def is_detectable(self, state: GroundTruthState) -> bool:
tmp_meas_model = CartesianToBearingRange(
ndim_state=self.ndim_state,
mapping=self.position_mapping,
noise_covar=self.noise_covar,
translation_offset=self.position,
rotation_offset=self.orientation
)
def is_detectable(self, state: GroundTruthState, measurement_model=None) -> bool:
if measurement_model is None:
tmp_meas_model = CartesianToBearingRange(
ndim_state=self.ndim_state,
mapping=self.position_mapping,
noise_covar=self.noise_covar,
translation_offset=self.position,
rotation_offset=self.orientation
)
else:
tmp_meas_model = CartesianToBearingRange(
ndim_state=measurement_model.ndim_state,
mapping=measurement_model.mapping,
noise_covar=measurement_model.noise_covar,
translation_offset=measurement_model.translation_offset,
rotation_offset=measurement_model.rotation_offset
)
measurement_vector = tmp_meas_model.function(state, noise=False)
true_range = measurement_vector[1, 0] # Bearing(0), Range(1)
return true_range <= self.max_range
Expand Down Expand Up @@ -180,8 +191,10 @@ def measure(self, ground_truths: Set[GroundTruthState], noise: Union[np.ndarray,

return super().measure(ground_truths, noise, **kwargs)

def is_detectable(self, state: GroundTruthState) -> bool:
measurement_vector = self.measurement_model.function(state, noise=False)
def is_detectable(self, state: GroundTruthState, measurement_model=None) -> bool:
if measurement_model is None:
measurement_model = self.measurement_model
measurement_vector = measurement_model.function(state, noise=False)

# Check if state falls within sensor's FOV
fov_min = -self.fov_angle / 2
Expand Down Expand Up @@ -265,21 +278,30 @@ def measure(self, ground_truths: Set[GroundTruthState], noise: Union[np.ndarray,

return super().measure(ground_truths, noise, **kwargs)

def is_detectable(self, state: GroundTruthState) -> bool:
antenna_heading = self.orientation[2, 0] + self.dwell_centre[0, 0]
# Set rotation offset of underlying measurement model
rot_offset = \
StateVector(
[[self.orientation[0, 0]],
[self.orientation[1, 0]],
[antenna_heading]])
tmp_meas_model = CartesianToBearingRange(
ndim_state=self.position_mapping,
mapping=self.position_mapping,
noise_covar=self.noise_covar,
translation_offset=self.position,
rotation_offset=rot_offset
)
def is_detectable(self, state: GroundTruthState, measurement_model=None) -> bool:
if measurement_model is None:
antenna_heading = self.orientation[2, 0] + self.dwell_centre[0, 0]
# Set rotation offset of underlying measurement model
rot_offset = \
StateVector(
[[self.orientation[0, 0]],
[self.orientation[1, 0]],
[antenna_heading]])
tmp_meas_model = CartesianToBearingRange(
ndim_state=self.ndim_state,
mapping=self.position_mapping,
noise_covar=self.noise_covar,
translation_offset=self.position,
rotation_offset=rot_offset
)
else:
tmp_meas_model = CartesianToBearingRange(
ndim_state=measurement_model.ndim_state,
mapping=measurement_model.mapping,
noise_covar=measurement_model.noise_covar,
translation_offset=measurement_model.translation_offset,
rotation_offset=measurement_model.rotation_offset
)
measurement_vector = tmp_meas_model.function(state, noise=False)

# Check if state falls within sensor's FOV
Expand Down Expand Up @@ -322,8 +344,10 @@ def measurement_model(self):
translation_offset=self.position,
rotation_offset=self.orientation)

def is_detectable(self, state: GroundTruthState) -> bool:
measurement_vector = self.measurement_model.function(state, noise=False)
def is_detectable(self, state: GroundTruthState, measurement_model=None) -> bool:
if measurement_model is None:
measurement_model = self.measurement_model
measurement_vector = measurement_model.function(state, noise=False)
true_range = measurement_vector[2, 0] # Elevation(0), Bearing(1), Range(2)
return true_range <= self.max_range

Expand Down Expand Up @@ -363,8 +387,10 @@ def measurement_model(self):
velocity=self.velocity,
rotation_offset=self.orientation)

def is_detectable(self, state: GroundTruthState) -> bool:
measurement_vector = self.measurement_model.function(state, noise=False)
def is_detectable(self, state: GroundTruthState, measurement_model=None) -> bool:
if measurement_model is None:
measurement_model = self.measurement_model
measurement_vector = measurement_model.function(state, noise=False)
true_range = measurement_vector[1, 0] # Bearing(0), Range(1), Range-Rate(2)
return true_range <= self.max_range

Expand Down Expand Up @@ -403,8 +429,10 @@ def measurement_model(self):
velocity=self.velocity,
rotation_offset=self.orientation)

def is_detectable(self, state: GroundTruthState) -> bool:
measurement_vector = self.measurement_model.function(state, noise=False)
def is_detectable(self, state: GroundTruthState, measurement_model=None) -> bool:
if measurement_model is None:
measurement_model = self.measurement_model
measurement_vector = measurement_model.function(state, noise=False)
true_range = measurement_vector[2, 0] # Elevation(0), Bearing(1), Range(2), Range-Rate(3)
return true_range <= self.max_range

Expand Down
4 changes: 2 additions & 2 deletions stonesoup/sensor/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def measure(self, ground_truths: Set[GroundTruthState], noise: Union[np.ndarray,
measurement_model = self.measurement_model

detectable_ground_truths = [truth for truth in ground_truths
if self.is_detectable(truth)]
if self.is_detectable(truth, measurement_model)]

if noise is True:
if len(detectable_ground_truths) > 1:
Expand Down Expand Up @@ -126,7 +126,7 @@ def measure(self, ground_truths: Set[GroundTruthState], noise: Union[np.ndarray,
return detections

@abstractmethod
def is_detectable(self, state: GroundTruthState) -> bool:
def is_detectable(self, state: GroundTruthState, measurement_model=None) -> bool:
raise NotImplementedError

@abstractmethod
Expand Down

0 comments on commit 25a1697

Please sign in to comment.