nrl-tracker 0.4.2__py3-none-any.whl → 0.21.1__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 (135) hide show
  1. {nrl_tracker-0.4.2.dist-info → nrl_tracker-0.21.1.dist-info}/METADATA +16 -8
  2. nrl_tracker-0.21.1.dist-info/RECORD +148 -0
  3. pytcl/__init__.py +16 -19
  4. pytcl/assignment_algorithms/__init__.py +45 -22
  5. pytcl/assignment_algorithms/data_association.py +18 -8
  6. pytcl/assignment_algorithms/gating.py +74 -1
  7. pytcl/assignment_algorithms/jpda.py +2 -1
  8. pytcl/assignment_algorithms/three_dimensional/__init__.py +24 -0
  9. pytcl/assignment_algorithms/three_dimensional/assignment.py +659 -0
  10. pytcl/assignment_algorithms/two_dimensional/__init__.py +17 -4
  11. pytcl/assignment_algorithms/two_dimensional/assignment.py +2 -1
  12. pytcl/assignment_algorithms/two_dimensional/kbest.py +568 -0
  13. pytcl/astronomical/__init__.py +183 -30
  14. pytcl/astronomical/lambert.py +574 -0
  15. pytcl/astronomical/orbital_mechanics.py +877 -0
  16. pytcl/astronomical/reference_frames.py +677 -0
  17. pytcl/astronomical/time_systems.py +2 -2
  18. pytcl/atmosphere/__init__.py +9 -10
  19. pytcl/atmosphere/models.py +2 -1
  20. pytcl/clustering/__init__.py +20 -23
  21. pytcl/clustering/dbscan.py +2 -1
  22. pytcl/clustering/gaussian_mixture.py +2 -1
  23. pytcl/clustering/hierarchical.py +2 -1
  24. pytcl/clustering/kmeans.py +2 -1
  25. pytcl/containers/__init__.py +88 -2
  26. pytcl/containers/cluster_set.py +784 -0
  27. pytcl/containers/covertree.py +419 -0
  28. pytcl/containers/kd_tree.py +547 -0
  29. pytcl/containers/measurement_set.py +461 -0
  30. pytcl/containers/rtree.py +506 -0
  31. pytcl/containers/track_list.py +477 -0
  32. pytcl/containers/vptree.py +308 -0
  33. pytcl/coordinate_systems/__init__.py +79 -47
  34. pytcl/coordinate_systems/conversions/__init__.py +17 -18
  35. pytcl/coordinate_systems/conversions/geodetic.py +2 -1
  36. pytcl/coordinate_systems/conversions/spherical.py +2 -1
  37. pytcl/coordinate_systems/jacobians/__init__.py +7 -7
  38. pytcl/coordinate_systems/jacobians/jacobians.py +1 -0
  39. pytcl/coordinate_systems/projections/__init__.py +88 -2
  40. pytcl/coordinate_systems/projections/projections.py +1329 -0
  41. pytcl/coordinate_systems/rotations/__init__.py +12 -12
  42. pytcl/coordinate_systems/rotations/rotations.py +82 -0
  43. pytcl/core/__init__.py +11 -11
  44. pytcl/core/constants.py +1 -1
  45. pytcl/dynamic_estimation/__init__.py +100 -62
  46. pytcl/dynamic_estimation/imm.py +2 -1
  47. pytcl/dynamic_estimation/information_filter.py +647 -0
  48. pytcl/dynamic_estimation/kalman/__init__.py +30 -33
  49. pytcl/dynamic_estimation/kalman/extended.py +1 -0
  50. pytcl/dynamic_estimation/kalman/linear.py +2 -1
  51. pytcl/dynamic_estimation/kalman/square_root.py +2 -1
  52. pytcl/dynamic_estimation/kalman/unscented.py +2 -1
  53. pytcl/dynamic_estimation/particle_filters/__init__.py +7 -7
  54. pytcl/dynamic_estimation/particle_filters/bootstrap.py +2 -1
  55. pytcl/dynamic_estimation/smoothers.py +668 -0
  56. pytcl/dynamic_models/__init__.py +28 -29
  57. pytcl/dynamic_models/continuous_time/__init__.py +7 -7
  58. pytcl/dynamic_models/continuous_time/dynamics.py +3 -2
  59. pytcl/dynamic_models/discrete_time/__init__.py +7 -9
  60. pytcl/dynamic_models/discrete_time/polynomial.py +1 -0
  61. pytcl/dynamic_models/process_noise/__init__.py +8 -10
  62. pytcl/dynamic_models/process_noise/polynomial.py +1 -0
  63. pytcl/gravity/__init__.py +149 -2
  64. pytcl/gravity/clenshaw.py +556 -0
  65. pytcl/gravity/egm.py +697 -0
  66. pytcl/gravity/models.py +484 -0
  67. pytcl/gravity/spherical_harmonics.py +505 -0
  68. pytcl/gravity/tides.py +994 -0
  69. pytcl/magnetism/__init__.py +99 -2
  70. pytcl/magnetism/emm.py +820 -0
  71. pytcl/magnetism/igrf.py +643 -0
  72. pytcl/magnetism/wmm.py +709 -0
  73. pytcl/mathematical_functions/__init__.py +91 -59
  74. pytcl/mathematical_functions/basic_matrix/__init__.py +14 -15
  75. pytcl/mathematical_functions/basic_matrix/decompositions.py +3 -2
  76. pytcl/mathematical_functions/basic_matrix/special_matrices.py +1 -0
  77. pytcl/mathematical_functions/combinatorics/__init__.py +9 -9
  78. pytcl/mathematical_functions/combinatorics/combinatorics.py +3 -2
  79. pytcl/mathematical_functions/geometry/__init__.py +9 -9
  80. pytcl/mathematical_functions/geometry/geometry.py +2 -1
  81. pytcl/mathematical_functions/interpolation/__init__.py +6 -6
  82. pytcl/mathematical_functions/interpolation/interpolation.py +2 -1
  83. pytcl/mathematical_functions/numerical_integration/__init__.py +7 -7
  84. pytcl/mathematical_functions/numerical_integration/quadrature.py +39 -9
  85. pytcl/mathematical_functions/signal_processing/__init__.py +104 -2
  86. pytcl/mathematical_functions/signal_processing/detection.py +1047 -0
  87. pytcl/mathematical_functions/signal_processing/filters.py +839 -0
  88. pytcl/mathematical_functions/signal_processing/matched_filter.py +783 -0
  89. pytcl/mathematical_functions/special_functions/__init__.py +118 -39
  90. pytcl/mathematical_functions/special_functions/bessel.py +262 -1
  91. pytcl/mathematical_functions/special_functions/debye.py +288 -0
  92. pytcl/mathematical_functions/special_functions/elliptic.py +1 -1
  93. pytcl/mathematical_functions/special_functions/error_functions.py +1 -1
  94. pytcl/mathematical_functions/special_functions/gamma_functions.py +1 -1
  95. pytcl/mathematical_functions/special_functions/hypergeometric.py +420 -0
  96. pytcl/mathematical_functions/special_functions/lambert_w.py +294 -0
  97. pytcl/mathematical_functions/special_functions/marcum_q.py +370 -0
  98. pytcl/mathematical_functions/statistics/__init__.py +16 -17
  99. pytcl/mathematical_functions/statistics/distributions.py +3 -2
  100. pytcl/mathematical_functions/statistics/estimators.py +1 -0
  101. pytcl/mathematical_functions/transforms/__init__.py +119 -2
  102. pytcl/mathematical_functions/transforms/fourier.py +794 -0
  103. pytcl/mathematical_functions/transforms/stft.py +668 -0
  104. pytcl/mathematical_functions/transforms/wavelets.py +847 -0
  105. pytcl/navigation/__init__.py +202 -13
  106. pytcl/navigation/geodesy.py +2 -1
  107. pytcl/navigation/great_circle.py +799 -0
  108. pytcl/navigation/ins.py +1120 -0
  109. pytcl/navigation/ins_gnss.py +1086 -0
  110. pytcl/navigation/rhumb.py +722 -0
  111. pytcl/performance_evaluation/__init__.py +20 -20
  112. pytcl/performance_evaluation/estimation_metrics.py +2 -1
  113. pytcl/performance_evaluation/track_metrics.py +2 -1
  114. pytcl/plotting/__init__.py +29 -29
  115. pytcl/plotting/coordinates.py +2 -1
  116. pytcl/plotting/ellipses.py +2 -1
  117. pytcl/plotting/metrics.py +2 -1
  118. pytcl/plotting/tracks.py +2 -1
  119. pytcl/static_estimation/__init__.py +102 -2
  120. pytcl/static_estimation/least_squares.py +505 -0
  121. pytcl/static_estimation/maximum_likelihood.py +805 -0
  122. pytcl/static_estimation/robust.py +746 -0
  123. pytcl/terrain/__init__.py +127 -2
  124. pytcl/terrain/dem.py +722 -0
  125. pytcl/terrain/loaders.py +921 -0
  126. pytcl/terrain/visibility.py +705 -0
  127. pytcl/trackers/__init__.py +12 -15
  128. pytcl/trackers/hypothesis.py +2 -1
  129. pytcl/trackers/mht.py +5 -4
  130. pytcl/trackers/multi_target.py +3 -2
  131. pytcl/trackers/single_target.py +2 -1
  132. nrl_tracker-0.4.2.dist-info/RECORD +0 -104
  133. {nrl_tracker-0.4.2.dist-info → nrl_tracker-0.21.1.dist-info}/LICENSE +0 -0
  134. {nrl_tracker-0.4.2.dist-info → nrl_tracker-0.21.1.dist-info}/WHEEL +0 -0
  135. {nrl_tracker-0.4.2.dist-info → nrl_tracker-0.21.1.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nrl-tracker
3
- Version: 0.4.2
3
+ Version: 0.21.1
4
4
  Summary: Python port of the U.S. Naval Research Laboratory's Tracker Component Library for target tracking algorithms
5
5
  Author: Original: David F. Crouse, Naval Research Laboratory
6
6
  Maintainer: Python Port Contributors
7
- Project-URL: Homepage, https://github.com/nedonatelli/TCL
7
+ Project-URL: Homepage, https://pytcl.readthedocs.io/en
8
+ Project-URL: Documentation, https://pytcl.readthedocs.io/en/latest/docs.html
9
+ Project-URL: Repository, https://github.com/nedonatelli/TCL
8
10
  Project-URL: Bug Tracker, https://github.com/nedonatelli/TCL/issues
9
- Project-URL: Documentation, https://github.com/nedonatelli/TCL#readme
10
11
  Project-URL: Original MATLAB Library, https://github.com/USNavalResearchLaboratory/TrackerComponentLibrary
11
12
  Keywords: tracking,kalman-filter,target-tracking,data-association,estimation,navigation,coordinate-systems,signal-processing
12
13
  Classifier: Development Status :: 3 - Alpha
@@ -29,7 +30,7 @@ Requires-Dist: numpy>=1.24.0
29
30
  Requires-Dist: scipy>=1.10.0
30
31
  Requires-Dist: numba>=0.57.0
31
32
  Provides-Extra: all
32
- Requires-Dist: nrl-tracker[astronomy,dev,geodesy,optimization,visualization]; extra == "all"
33
+ Requires-Dist: nrl-tracker[astronomy,dev,geodesy,optimization,signal,visualization]; extra == "all"
33
34
  Provides-Extra: astronomy
34
35
  Requires-Dist: astropy>=5.0; extra == "astronomy"
35
36
  Requires-Dist: jplephem>=2.18; extra == "astronomy"
@@ -39,7 +40,8 @@ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
39
40
  Requires-Dist: pytest-xdist>=3.0.0; extra == "dev"
40
41
  Requires-Dist: hypothesis>=6.0.0; extra == "dev"
41
42
  Requires-Dist: black>=23.0.0; extra == "dev"
42
- Requires-Dist: ruff>=0.1.0; extra == "dev"
43
+ Requires-Dist: isort>=5.12.0; extra == "dev"
44
+ Requires-Dist: flake8>=7.0.0; extra == "dev"
43
45
  Requires-Dist: mypy>=1.0.0; extra == "dev"
44
46
  Requires-Dist: pre-commit>=3.0.0; extra == "dev"
45
47
  Requires-Dist: sphinx>=6.0.0; extra == "dev"
@@ -51,17 +53,23 @@ Requires-Dist: pyproj>=3.4.0; extra == "geodesy"
51
53
  Requires-Dist: geographiclib>=2.0; extra == "geodesy"
52
54
  Provides-Extra: optimization
53
55
  Requires-Dist: cvxpy>=1.3.0; extra == "optimization"
56
+ Provides-Extra: signal
57
+ Requires-Dist: pywavelets>=1.4.0; extra == "signal"
54
58
  Provides-Extra: visualization
55
59
  Requires-Dist: plotly>=5.15.0; extra == "visualization"
56
60
 
57
61
  # Tracker Component Library (Python)
58
62
 
63
+ [![PyPI version](https://img.shields.io/badge/pypi-v0.21.1-blue.svg)](https://pypi.org/project/nrl-tracker/)
59
64
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
60
65
  [![License: Public Domain](https://img.shields.io/badge/License-Public%20Domain-brightgreen.svg)](https://en.wikipedia.org/wiki/Public_domain)
61
66
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
67
+ [![Tests](https://img.shields.io/badge/tests-1530%20passing-success.svg)](https://github.com/nedonatelli/TCL)
62
68
 
63
69
  A Python port of the [U.S. Naval Research Laboratory's Tracker Component Library](https://github.com/USNavalResearchLaboratory/TrackerComponentLibrary), a comprehensive collection of algorithms for target tracking, estimation, coordinate systems, and related mathematical functions.
64
70
 
71
+ **800+ functions** | **144 modules** | **1,530 tests** | **15+ algorithm categories**
72
+
65
73
  ## Overview
66
74
 
67
75
  The Tracker Component Library provides building blocks for developing target tracking algorithms, including:
@@ -191,9 +199,9 @@ pytcl/
191
199
 
192
200
  ## Documentation
193
201
 
194
- - [API Reference](https://tracker-component-library-python.readthedocs.io/en/latest/api/)
195
- - [Tutorials](https://tracker-component-library-python.readthedocs.io/en/latest/tutorials/)
196
- - [Examples](https://tracker-component-library-python.readthedocs.io/en/latest/examples/)
202
+ - [API Reference](https://pytcl.readthedocs.io/en/latest/api/)
203
+ - [User Guides](https://pytcl.readthedocs.io/en/latest/user_guide/)
204
+ - [Examples](examples/)
197
205
 
198
206
  ## Comparison with Original MATLAB Library
199
207
 
@@ -0,0 +1,148 @@
1
+ pytcl/__init__.py,sha256=1grcwT7hqkF4MBmoUc9ugi2bhsecHLZuLZr8ALWSgC8,1894
2
+ pytcl/assignment_algorithms/__init__.py,sha256=f9V-TkEVmiKYYyth4PTpDfJvA7yYV_ys6Zix-QwWIYY,2136
3
+ pytcl/assignment_algorithms/data_association.py,sha256=X6Kww9-J2WLxU1790w7dRvAFdM90RSXHvs7IF26zweQ,11427
4
+ pytcl/assignment_algorithms/gating.py,sha256=fN_oAOkv7nYYOWE1oPOLrcCn3xEpKdMVlFSbRMAURxY,10815
5
+ pytcl/assignment_algorithms/jpda.py,sha256=hvZGkSrStuw9iQg7gPuIV7_bOinX3Xix5vLrVLMnEMM,19288
6
+ pytcl/assignment_algorithms/three_dimensional/__init__.py,sha256=1Q40OUlUQoo7YKEucwdrSNo3D4A0Zibvkr8z4TpueBg,526
7
+ pytcl/assignment_algorithms/three_dimensional/assignment.py,sha256=9BJhwlYu3JJ0kZ9sRyKKfpdvQdL4WYYHCtLbvaWycBw,19212
8
+ pytcl/assignment_algorithms/two_dimensional/__init__.py,sha256=4Evsn__9hTfI2i8m8Ngl-Zy0Fa2OydKmDKlZlH6jaao,778
9
+ pytcl/assignment_algorithms/two_dimensional/assignment.py,sha256=IRwbv-82dEbbm3KwjyUjuUWM3wP9s6oUtzX2mZffMjA,11419
10
+ pytcl/assignment_algorithms/two_dimensional/kbest.py,sha256=yiTToLuP7xWxQlQ8E-fpgXg-5iu0nnXcJXStjUB0nOE,17284
11
+ pytcl/astronomical/__init__.py,sha256=SKELDaDhxpvCo1dMswBQYOQr_Th3ShuzZTzxZMdhE-U,5650
12
+ pytcl/astronomical/lambert.py,sha256=Lc8FT1JmpI9WSXsG2s5vIRkSoBSV7r5hd3o2bGh2Ojo,15607
13
+ pytcl/astronomical/orbital_mechanics.py,sha256=8GssRanwTowCl6PJYqmB_SDnNznLUq5gkPa3j6iEo3U,19965
14
+ pytcl/astronomical/reference_frames.py,sha256=GDak7af6BqOwGnCUxkvFoeqd_H2TMubdjG9lGPCoUB4,15799
15
+ pytcl/astronomical/time_systems.py,sha256=Jg0Zaq60hc4Ts1aQtb5bK4KSZhz-uQse8gYC89Y0-TA,15243
16
+ pytcl/atmosphere/__init__.py,sha256=QAYgJYzgs0kreRV8fByii4p477LCxBDfrXB_cL7SYkM,706
17
+ pytcl/atmosphere/models.py,sha256=pMLv8D7qoFqLZrlbTHLJJULOdDdhPskJ1m7KVKLV63E,9584
18
+ pytcl/clustering/__init__.py,sha256=bYdhC_XJEt6KUUni9bIPxaddXNEGmIJQvGkA14rK4J8,1697
19
+ pytcl/clustering/dbscan.py,sha256=cjBi5b0gcBgFqUtkLm1G0JMJLQYALahyYuoSI4G0zAY,6903
20
+ pytcl/clustering/gaussian_mixture.py,sha256=U5U0Z46tZWdTLNdNNNJenoeviwZRAOvexVFYVLt4QMc,22865
21
+ pytcl/clustering/hierarchical.py,sha256=PEkIGqAQ33InUGIcCRevv0rko4R1HqIwfejNhHsbnKQ,13794
22
+ pytcl/clustering/kmeans.py,sha256=fmUIQdQLKCocwmMabdReQ0cKqMNKNFI_DyTCivPmAtw,10842
23
+ pytcl/containers/__init__.py,sha256=t8oRtusBrh6G2dEk2PcofmxrpLPQ9nOJwH19GyKnNcc,1699
24
+ pytcl/containers/cluster_set.py,sha256=_lZ39PNHTL7fUEZAwBF2ICK6v0GjZKpeUOg0knEdPzo,22760
25
+ pytcl/containers/covertree.py,sha256=1JWqXxoUFLxuMnjwj2qf0iz2uPzdujQYdwJW3l5qsOs,13282
26
+ pytcl/containers/kd_tree.py,sha256=pxRC62RYkqz9zXPz6c1fubmtPPBDLYA5I9AXMAoGanw,16348
27
+ pytcl/containers/measurement_set.py,sha256=Kr29mlJOCyGMYhMnE89f-W72aunlv4p04QAdfCZcm-0,12687
28
+ pytcl/containers/rtree.py,sha256=gv2EztvPnaAXEa6OoFnOYBY1MfTwjNMYh_BCiIomHJk,15450
29
+ pytcl/containers/track_list.py,sha256=6q9Qgcwm-8H_JqtOCsMssF27av4XaSkhfDl-MWb1ABc,12520
30
+ pytcl/containers/vptree.py,sha256=6fBNHrezkmj7L2nH0-2bONRN92f5cZAhS-5vaI1JZnA,8814
31
+ pytcl/coordinate_systems/__init__.py,sha256=jwYhu_-9AvOeP9WLG9PYtyDwfe0GjxNZ9-xCqiLymW4,3909
32
+ pytcl/coordinate_systems/conversions/__init__.py,sha256=PkNevB78vBw0BkalydJBbQO91AyiMJxKRrgJNt4HsYc,1100
33
+ pytcl/coordinate_systems/conversions/geodetic.py,sha256=qQSnJRt3jg5KiostvzyslPIbfn-1xBluo1r12oavWTQ,15737
34
+ pytcl/coordinate_systems/conversions/spherical.py,sha256=q7k9l5mJbVzVdNj9Gcq4ibFxax8z_mVpJfITRBzx630,10812
35
+ pytcl/coordinate_systems/jacobians/__init__.py,sha256=CRGB8GzvGT_sr4Ynm51S7gSX8grqt1pO1Pq1MWmHPTs,890
36
+ pytcl/coordinate_systems/jacobians/jacobians.py,sha256=1KufIoktm9mXLO34X9KjysdMpu7itGwfssRyAdkTTN8,11703
37
+ pytcl/coordinate_systems/projections/__init__.py,sha256=-IaYuCO9EU3ytik2KqIbFLP2YZScdaLsNJOXZJev6s0,2438
38
+ pytcl/coordinate_systems/projections/projections.py,sha256=yODS7n1gA4jsCJcU8EaeclHrbUBsZI9O2M_XJs2HOXs,33169
39
+ pytcl/coordinate_systems/rotations/__init__.py,sha256=nqAz4iJd2hEOX_r7Tz4cE524sShyxdbtcQ5m56RrDLg,1047
40
+ pytcl/coordinate_systems/rotations/rotations.py,sha256=FAYHkShQcpOlWJjtvLfNvtCx-a56pr-cbpo0QjC5W9U,18227
41
+ pytcl/core/__init__.py,sha256=H5JJPS-43DfF1UG7fSgV-VMTcZFBO8GuzDW1lM_1sm4,1152
42
+ pytcl/core/array_utils.py,sha256=SsgEiAoRCWxAVKq1aa5-nPdOi-2AB6XNObu0IaGClUk,13983
43
+ pytcl/core/constants.py,sha256=lZVDK5zsSR02_4b2Nqx9KDtZT9QaYhkZ9wuoODbifd4,8693
44
+ pytcl/core/validation.py,sha256=WRlzMlUihtqc3XZoWOTFK0sBAZVDIwTMGCiWcX5OZVY,13093
45
+ pytcl/dynamic_estimation/__init__.py,sha256=jA5FF6kHYklY5LMOfZaKcCeiPTpVe8vHIMp3ECDOmsc,4582
46
+ pytcl/dynamic_estimation/imm.py,sha256=CoOwJJv0DMrNKRkP-OqWbSxZO_-GAgNLaQ4KiBhjvEg,21313
47
+ pytcl/dynamic_estimation/information_filter.py,sha256=x7iQwO_iJT1dCSvDws5LqD3yAtjw9QVGUfMPcXn1IA4,17349
48
+ pytcl/dynamic_estimation/smoothers.py,sha256=qC_g0YG0U4L_7rGBpcZzYcb11A--Hc8tb0fxWXIJdxM,18931
49
+ pytcl/dynamic_estimation/batch_estimation/__init__.py,sha256=JQ0s76Enov5a7plA4EnUua4t-7etikQrwr5z4WIjUeo,46
50
+ pytcl/dynamic_estimation/kalman/__init__.py,sha256=yoFLj0n-NRkdZnRVL-BkHBlATk8pfZEVlsY3BhSYgKc,2387
51
+ pytcl/dynamic_estimation/kalman/extended.py,sha256=_deQTnUGOp_BlhP-FDEY0LOjgUMN32FQn0V12unCM4A,10397
52
+ pytcl/dynamic_estimation/kalman/linear.py,sha256=sTfWt_yDxyQCA0SMjOx4xfhVnq3nReOVUObXuUuZRv8,11844
53
+ pytcl/dynamic_estimation/kalman/square_root.py,sha256=Hw1F4_Zc7IA6Mt1WCkjx1UuLAUmNhM5vPLvueb7oRSA,26931
54
+ pytcl/dynamic_estimation/kalman/unscented.py,sha256=NXPBTAf6814Yw5HTFpX21w_Y0eSC6q1gZSRUHHYEQjI,14943
55
+ pytcl/dynamic_estimation/measurement_update/__init__.py,sha256=8rlyJwVpxf0fZj-AFo1hlewvryZRhUzcy3F8uMe6I8c,48
56
+ pytcl/dynamic_estimation/particle_filters/__init__.py,sha256=-DRF5rVF2749suLlArmkTvVkqeMcV_mIx0eLeTj6wNU,906
57
+ pytcl/dynamic_estimation/particle_filters/bootstrap.py,sha256=EfF9w0xqyBIYOHIwoYRt7D8aCgdPoGpvaFINu8gCZ80,12396
58
+ pytcl/dynamic_models/__init__.py,sha256=Cd8MyyYuB8gMnepkPA-HSwTaKFPThnqoKOhdjVOsXWg,2783
59
+ pytcl/dynamic_models/continuous_time/__init__.py,sha256=dAkfEddLkfMvDalK9v2GRBvaZV1KgqYpFBLOnoiFClw,1023
60
+ pytcl/dynamic_models/continuous_time/dynamics.py,sha256=CDwqn-66eUwXA5xfIjaG6A4EDBqtOyQ3aWarJr9QH4g,12858
61
+ pytcl/dynamic_models/discrete_time/__init__.py,sha256=pJ-VWMPkIdOcARM3CXlpYZcdUS5jWmqC6z2DXTd-b7c,966
62
+ pytcl/dynamic_models/discrete_time/coordinated_turn.py,sha256=jrSGCKiAdXaFIJBLzRyAv0xxxpOHOBnAtDHyu7VYsm8,7206
63
+ pytcl/dynamic_models/discrete_time/polynomial.py,sha256=zv5V-AbuaXlIj36n-YkOEyC74jV2vczxpCW09P0kmi0,5529
64
+ pytcl/dynamic_models/discrete_time/singer.py,sha256=wZS3Nad-YyPZp8Mle8Sf5GgW0-t4TxMRcnbc42HtQnA,3861
65
+ pytcl/dynamic_models/process_noise/__init__.py,sha256=3KVpLzGaNaR36DloPG5R1yaZWcR5QpdUJp2hwh5KFnk,950
66
+ pytcl/dynamic_models/process_noise/coordinated_turn.py,sha256=w7bHUImLPL5m3KYenfNgAnHPCRtAyYESbsFc6lQKXRg,4768
67
+ pytcl/dynamic_models/process_noise/polynomial.py,sha256=natfpsdN3qM9VzPeXF_nBpsbRI74S1WkkRCaaem6EQo,7620
68
+ pytcl/dynamic_models/process_noise/singer.py,sha256=lsJDT6xOvcS_qQKFtgHX0L7Ukpy4D7HgvPT8Q3I0ibU,3901
69
+ pytcl/gravity/__init__.py,sha256=5xNdQSrrkt7-1-JPOYqR38CqvNJ7qKlPyMK36DGm6-I,3693
70
+ pytcl/gravity/clenshaw.py,sha256=1BdxzU8IfGGd68H_U35soIJkiOHphY35e9mLElhPTOg,15364
71
+ pytcl/gravity/egm.py,sha256=QTRuvCiMjuNQdZF163OGwjxuivpGu2dB6E0zQLbKPP8,18083
72
+ pytcl/gravity/models.py,sha256=rdY3Do4M1eRFO74gu3xy-bBn7tox3zM49wYbfnsIQWw,11159
73
+ pytcl/gravity/spherical_harmonics.py,sha256=uZasz-w2K16sWT6xrNIPyTEP6MSlMQSe_BCWpXhRkWY,14722
74
+ pytcl/gravity/tides.py,sha256=hef_BGewFGD7dJwg0t09Z6tfWLco_avATLuu66rnTpI,27733
75
+ pytcl/magnetism/__init__.py,sha256=FNggjh99tEybKM2RxuX_EJlgu3U3CrREBadXOvRguGA,2549
76
+ pytcl/magnetism/emm.py,sha256=5Jwl99wvdKYtx1-3LBB7x-w5KT-fqLiRg7uBW0Ai_Gw,22292
77
+ pytcl/magnetism/igrf.py,sha256=3g0PsH8IdbwQQS28OR5XWD-g-QxvfUva7jOkKToxndQ,13384
78
+ pytcl/magnetism/wmm.py,sha256=p0H7Eo02iB6nEMvGyvjsrAWOSKrIye6PGwQtNKfHaNw,15999
79
+ pytcl/mathematical_functions/__init__.py,sha256=zeJ1ffRRl83k2NHn3HTn-fgtFoWNPq6LCALc3xRo4Do,3767
80
+ pytcl/mathematical_functions/basic_matrix/__init__.py,sha256=kZv3kMAEHBdVxhbyMxTyM0s-4XJP1tK6po82UsIE4tc,1318
81
+ pytcl/mathematical_functions/basic_matrix/decompositions.py,sha256=PWJsFDiXM2T78RHdxBJZPFnl8kFbNZQpHrbpw0mhE00,12268
82
+ pytcl/mathematical_functions/basic_matrix/special_matrices.py,sha256=kOozwP2CHAj4qyO7Z9ct6GwDMkmHkk1bQa0e9G98FgA,13499
83
+ pytcl/mathematical_functions/combinatorics/__init__.py,sha256=byuHI0WkxOkQF8egrfjEr-awB2visWDXlGMnDux5IBg,1043
84
+ pytcl/mathematical_functions/combinatorics/combinatorics.py,sha256=3EgkWdBqQ9e6JU34bec9EeCEmB-46tUSXXTAJrckSO4,12314
85
+ pytcl/mathematical_functions/continuous_optimization/__init__.py,sha256=lck60eeCUOsRpEzPHBY3kiLKwNz_fhmYoUGP3lTmTwk,55
86
+ pytcl/mathematical_functions/geometry/__init__.py,sha256=DhCmux9-6zxYRzlhQ9du18kvUL-leiiZwdd3Cmb5WX0,1092
87
+ pytcl/mathematical_functions/geometry/geometry.py,sha256=l63wQnhCtJwVHZOJeONX1qyJ5Sedji8etgxwJCFtH8Y,16403
88
+ pytcl/mathematical_functions/interpolation/__init__.py,sha256=HDhP7ZsgUrXFBNJ_eCZEdp5gizWJ-BxvkQSCMnvBg3A,677
89
+ pytcl/mathematical_functions/interpolation/interpolation.py,sha256=2cXMDgWBjWDGHnK1K_lawFlJL8oPl5AQGf9MNgsESfo,12610
90
+ pytcl/mathematical_functions/numerical_integration/__init__.py,sha256=iXiHzyV_KIhCv7tXErXlN1_fUEACN6yN3CYDHRA7esw,974
91
+ pytcl/mathematical_functions/numerical_integration/quadrature.py,sha256=ZRMKs0vbcgFDe1Sr8sjyEOkALLmJU4zKRJjoPEcXrUc,15670
92
+ pytcl/mathematical_functions/polynomials/__init__.py,sha256=WJWZcoQhnvy5f59-kncMTgD9mCtgwfDgULvDYYHS5ys,43
93
+ pytcl/mathematical_functions/signal_processing/__init__.py,sha256=_SzzBVtxmSvP8FKeogRdNmFo8FOVDDoexVOqd-lE7do,2325
94
+ pytcl/mathematical_functions/signal_processing/detection.py,sha256=9F0xdy3hMat1czSWAQYMExn0kY5DBRpyBneAfjjHUVI,30377
95
+ pytcl/mathematical_functions/signal_processing/filters.py,sha256=8Ojf4h4rfiucBXqUmB1odvHH41Gf3rPwmWCMKb-qzWk,23435
96
+ pytcl/mathematical_functions/signal_processing/matched_filter.py,sha256=AahJZRZk2IIXzRL7www0n8bc0XoKabaLOe8yYNSjuDY,22893
97
+ pytcl/mathematical_functions/special_functions/__init__.py,sha256=qDPGfee1i1NkVi9LXJKnsWXL3CWHkPQINrkwqLqB8YU,3796
98
+ pytcl/mathematical_functions/special_functions/bessel.py,sha256=M0mwLQBaUXEHA8wyKReJ2D66I1v1XR7y-txAipd-WDs,14377
99
+ pytcl/mathematical_functions/special_functions/debye.py,sha256=Nchjwkl1vzSL1L7nQpslb-lvT49LgTfdTIQMeSNn4vQ,6689
100
+ pytcl/mathematical_functions/special_functions/elliptic.py,sha256=WyzBkrfZufIR5dUmCKGcxp6KNpVDrU89NGLDyRrZOqQ,7418
101
+ pytcl/mathematical_functions/special_functions/error_functions.py,sha256=a3SS8FYAMRv1KdCmebOZL95yjvVt9gZRF2XOjHvQ9M8,6253
102
+ pytcl/mathematical_functions/special_functions/gamma_functions.py,sha256=xXN_9SCokH10HjE8PpaPKHYVK_RZRHRAbZgR2mZYIAA,10191
103
+ pytcl/mathematical_functions/special_functions/hypergeometric.py,sha256=gKn_tXboEst7pVDiW15IbKFAANM4XVqKtDc1dmWL-2A,9768
104
+ pytcl/mathematical_functions/special_functions/lambert_w.py,sha256=ivRc4KH5Lwoxb_yijrJEwG0ITa0hhcYF7_gCfVBBNW4,6855
105
+ pytcl/mathematical_functions/special_functions/marcum_q.py,sha256=OZ5QjIB1e_XvRG8A-3dbZ13YXHtdk2EYVEPaqtgVr14,9580
106
+ pytcl/mathematical_functions/statistics/__init__.py,sha256=dfypStgmnFmOrnWcm-3CEvLinONHraFgx9O66_37bqw,1278
107
+ pytcl/mathematical_functions/statistics/distributions.py,sha256=icfFIIKCEFzkpFHuYGWL197nm8wvS7UPJlr9kd_uEgw,19373
108
+ pytcl/mathematical_functions/statistics/estimators.py,sha256=TLnYXSwk5MzBakZrzDBupbOB3ONmJI7q1-oB2xuSVQM,10831
109
+ pytcl/mathematical_functions/transforms/__init__.py,sha256=SPXSKHjqR6B_8pvgtbtOnEiCpU-u0JF2s7hAlhb0BbI,2343
110
+ pytcl/mathematical_functions/transforms/fourier.py,sha256=QH6OaTzw4kN6M-DuSmwB_5b-wu_4yP5I2CUmNEyLORM,20737
111
+ pytcl/mathematical_functions/transforms/stft.py,sha256=zQapXl-v69_RDPwMqci83jah17GyAfnr3gx0budv2Cg,18619
112
+ pytcl/mathematical_functions/transforms/wavelets.py,sha256=dm273Z_t13BlEVSlHTaGE7jR1ocugL7lEkcO499U7bY,21656
113
+ pytcl/misc/__init__.py,sha256=SCHf_lQVfdl2gwUluHBiIloTF8HRH8EkgYfbNr7zOug,33
114
+ pytcl/navigation/__init__.py,sha256=9tUhEgPVugA8nmZ9rvOaAntCd7rDPgW2RBLHqaDAXSc,5864
115
+ pytcl/navigation/geodesy.py,sha256=M9XXfBTMCRdaWMV2-ViDSTEt94WZnMtxMeJQ1FAgQHY,17227
116
+ pytcl/navigation/great_circle.py,sha256=TtlkWZbzr-HzSt4ultG_h137ZnX0pJZx_87kr3uvpjI,20923
117
+ pytcl/navigation/ins.py,sha256=V3ZA4z8y5E6PBCd1FhifR5VaCU7DRAn2fb7W0LilByo,31168
118
+ pytcl/navigation/ins_gnss.py,sha256=euKF5JGgwmVBsw3jBf7_wa2z1BpZeVbSNmBuwzhGS6c,30157
119
+ pytcl/navigation/rhumb.py,sha256=lr1c3iEXfoOSfIyyXSRWv6He5TlaxEHbJy-dhqM1gRw,18224
120
+ pytcl/performance_evaluation/__init__.py,sha256=tM2pnBfDb2XbnLt4Y5MQ6w6XBwFy_5bf_y0toZmxx88,1859
121
+ pytcl/performance_evaluation/estimation_metrics.py,sha256=X1ZCpp8m6DV14N2wbMvlRwfORRKga8DgKmG3dROyJqA,12351
122
+ pytcl/performance_evaluation/track_metrics.py,sha256=Nd3royJkAelZV-Qggl8i72e7WocCxWomgliArvVAEkc,13342
123
+ pytcl/physical_values/__init__.py,sha256=SGbg6b0d4dWebE3baW4OlJshL00grG5E4wABw6jxl20,44
124
+ pytcl/plotting/__init__.py,sha256=YtYnKYHL5lN6EaT_bwwR3h89NW0HSMToIWHhHBxcidY,3126
125
+ pytcl/plotting/coordinates.py,sha256=h39H855Qjqtcly62m09demaOFpfMs_8EF_nXhoLBSBs,17198
126
+ pytcl/plotting/ellipses.py,sha256=bcns6dfNK4bwA_QBshscYhbAz_5wegwyqjDzzoUdWsQ,12465
127
+ pytcl/plotting/metrics.py,sha256=zbJr5P2kQg7-rGpGHsN7rC02S0JLOpPUZeoscQem7uQ,18148
128
+ pytcl/plotting/tracks.py,sha256=cqZG71ZHM-wDSzjH4I4kCESORIiZjmGesQtADmAi4gc,23034
129
+ pytcl/scheduling/__init__.py,sha256=jTqMSKcsCrWU_Fh6WaT6BW5WatNHyyEYjFbsv6X18Oc,39
130
+ pytcl/static_estimation/__init__.py,sha256=sSEhqq35jq_MpRLnBtWjKXwGZ9dqIw71iwji-TNwXmc,2222
131
+ pytcl/static_estimation/least_squares.py,sha256=8ouOyRGC7K-W8fynZMWlc2-KAFojvTbuzcqi5uS_sVA,13432
132
+ pytcl/static_estimation/maximum_likelihood.py,sha256=P6BKMcuzzDu_Qc6mX9KLI-zPWFX_NabbA6AKYjkNBcY,21581
133
+ pytcl/static_estimation/robust.py,sha256=egBLKWmo6d9PzP6LDh0J7ee4j6hYZh8kAb9TR5uC2so,18527
134
+ pytcl/terrain/__init__.py,sha256=e7plNQI5Y_jpZ24r82AgqdX0ChmmyYoeT7HReclnGXc,3228
135
+ pytcl/terrain/dem.py,sha256=rg2o0h0ZDrfxvtYhnE2A5tdzRnCmqcihu4w1uNJdH3Y,20814
136
+ pytcl/terrain/loaders.py,sha256=KBs1vdYUYW-0ETIujRv4-WxO-bExZk-FvPLY5l6gyTc,27028
137
+ pytcl/terrain/visibility.py,sha256=nIJr9AVk7C8GCpJV4UDvUjhmAieycWD8BLepAMUBMIQ,22739
138
+ pytcl/trackers/__init__.py,sha256=8-KpFtxS0n83B-dq4x0X4V1TQGHZnNSzdujAJUGcjxc,1198
139
+ pytcl/trackers/hypothesis.py,sha256=RApWfji-f0-a68KnAJela0BvPdIlOY_FV_cYJFmVUoE,17353
140
+ pytcl/trackers/mht.py,sha256=7mwhMmja3ri2wnx7W1wueDGn2r3ArwAxJDPUJ7IZAkQ,20617
141
+ pytcl/trackers/multi_target.py,sha256=7ZL8V25TO_rEMtQm2eYkScesDQHC9qXZVHLHyVbxy3M,10529
142
+ pytcl/trackers/single_target.py,sha256=Yy3FwaNTArMWcaod-0HVeiioNV4xLWxNDn_7ZPVqQYs,6562
143
+ pytcl/transponders/__init__.py,sha256=5fL4u3lKCYgPLo5uFeuZbtRZkJPABntuKYGUvVgMMEI,41
144
+ nrl_tracker-0.21.1.dist-info/LICENSE,sha256=rB5G4WppIIUzMOYr2N6uyYlNJ00hRJqE5tie6BMvYuE,1612
145
+ nrl_tracker-0.21.1.dist-info/METADATA,sha256=Do-PM_-vvQ08w8QWNyvIuRmsAEqzFXe8NSO5BXLTlHg,10005
146
+ nrl_tracker-0.21.1.dist-info/WHEEL,sha256=pL8R0wFFS65tNSRnaOVrsw9EOkOqxLrlUPenUYnJKNo,91
147
+ nrl_tracker-0.21.1.dist-info/top_level.txt,sha256=17megxcrTPBWwPZTh6jTkwTKxX7No-ZqRpyvElnnO-s,6
148
+ nrl_tracker-0.21.1.dist-info/RECORD,,
pytcl/__init__.py CHANGED
@@ -20,29 +20,26 @@ References
20
20
  no. 5, pp. 18-27, May 2017.
21
21
  """
22
22
 
23
- __version__ = "0.4.2"
23
+ __version__ = "0.18.0"
24
24
  __author__ = "Python Port Contributors"
25
25
  __original_author__ = "David F. Crouse, Naval Research Laboratory"
26
26
 
27
- # Core utilities
28
- from pytcl import core
29
-
30
- # Assignment algorithms (Phase 5)
31
- from pytcl import assignment_algorithms
32
-
33
- # Specialized domains (Phase 6)
34
- from pytcl import astronomical
35
- from pytcl import navigation
36
- from pytcl import atmosphere
37
-
38
- # End-to-end trackers (Phase 7)
39
- from pytcl import trackers
40
-
41
- # Performance evaluation
42
- from pytcl import performance_evaluation
43
-
44
27
  # Plotting utilities
45
- from pytcl import plotting
28
+ # Performance evaluation
29
+ # End-to-end trackers (Phase 7)
30
+ # Specialized domains (Phase 6)
31
+ # Assignment algorithms (Phase 5)
32
+ # Core utilities
33
+ from pytcl import (
34
+ assignment_algorithms,
35
+ astronomical,
36
+ atmosphere,
37
+ core,
38
+ navigation,
39
+ performance_evaluation,
40
+ plotting,
41
+ trackers,
42
+ )
46
43
 
47
44
 
48
45
  # Version tuple for programmatic access
@@ -2,43 +2,54 @@
2
2
  Assignment algorithms for data association in target tracking.
3
3
 
4
4
  This module provides:
5
- - 2D assignment algorithms (Hungarian, Auction, JVC)
5
+ - 2D assignment algorithms (Hungarian, Auction)
6
+ - K-best 2D assignment (Murty's algorithm)
7
+ - 3D assignment algorithms (Lagrangian relaxation, Auction)
6
8
  - Gating methods (ellipsoidal, rectangular)
7
9
  - Data association algorithms (GNN, JPDA)
8
10
  """
9
11
 
10
- from pytcl.assignment_algorithms.two_dimensional import (
11
- hungarian,
12
- auction,
13
- linear_sum_assignment,
14
- assign2d,
15
- AssignmentResult,
12
+ from pytcl.assignment_algorithms.data_association import (
13
+ AssociationResult,
14
+ compute_association_cost,
15
+ gated_gnn_association,
16
+ gnn_association,
17
+ nearest_neighbor,
16
18
  )
17
-
18
19
  from pytcl.assignment_algorithms.gating import (
20
+ chi2_gate_threshold,
21
+ compute_gate_volume,
19
22
  ellipsoidal_gate,
20
- rectangular_gate,
21
23
  gate_measurements,
22
24
  mahalanobis_distance,
23
- chi2_gate_threshold,
24
- compute_gate_volume,
25
- )
26
-
27
- from pytcl.assignment_algorithms.data_association import (
28
- gnn_association,
29
- nearest_neighbor,
30
- compute_association_cost,
31
- gated_gnn_association,
32
- AssociationResult,
25
+ rectangular_gate,
33
26
  )
34
-
35
27
  from pytcl.assignment_algorithms.jpda import (
36
28
  JPDAResult,
37
29
  JPDAUpdate,
30
+ compute_likelihood_matrix,
38
31
  jpda,
39
- jpda_update,
40
32
  jpda_probabilities,
41
- compute_likelihood_matrix,
33
+ jpda_update,
34
+ )
35
+ from pytcl.assignment_algorithms.three_dimensional import (
36
+ Assignment3DResult,
37
+ assign3d,
38
+ assign3d_auction,
39
+ assign3d_lagrangian,
40
+ decompose_to_2d,
41
+ greedy_3d,
42
+ )
43
+ from pytcl.assignment_algorithms.two_dimensional import (
44
+ AssignmentResult,
45
+ KBestResult,
46
+ assign2d,
47
+ auction,
48
+ hungarian,
49
+ kbest_assign2d,
50
+ linear_sum_assignment,
51
+ murty,
52
+ ranked_assignments,
42
53
  )
43
54
 
44
55
  __all__ = [
@@ -48,6 +59,18 @@ __all__ = [
48
59
  "linear_sum_assignment",
49
60
  "assign2d",
50
61
  "AssignmentResult",
62
+ # K-Best 2D Assignment
63
+ "KBestResult",
64
+ "murty",
65
+ "kbest_assign2d",
66
+ "ranked_assignments",
67
+ # 3D Assignment
68
+ "Assignment3DResult",
69
+ "assign3d",
70
+ "assign3d_lagrangian",
71
+ "assign3d_auction",
72
+ "greedy_3d",
73
+ "decompose_to_2d",
51
74
  # Gating
52
75
  "ellipsoidal_gate",
53
76
  "rectangular_gate",
@@ -5,16 +5,18 @@ This module provides algorithms for associating measurements to tracks,
5
5
  including Global Nearest Neighbor (GNN) and related methods.
6
6
  """
7
7
 
8
- from typing import Optional, NamedTuple, List
8
+ from typing import List, NamedTuple, Optional
9
+
9
10
  import numpy as np
10
11
  from numpy.typing import ArrayLike, NDArray
11
12
 
12
- from pytcl.assignment_algorithms.two_dimensional import (
13
- assign2d,
14
- )
15
13
  from pytcl.assignment_algorithms.gating import (
14
+ mahalanobis_batch,
16
15
  mahalanobis_distance,
17
16
  )
17
+ from pytcl.assignment_algorithms.two_dimensional import (
18
+ assign2d,
19
+ )
18
20
 
19
21
 
20
22
  class AssociationResult(NamedTuple):
@@ -102,7 +104,7 @@ def compute_association_cost(
102
104
  else:
103
105
  H_per_track = H_arr
104
106
 
105
- # Compute cost matrix
107
+ # Compute cost matrix using batch Mahalanobis distance for performance
106
108
  cost_matrix = np.full((n_tracks, n_meas), np.inf, dtype=np.float64)
107
109
 
108
110
  for i in range(n_tracks):
@@ -110,9 +112,17 @@ def compute_association_cost(
110
112
  z_pred = H @ X[i]
111
113
  S = H @ P[i] @ H.T # Innovation covariance
112
114
 
113
- for j in range(n_meas):
114
- innovation = Z[j] - z_pred
115
- cost_matrix[i, j] = mahalanobis_distance(innovation, S)
115
+ # Compute innovations for all measurements at once
116
+ innovations = Z - z_pred # (n_meas, meas_dim)
117
+
118
+ # Use batch Mahalanobis distance (JIT-compiled)
119
+ try:
120
+ S_inv = np.linalg.inv(S)
121
+ mahalanobis_batch(innovations, S_inv, cost_matrix[i])
122
+ except np.linalg.LinAlgError:
123
+ # Fallback if S is singular
124
+ for j in range(n_meas):
125
+ cost_matrix[i, j] = mahalanobis_distance(innovations[j], S)
116
126
 
117
127
  return cost_matrix
118
128
 
@@ -5,12 +5,52 @@ This module provides gating methods to determine which measurements
5
5
  fall within a validation region around predicted track states.
6
6
  """
7
7
 
8
- from typing import Tuple, List
8
+ from typing import List, Tuple
9
+
9
10
  import numpy as np
11
+ from numba import njit
10
12
  from numpy.typing import ArrayLike, NDArray
11
13
  from scipy.stats import chi2
12
14
 
13
15
 
16
+ @njit(cache=True, fastmath=True)
17
+ def _mahalanobis_distance_2d(
18
+ innovation: np.ndarray,
19
+ S_inv: np.ndarray,
20
+ ) -> float:
21
+ """JIT-compiled Mahalanobis distance for 2D innovations."""
22
+ return innovation[0] * (
23
+ S_inv[0, 0] * innovation[0] + S_inv[0, 1] * innovation[1]
24
+ ) + innovation[1] * (S_inv[1, 0] * innovation[0] + S_inv[1, 1] * innovation[1])
25
+
26
+
27
+ @njit(cache=True, fastmath=True)
28
+ def _mahalanobis_distance_3d(
29
+ innovation: np.ndarray,
30
+ S_inv: np.ndarray,
31
+ ) -> float:
32
+ """JIT-compiled Mahalanobis distance for 3D innovations."""
33
+ result = 0.0
34
+ for i in range(3):
35
+ for j in range(3):
36
+ result += innovation[i] * S_inv[i, j] * innovation[j]
37
+ return result
38
+
39
+
40
+ @njit(cache=True, fastmath=True)
41
+ def _mahalanobis_distance_general(
42
+ innovation: np.ndarray,
43
+ S_inv: np.ndarray,
44
+ ) -> float:
45
+ """JIT-compiled Mahalanobis distance for general dimension."""
46
+ n = len(innovation)
47
+ result = 0.0
48
+ for i in range(n):
49
+ for j in range(n):
50
+ result += innovation[i] * S_inv[i, j] * innovation[j]
51
+ return result
52
+
53
+
14
54
  def mahalanobis_distance(
15
55
  innovation: ArrayLike,
16
56
  innovation_covariance: ArrayLike,
@@ -299,8 +339,41 @@ def compute_gate_volume(
299
339
  return float(volume)
300
340
 
301
341
 
342
+ @njit(cache=True, fastmath=True, parallel=False)
343
+ def mahalanobis_batch(
344
+ innovations: np.ndarray,
345
+ S_inv: np.ndarray,
346
+ output: np.ndarray,
347
+ ) -> None:
348
+ """
349
+ Compute Mahalanobis distances for a batch of innovations.
350
+
351
+ JIT-compiled for performance. Computes squared Mahalanobis distances
352
+ for multiple innovations against a single covariance matrix.
353
+
354
+ Parameters
355
+ ----------
356
+ innovations : ndarray
357
+ Innovations of shape (n_measurements, dim).
358
+ S_inv : ndarray
359
+ Inverse of innovation covariance matrix of shape (dim, dim).
360
+ output : ndarray
361
+ Output array of shape (n_measurements,) to store distances.
362
+ """
363
+ n_meas = innovations.shape[0]
364
+ dim = innovations.shape[1]
365
+
366
+ for i in range(n_meas):
367
+ result = 0.0
368
+ for j in range(dim):
369
+ for k in range(dim):
370
+ result += innovations[i, j] * S_inv[j, k] * innovations[i, k]
371
+ output[i] = result
372
+
373
+
302
374
  __all__ = [
303
375
  "mahalanobis_distance",
376
+ "mahalanobis_batch",
304
377
  "ellipsoidal_gate",
305
378
  "rectangular_gate",
306
379
  "gate_measurements",
@@ -9,7 +9,8 @@ This is more sophisticated than GNN which makes hard assignment decisions,
9
9
  as JPDA can handle measurement origin uncertainty in cluttered environments.
10
10
  """
11
11
 
12
- from typing import NamedTuple, List, Optional, Tuple
12
+ from typing import List, NamedTuple, Optional, Tuple
13
+
13
14
  import numpy as np
14
15
  from numpy.typing import ArrayLike, NDArray
15
16
  from scipy.stats import chi2
@@ -0,0 +1,24 @@
1
+ """
2
+ Three-dimensional assignment algorithms.
3
+
4
+ This module provides algorithms for solving 3D assignment problems,
5
+ which arise in multi-sensor data fusion and multi-scan tracking.
6
+ """
7
+
8
+ from pytcl.assignment_algorithms.three_dimensional.assignment import (
9
+ Assignment3DResult,
10
+ assign3d,
11
+ assign3d_auction,
12
+ assign3d_lagrangian,
13
+ decompose_to_2d,
14
+ greedy_3d,
15
+ )
16
+
17
+ __all__ = [
18
+ "Assignment3DResult",
19
+ "assign3d",
20
+ "assign3d_lagrangian",
21
+ "assign3d_auction",
22
+ "greedy_3d",
23
+ "decompose_to_2d",
24
+ ]