nrl-tracker 1.9.0__py3-none-any.whl → 1.9.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/METADATA +4 -4
  2. {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/RECORD +61 -60
  3. pytcl/__init__.py +2 -2
  4. pytcl/assignment_algorithms/gating.py +18 -0
  5. pytcl/assignment_algorithms/jpda.py +56 -0
  6. pytcl/assignment_algorithms/nd_assignment.py +65 -0
  7. pytcl/assignment_algorithms/network_flow.py +40 -0
  8. pytcl/astronomical/ephemerides.py +18 -0
  9. pytcl/astronomical/orbital_mechanics.py +131 -0
  10. pytcl/atmosphere/ionosphere.py +44 -0
  11. pytcl/atmosphere/models.py +29 -0
  12. pytcl/clustering/dbscan.py +9 -0
  13. pytcl/clustering/gaussian_mixture.py +20 -0
  14. pytcl/clustering/hierarchical.py +29 -0
  15. pytcl/clustering/kmeans.py +9 -0
  16. pytcl/coordinate_systems/conversions/geodetic.py +46 -0
  17. pytcl/coordinate_systems/conversions/spherical.py +35 -0
  18. pytcl/coordinate_systems/rotations/rotations.py +147 -0
  19. pytcl/core/__init__.py +16 -0
  20. pytcl/core/maturity.py +346 -0
  21. pytcl/core/optional_deps.py +1 -1
  22. pytcl/dynamic_estimation/gaussian_sum_filter.py +55 -0
  23. pytcl/dynamic_estimation/imm.py +29 -0
  24. pytcl/dynamic_estimation/information_filter.py +64 -0
  25. pytcl/dynamic_estimation/kalman/extended.py +56 -0
  26. pytcl/dynamic_estimation/kalman/linear.py +69 -0
  27. pytcl/dynamic_estimation/kalman/unscented.py +81 -0
  28. pytcl/dynamic_estimation/particle_filters/bootstrap.py +146 -0
  29. pytcl/dynamic_estimation/rbpf.py +51 -0
  30. pytcl/dynamic_estimation/smoothers.py +58 -0
  31. pytcl/dynamic_models/continuous_time/dynamics.py +104 -0
  32. pytcl/dynamic_models/discrete_time/coordinated_turn.py +6 -0
  33. pytcl/dynamic_models/discrete_time/singer.py +12 -0
  34. pytcl/dynamic_models/process_noise/coordinated_turn.py +46 -0
  35. pytcl/dynamic_models/process_noise/polynomial.py +6 -0
  36. pytcl/dynamic_models/process_noise/singer.py +52 -0
  37. pytcl/gravity/clenshaw.py +60 -0
  38. pytcl/gravity/egm.py +47 -0
  39. pytcl/gravity/models.py +34 -0
  40. pytcl/gravity/spherical_harmonics.py +73 -0
  41. pytcl/gravity/tides.py +34 -0
  42. pytcl/mathematical_functions/numerical_integration/quadrature.py +85 -0
  43. pytcl/mathematical_functions/special_functions/bessel.py +55 -0
  44. pytcl/mathematical_functions/special_functions/elliptic.py +42 -0
  45. pytcl/mathematical_functions/special_functions/error_functions.py +49 -0
  46. pytcl/mathematical_functions/special_functions/gamma_functions.py +43 -0
  47. pytcl/mathematical_functions/special_functions/lambert_w.py +5 -0
  48. pytcl/mathematical_functions/special_functions/marcum_q.py +16 -0
  49. pytcl/navigation/geodesy.py +101 -2
  50. pytcl/navigation/great_circle.py +71 -0
  51. pytcl/navigation/rhumb.py +74 -0
  52. pytcl/performance_evaluation/estimation_metrics.py +70 -0
  53. pytcl/performance_evaluation/track_metrics.py +30 -0
  54. pytcl/static_estimation/maximum_likelihood.py +54 -0
  55. pytcl/static_estimation/robust.py +57 -0
  56. pytcl/terrain/dem.py +69 -0
  57. pytcl/terrain/visibility.py +65 -0
  58. pytcl/trackers/hypothesis.py +65 -0
  59. {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/LICENSE +0 -0
  60. {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/WHEEL +0 -0
  61. {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/top_level.txt +0 -0
@@ -160,6 +160,20 @@ def line_of_sight(
160
160
  The refraction coefficient models atmospheric bending of radio waves.
161
161
  A typical value for radio frequencies is 0.13 (4/3 Earth model).
162
162
  For optical line of sight, use 0.
163
+
164
+ Examples
165
+ --------
166
+ >>> import numpy as np
167
+ >>> from pytcl.terrain.dem import create_flat_dem
168
+ >>> dem = create_flat_dem(
169
+ ... np.radians(35), np.radians(36),
170
+ ... np.radians(-120), np.radians(-119), elevation=100)
171
+ >>> result = line_of_sight(
172
+ ... dem,
173
+ ... np.radians(35.3), np.radians(-119.7), 10,
174
+ ... np.radians(35.7), np.radians(-119.3), 10)
175
+ >>> result.visible # Clear LOS over flat terrain
176
+ True
163
177
  """
164
178
  # Effective Earth radius for refraction
165
179
  if refraction_coeff > 0:
@@ -296,6 +310,19 @@ def viewshed(
296
310
  -------
297
311
  ViewshedResult
298
312
  Viewshed computation result with visibility grid.
313
+
314
+ Examples
315
+ --------
316
+ >>> import numpy as np
317
+ >>> from pytcl.terrain.dem import create_flat_dem
318
+ >>> dem = create_flat_dem(
319
+ ... np.radians(35), np.radians(36),
320
+ ... np.radians(-120), np.radians(-119), elevation=100)
321
+ >>> result = viewshed(
322
+ ... dem, np.radians(35.5), np.radians(-119.5), 20,
323
+ ... max_range=10000, n_radials=36, samples_per_radial=10)
324
+ >>> result.visible.any() # Some cells visible
325
+ True
299
326
  """
300
327
  # Convert max range to angular distance
301
328
  max_angular_range = max_range / earth_radius
@@ -428,6 +455,19 @@ def compute_horizon(
428
455
  -------
429
456
  list of HorizonPoint
430
457
  Horizon points for each azimuth direction.
458
+
459
+ Examples
460
+ --------
461
+ >>> import numpy as np
462
+ >>> from pytcl.terrain.dem import create_flat_dem
463
+ >>> dem = create_flat_dem(
464
+ ... np.radians(35), np.radians(36),
465
+ ... np.radians(-120), np.radians(-119), elevation=100)
466
+ >>> horizon = compute_horizon(
467
+ ... dem, np.radians(35.5), np.radians(-119.5), 10,
468
+ ... n_azimuths=8, max_range=10000, samples_per_radial=10)
469
+ >>> len(horizon)
470
+ 8
431
471
  """
432
472
  max_angular_range = max_range / earth_radius
433
473
 
@@ -534,6 +574,18 @@ def terrain_masking_angle(
534
574
  -------
535
575
  float
536
576
  Masking angle in radians above horizontal.
577
+
578
+ Examples
579
+ --------
580
+ >>> import numpy as np
581
+ >>> from pytcl.terrain.dem import create_flat_dem
582
+ >>> dem = create_flat_dem(
583
+ ... np.radians(35), np.radians(36),
584
+ ... np.radians(-120), np.radians(-119), elevation=100)
585
+ >>> angle = terrain_masking_angle(
586
+ ... dem, np.radians(35.5), np.radians(-119.5), 10, azimuth=0)
587
+ >>> -np.pi/2 <= angle <= np.pi/2 # Valid angle range
588
+ True
537
589
  """
538
590
  max_angular_range = max_range / earth_radius
539
591
 
@@ -628,6 +680,19 @@ def radar_coverage_map(
628
680
  -------
629
681
  ViewshedResult
630
682
  Radar coverage map.
683
+
684
+ Examples
685
+ --------
686
+ >>> import numpy as np
687
+ >>> from pytcl.terrain.dem import create_flat_dem
688
+ >>> dem = create_flat_dem(
689
+ ... np.radians(35), np.radians(36),
690
+ ... np.radians(-120), np.radians(-119), elevation=100)
691
+ >>> coverage = radar_coverage_map(
692
+ ... dem, np.radians(35.5), np.radians(-119.5), 30,
693
+ ... max_range=20000, n_radials=36, samples_per_radial=20)
694
+ >>> coverage.visible.any() # Some coverage exists
695
+ True
631
696
  """
632
697
  # Compute basic viewshed with refraction
633
698
  result = viewshed(
@@ -208,6 +208,29 @@ def compute_association_likelihood(
208
208
  -------
209
209
  likelihood : float
210
210
  Joint likelihood of the association.
211
+
212
+ Examples
213
+ --------
214
+ >>> import numpy as np
215
+ >>> # 2 tracks, 2 measurements
216
+ >>> likelihood_matrix = np.array([[0.9, 0.1],
217
+ ... [0.1, 0.8]])
218
+ >>> # Association: track 0 -> meas 0, track 1 -> meas 1
219
+ >>> association = {0: 0, 1: 1}
220
+ >>> lik = compute_association_likelihood(
221
+ ... association, likelihood_matrix,
222
+ ... detection_prob=0.9, clutter_density=1e-6, n_meas=2
223
+ ... )
224
+ >>> lik > 0
225
+ True
226
+ >>> # Association with missed detection
227
+ >>> assoc_miss = {0: 0, 1: -1} # track 1 misses
228
+ >>> lik_miss = compute_association_likelihood(
229
+ ... assoc_miss, likelihood_matrix,
230
+ ... detection_prob=0.9, clutter_density=1e-6, n_meas=2
231
+ ... )
232
+ >>> lik > lik_miss # Full detection more likely
233
+ True
211
234
  """
212
235
  likelihood = 1.0
213
236
 
@@ -259,6 +282,31 @@ def n_scan_prune(
259
282
  committed_track_ids : set
260
283
  Track IDs that are now committed (survived N-scan).
261
284
 
285
+ Examples
286
+ --------
287
+ >>> import numpy as np
288
+ >>> from pytcl.trackers.hypothesis import (
289
+ ... Hypothesis, MHTTrack, MHTTrackStatus, n_scan_prune
290
+ ... )
291
+ >>> # Two hypotheses, tracks with different creation scans
292
+ >>> track1 = MHTTrack(id=0, state=np.zeros(2), covariance=np.eye(2),
293
+ ... score=1.0, status=MHTTrackStatus.CONFIRMED,
294
+ ... history=[0], parent_id=-1, scan_created=0,
295
+ ... n_hits=3, n_misses=0)
296
+ >>> track2 = MHTTrack(id=1, state=np.zeros(2), covariance=np.eye(2),
297
+ ... score=0.5, status=MHTTrackStatus.TENTATIVE,
298
+ ... history=[1], parent_id=-1, scan_created=2,
299
+ ... n_hits=1, n_misses=0)
300
+ >>> tracks = {0: track1, 1: track2}
301
+ >>> hyp1 = Hypothesis(id=0, probability=0.8, track_ids=[0],
302
+ ... scan_created=0, parent_id=-1)
303
+ >>> hyp2 = Hypothesis(id=1, probability=0.2, track_ids=[1],
304
+ ... scan_created=2, parent_id=-1)
305
+ >>> pruned, committed = n_scan_prune([hyp1, hyp2], tracks, n_scan=2,
306
+ ... current_scan=3)
307
+ >>> len(pruned) >= 1
308
+ True
309
+
262
310
  Notes
263
311
  -----
264
312
  N-scan pruning works by:
@@ -338,6 +386,23 @@ def prune_hypotheses_by_probability(
338
386
  -------
339
387
  pruned : list of Hypothesis
340
388
  Pruned and renormalized hypotheses.
389
+
390
+ Examples
391
+ --------
392
+ >>> from pytcl.trackers.hypothesis import Hypothesis, prune_hypotheses_by_probability
393
+ >>> # 5 hypotheses with varying probabilities
394
+ >>> hyps = [
395
+ ... Hypothesis(id=0, probability=0.5, track_ids=[0], scan_created=0, parent_id=-1),
396
+ ... Hypothesis(id=1, probability=0.3, track_ids=[1], scan_created=0, parent_id=-1),
397
+ ... Hypothesis(id=2, probability=0.1, track_ids=[2], scan_created=0, parent_id=-1),
398
+ ... Hypothesis(id=3, probability=0.05, track_ids=[3], scan_created=0, parent_id=-1),
399
+ ... Hypothesis(id=4, probability=1e-8, track_ids=[4], scan_created=0, parent_id=-1),
400
+ ... ]
401
+ >>> pruned = prune_hypotheses_by_probability(hyps, max_hypotheses=3)
402
+ >>> len(pruned) # Only top 3 kept
403
+ 3
404
+ >>> sum(h.probability for h in pruned) # Renormalized to 1
405
+ 1.0
341
406
  """
342
407
  if not hypotheses:
343
408
  return []